summaryrefslogtreecommitdiff
path: root/chromium/net
diff options
context:
space:
mode:
authorAllan Sandfeld Jensen <allan.jensen@qt.io>2017-04-05 14:08:31 +0200
committerAllan Sandfeld Jensen <allan.jensen@qt.io>2017-04-11 07:46:53 +0000
commit6a4cabb866f66d4128a97cdc6d9d08ce074f1247 (patch)
treeab00f70a5e89278d6a0d16ff0c42578dc4d84a2d /chromium/net
parente733310db58160074f574c429d48f8308c0afe17 (diff)
downloadqtwebengine-chromium-6a4cabb866f66d4128a97cdc6d9d08ce074f1247.tar.gz
BASELINE: Update Chromium to 57.0.2987.144
Change-Id: I29db402ff696c71a04c4dbaec822c2e53efe0267 Reviewed-by: Peter Varga <pvarga@inf.u-szeged.hu>
Diffstat (limited to 'chromium/net')
-rw-r--r--chromium/net/BUILD.gn122
-rw-r--r--chromium/net/android/BUILD.gn5
-rw-r--r--chromium/net/android/cellular_signal_strength_unittest.cc2
-rw-r--r--chromium/net/android/dummy_spnego_authenticator.h4
-rw-r--r--chromium/net/android/keystore.h6
-rw-r--r--chromium/net/android/legacy_openssl.h6
-rw-r--r--chromium/net/android/network_change_notifier_delegate_android.h1
-rw-r--r--chromium/net/android/network_change_notifier_factory_android.h2
-rw-r--r--chromium/net/android/network_library.cc30
-rw-r--r--chromium/net/android/network_library.h24
-rw-r--r--chromium/net/android/network_library_unittest.cc19
-rw-r--r--chromium/net/android/unittest_support/AndroidManifest.xml1
-rw-r--r--chromium/net/base/arena.cc2
-rw-r--r--chromium/net/base/arena.h13
-rw-r--r--chromium/net/base/escape.cc70
-rw-r--r--chromium/net/base/escape.h31
-rw-r--r--chromium/net/base/int128.h4
-rw-r--r--chromium/net/base/int128_unittest.cc10
-rw-r--r--chromium/net/base/iovec.h2
-rw-r--r--chromium/net/base/ip_address.h6
-rw-r--r--chromium/net/base/keygen_handler.cc29
-rw-r--r--chromium/net/base/keygen_handler.h66
-rw-r--r--chromium/net/base/keygen_handler_mac.cc339
-rw-r--r--chromium/net/base/keygen_handler_nss.cc48
-rw-r--r--chromium/net/base/keygen_handler_openssl.cc122
-rw-r--r--chromium/net/base/keygen_handler_unittest.cc230
-rw-r--r--chromium/net/base/keygen_handler_win.cc218
-rw-r--r--chromium/net/base/linked_hash_map.h6
-rw-r--r--chromium/net/base/load_timing_info.cc1
-rw-r--r--chromium/net/base/logging_network_change_observer.h2
-rw-r--r--chromium/net/base/mime_sniffer.cc8
-rw-r--r--chromium/net/base/net_error_details.h4
-rw-r--r--chromium/net/base/net_error_list.h21
-rw-r--r--chromium/net/base/net_errors_posix.cc1
-rw-r--r--chromium/net/base/network_change_notifier.h2
-rw-r--r--chromium/net/base/network_delegate.cc22
-rw-r--r--chromium/net/base/network_interfaces_unittest.cc1
-rw-r--r--chromium/net/base/network_throttle_manager.h27
-rw-r--r--chromium/net/base/network_throttle_manager_impl.cc326
-rw-r--r--chromium/net/base/network_throttle_manager_impl.h152
-rw-r--r--chromium/net/base/network_throttle_manager_impl_unittest.cc568
-rw-r--r--chromium/net/base/openssl_private_key_store.h53
-rw-r--r--chromium/net/base/openssl_private_key_store_android.cc47
-rw-r--r--chromium/net/base/openssl_private_key_store_memory.cc74
-rw-r--r--chromium/net/base/parse_number.h2
-rw-r--r--chromium/net/base/percentile_estimator.cc100
-rw-r--r--chromium/net/base/percentile_estimator.h59
-rw-r--r--chromium/net/base/percentile_estimator_unittest.cc242
-rw-r--r--chromium/net/base/port_util.cc1
-rw-r--r--chromium/net/base/port_util.h6
-rw-r--r--chromium/net/base/proxy_delegate.h1
-rw-r--r--chromium/net/base/registry_controlled_domains/effective_tld_names.dat337
-rw-r--r--chromium/net/base/registry_controlled_domains/effective_tld_names.gperf263
-rw-r--r--chromium/net/base/registry_controlled_domains/registry_controlled_domain.cc56
-rw-r--r--chromium/net/base/registry_controlled_domains/registry_controlled_domain.h3
-rw-r--r--chromium/net/base/sdch_dictionary.h5
-rw-r--r--chromium/net/base/sdch_manager.cc33
-rw-r--r--chromium/net/base/sdch_manager.h9
-rw-r--r--chromium/net/base/sdch_manager_unittest.cc58
-rw-r--r--chromium/net/base/sdch_observer.h2
-rw-r--r--chromium/net/base/sys_addrinfo.h5
-rw-r--r--chromium/net/base/test_completion_callback.cc4
-rw-r--r--chromium/net/base/test_completion_callback_unittest.cc37
-rw-r--r--chromium/net/base/test_data_stream.cc1
-rw-r--r--chromium/net/base/test_proxy_delegate.cc2
-rw-r--r--chromium/net/base/test_proxy_delegate.h3
-rw-r--r--chromium/net/base/trace_constants.cc (renamed from chromium/net/cert/internal/completion_status.h)12
-rw-r--r--chromium/net/base/trace_constants.h15
-rw-r--r--chromium/net/base/upload_data_stream.h1
-rw-r--r--chromium/net/base/url_util.cc3
-rw-r--r--chromium/net/cert/cert_net_fetcher.h79
-rw-r--r--chromium/net/cert/cert_verify_proc.cc111
-rw-r--r--chromium/net/cert/cert_verify_proc.h22
-rw-r--r--chromium/net/cert/cert_verify_proc_android.cc26
-rw-r--r--chromium/net/cert/cert_verify_proc_blacklist.inc10
-rw-r--r--chromium/net/cert/cert_verify_proc_ios.cc25
-rw-r--r--chromium/net/cert/cert_verify_proc_mac.cc119
-rw-r--r--chromium/net/cert/cert_verify_proc_nss.cc24
-rw-r--r--chromium/net/cert/cert_verify_proc_openssl.cc21
-rw-r--r--chromium/net/cert/cert_verify_proc_unittest.cc282
-rw-r--r--chromium/net/cert/cert_verify_proc_whitelist.cc1681
-rw-r--r--chromium/net/cert/cert_verify_proc_whitelist.h29
-rw-r--r--chromium/net/cert/cert_verify_proc_whitelist_unittest.cc237
-rw-r--r--chromium/net/cert/cert_verify_proc_whitelist_unittest1.gperf9
-rw-r--r--chromium/net/cert/cert_verify_proc_win.cc21
-rw-r--r--chromium/net/cert/cert_verify_result.cc3
-rw-r--r--chromium/net/cert/cert_verify_result.h25
-rw-r--r--chromium/net/cert/crl_set_storage.cc5
-rw-r--r--chromium/net/cert/ct_known_logs.cc1
-rw-r--r--chromium/net/cert/ct_known_logs_static-inc.h10
-rw-r--r--chromium/net/cert/ct_log_response_parser.cc7
-rw-r--r--chromium/net/cert/ct_log_response_parser_unittest.cc1
-rw-r--r--chromium/net/cert/ct_log_verifier_util.h2
-rw-r--r--chromium/net/cert/ct_objects_extractor.cc2
-rw-r--r--chromium/net/cert/ct_objects_extractor.h3
-rw-r--r--chromium/net/cert/ct_objects_extractor_unittest.cc3
-rw-r--r--chromium/net/cert/ct_policy_enforcer.h6
-rw-r--r--chromium/net/cert/ct_policy_enforcer_unittest.cc84
-rw-r--r--chromium/net/cert/ct_policy_status.h6
-rw-r--r--chromium/net/cert/ct_serialization.cc8
-rw-r--r--chromium/net/cert/ct_serialization.h2
-rw-r--r--chromium/net/cert/ct_serialization_unittest.cc5
-rw-r--r--chromium/net/cert/ct_signed_certificate_timestamp_log_param.cc20
-rw-r--r--chromium/net/cert/ct_signed_certificate_timestamp_log_param.h8
-rw-r--r--chromium/net/cert/ct_verifier.h18
-rw-r--r--chromium/net/cert/do_nothing_ct_verifier.cc25
-rw-r--r--chromium/net/cert/do_nothing_ct_verifier.h67
-rw-r--r--chromium/net/cert/ev_root_ca_metadata.cc60
-rw-r--r--chromium/net/cert/internal/cert_errors.h1
-rw-r--r--chromium/net/cert/internal/cert_issuer_source.h37
-rw-r--r--chromium/net/cert/internal/cert_issuer_source_aia.cc110
-rw-r--r--chromium/net/cert/internal/cert_issuer_source_aia.h11
-rw-r--r--chromium/net/cert/internal/cert_issuer_source_aia_unittest.cc351
-rw-r--r--chromium/net/cert/internal/cert_issuer_source_nss.cc62
-rw-r--r--chromium/net/cert/internal/cert_issuer_source_nss.h40
-rw-r--r--chromium/net/cert/internal/cert_issuer_source_nss_unittest.cc62
-rw-r--r--chromium/net/cert/internal/cert_issuer_source_static.cc1
-rw-r--r--chromium/net/cert/internal/cert_issuer_source_static.h1
-rw-r--r--chromium/net/cert/internal/cert_issuer_source_static_unittest.cc133
-rw-r--r--chromium/net/cert/internal/cert_issuer_source_sync_unittest.h210
-rw-r--r--chromium/net/cert/internal/name_constraints.cc5
-rw-r--r--chromium/net/cert/internal/name_constraints_unittest.cc41
-rw-r--r--chromium/net/cert/internal/nist_pkits_unittest.h6
-rw-r--r--chromium/net/cert/internal/parse_certificate_unittest.cc284
-rw-r--r--chromium/net/cert/internal/parse_ocsp.cc1
-rw-r--r--chromium/net/cert/internal/parsed_certificate_unittest.cc303
-rw-r--r--chromium/net/cert/internal/path_builder.cc340
-rw-r--r--chromium/net/cert/internal/path_builder.h37
-rw-r--r--chromium/net/cert/internal/path_builder_pkits_unittest.cc3
-rw-r--r--chromium/net/cert/internal/path_builder_unittest.cc376
-rw-r--r--chromium/net/cert/internal/path_builder_verify_certificate_chain_unittest.cc4
-rw-r--r--chromium/net/cert/internal/trust_store.cc3
-rw-r--r--chromium/net/cert/internal/trust_store.h28
-rw-r--r--chromium/net/cert/internal/trust_store_collection.cc23
-rw-r--r--chromium/net/cert/internal/trust_store_collection.h38
-rw-r--r--chromium/net/cert/internal/trust_store_collection_unittest.cc170
-rw-r--r--chromium/net/cert/internal/trust_store_in_memory.cc6
-rw-r--r--chromium/net/cert/internal/trust_store_in_memory.h11
-rw-r--r--chromium/net/cert/internal/trust_store_nss.cc80
-rw-r--r--chromium/net/cert/internal/trust_store_nss.h21
-rw-r--r--chromium/net/cert/internal/trust_store_nss_unittest.cc120
-rw-r--r--chromium/net/cert/internal/trust_store_test_helpers.cc95
-rw-r--r--chromium/net/cert/internal/trust_store_test_helpers.h68
-rw-r--r--chromium/net/cert/internal/verify_certificate_chain.h1
-rw-r--r--chromium/net/cert/internal/verify_signed_data.cc1
-rw-r--r--chromium/net/cert/multi_log_ct_verifier.cc62
-rw-r--r--chromium/net/cert/multi_log_ct_verifier.h15
-rw-r--r--chromium/net/cert/multi_log_ct_verifier_unittest.cc49
-rw-r--r--chromium/net/cert/multi_threaded_cert_verifier.cc5
-rw-r--r--chromium/net/cert/multi_threaded_cert_verifier.h1
-rw-r--r--chromium/net/cert/multi_threaded_cert_verifier_unittest.cc1
-rw-r--r--chromium/net/cert/nss_cert_database.cc18
-rw-r--r--chromium/net/cert/nss_cert_database.h14
-rw-r--r--chromium/net/cert/nss_cert_database_chromeos.h6
-rw-r--r--chromium/net/cert/nss_cert_database_unittest.cc46
-rw-r--r--chromium/net/cert/nss_profile_filter_chromeos.cc1
-rw-r--r--chromium/net/cert/ocsp_revocation_status.h6
-rw-r--r--chromium/net/cert/ocsp_verify_result.h11
-rw-r--r--chromium/net/cert/signed_tree_head.h2
-rw-r--r--chromium/net/cert/test_keychain_search_list_mac.h6
-rw-r--r--chromium/net/cert/test_root_certs.h2
-rw-r--r--chromium/net/cert/x509_cert_types.cc6
-rw-r--r--chromium/net/cert/x509_cert_types.h2
-rw-r--r--chromium/net/cert/x509_cert_types_unittest.cc37
-rw-r--r--chromium/net/cert/x509_certificate.cc3
-rw-r--r--chromium/net/cert/x509_certificate.h42
-rw-r--r--chromium/net/cert/x509_certificate_ios.cc23
-rw-r--r--chromium/net/cert/x509_certificate_known_roots_win.h2
-rw-r--r--chromium/net/cert/x509_certificate_mac.cc37
-rw-r--r--chromium/net/cert/x509_certificate_net_log_param.h6
-rw-r--r--chromium/net/cert/x509_certificate_nss.cc46
-rw-r--r--chromium/net/cert/x509_certificate_openssl.cc18
-rw-r--r--chromium/net/cert/x509_certificate_win.cc27
-rw-r--r--chromium/net/cert/x509_util.cc2
-rw-r--r--chromium/net/cert/x509_util.h1
-rw-r--r--chromium/net/cert_net/cert_net_fetcher_impl.cc633
-rw-r--r--chromium/net/cert_net/cert_net_fetcher_impl.h106
-rw-r--r--chromium/net/cert_net/cert_net_fetcher_impl_unittest.cc682
-rw-r--r--chromium/net/cookies/cookie_monster.cc8
-rw-r--r--chromium/net/cookies/cookie_monster.h1
-rw-r--r--chromium/net/cookies/cookie_monster_unittest.cc136
-rw-r--r--chromium/net/cookies/cookie_store.h11
-rw-r--r--chromium/net/cookies/parsed_cookie.h2
-rw-r--r--chromium/net/data/cert_issuer_source_static_unittest/c1.pem100
-rw-r--r--chromium/net/data/cert_issuer_source_static_unittest/c2.pem100
-rw-r--r--chromium/net/data/cert_issuer_source_static_unittest/d.pem100
-rw-r--r--chromium/net/data/cert_issuer_source_static_unittest/e1.pem90
-rw-r--r--chromium/net/data/cert_issuer_source_static_unittest/e2.pem90
-rwxr-xr-xchromium/net/data/cert_issuer_source_static_unittest/generate-certs.py42
-rw-r--r--chromium/net/data/cert_issuer_source_static_unittest/i1_1.pem100
-rw-r--r--chromium/net/data/cert_issuer_source_static_unittest/i1_2.pem100
-rw-r--r--chromium/net/data/cert_issuer_source_static_unittest/i2.pem100
-rw-r--r--chromium/net/data/cert_issuer_source_static_unittest/i3_1.pem90
-rw-r--r--chromium/net/data/cert_issuer_source_static_unittest/i3_2.pem90
-rw-r--r--chromium/net/data/cert_issuer_source_static_unittest/root.pem100
-rw-r--r--chromium/net/data/ftp/dir-listing-ls-342
-rw-r--r--chromium/net/data/ftp/dir-listing-ls-34.expected17
-rw-r--r--chromium/net/data/fuzzer_data/net_url_request_ftp_fuzzer/epsv-mode.txtbin0 -> 309 bytes
-rw-r--r--chromium/net/data/fuzzer_data/net_url_request_ftp_fuzzer/pasv-mode.txtbin0 -> 457 bytes
-rw-r--r--chromium/net/data/fuzzer_dictionaries/net_http_transport_security_state_fuzzer.dict62
-rw-r--r--chromium/net/data/fuzzer_dictionaries/net_url_request_ftp_fuzzer.dict59
-rw-r--r--chromium/net/data/name_constraints_unittest/dnsname-excluded_with_leading_dot.pem7
-rw-r--r--chromium/net/data/name_constraints_unittest/dnsname-permitted_two_dot.pem7
-rwxr-xr-xchromium/net/data/name_constraints_unittest/generate_name_constraints.py8
-rw-r--r--chromium/net/data/quic_http_response_cache_data/www.example.com/index.html63
-rw-r--r--chromium/net/data/quic_http_response_cache_data/www.example.com/map.html65
-rw-r--r--chromium/net/data/quic_http_response_cache_data_with_push/www.example.com/favicon.ico (renamed from chromium/net/data/quic_in_memory_cache_data_with_push/quic-datatesturl.com/favicon.ico)bin1036 -> 1039 bytes
-rw-r--r--chromium/net/data/quic_http_response_cache_data_with_push/www.example.com/index.html (renamed from chromium/net/data/quic_in_memory_cache_data/quic-datatesturl.com/index.html)3
-rw-r--r--chromium/net/data/quic_http_response_cache_data_with_push/www.example.com/index2.html (renamed from chromium/net/data/quic_in_memory_cache_data_with_push/quic-datatesturl.com/index2.html)6
-rw-r--r--chromium/net/data/quic_http_response_cache_data_with_push/www.example.com/kitten-1.jpg (renamed from chromium/net/data/quic_in_memory_cache_data_with_push/quic-datatesturl.com/kitten-1.jpg)bin144862 -> 144864 bytes
-rw-r--r--chromium/net/data/quic_in_memory_cache_data_with_push/quic-datatesturl.com/index.html15
-rw-r--r--chromium/net/data/ssl/blacklist/1c01c6f4dbb2fefc22558b2bca32563f49844acfc32b7be4b0ff599f9e8c7af7.pem24
-rw-r--r--chromium/net/data/ssl/blacklist/README.md11
-rw-r--r--chromium/net/data/ssl/blacklist/e28393773da845a679f2080cc7fb44a3b7a1c3792cb7eb7729fdcb6a8d99aea7.pem20
-rw-r--r--chromium/net/data/ssl/certificates/README37
-rw-r--r--chromium/net/data/ssl/certificates/client-empty-password.p12bin0 -> 2367 bytes
-rw-r--r--chromium/net/data/ssl/certificates/client-null-password.p12bin0 -> 2364 bytes
-rw-r--r--chromium/net/data/ssl/certificates/client_1.key50
-rw-r--r--chromium/net/data/ssl/certificates/client_1.pem100
-rw-r--r--chromium/net/data/ssl/certificates/client_1.pk8bin1218 -> 1219 bytes
-rw-r--r--chromium/net/data/ssl/certificates/client_1_ca.pem98
-rw-r--r--chromium/net/data/ssl/certificates/client_2.key50
-rw-r--r--chromium/net/data/ssl/certificates/client_2.pem100
-rw-r--r--chromium/net/data/ssl/certificates/client_2.pk8bin1217 -> 1218 bytes
-rw-r--r--chromium/net/data/ssl/certificates/client_2_ca.pem98
-rw-r--r--chromium/net/data/ssl/certificates/client_3.key50
-rw-r--r--chromium/net/data/ssl/certificates/client_3.pem98
-rw-r--r--chromium/net/data/ssl/certificates/client_3.pk8bin1218 -> 1219 bytes
-rw-r--r--chromium/net/data/ssl/certificates/client_3_ca.pem98
-rw-r--r--chromium/net/data/ssl/certificates/client_4.key6
-rw-r--r--chromium/net/data/ssl/certificates/client_4.pem64
-rw-r--r--chromium/net/data/ssl/certificates/client_4.pk8bin138 -> 138 bytes
-rw-r--r--chromium/net/data/ssl/certificates/client_4_ca.pem98
-rw-r--r--chromium/net/data/ssl/certificates/client_5.key6
-rw-r--r--chromium/net/data/ssl/certificates/client_5.pem57
-rw-r--r--chromium/net/data/ssl/certificates/client_5.pk8bin0 -> 185 bytes
-rw-r--r--chromium/net/data/ssl/certificates/client_5_ca.pem71
-rw-r--r--chromium/net/data/ssl/certificates/client_6.key7
-rw-r--r--chromium/net/data/ssl/certificates/client_6.pem60
-rw-r--r--chromium/net/data/ssl/certificates/client_6.pk8bin0 -> 241 bytes
-rw-r--r--chromium/net/data/ssl/certificates/client_6_ca.pem71
-rw-r--r--chromium/net/data/ssl/certificates/client_root_ca.pem30
-rw-r--r--chromium/net/data/ssl/certificates/crlset_by_intermediate_serial.rawbin147 -> 147 bytes
-rw-r--r--chromium/net/data/ssl/certificates/intermediate_ca_cert.pem104
-rw-r--r--chromium/net/data/ssl/certificates/ocsp-test-root.pem80
-rw-r--r--chromium/net/data/ssl/certificates/ok_cert_by_intermediate.pem112
-rw-r--r--chromium/net/data/ssl/certificates/quic_test.example.com.key.sctbin30 -> 33 bytes
-rw-r--r--chromium/net/data/ssl/certificates/quic_test_ecc.example.com.sctbin0 -> 37 bytes
-rw-r--r--chromium/net/data/ssl/certificates/x509_verify_results.chain.pem210
-rw-r--r--chromium/net/data/ssl/scripts/ca.cnf1
-rwxr-xr-xchromium/net/data/ssl/scripts/generate-client-certificates.sh52
-rwxr-xr-xchromium/net/data/ssl/scripts/generate-test-certs.sh93
-rw-r--r--chromium/net/data/ssl/wosign/BUILD.gn18
-rw-r--r--chromium/net/data/ssl/wosign/wosign_domains.gperf16759
-rw-r--r--chromium/net/data/websocket/OWNERS3
-rw-r--r--chromium/net/der/encode_values.cc6
-rw-r--r--chromium/net/der/encode_values.h5
-rw-r--r--chromium/net/der/encode_values_unittest.cc4
-rw-r--r--chromium/net/der/input.cc3
-rw-r--r--chromium/net/der/input_unittest.cc3
-rw-r--r--chromium/net/der/parse_values.cc4
-rw-r--r--chromium/net/der/parse_values_unittest.cc3
-rw-r--r--chromium/net/der/parser.cc5
-rw-r--r--chromium/net/der/parser.h1
-rw-r--r--chromium/net/der/parser_unittest.cc5
-rw-r--r--chromium/net/der/tag.cc3
-rw-r--r--chromium/net/disk_cache/backend_unittest.cc65
-rw-r--r--chromium/net/disk_cache/blockfile/eviction.cc10
-rw-r--r--chromium/net/disk_cache/blockfile/file_ios.cc20
-rw-r--r--chromium/net/disk_cache/blockfile/file_posix.cc2
-rw-r--r--chromium/net/disk_cache/blockfile/in_flight_io.cc2
-rw-r--r--chromium/net/disk_cache/blockfile/stats.h4
-rw-r--r--chromium/net/disk_cache/disk_cache.cc (renamed from chromium/net/disk_cache/cache_creator.cc)29
-rw-r--r--chromium/net/disk_cache/disk_cache.h16
-rw-r--r--chromium/net/disk_cache/disk_cache_perftest.cc2
-rw-r--r--chromium/net/disk_cache/disk_cache_test_base.cc9
-rw-r--r--chromium/net/disk_cache/disk_cache_test_base.h9
-rw-r--r--chromium/net/disk_cache/memory/mem_backend_impl.cc21
-rw-r--r--chromium/net/disk_cache/memory/mem_backend_impl.h4
-rw-r--r--chromium/net/disk_cache/net_log_parameters.h2
-rw-r--r--chromium/net/disk_cache/simple/simple_backend_impl.cc21
-rw-r--r--chromium/net/disk_cache/simple/simple_backend_impl.h11
-rw-r--r--chromium/net/disk_cache/simple/simple_entry_format.h4
-rw-r--r--chromium/net/disk_cache/simple/simple_entry_impl.cc2
-rw-r--r--chromium/net/disk_cache/simple/simple_experiment_unittest.cc1
-rw-r--r--chromium/net/disk_cache/simple/simple_index.cc36
-rw-r--r--chromium/net/disk_cache/simple/simple_index.h6
-rw-r--r--chromium/net/disk_cache/simple/simple_index_file_unittest.cc1
-rw-r--r--chromium/net/disk_cache/simple/simple_net_log_parameters.h6
-rw-r--r--chromium/net/disk_cache/simple/simple_synchronous_entry.cc1
-rw-r--r--chromium/net/disk_cache/simple/simple_test_util.cc12
-rw-r--r--chromium/net/dns/address_sorter_posix.cc1
-rw-r--r--chromium/net/dns/address_sorter_unittest.cc4
-rw-r--r--chromium/net/dns/address_sorter_win.cc21
-rw-r--r--chromium/net/dns/dns_client.cc1
-rw-r--r--chromium/net/dns/dns_client.h1
-rw-r--r--chromium/net/dns/dns_config_service.cc1
-rw-r--r--chromium/net/dns/dns_config_service.h2
-rw-r--r--chromium/net/dns/dns_config_service_posix.cc10
-rw-r--r--chromium/net/dns/dns_config_service_unittest.cc1
-rw-r--r--chromium/net/dns/dns_config_service_win.h1
-rw-r--r--chromium/net/dns/dns_config_service_win_unittest.cc1
-rw-r--r--chromium/net/dns/dns_config_watcher_mac.h5
-rw-r--r--chromium/net/dns/dns_hosts.cc1
-rw-r--r--chromium/net/dns/dns_hosts.h1
-rw-r--r--chromium/net/dns/dns_hosts_unittest.cc1
-rw-r--r--chromium/net/dns/dns_protocol.h1
-rw-r--r--chromium/net/dns/dns_response.cc10
-rw-r--r--chromium/net/dns/dns_session.h2
-rw-r--r--chromium/net/dns/dns_session_unittest.cc7
-rw-r--r--chromium/net/dns/dns_socket_pool.cc21
-rw-r--r--chromium/net/dns/dns_test_util.cc27
-rw-r--r--chromium/net/dns/dns_test_util.h15
-rw-r--r--chromium/net/dns/dns_transaction.h1
-rw-r--r--chromium/net/dns/fuzzed_host_resolver.h8
-rw-r--r--chromium/net/dns/host_cache.cc3
-rw-r--r--chromium/net/dns/host_resolver_impl.cc105
-rw-r--r--chromium/net/dns/host_resolver_impl.h6
-rw-r--r--chromium/net/dns/host_resolver_impl_unittest.cc64
-rw-r--r--chromium/net/dns/host_resolver_mojo.cc3
-rw-r--r--chromium/net/dns/mdns_cache.h1
-rw-r--r--chromium/net/dns/mdns_client_impl.cc16
-rw-r--r--chromium/net/dns/mdns_client_impl.h3
-rw-r--r--chromium/net/dns/mojo_host_resolver_impl.cc28
-rw-r--r--chromium/net/dns/mojo_host_resolver_impl.h10
-rw-r--r--chromium/net/dns/mojo_host_resolver_impl_unittest.cc17
-rw-r--r--chromium/net/dns/mojo_host_struct_traits.cc1
-rw-r--r--chromium/net/dns/serial_worker.cc1
-rw-r--r--chromium/net/dns/serial_worker.h1
-rw-r--r--chromium/net/dns/serial_worker_unittest.cc1
-rw-r--r--chromium/net/docs/bug-triage-labels.md30
-rw-r--r--chromium/net/docs/bug-triage-suggested-workflow.md10
-rw-r--r--chromium/net/docs/bug-triage.md2
-rw-r--r--chromium/net/docs/crash-course-in-net-internals.md176
-rw-r--r--chromium/net/extras/sqlite/sqlite_channel_id_store.cc6
-rw-r--r--chromium/net/extras/sqlite/sqlite_channel_id_store.h2
-rw-r--r--chromium/net/extras/sqlite/sqlite_channel_id_store_unittest.cc12
-rw-r--r--chromium/net/extras/sqlite/sqlite_persistent_cookie_store.h2
-rw-r--r--chromium/net/filter/gzip_source_stream.cc111
-rw-r--r--chromium/net/filter/gzip_source_stream.h22
-rw-r--r--chromium/net/filter/gzip_source_stream_unittest.cc208
-rw-r--r--chromium/net/filter/mock_source_stream.cc27
-rw-r--r--chromium/net/filter/mock_source_stream.h13
-rw-r--r--chromium/net/ftp/ftp_directory_listing_parser.cc4
-rw-r--r--chromium/net/ftp/ftp_directory_listing_parser_ls.cc5
-rw-r--r--chromium/net/ftp/ftp_directory_listing_parser_unittest.cc8
-rw-r--r--chromium/net/ftp/ftp_directory_listing_parser_unittest.h9
-rw-r--r--chromium/net/ftp/ftp_directory_listing_parser_vms.cc41
-rw-r--r--chromium/net/ftp/ftp_directory_listing_parser_vms_unittest.cc129
-rw-r--r--chromium/net/ftp/ftp_network_session.cc1
-rw-r--r--chromium/net/ftp/ftp_network_transaction.cc109
-rw-r--r--chromium/net/ftp/ftp_network_transaction_unittest.cc268
-rw-r--r--chromium/net/ftp/ftp_util.cc16
-rw-r--r--chromium/net/ftp/ftp_util_unittest.cc53
-rw-r--r--chromium/net/http/bidirectional_stream.h2
-rw-r--r--chromium/net/http/bidirectional_stream_unittest.cc29
-rw-r--r--chromium/net/http/disk_cache_based_quic_server_info.h2
-rw-r--r--chromium/net/http/disk_cache_based_quic_server_info_unittest.cc2
-rw-r--r--chromium/net/http/failing_http_transaction_factory.h6
-rw-r--r--chromium/net/http/http_auth_challenge_tokenizer.h6
-rw-r--r--chromium/net/http/http_auth_gssapi_posix.cc2
-rw-r--r--chromium/net/http/http_auth_gssapi_posix.h13
-rw-r--r--chromium/net/http/http_cache.cc2
-rw-r--r--chromium/net/http/http_cache.h11
-rw-r--r--chromium/net/http/http_cache_lookup_manager.cc71
-rw-r--r--chromium/net/http/http_cache_lookup_manager.h63
-rw-r--r--chromium/net/http/http_cache_lookup_manager_unittest.cc288
-rw-r--r--chromium/net/http/http_cache_transaction.cc47
-rw-r--r--chromium/net/http/http_cache_unittest.cc47
-rw-r--r--chromium/net/http/http_log_util.h6
-rw-r--r--chromium/net/http/http_network_session.cc130
-rw-r--r--chromium/net/http/http_network_session.h36
-rw-r--r--chromium/net/http/http_network_session_peer.h1
-rw-r--r--chromium/net/http/http_network_transaction.cc11
-rw-r--r--chromium/net/http/http_network_transaction.h23
-rw-r--r--chromium/net/http/http_network_transaction_ssl_unittest.cc50
-rw-r--r--chromium/net/http/http_network_transaction_unittest.cc70
-rw-r--r--chromium/net/http/http_proxy_client_socket.cc5
-rw-r--r--chromium/net/http/http_proxy_client_socket.h3
-rw-r--r--chromium/net/http/http_proxy_client_socket_pool.cc3
-rw-r--r--chromium/net/http/http_proxy_client_socket_pool.h1
-rw-r--r--chromium/net/http/http_proxy_client_socket_pool_unittest.cc2
-rw-r--r--chromium/net/http/http_proxy_client_socket_wrapper.cc4
-rw-r--r--chromium/net/http/http_proxy_client_socket_wrapper.h2
-rw-r--r--chromium/net/http/http_response_headers.cc116
-rw-r--r--chromium/net/http/http_response_headers.h12
-rw-r--r--chromium/net/http/http_response_headers_unittest.cc101
-rw-r--r--chromium/net/http/http_response_info.cc3
-rw-r--r--chromium/net/http/http_response_info.h1
-rw-r--r--chromium/net/http/http_server_properties_impl.cc1
-rw-r--r--chromium/net/http/http_server_properties_manager.cc27
-rw-r--r--chromium/net/http/http_server_properties_manager.h27
-rw-r--r--chromium/net/http/http_server_properties_manager_unittest.cc398
-rw-r--r--chromium/net/http/http_status_line_validator.cc136
-rw-r--r--chromium/net/http/http_status_line_validator.h88
-rw-r--r--chromium/net/http/http_status_line_validator_unittest.cc88
-rw-r--r--chromium/net/http/http_stream_factory.cc2
-rw-r--r--chromium/net/http/http_stream_factory.h8
-rw-r--r--chromium/net/http/http_stream_factory_impl.cc87
-rw-r--r--chromium/net/http/http_stream_factory_impl.h36
-rw-r--r--chromium/net/http/http_stream_factory_impl_job.cc29
-rw-r--r--chromium/net/http/http_stream_factory_impl_job.h9
-rw-r--r--chromium/net/http/http_stream_factory_impl_job_controller.cc70
-rw-r--r--chromium/net/http/http_stream_factory_impl_job_controller.h16
-rw-r--r--chromium/net/http/http_stream_factory_impl_job_controller_unittest.cc185
-rw-r--r--chromium/net/http/http_stream_factory_impl_request.h2
-rw-r--r--chromium/net/http/http_stream_factory_impl_request_unittest.cc1
-rw-r--r--chromium/net/http/http_stream_factory_impl_unittest.cc338
-rw-r--r--chromium/net/http/http_stream_factory_test_util.cc4
-rw-r--r--chromium/net/http/http_stream_parser.cc74
-rw-r--r--chromium/net/http/http_stream_parser.h4
-rw-r--r--chromium/net/http/http_stream_parser_unittest.cc126
-rw-r--r--chromium/net/http/http_transaction_test_util.cc5
-rw-r--r--chromium/net/http/http_transaction_test_util.h6
-rw-r--r--chromium/net/http/http_util.cc149
-rw-r--r--chromium/net/http/http_util.h51
-rw-r--r--chromium/net/http/http_util_unittest.cc254
-rw-r--r--chromium/net/http/mock_gssapi_library_posix.cc1
-rw-r--r--chromium/net/http/mock_gssapi_library_posix.h1
-rw-r--r--chromium/net/http/partial_data.cc2
-rw-r--r--chromium/net/http/proxy_client_socket.h3
-rw-r--r--chromium/net/http/transport_security_state.cc15
-rw-r--r--chromium/net/http/transport_security_state.h3
-rw-r--r--chromium/net/http/transport_security_state_static.h29727
-rw-r--r--chromium/net/http/transport_security_state_static.json2567
-rw-r--r--chromium/net/http/transport_security_state_static_fuzzer.cc49
-rw-r--r--chromium/net/http/transport_security_state_unittest.cc27
-rw-r--r--chromium/net/http2/decoder/decode_buffer.cc90
-rw-r--r--chromium/net/http2/decoder/decode_buffer.h289
-rw-r--r--chromium/net/http2/decoder/decode_buffer_test.cc378
-rw-r--r--chromium/net/http2/decoder/decode_http2_structures.cc355
-rw-r--r--chromium/net/http2/decoder/decode_http2_structures.h94
-rw-r--r--chromium/net/http2/decoder/decode_http2_structures_test.cc534
-rw-r--r--chromium/net/http2/decoder/decode_status.cc27
-rw-r--r--chromium/net/http2/decoder/decode_status.h32
-rw-r--r--chromium/net/http2/decoder/frame_decoder_state.cc81
-rw-r--r--chromium/net/http2/decoder/frame_decoder_state.h252
-rw-r--r--chromium/net/http2/decoder/frame_decoder_state_test_util.cc34
-rw-r--r--chromium/net/http2/decoder/frame_decoder_state_test_util.h36
-rw-r--r--chromium/net/http2/decoder/frame_parts.cc527
-rw-r--r--chromium/net/http2/decoder/frame_parts.h176
-rw-r--r--chromium/net/http2/decoder/frame_parts_collector.cc112
-rw-r--r--chromium/net/http2/decoder/frame_parts_collector.h116
-rw-r--r--chromium/net/http2/decoder/frame_parts_collector_listener.cc230
-rw-r--r--chromium/net/http2/decoder/frame_parts_collector_listener.h83
-rw-r--r--chromium/net/http2/decoder/http2_frame_decoder.cc426
-rw-r--r--chromium/net/http2/decoder/http2_frame_decoder.h203
-rw-r--r--chromium/net/http2/decoder/http2_frame_decoder_listener.cc14
-rw-r--r--chromium/net/http2/decoder/http2_frame_decoder_listener.h356
-rw-r--r--chromium/net/http2/decoder/http2_frame_decoder_listener_test_util.cc485
-rw-r--r--chromium/net/http2/decoder/http2_frame_decoder_listener_test_util.h141
-rw-r--r--chromium/net/http2/decoder/http2_frame_decoder_test.cc930
-rw-r--r--chromium/net/http2/decoder/http2_structure_decoder.cc90
-rw-r--r--chromium/net/http2/decoder/http2_structure_decoder.h129
-rw-r--r--chromium/net/http2/decoder/http2_structure_decoder_test.cc505
-rw-r--r--chromium/net/http2/decoder/http2_structure_decoder_test_util.h30
-rw-r--r--chromium/net/http2/decoder/payload_decoders/altsvc_payload_decoder.cc143
-rw-r--r--chromium/net/http2/decoder/payload_decoders/altsvc_payload_decoder.h64
-rw-r--r--chromium/net/http2/decoder/payload_decoders/altsvc_payload_decoder_test.cc131
-rw-r--r--chromium/net/http2/decoder/payload_decoders/continuation_payload_decoder.cc58
-rw-r--r--chromium/net/http2/decoder/payload_decoders/continuation_payload_decoder.h31
-rw-r--r--chromium/net/http2/decoder/payload_decoders/continuation_payload_decoder_test.cc94
-rw-r--r--chromium/net/http2/decoder/payload_decoders/data_payload_decoder.cc123
-rw-r--r--chromium/net/http2/decoder/payload_decoders/data_payload_decoder.h54
-rw-r--r--chromium/net/http2/decoder/payload_decoders/data_payload_decoder_test.cc120
-rw-r--r--chromium/net/http2/decoder/payload_decoders/goaway_payload_decoder.cc118
-rw-r--r--chromium/net/http2/decoder/payload_decoders/goaway_payload_decoder.h66
-rw-r--r--chromium/net/http2/decoder/payload_decoders/goaway_payload_decoder_test.cc117
-rw-r--r--chromium/net/http2/decoder/payload_decoders/headers_payload_decoder.cc173
-rw-r--r--chromium/net/http2/decoder/payload_decoders/headers_payload_decoder.h67
-rw-r--r--chromium/net/http2/decoder/payload_decoders/headers_payload_decoder_test.cc169
-rw-r--r--chromium/net/http2/decoder/payload_decoders/payload_decoder_base_test_util.cc98
-rw-r--r--chromium/net/http2/decoder/payload_decoders/payload_decoder_base_test_util.h462
-rw-r--r--chromium/net/http2/decoder/payload_decoders/ping_payload_decoder.cc89
-rw-r--r--chromium/net/http2/decoder/payload_decoders/ping_payload_decoder.h43
-rw-r--r--chromium/net/http2/decoder/payload_decoders/ping_payload_decoder_test.cc117
-rw-r--r--chromium/net/http2/decoder/payload_decoders/priority_payload_decoder.cc64
-rw-r--r--chromium/net/http2/decoder/payload_decoders/priority_payload_decoder.h44
-rw-r--r--chromium/net/http2/decoder/payload_decoders/priority_payload_decoder_test.cc95
-rw-r--r--chromium/net/http2/decoder/payload_decoders/push_promise_payload_decoder.cc172
-rw-r--r--chromium/net/http2/decoder/payload_decoders/push_promise_payload_decoder.h66
-rw-r--r--chromium/net/http2/decoder/payload_decoders/push_promise_payload_decoder_test.cc147
-rw-r--r--chromium/net/http2/decoder/payload_decoders/rst_stream_payload_decoder.cc66
-rw-r--r--chromium/net/http2/decoder/payload_decoders/rst_stream_payload_decoder.h42
-rw-r--r--chromium/net/http2/decoder/payload_decoders/rst_stream_payload_decoder_test.cc97
-rw-r--r--chromium/net/http2/decoder/payload_decoders/settings_payload_decoder.cc97
-rw-r--r--chromium/net/http2/decoder/payload_decoders/settings_payload_decoder.h54
-rw-r--r--chromium/net/http2/decoder/payload_decoders/settings_payload_decoder_test.cc165
-rw-r--r--chromium/net/http2/decoder/payload_decoders/unknown_payload_decoder.cc55
-rw-r--r--chromium/net/http2/decoder/payload_decoders/unknown_payload_decoder.h33
-rw-r--r--chromium/net/http2/decoder/payload_decoders/unknown_payload_decoder_test.cc108
-rw-r--r--chromium/net/http2/decoder/payload_decoders/window_update_payload_decoder.cc82
-rw-r--r--chromium/net/http2/decoder/payload_decoders/window_update_payload_decoder.h42
-rw-r--r--chromium/net/http2/decoder/payload_decoders/window_update_payload_decoder_test.cc102
-rw-r--r--chromium/net/http2/hpack/decoder/README.md50
-rw-r--r--chromium/net/http2/hpack/decoder/hpack_block_collector.cc154
-rw-r--r--chromium/net/http2/hpack/decoder/hpack_block_collector.h128
-rw-r--r--chromium/net/http2/hpack/decoder/hpack_block_decoder.cc65
-rw-r--r--chromium/net/http2/hpack/decoder/hpack_block_decoder.h73
-rw-r--r--chromium/net/http2/hpack/decoder/hpack_block_decoder_test.cc296
-rw-r--r--chromium/net/http2/hpack/decoder/hpack_decoder_listener.cc32
-rw-r--r--chromium/net/http2/hpack/decoder/hpack_decoder_listener.h65
-rw-r--r--chromium/net/http2/hpack/decoder/hpack_decoder_state.cc221
-rw-r--r--chromium/net/http2/hpack/decoder/hpack_decoder_state.h124
-rw-r--r--chromium/net/http2/hpack/decoder/hpack_decoder_state_test.cc550
-rw-r--r--chromium/net/http2/hpack/decoder/hpack_decoder_string_buffer.cc225
-rw-r--r--chromium/net/http2/hpack/decoder/hpack_decoder_string_buffer.h97
-rw-r--r--chromium/net/http2/hpack/decoder/hpack_decoder_string_buffer_test.cc254
-rw-r--r--chromium/net/http2/hpack/decoder/hpack_decoder_tables.cc118
-rw-r--r--chromium/net/http2/hpack/decoder/hpack_decoder_tables.h151
-rw-r--r--chromium/net/http2/hpack/decoder/hpack_decoder_tables_test.cc265
-rw-r--r--chromium/net/http2/hpack/decoder/hpack_entry_collector.cc317
-rw-r--r--chromium/net/http2/hpack/decoder/hpack_entry_collector.h154
-rw-r--r--chromium/net/http2/hpack/decoder/hpack_entry_decoder.cc233
-rw-r--r--chromium/net/http2/hpack/decoder/hpack_entry_decoder.h117
-rw-r--r--chromium/net/http2/hpack/decoder/hpack_entry_decoder_listener.cc83
-rw-r--r--chromium/net/http2/hpack/decoder/hpack_entry_decoder_listener.h110
-rw-r--r--chromium/net/http2/hpack/decoder/hpack_entry_decoder_test.cc213
-rw-r--r--chromium/net/http2/hpack/decoder/hpack_entry_type_decoder.cc360
-rw-r--r--chromium/net/http2/hpack/decoder/hpack_entry_type_decoder.h56
-rw-r--r--chromium/net/http2/hpack/decoder/hpack_entry_type_decoder_test.cc88
-rw-r--r--chromium/net/http2/hpack/decoder/hpack_string_collector.cc127
-rw-r--r--chromium/net/http2/hpack/decoder/hpack_string_collector.h63
-rw-r--r--chromium/net/http2/hpack/decoder/hpack_string_decoder.cc39
-rw-r--r--chromium/net/http2/hpack/decoder/hpack_string_decoder.h236
-rw-r--r--chromium/net/http2/hpack/decoder/hpack_string_decoder_listener.cc36
-rw-r--r--chromium/net/http2/hpack/decoder/hpack_string_decoder_listener.h62
-rw-r--r--chromium/net/http2/hpack/decoder/hpack_string_decoder_test.cc187
-rw-r--r--chromium/net/http2/hpack/decoder/hpack_varint_decoder.cc36
-rw-r--r--chromium/net/http2/hpack/decoder/hpack_varint_decoder.h181
-rw-r--r--chromium/net/http2/hpack/decoder/hpack_varint_decoder_test.cc382
-rw-r--r--chromium/net/http2/hpack/decoder/hpack_whole_entry_buffer.cc135
-rw-r--r--chromium/net/http2/hpack/decoder/hpack_whole_entry_buffer.h101
-rw-r--r--chromium/net/http2/hpack/decoder/hpack_whole_entry_buffer_test.cc219
-rw-r--r--chromium/net/http2/hpack/decoder/hpack_whole_entry_listener.cc35
-rw-r--r--chromium/net/http2/hpack/decoder/hpack_whole_entry_listener.h80
-rw-r--r--chromium/net/http2/hpack/decoder/http2_hpack_decoder.cc124
-rw-r--r--chromium/net/http2/hpack/decoder/http2_hpack_decoder.h116
-rw-r--r--chromium/net/http2/hpack/decoder/http2_hpack_decoder_test.cc1219
-rw-r--r--chromium/net/http2/hpack/hpack_static_table_entries.inc69
-rw-r--r--chromium/net/http2/hpack/hpack_string.cc78
-rw-r--r--chromium/net/http2/hpack/hpack_string.h76
-rw-r--r--chromium/net/http2/hpack/hpack_string_test.cc150
-rw-r--r--chromium/net/http2/hpack/http2_hpack_constants.cc33
-rw-r--r--chromium/net/http2/hpack/http2_hpack_constants.h61
-rw-r--r--chromium/net/http2/hpack/http2_hpack_constants_test.cc34
-rw-r--r--chromium/net/http2/hpack/huffman/http2_hpack_huffman_decoder.cc542
-rw-r--r--chromium/net/http2/hpack/huffman/http2_hpack_huffman_decoder.h149
-rw-r--r--chromium/net/http2/hpack/huffman/http2_hpack_huffman_decoder_test.cc284
-rw-r--r--chromium/net/http2/hpack/tools/hpack_block_builder.cc84
-rw-r--r--chromium/net/http2/hpack/tools/hpack_block_builder.h95
-rw-r--r--chromium/net/http2/hpack/tools/hpack_block_builder_test.cc169
-rw-r--r--chromium/net/http2/hpack/tools/hpack_example.cc61
-rw-r--r--chromium/net/http2/hpack/tools/hpack_example.h32
-rw-r--r--chromium/net/http2/http2_constants.cc161
-rw-r--r--chromium/net/http2/http2_constants.h265
-rw-r--r--chromium/net/http2/http2_constants_test.cc272
-rw-r--r--chromium/net/http2/http2_constants_test_util.cc142
-rw-r--r--chromium/net/http2/http2_constants_test_util.h40
-rw-r--r--chromium/net/http2/http2_structures.cc138
-rw-r--r--chromium/net/http2/http2_structures.h326
-rw-r--r--chromium/net/http2/http2_structures_test.cc486
-rw-r--r--chromium/net/http2/http2_structures_test_util.cc107
-rw-r--r--chromium/net/http2/http2_structures_test_util.h61
-rw-r--r--chromium/net/http2/tools/failure.cc29
-rw-r--r--chromium/net/http2/tools/failure.h154
-rw-r--r--chromium/net/http2/tools/http2_bug_tracker.h14
-rw-r--r--chromium/net/http2/tools/http2_frame_builder.cc182
-rw-r--r--chromium/net/http2/tools/http2_frame_builder.h100
-rw-r--r--chromium/net/http2/tools/http2_random.cc58
-rw-r--r--chromium/net/http2/tools/http2_random.h57
-rw-r--r--chromium/net/http2/tools/random_decoder_test.cc178
-rw-r--r--chromium/net/http2/tools/random_decoder_test.h260
-rw-r--r--chromium/net/http2/tools/random_util.cc96
-rw-r--r--chromium/net/http2/tools/random_util.h43
-rw-r--r--chromium/net/log/bounded_file_net_log_observer.h136
-rw-r--r--chromium/net/log/file_net_log_observer.cc (renamed from chromium/net/log/bounded_file_net_log_observer.cc)312
-rw-r--r--chromium/net/log/file_net_log_observer.h157
-rw-r--r--chromium/net/log/file_net_log_observer_unittest.cc (renamed from chromium/net/log/bounded_file_net_log_observer_unittest.cc)822
-rw-r--r--chromium/net/log/net_log.cc29
-rw-r--r--chromium/net/log/net_log.h16
-rw-r--r--chromium/net/log/net_log_event_type_list.h78
-rw-r--r--chromium/net/log/net_log_source_type_list.h6
-rw-r--r--chromium/net/log/net_log_util.cc11
-rw-r--r--chromium/net/log/net_log_util.h1
-rw-r--r--chromium/net/log/trace_net_log_observer.cc15
-rw-r--r--chromium/net/log/trace_net_log_observer_unittest.cc63
-rw-r--r--chromium/net/log/write_to_file_net_log_observer.h8
-rw-r--r--chromium/net/net.gypi425
-rw-r--r--chromium/net/nqe/OWNERS3
-rw-r--r--chromium/net/nqe/cached_network_quality.cc2
-rw-r--r--chromium/net/nqe/cached_network_quality.h2
-rw-r--r--chromium/net/nqe/effective_connection_type.cc2
-rw-r--r--chromium/net/nqe/effective_connection_type_unittest.cc2
-rw-r--r--chromium/net/nqe/network_id.h4
-rw-r--r--chromium/net/nqe/network_qualities_prefs_manager.cc33
-rw-r--r--chromium/net/nqe/network_qualities_prefs_manager.h4
-rw-r--r--chromium/net/nqe/network_qualities_prefs_manager_unittest.cc96
-rw-r--r--chromium/net/nqe/network_quality.cc2
-rw-r--r--chromium/net/nqe/network_quality.h2
-rw-r--r--chromium/net/nqe/network_quality_estimator.cc364
-rw-r--r--chromium/net/nqe/network_quality_estimator.h66
-rw-r--r--chromium/net/nqe/network_quality_estimator_params.cc164
-rw-r--r--chromium/net/nqe/network_quality_estimator_params.h22
-rw-r--r--chromium/net/nqe/network_quality_estimator_test_util.cc24
-rw-r--r--chromium/net/nqe/network_quality_estimator_test_util.h18
-rw-r--r--chromium/net/nqe/network_quality_estimator_unittest.cc723
-rw-r--r--chromium/net/nqe/network_quality_observation.h12
-rw-r--r--chromium/net/nqe/network_quality_observation_source.h2
-rw-r--r--chromium/net/nqe/network_quality_store.cc43
-rw-r--r--chromium/net/nqe/network_quality_store.h16
-rw-r--r--chromium/net/nqe/network_quality_store_unittest.cc2
-rw-r--r--chromium/net/nqe/observation_buffer.h74
-rw-r--r--chromium/net/nqe/observation_buffer_unittest.cc330
-rw-r--r--chromium/net/nqe/socket_watcher.cc18
-rw-r--r--chromium/net/nqe/socket_watcher.h25
-rw-r--r--chromium/net/nqe/socket_watcher_factory.cc16
-rw-r--r--chromium/net/nqe/socket_watcher_factory.h15
-rw-r--r--chromium/net/nqe/socket_watcher_unittest.cc57
-rw-r--r--chromium/net/nqe/throughput_analyzer.cc2
-rw-r--r--chromium/net/nqe/throughput_analyzer.h2
-rw-r--r--chromium/net/nqe/weighted_observation.h2
-rw-r--r--chromium/net/proxy/dhcp_proxy_script_fetcher.h6
-rw-r--r--chromium/net/proxy/dhcp_proxy_script_fetcher_factory.h6
-rw-r--r--chromium/net/proxy/dhcpcsvc_init_win.h7
-rw-r--r--chromium/net/proxy/in_process_mojo_proxy_resolver_factory.cc38
-rw-r--r--chromium/net/proxy/in_process_mojo_proxy_resolver_factory.h43
-rw-r--r--chromium/net/proxy/mojo_proxy_resolver_factory_impl.h2
-rw-r--r--chromium/net/proxy/mojo_proxy_resolver_factory_impl_unittest.cc18
-rw-r--r--chromium/net/proxy/mojo_proxy_resolver_impl_unittest.cc13
-rw-r--r--chromium/net/proxy/proxy_config_service_linux.cc2
-rw-r--r--chromium/net/proxy/proxy_resolver_factory_mojo.cc4
-rw-r--r--chromium/net/proxy/proxy_resolver_factory_mojo_unittest.cc9
-rw-r--r--chromium/net/proxy/proxy_resolver_v8.cc4
-rw-r--r--chromium/net/proxy/proxy_resolver_v8_tracing.cc3
-rw-r--r--chromium/net/proxy/proxy_script_decider.h1
-rw-r--r--chromium/net/proxy/proxy_service.h2
-rw-r--r--chromium/net/proxy/proxy_service_mojo.cc16
-rw-r--r--chromium/net/proxy/proxy_service_mojo.h19
-rw-r--r--chromium/net/proxy/proxy_service_mojo_unittest.cc32
-rw-r--r--chromium/net/quic/chromium/bidirectional_stream_quic_impl.cc1
-rw-r--r--chromium/net/quic/chromium/bidirectional_stream_quic_impl.h6
-rw-r--r--chromium/net/quic/chromium/bidirectional_stream_quic_impl_unittest.cc195
-rw-r--r--chromium/net/quic/chromium/crypto/channel_id_chromium.cc2
-rw-r--r--chromium/net/quic/chromium/crypto/channel_id_chromium.h6
-rw-r--r--chromium/net/quic/chromium/crypto/proof_source_chromium.cc31
-rw-r--r--chromium/net/quic/chromium/crypto/proof_source_chromium.h17
-rw-r--r--chromium/net/quic/chromium/crypto/proof_test_chromium.cc99
-rw-r--r--chromium/net/quic/chromium/crypto/proof_verifier_chromium.cc11
-rw-r--r--chromium/net/quic/chromium/crypto/proof_verifier_chromium.h6
-rw-r--r--chromium/net/quic/chromium/crypto_test_utils_chromium.cc21
-rw-r--r--chromium/net/quic/chromium/mock_crypto_client_stream_factory.cc (renamed from chromium/net/quic/test_tools/mock_crypto_client_stream_factory.cc)2
-rw-r--r--chromium/net/quic/chromium/mock_crypto_client_stream_factory.h (renamed from chromium/net/quic/test_tools/mock_crypto_client_stream_factory.h)8
-rw-r--r--chromium/net/quic/chromium/mock_quic_data.h7
-rw-r--r--chromium/net/quic/chromium/network_connection.h6
-rw-r--r--chromium/net/quic/chromium/port_suggester.cc47
-rw-r--r--chromium/net/quic/chromium/port_suggester.h51
-rw-r--r--chromium/net/quic/chromium/port_suggester_unittest.cc108
-rw-r--r--chromium/net/quic/chromium/properties_based_quic_server_info.cc (renamed from chromium/net/quic/core/crypto/properties_based_quic_server_info.cc)2
-rw-r--r--chromium/net/quic/chromium/properties_based_quic_server_info.h (renamed from chromium/net/quic/core/crypto/properties_based_quic_server_info.h)15
-rw-r--r--chromium/net/quic/chromium/properties_based_quic_server_info_test.cc (renamed from chromium/net/quic/core/crypto/properties_based_quic_server_info_test.cc)2
-rw-r--r--chromium/net/quic/chromium/quic_address_mismatch.cc (renamed from chromium/net/quic/core/quic_address_mismatch.cc)2
-rw-r--r--chromium/net/quic/chromium/quic_address_mismatch.h (renamed from chromium/net/quic/core/quic_address_mismatch.h)6
-rw-r--r--chromium/net/quic/chromium/quic_address_mismatch_test.cc (renamed from chromium/net/quic/core/quic_address_mismatch_test.cc)2
-rw-r--r--chromium/net/quic/chromium/quic_chromium_alarm_factory.h10
-rw-r--r--chromium/net/quic/chromium/quic_chromium_client_session.cc54
-rw-r--r--chromium/net/quic/chromium/quic_chromium_client_session.h28
-rw-r--r--chromium/net/quic/chromium/quic_chromium_client_session_peer.h8
-rw-r--r--chromium/net/quic/chromium/quic_chromium_client_session_test.cc186
-rw-r--r--chromium/net/quic/chromium/quic_chromium_client_stream.cc6
-rw-r--r--chromium/net/quic/chromium/quic_chromium_client_stream.h9
-rw-r--r--chromium/net/quic/chromium/quic_chromium_client_stream_test.cc47
-rw-r--r--chromium/net/quic/chromium/quic_chromium_connection_helper.h8
-rw-r--r--chromium/net/quic/chromium/quic_chromium_packet_reader.cc2
-rw-r--r--chromium/net/quic/chromium/quic_chromium_packet_reader.h8
-rw-r--r--chromium/net/quic/chromium/quic_chromium_packet_writer.cc6
-rw-r--r--chromium/net/quic/chromium/quic_chromium_packet_writer.h16
-rw-r--r--chromium/net/quic/chromium/quic_connection_logger.cc102
-rw-r--r--chromium/net/quic/chromium/quic_connection_logger.h16
-rw-r--r--chromium/net/quic/chromium/quic_crypto_client_stream_factory.cc (renamed from chromium/net/quic/core/quic_crypto_client_stream_factory.cc)2
-rw-r--r--chromium/net/quic/chromium/quic_crypto_client_stream_factory.h (renamed from chromium/net/quic/core/quic_crypto_client_stream_factory.h)6
-rw-r--r--chromium/net/quic/chromium/quic_end_to_end_unittest.cc19
-rw-r--r--chromium/net/quic/chromium/quic_http_stream.cc75
-rw-r--r--chromium/net/quic/chromium/quic_http_stream.h25
-rw-r--r--chromium/net/quic/chromium/quic_http_stream_test.cc244
-rw-r--r--chromium/net/quic/chromium/quic_http_utils.cc (renamed from chromium/net/quic/core/quic_http_utils.cc)2
-rw-r--r--chromium/net/quic/chromium/quic_http_utils.h (renamed from chromium/net/quic/core/quic_http_utils.h)8
-rw-r--r--chromium/net/quic/chromium/quic_http_utils_test.cc (renamed from chromium/net/quic/core/quic_http_utils_test.cc)2
-rw-r--r--chromium/net/quic/chromium/quic_network_transaction_unittest.cc461
-rw-r--r--chromium/net/quic/chromium/quic_server_info.cc (renamed from chromium/net/quic/core/crypto/quic_server_info.cc)2
-rw-r--r--chromium/net/quic/chromium/quic_server_info.h (renamed from chromium/net/quic/core/crypto/quic_server_info.h)15
-rw-r--r--chromium/net/quic/chromium/quic_stream_factory.cc62
-rw-r--r--chromium/net/quic/chromium/quic_stream_factory.h29
-rw-r--r--chromium/net/quic/chromium/quic_stream_factory_test.cc554
-rw-r--r--chromium/net/quic/chromium/quic_test_packet_maker.cc (renamed from chromium/net/quic/test_tools/quic_test_packet_maker.cc)121
-rw-r--r--chromium/net/quic/chromium/quic_test_packet_maker.h (renamed from chromium/net/quic/test_tools/quic_test_packet_maker.h)16
-rw-r--r--chromium/net/quic/chromium/quic_utils_chromium.cc31
-rw-r--r--chromium/net/quic/chromium/quic_utils_chromium.h15
-rw-r--r--chromium/net/quic/chromium/quic_utils_chromium_test.cc21
-rw-r--r--chromium/net/quic/core/congestion_control/bandwidth_sampler.cc2
-rw-r--r--chromium/net/quic/core/congestion_control/bandwidth_sampler.h7
-rw-r--r--chromium/net/quic/core/congestion_control/bbr_sender.cc44
-rw-r--r--chromium/net/quic/core/congestion_control/bbr_sender.h23
-rw-r--r--chromium/net/quic/core/congestion_control/bbr_sender_test.cc59
-rw-r--r--chromium/net/quic/core/congestion_control/cubic.cc79
-rw-r--r--chromium/net/quic/core/congestion_control/cubic.h56
-rw-r--r--chromium/net/quic/core/congestion_control/cubic_bytes.cc111
-rw-r--r--chromium/net/quic/core/congestion_control/cubic_bytes.h59
-rw-r--r--chromium/net/quic/core/congestion_control/cubic_bytes_test.cc343
-rw-r--r--chromium/net/quic/core/congestion_control/cubic_test.cc165
-rw-r--r--chromium/net/quic/core/congestion_control/general_loss_algorithm.cc6
-rw-r--r--chromium/net/quic/core/congestion_control/general_loss_algorithm.h12
-rw-r--r--chromium/net/quic/core/congestion_control/general_loss_algorithm_test.cc11
-rw-r--r--chromium/net/quic/core/congestion_control/hybrid_slow_start.cc13
-rw-r--r--chromium/net/quic/core/congestion_control/hybrid_slow_start.h14
-rw-r--r--chromium/net/quic/core/congestion_control/hybrid_slow_start_test.cc1
-rw-r--r--chromium/net/quic/core/congestion_control/loss_detection_interface.h12
-rw-r--r--chromium/net/quic/core/congestion_control/pacing_sender.cc18
-rw-r--r--chromium/net/quic/core/congestion_control/pacing_sender.h15
-rw-r--r--chromium/net/quic/core/congestion_control/pacing_sender_test.cc10
-rw-r--r--chromium/net/quic/core/congestion_control/prr_sender.cc2
-rw-r--r--chromium/net/quic/core/congestion_control/prr_sender.h12
-rw-r--r--chromium/net/quic/core/congestion_control/prr_sender_test.cc4
-rw-r--r--chromium/net/quic/core/congestion_control/rtt_stats.cc23
-rw-r--r--chromium/net/quic/core/congestion_control/rtt_stats.h17
-rw-r--r--chromium/net/quic/core/congestion_control/rtt_stats_test.cc5
-rw-r--r--chromium/net/quic/core/congestion_control/send_algorithm_interface.cc8
-rw-r--r--chromium/net/quic/core/congestion_control/send_algorithm_interface.h16
-rw-r--r--chromium/net/quic/core/congestion_control/send_algorithm_test.cc380
-rw-r--r--chromium/net/quic/core/congestion_control/tcp_cubic_sender_base.cc22
-rw-r--r--chromium/net/quic/core/congestion_control/tcp_cubic_sender_base.h21
-rw-r--r--chromium/net/quic/core/congestion_control/tcp_cubic_sender_bytes.cc71
-rw-r--r--chromium/net/quic/core/congestion_control/tcp_cubic_sender_bytes.h19
-rw-r--r--chromium/net/quic/core/congestion_control/tcp_cubic_sender_bytes_test.cc11
-rw-r--r--chromium/net/quic/core/congestion_control/tcp_cubic_sender_packets.cc61
-rw-r--r--chromium/net/quic/core/congestion_control/tcp_cubic_sender_packets.h19
-rw-r--r--chromium/net/quic/core/congestion_control/tcp_cubic_sender_packets_test.cc14
-rw-r--r--chromium/net/quic/core/congestion_control/windowed_filter.h7
-rw-r--r--chromium/net/quic/core/congestion_control/windowed_filter_test.cc9
-rw-r--r--chromium/net/quic/core/crypto/aead_base_decrypter.cc11
-rw-r--r--chromium/net/quic/core/crypto/aead_base_decrypter.h15
-rw-r--r--chromium/net/quic/core/crypto/aead_base_encrypter.cc19
-rw-r--r--chromium/net/quic/core/crypto/aead_base_encrypter.h15
-rw-r--r--chromium/net/quic/core/crypto/aes_128_gcm_12_decrypter.h13
-rw-r--r--chromium/net/quic/core/crypto/aes_128_gcm_12_decrypter_test.cc18
-rw-r--r--chromium/net/quic/core/crypto/aes_128_gcm_12_encrypter.h12
-rw-r--r--chromium/net/quic/core/crypto/aes_128_gcm_12_encrypter_test.cc13
-rw-r--r--chromium/net/quic/core/crypto/cert_compressor.cc5
-rw-r--r--chromium/net/quic/core/crypto/cert_compressor.h10
-rw-r--r--chromium/net/quic/core/crypto/cert_compressor_test.cc49
-rw-r--r--chromium/net/quic/core/crypto/chacha20_poly1305_decrypter.h13
-rw-r--r--chromium/net/quic/core/crypto/chacha20_poly1305_decrypter_test.cc18
-rw-r--r--chromium/net/quic/core/crypto/chacha20_poly1305_encrypter.h19
-rw-r--r--chromium/net/quic/core/crypto/chacha20_poly1305_encrypter_test.cc27
-rw-r--r--chromium/net/quic/core/crypto/channel_id.cc6
-rw-r--r--chromium/net/quic/core/crypto/channel_id.h14
-rw-r--r--chromium/net/quic/core/crypto/channel_id_test.cc84
-rw-r--r--chromium/net/quic/core/crypto/common_cert_set.cc1
-rw-r--r--chromium/net/quic/core/crypto/common_cert_set.h10
-rw-r--r--chromium/net/quic/core/crypto/common_cert_set_test.cc2
-rw-r--r--chromium/net/quic/core/crypto/crypto_framer.cc22
-rw-r--r--chromium/net/quic/core/crypto/crypto_framer.h25
-rw-r--r--chromium/net/quic/core/crypto/crypto_framer_test.cc6
-rw-r--r--chromium/net/quic/core/crypto/crypto_handshake.h25
-rw-r--r--chromium/net/quic/core/crypto/crypto_handshake_message.cc20
-rw-r--r--chromium/net/quic/core/crypto/crypto_handshake_message.h16
-rw-r--r--chromium/net/quic/core/crypto/crypto_handshake_message_test.cc2
-rw-r--r--chromium/net/quic/core/crypto/crypto_protocol.h33
-rw-r--r--chromium/net/quic/core/crypto/crypto_secret_boxer.cc20
-rw-r--r--chromium/net/quic/core/crypto/crypto_secret_boxer.h23
-rw-r--r--chromium/net/quic/core/crypto/crypto_secret_boxer_test.cc2
-rw-r--r--chromium/net/quic/core/crypto/crypto_server_config_protobuf.h16
-rw-r--r--chromium/net/quic/core/crypto/crypto_server_test.cc281
-rw-r--r--chromium/net/quic/core/crypto/crypto_utils.cc12
-rw-r--r--chromium/net/quic/core/crypto/crypto_utils.h21
-rw-r--r--chromium/net/quic/core/crypto/crypto_utils_test.cc16
-rw-r--r--chromium/net/quic/core/crypto/curve25519_key_exchange.cc42
-rw-r--r--chromium/net/quic/core/crypto/curve25519_key_exchange.h13
-rw-r--r--chromium/net/quic/core/crypto/curve25519_key_exchange_test.cc1
-rw-r--r--chromium/net/quic/core/crypto/ephemeral_key_source.h10
-rw-r--r--chromium/net/quic/core/crypto/key_exchange.h10
-rw-r--r--chromium/net/quic/core/crypto/local_strike_register_client.cc4
-rw-r--r--chromium/net/quic/core/crypto/local_strike_register_client.h18
-rw-r--r--chromium/net/quic/core/crypto/local_strike_register_client_test.cc11
-rw-r--r--chromium/net/quic/core/crypto/null_decrypter.cc37
-rw-r--r--chromium/net/quic/core/crypto/null_decrypter.h27
-rw-r--r--chromium/net/quic/core/crypto/null_decrypter_test.cc83
-rw-r--r--chromium/net/quic/core/crypto/null_encrypter.cc21
-rw-r--r--chromium/net/quic/core/crypto/null_encrypter.h20
-rw-r--r--chromium/net/quic/core/crypto/null_encrypter_test.cc68
-rw-r--r--chromium/net/quic/core/crypto/p256_key_exchange.cc26
-rw-r--r--chromium/net/quic/core/crypto/p256_key_exchange.h16
-rw-r--r--chromium/net/quic/core/crypto/p256_key_exchange_test.cc1
-rw-r--r--chromium/net/quic/core/crypto/proof_source.cc5
-rw-r--r--chromium/net/quic/core/crypto/proof_source.h43
-rw-r--r--chromium/net/quic/core/crypto/proof_verifier.h18
-rw-r--r--chromium/net/quic/core/crypto/quic_compressed_certs_cache.cc28
-rw-r--r--chromium/net/quic/core/crypto/quic_compressed_certs_cache.h31
-rw-r--r--chromium/net/quic/core/crypto/quic_compressed_certs_cache_test.cc32
-rw-r--r--chromium/net/quic/core/crypto/quic_crypto_client_config.cc79
-rw-r--r--chromium/net/quic/core/crypto/quic_crypto_client_config.h33
-rw-r--r--chromium/net/quic/core/crypto/quic_crypto_client_config_test.cc27
-rw-r--r--chromium/net/quic/core/crypto/quic_crypto_proof.cc11
-rw-r--r--chromium/net/quic/core/crypto/quic_crypto_proof.h29
-rw-r--r--chromium/net/quic/core/crypto/quic_crypto_server_config.cc904
-rw-r--r--chromium/net/quic/core/crypto/quic_crypto_server_config.h288
-rw-r--r--chromium/net/quic/core/crypto/quic_crypto_server_config_test.cc142
-rw-r--r--chromium/net/quic/core/crypto/quic_decrypter.cc5
-rw-r--r--chromium/net/quic/core/crypto/quic_decrypter.h19
-rw-r--r--chromium/net/quic/core/crypto/quic_encrypter.cc5
-rw-r--r--chromium/net/quic/core/crypto/quic_encrypter.h17
-rw-r--r--chromium/net/quic/core/crypto/quic_random.cc3
-rw-r--r--chromium/net/quic/core/crypto/quic_random.h14
-rw-r--r--chromium/net/quic/core/crypto/scoped_evp_aead_ctx.h6
-rw-r--r--chromium/net/quic/core/crypto/strike_register.cc2
-rw-r--r--chromium/net/quic/core/crypto/strike_register.h13
-rw-r--r--chromium/net/quic/core/crypto/strike_register_client.h12
-rw-r--r--chromium/net/quic/core/crypto/strike_register_test.cc5
-rw-r--r--chromium/net/quic/core/frames/quic_ack_frame.cc161
-rw-r--r--chromium/net/quic/core/frames/quic_ack_frame.h133
-rw-r--r--chromium/net/quic/core/frames/quic_blocked_frame.cc18
-rw-r--r--chromium/net/quic/core/frames/quic_blocked_frame.h34
-rw-r--r--chromium/net/quic/core/frames/quic_connection_close_frame.cc20
-rw-r--r--chromium/net/quic/core/frames/quic_connection_close_frame.h29
-rw-r--r--chromium/net/quic/core/frames/quic_frame.cc163
-rw-r--r--chromium/net/quic/core/frames/quic_frame.h82
-rw-r--r--chromium/net/quic/core/frames/quic_frames_test.cc285
-rw-r--r--chromium/net/quic/core/frames/quic_goaway_frame.cc29
-rw-r--r--chromium/net/quic/core/frames/quic_goaway_frame.h33
-rw-r--r--chromium/net/quic/core/frames/quic_mtu_discovery_frame.h18
-rw-r--r--chromium/net/quic/core/frames/quic_padding_frame.cc17
-rw-r--r--chromium/net/quic/core/frames/quic_padding_frame.h32
-rw-r--r--chromium/net/quic/core/frames/quic_path_close_frame.cc17
-rw-r--r--chromium/net/quic/core/frames/quic_path_close_frame.h34
-rw-r--r--chromium/net/quic/core/frames/quic_ping_frame.h18
-rw-r--r--chromium/net/quic/core/frames/quic_rst_stream_frame.cc26
-rw-r--r--chromium/net/quic/core/frames/quic_rst_stream_frame.h38
-rw-r--r--chromium/net/quic/core/frames/quic_stop_waiting_frame.cc22
-rw-r--r--chromium/net/quic/core/frames/quic_stop_waiting_frame.h31
-rw-r--r--chromium/net/quic/core/frames/quic_stream_frame.cc82
-rw-r--r--chromium/net/quic/core/frames/quic_stream_frame.h81
-rw-r--r--chromium/net/quic/core/frames/quic_window_update_frame.cc20
-rw-r--r--chromium/net/quic/core/frames/quic_window_update_frame.h39
-rw-r--r--chromium/net/quic/core/interval.h6
-rw-r--r--chromium/net/quic/core/interval_set.h7
-rw-r--r--chromium/net/quic/core/interval_set_test.cc17
-rw-r--r--chromium/net/quic/core/interval_test.cc4
-rw-r--r--chromium/net/quic/core/quic_ack_listener_interface.cc21
-rw-r--r--chromium/net/quic/core/quic_ack_listener_interface.h48
-rw-r--r--chromium/net/quic/core/quic_alarm.cc3
-rw-r--r--chromium/net/quic/core/quic_alarm.h14
-rw-r--r--chromium/net/quic/core/quic_alarm_factory.h10
-rw-r--r--chromium/net/quic/core/quic_alarm_test.cc1
-rw-r--r--chromium/net/quic/core/quic_arena_scoped_ptr.h13
-rw-r--r--chromium/net/quic/core/quic_arena_scoped_ptr_test.cc1
-rw-r--r--chromium/net/quic/core/quic_bandwidth.cc8
-rw-r--r--chromium/net/quic/core/quic_bandwidth.h17
-rw-r--r--chromium/net/quic/core/quic_bandwidth_test.cc9
-rw-r--r--chromium/net/quic/core/quic_blocked_writer_interface.h12
-rw-r--r--chromium/net/quic/core/quic_buffer_allocator.cc11
-rw-r--r--chromium/net/quic/core/quic_buffer_allocator.h37
-rw-r--r--chromium/net/quic/core/quic_buffered_packet_store.cc40
-rw-r--r--chromium/net/quic/core/quic_buffered_packet_store.h40
-rw-r--r--chromium/net/quic/core/quic_buffered_packet_store_test.cc52
-rw-r--r--chromium/net/quic/core/quic_bug_tracker.h13
-rw-r--r--chromium/net/quic/core/quic_client_promised_info.cc17
-rw-r--r--chromium/net/quic/core/quic_client_promised_info.h16
-rw-r--r--chromium/net/quic/core/quic_client_promised_info_test.cc13
-rw-r--r--chromium/net/quic/core/quic_client_push_promise_index.h14
-rw-r--r--chromium/net/quic/core/quic_client_session_base.cc20
-rw-r--r--chromium/net/quic/core/quic_client_session_base.h10
-rw-r--r--chromium/net/quic/core/quic_config.cc190
-rw-r--r--chromium/net/quic/core/quic_config.h106
-rw-r--r--chromium/net/quic/core/quic_config_test.cc56
-rw-r--r--chromium/net/quic/core/quic_connection.cc656
-rw-r--r--chromium/net/quic/core/quic_connection.h123
-rw-r--r--chromium/net/quic/core/quic_connection_close_delegate_interface.h27
-rw-r--r--chromium/net/quic/core/quic_connection_stats.cc42
-rw-r--r--chromium/net/quic/core/quic_connection_stats.h14
-rw-r--r--chromium/net/quic/core/quic_connection_test.cc642
-rw-r--r--chromium/net/quic/core/quic_constants.cc11
-rw-r--r--chromium/net/quic/core/quic_constants.h189
-rw-r--r--chromium/net/quic/core/quic_crypto_client_stream.cc29
-rw-r--r--chromium/net/quic/core/quic_crypto_client_stream.h16
-rw-r--r--chromium/net/quic/core/quic_crypto_client_stream_test.cc50
-rw-r--r--chromium/net/quic/core/quic_crypto_server_stream.cc88
-rw-r--r--chromium/net/quic/core/quic_crypto_server_stream.h39
-rw-r--r--chromium/net/quic/core/quic_crypto_server_stream_test.cc162
-rw-r--r--chromium/net/quic/core/quic_crypto_stream.cc15
-rw-r--r--chromium/net/quic/core/quic_crypto_stream.h15
-rw-r--r--chromium/net/quic/core/quic_crypto_stream_test.cc1
-rw-r--r--chromium/net/quic/core/quic_data_reader.cc4
-rw-r--r--chromium/net/quic/core/quic_data_reader.h14
-rw-r--r--chromium/net/quic/core/quic_data_writer.cc1
-rw-r--r--chromium/net/quic/core/quic_data_writer.h17
-rw-r--r--chromium/net/quic/core/quic_data_writer_test.cc5
-rw-r--r--chromium/net/quic/core/quic_error_codes.cc144
-rw-r--r--chromium/net/quic/core/quic_error_codes.h293
-rw-r--r--chromium/net/quic/core/quic_error_codes_test.cc25
-rw-r--r--chromium/net/quic/core/quic_flags.h56
-rw-r--r--chromium/net/quic/core/quic_flags_list.h184
-rw-r--r--chromium/net/quic/core/quic_flow_controller.cc112
-rw-r--r--chromium/net/quic/core/quic_flow_controller.h12
-rw-r--r--chromium/net/quic/core/quic_flow_controller_test.cc26
-rw-r--r--chromium/net/quic/core/quic_frame_list.cc254
-rw-r--r--chromium/net/quic/core/quic_frame_list.h82
-rw-r--r--chromium/net/quic/core/quic_framer.cc551
-rw-r--r--chromium/net/quic/core/quic_framer.h92
-rw-r--r--chromium/net/quic/core/quic_framer_test.cc2823
-rw-r--r--chromium/net/quic/core/quic_header_list.cc10
-rw-r--r--chromium/net/quic/core/quic_header_list.h14
-rw-r--r--chromium/net/quic/core/quic_header_list_test.cc5
-rw-r--r--chromium/net/quic/core/quic_headers_stream.cc637
-rw-r--r--chromium/net/quic/core/quic_headers_stream.h137
-rw-r--r--chromium/net/quic/core/quic_headers_stream_test.cc259
-rw-r--r--chromium/net/quic/core/quic_iovector.h28
-rw-r--r--chromium/net/quic/core/quic_multipath_received_packet_manager.cc9
-rw-r--r--chromium/net/quic/core/quic_multipath_received_packet_manager.h12
-rw-r--r--chromium/net/quic/core/quic_multipath_received_packet_manager_test.cc8
-rw-r--r--chromium/net/quic/core/quic_multipath_sent_packet_manager.cc524
-rw-r--r--chromium/net/quic/core/quic_multipath_sent_packet_manager.h220
-rw-r--r--chromium/net/quic/core/quic_multipath_sent_packet_manager_test.cc356
-rw-r--r--chromium/net/quic/core/quic_multipath_transmissions_map.h12
-rw-r--r--chromium/net/quic/core/quic_one_block_arena.h18
-rw-r--r--chromium/net/quic/core/quic_one_block_arena_test.cc5
-rw-r--r--chromium/net/quic/core/quic_packet_creator.cc84
-rw-r--r--chromium/net/quic/core/quic_packet_creator.h82
-rw-r--r--chromium/net/quic/core/quic_packet_creator_test.cc204
-rw-r--r--chromium/net/quic/core/quic_packet_generator.cc36
-rw-r--r--chromium/net/quic/core/quic_packet_generator.h50
-rw-r--r--chromium/net/quic/core/quic_packet_generator_test.cc62
-rw-r--r--chromium/net/quic/core/quic_packet_writer.h25
-rw-r--r--chromium/net/quic/core/quic_packets.cc250
-rw-r--r--chromium/net/quic/core/quic_packets.h262
-rw-r--r--chromium/net/quic/core/quic_pending_retransmission.h42
-rw-r--r--chromium/net/quic/core/quic_protocol.cc856
-rw-r--r--chromium/net/quic/core/quic_protocol.h1528
-rw-r--r--chromium/net/quic/core/quic_protocol_test.cc517
-rw-r--r--chromium/net/quic/core/quic_received_packet_manager.cc186
-rw-r--r--chromium/net/quic/core/quic_received_packet_manager.h107
-rw-r--r--chromium/net/quic/core/quic_received_packet_manager_test.cc276
-rw-r--r--chromium/net/quic/core/quic_sent_entropy_manager.cc113
-rw-r--r--chromium/net/quic/core/quic_sent_entropy_manager.h89
-rw-r--r--chromium/net/quic/core/quic_sent_entropy_manager_test.cc96
-rw-r--r--chromium/net/quic/core/quic_sent_packet_manager.cc282
-rw-r--r--chromium/net/quic/core/quic_sent_packet_manager.h207
-rw-r--r--chromium/net/quic/core/quic_sent_packet_manager_interface.h195
-rw-r--r--chromium/net/quic/core/quic_sent_packet_manager_test.cc339
-rw-r--r--chromium/net/quic/core/quic_server_id.cc6
-rw-r--r--chromium/net/quic/core/quic_server_id.h10
-rw-r--r--chromium/net/quic/core/quic_server_session_base.cc16
-rw-r--r--chromium/net/quic/core/quic_server_session_base.h14
-rw-r--r--chromium/net/quic/core/quic_server_session_base_test.cc77
-rw-r--r--chromium/net/quic/core/quic_session.cc170
-rw-r--r--chromium/net/quic/core/quic_session.h39
-rw-r--r--chromium/net/quic/core/quic_session_test.cc73
-rw-r--r--chromium/net/quic/core/quic_simple_buffer_allocator.h12
-rw-r--r--chromium/net/quic/core/quic_simple_buffer_allocator_test.cc2
-rw-r--r--chromium/net/quic/core/quic_socket_address_coder.cc15
-rw-r--r--chromium/net/quic/core/quic_socket_address_coder.h20
-rw-r--r--chromium/net/quic/core/quic_socket_address_coder_test.cc26
-rw-r--r--chromium/net/quic/core/quic_spdy_session.cc636
-rw-r--r--chromium/net/quic/core/quic_spdy_session.h171
-rw-r--r--chromium/net/quic/core/quic_spdy_stream.cc78
-rw-r--r--chromium/net/quic/core/quic_spdy_stream.h45
-rw-r--r--chromium/net/quic/core/quic_spdy_stream_test.cc61
-rw-r--r--chromium/net/quic/core/quic_stream.cc63
-rw-r--r--chromium/net/quic/core/quic_stream.h37
-rw-r--r--chromium/net/quic/core/quic_stream_sequencer.cc55
-rw-r--r--chromium/net/quic/core/quic_stream_sequencer.h13
-rw-r--r--chromium/net/quic/core/quic_stream_sequencer_buffer.cc177
-rw-r--r--chromium/net/quic/core/quic_stream_sequencer_buffer.h29
-rw-r--r--chromium/net/quic/core/quic_stream_sequencer_buffer_interface.h77
-rw-r--r--chromium/net/quic/core/quic_stream_sequencer_buffer_test.cc85
-rw-r--r--chromium/net/quic/core/quic_stream_sequencer_test.cc56
-rw-r--r--chromium/net/quic/core/quic_stream_test.cc71
-rw-r--r--chromium/net/quic/core/quic_sustained_bandwidth_recorder.cc15
-rw-r--r--chromium/net/quic/core/quic_sustained_bandwidth_recorder.h12
-rw-r--r--chromium/net/quic/core/quic_tag.cc72
-rw-r--r--chromium/net/quic/core/quic_tag.h54
-rw-r--r--chromium/net/quic/core/quic_tag_test.cc37
-rw-r--r--chromium/net/quic/core/quic_time.cc4
-rw-r--r--chromium/net/quic/core/quic_time.h21
-rw-r--r--chromium/net/quic/core/quic_transmission_info.cc45
-rw-r--r--chromium/net/quic/core/quic_transmission_info.h62
-rw-r--r--chromium/net/quic/core/quic_types.cc13
-rw-r--r--chromium/net/quic/core/quic_types.h218
-rw-r--r--chromium/net/quic/core/quic_unacked_packet_map.cc83
-rw-r--r--chromium/net/quic/core/quic_unacked_packet_map.h51
-rw-r--r--chromium/net/quic/core/quic_unacked_packet_map_test.cc9
-rw-r--r--chromium/net/quic/core/quic_utils.cc441
-rw-r--r--chromium/net/quic/core/quic_utils.h128
-rw-r--r--chromium/net/quic/core/quic_utils_test.cc115
-rw-r--r--chromium/net/quic/core/quic_version_manager.cc45
-rw-r--r--chromium/net/quic/core/quic_version_manager.h49
-rw-r--r--chromium/net/quic/core/quic_version_manager_test.cc54
-rw-r--r--chromium/net/quic/core/quic_versions.cc123
-rw-r--r--chromium/net/quic/core/quic_versions.h87
-rw-r--r--chromium/net/quic/core/quic_versions_test.cc201
-rw-r--r--chromium/net/quic/core/quic_write_blocked_list.h25
-rw-r--r--chromium/net/quic/core/spdy_utils.cc81
-rw-r--r--chromium/net/quic/core/spdy_utils.h32
-rw-r--r--chromium/net/quic/core/spdy_utils_test.cc12
-rw-r--r--chromium/net/quic/platform/README.md12
-rw-r--r--chromium/net/quic/platform/api/quic_aligned.h14
-rw-r--r--chromium/net/quic/platform/api/quic_bug_tracker.h12
-rw-r--r--chromium/net/quic/platform/api/quic_clock.cc (renamed from chromium/net/quic/core/quic_clock.cc)19
-rw-r--r--chromium/net/quic/platform/api/quic_clock.h (renamed from chromium/net/quic/core/quic_clock.h)28
-rw-r--r--chromium/net/quic/platform/api/quic_export.h10
-rw-r--r--chromium/net/quic/platform/api/quic_ip_address.cc86
-rw-r--r--chromium/net/quic/platform/api/quic_ip_address.h67
-rw-r--r--chromium/net/quic/platform/api/quic_ip_address_family.h20
-rw-r--r--chromium/net/quic/platform/api/quic_logging.h23
-rw-r--r--chromium/net/quic/platform/api/quic_lru_cache.h52
-rw-r--r--chromium/net/quic/platform/api/quic_lru_cache_test.cc76
-rw-r--r--chromium/net/quic/platform/api/quic_mutex.cc45
-rw-r--r--chromium/net/quic/platform/api/quic_mutex.h70
-rw-r--r--chromium/net/quic/platform/api/quic_ptr_util.h23
-rw-r--r--chromium/net/quic/platform/api/quic_reference_counted.h161
-rw-r--r--chromium/net/quic/platform/api/quic_reference_counted_test.cc173
-rw-r--r--chromium/net/quic/platform/api/quic_socket_address.cc59
-rw-r--r--chromium/net/quic/platform/api/quic_socket_address.h48
-rw-r--r--chromium/net/quic/platform/api/quic_str_cat.h19
-rw-r--r--chromium/net/quic/platform/api/quic_str_cat_test.cc167
-rw-r--r--chromium/net/quic/platform/api/quic_text_utils.h98
-rw-r--r--chromium/net/quic/platform/api/quic_text_utils_test.cc140
-rw-r--r--chromium/net/quic/platform/impl/quic_aligned_impl.h22
-rw-r--r--chromium/net/quic/platform/impl/quic_bug_tracker_impl.h15
-rw-r--r--chromium/net/quic/platform/impl/quic_chromium_clock.cc30
-rw-r--r--chromium/net/quic/platform/impl/quic_chromium_clock.h32
-rw-r--r--chromium/net/quic/platform/impl/quic_chromium_clock_test.cc (renamed from chromium/net/quic/core/quic_clock_test.cc)10
-rw-r--r--chromium/net/quic/platform/impl/quic_export_impl.h13
-rw-r--r--chromium/net/quic/platform/impl/quic_ip_address_impl.cc133
-rw-r--r--chromium/net/quic/platform/impl/quic_ip_address_impl.h52
-rw-r--r--chromium/net/quic/platform/impl/quic_logging_impl.h47
-rw-r--r--chromium/net/quic/platform/impl/quic_lru_cache_impl.h50
-rw-r--r--chromium/net/quic/platform/impl/quic_mutex_impl.cc25
-rw-r--r--chromium/net/quic/platform/impl/quic_mutex_impl.h73
-rw-r--r--chromium/net/quic/platform/impl/quic_ptr_util_impl.h23
-rw-r--r--chromium/net/quic/platform/impl/quic_reference_counted_impl.h114
-rw-r--r--chromium/net/quic/platform/impl/quic_socket_address_impl.cc91
-rw-r--r--chromium/net/quic/platform/impl/quic_socket_address_impl.h45
-rw-r--r--chromium/net/quic/platform/impl/quic_str_cat_impl.h23
-rw-r--r--chromium/net/quic/platform/impl/quic_text_utils_impl.h146
-rw-r--r--chromium/net/quic/quartc/quartc_alarm_factory.h6
-rw-r--r--chromium/net/quic/quartc/quartc_factory.cc3
-rw-r--r--chromium/net/quic/quartc/quartc_factory.h12
-rw-r--r--chromium/net/quic/quartc/quartc_factory_interface.h6
-rw-r--r--chromium/net/quic/quartc/quartc_packet_writer.cc13
-rw-r--r--chromium/net/quic/quartc/quartc_packet_writer.h11
-rw-r--r--chromium/net/quic/quartc/quartc_session.cc26
-rw-r--r--chromium/net/quic/quartc/quartc_session.h9
-rw-r--r--chromium/net/quic/quartc/quartc_session_interface.h4
-rw-r--r--chromium/net/quic/quartc/quartc_session_test.cc21
-rw-r--r--chromium/net/quic/quartc/quartc_stream.h7
-rw-r--r--chromium/net/quic/quartc/quartc_stream_interface.h4
-rw-r--r--chromium/net/quic/quartc/quartc_stream_test.cc17
-rw-r--r--chromium/net/quic/quartc/quartc_task_runner_interface.h6
-rw-r--r--chromium/net/quic/test_tools/crypto_test_utils.cc102
-rw-r--r--chromium/net/quic/test_tools/crypto_test_utils.h42
-rw-r--r--chromium/net/quic/test_tools/crypto_test_utils_test.cc68
-rw-r--r--chromium/net/quic/test_tools/failing_proof_source.cc33
-rw-r--r--chromium/net/quic/test_tools/failing_proof_source.h36
-rw-r--r--chromium/net/quic/test_tools/fake_proof_source.cc65
-rw-r--r--chromium/net/quic/test_tools/fake_proof_source.h13
-rw-r--r--chromium/net/quic/test_tools/mock_clock.h11
-rw-r--r--chromium/net/quic/test_tools/mock_crypto_client_stream.cc24
-rw-r--r--chromium/net/quic/test_tools/mock_quic_client_promised_info.h2
-rw-r--r--chromium/net/quic/test_tools/mock_quic_dispatcher.cc6
-rw-r--r--chromium/net/quic/test_tools/mock_quic_dispatcher.h10
-rw-r--r--chromium/net/quic/test_tools/mock_quic_spdy_client_stream.h2
-rw-r--r--chromium/net/quic/test_tools/quic_buffered_packet_store_peer.h2
-rw-r--r--chromium/net/quic/test_tools/quic_config_peer.cc2
-rw-r--r--chromium/net/quic/test_tools/quic_config_peer.h4
-rw-r--r--chromium/net/quic/test_tools/quic_connection_peer.cc58
-rw-r--r--chromium/net/quic/test_tools/quic_connection_peer.h33
-rw-r--r--chromium/net/quic/test_tools/quic_crypto_server_config_peer.cc57
-rw-r--r--chromium/net/quic/test_tools/quic_crypto_server_config_peer.h38
-rw-r--r--chromium/net/quic/test_tools/quic_flow_controller_peer.cc2
-rw-r--r--chromium/net/quic/test_tools/quic_flow_controller_peer.h2
-rw-r--r--chromium/net/quic/test_tools/quic_framer_peer.cc2
-rw-r--r--chromium/net/quic/test_tools/quic_framer_peer.h2
-rw-r--r--chromium/net/quic/test_tools/quic_headers_stream_peer.cc19
-rw-r--r--chromium/net/quic/test_tools/quic_headers_stream_peer.h28
-rw-r--r--chromium/net/quic/test_tools/quic_multipath_sent_packet_manager_peer.cc29
-rw-r--r--chromium/net/quic/test_tools/quic_multipath_sent_packet_manager_peer.h31
-rw-r--r--chromium/net/quic/test_tools/quic_packet_creator_peer.h3
-rw-r--r--chromium/net/quic/test_tools/quic_packet_generator_peer.h2
-rw-r--r--chromium/net/quic/test_tools/quic_received_packet_manager_peer.cc11
-rw-r--r--chromium/net/quic/test_tools/quic_received_packet_manager_peer.h7
-rw-r--r--chromium/net/quic/test_tools/quic_sent_packet_manager_peer.cc12
-rw-r--r--chromium/net/quic/test_tools/quic_sent_packet_manager_peer.h14
-rw-r--r--chromium/net/quic/test_tools/quic_session_peer.h4
-rw-r--r--chromium/net/quic/test_tools/quic_spdy_session_peer.cc36
-rw-r--r--chromium/net/quic/test_tools/quic_spdy_session_peer.h21
-rw-r--r--chromium/net/quic/test_tools/quic_stream_factory_peer.cc7
-rw-r--r--chromium/net/quic/test_tools/quic_stream_factory_peer.h2
-rw-r--r--chromium/net/quic/test_tools/quic_stream_peer.cc4
-rw-r--r--chromium/net/quic/test_tools/quic_stream_peer.h4
-rw-r--r--chromium/net/quic/test_tools/quic_stream_sequencer_buffer_peer.cc18
-rw-r--r--chromium/net/quic/test_tools/quic_stream_sequencer_peer.cc1
-rw-r--r--chromium/net/quic/test_tools/quic_stream_sequencer_peer.h2
-rw-r--r--chromium/net/quic/test_tools/quic_sustained_bandwidth_recorder_peer.cc2
-rw-r--r--chromium/net/quic/test_tools/quic_sustained_bandwidth_recorder_peer.h2
-rw-r--r--chromium/net/quic/test_tools/quic_test_utils.cc163
-rw-r--r--chromium/net/quic/test_tools/quic_test_utils.h199
-rw-r--r--chromium/net/quic/test_tools/quic_test_utils_test.cc8
-rw-r--r--chromium/net/quic/test_tools/simple_quic_framer.cc64
-rw-r--r--chromium/net/quic/test_tools/simple_quic_framer.h6
-rw-r--r--chromium/net/quic/test_tools/simulator/README.md2
-rw-r--r--chromium/net/quic/test_tools/simulator/actor.cc4
-rw-r--r--chromium/net/quic/test_tools/simulator/actor.h3
-rw-r--r--chromium/net/quic/test_tools/simulator/alarm_factory.cc9
-rw-r--r--chromium/net/quic/test_tools/simulator/link.cc8
-rw-r--r--chromium/net/quic/test_tools/simulator/packet_filter.cc40
-rw-r--r--chromium/net/quic/test_tools/simulator/packet_filter.h77
-rw-r--r--chromium/net/quic/test_tools/simulator/port.cc4
-rw-r--r--chromium/net/quic/test_tools/simulator/port.h2
-rw-r--r--chromium/net/quic/test_tools/simulator/queue.cc16
-rw-r--r--chromium/net/quic/test_tools/simulator/quic_endpoint.cc51
-rw-r--r--chromium/net/quic/test_tools/simulator/quic_endpoint.h10
-rw-r--r--chromium/net/quic/test_tools/simulator/quic_endpoint_test.cc23
-rw-r--r--chromium/net/quic/test_tools/simulator/simulator.cc6
-rw-r--r--chromium/net/quic/test_tools/simulator/simulator.h2
-rw-r--r--chromium/net/quic/test_tools/simulator/simulator_test.cc91
-rw-r--r--chromium/net/quic/test_tools/simulator/switch.cc16
-rw-r--r--chromium/net/quic/test_tools/simulator/traffic_policer.cc50
-rw-r--r--chromium/net/quic/test_tools/simulator/traffic_policer.h32
-rw-r--r--chromium/net/server/http_server.cc3
-rw-r--r--chromium/net/server/http_server.h1
-rw-r--r--chromium/net/server/http_server_unittest.cc4
-rw-r--r--chromium/net/server/web_socket_encoder.cc5
-rw-r--r--chromium/net/socket/client_socket_handle.cc11
-rw-r--r--chromium/net/socket/client_socket_handle.h14
-rw-r--r--chromium/net/socket/client_socket_pool_base.cc137
-rw-r--r--chromium/net/socket/client_socket_pool_base.h18
-rw-r--r--chromium/net/socket/client_socket_pool_base_unittest.cc136
-rw-r--r--chromium/net/socket/client_socket_pool_manager.cc2
-rw-r--r--chromium/net/socket/client_socket_pool_manager.h13
-rw-r--r--chromium/net/socket/client_socket_pool_manager_impl.cc6
-rw-r--r--chromium/net/socket/client_socket_pool_manager_impl.h11
-rw-r--r--chromium/net/socket/fuzzed_socket.cc18
-rw-r--r--chromium/net/socket/fuzzed_socket.h2
-rw-r--r--chromium/net/socket/fuzzed_socket_factory.cc2
-rw-r--r--chromium/net/socket/mock_client_socket_pool_manager.cc4
-rw-r--r--chromium/net/socket/mock_client_socket_pool_manager.h5
-rw-r--r--chromium/net/socket/next_proto.cc6
-rw-r--r--chromium/net/socket/sequenced_socket_data_unittest.cc3
-rw-r--r--chromium/net/socket/socket_bio_adapter.cc10
-rw-r--r--chromium/net/socket/socket_bio_adapter.h3
-rw-r--r--chromium/net/socket/socket_posix.cc4
-rw-r--r--chromium/net/socket/socket_posix.h1
-rw-r--r--chromium/net/socket/socket_test_util.cc4
-rw-r--r--chromium/net/socket/socket_test_util.h4
-rw-r--r--chromium/net/socket/socks5_client_socket.cc4
-rw-r--r--chromium/net/socket/socks5_client_socket.h2
-rw-r--r--chromium/net/socket/socks_client_socket.cc4
-rw-r--r--chromium/net/socket/socks_client_socket.h2
-rw-r--r--chromium/net/socket/socks_client_socket_pool.cc2
-rw-r--r--chromium/net/socket/ssl_client_socket.cc17
-rw-r--r--chromium/net/socket/ssl_client_socket.h9
-rw-r--r--chromium/net/socket/ssl_client_socket_impl.cc177
-rw-r--r--chromium/net/socket/ssl_client_socket_impl.h19
-rw-r--r--chromium/net/socket/ssl_client_socket_pool.cc37
-rw-r--r--chromium/net/socket/ssl_client_socket_pool.h5
-rw-r--r--chromium/net/socket/ssl_client_socket_pool_unittest.cc6
-rw-r--r--chromium/net/socket/ssl_client_socket_unittest.cc125
-rw-r--r--chromium/net/socket/ssl_server_socket_impl.cc9
-rw-r--r--chromium/net/socket/ssl_server_socket_impl.h2
-rw-r--r--chromium/net/socket/ssl_server_socket_unittest.cc24
-rw-r--r--chromium/net/socket/stream_socket.cc5
-rw-r--r--chromium/net/socket/stream_socket.h33
-rw-r--r--chromium/net/socket/tcp_client_socket.cc2
-rw-r--r--chromium/net/socket/tcp_client_socket.h2
-rw-r--r--chromium/net/socket/tcp_socket_posix.cc19
-rw-r--r--chromium/net/socket/tcp_socket_posix.h15
-rw-r--r--chromium/net/socket/tcp_socket_unittest.cc46
-rw-r--r--chromium/net/socket/tcp_socket_win.cc77
-rw-r--r--chromium/net/socket/transport_client_socket_pool.cc7
-rw-r--r--chromium/net/socket/transport_client_socket_pool_test_util.cc6
-rw-r--r--chromium/net/socket/udp_socket_posix.cc7
-rw-r--r--chromium/net/socket/udp_socket_win.cc4
-rw-r--r--chromium/net/socket/unix_domain_client_socket_posix.cc2
-rw-r--r--chromium/net/socket/unix_domain_client_socket_posix.h2
-rw-r--r--chromium/net/socket/websocket_endpoint_lock_manager_unittest.cc2
-rw-r--r--chromium/net/socket/websocket_transport_client_socket_pool.cc19
-rw-r--r--chromium/net/spdy/bidirectional_stream_spdy_impl.cc9
-rw-r--r--chromium/net/spdy/bidirectional_stream_spdy_impl.h5
-rw-r--r--chromium/net/spdy/buffered_spdy_framer.cc47
-rw-r--r--chromium/net/spdy/buffered_spdy_framer.h23
-rw-r--r--chromium/net/spdy/buffered_spdy_framer_unittest.cc11
-rw-r--r--chromium/net/spdy/hpack/hpack_constants.cc4
-rw-r--r--chromium/net/spdy/hpack/hpack_constants.h6
-rw-r--r--chromium/net/spdy/hpack/hpack_decoder2.cc330
-rw-r--r--chromium/net/spdy/hpack/hpack_decoder2.h146
-rw-r--r--chromium/net/spdy/hpack/hpack_decoder2_test.cc959
-rw-r--r--chromium/net/spdy/hpack/hpack_decoder3.cc151
-rw-r--r--chromium/net/spdy/hpack/hpack_decoder3.h112
-rw-r--r--chromium/net/spdy/hpack/hpack_decoder3_test.cc1012
-rw-r--r--chromium/net/spdy/hpack/hpack_decoder_interface.h11
-rw-r--r--chromium/net/spdy/hpack/hpack_decoder_test.cc16
-rw-r--r--chromium/net/spdy/hpack/hpack_encoder.cc75
-rw-r--r--chromium/net/spdy/hpack/hpack_encoder.h13
-rw-r--r--chromium/net/spdy/hpack/hpack_encoder_test.cc85
-rw-r--r--chromium/net/spdy/hpack/hpack_entry.cc8
-rw-r--r--chromium/net/spdy/hpack/hpack_entry.h6
-rw-r--r--chromium/net/spdy/hpack/hpack_header_table.h6
-rw-r--r--chromium/net/spdy/hpack/hpack_huffman_decoder.cc4
-rw-r--r--chromium/net/spdy/hpack/hpack_huffman_table.h6
-rw-r--r--chromium/net/spdy/hpack/hpack_input_stream.h6
-rw-r--r--chromium/net/spdy/hpack/hpack_output_stream.h6
-rw-r--r--chromium/net/spdy/hpack/hpack_static_table.h6
-rw-r--r--chromium/net/spdy/http2_frame_decoder_adapter.cc975
-rw-r--r--chromium/net/spdy/http2_frame_decoder_adapter.h24
-rw-r--r--chromium/net/spdy/http2_priority_dependencies.cc133
-rw-r--r--chromium/net/spdy/http2_priority_dependencies.h50
-rw-r--r--chromium/net/spdy/http2_priority_dependencies_unittest.cc154
-rw-r--r--chromium/net/spdy/http2_write_scheduler.h1
-rw-r--r--chromium/net/spdy/mock_spdy_framer_visitor.h9
-rw-r--r--chromium/net/spdy/multiplexed_http_stream.cc59
-rw-r--r--chromium/net/spdy/multiplexed_http_stream.h39
-rw-r--r--chromium/net/spdy/multiplexed_session.cc51
-rw-r--r--chromium/net/spdy/multiplexed_session.h78
-rw-r--r--chromium/net/spdy/server_push_delegate.h2
-rw-r--r--chromium/net/spdy/spdy_alt_svc_wire_format.cc22
-rw-r--r--chromium/net/spdy/spdy_deframer_visitor.cc43
-rw-r--r--chromium/net/spdy/spdy_deframer_visitor_test.cc8
-rw-r--r--chromium/net/spdy/spdy_flags.cc12
-rw-r--r--chromium/net/spdy/spdy_flags.h6
-rw-r--r--chromium/net/spdy/spdy_frame_builder.cc124
-rw-r--r--chromium/net/spdy/spdy_frame_builder.h41
-rw-r--r--chromium/net/spdy/spdy_frame_builder_test.cc56
-rw-r--r--chromium/net/spdy/spdy_frame_reader.cc10
-rw-r--r--chromium/net/spdy/spdy_framer.cc1726
-rw-r--r--chromium/net/spdy/spdy_framer.h237
-rw-r--r--chromium/net/spdy/spdy_framer_decoder_adapter.cc28
-rw-r--r--chromium/net/spdy/spdy_framer_decoder_adapter.h25
-rw-r--r--chromium/net/spdy/spdy_framer_test.cc2923
-rw-r--r--chromium/net/spdy/spdy_header_block.cc160
-rw-r--r--chromium/net/spdy/spdy_header_block.h120
-rw-r--r--chromium/net/spdy/spdy_header_block_test.cc41
-rw-r--r--chromium/net/spdy/spdy_header_indexing.cc7
-rw-r--r--chromium/net/spdy/spdy_header_indexing.h12
-rw-r--r--chromium/net/spdy/spdy_headers_block_parser.cc4
-rw-r--r--chromium/net/spdy/spdy_headers_block_parser.h13
-rw-r--r--chromium/net/spdy/spdy_headers_block_parser_test.cc34
-rw-r--r--chromium/net/spdy/spdy_http_stream.cc73
-rw-r--r--chromium/net/spdy/spdy_http_stream.h24
-rw-r--r--chromium/net/spdy/spdy_http_stream_unittest.cc186
-rw-r--r--chromium/net/spdy/spdy_http_utils.cc19
-rw-r--r--chromium/net/spdy/spdy_http_utils.h6
-rw-r--r--chromium/net/spdy/spdy_network_transaction_unittest.cc1224
-rw-r--r--chromium/net/spdy/spdy_no_op_visitor.h8
-rw-r--r--chromium/net/spdy/spdy_protocol.cc867
-rw-r--r--chromium/net/spdy/spdy_protocol.h577
-rw-r--r--chromium/net/spdy/spdy_protocol_test.cc188
-rw-r--r--chromium/net/spdy/spdy_protocol_test_utils.cc4
-rw-r--r--chromium/net/spdy/spdy_proxy_client_socket.cc14
-rw-r--r--chromium/net/spdy/spdy_proxy_client_socket.h8
-rw-r--r--chromium/net/spdy/spdy_proxy_client_socket_unittest.cc4
-rw-r--r--chromium/net/spdy/spdy_read_queue.h6
-rw-r--r--chromium/net/spdy/spdy_session.cc470
-rw-r--r--chromium/net/spdy/spdy_session.h108
-rw-r--r--chromium/net/spdy/spdy_session_key.h1
-rw-r--r--chromium/net/spdy/spdy_session_pool.cc62
-rw-r--r--chromium/net/spdy/spdy_session_pool.h29
-rw-r--r--chromium/net/spdy/spdy_session_pool_unittest.cc66
-rw-r--r--chromium/net/spdy/spdy_session_unittest.cc342
-rw-r--r--chromium/net/spdy/spdy_stream.cc316
-rw-r--r--chromium/net/spdy/spdy_stream.h145
-rw-r--r--chromium/net/spdy/spdy_stream_test_util.cc27
-rw-r--r--chromium/net/spdy/spdy_stream_test_util.h22
-rw-r--r--chromium/net/spdy/spdy_stream_unittest.cc877
-rw-r--r--chromium/net/spdy/spdy_test_util_common.cc85
-rw-r--r--chromium/net/spdy/spdy_test_util_common.h12
-rw-r--r--chromium/net/spdy/spdy_test_utils.cc44
-rw-r--r--chromium/net/spdy/spdy_test_utils.h8
-rw-r--r--chromium/net/spdy/spdy_write_queue.h1
-rw-r--r--chromium/net/ssl/channel_id_service.cc3
-rw-r--r--chromium/net/ssl/channel_id_service.h6
-rw-r--r--chromium/net/ssl/ssl_client_session_cache.cc77
-rw-r--r--chromium/net/ssl/ssl_client_session_cache.h34
-rw-r--r--chromium/net/ssl/ssl_client_session_cache_unittest.cc162
-rw-r--r--chromium/net/ssl/ssl_config.cc2
-rw-r--r--chromium/net/ssl/ssl_config_service.cc24
-rw-r--r--chromium/net/ssl/ssl_config_service_unittest.cc15
-rw-r--r--chromium/net/ssl/ssl_connection_status_flags.h7
-rw-r--r--chromium/net/ssl/ssl_platform_key.h8
-rw-r--r--chromium/net/ssl/ssl_platform_key_android.cc2
-rw-r--r--chromium/net/ssl/ssl_platform_key_android_unittest.cc347
-rw-r--r--chromium/net/ssl/ssl_platform_key_chromecast.cc9
-rw-r--r--chromium/net/ssl/ssl_platform_key_chromecast_unittest.cc52
-rw-r--r--chromium/net/ssl/ssl_platform_key_mac.cc239
-rw-r--r--chromium/net/ssl/ssl_platform_key_mac.h27
-rw-r--r--chromium/net/ssl/ssl_platform_key_mac_unittest.cc137
-rw-r--r--chromium/net/ssl/ssl_platform_key_nss.cc2
-rw-r--r--chromium/net/ssl/ssl_platform_key_nss_unittest.cc141
-rw-r--r--chromium/net/ssl/ssl_platform_key_util.cc7
-rw-r--r--chromium/net/ssl/ssl_platform_key_util_unittest.cc14
-rw-r--r--chromium/net/ssl/ssl_platform_key_win.cc2
-rw-r--r--chromium/net/ssl/ssl_private_key_test_util.cc221
-rw-r--r--chromium/net/ssl/ssl_private_key_test_util.h24
-rw-r--r--chromium/net/ssl/test_ssl_private_key.h6
-rw-r--r--chromium/net/test/cert_test_util.h4
-rw-r--r--chromium/net/test/ct_test_util.h6
-rw-r--r--chromium/net/test/embedded_test_server/embedded_test_server.cc58
-rw-r--r--chromium/net/test/embedded_test_server/embedded_test_server.h11
-rw-r--r--chromium/net/test/embedded_test_server/embedded_test_server_unittest.cc7
-rw-r--r--chromium/net/test/embedded_test_server/http_connection.h1
-rw-r--r--chromium/net/test/embedded_test_server/http_request.cc3
-rw-r--r--chromium/net/test/embedded_test_server/http_request.h2
-rw-r--r--chromium/net/test/embedded_test_server/http_request_unittest.cc14
-rw-r--r--chromium/net/test/gtest_util.h33
-rw-r--r--chromium/net/test/python_utils.cc11
-rw-r--r--chromium/net/test/python_utils.h3
-rw-r--r--chromium/net/test/run_all_unittests.cc36
-rw-r--r--chromium/net/test/spawned_test_server/base_test_server.cc7
-rw-r--r--chromium/net/test/spawned_test_server/base_test_server.h4
-rw-r--r--chromium/net/test/spawned_test_server/local_test_server.cc18
-rw-r--r--chromium/net/test/spawned_test_server/local_test_server_win.cc1
-rw-r--r--chromium/net/test/spawned_test_server/remote_test_server.cc1
-rw-r--r--chromium/net/test/spawned_test_server/remote_test_server.h1
-rw-r--r--chromium/net/test/spawned_test_server/spawned_test_server.h1
-rw-r--r--chromium/net/test/spawned_test_server/spawner_communicator.cc2
-rw-r--r--chromium/net/test/test_certificate_data.h5
-rw-r--r--chromium/net/test/url_request/url_request_failed_job.cc9
-rw-r--r--chromium/net/test/url_request/url_request_failed_job.h2
-rw-r--r--chromium/net/test/url_request/url_request_hanging_read_job.cc2
-rw-r--r--chromium/net/test/url_request/url_request_hanging_read_job.h6
-rw-r--r--chromium/net/test/url_request/url_request_mock_data_job.h6
-rw-r--r--chromium/net/test/url_request/url_request_mock_http_job.cc1
-rw-r--r--chromium/net/third_party/mozilla_security_manager/nsKeygenHandler.cpp257
-rw-r--r--chromium/net/third_party/mozilla_security_manager/nsKeygenHandler.h69
-rw-r--r--chromium/net/third_party/mozilla_security_manager/nsPKCS12Blob.cpp4
-rw-r--r--chromium/net/tools/cachetool/cachetool.cc175
-rw-r--r--chromium/net/tools/cert_verify_tool/cert_verify_tool.cc1
-rw-r--r--chromium/net/tools/cert_verify_tool/verify_using_path_builder.cc97
-rw-r--r--chromium/net/tools/dns_fuzz_stub/dns_fuzz_stub.cc1
-rw-r--r--chromium/net/tools/domain_security_preload_generator/bit_writer.cc53
-rw-r--r--chromium/net/tools/domain_security_preload_generator/bit_writer.h61
-rw-r--r--chromium/net/tools/domain_security_preload_generator/cert_util.cc155
-rw-r--r--chromium/net/tools/domain_security_preload_generator/cert_util.h46
-rw-r--r--chromium/net/tools/domain_security_preload_generator/domain_security_entry.cc15
-rw-r--r--chromium/net/tools/domain_security_preload_generator/domain_security_entry.h60
-rw-r--r--chromium/net/tools/domain_security_preload_generator/domain_security_preload_generator.cc632
-rw-r--r--chromium/net/tools/domain_security_preload_generator/huffman/huffman_frequency_tracker.cc159
-rw-r--r--chromium/net/tools/domain_security_preload_generator/huffman/huffman_frequency_tracker.h84
-rw-r--r--chromium/net/tools/domain_security_preload_generator/pinset.cc26
-rw-r--r--chromium/net/tools/domain_security_preload_generator/pinset.h58
-rw-r--r--chromium/net/tools/domain_security_preload_generator/pinsets.cc28
-rw-r--r--chromium/net/tools/domain_security_preload_generator/pinsets.h56
-rw-r--r--chromium/net/tools/domain_security_preload_generator/preloaded_state_generator.cc366
-rw-r--r--chromium/net/tools/domain_security_preload_generator/preloaded_state_generator.h59
-rw-r--r--chromium/net/tools/domain_security_preload_generator/resources/transport_security_state_static.template50
-rw-r--r--chromium/net/tools/domain_security_preload_generator/spki_hash.cc50
-rw-r--r--chromium/net/tools/domain_security_preload_generator/spki_hash.h49
-rw-r--r--chromium/net/tools/domain_security_preload_generator/trie/trie_bit_buffer.cc133
-rw-r--r--chromium/net/tools/domain_security_preload_generator/trie/trie_bit_buffer.h85
-rw-r--r--chromium/net/tools/domain_security_preload_generator/trie/trie_writer.cc283
-rw-r--r--chromium/net/tools/domain_security_preload_generator/trie/trie_writer.h92
-rw-r--r--chromium/net/tools/dump_cache/dump_cache.cc1
-rw-r--r--chromium/net/tools/epoll_server/epoll_server.cc6
-rw-r--r--chromium/net/tools/epoll_server/epoll_server.h16
-rw-r--r--chromium/net/tools/quic/chlo_extractor.cc4
-rw-r--r--chromium/net/tools/quic/chlo_extractor.h2
-rw-r--r--chromium/net/tools/quic/chlo_extractor_test.cc2
-rw-r--r--chromium/net/tools/quic/crypto_message_printer_bin.cc4
-rw-r--r--chromium/net/tools/quic/end_to_end_test.cc618
-rw-r--r--chromium/net/tools/quic/platform/impl/quic_epoll_clock.cc (renamed from chromium/net/tools/quic/quic_epoll_clock.cc)2
-rw-r--r--chromium/net/tools/quic/platform/impl/quic_epoll_clock.h (renamed from chromium/net/tools/quic/quic_epoll_clock.h)9
-rw-r--r--chromium/net/tools/quic/platform/impl/quic_epoll_clock_test.cc (renamed from chromium/net/tools/quic/quic_epoll_clock_test.cc)2
-rw-r--r--chromium/net/tools/quic/platform/impl/quic_socket_utils.cc (renamed from chromium/net/tools/quic/quic_socket_utils.cc)86
-rw-r--r--chromium/net/tools/quic/platform/impl/quic_socket_utils.h (renamed from chromium/net/tools/quic/quic_socket_utils.h)23
-rw-r--r--chromium/net/tools/quic/platform/impl/quic_socket_utils_test.cc173
-rw-r--r--chromium/net/tools/quic/quic_client.cc61
-rw-r--r--chromium/net/tools/quic/quic_client.h22
-rw-r--r--chromium/net/tools/quic/quic_client_base.cc24
-rw-r--r--chromium/net/tools/quic/quic_client_base.h77
-rw-r--r--chromium/net/tools/quic/quic_client_bin.cc56
-rw-r--r--chromium/net/tools/quic/quic_client_session.cc29
-rw-r--r--chromium/net/tools/quic/quic_client_session.h5
-rw-r--r--chromium/net/tools/quic/quic_client_session_test.cc39
-rw-r--r--chromium/net/tools/quic/quic_client_test.cc62
-rw-r--r--chromium/net/tools/quic/quic_default_packet_writer.cc21
-rw-r--r--chromium/net/tools/quic/quic_default_packet_writer.h15
-rw-r--r--chromium/net/tools/quic/quic_dispatcher.cc112
-rw-r--r--chromium/net/tools/quic/quic_dispatcher.h46
-rw-r--r--chromium/net/tools/quic/quic_dispatcher_test.cc305
-rw-r--r--chromium/net/tools/quic/quic_epoll_alarm_factory.cc1
-rw-r--r--chromium/net/tools/quic/quic_epoll_alarm_factory.h6
-rw-r--r--chromium/net/tools/quic/quic_epoll_alarm_factory_test.cc2
-rw-r--r--chromium/net/tools/quic/quic_epoll_connection_helper.cc4
-rw-r--r--chromium/net/tools/quic/quic_epoll_connection_helper.h4
-rw-r--r--chromium/net/tools/quic/quic_epoll_connection_helper_test.cc2
-rw-r--r--chromium/net/tools/quic/quic_http_response_cache.cc (renamed from chromium/net/tools/quic/quic_in_memory_cache.cc)187
-rw-r--r--chromium/net/tools/quic/quic_http_response_cache.h (renamed from chromium/net/tools/quic/quic_in_memory_cache.h)49
-rw-r--r--chromium/net/tools/quic/quic_http_response_cache_test.cc (renamed from chromium/net/tools/quic/quic_in_memory_cache_test.cc)153
-rw-r--r--chromium/net/tools/quic/quic_packet_printer_bin.cc13
-rw-r--r--chromium/net/tools/quic/quic_packet_reader.cc31
-rw-r--r--chromium/net/tools/quic/quic_packet_reader.h15
-rw-r--r--chromium/net/tools/quic/quic_packet_writer_wrapper.cc13
-rw-r--r--chromium/net/tools/quic/quic_packet_writer_wrapper.h7
-rw-r--r--chromium/net/tools/quic/quic_per_connection_packet_writer.cc6
-rw-r--r--chromium/net/tools/quic/quic_per_connection_packet_writer.h9
-rw-r--r--chromium/net/tools/quic/quic_process_packet_interface.h8
-rw-r--r--chromium/net/tools/quic/quic_server.cc68
-rw-r--r--chromium/net/tools/quic/quic_server.h20
-rw-r--r--chromium/net/tools/quic/quic_server_bin.cc24
-rw-r--r--chromium/net/tools/quic/quic_server_test.cc45
-rw-r--r--chromium/net/tools/quic/quic_simple_client.cc47
-rw-r--r--chromium/net/tools/quic/quic_simple_client.h22
-rw-r--r--chromium/net/tools/quic/quic_simple_client_bin.cc74
-rw-r--r--chromium/net/tools/quic/quic_simple_client_test.cc4
-rw-r--r--chromium/net/tools/quic/quic_simple_crypto_server_stream_helper.cc2
-rw-r--r--chromium/net/tools/quic/quic_simple_crypto_server_stream_helper.h8
-rw-r--r--chromium/net/tools/quic/quic_simple_dispatcher.cc14
-rw-r--r--chromium/net/tools/quic/quic_simple_dispatcher.h11
-rw-r--r--chromium/net/tools/quic/quic_simple_per_connection_packet_writer.cc6
-rw-r--r--chromium/net/tools/quic/quic_simple_per_connection_packet_writer.h13
-rw-r--r--chromium/net/tools/quic/quic_simple_server.cc12
-rw-r--r--chromium/net/tools/quic/quic_simple_server.h21
-rw-r--r--chromium/net/tools/quic/quic_simple_server_bin.cc16
-rw-r--r--chromium/net/tools/quic/quic_simple_server_packet_writer.cc13
-rw-r--r--chromium/net/tools/quic/quic_simple_server_packet_writer.h21
-rw-r--r--chromium/net/tools/quic/quic_simple_server_session.cc46
-rw-r--r--chromium/net/tools/quic/quic_simple_server_session.h18
-rw-r--r--chromium/net/tools/quic/quic_simple_server_session_helper.cc2
-rw-r--r--chromium/net/tools/quic/quic_simple_server_session_helper.h2
-rw-r--r--chromium/net/tools/quic/quic_simple_server_session_test.cc240
-rw-r--r--chromium/net/tools/quic/quic_simple_server_stream.cc101
-rw-r--r--chromium/net/tools/quic/quic_simple_server_stream.h12
-rw-r--r--chromium/net/tools/quic/quic_simple_server_stream_test.cc153
-rw-r--r--chromium/net/tools/quic/quic_simple_server_test.cc16
-rw-r--r--chromium/net/tools/quic/quic_spdy_client_stream.cc43
-rw-r--r--chromium/net/tools/quic/quic_spdy_client_stream.h13
-rw-r--r--chromium/net/tools/quic/quic_spdy_client_stream_test.cc47
-rw-r--r--chromium/net/tools/quic/quic_spdy_server_stream_base.cc30
-rw-r--r--chromium/net/tools/quic/quic_spdy_server_stream_base.h26
-rw-r--r--chromium/net/tools/quic/quic_spdy_server_stream_base_test.cc65
-rw-r--r--chromium/net/tools/quic/quic_time_wait_list_manager.cc64
-rw-r--r--chromium/net/tools/quic/quic_time_wait_list_manager.h22
-rw-r--r--chromium/net/tools/quic/quic_time_wait_list_manager_test.cc48
-rw-r--r--chromium/net/tools/quic/stateless_rejector.cc32
-rw-r--r--chromium/net/tools/quic/stateless_rejector.h23
-rw-r--r--chromium/net/tools/quic/stateless_rejector_test.cc53
-rw-r--r--chromium/net/tools/quic/test_tools/limited_mtu_test_writer.cc11
-rw-r--r--chromium/net/tools/quic/test_tools/limited_mtu_test_writer.h6
-rw-r--r--chromium/net/tools/quic/test_tools/mock_quic_server_session_visitor.h6
-rw-r--r--chromium/net/tools/quic/test_tools/mock_quic_time_wait_list_manager.h8
-rw-r--r--chromium/net/tools/quic/test_tools/packet_dropping_test_writer.cc35
-rw-r--r--chromium/net/tools/quic/test_tools/packet_dropping_test_writer.h42
-rw-r--r--chromium/net/tools/quic/test_tools/packet_reordering_writer.cc11
-rw-r--r--chromium/net/tools/quic/test_tools/packet_reordering_writer.h8
-rw-r--r--chromium/net/tools/quic/test_tools/quic_client_peer.cc2
-rw-r--r--chromium/net/tools/quic/test_tools/quic_dispatcher_peer.cc4
-rw-r--r--chromium/net/tools/quic/test_tools/quic_dispatcher_peer.h4
-rw-r--r--chromium/net/tools/quic/test_tools/quic_in_memory_cache_peer.cc18
-rw-r--r--chromium/net/tools/quic/test_tools/quic_in_memory_cache_peer.h26
-rw-r--r--chromium/net/tools/quic/test_tools/quic_test_client.cc76
-rw-r--r--chromium/net/tools/quic/test_tools/quic_test_client.h69
-rw-r--r--chromium/net/tools/quic/test_tools/quic_test_server.cc66
-rw-r--r--chromium/net/tools/quic/test_tools/quic_test_server.h19
-rw-r--r--chromium/net/tools/quic/test_tools/server_thread.cc14
-rw-r--r--chromium/net/tools/quic/test_tools/server_thread.h15
-rw-r--r--chromium/net/tools/testserver/minica.py164
-rwxr-xr-xchromium/net/tools/testserver/testserver.py37
-rw-r--r--chromium/net/tools/testserver/testserver.pydeps3
-rw-r--r--chromium/net/url_request/http_user_agent_settings.h3
-rw-r--r--chromium/net/url_request/sdch_dictionary_fetcher.h1
-rw-r--r--chromium/net/url_request/static_http_user_agent_settings.cc1
-rw-r--r--chromium/net/url_request/static_http_user_agent_settings.h1
-rw-r--r--chromium/net/url_request/url_fetcher.h5
-rw-r--r--chromium/net/url_request/url_fetcher_core.cc42
-rw-r--r--chromium/net/url_request/url_fetcher_core.h11
-rw-r--r--chromium/net/url_request/url_fetcher_impl_unittest.cc29
-rw-r--r--chromium/net/url_request/url_fetcher_response_writer.h1
-rw-r--r--chromium/net/url_request/url_request.cc32
-rw-r--r--chromium/net/url_request/url_request.h4
-rw-r--r--chromium/net/url_request/url_request_context.cc38
-rw-r--r--chromium/net/url_request/url_request_context.h38
-rw-r--r--chromium/net/url_request/url_request_context_builder.h3
-rw-r--r--chromium/net/url_request/url_request_context_getter.h1
-rw-r--r--chromium/net/url_request/url_request_context_storage.h1
-rw-r--r--chromium/net/url_request/url_request_context_unittest.cc59
-rw-r--r--chromium/net/url_request/url_request_data_job_fuzzer.cc1
-rw-r--r--chromium/net/url_request/url_request_file_dir_job_unittest.cc1
-rw-r--r--chromium/net/url_request/url_request_file_job.cc28
-rw-r--r--chromium/net/url_request/url_request_file_job.h14
-rw-r--r--chromium/net/url_request/url_request_file_job_unittest.cc205
-rw-r--r--chromium/net/url_request/url_request_ftp_fuzzer.cc89
-rw-r--r--chromium/net/url_request/url_request_fuzzer.cc2
-rw-r--r--chromium/net/url_request/url_request_http_job.cc98
-rw-r--r--chromium/net/url_request/url_request_http_job.h1
-rw-r--r--chromium/net/url_request/url_request_http_job_unittest.cc91
-rw-r--r--chromium/net/url_request/url_request_intercepting_job_factory.cc17
-rw-r--r--chromium/net/url_request/url_request_intercepting_job_factory.h11
-rw-r--r--chromium/net/url_request/url_request_job.cc46
-rw-r--r--chromium/net/url_request/url_request_job.h19
-rw-r--r--chromium/net/url_request/url_request_job_manager.h8
-rw-r--r--chromium/net/url_request/url_request_netlog_params.cc12
-rw-r--r--chromium/net/url_request/url_request_netlog_params.h7
-rw-r--r--chromium/net/url_request/url_request_quic_unittest.cc12
-rw-r--r--chromium/net/url_request/url_request_test_job.cc89
-rw-r--r--chromium/net/url_request/url_request_test_job.h27
-rw-r--r--chromium/net/url_request/url_request_test_util.cc15
-rw-r--r--chromium/net/url_request/url_request_test_util.h1
-rw-r--r--chromium/net/url_request/url_request_throttler_entry.h1
-rw-r--r--chromium/net/url_request/url_request_throttler_entry_interface.h2
-rw-r--r--chromium/net/url_request/url_request_throttler_unittest.cc1
-rw-r--r--chromium/net/url_request/url_request_unittest.cc599
-rw-r--r--chromium/net/websockets/OWNERS3
-rw-r--r--chromium/net/websockets/websocket_deflate_stream.h2
-rw-r--r--chromium/net/websockets/websocket_deflate_stream_test.cc76
-rw-r--r--chromium/net/websockets/websocket_stream.cc5
-rw-r--r--chromium/net/websockets/websocket_stream_test.cc4
-rw-r--r--chromium/net/websockets/websocket_test_util.h12
1516 files changed, 106146 insertions, 54135 deletions
diff --git a/chromium/net/BUILD.gn b/chromium/net/BUILD.gn
index b1e0e9964dc..07ab2e39ee7 100644
--- a/chromium/net/BUILD.gn
+++ b/chromium/net/BUILD.gn
@@ -86,14 +86,26 @@ if (is_linux) {
net_configs += [ "//build/config/linux:libresolv" ]
}
+source_set("constants") {
+ sources = [
+ "base/trace_constants.cc",
+ "base/trace_constants.h",
+ ]
+ deps = [
+ "//base",
+ ]
+}
+
component("net") {
sources = gypi_values.net_nacl_common_sources
net_unfiltered_sources = []
deps = [
+ ":constants",
":net_resources",
"//base",
"//net/base/registry_controlled_domains",
+ "//net/data/ssl/wosign:wosign_domains",
"//third_party/protobuf:protobuf_lite",
"//url:url_features",
]
@@ -109,7 +121,6 @@ component("net") {
deps += [
"//base/third_party/dynamic_annotations",
- "//components/prefs",
"//sdch",
"//third_party/zlib",
]
@@ -140,9 +151,6 @@ component("net") {
if (!use_openssl_certs) {
sources -= [
"base/crypto_module_openssl.cc",
- "base/keygen_handler_openssl.cc",
- "base/openssl_private_key_store.h",
- "base/openssl_private_key_store_memory.cc",
"cert/cert_database_openssl.cc",
"cert/cert_verify_proc_openssl.cc",
"cert/cert_verify_proc_openssl.h",
@@ -151,14 +159,10 @@ component("net") {
"ssl/openssl_client_key_store.cc",
"ssl/openssl_client_key_store.h",
]
- if (is_android) {
- sources -= [ "base/openssl_private_key_store_android.cc" ]
- }
} else {
if (is_android) {
# Android doesn't use these even when using OpenSSL.
sources -= [
- "base/openssl_private_key_store_memory.cc",
"cert/cert_database_openssl.cc",
"cert/cert_verify_proc_openssl.cc",
"cert/test_root_certs_openssl.cc",
@@ -180,8 +184,9 @@ component("net") {
if (!use_nss_certs) {
sources -= [
"base/crypto_module_nss.cc",
- "base/keygen_handler_nss.cc",
"cert/cert_database_nss.cc",
+ "cert/internal/cert_issuer_source_nss.cc",
+ "cert/internal/cert_issuer_source_nss.h",
"cert/internal/trust_store_nss.cc",
"cert/internal/trust_store_nss.h",
"cert/nss_cert_database.cc",
@@ -189,8 +194,6 @@ component("net") {
"cert/x509_certificate_nss.cc",
"ssl/client_cert_store_nss.cc",
"ssl/client_cert_store_nss.h",
- "third_party/mozilla_security_manager/nsKeygenHandler.cpp",
- "third_party/mozilla_security_manager/nsKeygenHandler.h",
"third_party/mozilla_security_manager/nsNSSCertificateDB.cpp",
"third_party/mozilla_security_manager/nsNSSCertificateDB.h",
"third_party/mozilla_security_manager/nsPKCS12Blob.cpp",
@@ -685,6 +688,7 @@ if (use_v8_in_net) {
]
public_deps = [
+ ":constants",
":net",
]
deps = [
@@ -701,8 +705,6 @@ if (use_v8_in_net && !is_android) {
sources = [
"dns/mojo_host_resolver_impl.cc",
"dns/mojo_host_resolver_impl.h",
- "proxy/in_process_mojo_proxy_resolver_factory.cc",
- "proxy/in_process_mojo_proxy_resolver_factory.h",
"proxy/mojo_proxy_resolver_factory.h",
"proxy/proxy_resolver_factory_mojo.cc",
"proxy/proxy_resolver_factory_mojo.h",
@@ -715,12 +717,6 @@ if (use_v8_in_net && !is_android) {
"//base",
"//mojo/public/cpp/bindings",
"//net/interfaces",
-
- # NOTE(amistry): As long as we support in-process Mojo v8 PAC, we need
- # this dependency since in_process_mojo_proxy_resolver_factory creates
- # the utility process side Mojo services in the browser process.
- # Ultimately, this will go away when we only support out-of-process.
- ":net_utility_services",
]
}
@@ -1009,14 +1005,16 @@ if (is_linux) {
source_set("epoll_quic_tools") {
sources = [
+ "tools/quic/platform/impl/quic_epoll_clock.cc",
+ "tools/quic/platform/impl/quic_epoll_clock.h",
+ "tools/quic/platform/impl/quic_socket_utils.cc",
+ "tools/quic/platform/impl/quic_socket_utils.h",
"tools/quic/quic_client.cc",
"tools/quic/quic_client.h",
"tools/quic/quic_default_packet_writer.cc",
"tools/quic/quic_default_packet_writer.h",
"tools/quic/quic_epoll_alarm_factory.cc",
"tools/quic/quic_epoll_alarm_factory.h",
- "tools/quic/quic_epoll_clock.cc",
- "tools/quic/quic_epoll_clock.h",
"tools/quic/quic_epoll_connection_helper.cc",
"tools/quic/quic_epoll_connection_helper.h",
"tools/quic/quic_packet_reader.cc",
@@ -1025,8 +1023,6 @@ if (is_linux) {
"tools/quic/quic_packet_writer_wrapper.h",
"tools/quic/quic_server.cc",
"tools/quic/quic_server.h",
- "tools/quic/quic_socket_utils.cc",
- "tools/quic/quic_socket_utils.h",
]
deps = [
":epoll_server",
@@ -1091,6 +1087,7 @@ if (is_android) {
generate_jni("net_test_jni_headers") {
sources = [
"android/javatests/src/org/chromium/net/AndroidKeyStoreTestUtil.java",
+ "android/javatests/src/org/chromium/net/AndroidNetworkLibraryTestUtil.java",
"test/android/javatests/src/org/chromium/net/test/DummySpnegoAuthenticator.java",
"test/android/javatests/src/org/chromium/net/test/EmbeddedTestServerImpl.java",
]
@@ -1122,8 +1119,8 @@ source_set("simple_quic_tools") {
"tools/quic/quic_client_session.h",
"tools/quic/quic_dispatcher.cc",
"tools/quic/quic_dispatcher.h",
- "tools/quic/quic_in_memory_cache.cc",
- "tools/quic/quic_in_memory_cache.h",
+ "tools/quic/quic_http_response_cache.cc",
+ "tools/quic/quic_http_response_cache.h",
"tools/quic/quic_per_connection_packet_writer.cc",
"tools/quic/quic_per_connection_packet_writer.h",
"tools/quic/quic_process_packet_interface.h",
@@ -1147,6 +1144,8 @@ source_set("simple_quic_tools") {
"tools/quic/quic_simple_server_stream.h",
"tools/quic/quic_spdy_client_stream.cc",
"tools/quic/quic_spdy_client_stream.h",
+ "tools/quic/quic_spdy_server_stream_base.cc",
+ "tools/quic/quic_spdy_server_stream_base.h",
"tools/quic/quic_time_wait_list_manager.cc",
"tools/quic/quic_time_wait_list_manager.h",
"tools/quic/stateless_rejector.cc",
@@ -1252,6 +1251,7 @@ test("net_unittests") {
defines = []
deps = [
+ ":cert_verify_proc_whitelist_unittest_data",
":extras",
":net",
":simple_quic_tools",
@@ -1325,9 +1325,11 @@ test("net_unittests") {
if (!use_nss_certs) {
sources -= [
+ "cert/internal/cert_issuer_source_nss_unittest.cc",
"cert/internal/trust_store_nss_unittest.cc",
"cert/nss_cert_database_unittest.cc",
"ssl/client_cert_store_nss_unittest.cc",
+ "ssl/ssl_platform_key_nss_unittest.cc",
]
if (is_chromeos) { # Already removed for all non-ChromeOS builds.
sources -= [
@@ -1438,8 +1440,6 @@ test("net_unittests") {
sources -= [
# TODO(droger): The following tests are disabled because the
# implementation is missing or incomplete.
- # KeygenHandler::GenKeyAndSignChallenge() is not ported to iOS.
- "base/keygen_handler_unittest.cc",
"disk_cache/backend_unittest.cc",
"disk_cache/blockfile/block_files_unittest.cc",
@@ -1539,6 +1539,11 @@ test("net_unittests") {
if (is_win) {
libs = [ "iphlpapi.lib" ]
}
+
+ if (is_chromecast && use_nss_certs) {
+ sources += [ "ssl/ssl_platform_key_chromecast_unittest.cc" ]
+ sources -= [ "ssl/ssl_platform_key_nss_unittest.cc" ]
+ }
}
# !is_android && !is_win && !is_mac
@@ -1580,9 +1585,31 @@ if (!is_ios) {
} else {
sources -= [ "proxy/proxy_resolver_perftest.cc" ]
}
+
+ # Some linker failures have been observed for this target on the Win64
+ # continuous builder, see crbug.com/659369.
+ # TODO(sebmarchand): Remove this once we have some data.
+ if (is_win && linkrepro_root_dir != "") {
+ ldflags = [ "/LINKREPRO:" + linkrepro_root_dir + "/" + target_name ]
+ }
}
}
+action_foreach("cert_verify_proc_whitelist_unittest_data") {
+ script = "//net/tools/dafsa/make_dafsa.py"
+ sources = [
+ "//net/cert/cert_verify_proc_whitelist_unittest1.gperf",
+ ]
+ outputs = [
+ "${target_gen_dir}/cert/{{source_name_part}}-inc.cc",
+ ]
+ args = [
+ "{{source}}",
+ rebase_path("${target_gen_dir}/cert/{{source_name_part}}-inc.cc",
+ root_build_dir),
+ ]
+}
+
# Fuzzers
# This has a global (InitGlobals) that must always be linked in, so
@@ -1592,6 +1619,8 @@ source_set("net_fuzzer_test_support") {
sources = [
"base/fuzzer_test_support.cc",
+ "dns/fuzzed_host_resolver.cc",
+ "dns/fuzzed_host_resolver.h",
"filter/fuzzed_source_stream.cc",
"filter/fuzzed_source_stream.h",
"socket/fuzzed_datagram_client_socket.cc",
@@ -1788,8 +1817,6 @@ fuzzer_test("net_dns_hosts_parse_fuzzer") {
fuzzer_test("net_host_resolver_impl_fuzzer") {
sources = [
- "dns/fuzzed_host_resolver.cc",
- "dns/fuzzed_host_resolver.h",
"dns/host_resolver_impl_fuzzer.cc",
]
deps = [
@@ -1982,6 +2009,20 @@ fuzzer_test("net_socks5_client_socket_fuzzer") {
]
}
+fuzzer_test("net_url_request_ftp_fuzzer") {
+ sources = [
+ "url_request/url_request_ftp_fuzzer.cc",
+ ]
+ deps = [
+ ":net_fuzzer_test_support",
+ ":test_support",
+ "//base",
+ "//net",
+ ]
+ dict = "data/fuzzer_dictionaries/net_url_request_ftp_fuzzer.dict"
+ seed_corpus = "data/fuzzer_data/net_url_request_ftp_fuzzer/"
+}
+
fuzzer_test("net_url_request_fuzzer") {
sources = [
"url_request/url_request_fuzzer.cc",
@@ -2043,3 +2084,26 @@ fuzzer_test("net_http_security_headers_hpkp_report_only_fuzzer") {
]
dict = "data/fuzzer_dictionaries/net_http_security_headers_fuzzer.dict"
}
+
+fuzzer_test("net_http_transport_security_state_static_fuzzer") {
+ sources = [
+ "http/transport_security_state_static_fuzzer.cc",
+ ]
+ deps = [
+ ":net_fuzzer_test_support",
+ "//net",
+ ]
+ dict =
+ "data/fuzzer_dictionaries/net_http_transport_security_state_fuzzer.dict"
+}
+
+if (host_toolchain == current_toolchain) {
+ executable("domain_security_preload_generator") {
+ sources = gypi_values.net_domain_security_state_generator_sources
+ deps = [
+ "//base",
+ "//crypto",
+ "//third_party/boringssl",
+ ]
+ }
+}
diff --git a/chromium/net/android/BUILD.gn b/chromium/net/android/BUILD.gn
index 74142bd4723..1cf3789edbb 100644
--- a/chromium/net/android/BUILD.gn
+++ b/chromium/net/android/BUILD.gn
@@ -94,6 +94,9 @@ shared_library("net_java_test_native_support") {
android_apk("net_test_support_apk") {
testonly = true
+
+ # Used as an additional_apk in test scripts.
+ never_incremental = true
deps = [
":net_java_test_support",
"//base:base_java",
@@ -112,6 +115,7 @@ android_library("net_javatests") {
testonly = true
java_files = [
"javatests/src/org/chromium/net/AndroidKeyStoreTestUtil.java",
+ "javatests/src/org/chromium/net/AndroidNetworkLibraryTestUtil.java",
"javatests/src/org/chromium/net/AndroidProxySelectorTest.java",
"javatests/src/org/chromium/net/NetErrorsTest.java",
"javatests/src/org/chromium/net/NetworkChangeNotifierTest.java",
@@ -122,6 +126,7 @@ android_library("net_javatests") {
":net_java_test_support",
"//base:base_java",
"//base:base_java_test_support",
+ "//third_party/android_support_test_runner:runner_java",
]
}
diff --git a/chromium/net/android/cellular_signal_strength_unittest.cc b/chromium/net/android/cellular_signal_strength_unittest.cc
index 50510b7f631..c6f879723e5 100644
--- a/chromium/net/android/cellular_signal_strength_unittest.cc
+++ b/chromium/net/android/cellular_signal_strength_unittest.cc
@@ -52,4 +52,4 @@ TEST(CellularSignalStrengthAndroidTest, SignalStrengthLevelTest) {
} // namespace
-} // namespace net \ No newline at end of file
+} // namespace net
diff --git a/chromium/net/android/dummy_spnego_authenticator.h b/chromium/net/android/dummy_spnego_authenticator.h
index 2abca104025..a0ce00b2ee3 100644
--- a/chromium/net/android/dummy_spnego_authenticator.h
+++ b/chromium/net/android/dummy_spnego_authenticator.h
@@ -25,8 +25,6 @@ namespace net {
#define GSS_S_CONTINUE_NEEDED 1
#define GSS_S_FAILURE 2
-class gss_buffer_desc;
-
typedef struct gss_OID_desc_struct {
uint32_t length;
void* elements;
@@ -143,4 +141,4 @@ class DummySpnegoAuthenticator {
} // namespace android
} // namespace net
-#endif // NET_ANDROID_DUMMY_SPNEGO_AUTHENTICATOR_DRIVER_H
+#endif // NET_ANDROID_DUMMY_SPNEGO_AUTHENTICATOR_H_
diff --git a/chromium/net/android/keystore.h b/chromium/net/android/keystore.h
index 0fca8e6c3cc..fe2de2bab4f 100644
--- a/chromium/net/android/keystore.h
+++ b/chromium/net/android/keystore.h
@@ -2,8 +2,8 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#ifndef NET_ANDROID_KEYSTORE_H
-#define NET_ANDROID_KEYSTORE_H
+#ifndef NET_ANDROID_KEYSTORE_H_
+#define NET_ANDROID_KEYSTORE_H_
#include <jni.h>
#include <stdint.h>
@@ -77,4 +77,4 @@ base::android::ScopedJavaLocalRef<jobject> GetOpenSSLEngineForPrivateKey(
} // namespace android
} // namespace net
-#endif // NET_ANDROID_KEYSTORE_H
+#endif // NET_ANDROID_KEYSTORE_H_
diff --git a/chromium/net/android/legacy_openssl.h b/chromium/net/android/legacy_openssl.h
index 75c77b8a06f..434dc180805 100644
--- a/chromium/net/android/legacy_openssl.h
+++ b/chromium/net/android/legacy_openssl.h
@@ -2,8 +2,8 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#ifndef NET_ANDROID_LEGACY_OPENSSL_H
-#define NET_ANDROID_LEGACY_OPENSSL_H
+#ifndef NET_ANDROID_LEGACY_OPENSSL_H_
+#define NET_ANDROID_LEGACY_OPENSSL_H_
// This file contains a replica of the Android system OpenSSL ABI shipped in
// Android 4.1.x (API level 16). The ABI may not necessarily be compatible with
@@ -94,4 +94,4 @@ struct AndroidEVP_PKEY {
} // namespace android
} // namespace net
-#endif // NET_ANDROID_LEGACY_OPENSSL_H
+#endif // NET_ANDROID_LEGACY_OPENSSL_H_
diff --git a/chromium/net/android/network_change_notifier_delegate_android.h b/chromium/net/android/network_change_notifier_delegate_android.h
index e80ebe90d1d..4329d6384f8 100644
--- a/chromium/net/android/network_change_notifier_delegate_android.h
+++ b/chromium/net/android/network_change_notifier_delegate_android.h
@@ -5,6 +5,7 @@
#ifndef NET_ANDROID_NETWORK_CHANGE_NOTIFIER_DELEGATE_ANDROID_H_
#define NET_ANDROID_NETWORK_CHANGE_NOTIFIER_DELEGATE_ANDROID_H_
+#include <map>
#include <string>
#include "base/android/jni_android.h"
diff --git a/chromium/net/android/network_change_notifier_factory_android.h b/chromium/net/android/network_change_notifier_factory_android.h
index ab4d169866a..17eb11bc525 100644
--- a/chromium/net/android/network_change_notifier_factory_android.h
+++ b/chromium/net/android/network_change_notifier_factory_android.h
@@ -40,4 +40,4 @@ class NET_EXPORT NetworkChangeNotifierFactoryAndroid :
} // namespace net
-#endif // NET_ANDROID_NETWORK_CHANGE_NOTIFIER_FACTORY_H_
+#endif // NET_ANDROID_NETWORK_CHANGE_NOTIFIER_FACTORY_ANDROID_H_
diff --git a/chromium/net/android/network_library.cc b/chromium/net/android/network_library.cc
index 939319cd0b2..75359526281 100644
--- a/chromium/net/android/network_library.cc
+++ b/chromium/net/android/network_library.cc
@@ -11,6 +11,7 @@
#include "base/android/scoped_java_ref.h"
#include "base/logging.h"
#include "jni/AndroidNetworkLibrary_jni.h"
+#include "net/dns/dns_protocol.h"
using base::android::AttachCurrentThread;
using base::android::ConvertJavaStringToUTF8;
@@ -79,6 +80,12 @@ bool StoreKeyPair(const uint8_t* public_key,
return ret;
}
+bool IsCleartextPermitted(const std::string& host) {
+ JNIEnv* env = AttachCurrentThread();
+ ScopedJavaLocalRef<jstring> host_string = ConvertUTF8ToJavaString(env, host);
+ return Java_AndroidNetworkLibrary_isCleartextPermitted(env, host_string);
+}
+
bool HaveOnlyLoopbackAddresses() {
JNIEnv* env = AttachCurrentThread();
return Java_AndroidNetworkLibrary_haveOnlyLoopbackAddresses(env);
@@ -127,6 +134,12 @@ bool GetIsRoaming() {
base::android::GetApplicationContext());
}
+bool GetIsCaptivePortal() {
+ return Java_AndroidNetworkLibrary_getIsCaptivePortal(
+ base::android::AttachCurrentThread(),
+ base::android::GetApplicationContext());
+}
+
std::string GetWifiSSID() {
return base::android::ConvertJavaStringToUTF8(
Java_AndroidNetworkLibrary_getWifiSSID(
@@ -134,5 +147,22 @@ std::string GetWifiSSID() {
base::android::GetApplicationContext()));
}
+void GetDnsServers(std::vector<IPEndPoint>* dns_servers) {
+ JNIEnv* env = AttachCurrentThread();
+ std::vector<std::string> dns_servers_strings;
+ base::android::JavaArrayOfByteArrayToStringVector(
+ env, Java_AndroidNetworkLibrary_getDnsServers(
+ env, base::android::GetApplicationContext())
+ .obj(),
+ &dns_servers_strings);
+ for (const std::string& dns_address_string : dns_servers_strings) {
+ IPAddress dns_address(
+ reinterpret_cast<const uint8_t*>(dns_address_string.c_str()),
+ dns_address_string.size());
+ IPEndPoint dns_server(dns_address, dns_protocol::kDefaultPort);
+ dns_servers->push_back(dns_server);
+ }
+}
+
} // namespace android
} // namespace net
diff --git a/chromium/net/android/network_library.h b/chromium/net/android/network_library.h
index 24610bb50d2..b72cb259279 100644
--- a/chromium/net/android/network_library.h
+++ b/chromium/net/android/network_library.h
@@ -13,6 +13,7 @@
#include <vector>
#include "net/android/cert_verify_result_android.h"
+#include "net/base/ip_endpoint.h"
#include "net/base/mime_util.h"
#include "net/base/net_export.h"
@@ -36,14 +37,9 @@ void AddTestRootCertificate(const uint8_t* cert, size_t len);
// Removes all root certificates added by |AddTestRootCertificate| calls.
void ClearTestRootCertificates();
-// Helper for the <keygen> handler. Passes the DER-encoded key pair via JNI to
-// the Credentials store. The public key should be a DER-encoded
-// SubjectPublicKeyInfo (X.509) and the private key a DER-encode PrivateKeyInfo
-// (PKCS#8).
-bool StoreKeyPair(const uint8_t* public_key,
- size_t public_len,
- const uint8_t* private_key,
- size_t private_len);
+// Returns true if cleartext traffic to |host| is allowed by the app. Always
+// true on L and older.
+bool IsCleartextPermitted(const std::string& host);
// Returns true if it can determine that only loopback addresses are configured.
// i.e. if only 127.0.0.1 and ::1 are routable.
@@ -71,10 +67,22 @@ NET_EXPORT std::string GetTelephonySimOperator();
// true, it suggests that use of data may incur extra costs.
NET_EXPORT bool GetIsRoaming();
+// Returns true if the system's captive portal probe was blocked for the current
+// default data network. The method will return false if the captive portal
+// probe was not blocked, the login process to the captive portal has been
+// successfully completed, or if the captive portal status can't be determined.
+// Requires ACCESS_NETWORK_STATE permission. Only available on Android
+// Marshmallow and later versions. Returns false on earlier versions.
+NET_EXPORT bool GetIsCaptivePortal();
+
// Gets the SSID of the currently associated WiFi access point if there is one.
// Otherwise, returns empty string.
NET_EXPORT_PRIVATE std::string GetWifiSSID();
+// Gets the DNS servers and puts them in |dns_servers|.
+// Only callable on Marshmallow and newer releases.
+NET_EXPORT_PRIVATE void GetDnsServers(std::vector<IPEndPoint>* dns_servers);
+
} // namespace android
} // namespace net
diff --git a/chromium/net/android/network_library_unittest.cc b/chromium/net/android/network_library_unittest.cc
new file mode 100644
index 00000000000..b6cb8753ebc
--- /dev/null
+++ b/chromium/net/android/network_library_unittest.cc
@@ -0,0 +1,19 @@
+// Copyright 2016 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.
+
+#include "net/android/network_library.h"
+
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace net {
+
+namespace android {
+
+TEST(NetworkLibraryTest, CaptivePortal) {
+ EXPECT_FALSE(android::GetIsCaptivePortal());
+}
+
+} // namespace android
+
+} // namespace net
diff --git a/chromium/net/android/unittest_support/AndroidManifest.xml b/chromium/net/android/unittest_support/AndroidManifest.xml
index 69a29e08f5a..a6ee79bb29d 100644
--- a/chromium/net/android/unittest_support/AndroidManifest.xml
+++ b/chromium/net/android/unittest_support/AndroidManifest.xml
@@ -12,6 +12,7 @@ found in the LICENSE file.
<uses-sdk android:minSdkVersion="16" android:targetSdkVersion="23" />
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION"/>
+ <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>
<uses-permission android:name="android.permission.AUTHENTICATE_ACCOUNTS"/>
<uses-permission android:name="android.permission.BLUETOOTH"/>
<uses-permission android:name="android.permission.BLUETOOTH_ADMIN"/>
diff --git a/chromium/net/base/arena.cc b/chromium/net/base/arena.cc
index eeb286337be..3bf29a79fca 100644
--- a/chromium/net/base/arena.cc
+++ b/chromium/net/base/arena.cc
@@ -68,6 +68,7 @@ void UnsafeArena::Free(char* data, size_t size) {
void UnsafeArena::Reset() {
blocks_.clear();
+ status_.bytes_allocated_ = 0;
}
void UnsafeArena::Reserve(size_t additional_space) {
@@ -83,6 +84,7 @@ void UnsafeArena::Reserve(size_t additional_space) {
void UnsafeArena::AllocBlock(size_t size) {
blocks_.push_back(Block(size));
+ status_.bytes_allocated_ += size;
}
UnsafeArena::Block::Block(size_t s) : data(new char[s]), size(s), used(0) {}
diff --git a/chromium/net/base/arena.h b/chromium/net/base/arena.h
index 223517df5e2..f9a31acd96d 100644
--- a/chromium/net/base/arena.h
+++ b/chromium/net/base/arena.h
@@ -16,6 +16,16 @@ namespace net {
// Not thread-safe.
class NET_EXPORT_PRIVATE UnsafeArena {
public:
+ class Status {
+ private:
+ friend class UnsafeArena;
+ size_t bytes_allocated_;
+
+ public:
+ Status() : bytes_allocated_(0) {}
+ size_t bytes_allocated() const { return bytes_allocated_; }
+ };
+
// Blocks allocated by this arena will be at least |block_size| bytes.
explicit UnsafeArena(size_t block_size);
~UnsafeArena();
@@ -39,6 +49,8 @@ class NET_EXPORT_PRIVATE UnsafeArena {
void Reset();
+ Status status() const { return status_; }
+
private:
struct Block {
std::unique_ptr<char[]> data;
@@ -57,6 +69,7 @@ class NET_EXPORT_PRIVATE UnsafeArena {
size_t block_size_;
std::vector<Block> blocks_;
+ Status status_;
};
} // namespace net
diff --git a/chromium/net/base/escape.cc b/chromium/net/base/escape.cc
index 9f22778f0a5..65a23c1c395 100644
--- a/chromium/net/base/escape.cc
+++ b/chromium/net/base/escape.cc
@@ -4,13 +4,8 @@
#include "net/base/escape.h"
-#include <algorithm>
-#include <memory>
-
#include "base/logging.h"
-#include "base/strings/string_piece.h"
#include "base/strings/string_util.h"
-#include "base/strings/utf_offset_string_conversions.h"
#include "base/strings/utf_string_conversions.h"
namespace net {
@@ -41,7 +36,7 @@ struct Charmap {
// to +, otherwise, if spaces are in the charmap, they are converted to
// %20. And if keep_escaped is true, %XX will be kept as it is, otherwise, if
// '%' is in the charmap, it is converted to %25.
-std::string Escape(const std::string& text,
+std::string Escape(base::StringPiece text,
const Charmap& charmap,
bool use_plus,
bool keep_escaped = false) {
@@ -106,8 +101,8 @@ const char kUrlUnescape[128] = {
// Attempts to unescape the sequence at |index| within |escaped_text|. If
// successful, sets |value| to the unescaped value. Returns whether
// unescaping succeeded.
-template<typename STR>
-bool UnescapeUnsignedCharAtIndex(const STR& escaped_text,
+template <typename STR>
+bool UnescapeUnsignedCharAtIndex(STR escaped_text,
size_t index,
unsigned char* value) {
if ((index + 2) >= escaped_text.size())
@@ -128,8 +123,8 @@ bool UnescapeUnsignedCharAtIndex(const STR& escaped_text,
// Returns true if there is an Arabic Language Mark at |index|. |first_byte|
// is the byte at |index|.
-template<typename STR>
-bool HasArabicLanguageMarkAtIndex(const STR& escaped_text,
+template <typename STR>
+bool HasArabicLanguageMarkAtIndex(STR escaped_text,
unsigned char first_byte,
size_t index) {
if (first_byte != 0xD8)
@@ -142,8 +137,8 @@ bool HasArabicLanguageMarkAtIndex(const STR& escaped_text,
// Returns true if there is a BiDi control char at |index|. |first_byte| is the
// byte at |index|.
-template<typename STR>
-bool HasThreeByteBidiControlCharAtIndex(const STR& escaped_text,
+template <typename STR>
+bool HasThreeByteBidiControlCharAtIndex(STR escaped_text,
unsigned char first_byte,
size_t index) {
if (first_byte != 0xE2)
@@ -167,7 +162,7 @@ bool HasThreeByteBidiControlCharAtIndex(const STR& escaped_text,
// Returns true if there is a four-byte banned char at |index|. |first_byte| is
// the byte at |index|.
template <typename STR>
-bool HasFourByteBannedCharAtIndex(const STR& escaped_text,
+bool HasFourByteBannedCharAtIndex(STR escaped_text,
unsigned char first_byte,
size_t index) {
// The following characters are blacklisted for spoofability concerns.
@@ -201,16 +196,16 @@ bool HasFourByteBannedCharAtIndex(const STR& escaped_text,
// the alterations done to the string that are not one-character-to-one-
// character. The resulting |adjustments| will always be sorted by increasing
// offset.
-template<typename STR>
+template <typename STR>
STR UnescapeURLWithAdjustmentsImpl(
- const STR& escaped_text,
+ base::BasicStringPiece<STR> escaped_text,
UnescapeRule::Type rules,
base::OffsetAdjuster::Adjustments* adjustments) {
if (adjustments)
adjustments->clear();
// Do not unescape anything, return the |escaped_text| text.
if (rules == UnescapeRule::NONE)
- return escaped_text;
+ return escaped_text.as_string();
// The output of the unescaping is always smaller than the input, so we can
// reserve the input size to make sure we have enough buffer and don't have
@@ -265,19 +260,19 @@ STR UnescapeURLWithAdjustmentsImpl(
if (!(rules & UnescapeRule::SPOOFING_AND_CONTROL_CHARS)) {
if (HasArabicLanguageMarkAtIndex(escaped_text, first_byte, i)) {
// Keep Arabic Language Mark escaped.
- result.append(escaped_text, i, 6);
+ escaped_text.substr(i, 6).AppendToString(&result);
i += 5;
continue;
}
if (HasThreeByteBidiControlCharAtIndex(escaped_text, first_byte, i)) {
// Keep BiDi control char escaped.
- result.append(escaped_text, i, 9);
+ escaped_text.substr(i, 9).AppendToString(&result);
i += 8;
continue;
}
if (HasFourByteBannedCharAtIndex(escaped_text, first_byte, i)) {
// Keep banned char escaped.
- result.append(escaped_text, i, 12);
+ escaped_text.substr(i, 12).AppendToString(&result);
i += 11;
continue;
}
@@ -345,12 +340,13 @@ void AppendEscapedCharForHTMLImpl(typename str::value_type c, str* output) {
}
template <class str>
-str EscapeForHTMLImpl(const str& input) {
+str EscapeForHTMLImpl(base::BasicStringPiece<str> input) {
str result;
result.reserve(input.size()); // Optimize for no escaping.
- for (typename str::const_iterator i = input.begin(); i != input.end(); ++i)
- AppendEscapedCharForHTMLImpl(*i, &result);
+ for (auto c : input) {
+ AppendEscapedCharForHTMLImpl(c, &result);
+ }
return result;
}
@@ -397,29 +393,29 @@ static const Charmap kExternalHandlerCharmap = {{
} // namespace
-std::string EscapeQueryParamValue(const std::string& text, bool use_plus) {
+std::string EscapeQueryParamValue(base::StringPiece text, bool use_plus) {
return Escape(text, kQueryCharmap, use_plus);
}
-std::string EscapePath(const std::string& path) {
+std::string EscapePath(base::StringPiece path) {
return Escape(path, kPathCharmap, false);
}
#if defined(OS_MACOSX)
-std::string EscapeNSURLPrecursor(const std::string& precursor) {
+std::string EscapeNSURLPrecursor(base::StringPiece precursor) {
return Escape(precursor, kNSURLCharmap, false, true);
}
#endif // defined(OS_MACOSX)
-std::string EscapeUrlEncodedData(const std::string& path, bool use_plus) {
+std::string EscapeUrlEncodedData(base::StringPiece path, bool use_plus) {
return Escape(path, kUrlEscape, use_plus);
}
-std::string EscapeNonASCII(const std::string& input) {
+std::string EscapeNonASCII(base::StringPiece input) {
return Escape(input, kNonASCIICharmap, false);
}
-std::string EscapeExternalHandlerValue(const std::string& text) {
+std::string EscapeExternalHandlerValue(base::StringPiece text) {
return Escape(text, kExternalHandlerCharmap, false, true);
}
@@ -427,31 +423,31 @@ void AppendEscapedCharForHTML(char c, std::string* output) {
AppendEscapedCharForHTMLImpl(c, output);
}
-std::string EscapeForHTML(const std::string& input) {
+std::string EscapeForHTML(base::StringPiece input) {
return EscapeForHTMLImpl(input);
}
-base::string16 EscapeForHTML(const base::string16& input) {
+base::string16 EscapeForHTML(base::StringPiece16 input) {
return EscapeForHTMLImpl(input);
}
-std::string UnescapeURLComponent(const std::string& escaped_text,
+std::string UnescapeURLComponent(base::StringPiece escaped_text,
UnescapeRule::Type rules) {
return UnescapeURLWithAdjustmentsImpl(escaped_text, rules, NULL);
}
-base::string16 UnescapeURLComponent(const base::string16& escaped_text,
+base::string16 UnescapeURLComponent(base::StringPiece16 escaped_text,
UnescapeRule::Type rules) {
return UnescapeURLWithAdjustmentsImpl(escaped_text, rules, NULL);
}
-base::string16 UnescapeAndDecodeUTF8URLComponent(const std::string& text,
+base::string16 UnescapeAndDecodeUTF8URLComponent(base::StringPiece text,
UnescapeRule::Type rules) {
return UnescapeAndDecodeUTF8URLComponentWithAdjustments(text, rules, NULL);
}
base::string16 UnescapeAndDecodeUTF8URLComponentWithAdjustments(
- const std::string& text,
+ base::StringPiece text,
UnescapeRule::Type rules,
base::OffsetAdjuster::Adjustments* adjustments) {
base::string16 result;
@@ -472,7 +468,7 @@ base::string16 UnescapeAndDecodeUTF8URLComponentWithAdjustments(
return base::UTF8ToUTF16WithAdjustments(text, adjustments);
}
-base::string16 UnescapeForHTML(const base::string16& input) {
+base::string16 UnescapeForHTML(base::StringPiece16 input) {
static const struct {
const char* ampersand_code;
const char replacement;
@@ -485,10 +481,10 @@ base::string16 UnescapeForHTML(const base::string16& input) {
};
if (input.find(base::ASCIIToUTF16("&")) == std::string::npos)
- return input;
+ return input.as_string();
base::string16 ampersand_chars[arraysize(kEscapeToChars)];
- base::string16 text(input);
+ base::string16 text = input.as_string();
for (base::string16::iterator iter = text.begin();
iter != text.end(); ++iter) {
if (*iter == '&') {
diff --git a/chromium/net/base/escape.h b/chromium/net/base/escape.h
index 8637a70a5e7..cb013922dc3 100644
--- a/chromium/net/base/escape.h
+++ b/chromium/net/base/escape.h
@@ -8,9 +8,9 @@
#include <stdint.h>
#include <string>
-#include <vector>
#include "base/strings/string16.h"
+#include "base/strings/string_piece.h"
#include "base/strings/utf_offset_string_conversions.h"
#include "net/base/net_export.h"
@@ -22,44 +22,44 @@ namespace net {
// We %XX everything except alphanumerics and -_.!~*'()
// Spaces change to "+" unless you pass usePlus=false.
// This is basically the same as encodeURIComponent in javascript.
-NET_EXPORT std::string EscapeQueryParamValue(const std::string& text,
+NET_EXPORT std::string EscapeQueryParamValue(base::StringPiece text,
bool use_plus);
// Escapes a partial or complete file/pathname. This includes:
// non-printable, non-7bit, and (including space) "#%:<>?[\]^`{|}
// For the base::string16 version, we attempt a conversion to |codepage| before
// encoding the string. If this conversion fails, we return false.
-NET_EXPORT std::string EscapePath(const std::string& path);
+NET_EXPORT std::string EscapePath(base::StringPiece path);
#if defined(OS_MACOSX)
// Escapes characters as per expectations of NSURL. This includes:
// non-printable, non-7bit, and (including space) "#%<>[\]^`{|}
-NET_EXPORT std::string EscapeNSURLPrecursor(const std::string& precursor);
+NET_EXPORT std::string EscapeNSURLPrecursor(base::StringPiece precursor);
#endif // defined(OS_MACOSX)
// Escapes application/x-www-form-urlencoded content. This includes:
// non-printable, non-7bit, and (including space) ?>=<;+'&%$#"![\]^`{|}
// Space is escaped as + (if use_plus is true) and other special characters
// as %XX (hex).
-NET_EXPORT std::string EscapeUrlEncodedData(const std::string& path,
+NET_EXPORT std::string EscapeUrlEncodedData(base::StringPiece path,
bool use_plus);
// Escapes all non-ASCII input.
-NET_EXPORT std::string EscapeNonASCII(const std::string& input);
+NET_EXPORT std::string EscapeNonASCII(base::StringPiece input);
// Escapes characters in text suitable for use as an external protocol handler
// command.
// We %XX everything except alphanumerics and -_.!~*'() and the restricted
// chracters (;/?:@&=+$,#[]) and a valid percent escape sequence (%XX).
-NET_EXPORT std::string EscapeExternalHandlerValue(const std::string& text);
+NET_EXPORT std::string EscapeExternalHandlerValue(base::StringPiece text);
// Appends the given character to the output string, escaping the character if
// the character would be interpretted as an HTML delimiter.
NET_EXPORT void AppendEscapedCharForHTML(char c, std::string* output);
// Escapes chars that might cause this text to be interpretted as HTML tags.
-NET_EXPORT std::string EscapeForHTML(const std::string& text);
-NET_EXPORT base::string16 EscapeForHTML(const base::string16& text);
+NET_EXPORT std::string EscapeForHTML(base::StringPiece text);
+NET_EXPORT base::string16 EscapeForHTML(base::StringPiece16 text);
// Unescaping ------------------------------------------------------------------
@@ -125,11 +125,10 @@ class UnescapeRule {
// which, after unescaping, is supposed to be interpreted as UTF-8, and then
// converted into full UTF-16 chars. This function won't tell you if any
// conversions need to take place, it only unescapes.
-NET_EXPORT std::string UnescapeURLComponent(const std::string& escaped_text,
+NET_EXPORT std::string UnescapeURLComponent(base::StringPiece escaped_text,
UnescapeRule::Type rules);
-NET_EXPORT base::string16 UnescapeURLComponent(
- const base::string16& escaped_text,
- UnescapeRule::Type rules);
+NET_EXPORT base::string16 UnescapeURLComponent(base::StringPiece16 escaped_text,
+ UnescapeRule::Type rules);
// Unescapes the given substring as a URL, and then tries to interpret the
// result as being encoded as UTF-8. If the result is convertable into UTF-8, it
@@ -138,16 +137,16 @@ NET_EXPORT base::string16 UnescapeURLComponent(
// information on how the original string was adjusted to get the string
// returned.
NET_EXPORT base::string16 UnescapeAndDecodeUTF8URLComponent(
- const std::string& text,
+ base::StringPiece text,
UnescapeRule::Type rules);
NET_EXPORT base::string16 UnescapeAndDecodeUTF8URLComponentWithAdjustments(
- const std::string& text,
+ base::StringPiece text,
UnescapeRule::Type rules,
base::OffsetAdjuster::Adjustments* adjustments);
// Unescapes the following ampersand character codes from |text|:
// &lt; &gt; &amp; &quot; &#39;
-NET_EXPORT base::string16 UnescapeForHTML(const base::string16& text);
+NET_EXPORT base::string16 UnescapeForHTML(base::StringPiece16 text);
} // namespace net
diff --git a/chromium/net/base/int128.h b/chromium/net/base/int128.h
index b9be53dc58a..c2fc51ba48f 100644
--- a/chromium/net/base/int128.h
+++ b/chromium/net/base/int128.h
@@ -66,6 +66,10 @@ class uint128 {
uint128(double v);
};
+inline uint128 MakeUint128(uint64_t top, uint64_t bottom) {
+ return uint128(top, bottom);
+}
+
// This is a POD form of uint128 which can be used for static variables which
// need to be operated on as uint128.
struct uint128_pod {
diff --git a/chromium/net/base/int128_unittest.cc b/chromium/net/base/int128_unittest.cc
index 2d740d375d7..9a9028978ab 100644
--- a/chromium/net/base/int128_unittest.cc
+++ b/chromium/net/base/int128_unittest.cc
@@ -10,9 +10,9 @@
#include "net/base/int128.h"
#include "testing/gtest/include/gtest/gtest.h"
-using net::uint128;
-using net::uint128_pod;
-using net::kuint128max;
+namespace net {
+
+namespace test {
TEST(Int128, AllTests) {
uint128 zero(0);
@@ -264,3 +264,7 @@ TEST(Int128, AliasTests) {
x3 += x3;
EXPECT_EQ(x4, x3);
}
+
+} // namespace test
+
+} // namespace net
diff --git a/chromium/net/base/iovec.h b/chromium/net/base/iovec.h
index a98ed212148..61e2593551e 100644
--- a/chromium/net/base/iovec.h
+++ b/chromium/net/base/iovec.h
@@ -7,6 +7,8 @@
#include <stddef.h>
+#include "build/build_config.h"
+
#if defined(OS_POSIX) && !defined(OS_NACL)
#include <sys/uio.h>
#else
diff --git a/chromium/net/base/ip_address.h b/chromium/net/base/ip_address.h
index f095384a2c0..e326e78da6e 100644
--- a/chromium/net/base/ip_address.h
+++ b/chromium/net/base/ip_address.h
@@ -2,8 +2,8 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#ifndef NET_BASE_IP_ADDRESS_NET_H_
-#define NET_BASE_IP_ADDRESS_NET_H_
+#ifndef NET_BASE_IP_ADDRESS_H_
+#define NET_BASE_IP_ADDRESS_H_
#include <stddef.h>
#include <stdint.h>
@@ -205,4 +205,4 @@ bool IPAddressStartsWith(const IPAddress& address, const uint8_t (&prefix)[N]) {
} // namespace net
-#endif // NET_BASE_IP_ADDRESS_NET_H_
+#endif // NET_BASE_IP_ADDRESS_H_
diff --git a/chromium/net/base/keygen_handler.cc b/chromium/net/base/keygen_handler.cc
deleted file mode 100644
index d1e91a4806a..00000000000
--- a/chromium/net/base/keygen_handler.cc
+++ /dev/null
@@ -1,29 +0,0 @@
-// Copyright (c) 2011 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.
-
-#include "net/base/keygen_handler.h"
-
-#if defined(USE_NSS_CERTS)
-#include "crypto/nss_crypto_module_delegate.h"
-#endif // defined(USE_NSS_CERTS)
-
-namespace net {
-
-// The constructor and destructor must be defined in a .cc file so that
-// CryptoModuleBlockingPasswordDelegate can be forward-declared on platforms
-// which use NSS.
-
-KeygenHandler::KeygenHandler(int key_size_in_bits,
- const std::string& challenge,
- const GURL& url)
- : key_size_in_bits_(key_size_in_bits),
- challenge_(challenge),
- url_(url),
- stores_key_(true) {
-}
-
-KeygenHandler::~KeygenHandler() {
-}
-
-} // namespace net
diff --git a/chromium/net/base/keygen_handler.h b/chromium/net/base/keygen_handler.h
deleted file mode 100644
index 67a11bc9b65..00000000000
--- a/chromium/net/base/keygen_handler.h
+++ /dev/null
@@ -1,66 +0,0 @@
-// Copyright (c) 2011 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.
-
-#ifndef NET_BASE_KEYGEN_HANDLER_H_
-#define NET_BASE_KEYGEN_HANDLER_H_
-
-#include <memory>
-#include <string>
-
-#include "base/callback_forward.h"
-#include "build/build_config.h"
-#include "net/base/net_export.h"
-#include "url/gurl.h"
-
-namespace crypto {
-class NSSCryptoModuleDelegate;
-}
-
-namespace net {
-
-// This class handles keypair generation for generating client
-// certificates via the <keygen> tag.
-// <http://dev.w3.org/html5/spec/Overview.html#the-keygen-element>
-// <https://developer.mozilla.org/En/HTML/HTML_Extensions/KEYGEN_Tag>
-
-class NET_EXPORT KeygenHandler {
- public:
- // Creates a handler that will generate a key with the given key size and
- // incorporate the |challenge| into the Netscape SPKAC structure. The request
- // for the key originated from |url|.
- KeygenHandler(int key_size_in_bits,
- const std::string& challenge,
- const GURL& url);
- ~KeygenHandler();
-
- // Actually generates the key-pair and the cert request (SPKAC), and returns
- // a base64-encoded string suitable for use as the form value of <keygen>.
- std::string GenKeyAndSignChallenge();
-
- // Exposed only for unit tests.
- void set_stores_key(bool store) { stores_key_ = store;}
-
-#if defined(USE_NSS_CERTS)
- // Register the delegate to be used to get the token to store the key in, and
- // to get the password if the token is unauthenticated.
- // GenKeyAndSignChallenge runs on a worker thread, so using a blocking
- // password callback is okay here.
- void set_crypto_module_delegate(
- std::unique_ptr<crypto::NSSCryptoModuleDelegate> delegate);
-#endif // defined(USE_NSS_CERTS)
-
- private:
- int key_size_in_bits_; // key size in bits (usually 2048)
- std::string challenge_; // challenge string sent by server
- GURL url_; // the URL that requested the key
- bool stores_key_; // should the generated key-pair be stored persistently?
-#if defined(USE_NSS_CERTS)
- // The callback for requesting a password to the PKCS#11 token.
- std::unique_ptr<crypto::NSSCryptoModuleDelegate> crypto_module_delegate_;
-#endif // defined(USE_NSS_CERTS)
-};
-
-} // namespace net
-
-#endif // NET_BASE_KEYGEN_HANDLER_H_
diff --git a/chromium/net/base/keygen_handler_mac.cc b/chromium/net/base/keygen_handler_mac.cc
deleted file mode 100644
index 13814fea820..00000000000
--- a/chromium/net/base/keygen_handler_mac.cc
+++ /dev/null
@@ -1,339 +0,0 @@
-// Copyright (c) 2012 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.
-
-#include "net/base/keygen_handler.h"
-
-#include <Security/SecAsn1Coder.h>
-#include <Security/SecAsn1Templates.h>
-#include <Security/Security.h>
-
-#include "base/base64.h"
-#include "base/logging.h"
-#include "base/mac/mac_logging.h"
-#include "base/mac/scoped_cftyperef.h"
-#include "base/strings/string_util.h"
-#include "base/strings/sys_string_conversions.h"
-#include "base/synchronization/lock.h"
-#include "crypto/cssm_init.h"
-#include "crypto/mac_security_services_lock.h"
-
-// CSSM functions are deprecated as of OSX 10.7, but have no replacement.
-// https://bugs.chromium.org/p/chromium/issues/detail?id=590914#c1
-#pragma clang diagnostic push
-#pragma clang diagnostic ignored "-Wdeprecated-declarations"
-
-// These are in Security.framework but not declared in a public header.
-extern const SecAsn1Template kSecAsn1AlgorithmIDTemplate[];
-extern const SecAsn1Template kSecAsn1SubjectPublicKeyInfoTemplate[];
-
-namespace net {
-
-// Declarations of Netscape keygen cert structures for ASN.1 encoding:
-
-struct PublicKeyAndChallenge {
- CSSM_X509_SUBJECT_PUBLIC_KEY_INFO spki;
- CSSM_DATA challenge_string;
-};
-
-// This is a copy of the built-in kSecAsn1IA5StringTemplate, but without the
-// 'streamable' flag, which was causing bogus data to be written.
-const SecAsn1Template kIA5StringTemplate[] = {
- { SEC_ASN1_IA5_STRING, 0, NULL, sizeof(CSSM_DATA) }
-};
-
-static const SecAsn1Template kPublicKeyAndChallengeTemplate[] = {
- {
- SEC_ASN1_SEQUENCE,
- 0,
- NULL,
- sizeof(PublicKeyAndChallenge)
- },
- {
- SEC_ASN1_INLINE,
- offsetof(PublicKeyAndChallenge, spki),
- kSecAsn1SubjectPublicKeyInfoTemplate
- },
- {
- SEC_ASN1_INLINE,
- offsetof(PublicKeyAndChallenge, challenge_string),
- kIA5StringTemplate
- },
- {
- 0
- }
-};
-
-struct SignedPublicKeyAndChallenge {
- PublicKeyAndChallenge pkac;
- CSSM_X509_ALGORITHM_IDENTIFIER signature_algorithm;
- CSSM_DATA signature;
-};
-
-static const SecAsn1Template kSignedPublicKeyAndChallengeTemplate[] = {
- {
- SEC_ASN1_SEQUENCE,
- 0,
- NULL,
- sizeof(SignedPublicKeyAndChallenge)
- },
- {
- SEC_ASN1_INLINE,
- offsetof(SignedPublicKeyAndChallenge, pkac),
- kPublicKeyAndChallengeTemplate
- },
- {
- SEC_ASN1_INLINE,
- offsetof(SignedPublicKeyAndChallenge, signature_algorithm),
- kSecAsn1AlgorithmIDTemplate
- },
- {
- SEC_ASN1_BIT_STRING,
- offsetof(SignedPublicKeyAndChallenge, signature)
- },
- {
- 0
- }
-};
-
-
-static OSStatus CreateRSAKeyPair(int size_in_bits,
- SecAccessRef initial_access,
- SecKeyRef* out_pub_key,
- SecKeyRef* out_priv_key);
-static OSStatus SignData(CSSM_DATA data,
- SecKeyRef private_key,
- CSSM_DATA* signature);
-
-std::string KeygenHandler::GenKeyAndSignChallenge() {
- std::string result;
- OSStatus err;
- SecAccessRef initial_access = NULL;
- SecKeyRef public_key = NULL;
- SecKeyRef private_key = NULL;
- SecAsn1CoderRef coder = NULL;
- CSSM_DATA signature = {0, NULL};
-
- {
- if (url_.has_host()) {
- // TODO(davidben): Use something like "Key generated for
- // example.com", but localize it.
- base::ScopedCFTypeRef<CFStringRef> label(
- base::SysUTF8ToCFStringRef(url_.host()));
- // Create an initial access object to set the SecAccessRef. This
- // sets a label on the Keychain dialogs. Pass NULL as the second
- // argument to use the default trusted list; only allow the
- // current application to access without user confirmation.
- err = SecAccessCreate(label, NULL, &initial_access);
- // If we fail, just continue without a label.
- if (err)
- crypto::LogCSSMError("SecAccessCreate", err);
- }
-
- // Create the key-pair.
- err = CreateRSAKeyPair(key_size_in_bits_, initial_access,
- &public_key, &private_key);
- if (err)
- goto failure;
-
- // Get the public key data (DER sequence of modulus, exponent).
- CFDataRef key_data = NULL;
- err = SecKeychainItemExport(public_key, kSecFormatBSAFE, 0, NULL,
- &key_data);
- if (err) {
- crypto::LogCSSMError("SecKeychainItemExpor", err);
- goto failure;
- }
- base::ScopedCFTypeRef<CFDataRef> scoped_key_data(key_data);
-
- // Create an ASN.1 encoder.
- err = SecAsn1CoderCreate(&coder);
- if (err) {
- crypto::LogCSSMError("SecAsn1CoderCreate", err);
- goto failure;
- }
-
- // The DER encoding of a NULL.
- static const uint8_t kNullDer[] = {0x05, 0x00};
-
- // Fill in and DER-encode the PublicKeyAndChallenge:
- SignedPublicKeyAndChallenge spkac;
- memset(&spkac, 0, sizeof(spkac));
- spkac.pkac.spki.algorithm.algorithm = CSSMOID_RSA;
- spkac.pkac.spki.algorithm.parameters.Data = const_cast<uint8_t*>(kNullDer);
- spkac.pkac.spki.algorithm.parameters.Length = sizeof(kNullDer);
- spkac.pkac.spki.subjectPublicKey.Length =
- CFDataGetLength(key_data) * 8; // interpreted as a _bit_ count
- spkac.pkac.spki.subjectPublicKey.Data =
- const_cast<uint8_t*>(CFDataGetBytePtr(key_data));
- spkac.pkac.challenge_string.Length = challenge_.length();
- spkac.pkac.challenge_string.Data =
- reinterpret_cast<uint8_t*>(const_cast<char*>(challenge_.data()));
-
- CSSM_DATA encoded;
- err = SecAsn1EncodeItem(coder, &spkac.pkac,
- kPublicKeyAndChallengeTemplate, &encoded);
- if (err) {
- crypto::LogCSSMError("SecAsn1EncodeItem", err);
- goto failure;
- }
-
- // Compute a signature of the result:
- err = SignData(encoded, private_key, &signature);
- if (err)
- goto failure;
- spkac.signature.Data = signature.Data;
- spkac.signature.Length = signature.Length * 8; // a _bit_ count
- spkac.signature_algorithm.algorithm = CSSMOID_MD5WithRSA;
- spkac.signature_algorithm.parameters.Data = const_cast<uint8_t*>(kNullDer);
- spkac.signature_algorithm.parameters.Length = sizeof(kNullDer);
- // TODO(snej): MD5 is weak. Can we use SHA1 instead?
- // See <https://bugzilla.mozilla.org/show_bug.cgi?id=549460>
-
- // DER-encode the entire SignedPublicKeyAndChallenge:
- err = SecAsn1EncodeItem(coder, &spkac,
- kSignedPublicKeyAndChallengeTemplate, &encoded);
- if (err) {
- crypto::LogCSSMError("SecAsn1EncodeItem", err);
- goto failure;
- }
-
- // Base64 encode the result.
- std::string input(reinterpret_cast<char*>(encoded.Data), encoded.Length);
- base::Base64Encode(input, &result);
- }
-
- failure:
- if (err)
- OSSTATUS_LOG(ERROR, err) << "SSL Keygen failed!";
- else
- VLOG(1) << "SSL Keygen succeeded! Output is: " << result;
-
- // Remove keys from keychain if asked to during unit testing:
- if (!stores_key_) {
- if (public_key)
- SecKeychainItemDelete(reinterpret_cast<SecKeychainItemRef>(public_key));
- if (private_key)
- SecKeychainItemDelete(reinterpret_cast<SecKeychainItemRef>(private_key));
- }
-
- // Clean up:
- free(signature.Data);
- if (coder)
- SecAsn1CoderRelease(coder);
- if (initial_access)
- CFRelease(initial_access);
- if (public_key)
- CFRelease(public_key);
- if (private_key)
- CFRelease(private_key);
- return result;
-}
-
-
-// Create an RSA key pair with size |size_in_bits|. |initial_access|
-// is passed as the initial access control list in Keychain. The
-// public and private keys are placed in |out_pub_key| and
-// |out_priv_key|, respectively.
-static OSStatus CreateRSAKeyPair(int size_in_bits,
- SecAccessRef initial_access,
- SecKeyRef* out_pub_key,
- SecKeyRef* out_priv_key) {
- OSStatus err;
- SecKeychainRef keychain;
- err = SecKeychainCopyDefault(&keychain);
- if (err) {
- crypto::LogCSSMError("SecKeychainCopyDefault", err);
- return err;
- }
- base::ScopedCFTypeRef<SecKeychainRef> scoped_keychain(keychain);
- {
- base::AutoLock locked(crypto::GetMacSecurityServicesLock());
- err = SecKeyCreatePair(
- keychain,
- CSSM_ALGID_RSA,
- size_in_bits,
- 0LL,
- // public key usage and attributes:
- CSSM_KEYUSE_ENCRYPT | CSSM_KEYUSE_VERIFY | CSSM_KEYUSE_WRAP,
- CSSM_KEYATTR_EXTRACTABLE | CSSM_KEYATTR_PERMANENT,
- // private key usage and attributes:
- CSSM_KEYUSE_DECRYPT | CSSM_KEYUSE_SIGN | CSSM_KEYUSE_UNWRAP,
- CSSM_KEYATTR_EXTRACTABLE | CSSM_KEYATTR_PERMANENT |
- CSSM_KEYATTR_SENSITIVE,
- initial_access,
- out_pub_key, out_priv_key);
- }
- if (err)
- crypto::LogCSSMError("SecKeyCreatePair", err);
- return err;
-}
-
-static OSStatus CreateSignatureContext(SecKeyRef key,
- CSSM_ALGORITHMS algorithm,
- CSSM_CC_HANDLE* out_cc_handle) {
- OSStatus err;
- const CSSM_ACCESS_CREDENTIALS* credentials = NULL;
- {
- base::AutoLock locked(crypto::GetMacSecurityServicesLock());
- err = SecKeyGetCredentials(key,
- CSSM_ACL_AUTHORIZATION_SIGN,
- kSecCredentialTypeDefault,
- &credentials);
- }
- if (err) {
- crypto::LogCSSMError("SecKeyGetCredentials", err);
- return err;
- }
-
- CSSM_CSP_HANDLE csp_handle = 0;
- {
- base::AutoLock locked(crypto::GetMacSecurityServicesLock());
- err = SecKeyGetCSPHandle(key, &csp_handle);
- }
- if (err) {
- crypto::LogCSSMError("SecKeyGetCSPHandle", err);
- return err;
- }
-
- const CSSM_KEY* cssm_key = NULL;
- {
- base::AutoLock locked(crypto::GetMacSecurityServicesLock());
- err = SecKeyGetCSSMKey(key, &cssm_key);
- }
- if (err) {
- crypto::LogCSSMError("SecKeyGetCSSMKey", err);
- return err;
- }
-
- err = CSSM_CSP_CreateSignatureContext(csp_handle,
- algorithm,
- credentials,
- cssm_key,
- out_cc_handle);
- if (err)
- crypto::LogCSSMError("CSSM_CSP_CreateSignatureContext", err);
- return err;
-}
-
-static OSStatus SignData(CSSM_DATA data,
- SecKeyRef private_key,
- CSSM_DATA* signature) {
- CSSM_CC_HANDLE cc_handle;
- OSStatus err = CreateSignatureContext(private_key,
- CSSM_ALGID_MD5WithRSA,
- &cc_handle);
- if (err) {
- crypto::LogCSSMError("CreateSignatureContext", err);
- return err;
- }
- err = CSSM_SignData(cc_handle, &data, 1, CSSM_ALGID_NONE, signature);
- if (err)
- crypto::LogCSSMError("CSSM_SignData", err);
- CSSM_DeleteContext(cc_handle);
- return err;
-}
-
-} // namespace net
-
-#pragma clang diagnostic pop // "-Wdeprecated-declarations"
diff --git a/chromium/net/base/keygen_handler_nss.cc b/chromium/net/base/keygen_handler_nss.cc
deleted file mode 100644
index 97e0018f5e2..00000000000
--- a/chromium/net/base/keygen_handler_nss.cc
+++ /dev/null
@@ -1,48 +0,0 @@
-// Copyright (c) 2011 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.
-
-#include "net/base/keygen_handler.h"
-
-#include <utility>
-
-#include "base/logging.h"
-#include "crypto/nss_crypto_module_delegate.h"
-#include "crypto/nss_util.h"
-#include "crypto/scoped_nss_types.h"
-#include "net/third_party/mozilla_security_manager/nsKeygenHandler.h"
-
-// PSM = Mozilla's Personal Security Manager.
-namespace psm = mozilla_security_manager;
-
-namespace net {
-
-std::string KeygenHandler::GenKeyAndSignChallenge() {
- crypto::EnsureNSSInit();
-
- crypto::ScopedPK11Slot slot;
- if (crypto_module_delegate_) {
- slot = crypto_module_delegate_->RequestSlot();
- } else {
- LOG(ERROR) << "Could not get an NSS key slot.";
- return std::string();
- }
-
- // Authenticate to the token.
- if (SECSuccess != PK11_Authenticate(slot.get(),
- PR_TRUE,
- crypto_module_delegate_->wincx())) {
- LOG(ERROR) << "Could not authenticate to the key slot.";
- return std::string();
- }
-
- return psm::GenKeyAndSignChallenge(key_size_in_bits_, challenge_, url_,
- slot.get(), stores_key_);
-}
-
-void KeygenHandler::set_crypto_module_delegate(
- std::unique_ptr<crypto::NSSCryptoModuleDelegate> delegate) {
- crypto_module_delegate_ = std::move(delegate);
-}
-
-} // namespace net
diff --git a/chromium/net/base/keygen_handler_openssl.cc b/chromium/net/base/keygen_handler_openssl.cc
deleted file mode 100644
index 161a5b743d8..00000000000
--- a/chromium/net/base/keygen_handler_openssl.cc
+++ /dev/null
@@ -1,122 +0,0 @@
-// Copyright (c) 2011 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.
-
-#include <stdint.h>
-
-#include <memory>
-
-#include "base/base64.h"
-#include "base/location.h"
-#include "base/logging.h"
-#include "base/strings/string_piece.h"
-#include "crypto/openssl_util.h"
-#include "crypto/rsa_private_key.h"
-#include "net/base/keygen_handler.h"
-#include "net/base/openssl_private_key_store.h"
-#include "third_party/boringssl/src/include/openssl/bytestring.h"
-#include "third_party/boringssl/src/include/openssl/digest.h"
-#include "third_party/boringssl/src/include/openssl/evp.h"
-#include "third_party/boringssl/src/include/openssl/mem.h"
-
-namespace net {
-
-std::string KeygenHandler::GenKeyAndSignChallenge() {
- std::unique_ptr<crypto::RSAPrivateKey> key(
- crypto::RSAPrivateKey::Create(key_size_in_bits_));
- EVP_PKEY* pkey = key->key();
-
- if (stores_key_)
- OpenSSLPrivateKeyStore::StoreKeyPair(url_, pkey);
-
- // Serialize the following structure, from
- // https://developer.mozilla.org/en-US/docs/Web/HTML/Element/keygen.
- //
- // PublicKeyAndChallenge ::= SEQUENCE {
- // spki SubjectPublicKeyInfo,
- // challenge IA5STRING
- // }
- //
- // SignedPublicKeyAndChallenge ::= SEQUENCE {
- // publicKeyAndChallenge PublicKeyAndChallenge,
- // signatureAlgorithm AlgorithmIdentifier,
- // signature BIT STRING
- // }
- //
- // The signature is over the PublicKeyAndChallenge.
-
- // TODO(davidben): If we gain another consumer, factor this code out into
- // shared logic, sharing OID definitions with the verifier, to support signing
- // other X.509-style structures.
-
- crypto::OpenSSLErrStackTracer tracer(FROM_HERE);
-
- // Serialize up to the PublicKeyAndChallenge.
- bssl::ScopedCBB cbb;
- CBB spkac, public_key_and_challenge, challenge;
- if (!CBB_init(cbb.get(), 0) ||
- !CBB_add_asn1(cbb.get(), &spkac, CBS_ASN1_SEQUENCE) ||
- !CBB_add_asn1(&spkac, &public_key_and_challenge, CBS_ASN1_SEQUENCE) ||
- !EVP_marshal_public_key(&public_key_and_challenge, pkey) ||
- !CBB_add_asn1(&public_key_and_challenge, &challenge,
- CBS_ASN1_IA5STRING) ||
- !CBB_add_bytes(&challenge,
- reinterpret_cast<const uint8_t*>(challenge_.data()),
- challenge_.size()) ||
- !CBB_flush(&spkac)) {
- return std::string();
- }
-
- // Hash what's been written so far.
- bssl::ScopedEVP_MD_CTX ctx;
- if (!EVP_DigestSignInit(ctx.get(), nullptr, EVP_md5(), nullptr, pkey) ||
- !EVP_DigestSignUpdate(ctx.get(), CBB_data(&spkac), CBB_len(&spkac))) {
- return std::string();
- }
-
- // The DER encoding of 1.2.840.113549.1.1.4, MD5 with RSA encryption.
- static const uint8_t kMd5WithRsaEncryption[] = {
- 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x04,
- };
-
- // Write the signatureAlgorithm.
- CBB algorithm, oid, null;
- if (!CBB_add_asn1(&spkac, &algorithm, CBS_ASN1_SEQUENCE) ||
- !CBB_add_asn1(&algorithm, &oid, CBS_ASN1_OBJECT) ||
- !CBB_add_bytes(&oid, kMd5WithRsaEncryption,
- sizeof(kMd5WithRsaEncryption)) ||
- !CBB_add_asn1(&algorithm, &null, CBS_ASN1_NULL)) {
- return std::string();
- }
-
- // Compute and write the signature. Note that X.509 signatures, although
- // always byte strings for RSA, are encoded as BIT STRINGS with a multiple of
- // 8 bits.
- CBB sig_bitstring;
- uint8_t* sig;
- size_t sig_len;
- if (!CBB_add_asn1(&spkac, &sig_bitstring, CBS_ASN1_BITSTRING) ||
- !CBB_add_u8(&sig_bitstring, 0 /* no unused bits */) ||
- // Determine the maximum length of the signature.
- !EVP_DigestSignFinal(ctx.get(), nullptr, &sig_len) ||
- // Reserve |sig_len| bytes and write the signature to |spkac|.
- !CBB_reserve(&sig_bitstring, &sig, sig_len) ||
- !EVP_DigestSignFinal(ctx.get(), sig, &sig_len) ||
- !CBB_did_write(&sig_bitstring, sig_len)) {
- return std::string();
- }
-
- // Finally, the structure is base64-encoded.
- uint8_t* der;
- size_t der_len;
- if (!CBB_finish(cbb.get(), &der, &der_len)) {
- return std::string();
- }
- std::string result;
- base::Base64Encode(
- base::StringPiece(reinterpret_cast<const char*>(der), der_len), &result);
- OPENSSL_free(der);
- return result;
-}
-
-} // namespace net
diff --git a/chromium/net/base/keygen_handler_unittest.cc b/chromium/net/base/keygen_handler_unittest.cc
deleted file mode 100644
index b0c90b238ff..00000000000
--- a/chromium/net/base/keygen_handler_unittest.cc
+++ /dev/null
@@ -1,230 +0,0 @@
-// Copyright (c) 2011 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.
-
-#include "net/base/keygen_handler.h"
-
-#include <stdint.h>
-
-#include <string>
-#include <utility>
-
-#include "base/base64.h"
-#include "base/bind.h"
-#include "base/location.h"
-#include "base/logging.h"
-#include "base/strings/string_piece.h"
-#include "base/synchronization/waitable_event.h"
-#include "base/threading/thread_restrictions.h"
-#include "base/threading/worker_pool.h"
-#include "build/build_config.h"
-#include "testing/gtest/include/gtest/gtest.h"
-#include "third_party/boringssl/src/include/openssl/bytestring.h"
-#include "third_party/boringssl/src/include/openssl/evp.h"
-
-#if defined(USE_NSS_CERTS)
-#include <private/pprthred.h> // PR_DetachThread
-#include "crypto/nss_crypto_module_delegate.h"
-#include "crypto/scoped_test_nss_db.h"
-#endif
-
-namespace net {
-
-namespace {
-
-#if defined(USE_NSS_CERTS)
-class StubCryptoModuleDelegate : public crypto::NSSCryptoModuleDelegate {
- public:
- explicit StubCryptoModuleDelegate(crypto::ScopedPK11Slot slot)
- : slot_(std::move(slot)) {}
-
- std::string RequestPassword(const std::string& slot_name,
- bool retry,
- bool* cancelled) override {
- return std::string();
- }
-
- crypto::ScopedPK11Slot RequestSlot() override {
- return crypto::ScopedPK11Slot(PK11_ReferenceSlot(slot_.get()));
- }
-
- private:
- crypto::ScopedPK11Slot slot_;
-};
-#endif
-
-const char kChallenge[] = "some challenge";
-
-class KeygenHandlerTest : public ::testing::Test {
- public:
- KeygenHandlerTest() {}
- ~KeygenHandlerTest() override {}
-
- std::unique_ptr<KeygenHandler> CreateKeygenHandler() {
- std::unique_ptr<KeygenHandler> handler(
- new KeygenHandler(768, kChallenge, GURL("http://www.example.com")));
-#if defined(USE_NSS_CERTS)
- handler->set_crypto_module_delegate(
- std::unique_ptr<crypto::NSSCryptoModuleDelegate>(
- new StubCryptoModuleDelegate(crypto::ScopedPK11Slot(
- PK11_ReferenceSlot(test_nss_db_.slot())))));
-#endif
- return handler;
- }
-
- private:
-#if defined(USE_NSS_CERTS)
- crypto::ScopedTestNSSDB test_nss_db_;
-#endif
-};
-
-base::StringPiece StringPieceFromCBS(const CBS& cbs) {
- return base::StringPiece(reinterpret_cast<const char*>(CBS_data(&cbs)),
- CBS_len(&cbs));
-}
-
-// Assert that |result| is a valid output for KeygenHandler given challenge
-// string of |challenge|.
-void AssertValidSignedPublicKeyAndChallenge(const std::string& result,
- const std::string& challenge) {
- // Verify it's valid base64:
- std::string spkac;
- ASSERT_TRUE(base::Base64Decode(result, &spkac));
-
- // Parse the following structure:
- //
- // PublicKeyAndChallenge ::= SEQUENCE {
- // spki SubjectPublicKeyInfo,
- // challenge IA5STRING
- // }
- // SignedPublicKeyAndChallenge ::= SEQUENCE {
- // publicKeyAndChallenge PublicKeyAndChallenge,
- // signatureAlgorithm AlgorithmIdentifier,
- // signature BIT STRING
- // }
-
- CBS cbs;
- CBS_init(&cbs, reinterpret_cast<const uint8_t*>(spkac.data()), spkac.size());
-
- // The input should consist of a SEQUENCE.
- CBS child;
- ASSERT_TRUE(CBS_get_asn1(&cbs, &child, CBS_ASN1_SEQUENCE));
- ASSERT_EQ(0u, CBS_len(&cbs));
-
- // Extract the raw PublicKeyAndChallenge.
- CBS public_key_and_challenge_raw;
- ASSERT_TRUE(CBS_get_asn1_element(&child, &public_key_and_challenge_raw,
- CBS_ASN1_SEQUENCE));
-
- // Parse out the PublicKeyAndChallenge.
- CBS copy = public_key_and_challenge_raw;
- CBS public_key_and_challenge;
- ASSERT_TRUE(
- CBS_get_asn1(&copy, &public_key_and_challenge, CBS_ASN1_SEQUENCE));
- ASSERT_EQ(0u, CBS_len(&copy));
- bssl::UniquePtr<EVP_PKEY> key(
- EVP_parse_public_key(&public_key_and_challenge));
- ASSERT_TRUE(key);
- CBS challenge_spkac;
- ASSERT_TRUE(CBS_get_asn1(&public_key_and_challenge, &challenge_spkac,
- CBS_ASN1_IA5STRING));
- ASSERT_EQ(0u, CBS_len(&public_key_and_challenge));
-
- // The challenge must match.
- ASSERT_EQ(challenge, StringPieceFromCBS(challenge_spkac));
-
- // The next element must be the AlgorithmIdentifier for MD5 with RSA.
- static const uint8_t kMd5WithRsaEncryption[] = {
- 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86,
- 0xf7, 0x0d, 0x01, 0x01, 0x04, 0x05, 0x00,
- };
- CBS algorithm;
- ASSERT_TRUE(CBS_get_bytes(&child, &algorithm, sizeof(kMd5WithRsaEncryption)));
- ASSERT_EQ(
- base::StringPiece(reinterpret_cast<const char*>(kMd5WithRsaEncryption),
- sizeof(kMd5WithRsaEncryption)),
- StringPieceFromCBS(algorithm));
-
- // Finally, parse the signature.
- CBS signature;
- ASSERT_TRUE(CBS_get_asn1(&child, &signature, CBS_ASN1_BITSTRING));
- ASSERT_EQ(0u, CBS_len(&child));
- uint8_t pad;
- ASSERT_TRUE(CBS_get_u8(&signature, &pad));
- ASSERT_EQ(0u, pad);
-
- // Check the signature.
- bssl::ScopedEVP_MD_CTX ctx;
- ASSERT_TRUE(
- EVP_DigestVerifyInit(ctx.get(), nullptr, EVP_md5(), nullptr, key.get()));
- ASSERT_TRUE(EVP_DigestVerifyUpdate(ctx.get(),
- CBS_data(&public_key_and_challenge_raw),
- CBS_len(&public_key_and_challenge_raw)));
- ASSERT_TRUE(EVP_DigestVerifyFinal(ctx.get(), CBS_data(&signature),
- CBS_len(&signature)));
-}
-
-TEST_F(KeygenHandlerTest, SmokeTest) {
- std::unique_ptr<KeygenHandler> handler(CreateKeygenHandler());
- handler->set_stores_key(false); // Don't leave the key-pair behind
- std::string result = handler->GenKeyAndSignChallenge();
- VLOG(1) << "KeygenHandler produced: " << result;
- AssertValidSignedPublicKeyAndChallenge(result, kChallenge);
-}
-
-void ConcurrencyTestCallback(const std::string& challenge,
- base::WaitableEvent* event,
- std::unique_ptr<KeygenHandler> handler,
- std::string* result) {
- // We allow Singleton use on the worker thread here since we use a
- // WaitableEvent to synchronize, so it's safe.
- base::ThreadRestrictions::ScopedAllowSingleton scoped_allow_singleton;
- handler->set_stores_key(false); // Don't leave the key-pair behind.
- *result = handler->GenKeyAndSignChallenge();
- event->Signal();
-#if defined(USE_NSS_CERTS)
- // Detach the thread from NSPR.
- // Calling NSS functions attaches the thread to NSPR, which stores
- // the NSPR thread ID in thread-specific data.
- // The threads in our thread pool terminate after we have called
- // PR_Cleanup. Unless we detach them from NSPR, net_unittests gets
- // segfaults on shutdown when the threads' thread-specific data
- // destructors run.
- PR_DetachThread();
-#endif
-}
-
-// We asynchronously generate the keys so as not to hang up the IO thread. This
-// test tries to catch concurrency problems in the keygen implementation.
-TEST_F(KeygenHandlerTest, ConcurrencyTest) {
- const int NUM_HANDLERS = 5;
- base::WaitableEvent* events[NUM_HANDLERS] = { NULL };
- std::string results[NUM_HANDLERS];
- for (int i = 0; i < NUM_HANDLERS; i++) {
- std::unique_ptr<KeygenHandler> handler(CreateKeygenHandler());
- events[i] = new base::WaitableEvent(
- base::WaitableEvent::ResetPolicy::AUTOMATIC,
- base::WaitableEvent::InitialState::NOT_SIGNALED);
- base::WorkerPool::PostTask(FROM_HERE,
- base::Bind(ConcurrencyTestCallback,
- "some challenge",
- events[i],
- base::Passed(&handler),
- &results[i]),
- true);
- }
-
- for (int i = 0; i < NUM_HANDLERS; i++) {
- // Make sure the job completed
- events[i]->Wait();
- delete events[i];
- events[i] = NULL;
-
- VLOG(1) << "KeygenHandler " << i << " produced: " << results[i];
- AssertValidSignedPublicKeyAndChallenge(results[i], "some challenge");
- }
-}
-
-} // namespace
-
-} // namespace net
diff --git a/chromium/net/base/keygen_handler_win.cc b/chromium/net/base/keygen_handler_win.cc
deleted file mode 100644
index f88e7e12579..00000000000
--- a/chromium/net/base/keygen_handler_win.cc
+++ /dev/null
@@ -1,218 +0,0 @@
-// Copyright (c) 2011 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.
-
-#include "net/base/keygen_handler.h"
-
-#include <windows.h>
-#include <rpc.h>
-
-#include <list>
-#include <string>
-#include <vector>
-
-#include "base/base64.h"
-#include "base/logging.h"
-#include "base/strings/string_piece.h"
-#include "base/strings/string_util.h"
-#include "base/strings/utf_string_conversions.h"
-#include "crypto/capi_util.h"
-#include "crypto/scoped_capi_types.h"
-#include "crypto/wincrypt_shim.h"
-
-namespace net {
-
-// Assigns the contents of a CERT_PUBLIC_KEY_INFO structure for the signing
-// key in |prov| to |output|. Returns true if encoding was successful.
-bool GetSubjectPublicKeyInfo(HCRYPTPROV prov, std::vector<BYTE>* output) {
- BOOL ok;
- DWORD size = 0;
-
- // From the private key stored in HCRYPTPROV, obtain the public key, stored
- // as a CERT_PUBLIC_KEY_INFO structure. Currently, only RSA public keys are
- // supported.
- ok = CryptExportPublicKeyInfoEx(prov, AT_KEYEXCHANGE, X509_ASN_ENCODING,
- const_cast<char*>(szOID_RSA_RSA), 0, NULL,
- NULL, &size);
- DCHECK(ok);
- if (!ok)
- return false;
-
- output->resize(size);
-
- PCERT_PUBLIC_KEY_INFO public_key_casted =
- reinterpret_cast<PCERT_PUBLIC_KEY_INFO>(&(*output)[0]);
- ok = CryptExportPublicKeyInfoEx(prov, AT_KEYEXCHANGE, X509_ASN_ENCODING,
- const_cast<char*>(szOID_RSA_RSA), 0, NULL,
- public_key_casted, &size);
- DCHECK(ok);
- if (!ok)
- return false;
-
- output->resize(size);
-
- return true;
-}
-
-// Generates a DER encoded SignedPublicKeyAndChallenge structure from the
-// signing key of |prov| and the specified ASCII |challenge| string and
-// appends it to |output|.
-// True if the encoding was successfully generated.
-bool GetSignedPublicKeyAndChallenge(HCRYPTPROV prov,
- const std::string& challenge,
- std::string* output) {
- base::string16 challenge16 = base::ASCIIToUTF16(challenge);
- std::vector<BYTE> spki;
-
- if (!GetSubjectPublicKeyInfo(prov, &spki))
- return false;
-
- // PublicKeyAndChallenge ::= SEQUENCE {
- // spki SubjectPublicKeyInfo,
- // challenge IA5STRING
- // }
- CERT_KEYGEN_REQUEST_INFO pkac;
- pkac.dwVersion = CERT_KEYGEN_REQUEST_V1;
- pkac.SubjectPublicKeyInfo =
- *reinterpret_cast<PCERT_PUBLIC_KEY_INFO>(&spki[0]);
- pkac.pwszChallengeString = const_cast<base::char16*>(challenge16.c_str());
-
- CRYPT_ALGORITHM_IDENTIFIER sig_alg;
- memset(&sig_alg, 0, sizeof(sig_alg));
- sig_alg.pszObjId = const_cast<char*>(szOID_RSA_MD5RSA);
-
- BOOL ok;
- DWORD size = 0;
- std::vector<BYTE> signed_pkac;
- ok = CryptSignAndEncodeCertificate(prov, AT_KEYEXCHANGE, X509_ASN_ENCODING,
- X509_KEYGEN_REQUEST_TO_BE_SIGNED,
- &pkac, &sig_alg, NULL,
- NULL, &size);
- DCHECK(ok);
- if (!ok)
- return false;
-
- signed_pkac.resize(size);
- ok = CryptSignAndEncodeCertificate(prov, AT_KEYEXCHANGE, X509_ASN_ENCODING,
- X509_KEYGEN_REQUEST_TO_BE_SIGNED,
- &pkac, &sig_alg, NULL,
- &signed_pkac[0], &size);
- DCHECK(ok);
- if (!ok)
- return false;
-
- output->assign(reinterpret_cast<char*>(&signed_pkac[0]), size);
- return true;
-}
-
-// Generates a unique name for the container which will store the key that is
-// generated. The traditional Windows approach is to use a GUID here.
-std::wstring GetNewKeyContainerId() {
- RPC_STATUS status = RPC_S_OK;
- std::wstring result;
-
- UUID id = { 0 };
- status = UuidCreateSequential(&id);
- if (status != RPC_S_OK && status != RPC_S_UUID_LOCAL_ONLY)
- return result;
-
- RPC_WSTR rpc_string = NULL;
- status = UuidToString(&id, &rpc_string);
- if (status != RPC_S_OK)
- return result;
-
- // RPC_WSTR is unsigned short*. wchar_t is a built-in type of Visual C++,
- // so the type cast is necessary.
- result.assign(reinterpret_cast<wchar_t*>(rpc_string));
- RpcStringFree(&rpc_string);
-
- return result;
-}
-
-// This is a helper struct designed to optionally delete a key after releasing
-// the associated provider.
-struct KeyContainer {
- public:
- explicit KeyContainer(bool delete_keyset)
- : delete_keyset_(delete_keyset) {}
-
- ~KeyContainer() {
- if (provider_) {
- provider_.reset();
- if (delete_keyset_ && !key_id_.empty()) {
- HCRYPTPROV provider;
- crypto::CryptAcquireContextLocked(&provider, key_id_.c_str(), NULL,
- PROV_RSA_FULL, CRYPT_SILENT | CRYPT_DELETEKEYSET);
- }
- }
- }
-
- crypto::ScopedHCRYPTPROV provider_;
- std::wstring key_id_;
-
- private:
- bool delete_keyset_;
-};
-
-std::string KeygenHandler::GenKeyAndSignChallenge() {
- KeyContainer key_container(!stores_key_);
-
- // TODO(rsleevi): Have the user choose which provider they should use, which
- // needs to be filtered by those providers which can provide the key type
- // requested or the key size requested. This is especially important for
- // generating certificates that will be stored on smart cards.
- const int kMaxAttempts = 5;
- int attempt;
- for (attempt = 0; attempt < kMaxAttempts; ++attempt) {
- // Per MSDN documentation for CryptAcquireContext, if applications will be
- // creating their own keys, they should ensure unique naming schemes to
- // prevent overlap with any other applications or consumers of CSPs, and
- // *should not* store new keys within the default, NULL key container.
- key_container.key_id_ = GetNewKeyContainerId();
- if (key_container.key_id_.empty())
- return std::string();
-
- // Only create new key containers, so that existing key containers are not
- // overwritten.
- if (crypto::CryptAcquireContextLocked(key_container.provider_.receive(),
- key_container.key_id_.c_str(), NULL, PROV_RSA_FULL,
- CRYPT_SILENT | CRYPT_NEWKEYSET))
- break;
-
- if (GetLastError() != static_cast<DWORD>(NTE_BAD_KEYSET)) {
- LOG(ERROR) << "Keygen failed: Couldn't acquire a CryptoAPI provider "
- "context: " << GetLastError();
- return std::string();
- }
- }
- if (attempt == kMaxAttempts) {
- LOG(ERROR) << "Keygen failed: Couldn't acquire a CryptoAPI provider "
- "context: Max retries exceeded";
- return std::string();
- }
-
- {
- crypto::ScopedHCRYPTKEY key;
- if (!CryptGenKey(key_container.provider_, CALG_RSA_KEYX,
- (key_size_in_bits_ << 16) | CRYPT_EXPORTABLE, key.receive())) {
- LOG(ERROR) << "Keygen failed: Couldn't generate an RSA key";
- return std::string();
- }
-
- std::string spkac;
- if (!GetSignedPublicKeyAndChallenge(key_container.provider_, challenge_,
- &spkac)) {
- LOG(ERROR) << "Keygen failed: Couldn't generate the signed public key "
- "and challenge";
- return std::string();
- }
-
- std::string result;
- base::Base64Encode(spkac, &result);
-
- VLOG(1) << "Keygen succeeded";
- return result;
- }
-}
-
-} // namespace net
diff --git a/chromium/net/base/linked_hash_map.h b/chromium/net/base/linked_hash_map.h
index 8397243958c..e12fd12af38 100644
--- a/chromium/net/base/linked_hash_map.h
+++ b/chromium/net/base/linked_hash_map.h
@@ -12,8 +12,8 @@
// Iterators should be stable in the face of mutations, except for an
// iterator pointing to an element that was just deleted.
-#ifndef UTIL_GTL_LINKED_HASH_MAP_H_
-#define UTIL_GTL_LINKED_HASH_MAP_H_
+#ifndef NET_BASE_LINKED_HASH_MAP_H_
+#define NET_BASE_LINKED_HASH_MAP_H_
#include <stddef.h>
@@ -261,4 +261,4 @@ class linked_hash_map {
} // namespace net
-#endif // UTIL_GTL_LINKED_HASH_MAP_H_
+#endif // NET_BASE_LINKED_HASH_MAP_H_
diff --git a/chromium/net/base/load_timing_info.cc b/chromium/net/base/load_timing_info.cc
index f3301fb2191..875acdd1bbe 100644
--- a/chromium/net/base/load_timing_info.cc
+++ b/chromium/net/base/load_timing_info.cc
@@ -20,4 +20,3 @@ LoadTimingInfo::LoadTimingInfo(const LoadTimingInfo& other) = default;
LoadTimingInfo::~LoadTimingInfo() {}
} // namespace net
-
diff --git a/chromium/net/base/logging_network_change_observer.h b/chromium/net/base/logging_network_change_observer.h
index 503cb4ff3d8..1d0d61e6e33 100644
--- a/chromium/net/base/logging_network_change_observer.h
+++ b/chromium/net/base/logging_network_change_observer.h
@@ -54,4 +54,4 @@ class NET_EXPORT LoggingNetworkChangeObserver
} // namespace net
-#endif // NET_BASE_LOGGING_NETWORK_CHANGE_OBSERVER_H_ \ No newline at end of file
+#endif // NET_BASE_LOGGING_NETWORK_CHANGE_OBSERVER_H_
diff --git a/chromium/net/base/mime_sniffer.cc b/chromium/net/base/mime_sniffer.cc
index faa5a0d84d3..0b280ca70b9 100644
--- a/chromium/net/base/mime_sniffer.cc
+++ b/chromium/net/base/mime_sniffer.cc
@@ -108,11 +108,11 @@ namespace net {
static const size_t kBytesRequiredForMagic = 42;
struct MagicNumber {
- const char* const mime_type;
- const char* const magic;
+ const char* mime_type;
+ const char* magic;
size_t magic_len;
bool is_string;
- const char* const mask; // if set, must have same length as |magic|
+ const char* mask; // if set, must have same length as |magic|
};
#define MAGIC_NUMBER(mime_type, magic) \
@@ -203,7 +203,7 @@ enum OfficeDocType {
struct OfficeExtensionType {
OfficeDocType doc_type;
- const char* const extension;
+ const char* extension;
size_t extension_len;
};
diff --git a/chromium/net/base/net_error_details.h b/chromium/net/base/net_error_details.h
index a7f239a3a91..5d10d11c517 100644
--- a/chromium/net/base/net_error_details.h
+++ b/chromium/net/base/net_error_details.h
@@ -7,7 +7,7 @@
#include "net/base/net_export.h"
#include "net/http/http_response_info.h"
-#include "net/quic/core/quic_protocol.h"
+#include "net/quic/core/quic_packets.h"
namespace net {
@@ -41,4 +41,4 @@ struct NET_EXPORT NetErrorDetails {
} // namespace net
-#endif
+#endif // NET_BASE_NET_ERROR_DETAILS_H_
diff --git a/chromium/net/base/net_error_list.h b/chromium/net/base/net_error_list.h
index 0694b6958d2..617a56d41f7 100644
--- a/chromium/net/base/net_error_list.h
+++ b/chromium/net/base/net_error_list.h
@@ -112,6 +112,14 @@ NET_ERROR(CONTEXT_SHUT_DOWN, -26)
// checks, for instance).
NET_ERROR(BLOCKED_BY_RESPONSE, -27)
+// The request failed after the response was received, based on client-side
+// heuristics that point to the possiblility of a cross-site scripting attack.
+NET_ERROR(BLOCKED_BY_XSS_AUDITOR, -28)
+
+// The request was blocked by system policy disallowing some or all cleartext
+// requests. Used for NetworkSecurityPolicy on Android.
+NET_ERROR(CLEARTEXT_NOT_PERMITTED, -29)
+
// A connection was closed (corresponding to a TCP FIN).
NET_ERROR(CONNECTION_CLOSED, -100)
@@ -316,8 +324,7 @@ NET_ERROR(SSL_SERVER_CERT_CHANGED, -156)
// Error -157 was removed (SSL_INAPPROPRIATE_FALLBACK).
-// Certificate Transparency: All Signed Certificate Timestamps failed to verify.
-NET_ERROR(CT_NO_SCTS_VERIFIED_OK, -158)
+// Error -158 was removed (CT_NO_SCTS_VERIFIED_OK).
// The SSL server sent us a fatal unrecognized_name alert.
NET_ERROR(SSL_UNRECOGNIZED_NAME_ALERT, -159)
@@ -375,6 +382,10 @@ NET_ERROR(CT_CONSISTENCY_PROOF_PARSING_FAILED, -171)
// fallback will be removed.
NET_ERROR(SSL_OBSOLETE_CIPHER, -172)
+// When a WebSocket handshake is done successfully and the connection has been
+// upgraded, the URLRequest is cancelled with this error code.
+NET_ERROR(WS_UPGRADE, -173)
+
// Certificate error codes
//
// The values of certificate error codes must be consecutive.
@@ -732,11 +743,11 @@ NET_ERROR(CACHE_AUTH_FAILURE_AFTER_READ, -410)
// The server's response was insecure (e.g. there was a cert error).
NET_ERROR(INSECURE_RESPONSE, -501)
-// The server responded to a <keygen> with a generated client cert that we
-// don't have the matching private key for.
+// An attempt to import a client certificate failed, as the user's key
+// database lacked a corresponding private key.
NET_ERROR(NO_PRIVATE_KEY_FOR_CERT, -502)
-// An error adding to the OS certificate database (e.g. OS X Keychain).
+// An error adding a certificate to the OS certificate database.
NET_ERROR(ADD_USER_CERT_FAILED, -503)
// *** Code -600 is reserved (was FTP_PASV_COMMAND_FAILED). ***
diff --git a/chromium/net/base/net_errors_posix.cc b/chromium/net/base/net_errors_posix.cc
index a8573fdfc68..123f7e54d67 100644
--- a/chromium/net/base/net_errors_posix.cc
+++ b/chromium/net/base/net_errors_posix.cc
@@ -10,7 +10,6 @@
#include <unistd.h>
#include "base/logging.h"
-#include "base/strings/stringprintf.h"
namespace net {
diff --git a/chromium/net/base/network_change_notifier.h b/chromium/net/base/network_change_notifier.h
index 27a798d04d1..1cefe85ff6e 100644
--- a/chromium/net/base/network_change_notifier.h
+++ b/chromium/net/base/network_change_notifier.h
@@ -15,8 +15,6 @@
#include "base/time/time.h"
#include "net/base/net_export.h"
-class GURL;
-
namespace net {
struct DnsConfig;
diff --git a/chromium/net/base/network_delegate.cc b/chromium/net/base/network_delegate.cc
index 192b9e37cef..8116432060d 100644
--- a/chromium/net/base/network_delegate.cc
+++ b/chromium/net/base/network_delegate.cc
@@ -9,6 +9,7 @@
#include "base/trace_event/trace_event.h"
#include "net/base/load_flags.h"
#include "net/base/net_errors.h"
+#include "net/base/trace_constants.h"
#include "net/proxy/proxy_info.h"
#include "net/url_request/url_request.h"
@@ -17,8 +18,7 @@ namespace net {
int NetworkDelegate::NotifyBeforeURLRequest(
URLRequest* request, const CompletionCallback& callback,
GURL* new_url) {
- TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("net"),
- "NetworkDelegate::NotifyBeforeURLRequest");
+ TRACE_EVENT0(kNetTracingCategory, "NetworkDelegate::NotifyBeforeURLRequest");
DCHECK(CalledOnValidThread());
DCHECK(request);
DCHECK(!callback.is_null());
@@ -33,7 +33,7 @@ int NetworkDelegate::NotifyBeforeStartTransaction(
URLRequest* request,
const CompletionCallback& callback,
HttpRequestHeaders* headers) {
- TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("net"),
+ TRACE_EVENT0(kNetTracingCategory,
"NetworkDelegate::NotifyBeforeStartTransation");
DCHECK(CalledOnValidThread());
DCHECK(headers);
@@ -54,8 +54,7 @@ void NetworkDelegate::NotifyBeforeSendHeaders(
void NetworkDelegate::NotifyStartTransaction(
URLRequest* request,
const HttpRequestHeaders& headers) {
- TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("net"),
- "NetworkDelegate::NotifyStartTransaction");
+ TRACE_EVENT0(kNetTracingCategory, "NetworkDelegate::NotifyStartTransaction");
DCHECK(CalledOnValidThread());
OnStartTransaction(request, headers);
}
@@ -66,8 +65,7 @@ int NetworkDelegate::NotifyHeadersReceived(
const HttpResponseHeaders* original_response_headers,
scoped_refptr<HttpResponseHeaders>* override_response_headers,
GURL* allowed_unsafe_redirect_url) {
- TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("net"),
- "NetworkDelegate::NotifyHeadersReceived");
+ TRACE_EVENT0(kNetTracingCategory, "NetworkDelegate::NotifyHeadersReceived");
DCHECK(CalledOnValidThread());
DCHECK(original_response_headers);
DCHECK(!callback.is_null());
@@ -88,7 +86,7 @@ void NetworkDelegate::NotifyResponseStarted(URLRequest* request,
void NetworkDelegate::NotifyNetworkBytesReceived(URLRequest* request,
int64_t bytes_received) {
- TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("net"),
+ TRACE_EVENT0(kNetTracingCategory,
"NetworkDelegate::NotifyNetworkBytesReceived");
DCHECK(CalledOnValidThread());
DCHECK_GT(bytes_received, 0);
@@ -112,8 +110,7 @@ void NetworkDelegate::NotifyBeforeRedirect(URLRequest* request,
void NetworkDelegate::NotifyCompleted(URLRequest* request,
bool started,
int net_error) {
- TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("net"),
- "NetworkDelegate::NotifyCompleted");
+ TRACE_EVENT0(kNetTracingCategory, "NetworkDelegate::NotifyCompleted");
DCHECK(CalledOnValidThread());
DCHECK(request);
// TODO(cbentzel): Remove ScopedTracker below once crbug.com/475753 is fixed.
@@ -124,7 +121,7 @@ void NetworkDelegate::NotifyCompleted(URLRequest* request,
}
void NetworkDelegate::NotifyURLRequestDestroyed(URLRequest* request) {
- TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("net"),
+ TRACE_EVENT0(kNetTracingCategory,
"NetworkDelegate::NotifyURLRequestDestroyed");
DCHECK(CalledOnValidThread());
DCHECK(request);
@@ -170,8 +167,7 @@ bool NetworkDelegate::CanAccessFile(const URLRequest& request,
bool NetworkDelegate::CanEnablePrivacyMode(
const GURL& url,
const GURL& first_party_for_cookies) const {
- TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("net"),
- "NetworkDelegate::CanEnablePrivacyMode");
+ TRACE_EVENT0(kNetTracingCategory, "NetworkDelegate::CanEnablePrivacyMode");
DCHECK(CalledOnValidThread());
return OnCanEnablePrivacyMode(url, first_party_for_cookies);
}
diff --git a/chromium/net/base/network_interfaces_unittest.cc b/chromium/net/base/network_interfaces_unittest.cc
index 718e796e8d3..7f36c556343 100644
--- a/chromium/net/base/network_interfaces_unittest.cc
+++ b/chromium/net/base/network_interfaces_unittest.cc
@@ -14,7 +14,6 @@
#include "base/scoped_native_library.h"
#include "base/strings/string_number_conversions.h"
#include "base/strings/string_util.h"
-#include "base/strings/stringprintf.h"
#include "base/strings/utf_string_conversions.h"
#include "base/sys_byteorder.h"
#include "base/time/time.h"
diff --git a/chromium/net/base/network_throttle_manager.h b/chromium/net/base/network_throttle_manager.h
index 4fde0f245d2..96a864e6784 100644
--- a/chromium/net/base/network_throttle_manager.h
+++ b/chromium/net/base/network_throttle_manager.h
@@ -24,12 +24,13 @@ namespace net {
// Methods are virtual to allow for test mocks.
class NET_EXPORT_PRIVATE NetworkThrottleManager {
public:
+ class Throttle;
+
// Abstract base class other classes can inherit from to get
// notifications from throttle state changes.
class NET_EXPORT_PRIVATE ThrottleDelegate {
public:
- // Called whenever the throttle state of this stream has changed.
- // The new state can be determined through Throttle::IsThrottled().
+ // Called when a throttle is unblocked.
//
// Note that this call may occur as the result of either a call to
// Throttle::SetPriority (on the throttle related to this delegate
@@ -37,7 +38,7 @@ class NET_EXPORT_PRIVATE NetworkThrottleManager {
// so will occur synchronously during those events. It will not
// be called from the destructor of the Throttle associated with
// the ThrottleDelegate.
- virtual void OnThrottleStateChanged() = 0;
+ virtual void OnThrottleUnblocked(Throttle* throttle) = 0;
protected:
virtual ~ThrottleDelegate() {}
@@ -45,24 +46,28 @@ class NET_EXPORT_PRIVATE NetworkThrottleManager {
// Class owned by external stream representations that
// routes notifications. It may be constructed in either the
- // throttled or unthrottled state according to the state of the
- // NetworkThrottleManager; if it's constructed in the throttled
- // state, it will only make a single transition to unthrottled,
- // which will be signaled by delegate->OnThrottleStateChanged().
- // If it's constructed in the unthrottled state, it will remain
+ // blocked or unblocked state according to the state of the
+ // NetworkThrottleManager; if it's constructed in the unblocked
+ // state, it will only make a single transition to unblocked,
+ // which will be signaled by delegate->OnThrottleUnblocked(this).
+ // If it's constructed in the unblocked state, it will remain
// there.
class NET_EXPORT_PRIVATE Throttle {
public:
virtual ~Throttle() {}
- virtual bool IsThrottled() const = 0;
+ virtual bool IsBlocked() const = 0;
+
+ virtual RequestPriority Priority() const = 0;
// Note that this may result in a possibly reentrant call to
- // |ThrottleDelegate::OnThrottleStateChanged|, as well as the resumption
+ // |ThrottleDelegate::OnThrottleUnblocked|, as well as the resumption
// of this or other requests, which may result in request completion
// and destruction before return. Any caller of this function
// should not rely on this object or containing objects surviving
// this call.
+ //
+ // This call is a no-op if the priority is set to its current value.
virtual void SetPriority(RequestPriority priority) = 0;
protected:
@@ -80,8 +85,6 @@ class NET_EXPORT_PRIVATE NetworkThrottleManager {
RequestPriority priority,
bool ignore_limits) = 0;
- static std::unique_ptr<NetworkThrottleManager> CreateThrottler();
-
protected:
NetworkThrottleManager() {}
diff --git a/chromium/net/base/network_throttle_manager_impl.cc b/chromium/net/base/network_throttle_manager_impl.cc
new file mode 100644
index 00000000000..eda6fea2cfc
--- /dev/null
+++ b/chromium/net/base/network_throttle_manager_impl.cc
@@ -0,0 +1,326 @@
+// Copyright 2016 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.
+
+#include "net/base/network_throttle_manager_impl.h"
+
+#include <algorithm>
+
+#include "base/logging.h"
+#include "base/threading/thread_task_runner_handle.h"
+#include "base/time/default_tick_clock.h"
+
+namespace net {
+
+const size_t NetworkThrottleManagerImpl::kActiveRequestThrottlingLimit = 2;
+const int NetworkThrottleManagerImpl::kMedianLifetimeMultiple = 5;
+
+// Initial estimate based on the median in the
+// Net.RequestTime2.Success histogram, excluding cached results by eye.
+const int NetworkThrottleManagerImpl::kInitialMedianInMs = 400;
+
+// Set timers slightly further into the future than they need to be set, so
+// that the algorithm isn't vulnerable to timer round off errors triggering
+// the callback before the throttle would be considered aged out of the set.
+// Set to 17 to hanlde systems with |!base::TimeTicks::IsHighResolution()|.
+// Note that even if the timer goes off before it should, all that should cost
+// is a second task; this class does not rely on timer accuracy for its
+// correctness.
+const int kTimerFudgeInMs = 17;
+
+class NetworkThrottleManagerImpl::ThrottleImpl
+ : public NetworkThrottleManager::Throttle {
+ public:
+ // Allowed state transitions are BLOCKED -> OUTSTANDING -> AGED.
+ // Throttles may be created in the BLOCKED or OUTSTANDING states.
+ enum class State {
+ // Not allowed to proceed by manager.
+ BLOCKED,
+
+ // Allowed to proceed, counts as an "outstanding" request for
+ // manager accounting purposes.
+ OUTSTANDING,
+
+ // Old enough to not count as "outstanding" anymore for
+ // manager accounting purposes.
+ AGED
+ };
+
+ using ThrottleListQueuePointer =
+ NetworkThrottleManagerImpl::ThrottleList::iterator;
+
+ // Caller must arrange that |*delegate| and |*manager| outlive
+ // the ThrottleImpl class.
+ ThrottleImpl(bool blocked,
+ RequestPriority priority,
+ ThrottleDelegate* delegate,
+ NetworkThrottleManagerImpl* manager,
+ ThrottleListQueuePointer queue_pointer);
+
+ ~ThrottleImpl() override;
+
+ // Throttle:
+ bool IsBlocked() const override;
+ RequestPriority Priority() const override;
+ void SetPriority(RequestPriority priority) override;
+
+ State state() const { return state_; }
+
+ ThrottleListQueuePointer queue_pointer() const { return queue_pointer_; }
+ void set_queue_pointer(const ThrottleListQueuePointer& pointer) {
+ if (state_ != State::AGED)
+ DCHECK_EQ(this, *pointer);
+ queue_pointer_ = pointer;
+ }
+
+ void set_start_time(base::TimeTicks start_time) { start_time_ = start_time; }
+ base::TimeTicks start_time() const { return start_time_; }
+
+ // Change the throttle's state to AGED. The previous
+ // state must be OUTSTANDING.
+ void SetAged();
+
+ // Note that this call calls the delegate, and hence may result in
+ // re-entrant calls into the manager or ThrottleImpl. The manager should
+ // not rely on any state other than its own existence being persistent
+ // across this call.
+ void NotifyUnblocked();
+
+ private:
+ State state_;
+ RequestPriority priority_;
+ ThrottleDelegate* const delegate_;
+ NetworkThrottleManagerImpl* const manager_;
+
+ base::TimeTicks start_time_;
+
+ // To allow deletion from the blocked queue (when the throttle is in the
+ // blocked queue).
+ ThrottleListQueuePointer queue_pointer_;
+
+ DISALLOW_COPY_AND_ASSIGN(ThrottleImpl);
+};
+
+NetworkThrottleManagerImpl::ThrottleImpl::ThrottleImpl(
+ bool blocked,
+ RequestPriority priority,
+ NetworkThrottleManager::ThrottleDelegate* delegate,
+ NetworkThrottleManagerImpl* manager,
+ ThrottleListQueuePointer queue_pointer)
+ : state_(blocked ? State::BLOCKED : State::OUTSTANDING),
+ priority_(priority),
+ delegate_(delegate),
+ manager_(manager),
+ queue_pointer_(queue_pointer) {
+ DCHECK(delegate);
+ if (!blocked)
+ start_time_ = manager->tick_clock_->NowTicks();
+}
+
+NetworkThrottleManagerImpl::ThrottleImpl::~ThrottleImpl() {
+ manager_->OnThrottleDestroyed(this);
+}
+
+bool NetworkThrottleManagerImpl::ThrottleImpl::IsBlocked() const {
+ return state_ == State::BLOCKED;
+}
+
+RequestPriority NetworkThrottleManagerImpl::ThrottleImpl::Priority() const {
+ return priority_;
+}
+
+void NetworkThrottleManagerImpl::ThrottleImpl::SetPriority(
+ RequestPriority new_priority) {
+ RequestPriority old_priority(priority_);
+ if (old_priority == new_priority)
+ return;
+ priority_ = new_priority;
+ manager_->OnThrottlePriorityChanged(this, old_priority, new_priority);
+}
+
+void NetworkThrottleManagerImpl::ThrottleImpl::SetAged() {
+ DCHECK_EQ(State::OUTSTANDING, state_);
+ state_ = State::AGED;
+}
+
+void NetworkThrottleManagerImpl::ThrottleImpl::NotifyUnblocked() {
+ // This method should only be called once, and only if the
+ // current state is blocked.
+ DCHECK_EQ(State::BLOCKED, state_);
+ state_ = State::OUTSTANDING;
+ delegate_->OnThrottleUnblocked(this);
+}
+
+NetworkThrottleManagerImpl::NetworkThrottleManagerImpl()
+ : lifetime_median_estimate_(PercentileEstimator::kMedianPercentile,
+ kInitialMedianInMs),
+ outstanding_recomputation_timer_(false /* retain_user_task */,
+ false /* is_repeating */),
+ tick_clock_(new base::DefaultTickClock()),
+ weak_ptr_factory_(this) {
+ outstanding_recomputation_timer_.SetTaskRunner(
+ base::ThreadTaskRunnerHandle::Get());
+}
+
+NetworkThrottleManagerImpl::~NetworkThrottleManagerImpl() {}
+
+std::unique_ptr<NetworkThrottleManager::Throttle>
+NetworkThrottleManagerImpl::CreateThrottle(
+ NetworkThrottleManager::ThrottleDelegate* delegate,
+ RequestPriority priority,
+ bool ignore_limits) {
+ bool blocked =
+ (!ignore_limits && priority == THROTTLED &&
+ outstanding_throttles_.size() >= kActiveRequestThrottlingLimit);
+
+ std::unique_ptr<NetworkThrottleManagerImpl::ThrottleImpl> throttle(
+ new ThrottleImpl(blocked, priority, delegate, this,
+ blocked_throttles_.end()));
+
+ ThrottleList& insert_list(blocked ? blocked_throttles_
+ : outstanding_throttles_);
+
+ throttle->set_queue_pointer(
+ insert_list.insert(insert_list.end(), throttle.get()));
+
+ // In case oustanding_throttles_ was empty, set up timer.
+ if (!blocked)
+ RecomputeOutstanding();
+
+ return std::move(throttle);
+}
+
+void NetworkThrottleManagerImpl::SetTickClockForTesting(
+ std::unique_ptr<base::TickClock> tick_clock) {
+ tick_clock_ = std::move(tick_clock);
+}
+
+bool NetworkThrottleManagerImpl::ConditionallyTriggerTimerForTesting() {
+ if (!outstanding_recomputation_timer_.IsRunning() ||
+ (tick_clock_->NowTicks() <
+ outstanding_recomputation_timer_.desired_run_time())) {
+ return false;
+ }
+
+ base::Closure timer_callback(outstanding_recomputation_timer_.user_task());
+ outstanding_recomputation_timer_.Stop();
+ timer_callback.Run();
+ return true;
+}
+
+void NetworkThrottleManagerImpl::OnThrottlePriorityChanged(
+ NetworkThrottleManagerImpl::ThrottleImpl* throttle,
+ RequestPriority old_priority,
+ RequestPriority new_priority) {
+ // The only case requiring a state change is if the priority change
+ // implies unblocking, which can only happen on a transition from blocked
+ // (implies THROTTLED) to non-THROTTLED.
+ if (throttle->IsBlocked() && new_priority != THROTTLED) {
+ // May result in re-entrant calls into this class.
+ UnblockThrottle(throttle);
+ }
+}
+
+void NetworkThrottleManagerImpl::OnThrottleDestroyed(ThrottleImpl* throttle) {
+ switch (throttle->state()) {
+ case ThrottleImpl::State::BLOCKED:
+ DCHECK(throttle->queue_pointer() != blocked_throttles_.end());
+ DCHECK_EQ(throttle, *(throttle->queue_pointer()));
+ blocked_throttles_.erase(throttle->queue_pointer());
+ break;
+ case ThrottleImpl::State::OUTSTANDING:
+ DCHECK(throttle->queue_pointer() != outstanding_throttles_.end());
+ DCHECK_EQ(throttle, *(throttle->queue_pointer()));
+ outstanding_throttles_.erase(throttle->queue_pointer());
+ // Fall through
+ case ThrottleImpl::State::AGED:
+ DCHECK(!throttle->start_time().is_null());
+ lifetime_median_estimate_.AddSample(
+ (tick_clock_->NowTicks() - throttle->start_time())
+ .InMillisecondsRoundedUp());
+ break;
+ }
+
+ DCHECK(std::find(blocked_throttles_.begin(), blocked_throttles_.end(),
+ throttle) == blocked_throttles_.end());
+ DCHECK(std::find(outstanding_throttles_.begin(), outstanding_throttles_.end(),
+ throttle) == outstanding_throttles_.end());
+
+ // Unblock the throttles if there's some chance there's a throttle to
+ // unblock.
+ if (outstanding_throttles_.size() < kActiveRequestThrottlingLimit &&
+ !blocked_throttles_.empty()) {
+ // Via PostTask so there aren't upcalls from within destructors.
+ base::ThreadTaskRunnerHandle::Get()->PostTask(
+ FROM_HERE,
+ base::Bind(&NetworkThrottleManagerImpl::MaybeUnblockThrottles,
+ weak_ptr_factory_.GetWeakPtr()));
+ }
+}
+
+void NetworkThrottleManagerImpl::RecomputeOutstanding() {
+ // Remove all throttles that have aged out of the outstanding set.
+ base::TimeTicks now(tick_clock_->NowTicks());
+ base::TimeDelta age_horizon(base::TimeDelta::FromMilliseconds((
+ kMedianLifetimeMultiple * lifetime_median_estimate_.current_estimate())));
+ while (!outstanding_throttles_.empty()) {
+ ThrottleImpl* throttle = *outstanding_throttles_.begin();
+ if (throttle->start_time() + age_horizon >= now)
+ break;
+
+ outstanding_throttles_.erase(outstanding_throttles_.begin());
+ throttle->SetAged();
+ throttle->set_queue_pointer(outstanding_throttles_.end());
+ }
+
+ if (outstanding_throttles_.empty())
+ return;
+
+ // If the timer is already running, be conservative and leave it alone;
+ // the time for which it would be set will only be later than when it's
+ // currently set.
+ // This addresses, e.g., situations where a RecomputeOutstanding() races
+ // with a running timer which would unblock blocked throttles.
+ if (outstanding_recomputation_timer_.IsRunning())
+ return;
+
+ ThrottleImpl* first_throttle(*outstanding_throttles_.begin());
+ DCHECK_GE(first_throttle->start_time() + age_horizon, now);
+ outstanding_recomputation_timer_.Start(
+ FROM_HERE, ((first_throttle->start_time() + age_horizon) - now +
+ base::TimeDelta::FromMilliseconds(kTimerFudgeInMs)),
+ // Unretained use of |this| is safe because the timer is
+ // owned by this object, and will be torn down if this object
+ // is destroyed.
+ base::Bind(&NetworkThrottleManagerImpl::MaybeUnblockThrottles,
+ base::Unretained(this)));
+}
+
+void NetworkThrottleManagerImpl::UnblockThrottle(ThrottleImpl* throttle) {
+ DCHECK(throttle->IsBlocked());
+
+ blocked_throttles_.erase(throttle->queue_pointer());
+ throttle->set_start_time(tick_clock_->NowTicks());
+ throttle->set_queue_pointer(
+ outstanding_throttles_.insert(outstanding_throttles_.end(), throttle));
+
+ // Called in case |*throttle| was added to a null set.
+ RecomputeOutstanding();
+
+ // May result in re-entrant calls into this class.
+ throttle->NotifyUnblocked();
+}
+
+void NetworkThrottleManagerImpl::MaybeUnblockThrottles() {
+ RecomputeOutstanding();
+
+ while (outstanding_throttles_.size() < kActiveRequestThrottlingLimit &&
+ !blocked_throttles_.empty()) {
+ // NOTE: This call may result in reentrant calls into
+ // NetworkThrottleManagerImpl; no state should be assumed to be
+ // persistent across this call.
+ UnblockThrottle(blocked_throttles_.front());
+ }
+}
+
+} // namespace net
diff --git a/chromium/net/base/network_throttle_manager_impl.h b/chromium/net/base/network_throttle_manager_impl.h
new file mode 100644
index 00000000000..47afcc46ffa
--- /dev/null
+++ b/chromium/net/base/network_throttle_manager_impl.h
@@ -0,0 +1,152 @@
+// Copyright 2016 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.
+
+#ifndef NET_BASE_NETWORK_THROTTLE_MANAGER_IMPL_H_
+#define NET_BASE_NETWORK_THROTTLE_MANAGER_IMPL_H_
+
+#include <list>
+#include <memory>
+#include <set>
+
+#include "base/memory/weak_ptr.h"
+#include "base/time/tick_clock.h"
+#include "base/time/time.h"
+#include "base/timer/timer.h"
+#include "net/base/network_throttle_manager.h"
+#include "net/base/percentile_estimator.h"
+
+namespace net {
+
+// The NetworkThrottleManagerImpl implements the following semantics:
+// * All throttles of priority above THROTTLED are created unblocked.
+// * Throttles of priority THROTTLED are created unblocked, unless
+// there are |kActiveRequestThrottlingLimit| or more throttles active,
+// in which case they are created blocked.
+// When that condition is no longer true, throttles of priority
+// THROTTLED are unblocked, in FIFO order.
+// * Throttles that have been alive for more than |kMedianLifetimeMultiple|
+// times the current estimate of the throttle median lifetime do
+// not count against the |kActiveRequestThrottlingLimit| limit.
+class NET_EXPORT NetworkThrottleManagerImpl : public NetworkThrottleManager {
+ public:
+ // Maximum number of active requests before new THROTTLED throttles
+ // are created blocked. Throttles are unblocked as the active requests
+ // fall below this limit.
+ static const size_t kActiveRequestThrottlingLimit;
+
+ // Note that the following constants are implementation details exposed in the
+ // header file only for testing, and should not be relied on by consumers.
+
+ // Constants used for the running estimate of the median lifetime
+ // for throttles created by this class. That estimate is used to detect
+ // throttles that are "unusually old" and hence may represent hanging GETs
+ // or long-running streams. Such throttles should not be considered
+ // "active" for the purposes of determining whether THROTTLED throttles
+ // should be created in a blocked state.
+ // Note that the precise details of this algorithm aren't very important;
+ // specifically, if it takes a while for the median estimate to reach the
+ // "actual" median of a request stream, the consequence is either a bit more
+ // of a delay in unblocking THROTTLED requests or more THROTTLED requests
+ // being unblocked than would be ideal (i.e. performance tweaks at
+ // the margins).
+
+ // Multiple of the current median lifetime beyond which a throttle is
+ // considered "unusually old" and not considered in counting active
+ // requests. This is used instead of a percentile estimate because the goal
+ // is eliminating requests that are qualitatively different
+ // (e.g. hanging gets, streams), and the percentage of all requests
+ // that are in that category can vary greatly.
+ static const int kMedianLifetimeMultiple;
+
+ // The median lifetime estimate starts at class creation at
+ // |kInitialMedianInMs|.
+ static const int kInitialMedianInMs;
+
+ NetworkThrottleManagerImpl();
+ ~NetworkThrottleManagerImpl() override;
+
+ // NetworkThrottleManager:
+ std::unique_ptr<Throttle> CreateThrottle(ThrottleDelegate* delegate,
+ RequestPriority priority,
+ bool ignore_limits) override;
+
+ void SetTickClockForTesting(std::unique_ptr<base::TickClock> tick_clock);
+
+ // If the |NowTicks()| value of |tick_clock_| is greater than the
+ // time the outstanding_recomputation_timer_ has set to go off, Stop()
+ // the timer and manually run the associated user task. This is to allow
+ // "fast-forwarding" of the clock for testing by working around
+ // base::Timer's direct use of base::TimeTicks rather than a base::TickClock.
+ //
+ // Note specifically that base::Timer::Start takes a time delta into the
+ // future and adds it to base::TimeTicks::Now() to get
+ // base::Timer::desired_run_time(), which is what this method compares
+ // |tick_clock_->NowTicks()| against. So tests should be written so that
+ // the timer Start() routine whose callback should be run is called
+ // with |tick_clock_| in accord with wallclock time. This routine can then
+ // be called with |tick_clock_| set into the future.
+ //
+ // Returns true if there was a timer running and it was triggerred
+ // (|tick_clock_->NowTicks() >
+ // outstanding_recomputation_timer_.desired_run_time()|).
+ bool ConditionallyTriggerTimerForTesting();
+
+ private:
+ class ThrottleImpl;
+ using ThrottleList = std::list<ThrottleImpl*>;
+
+ void OnThrottlePriorityChanged(ThrottleImpl* throttle,
+ RequestPriority old_priority,
+ RequestPriority new_priority);
+ void OnThrottleDestroyed(ThrottleImpl* throttle);
+
+ // Recompute how many requests count as outstanding (i.e.
+ // are not older than kMedianLifetimeMultiple * MedianThrottleLifetime()).
+ // If outstanding_recomputation_timer_ is not set, it will be set
+ // to the earliest a throttle might "age out" of the outstanding list.
+ void RecomputeOutstanding();
+
+ // Unblock the specified throttle. May result in re-entrant calls
+ // into NetworkThrottleManagerImpl.
+ void UnblockThrottle(ThrottleImpl* throttle);
+
+ // Recomputes how many requests count as outstanding, checks to see
+ // if any currently blocked throttles should be unblocked,
+ // and unblock them if so. Note that unblocking may result in
+ // re-entrant calls to this class, so no assumptions about state persistence
+ // should be made across this call.
+ void MaybeUnblockThrottles();
+
+ PercentileEstimator lifetime_median_estimate_;
+
+ // base::Timer controlling outstanding request recomputation.
+ //
+ // This is started whenever it is not running and a new throttle is
+ // added to |outstanding_throttles_|, and is never cleared except by
+ // execution, which re-starts it if there are any
+ // outstanding_throttles_. So it should always be running if any
+ // throttles are outstanding. This guarantees that the class will
+ // eventually detect aging out of outstanding throttles and unblock
+ // throttles blocked on those outstanding throttles.
+ base::Timer outstanding_recomputation_timer_;
+
+ // FIFO of OUTSTANDING throttles (ordered by time of entry into the
+ // OUTSTANDING state).
+ ThrottleList outstanding_throttles_;
+
+ // FIFO list of BLOCKED throttles. This is a list so that the
+ // throttles can store iterators to themselves.
+ ThrottleList blocked_throttles_;
+
+ // For testing.
+ std::unique_ptr<base::TickClock> tick_clock_;
+
+ base::WeakPtrFactory<NetworkThrottleManagerImpl> weak_ptr_factory_;
+
+ DISALLOW_COPY_AND_ASSIGN(NetworkThrottleManagerImpl);
+};
+
+} // namespace net
+
+#endif // NET_BASE_NETWORK_THROTTLE_MANAGER_IMPL_H_
diff --git a/chromium/net/base/network_throttle_manager_impl_unittest.cc b/chromium/net/base/network_throttle_manager_impl_unittest.cc
new file mode 100644
index 00000000000..bc672b2c679
--- /dev/null
+++ b/chromium/net/base/network_throttle_manager_impl_unittest.cc
@@ -0,0 +1,568 @@
+// Copyright 2016 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.
+
+#include "net/base/network_throttle_manager_impl.h"
+
+#include <memory>
+
+#include "base/bind.h"
+#include "base/callback.h"
+#include "base/callback_helpers.h"
+#include "base/memory/scoped_vector.h"
+#include "base/run_loop.h"
+#include "base/test/simple_test_tick_clock.h"
+#include "base/test/test_message_loop.h"
+#include "net/base/request_priority.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace net {
+
+namespace {
+
+#include "testing/gtest/include/gtest/gtest.h"
+
+const int kInitialAgeHorizonForUncountedRequests =
+ (NetworkThrottleManagerImpl::kInitialMedianInMs *
+ NetworkThrottleManagerImpl::kMedianLifetimeMultiple);
+
+// Must be greater than the corresponding fudge factor in
+// network_throttle_manager_impl.cc.
+const int kAgeHorizonFudgeFactor = 20;
+
+// Test fixture for throttle manager tests.
+
+// Note that the manager owned and managed by this fixture has a clock
+// that is set to base::TimeTicks::Now() (which value is also exposed
+// via an accessor) on creation but does not change without
+// intervention by tests (to make the tests more predictable).
+//
+// HOWEVER, also note that that manager uses the base::Timer class, which
+// uses the system clock, which isn't affected by the setting of the
+// test fixture clock. So test should be written to a) avoid situations
+// in which the manager's timer will actually go off based on the system
+// clock, and b) call ConditionallyTriggerTimerForTesting() (which does
+// evaluate the manager's clock) when timer based tests are necessary.
+class NetworkThrottleManagerTest : public testing::Test,
+ NetworkThrottleManager::ThrottleDelegate {
+ public:
+ NetworkThrottleManagerTest()
+ : clock_(new base::SimpleTestTickClock),
+ now_(base::TimeTicks::Now()),
+ throttle_state_change_count_(0),
+ last_throttle_to_change_state_(nullptr),
+ throttle_manager_(new NetworkThrottleManagerImpl) {
+ clock_->SetNowTicks(now_);
+ throttle_manager_->SetTickClockForTesting(
+ std::unique_ptr<base::TickClock>(clock_));
+ }
+
+ protected:
+ enum ExpectedThrottleBlockState { BLOCKED, UNBLOCKED };
+
+ base::TimeTicks now() { return now_; }
+ NetworkThrottleManagerImpl* throttle_manager() {
+ return throttle_manager_.get();
+ }
+
+ // Set the offset of the test clock from now_.
+ void SetClockDelta(base::TimeDelta time_delta) {
+ clock_->SetNowTicks(now_ + time_delta);
+ }
+
+ // Throttle creation
+ std::unique_ptr<NetworkThrottleManager::Throttle> CreateThrottle(
+ net::RequestPriority priority,
+ ExpectedThrottleBlockState throttle_state) {
+ std::unique_ptr<NetworkThrottleManager::Throttle> throttle(
+ throttle_manager_->CreateThrottle(this, priority, false));
+ EXPECT_EQ(throttle_state == BLOCKED, throttle->IsBlocked());
+ return throttle;
+ }
+ std::unique_ptr<NetworkThrottleManager::Throttle>
+ CreateThrottleIgnoringLimits(net::RequestPriority priority) {
+ std::unique_ptr<NetworkThrottleManager::Throttle> throttle(
+ throttle_manager_->CreateThrottle(this, priority, true));
+ EXPECT_FALSE(throttle->IsBlocked());
+ return throttle;
+ }
+
+ // Throttle state change information.
+ int throttle_state_change_count() { return throttle_state_change_count_; }
+ NetworkThrottleManager::Throttle* last_throttle_to_change_state() {
+ return last_throttle_to_change_state_;
+ }
+
+ // Setting a callback to be invoked when a throttle's state changes.
+ void SetThrottleStateChangedCallback(const base::Closure& callback) {
+ throttle_state_changed_callback_ = callback;
+ }
+
+ private:
+ // NetworkThrottleManager::Delegate
+ void OnThrottleUnblocked(
+ NetworkThrottleManager::Throttle* throttle) override {
+ ++throttle_state_change_count_;
+ last_throttle_to_change_state_ = throttle;
+ if (!throttle_state_changed_callback_.is_null())
+ base::ResetAndReturn(&throttle_state_changed_callback_).Run();
+ }
+
+ base::SimpleTestTickClock* clock_;
+ base::TimeTicks now_;
+ int throttle_state_change_count_;
+ NetworkThrottleManager::Throttle* last_throttle_to_change_state_;
+ std::unique_ptr<NetworkThrottleManagerImpl> throttle_manager_;
+ base::Closure throttle_state_changed_callback_;
+
+ DISALLOW_COPY_AND_ASSIGN(NetworkThrottleManagerTest);
+};
+
+// Check to confirm that all created throttles at priorities other than
+// THROTTLED start unblocked.
+TEST_F(NetworkThrottleManagerTest, AllUnthrottled) {
+ for (int i = MINIMUM_PRIORITY; i <= MAXIMUM_PRIORITY; ++i) {
+ if (i == THROTTLED)
+ continue;
+ CreateThrottle(static_cast<RequestPriority>(i), UNBLOCKED);
+ }
+}
+
+// Check for basic semantics around the new THROTTLED level.
+TEST_F(NetworkThrottleManagerTest, ThrottledBlocking) {
+ std::unique_ptr<NetworkThrottleManager::Throttle> throttle1(
+ CreateThrottle(THROTTLED, UNBLOCKED));
+ std::unique_ptr<NetworkThrottleManager::Throttle> throttle2(
+ CreateThrottle(THROTTLED, UNBLOCKED));
+ std::unique_ptr<NetworkThrottleManager::Throttle> throttle3(
+ CreateThrottle(THROTTLED, BLOCKED));
+ std::unique_ptr<NetworkThrottleManager::Throttle> throttle4(
+ CreateThrottle(THROTTLED, BLOCKED));
+ std::unique_ptr<NetworkThrottleManager::Throttle> throttle5(
+ CreateThrottle(THROTTLED, BLOCKED));
+
+ EXPECT_EQ(0, throttle_state_change_count());
+
+ throttle1.reset();
+ base::RunLoop().RunUntilIdle(); // Allow posttasks to run.
+ EXPECT_EQ(1, throttle_state_change_count());
+ EXPECT_EQ(throttle3.get(), last_throttle_to_change_state());
+
+ EXPECT_FALSE(throttle3->IsBlocked());
+ EXPECT_TRUE(throttle4->IsBlocked());
+ EXPECT_TRUE(throttle5->IsBlocked());
+
+ throttle2.reset();
+ base::RunLoop().RunUntilIdle(); // Allow posttasks to run.
+ EXPECT_EQ(2, throttle_state_change_count());
+ EXPECT_EQ(throttle4.get(), last_throttle_to_change_state());
+
+ EXPECT_FALSE(throttle3->IsBlocked());
+ EXPECT_FALSE(throttle4->IsBlocked());
+ EXPECT_TRUE(throttle5->IsBlocked());
+}
+
+// Check that THROTTLED semantics are dependent on all outstanding requests.
+TEST_F(NetworkThrottleManagerTest, ThrottledBlockingMultiPriority) {
+ std::unique_ptr<NetworkThrottleManager::Throttle> throttle1(
+ CreateThrottle(HIGHEST, UNBLOCKED));
+ std::unique_ptr<NetworkThrottleManager::Throttle> throttle2(
+ CreateThrottle(LOW, UNBLOCKED));
+ std::unique_ptr<NetworkThrottleManager::Throttle> throttle3(
+ CreateThrottle(IDLE, UNBLOCKED));
+ std::unique_ptr<NetworkThrottleManager::Throttle> throttle4(
+ CreateThrottle(THROTTLED, BLOCKED));
+ std::unique_ptr<NetworkThrottleManager::Throttle> throttle5(
+ CreateThrottle(THROTTLED, BLOCKED));
+
+ EXPECT_EQ(0, throttle_state_change_count());
+
+ throttle1.reset();
+ base::RunLoop().RunUntilIdle(); // Allow posttasks to run.
+ EXPECT_EQ(0, throttle_state_change_count());
+ EXPECT_FALSE(throttle3->IsBlocked());
+ EXPECT_TRUE(throttle4->IsBlocked());
+ EXPECT_TRUE(throttle5->IsBlocked());
+
+ throttle2.reset();
+ base::RunLoop().RunUntilIdle(); // Allow posttasks to run.
+ EXPECT_EQ(1, throttle_state_change_count());
+ EXPECT_EQ(throttle4.get(), last_throttle_to_change_state());
+
+ EXPECT_FALSE(throttle3->IsBlocked());
+ EXPECT_FALSE(throttle4->IsBlocked());
+ EXPECT_TRUE(throttle5->IsBlocked());
+
+ throttle3.reset();
+ base::RunLoop().RunUntilIdle(); // Allow posttasks to run.
+ EXPECT_EQ(2, throttle_state_change_count());
+ EXPECT_EQ(throttle5.get(), last_throttle_to_change_state());
+
+ EXPECT_FALSE(throttle4->IsBlocked());
+ EXPECT_FALSE(throttle5->IsBlocked());
+}
+
+// Check that a SetPriority() away from THROTTLED results in unblocking
+// and an upcall.
+TEST_F(NetworkThrottleManagerTest, ThrottledSetPriority) {
+ std::unique_ptr<NetworkThrottleManager::Throttle> throttle1(
+ CreateThrottle(THROTTLED, UNBLOCKED));
+ std::unique_ptr<NetworkThrottleManager::Throttle> throttle2(
+ CreateThrottle(THROTTLED, UNBLOCKED));
+ std::unique_ptr<NetworkThrottleManager::Throttle> throttle3(
+ CreateThrottle(THROTTLED, BLOCKED));
+ std::unique_ptr<NetworkThrottleManager::Throttle> throttle4(
+ CreateThrottle(THROTTLED, BLOCKED));
+
+ EXPECT_EQ(0, throttle_state_change_count());
+
+ throttle3->SetPriority(LOW);
+ EXPECT_EQ(1, throttle_state_change_count());
+ EXPECT_EQ(throttle3.get(), last_throttle_to_change_state());
+ EXPECT_FALSE(throttle3->IsBlocked());
+ EXPECT_TRUE(throttle4->IsBlocked());
+}
+
+void ResetThrottles(bool* function_called,
+ ScopedVector<NetworkThrottleManager::Throttle> throttles) {
+ *function_called = true;
+ // All pointers in the vector should be deleted on exit.
+}
+
+// Check that tearing down all elements in the NTM on a SetPriority
+// upcall doesn't create any problems.
+TEST_F(NetworkThrottleManagerTest, ThrottleTeardown) {
+ ScopedVector<NetworkThrottleManager::Throttle> throttles;
+ std::unique_ptr<NetworkThrottleManager::Throttle> throttle_temporary;
+
+ throttles.push_back(std::unique_ptr<NetworkThrottleManager::Throttle>(
+ CreateThrottle(THROTTLED, UNBLOCKED)));
+ throttles.push_back(std::unique_ptr<NetworkThrottleManager::Throttle>(
+ CreateThrottle(THROTTLED, UNBLOCKED)));
+
+ // Note that if there is more than one throttle blocked, then the
+ // number of throttle state changes is dependent on destruction order.
+ // So only one blocked throttle is created.
+ throttle_temporary = CreateThrottle(THROTTLED, BLOCKED);
+ NetworkThrottleManager::Throttle* throttle3 = throttle_temporary.get();
+ throttles.push_back(std::move(throttle_temporary));
+
+ bool callback_called(false);
+ SetThrottleStateChangedCallback(
+ base::Bind(&ResetThrottles, &callback_called, base::Passed(&throttles)));
+
+ EXPECT_EQ(0, throttle_state_change_count());
+
+ throttle3->SetPriority(LOW);
+
+ // If the test is functioning as expected, throttle3 now points to
+ // a deleted object and can no longer be indirected through.
+
+ EXPECT_TRUE(callback_called);
+ EXPECT_EQ(1, throttle_state_change_count());
+ EXPECT_EQ(throttle3, last_throttle_to_change_state());
+}
+
+// Note that this routine is dependent on priority setting *not* resulting in
+// destruction of any throttle and should only be used in tests where that is
+// true.
+void SetAllToPriority(
+ RequestPriority priority,
+ std::vector<NetworkThrottleManager::Throttle*> throttles) {
+ for (size_t i = 0; i < throttles.size(); ++i)
+ throttles[i]->SetPriority(priority);
+}
+
+// Check that modifying all the priorities of the allocated throttles in
+// the callback works properly.
+TEST_F(NetworkThrottleManagerTest, ThrottlePriorityReset) {
+ std::unique_ptr<NetworkThrottleManager::Throttle> throttle1(
+ CreateThrottle(THROTTLED, UNBLOCKED));
+ std::unique_ptr<NetworkThrottleManager::Throttle> throttle2(
+ CreateThrottle(THROTTLED, UNBLOCKED));
+ std::unique_ptr<NetworkThrottleManager::Throttle> throttle3(
+ CreateThrottle(THROTTLED, BLOCKED));
+ std::unique_ptr<NetworkThrottleManager::Throttle> throttle4(
+ CreateThrottle(THROTTLED, BLOCKED));
+
+ std::vector<NetworkThrottleManager::Throttle*> throttles;
+ throttles.push_back(throttle1.get());
+ throttles.push_back(throttle2.get());
+ throttles.push_back(throttle3.get());
+
+ SetThrottleStateChangedCallback(
+ base::Bind(&SetAllToPriority, MEDIUM, base::Passed(&throttles)));
+
+ EXPECT_EQ(0, throttle_state_change_count());
+ throttle3->SetPriority(HIGHEST);
+
+ // Expected result: throttles 1-3 @ medium priority (the callback should
+ // have overridden the priority setting above), only throttle 4 blocked
+ // (throttle3 should have been unblocked by either of the priority changes),
+ // and one state changes (the unblocking).
+ EXPECT_EQ(MEDIUM, throttle1->Priority());
+ EXPECT_EQ(MEDIUM, throttle2->Priority());
+ EXPECT_EQ(MEDIUM, throttle3->Priority());
+ EXPECT_EQ(THROTTLED, throttle4->Priority());
+ EXPECT_FALSE(throttle1->IsBlocked());
+ EXPECT_FALSE(throttle2->IsBlocked());
+ EXPECT_FALSE(throttle3->IsBlocked());
+ EXPECT_TRUE(throttle4->IsBlocked());
+ EXPECT_EQ(1, throttle_state_change_count());
+}
+
+// Check that modifying the priority of a request from a non-THROTTLED
+// value to THROTTLED causes no change in behavior.
+TEST_F(NetworkThrottleManagerTest, ThrottlePriorityResetToThrottled) {
+ std::unique_ptr<NetworkThrottleManager::Throttle> throttle1(
+ CreateThrottle(THROTTLED, UNBLOCKED));
+ std::unique_ptr<NetworkThrottleManager::Throttle> throttle2(
+ CreateThrottle(THROTTLED, UNBLOCKED));
+ std::unique_ptr<NetworkThrottleManager::Throttle> throttle3(
+ CreateThrottle(LOW, UNBLOCKED));
+ std::unique_ptr<NetworkThrottleManager::Throttle> throttle4(
+ CreateThrottle(THROTTLED, BLOCKED));
+
+ EXPECT_EQ(0, throttle_state_change_count());
+ throttle3->SetPriority(THROTTLED);
+ EXPECT_EQ(0, throttle_state_change_count());
+
+ EXPECT_FALSE(throttle1->IsBlocked());
+ EXPECT_FALSE(throttle2->IsBlocked());
+ EXPECT_FALSE(throttle3->IsBlocked());
+ EXPECT_TRUE(throttle4->IsBlocked());
+
+ EXPECT_EQ(THROTTLED, throttle1->Priority());
+ EXPECT_EQ(THROTTLED, throttle2->Priority());
+ EXPECT_EQ(THROTTLED, throttle3->Priority());
+ EXPECT_EQ(THROTTLED, throttle4->Priority());
+}
+
+// Confirm that old requests don't count against the limit.
+TEST_F(NetworkThrottleManagerTest, DontCountAgedRequests) {
+ const int age_in_days_of_old_throttles = 4;
+
+ // Confirm default median and timing means that 4 days is long enough ago
+ // to be aged out.
+ EXPECT_GT(age_in_days_of_old_throttles * 24 * 60 * 60 * 1000,
+ kInitialAgeHorizonForUncountedRequests);
+
+ SetClockDelta(-base::TimeDelta::FromDays(age_in_days_of_old_throttles));
+ std::unique_ptr<NetworkThrottleManager::Throttle> throttle1(
+ CreateThrottle(IDLE, UNBLOCKED));
+ std::unique_ptr<NetworkThrottleManager::Throttle> throttle2(
+ CreateThrottle(IDLE, UNBLOCKED));
+
+ SetClockDelta(base::TimeDelta());
+ std::unique_ptr<NetworkThrottleManager::Throttle> throttle3(
+ CreateThrottle(LOW, UNBLOCKED));
+
+ // First throttled request should not be blocked.
+ std::unique_ptr<NetworkThrottleManager::Throttle> throttle4(
+ CreateThrottle(THROTTLED, UNBLOCKED));
+
+ // Second should be.
+ std::unique_ptr<NetworkThrottleManager::Throttle> throttle5(
+ CreateThrottle(THROTTLED, BLOCKED));
+
+ // Destroying the old requests should not result in any upcalls.
+ EXPECT_EQ(0, throttle_state_change_count());
+ throttle1.reset();
+ base::RunLoop().RunUntilIdle(); // Allow posttasks to run.
+ EXPECT_EQ(0, throttle_state_change_count());
+ throttle2.reset();
+ base::RunLoop().RunUntilIdle(); // Allow posttasks to run.
+ EXPECT_EQ(0, throttle_state_change_count());
+
+ // But destroying a new request should result in a state change.
+ throttle3.reset();
+ base::RunLoop().RunUntilIdle(); // Allow posttasks to run.
+ EXPECT_EQ(1, throttle_state_change_count());
+ EXPECT_EQ(throttle5.get(), last_throttle_to_change_state());
+}
+
+// Confirm that a slew of throttles of a specific age will shift the
+// median for determining "aged requests" to that age.
+TEST_F(NetworkThrottleManagerTest, ShiftMedian) {
+ // Setup two throttles of age *just short* of aging out; confirm
+ // they result in blocked THROTTLED requests.
+ std::unique_ptr<NetworkThrottleManager::Throttle> throttle1(
+ CreateThrottle(IDLE, UNBLOCKED));
+ std::unique_ptr<NetworkThrottleManager::Throttle> throttle2(
+ CreateThrottle(IDLE, UNBLOCKED));
+ SetClockDelta(base::TimeDelta::FromMilliseconds(
+ kInitialAgeHorizonForUncountedRequests - 1));
+ EXPECT_FALSE(throttle_manager()->ConditionallyTriggerTimerForTesting());
+
+ std::unique_ptr<NetworkThrottleManager::Throttle> throttle3(
+ CreateThrottle(THROTTLED, BLOCKED));
+
+ throttle1.reset();
+ throttle2.reset();
+ throttle3.reset();
+ base::RunLoop().RunUntilIdle(); // Allow posttasks to run.
+
+ // Create 100 throttles and destroy them, effectively with lifetime zero.
+ // This should substantially decrease the median age estimate.
+ SetClockDelta(base::TimeDelta());
+ for (int i = 0; i < 100; ++i) {
+ std::unique_ptr<NetworkThrottleManager::Throttle> tmp(
+ CreateThrottle(IDLE, UNBLOCKED));
+ }
+
+ // Clear out any possible leftover timer by setting the clock to a point
+ // in the future at which it will definitely go off, and triggering it.
+ SetClockDelta(base::TimeDelta::FromMilliseconds(
+ 2 * kInitialAgeHorizonForUncountedRequests + kAgeHorizonFudgeFactor));
+ throttle_manager()->ConditionallyTriggerTimerForTesting();
+
+ // The identical test above should no longer result in blocked throttles.
+ SetClockDelta(base::TimeDelta());
+ std::unique_ptr<NetworkThrottleManager::Throttle> throttle5(
+ CreateThrottle(IDLE, UNBLOCKED));
+ std::unique_ptr<NetworkThrottleManager::Throttle> throttle6(
+ CreateThrottle(IDLE, UNBLOCKED));
+ SetClockDelta(base::TimeDelta::FromMilliseconds(
+ kInitialAgeHorizonForUncountedRequests - 1));
+ EXPECT_TRUE(throttle_manager()->ConditionallyTriggerTimerForTesting());
+ std::unique_ptr<NetworkThrottleManager::Throttle> throttle7(
+ CreateThrottle(THROTTLED, UNBLOCKED));
+}
+
+// Confirm that just "aging out" requests will result in unblocking
+// blocked requests.
+TEST_F(NetworkThrottleManagerTest, AgeInvalidThrottles) {
+ std::unique_ptr<NetworkThrottleManager::Throttle> throttle1(
+ CreateThrottle(IDLE, UNBLOCKED));
+ std::unique_ptr<NetworkThrottleManager::Throttle> throttle2(
+ CreateThrottle(IDLE, UNBLOCKED));
+ std::unique_ptr<NetworkThrottleManager::Throttle> throttle3(
+ CreateThrottle(THROTTLED, BLOCKED));
+
+ EXPECT_EQ(0, throttle_state_change_count());
+ SetClockDelta(base::TimeDelta::FromMilliseconds(
+ kInitialAgeHorizonForUncountedRequests + kAgeHorizonFudgeFactor));
+ EXPECT_TRUE(throttle_manager()->ConditionallyTriggerTimerForTesting());
+ EXPECT_EQ(1, throttle_state_change_count());
+ EXPECT_EQ(throttle3.get(), last_throttle_to_change_state());
+ EXPECT_FALSE(throttle3->IsBlocked());
+}
+
+// Confirm that if throttles are unblocked and made active by all
+// existing outstanding throttles aging out, they will also eventually
+// age out and let new throttles through.
+TEST_F(NetworkThrottleManagerTest, NewlyUnblockedThrottlesAlsoAge) {
+ std::unique_ptr<NetworkThrottleManager::Throttle> throttle1(
+ CreateThrottle(IDLE, UNBLOCKED));
+ std::unique_ptr<NetworkThrottleManager::Throttle> throttle2(
+ CreateThrottle(IDLE, UNBLOCKED));
+ std::unique_ptr<NetworkThrottleManager::Throttle> throttle3(
+ CreateThrottle(THROTTLED, BLOCKED));
+ std::unique_ptr<NetworkThrottleManager::Throttle> throttle4(
+ CreateThrottle(THROTTLED, BLOCKED));
+ std::unique_ptr<NetworkThrottleManager::Throttle> throttle5(
+ CreateThrottle(THROTTLED, BLOCKED));
+ std::unique_ptr<NetworkThrottleManager::Throttle> throttle6(
+ CreateThrottle(THROTTLED, BLOCKED));
+
+ // Age the first two throttles out of the outstanding, which should
+ // result in the next two throttles becoming unblocked (and in the
+ // oustanding list). (The internal implementation will zero out
+ // the outstanding queue and then add in the two new unblocked throttles.)
+ EXPECT_EQ(0, throttle_state_change_count());
+ SetClockDelta(base::TimeDelta::FromMilliseconds(
+ kInitialAgeHorizonForUncountedRequests + kAgeHorizonFudgeFactor));
+ EXPECT_TRUE(throttle_manager()->ConditionallyTriggerTimerForTesting());
+ EXPECT_EQ(2, throttle_state_change_count());
+ EXPECT_FALSE(throttle3->IsBlocked());
+ EXPECT_FALSE(throttle4->IsBlocked());
+
+ // Age the next two throttles out of the outstanding queue, which
+ // should result in the next two throttles becoming unblocked (and
+ // in the oustanding list). This will only happen if a timer was properly
+ // set in the above age process as the oustanding queue went through
+ // the empty state.
+ SetClockDelta(base::TimeDelta::FromMilliseconds(
+ 2 * (kInitialAgeHorizonForUncountedRequests + kAgeHorizonFudgeFactor)));
+ EXPECT_TRUE(throttle_manager()->ConditionallyTriggerTimerForTesting());
+ EXPECT_EQ(4, throttle_state_change_count());
+ EXPECT_FALSE(throttle5->IsBlocked());
+ EXPECT_FALSE(throttle6->IsBlocked());
+}
+
+// Confirm that throttles that are blocked for a while and then
+// unblocked don't "age out".
+TEST_F(NetworkThrottleManagerTest, AgeBlockedThrottles) {
+ std::unique_ptr<NetworkThrottleManager::Throttle> throttle1(
+ CreateThrottle(IDLE, UNBLOCKED));
+ std::unique_ptr<NetworkThrottleManager::Throttle> throttle2(
+ CreateThrottle(IDLE, UNBLOCKED));
+ std::unique_ptr<NetworkThrottleManager::Throttle> throttle3(
+ CreateThrottle(THROTTLED, BLOCKED));
+ std::unique_ptr<NetworkThrottleManager::Throttle> throttle4(
+ CreateThrottle(THROTTLED, BLOCKED));
+ std::unique_ptr<NetworkThrottleManager::Throttle> throttle5(
+ CreateThrottle(THROTTLED, BLOCKED));
+
+ EXPECT_EQ(0, throttle_state_change_count());
+ SetClockDelta(base::TimeDelta::FromMilliseconds(
+ kInitialAgeHorizonForUncountedRequests + kAgeHorizonFudgeFactor));
+ EXPECT_TRUE(throttle_manager()->ConditionallyTriggerTimerForTesting());
+
+ // If blocked throttles aged out, all three throttles should have been
+ // unblocked. If not, only the two replacing the IDLE throttles should
+ // have.
+ EXPECT_EQ(2, throttle_state_change_count());
+}
+
+// Confirm that deleting old throttles before they age out doesn't
+// interfere with the aging out of more recent throttles.
+TEST_F(NetworkThrottleManagerTest, DeletionAgingInterference) {
+ std::unique_ptr<NetworkThrottleManager::Throttle> throttle1(
+ CreateThrottle(IDLE, UNBLOCKED));
+ std::unique_ptr<NetworkThrottleManager::Throttle> throttle2(
+ CreateThrottle(IDLE, UNBLOCKED));
+ std::unique_ptr<NetworkThrottleManager::Throttle> throttle3(
+ CreateThrottle(THROTTLED, BLOCKED));
+ EXPECT_EQ(0, throttle_state_change_count());
+
+ SetClockDelta(base::TimeDelta::FromMilliseconds(
+ kInitialAgeHorizonForUncountedRequests / 2));
+ std::unique_ptr<NetworkThrottleManager::Throttle> throttle4(
+ CreateThrottle(IDLE, UNBLOCKED));
+ std::unique_ptr<NetworkThrottleManager::Throttle> throttle5(
+ CreateThrottle(IDLE, UNBLOCKED));
+ EXPECT_FALSE(throttle_manager()->ConditionallyTriggerTimerForTesting());
+ EXPECT_EQ(0, throttle_state_change_count());
+
+ throttle1.reset();
+ throttle2.reset();
+ EXPECT_FALSE(throttle_manager()->ConditionallyTriggerTimerForTesting());
+ EXPECT_EQ(0, throttle_state_change_count());
+
+ SetClockDelta(base::TimeDelta::FromMilliseconds(
+ (3 * kInitialAgeHorizonForUncountedRequests / 2 +
+ 2 * kAgeHorizonFudgeFactor)));
+ EXPECT_TRUE(throttle_manager()->ConditionallyTriggerTimerForTesting());
+ EXPECT_EQ(1, throttle_state_change_count());
+ EXPECT_EQ(throttle3.get(), last_throttle_to_change_state());
+ EXPECT_FALSE(throttle3->IsBlocked());
+}
+
+// Confirm that "ignore_limits" boolean is respected.
+TEST_F(NetworkThrottleManagerTest, IgnoreLimits) {
+ std::unique_ptr<NetworkThrottleManager::Throttle> throttle1(
+ CreateThrottle(HIGHEST, UNBLOCKED));
+ std::unique_ptr<NetworkThrottleManager::Throttle> throttle2(
+ CreateThrottle(LOW, UNBLOCKED));
+ std::unique_ptr<NetworkThrottleManager::Throttle> throttle3(
+ CreateThrottle(IDLE, UNBLOCKED));
+ std::unique_ptr<NetworkThrottleManager::Throttle> throttle4(
+ CreateThrottle(THROTTLED, BLOCKED));
+ std::unique_ptr<NetworkThrottleManager::Throttle> throttle5(
+ CreateThrottleIgnoringLimits(THROTTLED));
+}
+
+} // namespace
+
+} // namespace net
diff --git a/chromium/net/base/openssl_private_key_store.h b/chromium/net/base/openssl_private_key_store.h
deleted file mode 100644
index ee4bc35f9bb..00000000000
--- a/chromium/net/base/openssl_private_key_store.h
+++ /dev/null
@@ -1,53 +0,0 @@
-// Copyright (c) 2010 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.
-
-#ifndef NET_BASE_OPENSSL_PRIVATE_KEY_STORE_H_
-#define NET_BASE_OPENSSL_PRIVATE_KEY_STORE_H_
-
-#include <vector>
-
-// Avoid including <openssl/evp.h>
-typedef struct evp_pkey_st EVP_PKEY;
-
-#include "base/macros.h"
-#include "net/base/net_export.h"
-
-class GURL;
-
-namespace net {
-
-class X509Certificate;
-
-// OpenSSLPrivateKeyStore provides an interface for storing
-// public/private key pairs to system storage on platforms where
-// OpenSSL is used.
-// This class shall only be used from the network thread.
-class NET_EXPORT OpenSSLPrivateKeyStore {
- public:
- // Called to permanently store a private/public key pair, generated
- // via <keygen> while visiting |url|, to an appropriate system
- // location. Increments |pkey|'s reference count, so the caller is still
- // responsible for calling EVP_PKEY_free on it.
- // |url| is the corresponding server URL.
- // |pkey| is the key pair handle.
- // Returns false if an error occurred whilst attempting to store the key.
- static bool StoreKeyPair(const GURL& url, EVP_PKEY* pkey);
-
- // Checks that the private key for a given public key is installed.
- // |pub_key| a public key.
- // Returns true if there is a private key that was previously
- // recorded through StoreKeyPair().
- // NOTE: Intentionally not implemented on Android because there is no
- // platform API that can perform this operation silently.
- static bool HasPrivateKey(EVP_PKEY* pub_key);
-
- private:
- OpenSSLPrivateKeyStore(); // not implemented.
- ~OpenSSLPrivateKeyStore(); // not implemented.
- DISALLOW_COPY_AND_ASSIGN(OpenSSLPrivateKeyStore);
-};
-
-} // namespace net
-
-#endif // NET_BASE_OPENSSL_PRIVATE_KEY_STORE_H_
diff --git a/chromium/net/base/openssl_private_key_store_android.cc b/chromium/net/base/openssl_private_key_store_android.cc
deleted file mode 100644
index 59cd8b0ffb4..00000000000
--- a/chromium/net/base/openssl_private_key_store_android.cc
+++ /dev/null
@@ -1,47 +0,0 @@
-// Copyright (c) 2012 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.
-
-#include "net/base/openssl_private_key_store.h"
-
-#include "base/logging.h"
-#include "base/memory/singleton.h"
-#include "crypto/openssl_util.h"
-#include "net/android/network_library.h"
-#include "third_party/boringssl/src/include/openssl/bytestring.h"
-#include "third_party/boringssl/src/include/openssl/evp.h"
-#include "third_party/boringssl/src/include/openssl/mem.h"
-
-namespace net {
-
-bool OpenSSLPrivateKeyStore::StoreKeyPair(const GURL& url, EVP_PKEY* pkey) {
- // Always clear openssl errors on exit.
- crypto::OpenSSLErrStackTracer err_trace(FROM_HERE);
-
- uint8_t* public_key;
- size_t public_len;
- bssl::ScopedCBB cbb;
- if (!CBB_init(cbb.get(), 0) || !EVP_marshal_public_key(cbb.get(), pkey) ||
- !CBB_finish(cbb.get(), &public_key, &public_len)) {
- return false;
- }
- bssl::UniquePtr<uint8_t> free_public_key(public_key);
-
- uint8_t* private_key;
- size_t private_len;
- cbb.Reset();
- if (!CBB_init(cbb.get(), 0) || !EVP_marshal_private_key(cbb.get(), pkey) ||
- !CBB_finish(cbb.get(), &private_key, &private_len)) {
- return false;
- }
- bssl::UniquePtr<uint8_t> free_private_key(private_key);
-
- if (!android::StoreKeyPair(public_key, public_len, private_key,
- private_len)) {
- LOG(ERROR) << "StoreKeyPair failed. public_len = " << public_len
- << " private_len = " << private_len;
- }
- return true;
-}
-
-} // namespace net
diff --git a/chromium/net/base/openssl_private_key_store_memory.cc b/chromium/net/base/openssl_private_key_store_memory.cc
deleted file mode 100644
index 5b86b1523c7..00000000000
--- a/chromium/net/base/openssl_private_key_store_memory.cc
+++ /dev/null
@@ -1,74 +0,0 @@
-// Copyright (c) 2011 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.
-
-// Defines an in-memory private key store, primarily used for testing.
-
-#include "net/base/openssl_private_key_store.h"
-
-#include "base/logging.h"
-#include "base/macros.h"
-#include "base/memory/singleton.h"
-#include "base/synchronization/lock.h"
-#include "third_party/boringssl/src/include/openssl/evp.h"
-
-namespace net {
-
-namespace {
-
-// A small in-memory store for public/private key pairs held in
-// a single EVP_PKEY object. This is intentionally distinct from
-// net::SSLClientKeyStore.
-class MemoryKeyPairStore {
- public:
- MemoryKeyPairStore() {}
-
- static MemoryKeyPairStore* GetInstance() {
- return base::Singleton<MemoryKeyPairStore>::get();
- }
-
- ~MemoryKeyPairStore() {
- base::AutoLock lock(lock_);
- for (std::vector<EVP_PKEY*>::iterator it = keys_.begin();
- it != keys_.end(); ++it) {
- EVP_PKEY_free(*it);
- }
- }
-
- bool StoreKeyPair(EVP_PKEY* pkey) {
- EVP_PKEY_up_ref(pkey);
- base::AutoLock lock(lock_);
- keys_.push_back(pkey);
- return true;
- }
-
- bool HasPrivateKey(EVP_PKEY* pkey) {
- base::AutoLock lock(lock_);
- for (std::vector<EVP_PKEY*>::iterator it = keys_.begin();
- it != keys_.end(); ++it) {
- if (EVP_PKEY_cmp(*it, pkey) == 1)
- return true;
- }
- return false;
- }
-
- private:
- std::vector<EVP_PKEY*> keys_;
- base::Lock lock_;
-
- DISALLOW_COPY_AND_ASSIGN(MemoryKeyPairStore);
-};
-
-} // namespace
-
-bool OpenSSLPrivateKeyStore::StoreKeyPair(const GURL& url,
- EVP_PKEY* pkey) {
- return MemoryKeyPairStore::GetInstance()->StoreKeyPair(pkey);
-}
-
-bool OpenSSLPrivateKeyStore::HasPrivateKey(EVP_PKEY* pub_key) {
- return MemoryKeyPairStore::GetInstance()->HasPrivateKey(pub_key);
-}
-
-} // namespace net
-
diff --git a/chromium/net/base/parse_number.h b/chromium/net/base/parse_number.h
index dc66fb6d8b5..0b4cfc1f8e3 100644
--- a/chromium/net/base/parse_number.h
+++ b/chromium/net/base/parse_number.h
@@ -27,8 +27,6 @@
// This API tries to avoid these problems by picking sensible defaults for
// //net code. For more details see crbug.com/596523.
-class GURL;
-
namespace net {
// Format to use when parsing integers.
diff --git a/chromium/net/base/percentile_estimator.cc b/chromium/net/base/percentile_estimator.cc
new file mode 100644
index 00000000000..7b3d9cf0c16
--- /dev/null
+++ b/chromium/net/base/percentile_estimator.cc
@@ -0,0 +1,100 @@
+// Copyright 2016 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.
+
+#include "percentile_estimator.h"
+
+#include "base/bind.h"
+#include "base/callback.h"
+#include "base/rand_util.h"
+
+namespace {
+
+// Random number wrapper to allow substitutions for testing.
+int GenerateRand0To99() {
+ return base::RandInt(0, 99);
+}
+
+} // namespace
+
+namespace net {
+
+// The algorithm used for percentile estimation is "Algorithm 3" from
+// https://arxiv.org/pdf/1407.1121v1.pdf. There are several parts to the
+// algorithm:
+// * The estimate is conditionally moved towards the sample by a step amount.
+// This means that if the samples are clustered around a value the estimates
+// will converge to that sample.
+// * The percentile requested (e.g. 90%l) is handled by the conditional move.
+// If the estimate is accurate, there is a chance equal to the percentile
+// value that a sample will be lower than it, and a chance equal to
+// 1-percentile that it will be higher. So the code balances those
+// probabilities by increasing the estimate in the percentile fraction
+// of the cases where the sample is over the estimate, and decreases the
+// estimate in (1-percentile) fraction of the cases where the sample is under
+// the estimate.
+// E.g. in the case of the 90%l estimation, the estimate would
+// move up in 90% of the cases in which the sample was above the
+// estimate (which would be 10% of the total samples, presuming the
+// estimate was accurate), and it would move down in 10% of the cases
+// in which the sample was below the estimate.
+// * Every time the estimate moves in the same direction, the step
+// amount is increased by one, and every time the estimate reverses
+// direction, the step amount is decreased (to 1, if greater than 1,
+// by one, if zero or negative). The effective step amount is
+// Max(step, 1).
+// * If the estimate
+// would be moved beyond the sample causing its move, it is moved to
+// be equal to the same (and the step amount set to the distance to
+// the sample). See the paper for further details.
+
+PercentileEstimator::PercentileEstimator(int percentile, int initial_estimate)
+ : percentile_(percentile),
+ sign_positive_(true),
+ current_estimate_(initial_estimate),
+ current_step_(1),
+ generator_callback_(base::Bind(&GenerateRand0To99)) {}
+
+PercentileEstimator::~PercentileEstimator() {}
+
+void PercentileEstimator::AddSample(int sample) {
+ int rand100 = generator_callback_.Run();
+ if (sample > current_estimate_ && rand100 > 1 - percentile_) {
+ current_step_ += sign_positive_ ? 1 : -1;
+ current_estimate_ += (current_step_ > 0) ? current_step_ : 1;
+
+ // Clamp movement to distance to sample.
+ if (current_estimate_ > sample) {
+ current_step_ -= current_estimate_ - sample;
+ current_estimate_ = sample;
+ }
+
+ // If we've reversed direction, reset the step down.
+ if (!sign_positive_ && current_step_ > 1)
+ current_step_ = 1;
+
+ sign_positive_ = true;
+ } else if (sample < current_estimate_ && rand100 > percentile_) {
+ current_step_ += !sign_positive_ ? 1 : -1;
+ current_estimate_ -= (current_step_ > 0) ? current_step_ : 1;
+
+ // Clamp movement to distance to sample.
+ if (current_estimate_ < sample) {
+ current_step_ -= sample - current_estimate_;
+ current_estimate_ = sample;
+ }
+
+ // If we've reversed direction, reset the step down.
+ if (sign_positive_ && current_step_ > 1)
+ current_step_ = 1;
+
+ sign_positive_ = false;
+ }
+}
+
+void PercentileEstimator::SetRandomNumberGeneratorForTesting(
+ RandomNumberCallback generator_callback) {
+ generator_callback_ = generator_callback;
+}
+
+} // namespace net
diff --git a/chromium/net/base/percentile_estimator.h b/chromium/net/base/percentile_estimator.h
new file mode 100644
index 00000000000..0ff7b8176e2
--- /dev/null
+++ b/chromium/net/base/percentile_estimator.h
@@ -0,0 +1,59 @@
+// Copyright 2016 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.
+
+#ifndef NET_BASE_PERCENTILE_ESTIMATOR_H_
+#define NET_BASE_PERCENTILE_ESTIMATOR_H_
+
+#include "base/callback.h"
+#include "base/macros.h"
+#include "net/base/net_export.h"
+
+namespace net {
+
+// This class estimates statistical percentiles (e.g. 10%l, 50%l) for
+// integer distributions presented in stream form. These estimates
+// adjust automatically when the stream distribution changes.
+// TODO(rdsmith): Expand the class to maintain floating point
+// estimates rather than integer estimates, when there's a use case
+// for that that deserves the extra complexity and pitfalls of
+// floating point arithmetic.
+class NET_EXPORT PercentileEstimator {
+ public:
+ using RandomNumberCallback = base::Callback<int(void)>;
+
+ static const int kMedianPercentile = 50;
+
+ // |percentile| is a number between 0 and 100 indicating what percentile
+ // should be estimated (e.g. 50 would be a median estimate).
+ // |initial_estimate| is the value the class is seeded with; in other
+ // words, if AddSample() is never called,
+ // |CurrentEstimate() == initial_estimate|.
+ PercentileEstimator(int percentile, int initial_estimate);
+
+ ~PercentileEstimator();
+
+ int current_estimate() const { return current_estimate_; }
+ void AddSample(int sample);
+
+ // Specify a callback that will generate a "random" number
+ // in the range [0,99] on each call. Used so that tests can
+ // rely on reproducible behavior.
+ void SetRandomNumberGeneratorForTesting(
+ RandomNumberCallback generator_callback);
+
+ private:
+ const int percentile_;
+
+ bool sign_positive_;
+ int current_estimate_;
+ int current_step_;
+
+ RandomNumberCallback generator_callback_;
+
+ DISALLOW_COPY_AND_ASSIGN(PercentileEstimator);
+};
+
+} // namespace net
+
+#endif // NET_BASE_PERCENTILE_ESTIMATOR_H_
diff --git a/chromium/net/base/percentile_estimator_unittest.cc b/chromium/net/base/percentile_estimator_unittest.cc
new file mode 100644
index 00000000000..71d9c1d386b
--- /dev/null
+++ b/chromium/net/base/percentile_estimator_unittest.cc
@@ -0,0 +1,242 @@
+// Copyright 2016 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.
+
+#include "net/base/percentile_estimator.h"
+
+#include "base/bind.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace {
+
+// A number to turn sawtooth ramps from 0->100 into something that looks more
+// random to the algorithm.
+const int kPrimeMultipleToRandomizeRamps = 71;
+
+// Random numbers (fixed here for repeatability of tests). Generated originally
+// by using python's random module with randrange(0,100).
+int random_numbers[] = {
+ 83, 11, 33, 98, 49, 54, 83, 19, 93, 37, 98, 39, 59, 13, 51, 39, 69, 18, 17,
+ 17, 6, 85, 95, 51, 83, 39, 18, 82, 88, 47, 69, 27, 20, 82, 86, 38, 98, 65,
+ 53, 13, 71, 66, 29, 40, 70, 28, 64, 35, 47, 50, 84, 90, 36, 54, 15, 93, 98,
+ 51, 82, 50, 17, 46, 12, 18, 26, 39, 95, 61, 52, 63, 97, 92, 12, 71, 7, 15,
+ 74, 10, 64, 57, 25, 82, 95, 40, 76, 8, 28, 83, 58, 1, 22, 58, 17, 33, 61,
+ 94, 40, 50, 84, 47, 81, 9, 79, 16, 45, 78, 15, 3, 97, 60, 70, 25, 11, 11,
+ 68, 64, 61, 84, 52, 64, 54, 72, 24, 46, 48, 4, 46, 34, 10, 97, 2, 42, 13,
+ 9, 95, 75, 11, 99, 92, 33, 65, 48, 19, 72, 63, 39, 0, 10, 83, 62, 12, 99,
+ 67, 98, 99, 83, 40, 45, 34, 80, 13, 94, 22, 74, 8, 11, 11, 98, 35, 86, 80,
+ 94, 87, 60, 16, 46, 9, 25, 75, 50, 54, 23, 31, 63, 9, 50, 5, 18, 87, 16,
+ 47, 72, 24, 93, 14, 1, 26, 41, 50, 49, 41, 77, 54, 48, 50, 3, 50, 16, 54,
+ 97, 57, 63, 83, 33, 65, 90, 48, 55, 44, 11, 71, 6, 86, 29, 46, 61, 20, 8,
+ 88, 3, 70, 76, 84, 59, 36, 50, 77, 63, 10, 55, 32, 82, 58, 19, 97, 8, 73,
+ 47, 55, 74, 46, 52, 62, 19, 65, 75, 57, 23, 98, 39, 63, 19, 75, 48, 93, 58,
+ 29, 96, 57, 31, 17, 33, 8, 69, 89, 90, 17, 79, 59, 67, 34, 20, 44, 80, 71,
+ 79, 24, 63, 13, 27, 28, 61, 38, 67, 82, 46, 9, 4, 69, 41, 49, 49, 10, 3,
+ 93, 46, 57, 96, 78, 51, 45, 37, 0, 6, 99, 93, 87, 18, 72, 83, 95, 39, 54,
+ 84, 12, 47, 14, 55, 15, 27, 95, 6, 13, 80, 40, 8, 39, 18, 15, 52, 31, 66,
+ 59, 67, 90, 12, 61, 77, 66, 61, 33, 89, 47, 40, 86, 34, 98, 13, 76, 30, 43,
+ 56, 57, 88, 34, 48, 67, 6, 29, 92, 38, 11, 23, 74, 45, 38, 35, 94, 15, 72,
+ 65, 20, 94, 72, 97, 78, 61, 79, 75, 0, 45, 38, 32, 94, 3, 5, 67, 91, 34,
+ 37, 12, 11, 15, 75, 14, 73, 34, 55, 78, 64, 52, 29, 60, 62, 16, 51, 44, 78,
+ 0, 15, 41, 5, 52, 4, 68, 53, 39, 39, 68, 71, 66, 68, 97, 65, 55, 39, 94,
+ 57, 43, 81, 67, 22, 30, 64, 37, 42, 35, 60, 61, 2, 51, 49, 43, 82, 61, 70,
+ 63, 47, 57, 8, 55, 96, 68, 7, 46, 69, 8, 43, 18, 9, 25, 8, 97, 98, 83,
+ 79, 19, 92, 54, 90, 72, 80, 92, 94, 26, 48, 94, 74, 32, 29, 44, 34, 55, 56,
+ 97, 40, 86, 35, 64, 25, 85, 13, 57, 2, 29, 77, 19, 94, 46, 85, 15, 71, 81,
+ 25, 45, 2, 1, 62, 77, 28, 95, 72, 72, 28, 3, 36, 76, 81, 56, 52, 27, 62,
+ 8, 5, 62, 1, 43, 68, 40, 68, 22, 65, 30, 50, 36, 89, 5, 71, 68, 99, 53,
+ 22, 26, 0, 1, 72, 76, 79, 50, 2, 32, 39, 40, 6, 99, 60, 59, 55, 28, 17,
+ 12, 94, 51, 3, 4, 71, 36, 88, 26, 99, 25, 13, 80, 53, 4, 57, 55, 44, 26,
+ 82, 4, 53, 34, 47, 16, 97, 56, 30, 0, 73, 85, 59, 86, 24, 70, 73, 53, 68,
+ 15, 91, 90, 74, 39, 61, 32, 98, 14, 82, 99, 31, 7, 99, 34, 6, 3, 30, 57,
+ 44, 58, 86, 37, 12, 63, 82, 78, 94, 4, 93, 89, 92, 59, 40, 94, 88, 97, 95,
+ 5, 88, 40, 80, 79, 0, 2, 46, 86, 46, 75, 87, 86, 8, 23, 35, 62, 79, 66,
+ 16, 16, 45, 11, 78, 76, 40, 73, 85, 28, 44, 33, 34, 22, 11, 62, 8, 35, 88,
+ 92, 35, 53, 50, 51, 54, 75, 41, 21, 83, 57, 82, 80, 84, 65, 19, 11, 85, 41,
+ 80, 86, 62, 34, 54, 54, 79, 81, 52, 87, 54, 54, 43, 17, 44, 63, 54, 14, 88,
+ 84, 86, 73, 58, 44, 2, 70, 86, 80, 94, 13, 85, 78, 6, 44, 11, 11, 97, 67,
+ 65, 28, 42, 40, 84, 92, 66, 85, 75, 29, 84, 82, 54, 50, 26, 12, 83, 57, 90,
+ 9, 40, 69, 38, 70, 65, 76, 85, 76, 4, 30, 86, 43, 79, 77, 69, 53, 35, 12,
+ 98, 7, 47, 12, 63, 10, 81, 39, 88, 12, 16, 88, 22, 72, 25, 41, 22, 34, 87,
+ 68, 51, 86, 45, 27, 51, 80, 69, 89, 64, 89, 68, 61, 80, 6, 83, 47, 18, 86,
+ 73, 16, 61, 89, 47, 5, 33, 59, 47, 75, 15, 60, 28, 18, 59, 65, 51, 13, 28,
+ 26, 84, 89, 80, 51, 15, 92, 36, 89, 83, 28, 56, 65, 25, 44, 84, 70, 26, 10,
+ 74, 91, 55, 85, 73, 25, 24, 64, 11, 1, 55, 32, 45, 74, 4, 55, 98, 42, 91,
+ 88, 18, 79, 37, 15, 5, 98, 63, 65, 77, 66, 18, 99, 1, 78, 96, 15, 16, 16,
+ 51, 11, 47, 58, 1, 12, 46, 5, 56, 34, 40, 36, 20, 4, 89, 59, 4, 13, 3,
+ 8, 74, 41, 21, 64, 88, 97, 42, 14, 29, 38, 53, 65, 55, 67, 33, 69, 17, 79,
+ 45, 2, 63, 2, 97, 47, 73, 22, 86, 32, 31, 95, 90, 84, 25, 86, 91, 77, 1,
+ 5, 6, 22, 91, 3, 94, 52, 2, 95, 17, 1, 19, 22, 34, 49, 96, 88, 63, 26,
+ 5, 25, 75, 23, 25, 80, 21, 83, 86, 81, 11, 70, 67, 11, 95, 81, 57, 63, 8,
+ 43, 60, 40, 42, 67, 50, 2, 51, 43, 34, 7, 1, 90, 59, 74, 87, 23, 23, 71,
+ 20, 89, 2, 75, 21, 91, 32, 87, 67, 98, 99, 22, 31, 59, 50, 64, 55, 22, 84,
+ 9, 31, 31, 84, 36, 92, 60, 37, 85, 18, 12, 38, 55, 55, 93, 36, 9, 46, 48,
+ 24, 91, 60, 95, 55, 73, 63, 27, 55, 96, 79, 50, 41, 5, 67, 85, 99, 95, 3,
+ 97, 28, 27, 78, 38, 11, 77, 11, 64, 25, 22, 88, 34, 86, 30, 78, 95, 17, 9,
+ 29, 58, 35, 22, 99, 28, 66, 35, 60, 10, 7, 51, 64, 86, 30, 27, 97, 63, 0,
+ 36, 87, 52, 16, 5, 90, 8, 66, 58, 91, 85, 3, 95, 31, 73, 87, 30, 78, 46,
+ 30, 75, 36, 44, 52, 76, 24, 58, 8, 70, 58, 95, 88, 0, 35, 86, 21, 96, 90,
+ 54, 85, 56, 30, 37, 30, 62, 56, 63, 91, 25, 56, 20, 56, 23, 12, 8, 70, 56,
+ 83, 49, 70, 67, 61, 95, 50, 41, 88, 37, 89, 37, 21, 63, 25, 46, 16, 75, 73,
+ 86, 39, 4, 55, 41, 39, 45, 31, 97, 6, 81, 68, 38, 49, 80, 9, 87, 22, 37,
+ 41, 28, 47, 74, 76, 34, 72, 65, 34, 41, 59, 42, 73, 32, 75, 25, 18, 26, 71,
+ 93, 92, 12, 76, 93, 84, 44, 43, 4, 9, 3, 90, 91, 45, 0, 10, 43, 45, 65,
+ 34, 82, 54, 1, 78, 36, 74, 58, 3, 26, 89, 21, 57, 42, 37, 12, 90, 97, 48,
+ 27, 75, 40, 69, 61, 56, 44, 75, 77, 55, 31, 0, 77, 12, 23, 16, 98, 77, 8,
+ 96, 92, 91, 26, 50, 42, 65, 38, 58, 41, 45, 69, 42, 37, 89, 92, 40, 74, 68,
+ 86, 80, 49, 16, 48, 74, 50, 92, 54, 6, 82, 21, 35, 57, 81, 29, 10, 60, 74,
+ 41, 70, 18, 65, 44, 77, 64, 8, 87, 90, 24, 52, 67, 58, 56, 89, 47, 15, 20,
+ 4, 87, 72, 87, 13, 79, 3, 26, 43, 52, 72, 83, 17, 99, 29, 10, 61, 62, 42,
+ 35, 47, 42, 40, 17, 71, 54, 30, 99, 64, 78, 70, 75, 38, 32, 51, 2, 49, 47,
+ 0, 41, 50, 41, 64, 57, 78, 22, 17, 94, 24, 65, 84, 38, 75, 3, 58, 18, 51,
+ 91, 72, 91, 55, 6, 70, 76, 73, 30, 54, 73, 77, 45, 85, 88, 58, 25, 80, 35,
+ 99, 57, 73, 15, 55, 71, 44, 44, 79, 20, 63, 29, 14, 51, 10, 46, 80, 36, 47,
+ 80, 53, 15, 64, 42, 59, 94, 55, 99, 28, 76, 80, 51, 4, 98, 98, 38, 59, 71,
+ 9, 93, 91, 46, 74, 63, 10, 39, 1, 43, 11, 64, 39, 59, 54, 9, 44, 78, 52,
+ 98, 9, 73, 24, 15, 40, 5, 55, 23, 83, 67, 10, 58, 45, 64, 41, 92, 85, 72,
+ 18, 67, 65, 30, 56, 84, 63, 96, 51, 55, 19, 70, 48, 81, 2, 37, 85, 77};
+
+class PercentileEstimatorTest : public testing::Test {
+ public:
+ PercentileEstimatorTest() : index_(0) {}
+
+ // Create a new estimator with the given parameters.
+ void SetUpEstimator(int percentile, int initial_estimate) {
+ estimator_.reset(
+ new net::PercentileEstimator(percentile, initial_estimate));
+ estimator_->SetRandomNumberGeneratorForTesting(
+ base::Bind(&PercentileEstimatorTest::GetRandomNumber,
+ // Safe since |estimator_| is owned by and
+ // will not survive destruction of |this|.
+ base::Unretained(this)));
+ }
+
+ int CurrentEstimate() { return estimator_->current_estimate(); }
+ void AddSample(int sample) { estimator_->AddSample(sample); }
+
+ // Add the sample until there's a change in the estimate, then return the
+ // new estimate. To get around the randomness of whether samples are
+ // incorporated or not.
+ int AddSampleUntilRegistered(int sample) {
+ int old_estimate = estimator_->current_estimate();
+ while (old_estimate == estimator_->current_estimate())
+ estimator_->AddSample(sample);
+
+ return estimator_->current_estimate();
+ }
+
+ int GetRandomNumber() {
+ int result = random_numbers[index_];
+ ++index_;
+ if (static_cast<unsigned long>(index_) >=
+ sizeof(random_numbers) / sizeof(int)) {
+ index_ = 0;
+ }
+ return result;
+ }
+
+ private:
+ int index_;
+ std::unique_ptr<net::PercentileEstimator> estimator_;
+
+ DISALLOW_COPY_AND_ASSIGN(PercentileEstimatorTest);
+};
+
+// Converges upwards fairly quickly.
+TEST_F(PercentileEstimatorTest, MedianConvergesUpwards) {
+ SetUpEstimator(50, 100);
+
+ for (int i = 0; i < 40; ++i)
+ AddSample(150);
+
+ EXPECT_EQ(150, CurrentEstimate());
+}
+
+// Converges downwards fairly quickly.
+TEST_F(PercentileEstimatorTest, MedianConvergesDownwards) {
+ SetUpEstimator(50, 100);
+
+ for (int i = 0; i < 40; ++i)
+ AddSample(50);
+
+ EXPECT_EQ(50, CurrentEstimate());
+}
+
+// Stable if the value is bouncing around.
+TEST_F(PercentileEstimatorTest, BounceStable) {
+ SetUpEstimator(50, 100);
+
+ for (int i = 0; i < 20; ++i)
+ AddSample(50 + (i % 2) * 100);
+
+ EXPECT_LE(97, CurrentEstimate());
+ EXPECT_LE(CurrentEstimate(), 103);
+}
+
+// Correctly converges to a 90%l value upwards.
+TEST_F(PercentileEstimatorTest, NinetythConvergesUpwards) {
+ SetUpEstimator(90, 50);
+
+ for (int i = 0; i < 10000; ++i)
+ AddSample((i * kPrimeMultipleToRandomizeRamps) % 100);
+
+ EXPECT_LE(86, CurrentEstimate());
+ EXPECT_LE(CurrentEstimate(), 94);
+}
+
+// Correctly converges to a 90%l value downwards.
+TEST_F(PercentileEstimatorTest, NinetythConvergesDownwards) {
+ SetUpEstimator(90, 150);
+
+ for (int i = 0; i < 1000; ++i)
+ AddSample((i * kPrimeMultipleToRandomizeRamps) % 100);
+
+ EXPECT_LT(86, CurrentEstimate());
+ EXPECT_LT(CurrentEstimate(), 94);
+}
+
+// Doesn't overshoot sample heading upwards.
+TEST_F(PercentileEstimatorTest, NoUpwardsOvershoot) {
+ SetUpEstimator(50, 100);
+
+ // Crank up the step size
+ for (int i = 0; i < 20; ++i)
+ AddSample(1000);
+
+ // Derive the step size.
+ int e1 = CurrentEstimate();
+ int e2 = AddSampleUntilRegistered(1000);
+ int step_size = e2 - e1;
+ ASSERT_GT(step_size, 1);
+
+ // Increment by less than the current step size.
+ int new_sample = e2 + step_size / 2;
+ AddSampleUntilRegistered(new_sample);
+ EXPECT_EQ(new_sample, CurrentEstimate());
+ AddSampleUntilRegistered(1000);
+ EXPECT_GT(new_sample + step_size, CurrentEstimate());
+}
+
+// Doesn't overshoot sample heading downwards
+TEST_F(PercentileEstimatorTest, NoDownwardsOvershoot) {
+ SetUpEstimator(50, 1000);
+
+ // Crank up the step size
+ for (int i = 0; i < 20; ++i)
+ AddSample(100);
+
+ // Derive the step size.
+ int e1 = CurrentEstimate();
+ int e2 = AddSampleUntilRegistered(100);
+ int step_size = e1 - e2;
+ ASSERT_GT(step_size, 1);
+
+ // Increment by less than the current step size.
+ int new_sample = e2 - step_size / 2;
+ AddSampleUntilRegistered(new_sample);
+ EXPECT_EQ(new_sample, CurrentEstimate());
+ AddSampleUntilRegistered(100);
+ EXPECT_LT(new_sample - step_size, CurrentEstimate());
+}
+
+} // namespace
diff --git a/chromium/net/base/port_util.cc b/chromium/net/base/port_util.cc
index 7328b5e842f..543d9db9435 100644
--- a/chromium/net/base/port_util.cc
+++ b/chromium/net/base/port_util.cc
@@ -84,6 +84,7 @@ const int kRestrictedPorts[] = {
6667, // Standard IRC [Apple addition]
6668, // Alternate IRC [Apple addition]
6669, // Alternate IRC [Apple addition]
+ 6697, // IRC + TLS
0xFFFF, // Used to block all invalid port numbers (see
// third_party/WebKit/Source/platform/weborigin/KURL.cpp,
// KURL::port())
diff --git a/chromium/net/base/port_util.h b/chromium/net/base/port_util.h
index 99a1ec484e3..d1cc5fe6ccd 100644
--- a/chromium/net/base/port_util.h
+++ b/chromium/net/base/port_util.h
@@ -2,8 +2,8 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#ifndef NET_BASE_NET_PORT_UTIL_
-#define NET_BASE_NET_PORT_UTIL_
+#ifndef NET_BASE_PORT_UTIL_H_
+#define NET_BASE_PORT_UTIL_H_
#include <stddef.h>
@@ -45,4 +45,4 @@ class NET_EXPORT ScopedPortException {
} // namespace net
-#endif // NET_BASE_NET_PORT_UTIL_
+#endif // NET_BASE_PORT_UTIL_H_
diff --git a/chromium/net/base/proxy_delegate.h b/chromium/net/base/proxy_delegate.h
index ad3a2bcafdd..2343196969f 100644
--- a/chromium/net/base/proxy_delegate.h
+++ b/chromium/net/base/proxy_delegate.h
@@ -20,7 +20,6 @@ class HostPortPair;
class ProxyInfo;
class ProxyServer;
class ProxyService;
-class URLRequest;
// Delegate for setting up a connection.
class NET_EXPORT ProxyDelegate {
diff --git a/chromium/net/base/registry_controlled_domains/effective_tld_names.dat b/chromium/net/base/registry_controlled_domains/effective_tld_names.dat
index e93211f79e1..bba925debcd 100644
--- a/chromium/net/base/registry_controlled_domains/effective_tld_names.dat
+++ b/chromium/net/base/registry_controlled_domains/effective_tld_names.dat
@@ -4440,20 +4440,21 @@ org.ng
sch.ng
// ni : http://www.nic.ni/
+ni
+ac.ni
+biz.ni
+co.ni
com.ni
-gob.ni
edu.ni
-org.ni
-nom.ni
-net.ni
-mil.ni
-co.ni
-biz.ni
-web.ni
-int.ni
-ac.ni
+gob.ni
in.ni
info.ni
+int.ni
+mil.ni
+net.ni
+nom.ni
+org.ni
+web.ni
// nl : https://en.wikipedia.org/wiki/.nl
// https://www.sidn.nl/
@@ -5279,6 +5280,9 @@ net.om
org.om
pro.om
+// onion : https://tools.ietf.org/html/rfc7686
+onion
+
// org : https://en.wikipedia.org/wiki/.org
org
@@ -5680,143 +5684,13 @@ gov.rs
in.rs
org.rs
-// ru : http://www.cctld.ru/ru/docs/aktiv_8.php
-// Industry domains
+// ru : https://cctld.ru/en/domains/domens_ru/reserved/
ru
ac.ru
-com.ru
edu.ru
-int.ru
-net.ru
-org.ru
-pp.ru
-// Geographical domains
-adygeya.ru
-altai.ru
-amur.ru
-arkhangelsk.ru
-astrakhan.ru
-bashkiria.ru
-belgorod.ru
-bir.ru
-bryansk.ru
-buryatia.ru
-cbg.ru
-chel.ru
-chelyabinsk.ru
-chita.ru
-chukotka.ru
-chuvashia.ru
-dagestan.ru
-dudinka.ru
-e-burg.ru
-grozny.ru
-irkutsk.ru
-ivanovo.ru
-izhevsk.ru
-jar.ru
-joshkar-ola.ru
-kalmykia.ru
-kaluga.ru
-kamchatka.ru
-karelia.ru
-kazan.ru
-kchr.ru
-kemerovo.ru
-khabarovsk.ru
-khakassia.ru
-khv.ru
-kirov.ru
-koenig.ru
-komi.ru
-kostroma.ru
-krasnoyarsk.ru
-kuban.ru
-kurgan.ru
-kursk.ru
-lipetsk.ru
-magadan.ru
-mari.ru
-mari-el.ru
-marine.ru
-mordovia.ru
-// mosreg.ru Bug 1090800 - removed at request of Aleksey Konstantinov <konstantinovav@mosreg.ru>
-msk.ru
-murmansk.ru
-nalchik.ru
-nnov.ru
-nov.ru
-novosibirsk.ru
-nsk.ru
-omsk.ru
-orenburg.ru
-oryol.ru
-palana.ru
-penza.ru
-perm.ru
-ptz.ru
-rnd.ru
-ryazan.ru
-sakhalin.ru
-samara.ru
-saratov.ru
-simbirsk.ru
-smolensk.ru
-spb.ru
-stavropol.ru
-stv.ru
-surgut.ru
-tambov.ru
-tatarstan.ru
-tom.ru
-tomsk.ru
-tsaritsyn.ru
-tsk.ru
-tula.ru
-tuva.ru
-tver.ru
-tyumen.ru
-udm.ru
-udmurtia.ru
-ulan-ude.ru
-vladikavkaz.ru
-vladimir.ru
-vladivostok.ru
-volgograd.ru
-vologda.ru
-voronezh.ru
-vrn.ru
-vyatka.ru
-yakutia.ru
-yamal.ru
-yaroslavl.ru
-yekaterinburg.ru
-yuzhno-sakhalinsk.ru
-// More geographical domains
-amursk.ru
-baikal.ru
-cmw.ru
-fareast.ru
-jamal.ru
-kms.ru
-k-uralsk.ru
-kustanai.ru
-kuzbass.ru
-mytis.ru
-nakhodka.ru
-nkz.ru
-norilsk.ru
-oskol.ru
-pyatigorsk.ru
-rubtsovsk.ru
-snz.ru
-syzran.ru
-vdonsk.ru
-zgrad.ru
-// State domains
gov.ru
+int.ru
mil.ru
-// Technical domains
test.ru
// rw : http://www.nic.rw/cgi-bin/policy.pl
@@ -5990,38 +5864,6 @@ store.st
// su : https://en.wikipedia.org/wiki/.su
su
-adygeya.su
-arkhangelsk.su
-balashov.su
-bashkiria.su
-bryansk.su
-dagestan.su
-grozny.su
-ivanovo.su
-kalmykia.su
-kaluga.su
-karelia.su
-khakassia.su
-krasnodar.su
-kurgan.su
-lenug.su
-mordovia.su
-msk.su
-murmansk.su
-nalchik.su
-nov.su
-obninsk.su
-penza.su
-pokrovsk.su
-sochi.su
-spb.su
-togliatti.su
-troitsk.su
-tula.su
-tuva.su
-vladikavkaz.su
-vladimir.su
-vologda.su
// sv : http://www.svnet.org.sv/niveldos.pdf
sv
@@ -10661,32 +10503,34 @@ beep.pl
cloudfront.net
// Amazon Elastic Compute Cloud: https://aws.amazon.com/ec2/
-// Submitted by Luke Wells <lawells@amazon.com>
+// Submitted by Luke Wells <psl-maintainers@amazon.com>
*.compute.amazonaws.com
*.compute-1.amazonaws.com
*.compute.amazonaws.com.cn
us-east-1.amazonaws.com
// Amazon Elastic Beanstalk : https://aws.amazon.com/elasticbeanstalk/
-// Submitted by Luke Wells <lawells@amazon.com>
+// Submitted by Luke Wells <psl-maintainers@amazon.com>
elasticbeanstalk.cn-north-1.amazonaws.com.cn
*.elasticbeanstalk.com
// Amazon Elastic Load Balancing : https://aws.amazon.com/elasticloadbalancing/
-// Submitted by Luke Wells <lawells@amazon.com>
+// Submitted by Luke Wells <psl-maintainers@amazon.com>
*.elb.amazonaws.com
*.elb.amazonaws.com.cn
// Amazon S3 : https://aws.amazon.com/s3/
-// Submitted by Luke Wells <lawells@amazon.com>
+// Submitted by Luke Wells <psl-maintainers@amazon.com>
s3.amazonaws.com
s3-ap-northeast-1.amazonaws.com
s3-ap-northeast-2.amazonaws.com
s3-ap-south-1.amazonaws.com
s3-ap-southeast-1.amazonaws.com
s3-ap-southeast-2.amazonaws.com
+s3-ca-central-1.amazonaws.com
s3-eu-central-1.amazonaws.com
s3-eu-west-1.amazonaws.com
+s3-eu-west-2.amazonaws.com
s3-external-1.amazonaws.com
s3-fips-us-gov-west-1.amazonaws.com
s3-sa-east-1.amazonaws.com
@@ -10697,15 +10541,19 @@ s3-us-west-2.amazonaws.com
s3.ap-northeast-2.amazonaws.com
s3.ap-south-1.amazonaws.com
s3.cn-north-1.amazonaws.com.cn
+s3.ca-central-1.amazonaws.com
s3.eu-central-1.amazonaws.com
+s3.eu-west-2.amazonaws.com
s3.us-east-2.amazonaws.com
s3.dualstack.ap-northeast-1.amazonaws.com
s3.dualstack.ap-northeast-2.amazonaws.com
s3.dualstack.ap-south-1.amazonaws.com
s3.dualstack.ap-southeast-1.amazonaws.com
s3.dualstack.ap-southeast-2.amazonaws.com
+s3.dualstack.ca-central-1.amazonaws.com
s3.dualstack.eu-central-1.amazonaws.com
s3.dualstack.eu-west-1.amazonaws.com
+s3.dualstack.eu-west-2.amazonaws.com
s3.dualstack.sa-east-1.amazonaws.com
s3.dualstack.us-east-1.amazonaws.com
s3.dualstack.us-east-2.amazonaws.com
@@ -10719,13 +10567,24 @@ s3-website-eu-west-1.amazonaws.com
s3-website-sa-east-1.amazonaws.com
s3-website.ap-northeast-2.amazonaws.com
s3-website.ap-south-1.amazonaws.com
+s3-website.ca-central-1.amazonaws.com
s3-website.eu-central-1.amazonaws.com
+s3-website.eu-west-2.amazonaws.com
s3-website.us-east-2.amazonaws.com
+// Amune : https://amune.org/
+// Submitted by Team Amune <cert@amune.org>
+t3l3p0rt.net
+tele.amune.org
+
// Aptible : https://www.aptible.com/
// Submitted by Thomas Orozco <thomas@aptible.com>
on-aptible.com
+// Asociación Amigos de la Informática "Euskalamiga" : http://encounter.eus/
+// Submitted by Hector Martin <marcan@euskalencounter.org>
+user.party.eus
+
// Association potager.org : https://potager.org/
// Submitted by Lunar <jardiniers@potager.org>
pimienta.org
@@ -11321,13 +11180,92 @@ us-2.evennode.com
// Submitted by Peter Ruibal <public-suffix@fb.com>
apps.fbsbx.com
-// Fastly Inc. http://www.fastly.com/
-// Submitted by Vladimir Vuksan <vladimir@fastly.com>
+// FAITID : https://faitid.org/
+// Submitted by Maxim Alzoba <tech.contact@faitid.org>
+// https://www.flexireg.net/stat_info
+ru.net
+adygeya.ru
+bashkiria.ru
+bir.ru
+cbg.ru
+com.ru
+dagestan.ru
+grozny.ru
+kalmykia.ru
+kustanai.ru
+marine.ru
+mordovia.ru
+msk.ru
+mytis.ru
+nalchik.ru
+nov.ru
+pyatigorsk.ru
+spb.ru
+vladikavkaz.ru
+vladimir.ru
+abkhazia.su
+adygeya.su
+aktyubinsk.su
+arkhangelsk.su
+armenia.su
+ashgabad.su
+azerbaijan.su
+balashov.su
+bashkiria.su
+bryansk.su
+bukhara.su
+chimkent.su
+dagestan.su
+east-kazakhstan.su
+exnet.su
+georgia.su
+grozny.su
+ivanovo.su
+jambyl.su
+kalmykia.su
+kaluga.su
+karacol.su
+karaganda.su
+karelia.su
+khakassia.su
+krasnodar.su
+kurgan.su
+kustanai.su
+lenug.su
+mangyshlak.su
+mordovia.su
+msk.su
+murmansk.su
+nalchik.su
+navoi.su
+north-kazakhstan.su
+nov.su
+obninsk.su
+penza.su
+pokrovsk.su
+sochi.su
+spb.su
+tashkent.su
+termez.su
+togliatti.su
+troitsk.su
+tselinograd.su
+tula.su
+tuva.su
+vladikavkaz.su
+vladimir.su
+vologda.su
+
+// Fastly Inc. : http://www.fastly.com/
+// Submitted by Fastly Security <security@fastly.com>
+map.fastly.net
+a.prod.fastly.net
+global.prod.fastly.net
a.ssl.fastly.net
b.ssl.fastly.net
global.ssl.fastly.net
-a.prod.fastly.net
-global.prod.fastly.net
+fastlylb.net
+map.fastlylb.net
// Featherhead : https://featherhead.xyz/
// Submitted by Simon Menke <simon@featherhead.xyz>
@@ -11380,9 +11318,12 @@ gist.githubcloud.com
// Submitted by Alex Hanselka <alex@gitlab.com>
gitlab.io
+// UKHomeOffice : https://www.gov.uk/government/organisations/home-office
+// Submitted by Jon Shanks <jon.shanks@digital.homeoffice.gov.uk>
+homeoffice.gov.uk
+
// GlobeHosting, Inc.
// Submitted by Zoltan Egresi <egresi@globehosting.com>
-ro.com
ro.im
shop.ro
@@ -11732,6 +11673,10 @@ gotpantheon.com
// Submitted by Steve Leung <steveleung@peplink.com>
mypep.link
+// Planet-Work : https://www.planet-work.com/
+// Submitted by Frédéric VANNIÈRE <f.vanniere@planet-work.com>
+on-web.fr
+
// prgmr.com : https://prgmr.com/
// Submitted by Sarah Newman <owner@prgmr.com>
xen.prgmr.com
@@ -11888,6 +11833,22 @@ townnews-staging.com
// Submitted by TuxFamily administrators <adm@staff.tuxfamily.org>
tuxfamily.org
+// TwoDNS : https://www.twodns.de/
+// Submitted by TwoDNS-Support <support@two-dns.de>
+dd-dns.de
+diskstation.eu
+diskstation.org
+dray-dns.de
+draydns.de
+dyn-vpn.de
+dynvpn.de
+mein-vigor.de
+my-vigor.de
+my-wan.de
+syno-ds.de
+synology-diskstation.de
+synology-ds.de
+
// UDR Limited : http://www.udr.hk.com
// Submitted by registry <hostmaster@udr.hk.com>
hk.com
@@ -11903,6 +11864,10 @@ lib.de.us
// Submitted by Simon Kissel <hostmaster@viprinet.com>
router.management
+// Western Digital Technologies, Inc : https://www.wdc.com
+// Submitted by Jung Jin <jungseok.jin@wdc.com>
+remotewd.com
+
// Wikimedia Labs : https://wikitech.wikimedia.org
// Submitted by Yuvi Panda <yuvipanda@wikimedia.org>
wmflabs.org
@@ -11930,4 +11895,10 @@ za.org
// Submitted by Olli Vanhoja <olli@zeit.co>
now.sh
+// 1GB LLC : https://www.1gb.ua/
+// Submitted by 1GB LLC <noc@1gb.com.ua>
+cc.ua
+inf.ua
+ltd.ua
+
// ===END PRIVATE DOMAINS===
diff --git a/chromium/net/base/registry_controlled_domains/effective_tld_names.gperf b/chromium/net/base/registry_controlled_domains/effective_tld_names.gperf
index 58f69a044f9..5d152382a64 100644
--- a/chromium/net/base/registry_controlled_domains/effective_tld_names.gperf
+++ b/chromium/net/base/registry_controlled_domains/effective_tld_names.gperf
@@ -45,6 +45,7 @@ abc, 0
abeno.osaka.jp, 0
abiko.chiba.jp, 0
abira.hokkaido.jp, 0
+abkhazia.su, 4
able, 0
abo.pa, 0
abogado, 0
@@ -117,8 +118,8 @@ adult, 0
adult.ht, 0
adv.br, 0
adv.mz, 0
-adygeya.ru, 0
-adygeya.su, 0
+adygeya.ru, 4
+adygeya.su, 4
ae, 0
ae.org, 4
aeg, 0
@@ -198,6 +199,7 @@ akkeshi.hokkaido.jp, 0
aknoluokta.no, 0
ako.hyogo.jp, 0
akrehamn.no, 0
+aktyubinsk.su, 4
akune.kagoshima.jp, 0
al, 0
al.eu.org, 4
@@ -226,7 +228,6 @@ alstahaug.no, 0
alstom, 0
alt.za, 0
alta.no, 0
-altai.ru, 0
alto-adige.it, 0
altoadige.it, 0
alvdal.no, 0
@@ -256,8 +257,6 @@ amli.no, 0
amot.no, 0
amsterdam, 0
amsterdam.museum, 0
-amur.ru, 0
-amursk.ru, 0
amusement.aero, 0
an.it, 0
analytics, 0
@@ -336,8 +335,8 @@ ariake.saga.jp, 0
arida.wakayama.jp, 0
aridagawa.wakayama.jp, 0
arita.saga.jp, 0
-arkhangelsk.ru, 0
-arkhangelsk.su, 0
+arkhangelsk.su, 4
+armenia.su, 4
army, 0
arna.no, 0
arpa, 0
@@ -380,6 +379,7 @@ ascoli-piceno.it, 0
ascolipiceno.it, 0
asda, 0
aseral.no, 0
+ashgabad.su, 4
ashibetsu.hokkaido.jp, 0
ashikaga.tochigi.jp, 0
ashiya.fukuoka.jp, 0
@@ -416,7 +416,6 @@ associates, 0
association.aero, 0
association.museum, 0
asti.it, 0
-astrakhan.ru, 0
astronomy.museum, 0
asuke.aichi.jp, 0
at, 0
@@ -476,6 +475,7 @@ ayagawa.kagawa.jp, 0
ayase.kanagawa.jp, 0
az, 0
az.us, 0
+azerbaijan.su, 4
azumino.nagano.jp, 0
azure, 0
azure-mobile.net, 4
@@ -498,9 +498,8 @@ bahccavuotna.no, 0
bahn.museum, 0
baidar.no, 0
baidu, 0
-baikal.ru, 0
bajddar.no, 0
-balashov.su, 0
+balashov.su, 4
balat.no, 0
bale.museum, 0
balestrand.no, 0
@@ -536,8 +535,8 @@ bas.it, 0
baseball, 0
baseball.museum, 0
basel.museum, 0
-bashkiria.ru, 0
-bashkiria.su, 0
+bashkiria.ru, 4
+bashkiria.su, 4
basilicata.it, 0
basketball, 0
baths.museum, 0
@@ -570,7 +569,6 @@ beer, 0
beiarn.no, 0
bel.tr, 0
belau.pw, 0
-belgorod.ru, 0
bellevue.museum, 0
belluno.it, 0
benevento.it, 0
@@ -621,7 +619,7 @@ bing, 0
bingo, 0
bio, 0
bio.br, 0
-bir.ru, 0
+bir.ru, 4
biratori.hokkaido.jp, 0
birdart.museum, 0
birkenes.no, 0
@@ -820,8 +818,7 @@ brussel.museum, 0
brussels, 0
brussels.museum, 0
bruxelles.museum, 0
-bryansk.ru, 0
-bryansk.su, 0
+bryansk.su, 4
bryne.no, 0
bs, 0
bs.it, 0
@@ -834,11 +831,11 @@ bugatti, 0
build, 0
builders, 0
building.museum, 0
+bukhara.su, 4
bungoono.oita.jp, 0
bungotakada.oita.jp, 0
bunkyo.tokyo.jp, 0
burghof.museum, 0
-buryatia.ru, 0
bus.museum, 0
busan.kr, 0
bushey.museum, 0
@@ -931,7 +928,7 @@ catering.aero, 0
catholic, 0
cb.it, 0
cba, 0
-cbg.ru, 0
+cbg.ru, 4
cbn, 0
cbre, 0
cbs, 0
@@ -984,6 +981,7 @@ cc.sc.us, 0
cc.sd.us, 0
cc.tn.us, 0
cc.tx.us, 0
+cc.ua, 4
cc.ut.us, 0
cc.va.us, 0
cc.vi.us, 0
@@ -1025,9 +1023,7 @@ chase, 0
chat, 0
chattanooga.museum, 0
cheap, 0
-chel.ru, 0
cheltenham.museum, 0
-chelyabinsk.ru, 0
cherkassy.ua, 0
cherkasy.ua, 0
chernigov.ua, 0
@@ -1053,6 +1049,7 @@ chikuzen.fukuoka.jp, 0
children.museum, 0
childrens.museum, 0
childrensgarden.museum, 0
+chimkent.su, 4
chino.nagano.jp, 0
chintai, 0
chippubetsu.hokkaido.jp, 0
@@ -1061,7 +1058,6 @@ chirurgiens-dentistes-en-france.fr, 4
chirurgiens-dentistes.fr, 0
chiryu.aichi.jp, 0
chita.aichi.jp, 0
-chita.ru, 0
chitose.hokkaido.jp, 0
chiyoda.gunma.jp, 0
chiyoda.tokyo.jp, 0
@@ -1078,7 +1074,6 @@ christmas, 0
chrome, 0
chrysler, 0
chtr.k12.ma.us, 0
-chukotka.ru, 0
chungbuk.kr, 0
chungnam.kr, 0
chuo.chiba.jp, 0
@@ -1087,7 +1082,6 @@ chuo.osaka.jp, 0
chuo.tokyo.jp, 0
chuo.yamanashi.jp, 0
church, 0
-chuvashia.ru, 0
ci, 0
ci.it, 0
cieszyn.pl, 0
@@ -1150,7 +1144,6 @@ club.aero, 0
club.tw, 0
clubmed, 0
cm, 0
-cmw.ru, 0
cn, 0
cn.com, 4
cn.eu.org, 4
@@ -1339,7 +1332,7 @@ com.py, 0
com.qa, 0
com.re, 0
com.ro, 0
-com.ru, 0
+com.ru, 4
com.rw, 0
com.sa, 0
com.sb, 0
@@ -1486,8 +1479,8 @@ dabur, 0
dad, 0
daegu.kr, 0
daejeon.kr, 0
-dagestan.ru, 0
-dagestan.su, 0
+dagestan.ru, 4
+dagestan.su, 4
daigo.ibaraki.jp, 0
daisen.akita.jp, 0
daito.osaka.jp, 0
@@ -1510,6 +1503,7 @@ day, 0
dazaifu.fukuoka.jp, 0
dc.us, 0
dclk, 0
+dd-dns.de, 4
ddns.me, 4
ddns.net, 4
ddnsking.com, 4
@@ -1566,7 +1560,9 @@ discount, 0
discover, 0
discovery.museum, 0
dish, 0
+diskstation.eu, 4
diskstation.me, 4
+diskstation.org, 4
ditchyourip.com, 4
divtasvuodna.no, 0
divttasvuotna.no, 0
@@ -1620,6 +1616,8 @@ dr.na, 0
dr.tr, 0
drammen.no, 0
drangedal.no, 0
+dray-dns.de, 4
+draydns.de, 4
dreamhosters.com, 4
drive, 0
drobak.no, 0
@@ -1635,7 +1633,6 @@ dtv, 0
dubai, 0
duck, 0
duckdns.org, 4
-dudinka.ru, 0
dunlop, 0
duns, 0
dupont, 0
@@ -1649,6 +1646,7 @@ dwg, 0
dy.fi, 4
dyn-ip24.de, 4
dyn-o-saur.com, 4
+dyn-vpn.de, 4
dyn.cosidns.de, 4
dyn.ddnss.de, 4
dyn.home-webserver.de, 4
@@ -1681,15 +1679,16 @@ dyndns.ws, 4
dyndns1.de, 4
dynns.com, 4
dynv6.net, 4
+dynvpn.de, 4
dyroy.no, 0
dz, 0
-e-burg.ru, 0
e.bg, 0
e.se, 0
e12.ve, 0
e164.arpa, 0
e4.cz, 4
earth, 0
+east-kazakhstan.su, 4
eastafrica.museum, 0
eastcoast.museum, 0
eat, 0
@@ -1950,6 +1949,7 @@ exchange, 0
exchange.aero, 0
exeter.museum, 0
exhibition.museum, 0
+exnet.su, 4
expert, 0
experts-comptables.fr, 0
exposed, 0
@@ -1973,7 +1973,6 @@ fan, 0
fans, 0
fantasyleague.cc, 4
far.br, 0
-fareast.ru, 0
farm, 0
farm.museum, 0
farmequipment.museum, 0
@@ -1983,6 +1982,7 @@ farmstead.museum, 0
farsund.no, 0
fashion, 0
fast, 0
+fastlylb.net, 4
fauske.no, 0
fbx-os.fr, 4
fbxos.fr, 4
@@ -2335,6 +2335,7 @@ geology.museum, 0
geometre-expert.fr, 0
george, 0
georgia.museum, 0
+georgia.su, 4
getmyip.com, 4
gets-it.net, 4
gf, 0
@@ -2617,8 +2618,8 @@ grosseto.it, 0
groundhandling.aero, 0
group, 0
group.aero, 0
-grozny.ru, 0
-grozny.su, 0
+grozny.ru, 4
+grozny.su, 4
grp.lk, 0
grue.no, 0
gs, 0
@@ -2908,6 +2909,7 @@ homelink.one, 4
homelinux.com, 4
homelinux.net, 4
homelinux.org, 4
+homeoffice.gov.uk, 4
homes, 0
homesecuritymac.com, 4
homesecuritypc.com, 4
@@ -3095,6 +3097,7 @@ ine.kyoto.jp, 0
inf.br, 0
inf.cu, 0
inf.mk, 0
+inf.ua, 4
infiniti, 0
info, 0
info.at, 4
@@ -3172,7 +3175,6 @@ ir, 0
iraq.museum, 0
iris.arpa, 0
irish, 0
-irkutsk.ru, 0
iron.museum, 0
iruma.saitama.jp, 0
is, 0
@@ -3299,8 +3301,7 @@ itoman.okinawa.jp, 0
its.me, 0
itv, 0
ivano-frankivsk.ua, 0
-ivanovo.ru, 0
-ivanovo.su, 0
+ivanovo.su, 4
iveco, 0
iveland.no, 0
ivgu.no, 0
@@ -3323,7 +3324,6 @@ iwi.nz, 0
iyo.ehime.jp, 0
iz.hr, 0
izena.okinawa.jp, 0
-izhevsk.ru, 0
izu.shizuoka.jp, 0
izumi.kagoshima.jp, 0
izumi.osaka.jp, 0
@@ -3335,10 +3335,9 @@ izumozaki.niigata.jp, 0
izunokuni.shizuoka.jp, 0
j.bg, 0
jaguar, 0
-jamal.ru, 0
+jambyl.su, 4
jamison.museum, 0
jan-mayen.no, 0
-jar.ru, 0
java, 0
jaworzno.pl, 0
jcb, 0
@@ -3380,7 +3379,6 @@ jolster.no, 0
jondal.no, 0
jor.br, 0
jorpeland.no, 0
-joshkar-ola.ru, 0
joso.ibaraki.jp, 0
jot, 0
journal.aero, 0
@@ -3405,7 +3403,6 @@ juniper, 0
jur.pro, 0
jus.br, 0
jx.cn, 0
-k-uralsk.ru, 0
k.bg, 0
k.se, 0
k12.ak.us, 0
@@ -3489,14 +3486,12 @@ kakinoki.shimane.jp, 0
kakogawa.hyogo.jp, 0
kakuda.miyagi.jp, 0
kalisz.pl, 0
-kalmykia.ru, 0
-kalmykia.su, 0
-kaluga.ru, 0
-kaluga.su, 0
+kalmykia.ru, 4
+kalmykia.su, 4
+kaluga.su, 4
kamagaya.chiba.jp, 0
kamaishi.iwate.jp, 0
kamakura.kanagawa.jp, 0
-kamchatka.ru, 0
kameoka.kyoto.jp, 0
kameyama.mie.jp, 0
kami.kochi.jp, 0
@@ -3542,13 +3537,14 @@ kanoya.kagoshima.jp, 0
kanra.gunma.jp, 0
kanuma.tochigi.jp, 0
kanzaki.saga.jp, 0
+karacol.su, 4
+karaganda.su, 4
karasjohka.no, 0
karasjok.no, 0
karasuyama.tochigi.jp, 0
karate.museum, 0
karatsu.saga.jp, 0
-karelia.ru, 0
-karelia.su, 0
+karelia.su, 4
karikatur.museum, 0
kariwa.niigata.jp, 0
kariya.aichi.jp, 0
@@ -3615,16 +3611,13 @@ kawatana.nagasaki.jp, 0
kawaue.gifu.jp, 0
kawazu.shizuoka.jp, 0
kayabe.hokkaido.jp, 0
-kazan.ru, 0
kazimierz-dolny.pl, 0
kazo.saitama.jp, 0
kazuno.akita.jp, 0
-kchr.ru, 0
kddi, 0
ke, 2
keisen.fukuoka.jp, 0
kembuchi.hokkaido.jp, 0
-kemerovo.ru, 0
kep.tr, 0
kepno.pl, 0
kerryhotels, 0
@@ -3637,15 +3630,12 @@ kg, 0
kg.kr, 0
kh, 2
kh.ua, 0
-khabarovsk.ru, 0
-khakassia.ru, 0
-khakassia.su, 0
+khakassia.su, 4
kharkiv.ua, 0
kharkov.ua, 0
kherson.ua, 0
khmelnitskiy.ua, 0
khmelnytskyi.ua, 0
-khv.ru, 0
ki, 0
kia, 0
kibichuo.okayama.jp, 0
@@ -3671,7 +3661,6 @@ kinko.kagoshima.jp, 0
kinokawa.wakayama.jp, 0
kira.aichi.jp, 0
kirkenes.no, 0
-kirov.ru, 0
kirovograd.ua, 0
kiryu.gunma.jp, 0
kisarazu.chiba.jp, 0
@@ -3717,7 +3706,6 @@ klodzko.pl, 0
km, 0
km.ua, 0
kmpsp.gov.pl, 0
-kms.ru, 0
kn, 0
knightpoint.systems, 4
knowsitall.info, 4
@@ -3731,7 +3719,6 @@ kodaira.tokyo.jp, 0
koebenhavn.museum, 0
koeln, 0
koeln.museum, 0
-koenig.ru, 0
kofu.yamanashi.jp, 0
koga.fukuoka.jp, 0
koga.ibaraki.jp, 0
@@ -3748,7 +3735,6 @@ komatsu, 0
komatsu.ishikawa.jp, 0
komatsushima.tokushima.jp, 0
komforb.se, 0
-komi.ru, 0
kommunalforbund.se, 0
kommune.no, 0
komono.mie.jp, 0
@@ -3773,7 +3759,6 @@ kosher, 0
koshigaya.saitama.jp, 0
koshimizu.hokkaido.jp, 0
koshu.yamanashi.jp, 0
-kostroma.ru, 0
kosuge.yamanashi.jp, 0
kota.aichi.jp, 0
koto.shiga.jp, 0
@@ -3800,8 +3785,7 @@ kr.ua, 0
kraanghke.no, 0
kragero.no, 0
krakow.pl, 4
-krasnodar.su, 0
-krasnoyarsk.ru, 0
+krasnodar.su, 4
krd, 0
kred, 0
kristiansand.no, 0
@@ -3811,7 +3795,6 @@ krokstadelva.no, 0
krym.ua, 0
ks.ua, 0
ks.us, 0
-kuban.ru, 0
kuchinotsu.nagasaki.jp, 0
kudamatsu.yamaguchi.jp, 0
kudoyama.wakayama.jp, 0
@@ -3845,8 +3828,7 @@ kuokgroup, 0
kurashiki.okayama.jp, 0
kurate.fukuoka.jp, 0
kure.hiroshima.jp, 0
-kurgan.ru, 0
-kurgan.su, 0
+kurgan.su, 4
kuriyama.hokkaido.jp, 0
kurobe.toyama.jp, 0
kurogi.fukuoka.jp, 0
@@ -3854,19 +3836,18 @@ kuroishi.aomori.jp, 0
kuroiso.tochigi.jp, 0
kuromatsunai.hokkaido.jp, 0
kurotaki.nara.jp, 0
-kursk.ru, 0
kurume.fukuoka.jp, 0
kusatsu.gunma.jp, 0
kusatsu.shiga.jp, 0
kushima.miyazaki.jp, 0
kushimoto.wakayama.jp, 0
kushiro.hokkaido.jp, 0
-kustanai.ru, 0
+kustanai.ru, 4
+kustanai.su, 4
kusu.oita.jp, 0
kutchan.hokkaido.jp, 0
kutno.pl, 0
kuwana.mie.jp, 0
-kuzbass.ru, 0
kuzumaki.iwate.jp, 0
kv.ua, 0
kvafjord.no, 0
@@ -3966,7 +3947,7 @@ leitungsen.de, 4
leka.no, 0
leksvik.no, 0
lel.br, 0
-lenug.su, 0
+lenug.su, 4
lenvik.no, 0
lerdal.no, 0
lesja.no, 0
@@ -4060,7 +4041,6 @@ linde, 0
lindesnes.no, 0
link, 0
linz.museum, 0
-lipetsk.ru, 0
lipsy, 0
live, 0
living, 0
@@ -4116,6 +4096,7 @@ ltd.cy, 0
ltd.gi, 0
ltd.hk, 4
ltd.lk, 0
+ltd.ua, 4
ltd.uk, 0
ltda, 0
lu, 0
@@ -4157,7 +4138,6 @@ mad.museum, 0
madrid, 0
madrid.museum, 0
maebashi.gunma.jp, 0
-magadan.ru, 0
magazine.aero, 0
magentosite.cloud, 6
maibara.shiga.jp, 0
@@ -4181,6 +4161,7 @@ management, 0
manchester.museum, 0
mandal.no, 0
mango, 0
+mangyshlak.su, 4
maniwa.okayama.jp, 0
manno.kagawa.jp, 0
mansion.museum, 0
@@ -4189,12 +4170,12 @@ mantova.it, 0
manx.museum, 0
maori.nz, 0
map, 0
+map.fastly.net, 4
+map.fastlylb.net, 4
mar.it, 0
marburg.museum, 0
marche.it, 0
-mari-el.ru, 0
-mari.ru, 0
-marine.ru, 0
+marine.ru, 4
maritime.museum, 0
maritimo.museum, 0
marker.no, 0
@@ -4284,6 +4265,7 @@ medizinhistorisches.museum, 0
meeres.museum, 0
meet, 0
meguro.tokyo.jp, 0
+mein-vigor.de, 4
meiwa.gunma.jp, 0
meiwa.mie.jp, 0
meland.no, 0
@@ -4549,8 +4531,8 @@ monzabrianza.it, 0
monzaebrianza.it, 0
monzaedellabrianza.it, 0
mopar, 0
-mordovia.ru, 0
-mordovia.su, 0
+mordovia.ru, 4
+mordovia.su, 4
moriguchi.osaka.jp, 0
morimachi.shizuoka.jp, 0
morioka.iwate.jp, 0
@@ -4590,8 +4572,8 @@ ms.kr, 0
ms.leg.br, 4
ms.us, 0
msd, 0
-msk.ru, 0
-msk.su, 0
+msk.ru, 4
+msk.su, 4
mt, 0
mt.eu.org, 4
mt.it, 0
@@ -4616,8 +4598,7 @@ mup.gov.pl, 0
murakami.niigata.jp, 0
murata.miyagi.jp, 0
murayama.yamagata.jp, 0
-murmansk.ru, 0
-murmansk.su, 0
+murmansk.su, 4
muroran.hokkaido.jp, 0
muroto.kochi.jp, 0
mus.br, 0
@@ -4646,6 +4627,8 @@ my, 0
my-firewall.org, 4
my-gateway.de, 4
my-router.de, 4
+my-vigor.de, 4
+my-wan.de, 4
my.eu.org, 4
my.id, 0
myactivedirectory.com, 4
@@ -4673,7 +4656,7 @@ mysecuritycamera.com, 4
mysecuritycamera.net, 4
mysecuritycamera.org, 4
myshopblocks.com, 4
-mytis.ru, 0
+mytis.ru, 4
myvnc.com, 4
mz, 0
n.bg, 0
@@ -4731,11 +4714,10 @@ nakatane.kagoshima.jp, 0
nakatombetsu.hokkaido.jp, 0
nakatsugawa.gifu.jp, 0
nakayama.yamagata.jp, 0
-nakhodka.ru, 0
nakijin.okinawa.jp, 0
naklo.pl, 0
-nalchik.ru, 0
-nalchik.su, 0
+nalchik.ru, 4
+nalchik.su, 4
namdalseid.no, 0
name, 0
name.az, 0
@@ -4808,6 +4790,7 @@ naumburg.museum, 0
naustdal.no, 0
naval.museum, 0
navigation.aero, 0
+navoi.su, 4
navuotna.no, 0
navy, 0
nayoro.hokkaido.jp, 0
@@ -4934,7 +4917,6 @@ net.ps, 0
net.pt, 0
net.py, 0
net.qa, 0
-net.ru, 0
net.rw, 0
net.sa, 0
net.sb, 0
@@ -5055,14 +5037,12 @@ nisshin.aichi.jp, 0
nittedal.no, 0
niyodogawa.kochi.jp, 0
nj.us, 0
-nkz.ru, 0
nl, 0
nl.ca, 0
nl.eu.org, 4
nl.no, 0
nm.cn, 0
nm.us, 0
-nnov.ru, 0
no, 0
no-ip.biz, 4
no-ip.ca, 4
@@ -5111,7 +5091,7 @@ nordre-land.no, 0
nordreisa.no, 0
nore-og-uvdal.no, 0
norfolk.museum, 0
-norilsk.ru, 0
+north-kazakhstan.su, 4
north.museum, 0
northwesternmutual, 0
norton, 0
@@ -5125,10 +5105,9 @@ noto.ishikawa.jp, 0
notodden.no, 0
notogawa.shiga.jp, 0
notteroy.no, 0
-nov.ru, 0
-nov.su, 0
+nov.ru, 4
+nov.su, 4
novara.it, 0
-novosibirsk.ru, 0
now, 0
now.sh, 4
nowaruda.pl, 0
@@ -5141,7 +5120,6 @@ nra, 0
nrw, 0
nrw.museum, 0
ns.ca, 0
-nsk.ru, 0
nsn.us, 0
nsupdate.info, 4
nsw.au, 0
@@ -5183,7 +5161,7 @@ obanazawa.yamagata.jp, 0
obi, 0
obihiro.hokkaido.jp, 0
obira.hokkaido.jp, 0
-obninsk.su, 0
+obninsk.su, 4
observer, 0
obu.aichi.jp, 0
obuse.nagano.jp, 0
@@ -5288,16 +5266,17 @@ omihachiman.shiga.jp, 0
omitama.ibaraki.jp, 0
omiya.saitama.jp, 0
omotego.fukushima.jp, 0
-omsk.ru, 0
omura.nagasaki.jp, 0
omuta.fukuoka.jp, 0
on-aptible.com, 4
on-the-web.tv, 4
+on-web.fr, 4
on.ca, 0
onagawa.miyagi.jp, 0
one, 0
ong, 0
onga.fukuoka.jp, 0
+onion, 0
onjuku.chiba.jp, 0
onl, 0
online, 0
@@ -5342,7 +5321,6 @@ oracle, 0
orange, 0
oregon.museum, 0
oregontrail.museum, 0
-orenburg.ru, 0
org, 0
org.ac, 0
org.ae, 0
@@ -5450,7 +5428,6 @@ org.py, 0
org.qa, 0
org.ro, 0
org.rs, 0
-org.ru, 0
org.sa, 0
org.sb, 0
org.sc, 0
@@ -5494,7 +5471,6 @@ orkdal.no, 0
orland.no, 0
orskog.no, 0
orsta.no, 0
-oryol.ru, 0
os.hedmark.no, 0
os.hordaland.no, 0
osaka, 0
@@ -5508,7 +5484,6 @@ oshima.tokyo.jp, 0
oshima.yamaguchi.jp, 0
oshino.yamanashi.jp, 0
oshu.iwate.jp, 0
-oskol.ru, 0
oslo.no, 0
osoyro.no, 0
osteroy.no, 0
@@ -5579,7 +5554,6 @@ page, 0
pagefrontapp.com, 4
pagespeedmobilizer.com, 4
palace.museum, 0
-palana.ru, 0
paleo.museum, 0
palermo.it, 0
palmsprings.museum, 0
@@ -5618,12 +5592,10 @@ pe.ca, 0
pe.it, 0
pe.kr, 0
pe.leg.br, 4
-penza.ru, 0
-penza.su, 0
+penza.su, 4
per.la, 0
per.nf, 0
per.sg, 0
-perm.ru, 0
perso.ht, 0
perso.sn, 0
perso.tn, 0
@@ -5714,7 +5686,7 @@ point2this.com, 4
pointto.us, 4
poivron.org, 4
poker, 0
-pokrovsk.su, 0
+pokrovsk.su, 4
pol.dz, 0
pol.ht, 0
pol.tr, 0
@@ -5740,7 +5712,6 @@ potenza.it, 0
powiat.pl, 0
poznan.pl, 4
pp.az, 0
-pp.ru, 0
pp.se, 0
pp.ua, 4
ppg.br, 0
@@ -5813,7 +5784,6 @@ pt, 0
pt.eu.org, 4
pt.it, 0
ptplus.fit, 4
-ptz.ru, 0
pu.it, 0
pub, 0
pub.sa, 0
@@ -5831,7 +5801,7 @@ pvt.k12.ma.us, 0
pw, 0
pwc, 0
py, 0
-pyatigorsk.ru, 0
+pyatigorsk.ru, 4
pz.it, 0
q-a.eu.org, 4
q.bg, 0
@@ -5917,6 +5887,7 @@ reklam.hu, 0
rel.ht, 0
rel.pl, 0
reliance, 0
+remotewd.com, 4
ren, 0
rendalen.no, 0
rennebu.no, 0
@@ -5972,12 +5943,10 @@ rm.it, 0
rmit, 0
rn.it, 0
rn.leg.br, 4
-rnd.ru, 0
rnrt.tn, 0
rns.tn, 0
rnu.tn, 0
ro, 0
-ro.com, 4
ro.eu.org, 4
ro.im, 4
ro.it, 0
@@ -6014,7 +5983,7 @@ rsvp, 0
ru, 0
ru.com, 4
ru.eu.org, 4
-rubtsovsk.ru, 0
+ru.net, 4
ruhr, 0
run, 0
ruovat.no, 0
@@ -6022,7 +5991,6 @@ russia.museum, 0
rv.ua, 0
rw, 0
rwe, 0
-ryazan.ru, 0
rybnik.pl, 0
rygge.no, 0
ryokami.saitama.jp, 0
@@ -6038,8 +6006,10 @@ s3-ap-northeast-2.amazonaws.com, 4
s3-ap-south-1.amazonaws.com, 4
s3-ap-southeast-1.amazonaws.com, 4
s3-ap-southeast-2.amazonaws.com, 4
+s3-ca-central-1.amazonaws.com, 4
s3-eu-central-1.amazonaws.com, 4
s3-eu-west-1.amazonaws.com, 4
+s3-eu-west-2.amazonaws.com, 4
s3-external-1.amazonaws.com, 4
s3-fips-us-gov-west-1.amazonaws.com, 4
s3-sa-east-1.amazonaws.com, 4
@@ -6057,23 +6027,29 @@ s3-website-us-west-1.amazonaws.com, 4
s3-website-us-west-2.amazonaws.com, 4
s3-website.ap-northeast-2.amazonaws.com, 4
s3-website.ap-south-1.amazonaws.com, 4
+s3-website.ca-central-1.amazonaws.com, 4
s3-website.eu-central-1.amazonaws.com, 4
+s3-website.eu-west-2.amazonaws.com, 4
s3-website.us-east-2.amazonaws.com, 4
s3.amazonaws.com, 4
s3.ap-northeast-2.amazonaws.com, 4
s3.ap-south-1.amazonaws.com, 4
+s3.ca-central-1.amazonaws.com, 4
s3.cn-north-1.amazonaws.com.cn, 4
s3.dualstack.ap-northeast-1.amazonaws.com, 4
s3.dualstack.ap-northeast-2.amazonaws.com, 4
s3.dualstack.ap-south-1.amazonaws.com, 4
s3.dualstack.ap-southeast-1.amazonaws.com, 4
s3.dualstack.ap-southeast-2.amazonaws.com, 4
+s3.dualstack.ca-central-1.amazonaws.com, 4
s3.dualstack.eu-central-1.amazonaws.com, 4
s3.dualstack.eu-west-1.amazonaws.com, 4
+s3.dualstack.eu-west-2.amazonaws.com, 4
s3.dualstack.sa-east-1.amazonaws.com, 4
s3.dualstack.us-east-1.amazonaws.com, 4
s3.dualstack.us-east-2.amazonaws.com, 4
s3.eu-central-1.amazonaws.com, 4
+s3.eu-west-2.amazonaws.com, 4
s3.us-east-2.amazonaws.com, 4
sa, 0
sa.au, 0
@@ -6114,7 +6090,6 @@ sakaki.nagano.jp, 0
sakata.yamagata.jp, 0
sakawa.kochi.jp, 0
sakegawa.yamagata.jp, 0
-sakhalin.ru, 0
saku.nagano.jp, 0
sakuho.nagano.jp, 0
sakura, 0
@@ -6132,7 +6107,6 @@ salon, 0
saltdal.no, 0
salvadordali.museum, 0
salzburg.museum, 0
-samara.ru, 0
samegawa.fukushima.jp, 0
samnanger.no, 0
samsclub, 0
@@ -6168,7 +6142,6 @@ sap, 0
sapo, 0
sapporo.jp, 2
sar.it, 0
-saratov.ru, 0
sardegna.it, 0
sardinia.it, 0
sarl, 0
@@ -6472,7 +6445,6 @@ sigdal.no, 0
siljan.no, 0
silk, 0
silk.museum, 0
-simbirsk.ru, 0
simple-url.com, 4
sina, 0
sinaapp.com, 4
@@ -6520,7 +6492,6 @@ sm.ua, 0
smart, 0
smile, 0
smola.no, 0
-smolensk.ru, 0
sn, 0
sn.cn, 0
snaase.no, 0
@@ -6528,14 +6499,13 @@ snasa.no, 0
sncf, 0
snillfjord.no, 0
snoasa.no, 0
-snz.ru, 0
so, 0
so.gov.pl, 0
so.it, 0
sobetsu.hokkaido.jp, 0
soc.lk, 0
soccer, 0
-sochi.su, 0
+sochi.su, 4
social, 0
society.museum, 0
sodegaura.chiba.jp, 0
@@ -6586,8 +6556,8 @@ space, 0
space-to-rent.com, 4
space.museum, 0
spacekit.io, 4
-spb.ru, 0
-spb.su, 0
+spb.ru, 4
+spb.su, 4
spdns.de, 4
spdns.eu, 4
spdns.org, 4
@@ -6635,7 +6605,6 @@ station.museum, 0
statoil, 0
stavanger.no, 0
stavern.no, 0
-stavropol.ru, 0
stc, 0
stcgroup, 0
steam.museum, 0
@@ -6673,7 +6642,6 @@ stuff-4-sale.org, 4
stuff-4-sale.us, 4
stufftoread.com, 4
stuttgart.museum, 0
-stv.ru, 0
style, 0
su, 0
sucks, 0
@@ -6703,7 +6671,6 @@ support, 0
surf, 0
surgeonshall.museum, 0
surgery, 0
-surgut.ru, 0
surnadal.no, 0
surrey.museum, 0
susaki.kochi.jp, 0
@@ -6735,10 +6702,12 @@ sydney, 0
sydney.museum, 0
sykkylven.no, 0
symantec, 0
+syno-ds.de, 4
+synology-diskstation.de, 4
+synology-ds.de, 4
synology.me, 4
systems, 0
sytes.net, 4
-syzran.ru, 0
sz, 0
szczecin.pl, 0
szczytno.pl, 0
@@ -6746,6 +6715,7 @@ szex.hu, 0
szkola.pl, 0
t.bg, 0
t.se, 0
+t3l3p0rt.net, 4
ta.it, 0
taa.it, 0
tab, 0
@@ -6821,7 +6791,6 @@ tamano.okayama.jp, 0
tamatsukuri.ibaraki.jp, 0
tamayu.shimane.jp, 0
tamba.hyogo.jp, 0
-tambov.ru, 0
tana.no, 0
tanabe.kyoto.jp, 0
tanabe.wakayama.jp, 0
@@ -6841,9 +6810,9 @@ tarumizu.kagoshima.jp, 0
tas.au, 0
tas.edu.au, 0
tas.gov.au, 0
+tashkent.su, 4
tatamotors, 0
tatar, 0
-tatarstan.ru, 0
tatebayashi.gunma.jp, 0
tateshina.nagano.jp, 0
tateyama.chiba.jp, 0
@@ -6870,6 +6839,7 @@ technology, 0
technology.museum, 0
tel, 0
tel.tr, 0
+tele.amune.org, 4
telecity, 0
telefonica, 0
telekommunikation.museum, 0
@@ -6884,6 +6854,7 @@ tennis, 0
tenri.nara.jp, 0
teo.br, 0
teramo.it, 0
+termez.su, 4
terni.it, 0
ternopil.ua, 0
teshikaga.hokkaido.jp, 0
@@ -6957,7 +6928,7 @@ toga.toyama.jp, 0
togakushi.nagano.jp, 0
togane.chiba.jp, 0
togitsu.nagasaki.jp, 0
-togliatti.su, 0
+togliatti.su, 4
togo.aichi.jp, 0
togura.nagano.jp, 0
tohma.hokkaido.jp, 0
@@ -6978,7 +6949,6 @@ tokuyama.yamaguchi.jp, 0
tokyo, 0
tokyo.jp, 0
tolga.no, 0
-tom.ru, 0
tomakomai.hokkaido.jp, 0
tomari.hokkaido.jp, 0
tome.miyagi.jp, 0
@@ -6989,7 +6959,6 @@ tomioka.gunma.jp, 0
tomisato.chiba.jp, 0
tomiya.miyagi.jp, 0
tomobe.ibaraki.jp, 0
-tomsk.ru, 0
tonaki.okinawa.jp, 0
tonami.toyama.jp, 0
tondabayashi.osaka.jp, 0
@@ -7107,7 +7076,7 @@ trieste.it, 0
triton.zone, 6
troandin.no, 0
trogstad.no, 0
-troitsk.su, 0
+troitsk.su, 4
trolley.museum, 0
tromsa.no, 0
tromso.no, 0
@@ -7118,8 +7087,7 @@ trustee.museum, 0
trv, 0
trysil.no, 0
ts.it, 0
-tsaritsyn.ru, 0
-tsk.ru, 0
+tselinograd.su, 4
tsu.mie.jp, 0
tsubame.niigata.jp, 0
tsubata.ishikawa.jp, 0
@@ -7151,8 +7119,7 @@ tt, 0
tt.im, 0
tube, 0
tui, 0
-tula.ru, 0
-tula.su, 0
+tula.su, 4
tunes, 0
tunk.org, 4
tur.ar, 0
@@ -7163,8 +7130,7 @@ turin.it, 0
turystyka.pl, 0
tuscany.it, 0
tushu, 0
-tuva.ru, 0
-tuva.su, 0
+tuva.su, 4
tuxfamily.org, 4
tv, 0
tv.bb, 0
@@ -7177,7 +7143,6 @@ tv.sd, 0
tv.tr, 0
tv.tz, 0
tvedestrand.no, 0
-tver.ru, 0
tvs, 0
tw, 0
tw.cn, 0
@@ -7188,7 +7153,6 @@ tynset.no, 0
tysfjord.no, 0
tysnes.no, 0
tysvar.no, 0
-tyumen.ru, 0
tz, 0
u.bg, 0
u.se, 0
@@ -7204,8 +7168,6 @@ uconnect, 0
ud.it, 0
uda.nara.jp, 0
udine.it, 0
-udm.ru, 0
-udmurtia.ru, 0
udono.mie.jp, 0
ueda.nagano.jp, 0
ueno.gunma.jp, 0
@@ -7224,7 +7186,6 @@ uk.eu.org, 4
uk.net, 4
uki.kumamoto.jp, 0
ukiha.fukuoka.jp, 0
-ulan-ude.ru, 0
ullensaker.no, 0
ullensvang.no, 0
ulm.museum, 0
@@ -7282,6 +7243,7 @@ usarts.museum, 0
uscountryestate.museum, 0
usculture.museum, 0
usdecorativearts.museum, 0
+user.party.eus, 4
usgarden.museum, 0
ushiku.ibaraki.jp, 0
ushistory.museum, 0
@@ -7349,7 +7311,6 @@ vb.it, 0
vc, 0
vc.it, 0
vda.it, 0
-vdonsk.ru, 0
ve, 0
ve.it, 0
vefsn.no, 0
@@ -7422,25 +7383,21 @@ viva, 0
vivo, 0
vlaanderen, 0
vlaanderen.museum, 0
-vladikavkaz.ru, 0
-vladikavkaz.su, 0
-vladimir.ru, 0
-vladimir.su, 0
-vladivostok.ru, 0
+vladikavkaz.ru, 4
+vladikavkaz.su, 4
+vladimir.ru, 4
+vladimir.su, 4
vlog.br, 0
vn, 0
vn.ua, 0
voagat.no, 0
vodka, 0
volda.no, 0
-volgograd.ru, 0
volkenkunde.museum, 0
volkswagen, 0
-vologda.ru, 0
-vologda.su, 0
+vologda.su, 4
volvo, 0
volyn.ua, 0
-voronezh.ru, 0
voss.no, 0
vossevangen.no, 0
vote, 0
@@ -7448,14 +7405,12 @@ voting, 0
voto, 0
voyage, 0
vr.it, 0
-vrn.ru, 0
vs.it, 0
vt.it, 0
vt.us, 0
vu, 0
vuelos, 0
vv.it, 0
-vyatka.ru, 0
w.bg, 0
w.se, 0
wa.au, 0
@@ -8019,7 +7974,6 @@ yaizu.shizuoka.jp, 0
yakage.okayama.jp, 0
yakumo.hokkaido.jp, 0
yakumo.shimane.jp, 0
-yakutia.ru, 0
yalta.ua, 0
yamada.fukuoka.jp, 0
yamada.iwate.jp, 0
@@ -8032,7 +7986,6 @@ yamagata.nagano.jp, 0
yamagata.yamagata.jp, 0
yamaguchi.jp, 0
yamakita.kanagawa.jp, 0
-yamal.ru, 0
yamamoto.miyagi.jp, 0
yamanakako.yamanashi.jp, 0
yamanashi.jp, 0
@@ -8054,7 +8007,6 @@ yanaizu.fukushima.jp, 0
yandex, 0
yao.osaka.jp, 0
yaotsu.gifu.jp, 0
-yaroslavl.ru, 0
yasaka.nagano.jp, 0
yashio.saitama.jp, 0
yashiro.hyogo.jp, 0
@@ -8075,7 +8027,6 @@ ybo.review, 4
ybo.science, 4
ybo.trade, 4
ye, 2
-yekaterinburg.ru, 0
yk.ca, 0
yn.cn, 0
yodobashi, 0
@@ -8131,7 +8082,6 @@ yusui.kagoshima.jp, 0
yuu.yamaguchi.jp, 0
yuza.yamagata.jp, 0
yuzawa.niigata.jp, 0
-yuzhno-sakhalinsk.ru, 0
z.bg, 0
z.se, 0
za, 0
@@ -8155,7 +8105,6 @@ zentsuji.kagawa.jp, 0
zero, 0
zgora.pl, 0
zgorzelec.pl, 0
-zgrad.ru, 0
zhitomir.ua, 0
zhytomyr.ua, 0
zip, 0
diff --git a/chromium/net/base/registry_controlled_domains/registry_controlled_domain.cc b/chromium/net/base/registry_controlled_domains/registry_controlled_domain.cc
index 5af090a891a..3777582812b 100644
--- a/chromium/net/base/registry_controlled_domains/registry_controlled_domain.cc
+++ b/chromium/net/base/registry_controlled_domains/registry_controlled_domain.cc
@@ -54,6 +54,7 @@
#include "url/gurl.h"
#include "url/origin.h"
#include "url/third_party/mozilla/url_parse.h"
+#include "url/url_util.h"
namespace net {
namespace registry_controlled_domains {
@@ -190,10 +191,9 @@ base::StringPiece GetDomainAndRegistryImpl(
// TODO(pkalinnikov): Eliminate this helper by exposing StringPiece as the
// interface type for all the APIs.
base::StringPiece GetDomainAndRegistryAsStringPiece(
- const GURL& gurl,
+ base::StringPiece host,
PrivateRegistryFilter filter) {
- base::StringPiece host = gurl.host_piece();
- if (host.empty() || gurl.HostIsIPAddress())
+ if (host.empty() || url::HostIsIPAddress(host))
return base::StringPiece();
return GetDomainAndRegistryImpl(host, filter);
}
@@ -309,11 +309,31 @@ size_t DoPermissiveGetHostRegistryLength(base::BasicStringPiece<Str> host,
return canonical_rcd_len;
}
+bool SameDomainOrHost(base::StringPiece host1,
+ base::StringPiece host2,
+ PrivateRegistryFilter filter) {
+ // Quickly reject cases where either host is empty.
+ if (host1.empty() || host2.empty())
+ return false;
+
+ // Check for exact host matches, which is faster than looking up the domain
+ // and registry.
+ if (host1 == host2)
+ return true;
+
+ // Check for a domain and registry match.
+ const base::StringPiece& domain1 =
+ GetDomainAndRegistryAsStringPiece(host1, filter);
+ return !domain1.empty() &&
+ (domain1 == GetDomainAndRegistryAsStringPiece(host2, filter));
+}
+
} // namespace
std::string GetDomainAndRegistry(const GURL& gurl,
PrivateRegistryFilter filter) {
- return GetDomainAndRegistryAsStringPiece(gurl, filter).as_string();
+ return GetDomainAndRegistryAsStringPiece(gurl.host_piece(), filter)
+ .as_string();
}
std::string GetDomainAndRegistry(base::StringPiece host,
@@ -329,34 +349,26 @@ bool SameDomainOrHost(
const GURL& gurl1,
const GURL& gurl2,
PrivateRegistryFilter filter) {
- // Quickly reject cases where either host is empty.
- if (!gurl1.has_host() || !gurl2.has_host())
- return false;
-
- // Check for exact host matches, which is faster than looking up the domain
- // and registry.
- if (gurl1.host_piece() == gurl2.host_piece())
- return true;
-
- // Check for a domain and registry match.
- const base::StringPiece& domain1 =
- GetDomainAndRegistryAsStringPiece(gurl1, filter);
- return !domain1.empty() &&
- (domain1 == GetDomainAndRegistryAsStringPiece(gurl2, filter));
+ return SameDomainOrHost(gurl1.host_piece(), gurl2.host_piece(), filter);
}
bool SameDomainOrHost(const url::Origin& origin1,
const url::Origin& origin2,
PrivateRegistryFilter filter) {
- return SameDomainOrHost(origin1.GetURL(), origin2.GetURL(), filter);
+ return SameDomainOrHost(origin1.host(), origin2.host(), filter);
}
bool SameDomainOrHost(const url::Origin& origin1,
const base::Optional<url::Origin>& origin2,
PrivateRegistryFilter filter) {
- if (!origin2.has_value())
- return false;
- return SameDomainOrHost(origin1, origin2.value(), filter);
+ return origin2.has_value() &&
+ SameDomainOrHost(origin1, origin2.value(), filter);
+}
+
+bool SameDomainOrHost(const GURL& gurl,
+ const url::Origin& origin,
+ PrivateRegistryFilter filter) {
+ return SameDomainOrHost(gurl.host_piece(), origin.host(), filter);
}
size_t GetRegistryLength(
diff --git a/chromium/net/base/registry_controlled_domains/registry_controlled_domain.h b/chromium/net/base/registry_controlled_domains/registry_controlled_domain.h
index 429a5770cc2..9f3101a5c4a 100644
--- a/chromium/net/base/registry_controlled_domains/registry_controlled_domain.h
+++ b/chromium/net/base/registry_controlled_domains/registry_controlled_domain.h
@@ -204,6 +204,9 @@ NET_EXPORT bool SameDomainOrHost(const url::Origin& origin1,
NET_EXPORT bool SameDomainOrHost(const url::Origin& origin1,
const base::Optional<url::Origin>& origin2,
PrivateRegistryFilter filter);
+NET_EXPORT bool SameDomainOrHost(const GURL& gurl,
+ const url::Origin& origin,
+ PrivateRegistryFilter filter);
// Finds the length in bytes of the registrar portion of the host in the
// given GURL. Returns std::string::npos if the GURL is invalid or has no
diff --git a/chromium/net/base/sdch_dictionary.h b/chromium/net/base/sdch_dictionary.h
index c2fb7c87bf9..4d0ddbc80d3 100644
--- a/chromium/net/base/sdch_dictionary.h
+++ b/chromium/net/base/sdch_dictionary.h
@@ -17,11 +17,6 @@
#include "net/base/sdch_problem_codes.h"
#include "url/gurl.h"
-namespace base {
-class Clock;
-class Value;
-}
-
namespace net {
// Contains all information for an SDCH dictionary. This class is intended
diff --git a/chromium/net/base/sdch_manager.cc b/chromium/net/base/sdch_manager.cc
index e57d73cfb24..d577db8436c 100644
--- a/chromium/net/base/sdch_manager.cc
+++ b/chromium/net/base/sdch_manager.cc
@@ -13,7 +13,10 @@
#include "base/metrics/histogram_macros.h"
#include "base/strings/string_number_conversions.h"
#include "base/strings/string_util.h"
+#include "base/strings/stringprintf.h"
#include "base/time/default_clock.h"
+#include "base/trace_event/memory_allocator_dump.h"
+#include "base/trace_event/process_memory_dump.h"
#include "base/values.h"
#include "crypto/sha2.h"
#include "net/base/parse_number.h"
@@ -324,6 +327,36 @@ void SdchManager::RemoveObserver(SdchObserver* observer) {
observers_.RemoveObserver(observer);
}
+void SdchManager::DumpMemoryStats(
+ base::trace_event::ProcessMemoryDump* pmd,
+ const std::string& parent_dump_absolute_name) const {
+ // If there are no dictionaries stored, return early without creating a new
+ // MemoryAllocatorDump.
+ size_t total_count = dictionaries_.size();
+ if (total_count == 0)
+ return;
+ std::string name = base::StringPrintf("net/sdch_manager_%p", this);
+ base::trace_event::MemoryAllocatorDump* dump = pmd->GetAllocatorDump(name);
+ if (dump == nullptr) {
+ dump = pmd->CreateAllocatorDump(name);
+ size_t total_size = 0;
+ for (const auto& dictionary : dictionaries_) {
+ total_size += dictionary.second->data.text().size();
+ }
+ dump->AddScalar(base::trace_event::MemoryAllocatorDump::kNameSize,
+ base::trace_event::MemoryAllocatorDump::kUnitsBytes,
+ total_size);
+ dump->AddScalar(base::trace_event::MemoryAllocatorDump::kNameObjectCount,
+ base::trace_event::MemoryAllocatorDump::kUnitsObjects,
+ total_count);
+ }
+ // Create an empty row under parent's dump so size can be attributed correctly
+ // if |this| is shared between URLRequestContexts.
+ base::trace_event::MemoryAllocatorDump* empty_row_dump =
+ pmd->CreateAllocatorDump(parent_dump_absolute_name + "/sdch_manager");
+ pmd->AddOwnershipEdge(empty_row_dump->guid(), dump->guid());
+}
+
SdchProblemCode SdchManager::AddSdchDictionary(
const std::string& dictionary_text,
const GURL& dictionary_url,
diff --git a/chromium/net/base/sdch_manager.h b/chromium/net/base/sdch_manager.h
index dcb47717851..1db8105e9a8 100644
--- a/chromium/net/base/sdch_manager.h
+++ b/chromium/net/base/sdch_manager.h
@@ -32,6 +32,10 @@ class GURL;
namespace base {
class Value;
+
+namespace trace_event {
+class ProcessMemoryDump;
+}
}
namespace net {
@@ -195,6 +199,11 @@ class NET_EXPORT SdchManager {
void AddObserver(SdchObserver* observer);
void RemoveObserver(SdchObserver* observer);
+ // Dumps memory allocation stats. |parent_dump_absolute_name| is the name
+ // used by the parent MemoryAllocatorDump in the memory dump hierarchy.
+ void DumpMemoryStats(base::trace_event::ProcessMemoryDump* pmd,
+ const std::string& parent_dump_absolute_name) const;
+
// Logs an SDCH failure to UMA and |netlog|.
static void LogSdchProblem(NetLogWithSource netlog, SdchProblemCode problem);
diff --git a/chromium/net/base/sdch_manager_unittest.cc b/chromium/net/base/sdch_manager_unittest.cc
index bfdb78fc7ca..31162841b6c 100644
--- a/chromium/net/base/sdch_manager_unittest.cc
+++ b/chromium/net/base/sdch_manager_unittest.cc
@@ -11,8 +11,12 @@
#include "base/logging.h"
#include "base/macros.h"
+#include "base/strings/string_number_conversions.h"
#include "base/strings/stringprintf.h"
#include "base/test/simple_test_clock.h"
+#include "base/trace_event/memory_allocator_dump.h"
+#include "base/trace_event/process_memory_dump.h"
+#include "base/trace_event/trace_event_argument.h"
#include "net/base/sdch_observer.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "url/gurl.h"
@@ -636,4 +640,58 @@ TEST_F(SdchManagerTest, AddRemoveNotifications) {
sdch_manager()->RemoveObserver(&observer);
}
+TEST_F(SdchManagerTest, DumpMemoryStats) {
+ MockSdchObserver observer;
+ sdch_manager()->AddObserver(&observer);
+
+ std::string dictionary_domain("x.y.z.google.com");
+ GURL target_gurl("http://" + dictionary_domain);
+ std::string dictionary_text(NewSdchDictionary(dictionary_domain));
+ std::string client_hash;
+ std::string server_hash;
+ SdchManager::GenerateHash(dictionary_text, &client_hash, &server_hash);
+ EXPECT_TRUE(AddSdchDictionary(dictionary_text, target_gurl));
+ EXPECT_EQ(1, observer.dictionary_added_notifications());
+ EXPECT_EQ(target_gurl, observer.last_dictionary_url());
+ EXPECT_EQ(server_hash, observer.last_server_hash());
+
+ base::trace_event::MemoryDumpArgs dump_args = {
+ base::trace_event::MemoryDumpLevelOfDetail::DETAILED};
+ std::unique_ptr<base::trace_event::ProcessMemoryDump> pmd(
+ new base::trace_event::ProcessMemoryDump(nullptr, dump_args));
+
+ base::trace_event::MemoryAllocatorDump* parent =
+ pmd->CreateAllocatorDump("parent");
+ sdch_manager()->DumpMemoryStats(pmd.get(), parent->absolute_name());
+
+ const base::trace_event::MemoryAllocatorDump* sub_dump =
+ pmd->GetAllocatorDump("parent/sdch_manager");
+ ASSERT_NE(nullptr, sub_dump);
+ const base::trace_event::MemoryAllocatorDump* dump = pmd->GetAllocatorDump(
+ base::StringPrintf("net/sdch_manager_%p", sdch_manager()));
+ std::unique_ptr<base::Value> raw_attrs =
+ dump->attributes_for_testing()->ToBaseValue();
+ base::DictionaryValue* attrs;
+ ASSERT_TRUE(raw_attrs->GetAsDictionary(&attrs));
+ base::DictionaryValue* size_attrs;
+ ASSERT_TRUE(attrs->GetDictionary(
+ base::trace_event::MemoryAllocatorDump::kNameSize, &size_attrs));
+ size_t offset = dictionary_text.find("\n\n") + 2;
+ std::string size;
+ ASSERT_TRUE(size_attrs->GetString("value", &size));
+ int actual_size;
+ ASSERT_TRUE(base::HexStringToInt(size, &actual_size));
+ EXPECT_EQ(dictionary_text.size() - offset, static_cast<size_t>(actual_size));
+
+ base::DictionaryValue* count_attrs;
+ ASSERT_TRUE(attrs->GetDictionary(
+ base::trace_event::MemoryAllocatorDump::kNameObjectCount, &count_attrs));
+ std::string count;
+ ASSERT_TRUE(count_attrs->GetString("value", &count));
+ // One dictionary.
+ EXPECT_EQ("1", count);
+
+ sdch_manager()->RemoveObserver(&observer);
+}
+
} // namespace net
diff --git a/chromium/net/base/sdch_observer.h b/chromium/net/base/sdch_observer.h
index b2311de88f8..927e88d7ab6 100644
--- a/chromium/net/base/sdch_observer.h
+++ b/chromium/net/base/sdch_observer.h
@@ -56,4 +56,4 @@ class NET_EXPORT SdchObserver {
} // namespace net
-#endif // NET_BASE_SDCH_MANAGER_H_
+#endif // NET_BASE_SDCH_OBSERVER_H_
diff --git a/chromium/net/base/sys_addrinfo.h b/chromium/net/base/sys_addrinfo.h
index 78f491c0263..1799fc2dd12 100644
--- a/chromium/net/base/sys_addrinfo.h
+++ b/chromium/net/base/sys_addrinfo.h
@@ -15,6 +15,9 @@
// Prefer including this file instead of directly writing the #if / #else,
// since it avoids duplicating the platform-specific selections.
+#ifndef NET_BASE_SYS_ADDRINFO_H_
+#define NET_BASE_SYS_ADDRINFO_H_
+
#include "build/build_config.h"
#if defined(OS_WIN)
@@ -24,3 +27,5 @@
#include <netinet/in.h>
#include <sys/socket.h>
#endif
+
+#endif // NET_BASE_SYS_ADDRINFO_H_
diff --git a/chromium/net/base/test_completion_callback.cc b/chromium/net/base/test_completion_callback.cc
index 07658503673..c50ba8cf74a 100644
--- a/chromium/net/base/test_completion_callback.cc
+++ b/chromium/net/base/test_completion_callback.cc
@@ -27,10 +27,6 @@ void TestCompletionCallbackBaseInternal::WaitForResult() {
run_loop_->Run();
run_loop_.reset();
DCHECK(have_result_);
- // A huge number of tests depend on this class running events after the
- // result is set.
- // TODO(mmenke): We really should fix this.
- base::RunLoop().RunUntilIdle();
}
have_result_ = false; // Auto-reset for next callback.
}
diff --git a/chromium/net/base/test_completion_callback_unittest.cc b/chromium/net/base/test_completion_callback_unittest.cc
index a2bc49092dd..db62f7e6ae3 100644
--- a/chromium/net/base/test_completion_callback_unittest.cc
+++ b/chromium/net/base/test_completion_callback_unittest.cc
@@ -2,15 +2,14 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-// Illustrates how to use worker threads that issue completion callbacks
+// Illustrates how to use net::TestCompletionCallback.
#include "base/bind.h"
#include "base/location.h"
#include "base/logging.h"
#include "base/macros.h"
-#include "base/message_loop/message_loop.h"
#include "base/single_thread_task_runner.h"
-#include "base/threading/worker_pool.h"
+#include "base/threading/thread_task_runner_handle.h"
#include "net/base/completion_callback.h"
#include "net/base/test_completion_callback.h"
#include "testing/gtest/include/gtest/gtest.h"
@@ -38,9 +37,8 @@ class ExampleEmployer {
ExampleEmployer();
~ExampleEmployer();
- // Do some imaginary work on a worker thread;
- // when done, worker posts callback on the original thread.
- // Returns true on success
+ // Posts to the current thread a task which itself posts |callback| to the
+ // current thread. Returns true on success
bool DoSomething(const CompletionCallback& callback);
private:
@@ -50,14 +48,12 @@ class ExampleEmployer {
DISALLOW_COPY_AND_ASSIGN(ExampleEmployer);
};
-// Helper class; this is how ExampleEmployer puts work on a different thread
+// Helper class; this is how ExampleEmployer schedules work.
class ExampleEmployer::ExampleWorker
: public base::RefCountedThreadSafe<ExampleWorker> {
public:
ExampleWorker(ExampleEmployer* employer, const CompletionCallback& callback)
- : employer_(employer),
- callback_(callback),
- origin_loop_(base::MessageLoop::current()) {}
+ : employer_(employer), callback_(callback) {}
void DoWork();
void DoCallback();
private:
@@ -69,23 +65,15 @@ class ExampleEmployer::ExampleWorker
ExampleEmployer* employer_;
CompletionCallback callback_;
// Used to post ourselves onto the origin thread.
- base::Lock origin_loop_lock_;
- base::MessageLoop* origin_loop_;
+ const scoped_refptr<base::SingleThreadTaskRunner> origin_task_runner_ =
+ base::ThreadTaskRunnerHandle::Get();
};
void ExampleEmployer::ExampleWorker::DoWork() {
- // Running on the worker thread
// In a real worker thread, some work would be done here.
// Pretend it is, and send the completion callback.
-
- // The origin loop could go away while we are trying to post to it, so we
- // need to call its PostTask method inside a lock. See ~ExampleEmployer.
- {
- base::AutoLock locked(origin_loop_lock_);
- if (origin_loop_)
- origin_loop_->task_runner()->PostTask(
- FROM_HERE, base::Bind(&ExampleWorker::DoCallback, this));
- }
+ origin_task_runner_->PostTask(FROM_HERE,
+ base::Bind(&ExampleWorker::DoCallback, this));
}
void ExampleEmployer::ExampleWorker::DoCallback() {
@@ -110,9 +98,8 @@ bool ExampleEmployer::DoSomething(const CompletionCallback& callback) {
request_ = new ExampleWorker(this, callback);
- // Dispatch to worker thread...
- if (!base::WorkerPool::PostTask(
- FROM_HERE, base::Bind(&ExampleWorker::DoWork, request_), true)) {
+ if (!base::ThreadTaskRunnerHandle::Get()->PostTask(
+ FROM_HERE, base::Bind(&ExampleWorker::DoWork, request_))) {
NOTREACHED();
request_ = NULL;
return false;
diff --git a/chromium/net/base/test_data_stream.cc b/chromium/net/base/test_data_stream.cc
index 66728043011..b77642150a4 100644
--- a/chromium/net/base/test_data_stream.cc
+++ b/chromium/net/base/test_data_stream.cc
@@ -65,4 +65,3 @@ void TestDataStream::Consume(int bytes) {
}
} // namespace net
-
diff --git a/chromium/net/base/test_proxy_delegate.cc b/chromium/net/base/test_proxy_delegate.cc
index bfaa28e1dc0..66fd1a9bad6 100644
--- a/chromium/net/base/test_proxy_delegate.cc
+++ b/chromium/net/base/test_proxy_delegate.cc
@@ -101,4 +101,4 @@ ProxyServer TestProxyDelegate::GetDefaultAlternativeProxy() const {
return alternative_proxy_server_;
}
-} // namespace net \ No newline at end of file
+} // namespace net
diff --git a/chromium/net/base/test_proxy_delegate.h b/chromium/net/base/test_proxy_delegate.h
index dea1e609930..373995306d2 100644
--- a/chromium/net/base/test_proxy_delegate.h
+++ b/chromium/net/base/test_proxy_delegate.h
@@ -19,7 +19,6 @@ class HttpRequestHeaders;
class HttpResponseHeaders;
class ProxyInfo;
class ProxyService;
-class URLRequest;
class TestProxyDelegate : public ProxyDelegate {
public:
@@ -103,4 +102,4 @@ class TestProxyDelegate : public ProxyDelegate {
} // namespace net
-#endif // NET_BASE_TEST_PROXY_DELEGATE_H_ \ No newline at end of file
+#endif // NET_BASE_TEST_PROXY_DELEGATE_H_
diff --git a/chromium/net/cert/internal/completion_status.h b/chromium/net/base/trace_constants.cc
index 69126cd6010..ceade2cab01 100644
--- a/chromium/net/cert/internal/completion_status.h
+++ b/chromium/net/base/trace_constants.cc
@@ -2,16 +2,12 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#ifndef NET_CERT_INTERNAL_COMPLETION_STATUS_H_
-#define NET_CERT_INTERNAL_COMPLETION_STATUS_H_
+#include "net/base/trace_constants.h"
+
+#include "base/trace_event/common/trace_event_common.h"
namespace net {
-enum class CompletionStatus {
- SYNC,
- ASYNC,
-};
+const char kNetTracingCategory[] = TRACE_DISABLED_BY_DEFAULT("net");
} // namespace net
-
-#endif // NET_CERT_INTERNAL_COMPLETION_STATUS_H_
diff --git a/chromium/net/base/trace_constants.h b/chromium/net/base/trace_constants.h
new file mode 100644
index 00000000000..dc5d84aabc2
--- /dev/null
+++ b/chromium/net/base/trace_constants.h
@@ -0,0 +1,15 @@
+// Copyright 2016 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.
+
+#ifndef NET_BASE_TRACE_CONSTANTS_H_
+#define NET_BASE_TRACE_CONSTANTS_H_
+
+namespace net {
+
+// Net Category used in Tracing.
+extern const char kNetTracingCategory[];
+
+} // namespace net
+
+#endif // NET_BASE_TRACE_CONSTANTS_H_
diff --git a/chromium/net/base/upload_data_stream.h b/chromium/net/base/upload_data_stream.h
index 6b8f1bffb0c..b84e3d930a9 100644
--- a/chromium/net/base/upload_data_stream.h
+++ b/chromium/net/base/upload_data_stream.h
@@ -18,7 +18,6 @@
namespace net {
-class DrainableIOBuffer;
class IOBuffer;
class UploadElementReader;
diff --git a/chromium/net/base/url_util.cc b/chromium/net/base/url_util.cc
index 111c95400a8..062481fef39 100644
--- a/chromium/net/base/url_util.cc
+++ b/chromium/net/base/url_util.cc
@@ -373,6 +373,9 @@ bool IsLocalhost(base::StringPiece host) {
GURL SimplifyUrlForRequest(const GURL& url) {
DCHECK(url.is_valid());
+ // Fast path to avoid re-canonicalization via ReplaceComponents.
+ if (!url.has_username() && !url.has_password() && !url.has_ref())
+ return url;
GURL::Replacements replacements;
replacements.ClearUsername();
replacements.ClearPassword();
diff --git a/chromium/net/cert/cert_net_fetcher.h b/chromium/net/cert/cert_net_fetcher.h
index f8344702bea..2a45fe3b6f7 100644
--- a/chromium/net/cert/cert_net_fetcher.h
+++ b/chromium/net/cert/cert_net_fetcher.h
@@ -19,59 +19,42 @@ class GURL;
namespace net {
-class URLRequestContext;
-
-// CertNetFetcher is an asynchronous interface for fetching AIA URLs and CRL
-// URLs.
-//
-// -------------------------
-// Cancellation of requests
-// -------------------------
-//
-// * Network requests started by the CertNetFetcher can be cancelled by
-// deleting the Request object. Cancellation means the request's callback
-// will no longer be invoked.
-//
-// * If the CertNetFetcher is deleted then any outstanding
-// requests are automatically cancelled.
-//
-// * Cancelling a request within the execution of a callback is allowed.
-//
-// * Deleting the CertNetFetcher from within the execution of a callback is
-// allowed.
-//
-// -------------------------
-// Threading
-// -------------------------
+// CertNetFetcher is a synchronous interface for fetching AIA URLs and CRL
+// URLs. It is shared between a caller thread (which starts and waits for
+// fetches), and a network thread (which does the actual fetches). It can be
+// shutdown from the network thread to cancel outstanding requests.
//
-// The CertNetFetcher is expected to be operated from a single thread, which has
-// an IO message loop. The URLRequestContext will be accessed from this same
-// thread, and callbacks will be posted to this message loop.
-//
-// For more details see the design document:
-// https://docs.google.com/a/chromium.org/document/d/1CdS9YOnPdAyVZBJqHY7ZJ6tUlU71OCvX8kHnaVhf144/edit
-class NET_EXPORT CertNetFetcher {
+// A Request object is returned when starting a fetch. The consumer can
+// use this as a handle for aborting the request (by freeing it), or reading
+// the result of the request (WaitForResult)
+class NET_EXPORT CertNetFetcher
+ : public base::RefCountedThreadSafe<CertNetFetcher> {
public:
class Request {
public:
virtual ~Request() {}
- };
- // Callback invoked on request completion. If the Error is OK, then the
- // vector contains the response bytes.
- using FetchCallback =
- base::Callback<void(Error, const std::vector<uint8_t>&)>;
+ // WaitForResult() can be called at most once.
+ //
+ // It will block and wait for the (network) request to complete, and
+ // then write the result into the provided out-parameters.
+ virtual void WaitForResult(Error* error, std::vector<uint8_t>* bytes) = 0;
+ };
// This value can be used in place of timeout or max size limits.
enum { DEFAULT = -1 };
CertNetFetcher() {}
- // Deletion implicitly cancels any outstanding requests.
- virtual ~CertNetFetcher() {}
+ // Shuts down the CertNetFetcher and cancels outstanding network requests. It
+ // is not guaranteed that any outstanding or subsequent
+ // Request::WaitForResult() calls will be completed. Shutdown() must be called
+ // from the network thread. It can be called more than once, but must be
+ // called before the CertNetFetcher is destroyed.
+ virtual void Shutdown() = 0;
- // The Fetch*() methods start an asynchronous request which can be cancelled
- // by deleting the returned Request. Here is the meaning of the common
+ // The Fetch*() methods start a request which can be cancelled by
+ // deleting the returned Request. Here is the meaning of the common
// parameters:
//
// * url -- The http:// URL to fetch.
@@ -81,30 +64,30 @@ class NET_EXPORT CertNetFetcher {
// * max_response_bytes -- The maximum size of the response body. If this
// size is exceeded then the request will fail. To use a default timeout
// pass DEFAULT.
- // * callback -- The callback that will be invoked on completion of the job.
virtual WARN_UNUSED_RESULT std::unique_ptr<Request> FetchCaIssuers(
const GURL& url,
int timeout_milliseconds,
- int max_response_bytes,
- const FetchCallback& callback) = 0;
+ int max_response_bytes) = 0;
virtual WARN_UNUSED_RESULT std::unique_ptr<Request> FetchCrl(
const GURL& url,
int timeout_milliseconds,
- int max_response_bytes,
- const FetchCallback& callback) = 0;
+ int max_response_bytes) = 0;
virtual WARN_UNUSED_RESULT std::unique_ptr<Request> FetchOcsp(
const GURL& url,
int timeout_milliseconds,
- int max_response_bytes,
- const FetchCallback& callback) = 0;
+ int max_response_bytes) = 0;
+
+ protected:
+ virtual ~CertNetFetcher() {}
private:
+ friend class base::RefCountedThreadSafe<CertNetFetcher>;
DISALLOW_COPY_AND_ASSIGN(CertNetFetcher);
};
} // namespace net
-#endif // NET_CERT_NET_CERT_NET_FETCHER_H_
+#endif // NET_CERT_CERT_NET_FETCHER_H_
diff --git a/chromium/net/cert/cert_verify_proc.cc b/chromium/net/cert/cert_verify_proc.cc
index 413abb4b2fb..d9462561012 100644
--- a/chromium/net/cert/cert_verify_proc.cc
+++ b/chromium/net/cert/cert_verify_proc.cc
@@ -369,6 +369,69 @@ bool AreSHA1IntermediatesAllowed() {
#endif
};
+// Sets the "has_*" boolean members in |verify_result| that correspond with
+// the the presence of |hash| somewhere in the certificate chain (excluding the
+// trust anchor).
+void MapHashAlgorithmToBool(X509Certificate::SignatureHashAlgorithm hash,
+ CertVerifyResult* verify_result) {
+ switch (hash) {
+ case X509Certificate::kSignatureHashAlgorithmMd2:
+ verify_result->has_md2 = true;
+ break;
+ case X509Certificate::kSignatureHashAlgorithmMd4:
+ verify_result->has_md4 = true;
+ break;
+ case X509Certificate::kSignatureHashAlgorithmMd5:
+ verify_result->has_md5 = true;
+ break;
+ case X509Certificate::kSignatureHashAlgorithmSha1:
+ verify_result->has_sha1 = true;
+ break;
+ case X509Certificate::kSignatureHashAlgorithmOther:
+ break;
+ }
+}
+
+// Sets to true the |verify_result->has_*| boolean members for the hash
+// algorithms present in the certificate chain.
+//
+// This considers the hash algorithms in all certificates except trusted
+// certificates.
+//
+// In the case of a successful verification the trust anchor is the final
+// certificate in the chain (either the final intermediate, or the leaf
+// certificate).
+//
+// Whereas if verification was uncessful, the chain may be partial, and the
+// final certificate may not be a trust anchor. This heuristic is used
+// in both successful and failed verifications, despite this ambiguity (failure
+// to tag one of the signature algorithms should only affect the final error).
+void ComputeSignatureHashAlgorithms(CertVerifyResult* verify_result) {
+ const X509Certificate::OSCertHandles& intermediates =
+ verify_result->verified_cert->GetIntermediateCertificates();
+
+ // If there are no intermediates, then the leaf is trusted or verification
+ // failed.
+ if (intermediates.empty())
+ return;
+
+ DCHECK(!verify_result->has_sha1);
+
+ // Fill in hash algorithms for the leaf certificate.
+ MapHashAlgorithmToBool(X509Certificate::GetSignatureHashAlgorithm(
+ verify_result->verified_cert->os_cert_handle()),
+ verify_result);
+ verify_result->has_sha1_leaf = verify_result->has_sha1;
+
+ // Fill in hash algorithms for the intermediate cerificates, excluding the
+ // final one (which is the trust anchor).
+ for (size_t i = 0; i + 1 < intermediates.size(); ++i) {
+ MapHashAlgorithmToBool(
+ X509Certificate::GetSignatureHashAlgorithm(intermediates[i]),
+ verify_result);
+ }
+}
+
} // namespace
// static
@@ -420,6 +483,8 @@ int CertVerifyProc::Verify(X509Certificate* cert,
int rv = VerifyInternal(cert, hostname, ocsp_response, flags, crl_set,
additional_trust_anchors, verify_result);
+ ComputeSignatureHashAlgorithms(verify_result);
+
UMA_HISTOGRAM_BOOLEAN("Net.CertCommonNameFallback",
verify_result->common_name_fallback_used);
if (!verify_result->is_issued_by_known_root) {
@@ -448,7 +513,7 @@ int CertVerifyProc::Verify(X509Certificate* cert,
}
if (IsNonWhitelistedCertificate(*verify_result->verified_cert,
- verify_result->public_key_hashes)) {
+ verify_result->public_key_hashes, hostname)) {
verify_result->cert_status |= CERT_STATUS_AUTHORITY_INVALID;
rv = MapCertStatusToNetError(verify_result->cert_status);
}
@@ -476,30 +541,28 @@ int CertVerifyProc::Verify(X509Certificate* cert,
verify_result->cert_status |= CERT_STATUS_SHA1_SIGNATURE_PRESENT;
// Flag certificates using weak signature algorithms.
- // The CA/Browser Forum Baseline Requirements (beginning with v1.2.1)
- // prohibits SHA-1 certificates from being issued beginning on
- // 1 January 2016. Ideally, all of SHA-1 in new certificates would be
- // disabled on this date, but enterprises need more time to transition.
- // As the risk is greatest for publicly trusted certificates, prevent
- // those certificates from being trusted from that date forward.
- //
- // TODO(mattm): apply the SHA-1 deprecation check to all certs unless
- // CertVerifier::VERIFY_ENABLE_SHA1_LOCAL_ANCHORS flag is present.
+
+ // Legacy SHA-1 behaviour:
+ // - Reject all publicly trusted SHA-1 leaf certs issued after
+ // 2016-01-01.
+ bool legacy_sha1_issue = verify_result->has_sha1_leaf &&
+ verify_result->is_issued_by_known_root &&
+ IsPastSHA1DeprecationDate(*cert);
+
+ // Current SHA-1 behaviour:
+ // - Reject all SHA-1
+ // - ... unless it's not publicly trusted and SHA-1 is allowed
+ // - ... or SHA-1 is in the intermediate and SHA-1 intermediates are
+ // allowed for that platform. See https://crbug.com/588789
+ bool current_sha1_issue =
+ (verify_result->is_issued_by_known_root ||
+ !(flags & CertVerifier::VERIFY_ENABLE_SHA1_LOCAL_ANCHORS)) &&
+ (verify_result->has_sha1_leaf ||
+ (verify_result->has_sha1 && !AreSHA1IntermediatesAllowed()));
+
if (verify_result->has_md5 ||
- // Current SHA-1 behaviour:
- // - Reject all publicly trusted SHA-1
- // - ... unless it's in the intermediate and SHA-1 intermediates are
- // allowed for that platform. See https://crbug.com/588789
- (!sha1_legacy_mode_enabled &&
- (verify_result->is_issued_by_known_root &&
- (verify_result->has_sha1_leaf ||
- (verify_result->has_sha1 && !AreSHA1IntermediatesAllowed())))) ||
- // Legacy SHA-1 behaviour:
- // - Reject all publicly trusted SHA-1 leaf certs issued after
- // 2016-01-01.
- (sha1_legacy_mode_enabled && (verify_result->has_sha1_leaf &&
- verify_result->is_issued_by_known_root &&
- IsPastSHA1DeprecationDate(*cert)))) {
+ (sha1_legacy_mode_enabled && legacy_sha1_issue) ||
+ (!sha1_legacy_mode_enabled && current_sha1_issue)) {
verify_result->cert_status |= CERT_STATUS_WEAK_SIGNATURE_ALGORITHM;
// Avoid replacing a more serious error, such as an OS/library failure,
// by ensuring that if verification failed, it failed with a certificate
diff --git a/chromium/net/cert/cert_verify_proc.h b/chromium/net/cert/cert_verify_proc.h
index 352610f22e5..33f87ee3f62 100644
--- a/chromium/net/cert/cert_verify_proc.h
+++ b/chromium/net/cert/cert_verify_proc.h
@@ -88,9 +88,25 @@ class NET_EXPORT CertVerifyProc
VerifyRejectsSHA1AfterDeprecationLegacyMode);
// Performs the actual verification using the desired underlying
- // cryptographic library. On entry, |verify_result->verified_cert|
- // is set to |cert|, the unverified chain. If no chain is built, the
- // value must be left untouched.
+ //
+ // On entry, |verify_result| will be default-initialized as a successful
+ // validation, with |verify_result->verified_cert| set to |cert|.
+ //
+ // Implementations are expected to fill in all applicable fields, excluding:
+ //
+ // * ocsp_result
+ // * has_md2
+ // * has_md4
+ // * has_md5
+ // * has_sha1
+ // * has_sha1_leaf
+ //
+ // which will be filled in by |Verify()|. If an error code is returned,
+ // |verify_result->cert_status| should be non-zero, indicating an
+ // error occurred.
+ //
+ // On success, net::OK should be returned, with |verify_result| updated to
+ // reflect the successfully verified chain.
virtual int VerifyInternal(X509Certificate* cert,
const std::string& hostname,
const std::string& ocsp_response,
diff --git a/chromium/net/cert/cert_verify_proc_android.cc b/chromium/net/cert/cert_verify_proc_android.cc
index 2cb12f75c23..f90f5721c3d 100644
--- a/chromium/net/cert/cert_verify_proc_android.cc
+++ b/chromium/net/cert/cert_verify_proc_android.cc
@@ -79,32 +79,6 @@ bool VerifyFromAndroidTrustManager(const std::vector<std::string>& cert_bytes,
chain.push_back(verify_result->verified_cert->os_cert_handle());
chain.insert(chain.end(), intermediates.begin(), intermediates.end());
- // If the chain successfully verified, ignore the trust anchor (the last
- // certificate). Otherwise, assume the chain is partial. This is not entirely
- // correct, as a full chain may have been constructed and then failed to
- // validate. However, if that is the case, the more serious error will
- // override any SHA-1 considerations.
- size_t correction_for_root =
- (status == android::CERT_VERIFY_STATUS_ANDROID_OK) ? 1 : 0;
- for (size_t i = 0; i < chain.size() - correction_for_root; ++i) {
- int sig_alg = OBJ_obj2nid(chain[i]->sig_alg->algorithm);
- if (sig_alg == NID_md2WithRSAEncryption) {
- verify_result->has_md2 = true;
- } else if (sig_alg == NID_md4WithRSAEncryption) {
- verify_result->has_md4 = true;
- } else if (sig_alg == NID_md5WithRSAEncryption ||
- sig_alg == NID_md5WithRSA) {
- verify_result->has_md5 = true;
- } else if (sig_alg == NID_sha1WithRSAEncryption ||
- sig_alg == NID_dsaWithSHA || sig_alg == NID_dsaWithSHA1 ||
- sig_alg == NID_dsaWithSHA1_2 || sig_alg == NID_sha1WithRSA ||
- sig_alg == NID_ecdsa_with_SHA1) {
- verify_result->has_sha1 = true;
- if (i == 0)
- verify_result->has_sha1_leaf = true;
- }
- }
-
// Extract the public key hashes.
for (size_t i = 0; i < verified_chain.size(); i++) {
base::StringPiece spki_bytes;
diff --git a/chromium/net/cert/cert_verify_proc_blacklist.inc b/chromium/net/cert/cert_verify_proc_blacklist.inc
index b2bb55464a3..3ca92f144eb 100644
--- a/chromium/net/cert/cert_verify_proc_blacklist.inc
+++ b/chromium/net/cert/cert_verify_proc_blacklist.inc
@@ -5,7 +5,7 @@
// The certificate(s) that were misissued, and which represent these SPKIs,
// are stored within net/data/ssl/blacklist. Further details about the
// rationale is documented in net/data/ssl/blacklist/README.md
-static const size_t kNumBlacklistedSPKIs = 34u;
+static const size_t kNumBlacklistedSPKIs = 36u;
static const uint8_t
kBlacklistedSPKIs[kNumBlacklistedSPKIs][crypto::kSHA256Length] = {
// ead610e6e90b439f2ecb51628b0932620f6ef340bd843fca38d3181b8f4ba197.pem
@@ -24,6 +24,10 @@ static const uint8_t
{0x1a, 0xf5, 0x6c, 0x98, 0xff, 0x04, 0x3e, 0xf9, 0x2b, 0xeb, 0xff,
0x54, 0xce, 0xbb, 0x4d, 0xd6, 0x7a, 0x25, 0xba, 0x95, 0x6c, 0x81,
0x7f, 0x3e, 0x6d, 0xd3, 0xc1, 0xe5, 0x2e, 0xb5, 0x84, 0xc1},
+ // e28393773da845a679f2080cc7fb44a3b7a1c3792cb7eb7729fdcb6a8d99aea7.pem
+ {0x1f, 0x42, 0x24, 0xce, 0xc8, 0x4f, 0xc9, 0x9c, 0xed, 0x88, 0x1f,
+ 0xf6, 0xfc, 0xfd, 0x3e, 0x21, 0xf8, 0xc5, 0x19, 0xc5, 0x47, 0xaa,
+ 0x6a, 0x5d, 0xd3, 0xde, 0x24, 0x73, 0x02, 0xce, 0x50, 0xd1},
// 2c998e761160c3b06d82faa9fdc7545d9bda9eb60310f992aa510a6280b74245.pem
{0x2c, 0x99, 0x8e, 0x76, 0x11, 0x60, 0xc3, 0xb0, 0x6d, 0x82, 0xfa,
0xa9, 0xfd, 0xc7, 0x54, 0x5d, 0x9b, 0xda, 0x9e, 0xb6, 0x03, 0x10,
@@ -78,6 +82,10 @@ static const uint8_t
{0x9b, 0x8a, 0x93, 0xde, 0xcc, 0xcf, 0xba, 0xfc, 0xf4, 0xd0, 0x4d,
0x34, 0x42, 0x12, 0x8f, 0xb3, 0x52, 0x18, 0xcf, 0xe4, 0x37, 0xa3,
0xd8, 0xd0, 0x32, 0x8c, 0x99, 0xf8, 0x90, 0x89, 0xe4, 0x50},
+ // 1c01c6f4dbb2fefc22558b2bca32563f49844acfc32b7be4b0ff599f9e8c7af7.pem
+ {0x9d, 0xd5, 0x5f, 0xc5, 0x73, 0xf5, 0x46, 0xcb, 0x6a, 0x38, 0x31,
+ 0xd1, 0x11, 0x2d, 0x87, 0x10, 0xa6, 0xf4, 0xf8, 0x2d, 0xc8, 0x7f,
+ 0x5f, 0xae, 0x9d, 0x3a, 0x1a, 0x02, 0x8d, 0xd3, 0x6e, 0x4b},
// 0d136e439f0ab6e97f3a02a540da9f0641aa554e1d66ea51ae2920d51b2f7217.pem
// 4fee0163686ecbd65db968e7494f55d84b25486d438e9de558d629d28cd4d176.pem
// 8a1bd21661c60015065212cc98b1abb50dfd14c872a208e66bae890f25c448af.pem
diff --git a/chromium/net/cert/cert_verify_proc_ios.cc b/chromium/net/cert/cert_verify_proc_ios.cc
index 2ab30ed07e4..19dc20fa722 100644
--- a/chromium/net/cert/cert_verify_proc_ios.cc
+++ b/chromium/net/cert/cert_verify_proc_ios.cc
@@ -104,12 +104,6 @@ int BuildAndEvaluateSecTrustRef(CFArrayRef cert_array,
void GetCertChainInfo(CFArrayRef cert_chain, CertVerifyResult* verify_result) {
DCHECK_LT(0, CFArrayGetCount(cert_chain));
- verify_result->has_md2 = false;
- verify_result->has_md4 = false;
- verify_result->has_md5 = false;
- verify_result->has_sha1 = false;
- verify_result->has_sha1_leaf = false;
-
SecCertificateRef verified_cert = nullptr;
std::vector<SecCertificateRef> verified_chain;
for (CFIndex i = 0, count = CFArrayGetCount(cert_chain); i < count; ++i) {
@@ -124,8 +118,6 @@ void GetCertChainInfo(CFArrayRef cert_chain, CertVerifyResult* verify_result) {
std::string der_bytes;
if (!X509Certificate::GetDEREncoded(chain_cert, &der_bytes))
return;
- const uint8_t* bytes = reinterpret_cast<const uint8_t*>(der_bytes.data());
- bssl::UniquePtr<X509> x509_cert(d2i_X509(NULL, &bytes, der_bytes.size()));
base::StringPiece spki_bytes;
if (!asn1::ExtractSPKIFromDERCert(der_bytes, &spki_bytes))
@@ -144,23 +136,6 @@ void GetCertChainInfo(CFArrayRef cert_chain, CertVerifyResult* verify_result) {
i == count - 1) {
continue;
}
-
- int sig_alg = OBJ_obj2nid(x509_cert->sig_alg->algorithm);
- if (sig_alg == NID_md2WithRSAEncryption) {
- verify_result->has_md2 = true;
- } else if (sig_alg == NID_md4WithRSAEncryption) {
- verify_result->has_md4 = true;
- } else if (sig_alg == NID_md5WithRSAEncryption ||
- sig_alg == NID_md5WithRSA) {
- verify_result->has_md5 = true;
- } else if (sig_alg == NID_sha1WithRSAEncryption ||
- sig_alg == NID_dsaWithSHA || sig_alg == NID_dsaWithSHA1 ||
- sig_alg == NID_dsaWithSHA1_2 || sig_alg == NID_sha1WithRSA ||
- sig_alg == NID_ecdsa_with_SHA1) {
- verify_result->has_sha1 = true;
- if (i == 0)
- verify_result->has_sha1_leaf = true;
- }
}
if (!verified_cert) {
NOTREACHED();
diff --git a/chromium/net/cert/cert_verify_proc_mac.cc b/chromium/net/cert/cert_verify_proc_mac.cc
index 08f1b887f59..46d1cc864b8 100644
--- a/chromium/net/cert/cert_verify_proc_mac.cc
+++ b/chromium/net/cert/cert_verify_proc_mac.cc
@@ -177,23 +177,12 @@ OSStatus CreateTrustPolicies(int flags, ScopedCFTypeRef<CFArrayRef>* policies) {
return noErr;
}
-// Stores the constructed certificate chain |cert_chain| and information about
-// the signature algorithms used into |*verify_result|. If the leaf cert in
-// |cert_chain| contains a weak (MD2, MD4, MD5, SHA-1) signature, stores that
-// in |*leaf_is_weak|. |cert_chain| must not be empty.
-void GetCertChainInfo(CFArrayRef cert_chain,
- CSSM_TP_APPLE_EVIDENCE_INFO* chain_info,
- CertVerifyResult* verify_result,
- bool* leaf_is_weak) {
+// Stores the constructed certificate chain |cert_chain| into
+// |*verify_result|. |cert_chain| must not be empty.
+void CopyCertChainToVerifyResult(CFArrayRef cert_chain,
+ CertVerifyResult* verify_result) {
DCHECK_LT(0, CFArrayGetCount(cert_chain));
- *leaf_is_weak = false;
- verify_result->has_md2 = false;
- verify_result->has_md4 = false;
- verify_result->has_md5 = false;
- verify_result->has_sha1 = false;
- verify_result->has_sha1_leaf = false;
-
SecCertificateRef verified_cert = NULL;
std::vector<SecCertificateRef> verified_chain;
for (CFIndex i = 0, count = CFArrayGetCount(cert_chain); i < count; ++i) {
@@ -204,6 +193,29 @@ void GetCertChainInfo(CFArrayRef cert_chain,
} else {
verified_chain.push_back(chain_cert);
}
+ }
+ if (!verified_cert) {
+ NOTREACHED();
+ return;
+ }
+
+ verify_result->verified_cert =
+ X509Certificate::CreateFromHandle(verified_cert, verified_chain);
+}
+
+// Returns true if the intermediates (excluding trusted certificates) use a
+// weak hashing algorithm, but the target does not use a weak hash.
+bool IsWeakChainBasedOnHashingAlgorithms(
+ CFArrayRef cert_chain,
+ CSSM_TP_APPLE_EVIDENCE_INFO* chain_info) {
+ DCHECK_LT(0, CFArrayGetCount(cert_chain));
+
+ bool intermediates_contain_weak_hash = false;
+ bool leaf_uses_weak_hash = false;
+
+ for (CFIndex i = 0, count = CFArrayGetCount(cert_chain); i < count; ++i) {
+ SecCertificateRef chain_cert = reinterpret_cast<SecCertificateRef>(
+ const_cast<void*>(CFArrayGetValueAtIndex(cert_chain, i)));
if ((chain_info[i].StatusBits & CSSM_CERT_STATUS_IS_IN_ANCHORS) ||
(chain_info[i].StatusBits & CSSM_CERT_STATUS_IS_ROOT)) {
@@ -215,57 +227,26 @@ void GetCertChainInfo(CFArrayRef cert_chain,
continue;
}
- x509_util::CSSMCachedCertificate cached_cert;
- OSStatus status = cached_cert.Init(chain_cert);
- if (status)
- continue;
- x509_util::CSSMFieldValue signature_field;
- status = cached_cert.GetField(&CSSMOID_X509V1SignatureAlgorithm,
- &signature_field);
- if (status || !signature_field.field())
- continue;
- // Match the behaviour of OS X system tools and defensively check that
- // sizes are appropriate. This would indicate a critical failure of the
- // OS X certificate library, but based on history, it is best to play it
- // safe.
- const CSSM_X509_ALGORITHM_IDENTIFIER* sig_algorithm =
- signature_field.GetAs<CSSM_X509_ALGORITHM_IDENTIFIER>();
- if (!sig_algorithm)
- continue;
-
- const CSSM_OID* alg_oid = &sig_algorithm->algorithm;
- if (CSSMOIDEqual(alg_oid, &CSSMOID_MD2WithRSA)) {
- verify_result->has_md2 = true;
- if (i == 0)
- *leaf_is_weak = true;
- } else if (CSSMOIDEqual(alg_oid, &CSSMOID_MD4WithRSA)) {
- verify_result->has_md4 = true;
- if (i == 0)
- *leaf_is_weak = true;
- } else if (CSSMOIDEqual(alg_oid, &CSSMOID_MD5WithRSA)) {
- verify_result->has_md5 = true;
- if (i == 0)
- *leaf_is_weak = true;
- } else if (CSSMOIDEqual(alg_oid, &CSSMOID_SHA1WithRSA) ||
- CSSMOIDEqual(alg_oid, &CSSMOID_SHA1WithRSA_OIW) ||
- CSSMOIDEqual(alg_oid, &CSSMOID_SHA1WithDSA) ||
- CSSMOIDEqual(alg_oid, &CSSMOID_SHA1WithDSA_CMS) ||
- CSSMOIDEqual(alg_oid, &CSSMOID_SHA1WithDSA_JDK) ||
- CSSMOIDEqual(alg_oid, &CSSMOID_ECDSA_WithSHA1)) {
- verify_result->has_sha1 = true;
- if (i == 0) {
- verify_result->has_sha1_leaf = true;
- *leaf_is_weak = true;
- }
+ X509Certificate::SignatureHashAlgorithm hash_algorithm =
+ X509Certificate::GetSignatureHashAlgorithm(chain_cert);
+
+ switch (hash_algorithm) {
+ case X509Certificate::kSignatureHashAlgorithmMd2:
+ case X509Certificate::kSignatureHashAlgorithmMd4:
+ case X509Certificate::kSignatureHashAlgorithmMd5:
+ case X509Certificate::kSignatureHashAlgorithmSha1:
+ if (i == 0) {
+ leaf_uses_weak_hash = true;
+ } else {
+ intermediates_contain_weak_hash = true;
+ }
+ break;
+ case X509Certificate::kSignatureHashAlgorithmOther:
+ break;
}
}
- if (!verified_cert) {
- NOTREACHED();
- return;
- }
- verify_result->verified_cert =
- X509Certificate::CreateFromHandle(verified_cert, verified_chain);
+ return !leaf_uses_weak_hash && intermediates_contain_weak_hash;
}
using ExtensionsMap = std::map<net::der::Input, net::ParsedExtension>;
@@ -842,14 +823,8 @@ int VerifyWithGivenFlags(X509Certificate* cert,
DCHECK(untrusted);
DCHECK_NE(kSecTrustResultRecoverableTrustFailure, temp_trust_result);
} else {
- CertVerifyResult temp_verify_result;
- bool leaf_is_weak = false;
- GetCertChainInfo(temp_chain, temp_chain_info, &temp_verify_result,
- &leaf_is_weak);
weak_chain =
- !leaf_is_weak &&
- (temp_verify_result.has_md2 || temp_verify_result.has_md4 ||
- temp_verify_result.has_md5 || temp_verify_result.has_sha1);
+ IsWeakChainBasedOnHashingAlgorithms(temp_chain, temp_chain_info);
}
// Set the result to the current chain if:
// - This is the first verification attempt. This ensures that if
@@ -894,9 +869,7 @@ int VerifyWithGivenFlags(X509Certificate* cert,
verify_result->cert_status |= CERT_STATUS_REVOKED;
if (CFArrayGetCount(completed_chain) > 0) {
- bool leaf_is_weak_unused = false;
- GetCertChainInfo(completed_chain, chain_info, verify_result,
- &leaf_is_weak_unused);
+ CopyCertChainToVerifyResult(completed_chain, verify_result);
}
// As of Security Update 2012-002/OS X 10.7.4, when an RSA key < 1024 bits
diff --git a/chromium/net/cert/cert_verify_proc_nss.cc b/chromium/net/cert/cert_verify_proc_nss.cc
index 1ac27cb48ef..59cfa03235a 100644
--- a/chromium/net/cert/cert_verify_proc_nss.cc
+++ b/chromium/net/cert/cert_verify_proc_nss.cc
@@ -191,30 +191,6 @@ void GetCertChainInfo(CERTCertList* cert_list,
}
verified_chain.push_back(node->cert);
}
-
- SECAlgorithmID& signature = node->cert->signature;
- SECOidTag oid_tag = SECOID_FindOIDTag(&signature.algorithm);
- switch (oid_tag) {
- case SEC_OID_PKCS1_MD5_WITH_RSA_ENCRYPTION:
- verify_result->has_md5 = true;
- break;
- case SEC_OID_PKCS1_MD2_WITH_RSA_ENCRYPTION:
- verify_result->has_md2 = true;
- break;
- case SEC_OID_PKCS1_MD4_WITH_RSA_ENCRYPTION:
- verify_result->has_md4 = true;
- break;
- case SEC_OID_PKCS1_SHA1_WITH_RSA_ENCRYPTION:
- case SEC_OID_ISO_SHA1_WITH_RSA_SIGNATURE:
- case SEC_OID_ANSIX9_DSA_SIGNATURE_WITH_SHA1_DIGEST:
- case SEC_OID_ANSIX962_ECDSA_SHA1_SIGNATURE:
- verify_result->has_sha1 = true;
- if (i == 0)
- verify_result->has_sha1_leaf = true;
- break;
- default:
- break;
- }
}
if (root_cert)
diff --git a/chromium/net/cert/cert_verify_proc_openssl.cc b/chromium/net/cert/cert_verify_proc_openssl.cc
index 988bdec1e2e..d822bc00d6c 100644
--- a/chromium/net/cert/cert_verify_proc_openssl.cc
+++ b/chromium/net/cert/cert_verify_proc_openssl.cc
@@ -104,27 +104,6 @@ void GetCertChainInfo(X509_STORE_CTX* store_ctx,
} else {
verified_chain.push_back(cert);
}
-
- // Only check the algorithm status for certificates that are not in the
- // trust store.
- if (i < static_cast<size_t>(store_ctx->last_untrusted)) {
- int sig_alg = OBJ_obj2nid(cert->sig_alg->algorithm);
- if (sig_alg == NID_md2WithRSAEncryption) {
- verify_result->has_md2 = true;
- } else if (sig_alg == NID_md4WithRSAEncryption) {
- verify_result->has_md4 = true;
- } else if (sig_alg == NID_md5WithRSAEncryption ||
- sig_alg == NID_md5WithRSA) {
- verify_result->has_md5 = true;
- } else if (sig_alg == NID_sha1WithRSAEncryption ||
- sig_alg == NID_dsaWithSHA || sig_alg == NID_dsaWithSHA1 ||
- sig_alg == NID_dsaWithSHA1_2 || sig_alg == NID_sha1WithRSA ||
- sig_alg == NID_ecdsa_with_SHA1) {
- verify_result->has_sha1 = true;
- if (i == 0)
- verify_result->has_sha1_leaf = true;
- }
- }
}
// Set verify_result->verified_cert and
diff --git a/chromium/net/cert/cert_verify_proc_unittest.cc b/chromium/net/cert/cert_verify_proc_unittest.cc
index 862f7c8690c..2e3a0f5d458 100644
--- a/chromium/net/cert/cert_verify_proc_unittest.cc
+++ b/chromium/net/cert/cert_verify_proc_unittest.cc
@@ -38,6 +38,7 @@
#endif
#if defined(OS_MACOSX) && !defined(OS_IOS)
+#include "base/mac/mac_util.h"
#include "net/cert/test_keychain_search_list_mac.h"
#endif
@@ -122,6 +123,16 @@ bool SupportsDetectingKnownRoots() {
return true;
}
+bool WeakKeysAreInvalid() {
+#if defined(OS_MACOSX) && !defined(OS_IOS)
+ // Starting with Mac OS 10.12, certs with weak keys are treated as
+ // (recoverable) invalid certificate errors.
+ return base::mac::IsAtLeastOS10_12();
+#else
+ return false;
+#endif
+}
+
// Template helper to load a series of certificate files into a CertificateList.
// Like CertTestUtil's CreateCertificateListFromFile, except it can load a
// series of individual certificates (to make the tests clearer).
@@ -407,7 +418,7 @@ TEST_F(CertVerifyProcTest, RejectWeakKeys) {
EXPECT_NE(OK, error);
EXPECT_EQ(CERT_STATUS_WEAK_KEY,
verify_result.cert_status & CERT_STATUS_WEAK_KEY);
- EXPECT_NE(CERT_STATUS_INVALID,
+ EXPECT_EQ(WeakKeysAreInvalid() ? CERT_STATUS_INVALID : 0,
verify_result.cert_status & CERT_STATUS_INVALID);
} else {
EXPECT_THAT(error, IsOk());
@@ -882,8 +893,6 @@ TEST_F(CertVerifyProcTest, IntranetHostsRejected) {
// that were issued after 1 January 2016, while still allowing those from
// before that date, with SHA-1 in the intermediate, or from an enterprise
// CA.
-//
-// TODO(rsleevi): This code should be removed in M57.
TEST_F(CertVerifyProcTest, VerifyRejectsSHA1AfterDeprecationLegacyMode) {
base::test::ScopedFeatureList scoped_feature_list;
scoped_feature_list.InitAndEnableFeature(CertVerifyProc::kSHA1LegacyMode);
@@ -928,7 +937,7 @@ TEST_F(CertVerifyProcTest, VerifyRejectsSHA1AfterDeprecationLegacyMode) {
EXPECT_TRUE(verify_result.cert_status & CERT_STATUS_WEAK_SIGNATURE_ALGORITHM);
// Enterprise issued SHA-1 leaf certificates issued on/after 1 January 2016
- // remain accepted until SHA-1 is disabled.
+ // remain accepted.
verify_result.Reset();
dummy_result.Reset();
dummy_result.is_issued_by_known_root = false;
@@ -1208,39 +1217,32 @@ TEST_F(CertVerifyProcTest, CRLSet) {
TEST_F(CertVerifyProcTest, CRLSetLeafSerial) {
CertificateList ca_cert_list =
- CreateCertificateListFromFile(GetTestCertsDirectory(),
- "quic_root.crt",
+ CreateCertificateListFromFile(GetTestCertsDirectory(), "root_ca_cert.pem",
X509Certificate::FORMAT_AUTO);
ASSERT_EQ(1U, ca_cert_list.size());
ScopedTestRoot test_root(ca_cert_list[0].get());
- CertificateList intermediate_cert_list =
- CreateCertificateListFromFile(GetTestCertsDirectory(),
- "quic_intermediate.crt",
- X509Certificate::FORMAT_AUTO);
+ CertificateList intermediate_cert_list = CreateCertificateListFromFile(
+ GetTestCertsDirectory(), "intermediate_ca_cert.pem",
+ X509Certificate::FORMAT_AUTO);
ASSERT_EQ(1U, intermediate_cert_list.size());
X509Certificate::OSCertHandles intermediates;
intermediates.push_back(intermediate_cert_list[0]->os_cert_handle());
CertificateList cert_list = CreateCertificateListFromFile(
- GetTestCertsDirectory(), "quic_test.example.com.crt",
+ GetTestCertsDirectory(), "ok_cert_by_intermediate.pem",
X509Certificate::FORMAT_AUTO);
ASSERT_EQ(1U, cert_list.size());
- scoped_refptr<X509Certificate> leaf =
- X509Certificate::CreateFromHandle(cert_list[0]->os_cert_handle(),
- intermediates);
+ scoped_refptr<X509Certificate> leaf = X509Certificate::CreateFromHandle(
+ cert_list[0]->os_cert_handle(), intermediates);
+ ASSERT_TRUE(leaf);
int flags = 0;
CertVerifyResult verify_result;
- int error = Verify(leaf.get(),
- "test.example.com",
- flags,
- NULL,
- empty_cert_list_,
+ int error = Verify(leaf.get(), "127.0.0.1", flags, NULL, empty_cert_list_,
&verify_result);
EXPECT_THAT(error, IsOk());
- EXPECT_EQ(CERT_STATUS_SHA1_SIGNATURE_PRESENT, verify_result.cert_status);
// Test revocation by serial number of a certificate not under the root.
scoped_refptr<CRLSet> crl_set;
@@ -1250,12 +1252,8 @@ TEST_F(CertVerifyProcTest, CRLSetLeafSerial) {
&crl_set_bytes));
ASSERT_TRUE(CRLSetStorage::Parse(crl_set_bytes, &crl_set));
- error = Verify(leaf.get(),
- "test.example.com",
- flags,
- crl_set.get(),
- empty_cert_list_,
- &verify_result);
+ error = Verify(leaf.get(), "127.0.0.1", flags, crl_set.get(),
+ empty_cert_list_, &verify_result);
EXPECT_THAT(error, IsError(ERR_CERT_REVOKED));
}
@@ -1392,6 +1390,11 @@ TEST_F(CertVerifyProcTest, CRLSetDuringPathBuilding) {
// The verifier should rollback until it just tries A(B) alone, at which point
// it will pull B(F) & F(E) from the keychain and succeed.
TEST_F(CertVerifyProcTest, MacCRLIntermediate) {
+ if (base::mac::IsAtLeastOS10_12()) {
+ // TODO(crbug.com/671889): Investigate SecTrustSetKeychains issue on Sierra.
+ LOG(INFO) << "Skipping test, SecTrustSetKeychains does not work on 10.12";
+ return;
+ }
const char* const kPath2Files[] = {
"multi-root-A-by-B.pem", "multi-root-B-by-C.pem", "multi-root-C-by-E.pem",
"multi-root-E-by-E.pem"};
@@ -1631,7 +1634,7 @@ TEST_F(CertVerifyProcTest, RejectsPublicSHA1IntermediatesUnlessAllowed) {
}
}
-TEST_F(CertVerifyProcTest, AcceptsPrivateSHA1) {
+TEST_F(CertVerifyProcTest, RejectsPrivateSHA1UnlessFlag) {
scoped_refptr<X509Certificate> cert(
ImportCertFromFile(GetTestCertsDirectory(), "ok_cert.pem"));
ASSERT_TRUE(cert);
@@ -1642,10 +1645,19 @@ TEST_F(CertVerifyProcTest, AcceptsPrivateSHA1) {
result.is_issued_by_known_root = false;
verify_proc_ = new MockCertVerifyProc(result);
+ // SHA-1 should be rejected by default for private roots...
int flags = 0;
CertVerifyResult verify_result;
int error = Verify(cert.get(), "127.0.0.1", flags, nullptr /* crl_set */,
empty_cert_list_, &verify_result);
+ EXPECT_THAT(error, IsError(ERR_CERT_WEAK_SIGNATURE_ALGORITHM));
+ EXPECT_TRUE(verify_result.cert_status & CERT_STATUS_SHA1_SIGNATURE_PRESENT);
+
+ // ... unless VERIFY_ENABLE_SHA1_LOCAL_ANCHORS was supplied.
+ flags = CertVerifier::VERIFY_ENABLE_SHA1_LOCAL_ANCHORS;
+ verify_result.Reset();
+ error = Verify(cert.get(), "127.0.0.1", flags, nullptr /* crl_set */,
+ empty_cert_list_, &verify_result);
EXPECT_THAT(error, IsOk());
EXPECT_TRUE(verify_result.cert_status & CERT_STATUS_SHA1_SIGNATURE_PRESENT);
}
@@ -1665,14 +1677,20 @@ struct WeakDigestTestData {
int expected_algorithms;
};
+const char* StringOrDefault(const char* str, const char* default_value) {
+ if (!str)
+ return default_value;
+ return str;
+}
+
// GTest 'magic' pretty-printer, so that if/when a test fails, it knows how
// to output the parameter that was passed. Without this, it will simply
// attempt to print out the first twenty bytes of the object, which depending
// on platform and alignment, may result in an invalid read.
void PrintTo(const WeakDigestTestData& data, std::ostream* os) {
- *os << "root: "
- << (data.root_cert_filename ? data.root_cert_filename : "none")
- << "; intermediate: " << data.intermediate_cert_filename
+ *os << "root: " << StringOrDefault(data.root_cert_filename, "none")
+ << "; intermediate: "
+ << StringOrDefault(data.intermediate_cert_filename, "none")
<< "; end-entity: " << data.ee_cert_filename;
}
@@ -1684,31 +1702,35 @@ class CertVerifyProcWeakDigestTest
virtual ~CertVerifyProcWeakDigestTest() {}
};
-// Test that the underlying cryptographic library properly surfaces the
-// algorithms used in the chain. Some libraries, like NSS, don't return
-// the failing chain on error, and thus not all tests can be run.
+// Test that the CertVerifyProc::Verify() properly surfaces the (weak) hashing
+// algorithms used in the chain.
TEST_P(CertVerifyProcWeakDigestTest, VerifyDetectsAlgorithm) {
WeakDigestTestData data = GetParam();
base::FilePath certs_dir = GetTestCertsDirectory();
- ScopedTestRoot test_root;
+ scoped_refptr<X509Certificate> intermediate_cert;
+ scoped_refptr<X509Certificate> root_cert;
+
+ // Build |intermediates| as the full chain (including trust anchor).
+ X509Certificate::OSCertHandles intermediates;
+
+ if (data.intermediate_cert_filename) {
+ intermediate_cert =
+ ImportCertFromFile(certs_dir, data.intermediate_cert_filename);
+ ASSERT_TRUE(intermediate_cert);
+ intermediates.push_back(intermediate_cert->os_cert_handle());
+ }
+
if (data.root_cert_filename) {
- scoped_refptr<X509Certificate> root_cert =
- ImportCertFromFile(certs_dir, data.root_cert_filename);
- ASSERT_TRUE(root_cert);
- test_root.Reset(root_cert.get());
+ root_cert = ImportCertFromFile(certs_dir, data.root_cert_filename);
+ ASSERT_TRUE(root_cert);
+ intermediates.push_back(root_cert->os_cert_handle());
}
- scoped_refptr<X509Certificate> intermediate_cert =
- ImportCertFromFile(certs_dir, data.intermediate_cert_filename);
- ASSERT_TRUE(intermediate_cert);
scoped_refptr<X509Certificate> ee_cert =
ImportCertFromFile(certs_dir, data.ee_cert_filename);
ASSERT_TRUE(ee_cert);
- X509Certificate::OSCertHandles intermediates;
- intermediates.push_back(intermediate_cert->os_cert_handle());
-
scoped_refptr<X509Certificate> ee_chain =
X509Certificate::CreateFromHandle(ee_cert->os_cert_handle(),
intermediates);
@@ -1716,8 +1738,16 @@ TEST_P(CertVerifyProcWeakDigestTest, VerifyDetectsAlgorithm) {
int flags = 0;
CertVerifyResult verify_result;
- Verify(ee_chain.get(), "127.0.0.1", flags, NULL, empty_cert_list_,
- &verify_result);
+
+ // Use a mock CertVerifyProc that returns success with a verified_cert of
+ // |ee_chain|.
+ //
+ // This is sufficient for the purposes of this test, as the checking for weak
+ // hashing algorithms is done by CertVerifyProc::Verify().
+ scoped_refptr<CertVerifyProc> proc =
+ new MockCertVerifyProc(CertVerifyResult());
+ proc->Verify(ee_chain.get(), "127.0.0.1", std::string(), flags, nullptr,
+ empty_cert_list_, &verify_result);
EXPECT_EQ(!!(data.expected_algorithms & EXPECT_MD2), verify_result.has_md2);
EXPECT_EQ(!!(data.expected_algorithms & EXPECT_MD4), verify_result.has_md4);
EXPECT_EQ(!!(data.expected_algorithms & EXPECT_MD5), verify_result.has_md5);
@@ -1726,34 +1756,16 @@ TEST_P(CertVerifyProcWeakDigestTest, VerifyDetectsAlgorithm) {
verify_result.has_sha1_leaf);
}
-// Unlike TEST/TEST_F, which are macros that expand to further macros,
-// INSTANTIATE_TEST_CASE_P is a macro that expands directly to code that
-// stringizes the arguments. As a result, macros passed as parameters (such as
-// prefix or test_case_name) will not be expanded by the preprocessor. To work
-// around this, indirect the macro for INSTANTIATE_TEST_CASE_P, so that the
-// pre-processor will expand macros such as MAYBE_test_name before
-// instantiating the test.
-#define WRAPPED_INSTANTIATE_TEST_CASE_P(prefix, test_case_name, generator) \
- INSTANTIATE_TEST_CASE_P(prefix, test_case_name, generator)
-
// The signature algorithm of the root CA should not matter.
const WeakDigestTestData kVerifyRootCATestData[] = {
{"weak_digest_md5_root.pem", "weak_digest_sha1_intermediate.pem",
"weak_digest_sha1_ee.pem", EXPECT_SHA1 | EXPECT_SHA1_LEAF},
-#if defined(USE_OPENSSL_CERTS) || defined(OS_WIN)
- // MD4 is not supported by OS X / NSS
{"weak_digest_md4_root.pem", "weak_digest_sha1_intermediate.pem",
"weak_digest_sha1_ee.pem", EXPECT_SHA1 | EXPECT_SHA1_LEAF},
-#endif
{"weak_digest_md2_root.pem", "weak_digest_sha1_intermediate.pem",
"weak_digest_sha1_ee.pem", EXPECT_SHA1 | EXPECT_SHA1_LEAF},
};
-#if defined(OS_ANDROID)
-#define MAYBE_VerifyRoot DISABLED_VerifyRoot
-#else
-#define MAYBE_VerifyRoot VerifyRoot
-#endif
-INSTANTIATE_TEST_CASE_P(MAYBE_VerifyRoot,
+INSTANTIATE_TEST_CASE_P(VerifyRoot,
CertVerifyProcWeakDigestTest,
testing::ValuesIn(kVerifyRootCATestData));
@@ -1761,97 +1773,66 @@ INSTANTIATE_TEST_CASE_P(MAYBE_VerifyRoot,
const WeakDigestTestData kVerifyIntermediateCATestData[] = {
{"weak_digest_sha1_root.pem", "weak_digest_md5_intermediate.pem",
"weak_digest_sha1_ee.pem", EXPECT_MD5 | EXPECT_SHA1 | EXPECT_SHA1_LEAF},
-#if defined(USE_OPENSSL_CERTS) || defined(OS_WIN)
- // MD4 is not supported by OS X / NSS
{"weak_digest_sha1_root.pem", "weak_digest_md4_intermediate.pem",
"weak_digest_sha1_ee.pem", EXPECT_MD4 | EXPECT_SHA1 | EXPECT_SHA1_LEAF},
-#endif
{"weak_digest_sha1_root.pem", "weak_digest_md2_intermediate.pem",
"weak_digest_sha1_ee.pem", EXPECT_MD2 | EXPECT_SHA1 | EXPECT_SHA1_LEAF},
};
-// Disabled on NSS - MD4 is not supported, and MD2 and MD5 are disabled.
-#if defined(USE_NSS_CERTS) || defined(OS_IOS) || defined(OS_ANDROID)
-#define MAYBE_VerifyIntermediate DISABLED_VerifyIntermediate
-#else
-#define MAYBE_VerifyIntermediate VerifyIntermediate
-#endif
-WRAPPED_INSTANTIATE_TEST_CASE_P(
- MAYBE_VerifyIntermediate,
- CertVerifyProcWeakDigestTest,
- testing::ValuesIn(kVerifyIntermediateCATestData));
+
+INSTANTIATE_TEST_CASE_P(VerifyIntermediate,
+ CertVerifyProcWeakDigestTest,
+ testing::ValuesIn(kVerifyIntermediateCATestData));
// The signature algorithm of end-entity should be properly detected.
const WeakDigestTestData kVerifyEndEntityTestData[] = {
{ "weak_digest_sha1_root.pem", "weak_digest_sha1_intermediate.pem",
"weak_digest_md5_ee.pem", EXPECT_MD5 | EXPECT_SHA1 },
-#if defined(USE_OPENSSL_CERTS) || defined(OS_WIN)
- // MD4 is not supported by OS X / NSS
{ "weak_digest_sha1_root.pem", "weak_digest_sha1_intermediate.pem",
"weak_digest_md4_ee.pem", EXPECT_MD4 | EXPECT_SHA1 },
-#endif
{ "weak_digest_sha1_root.pem", "weak_digest_sha1_intermediate.pem",
"weak_digest_md2_ee.pem", EXPECT_MD2 | EXPECT_SHA1 },
};
-// Disabled on NSS - NSS caches chains/signatures in such a way that cannot
-// be cleared until NSS is cleanly shutdown, which is not presently supported
-// in Chromium.
-#if defined(USE_NSS_CERTS) || defined(OS_IOS) || defined(OS_ANDROID)
-#define MAYBE_VerifyEndEntity DISABLED_VerifyEndEntity
-#else
-#define MAYBE_VerifyEndEntity VerifyEndEntity
-#endif
-WRAPPED_INSTANTIATE_TEST_CASE_P(MAYBE_VerifyEndEntity,
- CertVerifyProcWeakDigestTest,
- testing::ValuesIn(kVerifyEndEntityTestData));
-// Incomplete chains should still report the status of the intermediate.
+INSTANTIATE_TEST_CASE_P(VerifyEndEntity,
+ CertVerifyProcWeakDigestTest,
+ testing::ValuesIn(kVerifyEndEntityTestData));
+
+// Incomplete chains do not report the status of the intermediate.
+// Note: really each of these tests should also expect the digest algorithm of
+// the intermediate (included as a comment). However CertVerifyProc::Verify() is
+// unable to distinguish that this is an intermediate and not a trust anchor, so
+// this intermediate is treated like a trust anchor.
const WeakDigestTestData kVerifyIncompleteIntermediateTestData[] = {
{NULL, "weak_digest_md5_intermediate.pem", "weak_digest_sha1_ee.pem",
- EXPECT_MD5 | EXPECT_SHA1 | EXPECT_SHA1_LEAF},
-#if defined(USE_OPENSSL_CERTS) || defined(OS_WIN)
- // MD4 is not supported by OS X / NSS
+ /*EXPECT_MD5 |*/ EXPECT_SHA1 | EXPECT_SHA1_LEAF},
{NULL, "weak_digest_md4_intermediate.pem", "weak_digest_sha1_ee.pem",
- EXPECT_MD4 | EXPECT_SHA1 | EXPECT_SHA1_LEAF},
-#endif
+ /*EXPECT_MD4 |*/ EXPECT_SHA1 | EXPECT_SHA1_LEAF},
{NULL, "weak_digest_md2_intermediate.pem", "weak_digest_sha1_ee.pem",
- EXPECT_MD2 | EXPECT_SHA1 | EXPECT_SHA1_LEAF},
+ /*EXPECT_MD2 |*/ EXPECT_SHA1 | EXPECT_SHA1_LEAF},
};
-// Disabled on NSS - libpkix does not return constructed chains on error,
-// preventing us from detecting/inspecting the verified chain.
-#if defined(USE_NSS_CERTS) || defined(OS_IOS) || defined(OS_ANDROID)
-#define MAYBE_VerifyIncompleteIntermediate \
- DISABLED_VerifyIncompleteIntermediate
-#else
-#define MAYBE_VerifyIncompleteIntermediate VerifyIncompleteIntermediate
-#endif
-WRAPPED_INSTANTIATE_TEST_CASE_P(
+
+INSTANTIATE_TEST_CASE_P(
MAYBE_VerifyIncompleteIntermediate,
CertVerifyProcWeakDigestTest,
testing::ValuesIn(kVerifyIncompleteIntermediateTestData));
-// Incomplete chains should still report the status of the end-entity.
+// Incomplete chains should report the status of the end-entity.
+// Note: really each of these tests should also expect EXPECT_SHA1 (included as
+// a comment). However CertVerifyProc::Verify() is unable to distinguish that
+// this is an intermediate and not a trust anchor, so this intermediate is
+// treated like a trust anchor.
const WeakDigestTestData kVerifyIncompleteEETestData[] = {
- { NULL, "weak_digest_sha1_intermediate.pem", "weak_digest_md5_ee.pem",
- EXPECT_MD5 | EXPECT_SHA1 },
-#if defined(USE_OPENSSL_CERTS) || defined(OS_WIN)
- // MD4 is not supported by OS X / NSS
- { NULL, "weak_digest_sha1_intermediate.pem", "weak_digest_md4_ee.pem",
- EXPECT_MD4 | EXPECT_SHA1 },
-#endif
- { NULL, "weak_digest_sha1_intermediate.pem", "weak_digest_md2_ee.pem",
- EXPECT_MD2 | EXPECT_SHA1 },
+ {NULL, "weak_digest_sha1_intermediate.pem", "weak_digest_md5_ee.pem",
+ /*EXPECT_SHA1 |*/ EXPECT_MD5},
+ {NULL, "weak_digest_sha1_intermediate.pem", "weak_digest_md4_ee.pem",
+ /*EXPECT_SHA1 |*/ EXPECT_MD4},
+ {NULL, "weak_digest_sha1_intermediate.pem", "weak_digest_md2_ee.pem",
+ /*EXPECT_SHA1 |*/ EXPECT_MD2},
};
-// Disabled on NSS - libpkix does not return constructed chains on error,
-// preventing us from detecting/inspecting the verified chain.
-#if defined(USE_NSS_CERTS) || defined(OS_IOS) || defined(OS_ANDROID)
-#define MAYBE_VerifyIncompleteEndEntity DISABLED_VerifyIncompleteEndEntity
-#else
-#define MAYBE_VerifyIncompleteEndEntity VerifyIncompleteEndEntity
-#endif
-WRAPPED_INSTANTIATE_TEST_CASE_P(
- MAYBE_VerifyIncompleteEndEntity,
- CertVerifyProcWeakDigestTest,
- testing::ValuesIn(kVerifyIncompleteEETestData));
+
+INSTANTIATE_TEST_CASE_P(VerifyIncompleteEndEntity,
+ CertVerifyProcWeakDigestTest,
+ testing::ValuesIn(kVerifyIncompleteEETestData));
// Differing algorithms between the intermediate and the EE should still be
// reported.
@@ -1860,23 +1841,26 @@ const WeakDigestTestData kVerifyMixedTestData[] = {
"weak_digest_md2_ee.pem", EXPECT_MD2 | EXPECT_MD5 },
{ "weak_digest_sha1_root.pem", "weak_digest_md2_intermediate.pem",
"weak_digest_md5_ee.pem", EXPECT_MD2 | EXPECT_MD5 },
-#if defined(USE_OPENSSL_CERTS) || defined(OS_WIN)
- // MD4 is not supported by OS X / NSS
{ "weak_digest_sha1_root.pem", "weak_digest_md4_intermediate.pem",
"weak_digest_md2_ee.pem", EXPECT_MD2 | EXPECT_MD4 },
-#endif
};
-// NSS does not support MD4 and does not enable MD2 by default, making all
-// permutations invalid.
-#if defined(USE_NSS_CERTS) || defined(OS_IOS) || defined(OS_ANDROID)
-#define MAYBE_VerifyMixed DISABLED_VerifyMixed
-#else
-#define MAYBE_VerifyMixed VerifyMixed
-#endif
-WRAPPED_INSTANTIATE_TEST_CASE_P(
- MAYBE_VerifyMixed,
- CertVerifyProcWeakDigestTest,
- testing::ValuesIn(kVerifyMixedTestData));
+
+INSTANTIATE_TEST_CASE_P(VerifyMixed,
+ CertVerifyProcWeakDigestTest,
+ testing::ValuesIn(kVerifyMixedTestData));
+
+// The EE is a trusted certificate. Even though it uses weak hashes, these
+// should not be reported.
+const WeakDigestTestData kVerifyTrustedEETestData[] = {
+ {NULL, NULL, "weak_digest_md5_ee.pem", 0},
+ {NULL, NULL, "weak_digest_md4_ee.pem", 0},
+ {NULL, NULL, "weak_digest_md2_ee.pem", 0},
+ {NULL, NULL, "weak_digest_sha1_ee.pem", 0},
+};
+
+INSTANTIATE_TEST_CASE_P(VerifyTrustedEE,
+ CertVerifyProcWeakDigestTest,
+ testing::ValuesIn(kVerifyTrustedEETestData));
// For the list of valid hostnames, see
// net/cert/data/ssl/certificates/subjectAltName_sanity_check.pem
@@ -1938,15 +1922,17 @@ TEST_P(CertVerifyProcNameTest, VerifyCertName) {
}
}
-WRAPPED_INSTANTIATE_TEST_CASE_P(
- VerifyName,
- CertVerifyProcNameTest,
- testing::ValuesIn(kVerifyNameData));
+INSTANTIATE_TEST_CASE_P(VerifyName,
+ CertVerifyProcNameTest,
+ testing::ValuesIn(kVerifyNameData));
#if defined(OS_MACOSX) && !defined(OS_IOS)
// Test that CertVerifyProcMac reacts appropriately when Apple's certificate
// verifier rejects a certificate with a fatal error. This is a regression
// test for https://crbug.com/472291.
+// (Since 10.12, this causes a recoverable error instead of a fatal one.)
+// TODO(mattm): Try to find a different way to cause a fatal error that works
+// on 10.12.
TEST_F(CertVerifyProcTest, LargeKey) {
// Load root_ca_cert.pem into the test root store.
ScopedTestRoot test_root(
@@ -1963,7 +1949,7 @@ TEST_F(CertVerifyProcTest, LargeKey) {
int error = Verify(cert.get(), "127.0.0.1", flags, NULL, empty_cert_list_,
&verify_result);
EXPECT_THAT(error, IsError(ERR_CERT_INVALID));
- EXPECT_EQ(CERT_STATUS_INVALID, verify_result.cert_status);
+ EXPECT_TRUE(verify_result.cert_status & CERT_STATUS_INVALID);
}
#endif // defined(OS_MACOSX) && !defined(OS_IOS)
diff --git a/chromium/net/cert/cert_verify_proc_whitelist.cc b/chromium/net/cert/cert_verify_proc_whitelist.cc
index 5c53a77a36c..2ba4166d4d8 100644
--- a/chromium/net/cert/cert_verify_proc_whitelist.cc
+++ b/chromium/net/cert/cert_verify_proc_whitelist.cc
@@ -6,6 +6,7 @@
#include <cstdlib>
+#include "net/base/lookup_string_in_fixed_set.h"
#include "net/cert/x509_certificate.h"
namespace net {
@@ -46,1604 +47,7 @@ const uint8_t kWosignKeys[][crypto::kSHA256Length] = {
0x21, 0x9f, 0xe0, 0xe9, 0xe3, 0xa3, 0x82, 0xa1,
0xb3, 0xcb, 0x66, 0xc9, 0x39, 0x55, 0xde, 0x75 },
};
-
-// SHA-256 hashes of the leaf certificates whitelisted as issued by CNNIC's
-// DV root.
-const uint8_t kCNNICDVWhitelist[][crypto::kSHA256Length] = {
- { 0x00, 0xc5, 0x9f, 0x5e, 0xf3, 0xb4, 0x6d, 0xbc,
- 0xa0, 0xa8, 0xbb, 0xa5, 0x0a, 0x72, 0xd4, 0xe1,
- 0x83, 0x9a, 0x94, 0xfb, 0x1a, 0x58, 0x5a, 0xd7,
- 0x2a, 0x7a, 0xac, 0x3c, 0x72, 0x56, 0x1f, 0xc0 },
- { 0x02, 0x01, 0x4e, 0x80, 0xf5, 0xc4, 0xf3, 0x8b,
- 0xa9, 0xd9, 0x04, 0x79, 0x1a, 0x63, 0xf6, 0x4d,
- 0x05, 0xf9, 0xe2, 0x03, 0xa1, 0xf1, 0x2b, 0x06,
- 0xd6, 0x55, 0x94, 0x01, 0x41, 0x0e, 0x73, 0x36 },
- { 0x02, 0x35, 0x38, 0xe2, 0x48, 0x15, 0x28, 0x75,
- 0x29, 0x2f, 0x2c, 0x83, 0x9a, 0xb3, 0x2b, 0xc7,
- 0x35, 0x1e, 0x2b, 0x29, 0x99, 0x1d, 0x66, 0xae,
- 0xa6, 0x16, 0xcb, 0x0b, 0x26, 0xa5, 0xe3, 0x75 },
- { 0x02, 0xec, 0x35, 0xf5, 0x83, 0x4c, 0xd2, 0xc3,
- 0x43, 0x33, 0x39, 0x9a, 0xea, 0x6b, 0xda, 0x84,
- 0x68, 0xab, 0x8d, 0x74, 0xef, 0x6c, 0xa5, 0x2d,
- 0x33, 0x7a, 0x30, 0x69, 0x4c, 0x3f, 0x95, 0xa4 },
- { 0x03, 0xe0, 0x6e, 0x0b, 0x7a, 0x2c, 0xba, 0xe4,
- 0xb6, 0x8b, 0xce, 0x5f, 0x83, 0xe7, 0xa9, 0x31,
- 0x6e, 0xd7, 0x82, 0x3e, 0x8d, 0x94, 0x85, 0x38,
- 0xf1, 0x94, 0x3f, 0xa4, 0x27, 0xd7, 0x91, 0x0e },
- { 0x04, 0x0f, 0x53, 0x7a, 0x51, 0x95, 0x95, 0xcc,
- 0xff, 0xde, 0x35, 0xe0, 0xd1, 0x28, 0xb7, 0x99,
- 0x92, 0x2b, 0xa9, 0x37, 0xa2, 0xe8, 0x65, 0x84,
- 0x36, 0x62, 0xf1, 0xf4, 0x50, 0x02, 0xb8, 0x2d },
- { 0x07, 0x19, 0x4f, 0x47, 0xf4, 0xce, 0xd0, 0x96,
- 0xd1, 0x06, 0x8d, 0x34, 0x49, 0x3b, 0x67, 0x37,
- 0x14, 0x45, 0x16, 0x93, 0xa6, 0xa2, 0x71, 0x2f,
- 0x70, 0x8f, 0x59, 0x36, 0x12, 0x11, 0xc6, 0x21 },
- { 0x07, 0x8f, 0xee, 0x58, 0x8a, 0x2c, 0x55, 0xc8,
- 0xe2, 0xc1, 0x78, 0x71, 0xaa, 0xb6, 0xe4, 0x00,
- 0xb3, 0xfd, 0xbc, 0xdc, 0xf3, 0x91, 0x46, 0xa0,
- 0x89, 0x37, 0xf9, 0xac, 0x06, 0xa1, 0xb8, 0xbd },
- { 0x08, 0x21, 0x0a, 0xc3, 0xa2, 0x95, 0x56, 0xf6,
- 0x8d, 0x33, 0xb4, 0x40, 0x87, 0x9c, 0x54, 0x63,
- 0x64, 0x04, 0xe9, 0x7c, 0x4d, 0x9f, 0x97, 0x82,
- 0x23, 0xd2, 0x42, 0xab, 0xe5, 0x38, 0x5e, 0x4e },
- { 0x08, 0xc2, 0xd3, 0x17, 0xa8, 0x4a, 0x3c, 0xbe,
- 0x38, 0xde, 0x64, 0xa2, 0x4d, 0xd4, 0x27, 0x91,
- 0x09, 0xe2, 0xbc, 0x02, 0x2b, 0x93, 0xb1, 0x05,
- 0xa8, 0x94, 0xa5, 0x1a, 0xdc, 0x3e, 0xe5, 0xcc },
- { 0x09, 0x9f, 0x3e, 0x71, 0xb5, 0x00, 0xd1, 0x5b,
- 0x03, 0x7b, 0x93, 0xaa, 0x5f, 0xb4, 0x16, 0x19,
- 0x0a, 0xd1, 0xdf, 0x86, 0x73, 0xab, 0x31, 0xa8,
- 0xf6, 0xd9, 0x7f, 0x59, 0x5e, 0x8e, 0x16, 0xe9 },
- { 0x09, 0xeb, 0xdd, 0x1b, 0x7f, 0xfa, 0x4e, 0xd7,
- 0x4b, 0xeb, 0xae, 0x96, 0xba, 0x10, 0x65, 0xdc,
- 0x7d, 0xa1, 0xc5, 0xd3, 0x18, 0x3c, 0xc5, 0x94,
- 0x19, 0xe9, 0x78, 0x36, 0xaf, 0x7f, 0x6d, 0x70 },
- { 0x0a, 0x01, 0x88, 0x81, 0x2c, 0x9d, 0xe8, 0x8a,
- 0x2f, 0x0a, 0x5c, 0x4c, 0x57, 0xe6, 0xf9, 0xa8,
- 0x15, 0x69, 0xe9, 0xc7, 0x09, 0xc0, 0x95, 0x40,
- 0x80, 0xe5, 0xe4, 0xe6, 0x62, 0x85, 0x6d, 0xf8 },
- { 0x0a, 0x42, 0x19, 0x7e, 0x48, 0x70, 0xb2, 0x34,
- 0x20, 0xf5, 0x51, 0x9f, 0xb8, 0x39, 0xb6, 0xcc,
- 0x83, 0x03, 0x52, 0x9a, 0xa9, 0x06, 0x9a, 0xd1,
- 0xa0, 0x90, 0x86, 0xcf, 0x6c, 0xba, 0x07, 0xc2 },
- { 0x0b, 0x03, 0xe1, 0x27, 0xc2, 0xe3, 0x3e, 0xad,
- 0xbc, 0xb0, 0x99, 0x80, 0x46, 0xcc, 0x9b, 0xa7,
- 0x33, 0x46, 0x3e, 0x0c, 0xa6, 0x43, 0x52, 0x27,
- 0x81, 0xb0, 0x3d, 0x81, 0x53, 0x97, 0xeb, 0x4f },
- { 0x0b, 0x1e, 0x1e, 0x73, 0x43, 0xa0, 0xe9, 0x1c,
- 0x2a, 0x27, 0xdd, 0x2a, 0x4d, 0x7e, 0x6b, 0xf1,
- 0xe8, 0x04, 0x4b, 0x58, 0xce, 0x1a, 0xe8, 0x1e,
- 0x27, 0xd8, 0x14, 0xfd, 0x2d, 0xc0, 0x18, 0x93 },
- { 0x0b, 0x48, 0xd5, 0x5c, 0xac, 0x84, 0xfd, 0xee,
- 0x15, 0xd8, 0x1a, 0xff, 0x99, 0x07, 0xbb, 0x9a,
- 0x57, 0x11, 0xa9, 0x5c, 0xe2, 0x3a, 0x8d, 0x4d,
- 0x5e, 0x88, 0x62, 0xbf, 0x15, 0xa7, 0x6a, 0x75 },
- { 0x0b, 0xfe, 0xa1, 0x38, 0x31, 0x67, 0x3e, 0xc9,
- 0x69, 0xd0, 0x5f, 0xd8, 0x67, 0xb6, 0x69, 0xf2,
- 0x71, 0x24, 0xaf, 0xeb, 0x7c, 0x60, 0x8c, 0xfe,
- 0x54, 0xcf, 0x46, 0x33, 0x06, 0xcc, 0x99, 0x2e },
- { 0x0c, 0xb9, 0x31, 0x93, 0xf1, 0x65, 0x26, 0xe1,
- 0xd1, 0x65, 0x52, 0x11, 0x7b, 0xa2, 0x1a, 0xac,
- 0xb9, 0xf1, 0xd7, 0xa8, 0x93, 0x56, 0xa3, 0x5d,
- 0xe4, 0xf6, 0x65, 0xe9, 0x39, 0x90, 0x79, 0x38 },
- { 0x0d, 0x16, 0x1b, 0xb9, 0xca, 0x0d, 0x20, 0xe4,
- 0x67, 0x35, 0x89, 0x67, 0x22, 0x78, 0xb0, 0xa3,
- 0xc5, 0xe2, 0x69, 0x30, 0xa4, 0xdc, 0x3a, 0x82,
- 0x16, 0x85, 0x43, 0x24, 0x27, 0xc7, 0x31, 0x5a },
- { 0x0d, 0x71, 0xc8, 0xca, 0x16, 0x56, 0x59, 0xef,
- 0xaf, 0x69, 0x65, 0x29, 0x28, 0x9a, 0xae, 0x25,
- 0xd9, 0xc4, 0x2a, 0x1b, 0xbb, 0x03, 0x5a, 0x2b,
- 0x8c, 0x61, 0x14, 0x7e, 0x1b, 0x8b, 0x90, 0x52 },
- { 0x0e, 0xfd, 0x68, 0x73, 0xd6, 0x0e, 0x77, 0x96,
- 0x2d, 0xf6, 0x00, 0x16, 0xdc, 0x3b, 0xaf, 0x9c,
- 0xa7, 0x1e, 0x7d, 0x86, 0x19, 0xe7, 0xeb, 0xaa,
- 0x3a, 0xf2, 0xdc, 0xb5, 0xba, 0x24, 0xde, 0xc2 },
- { 0x0e, 0xff, 0x3c, 0xff, 0xda, 0x4a, 0x3e, 0x87,
- 0x23, 0x4a, 0x86, 0xc7, 0x0d, 0x49, 0x8c, 0x62,
- 0x60, 0x7f, 0x37, 0x44, 0xea, 0x71, 0xf1, 0x83,
- 0x1d, 0xcf, 0xca, 0xf3, 0xaf, 0x15, 0x56, 0x9c },
- { 0x10, 0x83, 0x6d, 0xa0, 0xcd, 0x6a, 0xc0, 0x95,
- 0xdd, 0x7a, 0xc3, 0x4d, 0x99, 0x01, 0x90, 0x9a,
- 0x8e, 0xf8, 0x4d, 0x6e, 0xe0, 0x5b, 0x83, 0x43,
- 0x03, 0xd4, 0x7f, 0xc0, 0xa5, 0xf9, 0x14, 0xfa },
- { 0x11, 0xa4, 0x02, 0x7b, 0x45, 0xfc, 0x9a, 0x6f,
- 0x40, 0x21, 0x25, 0xc3, 0xca, 0x22, 0x68, 0xe0,
- 0x15, 0xa3, 0x1b, 0xa4, 0xfd, 0xb0, 0x05, 0x9d,
- 0x66, 0x6b, 0x73, 0xc8, 0x51, 0xd5, 0x35, 0x92 },
- { 0x12, 0x6b, 0x1b, 0xa6, 0x38, 0xc7, 0xe6, 0x99,
- 0xbc, 0xbc, 0x54, 0xf5, 0x79, 0xac, 0xd3, 0x9f,
- 0xe6, 0x1d, 0x08, 0x22, 0x5f, 0xe5, 0xb1, 0xf9,
- 0x01, 0x88, 0xb2, 0x3f, 0xd8, 0x43, 0x3e, 0x8e },
- { 0x13, 0x5d, 0x3e, 0xda, 0x6e, 0x55, 0x9b, 0xf5,
- 0xee, 0x23, 0x0a, 0xa5, 0xba, 0x59, 0xbb, 0x6a,
- 0x2a, 0x0f, 0x07, 0x82, 0x2f, 0xed, 0x38, 0x44,
- 0x7e, 0x6a, 0xbc, 0x5c, 0x23, 0xaa, 0xd0, 0x27 },
- { 0x13, 0x6a, 0x40, 0x09, 0x81, 0xb1, 0xa3, 0xe0,
- 0x5f, 0xdc, 0xac, 0x20, 0xa2, 0x36, 0xf8, 0x6e,
- 0x94, 0xe5, 0xee, 0x58, 0x59, 0xd8, 0xfd, 0x45,
- 0xe9, 0xe9, 0xc5, 0xa6, 0xc5, 0xc0, 0xa4, 0x13 },
- { 0x14, 0x21, 0x28, 0xa6, 0x65, 0x1c, 0xdc, 0x18,
- 0x70, 0xc2, 0x67, 0x5e, 0xc0, 0xb0, 0xef, 0x32,
- 0xb5, 0xd4, 0xc1, 0x55, 0x35, 0x8e, 0x7e, 0xd9,
- 0x5a, 0x98, 0xe8, 0x3b, 0x1a, 0xd8, 0xbe, 0x4d },
- { 0x14, 0x47, 0x25, 0xa6, 0x79, 0x1c, 0x60, 0x0c,
- 0x4c, 0x2c, 0xf3, 0x94, 0x3f, 0x3e, 0xcf, 0x40,
- 0xd6, 0x31, 0xd7, 0x60, 0xe4, 0x51, 0xef, 0x28,
- 0x29, 0xaf, 0xfb, 0xee, 0x74, 0x80, 0xad, 0x17 },
- { 0x15, 0x27, 0x2a, 0xbc, 0x1f, 0x0c, 0x4d, 0x1d,
- 0x1a, 0x92, 0x08, 0x73, 0x55, 0xa1, 0xe0, 0x42,
- 0x6c, 0x2b, 0xb5, 0xb4, 0x37, 0x30, 0x00, 0xb8,
- 0x2c, 0x2c, 0xca, 0xb7, 0xfa, 0xd6, 0xfa, 0x20 },
- { 0x15, 0x48, 0x1f, 0xde, 0x4e, 0x3f, 0x72, 0x49,
- 0x66, 0x87, 0xdf, 0x57, 0x5f, 0xb5, 0xb1, 0x27,
- 0xbd, 0x6d, 0xeb, 0x66, 0x1d, 0xd9, 0x07, 0x71,
- 0x8b, 0xa0, 0x65, 0xc7, 0xda, 0x66, 0x76, 0xd1 },
- { 0x15, 0x5a, 0x88, 0x39, 0x60, 0x8b, 0x77, 0x25,
- 0x34, 0x6a, 0x72, 0x40, 0xe4, 0xe2, 0x50, 0x3a,
- 0xcc, 0x7b, 0x8b, 0xef, 0x0b, 0x1b, 0xe6, 0x15,
- 0xb9, 0x02, 0x4a, 0x88, 0xe6, 0x52, 0x11, 0xf9 },
- { 0x15, 0x5d, 0x88, 0x6e, 0x99, 0x1d, 0x40, 0x0a,
- 0xbf, 0x2f, 0x83, 0xc2, 0x80, 0xd1, 0x24, 0x6d,
- 0xce, 0x02, 0xa6, 0x28, 0x31, 0x26, 0xc6, 0x17,
- 0xe4, 0x17, 0xd2, 0xb7, 0xea, 0xc1, 0x19, 0x24 },
- { 0x17, 0x3d, 0xe2, 0x60, 0xe2, 0x2d, 0x76, 0x9d,
- 0x2d, 0x54, 0x99, 0xc8, 0x22, 0x0d, 0x86, 0xed,
- 0xe3, 0x48, 0xda, 0x1e, 0x57, 0xc1, 0xe7, 0xc8,
- 0x15, 0x07, 0xfb, 0x3e, 0x6b, 0xd7, 0x3b, 0x7f },
- { 0x18, 0x1e, 0xbb, 0x29, 0x8d, 0x20, 0x68, 0x5c,
- 0x48, 0xf7, 0x53, 0x89, 0x80, 0xc5, 0x63, 0xc8,
- 0xf7, 0x48, 0x95, 0x4c, 0xf2, 0x64, 0x41, 0x9a,
- 0x72, 0xfc, 0xc6, 0x34, 0x0a, 0x10, 0x23, 0x80 },
- { 0x19, 0xff, 0xe6, 0xc6, 0x7a, 0x35, 0x86, 0xfc,
- 0x48, 0x6c, 0xe2, 0x07, 0xfa, 0x2a, 0xf6, 0x62,
- 0xf5, 0x50, 0xfc, 0x51, 0x2f, 0xdd, 0x78, 0x17,
- 0xe3, 0x86, 0xc9, 0x4a, 0x7b, 0xde, 0x37, 0xa9 },
- { 0x1a, 0x9e, 0xc6, 0x8c, 0xed, 0xb6, 0xbd, 0x94,
- 0x0c, 0x95, 0x34, 0xe6, 0x84, 0xbb, 0x04, 0x9f,
- 0xf1, 0xe2, 0x3b, 0x66, 0xa1, 0x33, 0x01, 0x2f,
- 0xc3, 0x99, 0xeb, 0x4f, 0xb5, 0xd3, 0xaa, 0x35 },
- { 0x1b, 0x7b, 0xf8, 0xd9, 0xe8, 0x29, 0x3c, 0x53,
- 0xdd, 0x59, 0xec, 0x97, 0xfe, 0x16, 0xf0, 0xea,
- 0xb4, 0x68, 0x5b, 0x95, 0xce, 0x14, 0xd2, 0x62,
- 0x3e, 0x70, 0x94, 0x2c, 0xff, 0x25, 0xe7, 0x30 },
- { 0x1b, 0xd7, 0xb3, 0x62, 0xbc, 0x14, 0x66, 0xfa,
- 0xc0, 0x5e, 0xc5, 0x9e, 0x12, 0xe8, 0x1b, 0xe7,
- 0x35, 0x38, 0xc4, 0x97, 0x28, 0xf5, 0xad, 0xba,
- 0x2d, 0x81, 0xfc, 0xdb, 0xc4, 0x65, 0x7c, 0x1b },
- { 0x1b, 0xec, 0xfe, 0x78, 0xce, 0x5e, 0x77, 0xa9,
- 0x77, 0xbb, 0x5f, 0xe3, 0x49, 0x91, 0x06, 0xc6,
- 0x4c, 0xf2, 0xb0, 0x76, 0x16, 0x59, 0x49, 0x04,
- 0x11, 0x17, 0xcd, 0x8a, 0xbc, 0xd9, 0x05, 0xd4 },
- { 0x1b, 0xf4, 0x8a, 0x83, 0x3c, 0xe4, 0x05, 0x64,
- 0x8c, 0xc0, 0xbd, 0xd3, 0xb5, 0xb8, 0xc1, 0x8e,
- 0xb5, 0x13, 0x15, 0x34, 0x29, 0x3a, 0xb2, 0x63,
- 0x44, 0xb5, 0x00, 0x76, 0x48, 0x11, 0x41, 0xed },
- { 0x1c, 0x04, 0x82, 0x0f, 0x7b, 0x4a, 0x2f, 0x1e,
- 0x38, 0x5d, 0xe1, 0xde, 0x16, 0xb2, 0x22, 0x6e,
- 0x88, 0x3d, 0x9c, 0x34, 0x66, 0x3e, 0x1b, 0x64,
- 0xe8, 0x5b, 0x98, 0x0e, 0xaf, 0xf0, 0xb9, 0xd3 },
- { 0x1d, 0x9e, 0xc0, 0x06, 0xa5, 0x26, 0xfa, 0xb5,
- 0xce, 0x2e, 0x71, 0xfd, 0xfc, 0x07, 0xc0, 0x11,
- 0xf7, 0x65, 0x7b, 0xf8, 0x5f, 0x5d, 0x03, 0x52,
- 0xb8, 0xcb, 0x21, 0x8d, 0x4f, 0xcb, 0xc4, 0x43 },
- { 0x1e, 0x78, 0xf8, 0x08, 0x84, 0xe3, 0x2a, 0x2e,
- 0xa5, 0xad, 0x1e, 0xe8, 0x35, 0x88, 0xac, 0xdb,
- 0x18, 0x4a, 0x4a, 0x6e, 0x87, 0x56, 0x5b, 0xf5,
- 0x03, 0xb5, 0x69, 0x7a, 0xbf, 0xae, 0x64, 0xa4 },
- { 0x1f, 0x11, 0x85, 0xa5, 0x21, 0xe2, 0x8e, 0x95,
- 0x17, 0x1c, 0xf3, 0x86, 0x07, 0x8a, 0x76, 0x4a,
- 0x9a, 0x3e, 0x71, 0xc2, 0x59, 0xbc, 0xdc, 0x5f,
- 0x8e, 0x66, 0xe1, 0xb5, 0x20, 0x55, 0xa2, 0x6d },
- { 0x1f, 0x23, 0xd7, 0xa6, 0x38, 0x17, 0x1f, 0x6d,
- 0x09, 0x99, 0x64, 0xe0, 0xfa, 0x01, 0x72, 0x1c,
- 0x06, 0xcc, 0xeb, 0x8e, 0xa2, 0x98, 0xbf, 0xd0,
- 0x04, 0x8e, 0x13, 0x8d, 0x98, 0xfc, 0x36, 0x24 },
- { 0x1f, 0xc7, 0xf8, 0x10, 0x4e, 0x27, 0xff, 0x2a,
- 0x45, 0x56, 0xf9, 0x1e, 0x05, 0x42, 0x17, 0xc5,
- 0x8f, 0x69, 0x3f, 0x70, 0x36, 0x25, 0x9e, 0x39,
- 0x80, 0xb5, 0x59, 0x5b, 0x04, 0x3d, 0x11, 0x92 },
- { 0x20, 0x0b, 0x49, 0xbd, 0xd6, 0x35, 0x02, 0x57,
- 0xcc, 0xd4, 0xe6, 0xad, 0xe1, 0xcb, 0x75, 0x13,
- 0x8d, 0xd6, 0xd9, 0x06, 0xfe, 0xf3, 0x49, 0xc0,
- 0xc9, 0x86, 0xa5, 0x1b, 0x29, 0xb9, 0xe5, 0x2d },
- { 0x21, 0x78, 0xe8, 0x28, 0x3a, 0x73, 0x39, 0x6e,
- 0x08, 0xc0, 0xa1, 0x1a, 0x88, 0x72, 0xfa, 0x4a,
- 0x9f, 0xcc, 0x05, 0x67, 0x0c, 0xee, 0xff, 0xb8,
- 0x95, 0x83, 0x8e, 0xb6, 0x59, 0xde, 0x38, 0xdb },
- { 0x22, 0x01, 0x71, 0xf7, 0x0e, 0x1f, 0xc3, 0xc4,
- 0xf7, 0x8d, 0xa6, 0xc8, 0xb1, 0xd7, 0x2c, 0x3b,
- 0xa8, 0x31, 0x9a, 0x46, 0xf8, 0x19, 0x2d, 0x1e,
- 0x19, 0xb9, 0xe2, 0x9a, 0xba, 0x18, 0xee, 0x87 },
- { 0x23, 0x19, 0xcb, 0x3d, 0x58, 0xc6, 0xd5, 0x53,
- 0x62, 0x5d, 0xe5, 0xf4, 0x25, 0x2b, 0xf0, 0x29,
- 0xab, 0x83, 0x05, 0xeb, 0xf2, 0x2f, 0xa2, 0x3e,
- 0x99, 0x73, 0x04, 0x66, 0xde, 0x24, 0xd6, 0xc3 },
- { 0x23, 0x8a, 0x80, 0xcc, 0x9b, 0x58, 0x9a, 0xdc,
- 0x89, 0xb7, 0xa8, 0xf3, 0x4d, 0xdf, 0x12, 0x48,
- 0x73, 0x4b, 0x9f, 0x7f, 0x78, 0x20, 0xb6, 0x04,
- 0x07, 0x66, 0xc5, 0x41, 0x3a, 0xd2, 0xbd, 0xef },
- { 0x23, 0x9c, 0x79, 0x5f, 0x0c, 0x55, 0xa5, 0x53,
- 0x16, 0x2a, 0x9c, 0xa0, 0x6e, 0x88, 0x01, 0xe1,
- 0x19, 0xbd, 0xff, 0x54, 0x35, 0x4a, 0x3f, 0x68,
- 0x43, 0xcf, 0x2a, 0x2f, 0xa6, 0x01, 0x75, 0x8e },
- { 0x24, 0x62, 0x52, 0x48, 0x32, 0xc1, 0x54, 0xd8,
- 0x4d, 0xf5, 0x8e, 0xd7, 0x75, 0x22, 0x3b, 0xbe,
- 0x25, 0x7d, 0xea, 0xf7, 0x0e, 0xf9, 0xd2, 0x08,
- 0x61, 0x4e, 0xc0, 0xf5, 0x97, 0x7f, 0x6d, 0x58 },
- { 0x24, 0x6d, 0x0c, 0x31, 0x48, 0x72, 0x75, 0x59,
- 0xf9, 0x9a, 0xd0, 0xc1, 0x50, 0x37, 0x70, 0x06,
- 0xb7, 0xa1, 0x7a, 0x60, 0x3a, 0x47, 0x3b, 0x6a,
- 0xac, 0xd2, 0x4e, 0x16, 0xc6, 0xc5, 0x1b, 0x42 },
- { 0x25, 0x1b, 0xb7, 0xc5, 0x42, 0x33, 0xda, 0x44,
- 0xbf, 0x53, 0xb5, 0x8a, 0xf2, 0x9a, 0xe1, 0x74,
- 0xb9, 0x78, 0xba, 0xdb, 0x89, 0xa9, 0x50, 0xab,
- 0x3e, 0x5f, 0x9b, 0x4d, 0x0d, 0xcd, 0xbc, 0x62 },
- { 0x26, 0x03, 0xcb, 0xdf, 0x69, 0x75, 0xe3, 0x68,
- 0x83, 0x7f, 0x95, 0x1a, 0x00, 0x49, 0xfd, 0xc3,
- 0xc4, 0xb2, 0x39, 0xf0, 0x82, 0xf6, 0xbf, 0x89,
- 0x5d, 0xb8, 0xf3, 0x27, 0x05, 0xe6, 0x9c, 0xf3 },
- { 0x27, 0x50, 0x11, 0x93, 0xe4, 0x61, 0xca, 0xce,
- 0x55, 0x32, 0xfa, 0xd5, 0xd5, 0xb2, 0x7e, 0x01,
- 0x16, 0x57, 0x92, 0xe0, 0x4f, 0x24, 0x21, 0x93,
- 0x2f, 0x39, 0x28, 0xaf, 0x9f, 0xcd, 0xa4, 0xf3 },
- { 0x27, 0xa8, 0x41, 0xae, 0xcf, 0xe0, 0xa1, 0x39,
- 0x37, 0x51, 0xc2, 0x55, 0xf9, 0x06, 0xdb, 0x9e,
- 0x88, 0x6b, 0xba, 0x4d, 0x7c, 0x44, 0xec, 0x63,
- 0xce, 0x7d, 0xc6, 0xde, 0xc1, 0x8b, 0xb9, 0x20 },
- { 0x28, 0x07, 0x10, 0x60, 0x44, 0x03, 0x45, 0xd0,
- 0x0e, 0x80, 0xb9, 0xd7, 0xcb, 0xe1, 0x87, 0xc1,
- 0xd8, 0xb0, 0xf2, 0xef, 0x5d, 0x0a, 0xac, 0x9c,
- 0xce, 0xef, 0x9a, 0x8c, 0x5a, 0x06, 0xf3, 0x02 },
- { 0x28, 0xd9, 0x51, 0x84, 0xb5, 0xea, 0x14, 0x0f,
- 0x47, 0x4f, 0x3a, 0xf6, 0xce, 0x70, 0x52, 0xe8,
- 0x59, 0x3c, 0xf3, 0xa5, 0x01, 0x0f, 0x52, 0x24,
- 0x1a, 0x1e, 0x36, 0x64, 0x60, 0xe5, 0x91, 0x9e },
- { 0x29, 0x01, 0x93, 0xe3, 0x7a, 0x38, 0x87, 0xfd,
- 0x36, 0x15, 0xdf, 0x12, 0x2e, 0x95, 0x21, 0x17,
- 0x42, 0x15, 0xee, 0x68, 0xf7, 0x44, 0xb2, 0xfa,
- 0x35, 0xd2, 0x9c, 0x5d, 0xf1, 0x08, 0xf5, 0x5b },
- { 0x2a, 0x0f, 0x70, 0x67, 0x6e, 0x18, 0x4d, 0x49,
- 0x39, 0xa4, 0x04, 0xde, 0x35, 0xac, 0x84, 0xab,
- 0x81, 0xaf, 0xec, 0x36, 0x17, 0xe7, 0xe1, 0xbf,
- 0x34, 0x67, 0xd4, 0x19, 0x25, 0x5d, 0xd8, 0x17 },
- { 0x2a, 0xa6, 0x47, 0x8c, 0xc7, 0x5d, 0x67, 0xa8,
- 0xca, 0x55, 0xb2, 0xe1, 0x63, 0xfd, 0xbb, 0xbc,
- 0x9d, 0x74, 0xb4, 0xe5, 0xf3, 0x7b, 0x7d, 0xbd,
- 0x13, 0xc9, 0x4e, 0x85, 0x8d, 0x40, 0xda, 0xd0 },
- { 0x2c, 0x82, 0x47, 0x4f, 0x0e, 0xf6, 0xcb, 0x65,
- 0x0a, 0x13, 0xef, 0x20, 0x99, 0x6e, 0x65, 0x7b,
- 0x67, 0x24, 0xf0, 0xa0, 0xd5, 0xee, 0x24, 0x6d,
- 0x26, 0xbb, 0xfa, 0x0a, 0xbb, 0x2c, 0x22, 0xe1 },
- { 0x2c, 0x9b, 0xe1, 0x2d, 0xa4, 0x99, 0xea, 0xbb,
- 0x2f, 0xfd, 0xf9, 0x91, 0x6f, 0x2b, 0x27, 0x18,
- 0x81, 0x19, 0x5b, 0x74, 0x19, 0xbd, 0x1e, 0xef,
- 0x8d, 0x50, 0x77, 0x2a, 0xb9, 0x46, 0x4a, 0xa8 },
- { 0x2c, 0xbd, 0xd5, 0x6c, 0xe4, 0xb4, 0x06, 0x09,
- 0xe9, 0xaa, 0x52, 0x1e, 0xaa, 0x76, 0xac, 0x7e,
- 0x55, 0x73, 0x7b, 0xf4, 0x3e, 0x2b, 0x0c, 0x30,
- 0xdd, 0xcf, 0x59, 0x87, 0x2e, 0xab, 0xe7, 0x7b },
- { 0x2d, 0xde, 0xe4, 0x5f, 0x72, 0x78, 0x38, 0xde,
- 0xad, 0xe6, 0x7e, 0x9c, 0xa7, 0x05, 0xeb, 0xb4,
- 0xc2, 0xe9, 0x40, 0xae, 0x1b, 0x9d, 0x62, 0x35,
- 0x72, 0x18, 0x04, 0x58, 0x31, 0xe9, 0x8f, 0xde },
- { 0x2e, 0x5d, 0xd2, 0x55, 0x09, 0x6d, 0x64, 0x83,
- 0x10, 0x5c, 0xb6, 0x03, 0x6c, 0x59, 0x17, 0x57,
- 0xfd, 0x98, 0x49, 0x70, 0x66, 0x05, 0x3f, 0x83,
- 0x39, 0xe4, 0xd8, 0xd0, 0xc3, 0x75, 0x49, 0x03 },
- { 0x2e, 0xd2, 0x05, 0x8f, 0x39, 0xea, 0xba, 0x5c,
- 0xb3, 0xd7, 0xdf, 0x24, 0xca, 0x74, 0xa7, 0x7d,
- 0xdc, 0x12, 0x06, 0x01, 0x52, 0x7b, 0x0f, 0x51,
- 0x06, 0x91, 0x05, 0xca, 0x88, 0x37, 0x6e, 0x20 },
- { 0x30, 0x7b, 0x09, 0x34, 0xef, 0x97, 0x85, 0xe7,
- 0x08, 0xed, 0x48, 0x1a, 0x99, 0x7a, 0x8a, 0x88,
- 0xb7, 0xbf, 0x22, 0xdd, 0x26, 0xaa, 0x17, 0x17,
- 0x31, 0xb8, 0xf7, 0xe0, 0xd5, 0x97, 0xb7, 0x08 },
- { 0x30, 0xe0, 0x69, 0x80, 0x9c, 0x79, 0x90, 0xf0,
- 0xb5, 0xf2, 0x66, 0xe8, 0x94, 0x59, 0x96, 0x42,
- 0xe8, 0x53, 0x50, 0xab, 0x82, 0x81, 0x05, 0x34,
- 0xc7, 0xf3, 0xfd, 0x67, 0x0c, 0x1b, 0xeb, 0x18 },
- { 0x31, 0x53, 0x47, 0x52, 0xb6, 0xf5, 0x48, 0x20,
- 0x91, 0x5c, 0x39, 0x5b, 0xee, 0x97, 0x5b, 0xc5,
- 0x4e, 0x3f, 0x07, 0xc0, 0x8c, 0xd3, 0x4c, 0x5a,
- 0x51, 0x15, 0xde, 0xf0, 0x17, 0xdb, 0x2b, 0x54 },
- { 0x31, 0xb8, 0x3e, 0x01, 0x90, 0x98, 0x95, 0xbc,
- 0x74, 0x2d, 0x6b, 0xe8, 0x40, 0x0a, 0xde, 0x51,
- 0xb2, 0x09, 0x83, 0xf6, 0x83, 0xa2, 0xaa, 0xee,
- 0xb2, 0x5f, 0x58, 0xdf, 0x98, 0x1b, 0xde, 0x0d },
- { 0x32, 0xef, 0x13, 0x33, 0x86, 0xbf, 0x0c, 0x63,
- 0xcf, 0x29, 0xd6, 0x2b, 0x0d, 0x76, 0x88, 0x9e,
- 0x9d, 0x9d, 0x53, 0x2e, 0xe4, 0x90, 0x38, 0x94,
- 0x4d, 0xbc, 0x21, 0x49, 0xd8, 0xca, 0xa5, 0xd1 },
- { 0x33, 0xd1, 0x6c, 0xd9, 0xe8, 0x2e, 0xdf, 0xfd,
- 0x0b, 0x3a, 0xfb, 0x46, 0xa6, 0x84, 0xc5, 0xa0,
- 0xd1, 0x2f, 0x2b, 0x40, 0x58, 0x6d, 0x53, 0x2f,
- 0x6a, 0xab, 0x54, 0xce, 0xbc, 0x42, 0x33, 0xd3 },
- { 0x34, 0x06, 0x4f, 0xf9, 0x3b, 0x27, 0x4c, 0xf5,
- 0xa7, 0x24, 0xec, 0x19, 0x64, 0x50, 0x4a, 0x71,
- 0x0a, 0xb9, 0x7b, 0xa1, 0x10, 0x3c, 0xd9, 0xb9,
- 0x8c, 0x81, 0xd0, 0xab, 0xcf, 0x3b, 0x19, 0xbd },
- { 0x34, 0x65, 0xc2, 0xf9, 0xa0, 0xcf, 0x36, 0xe5,
- 0xee, 0xf0, 0x27, 0x1c, 0x52, 0x91, 0x2d, 0x58,
- 0x6f, 0xb2, 0x0b, 0x94, 0x43, 0xe7, 0xd5, 0x82,
- 0xa3, 0xe2, 0x23, 0x93, 0xfa, 0xc8, 0x1b, 0xb4 },
- { 0x34, 0x87, 0x46, 0xbf, 0xd4, 0x98, 0xc3, 0xf5,
- 0xc8, 0x68, 0x5e, 0xea, 0xac, 0x57, 0x87, 0x2d,
- 0x3b, 0x47, 0xe6, 0x02, 0xf4, 0x97, 0xe9, 0xf0,
- 0x28, 0x54, 0x12, 0x32, 0x59, 0xfb, 0xe1, 0x69 },
- { 0x36, 0x45, 0xef, 0x7f, 0x5d, 0x15, 0xa5, 0x46,
- 0x7e, 0x85, 0x30, 0x7d, 0xda, 0x15, 0xcb, 0xbb,
- 0x55, 0xb7, 0x30, 0xae, 0xf8, 0xef, 0x9c, 0x71,
- 0x5d, 0x7d, 0x9f, 0xb4, 0x7f, 0xdf, 0x33, 0xad },
- { 0x36, 0xb4, 0xfe, 0x74, 0x3b, 0x6d, 0xf4, 0x4a,
- 0x71, 0x3e, 0x91, 0x4c, 0xab, 0xfb, 0xf2, 0xbe,
- 0x60, 0x24, 0x9b, 0x46, 0x43, 0x4d, 0x04, 0x43,
- 0x59, 0x12, 0x5a, 0x10, 0x6a, 0x37, 0xeb, 0x1c },
- { 0x36, 0xf5, 0xa9, 0x7d, 0x79, 0x3f, 0x84, 0x97,
- 0x44, 0xd6, 0xab, 0x39, 0xb7, 0xa8, 0x18, 0xf8,
- 0x17, 0x6e, 0x65, 0x20, 0xdc, 0x86, 0x3d, 0xce,
- 0x43, 0xb3, 0x98, 0xc3, 0x0b, 0x5e, 0xdb, 0x09 },
- { 0x38, 0x23, 0x4e, 0x55, 0x9d, 0x30, 0x27, 0xd1,
- 0x61, 0xda, 0x8c, 0x98, 0x88, 0x04, 0x9a, 0x4d,
- 0x20, 0xac, 0xf2, 0x00, 0x90, 0xad, 0x1a, 0x22,
- 0x2b, 0x73, 0x9a, 0xc8, 0x6e, 0xb7, 0x6f, 0x06 },
- { 0x39, 0x02, 0x27, 0xce, 0x88, 0x1c, 0x71, 0x8b,
- 0x59, 0xa6, 0xbc, 0x31, 0x90, 0xd5, 0x17, 0xe7,
- 0x1e, 0x1e, 0x58, 0x66, 0x93, 0xc8, 0xbf, 0x8a,
- 0x30, 0x27, 0x26, 0x20, 0x13, 0xfe, 0x16, 0x63 },
- { 0x39, 0x21, 0x5c, 0xaa, 0x37, 0x1a, 0xbe, 0x57,
- 0x6a, 0xb9, 0x3b, 0x18, 0xc2, 0xf3, 0x75, 0x5e,
- 0xe2, 0x6f, 0x8c, 0x3a, 0xdb, 0x75, 0x9b, 0x6f,
- 0x34, 0x78, 0x9f, 0xb8, 0xec, 0xf0, 0x54, 0x28 },
- { 0x39, 0x7d, 0x00, 0x6e, 0xf8, 0xaf, 0xb2, 0x0f,
- 0x43, 0x61, 0xa6, 0xc9, 0x72, 0xf0, 0xc5, 0x7c,
- 0xc0, 0x87, 0x74, 0x01, 0x06, 0x12, 0x78, 0x3f,
- 0xba, 0xbc, 0xb8, 0xd6, 0xf6, 0x03, 0x9e, 0x2c },
- { 0x3a, 0xcf, 0x85, 0x3c, 0x4e, 0x45, 0x02, 0xbd,
- 0x82, 0xd5, 0x85, 0xd5, 0xe0, 0x82, 0xc4, 0xb3,
- 0xad, 0x03, 0xcd, 0xb6, 0xb5, 0x05, 0xca, 0x80,
- 0x47, 0x19, 0x88, 0xec, 0x4c, 0x58, 0x99, 0x9e },
- { 0x3a, 0xea, 0x2c, 0xef, 0xae, 0x63, 0x44, 0xff,
- 0xae, 0x67, 0x49, 0x4c, 0x68, 0x4e, 0x1e, 0xbf,
- 0x87, 0x95, 0x40, 0xb5, 0x3d, 0x40, 0xf5, 0x16,
- 0x9f, 0x78, 0x89, 0x7f, 0x1b, 0x38, 0xab, 0x66 },
- { 0x3b, 0x47, 0x85, 0x0b, 0xf8, 0x4c, 0x4c, 0xf2,
- 0xca, 0x6c, 0x31, 0xb3, 0x78, 0x39, 0xc9, 0x50,
- 0x76, 0x63, 0x70, 0xd7, 0xf4, 0xb6, 0x4a, 0xd0,
- 0x18, 0x55, 0xca, 0xcf, 0xe3, 0x51, 0x2f, 0xc3 },
- { 0x3b, 0xaa, 0x31, 0x31, 0x70, 0x68, 0xac, 0xe0,
- 0x89, 0xae, 0xb4, 0xa8, 0x8d, 0x7e, 0xde, 0xbe,
- 0x94, 0xab, 0x4a, 0xce, 0x46, 0xbb, 0xd2, 0x68,
- 0x3e, 0x3f, 0xdf, 0xf5, 0x59, 0x30, 0x0f, 0x93 },
- { 0x3c, 0x38, 0x36, 0x2e, 0x16, 0x8b, 0xb4, 0xa7,
- 0x59, 0xc4, 0x80, 0x55, 0x1c, 0xb1, 0x65, 0x6f,
- 0x6a, 0x96, 0x8b, 0x9b, 0x43, 0xcb, 0xe0, 0xd7,
- 0x39, 0x75, 0x4a, 0xb7, 0x8a, 0x28, 0x87, 0x0e },
- { 0x3c, 0x84, 0xa8, 0xb3, 0x4d, 0x0f, 0x95, 0xca,
- 0xc6, 0xfa, 0xaa, 0xb6, 0x22, 0xc2, 0x74, 0x46,
- 0xb4, 0xc4, 0x72, 0xdf, 0x34, 0x53, 0xd7, 0x54,
- 0x64, 0xc0, 0x96, 0x23, 0x86, 0x56, 0xb9, 0xd4 },
- { 0x3d, 0x14, 0x47, 0x2d, 0xce, 0x4a, 0xfd, 0xc2,
- 0x27, 0x6c, 0x81, 0x47, 0x97, 0xc7, 0xbc, 0x7a,
- 0x6c, 0x14, 0xf7, 0x95, 0x3e, 0x7e, 0x9f, 0xea,
- 0x69, 0x51, 0x04, 0x0f, 0x2d, 0xaf, 0xbe, 0x9a },
- { 0x3e, 0x8e, 0x9b, 0xad, 0x8e, 0xd9, 0xb5, 0x72,
- 0x38, 0x2e, 0x59, 0x8d, 0x2d, 0x73, 0x67, 0xe1,
- 0xfd, 0x6a, 0xf6, 0x95, 0x25, 0x00, 0x9d, 0x67,
- 0xb4, 0xe8, 0xaf, 0x80, 0xd9, 0x15, 0x85, 0x49 },
- { 0x3f, 0x27, 0xbd, 0xca, 0x9b, 0x0e, 0x42, 0xf3,
- 0xf6, 0xd0, 0x91, 0x2c, 0x92, 0xe2, 0xda, 0x65,
- 0xcb, 0x35, 0x8f, 0x0b, 0x8f, 0x80, 0x5b, 0xec,
- 0x5d, 0xe9, 0x32, 0x51, 0xd9, 0xc4, 0xb1, 0x99 },
- { 0x3f, 0x2e, 0xa6, 0x4e, 0xfb, 0xd6, 0xbf, 0xc4,
- 0x0a, 0xf0, 0xad, 0x46, 0xa4, 0xa2, 0x57, 0x84,
- 0x19, 0xd8, 0x68, 0x6e, 0x38, 0x98, 0x8b, 0x91,
- 0x47, 0x01, 0x8c, 0x36, 0x29, 0x31, 0xe4, 0xf9 },
- { 0x3f, 0x4f, 0x28, 0x8b, 0xaf, 0x5b, 0xde, 0x86,
- 0x72, 0xd6, 0xad, 0xd1, 0x50, 0xe3, 0x23, 0x79,
- 0x49, 0x9a, 0x16, 0xc5, 0x81, 0xfb, 0x77, 0x37,
- 0xec, 0x49, 0x80, 0xe4, 0xf9, 0xc3, 0x3d, 0x4d },
- { 0x3f, 0x92, 0x54, 0x89, 0x64, 0xcc, 0xde, 0xfb,
- 0x29, 0x96, 0x5a, 0x27, 0xc1, 0x6c, 0x2f, 0xed,
- 0x28, 0xd9, 0xb9, 0x14, 0x0e, 0x4f, 0xb5, 0x5b,
- 0x37, 0x22, 0x4c, 0x67, 0xb2, 0xa0, 0x55, 0x1f },
- { 0x40, 0x58, 0xec, 0x4a, 0x7a, 0x7b, 0xa0, 0xb8,
- 0x65, 0xa7, 0x39, 0xa0, 0x0c, 0x85, 0xf3, 0x44,
- 0x58, 0x79, 0xd6, 0x5e, 0x1d, 0x42, 0x2e, 0xed,
- 0x07, 0x65, 0x5a, 0x8e, 0x3e, 0xc3, 0x18, 0xcf },
- { 0x41, 0x29, 0x6b, 0x9f, 0xaa, 0xd6, 0x41, 0x33,
- 0xfc, 0xcb, 0xa6, 0xba, 0x74, 0x54, 0x11, 0xec,
- 0xc9, 0x11, 0xfd, 0x8e, 0xd5, 0x41, 0x90, 0x0f,
- 0x9e, 0x20, 0x36, 0x08, 0xee, 0xa3, 0x59, 0x2d },
- { 0x41, 0x88, 0x71, 0x80, 0x7e, 0xdc, 0xed, 0xa8,
- 0x57, 0xd7, 0xe8, 0x48, 0x31, 0x71, 0x81, 0xe1,
- 0xe8, 0x33, 0xf5, 0x4c, 0x89, 0xa6, 0x11, 0xa2,
- 0x30, 0xad, 0x99, 0x06, 0x5d, 0x45, 0x86, 0x95 },
- { 0x41, 0xa6, 0x8d, 0xfd, 0x90, 0xda, 0x6d, 0x12,
- 0x09, 0x84, 0x85, 0xbf, 0x6f, 0x87, 0x24, 0x5f,
- 0x4e, 0xc0, 0x54, 0x71, 0xda, 0x59, 0xd0, 0x81,
- 0x06, 0x01, 0x53, 0xa2, 0x22, 0x25, 0x23, 0x7f },
- { 0x42, 0x08, 0x71, 0xd8, 0xac, 0x49, 0x3c, 0xf9,
- 0x46, 0x8b, 0xb3, 0x76, 0x97, 0x6d, 0x65, 0x5e,
- 0xf0, 0xaf, 0xaa, 0xc2, 0x3d, 0x77, 0x00, 0x92,
- 0x20, 0xc3, 0xaf, 0x8b, 0xdd, 0x37, 0x5a, 0x24 },
- { 0x42, 0x5d, 0x4e, 0xbf, 0x1b, 0xde, 0x0b, 0xf8,
- 0xd1, 0xdb, 0xd3, 0x3d, 0x8d, 0x16, 0x34, 0xc4,
- 0xfa, 0xfe, 0xb6, 0xf8, 0x05, 0xf1, 0xcc, 0xb5,
- 0x34, 0xac, 0xb7, 0x2a, 0xed, 0xa2, 0xcd, 0x0a },
- { 0x44, 0x12, 0x63, 0x80, 0xa0, 0x73, 0xfe, 0xa1,
- 0xa2, 0x00, 0x4f, 0x71, 0x1d, 0xf2, 0xca, 0x47,
- 0xc2, 0xc4, 0xb4, 0xff, 0x64, 0x4e, 0x76, 0xaf,
- 0xbe, 0x27, 0x97, 0xc9, 0x63, 0x7c, 0x6a, 0xf9 },
- { 0x44, 0x25, 0xdd, 0xfb, 0xba, 0xfb, 0xe1, 0xaa,
- 0xce, 0x25, 0x85, 0x70, 0x48, 0x96, 0x9d, 0xc8,
- 0x9d, 0xf5, 0x97, 0x7b, 0xb2, 0xe3, 0x34, 0x7c,
- 0x9c, 0xeb, 0x0e, 0x5a, 0x7b, 0x68, 0xc5, 0x31 },
- { 0x45, 0x63, 0xcf, 0x13, 0xc2, 0x49, 0x2c, 0xaa,
- 0x92, 0xf5, 0x5b, 0x17, 0x26, 0x3a, 0xdd, 0x72,
- 0x04, 0xa8, 0x0f, 0xe6, 0x24, 0x0c, 0x4d, 0x63,
- 0xe8, 0x39, 0x59, 0x58, 0xf6, 0x94, 0xcd, 0x33 },
- { 0x45, 0xcb, 0x86, 0xca, 0x97, 0x52, 0x29, 0xb7,
- 0xd5, 0xda, 0xfc, 0x05, 0xeb, 0x0c, 0x53, 0x65,
- 0x82, 0x3a, 0x91, 0xa9, 0x8b, 0x7d, 0xbe, 0x81,
- 0xab, 0x5f, 0x17, 0x8b, 0x2d, 0xa4, 0xad, 0x9e },
- { 0x46, 0x9b, 0xd8, 0x04, 0xe9, 0x98, 0xae, 0x27,
- 0x9a, 0xc3, 0xfe, 0x1b, 0x52, 0x88, 0x46, 0xe7,
- 0xae, 0xc7, 0x6c, 0x56, 0xb8, 0x0b, 0x40, 0xf3,
- 0x24, 0x20, 0x8f, 0x5a, 0x9f, 0x64, 0x5c, 0xb5 },
- { 0x46, 0xcd, 0x08, 0x08, 0x8d, 0x36, 0x06, 0x2c,
- 0x56, 0x71, 0x09, 0x2c, 0x02, 0x76, 0x7a, 0x25,
- 0x0d, 0xe7, 0x0b, 0xf3, 0xe1, 0x53, 0x63, 0x69,
- 0x66, 0xe6, 0x6e, 0xc5, 0x7e, 0x8e, 0xe9, 0xf5 },
- { 0x47, 0x84, 0xf6, 0xcd, 0x59, 0x3d, 0x7b, 0x31,
- 0x2e, 0xb1, 0xf6, 0x19, 0xe1, 0x11, 0xdf, 0x3b,
- 0x48, 0x6d, 0x1b, 0xf8, 0x37, 0x15, 0xad, 0x8d,
- 0xab, 0xa5, 0x72, 0xaf, 0xb2, 0x61, 0xd5, 0xbe },
- { 0x47, 0x8c, 0xdd, 0x82, 0x3f, 0x81, 0x7d, 0x21,
- 0x8b, 0xf5, 0xdd, 0xa4, 0xc3, 0xe9, 0x9e, 0x7f,
- 0xa3, 0x10, 0x9b, 0x67, 0xbd, 0x0c, 0x9b, 0x1f,
- 0x40, 0x75, 0x96, 0x65, 0xb9, 0xec, 0x3f, 0xf2 },
- { 0x48, 0xc5, 0xd4, 0xff, 0x5d, 0x08, 0x4a, 0xc1,
- 0x95, 0xb1, 0xa6, 0xa2, 0x19, 0xf8, 0x1b, 0xbd,
- 0xf9, 0xd2, 0xe5, 0xc0, 0x70, 0xec, 0x97, 0xdf,
- 0x3c, 0xb0, 0xb7, 0x3e, 0xf4, 0x70, 0xdc, 0xe9 },
- { 0x49, 0xdc, 0xf8, 0xfa, 0x68, 0xe9, 0x2b, 0x5c,
- 0x21, 0xfe, 0xf9, 0x3d, 0x26, 0x0c, 0x24, 0x8c,
- 0xe3, 0xbe, 0x98, 0x62, 0x68, 0x68, 0xe7, 0x5a,
- 0x3f, 0x63, 0x34, 0xbb, 0x7d, 0xc1, 0x81, 0xec },
- { 0x4b, 0x1f, 0xc8, 0x2d, 0x24, 0x72, 0x92, 0x7a,
- 0xc1, 0x7c, 0x58, 0x43, 0x07, 0xcb, 0x96, 0xd6,
- 0xfd, 0xdb, 0x8d, 0x50, 0xa5, 0x29, 0x53, 0x07,
- 0xd3, 0x0c, 0x75, 0x88, 0x59, 0x6a, 0xd4, 0x0b },
- { 0x4b, 0x51, 0xfc, 0x11, 0x4b, 0xac, 0x8e, 0x2d,
- 0x2a, 0xf2, 0xae, 0x56, 0x84, 0x42, 0x9c, 0xca,
- 0xab, 0x21, 0x39, 0xc9, 0xb3, 0x51, 0xbf, 0x7e,
- 0x1b, 0x03, 0x0a, 0xe8, 0x62, 0x4a, 0xc1, 0x72 },
- { 0x4c, 0xd0, 0xd6, 0x7e, 0xcc, 0x3b, 0x01, 0xc8,
- 0xc2, 0x63, 0x4e, 0x7a, 0x73, 0x76, 0x12, 0xf6,
- 0x3a, 0x17, 0xff, 0x51, 0x0a, 0x77, 0xa8, 0x04,
- 0xbb, 0x33, 0x1b, 0x2b, 0xe5, 0x8d, 0xfe, 0x0c },
- { 0x4d, 0xcf, 0xeb, 0xdc, 0x15, 0x4b, 0x0c, 0x85,
- 0x46, 0x7f, 0x6f, 0x52, 0xad, 0x80, 0x4e, 0x19,
- 0x1d, 0x5b, 0xc8, 0x13, 0x51, 0x72, 0x0e, 0xc0,
- 0xd1, 0x9b, 0xd2, 0x5b, 0xf8, 0xf0, 0xa5, 0x53 },
- { 0x4f, 0x19, 0xdd, 0x12, 0x92, 0x4c, 0xe0, 0xc1,
- 0x4f, 0x82, 0xc0, 0x56, 0xc7, 0xd4, 0x2b, 0xac,
- 0x43, 0xd0, 0x13, 0x3a, 0xaf, 0x89, 0xc1, 0xef,
- 0xdc, 0xfa, 0x3c, 0x3e, 0x47, 0x09, 0x7d, 0x59 },
- { 0x4f, 0xfb, 0x59, 0x19, 0xbc, 0x38, 0x5c, 0x8c,
- 0x58, 0xe4, 0x62, 0xbf, 0x13, 0x22, 0x10, 0xd8,
- 0xb7, 0x86, 0x12, 0xd0, 0xc2, 0x2a, 0x6b, 0x6a,
- 0x68, 0x2e, 0x0b, 0x9e, 0x9c, 0x9f, 0x9a, 0x44 },
- { 0x50, 0xf4, 0x78, 0x1e, 0xb1, 0xc1, 0x46, 0x70,
- 0xd9, 0xa5, 0x52, 0xc3, 0x49, 0x5f, 0xb9, 0xf6,
- 0xae, 0x86, 0x8a, 0xb1, 0xc9, 0xd9, 0x83, 0xe0,
- 0x82, 0x68, 0x65, 0xa1, 0x02, 0xec, 0xa6, 0xd3 },
- { 0x51, 0x6a, 0x2f, 0x33, 0x60, 0xc7, 0x6f, 0xc4,
- 0x6a, 0xb2, 0x88, 0x7f, 0x88, 0xe8, 0xd0, 0x8e,
- 0xfb, 0xd8, 0x44, 0x5a, 0xa7, 0xbb, 0xd2, 0x29,
- 0xdf, 0xc7, 0x1a, 0x90, 0x4f, 0x55, 0xae, 0xb4 },
- { 0x52, 0x1f, 0x6c, 0x6a, 0x84, 0x36, 0x65, 0x79,
- 0xca, 0x2d, 0xea, 0xeb, 0x23, 0x15, 0xbf, 0x8e,
- 0x53, 0x1c, 0x9f, 0xa4, 0x7b, 0x89, 0x9d, 0xa2,
- 0x72, 0x16, 0xa9, 0x98, 0x82, 0x86, 0xaf, 0xe5 },
- { 0x52, 0xff, 0x8b, 0x6e, 0x98, 0xb0, 0x96, 0x19,
- 0x90, 0x03, 0xde, 0x97, 0xbc, 0xcf, 0xd2, 0xa7,
- 0xf1, 0xac, 0x57, 0xa8, 0x31, 0x35, 0xb9, 0x55,
- 0xff, 0x68, 0x63, 0x36, 0xa6, 0x91, 0xd5, 0xca },
- { 0x53, 0x79, 0x64, 0x58, 0xda, 0x97, 0xce, 0x36,
- 0x78, 0xf2, 0xd1, 0xd9, 0xb2, 0xa5, 0xb2, 0xfb,
- 0x30, 0x75, 0xea, 0xfa, 0xf6, 0xff, 0x04, 0x78,
- 0xb5, 0x72, 0xdd, 0xfd, 0x70, 0x99, 0xae, 0xe2 },
- { 0x53, 0x82, 0xd6, 0xba, 0xb5, 0x78, 0x51, 0xd9,
- 0xb5, 0x8c, 0x17, 0x54, 0x46, 0xbf, 0x2d, 0x1b,
- 0xb7, 0x86, 0xa5, 0x30, 0xfb, 0xf0, 0xae, 0xcd,
- 0x12, 0xea, 0xb8, 0xa9, 0xa5, 0xb4, 0x96, 0x60 },
- { 0x53, 0x9c, 0xa9, 0xe1, 0xf0, 0x6a, 0xf2, 0x10,
- 0x7f, 0x96, 0xbf, 0x4b, 0x7d, 0xd4, 0xce, 0xcd,
- 0x9e, 0xd1, 0x1a, 0x38, 0xd6, 0x70, 0x91, 0x69,
- 0x9c, 0x56, 0x26, 0xe2, 0x7a, 0x1f, 0x54, 0xa5 },
- { 0x55, 0x21, 0xf9, 0x63, 0x57, 0x81, 0x58, 0xb8,
- 0xd0, 0xe7, 0xc4, 0x91, 0xcd, 0xb8, 0x5c, 0x3d,
- 0xe9, 0xd5, 0x2e, 0xa5, 0x1f, 0xfc, 0xb0, 0x93,
- 0xd3, 0x12, 0x28, 0x11, 0x13, 0x14, 0x97, 0xeb },
- { 0x55, 0xd0, 0xeb, 0xe3, 0x2c, 0xba, 0x09, 0xf6,
- 0x58, 0x4d, 0x9e, 0x7b, 0x57, 0x92, 0xa4, 0x03,
- 0xc2, 0x1d, 0x39, 0xd6, 0xe1, 0xf5, 0xe8, 0xed,
- 0x37, 0xb9, 0x3f, 0xa6, 0x1d, 0x88, 0x35, 0x16 },
- { 0x58, 0x1a, 0xde, 0x64, 0x84, 0x95, 0xb4, 0xb1,
- 0x62, 0x9c, 0x3c, 0x7c, 0x78, 0xef, 0xbe, 0xf2,
- 0x75, 0x06, 0x56, 0x65, 0xb2, 0x41, 0x1c, 0x0e,
- 0x5f, 0xcf, 0xbc, 0x7e, 0xb4, 0xbe, 0x34, 0x0b },
- { 0x59, 0xc9, 0xe8, 0xdf, 0x03, 0x0b, 0x1c, 0xd5,
- 0x89, 0xa8, 0xb3, 0x4f, 0xe7, 0x42, 0x51, 0xea,
- 0xd5, 0xa5, 0xfb, 0xe9, 0xe6, 0x13, 0x67, 0xca,
- 0x76, 0xaf, 0xd9, 0xdd, 0xd9, 0xc6, 0xf1, 0x6f },
- { 0x59, 0xe9, 0xfa, 0x2f, 0xf0, 0x76, 0x89, 0x33,
- 0x28, 0x33, 0xc6, 0x40, 0xf5, 0x05, 0xfa, 0x24,
- 0x09, 0xeb, 0x88, 0x93, 0x32, 0x57, 0xc1, 0x93,
- 0xb0, 0x07, 0xd3, 0xa2, 0x89, 0x6a, 0x98, 0x50 },
- { 0x59, 0xee, 0x9b, 0x36, 0x80, 0xae, 0x20, 0x56,
- 0x83, 0x9c, 0x0b, 0xf6, 0x9e, 0xe6, 0x63, 0x26,
- 0x57, 0x16, 0xa8, 0xe2, 0x4c, 0xc6, 0x49, 0x95,
- 0xfb, 0xa6, 0xcb, 0x6f, 0x0c, 0x12, 0x39, 0xdc },
- { 0x5a, 0x84, 0xaf, 0xe6, 0x74, 0x05, 0xab, 0xe8,
- 0x4a, 0x0c, 0xd4, 0x2c, 0x2b, 0xa2, 0xe4, 0xc8,
- 0x8f, 0x35, 0xe0, 0xa5, 0x95, 0xe5, 0x69, 0xa3,
- 0xe1, 0x86, 0x69, 0x44, 0x40, 0x5b, 0xe7, 0x36 },
- { 0x5a, 0x8e, 0x86, 0x21, 0x2c, 0x06, 0x33, 0x94,
- 0x94, 0xf8, 0x5b, 0x5f, 0x85, 0x11, 0xdf, 0x00,
- 0x00, 0x23, 0x94, 0x07, 0x8f, 0xfc, 0x77, 0x4d,
- 0x43, 0x6f, 0x0d, 0x63, 0x86, 0xd7, 0xa6, 0xf7 },
- { 0x5a, 0xc0, 0x98, 0x2d, 0xa0, 0xc8, 0x3d, 0x0b,
- 0xa9, 0x38, 0x1a, 0x5c, 0xd8, 0x7b, 0x80, 0xd1,
- 0x10, 0xf2, 0x6e, 0xe8, 0x39, 0x27, 0x1b, 0xc2,
- 0x70, 0x60, 0x8f, 0xd1, 0x43, 0x7f, 0x55, 0xb0 },
- { 0x5c, 0x7f, 0xf0, 0x55, 0xc2, 0xfd, 0x03, 0x3f,
- 0x34, 0xc4, 0xc4, 0xf7, 0xc4, 0xfb, 0x7d, 0xda,
- 0xaa, 0xfb, 0x43, 0x56, 0xc5, 0x60, 0xc9, 0x9e,
- 0xdf, 0xf0, 0x74, 0xda, 0x04, 0xaf, 0x65, 0x7c },
- { 0x5c, 0xd2, 0x44, 0x6a, 0x8e, 0x4a, 0x0f, 0xa7,
- 0xe3, 0xcd, 0xf8, 0x00, 0x5d, 0xed, 0xce, 0xba,
- 0xe9, 0xe6, 0x81, 0x9a, 0x8a, 0x69, 0x87, 0x31,
- 0x55, 0x5b, 0x7d, 0xc9, 0xd0, 0xa2, 0x3f, 0xc0 },
- { 0x5c, 0xeb, 0xeb, 0xd8, 0x34, 0x01, 0xb7, 0x0b,
- 0xac, 0xb5, 0x4f, 0x66, 0xa9, 0xb7, 0x78, 0x55,
- 0x69, 0x6e, 0xce, 0x16, 0x7f, 0xe6, 0xc6, 0x0a,
- 0x05, 0x16, 0x8b, 0xe4, 0x39, 0x19, 0xc8, 0x0f },
- { 0x5f, 0x8b, 0x88, 0x8e, 0xe9, 0x6c, 0x0c, 0x0f,
- 0x5a, 0x91, 0x72, 0x90, 0xac, 0xa6, 0x5a, 0xfd,
- 0x6e, 0xbd, 0xae, 0x05, 0xa0, 0x2a, 0xaf, 0x04,
- 0x29, 0xe9, 0x72, 0xec, 0x01, 0x90, 0xec, 0xfc },
- { 0x62, 0x2e, 0xc3, 0xbe, 0x7c, 0xf5, 0xe4, 0xe6,
- 0x3f, 0x74, 0x18, 0x69, 0x28, 0x74, 0x40, 0x05,
- 0xcb, 0xb7, 0x8d, 0xf3, 0x06, 0xb8, 0x67, 0xc3,
- 0xfc, 0xad, 0x5e, 0x2b, 0xa7, 0x53, 0x96, 0x83 },
- { 0x62, 0x6f, 0x7e, 0xb4, 0xfd, 0x9b, 0x71, 0xff,
- 0xaa, 0x0c, 0x8e, 0xc9, 0x65, 0x54, 0x64, 0xe6,
- 0x5e, 0x7f, 0x96, 0xcf, 0xa3, 0x82, 0x73, 0x97,
- 0x41, 0x35, 0x66, 0xaa, 0x2c, 0xc1, 0xe5, 0x72 },
- { 0x63, 0x64, 0x15, 0x61, 0x77, 0xdc, 0xdf, 0x60,
- 0x4d, 0xf9, 0x1e, 0x31, 0x32, 0x2e, 0x57, 0x74,
- 0x69, 0x1e, 0x0c, 0x41, 0xfa, 0x0d, 0x2f, 0x25,
- 0x7a, 0xd7, 0xf9, 0xf0, 0x25, 0x98, 0x14, 0x45 },
- { 0x65, 0x66, 0x00, 0xa4, 0x5e, 0x45, 0x6a, 0xba,
- 0x5b, 0x00, 0x8d, 0x87, 0x91, 0x54, 0xb7, 0x69,
- 0x0d, 0x7f, 0x27, 0x31, 0x02, 0x09, 0x7d, 0x8f,
- 0xd8, 0xc3, 0xde, 0xab, 0x30, 0xd8, 0x4a, 0xb2 },
- { 0x65, 0xed, 0x61, 0xa8, 0x8c, 0x55, 0xef, 0xb0,
- 0x38, 0x07, 0x1a, 0xee, 0xde, 0xf8, 0xe1, 0x83,
- 0xe2, 0x37, 0x38, 0x46, 0x97, 0x26, 0xeb, 0x99,
- 0x68, 0x0c, 0xd2, 0x44, 0x72, 0x73, 0x6b, 0xec },
- { 0x66, 0x50, 0xb2, 0xea, 0x64, 0x4c, 0x3f, 0x4e,
- 0x8c, 0x9e, 0x3c, 0x46, 0xac, 0xea, 0xc4, 0x52,
- 0x33, 0xd8, 0x66, 0xe3, 0x98, 0xff, 0x90, 0xeb,
- 0x59, 0xb2, 0xc6, 0x25, 0x20, 0x82, 0xac, 0x04 },
- { 0x66, 0xbe, 0x7e, 0xa1, 0x13, 0x8b, 0xcb, 0xa4,
- 0xde, 0x0b, 0x41, 0x28, 0x5d, 0x9a, 0x13, 0x3f,
- 0xa7, 0xf5, 0x70, 0xa3, 0xc8, 0x13, 0x55, 0x79,
- 0xb8, 0x60, 0x19, 0x9d, 0x0a, 0x51, 0x45, 0x7c },
- { 0x69, 0x01, 0x4b, 0xbc, 0x84, 0x29, 0xd8, 0x5f,
- 0x41, 0xc2, 0x22, 0xd9, 0x7f, 0x7e, 0xd5, 0x35,
- 0xcf, 0x81, 0x23, 0x9a, 0xf2, 0x7a, 0xcc, 0x88,
- 0x70, 0xdc, 0xd4, 0x08, 0x34, 0x8b, 0x48, 0xba },
- { 0x69, 0x21, 0x1f, 0x36, 0x3a, 0x2d, 0xbe, 0x01,
- 0x5b, 0x31, 0xcb, 0xd9, 0xfc, 0x5e, 0x94, 0xc2,
- 0xf6, 0xf4, 0x3c, 0x58, 0xdb, 0xde, 0xe9, 0xe3,
- 0xe4, 0x6b, 0x19, 0xd7, 0x59, 0xbb, 0xb8, 0x81 },
- { 0x69, 0x75, 0x67, 0xbb, 0xac, 0x94, 0xee, 0xc3,
- 0xe6, 0xfa, 0x4a, 0x4e, 0x46, 0xfa, 0x51, 0x74,
- 0x05, 0xf3, 0x77, 0xc0, 0xde, 0xe3, 0xd4, 0x29,
- 0x91, 0x4e, 0x6b, 0x7e, 0xa0, 0x8c, 0xb1, 0xa6 },
- { 0x6a, 0xac, 0xc5, 0x09, 0x2f, 0x12, 0xbc, 0x94,
- 0xa0, 0xad, 0x0e, 0x9e, 0xf6, 0x36, 0x43, 0x7d,
- 0x36, 0x0d, 0xc7, 0xc9, 0xf1, 0x40, 0x44, 0x17,
- 0xa3, 0x36, 0x91, 0x94, 0x4e, 0x76, 0x31, 0x36 },
- { 0x6b, 0x4a, 0x8c, 0xb6, 0x07, 0xf5, 0x1c, 0x83,
- 0x0d, 0xe7, 0x20, 0xf4, 0xbb, 0xde, 0xdf, 0x49,
- 0x10, 0x15, 0x13, 0xdf, 0xd1, 0xdb, 0x0b, 0x0a,
- 0x97, 0xcc, 0x3f, 0xdd, 0x9a, 0x39, 0xc6, 0xe7 },
- { 0x6c, 0x8f, 0xd1, 0xe6, 0xe1, 0x1b, 0xaf, 0xa6,
- 0x17, 0x78, 0x13, 0xa0, 0x44, 0x40, 0xb1, 0xb9,
- 0x6a, 0x1c, 0xdb, 0x7c, 0x2d, 0x70, 0x3f, 0x55,
- 0xde, 0x85, 0x7c, 0x80, 0xa8, 0x9e, 0x73, 0x25 },
- { 0x6c, 0xc6, 0xdc, 0xda, 0x58, 0xc6, 0x1f, 0xb2,
- 0x86, 0x70, 0xd1, 0xc2, 0x01, 0x76, 0x57, 0xb0,
- 0xc5, 0xd6, 0x1a, 0x26, 0xc9, 0xcb, 0xd1, 0xea,
- 0x75, 0x5c, 0x68, 0x20, 0xb5, 0xf6, 0xd6, 0x7d },
- { 0x6d, 0x32, 0xf4, 0x93, 0x40, 0x56, 0xee, 0x17,
- 0x14, 0xca, 0x72, 0x70, 0x3f, 0x64, 0x46, 0x9b,
- 0x98, 0x58, 0xfc, 0x39, 0x96, 0x4b, 0x4c, 0x03,
- 0x93, 0xb3, 0x7d, 0xde, 0xab, 0x8b, 0x19, 0x75 },
- { 0x6e, 0x1a, 0x88, 0x63, 0xf2, 0x93, 0x4b, 0x39,
- 0x01, 0x23, 0x7e, 0x84, 0xd0, 0x76, 0x27, 0x04,
- 0x23, 0x06, 0x78, 0x7f, 0x2d, 0xe0, 0x66, 0x30,
- 0xbd, 0x37, 0xd8, 0x03, 0x94, 0x35, 0xbf, 0xca },
- { 0x6e, 0x99, 0x8d, 0xdd, 0xf2, 0x93, 0x9b, 0xfe,
- 0x8c, 0xc5, 0x2a, 0x48, 0x0a, 0xc0, 0x6d, 0x69,
- 0x71, 0xc5, 0xa3, 0xda, 0x97, 0xcf, 0x3e, 0xf0,
- 0x1a, 0xf2, 0x9d, 0x74, 0x72, 0x62, 0x31, 0xe2 },
- { 0x6f, 0x3b, 0xb3, 0x4b, 0x5d, 0x32, 0x91, 0xdf,
- 0xb3, 0xe4, 0x12, 0x71, 0xa1, 0xd7, 0x30, 0xcd,
- 0xbc, 0xff, 0xc1, 0x0b, 0x68, 0x05, 0x9d, 0xcc,
- 0xd3, 0x1c, 0x47, 0x4b, 0xb7, 0x44, 0x16, 0xe5 },
- { 0x6f, 0xbd, 0xcd, 0xf1, 0xb4, 0x37, 0x9f, 0xc4,
- 0x73, 0xab, 0x5e, 0xea, 0x4e, 0xc2, 0xf4, 0x84,
- 0xce, 0x91, 0xd1, 0x0e, 0x31, 0x34, 0x5f, 0x15,
- 0xa7, 0x6a, 0x84, 0x85, 0xb8, 0xff, 0xfb, 0x7e },
- { 0x70, 0xb8, 0xec, 0xd5, 0x62, 0xec, 0x3d, 0x9f,
- 0x48, 0x64, 0x75, 0x2a, 0x3a, 0x8c, 0x54, 0x39,
- 0x93, 0xb4, 0x38, 0x72, 0x8f, 0xe2, 0x71, 0x81,
- 0xf4, 0xc0, 0x8d, 0xe6, 0xa0, 0xd8, 0xb7, 0x9a },
- { 0x72, 0x1b, 0x1f, 0x92, 0x9d, 0xa7, 0xea, 0xf8,
- 0x96, 0x24, 0x64, 0x7b, 0xa3, 0xcc, 0x4e, 0x1e,
- 0xd1, 0x57, 0x54, 0xab, 0x83, 0x6e, 0x33, 0x58,
- 0xb0, 0x35, 0xa1, 0xf2, 0x27, 0x4a, 0x43, 0xbe },
- { 0x72, 0x81, 0xda, 0x0d, 0x8c, 0xe9, 0xd5, 0x3e,
- 0xa3, 0xd1, 0xf5, 0x93, 0x5c, 0x58, 0x21, 0xea,
- 0x8d, 0x9a, 0xf1, 0xce, 0x0b, 0xca, 0xf8, 0x82,
- 0x5d, 0x78, 0x3f, 0x37, 0xea, 0xc3, 0x4f, 0x40 },
- { 0x72, 0xe7, 0x49, 0x87, 0x21, 0x0c, 0x7e, 0xf6,
- 0x67, 0x46, 0xe4, 0x9a, 0x96, 0xdf, 0x55, 0xcc,
- 0x6f, 0xad, 0xf7, 0xa6, 0x31, 0xc7, 0xae, 0x3f,
- 0x3e, 0x9e, 0x18, 0x72, 0x3d, 0xe5, 0x2a, 0x6e },
- { 0x73, 0x3b, 0x42, 0x24, 0x25, 0x8d, 0xee, 0x07,
- 0x0e, 0xdf, 0xa3, 0x41, 0x1f, 0xbc, 0x9b, 0xad,
- 0x31, 0x65, 0xbe, 0x66, 0x0f, 0x34, 0x0a, 0xa2,
- 0x30, 0x8a, 0x5a, 0x33, 0x23, 0xfa, 0xbf, 0xa7 },
- { 0x74, 0x8e, 0xbb, 0x72, 0xd1, 0x02, 0x04, 0xf4,
- 0x04, 0x10, 0xbe, 0x70, 0x80, 0xbf, 0xe7, 0xee,
- 0x63, 0x1f, 0xc0, 0x4d, 0x1f, 0xdb, 0x50, 0x72,
- 0x04, 0x4b, 0xfa, 0x55, 0x7a, 0xdf, 0x6e, 0x5a },
- { 0x74, 0xe2, 0xcc, 0xcf, 0x62, 0xd5, 0xb9, 0xf9,
- 0x00, 0xb4, 0x14, 0x73, 0xca, 0x44, 0xe6, 0x87,
- 0x96, 0x38, 0x74, 0x3d, 0x8f, 0xee, 0x66, 0xee,
- 0x71, 0x8c, 0x18, 0xd8, 0xf1, 0x12, 0x15, 0xd1 },
- { 0x76, 0x98, 0x67, 0x60, 0xac, 0xfe, 0x55, 0x59,
- 0xa2, 0xa2, 0xab, 0x2a, 0x4e, 0x85, 0x49, 0x83,
- 0xc5, 0xfd, 0xe6, 0x73, 0xce, 0x8e, 0xb1, 0x71,
- 0x23, 0x49, 0x48, 0x64, 0x86, 0x7a, 0x98, 0xb1 },
- { 0x78, 0x0c, 0x33, 0xfe, 0x95, 0x4c, 0xc4, 0xdb,
- 0x39, 0x04, 0xd7, 0x6a, 0x68, 0x58, 0xbc, 0xd1,
- 0x01, 0x7f, 0x52, 0xda, 0x59, 0x9d, 0x36, 0xda,
- 0xe6, 0x66, 0xc0, 0x4e, 0x41, 0xaf, 0x8d, 0xcd },
- { 0x78, 0xc9, 0x30, 0x40, 0x5a, 0x72, 0x0d, 0x9f,
- 0x00, 0x66, 0xdd, 0x88, 0xa2, 0xa8, 0xda, 0xfb,
- 0xbe, 0x6c, 0xd6, 0x5d, 0x54, 0xb7, 0x76, 0x06,
- 0x42, 0x1b, 0x45, 0x43, 0x8c, 0x65, 0x8a, 0xd4 },
- { 0x79, 0x8f, 0x83, 0xb1, 0xc4, 0xc6, 0x5c, 0x4d,
- 0x5d, 0xea, 0x13, 0x03, 0x53, 0x53, 0xd8, 0xed,
- 0xe5, 0xd7, 0x1d, 0x99, 0x47, 0xf4, 0x34, 0xfd,
- 0xea, 0x0d, 0xbc, 0x1e, 0xc8, 0x2f, 0x45, 0x35 },
- { 0x7b, 0xfe, 0x47, 0xae, 0xba, 0x8b, 0x0a, 0x3a,
- 0x94, 0x5a, 0x88, 0xd8, 0xef, 0x18, 0x91, 0xc9,
- 0x89, 0x97, 0x8a, 0xbf, 0x12, 0x2e, 0xc5, 0xe0,
- 0x51, 0x4b, 0xe3, 0x6c, 0x3a, 0x7f, 0x22, 0x9b },
- { 0x7d, 0x20, 0xc7, 0xa9, 0x27, 0x26, 0x2b, 0xe7,
- 0x38, 0xd2, 0x58, 0xd0, 0xfd, 0x97, 0x6e, 0x9a,
- 0xf3, 0x6e, 0xf7, 0x99, 0x5f, 0x05, 0xe2, 0x87,
- 0x6a, 0x29, 0xae, 0xbc, 0x3a, 0x24, 0xaa, 0xce },
- { 0x7e, 0x2e, 0xdb, 0x9d, 0x38, 0xf9, 0x29, 0x3c,
- 0xdd, 0xd6, 0x03, 0xb1, 0x75, 0xc9, 0xb2, 0x05,
- 0xac, 0x0b, 0x55, 0x3a, 0x4b, 0xf5, 0xfb, 0x08,
- 0xc2, 0x46, 0xec, 0xf9, 0xc8, 0x49, 0xdb, 0x28 },
- { 0x7f, 0x95, 0x9b, 0x06, 0x34, 0xda, 0x94, 0xfa,
- 0xca, 0xda, 0xb0, 0x21, 0xcf, 0x94, 0x20, 0x78,
- 0x16, 0x00, 0x36, 0x13, 0xef, 0x09, 0xeb, 0x54,
- 0xf6, 0x48, 0x60, 0x50, 0x08, 0x19, 0x02, 0x75 },
- { 0x7f, 0x9a, 0x69, 0xcf, 0xa2, 0xf5, 0x0c, 0x13,
- 0xe1, 0xb7, 0x11, 0xdd, 0x6b, 0x14, 0x69, 0x2b,
- 0xdb, 0x77, 0xd9, 0xff, 0xd8, 0xc1, 0x10, 0xae,
- 0x5d, 0x05, 0xa4, 0xcb, 0x73, 0x12, 0x37, 0x48 },
- { 0x7f, 0xcc, 0xa8, 0xb5, 0xf5, 0xe3, 0x3b, 0xca,
- 0x6d, 0xe0, 0x9c, 0x14, 0xaf, 0xbb, 0xe0, 0xc3,
- 0x41, 0x21, 0xac, 0xbb, 0x22, 0x22, 0x9f, 0x44,
- 0xee, 0x5c, 0x3f, 0x4d, 0xde, 0x73, 0x50, 0x55 },
- { 0x80, 0x20, 0x56, 0xe1, 0xdb, 0x9d, 0x9b, 0x73,
- 0x21, 0xd1, 0xff, 0xbb, 0xe1, 0x2f, 0x5c, 0xbe,
- 0xde, 0xc3, 0x6d, 0x0b, 0x5e, 0xc2, 0xa4, 0xe1,
- 0x8d, 0x99, 0x54, 0x36, 0x4c, 0xec, 0x81, 0x29 },
- { 0x80, 0x97, 0x63, 0x4c, 0xe3, 0x3d, 0x41, 0x53,
- 0x3d, 0x41, 0x5d, 0xaf, 0xdb, 0x8b, 0xa1, 0x91,
- 0xc0, 0x30, 0x52, 0xac, 0x8b, 0xaa, 0x25, 0x54,
- 0x34, 0x77, 0x3a, 0x16, 0x4b, 0x91, 0x1d, 0x6e },
- { 0x80, 0xd0, 0x17, 0x09, 0x34, 0xd2, 0x2a, 0xea,
- 0x73, 0x3f, 0x11, 0x5e, 0x52, 0x42, 0xc6, 0xb8,
- 0x6d, 0x7f, 0xcf, 0xb4, 0x90, 0x4e, 0x65, 0xb7,
- 0xb7, 0xb9, 0x07, 0xf2, 0xca, 0x94, 0xed, 0x71 },
- { 0x81, 0x1d, 0xf2, 0xf4, 0x73, 0x6f, 0x85, 0x62,
- 0xe2, 0x02, 0xfd, 0x00, 0x75, 0x32, 0xf1, 0xde,
- 0x40, 0x17, 0x86, 0x1e, 0xfa, 0xbe, 0x67, 0x34,
- 0x20, 0xc2, 0x7f, 0x2e, 0x2a, 0x33, 0xfa, 0xc1 },
- { 0x81, 0x1e, 0x37, 0x86, 0x37, 0xb1, 0xd2, 0xcb,
- 0xb1, 0x89, 0xaf, 0xd6, 0x74, 0x95, 0xfe, 0x8a,
- 0xb9, 0xd8, 0x3a, 0x74, 0x2e, 0x35, 0x8c, 0xbb,
- 0xdb, 0xd1, 0x54, 0x98, 0xbf, 0x9c, 0x7b, 0x56 },
- { 0x81, 0xa0, 0xf1, 0xd0, 0x29, 0x46, 0x8e, 0xe8,
- 0x66, 0x36, 0x4a, 0x19, 0x8a, 0x26, 0x08, 0x58,
- 0x30, 0xc2, 0xa4, 0x16, 0xe4, 0x9e, 0x22, 0x4c,
- 0xe8, 0x09, 0x66, 0xfc, 0xc4, 0x99, 0xd6, 0x36 },
- { 0x82, 0x56, 0x8b, 0x3b, 0xb3, 0xc6, 0x55, 0xd7,
- 0xf2, 0x2d, 0x8c, 0x97, 0xa5, 0x66, 0x9c, 0xc8,
- 0x34, 0xa2, 0xdd, 0x7c, 0xda, 0xe7, 0x5a, 0x26,
- 0x45, 0x59, 0x55, 0x16, 0x46, 0x55, 0x8e, 0x14 },
- { 0x82, 0x7c, 0x8c, 0x80, 0x11, 0x1f, 0xf2, 0x21,
- 0xc3, 0xeb, 0x1e, 0xf5, 0xc0, 0xd5, 0xd4, 0x34,
- 0x48, 0x31, 0x86, 0xe2, 0x09, 0x00, 0x75, 0x63,
- 0x15, 0x8e, 0x9e, 0x76, 0xd2, 0x79, 0x0f, 0x1c },
- { 0x82, 0x92, 0x67, 0xc5, 0xad, 0x70, 0xe5, 0x45,
- 0x18, 0x02, 0x3a, 0xb7, 0x85, 0xfa, 0x3c, 0xde,
- 0xd6, 0x6f, 0x42, 0x5d, 0xe1, 0xf3, 0x2f, 0xcd,
- 0x72, 0x1b, 0x49, 0x46, 0x3a, 0x5a, 0x5f, 0x5b },
- { 0x83, 0x34, 0xea, 0xb8, 0x1c, 0x60, 0x4e, 0x99,
- 0xd5, 0x40, 0x51, 0x3e, 0xf2, 0xe3, 0x7a, 0xba,
- 0x71, 0x4f, 0x07, 0xb2, 0xba, 0x01, 0x0a, 0xd7,
- 0x1d, 0xc4, 0xe1, 0x1a, 0x92, 0x18, 0xc1, 0x8c },
- { 0x83, 0x54, 0x7a, 0xca, 0x3c, 0xed, 0x73, 0xdf,
- 0x99, 0x14, 0xf3, 0x15, 0x60, 0x74, 0x63, 0x79,
- 0x29, 0x4c, 0x76, 0x0e, 0xf9, 0xa8, 0xb7, 0x6e,
- 0x00, 0x06, 0x46, 0xc7, 0x39, 0x07, 0x21, 0x65 },
- { 0x83, 0x89, 0xc8, 0x79, 0xb6, 0x3b, 0x82, 0x9d,
- 0x2d, 0x39, 0xa8, 0xcf, 0xb7, 0x87, 0xe7, 0x72,
- 0x77, 0xd5, 0xcf, 0xa3, 0xe3, 0x6f, 0xda, 0xcb,
- 0xab, 0x4d, 0x18, 0xb2, 0xb0, 0x4e, 0x32, 0x94 },
- { 0x84, 0x23, 0xb3, 0xf1, 0xcc, 0x85, 0x2b, 0x49,
- 0xcf, 0x81, 0xb7, 0xd5, 0xff, 0x51, 0xa7, 0xa5,
- 0x6a, 0x84, 0x78, 0x3a, 0x2d, 0xf7, 0x43, 0x61,
- 0xff, 0x2e, 0xee, 0x0f, 0x92, 0x12, 0xc1, 0x59 },
- { 0x84, 0x7b, 0x5f, 0x1e, 0xeb, 0x2a, 0x44, 0x13,
- 0xc8, 0xfa, 0x37, 0x98, 0x21, 0x97, 0x37, 0xe1,
- 0x92, 0xba, 0x72, 0x72, 0xa1, 0x08, 0xb7, 0x17,
- 0x28, 0xa8, 0xd1, 0x65, 0x17, 0xf6, 0x1e, 0x9d },
- { 0x85, 0x31, 0xb2, 0xbf, 0xc5, 0x45, 0x79, 0xe8,
- 0xf1, 0x8f, 0x27, 0xb2, 0xe6, 0xec, 0xc0, 0xf8,
- 0x90, 0x64, 0xee, 0x86, 0x87, 0x0e, 0xcc, 0x8b,
- 0xbe, 0x0c, 0xe6, 0x86, 0xec, 0xda, 0x2c, 0x17 },
- { 0x85, 0x76, 0x0f, 0x59, 0x51, 0x90, 0xe9, 0xb4,
- 0x67, 0x8b, 0xbf, 0x44, 0xef, 0xb5, 0xcf, 0x8f,
- 0x6b, 0x19, 0x37, 0xa9, 0xb8, 0x6b, 0x31, 0xb7,
- 0x51, 0xbe, 0xcf, 0x72, 0x18, 0x03, 0xb0, 0x1c },
- { 0x85, 0xf0, 0x79, 0x36, 0xb4, 0x29, 0x1f, 0x36,
- 0xd9, 0xb7, 0x5f, 0x42, 0xe8, 0xb7, 0xee, 0x8a,
- 0x64, 0xe6, 0x32, 0xa1, 0x18, 0x11, 0x65, 0xfe,
- 0x72, 0xb4, 0x88, 0x23, 0xc3, 0xd9, 0x9d, 0x9d },
- { 0x86, 0x12, 0x9f, 0xe7, 0x61, 0x99, 0x4d, 0x7b,
- 0x64, 0xe4, 0x02, 0x85, 0x8f, 0x88, 0xc5, 0x2b,
- 0x3e, 0xb9, 0xc0, 0x71, 0xff, 0xbe, 0x80, 0x02,
- 0x80, 0xac, 0x8c, 0x0c, 0x6f, 0x79, 0xe7, 0xa6 },
- { 0x86, 0x19, 0x6b, 0x0f, 0xd3, 0x0f, 0x8f, 0x57,
- 0x56, 0x98, 0xb5, 0xee, 0xf2, 0x69, 0xd0, 0x69,
- 0x2f, 0x88, 0xad, 0xea, 0xc4, 0x83, 0x6a, 0x62,
- 0x67, 0xab, 0xc8, 0x36, 0x23, 0x34, 0x00, 0x86 },
- { 0x86, 0xcf, 0xec, 0xbe, 0x82, 0xba, 0xdb, 0x93,
- 0x14, 0x75, 0xf1, 0x9e, 0xcd, 0x6e, 0xa6, 0x7d,
- 0x59, 0xc2, 0xc7, 0x00, 0x78, 0xb6, 0xcc, 0x56,
- 0xbf, 0xdc, 0x27, 0x55, 0x47, 0x67, 0xf2, 0x3f },
- { 0x86, 0xd1, 0x8b, 0xcd, 0xde, 0x16, 0x45, 0x42,
- 0x48, 0x6e, 0x56, 0x44, 0x2c, 0xe1, 0xb8, 0x8b,
- 0x1a, 0x10, 0x73, 0x7c, 0xbd, 0x5e, 0xa4, 0xaa,
- 0xb8, 0xd5, 0xb8, 0xaf, 0x51, 0xf5, 0x29, 0x09 },
- { 0x87, 0x5f, 0x57, 0x42, 0x4c, 0x90, 0x2b, 0x24,
- 0xe8, 0x1c, 0x27, 0xd1, 0xca, 0xf2, 0x74, 0xb1,
- 0x7d, 0x72, 0x0d, 0xf8, 0x07, 0x8b, 0x6f, 0x2a,
- 0x5c, 0x3b, 0xb8, 0xd8, 0xdf, 0xf0, 0x55, 0x00 },
- { 0x88, 0x8d, 0x6d, 0x77, 0xd8, 0x1c, 0x62, 0x91,
- 0xcb, 0x84, 0xd9, 0xd6, 0x56, 0x27, 0x82, 0xfd,
- 0x2e, 0xb3, 0x42, 0x5d, 0x49, 0x1e, 0x68, 0x74,
- 0x20, 0x28, 0x4b, 0x76, 0xa1, 0xde, 0xbf, 0xab },
- { 0x89, 0xaf, 0x0e, 0x54, 0xc7, 0x62, 0x77, 0x86,
- 0x93, 0x52, 0x9d, 0x0a, 0x95, 0x0b, 0x78, 0x33,
- 0xf5, 0xea, 0xba, 0xf3, 0x42, 0x79, 0x72, 0x60,
- 0x7f, 0xb2, 0xc7, 0x0c, 0x96, 0xa3, 0x21, 0x61 },
- { 0x89, 0xda, 0xc7, 0x89, 0x6b, 0x46, 0xf2, 0xfc,
- 0x8b, 0xea, 0x62, 0x11, 0xff, 0x98, 0xb6, 0x1f,
- 0xaa, 0x15, 0x7b, 0xa8, 0xc4, 0xad, 0x6f, 0xd1,
- 0x75, 0x92, 0x75, 0xce, 0x39, 0x41, 0xc3, 0x28 },
- { 0x8a, 0x09, 0x85, 0xbf, 0x86, 0xe8, 0xc9, 0xb9,
- 0x17, 0xec, 0x84, 0xda, 0x2a, 0x56, 0x73, 0x1e,
- 0x75, 0x2a, 0xa0, 0xdc, 0x52, 0x87, 0xc2, 0xbf,
- 0x39, 0x51, 0x0b, 0xb3, 0xf0, 0xf2, 0x0a, 0xd1 },
- { 0x8a, 0xaf, 0x36, 0x3c, 0xc9, 0xd8, 0x44, 0x15,
- 0xa7, 0xeb, 0x0d, 0x72, 0xda, 0x08, 0xb3, 0x58,
- 0x80, 0x68, 0x55, 0x9c, 0xb0, 0xa9, 0xae, 0x92,
- 0xb8, 0xf4, 0x60, 0x2e, 0xda, 0x23, 0x82, 0xaa },
- { 0x8a, 0xb2, 0x77, 0x62, 0xf4, 0xa2, 0xe3, 0x11,
- 0x22, 0x04, 0x96, 0x98, 0x39, 0x99, 0xc8, 0xc4,
- 0x60, 0x96, 0x3d, 0xfc, 0x1b, 0x88, 0x51, 0x11,
- 0x1d, 0xa4, 0x1d, 0x3f, 0x3b, 0x0a, 0x6e, 0x94 },
- { 0x8a, 0xd1, 0xd5, 0x48, 0x95, 0x27, 0xb5, 0x28,
- 0xe5, 0xb5, 0xd6, 0xa5, 0x95, 0x78, 0x87, 0x08,
- 0x88, 0x8a, 0x3f, 0xb1, 0x9f, 0x2c, 0x7c, 0x8b,
- 0x38, 0x07, 0x0e, 0x1f, 0x38, 0x98, 0x96, 0x8b },
- { 0x8a, 0xdb, 0x49, 0xd4, 0x15, 0x53, 0x56, 0x70,
- 0x5b, 0x64, 0x42, 0x6a, 0x99, 0x0f, 0x58, 0xb3,
- 0xa0, 0x71, 0xef, 0x78, 0x2e, 0x6c, 0x09, 0x53,
- 0x07, 0xd7, 0x74, 0x74, 0xd5, 0xb5, 0x7a, 0x62 },
- { 0x8b, 0x3a, 0x10, 0x35, 0xc3, 0xfd, 0xf3, 0x45,
- 0xfb, 0x70, 0x80, 0x44, 0x83, 0xa5, 0x04, 0x49,
- 0xa3, 0xd7, 0x60, 0xc6, 0xba, 0x48, 0xf5, 0xb8,
- 0x2d, 0x6b, 0xb2, 0x62, 0xed, 0x9d, 0xe3, 0x73 },
- { 0x8b, 0x3a, 0x75, 0xcb, 0xc3, 0x62, 0xd2, 0x35,
- 0x57, 0x0e, 0x5d, 0xe7, 0x04, 0x29, 0x38, 0x70,
- 0x8a, 0x1b, 0x0f, 0xce, 0xb4, 0x59, 0x86, 0x2a,
- 0x38, 0x67, 0xb7, 0x34, 0xcd, 0xcb, 0x97, 0x94 },
- { 0x8c, 0x3e, 0x7c, 0x1d, 0xcc, 0x7d, 0xd8, 0xe7,
- 0xd8, 0xbf, 0x7b, 0x5b, 0x3a, 0xe5, 0xe0, 0x27,
- 0x2e, 0x81, 0x1a, 0xb9, 0xf3, 0xc3, 0xc5, 0x38,
- 0xe5, 0x74, 0x71, 0x77, 0xe6, 0x2d, 0x62, 0x92 },
- { 0x8c, 0x7c, 0x65, 0x7b, 0xda, 0x13, 0xca, 0x62,
- 0xf2, 0x9a, 0x65, 0xc6, 0xd5, 0x19, 0x3a, 0x93,
- 0xcf, 0x6c, 0x58, 0x77, 0x18, 0xad, 0xca, 0x67,
- 0x15, 0x8e, 0x97, 0xd3, 0x6a, 0x62, 0x3e, 0xca },
- { 0x8c, 0xa6, 0x79, 0x62, 0xc4, 0xa8, 0x09, 0x13,
- 0x33, 0xf2, 0x4e, 0xfd, 0x60, 0xee, 0x70, 0xcf,
- 0xed, 0xdb, 0xd6, 0x41, 0x59, 0x04, 0x70, 0x9e,
- 0x78, 0x5c, 0x33, 0x1b, 0x1e, 0xf5, 0x8f, 0x8e },
- { 0x8e, 0x18, 0xfd, 0xbd, 0xb0, 0x08, 0x16, 0x00,
- 0x35, 0xfa, 0xf5, 0x01, 0x5b, 0xe7, 0xda, 0xf4,
- 0x63, 0xb5, 0xc4, 0x14, 0xea, 0xbc, 0x8b, 0x89,
- 0xf3, 0xdb, 0xa2, 0x05, 0xab, 0x09, 0xa6, 0x43 },
- { 0x8f, 0x10, 0x10, 0x47, 0x93, 0xe8, 0x55, 0x42,
- 0xbc, 0x06, 0x04, 0xd6, 0xcf, 0x21, 0x5f, 0x78,
- 0x80, 0xbd, 0x6a, 0x4d, 0xd0, 0xfd, 0xf1, 0xe7,
- 0xa5, 0xb9, 0xca, 0x12, 0x46, 0xf5, 0xc4, 0x09 },
- { 0x8f, 0x71, 0x27, 0x76, 0x2e, 0xe7, 0x51, 0x69,
- 0xbd, 0xc3, 0x5b, 0x04, 0xa7, 0x28, 0xe9, 0xd3,
- 0x1b, 0x7e, 0x4d, 0x37, 0x89, 0xaa, 0x2c, 0x46,
- 0xd8, 0xa3, 0x1b, 0x3d, 0xfa, 0x81, 0xa9, 0x7e },
- { 0x8f, 0x94, 0x15, 0x92, 0x6f, 0x40, 0x49, 0xea,
- 0x41, 0x8a, 0x30, 0x7c, 0x76, 0x36, 0xe4, 0x9b,
- 0x14, 0x4f, 0xa5, 0x3e, 0x52, 0xe1, 0x04, 0x15,
- 0x5f, 0x58, 0x03, 0x5e, 0x45, 0x41, 0xcd, 0x6e },
- { 0x90, 0xe2, 0x51, 0x86, 0x7f, 0x6b, 0x0c, 0x14,
- 0xbd, 0x9b, 0x51, 0x0c, 0xfd, 0xa8, 0x48, 0x49,
- 0x72, 0xfd, 0xf0, 0xe0, 0x6d, 0xc1, 0x1f, 0x5d,
- 0x1d, 0x59, 0x0b, 0xe3, 0xfc, 0x38, 0xdf, 0xf0 },
- { 0x91, 0x90, 0xf8, 0x25, 0x51, 0x0c, 0x65, 0x98,
- 0xe1, 0x9d, 0x17, 0xdb, 0xbe, 0x6e, 0x7c, 0x82,
- 0x31, 0x86, 0x9c, 0xa7, 0xf6, 0xe3, 0x07, 0xa2,
- 0xc2, 0xcc, 0x54, 0x77, 0x8d, 0x4a, 0x89, 0xb3 },
- { 0x92, 0x3f, 0x0f, 0x8c, 0x40, 0x5a, 0x02, 0xe6,
- 0x82, 0xc4, 0xb4, 0x66, 0x5a, 0x7e, 0xe7, 0x16,
- 0xaa, 0x57, 0xe0, 0xa5, 0x86, 0xc2, 0x4a, 0x16,
- 0x5a, 0xad, 0x7e, 0x5b, 0xda, 0x22, 0x78, 0x24 },
- { 0x92, 0x71, 0x44, 0x12, 0x1c, 0x23, 0x63, 0x57,
- 0x07, 0xe9, 0x40, 0x7f, 0x7f, 0xff, 0x6a, 0x64,
- 0x63, 0x5d, 0x7c, 0xe9, 0x06, 0x66, 0xd4, 0x29,
- 0x94, 0x09, 0x7a, 0xf4, 0x0c, 0x31, 0x36, 0xfb },
- { 0x94, 0xdc, 0x80, 0x07, 0x49, 0x1d, 0xa8, 0xbf,
- 0xb7, 0x39, 0x14, 0xad, 0xce, 0xf7, 0x1a, 0x12,
- 0x41, 0x58, 0xba, 0xd1, 0x7b, 0xa8, 0x8f, 0xa9,
- 0x46, 0x57, 0x9b, 0xbc, 0x2d, 0x64, 0x97, 0x8d },
- { 0x95, 0x68, 0x33, 0xae, 0xe6, 0x61, 0x19, 0x26,
- 0xe9, 0x52, 0x72, 0xa1, 0xf5, 0x88, 0xf9, 0x2a,
- 0xf5, 0x2c, 0xae, 0x70, 0x7a, 0xcd, 0xcc, 0x82,
- 0x63, 0x99, 0x7b, 0xfa, 0x8c, 0x71, 0x9c, 0xa8 },
- { 0x95, 0x89, 0xda, 0xc9, 0xec, 0xe7, 0x6d, 0xf5,
- 0x72, 0x01, 0x96, 0xdc, 0x58, 0x6d, 0x17, 0x9d,
- 0x73, 0x5d, 0xf7, 0x17, 0x92, 0x6c, 0x06, 0x1e,
- 0xa7, 0x0c, 0x40, 0x85, 0x64, 0x8f, 0xf3, 0x12 },
- { 0x96, 0xa4, 0x59, 0x90, 0xfc, 0xd0, 0x1c, 0x9c,
- 0x2a, 0xf0, 0x64, 0x5f, 0x87, 0xb9, 0x69, 0x8b,
- 0x05, 0xaf, 0xe6, 0x94, 0x32, 0xeb, 0x57, 0x01,
- 0x08, 0x20, 0x13, 0xba, 0xc5, 0xb0, 0x55, 0x60 },
- { 0x96, 0xeb, 0x44, 0xaa, 0x6a, 0x20, 0x49, 0xe6,
- 0xba, 0xff, 0xe6, 0xb5, 0x21, 0xc4, 0xad, 0x8c,
- 0x58, 0x77, 0x26, 0xca, 0xa0, 0x12, 0xe8, 0xfb,
- 0x8e, 0x8e, 0x21, 0x89, 0x77, 0xbf, 0x1d, 0xf6 },
- { 0x97, 0x4f, 0x51, 0xa6, 0x04, 0x68, 0x48, 0xfa,
- 0xa7, 0xb3, 0x3f, 0xd2, 0x39, 0x13, 0x86, 0x42,
- 0x8b, 0xd5, 0x24, 0xea, 0xeb, 0xa8, 0x01, 0x4e,
- 0x6d, 0x1f, 0xe2, 0x54, 0x38, 0x3f, 0x41, 0x79 },
- { 0x97, 0x8d, 0x6f, 0x1e, 0x9a, 0xa3, 0xa3, 0xce,
- 0xb1, 0xad, 0xa6, 0x09, 0xe2, 0x00, 0x95, 0xfb,
- 0xc3, 0x3a, 0x6b, 0xbc, 0x6a, 0x21, 0xd8, 0x0a,
- 0x4e, 0xcb, 0x27, 0x3c, 0x60, 0xac, 0x2a, 0xc7 },
- { 0x99, 0xa5, 0x5f, 0x76, 0xcb, 0xea, 0x0f, 0x3e,
- 0x60, 0x71, 0xd3, 0x82, 0x18, 0x1a, 0xf6, 0xcb,
- 0x25, 0xbd, 0xc5, 0x87, 0x5e, 0x29, 0xf0, 0xf4,
- 0xd7, 0x19, 0xa9, 0xd3, 0x5b, 0x5b, 0xd6, 0xbf },
- { 0x9a, 0x4b, 0x49, 0x93, 0xb4, 0xed, 0x8c, 0x27,
- 0xe7, 0x7f, 0x3c, 0x8a, 0xaf, 0xdb, 0xdc, 0x11,
- 0x1a, 0x36, 0xb7, 0x3c, 0xca, 0xdb, 0x87, 0x04,
- 0x98, 0x25, 0x00, 0xd1, 0xb0, 0xf1, 0x09, 0xf2 },
- { 0x9a, 0xae, 0x9d, 0x45, 0xaa, 0x04, 0x03, 0x06,
- 0x4b, 0xc5, 0xa7, 0x4d, 0xd0, 0x32, 0x5d, 0xa4,
- 0x1e, 0x12, 0xcf, 0x58, 0x6c, 0x46, 0x2e, 0xe0,
- 0x6c, 0x2b, 0xb4, 0x56, 0xf8, 0x44, 0x1c, 0x4f },
- { 0x9b, 0x8f, 0x9f, 0xc4, 0xaf, 0xa7, 0x04, 0x0d,
- 0x4e, 0x59, 0x4d, 0x66, 0x7c, 0x44, 0x44, 0xb5,
- 0x25, 0x88, 0x20, 0xc0, 0x8f, 0x89, 0x91, 0x0e,
- 0xd3, 0x42, 0x1c, 0xb4, 0xa9, 0x7b, 0xb7, 0x9e },
- { 0x9c, 0x70, 0x8d, 0x5b, 0xab, 0x37, 0xf5, 0xb6,
- 0xbc, 0x8a, 0x77, 0x53, 0x12, 0x57, 0x2a, 0xb2,
- 0x79, 0x21, 0x6d, 0x55, 0x6d, 0xa7, 0x4a, 0xc2,
- 0xa7, 0xc0, 0x41, 0xe8, 0xce, 0xb0, 0xbe, 0x0a },
- { 0x9d, 0x6b, 0xdf, 0xcf, 0x0c, 0xbf, 0xfe, 0xea,
- 0x3b, 0x1a, 0xc7, 0xe9, 0x63, 0xcb, 0xb5, 0xf2,
- 0x7f, 0xbd, 0xa8, 0x9d, 0x27, 0x77, 0xf6, 0x0e,
- 0x56, 0x5b, 0x27, 0x78, 0x54, 0xef, 0xb0, 0x19 },
- { 0x9d, 0xac, 0x33, 0x14, 0xb2, 0x5b, 0xb7, 0x9a,
- 0x39, 0xcd, 0x01, 0xec, 0x4b, 0x33, 0xa1, 0x2f,
- 0x47, 0x51, 0x2f, 0x54, 0x09, 0xff, 0x09, 0x5d,
- 0x40, 0xaa, 0xd6, 0x20, 0x84, 0xef, 0x15, 0xbe },
- { 0x9f, 0x24, 0x5c, 0x0a, 0x0e, 0xc6, 0x3a, 0xaa,
- 0xcb, 0xf9, 0x69, 0xc6, 0xfc, 0x24, 0xa1, 0x07,
- 0x15, 0x83, 0xb7, 0x79, 0xa5, 0x8a, 0xb6, 0x23,
- 0xdd, 0x15, 0x31, 0xa2, 0xca, 0x9f, 0x87, 0x51 },
- { 0x9f, 0xaf, 0x1c, 0x11, 0xa3, 0xc7, 0xe2, 0x41,
- 0xf8, 0x63, 0x71, 0x97, 0xe8, 0x99, 0x68, 0xdb,
- 0x86, 0x6a, 0xd0, 0x1a, 0x5d, 0x4e, 0xd5, 0x34,
- 0x59, 0x48, 0x65, 0xb9, 0x70, 0x75, 0xf2, 0x60 },
- { 0xa0, 0x05, 0x20, 0xb9, 0x68, 0xbf, 0xcb, 0x63,
- 0x40, 0x87, 0x9f, 0xa8, 0x43, 0x82, 0x0c, 0xec,
- 0x95, 0x45, 0x86, 0x0f, 0xe2, 0x9e, 0x2f, 0x8f,
- 0xee, 0x00, 0xb0, 0x0f, 0xf8, 0x43, 0x42, 0x74 },
- { 0xa0, 0xc2, 0xd2, 0x07, 0xa4, 0x7e, 0x18, 0xd0,
- 0x37, 0x14, 0xd5, 0xb3, 0x44, 0x5d, 0x88, 0xbe,
- 0x81, 0xff, 0x5e, 0x1d, 0x16, 0x07, 0x3d, 0xc1,
- 0x16, 0x6b, 0xb5, 0x44, 0x8f, 0xf6, 0x52, 0xdf },
- { 0xa1, 0x50, 0x03, 0x2f, 0x4e, 0xf5, 0xd4, 0xfe,
- 0xb0, 0xae, 0x4a, 0xe1, 0xcd, 0x54, 0x35, 0xba,
- 0x04, 0xa9, 0xb6, 0xa0, 0xf9, 0x0e, 0x2f, 0x3c,
- 0x4b, 0x8a, 0x7b, 0x69, 0xe7, 0xc8, 0x7e, 0x43 },
- { 0xa1, 0x97, 0x7d, 0x0c, 0x92, 0x7c, 0x21, 0xeb,
- 0x47, 0x6f, 0x67, 0xbe, 0xfe, 0xd6, 0xcf, 0x2c,
- 0x61, 0xb7, 0x45, 0xf0, 0xce, 0x8d, 0x26, 0x58,
- 0x3d, 0x03, 0xb2, 0x70, 0x02, 0xd5, 0xcd, 0xaf },
- { 0xa2, 0x6c, 0x37, 0x5e, 0xb3, 0x19, 0x6e, 0x28,
- 0x3b, 0xec, 0x60, 0x3d, 0xb6, 0xbb, 0xda, 0xe2,
- 0x49, 0x55, 0xe4, 0xba, 0x91, 0x0c, 0xd4, 0x2d,
- 0x9e, 0xac, 0x55, 0xca, 0xc6, 0x10, 0x3a, 0xb9 },
- { 0xa3, 0xa4, 0xfc, 0x03, 0xe1, 0x75, 0xf2, 0x68,
- 0x02, 0x57, 0x46, 0x34, 0xde, 0x70, 0x7d, 0x2f,
- 0x92, 0xf4, 0xd0, 0xcb, 0x90, 0xcd, 0xb6, 0x1d,
- 0xd1, 0x95, 0x8b, 0xcf, 0x0c, 0x55, 0x20, 0x86 },
- { 0xa6, 0x62, 0xfc, 0x81, 0xc9, 0x09, 0x34, 0xb9,
- 0xb4, 0xd6, 0x30, 0xb5, 0xd8, 0x2e, 0x86, 0xf2,
- 0x36, 0x3e, 0xc1, 0x5c, 0xcf, 0xcd, 0xaf, 0xa7,
- 0xa2, 0x0c, 0x9b, 0x4e, 0x3a, 0x90, 0x0d, 0xd1 },
- { 0xa6, 0xa4, 0xa3, 0xf6, 0x1f, 0xa5, 0x8c, 0xe9,
- 0x70, 0xb4, 0x58, 0xb7, 0xc3, 0x7c, 0x05, 0x2e,
- 0xad, 0x1e, 0xb2, 0x0b, 0x85, 0x67, 0xe3, 0x51,
- 0xad, 0x8e, 0x6f, 0xba, 0x49, 0xc2, 0x69, 0x2c },
- { 0xa6, 0xde, 0x6c, 0x3b, 0x8c, 0x14, 0x05, 0xcb,
- 0xe1, 0x2d, 0xb4, 0x09, 0x97, 0x61, 0x71, 0xac,
- 0xb5, 0x1f, 0xb3, 0xdc, 0xfb, 0xb7, 0x6e, 0xe3,
- 0x84, 0x95, 0x39, 0xcd, 0x8a, 0xb0, 0x66, 0xdf },
- { 0xa8, 0x53, 0xad, 0xc1, 0xc2, 0x18, 0x59, 0xaf,
- 0x7c, 0x46, 0x2b, 0x4a, 0xa0, 0xa5, 0x74, 0xca,
- 0x9f, 0xee, 0xfb, 0x18, 0x5a, 0x1f, 0xdb, 0xb6,
- 0xc1, 0x0e, 0x17, 0xd6, 0x01, 0xb7, 0x09, 0x8f },
- { 0xa8, 0xdf, 0xf0, 0x6a, 0x17, 0x35, 0xb4, 0x6d,
- 0x17, 0xda, 0xeb, 0xc3, 0x43, 0x43, 0x18, 0x31,
- 0x3b, 0x2d, 0x9e, 0x7c, 0x3e, 0xf4, 0x8f, 0x28,
- 0x53, 0x75, 0x35, 0x13, 0xe1, 0xb2, 0x53, 0xa8 },
- { 0xa8, 0xe3, 0x8c, 0x6e, 0xc0, 0x93, 0xf5, 0xaf,
- 0x53, 0x88, 0xf1, 0xe7, 0x66, 0xd7, 0x5f, 0xfb,
- 0x57, 0xdd, 0xbe, 0x3e, 0x9d, 0xc2, 0xe0, 0xbe,
- 0x57, 0xbb, 0x88, 0x36, 0x46, 0xc5, 0xc0, 0x32 },
- { 0xa9, 0x0b, 0x8d, 0xe1, 0x7f, 0x6b, 0x68, 0x37,
- 0x56, 0x21, 0x2d, 0xb3, 0xab, 0x34, 0x89, 0x6e,
- 0x91, 0x70, 0x93, 0x11, 0x3e, 0x47, 0xca, 0x35,
- 0x96, 0x2e, 0xac, 0xca, 0x9c, 0xb3, 0x86, 0xf0 },
- { 0xaa, 0x4b, 0xb3, 0x6f, 0x51, 0xd3, 0xc5, 0x33,
- 0xb5, 0x27, 0x23, 0xcf, 0x66, 0xa5, 0xa9, 0x9f,
- 0xc1, 0x2f, 0x11, 0xd4, 0xcc, 0x12, 0x87, 0x56,
- 0xa5, 0xa3, 0xe8, 0x9c, 0x57, 0xbb, 0x97, 0x51 },
- { 0xaa, 0xeb, 0xfe, 0x2d, 0x21, 0xb7, 0xe5, 0x35,
- 0x1b, 0xb9, 0x99, 0x69, 0x44, 0x44, 0x19, 0xef,
- 0x21, 0xc9, 0x68, 0x8c, 0xe0, 0x53, 0x24, 0x88,
- 0x84, 0xca, 0xb0, 0xb8, 0x95, 0x10, 0x30, 0xff },
- { 0xab, 0x41, 0x28, 0x10, 0x9c, 0xab, 0x8a, 0x58,
- 0x7c, 0x8f, 0xf4, 0xc7, 0xf6, 0x87, 0x34, 0x49,
- 0x98, 0x18, 0xd1, 0x3f, 0x52, 0x26, 0x76, 0xd0,
- 0x66, 0xb3, 0x52, 0x17, 0x6f, 0xd2, 0x35, 0x96 },
- { 0xab, 0x80, 0xd9, 0xba, 0x0a, 0xef, 0xad, 0x7b,
- 0xec, 0xce, 0x7f, 0x5e, 0x61, 0x59, 0x9a, 0xf5,
- 0x26, 0x69, 0xbf, 0x59, 0x50, 0x7f, 0x8e, 0xf1,
- 0x99, 0x13, 0xc4, 0x2e, 0xe1, 0x29, 0xda, 0xf0 },
- { 0xab, 0xeb, 0x6a, 0xa0, 0xd1, 0xb0, 0xe0, 0x49,
- 0xd6, 0x9d, 0xf8, 0x3a, 0xdd, 0x19, 0xf7, 0x26,
- 0x8a, 0x38, 0xde, 0x6c, 0x00, 0x72, 0x60, 0x68,
- 0xc2, 0xee, 0xe4, 0x55, 0x44, 0xf6, 0xd6, 0x7a },
- { 0xac, 0x1b, 0x4c, 0x64, 0x6c, 0xae, 0xfb, 0x10,
- 0x8a, 0x54, 0xca, 0xb5, 0x4a, 0x96, 0xe9, 0x66,
- 0x6e, 0x72, 0xa8, 0x20, 0x22, 0x44, 0xef, 0x3d,
- 0x7c, 0xa9, 0x34, 0xdf, 0xcc, 0x24, 0xfc, 0xa7 },
- { 0xad, 0x69, 0x54, 0x5f, 0x9f, 0x85, 0x25, 0x5f,
- 0xe4, 0x16, 0x51, 0x3d, 0x94, 0xdb, 0x31, 0x50,
- 0x5f, 0x38, 0x4b, 0x52, 0x3c, 0x2c, 0xa2, 0x6e,
- 0xdc, 0x0a, 0x54, 0x9a, 0x8f, 0x16, 0x26, 0xf9 },
- { 0xae, 0x03, 0x19, 0xfe, 0xa6, 0xa6, 0x5e, 0x84,
- 0xe8, 0x54, 0xb5, 0x15, 0x50, 0xea, 0x44, 0x4f,
- 0xa3, 0xb8, 0xbb, 0x50, 0xae, 0x93, 0x74, 0x01,
- 0x3c, 0xfe, 0xf3, 0x88, 0x73, 0x5d, 0x0b, 0xd3 },
- { 0xaf, 0x1f, 0x37, 0x1f, 0x34, 0x84, 0x57, 0x51,
- 0x65, 0x2d, 0xc7, 0x48, 0x23, 0xf3, 0x01, 0x5c,
- 0x5a, 0x11, 0xca, 0x65, 0x3f, 0x28, 0x70, 0x1e,
- 0xdd, 0x4a, 0x7e, 0x0d, 0x23, 0x17, 0x1b, 0xbb },
- { 0xaf, 0x6b, 0x80, 0x51, 0x47, 0x14, 0x0a, 0x0e,
- 0x41, 0x81, 0xd8, 0x6a, 0x7e, 0x8f, 0x07, 0x69,
- 0xb6, 0x1d, 0x46, 0xd7, 0xb6, 0xfa, 0xc6, 0xe6,
- 0xf9, 0x59, 0x6d, 0xe9, 0x4a, 0xa8, 0xe2, 0xe8 },
- { 0xb0, 0x5c, 0x14, 0x33, 0x61, 0x75, 0x9b, 0xe1,
- 0x52, 0xfd, 0x76, 0xa5, 0xff, 0xa4, 0x87, 0x2d,
- 0xd4, 0x2e, 0xa0, 0x60, 0xae, 0x40, 0xa3, 0x83,
- 0x13, 0xb7, 0xb5, 0x4a, 0xec, 0x06, 0x73, 0xc2 },
- { 0xb0, 0xe0, 0xe1, 0x6c, 0x5f, 0x69, 0x1f, 0x66,
- 0xa9, 0x57, 0x3b, 0xd3, 0xcf, 0x43, 0xf9, 0xdf,
- 0xd2, 0xad, 0x3e, 0x56, 0x15, 0x54, 0x63, 0x7f,
- 0x1e, 0x7b, 0x71, 0x91, 0x4d, 0x62, 0x73, 0x38 },
- { 0xb2, 0xdc, 0x86, 0x25, 0x6c, 0xcf, 0xf4, 0xbb,
- 0x14, 0xfd, 0x70, 0x27, 0x9f, 0xcc, 0x3c, 0xe9,
- 0x25, 0xc5, 0x1f, 0xb7, 0x17, 0xe5, 0x87, 0x6f,
- 0x29, 0x1b, 0xa1, 0x70, 0x73, 0x43, 0x85, 0x68 },
- { 0xb3, 0x0d, 0x88, 0x44, 0x30, 0x43, 0xf5, 0xf3,
- 0x72, 0x32, 0xbb, 0x9b, 0xac, 0xb9, 0x94, 0xc5,
- 0xba, 0xe9, 0x3a, 0x46, 0xfc, 0x87, 0xf1, 0x51,
- 0x29, 0xc9, 0x74, 0x69, 0xa5, 0x81, 0x4e, 0xca },
- { 0xb3, 0x1a, 0xf0, 0xc2, 0xe5, 0x1e, 0xa2, 0x1c,
- 0x91, 0x04, 0xf9, 0x4f, 0xaa, 0x66, 0xe0, 0xcc,
- 0xc0, 0x41, 0x34, 0xd5, 0x80, 0x9a, 0x2a, 0x26,
- 0x70, 0xa3, 0xb7, 0xbc, 0x7d, 0xd9, 0x64, 0xf8 },
- { 0xb3, 0xf4, 0xb1, 0x6f, 0x8e, 0xce, 0xbb, 0x41,
- 0x47, 0x4f, 0x92, 0x4f, 0xee, 0xf9, 0xb0, 0xbd,
- 0x97, 0x9b, 0x36, 0x36, 0xc3, 0x4f, 0xf2, 0x72,
- 0x3f, 0x67, 0x3c, 0x8e, 0xee, 0x2a, 0xf1, 0x52 },
- { 0xb5, 0xe5, 0xdc, 0xde, 0xcb, 0x8d, 0xeb, 0x27,
- 0x13, 0x4f, 0x02, 0xa5, 0x18, 0x79, 0x43, 0x16,
- 0xf0, 0x8f, 0xaf, 0x9c, 0x2b, 0x1f, 0xda, 0xd6,
- 0xd4, 0x86, 0x61, 0xf5, 0x7e, 0xa6, 0x45, 0xd9 },
- { 0xb7, 0x06, 0xde, 0x1b, 0xd1, 0xee, 0x2f, 0x4c,
- 0xec, 0x6c, 0xe0, 0x92, 0x02, 0x2b, 0x49, 0x32,
- 0x81, 0xe2, 0x9a, 0x21, 0x73, 0x50, 0x8c, 0x9b,
- 0xd0, 0xfb, 0xc2, 0xc3, 0xd9, 0x68, 0xe3, 0xe7 },
- { 0xb7, 0xa2, 0xae, 0x06, 0x06, 0xaa, 0x2c, 0xfb,
- 0x27, 0x01, 0xb3, 0xb2, 0x77, 0xf4, 0xd7, 0x12,
- 0x54, 0x70, 0x48, 0x7e, 0xfd, 0x94, 0x05, 0x85,
- 0x7f, 0xfc, 0xe4, 0xbf, 0x29, 0x10, 0x5e, 0x68 },
- { 0xb8, 0x74, 0x36, 0x95, 0x1c, 0xec, 0x37, 0x7e,
- 0xef, 0x73, 0xde, 0x4b, 0x74, 0xf2, 0x83, 0xc4,
- 0x2b, 0x2c, 0xcb, 0x1c, 0xa3, 0x7c, 0x5b, 0x30,
- 0xaa, 0xd6, 0x55, 0xa7, 0x40, 0x1a, 0x3d, 0x2f },
- { 0xb9, 0x8d, 0x83, 0x38, 0x55, 0xc3, 0x67, 0x88,
- 0x62, 0xb6, 0x2f, 0x36, 0x50, 0xdb, 0x00, 0xa3,
- 0x45, 0xf4, 0x6a, 0x0e, 0x8e, 0x01, 0x1a, 0x20,
- 0x01, 0x3f, 0xd8, 0xed, 0xce, 0x25, 0x27, 0x0d },
- { 0xba, 0x51, 0xaf, 0xf5, 0xd5, 0xd3, 0x10, 0x5f,
- 0x34, 0xa2, 0xb3, 0x3a, 0x83, 0xe3, 0xad, 0xfd,
- 0x12, 0xd7, 0x9c, 0xa6, 0x05, 0x90, 0x9d, 0x96,
- 0x03, 0x3e, 0x32, 0xa5, 0xcf, 0x2f, 0x71, 0xf6 },
- { 0xbb, 0x5c, 0xb3, 0x78, 0xb7, 0xb9, 0x48, 0x7f,
- 0xa6, 0x1b, 0xc0, 0x91, 0x3d, 0xa1, 0xdf, 0x26,
- 0xa1, 0xcf, 0xef, 0xf7, 0x45, 0x2d, 0x9b, 0xa3,
- 0x6c, 0xac, 0x47, 0xa8, 0x5c, 0x7f, 0xf3, 0x48 },
- { 0xbc, 0x14, 0x2e, 0xba, 0xc2, 0x78, 0xa8, 0xfe,
- 0x8c, 0xa8, 0xbc, 0x2c, 0x62, 0xfb, 0xcc, 0x40,
- 0x17, 0xff, 0x24, 0x96, 0x98, 0xbe, 0xed, 0xfb,
- 0x1e, 0xf3, 0x6f, 0x37, 0x5f, 0xb3, 0x9f, 0x72 },
- { 0xbd, 0x2e, 0x2f, 0x37, 0xc9, 0x66, 0xc3, 0x86,
- 0xd9, 0x70, 0x44, 0xfd, 0xe3, 0xe3, 0xf9, 0x00,
- 0xfb, 0x1a, 0x0b, 0x04, 0x03, 0xb5, 0x81, 0x72,
- 0x5f, 0x34, 0xe3, 0xc1, 0x90, 0x05, 0x60, 0x56 },
- { 0xbe, 0xb9, 0x09, 0x0c, 0x92, 0xd1, 0x6b, 0xd0,
- 0x5a, 0xf3, 0x91, 0x5a, 0x39, 0xcc, 0x2a, 0xfa,
- 0x9f, 0x6a, 0x8a, 0x6f, 0xbe, 0xd4, 0xfe, 0x54,
- 0xd9, 0xde, 0x32, 0x49, 0x23, 0xb3, 0x93, 0x5a },
- { 0xbf, 0x38, 0xe6, 0xae, 0x32, 0x0f, 0x69, 0x16,
- 0x16, 0x0d, 0xa6, 0x06, 0x86, 0x83, 0xbf, 0x49,
- 0xf2, 0xb2, 0x2b, 0x25, 0x24, 0x84, 0x63, 0x68,
- 0xf5, 0x04, 0x51, 0x81, 0x52, 0x40, 0x25, 0x9a },
- { 0xbf, 0x60, 0xae, 0xb3, 0x91, 0xc0, 0xfb, 0xd0,
- 0x49, 0x53, 0x52, 0x6d, 0xa9, 0xfd, 0x59, 0x96,
- 0x9a, 0x82, 0xf1, 0xee, 0x81, 0xa7, 0x97, 0x98,
- 0xa4, 0x17, 0x1e, 0x14, 0x59, 0x39, 0x19, 0x67 },
- { 0xbf, 0xf4, 0x3a, 0x97, 0x20, 0x48, 0x2d, 0x13,
- 0x4c, 0xd5, 0xee, 0x8a, 0x88, 0x99, 0xe1, 0xa7,
- 0x36, 0xbf, 0x54, 0xa2, 0xb7, 0x86, 0x26, 0x9c,
- 0x0d, 0xcb, 0x8b, 0xa1, 0x92, 0xa8, 0x1f, 0xa4 },
- { 0xc0, 0x09, 0xa1, 0xbe, 0x5b, 0xe8, 0xaf, 0xb5,
- 0x25, 0x8e, 0x12, 0x85, 0x5c, 0x64, 0xd0, 0x4d,
- 0x13, 0xe8, 0xcc, 0xc4, 0x7b, 0x02, 0xbf, 0x3b,
- 0x51, 0xc6, 0xe1, 0x18, 0x05, 0xae, 0xec, 0xeb },
- { 0xc0, 0x9f, 0xfa, 0x0e, 0xdd, 0x16, 0xba, 0x55,
- 0xf2, 0x3c, 0xea, 0xf7, 0x2b, 0x11, 0x34, 0xe9,
- 0x28, 0xdb, 0xa1, 0xc2, 0x34, 0x5a, 0x5a, 0xb5,
- 0x63, 0x1e, 0x25, 0x41, 0x24, 0x05, 0x4a, 0xdb },
- { 0xc0, 0xab, 0xd1, 0xc3, 0x56, 0x2f, 0xbc, 0x7f,
- 0xf7, 0xbd, 0x38, 0x95, 0x54, 0x60, 0xc3, 0xfc,
- 0x43, 0x55, 0x0d, 0x97, 0x7f, 0x25, 0xe3, 0x43,
- 0xd4, 0x9c, 0xd4, 0xaf, 0xad, 0xf2, 0x09, 0x3c },
- { 0xc0, 0xfe, 0xb7, 0x2a, 0x5f, 0x33, 0x16, 0x5c,
- 0x0d, 0xc7, 0xc4, 0x24, 0x7e, 0x23, 0xf3, 0x8c,
- 0xc6, 0x1f, 0x25, 0x24, 0x42, 0xb2, 0xf6, 0x13,
- 0x40, 0x92, 0xde, 0x3b, 0xad, 0x7e, 0x45, 0x0d },
- { 0xc1, 0x77, 0x12, 0x97, 0xa4, 0xe8, 0xdc, 0x53,
- 0x75, 0x19, 0x5e, 0x1b, 0x63, 0x04, 0x2b, 0x59,
- 0x19, 0x09, 0xf1, 0xd7, 0xeb, 0x5d, 0x25, 0xf2,
- 0x97, 0xae, 0x7a, 0x61, 0xc1, 0x53, 0x8f, 0x9e },
- { 0xc1, 0x86, 0xbe, 0x26, 0xe4, 0x47, 0x89, 0x7c,
- 0x48, 0x3c, 0x43, 0xfd, 0xc0, 0x86, 0xe2, 0x60,
- 0x74, 0x17, 0xeb, 0x3e, 0xa7, 0x88, 0xec, 0x03,
- 0x10, 0xa7, 0x9d, 0xa9, 0x24, 0x1d, 0x16, 0xde },
- { 0xc1, 0xde, 0x5f, 0xa3, 0x92, 0x13, 0x68, 0x58,
- 0x11, 0xa5, 0xba, 0x93, 0x12, 0x1d, 0xe7, 0xa3,
- 0x95, 0x98, 0x4e, 0x84, 0x44, 0x4e, 0x58, 0xf1,
- 0x63, 0xb7, 0xa6, 0x20, 0xae, 0x3b, 0xbf, 0xa8 },
- { 0xc2, 0xad, 0xdf, 0x99, 0xcf, 0xc4, 0x2c, 0xe0,
- 0xe5, 0xa0, 0x93, 0xbc, 0xbf, 0x87, 0x40, 0x7c,
- 0x61, 0x1f, 0x9d, 0x0a, 0xbf, 0x2a, 0x35, 0xd6,
- 0xe8, 0x03, 0xa3, 0x8e, 0xcb, 0x92, 0xc7, 0xb3 },
- { 0xc2, 0xe7, 0x92, 0x11, 0x6a, 0x05, 0x00, 0x00,
- 0xbd, 0x47, 0x59, 0x1d, 0x93, 0x04, 0x71, 0xe6,
- 0x17, 0x4c, 0x93, 0x85, 0xf5, 0xdc, 0x32, 0xb7,
- 0x62, 0x31, 0x65, 0x5f, 0xc8, 0x5e, 0x22, 0xe2 },
- { 0xc3, 0x79, 0x03, 0xc5, 0x3a, 0xe6, 0x02, 0xec,
- 0x96, 0x9e, 0xc3, 0x3f, 0x63, 0xfe, 0x9a, 0xb2,
- 0x0c, 0x39, 0x5f, 0x83, 0x0d, 0x30, 0xe4, 0xee,
- 0x9d, 0x8d, 0xd9, 0x05, 0x92, 0x1e, 0xc1, 0xa0 },
- { 0xc3, 0xcf, 0x54, 0x16, 0xa5, 0x31, 0xaf, 0x4b,
- 0xfa, 0xe8, 0x9c, 0x45, 0x14, 0x3f, 0x20, 0xcc,
- 0x1b, 0x3e, 0x18, 0x1d, 0x29, 0xc2, 0xd0, 0xe8,
- 0xff, 0x7d, 0x3f, 0x2a, 0x66, 0xb1, 0x82, 0xfe },
- { 0xc4, 0x98, 0xa1, 0xb6, 0x9f, 0x54, 0x40, 0x86,
- 0x17, 0x47, 0x47, 0x71, 0x5a, 0x27, 0x4d, 0x3f,
- 0xb5, 0x90, 0x19, 0xbe, 0x09, 0x21, 0x31, 0xbc,
- 0xfa, 0xa8, 0x3a, 0x39, 0x5f, 0x7e, 0x57, 0x3c },
- { 0xc4, 0xe2, 0x8d, 0xd8, 0x3f, 0xe3, 0x0c, 0x96,
- 0x33, 0x8c, 0xef, 0x77, 0x73, 0xc6, 0xdf, 0xca,
- 0x6c, 0xe4, 0xfa, 0x96, 0x41, 0xbe, 0xab, 0x38,
- 0x05, 0xa8, 0xef, 0xb6, 0xcd, 0xc3, 0xcf, 0x0a },
- { 0xc5, 0x00, 0xb8, 0x3f, 0x3e, 0x06, 0x6c, 0xd1,
- 0xdd, 0x0e, 0xbc, 0xd7, 0x3d, 0xd4, 0x01, 0x61,
- 0xb9, 0x25, 0x9a, 0xa7, 0x7a, 0xb8, 0xa6, 0x47,
- 0xe8, 0x57, 0x1f, 0xf3, 0x37, 0xcf, 0x94, 0x6d },
- { 0xc5, 0x29, 0x5b, 0xa6, 0xe2, 0x7e, 0x72, 0x10,
- 0x22, 0xfe, 0xb2, 0x1e, 0x78, 0xeb, 0x7b, 0x03,
- 0x57, 0xc9, 0xcd, 0x56, 0x5b, 0xd0, 0xe5, 0x96,
- 0x72, 0xf6, 0x66, 0x34, 0x2b, 0x79, 0x94, 0x9d },
- { 0xc6, 0x12, 0x75, 0x6b, 0xa5, 0x42, 0x34, 0x4a,
- 0xdc, 0x1b, 0x80, 0xe9, 0x38, 0x84, 0x5a, 0x1e,
- 0xd6, 0xe9, 0x38, 0xfe, 0xf4, 0x0d, 0x04, 0xec,
- 0x86, 0x55, 0x8f, 0x4b, 0x21, 0x05, 0x2f, 0xd2 },
- { 0xc6, 0x17, 0xe0, 0x85, 0x5b, 0xf1, 0x4f, 0xbf,
- 0x21, 0xaf, 0x00, 0x82, 0x25, 0xca, 0xbe, 0x40,
- 0x4f, 0x73, 0x8c, 0x27, 0x8a, 0x4a, 0x42, 0x87,
- 0xf1, 0xee, 0x38, 0x01, 0x27, 0xc5, 0x61, 0xfa },
- { 0xc6, 0xa4, 0x24, 0xbf, 0x7c, 0xfe, 0x31, 0x72,
- 0x74, 0x7a, 0x47, 0x14, 0xa0, 0xef, 0xb9, 0x17,
- 0x93, 0x8c, 0x5e, 0xbd, 0x59, 0x12, 0x9d, 0xed,
- 0x7a, 0x81, 0x18, 0xc7, 0xf6, 0x59, 0xd1, 0x33 },
- { 0xc6, 0xad, 0x1d, 0x7a, 0x14, 0x1a, 0x91, 0x75,
- 0x2d, 0x31, 0xfb, 0xc1, 0x06, 0x16, 0xbf, 0x1c,
- 0xa2, 0xfb, 0x5b, 0x02, 0xe8, 0x46, 0xb5, 0x9e,
- 0x63, 0x34, 0x6b, 0x31, 0x92, 0xa7, 0x52, 0x92 },
- { 0xc7, 0x01, 0x83, 0x64, 0x38, 0xf3, 0x7b, 0xea,
- 0x8a, 0x88, 0x16, 0x10, 0x63, 0x70, 0x86, 0xf8,
- 0x8d, 0x9a, 0x11, 0x5e, 0x00, 0x92, 0x46, 0xd2,
- 0x7f, 0x48, 0x9f, 0xa7, 0x18, 0x51, 0x88, 0xa8 },
- { 0xc7, 0xff, 0x8e, 0xfd, 0xec, 0xdf, 0x00, 0xd1,
- 0xfc, 0x8d, 0x55, 0x2d, 0x2a, 0x70, 0x70, 0xe5,
- 0xe3, 0x3d, 0x42, 0xe5, 0x90, 0xf5, 0x86, 0xc6,
- 0xae, 0xde, 0x03, 0x2b, 0x2d, 0x86, 0x7b, 0xd5 },
- { 0xc7, 0xff, 0xb4, 0x9f, 0xbc, 0x94, 0x72, 0x24,
- 0x5c, 0x8e, 0x95, 0xde, 0x62, 0x9a, 0xf5, 0xc1,
- 0xbf, 0xea, 0xc5, 0x50, 0x04, 0xc1, 0x54, 0x82,
- 0x3a, 0x58, 0xba, 0xe8, 0x05, 0x6e, 0x3c, 0x64 },
- { 0xc8, 0x37, 0xd6, 0xf2, 0xab, 0x14, 0x79, 0x91,
- 0x42, 0xed, 0x3c, 0x79, 0xbe, 0xd9, 0x44, 0x1e,
- 0x92, 0x50, 0xbd, 0x05, 0x20, 0x25, 0xad, 0x8a,
- 0xf4, 0x40, 0x41, 0xac, 0x19, 0xef, 0xbb, 0x4c },
- { 0xc9, 0x72, 0xf4, 0xf9, 0x6e, 0x71, 0x33, 0xe1,
- 0x6e, 0x55, 0x57, 0xa0, 0x57, 0xb1, 0xd4, 0x2b,
- 0xa9, 0x2d, 0x98, 0x5c, 0xae, 0xe7, 0x3c, 0xaf,
- 0xda, 0xeb, 0x55, 0xec, 0xa2, 0xe4, 0xab, 0xb0 },
- { 0xc9, 0x78, 0x37, 0x2c, 0x9e, 0x11, 0x60, 0x71,
- 0xb6, 0x1b, 0x90, 0x92, 0xa9, 0xaa, 0x96, 0x81,
- 0x62, 0x36, 0x55, 0xa6, 0x6f, 0x4f, 0xcb, 0xc4,
- 0xd3, 0xa6, 0x7e, 0xfd, 0x56, 0x72, 0x48, 0x30 },
- { 0xca, 0x55, 0x6f, 0x82, 0xc9, 0x68, 0x4c, 0x9a,
- 0xf3, 0x55, 0x7d, 0x3e, 0x2d, 0x88, 0xaf, 0x92,
- 0xed, 0x25, 0x9c, 0x20, 0xff, 0xd1, 0xdd, 0xe9,
- 0xf7, 0x9d, 0x6b, 0x92, 0xc6, 0x1e, 0xe1, 0xb9 },
- { 0xca, 0xbe, 0x25, 0x56, 0xf1, 0xbb, 0x56, 0x57,
- 0x0c, 0xef, 0x3a, 0x87, 0x03, 0x32, 0x71, 0xa1,
- 0xf2, 0x1d, 0x09, 0xb7, 0xfd, 0x04, 0x12, 0x83,
- 0x18, 0xe5, 0xe7, 0xbc, 0xe3, 0xa2, 0x01, 0xe2 },
- { 0xca, 0xdc, 0xd5, 0xae, 0x1b, 0x75, 0x6a, 0xb7,
- 0x41, 0xb3, 0x56, 0x9c, 0x42, 0xa5, 0x41, 0x1f,
- 0x09, 0x3e, 0x4e, 0x1f, 0x01, 0x2e, 0xc5, 0x79,
- 0x91, 0xcb, 0xd6, 0xdb, 0xe0, 0x8f, 0xaa, 0xc1 },
- { 0xcb, 0x7a, 0x43, 0x8d, 0x16, 0xe4, 0xa5, 0xf3,
- 0xc5, 0x6f, 0xdf, 0x19, 0x1e, 0x1d, 0xaf, 0x9f,
- 0x32, 0x5c, 0x65, 0x0b, 0xd6, 0x2f, 0x07, 0xc4,
- 0x67, 0x71, 0x72, 0x07, 0x35, 0x1a, 0xe3, 0x29 },
- { 0xcc, 0x30, 0xd8, 0x19, 0xde, 0x54, 0x05, 0xf6,
- 0x49, 0xc8, 0xb7, 0xa8, 0x14, 0x8f, 0x26, 0xd7,
- 0x71, 0x08, 0x3e, 0xc5, 0x18, 0xf9, 0xb6, 0x6f,
- 0xf5, 0x47, 0xf2, 0x82, 0x2d, 0x11, 0x93, 0x6d },
- { 0xcc, 0x65, 0xcd, 0xc5, 0x33, 0x62, 0xd4, 0x21,
- 0x62, 0x7e, 0xae, 0xf5, 0xd0, 0xc8, 0xe4, 0xc4,
- 0xe2, 0x40, 0xad, 0xe0, 0xc9, 0xd4, 0x20, 0xbe,
- 0x67, 0x1e, 0x70, 0xf0, 0xfb, 0xac, 0x8d, 0x0a },
- { 0xcd, 0xb1, 0x62, 0x53, 0xd2, 0x2e, 0xd5, 0xd4,
- 0x26, 0xcf, 0xa1, 0xb0, 0x5c, 0xec, 0xd8, 0x6e,
- 0xf1, 0xb7, 0xde, 0xaa, 0x07, 0xc5, 0x70, 0x5e,
- 0xbb, 0xaf, 0x7d, 0x9a, 0x80, 0x7d, 0x56, 0x16 },
- { 0xcd, 0xc0, 0x39, 0xf3, 0xa2, 0xd1, 0xbb, 0xa5,
- 0xe8, 0x09, 0x4e, 0x55, 0x23, 0xcf, 0x60, 0x47,
- 0x09, 0x7d, 0x4b, 0x3c, 0xd4, 0xec, 0x4e, 0xd6,
- 0xaa, 0x8e, 0xb7, 0xb4, 0xd8, 0xb5, 0x77, 0x7d },
- { 0xcd, 0xc4, 0xea, 0x92, 0x02, 0xe3, 0x3e, 0xdd,
- 0x0f, 0x2d, 0x3a, 0xe8, 0x6a, 0xca, 0xc7, 0xfb,
- 0x25, 0x35, 0x4b, 0x02, 0x23, 0x5b, 0x09, 0x33,
- 0xaa, 0x81, 0xa3, 0x13, 0xb5, 0xfd, 0xfe, 0xec },
- { 0xce, 0x4c, 0x2f, 0x8f, 0x16, 0x46, 0x8a, 0x58,
- 0x88, 0xe9, 0x0f, 0x73, 0x4e, 0x4d, 0x22, 0x02,
- 0xdf, 0xad, 0xbf, 0xa6, 0x6f, 0x5b, 0x35, 0x75,
- 0x2b, 0xaa, 0x76, 0x21, 0xa7, 0x60, 0xb0, 0x88 },
- { 0xce, 0x81, 0x44, 0x58, 0x54, 0x03, 0x1f, 0x3d,
- 0x0f, 0x5c, 0x88, 0x75, 0x46, 0x4d, 0xcd, 0x5b,
- 0xa6, 0xc8, 0x90, 0xf4, 0x49, 0xb3, 0x20, 0x7b,
- 0xca, 0x2b, 0xc9, 0x61, 0x82, 0x2d, 0x27, 0xc4 },
- { 0xcf, 0xa0, 0xc0, 0x0c, 0xb2, 0xfb, 0x4b, 0x85,
- 0x7a, 0xad, 0x22, 0xb1, 0x3a, 0x90, 0xe3, 0x46,
- 0xa0, 0x3e, 0x6b, 0x79, 0xab, 0xd5, 0xd2, 0x75,
- 0xb5, 0x43, 0x24, 0x68, 0x17, 0x92, 0xd6, 0xd1 },
- { 0xd0, 0xf5, 0x93, 0xc1, 0xa8, 0x1b, 0x1e, 0xf8,
- 0x51, 0x69, 0x81, 0xee, 0x56, 0xf1, 0xd5, 0x98,
- 0xa2, 0xa6, 0x03, 0x48, 0x8c, 0x67, 0x8c, 0x1b,
- 0x7b, 0xbe, 0xa6, 0x44, 0x6b, 0x00, 0x83, 0xad },
- { 0xd2, 0x90, 0x3c, 0xa2, 0x55, 0x17, 0x27, 0xed,
- 0x01, 0x71, 0xcc, 0x4a, 0x43, 0xb3, 0xca, 0xe0,
- 0x09, 0xb7, 0x47, 0xb9, 0xf4, 0xf8, 0x48, 0x72,
- 0x92, 0x27, 0xbf, 0x59, 0x02, 0xf2, 0x3e, 0x47 },
- { 0xd2, 0xe8, 0xa1, 0x23, 0x7a, 0x93, 0xf5, 0x78,
- 0xd1, 0xba, 0x8f, 0x09, 0xe4, 0xff, 0x10, 0x7b,
- 0x62, 0x35, 0x78, 0x85, 0x42, 0xaa, 0x61, 0x83,
- 0xd1, 0x76, 0xdb, 0xf1, 0xc8, 0x8d, 0xcf, 0xb6 },
- { 0xd5, 0x04, 0x88, 0x96, 0x86, 0x07, 0x29, 0xa8,
- 0xfa, 0x5d, 0x23, 0x57, 0x81, 0x2b, 0xa5, 0x6c,
- 0xbe, 0x84, 0xc9, 0xab, 0x7d, 0x14, 0xdf, 0x47,
- 0x64, 0xe0, 0xb6, 0x62, 0x0f, 0xa3, 0x20, 0x10 },
- { 0xd5, 0x41, 0xa7, 0x7e, 0x13, 0x6e, 0x9e, 0x70,
- 0x3b, 0xb9, 0x9f, 0x80, 0x68, 0xcf, 0xee, 0x86,
- 0xa4, 0xb9, 0xf0, 0x89, 0xe0, 0x2d, 0x0c, 0x6c,
- 0xb6, 0xd4, 0xa3, 0x94, 0x6c, 0x6b, 0x16, 0x7a },
- { 0xd5, 0x83, 0x94, 0x96, 0xcd, 0xc8, 0x5b, 0xe3,
- 0xd1, 0xf1, 0xac, 0x65, 0x2e, 0xfa, 0x92, 0xbe,
- 0xa3, 0xb0, 0x61, 0xc1, 0x3d, 0xad, 0x5a, 0x82,
- 0x11, 0x22, 0xcf, 0xe9, 0xc7, 0x1a, 0x5a, 0x32 },
- { 0xd5, 0xa4, 0xee, 0x46, 0x95, 0xb5, 0x65, 0xa6,
- 0x7e, 0x50, 0x48, 0x66, 0xfe, 0x5b, 0xa3, 0xc0,
- 0xed, 0xca, 0xee, 0xd5, 0x2a, 0xd0, 0xaf, 0x07,
- 0xe6, 0x79, 0x17, 0x73, 0x85, 0x12, 0xc8, 0xf5 },
- { 0xd6, 0x25, 0xc0, 0x59, 0x2b, 0x25, 0xdc, 0x03,
- 0xaa, 0x7e, 0x87, 0x8e, 0x6a, 0x85, 0x09, 0x1b,
- 0xaa, 0x07, 0x8d, 0x26, 0x8b, 0xbd, 0xb4, 0x9f,
- 0x09, 0x67, 0x94, 0x08, 0x61, 0x2d, 0x1e, 0xfe },
- { 0xd6, 0xd1, 0xb3, 0x5c, 0xbc, 0x12, 0xfb, 0x1c,
- 0x70, 0xa0, 0xb4, 0x3b, 0xa5, 0x9a, 0xb3, 0xd3,
- 0x22, 0x5f, 0x37, 0x32, 0x64, 0xdd, 0x87, 0xfb,
- 0xca, 0x00, 0x61, 0xec, 0x1c, 0x4d, 0xa1, 0x1a },
- { 0xd7, 0x32, 0x49, 0x74, 0xb5, 0x60, 0x09, 0x62,
- 0x17, 0x61, 0xf7, 0xc0, 0xff, 0x68, 0x9d, 0xde,
- 0x47, 0x74, 0x99, 0x85, 0xe1, 0xee, 0x8b, 0x5c,
- 0x89, 0x61, 0xdd, 0x8f, 0x6a, 0x78, 0xbb, 0xf5 },
- { 0xd9, 0x2e, 0x3e, 0xe3, 0x82, 0xc8, 0xdc, 0xaf,
- 0xa0, 0x39, 0x3d, 0x9f, 0x9a, 0x00, 0xbf, 0x4c,
- 0xd9, 0xd5, 0x64, 0x26, 0x2b, 0x18, 0x0f, 0x68,
- 0x16, 0x0b, 0x20, 0x34, 0xc5, 0x44, 0xd1, 0x0a },
- { 0xd9, 0x65, 0xf7, 0x41, 0x62, 0x04, 0xda, 0x83,
- 0x1a, 0xf6, 0x6b, 0xfa, 0x8f, 0x90, 0xd1, 0x41,
- 0xe9, 0x93, 0xf0, 0x00, 0x21, 0x33, 0xf2, 0x8d,
- 0xe9, 0x7f, 0x56, 0x4a, 0x1d, 0x60, 0x4e, 0xcc },
- { 0xda, 0xdf, 0x97, 0x13, 0x34, 0x14, 0xad, 0x51,
- 0x3f, 0xc7, 0x50, 0x14, 0xe9, 0x56, 0x65, 0xda,
- 0xd7, 0x76, 0xb1, 0x50, 0x4b, 0x15, 0x67, 0x43,
- 0x4f, 0xd8, 0x2a, 0x79, 0xa2, 0x20, 0xe9, 0xa1 },
- { 0xda, 0xff, 0xd4, 0x05, 0x6f, 0xc3, 0x68, 0xfa,
- 0x64, 0x8d, 0x0e, 0xd8, 0x9b, 0x5d, 0xe0, 0xee,
- 0x93, 0x1f, 0x1b, 0x33, 0x84, 0x78, 0xab, 0xf5,
- 0x69, 0x29, 0xa9, 0x4d, 0x3b, 0xd6, 0x1d, 0x46 },
- { 0xde, 0xcd, 0xb9, 0xfc, 0x1d, 0xde, 0xc9, 0x7e,
- 0x09, 0xc3, 0x02, 0x6a, 0xce, 0xb7, 0x6b, 0xda,
- 0xe9, 0xde, 0xb6, 0x62, 0x75, 0x1d, 0xda, 0x34,
- 0x9d, 0x2f, 0xa6, 0xbd, 0x75, 0xca, 0x59, 0x14 },
- { 0xde, 0xd1, 0x9a, 0xd5, 0xde, 0x99, 0x65, 0xd9,
- 0x22, 0x5c, 0x1b, 0xba, 0x5f, 0xb4, 0xd8, 0x90,
- 0xc8, 0xe5, 0xc0, 0x35, 0xe4, 0x85, 0x27, 0x52,
- 0xb6, 0x69, 0xb0, 0x40, 0x0f, 0x24, 0xf1, 0x74 },
- { 0xdf, 0x30, 0xbf, 0x8d, 0x1b, 0xf9, 0x37, 0x8e,
- 0x43, 0x3e, 0xf9, 0xe1, 0xb3, 0xa2, 0x28, 0xa0,
- 0x7e, 0x36, 0x58, 0xa5, 0xbc, 0x43, 0x88, 0x23,
- 0x45, 0x4d, 0xb0, 0x6a, 0x67, 0x94, 0x4c, 0x6e },
- { 0xe0, 0x0b, 0xd7, 0x86, 0xd1, 0xf2, 0xf4, 0x46,
- 0xc4, 0xba, 0x83, 0x99, 0xd4, 0xd8, 0xd5, 0xa0,
- 0xd1, 0x98, 0x57, 0x8f, 0x42, 0x99, 0xfd, 0xfd,
- 0xaf, 0xf7, 0x8c, 0x3f, 0x67, 0x71, 0xf3, 0x94 },
- { 0xe0, 0x8b, 0x2c, 0xc2, 0x7a, 0xe8, 0xe2, 0xef,
- 0x1a, 0x33, 0x01, 0x7a, 0x9a, 0xc2, 0x5d, 0xda,
- 0xfb, 0x5e, 0xa1, 0x12, 0xc9, 0x56, 0xb0, 0x02,
- 0xfe, 0x6c, 0x79, 0x80, 0x14, 0xaa, 0x90, 0x65 },
- { 0xe1, 0xb2, 0xe8, 0x6b, 0x0d, 0xa8, 0x69, 0xe9,
- 0x25, 0x26, 0x6c, 0x1b, 0x56, 0x88, 0x34, 0x5a,
- 0x17, 0xb0, 0xf6, 0xe2, 0xa2, 0x14, 0x94, 0x54,
- 0x7e, 0xac, 0x09, 0x7c, 0x8b, 0xf5, 0x3c, 0x5a },
- { 0xe1, 0xd6, 0x44, 0xa0, 0x96, 0xbd, 0x8a, 0x6c,
- 0xac, 0xbb, 0xda, 0x3e, 0x7f, 0xc3, 0x38, 0xea,
- 0xdd, 0xc1, 0x2f, 0x23, 0x6c, 0x72, 0x61, 0xe4,
- 0x5f, 0x8a, 0xd2, 0xd8, 0x42, 0x42, 0x4f, 0x72 },
- { 0xe2, 0x24, 0x10, 0xb5, 0xa6, 0x7f, 0xed, 0xc2,
- 0x64, 0x69, 0x4c, 0x44, 0x9d, 0x84, 0xfa, 0x1a,
- 0x02, 0xbc, 0x8b, 0x21, 0x28, 0xc1, 0x25, 0x60,
- 0x71, 0x58, 0xc9, 0x1b, 0x05, 0x38, 0x6c, 0x6a },
- { 0xe2, 0xa8, 0x47, 0xc3, 0xf0, 0x9b, 0xeb, 0x6f,
- 0x05, 0x68, 0x6f, 0x17, 0x79, 0x1b, 0x05, 0xf1,
- 0xfe, 0x25, 0xf7, 0x71, 0x86, 0x9c, 0x42, 0x63,
- 0xa5, 0x5b, 0x94, 0x18, 0x77, 0xe4, 0x79, 0x04 },
- { 0xe2, 0xf3, 0x9a, 0x9d, 0x48, 0xa3, 0x22, 0x10,
- 0x55, 0xb3, 0xc8, 0xa3, 0xeb, 0x14, 0x39, 0xd6,
- 0xb8, 0x73, 0x01, 0x3e, 0xe4, 0xd0, 0x97, 0x12,
- 0x20, 0x64, 0xf2, 0x7e, 0xc0, 0x3d, 0xd4, 0xda },
- { 0xe2, 0xf5, 0xde, 0x57, 0xcd, 0x67, 0x24, 0x9a,
- 0x7e, 0x1f, 0x45, 0x5b, 0x85, 0xc0, 0x6f, 0x0d,
- 0x80, 0x9e, 0x75, 0xa5, 0x5c, 0x6b, 0x05, 0x48,
- 0x16, 0xe0, 0x19, 0x89, 0x9a, 0x3a, 0x02, 0xff },
- { 0xe4, 0xf1, 0xde, 0x31, 0xcd, 0xaa, 0x6d, 0x9e,
- 0xb1, 0xaa, 0xfd, 0x10, 0x81, 0x27, 0xa2, 0xf0,
- 0xa8, 0xfb, 0x6d, 0xa8, 0x5a, 0x04, 0x14, 0xad,
- 0x24, 0x99, 0x47, 0xc4, 0x8d, 0x24, 0x92, 0xc5 },
- { 0xe6, 0x44, 0xd1, 0x1c, 0x37, 0x07, 0x0f, 0x89,
- 0x69, 0x33, 0x08, 0x17, 0x8d, 0x6b, 0xe4, 0x95,
- 0x94, 0x96, 0x92, 0xc1, 0xfb, 0xeb, 0x30, 0xed,
- 0x32, 0x9b, 0x74, 0x02, 0x7f, 0xcf, 0xfd, 0x48 },
- { 0xe6, 0xb0, 0xf2, 0xe2, 0x5b, 0xd5, 0x16, 0xe4,
- 0xbb, 0xa3, 0x7a, 0x2b, 0xf2, 0xe2, 0xc7, 0x2a,
- 0x1e, 0x53, 0x9c, 0x60, 0x30, 0xf3, 0xcf, 0x9b,
- 0xbe, 0x5e, 0x79, 0x72, 0x8d, 0x68, 0x64, 0x78 },
- { 0xe6, 0xe5, 0x4d, 0xe7, 0xb4, 0x97, 0x54, 0xd3,
- 0x57, 0xb0, 0xa8, 0xd9, 0x4a, 0x4d, 0x4f, 0x80,
- 0xac, 0xd1, 0x99, 0x4c, 0xcc, 0x1c, 0x99, 0x08,
- 0xe9, 0xf0, 0xd9, 0x21, 0xe4, 0x28, 0xb8, 0x38 },
- { 0xe7, 0x0c, 0xbb, 0x7a, 0xf7, 0xaa, 0x20, 0xb9,
- 0x89, 0x0b, 0xc1, 0xf9, 0xfa, 0x00, 0xd8, 0x09,
- 0x0b, 0x5a, 0xc9, 0x82, 0x5e, 0xa9, 0xd2, 0xfd,
- 0xf7, 0x7c, 0xa4, 0xda, 0xe9, 0x44, 0x51, 0xb2 },
- { 0xe8, 0x16, 0xf9, 0x92, 0x94, 0xa1, 0x3a, 0xc2,
- 0xfa, 0x2b, 0xfb, 0x76, 0xc2, 0x2d, 0xfa, 0x71,
- 0xbc, 0x3d, 0xa4, 0x8f, 0x67, 0x1e, 0xf7, 0x7c,
- 0x00, 0xaa, 0x8e, 0x45, 0x9b, 0x7c, 0xc8, 0x2a },
- { 0xe9, 0xd4, 0x98, 0x51, 0xbf, 0x78, 0x37, 0x6d,
- 0x54, 0x08, 0x2d, 0x1e, 0xb8, 0x2b, 0xd2, 0xdc,
- 0x96, 0x82, 0x07, 0x09, 0xb7, 0x77, 0x2d, 0x3f,
- 0xbc, 0xa3, 0x90, 0x08, 0x8b, 0x54, 0xc4, 0x53 },
- { 0xe9, 0xf5, 0x71, 0xc7, 0x71, 0x64, 0xab, 0xea,
- 0xe1, 0x85, 0x28, 0x37, 0x5c, 0xfd, 0xc7, 0x21,
- 0x9a, 0x6b, 0xde, 0x46, 0x1b, 0x19, 0x73, 0xbe,
- 0x2b, 0xb8, 0xbd, 0xf0, 0xda, 0x78, 0xb2, 0xb4 },
- { 0xeb, 0x11, 0x63, 0xaa, 0xef, 0xe8, 0xfd, 0x88,
- 0xe1, 0x32, 0x7b, 0x48, 0xa9, 0xc0, 0x06, 0x2e,
- 0x06, 0xf0, 0xa6, 0xea, 0xa0, 0xa0, 0x18, 0x24,
- 0x7f, 0x9f, 0xa4, 0xe3, 0x4e, 0x3a, 0x47, 0x4c },
- { 0xec, 0x4b, 0xbd, 0xeb, 0x15, 0x12, 0x1d, 0x96,
- 0x76, 0x4d, 0x6c, 0x01, 0xb2, 0x7e, 0xd5, 0xae,
- 0x86, 0x46, 0x5c, 0x46, 0xd5, 0xa4, 0x0e, 0x34,
- 0xae, 0xfc, 0x09, 0x2d, 0x3e, 0x8b, 0xb1, 0x76 },
- { 0xec, 0x5f, 0xa4, 0x73, 0x12, 0x1e, 0x3f, 0x49,
- 0xf0, 0x95, 0x3a, 0x2a, 0x91, 0x83, 0x39, 0xe3,
- 0x6f, 0x3c, 0xb6, 0xb8, 0xd8, 0xb8, 0x9e, 0x91,
- 0x74, 0x23, 0xda, 0xce, 0xac, 0xe6, 0xd5, 0x8a },
- { 0xec, 0xce, 0x4e, 0x52, 0x82, 0xfd, 0x2e, 0xe0,
- 0x03, 0xa4, 0x03, 0x2c, 0x80, 0xd3, 0x32, 0x1a,
- 0x69, 0x47, 0x25, 0x98, 0x94, 0x59, 0x09, 0xcb,
- 0x25, 0x55, 0x7a, 0xa8, 0x47, 0x74, 0x2d, 0xdf },
- { 0xed, 0x5b, 0xb8, 0x6a, 0x95, 0xa5, 0xfe, 0x2b,
- 0x17, 0x08, 0xf2, 0x56, 0x75, 0x4a, 0x89, 0xc4,
- 0x29, 0x67, 0x9b, 0x30, 0x75, 0x8e, 0xe0, 0x12,
- 0x2b, 0x9e, 0x50, 0x85, 0x8d, 0xe2, 0x10, 0x4b },
- { 0xed, 0xc1, 0xbf, 0x3e, 0xfb, 0xf7, 0xe1, 0xd9,
- 0x5e, 0x19, 0xc5, 0x5e, 0xca, 0xe7, 0x7e, 0x83,
- 0x69, 0x46, 0xab, 0x0a, 0x26, 0xa7, 0x8e, 0x32,
- 0xa4, 0x72, 0xc9, 0xd3, 0x6c, 0x69, 0xce, 0xcd },
- { 0xed, 0xf4, 0xdf, 0x97, 0x2c, 0xad, 0x6c, 0x47,
- 0x0b, 0xab, 0x5d, 0x66, 0x42, 0xf6, 0x60, 0xb8,
- 0x42, 0xd6, 0xc9, 0x73, 0x07, 0x44, 0x93, 0xe4,
- 0xef, 0x1b, 0xbf, 0x31, 0x1a, 0x92, 0x79, 0x95 },
- { 0xee, 0x34, 0xe1, 0xa1, 0x9b, 0xc8, 0x89, 0xf8,
- 0x5f, 0x7f, 0x0f, 0x5b, 0xf8, 0x72, 0xb1, 0xac,
- 0x56, 0x5e, 0xc6, 0xf1, 0x9d, 0xb5, 0x17, 0xba,
- 0x4e, 0xd7, 0x55, 0xc4, 0x18, 0x5f, 0x69, 0xe8 },
- { 0xef, 0x36, 0xa2, 0x29, 0x89, 0x65, 0xe4, 0x98,
- 0x84, 0x59, 0xb9, 0x21, 0x6a, 0xb3, 0x3c, 0x3c,
- 0xa8, 0x42, 0xd2, 0x16, 0x83, 0xb6, 0x2a, 0x2b,
- 0xf1, 0x53, 0x0d, 0x30, 0xb0, 0xae, 0x78, 0x25 },
- { 0xef, 0xaf, 0xca, 0x84, 0x90, 0x30, 0x7b, 0x0f,
- 0x62, 0x2b, 0xf4, 0x3a, 0x0e, 0xb3, 0xc5, 0x1a,
- 0xcb, 0xdd, 0xde, 0xdc, 0x23, 0x92, 0xf1, 0x61,
- 0xac, 0xed, 0x16, 0x71, 0xa6, 0x53, 0x60, 0x7e },
- { 0xef, 0xd1, 0xe0, 0xe7, 0x3f, 0xa8, 0x71, 0x00,
- 0xb7, 0x6a, 0x93, 0x23, 0x49, 0xc4, 0x5d, 0x09,
- 0xb2, 0x8b, 0x2d, 0x8a, 0x00, 0x17, 0x19, 0xa5,
- 0x8d, 0xfa, 0xcc, 0x74, 0x84, 0xc7, 0xcf, 0x42 },
- { 0xf0, 0x6b, 0x35, 0x95, 0x36, 0xd1, 0x34, 0x32,
- 0x8b, 0x36, 0x00, 0x4d, 0xa9, 0xa9, 0x19, 0x0c,
- 0x3a, 0x76, 0x69, 0xe8, 0x27, 0x8d, 0xb9, 0xf7,
- 0x58, 0x57, 0xc4, 0x8d, 0x64, 0x4b, 0xe2, 0x03 },
- { 0xf0, 0xcf, 0xc7, 0x79, 0x13, 0x39, 0x7d, 0xe2,
- 0x38, 0xed, 0xb5, 0x9f, 0x0f, 0x99, 0x23, 0xc6,
- 0xd4, 0x11, 0x0a, 0x4b, 0x3a, 0xc8, 0xac, 0x76,
- 0x55, 0x6a, 0x0c, 0x92, 0x44, 0xf0, 0x3f, 0xc1 },
- { 0xf2, 0xb1, 0x95, 0x84, 0x6e, 0xe2, 0xb9, 0xab,
- 0x5f, 0x18, 0xe6, 0x80, 0x21, 0xf8, 0xdf, 0x7c,
- 0x0b, 0x60, 0x58, 0xde, 0xde, 0x86, 0xc5, 0xd5,
- 0x90, 0xf2, 0xe8, 0x64, 0x3a, 0xfe, 0x04, 0x52 },
- { 0xf2, 0xe5, 0x30, 0x0c, 0x39, 0xf2, 0x86, 0xc6,
- 0x78, 0x99, 0x90, 0x9c, 0x7c, 0xe7, 0x35, 0x9b,
- 0x09, 0x45, 0xd2, 0xaf, 0xd3, 0x4a, 0x6d, 0xd6,
- 0x9e, 0x08, 0xcd, 0xa5, 0x44, 0xc8, 0x7b, 0x3a },
- { 0xf3, 0x0c, 0x0a, 0xed, 0x70, 0x6d, 0x22, 0x55,
- 0x5f, 0x07, 0x09, 0x6a, 0xf4, 0xb8, 0xbe, 0xdc,
- 0x16, 0x3c, 0x0f, 0x6e, 0xd5, 0x34, 0x6e, 0xfc,
- 0x28, 0xe8, 0xcf, 0xaf, 0x84, 0x2f, 0xa5, 0xd9 },
- { 0xf6, 0x13, 0xd5, 0x90, 0x46, 0xd1, 0x66, 0x71,
- 0xd3, 0xc5, 0x60, 0x17, 0x6f, 0x3d, 0x77, 0xfd,
- 0xc5, 0x1e, 0x5f, 0x57, 0xb5, 0xe4, 0x8a, 0xe7,
- 0xa4, 0xb9, 0x70, 0x0a, 0x11, 0xd4, 0x69, 0x3a },
- { 0xf6, 0x54, 0x6b, 0x2f, 0xfe, 0x2b, 0xae, 0xf7,
- 0x35, 0xe8, 0x25, 0x67, 0xa6, 0xe2, 0x36, 0x75,
- 0x03, 0x94, 0xc1, 0x19, 0x14, 0x09, 0x87, 0x0c,
- 0x6f, 0xbe, 0x95, 0x2d, 0x08, 0xa3, 0x3a, 0xba },
- { 0xf8, 0x64, 0x44, 0x3e, 0x2f, 0x63, 0x9e, 0x7c,
- 0xff, 0xd2, 0x42, 0x21, 0xf6, 0x1b, 0xbf, 0xf0,
- 0x7c, 0xce, 0x5c, 0x61, 0xdd, 0xb1, 0x68, 0xb3,
- 0xb4, 0x04, 0xd7, 0xc8, 0xcd, 0xca, 0x18, 0xb2 },
- { 0xf8, 0x94, 0xf9, 0x67, 0x36, 0x9c, 0xe7, 0xcf,
- 0xa3, 0x1a, 0xc1, 0x9a, 0x66, 0x65, 0xb0, 0xc4,
- 0x24, 0xba, 0x40, 0x8a, 0xd5, 0xd3, 0x65, 0xf1,
- 0x68, 0xd8, 0xbe, 0xeb, 0x79, 0xf4, 0x89, 0xf3 },
- { 0xf8, 0xcf, 0x1e, 0x08, 0x6a, 0x6a, 0x06, 0x3f,
- 0xad, 0x25, 0x74, 0x25, 0xaa, 0xe7, 0x20, 0x01,
- 0x40, 0x05, 0xb4, 0x15, 0x91, 0x2d, 0xbb, 0x8c,
- 0x0b, 0xc9, 0x99, 0xaf, 0x48, 0x48, 0xcf, 0xe5 },
- { 0xfb, 0x9a, 0xf7, 0x9d, 0xea, 0x18, 0xaf, 0x62,
- 0x99, 0x85, 0x0e, 0x25, 0x15, 0x9b, 0x4f, 0xb2,
- 0x24, 0xcb, 0xb0, 0xf1, 0x4e, 0xad, 0x7e, 0x85,
- 0xf6, 0x0c, 0x2a, 0xb2, 0x09, 0xea, 0x45, 0x0d },
- { 0xfb, 0xc4, 0xc9, 0xba, 0xcf, 0xe3, 0xda, 0x64,
- 0x13, 0x18, 0x26, 0x6b, 0x72, 0x58, 0x56, 0x00,
- 0x35, 0xbc, 0x64, 0x60, 0x8e, 0x34, 0xb9, 0x90,
- 0xca, 0x92, 0xa5, 0x52, 0xf3, 0x14, 0x21, 0x61 },
- { 0xfb, 0xed, 0xd3, 0x88, 0x89, 0xf0, 0xb4, 0x1f,
- 0x73, 0x4d, 0xe2, 0xf4, 0xc9, 0xd6, 0xf2, 0x7c,
- 0x8d, 0x4a, 0xa9, 0xab, 0x73, 0x64, 0x91, 0xe1,
- 0x64, 0xe1, 0x21, 0xb7, 0xbc, 0xaf, 0x44, 0xe8 },
- { 0xfc, 0x01, 0xa5, 0x5a, 0x36, 0xcc, 0x8b, 0x7b,
- 0x7c, 0xa2, 0xea, 0xb0, 0x84, 0x60, 0xc2, 0x8d,
- 0x1d, 0x6c, 0xd8, 0x9c, 0x57, 0x59, 0x94, 0x05,
- 0xd5, 0x37, 0x4b, 0x91, 0xaa, 0xeb, 0xc8, 0x79 },
- { 0xfc, 0x4d, 0x9a, 0x37, 0xe5, 0xf7, 0x32, 0x72,
- 0xd0, 0xa9, 0xdf, 0xcc, 0xe9, 0x03, 0x12, 0xc7,
- 0x52, 0xe1, 0xb5, 0x2e, 0xb6, 0x54, 0xc4, 0x2c,
- 0x36, 0x94, 0x4b, 0x90, 0x2a, 0x30, 0x41, 0x07 },
- { 0xfc, 0x56, 0xdb, 0xa1, 0xe7, 0xaf, 0xbd, 0xaa,
- 0x07, 0x33, 0xc6, 0x91, 0x1c, 0x5f, 0x1f, 0x18,
- 0x28, 0xcb, 0x12, 0x98, 0x31, 0x40, 0x1a, 0x3c,
- 0xfd, 0xea, 0xa7, 0x24, 0x62, 0x95, 0x35, 0x94 },
- { 0xfc, 0x83, 0xc2, 0x89, 0x89, 0x5a, 0x92, 0x08,
- 0xc9, 0xb1, 0x7a, 0x16, 0xbc, 0xe5, 0xce, 0x80,
- 0xe8, 0xf4, 0xa0, 0x77, 0x21, 0x25, 0x29, 0xce,
- 0x0b, 0xc7, 0xf5, 0x42, 0xc6, 0xcb, 0xde, 0x1a },
- { 0xfc, 0xa6, 0x23, 0x5d, 0x2a, 0xa4, 0xb1, 0xb2,
- 0x51, 0x50, 0x78, 0x57, 0xb4, 0xf0, 0x08, 0xdf,
- 0xd5, 0x27, 0x04, 0x2c, 0xe0, 0x45, 0x01, 0xaa,
- 0xe2, 0x9d, 0xd2, 0x05, 0xbb, 0xef, 0xce, 0x0d },
- { 0xfc, 0xe7, 0x34, 0xe1, 0x2b, 0x8e, 0xfb, 0x43,
- 0x12, 0x71, 0xbf, 0xf6, 0x7a, 0x7a, 0x0a, 0x93,
- 0xb2, 0x19, 0xdd, 0x5e, 0x5d, 0xcc, 0x12, 0x58,
- 0x59, 0x4d, 0x96, 0xfc, 0xe1, 0x93, 0xb8, 0x60 },
- { 0xfd, 0x9c, 0xfe, 0x14, 0xda, 0xd8, 0x97, 0x8c,
- 0x5b, 0xc8, 0x88, 0x93, 0x8f, 0x16, 0xf3, 0xb3,
- 0x98, 0xf7, 0x63, 0xa3, 0xad, 0xaf, 0xaa, 0x4a,
- 0xd9, 0x41, 0xb7, 0xe3, 0x87, 0xeb, 0x4f, 0x4a },
- { 0xfd, 0xed, 0x92, 0xcb, 0x40, 0x91, 0x66, 0x82,
- 0x3a, 0x35, 0xe2, 0x17, 0xf3, 0x0b, 0x38, 0xc4,
- 0x86, 0xf8, 0x3e, 0xf2, 0xd4, 0xf2, 0x7b, 0x05,
- 0xf1, 0x8c, 0x74, 0x49, 0x81, 0x33, 0x9a, 0x1c },
- { 0xfe, 0x26, 0xb2, 0xa6, 0x45, 0xa3, 0x1a, 0x91,
- 0x11, 0x00, 0x09, 0x9a, 0xa9, 0xa2, 0x93, 0x9f,
- 0x49, 0xe9, 0xfb, 0xea, 0x64, 0x48, 0x7b, 0xdf,
- 0x68, 0xa5, 0x23, 0x70, 0x32, 0x92, 0xd6, 0xa0 },
- { 0xfe, 0x42, 0x1b, 0x24, 0x4e, 0x0e, 0x81, 0x6d,
- 0x9f, 0x26, 0xb3, 0x52, 0xc8, 0x31, 0xd9, 0x30,
- 0xe1, 0xc1, 0xc5, 0xd2, 0xfa, 0x4e, 0x0a, 0x1c,
- 0x77, 0x96, 0xa1, 0xf2, 0x02, 0x0e, 0xf1, 0x67 },
- { 0xfe, 0x4f, 0x35, 0x6c, 0x7f, 0x9b, 0xfc, 0x17,
- 0xff, 0xcb, 0x68, 0xd0, 0x76, 0x4e, 0xcb, 0x2a,
- 0x87, 0xca, 0xa0, 0xae, 0x4c, 0xb5, 0x66, 0x62,
- 0x21, 0x04, 0xd3, 0x6f, 0xfb, 0x52, 0xcb, 0x29 },
- { 0xff, 0x82, 0x6e, 0x2d, 0x0c, 0xb7, 0x71, 0x68,
- 0x68, 0x67, 0x5a, 0xe4, 0xb4, 0x31, 0xb6, 0x37,
- 0x1e, 0x9f, 0x0c, 0xdf, 0xcc, 0xb4, 0x9d, 0x43,
- 0xba, 0x30, 0x49, 0xbf, 0xdd, 0x2c, 0x41, 0xb1 },
- { 0xff, 0xdc, 0x6b, 0x85, 0xfe, 0x7b, 0x10, 0x83,
- 0xb5, 0x41, 0x6f, 0x80, 0x6f, 0xc2, 0x44, 0xb9,
- 0xe4, 0xdf, 0x42, 0x99, 0xfb, 0xe3, 0xf6, 0x81,
- 0xaf, 0x3f, 0x5c, 0xf4, 0x22, 0x5a, 0x8e, 0xaf },
-};
-
-// SHA-256 hashes of leaf certificates issued by CNNIC's EV root.
-const uint8_t kCNNICEVWhitelist[][crypto::kSHA256Length] = {
- { 0xb5, 0xef, 0x42, 0xc4, 0xbc, 0xed, 0xf1, 0x7b,
- 0xec, 0xc7, 0x5b, 0xf4, 0x63, 0x66, 0x49, 0xce,
- 0xbf, 0xf8, 0x71, 0x1b, 0xce, 0xff, 0xfa, 0x69,
- 0x5c, 0xc2, 0x52, 0xfa, 0x57, 0x4d, 0x42, 0x18 },
- { 0xb6, 0x82, 0x3c, 0x9d, 0xbc, 0x8e, 0x8c, 0x05,
- 0x4b, 0xcf, 0x60, 0xf2, 0x38, 0x21, 0xac, 0x6c,
- 0x58, 0x19, 0x73, 0x51, 0xea, 0xcf, 0xa5, 0x57,
- 0x4c, 0xf0, 0x41, 0xb4, 0xce, 0x6b, 0x84, 0x04 },
- { 0xdf, 0x69, 0xf9, 0x6a, 0x85, 0x67, 0x8f, 0x6c,
- 0xaf, 0x3f, 0xde, 0x25, 0xec, 0xfb, 0x5d, 0xf4,
- 0x74, 0x70, 0x87, 0xc2, 0xaf, 0x3b, 0x00, 0x65,
- 0xfb, 0x15, 0x10, 0x55, 0xcb, 0xcb, 0xa8, 0xc1 },
- { 0xee, 0x0c, 0xf6, 0x2b, 0x9d, 0x8e, 0x42, 0xa2,
- 0x23, 0xb9, 0xa9, 0x60, 0xb5, 0xe9, 0x67, 0x0c,
- 0xcc, 0x34, 0x6d, 0x89, 0x93, 0x8f, 0xfa, 0x5d,
- 0xf7, 0x98, 0x65, 0xe4, 0x13, 0xd6, 0x31, 0x54 },
-};
-
-const PublicKeyWhitelist kBuiltinWhitelist[] = {
- // C=CN, O=China Internet Network Information Center,
- // CN=China Internet Network Information Center EV Certificates Root
- // Expires: August 31 2030.
- { { 0x9d, 0xd5, 0x5f, 0xc5, 0x73, 0xf5, 0x46, 0xcb,
- 0x6a, 0x38, 0x31, 0xd1, 0x11, 0x2d, 0x87, 0x10,
- 0xa6, 0xf4, 0xf8, 0x2d, 0xc8, 0x7f, 0x5f, 0xae,
- 0x9d, 0x3a, 0x1a, 0x02, 0x8d, 0xd3, 0x6e, 0x4b },
- kCNNICEVWhitelist, arraysize(kCNNICEVWhitelist)
- },
- // C=CN, O=CNNIC, CN=CNNIC ROOT
- // Expires: April 16 2027.
- { { 0x1f, 0x42, 0x24, 0xce, 0xc8, 0x4f, 0xc9, 0x9c,
- 0xed, 0x88, 0x1f, 0xf6, 0xfc, 0xfd, 0x3e, 0x21,
- 0xf8, 0xc5, 0x19, 0xc5, 0x47, 0xaa, 0x6a, 0x5d,
- 0xd3, 0xde, 0x24, 0x73, 0x02, 0xce, 0x50, 0xd1 },
- kCNNICDVWhitelist, arraysize(kCNNICDVWhitelist)
- },
-};
// clang-format on
-const size_t kBuiltinWhitelistSize = arraysize(kBuiltinWhitelist);
-
-const PublicKeyWhitelist* g_whitelist = kBuiltinWhitelist;
-size_t g_whitelist_size = kBuiltinWhitelistSize;
-
-// Comparator to compare a SHA256HashValue with a uint8_t array containing a
-// raw SHA-256 hash. Return value follows memcmp semantics.
-int CompareSHA256HashValueToRawHash(const void* key, const void* element) {
- const SHA256HashValue* search_key =
- reinterpret_cast<const SHA256HashValue*>(key);
- return memcmp(search_key->data, element, sizeof(search_key->data));
-}
// Comparator to compare a (SHA-256) HashValue with a uint8_t array containing
// a raw SHA-256 hash. Return value follows memcmp semantics.
@@ -1652,55 +56,74 @@ int CompareHashValueToRawHash(const void* key, const void* element) {
return memcmp(search_key->data(), element, search_key->size());
}
+namespace wosign {
+#include "net/data/ssl/wosign/wosign_domains-inc.cc"
} // namespace
-bool IsNonWhitelistedCertificate(const X509Certificate& cert,
- const HashValueVector& public_key_hashes) {
- // 2016-10-21 00:00:00 UTC
- const base::Time last_wosign_cert =
- base::Time::UnixEpoch() + base::TimeDelta::FromSeconds(1477008000);
+} // namespace
+bool IsNonWhitelistedCertificate(const X509Certificate& cert,
+ const HashValueVector& public_key_hashes,
+ base::StringPiece hostname) {
for (const auto& hash : public_key_hashes) {
if (hash.tag != HASH_VALUE_SHA256)
continue;
// Check for WoSign/StartCom certificates.
if (bsearch(&hash, kWosignKeys, arraysize(kWosignKeys),
- crypto::kSHA256Length, CompareHashValueToRawHash) != nullptr &&
- (cert.valid_start().is_null() || cert.valid_start().is_max() ||
- cert.valid_start() > last_wosign_cert)) {
- return true;
- }
-
- // Check the public key whitelist.
- for (size_t i = 0; i < g_whitelist_size; ++i) {
- if (memcmp(hash.data(), g_whitelist[i].public_key,
- crypto::kSHA256Length) != 0) {
- continue;
+ crypto::kSHA256Length, CompareHashValueToRawHash) != nullptr) {
+ // 2016-10-21 00:00:00 UTC
+ const base::Time last_wosign_cert =
+ base::Time::UnixEpoch() + base::TimeDelta::FromSeconds(1477008000);
+
+ // Don't allow new certificates.
+ if (cert.valid_start().is_null() || cert.valid_start().is_max() ||
+ cert.valid_start() > last_wosign_cert) {
+ return true;
}
- const SHA256HashValue leaf_hash =
- X509Certificate::CalculateFingerprint256(cert.os_cert_handle());
- void* result = bsearch(
- &leaf_hash, g_whitelist[i].whitelist, g_whitelist[i].whitelist_size,
- crypto::kSHA256Length, CompareSHA256HashValueToRawHash);
- if (result == nullptr)
- return true; // Hash was not found on the public key whitelist.
- break;
+
+ // Don't allow certificates from non-whitelisted hosts.
+ return !IsWhitelistedHost(wosign::kDafsa, arraysize(wosign::kDafsa),
+ hostname);
}
}
return false;
}
-void SetCertificateWhitelistForTesting(const PublicKeyWhitelist* whitelist,
- size_t whitelist_size) {
- if (whitelist == nullptr || whitelist_size == 0) {
- g_whitelist = kBuiltinWhitelist;
- g_whitelist_size = kBuiltinWhitelistSize;
- return;
+bool IsWhitelistedHost(const unsigned char* graph,
+ size_t graph_length,
+ base::StringPiece host) {
+ if (host.empty())
+ return false;
+
+ size_t end = host.length();
+
+ // Skip trailing '.', if any.
+ if (host[end - 1] == '.') {
+ --end;
+ }
+
+ // Reverse through each of the domain components, trying to see if the
+ // domain is on the whitelist. For example, the string
+ // "www.domain.example.com" would be processed by first searching
+ // for "com", then "example.com", then "domain.example.com". The
+ // loop will terminate when there are no more distinct label separators,
+ // and thus the final check for "www.domain.example.com".
+ size_t start = end;
+ while (start != 0 &&
+ (start = host.rfind('.', start - 1)) != base::StringPiece::npos) {
+ const char* domain_str = host.data() + start + 1;
+ size_t domain_length = end - start - 1;
+ if (domain_length == 0)
+ return false;
+ if (LookupStringInFixedSet(graph, graph_length, domain_str,
+ domain_length) != kDafsaNotFound) {
+ return true;
+ }
}
- g_whitelist = whitelist;
- g_whitelist_size = whitelist_size;
+ return LookupStringInFixedSet(graph, graph_length, host.data(), end) !=
+ kDafsaNotFound;
}
} // namespace net
diff --git a/chromium/net/cert/cert_verify_proc_whitelist.h b/chromium/net/cert/cert_verify_proc_whitelist.h
index 47ce9831848..2c7dfd5bda1 100644
--- a/chromium/net/cert/cert_verify_proc_whitelist.h
+++ b/chromium/net/cert/cert_verify_proc_whitelist.h
@@ -8,6 +8,7 @@
#include <stddef.h>
#include <stdint.h>
+#include "base/strings/string_piece.h"
#include "crypto/sha2.h"
#include "net/base/hash_value.h"
#include "net/base/net_export.h"
@@ -16,32 +17,26 @@ namespace net {
class X509Certificate;
-// PublicKeyWhitelist contains a SHA-256 SPKI hash and a pointer to an array
-// of SHA-256 certificate hashes that have been publicly disclosed and
-// whitelisted.
-struct PublicKeyWhitelist {
- uint8_t public_key[crypto::kSHA256Length];
- const uint8_t (*whitelist)[crypto::kSHA256Length];
- size_t whitelist_size;
-};
-
// Returns true if |cert| has been issued by a CA that is constrained from
// issuing new certificates and |cert| is not within the whitelist of
// existing certificates. Returns false if |cert| was issued by an
// unconstrained CA or if it was in the whitelist for that
// CA.
// |cert| should be the verified certificate chain, with |public_key_hashes|
-// being the set of hashes of the SPKIs within the verified chain.
+// being the set of hashes of the SPKIs within the verified chain, and
+// |hostname| as the GURL-normalized hostname.
bool NET_EXPORT_PRIVATE
IsNonWhitelistedCertificate(const X509Certificate& cert,
- const HashValueVector& public_key_hashes);
+ const HashValueVector& public_key_hashes,
+ base::StringPiece hostname);
-// Sets the certificate whitelist for testing. Supply nullptr/0 to reset to
-// the built-in whitelist.
-void NET_EXPORT_PRIVATE
-SetCertificateWhitelistForTesting(const PublicKeyWhitelist* whitelist,
- size_t whitelist_size);
+// Returns true if |host| is in (or a subdomain of) a whitelisted host
+// in |graph|, which is a DAFSA constructed by
+// //net/tools/dafsa/make_dafsa.py that is |graph_length| bytes long.
+bool NET_EXPORT_PRIVATE IsWhitelistedHost(const unsigned char* graph,
+ size_t graph_length,
+ base::StringPiece host);
} // namespace net
-#endif // NET_CERT_CERT_VERIFY_PROC_WHITELIST
+#endif // NET_CERT_CERT_VERIFY_PROC_WHITELIST_H_
diff --git a/chromium/net/cert/cert_verify_proc_whitelist_unittest.cc b/chromium/net/cert/cert_verify_proc_whitelist_unittest.cc
index 791957315a6..1ad6a1c5316 100644
--- a/chromium/net/cert/cert_verify_proc_whitelist_unittest.cc
+++ b/chromium/net/cert/cert_verify_proc_whitelist_unittest.cc
@@ -14,177 +14,16 @@ namespace net {
namespace {
-HashValue GetTestHashValue(uint8_t label, HashValueTag tag) {
- HashValue hash_value(tag);
- memset(hash_value.data(), label, hash_value.size());
- return hash_value;
-}
-
-HashValueVector GetFakeHashValues() {
- HashValueVector public_key_hashes;
-
- // Fake "root" hash
- public_key_hashes.push_back(GetTestHashValue(0x00, HASH_VALUE_SHA256));
- public_key_hashes.push_back(GetTestHashValue(0x01, HASH_VALUE_SHA1));
- // Fake "intermediate" hash
- public_key_hashes.push_back(GetTestHashValue(0x02, HASH_VALUE_SHA256));
- public_key_hashes.push_back(GetTestHashValue(0x03, HASH_VALUE_SHA1));
- // Fake "leaf" hash
- public_key_hashes.push_back(GetTestHashValue(0x04, HASH_VALUE_SHA256));
- public_key_hashes.push_back(GetTestHashValue(0x05, HASH_VALUE_SHA1));
-
- return public_key_hashes;
-}
-
-// The SHA-256 hash of the leaf cert "ok_cert.pem"; obtainable either
-// via X509Certificate::CalculateFingerprint256 or
-// openssl x509 -inform pem -in ok_cert.pem -outform der | openssl
-// dgst -sha256 -c
-const uint8_t kWhitelistCerts[][crypto::kSHA256Length] = {
- /* clang-format off */
- { 0xf4, 0x42, 0xdd, 0x66, 0xfa, 0x10, 0x70, 0x65,
- 0xd1, 0x7e, 0xd9, 0xbb, 0x7c, 0xa9, 0x3c, 0x79,
- 0x63, 0xbe, 0x01, 0xa7, 0x54, 0x18, 0xab, 0x2f,
- 0xc3, 0x9a, 0x14, 0x53, 0xc3, 0x83, 0xa0, 0x5a },
- /* clang-format on */
-};
-
-TEST(CertVerifyProcWhitelistTest, AcceptsWhitelistedEEByRoot) {
- scoped_refptr<X509Certificate> cert =
- ImportCertFromFile(GetTestCertsDirectory(), "ok_cert.pem");
- ASSERT_TRUE(cert);
-
- // clang-format off
- const PublicKeyWhitelist kWhitelist[] = {
- { { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
- kWhitelistCerts, arraysize(kWhitelistCerts)
- },
- };
- // clang-format on
-
- SetCertificateWhitelistForTesting(kWhitelist, arraysize(kWhitelist));
-
- HashValueVector public_key_hashes = GetFakeHashValues();
-
- // Should return false, indicating this cert is acceptable because of
- // it being whitelisted.
- EXPECT_FALSE(IsNonWhitelistedCertificate(*cert, public_key_hashes));
-
- SetCertificateWhitelistForTesting(nullptr, 0);
-}
-
-TEST(CertVerifyProcWhitelistTest, AcceptsWhitelistedEEByIntermediate) {
- scoped_refptr<X509Certificate> cert =
- ImportCertFromFile(GetTestCertsDirectory(), "ok_cert.pem");
- ASSERT_TRUE(cert);
-
- // clang-format off
- const PublicKeyWhitelist kWhitelist[] = {
- { { 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02,
- 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02,
- 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02,
- 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02 },
- kWhitelistCerts, arraysize(kWhitelistCerts)
- },
- };
- // clang-format on
-
- SetCertificateWhitelistForTesting(kWhitelist, arraysize(kWhitelist));
-
- HashValueVector public_key_hashes = GetFakeHashValues();
-
- // Should return false, indicating this cert is acceptable because of
- // it being whitelisted.
- EXPECT_FALSE(IsNonWhitelistedCertificate(*cert, public_key_hashes));
-
- SetCertificateWhitelistForTesting(nullptr, 0);
-}
-
-TEST(CertVerifyProcWhitelistTest, RejectsNonWhitelistedEE) {
- scoped_refptr<X509Certificate> cert =
- ImportCertFromFile(GetTestCertsDirectory(), "expired_cert.pem");
- ASSERT_TRUE(cert);
-
- // clang-format off
- const PublicKeyWhitelist kWhitelist[] = {
- { { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
- kWhitelistCerts, arraysize(kWhitelistCerts)
- },
- };
- // clang-format on
-
- SetCertificateWhitelistForTesting(kWhitelist, arraysize(kWhitelist));
-
- HashValueVector public_key_hashes = GetFakeHashValues();
-
- // Should return true, indicating this certificate chains to a constrained
- // root and is not whitelisted.
- EXPECT_TRUE(IsNonWhitelistedCertificate(*cert, public_key_hashes));
-
- SetCertificateWhitelistForTesting(nullptr, 0);
-}
-
-TEST(CertVerifyProcWhitelistTest, RejectsNonWhitelistedEEByIntermediate) {
- scoped_refptr<X509Certificate> cert =
- ImportCertFromFile(GetTestCertsDirectory(), "expired_cert.pem");
- ASSERT_TRUE(cert);
-
- // clang-format off
- const PublicKeyWhitelist kWhitelist[] = {
- { { 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02,
- 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02,
- 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02,
- 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02 },
- kWhitelistCerts, arraysize(kWhitelistCerts)
- },
- };
- // clang-format on
-
- SetCertificateWhitelistForTesting(kWhitelist, arraysize(kWhitelist));
-
- HashValueVector public_key_hashes = GetFakeHashValues();
-
- // Should return true, indicating this certificate chains to a constrained
- // root and is not whitelisted.
- EXPECT_TRUE(IsNonWhitelistedCertificate(*cert, public_key_hashes));
-
- SetCertificateWhitelistForTesting(nullptr, 0);
-}
-
-TEST(CertVerifyProcWhitelistTest, AcceptsUnconstrainedLeaf) {
- scoped_refptr<X509Certificate> cert =
- ImportCertFromFile(GetTestCertsDirectory(), "ok_cert.pem");
- ASSERT_TRUE(cert);
-
- // clang-format off
- const PublicKeyWhitelist kWhitelist[] = {
- { { 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10,
- 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10,
- 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10,
- 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10 },
- kWhitelistCerts, arraysize(kWhitelistCerts)
- },
- };
- // clang-format on
-
- SetCertificateWhitelistForTesting(kWhitelist, arraysize(kWhitelist));
-
- HashValueVector public_key_hashes = GetFakeHashValues();
-
- // Should return false, because the chain (as indicated by
- // public_key_hashes) is not constrained.
- EXPECT_FALSE(IsNonWhitelistedCertificate(*cert, public_key_hashes));
-
- SetCertificateWhitelistForTesting(nullptr, 0);
-}
+namespace test1 {
+#include "net/cert/cert_verify_proc_whitelist_unittest1-inc.cc"
+} // namespace test
TEST(CertVerifyProcWhitelistTest, HandlesWosignCerts) {
+ // The domain must be in the whitelist from
+ // //net/data/ssl/wosign/wosign_domains.gperf
+ const char kWhitelistedDomain[] = "005.tv";
+ const char kNonWhitelistedDomain[] = "006.tv";
+
scoped_refptr<X509Certificate> cert =
ImportCertFromFile(GetTestCertsDirectory(), "wosign_before_oct_21.pem");
ASSERT_TRUE(cert);
@@ -195,12 +34,68 @@ TEST(CertVerifyProcWhitelistTest, HandlesWosignCerts) {
0x95, 0xa5, 0x99, 0x68, 0xce, 0xf2, 0x34, 0x77, 0x37, 0x79, 0xdf,
0x51, 0x81, 0xcf, 0x10, 0xfa, 0x64, 0x75, 0x34, 0xbb, 0x65}});
- EXPECT_FALSE(IsNonWhitelistedCertificate(*cert, public_key_hashes));
+ // Domains on the whitelist are allowed, as long as their certificates were
+ // pre-existing before Oct 21, 2016.
+ EXPECT_FALSE(IsNonWhitelistedCertificate(*cert, public_key_hashes,
+ kWhitelistedDomain));
+ // Domains not on the whitelist are not allowed, regardless of the validity
+ // period of the certificate.
+ EXPECT_TRUE(IsNonWhitelistedCertificate(*cert, public_key_hashes,
+ kNonWhitelistedDomain));
cert = ImportCertFromFile(GetTestCertsDirectory(), "wosign_after_oct_21.pem");
ASSERT_TRUE(cert);
- EXPECT_TRUE(IsNonWhitelistedCertificate(*cert, public_key_hashes));
+ // No new certificates (after Oct 21, 2016) are all allowed, regardless
+ // of the domain.
+ EXPECT_TRUE(IsNonWhitelistedCertificate(*cert, public_key_hashes,
+ kWhitelistedDomain));
+ EXPECT_TRUE(IsNonWhitelistedCertificate(*cert, public_key_hashes,
+ kNonWhitelistedDomain));
+
+ // Certificates that aren't issued by WoSign are allowed, regardless of
+ // domain.
+ public_key_hashes[0].data()[0] = 0x14;
+ EXPECT_FALSE(IsNonWhitelistedCertificate(*cert, public_key_hashes,
+ kWhitelistedDomain));
+ EXPECT_FALSE(IsNonWhitelistedCertificate(*cert, public_key_hashes,
+ kNonWhitelistedDomain));
+}
+
+TEST(CertVerifyProcWhitelistTest, IsWhitelistedHost) {
+ const unsigned char* graph = test1::kDafsa;
+ size_t graph_size = arraysize(test1::kDafsa);
+
+ // Test malformed inputs.
+ EXPECT_FALSE(IsWhitelistedHost(graph, graph_size, ""));
+ EXPECT_FALSE(IsWhitelistedHost(graph, graph_size, "."));
+ EXPECT_FALSE(IsWhitelistedHost(graph, graph_size, ".."));
+
+ // Make sure that TLDs aren't accepted just because a subdomain is.
+ EXPECT_FALSE(IsWhitelistedHost(graph, graph_size, "com"));
+
+ // Test various forms of domain names that GURL will accept for entries in
+ // the graph.
+ EXPECT_TRUE(IsWhitelistedHost(graph, graph_size, "example.com"));
+ EXPECT_TRUE(IsWhitelistedHost(graph, graph_size, "subdomain.example.com"));
+ EXPECT_TRUE(IsWhitelistedHost(graph, graph_size, ".subdomain.example.com"));
+ EXPECT_TRUE(IsWhitelistedHost(graph, graph_size, "example.com."));
+ EXPECT_TRUE(IsWhitelistedHost(graph, graph_size, ".example.com."));
+ EXPECT_TRUE(IsWhitelistedHost(graph, graph_size, "www.example.bar.jp"));
+
+ // Test various prefix/suffices of entries in the graph, but that aren't
+ // themselves domain matches.
+ EXPECT_FALSE(IsWhitelistedHost(graph, graph_size, "anotherexample.com"));
+ EXPECT_FALSE(IsWhitelistedHost(graph, graph_size, "bar.jp"));
+ EXPECT_FALSE(IsWhitelistedHost(graph, graph_size, "example.bar.jp.junk"));
+ EXPECT_FALSE(IsWhitelistedHost(graph, graph_size, "foo.example.bar.jp.junk"));
+
+ // Test various forms of domain names that GURL will accept for entries not
+ // in the graph.
+ EXPECT_FALSE(IsWhitelistedHost(graph, graph_size, "domain.com"));
+ EXPECT_FALSE(IsWhitelistedHost(graph, graph_size, "example..com"));
+ EXPECT_FALSE(IsWhitelistedHost(graph, graph_size, "www.co.uk"));
+ EXPECT_FALSE(IsWhitelistedHost(graph, graph_size, "www..co.uk"));
}
} // namespace
diff --git a/chromium/net/cert/cert_verify_proc_whitelist_unittest1.gperf b/chromium/net/cert/cert_verify_proc_whitelist_unittest1.gperf
new file mode 100644
index 00000000000..cfe582aa6f7
--- /dev/null
+++ b/chromium/net/cert/cert_verify_proc_whitelist_unittest1.gperf
@@ -0,0 +1,9 @@
+%{
+// Copyright (c) 2017 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.
+%}
+%%
+example.com, 0
+example.bar.jp, 0
+%%
diff --git a/chromium/net/cert/cert_verify_proc_win.cc b/chromium/net/cert/cert_verify_proc_win.cc
index a13117a7a8e..373b43cbe8e 100644
--- a/chromium/net/cert/cert_verify_proc_win.cc
+++ b/chromium/net/cert/cert_verify_proc_win.cc
@@ -363,27 +363,6 @@ void GetCertChainInfo(PCCERT_CHAIN_CONTEXT chain_context,
} else {
verified_chain.push_back(cert);
}
-
- const char* algorithm = cert->pCertInfo->SignatureAlgorithm.pszObjId;
- if (strcmp(algorithm, szOID_RSA_MD5RSA) == 0) {
- // md5WithRSAEncryption: 1.2.840.113549.1.1.4
- verify_result->has_md5 = true;
- } else if (strcmp(algorithm, szOID_RSA_MD2RSA) == 0) {
- // md2WithRSAEncryption: 1.2.840.113549.1.1.2
- verify_result->has_md2 = true;
- } else if (strcmp(algorithm, szOID_RSA_MD4RSA) == 0) {
- // md4WithRSAEncryption: 1.2.840.113549.1.1.3
- verify_result->has_md4 = true;
- } else if (strcmp(algorithm, szOID_RSA_SHA1RSA) == 0 ||
- strcmp(algorithm, szOID_X957_SHA1DSA) == 0 ||
- strcmp(algorithm, szOID_ECDSA_SHA1) == 0) {
- // sha1WithRSAEncryption: 1.2.840.113549.1.1.5
- // id-dsa-with-sha1: 1.2.840.10040.4.3
- // ecdsa-with-SHA1: 1.2.840.10045.4.1
- verify_result->has_sha1 = true;
- if (i == 0)
- verify_result->has_sha1_leaf = true;
- }
}
if (verified_cert) {
diff --git a/chromium/net/cert/cert_verify_result.cc b/chromium/net/cert/cert_verify_result.cc
index b1054e4ced3..4b605165d60 100644
--- a/chromium/net/cert/cert_verify_result.cc
+++ b/chromium/net/cert/cert_verify_result.cc
@@ -36,7 +36,8 @@ void CertVerifyResult::Reset() {
}
bool CertVerifyResult::operator==(const CertVerifyResult& other) const {
- return verified_cert->Equals(other.verified_cert.get()) &&
+ return (!!verified_cert == !!other.verified_cert) &&
+ (!verified_cert || verified_cert->Equals(other.verified_cert.get())) &&
std::tie(cert_status, has_md2, has_md4, has_md5, has_sha1,
has_sha1_leaf, public_key_hashes, is_issued_by_known_root,
is_issued_by_additional_trust_anchor,
diff --git a/chromium/net/cert/cert_verify_result.h b/chromium/net/cert/cert_verify_result.h
index 29c0675af3f..176c4ca50ed 100644
--- a/chromium/net/cert/cert_verify_result.h
+++ b/chromium/net/cert/cert_verify_result.h
@@ -28,12 +28,22 @@ class NET_EXPORT CertVerifyResult {
bool operator==(const CertVerifyResult& other) const;
- // The certificate and chain that was constructed during verification.
- // Note that the though the verified certificate will match the originally
- // supplied certificate, the intermediate certificates stored within may
- // be substantially different. In the event of a verification failure, this
- // will contain the chain as supplied by the server. This may be NULL if
- // running within the sandbox.
+ // The certificate chain that was constructed during verification.
+ //
+ // Note: Although |verified_cert| will match the originally supplied
+ // certificate to be validated, the results of GetIntermediateCertificates()
+ // may be substantially different, both in order and in content, then the
+ // originally supplied intermediates.
+ //
+ // In the event of validation failures, this may contain the originally
+ // supplied certificate chain or a partially constructed path, depending on
+ // the implementation.
+ //
+ // In the event of validation success, the trust anchor will be
+ // |verified_cert->GetIntermediateCertificates().back()| if
+ // there was a certificate chain to the trust anchor, and will
+ // be |verified_cert->os_cert_handle()| if the certificate was
+ // the trust anchor.
scoped_refptr<X509Certificate> verified_cert;
// Bitmask of CERT_STATUS_* from net/cert/cert_status_flags.h. Note that
@@ -42,7 +52,8 @@ class NET_EXPORT CertVerifyResult {
// chain.
CertStatus cert_status;
- // Properties of the certificate chain.
+ // Hash algorithms used by the certificate chain, excluding the trust
+ // anchor.
bool has_md2;
bool has_md4;
bool has_md5;
diff --git a/chromium/net/cert/crl_set_storage.cc b/chromium/net/cert/crl_set_storage.cc
index a4e3fd122cd..007cf3c1f47 100644
--- a/chromium/net/cert/crl_set_storage.cc
+++ b/chromium/net/cert/crl_set_storage.cc
@@ -14,6 +14,7 @@
#include "base/trace_event/trace_event.h"
#include "base/values.h"
#include "crypto/sha2.h"
+#include "net/base/trace_constants.h"
#include "third_party/zlib/zlib.h"
namespace net {
@@ -132,7 +133,7 @@ static base::DictionaryValue* ReadHeader(base::StringPiece* data) {
if (header.get() == NULL)
return NULL;
- if (!header->IsType(base::Value::TYPE_DICTIONARY))
+ if (!header->IsType(base::Value::Type::DICTIONARY))
return NULL;
return static_cast<base::DictionaryValue*>(header.release());
}
@@ -294,7 +295,7 @@ static bool ReadDeltaCRL(base::StringPiece* data,
// static
bool CRLSetStorage::Parse(base::StringPiece data,
scoped_refptr<CRLSet>* out_crl_set) {
- TRACE_EVENT0("net", "CRLSetStorage::Parse");
+ TRACE_EVENT0(kNetTracingCategory, "CRLSetStorage::Parse");
// Other parts of Chrome assume that we're little endian, so we don't lose
// anything by doing this.
#if defined(__BYTE_ORDER)
diff --git a/chromium/net/cert/ct_known_logs.cc b/chromium/net/cert/ct_known_logs.cc
index a65988971ed..cca1fbefcef 100644
--- a/chromium/net/cert/ct_known_logs.cc
+++ b/chromium/net/cert/ct_known_logs.cc
@@ -92,4 +92,3 @@ bool IsLogDisqualified(base::StringPiece log_id,
} // namespace ct
} // namespace net
-
diff --git a/chromium/net/cert/ct_known_logs_static-inc.h b/chromium/net/cert/ct_known_logs_static-inc.h
index 7ead66cc559..87961b92403 100644
--- a/chromium/net/cert/ct_known_logs_static-inc.h
+++ b/chromium/net/cert/ct_known_logs_static-inc.h
@@ -4,21 +4,21 @@
struct CTLogInfo {
// The DER-encoded SubjectPublicKeyInfo for the log.
- const char* const log_key;
+ const char* log_key;
// The length, in bytes, of |log_key|.
- const size_t log_key_length;
+ size_t log_key_length;
// The user-friendly log name.
// Note: This will not be translated.
- const char* const log_name;
+ const char* log_name;
// The HTTPS API endpoint for the log.
// Note: Trailing slashes should be included.
- const char* const log_url;
+ const char* log_url;
// The DNS API endpoint for the log.
// This is used as the parent domain for all queries about the log.
// If empty, CT DNS queries are not supported for the log. This will prevent
// retrieval of inclusion proofs over DNS for SCTs from the log.
// https://github.com/google/certificate-transparency-rfcs/blob/master/dns/draft-ct-over-dns.md.
- const char* const log_dns_domain;
+ const char* log_dns_domain;
};
// The set of all presently-qualifying CT logs.
diff --git a/chromium/net/cert/ct_log_response_parser.cc b/chromium/net/cert/ct_log_response_parser.cc
index 5baf1b33534..b6067d14f38 100644
--- a/chromium/net/cert/ct_log_response_parser.cc
+++ b/chromium/net/cert/ct_log_response_parser.cc
@@ -4,10 +4,11 @@
#include "net/cert/ct_log_response_parser.h"
+#include <memory>
+
#include "base/base64.h"
#include "base/json/json_value_converter.h"
#include "base/logging.h"
-#include "base/memory/scoped_vector.h"
#include "base/strings/string_piece.h"
#include "base/time/time.h"
#include "base/values.h"
@@ -105,7 +106,7 @@ bool IsJsonSTHStructurallyValid(const JsonSignedTreeHead& sth) {
// Structure for making JSON decoding easier. The string fields
// are base64-encoded so will require further decoding.
struct JsonConsistencyProof {
- ScopedVector<std::string> proof_nodes;
+ std::vector<std::unique_ptr<std::string>> proof_nodes;
static void RegisterJSONConverter(
base::JSONValueConverter<JsonConsistencyProof>* converter);
@@ -170,7 +171,7 @@ bool FillConsistencyProof(const base::Value& json_consistency_proof,
}
consistency_proof->reserve(parsed_proof.proof_nodes.size());
- for (std::string* proof_node : parsed_proof.proof_nodes) {
+ for (const auto& proof_node : parsed_proof.proof_nodes) {
consistency_proof->push_back(*proof_node);
}
diff --git a/chromium/net/cert/ct_log_response_parser_unittest.cc b/chromium/net/cert/ct_log_response_parser_unittest.cc
index 110a432aaa4..11006ec5ece 100644
--- a/chromium/net/cert/ct_log_response_parser_unittest.cc
+++ b/chromium/net/cert/ct_log_response_parser_unittest.cc
@@ -9,7 +9,6 @@
#include "base/base64.h"
#include "base/json/json_reader.h"
-#include "base/strings/stringprintf.h"
#include "base/time/time.h"
#include "base/values.h"
#include "net/cert/ct_serialization.h"
diff --git a/chromium/net/cert/ct_log_verifier_util.h b/chromium/net/cert/ct_log_verifier_util.h
index 9894afe59ea..2e62d1a7a3d 100644
--- a/chromium/net/cert/ct_log_verifier_util.h
+++ b/chromium/net/cert/ct_log_verifier_util.h
@@ -27,4 +27,4 @@ NET_EXPORT std::string HashNodes(const std::string& lh, const std::string& rh);
} // namespace net
-#endif
+#endif // NET_CERT_CT_LOG_VERIFIER_UTIL_H_
diff --git a/chromium/net/cert/ct_objects_extractor.cc b/chromium/net/cert/ct_objects_extractor.cc
index 4f451fdd1f2..1a6e6e4772d 100644
--- a/chromium/net/cert/ct_objects_extractor.cc
+++ b/chromium/net/cert/ct_objects_extractor.cc
@@ -252,7 +252,7 @@ bool GetX509LogEntry(X509Certificate::OSCertHandle leaf, LogEntry* result) {
bool ExtractSCTListFromOCSPResponse(X509Certificate::OSCertHandle issuer,
const std::string& cert_serial_number,
- const std::string& ocsp_response,
+ base::StringPiece ocsp_response,
std::string* sct_list) {
// The input is an OCSPResponse. See RFC2560, section 4.2.1. The SCT list is
// in the extensions field of the SingleResponse which matches the input
diff --git a/chromium/net/cert/ct_objects_extractor.h b/chromium/net/cert/ct_objects_extractor.h
index d8fc5f95e52..d5deb5b607e 100644
--- a/chromium/net/cert/ct_objects_extractor.h
+++ b/chromium/net/cert/ct_objects_extractor.h
@@ -7,6 +7,7 @@
#include <string>
+#include "base/strings/string_piece.h"
#include "net/base/net_export.h"
#include "net/cert/x509_certificate.h"
@@ -54,7 +55,7 @@ NET_EXPORT_PRIVATE bool GetX509LogEntry(X509Certificate::OSCertHandle leaf,
NET_EXPORT_PRIVATE bool ExtractSCTListFromOCSPResponse(
X509Certificate::OSCertHandle issuer,
const std::string& cert_serial_number,
- const std::string& ocsp_response,
+ base::StringPiece ocsp_response,
std::string* sct_list);
} // namespace ct
diff --git a/chromium/net/cert/ct_objects_extractor_unittest.cc b/chromium/net/cert/ct_objects_extractor_unittest.cc
index 7efec352535..8f8896938cd 100644
--- a/chromium/net/cert/ct_objects_extractor_unittest.cc
+++ b/chromium/net/cert/ct_objects_extractor_unittest.cc
@@ -44,8 +44,7 @@ class CTObjectsExtractorTest : public ::testing::Test {
std::vector<base::StringPiece> parsed_scts;
base::StringPiece sct_list_sp(sct_list);
// Make sure the SCT list can be decoded properly
- EXPECT_TRUE(DecodeSCTList(&sct_list_sp, &parsed_scts));
-
+ EXPECT_TRUE(DecodeSCTList(sct_list_sp, &parsed_scts));
EXPECT_TRUE(DecodeSignedCertificateTimestamp(&parsed_scts[0], sct));
}
diff --git a/chromium/net/cert/ct_policy_enforcer.h b/chromium/net/cert/ct_policy_enforcer.h
index c732cee6ff4..7111970e29d 100644
--- a/chromium/net/cert/ct_policy_enforcer.h
+++ b/chromium/net/cert/ct_policy_enforcer.h
@@ -2,8 +2,8 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#ifndef NET_CERT_CT_POLICY_ENFORCER_H
-#define NET_CERT_CT_POLICY_ENFORCER_H
+#ifndef NET_CERT_CT_POLICY_ENFORCER_H_
+#define NET_CERT_CT_POLICY_ENFORCER_H_
#include <stddef.h>
#include <vector>
@@ -105,4 +105,4 @@ class NET_EXPORT CTPolicyEnforcer {
} // namespace net
-#endif // NET_CERT_CT_POLICY_ENFORCER_H
+#endif // NET_CERT_CT_POLICY_ENFORCER_H_
diff --git a/chromium/net/cert/ct_policy_enforcer_unittest.cc b/chromium/net/cert/ct_policy_enforcer_unittest.cc
index 59544094c29..f30411c338b 100644
--- a/chromium/net/cert/ct_policy_enforcer_unittest.cc
+++ b/chromium/net/cert/ct_policy_enforcer_unittest.cc
@@ -85,11 +85,11 @@ class CTPolicyEnforcerTest : public ::testing::Test {
sct->log_id = std::string(crypto::kSHA256Length, static_cast<char>(i));
if (timestamp_past_enforcement_date) {
- sct->timestamp =
- base::Time::FromUTCExploded({2015, 8, 0, 15, 0, 0, 0, 0});
+ EXPECT_TRUE(base::Time::FromUTCExploded({2015, 8, 0, 15, 0, 0, 0, 0},
+ &sct->timestamp));
} else {
- sct->timestamp =
- base::Time::FromUTCExploded({2015, 6, 0, 15, 0, 0, 0, 0});
+ EXPECT_TRUE(base::Time::FromUTCExploded({2015, 6, 0, 15, 0, 0, 0, 0},
+ &sct->timestamp));
}
verified_scts->push_back(sct);
@@ -111,10 +111,11 @@ class CTPolicyEnforcerTest : public ::testing::Test {
sct->origin = desired_origin;
sct->log_id = std::string(kCertlyLogID, crypto::kSHA256Length);
if (timestamp_after_disqualification_date) {
- sct->timestamp =
- base::Time::FromUTCExploded({2016, 4, 0, 16, 0, 0, 0, 0});
+ EXPECT_TRUE(base::Time::FromUTCExploded({2016, 4, 0, 16, 0, 0, 0, 0},
+ &sct->timestamp));
} else {
- sct->timestamp = base::Time::FromUTCExploded({2016, 4, 0, 1, 0, 0, 0, 0});
+ EXPECT_TRUE(base::Time::FromUTCExploded({2016, 4, 0, 1, 0, 0, 0, 0},
+ &sct->timestamp));
}
verified_scts->push_back(sct);
@@ -130,6 +131,14 @@ class CTPolicyEnforcerTest : public ::testing::Test {
verified_scts);
}
+ base::Time CreateTime(const base::Time::Exploded& exploded) {
+ base::Time result;
+ if (!base::Time::FromUTCExploded(exploded, &result)) {
+ ADD_FAILURE() << "Failed FromUTCExploded";
+ }
+ return result;
+ }
+
protected:
std::unique_ptr<CTPolicyEnforcer> policy_enforcer_;
scoped_refptr<X509Certificate> chain_;
@@ -137,8 +146,15 @@ class CTPolicyEnforcerTest : public ::testing::Test {
std::string non_google_log_id_;
};
+#if defined(OS_ANDROID)
+#define MAYBE_DoesNotConformToCTEVPolicyNotEnoughDiverseSCTsAllGoogle \
+ DISABLED_DoesNotConformToCTEVPolicyNotEnoughDiverseSCTsAllGoogle
+#else
+#define MAYBE_DoesNotConformToCTEVPolicyNotEnoughDiverseSCTsAllGoogle \
+ DoesNotConformToCTEVPolicyNotEnoughDiverseSCTsAllGoogle
+#endif
TEST_F(CTPolicyEnforcerTest,
- DoesNotConformToCTEVPolicyNotEnoughDiverseSCTsAllGoogle) {
+ MAYBE_DoesNotConformToCTEVPolicyNotEnoughDiverseSCTsAllGoogle) {
ct::SCTList scts;
std::vector<std::string> desired_log_ids(2, google_log_id_);
@@ -443,38 +459,48 @@ TEST_F(CTPolicyEnforcerTest,
ASSERT_TRUE(private_key);
// Test multiple validity periods
+ base::Time time_2015_3_0_25_11_25_0_0 =
+ CreateTime({2015, 3, 0, 25, 11, 25, 0, 0});
+
+ base::Time time_2016_6_0_6_11_25_0_0 =
+ CreateTime({2016, 6, 0, 6, 11, 25, 0, 0});
+
+ base::Time time_2016_6_0_25_11_25_0_0 =
+ CreateTime({2016, 6, 0, 25, 11, 25, 0, 0});
+
+ base::Time time_2016_6_0_27_11_25_0_0 =
+ CreateTime({2016, 6, 0, 27, 11, 25, 0, 0});
+
+ base::Time time_2017_6_0_25_11_25_0_0 =
+ CreateTime({2017, 6, 0, 25, 11, 25, 0, 0});
+
+ base::Time time_2017_6_0_28_11_25_0_0 =
+ CreateTime({2017, 6, 0, 28, 11, 25, 0, 0});
+
+ base::Time time_2018_6_0_25_11_25_0_0 =
+ CreateTime({2018, 6, 0, 25, 11, 25, 0, 0});
+
+ base::Time time_2018_6_0_27_11_25_0_0 =
+ CreateTime({2018, 6, 0, 27, 11, 25, 0, 0});
+
const struct TestData {
base::Time validity_start;
base::Time validity_end;
size_t scts_required;
} kTestData[] = {{// Cert valid for 14 months, needs 2 SCTs.
- base::Time::FromUTCExploded({2015, 3, 0, 25, 11, 25, 0, 0}),
- base::Time::FromUTCExploded({2016, 6, 0, 6, 11, 25, 0, 0}),
- 2},
+ time_2015_3_0_25_11_25_0_0, time_2016_6_0_6_11_25_0_0, 2},
{// Cert valid for exactly 15 months, needs 3 SCTs.
- base::Time::FromUTCExploded({2015, 3, 0, 25, 11, 25, 0, 0}),
- base::Time::FromUTCExploded({2016, 6, 0, 25, 11, 25, 0, 0}),
- 3},
+ time_2015_3_0_25_11_25_0_0, time_2016_6_0_25_11_25_0_0, 3},
{// Cert valid for over 15 months, needs 3 SCTs.
- base::Time::FromUTCExploded({2015, 3, 0, 25, 11, 25, 0, 0}),
- base::Time::FromUTCExploded({2016, 6, 0, 27, 11, 25, 0, 0}),
- 3},
+ time_2015_3_0_25_11_25_0_0, time_2016_6_0_27_11_25_0_0, 3},
{// Cert valid for exactly 27 months, needs 3 SCTs.
- base::Time::FromUTCExploded({2015, 3, 0, 25, 11, 25, 0, 0}),
- base::Time::FromUTCExploded({2017, 6, 0, 25, 11, 25, 0, 0}),
- 3},
+ time_2015_3_0_25_11_25_0_0, time_2017_6_0_25_11_25_0_0, 3},
{// Cert valid for over 27 months, needs 4 SCTs.
- base::Time::FromUTCExploded({2015, 3, 0, 25, 11, 25, 0, 0}),
- base::Time::FromUTCExploded({2017, 6, 0, 28, 11, 25, 0, 0}),
- 4},
+ time_2015_3_0_25_11_25_0_0, time_2017_6_0_28_11_25_0_0, 4},
{// Cert valid for exactly 39 months, needs 4 SCTs.
- base::Time::FromUTCExploded({2015, 3, 0, 25, 11, 25, 0, 0}),
- base::Time::FromUTCExploded({2018, 6, 0, 25, 11, 25, 0, 0}),
- 4},
+ time_2015_3_0_25_11_25_0_0, time_2018_6_0_25_11_25_0_0, 4},
{// Cert valid for over 39 months, needs 5 SCTs.
- base::Time::FromUTCExploded({2015, 3, 0, 25, 11, 25, 0, 0}),
- base::Time::FromUTCExploded({2018, 6, 0, 27, 11, 25, 0, 0}),
- 5}};
+ time_2015_3_0_25_11_25_0_0, time_2018_6_0_27_11_25_0_0, 5}};
for (size_t i = 0; i < arraysize(kTestData); ++i) {
SCOPED_TRACE(i);
diff --git a/chromium/net/cert/ct_policy_status.h b/chromium/net/cert/ct_policy_status.h
index cc38585d6fa..c86e68100ed 100644
--- a/chromium/net/cert/ct_policy_status.h
+++ b/chromium/net/cert/ct_policy_status.h
@@ -2,8 +2,8 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#ifndef NET_CERT_CT_POLICY_STATUS_H
-#define NET_CERT_CT_POLICY_STATUS_H
+#ifndef NET_CERT_CT_POLICY_STATUS_H_
+#define NET_CERT_CT_POLICY_STATUS_H_
namespace net {
@@ -54,4 +54,4 @@ enum class EVPolicyCompliance {
} // namespace net
-#endif // NET_CERT_CT_POLICY_STATUS_H
+#endif // NET_CERT_CT_POLICY_STATUS_H_
diff --git a/chromium/net/cert/ct_serialization.cc b/chromium/net/cert/ct_serialization.cc
index 60d94263423..64a6ff5c5d0 100644
--- a/chromium/net/cert/ct_serialization.cc
+++ b/chromium/net/cert/ct_serialization.cc
@@ -383,15 +383,15 @@ void EncodeTreeHeadSignature(const SignedTreeHead& signed_tree_head,
output);
}
-bool DecodeSCTList(base::StringPiece* input,
+bool DecodeSCTList(base::StringPiece input,
std::vector<base::StringPiece>* output) {
std::vector<base::StringPiece> result;
- if (!ReadList(kSCTListLengthBytes, kSerializedSCTLengthBytes,
- input, &result)) {
+ if (!ReadList(kSCTListLengthBytes, kSerializedSCTLengthBytes, &input,
+ &result)) {
return false;
}
- if (!input->empty() || result.empty())
+ if (!input.empty() || result.empty())
return false;
output->swap(result);
return true;
diff --git a/chromium/net/cert/ct_serialization.h b/chromium/net/cert/ct_serialization.h
index 269892d3512..b5b3d77d69d 100644
--- a/chromium/net/cert/ct_serialization.h
+++ b/chromium/net/cert/ct_serialization.h
@@ -75,7 +75,7 @@ NET_EXPORT_PRIVATE void EncodeTreeHeadSignature(
// Returns true if the list could be read and decoded successfully, false
// otherwise (note that the validity of each individual SCT should be checked
// separately).
-NET_EXPORT_PRIVATE bool DecodeSCTList(base::StringPiece* input,
+NET_EXPORT_PRIVATE bool DecodeSCTList(base::StringPiece input,
std::vector<base::StringPiece>* output);
// Decodes a single SCT from |input| to |output|.
diff --git a/chromium/net/cert/ct_serialization_unittest.cc b/chromium/net/cert/ct_serialization_unittest.cc
index 6056ea3bcf1..6ddb329b7c4 100644
--- a/chromium/net/cert/ct_serialization_unittest.cc
+++ b/chromium/net/cert/ct_serialization_unittest.cc
@@ -141,7 +141,7 @@ TEST_F(CtSerializationTest, DecodesSCTList) {
base::StringPiece encoded("\x0\xa\x0\x3\x61\x62\x63\x0\x3\x64\x65\x66", 12);
std::vector<base::StringPiece> decoded;
- ASSERT_TRUE(ct::DecodeSCTList(&encoded, &decoded));
+ ASSERT_TRUE(ct::DecodeSCTList(encoded, &decoded));
ASSERT_STREQ("abc", decoded[0].data());
ASSERT_STREQ("def", decoded[1].data());
}
@@ -151,7 +151,7 @@ TEST_F(CtSerializationTest, FailsDecodingInvalidSCTList) {
base::StringPiece encoded("\x0\xa\x0\x3\x61\x62\x63\x0\x5\x64\x65\x66", 12);
std::vector<base::StringPiece> decoded;
- ASSERT_FALSE(ct::DecodeSCTList(&encoded, &decoded));
+ ASSERT_FALSE(ct::DecodeSCTList(encoded, &decoded));
}
TEST_F(CtSerializationTest, DecodesSignedCertificateTimestamp) {
@@ -259,4 +259,3 @@ TEST_F(CtSerializationTest, EncodesValidSignedTreeHead) {
}
} // namespace net
-
diff --git a/chromium/net/cert/ct_signed_certificate_timestamp_log_param.cc b/chromium/net/cert/ct_signed_certificate_timestamp_log_param.cc
index 1930ba892ce..d92f028897f 100644
--- a/chromium/net/cert/ct_signed_certificate_timestamp_log_param.cc
+++ b/chromium/net/cert/ct_signed_certificate_timestamp_log_param.cc
@@ -10,7 +10,6 @@
#include "base/base64.h"
#include "base/strings/string_number_conversions.h"
-#include "base/strings/stringprintf.h"
#include "base/values.h"
#include "net/cert/ct_sct_to_string.h"
#include "net/cert/signed_certificate_timestamp.h"
@@ -22,10 +21,9 @@ namespace {
// Base64 encode the given |value| string and put it in |dict| with the
// description |key|.
-void SetBinaryData(
- const char* key,
- const std::string& value,
- base::DictionaryValue* dict) {
+void SetBinaryData(const char* key,
+ base::StringPiece value,
+ base::DictionaryValue* dict) {
std::string b64_value;
base::Base64Encode(value, &b64_value);
@@ -85,15 +83,15 @@ std::unique_ptr<base::Value> NetLogSignedCertificateTimestampCallback(
}
std::unique_ptr<base::Value> NetLogRawSignedCertificateTimestampCallback(
- const std::string* embedded_scts,
- const std::string* sct_list_from_ocsp,
- const std::string* sct_list_from_tls_extension,
+ base::StringPiece embedded_scts,
+ base::StringPiece sct_list_from_ocsp,
+ base::StringPiece sct_list_from_tls_extension,
NetLogCaptureMode capture_mode) {
std::unique_ptr<base::DictionaryValue> dict(new base::DictionaryValue());
- SetBinaryData("embedded_scts", *embedded_scts, dict.get());
- SetBinaryData("scts_from_ocsp_response", *sct_list_from_ocsp, dict.get());
- SetBinaryData("scts_from_tls_extension", *sct_list_from_tls_extension,
+ SetBinaryData("embedded_scts", embedded_scts, dict.get());
+ SetBinaryData("scts_from_ocsp_response", sct_list_from_ocsp, dict.get());
+ SetBinaryData("scts_from_tls_extension", sct_list_from_tls_extension,
dict.get());
return std::move(dict);
diff --git a/chromium/net/cert/ct_signed_certificate_timestamp_log_param.h b/chromium/net/cert/ct_signed_certificate_timestamp_log_param.h
index 373a7525337..c2149cdb578 100644
--- a/chromium/net/cert/ct_signed_certificate_timestamp_log_param.h
+++ b/chromium/net/cert/ct_signed_certificate_timestamp_log_param.h
@@ -6,8 +6,8 @@
#define NET_CERT_CT_SIGNED_CERTIFICATE_TIMESTAMP_LOG_PARAM_H_
#include <memory>
-#include <string>
+#include "base/strings/string_piece.h"
#include "net/cert/signed_certificate_timestamp_and_status.h"
namespace base {
@@ -31,9 +31,9 @@ std::unique_ptr<base::Value> NetLogSignedCertificateTimestampCallback(
// See the documentation for SIGNED_CERTIFICATE_TIMESTAMPS_RECEIVED
// in net/log/net_log_event_type_list.h
std::unique_ptr<base::Value> NetLogRawSignedCertificateTimestampCallback(
- const std::string* embedded_scts,
- const std::string* sct_list_from_ocsp,
- const std::string* sct_list_from_tls_extension,
+ base::StringPiece embedded_scts,
+ base::StringPiece sct_list_from_ocsp,
+ base::StringPiece sct_list_from_tls_extension,
NetLogCaptureMode capture_mode);
} // namespace net
diff --git a/chromium/net/cert/ct_verifier.h b/chromium/net/cert/ct_verifier.h
index b65a1334b48..b5b1c79045f 100644
--- a/chromium/net/cert/ct_verifier.h
+++ b/chromium/net/cert/ct_verifier.h
@@ -5,14 +5,12 @@
#ifndef NET_CERT_CT_VERIFIER_H_
#define NET_CERT_CT_VERIFIER_H_
-#include <string>
-
+#include "base/strings/string_piece.h"
#include "net/base/net_export.h"
#include "net/cert/signed_certificate_timestamp_and_status.h"
namespace net {
-class CTLogVerifier;
class NetLogWithSource;
class X509Certificate;
@@ -45,13 +43,13 @@ class NET_EXPORT CTVerifier {
// (embedding, TLS extension or OCSP stapling). If no stapled OCSP response
// is available, |stapled_ocsp_response| should be an empty string. If no SCT
// TLS extension was negotiated, |sct_list_from_tls_extension| should be an
- // empty string. |result| will be filled with the SCTs present, divided into
- // categories based on the verification result.
- virtual int Verify(X509Certificate* cert,
- const std::string& stapled_ocsp_response,
- const std::string& sct_list_from_tls_extension,
- SignedCertificateTimestampAndStatusList* output_scts,
- const NetLogWithSource& net_log) = 0;
+ // empty string. |output_scts| will be cleared and filled with the SCTs
+ // present, if any, along with their verification results.
+ virtual void Verify(X509Certificate* cert,
+ base::StringPiece stapled_ocsp_response,
+ base::StringPiece sct_list_from_tls_extension,
+ SignedCertificateTimestampAndStatusList* output_scts,
+ const NetLogWithSource& net_log) = 0;
// Registers |observer| to receive notifications of validated SCTs. Does not
// take ownership of the observer as the observer may be performing
diff --git a/chromium/net/cert/do_nothing_ct_verifier.cc b/chromium/net/cert/do_nothing_ct_verifier.cc
new file mode 100644
index 00000000000..0429d86e765
--- /dev/null
+++ b/chromium/net/cert/do_nothing_ct_verifier.cc
@@ -0,0 +1,25 @@
+// Copyright 2016 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.
+
+#include "net/cert/do_nothing_ct_verifier.h"
+
+#include "net/base/net_errors.h"
+
+namespace net {
+
+DoNothingCTVerifier::DoNothingCTVerifier() = default;
+DoNothingCTVerifier::~DoNothingCTVerifier() = default;
+
+void DoNothingCTVerifier::Verify(
+ X509Certificate* cert,
+ base::StringPiece stapled_ocsp_response,
+ base::StringPiece sct_list_from_tls_extension,
+ SignedCertificateTimestampAndStatusList* output_scts,
+ const NetLogWithSource& net_log) {
+ output_scts->clear();
+}
+
+void DoNothingCTVerifier::SetObserver(Observer* observer) {}
+
+} // namespace net
diff --git a/chromium/net/cert/do_nothing_ct_verifier.h b/chromium/net/cert/do_nothing_ct_verifier.h
new file mode 100644
index 00000000000..025ffd11be8
--- /dev/null
+++ b/chromium/net/cert/do_nothing_ct_verifier.h
@@ -0,0 +1,67 @@
+// Copyright 2016 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.
+
+#ifndef NET_CERT_DO_NOTHING_CT_VERIFIER_H_
+#define NET_CERT_DO_NOTHING_CT_VERIFIER_H_
+
+#include "base/macros.h"
+#include "net/base/net_export.h"
+#include "net/cert/ct_verifier.h"
+
+namespace net {
+
+// An implementation of CTVerifier that does not validate SCTs.
+//
+// SECURITY NOTE:
+// As Certificate Transparency is an essential part in safeguarding TLS
+// connections, disabling Certificate Transparency enforcement is a decision
+// that should not be taken lightly, and it should be made an explicit
+// decision rather than a potentially accidental decision (such as allowing
+// for a nullptr instance). By checking Certificate Transparency information,
+// typically via a net::MultiLogCTVerifier, and enforcing policies related
+// to Certificate Transparency provided by a net::CTPolicyEnforcer, developers
+// can help protect their users by ensuring that misissued TLS certificates
+// are detected.
+//
+// However, not every consumer of TLS certificates is using the Web PKI. For
+// example, they may be using connections authenticated out of band, or may
+// be using private or local PKIs for which Certificate Transparency is not
+// relevant. Alternatively, much like how a robust and secure TLS client
+// requires a regularly updated root certificate store, a robust and secure
+// Certificate Transparency client requires regular updates. However, since
+// some clients may not support regular updates, it may be intentional to
+// disable Certificate Transparency and choose a less-secure default
+// behavior.
+//
+// Consumers of this class should generally try to get a security or design
+// to discuss the type of net::X509Certificates they will be validating,
+// and determine whether or not Certificate Transparency is right for the
+// particular use case.
+//
+// Because of the complex nuances related to security tradeoffs, it is
+// expected that classes which expect a CTVerifier will require one to be
+// supplied, forcing the caller to make an intentional and explicit decision
+// about the appropriate security policy, rather than leaving it ambiguous,
+// such as via a nullptr. This class is intended to indicate an intentional
+// consideration of CT, and a decision to not support it.
+class NET_EXPORT DoNothingCTVerifier : public CTVerifier {
+ public:
+ DoNothingCTVerifier();
+ ~DoNothingCTVerifier() override;
+
+ void Verify(X509Certificate* cert,
+ base::StringPiece stapled_ocsp_response,
+ base::StringPiece sct_list_from_tls_extension,
+ SignedCertificateTimestampAndStatusList* output_scts,
+ const NetLogWithSource& net_log) override;
+
+ void SetObserver(Observer* observer) override;
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(DoNothingCTVerifier);
+};
+
+} // namespace net
+
+#endif // NET_CERT_DO_NOTHING_CT_VERIFIER_H_
diff --git a/chromium/net/cert/ev_root_ca_metadata.cc b/chromium/net/cert/ev_root_ca_metadata.cc
index 1370f1726c4..a7e85ec8059 100644
--- a/chromium/net/cert/ev_root_ca_metadata.cc
+++ b/chromium/net/cert/ev_root_ca_metadata.cc
@@ -41,7 +41,7 @@ struct EVMetadata {
SHA1HashValue fingerprint;
// The EV policy OIDs of the root CA.
- const char policy_oids[kMaxOIDsPerCA][kMaxOIDLength];
+ char policy_oids[kMaxOIDsPerCA][kMaxOIDLength];
};
static const EVMetadata ev_root_ca_metadata[] = {
@@ -114,6 +114,34 @@ static const EVMetadata ev_root_ca_metadata[] = {
0x55, 0x6c, 0x11, 0xa4, 0x37, 0xca, 0xeb, 0xff, 0xc3, 0xbb}},
{"1.3.6.1.4.1.34697.2.4", ""},
},
+ // Amazon Root CA 1
+ // https://good.sca1a.amazontrust.com/
+ {
+ {{0x8d, 0xa7, 0xf9, 0x65, 0xec, 0x5e, 0xfc, 0x37, 0x91, 0x0f,
+ 0x1c, 0x6e, 0x59, 0xfd, 0xc1, 0xcc, 0x6a, 0x6e, 0xde, 0x16}},
+ {"2.23.140.1.1", ""},
+ },
+ // Amazon Root CA 2
+ // https://good.sca2a.amazontrust.com/
+ {
+ {{0x5a, 0x8c, 0xef, 0x45, 0xd7, 0xa6, 0x98, 0x59, 0x76, 0x7a,
+ 0x8c, 0x8b, 0x44, 0x96, 0xb5, 0x78, 0xcf, 0x47, 0x4b, 0x1a}},
+ {"2.23.140.1.1", ""},
+ },
+ // Amazon Root CA 3
+ // https://good.sca3a.amazontrust.com/
+ {
+ {{0x0d, 0x44, 0xdd, 0x8c, 0x3c, 0x8c, 0x1a, 0x1a, 0x58, 0x75,
+ 0x64, 0x81, 0xe9, 0x0f, 0x2e, 0x2a, 0xff, 0xb3, 0xd2, 0x6e}},
+ {"2.23.140.1.1", ""},
+ },
+ // Amazon Root CA 4
+ // https://good.sca4a.amazontrust.com/
+ {
+ {{0xf6, 0x10, 0x84, 0x07, 0xd6, 0xf8, 0xbb, 0x67, 0x98, 0x0c,
+ 0xc2, 0xe2, 0x44, 0xc2, 0xeb, 0xae, 0x1c, 0xef, 0x63, 0xbe}},
+ {"2.23.140.1.1", ""},
+ },
// Autoridad de Certificacion Firmaprofesional CIF A62634068
// https://publifirma.firmaprofesional.com/
{{{0xae, 0xc5, 0xfb, 0x3f, 0xc8, 0xe1, 0xbf, 0xc4, 0xe5, 0x4f,
@@ -168,6 +196,13 @@ static const EVMetadata ev_root_ca_metadata[] = {
0x06, 0x28, 0xa2, 0x59, 0x3a, 0x19, 0xa7, 0x0f, 0x06, 0x9e}},
{"1.2.616.1.113527.2.5.1.1", ""},
},
+ // CFCA EV ROOT
+ // https://www.erenepu.com/
+ {
+ {{0xe2, 0xb8, 0x29, 0x4b, 0x55, 0x84, 0xab, 0x6b, 0x58, 0xc2,
+ 0x90, 0x46, 0x6c, 0xac, 0x3f, 0xb8, 0x39, 0x8f, 0x84, 0x83}},
+ {"2.16.156.112554.3", ""},
+ },
// China Internet Network Information Center EV Certificates Root
// https://evdemo.cnnic.cn/
{
@@ -239,6 +274,13 @@ static const EVMetadata ev_root_ca_metadata[] = {
0xdc, 0x37, 0xd4, 0x4d, 0xf5, 0xd4, 0x67, 0x49, 0x52, 0xf9}},
{"2.16.840.1.114028.10.1.2", ""},
},
+ // Entrust Root Certification Authority – G2
+ // https://validg2.entrust.net
+ {
+ {{0x8c, 0xf4, 0x27, 0xfd, 0x79, 0x0c, 0x3a, 0xd1, 0x66, 0x06,
+ 0x8d, 0xe8, 0x1e, 0x57, 0xef, 0xbb, 0x93, 0x22, 0x72, 0xd4}},
+ {"2.16.840.1.114028.10.1.2", ""},
+ },
// Equifax Secure Certificate Authority (GeoTrust)
// https://www.geotrust.com/
{
@@ -343,6 +385,13 @@ static const EVMetadata ev_root_ca_metadata[] = {
0x3f, 0xf8, 0xbc, 0xf8, 0x15, 0xb0, 0x82, 0xf9, 0xae, 0xfd}},
{"1.3.6.1.4.1.14777.6.1.1", "1.3.6.1.4.1.14777.6.1.2"},
},
+ // LuxTrust Global Root 2
+ // https://ltsslca5.trustme.lu/
+ {
+ {{0x1e, 0x0e, 0x56, 0x19, 0x0a, 0xd1, 0x8b, 0x25, 0x98, 0xb2,
+ 0x04, 0x44, 0xff, 0x66, 0x8a, 0x04, 0x17, 0x99, 0x5f, 0x3f}},
+ {"1.3.171.1.1.10.5.2", ""},
+ },
// Network Solutions Certificate Authority
// https://www.networksolutions.com/website-packages/index.jsp
{
@@ -358,6 +407,13 @@ static const EVMetadata ev_root_ca_metadata[] = {
0xc0, 0x71, 0xf8, 0xf7, 0x33, 0xb1, 0x83, 0x85, 0x63, 0x32}},
{"1.3.6.1.4.1.782.1.2.1.8.1", ""},
},
+ // OISTE WISeKey Global Root GB CA
+ // https://goodevssl.wisekey.com
+ {
+ {{0x0f, 0xf9, 0x40, 0x76, 0x18, 0xd3, 0xd7, 0x6a, 0x4b, 0x98,
+ 0xf0, 0xa8, 0x35, 0x9e, 0x0c, 0xfd, 0x27, 0xac, 0xcc, 0xed}},
+ {"2.16.756.5.14.7.4.8", ""},
+ },
// QuoVadis Root CA 2
// https://www.quovadis.bm/
{
@@ -440,7 +496,7 @@ static const EVMetadata ev_root_ca_metadata[] = {
{
{{0x92, 0x5a, 0x8f, 0x8d, 0x2c, 0x6d, 0x04, 0xe0, 0x66, 0x5f,
0x59, 0x6a, 0xff, 0x22, 0xd8, 0x63, 0xe8, 0x25, 0x6f, 0x3f}},
- {"2.16.840.1.114414.1.7.24.3", ""},
+ {"2.16.840.1.114414.1.7.24.3", "2.23.140.1.1"},
},
// SwissSign Gold CA - G2
// https://testevg2.swisssign.net/
diff --git a/chromium/net/cert/internal/cert_errors.h b/chromium/net/cert/internal/cert_errors.h
index a9579ce0c31..cd713ed42ec 100644
--- a/chromium/net/cert/internal/cert_errors.h
+++ b/chromium/net/cert/internal/cert_errors.h
@@ -75,7 +75,6 @@ namespace net {
class CertErrorParams;
class CertErrorScoper;
-class ParsedCertificate;
// The type of a particular CertErrorNode.
enum class CertErrorNodeType {
diff --git a/chromium/net/cert/internal/cert_issuer_source.h b/chromium/net/cert/internal/cert_issuer_source.h
index 1ffc3b3a9f9..c38b61d2546 100644
--- a/chromium/net/cert/internal/cert_issuer_source.h
+++ b/chromium/net/cert/internal/cert_issuer_source.h
@@ -8,9 +8,7 @@
#include <memory>
#include <vector>
-#include "base/callback.h"
#include "net/base/net_export.h"
-#include "net/cert/internal/completion_status.h"
#include "net/cert/internal/parsed_certificate.h"
namespace net {
@@ -30,27 +28,19 @@ class NET_EXPORT CertIssuerSource {
// Destruction of the Request cancels it.
virtual ~Request() = default;
- // Retrieves the next issuer.
+ // Retrieves issuers and appends them to |issuers|.
//
- // If one is available it will be stored in |out_cert| and SYNC will be
- // returned. GetNext should be called again to retrieve any remaining
- // issuers.
+ // GetNext should be called again to retrieve any remaining issuers.
//
- // If no issuers are currently available, |out_cert| will be cleared and the
- // return value will indicate if the Request is exhausted. If the return
- // value is ASYNC, the |issuers_callback| that was passed to
- // AsyncGetIssuersOf will be called again (unless the Request is destroyed
- // first). If the return value is SYNC, the Request is complete and the
- // |issuers_callback| will not be called again.
- virtual CompletionStatus GetNext(
- scoped_refptr<ParsedCertificate>* out_cert) = 0;
+ // If no issuers are left then |issuers| will not be modified. This
+ // indicates that the issuers have been exhausted and GetNext() should
+ // not be called again.
+ virtual void GetNext(ParsedCertificateList* issuers) = 0;
private:
DISALLOW_COPY_AND_ASSIGN(Request);
};
- using IssuerCallback = base::Callback<void(Request*)>;
-
virtual ~CertIssuerSource() = default;
// Finds certificates whose Subject matches |cert|'s Issuer.
@@ -61,18 +51,13 @@ class NET_EXPORT CertIssuerSource {
ParsedCertificateList* issuers) = 0;
// Finds certificates whose Subject matches |cert|'s Issuer.
- // If an async callback will be made |*out_req| is filled with a Request
- // object which may be destroyed to cancel the callback. If the implementation
- // does not support asynchronous lookups or can determine synchronously that
- // it would return no results, |*out_req| will be set to nullptr.
+ // If the implementation does not support asynchronous lookups or can
+ // determine synchronously that it would return no results, |*out_req|
+ // will be set to nullptr.
//
- // When matches are available or the request is complete, |issuers_callback|
- // will be called with a pointer to the same Request. The Request::GetNext
- // method may then be used to iterate through the retrieved issuers. Note that
- // |issuers_callback| may be called multiple times. See the documentation for
- // Request::GetNext for more details.
+ // Otherwise a request is started and saved to |out_req|. The results can be
+ // read through the Request interface.
virtual void AsyncGetIssuersOf(const ParsedCertificate* cert,
- const IssuerCallback& issuers_callback,
std::unique_ptr<Request>* out_req) = 0;
};
diff --git a/chromium/net/cert/internal/cert_issuer_source_aia.cc b/chromium/net/cert/internal/cert_issuer_source_aia.cc
index a6fb1b703d1..6e1290ab26d 100644
--- a/chromium/net/cert/internal/cert_issuer_source_aia.cc
+++ b/chromium/net/cert/internal/cert_issuer_source_aia.cc
@@ -20,94 +20,82 @@ const int kMaxFetchesPerCert = 5;
class AiaRequest : public CertIssuerSource::Request {
public:
- explicit AiaRequest(const CertIssuerSource::IssuerCallback& issuers_callback);
+ AiaRequest() {}
~AiaRequest() override;
// CertIssuerSource::Request implementation.
- CompletionStatus GetNext(scoped_refptr<ParsedCertificate>* out_cert) override;
+ void GetNext(ParsedCertificateList* issuers) override;
void AddCertFetcherRequest(
std::unique_ptr<CertNetFetcher::Request> cert_fetcher_request);
- void OnFetchCompleted(Error error, const std::vector<uint8_t>& fetched_bytes);
+ bool AddCompletedFetchToResults(Error error,
+ std::vector<uint8_t> fetched_bytes,
+ ParsedCertificateList* results);
private:
- bool HasNext() const { return current_result_ < results_.size(); }
-
- CertIssuerSource::IssuerCallback issuers_callback_;
std::vector<std::unique_ptr<CertNetFetcher::Request>> cert_fetcher_requests_;
- size_t pending_requests_ = 0;
- ParsedCertificateList results_;
- size_t current_result_ = 0;
+ size_t current_request_ = 0;
DISALLOW_COPY_AND_ASSIGN(AiaRequest);
};
-AiaRequest::AiaRequest(const CertIssuerSource::IssuerCallback& issuers_callback)
- : issuers_callback_(issuers_callback) {}
-
AiaRequest::~AiaRequest() = default;
-CompletionStatus AiaRequest::GetNext(
- scoped_refptr<ParsedCertificate>* out_cert) {
- if (HasNext()) {
- *out_cert = std::move(results_[current_result_++]);
- return CompletionStatus::SYNC;
+void AiaRequest::GetNext(ParsedCertificateList* out_certs) {
+ // TODO(eroman): Rather than blocking in FIFO order, select the one that
+ // completes first.
+ while (current_request_ < cert_fetcher_requests_.size()) {
+ Error error;
+ std::vector<uint8_t> bytes;
+ auto req = std::move(cert_fetcher_requests_[current_request_++]);
+ req->WaitForResult(&error, &bytes);
+
+ if (AddCompletedFetchToResults(error, std::move(bytes), out_certs))
+ return;
}
- *out_cert = nullptr;
- if (pending_requests_)
- return CompletionStatus::ASYNC;
- return CompletionStatus::SYNC;
}
void AiaRequest::AddCertFetcherRequest(
std::unique_ptr<CertNetFetcher::Request> cert_fetcher_request) {
DCHECK(cert_fetcher_request);
cert_fetcher_requests_.push_back(std::move(cert_fetcher_request));
- pending_requests_++;
}
-void AiaRequest::OnFetchCompleted(Error error,
- const std::vector<uint8_t>& fetched_bytes) {
- DCHECK_GT(pending_requests_, 0U);
- pending_requests_--;
- bool client_waiting_for_callback = !HasNext();
+bool AiaRequest::AddCompletedFetchToResults(Error error,
+ std::vector<uint8_t> fetched_bytes,
+ ParsedCertificateList* results) {
if (error != OK) {
// TODO(mattm): propagate error info.
LOG(ERROR) << "AiaRequest::OnFetchCompleted got error " << error;
- } else {
- // RFC 5280 section 4.2.2.1:
- //
- // Conforming applications that support HTTP or FTP for accessing
- // certificates MUST be able to accept individual DER encoded
- // certificates and SHOULD be able to accept "certs-only" CMS messages.
- //
- // TODO(mattm): Is supporting CMS message format important?
- //
- // TODO(mattm): Avoid copying bytes. Change the CertNetFetcher and
- // ParsedCertificate interface to allow passing through ownership of the
- // bytes.
- CertErrors errors;
- if (!ParsedCertificate::CreateAndAddToVector(fetched_bytes.data(),
- fetched_bytes.size(), {},
- &results_, &errors)) {
- // TODO(crbug.com/634443): propagate error info.
- LOG(ERROR) << "Error parsing cert retrieved from AIA:\n"
- << errors.ToDebugString();
- }
+ return false;
}
- // If the client is waiting for results, need to run callback if:
- // * Some are available now.
- // * The last fetch finished, even with no results. (Client needs to know to
- // stop waiting.)
- if (client_waiting_for_callback && (HasNext() || pending_requests_ == 0))
- issuers_callback_.Run(this);
+ // RFC 5280 section 4.2.2.1:
+ //
+ // Conforming applications that support HTTP or FTP for accessing
+ // certificates MUST be able to accept individual DER encoded
+ // certificates and SHOULD be able to accept "certs-only" CMS messages.
+ //
+ // TODO(mattm): Is supporting CMS message format important?
+ //
+ // TODO(eroman): Avoid copying bytes in the certificate?
+ CertErrors errors;
+ if (!ParsedCertificate::CreateAndAddToVector(
+ fetched_bytes.data(), fetched_bytes.size(), {}, results, &errors)) {
+ // TODO(crbug.com/634443): propagate error info.
+ LOG(ERROR) << "Error parsing cert retrieved from AIA:\n"
+ << errors.ToDebugString();
+ return false;
+ }
+
+ return true;
}
} // namespace
-CertIssuerSourceAia::CertIssuerSourceAia(CertNetFetcher* cert_fetcher)
- : cert_fetcher_(cert_fetcher) {}
+CertIssuerSourceAia::CertIssuerSourceAia(
+ scoped_refptr<CertNetFetcher> cert_fetcher)
+ : cert_fetcher_(std::move(cert_fetcher)) {}
CertIssuerSourceAia::~CertIssuerSourceAia() = default;
@@ -116,10 +104,8 @@ void CertIssuerSourceAia::SyncGetIssuersOf(const ParsedCertificate* cert,
// CertIssuerSourceAia never returns synchronous results.
}
-void CertIssuerSourceAia::AsyncGetIssuersOf(
- const ParsedCertificate* cert,
- const IssuerCallback& issuers_callback,
- std::unique_ptr<Request>* out_req) {
+void CertIssuerSourceAia::AsyncGetIssuersOf(const ParsedCertificate* cert,
+ std::unique_ptr<Request>* out_req) {
out_req->reset();
if (!cert->has_authority_info_access())
@@ -152,16 +138,14 @@ void CertIssuerSourceAia::AsyncGetIssuersOf(
if (urls.empty())
return;
- std::unique_ptr<AiaRequest> aia_request(new AiaRequest(issuers_callback));
+ std::unique_ptr<AiaRequest> aia_request(new AiaRequest());
for (const auto& url : urls) {
// TODO(mattm): add synchronous failure mode to FetchCaIssuers interface so
// that this doesn't need to wait for async callback just to tell that an
// URL has an unsupported scheme?
aia_request->AddCertFetcherRequest(cert_fetcher_->FetchCaIssuers(
- url, kTimeoutMilliseconds, kMaxResponseBytes,
- base::Bind(&AiaRequest::OnFetchCompleted,
- base::Unretained(aia_request.get()))));
+ url, kTimeoutMilliseconds, kMaxResponseBytes));
}
*out_req = std::move(aia_request);
diff --git a/chromium/net/cert/internal/cert_issuer_source_aia.h b/chromium/net/cert/internal/cert_issuer_source_aia.h
index 73c8177bce0..3e62c95a085 100644
--- a/chromium/net/cert/internal/cert_issuer_source_aia.h
+++ b/chromium/net/cert/internal/cert_issuer_source_aia.h
@@ -16,21 +16,20 @@ class CertNetFetcher;
class NET_EXPORT CertIssuerSourceAia : public CertIssuerSource {
public:
// Creates CertIssuerSource that will use |cert_fetcher| to retrieve issuers
- // using AuthorityInfoAccess URIs. |cert_fetcher| must outlive the
- // CertIssuerSourceAia. CertIssuerSourceAia must be created and used only on
- // a single thread, which is the thread |cert_fetcher| will be operated from.
- explicit CertIssuerSourceAia(CertNetFetcher* cert_fetcher);
+ // using AuthorityInfoAccess URIs. CertIssuerSourceAia must be created and
+ // used only on a single thread, which is the thread |cert_fetcher| will be
+ // operated from.
+ explicit CertIssuerSourceAia(scoped_refptr<CertNetFetcher> cert_fetcher);
~CertIssuerSourceAia() override;
// CertIssuerSource implementation:
void SyncGetIssuersOf(const ParsedCertificate* cert,
ParsedCertificateList* issuers) override;
void AsyncGetIssuersOf(const ParsedCertificate* cert,
- const IssuerCallback& issuers_callback,
std::unique_ptr<Request>* out_req) override;
private:
- CertNetFetcher* cert_fetcher_;
+ scoped_refptr<CertNetFetcher> cert_fetcher_;
DISALLOW_COPY_AND_ASSIGN(CertIssuerSourceAia);
};
diff --git a/chromium/net/cert/internal/cert_issuer_source_aia_unittest.cc b/chromium/net/cert/internal/cert_issuer_source_aia_unittest.cc
index b0f1aa72d28..f81c33d76f3 100644
--- a/chromium/net/cert/internal/cert_issuer_source_aia_unittest.cc
+++ b/chromium/net/cert/internal/cert_issuer_source_aia_unittest.cc
@@ -5,6 +5,7 @@
#include "net/cert/internal/cert_issuer_source_aia.h"
#include "base/bind.h"
+#include "base/memory/ptr_util.h"
#include "net/cert/cert_net_fetcher.h"
#include "net/cert/internal/cert_errors.h"
#include "net/cert/internal/parsed_certificate.h"
@@ -17,8 +18,11 @@ namespace net {
namespace {
+using ::testing::ByMove;
using ::testing::Mock;
+using ::testing::Return;
using ::testing::StrictMock;
+using ::testing::_;
::testing::AssertionResult ReadTestPem(const std::string& file_name,
const std::string& block_name,
@@ -56,112 +60,59 @@ std::vector<uint8_t> CertDataVector(const ParsedCertificate* cert) {
return data;
}
-// Tracks a CertNetFetcher::Request that will be returned to the
-// CertIssuerSourceAia. Allows the tests to tell if the Request is still alive
-// or was deleted(cancelled) by the CertIssuerSourceAia. If the Request is still
-// alive, the test can get the FetchCallback to simulate the Request completing.
-class RequestManager {
+// MockCertNetFetcher is an implementation of CertNetFetcher for testing.
+class MockCertNetFetcher : public CertNetFetcher {
public:
- class Request : public CertNetFetcher::Request {
- public:
- Request(RequestManager* manager,
- const CertNetFetcher::FetchCallback& callback)
- : manager_(manager), callback_(callback) {}
- ~Request() override { manager_->RequestWasDestroyed(); }
-
- CertNetFetcher::FetchCallback get_callback() const { return callback_; }
-
- private:
- RequestManager* manager_;
- CertNetFetcher::FetchCallback callback_;
- };
-
- ~RequestManager() { CHECK(!request_); }
-
- std::unique_ptr<Request> CreateRequest(
- const CertNetFetcher::FetchCallback& callback) {
- EXPECT_FALSE(request_);
- std::unique_ptr<Request> request(new Request(this, callback));
- request_ = request.get();
- return request;
- }
-
- bool is_request_alive() const { return request_; }
-
- CertNetFetcher::FetchCallback get_callback() const {
- CHECK(is_request_alive());
- return request_->get_callback();
- }
-
- private:
- void RequestWasDestroyed() {
- EXPECT_TRUE(request_);
- request_ = nullptr;
- }
-
- Request* request_;
+ MockCertNetFetcher() {}
+ MOCK_METHOD0(Shutdown, void());
+ MOCK_METHOD3(FetchCaIssuers,
+ std::unique_ptr<Request>(const GURL& url,
+ int timeout_milliseconds,
+ int max_response_bytes));
+ MOCK_METHOD3(FetchCrl,
+ std::unique_ptr<Request>(const GURL& url,
+ int timeout_milliseconds,
+ int max_response_bytes));
+
+ MOCK_METHOD3(FetchOcsp,
+ std::unique_ptr<Request>(const GURL& url,
+ int timeout_milliseconds,
+ int max_response_bytes));
+
+ protected:
+ ~MockCertNetFetcher() override {}
};
-// MockCertNetFetcherImpl is an implementation of CertNetFetcher for testing.
-class MockCertNetFetcherImpl : public CertNetFetcher {
+// MockCertNetFetcherRequest gives back the indicated error and bytes.
+class MockCertNetFetcherRequest : public CertNetFetcher::Request {
public:
- MockCertNetFetcherImpl() = default;
- ~MockCertNetFetcherImpl() override = default;
-
- RequestManager* GetRequestManagerForURL(const GURL& url) {
- auto it = request_map_.find(url);
- if (it == request_map_.end())
- return nullptr;
- return it->second.get();
- }
-
- WARN_UNUSED_RESULT std::unique_ptr<Request> FetchCaIssuers(
- const GURL& url,
- int timeout_milliseconds,
- int max_response_bytes,
- const FetchCallback& callback) override {
- EXPECT_TRUE(request_map_.find(url) == request_map_.end());
-
- std::unique_ptr<RequestManager> request_manager(new RequestManager());
-
- std::unique_ptr<Request> request = request_manager->CreateRequest(callback);
-
- request_map_[url] = std::move(request_manager);
-
- return request;
- }
-
- WARN_UNUSED_RESULT std::unique_ptr<Request> FetchCrl(
- const GURL& url,
- int timeout_milliseconds,
- int max_response_bytes,
- const FetchCallback& callback) override {
- NOTREACHED();
- return nullptr;
- }
-
- WARN_UNUSED_RESULT std::unique_ptr<Request> FetchOcsp(
- const GURL& url,
- int timeout_milliseconds,
- int max_response_bytes,
- const FetchCallback& callback) override {
- NOTREACHED();
- return nullptr;
+ MockCertNetFetcherRequest(Error error, std::vector<uint8_t> bytes)
+ : error_(error), bytes_(std::move(bytes)) {}
+
+ void WaitForResult(Error* error, std::vector<uint8_t>* bytes) override {
+ DCHECK(!did_consume_result_);
+ *error = error_;
+ *bytes = std::move(bytes_);
+ did_consume_result_ = true;
}
private:
- std::map<GURL, std::unique_ptr<RequestManager>> request_map_;
-
- DISALLOW_COPY_AND_ASSIGN(MockCertNetFetcherImpl);
+ Error error_;
+ std::vector<uint8_t> bytes_;
+ bool did_consume_result_ = false;
};
-class MockIssuerCallback {
- public:
- MOCK_METHOD1(Callback, void(CertIssuerSource::Request*));
-};
+// Creates a CertNetFetcher::Request that completes with an error.
+std::unique_ptr<CertNetFetcher::Request> CreateMockRequest(Error error) {
+ return base::MakeUnique<MockCertNetFetcherRequest>(error,
+ std::vector<uint8_t>());
+}
-void NotCalled(CertIssuerSource::Request* request) {
- ADD_FAILURE() << "NotCalled was called";
+// Creates a CertNetFetcher::Request that completes with the specified error
+// code and bytes.
+std::unique_ptr<CertNetFetcher::Request> CreateMockRequest(
+ const std::vector<uint8_t>& bytes) {
+ return base::MakeUnique<MockCertNetFetcherRequest>(OK, bytes);
}
// CertIssuerSourceAia does not return results for SyncGetIssuersOf.
@@ -169,8 +120,9 @@ TEST(CertIssuerSourceAiaTest, NoSyncResults) {
scoped_refptr<ParsedCertificate> cert;
ASSERT_TRUE(ReadTestCert("target_two_aia.pem", &cert));
- StrictMock<MockCertNetFetcherImpl> mock_fetcher;
- CertIssuerSourceAia aia_source(&mock_fetcher);
+ // No methods on |mock_fetcher| should be called.
+ auto mock_fetcher = make_scoped_refptr(new StrictMock<MockCertNetFetcher>());
+ CertIssuerSourceAia aia_source(mock_fetcher);
ParsedCertificateList issuers;
aia_source.SyncGetIssuersOf(cert.get(), &issuers);
EXPECT_EQ(0U, issuers.size());
@@ -182,10 +134,11 @@ TEST(CertIssuerSourceAiaTest, NoAia) {
scoped_refptr<ParsedCertificate> cert;
ASSERT_TRUE(ReadTestCert("target_no_aia.pem", &cert));
- StrictMock<MockCertNetFetcherImpl> mock_fetcher;
- CertIssuerSourceAia aia_source(&mock_fetcher);
+ // No methods on |mock_fetcher| should be called.
+ auto mock_fetcher = make_scoped_refptr(new StrictMock<MockCertNetFetcher>());
+ CertIssuerSourceAia aia_source(mock_fetcher);
std::unique_ptr<CertIssuerSource::Request> request;
- aia_source.AsyncGetIssuersOf(cert.get(), base::Bind(&NotCalled), &request);
+ aia_source.AsyncGetIssuersOf(cert.get(), &request);
EXPECT_EQ(nullptr, request);
}
@@ -198,32 +151,19 @@ TEST(CertIssuerSourceAiaTest, FileAia) {
scoped_refptr<ParsedCertificate> cert;
ASSERT_TRUE(ReadTestCert("target_file_aia.pem", &cert));
- StrictMock<MockIssuerCallback> mock_callback;
- StrictMock<MockCertNetFetcherImpl> mock_fetcher;
- CertIssuerSourceAia aia_source(&mock_fetcher);
+ auto mock_fetcher = make_scoped_refptr(new StrictMock<MockCertNetFetcher>());
+ EXPECT_CALL(*mock_fetcher, FetchCaIssuers(GURL("file:///dev/null"), _, _))
+ .WillOnce(Return(ByMove(CreateMockRequest(ERR_DISALLOWED_URL_SCHEME))));
+
+ CertIssuerSourceAia aia_source(mock_fetcher);
std::unique_ptr<CertIssuerSource::Request> cert_source_request;
- aia_source.AsyncGetIssuersOf(cert.get(),
- base::Bind(&MockIssuerCallback::Callback,
- base::Unretained(&mock_callback)),
- &cert_source_request);
+ aia_source.AsyncGetIssuersOf(cert.get(), &cert_source_request);
ASSERT_NE(nullptr, cert_source_request);
- RequestManager* req_manager =
- mock_fetcher.GetRequestManagerForURL(GURL("file:///dev/null"));
- ASSERT_TRUE(req_manager);
- ASSERT_TRUE(req_manager->is_request_alive());
-
- EXPECT_CALL(mock_callback, Callback(cert_source_request.get()));
- // CertNetFetcher rejects the URL scheme.
- req_manager->get_callback().Run(ERR_DISALLOWED_URL_SCHEME,
- std::vector<uint8_t>());
- Mock::VerifyAndClearExpectations(&mock_callback);
-
// No results.
- scoped_refptr<ParsedCertificate> result_cert;
- CompletionStatus status = cert_source_request->GetNext(&result_cert);
- EXPECT_EQ(CompletionStatus::SYNC, status);
- EXPECT_FALSE(result_cert.get());
+ ParsedCertificateList result_certs;
+ cert_source_request->GetNext(&result_certs);
+ EXPECT_TRUE(result_certs.empty());
}
// If the AuthorityInfoAccess extension contains an invalid URL,
@@ -232,10 +172,10 @@ TEST(CertIssuerSourceAiaTest, OneInvalidURL) {
scoped_refptr<ParsedCertificate> cert;
ASSERT_TRUE(ReadTestCert("target_invalid_url_aia.pem", &cert));
- StrictMock<MockCertNetFetcherImpl> mock_fetcher;
- CertIssuerSourceAia aia_source(&mock_fetcher);
+ auto mock_fetcher = make_scoped_refptr(new StrictMock<MockCertNetFetcher>());
+ CertIssuerSourceAia aia_source(mock_fetcher);
std::unique_ptr<CertIssuerSource::Request> request;
- aia_source.AsyncGetIssuersOf(cert.get(), base::Bind(&NotCalled), &request);
+ aia_source.AsyncGetIssuersOf(cert.get(), &request);
EXPECT_EQ(nullptr, request);
}
@@ -246,38 +186,26 @@ TEST(CertIssuerSourceAiaTest, OneAia) {
scoped_refptr<ParsedCertificate> intermediate_cert;
ASSERT_TRUE(ReadTestCert("i.pem", &intermediate_cert));
- StrictMock<MockIssuerCallback> mock_callback;
- StrictMock<MockCertNetFetcherImpl> mock_fetcher;
- CertIssuerSourceAia aia_source(&mock_fetcher);
- std::unique_ptr<CertIssuerSource::Request> cert_source_request;
- aia_source.AsyncGetIssuersOf(cert.get(),
- base::Bind(&MockIssuerCallback::Callback,
- base::Unretained(&mock_callback)),
- &cert_source_request);
- ASSERT_NE(nullptr, cert_source_request);
-
- RequestManager* req_manager =
- mock_fetcher.GetRequestManagerForURL(GURL("http://url-for-aia/I.cer"));
- ASSERT_TRUE(req_manager);
- ASSERT_TRUE(req_manager->is_request_alive());
+ auto mock_fetcher = make_scoped_refptr(new StrictMock<MockCertNetFetcher>());
- EXPECT_CALL(mock_callback, Callback(cert_source_request.get()));
- req_manager->get_callback().Run(OK, CertDataVector(intermediate_cert.get()));
- Mock::VerifyAndClearExpectations(&mock_callback);
+ EXPECT_CALL(*mock_fetcher,
+ FetchCaIssuers(GURL("http://url-for-aia/I.cer"), _, _))
+ .WillOnce(Return(
+ ByMove(CreateMockRequest(CertDataVector(intermediate_cert.get())))));
- scoped_refptr<ParsedCertificate> result_cert;
- CompletionStatus status = cert_source_request->GetNext(&result_cert);
- EXPECT_EQ(CompletionStatus::SYNC, status);
- ASSERT_TRUE(result_cert.get());
- ASSERT_EQ(result_cert->der_cert(), intermediate_cert->der_cert());
+ CertIssuerSourceAia aia_source(mock_fetcher);
+ std::unique_ptr<CertIssuerSource::Request> cert_source_request;
+ aia_source.AsyncGetIssuersOf(cert.get(), &cert_source_request);
+ ASSERT_NE(nullptr, cert_source_request);
- status = cert_source_request->GetNext(&result_cert);
- EXPECT_EQ(CompletionStatus::SYNC, status);
- EXPECT_FALSE(result_cert.get());
+ ParsedCertificateList result_certs;
+ cert_source_request->GetNext(&result_certs);
+ ASSERT_EQ(1u, result_certs.size());
+ ASSERT_EQ(result_certs.front()->der_cert(), intermediate_cert->der_cert());
- EXPECT_TRUE(req_manager->is_request_alive());
- cert_source_request.reset();
- EXPECT_FALSE(req_manager->is_request_alive());
+ result_certs.clear();
+ cert_source_request->GetNext(&result_certs);
+ EXPECT_TRUE(result_certs.empty());
}
// AuthorityInfoAccess with two URIs, one a FILE, the other a HTTP.
@@ -290,52 +218,32 @@ TEST(CertIssuerSourceAiaTest, OneFileOneHttpAia) {
scoped_refptr<ParsedCertificate> intermediate_cert;
ASSERT_TRUE(ReadTestCert("i2.pem", &intermediate_cert));
- StrictMock<MockIssuerCallback> mock_callback;
- StrictMock<MockCertNetFetcherImpl> mock_fetcher;
- CertIssuerSourceAia aia_source(&mock_fetcher);
- std::unique_ptr<CertIssuerSource::Request> cert_source_request;
- aia_source.AsyncGetIssuersOf(cert.get(),
- base::Bind(&MockIssuerCallback::Callback,
- base::Unretained(&mock_callback)),
- &cert_source_request);
- ASSERT_NE(nullptr, cert_source_request);
-
- RequestManager* req_manager =
- mock_fetcher.GetRequestManagerForURL(GURL("file:///dev/null"));
- ASSERT_TRUE(req_manager);
- ASSERT_TRUE(req_manager->is_request_alive());
+ auto mock_fetcher = make_scoped_refptr(new StrictMock<MockCertNetFetcher>());
- RequestManager* req_manager2 =
- mock_fetcher.GetRequestManagerForURL(GURL("http://url-for-aia2/I2.foo"));
- ASSERT_TRUE(req_manager2);
- ASSERT_TRUE(req_manager2->is_request_alive());
+ EXPECT_CALL(*mock_fetcher, FetchCaIssuers(GURL("file:///dev/null"), _, _))
+ .WillOnce(Return(ByMove(CreateMockRequest(ERR_DISALLOWED_URL_SCHEME))));
- // Request for file URL completes with disallowed scheme failure. Callback is
- // NOT called.
- req_manager->get_callback().Run(ERR_DISALLOWED_URL_SCHEME,
- std::vector<uint8_t>());
- Mock::VerifyAndClearExpectations(&mock_callback);
-
- // Request for I2.foo completes. Callback should be called now.
- EXPECT_CALL(mock_callback, Callback(cert_source_request.get()));
- req_manager2->get_callback().Run(OK, CertDataVector(intermediate_cert.get()));
- Mock::VerifyAndClearExpectations(&mock_callback);
+ EXPECT_CALL(*mock_fetcher,
+ FetchCaIssuers(GURL("http://url-for-aia2/I2.foo"), _, _))
+ .WillOnce(Return(
+ ByMove(CreateMockRequest(CertDataVector(intermediate_cert.get())))));
- scoped_refptr<ParsedCertificate> result_cert;
- CompletionStatus status = cert_source_request->GetNext(&result_cert);
- EXPECT_EQ(CompletionStatus::SYNC, status);
- ASSERT_TRUE(result_cert.get());
- ASSERT_EQ(result_cert->der_cert(), intermediate_cert->der_cert());
+ CertIssuerSourceAia aia_source(mock_fetcher);
+ std::unique_ptr<CertIssuerSource::Request> cert_source_request;
+ aia_source.AsyncGetIssuersOf(cert.get(), &cert_source_request);
+ ASSERT_NE(nullptr, cert_source_request);
- status = cert_source_request->GetNext(&result_cert);
- EXPECT_EQ(CompletionStatus::SYNC, status);
- EXPECT_FALSE(result_cert.get());
+ ParsedCertificateList result_certs;
+ cert_source_request->GetNext(&result_certs);
+ ASSERT_EQ(1u, result_certs.size());
+ ASSERT_EQ(result_certs.front()->der_cert(), intermediate_cert->der_cert());
- EXPECT_TRUE(req_manager2->is_request_alive());
- cert_source_request.reset();
- EXPECT_FALSE(req_manager2->is_request_alive());
+ cert_source_request->GetNext(&result_certs);
+ EXPECT_EQ(1u, result_certs.size());
}
+// TODO(eroman): Re-enable these tests!
+#if 0
// AuthorityInfoAccess with two URIs, one is invalid, the other HTTP.
TEST(CertIssuerSourceAiaTest, OneInvalidOneHttpAia) {
scoped_refptr<ParsedCertificate> cert;
@@ -344,8 +252,9 @@ TEST(CertIssuerSourceAiaTest, OneInvalidOneHttpAia) {
ASSERT_TRUE(ReadTestCert("i2.pem", &intermediate_cert));
StrictMock<MockIssuerCallback> mock_callback;
- StrictMock<MockCertNetFetcherImpl> mock_fetcher;
- CertIssuerSourceAia aia_source(&mock_fetcher);
+ scoped_refptr<StrictMock<MockCertNetFetcherImpl>> mock_fetcher(
+ new StrictMock<MockCertNetFetcherImpl>());
+ CertIssuerSourceAia aia_source(mock_fetcher);
std::unique_ptr<CertIssuerSource::Request> cert_source_request;
aia_source.AsyncGetIssuersOf(cert.get(),
base::Bind(&MockIssuerCallback::Callback,
@@ -389,8 +298,9 @@ TEST(CertIssuerSourceAiaTest, TwoAiaCompletedInSeries) {
ASSERT_TRUE(ReadTestCert("i2.pem", &intermediate_cert2));
StrictMock<MockIssuerCallback> mock_callback;
- StrictMock<MockCertNetFetcherImpl> mock_fetcher;
- CertIssuerSourceAia aia_source(&mock_fetcher);
+ scoped_refptr<StrictMock<MockCertNetFetcherImpl>> mock_fetcher(
+ new StrictMock<MockCertNetFetcherImpl>());
+ CertIssuerSourceAia aia_source(mock_fetcher);
std::unique_ptr<CertIssuerSource::Request> cert_source_request;
aia_source.AsyncGetIssuersOf(cert.get(),
base::Bind(&MockIssuerCallback::Callback,
@@ -465,8 +375,9 @@ TEST(CertIssuerSourceAiaTest, TwoAiaCompletedBeforeGetNext) {
ASSERT_TRUE(ReadTestCert("i2.pem", &intermediate_cert2));
StrictMock<MockIssuerCallback> mock_callback;
- StrictMock<MockCertNetFetcherImpl> mock_fetcher;
- CertIssuerSourceAia aia_source(&mock_fetcher);
+ scoped_refptr<StrictMock<MockCertNetFetcherImpl>> mock_fetcher(
+ new StrictMock<MockCertNetFetcherImpl>());
+ CertIssuerSourceAia aia_source(mock_fetcher);
std::unique_ptr<CertIssuerSource::Request> cert_source_request;
aia_source.AsyncGetIssuersOf(cert.get(),
base::Bind(&MockIssuerCallback::Callback,
@@ -537,8 +448,9 @@ TEST(CertIssuerSourceAiaTest, AiaRequestCompletesDuringGetNextSequence) {
ASSERT_TRUE(ReadTestCert("i3.pem", &intermediate_cert3));
StrictMock<MockIssuerCallback> mock_callback;
- StrictMock<MockCertNetFetcherImpl> mock_fetcher;
- CertIssuerSourceAia aia_source(&mock_fetcher);
+ scoped_refptr<StrictMock<MockCertNetFetcherImpl>> mock_fetcher(
+ new StrictMock<MockCertNetFetcherImpl>());
+ CertIssuerSourceAia aia_source(mock_fetcher);
std::unique_ptr<CertIssuerSource::Request> cert_source_request;
aia_source.AsyncGetIssuersOf(cert.get(),
base::Bind(&MockIssuerCallback::Callback,
@@ -613,8 +525,9 @@ TEST(CertIssuerSourceAiaTest, OneAiaHttpError) {
ASSERT_TRUE(ReadTestCert("target_one_aia.pem", &cert));
StrictMock<MockIssuerCallback> mock_callback;
- StrictMock<MockCertNetFetcherImpl> mock_fetcher;
- CertIssuerSourceAia aia_source(&mock_fetcher);
+ scoped_refptr<StrictMock<MockCertNetFetcherImpl>> mock_fetcher(
+ new StrictMock<MockCertNetFetcherImpl>());
+ CertIssuerSourceAia aia_source(mock_fetcher);
std::unique_ptr<CertIssuerSource::Request> cert_source_request;
aia_source.AsyncGetIssuersOf(cert.get(),
base::Bind(&MockIssuerCallback::Callback,
@@ -647,8 +560,9 @@ TEST(CertIssuerSourceAiaTest, OneAiaParseError) {
ASSERT_TRUE(ReadTestCert("target_one_aia.pem", &cert));
StrictMock<MockIssuerCallback> mock_callback;
- StrictMock<MockCertNetFetcherImpl> mock_fetcher;
- CertIssuerSourceAia aia_source(&mock_fetcher);
+ scoped_refptr<StrictMock<MockCertNetFetcherImpl>> mock_fetcher(
+ new StrictMock<MockCertNetFetcherImpl>());
+ CertIssuerSourceAia aia_source(mock_fetcher);
std::unique_ptr<CertIssuerSource::Request> cert_source_request;
aia_source.AsyncGetIssuersOf(cert.get(),
base::Bind(&MockIssuerCallback::Callback,
@@ -682,8 +596,9 @@ TEST(CertIssuerSourceAiaTest, TwoAiaCompletedInSeriesFirstFails) {
ASSERT_TRUE(ReadTestCert("i2.pem", &intermediate_cert2));
StrictMock<MockIssuerCallback> mock_callback;
- StrictMock<MockCertNetFetcherImpl> mock_fetcher;
- CertIssuerSourceAia aia_source(&mock_fetcher);
+ scoped_refptr<StrictMock<MockCertNetFetcherImpl>> mock_fetcher(
+ new StrictMock<MockCertNetFetcherImpl>());
+ CertIssuerSourceAia aia_source(mock_fetcher);
std::unique_ptr<CertIssuerSource::Request> cert_source_request;
aia_source.AsyncGetIssuersOf(cert.get(),
base::Bind(&MockIssuerCallback::Callback,
@@ -736,8 +651,9 @@ TEST(CertIssuerSourceAiaTest, TwoAiaCompletedInSeriesSecondFails) {
ASSERT_TRUE(ReadTestCert("i.pem", &intermediate_cert));
StrictMock<MockIssuerCallback> mock_callback;
- StrictMock<MockCertNetFetcherImpl> mock_fetcher;
- CertIssuerSourceAia aia_source(&mock_fetcher);
+ scoped_refptr<StrictMock<MockCertNetFetcherImpl>> mock_fetcher(
+ new StrictMock<MockCertNetFetcherImpl>());
+ CertIssuerSourceAia aia_source(mock_fetcher);
std::unique_ptr<CertIssuerSource::Request> cert_source_request;
aia_source.AsyncGetIssuersOf(cert.get(),
base::Bind(&MockIssuerCallback::Callback,
@@ -794,8 +710,9 @@ TEST(CertIssuerSourceAiaTest, CertSourceRequestCancelled) {
ASSERT_TRUE(ReadTestCert("target_two_aia.pem", &cert));
StrictMock<MockIssuerCallback> mock_callback;
- StrictMock<MockCertNetFetcherImpl> mock_fetcher;
- CertIssuerSourceAia aia_source(&mock_fetcher);
+ scoped_refptr<StrictMock<MockCertNetFetcherImpl>> mock_fetcher(
+ new StrictMock<MockCertNetFetcherImpl>());
+ CertIssuerSourceAia aia_source(mock_fetcher);
std::unique_ptr<CertIssuerSource::Request> cert_source_request;
aia_source.AsyncGetIssuersOf(cert.get(),
base::Bind(&MockIssuerCallback::Callback,
@@ -830,8 +747,9 @@ TEST(CertIssuerSourceAiaTest, TwoAiaOneCompletedThenRequestCancelled) {
ASSERT_TRUE(ReadTestCert("i.pem", &intermediate_cert));
StrictMock<MockIssuerCallback> mock_callback;
- StrictMock<MockCertNetFetcherImpl> mock_fetcher;
- CertIssuerSourceAia aia_source(&mock_fetcher);
+ scoped_refptr<StrictMock<MockCertNetFetcherImpl>> mock_fetcher(
+ new StrictMock<MockCertNetFetcherImpl>());
+ CertIssuerSourceAia aia_source(mock_fetcher);
std::unique_ptr<CertIssuerSource::Request> cert_source_request;
aia_source.AsyncGetIssuersOf(cert.get(),
base::Bind(&MockIssuerCallback::Callback,
@@ -881,8 +799,9 @@ TEST(CertIssuerSourceAiaTest, MaxFetchesPerCert) {
ASSERT_TRUE(ReadTestCert("target_six_aia.pem", &cert));
StrictMock<MockIssuerCallback> mock_callback;
- StrictMock<MockCertNetFetcherImpl> mock_fetcher;
- CertIssuerSourceAia aia_source(&mock_fetcher);
+ scoped_refptr<StrictMock<MockCertNetFetcherImpl>> mock_fetcher(
+ new StrictMock<MockCertNetFetcherImpl>());
+ CertIssuerSourceAia aia_source(mock_fetcher);
std::unique_ptr<CertIssuerSource::Request> cert_source_request;
aia_source.AsyncGetIssuersOf(cert.get(),
base::Bind(&MockIssuerCallback::Callback,
@@ -920,6 +839,8 @@ TEST(CertIssuerSourceAiaTest, MaxFetchesPerCert) {
mock_fetcher.GetRequestManagerForURL(GURL("http://url-for-aia6/I6.foo")));
}
+#endif
+
} // namespace
} // namespace net
diff --git a/chromium/net/cert/internal/cert_issuer_source_nss.cc b/chromium/net/cert/internal/cert_issuer_source_nss.cc
new file mode 100644
index 00000000000..418efe3ada6
--- /dev/null
+++ b/chromium/net/cert/internal/cert_issuer_source_nss.cc
@@ -0,0 +1,62 @@
+// Copyright 2016 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.
+
+#include "net/cert/internal/cert_issuer_source_nss.h"
+
+#include <cert.h>
+#include <certdb.h>
+
+#include "crypto/nss_util.h"
+#include "net/cert/internal/cert_errors.h"
+#include "net/cert/internal/parsed_certificate.h"
+
+namespace net {
+
+CertIssuerSourceNSS::CertIssuerSourceNSS() = default;
+CertIssuerSourceNSS::~CertIssuerSourceNSS() = default;
+
+void CertIssuerSourceNSS::SyncGetIssuersOf(const ParsedCertificate* cert,
+ ParsedCertificateList* issuers) {
+ crypto::EnsureNSSInit();
+
+ SECItem name;
+ // Use the original issuer value instead of the normalized version. NSS does a
+ // less extensive normalization in its Name comparisons, so our normalized
+ // version may not match the unnormalized version.
+ name.len = cert->tbs().issuer_tlv.Length();
+ name.data = const_cast<uint8_t*>(cert->tbs().issuer_tlv.UnsafeData());
+ // |validOnly| in CERT_CreateSubjectCertList controls whether to return only
+ // certs that are valid at |sorttime|. Including expired certs could lead to
+ // more useful error messages in the case where a valid path can't be found,
+ // so request all matches.
+ CERTCertList* found_certs = CERT_CreateSubjectCertList(
+ nullptr /* certList */, CERT_GetDefaultCertDB(), &name,
+ PR_Now() /* sorttime */, PR_FALSE /* validOnly */);
+ if (!found_certs)
+ return;
+
+ for (CERTCertListNode* node = CERT_LIST_HEAD(found_certs);
+ !CERT_LIST_END(node, found_certs); node = CERT_LIST_NEXT(node)) {
+ CertErrors errors;
+ scoped_refptr<ParsedCertificate> issuer_cert = ParsedCertificate::Create(
+ node->cert->derCert.data, node->cert->derCert.len, {}, &errors);
+ if (!issuer_cert) {
+ // TODO(crbug.com/634443): return errors better.
+ LOG(ERROR) << "Error parsing issuer certificate:\n"
+ << errors.ToDebugString();
+ continue;
+ }
+
+ issuers->push_back(std::move(issuer_cert));
+ }
+ CERT_DestroyCertList(found_certs);
+}
+
+void CertIssuerSourceNSS::AsyncGetIssuersOf(const ParsedCertificate* cert,
+ std::unique_ptr<Request>* out_req) {
+ // CertIssuerSourceNSS never returns asynchronous results.
+ out_req->reset();
+}
+
+} // namespace net
diff --git a/chromium/net/cert/internal/cert_issuer_source_nss.h b/chromium/net/cert/internal/cert_issuer_source_nss.h
new file mode 100644
index 00000000000..1621b3b0457
--- /dev/null
+++ b/chromium/net/cert/internal/cert_issuer_source_nss.h
@@ -0,0 +1,40 @@
+// Copyright 2016 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.
+
+#ifndef NET_CERT_INTERNAL_CERT_ISSUER_SOURCE_NSS_H_
+#define NET_CERT_INTERNAL_CERT_ISSUER_SOURCE_NSS_H_
+
+#include "net/base/net_export.h"
+#include "net/cert/internal/cert_issuer_source.h"
+
+namespace net {
+
+// Returns issuers from NSS. Always returns results synchronously.
+// This will return any matches from NSS, possibly including trust anchors,
+// blacklisted/distrusted certs, and temporary/cached certs. In the current
+// implementation, trust is checked in a separate stage of path building, so
+// including trusted certs here doesn't cause any issues. In particular, a trust
+// anchor being returned here indicates the path ending in that trust anchor
+// must already have been tested and failed to verify, and now the pathbuilder
+// is trying to find a different path through that certificate. Including
+// distrusted certs is desirable so that those paths can be built (and then fail
+// to verify), leading to a better error message.
+class NET_EXPORT CertIssuerSourceNSS : public CertIssuerSource {
+ public:
+ CertIssuerSourceNSS();
+ ~CertIssuerSourceNSS() override;
+
+ // CertIssuerSource implementation:
+ void SyncGetIssuersOf(const ParsedCertificate* cert,
+ ParsedCertificateList* issuers) override;
+ void AsyncGetIssuersOf(const ParsedCertificate* cert,
+ std::unique_ptr<Request>* out_req) override;
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(CertIssuerSourceNSS);
+};
+
+} // namespace net
+
+#endif // NET_CERT_INTERNAL_CERT_ISSUER_SOURCE_NSS_H_
diff --git a/chromium/net/cert/internal/cert_issuer_source_nss_unittest.cc b/chromium/net/cert/internal/cert_issuer_source_nss_unittest.cc
new file mode 100644
index 00000000000..1653998aa24
--- /dev/null
+++ b/chromium/net/cert/internal/cert_issuer_source_nss_unittest.cc
@@ -0,0 +1,62 @@
+// Copyright 2016 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.
+
+#include "net/cert/internal/cert_issuer_source_nss.h"
+
+#include <cert.h>
+#include <certdb.h>
+
+#include "base/strings/string_number_conversions.h"
+#include "crypto/scoped_test_nss_db.h"
+#include "net/cert/internal/cert_issuer_source_sync_unittest.h"
+#include "net/cert/scoped_nss_types.h"
+#include "net/cert/x509_certificate.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace net {
+
+namespace {
+
+class CertIssuerSourceNSSTestDelegate {
+ public:
+ void AddCert(scoped_refptr<ParsedCertificate> cert) {
+ ASSERT_TRUE(test_nssdb_.is_open());
+ std::string nickname = GetUniqueNickname();
+ ScopedCERTCertificate nss_cert(
+ X509Certificate::CreateOSCertHandleFromBytesWithNickname(
+ cert->der_cert().AsStringPiece().data(), cert->der_cert().Length(),
+ nickname.c_str()));
+ ASSERT_TRUE(nss_cert);
+ SECStatus srv =
+ PK11_ImportCert(test_nssdb_.slot(), nss_cert.get(), CK_INVALID_HANDLE,
+ nickname.c_str(), PR_FALSE /* includeTrust (unused) */);
+ ASSERT_EQ(SECSuccess, srv);
+ }
+
+ CertIssuerSource& source() { return cert_issuer_source_nss_; }
+
+ protected:
+ std::string GetUniqueNickname() {
+ return "cert_issuer_source_nss_unittest" +
+ base::UintToString(nickname_counter_++);
+ }
+
+ crypto::ScopedTestNSSDB test_nssdb_;
+ CertIssuerSourceNSS cert_issuer_source_nss_;
+ unsigned int nickname_counter_ = 0;
+};
+
+INSTANTIATE_TYPED_TEST_CASE_P(CertIssuerSourceNSSTest,
+ CertIssuerSourceSyncTest,
+ CertIssuerSourceNSSTestDelegate);
+
+// NSS doesn't normalize UTF8String values, so use the not-normalized version of
+// those tests.
+INSTANTIATE_TYPED_TEST_CASE_P(CertIssuerSourceNSSNotNormalizedTest,
+ CertIssuerSourceSyncNotNormalizedTest,
+ CertIssuerSourceNSSTestDelegate);
+
+} // namespace
+
+} // namespace net
diff --git a/chromium/net/cert/internal/cert_issuer_source_static.cc b/chromium/net/cert/internal/cert_issuer_source_static.cc
index d8a42a3f30e..e6ddb27b39f 100644
--- a/chromium/net/cert/internal/cert_issuer_source_static.cc
+++ b/chromium/net/cert/internal/cert_issuer_source_static.cc
@@ -24,7 +24,6 @@ void CertIssuerSourceStatic::SyncGetIssuersOf(const ParsedCertificate* cert,
void CertIssuerSourceStatic::AsyncGetIssuersOf(
const ParsedCertificate* cert,
- const IssuerCallback& issuers_callback,
std::unique_ptr<Request>* out_req) {
// CertIssuerSourceStatic never returns asynchronous results.
out_req->reset();
diff --git a/chromium/net/cert/internal/cert_issuer_source_static.h b/chromium/net/cert/internal/cert_issuer_source_static.h
index 143e97d660b..4f9240b6e94 100644
--- a/chromium/net/cert/internal/cert_issuer_source_static.h
+++ b/chromium/net/cert/internal/cert_issuer_source_static.h
@@ -27,7 +27,6 @@ class NET_EXPORT CertIssuerSourceStatic : public CertIssuerSource {
void SyncGetIssuersOf(const ParsedCertificate* cert,
ParsedCertificateList* issuers) override;
void AsyncGetIssuersOf(const ParsedCertificate* cert,
- const IssuerCallback& issuers_callback,
std::unique_ptr<Request>* out_req) override;
private:
diff --git a/chromium/net/cert/internal/cert_issuer_source_static_unittest.cc b/chromium/net/cert/internal/cert_issuer_source_static_unittest.cc
index 949035c0eb1..627757f6c6d 100644
--- a/chromium/net/cert/internal/cert_issuer_source_static_unittest.cc
+++ b/chromium/net/cert/internal/cert_issuer_source_static_unittest.cc
@@ -4,142 +4,33 @@
#include "net/cert/internal/cert_issuer_source_static.h"
-#include "base/bind.h"
-#include "net/cert/internal/cert_errors.h"
+#include "net/cert/internal/cert_issuer_source_sync_unittest.h"
#include "net/cert/internal/parsed_certificate.h"
-#include "net/cert/internal/test_helpers.h"
#include "testing/gtest/include/gtest/gtest.h"
namespace net {
namespace {
-void NotCalled(CertIssuerSource::Request* req) {
- ADD_FAILURE() << "NotCalled was called";
-}
-
-::testing::AssertionResult ReadTestPem(const std::string& file_name,
- const std::string& block_name,
- std::string* result) {
- const PemBlockMapping mappings[] = {
- {block_name.c_str(), result},
- };
-
- return ReadTestDataFromPemFile(file_name, mappings);
-}
-
-::testing::AssertionResult ReadTestCert(
- const std::string& file_name,
- scoped_refptr<ParsedCertificate>* result) {
- std::string der;
- ::testing::AssertionResult r =
- ReadTestPem("net/data/cert_issuer_source_static_unittest/" + file_name,
- "CERTIFICATE", &der);
- if (!r)
- return r;
- CertErrors errors;
- *result = ParsedCertificate::Create(der, {}, &errors);
- if (!*result) {
- return ::testing::AssertionFailure()
- << "ParsedCertificate::Create() failed:\n"
- << errors.ToDebugString();
- }
- return ::testing::AssertionSuccess();
-}
-
-class CertIssuerSourceStaticTest : public ::testing::Test {
+class CertIssuerSourceStaticTestDelegate {
public:
- void SetUp() override {
- ASSERT_TRUE(ReadTestCert("root.pem", &root_));
- ASSERT_TRUE(ReadTestCert("i1_1.pem", &i1_1_));
- ASSERT_TRUE(ReadTestCert("i1_2.pem", &i1_2_));
- ASSERT_TRUE(ReadTestCert("i2.pem", &i2_));
- ASSERT_TRUE(ReadTestCert("c1.pem", &c1_));
- ASSERT_TRUE(ReadTestCert("c2.pem", &c2_));
- ASSERT_TRUE(ReadTestCert("d.pem", &d_));
+ void AddCert(scoped_refptr<ParsedCertificate> cert) {
+ source_.AddCert(std::move(cert));
}
- void AddAllCerts(CertIssuerSourceStatic* source) {
- source->AddCert(root_);
- source->AddCert(i1_1_);
- source->AddCert(i1_2_);
- source->AddCert(i2_);
- source->AddCert(c1_);
- source->AddCert(c2_);
- source->AddCert(d_);
- }
+ CertIssuerSource& source() { return source_; }
protected:
- scoped_refptr<ParsedCertificate> root_;
- scoped_refptr<ParsedCertificate> i1_1_;
- scoped_refptr<ParsedCertificate> i1_2_;
- scoped_refptr<ParsedCertificate> i2_;
- scoped_refptr<ParsedCertificate> c1_;
- scoped_refptr<ParsedCertificate> c2_;
- scoped_refptr<ParsedCertificate> d_;
+ CertIssuerSourceStatic source_;
};
-TEST_F(CertIssuerSourceStaticTest, NoMatch) {
- CertIssuerSourceStatic source;
- source.AddCert(root_);
-
- ParsedCertificateList issuers;
- source.SyncGetIssuersOf(c1_.get(), &issuers);
- ASSERT_EQ(0U, issuers.size());
-}
-
-TEST_F(CertIssuerSourceStaticTest, OneMatch) {
- CertIssuerSourceStatic source;
- AddAllCerts(&source);
-
- ParsedCertificateList issuers;
- source.SyncGetIssuersOf(i1_1_.get(), &issuers);
- ASSERT_EQ(1U, issuers.size());
- EXPECT_TRUE(issuers[0] == root_);
-
- issuers.clear();
- source.SyncGetIssuersOf(d_.get(), &issuers);
- ASSERT_EQ(1U, issuers.size());
- EXPECT_TRUE(issuers[0] == i2_);
-}
-
-TEST_F(CertIssuerSourceStaticTest, MultipleMatches) {
- CertIssuerSourceStatic source;
- AddAllCerts(&source);
-
- ParsedCertificateList issuers;
- source.SyncGetIssuersOf(c1_.get(), &issuers);
-
- ASSERT_EQ(2U, issuers.size());
- EXPECT_TRUE(std::find(issuers.begin(), issuers.end(), i1_1_) !=
- issuers.end());
- EXPECT_TRUE(std::find(issuers.begin(), issuers.end(), i1_2_) !=
- issuers.end());
-}
-
-// Searching for the issuer of a self-issued cert returns the same cert if it
-// happens to be in the CertIssuerSourceStatic.
-// Conceptually this makes sense, though probably not very useful in practice.
-// Doesn't hurt anything though.
-TEST_F(CertIssuerSourceStaticTest, SelfIssued) {
- CertIssuerSourceStatic source;
- AddAllCerts(&source);
-
- ParsedCertificateList issuers;
- source.SyncGetIssuersOf(root_.get(), &issuers);
-
- ASSERT_EQ(1U, issuers.size());
- EXPECT_TRUE(issuers[0] == root_);
-}
+INSTANTIATE_TYPED_TEST_CASE_P(CertIssuerSourceStaticTest,
+ CertIssuerSourceSyncTest,
+ CertIssuerSourceStaticTestDelegate);
-// CertIssuerSourceStatic never returns results asynchronously.
-TEST_F(CertIssuerSourceStaticTest, IsNotAsync) {
- CertIssuerSourceStatic source;
- source.AddCert(i1_1_);
- std::unique_ptr<CertIssuerSource::Request> request;
- source.AsyncGetIssuersOf(c1_.get(), base::Bind(&NotCalled), &request);
- EXPECT_EQ(nullptr, request);
-}
+INSTANTIATE_TYPED_TEST_CASE_P(CertIssuerSourceStaticNormalizationTest,
+ CertIssuerSourceSyncNormalizationTest,
+ CertIssuerSourceStaticTestDelegate);
} // namespace
diff --git a/chromium/net/cert/internal/cert_issuer_source_sync_unittest.h b/chromium/net/cert/internal/cert_issuer_source_sync_unittest.h
new file mode 100644
index 00000000000..6b36b2fe28f
--- /dev/null
+++ b/chromium/net/cert/internal/cert_issuer_source_sync_unittest.h
@@ -0,0 +1,210 @@
+// Copyright 2016 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.
+
+#ifndef NET_CERT_INTERNAL_CERT_ISSUER_SOURCE_SYNC_UNITTEST_H_
+#define NET_CERT_INTERNAL_CERT_ISSUER_SOURCE_SYNC_UNITTEST_H_
+
+#include "net/cert/internal/cert_errors.h"
+#include "net/cert/internal/cert_issuer_source.h"
+#include "net/cert/internal/test_helpers.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace net {
+
+namespace {
+
+::testing::AssertionResult ReadTestPem(const std::string& file_name,
+ const std::string& block_name,
+ std::string* result) {
+ const PemBlockMapping mappings[] = {
+ {block_name.c_str(), result},
+ };
+
+ return ReadTestDataFromPemFile(file_name, mappings);
+}
+
+::testing::AssertionResult ReadTestCert(
+ const std::string& file_name,
+ scoped_refptr<ParsedCertificate>* result) {
+ std::string der;
+ ::testing::AssertionResult r =
+ ReadTestPem("net/data/cert_issuer_source_static_unittest/" + file_name,
+ "CERTIFICATE", &der);
+ if (!r)
+ return r;
+ CertErrors errors;
+ *result = ParsedCertificate::Create(der, {}, &errors);
+ if (!*result) {
+ return ::testing::AssertionFailure()
+ << "ParsedCertificate::Create() failed:\n"
+ << errors.ToDebugString();
+ }
+ return ::testing::AssertionSuccess();
+}
+
+} // namespace
+
+template <typename TestDelegate>
+class CertIssuerSourceSyncTest : public ::testing::Test {
+ public:
+ void SetUp() override {
+ ASSERT_TRUE(ReadTestCert("root.pem", &root_));
+ ASSERT_TRUE(ReadTestCert("i1_1.pem", &i1_1_));
+ ASSERT_TRUE(ReadTestCert("i1_2.pem", &i1_2_));
+ ASSERT_TRUE(ReadTestCert("i2.pem", &i2_));
+ ASSERT_TRUE(ReadTestCert("i3_1.pem", &i3_1_));
+ ASSERT_TRUE(ReadTestCert("i3_2.pem", &i3_2_));
+ ASSERT_TRUE(ReadTestCert("c1.pem", &c1_));
+ ASSERT_TRUE(ReadTestCert("c2.pem", &c2_));
+ ASSERT_TRUE(ReadTestCert("d.pem", &d_));
+ ASSERT_TRUE(ReadTestCert("e1.pem", &e1_));
+ ASSERT_TRUE(ReadTestCert("e2.pem", &e2_));
+ }
+
+ void AddCert(scoped_refptr<ParsedCertificate> cert) {
+ delegate_.AddCert(std::move(cert));
+ }
+
+ void AddAllCerts() {
+ AddCert(root_);
+ AddCert(i1_1_);
+ AddCert(i1_2_);
+ AddCert(i2_);
+ AddCert(i3_1_);
+ AddCert(i3_2_);
+ AddCert(c1_);
+ AddCert(c2_);
+ AddCert(d_);
+ AddCert(e1_);
+ AddCert(e2_);
+ }
+
+ CertIssuerSource& source() { return delegate_.source(); }
+
+ protected:
+ bool IssuersMatch(scoped_refptr<ParsedCertificate> cert,
+ ParsedCertificateList expected_matches) {
+ ParsedCertificateList matches;
+ source().SyncGetIssuersOf(cert.get(), &matches);
+
+ std::vector<der::Input> der_result_matches;
+ for (const auto& it : matches)
+ der_result_matches.push_back(it->der_cert());
+ std::sort(der_result_matches.begin(), der_result_matches.end());
+
+ std::vector<der::Input> der_expected_matches;
+ for (const auto& it : expected_matches)
+ der_expected_matches.push_back(it->der_cert());
+ std::sort(der_expected_matches.begin(), der_expected_matches.end());
+
+ if (der_expected_matches == der_result_matches)
+ return true;
+
+ // Print some extra information for debugging.
+ EXPECT_EQ(der_expected_matches, der_result_matches);
+ return false;
+ }
+
+ TestDelegate delegate_;
+ scoped_refptr<ParsedCertificate> root_;
+ scoped_refptr<ParsedCertificate> i1_1_;
+ scoped_refptr<ParsedCertificate> i1_2_;
+ scoped_refptr<ParsedCertificate> i2_;
+ scoped_refptr<ParsedCertificate> i3_1_;
+ scoped_refptr<ParsedCertificate> i3_2_;
+ scoped_refptr<ParsedCertificate> c1_;
+ scoped_refptr<ParsedCertificate> c2_;
+ scoped_refptr<ParsedCertificate> d_;
+ scoped_refptr<ParsedCertificate> e1_;
+ scoped_refptr<ParsedCertificate> e2_;
+};
+
+TYPED_TEST_CASE_P(CertIssuerSourceSyncTest);
+
+TYPED_TEST_P(CertIssuerSourceSyncTest, NoMatch) {
+ this->AddCert(this->root_);
+
+ EXPECT_TRUE(this->IssuersMatch(this->c1_, ParsedCertificateList()));
+}
+
+TYPED_TEST_P(CertIssuerSourceSyncTest, OneMatch) {
+ this->AddAllCerts();
+
+ EXPECT_TRUE(this->IssuersMatch(this->i1_1_, {this->root_}));
+ EXPECT_TRUE(this->IssuersMatch(this->d_, {this->i2_}));
+}
+
+TYPED_TEST_P(CertIssuerSourceSyncTest, MultipleMatches) {
+ this->AddAllCerts();
+
+ EXPECT_TRUE(this->IssuersMatch(this->e1_, {this->i3_1_, this->i3_2_}));
+ EXPECT_TRUE(this->IssuersMatch(this->e2_, {this->i3_1_, this->i3_2_}));
+}
+
+// Searching for the issuer of a self-issued cert returns the same cert if it
+// happens to be in the CertIssuerSourceStatic.
+// Conceptually this makes sense, though probably not very useful in practice.
+// Doesn't hurt anything though.
+TYPED_TEST_P(CertIssuerSourceSyncTest, SelfIssued) {
+ this->AddAllCerts();
+
+ EXPECT_TRUE(this->IssuersMatch(this->root_, {this->root_}));
+}
+
+// CertIssuerSourceStatic never returns results asynchronously.
+TYPED_TEST_P(CertIssuerSourceSyncTest, IsNotAsync) {
+ this->AddCert(this->i1_1_);
+ std::unique_ptr<CertIssuerSource::Request> request;
+ this->source().AsyncGetIssuersOf(this->c1_.get(), &request);
+ EXPECT_EQ(nullptr, request);
+}
+
+// These are all the tests that should have the same result with or without
+// normalization.
+REGISTER_TYPED_TEST_CASE_P(CertIssuerSourceSyncTest,
+ NoMatch,
+ OneMatch,
+ MultipleMatches,
+ SelfIssued,
+ IsNotAsync);
+
+template <typename TestDelegate>
+class CertIssuerSourceSyncNormalizationTest
+ : public CertIssuerSourceSyncTest<TestDelegate> {};
+TYPED_TEST_CASE_P(CertIssuerSourceSyncNormalizationTest);
+
+TYPED_TEST_P(CertIssuerSourceSyncNormalizationTest,
+ MultipleMatchesAfterNormalization) {
+ this->AddAllCerts();
+
+ EXPECT_TRUE(this->IssuersMatch(this->c1_, {this->i1_1_, this->i1_2_}));
+ EXPECT_TRUE(this->IssuersMatch(this->c2_, {this->i1_1_, this->i1_2_}));
+}
+
+// These tests require (utf8) normalization.
+REGISTER_TYPED_TEST_CASE_P(CertIssuerSourceSyncNormalizationTest,
+ MultipleMatchesAfterNormalization);
+
+template <typename TestDelegate>
+class CertIssuerSourceSyncNotNormalizedTest
+ : public CertIssuerSourceSyncTest<TestDelegate> {};
+TYPED_TEST_CASE_P(CertIssuerSourceSyncNotNormalizedTest);
+
+TYPED_TEST_P(CertIssuerSourceSyncNotNormalizedTest,
+ OneMatchWithoutNormalization) {
+ this->AddAllCerts();
+
+ // Without normalization c1 and c2 should at least be able to find their
+ // exact matching issuer. (c1 should match i1_1, and c2 should match i1_2.)
+ EXPECT_TRUE(this->IssuersMatch(this->c1_, {this->i1_1_}));
+ EXPECT_TRUE(this->IssuersMatch(this->c2_, {this->i1_2_}));
+}
+
+// These tests are for implementations which do not do utf8 normalization.
+REGISTER_TYPED_TEST_CASE_P(CertIssuerSourceSyncNotNormalizedTest,
+ OneMatchWithoutNormalization);
+
+} // namespace net
+
+#endif // NET_CERT_INTERNAL_CERT_ISSUER_SOURCE_SYNC_UNITTEST_H_
diff --git a/chromium/net/cert/internal/name_constraints.cc b/chromium/net/cert/internal/name_constraints.cc
index 162569f964c..0ed685101e9 100644
--- a/chromium/net/cert/internal/name_constraints.cc
+++ b/chromium/net/cert/internal/name_constraints.cc
@@ -87,6 +87,11 @@ bool DNSNameMatches(base::StringPiece name,
// Exact match.
if (name.size() == dns_constraint.size())
return true;
+ // If dNSName constraint starts with a dot, only subdomains should match.
+ // (e.g., "foo.bar.com" matches constraint ".bar.com", but "bar.com" doesn't.)
+ // RFC 5280 is ambiguous, but this matches the behavior of other platforms.
+ if (!dns_constraint.empty() && dns_constraint[0] == '.')
+ dns_constraint.remove_prefix(1);
// Subtree match.
if (name.size() > dns_constraint.size() &&
name[name.size() - dns_constraint.size() - 1] == '.') {
diff --git a/chromium/net/cert/internal/name_constraints_unittest.cc b/chromium/net/cert/internal/name_constraints_unittest.cc
index f1dd470d093..150d851c491 100644
--- a/chromium/net/cert/internal/name_constraints_unittest.cc
+++ b/chromium/net/cert/internal/name_constraints_unittest.cc
@@ -186,7 +186,7 @@ TEST_P(ParseNameConstraints,
EXPECT_FALSE(name_constraints->IsPermittedDNSName("*.foo.bar.com"));
}
-TEST_P(ParseNameConstraints, DNSNamesWithLeadingDot) {
+TEST_P(ParseNameConstraints, DNSNamesPermittedWithLeadingDot) {
std::string a;
ASSERT_TRUE(
LoadTestNameConstraint("dnsname-permitted_with_leading_dot.pem", &a));
@@ -194,13 +194,44 @@ TEST_P(ParseNameConstraints, DNSNamesWithLeadingDot) {
NameConstraints::Create(der::Input(&a), is_critical()));
ASSERT_TRUE(name_constraints);
- // dNSName constraints should be specified as a host. A dNSName constraint
- // with a leading "." doesn't make sense, though some certs include it
- // (probably confusing it with the rules for uniformResourceIdentifier
- // constraints). It should not match anything.
+ // A permitted dNSName constraint of ".bar.com" should only match subdomains
+ // of .bar.com, but not bar.com itself.
EXPECT_FALSE(name_constraints->IsPermittedDNSName("com"));
EXPECT_FALSE(name_constraints->IsPermittedDNSName("bar.com"));
+ EXPECT_FALSE(name_constraints->IsPermittedDNSName("foobar.com"));
+ EXPECT_TRUE(name_constraints->IsPermittedDNSName("foo.bar.com"));
+ EXPECT_TRUE(name_constraints->IsPermittedDNSName("*.bar.com"));
+}
+
+TEST_P(ParseNameConstraints, DNSNamesExcludedWithLeadingDot) {
+ std::string a;
+ ASSERT_TRUE(
+ LoadTestNameConstraint("dnsname-excluded_with_leading_dot.pem", &a));
+ std::unique_ptr<NameConstraints> name_constraints(
+ NameConstraints::Create(der::Input(&a), is_critical()));
+ ASSERT_TRUE(name_constraints);
+
+ // An excluded dNSName constraint of ".bar.com" should only match subdomains
+ // of .bar.com, but not bar.com itself.
+ EXPECT_TRUE(name_constraints->IsPermittedDNSName("com"));
+ EXPECT_TRUE(name_constraints->IsPermittedDNSName("bar.com"));
+ EXPECT_TRUE(name_constraints->IsPermittedDNSName("foobar.com"));
EXPECT_FALSE(name_constraints->IsPermittedDNSName("foo.bar.com"));
+ EXPECT_FALSE(name_constraints->IsPermittedDNSName("*.bar.com"));
+}
+
+TEST_P(ParseNameConstraints, DNSNamesPermittedTwoDot) {
+ std::string a;
+ ASSERT_TRUE(LoadTestNameConstraint("dnsname-permitted_two_dot.pem", &a));
+ std::unique_ptr<NameConstraints> name_constraints(
+ NameConstraints::Create(der::Input(&a), is_critical()));
+ ASSERT_TRUE(name_constraints);
+
+ // A dNSName constraint of ".." isn't meaningful. Shouldn't match anything.
+ EXPECT_FALSE(name_constraints->IsPermittedDNSName("com"));
+ EXPECT_FALSE(name_constraints->IsPermittedDNSName("com."));
+ EXPECT_FALSE(name_constraints->IsPermittedDNSName("foo.com"));
+ EXPECT_FALSE(name_constraints->IsPermittedDNSName("*.com"));
}
TEST_P(ParseNameConstraints, DNSNamesExcludeOnly) {
diff --git a/chromium/net/cert/internal/nist_pkits_unittest.h b/chromium/net/cert/internal/nist_pkits_unittest.h
index 47fd46274d6..6a454020ffb 100644
--- a/chromium/net/cert/internal/nist_pkits_unittest.h
+++ b/chromium/net/cert/internal/nist_pkits_unittest.h
@@ -2,8 +2,8 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#ifndef NET_CERT_INTERNAL_NIST_PKITS_UNITTEST_H
-#define NET_CERT_INTERNAL_NIST_PKITS_UNITTEST_H
+#ifndef NET_CERT_INTERNAL_NIST_PKITS_UNITTEST_H_
+#define NET_CERT_INTERNAL_NIST_PKITS_UNITTEST_H_
#include "net/cert/internal/test_helpers.h"
#include "testing/gtest/include/gtest/gtest.h"
@@ -33,4 +33,4 @@ class PkitsTest : public ::testing::Test {
// Inline the generated test code:
#include "net/third_party/nist-pkits/pkits_testcases-inl.h"
-#endif // NET_CERT_INTERNAL_NIST_PKITS_UNITTEST_H
+#endif // NET_CERT_INTERNAL_NIST_PKITS_UNITTEST_H_
diff --git a/chromium/net/cert/internal/parse_certificate_unittest.cc b/chromium/net/cert/internal/parse_certificate_unittest.cc
index 08c37944cea..a54d895acba 100644
--- a/chromium/net/cert/internal/parse_certificate_unittest.cc
+++ b/chromium/net/cert/internal/parse_certificate_unittest.cc
@@ -6,10 +6,6 @@
#include "base/strings/stringprintf.h"
#include "net/cert/internal/cert_errors.h"
-// TODO(eroman): These tests should be moved into
-// parsed_certificate_unittest.cc; this include dependency should
-// go.
-#include "net/cert/internal/parsed_certificate.h"
#include "net/cert/internal/test_helpers.h"
#include "net/der/input.h"
#include "testing/gtest/include/gtest/gtest.h"
@@ -79,37 +75,6 @@ void RunCertificateTest(const std::string& file_name) {
}
}
-// Reads and parses a certificate from the PEM file |file_name|.
-//
-// Returns nullptr if the certificate parsing failed, and verifies that any
-// errors match the ERRORS block in the .pem file.
-scoped_refptr<ParsedCertificate> ParseCertificateFromFile(
- const std::string& file_name) {
- std::string data;
- std::string expected_errors;
-
- // Read the certificate data and error expectations from a single PEM file.
- const PemBlockMapping mappings[] = {
- {"CERTIFICATE", &data}, {"ERRORS", &expected_errors, true /*optional*/},
- };
- std::string test_file_path = GetFilePath(file_name);
- EXPECT_TRUE(ReadTestDataFromPemFile(test_file_path, mappings));
-
- CertErrors errors;
- scoped_refptr<ParsedCertificate> cert =
- ParsedCertificate::Create(data, {}, &errors);
-
- EXPECT_EQ(expected_errors, errors.ToDebugString()) << "Test file: "
- << test_file_path;
-
- // TODO(crbug.com/634443): Every parse failure being tested should emit error
- // information.
- // if (!cert)
- // EXPECT_FALSE(errors.empty());
-
- return cert;
-}
-
// Tests parsing a Certificate.
TEST(ParseCertificateTest, Version3) {
RunCertificateTest("cert_version3.pem");
@@ -362,255 +327,6 @@ TEST(ParseTbsCertificateTest, ValidityRelaxed) {
RunTbsCertificateTest("tbs_validity_relaxed.pem");
}
-der::Input DavidBenOid() {
- // This OID corresponds with
- // 1.2.840.113554.4.1.72585.0 (https://davidben.net/oid)
- static const uint8_t kOid[] = {0x2a, 0x86, 0x48, 0x86, 0xf7, 0x12,
- 0x04, 0x01, 0x84, 0xb7, 0x09, 0x00};
- return der::Input(kOid);
-}
-
-// Parses an Extension whose critical field is true (255).
-TEST(ParseCertificateTest, ExtensionCritical) {
- scoped_refptr<ParsedCertificate> cert =
- ParseCertificateFromFile("extension_critical.pem");
- ASSERT_TRUE(cert);
-
- const uint8_t kExpectedValue[] = {0x30, 0x00};
-
- auto it = cert->unparsed_extensions().find(DavidBenOid());
- ASSERT_NE(cert->unparsed_extensions().end(), it);
- const auto& extension = it->second;
-
- EXPECT_TRUE(extension.critical);
- EXPECT_EQ(DavidBenOid(), extension.oid);
- EXPECT_EQ(der::Input(kExpectedValue), extension.value);
-}
-
-// Parses an Extension whose critical field is false (omitted).
-TEST(ParseCertificateTest, ExtensionNotCritical) {
- scoped_refptr<ParsedCertificate> cert =
- ParseCertificateFromFile("extension_not_critical.pem");
- ASSERT_TRUE(cert);
-
- const uint8_t kExpectedValue[] = {0x30, 0x00};
-
- auto it = cert->unparsed_extensions().find(DavidBenOid());
- ASSERT_NE(cert->unparsed_extensions().end(), it);
- const auto& extension = it->second;
-
- EXPECT_FALSE(extension.critical);
- EXPECT_EQ(DavidBenOid(), extension.oid);
- EXPECT_EQ(der::Input(kExpectedValue), extension.value);
-}
-
-// Parses an Extension whose critical field is 0. This is in one sense FALSE,
-// however because critical has DEFAULT of false this is in fact invalid
-// DER-encoding.
-TEST(ParseCertificateTest, ExtensionCritical0) {
- ASSERT_FALSE(ParseCertificateFromFile("extension_critical_0.pem"));
-}
-
-// Parses an Extension whose critical field is 3. Under DER-encoding BOOLEAN
-// values must an octet of either all zero bits, or all 1 bits, so this is not
-// valid.
-TEST(ParseCertificateTest, ExtensionCritical3) {
- ASSERT_FALSE(ParseCertificateFromFile("extension_critical_3.pem"));
-}
-
-// Parses an Extensions that is an empty sequence.
-TEST(ParseCertificateTest, ExtensionsEmptySequence) {
- ASSERT_FALSE(ParseCertificateFromFile("extensions_empty_sequence.pem"));
-}
-
-// Parses an Extensions that is not a sequence.
-TEST(ParseCertificateTest, ExtensionsNotSequence) {
- ASSERT_FALSE(ParseCertificateFromFile("extensions_not_sequence.pem"));
-}
-
-// Parses an Extensions that has data after the sequence.
-TEST(ParseCertificateTest, ExtensionsDataAfterSequence) {
- ASSERT_FALSE(ParseCertificateFromFile("extensions_data_after_sequence.pem"));
-}
-
-// Parses an Extensions that contains duplicated key usages.
-TEST(ParseCertificateTest, ExtensionsDuplicateKeyUsage) {
- ASSERT_FALSE(ParseCertificateFromFile("extensions_duplicate_key_usage.pem"));
-}
-
-// Parses an Extensions that contains an extended key usages.
-TEST(ParseCertificateTest, ExtendedKeyUsage) {
- scoped_refptr<ParsedCertificate> cert =
- ParseCertificateFromFile("extended_key_usage.pem");
- ASSERT_TRUE(cert);
-
- const auto& extensions = cert->unparsed_extensions();
- ASSERT_EQ(3u, extensions.size());
-
- auto iter = extensions.find(ExtKeyUsageOid());
- ASSERT_TRUE(iter != extensions.end());
- EXPECT_FALSE(iter->second.critical);
- EXPECT_EQ(45u, iter->second.value.Length());
-}
-
-// Parses an Extensions that contains a key usage.
-TEST(ParseCertificateTest, KeyUsage) {
- scoped_refptr<ParsedCertificate> cert =
- ParseCertificateFromFile("key_usage.pem");
- ASSERT_TRUE(cert);
-
- ASSERT_TRUE(cert->has_key_usage());
-
- EXPECT_EQ(5u, cert->key_usage().unused_bits());
- const uint8_t kExpectedBytes[] = {0xA0};
- EXPECT_EQ(der::Input(kExpectedBytes), cert->key_usage().bytes());
-
- EXPECT_TRUE(cert->key_usage().AssertsBit(0));
- EXPECT_FALSE(cert->key_usage().AssertsBit(1));
- EXPECT_TRUE(cert->key_usage().AssertsBit(2));
-}
-
-// Parses an Extensions that contains a policies extension.
-TEST(ParseCertificateTest, Policies) {
- scoped_refptr<ParsedCertificate> cert =
- ParseCertificateFromFile("policies.pem");
- ASSERT_TRUE(cert);
-
- const auto& extensions = cert->unparsed_extensions();
- ASSERT_EQ(3u, extensions.size());
-
- auto iter = extensions.find(CertificatePoliciesOid());
- ASSERT_TRUE(iter != extensions.end());
- EXPECT_FALSE(iter->second.critical);
- EXPECT_EQ(95u, iter->second.value.Length());
-}
-
-// Parses an Extensions that contains a subjectaltname extension.
-TEST(ParseCertificateTest, SubjectAltName) {
- scoped_refptr<ParsedCertificate> cert =
- ParseCertificateFromFile("subject_alt_name.pem");
- ASSERT_TRUE(cert);
-
- ASSERT_TRUE(cert->has_subject_alt_names());
-}
-
-// Parses an Extensions that contains multiple extensions, sourced from a
-// real-world certificate.
-TEST(ParseCertificateTest, ExtensionsReal) {
- scoped_refptr<ParsedCertificate> cert =
- ParseCertificateFromFile("extensions_real.pem");
- ASSERT_TRUE(cert);
-
- const auto& extensions = cert->unparsed_extensions();
- ASSERT_EQ(4u, extensions.size());
-
- EXPECT_TRUE(cert->has_key_usage());
- EXPECT_TRUE(cert->has_basic_constraints());
-
- auto iter = extensions.find(CertificatePoliciesOid());
- ASSERT_TRUE(iter != extensions.end());
- EXPECT_FALSE(iter->second.critical);
- EXPECT_EQ(16u, iter->second.value.Length());
-
- // TODO(eroman): Verify the other 4 extensions' values.
-}
-
-// Parses a BasicConstraints with no CA or pathlen.
-TEST(ParseCertificateTest, BasicConstraintsNotCa) {
- scoped_refptr<ParsedCertificate> cert =
- ParseCertificateFromFile("basic_constraints_not_ca.pem");
- ASSERT_TRUE(cert);
-
- EXPECT_TRUE(cert->has_basic_constraints());
- EXPECT_FALSE(cert->basic_constraints().is_ca);
- EXPECT_FALSE(cert->basic_constraints().has_path_len);
-}
-
-// Parses a BasicConstraints with CA but no pathlen.
-TEST(ParseCertificateTest, BasicConstraintsCaNoPath) {
- scoped_refptr<ParsedCertificate> cert =
- ParseCertificateFromFile("basic_constraints_ca_no_path.pem");
- ASSERT_TRUE(cert);
-
- EXPECT_TRUE(cert->has_basic_constraints());
- EXPECT_TRUE(cert->basic_constraints().is_ca);
- EXPECT_FALSE(cert->basic_constraints().has_path_len);
-}
-
-// Parses a BasicConstraints with CA and pathlen of 9.
-TEST(ParseCertificateTest, BasicConstraintsCaPath9) {
- scoped_refptr<ParsedCertificate> cert =
- ParseCertificateFromFile("basic_constraints_ca_path_9.pem");
- ASSERT_TRUE(cert);
-
- EXPECT_TRUE(cert->has_basic_constraints());
- EXPECT_TRUE(cert->basic_constraints().is_ca);
- EXPECT_TRUE(cert->basic_constraints().has_path_len);
- EXPECT_EQ(9u, cert->basic_constraints().path_len);
-}
-
-// Parses a BasicConstraints with CA and pathlen of 255 (largest allowed size).
-TEST(ParseCertificateTest, BasicConstraintsPathlen255) {
- scoped_refptr<ParsedCertificate> cert =
- ParseCertificateFromFile("basic_constraints_pathlen_255.pem");
- ASSERT_TRUE(cert);
-
- EXPECT_TRUE(cert->has_basic_constraints());
- EXPECT_TRUE(cert->basic_constraints().is_ca);
- EXPECT_TRUE(cert->basic_constraints().has_path_len);
- EXPECT_EQ(255, cert->basic_constraints().path_len);
-}
-
-// Parses a BasicConstraints with CA and pathlen of 256 (too large).
-TEST(ParseCertificateTest, BasicConstraintsPathlen256) {
- ASSERT_FALSE(ParseCertificateFromFile("basic_constraints_pathlen_256.pem"));
-}
-
-// Parses a BasicConstraints with CA and a negative pathlen.
-TEST(ParseCertificateTest, BasicConstraintsNegativePath) {
- ASSERT_FALSE(ParseCertificateFromFile("basic_constraints_negative_path.pem"));
-}
-
-// Parses a BasicConstraints with CA and pathlen that is very large (and
-// couldn't fit in a 64-bit integer).
-TEST(ParseCertificateTest, BasicConstraintsPathTooLarge) {
- ASSERT_FALSE(
- ParseCertificateFromFile("basic_constraints_path_too_large.pem"));
-}
-
-// Parses a BasicConstraints with CA explicitly set to false. This violates
-// DER-encoding rules, however is commonly used, so it is accepted.
-TEST(ParseCertificateTest, BasicConstraintsCaFalse) {
- scoped_refptr<ParsedCertificate> cert =
- ParseCertificateFromFile("basic_constraints_ca_false.pem");
- ASSERT_TRUE(cert);
-
- EXPECT_TRUE(cert->has_basic_constraints());
- EXPECT_FALSE(cert->basic_constraints().is_ca);
- EXPECT_FALSE(cert->basic_constraints().has_path_len);
-}
-
-// Parses a BasicConstraints with CA set to true and an unexpected NULL at
-// the end.
-TEST(ParseCertificateTest, BasicConstraintsUnconsumedData) {
- ASSERT_FALSE(
- ParseCertificateFromFile("basic_constraints_unconsumed_data.pem"));
-}
-
-// Parses a BasicConstraints with CA omitted (false), but with a pathlen of 1.
-// This is valid DER for the ASN.1, however is not valid when interpreting the
-// BasicConstraints at a higher level.
-TEST(ParseCertificateTest, BasicConstraintsPathLenButNotCa) {
- scoped_refptr<ParsedCertificate> cert =
- ParseCertificateFromFile("basic_constraints_pathlen_not_ca.pem");
- ASSERT_TRUE(cert);
-
- EXPECT_TRUE(cert->has_basic_constraints());
- EXPECT_FALSE(cert->basic_constraints().is_ca);
- EXPECT_TRUE(cert->basic_constraints().has_path_len);
- EXPECT_EQ(1u, cert->basic_constraints().path_len);
-}
-
// Parses a KeyUsage with a single 0 bit.
TEST(ParseKeyUsageTest, OneBitAllZeros) {
const uint8_t der[] = {
diff --git a/chromium/net/cert/internal/parse_ocsp.cc b/chromium/net/cert/internal/parse_ocsp.cc
index 2f734102270..0e13fc3d09a 100644
--- a/chromium/net/cert/internal/parse_ocsp.cc
+++ b/chromium/net/cert/internal/parse_ocsp.cc
@@ -5,6 +5,7 @@
#include <algorithm>
#include "base/sha1.h"
+#include "base/time/time.h"
#include "crypto/sha2.h"
#include "net/cert/internal/cert_errors.h"
#include "net/cert/internal/parse_ocsp.h"
diff --git a/chromium/net/cert/internal/parsed_certificate_unittest.cc b/chromium/net/cert/internal/parsed_certificate_unittest.cc
new file mode 100644
index 00000000000..ab1d4a0f91c
--- /dev/null
+++ b/chromium/net/cert/internal/parsed_certificate_unittest.cc
@@ -0,0 +1,303 @@
+// Copyright 2017 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.
+
+#include "net/cert/internal/parsed_certificate.h"
+
+#include "net/cert/internal/cert_errors.h"
+#include "net/cert/internal/parse_certificate.h"
+#include "net/cert/internal/test_helpers.h"
+#include "net/der/input.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace net {
+
+namespace {
+
+std::string GetFilePath(const std::string& file_name) {
+ return std::string("net/data/parse_certificate_unittest/") + file_name;
+}
+
+// Reads and parses a certificate from the PEM file |file_name|.
+//
+// Returns nullptr if the certificate parsing failed, and verifies that any
+// errors match the ERRORS block in the .pem file.
+scoped_refptr<ParsedCertificate> ParseCertificateFromFile(
+ const std::string& file_name) {
+ std::string data;
+ std::string expected_errors;
+
+ // Read the certificate data and error expectations from a single PEM file.
+ const PemBlockMapping mappings[] = {
+ {"CERTIFICATE", &data}, {"ERRORS", &expected_errors, true /*optional*/},
+ };
+ std::string test_file_path = GetFilePath(file_name);
+ EXPECT_TRUE(ReadTestDataFromPemFile(test_file_path, mappings));
+
+ CertErrors errors;
+ scoped_refptr<ParsedCertificate> cert =
+ ParsedCertificate::Create(data, {}, &errors);
+
+ EXPECT_EQ(expected_errors, errors.ToDebugString()) << "Test file: "
+ << test_file_path;
+
+ // TODO(crbug.com/634443): Every parse failure being tested should emit error
+ // information.
+ // if (!cert)
+ // EXPECT_FALSE(errors.empty());
+
+ return cert;
+}
+
+der::Input DavidBenOid() {
+ // This OID corresponds with
+ // 1.2.840.113554.4.1.72585.0 (https://davidben.net/oid)
+ static const uint8_t kOid[] = {0x2a, 0x86, 0x48, 0x86, 0xf7, 0x12,
+ 0x04, 0x01, 0x84, 0xb7, 0x09, 0x00};
+ return der::Input(kOid);
+}
+
+// Parses an Extension whose critical field is true (255).
+TEST(ParsedCertificateTest, ExtensionCritical) {
+ scoped_refptr<ParsedCertificate> cert =
+ ParseCertificateFromFile("extension_critical.pem");
+ ASSERT_TRUE(cert);
+
+ const uint8_t kExpectedValue[] = {0x30, 0x00};
+
+ auto it = cert->unparsed_extensions().find(DavidBenOid());
+ ASSERT_NE(cert->unparsed_extensions().end(), it);
+ const auto& extension = it->second;
+
+ EXPECT_TRUE(extension.critical);
+ EXPECT_EQ(DavidBenOid(), extension.oid);
+ EXPECT_EQ(der::Input(kExpectedValue), extension.value);
+}
+
+// Parses an Extension whose critical field is false (omitted).
+TEST(ParsedCertificateTest, ExtensionNotCritical) {
+ scoped_refptr<ParsedCertificate> cert =
+ ParseCertificateFromFile("extension_not_critical.pem");
+ ASSERT_TRUE(cert);
+
+ const uint8_t kExpectedValue[] = {0x30, 0x00};
+
+ auto it = cert->unparsed_extensions().find(DavidBenOid());
+ ASSERT_NE(cert->unparsed_extensions().end(), it);
+ const auto& extension = it->second;
+
+ EXPECT_FALSE(extension.critical);
+ EXPECT_EQ(DavidBenOid(), extension.oid);
+ EXPECT_EQ(der::Input(kExpectedValue), extension.value);
+}
+
+// Parses an Extension whose critical field is 0. This is in one sense FALSE,
+// however because critical has DEFAULT of false this is in fact invalid
+// DER-encoding.
+TEST(ParsedCertificateTest, ExtensionCritical0) {
+ ASSERT_FALSE(ParseCertificateFromFile("extension_critical_0.pem"));
+}
+
+// Parses an Extension whose critical field is 3. Under DER-encoding BOOLEAN
+// values must an octet of either all zero bits, or all 1 bits, so this is not
+// valid.
+TEST(ParsedCertificateTest, ExtensionCritical3) {
+ ASSERT_FALSE(ParseCertificateFromFile("extension_critical_3.pem"));
+}
+
+// Parses an Extensions that is an empty sequence.
+TEST(ParsedCertificateTest, ExtensionsEmptySequence) {
+ ASSERT_FALSE(ParseCertificateFromFile("extensions_empty_sequence.pem"));
+}
+
+// Parses an Extensions that is not a sequence.
+TEST(ParsedCertificateTest, ExtensionsNotSequence) {
+ ASSERT_FALSE(ParseCertificateFromFile("extensions_not_sequence.pem"));
+}
+
+// Parses an Extensions that has data after the sequence.
+TEST(ParsedCertificateTest, ExtensionsDataAfterSequence) {
+ ASSERT_FALSE(ParseCertificateFromFile("extensions_data_after_sequence.pem"));
+}
+
+// Parses an Extensions that contains duplicated key usages.
+TEST(ParsedCertificateTest, ExtensionsDuplicateKeyUsage) {
+ ASSERT_FALSE(ParseCertificateFromFile("extensions_duplicate_key_usage.pem"));
+}
+
+// Parses an Extensions that contains an extended key usages.
+TEST(ParsedCertificateTest, ExtendedKeyUsage) {
+ scoped_refptr<ParsedCertificate> cert =
+ ParseCertificateFromFile("extended_key_usage.pem");
+ ASSERT_TRUE(cert);
+
+ const auto& extensions = cert->unparsed_extensions();
+ ASSERT_EQ(3u, extensions.size());
+
+ auto iter = extensions.find(ExtKeyUsageOid());
+ ASSERT_TRUE(iter != extensions.end());
+ EXPECT_FALSE(iter->second.critical);
+ EXPECT_EQ(45u, iter->second.value.Length());
+}
+
+// Parses an Extensions that contains a key usage.
+TEST(ParsedCertificateTest, KeyUsage) {
+ scoped_refptr<ParsedCertificate> cert =
+ ParseCertificateFromFile("key_usage.pem");
+ ASSERT_TRUE(cert);
+
+ ASSERT_TRUE(cert->has_key_usage());
+
+ EXPECT_EQ(5u, cert->key_usage().unused_bits());
+ const uint8_t kExpectedBytes[] = {0xA0};
+ EXPECT_EQ(der::Input(kExpectedBytes), cert->key_usage().bytes());
+
+ EXPECT_TRUE(cert->key_usage().AssertsBit(0));
+ EXPECT_FALSE(cert->key_usage().AssertsBit(1));
+ EXPECT_TRUE(cert->key_usage().AssertsBit(2));
+}
+
+// Parses an Extensions that contains a policies extension.
+TEST(ParsedCertificateTest, Policies) {
+ scoped_refptr<ParsedCertificate> cert =
+ ParseCertificateFromFile("policies.pem");
+ ASSERT_TRUE(cert);
+
+ const auto& extensions = cert->unparsed_extensions();
+ ASSERT_EQ(3u, extensions.size());
+
+ auto iter = extensions.find(CertificatePoliciesOid());
+ ASSERT_TRUE(iter != extensions.end());
+ EXPECT_FALSE(iter->second.critical);
+ EXPECT_EQ(95u, iter->second.value.Length());
+}
+
+// Parses an Extensions that contains a subjectaltname extension.
+TEST(ParsedCertificateTest, SubjectAltName) {
+ scoped_refptr<ParsedCertificate> cert =
+ ParseCertificateFromFile("subject_alt_name.pem");
+ ASSERT_TRUE(cert);
+
+ ASSERT_TRUE(cert->has_subject_alt_names());
+}
+
+// Parses an Extensions that contains multiple extensions, sourced from a
+// real-world certificate.
+TEST(ParsedCertificateTest, ExtensionsReal) {
+ scoped_refptr<ParsedCertificate> cert =
+ ParseCertificateFromFile("extensions_real.pem");
+ ASSERT_TRUE(cert);
+
+ const auto& extensions = cert->unparsed_extensions();
+ ASSERT_EQ(4u, extensions.size());
+
+ EXPECT_TRUE(cert->has_key_usage());
+ EXPECT_TRUE(cert->has_basic_constraints());
+
+ auto iter = extensions.find(CertificatePoliciesOid());
+ ASSERT_TRUE(iter != extensions.end());
+ EXPECT_FALSE(iter->second.critical);
+ EXPECT_EQ(16u, iter->second.value.Length());
+
+ // TODO(eroman): Verify the other 4 extensions' values.
+}
+
+// Parses a BasicConstraints with no CA or pathlen.
+TEST(ParsedCertificateTest, BasicConstraintsNotCa) {
+ scoped_refptr<ParsedCertificate> cert =
+ ParseCertificateFromFile("basic_constraints_not_ca.pem");
+ ASSERT_TRUE(cert);
+
+ EXPECT_TRUE(cert->has_basic_constraints());
+ EXPECT_FALSE(cert->basic_constraints().is_ca);
+ EXPECT_FALSE(cert->basic_constraints().has_path_len);
+}
+
+// Parses a BasicConstraints with CA but no pathlen.
+TEST(ParsedCertificateTest, BasicConstraintsCaNoPath) {
+ scoped_refptr<ParsedCertificate> cert =
+ ParseCertificateFromFile("basic_constraints_ca_no_path.pem");
+ ASSERT_TRUE(cert);
+
+ EXPECT_TRUE(cert->has_basic_constraints());
+ EXPECT_TRUE(cert->basic_constraints().is_ca);
+ EXPECT_FALSE(cert->basic_constraints().has_path_len);
+}
+
+// Parses a BasicConstraints with CA and pathlen of 9.
+TEST(ParsedCertificateTest, BasicConstraintsCaPath9) {
+ scoped_refptr<ParsedCertificate> cert =
+ ParseCertificateFromFile("basic_constraints_ca_path_9.pem");
+ ASSERT_TRUE(cert);
+
+ EXPECT_TRUE(cert->has_basic_constraints());
+ EXPECT_TRUE(cert->basic_constraints().is_ca);
+ EXPECT_TRUE(cert->basic_constraints().has_path_len);
+ EXPECT_EQ(9u, cert->basic_constraints().path_len);
+}
+
+// Parses a BasicConstraints with CA and pathlen of 255 (largest allowed size).
+TEST(ParsedCertificateTest, BasicConstraintsPathlen255) {
+ scoped_refptr<ParsedCertificate> cert =
+ ParseCertificateFromFile("basic_constraints_pathlen_255.pem");
+ ASSERT_TRUE(cert);
+
+ EXPECT_TRUE(cert->has_basic_constraints());
+ EXPECT_TRUE(cert->basic_constraints().is_ca);
+ EXPECT_TRUE(cert->basic_constraints().has_path_len);
+ EXPECT_EQ(255, cert->basic_constraints().path_len);
+}
+
+// Parses a BasicConstraints with CA and pathlen of 256 (too large).
+TEST(ParsedCertificateTest, BasicConstraintsPathlen256) {
+ ASSERT_FALSE(ParseCertificateFromFile("basic_constraints_pathlen_256.pem"));
+}
+
+// Parses a BasicConstraints with CA and a negative pathlen.
+TEST(ParsedCertificateTest, BasicConstraintsNegativePath) {
+ ASSERT_FALSE(ParseCertificateFromFile("basic_constraints_negative_path.pem"));
+}
+
+// Parses a BasicConstraints with CA and pathlen that is very large (and
+// couldn't fit in a 64-bit integer).
+TEST(ParsedCertificateTest, BasicConstraintsPathTooLarge) {
+ ASSERT_FALSE(
+ ParseCertificateFromFile("basic_constraints_path_too_large.pem"));
+}
+
+// Parses a BasicConstraints with CA explicitly set to false. This violates
+// DER-encoding rules, however is commonly used, so it is accepted.
+TEST(ParsedCertificateTest, BasicConstraintsCaFalse) {
+ scoped_refptr<ParsedCertificate> cert =
+ ParseCertificateFromFile("basic_constraints_ca_false.pem");
+ ASSERT_TRUE(cert);
+
+ EXPECT_TRUE(cert->has_basic_constraints());
+ EXPECT_FALSE(cert->basic_constraints().is_ca);
+ EXPECT_FALSE(cert->basic_constraints().has_path_len);
+}
+
+// Parses a BasicConstraints with CA set to true and an unexpected NULL at
+// the end.
+TEST(ParsedCertificateTest, BasicConstraintsUnconsumedData) {
+ ASSERT_FALSE(
+ ParseCertificateFromFile("basic_constraints_unconsumed_data.pem"));
+}
+
+// Parses a BasicConstraints with CA omitted (false), but with a pathlen of 1.
+// This is valid DER for the ASN.1, however is not valid when interpreting the
+// BasicConstraints at a higher level.
+TEST(ParsedCertificateTest, BasicConstraintsPathLenButNotCa) {
+ scoped_refptr<ParsedCertificate> cert =
+ ParseCertificateFromFile("basic_constraints_pathlen_not_ca.pem");
+ ASSERT_TRUE(cert);
+
+ EXPECT_TRUE(cert->has_basic_constraints());
+ EXPECT_FALSE(cert->basic_constraints().is_ca);
+ EXPECT_TRUE(cert->basic_constraints().has_path_len);
+ EXPECT_EQ(1u, cert->basic_constraints().path_len);
+}
+
+} // namespace
+
+} // namespace net
diff --git a/chromium/net/cert/internal/path_builder.cc b/chromium/net/cert/internal/path_builder.cc
index 36cd9d45f8d..bb4283eeed6 100644
--- a/chromium/net/cert/internal/path_builder.cc
+++ b/chromium/net/cert/internal/path_builder.cc
@@ -7,7 +7,6 @@
#include <set>
#include <unordered_set>
-#include "base/callback_helpers.h"
#include "base/logging.h"
#include "base/memory/ptr_util.h"
#include "net/base/net_errors.h"
@@ -71,24 +70,20 @@ class CertIssuersIter {
CertIssuerSources* cert_issuer_sources,
const TrustStore* trust_store);
- // Gets the next candidate issuer. If an issuer is ready synchronously, SYNC
- // is returned and the cert is stored in |*cert|. If an issuer is not
- // ready, ASYNC is returned and |callback| will be called once |*out_cert| has
- // been set. If |callback| is null, always completes synchronously.
- //
- // In either case, if all issuers have been exhausted, |*out| is cleared.
- CompletionStatus GetNextIssuer(CertificateOrTrustAnchor* out,
- const base::Closure& callback);
+ // Gets the next candidate issuer, or clears |*out| when all issuers have been
+ // exhausted.
+ void GetNextIssuer(CertificateOrTrustAnchor* out);
// Returns the |cert| for which issuers are being retrieved.
const ParsedCertificate* cert() const { return cert_.get(); }
scoped_refptr<ParsedCertificate> reference_cert() const { return cert_; }
private:
+ void AddIssuers(ParsedCertificateList issuers);
void DoAsyncIssuerQuery();
- void GotAsyncAnchors(TrustAnchors anchors);
- void GotAsyncCerts(CertIssuerSource::Request* request);
- void NotifyIfNecessary();
+
+ // Returns true if |issuers_| contains unconsumed certificates.
+ bool HasCurrentIssuer() const { return cur_issuer_ < issuers_.size(); }
scoped_refptr<ParsedCertificate> cert_;
CertIssuerSources* cert_issuer_sources_;
@@ -119,19 +114,12 @@ class CertIssuersIter {
// Tracks which requests have been made yet.
bool did_initial_query_ = false;
bool did_async_issuer_query_ = false;
- // If asynchronous requests were made, how many of them are still outstanding?
- size_t pending_async_results_;
+ // Index into pending_async_requests_ that is the next one to process.
+ size_t cur_async_request_ = 0;
// Owns the Request objects for any asynchronous requests so that they will be
// cancelled if CertIssuersIter is destroyed.
std::vector<std::unique_ptr<CertIssuerSource::Request>>
pending_async_requests_;
- std::unique_ptr<TrustStore::Request> pending_anchor_request_;
-
- // When GetNextIssuer was called and returned asynchronously, |*out_| is
- // where the result will be stored, and |callback_| will be run when the
- // result is ready.
- CertificateOrTrustAnchor* out_;
- base::Closure callback_;
DISALLOW_COPY_AND_ASSIGN(CertIssuersIter);
};
@@ -145,30 +133,15 @@ CertIssuersIter::CertIssuersIter(scoped_refptr<ParsedCertificate> in_cert,
DVLOG(1) << "CertIssuersIter(" << CertDebugString(cert()) << ") created";
}
-CompletionStatus CertIssuersIter::GetNextIssuer(CertificateOrTrustAnchor* out,
- const base::Closure& callback) {
- // Should not be called again while already waiting for an async result.
- DCHECK(callback_.is_null());
-
+void CertIssuersIter::GetNextIssuer(CertificateOrTrustAnchor* out) {
if (!did_initial_query_) {
did_initial_query_ = true;
- trust_store_->FindTrustAnchorsForCert(
- cert_,
- callback.is_null() ? TrustStore::TrustAnchorsCallback()
- : base::Bind(&CertIssuersIter::GotAsyncAnchors,
- base::Unretained(this)),
- &anchors_, &pending_anchor_request_);
+ trust_store_->FindTrustAnchorsForCert(cert_, &anchors_);
for (auto* cert_issuer_source : *cert_issuer_sources_) {
ParsedCertificateList new_issuers;
cert_issuer_source->SyncGetIssuersOf(cert(), &new_issuers);
- for (scoped_refptr<ParsedCertificate>& issuer : new_issuers) {
- if (present_issuers_.find(issuer->der_cert().AsStringPiece()) !=
- present_issuers_.end())
- continue;
- present_issuers_.insert(issuer->der_cert().AsStringPiece());
- issuers_.push_back(std::move(issuer));
- }
+ AddIssuers(std::move(new_issuers));
}
DVLOG(1) << anchors_.size() << " sync anchors, " << issuers_.size()
<< " sync issuers";
@@ -186,18 +159,33 @@ CompletionStatus CertIssuersIter::GetNextIssuer(CertificateOrTrustAnchor* out,
<< anchors_.size();
// Still have anchors that haven't been returned yet, return one of them.
*out = CertificateOrTrustAnchor(anchors_[cur_anchor_++]);
- return CompletionStatus::SYNC;
+ return;
}
- if (pending_anchor_request_) {
- DVLOG(1) << "CertIssuersIter(" << CertDebugString(cert())
- << ") Still waiting for async trust anchor results.";
- out_ = out;
- callback_ = callback;
- return CompletionStatus::ASYNC;
+ // If there aren't any issuers left, block until async results are ready.
+ if (!HasCurrentIssuer()) {
+ if (!did_async_issuer_query_) {
+ // Now issue request(s) for async ones (AIA, etc).
+ DoAsyncIssuerQuery();
+ }
+
+ // TODO(eroman): Rather than blocking on the async requests in FIFO order,
+ // consume in the order they become ready.
+ while (!HasCurrentIssuer() &&
+ cur_async_request_ < pending_async_requests_.size()) {
+ ParsedCertificateList new_issuers;
+ pending_async_requests_[cur_async_request_]->GetNext(&new_issuers);
+ if (new_issuers.empty()) {
+ // Request is exhausted, no more results pending from that
+ // CertIssuerSource.
+ pending_async_requests_[cur_async_request_++].reset();
+ } else {
+ AddIssuers(std::move(new_issuers));
+ }
+ }
}
- if (cur_issuer_ < issuers_.size()) {
+ if (HasCurrentIssuer()) {
DVLOG(1) << "CertIssuersIter(" << CertDebugString(cert())
<< "): returning issuer " << cur_issuer_ << " of "
<< issuers_.size();
@@ -205,148 +193,40 @@ CompletionStatus CertIssuersIter::GetNextIssuer(CertificateOrTrustAnchor* out,
// A reference to the returned issuer is retained, since |present_issuers_|
// points to data owned by it.
*out = CertificateOrTrustAnchor(issuers_[cur_issuer_++]);
- return CompletionStatus::SYNC;
- }
-
- if (did_async_issuer_query_) {
- if (pending_async_results_ == 0) {
- DVLOG(1) << "CertIssuersIter(" << CertDebugString(cert())
- << ") Reached the end of all available issuers.";
- // Reached the end of all available issuers.
- *out = CertificateOrTrustAnchor();
- return CompletionStatus::SYNC;
- }
-
- DVLOG(1) << "CertIssuersIter(" << CertDebugString(cert())
- << ") Still waiting for async results from other "
- "CertIssuerSources.";
- // Still waiting for async results from other CertIssuerSources.
- out_ = out;
- callback_ = callback;
- return CompletionStatus::ASYNC;
+ return;
}
- // Reached the end of synchronously gathered issuers.
- if (callback.is_null()) {
- // Synchronous-only mode, don't try to query async sources.
- *out = CertificateOrTrustAnchor();
- return CompletionStatus::SYNC;
- }
-
- // Now issue request(s) for async ones (AIA, etc).
- DoAsyncIssuerQuery();
+ DVLOG(1) << "CertIssuersIter(" << CertDebugString(cert())
+ << ") Reached the end of all available issuers.";
+ // Reached the end of all available issuers.
+ *out = CertificateOrTrustAnchor();
+}
- if (pending_async_results_ == 0) {
- DVLOG(1) << "CertIssuersIter(" << CertDebugString(cert())
- << ") No cert sources have async results.";
- // No cert sources have async results.
- *out = CertificateOrTrustAnchor();
- return CompletionStatus::SYNC;
+void CertIssuersIter::AddIssuers(ParsedCertificateList new_issuers) {
+ for (scoped_refptr<ParsedCertificate>& issuer : new_issuers) {
+ if (present_issuers_.find(issuer->der_cert().AsStringPiece()) !=
+ present_issuers_.end())
+ continue;
+ present_issuers_.insert(issuer->der_cert().AsStringPiece());
+ issuers_.push_back(std::move(issuer));
}
-
- DVLOG(1) << "CertIssuersIter(" << CertDebugString(cert())
- << ") issued AsyncGetIssuersOf call(s) (n=" << pending_async_results_
- << ")";
- out_ = out;
- callback_ = callback;
- return CompletionStatus::ASYNC;
}
void CertIssuersIter::DoAsyncIssuerQuery() {
DCHECK(!did_async_issuer_query_);
did_async_issuer_query_ = true;
- pending_async_results_ = 0;
+ cur_async_request_ = 0;
for (auto* cert_issuer_source : *cert_issuer_sources_) {
std::unique_ptr<CertIssuerSource::Request> request;
- cert_issuer_source->AsyncGetIssuersOf(
- cert(),
- base::Bind(&CertIssuersIter::GotAsyncCerts, base::Unretained(this)),
- &request);
+ cert_issuer_source->AsyncGetIssuersOf(cert(), &request);
if (request) {
DVLOG(1) << "AsyncGetIssuersOf(" << CertDebugString(cert())
<< ") pending...";
- pending_async_results_++;
pending_async_requests_.push_back(std::move(request));
}
}
}
-void CertIssuersIter::GotAsyncAnchors(TrustAnchors anchors) {
- DVLOG(1) << "CertIssuersIter::GotAsyncAnchors(" << CertDebugString(cert())
- << "): " << anchors.size() << " anchors";
- for (scoped_refptr<TrustAnchor>& anchor : anchors)
- anchors_.push_back(std::move(anchor));
- pending_anchor_request_.reset();
-
- NotifyIfNecessary();
-}
-
-void CertIssuersIter::GotAsyncCerts(CertIssuerSource::Request* request) {
- DVLOG(1) << "CertIssuersIter::GotAsyncCerts(" << CertDebugString(cert())
- << ")";
- while (true) {
- scoped_refptr<ParsedCertificate> cert;
- CompletionStatus status = request->GetNext(&cert);
- if (!cert) {
- if (status == CompletionStatus::SYNC) {
- // Request is exhausted, no more results pending from that
- // CertIssuerSource.
- DCHECK_GT(pending_async_results_, 0U);
- pending_async_results_--;
- }
- break;
- }
- DCHECK_EQ(status, CompletionStatus::SYNC);
- if (present_issuers_.find(cert->der_cert().AsStringPiece()) !=
- present_issuers_.end())
- continue;
- present_issuers_.insert(cert->der_cert().AsStringPiece());
- issuers_.push_back(std::move(cert));
- }
-
- // TODO(mattm): re-sort remaining elements of issuers_ (remaining elements may
- // be more than the ones just inserted, depending on |cur_| value).
-
- NotifyIfNecessary();
-}
-
-void CertIssuersIter::NotifyIfNecessary() {
- // Notify that more results are available, if necessary.
- if (!callback_.is_null()) {
- if (cur_anchor_ < anchors_.size()) {
- DVLOG(1) << "CertIssuersIter(" << CertDebugString(cert())
- << "): async returning anchor " << cur_anchor_ << " of "
- << anchors_.size();
- *out_ = CertificateOrTrustAnchor(std::move(anchors_[cur_anchor_++]));
- base::ResetAndReturn(&callback_).Run();
- return;
- }
- if (cur_issuer_ < issuers_.size()) {
- DCHECK(!pending_anchor_request_);
- DVLOG(1) << "CertIssuersIter(" << CertDebugString(cert())
- << "): async returning issuer " << cur_issuer_ << " of "
- << issuers_.size();
- *out_ = CertificateOrTrustAnchor(std::move(issuers_[cur_issuer_++]));
- base::ResetAndReturn(&callback_).Run();
- return;
- }
-
- if (!did_async_issuer_query_)
- DoAsyncIssuerQuery();
-
- if (pending_async_results_ == 0) {
- DVLOG(1) << "CertIssuersIter(" << CertDebugString(cert())
- << "): async returning empty result";
- *out_ = CertificateOrTrustAnchor();
- base::ResetAndReturn(&callback_).Run();
- return;
- }
- DVLOG(1) << "CertIssuersIter(" << CertDebugString(cert())
- << "): empty result, but other async results "
- "pending, waiting..";
- }
-}
-
// CertIssuerIterPath tracks which certs are present in the path and prevents
// paths from being built which repeat any certs (including different versions
// of the same cert, based on Subject+SubjectAltName+SPKI).
@@ -446,11 +326,9 @@ class CertPathIter {
// CertPathIter.
void AddCertIssuerSource(CertIssuerSource* cert_issuer_source);
- // Gets the next candidate path. If a path is ready synchronously, SYNC is
- // returned and the path is stored in |*path|. If a path is not ready,
- // ASYNC is returned and |callback| will be called once |*path| has been set.
- // In either case, if all paths have been exhausted, |*path| is cleared.
- CompletionStatus GetNextPath(CertPath* path, const base::Closure& callback);
+ // Gets the next candidate path, or clears |*path| when all paths have been
+ // exhausted.
+ void GetNextPath(CertPath* path);
private:
enum State {
@@ -461,13 +339,9 @@ class CertPathIter {
STATE_BACKTRACK,
};
- CompletionStatus DoLoop(bool allow_async);
-
- CompletionStatus DoGetNextIssuer(bool allow_async);
- CompletionStatus DoGetNextIssuerComplete();
- CompletionStatus DoBackTrack();
-
- void HandleGotNextIssuer(void);
+ void DoGetNextIssuer();
+ void DoGetNextIssuerComplete();
+ void DoBackTrack();
// Stores the next candidate issuer, until it is used during the
// STATE_GET_NEXT_ISSUER_COMPLETE step.
@@ -483,8 +357,6 @@ class CertPathIter {
// The output variable for storing the next candidate path, which the client
// passes in to GetNextPath. Only used for a single path output.
CertPath* out_path_;
- // The callback to be called if an async lookup generated a candidate path.
- base::Closure callback_;
// Current state of the state machine.
State next_state_;
@@ -501,22 +373,10 @@ void CertPathIter::AddCertIssuerSource(CertIssuerSource* cert_issuer_source) {
cert_issuer_sources_.push_back(cert_issuer_source);
}
-CompletionStatus CertPathIter::GetNextPath(CertPath* path,
- const base::Closure& callback) {
+// TODO(eroman): Simplify (doesn't need to use the "DoLoop" pattern).
+void CertPathIter::GetNextPath(CertPath* path) {
out_path_ = path;
out_path_->Clear();
- CompletionStatus rv = DoLoop(!callback.is_null());
- if (rv == CompletionStatus::ASYNC) {
- callback_ = callback;
- } else {
- // Clear the reference to the output parameter as a precaution.
- out_path_ = nullptr;
- }
- return rv;
-}
-
-CompletionStatus CertPathIter::DoLoop(bool allow_async) {
- CompletionStatus result = CompletionStatus::SYNC;
do {
State state = next_state_;
next_state_ = STATE_NONE;
@@ -525,39 +385,32 @@ CompletionStatus CertPathIter::DoLoop(bool allow_async) {
NOTREACHED();
break;
case STATE_GET_NEXT_ISSUER:
- result = DoGetNextIssuer(allow_async);
+ DoGetNextIssuer();
break;
case STATE_GET_NEXT_ISSUER_COMPLETE:
- result = DoGetNextIssuerComplete();
+ DoGetNextIssuerComplete();
break;
case STATE_RETURN_A_PATH:
// If the returned path did not verify, keep looking for other paths
// (the trust root is not part of cur_path_, so don't need to
// backtrack).
next_state_ = STATE_GET_NEXT_ISSUER;
- result = CompletionStatus::SYNC;
break;
case STATE_BACKTRACK:
- result = DoBackTrack();
+ DoBackTrack();
break;
}
- } while (result == CompletionStatus::SYNC && next_state_ != STATE_NONE &&
- next_state_ != STATE_RETURN_A_PATH);
+ } while (next_state_ != STATE_NONE && next_state_ != STATE_RETURN_A_PATH);
- return result;
+ out_path_ = nullptr;
}
-CompletionStatus CertPathIter::DoGetNextIssuer(bool allow_async) {
+void CertPathIter::DoGetNextIssuer() {
next_state_ = STATE_GET_NEXT_ISSUER_COMPLETE;
- CompletionStatus rv = cur_path_.back()->GetNextIssuer(
- &next_issuer_, allow_async
- ? base::Bind(&CertPathIter::HandleGotNextIssuer,
- base::Unretained(this))
- : base::Closure());
- return rv;
+ cur_path_.back()->GetNextIssuer(&next_issuer_);
}
-CompletionStatus CertPathIter::DoGetNextIssuerComplete() {
+void CertPathIter::DoGetNextIssuerComplete() {
// If the issuer is a trust anchor signal readiness.
if (next_issuer_.IsTrustAnchor()) {
DVLOG(1) << "CertPathIter got anchor("
@@ -566,14 +419,14 @@ CompletionStatus CertPathIter::DoGetNextIssuerComplete() {
cur_path_.CopyPath(&out_path_->certs);
out_path_->trust_anchor = std::move(next_issuer_.anchor);
next_issuer_ = CertificateOrTrustAnchor();
- return CompletionStatus::SYNC;
+ return;
}
if (next_issuer_.IsCertificate()) {
// Skip this cert if it is already in the chain.
if (cur_path_.IsPresent(next_issuer_.cert.get())) {
next_state_ = STATE_GET_NEXT_ISSUER;
- return CompletionStatus::SYNC;
+ return;
}
cur_path_.Append(base::MakeUnique<CertIssuersIter>(
@@ -590,10 +443,9 @@ CompletionStatus CertPathIter::DoGetNextIssuerComplete() {
// more for the previous cert.
next_state_ = STATE_BACKTRACK;
}
- return CompletionStatus::SYNC;
}
-CompletionStatus CertPathIter::DoBackTrack() {
+void CertPathIter::DoBackTrack() {
DVLOG(1) << "CertPathIter backtracking...";
cur_path_.Pop();
if (cur_path_.Empty()) {
@@ -603,17 +455,6 @@ CompletionStatus CertPathIter::DoBackTrack() {
// Continue exploring issuers of the previous path.
next_state_ = STATE_GET_NEXT_ISSUER;
}
- return CompletionStatus::SYNC;
-}
-
-void CertPathIter::HandleGotNextIssuer(void) {
- DCHECK(!callback_.is_null());
- CompletionStatus rv = DoLoop(true /* allow_async */);
- if (rv == CompletionStatus::SYNC) {
- // Clear the reference to the output parameter as a precaution.
- out_path_ = nullptr;
- base::ResetAndReturn(&callback_).Run();
- }
}
CertPathBuilder::ResultPath::ResultPath() = default;
@@ -658,19 +499,10 @@ void CertPathBuilder::AddCertIssuerSource(
cert_path_iter_->AddCertIssuerSource(cert_issuer_source);
}
-CompletionStatus CertPathBuilder::Run(const base::Closure& callback) {
+// TODO(eroman): Simplify (doesn't need to use the "DoLoop" pattern).
+void CertPathBuilder::Run() {
DCHECK_EQ(STATE_NONE, next_state_);
next_state_ = STATE_GET_NEXT_PATH;
- CompletionStatus rv = DoLoop(!callback.is_null());
-
- if (rv == CompletionStatus::ASYNC)
- callback_ = callback;
-
- return rv;
-}
-
-CompletionStatus CertPathBuilder::DoLoop(bool allow_async) {
- CompletionStatus result = CompletionStatus::SYNC;
do {
State state = next_state_;
@@ -680,38 +512,25 @@ CompletionStatus CertPathBuilder::DoLoop(bool allow_async) {
NOTREACHED();
break;
case STATE_GET_NEXT_PATH:
- result = DoGetNextPath(allow_async);
+ DoGetNextPath();
break;
case STATE_GET_NEXT_PATH_COMPLETE:
- result = DoGetNextPathComplete();
+ DoGetNextPathComplete();
break;
}
- } while (result == CompletionStatus::SYNC && next_state_ != STATE_NONE);
-
- return result;
+ } while (next_state_ != STATE_NONE);
}
-CompletionStatus CertPathBuilder::DoGetNextPath(bool allow_async) {
+void CertPathBuilder::DoGetNextPath() {
next_state_ = STATE_GET_NEXT_PATH_COMPLETE;
- CompletionStatus rv = cert_path_iter_->GetNextPath(
- &next_path_, allow_async ? base::Bind(&CertPathBuilder::HandleGotNextPath,
- base::Unretained(this))
- : base::Closure());
- return rv;
-}
-
-void CertPathBuilder::HandleGotNextPath() {
- DCHECK(!callback_.is_null());
- CompletionStatus rv = DoLoop(true /* allow_async */);
- if (rv == CompletionStatus::SYNC)
- base::ResetAndReturn(&callback_).Run();
+ cert_path_iter_->GetNextPath(&next_path_);
}
-CompletionStatus CertPathBuilder::DoGetNextPathComplete() {
+void CertPathBuilder::DoGetNextPathComplete() {
if (next_path_.IsEmpty()) {
// No more paths to check, signal completion.
next_state_ = STATE_NONE;
- return CompletionStatus::SYNC;
+ return;
}
// Verify the entire certificate chain.
@@ -729,14 +548,13 @@ CompletionStatus CertPathBuilder::DoGetNextPathComplete() {
// Found a valid path, return immediately.
// TODO(mattm): add debug/test mode that tries all possible paths.
next_state_ = STATE_NONE;
- return CompletionStatus::SYNC;
+ return;
}
// Path did not verify. Try more paths. If there are no more paths, the result
// will be returned next time DoGetNextPathComplete is called with next_path_
// empty.
next_state_ = STATE_GET_NEXT_PATH;
- return CompletionStatus::SYNC;
}
void CertPathBuilder::AddResultPath(std::unique_ptr<ResultPath> result_path) {
diff --git a/chromium/net/cert/internal/path_builder.h b/chromium/net/cert/internal/path_builder.h
index 69784f333b0..ee39ed67ee5 100644
--- a/chromium/net/cert/internal/path_builder.h
+++ b/chromium/net/cert/internal/path_builder.h
@@ -9,11 +9,8 @@
#include <string>
#include <vector>
-#include "base/callback.h"
-#include "net/base/completion_callback.h"
#include "net/base/net_export.h"
#include "net/cert/internal/cert_errors.h"
-#include "net/cert/internal/completion_status.h"
#include "net/cert/internal/parsed_certificate.h"
#include "net/cert/internal/trust_store.h"
#include "net/der/input.h"
@@ -107,6 +104,9 @@ class NET_EXPORT CertPathBuilder {
// TODO(mattm): allow caller specified hook/callback to extend path
// verification.
//
+ // TODO(eroman): The assumption is that |result| is default initialized. Can
+ // probably just internalize |result| into CertPathBuilder.
+ //
// Creates a CertPathBuilder that attempts to find a path from |cert| to a
// trust anchor in |trust_store|, which satisfies |signature_policy| and is
// valid at |time|. Details of attempted path(s) are stored in |*result|.
@@ -129,24 +129,12 @@ class NET_EXPORT CertPathBuilder {
// it is a trust anchor or is directly signed by a trust anchor.)
void AddCertIssuerSource(CertIssuerSource* cert_issuer_source);
- // Begins verification of the target certificate.
- //
- // If the return value is SYNC then the verification is complete and the
- // |result| value can be inspected for the status, and |callback| will not be
- // called.
- // If the return value is ASYNC, the |callback| will be called asynchronously
- // once the verification is complete. |result| should not be examined or
- // modified until the |callback| is run.
- //
- // If |callback| is null, verification always completes synchronously, even if
- // it fails to find a valid path and one could have been found asynchronously.
+ // Executes verification of the target certificate.
//
- // The CertPathBuilder may be deleted while an ASYNC verification is pending,
- // in which case the verification is cancelled, |callback| will not be called,
- // and the output Result will be in an undefined state.
- // It is safe to delete the CertPathBuilder during the |callback|.
- // Run must not be called more than once on each CertPathBuilder instance.
- CompletionStatus Run(const base::Closure& callback);
+ // Upon return results are written to the |result| object passed into the
+ // constructor. Run must not be called more than once on each CertPathBuilder
+ // instance.
+ void Run();
private:
enum State {
@@ -155,16 +143,11 @@ class NET_EXPORT CertPathBuilder {
STATE_GET_NEXT_PATH_COMPLETE,
};
- CompletionStatus DoLoop(bool allow_async);
-
- CompletionStatus DoGetNextPath(bool allow_async);
- void HandleGotNextPath();
- CompletionStatus DoGetNextPathComplete();
+ void DoGetNextPath();
+ void DoGetNextPathComplete();
void AddResultPath(std::unique_ptr<ResultPath> result_path);
- base::Closure callback_;
-
std::unique_ptr<CertPathIter> cert_path_iter_;
const SignaturePolicy* signature_policy_;
const der::GeneralizedTime time_;
diff --git a/chromium/net/cert/internal/path_builder_pkits_unittest.cc b/chromium/net/cert/internal/path_builder_pkits_unittest.cc
index 4039428687e..b362519319d 100644
--- a/chromium/net/cert/internal/path_builder_pkits_unittest.cc
+++ b/chromium/net/cert/internal/path_builder_pkits_unittest.cc
@@ -90,8 +90,7 @@ class PathBuilderPkitsTestDelegate {
&signature_policy, time, &result);
path_builder.AddCertIssuerSource(&cert_issuer_source);
- CompletionStatus rv = path_builder.Run(base::Closure());
- EXPECT_EQ(CompletionStatus::SYNC, rv);
+ path_builder.Run();
return result.HasValidPath();
}
diff --git a/chromium/net/cert/internal/path_builder_unittest.cc b/chromium/net/cert/internal/path_builder_unittest.cc
index 5f0a2eb6234..35fe1542905 100644
--- a/chromium/net/cert/internal/path_builder_unittest.cc
+++ b/chromium/net/cert/internal/path_builder_unittest.cc
@@ -5,18 +5,14 @@
#include "net/cert/internal/path_builder.h"
#include "base/base_paths.h"
-#include "base/cancelable_callback.h"
#include "base/files/file_util.h"
-#include "base/location.h"
#include "base/path_service.h"
-#include "base/threading/thread_task_runner_handle.h"
-#include "net/base/test_completion_callback.h"
#include "net/cert/internal/cert_issuer_source_static.h"
#include "net/cert/internal/parsed_certificate.h"
#include "net/cert/internal/signature_policy.h"
#include "net/cert/internal/test_helpers.h"
+#include "net/cert/internal/trust_store_collection.h"
#include "net/cert/internal/trust_store_in_memory.h"
-#include "net/cert/internal/trust_store_test_helpers.h"
#include "net/cert/internal/verify_certificate_chain.h"
#include "net/cert/pem_tokenizer.h"
#include "net/der/input.h"
@@ -44,32 +40,17 @@ class AsyncCertIssuerSourceStatic : public CertIssuerSource {
public:
class StaticAsyncRequest : public Request {
public:
- StaticAsyncRequest(const IssuerCallback& issuers_callback,
- ParsedCertificateList&& issuers)
- : cancelable_closure_(base::Bind(&StaticAsyncRequest::RunCallback,
- base::Unretained(this))),
- issuers_callback_(issuers_callback) {
+ StaticAsyncRequest(ParsedCertificateList&& issuers) {
issuers_.swap(issuers);
issuers_iter_ = issuers_.begin();
}
~StaticAsyncRequest() override {}
- CompletionStatus GetNext(
- scoped_refptr<ParsedCertificate>* out_cert) override {
- if (issuers_iter_ == issuers_.end())
- *out_cert = nullptr;
- else
- *out_cert = std::move(*issuers_iter_++);
- return CompletionStatus::SYNC;
+ void GetNext(ParsedCertificateList* out_certs) override {
+ if (issuers_iter_ != issuers_.end())
+ out_certs->push_back(std::move(*issuers_iter_++));
}
- base::Closure callback() { return cancelable_closure_.callback(); }
-
- private:
- void RunCallback() { issuers_callback_.Run(this); }
-
- base::CancelableClosure cancelable_closure_;
- IssuerCallback issuers_callback_;
ParsedCertificateList issuers_;
ParsedCertificateList::iterator issuers_iter_;
@@ -85,14 +66,12 @@ class AsyncCertIssuerSourceStatic : public CertIssuerSource {
void SyncGetIssuersOf(const ParsedCertificate* cert,
ParsedCertificateList* issuers) override {}
void AsyncGetIssuersOf(const ParsedCertificate* cert,
- const IssuerCallback& issuers_callback,
std::unique_ptr<Request>* out_req) override {
num_async_gets_++;
ParsedCertificateList issuers;
static_cert_issuer_source_.SyncGetIssuersOf(cert, &issuers);
std::unique_ptr<StaticAsyncRequest> req(
- new StaticAsyncRequest(issuers_callback, std::move(issuers)));
- base::ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE, req->callback());
+ new StaticAsyncRequest(std::move(issuers)));
*out_req = std::move(req);
}
int num_async_gets() const { return num_async_gets_; }
@@ -131,21 +110,6 @@ class AsyncCertIssuerSourceStatic : public CertIssuerSource {
return ::testing::AssertionSuccess();
}
-// Run the path builder, and wait for async completion if necessary. The return
-// value signifies whether the path builder completed synchronously or
-// asynchronously, not that RunPathBuilder itself is asynchronous.
-CompletionStatus RunPathBuilder(CertPathBuilder* path_builder) {
- TestClosure callback;
- CompletionStatus rv = path_builder->Run(callback.closure());
-
- if (rv == CompletionStatus::ASYNC) {
- DVLOG(1) << "waiting for async completion...";
- callback.WaitForResult();
- DVLOG(1) << "async completed.";
- }
- return rv;
-}
-
class PathBuilderMultiRootTest : public ::testing::Test {
public:
PathBuilderMultiRootTest() : signature_policy_(1024) {}
@@ -194,7 +158,7 @@ TEST_F(PathBuilderMultiRootTest, TargetHasNameAndSpkiOfTrustAnchor) {
CertPathBuilder path_builder(a_by_b_, &trust_store, &signature_policy_, time_,
&result);
- EXPECT_EQ(CompletionStatus::SYNC, RunPathBuilder(&path_builder));
+ path_builder.Run();
ASSERT_TRUE(result.HasValidPath());
const auto& path = result.GetBestValidPath()->path;
@@ -214,7 +178,7 @@ TEST_F(PathBuilderMultiRootTest, TargetWithSameNameAsTrustAnchorFails) {
CertPathBuilder path_builder(a_by_b_, &trust_store, &signature_policy_, time_,
&result);
- EXPECT_EQ(CompletionStatus::SYNC, RunPathBuilder(&path_builder));
+ path_builder.Run();
EXPECT_FALSE(result.HasValidPath());
}
@@ -245,7 +209,7 @@ TEST_F(PathBuilderMultiRootTest, SelfSignedTrustAnchorSupplementalCert) {
expired_time, &result);
path_builder.AddCertIssuerSource(&sync_certs);
- EXPECT_EQ(CompletionStatus::SYNC, RunPathBuilder(&path_builder));
+ path_builder.Run();
EXPECT_FALSE(result.HasValidPath());
ASSERT_EQ(2U, result.paths.size());
@@ -277,7 +241,7 @@ TEST_F(PathBuilderMultiRootTest, TargetIsSelfSignedTrustAnchor) {
CertPathBuilder path_builder(e_by_e_, &trust_store, &signature_policy_, time_,
&result);
- EXPECT_EQ(CompletionStatus::SYNC, RunPathBuilder(&path_builder));
+ path_builder.Run();
ASSERT_TRUE(result.HasValidPath());
const auto& path = result.GetBestValidPath()->path;
@@ -296,7 +260,7 @@ TEST_F(PathBuilderMultiRootTest, TargetDirectlySignedByTrustAnchor) {
CertPathBuilder path_builder(a_by_b_, &trust_store, &signature_policy_, time_,
&result);
- EXPECT_EQ(CompletionStatus::SYNC, RunPathBuilder(&path_builder));
+ path_builder.Run();
ASSERT_TRUE(result.HasValidPath());
const auto& path = result.GetBestValidPath()->path;
@@ -325,35 +289,12 @@ TEST_F(PathBuilderMultiRootTest, TriesSyncFirst) {
path_builder.AddCertIssuerSource(&async_certs);
path_builder.AddCertIssuerSource(&sync_certs);
- EXPECT_EQ(CompletionStatus::SYNC, RunPathBuilder(&path_builder));
+ path_builder.Run();
EXPECT_TRUE(result.HasValidPath());
EXPECT_EQ(0, async_certs.num_async_gets());
}
-// Test that async cert queries are not made if no callback is provided.
-TEST_F(PathBuilderMultiRootTest, SychronousOnlyMode) {
- TrustStoreInMemory trust_store;
- AddTrustedCertificate(e_by_e_, &trust_store);
-
- CertIssuerSourceStatic sync_certs;
- sync_certs.AddCert(f_by_e_);
-
- AsyncCertIssuerSourceStatic async_certs;
- async_certs.AddCert(b_by_f_);
-
- CertPathBuilder::Result result;
- CertPathBuilder path_builder(a_by_b_, &trust_store, &signature_policy_, time_,
- &result);
- path_builder.AddCertIssuerSource(&async_certs);
- path_builder.AddCertIssuerSource(&sync_certs);
-
- EXPECT_EQ(CompletionStatus::SYNC, path_builder.Run(base::Closure()));
-
- EXPECT_FALSE(result.HasValidPath());
- EXPECT_EQ(0, async_certs.num_async_gets());
-}
-
// If async queries are needed, all async sources will be queried
// simultaneously.
TEST_F(PathBuilderMultiRootTest, TestAsyncSimultaneous) {
@@ -377,7 +318,7 @@ TEST_F(PathBuilderMultiRootTest, TestAsyncSimultaneous) {
path_builder.AddCertIssuerSource(&async_certs2);
path_builder.AddCertIssuerSource(&sync_certs);
- EXPECT_EQ(CompletionStatus::ASYNC, RunPathBuilder(&path_builder));
+ path_builder.Run();
EXPECT_TRUE(result.HasValidPath());
EXPECT_EQ(1, async_certs1.num_async_gets());
@@ -402,7 +343,7 @@ TEST_F(PathBuilderMultiRootTest, TestLongChain) {
&result);
path_builder.AddCertIssuerSource(&sync_certs);
- EXPECT_EQ(CompletionStatus::SYNC, RunPathBuilder(&path_builder));
+ path_builder.Run();
ASSERT_TRUE(result.HasValidPath());
@@ -436,7 +377,7 @@ TEST_F(PathBuilderMultiRootTest, TestBacktracking) {
path_builder.AddCertIssuerSource(&sync_certs);
path_builder.AddCertIssuerSource(&async_certs);
- EXPECT_EQ(CompletionStatus::ASYNC, RunPathBuilder(&path_builder));
+ path_builder.Run();
ASSERT_TRUE(result.HasValidPath());
@@ -474,7 +415,7 @@ TEST_F(PathBuilderMultiRootTest, TestCertIssuerOrdering) {
time_, &result);
path_builder.AddCertIssuerSource(&sync_certs);
- EXPECT_EQ(CompletionStatus::SYNC, RunPathBuilder(&path_builder));
+ path_builder.Run();
ASSERT_TRUE(result.HasValidPath());
@@ -558,7 +499,7 @@ TEST_F(PathBuilderKeyRolloverTest, TestRolloverOnlyOldRootTrusted) {
&result);
path_builder.AddCertIssuerSource(&sync_certs);
- EXPECT_EQ(CompletionStatus::SYNC, RunPathBuilder(&path_builder));
+ path_builder.Run();
EXPECT_TRUE(result.HasValidPath());
@@ -606,7 +547,7 @@ TEST_F(PathBuilderKeyRolloverTest, TestRolloverBothRootsTrusted) {
&result);
path_builder.AddCertIssuerSource(&sync_certs);
- EXPECT_EQ(CompletionStatus::SYNC, RunPathBuilder(&path_builder));
+ path_builder.Run();
EXPECT_TRUE(result.HasValidPath());
@@ -630,141 +571,39 @@ TEST_F(PathBuilderKeyRolloverTest, TestRolloverBothRootsTrusted) {
}
}
-// If trust anchors are provided both synchronously and asynchronously for the
-// same cert, the synchronously provided ones should be tried first, and
-// pathbuilder should finish synchronously.
-TEST_F(PathBuilderKeyRolloverTest, TestSyncAnchorsPreferred) {
- TrustStoreInMemoryAsync trust_store;
- // Both oldintermediate and newintermediate are trusted, but oldintermediate
- // is returned synchronously and newintermediate asynchronously.
- trust_store.AddSyncTrustAnchor(
- TrustAnchor::CreateFromCertificateNoConstraints(oldintermediate_));
- trust_store.AddAsyncTrustAnchor(
- TrustAnchor::CreateFromCertificateNoConstraints(newintermediate_));
-
- CertPathBuilder::Result result;
- CertPathBuilder path_builder(target_, &trust_store, &signature_policy_, time_,
- &result);
-
- EXPECT_EQ(CompletionStatus::SYNC, RunPathBuilder(&path_builder));
-
- EXPECT_TRUE(result.HasValidPath());
-
- ASSERT_EQ(1U, result.paths.size());
- const auto& path = result.paths[0]->path;
- EXPECT_TRUE(result.paths[0]->valid);
- ASSERT_EQ(1U, path.certs.size());
- EXPECT_EQ(target_, path.certs[0]);
- EXPECT_EQ(oldintermediate_, path.trust_anchor->cert());
-}
-
-// Async trust anchor checks should be done before synchronous issuer checks are
-// considered. (Avoiding creating unnecessarily long paths.)
-//
-// Two valid paths could be built:
-// newintermediate <- newrootrollover <- oldroot
-// newintermediate <- newroot
-// One invalid path could be built:
-// newintermediate <- oldroot
-//
-// First: newintermediate <- oldroot will be tried, since oldroot is
-// available synchronously, but this path will not verify.
-// Second: newintermediate <- newroot should be built, even though
-// newrootrollover issuer is available synchronously and newroot is async. This
-// path should verify and pathbuilder will stop.
-TEST_F(PathBuilderKeyRolloverTest, TestAsyncAnchorsBeforeSyncIssuers) {
- TrustStoreInMemoryAsync trust_store;
- trust_store.AddSyncTrustAnchor(oldroot_);
- trust_store.AddAsyncTrustAnchor(
- TrustAnchor::CreateFromCertificateNoConstraints(newroot_));
-
- CertIssuerSourceStatic sync_certs;
- sync_certs.AddCert(newrootrollover_);
-
- CertPathBuilder::Result result;
- CertPathBuilder path_builder(newintermediate_, &trust_store,
- &signature_policy_, time_, &result);
- path_builder.AddCertIssuerSource(&sync_certs);
-
- EXPECT_EQ(CompletionStatus::ASYNC, RunPathBuilder(&path_builder));
-
- EXPECT_TRUE(result.HasValidPath());
-
- ASSERT_EQ(2U, result.paths.size());
- {
- const auto& path = result.paths[0]->path;
- EXPECT_FALSE(result.paths[0]->valid);
- ASSERT_EQ(1U, path.certs.size());
- EXPECT_EQ(newintermediate_, path.certs[0]);
- EXPECT_EQ(oldroot_, path.trust_anchor);
- }
- {
- const auto& path = result.paths[1]->path;
- EXPECT_TRUE(result.paths[1]->valid);
- ASSERT_EQ(1U, path.certs.size());
- EXPECT_EQ(newintermediate_, path.certs[0]);
- EXPECT_EQ(newroot_, path.trust_anchor->cert());
- }
-}
-
-// If async trust anchor query returned no results, and there are no issuer
+// If trust anchor query returned no results, and there are no issuer
// sources, path building should fail at that point.
-TEST_F(PathBuilderKeyRolloverTest, TestAsyncAnchorsNoMatchAndNoIssuerSources) {
- TrustStoreInMemoryAsync trust_store;
- trust_store.AddAsyncTrustAnchor(
+TEST_F(PathBuilderKeyRolloverTest, TestAnchorsNoMatchAndNoIssuerSources) {
+ TrustStoreInMemory trust_store;
+ trust_store.AddTrustAnchor(
TrustAnchor::CreateFromCertificateNoConstraints(newroot_));
CertPathBuilder::Result result;
CertPathBuilder path_builder(target_, &trust_store, &signature_policy_, time_,
&result);
- EXPECT_EQ(CompletionStatus::ASYNC, RunPathBuilder(&path_builder));
+ path_builder.Run();
EXPECT_FALSE(result.HasValidPath());
ASSERT_EQ(0U, result.paths.size());
}
-// Both trust store and issuer source are async. Should successfully build a
-// path.
-TEST_F(PathBuilderKeyRolloverTest, TestAsyncAnchorsAndAsyncIssuers) {
- TrustStoreInMemoryAsync trust_store;
- trust_store.AddAsyncTrustAnchor(
- TrustAnchor::CreateFromCertificateNoConstraints(newroot_));
-
- AsyncCertIssuerSourceStatic async_certs;
- async_certs.AddCert(newintermediate_);
-
- CertPathBuilder::Result result;
- CertPathBuilder path_builder(target_, &trust_store, &signature_policy_, time_,
- &result);
- path_builder.AddCertIssuerSource(&async_certs);
-
- EXPECT_EQ(CompletionStatus::ASYNC, RunPathBuilder(&path_builder));
-
- EXPECT_TRUE(result.HasValidPath());
-
- ASSERT_EQ(1U, result.paths.size());
- const auto& path = result.paths[0]->path;
- EXPECT_TRUE(result.paths[0]->valid);
- ASSERT_EQ(2U, path.certs.size());
- EXPECT_EQ(target_, path.certs[0]);
- EXPECT_EQ(newintermediate_, path.certs[1]);
- EXPECT_EQ(newroot_, path.trust_anchor->cert());
-}
-
// Tests that multiple trust root matches on a single path will be considered.
// Both roots have the same subject but different keys. Only one of them will
// verify.
TEST_F(PathBuilderKeyRolloverTest, TestMultipleRootMatchesOnlyOneWorks) {
- TrustStoreInMemoryAsync trust_store;
- // Since FindTrustAnchorsByNormalizedName returns newroot synchronously, it
- // should be tried first.
- trust_store.AddSyncTrustAnchor(
+ TrustStoreCollection trust_store_collection;
+ TrustStoreInMemory trust_store1;
+ TrustStoreInMemory trust_store2;
+ trust_store_collection.AddTrustStore(&trust_store1);
+ trust_store_collection.AddTrustStore(&trust_store2);
+ // Add two trust anchors (newroot_ and oldroot_). Path building will attempt
+ // them in this same order, as trust_store1 was added to
+ // trust_store_collection first.
+ trust_store1.AddTrustAnchor(
TrustAnchor::CreateFromCertificateNoConstraints(newroot_));
- // oldroot is returned asynchronously, so it should only be tried after the
- // path built with newroot fails.
- trust_store.AddAsyncTrustAnchor(oldroot_);
+ trust_store2.AddTrustAnchor(oldroot_);
// Only oldintermediate is supplied, so the path with newroot should fail,
// oldroot should succeed.
@@ -772,11 +611,11 @@ TEST_F(PathBuilderKeyRolloverTest, TestMultipleRootMatchesOnlyOneWorks) {
sync_certs.AddCert(oldintermediate_);
CertPathBuilder::Result result;
- CertPathBuilder path_builder(target_, &trust_store, &signature_policy_, time_,
- &result);
+ CertPathBuilder path_builder(target_, &trust_store_collection,
+ &signature_policy_, time_, &result);
path_builder.AddCertIssuerSource(&sync_certs);
- EXPECT_EQ(CompletionStatus::ASYNC, RunPathBuilder(&path_builder));
+ path_builder.Run();
EXPECT_TRUE(result.HasValidPath());
ASSERT_EQ(2U, result.paths.size());
@@ -827,7 +666,7 @@ TEST_F(PathBuilderKeyRolloverTest, TestRolloverLongChain) {
path_builder.AddCertIssuerSource(&sync_certs);
path_builder.AddCertIssuerSource(&async_certs);
- EXPECT_EQ(CompletionStatus::ASYNC, RunPathBuilder(&path_builder));
+ path_builder.Run();
EXPECT_TRUE(result.HasValidPath());
ASSERT_EQ(3U, result.paths.size());
@@ -882,7 +721,7 @@ TEST_F(PathBuilderKeyRolloverTest, TestEndEntityIsTrustRoot) {
CertPathBuilder path_builder(newintermediate_, &trust_store,
&signature_policy_, time_, &result);
- EXPECT_EQ(CompletionStatus::SYNC, RunPathBuilder(&path_builder));
+ path_builder.Run();
EXPECT_FALSE(result.HasValidPath());
}
@@ -907,7 +746,7 @@ TEST_F(PathBuilderKeyRolloverTest,
time_, &result);
path_builder.AddCertIssuerSource(&sync_certs);
- EXPECT_EQ(CompletionStatus::SYNC, RunPathBuilder(&path_builder));
+ path_builder.Run();
// This could actually be OK, but CertPathBuilder does not build the
// newroot <- newrootrollover <- oldroot path.
@@ -927,7 +766,7 @@ TEST_F(PathBuilderKeyRolloverTest,
CertPathBuilder path_builder(newroot_, &trust_store, &signature_policy_,
time_, &result);
- EXPECT_EQ(CompletionStatus::SYNC, RunPathBuilder(&path_builder));
+ path_builder.Run();
ASSERT_TRUE(result.HasValidPath());
@@ -975,7 +814,7 @@ TEST_F(PathBuilderKeyRolloverTest, TestDuplicateIntermediates) {
path_builder.AddCertIssuerSource(&sync_certs2);
path_builder.AddCertIssuerSource(&async_certs);
- EXPECT_EQ(CompletionStatus::ASYNC, RunPathBuilder(&path_builder));
+ path_builder.Run();
EXPECT_TRUE(result.HasValidPath());
ASSERT_EQ(2U, result.paths.size());
@@ -1024,7 +863,7 @@ TEST_F(PathBuilderKeyRolloverTest, TestDuplicateIntermediateAndRoot) {
&result);
path_builder.AddCertIssuerSource(&sync_certs);
- EXPECT_EQ(CompletionStatus::SYNC, RunPathBuilder(&path_builder));
+ path_builder.Run();
EXPECT_FALSE(result.HasValidPath());
ASSERT_EQ(2U, result.paths.size());
@@ -1044,17 +883,15 @@ TEST_F(PathBuilderKeyRolloverTest, TestDuplicateIntermediateAndRoot) {
class MockCertIssuerSourceRequest : public CertIssuerSource::Request {
public:
- MOCK_METHOD1(GetNext, CompletionStatus(scoped_refptr<ParsedCertificate>*));
+ MOCK_METHOD1(GetNext, void(ParsedCertificateList*));
};
class MockCertIssuerSource : public CertIssuerSource {
public:
MOCK_METHOD2(SyncGetIssuersOf,
void(const ParsedCertificate*, ParsedCertificateList*));
- MOCK_METHOD3(AsyncGetIssuersOf,
- void(const ParsedCertificate*,
- const IssuerCallback&,
- std::unique_ptr<Request>*));
+ MOCK_METHOD2(AsyncGetIssuersOf,
+ void(const ParsedCertificate*, std::unique_ptr<Request>*));
};
// Helper class to pass the Request to the PathBuilder when it calls
@@ -1065,7 +902,6 @@ class CertIssuerSourceRequestMover {
CertIssuerSourceRequestMover(std::unique_ptr<CertIssuerSource::Request> req)
: request_(std::move(req)) {}
void MoveIt(const ParsedCertificate* cert,
- const CertIssuerSource::IssuerCallback& issuers_callback,
std::unique_ptr<CertIssuerSource::Request>* out_req) {
*out_req = std::move(request_);
}
@@ -1074,10 +910,23 @@ class CertIssuerSourceRequestMover {
std::unique_ptr<CertIssuerSource::Request> request_;
};
+// Functor that when called with a ParsedCertificateList* will append the
+// specified certificate.
+class AppendCertToList {
+ public:
+ explicit AppendCertToList(const scoped_refptr<ParsedCertificate>& cert)
+ : cert_(cert) {}
+
+ void operator()(ParsedCertificateList* out) { out->push_back(cert_); }
+
+ private:
+ scoped_refptr<ParsedCertificate> cert_;
+};
+
// Test that a single CertIssuerSource returning multiple async batches of
// issuers is handled correctly. Due to the StrictMocks, it also tests that path
// builder does not request issuers of certs that it shouldn't.
-TEST_F(PathBuilderKeyRolloverTest, TestMultipleAsyncCallbacksFromSingleSource) {
+TEST_F(PathBuilderKeyRolloverTest, TestMultipleAsyncIssuersFromSingleSource) {
StrictMock<MockCertIssuerSource> cert_issuer_source;
// Only newroot is a trusted root.
@@ -1089,7 +938,6 @@ TEST_F(PathBuilderKeyRolloverTest, TestMultipleAsyncCallbacksFromSingleSource) {
&result);
path_builder.AddCertIssuerSource(&cert_issuer_source);
- CertIssuerSource::IssuerCallback target_issuers_callback;
// Create the mock CertIssuerSource::Request...
std::unique_ptr<StrictMock<MockCertIssuerSourceRequest>>
target_issuers_req_owner(new StrictMock<MockCertIssuerSourceRequest>());
@@ -1102,26 +950,15 @@ TEST_F(PathBuilderKeyRolloverTest, TestMultipleAsyncCallbacksFromSingleSource) {
{
::testing::InSequence s;
EXPECT_CALL(cert_issuer_source, SyncGetIssuersOf(target_.get(), _));
- EXPECT_CALL(cert_issuer_source, AsyncGetIssuersOf(target_.get(), _, _))
- .WillOnce(
- DoAll(SaveArg<1>(&target_issuers_callback),
- Invoke(&req_mover, &CertIssuerSourceRequestMover::MoveIt)));
+ EXPECT_CALL(cert_issuer_source, AsyncGetIssuersOf(target_.get(), _))
+ .WillOnce(Invoke(&req_mover, &CertIssuerSourceRequestMover::MoveIt));
}
- TestClosure callback;
- CompletionStatus rv = path_builder.Run(callback.closure());
- ASSERT_EQ(CompletionStatus::ASYNC, rv);
-
- ASSERT_FALSE(target_issuers_callback.is_null());
-
- ::testing::Mock::VerifyAndClearExpectations(&cert_issuer_source);
-
- // First async batch: return oldintermediate_.
EXPECT_CALL(*target_issuers_req, GetNext(_))
- .WillOnce(DoAll(SetArgPointee<0>(oldintermediate_),
- Return(CompletionStatus::SYNC)))
- .WillOnce(
- DoAll(SetArgPointee<0>(nullptr), Return(CompletionStatus::ASYNC)));
+ // First async batch: return oldintermediate_.
+ .WillOnce(Invoke(AppendCertToList(oldintermediate_)))
+ // Second async batch: return newintermediate_.
+ .WillOnce(Invoke(AppendCertToList(newintermediate_)));
{
::testing::InSequence s;
// oldintermediate_ does not create a valid path, so both sync and async
@@ -1129,30 +966,21 @@ TEST_F(PathBuilderKeyRolloverTest, TestMultipleAsyncCallbacksFromSingleSource) {
EXPECT_CALL(cert_issuer_source,
SyncGetIssuersOf(oldintermediate_.get(), _));
EXPECT_CALL(cert_issuer_source,
- AsyncGetIssuersOf(oldintermediate_.get(), _, _));
+ AsyncGetIssuersOf(oldintermediate_.get(), _));
}
- target_issuers_callback.Run(target_issuers_req);
- ::testing::Mock::VerifyAndClearExpectations(target_issuers_req);
- ::testing::Mock::VerifyAndClearExpectations(&cert_issuer_source);
- // Second async batch: return newintermediate_.
- EXPECT_CALL(*target_issuers_req, GetNext(_))
- .WillOnce(DoAll(SetArgPointee<0>(newintermediate_),
- Return(CompletionStatus::SYNC)))
- .WillOnce(
- DoAll(SetArgPointee<0>(nullptr), Return(CompletionStatus::ASYNC)));
// newroot_ is in the trust store, so this path will be completed
// synchronously. AsyncGetIssuersOf will not be called on newintermediate_.
EXPECT_CALL(cert_issuer_source, SyncGetIssuersOf(newintermediate_.get(), _));
- target_issuers_callback.Run(target_issuers_req);
+
+ // Ensure pathbuilder finished and filled result.
+ path_builder.Run();
+
// Note that VerifyAndClearExpectations(target_issuers_req) is not called
// here. PathBuilder could have destroyed it already, so just let the
// expectations get checked by the destructor.
::testing::Mock::VerifyAndClearExpectations(&cert_issuer_source);
- // Ensure pathbuilder finished and filled result.
- callback.WaitForResult();
-
EXPECT_TRUE(result.HasValidPath());
ASSERT_EQ(2U, result.paths.size());
@@ -1189,7 +1017,6 @@ TEST_F(PathBuilderKeyRolloverTest, TestDuplicateAsyncIntermediates) {
&result);
path_builder.AddCertIssuerSource(&cert_issuer_source);
- CertIssuerSource::IssuerCallback target_issuers_callback;
// Create the mock CertIssuerSource::Request...
std::unique_ptr<StrictMock<MockCertIssuerSourceRequest>>
target_issuers_req_owner(new StrictMock<MockCertIssuerSourceRequest>());
@@ -1202,26 +1029,22 @@ TEST_F(PathBuilderKeyRolloverTest, TestDuplicateAsyncIntermediates) {
{
::testing::InSequence s;
EXPECT_CALL(cert_issuer_source, SyncGetIssuersOf(target_.get(), _));
- EXPECT_CALL(cert_issuer_source, AsyncGetIssuersOf(target_.get(), _, _))
- .WillOnce(
- DoAll(SaveArg<1>(&target_issuers_callback),
- Invoke(&req_mover, &CertIssuerSourceRequestMover::MoveIt)));
+ EXPECT_CALL(cert_issuer_source, AsyncGetIssuersOf(target_.get(), _))
+ .WillOnce(Invoke(&req_mover, &CertIssuerSourceRequestMover::MoveIt));
}
- TestClosure callback;
- CompletionStatus rv = path_builder.Run(callback.closure());
- ASSERT_EQ(CompletionStatus::ASYNC, rv);
-
- ASSERT_FALSE(target_issuers_callback.is_null());
-
- ::testing::Mock::VerifyAndClearExpectations(&cert_issuer_source);
+ scoped_refptr<ParsedCertificate> oldintermediate_dupe(
+ ParsedCertificate::Create(oldintermediate_->der_cert().AsStringPiece(),
+ {}, nullptr));
- // First async batch: return oldintermediate_.
EXPECT_CALL(*target_issuers_req, GetNext(_))
- .WillOnce(DoAll(SetArgPointee<0>(oldintermediate_),
- Return(CompletionStatus::SYNC)))
- .WillOnce(
- DoAll(SetArgPointee<0>(nullptr), Return(CompletionStatus::ASYNC)));
+ // First async batch: return oldintermediate_.
+ .WillOnce(Invoke(AppendCertToList(oldintermediate_)))
+ // Second async batch: return a different copy of oldintermediate_ again.
+ .WillOnce(Invoke(AppendCertToList(oldintermediate_dupe)))
+ // Third async batch: return newintermediate_.
+ .WillOnce(Invoke(AppendCertToList(newintermediate_)));
+
{
::testing::InSequence s;
// oldintermediate_ does not create a valid path, so both sync and async
@@ -1229,44 +1052,17 @@ TEST_F(PathBuilderKeyRolloverTest, TestDuplicateAsyncIntermediates) {
EXPECT_CALL(cert_issuer_source,
SyncGetIssuersOf(oldintermediate_.get(), _));
EXPECT_CALL(cert_issuer_source,
- AsyncGetIssuersOf(oldintermediate_.get(), _, _));
+ AsyncGetIssuersOf(oldintermediate_.get(), _));
}
- target_issuers_callback.Run(target_issuers_req);
- ::testing::Mock::VerifyAndClearExpectations(target_issuers_req);
- ::testing::Mock::VerifyAndClearExpectations(&cert_issuer_source);
-
- // Second async batch: return a different copy of oldintermediate_ again.
- scoped_refptr<ParsedCertificate> oldintermediate_dupe(
- ParsedCertificate::Create(oldintermediate_->der_cert().AsStringPiece(),
- {}, nullptr));
- EXPECT_CALL(*target_issuers_req, GetNext(_))
- .WillOnce(DoAll(SetArgPointee<0>(oldintermediate_dupe),
- Return(CompletionStatus::SYNC)))
- .WillOnce(
- DoAll(SetArgPointee<0>(nullptr), Return(CompletionStatus::ASYNC)));
- target_issuers_callback.Run(target_issuers_req);
- // oldintermediate was already processed above, it should not generate any
- // more requests.
- ::testing::Mock::VerifyAndClearExpectations(target_issuers_req);
- ::testing::Mock::VerifyAndClearExpectations(&cert_issuer_source);
- // Third async batch: return newintermediate_.
- EXPECT_CALL(*target_issuers_req, GetNext(_))
- .WillOnce(DoAll(SetArgPointee<0>(newintermediate_),
- Return(CompletionStatus::SYNC)))
- .WillOnce(
- DoAll(SetArgPointee<0>(nullptr), Return(CompletionStatus::ASYNC)));
// newroot_ is in the trust store, so this path will be completed
// synchronously. AsyncGetIssuersOf will not be called on newintermediate_.
EXPECT_CALL(cert_issuer_source, SyncGetIssuersOf(newintermediate_.get(), _));
- target_issuers_callback.Run(target_issuers_req);
- // Note that VerifyAndClearExpectations(target_issuers_req) is not called
- // here. PathBuilder could have destroyed it already, so just let the
- // expectations get checked by the destructor.
- ::testing::Mock::VerifyAndClearExpectations(&cert_issuer_source);
// Ensure pathbuilder finished and filled result.
- callback.WaitForResult();
+ path_builder.Run();
+
+ ::testing::Mock::VerifyAndClearExpectations(&cert_issuer_source);
EXPECT_TRUE(result.HasValidPath());
ASSERT_EQ(2U, result.paths.size());
diff --git a/chromium/net/cert/internal/path_builder_verify_certificate_chain_unittest.cc b/chromium/net/cert/internal/path_builder_verify_certificate_chain_unittest.cc
index 3bc20ef0819..003157b8dfa 100644
--- a/chromium/net/cert/internal/path_builder_verify_certificate_chain_unittest.cc
+++ b/chromium/net/cert/internal/path_builder_verify_certificate_chain_unittest.cc
@@ -37,9 +37,7 @@ class PathBuilderDelegate {
time, &result);
path_builder.AddCertIssuerSource(&intermediate_cert_issuer_source);
- CompletionStatus rv = path_builder.Run(base::Closure());
- EXPECT_EQ(CompletionStatus::SYNC, rv);
-
+ path_builder.Run();
EXPECT_EQ(expected_result, result.HasValidPath());
}
};
diff --git a/chromium/net/cert/internal/trust_store.cc b/chromium/net/cert/internal/trust_store.cc
index 07eff04a326..7540cfdab8b 100644
--- a/chromium/net/cert/internal/trust_store.cc
+++ b/chromium/net/cert/internal/trust_store.cc
@@ -36,9 +36,6 @@ TrustAnchor::TrustAnchor(scoped_refptr<ParsedCertificate> cert,
TrustAnchor::~TrustAnchor() = default;
-TrustStore::Request::Request() = default;
-TrustStore::Request::~Request() = default;
-
TrustStore::TrustStore() = default;
TrustStore::~TrustStore() = default;
diff --git a/chromium/net/cert/internal/trust_store.h b/chromium/net/cert/internal/trust_store.h
index 8422fd5c96a..6985301f35c 100644
--- a/chromium/net/cert/internal/trust_store.h
+++ b/chromium/net/cert/internal/trust_store.h
@@ -7,7 +7,6 @@
#include <vector>
-#include "base/callback.h"
#include "base/memory/ref_counted.h"
#include "net/base/net_export.h"
#include "net/cert/internal/parsed_certificate.h"
@@ -115,35 +114,14 @@ using TrustAnchors = std::vector<scoped_refptr<TrustAnchor>>;
// Interface for finding trust anchors.
class NET_EXPORT TrustStore {
public:
- class NET_EXPORT Request {
- public:
- Request();
- // Destruction of the Request cancels it.
- virtual ~Request();
- };
-
TrustStore();
virtual ~TrustStore();
- using TrustAnchorsCallback = base::Callback<void(TrustAnchors)>;
-
- // Returns the trust anchors that match |cert|'s issuer name in
- // |*synchronous_matches| and/or through |callback|. |cert| and
- // |synchronous_matches| must not be null.
- //
- // If results are available synchronously, they will be appended to
- // |*synchronous_matches|. |*synchronous_matches| will not be modified
- // asynchronously.
- //
- // If |callback| is not null and results may be available asynchronously,
- // |*out_req| will be filled with a Request, and |callback| will be called
- // when results are available. The Request may be destroyed to cancel
- // the callback if it has not occurred yet.
+ // Appends the trust anchors that match |cert|'s issuer name to |*matches|.
+ // |cert| and |matches| must not be null.
virtual void FindTrustAnchorsForCert(
const scoped_refptr<ParsedCertificate>& cert,
- const TrustAnchorsCallback& callback,
- TrustAnchors* synchronous_matches,
- std::unique_ptr<Request>* out_req) const = 0;
+ TrustAnchors* matches) const = 0;
private:
DISALLOW_COPY_AND_ASSIGN(TrustStore);
diff --git a/chromium/net/cert/internal/trust_store_collection.cc b/chromium/net/cert/internal/trust_store_collection.cc
index dc35306eee2..7e004ae1b72 100644
--- a/chromium/net/cert/internal/trust_store_collection.cc
+++ b/chromium/net/cert/internal/trust_store_collection.cc
@@ -9,29 +9,16 @@ namespace net {
TrustStoreCollection::TrustStoreCollection() = default;
TrustStoreCollection::~TrustStoreCollection() = default;
-void TrustStoreCollection::SetPrimaryTrustStore(TrustStore* store) {
- DCHECK(!primary_store_);
+void TrustStoreCollection::AddTrustStore(TrustStore* store) {
DCHECK(store);
- primary_store_ = store;
-}
-
-void TrustStoreCollection::AddTrustStoreSynchronousOnly(TrustStore* store) {
- DCHECK(store);
- sync_only_stores_.push_back(store);
+ stores_.push_back(store);
}
void TrustStoreCollection::FindTrustAnchorsForCert(
const scoped_refptr<ParsedCertificate>& cert,
- const TrustAnchorsCallback& callback,
- TrustAnchors* synchronous_matches,
- std::unique_ptr<Request>* out_req) const {
- if (primary_store_)
- primary_store_->FindTrustAnchorsForCert(cert, callback, synchronous_matches,
- out_req);
-
- for (auto* store : sync_only_stores_) {
- store->FindTrustAnchorsForCert(cert, TrustAnchorsCallback(),
- synchronous_matches, nullptr);
+ TrustAnchors* matches) const {
+ for (auto* store : stores_) {
+ store->FindTrustAnchorsForCert(cert, matches);
}
}
diff --git a/chromium/net/cert/internal/trust_store_collection.h b/chromium/net/cert/internal/trust_store_collection.h
index ec9d49fd8e2..74ece5f97ba 100644
--- a/chromium/net/cert/internal/trust_store_collection.h
+++ b/chromium/net/cert/internal/trust_store_collection.h
@@ -9,50 +9,28 @@
#include "net/base/net_export.h"
#include "net/cert/internal/trust_store.h"
-namespace base {
-class TaskRunner;
-}
-
namespace net {
// TrustStoreCollection is an implementation of TrustStore which combines the
// results from multiple TrustStores.
//
-// The synchronous matches will be in order from the primary store, and then
-// from the secondary stores in the order they were added to the
-// TrustStoreCollection.
-//
-// Currently only one "primary" store can be added that supports async queries,
-// any number of additional, synchronous-only stores can be used. (The
-// assumption is that the async one would be useful for OS integration, while
-// the sync only stores can be used for supplying additional anchors. If
-// multiple async stores are desired, it might be worth changing the
-// FindTrustAnchorsForCert interface so that it can return async results in
-// multiple batches.)
+// The order of the matches will correspond to a concatenation of matches in
+// the order the stores were added.
class NET_EXPORT TrustStoreCollection : public TrustStore {
public:
TrustStoreCollection();
~TrustStoreCollection() override;
- // Includes results from |store| in the combined output. Both sync and async
- // queries to |store| will be allowed. |store| must outlive the
- // TrustStoreCollection.
- void SetPrimaryTrustStore(TrustStore* store);
-
- // Includes results from |store| in the combined output. |store| will only be
- // queried synchronously. |store| must outlive the TrustStoreCollection.
- void AddTrustStoreSynchronousOnly(TrustStore* store);
+ // Includes results from |store| in the combined output. |store| must
+ // outlive the TrustStoreCollection.
+ void AddTrustStore(TrustStore* store);
// TrustStore implementation:
- void FindTrustAnchorsForCert(
- const scoped_refptr<ParsedCertificate>& cert,
- const TrustAnchorsCallback& callback,
- TrustAnchors* synchronous_matches,
- std::unique_ptr<Request>* out_req) const override;
+ void FindTrustAnchorsForCert(const scoped_refptr<ParsedCertificate>& cert,
+ TrustAnchors* matches) const override;
private:
- TrustStore* primary_store_ = nullptr;
- std::vector<TrustStore*> sync_only_stores_;
+ std::vector<TrustStore*> stores_;
DISALLOW_COPY_AND_ASSIGN(TrustStoreCollection);
};
diff --git a/chromium/net/cert/internal/trust_store_collection_unittest.cc b/chromium/net/cert/internal/trust_store_collection_unittest.cc
index a7561d3f782..c9cd85ccab8 100644
--- a/chromium/net/cert/internal/trust_store_collection_unittest.cc
+++ b/chromium/net/cert/internal/trust_store_collection_unittest.cc
@@ -4,33 +4,14 @@
#include "net/cert/internal/trust_store_collection.h"
-#include "base/bind.h"
#include "net/cert/internal/test_helpers.h"
-#include "net/cert/internal/trust_store_test_helpers.h"
-#include "testing/gmock/include/gmock/gmock.h"
+#include "net/cert/internal/trust_store_in_memory.h"
#include "testing/gtest/include/gtest/gtest.h"
namespace net {
namespace {
-using ::testing::_;
-using ::testing::Property;
-using ::testing::StrictMock;
-
-void NotCalled(TrustAnchors anchors) {
- ADD_FAILURE() << "NotCalled was called";
-}
-
-class MockTrustStore : public TrustStore {
- public:
- MOCK_CONST_METHOD4(FindTrustAnchorsForCert,
- void(const scoped_refptr<ParsedCertificate>&,
- const TrustAnchorsCallback&,
- TrustAnchors*,
- std::unique_ptr<Request>*));
-};
-
class TrustStoreCollectionTest : public testing::Test {
public:
void SetUp() override {
@@ -75,155 +56,46 @@ class TrustStoreCollectionTest : public testing::Test {
scoped_refptr<ParsedCertificate> newintermediate_;
};
-// Collection contains no stores, should return no results and complete
-// synchronously.
+// Collection contains no stores, should return no results.
TEST_F(TrustStoreCollectionTest, NoStores) {
- std::unique_ptr<TrustStore::Request> req;
- TrustAnchors sync_matches;
+ TrustAnchors matches;
TrustStoreCollection collection;
- collection.FindTrustAnchorsForCert(target_, base::Bind(&NotCalled),
- &sync_matches, &req);
+ collection.FindTrustAnchorsForCert(target_, &matches);
- EXPECT_FALSE(req);
- EXPECT_TRUE(sync_matches.empty());
+ EXPECT_TRUE(matches.empty());
}
-// Collection contains only one synchronous store, should complete
-// synchronously.
-TEST_F(TrustStoreCollectionTest, NoPrimaryStoreOneSyncStore) {
- std::unique_ptr<TrustStore::Request> req;
- TrustAnchors sync_matches;
+// Collection contains only one store.
+TEST_F(TrustStoreCollectionTest, OneStore) {
+ TrustAnchors matches;
TrustStoreCollection collection;
TrustStoreInMemory in_memory;
in_memory.AddTrustAnchor(newroot_);
- collection.AddTrustStoreSynchronousOnly(&in_memory);
- collection.FindTrustAnchorsForCert(newintermediate_, base::Bind(&NotCalled),
- &sync_matches, &req);
-
- EXPECT_FALSE(req);
- ASSERT_EQ(1U, sync_matches.size());
- EXPECT_EQ(newroot_, sync_matches[0]);
-}
-
-// Collection contains two synchronous stores, should complete synchronously.
-TEST_F(TrustStoreCollectionTest, NoPrimaryStoreTwoSyncStores) {
- std::unique_ptr<TrustStore::Request> req;
- TrustAnchors sync_matches;
-
- TrustStoreCollection collection;
- TrustStoreInMemory in_memory1;
- TrustStoreInMemory in_memory2;
- in_memory1.AddTrustAnchor(newroot_);
- in_memory2.AddTrustAnchor(oldroot_);
- collection.AddTrustStoreSynchronousOnly(&in_memory1);
- collection.AddTrustStoreSynchronousOnly(&in_memory2);
- collection.FindTrustAnchorsForCert(newintermediate_, base::Bind(&NotCalled),
- &sync_matches, &req);
-
- EXPECT_FALSE(req);
- ASSERT_EQ(2U, sync_matches.size());
- EXPECT_EQ(newroot_, sync_matches[0]);
- EXPECT_EQ(oldroot_, sync_matches[1]);
-}
-
-// The secondary stores in the collection should not be passed a callback to
-// their FindTrustAnchorsForCert call.
-TEST_F(TrustStoreCollectionTest, SyncStoresAreQueriedSynchronously) {
- std::unique_ptr<TrustStore::Request> req;
- TrustAnchors sync_matches;
-
- TrustStoreCollection collection;
- StrictMock<MockTrustStore> store;
- collection.AddTrustStoreSynchronousOnly(&store);
+ collection.AddTrustStore(&in_memory);
+ collection.FindTrustAnchorsForCert(newintermediate_, &matches);
- EXPECT_CALL(
- store,
- FindTrustAnchorsForCert(
- _, Property(&TrustStore::TrustAnchorsCallback::is_null, true), _, _));
-
- collection.FindTrustAnchorsForCert(newintermediate_, base::Bind(&NotCalled),
- &sync_matches, &req);
-
- EXPECT_FALSE(req);
- EXPECT_TRUE(sync_matches.empty());
+ ASSERT_EQ(1U, matches.size());
+ EXPECT_EQ(newroot_, matches[0]);
}
-// If the primary store completes synchronously, TrustStoreCollection should
-// complete synchronously also.
-TEST_F(TrustStoreCollectionTest, AllStoresAreSynchronous) {
- std::unique_ptr<TrustStore::Request> req;
- TrustAnchors sync_matches;
+// Collection contains two stores.
+TEST_F(TrustStoreCollectionTest, TwoStores) {
+ TrustAnchors matches;
TrustStoreCollection collection;
TrustStoreInMemory in_memory1;
TrustStoreInMemory in_memory2;
in_memory1.AddTrustAnchor(newroot_);
in_memory2.AddTrustAnchor(oldroot_);
- collection.SetPrimaryTrustStore(&in_memory1);
- collection.AddTrustStoreSynchronousOnly(&in_memory2);
- collection.FindTrustAnchorsForCert(newintermediate_, base::Bind(&NotCalled),
- &sync_matches, &req);
-
- EXPECT_FALSE(req);
- ASSERT_EQ(2U, sync_matches.size());
- EXPECT_EQ(newroot_, sync_matches[0]);
- EXPECT_EQ(oldroot_, sync_matches[1]);
-}
-
-// Primary store returns results asynchronously. No secondary stores registered.
-TEST_F(TrustStoreCollectionTest, AsyncPrimaryStore) {
- std::unique_ptr<TrustStore::Request> req;
- TrustAnchors sync_matches;
-
- TrustStoreInMemoryAsync in_memory_async;
- in_memory_async.AddAsyncTrustAnchor(newroot_);
-
- TrustStoreCollection collection;
- collection.SetPrimaryTrustStore(&in_memory_async);
-
- TrustAnchorResultRecorder anchor_results;
- collection.FindTrustAnchorsForCert(
- newintermediate_, anchor_results.Callback(), &sync_matches, &req);
-
- ASSERT_TRUE(req);
- EXPECT_TRUE(sync_matches.empty());
-
- anchor_results.Run();
- ASSERT_EQ(1U, anchor_results.matches().size());
- EXPECT_EQ(newroot_, anchor_results.matches()[0]);
-}
-
-// Primary store returns results both synchronously and asynchronously, and
-// a secondary store returns results synchronously as well.
-TEST_F(TrustStoreCollectionTest, SyncAndAsyncPrimaryStoreAndSyncStore) {
- std::unique_ptr<TrustStore::Request> req;
- TrustAnchors sync_matches;
-
- TrustStoreInMemoryAsync in_memory_async;
- in_memory_async.AddAsyncTrustAnchor(newroot_);
- in_memory_async.AddSyncTrustAnchor(newrootrollover_);
-
- TrustStoreInMemory in_memory;
- in_memory.AddTrustAnchor(oldroot_);
-
- TrustStoreCollection collection;
- collection.SetPrimaryTrustStore(&in_memory_async);
- collection.AddTrustStoreSynchronousOnly(&in_memory);
-
- TrustAnchorResultRecorder anchor_results;
- collection.FindTrustAnchorsForCert(
- newintermediate_, anchor_results.Callback(), &sync_matches, &req);
-
- ASSERT_TRUE(req);
- ASSERT_EQ(2U, sync_matches.size());
- EXPECT_EQ(newrootrollover_, sync_matches[0]);
- EXPECT_EQ(oldroot_, sync_matches[1]);
+ collection.AddTrustStore(&in_memory1);
+ collection.AddTrustStore(&in_memory2);
+ collection.FindTrustAnchorsForCert(newintermediate_, &matches);
- anchor_results.Run();
- ASSERT_EQ(1U, anchor_results.matches().size());
- EXPECT_EQ(newroot_, anchor_results.matches()[0]);
+ ASSERT_EQ(2U, matches.size());
+ EXPECT_EQ(newroot_, matches[0]);
+ EXPECT_EQ(oldroot_, matches[1]);
}
} // namespace
diff --git a/chromium/net/cert/internal/trust_store_in_memory.cc b/chromium/net/cert/internal/trust_store_in_memory.cc
index 4cdab9672d2..3f94b6f0c49 100644
--- a/chromium/net/cert/internal/trust_store_in_memory.cc
+++ b/chromium/net/cert/internal/trust_store_in_memory.cc
@@ -21,12 +21,10 @@ void TrustStoreInMemory::AddTrustAnchor(scoped_refptr<TrustAnchor> anchor) {
void TrustStoreInMemory::FindTrustAnchorsForCert(
const scoped_refptr<ParsedCertificate>& cert,
- const TrustAnchorsCallback& callback,
- TrustAnchors* synchronous_matches,
- std::unique_ptr<Request>* out_req) const {
+ TrustAnchors* matches) const {
auto range = anchors_.equal_range(cert->normalized_issuer().AsStringPiece());
for (auto it = range.first; it != range.second; ++it)
- synchronous_matches->push_back(it->second);
+ matches->push_back(it->second);
}
} // namespace net
diff --git a/chromium/net/cert/internal/trust_store_in_memory.h b/chromium/net/cert/internal/trust_store_in_memory.h
index fea4c87d314..45b5123caf1 100644
--- a/chromium/net/cert/internal/trust_store_in_memory.h
+++ b/chromium/net/cert/internal/trust_store_in_memory.h
@@ -14,10 +14,6 @@
namespace net {
-namespace der {
-class Input;
-}
-
// A very simple implementation of a TrustStore, which contains a set of
// trust anchors.
class NET_EXPORT TrustStoreInMemory : public TrustStore {
@@ -31,11 +27,8 @@ class NET_EXPORT TrustStoreInMemory : public TrustStore {
void AddTrustAnchor(scoped_refptr<TrustAnchor> anchor);
// TrustStore implementation:
- void FindTrustAnchorsForCert(
- const scoped_refptr<ParsedCertificate>& cert,
- const TrustAnchorsCallback& callback,
- TrustAnchors* synchronous_matches,
- std::unique_ptr<Request>* out_req) const override;
+ void FindTrustAnchorsForCert(const scoped_refptr<ParsedCertificate>& cert,
+ TrustAnchors* matches) const override;
private:
// Multimap from normalized subject -> TrustAnchor.
diff --git a/chromium/net/cert/internal/trust_store_nss.cc b/chromium/net/cert/internal/trust_store_nss.cc
index 1a01875ecdf..dd214dca4cf 100644
--- a/chromium/net/cert/internal/trust_store_nss.cc
+++ b/chromium/net/cert/internal/trust_store_nss.cc
@@ -7,11 +7,7 @@
#include <cert.h>
#include <certdb.h>
-#include "base/bind.h"
-#include "base/callback_helpers.h"
#include "base/memory/ptr_util.h"
-#include "base/memory/weak_ptr.h"
-#include "base/task_runner.h"
#include "crypto/nss_util.h"
#include "net/cert/internal/cert_errors.h"
#include "net/cert/internal/parsed_certificate.h"
@@ -22,13 +18,14 @@
namespace net {
-namespace {
+TrustStoreNSS::TrustStoreNSS(SECTrustType trust_type)
+ : trust_type_(trust_type) {}
-// Get all certs in NSS which have a subject matching |der_name| and which are
-// marked as a trusted CA.
-void GetAnchors(const scoped_refptr<ParsedCertificate>& cert,
- SECTrustType trust_type,
- TrustAnchors* out_anchors) {
+TrustStoreNSS::~TrustStoreNSS() = default;
+
+void TrustStoreNSS::FindTrustAnchorsForCert(
+ const scoped_refptr<ParsedCertificate>& cert,
+ TrustAnchors* out_anchors) const {
crypto::EnsureNSSInit();
SECItem name;
@@ -54,7 +51,7 @@ void GetAnchors(const scoped_refptr<ParsedCertificate>& cert,
// TODO(mattm): handle explicit distrust (blacklisting)?
const int ca_trust = CERTDB_TRUSTED_CA;
- if ((SEC_GET_TRUST_FLAGS(&trust, trust_type) & ca_trust) != ca_trust)
+ if ((SEC_GET_TRUST_FLAGS(&trust, trust_type_) & ca_trust) != ca_trust)
continue;
CertErrors errors;
@@ -73,65 +70,4 @@ void GetAnchors(const scoped_refptr<ParsedCertificate>& cert,
CERT_DestroyCertList(found_certs);
}
-class GetAnchorsRequest : public TrustStore::Request {
- public:
- explicit GetAnchorsRequest(const TrustStore::TrustAnchorsCallback& callback);
- // Destruction of the Request cancels it. GetAnchors will still run, but the
- // callback will not be called since the WeakPtr will be invalidated.
- ~GetAnchorsRequest() override = default;
-
- void Start(const scoped_refptr<ParsedCertificate>& cert,
- SECTrustType trust_type,
- base::TaskRunner* task_runner);
-
- private:
- void HandleGetAnchors(std::unique_ptr<TrustAnchors> anchors);
-
- TrustStore::TrustAnchorsCallback callback_;
- base::WeakPtrFactory<GetAnchorsRequest> weak_ptr_factory_;
-};
-
-GetAnchorsRequest::GetAnchorsRequest(
- const TrustStore::TrustAnchorsCallback& callback)
- : callback_(callback), weak_ptr_factory_(this) {}
-
-void GetAnchorsRequest::Start(const scoped_refptr<ParsedCertificate>& cert,
- SECTrustType trust_type,
- base::TaskRunner* task_runner) {
- auto anchors = base::MakeUnique<TrustAnchors>();
-
- auto* anchors_ptr = anchors.get();
- task_runner->PostTaskAndReply(
- FROM_HERE, base::Bind(&GetAnchors, cert, trust_type, anchors_ptr),
- base::Bind(&GetAnchorsRequest::HandleGetAnchors,
- weak_ptr_factory_.GetWeakPtr(), base::Passed(&anchors)));
-}
-
-void GetAnchorsRequest::HandleGetAnchors(
- std::unique_ptr<TrustAnchors> anchors) {
- base::ResetAndReturn(&callback_).Run(std::move(*anchors));
- // |this| may be deleted here.
-}
-
-} // namespace
-
-TrustStoreNSS::TrustStoreNSS(SECTrustType trust_type,
- scoped_refptr<base::TaskRunner> nss_task_runner)
- : trust_type_(trust_type), nss_task_runner_(std::move(nss_task_runner)) {}
-
-TrustStoreNSS::~TrustStoreNSS() = default;
-
-void TrustStoreNSS::FindTrustAnchorsForCert(
- const scoped_refptr<ParsedCertificate>& cert,
- const TrustAnchorsCallback& callback,
- TrustAnchors* synchronous_matches,
- std::unique_ptr<Request>* out_req) const {
- if (callback.is_null())
- return;
-
- auto req = base::MakeUnique<GetAnchorsRequest>(callback);
- req->Start(cert, trust_type_, nss_task_runner_.get());
- *out_req = std::move(req);
-}
-
} // namespace net
diff --git a/chromium/net/cert/internal/trust_store_nss.h b/chromium/net/cert/internal/trust_store_nss.h
index d153dbc5fdf..760d49953c2 100644
--- a/chromium/net/cert/internal/trust_store_nss.h
+++ b/chromium/net/cert/internal/trust_store_nss.h
@@ -11,36 +11,23 @@
#include "net/base/net_export.h"
#include "net/cert/internal/trust_store.h"
-namespace base {
-class TaskRunner;
-}
-
namespace net {
// TrustStoreNSS is an implementation of TrustStore which uses NSS to find trust
// anchors for path building.
-// TODO(mattm): also implement CertIssuerSource to return intermediates in NSS
-// DB? Or have a separate CertIssuerSourceNSS for that? (implementing both in
-// the same class could be more efficient with some caching/etc. Need to be
-// careful about caching between different pathbuilder instances though.)
class NET_EXPORT TrustStoreNSS : public TrustStore {
public:
// Creates a TrustStoreNSS which will find anchors that are trusted for
- // |trust_type|. All NSS calls will be done on |nss_task_runner|.
- TrustStoreNSS(SECTrustType trust_type,
- scoped_refptr<base::TaskRunner> nss_task_runner);
+ // |trust_type|.
+ explicit TrustStoreNSS(SECTrustType trust_type);
~TrustStoreNSS() override;
// TrustStore implementation:
- void FindTrustAnchorsForCert(
- const scoped_refptr<ParsedCertificate>& cert,
- const TrustAnchorsCallback& callback,
- TrustAnchors* synchronous_matches,
- std::unique_ptr<Request>* out_req) const override;
+ void FindTrustAnchorsForCert(const scoped_refptr<ParsedCertificate>& cert,
+ TrustAnchors* matches) const override;
private:
SECTrustType trust_type_;
- scoped_refptr<base::TaskRunner> nss_task_runner_;
DISALLOW_COPY_AND_ASSIGN(TrustStoreNSS);
};
diff --git a/chromium/net/cert/internal/trust_store_nss_unittest.cc b/chromium/net/cert/internal/trust_store_nss_unittest.cc
index b74c5f97125..f9d1f272d74 100644
--- a/chromium/net/cert/internal/trust_store_nss_unittest.cc
+++ b/chromium/net/cert/internal/trust_store_nss_unittest.cc
@@ -7,14 +7,10 @@
#include <cert.h>
#include <certdb.h>
-#include "base/bind.h"
#include "base/memory/ptr_util.h"
-#include "base/run_loop.h"
#include "base/strings/string_number_conversions.h"
-#include "base/threading/thread_task_runner_handle.h"
#include "crypto/scoped_test_nss_db.h"
#include "net/cert/internal/test_helpers.h"
-#include "net/cert/internal/trust_store_test_helpers.h"
#include "net/cert/scoped_nss_types.h"
#include "net/cert/x509_certificate.h"
#include "testing/gtest/include/gtest/gtest.h"
@@ -23,10 +19,6 @@ namespace net {
namespace {
-void NotCalled(TrustAnchors anchors) {
- ADD_FAILURE() << "NotCalled was called";
-}
-
class TrustStoreNSSTest : public testing::Test {
public:
void SetUp() override {
@@ -61,8 +53,7 @@ class TrustStoreNSSTest : public testing::Test {
ASSERT_TRUE(newroot_);
ASSERT_TRUE(newrootrollover_);
- trust_store_nss_.reset(
- new TrustStoreNSS(trustSSL, base::ThreadTaskRunnerHandle::Get()));
+ trust_store_nss_.reset(new TrustStoreNSS(trustSSL));
}
std::string GetUniqueNickname() {
@@ -112,31 +103,27 @@ class TrustStoreNSSTest : public testing::Test {
}
protected:
- void ExpectTrustStoreContains(tracked_objects::Location loc,
- scoped_refptr<ParsedCertificate> cert,
- TrustAnchors expected_async_matches) {
- SCOPED_TRACE(loc.ToString());
-
- TrustAnchors sync_matches;
- TrustAnchorResultRecorder anchor_results;
- std::unique_ptr<TrustStore::Request> req;
- trust_store_nss_->FindTrustAnchorsForCert(cert, anchor_results.Callback(),
- &sync_matches, &req);
- ASSERT_TRUE(req);
- EXPECT_TRUE(sync_matches.empty());
-
- anchor_results.Run();
+ bool TrustStoreContains(scoped_refptr<ParsedCertificate> cert,
+ TrustAnchors expected_matches) {
+ TrustAnchors matches;
+ trust_store_nss_->FindTrustAnchorsForCert(cert, &matches);
+
std::vector<der::Input> der_result_matches;
- for (const auto& it : anchor_results.matches())
+ for (const auto& it : matches)
der_result_matches.push_back(it->cert()->der_cert());
std::sort(der_result_matches.begin(), der_result_matches.end());
std::vector<der::Input> der_expected_matches;
- for (const auto& it : expected_async_matches)
+ for (const auto& it : expected_matches)
der_expected_matches.push_back(it->cert()->der_cert());
std::sort(der_expected_matches.begin(), der_expected_matches.end());
+ if (der_expected_matches == der_result_matches)
+ return true;
+
+ // Print some extra information for debugging.
EXPECT_EQ(der_expected_matches, der_result_matches);
+ return false;
}
scoped_refptr<TrustAnchor> oldroot_;
@@ -154,19 +141,19 @@ class TrustStoreNSSTest : public testing::Test {
// Without adding any certs to the NSS DB, should get no anchor results for any
// of the test certs.
TEST_F(TrustStoreNSSTest, CertsNotPresent) {
- ExpectTrustStoreContains(FROM_HERE, target_, TrustAnchors());
- ExpectTrustStoreContains(FROM_HERE, newintermediate_, TrustAnchors());
- ExpectTrustStoreContains(FROM_HERE, newroot_->cert(), TrustAnchors());
+ EXPECT_TRUE(TrustStoreContains(target_, TrustAnchors()));
+ EXPECT_TRUE(TrustStoreContains(newintermediate_, TrustAnchors()));
+ EXPECT_TRUE(TrustStoreContains(newroot_->cert(), TrustAnchors()));
}
// If certs are present in NSS DB but aren't marked as trusted, should get no
// anchor results for any of the test certs.
TEST_F(TrustStoreNSSTest, CertsPresentButNotTrusted) {
AddCertsToNSS();
- ExpectTrustStoreContains(FROM_HERE, newintermediate_, TrustAnchors());
- ExpectTrustStoreContains(FROM_HERE, target_, TrustAnchors());
- ExpectTrustStoreContains(FROM_HERE, newintermediate_, TrustAnchors());
- ExpectTrustStoreContains(FROM_HERE, newroot_->cert(), TrustAnchors());
+ EXPECT_TRUE(TrustStoreContains(newintermediate_, TrustAnchors()));
+ EXPECT_TRUE(TrustStoreContains(target_, TrustAnchors()));
+ EXPECT_TRUE(TrustStoreContains(newintermediate_, TrustAnchors()));
+ EXPECT_TRUE(TrustStoreContains(newroot_->cert(), TrustAnchors()));
}
// A self-signed CA certificate is trusted. FindTrustAnchorsForCert should
@@ -175,12 +162,12 @@ TEST_F(TrustStoreNSSTest, CertsPresentButNotTrusted) {
TEST_F(TrustStoreNSSTest, TrustedCA) {
AddCertsToNSS();
TrustCert(newroot_.get());
- ExpectTrustStoreContains(FROM_HERE, target_, TrustAnchors());
- ExpectTrustStoreContains(FROM_HERE, newintermediate_, {newroot_});
- ExpectTrustStoreContains(FROM_HERE, oldintermediate_, {newroot_});
- ExpectTrustStoreContains(FROM_HERE, newrootrollover_, {newroot_});
- ExpectTrustStoreContains(FROM_HERE, oldroot_->cert(), {newroot_});
- ExpectTrustStoreContains(FROM_HERE, newroot_->cert(), {newroot_});
+ EXPECT_TRUE(TrustStoreContains(target_, TrustAnchors()));
+ EXPECT_TRUE(TrustStoreContains(newintermediate_, {newroot_}));
+ EXPECT_TRUE(TrustStoreContains(oldintermediate_, {newroot_}));
+ EXPECT_TRUE(TrustStoreContains(newrootrollover_, {newroot_}));
+ EXPECT_TRUE(TrustStoreContains(oldroot_->cert(), {newroot_}));
+ EXPECT_TRUE(TrustStoreContains(newroot_->cert(), {newroot_}));
}
// When an intermediate certificate is trusted, FindTrustAnchorsForCert should
@@ -189,14 +176,14 @@ TEST_F(TrustStoreNSSTest, TrustedCA) {
TEST_F(TrustStoreNSSTest, TrustedIntermediate) {
AddCertsToNSS();
TrustCert(newintermediate_.get());
- ExpectTrustStoreContains(
- FROM_HERE, target_,
- {TrustAnchor::CreateFromCertificateNoConstraints(newintermediate_)});
- ExpectTrustStoreContains(FROM_HERE, newintermediate_, TrustAnchors());
- ExpectTrustStoreContains(FROM_HERE, oldintermediate_, TrustAnchors());
- ExpectTrustStoreContains(FROM_HERE, newrootrollover_, TrustAnchors());
- ExpectTrustStoreContains(FROM_HERE, oldroot_->cert(), TrustAnchors());
- ExpectTrustStoreContains(FROM_HERE, newroot_->cert(), TrustAnchors());
+ EXPECT_TRUE(TrustStoreContains(
+ target_,
+ {TrustAnchor::CreateFromCertificateNoConstraints(newintermediate_)}));
+ EXPECT_TRUE(TrustStoreContains(newintermediate_, TrustAnchors()));
+ EXPECT_TRUE(TrustStoreContains(oldintermediate_, TrustAnchors()));
+ EXPECT_TRUE(TrustStoreContains(newrootrollover_, TrustAnchors()));
+ EXPECT_TRUE(TrustStoreContains(oldroot_->cert(), TrustAnchors()));
+ EXPECT_TRUE(TrustStoreContains(newroot_->cert(), TrustAnchors()));
}
// Multiple self-signed CA certificates with the same name are trusted.
@@ -206,41 +193,10 @@ TEST_F(TrustStoreNSSTest, MultipleTrustedCAWithSameSubject) {
AddCertsToNSS();
TrustCert(oldroot_.get());
TrustCert(newroot_.get());
- ExpectTrustStoreContains(FROM_HERE, target_, TrustAnchors());
- ExpectTrustStoreContains(FROM_HERE, newintermediate_, {newroot_, oldroot_});
- ExpectTrustStoreContains(FROM_HERE, oldintermediate_, {newroot_, oldroot_});
- ExpectTrustStoreContains(FROM_HERE, oldroot_->cert(), {newroot_, oldroot_});
-}
-
-// Cancel a FindTrustAnchorsForCert request before it has returned any results.
-// Callback should not be called.
-TEST_F(TrustStoreNSSTest, CancelRequest) {
- std::unique_ptr<TrustStore::Request> req;
- TrustAnchors sync_matches;
- trust_store_nss_->FindTrustAnchorsForCert(target_, base::Bind(&NotCalled),
- &sync_matches, &req);
- ASSERT_TRUE(req);
- req.reset();
- base::RunLoop().RunUntilIdle();
-}
-
-// Cancel a FindTrustAnchorsForCert request during the callback. Should not
-// crash.
-TEST_F(TrustStoreNSSTest, CancelRequestDuringCallback) {
- AddCertsToNSS();
- TrustCert(newroot_.get());
-
- base::RunLoop run_loop;
- std::unique_ptr<TrustStore::Request> req;
- TrustAnchors sync_matches;
- trust_store_nss_->FindTrustAnchorsForCert(
- newintermediate_,
- base::Bind(&TrustStoreRequestDeleter, &req, run_loop.QuitClosure()),
- &sync_matches, &req);
- ASSERT_TRUE(req);
- run_loop.Run();
- ASSERT_FALSE(req);
- base::RunLoop().RunUntilIdle();
+ EXPECT_TRUE(TrustStoreContains(target_, TrustAnchors()));
+ EXPECT_TRUE(TrustStoreContains(newintermediate_, {newroot_, oldroot_}));
+ EXPECT_TRUE(TrustStoreContains(oldintermediate_, {newroot_, oldroot_}));
+ EXPECT_TRUE(TrustStoreContains(oldroot_->cert(), {newroot_, oldroot_}));
}
} // namespace
diff --git a/chromium/net/cert/internal/trust_store_test_helpers.cc b/chromium/net/cert/internal/trust_store_test_helpers.cc
deleted file mode 100644
index 52edc4e61e4..00000000000
--- a/chromium/net/cert/internal/trust_store_test_helpers.cc
+++ /dev/null
@@ -1,95 +0,0 @@
-// Copyright 2016 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.
-
-#include "net/cert/internal/trust_store_test_helpers.h"
-
-#include "base/bind.h"
-#include "base/callback_helpers.h"
-#include "base/memory/ptr_util.h"
-#include "base/memory/weak_ptr.h"
-#include "base/threading/thread_task_runner_handle.h"
-
-namespace net {
-
-namespace {
-
-class TrustStoreInMemoryAsyncRequest : public TrustStore::Request {
- public:
- explicit TrustStoreInMemoryAsyncRequest(
- const TrustStore::TrustAnchorsCallback& callback)
- : callback_(callback), weak_ptr_factory_(this) {}
-
- void PostTrustCallback(TrustAnchors anchors) {
- base::ThreadTaskRunnerHandle::Get()->PostTask(
- FROM_HERE,
- base::Bind(&TrustStoreInMemoryAsyncRequest::DoTrustCallback,
- weak_ptr_factory_.GetWeakPtr(), std::move(anchors)));
- }
-
- private:
- void DoTrustCallback(TrustAnchors anchors) {
- base::ResetAndReturn(&callback_).Run(std::move(anchors));
- // |this| may be deleted here.
- }
-
- TrustStore::TrustAnchorsCallback callback_;
- base::WeakPtrFactory<TrustStoreInMemoryAsyncRequest> weak_ptr_factory_;
-};
-
-} // namespace
-
-void TrustStoreRequestDeleter(std::unique_ptr<TrustStore::Request>* req_owner,
- const base::Closure& done_callback,
- TrustAnchors anchors) {
- req_owner->reset();
- done_callback.Run();
-}
-
-TrustAnchorResultRecorder::TrustAnchorResultRecorder() = default;
-TrustAnchorResultRecorder::~TrustAnchorResultRecorder() = default;
-
-TrustStore::TrustAnchorsCallback TrustAnchorResultRecorder::Callback() {
- return base::Bind(&TrustAnchorResultRecorder::OnGotAnchors,
- base::Unretained(this));
-}
-
-void TrustAnchorResultRecorder::OnGotAnchors(TrustAnchors anchors) {
- anchors_ = std::move(anchors);
- run_loop_.Quit();
-}
-
-TrustStoreInMemoryAsync::TrustStoreInMemoryAsync() = default;
-TrustStoreInMemoryAsync::~TrustStoreInMemoryAsync() = default;
-
-void TrustStoreInMemoryAsync::AddSyncTrustAnchor(
- scoped_refptr<TrustAnchor> anchor) {
- sync_store_.AddTrustAnchor(std::move(anchor));
-}
-
-void TrustStoreInMemoryAsync::AddAsyncTrustAnchor(
- scoped_refptr<TrustAnchor> anchor) {
- async_store_.AddTrustAnchor(std::move(anchor));
-}
-
-void TrustStoreInMemoryAsync::FindTrustAnchorsForCert(
- const scoped_refptr<ParsedCertificate>& cert,
- const TrustAnchorsCallback& callback,
- TrustAnchors* synchronous_matches,
- std::unique_ptr<Request>* out_req) const {
- sync_store_.FindTrustAnchorsForCert(cert, TrustAnchorsCallback(),
- synchronous_matches, nullptr);
- if (!callback.is_null()) {
- TrustAnchors async_matches;
- async_store_.FindTrustAnchorsForCert(cert, TrustAnchorsCallback(),
- &async_matches, nullptr);
-
- std::unique_ptr<TrustStoreInMemoryAsyncRequest> req(
- base::MakeUnique<TrustStoreInMemoryAsyncRequest>(callback));
- req->PostTrustCallback(std::move(async_matches));
-
- *out_req = std::move(req);
- }
-}
-
-} // namespace net
diff --git a/chromium/net/cert/internal/trust_store_test_helpers.h b/chromium/net/cert/internal/trust_store_test_helpers.h
deleted file mode 100644
index 3d1d5a6594c..00000000000
--- a/chromium/net/cert/internal/trust_store_test_helpers.h
+++ /dev/null
@@ -1,68 +0,0 @@
-// Copyright 2016 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.
-
-#ifndef NET_CERT_INTERNAL_TRUST_STORE_TEST_HELPERS_H_
-#define NET_CERT_INTERNAL_TRUST_STORE_TEST_HELPERS_H_
-
-#include "base/callback.h"
-#include "base/run_loop.h"
-#include "net/cert/internal/trust_store.h"
-#include "net/cert/internal/trust_store_in_memory.h"
-
-namespace net {
-
-// Deletes the Request owned by |*req_owner|, then calls done_callback. Intended
-// to be passed as the TrustAnchorsCallback to FindTrustAnchorsForCert to test
-// deleting the Request during the request callback.
-void TrustStoreRequestDeleter(std::unique_ptr<TrustStore::Request>* req_owner,
- const base::Closure& done_callback,
- TrustAnchors anchors);
-
-// Helper to record async results from a FindTrustAnchorsForCert call.
-class TrustAnchorResultRecorder {
- public:
- TrustAnchorResultRecorder();
- ~TrustAnchorResultRecorder();
-
- TrustStore::TrustAnchorsCallback Callback();
-
- void Run() { run_loop_.Run(); }
-
- const TrustAnchors& matches() const { return anchors_; }
-
- private:
- void OnGotAnchors(TrustAnchors anchors);
-
- base::RunLoop run_loop_;
- TrustAnchors anchors_;
-};
-
-// In-memory TrustStore that can return results synchronously, asynchronously,
-// or both.
-class TrustStoreInMemoryAsync : public TrustStore {
- public:
- TrustStoreInMemoryAsync();
- ~TrustStoreInMemoryAsync() override;
-
- // Adds |anchor| to the set of results that will be returned synchronously.
- void AddSyncTrustAnchor(scoped_refptr<TrustAnchor> anchor);
-
- // Adds |anchor| to the set of results that will be returned asynchronously.
- void AddAsyncTrustAnchor(scoped_refptr<TrustAnchor> anchor);
-
- // TrustStore implementation:
- void FindTrustAnchorsForCert(
- const scoped_refptr<ParsedCertificate>& cert,
- const TrustAnchorsCallback& callback,
- TrustAnchors* synchronous_matches,
- std::unique_ptr<Request>* out_req) const override;
-
- private:
- TrustStoreInMemory sync_store_;
- TrustStoreInMemory async_store_;
-};
-
-} // namespace net
-
-#endif // NET_CERT_INTERNAL_TRUST_STORE_TEST_HELPERS_H_
diff --git a/chromium/net/cert/internal/verify_certificate_chain.h b/chromium/net/cert/internal/verify_certificate_chain.h
index d1ea57e0575..428bd7b0214 100644
--- a/chromium/net/cert/internal/verify_certificate_chain.h
+++ b/chromium/net/cert/internal/verify_certificate_chain.h
@@ -22,7 +22,6 @@ struct GeneralizedTime;
class SignaturePolicy;
class TrustAnchor;
-class TrustStore;
// VerifyCertificateChain() verifies a certificate path (chain) based on the
// rules in RFC 5280. The caller is responsible for building the path and
diff --git a/chromium/net/cert/internal/verify_signed_data.cc b/chromium/net/cert/internal/verify_signed_data.cc
index 37fc0eb0a9e..8fd045b2a91 100644
--- a/chromium/net/cert/internal/verify_signed_data.cc
+++ b/chromium/net/cert/internal/verify_signed_data.cc
@@ -6,6 +6,7 @@
#include "base/compiler_specific.h"
#include "base/logging.h"
+#include "base/numerics/safe_math.h"
#include "crypto/openssl_util.h"
#include "net/cert/internal/cert_errors.h"
#include "net/cert/internal/signature_algorithm.h"
diff --git a/chromium/net/cert/multi_log_ct_verifier.cc b/chromium/net/cert/multi_log_ct_verifier.cc
index 61c07b6d4e5..a372b05c8a9 100644
--- a/chromium/net/cert/multi_log_ct_verifier.cc
+++ b/chromium/net/cert/multi_log_ct_verifier.cc
@@ -81,10 +81,10 @@ void MultiLogCTVerifier::SetObserver(Observer* observer) {
observer_ = observer;
}
-int MultiLogCTVerifier::Verify(
+void MultiLogCTVerifier::Verify(
X509Certificate* cert,
- const std::string& stapled_ocsp_response,
- const std::string& sct_list_from_tls_extension,
+ base::StringPiece stapled_ocsp_response,
+ base::StringPiece sct_list_from_tls_extension,
SignedCertificateTimestampAndStatusList* output_scts,
const NetLogWithSource& net_log) {
DCHECK(cert);
@@ -92,8 +92,6 @@ int MultiLogCTVerifier::Verify(
output_scts->clear();
- bool has_verified_scts = false;
-
std::string embedded_scts;
if (!cert->GetIntermediateCertificates().empty() &&
ct::ExtractEmbeddedSCTList(
@@ -101,13 +99,13 @@ int MultiLogCTVerifier::Verify(
&embedded_scts)) {
ct::LogEntry precert_entry;
- has_verified_scts =
- ct::GetPrecertLogEntry(cert->os_cert_handle(),
+ if (ct::GetPrecertLogEntry(cert->os_cert_handle(),
cert->GetIntermediateCertificates().front(),
- &precert_entry) &&
- VerifySCTs(embedded_scts, precert_entry,
- ct::SignedCertificateTimestamp::SCT_EMBEDDED, cert,
- output_scts);
+ &precert_entry)) {
+ VerifySCTs(embedded_scts, precert_entry,
+ ct::SignedCertificateTimestamp::SCT_EMBEDDED, cert,
+ output_scts);
+ }
}
std::string sct_list_from_ocsp;
@@ -121,23 +119,21 @@ int MultiLogCTVerifier::Verify(
// Log to Net Log, after extracting SCTs but before possibly failing on
// X.509 entry creation.
NetLogParametersCallback net_log_callback =
- base::Bind(&NetLogRawSignedCertificateTimestampCallback, &embedded_scts,
- &sct_list_from_ocsp, &sct_list_from_tls_extension);
+ base::Bind(&NetLogRawSignedCertificateTimestampCallback, embedded_scts,
+ sct_list_from_ocsp, sct_list_from_tls_extension);
net_log.AddEvent(NetLogEventType::SIGNED_CERTIFICATE_TIMESTAMPS_RECEIVED,
net_log_callback);
ct::LogEntry x509_entry;
if (ct::GetX509LogEntry(cert->os_cert_handle(), &x509_entry)) {
- has_verified_scts |=
- VerifySCTs(sct_list_from_ocsp, x509_entry,
- ct::SignedCertificateTimestamp::SCT_FROM_OCSP_RESPONSE, cert,
- output_scts);
-
- has_verified_scts |=
- VerifySCTs(sct_list_from_tls_extension, x509_entry,
- ct::SignedCertificateTimestamp::SCT_FROM_TLS_EXTENSION, cert,
- output_scts);
+ VerifySCTs(sct_list_from_ocsp, x509_entry,
+ ct::SignedCertificateTimestamp::SCT_FROM_OCSP_RESPONSE, cert,
+ output_scts);
+
+ VerifySCTs(sct_list_from_tls_extension, x509_entry,
+ ct::SignedCertificateTimestamp::SCT_FROM_TLS_EXTENSION, cert,
+ output_scts);
}
NetLogParametersCallback net_log_checked_callback =
@@ -147,29 +143,22 @@ int MultiLogCTVerifier::Verify(
net_log_checked_callback);
LogNumSCTsToUMA(*output_scts);
-
- if (has_verified_scts)
- return OK;
-
- return ERR_CT_NO_SCTS_VERIFIED_OK;
}
-bool MultiLogCTVerifier::VerifySCTs(
- const std::string& encoded_sct_list,
+void MultiLogCTVerifier::VerifySCTs(
+ base::StringPiece encoded_sct_list,
const ct::LogEntry& expected_entry,
ct::SignedCertificateTimestamp::Origin origin,
X509Certificate* cert,
SignedCertificateTimestampAndStatusList* output_scts) {
if (logs_.empty())
- return false;
+ return;
- base::StringPiece temp(encoded_sct_list);
std::vector<base::StringPiece> sct_list;
- if (!ct::DecodeSCTList(&temp, &sct_list))
- return false;
+ if (!ct::DecodeSCTList(encoded_sct_list, &sct_list))
+ return;
- bool verified = false;
for (std::vector<base::StringPiece>::const_iterator it = sct_list.begin();
it != sct_list.end(); ++it) {
base::StringPiece encoded_sct(*it);
@@ -178,15 +167,12 @@ bool MultiLogCTVerifier::VerifySCTs(
scoped_refptr<ct::SignedCertificateTimestamp> decoded_sct;
if (!DecodeSignedCertificateTimestamp(&encoded_sct, &decoded_sct)) {
LogSCTStatusToUMA(ct::SCT_STATUS_NONE);
- // XXX(rsleevi): Should we really just skip over bad SCTs?
continue;
}
decoded_sct->origin = origin;
- verified |= VerifySingleSCT(decoded_sct, expected_entry, cert, output_scts);
+ VerifySingleSCT(decoded_sct, expected_entry, cert, output_scts);
}
-
- return verified;
}
bool MultiLogCTVerifier::VerifySingleSCT(
diff --git a/chromium/net/cert/multi_log_ct_verifier.h b/chromium/net/cert/multi_log_ct_verifier.h
index 05c2c069264..d4cb56fc2ac 100644
--- a/chromium/net/cert/multi_log_ct_verifier.h
+++ b/chromium/net/cert/multi_log_ct_verifier.h
@@ -10,6 +10,7 @@
#include "base/macros.h"
#include "base/memory/ref_counted.h"
+#include "base/strings/string_piece.h"
#include "net/base/net_export.h"
#include "net/cert/ct_verifier.h"
#include "net/cert/signed_certificate_timestamp.h"
@@ -34,19 +35,19 @@ class NET_EXPORT MultiLogCTVerifier : public CTVerifier {
const std::vector<scoped_refptr<const CTLogVerifier>>& log_verifiers);
// CTVerifier implementation:
- int Verify(X509Certificate* cert,
- const std::string& stapled_ocsp_response,
- const std::string& sct_list_from_tls_extension,
- SignedCertificateTimestampAndStatusList* output_scts,
- const NetLogWithSource& net_log) override;
+ void Verify(X509Certificate* cert,
+ base::StringPiece stapled_ocsp_response,
+ base::StringPiece sct_list_from_tls_extension,
+ SignedCertificateTimestampAndStatusList* output_scts,
+ const NetLogWithSource& net_log) override;
void SetObserver(Observer* observer) override;
private:
// Verify a list of SCTs from |encoded_sct_list| over |expected_entry|,
- // placing the verification results in |result|. The SCTs in the list
+ // placing the verification results in |output_scts|. The SCTs in the list
// come from |origin| (as will be indicated in the origin field of each SCT).
- bool VerifySCTs(const std::string& encoded_sct_list,
+ void VerifySCTs(base::StringPiece encoded_sct_list,
const ct::LogEntry& expected_entry,
ct::SignedCertificateTimestamp::Origin origin,
X509Certificate* cert,
diff --git a/chromium/net/cert/multi_log_ct_verifier_unittest.cc b/chromium/net/cert/multi_log_ct_verifier_unittest.cc
index 2efd7012a46..aea27f97195 100644
--- a/chromium/net/cert/multi_log_ct_verifier_unittest.cc
+++ b/chromium/net/cert/multi_log_ct_verifier_unittest.cc
@@ -111,34 +111,29 @@ class MultiLogCTVerifierTest : public ::testing::Test {
return true;
}
- bool VerifySinglePrecertificateChain(
- scoped_refptr<X509Certificate> chain,
- const NetLogWithSource& net_log,
- SignedCertificateTimestampAndStatusList* output_scts) {
- return verifier_->Verify(chain.get(), std::string(), std::string(),
- output_scts, net_log) == OK;
- }
-
+ // Returns true is |chain| is a certificate with embedded SCTs that can be
+ // successfully extracted.
bool VerifySinglePrecertificateChain(scoped_refptr<X509Certificate> chain) {
SignedCertificateTimestampAndStatusList scts;
- TestNetLog test_net_log;
- NetLogWithSource net_log =
- NetLogWithSource::Make(&test_net_log, NetLogSourceType::CONNECT_JOB);
-
- return verifier_->Verify(chain.get(), std::string(), std::string(), &scts,
- net_log) == OK;
+ verifier_->Verify(chain.get(), base::StringPiece(), base::StringPiece(),
+ &scts, NetLogWithSource());
+ return !scts.empty();
}
+ // Returns true if |chain| is a certificate with a single embedded SCT that
+ // can be successfully extracted and matched to the test log indicated by
+ // |kLogDescription|.
bool CheckPrecertificateVerification(scoped_refptr<X509Certificate> chain) {
SignedCertificateTimestampAndStatusList scts;
TestNetLog test_net_log;
- NetLogWithSource net_log =
- NetLogWithSource::Make(&test_net_log, NetLogSourceType::CONNECT_JOB);
- return (VerifySinglePrecertificateChain(chain, net_log, &scts) &&
- ct::CheckForSingleVerifiedSCTInResult(scts, kLogDescription) &&
- ct::CheckForSCTOrigin(
- scts, ct::SignedCertificateTimestamp::SCT_EMBEDDED) &&
- CheckForEmbeddedSCTInNetLog(test_net_log));
+ NetLogWithSource net_log = NetLogWithSource::Make(
+ &test_net_log, NetLogSourceType::SSL_CONNECT_JOB);
+ verifier_->Verify(chain.get(), base::StringPiece(), base::StringPiece(),
+ &scts, net_log);
+ return ct::CheckForSingleVerifiedSCTInResult(scts, kLogDescription) &&
+ ct::CheckForSCTOrigin(
+ scts, ct::SignedCertificateTimestamp::SCT_EMBEDDED) &&
+ CheckForEmbeddedSCTInNetLog(test_net_log);
}
// Histogram-related helper methods
@@ -212,8 +207,8 @@ TEST_F(MultiLogCTVerifierTest, VerifiesSCTOverX509Cert) {
std::string sct_list = ct::GetSCTListForTesting();
SignedCertificateTimestampAndStatusList scts;
- EXPECT_EQ(OK, verifier_->Verify(chain_.get(), std::string(), sct_list, &scts,
- NetLogWithSource()));
+ verifier_->Verify(chain_.get(), base::StringPiece(), sct_list, &scts,
+ NetLogWithSource());
ASSERT_TRUE(ct::CheckForSingleVerifiedSCTInResult(scts, kLogDescription));
ASSERT_TRUE(ct::CheckForSCTOrigin(
scts, ct::SignedCertificateTimestamp::SCT_FROM_TLS_EXTENSION));
@@ -223,8 +218,8 @@ TEST_F(MultiLogCTVerifierTest, IdentifiesSCTFromUnknownLog) {
std::string sct_list = ct::GetSCTListWithInvalidSCT();
SignedCertificateTimestampAndStatusList scts;
- EXPECT_NE(OK, verifier_->Verify(chain_.get(), std::string(), sct_list, &scts,
- NetLogWithSource()));
+ verifier_->Verify(chain_.get(), base::StringPiece(), sct_list, &scts,
+ NetLogWithSource());
EXPECT_EQ(1U, scts.size());
EXPECT_EQ("", scts[0].sct->log_description);
EXPECT_EQ(ct::SCT_STATUS_LOG_UNKNOWN, scts[0].status);
@@ -246,8 +241,8 @@ TEST_F(MultiLogCTVerifierTest, CountsInvalidSCTsInStatusHistogram) {
int num_invalid_scts = GetValueFromHistogram(
"Net.CertificateTransparency.SCTStatus", ct::SCT_STATUS_LOG_UNKNOWN);
- EXPECT_NE(OK, verifier_->Verify(chain_.get(), std::string(), sct_list, &scts,
- NetLogWithSource()));
+ verifier_->Verify(chain_.get(), base::StringPiece(), sct_list, &scts,
+ NetLogWithSource());
ASSERT_EQ(num_valid_scts, NumValidSCTsInStatusHistogram());
ASSERT_EQ(num_invalid_scts + 1,
diff --git a/chromium/net/cert/multi_threaded_cert_verifier.cc b/chromium/net/cert/multi_threaded_cert_verifier.cc
index 061ecd973f9..8312d413933 100644
--- a/chromium/net/cert/multi_threaded_cert_verifier.cc
+++ b/chromium/net/cert/multi_threaded_cert_verifier.cc
@@ -24,6 +24,7 @@
#include "base/values.h"
#include "net/base/hash_value.h"
#include "net/base/net_errors.h"
+#include "net/base/trace_constants.h"
#include "net/cert/cert_verify_proc.h"
#include "net/cert/cert_verify_result.h"
#include "net/cert/crl_set.h"
@@ -189,7 +190,7 @@ void DoVerifyOnWorkerThread(const scoped_refptr<CertVerifyProc>& verify_proc,
const CertificateList& additional_trust_anchors,
int* error,
CertVerifyResult* result) {
- TRACE_EVENT0("net", "DoVerifyOnWorkerThread");
+ TRACE_EVENT0(kNetTracingCategory, "DoVerifyOnWorkerThread");
*error = verify_proc->Verify(cert.get(), hostname, ocsp_response, flags,
crl_set.get(), additional_trust_anchors, result);
@@ -308,7 +309,7 @@ class CertVerifierJob {
}
void OnJobCompleted(std::unique_ptr<ResultHelper> verify_result) {
- TRACE_EVENT0("net", "CertVerifierJob::OnJobCompleted");
+ TRACE_EVENT0(kNetTracingCategory, "CertVerifierJob::OnJobCompleted");
std::unique_ptr<CertVerifierJob> keep_alive =
cert_verifier_->RemoveJob(this);
diff --git a/chromium/net/cert/multi_threaded_cert_verifier.h b/chromium/net/cert/multi_threaded_cert_verifier.h
index 6022984dac6..6b9dfadb7ae 100644
--- a/chromium/net/cert/multi_threaded_cert_verifier.h
+++ b/chromium/net/cert/multi_threaded_cert_verifier.h
@@ -25,7 +25,6 @@ namespace net {
class CertVerifierJob;
class CertVerifierRequest;
-class CertVerifierWorker;
class CertVerifyProc;
// MultiThreadedCertVerifier is a CertVerifier implementation that runs
diff --git a/chromium/net/cert/multi_threaded_cert_verifier_unittest.cc b/chromium/net/cert/multi_threaded_cert_verifier_unittest.cc
index 1c1dbe43f31..aecbb51de08 100644
--- a/chromium/net/cert/multi_threaded_cert_verifier_unittest.cc
+++ b/chromium/net/cert/multi_threaded_cert_verifier_unittest.cc
@@ -10,7 +10,6 @@
#include "base/debug/leak_annotations.h"
#include "base/files/file_path.h"
#include "base/format_macros.h"
-#include "base/strings/stringprintf.h"
#include "net/base/net_errors.h"
#include "net/base/test_completion_callback.h"
#include "net/cert/cert_verify_proc.h"
diff --git a/chromium/net/cert/nss_cert_database.cc b/chromium/net/cert/nss_cert_database.cc
index 6842643d5f6..fc2ae61557a 100644
--- a/chromium/net/cert/nss_cert_database.cc
+++ b/chromium/net/cert/nss_cert_database.cc
@@ -143,16 +143,6 @@ crypto::ScopedPK11Slot NSSCertDatabase::GetPrivateSlot() const {
return crypto::ScopedPK11Slot(PK11_ReferenceSlot(private_slot_.get()));
}
-CryptoModule* NSSCertDatabase::GetPublicModule() const {
- crypto::ScopedPK11Slot slot(GetPublicSlot());
- return CryptoModule::CreateFromHandle(slot.get());
-}
-
-CryptoModule* NSSCertDatabase::GetPrivateModule() const {
- crypto::ScopedPK11Slot slot(GetPrivateSlot());
- return CryptoModule::CreateFromHandle(slot.get());
-}
-
void NSSCertDatabase::ListModules(CryptoModuleList* modules,
bool need_rw) const {
modules->clear();
@@ -176,15 +166,15 @@ void NSSCertDatabase::ListModules(CryptoModuleList* modules,
}
}
-int NSSCertDatabase::ImportFromPKCS12(CryptoModule* module,
+int NSSCertDatabase::ImportFromPKCS12(PK11SlotInfo* slot_info,
const std::string& data,
const base::string16& password,
bool is_extractable,
CertificateList* imported_certs) {
DVLOG(1) << __func__ << " "
- << PK11_GetModuleID(module->os_module_handle()) << ":"
- << PK11_GetSlotID(module->os_module_handle());
- int result = psm::nsPKCS12Blob_Import(module->os_module_handle(),
+ << PK11_GetModuleID(slot_info) << ":"
+ << PK11_GetSlotID(slot_info);
+ int result = psm::nsPKCS12Blob_Import(slot_info,
data.data(), data.size(),
password,
is_extractable,
diff --git a/chromium/net/cert/nss_cert_database.h b/chromium/net/cert/nss_cert_database.h
index 2ee859dbb71..18e14768ac0 100644
--- a/chromium/net/cert/nss_cert_database.h
+++ b/chromium/net/cert/nss_cert_database.h
@@ -145,18 +145,6 @@ class NET_EXPORT NSSCertDatabase {
// Can return NULL.
crypto::ScopedPK11Slot GetPrivateSlot() const;
- // Get the default module for public key data.
- // The returned pointer must be stored in a scoped_refptr<CryptoModule>.
- // DEPRECATED: use GetPublicSlot instead.
- // TODO(mattm): remove usage of this method and remove it.
- CryptoModule* GetPublicModule() const;
-
- // Get the default module for private key or mixed private/public key data.
- // The returned pointer must be stored in a scoped_refptr<CryptoModule>.
- // DEPRECATED: use GetPrivateSlot instead.
- // TODO(mattm): remove usage of this method and remove it.
- CryptoModule* GetPrivateModule() const;
-
// Get all modules.
// If |need_rw| is true, only writable modules will be returned.
// TODO(mattm): come up with better alternative to CryptoModuleList.
@@ -168,7 +156,7 @@ class NET_EXPORT NSSCertDatabase {
// Returns OK or a network error code such as ERR_PKCS12_IMPORT_BAD_PASSWORD
// or ERR_PKCS12_IMPORT_ERROR. |imported_certs|, if non-NULL, returns a list
// of certs that were imported.
- int ImportFromPKCS12(CryptoModule* module,
+ int ImportFromPKCS12(PK11SlotInfo* slot_info,
const std::string& data,
const base::string16& password,
bool is_extractable,
diff --git a/chromium/net/cert/nss_cert_database_chromeos.h b/chromium/net/cert/nss_cert_database_chromeos.h
index 4eb27a7fd48..fa440575fb0 100644
--- a/chromium/net/cert/nss_cert_database_chromeos.h
+++ b/chromium/net/cert/nss_cert_database_chromeos.h
@@ -2,8 +2,8 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#ifndef NET_CERT_NSS_CERT_DATABASE_CHROMEOS_
-#define NET_CERT_NSS_CERT_DATABASE_CHROMEOS_
+#ifndef NET_CERT_NSS_CERT_DATABASE_CHROMEOS_H_
+#define NET_CERT_NSS_CERT_DATABASE_CHROMEOS_H_
#include "base/callback.h"
#include "base/macros.h"
@@ -51,4 +51,4 @@ class NET_EXPORT NSSCertDatabaseChromeOS : public NSSCertDatabase {
} // namespace net
-#endif // NET_CERT_NSS_CERT_DATABASE_CHROMEOS_
+#endif // NET_CERT_NSS_CERT_DATABASE_CHROMEOS_H_
diff --git a/chromium/net/cert/nss_cert_database_unittest.cc b/chromium/net/cert/nss_cert_database_unittest.cc
index 9e20f886def..235ea44cc0d 100644
--- a/chromium/net/cert/nss_cert_database_unittest.cc
+++ b/chromium/net/cert/nss_cert_database_unittest.cc
@@ -68,7 +68,7 @@ class CertDatabaseNSSTest : public testing::Test {
PK11_ReferenceSlot(test_nssdb_.slot())) /* public slot */,
crypto::ScopedPK11Slot(
PK11_ReferenceSlot(test_nssdb_.slot())) /* private slot */));
- public_module_ = cert_db_->GetPublicModule();
+ public_slot_ = cert_db_->GetPublicSlot();
// Test db should be empty at start of test.
EXPECT_EQ(0U, ListCerts().size());
@@ -82,7 +82,7 @@ class CertDatabaseNSSTest : public testing::Test {
}
protected:
- CryptoModule* GetPublicModule() { return public_module_.get(); }
+ PK11SlotInfo* GetPublicSlot() { return public_slot_.get(); }
static std::string ReadTestFile(const std::string& name) {
std::string result;
@@ -128,7 +128,7 @@ class CertDatabaseNSSTest : public testing::Test {
std::unique_ptr<NSSCertDatabase> cert_db_;
const CertificateList empty_cert_list_;
crypto::ScopedTestNSSDB test_nssdb_;
- scoped_refptr<CryptoModule> public_module_;
+ crypto::ScopedPK11Slot public_slot_;
};
TEST_F(CertDatabaseNSSTest, ListCertsSync) {
@@ -160,7 +160,7 @@ TEST_F(CertDatabaseNSSTest, ImportFromPKCS12WrongPassword) {
std::string pkcs12_data = ReadTestFile("client.p12");
EXPECT_EQ(ERR_PKCS12_IMPORT_BAD_PASSWORD,
- cert_db_->ImportFromPKCS12(GetPublicModule(),
+ cert_db_->ImportFromPKCS12(GetPublicSlot(),
pkcs12_data,
base::string16(),
true, // is_extractable
@@ -174,7 +174,7 @@ TEST_F(CertDatabaseNSSTest, ImportFromPKCS12AsExtractableAndExportAgain) {
std::string pkcs12_data = ReadTestFile("client.p12");
EXPECT_EQ(OK,
- cert_db_->ImportFromPKCS12(GetPublicModule(),
+ cert_db_->ImportFromPKCS12(GetPublicSlot(),
pkcs12_data,
ASCIIToUTF16("12345"),
true, // is_extractable
@@ -199,7 +199,7 @@ TEST_F(CertDatabaseNSSTest, ImportFromPKCS12Twice) {
std::string pkcs12_data = ReadTestFile("client.p12");
EXPECT_EQ(OK,
- cert_db_->ImportFromPKCS12(GetPublicModule(),
+ cert_db_->ImportFromPKCS12(GetPublicSlot(),
pkcs12_data,
ASCIIToUTF16("12345"),
true, // is_extractable
@@ -209,7 +209,7 @@ TEST_F(CertDatabaseNSSTest, ImportFromPKCS12Twice) {
// NSS has a SEC_ERROR_PKCS12_DUPLICATE_DATA error, but it doesn't look like
// it's ever used. This test verifies that.
EXPECT_EQ(OK,
- cert_db_->ImportFromPKCS12(GetPublicModule(),
+ cert_db_->ImportFromPKCS12(GetPublicSlot(),
pkcs12_data,
ASCIIToUTF16("12345"),
true, // is_extractable
@@ -221,7 +221,7 @@ TEST_F(CertDatabaseNSSTest, ImportFromPKCS12AsUnextractableAndExportAgain) {
std::string pkcs12_data = ReadTestFile("client.p12");
EXPECT_EQ(OK,
- cert_db_->ImportFromPKCS12(GetPublicModule(),
+ cert_db_->ImportFromPKCS12(GetPublicSlot(),
pkcs12_data,
ASCIIToUTF16("12345"),
false, // is_extractable
@@ -244,7 +244,7 @@ TEST_F(CertDatabaseNSSTest, ImportFromPKCS12AsUnextractableAndExportAgain) {
TEST_F(CertDatabaseNSSTest, ImportFromPKCS12OnlyMarkIncludedKey) {
std::string pkcs12_data = ReadTestFile("client.p12");
EXPECT_EQ(OK,
- cert_db_->ImportFromPKCS12(GetPublicModule(),
+ cert_db_->ImportFromPKCS12(GetPublicSlot(),
pkcs12_data,
ASCIIToUTF16("12345"),
true, // is_extractable
@@ -256,7 +256,7 @@ TEST_F(CertDatabaseNSSTest, ImportFromPKCS12OnlyMarkIncludedKey) {
// Now import a PKCS#12 file with just a certificate but no private key.
pkcs12_data = ReadTestFile("client-nokey.p12");
EXPECT_EQ(OK,
- cert_db_->ImportFromPKCS12(GetPublicModule(),
+ cert_db_->ImportFromPKCS12(GetPublicSlot(),
pkcs12_data,
ASCIIToUTF16("12345"),
false, // is_extractable
@@ -276,7 +276,7 @@ TEST_F(CertDatabaseNSSTest, ImportFromPKCS12InvalidFile) {
std::string pkcs12_data = "Foobarbaz";
EXPECT_EQ(ERR_PKCS12_IMPORT_INVALID_FILE,
- cert_db_->ImportFromPKCS12(GetPublicModule(),
+ cert_db_->ImportFromPKCS12(GetPublicSlot(),
pkcs12_data,
base::string16(),
true, // is_extractable
@@ -286,6 +286,30 @@ TEST_F(CertDatabaseNSSTest, ImportFromPKCS12InvalidFile) {
EXPECT_EQ(0U, ListCerts().size());
}
+TEST_F(CertDatabaseNSSTest, ImportFromPKCS12EmptyPassword) {
+ std::string pkcs12_data = ReadTestFile("client-empty-password.p12");
+
+ EXPECT_EQ(OK,
+ cert_db_->ImportFromPKCS12(GetPublicSlot(),
+ pkcs12_data,
+ base::string16(),
+ true, // is_extractable
+ NULL));
+ EXPECT_EQ(1U, ListCerts().size());
+}
+
+TEST_F(CertDatabaseNSSTest, ImportFromPKCS12NullPassword) {
+ std::string pkcs12_data = ReadTestFile("client-null-password.p12");
+
+ EXPECT_EQ(OK,
+ cert_db_->ImportFromPKCS12(GetPublicSlot(),
+ pkcs12_data,
+ base::string16(),
+ true, // is_extractable
+ NULL));
+ EXPECT_EQ(1U, ListCerts().size());
+}
+
TEST_F(CertDatabaseNSSTest, ImportCACert_SSLTrust) {
CertificateList certs = CreateCertificateListFromFile(
GetTestCertsDirectory(), "root_ca_cert.pem",
diff --git a/chromium/net/cert/nss_profile_filter_chromeos.cc b/chromium/net/cert/nss_profile_filter_chromeos.cc
index adb5defb6f8..71eeab20629 100644
--- a/chromium/net/cert/nss_profile_filter_chromeos.cc
+++ b/chromium/net/cert/nss_profile_filter_chromeos.cc
@@ -158,4 +158,3 @@ bool NSSProfileFilterChromeOS::ModuleNotAllowedForProfilePredicate::operator()(
}
} // namespace net
-
diff --git a/chromium/net/cert/ocsp_revocation_status.h b/chromium/net/cert/ocsp_revocation_status.h
index 945104f26f6..c20dd2e2c83 100644
--- a/chromium/net/cert/ocsp_revocation_status.h
+++ b/chromium/net/cert/ocsp_revocation_status.h
@@ -2,8 +2,8 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#ifndef NET_CERT_OCSP_REVOCATION_STATUS_H
-#define NET_CERT_OCSP_REVOCATION_STATUS_H
+#ifndef NET_CERT_OCSP_REVOCATION_STATUS_H_
+#define NET_CERT_OCSP_REVOCATION_STATUS_H_
namespace net {
@@ -15,4 +15,4 @@ enum class OCSPRevocationStatus {
} // namespace net
-#endif // NET_CERT_OCSP_REVOCATION_STATUS_H
+#endif // NET_CERT_OCSP_REVOCATION_STATUS_H_
diff --git a/chromium/net/cert/ocsp_verify_result.h b/chromium/net/cert/ocsp_verify_result.h
index a2b8494b277..3a0bd7c26e3 100644
--- a/chromium/net/cert/ocsp_verify_result.h
+++ b/chromium/net/cert/ocsp_verify_result.h
@@ -2,8 +2,8 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#ifndef NET_CERT_OCSP_VERIFY_RESULT_H
-#define NET_CERT_OCSP_VERIFY_RESULT_H
+#ifndef NET_CERT_OCSP_VERIFY_RESULT_H_
+#define NET_CERT_OCSP_VERIFY_RESULT_H_
#include <string>
@@ -27,6 +27,9 @@ struct NET_EXPORT OCSPVerifyResult {
bool operator==(const OCSPVerifyResult& other) const;
enum ResponseStatus {
+ // OCSP verification was not checked on this connection.
+ NOT_CHECKED,
+
// No OCSPResponse was stapled.
MISSING,
@@ -56,7 +59,7 @@ struct NET_EXPORT OCSPVerifyResult {
};
- ResponseStatus response_status = MISSING;
+ ResponseStatus response_status = NOT_CHECKED;
// The strictest CertStatus matching the certificate (REVOKED > UNKNOWN >
// GOOD). Only valid if |response_status| = PROVIDED.
@@ -65,4 +68,4 @@ struct NET_EXPORT OCSPVerifyResult {
} // namespace net
-#endif // NET_CERT_OCSP_VERIFY_RESULT_H
+#endif // NET_CERT_OCSP_VERIFY_RESULT_H_
diff --git a/chromium/net/cert/signed_tree_head.h b/chromium/net/cert/signed_tree_head.h
index 2d65192fc54..2b97f744506 100644
--- a/chromium/net/cert/signed_tree_head.h
+++ b/chromium/net/cert/signed_tree_head.h
@@ -61,4 +61,4 @@ NET_EXPORT bool operator!=(const SignedTreeHead& lhs,
} // namespace net
-#endif
+#endif // NET_CERT_SIGNED_TREE_HEAD_H_
diff --git a/chromium/net/cert/test_keychain_search_list_mac.h b/chromium/net/cert/test_keychain_search_list_mac.h
index d0faffdbf54..4ae25729c93 100644
--- a/chromium/net/cert/test_keychain_search_list_mac.h
+++ b/chromium/net/cert/test_keychain_search_list_mac.h
@@ -2,8 +2,8 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#ifndef NET_CERT_KEYCHAIN_SEARCH_LIST_MAC_H_
-#define NET_CERT_KEYCHAIN_SEARCH_LIST_MAC_H_
+#ifndef NET_CERT_TEST_KEYCHAIN_SEARCH_LIST_MAC_H_
+#define NET_CERT_TEST_KEYCHAIN_SEARCH_LIST_MAC_H_
#include <CoreServices/CoreServices.h>
#include <Security/Security.h>
@@ -43,4 +43,4 @@ class NET_EXPORT TestKeychainSearchList {
} // namespace net
-#endif // NET_CERT_KEYCHAIN_SEARCH_LIST_MAC_H_
+#endif // NET_CERT_TEST_KEYCHAIN_SEARCH_LIST_MAC_H_
diff --git a/chromium/net/cert/test_root_certs.h b/chromium/net/cert/test_root_certs.h
index a77f0bf5f1d..53dd5f59106 100644
--- a/chromium/net/cert/test_root_certs.h
+++ b/chromium/net/cert/test_root_certs.h
@@ -150,7 +150,7 @@ class NET_EXPORT TestRootCerts {
class NET_EXPORT_PRIVATE ScopedTestRoot {
public:
ScopedTestRoot();
- // Creates a ScopedTestRoot that will adds|cert| to the TestRootCerts store.
+ // Creates a ScopedTestRoot that will add |cert| to the TestRootCerts store.
explicit ScopedTestRoot(X509Certificate* cert);
~ScopedTestRoot();
diff --git a/chromium/net/cert/x509_cert_types.cc b/chromium/net/cert/x509_cert_types.cc
index e2ffb3d1b05..eec184a10f4 100644
--- a/chromium/net/cert/x509_cert_types.cc
+++ b/chromium/net/cert/x509_cert_types.cc
@@ -71,13 +71,9 @@ bool ParseCertificateDate(const base::StringPiece& raw_date,
if (valid && year_length == 2)
exploded.year += exploded.year < 50 ? 2000 : 1900;
- valid &= exploded.HasValidValues();
-
if (!valid)
return false;
-
- *time = base::Time::FromUTCExploded(exploded);
- return true;
+ return base::Time::FromUTCExploded(exploded, time);
}
} // namespace net
diff --git a/chromium/net/cert/x509_cert_types.h b/chromium/net/cert/x509_cert_types.h
index d2a55fe4b54..acb5b4fa3d5 100644
--- a/chromium/net/cert/x509_cert_types.h
+++ b/chromium/net/cert/x509_cert_types.h
@@ -30,8 +30,6 @@ class Time;
namespace net {
-class X509Certificate;
-
// CertPrincipal represents the issuer or subject field of an X.509 certificate.
struct NET_EXPORT CertPrincipal {
CertPrincipal();
diff --git a/chromium/net/cert/x509_cert_types_unittest.cc b/chromium/net/cert/x509_cert_types_unittest.cc
index 50275f0eb01..cc9d88fbe9f 100644
--- a/chromium/net/cert/x509_cert_types_unittest.cc
+++ b/chromium/net/cert/x509_cert_types_unittest.cc
@@ -182,18 +182,21 @@ const struct CertDateTestData {
"20120101123000Z",
true,
{2012, 1, 0, 1, 12, 30, 0}},
+ // test 31st of April
+ {CERT_DATE_FORMAT_GENERALIZED_TIME, "20160431121000Z", false, {0}},
+ // test 31st of February
+ {CERT_DATE_FORMAT_GENERALIZED_TIME, "20160231121000Z", false, {0}},
};
// GTest pretty printer.
void PrintTo(const CertDateTestData& data, std::ostream* os) {
+ base::Time out_time;
+ bool result = base::Time::FromUTCExploded(data.expected_result, &out_time);
*os << " format: " << data.format
<< "; date string: " << base::StringPiece(data.date_string)
- << "; valid: " << data.is_valid
- << "; expected date: "
- << (data.is_valid ?
- base::Time::FromUTCExploded(data.expected_result)
- .ToInternalValue() :
- 0U);
+ << "; valid: " << data.is_valid << "; expected date: "
+ << (data.is_valid ? out_time.ToInternalValue() : 0U)
+ << "; FromUTCExploded conversion result: " << result;
}
class X509CertTypesDateTest : public testing::TestWithParam<CertDateTestData> {
@@ -202,24 +205,30 @@ class X509CertTypesDateTest : public testing::TestWithParam<CertDateTestData> {
void SetUp() override { test_data_ = GetParam(); }
protected:
- CertDateTestData test_data_;
+ CertDateTestData test_data_;
};
TEST_P(X509CertTypesDateTest, Parse) {
base::Time parsed_date;
bool parsed = ParseCertificateDate(
test_data_.date_string, test_data_.format, &parsed_date);
- EXPECT_EQ(test_data_.is_valid, parsed);
+ if (!parsed && test_data_.is_valid &&
+ test_data_.expected_result.year >= 2038 && sizeof(time_t) == 4) {
+ // Some of the valid test data will fail on 32-bit POSIX systems
+ return;
+ }
+
if (!test_data_.is_valid)
return;
- // Convert the expected value to a base::Time(). This ensures that systems
+ // Convert the expected value to a base::Time(). This ensures that
// systems that only support 32-bit times will pass the tests, by ensuring at
- // least that the times have the same truncating behaviour.
+ // least that the times have the same truncating behavior.
// Note: Compared as internal values so that mismatches can be cleanly
- // printed by GTest (eg: without PrintTo overrides).
- EXPECT_EQ(base::Time::FromUTCExploded(test_data_.expected_result)
- .ToInternalValue(),
- parsed_date.ToInternalValue());
+ // printed by GTest (e.g.: without PrintTo overrides).
+ base::Time out_time;
+ EXPECT_TRUE(
+ base::Time::FromUTCExploded(test_data_.expected_result, &out_time));
+ EXPECT_EQ(out_time.ToInternalValue(), parsed_date.ToInternalValue());
}
INSTANTIATE_TEST_CASE_P(,
X509CertTypesDateTest,
diff --git a/chromium/net/cert/x509_certificate.cc b/chromium/net/cert/x509_certificate.cc
index 7f23e7bf1d4..0d6fe95f134 100644
--- a/chromium/net/cert/x509_certificate.cc
+++ b/chromium/net/cert/x509_certificate.cc
@@ -25,6 +25,7 @@
#include "base/strings/string_util.h"
#include "base/synchronization/lock.h"
#include "base/time/time.h"
+#include "base/trace_event/trace_event.h"
#include "crypto/secure_hash.h"
#include "net/base/registry_controlled_domains/registry_controlled_domain.h"
#include "net/base/url_util.h"
@@ -235,6 +236,8 @@ scoped_refptr<X509Certificate> X509Certificate::CreateFromHandle(
// static
scoped_refptr<X509Certificate> X509Certificate::CreateFromDERCertChain(
const std::vector<base::StringPiece>& der_certs) {
+ TRACE_EVENT0("io", "X509Certificate::CreateFromDERCertChain");
+
// TODO(cbentzel): Remove ScopedTracker below once crbug.com/424386 is fixed.
tracked_objects::ScopedTracker tracking_profile(
FROM_HERE_WITH_EXPLICIT_FUNCTION(
diff --git a/chromium/net/cert/x509_certificate.h b/chromium/net/cert/x509_certificate.h
index dde8ae0ad4e..0aff1be6100 100644
--- a/chromium/net/cert/x509_certificate.h
+++ b/chromium/net/cert/x509_certificate.h
@@ -42,8 +42,7 @@ class PickleIterator;
namespace net {
-class CRLSet;
-class CertVerifyResult;
+class X509Certificate;
typedef std::vector<scoped_refptr<X509Certificate> > CertificateList;
@@ -81,6 +80,14 @@ class NET_EXPORT X509Certificate
kPublicKeyTypeECDH
};
+ enum SignatureHashAlgorithm {
+ kSignatureHashAlgorithmMd2,
+ kSignatureHashAlgorithmMd4,
+ kSignatureHashAlgorithmMd5,
+ kSignatureHashAlgorithmSha1,
+ kSignatureHashAlgorithmOther,
+ };
+
enum Format {
// The data contains a single DER-encoded certificate, or a PEM-encoded
// DER certificate with the PEM encoding block name of "CERTIFICATE".
@@ -146,20 +153,8 @@ class NET_EXPORT X509Certificate
size_t length);
#if defined(USE_NSS_CERTS)
- // Create an X509Certificate from the DER-encoded representation.
- // |nickname| can be NULL if an auto-generated nickname is desired.
- // Returns NULL on failure.
- //
- // This function differs from CreateFromBytes in that it takes a
- // nickname that will be used when the certificate is imported into PKCS#11.
- static scoped_refptr<X509Certificate> CreateFromBytesWithNickname(
- const char* data,
- size_t length,
- const char* nickname);
-
// The default nickname of the certificate, based on the certificate type
- // passed in. If this object was created using CreateFromBytesWithNickname,
- // then this will return the nickname specified upon creation.
+ // passed in.
std::string GetDefaultNickname(CertType type) const;
#endif
@@ -328,6 +323,15 @@ class NET_EXPORT X509Certificate
size_t* size_bits,
PublicKeyType* type);
+ // Returns the digest algorithm used in |cert_handle|'s signature.
+ // If the digest algorithm cannot be determined, or if it is not one
+ // of the explicitly enumerated values, kSignatureHashAlgorithmOther
+ // will be returned.
+ // NOTE: No validation of the signature is performed, and thus invalid
+ // signatures may result in seemingly meaningful values.
+ static SignatureHashAlgorithm GetSignatureHashAlgorithm(
+ OSCertHandle cert_handle);
+
// Returns the OSCertHandle of this object. Because of caching, this may
// differ from the OSCertHandle originally supplied during initialization.
// Note: On Windows, CryptoAPI may return unexpected results if this handle
@@ -462,14 +466,6 @@ class NET_EXPORT X509Certificate
// that may be needed for chain building.
OSCertHandles intermediate_ca_certs_;
-#if defined(USE_NSS_CERTS)
- // This stores any default nickname that has been set on the certificate
- // at creation time with CreateFromBytesWithNickname.
- // If this is empty, then GetDefaultNickname will return a generated name
- // based on the type of the certificate.
- std::string default_nickname_;
-#endif
-
DISALLOW_COPY_AND_ASSIGN(X509Certificate);
};
diff --git a/chromium/net/cert/x509_certificate_ios.cc b/chromium/net/cert/x509_certificate_ios.cc
index 737970768fb..18ce828df72 100644
--- a/chromium/net/cert/x509_certificate_ios.cc
+++ b/chromium/net/cert/x509_certificate_ios.cc
@@ -358,6 +358,29 @@ void X509Certificate::GetPublicKeyInfo(OSCertHandle os_cert,
*size_bits = EVP_PKEY_bits(key);
}
+// static
+X509Certificate::SignatureHashAlgorithm
+X509Certificate::GetSignatureHashAlgorithm(OSCertHandle cert_handle) {
+ bssl::UniquePtr<X509> cert = OSCertHandleToOpenSSL(cert_handle);
+ if (!cert)
+ return kSignatureHashAlgorithmOther;
+
+ // TODO(eroman): This duplicates code with x509_certificate_openssl.cc
+ int sig_alg = OBJ_obj2nid(cert->sig_alg->algorithm);
+ if (sig_alg == NID_md2WithRSAEncryption)
+ return kSignatureHashAlgorithmMd2;
+ if (sig_alg == NID_md4WithRSAEncryption)
+ return kSignatureHashAlgorithmMd4;
+ if (sig_alg == NID_md5WithRSAEncryption || sig_alg == NID_md5WithRSA)
+ return kSignatureHashAlgorithmMd5;
+ if (sig_alg == NID_sha1WithRSAEncryption || sig_alg == NID_dsaWithSHA ||
+ sig_alg == NID_dsaWithSHA1 || sig_alg == NID_dsaWithSHA1_2 ||
+ sig_alg == NID_sha1WithRSA || sig_alg == NID_ecdsa_with_SHA1) {
+ return kSignatureHashAlgorithmSha1;
+ }
+ return kSignatureHashAlgorithmOther;
+}
+
bool X509Certificate::SupportsSSLClientAuth() const {
return false;
}
diff --git a/chromium/net/cert/x509_certificate_known_roots_win.h b/chromium/net/cert/x509_certificate_known_roots_win.h
index eea3a6875ff..43ce812de9e 100644
--- a/chromium/net/cert/x509_certificate_known_roots_win.h
+++ b/chromium/net/cert/x509_certificate_known_roots_win.h
@@ -16,7 +16,7 @@
//
// Note that these *are not* trust anchors for Chromium. They are only used to
// distinguish `real' root CAs from roots that were user-installed.
-static uint8_t kKnownRootCertSHA256Hashes[][32] = {
+static const uint8_t kKnownRootCertSHA256Hashes[][32] = {
// C=US, O=Network Solutions L.L.C., CN=Network Solutions Certificate
// Authority
{0x00, 0x16, 0x86, 0xCD, 0x18, 0x1F, 0x83, 0xA1, 0xB1, 0x21, 0x7D, 0x30,
diff --git a/chromium/net/cert/x509_certificate_mac.cc b/chromium/net/cert/x509_certificate_mac.cc
index 8e6ecf9fb42..6283d3658d2 100644
--- a/chromium/net/cert/x509_certificate_mac.cc
+++ b/chromium/net/cert/x509_certificate_mac.cc
@@ -518,6 +518,43 @@ void X509Certificate::GetPublicKeyInfo(OSCertHandle cert_handle,
}
}
+X509Certificate::SignatureHashAlgorithm
+X509Certificate::GetSignatureHashAlgorithm(OSCertHandle cert_handle) {
+ x509_util::CSSMCachedCertificate cached_cert;
+ OSStatus status = cached_cert.Init(cert_handle);
+ if (status)
+ return kSignatureHashAlgorithmOther;
+
+ x509_util::CSSMFieldValue signature_field;
+ status =
+ cached_cert.GetField(&CSSMOID_X509V1SignatureAlgorithm, &signature_field);
+ if (status || !signature_field.field())
+ return kSignatureHashAlgorithmOther;
+
+ const CSSM_X509_ALGORITHM_IDENTIFIER* sig_algorithm =
+ signature_field.GetAs<CSSM_X509_ALGORITHM_IDENTIFIER>();
+ if (!sig_algorithm)
+ return kSignatureHashAlgorithmOther;
+
+ const CSSM_OID* alg_oid = &sig_algorithm->algorithm;
+ if (CSSMOIDEqual(alg_oid, &CSSMOID_MD2WithRSA))
+ return kSignatureHashAlgorithmMd2;
+ if (CSSMOIDEqual(alg_oid, &CSSMOID_MD4WithRSA))
+ return kSignatureHashAlgorithmMd4;
+ if (CSSMOIDEqual(alg_oid, &CSSMOID_MD5WithRSA))
+ return kSignatureHashAlgorithmMd5;
+ if (CSSMOIDEqual(alg_oid, &CSSMOID_SHA1WithRSA) ||
+ CSSMOIDEqual(alg_oid, &CSSMOID_SHA1WithRSA_OIW) ||
+ CSSMOIDEqual(alg_oid, &CSSMOID_SHA1WithDSA) ||
+ CSSMOIDEqual(alg_oid, &CSSMOID_SHA1WithDSA_CMS) ||
+ CSSMOIDEqual(alg_oid, &CSSMOID_SHA1WithDSA_JDK) ||
+ CSSMOIDEqual(alg_oid, &CSSMOID_ECDSA_WithSHA1)) {
+ return kSignatureHashAlgorithmSha1;
+ }
+
+ return kSignatureHashAlgorithmOther;
+}
+
// static
bool X509Certificate::IsSelfSigned(OSCertHandle cert_handle) {
x509_util::CSSMCachedCertificate cached_cert;
diff --git a/chromium/net/cert/x509_certificate_net_log_param.h b/chromium/net/cert/x509_certificate_net_log_param.h
index 01b46f95b15..a6721ab4782 100644
--- a/chromium/net/cert/x509_certificate_net_log_param.h
+++ b/chromium/net/cert/x509_certificate_net_log_param.h
@@ -2,8 +2,8 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#ifndef NET_BASE_X509_CERT_NET_LOG_PARAM_H_
-#define NET_BASE_X509_CERT_NET_LOG_PARAM_H_
+#ifndef NET_CERT_X509_CERTIFICATE_NET_LOG_PARAM_H_
+#define NET_CERT_X509_CERTIFICATE_NET_LOG_PARAM_H_
#include <memory>
@@ -23,4 +23,4 @@ std::unique_ptr<base::Value> NetLogX509CertificateCallback(
} // namespace net
-#endif // NET_BASE_X509_CERT_NET_LOG_PARAM_H_
+#endif // NET_CERT_X509_CERTIFICATE_NET_LOG_PARAM_H_
diff --git a/chromium/net/cert/x509_certificate_nss.cc b/chromium/net/cert/x509_certificate_nss.cc
index abb6f20462e..2f2f9772662 100644
--- a/chromium/net/cert/x509_certificate_nss.cc
+++ b/chromium/net/cert/x509_certificate_nss.cc
@@ -36,31 +36,7 @@ void X509Certificate::Initialize() {
serial_number_ = x509_util::ParseSerialNumber(cert_handle_);
}
-// static
-scoped_refptr<X509Certificate> X509Certificate::CreateFromBytesWithNickname(
- const char* data,
- size_t length,
- const char* nickname) {
- OSCertHandle cert_handle = CreateOSCertHandleFromBytesWithNickname(data,
- length,
- nickname);
- if (!cert_handle)
- return NULL;
-
- scoped_refptr<X509Certificate> cert =
- CreateFromHandle(cert_handle, OSCertHandles());
- FreeOSCertHandle(cert_handle);
-
- if (nickname)
- cert->default_nickname_ = nickname;
-
- return cert;
-}
-
std::string X509Certificate::GetDefaultNickname(CertType type) const {
- if (!default_nickname_.empty())
- return default_nickname_;
-
std::string result;
if (type == USER_CERT && cert_handle_->slot) {
// Find the private key for this certificate and see if it has a
@@ -263,6 +239,28 @@ void X509Certificate::GetPublicKeyInfo(OSCertHandle cert_handle,
}
// static
+X509Certificate::SignatureHashAlgorithm
+X509Certificate::GetSignatureHashAlgorithm(OSCertHandle cert_handle) {
+ SECAlgorithmID& signature = cert_handle->signature;
+ SECOidTag oid_tag = SECOID_FindOIDTag(&signature.algorithm);
+ switch (oid_tag) {
+ case SEC_OID_PKCS1_MD5_WITH_RSA_ENCRYPTION:
+ return kSignatureHashAlgorithmMd5;
+ case SEC_OID_PKCS1_MD2_WITH_RSA_ENCRYPTION:
+ return kSignatureHashAlgorithmMd2;
+ case SEC_OID_PKCS1_MD4_WITH_RSA_ENCRYPTION:
+ return kSignatureHashAlgorithmMd4;
+ case SEC_OID_PKCS1_SHA1_WITH_RSA_ENCRYPTION:
+ case SEC_OID_ISO_SHA1_WITH_RSA_SIGNATURE:
+ case SEC_OID_ANSIX9_DSA_SIGNATURE_WITH_SHA1_DIGEST:
+ case SEC_OID_ANSIX962_ECDSA_SHA1_SIGNATURE:
+ return kSignatureHashAlgorithmSha1;
+ default:
+ return kSignatureHashAlgorithmOther;
+ }
+}
+
+// static
bool X509Certificate::IsSelfSigned(OSCertHandle cert_handle) {
crypto::ScopedSECKEYPublicKey public_key(CERT_ExtractPublicKey(cert_handle));
if (!public_key.get())
diff --git a/chromium/net/cert/x509_certificate_openssl.cc b/chromium/net/cert/x509_certificate_openssl.cc
index 30d9598a50a..730eef0d6ac 100644
--- a/chromium/net/cert/x509_certificate_openssl.cc
+++ b/chromium/net/cert/x509_certificate_openssl.cc
@@ -377,6 +377,24 @@ void X509Certificate::GetPublicKeyInfo(OSCertHandle cert_handle,
}
}
+// static
+X509Certificate::SignatureHashAlgorithm
+X509Certificate::GetSignatureHashAlgorithm(OSCertHandle cert_handle) {
+ int sig_alg = OBJ_obj2nid(cert_handle->sig_alg->algorithm);
+ if (sig_alg == NID_md2WithRSAEncryption)
+ return kSignatureHashAlgorithmMd2;
+ if (sig_alg == NID_md4WithRSAEncryption)
+ return kSignatureHashAlgorithmMd4;
+ if (sig_alg == NID_md5WithRSAEncryption || sig_alg == NID_md5WithRSA)
+ return kSignatureHashAlgorithmMd5;
+ if (sig_alg == NID_sha1WithRSAEncryption || sig_alg == NID_dsaWithSHA ||
+ sig_alg == NID_dsaWithSHA1 || sig_alg == NID_dsaWithSHA1_2 ||
+ sig_alg == NID_sha1WithRSA || sig_alg == NID_ecdsa_with_SHA1) {
+ return kSignatureHashAlgorithmSha1;
+ }
+ return kSignatureHashAlgorithmOther;
+}
+
bool X509Certificate::IsIssuedByEncoded(
const std::vector<std::string>& valid_issuers) {
if (valid_issuers.empty())
diff --git a/chromium/net/cert/x509_certificate_win.cc b/chromium/net/cert/x509_certificate_win.cc
index c67011e06b9..ef3d040e5df 100644
--- a/chromium/net/cert/x509_certificate_win.cc
+++ b/chromium/net/cert/x509_certificate_win.cc
@@ -421,6 +421,33 @@ void X509Certificate::GetPublicKeyInfo(OSCertHandle cert_handle,
}
}
+X509Certificate::SignatureHashAlgorithm
+X509Certificate::GetSignatureHashAlgorithm(OSCertHandle cert_handle) {
+ const char* algorithm = cert_handle->pCertInfo->SignatureAlgorithm.pszObjId;
+ if (strcmp(algorithm, szOID_RSA_MD5RSA) == 0) {
+ // md5WithRSAEncryption: 1.2.840.113549.1.1.4
+ return kSignatureHashAlgorithmMd5;
+ }
+ if (strcmp(algorithm, szOID_RSA_MD2RSA) == 0) {
+ // md2WithRSAEncryption: 1.2.840.113549.1.1.2
+ return kSignatureHashAlgorithmMd2;
+ }
+ if (strcmp(algorithm, szOID_RSA_MD4RSA) == 0) {
+ // md4WithRSAEncryption: 1.2.840.113549.1.1.3
+ return kSignatureHashAlgorithmMd4;
+ }
+ if (strcmp(algorithm, szOID_RSA_SHA1RSA) == 0 ||
+ strcmp(algorithm, szOID_X957_SHA1DSA) == 0 ||
+ strcmp(algorithm, szOID_ECDSA_SHA1) == 0) {
+ // sha1WithRSAEncryption: 1.2.840.113549.1.1.5
+ // id-dsa-with-sha1: 1.2.840.10040.4.3
+ // ecdsa-with-SHA1: 1.2.840.10045.4.1
+ return kSignatureHashAlgorithmSha1;
+ }
+
+ return kSignatureHashAlgorithmOther;
+}
+
bool X509Certificate::IsIssuedByEncoded(
const std::vector<std::string>& valid_issuers) {
diff --git a/chromium/net/cert/x509_util.cc b/chromium/net/cert/x509_util.cc
index 35913c19d2b..a5d583d0eb1 100644
--- a/chromium/net/cert/x509_util.cc
+++ b/chromium/net/cert/x509_util.cc
@@ -112,7 +112,7 @@ bool CreateKeyAndSelfSignedCert(const std::string& subject,
not_valid_after,
der_cert);
if (success)
- key->reset(new_key.release());
+ *key = std::move(new_key);
return success;
}
diff --git a/chromium/net/cert/x509_util.h b/chromium/net/cert/x509_util.h
index 07f4e21b1d3..e29219d3eca 100644
--- a/chromium/net/cert/x509_util.h
+++ b/chromium/net/cert/x509_util.h
@@ -17,7 +17,6 @@
#include "net/base/net_export.h"
namespace crypto {
-class ECPrivateKey;
class RSAPrivateKey;
}
diff --git a/chromium/net/cert_net/cert_net_fetcher_impl.cc b/chromium/net/cert_net/cert_net_fetcher_impl.cc
index 01fca4f796a..50cc66c4592 100644
--- a/chromium/net/cert_net/cert_net_fetcher_impl.cc
+++ b/chromium/net/cert_net/cert_net_fetcher_impl.cc
@@ -1,6 +1,60 @@
// Copyright 2015 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.
+//
+// Overview
+//
+// The main entry point is CertNetFetcherImpl. This is an implementation of
+// CertNetFetcher that provides a service for fetching network requests.
+//
+// The interface for CertNetFetcher is synchronous, however allows
+// overlapping requests. When starting a request CertNetFetcherImpl
+// returns a CertNetFetcher::Request (CertNetFetcherImpl) that the
+// caller can use to cancel the fetch, or wait for it to complete
+// (blocking).
+//
+// The CertNetFetcherImpl is shared between a network thread and a
+// caller thread that waits for fetches to happen on the network thread.
+//
+// The classes are mainly organized based on their thread affinity:
+//
+// ---------------
+// Straddles caller thread and network thread
+// ---------------
+//
+// CertNetFetcherImpl (implements CertNetFetcher)
+// * Main entry point. Must be created and shutdown from the network thread.
+// * Provides a service to start/cancel/wait for URL fetches, to be
+// used on the caller thread.
+// * Returns callers a CertNetFetcher::Request as a handle
+// * Requests can run in parallel, however will block the current thread when
+// reading results.
+// * Posts tasks to network thread to coordinate actual work
+//
+// RequestCore
+// * Reference-counted bridge between CertNetFetcherRequestImpl and the
+// dependencies on the network thread
+// * Holds the result of the request, a WaitableEvent for signaling
+// completion, and pointers for canceling work on network thread.
+//
+// ---------------
+// Lives on caller thread
+// ---------------
+//
+// CertNetFetcherRequestImpl (implements CertNetFetcher::Request)
+// * Wrapper for cancelling events, or waiting for a request to complete
+// * Waits on a WaitableEvent to complete requests.
+//
+// ---------------
+// Lives on network thread
+// ---------------
+//
+// AsyncCertNetFetcherImpl
+// * Asyncronous manager for outstanding requests. Handles de-duplication,
+// timeouts, and actual integration with network stack. This is where the
+// majority of the logic lives.
+// * Signals completion of requests through RequestCore's WaitableEvent.
+// * Attaches requests to Jobs for the purpose of de-duplication
#include "net/cert_net/cert_net_fetcher_impl.h"
@@ -8,13 +62,15 @@
#include <utility>
#include "base/callback_helpers.h"
-#include "base/containers/linked_list.h"
#include "base/logging.h"
#include "base/macros.h"
#include "base/memory/ptr_util.h"
#include "base/numerics/safe_math.h"
+#include "base/synchronization/waitable_event.h"
+#include "base/threading/thread_task_runner_handle.h"
#include "base/timer/timer.h"
#include "net/base/load_flags.h"
+#include "net/cert/cert_net_fetcher.h"
#include "net/url_request/redirect_info.h"
#include "net/url_request/url_request_context.h"
@@ -40,6 +96,69 @@ const int kMaxResponseSizeInBytesForAia = 64 * 1024;
// The default timeout in seconds for fetch requests.
const int kTimeoutSeconds = 15;
+class RequestCore;
+struct RequestParams;
+class Job;
+
+struct JobToRequestParamsComparator;
+
+struct JobComparator {
+ bool operator()(const Job* job1, const Job* job2) const;
+};
+
+// Would be a set<unique_ptr> but extraction of owned objects from a set of
+// owned types doesn't come until C++17.
+using JobSet = std::map<Job*, std::unique_ptr<Job>, JobComparator>;
+
+// AsyncCertNetFetcherImpl manages URLRequests in an async fashion on the
+// URLRequestContexts's task runner thread.
+//
+// * Schedules
+// * De-duplicates requests
+// * Handles timeouts
+class AsyncCertNetFetcherImpl {
+ public:
+ // Initializes AsyncCertNetFetcherImpl using the specified URLRequestContext
+ // for issuing requests. |context| must remain valid until Shutdown() is
+ // called or the AsyncCertNetFetcherImpl is destroyed.
+ explicit AsyncCertNetFetcherImpl(URLRequestContext* context);
+
+ // The AsyncCertNetFetcherImpl is expected to be kept alive until all
+ // requests have completed or Shutdown() is called.
+ ~AsyncCertNetFetcherImpl();
+
+ // Starts an asynchronous request to fetch the given URL. On completion
+ // request->OnJobCompleted() will be invoked.
+ void Fetch(std::unique_ptr<RequestParams> request_params,
+ scoped_refptr<RequestCore> request);
+
+ // Cancels outstanding jobs, which stops network requests and signals the
+ // corresponding RequestCores that the requests have completed.
+ void Shutdown();
+
+ private:
+ friend class Job;
+
+ // Finds a job with a matching RequestPararms or returns nullptr if there was
+ // no match.
+ Job* FindJob(const RequestParams& params);
+
+ // Removes |job| from the in progress jobs and transfers ownership to the
+ // caller.
+ std::unique_ptr<Job> RemoveJob(Job* job);
+
+ // The in-progress jobs. This set does not contain the job which is actively
+ // invoking callbacks (OnJobCompleted).
+ JobSet jobs_;
+
+ // Not owned. |context_| must outlive the AsyncCertNetFetcherImpl.
+ URLRequestContext* context_ = nullptr;
+
+ base::ThreadChecker thread_checker_;
+
+ DISALLOW_COPY_AND_ASSIGN(AsyncCertNetFetcherImpl);
+};
+
// Policy for which URLs are allowed to be fetched. This is called both for the
// initial URL and for each redirect. Returns OK on success or a net error
// code on failure.
@@ -74,46 +193,84 @@ enum HttpMethod {
HTTP_METHOD_POST,
};
-} // namespace
-
-// CertNetFetcherImpl::RequestImpl tracks an outstanding call to Fetch().
-class CertNetFetcherImpl::RequestImpl : public CertNetFetcher::Request,
- public base::LinkNode<RequestImpl> {
+// RequestCore tracks an outstanding call to Fetch(). It is
+// reference-counted for ease of sharing between threads.
+class RequestCore : public base::RefCountedThreadSafe<RequestCore> {
public:
- RequestImpl(Job* job, const FetchCallback& callback)
- : callback_(callback), job_(job) {
- DCHECK(!callback.is_null());
- }
-
- // Deletion cancels the outstanding request.
- ~RequestImpl() override;
-
- void OnJobCancelled(Job* job) {
- DCHECK_EQ(job_, job);
- job_ = nullptr;
- callback_.Reset();
+ explicit RequestCore(scoped_refptr<base::SingleThreadTaskRunner> task_runner)
+ : completion_event_(base::WaitableEvent::ResetPolicy::MANUAL,
+ base::WaitableEvent::InitialState::NOT_SIGNALED),
+ task_runner_(std::move(task_runner)) {}
+
+ void AttachedToJob(Job* job) {
+ DCHECK(task_runner_->RunsTasksOnCurrentThread());
+ DCHECK(!job_);
+ // Requests should not be attached to jobs after they have been signalled
+ // with a cancellation error (which happens via either Cancel() or
+ // SignalImmediateError()).
+ DCHECK_NE(error_, ERR_ABORTED);
+ job_ = job;
}
void OnJobCompleted(Job* job,
Error error,
const std::vector<uint8_t>& response_body) {
+ DCHECK(task_runner_->RunsTasksOnCurrentThread());
+
DCHECK_EQ(job_, job);
job_ = nullptr;
- base::ResetAndReturn(&callback_).Run(error, response_body);
+
+ error_ = error;
+ bytes_ = response_body;
+ completion_event_.Signal();
+ }
+
+ // Detaches this request from its job (if it is attached to any) and
+ // signals completion with ERR_ABORTED. Can be called from any thread.
+ void CancelJob();
+
+ // Can be used to signal that an error was encountered before the request was
+ // attached to a job. Can be called from any thread.
+ void SignalImmediateError();
+
+ // Should only be called once.
+ void WaitForResult(Error* error, std::vector<uint8_t>* bytes) {
+ DCHECK(!task_runner_->RunsTasksOnCurrentThread());
+
+ completion_event_.Wait();
+ *bytes = std::move(bytes_);
+ *error = error_;
+
+ error_ = ERR_UNEXPECTED;
}
private:
- // The callback to invoke when the request has completed.
- FetchCallback callback_;
+ friend class base::RefCountedThreadSafe<RequestCore>;
+
+ ~RequestCore() {
+ // Requests should have been cancelled prior to destruction.
+ DCHECK(!job_);
+ }
// A non-owned pointer to the job that is executing the request.
- Job* job_;
+ Job* job_ = nullptr;
- private:
- DISALLOW_COPY_AND_ASSIGN(RequestImpl);
+ // May be written to from network thread, or from the caller thread only when
+ // there is no work that will be done on the network thread (e.g. when the
+ // network thread has been shutdown before the request begins). See comment in
+ // SignalImmediateError.
+ Error error_;
+ std::vector<uint8_t> bytes_;
+
+ // Indicates when |error_| and |bytes_| have been written to.
+ base::WaitableEvent completion_event_;
+
+ scoped_refptr<base::SingleThreadTaskRunner> task_runner_;
+
+ DISALLOW_COPY_AND_ASSIGN(RequestCore);
};
-struct CertNetFetcherImpl::RequestParams {
+struct RequestParams {
RequestParams();
bool operator<(const RequestParams& other) const;
@@ -131,48 +288,43 @@ struct CertNetFetcherImpl::RequestParams {
DISALLOW_COPY_AND_ASSIGN(RequestParams);
};
-CertNetFetcherImpl::RequestParams::RequestParams()
- : http_method(HTTP_METHOD_GET), max_response_bytes(0) {
-}
+RequestParams::RequestParams()
+ : http_method(HTTP_METHOD_GET), max_response_bytes(0) {}
-bool CertNetFetcherImpl::RequestParams::operator<(
- const RequestParams& other) const {
+bool RequestParams::operator<(const RequestParams& other) const {
return std::tie(url, http_method, max_response_bytes, timeout) <
std::tie(other.url, other.http_method, other.max_response_bytes,
other.timeout);
}
-// CertNetFetcherImpl::Job tracks an outstanding URLRequest as well as all of
-// the pending requests for it.
-class CertNetFetcherImpl::Job : public URLRequest::Delegate {
+// Job tracks an outstanding URLRequest as well as all of the pending requests
+// for it.
+class Job : public URLRequest::Delegate {
public:
Job(std::unique_ptr<RequestParams> request_params,
- CertNetFetcherImpl* parent);
+ AsyncCertNetFetcherImpl* parent);
~Job() override;
- // Cancels the job and all requests attached to it. No callbacks will be
- // invoked following cancellation.
- void Cancel();
-
const RequestParams& request_params() const { return *request_params_; }
- // Create a request and attaches it to the job. When the job completes it will
- // notify the request of completion through OnJobCompleted. Note that the Job
- // does NOT own the request.
- std::unique_ptr<Request> CreateRequest(const FetchCallback& callback);
+ // Creates a request and attaches it to the job. When the job completes it
+ // will notify the request of completion through OnJobCompleted.
+ void AttachRequest(scoped_refptr<RequestCore> request);
// Removes |request| from the job.
- void DetachRequest(RequestImpl* request);
+ void DetachRequest(RequestCore* request);
- // Creates and starts a URLRequest for the job. After the request has
+ // Creates and starts a URLRequest for the job. After the URLRequest has
// completed, OnJobCompleted() will be invoked and all the registered requests
// notified of completion.
void StartURLRequest(URLRequestContext* context);
- private:
- // The pointers in RequestList are not owned by the Job.
- using RequestList = base::LinkedList<RequestImpl>;
+ // Cancels the request with an ERR_ABORTED error and invokes
+ // RequestCore::OnJobCompleted() to notify the registered requests of the
+ // cancellation. The job is *not* removed from the AsyncCertNetFetcherImpl.
+ void Cancel();
+ private:
// Implementation of URLRequest::Delegate
void OnReceivedRedirect(URLRequest* request,
const RedirectInfo& redirect_info,
@@ -199,12 +351,16 @@ class CertNetFetcherImpl::Job : public URLRequest::Delegate {
// method is called, the |response_body_| variable have been assigned.
void OnJobCompleted(Error error);
+ // Calls r->OnJobCompleted() for each RequestCore |r| currently attached
+ // to this job, and then clears |requests_|.
+ void CompleteAndClearRequests(Error error);
+
// Cancels a request with a specified error code and calls
// OnUrlRequestCompleted().
void FailRequest(Error error);
// The requests attached to this job.
- RequestList requests_;
+ std::vector<scoped_refptr<RequestCore>> requests_;
// The input parameters for starting a URLRequest.
std::unique_ptr<RequestParams> request_params_;
@@ -219,69 +375,75 @@ class CertNetFetcherImpl::Job : public URLRequest::Delegate {
// also used for notifying a failure to start the URLRequest.
base::OneShotTimer timer_;
- // Non-owned pointer to the CertNetFetcherImpl that created this job.
- CertNetFetcherImpl* parent_;
+ // Non-owned pointer to the AsyncCertNetFetcherImpl that created this job.
+ AsyncCertNetFetcherImpl* parent_;
DISALLOW_COPY_AND_ASSIGN(Job);
};
-CertNetFetcherImpl::RequestImpl::~RequestImpl() {
- if (job_)
- job_->DetachRequest(this);
-}
+void RequestCore::CancelJob() {
+ if (!task_runner_->RunsTasksOnCurrentThread()) {
+ task_runner_->PostTask(FROM_HERE,
+ base::Bind(&RequestCore::CancelJob, this));
+ return;
+ }
-CertNetFetcherImpl::Job::Job(std::unique_ptr<RequestParams> request_params,
- CertNetFetcherImpl* parent)
- : request_params_(std::move(request_params)),
- parent_(parent) {}
+ if (job_) {
+ auto* job = job_;
+ job_ = nullptr;
+ job->DetachRequest(this);
+ }
-CertNetFetcherImpl::Job::~Job() {
- Cancel();
+ SignalImmediateError();
}
-void CertNetFetcherImpl::Job::Cancel() {
- parent_ = nullptr;
+void RequestCore::SignalImmediateError() {
+ // These data members are normally only written on the network thread, but it
+ // is safe to write here from either thread. This is because
+ // SignalImmediateError is only to be called before this request is attached
+ // to a job. In particular, if called from the caller thread, no work will be
+ // done on the network thread for this request, so these variables will only
+ // be written and read on the caller thread. If called from the network
+ // thread, they will only be written to on the network thread and will not be
+ // read on the caller thread until |completion_event_| is signalled (after
+ // which it will be not be written on the network thread again).
+ DCHECK(!job_);
+ error_ = ERR_ABORTED;
+ bytes_.clear();
+ completion_event_.Signal();
+}
- // Notify each request of cancellation and remove it from the list.
- for (base::LinkNode<RequestImpl>* current = requests_.head();
- current != requests_.end();) {
- base::LinkNode<RequestImpl>* next = current->next();
- current->value()->OnJobCancelled(this);
- current->RemoveFromList();
- current = next;
- }
+Job::Job(std::unique_ptr<RequestParams> request_params,
+ AsyncCertNetFetcherImpl* parent)
+ : request_params_(std::move(request_params)), parent_(parent) {}
+Job::~Job() {
DCHECK(requests_.empty());
-
Stop();
}
-std::unique_ptr<CertNetFetcher::Request> CertNetFetcherImpl::Job::CreateRequest(
- const FetchCallback& callback) {
- std::unique_ptr<RequestImpl> request(new RequestImpl(this, callback));
- requests_.Append(request.get());
- return std::move(request);
+void Job::AttachRequest(scoped_refptr<RequestCore> request) {
+ request->AttachedToJob(this);
+ requests_.push_back(std::move(request));
}
-void CertNetFetcherImpl::Job::DetachRequest(RequestImpl* request) {
+void Job::DetachRequest(RequestCore* request) {
std::unique_ptr<Job> delete_this;
- request->RemoveFromList();
+ auto it = std::find(requests_.begin(), requests_.end(), request);
+ DCHECK(it != requests_.end());
+ requests_.erase(it);
// If there are no longer any requests attached to the job then
// cancel and delete it.
- if (requests_.empty() && !parent_->IsCurrentlyCompletingJob(this))
+ if (requests_.empty())
delete_this = parent_->RemoveJob(this);
}
-void CertNetFetcherImpl::Job::StartURLRequest(URLRequestContext* context) {
+void Job::StartURLRequest(URLRequestContext* context) {
Error error = CanFetchUrl(request_params_->url);
if (error != OK) {
- // The CertNetFetcher's API contract is that requests always complete
- // asynchronously. Use the timer class so the task is easily cancelled.
- timer_.Start(
- FROM_HERE, base::TimeDelta(),
- base::Bind(&Job::OnJobCompleted, base::Unretained(this), error));
+ OnJobCompleted(error);
return;
}
@@ -302,10 +464,16 @@ void CertNetFetcherImpl::Job::StartURLRequest(URLRequestContext* context) {
base::Bind(&Job::FailRequest, base::Unretained(this), ERR_TIMED_OUT));
}
-void CertNetFetcherImpl::Job::OnReceivedRedirect(
- URLRequest* request,
- const RedirectInfo& redirect_info,
- bool* defer_redirect) {
+void Job::Cancel() {
+ // Stop the timer and clear the URLRequest.
+ Stop();
+ // Signal attached requests that they've been completed.
+ CompleteAndClearRequests(static_cast<Error>(ERR_ABORTED));
+}
+
+void Job::OnReceivedRedirect(URLRequest* request,
+ const RedirectInfo& redirect_info,
+ bool* defer_redirect) {
DCHECK_EQ(url_request_.get(), request);
// Ensure that the new URL matches the policy.
@@ -316,8 +484,7 @@ void CertNetFetcherImpl::Job::OnReceivedRedirect(
}
}
-void CertNetFetcherImpl::Job::OnResponseStarted(URLRequest* request,
- int net_error) {
+void Job::OnResponseStarted(URLRequest* request, int net_error) {
DCHECK_EQ(url_request_.get(), request);
DCHECK_NE(ERR_IO_PENDING, net_error);
@@ -335,8 +502,7 @@ void CertNetFetcherImpl::Job::OnResponseStarted(URLRequest* request,
ReadBody(request);
}
-void CertNetFetcherImpl::Job::OnReadCompleted(URLRequest* request,
- int bytes_read) {
+void Job::OnReadCompleted(URLRequest* request, int bytes_read) {
DCHECK_EQ(url_request_.get(), request);
DCHECK_NE(ERR_IO_PENDING, bytes_read);
@@ -345,12 +511,12 @@ void CertNetFetcherImpl::Job::OnReadCompleted(URLRequest* request,
ReadBody(request);
}
-void CertNetFetcherImpl::Job::Stop() {
+void Job::Stop() {
timer_.Stop();
url_request_.reset();
}
-void CertNetFetcherImpl::Job::ReadBody(URLRequest* request) {
+void Job::ReadBody(URLRequest* request) {
// Read as many bytes as are available synchronously.
int num_bytes = 0;
while (num_bytes >= 0) {
@@ -364,8 +530,7 @@ void CertNetFetcherImpl::Job::ReadBody(URLRequest* request) {
OnUrlRequestCompleted(num_bytes);
}
-bool CertNetFetcherImpl::Job::ConsumeBytesRead(URLRequest* request,
- int num_bytes) {
+bool Job::ConsumeBytesRead(URLRequest* request, int num_bytes) {
DCHECK_NE(ERR_IO_PENDING, num_bytes);
if (num_bytes <= 0) {
// Error while reading, or EOF.
@@ -386,135 +551,88 @@ bool CertNetFetcherImpl::Job::ConsumeBytesRead(URLRequest* request,
return true;
}
-void CertNetFetcherImpl::Job::OnUrlRequestCompleted(int net_error) {
+void Job::OnUrlRequestCompleted(int net_error) {
DCHECK_NE(ERR_IO_PENDING, net_error);
Error result = static_cast<Error>(net_error);
OnJobCompleted(result);
}
-void CertNetFetcherImpl::Job::OnJobCompleted(Error error) {
+void Job::OnJobCompleted(Error error) {
DCHECK_NE(ERR_IO_PENDING, error);
// Stop the timer and clear the URLRequest.
Stop();
- // Invoking the callbacks is subtle as state may be mutated while iterating
- // through the callbacks:
- //
- // * The parent CertNetFetcherImpl may be deleted
- // * Requests in this job may be cancelled
-
std::unique_ptr<Job> delete_this = parent_->RemoveJob(this);
- parent_->SetCurrentlyCompletingJob(this);
+ CompleteAndClearRequests(error);
+}
- while (!requests_.empty()) {
- base::LinkNode<RequestImpl>* request = requests_.head();
- request->RemoveFromList();
- request->value()->OnJobCompleted(this, error, response_body_);
+void Job::CompleteAndClearRequests(Error error) {
+ for (const auto& request : requests_) {
+ request->OnJobCompleted(this, error, response_body_);
}
- if (parent_)
- parent_->ClearCurrentlyCompletingJob(this);
+ requests_.clear();
}
-void CertNetFetcherImpl::Job::FailRequest(Error error) {
+void Job::FailRequest(Error error) {
DCHECK_NE(ERR_IO_PENDING, error);
int result = url_request_->CancelWithError(error);
OnUrlRequestCompleted(result);
}
-CertNetFetcherImpl::CertNetFetcherImpl(URLRequestContext* context)
- : currently_completing_job_(nullptr), context_(context) {
+AsyncCertNetFetcherImpl::AsyncCertNetFetcherImpl(URLRequestContext* context)
+ : context_(context) {
+ // Allow creation to happen from another thread.
+ thread_checker_.DetachFromThread();
}
-CertNetFetcherImpl::~CertNetFetcherImpl() {
+AsyncCertNetFetcherImpl::~AsyncCertNetFetcherImpl() {
+ DCHECK(thread_checker_.CalledOnValidThread());
jobs_.clear();
-
- // The CertNetFetcherImpl was destroyed in a FetchCallback. Detach all
- // remaining requests from the job so no further callbacks are called.
- if (currently_completing_job_)
- currently_completing_job_->Cancel();
-}
-
-std::unique_ptr<CertNetFetcher::Request> CertNetFetcherImpl::FetchCaIssuers(
- const GURL& url,
- int timeout_milliseconds,
- int max_response_bytes,
- const FetchCallback& callback) {
- std::unique_ptr<RequestParams> request_params(new RequestParams);
-
- request_params->url = url;
- request_params->http_method = HTTP_METHOD_GET;
- request_params->timeout = GetTimeout(timeout_milliseconds);
- request_params->max_response_bytes =
- GetMaxResponseBytes(max_response_bytes, kMaxResponseSizeInBytesForAia);
-
- return Fetch(std::move(request_params), callback);
-}
-
-std::unique_ptr<CertNetFetcher::Request> CertNetFetcherImpl::FetchCrl(
- const GURL& url,
- int timeout_milliseconds,
- int max_response_bytes,
- const FetchCallback& callback) {
- std::unique_ptr<RequestParams> request_params(new RequestParams);
-
- request_params->url = url;
- request_params->http_method = HTTP_METHOD_GET;
- request_params->timeout = GetTimeout(timeout_milliseconds);
- request_params->max_response_bytes =
- GetMaxResponseBytes(max_response_bytes, kMaxResponseSizeInBytesForCrl);
-
- return Fetch(std::move(request_params), callback);
-}
-
-std::unique_ptr<CertNetFetcher::Request> CertNetFetcherImpl::FetchOcsp(
- const GURL& url,
- int timeout_milliseconds,
- int max_response_bytes,
- const FetchCallback& callback) {
- std::unique_ptr<RequestParams> request_params(new RequestParams);
-
- request_params->url = url;
- request_params->http_method = HTTP_METHOD_GET;
- request_params->timeout = GetTimeout(timeout_milliseconds);
- request_params->max_response_bytes =
- GetMaxResponseBytes(max_response_bytes, kMaxResponseSizeInBytesForAia);
-
- return Fetch(std::move(request_params), callback);
}
-bool CertNetFetcherImpl::JobComparator::operator()(const Job* job1,
- const Job* job2) const {
+bool JobComparator::operator()(const Job* job1, const Job* job2) const {
return job1->request_params() < job2->request_params();
}
-std::unique_ptr<CertNetFetcher::Request> CertNetFetcherImpl::Fetch(
+void AsyncCertNetFetcherImpl::Fetch(
std::unique_ptr<RequestParams> request_params,
- const FetchCallback& callback) {
+ scoped_refptr<RequestCore> request) {
DCHECK(thread_checker_.CalledOnValidThread());
// If there is an in-progress job that matches the request parameters use it.
// Otherwise start a new job.
Job* job = FindJob(*request_params);
-
- if (!job) {
- job = new Job(std::move(request_params), this);
- jobs_[job] = base::WrapUnique(job);
- job->StartURLRequest(context_);
+ if (job) {
+ job->AttachRequest(std::move(request));
+ return;
}
- return job->CreateRequest(callback);
+ job = new Job(std::move(request_params), this);
+ jobs_[job] = base::WrapUnique(job);
+ // Attach the request before calling StartURLRequest; this ensures that the
+ // request will get signalled if StartURLRequest completes the job
+ // synchronously.
+ job->AttachRequest(std::move(request));
+ job->StartURLRequest(context_);
}
-struct CertNetFetcherImpl::JobToRequestParamsComparator {
- bool operator()(const CertNetFetcherImpl::JobSet::value_type& job,
- const CertNetFetcherImpl::RequestParams& value) const {
+void AsyncCertNetFetcherImpl::Shutdown() {
+ DCHECK(thread_checker_.CalledOnValidThread());
+ for (const auto& job : jobs_) {
+ job.first->Cancel();
+ }
+ jobs_.clear();
+}
+
+struct JobToRequestParamsComparator {
+ bool operator()(const JobSet::value_type& job,
+ const RequestParams& value) const {
return job.first->request_params() < value;
}
};
-CertNetFetcherImpl::Job* CertNetFetcherImpl::FindJob(
- const RequestParams& params) {
+Job* AsyncCertNetFetcherImpl::FindJob(const RequestParams& params) {
DCHECK(thread_checker_.CalledOnValidThread());
// The JobSet is kept in sorted order so items can be found using binary
@@ -526,8 +644,7 @@ CertNetFetcherImpl::Job* CertNetFetcherImpl::FindJob(
return nullptr;
}
-std::unique_ptr<CertNetFetcherImpl::Job> CertNetFetcherImpl::RemoveJob(
- Job* job) {
+std::unique_ptr<Job> AsyncCertNetFetcherImpl::RemoveJob(Job* job) {
DCHECK(thread_checker_.CalledOnValidThread());
auto it = jobs_.find(job);
CHECK(it != jobs_.end());
@@ -536,19 +653,141 @@ std::unique_ptr<CertNetFetcherImpl::Job> CertNetFetcherImpl::RemoveJob(
return owned_job;
}
-void CertNetFetcherImpl::SetCurrentlyCompletingJob(Job* job) {
- DCHECK(!currently_completing_job_);
- DCHECK(job);
- currently_completing_job_ = job;
-}
+class CertNetFetcherRequestImpl : public CertNetFetcher::Request {
+ public:
+ explicit CertNetFetcherRequestImpl(scoped_refptr<RequestCore> core)
+ : core_(std::move(core)) {
+ DCHECK(core_);
+ }
-void CertNetFetcherImpl::ClearCurrentlyCompletingJob(Job* job) {
- DCHECK_EQ(currently_completing_job_, job);
- currently_completing_job_ = nullptr;
-}
+ void WaitForResult(Error* error, std::vector<uint8_t>* bytes) override {
+ // Should only be called a single time.
+ DCHECK(core_);
+ core_->WaitForResult(error, bytes);
+ core_ = nullptr;
+ }
+
+ ~CertNetFetcherRequestImpl() override {
+ if (core_)
+ core_->CancelJob();
+ }
+
+ private:
+ scoped_refptr<RequestCore> core_;
+};
+
+class CertNetFetcherImpl : public CertNetFetcher {
+ public:
+ explicit CertNetFetcherImpl(URLRequestContext* context)
+ : task_runner_(base::ThreadTaskRunnerHandle::Get()), context_(context) {}
+
+ void Shutdown() override {
+ DCHECK(task_runner_->RunsTasksOnCurrentThread());
+ if (impl_) {
+ impl_->Shutdown();
+ impl_.reset();
+ }
+ context_ = nullptr;
+ }
+
+ std::unique_ptr<Request> FetchCaIssuers(const GURL& url,
+ int timeout_milliseconds,
+ int max_response_bytes) override {
+ std::unique_ptr<RequestParams> request_params(new RequestParams);
+
+ request_params->url = url;
+ request_params->http_method = HTTP_METHOD_GET;
+ request_params->timeout = GetTimeout(timeout_milliseconds);
+ request_params->max_response_bytes =
+ GetMaxResponseBytes(max_response_bytes, kMaxResponseSizeInBytesForAia);
+
+ return DoFetch(std::move(request_params));
+ }
+
+ std::unique_ptr<Request> FetchCrl(const GURL& url,
+ int timeout_milliseconds,
+ int max_response_bytes) override {
+ std::unique_ptr<RequestParams> request_params(new RequestParams);
+
+ request_params->url = url;
+ request_params->http_method = HTTP_METHOD_GET;
+ request_params->timeout = GetTimeout(timeout_milliseconds);
+ request_params->max_response_bytes =
+ GetMaxResponseBytes(max_response_bytes, kMaxResponseSizeInBytesForCrl);
+
+ return DoFetch(std::move(request_params));
+ }
+
+ WARN_UNUSED_RESULT std::unique_ptr<Request> FetchOcsp(
+ const GURL& url,
+ int timeout_milliseconds,
+ int max_response_bytes) override {
+ std::unique_ptr<RequestParams> request_params(new RequestParams);
+
+ request_params->url = url;
+ request_params->http_method = HTTP_METHOD_GET;
+ request_params->timeout = GetTimeout(timeout_milliseconds);
+ request_params->max_response_bytes =
+ GetMaxResponseBytes(max_response_bytes, kMaxResponseSizeInBytesForAia);
+
+ return DoFetch(std::move(request_params));
+ }
+
+ private:
+ ~CertNetFetcherImpl() override {
+ // The fetcher must be shutdown (at which point |context_| will be set to
+ // null) before destruction.
+ DCHECK(!context_);
+ }
+
+ void DoFetchOnNetworkThread(std::unique_ptr<RequestParams> request_params,
+ scoped_refptr<RequestCore> request) {
+ DCHECK(task_runner_->RunsTasksOnCurrentThread());
+
+ if (!context_) {
+ // The fetcher might have been shutdown between when this task was posted
+ // and when it is running. In this case, signal the request and do not
+ // start a network request.
+ request->SignalImmediateError();
+ return;
+ }
+
+ if (!impl_) {
+ impl_.reset(new AsyncCertNetFetcherImpl(context_));
+ }
+
+ impl_->Fetch(std::move(request_params), request);
+ }
+
+ std::unique_ptr<Request> DoFetch(
+ std::unique_ptr<RequestParams> request_params) {
+ scoped_refptr<RequestCore> request_core = new RequestCore(task_runner_);
+
+ // If the fetcher has already been shutdown, DoFetchOnNetworkThread will
+ // signal the request with an error. However, if the fetcher shuts down
+ // before DoFetchOnNetworkThread runs and PostTask still returns true, then
+ // the request will hang (that is, WaitForResult will not return).
+ if (!task_runner_->PostTask(
+ FROM_HERE,
+ base::Bind(&CertNetFetcherImpl::DoFetchOnNetworkThread, this,
+ base::Passed(&request_params), request_core))) {
+ request_core->SignalImmediateError();
+ }
+
+ return base::MakeUnique<CertNetFetcherRequestImpl>(std::move(request_core));
+ }
+
+ private:
+ scoped_refptr<base::SingleThreadTaskRunner> task_runner_;
+ // Not owned. |context_| must stay valid until Shutdown() is called.
+ URLRequestContext* context_ = nullptr;
+ std::unique_ptr<AsyncCertNetFetcherImpl> impl_;
+};
+
+} // namespace
-bool CertNetFetcherImpl::IsCurrentlyCompletingJob(Job* job) {
- return job == currently_completing_job_;
+scoped_refptr<CertNetFetcher> CreateCertNetFetcher(URLRequestContext* context) {
+ return make_scoped_refptr(new CertNetFetcherImpl(context));
}
} // namespace net
diff --git a/chromium/net/cert_net/cert_net_fetcher_impl.h b/chromium/net/cert_net/cert_net_fetcher_impl.h
index 82f030122eb..c863fda7f01 100644
--- a/chromium/net/cert_net/cert_net_fetcher_impl.h
+++ b/chromium/net/cert_net/cert_net_fetcher_impl.h
@@ -2,109 +2,27 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#ifndef NET_CERT_NET_CERT_NET_FETCHER_H_
-#define NET_CERT_NET_CERT_NET_FETCHER_H_
+#ifndef NET_CERT_NET_CERT_NET_FETCHER_IMPL_H_
+#define NET_CERT_NET_CERT_NET_FETCHER_IMPL_H_
-#include <map>
#include <memory>
-#include "base/callback.h"
-#include "base/macros.h"
-#include "base/threading/thread_checker.h"
-#include "net/base/net_errors.h"
+#include "base/memory/ref_counted.h"
#include "net/base/net_export.h"
-#include "net/cert/cert_net_fetcher.h"
namespace net {
+class CertNetFetcher;
class URLRequestContext;
-// CertNetFetcherImpl is an implementation of CertNetFetcher that uses the
-// network stack.
-//
-// For more details refer to the documentation for the interface.
-class NET_EXPORT CertNetFetcherImpl : public CertNetFetcher {
- public:
- // Initializes CertNetFetcherImpl using the specified URLRequestContext for
- // issuing requests. |context| must remain valid for the entire lifetime of
- // the CertNetFetcherImpl.
- explicit CertNetFetcherImpl(URLRequestContext* context);
-
- // Deletion implicitly cancels any outstanding requests.
- ~CertNetFetcherImpl() override;
-
- WARN_UNUSED_RESULT std::unique_ptr<Request> FetchCaIssuers(
- const GURL& url,
- int timeout_milliseconds,
- int max_response_bytes,
- const FetchCallback& callback) override;
-
- WARN_UNUSED_RESULT std::unique_ptr<Request> FetchCrl(
- const GURL& url,
- int timeout_milliseconds,
- int max_response_bytes,
- const FetchCallback& callback) override;
-
- WARN_UNUSED_RESULT std::unique_ptr<Request> FetchOcsp(
- const GURL& url,
- int timeout_milliseconds,
- int max_response_bytes,
- const FetchCallback& callback) override;
-
- private:
- class RequestImpl;
- class Job;
- struct JobToRequestParamsComparator;
- struct RequestParams;
-
- struct JobComparator {
- bool operator()(const Job* job1, const Job* job2) const;
- };
-
- // Would be a set<unique_ptr> but extraction of owned objects from a set of
- // owned types doesn't come until C++17.
- using JobSet = std::map<Job*, std::unique_ptr<Job>, JobComparator>;
-
- // Starts an asynchronous request to fetch the given URL. On completion
- // |callback| will be invoked.
- //
- // Completion of the request will never occur synchronously. In other words it
- // is guaranteed that |callback| will only be invoked once the Fetch*() method
- // has returned.
- WARN_UNUSED_RESULT std::unique_ptr<Request> Fetch(
- std::unique_ptr<RequestParams> request_params,
- const FetchCallback& callback);
-
- // Finds a job with a matching RequestPararms or returns nullptr if there was
- // no match.
- Job* FindJob(const RequestParams& params);
-
- // Removes |job| from the in progress jobs and transfers ownership to the
- // caller.
- std::unique_ptr<Job> RemoveJob(Job* job);
-
- // Indicates which Job is currently executing inside of OnJobCompleted().
- void SetCurrentlyCompletingJob(Job* job);
- void ClearCurrentlyCompletingJob(Job* job);
- bool IsCurrentlyCompletingJob(Job* job);
-
- // The in-progress jobs. This set does not contain the job which is actively
- // invoking callbacks (OnJobCompleted). Instead that is tracked by
- // |currently_completing_job_|.
- JobSet jobs_;
-
- // The Job that is currently executing OnJobCompleted(). There can be at most
- // one such job. This pointer is not owned.
- Job* currently_completing_job_;
-
- // Not owned. CertNetFetcherImpl must outlive the URLRequestContext.
- URLRequestContext* context_;
-
- base::ThreadChecker thread_checker_;
-
- DISALLOW_COPY_AND_ASSIGN(CertNetFetcherImpl);
-};
+// Creates a CertNetFetcher that issues requests through the provided
+// URLRequestContext. The URLRequestContext must stay valid until the returned
+// CertNetFetcher's Shutdown method is called. The CertNetFetcher is to be
+// created and shutdown on the network thread. Its Fetch methods are to be used
+// on a *different* thread, since it gives a blocking interface to URL fetching.
+NET_EXPORT scoped_refptr<CertNetFetcher> CreateCertNetFetcher(
+ URLRequestContext* context);
} // namespace net
-#endif // NET_CERT_NET_CERT_NET_FETCHER_H_
+#endif // NET_CERT_NET_CERT_NET_FETCHER_IMPL_H_
diff --git a/chromium/net/cert_net/cert_net_fetcher_impl_unittest.cc b/chromium/net/cert_net/cert_net_fetcher_impl_unittest.cc
index da2c116064a..99f57700669 100644
--- a/chromium/net/cert_net/cert_net_fetcher_impl_unittest.cc
+++ b/chromium/net/cert_net/cert_net_fetcher_impl_unittest.cc
@@ -10,6 +10,8 @@
#include "base/compiler_specific.h"
#include "base/memory/ptr_util.h"
#include "base/run_loop.h"
+#include "base/synchronization/lock.h"
+#include "net/cert/cert_net_fetcher.h"
#include "net/cert/ct_policy_enforcer.h"
#include "net/cert/mock_cert_verifier.h"
#include "net/cert/multi_log_ct_verifier.h"
@@ -17,6 +19,8 @@
#include "net/http/http_server_properties_impl.h"
#include "net/test/embedded_test_server/embedded_test_server.h"
#include "net/test/gtest_util.h"
+#include "net/test/url_request/url_request_hanging_read_job.h"
+#include "net/url_request/url_request_filter.h"
#include "net/url_request/url_request_job_factory_impl.h"
#include "net/url_request/url_request_test_util.h"
#include "testing/gmock/include/gmock/gmock.h"
@@ -27,8 +31,6 @@ using net::test::IsOk;
// TODO(eroman): Test that cookies aren't sent.
-using base::ASCIIToUTF16;
-
namespace net {
namespace {
@@ -77,140 +79,192 @@ class RequestContext : public URLRequestContext {
URLRequestContextStorage storage_;
};
-class FetchResult {
+// Wait for the request to complete, and verify that it completed successfully
+// with the indicated bytes.
+void VerifySuccess(const std::string& expected_body,
+ CertNetFetcher::Request* request) {
+ Error actual_error;
+ std::vector<uint8_t> actual_body;
+ request->WaitForResult(&actual_error, &actual_body);
+
+ EXPECT_THAT(actual_error, IsOk());
+ EXPECT_EQ(expected_body, std::string(actual_body.begin(), actual_body.end()));
+}
+
+// Wait for the request to complete, and verify that it completed with the
+// indicated failure.
+void VerifyFailure(Error expected_error, CertNetFetcher::Request* request) {
+ Error actual_error;
+ std::vector<uint8_t> actual_body;
+ request->WaitForResult(&actual_error, &actual_body);
+
+ EXPECT_EQ(expected_error, actual_error);
+ EXPECT_EQ(0u, actual_body.size());
+}
+
+struct NetworkThreadState {
+ TestNetworkDelegate network_delegate;
+ RequestContext context;
+};
+
+class CertNetFetcherImplTest : public PlatformTest {
public:
- FetchResult(Error net_error, const std::vector<uint8_t>& response_body)
- : net_error_(net_error), response_body_(response_body) {}
+ CertNetFetcherImplTest() {
+ test_server_.AddDefaultHandlers(base::FilePath(kDocRoot));
+ StartNetworkThread();
+ }
- void VerifySuccess(const std::string& expected_body) {
- EXPECT_THAT(net_error_, IsOk());
- EXPECT_EQ(expected_body,
- std::string(response_body_.begin(), response_body_.end()));
+ ~CertNetFetcherImplTest() override {
+ if (!network_thread_)
+ return;
+ network_thread_->task_runner()->PostTask(
+ FROM_HERE, base::Bind(&CertNetFetcherImplTest::TeardownOnNetworkThread,
+ base::Unretained(this)));
+ network_thread_->Stop();
}
- void VerifyFailure(Error expected_error) {
- EXPECT_EQ(expected_error, net_error_);
- EXPECT_EQ(0u, response_body_.size());
+ protected:
+ CertNetFetcher* fetcher() const { return fetcher_.get(); }
+
+ void CreateFetcherOnNetworkThread(base::WaitableEvent* done) {
+ fetcher_ = CreateCertNetFetcher(&state_->context);
+ done->Signal();
}
- private:
- const Error net_error_;
- const std::vector<uint8_t> response_body_;
-};
+ void CreateFetcher() {
+ base::WaitableEvent done(base::WaitableEvent::ResetPolicy::MANUAL,
+ base::WaitableEvent::InitialState::NOT_SIGNALED);
+ network_thread_->task_runner()->PostTask(
+ FROM_HERE,
+ base::Bind(&CertNetFetcherImplTest::CreateFetcherOnNetworkThread,
+ base::Unretained(this), &done));
+ done.Wait();
+ }
-// Helper to synchronously wait for the fetch completion. This is similar to
-// net's TestCompletionCallback, but built around FetchCallback.
-class TestFetchCallback {
- public:
- TestFetchCallback()
- : callback_(base::Bind(&TestFetchCallback::OnCallback,
- base::Unretained(this))) {}
-
- const CertNetFetcher::FetchCallback& callback() const { return callback_; }
-
- std::unique_ptr<FetchResult> WaitForResult() {
- DCHECK(quit_closure_.is_null());
- while (!HasResult()) {
- base::RunLoop run_loop;
- quit_closure_ = run_loop.QuitClosure();
- run_loop.Run();
- quit_closure_.Reset();
- }
- return std::move(result_);
+ void ShutDownFetcherOnNetworkThread(base::WaitableEvent* done) {
+ fetcher_->Shutdown();
+ done->Signal();
}
- bool HasResult() const { return result_.get(); }
+ void ShutDownFetcher() {
+ base::WaitableEvent done(base::WaitableEvent::ResetPolicy::MANUAL,
+ base::WaitableEvent::InitialState::NOT_SIGNALED);
+ network_thread_->task_runner()->PostTask(
+ FROM_HERE,
+ base::Bind(&CertNetFetcherImplTest::ShutDownFetcherOnNetworkThread,
+ base::Unretained(this), &done));
+ done.Wait();
+ }
- // Sets an extra action (in addition to recording the result) that is run when
- // the FetchCallback is invoked.
- void set_extra_closure(const base::Closure& closure) {
- extra_closure_ = closure;
+ int NumCreatedRequests() {
+ int count = 0;
+ base::WaitableEvent done(base::WaitableEvent::ResetPolicy::MANUAL,
+ base::WaitableEvent::InitialState::NOT_SIGNALED);
+ network_thread_->task_runner()->PostTask(
+ FROM_HERE, base::Bind(&CertNetFetcherImplTest::CountCreatedRequests,
+ base::Unretained(this), &count, &done));
+ done.Wait();
+ return count;
}
- private:
- void OnCallback(Error net_error, const std::vector<uint8_t>& response_body) {
- DCHECK(!HasResult());
- result_.reset(new FetchResult(net_error, response_body));
+ void StartNetworkThread() {
+ // Start the network thread.
+ network_thread_.reset(new base::Thread("network thread"));
+ base::Thread::Options options(base::MessageLoop::TYPE_IO, 0);
+ EXPECT_TRUE(network_thread_->StartWithOptions(options));
+
+ // Initialize the URLRequestContext (and wait till it has completed).
+ base::WaitableEvent done(base::WaitableEvent::ResetPolicy::MANUAL,
+ base::WaitableEvent::InitialState::NOT_SIGNALED);
+ network_thread_->task_runner()->PostTask(
+ FROM_HERE, base::Bind(&CertNetFetcherImplTest::InitOnNetworkThread,
+ base::Unretained(this), &done));
+ done.Wait();
+ }
- if (!extra_closure_.is_null())
- extra_closure_.Run();
+ void InitOnNetworkThread(base::WaitableEvent* done) {
+ state_.reset(new NetworkThreadState);
+ state_->context.set_network_delegate(&state_->network_delegate);
+ done->Signal();
+ }
- if (!quit_closure_.is_null())
- quit_closure_.Run();
+ void ResetStateOnNetworkThread(base::WaitableEvent* done) {
+ state_.reset();
+ done->Signal();
}
- CertNetFetcher::FetchCallback callback_;
- std::unique_ptr<FetchResult> result_;
- base::Closure quit_closure_;
- base::Closure extra_closure_;
-};
+ void ResetState() {
+ base::WaitableEvent done(base::WaitableEvent::ResetPolicy::MANUAL,
+ base::WaitableEvent::InitialState::NOT_SIGNALED);
+ network_thread_->task_runner()->PostTask(
+ FROM_HERE,
+ base::Bind(&CertNetFetcherImplTest::ResetStateOnNetworkThread,
+ base::Unretained(this), &done));
+ done.Wait();
+ }
-} // namespace
+ void TeardownOnNetworkThread() {
+ fetcher_->Shutdown();
+ state_.reset();
+ fetcher_ = nullptr;
+ }
-class CertNetFetcherImplTest : public PlatformTest {
- public:
- CertNetFetcherImplTest() {
- test_server_.AddDefaultHandlers(base::FilePath(kDocRoot));
- context_.set_network_delegate(&network_delegate_);
+ void CountCreatedRequests(int* count, base::WaitableEvent* done) {
+ *count = state_->network_delegate.created_requests();
+ done->Signal();
}
- protected:
EmbeddedTestServer test_server_;
- TestNetworkDelegate network_delegate_;
- RequestContext context_;
+ std::unique_ptr<base::Thread> network_thread_;
+ scoped_refptr<CertNetFetcher> fetcher_;
+
+ std::unique_ptr<NetworkThreadState> state_;
+};
+
+// Installs URLRequestHangingReadJob handlers and clears them on teardown.
+class CertNetFetcherImplTestWithHangingReadHandler
+ : public CertNetFetcherImplTest {
+ protected:
+ void SetUp() override { URLRequestHangingReadJob::AddUrlHandler(); }
+
+ void TearDown() override { URLRequestFilter::GetInstance()->ClearHandlers(); }
};
// Helper to start an AIA fetch using default parameters.
WARN_UNUSED_RESULT std::unique_ptr<CertNetFetcher::Request> StartRequest(
CertNetFetcher* fetcher,
- const GURL& url,
- const TestFetchCallback& callback) {
+ const GURL& url) {
return fetcher->FetchCaIssuers(url, CertNetFetcher::DEFAULT,
- CertNetFetcher::DEFAULT, callback.callback());
+ CertNetFetcher::DEFAULT);
}
-// Flaky on Android. See http://crbug.com/646147.
-#if defined(OS_ANDROID)
-#define MAYBE_ParallelFetchNoDuplicates DISABLED_ParallelFetchNoDuplicates
-#else
-#define MAYBE_ParallelFetchNoDuplicates ParallelFetchNoDuplicates
-#endif
// Fetch a few unique URLs using GET in parallel. Each URL has a different body
// and Content-Type.
-TEST_F(CertNetFetcherImplTest, MAYBE_ParallelFetchNoDuplicates) {
+TEST_F(CertNetFetcherImplTest, ParallelFetchNoDuplicates) {
ASSERT_TRUE(test_server_.Start());
-
- CertNetFetcherImpl fetcher(&context_);
- TestFetchCallback callback1;
- TestFetchCallback callback2;
- TestFetchCallback callback3;
+ CreateFetcher();
// Request a URL with Content-Type "application/pkix-cert"
GURL url1 = test_server_.GetURL("/cert.crt");
std::unique_ptr<CertNetFetcher::Request> request1 =
- StartRequest(&fetcher, url1, callback1);
+ StartRequest(fetcher(), url1);
// Request a URL with Content-Type "application/pkix-crl"
GURL url2 = test_server_.GetURL("/root.crl");
std::unique_ptr<CertNetFetcher::Request> request2 =
- StartRequest(&fetcher, url2, callback2);
+ StartRequest(fetcher(), url2);
// Request a URL with Content-Type "application/pkcs7-mime"
GURL url3 = test_server_.GetURL("/certs.p7c");
std::unique_ptr<CertNetFetcher::Request> request3 =
- StartRequest(&fetcher, url3, callback3);
-
- // Wait for all of the requests to complete.
- std::unique_ptr<FetchResult> result1 = callback1.WaitForResult();
- std::unique_ptr<FetchResult> result2 = callback2.WaitForResult();
- std::unique_ptr<FetchResult> result3 = callback3.WaitForResult();
+ StartRequest(fetcher(), url3);
- // Verify the fetch results.
- result1->VerifySuccess("-cert.crt-\n");
- result2->VerifySuccess("-root.crl-\n");
- result3->VerifySuccess("-certs.p7c-\n");
+ // Wait for all of the requests to complete and verify the fetch results.
+ VerifySuccess("-cert.crt-\n", request1.get());
+ VerifySuccess("-root.crl-\n", request2.get());
+ VerifySuccess("-certs.p7c-\n", request3.get());
- EXPECT_EQ(3, network_delegate_.created_requests());
+ EXPECT_EQ(3, NumCreatedRequests());
}
// Fetch a caIssuers URL which has an unexpected extension and Content-Type.
@@ -219,57 +273,46 @@ TEST_F(CertNetFetcherImplTest, MAYBE_ParallelFetchNoDuplicates) {
// be meaningful.
TEST_F(CertNetFetcherImplTest, ContentTypeDoesntMatter) {
ASSERT_TRUE(test_server_.Start());
+ CreateFetcher();
- CertNetFetcherImpl fetcher(&context_);
-
- TestFetchCallback callback;
GURL url = test_server_.GetURL("/foo.txt");
std::unique_ptr<CertNetFetcher::Request> request =
- StartRequest(&fetcher, url, callback);
- std::unique_ptr<FetchResult> result = callback.WaitForResult();
- result->VerifySuccess("-foo.txt-\n");
+ StartRequest(fetcher(), url);
+ VerifySuccess("-foo.txt-\n", request.get());
}
// Fetch a URLs whose HTTP response code is not 200. These are considered
// failures.
TEST_F(CertNetFetcherImplTest, HttpStatusCode) {
ASSERT_TRUE(test_server_.Start());
-
- CertNetFetcherImpl fetcher(&context_);
+ CreateFetcher();
// Response was HTTP status 404.
{
- TestFetchCallback callback;
GURL url = test_server_.GetURL("/404.html");
std::unique_ptr<CertNetFetcher::Request> request =
- StartRequest(&fetcher, url, callback);
- std::unique_ptr<FetchResult> result = callback.WaitForResult();
- result->VerifyFailure(ERR_FAILED);
+ StartRequest(fetcher(), url);
+ VerifyFailure(ERR_FAILED, request.get());
}
// Response was HTTP status 500.
{
- TestFetchCallback callback;
GURL url = test_server_.GetURL("/500.html");
std::unique_ptr<CertNetFetcher::Request> request =
- StartRequest(&fetcher, url, callback);
- std::unique_ptr<FetchResult> result = callback.WaitForResult();
- result->VerifyFailure(ERR_FAILED);
+ StartRequest(fetcher(), url);
+ VerifyFailure(ERR_FAILED, request.get());
}
}
// Fetching a URL with a Content-Disposition header should have no effect.
TEST_F(CertNetFetcherImplTest, ContentDisposition) {
ASSERT_TRUE(test_server_.Start());
+ CreateFetcher();
- CertNetFetcherImpl fetcher(&context_);
-
- TestFetchCallback callback;
GURL url = test_server_.GetURL("/downloadable.js");
std::unique_ptr<CertNetFetcher::Request> request =
- StartRequest(&fetcher, url, callback);
- std::unique_ptr<FetchResult> result = callback.WaitForResult();
- result->VerifySuccess("-downloadable.js-\n");
+ StartRequest(fetcher(), url);
+ VerifySuccess("-downloadable.js-\n", request.get());
}
// Verifies that a cachable request will be served from the HTTP cache the
@@ -277,34 +320,29 @@ TEST_F(CertNetFetcherImplTest, ContentDisposition) {
TEST_F(CertNetFetcherImplTest, Cache) {
ASSERT_TRUE(test_server_.Start());
- CertNetFetcherImpl fetcher(&context_);
+ CreateFetcher();
// Fetch a URL whose HTTP headers make it cacheable for 1 hour.
GURL url(test_server_.GetURL("/cacheable_1hr.crt"));
{
- TestFetchCallback callback;
-
std::unique_ptr<CertNetFetcher::Request> request =
- StartRequest(&fetcher, url, callback);
- std::unique_ptr<FetchResult> result = callback.WaitForResult();
- result->VerifySuccess("-cacheable_1hr.crt-\n");
+ StartRequest(fetcher(), url);
+ VerifySuccess("-cacheable_1hr.crt-\n", request.get());
}
- EXPECT_EQ(1, network_delegate_.created_requests());
+ EXPECT_EQ(1, NumCreatedRequests());
// Kill the HTTP server.
ASSERT_TRUE(test_server_.ShutdownAndWaitUntilComplete());
// Fetch again -- will fail unless served from cache.
{
- TestFetchCallback callback;
std::unique_ptr<CertNetFetcher::Request> request =
- StartRequest(&fetcher, url, callback);
- std::unique_ptr<FetchResult> result = callback.WaitForResult();
- result->VerifySuccess("-cacheable_1hr.crt-\n");
+ StartRequest(fetcher(), url);
+ VerifySuccess("-cacheable_1hr.crt-\n", request.get());
}
- EXPECT_EQ(2, network_delegate_.created_requests());
+ EXPECT_EQ(2, NumCreatedRequests());
}
// Verify that the maximum response body constraints are enforced by fetching a
@@ -312,17 +350,15 @@ TEST_F(CertNetFetcherImplTest, Cache) {
TEST_F(CertNetFetcherImplTest, TooLarge) {
ASSERT_TRUE(test_server_.Start());
- CertNetFetcherImpl fetcher(&context_);
+ CreateFetcher();
// This file has a response body 12 bytes long. So setting the maximum to 11
// bytes will cause it to fail.
GURL url(test_server_.GetURL("/certs.p7c"));
- TestFetchCallback callback;
- std::unique_ptr<CertNetFetcher::Request> request = fetcher.FetchCaIssuers(
- url, CertNetFetcher::DEFAULT, 11, callback.callback());
+ std::unique_ptr<CertNetFetcher::Request> request =
+ fetcher()->FetchCaIssuers(url, CertNetFetcher::DEFAULT, 11);
- std::unique_ptr<FetchResult> result = callback.WaitForResult();
- result->VerifyFailure(ERR_FILE_TOO_BIG);
+ VerifyFailure(ERR_FILE_TOO_BIG, request.get());
}
// Set the timeout to 10 milliseconds, and try fetching a URL that takes 5
@@ -330,14 +366,12 @@ TEST_F(CertNetFetcherImplTest, TooLarge) {
TEST_F(CertNetFetcherImplTest, Hang) {
ASSERT_TRUE(test_server_.Start());
- CertNetFetcherImpl fetcher(&context_);
+ CreateFetcher();
GURL url(test_server_.GetURL("/slow/certs.p7c?5"));
- TestFetchCallback callback;
- std::unique_ptr<CertNetFetcher::Request> request = fetcher.FetchCaIssuers(
- url, 10, CertNetFetcher::DEFAULT, callback.callback());
- std::unique_ptr<FetchResult> result = callback.WaitForResult();
- result->VerifyFailure(ERR_TIMED_OUT);
+ std::unique_ptr<CertNetFetcher::Request> request =
+ fetcher()->FetchCaIssuers(url, 10, CertNetFetcher::DEFAULT);
+ VerifyFailure(ERR_TIMED_OUT, request.get());
}
// Verify that if a response is gzip-encoded it gets inflated before being
@@ -345,51 +379,42 @@ TEST_F(CertNetFetcherImplTest, Hang) {
TEST_F(CertNetFetcherImplTest, Gzip) {
ASSERT_TRUE(test_server_.Start());
- CertNetFetcherImpl fetcher(&context_);
+ CreateFetcher();
GURL url(test_server_.GetURL("/gzipped_crl"));
- TestFetchCallback callback;
std::unique_ptr<CertNetFetcher::Request> request =
- StartRequest(&fetcher, url, callback);
- std::unique_ptr<FetchResult> result = callback.WaitForResult();
- result->VerifySuccess("-gzipped_crl-\n");
+ StartRequest(fetcher(), url);
+ VerifySuccess("-gzipped_crl-\n", request.get());
}
// Try fetching an unsupported URL scheme (https).
TEST_F(CertNetFetcherImplTest, HttpsNotAllowed) {
ASSERT_TRUE(test_server_.Start());
- CertNetFetcherImpl fetcher(&context_);
+ CreateFetcher();
GURL url("https://foopy/foo.crt");
- TestFetchCallback callback;
std::unique_ptr<CertNetFetcher::Request> request =
- StartRequest(&fetcher, url, callback);
- // Should NOT complete synchronously despite being a test that could be done
- // immediately.
- EXPECT_FALSE(callback.HasResult());
- std::unique_ptr<FetchResult> result = callback.WaitForResult();
- result->VerifyFailure(ERR_DISALLOWED_URL_SCHEME);
+ StartRequest(fetcher(), url);
+ VerifyFailure(ERR_DISALLOWED_URL_SCHEME, request.get());
// No request was created because the URL scheme was unsupported.
- EXPECT_EQ(0, network_delegate_.created_requests());
+ EXPECT_EQ(0, NumCreatedRequests());
}
// Try fetching a URL which redirects to https.
TEST_F(CertNetFetcherImplTest, RedirectToHttpsNotAllowed) {
ASSERT_TRUE(test_server_.Start());
- CertNetFetcherImpl fetcher(&context_);
+ CreateFetcher();
GURL url(test_server_.GetURL("/redirect_https"));
- TestFetchCallback callback;
std::unique_ptr<CertNetFetcher::Request> request =
- StartRequest(&fetcher, url, callback);
- std::unique_ptr<FetchResult> result = callback.WaitForResult();
- result->VerifyFailure(ERR_DISALLOWED_URL_SCHEME);
+ StartRequest(fetcher(), url);
+ VerifyFailure(ERR_DISALLOWED_URL_SCHEME, request.get());
- EXPECT_EQ(1, network_delegate_.created_requests());
+ EXPECT_EQ(1, NumCreatedRequests());
}
// Try fetching an unsupported URL scheme (https) and then immediately
@@ -397,73 +422,44 @@ TEST_F(CertNetFetcherImplTest, RedirectToHttpsNotAllowed) {
TEST_F(CertNetFetcherImplTest, CancelHttpsNotAllowed) {
ASSERT_TRUE(test_server_.Start());
- CertNetFetcherImpl fetcher(&context_);
+ CreateFetcher();
GURL url("https://foopy/foo.crt");
- TestFetchCallback callback;
std::unique_ptr<CertNetFetcher::Request> request =
- StartRequest(&fetcher, url, callback);
+ StartRequest(fetcher(), url);
- // Cancel the request.
+ // Cancel the request (May or may not have started yet, as the request is
+ // running on another thread).
request.reset();
-
- // Spin the message loop to increase chance of catching a bug.
- base::RunLoop().RunUntilIdle();
-
- // Should NOT complete synchronously despite being a test that could be done
- // immediately.
- EXPECT_FALSE(callback.HasResult());
-
- EXPECT_EQ(0, network_delegate_.created_requests());
}
-// Flaky on Android. See http://crbug.com/646147.
-#if defined(OS_ANDROID)
-#define MAYBE_CancelBeforeRunningMessageLoop \
- DISABLED_CancelBeforeRunningMessageLoop
-#else
-#define MAYBE_CancelBeforeRunningMessageLoop CancelBeforeRunningMessageLoop
-#endif
// Start a few requests, and cancel one of them before running the message loop
// again.
-TEST_F(CertNetFetcherImplTest, MAYBE_CancelBeforeRunningMessageLoop) {
+TEST_F(CertNetFetcherImplTest, CancelBeforeRunningMessageLoop) {
ASSERT_TRUE(test_server_.Start());
- CertNetFetcherImpl fetcher(&context_);
- TestFetchCallback callback1;
- TestFetchCallback callback2;
- TestFetchCallback callback3;
+ CreateFetcher();
GURL url1 = test_server_.GetURL("/cert.crt");
std::unique_ptr<CertNetFetcher::Request> request1 =
- StartRequest(&fetcher, url1, callback1);
+ StartRequest(fetcher(), url1);
GURL url2 = test_server_.GetURL("/root.crl");
std::unique_ptr<CertNetFetcher::Request> request2 =
- StartRequest(&fetcher, url2, callback2);
+ StartRequest(fetcher(), url2);
GURL url3 = test_server_.GetURL("/certs.p7c");
std::unique_ptr<CertNetFetcher::Request> request3 =
- StartRequest(&fetcher, url3, callback3);
-
- EXPECT_EQ(3, network_delegate_.created_requests());
- EXPECT_FALSE(callback1.HasResult());
- EXPECT_FALSE(callback2.HasResult());
- EXPECT_FALSE(callback3.HasResult());
+ StartRequest(fetcher(), url3);
// Cancel the second request.
request2.reset();
- // Wait for the non-cancelled requests to complete.
- std::unique_ptr<FetchResult> result1 = callback1.WaitForResult();
- std::unique_ptr<FetchResult> result3 = callback3.WaitForResult();
-
- // Verify the fetch results.
- result1->VerifySuccess("-cert.crt-\n");
- result3->VerifySuccess("-certs.p7c-\n");
-
- EXPECT_FALSE(callback2.HasResult());
+ // Wait for the non-cancelled requests to complete, and verify the fetch
+ // results.
+ VerifySuccess("-cert.crt-\n", request1.get());
+ VerifySuccess("-certs.p7c-\n", request3.get());
}
// Start several requests, and cancel one of them after the first has completed.
@@ -478,333 +474,165 @@ TEST_F(CertNetFetcherImplTest, MAYBE_CancelBeforeRunningMessageLoop) {
// To work around this, the last request is cancelled, and hope that the
// requests are given opened sockets in a FIFO order.
// TODO(eroman): Make this more robust.
+// TODO(eroman): Rename this test.
TEST_F(CertNetFetcherImplTest, CancelAfterRunningMessageLoop) {
ASSERT_TRUE(test_server_.Start());
- CertNetFetcherImpl fetcher(&context_);
- TestFetchCallback callback1;
- TestFetchCallback callback2;
- TestFetchCallback callback3;
+ CreateFetcher();
GURL url1 = test_server_.GetURL("/cert.crt");
std::unique_ptr<CertNetFetcher::Request> request1 =
- StartRequest(&fetcher, url1, callback1);
+ StartRequest(fetcher(), url1);
GURL url2 = test_server_.GetURL("/certs.p7c");
std::unique_ptr<CertNetFetcher::Request> request2 =
- StartRequest(&fetcher, url2, callback2);
+ StartRequest(fetcher(), url2);
GURL url3("ftp://www.not.supported.com/foo");
std::unique_ptr<CertNetFetcher::Request> request3 =
- StartRequest(&fetcher, url3, callback3);
-
- EXPECT_FALSE(callback1.HasResult());
- EXPECT_FALSE(callback2.HasResult());
- EXPECT_FALSE(callback3.HasResult());
+ StartRequest(fetcher(), url3);
// Wait for the ftp request to complete (it should complete right away since
// it doesn't even try to connect to the server).
- std::unique_ptr<FetchResult> result3 = callback3.WaitForResult();
- result3->VerifyFailure(ERR_DISALLOWED_URL_SCHEME);
+ VerifyFailure(ERR_DISALLOWED_URL_SCHEME, request3.get());
// Cancel the second outstanding request.
request2.reset();
- // Wait for the first request to complete.
- std::unique_ptr<FetchResult> result2 = callback1.WaitForResult();
-
- // Verify the fetch results.
- result2->VerifySuccess("-cert.crt-\n");
+ // Wait for the first request to complete and verify the fetch result.
+ VerifySuccess("-cert.crt-\n", request1.get());
}
-// Delete a CertNetFetcherImpl with outstanding requests on it.
-TEST_F(CertNetFetcherImplTest, DeleteCancels) {
- ASSERT_TRUE(test_server_.Start());
-
- std::unique_ptr<CertNetFetcherImpl> fetcher(
- new CertNetFetcherImpl(&context_));
-
- GURL url(test_server_.GetURL("/slow/certs.p7c?20"));
- TestFetchCallback callback;
- std::unique_ptr<CertNetFetcher::Request> request =
- StartRequest(fetcher.get(), url, callback);
-
- // Destroy the fetcher before the outstanding request.
- fetcher.reset();
-}
-
-// Flaky on Android. See http://crbug.com/646147.
-#if defined(OS_ANDROID)
-#define MAYBE_ParallelFetchDuplicates DISABLED_ParallelFetchDuplicates
-#else
-#define MAYBE_ParallelFetchDuplicates ParallelFetchDuplicates
-#endif
// Fetch the same URLs in parallel and verify that only 1 request is made per
// URL.
-TEST_F(CertNetFetcherImplTest, MAYBE_ParallelFetchDuplicates) {
+TEST_F(CertNetFetcherImplTest, ParallelFetchDuplicates) {
ASSERT_TRUE(test_server_.Start());
- CertNetFetcherImpl fetcher(&context_);
+ CreateFetcher();
GURL url1 = test_server_.GetURL("/cert.crt");
GURL url2 = test_server_.GetURL("/root.crl");
// Issue 3 requests for url1, and 3 requests for url2
- TestFetchCallback callback1;
std::unique_ptr<CertNetFetcher::Request> request1 =
- StartRequest(&fetcher, url1, callback1);
+ StartRequest(fetcher(), url1);
- TestFetchCallback callback2;
std::unique_ptr<CertNetFetcher::Request> request2 =
- StartRequest(&fetcher, url2, callback2);
+ StartRequest(fetcher(), url2);
- TestFetchCallback callback3;
std::unique_ptr<CertNetFetcher::Request> request3 =
- StartRequest(&fetcher, url1, callback3);
+ StartRequest(fetcher(), url1);
- TestFetchCallback callback4;
std::unique_ptr<CertNetFetcher::Request> request4 =
- StartRequest(&fetcher, url2, callback4);
+ StartRequest(fetcher(), url2);
- TestFetchCallback callback5;
std::unique_ptr<CertNetFetcher::Request> request5 =
- StartRequest(&fetcher, url2, callback5);
+ StartRequest(fetcher(), url2);
- TestFetchCallback callback6;
std::unique_ptr<CertNetFetcher::Request> request6 =
- StartRequest(&fetcher, url1, callback6);
+ StartRequest(fetcher(), url1);
// Cancel all but one of the requests for url1.
request1.reset();
request3.reset();
- // Wait for the remaining requests to finish.
- std::unique_ptr<FetchResult> result2 = callback2.WaitForResult();
- std::unique_ptr<FetchResult> result4 = callback4.WaitForResult();
- std::unique_ptr<FetchResult> result5 = callback5.WaitForResult();
- std::unique_ptr<FetchResult> result6 = callback6.WaitForResult();
-
- // Verify that none of the cancelled requests for url1 completed (since they
- // were cancelled).
- EXPECT_FALSE(callback1.HasResult());
- EXPECT_FALSE(callback3.HasResult());
-
- // Verify the fetch results.
- result2->VerifySuccess("-root.crl-\n");
- result4->VerifySuccess("-root.crl-\n");
- result5->VerifySuccess("-root.crl-\n");
- result6->VerifySuccess("-cert.crt-\n");
+ // Wait for the remaining requests to finish and verify the fetch results.
+ VerifySuccess("-root.crl-\n", request2.get());
+ VerifySuccess("-root.crl-\n", request4.get());
+ VerifySuccess("-root.crl-\n", request5.get());
+ VerifySuccess("-cert.crt-\n", request6.get());
// Verify that only 2 URLRequests were started even though 6 requests were
// issued.
- EXPECT_EQ(2, network_delegate_.created_requests());
+ EXPECT_EQ(2, NumCreatedRequests());
}
-// Flaky on Android. See http://crbug.com/646147.
-#if defined(OS_ANDROID)
-#define MAYBE_CancelThenStart DISABLED_CancelThenStart
-#else
-#define MAYBE_CancelThenStart CancelThenStart
-#endif
// Cancel a request and then start another one for the same URL.
-TEST_F(CertNetFetcherImplTest, MAYBE_CancelThenStart) {
+TEST_F(CertNetFetcherImplTest, CancelThenStart) {
ASSERT_TRUE(test_server_.Start());
- CertNetFetcherImpl fetcher(&context_);
- TestFetchCallback callback1;
- TestFetchCallback callback2;
- TestFetchCallback callback3;
+ CreateFetcher();
GURL url = test_server_.GetURL("/cert.crt");
std::unique_ptr<CertNetFetcher::Request> request1 =
- StartRequest(&fetcher, url, callback1);
+ StartRequest(fetcher(), url);
request1.reset();
std::unique_ptr<CertNetFetcher::Request> request2 =
- StartRequest(&fetcher, url, callback2);
+ StartRequest(fetcher(), url);
std::unique_ptr<CertNetFetcher::Request> request3 =
- StartRequest(&fetcher, url, callback3);
+ StartRequest(fetcher(), url);
request3.reset();
// All but |request2| were canceled.
- std::unique_ptr<FetchResult> result = callback2.WaitForResult();
-
- result->VerifySuccess("-cert.crt-\n");
-
- EXPECT_FALSE(callback1.HasResult());
- EXPECT_FALSE(callback3.HasResult());
-
- // One URLRequest that was cancelled, then another right afterwards.
- EXPECT_EQ(2, network_delegate_.created_requests());
+ VerifySuccess("-cert.crt-\n", request2.get());
}
// Start duplicate requests and then cancel all of them.
TEST_F(CertNetFetcherImplTest, CancelAll) {
ASSERT_TRUE(test_server_.Start());
- CertNetFetcherImpl fetcher(&context_);
- TestFetchCallback callback[3];
+ CreateFetcher();
std::unique_ptr<CertNetFetcher::Request> request[3];
GURL url = test_server_.GetURL("/cert.crt");
- for (size_t i = 0; i < arraysize(callback); ++i) {
- request[i] = StartRequest(&fetcher, url, callback[i]);
+ for (size_t i = 0; i < arraysize(request); ++i) {
+ request[i] = StartRequest(fetcher(), url);
}
// Cancel all the requests.
for (size_t i = 0; i < arraysize(request); ++i)
request[i].reset();
- EXPECT_EQ(1, network_delegate_.created_requests());
-
- for (size_t i = 0; i < arraysize(request); ++i)
- EXPECT_FALSE(callback[i].HasResult());
-}
-
-void DeleteCertNetFetcher(CertNetFetcher* fetcher) {
- delete fetcher;
+ EXPECT_EQ(1, NumCreatedRequests());
}
-// Delete the CertNetFetcherImpl within a request callback.
-TEST_F(CertNetFetcherImplTest, DeleteWithinCallback) {
+// Tests that Requests are signalled for completion even if they are
+// created after the CertNetFetcher has been shutdown.
+TEST_F(CertNetFetcherImplTest, RequestsAfterShutdown) {
ASSERT_TRUE(test_server_.Start());
-
- // Deleted by callback2.
- CertNetFetcher* fetcher = new CertNetFetcherImpl(&context_);
+ CreateFetcher();
+ ShutDownFetcher();
GURL url = test_server_.GetURL("/cert.crt");
-
- TestFetchCallback callback[4];
- std::unique_ptr<CertNetFetcher::Request> reqs[4];
- callback[1].set_extra_closure(base::Bind(DeleteCertNetFetcher, fetcher));
-
- for (size_t i = 0; i < arraysize(callback); ++i)
- reqs[i] = StartRequest(fetcher, url, callback[i]);
-
- EXPECT_EQ(1, network_delegate_.created_requests());
-
- callback[1].WaitForResult();
-
- // Assume requests for the same URL are executed in FIFO order.
- EXPECT_TRUE(callback[0].HasResult());
- EXPECT_FALSE(callback[2].HasResult());
- EXPECT_FALSE(callback[3].HasResult());
-}
-
-void FetchRequest(CertNetFetcher* fetcher,
- const GURL& url,
- TestFetchCallback* callback,
- std::unique_ptr<CertNetFetcher::Request>* request) {
- *request = StartRequest(fetcher, url, *callback);
+ std::unique_ptr<CertNetFetcher::Request> request =
+ StartRequest(fetcher(), url);
+ VerifyFailure(ERR_ABORTED, request.get());
+ EXPECT_EQ(0, NumCreatedRequests());
}
-// Flaky on Android. See http://crbug.com/646147.
-#if defined(OS_ANDROID)
-#define MAYBE_FetchWithinCallback DISABLED_FetchWithinCallback
-#else
-#define MAYBE_FetchWithinCallback FetchWithinCallback
-#endif
-// Make a request during callback for the same URL.
-TEST_F(CertNetFetcherImplTest, MAYBE_FetchWithinCallback) {
+// Tests that Requests are signalled for completion if the fetcher is
+// shutdown and the network thread stopped before the request is
+// started.
+TEST_F(CertNetFetcherImplTest, RequestAfterShutdownAndNetworkThreadStopped) {
ASSERT_TRUE(test_server_.Start());
-
- CertNetFetcherImpl fetcher(&context_);
+ CreateFetcher();
+ ShutDownFetcher();
+ ResetState();
+ network_thread_.reset();
GURL url = test_server_.GetURL("/cert.crt");
-
- TestFetchCallback callback[5];
- std::unique_ptr<CertNetFetcher::Request> req[5];
- callback[1].set_extra_closure(
- base::Bind(FetchRequest, &fetcher, url, &callback[4], &req[4]));
-
- for (size_t i = 0; i < arraysize(callback) - 1; ++i)
- req[i] = StartRequest(&fetcher, url, callback[i]);
-
- EXPECT_EQ(1, network_delegate_.created_requests());
-
- for (size_t i = 0; i < arraysize(callback); ++i) {
- std::unique_ptr<FetchResult> result = callback[i].WaitForResult();
- result->VerifySuccess("-cert.crt-\n");
- }
-
- // The fetch started within a callback should have started a new request
- // rather than attaching to the current job.
- EXPECT_EQ(2, network_delegate_.created_requests());
-}
-
-void CancelRequest(std::unique_ptr<CertNetFetcher::Request>* request) {
- request->reset();
+ std::unique_ptr<CertNetFetcher::Request> request =
+ StartRequest(fetcher(), url);
+ VerifyFailure(ERR_ABORTED, request.get());
}
-// Cancel a request while executing a callback for the same job.
-TEST_F(CertNetFetcherImplTest, CancelWithinCallback) {
- ASSERT_TRUE(test_server_.Start());
-
- CertNetFetcherImpl fetcher(&context_);
-
- GURL url = test_server_.GetURL("/cert.crt");
-
- TestFetchCallback callback[4];
- std::unique_ptr<CertNetFetcher::Request> request[4];
+// Tests that outstanding Requests are cancelled when Shutdown is called.
+TEST_F(CertNetFetcherImplTestWithHangingReadHandler, ShutdownCancelsRequests) {
+ CreateFetcher();
- for (size_t i = 0; i < arraysize(callback); ++i)
- request[i] = StartRequest(&fetcher, url, callback[i]);
-
- // Cancel request[2] when the callback for request[1] runs.
- callback[1].set_extra_closure(base::Bind(CancelRequest, &request[2]));
-
- EXPECT_EQ(1, network_delegate_.created_requests());
-
- for (size_t i = 0; i < arraysize(request); ++i) {
- if (i == 2)
- continue;
-
- std::unique_ptr<FetchResult> result = callback[i].WaitForResult();
- result->VerifySuccess("-cert.crt-\n");
- }
+ GURL url = URLRequestHangingReadJob::GetMockHttpUrl();
+ std::unique_ptr<CertNetFetcher::Request> request =
+ StartRequest(fetcher(), url);
- // request[2] was cancelled.
- EXPECT_FALSE(callback[2].HasResult());
+ ShutDownFetcher();
+ VerifyFailure(ERR_ABORTED, request.get());
}
-// Flaky on Android. See http://crbug.com/646147.
-#if defined(OS_ANDROID)
-#define MAYBE_CancelLastRequestWithinCallback \
- DISABLED_CancelLastRequestWithinCallback
-#else
-#define MAYBE_CancelLastRequestWithinCallback CancelLastRequestWithinCallback
-#endif
-// Cancel the final request while executing a callback for the same job. Ensure
-// that the job is not deleted twice.
-TEST_F(CertNetFetcherImplTest, MAYBE_CancelLastRequestWithinCallback) {
- ASSERT_TRUE(test_server_.Start());
-
- CertNetFetcherImpl fetcher(&context_);
-
- GURL url = test_server_.GetURL("/cert.crt");
-
- TestFetchCallback callback1;
- std::unique_ptr<CertNetFetcher::Request> request1 =
- StartRequest(&fetcher, url, callback1);
-
- TestFetchCallback callback2;
- std::unique_ptr<CertNetFetcher::Request> request2 =
- StartRequest(&fetcher, url, callback1);
-
- // Cancel request2 when the callback for request1 runs.
- callback1.set_extra_closure(base::Bind(CancelRequest, &request2));
-
- EXPECT_EQ(1, network_delegate_.created_requests());
-
- std::unique_ptr<FetchResult> result = callback1.WaitForResult();
- result->VerifySuccess("-cert.crt-\n");
-
- // request2 was cancelled.
- EXPECT_FALSE(callback2.HasResult());
-}
+} // namespace
} // namespace net
diff --git a/chromium/net/cookies/cookie_monster.cc b/chromium/net/cookies/cookie_monster.cc
index b656d83e6c0..1b812c1d028 100644
--- a/chromium/net/cookies/cookie_monster.cc
+++ b/chromium/net/cookies/cookie_monster.cc
@@ -274,7 +274,7 @@ typedef struct ChangeCausePair_struct {
} ChangeCausePair;
const ChangeCausePair kChangeCauseMapping[] = {
// DELETE_COOKIE_EXPLICIT
- {CookieStore::ChangeCause::EXPLICIT, true},
+ {CookieStore::ChangeCause::EXPLICIT_DELETE, true},
// DELETE_COOKIE_OVERWRITE
{CookieStore::ChangeCause::OVERWRITE, true},
// DELETE_COOKIE_EXPIRED
@@ -282,9 +282,9 @@ const ChangeCausePair kChangeCauseMapping[] = {
// DELETE_COOKIE_EVICTED
{CookieStore::ChangeCause::EVICTED, true},
// DELETE_COOKIE_DUPLICATE_IN_BACKING_STORE
- {CookieStore::ChangeCause::EXPLICIT, false},
+ {CookieStore::ChangeCause::EXPLICIT_DUPLICATE_IN_BACKING_STORE, false},
// DELETE_COOKIE_DONT_RECORD
- {CookieStore::ChangeCause::EXPLICIT, false},
+ {CookieStore::ChangeCause::EXPLICIT_DONT_RECORD, false},
// DELETE_COOKIE_EVICTED_DOMAIN
{CookieStore::ChangeCause::EVICTED, true},
// DELETE_COOKIE_EVICTED_GLOBAL
@@ -300,7 +300,7 @@ const ChangeCausePair kChangeCauseMapping[] = {
// DELETE_COOKIE_NON_SECURE
{CookieStore::ChangeCause::EVICTED, true},
// DELETE_COOKIE_LAST_ENTRY
- {CookieStore::ChangeCause::EXPLICIT, false}};
+ {CookieStore::ChangeCause::EXPLICIT_LAST_ENTRY, false}};
void RunAsync(scoped_refptr<base::TaskRunner> proxy,
const CookieStore::CookieChangedCallback& callback,
diff --git a/chromium/net/cookies/cookie_monster.h b/chromium/net/cookies/cookie_monster.h
index 8dea3d32903..d509c41203d 100644
--- a/chromium/net/cookies/cookie_monster.h
+++ b/chromium/net/cookies/cookie_monster.h
@@ -22,7 +22,6 @@
#include "base/callback_forward.h"
#include "base/gtest_prod_util.h"
#include "base/macros.h"
-#include "base/memory/linked_ptr.h"
#include "base/memory/ref_counted.h"
#include "base/memory/weak_ptr.h"
#include "base/threading/thread_checker.h"
diff --git a/chromium/net/cookies/cookie_monster_unittest.cc b/chromium/net/cookies/cookie_monster_unittest.cc
index 2c5ae97212b..52812d332da 100644
--- a/chromium/net/cookies/cookie_monster_unittest.cc
+++ b/chromium/net/cookies/cookie_monster_unittest.cc
@@ -23,6 +23,7 @@
#include "base/strings/string_tokenizer.h"
#include "base/strings/stringprintf.h"
#include "base/test/histogram_tester.h"
+#include "base/test/mock_callback.h"
#include "base/threading/thread.h"
#include "base/threading/thread_task_runner_handle.h"
#include "base/time/time.h"
@@ -809,46 +810,14 @@ using CookieMonsterStrictSecureTest =
// TODO(erikwright): Replace the other callbacks and synchronous helper methods
// in this test suite with these Mocks.
-template <typename T, typename C>
-class MockCookieCallback {
- public:
- C AsCallback() {
- return base::Bind(&T::Invoke, base::Unretained(static_cast<T*>(this)));
- }
-};
-
-class MockGetCookiesCallback
- : public MockCookieCallback<MockGetCookiesCallback,
- CookieStore::GetCookiesCallback> {
- public:
- MOCK_METHOD1(Invoke, void(const std::string& cookies));
-};
-
-class MockSetCookiesCallback
- : public MockCookieCallback<MockSetCookiesCallback,
- CookieStore::SetCookiesCallback> {
- public:
- MOCK_METHOD1(Invoke, void(bool success));
-};
-
-class MockClosure : public MockCookieCallback<MockClosure, base::Closure> {
- public:
- MOCK_METHOD0(Invoke, void(void));
-};
-
-class MockGetCookieListCallback
- : public MockCookieCallback<MockGetCookieListCallback,
- CookieMonster::GetCookieListCallback> {
- public:
- MOCK_METHOD1(Invoke, void(const CookieList& cookies));
-};
-
-class MockDeleteCallback
- : public MockCookieCallback<MockDeleteCallback,
- CookieMonster::DeleteCallback> {
- public:
- MOCK_METHOD1(Invoke, void(int num_deleted));
-};
+using MockClosure = base::MockCallback<base::Closure>;
+using MockGetCookiesCallback =
+ base::MockCallback<CookieStore::GetCookiesCallback>;
+using MockSetCookiesCallback =
+ base::MockCallback<CookieStore::SetCookiesCallback>;
+using MockGetCookieListCallback =
+ base::MockCallback<CookieMonster::GetCookieListCallback>;
+using MockDeleteCallback = base::MockCallback<CookieMonster::DeleteCallback>;
struct CookiesInputInfo {
const GURL url;
@@ -870,18 +839,18 @@ ACTION_P(QuitRunLoop, run_loop) {
// TODO(erikwright): When the synchronous helpers 'GetCookies' etc. are removed,
// rename these, removing the 'Action' suffix.
ACTION_P4(DeleteCookieAction, cookie_monster, url, name, callback) {
- cookie_monster->DeleteCookieAsync(url, name, callback->AsCallback());
+ cookie_monster->DeleteCookieAsync(url, name, callback->Get());
}
ACTION_P3(GetCookiesAction, cookie_monster, url, callback) {
cookie_monster->GetCookiesWithOptionsAsync(url, CookieOptions(),
- callback->AsCallback());
+ callback->Get());
}
ACTION_P4(SetCookieAction, cookie_monster, url, cookie_line, callback) {
cookie_monster->SetCookieWithOptionsAsync(url, cookie_line, CookieOptions(),
- callback->AsCallback());
+ callback->Get());
}
ACTION_P3(SetAllCookiesAction, cookie_monster, list, callback) {
- cookie_monster->SetAllCookiesAsync(list, callback->AsCallback());
+ cookie_monster->SetAllCookiesAsync(list, callback->Get());
}
ACTION_P4(DeleteAllCreatedBetweenAction,
cookie_monster,
@@ -889,18 +858,17 @@ ACTION_P4(DeleteAllCreatedBetweenAction,
delete_end,
callback) {
cookie_monster->DeleteAllCreatedBetweenAsync(delete_begin, delete_end,
- callback->AsCallback());
+ callback->Get());
}
ACTION_P3(SetCookieWithDetailsAction, cookie_monster, cc, callback) {
cookie_monster->SetCookieWithDetailsAsync(
cc.url, cc.name, cc.value, cc.domain, cc.path, base::Time(),
cc.expiration_time, base::Time(), cc.secure, cc.http_only, cc.same_site,
- false /* enforces strict secure cookies */, cc.priority,
- callback->AsCallback());
+ false /* enforces strict secure cookies */, cc.priority, callback->Get());
}
ACTION_P2(GetAllCookiesAction, cookie_monster, callback) {
- cookie_monster->GetAllCookiesAsync(callback->AsCallback());
+ cookie_monster->GetAllCookiesAsync(callback->Get());
}
ACTION_P5(DeleteAllCreatedBetweenWithPredicateAction,
@@ -910,24 +878,24 @@ ACTION_P5(DeleteAllCreatedBetweenWithPredicateAction,
predicate,
callback) {
cookie_monster->DeleteAllCreatedBetweenWithPredicateAsync(
- delete_begin, delete_end, predicate, callback->AsCallback());
+ delete_begin, delete_end, predicate, callback->Get());
}
ACTION_P3(DeleteCanonicalCookieAction, cookie_monster, cookie, callback) {
- cookie_monster->DeleteCanonicalCookieAsync(cookie, callback->AsCallback());
+ cookie_monster->DeleteCanonicalCookieAsync(cookie, callback->Get());
}
ACTION_P2(DeleteAllAction, cookie_monster, callback) {
- cookie_monster->DeleteAllAsync(callback->AsCallback());
+ cookie_monster->DeleteAllAsync(callback->Get());
}
ACTION_P3(GetCookieListForUrlWithOptionsAction, cookie_monster, url, callback) {
cookie_monster->GetCookieListWithOptionsAsync(url, CookieOptions(),
- callback->AsCallback());
+ callback->Get());
}
ACTION_P3(GetAllCookiesForUrlAction, cookie_monster, url, callback) {
- cookie_monster->GetAllCookiesForURLAsync(url, callback->AsCallback());
+ cookie_monster->GetAllCookiesForURLAsync(url, callback->Get());
}
ACTION_P(PushCallbackAction, callback_vector) {
@@ -935,7 +903,7 @@ ACTION_P(PushCallbackAction, callback_vector) {
}
ACTION_P2(DeleteSessionCookiesAction, cookie_monster, callback) {
- cookie_monster->DeleteSessionCookiesAsync(callback->AsCallback());
+ cookie_monster->DeleteSessionCookiesAsync(callback->Get());
}
} // namespace
@@ -1059,11 +1027,11 @@ TEST_F(DeferredCookieTaskTest, DeferredGetCookies) {
WaitForLoadCall();
- EXPECT_CALL(get_cookies_callback, Invoke("X=1"))
+ EXPECT_CALL(get_cookies_callback, Run("X=1"))
.WillOnce(GetCookiesAction(&cookie_monster(), http_www_google_.url(),
&get_cookies_callback));
base::RunLoop loop;
- EXPECT_CALL(get_cookies_callback, Invoke("X=1")).WillOnce(QuitRunLoop(&loop));
+ EXPECT_CALL(get_cookies_callback, Run("X=1")).WillOnce(QuitRunLoop(&loop));
CompleteLoading();
loop.Run();
@@ -1079,11 +1047,11 @@ TEST_F(DeferredCookieTaskTest, DeferredSetCookie) {
WaitForLoadCall();
- EXPECT_CALL(set_cookies_callback, Invoke(true))
+ EXPECT_CALL(set_cookies_callback, Run(true))
.WillOnce(SetCookieAction(&cookie_monster(), http_www_google_.url(),
"X=Y", &set_cookies_callback));
base::RunLoop loop;
- EXPECT_CALL(set_cookies_callback, Invoke(true)).WillOnce(QuitRunLoop(&loop));
+ EXPECT_CALL(set_cookies_callback, Run(true)).WillOnce(QuitRunLoop(&loop));
CompleteLoading();
loop.Run();
@@ -1106,11 +1074,11 @@ TEST_F(DeferredCookieTaskTest, DeferredSetAllCookies) {
WaitForLoadCall();
- EXPECT_CALL(set_cookies_callback, Invoke(true))
+ EXPECT_CALL(set_cookies_callback, Run(true))
.WillOnce(
SetAllCookiesAction(&cookie_monster(), list, &set_cookies_callback));
base::RunLoop loop;
- EXPECT_CALL(set_cookies_callback, Invoke(true)).WillOnce(QuitRunLoop(&loop));
+ EXPECT_CALL(set_cookies_callback, Run(true)).WillOnce(QuitRunLoop(&loop));
CompleteLoading();
loop.Run();
@@ -1126,11 +1094,11 @@ TEST_F(DeferredCookieTaskTest, DeferredDeleteCookie) {
WaitForLoadCall();
- EXPECT_CALL(delete_cookie_callback, Invoke())
+ EXPECT_CALL(delete_cookie_callback, Run())
.WillOnce(DeleteCookieAction(&cookie_monster(), http_www_google_.url(),
"X", &delete_cookie_callback));
base::RunLoop loop;
- EXPECT_CALL(delete_cookie_callback, Invoke()).WillOnce(QuitRunLoop(&loop));
+ EXPECT_CALL(delete_cookie_callback, Run()).WillOnce(QuitRunLoop(&loop));
CompleteLoading();
loop.Run();
@@ -1166,11 +1134,11 @@ TEST_F(DeferredCookieTaskTest, DeferredSetCookieWithDetails) {
false,
CookieSameSite::DEFAULT_MODE,
COOKIE_PRIORITY_DEFAULT};
- EXPECT_CALL(set_cookies_callback, Invoke(true))
+ EXPECT_CALL(set_cookies_callback, Run(true))
.WillOnce(SetCookieWithDetailsAction(&cookie_monster(), cookie_info_exp,
&set_cookies_callback));
base::RunLoop loop;
- EXPECT_CALL(set_cookies_callback, Invoke(true)).WillOnce(QuitRunLoop(&loop));
+ EXPECT_CALL(set_cookies_callback, Run(true)).WillOnce(QuitRunLoop(&loop));
CompleteLoading();
loop.Run();
@@ -1187,11 +1155,11 @@ TEST_F(DeferredCookieTaskTest, DeferredGetAllCookies) {
WaitForLoadCall();
- EXPECT_CALL(get_cookie_list_callback, Invoke(testing::_))
+ EXPECT_CALL(get_cookie_list_callback, Run(testing::_))
.WillOnce(
GetAllCookiesAction(&cookie_monster(), &get_cookie_list_callback));
base::RunLoop loop;
- EXPECT_CALL(get_cookie_list_callback, Invoke(testing::_))
+ EXPECT_CALL(get_cookie_list_callback, Run(testing::_))
.WillOnce(QuitRunLoop(&loop));
CompleteLoading();
@@ -1212,12 +1180,12 @@ TEST_F(DeferredCookieTaskTest, DeferredGetAllForUrlCookies) {
WaitForLoadCall();
- EXPECT_CALL(get_cookie_list_callback, Invoke(testing::_))
+ EXPECT_CALL(get_cookie_list_callback, Run(testing::_))
.WillOnce(GetAllCookiesForUrlAction(&cookie_monster(),
http_www_google_.url(),
&get_cookie_list_callback));
base::RunLoop loop;
- EXPECT_CALL(get_cookie_list_callback, Invoke(testing::_))
+ EXPECT_CALL(get_cookie_list_callback, Run(testing::_))
.WillOnce(QuitRunLoop(&loop));
CompleteLoading();
@@ -1238,12 +1206,12 @@ TEST_F(DeferredCookieTaskTest, DeferredGetAllForUrlWithOptionsCookies) {
WaitForLoadCall();
- EXPECT_CALL(get_cookie_list_callback, Invoke(testing::_))
+ EXPECT_CALL(get_cookie_list_callback, Run(testing::_))
.WillOnce(GetCookieListForUrlWithOptionsAction(
&cookie_monster(), http_www_google_.url(),
&get_cookie_list_callback));
base::RunLoop loop;
- EXPECT_CALL(get_cookie_list_callback, Invoke(testing::_))
+ EXPECT_CALL(get_cookie_list_callback, Run(testing::_))
.WillOnce(QuitRunLoop(&loop));
CompleteLoading();
@@ -1257,11 +1225,11 @@ TEST_F(DeferredCookieTaskTest, DeferredDeleteAllCookies) {
WaitForLoadCall();
- EXPECT_CALL(delete_callback, Invoke(false))
+ EXPECT_CALL(delete_callback, Run(false))
.WillOnce(DeleteAllAction(&cookie_monster(), &delete_callback));
base::RunLoop loop;
- EXPECT_CALL(delete_callback, Invoke(false)).WillOnce(QuitRunLoop(&loop));
+ EXPECT_CALL(delete_callback, Run(false)).WillOnce(QuitRunLoop(&loop));
CompleteLoading();
loop.Run();
@@ -1275,12 +1243,12 @@ TEST_F(DeferredCookieTaskTest, DeferredDeleteAllCreatedBetweenCookies) {
WaitForLoadCall();
- EXPECT_CALL(delete_callback, Invoke(false))
+ EXPECT_CALL(delete_callback, Run(false))
.WillOnce(DeleteAllCreatedBetweenAction(&cookie_monster(), base::Time(),
base::Time::Now(),
&delete_callback));
base::RunLoop loop;
- EXPECT_CALL(delete_callback, Invoke(false)).WillOnce(QuitRunLoop(&loop));
+ EXPECT_CALL(delete_callback, Run(false)).WillOnce(QuitRunLoop(&loop));
CompleteLoading();
loop.Run();
@@ -1298,12 +1266,12 @@ TEST_F(DeferredCookieTaskTest,
WaitForLoadCall();
- EXPECT_CALL(delete_callback, Invoke(false))
+ EXPECT_CALL(delete_callback, Run(false))
.WillOnce(DeleteAllCreatedBetweenWithPredicateAction(
&cookie_monster(), base::Time(), base::Time::Now(), predicate,
&delete_callback));
base::RunLoop loop;
- EXPECT_CALL(delete_callback, Invoke(false)).WillOnce(QuitRunLoop(&loop));
+ EXPECT_CALL(delete_callback, Run(false)).WillOnce(QuitRunLoop(&loop));
CompleteLoading();
loop.Run();
@@ -1321,11 +1289,11 @@ TEST_F(DeferredCookieTaskTest, DeferredDeleteCanonicalCookie) {
WaitForLoadCall();
- EXPECT_CALL(delete_cookie_callback, Invoke(0))
+ EXPECT_CALL(delete_cookie_callback, Run(0))
.WillOnce(DeleteCanonicalCookieAction(&cookie_monster(), *cookie,
&delete_cookie_callback));
base::RunLoop loop;
- EXPECT_CALL(delete_cookie_callback, Invoke(0)).WillOnce(QuitRunLoop(&loop));
+ EXPECT_CALL(delete_cookie_callback, Run(0)).WillOnce(QuitRunLoop(&loop));
CompleteLoading();
loop.Run();
@@ -1338,11 +1306,11 @@ TEST_F(DeferredCookieTaskTest, DeferredDeleteSessionCookies) {
WaitForLoadCall();
- EXPECT_CALL(delete_callback, Invoke(false))
+ EXPECT_CALL(delete_callback, Run(false))
.WillOnce(
DeleteSessionCookiesAction(&cookie_monster(), &delete_callback));
base::RunLoop loop;
- EXPECT_CALL(delete_callback, Invoke(false)).WillOnce(QuitRunLoop(&loop));
+ EXPECT_CALL(delete_callback, Run(false)).WillOnce(QuitRunLoop(&loop));
CompleteLoading();
loop.Run();
@@ -1371,12 +1339,12 @@ TEST_F(DeferredCookieTaskTest, DeferredTaskOrder) {
Begin();
WaitForLoadCall();
- EXPECT_CALL(get_cookies_callback, Invoke("X=1"))
+ EXPECT_CALL(get_cookies_callback, Run("X=1"))
.WillOnce(GetCookiesAction(&cookie_monster(), http_www_google_.url(),
&get_cookies_callback_deferred));
- EXPECT_CALL(set_cookies_callback, Invoke(true));
+ EXPECT_CALL(set_cookies_callback, Run(true));
base::RunLoop loop;
- EXPECT_CALL(get_cookies_callback_deferred, Invoke("A=B; X=1"))
+ EXPECT_CALL(get_cookies_callback_deferred, Run("A=B; X=1"))
.WillOnce(QuitRunLoop(&loop));
CompleteLoading();
@@ -3430,7 +3398,7 @@ TEST_F(CookieMonsterNotificationTest, NotifyOnDelete) {
EXPECT_EQ("abc", cookies[1].Name());
EXPECT_EQ("def", cookies[1].Value());
- EXPECT_EQ(CookieStore::ChangeCause::EXPLICIT, causes[1]);
+ EXPECT_EQ(CookieStore::ChangeCause::EXPLICIT_DELETE, causes[1]);
}
TEST_F(CookieMonsterNotificationTest, NotifyOnUpdate) {
diff --git a/chromium/net/cookies/cookie_store.h b/chromium/net/cookies/cookie_store.h
index 2b036b94024..63241b5e59a 100644
--- a/chromium/net/cookies/cookie_store.h
+++ b/chromium/net/cookies/cookie_store.h
@@ -22,8 +22,6 @@ class GURL;
namespace net {
-class CookieMonster;
-
// An interface for storing and retrieving cookies. Implementations are not
// thread safe, as with most other net classes. All methods must be invoked on
// the network thread, and all callbacks will be calle there.
@@ -38,7 +36,14 @@ class NET_EXPORT CookieStore {
// The cookie was inserted.
INSERTED,
// The cookie was changed directly by a consumer's action.
- EXPLICIT,
+ // The following enum values all have the same meaning, but are being used
+ // to track down where a bug came from.
+ // TODO(nharper): Remove all but one of these and rename to EXPLICIT once
+ // the one of interest has been found.
+ EXPLICIT_DELETE,
+ EXPLICIT_DUPLICATE_IN_BACKING_STORE,
+ EXPLICIT_DONT_RECORD,
+ EXPLICIT_LAST_ENTRY,
// The cookie was deleted, but no more details are known.
UNKNOWN_DELETION,
// The cookie was automatically removed due to an insert operation that
diff --git a/chromium/net/cookies/parsed_cookie.h b/chromium/net/cookies/parsed_cookie.h
index aed763502c1..ccb30d8ed06 100644
--- a/chromium/net/cookies/parsed_cookie.h
+++ b/chromium/net/cookies/parsed_cookie.h
@@ -153,4 +153,4 @@ class NET_EXPORT ParsedCookie {
} // namespace net
-#endif // NET_COOKIES_COOKIE_MONSTER_H_
+#endif // NET_COOKIES_PARSED_COOKIE_H_
diff --git a/chromium/net/data/cert_issuer_source_static_unittest/c1.pem b/chromium/net/data/cert_issuer_source_static_unittest/c1.pem
index 379c130e66f..a646a3443a1 100644
--- a/chromium/net/data/cert_issuer_source_static_unittest/c1.pem
+++ b/chromium/net/data/cert_issuer_source_static_unittest/c1.pem
@@ -14,30 +14,30 @@ Certificate:
Public Key Algorithm: rsaEncryption
Public-Key: (2048 bit)
Modulus:
- 00:ad:79:b8:ba:9b:81:f0:0e:08:a2:3d:f8:20:ee:
- 9a:96:1a:5d:81:63:42:ed:a4:82:b2:80:5b:0b:d8:
- 9f:47:9c:96:d3:b6:53:5f:5f:86:ce:70:70:2b:58:
- 75:95:12:f7:0e:0a:12:67:35:2d:69:56:f8:15:18:
- f1:4d:87:2e:9a:6e:00:19:b9:4b:67:22:46:04:f0:
- ba:d0:07:c5:d7:60:47:f2:b3:ba:a0:5e:96:ec:5e:
- dc:58:ee:1a:6a:3d:1e:e9:16:17:20:59:97:7b:18:
- 80:0c:58:2b:aa:71:be:aa:3e:54:7b:57:93:10:8d:
- 25:37:50:77:5c:17:4c:a2:8a:4e:db:41:18:ce:10:
- 84:32:1e:8b:be:ee:23:3a:7c:d5:cb:54:1e:15:66:
- f4:12:69:10:86:0a:77:28:3a:9e:58:6c:06:0d:2a:
- a1:3b:f6:05:f4:e3:32:d0:2a:f5:33:04:e8:b3:71:
- 9e:40:59:7d:62:5f:4b:9a:0b:c0:12:32:c9:e9:33:
- 5f:f1:d3:a5:e7:fe:01:77:13:d4:33:65:54:66:9f:
- 46:c0:6b:e4:93:62:bc:0a:15:29:6e:b0:a2:13:4f:
- cb:73:78:fd:3f:a5:d4:70:e0:13:8b:17:c7:d1:08:
- 1f:24:8c:83:87:b8:0c:d1:d7:9a:ea:23:3e:61:ef:
- 6e:ab
+ 00:bb:13:e9:bf:8b:1d:f4:75:aa:64:73:cd:df:75:
+ d7:37:79:44:01:6e:57:50:87:9a:17:d0:36:e7:12:
+ 29:67:47:e2:7b:ff:a1:0c:36:04:a7:dd:7a:a4:7e:
+ 33:c3:12:6c:56:dd:48:b5:07:83:b6:9c:f1:41:d2:
+ 72:24:63:d0:08:f8:d3:bf:ea:c7:d2:89:9f:10:57:
+ 04:ab:63:a5:e0:4b:53:86:a3:05:be:9f:86:b0:b9:
+ 09:c7:77:20:36:f1:03:f1:46:ef:13:d4:d1:39:11:
+ 0f:7c:3d:e4:a4:9a:53:9b:f1:2a:7a:1c:52:b7:0c:
+ 72:38:ea:f7:97:4d:a3:dd:aa:90:77:d6:0f:59:90:
+ ce:5e:ea:f6:4c:38:9c:15:22:23:dc:36:59:78:24:
+ ca:79:80:f4:60:4e:46:ac:dc:f5:22:1d:49:40:51:
+ af:a5:e1:da:1b:8f:81:a7:b0:5b:8e:49:19:06:a7:
+ 83:a7:22:d0:15:0d:8c:e9:b0:1d:4f:e6:68:e4:ac:
+ db:31:50:6c:8f:00:f0:cb:30:d5:e5:65:61:ee:6e:
+ 9c:3a:f5:62:2c:ab:c1:1d:44:c7:de:10:a1:c6:a6:
+ a2:89:37:66:ab:ff:06:6f:a6:60:d7:36:2b:b7:5a:
+ 36:72:6b:85:fe:79:4a:63:f4:4e:ef:24:09:0c:42:
+ 28:c3
Exponent: 65537 (0x10001)
X509v3 extensions:
X509v3 Subject Key Identifier:
- 0F:82:42:07:C8:05:DD:6F:B7:77:F2:63:C3:D8:5C:44:62:80:09:36
+ 03:19:93:1B:92:8F:1C:2D:2E:A5:71:01:0D:D0:DF:56:D4:7E:EF:8D
X509v3 Authority Key Identifier:
- keyid:AD:51:13:DE:24:4F:02:2A:BD:20:69:DE:9C:8C:18:83:9E:4B:D1:D0
+ keyid:84:17:CE:FE:EA:88:CB:E4:D7:19:40:7A:01:E3:62:84:3D:C6:05:EB
Authority Information Access:
CA Issuers - URI:http://url-for-aia/I1.cer
@@ -52,39 +52,39 @@ Certificate:
X509v3 Extended Key Usage:
TLS Web Server Authentication, TLS Web Client Authentication
Signature Algorithm: sha256WithRSAEncryption
- 81:a6:81:fb:64:58:22:70:91:e7:0b:2b:08:01:39:ef:01:d9:
- ac:a2:5e:11:b9:fa:6e:ea:20:77:cc:4f:de:8b:d2:7d:18:47:
- 65:58:d4:61:ba:3f:36:04:2f:25:c6:3b:cf:3e:e5:c6:45:b4:
- 4c:56:5f:68:1d:3a:da:21:10:fc:3a:9f:03:58:b0:0e:da:17:
- 5b:37:15:c5:02:f9:e6:9a:4b:b9:c7:6b:70:2f:2b:9e:d8:c2:
- 39:58:4f:87:06:f9:1a:cd:bc:1c:72:a2:36:f6:fd:4b:2c:d8:
- a5:36:a8:28:a7:a7:5d:48:d0:87:b7:9f:3b:2d:3e:a6:fe:7a:
- d1:43:3a:c1:32:24:eb:a4:1f:3e:36:9f:ee:5c:86:03:76:de:
- 7f:aa:a8:2d:d8:ed:09:b8:c9:dc:33:1d:55:e8:41:d6:dc:53:
- fe:90:7d:11:20:75:7a:ea:80:09:1f:fb:c5:cf:36:0b:cc:a5:
- 4c:1b:8c:16:e3:8a:09:c2:e5:33:79:85:5e:92:27:0d:20:b6:
- 4d:01:c0:b0:05:fb:c0:bb:f3:d1:c4:51:1d:a1:41:16:4a:0e:
- 48:8d:e1:ef:d1:40:30:fe:a3:4b:39:12:2c:6d:32:e1:7a:5f:
- 84:aa:e6:80:8d:fd:f1:4b:21:cc:51:da:a6:c4:a7:78:2b:31:
- be:87:f5:e3
+ b7:7c:3d:49:2c:c9:e7:5b:98:21:11:ae:ff:f1:b8:ec:b1:f6:
+ 59:8b:d0:9c:0c:de:81:89:fe:35:aa:73:8c:56:67:82:bb:0f:
+ 04:c5:3f:c2:4b:72:2f:29:ae:69:37:0e:86:46:fb:73:af:70:
+ 8f:36:c3:ad:10:05:41:78:fc:29:9a:79:1d:ce:ff:cc:ec:87:
+ 8b:ee:da:72:6d:27:7c:7e:44:11:20:79:e0:bd:55:c5:dd:e5:
+ 9b:1a:ce:dc:8f:9b:25:7d:a1:4b:d0:cc:05:42:7a:2e:b4:79:
+ 0b:06:5b:28:39:12:a7:54:42:5c:a9:23:a3:8b:64:2e:96:dd:
+ 35:e0:21:09:ff:60:6d:c1:0b:41:4b:2c:bf:d5:c3:70:64:d0:
+ 0b:8d:b0:79:3a:b7:00:2e:90:f3:aa:e9:ff:3f:3c:dc:26:7b:
+ 7e:3e:90:7c:cc:96:d0:4a:f8:8d:b5:e7:49:59:fe:93:c9:8a:
+ 53:75:db:da:3e:46:af:7c:8b:b6:c8:7a:dd:88:ce:5b:2d:50:
+ 01:5e:3c:1a:a0:20:b6:4e:60:4c:10:a9:74:d0:36:a0:c6:c8:
+ 14:d7:3d:1a:11:8d:a3:0b:8a:3a:e2:27:76:c2:bb:26:4c:61:
+ 29:1d:10:6d:8b:b4:67:a6:66:db:43:76:a0:49:dc:ab:21:64:
+ 28:5d:d6:cb
-----BEGIN CERTIFICATE-----
MIIDazCCAlOgAwIBAgIBATANBgkqhkiG9w0BAQsFADANMQswCQYDVQQDDAJJMTAe
Fw0xNTAxMDExMjAwMDBaFw0xNjAxMDExMjAwMDBaMA0xCzAJBgNVBAMMAkMxMIIB
-IjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEArXm4upuB8A4Ioj34IO6alhpd
-gWNC7aSCsoBbC9ifR5yW07ZTX1+GznBwK1h1lRL3DgoSZzUtaVb4FRjxTYcumm4A
-GblLZyJGBPC60AfF12BH8rO6oF6W7F7cWO4aaj0e6RYXIFmXexiADFgrqnG+qj5U
-e1eTEI0lN1B3XBdMoopO20EYzhCEMh6Lvu4jOnzVy1QeFWb0EmkQhgp3KDqeWGwG
-DSqhO/YF9OMy0Cr1MwTos3GeQFl9Yl9LmgvAEjLJ6TNf8dOl5/4BdxPUM2VUZp9G
-wGvkk2K8ChUpbrCiE0/Lc3j9P6XUcOATixfH0QgfJIyDh7gM0dea6iM+Ye9uqwID
-AQABo4HVMIHSMB0GA1UdDgQWBBQPgkIHyAXdb7d38mPD2FxEYoAJNjAfBgNVHSME
-GDAWgBStURPeJE8CKr0gad6cjBiDnkvR0DA1BggrBgEFBQcBAQQpMCcwJQYIKwYB
+IjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAuxPpv4sd9HWqZHPN33XXN3lE
+AW5XUIeaF9A25xIpZ0fie/+hDDYEp916pH4zwxJsVt1ItQeDtpzxQdJyJGPQCPjT
+v+rH0omfEFcEq2Ol4EtThqMFvp+GsLkJx3cgNvED8UbvE9TROREPfD3kpJpTm/Eq
+ehxStwxyOOr3l02j3aqQd9YPWZDOXur2TDicFSIj3DZZeCTKeYD0YE5GrNz1Ih1J
+QFGvpeHaG4+Bp7BbjkkZBqeDpyLQFQ2M6bAdT+Zo5KzbMVBsjwDwyzDV5WVh7m6c
+OvViLKvBHUTH3hChxqaiiTdmq/8Gb6Zg1zYrt1o2cmuF/nlKY/RO7yQJDEIowwID
+AQABo4HVMIHSMB0GA1UdDgQWBBQDGZMbko8cLS6lcQEN0N9W1H7vjTAfBgNVHSME
+GDAWgBSEF87+6ojL5NcZQHoB42KEPcYF6zA1BggrBgEFBQcBAQQpMCcwJQYIKwYB
BQUHMAKGGWh0dHA6Ly91cmwtZm9yLWFpYS9JMS5jZXIwKgYDVR0fBCMwITAfoB2g
G4YZaHR0cDovL3VybC1mb3ItY3JsL0kxLmNybDAOBgNVHQ8BAf8EBAMCBaAwHQYD
-VR0lBBYwFAYIKwYBBQUHAwEGCCsGAQUFBwMCMA0GCSqGSIb3DQEBCwUAA4IBAQCB
-poH7ZFgicJHnCysIATnvAdmsol4Rufpu6iB3zE/ei9J9GEdlWNRhuj82BC8lxjvP
-PuXGRbRMVl9oHTraIRD8Op8DWLAO2hdbNxXFAvnmmku5x2twLyue2MI5WE+HBvka
-zbwccqI29v1LLNilNqgop6ddSNCHt587LT6m/nrRQzrBMiTrpB8+Np/uXIYDdt5/
-qqgt2O0JuMncMx1V6EHW3FP+kH0RIHV66oAJH/vFzzYLzKVMG4wW44oJwuUzeYVe
-kicNILZNAcCwBfvAu/PRxFEdoUEWSg5IjeHv0UAw/qNLORIsbTLhel+EquaAjf3x
-SyHMUdqmxKd4KzG+h/Xj
+VR0lBBYwFAYIKwYBBQUHAwEGCCsGAQUFBwMCMA0GCSqGSIb3DQEBCwUAA4IBAQC3
+fD1JLMnnW5ghEa7/8bjssfZZi9CcDN6Bif41qnOMVmeCuw8ExT/CS3IvKa5pNw6G
+Rvtzr3CPNsOtEAVBePwpmnkdzv/M7IeL7tpybSd8fkQRIHngvVXF3eWbGs7cj5sl
+faFL0MwFQnoutHkLBlsoORKnVEJcqSOji2Qult014CEJ/2BtwQtBSyy/1cNwZNAL
+jbB5OrcALpDzqun/PzzcJnt+PpB8zJbQSviNtedJWf6TyYpTddvaPkavfIu2yHrd
+iM5bLVABXjwaoCC2TmBMEKl00DagxsgU1z0aEY2jC4o64id2wrsmTGEpHRBti7Rn
+pmbbQ3agSdyrIWQoXdbL
-----END CERTIFICATE-----
diff --git a/chromium/net/data/cert_issuer_source_static_unittest/c2.pem b/chromium/net/data/cert_issuer_source_static_unittest/c2.pem
index 431c139ed32..935a8648bb9 100644
--- a/chromium/net/data/cert_issuer_source_static_unittest/c2.pem
+++ b/chromium/net/data/cert_issuer_source_static_unittest/c2.pem
@@ -14,30 +14,30 @@ Certificate:
Public Key Algorithm: rsaEncryption
Public-Key: (2048 bit)
Modulus:
- 00:f4:4c:af:e3:23:18:0e:c6:ce:4e:16:5a:b4:05:
- 0c:86:5b:f8:0e:1e:78:03:ef:14:72:37:92:22:15:
- d5:d4:9b:6c:5d:f3:57:a0:8c:fb:e8:72:ae:c1:75:
- 32:4d:a2:db:21:b8:a3:9a:08:6d:14:f4:b0:9d:b6:
- 41:67:a3:45:50:e6:a9:5d:0f:8a:c2:84:b1:28:91:
- 18:ef:ea:fe:8b:6c:a2:c1:32:3d:11:ac:c3:60:7b:
- 93:61:f8:be:9c:9d:6b:0d:fb:3d:b7:d2:a0:1d:29:
- 6e:1d:bc:ce:e9:05:3e:b3:a8:88:13:08:11:4e:61:
- 22:c7:b8:eb:d4:00:c4:66:99:c6:60:b0:13:d0:c1:
- 79:7f:1b:86:f2:0d:f4:f7:d4:bb:31:0b:f1:9c:1c:
- 8d:4a:01:e6:31:53:9d:12:37:f9:ed:b2:01:6a:fb:
- b5:07:3e:74:19:a9:61:b7:0a:46:4e:5d:66:80:f0:
- dd:0b:e7:ad:18:c4:30:6a:78:60:2a:28:61:16:b1:
- 86:fd:24:a2:40:60:e8:45:0c:ad:9f:fb:e2:eb:07:
- 45:34:7b:93:b2:a7:a7:d5:81:8d:89:f5:82:83:05:
- 6f:c5:71:45:5b:c8:31:88:9c:b4:d4:dc:2e:8a:b7:
- 08:6e:c8:70:02:35:6f:0f:7f:1c:fa:d7:15:7e:ce:
- 92:7b
+ 00:dc:0c:20:7f:23:ae:ea:7d:0c:20:23:32:e1:b0:
+ 2d:e0:5d:95:b9:5f:89:95:f9:98:5a:df:96:4d:1d:
+ 66:43:47:15:61:6d:ab:0e:1a:fc:94:46:82:4e:12:
+ ca:9d:b2:99:78:a1:45:39:4d:6e:6f:5c:ba:c0:62:
+ ff:93:3e:0d:57:c4:86:4e:0f:fc:7b:7e:01:de:38:
+ 72:fb:f2:7f:e3:60:f8:0d:42:c3:4f:31:24:3f:96:
+ d1:73:ac:02:87:f6:30:ab:ec:8a:0e:c2:a5:cf:dd:
+ e7:91:83:8d:9e:2a:e8:c7:26:6f:0d:d1:ef:54:6f:
+ a3:91:80:bf:87:0f:77:f7:be:fd:6f:e9:a1:3d:42:
+ 15:0c:fa:0e:95:7c:de:a3:5e:f2:28:e3:bc:fd:3f:
+ 27:6d:30:89:e3:51:8a:f4:7f:72:b1:e6:48:12:1e:
+ 02:d8:b2:fe:64:64:4d:65:17:61:18:5f:1a:f8:f0:
+ eb:88:35:c8:ad:d0:ed:b4:c6:e3:09:3e:e3:ef:8e:
+ 40:a1:c7:f3:46:d5:50:a2:ff:ae:49:a4:52:65:4d:
+ 81:0f:57:ea:92:a6:64:74:90:17:67:82:ca:17:52:
+ 71:5a:d6:85:65:fe:f0:c7:ff:bb:7b:3d:a0:95:af:
+ 4c:64:17:56:7f:fe:b9:01:cd:db:b0:df:08:18:c1:
+ 5f:f3
Exponent: 65537 (0x10001)
X509v3 extensions:
X509v3 Subject Key Identifier:
- 42:9A:C2:7B:BB:94:1E:50:73:FD:C3:7C:D8:C1:CA:7D:78:81:2A:19
+ 17:8F:59:67:1C:97:6D:5F:5E:91:F1:28:D2:2F:37:9E:46:0F:A9:8D
X509v3 Authority Key Identifier:
- keyid:F9:72:F0:81:01:06:00:24:81:09:78:86:EB:FF:E1:51:82:0A:A8:44
+ keyid:0C:6A:CE:BB:AC:0D:C3:03:19:28:BF:63:76:72:0B:3D:89:5B:D3:B7
Authority Information Access:
CA Issuers - URI:http://url-for-aia/i1.cer
@@ -52,39 +52,39 @@ Certificate:
X509v3 Extended Key Usage:
TLS Web Server Authentication, TLS Web Client Authentication
Signature Algorithm: sha256WithRSAEncryption
- 2e:4a:94:16:8e:cd:8d:9b:15:98:a1:e2:ba:ef:86:96:df:63:
- a8:a5:3e:79:b6:c3:e2:6b:58:50:8c:5d:e3:1a:36:cb:82:fe:
- 59:60:a5:58:9b:98:26:49:74:85:db:91:8f:bc:4a:57:c4:c7:
- 33:f0:16:39:54:c4:13:19:03:d8:f9:b0:98:10:e2:7b:93:18:
- f5:39:26:e4:51:9f:12:c0:00:d2:2f:7b:a4:f6:8d:d4:63:af:
- 23:2f:d5:e6:25:53:43:b5:fa:b4:a9:ae:4c:ce:6d:2b:18:87:
- 27:3a:35:93:53:31:14:a3:2c:6c:84:16:29:93:a2:ae:d9:96:
- 20:e3:49:74:b0:2c:cc:5f:e5:e7:9e:70:b7:f9:ba:dc:45:d8:
- 46:10:df:81:ae:39:a4:52:67:2b:a9:b0:19:fb:30:36:0c:cb:
- 17:9a:a7:af:9a:a3:67:b9:bb:e1:4e:d7:7c:2d:0b:2d:12:6a:
- 9e:2c:3b:b9:ef:6c:9b:28:8d:5d:f0:a2:fa:f4:60:67:3a:72:
- fd:d1:4c:cb:65:e6:3a:68:12:e2:3d:99:4d:df:78:bb:69:15:
- 92:46:18:94:60:90:0b:83:a4:4d:b7:fa:fe:14:d5:5f:9a:aa:
- 44:ca:d4:fb:d6:b7:04:7f:ac:2c:33:03:d7:38:6b:16:53:c0:
- db:cf:aa:62
+ 7d:cd:21:c8:a9:3b:3e:d0:8c:47:24:c4:13:1a:ed:9b:b6:1d:
+ 14:d7:00:9e:5a:6c:6b:c0:6c:48:ab:89:ef:94:09:5b:5b:c3:
+ a3:54:43:62:70:12:b2:32:cd:15:ab:e9:69:af:15:02:63:71:
+ b0:9c:6f:ec:67:c9:e1:37:de:1b:ef:b1:5c:2a:95:39:3c:b5:
+ be:e3:e9:61:81:b5:67:b2:8f:17:8c:20:4b:9b:15:86:d4:0d:
+ 3b:00:aa:e7:0c:5a:53:93:73:fa:61:c8:d2:05:7d:22:ef:e4:
+ 3c:45:37:8d:5d:be:83:f8:90:75:33:f0:99:b0:60:36:7c:d4:
+ 09:fa:23:6a:e5:60:a0:89:94:5d:e9:6d:df:d5:b8:c0:8e:08:
+ 3b:20:72:e7:5b:03:84:42:fe:ee:e7:46:63:29:58:c4:9a:9b:
+ 8b:d7:bb:2f:9d:20:5e:5b:04:35:52:79:c6:56:63:d6:44:ae:
+ d9:5f:e6:c0:6b:fe:f5:8f:ff:3d:2b:7b:a7:8c:0e:36:02:79:
+ 7f:cd:c4:a5:f4:99:ff:cb:ca:8e:77:9e:de:c2:40:22:b5:d3:
+ 6d:6c:41:44:ce:b4:21:eb:8c:c3:7f:eb:da:ee:0c:54:9e:5d:
+ 2c:04:da:df:86:4e:34:b2:a4:8f:a8:9f:ab:73:1d:66:f8:ae:
+ e8:76:8d:eb
-----BEGIN CERTIFICATE-----
MIIDazCCAlOgAwIBAgIBATANBgkqhkiG9w0BAQsFADANMQswCQYDVQQDDAJpMTAe
Fw0xNTAxMDExMjAwMDBaFw0xNjAxMDExMjAwMDBaMA0xCzAJBgNVBAMMAkMyMIIB
-IjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA9Eyv4yMYDsbOThZatAUMhlv4
-Dh54A+8UcjeSIhXV1JtsXfNXoIz76HKuwXUyTaLbIbijmghtFPSwnbZBZ6NFUOap
-XQ+KwoSxKJEY7+r+i2yiwTI9EazDYHuTYfi+nJ1rDfs9t9KgHSluHbzO6QU+s6iI
-EwgRTmEix7jr1ADEZpnGYLAT0MF5fxuG8g3099S7MQvxnByNSgHmMVOdEjf57bIB
-avu1Bz50GalhtwpGTl1mgPDdC+etGMQwanhgKihhFrGG/SSiQGDoRQytn/vi6wdF
-NHuTsqen1YGNifWCgwVvxXFFW8gxiJy01NwuircIbshwAjVvD38c+tcVfs6SewID
-AQABo4HVMIHSMB0GA1UdDgQWBBRCmsJ7u5QeUHP9w3zYwcp9eIEqGTAfBgNVHSME
-GDAWgBT5cvCBAQYAJIEJeIbr/+FRggqoRDA1BggrBgEFBQcBAQQpMCcwJQYIKwYB
+IjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA3AwgfyOu6n0MICMy4bAt4F2V
+uV+JlfmYWt+WTR1mQ0cVYW2rDhr8lEaCThLKnbKZeKFFOU1ub1y6wGL/kz4NV8SG
+Tg/8e34B3jhy+/J/42D4DULDTzEkP5bRc6wCh/Ywq+yKDsKlz93nkYONniroxyZv
+DdHvVG+jkYC/hw939779b+mhPUIVDPoOlXzeo17yKOO8/T8nbTCJ41GK9H9yseZI
+Eh4C2LL+ZGRNZRdhGF8a+PDriDXIrdDttMbjCT7j745AocfzRtVQov+uSaRSZU2B
+D1fqkqZkdJAXZ4LKF1JxWtaFZf7wx/+7ez2gla9MZBdWf/65Ac3bsN8IGMFf8wID
+AQABo4HVMIHSMB0GA1UdDgQWBBQXj1lnHJdtX16R8SjSLzeeRg+pjTAfBgNVHSME
+GDAWgBQMas67rA3DAxkov2N2cgs9iVvTtzA1BggrBgEFBQcBAQQpMCcwJQYIKwYB
BQUHMAKGGWh0dHA6Ly91cmwtZm9yLWFpYS9pMS5jZXIwKgYDVR0fBCMwITAfoB2g
G4YZaHR0cDovL3VybC1mb3ItY3JsL2kxLmNybDAOBgNVHQ8BAf8EBAMCBaAwHQYD
-VR0lBBYwFAYIKwYBBQUHAwEGCCsGAQUFBwMCMA0GCSqGSIb3DQEBCwUAA4IBAQAu
-SpQWjs2NmxWYoeK674aW32OopT55tsPia1hQjF3jGjbLgv5ZYKVYm5gmSXSF25GP
-vEpXxMcz8BY5VMQTGQPY+bCYEOJ7kxj1OSbkUZ8SwADSL3uk9o3UY68jL9XmJVND
-tfq0qa5Mzm0rGIcnOjWTUzEUoyxshBYpk6Ku2ZYg40l0sCzMX+XnnnC3+brcRdhG
-EN+BrjmkUmcrqbAZ+zA2DMsXmqevmqNnubvhTtd8LQstEmqeLDu572ybKI1d8KL6
-9GBnOnL90UzLZeY6aBLiPZlN33i7aRWSRhiUYJALg6RNt/r+FNVfmqpEytT71rcE
-f6wsMwPXOGsWU8Dbz6pi
+VR0lBBYwFAYIKwYBBQUHAwEGCCsGAQUFBwMCMA0GCSqGSIb3DQEBCwUAA4IBAQB9
+zSHIqTs+0IxHJMQTGu2bth0U1wCeWmxrwGxIq4nvlAlbW8OjVENicBKyMs0Vq+lp
+rxUCY3GwnG/sZ8nhN94b77FcKpU5PLW+4+lhgbVnso8XjCBLmxWG1A07AKrnDFpT
+k3P6YcjSBX0i7+Q8RTeNXb6D+JB1M/CZsGA2fNQJ+iNq5WCgiZRd6W3f1bjAjgg7
+IHLnWwOEQv7u50ZjKVjEmpuL17svnSBeWwQ1UnnGVmPWRK7ZX+bAa/71j/89K3un
+jA42Anl/zcSl9Jn/y8qOd57ewkAitdNtbEFEzrQh64zDf+va7gxUnl0sBNrfhk40
+sqSPqJ+rcx1m+K7odo3r
-----END CERTIFICATE-----
diff --git a/chromium/net/data/cert_issuer_source_static_unittest/d.pem b/chromium/net/data/cert_issuer_source_static_unittest/d.pem
index a296294cc07..c6bdbb97cff 100644
--- a/chromium/net/data/cert_issuer_source_static_unittest/d.pem
+++ b/chromium/net/data/cert_issuer_source_static_unittest/d.pem
@@ -14,30 +14,30 @@ Certificate:
Public Key Algorithm: rsaEncryption
Public-Key: (2048 bit)
Modulus:
- 00:ec:24:64:8b:27:5d:f1:f0:12:a3:4d:99:9b:ff:
- 39:48:41:4a:5e:a3:c9:15:45:28:31:08:1e:c6:b8:
- d0:25:60:7b:2b:4a:e6:3b:33:e5:fd:76:0a:c1:2b:
- 7c:50:23:b5:15:8c:b6:cc:42:58:b1:1d:59:5e:e8:
- d8:82:1c:c2:f6:e3:e7:1f:2e:ef:0d:d1:36:81:65:
- dd:24:23:43:8b:e5:8e:1b:d3:6a:ad:d9:1d:b6:8f:
- 25:95:37:79:10:86:3c:bd:f3:20:d4:1a:0a:62:19:
- 9a:74:f1:70:7e:01:4e:2d:33:86:80:76:23:cc:f2:
- 2d:35:a3:09:1d:4d:25:bb:db:0f:38:f2:e4:97:be:
- 62:4c:da:8f:7e:de:ae:8b:68:31:6f:db:58:f7:23:
- 29:36:aa:ae:a1:cc:4d:a2:b7:19:91:82:14:ed:c2:
- 84:7e:5c:bc:7e:a8:cb:5e:02:8e:1d:41:29:d1:cf:
- 63:da:a9:15:d9:2b:11:e2:6a:68:0c:54:f4:ab:6b:
- 43:ea:0f:ce:3a:62:04:c0:fd:2c:6e:aa:7d:0d:9a:
- 76:ef:e8:86:e5:70:b7:2f:be:ba:b9:fc:19:e3:17:
- d1:2d:eb:c6:40:83:05:b1:cf:a5:0e:c7:6f:64:a1:
- 68:77:35:ad:d0:7c:f3:6a:cb:15:fd:be:11:39:09:
- bd:73
+ 00:d5:0f:8b:7e:d9:f3:86:97:fc:5f:8a:c7:df:e7:
+ 7e:18:c0:ee:c0:3a:8e:e6:75:65:30:6d:a4:7b:4e:
+ ef:63:82:ac:0c:46:81:ac:42:ff:12:53:06:51:6a:
+ d2:9f:e0:2a:15:cb:3c:80:d3:2a:8b:10:30:ff:0f:
+ bc:47:ab:72:2d:bd:14:06:73:8f:58:ce:4a:64:2f:
+ 41:eb:a6:2f:77:2d:67:04:d7:b9:00:b1:de:8b:9d:
+ 05:a0:b3:8f:46:5d:24:c9:2f:ba:e0:c1:c4:a0:5b:
+ 16:48:6a:f9:a0:0e:82:9b:d4:85:f4:2d:53:07:02:
+ 94:ec:2c:d2:bd:bc:86:c1:dc:3b:d7:a2:12:5e:38:
+ 78:4b:9d:30:4b:16:1b:36:6f:9a:12:93:89:f6:fa:
+ 5f:21:11:7d:ef:b2:ed:03:ab:7c:03:28:48:65:76:
+ 10:8e:b3:46:2b:19:a4:16:32:1a:ed:fe:19:fc:37:
+ 93:9d:65:57:ad:9c:6b:88:26:f6:30:bc:83:22:d6:
+ c0:51:17:2b:e7:79:b1:bc:45:b7:34:4b:ac:3c:40:
+ 8d:83:80:41:88:a4:25:46:ed:00:77:09:4f:39:cf:
+ 98:41:6f:49:ad:25:35:e3:01:98:49:13:7d:5e:f5:
+ 86:84:f1:e4:71:fb:ba:4a:ee:af:31:16:56:1f:f7:
+ df:cf
Exponent: 65537 (0x10001)
X509v3 extensions:
X509v3 Subject Key Identifier:
- 00:6C:9E:D2:DE:E9:FF:0C:B1:50:40:8E:7F:99:09:04:7C:BA:97:33
+ AE:28:BD:DE:6F:60:00:2A:01:59:8F:FD:E6:C5:27:65:CD:01:04:37
X509v3 Authority Key Identifier:
- keyid:FD:5E:CC:AF:B7:44:FD:EA:B3:2A:50:1D:1E:A0:2B:00:1C:E7:D2:84
+ keyid:B7:FB:54:77:0C:76:74:B0:72:84:2F:4E:AF:24:1F:CA:62:8D:99:61
Authority Information Access:
CA Issuers - URI:http://url-for-aia/I2.cer
@@ -52,39 +52,39 @@ Certificate:
X509v3 Extended Key Usage:
TLS Web Server Authentication, TLS Web Client Authentication
Signature Algorithm: sha256WithRSAEncryption
- 32:f9:5a:59:9c:97:81:43:0e:62:e7:4b:52:ef:6e:2d:98:12:
- 01:5e:34:d4:da:6a:da:9f:7e:04:8a:ab:00:89:67:0a:81:f4:
- 5f:9c:80:0c:01:6a:61:5e:b1:65:58:11:91:b8:6e:ee:9b:2d:
- 0f:ee:37:72:8a:e6:33:ba:79:5d:7b:5e:2d:d3:c9:03:83:29:
- 6f:a7:fc:bb:64:3d:5e:ba:37:77:f5:8f:35:b6:0d:dd:f5:50:
- 12:10:75:00:96:db:82:2f:15:f3:fe:f9:16:a8:e5:ff:71:ef:
- 0b:a8:30:5e:a4:fe:e8:9d:d0:43:da:94:64:ad:4b:53:53:4d:
- d1:5b:5a:15:ac:ad:0a:87:81:f1:d5:d2:ca:e7:c6:28:bd:af:
- 29:0a:df:69:0a:29:c9:8c:f4:7b:b2:cd:4c:54:28:ec:80:7a:
- 0b:b7:dc:b6:b6:d6:9d:0c:9f:ff:4b:fa:4e:75:7a:bd:4e:a7:
- 87:1c:ed:19:e1:7e:3e:28:99:92:14:91:0e:7d:8e:e7:49:46:
- 28:8d:42:46:aa:ed:3a:85:30:8b:d9:d0:97:a2:fe:cd:8d:76:
- f9:80:0f:ae:87:d7:f5:79:57:fc:d0:ff:44:12:65:c5:87:02:
- bb:6f:2f:f1:48:e6:0e:1a:12:58:9b:e3:18:ec:99:34:f3:9c:
- ae:d2:da:72
+ 16:1a:ad:91:a8:9a:d5:d2:63:d4:8c:61:73:0e:d4:14:66:ee:
+ ef:4e:cb:f4:40:82:42:95:60:ae:65:59:99:ca:62:47:47:48:
+ 6a:d8:c7:4b:b2:62:a2:c7:45:8a:92:a6:69:0e:f3:7d:8f:9d:
+ 0b:a7:ba:c0:61:80:76:46:ef:2b:80:56:3a:21:1d:e4:52:2d:
+ a0:98:bf:36:cc:36:4e:40:2c:55:48:93:39:e3:d7:54:21:48:
+ ce:03:65:9a:df:59:07:d5:76:5e:5c:25:fb:84:3e:a1:54:98:
+ ad:d4:7d:ff:7e:c5:62:5e:43:c1:33:f8:04:6d:dd:23:b5:8a:
+ 48:55:7a:55:69:a5:da:23:46:a2:58:29:6c:22:05:a2:ea:b0:
+ be:81:5d:6c:a1:9a:7c:41:a1:ae:02:de:4f:87:5b:83:01:81:
+ 4f:ba:dc:5f:0a:04:41:83:da:5d:79:2d:9a:ca:82:84:48:1d:
+ b7:a7:b4:e5:ab:28:6b:33:33:09:fc:d7:d8:80:0d:d6:f6:38:
+ 79:91:44:39:28:b8:bf:ee:4a:43:9b:27:42:7a:f2:e2:3c:4d:
+ 89:1d:21:e0:ce:ec:06:e0:2e:b2:dc:f2:0a:15:7c:33:0b:ec:
+ 36:8e:26:31:0e:f8:f7:e8:3d:07:d7:2c:91:c3:0c:35:7a:76:
+ f3:67:02:c1
-----BEGIN CERTIFICATE-----
MIIDajCCAlKgAwIBAgIBATANBgkqhkiG9w0BAQsFADANMQswCQYDVQQDDAJJMjAe
Fw0xNTAxMDExMjAwMDBaFw0xNjAxMDExMjAwMDBaMAwxCjAIBgNVBAMMAUQwggEi
-MA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDsJGSLJ13x8BKjTZmb/zlIQUpe
-o8kVRSgxCB7GuNAlYHsrSuY7M+X9dgrBK3xQI7UVjLbMQlixHVle6NiCHML24+cf
-Lu8N0TaBZd0kI0OL5Y4b02qt2R22jyWVN3kQhjy98yDUGgpiGZp08XB+AU4tM4aA
-diPM8i01owkdTSW72w848uSXvmJM2o9+3q6LaDFv21j3Iyk2qq6hzE2itxmRghTt
-woR+XLx+qMteAo4dQSnRz2PaqRXZKxHiamgMVPSra0PqD846YgTA/Sxuqn0Nmnbv
-6IblcLcvvrq5/BnjF9Et68ZAgwWxz6UOx29koWh3Na3QfPNqyxX9vhE5Cb1zAgMB
-AAGjgdUwgdIwHQYDVR0OBBYEFABsntLe6f8MsVBAjn+ZCQR8upczMB8GA1UdIwQY
-MBaAFP1ezK+3RP3qsypQHR6gKwAc59KEMDUGCCsGAQUFBwEBBCkwJzAlBggrBgEF
+MA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDVD4t+2fOGl/xfisff534YwO7A
+Oo7mdWUwbaR7Tu9jgqwMRoGsQv8SUwZRatKf4CoVyzyA0yqLEDD/D7xHq3ItvRQG
+c49YzkpkL0Hrpi93LWcE17kAsd6LnQWgs49GXSTJL7rgwcSgWxZIavmgDoKb1IX0
+LVMHApTsLNK9vIbB3DvXohJeOHhLnTBLFhs2b5oSk4n2+l8hEX3vsu0Dq3wDKEhl
+dhCOs0YrGaQWMhrt/hn8N5OdZVetnGuIJvYwvIMi1sBRFyvnebG8Rbc0S6w8QI2D
+gEGIpCVG7QB3CU85z5hBb0mtJTXjAZhJE31e9YaE8eRx+7pK7q8xFlYf99/PAgMB
+AAGjgdUwgdIwHQYDVR0OBBYEFK4ovd5vYAAqAVmP/ebFJ2XNAQQ3MB8GA1UdIwQY
+MBaAFLf7VHcMdnSwcoQvTq8kH8pijZlhMDUGCCsGAQUFBwEBBCkwJzAlBggrBgEF
BQcwAoYZaHR0cDovL3VybC1mb3ItYWlhL0kyLmNlcjAqBgNVHR8EIzAhMB+gHaAb
hhlodHRwOi8vdXJsLWZvci1jcmwvSTIuY3JsMA4GA1UdDwEB/wQEAwIFoDAdBgNV
-HSUEFjAUBggrBgEFBQcDAQYIKwYBBQUHAwIwDQYJKoZIhvcNAQELBQADggEBADL5
-Wlmcl4FDDmLnS1Lvbi2YEgFeNNTaatqffgSKqwCJZwqB9F+cgAwBamFesWVYEZG4
-bu6bLQ/uN3KK5jO6eV17Xi3TyQODKW+n/LtkPV66N3f1jzW2Dd31UBIQdQCW24Iv
-FfP++Rao5f9x7wuoMF6k/uid0EPalGStS1NTTdFbWhWsrQqHgfHV0srnxii9rykK
-32kKKcmM9HuyzUxUKOyAegu33La21p0Mn/9L+k51er1Op4cc7Rnhfj4omZIUkQ59
-judJRiiNQkaq7TqFMIvZ0Jei/s2NdvmAD66H1/V5V/zQ/0QSZcWHArtvL/FI5g4a
-Elib4xjsmTTznK7S2nI=
+HSUEFjAUBggrBgEFBQcDAQYIKwYBBQUHAwIwDQYJKoZIhvcNAQELBQADggEBABYa
+rZGomtXSY9SMYXMO1BRm7u9Oy/RAgkKVYK5lWZnKYkdHSGrYx0uyYqLHRYqSpmkO
+832PnQunusBhgHZG7yuAVjohHeRSLaCYvzbMNk5ALFVIkznj11QhSM4DZZrfWQfV
+dl5cJfuEPqFUmK3Uff9+xWJeQ8Ez+ARt3SO1ikhVelVppdojRqJYKWwiBaLqsL6B
+XWyhmnxBoa4C3k+HW4MBgU+63F8KBEGD2l15LZrKgoRIHbentOWrKGszMwn819iA
+Ddb2OHmRRDkouL/uSkObJ0J68uI8TYkdIeDO7AbgLrLc8goVfDML7DaOJjEO+Pfo
+PQfXLJHDDDV6dvNnAsE=
-----END CERTIFICATE-----
diff --git a/chromium/net/data/cert_issuer_source_static_unittest/e1.pem b/chromium/net/data/cert_issuer_source_static_unittest/e1.pem
new file mode 100644
index 00000000000..c722f529134
--- /dev/null
+++ b/chromium/net/data/cert_issuer_source_static_unittest/e1.pem
@@ -0,0 +1,90 @@
+Generated by ./generate-certs.py.
+Refer to generator script docstring for details.
+Certificate:
+ Data:
+ Version: 3 (0x2)
+ Serial Number: 1 (0x1)
+ Signature Algorithm: sha256WithRSAEncryption
+ Issuer: CN=I3
+ Validity
+ Not Before: Jan 1 12:00:00 2015 GMT
+ Not After : Jan 1 12:00:00 2016 GMT
+ Subject: CN=E1
+ Subject Public Key Info:
+ Public Key Algorithm: rsaEncryption
+ Public-Key: (2048 bit)
+ Modulus:
+ 00:f1:7c:c7:ef:ed:ae:f5:de:8a:c1:fd:b9:78:1c:
+ 8b:8b:73:54:19:45:78:0a:a9:56:df:05:7a:bb:3b:
+ 98:18:88:cf:d4:c2:c4:d9:66:5a:81:34:21:47:cb:
+ b7:d2:b4:9a:c6:22:ae:33:fa:f0:6a:3d:6f:7b:e1:
+ ad:7c:fe:e7:33:72:bc:53:aa:d8:92:06:9a:c8:5b:
+ 1a:8a:eb:b5:d5:72:de:df:43:97:78:22:e6:da:09:
+ 15:46:55:6c:88:c6:4e:4d:81:3d:6d:41:40:10:fc:
+ 64:d9:ee:7b:63:fe:fa:77:f1:58:ff:09:b8:46:e2:
+ 50:53:68:39:e1:5c:47:05:99:84:dd:3f:dc:e0:27:
+ f9:db:11:39:0c:71:a4:09:b5:42:86:04:f9:f4:fa:
+ 4a:34:f9:4b:cd:d3:c5:41:4d:4d:7d:47:27:f4:88:
+ 5a:cb:4a:62:65:6d:a8:76:27:6c:95:5b:40:91:3d:
+ 49:e2:dc:b9:c4:45:b3:e9:e3:65:67:1a:a4:e2:86:
+ f5:32:1a:fb:e6:95:7b:b0:4f:5b:89:d4:a7:5d:a3:
+ 50:a9:5e:bf:aa:c3:e5:0b:72:5c:1e:7f:e6:42:05:
+ 1f:21:f3:71:37:2e:48:f0:b6:0a:09:4f:2a:f5:81:
+ fd:46:b5:ba:e1:5f:04:82:8a:6e:b7:83:32:e9:7d:
+ 7a:35
+ Exponent: 65537 (0x10001)
+ X509v3 extensions:
+ X509v3 Subject Key Identifier:
+ 47:02:FD:6B:F5:26:65:BB:20:CA:5C:49:51:67:52:51:43:AB:40:02
+ X509v3 Authority Key Identifier:
+ keyid:B3:B8:D0:C2:16:D7:60:93:F5:51:DB:DF:12:8A:B5:36:66:76:C4:6C
+
+ Authority Information Access:
+ CA Issuers - URI:http://url-for-aia/I3.cer
+
+ X509v3 CRL Distribution Points:
+
+ Full Name:
+ URI:http://url-for-crl/I3.crl
+
+ X509v3 Key Usage: critical
+ Digital Signature, Key Encipherment
+ X509v3 Extended Key Usage:
+ TLS Web Server Authentication, TLS Web Client Authentication
+ Signature Algorithm: sha256WithRSAEncryption
+ 53:6d:3b:42:d8:23:af:be:ae:ef:dd:78:47:45:07:93:a9:84:
+ 1d:e9:a3:11:7f:77:0b:96:31:42:af:68:ca:4d:ed:84:f5:63:
+ 47:6c:4e:84:f6:79:e5:8c:da:ad:52:02:b7:f2:a3:3c:0e:95:
+ a3:8b:fc:54:94:02:5b:29:aa:a6:db:f7:74:da:42:9f:7a:7f:
+ de:bf:33:37:07:b9:bc:0a:5d:6f:77:86:89:98:6c:69:92:bf:
+ 9d:57:1d:da:fb:29:d6:80:ee:32:ed:53:25:66:24:53:57:10:
+ 79:8a:77:4e:77:15:11:4e:5e:db:2d:35:05:a5:14:09:d2:6c:
+ 96:76:41:7c:18:e1:fd:a7:22:a8:4c:d4:31:d0:7d:85:19:0d:
+ c9:2e:9f:15:09:a4:b8:c2:b5:95:71:29:78:09:fb:b4:87:a4:
+ 2f:0a:06:12:8f:14:49:8d:64:16:5f:5a:8f:72:5b:a6:c4:ce:
+ 73:c9:eb:e8:9d:80:b7:76:fd:80:33:5b:6e:dd:97:88:01:49:
+ 50:6e:7d:55:5d:1a:6d:e8:4c:53:4d:d0:d8:62:ef:25:09:bb:
+ 84:18:d4:f6:f3:3e:c0:a9:ef:ad:be:14:9b:db:6b:04:5a:c3:
+ 6b:59:5d:cb:bf:1b:60:6b:00:ab:cb:69:f2:b7:14:97:d2:3c:
+ af:a0:49:11
+-----BEGIN CERTIFICATE-----
+MIIDazCCAlOgAwIBAgIBATANBgkqhkiG9w0BAQsFADANMQswCQYDVQQDDAJJMzAe
+Fw0xNTAxMDExMjAwMDBaFw0xNjAxMDExMjAwMDBaMA0xCzAJBgNVBAMMAkUxMIIB
+IjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA8XzH7+2u9d6Kwf25eByLi3NU
+GUV4CqlW3wV6uzuYGIjP1MLE2WZagTQhR8u30rSaxiKuM/rwaj1ve+GtfP7nM3K8
+U6rYkgaayFsaiuu11XLe30OXeCLm2gkVRlVsiMZOTYE9bUFAEPxk2e57Y/76d/FY
+/wm4RuJQU2g54VxHBZmE3T/c4Cf52xE5DHGkCbVChgT59PpKNPlLzdPFQU1NfUcn
+9Ihay0piZW2odidslVtAkT1J4ty5xEWz6eNlZxqk4ob1Mhr75pV7sE9bidSnXaNQ
+qV6/qsPlC3JcHn/mQgUfIfNxNy5I8LYKCU8q9YH9RrW64V8Egoput4My6X16NQID
+AQABo4HVMIHSMB0GA1UdDgQWBBRHAv1r9SZluyDKXElRZ1JRQ6tAAjAfBgNVHSME
+GDAWgBSzuNDCFtdgk/VR298SirU2ZnbEbDA1BggrBgEFBQcBAQQpMCcwJQYIKwYB
+BQUHMAKGGWh0dHA6Ly91cmwtZm9yLWFpYS9JMy5jZXIwKgYDVR0fBCMwITAfoB2g
+G4YZaHR0cDovL3VybC1mb3ItY3JsL0kzLmNybDAOBgNVHQ8BAf8EBAMCBaAwHQYD
+VR0lBBYwFAYIKwYBBQUHAwEGCCsGAQUFBwMCMA0GCSqGSIb3DQEBCwUAA4IBAQBT
+bTtC2COvvq7v3XhHRQeTqYQd6aMRf3cLljFCr2jKTe2E9WNHbE6E9nnljNqtUgK3
+8qM8DpWji/xUlAJbKaqm2/d02kKfen/evzM3B7m8Cl1vd4aJmGxpkr+dVx3a+ynW
+gO4y7VMlZiRTVxB5indOdxURTl7bLTUFpRQJ0myWdkF8GOH9pyKoTNQx0H2FGQ3J
+Lp8VCaS4wrWVcSl4Cfu0h6QvCgYSjxRJjWQWX1qPclumxM5zyevonYC3dv2AM1tu
+3ZeIAUlQbn1VXRpt6ExTTdDYYu8lCbuEGNT28z7Aqe+tvhSb22sEWsNrWV3Lvxtg
+awCry2nytxSX0jyvoEkR
+-----END CERTIFICATE-----
diff --git a/chromium/net/data/cert_issuer_source_static_unittest/e2.pem b/chromium/net/data/cert_issuer_source_static_unittest/e2.pem
new file mode 100644
index 00000000000..c07000f73ce
--- /dev/null
+++ b/chromium/net/data/cert_issuer_source_static_unittest/e2.pem
@@ -0,0 +1,90 @@
+Generated by ./generate-certs.py.
+Refer to generator script docstring for details.
+Certificate:
+ Data:
+ Version: 3 (0x2)
+ Serial Number: 2 (0x2)
+ Signature Algorithm: sha256WithRSAEncryption
+ Issuer: CN=I3
+ Validity
+ Not Before: Jan 1 12:00:00 2015 GMT
+ Not After : Jan 1 12:00:00 2016 GMT
+ Subject: CN=E2
+ Subject Public Key Info:
+ Public Key Algorithm: rsaEncryption
+ Public-Key: (2048 bit)
+ Modulus:
+ 00:c7:40:5e:d8:28:53:68:bd:2f:cb:ec:40:bb:fa:
+ d2:0c:8f:06:6a:1d:e4:41:8b:48:d1:7f:02:00:01:
+ a5:8e:5c:07:df:ae:e9:98:f8:9e:30:7e:ce:47:5f:
+ 3b:15:1e:c4:12:d8:1c:ce:95:84:24:75:1e:2a:a7:
+ 16:cb:14:28:18:34:e3:51:62:13:7a:43:fe:a4:34:
+ 4e:b8:a0:a4:53:46:3f:d7:42:21:63:34:55:e1:08:
+ b1:ac:93:84:00:72:9a:ca:8b:91:19:44:9d:d1:2e:
+ 3f:69:00:d9:09:ab:c3:e4:de:19:8e:91:8b:65:d4:
+ c3:3d:e3:f2:b5:ea:6a:60:a0:c6:8e:2a:8e:d2:f9:
+ a3:fa:ca:26:2b:2a:4f:36:03:c2:3d:64:55:9f:38:
+ 24:60:11:4c:d6:94:3e:5a:61:2f:fe:39:76:bc:72:
+ d4:15:d5:5f:4a:10:18:b8:99:da:51:89:ec:51:ce:
+ ef:92:8c:f0:ec:5b:1a:83:c3:ad:59:05:a6:0d:cb:
+ a5:c0:ad:09:c4:12:fb:4b:a7:5a:17:3b:f6:4b:af:
+ a2:25:91:1c:db:97:8a:54:44:7f:14:db:88:69:59:
+ 62:f0:5e:23:2c:87:a0:9c:6e:d0:58:7f:de:a1:66:
+ 97:61:a8:1d:12:de:f9:aa:58:57:b7:c0:11:6e:df:
+ 53:17
+ Exponent: 65537 (0x10001)
+ X509v3 extensions:
+ X509v3 Subject Key Identifier:
+ 8F:E3:36:9B:E5:5C:3F:CC:AD:FF:DB:E9:ED:43:A2:FB:95:34:EB:44
+ X509v3 Authority Key Identifier:
+ keyid:1B:D9:9D:7F:59:30:84:1C:E4:92:D1:19:FF:EA:8D:02:B3:C1:8E:50
+
+ Authority Information Access:
+ CA Issuers - URI:http://url-for-aia/I3.cer
+
+ X509v3 CRL Distribution Points:
+
+ Full Name:
+ URI:http://url-for-crl/I3.crl
+
+ X509v3 Key Usage: critical
+ Digital Signature, Key Encipherment
+ X509v3 Extended Key Usage:
+ TLS Web Server Authentication, TLS Web Client Authentication
+ Signature Algorithm: sha256WithRSAEncryption
+ 73:92:fc:fb:89:b0:a0:d5:75:56:73:f7:70:44:75:45:d7:90:
+ 88:2a:40:1f:f7:4d:be:47:00:d9:36:ca:b1:d0:35:9b:f5:b8:
+ d1:8a:80:90:6a:6e:fa:cb:31:c3:3b:55:01:95:06:17:d7:33:
+ 45:f4:e1:a7:a6:7a:7f:c3:dc:4d:75:3b:a7:ae:74:e8:cb:9f:
+ 39:9a:1f:5d:8e:34:af:c5:4a:a0:7d:8c:7e:30:69:b4:72:86:
+ bb:ef:1f:c9:4f:b9:59:b0:b3:f4:11:af:c9:b7:ae:72:4c:3f:
+ dd:57:40:67:bf:30:df:33:42:92:e1:33:a7:58:c0:fa:60:10:
+ a4:bc:9b:cf:3b:bc:6a:5d:67:f9:36:8e:9b:ea:38:a7:4e:10:
+ 82:77:42:24:bf:17:37:41:ed:33:d6:87:74:09:8a:cb:c2:53:
+ 10:3d:10:f3:31:69:23:e2:30:45:fb:8b:3c:49:88:9f:01:cf:
+ 39:8c:11:fd:51:64:49:53:81:3b:67:3e:19:81:46:73:8b:e5:
+ d1:8b:a7:f0:38:b0:90:5b:48:37:2d:22:72:40:30:1b:31:ad:
+ 5b:a2:84:de:94:ca:db:8d:11:3d:c9:2e:91:f8:3f:a3:7c:db:
+ 45:2f:c7:29:57:5f:5a:11:eb:50:46:25:7e:4b:2f:7a:4a:02:
+ 2e:75:96:75
+-----BEGIN CERTIFICATE-----
+MIIDazCCAlOgAwIBAgIBAjANBgkqhkiG9w0BAQsFADANMQswCQYDVQQDDAJJMzAe
+Fw0xNTAxMDExMjAwMDBaFw0xNjAxMDExMjAwMDBaMA0xCzAJBgNVBAMMAkUyMIIB
+IjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAx0Be2ChTaL0vy+xAu/rSDI8G
+ah3kQYtI0X8CAAGljlwH367pmPieMH7OR187FR7EEtgczpWEJHUeKqcWyxQoGDTj
+UWITekP+pDROuKCkU0Y/10IhYzRV4QixrJOEAHKayouRGUSd0S4/aQDZCavD5N4Z
+jpGLZdTDPePytepqYKDGjiqO0vmj+somKypPNgPCPWRVnzgkYBFM1pQ+WmEv/jl2
+vHLUFdVfShAYuJnaUYnsUc7vkozw7Fsag8OtWQWmDculwK0JxBL7S6daFzv2S6+i
+JZEc25eKVER/FNuIaVli8F4jLIegnG7QWH/eoWaXYagdEt75qlhXt8ARbt9TFwID
+AQABo4HVMIHSMB0GA1UdDgQWBBSP4zab5Vw/zK3/2+ntQ6L7lTTrRDAfBgNVHSME
+GDAWgBQb2Z1/WTCEHOSS0Rn/6o0Cs8GOUDA1BggrBgEFBQcBAQQpMCcwJQYIKwYB
+BQUHMAKGGWh0dHA6Ly91cmwtZm9yLWFpYS9JMy5jZXIwKgYDVR0fBCMwITAfoB2g
+G4YZaHR0cDovL3VybC1mb3ItY3JsL0kzLmNybDAOBgNVHQ8BAf8EBAMCBaAwHQYD
+VR0lBBYwFAYIKwYBBQUHAwEGCCsGAQUFBwMCMA0GCSqGSIb3DQEBCwUAA4IBAQBz
+kvz7ibCg1XVWc/dwRHVF15CIKkAf902+RwDZNsqx0DWb9bjRioCQam76yzHDO1UB
+lQYX1zNF9OGnpnp/w9xNdTunrnToy585mh9djjSvxUqgfYx+MGm0coa77x/JT7lZ
+sLP0Ea/Jt65yTD/dV0BnvzDfM0KS4TOnWMD6YBCkvJvPO7xqXWf5No6b6jinThCC
+d0Ikvxc3Qe0z1od0CYrLwlMQPRDzMWkj4jBF+4s8SYifAc85jBH9UWRJU4E7Zz4Z
+gUZzi+XRi6fwOLCQW0g3LSJyQDAbMa1booTelMrbjRE9yS6R+D+jfNtFL8cpV19a
+EetQRiV+Sy96SgIudZZ1
+-----END CERTIFICATE-----
diff --git a/chromium/net/data/cert_issuer_source_static_unittest/generate-certs.py b/chromium/net/data/cert_issuer_source_static_unittest/generate-certs.py
index e15fd912f2f..7eac10ee4f4 100755
--- a/chromium/net/data/cert_issuer_source_static_unittest/generate-certs.py
+++ b/chromium/net/data/cert_issuer_source_static_unittest/generate-certs.py
@@ -5,26 +5,30 @@
"""Certificates for testing issuer lookup.
- Root
- /| |
- / | |
- / | |
- / | |
- / | |
- v v v
- I1_1 i1_2 I2
- | | |
- | | |
- | | |
- | | |
- v v v
- C1 C2 D
+ Root
+ /| | |\\
+ / | | | \\
+ / | | | \\
+ / | | | \\
+ / | | | \\
+ v v v v v
+ I1_1 i1_2 I2 I3_1 I3_2
+ | | | | |
+ | | | | |
+ | | | | |
+ | | | | |
+ v v v | |
+ C1 C2 D E1 E2
I1 (i1_1.pem) and i1 (i1_2.pem) have subjects that are equal after
normalization.
+I3_1 and I3_2 have subjects that are exactly equal.
+
C1 and C2 should (attempt to) chain up through both I1 and i1, since I1 and i1
have the same the name (after normalization).
+
+E1 and E3 should (attempt to) chain up through both I3 intermediates.
"""
import os
@@ -59,6 +63,11 @@ write_cert_to_file(i1_2, 'i1_2.pem')
i2 = common.create_intermediate_certificate('I2', root)
write_cert_to_file(i2, 'i2.pem')
+# Two intermediates with exactly the same name.
+i3_1 = common.create_intermediate_certificate('I3', root)
+write_cert_to_file(i3_1, 'i3_1.pem')
+i3_2 = common.create_intermediate_certificate('I3', root)
+write_cert_to_file(i3_2, 'i3_2.pem')
# target certs
@@ -71,4 +80,9 @@ write_cert_to_file(c2, 'c2.pem')
d = common.create_end_entity_certificate('D', i2)
write_cert_to_file(d, 'd.pem')
+e1 = common.create_end_entity_certificate('E1', i3_1)
+write_cert_to_file(e1, 'e1.pem')
+
+e2 = common.create_end_entity_certificate('E2', i3_2)
+write_cert_to_file(e2, 'e2.pem')
diff --git a/chromium/net/data/cert_issuer_source_static_unittest/i1_1.pem b/chromium/net/data/cert_issuer_source_static_unittest/i1_1.pem
index f04d47196e1..33168738a87 100644
--- a/chromium/net/data/cert_issuer_source_static_unittest/i1_1.pem
+++ b/chromium/net/data/cert_issuer_source_static_unittest/i1_1.pem
@@ -14,30 +14,30 @@ Certificate:
Public Key Algorithm: rsaEncryption
Public-Key: (2048 bit)
Modulus:
- 00:c8:26:47:62:ee:66:2d:a6:8d:90:4f:5d:60:4e:
- 5c:fb:c4:54:22:7c:07:d6:af:57:f2:d5:cb:00:24:
- 2a:6b:0c:76:e3:90:14:fe:d0:0b:74:fa:3a:a2:33:
- c9:b3:1f:9f:d5:69:7c:7c:51:56:8f:e9:48:e7:ac:
- c0:76:72:a4:1d:93:0d:c3:b4:ed:99:2d:5a:70:31:
- e9:83:a1:58:05:6e:50:c0:2e:5d:d9:e2:97:a6:ef:
- 08:e1:21:1c:a6:18:74:23:85:e0:0f:b7:85:b7:3c:
- e8:a2:ab:09:40:91:b4:21:51:2b:20:be:96:a8:eb:
- e9:2e:a1:0e:10:bd:bf:35:90:c8:02:7f:08:c1:1c:
- 6c:2c:71:98:79:5c:78:83:2c:96:6b:f0:fe:85:bd:
- f9:11:6a:8b:86:2f:73:64:e2:94:31:cc:bc:35:65:
- bd:43:42:7a:fa:12:a4:71:af:7f:2f:49:28:e9:07:
- 04:d2:d2:0b:7f:83:b8:80:20:b0:1e:b7:7f:c2:24:
- 13:b9:04:92:35:00:77:3a:86:8f:be:1a:88:79:7c:
- 3c:0f:b2:62:21:8d:1c:04:22:7f:ff:e0:c4:6f:98:
- 68:72:d6:02:97:72:19:71:4b:5d:b3:90:4e:b3:71:
- 68:58:9d:ff:53:f0:e3:5d:4c:01:1f:18:2f:d7:d0:
- 72:6f
+ 00:c1:66:fe:2a:a6:f6:54:97:b6:f0:ef:43:4a:a0:
+ 36:e7:70:2b:85:77:7c:e9:b9:2e:e0:d7:cc:43:b7:
+ 43:bb:30:f7:c4:f0:f7:57:44:38:a3:1b:d0:e0:bb:
+ 64:16:72:9d:7f:69:98:b5:2a:f9:49:c5:35:7b:46:
+ f4:d8:24:36:b7:56:24:fe:ab:9a:81:1e:eb:9e:18:
+ 5a:c2:73:fc:06:66:0d:25:4b:c8:04:bd:33:c0:cf:
+ cc:ca:a4:e6:95:10:a6:a7:82:24:ba:36:b4:f5:25:
+ 2c:db:d4:04:78:20:00:40:42:06:54:0c:fc:4c:c8:
+ 72:00:a4:e5:46:d2:3f:32:93:c4:75:d4:62:c7:c3:
+ 08:3d:da:eb:aa:bb:5b:54:14:08:b3:57:d5:cb:40:
+ 37:de:0a:77:4b:5d:88:95:d5:1e:b3:d3:07:48:8f:
+ 41:16:b6:78:4f:b5:8d:cd:74:9d:db:60:a6:95:c4:
+ ba:f8:3b:59:87:c9:5c:3b:75:69:3d:bb:d8:5c:39:
+ 33:f1:d0:0c:dd:9c:5b:d3:70:e4:85:e3:20:81:86:
+ dc:93:39:ef:4a:3b:3c:ff:be:12:c8:20:2b:2f:a3:
+ 3f:d3:5c:03:8c:82:f6:b9:94:27:a3:ff:d1:63:58:
+ 86:49:5f:f4:27:39:56:35:04:ee:df:a5:78:7b:7c:
+ b1:cf
Exponent: 65537 (0x10001)
X509v3 extensions:
X509v3 Subject Key Identifier:
- 6C:0B:63:35:AC:38:8B:C1:0C:F8:E5:53:88:09:6A:97:76:E9:EA:AB
+ 84:17:CE:FE:EA:88:CB:E4:D7:19:40:7A:01:E3:62:84:3D:C6:05:EB
X509v3 Authority Key Identifier:
- keyid:3D:DD:2C:00:BE:89:E0:43:4C:05:77:67:07:60:FC:AC:BE:48:D0:A4
+ keyid:B5:C3:65:5F:95:6A:F7:19:30:E3:80:DD:EF:B0:A4:1B:3D:BE:A6:9D
Authority Information Access:
CA Issuers - URI:http://url-for-aia/Root.cer
@@ -52,39 +52,39 @@ Certificate:
X509v3 Basic Constraints: critical
CA:TRUE
Signature Algorithm: sha256WithRSAEncryption
- 14:7a:f9:23:d9:15:da:95:72:31:67:ce:27:2f:a0:ba:5e:d4:
- 69:c2:cd:dc:b7:40:8a:9b:13:16:04:47:33:b5:0d:91:ef:62:
- 25:56:37:88:05:35:25:31:b9:fb:0f:fe:d1:03:75:f5:52:80:
- 22:d7:f9:96:07:7f:73:ea:a7:1b:99:28:f3:7b:eb:b1:5a:0a:
- 4e:fc:53:e1:6e:cb:eb:bc:43:c7:a9:91:39:88:f8:45:7b:41:
- 97:eb:d4:2c:45:20:16:7e:cd:51:57:63:3d:ac:1d:aa:ba:43:
- ec:08:e8:87:d5:c0:0d:16:d8:7b:d1:b0:6e:33:ac:88:9b:1a:
- 09:f4:12:92:6a:d5:8f:17:a9:a0:fd:f2:d8:b3:91:c1:41:32:
- d8:43:27:55:57:fa:0e:08:87:98:bc:15:86:9f:ad:2b:48:c2:
- ae:aa:86:60:de:77:08:e2:a4:da:ec:75:7c:6b:12:1d:b5:a8:
- 43:16:55:18:ee:c2:76:2c:38:0a:c2:ca:5f:d3:98:86:4b:e8:
- 40:20:b5:5c:7b:04:71:37:1b:4a:1d:fd:24:cc:04:2d:b1:27:
- eb:aa:a9:ef:36:1b:48:db:8e:21:ad:03:d4:90:03:4c:67:45:
- f4:b7:2d:19:f0:f7:1e:a1:0a:21:52:0f:89:5c:0c:50:81:e6:
- 13:fa:51:77
+ 5f:ff:6e:d1:01:0c:c2:c6:57:f7:57:71:b6:28:12:b0:7c:24:
+ 66:ca:cf:5f:3a:14:cb:77:07:14:a5:01:a9:22:6f:b1:60:fa:
+ 8d:0b:91:54:c7:24:ab:af:9b:be:73:63:fb:08:0c:31:94:5b:
+ 25:2a:a7:e3:6b:cb:89:c1:7b:48:fb:df:50:4f:3e:fd:97:aa:
+ 6f:40:2b:1d:15:97:3d:04:3a:6f:c9:dd:04:c7:73:75:88:06:
+ e8:e1:cf:bf:c6:d4:12:b9:73:f4:0f:2d:1c:af:06:51:96:ee:
+ 77:fe:65:28:e6:3b:4d:67:0c:55:83:9a:b9:6e:4d:1f:3a:58:
+ a2:03:6f:0f:1f:58:f2:b2:b4:dd:86:bd:fd:53:5c:20:6b:1e:
+ 73:c7:89:5d:8b:79:31:f6:33:b2:6c:5d:8b:52:b7:b7:4d:dc:
+ a4:80:87:54:2a:7a:af:cd:41:ba:82:bb:34:46:25:85:e9:87:
+ 61:2e:3b:d9:52:09:27:ec:eb:58:9a:39:b8:e0:bc:67:cb:af:
+ b7:f0:3f:1c:93:23:42:f2:00:9b:9d:61:6a:d7:ce:5a:67:72:
+ b7:06:da:de:13:11:e0:7c:16:69:91:fd:f8:e1:bd:ab:b6:bb:
+ 96:f9:82:51:8d:e5:ef:1d:6e:b2:97:d6:9d:75:0f:cb:ed:07:
+ 96:4a:e5:17
-----BEGIN CERTIFICATE-----
MIIDYzCCAkugAwIBAgIBAjANBgkqhkiG9w0BAQsFADAPMQ0wCwYDVQQDDARSb290
MB4XDTE1MDEwMTEyMDAwMFoXDTE2MDEwMTEyMDAwMFowDTELMAkGA1UEAwwCSTEw
-ggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDIJkdi7mYtpo2QT11gTlz7
-xFQifAfWr1fy1csAJCprDHbjkBT+0At0+jqiM8mzH5/VaXx8UVaP6UjnrMB2cqQd
-kw3DtO2ZLVpwMemDoVgFblDALl3Z4pem7wjhIRymGHQjheAPt4W3POiiqwlAkbQh
-USsgvpao6+kuoQ4Qvb81kMgCfwjBHGwscZh5XHiDLJZr8P6FvfkRaouGL3Nk4pQx
-zLw1Zb1DQnr6EqRxr38vSSjpBwTS0gt/g7iAILAet3/CJBO5BJI1AHc6ho++Goh5
-fDwPsmIhjRwEIn//4MRvmGhy1gKXchlxS12zkE6zcWhYnf9T8ONdTAEfGC/X0HJv
-AgMBAAGjgcswgcgwHQYDVR0OBBYEFGwLYzWsOIvBDPjlU4gJapd26eqrMB8GA1Ud
-IwQYMBaAFD3dLAC+ieBDTAV3Zwdg/Ky+SNCkMDcGCCsGAQUFBwEBBCswKTAnBggr
+ggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDBZv4qpvZUl7bw70NKoDbn
+cCuFd3zpuS7g18xDt0O7MPfE8PdXRDijG9Dgu2QWcp1/aZi1KvlJxTV7RvTYJDa3
+ViT+q5qBHuueGFrCc/wGZg0lS8gEvTPAz8zKpOaVEKangiS6NrT1JSzb1AR4IABA
+QgZUDPxMyHIApOVG0j8yk8R11GLHwwg92uuqu1tUFAizV9XLQDfeCndLXYiV1R6z
+0wdIj0EWtnhPtY3NdJ3bYKaVxLr4O1mHyVw7dWk9u9hcOTPx0AzdnFvTcOSF4yCB
+htyTOe9KOzz/vhLIICsvoz/TXAOMgva5lCej/9FjWIZJX/QnOVY1BO7fpXh7fLHP
+AgMBAAGjgcswgcgwHQYDVR0OBBYEFIQXzv7qiMvk1xlAegHjYoQ9xgXrMB8GA1Ud
+IwQYMBaAFLXDZV+VavcZMOOA3e+wpBs9vqadMDcGCCsGAQUFBwEBBCswKTAnBggr
BgEFBQcwAoYbaHR0cDovL3VybC1mb3ItYWlhL1Jvb3QuY2VyMCwGA1UdHwQlMCMw
IaAfoB2GG2h0dHA6Ly91cmwtZm9yLWNybC9Sb290LmNybDAOBgNVHQ8BAf8EBAMC
-AQYwDwYDVR0TAQH/BAUwAwEB/zANBgkqhkiG9w0BAQsFAAOCAQEAFHr5I9kV2pVy
-MWfOJy+gul7UacLN3LdAipsTFgRHM7UNke9iJVY3iAU1JTG5+w/+0QN19VKAItf5
-lgd/c+qnG5ko83vrsVoKTvxT4W7L67xDx6mROYj4RXtBl+vULEUgFn7NUVdjPawd
-qrpD7Ajoh9XADRbYe9GwbjOsiJsaCfQSkmrVjxepoP3y2LORwUEy2EMnVVf6DgiH
-mLwVhp+tK0jCrqqGYN53COKk2ux1fGsSHbWoQxZVGO7Cdiw4CsLKX9OYhkvoQCC1
-XHsEcTcbSh39JMwELbEn66qp7zYbSNuOIa0D1JADTGdF9LctGfD3HqEKIVIPiVwM
-UIHmE/pRdw==
+AQYwDwYDVR0TAQH/BAUwAwEB/zANBgkqhkiG9w0BAQsFAAOCAQEAX/9u0QEMwsZX
+91dxtigSsHwkZsrPXzoUy3cHFKUBqSJvsWD6jQuRVMckq6+bvnNj+wgMMZRbJSqn
+42vLicF7SPvfUE8+/Zeqb0ArHRWXPQQ6b8ndBMdzdYgG6OHPv8bUErlz9A8tHK8G
+UZbud/5lKOY7TWcMVYOauW5NHzpYogNvDx9Y8rK03Ya9/VNcIGsec8eJXYt5MfYz
+smxdi1K3t03cpICHVCp6r81BuoK7NEYlhemHYS472VIJJ+zrWJo5uOC8Z8uvt/A/
+HJMjQvIAm51hatfOWmdytwba3hMR4HwWaZH9+OG9q7a7lvmCUY3l7x1uspfWnXUP
+y+0HlkrlFw==
-----END CERTIFICATE-----
diff --git a/chromium/net/data/cert_issuer_source_static_unittest/i1_2.pem b/chromium/net/data/cert_issuer_source_static_unittest/i1_2.pem
index 81c9ec0da3f..1ff82f433fe 100644
--- a/chromium/net/data/cert_issuer_source_static_unittest/i1_2.pem
+++ b/chromium/net/data/cert_issuer_source_static_unittest/i1_2.pem
@@ -14,30 +14,30 @@ Certificate:
Public Key Algorithm: rsaEncryption
Public-Key: (2048 bit)
Modulus:
- 00:c5:46:7a:ab:3c:05:2b:17:02:4c:f7:d0:83:7c:
- 2a:5f:e4:d1:23:23:8f:5c:93:cd:e1:19:b7:6d:a2:
- cc:14:51:97:d0:87:1f:2e:a6:fb:9a:b0:f3:15:a3:
- e8:de:f0:45:df:ff:44:22:ca:7c:e2:6a:c8:e9:a6:
- 62:8e:af:2f:21:85:29:d4:2d:31:fe:4c:e1:5a:3b:
- cd:3b:8e:bb:e8:d5:55:c1:52:1e:e8:ae:38:f7:ab:
- 3e:5e:67:7d:a6:96:b2:3d:29:a1:26:f6:b6:23:18:
- ef:ed:49:71:64:f5:47:7f:40:e0:f2:b1:45:99:6c:
- 6a:f4:d4:96:ee:11:b8:d4:bc:9c:04:94:98:ac:0b:
- ee:9c:d1:5a:4d:da:0e:3b:da:55:59:12:85:99:41:
- c9:d5:ac:ce:f8:8a:6b:fb:e6:6f:97:8f:50:f9:7c:
- cd:42:6a:ab:c2:bf:28:1a:2e:33:94:65:b0:f0:56:
- 7a:be:e0:2a:4e:c3:99:f4:3b:db:12:04:11:d6:c4:
- 04:6f:4e:3e:c3:23:d3:8c:04:ed:39:c2:99:0f:ca:
- c8:0d:bc:6e:f6:d5:a1:5c:26:31:b7:a6:04:ad:6f:
- f2:2a:86:cd:bc:f7:5e:11:04:58:bd:db:17:72:31:
- 28:1c:f3:6d:5a:94:5d:f6:52:bb:9b:73:b8:9a:7a:
- 08:c9
+ 00:b9:f4:f5:17:e5:0d:0a:46:f6:81:21:97:dd:ba:
+ 5d:f4:16:a7:f8:ec:ac:37:cb:cf:50:d0:de:3b:d1:
+ 9f:7c:22:2d:0b:b6:f4:57:76:3a:69:92:fe:0f:be:
+ 0c:19:bd:2c:bb:49:bb:f1:d7:89:75:b4:3f:d1:e3:
+ d3:c0:6e:fd:26:63:d9:81:9c:1e:0a:a5:46:6d:18:
+ f8:ce:e1:ab:29:8f:82:5f:f3:d2:4f:ef:d1:77:20:
+ 11:b5:c6:b3:1d:8f:0c:06:3e:51:91:4a:73:19:f8:
+ 38:b3:b2:57:44:d8:1c:b3:29:8d:85:4f:38:0d:68:
+ 7d:4c:43:5a:73:7d:8a:63:62:a6:19:f0:19:3d:ca:
+ 32:af:b3:72:7d:d2:68:a6:29:ad:26:54:b6:6f:cc:
+ 26:75:3b:c2:58:03:50:af:3b:d2:cc:0a:97:56:ec:
+ 4c:18:2c:de:04:32:26:f3:36:15:50:bd:2c:81:2d:
+ 44:da:8f:4a:dc:44:1e:c6:b1:e6:97:d6:53:a8:01:
+ ca:c1:e9:0f:1e:17:89:17:c5:07:c1:4d:8b:61:ce:
+ f3:0f:2a:61:5d:eb:25:45:76:74:6c:c1:a3:b9:79:
+ db:39:aa:f9:e7:fe:d5:4b:c8:33:81:dd:a4:40:2c:
+ de:51:e0:48:d3:a3:d5:e7:a7:b8:9b:a0:b5:4f:bf:
+ ba:cd
Exponent: 65537 (0x10001)
X509v3 extensions:
X509v3 Subject Key Identifier:
- F9:72:F0:81:01:06:00:24:81:09:78:86:EB:FF:E1:51:82:0A:A8:44
+ 0C:6A:CE:BB:AC:0D:C3:03:19:28:BF:63:76:72:0B:3D:89:5B:D3:B7
X509v3 Authority Key Identifier:
- keyid:53:00:1D:70:48:9E:90:44:14:41:A0:92:6E:B8:1D:ED:EA:77:1F:81
+ keyid:B5:C3:65:5F:95:6A:F7:19:30:E3:80:DD:EF:B0:A4:1B:3D:BE:A6:9D
Authority Information Access:
CA Issuers - URI:http://url-for-aia/Root.cer
@@ -52,39 +52,39 @@ Certificate:
X509v3 Basic Constraints: critical
CA:TRUE
Signature Algorithm: sha256WithRSAEncryption
- f4:4f:69:8a:2e:d2:9e:f2:64:4f:b3:96:ef:8a:e1:4c:70:6a:
- 06:bb:f0:cf:c3:29:d8:61:1e:7a:79:13:89:7e:2c:67:87:d2:
- 4f:2c:e1:e5:73:99:31:51:ef:bc:b0:b0:5d:de:79:54:58:5a:
- 9b:9f:e9:f2:bb:16:b8:fa:70:cb:10:e0:02:5c:44:2d:a7:3f:
- 33:e2:6a:f1:f4:2e:2c:70:9c:07:4a:aa:72:21:f3:ac:4d:cd:
- d8:67:74:cd:16:cc:27:81:e9:05:26:4a:ec:1d:4f:a2:6e:c6:
- b0:88:f5:70:ee:00:cd:b6:61:ff:7f:10:59:a9:28:67:3b:26:
- c3:53:fc:ff:6c:38:a7:c9:fc:2f:3b:7a:67:0f:a5:66:44:1e:
- e7:ce:55:d2:df:ca:65:16:63:f6:5f:9f:9f:d0:1f:71:ae:0f:
- 5a:19:42:7c:6d:99:b2:be:28:5d:c1:b6:db:c2:d5:51:74:b8:
- a3:63:4e:bf:41:45:64:9a:65:3c:f0:2c:97:fb:db:46:0a:52:
- 89:46:6c:7e:2d:19:cd:b5:72:24:7f:86:2f:c0:bd:02:f0:1a:
- ea:21:7a:23:17:04:1e:01:db:43:95:7a:39:66:90:ac:1c:34:
- 92:19:b1:7a:4f:ff:ae:4a:44:b9:54:f5:2d:e9:ef:a8:9f:a5:
- ec:85:2c:cf
+ 85:49:62:75:55:96:56:c4:8b:46:3a:ee:27:1a:70:84:a4:bc:
+ b5:a1:0e:13:49:a3:00:bc:d4:54:ef:79:a7:8a:8f:cc:85:bc:
+ 9f:cc:11:5b:f8:b3:7d:7b:35:46:bb:67:d1:ed:ed:3e:c6:54:
+ 76:54:db:29:7d:5f:d0:35:f0:1e:cf:d9:7e:c3:1c:b9:32:2d:
+ 62:92:cb:bf:f2:8f:d2:a1:aa:95:c2:d9:be:9e:af:80:22:63:
+ 2b:dc:e4:c0:e8:24:64:7c:db:16:85:3c:a3:03:5d:6d:19:88:
+ 75:87:21:d3:ef:95:e6:20:79:eb:e1:57:44:e8:72:eb:d6:ea:
+ 46:58:62:5d:0c:43:3f:84:46:fb:cc:7e:3d:0b:5c:a5:7e:b0:
+ be:ce:14:92:d8:4a:2a:2f:76:68:cb:ff:ab:7d:ae:ac:58:2f:
+ 0d:25:66:46:d3:ac:f5:33:6c:91:c5:98:9d:83:cc:31:a5:c0:
+ 17:94:fb:9b:30:a7:de:52:17:dc:e5:72:40:45:37:31:32:a6:
+ c0:a9:c3:18:f2:0f:94:58:95:3c:03:98:15:70:d3:18:f1:e9:
+ 91:77:0b:02:02:09:21:6c:b8:34:d4:01:43:e3:97:bb:00:19:
+ fb:21:d7:1e:d1:ef:63:00:ae:c2:b8:5d:53:e4:30:25:47:f0:
+ 0f:cd:08:77
-----BEGIN CERTIFICATE-----
MIIDYzCCAkugAwIBAgIBAzANBgkqhkiG9w0BAQsFADAPMQ0wCwYDVQQDDARSb290
MB4XDTE1MDEwMTEyMDAwMFoXDTE2MDEwMTEyMDAwMFowDTELMAkGA1UEAwwCaTEw
-ggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDFRnqrPAUrFwJM99CDfCpf
-5NEjI49ck83hGbdtoswUUZfQhx8upvuasPMVo+je8EXf/0QiynziasjppmKOry8h
-hSnULTH+TOFaO807jrvo1VXBUh7orjj3qz5eZ32mlrI9KaEm9rYjGO/tSXFk9Ud/
-QODysUWZbGr01JbuEbjUvJwElJisC+6c0VpN2g472lVZEoWZQcnVrM74imv75m+X
-j1D5fM1CaqvCvygaLjOUZbDwVnq+4CpOw5n0O9sSBBHWxARvTj7DI9OMBO05wpkP
-ysgNvG721aFcJjG3pgStb/Iqhs28914RBFi92xdyMSgc821alF32Urubc7iaegjJ
-AgMBAAGjgcswgcgwHQYDVR0OBBYEFPly8IEBBgAkgQl4huv/4VGCCqhEMB8GA1Ud
-IwQYMBaAFFMAHXBInpBEFEGgkm64He3qdx+BMDcGCCsGAQUFBwEBBCswKTAnBggr
+ggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQC59PUX5Q0KRvaBIZfdul30
+Fqf47Kw3y89Q0N470Z98Ii0LtvRXdjppkv4PvgwZvSy7Sbvx14l1tD/R49PAbv0m
+Y9mBnB4KpUZtGPjO4aspj4Jf89JP79F3IBG1xrMdjwwGPlGRSnMZ+DizsldE2Byz
+KY2FTzgNaH1MQ1pzfYpjYqYZ8Bk9yjKvs3J90mimKa0mVLZvzCZ1O8JYA1CvO9LM
+CpdW7EwYLN4EMibzNhVQvSyBLUTaj0rcRB7GseaX1lOoAcrB6Q8eF4kXxQfBTYth
+zvMPKmFd6yVFdnRswaO5eds5qvnn/tVLyDOB3aRALN5R4EjTo9Xnp7iboLVPv7rN
+AgMBAAGjgcswgcgwHQYDVR0OBBYEFAxqzrusDcMDGSi/Y3ZyCz2JW9O3MB8GA1Ud
+IwQYMBaAFLXDZV+VavcZMOOA3e+wpBs9vqadMDcGCCsGAQUFBwEBBCswKTAnBggr
BgEFBQcwAoYbaHR0cDovL3VybC1mb3ItYWlhL1Jvb3QuY2VyMCwGA1UdHwQlMCMw
IaAfoB2GG2h0dHA6Ly91cmwtZm9yLWNybC9Sb290LmNybDAOBgNVHQ8BAf8EBAMC
-AQYwDwYDVR0TAQH/BAUwAwEB/zANBgkqhkiG9w0BAQsFAAOCAQEA9E9pii7SnvJk
-T7OW74rhTHBqBrvwz8Mp2GEeenkTiX4sZ4fSTyzh5XOZMVHvvLCwXd55VFham5/p
-8rsWuPpwyxDgAlxELac/M+Jq8fQuLHCcB0qqciHzrE3N2Gd0zRbMJ4HpBSZK7B1P
-om7GsIj1cO4AzbZh/38QWakoZzsmw1P8/2w4p8n8Lzt6Zw+lZkQe585V0t/KZRZj
-9l+fn9Afca4PWhlCfG2Zsr4oXcG228LVUXS4o2NOv0FFZJplPPAsl/vbRgpSiUZs
-fi0ZzbVyJH+GL8C9AvAa6iF6IxcEHgHbQ5V6OWaQrBw0khmxek//rkpEuVT1Lenv
-qJ+l7IUszw==
+AQYwDwYDVR0TAQH/BAUwAwEB/zANBgkqhkiG9w0BAQsFAAOCAQEAhUlidVWWVsSL
+RjruJxpwhKS8taEOE0mjALzUVO95p4qPzIW8n8wRW/izfXs1Rrtn0e3tPsZUdlTb
+KX1f0DXwHs/ZfsMcuTItYpLLv/KP0qGqlcLZvp6vgCJjK9zkwOgkZHzbFoU8owNd
+bRmIdYch0++V5iB56+FXROhy69bqRlhiXQxDP4RG+8x+PQtcpX6wvs4UkthKKi92
+aMv/q32urFgvDSVmRtOs9TNskcWYnYPMMaXAF5T7mzCn3lIX3OVyQEU3MTKmwKnD
+GPIPlFiVPAOYFXDTGPHpkXcLAgIJIWy4NNQBQ+OXuwAZ+yHXHtHvYwCuwrhdU+Qw
+JUfwD80Idw==
-----END CERTIFICATE-----
diff --git a/chromium/net/data/cert_issuer_source_static_unittest/i2.pem b/chromium/net/data/cert_issuer_source_static_unittest/i2.pem
index f5dadf439f7..b69bb9003a4 100644
--- a/chromium/net/data/cert_issuer_source_static_unittest/i2.pem
+++ b/chromium/net/data/cert_issuer_source_static_unittest/i2.pem
@@ -14,30 +14,30 @@ Certificate:
Public Key Algorithm: rsaEncryption
Public-Key: (2048 bit)
Modulus:
- 00:c5:2a:06:f1:73:72:43:37:0a:2f:24:24:32:6b:
- 04:fd:5d:0e:17:b6:3b:37:f0:59:09:10:39:f0:ee:
- cd:9b:43:e0:9d:e9:63:6e:05:42:5e:f8:b8:26:78:
- 6b:9c:bd:0c:cc:85:8b:10:e8:7b:ef:03:8f:6e:84:
- fe:30:64:f7:21:78:3e:2b:e4:2e:d2:51:4a:e7:92:
- e3:44:c2:eb:cb:b3:fe:7c:44:6e:17:e0:cc:7b:39:
- 4d:71:59:9b:d6:e8:8d:26:bd:49:fa:3e:b0:27:96:
- 36:2c:f0:61:ca:a9:c0:00:ed:85:70:69:64:b4:81:
- 71:69:a8:52:74:34:d7:61:6c:7c:84:9a:de:82:07:
- 3b:18:dc:85:35:11:b7:0b:3a:89:59:1d:23:62:48:
- 91:cf:60:0f:c4:ea:57:ca:42:8e:e8:52:1a:13:56:
- 2d:1c:5b:70:3a:64:2f:a1:b4:d7:de:51:19:57:63:
- 6d:10:c8:a3:1b:1d:92:96:dc:37:fa:8b:60:3a:67:
- 7c:61:0b:24:15:54:68:e2:b0:74:b3:1a:cd:33:4c:
- 3c:49:e1:56:eb:7d:59:07:eb:87:7a:bc:6f:f4:e8:
- 3b:2b:c6:d0:e6:ae:7a:df:04:d4:99:27:7d:4f:a7:
- 22:ea:7d:6a:ff:69:1a:b8:6e:f5:4a:18:0f:98:1a:
- 22:27
+ 00:bd:84:dd:82:37:cb:c8:69:8a:c2:c6:ff:38:f7:
+ 85:93:9e:22:d5:b8:94:12:3b:d9:9f:49:70:ef:ff:
+ 39:58:fc:e7:36:32:18:37:d4:2b:d9:4e:4e:67:60:
+ ee:2c:28:d0:4f:66:23:cd:c1:f0:75:f5:54:0e:51:
+ a5:f0:fa:9c:bd:42:5d:02:3a:62:60:83:b8:e5:fe:
+ cd:bc:ad:35:b7:9e:09:ec:3a:81:51:b7:46:56:2d:
+ 90:bb:e5:4a:4f:6a:c6:be:39:79:b6:31:99:1b:c4:
+ d0:a1:94:dc:e5:51:8e:9d:a9:c5:d8:91:f9:5c:76:
+ 3a:09:d2:8f:0c:24:3a:ff:91:4c:c6:c9:c7:36:53:
+ cc:78:eb:fc:00:25:fd:5f:b3:c0:95:10:91:3d:43:
+ fe:31:b6:b3:84:e9:ec:5f:1b:5a:77:a7:25:29:1a:
+ 7a:71:d9:7a:62:85:45:c3:51:da:ed:79:a5:41:7d:
+ 0b:49:3e:2b:51:5e:99:33:1f:1c:5a:52:51:6b:07:
+ c5:5a:0b:4b:b6:e1:6c:43:07:f2:b2:65:6e:9d:77:
+ a9:2a:b6:88:7b:a9:d9:97:6b:65:f9:be:4e:39:31:
+ 4c:a0:2d:06:18:de:53:7c:bf:80:64:cc:2b:7a:b0:
+ 2b:76:03:c4:40:a6:53:f1:dc:74:87:fb:c5:d8:2f:
+ f5:ef
Exponent: 65537 (0x10001)
X509v3 extensions:
X509v3 Subject Key Identifier:
- FD:5E:CC:AF:B7:44:FD:EA:B3:2A:50:1D:1E:A0:2B:00:1C:E7:D2:84
+ B7:FB:54:77:0C:76:74:B0:72:84:2F:4E:AF:24:1F:CA:62:8D:99:61
X509v3 Authority Key Identifier:
- keyid:53:00:1D:70:48:9E:90:44:14:41:A0:92:6E:B8:1D:ED:EA:77:1F:81
+ keyid:B5:C3:65:5F:95:6A:F7:19:30:E3:80:DD:EF:B0:A4:1B:3D:BE:A6:9D
Authority Information Access:
CA Issuers - URI:http://url-for-aia/Root.cer
@@ -52,39 +52,39 @@ Certificate:
X509v3 Basic Constraints: critical
CA:TRUE
Signature Algorithm: sha256WithRSAEncryption
- 02:a0:b5:94:14:2a:94:44:1f:25:f2:18:9e:64:8a:f6:b3:62:
- 35:95:ca:c5:ab:21:e7:18:d3:b2:41:5a:83:ac:3a:9c:bc:21:
- 3d:4f:6e:4a:94:31:da:71:16:dc:4a:e6:bc:15:84:6c:5e:10:
- b9:6e:62:f4:ba:b8:9a:c5:f5:53:f9:29:16:83:ab:fd:8a:81:
- 7b:39:3e:c9:2f:83:c3:37:f7:e3:0a:4d:47:bc:fc:ff:52:32:
- 70:c7:50:21:15:b6:17:79:ed:18:1e:9a:9c:a8:f9:d2:9e:76:
- 06:e3:3d:cd:2f:55:6d:e2:e5:ea:20:f7:03:80:7f:c2:13:3d:
- 99:4f:38:d0:b8:43:6e:12:69:82:79:79:0c:16:cb:6d:cb:2f:
- b7:2a:db:07:70:2a:20:96:45:80:03:9f:45:0d:91:be:29:e0:
- af:4a:fd:d8:68:ef:86:b1:85:cc:7d:9a:24:d0:72:a4:33:0f:
- 2e:7f:ce:e2:d4:10:8e:8b:3a:f8:d3:a0:13:ae:ca:3b:ef:2b:
- 39:d1:ba:dd:35:98:6a:44:d3:0f:f8:b7:47:f4:08:3c:f1:41:
- 45:f9:67:01:70:0c:fc:51:7b:a2:49:39:1f:31:09:e3:8c:7d:
- 98:c7:19:ce:a1:ce:a6:40:3f:ca:29:56:f4:90:2a:42:25:84:
- 2f:f1:79:fa
+ 4c:7b:dd:61:fc:1e:ea:5a:d7:73:ae:8a:3b:14:19:3a:8c:ae:
+ a5:a5:37:1a:74:87:a9:de:9f:79:db:5d:ad:92:85:46:65:35:
+ a8:77:8c:c2:4e:b8:90:67:7f:ec:ed:7b:a9:b9:1d:6a:27:05:
+ 22:19:92:6c:46:02:4f:3a:9c:69:67:29:12:33:e2:d6:db:c1:
+ 0c:79:cb:10:77:ab:d9:df:77:1b:9c:d2:73:8e:e6:31:72:f4:
+ 04:24:cb:67:b3:73:cc:02:83:7f:be:fb:01:0f:71:25:c0:02:
+ b1:23:aa:77:03:74:28:fd:5e:9b:03:af:44:60:e5:f4:be:c1:
+ c4:64:6a:17:47:ab:fe:b3:f5:47:dc:b8:f8:1c:c2:cf:bb:57:
+ ca:65:0f:73:f0:32:4d:d7:b5:38:35:f7:01:8c:13:de:ab:de:
+ cd:01:a9:5c:57:d7:2c:23:10:70:34:ea:b5:4a:eb:11:6d:ae:
+ 36:ee:70:3a:d2:96:73:2d:3c:e6:fe:6f:56:ff:ea:57:39:4f:
+ ca:70:1b:0e:7e:1c:75:b0:02:0d:4e:92:bb:c0:e6:0e:7d:16:
+ c4:07:b9:12:00:a5:a5:2f:fa:0e:38:52:62:7b:55:8e:f3:4d:
+ 62:c5:c1:71:ff:ab:f2:57:54:21:7d:64:7d:07:dd:d8:d9:26:
+ c2:07:39:8f
-----BEGIN CERTIFICATE-----
MIIDYzCCAkugAwIBAgIBBDANBgkqhkiG9w0BAQsFADAPMQ0wCwYDVQQDDARSb290
MB4XDTE1MDEwMTEyMDAwMFoXDTE2MDEwMTEyMDAwMFowDTELMAkGA1UEAwwCSTIw
-ggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDFKgbxc3JDNwovJCQyawT9
-XQ4Xtjs38FkJEDnw7s2bQ+Cd6WNuBUJe+LgmeGucvQzMhYsQ6HvvA49uhP4wZPch
-eD4r5C7SUUrnkuNEwuvLs/58RG4X4Mx7OU1xWZvW6I0mvUn6PrAnljYs8GHKqcAA
-7YVwaWS0gXFpqFJ0NNdhbHyEmt6CBzsY3IU1EbcLOolZHSNiSJHPYA/E6lfKQo7o
-UhoTVi0cW3A6ZC+htNfeURlXY20QyKMbHZKW3Df6i2A6Z3xhCyQVVGjisHSzGs0z
-TDxJ4VbrfVkH64d6vG/06DsrxtDmrnrfBNSZJ31PpyLqfWr/aRq4bvVKGA+YGiIn
-AgMBAAGjgcswgcgwHQYDVR0OBBYEFP1ezK+3RP3qsypQHR6gKwAc59KEMB8GA1Ud
-IwQYMBaAFFMAHXBInpBEFEGgkm64He3qdx+BMDcGCCsGAQUFBwEBBCswKTAnBggr
+ggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQC9hN2CN8vIaYrCxv8494WT
+niLVuJQSO9mfSXDv/zlY/Oc2Mhg31CvZTk5nYO4sKNBPZiPNwfB19VQOUaXw+py9
+Ql0COmJgg7jl/s28rTW3ngnsOoFRt0ZWLZC75UpPasa+OXm2MZkbxNChlNzlUY6d
+qcXYkflcdjoJ0o8MJDr/kUzGycc2U8x46/wAJf1fs8CVEJE9Q/4xtrOE6exfG1p3
+pyUpGnpx2XpihUXDUdrteaVBfQtJPitRXpkzHxxaUlFrB8VaC0u24WxDB/KyZW6d
+d6kqtoh7qdmXa2X5vk45MUygLQYY3lN8v4BkzCt6sCt2A8RAplPx3HSH+8XYL/Xv
+AgMBAAGjgcswgcgwHQYDVR0OBBYEFLf7VHcMdnSwcoQvTq8kH8pijZlhMB8GA1Ud
+IwQYMBaAFLXDZV+VavcZMOOA3e+wpBs9vqadMDcGCCsGAQUFBwEBBCswKTAnBggr
BgEFBQcwAoYbaHR0cDovL3VybC1mb3ItYWlhL1Jvb3QuY2VyMCwGA1UdHwQlMCMw
IaAfoB2GG2h0dHA6Ly91cmwtZm9yLWNybC9Sb290LmNybDAOBgNVHQ8BAf8EBAMC
-AQYwDwYDVR0TAQH/BAUwAwEB/zANBgkqhkiG9w0BAQsFAAOCAQEAAqC1lBQqlEQf
-JfIYnmSK9rNiNZXKxash5xjTskFag6w6nLwhPU9uSpQx2nEW3ErmvBWEbF4QuW5i
-9Lq4msX1U/kpFoOr/YqBezk+yS+Dwzf34wpNR7z8/1IycMdQIRW2F3ntGB6anKj5
-0p52BuM9zS9VbeLl6iD3A4B/whM9mU840LhDbhJpgnl5DBbLbcsvtyrbB3AqIJZF
-gAOfRQ2Rvingr0r92GjvhrGFzH2aJNBypDMPLn/O4tQQjos6+NOgE67KO+8rOdG6
-3TWYakTTD/i3R/QIPPFBRflnAXAM/FF7okk5HzEJ44x9mMcZzqHOpkA/yilW9JAq
-QiWEL/F5+g==
+AQYwDwYDVR0TAQH/BAUwAwEB/zANBgkqhkiG9w0BAQsFAAOCAQEATHvdYfwe6lrX
+c66KOxQZOoyupaU3GnSHqd6fedtdrZKFRmU1qHeMwk64kGd/7O17qbkdaicFIhmS
+bEYCTzqcaWcpEjPi1tvBDHnLEHer2d93G5zSc47mMXL0BCTLZ7NzzAKDf777AQ9x
+JcACsSOqdwN0KP1emwOvRGDl9L7BxGRqF0er/rP1R9y4+BzCz7tXymUPc/AyTde1
+ODX3AYwT3qvezQGpXFfXLCMQcDTqtUrrEW2uNu5wOtKWcy085v5vVv/qVzlPynAb
+Dn4cdbACDU6Su8DmDn0WxAe5EgClpS/6DjhSYntVjvNNYsXBcf+r8ldUIX1kfQfd
+2Nkmwgc5jw==
-----END CERTIFICATE-----
diff --git a/chromium/net/data/cert_issuer_source_static_unittest/i3_1.pem b/chromium/net/data/cert_issuer_source_static_unittest/i3_1.pem
new file mode 100644
index 00000000000..823f1fdbb88
--- /dev/null
+++ b/chromium/net/data/cert_issuer_source_static_unittest/i3_1.pem
@@ -0,0 +1,90 @@
+Generated by ./generate-certs.py.
+Refer to generator script docstring for details.
+Certificate:
+ Data:
+ Version: 3 (0x2)
+ Serial Number: 5 (0x5)
+ Signature Algorithm: sha256WithRSAEncryption
+ Issuer: CN=Root
+ Validity
+ Not Before: Jan 1 12:00:00 2015 GMT
+ Not After : Jan 1 12:00:00 2016 GMT
+ Subject: CN=I3
+ Subject Public Key Info:
+ Public Key Algorithm: rsaEncryption
+ Public-Key: (2048 bit)
+ Modulus:
+ 00:cf:8e:d2:27:02:c2:6e:56:2d:b8:25:f0:79:03:
+ b6:98:d5:27:a0:32:ec:bb:43:36:63:ce:f3:c6:e3:
+ 4b:69:1e:57:13:9a:be:d5:a1:34:d3:63:ca:5f:09:
+ 25:aa:25:13:ac:55:9f:4a:a1:38:ad:be:ae:68:d0:
+ 60:d8:f7:21:d5:5f:fb:08:66:10:9a:f3:ee:09:5f:
+ af:7b:58:c0:19:ab:a7:4d:13:b5:35:16:3f:da:27:
+ 6c:64:03:d3:79:40:3b:93:a8:c8:f2:19:f4:1c:55:
+ 1c:e5:4e:57:19:05:28:ee:df:46:d0:b6:38:e7:ba:
+ 34:d9:44:8a:70:f1:86:ec:41:f3:6f:0d:da:76:e6:
+ 7a:6b:52:36:70:3e:6e:8e:58:75:a8:18:5b:6f:f4:
+ fc:9d:c3:d3:3f:a2:fc:58:ba:2a:5c:97:56:cb:e0:
+ 1a:32:58:5b:31:98:19:54:2c:7e:f1:53:ed:ba:4e:
+ 33:7a:d7:b8:96:f4:22:b8:59:b4:7c:8c:56:ea:3b:
+ 34:f8:2b:44:66:73:be:d7:11:f7:48:0b:e0:bd:ae:
+ 03:00:aa:c8:5d:5c:f5:6d:2a:0b:c2:63:0e:3f:97:
+ 28:3d:b4:7f:53:a9:1d:aa:a8:12:f2:c8:01:05:15:
+ a4:25:36:89:54:45:e0:54:e3:18:a5:84:2c:98:b6:
+ ba:9b
+ Exponent: 65537 (0x10001)
+ X509v3 extensions:
+ X509v3 Subject Key Identifier:
+ B3:B8:D0:C2:16:D7:60:93:F5:51:DB:DF:12:8A:B5:36:66:76:C4:6C
+ X509v3 Authority Key Identifier:
+ keyid:B5:C3:65:5F:95:6A:F7:19:30:E3:80:DD:EF:B0:A4:1B:3D:BE:A6:9D
+
+ Authority Information Access:
+ CA Issuers - URI:http://url-for-aia/Root.cer
+
+ X509v3 CRL Distribution Points:
+
+ Full Name:
+ URI:http://url-for-crl/Root.crl
+
+ X509v3 Key Usage: critical
+ Certificate Sign, CRL Sign
+ X509v3 Basic Constraints: critical
+ CA:TRUE
+ Signature Algorithm: sha256WithRSAEncryption
+ a8:4f:66:e2:7f:66:d8:76:bb:06:e1:2b:68:63:33:6c:6f:77:
+ f1:14:a6:26:8d:4e:9d:7a:ad:c3:44:ad:4b:f5:c0:80:dd:e4:
+ 1a:07:59:32:76:c9:f0:43:e5:0e:dd:b2:2b:1b:de:85:15:86:
+ 68:ed:7b:81:b5:42:88:72:6d:17:5e:3b:c8:e0:2b:d5:d2:8b:
+ 2b:be:78:b9:fd:24:a8:02:15:cf:fb:80:c7:03:5b:4b:1a:6e:
+ dc:72:33:9f:ce:37:8a:91:03:87:c5:af:e2:97:73:75:77:a6:
+ 5b:59:23:30:2b:9a:ab:91:fc:af:7c:4d:7c:98:6e:bd:aa:b8:
+ 70:27:91:c6:8a:6a:d1:aa:1e:1e:45:a1:8d:48:c2:92:31:46:
+ 58:57:59:e4:56:9d:c6:92:8d:33:b1:60:76:ec:c2:0e:35:5c:
+ 5d:c2:12:a7:d6:12:26:6a:5c:e6:59:8e:29:a0:a8:82:fe:63:
+ 2a:f2:6d:a3:84:ad:3a:7b:21:1e:39:01:22:a8:77:35:77:f9:
+ d0:e1:6b:1d:80:e5:63:18:2b:70:75:75:c7:0b:89:3e:6f:5a:
+ 03:9f:ff:d3:5b:ba:8c:d5:e9:f6:11:ec:fa:51:ea:85:23:80:
+ ce:65:5f:18:dd:43:47:2c:a7:95:15:4b:65:88:e1:ac:5c:73:
+ 97:03:e3:d9
+-----BEGIN CERTIFICATE-----
+MIIDYzCCAkugAwIBAgIBBTANBgkqhkiG9w0BAQsFADAPMQ0wCwYDVQQDDARSb290
+MB4XDTE1MDEwMTEyMDAwMFoXDTE2MDEwMTEyMDAwMFowDTELMAkGA1UEAwwCSTMw
+ggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDPjtInAsJuVi24JfB5A7aY
+1SegMuy7QzZjzvPG40tpHlcTmr7VoTTTY8pfCSWqJROsVZ9KoTitvq5o0GDY9yHV
+X/sIZhCa8+4JX697WMAZq6dNE7U1Fj/aJ2xkA9N5QDuTqMjyGfQcVRzlTlcZBSju
+30bQtjjnujTZRIpw8YbsQfNvDdp25nprUjZwPm6OWHWoGFtv9Pydw9M/ovxYuipc
+l1bL4BoyWFsxmBlULH7xU+26TjN617iW9CK4WbR8jFbqOzT4K0Rmc77XEfdIC+C9
+rgMAqshdXPVtKgvCYw4/lyg9tH9TqR2qqBLyyAEFFaQlNolUReBU4xilhCyYtrqb
+AgMBAAGjgcswgcgwHQYDVR0OBBYEFLO40MIW12CT9VHb3xKKtTZmdsRsMB8GA1Ud
+IwQYMBaAFLXDZV+VavcZMOOA3e+wpBs9vqadMDcGCCsGAQUFBwEBBCswKTAnBggr
+BgEFBQcwAoYbaHR0cDovL3VybC1mb3ItYWlhL1Jvb3QuY2VyMCwGA1UdHwQlMCMw
+IaAfoB2GG2h0dHA6Ly91cmwtZm9yLWNybC9Sb290LmNybDAOBgNVHQ8BAf8EBAMC
+AQYwDwYDVR0TAQH/BAUwAwEB/zANBgkqhkiG9w0BAQsFAAOCAQEAqE9m4n9m2Ha7
+BuEraGMzbG938RSmJo1OnXqtw0StS/XAgN3kGgdZMnbJ8EPlDt2yKxvehRWGaO17
+gbVCiHJtF147yOAr1dKLK754uf0kqAIVz/uAxwNbSxpu3HIzn843ipEDh8Wv4pdz
+dXemW1kjMCuaq5H8r3xNfJhuvaq4cCeRxopq0aoeHkWhjUjCkjFGWFdZ5FadxpKN
+M7FgduzCDjVcXcISp9YSJmpc5lmOKaCogv5jKvJto4StOnshHjkBIqh3NXf50OFr
+HYDlYxgrcHV1xwuJPm9aA5//01u6jNXp9hHs+lHqhSOAzmVfGN1DRyynlRVLZYjh
+rFxzlwPj2Q==
+-----END CERTIFICATE-----
diff --git a/chromium/net/data/cert_issuer_source_static_unittest/i3_2.pem b/chromium/net/data/cert_issuer_source_static_unittest/i3_2.pem
new file mode 100644
index 00000000000..c92719f4d1a
--- /dev/null
+++ b/chromium/net/data/cert_issuer_source_static_unittest/i3_2.pem
@@ -0,0 +1,90 @@
+Generated by ./generate-certs.py.
+Refer to generator script docstring for details.
+Certificate:
+ Data:
+ Version: 3 (0x2)
+ Serial Number: 6 (0x6)
+ Signature Algorithm: sha256WithRSAEncryption
+ Issuer: CN=Root
+ Validity
+ Not Before: Jan 1 12:00:00 2015 GMT
+ Not After : Jan 1 12:00:00 2016 GMT
+ Subject: CN=I3
+ Subject Public Key Info:
+ Public Key Algorithm: rsaEncryption
+ Public-Key: (2048 bit)
+ Modulus:
+ 00:c9:4c:34:72:23:55:0b:48:d2:a4:6e:69:e8:68:
+ 86:c2:7f:ff:18:a7:75:05:00:b8:76:f9:1e:89:38:
+ 4b:2c:b5:fa:56:93:96:28:a6:59:a4:e4:a5:e9:68:
+ a2:b5:0b:8d:32:b4:cf:94:e0:9f:11:14:66:9a:41:
+ 25:d6:de:f3:6b:ff:6a:b9:e5:61:6a:82:ce:65:75:
+ 1e:c6:78:14:53:90:17:83:a2:07:26:86:08:b6:9c:
+ 54:be:1d:0d:dd:53:01:5f:50:21:37:92:c0:a9:2f:
+ 8d:4a:51:48:73:1f:7e:17:93:5a:5c:53:c8:f0:25:
+ 3e:94:ca:b9:82:8e:5a:d5:98:c8:1f:c7:f8:8c:9c:
+ 87:7b:8e:ee:da:92:34:6e:ab:1d:43:50:7e:87:f9:
+ b8:f7:49:58:be:f7:54:78:e8:21:6d:96:45:fa:68:
+ 3b:99:9f:4a:86:40:b1:2e:fc:15:e4:28:8d:3b:13:
+ 50:8f:33:6a:b7:c3:fc:fb:d6:fd:0b:97:c6:05:d4:
+ 6b:82:38:b2:1d:e3:5b:9d:60:97:de:1d:bc:1a:ed:
+ bd:71:44:18:d6:4d:51:3a:db:8c:f6:da:ee:08:f9:
+ 2f:ca:b8:ee:5d:4e:1a:1a:38:8c:79:30:9f:ba:4e:
+ 54:eb:86:12:1f:cc:ec:5d:c4:36:07:89:bd:40:57:
+ c9:8f
+ Exponent: 65537 (0x10001)
+ X509v3 extensions:
+ X509v3 Subject Key Identifier:
+ 1B:D9:9D:7F:59:30:84:1C:E4:92:D1:19:FF:EA:8D:02:B3:C1:8E:50
+ X509v3 Authority Key Identifier:
+ keyid:B5:C3:65:5F:95:6A:F7:19:30:E3:80:DD:EF:B0:A4:1B:3D:BE:A6:9D
+
+ Authority Information Access:
+ CA Issuers - URI:http://url-for-aia/Root.cer
+
+ X509v3 CRL Distribution Points:
+
+ Full Name:
+ URI:http://url-for-crl/Root.crl
+
+ X509v3 Key Usage: critical
+ Certificate Sign, CRL Sign
+ X509v3 Basic Constraints: critical
+ CA:TRUE
+ Signature Algorithm: sha256WithRSAEncryption
+ 81:3a:5d:49:dd:8a:88:7b:91:2d:5f:81:b7:4d:3c:24:2c:36:
+ ae:da:4e:9a:8a:d6:8d:7a:eb:93:7c:af:ab:57:0b:29:3d:19:
+ 1d:ed:52:26:a9:3f:bc:aa:c2:27:21:d0:7a:6a:1e:15:82:73:
+ af:1b:0d:f0:45:9a:e4:88:68:b7:21:a5:4f:a3:de:49:6d:f4:
+ a7:f6:51:c9:de:53:57:88:7a:1e:1f:58:26:c3:34:7e:06:ca:
+ d1:53:c7:dc:c3:c6:6d:6f:0c:c9:4d:e4:ca:5a:e6:91:1a:03:
+ 02:ac:04:1a:2b:33:6d:82:94:62:11:8a:5c:12:02:6f:65:e8:
+ 9e:21:10:30:c4:1c:77:be:44:bb:38:1e:3b:93:6e:85:e8:6f:
+ 1e:7d:12:f4:e9:ae:11:06:11:12:4b:63:ae:cb:c6:77:58:c4:
+ 18:3f:aa:d5:bf:a1:30:0d:ce:d6:d7:4d:94:4e:4b:af:80:50:
+ 9a:5f:26:aa:49:c5:68:c4:3d:f2:e7:bc:38:6f:45:13:62:e4:
+ e2:1f:8d:54:f5:91:a3:06:22:49:ca:f3:f3:13:46:7c:09:90:
+ 48:ba:61:13:08:5a:b0:bd:ed:88:45:ed:bc:7c:9f:03:8c:5e:
+ a8:24:6e:4c:1c:9e:15:f9:d3:0d:d2:fd:be:ac:01:52:f5:7c:
+ 23:d7:1d:0b
+-----BEGIN CERTIFICATE-----
+MIIDYzCCAkugAwIBAgIBBjANBgkqhkiG9w0BAQsFADAPMQ0wCwYDVQQDDARSb290
+MB4XDTE1MDEwMTEyMDAwMFoXDTE2MDEwMTEyMDAwMFowDTELMAkGA1UEAwwCSTMw
+ggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDJTDRyI1ULSNKkbmnoaIbC
+f/8Yp3UFALh2+R6JOEsstfpWk5Yoplmk5KXpaKK1C40ytM+U4J8RFGaaQSXW3vNr
+/2q55WFqgs5ldR7GeBRTkBeDogcmhgi2nFS+HQ3dUwFfUCE3ksCpL41KUUhzH34X
+k1pcU8jwJT6UyrmCjlrVmMgfx/iMnId7ju7akjRuqx1DUH6H+bj3SVi+91R46CFt
+lkX6aDuZn0qGQLEu/BXkKI07E1CPM2q3w/z71v0Ll8YF1GuCOLId41udYJfeHbwa
+7b1xRBjWTVE624z22u4I+S/KuO5dThoaOIx5MJ+6TlTrhhIfzOxdxDYHib1AV8mP
+AgMBAAGjgcswgcgwHQYDVR0OBBYEFBvZnX9ZMIQc5JLRGf/qjQKzwY5QMB8GA1Ud
+IwQYMBaAFLXDZV+VavcZMOOA3e+wpBs9vqadMDcGCCsGAQUFBwEBBCswKTAnBggr
+BgEFBQcwAoYbaHR0cDovL3VybC1mb3ItYWlhL1Jvb3QuY2VyMCwGA1UdHwQlMCMw
+IaAfoB2GG2h0dHA6Ly91cmwtZm9yLWNybC9Sb290LmNybDAOBgNVHQ8BAf8EBAMC
+AQYwDwYDVR0TAQH/BAUwAwEB/zANBgkqhkiG9w0BAQsFAAOCAQEAgTpdSd2KiHuR
+LV+Bt008JCw2rtpOmorWjXrrk3yvq1cLKT0ZHe1SJqk/vKrCJyHQemoeFYJzrxsN
+8EWa5IhotyGlT6PeSW30p/ZRyd5TV4h6Hh9YJsM0fgbK0VPH3MPGbW8MyU3kylrm
+kRoDAqwEGiszbYKUYhGKXBICb2XoniEQMMQcd75EuzgeO5NuhehvHn0S9OmuEQYR
+EktjrsvGd1jEGD+q1b+hMA3O1tdNlE5Lr4BQml8mqknFaMQ98ue8OG9FE2Lk4h+N
+VPWRowYiScrz8xNGfAmQSLphEwhasL3tiEXtvHyfA4xeqCRuTByeFfnTDdL9vqwB
+UvV8I9cdCw==
+-----END CERTIFICATE-----
diff --git a/chromium/net/data/cert_issuer_source_static_unittest/root.pem b/chromium/net/data/cert_issuer_source_static_unittest/root.pem
index c9dfce85807..318c678629d 100644
--- a/chromium/net/data/cert_issuer_source_static_unittest/root.pem
+++ b/chromium/net/data/cert_issuer_source_static_unittest/root.pem
@@ -14,30 +14,30 @@ Certificate:
Public Key Algorithm: rsaEncryption
Public-Key: (2048 bit)
Modulus:
- 00:a5:0a:40:af:c7:bf:e5:59:4c:96:13:a9:79:fe:
- ea:f1:ed:96:d3:c2:44:56:9a:a8:d1:15:1b:df:43:
- 17:6e:4e:6c:9f:b8:4b:5b:6e:65:cb:ca:fe:00:0d:
- 39:7b:00:55:69:ae:ef:28:97:67:2e:49:20:e3:03:
- 78:98:66:b8:f3:f9:fc:79:ca:ec:f9:2d:8e:f4:33:
- 3c:74:e4:d7:07:08:9b:6f:a9:1b:50:c2:9a:5e:57:
- 15:cc:7c:64:e0:14:9c:77:7d:62:69:83:db:f2:85:
- 21:e9:02:41:18:45:0e:3a:3b:47:af:4a:c6:04:eb:
- 5b:bf:dc:09:d8:c1:ae:31:b3:a8:42:83:5f:0a:54:
- ff:fa:3e:28:b7:b4:45:5e:c7:4d:b7:d5:d1:b0:e7:
- 6c:87:d8:36:cb:5d:25:a9:18:d4:0b:fe:d8:47:88:
- 78:4e:f9:40:af:a2:3c:d7:91:25:16:b7:15:34:13:
- 6f:ae:c3:d7:2a:36:10:22:92:6c:9d:68:62:92:70:
- a9:c6:ff:98:9e:ea:cf:9f:a6:17:61:ff:f5:2e:5c:
- f5:79:cb:44:6e:be:a6:cf:b8:e6:8c:50:34:04:b3:
- ee:79:cf:67:7b:f9:ad:b5:85:50:11:10:2f:e1:43:
- 7d:fd:1a:45:5c:7b:5d:a5:bd:50:ac:5b:19:5e:20:
- 33:a9
+ 00:bc:0a:87:63:a0:a0:fe:a8:d4:b1:9b:54:19:d6:
+ 12:74:61:bc:42:6d:1c:6f:c8:96:e9:6a:3d:16:e8:
+ cf:3a:c3:2f:eb:a8:7d:be:0c:3f:46:8c:b7:6d:29:
+ 82:a8:38:6f:74:ca:9f:14:45:f7:e4:25:a5:26:ba:
+ 22:55:a3:b6:98:3a:c9:62:22:a5:24:71:8b:66:33:
+ fc:b5:20:aa:d1:8c:83:f7:b3:19:4e:59:51:fb:82:
+ d7:fc:ea:78:a6:02:7f:7f:80:6f:4d:d1:3e:61:d6:
+ d9:f9:40:51:85:0f:bf:2d:56:98:d0:d5:47:ed:47:
+ e3:1d:3f:e3:e3:55:11:98:6b:94:b0:9f:ac:98:34:
+ f5:e1:d9:d0:f7:bb:dc:de:3e:18:1f:06:81:30:41:
+ 8c:ba:70:98:ee:38:0f:a1:dc:5b:01:b0:b0:6a:5c:
+ 7b:10:d5:aa:8a:40:33:79:9c:71:44:3a:aa:e1:f0:
+ 70:5c:7e:eb:ae:7f:fb:4d:bb:4d:af:8e:7a:62:cd:
+ d9:d6:bf:74:7a:3c:8a:1a:74:07:7a:7c:29:b4:f7:
+ 8c:cc:52:19:1a:f1:d8:a4:9a:a5:35:83:9a:3f:b0:
+ 46:1b:15:ee:ae:94:c6:fd:96:f5:dd:e1:98:7b:48:
+ 8e:9a:e3:fb:1a:57:84:c1:ae:69:af:2f:d0:76:99:
+ e5:61
Exponent: 65537 (0x10001)
X509v3 extensions:
X509v3 Subject Key Identifier:
- 3D:DD:2C:00:BE:89:E0:43:4C:05:77:67:07:60:FC:AC:BE:48:D0:A4
+ B5:C3:65:5F:95:6A:F7:19:30:E3:80:DD:EF:B0:A4:1B:3D:BE:A6:9D
X509v3 Authority Key Identifier:
- keyid:3D:DD:2C:00:BE:89:E0:43:4C:05:77:67:07:60:FC:AC:BE:48:D0:A4
+ keyid:B5:C3:65:5F:95:6A:F7:19:30:E3:80:DD:EF:B0:A4:1B:3D:BE:A6:9D
Authority Information Access:
CA Issuers - URI:http://url-for-aia/Root.cer
@@ -52,39 +52,39 @@ Certificate:
X509v3 Basic Constraints: critical
CA:TRUE
Signature Algorithm: sha256WithRSAEncryption
- 47:35:34:46:02:c2:86:e2:11:86:8c:cd:65:15:08:a5:2a:f7:
- 21:d8:d7:ae:b8:0a:c2:e7:0c:a6:f6:bc:50:d4:e1:7e:53:f6:
- 77:7d:8d:39:a5:85:b6:e8:0d:ac:a8:25:16:da:f6:9d:f7:1f:
- 18:06:0b:bf:dd:e1:90:4e:90:7c:2b:24:77:b1:58:9b:39:fc:
- 2e:d1:0e:1d:c7:a4:c7:70:2c:92:78:19:49:5c:7c:3d:5a:a7:
- b7:f3:89:f5:4f:48:1d:39:4f:53:a8:6f:e3:7c:62:9b:db:c5:
- 3f:ca:8a:e9:fe:83:f3:b9:66:20:28:89:1a:2c:8f:8a:07:6e:
- 4d:7b:fb:7b:f9:48:6f:07:d0:b2:f3:7d:d6:c8:42:1f:81:41:
- 0b:af:6b:4d:e2:19:6a:4a:1e:37:5b:de:fe:f8:82:e5:0b:ef:
- bd:20:0f:e3:2a:81:1a:35:ab:6b:38:d3:a9:29:09:f5:28:a8:
- 13:d1:c4:a7:aa:ea:3f:e3:8b:be:20:24:93:8d:06:da:8c:ce:
- 01:b1:61:ce:33:bb:ea:96:d0:01:11:e0:81:06:bc:1c:7b:62:
- 99:d1:f3:ef:a8:a7:ec:6a:bb:e9:2c:d6:d1:52:f0:a1:b6:e2:
- 71:6a:f6:06:2d:9f:79:14:28:47:b8:dd:d9:02:65:a9:53:cf:
- f5:3d:b9:ee
+ 6a:84:0c:35:b2:ec:47:ab:8b:be:3c:6f:e7:ae:84:8a:7d:6c:
+ ca:00:6f:98:51:15:f7:e7:fb:89:a9:43:b0:01:6c:b7:33:0a:
+ c1:e2:95:1e:d1:df:ec:17:a3:07:14:9e:04:9f:b4:68:f5:ed:
+ 27:dc:49:e9:b0:74:5b:a2:a5:9d:f6:da:f3:bf:66:9e:dd:43:
+ bf:ff:80:06:36:0d:1a:ba:52:b1:e3:5b:06:71:ae:b5:b6:d2:
+ b9:bc:3a:73:c0:da:24:62:2b:7b:8f:25:f0:95:aa:5d:d3:d6:
+ 3c:6f:68:38:2f:98:e5:43:6b:95:e6:f6:75:87:28:88:6d:7e:
+ 94:15:b5:71:93:8e:b9:9d:38:74:49:5a:93:03:59:03:59:21:
+ 2b:7e:95:0e:4d:ec:5c:eb:44:97:08:43:11:dd:05:ab:46:7d:
+ 55:7f:33:b7:96:24:40:00:9a:50:8b:8c:d3:f1:87:84:3d:a6:
+ 3d:83:2e:e0:49:a4:25:8b:1c:2e:c5:d1:7d:3d:1d:52:75:33:
+ f6:e0:41:7b:fa:92:f1:b9:fa:63:cd:c3:91:2f:0a:ec:6f:77:
+ a6:e3:30:06:4f:19:98:0f:17:ca:61:65:5d:3b:b4:b8:80:8f:
+ d4:de:ad:75:d6:6a:34:e8:24:3a:ca:f2:d2:1b:e1:10:bd:64:
+ 78:37:21:26
-----BEGIN CERTIFICATE-----
MIIDZTCCAk2gAwIBAgIBATANBgkqhkiG9w0BAQsFADAPMQ0wCwYDVQQDDARSb290
MB4XDTE1MDEwMTEyMDAwMFoXDTE2MDEwMTEyMDAwMFowDzENMAsGA1UEAwwEUm9v
-dDCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAKUKQK/Hv+VZTJYTqXn+
-6vHtltPCRFaaqNEVG99DF25ObJ+4S1tuZcvK/gANOXsAVWmu7yiXZy5JIOMDeJhm
-uPP5/HnK7PktjvQzPHTk1wcIm2+pG1DCml5XFcx8ZOAUnHd9YmmD2/KFIekCQRhF
-Djo7R69KxgTrW7/cCdjBrjGzqEKDXwpU//o+KLe0RV7HTbfV0bDnbIfYNstdJakY
-1Av+2EeIeE75QK+iPNeRJRa3FTQTb67D1yo2ECKSbJ1oYpJwqcb/mJ7qz5+mF2H/
-9S5c9XnLRG6+ps+45oxQNASz7nnPZ3v5rbWFUBEQL+FDff0aRVx7XaW9UKxbGV4g
-M6kCAwEAAaOByzCByDAdBgNVHQ4EFgQUPd0sAL6J4ENMBXdnB2D8rL5I0KQwHwYD
-VR0jBBgwFoAUPd0sAL6J4ENMBXdnB2D8rL5I0KQwNwYIKwYBBQUHAQEEKzApMCcG
+dDCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBALwKh2OgoP6o1LGbVBnW
+EnRhvEJtHG/IlulqPRbozzrDL+uofb4MP0aMt20pgqg4b3TKnxRF9+QlpSa6IlWj
+tpg6yWIipSRxi2Yz/LUgqtGMg/ezGU5ZUfuC1/zqeKYCf3+Ab03RPmHW2flAUYUP
+vy1WmNDVR+1H4x0/4+NVEZhrlLCfrJg09eHZ0Pe73N4+GB8GgTBBjLpwmO44D6Hc
+WwGwsGpcexDVqopAM3mccUQ6quHwcFx+665/+027Ta+OemLN2da/dHo8ihp0B3p8
+KbT3jMxSGRrx2KSapTWDmj+wRhsV7q6Uxv2W9d3hmHtIjprj+xpXhMGuaa8v0HaZ
+5WECAwEAAaOByzCByDAdBgNVHQ4EFgQUtcNlX5Vq9xkw44Dd77CkGz2+pp0wHwYD
+VR0jBBgwFoAUtcNlX5Vq9xkw44Dd77CkGz2+pp0wNwYIKwYBBQUHAQEEKzApMCcG
CCsGAQUFBzAChhtodHRwOi8vdXJsLWZvci1haWEvUm9vdC5jZXIwLAYDVR0fBCUw
IzAhoB+gHYYbaHR0cDovL3VybC1mb3ItY3JsL1Jvb3QuY3JsMA4GA1UdDwEB/wQE
-AwIBBjAPBgNVHRMBAf8EBTADAQH/MA0GCSqGSIb3DQEBCwUAA4IBAQBHNTRGAsKG
-4hGGjM1lFQilKvch2NeuuArC5wym9rxQ1OF+U/Z3fY05pYW26A2sqCUW2vad9x8Y
-Bgu/3eGQTpB8KyR3sVibOfwu0Q4dx6THcCySeBlJXHw9Wqe384n1T0gdOU9TqG/j
-fGKb28U/yorp/oPzuWYgKIkaLI+KB25Ne/t7+UhvB9Cy833WyEIfgUELr2tN4hlq
-Sh43W97++ILlC++9IA/jKoEaNatrONOpKQn1KKgT0cSnquo/44u+ICSTjQbajM4B
-sWHOM7vqltABEeCBBrwce2KZ0fPvqKfsarvpLNbRUvChtuJxavYGLZ95FChHuN3Z
-AmWpU8/1Pbnu
+AwIBBjAPBgNVHRMBAf8EBTADAQH/MA0GCSqGSIb3DQEBCwUAA4IBAQBqhAw1suxH
+q4u+PG/nroSKfWzKAG+YURX35/uJqUOwAWy3MwrB4pUe0d/sF6MHFJ4En7Ro9e0n
+3EnpsHRboqWd9trzv2ae3UO//4AGNg0aulKx41sGca61ttK5vDpzwNokYit7jyXw
+lapd09Y8b2g4L5jlQ2uV5vZ1hyiIbX6UFbVxk465nTh0SVqTA1kDWSErfpUOTexc
+60SXCEMR3QWrRn1VfzO3liRAAJpQi4zT8YeEPaY9gy7gSaQlixwuxdF9PR1SdTP2
+4EF7+pLxufpjzcORLwrsb3em4zAGTxmYDxfKYWVdO7S4gI/U3q111mo06CQ6yvLS
+G+EQvWR4NyEm
-----END CERTIFICATE-----
diff --git a/chromium/net/data/ftp/dir-listing-ls-34 b/chromium/net/data/ftp/dir-listing-ls-34
new file mode 100644
index 00000000000..6286ed186f4
--- /dev/null
+++ b/chromium/net/data/ftp/dir-listing-ls-34
@@ -0,0 +1,2 @@
+-rw-rw-r-- 1 ftpuser ftpusers 1761280 Dec 20 2002 controle_embarqu‚_avec_labview_real_time_et_compactfieldpoint.ppt
+-rw-rw-r-- 1 ftpuser ftpusers 329216 Dec 20 2002 optimisez_l'acquisition_de_donn‚es_sous_labview.ppt
diff --git a/chromium/net/data/ftp/dir-listing-ls-34.expected b/chromium/net/data/ftp/dir-listing-ls-34.expected
new file mode 100644
index 00000000000..d197cb362c8
--- /dev/null
+++ b/chromium/net/data/ftp/dir-listing-ls-34.expected
@@ -0,0 +1,17 @@
+-
+controle_embarqu�_avec_labview_real_time_et_compactfieldpoint.ppt
+1761280
+2002
+12
+20
+0
+0
+
+-
+optimisez_l'acquisition_de_donnFs_sous_labview.ppt
+329216
+2002
+12
+20
+0
+0
diff --git a/chromium/net/data/fuzzer_data/net_url_request_ftp_fuzzer/epsv-mode.txt b/chromium/net/data/fuzzer_data/net_url_request_ftp_fuzzer/epsv-mode.txt
new file mode 100644
index 00000000000..00f77e94ec6
--- /dev/null
+++ b/chromium/net/data/fuzzer_data/net_url_request_ftp_fuzzer/epsv-mode.txt
Binary files differ
diff --git a/chromium/net/data/fuzzer_data/net_url_request_ftp_fuzzer/pasv-mode.txt b/chromium/net/data/fuzzer_data/net_url_request_ftp_fuzzer/pasv-mode.txt
new file mode 100644
index 00000000000..e8ed414f8e2
--- /dev/null
+++ b/chromium/net/data/fuzzer_data/net_url_request_ftp_fuzzer/pasv-mode.txt
Binary files differ
diff --git a/chromium/net/data/fuzzer_dictionaries/net_http_transport_security_state_fuzzer.dict b/chromium/net/data/fuzzer_dictionaries/net_http_transport_security_state_fuzzer.dict
new file mode 100644
index 00000000000..8c0f09ebd3e
--- /dev/null
+++ b/chromium/net/data/fuzzer_dictionaries/net_http_transport_security_state_fuzzer.dict
@@ -0,0 +1,62 @@
+# Copyright 2016 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.
+
+# Fuzzer dictionary targetting (static) transport security state lookups.
+
+"xn--"
+
+# Common preloaded TLDs
+"com"
+"org"
+"org"
+"de"
+"cn"
+"net"
+"eu"
+"nl"
+"net"
+"us"
+"co.uk"
+
+# Characters in the Huffman Tree
+"\x00"
+"-"
+"."
+"0"
+"1"
+"2"
+"3"
+"4"
+"5"
+"6"
+"7"
+"8"
+"9"
+"a"
+"b"
+"c"
+"d"
+"e"
+"f"
+"g"
+"h"
+"i"
+"j"
+"k"
+"l"
+"m"
+"n"
+"o"
+"p"
+"q"
+"r"
+"s"
+"t"
+"u"
+"v"
+"w"
+"x"
+"y"
+"z"
+"\x7F"
diff --git a/chromium/net/data/fuzzer_dictionaries/net_url_request_ftp_fuzzer.dict b/chromium/net/data/fuzzer_dictionaries/net_url_request_ftp_fuzzer.dict
new file mode 100644
index 00000000000..eb4acff145d
--- /dev/null
+++ b/chromium/net/data/fuzzer_dictionaries/net_url_request_ftp_fuzzer.dict
@@ -0,0 +1,59 @@
+# Copyright 2016 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.
+
+# Fuzzer dictionary targetting FTP responses.
+
+# Each response is on its own line, so CRLF is generally useful.
+"\x0D\x0A"
+
+# End of string marker, used by FuzzedDataProvider.
+"\\ "
+
+# Suffixes for file types.
+";type=a"
+";type=i"
+";type=d"
+
+# Dashes indicate multi-line responses.
+"-"
+
+# Generic success.
+"200 OK\x0D\x0A\\ "
+
+# Greeting
+"230 Welcome\x0D\x0A\\ "
+
+# SIZE response
+"213 18\x0D\x0A\\ "
+
+# All important PASV/EPSV responses
+"227 Entering PASV mode (1,1,1,1,50,50)\x0D\x0A\\ "
+"227 Entering Passive Mode 127,0,0,1,123,456\x0D\x0A\\ "
+"227 Entering Extended Passive Mode (|||31744|)\x0D\x0A\\ "
+"227 Entering The Twilight Zone\x0D\x0A\\ "
+
+# RETR/LIST response.
+"125-Data connection already open.\x0D\x0A125 Transfer starting.\x0D\x0A226 Transfer complete.\x0D\x0A\\ "
+"125-Data connection already open.\x0D\x0A\\ "
+"125 Transfer starting.\x0D\x0A\\ "
+"226 Transfer complete.\x0D\x0A\\ "
+
+# Some specific success messages, taken from unittests.
+"215 UNIX\x0D\x0A\\ "
+"215 VMS\x0D\x0A\\ "
+"220 host TestFTPd\x0D\x0A\\ "
+"221 Goodbye!\x0D\x0A\\ "
+"257 \"/\" is your current location\x0D\x0A\\ "
+"257 \"ANONYMOUS_ROOT:[000000]\"\x0D\x0A\\ "
+
+# Error messages, taken from unittests.
+"331 Password needed\x0D\x0A\\ "
+"331 User okay, send password\x0D\x0A\\ "
+"451 not a directory\x0D\x0A\\ "
+"500 EPSV command unknown\x0D\x0A\\ "
+"503 Bad sequence of commands\x0D\x0A\\ "
+"530 Login authentication failed\x0D\x0A\\ "
+"550 I can only retrieve regular files\x0D\x0A\\ "
+"550 Not a directory\x0D\x0A\\ "
+"599 I'm sorry, Dave, I'm afraid I can't do that.\x0D\x0A\\ "
diff --git a/chromium/net/data/name_constraints_unittest/dnsname-excluded_with_leading_dot.pem b/chromium/net/data/name_constraints_unittest/dnsname-excluded_with_leading_dot.pem
new file mode 100644
index 00000000000..fe355ee6b88
--- /dev/null
+++ b/chromium/net/data/name_constraints_unittest/dnsname-excluded_with_leading_dot.pem
@@ -0,0 +1,7 @@
+ 0:d=0 hl=2 l= 14 cons: SEQUENCE
+ 2:d=1 hl=2 l= 12 cons: cont [ 1 ]
+ 4:d=2 hl=2 l= 10 cons: SEQUENCE
+ 6:d=3 hl=2 l= 8 prim: cont [ 2 ]
+-----BEGIN NAME CONSTRAINTS-----
+MA6hDDAKggguYmFyLmNvbQ==
+-----END NAME CONSTRAINTS-----
diff --git a/chromium/net/data/name_constraints_unittest/dnsname-permitted_two_dot.pem b/chromium/net/data/name_constraints_unittest/dnsname-permitted_two_dot.pem
new file mode 100644
index 00000000000..fba4b2b4cd5
--- /dev/null
+++ b/chromium/net/data/name_constraints_unittest/dnsname-permitted_two_dot.pem
@@ -0,0 +1,7 @@
+ 0:d=0 hl=2 l= 8 cons: SEQUENCE
+ 2:d=1 hl=2 l= 6 cons: cont [ 0 ]
+ 4:d=2 hl=2 l= 4 cons: SEQUENCE
+ 6:d=3 hl=2 l= 2 prim: cont [ 2 ]
+-----BEGIN NAME CONSTRAINTS-----
+MAigBjAEggIuLg==
+-----END NAME CONSTRAINTS-----
diff --git a/chromium/net/data/name_constraints_unittest/generate_name_constraints.py b/chromium/net/data/name_constraints_unittest/generate_name_constraints.py
index cdf54940f3c..3096db8a1f9 100755
--- a/chromium/net/data/name_constraints_unittest/generate_name_constraints.py
+++ b/chromium/net/data/name_constraints_unittest/generate_name_constraints.py
@@ -211,6 +211,14 @@ def main():
dnsname_constraints3.add_permitted(dns_name(".bar.com"))
generate(dnsname_constraints3, "dnsname-permitted_with_leading_dot.pem")
+ dnsname_constraints4 = NameConstraintsGenerator()
+ dnsname_constraints4.add_excluded(dns_name(".bar.com"))
+ generate(dnsname_constraints4, "dnsname-excluded_with_leading_dot.pem")
+
+ dnsname_constraints5 = NameConstraintsGenerator()
+ dnsname_constraints5.add_permitted(dns_name(".."))
+ generate(dnsname_constraints5, "dnsname-permitted_two_dot.pem")
+
c = NameConstraintsGenerator()
c.add_excluded(dns_name("excluded.permitted.example.com"))
generate(c, "dnsname-excluded.pem")
diff --git a/chromium/net/data/quic_http_response_cache_data/www.example.com/index.html b/chromium/net/data/quic_http_response_cache_data/www.example.com/index.html
new file mode 100644
index 00000000000..5edaf9af7b5
--- /dev/null
+++ b/chromium/net/data/quic_http_response_cache_data/www.example.com/index.html
@@ -0,0 +1,63 @@
+HTTP/1.1 200 OK
+Date: Tue, 28 Aug 2012 15:08:56 GMT
+Server: Apache/2.2.3 (CentOS)
+X-Powered-By: PHP/5.1.6
+Set-Cookie: bblastvisit=1346166536; expires=Wed, 28-Aug-2013 15:08:56 GMT; path=/; domain=.nasioc.com
+Set-Cookie: bblastactivity=0; expires=Wed, 28-Aug-2013 15:08:56 GMT; path=/; domain=.nasioc.com
+Expires: 0
+Cache-Control: private, post-check=0, pre-check=0, max-age=0
+Pragma: no-cache
+X-UA-Compatible: IE=7
+Connection: close
+Content-Type: text/html; charset=ISO-8859-1
+
+<!doctype html>
+<html>
+<head>
+ <title>Example Domain</title>
+
+ <meta charset="utf-8" />
+ <meta http-equiv="Content-type" content="text/html; charset=utf-8" />
+ <meta name="viewport" content="width=device-width, initial-scale=1" />
+ <style type="text/css">
+ body {
+ background-color: #f0f0f2;
+ margin: 0;
+ padding: 0;
+ font-family: "Open Sans", "Helvetica Neue", Helvetica, Arial, sans-serif;
+
+ }
+ div {
+ width: 600px;
+ margin: 5em auto;
+ padding: 50px;
+ background-color: #fff;
+ border-radius: 1em;
+ }
+ a:link, a:visited {
+ color: #38488f;
+ text-decoration: none;
+ }
+ @media (max-width: 700px) {
+ body {
+ background-color: #fff;
+ }
+ div {
+ width: auto;
+ margin: 0 auto;
+ border-radius: 0;
+ padding: 1em;
+ }
+ }
+ </style>
+</head>
+
+<body>
+<div>
+ <h1>Example Domain</h1>
+ <p>This domain is established to be used for illustrative examples in documents. You may use this
+ domain in examples without prior coordination or asking for permission.</p>
+ <p><a href="http://www.iana.org/domains/example">More information...</a></p>
+</div>
+</body>
+</html>
diff --git a/chromium/net/data/quic_http_response_cache_data/www.example.com/map.html b/chromium/net/data/quic_http_response_cache_data/www.example.com/map.html
new file mode 100644
index 00000000000..470faa1a935
--- /dev/null
+++ b/chromium/net/data/quic_http_response_cache_data/www.example.com/map.html
@@ -0,0 +1,65 @@
+HTTP/1.1 200 OK
+Date: Tue, 28 Aug 2012 15:08:56 GMT
+Server: Apache/2.2.3 (CentOS)
+X-Powered-By: PHP/5.1.6
+Set-Cookie: bblastvisit=1346166536; expires=Wed, 28-Aug-2013 15:08:56 GMT; path=/; domain=.nasioc.com
+Set-Cookie: bblastactivity=0; expires=Wed, 28-Aug-2013 15:08:56 GMT; path=/; domain=.nasioc.com
+Expires: 0
+Cache-Control: private, post-check=0, pre-check=0, max-age=0
+Pragma: no-cache
+X-UA-Compatible: IE=7
+Connection: close
+Content-Type: text/html; charset=ISO-8859-1
+X-Original-Url: http://www.example.com/site_map.html
+
+
+<!doctype html>
+<html>
+<head>
+ <title>Example Domain</title>
+
+ <meta charset="utf-8" />
+ <meta http-equiv="Content-type" content="text/html; charset=utf-8" />
+ <meta name="viewport" content="width=device-width, initial-scale=1" />
+ <style type="text/css">
+ body {
+ background-color: #f0f0f2;
+ margin: 0;
+ padding: 0;
+ font-family: "Open Sans", "Helvetica Neue", Helvetica, Arial, sans-serif;
+
+ }
+ div {
+ width: 600px;
+ margin: 5em auto;
+ padding: 50px;
+ background-color: #fff;
+ border-radius: 1em;
+ }
+ a:link, a:visited {
+ color: #38488f;
+ text-decoration: none;
+ }
+ @media (max-width: 700px) {
+ body {
+ background-color: #fff;
+ }
+ div {
+ width: auto;
+ margin: 0 auto;
+ border-radius: 0;
+ padding: 1em;
+ }
+ }
+ </style>
+</head>
+
+<body>
+<div>
+ <h1>Example Domain</h1>
+ <p>This domain is established to be used for illustrative examples in documents. You may use this
+ domain in examples without prior coordination or asking for permission.</p>
+ <p><a href="http://www.iana.org/domains/example">More information...</a></p>
+</div>
+</body>
+</html>
diff --git a/chromium/net/data/quic_in_memory_cache_data_with_push/quic-datatesturl.com/favicon.ico b/chromium/net/data/quic_http_response_cache_data_with_push/www.example.com/favicon.ico
index a559c5856e1..b7b01b5e3fb 100644
--- a/chromium/net/data/quic_in_memory_cache_data_with_push/quic-datatesturl.com/favicon.ico
+++ b/chromium/net/data/quic_http_response_cache_data_with_push/www.example.com/favicon.ico
Binary files differ
diff --git a/chromium/net/data/quic_in_memory_cache_data/quic-datatesturl.com/index.html b/chromium/net/data/quic_http_response_cache_data_with_push/www.example.com/index.html
index 71aaeb0c622..bfcb61430f1 100644
--- a/chromium/net/data/quic_in_memory_cache_data/quic-datatesturl.com/index.html
+++ b/chromium/net/data/quic_http_response_cache_data_with_push/www.example.com/index.html
@@ -9,6 +9,7 @@ Content-Encoding: None
Keep-Alive: timeout=5, max=100
Connection: close
Content-Type: text/html
-X-Original-Url: http://quic.test.url/index.html
+X-Original-Url: https://www.example.com/
+X-Push-Url: https://www.example.com/kitten-1.jpg
This is a test page.
diff --git a/chromium/net/data/quic_in_memory_cache_data_with_push/quic-datatesturl.com/index2.html b/chromium/net/data/quic_http_response_cache_data_with_push/www.example.com/index2.html
index 74afa66a0bb..58c5db9d484 100644
--- a/chromium/net/data/quic_in_memory_cache_data_with_push/quic-datatesturl.com/index2.html
+++ b/chromium/net/data/quic_http_response_cache_data_with_push/www.example.com/index2.html
@@ -9,8 +9,8 @@ Content-Encoding: None
Keep-Alive: timeout=5, max=100
Connection: close
Content-Type: text/html
-X-Original-Url: https://quic.test.url/index2.html
-X-Push-Url: https://quic.test.url/kitten-1.jpg
-X-Push-Url: https://quic.test.url/favicon.ico
+X-Original-Url: https://www.example.com/index2.html
+X-Push-Url: https://www.example.com/kitten-1.jpg
+X-Push-Url: https://www.example.com/favicon.ico
This is a test page.
diff --git a/chromium/net/data/quic_in_memory_cache_data_with_push/quic-datatesturl.com/kitten-1.jpg b/chromium/net/data/quic_http_response_cache_data_with_push/www.example.com/kitten-1.jpg
index 25ba08a5635..25d543b80b8 100644
--- a/chromium/net/data/quic_in_memory_cache_data_with_push/quic-datatesturl.com/kitten-1.jpg
+++ b/chromium/net/data/quic_http_response_cache_data_with_push/www.example.com/kitten-1.jpg
Binary files differ
diff --git a/chromium/net/data/quic_in_memory_cache_data_with_push/quic-datatesturl.com/index.html b/chromium/net/data/quic_in_memory_cache_data_with_push/quic-datatesturl.com/index.html
deleted file mode 100644
index d13a4d0258a..00000000000
--- a/chromium/net/data/quic_in_memory_cache_data_with_push/quic-datatesturl.com/index.html
+++ /dev/null
@@ -1,15 +0,0 @@
-HTTP/1.1 200 OK
-Date: Sat, 22 Jun 2013 01:21:01 GMT
-Server: Apache/2.2.22 (Ubuntu)
-Last-Modified: Fri, 21 Jun 2013 22:20:24 GMT
-ETag: "2a9d2-98-4dfb17827450a"
-Accept-Ranges: bytes
-Vary: Accept-Encoding
-Content-Encoding: None
-Keep-Alive: timeout=5, max=100
-Connection: close
-Content-Type: text/html
-X-Original-Url: https://quic.test.url/
-X-Push-Url: https://quic.test.url/kitten-1.jpg
-
-This is a test page.
diff --git a/chromium/net/data/ssl/blacklist/1c01c6f4dbb2fefc22558b2bca32563f49844acfc32b7be4b0ff599f9e8c7af7.pem b/chromium/net/data/ssl/blacklist/1c01c6f4dbb2fefc22558b2bca32563f49844acfc32b7be4b0ff599f9e8c7af7.pem
new file mode 100644
index 00000000000..b5e4f9a1a26
--- /dev/null
+++ b/chromium/net/data/ssl/blacklist/1c01c6f4dbb2fefc22558b2bca32563f49844acfc32b7be4b0ff599f9e8c7af7.pem
@@ -0,0 +1,24 @@
+-----BEGIN CERTIFICATE-----
+MIID9zCCAt+gAwIBAgIESJ8AATANBgkqhkiG9w0BAQUFADCBijELMAkGA1UEBhMC
+Q04xMjAwBgNVBAoMKUNoaW5hIEludGVybmV0IE5ldHdvcmsgSW5mb3JtYXRpb24g
+Q2VudGVyMUcwRQYDVQQDDD5DaGluYSBJbnRlcm5ldCBOZXR3b3JrIEluZm9ybWF0
+aW9uIENlbnRlciBFViBDZXJ0aWZpY2F0ZXMgUm9vdDAeFw0xMDA4MzEwNzExMjVa
+Fw0zMDA4MzEwNzExMjVaMIGKMQswCQYDVQQGEwJDTjEyMDAGA1UECgwpQ2hpbmEg
+SW50ZXJuZXQgTmV0d29yayBJbmZvcm1hdGlvbiBDZW50ZXIxRzBFBgNVBAMMPkNo
+aW5hIEludGVybmV0IE5ldHdvcmsgSW5mb3JtYXRpb24gQ2VudGVyIEVWIENlcnRp
+ZmljYXRlcyBSb290MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAm35z
+7r07eKpkQ0H1UN+U8i6yjUqORlTSIRLIOTJCBumD1Z9S7eVnAztUwYyZmczpwA//
+DdmEEbK40ctb3B75aDFk4Zv6dOtouSCV98YPjUesWgbdYavi7NifFy2cyjw1l1Vx
+zUOFsUcW9SxTgHbP0wBkvUCZ3czY28Sf1hNfQYOL+Q2HklY0bBoQCxfVWhyXWIQ8
+hBouXJE0bhlffxdpxWXvayHG1VA6v2G5BY3vbzQ6sm8UY78WO5upKv23KzhmBsUs
+4qpnHkWnjQRmQvaPK++IIGmPMowUc9orhpFjIpryp9vOiYurXccUwVswah+xt54u
+gQEC7c+WXmPbqOY4twIDAQABo2MwYTAfBgNVHSMEGDAWgBR8cks5x8DbYqVPm6oY
+NJKiyoOCWTAPBgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB/wQEAwIBBjAdBgNVHQ4E
+FgQUfHJLOcfA22KlT5uqGDSSosqDglkwDQYJKoZIhvcNAQEFBQADggEBACrDx0M3
+j92tpLIM7twUbY8opJhJywyA6vPtI2Z1fcXTIWd50XPFtQO3WKwMVC/GVhMPMdoG
+52U7HW8228gd+f2ABsqjPWYWqJ1MFn3AlUa1UeTiH9fqBk1jjZaM7+czV0I664zB
+echNdn3e9rG3geCg+aF4RhcaVpjwTj2rHO3sOdwHSPdj/gauwqRcalsyiMXHM4Ws
+ZkJHwlgkmeHlPuV1LI5D1l08eB6olYIpUNHRFrrvwb562bTYzB5MRuF3sTGrvSrI
+zo9uoV1/A3U05K2JRVRevq4opbs/eHnrc7MKDf2+yfdWrPa37S+bISnHOLaVxATy
+wy39FCqQmbkHzJ8=
+-----END CERTIFICATE-----
diff --git a/chromium/net/data/ssl/blacklist/README.md b/chromium/net/data/ssl/blacklist/README.md
index 332bd47801d..937390a2178 100644
--- a/chromium/net/data/ssl/blacklist/README.md
+++ b/chromium/net/data/ssl/blacklist/README.md
@@ -8,6 +8,17 @@ are included.
## Compromises & Misissuances
+### China Internet Network Information Center (CNNIC)
+
+For details, see <https://security.googleblog.com/2015/03/maintaining-digital-certificate-security.html>
+
+As a result of misissuance of a sub-CA certificate, CNNIC end-entity
+certificates were temporarily whitelisted, and then trust in the root fully
+removed.
+
+ * [1c01c6f4dbb2fefc22558b2bca32563f49844acfc32b7be4b0ff599f9e8c7af7.pem](1c01c6f4dbb2fefc22558b2bca32563f49844acfc32b7be4b0ff599f9e8c7af7.pem)
+ * [e28393773da845a679f2080cc7fb44a3b7a1c3792cb7eb7729fdcb6a8d99aea7.pem](e28393773da845a679f2080cc7fb44a3b7a1c3792cb7eb7729fdcb6a8d99aea7.pem)
+
### Comodo
For details, see <https://www.comodo.com/Comodo-Fraud-Incident-2011-03-23.html>,
diff --git a/chromium/net/data/ssl/blacklist/e28393773da845a679f2080cc7fb44a3b7a1c3792cb7eb7729fdcb6a8d99aea7.pem b/chromium/net/data/ssl/blacklist/e28393773da845a679f2080cc7fb44a3b7a1c3792cb7eb7729fdcb6a8d99aea7.pem
new file mode 100644
index 00000000000..c81744b5f5e
--- /dev/null
+++ b/chromium/net/data/ssl/blacklist/e28393773da845a679f2080cc7fb44a3b7a1c3792cb7eb7729fdcb6a8d99aea7.pem
@@ -0,0 +1,20 @@
+-----BEGIN CERTIFICATE-----
+MIIDVTCCAj2gAwIBAgIESTMAATANBgkqhkiG9w0BAQUFADAyMQswCQYDVQQGEwJD
+TjEOMAwGA1UEChMFQ05OSUMxEzARBgNVBAMTCkNOTklDIFJPT1QwHhcNMDcwNDE2
+MDcwOTE0WhcNMjcwNDE2MDcwOTE0WjAyMQswCQYDVQQGEwJDTjEOMAwGA1UEChMF
+Q05OSUMxEzARBgNVBAMTCkNOTklDIFJPT1QwggEiMA0GCSqGSIb3DQEBAQUAA4IB
+DwAwggEKAoIBAQDTNfc/c3et6FtzF8LRb+1VvG7q6KR5smzDo+/hn7E7SIX1mlwh
+IhAsxYLO2uOabjfhhyzcuQxauohV3/2q2x8x6gHx3zkBwRP9SFIhxFXf2tizVHa6
+dLG3fdfA6PZZxU3Iva0fFNrfWEQlMhkqx35+jq44sDB7R3IJMfAw28Mbdim7aXZO
+V/kbZKKTVrdvmW7bCgScEeOAH8tjlBAKqeFkgjH5jCftppkA9nCTGPihNIaj3XrC
+GHn2emU1z5DrvTOTn1OrczvmmzQgLx3vqR1jGqCA2wMv+SYahtKNu6m+UjqHZ0gN
+v7Sg2Ca+I19zN38m5pIEo3/PIKe38zrKy5nLAgMBAAGjczBxMBEGCWCGSAGG+EIB
+AQQEAwIABzAfBgNVHSMEGDAWgBRl8jGtKvf33VKWCscCwQ7vptU7ETAPBgNVHRMB
+Af8EBTADAQH/MAsGA1UdDwQEAwIB/jAdBgNVHQ4EFgQUZfIxrSr3991SlgrHAsEO
+76bVOxEwDQYJKoZIhvcNAQEFBQADggEBAEs17szkrr/Dbq2flTtLP1se31cpolnK
+OOK5Gv+e5m4y3R6u6jW39ZORTtpC4cMXYFDy0VwmuYK36m3knITnA3kXr5g9lNvH
+ugDnuL8BV8F3RTIMO/G0HAiw/VGgod2aHRM2mm23xzy54cXZF/qD1T0VoDy7Hgvi
+yJA/qIYM/PmLXoXLT1tLYhFHxUV8BS9BsZ4QaRuZluBVeftOhpm4lNqGOGqTo+fL
+buXf6iFViZx9fX+Y9QCJ7uOEwFyWtcVG6kbghVW2G8kS1sHNzYDzAgE8yGnLRUhj
+2JTQ7IUOO04RZfSCjKY9ri4ilAnIXOo8gV0WKgOXFlUJ24pBgp5mmxE=
+-----END CERTIFICATE-----
diff --git a/chromium/net/data/ssl/certificates/README b/chromium/net/data/ssl/certificates/README
index 2d32454b5cc..0504acd914f 100644
--- a/chromium/net/data/ssl/certificates/README
+++ b/chromium/net/data/ssl/certificates/README
@@ -79,6 +79,15 @@ unit tests.
- client-nokey.p12 : A PKCS #12 file containing a client certificate (the same
as the one in client.p12) but no private key. The password is "12345".
+- client-empty-password.p12 : A PKCS #12 file containing an unencrypted client
+ certificate and a encrypted private key. The password is the empty string,
+ encoded as two zero bytes. (PKCS#12 passwords are encoded as
+ NUL-terminated UTF-16.)
+
+- client-null-password.p12 : A PKCS #12 file containing an unencrypted client
+ certificate and a encrypted private key. The password is the empty string,
+ encoded as the empty byte string.
+
- unittest.selfsigned.der : A self-signed certificate generated using private
key in unittest.key.bin. The common name is "unittest".
@@ -88,11 +97,6 @@ unit tests.
https://www.google.com:443.
- unittest.originbound.key.der: matching PrivateKeyInfo.
-- x509_verify_results.chain.pem : A simple certificate chain used to test that
- the correctly ordered, filtered certificate chain is returned during
- verification, regardless of the order in which the intermediate/root CA
- certificates are provided.
-
- test_mail_google_com.pem : A certificate signed by the test CA for
"mail.google.com". Because it is signed by that CA instead of the true CA
for that host, it will fail the
@@ -135,6 +139,12 @@ unit tests.
These certificates are the common certificates used by the Python test
server for simulating HTTPS connections.
+- intermediate_ca_cert.pem
+- ok_cert_by_intermediate.pem
+ These certificates simulate a more common chain of root (root_ca_cert.pem)
+ to intermediate (intermediate_ca_cert.pem) to leaf
+ (ok_cert_by_intermediate.pem).
+
- wildcard_.pem
A certificate and private key valid for *.example.org, used in various
net unit tests.
@@ -188,6 +198,11 @@ unit tests.
- tls_feature_extension.pem
A certificate that contains the TLS Feature Extension.
+- x509_verify_results.chain.pem : A simple certificate chain used to test that
+ the correctly ordered, filtered certificate chain is returned during
+ verification, regardless of the order in which the intermediate/root CA
+ certificates are provided.
+
===== From net/data/ssl/scripts/generate-weak-test-chains.sh
- 2048-rsa-root.pem
- {768-rsa,1024-rsa,2048-rsa,prime256v1-ecdsa}-intermediate.pem
@@ -237,6 +252,14 @@ unit tests.
- client_4.key
- client_4.pk8
- client_4_ca.pem
+- client_5.pem
+- client_5.key
+- client_5.pk8
+- client_5_ca.pem
+- client_6.pem
+- client_6.key
+- client_6.pk8
+- client_6_ca.pem
- client_root_ca.pem
This is a set of files used to unit test SSL client certificate
authentication.
@@ -254,6 +277,10 @@ unit tests.
Alternative Name fields recognized by Chrome OS.
- client_4.pem is similar to client_2.pem but is a P-256 ECDSA key rather
than RSA.
+ - client_5.pem is similar to client_2.pem but is a P-384 ECDSA key rather
+ than RSA.
+ - client_6.pem is similar to client_2.pem but is a P-521 ECDSA key rather
+ than RSA.
- client_root_ca.pem is the CA certificate which signed client_*_ca.pem.
===== From net/data/ssl/scripts/generate-bad-eku-certs.sh
diff --git a/chromium/net/data/ssl/certificates/client-empty-password.p12 b/chromium/net/data/ssl/certificates/client-empty-password.p12
new file mode 100644
index 00000000000..e0b514c4bfc
--- /dev/null
+++ b/chromium/net/data/ssl/certificates/client-empty-password.p12
Binary files differ
diff --git a/chromium/net/data/ssl/certificates/client-null-password.p12 b/chromium/net/data/ssl/certificates/client-null-password.p12
new file mode 100644
index 00000000000..a8c45a7e7fc
--- /dev/null
+++ b/chromium/net/data/ssl/certificates/client-null-password.p12
Binary files differ
diff --git a/chromium/net/data/ssl/certificates/client_1.key b/chromium/net/data/ssl/certificates/client_1.key
index ea61cc86221..0389e2208b2 100644
--- a/chromium/net/data/ssl/certificates/client_1.key
+++ b/chromium/net/data/ssl/certificates/client_1.key
@@ -1,27 +1,27 @@
-----BEGIN RSA PRIVATE KEY-----
-MIIEpAIBAAKCAQEAm6YXgn7EzskCJawNsyffHz5P/wgyL9LkkYDzyFXqSGl2Rs66
-YlPkfBQVHAJXXcRMZL6GJ0qi32cpWgEsbXSk1zAiySVDayNej+jXNsQRoa9HE1lG
-6SvH5ojlGhiRV9r9c2a55L6HePnG3B9BTU1nPT01fGqnYpaUxVDxqwMHeG1xdfvx
-SEvrDsKWjYOSxVgbXGGDTwhMhA1rF1X+e9yimag0UxsB1IhNxd5YCJVRyaVTnxM+
-KmUe0OUYAXuKMGFGeT0W99M7YA3v6o2ZbPy3LZ07lwuP8w6egk5pjDo8v81FCUZn
-Vhv/xHVr/1JH98X+heE6eCq4yC+NXrdLiLGzywIDAQABAoIBACa5VuYHhg1wYxFe
-UfY9uDw8s4he0KWnUWiF7aDtByHG4z9QlXx7JMBd+raCOpxAh0UVRakm34i3UMls
-u1HsEErdVfo3RCO2pAMnyct9UmmogwVkU8kVNGG9s0ofzKFQAXihmSQ45tmJQxlm
-yUdjN4k73j+7BTP5BMBmmAmU8lnadWGIX97WG6hbB5mjfzIGlZM11kUlaIFnm9/f
-UbrazpB6CdTeS5eML4ikLYfSoM/5r6r1gT01B8q16ZDEW5/mSmAgTPvyEY4XdKpZ
-te2KOJFs9EfPn1VgSpN5ebnwRVnXKEYM6VRi2Ssn5YwQs8zS1+Fd95VBANVwS+yj
-rehgaqECgYEAzK6Ru/iCJj4ecSXiuIN15H9mAcAG6WQmuPCLUc0eyvUZ0Mj57yjg
-irJjflScLcotR/YdBUfUX+//XDBiQ9lVWCmFtHwWoynMBC4p+mBcVbId1LEk/kn4
-Oyx2Zkp7ccIpOe5JU8788GSroZzvQs9Ic2AI3hz/vC+igokNQJiUd5ECgYEAwqxZ
-x2tLz1vNLDlfXhaFkhpttJoUV+rQteV9SsEqcAOBLgBqk49hwFTInQELpEtrzfo9
-3IW1C7C/e378OOlw+fBnBtmkTDfPy9XJd6b+VQWHsk/t1g2D2qYO0htrfwNpIe5V
-Ns15MGiMV7kA8KELx+gAokSUws90StTqtJFG35sCgYEAxMSRr23w2IjhRQ8RzSX8
-AQWEb+xF+LriCuqcVLBniN9lyPRcadEXQ97IjRsT5WU2cLamIXxzKyOSjvKolOdr
-B00rj123eXXl/qLOkjdurKeFzAHcOWWs8F4HGMFDuRHaBioQbjRPr15oLP6seMLC
-uL+65qRkKWp1xR2yEsZb/DECgYAbwLRf4KUDH8RFPLyizjUmmgvvxlOGIRy2Acx1
-3sntBCLjav3GoZc+8xdSgralKndo+vbcvFcOHpl9wqG0f1sy1pnpeReaIg7GsWiy
-XSU++7XXrttqO60De877FxuhFNxlEPQnBu3y/8SaMO64X00tp56Hg51tlGOw01/O
-dDOVZwKBgQCKvxUHZPD6Q+M5HI/HmFxsHj9SsSl2sACErQMk7ru/aimuz9YPBXks
-KeMzjIeRqtJadK9KQCBeGWmOFTLezgt+mceXn92nfNYMfdSkLzlyKZM2FW9Kk1Z/
-7YduboDUCiGg2PMn/qZPUiko3vkR6B3es/G+VC16mCrh9GksfsGHVg==
+MIIEpQIBAAKCAQEAyYDjdJs5t0m2REDwka5GhFCGi8cPzDTgEKaqZj3wzRX/T8m/
+/jIRTK1ZfHxuzT61GnGOiut8XSw28a7/WY0/1/cc3nTGm0PuvKmBjrilQCZ9Y8kb
+LC+lEQaD1y/TMErQN9W5/dE/bU91Cg0zIXJgX9a0pGyWeM7C87q9DRky/WwbN6eS
+89fAsRNPILn7fDiSB8X3d27fv/mfWgw9pz0lew3hY4nppOulvBdaRKgxJKX8KTBS
+cy3osDwkB+urQLamGsP/7igjIGy5yKOw8nXsnf1Gq+GDhS0E4Ca6seNEAOiXaAGC
+W7wfNyBP+aVHj0CNvDPN147I/PfGKG1ZSvdipwIDAQABAoIBAQCXSQF8pp4qklkZ
+3XfAqIuhA6RAhW/C7V/coIUGxjJoh79r9BkFjCmY2/13jSTTS+VEuUU/35U7jtqh
+kbV9UqNATfOKwTnrkJFJbCotMUxAYaV6qZ6RCiRwJ+gMQ4fXlhPGF9zQR63LMAC7
+TzW4QttAmT5+xFgk03di7izKDMVPpedFlbpBPClBvf5nFiQAGY8jIhyyT0rKuoTN
+iowciprIKeDg32vFCJAiIWgV687tTByjknpxYkH7H00kWctXklTKV44hSB07ayC7
+dMkskH+X2LHxxFj/YP6goYjlN3c+cW7SDnwoRyZUNuhU7N8Xo62Rp94axhvKekJ0
+t58nLwehAoGBAP/CXyZmyPWOfcrxO7OgpM/MQuGqF7etS57t6EphLhyTQOWCGK5Z
+OS8Zun9/JOKxLPpjxQJpETfSBg1Q7KFRpzpnkd7db2GFP1+gz3bbeO3hsR6pfcQs
+DxlUx/GHvX+i7c3wHfVgoBYG+cUugt44CzjYulLF/O5OZORGhujtxog1AoGBAMmx
+cXb7naEgwa1dkRP7+OfbEN+gyJKN0D0bn/TRhaRaAoFUTGRqnvpbGMTsU5o9eOnh
+pNhwBX1U/t/7nd9TcgCEqPBCKGAGOou29hq9rZ6whEvAF/rZXdzigaMGJF7MRq3l
+XtNPC4+B9BJmoVxEu/l6dAI0HYwYaNFdEk9SZjLrAoGBANRABp7j5hqDKjnlgNpN
+kvkwVsDYW95+3qcCYSh5Bb+JJO5SzRDD0wUXoQJ2DbJjvyP88F5Tu4pLreIXKomm
+LdX2ZcRCmFCiODmwRvwon28rQcZkeo720YEALv5u3AC0wg2KHBKrIa+mElplgw3Q
+DOAcXGSdEo7iWDBpp0RfL8eRAoGAI5kU7KomPR0Z8e5Uv9E2Mj3g8YdgPzWWbmKk
+zcH5M3PLg2YMgaCr5IYVjhQkAVIeODFiNe03mtJYldHEIHmK4nqHkrgqhiAzTxuA
+vmGB9kMzZmdGFDkvLuAvf0WDP9QQGXslTGhkIvUNzf2dNzrObo7lUMo/+M0KGwGx
+TJy/evcCgYEA2rvXrdrpTMq9RwmjZejX5FjKvCTME1n5RE/I7kOgr3J4FShhDRyU
+1wlVvQe7C6W59MVGF+9OAhth/lPDagv3WsBK0r6luabm3QwakAZLQqjpbD7Anw+Q
+0+KEtl2M7PI8gwY8lrdFSEC2tJYp8iu/ahniyVxZjf5mEic6BnqIx/4=
-----END RSA PRIVATE KEY-----
diff --git a/chromium/net/data/ssl/certificates/client_1.pem b/chromium/net/data/ssl/certificates/client_1.pem
index 33573d35a3f..9e520615625 100644
--- a/chromium/net/data/ssl/certificates/client_1.pem
+++ b/chromium/net/data/ssl/certificates/client_1.pem
@@ -5,31 +5,31 @@ Certificate:
Signature Algorithm: sha256WithRSAEncryption
Issuer: CN=B CA
Validity
- Not Before: Oct 4 18:53:24 2016 GMT
- Not After : Oct 2 18:53:24 2026 GMT
+ Not Before: Dec 9 20:18:57 2016 GMT
+ Not After : Dec 7 20:18:57 2026 GMT
Subject: CN=Client Cert A
Subject Public Key Info:
Public Key Algorithm: rsaEncryption
Public-Key: (2048 bit)
Modulus:
- 00:9b:a6:17:82:7e:c4:ce:c9:02:25:ac:0d:b3:27:
- df:1f:3e:4f:ff:08:32:2f:d2:e4:91:80:f3:c8:55:
- ea:48:69:76:46:ce:ba:62:53:e4:7c:14:15:1c:02:
- 57:5d:c4:4c:64:be:86:27:4a:a2:df:67:29:5a:01:
- 2c:6d:74:a4:d7:30:22:c9:25:43:6b:23:5e:8f:e8:
- d7:36:c4:11:a1:af:47:13:59:46:e9:2b:c7:e6:88:
- e5:1a:18:91:57:da:fd:73:66:b9:e4:be:87:78:f9:
- c6:dc:1f:41:4d:4d:67:3d:3d:35:7c:6a:a7:62:96:
- 94:c5:50:f1:ab:03:07:78:6d:71:75:fb:f1:48:4b:
- eb:0e:c2:96:8d:83:92:c5:58:1b:5c:61:83:4f:08:
- 4c:84:0d:6b:17:55:fe:7b:dc:a2:99:a8:34:53:1b:
- 01:d4:88:4d:c5:de:58:08:95:51:c9:a5:53:9f:13:
- 3e:2a:65:1e:d0:e5:18:01:7b:8a:30:61:46:79:3d:
- 16:f7:d3:3b:60:0d:ef:ea:8d:99:6c:fc:b7:2d:9d:
- 3b:97:0b:8f:f3:0e:9e:82:4e:69:8c:3a:3c:bf:cd:
- 45:09:46:67:56:1b:ff:c4:75:6b:ff:52:47:f7:c5:
- fe:85:e1:3a:78:2a:b8:c8:2f:8d:5e:b7:4b:88:b1:
- b3:cb
+ 00:c9:80:e3:74:9b:39:b7:49:b6:44:40:f0:91:ae:
+ 46:84:50:86:8b:c7:0f:cc:34:e0:10:a6:aa:66:3d:
+ f0:cd:15:ff:4f:c9:bf:fe:32:11:4c:ad:59:7c:7c:
+ 6e:cd:3e:b5:1a:71:8e:8a:eb:7c:5d:2c:36:f1:ae:
+ ff:59:8d:3f:d7:f7:1c:de:74:c6:9b:43:ee:bc:a9:
+ 81:8e:b8:a5:40:26:7d:63:c9:1b:2c:2f:a5:11:06:
+ 83:d7:2f:d3:30:4a:d0:37:d5:b9:fd:d1:3f:6d:4f:
+ 75:0a:0d:33:21:72:60:5f:d6:b4:a4:6c:96:78:ce:
+ c2:f3:ba:bd:0d:19:32:fd:6c:1b:37:a7:92:f3:d7:
+ c0:b1:13:4f:20:b9:fb:7c:38:92:07:c5:f7:77:6e:
+ df:bf:f9:9f:5a:0c:3d:a7:3d:25:7b:0d:e1:63:89:
+ e9:a4:eb:a5:bc:17:5a:44:a8:31:24:a5:fc:29:30:
+ 52:73:2d:e8:b0:3c:24:07:eb:ab:40:b6:a6:1a:c3:
+ ff:ee:28:23:20:6c:b9:c8:a3:b0:f2:75:ec:9d:fd:
+ 46:ab:e1:83:85:2d:04:e0:26:ba:b1:e3:44:00:e8:
+ 97:68:01:82:5b:bc:1f:37:20:4f:f9:a5:47:8f:40:
+ 8d:bc:33:cd:d7:8e:c8:fc:f7:c6:28:6d:59:4a:f7:
+ 62:a7
Exponent: 65537 (0x10001)
X509v3 extensions:
X509v3 Basic Constraints: critical
@@ -37,36 +37,36 @@ Certificate:
X509v3 Extended Key Usage:
TLS Web Server Authentication, TLS Web Client Authentication
Signature Algorithm: sha256WithRSAEncryption
- 19:9b:41:39:61:cf:f8:0f:62:98:43:1a:a4:fb:0b:71:f2:f0:
- c4:b5:39:bb:dc:d1:d7:33:44:89:66:13:ff:0a:5a:66:02:74:
- 6a:8d:8a:dc:a0:e0:d0:cc:8d:5f:1c:c0:34:c6:58:02:76:3b:
- b5:1a:81:a5:a7:a1:c5:81:14:52:0f:21:37:06:2d:dc:dc:9c:
- d0:d1:98:03:ac:d3:b5:12:0b:f8:b4:84:d8:bc:be:4d:27:fa:
- df:16:6e:dd:0a:33:b7:87:50:7e:fe:c6:8d:84:b2:2d:7f:58:
- 88:21:af:09:64:5e:4a:2d:f0:56:d4:3e:a3:dc:4c:aa:92:41:
- 04:c1:6e:56:46:d5:36:69:0d:2a:f6:f0:29:d3:7c:ac:b7:cf:
- 7f:18:bc:76:fa:8c:5a:76:81:67:db:b2:91:97:05:7d:14:da:
- 26:d5:67:fe:c5:d2:6a:2c:5f:f4:96:3a:e4:0e:f5:15:95:05:
- 57:de:b5:e5:96:b2:10:99:4a:b2:3a:ac:d2:ae:64:30:31:54:
- f0:b9:9f:1d:56:e8:da:e9:4e:42:e3:26:3d:f7:8c:3e:9c:dd:
- 42:77:9d:0c:67:52:73:94:c4:73:42:c2:b7:96:a4:44:4a:d5:
- e9:3d:b1:46:aa:38:0b:1f:7f:ae:01:c6:07:da:40:3b:c0:22:
- 61:c4:cb:80
+ 1f:ef:f9:19:b9:64:e7:15:e2:7f:4f:e0:9e:66:f0:2a:b8:8f:
+ 4e:63:0c:7c:d5:a0:37:68:d2:c8:c2:9a:7b:e1:bd:13:31:c8:
+ ca:ce:96:c0:13:0a:bd:5e:f2:3c:8a:4d:0a:82:61:7e:35:0b:
+ fc:07:83:82:6e:cc:97:18:ff:32:68:08:5b:1a:34:35:ca:f0:
+ d2:19:d0:f0:35:66:c8:0b:44:ac:94:75:28:d8:cc:c1:b7:32:
+ df:93:cb:94:48:43:c7:cc:06:d3:b8:6c:6a:b2:c0:9f:f7:ef:
+ dd:36:c0:81:f9:e8:f0:7f:1c:d9:c5:92:31:91:de:88:a6:8d:
+ 0c:9e:e5:bf:a9:91:69:09:24:b1:5b:70:45:10:e1:8c:38:99:
+ c3:06:95:da:6a:c5:02:20:f8:25:e2:0c:b2:76:e5:01:1c:4b:
+ 0b:77:5a:ec:ff:99:37:fc:38:ff:17:cb:42:1d:c2:2f:2f:1f:
+ d1:be:d5:c6:22:89:e9:73:9c:ff:a9:03:77:cb:28:e5:e8:7e:
+ 0d:80:d4:75:88:ab:79:0b:bc:e3:98:1f:6e:0b:44:e2:c4:8a:
+ e6:6c:1d:74:30:6a:84:a7:2d:84:96:c4:7c:a9:25:39:8e:c8:
+ 50:df:0f:41:3f:4b:cb:92:c9:92:ed:2a:73:f1:7d:c3:cf:60:
+ a7:af:ab:85
-----BEGIN CERTIFICATE-----
MIIC0jCCAbqgAwIBAgICEAAwDQYJKoZIhvcNAQELBQAwDzENMAsGA1UEAwwEQiBD
-QTAeFw0xNjEwMDQxODUzMjRaFw0yNjEwMDIxODUzMjRaMBgxFjAUBgNVBAMMDUNs
-aWVudCBDZXJ0IEEwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCbpheC
-fsTOyQIlrA2zJ98fPk//CDIv0uSRgPPIVepIaXZGzrpiU+R8FBUcAlddxExkvoYn
-SqLfZylaASxtdKTXMCLJJUNrI16P6Nc2xBGhr0cTWUbpK8fmiOUaGJFX2v1zZrnk
-vod4+cbcH0FNTWc9PTV8aqdilpTFUPGrAwd4bXF1+/FIS+sOwpaNg5LFWBtcYYNP
-CEyEDWsXVf573KKZqDRTGwHUiE3F3lgIlVHJpVOfEz4qZR7Q5RgBe4owYUZ5PRb3
-0ztgDe/qjZls/LctnTuXC4/zDp6CTmmMOjy/zUUJRmdWG//EdWv/Ukf3xf6F4Tp4
-KrjIL41et0uIsbPLAgMBAAGjLzAtMAwGA1UdEwEB/wQCMAAwHQYDVR0lBBYwFAYI
-KwYBBQUHAwEGCCsGAQUFBwMCMA0GCSqGSIb3DQEBCwUAA4IBAQAZm0E5Yc/4D2KY
-Qxqk+wtx8vDEtTm73NHXM0SJZhP/ClpmAnRqjYrcoODQzI1fHMA0xlgCdju1GoGl
-p6HFgRRSDyE3Bi3c3JzQ0ZgDrNO1Egv4tITYvL5NJ/rfFm7dCjO3h1B+/saNhLIt
-f1iIIa8JZF5KLfBW1D6j3EyqkkEEwW5WRtU2aQ0q9vAp03yst89/GLx2+oxadoFn
-27KRlwV9FNom1Wf+xdJqLF/0ljrkDvUVlQVX3rXllrIQmUqyOqzSrmQwMVTwuZ8d
-Vuja6U5C4yY994w+nN1Cd50MZ1JzlMRzQsK3lqREStXpPbFGqjgLH3+uAcYH2kA7
-wCJhxMuA
+QTAeFw0xNjEyMDkyMDE4NTdaFw0yNjEyMDcyMDE4NTdaMBgxFjAUBgNVBAMMDUNs
+aWVudCBDZXJ0IEEwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDJgON0
+mzm3SbZEQPCRrkaEUIaLxw/MNOAQpqpmPfDNFf9Pyb/+MhFMrVl8fG7NPrUacY6K
+63xdLDbxrv9ZjT/X9xzedMabQ+68qYGOuKVAJn1jyRssL6URBoPXL9MwStA31bn9
+0T9tT3UKDTMhcmBf1rSkbJZ4zsLzur0NGTL9bBs3p5Lz18CxE08guft8OJIHxfd3
+bt+/+Z9aDD2nPSV7DeFjiemk66W8F1pEqDEkpfwpMFJzLeiwPCQH66tAtqYaw//u
+KCMgbLnIo7Dydeyd/Uar4YOFLQTgJrqx40QA6JdoAYJbvB83IE/5pUePQI28M83X
+jsj898YobVlK92KnAgMBAAGjLzAtMAwGA1UdEwEB/wQCMAAwHQYDVR0lBBYwFAYI
+KwYBBQUHAwEGCCsGAQUFBwMCMA0GCSqGSIb3DQEBCwUAA4IBAQAf7/kZuWTnFeJ/
+T+CeZvAquI9OYwx81aA3aNLIwpp74b0TMcjKzpbAEwq9XvI8ik0KgmF+NQv8B4OC
+bsyXGP8yaAhbGjQ1yvDSGdDwNWbIC0SslHUo2MzBtzLfk8uUSEPHzAbTuGxqssCf
+9+/dNsCB+ejwfxzZxZIxkd6Ipo0MnuW/qZFpCSSxW3BFEOGMOJnDBpXaasUCIPgl
+4gyyduUBHEsLd1rs/5k3/Dj/F8tCHcIvLx/RvtXGIonpc5z/qQN3yyjl6H4NgNR1
+iKt5C7zjmB9uC0TixIrmbB10MGqEpy2ElsR8qSU5jshQ3w9BP0vLksmS7Spz8X3D
+z2Cnr6uF
-----END CERTIFICATE-----
diff --git a/chromium/net/data/ssl/certificates/client_1.pk8 b/chromium/net/data/ssl/certificates/client_1.pk8
index 19db6db36b1..12bf489caf5 100644
--- a/chromium/net/data/ssl/certificates/client_1.pk8
+++ b/chromium/net/data/ssl/certificates/client_1.pk8
Binary files differ
diff --git a/chromium/net/data/ssl/certificates/client_1_ca.pem b/chromium/net/data/ssl/certificates/client_1_ca.pem
index 88723ce6589..9d61c0a6544 100644
--- a/chromium/net/data/ssl/certificates/client_1_ca.pem
+++ b/chromium/net/data/ssl/certificates/client_1_ca.pem
@@ -5,31 +5,31 @@ Certificate:
Signature Algorithm: sha256WithRSAEncryption
Issuer: CN=C Root CA
Validity
- Not Before: Oct 4 18:53:24 2016 GMT
- Not After : Oct 2 18:53:24 2026 GMT
+ Not Before: Dec 9 20:18:57 2016 GMT
+ Not After : Dec 7 20:18:57 2026 GMT
Subject: CN=B CA
Subject Public Key Info:
Public Key Algorithm: rsaEncryption
Public-Key: (2048 bit)
Modulus:
- 00:a5:56:c7:9d:32:e7:3d:17:ac:59:ca:f4:07:65:
- 25:3e:65:7c:d9:3d:f4:0e:73:eb:b9:0b:a1:7b:4b:
- 69:ab:ee:a3:50:49:2f:25:33:4d:2d:ac:00:32:17:
- 34:0d:c9:bf:83:7d:b4:e5:d5:82:89:6f:ad:41:78:
- 56:1d:05:bc:48:cc:0c:43:95:81:e3:e8:12:2d:67:
- 74:68:12:61:8e:03:24:88:2c:57:28:8e:3d:10:77:
- da:dc:78:b6:b4:72:92:56:0e:4a:0c:c6:f7:0a:44:
- f5:56:5d:72:7a:a8:1d:bc:16:e8:95:25:4d:50:b6:
- 2e:22:05:fd:d5:20:47:a4:32:37:52:38:61:90:9a:
- aa:40:a8:db:91:80:00:89:e6:2c:17:5d:7c:5f:6f:
- 2d:b2:b7:cf:71:a1:55:11:d8:fd:3b:9b:61:8f:1c:
- 80:dd:da:90:8c:82:04:63:36:7c:b1:28:38:56:bc:
- 6e:c0:b3:b9:4e:96:2b:3f:62:2a:e5:5f:f1:73:3c:
- 53:a8:5f:03:d0:63:31:36:ac:00:61:30:ab:ad:d9:
- aa:ab:5d:22:83:28:cc:f1:f7:88:f5:9a:be:57:c5:
- e1:46:da:a3:88:55:a7:3c:f9:1c:17:bb:72:01:1d:
- dd:8e:a0:b0:a3:d1:91:74:ae:94:58:c0:f5:30:63:
- 5c:91
+ 00:b3:87:98:77:4f:45:bb:de:87:86:1f:8b:1e:b2:
+ 26:cb:56:a3:d3:10:85:5e:95:ed:aa:c3:87:17:f4:
+ 40:86:bf:d7:e0:4a:ea:43:95:ce:b9:22:2a:c4:90:
+ f0:24:34:81:f2:5b:58:47:d3:d8:9b:eb:fc:90:4b:
+ 54:41:6d:6a:c0:5d:82:56:49:47:c4:ab:29:48:a4:
+ 23:05:fa:4f:a3:9e:83:65:5a:fd:57:c2:5a:4c:13:
+ bf:eb:75:ff:4d:f9:c1:5b:65:32:7d:bb:0d:e3:20:
+ 6a:4c:b3:28:fc:01:11:68:c0:9c:4b:f6:a5:df:68:
+ 0e:b2:c1:6f:b3:69:5f:53:35:2c:b9:3b:f8:c2:48:
+ 3b:3f:8f:d1:9f:76:b1:3a:1a:22:7f:fd:28:e6:6e:
+ 1c:96:95:c3:37:6f:c4:5a:24:28:25:5b:f6:a0:85:
+ f0:47:33:fa:9d:3b:38:cf:b1:d1:c9:06:d8:25:03:
+ bc:00:50:fe:08:dc:0d:d8:b1:87:94:8e:dc:74:ac:
+ 2c:53:44:91:4c:67:0a:71:5e:d3:df:c6:58:ee:00:
+ fe:96:fd:2f:96:f8:9f:35:5a:4e:be:ca:c1:5a:55:
+ f8:4d:85:77:3d:a9:d6:aa:75:0f:b9:82:07:c4:89:
+ 9e:9a:e6:39:f8:39:d2:be:62:cd:ca:43:a2:55:bf:
+ 0b:81
Exponent: 65537 (0x10001)
X509v3 extensions:
X509v3 Basic Constraints: critical
@@ -37,35 +37,35 @@ Certificate:
X509v3 Key Usage: critical
Certificate Sign, CRL Sign
Signature Algorithm: sha256WithRSAEncryption
- 41:1f:59:af:b3:83:87:87:bc:b3:2d:62:66:35:76:21:f2:bb:
- e5:d4:87:23:a3:ab:4f:2b:ef:d0:ee:53:6f:17:b0:d4:6a:93:
- 8e:74:71:7b:c5:36:f4:7b:87:3a:ab:84:b0:40:c5:3b:a0:e7:
- a1:18:e6:3f:8d:8d:a8:49:b5:da:c7:4b:26:e4:ea:b9:2d:85:
- b2:1d:01:70:bb:78:08:a6:c7:11:6b:0a:6f:5d:b0:d7:b5:72:
- ec:51:46:26:bc:7e:e1:bd:1e:5e:d6:44:cf:d0:1b:55:ef:a9:
- 5e:16:73:05:59:9f:ff:00:2e:5b:4e:29:7b:c4:2e:5c:46:9c:
- 56:0a:78:d9:0b:10:83:9e:ff:8a:e3:57:ec:f1:d1:a3:85:26:
- 2f:97:e6:d0:6f:5e:c8:cb:53:e7:28:64:ab:27:14:f4:b2:4b:
- 52:80:e2:d1:ef:50:ba:db:34:5c:95:a4:3f:ac:5b:eb:15:c5:
- d6:cb:4b:76:fb:f6:cd:2f:d9:ef:d4:cb:1c:85:52:8b:f2:2b:
- 1b:ce:e3:0f:ed:07:44:11:8b:d8:b8:5c:41:ab:e1:36:0d:7e:
- 3f:86:ff:0c:0f:f5:5e:ff:f6:b8:0a:ac:f0:3b:5d:c5:b7:ef:
- f1:80:7c:26:b9:a2:ee:17:a8:e7:cb:c4:f4:5c:51:ff:57:53:
- ee:a2:d3:66
+ 99:1e:ab:d0:ab:f7:27:85:ed:91:bc:b0:3e:af:57:a8:31:1d:
+ 8e:e8:4b:bc:3e:b4:82:c9:6c:62:3a:8d:48:be:a1:0a:42:27:
+ 11:18:ef:47:53:b2:46:5f:d0:de:31:4e:c3:de:e8:c5:f6:24:
+ 09:69:25:c9:e6:f8:1e:1a:b1:27:63:ff:07:8b:7b:e9:80:b5:
+ 68:d4:94:54:b6:fe:c6:a6:3b:61:01:f9:89:a2:50:f2:9b:a0:
+ 02:2a:85:bd:13:5a:43:45:a7:b7:7c:eb:1a:69:95:04:dc:c0:
+ 17:13:da:c8:73:fd:0b:94:a2:fe:af:e7:18:b4:b1:90:21:99:
+ ad:f8:06:9a:6d:c1:e1:3b:f4:85:69:91:6d:68:84:9f:e9:09:
+ 30:08:f6:11:87:99:67:8f:16:cc:59:43:38:95:5e:fa:9d:c5:
+ 4a:2d:55:f2:3d:1a:49:5c:12:66:ea:40:2d:a1:de:08:40:a4:
+ b3:dc:19:8a:23:04:a6:cf:a6:9b:2e:d0:2a:3c:5f:fa:4c:bb:
+ 5a:62:d0:0b:a4:f6:8c:06:42:54:b4:c6:63:e0:f1:f0:11:a8:
+ ec:57:3d:93:6c:0c:67:a5:5a:8a:52:c5:37:b6:c3:7e:54:05:
+ b0:82:d9:32:8a:a7:12:83:39:d9:bc:81:ce:db:e9:ad:e9:b7:
+ 5d:1d:6d:3a
-----BEGIN CERTIFICATE-----
MIICwjCCAaqgAwIBAgICEAEwDQYJKoZIhvcNAQELBQAwFDESMBAGA1UEAwwJQyBS
-b290IENBMB4XDTE2MTAwNDE4NTMyNFoXDTI2MTAwMjE4NTMyNFowDzENMAsGA1UE
-AwwEQiBDQTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAKVWx50y5z0X
-rFnK9AdlJT5lfNk99A5z67kLoXtLaavuo1BJLyUzTS2sADIXNA3Jv4N9tOXVgolv
-rUF4Vh0FvEjMDEOVgePoEi1ndGgSYY4DJIgsVyiOPRB32tx4trRyklYOSgzG9wpE
-9VZdcnqoHbwW6JUlTVC2LiIF/dUgR6QyN1I4YZCaqkCo25GAAInmLBddfF9vLbK3
-z3GhVRHY/TubYY8cgN3akIyCBGM2fLEoOFa8bsCzuU6WKz9iKuVf8XM8U6hfA9Bj
-MTasAGEwq63ZqqtdIoMozPH3iPWavlfF4Ubao4hVpzz5HBe7cgEd3Y6gsKPRkXSu
-lFjA9TBjXJECAwEAAaMjMCEwDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMC
-AQYwDQYJKoZIhvcNAQELBQADggEBAEEfWa+zg4eHvLMtYmY1diHyu+XUhyOjq08r
-79DuU28XsNRqk450cXvFNvR7hzqrhLBAxTug56EY5j+NjahJtdrHSybk6rkthbId
-AXC7eAimxxFrCm9dsNe1cuxRRia8fuG9Hl7WRM/QG1XvqV4WcwVZn/8ALltOKXvE
-LlxGnFYKeNkLEIOe/4rjV+zx0aOFJi+X5tBvXsjLU+coZKsnFPSyS1KA4tHvULrb
-NFyVpD+sW+sVxdbLS3b79s0v2e/UyxyFUovyKxvO4w/tB0QRi9i4XEGr4TYNfj+G
-/wwP9V7/9rgKrPA7XcW37/GAfCa5ou4XqOfLxPRcUf9XU+6i02Y=
+b290IENBMB4XDTE2MTIwOTIwMTg1N1oXDTI2MTIwNzIwMTg1N1owDzENMAsGA1UE
+AwwEQiBDQTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBALOHmHdPRbve
+h4Yfix6yJstWo9MQhV6V7arDhxf0QIa/1+BK6kOVzrkiKsSQ8CQ0gfJbWEfT2Jvr
+/JBLVEFtasBdglZJR8SrKUikIwX6T6Oeg2Va/VfCWkwTv+t1/035wVtlMn27DeMg
+akyzKPwBEWjAnEv2pd9oDrLBb7NpX1M1LLk7+MJIOz+P0Z92sToaIn/9KOZuHJaV
+wzdvxFokKCVb9qCF8Ecz+p07OM+x0ckG2CUDvABQ/gjcDdixh5SO3HSsLFNEkUxn
+CnFe09/GWO4A/pb9L5b4nzVaTr7KwVpV+E2Fdz2p1qp1D7mCB8SJnprmOfg50r5i
+zcpDolW/C4ECAwEAAaMjMCEwDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMC
+AQYwDQYJKoZIhvcNAQELBQADggEBAJkeq9Cr9yeF7ZG8sD6vV6gxHY7oS7w+tILJ
+bGI6jUi+oQpCJxEY70dTskZf0N4xTsPe6MX2JAlpJcnm+B4asSdj/weLe+mAtWjU
+lFS2/samO2EB+YmiUPKboAIqhb0TWkNFp7d86xpplQTcwBcT2shz/QuUov6v5xi0
+sZAhma34BpptweE79IVpkW1ohJ/pCTAI9hGHmWePFsxZQziVXvqdxUotVfI9Gklc
+EmbqQC2h3ghApLPcGYojBKbPppsu0Co8X/pMu1pi0Auk9owGQlS0xmPg8fARqOxX
+PZNsDGelWopSxTe2w35UBbCC2TKKpxKDOdm8gc7b6a3pt10dbTo=
-----END CERTIFICATE-----
diff --git a/chromium/net/data/ssl/certificates/client_2.key b/chromium/net/data/ssl/certificates/client_2.key
index e10b152c656..92cae727ee9 100644
--- a/chromium/net/data/ssl/certificates/client_2.key
+++ b/chromium/net/data/ssl/certificates/client_2.key
@@ -1,27 +1,27 @@
-----BEGIN RSA PRIVATE KEY-----
-MIIEowIBAAKCAQEA68lLXfm1qfzrGYiXtXmYfa/gwbcSGLTcu3VTD9Cow2A465PP
-wp6bs6Qu3eFgwr7mceQ72pU410+zEwxo1bqHorcc1qhemDBLEaL5cu1KEyw3GN97
-kJTxOMR4zahR8IvDpnYRzjTtmZOuLUpZ7Lo3oOouLDQ6OpoOw9mLu2I7RtVc8cQC
-iyOnQVWKeSbDQ/+or/m3DUbQq+Wyg9TTjDWAAbqxu3mP5Jf8nd8I/xAbRxe0jBSW
-8hiZ++Yxjo/kLVkI+s4TBFVV3dau2b5oHGMsFoBFCaTIyE+4KZAKZAdptvxuh1ic
-F/GhSZy3+H1w122uYmq7KA7pG32sBaQUl0iwnQIDAQABAoIBAGNOKlHwI9TuUs40
-O0ERb2owMwcjZZnGQtko9szIYuu2kQKXBH/BcW5djeehTrF22XPKXnMXOhNk29T/
-+v9ZSlr7qEe4Le8HF/bbnxgKXJJqouH07gPc1yPDi+WCKNCY7NQlEia5IAD4s/kb
-QXh0jY1WVBAGByg7TlCqRTGsk66myy3qA7Ii65Y1upiGFfDczpQL5mUKaBTjz3HC
-/DMr4GRuFOw5NkhELu9SOENZGSwuzpk6gNDVYDXJ+uo9bvH9EIB9S1KIoAoa+yr2
-L9LUcG9vwOuMNh7qN66nAGxGzoI8qh6kHVgfyTcF11NwaFutSIsGQTRKeANxiq2I
-IkbT3EECgYEA/QGxkv9iC/oJfe9gWlUeEFJsqlmLp2ii0HrH9KnywT5sgicd0//3
-eCU1KI8LygABbHb3hmFQRAwf2gFq0u1MBqXQQ4nVsrNtPVzNGGOkfk5T9DIu4vBN
-L9Qw29ULYDbaHaC1BFymwnMsOOsKctiMmsiklhyCWBczcHmE+gn+6ykCgYEA7pNx
-on/qgrCp9P8mMdBqjOmc5740Pbqu5JShYJkja1fv7IVLhGEuifdwGWge6ZfjaXPV
-wq7P7mbXa2Dreqc0LkxUrdAffZitsXckhNswSDToZzf7JB9GAnkcMKlLcJHbO0Kf
-jJALGpPknLg8XbpqsT+/GAS1GBNbL4Rz/MovPFUCgYBkJEt494SDYRBovFrS5mXj
-5/wC4TaZqJzpD/AdMzdWrbKdQYZY5zO4ZmHID/aGmcH2gJAwrEvs4y+oRm9V1X8G
-EpOAaAohlUtjwlubj7UIGVC5kzNjt+GVUNOV75l1F8D1gSqk81c+GAAk90NHedcN
-XOVoVRhybZx6pF6x6UrxIQKBgDc8EbIClYO+bQrYy7n6u8B2Eaqhoays/PLU6mvX
-6Jhgmp6S2cIDUegFToHDVmzUioUOmW3iVSenzbYBkWMrNOyHJY+8QJ4ubABLSjws
-FwiQn0HOdymMyAOokHs/psSgMDaPHStI6hk0JliWWvuEPlFdJdvksxyo1pKwwr3C
-/Z6lAoGBAIr0S/O5rYrEHchJ6yr+YtJa6vIowOSUvijG2L4ghVY63v/Ke5vzwmOZ
-wuPh0D6atpKPIq5p3eGlgq12cJHGwaybVP9C3C9vD+MlhMttOy7Ez9aVFILE9nt/
-hSrOTRwYYXLs0txl7K40Ja2hjIRXw1TQU37V4wADNa+GhPpUfg9y
+MIIEpAIBAAKCAQEA4IzClfxmgklkJHuaB4JlLIR6Z8ehIjoJ868C8YA5I23PDxHI
+G6W+l3F98IFAaO41q4VU/IimBRMIRiGZOkHgBi/NQS1nu11IQKxl1azljs2zvzLC
+V9j220CNyDqvsxv13/26W+rbjsZ+0VdIN+lh6RY9AhhDcA5BvN6vjZOFR02ypIin
+oSOKnhZOMLRVsosPuKS1qlaXCrWD8Z7n1tD4koZ6+9YiYCVgZ7pKNTIS8kR8b3Pj
+pm+8Q+FVR+HZWoYySE1n/w6vDmK47TUUI2vdBHpnKbis//DjVHrsDQ1ZqqvxRwDS
+FLtIoMwuMyO3rWuqsa2FnvgJbvA9XD4Pv3F3jwIDAQABAoIBAQCTe2ACarhZMiLX
+42aTMA2LY6eRqggnFr+akYP5YiIlJuYsG522qvG3Pg9de0b2pB4T/YqIIqgIBSwW
+A9ND9ChTZ+oDuPK8mNPvxktMQDa1yF0aYxhJ4nKgJpH4xLLJjL+80kUoQeTarXx1
+ukHwlxR7puODELSaUILUrd3XuuB6p06I3KBIzkGx0BqVRFmCk/nAaCZLA8WJcUmD
+rfYFPTc/2Jm7xH+Wzhd86evT1yIpTCu7VNdXuzFHLFesxeFSb49cRrJLlKEWT3B8
+7jRjhqclZvJ2jTvMEx8I48vIW40jrs5dGWFqzYRo0rbelI/BRwDQsGEDyHLwZdRG
+qAg158bhAoGBAPLAr2sGQhI0+v5GWMuqELgCJlqmDP9gP/6pU2E8CkmTefu8MsVx
+UzFaAN+WFr0wqpVuCTVczSZSF10/SwM4mNsTb6vc9CQ9uK655vTIiFLR8NTZOxAK
+sVyJKCRB0Ejf9nufSJaLZetW3QQTxWLmrhmVjKPjJOYsKLHfye3Oz7VLAoGBAOzN
+xt1Fgi2XgnASI+D3e7hwa/9obfCPdwB1kdyPq8A2sZBTzGdnixY5IcbwQmK4Ekuj
+d9gnaRqg/WKUoR/5PduYvxo1JErBh+itu/mdSpSd71465Do/Q5mQbV+MAnyWTPak
+mtBKs6W22Sk1+NSuoA4mX+oC8m29uDho8b+bIdBNAoGAWXTmcAM7X+hEQmX8HPmL
+9bNdHPSqP4Xhr2AIyQFOLTT6s+jzsM0FQl+PiNWPhaKkijKllBOhyihgUc2cQBCg
+S8NK2MOw+JYCM+lwEe7ARfz1ygpPeKboG1i0AUB7mA9ojr/xCQFPyr0U74a1q6+k
+our4jACNvYCycnIswMUAyCcCgYBh/vJKBYbOuUFogYlJgwE3HYcD5kKA5832abEY
+FnicDcZDlPok3KupYbFBs5G1arlfheGFmSGcvHy/fASFx846fyaugMlpClflCWid
+7uK7R/SUCUkDdcTS2vr4LGenCUgGVa4ffpqDfHy32jcERNPFp0nP/LI4ieefqIZK
+pbdDjQKBgQCEqdGn6ZB+dg3i2RK544RfNqQaVmDw0czmxl3xRnUEfElA7ZSmE4Lt
+Dx9bmXoXYAjMz3Elh3+3pIq4BjlKsPK18zZPAGQnVxoSnUtW9tVI+bc/yFk2irfo
+UtSDxMR8dcUd4vjE2WHIgBnJEbGj+PkMqjMimMZqQDhr4UI2OTe7Zw==
-----END RSA PRIVATE KEY-----
diff --git a/chromium/net/data/ssl/certificates/client_2.pem b/chromium/net/data/ssl/certificates/client_2.pem
index 1f7a03aff6c..abc9dde76a4 100644
--- a/chromium/net/data/ssl/certificates/client_2.pem
+++ b/chromium/net/data/ssl/certificates/client_2.pem
@@ -5,31 +5,31 @@ Certificate:
Signature Algorithm: sha256WithRSAEncryption
Issuer: CN=E CA
Validity
- Not Before: Oct 4 18:53:24 2016 GMT
- Not After : Oct 2 18:53:24 2026 GMT
+ Not Before: Dec 9 20:18:57 2016 GMT
+ Not After : Dec 7 20:18:57 2026 GMT
Subject: CN=Client Cert D
Subject Public Key Info:
Public Key Algorithm: rsaEncryption
Public-Key: (2048 bit)
Modulus:
- 00:eb:c9:4b:5d:f9:b5:a9:fc:eb:19:88:97:b5:79:
- 98:7d:af:e0:c1:b7:12:18:b4:dc:bb:75:53:0f:d0:
- a8:c3:60:38:eb:93:cf:c2:9e:9b:b3:a4:2e:dd:e1:
- 60:c2:be:e6:71:e4:3b:da:95:38:d7:4f:b3:13:0c:
- 68:d5:ba:87:a2:b7:1c:d6:a8:5e:98:30:4b:11:a2:
- f9:72:ed:4a:13:2c:37:18:df:7b:90:94:f1:38:c4:
- 78:cd:a8:51:f0:8b:c3:a6:76:11:ce:34:ed:99:93:
- ae:2d:4a:59:ec:ba:37:a0:ea:2e:2c:34:3a:3a:9a:
- 0e:c3:d9:8b:bb:62:3b:46:d5:5c:f1:c4:02:8b:23:
- a7:41:55:8a:79:26:c3:43:ff:a8:af:f9:b7:0d:46:
- d0:ab:e5:b2:83:d4:d3:8c:35:80:01:ba:b1:bb:79:
- 8f:e4:97:fc:9d:df:08:ff:10:1b:47:17:b4:8c:14:
- 96:f2:18:99:fb:e6:31:8e:8f:e4:2d:59:08:fa:ce:
- 13:04:55:55:dd:d6:ae:d9:be:68:1c:63:2c:16:80:
- 45:09:a4:c8:c8:4f:b8:29:90:0a:64:07:69:b6:fc:
- 6e:87:58:9c:17:f1:a1:49:9c:b7:f8:7d:70:d7:6d:
- ae:62:6a:bb:28:0e:e9:1b:7d:ac:05:a4:14:97:48:
- b0:9d
+ 00:e0:8c:c2:95:fc:66:82:49:64:24:7b:9a:07:82:
+ 65:2c:84:7a:67:c7:a1:22:3a:09:f3:af:02:f1:80:
+ 39:23:6d:cf:0f:11:c8:1b:a5:be:97:71:7d:f0:81:
+ 40:68:ee:35:ab:85:54:fc:88:a6:05:13:08:46:21:
+ 99:3a:41:e0:06:2f:cd:41:2d:67:bb:5d:48:40:ac:
+ 65:d5:ac:e5:8e:cd:b3:bf:32:c2:57:d8:f6:db:40:
+ 8d:c8:3a:af:b3:1b:f5:df:fd:ba:5b:ea:db:8e:c6:
+ 7e:d1:57:48:37:e9:61:e9:16:3d:02:18:43:70:0e:
+ 41:bc:de:af:8d:93:85:47:4d:b2:a4:88:a7:a1:23:
+ 8a:9e:16:4e:30:b4:55:b2:8b:0f:b8:a4:b5:aa:56:
+ 97:0a:b5:83:f1:9e:e7:d6:d0:f8:92:86:7a:fb:d6:
+ 22:60:25:60:67:ba:4a:35:32:12:f2:44:7c:6f:73:
+ e3:a6:6f:bc:43:e1:55:47:e1:d9:5a:86:32:48:4d:
+ 67:ff:0e:af:0e:62:b8:ed:35:14:23:6b:dd:04:7a:
+ 67:29:b8:ac:ff:f0:e3:54:7a:ec:0d:0d:59:aa:ab:
+ f1:47:00:d2:14:bb:48:a0:cc:2e:33:23:b7:ad:6b:
+ aa:b1:ad:85:9e:f8:09:6e:f0:3d:5c:3e:0f:bf:71:
+ 77:8f
Exponent: 65537 (0x10001)
X509v3 extensions:
X509v3 Basic Constraints: critical
@@ -37,36 +37,36 @@ Certificate:
X509v3 Extended Key Usage:
TLS Web Server Authentication, TLS Web Client Authentication
Signature Algorithm: sha256WithRSAEncryption
- 9f:d0:6e:8b:08:58:16:b5:78:3f:05:bb:59:bc:cf:74:1c:88:
- b0:7e:10:c5:71:9d:b5:08:05:59:ca:f0:c8:64:49:96:82:8b:
- 14:0c:da:9d:be:a2:8b:37:df:e1:69:bc:8e:f4:be:80:3f:f9:
- 8a:1d:7a:70:37:3c:18:a0:92:27:10:e3:74:ca:fa:b8:db:f2:
- c6:a5:32:66:85:88:29:3a:4e:64:95:85:b4:43:37:8a:6d:48:
- f4:12:2f:b2:d0:66:c9:b7:88:ad:b8:a7:1f:97:59:bf:d9:0d:
- d6:ce:ff:5f:75:2f:d2:e0:69:c8:d6:17:b9:fd:3c:ed:fd:1f:
- 47:14:f8:ef:0b:33:2a:1c:14:25:d1:82:90:d3:67:1b:ea:b0:
- f7:5b:78:a9:9d:28:1b:d3:cd:8d:bd:30:c2:7e:12:32:dd:83:
- cc:57:47:b3:e7:0c:79:b5:f8:a0:f4:f0:d8:29:1b:9b:fb:2f:
- a9:1c:cb:a9:84:14:29:c7:23:b8:85:88:d9:78:5f:c7:a4:c6:
- 1b:bd:6e:70:2e:a2:be:31:98:c7:9c:35:1d:44:59:f8:31:83:
- 87:ee:a9:c7:ab:f5:6f:e6:8a:cc:49:5f:23:fd:7c:a4:61:01:
- 9b:51:d8:b0:85:9a:bf:1d:9d:62:3e:b0:7c:e0:5e:57:ed:69:
- 3c:f3:8c:54
+ 95:de:33:2f:e2:11:c2:6d:64:4a:5f:98:69:cb:a3:c6:bd:a1:
+ 0f:00:9c:32:c8:83:c7:05:14:21:e3:ab:fa:7a:f8:43:36:95:
+ 6c:85:8b:b5:ee:2c:fc:4b:77:95:8a:bf:2f:89:c1:cc:c2:21:
+ 99:40:c4:01:be:2a:4a:5b:d9:61:06:16:b0:5d:3f:27:ad:e3:
+ 57:5c:41:89:fb:3b:dc:73:45:ac:05:e2:dd:89:95:74:09:30:
+ 68:3c:3f:e8:bc:e6:94:4a:ed:4c:74:90:ad:a0:a4:97:c0:04:
+ 9b:13:81:a5:24:76:db:4c:49:8f:80:f9:7c:7f:8b:f9:de:45:
+ 65:5d:03:b2:c7:99:3b:56:b1:f8:29:7e:b4:69:fe:f9:29:b3:
+ b6:59:bd:51:b1:02:97:5b:db:29:5e:9a:b5:1f:75:42:0f:7e:
+ 58:bc:e3:3f:39:ea:7b:12:c7:68:06:c0:e4:78:f4:e9:b4:9b:
+ 4c:fc:94:06:a3:1a:37:8b:3d:cd:67:f9:f4:e9:87:20:6c:07:
+ 71:62:85:78:35:96:9c:ef:98:59:33:50:83:7a:32:ad:22:01:
+ 3a:20:05:05:05:b0:62:9d:4e:20:94:1b:05:cc:7d:bb:ba:98:
+ a0:51:d2:50:b5:cb:d8:97:0f:42:13:65:2a:14:b8:cd:f2:24:
+ 5f:0e:6e:6b
-----BEGIN CERTIFICATE-----
MIIC0jCCAbqgAwIBAgICEAIwDQYJKoZIhvcNAQELBQAwDzENMAsGA1UEAwwERSBD
-QTAeFw0xNjEwMDQxODUzMjRaFw0yNjEwMDIxODUzMjRaMBgxFjAUBgNVBAMMDUNs
-aWVudCBDZXJ0IEQwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDryUtd
-+bWp/OsZiJe1eZh9r+DBtxIYtNy7dVMP0KjDYDjrk8/CnpuzpC7d4WDCvuZx5Dva
-lTjXT7MTDGjVuoeitxzWqF6YMEsRovly7UoTLDcY33uQlPE4xHjNqFHwi8OmdhHO
-NO2Zk64tSlnsujeg6i4sNDo6mg7D2Yu7YjtG1VzxxAKLI6dBVYp5JsND/6iv+bcN
-RtCr5bKD1NOMNYABurG7eY/kl/yd3wj/EBtHF7SMFJbyGJn75jGOj+QtWQj6zhME
-VVXd1q7ZvmgcYywWgEUJpMjIT7gpkApkB2m2/G6HWJwX8aFJnLf4fXDXba5iarso
-DukbfawFpBSXSLCdAgMBAAGjLzAtMAwGA1UdEwEB/wQCMAAwHQYDVR0lBBYwFAYI
-KwYBBQUHAwEGCCsGAQUFBwMCMA0GCSqGSIb3DQEBCwUAA4IBAQCf0G6LCFgWtXg/
-BbtZvM90HIiwfhDFcZ21CAVZyvDIZEmWgosUDNqdvqKLN9/habyO9L6AP/mKHXpw
-NzwYoJInEON0yvq42/LGpTJmhYgpOk5klYW0QzeKbUj0Ei+y0GbJt4ituKcfl1m/
-2Q3Wzv9fdS/S4GnI1he5/Tzt/R9HFPjvCzMqHBQl0YKQ02cb6rD3W3ipnSgb082N
-vTDCfhIy3YPMV0ez5wx5tfig9PDYKRub+y+pHMuphBQpxyO4hYjZeF/HpMYbvW5w
-LqK+MZjHnDUdRFn4MYOH7qnHq/Vv5orMSV8j/XykYQGbUdiwhZq/HZ1iPrB84F5X
-7Wk884xU
+QTAeFw0xNjEyMDkyMDE4NTdaFw0yNjEyMDcyMDE4NTdaMBgxFjAUBgNVBAMMDUNs
+aWVudCBDZXJ0IEQwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDgjMKV
+/GaCSWQke5oHgmUshHpnx6EiOgnzrwLxgDkjbc8PEcgbpb6XcX3wgUBo7jWrhVT8
+iKYFEwhGIZk6QeAGL81BLWe7XUhArGXVrOWOzbO/MsJX2PbbQI3IOq+zG/Xf/bpb
+6tuOxn7RV0g36WHpFj0CGENwDkG83q+Nk4VHTbKkiKehI4qeFk4wtFWyiw+4pLWq
+VpcKtYPxnufW0PiShnr71iJgJWBnuko1MhLyRHxvc+Omb7xD4VVH4dlahjJITWf/
+Dq8OYrjtNRQja90EemcpuKz/8ONUeuwNDVmqq/FHANIUu0igzC4zI7eta6qxrYWe
++Alu8D1cPg+/cXePAgMBAAGjLzAtMAwGA1UdEwEB/wQCMAAwHQYDVR0lBBYwFAYI
+KwYBBQUHAwEGCCsGAQUFBwMCMA0GCSqGSIb3DQEBCwUAA4IBAQCV3jMv4hHCbWRK
+X5hpy6PGvaEPAJwyyIPHBRQh46v6evhDNpVshYu17iz8S3eVir8vicHMwiGZQMQB
+vipKW9lhBhawXT8nreNXXEGJ+zvcc0WsBeLdiZV0CTBoPD/ovOaUSu1MdJCtoKSX
+wASbE4GlJHbbTEmPgPl8f4v53kVlXQOyx5k7VrH4KX60af75KbO2Wb1RsQKXW9sp
+Xpq1H3VCD35YvOM/Oep7EsdoBsDkePTptJtM/JQGoxo3iz3NZ/n06YcgbAdxYoV4
+NZac75hZM1CDejKtIgE6IAUFBbBinU4glBsFzH27upigUdJQtcvYlw9CE2UqFLjN
+8iRfDm5r
-----END CERTIFICATE-----
diff --git a/chromium/net/data/ssl/certificates/client_2.pk8 b/chromium/net/data/ssl/certificates/client_2.pk8
index 731e39c3cc7..ad3ca5d58f7 100644
--- a/chromium/net/data/ssl/certificates/client_2.pk8
+++ b/chromium/net/data/ssl/certificates/client_2.pk8
Binary files differ
diff --git a/chromium/net/data/ssl/certificates/client_2_ca.pem b/chromium/net/data/ssl/certificates/client_2_ca.pem
index dd58ffa7a3c..78080961705 100644
--- a/chromium/net/data/ssl/certificates/client_2_ca.pem
+++ b/chromium/net/data/ssl/certificates/client_2_ca.pem
@@ -5,31 +5,31 @@ Certificate:
Signature Algorithm: sha256WithRSAEncryption
Issuer: CN=C Root CA
Validity
- Not Before: Oct 4 18:53:24 2016 GMT
- Not After : Oct 2 18:53:24 2026 GMT
+ Not Before: Dec 9 20:18:57 2016 GMT
+ Not After : Dec 7 20:18:57 2026 GMT
Subject: CN=E CA
Subject Public Key Info:
Public Key Algorithm: rsaEncryption
Public-Key: (2048 bit)
Modulus:
- 00:a2:7e:a3:fd:c1:d7:78:cd:57:ac:67:54:37:69:
- fb:72:6f:1d:8f:d0:47:0f:11:14:ab:42:d8:3d:6a:
- 34:2b:d6:38:07:df:16:1d:c6:62:eb:d7:12:e1:86:
- 83:f2:dd:8f:97:09:94:8f:1b:ff:3b:84:9b:48:e5:
- 0d:43:6b:ae:bb:75:88:1c:c6:3a:7f:d8:12:d9:7c:
- 12:18:6d:e2:f0:88:d4:3e:5a:93:b3:af:c1:79:a1:
- b6:a3:f7:56:46:21:e6:7d:6e:36:ea:ba:4b:52:f7:
- a9:45:0b:83:09:2c:09:22:8a:67:5a:8f:88:60:b0:
- 11:07:25:9b:c2:6a:3c:63:4c:0e:69:45:ce:9d:ba:
- c9:d4:01:fb:78:56:38:08:8f:e5:d6:ff:ac:e4:04:
- fa:26:cf:d2:05:33:57:a3:8e:80:c0:b6:40:d5:d3:
- ca:85:17:30:b2:24:f4:19:af:c5:48:a4:ed:c0:49:
- c1:a4:b7:89:29:ba:e5:2d:37:78:1c:d6:3e:9b:03:
- fa:bc:7b:e2:76:a6:70:f3:1b:9d:b2:4b:fc:72:7b:
- 77:89:50:bb:88:2f:b5:b6:a2:c7:33:27:b7:d1:1a:
- 7c:d4:58:e3:5e:88:ca:f8:49:c3:cd:cc:0f:93:4b:
- 3c:fd:75:c3:7b:6f:bf:d3:db:ba:2e:31:7b:a7:a5:
- 42:c5
+ 00:c3:39:c3:5a:8e:ff:f2:1d:cc:26:91:5d:15:9e:
+ ca:e0:fb:cf:99:5f:13:3d:c6:37:59:8b:ce:cc:76:
+ 0e:1c:9f:b6:49:5b:09:97:63:9d:e1:00:74:44:fb:
+ 2f:53:f3:d5:03:92:77:97:53:74:7e:d2:da:d3:a3:
+ f4:c1:91:6a:83:ff:89:fe:73:46:56:ca:6d:51:0d:
+ 57:16:3d:3e:e8:fc:00:d9:4a:7a:7d:93:84:06:12:
+ c5:ff:31:b3:a6:eb:96:18:71:b8:56:5c:2f:ab:78:
+ e2:53:dd:15:d8:65:c8:f6:96:14:dc:15:cf:2a:39:
+ ed:e1:08:1b:84:29:c7:1c:78:67:c8:e0:72:58:4e:
+ 33:7f:cb:ef:71:82:db:45:1d:7c:0c:d0:f5:4c:af:
+ 85:6b:14:61:50:87:34:42:fe:45:a3:3c:a3:53:57:
+ 1d:ac:11:c8:cf:2f:5e:cb:78:87:39:a1:41:3f:69:
+ 21:5c:1e:19:02:a3:6c:91:d3:1b:4e:50:fc:a4:b1:
+ 03:87:c0:58:b1:fe:cd:58:5e:53:ed:c9:d6:5d:9e:
+ a3:fb:0d:e0:a0:8e:3d:c9:9e:9e:83:07:61:c7:30:
+ 5a:ca:29:93:04:af:5e:f3:57:2e:c2:d8:c8:ae:7f:
+ 5c:a4:27:fa:cd:55:a2:fd:89:d2:0b:87:24:6b:7b:
+ fb:19
Exponent: 65537 (0x10001)
X509v3 extensions:
X509v3 Basic Constraints: critical
@@ -37,35 +37,35 @@ Certificate:
X509v3 Key Usage: critical
Certificate Sign, CRL Sign
Signature Algorithm: sha256WithRSAEncryption
- 92:8b:93:94:03:04:91:3f:4d:8b:f3:90:53:ee:73:b5:33:c7:
- 61:ea:0f:a5:59:9b:f0:0d:4f:7d:48:0d:5a:58:e7:1f:68:f6:
- d6:58:75:33:a5:d2:b7:65:6a:28:40:bc:0e:1e:78:ee:9a:13:
- 3c:b0:8b:8f:98:72:86:50:3a:a3:bf:6d:f0:21:95:a8:73:d0:
- dd:e5:0e:25:b1:62:76:65:69:1f:ee:26:82:ab:be:a4:a8:30:
- a7:41:34:07:57:2f:8b:ab:25:af:cb:23:a5:79:cf:b2:a2:17:
- 02:a7:aa:50:92:6e:0d:9b:ff:c9:22:38:b4:0f:47:94:d2:80:
- 7f:92:30:00:ec:5b:22:e2:a6:71:5e:e8:8f:0d:2f:38:2c:29:
- 47:6a:7f:20:0a:e2:42:cb:b7:6e:2b:29:0f:03:55:94:84:5f:
- e7:47:bf:ae:75:88:05:4e:42:ac:78:57:9d:9c:e2:77:d2:17:
- 42:55:ba:f8:77:ee:61:d6:e8:ec:aa:e0:7a:a6:65:c6:35:80:
- 08:3d:39:a6:70:8c:9e:6d:7a:ee:e7:cf:36:46:98:00:c8:7b:
- b8:84:7f:9d:9f:bd:31:4f:99:25:6e:76:9a:5d:46:3e:40:70:
- c6:a8:03:f3:98:9c:be:fb:f6:ad:c2:8d:e3:f9:7d:93:3a:78:
- da:b3:d7:dc
+ 67:d4:6c:cf:cd:54:81:67:2a:c2:c4:66:c7:76:9c:b0:8b:6b:
+ ef:b8:ae:a9:b3:d6:f8:47:91:d5:97:0b:bd:1a:87:21:8c:ce:
+ be:0c:80:d5:a5:25:0d:0a:c7:ed:be:cb:8c:6d:08:e8:de:a5:
+ 33:89:e6:87:df:2b:f4:54:b3:c2:94:15:0d:36:5e:1a:aa:c0:
+ b0:03:3c:24:c6:a1:81:91:ca:fe:db:0f:59:1b:d6:4e:48:0b:
+ 52:d3:e7:07:d7:b1:ca:b2:22:e4:d4:37:a4:3c:87:3c:0a:11:
+ a6:10:2a:ed:86:2a:bb:db:10:7e:f3:a5:fc:10:ab:80:5b:07:
+ 58:7c:22:76:3e:9b:9c:72:79:0d:dc:85:f8:e7:c2:0f:17:aa:
+ 01:dd:8e:24:27:77:4e:23:03:da:88:e0:df:e6:ca:b4:84:56:
+ a1:dc:9f:e0:93:94:97:d2:98:cd:32:6d:73:84:f9:3e:4c:96:
+ b3:51:07:b8:9f:66:32:d1:ac:53:0e:17:a9:6f:29:d1:7b:73:
+ b3:55:9b:cc:8f:8b:e5:49:fd:fd:f2:30:d6:d0:f7:03:06:12:
+ e3:66:2d:0d:a1:da:28:04:04:29:b8:40:6e:0e:6f:31:48:cb:
+ 54:f7:e2:89:22:d8:05:e0:f5:7e:48:b3:96:ff:6b:ef:e7:fe:
+ 71:1d:0b:77
-----BEGIN CERTIFICATE-----
MIICwjCCAaqgAwIBAgICEAIwDQYJKoZIhvcNAQELBQAwFDESMBAGA1UEAwwJQyBS
-b290IENBMB4XDTE2MTAwNDE4NTMyNFoXDTI2MTAwMjE4NTMyNFowDzENMAsGA1UE
-AwwERSBDQTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAKJ+o/3B13jN
-V6xnVDdp+3JvHY/QRw8RFKtC2D1qNCvWOAffFh3GYuvXEuGGg/Ldj5cJlI8b/zuE
-m0jlDUNrrrt1iBzGOn/YEtl8Ehht4vCI1D5ak7OvwXmhtqP3VkYh5n1uNuq6S1L3
-qUULgwksCSKKZ1qPiGCwEQclm8JqPGNMDmlFzp26ydQB+3hWOAiP5db/rOQE+ibP
-0gUzV6OOgMC2QNXTyoUXMLIk9BmvxUik7cBJwaS3iSm65S03eBzWPpsD+rx74nam
-cPMbnbJL/HJ7d4lQu4gvtbaixzMnt9EafNRY416IyvhJw83MD5NLPP11w3tvv9Pb
-ui4xe6elQsUCAwEAAaMjMCEwDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMC
-AQYwDQYJKoZIhvcNAQELBQADggEBAJKLk5QDBJE/TYvzkFPuc7Uzx2HqD6VZm/AN
-T31IDVpY5x9o9tZYdTOl0rdlaihAvA4eeO6aEzywi4+YcoZQOqO/bfAhlahz0N3l
-DiWxYnZlaR/uJoKrvqSoMKdBNAdXL4urJa/LI6V5z7KiFwKnqlCSbg2b/8kiOLQP
-R5TSgH+SMADsWyLipnFe6I8NLzgsKUdqfyAK4kLLt24rKQ8DVZSEX+dHv651iAVO
-Qqx4V52c4nfSF0JVuvh37mHW6Oyq4HqmZcY1gAg9OaZwjJ5teu7nzzZGmADIe7iE
-f52fvTFPmSVudppdRj5AcMaoA/OYnL779q3CjeP5fZM6eNqz19w=
+b290IENBMB4XDTE2MTIwOTIwMTg1N1oXDTI2MTIwNzIwMTg1N1owDzENMAsGA1UE
+AwwERSBDQTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAMM5w1qO//Id
+zCaRXRWeyuD7z5lfEz3GN1mLzsx2DhyftklbCZdjneEAdET7L1Pz1QOSd5dTdH7S
+2tOj9MGRaoP/if5zRlbKbVENVxY9Puj8ANlKen2ThAYSxf8xs6brlhhxuFZcL6t4
+4lPdFdhlyPaWFNwVzyo57eEIG4Qpxxx4Z8jgclhOM3/L73GC20UdfAzQ9UyvhWsU
+YVCHNEL+RaM8o1NXHawRyM8vXst4hzmhQT9pIVweGQKjbJHTG05Q/KSxA4fAWLH+
+zVheU+3J1l2eo/sN4KCOPcmenoMHYccwWsopkwSvXvNXLsLYyK5/XKQn+s1Vov2J
+0guHJGt7+xkCAwEAAaMjMCEwDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMC
+AQYwDQYJKoZIhvcNAQELBQADggEBAGfUbM/NVIFnKsLEZsd2nLCLa++4rqmz1vhH
+kdWXC70ahyGMzr4MgNWlJQ0Kx+2+y4xtCOjepTOJ5offK/RUs8KUFQ02XhqqwLAD
+PCTGoYGRyv7bD1kb1k5IC1LT5wfXscqyIuTUN6Q8hzwKEaYQKu2GKrvbEH7zpfwQ
+q4BbB1h8InY+m5xyeQ3chfjnwg8XqgHdjiQnd04jA9qI4N/myrSEVqHcn+CTlJfS
+mM0ybXOE+T5MlrNRB7ifZjLRrFMOF6lvKdF7c7NVm8yPi+VJ/f3yMNbQ9wMGEuNm
+LQ2h2igEBCm4QG4ObzFIy1T34oki2AXg9X5Is5b/a+/n/nEdC3c=
-----END CERTIFICATE-----
diff --git a/chromium/net/data/ssl/certificates/client_3.key b/chromium/net/data/ssl/certificates/client_3.key
index 20498bab62e..c2b341fe2b8 100644
--- a/chromium/net/data/ssl/certificates/client_3.key
+++ b/chromium/net/data/ssl/certificates/client_3.key
@@ -1,27 +1,27 @@
-----BEGIN RSA PRIVATE KEY-----
-MIIEpAIBAAKCAQEAqblhT1L+ZDRTZ0fYWCIjgpdv0ILn9ws9204VFTjf3jU+66wZ
-m9iN2+j62y/68iBFkt/107YqA2so3o0kS6o7Izt+EQg+o5ZvvHM3fVSR/IGejHbt
-1fbk9o7oblbikOtRpfOQ2EXZ+h2RASE6YTE66lrE6RruAOaWYsoLpzepHDlOEj6t
-q+24LIalckzKOQNNYfwpuLzbMomVCmIaKNaObesGM5pbj+hz4S8ehCH7CzgnsYOg
-x/7tecyrV6XPW7OEDLm4GoyQIlnxvk1GDIVje6caSW+OzqL65SlkAwLcaN95tmub
-IgdZr6H/upzmXdRh3kCBLgKWAqpUJNSzxBjj/wIDAQABAoIBACvRiKYKL1N/jujj
-S5+1cKWOo3eZ1HmblWTBTAAmpuWfqZb+3720sytLgziDsq5AVrYMzFLUfRRU3kBX
-AD/ou0vlWC7dig6CEGb++ByLcQVYEa8CJXVQQNzHGIskM2pm1rWZpJOxtQ02BPHd
-ukzNgQBwXtYv9bKV1c27jDan0ClQ1nj14TK8k2LLCDYd3O9Zbfm+5fKqsJIjDFm6
-rPeltV8yFBsZPxBJAQUNTR0fnq5mYLrCm8ARWYbLxbbWSjInXStrwVuaG8P/T7Om
-sl6Jj7eRClM6HrCtJMukgAQ1f6Rg882MVKKv8sjVO0ZHIZrg+e3TLPLrngXYeLxP
-NgrJgUECgYEA2J5Ee5cVyvbJITD71dVHcZc8QcaBVFBsSCcw0ZQ4LgUmS/z3ERYq
-mpdXzU1bTAOOMujOjiv9qYXn800DqRiDML384/cQz9DNkUth2eSQjk2Ryp9x5z+Y
-CeeMrzTtPK+SRfbC12UnNkZqwg+OrVgQUswbgOt2tM/9Bx5ujo6kuDsCgYEAyJSX
-ouGtWU7wys3ffmrmYlc0G/hGXxvqunpD8YR61fxyIMb1M9FfqObbCWaD7tkboEfe
-u6l7+d+4eJO2Gv++68asqHPsNQeq0qqAVPVNVusD+Uw9DPK4yxfbtn0lbALikCAB
-VT4yudolYsZA0b6tHApSG2bZkr3lXSwLFmljCw0CgYEAtT3m6smE8Gb/7geADm/+
-8Omq/xXJy/PmRZCU5iXvw4GHg3jKd79mMiaCzkH1K2qmJa5odMgV2ysw4X8Emwzp
-Z3TvDQYBSP/Zn8HEw3zb/lSksTYrJWMuIMteCJJuFKKJ7oQCjhoSbvUICgreQ+c0
-8THZqUpZ7ftAKB6sPhbXd1UCgYEAsYjL+nBTtcOoX2j/U26dAhf7WHJVHyOfjHRh
-pOjErJhoD9jp+XZtfBrxbo2dYxApYqGaZHHr+MvrBFaBjb4lp5zO/76zKHDj4tjl
-A82nKbKUbtjrBIXlyGUSpKB6OfMHw9eANon57gRGqPmfL8bchAAiknxjQX3xAJnW
-Kn0XHBUCgYAnpq1dGwdknEcVnVMsoZQirc6UK39u8KIH6S7P2QhSzc6pXOeC8HGj
-H6zvc3LtddSj8tCWfGDGVWp4v9TIWHOZbmmg20iU93j7Xi53cL3zB6TaAa467tj9
-0JFgB4tk1zKLggwkF26Sf3m+kkPDGwm4+jmk8TfV7VZ9yCZQY5Onig==
+MIIEpQIBAAKCAQEAs1wyu8BIKDebRat4oOpyEyZdRu5xxCSc7ai2gTXXcroKrqlO
+IGESIuAAZ4BwvqzvA7LUsDr8xauFewRLYYV6F2xDNmcLGXx0uGXpHP3w30K8DP0J
+fk99OMBSceUrGYCCqmnCNmu3LQf0dGK/jpDtRxpkJKxMuNIq0J2GCMEYnj7eTxJc
+ZKQrhkMSgWcMjFbkFkY8Kc9OGOpPZl+01nNfHpOt38kGZczcQrrphkIIoaul/CLT
+I1eg2myA3sX5nMURZZyy3/PWyL2qr0Bm7c5fBEYX5pLqZMiz5CDL4EQJFR985OAH
+zSJ8vaAGZTXUPhwHYY8BUyIlhZN1c0LHwcASnwIDAQABAoIBAQCxZ/WKfdMhbHb5
+v3ROffadeGn0ue7vWmOaMzFpto7HHLtqLW5oWnts4XGk7ocWIsk7OExlj8Lr5g7e
+Mc45xKORvXTxv5Rb/h0ZMzwTgB4bRs/obPRR6l/qnVgu7cTmsZUM6BTAbWS+dsrV
+v8LHShRYKwN4vrAYc1EEDXtA93XZNp9OBsVRdHJbeV4PIXqdzr3lScbXHNNs+dSF
+i6pZ/VrCHWmp9H1NXQuicAHr5aTvRMvFpfNtFSpOo7xEX+4cbVTk2b5TwxBa5TTj
+oew8/h2IsU1OmytQ1zya9Xtpw9GIMOnWg5Ce2dAyoBIkmhQwYcJyYTMM34vul/eD
+k0u0cxFxAoGBAOPM4x1mjD6tuQHFYBivBySU1CpdI0taem3GCijCUj/7tHPA+7FZ
++DhtnYF4b9q/X9EHRoosCWY07/tImYZT7ziiEFITRZL/m/hA239M9zuop7+9Tp3W
+M2oTkTGQOn5qKNg8TplYinpHmpGD7VURUczsdmo28rgp9Ubu1h5CwHv3AoGBAMmQ
+Nz/wgVCPVnZ66AsHiwLcAZ99aZg5961XVgyUXpWSQ0wNYKYWsYwYhYCeVRmwImSA
+NavYq0+AxTgnZrwhXXkvKXYfkLhh6aePRqyPaT3AUfp4akNe/S24HW3zO9Z0BzG6
+Ca8+oERpQ6hZ92WB1yikVoUqIaw+oIn5mzjkouSZAoGBAJ7z/p4rSj0KN4gW06El
+sJREDW+qIdCYx8kFYV1jisT+u8HxrS7pmpy1UCxhf5th4lgW/Y+4fq6EzdfHpujm
+dIxN+ZlrvSZ/mbO2ffLsH6/PVY4jaFIWfzXLhYrSGx7OsMWB/05dS/NbN23GYrrz
+JOMbNN2UjfUXwgDG8z2WUn2tAoGAbzJzeH+7J3FcNtLJTsRjiTlMX+t1JLjeDa//
+1cLIh2WAYOWEazxbyLkCdZljw18rKhyc/2fx4lNc+gSqpaEWizNcgUEaus2xdHIT
+gEFBwwJld3OU1AQEUoOfILguS7oI+gLzMs2u5u7Xl3nChSpjQ5Wd8arzlq2aLWQZ
+oQJpZwkCgYEAt1rJPy0pThzwYvpYEiYS2HmVEa7PWvtD19qDPOC6AaoPJzmP3J4u
+KmJXdk6g01R8G/QMb52V9Uen9m8YcCRyZqTTjWUDH7fDpuS7M+OkeRX/ytp4TCL0
+WejDMpu98bDTWvUBXdzQfUhwAVb/CMpX4rLtRdLZt8JT14OCDbpgogE=
-----END RSA PRIVATE KEY-----
diff --git a/chromium/net/data/ssl/certificates/client_3.pem b/chromium/net/data/ssl/certificates/client_3.pem
index 4f5ad24856c..ccd60228285 100644
--- a/chromium/net/data/ssl/certificates/client_3.pem
+++ b/chromium/net/data/ssl/certificates/client_3.pem
@@ -5,66 +5,66 @@ Certificate:
Signature Algorithm: sha256WithRSAEncryption
Issuer: CN=E CA
Validity
- Not Before: Oct 4 18:53:24 2016 GMT
- Not After : Oct 2 18:53:24 2026 GMT
+ Not Before: Dec 9 20:18:57 2016 GMT
+ Not After : Dec 7 20:18:57 2026 GMT
Subject: CN=Client Cert F
Subject Public Key Info:
Public Key Algorithm: rsaEncryption
Public-Key: (2048 bit)
Modulus:
- 00:a9:b9:61:4f:52:fe:64:34:53:67:47:d8:58:22:
- 23:82:97:6f:d0:82:e7:f7:0b:3d:db:4e:15:15:38:
- df:de:35:3e:eb:ac:19:9b:d8:8d:db:e8:fa:db:2f:
- fa:f2:20:45:92:df:f5:d3:b6:2a:03:6b:28:de:8d:
- 24:4b:aa:3b:23:3b:7e:11:08:3e:a3:96:6f:bc:73:
- 37:7d:54:91:fc:81:9e:8c:76:ed:d5:f6:e4:f6:8e:
- e8:6e:56:e2:90:eb:51:a5:f3:90:d8:45:d9:fa:1d:
- 91:01:21:3a:61:31:3a:ea:5a:c4:e9:1a:ee:00:e6:
- 96:62:ca:0b:a7:37:a9:1c:39:4e:12:3e:ad:ab:ed:
- b8:2c:86:a5:72:4c:ca:39:03:4d:61:fc:29:b8:bc:
- db:32:89:95:0a:62:1a:28:d6:8e:6d:eb:06:33:9a:
- 5b:8f:e8:73:e1:2f:1e:84:21:fb:0b:38:27:b1:83:
- a0:c7:fe:ed:79:cc:ab:57:a5:cf:5b:b3:84:0c:b9:
- b8:1a:8c:90:22:59:f1:be:4d:46:0c:85:63:7b:a7:
- 1a:49:6f:8e:ce:a2:fa:e5:29:64:03:02:dc:68:df:
- 79:b6:6b:9b:22:07:59:af:a1:ff:ba:9c:e6:5d:d4:
- 61:de:40:81:2e:02:96:02:aa:54:24:d4:b3:c4:18:
- e3:ff
+ 00:b3:5c:32:bb:c0:48:28:37:9b:45:ab:78:a0:ea:
+ 72:13:26:5d:46:ee:71:c4:24:9c:ed:a8:b6:81:35:
+ d7:72:ba:0a:ae:a9:4e:20:61:12:22:e0:00:67:80:
+ 70:be:ac:ef:03:b2:d4:b0:3a:fc:c5:ab:85:7b:04:
+ 4b:61:85:7a:17:6c:43:36:67:0b:19:7c:74:b8:65:
+ e9:1c:fd:f0:df:42:bc:0c:fd:09:7e:4f:7d:38:c0:
+ 52:71:e5:2b:19:80:82:aa:69:c2:36:6b:b7:2d:07:
+ f4:74:62:bf:8e:90:ed:47:1a:64:24:ac:4c:b8:d2:
+ 2a:d0:9d:86:08:c1:18:9e:3e:de:4f:12:5c:64:a4:
+ 2b:86:43:12:81:67:0c:8c:56:e4:16:46:3c:29:cf:
+ 4e:18:ea:4f:66:5f:b4:d6:73:5f:1e:93:ad:df:c9:
+ 06:65:cc:dc:42:ba:e9:86:42:08:a1:ab:a5:fc:22:
+ d3:23:57:a0:da:6c:80:de:c5:f9:9c:c5:11:65:9c:
+ b2:df:f3:d6:c8:bd:aa:af:40:66:ed:ce:5f:04:46:
+ 17:e6:92:ea:64:c8:b3:e4:20:cb:e0:44:09:15:1f:
+ 7c:e4:e0:07:cd:22:7c:bd:a0:06:65:35:d4:3e:1c:
+ 07:61:8f:01:53:22:25:85:93:75:73:42:c7:c1:c0:
+ 12:9f
Exponent: 65537 (0x10001)
X509v3 extensions:
X509v3 Subject Alternative Name:
email:santest@example.com, othername:<unsupported>
Signature Algorithm: sha256WithRSAEncryption
- 5f:d8:99:71:11:d1:1f:ae:7e:4a:fa:85:ff:f6:18:60:e0:c3:
- e8:8c:8d:7b:51:b9:ed:ea:26:e8:2b:ff:d8:5c:1e:98:cb:c6:
- a5:e8:ef:21:af:e5:a8:f2:47:93:5e:36:66:21:7d:84:c7:b2:
- 2c:70:31:71:67:88:c4:a9:45:c1:20:1b:e1:47:df:75:d6:83:
- a2:db:45:27:ca:fa:b1:11:b0:c2:33:bc:a7:2c:fb:bd:2b:06:
- 68:0d:95:4c:d4:2f:ab:2a:5b:f8:92:4e:9b:74:30:f2:8d:7c:
- 26:c7:f1:0f:0e:f7:f1:28:b6:84:90:db:ac:a0:1a:84:4c:3e:
- 0b:14:39:de:90:ca:58:2c:f8:16:a4:0e:4d:cd:ba:c5:1d:bb:
- 91:69:a6:55:83:96:20:ee:1f:33:58:8f:da:44:32:9b:84:1e:
- 99:d3:74:60:c9:10:67:5c:a9:03:11:74:e3:82:85:99:4c:aa:
- 4e:3d:ee:ac:91:7c:e8:b9:b1:64:08:45:48:6f:34:f4:52:8a:
- 68:f9:80:6b:5b:b2:af:83:cb:fc:77:fd:9f:d0:aa:69:3e:bd:
- f7:ca:05:17:f8:f4:39:d3:58:9a:04:81:43:a8:b3:66:90:9e:
- b6:27:b3:1c:25:ad:8f:8c:c6:45:a4:f6:02:60:3a:0b:5e:6f:
- 6b:e6:1b:3f
+ 98:4b:03:9b:ef:b9:8b:47:81:42:9c:5b:a0:49:54:2e:e1:95:
+ 51:87:9c:5c:83:b1:3c:ab:21:29:7e:e0:de:11:92:ad:75:5e:
+ 9d:e2:51:70:0e:95:e3:68:3f:2e:ad:69:50:31:57:6b:6d:7b:
+ 6c:d2:c5:4b:e5:a7:a1:20:ba:bf:1a:8e:86:47:94:72:35:34:
+ 07:5f:1a:cf:3f:13:ad:53:7f:6b:db:ef:d8:00:a2:5c:e9:5c:
+ 20:47:5a:9e:f6:91:c5:9b:05:69:f3:25:05:e2:8b:dd:d8:41:
+ 99:64:44:ed:74:e2:eb:f7:42:2c:b5:d0:f1:ac:64:c0:f4:87:
+ e9:3e:51:52:41:a3:c2:4e:58:c2:ee:fe:b4:25:37:b9:3d:c2:
+ f0:cf:c0:90:7f:f6:02:b2:38:88:92:2a:e0:d4:db:87:5c:b2:
+ 02:a6:60:b4:da:ab:53:d2:b2:7d:64:d5:d3:b6:35:66:96:f0:
+ ec:fb:9c:8d:35:40:e1:4a:7e:52:98:1f:1b:a2:e3:e4:35:70:
+ ec:33:ad:e8:a4:ed:a4:26:7d:07:a5:03:92:ac:11:81:4f:0f:
+ b3:c7:97:7f:29:d8:09:d1:28:11:f6:8d:9a:e0:5f:26:b9:7f:
+ 74:77:e7:74:b1:5b:0f:7c:ae:13:d1:75:bc:ad:49:51:05:39:
+ 06:53:6d:5c
-----BEGIN CERTIFICATE-----
MIIC8jCCAdqgAwIBAgICEAMwDQYJKoZIhvcNAQELBQAwDzENMAsGA1UEAwwERSBD
-QTAeFw0xNjEwMDQxODUzMjRaFw0yNjEwMDIxODUzMjRaMBgxFjAUBgNVBAMMDUNs
-aWVudCBDZXJ0IEYwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCpuWFP
-Uv5kNFNnR9hYIiOCl2/Qguf3Cz3bThUVON/eNT7rrBmb2I3b6PrbL/ryIEWS3/XT
-tioDayjejSRLqjsjO34RCD6jlm+8czd9VJH8gZ6Mdu3V9uT2juhuVuKQ61Gl85DY
-Rdn6HZEBITphMTrqWsTpGu4A5pZiygunN6kcOU4SPq2r7bgshqVyTMo5A01h/Cm4
-vNsyiZUKYhoo1o5t6wYzmluP6HPhLx6EIfsLOCexg6DH/u15zKtXpc9bs4QMubga
-jJAiWfG+TUYMhWN7pxpJb47OovrlKWQDAtxo33m2a5siB1mvof+6nOZd1GHeQIEu
-ApYCqlQk1LPEGOP/AgMBAAGjTzBNMEsGA1UdEQREMEKBE3NhbnRlc3RAZXhhbXBs
+QTAeFw0xNjEyMDkyMDE4NTdaFw0yNjEyMDcyMDE4NTdaMBgxFjAUBgNVBAMMDUNs
+aWVudCBDZXJ0IEYwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCzXDK7
+wEgoN5tFq3ig6nITJl1G7nHEJJztqLaBNddyugquqU4gYRIi4ABngHC+rO8DstSw
+OvzFq4V7BEthhXoXbEM2ZwsZfHS4Zekc/fDfQrwM/Ql+T304wFJx5SsZgIKqacI2
+a7ctB/R0Yr+OkO1HGmQkrEy40irQnYYIwRiePt5PElxkpCuGQxKBZwyMVuQWRjwp
+z04Y6k9mX7TWc18ek63fyQZlzNxCuumGQgihq6X8ItMjV6DabIDexfmcxRFlnLLf
+89bIvaqvQGbtzl8ERhfmkupkyLPkIMvgRAkVH3zk4AfNIny9oAZlNdQ+HAdhjwFT
+IiWFk3VzQsfBwBKfAgMBAAGjTzBNMEsGA1UdEQREMEKBE3NhbnRlc3RAZXhhbXBs
ZS5jb22gKwYKKwYBBAGCNxQCA6AdDBtzYW50ZXN0QGFkLmNvcnAuZXhhbXBsZS5j
-b20wDQYJKoZIhvcNAQELBQADggEBAF/YmXER0R+ufkr6hf/2GGDgw+iMjXtRue3q
-Jugr/9hcHpjLxqXo7yGv5ajyR5NeNmYhfYTHsixwMXFniMSpRcEgG+FH33XWg6Lb
-RSfK+rERsMIzvKcs+70rBmgNlUzUL6sqW/iSTpt0MPKNfCbH8Q8O9/EotoSQ26yg
-GoRMPgsUOd6Qylgs+BakDk3NusUdu5FpplWDliDuHzNYj9pEMpuEHpnTdGDJEGdc
-qQMRdOOChZlMqk497qyRfOi5sWQIRUhvNPRSimj5gGtbsq+Dy/x3/Z/Qqmk+vffK
-BRf49DnTWJoEgUOos2aQnrYnsxwlrY+MxkWk9gJgOgteb2vmGz8=
+b20wDQYJKoZIhvcNAQELBQADggEBAJhLA5vvuYtHgUKcW6BJVC7hlVGHnFyDsTyr
+ISl+4N4Rkq11Xp3iUXAOleNoPy6taVAxV2tte2zSxUvlp6Egur8ajoZHlHI1NAdf
+Gs8/E61Tf2vb79gAolzpXCBHWp72kcWbBWnzJQXii93YQZlkRO104uv3Qiy10PGs
+ZMD0h+k+UVJBo8JOWMLu/rQlN7k9wvDPwJB/9gKyOIiSKuDU24dcsgKmYLTaq1PS
+sn1k1dO2NWaW8Oz7nI01QOFKflKYHxui4+Q1cOwzreik7aQmfQelA5KsEYFPD7PH
+l38p2AnRKBH2jZrgXya5f3R353SxWw98rhPRdbytSVEFOQZTbVw=
-----END CERTIFICATE-----
diff --git a/chromium/net/data/ssl/certificates/client_3.pk8 b/chromium/net/data/ssl/certificates/client_3.pk8
index 68f019a523d..2ffcdb2928a 100644
--- a/chromium/net/data/ssl/certificates/client_3.pk8
+++ b/chromium/net/data/ssl/certificates/client_3.pk8
Binary files differ
diff --git a/chromium/net/data/ssl/certificates/client_3_ca.pem b/chromium/net/data/ssl/certificates/client_3_ca.pem
index dd58ffa7a3c..78080961705 100644
--- a/chromium/net/data/ssl/certificates/client_3_ca.pem
+++ b/chromium/net/data/ssl/certificates/client_3_ca.pem
@@ -5,31 +5,31 @@ Certificate:
Signature Algorithm: sha256WithRSAEncryption
Issuer: CN=C Root CA
Validity
- Not Before: Oct 4 18:53:24 2016 GMT
- Not After : Oct 2 18:53:24 2026 GMT
+ Not Before: Dec 9 20:18:57 2016 GMT
+ Not After : Dec 7 20:18:57 2026 GMT
Subject: CN=E CA
Subject Public Key Info:
Public Key Algorithm: rsaEncryption
Public-Key: (2048 bit)
Modulus:
- 00:a2:7e:a3:fd:c1:d7:78:cd:57:ac:67:54:37:69:
- fb:72:6f:1d:8f:d0:47:0f:11:14:ab:42:d8:3d:6a:
- 34:2b:d6:38:07:df:16:1d:c6:62:eb:d7:12:e1:86:
- 83:f2:dd:8f:97:09:94:8f:1b:ff:3b:84:9b:48:e5:
- 0d:43:6b:ae:bb:75:88:1c:c6:3a:7f:d8:12:d9:7c:
- 12:18:6d:e2:f0:88:d4:3e:5a:93:b3:af:c1:79:a1:
- b6:a3:f7:56:46:21:e6:7d:6e:36:ea:ba:4b:52:f7:
- a9:45:0b:83:09:2c:09:22:8a:67:5a:8f:88:60:b0:
- 11:07:25:9b:c2:6a:3c:63:4c:0e:69:45:ce:9d:ba:
- c9:d4:01:fb:78:56:38:08:8f:e5:d6:ff:ac:e4:04:
- fa:26:cf:d2:05:33:57:a3:8e:80:c0:b6:40:d5:d3:
- ca:85:17:30:b2:24:f4:19:af:c5:48:a4:ed:c0:49:
- c1:a4:b7:89:29:ba:e5:2d:37:78:1c:d6:3e:9b:03:
- fa:bc:7b:e2:76:a6:70:f3:1b:9d:b2:4b:fc:72:7b:
- 77:89:50:bb:88:2f:b5:b6:a2:c7:33:27:b7:d1:1a:
- 7c:d4:58:e3:5e:88:ca:f8:49:c3:cd:cc:0f:93:4b:
- 3c:fd:75:c3:7b:6f:bf:d3:db:ba:2e:31:7b:a7:a5:
- 42:c5
+ 00:c3:39:c3:5a:8e:ff:f2:1d:cc:26:91:5d:15:9e:
+ ca:e0:fb:cf:99:5f:13:3d:c6:37:59:8b:ce:cc:76:
+ 0e:1c:9f:b6:49:5b:09:97:63:9d:e1:00:74:44:fb:
+ 2f:53:f3:d5:03:92:77:97:53:74:7e:d2:da:d3:a3:
+ f4:c1:91:6a:83:ff:89:fe:73:46:56:ca:6d:51:0d:
+ 57:16:3d:3e:e8:fc:00:d9:4a:7a:7d:93:84:06:12:
+ c5:ff:31:b3:a6:eb:96:18:71:b8:56:5c:2f:ab:78:
+ e2:53:dd:15:d8:65:c8:f6:96:14:dc:15:cf:2a:39:
+ ed:e1:08:1b:84:29:c7:1c:78:67:c8:e0:72:58:4e:
+ 33:7f:cb:ef:71:82:db:45:1d:7c:0c:d0:f5:4c:af:
+ 85:6b:14:61:50:87:34:42:fe:45:a3:3c:a3:53:57:
+ 1d:ac:11:c8:cf:2f:5e:cb:78:87:39:a1:41:3f:69:
+ 21:5c:1e:19:02:a3:6c:91:d3:1b:4e:50:fc:a4:b1:
+ 03:87:c0:58:b1:fe:cd:58:5e:53:ed:c9:d6:5d:9e:
+ a3:fb:0d:e0:a0:8e:3d:c9:9e:9e:83:07:61:c7:30:
+ 5a:ca:29:93:04:af:5e:f3:57:2e:c2:d8:c8:ae:7f:
+ 5c:a4:27:fa:cd:55:a2:fd:89:d2:0b:87:24:6b:7b:
+ fb:19
Exponent: 65537 (0x10001)
X509v3 extensions:
X509v3 Basic Constraints: critical
@@ -37,35 +37,35 @@ Certificate:
X509v3 Key Usage: critical
Certificate Sign, CRL Sign
Signature Algorithm: sha256WithRSAEncryption
- 92:8b:93:94:03:04:91:3f:4d:8b:f3:90:53:ee:73:b5:33:c7:
- 61:ea:0f:a5:59:9b:f0:0d:4f:7d:48:0d:5a:58:e7:1f:68:f6:
- d6:58:75:33:a5:d2:b7:65:6a:28:40:bc:0e:1e:78:ee:9a:13:
- 3c:b0:8b:8f:98:72:86:50:3a:a3:bf:6d:f0:21:95:a8:73:d0:
- dd:e5:0e:25:b1:62:76:65:69:1f:ee:26:82:ab:be:a4:a8:30:
- a7:41:34:07:57:2f:8b:ab:25:af:cb:23:a5:79:cf:b2:a2:17:
- 02:a7:aa:50:92:6e:0d:9b:ff:c9:22:38:b4:0f:47:94:d2:80:
- 7f:92:30:00:ec:5b:22:e2:a6:71:5e:e8:8f:0d:2f:38:2c:29:
- 47:6a:7f:20:0a:e2:42:cb:b7:6e:2b:29:0f:03:55:94:84:5f:
- e7:47:bf:ae:75:88:05:4e:42:ac:78:57:9d:9c:e2:77:d2:17:
- 42:55:ba:f8:77:ee:61:d6:e8:ec:aa:e0:7a:a6:65:c6:35:80:
- 08:3d:39:a6:70:8c:9e:6d:7a:ee:e7:cf:36:46:98:00:c8:7b:
- b8:84:7f:9d:9f:bd:31:4f:99:25:6e:76:9a:5d:46:3e:40:70:
- c6:a8:03:f3:98:9c:be:fb:f6:ad:c2:8d:e3:f9:7d:93:3a:78:
- da:b3:d7:dc
+ 67:d4:6c:cf:cd:54:81:67:2a:c2:c4:66:c7:76:9c:b0:8b:6b:
+ ef:b8:ae:a9:b3:d6:f8:47:91:d5:97:0b:bd:1a:87:21:8c:ce:
+ be:0c:80:d5:a5:25:0d:0a:c7:ed:be:cb:8c:6d:08:e8:de:a5:
+ 33:89:e6:87:df:2b:f4:54:b3:c2:94:15:0d:36:5e:1a:aa:c0:
+ b0:03:3c:24:c6:a1:81:91:ca:fe:db:0f:59:1b:d6:4e:48:0b:
+ 52:d3:e7:07:d7:b1:ca:b2:22:e4:d4:37:a4:3c:87:3c:0a:11:
+ a6:10:2a:ed:86:2a:bb:db:10:7e:f3:a5:fc:10:ab:80:5b:07:
+ 58:7c:22:76:3e:9b:9c:72:79:0d:dc:85:f8:e7:c2:0f:17:aa:
+ 01:dd:8e:24:27:77:4e:23:03:da:88:e0:df:e6:ca:b4:84:56:
+ a1:dc:9f:e0:93:94:97:d2:98:cd:32:6d:73:84:f9:3e:4c:96:
+ b3:51:07:b8:9f:66:32:d1:ac:53:0e:17:a9:6f:29:d1:7b:73:
+ b3:55:9b:cc:8f:8b:e5:49:fd:fd:f2:30:d6:d0:f7:03:06:12:
+ e3:66:2d:0d:a1:da:28:04:04:29:b8:40:6e:0e:6f:31:48:cb:
+ 54:f7:e2:89:22:d8:05:e0:f5:7e:48:b3:96:ff:6b:ef:e7:fe:
+ 71:1d:0b:77
-----BEGIN CERTIFICATE-----
MIICwjCCAaqgAwIBAgICEAIwDQYJKoZIhvcNAQELBQAwFDESMBAGA1UEAwwJQyBS
-b290IENBMB4XDTE2MTAwNDE4NTMyNFoXDTI2MTAwMjE4NTMyNFowDzENMAsGA1UE
-AwwERSBDQTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAKJ+o/3B13jN
-V6xnVDdp+3JvHY/QRw8RFKtC2D1qNCvWOAffFh3GYuvXEuGGg/Ldj5cJlI8b/zuE
-m0jlDUNrrrt1iBzGOn/YEtl8Ehht4vCI1D5ak7OvwXmhtqP3VkYh5n1uNuq6S1L3
-qUULgwksCSKKZ1qPiGCwEQclm8JqPGNMDmlFzp26ydQB+3hWOAiP5db/rOQE+ibP
-0gUzV6OOgMC2QNXTyoUXMLIk9BmvxUik7cBJwaS3iSm65S03eBzWPpsD+rx74nam
-cPMbnbJL/HJ7d4lQu4gvtbaixzMnt9EafNRY416IyvhJw83MD5NLPP11w3tvv9Pb
-ui4xe6elQsUCAwEAAaMjMCEwDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMC
-AQYwDQYJKoZIhvcNAQELBQADggEBAJKLk5QDBJE/TYvzkFPuc7Uzx2HqD6VZm/AN
-T31IDVpY5x9o9tZYdTOl0rdlaihAvA4eeO6aEzywi4+YcoZQOqO/bfAhlahz0N3l
-DiWxYnZlaR/uJoKrvqSoMKdBNAdXL4urJa/LI6V5z7KiFwKnqlCSbg2b/8kiOLQP
-R5TSgH+SMADsWyLipnFe6I8NLzgsKUdqfyAK4kLLt24rKQ8DVZSEX+dHv651iAVO
-Qqx4V52c4nfSF0JVuvh37mHW6Oyq4HqmZcY1gAg9OaZwjJ5teu7nzzZGmADIe7iE
-f52fvTFPmSVudppdRj5AcMaoA/OYnL779q3CjeP5fZM6eNqz19w=
+b290IENBMB4XDTE2MTIwOTIwMTg1N1oXDTI2MTIwNzIwMTg1N1owDzENMAsGA1UE
+AwwERSBDQTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAMM5w1qO//Id
+zCaRXRWeyuD7z5lfEz3GN1mLzsx2DhyftklbCZdjneEAdET7L1Pz1QOSd5dTdH7S
+2tOj9MGRaoP/if5zRlbKbVENVxY9Puj8ANlKen2ThAYSxf8xs6brlhhxuFZcL6t4
+4lPdFdhlyPaWFNwVzyo57eEIG4Qpxxx4Z8jgclhOM3/L73GC20UdfAzQ9UyvhWsU
+YVCHNEL+RaM8o1NXHawRyM8vXst4hzmhQT9pIVweGQKjbJHTG05Q/KSxA4fAWLH+
+zVheU+3J1l2eo/sN4KCOPcmenoMHYccwWsopkwSvXvNXLsLYyK5/XKQn+s1Vov2J
+0guHJGt7+xkCAwEAAaMjMCEwDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMC
+AQYwDQYJKoZIhvcNAQELBQADggEBAGfUbM/NVIFnKsLEZsd2nLCLa++4rqmz1vhH
+kdWXC70ahyGMzr4MgNWlJQ0Kx+2+y4xtCOjepTOJ5offK/RUs8KUFQ02XhqqwLAD
+PCTGoYGRyv7bD1kb1k5IC1LT5wfXscqyIuTUN6Q8hzwKEaYQKu2GKrvbEH7zpfwQ
+q4BbB1h8InY+m5xyeQ3chfjnwg8XqgHdjiQnd04jA9qI4N/myrSEVqHcn+CTlJfS
+mM0ybXOE+T5MlrNRB7ifZjLRrFMOF6lvKdF7c7NVm8yPi+VJ/f3yMNbQ9wMGEuNm
+LQ2h2igEBCm4QG4ObzFIy1T34oki2AXg9X5Is5b/a+/n/nEdC3c=
-----END CERTIFICATE-----
diff --git a/chromium/net/data/ssl/certificates/client_4.key b/chromium/net/data/ssl/certificates/client_4.key
index b1e7e0f86c2..43175e9c8a6 100644
--- a/chromium/net/data/ssl/certificates/client_4.key
+++ b/chromium/net/data/ssl/certificates/client_4.key
@@ -1,5 +1,5 @@
-----BEGIN EC PRIVATE KEY-----
-MHcCAQEEILP75xbRvuB3x6CmLmO6dnAz4SzWM52MjX/ENrMfZWSEoAoGCCqGSM49
-AwEHoUQDQgAEeS7h2cVpnREfhVilcTyRzlg4kE1IhGT3MUl1BkvR5e1EgvkLapKA
-8lLte3NLOoH/gPKnhLDPmN5N2uTCEZhpzw==
+MHcCAQEEIMivPU8D2DOgGS1XWJ0SHOybwHGLYceOy0di/O3NTyfooAoGCCqGSM49
+AwEHoUQDQgAEicT32YPEOZz49vy8i2ZucO1QMh1i5zJMBmKPOCgzY1l9FmLhv61t
+3zRtxNZRllR1HFiAOIOIVcadhrfDZqF5Zw==
-----END EC PRIVATE KEY-----
diff --git a/chromium/net/data/ssl/certificates/client_4.pem b/chromium/net/data/ssl/certificates/client_4.pem
index 3eeca242c95..914b4533710 100644
--- a/chromium/net/data/ssl/certificates/client_4.pem
+++ b/chromium/net/data/ssl/certificates/client_4.pem
@@ -5,18 +5,18 @@ Certificate:
Signature Algorithm: sha256WithRSAEncryption
Issuer: CN=E CA
Validity
- Not Before: Oct 4 18:53:24 2016 GMT
- Not After : Oct 2 18:53:24 2026 GMT
+ Not Before: Dec 9 20:18:57 2016 GMT
+ Not After : Dec 7 20:18:57 2026 GMT
Subject: CN=Client Cert G
Subject Public Key Info:
Public Key Algorithm: id-ecPublicKey
Public-Key: (256 bit)
pub:
- 04:79:2e:e1:d9:c5:69:9d:11:1f:85:58:a5:71:3c:
- 91:ce:58:38:90:4d:48:84:64:f7:31:49:75:06:4b:
- d1:e5:ed:44:82:f9:0b:6a:92:80:f2:52:ed:7b:73:
- 4b:3a:81:ff:80:f2:a7:84:b0:cf:98:de:4d:da:e4:
- c2:11:98:69:cf
+ 04:89:c4:f7:d9:83:c4:39:9c:f8:f6:fc:bc:8b:66:
+ 6e:70:ed:50:32:1d:62:e7:32:4c:06:62:8f:38:28:
+ 33:63:59:7d:16:62:e1:bf:ad:6d:df:34:6d:c4:d6:
+ 51:96:54:75:1c:58:80:38:83:88:55:c6:9d:86:b7:
+ c3:66:a1:79:67
ASN1 OID: prime256v1
X509v3 extensions:
X509v3 Basic Constraints: critical
@@ -24,31 +24,31 @@ Certificate:
X509v3 Extended Key Usage:
TLS Web Server Authentication, TLS Web Client Authentication
Signature Algorithm: sha256WithRSAEncryption
- 70:44:30:40:b7:d6:5b:09:e6:81:a1:a7:80:cd:bc:12:5d:e1:
- 45:7d:fb:04:5f:5f:21:b9:e5:a9:e0:79:52:5a:50:21:11:bb:
- 8c:25:08:e1:6d:19:e3:ba:e7:69:74:db:a6:b2:41:a4:f5:39:
- 63:18:e6:bc:ce:db:d8:3f:17:e1:90:9f:62:3a:d3:52:f4:c4:
- 01:4d:db:ad:16:ad:8b:31:51:fe:82:68:fd:34:c4:58:dc:4d:
- 6b:72:74:30:98:a6:03:4b:21:dd:54:1b:ed:e0:a5:3f:a9:5e:
- 1d:e6:57:3f:13:f4:e0:dc:d0:bf:90:68:dc:e1:e7:b5:81:b4:
- f8:d5:45:96:95:b9:cd:83:15:c8:32:a6:20:2c:fc:b5:05:42:
- 1a:7e:26:4c:a1:9a:8b:26:2b:1b:72:c7:a5:38:f3:57:4c:b4:
- 7f:8e:dc:d9:52:0a:52:ac:e5:d9:18:0b:ae:91:b9:c5:e0:13:
- cb:15:8d:19:3b:e9:60:1b:6b:31:0a:c7:22:4a:5a:ed:49:cf:
- 72:e1:dd:93:1e:43:a8:e0:3e:02:b6:06:ee:b9:a9:d3:d9:88:
- 2d:81:f6:96:cb:13:07:a8:51:81:89:8c:6b:28:d3:0c:22:8f:
- e9:d7:92:1d:5a:2a:d6:c0:55:6b:86:2b:a7:f9:9e:35:88:5d:
- bb:42:eb:b8
+ 43:3c:6f:e4:e7:89:a9:fe:f8:d0:d6:a0:13:94:1b:a1:98:22:
+ 26:0d:e1:3b:a1:91:41:f1:5e:88:38:cb:7d:f0:55:8c:c3:df:
+ a3:99:31:71:0c:d0:1f:23:86:89:d7:ca:9f:f0:c6:bc:d2:b8:
+ 0b:4e:bc:bf:63:93:4e:c4:71:65:97:c0:f2:ea:35:34:9c:d5:
+ b5:8e:15:2e:bb:0b:63:ab:f6:fd:5d:2d:22:f7:00:e6:5a:88:
+ 01:6f:f8:ef:8a:be:68:1d:95:b5:c9:b2:47:be:cd:98:bd:5a:
+ ae:a2:b9:a3:53:bc:9e:87:de:40:a6:17:b5:7c:bd:4d:35:f5:
+ 29:72:22:a7:ee:2a:bc:4c:e2:b0:a6:98:47:1d:93:01:f8:53:
+ ee:af:e3:3a:1f:a2:e0:36:eb:67:28:7a:39:b8:89:95:44:57:
+ 08:bb:20:8d:0b:27:36:15:ce:48:11:ae:32:07:ef:44:12:e5:
+ 97:2e:92:56:c4:d6:93:0f:41:25:38:e5:52:0e:c3:f3:cc:9d:
+ de:b0:1d:4e:e3:51:79:63:0f:4c:58:ea:7c:e7:7a:ac:a8:f3:
+ c4:45:16:34:77:ba:6b:a7:49:9c:aa:62:d1:dd:81:6b:55:08:
+ 38:39:11:23:a0:ec:50:ff:58:ca:22:d3:29:c8:2e:bc:35:62:
+ 9b:cd:56:fb
-----BEGIN CERTIFICATE-----
MIICBjCB76ADAgECAgIQBDANBgkqhkiG9w0BAQsFADAPMQ0wCwYDVQQDDARFIENB
-MB4XDTE2MTAwNDE4NTMyNFoXDTI2MTAwMjE4NTMyNFowGDEWMBQGA1UEAwwNQ2xp
-ZW50IENlcnQgRzBZMBMGByqGSM49AgEGCCqGSM49AwEHA0IABHku4dnFaZ0RH4VY
-pXE8kc5YOJBNSIRk9zFJdQZL0eXtRIL5C2qSgPJS7XtzSzqB/4Dyp4Swz5jeTdrk
-whGYac+jLzAtMAwGA1UdEwEB/wQCMAAwHQYDVR0lBBYwFAYIKwYBBQUHAwEGCCsG
-AQUFBwMCMA0GCSqGSIb3DQEBCwUAA4IBAQBwRDBAt9ZbCeaBoaeAzbwSXeFFffsE
-X18hueWp4HlSWlAhEbuMJQjhbRnjuudpdNumskGk9TljGOa8ztvYPxfhkJ9iOtNS
-9MQBTdutFq2LMVH+gmj9NMRY3E1rcnQwmKYDSyHdVBvt4KU/qV4d5lc/E/Tg3NC/
-kGjc4ee1gbT41UWWlbnNgxXIMqYgLPy1BUIafiZMoZqLJisbcselOPNXTLR/jtzZ
-UgpSrOXZGAuukbnF4BPLFY0ZO+lgG2sxCsciSlrtSc9y4d2THkOo4D4CtgbuuanT
-2YgtgfaWyxMHqFGBiYxrKNMMIo/p15IdWirWwFVrhiun+Z41iF27Quu4
+MB4XDTE2MTIwOTIwMTg1N1oXDTI2MTIwNzIwMTg1N1owGDEWMBQGA1UEAwwNQ2xp
+ZW50IENlcnQgRzBZMBMGByqGSM49AgEGCCqGSM49AwEHA0IABInE99mDxDmc+Pb8
+vItmbnDtUDIdYucyTAZijzgoM2NZfRZi4b+tbd80bcTWUZZUdRxYgDiDiFXGnYa3
+w2aheWejLzAtMAwGA1UdEwEB/wQCMAAwHQYDVR0lBBYwFAYIKwYBBQUHAwEGCCsG
+AQUFBwMCMA0GCSqGSIb3DQEBCwUAA4IBAQBDPG/k54mp/vjQ1qATlBuhmCImDeE7
+oZFB8V6IOMt98FWMw9+jmTFxDNAfI4aJ18qf8Ma80rgLTry/Y5NOxHFll8Dy6jU0
+nNW1jhUuuwtjq/b9XS0i9wDmWogBb/jvir5oHZW1ybJHvs2YvVquormjU7yeh95A
+phe1fL1NNfUpciKn7iq8TOKwpphHHZMB+FPur+M6H6LgNutnKHo5uImVRFcIuyCN
+Cyc2Fc5IEa4yB+9EEuWXLpJWxNaTD0ElOOVSDsPzzJ3esB1O41F5Yw9MWOp853qs
+qPPERRY0d7prp0mcqmLR3YFrVQg4OREjoOxQ/1jKItMpyC68NWKbzVb7
-----END CERTIFICATE-----
diff --git a/chromium/net/data/ssl/certificates/client_4.pk8 b/chromium/net/data/ssl/certificates/client_4.pk8
index 20ea5cfd7bc..5f5f1580c23 100644
--- a/chromium/net/data/ssl/certificates/client_4.pk8
+++ b/chromium/net/data/ssl/certificates/client_4.pk8
Binary files differ
diff --git a/chromium/net/data/ssl/certificates/client_4_ca.pem b/chromium/net/data/ssl/certificates/client_4_ca.pem
index dd58ffa7a3c..78080961705 100644
--- a/chromium/net/data/ssl/certificates/client_4_ca.pem
+++ b/chromium/net/data/ssl/certificates/client_4_ca.pem
@@ -5,31 +5,31 @@ Certificate:
Signature Algorithm: sha256WithRSAEncryption
Issuer: CN=C Root CA
Validity
- Not Before: Oct 4 18:53:24 2016 GMT
- Not After : Oct 2 18:53:24 2026 GMT
+ Not Before: Dec 9 20:18:57 2016 GMT
+ Not After : Dec 7 20:18:57 2026 GMT
Subject: CN=E CA
Subject Public Key Info:
Public Key Algorithm: rsaEncryption
Public-Key: (2048 bit)
Modulus:
- 00:a2:7e:a3:fd:c1:d7:78:cd:57:ac:67:54:37:69:
- fb:72:6f:1d:8f:d0:47:0f:11:14:ab:42:d8:3d:6a:
- 34:2b:d6:38:07:df:16:1d:c6:62:eb:d7:12:e1:86:
- 83:f2:dd:8f:97:09:94:8f:1b:ff:3b:84:9b:48:e5:
- 0d:43:6b:ae:bb:75:88:1c:c6:3a:7f:d8:12:d9:7c:
- 12:18:6d:e2:f0:88:d4:3e:5a:93:b3:af:c1:79:a1:
- b6:a3:f7:56:46:21:e6:7d:6e:36:ea:ba:4b:52:f7:
- a9:45:0b:83:09:2c:09:22:8a:67:5a:8f:88:60:b0:
- 11:07:25:9b:c2:6a:3c:63:4c:0e:69:45:ce:9d:ba:
- c9:d4:01:fb:78:56:38:08:8f:e5:d6:ff:ac:e4:04:
- fa:26:cf:d2:05:33:57:a3:8e:80:c0:b6:40:d5:d3:
- ca:85:17:30:b2:24:f4:19:af:c5:48:a4:ed:c0:49:
- c1:a4:b7:89:29:ba:e5:2d:37:78:1c:d6:3e:9b:03:
- fa:bc:7b:e2:76:a6:70:f3:1b:9d:b2:4b:fc:72:7b:
- 77:89:50:bb:88:2f:b5:b6:a2:c7:33:27:b7:d1:1a:
- 7c:d4:58:e3:5e:88:ca:f8:49:c3:cd:cc:0f:93:4b:
- 3c:fd:75:c3:7b:6f:bf:d3:db:ba:2e:31:7b:a7:a5:
- 42:c5
+ 00:c3:39:c3:5a:8e:ff:f2:1d:cc:26:91:5d:15:9e:
+ ca:e0:fb:cf:99:5f:13:3d:c6:37:59:8b:ce:cc:76:
+ 0e:1c:9f:b6:49:5b:09:97:63:9d:e1:00:74:44:fb:
+ 2f:53:f3:d5:03:92:77:97:53:74:7e:d2:da:d3:a3:
+ f4:c1:91:6a:83:ff:89:fe:73:46:56:ca:6d:51:0d:
+ 57:16:3d:3e:e8:fc:00:d9:4a:7a:7d:93:84:06:12:
+ c5:ff:31:b3:a6:eb:96:18:71:b8:56:5c:2f:ab:78:
+ e2:53:dd:15:d8:65:c8:f6:96:14:dc:15:cf:2a:39:
+ ed:e1:08:1b:84:29:c7:1c:78:67:c8:e0:72:58:4e:
+ 33:7f:cb:ef:71:82:db:45:1d:7c:0c:d0:f5:4c:af:
+ 85:6b:14:61:50:87:34:42:fe:45:a3:3c:a3:53:57:
+ 1d:ac:11:c8:cf:2f:5e:cb:78:87:39:a1:41:3f:69:
+ 21:5c:1e:19:02:a3:6c:91:d3:1b:4e:50:fc:a4:b1:
+ 03:87:c0:58:b1:fe:cd:58:5e:53:ed:c9:d6:5d:9e:
+ a3:fb:0d:e0:a0:8e:3d:c9:9e:9e:83:07:61:c7:30:
+ 5a:ca:29:93:04:af:5e:f3:57:2e:c2:d8:c8:ae:7f:
+ 5c:a4:27:fa:cd:55:a2:fd:89:d2:0b:87:24:6b:7b:
+ fb:19
Exponent: 65537 (0x10001)
X509v3 extensions:
X509v3 Basic Constraints: critical
@@ -37,35 +37,35 @@ Certificate:
X509v3 Key Usage: critical
Certificate Sign, CRL Sign
Signature Algorithm: sha256WithRSAEncryption
- 92:8b:93:94:03:04:91:3f:4d:8b:f3:90:53:ee:73:b5:33:c7:
- 61:ea:0f:a5:59:9b:f0:0d:4f:7d:48:0d:5a:58:e7:1f:68:f6:
- d6:58:75:33:a5:d2:b7:65:6a:28:40:bc:0e:1e:78:ee:9a:13:
- 3c:b0:8b:8f:98:72:86:50:3a:a3:bf:6d:f0:21:95:a8:73:d0:
- dd:e5:0e:25:b1:62:76:65:69:1f:ee:26:82:ab:be:a4:a8:30:
- a7:41:34:07:57:2f:8b:ab:25:af:cb:23:a5:79:cf:b2:a2:17:
- 02:a7:aa:50:92:6e:0d:9b:ff:c9:22:38:b4:0f:47:94:d2:80:
- 7f:92:30:00:ec:5b:22:e2:a6:71:5e:e8:8f:0d:2f:38:2c:29:
- 47:6a:7f:20:0a:e2:42:cb:b7:6e:2b:29:0f:03:55:94:84:5f:
- e7:47:bf:ae:75:88:05:4e:42:ac:78:57:9d:9c:e2:77:d2:17:
- 42:55:ba:f8:77:ee:61:d6:e8:ec:aa:e0:7a:a6:65:c6:35:80:
- 08:3d:39:a6:70:8c:9e:6d:7a:ee:e7:cf:36:46:98:00:c8:7b:
- b8:84:7f:9d:9f:bd:31:4f:99:25:6e:76:9a:5d:46:3e:40:70:
- c6:a8:03:f3:98:9c:be:fb:f6:ad:c2:8d:e3:f9:7d:93:3a:78:
- da:b3:d7:dc
+ 67:d4:6c:cf:cd:54:81:67:2a:c2:c4:66:c7:76:9c:b0:8b:6b:
+ ef:b8:ae:a9:b3:d6:f8:47:91:d5:97:0b:bd:1a:87:21:8c:ce:
+ be:0c:80:d5:a5:25:0d:0a:c7:ed:be:cb:8c:6d:08:e8:de:a5:
+ 33:89:e6:87:df:2b:f4:54:b3:c2:94:15:0d:36:5e:1a:aa:c0:
+ b0:03:3c:24:c6:a1:81:91:ca:fe:db:0f:59:1b:d6:4e:48:0b:
+ 52:d3:e7:07:d7:b1:ca:b2:22:e4:d4:37:a4:3c:87:3c:0a:11:
+ a6:10:2a:ed:86:2a:bb:db:10:7e:f3:a5:fc:10:ab:80:5b:07:
+ 58:7c:22:76:3e:9b:9c:72:79:0d:dc:85:f8:e7:c2:0f:17:aa:
+ 01:dd:8e:24:27:77:4e:23:03:da:88:e0:df:e6:ca:b4:84:56:
+ a1:dc:9f:e0:93:94:97:d2:98:cd:32:6d:73:84:f9:3e:4c:96:
+ b3:51:07:b8:9f:66:32:d1:ac:53:0e:17:a9:6f:29:d1:7b:73:
+ b3:55:9b:cc:8f:8b:e5:49:fd:fd:f2:30:d6:d0:f7:03:06:12:
+ e3:66:2d:0d:a1:da:28:04:04:29:b8:40:6e:0e:6f:31:48:cb:
+ 54:f7:e2:89:22:d8:05:e0:f5:7e:48:b3:96:ff:6b:ef:e7:fe:
+ 71:1d:0b:77
-----BEGIN CERTIFICATE-----
MIICwjCCAaqgAwIBAgICEAIwDQYJKoZIhvcNAQELBQAwFDESMBAGA1UEAwwJQyBS
-b290IENBMB4XDTE2MTAwNDE4NTMyNFoXDTI2MTAwMjE4NTMyNFowDzENMAsGA1UE
-AwwERSBDQTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAKJ+o/3B13jN
-V6xnVDdp+3JvHY/QRw8RFKtC2D1qNCvWOAffFh3GYuvXEuGGg/Ldj5cJlI8b/zuE
-m0jlDUNrrrt1iBzGOn/YEtl8Ehht4vCI1D5ak7OvwXmhtqP3VkYh5n1uNuq6S1L3
-qUULgwksCSKKZ1qPiGCwEQclm8JqPGNMDmlFzp26ydQB+3hWOAiP5db/rOQE+ibP
-0gUzV6OOgMC2QNXTyoUXMLIk9BmvxUik7cBJwaS3iSm65S03eBzWPpsD+rx74nam
-cPMbnbJL/HJ7d4lQu4gvtbaixzMnt9EafNRY416IyvhJw83MD5NLPP11w3tvv9Pb
-ui4xe6elQsUCAwEAAaMjMCEwDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMC
-AQYwDQYJKoZIhvcNAQELBQADggEBAJKLk5QDBJE/TYvzkFPuc7Uzx2HqD6VZm/AN
-T31IDVpY5x9o9tZYdTOl0rdlaihAvA4eeO6aEzywi4+YcoZQOqO/bfAhlahz0N3l
-DiWxYnZlaR/uJoKrvqSoMKdBNAdXL4urJa/LI6V5z7KiFwKnqlCSbg2b/8kiOLQP
-R5TSgH+SMADsWyLipnFe6I8NLzgsKUdqfyAK4kLLt24rKQ8DVZSEX+dHv651iAVO
-Qqx4V52c4nfSF0JVuvh37mHW6Oyq4HqmZcY1gAg9OaZwjJ5teu7nzzZGmADIe7iE
-f52fvTFPmSVudppdRj5AcMaoA/OYnL779q3CjeP5fZM6eNqz19w=
+b290IENBMB4XDTE2MTIwOTIwMTg1N1oXDTI2MTIwNzIwMTg1N1owDzENMAsGA1UE
+AwwERSBDQTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAMM5w1qO//Id
+zCaRXRWeyuD7z5lfEz3GN1mLzsx2DhyftklbCZdjneEAdET7L1Pz1QOSd5dTdH7S
+2tOj9MGRaoP/if5zRlbKbVENVxY9Puj8ANlKen2ThAYSxf8xs6brlhhxuFZcL6t4
+4lPdFdhlyPaWFNwVzyo57eEIG4Qpxxx4Z8jgclhOM3/L73GC20UdfAzQ9UyvhWsU
+YVCHNEL+RaM8o1NXHawRyM8vXst4hzmhQT9pIVweGQKjbJHTG05Q/KSxA4fAWLH+
+zVheU+3J1l2eo/sN4KCOPcmenoMHYccwWsopkwSvXvNXLsLYyK5/XKQn+s1Vov2J
+0guHJGt7+xkCAwEAAaMjMCEwDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMC
+AQYwDQYJKoZIhvcNAQELBQADggEBAGfUbM/NVIFnKsLEZsd2nLCLa++4rqmz1vhH
+kdWXC70ahyGMzr4MgNWlJQ0Kx+2+y4xtCOjepTOJ5offK/RUs8KUFQ02XhqqwLAD
+PCTGoYGRyv7bD1kb1k5IC1LT5wfXscqyIuTUN6Q8hzwKEaYQKu2GKrvbEH7zpfwQ
+q4BbB1h8InY+m5xyeQ3chfjnwg8XqgHdjiQnd04jA9qI4N/myrSEVqHcn+CTlJfS
+mM0ybXOE+T5MlrNRB7ifZjLRrFMOF6lvKdF7c7NVm8yPi+VJ/f3yMNbQ9wMGEuNm
+LQ2h2igEBCm4QG4ObzFIy1T34oki2AXg9X5Is5b/a+/n/nEdC3c=
-----END CERTIFICATE-----
diff --git a/chromium/net/data/ssl/certificates/client_5.key b/chromium/net/data/ssl/certificates/client_5.key
new file mode 100644
index 00000000000..ab74e24d820
--- /dev/null
+++ b/chromium/net/data/ssl/certificates/client_5.key
@@ -0,0 +1,6 @@
+-----BEGIN EC PRIVATE KEY-----
+MIGkAgEBBDDIPJAB+fFVxe/nIqgAGt9Pff2OF9Ts6WOBW3RZbf5o3SZiuS1fhUh1
+ppZfdaRmjEygBwYFK4EEACKhZANiAARMBdRlPc2YnctgdjXBkdxS79SBGI4WBsRz
+jiYMjMkPGDVdN/kID0Gi5hkwXTZ6yhRmbqf7NdNsC5f2nH74BTfoqn//Aj0SroiI
+OalVGt2S2NW6ea690MvYnA/AM2B3L/Y=
+-----END EC PRIVATE KEY-----
diff --git a/chromium/net/data/ssl/certificates/client_5.pem b/chromium/net/data/ssl/certificates/client_5.pem
new file mode 100644
index 00000000000..e9840481241
--- /dev/null
+++ b/chromium/net/data/ssl/certificates/client_5.pem
@@ -0,0 +1,57 @@
+Certificate:
+ Data:
+ Version: 3 (0x2)
+ Serial Number: 4101 (0x1005)
+ Signature Algorithm: sha256WithRSAEncryption
+ Issuer: CN=E CA
+ Validity
+ Not Before: Dec 9 20:18:57 2016 GMT
+ Not After : Dec 7 20:18:57 2026 GMT
+ Subject: CN=Client Cert H
+ Subject Public Key Info:
+ Public Key Algorithm: id-ecPublicKey
+ Public-Key: (384 bit)
+ pub:
+ 04:4c:05:d4:65:3d:cd:98:9d:cb:60:76:35:c1:91:
+ dc:52:ef:d4:81:18:8e:16:06:c4:73:8e:26:0c:8c:
+ c9:0f:18:35:5d:37:f9:08:0f:41:a2:e6:19:30:5d:
+ 36:7a:ca:14:66:6e:a7:fb:35:d3:6c:0b:97:f6:9c:
+ 7e:f8:05:37:e8:aa:7f:ff:02:3d:12:ae:88:88:39:
+ a9:55:1a:dd:92:d8:d5:ba:79:ae:bd:d0:cb:d8:9c:
+ 0f:c0:33:60:77:2f:f6
+ ASN1 OID: secp384r1
+ X509v3 extensions:
+ X509v3 Basic Constraints: critical
+ CA:FALSE
+ X509v3 Extended Key Usage:
+ TLS Web Server Authentication, TLS Web Client Authentication
+ Signature Algorithm: sha256WithRSAEncryption
+ b2:37:fc:b9:0c:90:27:fc:e3:3e:a7:6f:c6:94:95:2c:61:37:
+ 46:25:64:55:ae:61:fe:00:58:0e:64:5f:9a:5b:bc:3a:b7:52:
+ e1:42:9a:8a:05:c2:b6:1d:cc:d7:47:a8:88:d5:78:1f:74:08:
+ db:52:e1:00:3c:aa:7c:80:73:b1:91:f9:75:6e:d3:53:28:ef:
+ af:5a:b7:1d:3e:38:a8:b8:1b:48:ed:20:18:a8:4a:de:60:97:
+ bb:3f:b6:b8:cc:d5:5b:bf:1c:97:06:d1:9a:25:b8:85:1c:36:
+ 26:02:e0:78:47:e0:f5:07:a4:0a:6a:55:14:39:51:d6:f3:f2:
+ b9:d4:44:9d:78:c4:45:e5:39:6f:71:0e:bd:2a:7b:71:9e:c4:
+ 12:f2:52:f0:ed:6a:78:47:48:df:ea:a0:44:eb:ce:f6:5c:50:
+ 53:47:3d:a6:db:ca:ad:a7:62:d8:6d:06:56:9f:e2:1b:72:08:
+ b3:4a:cb:2d:e9:4a:62:9e:c1:7e:5e:bd:ce:08:2f:82:bd:2f:
+ 6e:8b:55:e2:43:01:e6:30:40:b7:67:3c:0d:96:e1:9a:33:bd:
+ b8:c2:88:03:f5:87:68:4d:6d:49:7f:8e:94:f3:6a:41:2f:31:
+ 19:b6:0d:33:61:24:41:33:16:d4:5b:ad:98:8e:05:f7:9c:a1:
+ 13:dd:5f:7d
+-----BEGIN CERTIFICATE-----
+MIICJDCCAQygAwIBAgICEAUwDQYJKoZIhvcNAQELBQAwDzENMAsGA1UEAwwERSBD
+QTAeFw0xNjEyMDkyMDE4NTdaFw0yNjEyMDcyMDE4NTdaMBgxFjAUBgNVBAMMDUNs
+aWVudCBDZXJ0IEgwdjAQBgcqhkjOPQIBBgUrgQQAIgNiAARMBdRlPc2YnctgdjXB
+kdxS79SBGI4WBsRzjiYMjMkPGDVdN/kID0Gi5hkwXTZ6yhRmbqf7NdNsC5f2nH74
+BTfoqn//Aj0SroiIOalVGt2S2NW6ea690MvYnA/AM2B3L/ajLzAtMAwGA1UdEwEB
+/wQCMAAwHQYDVR0lBBYwFAYIKwYBBQUHAwEGCCsGAQUFBwMCMA0GCSqGSIb3DQEB
+CwUAA4IBAQCyN/y5DJAn/OM+p2/GlJUsYTdGJWRVrmH+AFgOZF+aW7w6t1LhQpqK
+BcK2HczXR6iI1XgfdAjbUuEAPKp8gHOxkfl1btNTKO+vWrcdPjiouBtI7SAYqEre
+YJe7P7a4zNVbvxyXBtGaJbiFHDYmAuB4R+D1B6QKalUUOVHW8/K51ESdeMRF5Tlv
+cQ69KntxnsQS8lLw7Wp4R0jf6qBE6872XFBTRz2m28qtp2LYbQZWn+IbcgizSsst
+6UpinsF+Xr3OCC+CvS9ui1XiQwHmMEC3ZzwNluGaM724wogD9YdoTW1Jf46U82pB
+LzEZtg0zYSRBMxbUW62YjgX3nKET3V99
+-----END CERTIFICATE-----
diff --git a/chromium/net/data/ssl/certificates/client_5.pk8 b/chromium/net/data/ssl/certificates/client_5.pk8
new file mode 100644
index 00000000000..26da499c141
--- /dev/null
+++ b/chromium/net/data/ssl/certificates/client_5.pk8
Binary files differ
diff --git a/chromium/net/data/ssl/certificates/client_5_ca.pem b/chromium/net/data/ssl/certificates/client_5_ca.pem
new file mode 100644
index 00000000000..78080961705
--- /dev/null
+++ b/chromium/net/data/ssl/certificates/client_5_ca.pem
@@ -0,0 +1,71 @@
+Certificate:
+ Data:
+ Version: 3 (0x2)
+ Serial Number: 4098 (0x1002)
+ Signature Algorithm: sha256WithRSAEncryption
+ Issuer: CN=C Root CA
+ Validity
+ Not Before: Dec 9 20:18:57 2016 GMT
+ Not After : Dec 7 20:18:57 2026 GMT
+ Subject: CN=E CA
+ Subject Public Key Info:
+ Public Key Algorithm: rsaEncryption
+ Public-Key: (2048 bit)
+ Modulus:
+ 00:c3:39:c3:5a:8e:ff:f2:1d:cc:26:91:5d:15:9e:
+ ca:e0:fb:cf:99:5f:13:3d:c6:37:59:8b:ce:cc:76:
+ 0e:1c:9f:b6:49:5b:09:97:63:9d:e1:00:74:44:fb:
+ 2f:53:f3:d5:03:92:77:97:53:74:7e:d2:da:d3:a3:
+ f4:c1:91:6a:83:ff:89:fe:73:46:56:ca:6d:51:0d:
+ 57:16:3d:3e:e8:fc:00:d9:4a:7a:7d:93:84:06:12:
+ c5:ff:31:b3:a6:eb:96:18:71:b8:56:5c:2f:ab:78:
+ e2:53:dd:15:d8:65:c8:f6:96:14:dc:15:cf:2a:39:
+ ed:e1:08:1b:84:29:c7:1c:78:67:c8:e0:72:58:4e:
+ 33:7f:cb:ef:71:82:db:45:1d:7c:0c:d0:f5:4c:af:
+ 85:6b:14:61:50:87:34:42:fe:45:a3:3c:a3:53:57:
+ 1d:ac:11:c8:cf:2f:5e:cb:78:87:39:a1:41:3f:69:
+ 21:5c:1e:19:02:a3:6c:91:d3:1b:4e:50:fc:a4:b1:
+ 03:87:c0:58:b1:fe:cd:58:5e:53:ed:c9:d6:5d:9e:
+ a3:fb:0d:e0:a0:8e:3d:c9:9e:9e:83:07:61:c7:30:
+ 5a:ca:29:93:04:af:5e:f3:57:2e:c2:d8:c8:ae:7f:
+ 5c:a4:27:fa:cd:55:a2:fd:89:d2:0b:87:24:6b:7b:
+ fb:19
+ Exponent: 65537 (0x10001)
+ X509v3 extensions:
+ X509v3 Basic Constraints: critical
+ CA:TRUE
+ X509v3 Key Usage: critical
+ Certificate Sign, CRL Sign
+ Signature Algorithm: sha256WithRSAEncryption
+ 67:d4:6c:cf:cd:54:81:67:2a:c2:c4:66:c7:76:9c:b0:8b:6b:
+ ef:b8:ae:a9:b3:d6:f8:47:91:d5:97:0b:bd:1a:87:21:8c:ce:
+ be:0c:80:d5:a5:25:0d:0a:c7:ed:be:cb:8c:6d:08:e8:de:a5:
+ 33:89:e6:87:df:2b:f4:54:b3:c2:94:15:0d:36:5e:1a:aa:c0:
+ b0:03:3c:24:c6:a1:81:91:ca:fe:db:0f:59:1b:d6:4e:48:0b:
+ 52:d3:e7:07:d7:b1:ca:b2:22:e4:d4:37:a4:3c:87:3c:0a:11:
+ a6:10:2a:ed:86:2a:bb:db:10:7e:f3:a5:fc:10:ab:80:5b:07:
+ 58:7c:22:76:3e:9b:9c:72:79:0d:dc:85:f8:e7:c2:0f:17:aa:
+ 01:dd:8e:24:27:77:4e:23:03:da:88:e0:df:e6:ca:b4:84:56:
+ a1:dc:9f:e0:93:94:97:d2:98:cd:32:6d:73:84:f9:3e:4c:96:
+ b3:51:07:b8:9f:66:32:d1:ac:53:0e:17:a9:6f:29:d1:7b:73:
+ b3:55:9b:cc:8f:8b:e5:49:fd:fd:f2:30:d6:d0:f7:03:06:12:
+ e3:66:2d:0d:a1:da:28:04:04:29:b8:40:6e:0e:6f:31:48:cb:
+ 54:f7:e2:89:22:d8:05:e0:f5:7e:48:b3:96:ff:6b:ef:e7:fe:
+ 71:1d:0b:77
+-----BEGIN CERTIFICATE-----
+MIICwjCCAaqgAwIBAgICEAIwDQYJKoZIhvcNAQELBQAwFDESMBAGA1UEAwwJQyBS
+b290IENBMB4XDTE2MTIwOTIwMTg1N1oXDTI2MTIwNzIwMTg1N1owDzENMAsGA1UE
+AwwERSBDQTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAMM5w1qO//Id
+zCaRXRWeyuD7z5lfEz3GN1mLzsx2DhyftklbCZdjneEAdET7L1Pz1QOSd5dTdH7S
+2tOj9MGRaoP/if5zRlbKbVENVxY9Puj8ANlKen2ThAYSxf8xs6brlhhxuFZcL6t4
+4lPdFdhlyPaWFNwVzyo57eEIG4Qpxxx4Z8jgclhOM3/L73GC20UdfAzQ9UyvhWsU
+YVCHNEL+RaM8o1NXHawRyM8vXst4hzmhQT9pIVweGQKjbJHTG05Q/KSxA4fAWLH+
+zVheU+3J1l2eo/sN4KCOPcmenoMHYccwWsopkwSvXvNXLsLYyK5/XKQn+s1Vov2J
+0guHJGt7+xkCAwEAAaMjMCEwDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMC
+AQYwDQYJKoZIhvcNAQELBQADggEBAGfUbM/NVIFnKsLEZsd2nLCLa++4rqmz1vhH
+kdWXC70ahyGMzr4MgNWlJQ0Kx+2+y4xtCOjepTOJ5offK/RUs8KUFQ02XhqqwLAD
+PCTGoYGRyv7bD1kb1k5IC1LT5wfXscqyIuTUN6Q8hzwKEaYQKu2GKrvbEH7zpfwQ
+q4BbB1h8InY+m5xyeQ3chfjnwg8XqgHdjiQnd04jA9qI4N/myrSEVqHcn+CTlJfS
+mM0ybXOE+T5MlrNRB7ifZjLRrFMOF6lvKdF7c7NVm8yPi+VJ/f3yMNbQ9wMGEuNm
+LQ2h2igEBCm4QG4ObzFIy1T34oki2AXg9X5Is5b/a+/n/nEdC3c=
+-----END CERTIFICATE-----
diff --git a/chromium/net/data/ssl/certificates/client_6.key b/chromium/net/data/ssl/certificates/client_6.key
new file mode 100644
index 00000000000..289c2d73a3a
--- /dev/null
+++ b/chromium/net/data/ssl/certificates/client_6.key
@@ -0,0 +1,7 @@
+-----BEGIN EC PRIVATE KEY-----
+MIHcAgEBBEIBp33i9oT0DV1aUcOE8av0Nt6ZCvsoVPPP/4kpU6T6d7wgLNwLK3uG
+vGCZX5AbdL1VvLA1rvfodqYug3pRnH0wSyigBwYFK4EEACOhgYkDgYYABACtf0oy
+HoxXTu/joG5I2fTeeYe6ZCEKlz2D5cMckF4bIkjRpue12TMhzs7FYp0cg+My3bxO
+A87t7os/vXJ3SZxGCwBFIQJc/vMSz7eOlaYHWXYY+vuD4Ab/j34lv1U+6LjtinWo
+I2WAbq/rxzSku9/NnLtKATbz3YgnYyzCEsmxQHfiKg==
+-----END EC PRIVATE KEY-----
diff --git a/chromium/net/data/ssl/certificates/client_6.pem b/chromium/net/data/ssl/certificates/client_6.pem
new file mode 100644
index 00000000000..f90a4ca81e5
--- /dev/null
+++ b/chromium/net/data/ssl/certificates/client_6.pem
@@ -0,0 +1,60 @@
+Certificate:
+ Data:
+ Version: 3 (0x2)
+ Serial Number: 4102 (0x1006)
+ Signature Algorithm: sha256WithRSAEncryption
+ Issuer: CN=E CA
+ Validity
+ Not Before: Dec 9 20:18:57 2016 GMT
+ Not After : Dec 7 20:18:57 2026 GMT
+ Subject: CN=Client Cert I
+ Subject Public Key Info:
+ Public Key Algorithm: id-ecPublicKey
+ Public-Key: (521 bit)
+ pub:
+ 04:00:ad:7f:4a:32:1e:8c:57:4e:ef:e3:a0:6e:48:
+ d9:f4:de:79:87:ba:64:21:0a:97:3d:83:e5:c3:1c:
+ 90:5e:1b:22:48:d1:a6:e7:b5:d9:33:21:ce:ce:c5:
+ 62:9d:1c:83:e3:32:dd:bc:4e:03:ce:ed:ee:8b:3f:
+ bd:72:77:49:9c:46:0b:00:45:21:02:5c:fe:f3:12:
+ cf:b7:8e:95:a6:07:59:76:18:fa:fb:83:e0:06:ff:
+ 8f:7e:25:bf:55:3e:e8:b8:ed:8a:75:a8:23:65:80:
+ 6e:af:eb:c7:34:a4:bb:df:cd:9c:bb:4a:01:36:f3:
+ dd:88:27:63:2c:c2:12:c9:b1:40:77:e2:2a
+ ASN1 OID: secp521r1
+ X509v3 extensions:
+ X509v3 Basic Constraints: critical
+ CA:FALSE
+ X509v3 Extended Key Usage:
+ TLS Web Server Authentication, TLS Web Client Authentication
+ Signature Algorithm: sha256WithRSAEncryption
+ 8d:7b:44:61:33:92:ef:73:17:b7:b1:95:d8:f3:87:02:36:1c:
+ f7:d1:00:0d:2b:59:88:80:31:93:0b:ef:e8:c0:19:c6:bb:89:
+ 26:3a:6e:47:90:0b:b2:99:d5:46:19:c4:cb:61:eb:51:6e:74:
+ f7:d0:87:4f:3b:08:fe:5a:48:a3:23:cc:b4:5d:a4:b6:0c:78:
+ f1:b2:f0:36:71:d7:c6:a7:e1:80:59:a6:67:b4:2a:ea:b5:1b:
+ 9f:a2:bb:4d:01:36:e3:58:ed:19:bd:e6:b4:8e:d7:3c:b7:cc:
+ 95:76:8b:e9:ec:78:c0:de:1b:09:04:d7:44:6c:2c:3c:c3:0e:
+ 39:dc:be:3b:eb:ec:7d:b5:b9:3e:e6:eb:c0:ef:15:af:ca:96:
+ 1d:f0:9e:ba:27:41:a2:7c:66:67:7d:37:65:0c:66:b7:aa:1b:
+ e8:88:55:f1:50:54:b9:36:e3:84:9c:27:a9:fa:8c:06:06:ce:
+ 02:63:85:a6:70:dd:fc:78:1f:26:1f:13:01:aa:8d:34:54:80:
+ 23:28:84:bf:90:a4:1a:61:e7:83:90:93:b7:0b:13:1d:c5:78:
+ 7b:74:eb:5d:18:f1:b2:dd:6c:23:10:bc:80:1c:14:38:e6:76:
+ d5:78:b9:3a:0a:57:38:bd:fe:45:b0:68:a3:8c:1e:ae:25:84:
+ 2f:dc:7a:b2
+-----BEGIN CERTIFICATE-----
+MIICSjCCATKgAwIBAgICEAYwDQYJKoZIhvcNAQELBQAwDzENMAsGA1UEAwwERSBD
+QTAeFw0xNjEyMDkyMDE4NTdaFw0yNjEyMDcyMDE4NTdaMBgxFjAUBgNVBAMMDUNs
+aWVudCBDZXJ0IEkwgZswEAYHKoZIzj0CAQYFK4EEACMDgYYABACtf0oyHoxXTu/j
+oG5I2fTeeYe6ZCEKlz2D5cMckF4bIkjRpue12TMhzs7FYp0cg+My3bxOA87t7os/
+vXJ3SZxGCwBFIQJc/vMSz7eOlaYHWXYY+vuD4Ab/j34lv1U+6LjtinWoI2WAbq/r
+xzSku9/NnLtKATbz3YgnYyzCEsmxQHfiKqMvMC0wDAYDVR0TAQH/BAIwADAdBgNV
+HSUEFjAUBggrBgEFBQcDAQYIKwYBBQUHAwIwDQYJKoZIhvcNAQELBQADggEBAI17
+RGEzku9zF7exldjzhwI2HPfRAA0rWYiAMZML7+jAGca7iSY6bkeQC7KZ1UYZxMth
+61FudPfQh087CP5aSKMjzLRdpLYMePGy8DZx18an4YBZpme0Kuq1G5+iu00BNuNY
+7Rm95rSO1zy3zJV2i+nseMDeGwkE10RsLDzDDjncvjvr7H21uT7m68DvFa/Klh3w
+nronQaJ8Zmd9N2UMZreqG+iIVfFQVLk244ScJ6n6jAYGzgJjhaZw3fx4HyYfEwGq
+jTRUgCMohL+QpBph54OQk7cLEx3FeHt0610Y8bLdbCMQvIAcFDjmdtV4uToKVzi9
+/kWwaKOMHq4lhC/cerI=
+-----END CERTIFICATE-----
diff --git a/chromium/net/data/ssl/certificates/client_6.pk8 b/chromium/net/data/ssl/certificates/client_6.pk8
new file mode 100644
index 00000000000..62c42f4396b
--- /dev/null
+++ b/chromium/net/data/ssl/certificates/client_6.pk8
Binary files differ
diff --git a/chromium/net/data/ssl/certificates/client_6_ca.pem b/chromium/net/data/ssl/certificates/client_6_ca.pem
new file mode 100644
index 00000000000..78080961705
--- /dev/null
+++ b/chromium/net/data/ssl/certificates/client_6_ca.pem
@@ -0,0 +1,71 @@
+Certificate:
+ Data:
+ Version: 3 (0x2)
+ Serial Number: 4098 (0x1002)
+ Signature Algorithm: sha256WithRSAEncryption
+ Issuer: CN=C Root CA
+ Validity
+ Not Before: Dec 9 20:18:57 2016 GMT
+ Not After : Dec 7 20:18:57 2026 GMT
+ Subject: CN=E CA
+ Subject Public Key Info:
+ Public Key Algorithm: rsaEncryption
+ Public-Key: (2048 bit)
+ Modulus:
+ 00:c3:39:c3:5a:8e:ff:f2:1d:cc:26:91:5d:15:9e:
+ ca:e0:fb:cf:99:5f:13:3d:c6:37:59:8b:ce:cc:76:
+ 0e:1c:9f:b6:49:5b:09:97:63:9d:e1:00:74:44:fb:
+ 2f:53:f3:d5:03:92:77:97:53:74:7e:d2:da:d3:a3:
+ f4:c1:91:6a:83:ff:89:fe:73:46:56:ca:6d:51:0d:
+ 57:16:3d:3e:e8:fc:00:d9:4a:7a:7d:93:84:06:12:
+ c5:ff:31:b3:a6:eb:96:18:71:b8:56:5c:2f:ab:78:
+ e2:53:dd:15:d8:65:c8:f6:96:14:dc:15:cf:2a:39:
+ ed:e1:08:1b:84:29:c7:1c:78:67:c8:e0:72:58:4e:
+ 33:7f:cb:ef:71:82:db:45:1d:7c:0c:d0:f5:4c:af:
+ 85:6b:14:61:50:87:34:42:fe:45:a3:3c:a3:53:57:
+ 1d:ac:11:c8:cf:2f:5e:cb:78:87:39:a1:41:3f:69:
+ 21:5c:1e:19:02:a3:6c:91:d3:1b:4e:50:fc:a4:b1:
+ 03:87:c0:58:b1:fe:cd:58:5e:53:ed:c9:d6:5d:9e:
+ a3:fb:0d:e0:a0:8e:3d:c9:9e:9e:83:07:61:c7:30:
+ 5a:ca:29:93:04:af:5e:f3:57:2e:c2:d8:c8:ae:7f:
+ 5c:a4:27:fa:cd:55:a2:fd:89:d2:0b:87:24:6b:7b:
+ fb:19
+ Exponent: 65537 (0x10001)
+ X509v3 extensions:
+ X509v3 Basic Constraints: critical
+ CA:TRUE
+ X509v3 Key Usage: critical
+ Certificate Sign, CRL Sign
+ Signature Algorithm: sha256WithRSAEncryption
+ 67:d4:6c:cf:cd:54:81:67:2a:c2:c4:66:c7:76:9c:b0:8b:6b:
+ ef:b8:ae:a9:b3:d6:f8:47:91:d5:97:0b:bd:1a:87:21:8c:ce:
+ be:0c:80:d5:a5:25:0d:0a:c7:ed:be:cb:8c:6d:08:e8:de:a5:
+ 33:89:e6:87:df:2b:f4:54:b3:c2:94:15:0d:36:5e:1a:aa:c0:
+ b0:03:3c:24:c6:a1:81:91:ca:fe:db:0f:59:1b:d6:4e:48:0b:
+ 52:d3:e7:07:d7:b1:ca:b2:22:e4:d4:37:a4:3c:87:3c:0a:11:
+ a6:10:2a:ed:86:2a:bb:db:10:7e:f3:a5:fc:10:ab:80:5b:07:
+ 58:7c:22:76:3e:9b:9c:72:79:0d:dc:85:f8:e7:c2:0f:17:aa:
+ 01:dd:8e:24:27:77:4e:23:03:da:88:e0:df:e6:ca:b4:84:56:
+ a1:dc:9f:e0:93:94:97:d2:98:cd:32:6d:73:84:f9:3e:4c:96:
+ b3:51:07:b8:9f:66:32:d1:ac:53:0e:17:a9:6f:29:d1:7b:73:
+ b3:55:9b:cc:8f:8b:e5:49:fd:fd:f2:30:d6:d0:f7:03:06:12:
+ e3:66:2d:0d:a1:da:28:04:04:29:b8:40:6e:0e:6f:31:48:cb:
+ 54:f7:e2:89:22:d8:05:e0:f5:7e:48:b3:96:ff:6b:ef:e7:fe:
+ 71:1d:0b:77
+-----BEGIN CERTIFICATE-----
+MIICwjCCAaqgAwIBAgICEAIwDQYJKoZIhvcNAQELBQAwFDESMBAGA1UEAwwJQyBS
+b290IENBMB4XDTE2MTIwOTIwMTg1N1oXDTI2MTIwNzIwMTg1N1owDzENMAsGA1UE
+AwwERSBDQTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAMM5w1qO//Id
+zCaRXRWeyuD7z5lfEz3GN1mLzsx2DhyftklbCZdjneEAdET7L1Pz1QOSd5dTdH7S
+2tOj9MGRaoP/if5zRlbKbVENVxY9Puj8ANlKen2ThAYSxf8xs6brlhhxuFZcL6t4
+4lPdFdhlyPaWFNwVzyo57eEIG4Qpxxx4Z8jgclhOM3/L73GC20UdfAzQ9UyvhWsU
+YVCHNEL+RaM8o1NXHawRyM8vXst4hzmhQT9pIVweGQKjbJHTG05Q/KSxA4fAWLH+
+zVheU+3J1l2eo/sN4KCOPcmenoMHYccwWsopkwSvXvNXLsLYyK5/XKQn+s1Vov2J
+0guHJGt7+xkCAwEAAaMjMCEwDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMC
+AQYwDQYJKoZIhvcNAQELBQADggEBAGfUbM/NVIFnKsLEZsd2nLCLa++4rqmz1vhH
+kdWXC70ahyGMzr4MgNWlJQ0Kx+2+y4xtCOjepTOJ5offK/RUs8KUFQ02XhqqwLAD
+PCTGoYGRyv7bD1kb1k5IC1LT5wfXscqyIuTUN6Q8hzwKEaYQKu2GKrvbEH7zpfwQ
+q4BbB1h8InY+m5xyeQ3chfjnwg8XqgHdjiQnd04jA9qI4N/myrSEVqHcn+CTlJfS
+mM0ybXOE+T5MlrNRB7ifZjLRrFMOF6lvKdF7c7NVm8yPi+VJ/f3yMNbQ9wMGEuNm
+LQ2h2igEBCm4QG4ObzFIy1T34oki2AXg9X5Is5b/a+/n/nEdC3c=
+-----END CERTIFICATE-----
diff --git a/chromium/net/data/ssl/certificates/client_root_ca.pem b/chromium/net/data/ssl/certificates/client_root_ca.pem
index b40481033aa..cb41907eb13 100644
--- a/chromium/net/data/ssl/certificates/client_root_ca.pem
+++ b/chromium/net/data/ssl/certificates/client_root_ca.pem
@@ -1,18 +1,18 @@
-----BEGIN CERTIFICATE-----
-MIICzjCCAbagAwIBAgIJAO+K/Ai3YiytMA0GCSqGSIb3DQEBCwUAMBQxEjAQBgNV
-BAMMCUMgUm9vdCBDQTAeFw0xNjEwMDQxODUzMjRaFw0yNjEwMDIxODUzMjRaMBQx
+MIICzjCCAbagAwIBAgIJAOlWtiy6ZPwFMA0GCSqGSIb3DQEBCwUAMBQxEjAQBgNV
+BAMMCUMgUm9vdCBDQTAeFw0xNjEyMDkyMDE4NTdaFw0yNjEyMDcyMDE4NTdaMBQx
EjAQBgNVBAMMCUMgUm9vdCBDQTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoC
-ggEBALKU+gX11E3vQ6CHy5bNfePr5uiJMHX+P97/I8y8DCk117+0gGxlO4adwImE
-dgA6jFmMcphJU+BPfi1eDwO2WHQVa31NALMy3CbEzv4qV1gqTAfNJdICKZk7S87E
-GbZUBauHe8q443UwD3c+R49XTsGvUSoMjh3N7K0/kNeoLi4RLW6WOZvJh954Rj+I
-EHmCibJENDfzdYWfQtLZJEYrzJv01ZdWcigvOR7qQqLdX6f2WTBaWpjgSnP5QzO/
-8gkX+rVRRUpbD/lMNdXqO9AoBcSG07tWMx1MDRnDG8SzrCQ4sScSbcPnHQDEbdDv
-suCnGXzSerruQXCqVwcCHIEHRSMCAwEAAaMjMCEwDwYDVR0TAQH/BAUwAwEB/zAO
-BgNVHQ8BAf8EBAMCAQYwDQYJKoZIhvcNAQELBQADggEBAHL9wuInYSfItXwoO2jG
-W08CPjcPMN1Q7yulKFtND6jU4cWB/m2xQmpMjhrahrF1hYwwiOXfwB+bxHOoekmK
-Uf+WmsiFXUQ5q9IeBMnxrrKOqZ9X2S+WaTi9GosJ52IEX4JJT7w3JDEcNTh3h66g
-FHB9cXao0EDx5fkEvSCKhcSy+tWjWzUB+GszG3ApCe0ZxbcehUSRSZTcLYvlNlXF
-NMNvEH5C1BVzCQWAZlgT4gp4miEPCFTc4Vr90pgDzJ3eFWu4V0s6snyDOip0PD9A
-N6wOvSix25wUYni46xGHFc9ZZn3x35HdhW9+IMAgJI14hMsoIHQwAgzqF4neRYvY
-RT4=
+ggEBAMA+ZigXbDXCxJ4JCLXzWo/3dzVU/lQgToMmzXMAN7YLkYrpMHSh0+YgrtOv
+XA70wFaLPa6SYGqr9OU2FqTlob43GQU9uNmIOi/SNmz3WRudoJgqbYK0Gv4qRarR
+wrNqpPWgQXxP3T/slF7UVV0JRFWcscXPIxVIOQ64qGTtMpzjYP21g0V8e6pz30U9
+/9iil7FdSVIpjKc2RN42QGi2URIe2hYOIgCMADO/m5eUMVVX3wJ+ka4X619uTFrg
+BEexVhIMu5ZPwEXcyUBxebLzJqx+JTwe2P2/20UMGQBSqT9xsXcuW8Y3+5q7Vl0j
+7F5u9pE2PAZiVuDLWE3TXFSwVd8CAwEAAaMjMCEwDwYDVR0TAQH/BAUwAwEB/zAO
+BgNVHQ8BAf8EBAMCAQYwDQYJKoZIhvcNAQELBQADggEBAJE45oY5GAmSefzxBKI2
+mVfZj7TlUG/KQ1W7RrsoDeYb93PTA/S4XM56wQhT8vdz3imED83EZ1hoDFourhAV
+hNVCSSHBJ/Bgtj3Yt6bUZdx0dSK5PbnvfTYAnRxzx0o8d4pRXb0G225BT3kYNIOK
+E1M24xmnjP3OoeyqWzP7uyU7vxfA4oCloNgeMWMJ9zdfgRX8Qnj6XRHVuhMXdofn
+7vB9dpsbJI5ozXaFYuXMKZ8g97M1vUzWTQsbUWc/L3YaO+UZOQXg1gLHhZmwn9MC
+xZSldz7Z4QIDV+U03cJUKL5O4hQcMgrtug2d75vxMKVjETKkvqbzs56h62YmhEyw
+3Gg=
-----END CERTIFICATE-----
diff --git a/chromium/net/data/ssl/certificates/crlset_by_intermediate_serial.raw b/chromium/net/data/ssl/certificates/crlset_by_intermediate_serial.raw
index 04134b52b5a..5cde6fbe741 100644
--- a/chromium/net/data/ssl/certificates/crlset_by_intermediate_serial.raw
+++ b/chromium/net/data/ssl/certificates/crlset_by_intermediate_serial.raw
Binary files differ
diff --git a/chromium/net/data/ssl/certificates/intermediate_ca_cert.pem b/chromium/net/data/ssl/certificates/intermediate_ca_cert.pem
new file mode 100644
index 00000000000..952a230a49d
--- /dev/null
+++ b/chromium/net/data/ssl/certificates/intermediate_ca_cert.pem
@@ -0,0 +1,104 @@
+-----BEGIN PRIVATE KEY-----
+MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQCnUEvP8sppMxqR
+73F9aDqvHusU7mSoK0HG7CtS6WasXU/9LrAxOWwugR6DXVmV0iqZ+/E4Lvk2UlN8
+6rrf+9aY9Mk50TRGZ4NBibzLlPkmPbC2aPeTa9RAJ1JhDyAekVg9YN1KHP5UPwxK
+xFjXEf+oPPHNOfZIm6Ug28yQK/sfYutGTdPvA/j24IIFrypPAO3aYwRwQeYKk+lN
+hdT3K4bzNeFptYH82k/LQpTJ13a6m1ef++/tJu8tU3MvkjFLOHuGZusNLvKTj8W7
+/swTUOkYHRhkmZHa3pYrCHIhI0JnmYaY/m/1jg5hsQp+9bjVpwagU+9/BNsRxAcK
+R5bwk4LVAgMBAAECggEAfI59cfjIkRqXXC9KaNbwYTB+R93Vl5BkboehFR9m7Uim
+ZNCeIHckP1amdZtINw334xy5jl8B7lvJhYRlzJt6PfJ135IL/aHQCDlXEKP9+2cP
+qCxqqxgqMfxUCqes/LStYTw8YZFGEUfCieK0VKA0mHWOeX7+Bz2/579aAbaMQ+c2
+rlLIK9PelGPgRMSNHdNzusBG4qr4OBYeeAJ16gHBg4xVZPdp9ApM0UKN410M+gjx
+509D/HiBhiswMOJBPpxypfbnjMaTUklt0KLGSCkwocrf9K+TnrwfQ1ZWfq2Hmlu3
+B99i6rtsOEMREq8kvV4yqTV0qBFXOmMZbmNFUiBwoQKBgQDal+ILQEywfpAEHAIw
+p/F8WipX1K6XhsSumBRXg12yzE/oik7TOr6a5xML38d3Iml4S5IAhwFSVWZe/spU
+fu2ZUhQOISWOZ+pIw/OJx1KIo1iiHDMOQZ7HC+QVk8zoXkZDRPdxP8UDEORGA7UV
+TqmsNBnSbddCfbX7GAPs28AJvQKBgQDD8fWFxLotZh7RyhAdPdfCJcGhW7bDCAYU
+Vg6T4ZXS6COFUIYlA794BwjtDisCNQUkLOcCI0J/diSXVJ8HbRCWTvMh6ZCM6No0
+gEgMABeUYaDvc2ca+bJ/9jN9YLXyZYfU3RAwX4V/rTcbwJTB/+tnHQLbcb7WyLEg
+gyoDTlHS+QKBgDtv6QreJPworcgwRXgtckA51CGltwOEpZ5Dw+Q32BZx75hvYxeU
+dZdxFYC5DGecd8k54y05iGZ2yisyZJmtGbYC12kwIiIip1W50lK4W/zDTapmuIs7
+1IyS8yXa1nCokbpg2ld024EF6swO3gI5LXGhiRPqwglWXVE1KnwRFJqRAoGAbiMB
+c1gZoc0Fw7vFBPqu3MTmKnFnsAZBjIq2lO62jR7IYHXbgNCzfZ7OqJhPGmV851GJ
+40y4YvagKKN64+ys5x+nT8d95YY4qEv2szAWEOQzVoRSTvpNF9nmJTIH8yCYkdBT
++iym2BYfpKzBsK3Nvl6zLW+o6gdScEjpg4QxP9kCgYEAt0k4F/1bbnWOA9NFoIEA
+n8d9w4hyFpn4tYNcB/9PvXURDuPurOPEutydd/hFzgdewVu61dsb16rFNoAZOwPp
++BacwdewsPjrpA5Rr2sH7KsDwjOi+2TUACmt8ZZnAxCr96EeQje/ggUW2ukL7wza
+bm82NyldWSM4JidPhoDyWjA=
+-----END PRIVATE KEY-----
+Certificate:
+ Data:
+ Version: 3 (0x2)
+ Serial Number: 1 (0x1)
+ Signature Algorithm: sha256WithRSAEncryption
+ Issuer: CN=Test Root CA
+ Validity
+ Not Before: Dec 9 22:40:07 2016 GMT
+ Not After : Dec 7 22:40:07 2026 GMT
+ Subject: C=US, ST=California, L=Mountain View, O=Test CA, CN=Test Intermediate CA
+ Subject Public Key Info:
+ Public Key Algorithm: rsaEncryption
+ Public-Key: (2048 bit)
+ Modulus:
+ 00:a7:50:4b:cf:f2:ca:69:33:1a:91:ef:71:7d:68:
+ 3a:af:1e:eb:14:ee:64:a8:2b:41:c6:ec:2b:52:e9:
+ 66:ac:5d:4f:fd:2e:b0:31:39:6c:2e:81:1e:83:5d:
+ 59:95:d2:2a:99:fb:f1:38:2e:f9:36:52:53:7c:ea:
+ ba:df:fb:d6:98:f4:c9:39:d1:34:46:67:83:41:89:
+ bc:cb:94:f9:26:3d:b0:b6:68:f7:93:6b:d4:40:27:
+ 52:61:0f:20:1e:91:58:3d:60:dd:4a:1c:fe:54:3f:
+ 0c:4a:c4:58:d7:11:ff:a8:3c:f1:cd:39:f6:48:9b:
+ a5:20:db:cc:90:2b:fb:1f:62:eb:46:4d:d3:ef:03:
+ f8:f6:e0:82:05:af:2a:4f:00:ed:da:63:04:70:41:
+ e6:0a:93:e9:4d:85:d4:f7:2b:86:f3:35:e1:69:b5:
+ 81:fc:da:4f:cb:42:94:c9:d7:76:ba:9b:57:9f:fb:
+ ef:ed:26:ef:2d:53:73:2f:92:31:4b:38:7b:86:66:
+ eb:0d:2e:f2:93:8f:c5:bb:fe:cc:13:50:e9:18:1d:
+ 18:64:99:91:da:de:96:2b:08:72:21:23:42:67:99:
+ 86:98:fe:6f:f5:8e:0e:61:b1:0a:7e:f5:b8:d5:a7:
+ 06:a0:53:ef:7f:04:db:11:c4:07:0a:47:96:f0:93:
+ 82:d5
+ Exponent: 65537 (0x10001)
+ X509v3 extensions:
+ X509v3 Basic Constraints: critical
+ CA:TRUE
+ X509v3 Subject Key Identifier:
+ F9:98:21:49:71:FA:8D:B9:20:F7:FE:5D:4D:41:E8:8B:6C:E0:62:C3
+ X509v3 Key Usage: critical
+ Certificate Sign, CRL Sign
+ Signature Algorithm: sha256WithRSAEncryption
+ 50:c7:37:47:87:1a:8a:b2:cc:37:d0:f6:4a:46:ee:b5:85:90:
+ 35:a5:a0:c8:c7:c7:38:7d:5d:bb:e0:fc:0f:15:d3:75:50:e5:
+ 06:08:b5:ec:d7:e8:65:63:03:5a:38:3e:2c:5a:eb:28:a0:3c:
+ 70:3f:d4:30:25:20:dd:22:63:08:f0:9b:a9:c8:34:8f:f6:7c:
+ 5a:ce:10:72:5c:37:a0:01:a6:5e:1b:a4:60:e7:93:f6:42:61:
+ 2c:d1:57:67:16:d9:19:21:52:03:8c:9a:aa:75:10:ca:a1:bc:
+ 53:07:f1:6f:52:54:88:50:7d:11:ef:96:82:0d:e9:7d:c1:42:
+ 42:42:13:1f:48:ef:49:70:df:e1:30:f9:6f:2f:3d:cd:51:1c:
+ 14:9c:bd:12:0c:f2:d7:16:32:4a:d5:6b:4b:21:01:6c:4a:b1:
+ ee:7b:8c:d0:99:7e:5e:1e:ef:10:24:6e:e3:6f:e2:e0:4b:0b:
+ 42:79:78:ab:2b:af:54:82:c4:b1:57:a3:f0:6f:16:42:ed:61:
+ fc:69:5e:2b:09:14:4a:61:cc:6a:19:52:66:89:06:48:f1:b5:
+ 76:39:68:21:dc:68:9d:11:07:37:80:ae:37:77:b4:69:69:29:
+ ff:f6:fc:f1:50:bc:ee:9a:f9:ab:c8:bf:a6:65:51:cc:89:1e:
+ 2f:2c:95:e9
+-----BEGIN CERTIFICATE-----
+MIIDPzCCAiegAwIBAgIBATANBgkqhkiG9w0BAQsFADAXMRUwEwYDVQQDDAxUZXN0
+IFJvb3QgQ0EwHhcNMTYxMjA5MjI0MDA3WhcNMjYxMjA3MjI0MDA3WjBrMQswCQYD
+VQQGEwJVUzETMBEGA1UECAwKQ2FsaWZvcm5pYTEWMBQGA1UEBwwNTW91bnRhaW4g
+VmlldzEQMA4GA1UECgwHVGVzdCBDQTEdMBsGA1UEAwwUVGVzdCBJbnRlcm1lZGlh
+dGUgQ0EwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCnUEvP8sppMxqR
+73F9aDqvHusU7mSoK0HG7CtS6WasXU/9LrAxOWwugR6DXVmV0iqZ+/E4Lvk2UlN8
+6rrf+9aY9Mk50TRGZ4NBibzLlPkmPbC2aPeTa9RAJ1JhDyAekVg9YN1KHP5UPwxK
+xFjXEf+oPPHNOfZIm6Ug28yQK/sfYutGTdPvA/j24IIFrypPAO3aYwRwQeYKk+lN
+hdT3K4bzNeFptYH82k/LQpTJ13a6m1ef++/tJu8tU3MvkjFLOHuGZusNLvKTj8W7
+/swTUOkYHRhkmZHa3pYrCHIhI0JnmYaY/m/1jg5hsQp+9bjVpwagU+9/BNsRxAcK
+R5bwk4LVAgMBAAGjQjBAMA8GA1UdEwEB/wQFMAMBAf8wHQYDVR0OBBYEFPmYIUlx
++o25IPf+XU1B6Its4GLDMA4GA1UdDwEB/wQEAwIBBjANBgkqhkiG9w0BAQsFAAOC
+AQEAUMc3R4cairLMN9D2SkbutYWQNaWgyMfHOH1du+D8DxXTdVDlBgi17NfoZWMD
+Wjg+LFrrKKA8cD/UMCUg3SJjCPCbqcg0j/Z8Ws4Qclw3oAGmXhukYOeT9kJhLNFX
+ZxbZGSFSA4yaqnUQyqG8Uwfxb1JUiFB9Ee+Wgg3pfcFCQkITH0jvSXDf4TD5by89
+zVEcFJy9Egzy1xYyStVrSyEBbEqx7nuM0Jl+Xh7vECRu42/i4EsLQnl4qyuvVILE
+sVej8G8WQu1h/GleKwkUSmHMahlSZokGSPG1djloIdxonREHN4CuN3e0aWkp//b8
+8VC87pr5q8i/pmVRzIkeLyyV6Q==
+-----END CERTIFICATE-----
diff --git a/chromium/net/data/ssl/certificates/ocsp-test-root.pem b/chromium/net/data/ssl/certificates/ocsp-test-root.pem
index cad67cb3114..ba84f41e083 100644
--- a/chromium/net/data/ssl/certificates/ocsp-test-root.pem
+++ b/chromium/net/data/ssl/certificates/ocsp-test-root.pem
@@ -10,42 +10,64 @@ Certificate:
Subject: CN=Testing CA
Subject Public Key Info:
Public Key Algorithm: rsaEncryption
- Public-Key: (1024 bit)
+ Public-Key: (2048 bit)
Modulus:
- 00:a7:19:98:f2:93:0b:fe:73:d0:31:a8:7f:13:3d:
- 2f:37:8e:ee:ee:d5:2a:77:e4:4d:0f:c9:ff:6f:07:
- ff:32:cb:f3:da:99:9d:e4:ed:65:83:2a:fc:b0:80:
- 7f:98:78:75:06:53:9d:25:8a:0c:e3:c2:c7:79:67:
- 65:30:99:a9:03:4a:9b:11:5a:87:6c:39:a8:c4:e4:
- ed:4a:cd:0c:64:09:59:46:fb:39:ee:eb:47:a0:70:
- 4d:bb:01:8a:cf:48:c3:a1:c4:b8:95:fc:40:9f:b4:
- a3:40:a9:86:b1:af:c4:55:19:ab:9e:ca:47:c3:01:
- 85:c7:71:c6:4a:a5:ec:f0:7d
- Exponent: 3 (0x3)
+ 00:c1:54:1f:ac:63:d3:b9:69:aa:23:1a:02:cb:2e:
+ 0d:9e:e7:b2:67:24:f1:36:c1:21:b2:c2:8b:da:e5:
+ ca:a8:77:33:cc:40:7a:d8:38:42:ef:20:ec:67:d9:
+ 41:b4:48:a1:ce:35:57:cf:5d:de:bf:3c:9b:de:8f:
+ 36:f2:53:ee:73:e6:70:d1:c4:c6:63:1d:1d:dc:0e:
+ 39:cb:de:09:b8:33:f6:63:47:ea:37:9c:3f:a8:91:
+ d6:1a:0c:a0:05:b3:8b:0b:2c:ad:10:58:e3:58:9c:
+ 9f:30:60:0b:e8:1e:4f:f4:ac:22:09:72:c1:7b:74:
+ f9:2f:03:d7:2b:49:6f:64:35:43:d0:b2:7a:52:27:
+ f1:ef:ee:13:c1:38:88:8b:23:cb:10:18:77:b3:b4:
+ dc:09:1f:0b:3b:b6:fc:3c:79:21:87:b0:5a:b3:8e:
+ 97:86:2f:8a:f6:15:6b:cb:fb:b8:24:38:51:32:c6:
+ 74:1e:6c:65:cf:cd:5f:13:14:24:21:a2:10:b9:51:
+ 85:88:4c:48:66:f3:ea:64:4d:fb:80:06:13:3d:14:
+ e7:2a:47:04:f3:e7:00:cf:82:7c:a5:ff:d2:ef:74:
+ c2:ab:6a:52:59:ff:ff:40:f0:f7:f6:07:89:13:88:
+ f9:17:fc:9f:c9:e6:57:42:df:1b:fa:0b:32:21:40:
+ bb:65
+ Exponent: 65537 (0x10001)
X509v3 extensions:
X509v3 Basic Constraints: critical
- CA:TRUE, pathlen:0
+ CA:TRUE, pathlen:1
X509v3 Certificate Policies:
Policy: 1.3.6.1.4.1.11129.2.4.1
Signature Algorithm: sha256WithRSAEncryption
- 72:49:8a:05:e0:02:b1:ff:13:d9:f7:02:29:60:8a:f0:39:f2:
- 16:b0:49:15:6a:89:31:c7:bf:ba:00:82:e0:d1:ac:0e:33:0b:
- c2:2f:b0:be:9b:ff:a2:d5:ee:70:37:29:63:34:39:44:99:48:
- 61:37:cd:06:fd:52:50:76:9c:d6:2c:3c:c7:6f:d0:bb:38:1a:
- e3:b3:55:fc:b8:6e:74:17:a8:c5:88:7e:54:70:f4:be:59:e4:
- a1:fc:56:ee:54:de:88:68:39:40:9f:58:dd:6c:60:ca:1e:4b:
- df:f6:d8:af:71:b5:1b:03:3d:2f:9d:a5:0a:3b:43:a6:68:3a:
- 8f:28
+ 33:6b:be:80:32:a8:05:66:6f:27:4f:04:17:cb:46:ac:87:e0:
+ 35:ed:da:fb:8c:56:69:d2:76:75:a7:3b:16:22:11:ec:c6:98:
+ d4:8d:88:ed:64:d5:91:41:c1:54:ac:77:e2:47:ad:3d:b8:95:
+ ac:7d:92:f5:35:c9:00:d6:ff:f3:c1:bb:78:a3:7d:93:82:68:
+ 85:25:79:08:86:5c:73:06:7d:5e:0c:8f:38:18:6f:1a:6f:1c:
+ eb:c4:50:2e:88:5e:66:02:b0:81:30:71:98:0a:96:bc:27:7c:
+ 94:37:31:55:38:84:e8:06:4e:53:93:59:83:ed:0b:0b:d3:b0:
+ 13:9b:35:12:dd:22:cf:a2:7c:c4:22:5a:6c:cf:06:53:3c:5d:
+ e5:f8:7b:96:9c:0e:34:db:7a:67:0d:e2:cc:d4:dc:47:20:98:
+ 20:34:2e:f0:48:44:8e:05:e8:d5:a9:68:82:65:d9:69:cb:c8:
+ c5:03:c8:aa:b8:be:3a:51:24:e6:64:37:00:02:fb:9d:b9:76:
+ e0:eb:24:51:38:3c:a4:76:2e:1e:77:9c:94:08:26:fe:a6:71:
+ 36:50:91:7d:66:9b:0d:32:ce:a5:b1:70:60:a8:1c:00:a6:6b:
+ 74:e0:4b:03:87:af:2b:d2:a2:92:fe:b7:6e:be:66:54:2f:3f:
+ 6c:a0:c2:a6
-----BEGIN CERTIFICATE-----
-MIIBzTCCATagAwIBAgIBATANBgkqhkiG9w0BAQsFADAVMRMwEQYDVQQDEwpUZXN0
+MIIC1DCCAbygAwIBAgIBATANBgkqhkiG9w0BAQsFADAVMRMwEQYDVQQDEwpUZXN0
aW5nIENBMB4XDTEwMDEwMTA2MDAwMFoXDTMyMTIwMTA2MDAwMFowFTETMBEGA1UE
-AxMKVGVzdGluZyBDQTCBnTANBgkqhkiG9w0BAQEFAAOBiwAwgYcCgYEApxmY8pML
-/nPQMah/Ez0vN47u7tUqd+RND8n/bwf/Msvz2pmd5O1lgyr8sIB/mHh1BlOdJYoM
-48LHeWdlMJmpA0qbEVqHbDmoxOTtSs0MZAlZRvs57utHoHBNuwGKz0jDocS4lfxA
-n7SjQKmGsa/EVRmrnspHwwGFx3HGSqXs8H0CAQOjLzAtMBIGA1UdEwEB/wQIMAYB
-Af8CAQAwFwYDVR0gBBAwDjAMBgorBgEEAdZ5AgQBMA0GCSqGSIb3DQEBCwUAA4GB
-AHJJigXgArH/E9n3AilgivA58hawSRVqiTHHv7oAguDRrA4zC8IvsL6b/6LV7nA3
-KWM0OUSZSGE3zQb9UlB2nNYsPMdv0Ls4GuOzVfy4bnQXqMWIflRw9L5Z5KH8Vu5U
-3ohoOUCfWN1sYMoeS9/22K9xtRsDPS+dpQo7Q6ZoOo8o
+AxMKVGVzdGluZyBDQTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAMFU
+H6xj07lpqiMaAssuDZ7nsmck8TbBIbLCi9rlyqh3M8xAetg4Qu8g7GfZQbRIoc41
+V89d3r88m96PNvJT7nPmcNHExmMdHdwOOcveCbgz9mNH6jecP6iR1hoMoAWziwss
+rRBY41icnzBgC+geT/SsIglywXt0+S8D1ytJb2Q1Q9CyelIn8e/uE8E4iIsjyxAY
+d7O03AkfCzu2/Dx5IYewWrOOl4YvivYVa8v7uCQ4UTLGdB5sZc/NXxMUJCGiELlR
+hYhMSGbz6mRN+4AGEz0U5ypHBPPnAM+CfKX/0u90wqtqUln//0Dw9/YHiROI+Rf8
+n8nmV0LfG/oLMiFAu2UCAwEAAaMvMC0wEgYDVR0TAQH/BAgwBgEB/wIBATAXBgNV
+HSAEEDAOMAwGCisGAQQB1nkCBAEwDQYJKoZIhvcNAQELBQADggEBADNrvoAyqAVm
+bydPBBfLRqyH4DXt2vuMVmnSdnWnOxYiEezGmNSNiO1k1ZFBwVSsd+JHrT24lax9
+kvU1yQDW//PBu3ijfZOCaIUleQiGXHMGfV4MjzgYbxpvHOvEUC6IXmYCsIEwcZgK
+lrwnfJQ3MVU4hOgGTlOTWYPtCwvTsBObNRLdIs+ifMQiWmzPBlM8XeX4e5acDjTb
+emcN4szU3EcgmCA0LvBIRI4F6NWpaIJl2WnLyMUDyKq4vjpRJOZkNwAC+525duDr
+JFE4PKR2Lh53nJQIJv6mcTZQkX1mmw0yzqWxcGCoHACma3TgSwOHryvSopL+t26+
+ZlQvP2ygwqY=
-----END CERTIFICATE-----
diff --git a/chromium/net/data/ssl/certificates/ok_cert_by_intermediate.pem b/chromium/net/data/ssl/certificates/ok_cert_by_intermediate.pem
new file mode 100644
index 00000000000..73d2742e753
--- /dev/null
+++ b/chromium/net/data/ssl/certificates/ok_cert_by_intermediate.pem
@@ -0,0 +1,112 @@
+-----BEGIN PRIVATE KEY-----
+MIIEvAIBADANBgkqhkiG9w0BAQEFAASCBKYwggSiAgEAAoIBAQC/o1248m3ahtTW
+3Qyg28CaxDu3lQaaEdfPjdAc75ncit2HvdkOuRFpr5RXEa+LhhYIWcj+/oa6Jgn+
+8FG6FENkyGWFH8tEOfaTV5g08r8GdzYCatmZBPTiXX/b7fIUXUhysls0st/qVqvT
+iPZYRM9AM/7JtbjD4nNZDabmyVuRkkLB8lgxEuBXX5R8di3SrOfCYqKI6IPPiJ7t
+umcJYbgfWqXhdMqHGDtd0O/CRfUmJRjKmsX3YZuw+xwECgNZ14fGUWU7bnR2UOfC
+UgBaRVmOL2kdg6545QNmFT97QpPwxRqtluTnCTEOTZe1nptjeNMOyifSZCeSwt5r
+Llzwf3jZAgMBAAECggEAKxcAq+VW7hwDH4z0mfbPh/03sD/CDEKW1AR/FwKJBh3z
+UeJOPBFA6RKhuDIx1p1/tsD5gNyaTqDe/oPq3HxR6wdkTFqpyd1+pAK+JqmuajXD
+3ydHZjDHH18GsNz/4bRX5fJUr7TIxFhYqmfRfGd8cmM+lvxVXzY72XpIXPxJqqFk
+40AticFiOdMqVp/6gBBBx8TovTDnJCnvMFanNXh8qsfxwWQNS92U/OJ+uaLj1mLd
+r2pkMh5VIEzfxgWTTNsRLMOksnmLNLNQZ58UJMNfhJpjBCZ0yMw5EArolQLOyl77
+yHlAmSvZWBw216zij6TfcsBmZgdrNsF6GJ92ThwAAQKBgQDgtf8/LUoOv0OGPP8J
+Sa+1Ch+l3Lkezdx0p07hES3wNPcnh8yqLXAVt4CllaJKBJTDP5gqCZXTiLFMVwZY
+P0/NznTom/84CiEsm4EpdAUndPxM8Np+MZezch2aMlODDZEzfGOJs8Wd/a2UC9kW
+VgPIB3hBAZU+k7OSaeMu2BYq2QKBgQDaUnaO+YTJ5QKwZ94+8MI9JIyjIiZss4wk
+Qm1WgYToYUZeOQjg+iDELqlQFCahhPTiba8oovsv3BfHAkE2mMB22BccV8BwtZfg
+fG+goXbhEumYubMKNg0ST5/wVczPncBxfHCgpdg9G15vKmbV/7VEbwBM/idHiLTy
+DIYgPVb+AQKBgA4QlidYKFh/9DQEwVnNeOf1+EEjbZrV+8R5bGB9+MgeKJIa196W
+9XsGf1Dd6siDPORzqIyJCQ2ycpZ6o/UGEXKqR3r/uJvDVow6N31mu6PamKggMyzO
+4dXjgKLUH5IGWV5FnN1TmTzoUeMAUtgpDheJECfRd4vxJr41TnjyIYERAoGALJbV
+AgRyG237a537JS207hnt40+RO3g8MhejDxzq0S802P+bEZ/kW00QZXuIHEr0XN57
+/Le0x6SS8qFCQm1WOa+OoMpHUn20JDQl9E+l4Pgk331l1LsPVmMOzl4ns2uLp2H7
++sOEc46IbfniAOj106E8FX1+9jw0gI8QQbtlbgECgYA/QsKOQnnUoikpIsKRfJ7x
+S8AERMBXLa1Q9lPtaiCF7lQSkLUfn2goSWVUCEPD6mgsbOcq2hlY9HXQaVispSrm
+aUb8tCSa/cM9Gldxl0Jt1rSW4O0H2mw6vwjihZ0MGMfM921+x95vxNylHZxp2eYZ
+vKJsYp14tT/JqNH+qQN2mQ==
+-----END PRIVATE KEY-----
+Certificate:
+ Data:
+ Version: 3 (0x2)
+ Serial Number: 1 (0x1)
+ Signature Algorithm: sha256WithRSAEncryption
+ Issuer: C=US, ST=California, L=Mountain View, O=Test CA, CN=Test Intermediate CA
+ Validity
+ Not Before: Dec 9 22:40:08 2016 GMT
+ Not After : Dec 7 22:40:08 2026 GMT
+ Subject: C=US, ST=California, L=Mountain View, O=Test CA, CN=127.0.0.1
+ Subject Public Key Info:
+ Public Key Algorithm: rsaEncryption
+ Public-Key: (2048 bit)
+ Modulus:
+ 00:bf:a3:5d:b8:f2:6d:da:86:d4:d6:dd:0c:a0:db:
+ c0:9a:c4:3b:b7:95:06:9a:11:d7:cf:8d:d0:1c:ef:
+ 99:dc:8a:dd:87:bd:d9:0e:b9:11:69:af:94:57:11:
+ af:8b:86:16:08:59:c8:fe:fe:86:ba:26:09:fe:f0:
+ 51:ba:14:43:64:c8:65:85:1f:cb:44:39:f6:93:57:
+ 98:34:f2:bf:06:77:36:02:6a:d9:99:04:f4:e2:5d:
+ 7f:db:ed:f2:14:5d:48:72:b2:5b:34:b2:df:ea:56:
+ ab:d3:88:f6:58:44:cf:40:33:fe:c9:b5:b8:c3:e2:
+ 73:59:0d:a6:e6:c9:5b:91:92:42:c1:f2:58:31:12:
+ e0:57:5f:94:7c:76:2d:d2:ac:e7:c2:62:a2:88:e8:
+ 83:cf:88:9e:ed:ba:67:09:61:b8:1f:5a:a5:e1:74:
+ ca:87:18:3b:5d:d0:ef:c2:45:f5:26:25:18:ca:9a:
+ c5:f7:61:9b:b0:fb:1c:04:0a:03:59:d7:87:c6:51:
+ 65:3b:6e:74:76:50:e7:c2:52:00:5a:45:59:8e:2f:
+ 69:1d:83:ae:78:e5:03:66:15:3f:7b:42:93:f0:c5:
+ 1a:ad:96:e4:e7:09:31:0e:4d:97:b5:9e:9b:63:78:
+ d3:0e:ca:27:d2:64:27:92:c2:de:6b:2e:5c:f0:7f:
+ 78:d9
+ Exponent: 65537 (0x10001)
+ X509v3 extensions:
+ X509v3 Basic Constraints: critical
+ CA:FALSE
+ X509v3 Subject Key Identifier:
+ 1A:DE:3A:BF:17:09:87:0A:D0:12:6B:C9:47:D2:A7:EB:ED:5B:04:99
+ X509v3 Authority Key Identifier:
+ keyid:F9:98:21:49:71:FA:8D:B9:20:F7:FE:5D:4D:41:E8:8B:6C:E0:62:C3
+
+ X509v3 Extended Key Usage:
+ TLS Web Server Authentication, TLS Web Client Authentication
+ X509v3 Subject Alternative Name:
+ IP Address:127.0.0.1
+ Signature Algorithm: sha256WithRSAEncryption
+ 8a:ac:de:1c:d2:ca:a7:b3:f8:26:34:2e:a7:b4:ef:7e:26:08:
+ 5b:f4:78:ec:37:4a:a8:02:c8:37:cc:45:7c:e3:bd:5c:e3:87:
+ 24:ea:4f:1a:dd:f5:d7:a3:de:2f:78:6a:e9:3a:4d:87:3a:9b:
+ 7c:5c:5b:59:b4:2f:9e:1d:6d:29:9f:60:c0:d8:b7:87:0c:4b:
+ 59:ac:b3:0d:5c:11:4f:24:09:4e:7c:84:72:00:8c:12:b7:84:
+ 8a:80:91:97:4e:22:17:e0:5f:83:fd:97:6c:51:b3:03:c0:a2:
+ 3c:f8:9e:24:a1:c1:b7:14:a0:6b:30:e8:62:b8:84:87:6b:ae:
+ e0:d2:56:f0:08:f6:d6:0e:1a:8d:5e:8b:06:b3:1e:14:6c:1b:
+ 72:e9:46:25:cb:97:b7:d5:4e:79:20:37:05:a4:51:8e:d4:40:
+ 3f:de:6f:c7:32:b8:28:2e:2a:08:c0:51:4e:32:1b:6c:c9:c0:
+ 03:b3:b6:3e:fd:46:1e:5b:b7:6f:ef:97:ae:df:03:e9:4e:64:
+ 39:94:fa:6f:65:71:11:dc:f7:4d:ed:48:c4:3d:7a:55:b8:c6:
+ f5:04:a4:d8:06:cd:c7:42:48:eb:d0:7a:4c:21:db:44:e7:c2:
+ 68:a7:45:9f:54:2c:15:71:b5:74:c6:bf:1b:3c:eb:78:89:6f:
+ 19:3a:69:02
+-----BEGIN CERTIFICATE-----
+MIIDxzCCAq+gAwIBAgIBATANBgkqhkiG9w0BAQsFADBrMQswCQYDVQQGEwJVUzET
+MBEGA1UECAwKQ2FsaWZvcm5pYTEWMBQGA1UEBwwNTW91bnRhaW4gVmlldzEQMA4G
+A1UECgwHVGVzdCBDQTEdMBsGA1UEAwwUVGVzdCBJbnRlcm1lZGlhdGUgQ0EwHhcN
+MTYxMjA5MjI0MDA4WhcNMjYxMjA3MjI0MDA4WjBgMQswCQYDVQQGEwJVUzETMBEG
+A1UECAwKQ2FsaWZvcm5pYTEWMBQGA1UEBwwNTW91bnRhaW4gVmlldzEQMA4GA1UE
+CgwHVGVzdCBDQTESMBAGA1UEAwwJMTI3LjAuMC4xMIIBIjANBgkqhkiG9w0BAQEF
+AAOCAQ8AMIIBCgKCAQEAv6NduPJt2obU1t0MoNvAmsQ7t5UGmhHXz43QHO+Z3Ird
+h73ZDrkRaa+UVxGvi4YWCFnI/v6GuiYJ/vBRuhRDZMhlhR/LRDn2k1eYNPK/Bnc2
+AmrZmQT04l1/2+3yFF1IcrJbNLLf6lar04j2WETPQDP+ybW4w+JzWQ2m5slbkZJC
+wfJYMRLgV1+UfHYt0qznwmKiiOiDz4ie7bpnCWG4H1ql4XTKhxg7XdDvwkX1JiUY
+yprF92GbsPscBAoDWdeHxlFlO250dlDnwlIAWkVZji9pHYOueOUDZhU/e0KT8MUa
+rZbk5wkxDk2XtZ6bY3jTDson0mQnksLeay5c8H942QIDAQABo4GAMH4wDAYDVR0T
+AQH/BAIwADAdBgNVHQ4EFgQUGt46vxcJhwrQEmvJR9Kn6+1bBJkwHwYDVR0jBBgw
+FoAU+ZghSXH6jbkg9/5dTUHoi2zgYsMwHQYDVR0lBBYwFAYIKwYBBQUHAwEGCCsG
+AQUFBwMCMA8GA1UdEQQIMAaHBH8AAAEwDQYJKoZIhvcNAQELBQADggEBAIqs3hzS
+yqez+CY0Lqe0734mCFv0eOw3SqgCyDfMRXzjvVzjhyTqTxrd9dej3i94auk6TYc6
+m3xcW1m0L54dbSmfYMDYt4cMS1mssw1cEU8kCU58hHIAjBK3hIqAkZdOIhfgX4P9
+l2xRswPAojz4niShwbcUoGsw6GK4hIdrruDSVvAI9tYOGo1eiwazHhRsG3LpRiXL
+l7fVTnkgNwWkUY7UQD/eb8cyuCguKgjAUU4yG2zJwAOztj79Rh5bt2/vl67fA+lO
+ZDmU+m9lcRHc903tSMQ9elW4xvUEpNgGzcdCSOvQekwh20TnwminRZ9ULBVxtXTG
+vxs863iJbxk6aQI=
+-----END CERTIFICATE-----
diff --git a/chromium/net/data/ssl/certificates/quic_test.example.com.key.sct b/chromium/net/data/ssl/certificates/quic_test.example.com.key.sct
index 55b0b42b414..0d19282b535 100644
--- a/chromium/net/data/ssl/certificates/quic_test.example.com.key.sct
+++ b/chromium/net/data/ssl/certificates/quic_test.example.com.key.sct
Binary files differ
diff --git a/chromium/net/data/ssl/certificates/quic_test_ecc.example.com.sct b/chromium/net/data/ssl/certificates/quic_test_ecc.example.com.sct
new file mode 100644
index 00000000000..37582658969
--- /dev/null
+++ b/chromium/net/data/ssl/certificates/quic_test_ecc.example.com.sct
Binary files differ
diff --git a/chromium/net/data/ssl/certificates/x509_verify_results.chain.pem b/chromium/net/data/ssl/certificates/x509_verify_results.chain.pem
index 11c3187ab36..5b1c6bad05a 100644
--- a/chromium/net/data/ssl/certificates/x509_verify_results.chain.pem
+++ b/chromium/net/data/ssl/certificates/x509_verify_results.chain.pem
@@ -1,50 +1,178 @@
+Certificate:
+ Data:
+ Version: 3 (0x2)
+ Serial Number: 1 (0x1)
+ Signature Algorithm: sha256WithRSAEncryption
+ Issuer: C=US, ST=California, L=Mountain View, O=Test CA, CN=Test Intermediate CA
+ Validity
+ Not Before: Dec 9 22:40:08 2016 GMT
+ Not After : Dec 7 22:40:08 2026 GMT
+ Subject: C=US, ST=California, L=Mountain View, O=Test CA, CN=127.0.0.1
+ Subject Public Key Info:
+ Public Key Algorithm: rsaEncryption
+ Public-Key: (2048 bit)
+ Modulus:
+ 00:bf:a3:5d:b8:f2:6d:da:86:d4:d6:dd:0c:a0:db:
+ c0:9a:c4:3b:b7:95:06:9a:11:d7:cf:8d:d0:1c:ef:
+ 99:dc:8a:dd:87:bd:d9:0e:b9:11:69:af:94:57:11:
+ af:8b:86:16:08:59:c8:fe:fe:86:ba:26:09:fe:f0:
+ 51:ba:14:43:64:c8:65:85:1f:cb:44:39:f6:93:57:
+ 98:34:f2:bf:06:77:36:02:6a:d9:99:04:f4:e2:5d:
+ 7f:db:ed:f2:14:5d:48:72:b2:5b:34:b2:df:ea:56:
+ ab:d3:88:f6:58:44:cf:40:33:fe:c9:b5:b8:c3:e2:
+ 73:59:0d:a6:e6:c9:5b:91:92:42:c1:f2:58:31:12:
+ e0:57:5f:94:7c:76:2d:d2:ac:e7:c2:62:a2:88:e8:
+ 83:cf:88:9e:ed:ba:67:09:61:b8:1f:5a:a5:e1:74:
+ ca:87:18:3b:5d:d0:ef:c2:45:f5:26:25:18:ca:9a:
+ c5:f7:61:9b:b0:fb:1c:04:0a:03:59:d7:87:c6:51:
+ 65:3b:6e:74:76:50:e7:c2:52:00:5a:45:59:8e:2f:
+ 69:1d:83:ae:78:e5:03:66:15:3f:7b:42:93:f0:c5:
+ 1a:ad:96:e4:e7:09:31:0e:4d:97:b5:9e:9b:63:78:
+ d3:0e:ca:27:d2:64:27:92:c2:de:6b:2e:5c:f0:7f:
+ 78:d9
+ Exponent: 65537 (0x10001)
+ X509v3 extensions:
+ X509v3 Basic Constraints: critical
+ CA:FALSE
+ X509v3 Subject Key Identifier:
+ 1A:DE:3A:BF:17:09:87:0A:D0:12:6B:C9:47:D2:A7:EB:ED:5B:04:99
+ X509v3 Authority Key Identifier:
+ keyid:F9:98:21:49:71:FA:8D:B9:20:F7:FE:5D:4D:41:E8:8B:6C:E0:62:C3
+
+ X509v3 Extended Key Usage:
+ TLS Web Server Authentication, TLS Web Client Authentication
+ X509v3 Subject Alternative Name:
+ IP Address:127.0.0.1
+ Signature Algorithm: sha256WithRSAEncryption
+ 8a:ac:de:1c:d2:ca:a7:b3:f8:26:34:2e:a7:b4:ef:7e:26:08:
+ 5b:f4:78:ec:37:4a:a8:02:c8:37:cc:45:7c:e3:bd:5c:e3:87:
+ 24:ea:4f:1a:dd:f5:d7:a3:de:2f:78:6a:e9:3a:4d:87:3a:9b:
+ 7c:5c:5b:59:b4:2f:9e:1d:6d:29:9f:60:c0:d8:b7:87:0c:4b:
+ 59:ac:b3:0d:5c:11:4f:24:09:4e:7c:84:72:00:8c:12:b7:84:
+ 8a:80:91:97:4e:22:17:e0:5f:83:fd:97:6c:51:b3:03:c0:a2:
+ 3c:f8:9e:24:a1:c1:b7:14:a0:6b:30:e8:62:b8:84:87:6b:ae:
+ e0:d2:56:f0:08:f6:d6:0e:1a:8d:5e:8b:06:b3:1e:14:6c:1b:
+ 72:e9:46:25:cb:97:b7:d5:4e:79:20:37:05:a4:51:8e:d4:40:
+ 3f:de:6f:c7:32:b8:28:2e:2a:08:c0:51:4e:32:1b:6c:c9:c0:
+ 03:b3:b6:3e:fd:46:1e:5b:b7:6f:ef:97:ae:df:03:e9:4e:64:
+ 39:94:fa:6f:65:71:11:dc:f7:4d:ed:48:c4:3d:7a:55:b8:c6:
+ f5:04:a4:d8:06:cd:c7:42:48:eb:d0:7a:4c:21:db:44:e7:c2:
+ 68:a7:45:9f:54:2c:15:71:b5:74:c6:bf:1b:3c:eb:78:89:6f:
+ 19:3a:69:02
-----BEGIN CERTIFICATE-----
-MIICwjCCAiugAwIBAgIBAjANBgkqhkiG9w0BAQUFADBrMQswCQYDVQQGEwJVUzET
+MIIDxzCCAq+gAwIBAgIBATANBgkqhkiG9w0BAQsFADBrMQswCQYDVQQGEwJVUzET
MBEGA1UECAwKQ2FsaWZvcm5pYTEWMBQGA1UEBwwNTW91bnRhaW4gVmlldzEQMA4G
A1UECgwHVGVzdCBDQTEdMBsGA1UEAwwUVGVzdCBJbnRlcm1lZGlhdGUgQ0EwHhcN
-MTEwNDE4MDA1MzE4WhcNMjAxMTE2MDA1MzE4WjBgMQswCQYDVQQGEwJVUzETMBEG
+MTYxMjA5MjI0MDA4WhcNMjYxMjA3MjI0MDA4WjBgMQswCQYDVQQGEwJVUzETMBEG
A1UECAwKQ2FsaWZvcm5pYTEWMBQGA1UEBwwNTW91bnRhaW4gVmlldzEQMA4GA1UE
-CgwHVGVzdCBDQTESMBAGA1UEAwwJMTI3LjAuMC4xMIGfMA0GCSqGSIb3DQEBAQUA
-A4GNADCBiQKBgQCmXYTWf2ivhIc3uf3qdg8u9c8EobXlXHSGq2iYJBedlGwyFUa1
-lijbi4OhP53pVv/gP9rZJXKACWDI4ZryAa2La1CiTAgesewzPIIVzrJ2KaNUFpvO
-e7YLZVqa0AnMNv1LNVp8eT05rcvN0XxFqvOdaFASBKnjOTqdvdkLtqwYawIDAQAB
-o4GAMH4wDAYDVR0TAQH/BAIwADAdBgNVHQ4EFgQUhEM3aeclNoZ1e/vksAaYOkCW
-txUwHwYDVR0jBBgwFoAUlJpwHgPeLEqeOAaz6Y7gch7YeCgwHQYDVR0lBBYwFAYI
-KwYBBQUHAwEGCCsGAQUFBwMCMA8GA1UdEQQIMAaHBH8AAAEwDQYJKoZIhvcNAQEF
-BQADgYEAFMILenxcrqHu6+a77HDjZQ1TUHZcVnokdhbCR8n+jxO+QdrQcJuu9VPa
-0XpYR+x5VzN26Tbf88jGyCGEkDrtr7sBsw+YzUvDx18Rl9SfE4jFNuvNRCY+/oMH
-eq4v35gB0tHOH2As3QGywnp2zEAA8eVMJzSFHS18WR/vBUGpvzo=
+CgwHVGVzdCBDQTESMBAGA1UEAwwJMTI3LjAuMC4xMIIBIjANBgkqhkiG9w0BAQEF
+AAOCAQ8AMIIBCgKCAQEAv6NduPJt2obU1t0MoNvAmsQ7t5UGmhHXz43QHO+Z3Ird
+h73ZDrkRaa+UVxGvi4YWCFnI/v6GuiYJ/vBRuhRDZMhlhR/LRDn2k1eYNPK/Bnc2
+AmrZmQT04l1/2+3yFF1IcrJbNLLf6lar04j2WETPQDP+ybW4w+JzWQ2m5slbkZJC
+wfJYMRLgV1+UfHYt0qznwmKiiOiDz4ie7bpnCWG4H1ql4XTKhxg7XdDvwkX1JiUY
+yprF92GbsPscBAoDWdeHxlFlO250dlDnwlIAWkVZji9pHYOueOUDZhU/e0KT8MUa
+rZbk5wkxDk2XtZ6bY3jTDson0mQnksLeay5c8H942QIDAQABo4GAMH4wDAYDVR0T
+AQH/BAIwADAdBgNVHQ4EFgQUGt46vxcJhwrQEmvJR9Kn6+1bBJkwHwYDVR0jBBgw
+FoAU+ZghSXH6jbkg9/5dTUHoi2zgYsMwHQYDVR0lBBYwFAYIKwYBBQUHAwEGCCsG
+AQUFBwMCMA8GA1UdEQQIMAaHBH8AAAEwDQYJKoZIhvcNAQELBQADggEBAIqs3hzS
+yqez+CY0Lqe0734mCFv0eOw3SqgCyDfMRXzjvVzjhyTqTxrd9dej3i94auk6TYc6
+m3xcW1m0L54dbSmfYMDYt4cMS1mssw1cEU8kCU58hHIAjBK3hIqAkZdOIhfgX4P9
+l2xRswPAojz4niShwbcUoGsw6GK4hIdrruDSVvAI9tYOGo1eiwazHhRsG3LpRiXL
+l7fVTnkgNwWkUY7UQD/eb8cyuCguKgjAUU4yG2zJwAOztj79Rh5bt2/vl67fA+lO
+ZDmU+m9lcRHc903tSMQ9elW4xvUEpNgGzcdCSOvQekwh20TnwminRZ9ULBVxtXTG
+vxs863iJbxk6aQI=
-----END CERTIFICATE-----
+Certificate:
+ Data:
+ Version: 3 (0x2)
+ Serial Number: 1 (0x1)
+ Signature Algorithm: sha256WithRSAEncryption
+ Issuer: CN=Test Root CA
+ Validity
+ Not Before: Dec 9 22:40:07 2016 GMT
+ Not After : Dec 7 22:40:07 2026 GMT
+ Subject: C=US, ST=California, L=Mountain View, O=Test CA, CN=Test Intermediate CA
+ Subject Public Key Info:
+ Public Key Algorithm: rsaEncryption
+ Public-Key: (2048 bit)
+ Modulus:
+ 00:a7:50:4b:cf:f2:ca:69:33:1a:91:ef:71:7d:68:
+ 3a:af:1e:eb:14:ee:64:a8:2b:41:c6:ec:2b:52:e9:
+ 66:ac:5d:4f:fd:2e:b0:31:39:6c:2e:81:1e:83:5d:
+ 59:95:d2:2a:99:fb:f1:38:2e:f9:36:52:53:7c:ea:
+ ba:df:fb:d6:98:f4:c9:39:d1:34:46:67:83:41:89:
+ bc:cb:94:f9:26:3d:b0:b6:68:f7:93:6b:d4:40:27:
+ 52:61:0f:20:1e:91:58:3d:60:dd:4a:1c:fe:54:3f:
+ 0c:4a:c4:58:d7:11:ff:a8:3c:f1:cd:39:f6:48:9b:
+ a5:20:db:cc:90:2b:fb:1f:62:eb:46:4d:d3:ef:03:
+ f8:f6:e0:82:05:af:2a:4f:00:ed:da:63:04:70:41:
+ e6:0a:93:e9:4d:85:d4:f7:2b:86:f3:35:e1:69:b5:
+ 81:fc:da:4f:cb:42:94:c9:d7:76:ba:9b:57:9f:fb:
+ ef:ed:26:ef:2d:53:73:2f:92:31:4b:38:7b:86:66:
+ eb:0d:2e:f2:93:8f:c5:bb:fe:cc:13:50:e9:18:1d:
+ 18:64:99:91:da:de:96:2b:08:72:21:23:42:67:99:
+ 86:98:fe:6f:f5:8e:0e:61:b1:0a:7e:f5:b8:d5:a7:
+ 06:a0:53:ef:7f:04:db:11:c4:07:0a:47:96:f0:93:
+ 82:d5
+ Exponent: 65537 (0x10001)
+ X509v3 extensions:
+ X509v3 Basic Constraints: critical
+ CA:TRUE
+ X509v3 Subject Key Identifier:
+ F9:98:21:49:71:FA:8D:B9:20:F7:FE:5D:4D:41:E8:8B:6C:E0:62:C3
+ X509v3 Key Usage: critical
+ Certificate Sign, CRL Sign
+ Signature Algorithm: sha256WithRSAEncryption
+ 50:c7:37:47:87:1a:8a:b2:cc:37:d0:f6:4a:46:ee:b5:85:90:
+ 35:a5:a0:c8:c7:c7:38:7d:5d:bb:e0:fc:0f:15:d3:75:50:e5:
+ 06:08:b5:ec:d7:e8:65:63:03:5a:38:3e:2c:5a:eb:28:a0:3c:
+ 70:3f:d4:30:25:20:dd:22:63:08:f0:9b:a9:c8:34:8f:f6:7c:
+ 5a:ce:10:72:5c:37:a0:01:a6:5e:1b:a4:60:e7:93:f6:42:61:
+ 2c:d1:57:67:16:d9:19:21:52:03:8c:9a:aa:75:10:ca:a1:bc:
+ 53:07:f1:6f:52:54:88:50:7d:11:ef:96:82:0d:e9:7d:c1:42:
+ 42:42:13:1f:48:ef:49:70:df:e1:30:f9:6f:2f:3d:cd:51:1c:
+ 14:9c:bd:12:0c:f2:d7:16:32:4a:d5:6b:4b:21:01:6c:4a:b1:
+ ee:7b:8c:d0:99:7e:5e:1e:ef:10:24:6e:e3:6f:e2:e0:4b:0b:
+ 42:79:78:ab:2b:af:54:82:c4:b1:57:a3:f0:6f:16:42:ed:61:
+ fc:69:5e:2b:09:14:4a:61:cc:6a:19:52:66:89:06:48:f1:b5:
+ 76:39:68:21:dc:68:9d:11:07:37:80:ae:37:77:b4:69:69:29:
+ ff:f6:fc:f1:50:bc:ee:9a:f9:ab:c8:bf:a6:65:51:cc:89:1e:
+ 2f:2c:95:e9
-----BEGIN CERTIFICATE-----
-MIICpzCCAhCgAwIBAgIBATANBgkqhkiG9w0BAQUFADBjMQswCQYDVQQGEwJVUzET
-MBEGA1UECAwKQ2FsaWZvcm5pYTEWMBQGA1UEBwwNTW91bnRhaW4gVmlldzEQMA4G
-A1UECgwHVGVzdCBDQTEVMBMGA1UEAwwMVGVzdCBSb290IENBMB4XDTExMDQxNzIy
-MjU1OFoXDTIxMDIyMzIyMjU1OFowazELMAkGA1UEBhMCVVMxEzARBgNVBAgMCkNh
-bGlmb3JuaWExFjAUBgNVBAcMDU1vdW50YWluIFZpZXcxEDAOBgNVBAoMB1Rlc3Qg
-Q0ExHTAbBgNVBAMMFFRlc3QgSW50ZXJtZWRpYXRlIENBMIGfMA0GCSqGSIb3DQEB
-AQUAA4GNADCBiQKBgQCdrVeFppenZ20T6f76yHp+qIOuWpA9ojNKJW+p93kY/2wC
-bUxVndJ+YYQ2/HGHURRGwBs/1yYCaeyCeVF3Ckr3Ei65fDAHqZFpZ/IsjUT9eRBO
-BODSaKFfvCF7Iv+521PZq5QaIPZOA99CaL5nqlEUbtas+4ziEg76Ngc2KxII1QID
-AQABo2MwYTAPBgNVHRMBAf8EBTADAQH/MB0GA1UdDgQWBBSUmnAeA94sSp44BrPp
-juByHth4KDAfBgNVHSMEGDAWgBRqsJiqdonmw+gkmvYOysT9lJgj2zAOBgNVHQ8B
-Af8EBAMCAQYwDQYJKoZIhvcNAQEFBQADgYEAzGgopGXKvuBlz04KEFMu46fUrxYe
-O6B6csR7Rt7elDvIMu2+rdkaP9Ccv0PqtXv4DRFCxdrG8+LhL3B4SofYxCqTtq9e
-rNtFRIR5Xad07djNBshor9PjNeKHnrGc1rXesqCfILpg2fq/Qv1OM1yrpLjbcuM6
-eCG7aIfsh9LwP3o=
+MIIDPzCCAiegAwIBAgIBATANBgkqhkiG9w0BAQsFADAXMRUwEwYDVQQDDAxUZXN0
+IFJvb3QgQ0EwHhcNMTYxMjA5MjI0MDA3WhcNMjYxMjA3MjI0MDA3WjBrMQswCQYD
+VQQGEwJVUzETMBEGA1UECAwKQ2FsaWZvcm5pYTEWMBQGA1UEBwwNTW91bnRhaW4g
+VmlldzEQMA4GA1UECgwHVGVzdCBDQTEdMBsGA1UEAwwUVGVzdCBJbnRlcm1lZGlh
+dGUgQ0EwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCnUEvP8sppMxqR
+73F9aDqvHusU7mSoK0HG7CtS6WasXU/9LrAxOWwugR6DXVmV0iqZ+/E4Lvk2UlN8
+6rrf+9aY9Mk50TRGZ4NBibzLlPkmPbC2aPeTa9RAJ1JhDyAekVg9YN1KHP5UPwxK
+xFjXEf+oPPHNOfZIm6Ug28yQK/sfYutGTdPvA/j24IIFrypPAO3aYwRwQeYKk+lN
+hdT3K4bzNeFptYH82k/LQpTJ13a6m1ef++/tJu8tU3MvkjFLOHuGZusNLvKTj8W7
+/swTUOkYHRhkmZHa3pYrCHIhI0JnmYaY/m/1jg5hsQp+9bjVpwagU+9/BNsRxAcK
+R5bwk4LVAgMBAAGjQjBAMA8GA1UdEwEB/wQFMAMBAf8wHQYDVR0OBBYEFPmYIUlx
++o25IPf+XU1B6Its4GLDMA4GA1UdDwEB/wQEAwIBBjANBgkqhkiG9w0BAQsFAAOC
+AQEAUMc3R4cairLMN9D2SkbutYWQNaWgyMfHOH1du+D8DxXTdVDlBgi17NfoZWMD
+Wjg+LFrrKKA8cD/UMCUg3SJjCPCbqcg0j/Z8Ws4Qclw3oAGmXhukYOeT9kJhLNFX
+ZxbZGSFSA4yaqnUQyqG8Uwfxb1JUiFB9Ee+Wgg3pfcFCQkITH0jvSXDf4TD5by89
+zVEcFJy9Egzy1xYyStVrSyEBbEqx7nuM0Jl+Xh7vECRu42/i4EsLQnl4qyuvVILE
+sVej8G8WQu1h/GleKwkUSmHMahlSZokGSPG1djloIdxonREHN4CuN3e0aWkp//b8
+8VC87pr5q8i/pmVRzIkeLyyV6Q==
-----END CERTIFICATE-----
-----BEGIN CERTIFICATE-----
-MIIChjCCAe+gAwIBAgIJAOa+aXDInZR1MA0GCSqGSIb3DQEBBQUAMGMxCzAJBgNV
-BAYTAlVTMRMwEQYDVQQIDApDYWxpZm9ybmlhMRYwFAYDVQQHDA1Nb3VudGFpbiBW
-aWV3MRAwDgYDVQQKDAdUZXN0IENBMRUwEwYDVQQDDAxUZXN0IFJvb3QgQ0EwHhcN
-MTEwNDE3MjIzMTEzWhcNMjEwNDE0MjIzMTEzWjBjMQswCQYDVQQGEwJVUzETMBEG
-A1UECAwKQ2FsaWZvcm5pYTEWMBQGA1UEBwwNTW91bnRhaW4gVmlldzEQMA4GA1UE
-CgwHVGVzdCBDQTEVMBMGA1UEAwwMVGVzdCBSb290IENBMIGfMA0GCSqGSIb3DQEB
-AQUAA4GNADCBiQKBgQD0pusirvvLaxBXtAu7kE9X7q4K/iOjIQIBNIbGdKtPDZus
-9I7SCNa3ZWcvTKTOp1biFCuXLJ404cxSOqo6YB7s4hcyHVEMz+EHhxHUYQmmZb0P
-12QwWVteJd2MZvkwupPeaNJhlyR0Vf51m9kpPVuFLrMb4Smvgcx9jbwOut1ACwID
-AQABo0IwQDAPBgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB/wQEAwIBBjAdBgNVHQ4E
-FgQUarCYqnaJ5sPoJJr2DsrE/ZSYI9swDQYJKoZIhvcNAQEFBQADgYEAck/rD/Vy
-vD53HXph/Bc7+qo9t3Nmyy9rbgl0dQq9h5+6Ria4Btw3Uj8iaQZTeyyFvGP0NHR2
-ek2hgX7fDwD3fRKEJus4shs16BzuSCBmYKw/G5PehEC9trIly52pMuUGphczbpzp
-6RdYOT3pG713l25Kt436hDnCoonwUqB6mhs=
+MIIC8zCCAdugAwIBAgIJALF9qhLor0+aMA0GCSqGSIb3DQEBBQUAMBcxFTATBgNV
+BAMMDFRlc3QgUm9vdCBDQTAeFw0xNDA4MTQwMzA1MjlaFw0yNDA4MTEwMzA1Mjla
+MBcxFTATBgNVBAMMDFRlc3QgUm9vdCBDQTCCASIwDQYJKoZIhvcNAQEBBQADggEP
+ADCCAQoCggEBALZJQeNCAVGofzx6cdP7zZE1F4QajvY2x9FwHfqG8267dm/oMi43
+/TiSPWjkin1CMxRGG9wE9pFuVEDECgn97C1i4l7huiycwbFgTNrH+CJcgiBlQh5W
+d3VP65AsSupXDiKNbJWsEerM1+72cA0J3aY1YV3Jdm2w8h6/MIbYd1I2lZcO0UbF
+7YE9G7DyYZU8wUA4719dumGf7yucn4WJdHBj1XboNX7OAeHzERGQHA31/Y3OEGyt
+fFUaIW/XLfR4FeovOL2RnjwdB0b1Q8GCi68SU2UZimlpZgay2gv6KgChKhWESfEB
+v5swBtAVoB+dUZFH4VNf717swmF5whSfxOMCAwEAAaNCMEAwDwYDVR0TAQH/BAUw
+AwEB/zAdBgNVHQ4EFgQUvPcw0TzA8nn675/JbFyT84poq4MwDgYDVR0PAQH/BAQD
+AgEGMA0GCSqGSIb3DQEBBQUAA4IBAQBXByn7f+j/sObYWGrDkKE4HLTzaLHs6Ikj
+JNeo8iHDYOSkSVwAv9/HgniAKxj3rd3QYl6nsMzwqrTOcBJZZWd2BQAYmv/EKhfj
+8VXYvlxe68rLU4cQ1QkyNqdeQfRT2n5WYNJ+TpqlCF9ddennMMsi6e8ZSYOlI6H4
+YEzlNtU5eBjxXr/OqgtTgSx4qQpr2xMQIRR/G3A9iRpAigYsXVAZYvnHRYnyPWYF
+PX11W1UegEJyoZp8bQp09u6mIWw6mPt3gl/ya1bm3ZuOUPDGrv3qpgUHqSYGVrOy
+2bI3oCE+eQYfuVG+9LFJTZC1M+UOx15bQMVqBNFDepRqpE9h/ILg
-----END CERTIFICATE-----
diff --git a/chromium/net/data/ssl/scripts/ca.cnf b/chromium/net/data/ssl/scripts/ca.cnf
index 28778a3dd7f..356662661a1 100644
--- a/chromium/net/data/ssl/scripts/ca.cnf
+++ b/chromium/net/data/ssl/scripts/ca.cnf
@@ -4,6 +4,7 @@ KEY_SIZE = 2048
ALGO = sha256
CERT_TYPE = root
CA_NAME = req_env_dn
+CA_COMMON_NAME = Test Root CA
[ca]
default_ca = CA_root
diff --git a/chromium/net/data/ssl/scripts/generate-client-certificates.sh b/chromium/net/data/ssl/scripts/generate-client-certificates.sh
index e7c8c0162a6..5e584b2fed6 100755
--- a/chromium/net/data/ssl/scripts/generate-client-certificates.sh
+++ b/chromium/net/data/ssl/scripts/generate-client-certificates.sh
@@ -14,6 +14,8 @@
# 2. D (end-entity) -> E -> C (self-signed root)
# 3. F (end-entity) -> E -> C (self-signed root)
# 4. G (end-entity, P-256) -> E -> C (self-signed root)
+# 5. H (end-entity, P-384) -> E -> C (self-signed root)
+# 6. I (end-entity, P-521) -> E -> C (self-signed root)
#
# In which the certificates all have distinct keypairs. The client
# certificates share the same root, but are issued by different
@@ -45,6 +47,8 @@ do
done
try openssl ecparam -name prime256v1 -genkey -noout -out out/G.key
+try openssl ecparam -name secp384r1 -genkey -noout -out out/H.key
+try openssl ecparam -name secp521r1 -genkey -noout -out out/I.key
echo Generate the C CSR
COMMON_NAME="C Root CA" \
@@ -108,7 +112,7 @@ COMMON_NAME="C CA" \
-config client-certs.cnf
echo Generate the leaf certs
-for id in A D F G
+for id in A D F G H I
do
COMMON_NAME="Client Cert $id" \
ID=$id \
@@ -169,12 +173,36 @@ COMMON_NAME="E CA" \
-out out/G.pem \
-config client-certs.cnf
+echo E signs H
+COMMON_NAME="E CA" \
+ CA_DIR=out \
+ ID=E \
+ try openssl ca \
+ -batch \
+ -extensions user_cert \
+ -in out/H.csr \
+ -out out/H.pem \
+ -config client-certs.cnf
+
+echo E signs I
+COMMON_NAME="E CA" \
+ CA_DIR=out \
+ ID=E \
+ try openssl ca \
+ -batch \
+ -extensions user_cert \
+ -in out/I.csr \
+ -out out/I.pem \
+ -config client-certs.cnf
+
echo Package the client certs and private keys into PKCS12 files
# This is done for easily importing all of the certs needed for clients.
try /bin/sh -c "cat out/A.pem out/A.key out/B.pem out/C.pem > out/A-chain.pem"
try /bin/sh -c "cat out/D.pem out/D.key out/E.pem out/C.pem > out/D-chain.pem"
try /bin/sh -c "cat out/F.pem out/F.key out/E.pem out/C.pem > out/F-chain.pem"
try /bin/sh -c "cat out/G.pem out/G.key out/E.pem out/C.pem > out/G-chain.pem"
+try /bin/sh -c "cat out/H.pem out/H.key out/E.pem out/C.pem > out/H-chain.pem"
+try /bin/sh -c "cat out/I.pem out/I.key out/E.pem out/C.pem > out/I-chain.pem"
try openssl pkcs12 \
-in out/A-chain.pem \
@@ -200,6 +228,18 @@ try openssl pkcs12 \
-export \
-passout pass:chrome
+try openssl pkcs12 \
+ -in out/H-chain.pem \
+ -out client_5.p12 \
+ -export \
+ -passout pass:chrome
+
+try openssl pkcs12 \
+ -in out/I-chain.pem \
+ -out client_6.p12 \
+ -export \
+ -passout pass:chrome
+
echo Package the client certs for unit tests
try cp out/A.pem ../certificates/client_1.pem
try cp out/A.key ../certificates/client_1.key
@@ -221,4 +261,14 @@ try cp out/G.key ../certificates/client_4.key
try cp out/G.pk8 ../certificates/client_4.pk8
try cp out/E.pem ../certificates/client_4_ca.pem
+try cp out/H.pem ../certificates/client_5.pem
+try cp out/H.key ../certificates/client_5.key
+try cp out/H.pk8 ../certificates/client_5.pk8
+try cp out/E.pem ../certificates/client_5_ca.pem
+
+try cp out/I.pem ../certificates/client_6.pem
+try cp out/I.key ../certificates/client_6.key
+try cp out/I.pk8 ../certificates/client_6.pk8
+try cp out/E.pem ../certificates/client_6_ca.pem
+
try cp out/C.pem ../certificates/client_root_ca.pem
diff --git a/chromium/net/data/ssl/scripts/generate-test-certs.sh b/chromium/net/data/ssl/scripts/generate-test-certs.sh
index 55c54bb3ff6..e02c028b8ab 100755
--- a/chromium/net/data/ssl/scripts/generate-test-certs.sh
+++ b/chromium/net/data/ssl/scripts/generate-test-certs.sh
@@ -13,6 +13,7 @@ try() {
try rm -rf out
try mkdir out
+try mkdir out/int
try /bin/sh -c "echo 01 > out/2048-sha256-root-serial"
touch out/2048-sha256-root-index.txt
@@ -21,14 +22,14 @@ touch out/2048-sha256-root-index.txt
try openssl genrsa -out out/2048-sha256-root.key 2048
# Generate the root certificate
-CA_COMMON_NAME="Test Root CA" \
+CA_NAME="req_ca_dn" \
try openssl req \
-new \
-key out/2048-sha256-root.key \
-out out/2048-sha256-root.req \
-config ca.cnf
-CA_COMMON_NAME="Test Root CA" \
+CA_NAME="req_ca_dn" \
try openssl x509 \
-req -days 3650 \
-in out/2048-sha256-root.req \
@@ -37,6 +38,26 @@ CA_COMMON_NAME="Test Root CA" \
-extensions ca_cert \
-text > out/2048-sha256-root.pem
+# Generate the test intermediate
+try /bin/sh -c "echo 01 > out/int/2048-sha256-int-serial"
+touch out/int/2048-sha256-int-index.txt
+
+CA_NAME="req_intermediate_dn" \
+ try openssl req \
+ -new \
+ -keyout out/int/2048-sha256-int.key \
+ -out out/int/2048-sha256-int.req \
+ -config ca.cnf
+
+CA_NAME="req_intermediate_dn" \
+ try openssl ca \
+ -batch \
+ -extensions ca_cert \
+ -days 3650 \
+ -in out/int/2048-sha256-int.req \
+ -out out/int/2048-sha256-int.pem \
+ -config ca.cnf
+
# Generate the leaf certificate requests
try openssl req \
-new \
@@ -66,7 +87,7 @@ try openssl req \
-config ee.cnf
# Generate the leaf certificates
-CA_COMMON_NAME="Test Root CA" \
+CA_NAME="req_ca_dn" \
try openssl ca \
-batch \
-extensions user_cert \
@@ -76,7 +97,7 @@ CA_COMMON_NAME="Test Root CA" \
-out out/expired_cert.pem \
-config ca.cnf
-CA_COMMON_NAME="Test Root CA" \
+CA_NAME="req_ca_dn" \
try openssl ca \
-batch \
-extensions user_cert \
@@ -85,7 +106,18 @@ CA_COMMON_NAME="Test Root CA" \
-out out/ok_cert.pem \
-config ca.cnf
-CA_COMMON_NAME="Test Root CA" \
+CA_DIR="out/int" \
+CERT_TYPE="int" \
+CA_NAME="req_intermediate_dn" \
+ try openssl ca \
+ -batch \
+ -extensions user_cert \
+ -days 3650 \
+ -in out/ok_cert.req \
+ -out out/int/ok_cert.pem \
+ -config ca.cnf
+
+CA_NAME="req_ca_dn" \
try openssl ca \
-batch \
-extensions user_cert \
@@ -94,7 +126,7 @@ CA_COMMON_NAME="Test Root CA" \
-out out/wildcard.pem \
-config ca.cnf
-CA_COMMON_NAME="Test Root CA" \
+CA_NAME="req_ca_dn" \
try openssl ca \
-batch \
-extensions name_constraint_bad \
@@ -104,7 +136,7 @@ CA_COMMON_NAME="Test Root CA" \
-out out/name_constraint_bad.pem \
-config ca.cnf
-CA_COMMON_NAME="Test Root CA" \
+CA_NAME="req_ca_dn" \
try openssl ca \
-batch \
-extensions name_constraint_good \
@@ -114,7 +146,7 @@ CA_COMMON_NAME="Test Root CA" \
-out out/name_constraint_good.pem \
-config ca.cnf
-CA_COMMON_NAME="Test Root CA" \
+CA_NAME="req_ca_dn" \
try openssl ca \
-batch \
-extensions user_cert \
@@ -123,7 +155,7 @@ CA_COMMON_NAME="Test Root CA" \
-out out/localhost_cert.pem \
-config ca.cnf
-CA_COMMON_NAME="Test Root CA" \
+CA_NAME="req_ca_dn" \
try openssl ca \
-batch \
-extensions user_cert \
@@ -150,6 +182,13 @@ try /bin/sh -c "cat out/ok_cert.key out/name_constraint_good.pem \
> ../certificates/name_constraint_good.pem"
try /bin/sh -c "cat out/ok_cert.key out/bad_validity.pem \
> ../certificates/bad_validity.pem"
+try /bin/sh -c "cat out/ok_cert.key out/int/ok_cert.pem \
+ > ../certificates/ok_cert_by_intermediate.pem"
+try /bin/sh -c "cat out/int/2048-sha256-int.key out/int/2048-sha256-int.pem \
+ > ../certificates/intermediate_ca_cert.pem"
+try /bin/sh -c "cat out/int/ok_cert.pem out/int/2048-sha256-int.pem \
+ out/2048-sha256-root.pem \
+ > ../certificates/x509_verify_results.chain.pem"
# Now generate the one-off certs
## Self-signed cert for SPDY/QUIC/HTTP2 pooling testing
@@ -185,7 +224,7 @@ try openssl req -x509 -days 3650 \
## SHA1 certificate expiring in 2016.
try openssl req -config ../scripts/ee.cnf -sha1 \
-newkey rsa:2048 -text -out out/sha1_2016.req
-CA_COMMON_NAME="Test Root CA" \
+CA_NAME="req_ca_dn" \
try openssl ca \
-batch \
-extensions user_cert \
@@ -198,7 +237,7 @@ CA_COMMON_NAME="Test Root CA" \
## SHA1 certificate issued the last second before the SHA-1 deprecation date.
try openssl req -config ../scripts/ee.cnf -sha1 \
-newkey rsa:2048 -text -out out/sha1_dec_2015.req
-CA_COMMON_NAME="Test Root CA" \
+CA_NAME="req_ca_dn" \
try openssl ca \
-batch \
-extensions user_cert \
@@ -211,7 +250,7 @@ CA_COMMON_NAME="Test Root CA" \
## SHA1 certificate issued on the SHA-1 deprecation date.
try openssl req -config ../scripts/ee.cnf -sha1 \
-newkey rsa:2048 -text -out out/sha1_jan_2016.req
-CA_COMMON_NAME="Test Root CA" \
+CA_NAME="req_ca_dn" \
try openssl ca \
-batch \
-extensions user_cert \
@@ -224,7 +263,7 @@ CA_COMMON_NAME="Test Root CA" \
## Validity too long unit test support.
try openssl req -config ../scripts/ee.cnf \
-newkey rsa:2048 -text -out out/10_year_validity.req
-CA_COMMON_NAME="Test Root CA" \
+CA_NAME="req_ca_dn" \
try openssl ca \
-batch \
-extensions user_cert \
@@ -236,7 +275,7 @@ CA_COMMON_NAME="Test Root CA" \
# 365 * 11 = 4015
try openssl req -config ../scripts/ee.cnf \
-newkey rsa:2048 -text -out out/11_year_validity.req
-CA_COMMON_NAME="Test Root CA" \
+CA_NAME="req_ca_dn" \
try openssl ca \
-batch \
-extensions user_cert \
@@ -247,7 +286,7 @@ CA_COMMON_NAME="Test Root CA" \
-config ca.cnf
try openssl req -config ../scripts/ee.cnf \
-newkey rsa:2048 -text -out out/39_months_after_2015_04.req
-CA_COMMON_NAME="Test Root CA" \
+CA_NAME="req_ca_dn" \
try openssl ca \
-batch \
-extensions user_cert \
@@ -258,7 +297,7 @@ CA_COMMON_NAME="Test Root CA" \
-config ca.cnf
try openssl req -config ../scripts/ee.cnf \
-newkey rsa:2048 -text -out out/40_months_after_2015_04.req
-CA_COMMON_NAME="Test Root CA" \
+CA_NAME="req_ca_dn" \
try openssl ca \
-batch \
-extensions user_cert \
@@ -269,7 +308,7 @@ CA_COMMON_NAME="Test Root CA" \
-config ca.cnf
try openssl req -config ../scripts/ee.cnf \
-newkey rsa:2048 -text -out out/60_months_after_2012_07.req
-CA_COMMON_NAME="Test Root CA" \
+CA_NAME="req_ca_dn" \
try openssl ca \
-batch \
-extensions user_cert \
@@ -281,7 +320,7 @@ CA_COMMON_NAME="Test Root CA" \
try openssl req -config ../scripts/ee.cnf \
-newkey rsa:2048 -text -out out/61_months_after_2012_07.req
# 30 * 61 = 1830
-CA_COMMON_NAME="Test Root CA" \
+CA_NAME="req_ca_dn" \
try openssl ca \
-batch \
-extensions user_cert \
@@ -293,7 +332,7 @@ CA_COMMON_NAME="Test Root CA" \
# start date after expiry date
try openssl req -config ../scripts/ee.cnf \
-newkey rsa:2048 -text -out out/start_after_expiry.req
-CA_COMMON_NAME="Test Root CA" \
+CA_NAME="req_ca_dn" \
try openssl ca \
-batch \
-extensions user_cert \
@@ -307,7 +346,7 @@ try openssl req -config ../scripts/ee.cnf \
# Issued pre-BRs, lifetime < 120 months, expires before 2019-07-01
try openssl req -config ../scripts/ee.cnf \
-newkey rsa:2048 -text -out out/pre_br_validity_ok.req
-CA_COMMON_NAME="Test Root CA" \
+CA_NAME="req_ca_dn" \
try openssl ca \
-batch \
-extensions user_cert \
@@ -321,7 +360,7 @@ try openssl req -config ../scripts/ee.cnf \
# Issued pre-BRs, lifetime > 120 months, expires before 2019-07-01
try openssl req -config ../scripts/ee.cnf \
-newkey rsa:2048 -text -out out/pre_br_validity_bad_121.req
-CA_COMMON_NAME="Test Root CA" \
+CA_NAME="req_ca_dn" \
try openssl ca \
-batch \
-extensions user_cert \
@@ -335,7 +374,7 @@ try openssl req -config ../scripts/ee.cnf \
# Issued pre-BRs, lifetime < 120 months, expires after 2019-07-01
try openssl req -config ../scripts/ee.cnf \
-newkey rsa:2048 -text -out out/pre_br_validity_bad_2020.req
-CA_COMMON_NAME="Test Root CA" \
+CA_NAME="req_ca_dn" \
try openssl ca \
-batch \
-extensions user_cert \
@@ -348,7 +387,7 @@ CA_COMMON_NAME="Test Root CA" \
# Issued prior to 1 June 2016 (Symantec CT Enforcement Date)
try openssl req -config ../scripts/ee.cnf \
-newkey rsa:2048 -text -out out/pre_june_2016.req
-CA_COMMON_NAME="Test Root CA" \
+CA_NAME="req_ca_dn" \
try openssl ca \
-batch \
-extensions user_cert \
@@ -361,7 +400,7 @@ CA_COMMON_NAME="Test Root CA" \
# Issued after 1 June 2016 (Symantec CT Enforcement Date)
try openssl req -config ../scripts/ee.cnf \
-newkey rsa:2048 -text -out out/post_june_2016.req
-CA_COMMON_NAME="Test Root CA" \
+CA_NAME="req_ca_dn" \
try openssl ca \
-batch \
-extensions user_cert \
@@ -389,13 +428,13 @@ try python crlsetutil.py -o ../certificates/crlset_by_leaf_spki.raw \
}
CRLBYLEAFSPKI
-## Block a leaf cert by issuer-hash-and-serial (ok_cert.pem == serial 2, by
+## Block a leaf cert by issuer-hash-and-serial (ok_cert.pem == serial 3, by
## virtue of the serial file and ordering above.
try python crlsetutil.py -o ../certificates/crlset_by_root_serial.raw \
<<CRLBYROOTSERIAL
{
"BlockedByHash": {
- "../certificates/root_ca_cert.pem": [2]
+ "../certificates/root_ca_cert.pem": [3]
}
}
CRLBYROOTSERIAL
@@ -406,7 +445,7 @@ try python crlsetutil.py -o ../certificates/crlset_by_intermediate_serial.raw \
<<CRLSETBYINTERMEDIATESERIAL
{
"BlockedByHash": {
- "../certificates/quic_intermediate.crt": [3]
+ "../certificates/intermediate_ca_cert.pem": [1]
}
}
CRLSETBYINTERMEDIATESERIAL
diff --git a/chromium/net/data/ssl/wosign/BUILD.gn b/chromium/net/data/ssl/wosign/BUILD.gn
new file mode 100644
index 00000000000..90d9e9867ea
--- /dev/null
+++ b/chromium/net/data/ssl/wosign/BUILD.gn
@@ -0,0 +1,18 @@
+# Copyright (c) 2017 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.
+
+action_foreach("wosign_domains") {
+ script = "//net/tools/dafsa/make_dafsa.py"
+ sources = [
+ "wosign_domains.gperf",
+ ]
+ outputs = [
+ "${target_gen_dir}/{{source_name_part}}-inc.cc",
+ ]
+ args = [
+ "{{source}}",
+ rebase_path("${target_gen_dir}/{{source_name_part}}-inc.cc",
+ root_build_dir),
+ ]
+}
diff --git a/chromium/net/data/ssl/wosign/wosign_domains.gperf b/chromium/net/data/ssl/wosign/wosign_domains.gperf
new file mode 100644
index 00000000000..88b2ee37804
--- /dev/null
+++ b/chromium/net/data/ssl/wosign/wosign_domains.gperf
@@ -0,0 +1,16759 @@
+%{
+// Copyright 2017 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.
+
+// This file contains the set of domains that were issued certificates by
+// WoSign and StartCom-branded CAs and were logged before
+// 2016-10-21 00:00:00 UTC. This list only contains those domains whose
+// certificates were not revoked as of 2016-12-31 and which appear within
+// the Alexa Top 1M dataset as of 2016-12-28.
+%}
+%%
+005.tv, 0
+010100100000.com, 0
+0101shop.com, 0
+01788.net, 0
+01game.com, 0
+01teacher.com, 0
+020leader.com, 0
+02cq.com, 0
+0318ol.com, 0
+0513c.com, 0
+0514soft.com, 0
+05506.com, 0
+0577hr.com, 0
+05.ru, 0
+06681.com, 0
+0678life.com, 0
+07073.com, 0
+0762jr.com, 0
+07zr.com, 0
+0800net.com.br, 0
+0951job.com, 0
+098.pl, 0
+0fees.us, 0
+0web.ir, 0
+10000.com, 0
+10000link.com, 0
+1000bankov.ru, 0
+1000bazi.com, 0
+1000lela.com, 0
+1000pokupok.com, 0
+1000ukg.kz, 0
+10010.org, 0
+10044.cn, 0
+100500miles.ru, 0
+10086.cn, 0
+1008.cn, 0
+100bt.com, 0
+100e.com, 0
+100hub.com, 0
+100-k-1.ru, 0
+100k.net.ua, 0
+100kuskov.ru, 0
+100megabit.ru, 0
+100msh.com, 0
+100steps.net, 0
+100vkusov.ru, 0
+100xuexi.com, 0
+10101111.com, 0
+10155.com, 0
+101.com, 0
+101hr.com, 0
+101ka.com, 0
+101sauna.ru, 0
+101widgets.com, 0
+10333.com, 0
+10brandchina.com, 0
+10gigabit.net, 0
+10to8.com, 0
+110.com, 0
+110disk.net, 0
+11185.cn, 0
+111.com.cn, 0
+11315.com, 0
+115.com, 0
+117o.com, 0
+1-1ads.com, 0
+1-1.su, 0
+11x11.ru, 0
+120na80.cz, 0
+120x.net, 0
+121mai.com, 0
+12301.cn, 0
+123aprende.com, 0
+123.com.cn, 0
+123hjemmeside.dk, 0
+123mov.net, 0
+124zhe.com, 0
+12580.tv, 0
+12582.cn, 0
+125.la, 0
+126.net, 0
+12seemeilen.de, 0
+1300acepro.com, 0
+133448.com, 0
+135qp.com, 0
+1360.com, 0
+139site.com, 0
+1406.kz, 0
+15166.com, 0
+155175.com, 0
+161.ru, 0
+1633.com, 0
+16889999.com, 0
+16hour.com, 0
+16mb.com, 0
+17500.cn, 0
+178448.com, 0
+1791diamonds.com, 0
+17bdc.com, 0
+17doubao.com, 0
+17heli.com, 0
+17house.com, 0
+17huo.com, 0
+17k.com, 0
+17must.com, 0
+17sportweb.com, 0
+17yigo.com, 0
+17zuoye.net, 0
+18183.com, 0
+185sy.com, 0
+189.cn, 0
+189cube.com, 0
+189go.cn, 0
+18zf.com, 0
+1905.com, 0
+190.com, 0
+1919.cn, 0
+1919hdtv.com, 0
+1927.kiev.ua, 0
+197top.com, 0
+19800.com, 0
+19950501.com, 0
+1academy.pro, 0
+1blu.de, 0
+1byone.com, 0
+1byone.co.uk, 0
+1byone.de, 0
+1byone.jp, 0
+1cbit.ru, 0
+1chotel.ru, 0
+1conan.com, 0
+1dxr.com, 0
+1game.ua, 0
+1gb.ua, 0
+1hai.cn, 0
+1huwai.com, 0
+1jbest.com, 0
+1ka.cn, 0
+1kejian.com, 0
+1kxun.mobi, 0
+1more.com, 0
+1-page.com, 0
+1pkk.ru, 0
+1platforma.ru, 0
+1plus1.net, 0
+1plus1.ua, 0
+1popov.ru, 0
+1prime.ru, 0
+1proxy.de, 0
+1september.ru, 0
+1st-attractive.com, 0
+1stwebdesigns.com, 0
+1tempurl.com, 0
+1track.ru, 0
+1tv.co.ua, 0
+1tvcrimea.ru, 0
+1v2d.com, 0
+2016bec.ro, 0
+2016.life, 0
+2100d.com, 0
+2114.com, 0
+212webhost.com, 0
+2144.cn, 0
+21cn.com, 0
+21.co.uk, 0
+21food.cn, 0
+21jrr.com, 0
+21mmo.com, 0
+21vbluecloud.com, 0
+21vianet.com, 0
+21yunwei.com, 0
+22v.net, 0
+22web.org, 0
+230km.ru, 0
+2330.tw, 0
+23356.com, 0
+233.com, 0
+2341.tv, 0
+23yy.com, 0
+247rack.com, 0
+24dx.ru, 0
+24gadget.ru, 0
+24maker.com, 0
+24paybank.com, 0
+25u.com, 0
+27.ua, 0
+29bet.co, 0
+29.ru, 0
+2ap.pl, 0
+2bulu.com, 0
+2cash.ru, 0
+2dfire.com, 0
+2dip.su, 0
+2do2go.ru, 0
+2fh.co, 0
+2gis.ae, 0
+2gis.cl, 0
+2gis.com, 0
+2gis.com.cy, 0
+2gis.cz, 0
+2gis.it, 0
+2gis.kg, 0
+2gis.kz, 0
+2gis.ru, 0
+2gis.ua, 0
+2hi.pl, 0
+2iretegas.it, 0
+2ix.de, 0
+2k2k.cc, 0
+2kom.ru, 0
+2kraski.ru, 0
+2manhua.com, 0
+2mao.cc, 0
+2peak.com, 0
+2plus2.ua, 0
+2proxy.de, 0
+2ryby.pl, 0
+2stick.ru, 0
+2sxvpn.wang, 0
+300188.cn, 0
+300.cn, 0
+3023.com, 0
+30post.com, 0
+310win.com, 0
+315jiage.cn, 0
+32ph.com, 0
+3310.com, 0
+3322.org, 0
+33pol.net, 0
+33rus.ru, 0
+33un.com, 0
+3400.org, 0
+34regiongaz.ru, 0
+34travel.by, 0
+360.cn, 0
+360.com, 0
+360doc.com, 0
+360fdc.com, 0
+360haoyao.com, 0
+360jie.com.cn, 0
+360jk.com, 0
+360kad.com, 0
+360kan.com, 0
+360pay.cn, 0
+360safe.com, 0
+360shouji.com, 0
+360shouzhuan.com, 0
+360totalsecurity.com, 0
+360tpcdn.com, 0
+360zimeiti.com, 0
+361sport.com, 0
+365hsh.com, 0
+365rili.com, 0
+365soke.cn, 0
+365webcall.com, 0
+36fy.com, 0
+36jr.com, 0
+36krcnd.com, 0
+36kr.com, 0
+37k.org, 0
+37ren.com, 0
+39.net, 0
+3arrafni.com, 0
+3bro.info, 0
+3cx.asia, 0
+3cx.com, 0
+3cx.de, 0
+3cx.es, 0
+3cx.eu, 0
+3cx.fr, 0
+3cx.it, 0
+3cx.net, 0
+3cx.ru, 0
+3cx.us, 0
+3cyber.info, 0
+3dcenter.org, 0
+3dmgame.com, 0
+3dnews.ru, 0
+3dyf.com, 0
+3-e.cz, 0
+3e.eu, 0
+3esynaptiq.com, 0
+3ie.fr, 0
+3mang.com, 0
+3proxy.de, 0
+3proxy.ru, 0
+3songshu.com, 0
+3tong.net, 0
+3utilities.com, 0
+4008087799.com, 0
+40407.com, 0
+404content.com, 0
+41.cn, 0
+41q.com, 0
+4231.vn, 0
+42trip.com, 0
+4399om.com, 0
+4399sy.com, 0
+442hz.com, 0
+45so.org, 0
+46etplus.com, 0
+4848438.com, 0
+48.cn, 0
+4all.com, 0
+4c.cn, 0
+4d.com, 0
+4dk.ru, 0
+4gjsq.net, 0
+4hu.com, 0
+4ka.sk, 0
+4nmv.ru, 0
+4paradigm.com, 0
+4pda.uz, 0
+4programmers.net, 0
+4proxy.us, 0
+4px.com, 0
+4qualia.co.jp, 0
+4real.gr, 0
+4ru.es, 0
+4shared-desktop.com, 0
+4tuning.ro, 0
+4uarab.com, 0
+4vision.ru, 0
+50webs.org, 0
+5112017.org, 0
+515to.com, 0
+517.cn, 0
+517na.com, 0
+51baogao.cn, 0
+51bi.com, 0
+51bmb.com, 0
+51.com, 0
+51datakey.com, 0
+51duoduo.com, 0
+51duoying.com, 0
+51eng.com, 0
+51goagent.com, 0
+51gsl.com, 0
+51laibei.com, 0
+51liucheng.com, 0
+51mypc.cn, 0
+51p2b.com, 0
+51pianmen.com, 0
+51rz.com, 0
+51shebao.com, 0
+51tniu.com, 0
+51tuodao.com, 0
+51vip.biz, 0
+51vv.com, 0
+51wnl.com, 0
+51xiaoshuang.com, 0
+51yangsheng.com, 0
+51ykb.com, 0
+51yund.com, 0
+51yunqiang.cn, 0
+520cfc.com, 0
+5262.com, 0
+52bug.cn, 0
+52daohang.com, 0
+52dfg.com, 0
+52ilm.com, 0
+52ilm.vip, 0
+52itstyle.com, 0
+52jbj.com, 0
+52jiaoshi.com, 0
+52joy.org, 0
+52life.cc, 0
+52ml.net, 0
+52spin.com, 0
+531314.com, 0
+550550.ru, 0
+55188.com, 0
+552la.com, 0
+55freehost.com, 0
+55haitao.com, 0
+565656.com, 0
+56p2b.com, 0
+5778.com, 0
+58bank.com, 0
+58cdn.com.cn, 0
+58corp.com, 0
+5900.com.ar, 0
+59pi.com, 0
+59store.com, 0
+5adm.cc, 0
+5c.com.cn, 0
+5di.tv, 0
+5dmat-web.com, 0
+5gbfree.com, 0
+5g-ppp.eu, 0
+5hxn.com, 0
+5idream.net, 0
+5igupiao.com, 0
+5ilog.com, 0
+5karmanov.ru, 0
+5ok.com.ua, 0
+5ppai.com, 0
+5qqksa.com, 0
+5xiaoyuan.cn, 0
+5zig.net, 0
+600280.com, 0
+601601.com, 0
+60500.ru, 0
+6080bo.com, 0
+60-fps.org, 0
+612459.com, 0
+66163.com, 0
+6655.la, 0
+66law.cn, 0
+66.ru, 0
+6789g.com, 0
+68edu.ru, 0
+68kmla.org, 0
+6ack.com, 0
+6a.com, 0
+6d1b.cc, 0
+6kyun.com, 0
+6lib.ru, 0
+6rz.in, 0
+6so.so, 0
+6te.net, 0
+700shin.ru, 0
+7-11.cn, 0
+72du.com, 0
+72e.net, 0
+7311.by, 0
+7618.com, 0
+76.ru, 0
+77169.com, 0
+771dian.com, 0
+77file.com, 0
+7958.com, 0
+7bitcasino.com, 0
+7days.ru, 0
+7ero.org, 0
+7fon.ru, 0
+7i24.com, 0
+7launcher.com, 0
+7moor.com, 0
+7n5.net, 0
+7nujoom.com, 0
+7to.com.tw, 0
+7tor.org, 0
+800best.com, 0
+800pai.com, 0
+80code.com, 0
+80pai.net, 0
+80s.tw, 0
+80uncle.com, 0
+80vps.com, 0
+81mv.com, 0
+85vod.com, 0
+868e.com, 0
+86y.org, 0
+87.cn, 0
+87dyy.com, 0
+8800.org, 0
+8864.com, 0
+8866.org, 0
+890m.com, 0
+8a.hk, 0
+8asyym.com, 0
+8eoe.com, 0
+8gongli.com, 0
+8pig.com, 0
+8solution.de, 0
+8solutions.cloud, 0
+8solutions.de, 0
+8th.com, 0
+8u.cz, 0
+8win.com, 0
+9080.tv, 0
+90music.ir, 0
+9111.ru, 0
+911proxy.com, 0
+91300.com, 0
+9158.com, 0
+9188.com, 0
+91.com, 0
+91game.com, 0
+91huayi.com, 0
+91kds.net, 0
+91moe.com, 0
+91pintuan.com, 0
+91pxb.com, 0
+91ri.org, 0
+91ssfq.com, 0
+91sst.com, 0
+91wii.com, 0
+91wutong.com, 0
+91y.com, 0
+91yun.org, 0
+91yunxiao.com, 0
+92081.org, 0
+921.com, 0
+92ez.com, 0
+9384.com, 0
+945.com, 0
+94cb.com, 0
+9513.com, 0
+9527yy.com, 0
+95579.com, 0
+9597.biz, 0
+96533.com, 0
+9666.cn, 0
+96.lt, 0
+980x.com, 0
+988house.com, 0
+99496.com, 0
+999.com, 0
+999d.com, 0
+99chan.org, 0
+99.com, 0
+9ht.com, 0
+9ifriend.com, 0
+9tour.cn, 0
+9wody.com, 0
+a101.ru, 0
+a2hosted.com, 0
+a2yy.com, 0
+a360.ru, 0
+a4yy.com, 0
+a696.com, 0
+a6adserv.com, 0
+a8z8.com, 0
+a-a-ah.ru, 0
+aaayun.com, 0
+aab-edu.net, 0
+aapig.com.cn, 0
+aasaanjobs.com, 0
+aasfp.com, 0
+aas.org, 0
+aasp.org.br, 0
+aauekpoma.edu.ng, 0
+aazyw.com, 0
+abacusemedia.com, 0
+abadan-ref.ir, 0
+abakan.ru, 0
+abakus-internet-marketing.de, 0
+abble.cn, 0
+abbseo.com, 0
+abbyy.com, 0
+abbyyeu.com, 0
+abbyy-ls.com, 0
+abbyy.ru, 0
+abbyy.ua, 0
+abbyyusa.com, 0
+abc188.com, 0
+abc360.com, 0
+abc6.net, 0
+abcapk.com, 0
+abcb2b.eu, 0
+abcd.bz, 0
+abc.edu.sv, 0
+abclite.net, 0
+abc.re, 0
+abcydia.com, 0
+abelohost.com, 0
+abfar-kh.ir, 0
+abf.cz, 0
+abf.se, 0
+abhiguitar.com, 0
+abidjan911.com, 0
+abileneisd.org, 0
+abit-poisk.org.ua, 0
+abitu.net, 0
+abitur-und-studium.de, 0
+abiyefon.com, 0
+ablecloud.cn, 0
+abletive.com, 0
+abm-com.de, 0
+about-nya.com, 0
+abp.bzh, 0
+abresalamat.ir, 0
+abrites.com, 0
+abs.cn, 0
+absi.be, 0
+absolutbank.ru, 0
+absolutist.com, 0
+absolutist.ru, 0
+abuxiaoxi.com, 0
+abz.ch, 0
+abzone.cz, 0
+academicconf.com, 0
+academy21.ru, 0
+acanomas.com, 0
+accentforex.com, 0
+access.ly, 0
+accounterlive.com, 0
+accuenplatform.com, 0
+acelerato.com, 0
+acer.com, 0
+aceteamwork.com, 0
+acfun.tv, 0
+acg.bz, 0
+acgcss.com, 0
+acg-moe.com, 0
+acgmoon.org, 0
+acgn.ren, 0
+ac.gov.ru, 0
+acgpy.com, 0
+acg.tf, 0
+acilissaati24.com, 0
+ac-illust.com, 0
+acision.com, 0
+acko.net, 0
+acko.ru, 0
+acli.it, 0
+a-closer-look.com, 0
+aclu.org, 0
+acm.ac.uk, 0
+acmcoder.com, 0
+acmhabitat.fr, 0
+acom.pt, 0
+aconcaguapoker.com, 0
+acoola.ru, 0
+acornsau.com.au, 0
+acousticalsurfaces.com, 0
+ac-project.net, 0
+acquadiparma.com, 0
+acronis.com, 0
+acrylicwifi.com, 0
+acsc.az, 0
+acs.si, 0
+acs-tpkg.com, 0
+actilove.ch, 0
+actionnetwork.org, 0
+actiplans.com, 0
+actitime.com, 0
+active24.cz, 0
+active-city.net, 0
+activeeon.com, 0
+activelink.ie, 0
+activemotif.com, 0
+activ.kz, 0
+actonlytics.com, 0
+actoys.net, 0
+acueducto.com.co, 0
+acumatica.com, 0
+acupuncture.org.uk, 0
+ad7.com, 0
+ada.edu.az, 0
+adamas.ru, 0
+adashboard.info, 0
+adbusters.org, 0
+ad.co.kr, 0
+adcom.it, 0
+adctools.com, 0
+adcubum.com, 0
+added-value.com, 0
+addison-electronique.com, 0
+addpipe.com, 0
+addradio.de, 0
+add.re.kr, 0
+addvalue.de, 0
+adept.co.za, 0
+adfreehost.ir, 0
+adic.co.kr, 0
+adicu.com, 0
+adioma.com, 0
+adks.cn, 0
+adkulan.kz, 0
+adllink.com.br, 0
+admagazine.ru, 0
+admgor.nnov.ru, 0
+admin.ch, 0
+adminhost.org, 0
+administrator.de, 0
+adminn.cn, 0
+admin.tomsk.ru, 0
+admissions.fr, 0
+admkrsk.ru, 0
+admoblkaluga.ru, 0
+admon.org, 0
+admsakhalin.ru, 0
+adobeconnect.ir, 0
+adofms.com.au, 0
+adp.com, 0
+adpop-1.com, 0
+adpop.com, 0
+adquisitio.com.mx, 0
+adquisitio.es, 0
+adquisitio.it, 0
+ad-rek.ru, 0
+adriagate.com, 0
+adrs.me, 0
+ads1-adnow.com, 0
+ads2-adnow.com, 0
+ads3-adnow.com, 0
+ads5-adnow.com, 0
+adsanityplugin.com, 0
+adseedata.com, 0
+adselect.ir, 0
+adsender.us, 0
+adsensor.org, 0
+adstarknetwork.com, 0
+aduana.cl, 0
+adukacyja.info, 0
+adultwebmastercenter.biz, 0
+advancedrenamer.com, 0
+advancedtomato.com, 0
+advendor.net, 0
+adverten.com, 0
+adverti.ru, 0
+advertising.management, 0
+adview.cn, 0
+adviqo.com, 0
+advisor.travel, 0
+adways.net, 0
+adwhiztech.com, 0
+adwifi.com.tw, 0
+adwitiyacollection.com, 0
+adxxx.me, 0
+adxxx.org, 0
+ady.az, 0
+ady-co.com, 0
+adygnet.ru, 0
+adzuna.ca, 0
+adzuna.com.au, 0
+adzuna.com.br, 0
+adzuna.co.uk, 0
+adzuna.co.za, 0
+adzuna.de, 0
+adzuna.fr, 0
+adzuna.in, 0
+adzuna.nl, 0
+adzuna.pl, 0
+adzuna.ru, 0
+adzz.me, 0
+aegean.gr, 0
+aegee.org, 0
+aegif.jp, 0
+aelius.com, 0
+ae.org, 0
+aeparser.com, 0
+aepb.gov.cn, 0
+aerial.net, 0
+aerosoft.de, 0
+aertecsolutions.com, 0
+aerztekammer.at, 0
+aesop.com, 0
+aewb.cn, 0
+afagh.info, 0
+afaghnet.ir, 0
+afanti100.com, 0
+afd.berlin, 0
+afflecks.com, 0
+affordplan.com, 0
+afghan123.com, 0
+afphabitat.cl, 0
+afraid.org, 0
+africaintelligence.com, 0
+africaintelligence.fr, 0
+africaninnovation.org, 0
+africanleadershipacademy.org, 0
+africanmeccasafaris.com, 0
+afrimalin.cm, 0
+afrimalin.com.gn, 0
+agantty.com, 0
+agava.net, 0
+agava.ru, 0
+agc-energies.fr, 0
+agearche.ru, 0
+agefi.fr, 0
+agendatrad.org, 0
+agfw.me, 0
+agglo-annecy.fr, 0
+agh.edu.pl, 0
+agilecontents.com, 0
+agimonline.com, 0
+aginomoto.com, 0
+agnesb.com, 0
+agonistes.gr, 0
+agoodme.com, 0
+agora.co.il, 0
+agora-energiewende.de, 0
+agpc28.com, 0
+agrafka.com.ua, 0
+agrant.cn, 0
+agrantsem.com, 0
+agriconomie.com, 0
+agroklub.com, 0
+agro-mash.ru, 0
+agronationale.ru, 0
+agropravda.com, 0
+agrosemfond.ru, 0
+agroxxi.ru, 0
+agts.tv, 0
+agulife.ru, 0
+ahjzu.edu.cn, 0
+ahmia.fi, 0
+ahml.ru, 0
+ahnw.gov.cn, 0
+ahs-de.com, 0
+ahtv.cn, 0
+ahu.edu.cn, 0
+ahvaznovin.ir, 0
+aia.com.sg, 0
+aiaiu.com, 0
+aibing.cc, 0
+ai.ch, 0
+aidaojia.com, 0
+aidl.pw, 0
+aigame100.com, 0
+aihuo360.com, 0
+aiirony.com, 0
+aiisen.com, 0
+aikaiyuan.com, 0
+aikf.com, 0
+aimatech.com, 0
+aimms.com, 0
+aimodel.me, 0
+aim.uz, 0
+ainiseo.com, 0
+aipa.ru, 0
+aipb.org, 0
+air-austral.com, 0
+airbase.ru, 0
+airbusgroup.com, 0
+aircn.org, 0
+aircrack-ng.org, 0
+airdog.com, 0
+airedesantafe.com.ar, 0
+airelf.com.tw, 0
+airgun.org.ua, 0
+airlinegeeks.com, 0
+airly.co, 0
+airmp3.me, 0
+airnet.ru, 0
+air-serenity.com, 0
+airstoc.com, 0
+airtime.pro, 0
+airtribune.com, 0
+airwarriors.com, 0
+airweave.jp, 0
+ais.by, 0
+aisidi.com, 0
+aisne.fr, 0
+aist.net.ru, 0
+ais.ua, 0
+ait.ac.th, 0
+aitech.ac.jp, 0
+ai-thinker.com, 0
+aiwanba.com, 0
+aixifan.com, 0
+aizhuizhui.com, 0
+ajaums.ac.ir, 0
+ajinga.com, 0
+ajmide.com, 0
+ajou.ac.kr, 0
+akademie-bv.de, 0
+akademikerverlag.de, 0
+akado-ural.ru, 0
+akairan.com, 0
+akama.com.tw, 0
+akasakaprince.com, 0
+akb48game.jp, 0
+akcis.org, 0
+akisho.ru, 0
+akket.com, 0
+aknw.de, 0
+akosi.ru, 0
+akson.ru, 0
+aktinos.com, 0
+akud.info, 0
+akusherstvo.ru, 0
+alain-bensoussan.com, 0
+alamesacuba.com, 0
+alapetite.fr, 0
+alarmtrade.ru, 0
+alaska.ua, 0
+alau.kz, 0
+albank.ru, 0
+albedo.pw, 0
+alberlet.hu, 0
+alberthsieh.com, 0
+alberto.gr, 0
+albooked.com, 0
+alcateia.com.br, 0
+alcatelonetouch.com, 0
+alchevsk.net, 0
+alconost.com, 0
+aldebaran.cz, 0
+aldjf.com, 0
+alemtat.kz, 0
+alertachiapas.com, 0
+aler.to, 0
+alexa_host, 0
+alexander-freundeskreis.org, 0
+alexandriava.gov, 0
+alexandrinsky.ru, 0
+alexbloggt.com, 0
+alexbruni.ru, 0
+alexfitness.ru, 0
+alexnettm.org.ua, 0
+alexwz.com, 0
+alexyanovsky.com, 0
+alfabank.kz, 0
+alfacapital.ru, 0
+alfa-forex.ru, 0
+alfatyping.com, 0
+alfred.camera, 0
+algoritma.it, 0
+alhassan.de, 0
+ali213.net, 0
+aliall.ru, 0
+aliapp.com, 0
+aliatic.com, 0
+alibi.by, 0
+alicall.com, 0
+alicomez.com, 0
+alidemo.cn, 0
+aliexsale.ru, 0
+aligo.in, 0
+alinino.az, 0
+aliseed.com, 0
+alittlebit.ru, 0
+alittlebityummy.com, 0
+aliwords.com, 0
+aliyuncs.com, 0
+all4os.com, 0
+allaboutjazz.com, 0
+allaboutparenting.ro, 0
+allananas.ru, 0
+all.biz, 0
+allboxing.ru, 0
+allcoin.com, 0
+allcorp.ru, 0
+alldiscount.info, 0
+alles-vegetarisch.de, 0
+alleyneinc.net, 0
+allfon.org, 0
+allhostings.ru, 0
+alliance-global.com, 0
+allinpay.com, 0
+all-in.xyz, 0
+allmedia.ru, 0
+allmovies.uz, 0
+allnokia.ru, 0
+allobnk.com, 0
+allo.ua, 0
+allplay.uz, 0
+allrad.ru, 0
+allseenalliance.org, 0
+allthefallen.ninja, 0
+alltobid.com, 0
+allure.ru, 0
+allwetterzoo.de, 0
+allyes.com, 0
+almamarket.pl, 0
+almasdarnews.com, 0
+almatv.kz, 0
+almaz.center, 0
+almedina.net, 0
+almin.ru, 0
+almodi.org, 0
+almohtarifdz.com, 0
+alo.ir, 0
+alone.tw, 0
+alpedhueznet.com, 0
+alphabrock.cn, 0
+alphacrc.com, 0
+alphacrew.com, 0
+alpha-network.io, 0
+alphaspel.se, 0
+alpha-wallet.com, 0
+alphest.com, 0
+alpine.com, 0
+alpinelinux.org, 0
+alser.kz, 0
+als-japan.com, 0
+alsyundawy.com, 0
+altarix.ru, 0
+altechna.com, 0
+altegrosky.ru, 0
+altel.kz, 0
+alternatehistory.com, 0
+alternetivo.cz, 0
+altervista.org, 0
+alterway.fr, 0
+altigator.com, 0
+altinkaya.com.tr, 0
+altissia.com, 0
+altlinux.org, 0
+altlinux.ru, 0
+altrk.net, 0
+altruja.de, 0
+altspu.ru, 0
+alt-team.com, 0
+alvanikoku.edu.ng, 0
+alwaysdata.net, 0
+alyzq.com, 0
+amainhobbies.com, 0
+amalgam-fansubs.tk, 0
+amanbo.co.ke, 0
+amanbo.com, 0
+amap.com, 0
+amaroma.it, 0
+amarone.hu, 0
+amazee.io, 0
+amazingradio.com, 0
+amazonaws.com, 0
+ambiente.gob.ar, 0
+amdn.news, 0
+amersport.ru, 0
+amforward.com, 0
+amfostacolo.ro, 0
+amigaosecreto.com.br, 0
+amigo.lv, 0
+amigosdecosat.com, 0
+amikash.ca, 0
+aminidc.com, 0
+amiro.ru, 0
+ammc.ma, 0
+amniran.org, 0
+amocrm.com, 0
+amolf.nl, 0
+amorousgame.com, 0
+amoskadan.cz, 0
+ampfutures.com, 0
+amplexor.com, 0
+ampr.org, 0
+amrita-rus.ru, 0
+amss.ac.cn, 0
+amt.com.cn, 0
+amv.es, 0
+anadea.info, 0
+anadyr.org, 0
+anafarsh.com, 0
+analyticaltrader.com, 0
+anapa-official.ru, 0
+anchel.nl, 0
+ancii.com, 0
+ancor.ru, 0
+andalucia.org, 0
+anderlecht.be, 0
+anderlecht-online.be, 0
+anderssen.ru, 0
+andipartners.com, 0
+andraste.io, 0
+andrewcbancroft.com, 0
+androbit.net, 0
+androidcentral.com, 0
+android-coffee.com, 0
+android-gems.com, 0
+android-help.ru, 0
+android-iphone-recovery.com, 0
+androidlearning.in, 0
+androidlost.com, 0
+andyet.com, 0
+andykamto.com, 0
+anegrinews.ru, 0
+anekdot.ru, 0
+anevia.com, 0
+angara.net, 0
+angellight.com, 0
+anglius.ru, 0
+angrymetalguy.com, 0
+anhuinews.com, 0
+anidesu.ru, 0
+anidex.moe, 0
+animan.uz, 0
+animationclub.ru, 0
+animecharactersdatabase.com, 0
+animeimpulse.com, 0
+animelayer.ru, 0
+anime-pictures.net, 0
+anime-rus.ru, 0
+animetosho.org, 0
+animetreff.de, 0
+anionix.ru, 0
+anitama.cn, 0
+anitoys.com, 0
+anizone.net, 0
+ankaraka.org.tr, 0
+ankerkraut.de, 0
+ankermann.com, 0
+ankiety-tv.pl, 0
+anko3.com, 0
+ankolpakov.ru, 0
+anmb.ro, 0
+annet.pl, 0
+annibuku.com, 0
+annkestore.com, 0
+anoneko.com, 0
+anonimag.es, 0
+anonymox.net, 0
+anotherhome.net, 0
+anovaculinary.com, 0
+anpc.ro, 0
+anpec.org.br, 0
+anritsu.com, 0
+anruan.com, 0
+ansan.ac.kr, 0
+ans.cz, 0
+anseo.cn, 0
+answercenter.ir, 0
+answerconnect.com, 0
+answerconnect.co.uk, 0
+anta.cn, 0
+anta.com, 0
+antagosoft.com, 0
+antclub.org, 0
+anticenz.org, 0
+antiplag.ru, 0
+antizapret.info, 0
+antoshkaspb.ru, 0
+antplanet.ru, 0
+antrak.org.tr, 0
+antshares.org, 0
+antsoul.com, 0
+anturis.com, 0
+anunciobot.com, 0
+anunciosparatodos.com, 0
+anvidelabs.org, 0
+anviz.com, 0
+anwalt24.de, 0
+anyfiles.co, 0
+anysdk.com, 0
+anysports.tv, 0
+anyway.fm, 0
+anzhen.org, 0
+anzhi.com, 0
+aoaoao.me, 0
+aofall.com, 0
+aomygod.com, 0
+aonb.ru, 0
+aor.ca, 0
+aoreteam.com, 0
+aori.ru, 0
+aos.com, 0
+aov.de, 0
+ap1.by, 0
+apabi.com, 0
+apachehaus.com, 0
+apachelounge.com, 0
+apaipian.com, 0
+apalon.com, 0
+apartamenty.kz, 0
+apave.com, 0
+apba.es, 0
+aperza.jp, 0
+apexdc.net, 0
+apex.fr, 0
+apexpoint.com, 0
+apfelwerk.de, 0
+apgsensors.com, 0
+apgsga.ch, 0
+apic.in, 0
+apimatic.io, 0
+apkdigg.co, 0
+apkdy.com, 0
+apk.tw, 0
+aplgo.com, 0
+aplicit.com, 0
+aplikasipc.com, 0
+apmetrix.com, 0
+apn.ru, 0
+apolisglobal.com, 0
+appadhoc.com, 0
+appbase.io, 0
+appbonus.ru, 0
+appcan.cn, 0
+appcelerator.com, 0
+appcoachs.com, 0
+appdated.de, 0
+appdb.cc, 0
+appfollow.io, 0
+appful.io, 0
+app-global.ru, 0
+appier.com, 0
+appier.net, 0
+applico.ru, 0
+applied-research.ru, 0
+applinzi.com, 0
+applysquare.com, 0
+applythis.net, 0
+apppark.cn, 0
+appreal-vr.com, 0
+apps555.com, 0
+appshike.com, 0
+appsmod.com, 0
+appsocks.cn, 0
+appson.ir, 0
+appstar.com.cn, 0
+appvault.com, 0
+apreva.fr, 0
+apricityos.com, 0
+apronline.gov.ar, 0
+apropos-store.com, 0
+aptekarsk.ru, 0
+apur.org, 0
+apusapps.com, 0
+apuscn.com, 0
+apx.fr, 0
+aqha.com, 0
+aql.com, 0
+aqua-calc.com, 0
+aqualogo.ru, 0
+aquariumbg.com, 0
+aquaservice.com, 0
+aqua-shop.ru, 0
+arabshack.com, 0
+aradhost.com, 0
+arado.org, 0
+aranycsillag.net, 0
+aras.com, 0
+arawaza.com, 0
+arb4host.net, 0
+arba.uz, 0
+arbeitsschutz-portal.de, 0
+arbicon.ru, 0
+arbital.ru, 0
+arb-silva.de, 0
+arbuse.ru, 0
+arcadiamedical.ro, 0
+arcadja.com, 0
+arch-anywhere.org, 0
+archboy.org, 0
+archermind.com, 0
+archersbr.com, 0
+archirodon.net, 0
+arcsoft.com.cn, 0
+ardahan.edu.tr, 0
+ardda.gov.az, 0
+ardisson.ir, 0
+areajugones.es, 0
+areeya.co.th, 0
+arefyevstudio.com, 0
+arenabg.ch, 0
+arenabg.com, 0
+arencenter.ir, 0
+ares.com.tw, 0
+argentinacompra.gov.ar, 0
+argentina.gob.ar, 0
+argor.com, 0
+ar.gov, 0
+ariacomputer.ir, 0
+ariansystem.net, 0
+ariejan.net, 0
+arielis.com, 0
+ari.ir, 0
+arindo.net, 0
+aris.ge, 0
+aristo.ru, 0
+aritmos.it, 0
+arize.ir, 0
+arkadium.com, 0
+arkena.com, 0
+arkh-edu.ru, 0
+arkrdigital.com, 0
+arkvpn.wang, 0
+arlan.ru, 0
+arlingtonva.us, 0
+arma3.ru, 0
+armene.com, 0
+armor.kiev.ua, 0
+armorymarek.com, 0
+armtorrent.com, 0
+army.gr, 0
+armysoft.es, 0
+arnotts.ie, 0
+aroundprague.cz, 0
+arpuplus.com, 0
+arqatech.com, 0
+arsacia.ir, 0
+arsenal-sib.ru, 0
+ars-grin.gov, 0
+ars.sicilia.it, 0
+art1st.me, 0
+artar.com.sa, 0
+artcom.de, 0
+art-download.org, 0
+artezio.com, 0
+artfoxlive.com, 0
+artinfo.pl, 0
+artinvestment.ru, 0
+artistravel.eu, 0
+artist.ru, 0
+artlife.ru, 0
+artlords.com, 0
+art-oboi.com.ua, 0
+artonline.ru, 0
+artrade.com, 0
+artreal.ru, 0
+artron.net, 0
+artsadd.com, 0
+arturia.com, 0
+arty.space, 0
+asafaweb.com, 0
+asanak.ir, 0
+asanapps.com, 0
+asandk.com, 0
+asanfile.com, 0
+asanwebhost.com, 0
+asaptickets.com, 0
+ascendcorp.com, 0
+ascendi.pt, 0
+asc.es, 0
+asda.gr, 0
+asendiahk.com, 0
+aseugame.com, 0
+ashampoo.net, 0
+ashanet.org, 0
+asheblog.org, 0
+ashiyue.com, 0
+ashkalov.ru, 0
+ashland.edu, 0
+ashmanov.com, 0
+asiafull.com, 0
+asiago.it, 0
+asiainfo.com, 0
+asiainfo.com.cn, 0
+asiangeo.com, 0
+asiaplus.tj, 0
+asiatech.ir, 0
+asicminermarket.com, 0
+asilmedia.uz, 0
+asirikuy.com, 0
+asjyy.com, 0
+askermekani.com, 0
+askform.cn, 0
+asknlearn.com, 0
+askona.ru, 0
+askthepsych.com, 0
+aslenkov.ru, 0
+aslibra.com, 0
+asomin.net, 0
+asp.be, 0
+asphaltgold.de, 0
+aspiremi.com, 0
+asp.krakow.pl, 0
+aspone.me, 0
+aspswelten.de, 0
+asrock.com, 0
+assai.com.br, 0
+asse.fr, 0
+assistbet.co, 0
+assorti-market.ru, 0
+astana.kz, 0
+astana.tk, 0
+astegiudiziarie.it, 0
+asteriskmx.org, 0
+asteroidos.org, 0
+astralnalog.ru, 0
+astrobites.org, 0
+astrocenter.com, 0
+astrogeo.va.it, 0
+astrohled.cz, 0
+astrology.com, 0
+astro-online.ru, 0
+astropro.ru, 0
+astrosage.com, 0
+astroweb.tv, 0
+astrowi.com, 0
+asurgumus.com, 0
+asus.com.cn, 0
+asuscomm.com, 0
+asusmarket.ru, 0
+aswifter.com, 0
+atabank.com, 0
+ataka.tv, 0
+ataksupermarket.ru, 0
+ataland.com, 0
+atanor.ru, 0
+at-consulting.ru, 0
+atel76.ru, 0
+atempurl.com, 0
+atfbooru.ninja, 0
+atg-corp.com, 0
+ath.cx, 0
+athlenda.com, 0
+athome.lu, 0
+atiyehsazan.ir, 0
+atlanta.ua, 0
+atlanticmetro.net, 0
+atm.gob.ec, 0
+atmyplace.ru, 0
+atnf.csiro.au, 0
+atnifty.com, 0
+atol.ru, 0
+atomuniverse.net, 0
+aton.ru, 0
+atpesercizio.it, 0
+atraining.ru, 0
+atrapalo.com, 0
+atraveo.de, 0
+atrsara.ir, 0
+atservers.net, 0
+atso-net.jp, 0
+attijariwafa.com, 0
+attivonetworks.com, 0
+at.ua, 0
+atua.com.br, 0
+atyourservice.com.cy, 0
+atzenbunker.ws, 0
+auca.kg, 0
+auchandirect.fr, 0
+auchan.net, 0
+auchan.ro, 0
+auchan.ru, 0
+auctionata.com, 0
+audacity-forum.de, 0
+audatex.de, 0
+audials.com, 0
+audiklub.cz, 0
+audinate.com, 0
+audiofreaks.nl, 0
+audiophile.org, 0
+audioveda.ru, 0
+auditionpvs.com, 0
+audit-it.ru, 0
+au.edu.tw, 0
+aufe.edu.cn, 0
+augcg.com, 0
+auis.edu, 0
+aulacenter.com, 0
+aulamejor.com, 0
+auna.de, 0
+auna.fr, 0
+auna.it, 0
+auna-multimedia.co.uk, 0
+auna-multimedia.es, 0
+auno.kz, 0
+auooo.com, 0
+aurora-online.ru, 0
+aurubis.com, 0
+aussiebushwalking.com, 0
+austlink.net, 0
+austral.edu.ar, 0
+australia.com, 0
+australianturfclub.com.au, 0
+austrian.com, 0
+author24.ru, 0
+autoalkatresz.hu, 0
+autoazart.ru, 0
+autobam.ru, 0
+autobase.biz, 0
+autobole.com, 0
+autocash.com, 0
+autocensor.com, 0
+autocharge.ir, 0
+autocont.cz, 0
+autofides.ru, 0
+autoflex.hu, 0
+autofoco.com, 0
+autoforum.com.br, 0
+autohausaz.com, 0
+autoimport31.ru, 0
+autojarov.cz, 0
+autojerry.fi, 0
+autoklad.ua, 0
+autoklub.cz, 0
+autolikeviet.vn, 0
+automic.com, 0
+automotivelinux.org, 0
+autonavi.com, 0
+autonavigator.hu, 0
+autoonline.com, 0
+auto-online.ru, 0
+autopapa.ge, 0
+autopartslist.ru, 0
+autopilot.li, 0
+autoradiopc.it, 0
+autoria.biz, 0
+autoshinavrn.ru, 0
+autospares.lv, 0
+autostels.ru, 0
+autostrong-m.by, 0
+autosup.by, 0
+autosup.ru, 0
+autoteile-teufel.at, 0
+autoteile-teufel.de, 0
+autotoolza.ru, 0
+autotown55.ru, 0
+autotravel.ru, 0
+auto-wiki.ru, 0
+autozi.com, 0
+auxiliadorapredial.com.br, 0
+avaclinic.ru, 0
+avalon.ru, 0
+ava.md, 0
+avance-lg.com, 0
+avanset.com, 0
+avantbrowser.com, 0
+avantel.ru, 0
+avantgarde-labs.de, 0
+ava-saz.ir, 0
+avatanplus.com, 0
+avatan.ru, 0
+avatanshop.ru, 0
+avbt123.com, 0
+avcast.org, 0
+avenard.com, 0
+avenuedesvins.fr, 0
+aversi.ge, 0
+avg.club, 0
+av-gk.ru, 0
+avia.lt, 0
+avia.md, 0
+avianca.com.br, 0
+aviapark.com, 0
+aviationsmilitaires.net, 0
+avic.com, 0
+avic.ir, 0
+avis.pl, 0
+avito.ru, 0
+avlab.pl, 0
+avocat.qc.ca, 0
+avokado.kz, 0
+avokzal.ru, 0
+avonstore.com.br, 0
+avosapps.com, 0
+avra.pl, 0
+av.ru, 0
+avselectro-msk.ru, 0
+avselectro.ru, 0
+avsim.net, 0
+avspare.com, 0
+avtobor.uz, 0
+avtograd.ru, 0
+avtomir.ru, 0
+avtonalogi.ru, 0
+avtoopt.com, 0
+avto.pro, 0
+avtovod.org.ua, 0
+avtovokzal-on-line.ru, 0
+avtovokzaly.ru, 0
+avt.pl, 0
+avvalniaz.ir, 0
+awem.com, 0
+awstaticdn.net, 0
+awwapp.com, 0
+axa.cz, 0
+axelname.ru, 0
+axiangblog.com, 0
+axigen.com, 0
+axiomplus.com.ua, 0
+axiomtelecom.com, 0
+axiomus.ru, 0
+axp.dk, 0
+axzchou.com, 0
+ayla.com.cn, 0
+aytopalencia.es, 0
+ayudatpymes.com, 0
+ayurina.net, 0
+ayz.pl, 0
+azarfam.com, 0
+azasrs.gov, 0
+azcuba.cu, 0
+azersu.az, 0
+azfiles.ru, 0
+azfonts.net, 0
+azfonts.ru, 0
+az.gov, 0
+azimuthotels.com, 0
+azinsurance.az, 0
+azoft.com, 0
+az.pl, 0
+azsigorta.az, 0
+azskmg.kz, 0
+aztu.edu.az, 0
+azure.cn, 0
+azure.com, 0
+b0ne.com, 0
+b1.com.cn, 0
+b1-systems.de, 0
+b2cpl.ru, 0
+b2wdigital.com, 0
+b3log.org, 0
+b4value.net, 0
+b5m.com, 0
+b7yy.com, 0
+b8b8.tv, 0
+b8yy.com, 0
+baba-mail.co.il, 0
+babelsberger-filmgymnasium.de, 0
+babilon-m.tj, 0
+babilon-t.tj, 0
+babosik.ru, 0
+babotorrent.com, 0
+babruisk.com, 0
+babyblog.ru, 0
+babylongirls.co.uk, 0
+babypark.nl, 0
+babysfera.ru, 0
+babysitting24.ch, 0
+bacc1688.com, 0
+back2basics-wow.eu, 0
+bad.watch, 0
+bagevent.com, 0
+baggersmag.com, 0
+bagllerina.com, 0
+ba.gov.br, 0
+bahamsafar.com, 0
+bahmut.com, 0
+baicheng.com, 0
+baidu.com, 0
+baidu.nu, 0
+baidupan.com, 0
+baiduyun.me, 0
+baijiahulian.com, 0
+baijindai.com, 0
+baikal-daily.ru, 0
+baiten.cn, 0
+baitv.com, 0
+baixing.cn, 0
+baixou.com.br, 0
+bajiegc.com, 0
+bakemono-subs.com, 0
+bakkerdehouthandel.nl, 0
+baksman.com, 0
+baktelecom.az, 0
+baku2015.com, 0
+baku2017.com, 0
+bakulev.ru, 0
+balancer.ru, 0
+balassiintezet.hu, 0
+balder.se, 0
+baldtruthtalk.com, 0
+baldwins.co.uk, 0
+balgrist.ch, 0
+balitrand.fr, 0
+balkan.ru, 0
+ballbar.cc, 0
+baltikums.eu, 0
+bamada.net, 0
+bamia.ir, 0
+bamilo.com, 0
+bamper.by, 0
+bananacare.ch, 0
+bancogalicia.com.ar, 0
+bancomoc.mz, 0
+bandaancha.eu, 0
+bang5mai.com, 0
+bangcle.com, 0
+banggood.cn, 0
+banglatext.com, 0
+bangnipai.com, 0
+bangqu.com, 0
+banhai.com, 0
+banif.com.mt, 0
+banio.ir, 0
+banjiajia.com, 0
+bank24.uz, 0
+bankbps.pl, 0
+bankcomat.com, 0
+bankersonline.com, 0
+bank.gov.ua, 0
+bankmandiri.co.id, 0
+bankofbeijing.com.cn, 0
+bankofdl.com, 0
+bankowebezprawie.pl, 0
+bankreferatov.ru, 0
+banks.is, 0
+banmaxiaozhen.com, 0
+banob.ir, 0
+banyantree.com, 0
+bao.cn, 0
+baojia.com, 0
+baomitu.com, 0
+baoyuntong.com, 0
+baozou.com, 0
+baozun.cn, 0
+bappedakaltim.com, 0
+baraodemaua.br, 0
+baratz.es, 0
+barbars.ru, 0
+barbioyunu.com.tr, 0
+barcodeberlin.com, 0
+bareknucklepickups.co.uk, 0
+barnacl.es, 0
+barneos22.ru, 0
+barracuda.digital, 0
+bartin.edu.tr, 0
+bartonccc.edu, 0
+bas.co.jp, 0
+basetis.com, 0
+basezap.com, 0
+bashagroplast.com, 0
+bashkortostan.ru, 0
+basis.com, 0
+baskcompany.ru, 0
+basnet.by, 0
+bast.ru, 0
+basu.ac.ir, 0
+batcave.net, 0
+batiaoyu.com, 0
+battlecomics.co.kr, 0
+battleofballs.com, 0
+battleship-game.org, 0
+baykoreans.com, 0
+baykoreans.net, 0
+baysideonline.com, 0
+baza-artistov.ru, 0
+bazakolejowa.pl, 0
+baza.net, 0
+bazarelentrerriano.com.ar, 0
+bazarknig.ru, 0
+bazhongol.com, 0
+bazhuayu.com, 0
+bbdogroup.ru, 0
+bbmundo.com, 0
+bbonfire.com, 0
+bbport.ru, 0
+bbspro.net, 0
+bbvafrances.com.ar, 0
+bbztx.com, 0
+bcactc.com, 0
+bcamath.org, 0
+bcassessment.ca, 0
+bcat.ge, 0
+bcb5.com, 0
+bccto.me, 0
+bcebos.com, 0
+bch.com.cn, 0
+bch.hn, 0
+bcr.gob.sv, 0
+bcr.ro, 0
+bcsh.com, 0
+bcy.net, 0
+bda.bg, 0
+bdear.xyz, 0
+bdew.net, 0
+bd-film.com, 0
+bdimg.com, 0
+bdjc001.com, 0
+bdo.global, 0
+bdpan.com, 0
+bdpu.org, 0
+bdqn.cn, 0
+bdsmclub.pl, 0
+bdsm-russia.com, 0
+bdstatic.com, 0
+bdsu.de, 0
+bea.aero, 0
+beactive.it, 0
+beamr.com, 0
+beam.tv, 0
+bearworld.co.kr, 0
+beate-uhse.com, 0
+beatsound.ru, 0
+beatstage.com, 0
+beautyjagd.de, 0
+bebehouse.com, 0
+bebekoyunu.com.tr, 0
+bebinak.com, 0
+bebio.pl, 0
+becoder.org, 0
+beejournal.ru, 0
+beeline.ru, 0
+beeteco.com, 0
+beevalley.co.jp, 0
+beevideo.tv, 0
+behe.com, 0
+behranoil.com, 0
+behsaa.com, 0
+behsakala.com, 0
+behtarin.tj, 0
+beibei.com, 0
+beiersdorfgroup.com, 0
+beijingtoday.com.cn, 0
+beitaichufang.com, 0
+beitone.com, 0
+bejbynet.cz, 0
+belgazprombank.by, 0
+belgium.be, 0
+belgraviacentre.com, 0
+belhard.com, 0
+belightsoft.com, 0
+belink.com, 0
+belive.ru, 0
+belle8.com, 0
+bellicon.com, 0
+bellini.fr, 0
+bellpotter.com.au, 0
+belorusskiy-trikotazh.ru, 0
+belregion.ru, 0
+beltranssat.by, 0
+be.ma, 0
+bemanicn.com, 0
+bencil.pro, 0
+benedettis.com, 0
+benefitresource.com, 0
+benefitsystems.bg, 0
+benefitsystems.pl, 0
+beneylu.com, 0
+beneyluschool.net, 0
+bengalimusic.in, 0
+bengbeng.com, 0
+bengtsfors.se, 0
+benlai.com, 0
+benlailife.com, 0
+benmi.com, 0
+benq.com.cn, 0
+benrmatthews.com, 0
+beogradskioglasi.com, 0
+beontop.ae, 0
+berbidvps.ir, 0
+berdyansk.net, 0
+beridver.ru, 0
+berito.ru, 0
+berlin-partner.de, 0
+berlitz.com, 0
+berlitz.de, 0
+bernat.im, 0
+bertinaco.com, 0
+bertina.ir, 0
+bertina.us, 0
+berufe-universum.de, 0
+berui.com, 0
+beselettronica.com, 0
+besmart.az, 0
+besmart.kg, 0
+besmart.kz, 0
+besplatnyeprogrammy.net, 0
+bestcake.com, 0
+best-carnival.ru, 0
+besthosting.ua, 0
+bestload.me, 0
+bestmani.ru, 0
+best-price.com, 0
+bestprice.gr, 0
+bestr.it, 0
+bestsdk.com, 0
+bestsecret.at, 0
+bestsecret.ch, 0
+bestsecret.com, 0
+bestsecret.co.uk, 0
+bestsecret.fr, 0
+bestsecret.se, 0
+bestsolution.at, 0
+bestsub.com, 0
+bestv.cn, 0
+bestwallpapers-hd.com, 0
+bestwatch.ru, 0
+bestwinsoft.com, 0
+betaarchive.com, 0
+betaformazione.com, 0
+beta.gouv.fr, 0
+betawoo.com, 0
+betcity.ru.com, 0
+betcityru.com, 0
+bethowen.ru, 0
+bethplanet.ru, 0
+betina.ir, 0
+bet-minute.com, 0
+betonline.ag, 0
+beton.org, 0
+betprisma.com, 0
+betsbc-24.com, 0
+betsbc42.com, 0
+betscsgo.net, 0
+betsdota2.net, 0
+betsgate.com, 0
+bettingbusiness.ru, 0
+bexio.com, 0
+beyond3d.com, 0
+beyond-edge.com, 0
+beyond.pl, 0
+beyondsoft.com, 0
+beyotime.com, 0
+bezaza.ru, 0
+bezko.ru, 0
+bezlimit.ru, 0
+bezrealitky.cz, 0
+bezuzyteczna.pl, 0
+bfarm.de, 0
+bfgames.biz, 0
+bfh.com.cn, 0
+bfi.org, 0
+bfkh.ru, 0
+bfme-modding.ru, 0
+bftcom.com, 0
+bfun.cn, 0
+bfxdata.com, 0
+bfz.hu, 0
+bg.ac.rs, 0
+bgctv.com.cn, 0
+bget.ru, 0
+bgflash.com, 0
+bgforum.ru, 0
+bgreco.net, 0
+bgtop.net, 0
+bgu.co.il, 0
+bgunb.ru, 0
+bgy.com.cn, 0
+bh3.com, 0
+bialystok.pl, 0
+biapy.com, 0
+biba.de, 0
+bible-center.ru, 0
+bibleonline.ru, 0
+bible.ru, 0
+biblio.by, 0
+biblioclub.ru, 0
+biblionix.com, 0
+biboran.com, 0
+bibs.jp, 0
+bichruletka.ru, 0
+bidnews.cn, 0
+bidoo.com, 0
+bieszczady.pl, 0
+bi-file.ru, 0
+bigangwan.com, 0
+bigbangnews.com, 0
+bighost.ir, 0
+bigmir.net, 0
+bignox.com, 0
+bigotti.ro, 0
+bigpicture.ru, 0
+bigquant.com, 0
+bi-group.kz, 0
+biji.io, 0
+bikecitizens.net, 0
+bikefriday.com, 0
+bikemaster.ru, 0
+bikeroar.com, 0
+bikexpert.ro, 0
+bildungscentrum.de, 0
+bildung-schweiz.ch, 0
+biletix.ru, 0
+biletsofit.ru, 0
+bilibili.com, 0
+bilietai.lt, 0
+biligame.com, 0
+bilimal.kz, 0
+billing.ru, 0
+billin.net, 0
+bilp.fr, 0
+bimacarecard.com, 0
+bimm.uz, 0
+bimt.com, 0
+binarisonori.com, 0
+binaryfruit.com, 0
+binary.ninja, 0
+binb.co, 0
+bingo-boom.ru, 0
+bingoenglish.com, 0
+bingostars.com, 0
+bingyan.net, 0
+binomo.com, 0
+bin.sh, 0
+binus.ac.id, 0
+binzhi.com, 0
+biogena.com, 0
+biopodushka.ru, 0
+biotecan.com, 0
+bioware.ru, 0
+bipc.co.jp, 0
+bipdrive.com, 0
+bipskickers.com, 0
+bipush.com, 0
+birdol.com, 0
+birlikhabergazetesi.com, 0
+birmingham.io, 0
+birulevo.net, 0
+biryerde.biz, 0
+bisaboard.de, 0
+bisafans.de, 0
+bisai.tv, 0
+bislink.ir, 0
+bisoft.com.mx, 0
+bistek.com.br, 0
+bistudio.com, 0
+bistu.edu.cn, 0
+bit2.biz, 0
+bitauto.com, 0
+bitballoon.com, 0
+bitcheese.net, 0
+bitcoin.com, 0
+bitcomet.com, 0
+bitgame.ir, 0
+bit-hdtv.com, 0
+bitinn.net, 0
+bitkan.com, 0
+bitmessage.ch, 0
+bitminter.com, 0
+bitnamiapp.com, 0
+bitovi.com, 0
+bitp.kiev.ua, 0
+bitref.com, 0
+bitrix24.com, 0
+bits-handwerkersoftware.de, 0
+bits-hochschule.de, 0
+bitsighttech.com, 0
+bitskins.com, 0
+bittiraha.fi, 0
+bittorrentfiles.org, 0
+bittv.info, 0
+bittylicious.com, 0
+biyao.com, 0
+biysk22.ru, 0
+bizagi.com, 0
+biz.ht, 0
+bizmate.it, 0
+bizovo.ru, 0
+bizright.co.jp, 0
+biz.tm, 0
+bizws.cn, 0
+bjadks.com, 0
+bjd.com.cn, 0
+bjdx.gov.cn, 0
+bjedu.gov.cn, 0
+bjev.com.cn, 0
+bjhd.gov.cn, 0
+bjitic.com, 0
+bjjlb.org.cn, 0
+bjjtgl.gov.cn, 0
+bjkw.gov.cn, 0
+bjnsf.org, 0
+bjpost.com.cn, 0
+bj-tct.com, 0
+bjtu.edu.cn, 0
+bjwh.gov.cn, 0
+bk55.ru, 0
+bk-media.de, 0
+bkool.com, 0
+blablacar.com, 0
+blablacar.net, 0
+blablacode.ru, 0
+blackanddecker.com.br, 0
+blackberries.ru, 0
+blackberrys.ru, 0
+blackbiz.ws, 0
+blackpixel.com, 0
+blackroosteraudio.com, 0
+blackyau.cc, 0
+blafusel.de, 0
+blagovest-moskva.ru, 0
+blanco.com, 0
+blankslate.io, 0
+bl.ee, 0
+blender.org, 0
+bleujour.com, 0
+bl.gov.cn, 0
+blibao.com, 0
+blinko.ru, 0
+blitz-cinestar-bh.ba, 0
+blitz-cinestar.hr, 0
+blitzcorp.org, 0
+blockchainiz.io, 0
+block.io, 0
+bloemert.com, 0
+blogfeng.com, 0
+blogforacure.com, 0
+blogfuntw.com, 0
+bloggersclub.net, 0
+blogin.co, 0
+blogpage.eu, 0
+blogram.net, 0
+blogrebellen.de, 0
+blogshark.net, 0
+blogs-optimieren.de, 0
+blogsyte.com, 0
+blogun.ru, 0
+bloodcat.com, 0
+bloombex-options.com, 0
+blowtopop.net, 0
+blueandwhitehousepubandhkco.com, 0
+bluecomvn.com, 0
+bluefocusgroup.com, 0
+bluegolf.com, 0
+bluemarblegeo.com, 0
+bluemp.net, 0
+blueprintsys.com, 0
+blueprism.com, 0
+bluereader.org, 0
+bluesales.ru, 0
+blueshop.ca, 0
+blueshop.com.tw, 0
+bluesoft.com.br, 0
+bluevine.com, 0
+bluvacanze.it, 0
+bmbgroup.com, 0
+bme.hu, 0
+bm.lv, 0
+bmobile.ne.jp, 0
+bm.ru, 0
+bm-services.com, 0
+bmwclubmoto.ru, 0
+bmw.com.cn, 0
+bnaat.com, 0
+bndes.gov.br, 0
+bnext.com.tw, 0
+bnisecurities.co.id, 0
+bnq.com.cn, 0
+bn.ru, 0
+bnu.edu.cn, 0
+board24.lg.ua, 0
+boardom.io, 0
+boatingmag.com, 0
+bobs.com.br, 0
+bobsfa.com.br, 0
+boce.cn, 0
+bochkameda.net, 0
+bodc.ac.uk, 0
+boeffla.de, 0
+boeingisback.com, 0
+boerde-berufskolleg.de, 0
+boerse-stuttgart.de, 0
+bog.gov.gh, 0
+bohemiaenergy.cz, 0
+boioiong.com, 0
+bokee.net, 0
+boke.io, 0
+bokeyy.com, 0
+bombardir.ru, 0
+bombardo.ru, 0
+bombato.net, 0
+bomberarena.com, 0
+bomc.top, 0
+bome.com, 0
+bonbg.com, 0
+bonding.de, 0
+bondora.com, 0
+bondora.ee, 0
+bonek.de, 0
+bonitasoft.com, 0
+bonjwa.de, 0
+bonniercorp.com, 0
+bonnier.news, 0
+bonree.com, 0
+bonusesfera.com.br, 0
+bookacan.com, 0
+bookandtrip.ru, 0
+bookandtrip.ua, 0
+bookbet23.com, 0
+bookcdn.com, 0
+bookcity.club, 0
+booked.net, 0
+bookinbudapest.com, 0
+bookingpoint.net, 0
+bookmanager.com, 0
+bookmap.com, 0
+bookmate.com, 0
+book.ru, 0
+booksfree4u.tk, 0
+bookshop.ru, 0
+booksrun.com, 0
+booktory.com, 0
+booktype.pro, 0
+book-ye.com.ua, 0
+bookzone.ro, 0
+boombate.com, 0
+boomer.sk, 0
+boosj.com, 0
+boothamschool.com, 0
+bootstrapstudio.io, 0
+borfast.com, 0
+borges.es, 0
+borimed.com, 0
+borjdental.ir, 0
+bork.ru, 0
+bornemann.net, 0
+borsonline.hu, 0
+bose.res.in, 0
+bosscasino.eu, 0
+botevgrad.com, 0
+botnet.cc, 0
+bot.nu, 0
+botreetechnologies.com, 0
+botscript.ir, 0
+botzone.org, 0
+boukal.cz, 0
+bounceme.net, 0
+bouncepingpong.com, 0
+bourky.cz, 0
+boutique-parfums.fr, 0
+bov.com, 0
+boweihe.me, 0
+bowwowinsurance.com.au, 0
+boxcar.io, 0
+boxed.com, 0
+box-evidence.com, 0
+boxueio.com, 0
+boyans.net, 0
+boyhost.cn, 0
+boypoint.de, 0
+boysonyourscreen.org, 0
+boytrap2.net, 0
+bozhong.com, 0
+boziking.com, 0
+bozza.ru, 0
+bplaced.net, 0
+bpmsg.com, 0
+bq.sg, 0
+braas.de, 0
+brainient.com, 0
+brainpad.co.jp, 0
+brainsoftware.org, 0
+brainwave-research-institute.com, 0
+branchable.com, 0
+brandica.ir, 0
+brandos.se, 0
+brankovucinec.com, 0
+bravecollective.com, 0
+braveineve.com, 0
+bravosupermarket.az, 0
+br.com, 0
+br.de, 0
+breachalarm.com, 0
+breakingmuscle.com, 0
+breitling.co.jp, 0
+bremerhaven.de, 0
+bremsspur.org, 0
+bresser.de, 0
+bretty.de, 0
+brewers.com, 0
+brg14.at, 0
+bricker.info, 0
+bricker.ru, 0
+bricofer.it, 0
+bricomarche.pt, 0
+bridgeresort.ru, 0
+brightbox.com, 0
+brightsignnetwork.com, 0
+brightwallpapers.com.ua, 0
+briian.com, 0
+brilliancce.com, 0
+bringo247.ru, 0
+brn.cz, 0
+broadrichness.com, 0
+brocent.com, 0
+brodude.ru, 0
+broekhuis.nl, 0
+brokersjeans.com, 0
+bromium.com, 0
+brot-fuer-die-welt.de, 0
+brown-eyes.ru, 0
+brownpapertickets.com, 0
+brownsugar.tw, 0
+browserdoktor.de, 0
+browserleaks.com, 0
+browshot.com, 0
+brra.bg, 0
+brrc.ru, 0
+bruderste.in, 0
+brudno.com.ua, 0
+brusnika.ru, 0
+bsau.ru, 0
+bscotch.net, 0
+bsi.si, 0
+bsn.ru, 0
+bspb.ru, 0
+bspect.com, 0
+bstester.com, 0
+bstu.ru, 0
+bsuc.cc, 0
+bsuir.by, 0
+bswj.net, 0
+bt2d.com, 0
+btago.com, 0
+btbtdy.com, 0
+btcfans.com, 0
+btcinv4u.com, 0
+btempurl.com, 0
+btfx.net, 0
+btime.com, 0
+btk-fh.de, 0
+btmgg.com, 0
+btn-muenzen.de, 0
+btpeer.com, 0
+btrans.by, 0
+btsearch.co, 0
+btsearch.me, 0
+btydt.com, 0
+buaa.edu.cn, 0
+bubi.cn, 0
+bucek.name, 0
+buchmann.ch, 0
+bucketlist.org, 0
+buct.edu.cn, 0
+budacode.com, 0
+bud-stroynoy.ru, 0
+buffer.com, 0
+bufs.ac.kr, 0
+bugclose.com, 0
+bugetul.ro, 0
+bugscan.net, 0
+bugtags.com, 0
+bugunneleroldu.com, 0
+buhaoting.com, 0
+buhgalter911.com, 0
+buildabazaar.com, 0
+builder.eu, 0
+builder.hu, 0
+builds.io, 0
+buildyourownguitar.com.au, 0
+bukaba.com, 0
+bukainfo.com, 0
+buklya.com, 0
+bukmacherskie.com, 0
+bulkinkeys.com, 0
+bulkreefsupply.com, 0
+bulletsend.com, 0
+bultannews.com, 0
+bumimi.com, 0
+bundesliga.at, 0
+bunkus.org, 0
+bunz.com, 0
+bupa.com.sa, 0
+bupt.edu.cn, 0
+burenqi.com, 0
+burgerfuel.com, 0
+burgessyachts.com, 0
+burjauto.com, 0
+burningshed.com, 0
+busfor.com, 0
+busfor.pl, 0
+busfor.ru, 0
+business4all.ca, 0
+business-gazeta.ru, 0
+businesshemden.com, 0
+businessinfo.cz, 0
+business-internet.biz, 0
+businessportal.gr, 0
+business-software.com, 0
+businessstudio.ru, 0
+businesstoday.co.ke, 0
+busmap.vn, 0
+busqueda-local.es, 0
+bussoladoinvestidor.com.br, 0
+busybeeschildcare.co.uk, 0
+buyalenovo.com, 0
+buycheapr.com, 0
+buyex.ir, 0
+buyunder500.in, 0
+buzzerbeater.com, 0
+buzzhire.co, 0
+bvbcode.com, 0
+bwt-group.com, 0
+bybbs.org, 0
+byb.cn, 0
+bydauto.com.cn, 0
+bydgoszcz.pl, 0
+byethost10.com, 0
+byethost11.com, 0
+byethost12.com, 0
+byethost13.com, 0
+byethost14.com, 0
+byethost15.com, 0
+byethost16.com, 0
+byethost17.com, 0
+byethost18.com, 0
+byethost22.com, 0
+byethost24.com, 0
+byethost32.com, 0
+byethost3.com, 0
+byethost7.com, 0
+byethost8.com, 0
+byethost9.com, 0
+byfen.com, 0
+byggahus.se, 0
+bygmax.dk, 0
+byside.com, 0
+bytecdn.cn, 0
+byte.fm, 0
+bytemag.ru, 0
+bz-bx.net, 0
+bzgame.cc, 0
+bzs.su, 0
+c2lab.ovh, 0
+c4dcn.com, 0
+c7sky.com, 0
+c9users.io, 0
+caac.net, 0
+caa.edu.cn, 0
+caat.org.uk, 0
+cableforum.co.uk, 0
+cabovillas.com, 0
+cadict.net, 0
+cadstudio.ru, 0
+cafe24.com, 0
+cafekado.ir, 0
+cafetadris.com, 0
+cafeyun.com, 0
+cafiu.org.cn, 0
+cai310.cn, 0
+cai88.com, 0
+caict.ac.cn, 0
+caijing.com.cn, 0
+cailianpress.com, 0
+cailiaoren.com, 0
+caimomo.com, 0
+cainiaoapp.cn, 0
+caisan.io, 0
+caixin.com, 0
+caknun.com, 0
+caktusgroup.com, 0
+calcudoku.org, 0
+calculator-imt.com, 0
+calculatorpi.com, 0
+caldera.com, 0
+californiasciencecenter.org, 0
+callbackhunter.com, 0
+calligra.org, 0
+callnote.net, 0
+calmradio.com, 0
+caltech.edu, 0
+calvarycare.org.au, 0
+calweb.com, 0
+calyptix.com, 0
+camayak.com, 0
+cambiaresearch.com, 0
+cambiaste.com, 0
+cambio.se, 0
+cambodia-airports.aero, 0
+cambsed.net, 0
+camelia.lt, 0
+camellia-sinensis.com, 0
+cameron.edu, 0
+cameronsino.com, 0
+camisetanerd.com, 0
+camlab.co.uk, 0
+camonster.com, 0
+campaignmaster.co.uk, 0
+camping.info, 0
+camping-penhoat.com, 0
+camptocamp.com, 0
+campusgifts.co.uk, 0
+campyokwe.org, 0
+canaan.io, 0
+canadianarchitect.com, 0
+cancer.gov.co, 0
+cancerimagingarchive.net, 0
+candsleads.com, 0
+candy.it, 0
+canfreee.com, 0
+cang.com, 0
+canliligtvseyret.org, 0
+canoe.ie, 0
+canpars.ca, 0
+cantr.net, 0
+can-tv.cn, 0
+can.ua, 0
+caobai.com, 0
+caogen8.co, 0
+caoliuporn.com, 0
+capeanalytics.com, 0
+capitalmadrid.com, 0
+capital-match.com, 0
+capitalsports.de, 0
+captainbook.gr, 0
+captaincontrat.com, 0
+captainverify.com, 0
+captiv8.io, 0
+captivoice.com, 0
+captureone.cn, 0
+caracter.ru, 0
+carambis.com, 0
+carambis.ru, 0
+caravaning-univers.com, 0
+cardcastgame.com, 0
+cardmarket.eu, 0
+cardpay.com, 0
+cardq.co.kr, 0
+card-sharing.ru, 0
+cardwinner.com, 0
+careerindex.jp, 0
+career.lk, 0
+careesma.in, 0
+carefy.com, 0
+careiphone.com, 0
+carfix.ru, 0
+cargeek.ir, 0
+carhire.ie, 0
+caricatura.ru, 0
+caritas.at, 0
+carlab.co.kr, 0
+carnoc.com, 0
+carpediem.cd, 0
+carptime.ru, 0
+carrefourinternet.com, 0
+carreirafashion.com.br, 0
+carsbase.com, 0
+cars.kg, 0
+cars-promo.com, 0
+carta.ro, 0
+carteblanchepartenaires.fr, 0
+cartft.com, 0
+cartridgesave.co.uk, 0
+carus-verlag.com, 0
+car.uz, 0
+casadocodigo.com.br, 0
+casaley.com.mx, 0
+casalomacollege.edu, 0
+cas.cz, 0
+case24.it, 0
+caseloadmanager.com, 0
+cash24.ru, 0
+cashlai.com, 0
+casicloud.com, 0
+casinuevo.net, 0
+caspian.aero, 0
+cass.cn, 0
+castavote.it, 0
+casting360.com, 0
+castrol-original.ru, 0
+casualgamers.club, 0
+catalinahub.net, 0
+catalysts.cc, 0
+catfan.me, 0
+catharinehill.com.br, 0
+cathay-ins.com.cn, 0
+catholic.edu.au, 0
+catie.ac.cr, 0
+catlin.edu, 0
+cattry.com, 0
+catwalkwholesale.com, 0
+cau.edu.cn, 0
+causeway.com, 0
+cavinnash.at, 0
+cawi.fr, 0
+caykaragazetesi.com, 0
+cayneshousewares.com, 0
+cazin.net, 0
+cba.pl, 0
+cbbank.com, 0
+cbc.rs, 0
+cbda.cn, 0
+cbk.waw.pl, 0
+c-brains.jp, 0
+cbri.res.in, 0
+cbsi.com, 0
+cbsig.net, 0
+ccav1.com, 0
+ccav1.me, 0
+ccav.info, 0
+ccb.com, 0
+ccc.ac, 0
+cccamonde.com, 0
+cccampass.com, 0
+ccc.de, 0
+cccm.com, 0
+cccpmo.com, 0
+cccyun.cc, 0
+ccdi.gov.cn, 0
+cce.cz, 0
+ccf.com.cn, 0
+ccgenbr.com.br, 0
+ccit.js.cn, 0
+cclonline.com, 0
+ccpph.com.cn, 0
+cctin.com, 0
+cctld.ru, 0
+cdbbank.az, 0
+cdc.im, 0
+cdcoslm.com, 0
+cdeway.com, 0
+cdfgj.gov.cn, 0
+cdischina.com, 0
+cdmarf.ru, 0
+cdm.org, 0
+cdn3x.com, 0
+cdnbetcity.com, 0
+cdrinfo.pl, 0
+cds.spb.ru, 0
+cdu.edu.ua, 0
+cdut.edu.cn, 0
+cdvcloud.com, 0
+cdvpodarok.ru, 0
+cea.gov.cn, 0
+ceair.com, 0
+ceamadeus.com, 0
+cecb2b.com, 0
+ce.cn, 0
+cedarhd.com, 0
+cedrus.hu, 0
+ceeji.net, 0
+cefa.com, 0
+ce.gov.br, 0
+ceh9.tv, 0
+cehome.com, 0
+cei.com.cn, 0
+cekid.com, 0
+ceknito.cz, 0
+ceknito.sk, 0
+celakaja.lv, 0
+celemony.com, 0
+celera-group.com, 0
+celesc.com.br, 0
+celignes.com, 0
+cellstat.net, 0
+celulardireto.com.br, 0
+censhare.com, 0
+censys.io, 0
+centaline.com.cn, 0
+center-inform.ru, 0
+centeva.com, 0
+cention.se, 0
+centiumsoftware.com, 0
+centminmod.com, 0
+centracom.com, 0
+centralclubs.com, 0
+centralhealth.com.hk, 0
+centralmenu.com.pt, 0
+centralpark.com, 0
+centralstationcrm.net, 0
+centredeliquidationduquebec.com, 0
+centreon.com, 0
+centriohost.com, 0
+centroimpiego.it, 0
+centrora.com, 0
+centrzaimov.ru, 0
+cenynadne.sk, 0
+cephaiti.ht, 0
+cephastanesi.org, 0
+ceph.org.cn, 0
+ceramique.com, 0
+cerfrance.fr, 0
+certbase.de, 0
+certissim.com, 0
+certitudes.org, 0
+cert.org.cn, 0
+cesan.com.br, 0
+cesanta.com, 0
+cesareox.com, 0
+cesco.co.kr, 0
+ces.edu.uy, 0
+cesurformaciononline.com, 0
+cetc.com.cn, 0
+cetera.ru, 0
+ceu.edu.ph, 0
+ceva.com, 0
+ceve-market.org, 0
+cev.lu, 0
+cez.cz, 0
+cez.ro, 0
+cezurity.com, 0
+cf2016.ru, 0
+cfdsupport.com, 0
+cfei.net, 0
+cfldcn.com, 0
+cflex.com, 0
+cfpd.org.cn, 0
+cg976.fr, 0
+cgilfe.it, 0
+cgil.it, 0
+cgpersia.ru, 0
+cgs.gov.cn, 0
+cgu.edu.tw, 0
+chachazhan.com, 0
+chacuo.net, 0
+chadis.com, 0
+chaicp.com, 0
+chainfire.eu, 0
+chains.cc, 0
+chainsea.com.tw, 0
+chain.so, 0
+chaiwubi.com, 0
+chalmers.se, 0
+chal-tec.com, 0
+chamonet.com, 0
+championat.asia, 0
+championscubestore.com, 0
+chamwings.com, 0
+chancheng.gov.cn, 0
+chandashi.com, 0
+chanet.com.cn, 0
+changan.com.cn, 0
+changba.com, 0
+change38.ch, 0
+changeip.net, 0
+changingedu.com, 0
+changyou.com, 0
+chanjet.com, 0
+channeli.in, 0
+chanpin100.com, 0
+chaosforge.org, 0
+chaoshanw.cn, 0
+chapaiming.com, 0
+charogh.com, 0
+charter.com, 0
+chartrank.com, 0
+chat2desk.com, 0
+chataoke.com, 0
+chat-brasil.com, 0
+chatcity.de, 0
+chat-pt.com, 0
+chatruletka.com, 0
+chattermill.io, 0
+chatti.de, 0
+chaturbate.com.br, 0
+chatworld.de, 0
+chaxuntu.com, 0
+chb.com.tw, 0
+chcivyhodnejsienergie.cz, 0
+chdbits.vip, 0
+chd.edu.cn, 0
+che300.com, 0
+cheapjerseysfree.com, 0
+cheatcodesiosandroid.com, 0
+cheatorhackgames.com, 0
+cheatsandhack.info, 0
+cheatsgamehack.info, 0
+chebaba.com, 0
+chebao.com.cn, 0
+checknow.co.uk, 0
+cheers.com.tw, 0
+chefpartyswinger.com, 0
+cheladmin.ru, 0
+chelcenter.ru, 0
+chelm.pl, 0
+chel.ru, 0
+chem99.com, 0
+chemistry.org.tw, 0
+chemweb.com, 0
+chengduair.cc, 0
+chengdu.cn, 0
+chengniu.com, 0
+chengzivr.com, 0
+chennaihalls.in, 0
+chenxingweb.com, 0
+chenyudong.com, 0
+cherinfo.ru, 0
+chernigiv-rada.gov.ua, 0
+cheros.ru, 0
+chers.com.ua, 0
+cherubicsoft.com, 0
+cheryjaguarlandrover.com, 0
+chesspuzzle.net, 0
+chess-samara.ru, 0
+chevy-clan.ru, 0
+chexch.com, 0
+chexiu.cn, 0
+chgaki.ru, 0
+chgik.ru, 0
+chiapas.gob.mx, 0
+chia.ua, 0
+chickenkiller.com, 0
+chicrank.ir, 0
+childdevelop.com.ua, 0
+chiletrabajos.cl, 0
+chillglobal.com, 0
+chinaar.com, 0
+chinabluemix.net, 0
+chinacache.com, 0
+chinacardpos.com, 0
+china-cba.net, 0
+chinachugui.com, 0
+chinacloudapi.cn, 0
+chinacloudapp.cn, 0
+chinacloudsites.cn, 0
+china.com.cn, 0
+chinadaily.com.cn, 0
+chinadance.cn, 0
+chinaeducationexpo.com, 0
+chinaemail.cn, 0
+china-entercom.com, 0
+chinahr.com, 0
+chinahrt.com, 0
+chinamobile.com, 0
+chinancce.com, 0
+chinanetcenter.com, 0
+chinaoct.com, 0
+chinaopple.com, 0
+chinapiwei.com, 0
+chinaports.com, 0
+china-post-track.com, 0
+chinasalestore.com, 0
+china-shftz.gov.cn, 0
+chinaums.com, 0
+chinaunicom.cn, 0
+chinayasha.com, 0
+chineseall.cn, 0
+chinesecio.com, 0
+chinesegamer.net, 0
+chinesetest.cn, 0
+chinlingo.com, 0
+chint.com, 0
+chipfind.ru, 0
+chipic.ir, 0
+chitaitext.ru, 0
+chither.com, 0
+chkaja.com, 0
+chnlanker.com, 0
+chocolissimo.de, 0
+choices360.com, 0
+choisirsonfioul.fr, 0
+chongmoa.com, 0
+chopacho.ru, 0
+chordshub.com, 0
+chorus.ai, 0
+chrdk.ru, 0
+chrihani.com, 0
+chrishogan360.com, 0
+christenenvoorisrael.nl, 0
+christianliebel.com, 0
+christian-luetgens.de, 0
+chronicle.co.zw, 0
+chroniclejournal.com, 0
+chsu.ru, 0
+chtodelat.com, 0
+chuangkit.com, 0
+chuangkoo.com, 0
+chuanke.com, 0
+chu-dijon.fr, 0
+chudobilet.ru, 0
+chudu24.com, 0
+chuhai.edu.hk, 0
+chuhai.hk, 0
+chujianapp.com, 0
+chunk.com.cn, 0
+chuvsu.ru, 0
+chuyhiep.net, 0
+chv.ua, 0
+chytryhonza.cz, 0
+chzu.edu.cn, 0
+ci123.com, 0
+cib.com.cn, 0
+ci-bi.ru, 0
+cicams.ac.cn, 0
+cicon.ru, 0
+cidcode.net, 0
+ciencia-ficcion.com, 0
+ciftlikbank.com, 0
+cifttik.com, 0
+cig.com.cn, 0
+cik.bg, 0
+cimb.com, 0
+cimex.com.cu, 0
+cimt.de, 0
+cindasc.com, 0
+cinecoffee.com, 0
+cinemacity.hu, 0
+cinemapark.ru, 0
+cinematik.net, 0
+cinestarcinemas.rs, 0
+cinoherniklub.cz, 0
+ciob.org, 0
+cipcipstore.it, 0
+ciper.cl, 0
+cipf.es, 0
+circuitodejerez.com, 0
+circulaire-en-ligne.ca, 0
+cirici.com, 0
+ciscoexam.online, 0
+cislink.com, 0
+citadele.lt, 0
+citationprocessingcenter.com, 0
+cit.edu.tw, 0
+citicsf.com, 0
+citictel-cpc.com, 0
+citrio.com, 0
+cits.br, 0
+citsgbt.com, 0
+cittadellasalute.to.it, 0
+cityads.com, 0
+citygf.com, 0
+city.kharkov.ua, 0
+cityshop.com.cn, 0
+citytaxi.az, 0
+city-wohnen.de, 0
+ciu20.org, 0
+ciuvo.com, 0
+civey.com, 0
+civilavia.info, 0
+cizgi.com.tr, 0
+cjh.com.cn, 0
+cjlu.edu.cn, 0
+cjwsjy.com.cn, 0
+ck12info.org, 0
+ck180.com, 0
+ckclouds.com, 0
+ck-modelcars.de, 0
+clammr.com, 0
+clang.cn, 0
+clans.de, 0
+clansweb.com, 0
+clarin.com, 0
+clark-chen.com, 0
+clarocloud.co.za, 0
+classicalarchives.com, 0
+classic-gaming.net, 0
+classit.ro, 0
+classmethod.info, 0
+clayboxltd.com, 0
+clayesmore.com, 0
+cleanenergywire.org, 0
+cleanlinesurf.com, 0
+cleanpix.com, 0
+cleanvoice.ru, 0
+clearcast.co.uk, 0
+clearch.org, 0
+clear-code.com, 0
+clearscore.com, 0
+clearwebstats.com, 0
+clemensotto.com, 0
+cles.jp, 0
+cleveroad.com, 0
+cleversite.ru, 0
+cleversubtitles.ru, 0
+clewm.net, 0
+clickad.info, 0
+clickers.info, 0
+clickpayment.ir, 0
+click.uz, 0
+clickview.com.au, 0
+cliclavoroveneto.it, 0
+client-shop-logistics.ru, 0
+client.xzn.ir, 0
+cli.im, 0
+clilk.com, 0
+climate-kic.org, 0
+clinicbuddy.com, 0
+clio.it, 0
+clip.af, 0
+clippersync.com, 0
+clir.org, 0
+clockshop.ru, 0
+cloud4you.biz, 0
+cloud4y.ru, 0
+cloud86.cn, 0
+cloudapp.net, 0
+cloudcampus.cc, 0
+cloudcc.com, 0
+clouddn.com, 0
+cloudfire.ir, 0
+cloudfront.net, 0
+cloud.geek.nz, 0
+cloudin.cn, 0
+cloudlinux.com, 0
+cloudme.com, 0
+cloud-mine.online, 0
+cloudns.cc, 0
+cloudonaut.io, 0
+cloudparse.com, 0
+cloudrexx.com, 0
+cloudrino.net, 0
+cloudron.io, 0
+cloudsite.ir, 0
+cloudsmart.lu, 0
+cloudsms.com.ng, 0
+cloudsplus.com.cn, 0
+clouds.tf, 0
+cloudtv.bz, 0
+cloudvhost.cn, 0
+cloudware.jp, 0
+cloudxink.com, 0
+club3.cf, 0
+clubdesavantages.fr, 0
+clubs1.bg, 0
+clutchpoints.com, 0
+clzg.cn, 0
+cmaritime.com.cn, 0
+cmbi.com.hk, 0
+cmc.gv.ao, 0
+cmcnu.or.kr, 0
+cmeiwei.com, 0
+cmfchina.com, 0
+cmgame.com, 0
+cmgine.net, 0
+cml.pt, 0
+cmlt.ru, 0
+cmonitor.pl, 0
+cmscafe.ru, 0
+cms.gov.af, 0
+cms-guide.com, 0
+cm-sintra.pt, 0
+cmsky.com, 0
+cmtt.ru, 0
+cmu.ac.th, 0
+cmu.edu, 0
+cmu-edu.eu, 0
+cnaidai.com, 0
+cnbb.com.cn, 0
+cnblogs.com, 0
+cnbluebox.com, 0
+cncf.io, 0
+cndhl.com, 0
+cnexps.com, 0
+cnfeol.com, 0
+cngaosu.com, 0
+cngold.org, 0
+cn-healthcare.com, 0
+cnhnb.com, 0
+cnhubei.com, 0
+cnic.cn, 0
+cnki.net, 0
+cnkrl.cn, 0
+cnl.sk, 0
+cnl.su, 0
+cnl.tv, 0
+cnoa.cn, 0
+cnooc.com.cn, 0
+cnool.net, 0
+cnpatent.com, 0
+cnpq.br, 0
+cnprint.org, 0
+cnpzhe.com, 0
+cnr.cn, 0
+cnseay.com, 0
+cnsecer.com, 0
+cnshb.ru, 0
+cnsuning.com, 0
+cnsuning.com.hk, 0
+cntaiping.com, 0
+cnte.tn, 0
+cnt.my, 0
+cntraveller.ru, 0
+cntv.cn, 0
+cnxct.com, 0
+cnx-software.com, 0
+coaching-foot.com, 0
+coap.kz, 0
+cocha.com, 0
+cocobongo.com, 0
+cocoking.info, 0
+cocoleech.com, 0
+codacy.com, 0
+co.de, 0
+codeaurora.org, 0
+codebeer.ru, 0
+codebox.ir, 0
+codecanyonwp.com, 0
+codecasts.com.br, 0
+codeclic.com, 0
+codeforge.cn, 0
+codeforge.com, 0
+codefresh.io, 0
+code-industry.net, 0
+codelife.me, 0
+codemao.cn, 0
+coderknock.com, 0
+coder-note.com, 0
+code-route.info, 0
+coding-academy.fr, 0
+coding.io, 0
+coduka.de, 0
+coffee-butik.ru, 0
+cofina.pt, 0
+cofm.es, 0
+cofpo.org, 0
+coi.cz, 0
+coinflux.com, 0
+coinjar.com, 0
+coinjar.com.au, 0
+coinkeeper.me, 0
+coinpalace.io, 0
+coinsbank.com, 0
+coins.su, 0
+coinsup.com, 0
+colasoft.com, 0
+colasoft.com.cn, 0
+colbeh.ir, 0
+coldline.hu, 0
+colettehq.com, 0
+colibri.io, 0
+collabora.com, 0
+collaboraoffice.com, 0
+collaborative.org, 0
+collect.ai, 0
+collectivefab.com, 0
+collegeblondin.qc.ca, 0
+collegemarching.com, 0
+collibra.com, 0
+collsk12.org, 0
+colobot.info, 0
+coloproperty.com, 0
+color.com, 0
+colornumbers.ru, 0
+color-print39.ru, 0
+colourlife.com, 0
+colproba.org.ar, 0
+coma.lv, 0
+com.be, 0
+combowombo.ru, 0
+combr.ru, 0
+comein.sk, 0
+comeitaliani.it, 0
+comelite-arch.com, 0
+comelz.com, 0
+comeremcasa.com, 0
+comfone.com, 0
+comicool.cn, 0
+comics-porno.ru, 0
+com.kz, 0
+comlan.com, 0
+comli.com, 0
+comlu.com, 0
+commaster.net, 0
+commcenter.es, 0
+commerceduniya.com, 0
+commonhealth.com.tw, 0
+commonkindness.com, 0
+commotionwireless.net, 0
+comm-tec.de, 0
+communications.support, 0
+compagniedumontblanc.fr, 0
+companeo.be, 0
+companeo.com, 0
+compariimobiliare.ro, 0
+compass.education, 0
+compassplus.ru, 0
+complexityexplorer.org, 0
+comptable-en-ligne.fr, 0
+compulab.co.il, 0
+compumatrix.co, 0
+compumatrix.us.com, 0
+compumed.com.my, 0
+compusoluciones.com, 0
+computerads.ir, 0
+computershop.pisa.it, 0
+computrabajo.com, 0
+computrabajo.com.hn, 0
+com.se, 0
+comss.ru, 0
+comstats.de, 0
+comtech.com.cn, 0
+comtradeshop.com, 0
+comune.siena.it, 0
+comxa.com, 0
+conanwiki.org, 0
+concordemed.com, 0
+conde.com, 0
+condenast.co.uk, 0
+condenast.ru, 0
+confessionsofahomeschooler.com, 0
+confmaster.net, 0
+conglinnet.com, 0
+congm.in, 0
+connectedly.com, 0
+connectify.com, 0
+connectify.me, 0
+co.no, 0
+conpoint.com, 0
+conseil-config.com, 0
+conseq.cz, 0
+conservatoriotorino.gov.it, 0
+construction411.com, 0
+consulimus.de, 0
+consultant.ru, 0
+consumerscompare.org, 0
+contabo.host, 0
+contactlab.com, 0
+conta.mobi, 0
+contao.org, 0
+conte.by, 0
+content-cooperation.com, 0
+continentalcarbonic.com, 0
+contractiq.com, 0
+contragents.ru, 0
+controlerp.org, 0
+controletechniquegratuit.com, 0
+converter.cz, 0
+convex.ru, 0
+coobar.com, 0
+coodoor.com, 0
+coohua.com, 0
+cook-key.de, 0
+cook-key.it, 0
+coolapk.com, 0
+coolapkmarket.com, 0
+coolbaby.ru, 0
+coolion.com, 0
+coolnull.com, 0
+coolyun.com, 0
+coop-game.com, 0
+coop.py, 0
+coore.jp, 0
+copasa.com.br, 0
+copel.net, 0
+copiny.com, 0
+coppenrath-wiese.de, 0
+copr.cn, 0
+co.pt, 0
+copybet.com, 0
+copy.sh, 0
+copytrack.com, 0
+coracle.com, 0
+coradir.com.ar, 0
+coral-club.com, 0
+cordoba.es, 0
+corecodec.com, 0
+coreinfrastructure.org, 0
+corelan.be, 0
+corenominal.org, 0
+corepacks.com, 0
+core-rpg.net, 0
+cornell.edu, 0
+corrections.govt.nz, 0
+corsocomo.com, 0
+cortona3d.com, 0
+co.ru, 0
+cosmobase.ru, 0
+cosmos.ru, 0
+cotonti.com, 0
+counsellingresource.com, 0
+countryclubworld.com, 0
+countrygarden.com.cn, 0
+couponkun.jp, 0
+coursinformatiquepdf.com, 0
+cowlevel.net, 0
+co.za, 0
+cp247.net, 0
+cpanel.ir, 0
+cpapd.org.cn, 0
+cp.com.cn, 0
+cpc.vn, 0
+cpic.com.cn, 0
+cplusplus.me, 0
+cpmchina.co, 0
+cpnv.ch, 0
+cpoc.cn, 0
+cppcc.gov.cn, 0
+cprsweb.com, 0
+cpsite.ru, 0
+cpygames.com, 0
+cq118.com, 0
+cqgh.org, 0
+cqjtu.edu.cn, 0
+cqnews.net, 0
+cqsq.com, 0
+cqtimes.cn, 0
+cqu.edu.cn, 0
+cqupt.edu.cn, 0
+cr911.ru, 0
+cra0vision.net, 0
+crackberry.com, 0
+crack-cheat.ru, 0
+crackhogar.com, 0
+crackingking.com, 0
+craftmann.ru, 0
+crate.io, 0
+craym.eu, 0
+crazycen.com, 0
+crazyguyonabike.com, 0
+crazyhotseeds.com, 0
+crb-dnr.ru, 0
+crcc.cn, 0
+crc.com.cn, 0
+crc.com.hk, 0
+crdclub.su, 0
+creagames.com, 0
+creartest.com, 0
+createjs.cc, 0
+createsurvey.ru, 0
+creativcdn.net, 0
+credit2go.cn, 0
+credit-card.ru, 0
+creditchina.gov.cn, 0
+creditolo.de, 0
+crediton.ge, 0
+creditonline.hu, 0
+crediton.lv, 0
+crefal.edu.mx, 0
+cretaforce.gr, 0
+crevalue.cn, 0
+cribs.me, 0
+cri.cn, 0
+crictracker.com, 0
+crimea.com, 0
+crimea.ru, 0
+criogenizado.com, 0
+crisp.im, 0
+crm-simple.com, 0
+crmtipoftheday.com, 0
+crn.ru, 0
+croc-informatique.fr, 0
+croc.ru, 0
+crocus-hall.ru, 0
+croix-rouge.fr, 0
+cronista.com, 0
+cronobet.com, 0
+cronodeal.ch, 0
+croppola.com, 0
+cross-area.com, 0
+crouse.org, 0
+crous-toulouse.fr, 0
+crowdtangle.com, 0
+crsc.cn, 0
+crt.ru, 0
+crtslt.com, 0
+cruisingworld.com, 0
+cruzados.cl, 0
+crypters.ru, 0
+cryptogods.net, 0
+cryptomator.org, 0
+cryptshare.com, 0
+crystalvoice.sg, 0
+cs12333.com, 0
+csa.fr, 0
+csair.com, 0
+csbaonline.org, 0
+cscec.com, 0
+csc.fi, 0
+cs.co.nz, 0
+csdb.cn, 0
+csd.org.tw, 0
+cse.ru, 0
+csf.fr, 0
+csfunds.com.cn, 0
+csg.cn, 0
+csgoblaze.com, 0
+csgo.com, 0
+csgodestroy.com, 0
+csgofast.com, 0
+csgo-fate.ru, 0
+csgogamers.com, 0
+csgohouse.org, 0
+csgola.com, 0
+csgoloot.com, 0
+csgoshop.com, 0
+csgo.tm, 0
+csh.org.tw, 0
+cshr.com.cn, 0
+cshrss.gov.cn, 0
+cs-htc.com, 0
+csicr.cz, 0
+csie.org, 0
+csi.it, 0
+csi-net.it, 0
+cska.ru, 0
+cskin.net, 0
+csldbz.gov.cn, 0
+cslg.cn, 0
+csmania.ru, 0
+csna.cn, 0
+csob.sk, 0
+csopa.hu, 0
+csrc.ac.cn, 0
+csrc.gov.cn, 0
+csroller.ru, 0
+cssbuy.com, 0
+csscompressor.com, 0
+csserv.ru, 0
+csswg.org, 0
+cstnet.cn, 0
+c-stud.ru, 0
+csumentor.edu, 0
+csvt.qc.ca, 0
+csvw.com, 0
+ct10000.com, 0
+ct8.pl, 0
+ctfeshop.com.cn, 0
+ctfmall.com, 0
+cto1.ru, 0
+ctolib.com, 0
+ctrip.com, 0
+ctrlworks.com, 0
+c-t-s.ru, 0
+ctx.zone, 0
+cubalan.com, 0
+cubeisland.de, 0
+cubingchina.com, 0
+cuc.ac.jp, 0
+cuca.co.ao, 0
+cuccfree.com, 0
+cuc.edu.cn, 0
+cu-elbayadh.dz, 0
+cuentosparadormir.com, 0
+cuevana-movil.com, 0
+cuhk.edu.hk, 0
+cuintouch.com, 0
+cuiqingcai.com, 0
+cuizituan.com, 0
+cuk.pl, 0
+cultizone.fr, 0
+cu.ma, 0
+cumt.edu.cn, 0
+cupcakeproject.com, 0
+cupet.cu, 0
+cup.ir, 0
+cure53.de, 0
+curitzjt.cf, 0
+currencyrate.today, 0
+curriculum-web.com, 0
+curs.md, 0
+cursomeca.com, 0
+cuspy.org, 0
+customs4u.com, 0
+customs.ru, 0
+cuteness.com, 0
+cutestat.com, 0
+cutv.com, 0
+cv.ee, 0
+cv.lv, 0
+cvmc.org, 0
+cvonline.lt, 0
+cvp.com, 0
+cvte.com, 0
+cvut.cz, 0
+cw1.tw, 0
+cwbook.com.tw, 0
+cw.com.tw, 0
+cwdsellier.com, 0
+cwt-online.com.cn, 0
+cx580.com, 0
+cxcyds.com, 0
+cxhxrz.com, 0
+cxstar.com, 0
+cybercrime.gov.ua, 0
+cyberdefense.jp, 0
+cyberduck.io, 0
+cybergun.it, 0
+cyberoam.com, 0
+cyberprofs.com, 0
+cybersitter.com, 0
+cybo.com, 0
+cyclestore.com.es, 0
+cyclestore.co.uk, 0
+cycleworld.com, 0
+cycloneshockey.com, 0
+cycu.edu.tw, 0
+cyklobazar.cz, 0
+cyolito.com, 0
+cyotek.com, 0
+cyscorpions.com, 0
+cytbj.com, 0
+cyut.edu.tw, 0
+czcg.com, 0
+czech.cz, 0
+czechgames.com, 0
+czech-games.net, 0
+czechia.com, 0
+cz-pes.cz, 0
+czsmk.com, 0
+czxiu.com, 0
+d2fan.com, 0
+dabtc.com, 0
+dactylocours.com, 0
+dadaabc.com, 0
+dadacps.com, 0
+dadasoft.net, 0
+daddyleagues.com, 0
+dadget.ru, 0
+daewooenc.com, 0
+daewoong.co.kr, 0
+dafabet.com, 0
+dafangya.com, 0
+dafangya.com.cn, 0
+daft.ie, 0
+dahe.cn, 0
+dahuangbbs.com, 0
+dahuatech.com, 0
+dahuitu.net, 0
+daichuqu.com, 0
+daily-movies.ch, 0
+dailynews.co.th, 0
+dailystandard.com, 0
+dairyfarmgroup.com, 0
+dajia365.com, 0
+dajie.com, 0
+dalasterisk.com, 0
+dalcroze.ch, 0
+dalegames.com, 0
+daling.com, 0
+dalinuosi.lt, 0
+damailicai.com, 0
+dameiketang.com, 0
+damochka.ru, 0
+danar.ru, 0
+danbistore.com, 0
+danceconvention.net, 0
+daneiakartes.info, 0
+danet.vn, 0
+dangbei.com, 0
+dangdang.com, 0
+danilova.pro, 0
+dankstop.com, 0
+dan.me.uk, 0
+danmuji.cn, 0
+dannysite.com, 0
+dansezza.ru, 0
+daoiqi.com, 0
+daojia.com, 0
+daojia.com.cn, 0
+daojia-inc.com, 0
+daoyoudao.com, 0
+dapa.ir, 0
+daparto.de, 0
+dapenti.com, 0
+dapiniu.com, 0
+dapmalaysia.org, 0
+dapurcokelat.com, 0
+daren.pro, 0
+daricheno.com, 0
+darkbyte.ru, 0
+darkko.net, 0
+darklight.online, 0
+dark-night.me, 0
+darkseed.fr, 0
+darksidecc.com, 0
+darktech.org, 0
+dark-time.com, 0
+daroo.by, 0
+daroo.ru, 0
+da.ru, 0
+daryo.uz, 0
+dasannetworks.com, 0
+dataart.com, 0
+datacaciques.com, 0
+datacave.ch, 0
+dataexpress.com.tw, 0
+datagate.ee, 0
+data.gouv.fr, 0
+data.gov.hk, 0
+datagroup.ua, 0
+datakrat.ru, 0
+dataobject.hu, 0
+datapath.io, 0
+dataspeex.de, 0
+datastory.com.cn, 0
+datayes.com, 0
+datayuan.cn, 0
+datazucar.cu, 0
+datek.cn, 0
+datepanchang.com, 0
+datys.cu, 0
+daukce.cz, 0
+daunix.com, 0
+dautermann.io, 0
+daveramsey.com, 0
+davidrm.com, 0
+davidshuttle.com, 0
+davinciapps.com, 0
+davin.work, 0
+davispolk.com, 0
+davra.uz, 0
+dawang.tv, 0
+dawsoncollege.qc.ca, 0
+daxx.com, 0
+daybet24.com, 0
+daybuy.tw, 0
+daycare.com, 0
+daydao.com, 0
+dayezhifu.com, 0
+dayhr.com, 0
+dayin.la, 0
+daythem.edu.vn, 0
+dazzlepod.com, 0
+dba-china.com, 0
+dbappsecurity.com.cn, 0
+dbbest.com, 0
+dbelyaev.ru, 0
+dbface.com, 0
+dbpayment.com, 0
+dbscar.com, 0
+dc.gov, 0
+dcits.com, 0
+dcservices.in, 0
+dctp.tv, 0
+ddc.ac.kr, 0
+dd-dns.de, 0
+ddelivery.ru, 0
+ddit.ac.in, 0
+ddky.com, 0
+ddn.com, 0
+ddnsfree.com, 0
+ddns.info, 0
+ddnsking.com, 0
+ddns.me, 0
+ddns.ms, 0
+ddnss.de, 0
+ddns.us, 0
+ddoddotv.com, 0
+ddo.jp, 0
+ddol.es, 0
+ddoong2.com, 0
+ddpai.com, 0
+de1.cc, 0
+deaftone.com, 0
+dealber.gr, 0
+dealhaitao.com, 0
+deals.mu, 0
+deanza.edu, 0
+dearii.com, 0
+deartanker.com, 0
+deathgrind.club, 0
+debate.com.mx, 0
+debeste.de, 0
+debian-facile.org, 0
+debianforum.ru, 0
+debian-handbook.info, 0
+debian.net, 0
+debtcc.com, 0
+debugme.eu, 0
+de-clic.ro, 0
+decofire.pl, 0
+decoriko.ru, 0
+dedibox.fr, 0
+dedicated.co.za, 0
+dedizones.com, 0
+dedyn.io, 0
+deelkall.com, 0
+deeper.eu, 0
+deepgram.com, 0
+deepin.org, 0
+deepoon.com, 0
+deepss.co, 0
+defcon.ru, 0
+defo.ru, 0
+defre.be, 0
+deg.net, 0
+deichbrand.de, 0
+dejoris.de, 0
+del.ac.id, 0
+delaempokupki.ru, 0
+delfi.ee, 0
+delfi.lt, 0
+delfi.lv, 0
+delhivery.com, 0
+deliveryhero.com, 0
+deliverymuch.com.br, 0
+dell-brand.com, 0
+delmagyar.hu, 0
+deloks.ru, 0
+delovoymir.biz, 0
+delovoy-saransk.ru, 0
+delsa.net, 0
+delta.com.tw, 0
+deltacredit.ru, 0
+delwi-itr.de, 0
+demiart.ru, 0
+demirbank.az, 0
+demis.ru, 0
+demohoster.com, 0
+demoup.com, 0
+denascorp.ru, 0
+denbusiness.ru, 0
+dengivsem.com, 0
+denibertovic.com, 0
+denkwerk.com, 0
+dentaid.es, 0
+dentalspeedgraph.com.br, 0
+deondernemer.nl, 0
+de-oosterpoort.nl, 0
+depit.ru, 0
+depna.com, 0
+depositphotos.com, 0
+deppon.com, 0
+derbysoft.com, 0
+derev-grad.ru, 0
+derinat.ru, 0
+dermustermann.de, 0
+desamais.fr, 0
+descendentstudios.com, 0
+desc-wondo.org, 0
+designeroutlets-wolfsburg.de, 0
+design-hero.ru, 0
+design-sites.ru, 0
+desu.me, 0
+detective-conan-vostfr.info, 0
+detivgorode.ua, 0
+detoatepentrutoti.ro, 0
+detsky-mir.com, 0
+dev2.in, 0
+devbean.net, 0
+devel.cz, 0
+devicelock.com, 0
+devinotele.com, 0
+deviq.com, 0
+deviserweb.com, 0
+devochki-i-igry.ru, 0
+devoffice.com, 0
+devsmm.com, 0
+devuan.org, 0
+dewaele.com, 0
+dezhou.gov.cn, 0
+dezinfo.net, 0
+dfacture.com, 0
+dfb365.com, 0
+df.gov.br, 0
+dfss.com.cn, 0
+dftb.cn, 0
+dg.gov.cn, 0
+dgphoenix.com, 0
+dgprocast.com, 0
+dgso.cn, 0
+dgut.edu.cn, 0
+dgx.io, 0
+dhammacitta.org, 0
+dhb168.com, 0
+dhcp.com.br, 0
+dh.hu, 0
+dhis2.org, 0
+dhs.org, 0
+dhu.edu.cn, 0
+dhyhost.com, 0
+diakoweb.com, 0
+dialnice.info, 0
+diamondkeys.ru, 0
+diandianzu.com, 0
+dian.fm, 0
+dianhun.cn, 0
+dianjia.com, 0
+dianjoy.com, 0
+dianlujitao.com, 0
+dianrui.com, 0
+dianxiaomi.com, 0
+diaox2.com, 0
+diaoyuweng.com, 0
+diarioeltiempo.com.ar, 0
+diarioregistrado.com, 0
+diasporafoundation.org, 0
+dibpak.com, 0
+dicholding.com, 0
+dicoding.com, 0
+diconium.com, 0
+didatrip.com, 0
+diddlefinger.com, 0
+di-digo.com, 0
+didispace.com, 0
+didtheyreadit.com, 0
+didww.com, 0
+didyoumean-generator.com, 0
+die-auto-welt.de, 0
+diedart1.com, 0
+diederichs.com, 0
+diego.hu, 0
+dieselaccess.com, 0
+dieteren.be, 0
+die-tier-welt.com, 0
+digger-online.ru, 0
+digiboy.ir, 0
+digicom.net.ua, 0
+digiexam.com, 0
+digiexam.se, 0
+digift.ru, 0
+digikam.org, 0
+digik.ir, 0
+digitalcourage.de, 0
+digitaldruid.net, 0
+digitalero.rip, 0
+digital-forest.info, 0
+digitalmarketing.jp, 0
+digitalpad.co.jp, 0
+digitas.fr, 0
+digitellmobile.com, 0
+digito.com.tw, 0
+digix.io, 0
+dilekecza.com, 0
+dimensiondata.cloud, 0
+dimonvideo.ru, 0
+dinamicbet.com, 0
+dinaserver.com, 0
+dingdone.com, 0
+dingtalk.com, 0
+dinnerqueen.net, 0
+diocese-frejus-toulon.com, 0
+diocesismalaga.es, 0
+dior.cn, 0
+dipacademy.ru, 0
+dipaul.ru, 0
+dip.jp, 0
+diploma.de, 0
+directcall.com.br, 0
+directemar.cl, 0
+directgames.co.kr, 0
+directg.net, 0
+directnews.gr, 0
+directoriocubano.info, 0
+directoriodelosaltos.net, 0
+directpay.ir, 0
+directreal.sk, 0
+dirindirin.com, 0
+dirox.net, 0
+dirteam.com, 0
+dirtrider.com, 0
+discharge.be, 0
+discotek.club, 0
+discoworld.dk, 0
+disfilm.cz, 0
+diskingressos.com.br, 0
+diskret.de, 0
+diskstation.eu, 0
+diskstation.me, 0
+displayfusion.com, 0
+distance.ru, 0
+districenter.es, 0
+ditujiupian.com, 0
+dituwuyou.com, 0
+diulas.com, 0
+diva-e.com, 0
+diveinedu.com, 0
+divineengine.xyz, 0
+divteam.com, 0
+diychina.org, 0
+diyidan.com, 0
+diyidan.net, 0
+dj66.net, 0
+djcity.com.au, 0
+djdelivery.com, 0
+djduoduo.com, 0
+djfansub.com, 0
+djicorp.com, 0
+djjuniores.com, 0
+dj.ru, 0
+djv.de, 0
+djvu-pdf.com, 0
+djzmz.org, 0
+dk.kz, 0
+dlang.org, 0
+dle-news.ir, 0
+dlinkddns.com, 0
+dlinnov.com, 0
+dlsite.com.tw, 0
+dlt.com, 0
+dm930.com, 0
+dmall.com, 0
+dmc.de, 0
+dm.center, 0
+dmeng.net, 0
+dmnico.cn, 0
+dmww.com, 0
+dndz.tv, 0
+dnevnik.ru, 0
+dniproavia.com, 0
+dnpr.com.ua, 0
+dnr24.su, 0
+dnrsovet.su, 0
+dnsalias.com, 0
+dnsalias.org, 0
+dnsbil.com, 0
+dns.com.cn, 0
+dnscrypt.org, 0
+dns-dns.com, 0
+dnsisp.net, 0
+dnspai.com, 0
+dnsrv.ru, 0
+dnswa.com, 0
+dns.watch, 0
+do1.com.cn, 0
+dobavim.ru, 0
+dobot.cc, 0
+dobreobaly.cz, 0
+docdoc.ru, 0
+docer.com, 0
+dockerapp.io, 0
+docland.ru, 0
+docscrewbanks.com, 0
+docs-for-me.ru, 0
+doctorbormental.ru, 0
+doctorcom.com, 0
+doctormckay.com, 0
+doctorspring.com, 0
+doctrine.fr, 0
+doctu.ru, 0
+documentfoundation.org, 0
+dodohome.com.tw, 0
+dodopal.com, 0
+do.edu.ru, 0
+doefiratv.org, 0
+dogechain.info, 0
+dogovor24.kz, 0
+doguselektrik.com.tr, 0
+doido.ru, 0
+doi.gov, 0
+doity.com.br, 0
+dojobsonline.com, 0
+dojos.org, 0
+doki.co, 0
+dokipedia.ru, 0
+doktordanhaberler.com, 0
+doktornarabote.ru, 0
+dolabank.com, 0
+dollaruz.com, 0
+dolopo.net, 0
+dolorescannon.com, 0
+dom2-lifes.info, 0
+domain.by, 0
+domaintescil.com, 0
+domashke.net, 0
+dom-decora.ru, 0
+domeny.tv, 0
+domex.do, 0
+dominicos.org, 0
+dominos.by, 0
+dominos.com.do, 0
+dominos.ua, 0
+domirobot.com, 0
+dom-land.com, 0
+domob.cn, 0
+domobile.com, 0
+domovid.ru, 0
+domovina.je, 0
+domtain.de, 0
+domtele.com, 0
+donationalerts.ru, 0
+donfishback.com, 0
+dongao.com, 0
+dongeejiao.com, 0
+dongjiang.com.cn, 0
+dongshun3d.com, 0
+dongyoungsang.com, 0
+donjons-tresors.com, 0
+donland.ru, 0
+donnons.org, 0
+donya-digital.com, 0
+dooa.com, 0
+dooland.com, 0
+doppelkopf-palast.de, 0
+doraemoney.com, 0
+dorama.asia, 0
+doremir.com, 0
+dornanet.net, 0
+dornbracht.com, 0
+doroga.tv, 0
+dor.org, 0
+dorsafamily.ir, 0
+doska.chita.ru, 0
+dosnap.com, 0
+dosp.org, 0
+doswap.com, 0
+dota2house.com, 0
+dota2.net, 0
+dota2top.cn, 0
+dothome.co.kr, 0
+dotlan.net, 0
+dotroll.com, 0
+dots-game.org, 0
+dottnet.it, 0
+dotunnel001.com, 0
+dotunnel.com, 0
+dotw.com, 0
+dou-bi.co, 0
+doublemap.com, 0
+doubletwist.com, 0
+doujin.com.tw, 0
+doulike.com, 0
+douran.com, 0
+dowater.com, 0
+dowerandhall.com, 0
+downarchive.link, 0
+down.lc, 0
+downloadatoz.com, 0
+downloadcenter.me, 0
+download-flow.com, 0
+downloadgamesnow.org, 0
+downloadmanager.ir, 0
+download-redtube.eu, 0
+downloads-world.net, 0
+doxue.com, 0
+dozer.cc, 0
+dpap.ro, 0
+dpb.sk, 0
+dpfs.net, 0
+dp.gov.ua, 0
+dpg-physik.de, 0
+dpmb.cz, 0
+dpm.org.cn, 0
+dpo.cz, 0
+dprp.net, 0
+dp.ru, 0
+dpsi.com, 0
+dracoblue.net, 0
+draeger.com, 0
+dragonbound.net, 0
+dragongoserver.net, 0
+dragonknight.ru, 0
+dragonteam.ninja, 0
+dragplus.com, 0
+drakor.com, 0
+draw123.com.tw, 0
+drbd.org, 0
+drdump.com, 0
+dreamaction.co, 0
+dream.ren, 0
+dream-soft.de, 0
+dreifisch.com, 0
+drfakhar.ir, 0
+drgrab.ca, 0
+drgrab.com, 0
+drgrab.com.au, 0
+drgrab.co.nz, 0
+drgrab.co.uk, 0
+driedfloralshop.com, 0
+drillseo.com, 0
+driptip.ru, 0
+dripworks.com, 0
+drive2day.de, 0
+drive-my.com, 0
+driversnout.com, 0
+drlrcs.com, 0
+drofa-ventana.ru, 0
+drogariasnissei.com.br, 0
+drohobych.net, 0
+droi.com, 0
+droidbox.co.uk, 0
+droidboxforums.com, 0
+droidmod.ru, 0
+droidwiki.de, 0
+drom.ru, 0
+drone-forum.com, 0
+droneland.nl, 0
+dronk.ru, 0
+dropscan.de, 0
+drtihanyi.com, 0
+drugscouts.de, 0
+dschool.ru, 0
+dscloud.biz, 0
+dscloud.me, 0
+ds.cn, 0
+dsd.gov.hk, 0
+dshield.org, 0
+dsmynas.com, 0
+dsnews.ua, 0
+dsphere.info, 0
+dsporto.de, 0
+dss.go.th, 0
+dstu.education, 0
+dsty.ac.jp, 0
+dszo.cz, 0
+dszysoft.com, 0
+dtcj.com, 0
+dtcom.com.br, 0
+dtdns.net, 0
+dtempurl.com, 0
+dtest.cz, 0
+dtest.sk, 0
+dtln.ru, 0
+du9l.com, 0
+dualnitro.com, 0
+dualshockers.com, 0
+duanzhihu.com, 0
+duapp.com, 0
+dubna.net, 0
+dubtrack.fm, 0
+duc.cn, 0
+duckdns.org, 0
+duden.de, 0
+duguletian.com, 0
+duhowpi.net, 0
+duia.com, 0
+duiba.com.cn, 0
+duitang.com, 0
+dujin.org, 0
+duke.edu, 0
+dukey.cn, 0
+dumaosheng.com, 0
+duma.tomsk.ru, 0
+dumrt.ru, 0
+dundi.in, 0
+duniapulsa.co, 0
+dunkhome.com, 0
+duobeiyun.com, 0
+duocaitou.com, 0
+duoc.cl, 0
+duoduotv.com, 0
+duohuo.org, 0
+duoluodeyu.com, 0
+duplicationcentre.co.uk, 0
+durdom.in.ua, 0
+dushu.io, 0
+dusign.cn, 0
+dusoyun.com, 0
+dustmoon.com, 0
+dut.edu.ua, 0
+dutpt.com, 0
+duxa.cc, 0
+dva.lu, 0
+dvbank.ru, 0
+dv-com.net, 0
+dvdfab.cn, 0
+dvfu.ru, 0
+dvinaland.ru, 0
+dvr163.com, 0
+dvrdns.org, 0
+dwhd.org, 0
+dwhite.gr, 0
+dwkeji.com, 0
+dx.am, 0
+dxdt.ru, 0
+dx-racer.cz, 0
+dy530.com, 0
+dy886.com, 0
+dy.fi, 0
+dylog.it, 0
+dynabic.com, 0
+dynalias.com, 0
+dynalias.org, 0
+dynamic-dns.net, 0
+dynamo-dresden.de, 0
+dyndns-at-home.com, 0
+dyndns.biz, 0
+dyndns.dk, 0
+dyndns.info, 0
+dyndns-ip.com, 0
+dyndns.pro, 0
+dyndns-remote.com, 0
+dyndns-server.com, 0
+dyndns.tv, 0
+dyndns.ws, 0
+dynns.com, 0
+dynu.com, 0
+dynu.net, 0
+dyn-vpn.de, 0
+dzienniknaukowy.pl, 0
+dzo.com.ua, 0
+dzs.cz, 0
+dzsofts.net, 0
+dzwww.com, 0
+e100.eu, 0
+e123.pw, 0
+e2e4online.ru, 0
+e2say.com, 0
+e2time.net, 0
+e36.lv, 0
+e-actionlearning.jp, 0
+eadaily.com, 0
+eae-publishing.com, 0
+eagleplatform.com, 0
+ean-search.org, 0
+eapteka.ru, 0
+eareview.net, 0
+earthtreksclimbing.com, 0
+easemob.com, 0
+easetou.com, 0
+easeye.com.cn, 0
+easi-services.fr, 0
+eastal.com, 0
+eastcom.com, 0
+eastday.com, 0
+eastmachinery.com, 0
+eastview.com, 0
+eastweb.ir, 0
+easyapi.com, 0
+easyaq.com, 0
+easyaq.org, 0
+easycoding.org, 0
+easycoin.cz, 0
+easydrop.ru, 0
+easyfly.club, 0
+easynotebooks.de, 0
+easynvest.com.br, 0
+easyon.cn, 0
+easypano.com, 0
+easypass.cn, 0
+easypay.bg, 0
+easypm.cn, 0
+easysport.de, 0
+easytaxi.com.br, 0
+easytoys.cz, 0
+easyuni.com, 0
+easywebshop.com, 0
+ebacheca.it, 0
+ebaoquan.org, 0
+ebarrito.com, 0
+ebase.com, 0
+eb.br, 0
+ebesucher.com, 0
+ebesucher.de, 0
+ebesucher.es, 0
+ebesucher.fr, 0
+ebesucher.ru, 0
+ebg.net, 0
+ebible.org, 0
+ebmpapst.com, 0
+ebnevelde.hu, 0
+eboo.ir, 0
+ebookcn.com, 0
+ebottega.it, 0
+ebptt.com, 0
+ebrarbilgisayar.com, 0
+ebs.org.cn, 0
+ebuick.com.cn, 0
+ecall.ch, 0
+ecbiz.ru, 0
+eccom.com.cn, 0
+ecenter.travel, 0
+ecf.asso.fr, 0
+e-chinalife.com, 0
+echo24.cz, 0
+echofabrik.de, 0
+echosante.com, 0
+echoteen.com, 0
+eckert-schulen.de, 0
+eclisse.it, 0
+eclub.se, 0
+ecmsglobal.com, 0
+ecn.cz, 0
+ecnu.edu.cn, 0
+ecodms.de, 0
+ecoin.cc, 0
+ecolex.org, 0
+ecom-labs.com, 0
+ecommerce.gov.ir, 0
+economy.gov.az, 0
+economy.gov.by, 0
+economy.gov.ru, 0
+eco.pt, 0
+ecorepay.cc, 0
+ecovacs-japan.com, 0
+ecovanna.ru, 0
+ecovita.ru, 0
+ecpic.com.cn, 0
+ecplay.com, 0
+ecrm.com.tw, 0
+ecu.ac.uk, 0
+eczhuyin.com, 0
+ed2k.in, 0
+edaixi.cn, 0
+edaixi.com, 0
+edelweiss5.com, 0
+edge-core.com, 0
+edia.nl, 0
+edifier.ru, 0
+edigital.hu, 0
+edinarcoin.com, 0
+editions-ue.com, 0
+edizioni-ai.com, 0
+edj.club, 0
+edmundwatson.com, 0
+edm.uz, 0
+edmw.xyz, 0
+ednet.ns.ca, 0
+edns.com, 0
+edoc2.com, 0
+edooon.com, 0
+edoramedia.com, 0
+edsonqueiroz.com.br, 0
+edt02.net, 0
+edthena.com, 0
+edu35.ru, 0
+edu4school.gr, 0
+edu4schools.gr, 0
+edu53.ru, 0
+edu95.ru, 0
+eduasistent.ro, 0
+educacion.gob.ar, 0
+educationalinitiatives.com, 0
+educatorshandbook.com, 0
+educom.ru, 0
+edu-family.ru, 0
+eduherald.ru, 0
+edu.ky, 0
+edu.kz, 0
+edusite.ru, 0
+edu.sk, 0
+eduspb.com, 0
+edu.te.ua, 0
+edu.tomsk.ru, 0
+eduweb.com.ve, 0
+edznet.com, 0
+eee.com, 0
+eelly.com, 0
+eeload.com, 0
+eenot.com, 0
+eeworld.com.cn, 0
+eexcel.com.hk, 0
+eeyy.com, 0
+efeihu.com, 0
+efenix.cz, 0
+eff.org, 0
+effu.eu, 0
+efko.ru, 0
+efm.de, 0
+eforms.org, 0
+efrei.fr, 0
+efrontlearning.com, 0
+efsol.ru, 0
+efsyn.gr, 0
+efubo.com, 0
+efun.com, 0
+efunfun.com, 0
+efunkr.com, 0
+efuntw.com, 0
+efusion.co.jp, 0
+efw.cn, 0
+efzg.hr, 0
+e-garakuta.net, 0
+egarante.com, 0
+egent.ru, 0
+egmanga.com.tw, 0
+egou.com, 0
+egov66.ru, 0
+egret.com, 0
+egret-labs.org, 0
+egrp365.ru, 0
+egrul-egrip.ru, 0
+ehaoyao.com, 0
+ehbds.gov.cn, 0
+eheyin.com, 0
+ehighsun.com, 0
+ehm.cz, 0
+ehousechina.com, 0
+ehrana.si, 0
+ehrmedijugrupa.lv, 0
+eia.edu.co, 0
+eias.ru, 0
+eichsfeld-gymnasium.de, 0
+eicp.net, 0
+eiffel.com, 0
+eimagine.com, 0
+eink.com, 0
+e-inv.cn, 0
+eircom.net, 0
+eisenbahn.com.br, 0
+ejabberd.im, 0
+ejarehkhodro.com, 0
+ejieban.com, 0
+ejn.gov.ba, 0
+ejsino.com, 0
+ejuice.cz, 0
+ekartki-swiateczne.pl, 0
+eken.com, 0
+e-koncept.ru, 0
+ekr.or.kr, 0
+eksenbilgisayar.com, 0
+ekspresskonto.ee, 0
+eks.sk, 0
+eku8.com, 0
+elabjournal.com, 0
+elaion.ch, 0
+elane.ru, 0
+elar.ru, 0
+elasticbeanstalk.com, 0
+elasticrun.in, 0
+e-lationshop.de, 0
+elblag.pl, 0
+elbrus-zapchasti.ru, 0
+eldawlanews.com, 0
+eldiadehoy.net, 0
+eldorado.com.ua, 0
+eldorar.com, 0
+e-lead.com.tw, 0
+eleadglobal.com, 0
+elec.ru, 0
+electriclove.at, 0
+electroflot.ru, 0
+electrofun.ro, 0
+electro-mpo.ru, 0
+electronic-star.ch, 0
+electronic-star.cz, 0
+electronic-star.es, 0
+electronic-star.fi, 0
+electronic-star.fr, 0
+electronic-star.hr, 0
+electronic-star.hu, 0
+electronic-star.it, 0
+electronic-star.pl, 0
+electronic-star.pt, 0
+electronic-star.ro, 0
+electronic-star.se, 0
+electronic-star.si, 0
+electronic-star.sk, 0
+elegantt.com, 0
+eleks.com, 0
+elektra.ru, 0
+elektronik-star.de, 0
+elektronline.hu, 0
+elemer.ru, 0
+elem.mobi, 0
+elenafurs.ru, 0
+elenet.me, 0
+ele.to, 0
+eletrosom.com, 0
+elevenpaths.com, 0
+elf.com.tw, 0
+elfdict.com, 0
+elga.gr, 0
+elgato.com, 0
+elgaucho.com, 0
+eliademy.com, 0
+elinklaw.com, 0
+eliquidshop.cz, 0
+eliseparts.com, 0
+elitesochi.com, 0
+eliteunitedcrew.org, 0
+elitmus.com, 0
+elit.ro, 0
+elit.ua, 0
+eliv-group.ru, 0
+elkomp.ru, 0
+elkor.lv, 0
+ellco.ru, 0
+elleshop.com.cn, 0
+ellwoodepps.com, 0
+elm327rus.ru, 0
+elma-bpm.ru, 0
+elmarplatense.com, 0
+elmosanat.com, 0
+elnet.by, 0
+eloancn.com, 0
+elotech.com.br, 0
+elpo.net, 0
+elpreciodelagasolina.com, 0
+elsa.org, 0
+elsu.ru, 0
+eltallerdelbit.com, 0
+elte.hu, 0
+eltek.com, 0
+elumbus-reisen.de, 0
+elway.ru, 0
+ely.by, 0
+emailbidding.com, 0
+emailtray.com, 0
+emaintec.com, 0
+e-maker.com.tw, 0
+emao.com, 0
+emaos.de, 0
+emarbox.com, 0
+emarsys.com, 0
+emasa.es, 0
+embdev.net, 0
+embedy.cc, 0
+embl.de, 0
+emccann.net, 0
+emcmos.ru, 0
+emcsthai.com, 0
+emediamusic.com, 0
+emediava.org, 0
+emedi.gr, 0
+emeil.ir, 0
+emeraldmatch.com, 0
+emergencymedicinecases.com, 0
+emg.ru, 0
+emis.co.ao, 0
+emlid.com, 0
+emmalabs.com, 0
+emmaus-france.org, 0
+emnuvens.com.br, 0
+emo.org.tr, 0
+emory.edu, 0
+emos.cz, 0
+empathia.cz, 0
+empathy-portal.de, 0
+empireofcode.com, 0
+empleonuevo.com, 0
+emprana.ru, 0
+empro.com.br, 0
+emsb.qc.ca, 0
+ems.com.br, 0
+ems.network, 0
+emtec.com, 0
+emtelco.co, 0
+emu.ee, 0
+emulatornexus.com, 0
+emza.ru, 0
+enaa.com, 0
+enablecloud.co.uk, 0
+enaces.com, 0
+enact.co.uk, 0
+ename.net, 0
+en-charente-maritime.com, 0
+e-nci.com, 0
+encipher.it, 0
+enco.com, 0
+encoding.com, 0
+endian.com, 0
+endmyopia.org, 0
+endomondo.com, 0
+endplay.com, 0
+endpoint.com, 0
+energietec.eu, 0
+energiezivota.com, 0
+energy.gov.ua, 0
+energylabel.gov.cn, 0
+enflares.com, 0
+engagement.fr, 0
+engineowning.com, 0
+eng.it, 0
+england.nhs.uk, 0
+english-club.tv, 0
+englishtopics.net, 0
+engolit.de, 0
+eniac.ir, 0
+eniyikuafor.com, 0
+enjoitech.com, 0
+enkral.net, 0
+enlaza.mx, 0
+enl.wtf, 0
+en-marche.fr, 0
+e-norvik.eu, 0
+enow.cn, 0
+enportal.de, 0
+enriccorberainstitute.com, 0
+enro-griffins.de, 0
+ensage-forum.ru, 0
+ensartaos.com.ve, 0
+ensg.eu, 0
+entboost.com, 0
+entega.de, 0
+entre-geeks.com, 0
+entreleadership.com, 0
+entsog.eu, 0
+entware.net, 0
+enu.kz, 0
+envirolink.org, 0
+envisioncn.com, 0
+enwebhost.com, 0
+eoft.eu, 0
+eos.ru, 0
+eos-uptrade.de, 0
+eot.su, 0
+epac.to, 0
+epafos.gr, 0
+epam.com, 0
+epanchang.com, 0
+e-pard.com, 0
+epaslaugos.lt, 0
+epast.org, 0
+e-paths.com, 0
+epawaweather.com, 0
+epay.com, 0
+epay.lt, 0
+epcos.com, 0
+epd47.ru, 0
+epe.ir, 0
+epetbar.com, 0
+ephotobay.com, 0
+epicwow.com, 0
+epi.es, 0
+epi.sk, 0
+epita.fr, 0
+epitech.eu, 0
+epizod.ua, 0
+epizy.com, 0
+epm.br, 0
+e-pointchina.com.cn, 0
+epom.com, 0
+epommarket.com, 0
+epos.dk, 0
+epremki.pl, 0
+eprints.org, 0
+eprocurement.gov.gr, 0
+eproton.cz, 0
+epsic.ch, 0
+eptonic.com, 0
+epwk.com, 0
+eq28.cn, 0
+eqbal.ac.ir, 0
+erasmusu.com, 0
+erdalcelebi.com, 0
+ergasianews.gr, 0
+ericom.com, 0
+erinn.biz, 0
+erinome.net, 0
+eronsk.xxx, 0
+eropolis.hu, 0
+eroticen.com, 0
+erp-mz.ru, 0
+erpscan.com, 0
+errrotica.com, 0
+ershouhui.com, 0
+ertyu.org, 0
+esadn.com, 0
+escapefromtarkov.com, 0
+escape-game.org, 0
+escapes.ca, 0
+escience.cn, 0
+escolasecreches.com.br, 0
+escorts2000.com, 0
+escuelassj.com, 0
+esdict.cn, 0
+esearch.me, 0
+eseemodel.com, 0
+e-seenet.com, 0
+esetafrica.com, 0
+eset.kz, 0
+es.gov.br, 0
+eshangke.com, 0
+eshko.kz, 0
+eshraghtranslators.com, 0
+eshuyuan.net, 0
+esiea.fr, 0
+esi.uz, 0
+eskalat24.ru, 0
+eskalat.biz, 0
+eskom.eu, 0
+eso-database.com, 0
+eso.lt, 0
+esotravel.cz, 0
+espaciovino.com.ar, 0
+espago.com, 0
+esper.net, 0
+espol.edu.ec, 0
+esr-case.com, 0
+esri.com, 0
+essaybox.org, 0
+essayedge.com, 0
+essencegold.com.br, 0
+essentialpim.com, 0
+estcard.ee, 0
+estet.ru, 0
+esteveterradas.cat, 0
+estismail.com, 0
+estlandro.cc, 0
+estratosplus.com, 0
+estreams.tv, 0
+est.ua, 0
+estudarfora.org.br, 0
+estudar.org.br, 0
+estudiantesdelaplata.com, 0
+esu10.org, 0
+esu3.org, 0
+esu7.org, 0
+e-svatek.cz, 0
+esxi.gr, 0
+esy.es, 0
+et8.org, 0
+eta.cz, 0
+etaex.com, 0
+etagi.com, 0
+etalab.gouv.fr, 0
+etalasebisnis.com, 0
+etaplius.lt, 0
+etarget.cz, 0
+etb.net.co, 0
+etcnetwork.tv, 0
+etenal.me, 0
+etf.com, 0
+et-forum.org, 0
+eth0.com.br, 0
+ethereal-gaming.com, 0
+ethereumpool.co, 0
+ethfans.org, 0
+eth-gethired.ch, 0
+ethicsoft.it, 0
+ethinking.de, 0
+ethitter.com, 0
+ethst.de, 0
+ethz.ch, 0
+etick.ir, 0
+etland.co.kr, 0
+etong.com, 0
+etongdai.com, 0
+etowns.net, 0
+etowns.org, 0
+etracker.com, 0
+etruel.com, 0
+ets2planet.com, 0
+etsb.qc.ca, 0
+etstory.cn, 0
+etu.ru, 0
+euchost.com, 0
+eudic.net, 0
+eulji.ac.kr, 0
+eunetworks.com, 0
+euobserver.com, 0
+eurabota.com, 0
+eurasia.edu, 0
+eurasiangroup.org, 0
+eureka.lk, 0
+eurekamag.com, 0
+eurekers.com, 0
+eurodir.ru, 0
+eurofirms.es, 0
+eurogalaxy.sk, 0
+eurogest.company, 0
+euronics.cz, 0
+euronics.hu, 0
+euronova-italia.it, 0
+europa2.sk, 0
+europages.com, 0
+europa-market.ru, 0
+europeya.ru, 0
+eurostudy.info, 0
+eurovial.ro, 0
+eu.spb.ru, 0
+euvic.pl, 0
+eval.hu, 0
+evasionssecretes.fr, 0
+eveger.de, 0
+evejiaoben.com, 0
+evenflo.com, 0
+eventact.com, 0
+eventfarm.com, 0
+eventhia.com, 0
+eventim.si, 0
+eventpal.com.tw, 0
+eventsair.com, 0
+eve-online-com.ru, 0
+everest.com.tw, 0
+evergrande.com, 0
+evergreen.ca, 0
+evermarker.com, 0
+evermeet.cx, 0
+eversendai.com, 0
+everycaller.com, 0
+everyday.in.th, 0
+everymatrix.com, 0
+everything.kz, 0
+evget.com, 0
+evibe.in, 0
+evicertia.com, 0
+eviivo.com, 0
+evil0x.com, 0
+eviloctal.com, 0
+eviron.ru, 0
+evn.bg, 0
+evoi.ru, 0
+evolio.ro, 0
+evolix.net, 0
+evolutiontravel.it, 0
+evolveum.com, 0
+evotor.ru, 0
+evo-web.co.uk, 0
+evraz.com, 0
+evroopt.by, 0
+evvnt.com, 0
+evzo.net, 0
+eway-crm.com, 0
+eways.co, 0
+eways.ir, 0
+ewe.de, 0
+ewei.com, 0
+eweiqi.com, 0
+ewon.biz, 0
+exali.de, 0
+examslocal.com, 0
+exane.com, 0
+exaprint.fr, 0
+exapro.com, 0
+exceda.com, 0
+excelcalcs.com, 0
+excelsiorcommerce.com, 0
+exdreams.net, 0
+exehack.net, 0
+exertisireland.ie, 0
+exetools.com, 0
+ex-fs.net, 0
+exileed.com, 0
+eximb.com, 0
+experientia.com, 0
+experitest.com, 0
+experty.com, 0
+explee.com, 0
+exploretunes.com, 0
+explorr.net, 0
+expoforum.ru, 0
+exportimes.com, 0
+exportpages.com, 0
+exportpages.de, 0
+express.com.ar, 0
+express-odarennost.ru, 0
+exrates.me, 0
+extmail.org, 0
+extplorer.net, 0
+extrahop.com, 0
+extremecraft.net, 0
+extremo.club, 0
+eyaos.com, 0
+eyehere.net, 0
+eyou.net, 0
+ezacg.net, 0
+ezaisheng.com, 0
+ezdravkrg.org, 0
+ezfun.xyz, 0
+ezloo.com, 0
+ezmedia.me, 0
+ez.no, 0
+ezotericum.ru, 0
+ezoterikus.hu, 0
+ez-pz.com, 0
+ezwow.org, 0
+ezxing.com, 0
+ezyro.com, 0
+f0x.pw, 0
+f1news.ru, 0
+f3322.net, 0
+f3322.org, 0
+f4yy.com, 0
+f5.si, 0
+fabfab.net, 0
+fabrikaokon.ru, 0
+fabula.club, 0
+fabulous.ch, 0
+fabzat.com, 0
+facebac.com, 0
+facehack.me, 0
+faceit.ir, 0
+facenews.ua, 0
+facens.br, 0
+faceu.mobi, 0
+faceunity.com, 0
+facforpro.com, 0
+fackelmann.de, 0
+facta.com.br, 0
+factcool.com, 0
+factorenergia.com, 0
+factorkon.ir, 0
+factor.ua, 0
+facturamos.com.mx, 0
+factureaza.ro, 0
+fael.edu.br, 0
+fafait.ir, 0
+fainor.com.br, 0
+fairfieldcityschools.com, 0
+fairr.de, 0
+fairtop.in, 0
+faisco.cn, 0
+faisco.com, 0
+fakturyonline.eu, 0
+falconsocial.com, 0
+fals.com.br, 0
+famafutar.hu, 0
+famebit.com, 0
+famerom.ir, 0
+familienshirt.com, 0
+family.com.tw, 0
+familydoctor.com.cn, 0
+familyds.com, 0
+familyds.net, 0
+famo.ir, 0
+famtastic.cz, 0
+famtastic.hr, 0
+famtastic.hu, 0
+famtastic.ro, 0
+famtastic.sk, 0
+fancourier.ro, 0
+fanfic-fr.net, 0
+fanfic.hu, 0
+fanfou.com, 0
+fangamer.com, 0
+fangjie.info, 0
+fangjinsuo.com, 0
+fangrs.com, 0
+fangte.com, 0
+fanhaojia.com, 0
+fanpagesmarket.ru, 0
+fanqier.cn, 0
+fantabobshow.com, 0
+fantasyleague.com, 0
+fantawild.com, 0
+fantazya.net, 0
+fantlab.ru, 0
+fapiao.com, 0
+faponly.com, 0
+fapstor.com, 0
+far800.com, 0
+farakav.com, 0
+farapayamak.ir, 0
+farapic.com, 0
+faraso.org, 0
+fareastone.com.tw, 0
+farebookings.com, 0
+fariasbrito.com.br, 0
+farmaimpex.ru, 0
+farmainstant.com, 0
+farmalisto.com.co, 0
+farmec.ro, 0
+farmnest.com, 0
+farmskins.com, 0
+faro.es, 0
+farsiworld.ir, 0
+fashaoyou.net, 0
+fashion71.net, 0
+fashion.bg, 0
+fashioncompany.rs, 0
+fashionfriends.ch, 0
+fashn.de, 0
+fast-anime.ru, 0
+fastcr.cz, 0
+fasteasy.at, 0
+fasten.com, 0
+fastjet.com, 0
+fastloader.co, 0
+fast-mirror.de, 0
+fastprom.net, 0
+fastread.ru, 0
+fast-report.com, 0
+fastreport.ru, 0
+fasttony.es, 0
+fast-unfollow.com, 0
+fastvideotoscana.it, 0
+fastwebserver.de, 0
+fat.com.tw, 0
+fat-down.ru, 0
+fattor-rc.com.br, 0
+favbet.com, 0
+favera.ru, 0
+favorit.com.ua, 0
+favoritsport.com.ua, 0
+faw-vw.com, 0
+fayea.com, 0
+fayzfm.uz, 0
+fazekas.hu, 0
+fazmusic15.org, 0
+faz-musics.in, 0
+fbresponder.com.br, 0
+fbxos.fr, 0
+fcasd.edu, 0
+fcbarcelona.cz, 0
+fccs.com, 0
+fckrasnodar.ru, 0
+fcm-live.de, 0
+fcn.de, 0
+fcrmedia.ie, 0
+fcsm.ru, 0
+fcstpauli.com, 0
+fct-altai.ru, 0
+fcv.edu.br, 0
+fd114.com, 0
+fdc.com.cn, 0
+fdlx.com, 0
+f-droid.org, 0
+fedpress.ru, 0
+fedsp.com, 0
+fedyay.net, 0
+feedbooks.com, 0
+feedbooks.net, 0
+feedonomics.com, 0
+feedvisor.com, 0
+feelingplace.com, 0
+fee.org, 0
+feidai.com, 0
+feifandy.net, 0
+feifanvpn.com.cn, 0
+feig.de, 0
+feihuo.com, 0
+feijiu.net, 0
+feiliu.com, 0
+fei.sg, 0
+feisovet.ru, 0
+feixueacg.com, 0
+feiyangedu.com, 0
+feiyulian.cn, 0
+felgenshop.de, 0
+felink.com, 0
+feliway.com, 0
+femininesite.ru, 0
+fengbuy.com, 0
+feng.com, 0
+feng-shui.ru, 0
+fengsung.com, 0
+fengzigame.com, 0
+fenjinshe.com, 0
+fensifuwu.com, 0
+fenxiangba.org, 0
+fernsehkritik.tv, 0
+ferrarischule.at, 0
+ferrino.it, 0
+ferrite.ru, 0
+ferrotec.com, 0
+ferro-video.com, 0
+fertagus.pt, 0
+fert.cn, 0
+feste-ip.net, 0
+festima.ru, 0
+fextralife.com, 0
+ffa-assurance.fr, 0
+ffforever.info, 0
+ffh.de, 0
+ffhs.ch, 0
+ffmpeg.org, 0
+ffplum.info, 0
+ffruit.eu, 0
+ffsg.org, 0
+ffxiv.cn, 0
+fgs-impianti.it, 0
+fgup-ohrana.ru, 0
+fh21.com.cn, 0
+fh-diploma.de, 0
+fh-koeln.de, 0
+fhmsolutions.com, 0
+fhnw.ch, 0
+fia.academy, 0
+fialkovod.ru, 0
+fia-net.com, 0
+fiberhome.com, 0
+fibrum.com, 0
+fictiongrill.com, 0
+fictionmania.tv, 0
+fidelity-media.com, 0
+fidelitysalus.it, 0
+fidella.org, 0
+fidion.de, 0
+fieb.org.br, 0
+fieldandstream.com, 0
+fieldnation.com, 0
+fieldschina.com, 0
+fievent.com, 0
+fifanice.com, 0
+fiff.de, 0
+figotan.org, 0
+fileconvoy.com, 0
+filelist.ro, 0
+filemakermagazine.com, 0
+file.pet, 0
+filerooz.com, 0
+fileseek.ca, 0
+filesell.ir, 0
+filesend.to, 0
+filetender.com, 0
+fileup.ir, 0
+file-up.net, 0
+filewave.com, 0
+filkab.com, 0
+fill.ee, 0
+filmcrave.com, 0
+filmesonlinex1.com, 0
+filmistreet.com, 0
+film--izle.com, 0
+film.tv, 0
+film-ussr.ru, 0
+filorga.com, 0
+finansovyesovety.ru, 0
+finas-services.de, 0
+findercom.ru, 0
+findface.me, 0
+findface.pro, 0
+findface.ru, 0
+findlifevalue.com, 0
+findmima.com, 0
+findschool.ca, 0
+findsomeone.co.nz, 0
+findtenders.ru, 0
+findu.com, 0
+findyourtrainer.com, 0
+finestsin.de, 0
+fingent.com, 0
+finkafe.com, 0
+finkzeit.at, 0
+finolog.ru, 0
+fin-partners.ru, 0
+firdi.org.tw, 0
+fire2000.rocks, 0
+firefoxfan.cc, 0
+firehol.org, 0
+firejune.com, 0
+firepoweredgaming.com, 0
+firestock.ru, 0
+firmenkontaktmesse.de, 0
+firmstep.com, 0
+firo.ru, 0
+firstbit.ae, 0
+firstcare.com.cn, 0
+firstcarrental.co.za, 0
+firstleap.cn, 0
+first-moment.de, 0
+firstonetv.eu, 0
+firststage.org, 0
+fischer.com.br, 0
+fisc.md, 0
+fishbattle.net, 0
+fishcn.com, 0
+fisherman-market.ru, 0
+fishifarm.ru, 0
+fishki.net, 0
+fishyforum.com, 0
+fiskarsmarket.ru, 0
+fit.ac.ir, 0
+fitilio.com, 0
+fitnesspell.com, 0
+fitnessplus.ru, 0
+fitnezz.net, 0
+fixcenter.com.ua, 0
+fiza.ir, 0
+fizkult-nn.ru, 0
+fj.cn, 0
+fjcyl.com, 0
+fjdqqb.com, 0
+fjrs.gov.cn, 0
+fju.edu.tw, 0
+flag.org, 0
+flamboyant.com.br, 0
+flamp.ru, 0
+flarumone.com, 0
+flashphoner.com, 0
+flatfy.az, 0
+flatfy.by, 0
+flatfy.kz, 0
+flatfy.pl, 0
+flatfy.ro, 0
+flatfy.ru, 0
+flaticon.es, 0
+flatterer.ru, 0
+flboos.com, 0
+fleeber.com, 0
+fleex.tv, 0
+flexcils.com, 0
+flexibits.com, 0
+flibusta.net, 0
+flickrocket.com, 0
+flight-finder.com, 0
+flinteractive.fr, 0
+flip.id, 0
+flipup.ru, 0
+flipwalls.com.cn, 0
+flixbus.at, 0
+flixbus.be, 0
+flixbus.com, 0
+flixbus.co.uk, 0
+flixbus.cz, 0
+flixbus.de, 0
+flixbus.dk, 0
+flixbus.es, 0
+flixbus.fr, 0
+flixbus.hr, 0
+flixbus.it, 0
+flixbus.nl, 0
+flixbus.pl, 0
+flixbus.ru, 0
+flixbus.se, 0
+flixmobility.com, 0
+flnet.org, 0
+flnka.ru, 0
+floobits.com, 0
+floralinvestment.com, 0
+floraverse.com, 0
+floridelux.ro, 0
+flotalamacarena.com, 0
+flowerpassword.com, 0
+flowerplus.cn, 0
+flow-list.cz, 0
+flowmon.com, 0
+flowtraders.com, 0
+flptrading.net, 0
+fluentcloud.com, 0
+fluffy.is, 0
+fluger.pro, 0
+flukso.net, 0
+fluxbytes.com, 0
+fluxfm.de, 0
+fluxicon.com, 0
+flyco.com, 0
+flycosmos.com, 0
+flyerdevil.de, 0
+flyerpilot.de, 0
+flyingacademy.com, 0
+flyingmag.com, 0
+flymycloud.com, 0
+flynet.by, 0
+flynsarmy.com, 0
+flytcloud.com, 0
+fly.tj, 0
+flyuia.com, 0
+flyvpn.com, 0
+fmach.it, 0
+fmaroof.ir, 0
+fmdisk.net, 0
+fnblasanimas.com, 0
+fnmotol.cz, 0
+foboko.com, 0
+focusmedia.cn, 0
+focus-net.net, 0
+focus.ua, 0
+fodar.ru, 0
+foheart.com, 0
+followmyvote.com, 0
+fonar.tv, 0
+fondazionearching.it, 0
+fond-kino.ru, 0
+f-online.at, 0
+fontenay-sous-bois.fr, 0
+foodband.ru, 0
+foodbrothers.com, 0
+foodclub.ru, 0
+food.co.il, 0
+foodfox.ru, 0
+foodrussia.net, 0
+foody.com.cy, 0
+football-onlain.tv, 0
+footballua.tv, 0
+footbolka.ru, 0
+footway.dk, 0
+footway.fi, 0
+footway.no, 0
+footway.se, 0
+force9.co.uk, 0
+forces-war-records.co.uk, 0
+fordaq.com, 0
+fordclubs.org, 0
+ford-koegler.de, 0
+foresealife.com, 0
+foreveross.com, 0
+forexac.com, 0
+forexclub-russia.ru, 0
+forexsklad.com, 0
+forgerock.com, 0
+forgerock.org, 0
+forgottenbooks.com, 0
+forma2plus.com, 0
+formalytx.com, 0
+format-tv.net, 0
+formo.ua, 0
+formpipe.com, 0
+formsdotstar.com, 0
+formstone.it, 0
+formulalubvi.com, 0
+formulastudent.de, 0
+formz.com, 0
+foroffice.ru, 0
+forotrolls.com, 0
+fortiddns.com, 0
+fortinet.com, 0
+fortiss.org, 0
+fortunebill.com, 0
+forum-3dcenter.org, 0
+forumbee.com, 0
+forum-hardware.de, 0
+forum-laptopy.info.pl, 0
+forum.vn.ua, 0
+forumx.com.br, 0
+forushefile.com, 0
+forus.ru, 0
+for-vk.com, 0
+forward-bank.com, 0
+forwardvelo.ru, 0
+foscam.com, 0
+foscammall.com, 0
+fossee.in, 0
+fossies.org, 0
+fosu.edu.cn, 0
+fotile.com, 0
+fotky-foto.cz, 0
+fotoalbum.ee, 0
+fotoalbum.es, 0
+fotocopy.hu, 0
+fotoev.com, 0
+fotogoroda.net, 0
+fotograf.de, 0
+fotokasten.de, 0
+fotolab.ru, 0
+foton.com.cn, 0
+fotoprivet.com, 0
+fotor.com, 0
+fotor.com.cn, 0
+fotosklad.ru, 0
+fotospektr.ru, 0
+fotostars.me, 0
+foundationsu.com, 0
+founder.com, 0
+founderio.com, 0
+fountainpen.it, 0
+fourglobe.co.jp, 0
+fourierdsl.co.za, 0
+fow.watch, 0
+fox008.com, 0
+foxconn.com, 0
+foxconnmall.com, 0
+foxdeploy.com, 0
+foxitreader.cn, 0
+fox-mall.ru, 0
+foxrenderfarm.com, 0
+foxtrot.com.ua, 0
+fozzy.com, 0
+fpucentral.com, 0
+fqapps.com, 0
+fqproxy.com, 0
+fqrouter2.cn, 0
+frac.tl, 0
+fragfinn.de, 0
+frag-mutti.de, 0
+francedns.com, 0
+franceserv.com, 0
+franceserv.fr, 0
+france-troc.com, 0
+francite.net, 0
+francochinois.com, 0
+frankkingclub.com, 0
+franklincollege.edu, 0
+frankysweb.de, 0
+fraudect.com, 0
+frdic.com, 0
+free521.com, 0
+freebieac.com, 0
+freeboxos.fr, 0
+freebusy.io, 0
+freebytes.com, 0
+freeconferencecall.com, 0
+freeddns.org, 0
+freedns.io, 0
+freedomrussia.org, 0
+freedom-vrn.ru, 0
+freedriver.org, 0
+free-ebooks.net, 0
+free-electrons.com, 0
+freefeed.net, 0
+freefielder.jp, 0
+freefii.de, 0
+free.fr, 0
+freegeoip.net, 0
+free-hack.com, 0
+freehacks.ru, 0
+free-hosting.ir, 0
+freeintro.net, 0
+free-it.ru, 0
+freeje.com, 0
+freekulinar.ru, 0
+freelance.boutique, 0
+freelance.com, 0
+freelancerclub.net, 0
+freelance.ru, 0
+freelance.today, 0
+freemail.gr, 0
+freemaineads.com, 0
+freeman-btc.com, 0
+freepaper.me, 0
+free-pdftoword.com, 0
+freepik.es, 0
+freepost.es, 0
+freeprojectz.com, 0
+free-ro.com, 0
+freesafeip.com, 0
+freeskiers.net, 0
+freesoft-board.to, 0
+freestoriesforkids.com, 0
+freestylersworld.com, 0
+freetemplatesonline.com, 0
+free-torrent.org, 0
+free-torrents.org, 0
+freevar.com, 0
+freevpnxz.com, 0
+freevps.us, 0
+freexf.com, 0
+freezingblue.com, 0
+freie-volksmission.de, 0
+freifunk.net, 0
+frejustoulon.fr, 0
+frekvence1.cz, 0
+frenchkiss.ru, 0
+freshports.org, 0
+freshwatersystems.com, 0
+fr.ht, 0
+friends-forum.com, 0
+fri-gate.org, 0
+frischeis.at, 0
+friskyradio.com, 0
+fritzsch.net, 0
+frogshealth.com, 0
+fromae.com, 0
+frontcam.ru, 0
+frontenddev.org, 0
+fronter.com, 0
+frontpad.ru, 0
+frostland.pro, 0
+froxlor.org, 0
+frozenbyte.com, 0
+frozencpu.com, 0
+frsky-rc.com, 0
+fruct.org, 0
+frugalmechanic.com, 0
+fruitday.com, 0
+fryd.ru, 0
+fryshuset.se, 0
+fs.com, 0
+fsfund.com, 0
+fsfxpackages.com, 0
+fshrss.gov.cn, 0
+fsinf.at, 0
+fsk-ees.ru, 0
+fskn.gov.ru, 0
+fspro.net, 0
+fstrf.ru, 0
+ftbeautycn.com, 0
+ftsafe.com, 0
+ftvyifubi.com, 0
+fuckav.ru, 0
+fuckbilibili.com, 0
+fudan.edu.cn, 0
+fudan.sh.cn, 0
+fuelcellsworks.com, 0
+fugumobile.cn, 0
+fujian.gov.cn, 0
+fujifilm-x.ru, 0
+fukun.org, 0
+fulba.com, 0
+fulgan.com, 0
+fulidang.com, 0
+fulid.net, 0
+fuli.moe, 0
+fuling.com, 0
+fuliren.com, 0
+fuliv8.com, 0
+full-chip.net, 0
+fullprogramindir.biz, 0
+fullsecurity.org, 0
+fumasoft.com, 0
+funcook.com, 0
+fundamenta.hu, 0
+fundamental-research.ru, 0
+funeed.com, 0
+funeralone.com, 0
+funfactory.com, 0
+funfunquiz.com, 0
+fungames-forfree.com, 0
+funiber.org, 0
+funi.com, 0
+funinsta.ru, 0
+funkmeldesystem.de, 0
+funnysocks.ru, 0
+funpot.net, 0
+funradio.sk, 0
+funshion.com, 0
+fun-taiwan.com, 0
+funweek.it, 0
+fuqizy.com, 0
+furfest.org, 0
+furnation.com, 0
+furnation.ru, 0
+fusker.xxx, 0
+fussballfantipp.de, 0
+futbalnet.sk, 0
+futboholic.com, 0
+futboholic.com.ua, 0
+futboholic.ru, 0
+futbolki.ru, 0
+futpack.ru, 0
+fut.ru, 0
+futu5.com, 0
+futunn.com, 0
+futurecovenant.com, 0
+future-processing.pl, 0
+fuwo.com, 0
+fuyaogroup.com, 0
+fvds.ru, 0
+fx678.com, 0
+fx77.com, 0
+fxclub.org, 0
+fx-mt4.info, 0
+fxpan.com, 0
+fxsound.com, 0
+fxteam.ru, 0
+fyber.com, 0
+fyeedu.net, 0
+fync.edu.cn, 0
+fynews.net, 0
+fyygame.pw, 0
+fyysports.com, 0
+fyzhuji.com, 0
+fzdm.com, 0
+gadz.org, 0
+gaeamobile.com, 0
+gaeamobile.net, 0
+gagahi.com, 0
+gainapp.com, 0
+gaiz.com, 0
+galactikka.com, 0
+galaksion.com, 0
+galaktika.ru, 0
+galanz.com, 0
+galax.com, 0
+galaxytech.com, 0
+galgame.co, 0
+galinos.gr, 0
+gallerr.com, 0
+gallery-dump.com, 0
+galpenergia.com, 0
+gals.uz, 0
+game13.com, 0
+game2.cn, 0
+game2.com.cn, 0
+gamed9.com, 0
+gamedreamer.com.tw, 0
+gameforgirl.ru, 0
+gamehitzone.com, 0
+gamehonor.com, 0
+gameindy.com, 0
+gameliebe.com, 0
+gamelumi.com, 0
+gameofbombs.com, 0
+gamereactor.de, 0
+gamereactor.dk, 0
+gamereactor.es, 0
+gamereactor.eu, 0
+gamereactor.fi, 0
+gamereactor.it, 0
+gamereactor.no, 0
+gamereactor.pt, 0
+gamereactor.se, 0
+gamesites.cz, 0
+gamesow.com, 0
+gamesplanet.com, 0
+gamesuit.ru, 0
+gameswelt.at, 0
+gameswelt.ch, 0
+gameswelt.de, 0
+gameswelt.tv, 0
+gameurs.net, 0
+gameware.at, 0
+gamexp.ru, 0
+gamingmasters.org, 0
+gamyun.net, 0
+gannun.cn, 0
+ganso.com.cn, 0
+gansuche.cn, 0
+gaogulou.com, 0
+gaokaopai.com, 0
+gaokaowangbao.com, 0
+gaopeng.com, 0
+gaosouyi.com, 0
+gaotizi.com, 0
+garada.net, 0
+garageentertainment.com.au, 0
+garage-gps.com, 0
+garagemca.org, 0
+garant.by, 0
+garant.ru, 0
+garazh.ir, 0
+garden.org, 0
+garminshop.ir, 0
+gartenhaus-gmbh.de, 0
+garvan.org.au, 0
+gaskrank.tv, 0
+gastrogate.com, 0
+gasu.ru, 0
+gatan.com, 0
+gavag.ru, 0
+gaws.ru, 0
+gaypal.co, 0
+gazeta.ru, 0
+gazprom.ru, 0
+gaz.ru, 0
+gazu.ru, 0
+gba.gov.ar, 0
+gbs.edu, 0
+gcbi.com.cn, 0
+gcnewhorizons.net, 0
+gcp.edu.cn, 0
+gcstech.net, 0
+gcup.ru, 0
+gcx.org, 0
+gd10010.cn, 0
+gd88.org, 0
+gdalpha.com, 0
+gdcuffs.com, 0
+gdekluet.ru, 0
+gdga.gov.cn, 0
+gdgbpx.com, 0
+gd-line.com, 0
+gdsyzx.edu.cn, 0
+gdufs.edu.cn, 0
+gdzelektrik.com.tr, 0
+gear.host, 0
+gearsource.com, 0
+gebeco.de, 0
+gebrauchte-veranstaltungstechnik.de, 0
+geckosoftware.com, 0
+ge.com.cn, 0
+gedichte.com, 0
+gedizelektrik.com.tr, 0
+gedofile.com, 0
+geekbang.org, 0
+geekbrains.ru, 0
+geekie.com.br, 0
+geekielab.com.br, 0
+geekmaze.ru, 0
+geekpeek.net, 0
+geekteam.pro, 0
+geekup.pl, 0
+geekweekconf.com, 0
+geenfc.com, 0
+gefaellt-mir.me, 0
+gegejia.com, 0
+geichina.org, 0
+geilicdn.com, 0
+geizreich.de, 0
+gem4me.com, 0
+gemfury.com, 0
+gemkadeh.com, 0
+gemz.ir, 0
+gench.edu.cn, 0
+genealogieonline.nl, 0
+geneanet.org, 0
+geneawiki.com, 0
+genebang.com, 0
+genecopoeia.com, 0
+generalroca.gov.ar, 0
+generals.mobi, 0
+generationlove.com, 0
+generations-patrimoine.com, 0
+geniesolutions.com.au, 0
+genofond.org, 0
+genomics.cn, 0
+genscript.com, 0
+genscript.com.cn, 0
+genser.ru, 0
+geodata.it, 0
+geoprostor.net, 0
+georgikon.hu, 0
+georgio.fr, 0
+gerald.top, 0
+gerdoo.net, 0
+gerdoosoft.com, 0
+gerencianet.com.br, 0
+german-railroads.de, 0
+germanssky.de, 0
+germanystudy.net, 0
+geru.com.br, 0
+gesamtschule-zeuthen.eu, 0
+ges-bo.de, 0
+geschenkkartenwelt.de, 0
+gesext.de, 0
+get4click.ru, 0
+geta6.net, 0
+getabstract.com, 0
+getadmiral.com, 0
+getawesomesupport.com, 0
+getcoins.win, 0
+getcs16.ru, 0
+getdc.ru, 0
+getfreegate.com, 0
+get-in-it.de, 0
+getinmybelly.com, 0
+getitfree.cn, 0
+getitnow.gr, 0
+getkey.eu, 0
+getline.in, 0
+getmyscript.com, 0
+getriver.com, 0
+getrix.it, 0
+getsitecontrol.com, 0
+getsteam.cards, 0
+get-styles.ru, 0
+gettertools.com, 0
+getter-tools.de, 0
+get-tune.cc, 0
+get-tune.net, 0
+gettune.net, 0
+getujobs.com, 0
+getway.me, 0
+getwox.com, 0
+gewobag.de, 0
+gezergiyim.com, 0
+gfaq.ru, 0
+gfi.es, 0
+gfmrecharge.co.in, 0
+gfw.pics, 0
+gfycat.com, 0
+gg4m.com, 0
+ggbinary.com, 0
+ggcj.com, 0
+ggmgastro.com, 0
+ghac.cn, 0
+ghostforbeginners.com, 0
+ghostry.cn, 0
+ghtinc.com, 0
+gianganh.net, 0
+gibdd.ru, 0
+gicp.net, 0
+gidnetwork.com, 0
+giftcards.eu, 0
+giftman.ru, 0
+giftster.com, 0
+gigabaza.ru, 0
+gigabyte.cn, 0
+gigaleecher.com, 0
+giga-rapid.com, 0
+gigaserver.cz, 0
+gigatribe.com, 0
+gigatron.rs, 0
+gigatronshop.com, 0
+giga.ua, 0
+gigfa.com, 0
+giiwa.org, 0
+gilbo.ru, 0
+gimhoy.com, 0
+gimlet.us, 0
+gimp.org, 0
+gimvic.org, 0
+ginger-cat.ru, 0
+ginsystem.us, 0
+gioc.kiev.ua, 0
+gionee.com, 0
+giordano.com, 0
+gioseppo.com, 0
+gioxx.org, 0
+gipsr.ru, 0
+gira.cc, 0
+gira.com, 0
+gira.de, 0
+girimulya.com, 0
+girl010.com, 0
+girlsdocam.com, 0
+girlsinparis.com, 0
+girsa.ru, 0
+gisclub.tv, 0
+gis-lab.info, 0
+gisroad.com, 0
+gitgud.io, 0
+github.io, 0
+gitlab.cc, 0
+gitsea.com, 0
+giuseppe.cn, 0
+giustizia-amministrativa.it, 0
+givegift.com.hk, 0
+giveyousomecolortoseesee.com, 0
+gizmiz.com, 0
+gizzmoheaven.com, 0
+gjn.cz, 0
+gjs.so, 0
+gjzq.com.cn, 0
+gkk.uz, 0
+gkovd.ru, 0
+gladiators.ru, 0
+glamius.ru, 0
+glamot.cz, 0
+glamour.ru, 0
+glashkoff.com, 0
+glassrpske.com, 0
+glav-dostavka.ru, 0
+glavred.info, 0
+glitchthegame.com, 0
+glitzcloud.com, 0
+glkb.ch, 0
+globaladvisors.biz, 0
+global-customer.com, 0
+globaldynamicmarketing.com, 0
+globalhitss.com, 0
+globalitanalytics.com, 0
+global-katalog.ru, 0
+globalnomadic.com, 0
+globalpartszone.com, 0
+globalpolicy.org, 0
+globex.cn, 0
+globusmax.co.il, 0
+glocalme.com, 0
+gloeckle.de, 0
+glogow.pl, 0
+glopoi.com, 0
+glorioustrainwrecks.com, 0
+glyphter.com, 0
+gmcc.net, 0
+gm-city.ru, 0
+gmdao.cc, 0
+gmg.biz, 0
+gmod.de, 0
+gmtincorp.com, 0
+gmuz.uz, 0
+gnawers.de, 0
+gnewstv.com, 0
+gnome.org, 0
+gntech.ac.kr, 0
+gnway.cc, 0
+gnway.com, 0
+go189.cn, 0
+go2bus.ru, 0
+go2olymp.com, 0
+goanews.com, 0
+goapr.com, 0
+goarmy.co.uk, 0
+gobaidugle.com, 0
+gob.bo, 0
+gob.cl, 0
+gob.do, 0
+gobelinland.fr, 0
+gochengdu.cn, 0
+godata.tw, 0
+godeyes.cn, 0
+godic.net, 0
+god.jp, 0
+godnota.org, 0
+godon.biz, 0
+goeasy.io, 0
+goeducation.com.tw, 0
+goflyla.com, 0
+gogames.me, 0
+gogosu.xyz, 0
+gogovan.sg, 0
+go.gov.br, 0
+gogovpn.org, 0
+gogvo.com, 0
+goingnative.cn, 0
+goip.de, 0
+golbazar.net, 0
+gol.bg, 0
+goldapple.ru, 0
+goldbroker.com, 0
+goldbroker.fr, 0
+goldbroker.it, 0
+golden-monkey.ru, 0
+goldenpages.ie, 0
+goldenpalace.be, 0
+golden-time.ru, 0
+goldflyer.ru, 0
+goldpharma.cn, 0
+goldwind.com.cn, 0
+golo365.com, 0
+golospravdy.com, 0
+golpas.com, 0
+gomefinance.com.cn, 0
+gomehigo.hk, 0
+gomel.today, 0
+gomezacebo-pombo.com, 0
+gomobil.cz, 0
+goncakitap.com.tr, 0
+g-one-inc.com, 0
+gonetis.com, 0
+gongfubb.com, 0
+gonightshift.com, 0
+goocig.com, 0
+good.cc, 0
+goodgame.ru, 0
+goodly.pro, 0
+goodmaoningboy.com, 0
+good-movie.ru, 0
+goodnight.at, 0
+goodsflow.com, 0
+goodtyping.com, 0
+goody25.com, 0
+googto.org, 0
+goo.kz, 0
+gootara.org, 0
+gopas.cz, 0
+gorcenter.spb.ru, 0
+gorcomnet.ru, 0
+gorcom.ru, 0
+gorlice.pl, 0
+go.ro, 0
+gorodche.ru, 0
+gorodovik.com, 0
+gorodtv.net, 0
+goskills.com, 0
+gosmonitor.ru, 0
+gospmr.org, 0
+gossh.net, 0
+gotdns.com, 0
+gotdns.org, 0
+gothicwiki.pw, 0
+gotocdn.com, 0
+gotokeep.com, 0
+gotye.com.cn, 0
+goujiawang.com, 0
+gouv.bj, 0
+gouv.ci, 0
+gov110.cn, 0
+gov35.ru, 0
+gov.cl, 0
+government.bg, 0
+gov.karelia.ru, 0
+gov.kz, 0
+gov.md, 0
+gov.mg, 0
+gov.mw, 0
+govoritmoskva.ru, 0
+gov.ro, 0
+gov.sc, 0
+gov.sk, 0
+gov.taipei, 0
+govvrn.ru, 0
+gow.help, 0
+gp.by, 0
+gpgtools.org, 0
+gpl-express.com, 0
+gpntb.ru, 0
+gppc.ru, 0
+gqget.com, 0
+gq.ru, 0
+graacc.org.br, 0
+graa.ru, 0
+grabberz.com, 0
+grabien.com, 0
+grabitjeeves.com, 0
+graffitishop.it, 0
+graffitishop.net, 0
+gramula.com, 0
+grandcapital.net, 0
+grandest.fr, 0
+grandtheftarma.com, 0
+graphcommons.com, 0
+graphsketch.com, 0
+gravitypayments.com, 0
+gravitytales.com, 0
+gr.ch, 0
+grcrt.net, 0
+greatagroup.com, 0
+greekfestival.gr, 0
+greenbooki.ru, 0
+greengo.hu, 0
+green-japan.com, 0
+greenlightdigital.com, 0
+greenmama.ru, 0
+greenpeace.fr, 0
+greenpeace.org.br, 0
+greetz.be, 0
+greetz.nl, 0
+greg-kennedy.com, 0
+gregsdrivingschool.net, 0
+griddynamics.net, 0
+gridrepublic.org, 0
+gridsum.com, 0
+griffincapital.com, 0
+grimbets.com, 0
+grishko.ru, 0
+grisino.com, 0
+grnet.gr, 0
+grodno.net, 0
+groene.nl, 0
+gronkh-wiki.de, 0
+groov.pl, 0
+grossum.com, 0
+groundspeak.com, 0
+groupboard.com, 0
+groupe-efrei.fr, 0
+groupeleader.com, 0
+groupensia.com, 0
+group-ib.com, 0
+grouppartner.ru, 0
+growfood.pro, 0
+grpl.org, 0
+grsu.by, 0
+gruendl.de, 0
+grupoasv.com, 0
+grupocobra.com, 0
+grupodass.com.br, 0
+grupofrisa.com, 0
+grupoiris.net, 0
+grupomednet.com.br, 0
+gruponzn.com, 0
+gruposanilab.es, 0
+gruposayer.com, 0
+grupovips.com, 0
+gruppoiren.it, 0
+gruppolapastamadre.it, 0
+grupposandonato.it, 0
+gruso.cz, 0
+gruzovichkof.ru, 0
+gs8.com.tw, 0
+gsier.com.cn, 0
+gskj.gov.cn, 0
+gsmarena.com, 0
+gsmhosting.com, 0
+gsn7.jp, 0
+gso-koeln.de, 0
+g-store.ru, 0
+gstu.by, 0
+gtags.net, 0
+gtk.org, 0
+gtsce.com, 0
+gtshina.ru, 0
+gtue.de, 0
+guadaltel.es, 0
+guagua.cn, 0
+guahao.com, 0
+guanba.com, 0
+guangming.com.my, 0
+guap.ru, 0
+guardian.ng, 0
+guavabooking.com, 0
+guazi.com, 0
+gucheng.com, 0
+gucodd.ru, 0
+gudauri.ru, 0
+guerrillamail.com, 0
+guestcentric.net, 0
+gufener.com, 0
+gufs.org, 0
+guge.xxx, 0
+guguke.net, 0
+guidechem.com, 0
+guide.com.ru, 0
+guifibaix.net, 0
+guifi.net, 0
+guiguiw.com, 0
+guihaibk.com, 0
+guilinbank.com.cn, 0
+gulbenkian.pt, 0
+gulfstream.ru, 0
+gulliway.org, 0
+gullprint.com, 0
+gumrf.ru, 0
+gum.ru, 0
+gundam.eu, 0
+gunserver.ru, 0
+guosen.com.cn, 0
+guostrj.ru, 0
+gup.kz, 0
+gup.ru, 0
+gusline.ru, 0
+gusti-cuir.fr, 0
+gusti-lader.se, 0
+gusti-leder.de, 0
+gustullays.ro, 0
+guu.ru, 0
+gv.com.sg, 0
+gvhouse.com, 0
+gvodbox.com, 0
+gw500.com, 0
+gwales.com, 0
+gwdang.com, 0
+gwifi.com.cn, 0
+gwsecu.com, 0
+gwup.net, 0
+gxdlr.gov.cn, 0
+gxi.gov.cn, 0
+gxnews.com.cn, 0
+gxufe.edu.cn, 0
+gxust.edu.cn, 0
+gyb.ch, 0
+gybond.de, 0
+gyenno.com, 0
+gyertyalang.hu, 0
+gym-gbw.de, 0
+gymlit.cz, 0
+gymnasium-ganderkesee.eu, 0
+gymondo.de, 0
+gym-stolz.de, 0
+gym-training.com, 0
+gyroscope.com, 0
+gz163.cn, 0
+gzedu.com, 0
+gzjjzd.gov.cn, 0
+gzjkw.net, 0
+gzkkonline.com, 0
+gzlanen.com, 0
+gzmpc.com, 0
+gzmtr.com, 0
+gznet.com, 0
+gzpot.com, 0
+gzsfj.gov.cn, 0
+gztz.org, 0
+gzwhir.com, 0
+h1n.ru, 0
+h2opal.com, 0
+h3c.com, 0
+h3yun.com, 0
+h5jun.com, 0
+h6app.com, 0
+haadthip.com, 0
+haahi.com, 0
+haa.su, 0
+habari.co.tz, 0
+habbopoop.org, 0
+haberegider.com, 0
+habito.com, 0
+habitos.mx, 0
+habtium.es, 0
+hacam.me, 0
+hack80.com, 0
+hackacheats.com, 0
+hackademics.fr, 0
+hack.chat, 0
+hack-cn.com, 0
+hac-ker.net, 0
+hackerthemes.com, 0
+hackforums.ru, 0
+hackmygame.info, 0
+hacksbycheats.com, 0
+hacksforcheats.info, 0
+hackspark.fr, 0
+hacpai.com, 0
+hadawebshop.hu, 0
+hadiah.me, 0
+hadiko.de, 0
+haendlerschutz.com, 0
+hageltech.com, 0
+hahaxue.com, 0
+haibei.in, 0
+haier.com, 0
+haier.net, 0
+haihangyun.com, 0
+haimanchajian.com, 0
+haiphong.gov.vn, 0
+hairde.cn, 0
+hair.ms, 0
+hair.su, 0
+haisoft.net, 0
+haiziwang.com, 0
+hajduszoboszlo.hu, 0
+ha-lab.com, 0
+hal.ac.jp, 0
+half-moon.org, 0
+halidi.org, 0
+halihali.tv, 0
+hallard.me, 0
+hallenstadion.ch, 0
+halykbank.kz, 0
+ham3d.co, 0
+hamdi.web.id, 0
+hamfiles.co.uk, 0
+hamhire.com, 0
+haminvara.com, 0
+hamlog.ru, 0
+hamradioshop.it, 0
+hamresan.net, 0
+hamromovie.com, 0
+handball4all.de, 0
+handbrake.fr, 0
+hand-china.com, 0
+handel.pro, 0
+handhand.net, 0
+handicap-job.com, 0
+handicap-love.de, 0
+handyparadies.de, 0
+handy.travel, 0
+hanfan.cc, 0
+hanfverband.de, 0
+hangge.com, 0
+hangzhou.com.cn, 0
+hangzhou.gov.cn, 0
+hanhuazu.cc, 0
+hanjutv.com, 0
+hansn.cn, 0
+hanwha.co.kr, 0
+hanyalewat.com, 0
+hao123.com, 0
+hao24.cn, 0
+hao24.com, 0
+hao76.com, 0
+haoche51.com, 0
+haochedai.com, 0
+haodai.com, 0
+haodianpu.com, 0
+haodou.com, 0
+haofang.net, 0
+haohaizi.com, 0
+haoid.cn, 0
+haojs.cc, 0
+haomaiche.com, 0
+haomwei.com, 0
+haoshitong.com, 0
+haoso.com, 0
+haosou.com, 0
+haosuzhou.com, 0
+haowanyou.com, 0
+haoxiana.com, 0
+haoyangmao8.com, 0
+haozhebao.com, 0
+happeak.ru, 0
+happening.im, 0
+happist.com, 0
+happy88.com, 0
+happyelements.cn, 0
+happyelements.com, 0
+happyjuzi.com, 0
+happyme.club, 0
+happyskin.vn, 0
+happyz.me, 0
+harats.ru, 0
+hardgrand.com, 0
+hardtunedstore.com, 0
+hardwarebg.com, 0
+hargawebsite.com, 0
+haribo.com, 0
+harizanov.com, 0
+haroldltd.ru, 0
+harpacrista.org, 0
+harpoongaming.com, 0
+harpost.com, 0
+harvest.org, 0
+hasgeek.com, 0
+hash-c.co.jp, 0
+hashemian.com, 0
+hashflare.io, 0
+hashkiller.co.uk, 0
+hashlearn.com, 0
+hasjob.co, 0
+haskellstack.org, 0
+hassanabul.com, 0
+hassyon.com, 0
+hasznaltauto.hu, 0
+hasznaltautokereso.hu, 0
+hata.mobi, 0
+hatco.ir, 0
+hausaerzteverband.de, 0
+haus-des-meeres.at, 0
+haushaltshilfe24.at, 0
+haust.edu.cn, 0
+havaforum.com, 0
+hawaii.edu, 0
+hawaiipacifichealth.org, 0
+hayatikodla.net, 0
+haykerproductions.de, 0
+haypost.am, 0
+hays-careers.com, 0
+hazeover.com, 0
+hbcsd.org, 0
+hbhtxx.com, 0
+hb-n-tax.gov.cn, 0
+hboeck.de, 0
+hbooker.com, 0
+hbsc.cn, 0
+hbut.edu.cn, 0
+hc360.com, 0
+hcamur.ru, 0
+hcc.edu.tw, 0
+hclugano.ch, 0
+hc.ru, 0
+hcsibir.ru, 0
+hcs.land, 0
+hd123.com, 0
+hdarea.co, 0
+hdb.com, 0
+hdbox.ws, 0
+hdcity.org, 0
+hdclub.org, 0
+hdclub.sk, 0
+hdcmct.org, 0
+hddlife.com, 0
+hddlife.ru, 0
+hdfax.com, 0
+hd.free.fr, 0
+hdhello.com, 0
+hdhome.org, 0
+hdk.cz, 0
+hdktv.org, 0
+hdmoney.cn, 0
+hdmyjob.com, 0
+hdschools.org, 0
+hdshwh.com, 0
+hdslb.com, 0
+hd-spain.com, 0
+hdtmedia.com, 0
+hdw.la, 0
+head.ru, 0
+headstats.com, 0
+healthday.com.au, 0
+health.nz, 0
+heartbowsmakeup.com, 0
+hearthigen.com, 0
+hearth.net, 0
+heateor.com, 0
+heavytools.hu, 0
+hebaodai.com, 0
+hebei.com.cn, 0
+hebergratuit.net, 0
+hebis.de, 0
+hebut.edu.cn, 0
+hec.gov.pk, 0
+hechonghua.com, 0
+hedonism.com, 0
+hefe-und-mehr.de, 0
+heidelbergerwohnen.de, 0
+heidelpay.de, 0
+heiguang.com, 0
+heilsarmee.ch, 0
+hej.sk, 0
+hekko24.pl, 0
+heliguy.com, 0
+heliohost.org, 0
+heliopark.ru, 0
+helios.kz, 0
+hellclan.co.uk, 0
+hellenicnavy.gr, 0
+hellmann.net, 0
+hellocq.net, 0
+hellotalk.com, 0
+hellotars.com, 0
+hellweg.de, 0
+helmo.be, 0
+helpangel.org, 0
+help.com, 0
+help-im.ru, 0
+helpmij.nl, 0
+helprace.com, 0
+helpshift.com, 0
+helsinn.com, 0
+hemden.de, 0
+hentairules.net, 0
+herbies-herbs.com, 0
+herbolariosiempreviva.com, 0
+hercrentals.com, 0
+hermitageshop.ru, 0
+herni.cz, 0
+herokuapp.com, 0
+heureka.cz, 0
+heureka.sk, 0
+heuteinhamburg.de, 0
+heveya.ru, 0
+heweather.com, 0
+hexieshe.com, 0
+hexindai.com, 0
+hey-ai.com, 0
+heysky.cn, 0
+hgame.com, 0
+hgmail.com, 0
+hgsfss.com, 0
+hgyouxi.net, 0
+hh010.com, 0
+hh2.com, 0
+hhos.ru, 0
+hhwforum.hu, 0
+hiapk.com, 0
+hiapphere.com, 0
+hicraft.cn, 0
+hidalgo.gob.mx, 0
+hidata.org, 0
+hide-my-ip.com, 0
+hi-docs.com, 0
+hidolphin.cn, 0
+hifi.fr, 0
+hifi-tower.co.uk, 0
+hifi-tower.ie, 0
+higherlogic.com, 0
+high-minded.net, 0
+highpin.cn, 0
+highscreen.ru, 0
+hightech.fm, 0
+hihocoder.com, 0
+hihotel.asia, 0
+hiknow.com, 0
+hillstonenet.com, 0
+hinabian.com, 0
+hinaloe.net, 0
+hinata-online-community.fr, 0
+hindustansoftware.in, 0
+hinine.com, 0
+hipac.cn, 0
+hi-pda.com, 0
+hipertextual.com, 0
+hipnosenapratica.com.br, 0
+hippocratesinst.org, 0
+hirealestate.es, 0
+hirede.com, 0
+hiredops.com, 0
+hirist.com, 0
+hisense.com, 0
+his.gov.sd, 0
+hismarttv.com, 0
+histmag.org, 0
+histock.tw, 0
+histoire-image.org, 0
+hisunpharm.com, 0
+hitbox.tv, 0
+hitechboard.ru, 0
+hit.edu.cn, 0
+hitonline.ua, 0
+hitour.cc, 0
+hitrust.com.tw, 0
+hitutor.com.tw, 0
+hiyd.com, 0
+hiyowa.com, 0
+hj-qz.com, 0
+hkbf.org, 0
+hkcccc.org, 0
+hkcompany.org, 0
+hkedu.sh.cn, 0
+hk-lawyer.org, 0
+hkl-baumaschinen.de, 0
+hkst.com, 0
+hksuning.com, 0
+hkust.se, 0
+hkzyy.com.cn, 0
+hlamer.ru, 0
+hldns.ru, 0
+hledejinzerat.cz, 0
+hlidacsmluv.cz, 0
+hm.edu, 0
+hnagroup.com, 0
+hnagroup.net, 0
+hnair.com, 0
+hnair.net, 0
+hndnews.com, 0
+hneao.cn, 0
+hnee.de, 0
+hnks.gov.cn, 0
+hnldesign.nl, 0
+hnr.cn, 0
+hnrsks.com, 0
+hnrsks.gov.cn, 0
+hnteacher.net, 0
+hnu.edu.cn, 0
+hobbybrauerversand.de, 0
+hobby-site.com, 0
+hobimasak.info, 0
+hochanda.com, 0
+hochbahn.de, 0
+hochbahn-direkt.de, 0
+hockey30.com, 0
+hoerbiger.com, 0
+hoffmann-group.com, 0
+hoge.cn, 0
+hoippo.km.ua, 0
+hojitoyz.ir, 0
+hokudai.ac.jp, 0
+hola.com, 0
+holarse-linuxgaming.de, 0
+holder.com.ua, 0
+holema.eu, 0
+hol.es, 0
+holidaycalendar.com, 0
+holike.com, 0
+holime.cz, 0
+hollard.co.za, 0
+hollr2099.ga, 0
+holmesreport.com, 0
+holmglad.edu.hk, 0
+hologfx.com, 0
+holyo.org, 0
+homates.com, 0
+home-cloud.me, 0
+homecloud.pl, 0
+homeip.net, 0
+homelinux.com, 0
+homelinux.org, 0
+homemadetools.net, 0
+homemasters.ru, 0
+homemediaserver.ru, 0
+homenet.org, 0
+homepc.it, 0
+home.pl, 0
+homerez.com, 0
+homeserver.com, 0
+homeservice24.ch, 0
+homeunix.com, 0
+homeworkmarket.com, 0
+homeworkshop.org.uk, 0
+honest-fund.com, 0
+hongweipeng.com, 0
+hongxinbao.com, 0
+honor.es, 0
+honxb.com, 0
+hoop.co.uk, 0
+hoor.ir, 0
+hoornews.com, 0
+hoozin.com, 0
+hopdoddy.com, 0
+hopebilling.com, 0
+hoperun.com, 0
+hoplon.com, 0
+hop-sport.pl, 0
+hopto.org, 0
+horabrasil.com.br, 0
+horariodeapertura24.es, 0
+horki.info, 0
+horoscope.com, 0
+horoscopo.com, 0
+horoshee.fm, 0
+hospedando.com, 0
+hospmall.com, 0
+host4africa.com, 0
+host4g.ru, 0
+hostazor.com.tr, 0
+hostcoz.com, 0
+host-ed.me, 0
+hostedpbx.lu, 0
+hostelmanagement.com, 0
+hoste.pl, 0
+hosteurope.de, 0
+hoste.work, 0
+host-food.ru, 0
+hostforweb.com, 0
+hostiman.ru, 0
+hostingasp.pl, 0
+hostinghouse.pl, 0
+hostingkunde.de, 0
+hostingradio.ru, 0
+hostingtime.de, 0
+hosting.ua, 0
+hostit.ir, 0
+hostitsmart.com, 0
+host.kz, 0
+hostminio.es, 0
+hostpair.com, 0
+hostpark.cn, 0
+hostplus.gr, 0
+hostseo.com, 0
+hostserv.eu, 0
+hostsleek.com, 0
+hostsuki.pro, 0
+host-tracker.com, 0
+hostwp.es, 0
+hostzi.com, 0
+hotbikeweb.com, 0
+hotdealsclub.com, 0
+hot-deals.org, 0
+hotelmix.es, 0
+hotelmix.it, 0
+hotelnow.co.kr, 0
+hotels.ru, 0
+hotelston.com, 0
+hotjob.cn, 0
+ho.ua, 0
+houam.com, 0
+houbank.com, 0
+house365.com, 0
+housingcare.org, 0
+houxue.com, 0
+hoverwatch.com, 0
+howarth-timber.co.uk, 0
+how-living.com, 0
+howoo.net, 0
+howtoinstall.co, 0
+hozehkh.com, 0
+hozi.co.za, 0
+hozobzor.com, 0
+hpc.ru, 0
+hp-lexicon.org, 0
+hponline.cz, 0
+hpplay.com.cn, 0
+hpxy.net, 0
+hqhost.net, 0
+hq-patronen.de, 0
+hqvpn.cn, 0
+hrackarna.cz, 0
+hrbeu.edu.cn, 0
+hrc.govt.nz, 0
+hrjuice.com, 0
+hrlocker.com, 0
+hrloo.com, 0
+hrnz.co.nz, 0
+hro.ru, 0
+hrp.hu, 0
+hrpraktijk.nl, 0
+hrs.cn, 0
+hrsd.com, 0
+hrstop.com, 0
+hrstoppro.com, 0
+hrtl.com.cn, 0
+hrtoday.ch, 0
+hrtpayment.com, 0
+hrwhisper.me, 0
+hs21.de, 0
+hsc.gov.ua, 0
+hschinese.com, 0
+h-schmidt.net, 0
+hscloud.cn, 0
+hse.ru, 0
+hs-furtwangen.de, 0
+hslda.org, 0
+hsw.com.au, 0
+hsweb.me, 0
+htche.com, 0
+htfc.com, 0
+htgwf.com, 0
+ht-line.ru, 0
+htl-klu.at, 0
+htmlweb.ru, 0
+hts.ru, 0
+ht-systems.ru, 0
+httv.de, 0
+htv.bg, 0
+htyd50.com, 0
+htzyw.com, 0
+huai123.me, 0
+huajiao.com, 0
+huangwenchao.com.cn, 0
+huangxiaolong.net, 0
+huanhuba.com, 0
+huanqiushuzi.com, 0
+huashengsheng.com, 0
+huawei.com, 0
+huaxi100.com, 0
+huaxincem.com, 0
+huaxing.com, 0
+huayugame.com, 0
+hub-avocat.fr, 0
+hubcity.ir, 0
+hubeikaowu.com, 0
+hublaa.me, 0
+hubpress.ir, 0
+hubsan.com, 0
+hucheck.com, 0
+hudebnibanka.cz, 0
+huhamhire.com, 0
+huijia.edu.cn, 0
+huilianyi.com, 0
+huimaiche.com, 0
+huim.com, 0
+huimei.com, 0
+huimin.cn, 0
+huishoubao.com, 0
+hulsta.com, 0
+humaxasia.com.tw, 0
+humlak.cz, 0
+humlnet.cz, 0
+hunan.gov.cn, 0
+hunarr.co.in, 0
+hundsun.com, 0
+hunhan.kr, 0
+hunjuwang.com, 0
+hunliji.com, 0
+hunterdouglas.com.ar, 0
+hunters.com, 0
+hunters.sx, 0
+huntnews.in, 0
+huntworld.ru, 0
+huodonghezi.com, 0
+huoduan.com, 0
+huoduan.net, 0
+huodull.com, 0
+huorong.cn, 0
+huox.tv, 0
+huoyunren.com, 0
+hushangcaifu.com, 0
+hust.edu.cn, 0
+hustonline.net, 0
+hustvpn.com, 0
+hutamakarya.com, 0
+huway.com, 0
+huxiu.com, 0
+huzhan.com, 0
+hvaonline.net, 0
+hvf-bs.net, 0
+hvngroups.net, 0
+hwu.edu.tw, 0
+hx9999.com, 0
+hxacc.com, 0
+hxsd.com, 0
+hxtao.site, 0
+hybridmedia.be, 0
+hyipchina.com, 0
+hyip.tc, 0
+hyit.edu.cn, 0
+hymer.com, 0
+hymnal.net, 0
+hyperay.cc, 0
+hyperhosting.gr, 0
+hyperledger.org, 0
+hyperreal.info, 0
+hypers.com, 0
+hypetap.com, 0
+hypnoseries.tv, 0
+hypweb.net, 0
+hytc.edu.cn, 0
+hytera.com, 0
+hzfc.gov.cn, 0
+hzg.de, 0
+hzjcb.com, 0
+hzsh.xyz, 0
+i234.me, 0
+i24.cc, 0
+i3dpworld.com, 0
+i3wm.org, 0
+i4th.in.th, 0
+i7vpnn.com, 0
+i8xiaoshi.com, 0
+iachieved.it, 0
+iae.edu.ar, 0
+iaixue.com, 0
+ialf.edu, 0
+ialpa.net, 0
+iamgstore.com, 0
+iamue.com, 0
+iamwhitneywisconsin.com, 0
+iandunn.name, 0
+iapppay.com, 0
+iariss.fr, 0
+iasassessment.com, 0
+iasbs.ac.ir, 0
+ias.com.tr, 0
+iask.in, 0
+iautos.cn, 0
+ib3tv.com, 0
+ibanquan.com, 0
+ibantang.com, 0
+ibanyu.com, 0
+ibaoyin.com, 0
+ibaren.com, 0
+ibaroody.com, 0
+ibayapp.com, 0
+ibb.waw.pl, 0
+ibc-solar.de, 0
+ibdfam.org.br, 0
+ibero.mx, 0
+ibis.net.ua, 0
+ibooked.com.br, 0
+iboxpay.com, 0
+iboys.at, 0
+iboys.cz, 0
+ibpssc.in, 0
+ibroadlink.com, 0
+ibs.re.kr, 0
+ibs.ru, 0
+ibsys.com, 0
+iburger.bz, 0
+i-cad.fr, 0
+icaile.com, 0
+icard.com, 0
+icasa.ru, 0
+icculus.org, 0
+iccup.com, 0
+icc-usa.com, 0
+icdo.org, 0
+ice-apple.com, 0
+iceberg.ru, 0
+ice-fx.com, 0
+icegram.com, 0
+icej.org, 0
+icetrade.by, 0
+iceveil.com, 0
+icewing.cc, 0
+ichess.es, 0
+ichess.net, 0
+iciba.com, 0
+icicilombard.com, 0
+i-circle.net, 0
+ickd.cn, 0
+iclassx.com, 0
+iclei.org, 0
+icn.org.au, 0
+icourse163.org, 0
+icreator.cn, 0
+icrt.cu, 0
+ict.ac.cn, 0
+icta.lk, 0
+ictb.cz, 0
+icult.ru, 0
+icybee.cn, 0
+icy-veins.com, 0
+idaam.com.br, 0
+idaybreak.com, 0
+idda.com.au, 0
+ideabank.by, 0
+ideachess.com, 0
+ideadunes.com, 0
+ideal.az, 0
+idealkaynak.net, 0
+idealsee.com, 0
+idesa.com.py, 0
+idf.il, 0
+idhost.kz, 0
+idiannaomi.com, 0
+idioma.com, 0
+idirecto.es, 0
+idl.pl, 0
+idmarch.org, 0
+idm.party, 0
+idokep.eu, 0
+idokep.hu, 0
+idokep.ro, 0
+idoklad.cz, 0
+idomix.de, 0
+idope.se, 0
+idport.kz, 0
+idreamsky.com, 0
+idshost.fr, 0
+idsurvey.it, 0
+idtdna.com, 0
+id.uz, 0
+idv.biz, 0
+idv.la, 0
+idwpublishing.com, 0
+idx.com.cn, 0
+iecc.com, 0
+iee.lu, 0
+iemag.ru, 0
+ieminc.com, 0
+iesde.com.br, 0
+iesgrancapitan.org, 0
+iesp.edu.br, 0
+ietv.cc, 0
+ifanqiang.cn, 0
+ifanr.com, 0
+ifcmarkets.ae, 0
+ifcmarkets.com, 0
+ifcmarkets.es, 0
+ifcmarkets.ru, 0
+ifcmir.asia, 0
+ifeng.com, 0
+ifinterface.com, 0
+ifj.edu.pl, 0
+ifjing.com, 0
+iflym.com, 0
+iflysse.com, 0
+ifmo.ru, 0
+ifmsa.pl, 0
+ifnet.or.jp, 0
+ifood360.com, 0
+ifreespeed.com, 0
+ifto.edu.br, 0
+ifz.ru, 0
+igma.ru, 0
+ignatianum.edu.pl, 0
+ignitenet.com, 0
+ignorelist.com, 0
+igola.com, 0
+igoos.net, 0
+igps.ru, 0
+i-gram.ir, 0
+igrarniya.ru, 0
+igrovyeavtomatyvulcan.com, 0
+igrow.cn, 0
+igrushki7.com.ua, 0
+igs-aurichwest.de, 0
+igs-buchholz.de, 0
+igs-linden.eu, 0
+igsmelle.net, 0
+ih5.cn, 0
+ihaima.com, 0
+ihep.ac.cn, 0
+ihewro.com, 0
+ihoc.net, 0
+iho.in, 0
+ihonex.com, 0
+ihr-darlehen.de, 0
+ihrscloud.com, 0
+ihuaben.com, 0
+ihuan.me, 0
+ihx99.vip, 0
+iiapple.com, 0
+iica.in, 0
+iicavers.ru, 0
+ii-i.org, 0
+iiit.ac.in, 0
+iimjobs.com, 0
+iinfo.cz, 0
+iinuu.lv, 0
+iirose.com, 0
+iiss.org, 0
+iitb.ac.in, 0
+iitg.ac.in, 0
+iitp.ru, 0
+ijh.cc, 0
+ijser.cn, 0
+ikalogs.ru, 0
+ikapiracy.com, 0
+ikarussecurity.com, 0
+ikc.edu.tr, 0
+ikiapharm.com, 0
+iki.fi, 0
+iklangratiz.com, 0
+iklub.sk, 0
+iknow.jp, 0
+iknow.travel, 0
+ikraikra.ru, 0
+ikros.sk, 0
+iks.ru, 0
+ikuai8.com, 0
+ilab.cn, 0
+ilam.ac.ir, 0
+ilance.com, 0
+ilanni.com, 0
+ilaoyawo.com, 0
+ilcorsaronero.info, 0
+iletisimmakinesi.com, 0
+iliasnet.de, 0
+iligang.cn, 0
+ilizium.com, 0
+illucit.com, 0
+ilook.by, 0
+ilounge.ua, 0
+ilovemum.ru, 0
+iloveoops.com, 0
+ilucca.net, 0
+ilustra.org, 0
+ilvescovado.it, 0
+ilync.cn, 0
+im9.cz, 0
+imafex.sk, 0
+imageban.ru, 0
+images-du-monde.fr, 0
+imag.fr, 0
+imaginacolombia.com, 0
+imaginarium.com.br, 0
+imaginarium.es, 0
+imarket.by, 0
+imarotulos.com, 0
+imas.me, 0
+imatrix.com, 0
+imaxin.com, 0
+imaxmv.com, 0
+imcn.me, 0
+imcopex.com, 0
+imc.tomsk.ru, 0
+imedi.ge, 0
+imeidata.net, 0
+imei-server.com, 0
+imei-server.ru, 0
+ime.moe, 0
+imenidni.eu, 0
+i-meto.com, 0
+imgchr.com, 0
+img.com.br, 0
+img.com.ua, 0
+imikoko.com, 0
+imin.ru, 0
+immigrationvoice.org, 0
+immmmm.com, 0
+immobiliarefull.com, 0
+immobilienscout24.at, 0
+immobilienscout24.de, 0
+immocha.com, 0
+immotransit.be, 0
+imoffice.com, 0
+imore.com, 0
+impactradius.com, 0
+imperator.club, 0
+imperia-sadovoda.ru, 0
+imperiyanews.ru, 0
+imperosoftware.com, 0
+implyingrigged.info, 0
+impresa.pt, 0
+impressorajato.com.br, 0
+improbable.io, 0
+impulse.de, 0
+imspm.com, 0
+imssx.com, 0
+imsxm.com, 0
+imwork.net, 0
+in66.com, 0
+inaani.com, 0
+inap.gob.ar, 0
+in-berlin.de, 0
+inboxinsight.co.uk, 0
+inbucovina.ro, 0
+incaa.gob.ar, 0
+inc.com, 0
+incircle.jp, 0
+inconcertcc.com, 0
+incontrion.com, 0
+inc.ru, 0
+incust.com, 0
+inc-vrdl.iq, 0
+indamail.hu, 0
+indexa.de, 0
+indexforce.com, 0
+index.org.ru, 0
+indiada.ru, 0
+indiatradefair.com, 0
+indieweb.org, 0
+indirads.work, 0
+indir.biz, 0
+indirimkuponum.net, 0
+individualkimsk.com, 0
+indonesianbacktrack.or.id, 0
+indra.com, 0
+indue.com.au, 0
+indusos.com, 0
+ine.gob.gt, 0
+inera.se, 0
+ines.ro, 0
+inet.edu.ar, 0
+i-news.kz, 0
+inf74.ru, 0
+infars.ru, 0
+infiniflux.com, 0
+infiniti.com.cn, 0
+infinitus.com.cn, 0
+infinitycloud.com, 0
+infinixmobility.com, 0
+infino.me, 0
+infiplay.com, 0
+inflibnet.ac.in, 0
+influans.com, 0
+influencerdb.net, 0
+inflyteapp.com, 0
+info241.com, 0
+infobox.ru, 0
+infobusiness2.ru, 0
+infoherman.com, 0
+infoimoveis.com.br, 0
+infokam.su, 0
+infokartta.fi, 0
+infolan.by, 0
+info-leaks.ru, 0
+infomaniak.ch, 0
+infomaniak.com, 0
+infomercados.com, 0
+infometer.org, 0
+infomir.com.ua, 0
+infomir.eu, 0
+infomiruk.co.uk, 0
+infonavit.org.mx, 0
+infoniqa.com, 0
+infon.ru, 0
+infopraca.pl, 0
+infoprotector.com, 0
+inforesheniya.ru, 0
+inforesist.org, 0
+informamolise.com, 0
+informatics.ru, 0
+information-security.fr, 0
+informika.ru, 0
+inform.kz, 0
+inforoutefpt.org, 0
+infoskidka.ru, 0
+infosliv.club, 0
+infosport.ru, 0
+infoteca.it, 0
+infotec.be, 0
+infotec.com.pe, 0
+info.tm, 0
+infovend.ru, 0
+infovip.biz, 0
+infradead.org, 0
+infrymo.com, 0
+inf.ua, 0
+ingegneriareputazionale.com, 0
+ingeteam.com, 0
+ingress-mosaics.com, 0
+ingrnet.com, 0
+inistrack.net, 0
+initkms.ru, 0
+inits.at, 0
+inje.ac.kr, 0
+injntu.com, 0
+inkdrop.info, 0
+inke.cn, 0
+inke.com, 0
+inklestudios.com, 0
+inloox.com, 0
+inloox.de, 0
+inmart.ua, 0
+inmotionhosting.com, 0
+inmyroom.ru, 0
+innab.org, 0
+innerwise.com, 0
+innolux.com, 0
+innopolis.ru, 0
+innotech.co.jp, 0
+innotechx.com, 0
+inobroker.de, 0
+inonu.edu.tr, 0
+inovance.cn, 0
+inovarmais.com, 0
+inovex.de, 0
+inpa.gov.br, 0
+inpayment.ru, 0
+inplat-tech.com, 0
+inpost.ru, 0
+inpsycho.ru, 0
+inres.sk, 0
+inscripcionscc.com, 0
+inscription-facile.com, 0
+insearch.edu.au, 0
+insertcoin.mx, 0
+insert.com.pl, 0
+insgeek.com, 0
+inshanedesigns.com, 0
+insideblog.org, 0
+insideparadeplatz.ch, 0
+insistpost.com, 0
+inspire-energy.com.cn, 0
+inspur.com, 0
+instabot.ir, 0
+instagramtakiphilesi.com, 0
+instahack.me, 0
+instakib.com, 0
+instalex.ru, 0
+instamc.com.br, 0
+instaps.ru, 0
+instawork.com, 0
+instela.com, 0
+instrumentschedule.com, 0
+insurancenewsnet.com, 0
+insynq.com, 0
+intaa.net, 0
+intant.ru, 0
+inteam.com, 0
+intechinfo.fr, 0
+intechnic.com, 0
+integle.com, 0
+integnity.com, 0
+integralmedica.com.br, 0
+intel-academy.ru, 0
+intelek.cz, 0
+intelipost.com.br, 0
+intelligenceonline.com, 0
+intellij.net, 0
+intelsib.ru, 0
+intelvision.sc, 0
+interaction-design.org, 0
+interactivewebs.com, 0
+interaffairs.ru, 0
+interakt.co, 0
+interalpen.com, 0
+interaxions.ru, 0
+intercity.by, 0
+intermaps.com, 0
+international-license.com, 0
+internations.org, 0
+internetkurse-koeln.de, 0
+internetreputation.com, 0
+internet-verschenkmarkt.de, 0
+internetwerk.de, 0
+internorm.com, 0
+interpane.com, 0
+interpreters.travel, 0
+interra.ru, 0
+interspeedia.com, 0
+intersport.es, 0
+intersport.ru, 0
+inters.ru, 0
+intertop.kz, 0
+intertrustgroup.com, 0
+intertwine.it, 0
+intex.in, 0
+inthepicture.com, 0
+inti.co.id, 0
+intimcity.nl, 0
+intinfra.com, 0
+intnet.dj, 0
+intocareers.org, 0
+intorobot.com, 0
+intovps.com, 0
+intred.it, 0
+intt.gob.ve, 0
+intuit.com, 0
+intuit.ru, 0
+intvua.com, 0
+inventec.com, 0
+investservices.ir, 0
+invoicebus.com, 0
+invoiceplane.com, 0
+inwebpro.gr, 0
+inwx.com, 0
+inwx.de, 0
+iobb.net, 0
+iocenter.ru, 0
+ioe.edu.np, 0
+ioinformatics.org, 0
+iok.la, 0
+iol8.com, 0
+ioliu.cn, 0
+iomedia.ru, 0
+iondigi.com, 0
+ionidea.com, 0
+i-on.net, 0
+iooo.hu, 0
+ios.ac.cn, 0
+iosjailbreak.tech, 0
+iotivity.org, 0
+ip138.com, 0
+ip-188-165-217.eu, 0
+ipalfish.com, 0
+ip-approval.com, 0
+ipaslovakia.sk, 0
+ipb.ac.id, 0
+ipcn.org, 0
+ipdisk.co.kr, 0
+iperf.fr, 0
+ipeye.ru, 0
+ipfs.io, 0
+ip-games.ru, 0
+ipinyou.com, 0
+ipipe.ru, 0
+ipmobilea.com, 0
+ipmu.jp, 0
+ipnxnigeria.net, 0
+ipoint.kz, 0
+ippexpo.org, 0
+ippi.com, 0
+ipresta.ir, 0
+ipricegroup.com, 0
+iprim.ru, 0
+iprotime.com, 0
+ipstock.com, 0
+iptel.org, 0
+iptime.org, 0
+ipxe.org, 0
+iqads.ro, 0
+iqbaby.ru, 0
+iqbusiness.net, 0
+iqit-commerce.com, 0
+iqoption.com, 0
+iqor.com, 0
+iqugroup.com, 0
+iranadsco.com, 0
+iranapp.org, 0
+iran-doc.com, 0
+irangpsmap.com, 0
+iranh.ir, 0
+iranicard.com, 0
+irankhodros.com, 0
+irankiai.lt, 0
+iranmap.biz, 0
+iranmodern.com, 0
+iranmohajerat.ir, 0
+iran-music.com, 0
+irannic.org, 0
+iranonymous.org, 0
+iransamaneh.com, 0
+iranserver.com, 0
+iranshao.com, 0
+irantunez.com, 0
+iranweb.co, 0
+iraqinews.com, 0
+irbib.com, 0
+ircity.ru, 0
+irdp.ac.tz, 0
+ireadercity.com, 0
+iredmail.org, 0
+iresis.com, 0
+irfanview.de, 0
+irgups.ru, 0
+irht.ir, 0
+iriding.cc, 0
+iridize.com, 0
+iriney.ru, 0
+irklib.ru, 0
+irk.ru, 0
+irockbunny.com, 0
+ironplanet.com, 0
+ironwifi.com, 0
+iroot.kr, 0
+irpowerweb.com, 0
+irr.ru, 0
+irsahosting.ir, 0
+irsecteam.org, 0
+irserv.ir, 0
+irun.org, 0
+is74.ru, 0
+isaanco.com, 0
+is-a-geek.com, 0
+is-a-geek.org, 0
+is-best.net, 0
+ischool.com.tw, 0
+i-schools.ru, 0
+iscool.co.il, 0
+isea.ru, 0
+iseehd.tv, 0
+isel.pt, 0
+iserv-gis.de, 0
+ishangzu.com, 0
+ishanitech.biz, 0
+ishansong.com, 0
+ishield.cn, 0
+ishinfo.com, 0
+ishoutbox.com, 0
+ishuhui.com, 0
+isiarussia.ru, 0
+isi.edu, 0
+isif-life.com, 0
+iskmarket.com, 0
+iskn.co, 0
+iskyshop.com, 0
+islands.com, 0
+ismdy.com, 0
+isming.me, 0
+isnap.com, 0
+isoffice.cn, 0
+isolux.ru, 0
+isotools.org, 0
+ispbyte.ru, 0
+ispeak.cn, 0
+ispfr.net, 0
+isqchina.cn, 0
+isqchina.com, 0
+isra.edu.pk, 0
+israela.ru, 0
+israfish.com, 0
+issaplus.com, 0
+issdigitalthe.com.br, 0
+istafrica.com, 0
+istanbulbilisim.com.tr, 0
+istanbulfm.com.tr, 0
+istarshine.com, 0
+istarvip.cn, 0
+istek.edu.az, 0
+istic.ac.cn, 0
+istio.com, 0
+istitutodeglinnocenti.it, 0
+istranet.ru, 0
+istt.ir, 0
+istu.edu, 0
+isu.ru, 0
+isuv.de, 0
+iswind.com, 0
+it2b.com.br, 0
+it376.com, 0
+itaita.ru, 0
+italtronik.it, 0
+italy-vms.ru, 0
+itangyi.com, 0
+itb.ac.id, 0
+itbusiness.com.ua, 0
+itcast.cn, 0
+itchannel.pt, 0
+itcinfotech.com, 0
+itc-life.ru, 0
+itcolima.edu.mx, 0
+it-connection.ru, 0
+it.cx, 0
+itdos.com, 0
+iteam.ru, 0
+itec.es, 0
+itecgoi.in, 0
+itechgyan.com, 0
+itechromania.com, 0
+itehk.com.hk, 0
+itelligence.de, 0
+itelon.ru, 0
+ithmz.com, 0
+ithub.hu, 0
+itiankong.net, 0
+itiffany.cc, 0
+itinsight.pt, 0
+itiscali.cz, 0
+itivi.pl, 0
+itjh.net, 0
+it-kb.ru, 0
+itlab.com.br, 0
+itlalaguna.edu.mx, 0
+itmages.ru, 0
+itm.edu, 0
+itmitte.de, 0
+itmo.com, 0
+itmonline.co.in, 0
+itnull.ru, 0
+itotii.com, 0
+itour.cn, 0
+itouzi.com, 0
+itoyun.cn, 0
+itp.ac.cn, 0
+it.pt, 0
+itransition.com, 0
+itresearches.ir, 0
+itrip.com, 0
+itsajten.se, 0
+itshaman.ru, 0
+itshneg.com, 0
+itsk.com, 0
+itsyourshop.ru, 0
+ittour.com.ua, 0
+ittun.com, 0
+it-tv.org, 0
+itugo.com, 0
+itural.ru, 0
+itworx.com, 0
+itwriter.ru, 0
+ityx.de, 0
+itzmx.com, 0
+i.ua, 0
+iubh.de, 0
+iusss.us, 0
+iust.ac.ir, 0
+iustice.net, 0
+iuventa.sk, 0
+iuvui.net, 0
+ivan-site.com, 0
+ivaoru.org, 0
+ivc34.ru, 0
+ivedu.ru, 0
+ivers.ru, 0
+ivest.kz, 0
+iviewui.com, 0
+ivi.ru, 0
+ivolga.tv, 0
+i-vtb.by, 0
+ivteleradio.ru, 0
+iwant.cz, 0
+iwascoding.com, 0
+iwavesystems.com, 0
+iwin.me, 0
+iwo.es, 0
+iwuzhen.org, 0
+iwww.me, 0
+ixdzs.com, 0
+ixingpan.com, 0
+ixinyou.com, 0
+ixiumei.com, 0
+iyibank.com, 0
+iyingdi.com, 0
+iyiou.com, 0
+iyuce.com, 0
+iyuntoo.com, 0
+iyunv.com, 0
+iyunxiao.com, 0
+izhforum.info, 0
+izhuchuang.com, 0
+izim.az, 0
+izmailovo.ru, 0
+izntz.com, 0
+iztwp.com, 0
+izvestia.ru, 0
+j0.cn, 0
+j2e.com, 0
+jaadee.com, 0
+jaai.cn, 0
+jaas.ac.cn, 0
+jabber.ru, 0
+jac.com.cn, 0
+jackcola.org, 0
+jacksonholewy.com, 0
+jaeapp.com, 0
+jaguar.ru, 0
+jahanscan.ir, 0
+jahanserver.com, 0
+jahwa.com.cn, 0
+jakerevans.com, 0
+jakumo.org, 0
+jalf.com, 0
+jamasp.ir, 0
+jambit.com, 0
+jambler.com, 0
+jamesallen.com, 0
+jammer4uk.com, 0
+jana.com, 0
+janfou.com, 0
+ja.nl, 0
+janosh.com, 0
+jantrish.ru, 0
+japandaisuki.com, 0
+japantrek.ru, 0
+japex.ru, 0
+jap-mom.com, 0
+jaranguda.com, 0
+jardinazuayo.fin.ec, 0
+jarjad.ru, 0
+jarltech.de, 0
+jaroslaw.pl, 0
+javacardos.com, 0
+javamilk.com, 0
+javanonline.ir, 0
+javarush.ru, 0
+javascript.ru, 0
+jawset.com, 0
+jazz-shop.ru, 0
+jc-bingo.com, 0
+jci.cc, 0
+jcndev.com, 0
+jconline.cn, 0
+jcouncil.net, 0
+jcy.gov.cn, 0
+jdair.net, 0
+jdbc.tokyo, 0
+jd.com, 0
+jdlf.com.au, 0
+jdriven.com, 0
+jecvay.com, 0
+jee.io, 0
+jejunu.ac.kr, 0
+jelastic.com, 0
+jellyfish.net, 0
+jenkers.com, 0
+jenniczech.com, 0
+jennifersoft.com, 0
+je-papote.com, 0
+jeppson.org, 0
+jerez.es, 0
+jergym.cz, 0
+jerky.com, 0
+jerryspizza.ro, 0
+jester-soft.ws, 0
+jesuislibre.net, 0
+jesus-comes.com, 0
+jetinsta.com, 0
+jetlovers.com, 0
+jetzt.at, 0
+jewcer.org, 0
+jeyserver.com, 0
+jfservice.ru, 0
+jfz.com, 0
+jg-gta.com, 0
+jgospel.net, 0
+jhddg.com, 0
+jhs.ch, 0
+jhsnet.org, 0
+jhu.edu, 0
+jia.com, 0
+jiae.com, 0
+jiahao.me, 0
+jian40.com, 0
+jiandaoyun.com, 0
+jiangmen.gov.cn, 0
+jiangnan.edu.cn, 0
+jianjiaobuluo.com, 0
+jiankang51.cn, 0
+jiankang.com, 0
+jianyezuqiu.cn, 0
+jianzhimao.com, 0
+jiashuangkuaizi.com, 0
+jiashuangkuaizi.com.cn, 0
+jiasule.com, 0
+jiaxincloud.com, 0
+jiayougo.com, 0
+jicin.cz, 0
+jiecao.fm, 0
+jiedaibao.com, 0
+jiedai.cn, 0
+jieliku.com, 0
+jiemodui.com, 0
+jieyitong.cn, 0
+jiitsimplified.com, 0
+jijiys.com, 0
+jike.info, 0
+jikewenku.cn, 0
+jileniao.net, 0
+jiloc.com, 0
+jiluxinqing.com, 0
+jin10.com, 0
+jindl.com.cn, 0
+jingletruck.com, 0
+jingruis.com, 0
+jinkan.org, 0
+jinnong.cn, 0
+jinri.cn, 0
+jinritemai.com, 0
+jinr.ru, 0
+jinshangdai.com, 0
+jinshuju.com, 0
+jinshuju.net, 0
+jinxin99.cn, 0
+jinzhoubank.com, 0
+jios.org, 0
+jisutiyu.com, 0
+jit.edu.cn, 0
+jitterclick.it, 0
+jiu6.com, 0
+jiuguge.com, 0
+jiuxian.com, 0
+jiuzhang.net, 0
+jiuzhilan.com, 0
+jivaro.com, 0
+jixuanran.com, 0
+jj.cn, 0
+jjmmw.com, 0
+jkpan.cc, 0
+jl.gov.cn, 0
+jlmedu.com, 0
+jlnu.edu.cn, 0
+jlpay.com, 0
+jlu.edu.cn, 0
+jluzh.com, 0
+jmc.asia, 0
+jme.com, 0
+jmmama.com.cn, 0
+jmoins.fr, 0
+jmramirez.pro, 0
+jmtw.cc, 0
+jmyan.com, 0
+jnbhgbox.org, 0
+job-63.ru, 0
+jobbik.hu, 0
+jobcluster.de, 0
+jobindo.com, 0
+jobitus.com, 0
+jobmixer.com, 0
+jobnet.com.tw, 0
+job.ru, 0
+job-sbu.org, 0
+jobthai.com, 0
+jodies.de, 0
+jodoplay.com, 0
+joelmediatv.de, 0
+joeyh.name, 0
+johanpaul.net, 0
+joiiup.com, 0
+joinfcloud.com, 0
+joinquant.com, 0
+joins-job.com, 0
+joinsquad.ru, 0
+joker.com, 0
+jokerkartenwelt.de, 0
+jolco.com, 0
+joomlagate.com, 0
+joomlashop.org, 0
+joseantoniomadrigal.com, 0
+josefprusa.cz, 0
+jostle.me, 0
+joubert-change.fr, 0
+joudou.com, 0
+jourdegalop.com, 0
+journeyman.tv, 0
+joybomb.com.tw, 0
+joyfulhonda.com, 0
+joykidshop.com, 0
+joyland.se, 0
+joyme.com, 0
+joyomm.com, 0
+joyoung.com, 0
+joyowo.com, 0
+jozsefattilaszinhaz.hu, 0
+jpgazeta.ru, 0
+jpg.wtf, 0
+jplopsoft.idv.tw, 0
+jpmarumaru.com, 0
+jpmens.net, 0
+jp.net, 0
+jpn.ph, 0
+jpwind.com, 0
+jqpublicblog.com, 0
+jquery.re, 0
+jrj.com.cn, 0
+jrmf360.com, 0
+js7tv.cn, 0
+js99cf.com, 0
+jsbc.com, 0
+jsinfo.net, 0
+jsj.com.cn, 0
+jslib.org.cn, 0
+jsrun.net, 0
+j-stash.club, 0
+jst-hosp.com.cn, 0
+jstv.com, 0
+jsychrss.gov.cn, 0
+jtfa.cn, 0
+jtljia.com, 0
+jtmfoodgroup.com, 0
+jtthink.com, 0
+ju53.com, 0
+juandemariana.org, 0
+juanpi.com, 0
+juanpi.org, 0
+jubaopay.com, 0
+juben108.com, 0
+jubna.com, 0
+jubushoushen.com, 0
+jucaicat.com, 0
+juesheng.com, 0
+juhe.cn, 0
+juick.com, 0
+juicysexstories.com, 0
+juii.net, 0
+juju.com, 0
+julianhuang.cc, 0
+julyedu.com, 0
+jumei.com, 0
+jumin.cc, 0
+juming.com, 0
+jumpingcrab.com, 0
+jumpserver.org, 0
+juneinter.com, 0
+juneyaoair.com, 0
+jung.de, 0
+jungle-world.com, 0
+juniperresearch.com, 0
+juniqe.com, 0
+junkart.in, 0
+junlin.li, 0
+juntong.or.kr, 0
+junzejun.com, 0
+jupem.gov.my, 0
+jupiterhell.com, 0
+jurion.de, 0
+jusha.com, 0
+justarchi.net, 0
+justcoded.com, 0
+just-half-price.dk, 0
+just-hosting.ru, 0
+justhost.ru, 0
+justmoda.ru, 0
+just.social, 0
+justwinit.cn, 0
+juzhao.net, 0
+juzilab.com, 0
+juziplus.net, 0
+jv.ru, 0
+jvstoronto.org, 0
+jvtuiba.com, 0
+jvweb.fr, 0
+jvweb.org, 0
+jxcad.com.cn, 0
+jx.cn, 0
+jxt189.com, 0
+jxzmz.org, 0
+jy391.com, 0
+jyall.com, 0
+jyh.com, 0
+jylc168.com, 0
+jzez100.com, 0
+jzteyao.com, 0
+k12.al.us, 0
+k12.ca.us, 0
+k12china.com, 0
+k12.ia.us, 0
+k12.ma.us, 0
+k12.me.us, 0
+k12.ms.us, 0
+k12.ne.us, 0
+k12.ny.us, 0
+k12.or.us, 0
+k12.pa.us, 0
+k12.va.us, 0
+k1kan.cc, 0
+k31.ru, 0
+k3.cn, 0
+k3idc.com, 0
+k5-conference.com, 0
+k7computing.com, 0
+k8dy.top, 0
+kaartenhuis.nl, 0
+kaartje2go.nl, 0
+kabbalahgroup.info, 0
+kabbalah.info, 0
+kachon.com, 0
+kade.de, 0
+kadinca.club, 0
+kadrovik.ru, 0
+kadu.ru, 0
+kaedea.com, 0
+kaede.jp, 0
+kaercher.com, 0
+kafascript.com, 0
+kafazan.com, 0
+kaganonline.com, 0
+kagawa.jp, 0
+kagirl.cn, 0
+kagithane.bel.tr, 0
+kags.com, 0
+kaifakuai.com, 0
+kaikeba.com, 0
+kaike.la, 0
+kaimi.io, 0
+kaist.ac.kr, 0
+kaixian.tv, 0
+kajot-casino.com, 0
+kajot.cz, 0
+kakolijeciti.com, 0
+kakpravilnosdelat.ru, 0
+kakuro-knacker.de, 0
+kalcaddle.com, 0
+kaleostra.com, 0
+kalibr603.ru, 0
+kaluga-gov.ru, 0
+kalvin.cn, 0
+kalyanamitra.org, 0
+kalyanis.ru, 0
+kalyanmir.ru, 0
+kalyanvkarmane.ru, 0
+kamaran.ru, 0
+kamaz.ru, 0
+kameleoon.com, 0
+kamensktel.ru, 0
+kamenwang.com, 0
+kametsu.com, 0
+kamgov.ru, 0
+kamjachoob.com, 0
+kamo-uniforma.ru, 0
+kamrad.ru, 0
+kanagawa.jp, 0
+kanalizaciyavdome.ru, 0
+kancapos.com, 0
+kancelarskezidle.com, 0
+kancloud.cn, 0
+kandasoft.com, 0
+kandianying.tv, 0
+kaneland.org, 0
+kanet.ru, 0
+kangmei.com.cn, 0
+kangndo.com, 0
+kangou.cn, 0
+kanibaspinar.net.tr, 0
+kannadigaworld.com, 0
+kanyanbao.com, 0
+kanyewestshoe.com, 0
+kanyewestsneakers.com, 0
+kanz.jp, 0
+kaolalicai.cn, 0
+kaomanfen.com, 0
+kaonsoftwares.com, 0
+kaoputou.com, 0
+kaoyan.com, 0
+kapaza.be, 0
+kapitalbank.az, 0
+kapitalbank.uz, 0
+kapitosha.net, 0
+kapten-son.com, 0
+karandash.by, 0
+karaoteca.com, 0
+karate.ru, 0
+karatov.com, 0
+karcher.ru, 0
+karelia.pro, 0
+karex.ru, 0
+kargo.com, 0
+karibiya.ru, 0
+karl.com, 0
+karmagroup.com, 0
+karmania-auto.ir, 0
+karner-dechow.at, 0
+karofilm.ru, 0
+karpvp.net, 0
+kartagrada.ru, 0
+kartasportowa.pl, 0
+kartina.tv, 0
+kartinatv.co.il, 0
+kartinfo.me, 0
+kartkolandia.pl, 0
+kartoteka.by, 0
+karwan.cn, 0
+kasaba.uz, 0
+kasperskyclub.ru, 0
+kaspersky.ru, 0
+kassa.uz, 0
+kassir.kz, 0
+kastnersw.cz, 0
+katacoda.com, 0
+katatelecom.com, 0
+katetooncopywriter.com.au, 0
+kau-boys.com, 0
+kau-boys.de, 0
+kaufen.com, 0
+kaufmann.dk, 0
+kauf.sk, 0
+kaunoenergija.lt, 0
+kautbullinger.de, 0
+kavehglass.com, 0
+kavehome.com, 0
+kawasaki-net.ne.jp, 0
+kazagro.kz, 0
+kazakhmys.kz, 0
+kazakh-zerno.kz, 0
+kaze-travel.co.jp, 0
+kazminerals.com, 0
+kaznau.kz, 0
+kazntu.kz, 0
+kazpost.kz, 0
+kaztranscom.kz, 0
+kaztransoil.kz, 0
+kaztrk.kz, 0
+kb20.cc, 0
+kbb1.com, 0
+kbcnet.rs, 0
+kbdyw.com, 0
+kbrnet.ru, 0
+kbs.co.kr, 0
+kbstar.com, 0
+kbtu.kz, 0
+kcg.gov.tw, 0
+kcloud.me, 0
+kcorp.sk, 0
+kc-shoes.ru, 0
+kcsnet.or.kr, 0
+kddi.com, 0
+kde.org, 0
+kdevelop.org, 0
+kdliker.com, 0
+kdl.org, 0
+kdslife.com, 0
+ke8u.com, 0
+keaz.ru, 0
+kebudayaanindonesia.net, 0
+kechlibar.net, 0
+kedou.com, 0
+keejob.com, 0
+keelbeel.com, 0
+keepfree.de, 0
+keepo.me, 0
+keep.pl, 0
+keft.ru, 0
+kejianet.cn, 0
+kelasexcel.web.id, 0
+kemdikbud.go.id, 0
+kenfor.com, 0
+kenh76.vn, 0
+kenkaitube.com, 0
+kentrade.go.ke, 0
+kepeslap.hu, 0
+kerawa.com, 0
+kerch.net, 0
+keri.re.kr, 0
+kerneleros.com, 0
+kernelnewbies.org, 0
+kernel.org, 0
+kerosoft.com, 0
+ketabrah.ir, 0
+ketabshop.ir, 0
+ketangpai.com, 0
+ketianyun.com, 0
+kevinguanchedarias.com, 0
+kewaimiao.com, 0
+kexindai.com, 0
+key4math.com, 0
+keyboardmaestro.com, 0
+keybr.com, 0
+keylol.com, 0
+keymachine.de, 0
+keysystems.ru, 0
+keytrade.com, 0
+keyweb.de, 0
+keywordinspector.com, 0
+kfc.ru, 0
+kg7.ru, 0
+kgeu.ru, 0
+kgh.on.ca, 0
+kgs-drochtersen.de, 0
+kgsu.ru, 0
+khabshop.com, 0
+khai.edu, 0
+khaneirany.com, 0
+kharidaram.com, 0
+kharidazma.com, 0
+khatvongsong.vn, 0
+kh.edu.tw, 0
+khhq.net, 0
+khidmatnegara.gov.my, 0
+khnu.km.ua, 0
+khosousi.com, 0
+khotkovo.net, 0
+khstu.ru, 0
+khv.gov.ru, 0
+khv.ru, 0
+kia.ru, 0
+kichler.com, 0
+kick9.com, 0
+kick.lv, 0
+kicks-ass.net, 0
+kicksdaily.net, 0
+kickservapp.com, 0
+kickz.com, 0
+kidcheck.com, 0
+kid-control.com, 0
+kiddywood.ru, 0
+kidlogger.net, 0
+kidscasting.com, 0
+kidsmusic.info, 0
+kids-price.ru, 0
+kievcity.gov.ua, 0
+kimsufi.com, 0
+kinderedu.ru, 0
+kindertelefoon.nl, 0
+kineme.net, 0
+kingdee.com, 0
+kingnet.com.tw, 0
+kingoapp.com, 0
+kingpokers.com, 0
+kingsoft.net, 0
+kingss.win, 0
+kingsunsoft.com, 0
+kinhom.com, 0
+kinokosmos.ee, 0
+kinoloop.ru, 0
+kinoluvr.net, 0
+kinomarvel.info, 0
+kinonews.de, 0
+kinopark.kz, 0
+kinopik.info, 0
+kinoscenariy.net, 0
+kinosearch.me, 0
+kinosky.net, 0
+kinosmena.ru, 0
+kinotut.org, 0
+kinovinki.net, 0
+kinozal.cc, 0
+kinozal.website, 0
+kippee.com, 0
+kippnyc.org, 0
+kiprinform.com, 0
+kipspb.ru, 0
+kirmiziperfect.com, 0
+kirpalani.com, 0
+kissandfly.at, 0
+kissandfly.com, 0
+kissandfly.de, 0
+kissfm.md, 0
+kit.ac.jp, 0
+kitchenmag.ru, 0
+kitenet.ru, 0
+kitwee.com, 0
+kiwihk.net, 0
+kiwi.nz, 0
+kiwitaxi.com, 0
+kiwitaxi.ru, 0
+kiyu.tw, 0
+kjb-connect.com, 0
+kjds.com, 0
+kjm6.de, 0
+kjson.com, 0
+kjvvv.kr, 0
+kkguan.com, 0
+kkmcom.ru, 0
+kknyazeva.ru, 0
+kktv8.com, 0
+kku.ac.kr, 0
+kku.ac.th, 0
+klagemauer.tv, 0
+klarstein.com, 0
+klarstein.fr, 0
+klarstein.hu, 0
+klarstein.it, 0
+klarstein.sk, 0
+kla.tv, 0
+klavtorg.ru, 0
+kl.com.ua, 0
+kldp.org, 0
+kl.edu.tw, 0
+kleeneze.co.uk, 0
+kleotour.ru, 0
+kler.pl, 0
+klickmail.com.br, 0
+klick-tipp.com, 0
+klimatex.eu, 0
+klogeschichten.net, 0
+kloud51.com, 0
+klubcytrynki.pl, 0
+klv-oboi.ru, 0
+kmf.com, 0
+kmu.ac.ir, 0
+kmu.gov.ua, 0
+kmuh.org.tw, 0
+kmutt.ac.th, 0
+kmway.com, 0
+knastu.ru, 0
+knet.cn, 0
+kneu.edu.ua, 0
+knigafund.ru, 0
+knightfrank.com, 0
+knighthunter.com, 0
+knigogid.ru, 0
+knigosvet.com, 0
+knowbox.cn, 0
+knowledgehook.com, 0
+knutd.com.ua, 0
+knutd.edu.ua, 0
+knu.ua, 0
+kobayashi.co.jp, 0
+koblist.com, 0
+kochanhaengerwerke.de, 0
+koenig-solutions.com, 0
+kolgot.net, 0
+kolhoz.mobi, 0
+kolosej.si, 0
+komcity.ru, 0
+komersa.lv, 0
+komicolle.org, 0
+komi-news.ru, 0
+komoot.de, 0
+komparify.com, 0
+kompas.si, 0
+komtv.org, 0
+konduit.io, 0
+konicaminolta.com.cn, 0
+konigchain.com, 0
+konstanz.de, 0
+kontestapp.com, 0
+konwerter.net, 0
+konzolokszervize.hu, 0
+koo.cn, 0
+kookit.com, 0
+kookje.ac.kr, 0
+koolearn.com, 0
+kooxpi.com, 0
+kopeysk24.ru, 0
+kopilkaclub.ru, 0
+korea.ac.kr, 0
+koreastardaily.com, 0
+korenpub.com, 0
+koreus.com, 0
+korex.co.kr, 0
+kornit.com, 0
+koronacloud.com, 0
+koshelek.kz, 0
+koshikira.de, 0
+kosice.sk, 0
+kosmos-kino.ru, 0
+kosmos-x.net.ru, 0
+kotitorni.com, 0
+koule.cz, 0
+koulouba.com, 0
+kovrov.net, 0
+kpfu.ru, 0
+kpi.kharkov.ua, 0
+kplus.pro, 0
+kpoly.edu.gh, 0
+kq88.com, 0
+krakow.pl, 0
+kralici.cz, 0
+kralmp3.org, 0
+kramtp.info, 0
+krasgmu.ru, 0
+kraslan.ru, 0
+krasmama.ru, 0
+krasno.ru, 0
+krasview.ru, 0
+krautchan.net, 0
+krebsforum-fuer-angehoerige.de, 0
+kreditech.com, 0
+kre.hu, 0
+kresla-market.ru, 0
+k-res.net, 0
+kr.gov.ua, 0
+krita.org, 0
+krl.co.id, 0
+kro.kr, 0
+krones.com, 0
+krosno.com.pl, 0
+kros.sk, 0
+krsn.ru, 0
+krsu.edu.kg, 0
+kr-ustecky.cz, 0
+krutomer.ru, 0
+ksamata.ru, 0
+ksbao.com, 0
+ksd-i.com, 0
+ksil.com, 0
+ksivi.co, 0
+ksivi.pro, 0
+ksk66.ru, 0
+ksmx.me, 0
+ksoa.net, 0
+kspu.ru, 0
+ksrf.ru, 0
+kss45.ru, 0
+kstp.ir, 0
+kstu.kg, 0
+kstu.ru, 0
+ksu.edu.tw, 0
+ksu.kz, 0
+ksyic.com, 0
+kt.am, 0
+ktb.com.tw, 0
+ktb.co.th, 0
+k-telecom.org, 0
+kth.se, 0
+ktng.com, 0
+ktokogda.com, 0
+ktovkurse.com, 0
+ktze.kz, 0
+kuadro.com.br, 0
+kuaidi.com, 0
+kuaidihelp.com, 0
+kuaidi.hk, 0
+kuaikanmanhua.com, 0
+kuaishou.com, 0
+kuaiyun.cn, 0
+kuaxue.com, 0
+kubaninstrument.ru, 0
+kubankredit.ru, 0
+kubannet.ru, 0
+kubsau.ru, 0
+kubstu.ru, 0
+kucharkaprodceru.cz, 0
+kudo.co.id, 0
+kueiwa.com, 0
+kufatec.de, 0
+kugou.net, 0
+kuguya.com, 0
+kuitao8.com, 0
+kukmin.tv, 0
+kukubt.com, 0
+kuku.lu, 0
+kullsms.com, 0
+kulturniportal.cz, 0
+kumamoto.jp, 0
+kunstnet.de, 0
+kupai.me, 0
+kupi-prodai.kz, 0
+kuponuna.com, 0
+kupplung.at, 0
+kupplung.de, 0
+kuraldisi.com, 0
+kurien.co.kr, 0
+kurier.at, 0
+kursoteka.ru, 0
+kurtizanki.su, 0
+kurzy.sk, 0
+kusuriexpress.com, 0
+kutnahora.cz, 0
+kuvajmo-blogovski.com, 0
+kuwo.cn, 0
+kuz.ua, 0
+kvaclub.ru, 0
+kvado.ru, 0
+kvarnado.ru, 0
+kvartiranasutki.by, 0
+kvartplata.info, 0
+kvcc.edu, 0
+kvernelandgroup.com, 0
+kwant-project.org, 0
+kwps.info, 0
+kws7.com, 0
+kxtui.com, 0
+kyberia.sk, 0
+kyiv.ua, 0
+kylesfileserver.org, 0
+kylos.pl, 0
+kymcolux.com, 0
+kyoceramobile.com, 0
+kyoto-wu.ac.jp, 0
+kysto.com, 0
+kzn.ru, 0
+kzwr.com, 0
+l2jbrasil.com, 0
+l3600.com, 0
+l4m.fr, 0
+laartcc.org, 0
+lab4u.ru, 0
+labazur.com, 0
+labelup.ru, 0
+labelzone.co.uk, 0
+labix.org, 0
+labmedica-patient.fr, 0
+laboradian.com, 0
+labruixador.es, 0
+lacl.fr, 0
+lacompagnie.com, 0
+lacomunity.com, 0
+lacotto.jp, 0
+lada.kz, 0
+ladige.it, 0
+ladya-avto.ru, 0
+ladyband.com, 0
+ladybirds.ru, 0
+ladyclick.ru, 0
+ladyplace.ru, 0
+lae-edu.com, 0
+laekh.de, 0
+lael.be, 0
+lafibre.info, 0
+lagarderob.ru, 0
+lagence.pt, 0
+laguiaw.com, 0
+lagunacity.ru, 0
+lairen.com, 0
+lakana.com, 0
+lalettrea.fr, 0
+lalilali.com, 0
+laltroweb.it, 0
+lambertgroup.ro, 0
+lames.jp, 0
+lamptkes.org, 0
+lan1.de, 0
+lance.moe, 0
+lancloud.ru, 0
+landiannews.com, 0
+landi.com, 0
+landicorp.com, 0
+landmarklondon.co.uk, 0
+landray.com.cn, 0
+landrover.ru, 0
+lanet.lv, 0
+lanet.me, 0
+lanet.ua, 0
+lanfw.com, 0
+langageoral.com, 0
+langate.tv, 0
+langhamhotels.com, 0
+langland.cc, 0
+langren8.com, 0
+lanieri.com, 0
+lanik.us, 0
+lanit.ru, 0
+lanseyujie.com, 0
+lanterncn.cn, 0
+lanzou.com, 0
+laocaibao.com, 0
+laparfumerie.ru, 0
+laplacinte.ro, 0
+laplagnet.com, 0
+lap-publishing.com, 0
+laptopg7.vn, 0
+laptopszaki.hu, 0
+laptopvip.vn, 0
+laravist.com, 0
+laraweb.ir, 0
+lardbucket.org, 0
+largadoemguarapari.com.br, 0
+larinshop.com, 0
+larsjung.de, 0
+larusodejda.ru, 0
+laserbits.com, 0
+laserline.de, 0
+lasignificationprenom.com, 0
+lasindias.com, 0
+laspace.ru, 0
+last2ticket.com, 0
+lastationdeski.com, 0
+latamautos.com, 0
+latetrain.cn, 0
+lativ.com, 0
+lativ.com.tw, 0
+latoquedor.com, 0
+latvenergo.lv, 0
+latymer.co.uk, 0
+laukar.com, 0
+launchaco.com, 0
+lausanne.ch, 0
+lavaradio.com, 0
+lavector.com, 0
+lavitrinedelamode.com, 0
+lawfulpath.com, 0
+law-school.de, 0
+layabox.com, 0
+layouteditor.net, 0
+laziodisu.it, 0
+lazurit.com, 0
+lazyland.net, 0
+lazytool2.com, 0
+lbgoo.com, 0
+lbxcn.com, 0
+lbyx.cn, 0
+lcbk.net, 0
+lcd1.ru, 0
+lcgitsystems.com.br, 0
+lcxzs.cn, 0
+lcygroup.com, 0
+ldap-account-manager.org, 0
+ldcx.net, 0
+ldichina.com, 0
+ldiglobal.org, 0
+leadbit.com, 0
+leadercf.com, 0
+leader-id.ru, 0
+leadermt.ru, 0
+leadingsoft.com, 0
+leadiq.io, 0
+leadsale.com, 0
+leadvertex.ru, 0
+leaf-hide.jp, 0
+league-mastery.com, 0
+leandev.cn, 0
+leangoo.com, 0
+leanlabs.io, 0
+learnamatrol.com, 0
+learnattack.de, 0
+learning2learn.cn, 0
+learninghabitat.org, 0
+learningshop.com, 0
+learnsoci.al, 0
+leavesongs.com, 0
+leawo.com, 0
+leboncoin.fr, 0
+lecake.com, 0
+leclick.ru, 0
+lecloud.com, 0
+lede-project.org, 0
+ledwatts.fr, 0
+leechking.com, 0
+leeet.net, 0
+leet.cc, 0
+leforumcatholique.org, 0
+lefresnoy.net, 0
+legadelfilodoro.it, 0
+legalacts.ru, 0
+legalaid.gov.ua, 0
+legal-alien.ru, 0
+legavolleyfemminile.it, 0
+leg.br, 0
+legendsec.com, 0
+legionowo.pl, 0
+legnica.pl, 0
+legrandchangement.com, 0
+legrandchangement.tv, 0
+lehangart.com, 0
+lehner-versand.ch, 0
+lehrerfortbildung-bw.de, 0
+leibnitz.net, 0
+leicashop.ir, 0
+leidiandian.com, 0
+leiner.at, 0
+leju.com, 0
+lemeids.com, 0
+lemezkucko.hu, 0
+lemoboo.de, 0
+lemonnow.com, 0
+lemonsay.com, 0
+lemurov.net, 0
+lending51.com, 0
+lendio.com, 0
+lendock.com, 0
+lendon.pl, 0
+lenfilm.ru, 0
+leniter.org, 0
+lenizdat.ru, 0
+lennoxintl.com, 0
+lenobl.ru, 0
+lenovo.com, 0
+lenovo.com.cn, 0
+lenreg.ru, 0
+leomadeiras.com.br, 0
+leoneteam.com, 0
+leonrestaurants.co.uk, 0
+leopays.com, 0
+leplandiscret.com, 0
+lepu.cn, 0
+lepumedical.com, 0
+lerevecraze.com, 0
+lesieur.fr, 0
+lesiteimmo.com, 0
+lesk.ru, 0
+lestendances.fr, 0
+lestheatres.net, 0
+lesy.sk, 0
+letgo.com, 0
+letitfly.me, 0
+lets-farm.com, 0
+letsfilm.org, 0
+lets-fish.com, 0
+lets-hunt.com, 0
+letsinvite.xyz, 0
+letstalkpayments.com, 0
+letu.ru, 0
+letu.ua, 0
+leupay.eu, 0
+levelup.in.th, 0
+levneknihy.cz, 0
+lewaimai.com, 0
+lewaos.com, 0
+lewei50.com, 0
+lexdir.com, 0
+lextel.it, 0
+leya.com, 0
+leyifan.com, 0
+leyue100.com, 0
+lfrm.net, 0
+lfs.org.uk, 0
+lgallardo.com, 0
+lgek.ru, 0
+lgg.ru, 0
+lhageek.com, 0
+lh-broker.ru, 0
+lh.or.kr, 0
+lhoroscope.com, 0
+liangxinyao.com, 0
+lianshang.com, 0
+lianyexiuchang.in, 0
+liaohuqiu.net, 0
+libbs.com.br, 0
+libertex.com, 0
+libertex.org, 0
+liberty.me, 0
+libnvkz.ru, 0
+libraryofbabel.info, 0
+library.sh.cn, 0
+libreoffice.org, 0
+libreriacoletti.it, 0
+libri.it, 0
+libro.at, 0
+libroco.it, 0
+libros.ink, 0
+libsdl.org, 0
+libsmr.ru, 0
+libvirt.org, 0
+license.ddns.net, 0
+licenseha.com, 0
+lichanglin.cn, 0
+lider-exp.ru, 0
+lidgroup.ru, 0
+liesegang-partner.de, 0
+lieyunwang.com, 0
+lifan.moe, 0
+life2film.com, 0
+lifefood.eu, 0
+lifehacker.ru, 0
+lifeline.org.au, 0
+life-realty.ru, 0
+lifeseasy.com.cn, 0
+lifestyle4living.de, 0
+lifestyle.ng, 0
+lifetyper.com, 0
+lifo.gr, 0
+ligainternet.ru, 0
+liga.net, 0
+ligerelectronics.com, 0
+lightc.com, 0
+lighthouse.gr, 0
+lightss.co, 0
+lightstar.ru, 0
+ligloo.fr, 0
+liguebretagnebillard.fr, 0
+like4u.ru, 0
+likefifa.ru, 0
+likelo.ws, 0
+likesnew.ru, 0
+likewear.ru, 0
+likinming.com, 0
+lilanz.com, 0
+lileesystems.com, 0
+lilletourism.com, 0
+lima-city.de, 0
+lime-shop.ru, 0
+limh.me, 0
+limijiaoyin.com, 0
+limin.com, 0
+limuzhengxin.com, 0
+linban.com, 0
+lindner-group.com, 0
+linekong.com, 0
+linemedia.ru, 0
+linewell.com, 0
+linghit.com, 0
+lingla.com, 0
+linglongtech.com, 0
+linguanet.ru, 0
+linguarana.com, 0
+linguitronics.com, 0
+linhadefensiva.org, 0
+linkello.com, 0
+linkpc.net, 0
+linkup.com, 0
+linsenpate.de, 0
+lintut.com, 0
+linux62.org, 0
+linuxcenter.kz, 0
+linux.cn, 0
+linuxeye.com, 0
+linuxfoundation.org, 0
+linuxihaa.ir, 0
+linuxito.com, 0
+linux-mips.org, 0
+linux-mm.org, 0
+linux-onlineshop.de, 0
+linuxpl.eu, 0
+linuxsecurity.com, 0
+linuxsoid.com, 0
+linux-tips-and-tricks.de, 0
+linzi.ru, 0
+linzy.ru, 0
+lionfree.net, 0
+lions.de, 0
+liotech.ru, 0
+lipi.go.id, 0
+liqu.com, 0
+liquidation.com, 0
+liquid-life.de, 0
+liquidm.com, 0
+lirise.com, 0
+lirn.net, 0
+lis99.com, 0
+listafirme.ro, 0
+listcarbrands.com, 0
+listenflower.com, 0
+listenod.ru, 0
+listingdomsearch.com, 0
+listupp.com.br, 0
+listupp.es, 0
+listupp.fr, 0
+listupp.it, 0
+listupp.pl, 0
+listupp.ru, 0
+liteforex.com, 0
+liteforex.ru, 0
+litl-admin.ru, 0
+littlecaprice-dreams.com, 0
+littlelunch.de, 0
+littleswan.com, 0
+liturgia.pt, 0
+liu.ba, 0
+liubingyang.com, 0
+liugong.com, 0
+liujason.com, 0
+liujunchen.xyz, 0
+liuzhichao.com, 0
+livacha.com, 0
+livecoding.tv, 0
+livecoins.ru, 0
+livefast.it, 0
+livehome3d.com, 0
+livelivelive.com, 0
+livepda.ru, 0
+liveschool.net, 0
+livescore.com, 0
+livescore.co.uk, 0
+livetyping.com, 0
+living-bots.net, 0
+livingnaturally.com, 0
+livrenet.ru, 0
+liwai.com, 0
+lixin.edu.cn, 0
+liyang.io, 0
+liyathabara.com, 0
+liyunde.com, 0
+lizhenwang.cn, 0
+lizhenwang.com, 0
+lizhi.fm, 0
+lizhi.io, 0
+lizhiweike.com, 0
+lizi.com, 0
+lizihang.com, 0
+ljscripts.com, 0
+ljsilvers.com, 0
+lj-top.ru, 0
+lkker.com, 0
+lks-tv.ru, 0
+llamayamovil.com, 0
+lmcservers.com, 0
+lmdinteractive.com, 0
+lmt.lv, 0
+lncc.br, 0
+lnka.cn, 0
+lnu.edu.cn, 0
+lnu.edu.ua, 0
+lo9.de, 0
+loadedmovies.com, 0
+loadup.ru, 0
+loadxtreme.ph, 0
+localau.com, 0
+loccitane.cn, 0
+lockinchina.com, 0
+locojoy.com, 0
+locpg.hk, 0
+locutorioonline.es, 0
+loe.lviv.ua, 0
+loganmarchione.com, 0
+logcg.com, 0
+logic-games.spb.ru, 0
+logicmelon.com, 0
+logico.cloud, 0
+logindex.com, 0
+loginto.me, 0
+logobaker.ru, 0
+logodashi.com, 0
+logoip.de, 0
+logomatic.fr, 0
+logos.net, 0
+logre.eu, 0
+loh-group.com, 0
+lojasegmento.com.br, 0
+lojaskd.com.br, 0
+loji.com, 0
+lokalebasen.dk, 0
+lol5s.com, 0
+loldan.com, 0
+loli-h.com, 0
+lomax.cz, 0
+londontheatredirect.com, 0
+longfor.com, 0
+longsys.com, 0
+lookfor.kz, 0
+looknij.in, 0
+loongair.cn, 0
+loopbyte.com, 0
+loramobile.de, 0
+lords.mobi, 0
+loreal.net, 0
+lostcut.net, 0
+lostiempos.com, 0
+loto.ro, 0
+lottery.gov.cn, 0
+lottorich.co.kr, 0
+loudsound.ru, 0
+louisacoffee.com.tw, 0
+louisiana.edu, 0
+louisiana.gov, 0
+lovean.com, 0
+lovehd.top, 0
+loveliv.es, 0
+lovelivewiki.com, 0
+loveota.com, 0
+love-piano.ru, 0
+lovepresent.ru, 0
+loveq.cn, 0
+loveslife.biz, 0
+loveu.tw, 0
+lowcostparking.eu, 0
+lowcygier.pl, 0
+lowyinstitute.org, 0
+loxforum.com, 0
+loyalsoldier.me, 0
+lpcorp.com, 0
+lpcware.com, 0
+lpgenerator.ru, 0
+lrts.net, 0
+lsjsoso.com, 0
+lskc.edu.hk, 0
+lsoft.hu, 0
+ltdtickets.com, 0
+ltd.ua, 0
+ltsu.org, 0
+lua.org, 0
+luatminhgia.com.vn, 0
+lublin.eu, 0
+lucca.fr, 0
+luciad.com, 0
+ludado.com, 0
+ludwig.guru, 0
+luebeck.de, 0
+lufficc.com, 0
+lugasat.org.ua, 0
+lugons.org, 0
+luisfm.es, 0
+luluyou.com, 0
+lumenvox.com, 0
+lundalogik.com, 0
+lundao.com, 0
+lun.ua, 0
+luogu.org, 0
+luohuedu.net, 0
+luolei.org, 0
+luoxiao123.cn, 0
+lurenet.ua, 0
+lurkmo.re, 0
+lurkmore.co, 0
+lurkmore.net, 0
+lurkmore.ru, 0
+lurkmore.so, 0
+lurkmore.to, 0
+lusen.com, 0
+lush.com.ua, 0
+lusilusi.com, 0
+luviaglobal.com, 0
+luxedition.ru, 0
+luxoft.com, 0
+luxottica.com, 0
+luxuqing.com, 0
+luzhou.com, 0
+lv9.org, 0
+lvbeivpn.cc, 0
+lvbeivpn.cn, 0
+lvcgroup.com, 0
+lvwenhan.com, 0
+lvxia.me, 0
+lvyouquan.cn, 0
+lwl12.com, 0
+lwl.org, 0
+lwxshow.com, 0
+lxx1.com, 0
+lyad.fr, 0
+lyblog.net, 0
+lybomudr.ru, 0
+lyceefrancais.at, 0
+lyceefrancais.org.uk, 0
+lyceum62.ru, 0
+lyfboat.com, 0
+lylinux.org, 0
+lysa-hora.cz, 0
+lzhaofu.cn, 0
+lzu.edu.cn, 0
+m19aixin.com, 0
+m1net.com.sg, 0
+m247.com, 0
+m24.ru, 0
+m2c.ru, 0
+m2indonesia.com, 0
+m2mled.net, 0
+m3guo.com, 0
+maansun.com, 0
+mabangerp.com, 0
+ma.by, 0
+macau-airport.com, 0
+maccentre.ru, 0
+macgames.fr, 0
+mach3.jp, 0
+machinalis.com, 0
+machula.ru, 0
+maco.eu, 0
+macpeers.com, 0
+macphun.com, 0
+macprime.ch, 0
+macroscop.com, 0
+mac-status.de, 0
+macx86.cn, 0
+macx.cn, 0
+macx.ws, 0
+madailicai.com, 0
+madefire.com, 0
+madeinua.org, 0
+mad-gamble.net, 0
+madisoft.it, 0
+madison.ru, 0
+madurodam.nl, 0
+madvaper.ru, 0
+madwave.ru, 0
+maeda-atsuko.cn, 0
+maedchenflohmarkt.de, 0
+maemo.org, 0
+magazindoberman.ru, 0
+magazinlinz.ru, 0
+magcity74.ru, 0
+magecom.net, 0
+magenting.com, 0
+maggioli.it, 0
+magicalgirlsubs.de, 0
+magiccardmarket.eu, 0
+magicdoorss.com, 0
+magickartenmarkt.de, 0
+magiclen.org, 0
+magicstreams.gr, 0
+magicutilities.net, 0
+magimetrics.com, 0
+magnya.com, 0
+magtu.ru, 0
+mahluklar.org, 0
+mahor.ru, 0
+mahost.ca, 0
+mahua.com, 0
+maihaoche.com, 0
+mail3admin.de, 0
+mail-archive.com, 0
+mailasail.com, 0
+mailbox.hu, 0
+mailermailer.com, 0
+mail.gov.af, 0
+mail.kz, 0
+mailpile.is, 0
+maimemo.com, 0
+maimiaotech.com, 0
+mainbox.com, 0
+mainkeys.net, 0
+mainstreamdata.com, 0
+maiotaku.com, 0
+mai.ru, 0
+maiseed.com, 0
+makedonias.gr, 0
+makedreamprofits.ru, 0
+makeevka.com, 0
+makeii.com, 0
+makeupgroup.cz, 0
+maki-chan.de, 0
+makkhichoose.com, 0
+makler.md, 0
+makler.ua, 0
+maknails.ru, 0
+makovka.com.ua, 0
+maksatbilgi.com, 0
+maktab.tj, 0
+malaga.es, 0
+malchish.org, 0
+maliactu.info, 0
+maliburumdrinks.com, 0
+malina.ru, 0
+malloom.com, 0
+mamanam.com, 0
+mamantena.ru, 0
+mamazin.com.ua, 0
+mambaby.com, 0
+mamsy.ru, 0
+manabii.info, 0
+mandarinaduck.com, 0
+m-and-d.com, 0
+mangapanda.info, 0
+mango.com, 0
+mangoerp.com, 0
+mangooutlet.com, 0
+maniac-forum.de, 0
+manifest.ge, 0
+mann.tv, 0
+manprogress.com, 0
+manqian.cn, 0
+mans.edu.eg, 0
+manstrong.com.tw, 0
+manticgames.com, 0
+mantoufan.com, 0
+manuskri.tn, 0
+manybot.io, 0
+manzana.ua, 0
+maoming.gov.cn, 0
+maori.nz, 0
+mapado.com, 0
+mapamista.org.ua, 0
+mapbar.com, 0
+mapbase.ru, 0
+maplewood.com, 0
+mappingmegan.com, 0
+mapshop.ir, 0
+maralhost.com, 0
+maralhost.marketing, 0
+maratsafin.pro, 0
+marbeho.com, 0
+marburg.de, 0
+marcaentradas.com, 0
+marcopinheiro.com, 0
+marcopol.pl, 0
+marelepescar.ro, 0
+marfeel.com, 0
+marietta.edu, 0
+mariinsky.ru, 0
+mariinsky.tv, 0
+marijuanagrowing.eu, 0
+marine-conservation.org, 0
+marinelink.com, 0
+maritimeprofessional.com, 0
+markaz.uz, 0
+marketgoo.com, 0
+market.hu, 0
+marketinsight.it, 0
+marketmind.at, 0
+marketsmaster.org, 0
+markiza.sk, 0
+marklogic.com, 0
+markova.com, 0
+mark.ru, 0
+marktplatz-mittelstand.de, 0
+markum.net, 0
+marlinmag.com, 0
+marshrutka.com.ua, 0
+marthadebayle.com, 0
+martinezloriente.com, 0
+marwell.org.uk, 0
+marya.ru, 0
+masalnews.ir, 0
+mascheronistore.it, 0
+mashhad724.ir, 0
+mashhad.me, 0
+masivapp.com, 0
+maslahatim.uz, 0
+masnegocio.com, 0
+maspormas.com, 0
+massaget.kz, 0
+massengeschmack.tv, 0
+mastera-rukodeliya.ru, 0
+mastercity.ru, 0
+masterofsoccer.com, 0
+masterphone.ru, 0
+master-tao.com, 0
+masterzx.com, 0
+masutaka.net, 0
+matekmindenkinek.hu, 0
+matrixcalc.org, 0
+matrix-vision.com, 0
+matrony.ru, 0
+mauiarts.org, 0
+mavn.is, 0
+mawenjian.net, 0
+mawqe3.net, 0
+maxcuties.top, 0
+maxi.by, 0
+maxicard.ua, 0
+maxi-sale.ru, 0
+maxjia.com, 0
+maxmilhas.com.br, 0
+maxserv.com, 0
+maxst.com, 0
+maxtrack.uz, 0
+maxxipoint.com, 0
+maxzon.ru, 0
+mayflower.de, 0
+maytoni.ru, 0
+mazda.at, 0
+mazda.ch, 0
+mazda.de, 0
+mazdaeur.com, 0
+mazda.fr, 0
+mazda.hr, 0
+mazsihisz.hu, 0
+m-bet.co.tz, 0
+mbfilm.ir, 0
+mbhs.edu, 0
+mblox.com, 0
+mbo.com.ph, 0
+mbwar.com, 0
+mcafeestore.com, 0
+mc-auto.ru, 0
+mcbot.gq, 0
+mcb.ru, 0
+mccme.ru, 0
+mcdir.ru, 0
+mcdonalds.cz, 0
+mcent.com, 0
+mcetv.fr, 0
+mcfuzhu.net, 0
+mcgen.eu, 0
+mcguirksgolf.com, 0
+m-classic.com, 0
+mclc.ir, 0
+mcmaster.ca, 0
+mcncc.com, 0
+mcocmod.net, 0
+mconvert.net, 0
+m-cosmetica.ru, 0
+mcplay.cn, 0
+mcscostruzioni.it, 0
+mct.gov.az, 0
+mcu.edu.tw, 0
+mcx.ru, 0
+mdic.gov.br, 0
+mdict.cn, 0
+mdlivre.com.br, 0
+mdman.cc, 0
+mdog.mobi, 0
+mdolls.mobi, 0
+mdrv.ru, 0
+mdt-dodin.ru, 0
+mdv.de, 0
+meabilis.fr, 0
+measurementlab.net, 0
+meatbox.co.kr, 0
+mebeel.ru, 0
+mebelion.ru, 0
+mebel-top.ru, 0
+mecare.cn, 0
+mecbsegov.in, 0
+mecbsekvs.in, 0
+mechanization.ru, 0
+mectronica.it, 0
+medansatu.com, 0
+medbanks.cn, 0
+medbox.ru, 0
+medeintegra.com, 0
+medgadgets.ru, 0
+mediabak.com, 0
+mediabinn.com, 0
+mediabks.com, 0
+mediadec.com, 0
+mediafaze.com, 0
+mediagazer.com, 0
+mediagemm.com, 0
+mediahitt.com, 0
+mediakee.com, 0
+medialid.com, 0
+medialog.fr, 0
+mediaquelle.at, 0
+mediaraven.be, 0
+mediaresearch.se, 0
+mediascanner.net, 0
+mediasity.co, 0
+mediate.com, 0
+mediatoday.ru, 0
+mediatop.ws, 0
+mediavex.com, 0
+mediaweb.ru, 0
+mediazenn.com, 0
+medicalvideos.us, 0
+medicinalegal.gov.co, 0
+medicina.ru, 0
+medienrecht-urheberrecht.de, 0
+medieval-europe.eu, 0
+mediker.kz, 0
+medion.com, 0
+medjouel.com, 0
+medlibrary.org, 0
+medmag.ru, 0
+medmastery.com, 0
+medmedicine.it, 0
+medmeeting.org, 0
+mednet.ru, 0
+medscape.ru, 0
+medspros.ru, 0
+meduza.io, 0
+meekan.com, 0
+meest.us, 0
+meetfighters.com, 0
+meetme.com, 0
+meetshared.com, 0
+mef.net, 0
+megacampus.ru, 0
+megafilmes4k.com.br, 0
+mega-f.ru, 0
+megaglest.org, 0
+megaleech.us, 0
+megaline-films.kz, 0
+megaline.kg, 0
+megalink.ru, 0
+megamag.by, 0
+megamart.az, 0
+megameh.com, 0
+megaplan.by, 0
+megaplan.ru, 0
+megaterem.ru, 0
+megatheme.ir, 0
+megatrack.ru, 0
+megazat.com, 0
+megcart.com, 0
+me.gov.ar, 0
+mehrschool.com, 0
+meibu.net, 0
+meidebi.com, 0
+meideng.net, 0
+meiduimall.com, 0
+meigongyun.com, 0
+meijisp.jp, 0
+meilele.com, 0
+meinezwangsversteigerung.de, 0
+meinfernbus.de, 0
+meipian.cn, 0
+meipian.me, 0
+meishi.cc, 0
+meishij.net, 0
+meister.de, 0
+meitu.com, 0
+meix.com, 0
+meiyijia.com.cn, 0
+meizu.cn, 0
+meizu.com, 0
+melastampi.it, 0
+melenky.ru, 0
+mel.fm, 0
+melhorembarque.com.br, 0
+melodiak.hu, 0
+meloman.kz, 0
+memedai.cn, 0
+memeorandum.com, 0
+mena.org.eg, 0
+menariniapac.com, 0
+mendikat.net, 0
+mengdouwang.cn, 0
+mengniu.com.cn, 0
+mengzhu.tv, 0
+mensa.es, 0
+mensa.hu, 0
+menschen-leben.at, 0
+mephi.ru, 0
+mercadopme.com.br, 0
+mercedes-benz.ua, 0
+mercurial-scm.org, 0
+merici.ca, 0
+merproject.org, 0
+mersen.com, 0
+mertcangokgoz.com, 0
+mesago.de, 0
+mesalva.com, 0
+mesec.cz, 0
+mes.edu.cu, 0
+meshok.net, 0
+meshok.ru, 0
+meslekhocam.com, 0
+mestam.info, 0
+metabo.su, 0
+metapix.net, 0
+metasix.com.br, 0
+metasix.solutions, 0
+meten.cn, 0
+meteobox.cz, 0
+meteocontrol.de, 0
+meteorad.ru, 0
+meteor.ie, 0
+metin2.tc, 0
+metragi.ru, 0
+metricskey.net, 0
+metro.cl, 0
+metrol.jp, 0
+metropol.co.ke, 0
+metropole.cz, 0
+metropolitan.bg, 0
+metrosantiago.cl, 0
+metrosphera.ru, 0
+metroui.org.ua, 0
+metrouusor.com, 0
+metservice.com, 0
+metstr.com, 0
+mew.su, 0
+mexicoo.mx, 0
+mf8.biz, 0
+mfa.gov.by, 0
+mfb.io, 0
+mfc-74.ru, 0
+mfc74.ru, 0
+mfcto.ru, 0
+mferma.ru, 0
+mfor.hu, 0
+mfortune.co.uk, 0
+mf.uz, 0
+mgameday.com, 0
+mgb.bg, 0
+mgou.ru, 0
+mg-pen.com, 0
+mgpu.ru, 0
+mgts.ru, 0
+mgutm.ru, 0
+mguu.ru, 0
+mgvision.com, 0
+mhecy.com, 0
+mhelp.kz, 0
+mhliving.ru, 0
+mhp.com.ua, 0
+mhr-developer.com, 0
+mhunters.com, 0
+miacugra.ru, 0
+mia.gov.az, 0
+miamed.de, 0
+miamidade.gov, 0
+mianfeiwucan.org, 0
+mianshui365.com, 0
+miantiao.me, 0
+mianvpn.com, 0
+miaomiao520.cn, 0
+miaoyueyue.com, 0
+miascarpa.ru, 0
+miass.ru, 0
+mibd-gold.com, 0
+mibew.org, 0
+micasaverde.com, 0
+mic.co.at, 0
+michaelwest.com.au, 0
+michalsons.com, 0
+michelf.ca, 0
+michiganlabs.com, 0
+micous.com, 0
+microline.hr, 0
+microsoft.com, 0
+microsoftonline.cn, 0
+micros.uz, 0
+midaijihua.com, 0
+midea.com, 0
+midrub.com, 0
+miestilo.ru, 0
+mie-u.ac.jp, 0
+mightysignal.com, 0
+mignews.com.ua, 0
+migocorp.com, 0
+migros.ch, 0
+migu.cn, 0
+mihanwebserver.com, 0
+mihoyo.com, 0
+miit.gov.cn, 0
+mijnhva.nl, 0
+mikatiming.de, 0
+mikenopa.com, 0
+mikrocontroller.net, 0
+mikrotik-bg.net, 0
+mikrovps.hu, 0
+mikroways.net, 0
+mik.ua, 0
+mikulas.sk, 0
+mila.by, 0
+milanpassport.com.ua, 0
+militaryzone.ru, 0
+miloserdie.ru, 0
+mima.re, 0
+mimemoi.com, 0
+mimikko.cn, 0
+minbank.ru, 0
+minceraft.cl, 0
+mindai.com, 0
+mindasset.com, 0
+mindcont.com, 0
+mindjet.com, 0
+mindmeld.com, 0
+mindnode.com, 0
+mindoktor.se, 0
+mindresearch.org, 0
+mindstore.io, 0
+mineblue.com, 0
+mine.bz, 0
+mineconcapes.net, 0
+minecraft-alex.ru, 0
+minecrafting.ru, 0
+minecraftiplist.com, 0
+minecraft-moscow.com, 0
+minelist.kr, 0
+minem.gob.ar, 0
+mine.nu, 0
+mine-online.pw, 0
+minervanetworks.com, 0
+mines.edu, 0
+minfin.com.ua, 0
+mingdianwu8.com, 0
+mingkyaa.com, 0
+mingli.ru, 0
+mingyuanyun.com, 0
+mini189.cn, 0
+mini-koleso.ru, 0
+minimalart.cn, 0
+mininfra.gov.rw, 0
+mininterior.gob.ar, 0
+mininterior.gov.ar, 0
+miniyun.cn, 0
+minq.info, 0
+minsal.cl, 0
+minsk.by, 0
+mintrans.ru, 0
+mintrud.karelia.ru, 0
+minuporno.com, 0
+minus33.com, 0
+minv.sk, 0
+minyo.us, 0
+minzdravsakhalin.ru, 0
+mioji.com, 0
+mios.com, 0
+mipa.de, 0
+mipa-paints.com, 0
+mipko.ru, 0
+mipt.ru, 0
+mipuf.es, 0
+miracal.ru, 0
+mirage.ru, 0
+miranda-ng.org, 0
+mirante.net.br, 0
+mirapri.com, 0
+miraton.ua, 0
+mirbeer.ru, 0
+mirchar.ru, 0
+mirgaza.ru, 0
+miridei.com, 0
+mirkrestikom.ru, 0
+mirkvartir.ru, 0
+mirndv.ru, 0
+mir.partners, 0
+mirpchel.com, 0
+mirsushi.com, 0
+mis66.ru, 0
+missevan.com, 0
+missfresh.cn, 0
+missland.com, 0
+mista.ru, 0
+misterhorse.tv, 0
+misterspex.ch, 0
+misterspex.com, 0
+misterspex.co.uk, 0
+misterspex.de, 0
+misterspex.es, 0
+misterspex.fr, 0
+misterspex.nl, 0
+mist-game.ru, 0
+misuland.com, 0
+mi-sys.com, 0
+mit.com.mm, 0
+mit.edu, 0
+mitsubishielectric.com, 0
+mittwaldserver.info, 0
+mitusky.com, 0
+mitutoyo.eu, 0
+mit.uz, 0
+mitwork.kz, 0
+miu.ac.ir, 0
+miui.com, 0
+miuipro.ru, 0
+miutour.com, 0
+mivitec.net, 0
+mivlgu.ru, 0
+mivocloud.com, 0
+mixdrop.ru, 0
+mixupload.com, 0
+mixxx.org, 0
+miyagi.es, 0
+miyagi.jp, 0
+miyijia.com, 0
+mizban24.net, 0
+mizbansite.com, 0
+mjbang.cn, 0
+mj-king.net, 0
+mkb.ru, 0
+mke.hu, 0
+mkf.com, 0
+mk.gov.ua, 0
+mk-host.com, 0
+mkn.de, 0
+mkrada.gov.ua, 0
+mkvcorporation.com, 0
+mkvtoolnix.download, 0
+mlbeta.com, 0
+mlhang.com, 0
+mlife.by, 0
+mljia.cn, 0
+mljiadev.cn, 0
+mlpmerch.com, 0
+mlsdev.com, 0
+mma.su, 0
+mmbank.ru, 0
+mmcs.pro, 0
+mmdai.com, 0
+mmet.cn, 0
+mmgp.com, 0
+mmgp.ru, 0
+mmk.ru, 0
+mmo4me.net, 0
+mmorpgitalia.it, 0
+mmotraffic.com, 0
+mmtrix.com, 0
+mmyuer.com, 0
+mnbaa.com, 0
+mnb.hu, 0
+mnb.mn, 0
+mnd.cz, 0
+mnenie.su, 0
+mne.ru, 0
+mngz.ru, 0
+mnogokarat.ru, 0
+mnt.ee, 0
+mo2g.com, 0
+mo9.com, 0
+moahr.cn, 0
+mobazi.ir, 0
+mobcb.com, 0
+mob.com, 0
+mobdisc.com, 0
+mobialia.com, 0
+mobiamo.com, 0
+mobibrw.com, 0
+mobicheckin.com, 0
+mobicom.mn, 0
+mobile-harddisk.nl, 0
+mobilenations.com, 0
+mobileshop.ir, 0
+mobil-helden.de, 0
+mobilnost.hr, 0
+mobinnet.net, 0
+mobit.dp.ua, 0
+mobi-to-pdf.com, 0
+mobius.studio, 0
+mobomarket.net, 0
+mobopan.cn, 0
+mobsoftffree.xyz, 0
+mobtakeran.com, 0
+mobwall.com.ua, 0
+mockuai.com, 0
+mockup.io, 0
+modablaj.com, 0
+modayiz.com, 0
+mod.bg, 0
+modcom.kz, 0
+moddota.com, 0
+modelmen.ru, 0
+modelon.com, 0
+modeltag.com, 0
+modmcpe.net, 0
+modmed.com, 0
+modstore.pro, 0
+modularcircuits.com, 0
+modum.by, 0
+modxcloud.com, 0
+modx.com, 0
+modx.pro, 0
+modx.ru, 0
+moe-acg.cc, 0
+moegirl.org, 0
+moe.hm, 0
+moemesto.ru, 0
+moe-navi.jp, 0
+moesk.ru, 0
+mofac-alfred.com, 0
+mofang.com, 0
+mofangge.com, 0
+mofanghr.com, 0
+moguta.ru, 0
+moha.gov.my, 0
+mohammad-toluei.ir, 0
+mohande3.com, 0
+mohandeseit.ir, 0
+mohmo.net, 0
+mohmoshop.net, 0
+mohurd.gov.cn, 0
+moikit.com, 0
+moi-uni.ru, 0
+mojdoktor.gov.rs, 0
+mojeid.cz, 0
+mojichina.com, 0
+mojilala.com, 0
+mokpo.ac.kr, 0
+mokylin.com, 0
+molbase.cn, 0
+molbase.com, 0
+moleskines.ru, 0
+molnet.ru, 0
+molochnoe.ru, 0
+momic.me, 0
+momo-net.com, 0
+monamie.kz, 0
+mondiaspora.net, 0
+mondovantaggio.com, 0
+mondraker.com, 0
+monema.it, 0
+monerohash.com, 0
+monetizus.com, 0
+moneydashboard.com, 0
+moneyman.es, 0
+moneyman.ge, 0
+moneyman.kz, 0
+moneyman.pl, 0
+money-man.ru, 0
+moneyman.ru, 0
+moneyplatform.com, 0
+mongeneraliste.be, 0
+mon.gov.ru, 0
+mon.gov.ua, 0
+monifymedia.com, 0
+monitoring-plugins.org, 0
+monitor-polski.pl, 0
+monitorsanywhere.com, 0
+monitorulcj.ro, 0
+monkey-live.com, 0
+monkeytravel.com, 0
+monkkee.com, 0
+monolife.ru, 0
+monopoly-one.com, 0
+monstandardfacile.com, 0
+monsters-tk.net, 0
+montclair.edu, 0
+mooban.cn, 0
+moocollege.com, 0
+moodleschule.de, 0
+moodviewer.com, 0
+moojing.com, 0
+moonback.ru, 0
+moonfly.net, 0
+moonseo.cn, 0
+mooo.com, 0
+mooseframework.com, 0
+mooseframework.org, 0
+moovel.com, 0
+moovweb.com, 0
+mopaasapp.com, 0
+mopaas.com, 0
+moparscape.org, 0
+mopubi.com, 0
+morebooks.de, 0
+morefirm.ru, 0
+morepiva.ua, 0
+moretv.com.cn, 0
+morfans.cn, 0
+morgan.edu, 0
+morgoth.ru, 0
+morph.io, 0
+morznet.com, 0
+moscow.ovh, 0
+moscowteslaclub.ru, 0
+moseeker.com, 0
+mos-gorsud.ru, 0
+mos-kino.ru, 0
+mosmoda.com.tr, 0
+mosolymp.ru, 0
+mosreg.ru, 0
+mos.ru, 0
+mossport.ru, 0
+mostinfo.net, 0
+mosturflot.ru, 0
+motarjeminiran.com, 0
+motchallenge.net, 0
+motocms.com, 0
+motof.cn, 0
+motomaxonlineshop.com, 0
+motorbit.com, 0
+motorcyclistonline.com, 0
+motor-oel-guenstig.de, 0
+moto-scuter.ru, 0
+motosdetrabajo.com.mx, 0
+motoslave.net, 0
+motot.net, 0
+mountainduck.io, 0
+mountfield.cz, 0
+mountfield.sk, 0
+mountyhall.com, 0
+mousesports.com, 0
+mouwasat.com, 0
+movavi.com, 0
+moviejie.com, 0
+movielala.com, 0
+moviemaps.org, 0
+movienthusiast.com, 0
+movietend.com, 0
+movilizer.com, 0
+moviran.org, 0
+movitech.cn, 0
+movit-tech.com, 0
+movnow.com, 0
+moxacg.com, 0
+moxiaonai.cn, 0
+moyoyo.com, 0
+moyuniver.ru, 0
+mozaika.dn.ua, 0
+mozaik.info.hu, 0
+mozanaplo.hu, 0
+mozaweb.com, 0
+mozaweb.hu, 0
+mozayka.com.ua, 0
+moz.gov.ua, 0
+mozilla.community, 0
+mp3bass.ru, 0
+mp3.cc, 0
+mp3kw.com, 0
+mp3nta.com, 0
+mp3.pm, 0
+mp3-telechargement.net, 0
+mp4la.net, 0
+mp.br, 0
+mpets.mobi, 0
+mp.gov.in, 0
+mpgu.info, 0
+mpgu.org, 0
+mplayerhq.hu, 0
+mplife.com, 0
+mpsj99.com, 0
+mptool.cn, 0
+mpt.ru, 0
+mqlforum.com, 0
+mratwork.com, 0
+mrcode.ir, 0
+mrcraig.xyz, 0
+mrcredits.ru, 0
+mrecorder.com, 0
+mrgfd.org.ua, 0
+mritd.me, 0
+mrju.cn, 0
+mrlong.cc, 0
+mrmo.cc, 0
+mrmondialisation.org, 0
+m.ro, 0
+mrporn.com, 0
+mrtimemaker.com, 0
+mrush.mobi, 0
+mr-world.com, 0
+mr-wu.cn, 0
+ms0571.com, 0
+msa.gov.cn, 0
+msalkirov.ru, 0
+msd25.com, 0
+msdi.cn, 0
+msignitechina.com, 0
+msig.sg, 0
+msilab.net, 0
+msk.su, 0
+m-sku.com, 0
+msl.ua, 0
+msmsu.ru, 0
+m-stat.gr, 0
+msu.ru, 0
+msv-duisburg.de, 0
+msxf.com, 0
+mta.mn, 0
+mta-sa.org, 0
+mta.ua, 0
+mt-bbs.com, 0
+mtcsys.com, 0
+mtechpro.com, 0
+mte.gov.br, 0
+mt.gov.br, 0
+mtgpulse.com, 0
+mti.co.jp, 0
+mtis.by, 0
+mti.ua, 0
+mtn.co.za, 0
+mtrend.ru, 0
+mtroyal.ca, 0
+mts.by, 0
+mts.ru, 0
+mts.tm, 0
+mtuci.ru, 0
+mtv235.com, 0
+mubrr.com.br, 0
+mucangjun.com, 0
+mucfc.com, 0
+muchong.com, 0
+mueller-of.de, 0
+muh.ru, 0
+muis.gov.sg, 0
+mujglock.com, 0
+mujin.co.jp, 0
+mujot.net, 0
+mu-kingdom.com, 0
+mukolin.cz, 0
+muloqot.uz, 0
+multiloginapp.com, 0
+multinet.dp.ua, 0
+multi-net.ru, 0
+multi-online.ru, 0
+multiplay.ru, 0
+multirama.gr, 0
+multirom.me, 0
+multisport.cz, 0
+multitest.me, 0
+multitest.ua, 0
+multitran.com, 0
+multitran.ru, 0
+multiupload.biz, 0
+multiwork.org, 0
+mumayi.com, 0
+mumble.ru, 0
+mumms.com, 0
+mums.ac.ir, 0
+mun.ca, 0
+mundialvac.com, 0
+muniao.com, 0
+munzinger.de, 0
+muppetism.com, 0
+muquan.net, 0
+murabba.com, 0
+murad.com, 0
+murdoch.edu.au, 0
+murm.pro, 0
+musa24.fi, 0
+musc.edu, 0
+musclebearporn.com, 0
+museumsbund.de, 0
+music-all.ir, 0
+music-group.com, 0
+musicland.ru, 0
+musicnota.ru, 0
+musicshelf.jp, 0
+musikazblai.com, 0
+musik-promotion.net, 0
+musiland.cn, 0
+mutlucell.com, 0
+mutterhaus.de, 0
+muv.ac, 0
+muyingzhijia.com, 0
+muzhiso.com, 0
+muzikata.net, 0
+muziker.com, 0
+muziker.es, 0
+muziker.pt, 0
+muziker.si, 0
+muziker.sk, 0
+muzikum.eu, 0
+muzkom.ru, 0
+muzlan.ru, 0
+muzmix.com, 0
+muzoic.com, 0
+muzoic.org, 0
+muzrec.com, 0
+muz.uz, 0
+mvbits.com, 0
+mvmv.com.tw, 0
+mvs.gov.ua, 0
+mvu.com.br, 0
+mwa.co.th, 0
+mwee.cn, 0
+mw-light.ru, 0
+mxp.tw, 0
+mxyun.com, 0
+my3ds.pl, 0
+my3gb.com, 0
+my3w.com, 0
+my891.com, 0
+m-yabe.com, 0
+myaiji.com, 0
+myanimeshelf.com, 0
+myanmarmp3.net, 0
+myanmore.com, 0
+myanonamouse.net, 0
+myartsonline.com, 0
+myasustor.com, 0
+myauto.ge, 0
+mybanker.dk, 0
+mybb.de, 0
+mybodygraph.com, 0
+myboracayguide.com, 0
+mybox.ru, 0
+mycat.io, 0
+my-cccp.ru, 0
+mycos.com, 0
+mydailymanga.com, 0
+myddns.com, 0
+myddns.ru, 0
+mydns.jp, 0
+mydreamplus.com, 0
+myds.me, 0
+my-eclipse.cn, 0
+myfirms.su, 0
+myfolio.com, 0
+myfoscam.com, 0
+myfoscam.org, 0
+myfreeproject.com, 0
+myfritz.net, 0
+myftb.de, 0
+myftp.biz, 0
+myftp.org, 0
+mygalgame.com, 0
+mygarage.ro, 0
+mygaste.com, 0
+my-gateway.de, 0
+mygiftcard.ru, 0
+mygiftcardsplus.com, 0
+mygjp.com, 0
+my.gov.cn, 0
+mygzb.com, 0
+myhloli.com, 0
+myhome.cx, 0
+myhomeworkapp.com, 0
+myihor.ru, 0
+myimmitracker.com, 0
+myindiacoupons.com, 0
+myjar.com, 0
+myjeeva.com, 0
+myjino.ru, 0
+myjob.uz, 0
+mykhg.de, 0
+mykitchen.am, 0
+myl.com.cn, 0
+mylifeorganized.net, 0
+mymoria.de, 0
+mymru.ca, 0
+mynetgear.com, 0
+mynetname.net, 0
+mynewcompany.com, 0
+mynj.cn, 0
+myop.cf, 0
+myowndns.info, 0
+myparcels.net, 0
+myparcels.ru, 0
+mypet-online.ru, 0
+my-phone-finder.com, 0
+myphotobook.ch, 0
+myphotobook.de, 0
+myphotobook.fr, 0
+myphotobook.it, 0
+myphotos.cc, 0
+mypoints.com, 0
+mypoolin.com, 0
+mypos.eu, 0
+mypost4u.com, 0
+my-private-network.co.uk, 0
+myprom.ru, 0
+myqcloud.com, 0
+myqnapcloud.com, 0
+myrenova.com, 0
+myrescue.net, 0
+myrusakov.ru, 0
+mysav.eu, 0
+myschoolapp.com, 0
+myschoolcdn.com, 0
+mysecuritycamera.com, 0
+myseldon.com, 0
+my-servers.us, 0
+mysisel.com, 0
+mysocialbook.com, 0
+mysocio.ru, 0
+mysocrat.com, 0
+mysof.net, 0
+myspiegel.de, 0
+myss.club, 0
+mytextmusic.com, 0
+mythware.com, 0
+mytickets.ae, 0
+my.to, 0
+mytokri.com, 0
+myvapedeal.com, 0
+my.vg, 0
+myviasat.ru, 0
+myvimir.ru, 0
+mywed.ru, 0
+mywinamp.com, 0
+mywire.org, 0
+mywishboard.com, 0
+mywork.com.vn, 0
+mywpku.com, 0
+myxs.net, 0
+myxzy.com, 0
+myyearbook.com, 0
+myzqb.cn, 0
+myzte.com, 0
+mz19.ru, 0
+mzmoney.com, 0
+mzoo.mobi, 0
+mztgame.com, 0
+mzt.ru, 0
+mz-web.de, 0
+n0l.hu, 0
+n131adserv.com, 0
+n142adserv.com, 0
+n152adserv.com, 0
+n156adserv.com, 0
+n158adserv.com, 0
+n159adserv.com, 0
+n19adshostnet.com, 0
+n214adserv.com, 0
+n24.ru, 0
+n264adserv.com, 0
+n280adserv.com, 0
+n329adserv.com, 0
+n4bb.com, 0
+n56adshostnet.com, 0
+n64adserv.com, 0
+n99adshostnet.com, 0
+nabezky.sk, 0
+naca.com, 0
+nacalynx.com, 0
+nacao.org.cn, 0
+nacta.edu.cn, 0
+nadesne.ru, 0
+nadloc.kz, 0
+naftan.by, 0
+naiadmmm.com, 0
+naifl.ru, 0
+naikuber.com, 0
+naimies.com, 0
+naim.ru, 0
+najlepszefoto.pl, 0
+nalogcodex.ru, 0
+nalog.ru, 0
+namava.ir, 0
+namba.kg, 0
+named.cn, 0
+nametests.com, 0
+namhuy.net, 0
+namidensetsu.com, 0
+nanaiki.ru, 0
+nanguo.cn, 0
+nanhai.gov.cn, 0
+nanhutravel.com, 0
+nani.com.tw, 0
+nanoo.tv, 0
+nano-pad.ru, 0
+nanopool.org, 0
+nanosemantics.ru, 0
+nanrenwa.com, 0
+na-olimpe.ru, 0
+naomi24.com.ua, 0
+nap6.com, 0
+napa.com, 0
+napai.cn, 0
+napensii.ua, 0
+napratica.org.br, 0
+narfu.ru, 0
+narkom.net, 0
+narkom.pro, 0
+narkom.tv, 0
+narod-expert.ru, 0
+naroi.ru, 0
+nartac.com, 0
+nas-broker.com, 0
+nasejidelna.cz, 0
+nasf.ru, 0
+nas.gov.ua, 0
+nashanyanya.ru, 0
+nashaplaneta.net, 0
+nashural.ru, 0
+nasm.us, 0
+nastroi.net, 0
+nat123.net, 0
+natalie-tours.ru, 0
+natapp.cn, 0
+nationsgame.net, 0
+nativeads.com, 0
+native-network.net, 0
+nativerootsdispensary.com, 0
+natlot.be, 0
+natm.ru, 0
+natron.fr, 0
+nattule.com, 0
+natural-sciences.ru, 0
+naturalwellbeing.com, 0
+natureacoeur.fr, 0
+nauchu-gotovit.ru, 0
+nau.edu.ua, 0
+nauka.gov.pl, 0
+naumen.ru, 0
+nav.by, 0
+naviextras.com, 0
+navigate.de, 0
+navikey.org, 0
+naviki.org, 0
+navrcholu.cz, 0
+nayavideo.com, 0
+nazk.gov.ua, 0
+nazuby.cz, 0
+nazwa.pl, 0
+nbastats.info, 0
+nbd.com.cn, 0
+nbdeli.com, 0
+nbedu.gov.cn, 0
+nbepb.gov.cn, 0
+nbhis.com, 0
+nbikemsu.ru, 0
+nbmetro.com, 0
+nbn.org.il, 0
+nbrc.ac.in, 0
+nca.gov.tw, 0
+ncas.or.kr, 0
+ncca.ie, 0
+ncfgroup.com, 0
+nchkz.ru, 0
+ncihealth.cn, 0
+ncku.edu.tw, 0
+ncnu.edu.tw, 0
+ncomputing.com, 0
+nctu.edu.tw, 0
+ncu.edu.tw, 0
+ncyu.edu.tw, 0
+ndcnc.gov.cn, 0
+nd.gr, 0
+ndhu.edu.tw, 0
+ndi.org, 0
+ndrc.gov.cn, 0
+ndr.de, 0
+ndv.ru, 0
+nea.gov.cn, 0
+nearadio.no, 0
+nebopro.ru, 0
+neco.tech, 0
+nectarin.ru, 0
+necy.eu, 0
+nedes.sk, 0
+neftekamsk.ru, 0
+neigou.com, 0
+nejlepsiceny.cz, 0
+nekto.me, 0
+nemaloknig.info, 0
+nemidoonam.com, 0
+nemzetiszinhaz.hu, 0
+neocron-game.com, 0
+neocube-russia.ru, 0
+neoebiz.co.kr, 0
+neoferr.com, 0
+neoflex.ru, 0
+neolant.ru, 0
+neoline.ru, 0
+neotriad.com, 0
+neoway.com.br, 0
+nephila.it, 0
+nepszava.hu, 0
+nestoilgroup.com, 0
+net46.net, 0
+net9.org, 0
+net-agenta.ru, 0
+netangels.ru, 0
+netatmo.com, 0
+netau.net, 0
+netbalancer.com, 0
+netbox.cz, 0
+netcraft.com, 0
+netease.com, 0
+netease.im, 0
+neteasy.pl, 0
+neteng.co, 0
+net-film.ru, 0
+nethesis.it, 0
+nethouse.ru, 0
+netim.com, 0
+netim.fr, 0
+netim.net, 0
+netiyi.com, 0
+net-load.com, 0
+netmaid.com.sg, 0
+netnea.com, 0
+netoearth.com, 0
+netpioneer.de, 0
+netplus.ch, 0
+netplus.tv, 0
+netsdl.com, 0
+netsh.org, 0
+netsparkmobile.com, 0
+netsun.com, 0
+nettoplast.ru, 0
+netvolante.jp, 0
+net-well.ru, 0
+netwi.ru, 0
+networkguru.ru, 0
+networkhealth.com, 0
+netxms.org, 0
+netzpolitik.org, 0
+netztest.at, 0
+neu.edu.cn, 0
+neura.edu.au, 0
+neurocogtrials.com, 0
+neurogroove.info, 0
+neuronup.com, 0
+neusoft.com, 0
+neusoft.edu.cn, 0
+neutrik.com, 0
+neutrium.net, 0
+nevalink.net, 0
+nevsedni-svet.cz, 0
+newalive.net, 0
+newbd.com, 0
+newchama.com, 0
+newchic.com, 0
+newdefend.com, 0
+newfrog.com, 0
+newhistorian.com, 0
+newhopegroup.com, 0
+newhorizonindia.edu, 0
+newhorizons.ae, 0
+newifi.com, 0
+newikis.com, 0
+newinform.com, 0
+newmanity.com, 0
+newmanvip.com, 0
+newm.co.kr, 0
+newmobilelife.com, 0
+new-retail.ru, 0
+new-rock-france.com, 0
+new-rus.tv, 0
+newsbin.com, 0
+news.cn, 0
+newscom.com, 0
+newsdog.today, 0
+news-for.me, 0
+newsghana.com.gh, 0
+newsko.ru, 0
+newsone.ua, 0
+newsprom.ru, 0
+newssummedup.com, 0
+news.tj, 0
+newstral.com, 0
+newszeit.com, 0
+newtab.club, 0
+newtimes.ru, 0
+newtranx.com, 0
+newz-complex.org, 0
+nexsoft.com.tr, 0
+nex-tech.com, 0
+nextgis.com, 0
+nextlayer.at, 0
+nextmail.ru, 0
+nextmp.net, 0
+nexusenergia.com, 0
+neytron.com, 0
+nezavisne.com, 0
+nfc-tag-shop.de, 0
+nfls.com.cn, 0
+nfmedia.com, 0
+nfo.so, 0
+nfs.com.ru, 0
+nfshost.com, 0
+nfsplanet.com, 0
+ngaaron.com, 0
+ngagelive.com, 0
+ngame.cn, 0
+ngamew.com, 0
+ngbit.com, 0
+ng-erp.com, 0
+nginx.org, 0
+ngmk.uz, 0
+ngmu.ru, 0
+ngonline.cn, 0
+ngp-ua.info, 0
+ngrok.cc, 0
+ngrok.io, 0
+nh.ee, 0
+niarela.net, 0
+niazerooz.com, 0
+nibs.ac.cn, 0
+nicaifu.com, 0
+nic.cz, 0
+nicdn.de, 0
+nicebnb.com, 0
+nicecotedazur.org, 0
+nic.edu, 0
+nicelabel.com, 0
+nic.gob.ar, 0
+nickstories.de, 0
+nicolawealth.com, 0
+nicpars.ir, 0
+nic.tr, 0
+nicweb.net, 0
+nidami.com, 0
+nie.edu.sg, 0
+night-ladies.ru, 0
+nightwolves.ru, 0
+nihaoshijie.com.cn, 0
+nijiero-ch.com, 0
+niji.fr, 0
+nikan.ir, 0
+nikonians.org, 0
+niks.by, 0
+nilokala.com, 0
+nimaboke.com, 0
+nina.gov.pl, 0
+ninja250.org, 0
+ninjamock.com, 0
+ninjaromeo.com, 0
+nintendo.es, 0
+nip.io, 0
+nipkipro.ru, 0
+nipne.ro, 0
+nippon-antenna.co.jp, 0
+niracloud.com, 0
+nirhtu.ru, 0
+nirt.res.in, 0
+nitec.kz, 0
+nitecore.com, 0
+nitk.ac.in, 0
+nitrokey.com, 0
+nitroserv.com, 0
+niubide.com, 0
+niuche.com, 0
+niu.cl, 0
+niume.com, 0
+niva-club.net, 0
+niwi.nz, 0
+nixpro.by, 0
+nix.ru, 0
+nixstore.ru, 0
+nj13z.cn, 0
+njd1.com, 0
+njit.edu.cn, 0
+njmu.edu.cn, 0
+n-joy.de, 0
+njucs-os.tk, 0
+nju.edu.cn, 0
+njust.edu.cn, 0
+nkforex.com, 0
+nkon.nl, 0
+nku.cn, 0
+nlb.mk, 0
+nl.ua, 0
+nmdn.net, 0
+nmedik.org, 0
+nmetau.edu.ua, 0
+nmg.gov.cn, 0
+nmm-hd.org, 0
+nmn.tw, 0
+nmzh.net, 0
+nnbbxx.net, 0
+nng.com, 0
+nnovosti.info, 0
+no1lounges.com, 0
+no1muse.com, 0
+noao.edu, 0
+nobleocarina.net, 0
+no-bs.de, 0
+nochi.com, 0
+nococoti.org, 0
+noda.me, 0
+nodelog.cn, 0
+nodevice.com, 0
+nodevice.com.pt, 0
+nodevice.es, 0
+nodevice.fr, 0
+nodevice.it, 0
+nodevice.jp, 0
+nody.me, 0
+nohoobag.com, 0
+no-ip.biz, 0
+no-ip.ca, 0
+no-ip.com, 0
+noip.me, 0
+no-ip.net, 0
+noisefm.ru, 0
+nolog.com, 0
+nomadit.co.uk, 0
+nomensa.com, 0
+nominic.ru, 0
+nomisma.it, 0
+nomnomka.ru, 0
+nomorelyrics.net, 0
+nonfiction.fr, 0
+noniu.com, 0
+non.li, 0
+nonli.com, 0
+nonstop-recruitment.com, 0
+noonbora.xyz, 0
+noor.net, 0
+noor-publishing.com, 0
+norakrolika.ru, 0
+norbar.com, 0
+norbit.ru, 0
+nordstar.ru, 0
+nordvpn.com, 0
+nordwindairlines.ru, 0
+norilsk-city.ru, 0
+noringa.ru, 0
+norma.uz, 0
+nornik.ru, 0
+northghost.com, 0
+norvik.eu, 0
+no-shave.org, 0
+nostromo.io, 0
+nota11.com.br, 0
+notaire.be, 0
+notariat.ru, 0
+notaris.be, 0
+notebooksbilliger.de, 0
+note-pad.net, 0
+noticiasx7.com, 0
+notifyfox.com, 0
+notifyninja.com, 0
+notik.ru, 0
+notmuchmail.org, 0
+notre-siecle.com, 0
+novabizz.com, 0
+novaenergia.net, 0
+nova.net.cn, 0
+novatek.ru, 0
+novatour.ru, 0
+novayaopera.ru, 0
+noveinzeraty.cz, 0
+novex.com.gt, 0
+novgorod.ru, 0
+novline.ru, 0
+novobyt.ru, 0
+novonordisk.com, 0
+novotelecom.ru, 0
+novreg.ru, 0
+nowcoder.com, 0
+nowecor.de, 0
+now.im, 0
+nowlink.it, 0
+noxue.com, 0
+npc.gov.cn, 0
+np.gov.ua, 0
+npmcompare.com, 0
+nps.edu, 0
+nptu.edu.tw, 0
+npu.ac.th, 0
+npu.gov.ua, 0
+nqu.edu.tw, 0
+nrada.gov.ua, 0
+nrcc.org, 0
+nrhh.org, 0
+ns48.pl, 0
+nsccsz.gov.cn, 0
+nsc.ru, 0
+nsfocus.com, 0
+nsimg.net, 0
+nsk.ru, 0
+nsk.su, 0
+nsktarelka.ru, 0
+nso.edu, 0
+nso.ru, 0
+nssm.cc, 0
+nstarikov.ru, 0
+nstu.ru, 0
+nsu.edu.cn, 0
+nsuem.ru, 0
+nsupdate.info, 0
+nsw.edu.au, 0
+nsw.gov.au, 0
+n-sysdes.co.jp, 0
+ntbg.org, 0
+ntbprov.go.id, 0
+ntex.tw, 0
+ntk-intourist.ru, 0
+ntm.ir, 0
+ntnu.edu.tw, 0
+ntnu.no, 0
+ntpc.edu.tw, 0
+ntp-servers.net, 0
+ntrqq.net, 0
+ntrun.com, 0
+ntt-it.co.jp, 0
+ntt.pl, 0
+ntu.edu.tw, 0
+ntv.ru, 0
+nu3.at, 0
+nu3.ch, 0
+nu3.com, 0
+nu3.de, 0
+nu3.fr, 0
+nuaa.edu.cn, 0
+nuageapp.com, 0
+nuance-nts.com, 0
+nucrf.ru, 0
+nudt.edu.cn, 0
+nuestracasa.com.co, 0
+nuevaeps.com.co, 0
+nugalis.com, 0
+nuipogoda.ru, 0
+nuk.edu.tw, 0
+nulling.space, 0
+number2.com, 0
+nung.edu.ua, 0
+nurotan.kz, 0
+nut.cc, 0
+nutspace.com, 0
+nutz.cn, 0
+nuu.uz, 0
+nux.ro, 0
+nva-hk.com, 0
+nvrnet.ru, 0
+nw.ru, 0
+nwtc.edu, 0
+nwt.cz, 0
+nxlog.co, 0
+nxrom.us, 0
+nyaki.ru, 0
+nyaso.com, 0
+nyc.ny.us, 0
+nydusvpn.com.cn, 0
+nyitvatartas24.hu, 0
+nysoftland.com.cn, 0
+nyugat.hu, 0
+nyxcosmetic.com.ua, 0
+nzb.cat, 0
+nzcompany.org, 0
+n-z.jp, 0
+o12.pl, 0
+o2.cz, 0
+o2label.ru, 0
+o2switch.net, 0
+oakandfort.ca, 0
+oakandfort.com, 0
+oaklynschool.org, 0
+oaseatm.com.ar, 0
+oasiscatalog.com, 0
+oat.ru, 0
+oball.ru, 0
+obambu.com, 0
+obbtest.com, 0
+obd2-shop.eu, 0
+obiz.com.tw, 0
+obukhov.ru, 0
+obyava.ua, 0
+ob-zor.ru, 0
+ocamlcore.org, 0
+oca.org, 0
+ocas.ca, 0
+occ.com.mx, 0
+oceanfilmtour.com, 0
+oceanic.com.br, 0
+oceanoptics.cn, 0
+oceanoptics.com, 0
+ocenschiki-i-eksperty.ru, 0
+ochenprosto.ru, 0
+ochkov.net, 0
+oclaro.com, 0
+ocmax.sk, 0
+ocrking.com, 0
+ocrosoft.com, 0
+ocrsdk.com, 0
+ocry.com, 0
+ocs.ru, 0
+oddle.me, 0
+oddpi.com, 0
+oddsoddsodds.com, 0
+odessa.gov.ua, 0
+odessa-life.od.ua, 0
+odiaweb.in, 0
+odin.ru, 0
+odisha.gov.in, 0
+od.no, 0
+odontosystem.com.br, 0
+odoo-community.org, 0
+oe24.at, 0
+oeag.at, 0
+oefb.at, 0
+oeh-wu.at, 0
+oei.es, 0
+oe.if.ua, 0
+oem-oil.com, 0
+oevg-versteigerungen.at, 0
+ofamni.com, 0
+ofb.uz, 0
+ofcard.com, 0
+ofertaschevrolet.com.br, 0
+ofertasdeemprego.pt, 0
+ofertasdetrabajosyempleos.com, 0
+offcn.com, 0
+office-4-sale.de, 0
+officeevolution.com, 0
+officen.kr, 0
+officeplus.cn, 0
+officetotalshop.com.br, 0
+officeweb365.com, 0
+off.net.mk, 0
+offquattro.com, 0
+ofigenno.com, 0
+o-film.com, 0
+ofk18.ru, 0
+oformi.net, 0
+ofo.so, 0
+ofoto.org, 0
+oftendining.com, 0
+ogilvy.com.cn, 0
+ogilvy.it, 0
+oglaszamy24.pl, 0
+ogmem.com, 0
+ogrn.ru, 0
+ohgaki.net, 0
+ohtuleht.ee, 0
+oichinote.com, 0
+oicp.net, 0
+oieau.fr, 0
+oieau.org, 0
+oilchoice.ru, 0
+oitibs.com, 0
+okabashi.com, 0
+okair.net, 0
+okb1.ru, 0
+okbuy.com, 0
+ok-crimea.ru, 0
+okfun.org, 0
+okhosting.com, 0
+okidoki.ee, 0
+okidoki.ru, 0
+okoutris.gr, 0
+oktawave.com, 0
+oktell.ru, 0
+okupdate.ru, 0
+okwave.co.jp, 0
+okwave.jp, 0
+okwoo.com, 0
+okwu.edu, 0
+olark.com, 0
+olay.com.tr, 0
+olaytv.com.tr, 0
+olcdn.net, 0
+oldbk.ru, 0
+oldboyedu.com, 0
+old-games.ru, 0
+olico.it, 0
+olimex.com, 0
+olimpiada.ru, 0
+olimpt4.info, 0
+olimp.us, 0
+ollbiz.com, 0
+oll.tv, 0
+olympiaodos.gr, 0
+olz.by, 0
+om1.ru, 0
+omadaalithias.gr, 0
+omct.org, 0
+ome.tv, 0
+omgmobc.com, 0
+omgpu.ru, 0
+omgtu.ru, 0
+omk.ru, 0
+omnia.online, 0
+omnicomm.ru, 0
+omnikportal.com, 0
+omniscriptum.com, 0
+omnitron-systems.com, 0
+omsk.com, 0
+omskportal.ru, 0
+omskzan.ru, 0
+omsys.com.cn, 0
+omvapors.com, 0
+on5.ir, 0
+onaft.edu.ua, 0
+onda.ma, 0
+ondonnedesnouvelles.com, 0
+onechina.xyz, 0
+onego.ru, 0
+one.gov.hk, 0
+oneinstack.com, 0
+oneland.su, 0
+one-news.net, 0
+oneniceapp.com, 0
+onepiece.com.pl, 0
+one.pl, 0
+oneplus.cn, 0
+onepluscorp.cn, 0
+oneshield.com, 0
+onestic.com, 0
+onetrum.com, 0
+onevisionimaging.com, 0
+oneway.mobi, 0
+onfiles.me, 0
+onion.to, 0
+onligamez.ru, 0
+online2pdf.com, 0
+online-apteka.com.ua, 0
+onlinecomics.ru, 0
+online.cq.cn, 0
+onlinedizi.co, 0
+onlinefilerepair.com, 0
+online-go.com, 0
+onlinehome-server.com, 0
+onlinehome-server.info, 0
+online.kz, 0
+onlinelabs.ir, 0
+onlinemizban.net, 0
+online-olimpiada.ru, 0
+onlinepatent.ru, 0
+onlinepbx.ru, 0
+onlinepng.com, 0
+onlineproxy.eu, 0
+onlineservers.ir, 0
+online.tm, 0
+onlinetopgame.com, 0
+onlinetv.ru, 0
+onlinewebfonts.com, 0
+onloon.net, 0
+onlybird.com, 0
+onlyfans.com, 0
+onlyhot.net, 0
+onlylady.com, 0
+onlymobiles.com, 0
+onlymult.com, 0
+onlysasta.com, 0
+onmovie.ge, 0
+on.net, 0
+onnibus.com, 0
+onofis.com, 0
+onpage.org, 0
+ontariocolleges.ca, 0
+ont.by, 0
+onthewifi.com, 0
+onyx-boox.ru, 0
+oodii.com, 0
+oo.gd, 0
+ooi.moe, 0
+oomoe.moe, 0
+oostende.be, 0
+opapopa.ru, 0
+opava.cz, 0
+op.cz, 0
+open4u.ru, 0
+open.ac.uk, 0
+openal.org, 0
+openapis.org, 0
+openarch.nl, 0
+openasapp.net, 0
+openbadges.it, 0
+opencart2x.ru, 0
+opencartfrm.com, 0
+opencart.ir, 0
+opencartmodul.net, 0
+opencpu.org, 0
+opencsw.org, 0
+opendaylight.org, 0
+openlanguage.com, 0
+openledger.info, 0
+openlp.org, 0
+open-mind.ir, 0
+openmodelica.org, 0
+openneo.net, 0
+opennet.ru, 0
+opennicproject.org, 0
+open-o.org, 0
+openpediatrics.org, 0
+openprocurement.org, 0
+openproject.org, 0
+openproject-stage.com, 0
+open-real-estate.info, 0
+openreceptores.com, 0
+opensignal.com, 0
+opensource-excellence.com, 0
+openssource.info, 0
+openstat.com, 0
+opentopcart.com, 0
+opentown.org, 0
+opentraintimes.com, 0
+openttdcoop.org, 0
+opentutorials.org, 0
+openvz.org, 0
+openweb.co.za, 0
+openwrt.org, 0
+opera-online.com, 0
+opnfv.org, 0
+opogame.com, 0
+opole.pl, 0
+opolskie.pl, 0
+oponylux.pl, 0
+oporaua.org, 0
+oportuna.com, 0
+oppo.com, 0
+opportunitynetwork.com, 0
+opsteel.cn, 0
+opsview.com, 0
+optima.cz, 0
+optimism.ru, 0
+optimoney.ru, 0
+optiopay.com, 0
+opus.co.jp, 0
+orange-business.ru, 0
+orange.ci, 0
+orange.jo, 0
+orange-prem.com, 0
+orange-servicespace.com, 0
+orange-social.com, 0
+oraridiapertura24.it, 0
+orbita.dn.ua, 0
+orderbird.com, 0
+orderkleeneze.co.uk, 0
+orderonline.cn, 0
+ordinec.ru, 0
+oregonstudentaid.gov, 0
+orel.ru, 0
+orenu.co.il, 0
+orfeo-toolbox.org, 0
+orfogrammka.ru, 0
+organicawater.com, 0
+orgprint.com, 0
+oriental-dreamworks.com, 0
+orientdienst.de, 0
+orionnet.ru, 0
+oriwiki.net, 0
+ormansu.gov.tr, 0
+oroundo.com, 0
+orsk-adm.ru, 0
+orsk.ru, 0
+ortaid.fr, 0
+or.tl, 0
+ortn.edu, 0
+orzdream.com, 0
+orz.hm, 0
+osaifu.com, 0
+oschadbank.ua, 0
+oschina.io, 0
+oschina.net, 0
+osd.at, 0
+osf-global.com, 0
+osirisshoes.com, 0
+osmbuildings.org, 0
+osmocom.org, 0
+osnova.tv, 0
+os-scape.com, 0
+osstech.co.jp, 0
+osu.ru, 0
+osvita.ua, 0
+osx86.cn, 0
+osx.hk, 0
+oszk.hu, 0
+otanice.com, 0
+otani.co, 0
+otarikkoc.com, 0
+otdelkino.ru, 0
+otelrus.ru, 0
+otenko.com, 0
+otmechalka.com, 0
+otpbank.com.ua, 0
+otpbank.ro, 0
+otr-files.de, 0
+otr-ratte.de, 0
+otr.ru, 0
+ottino.com, 0
+otyrar.kz, 0
+oucnet.cn, 0
+ouistock.fr, 0
+oum.ru, 0
+ouo.us, 0
+oupeng.com, 0
+our-dream.cn, 0
+ourgold.ru, 0
+ourjnu.com, 0
+ourmind.ru, 0
+ourocg.cn, 0
+oursays.com, 0
+ourstage.com, 0
+oursweb.net, 0
+ourutec.com, 0
+ourwalrus.com, 0
+outdoorlife.com, 0
+outdoorvoices.com, 0
+outfittery.ch, 0
+outfittery.com, 0
+outfittery.de, 0
+outlook.cn, 0
+outside.cf, 0
+ovdinfo.org, 0
+overhear.club, 0
+overnightprints.com, 0
+overstockart.com, 0
+overtechnologies.com, 0
+overthewire.org, 0
+overture.org, 0
+overwall.cc, 0
+overwiki.ru, 0
+ovh.ca, 0
+ovh.net, 0
+ovi.su, 0
+ovomedia.tv, 0
+ovotv.com, 0
+ow2.org, 0
+ow365.cn, 0
+owen.ru, 0
+owk.cz, 0
+owox.com, 0
+ows.farm, 0
+ox.ac.uk, 0
+oxge.net, 0
+oxy.edu, 0
+oyasu.info, 0
+oypo.nl, 0
+oyunlarim.com.tr, 0
+ozgrozer.com, 0
+ozon.ru, 0
+p2bt.com, 0
+p2pnet.pl, 0
+p2psearchers.com, 0
+p30rank.ir, 0
+p7.de, 0
+paci.gov.kw, 0
+pacogames.com, 0
+pacreception.com, 0
+pactera.com, 0
+pactwork.com, 0
+paddez.com, 0
+paddlepalace.com, 0
+paderno.com, 0
+pados.hu, 0
+paetep.com, 0
+pagedmeble.pl, 0
+pages-24.fr, 0
+pages24.mx, 0
+pages24.pl, 0
+page-weight.ru, 0
+pagewizz.com, 0
+paginesi.it, 0
+pagoda.com.cn, 0
+pagostad.gob.ar, 0
+pa.gov.br, 0
+pagro.at, 0
+pah.org.pl, 0
+paidui.com, 0
+paiq.nl, 0
+palemoon.org, 0
+paleoforum.ru, 0
+palettegear.com, 0
+palexpo.ch, 0
+palizafzar.com, 0
+palobby.com, 0
+panc.cc, 0
+panchemodan.ru, 0
+pancr.ru, 0
+panda.tv, 0
+pandatv.com, 0
+pandemic-legion.pl, 0
+paneco.mx, 0
+pangora.com, 0
+panolapse360.com, 0
+panono.com, 0
+panqis.cn, 0
+panypay.ir, 0
+panzar.ru, 0
+paoding.cc, 0
+pa-online.it, 0
+paopaoche.net, 0
+papapiqueetmamancoud.fr, 0
+papapt.com, 0
+paparazziuav.org, 0
+papayamobile.com, 0
+papeleriaarte.com, 0
+paperdl.com, 0
+paperhive.org, 0
+paperpass.com, 0
+paperplane.io, 0
+paper-republic.org, 0
+papersearch.net, 0
+papersogay.com, 0
+papierovetasky-vrecka.sk, 0
+paradisep30.ir, 0
+paragon-software.com, 0
+paralelnipolis.cz, 0
+paran.com, 0
+paraninfo.es, 0
+parano.be, 0
+paraplan.ru, 0
+paratype.com, 0
+parcamarketim.com, 0
+parcelapp.net, 0
+parcelchina.co.uk, 0
+parcheggilowcost.it, 0
+pardazmizban.com, 0
+parenting.com.tw, 0
+parents.org.gr, 0
+parfumerika.ru, 0
+parfum-lider.ru, 0
+parfumuri-timisoara.ro, 0
+paristamil.com, 0
+parks.org.il, 0
+parmisit.com, 0
+parmismedia3.com, 0
+parscanada.com, 0
+parseapp.com, 0
+parsec.tv, 0
+parsine.com, 0
+parsmags.com, 0
+parsregister.ir, 0
+pars-server.com, 0
+partkeepr.org, 0
+part-kom.ru, 0
+partnerchoice.co.uk, 0
+partoserver.com, 0
+parts66.ru, 0
+parts-kobo.com, 0
+partsrunner.de, 0
+pasaiaport.eus, 0
+pasaz24.pl, 0
+pasionfutbol.com, 0
+pasona.com.tw, 0
+pas.org.my, 0
+pasp.ru, 0
+pass4sures.com, 0
+pass7.cf, 0
+pass.is, 0
+passkit.com, 0
+passportindex.org, 0
+passwordrecoverytools.com, 0
+passwordrevelator.net, 0
+pastaoyunu.com.tr, 0
+pastebox.in, 0
+patagames.com, 0
+pateks.info, 0
+patentamt.at, 0
+pathfinder.gr, 0
+patiotuerca.com, 0
+patpat.com, 0
+patriarchia.ru, 0
+patrimoniocultural.pt, 0
+patronbase.com, 0
+patroneer.com, 0
+patschool.com, 0
+pau.edu.ng, 0
+pavilion.com.bd, 0
+pawnmail.com, 0
+paxsz.com, 0
+payad.me, 0
+payamkutah.com, 0
+payapal.ir, 0
+paybao.com.tw, 0
+paybone.cn, 0
+paycheckcity.com, 0
+paycom.uz, 0
+paykeeper.ru, 0
+payline.ir, 0
+paymentwall.com, 0
+paymoon.com, 0
+payner.bg, 0
+paypersale.ru, 0
+paypertrail.com, 0
+payrexx.com, 0
+payroll-taxes.com, 0
+payscale.com, 0
+paywithpoli.com, 0
+pb86.net, 0
+pb.gov.br, 0
+pbplus.me, 0
+pbs-video.com, 0
+pbvusd.net, 0
+pbwiki.com, 0
+pc1ads.com, 0
+pc2ads.com, 0
+pc3ads.com, 0
+pc6.com, 0
+pcask.ru, 0
+pcauto.com.cn, 0
+pcbaby.com.cn, 0
+pcfun.ro, 0
+pcgames.com.cn, 0
+pcgarage.ro, 0
+pcgho.com, 0
+pchelp.zone, 0
+pchome.com, 0
+pchome.net, 0
+pchouse.com.cn, 0
+pci-suntektech.com, 0
+pcjoy.cn, 0
+pclady.com.cn, 0
+pclender.com, 0
+pcmag.ru, 0
+pcmarket.com.hk, 0
+pcmax.jp, 0
+pcnala.com, 0
+pc-online.co.il, 0
+pconline.com.cn, 0
+pc-radio.ru, 0
+pcradio.ru, 0
+pcsolottoresulttoday.com, 0
+pcstore.com.tw, 0
+pcvideo.com.cn, 0
+pcv.pt, 0
+pcweek.ru, 0
+pcworld.com.vn, 0
+pdaclub.pl, 0
+pdalife.ru, 0
+pdfm.net, 0
+pdlada.ru, 0
+pdn.ac.lk, 0
+pecs.hu, 0
+peergrade.io, 0
+pegast.com.ua, 0
+pegastour.ru, 0
+pegasus.de, 0
+pegasusknight.com, 0
+pegasusshop.de, 0
+pegatroncorp.com, 0
+pegitboard.com, 0
+pe.hu, 0
+p-e.kr, 0
+pelago.events, 0
+peliculas.cc, 0
+pelock.com, 0
+pelotok.net, 0
+penflip.com, 0
+penjualan.web.id, 0
+pensadordeapuestas.com, 0
+penshop.cz, 0
+pensioneram.info, 0
+pentesterschool.ir, 0
+pentestit.ru, 0
+peo.hu, 0
+peopleandconnection.com, 0
+peopleandlaw.ru, 0
+pepperkoko.com, 0
+peralppay.com, 0
+perevody-deneg.ru, 0
+perfekto.ru, 0
+performancehorizon.com, 0
+performia.com, 0
+peristeri.gr, 0
+permedu.ru, 0
+permprofi.ru, 0
+perqasje.com, 0
+persiangig.com, 0
+persiantools.com, 0
+person.com, 0
+personeelssysteem.nl, 0
+perspektiva-inva.ru, 0
+perssist.com, 0
+pervouralsk.ru, 0
+pesapal.com, 0
+pescms.com, 0
+pesc.ru, 0
+peshkupauje.com, 0
+pes.spb.ru, 0
+petdesk.com, 0
+peterkin.com.au, 0
+petersen.org, 0
+petkusuri.com, 0
+petradiamonds.com, 0
+petrimazepa.com, 0
+petrokimia-gresik.com, 0
+petromap.ru, 0
+petroren.com, 0
+petrsu.ru, 0
+petsoftware.net, 0
+petwellbeing.com, 0
+peugeot.com.cn, 0
+peugeot.it, 0
+peykasa.ir, 0
+pfconcept.com, 0
+pf-enclave.org, 0
+pfsw.com, 0
+pfthost.com, 0
+pgpru.com, 0
+pgsha.ru, 0
+pgw.jp, 0
+pgzs.com, 0
+phaistosnetworks.gr, 0
+phalconphp.com, 0
+pharminnotech.com, 0
+pharosmaris.net, 0
+phase-6.de, 0
+phcorner.net, 0
+phdl.net, 0
+phicomm.com, 0
+philipp-plein.com, 0
+philmorehost.net, 0
+philo.at, 0
+philofacile.com, 0
+phi-sci.com, 0
+phoenicis.com.ua, 0
+phoenix-dnr.ru, 0
+phoenixtree.com.cn, 0
+photo-ac.com, 0
+photobox.com, 0
+photocase.com, 0
+photocase.de, 0
+photographers.ua, 0
+photolemur.com, 0
+photonomy.ru, 0
+photophoto.cn, 0
+photoprocenter.ru, 0
+photorank.me, 0
+photosex.biz, 0
+photoshop-master.ru, 0
+photo-toolbox.com, 0
+photoworld.com.cn, 0
+php2.cc, 0
+phpcaptcha.org, 0
+phpclub.ru, 0
+phpdr.net, 0
+php-friends.de, 0
+phpinfo.me, 0
+phpmywind.com, 0
+phpnet.us, 0
+phps.kr, 0
+phpwind.me, 0
+phpxy.com, 0
+phtg.ch, 0
+phyks.me, 0
+phystech.edu, 0
+phystech.international, 0
+pi3g.com, 0
+picantecooking.com, 0
+picclick.de, 0
+picload.org, 0
+picnic.ly, 0
+picovico.com, 0
+picovr.com, 0
+picowork.com, 0
+picp.net, 0
+pictureview.com, 0
+pidak.cz, 0
+pidgin.im, 0
+pieas.edu.pk, 0
+piemex.net, 0
+pierotofy.it, 0
+pigcms.com, 0
+pikperfect.com, 0
+piktab.com, 0
+pilaipiwang.com, 0
+pila.pl, 0
+piligrim.ua, 0
+pilotgroup.net, 0
+pilot-theatre.com, 0
+piluli.ru, 0
+pinakothek.de, 0
+pine4.net, 0
+pine.fm, 0
+ping-admin.ru, 0
+pingan.com.cn, 0
+pingan.com.hk, 0
+pingpongx.com, 0
+pingstart.com, 0
+pingvin.pro, 0
+pingxx.com, 0
+pinkcasino.co.uk, 0
+pinpool.ir, 0
+pinsmedical.com, 0
+pinzhi365.com, 0
+pioneer-life.ir, 0
+pios.gov.pl, 0
+pipi.cn, 0
+pippkro.ru, 0
+piratebuhta.cc, 0
+pirateking.online, 0
+piratenpad.de, 0
+piratenpartei.de, 0
+piratepay.ir, 0
+pirateproxy.club, 0
+piratepublic.com, 0
+piratskastranka.si, 0
+pirobase.de, 0
+pirogov-dvorik.ru, 0
+pisofttech.com, 0
+pitbullguitars.com, 0
+pitchvision.com, 0
+pitersmoke.ru, 0
+pitupitu.pl, 0
+piuis.ru, 0
+pi-usa.us, 0
+pivnidenicek.cz, 0
+pixabay.com, 0
+pixelplus.ru, 0
+pixi.eu, 0
+pizzahut.be, 0
+pizzahut.com.ph, 0
+pizzamanager.eu, 0
+pjbc.gob.mx, 0
+pjeveracruz.gob.mx, 0
+pji.co.kr, 0
+pjn.gov.ar, 0
+pjud.cl, 0
+pjw.io, 0
+pkget.com, 0
+pkgh.edu.ru, 0
+pk.gov.pl, 0
+pkm.gov.gr, 0
+pkmn.net, 0
+pkmnreborn.com, 0
+pkpai.com, 0
+pkpai.kr, 0
+pkr.com, 0
+pks.id, 0
+pku.edu.cn, 0
+pkuh6.cn, 0
+placesrf.ru, 0
+placla.cz, 0
+plac-official.com, 0
+plagiarism-detector.com, 0
+plagly.com, 0
+plainjs.com, 0
+plainviewisd.org, 0
+plak.co.za, 0
+plan1.ru, 0
+planet3dnow.de, 0
+planetakino.ua, 0
+planeta-online.tv, 0
+planeta.tv, 0
+planetawrestling.com, 0
+planetemu.net, 0
+planete-zemlya.ru, 0
+planetkde.org, 0
+planet-kob.ru, 0
+planet-mcpe.net, 0
+planet.nl, 0
+planetofhotels.com, 0
+planetvampire.com, 0
+plan.io, 0
+planplus.cn, 0
+planujemywesele.pl, 0
+plarium.com, 0
+plasma-mobile.org, 0
+plasp.com, 0
+plasters.ru, 0
+plastics.ua, 0
+plastinka.com, 0
+plasway.com, 0
+plates4less.co.uk, 0
+platformaofd.ru, 0
+platon.sk, 0
+playa-games.com, 0
+playamedia.com, 0
+playgb.com, 0
+playgwent.cn, 0
+playinitium.com, 0
+playlist24.ru, 0
+playpass.be, 0
+playsport.cc, 0
+playstation.com, 0
+playstation.com.hk, 0
+playstore-api.com, 0
+playtomax.com, 0
+playzhan.com, 0
+plccenter.com, 0
+plobalapps.com, 0
+plocan.eu, 0
+pluie-solide.com, 0
+pluimen.nl, 0
+plumgrid.com, 0
+plus.com, 0
+plusgsm.com.br, 0
+plusmaster.ir, 0
+plus-plus.tv, 0
+ply.st, 0
+pm7.com, 0
+pmail.idv.tw, 0
+pmit.cn, 0
+pmlp.gov.lv, 0
+pndk.in, 0
+pneumax.ru, 0
+pnpapps.net, 0
+pnu.edu.ru, 0
+pnzreg.ru, 0
+pobedavkusa.ru, 0
+pocketbook-int.com, 0
+pocketdice.io, 0
+pocketlive.tv, 0
+podarit.net, 0
+podarit-prazdniki.ru, 0
+podari-zhizn.ru, 0
+poda.tv, 0
+podnikatel.cz, 0
+poems.co.id, 0
+poetrylabs.com, 0
+pofu.ru, 0
+pogazam.ru, 0
+pogliad.ua, 0
+pogovorim.net, 0
+poidem.ru, 0
+pointslab.org, 0
+poisk.ru, 0
+pokatne.pl, 0
+poke8.com, 0
+pokebip.com, 0
+pokedextracker.com, 0
+pokegosurewin.net, 0
+pokemoncardmarket.eu, 0
+pokemongomap.live, 0
+pokemonworld.ru, 0
+pokerdiscover.com, 0
+pokermatch.com, 0
+pokermoscow.ru, 0
+pokevision.hk, 0
+pokupo.ru, 0
+poland.travel, 0
+polarion.com, 0
+polar.org.cn, 0
+polessu.by, 0
+polibr.com.br, 0
+police.gov.ua, 0
+poliklinika45.ru, 0
+polime.it, 0
+politeka.net, 0
+politiadefrontiera.ro, 0
+politics.co.uk, 0
+polito.it, 0
+poliupg.ac.id, 0
+polocai.com, 0
+poloskaos.com, 0
+polovinka.org, 0
+polscygracze.pl, 0
+polska.lu, 0
+polska.travel, 0
+poltava.info, 0
+polus.com.ru, 0
+polus.su, 0
+polycn.com, 0
+polycomp.bg, 0
+polygongroup.com, 0
+polyv.net, 0
+pomelloapp.com, 0
+pomodoneapp.com, 0
+pomogi.org, 0
+pomorsu.ru, 0
+pomotodo.com, 0
+pomurec.com, 0
+ponosa.net, 0
+ponroy.com, 0
+p-on.ru, 0
+pontosido.com, 0
+pop136.com, 0
+pop800.com, 0
+popart.hk, 0
+popdg.com, 0
+popel-studio.com, 0
+popeyesdelivery.com.sg, 0
+popfax.com, 0
+popgo.space, 0
+popmog.com, 0
+popmotor.ru, 0
+popname.cz, 0
+popphoto.com, 0
+popsci.com, 0
+popunder24.com, 0
+popunder.net, 0
+porn0sex.net, 0
+porn4you.xxx, 0
+pornbase.info, 0
+pornfay.com, 0
+pornhublive.com, 0
+porno-gif.ru, 0
+porno-sex-online.com, 0
+pornvideos247.com, 0
+portail-familles.net, 0
+portaleperilcittadino.it, 0
+portal-preobrazenie.ru, 0
+portaltvto.com, 0
+portalwifi.com, 0
+portaportal.com, 0
+portfoliofinancial.hu, 0
+portfolio.hu, 0
+portodeimbituba.com.br, 0
+portoitapoa.com.br, 0
+portonave.com.br, 0
+portsdebalears.com, 0
+poshk.ru, 0
+positivoinformatica.com.br, 0
+posn.or.th, 0
+pos-shop.ru, 0
+postcalc.ru, 0
+postcross.me, 0
+postech.ac.kr, 0
+posteo.de, 0
+postgrespro.ru, 0
+postgresql.jp, 0
+postimees.ee, 0
+post.kz, 0
+postleitzahl.org, 0
+postmarket.kz, 0
+posuta.com, 0
+potemki.com, 0
+potokar.si, 0
+potsdam.de, 0
+potsdam.edu, 0
+pouyanit.com, 0
+povarenok.ru, 0
+pow88.com, 0
+powereasy.net, 0
+poweredbyclear.com, 0
+powerliftingiran.ir, 0
+powernet.com.ru, 0
+pozapisi.ru, 0
+poznan.pl, 0
+pp100.com, 0
+ppgame.com, 0
+ppm.cn, 0
+pptake.com, 0
+pptfans.cn, 0
+pptmall.net, 0
+ppt.ru, 0
+pptv.com, 0
+ppvke.com, 0
+ppypp.com, 0
+ppzuche.com, 0
+praegnanz.de, 0
+praktiker.hu, 0
+prala.pl, 0
+prankies.com, 0
+prasac.com.kh, 0
+pravda.sk, 0
+pravosudje.ba, 0
+pravsha.by, 0
+prawda2.info, 0
+prb.bg, 0
+prcjx.cn, 0
+prefis.sk, 0
+prego-services.de, 0
+prehraj.to, 0
+preis24.de, 0
+preissuche24.info, 0
+preistalent.de, 0
+premier-kladionica.com, 0
+premiumy.pl, 0
+prepaidcard.com.mm, 0
+preparedpantry.com, 0
+prepfactory.com, 0
+preporucamo.com, 0
+presidence.bj, 0
+presidencia.gov.co, 0
+pressenews.fr, 0
+prestigeflowers.co.uk, 0
+prestigehampers.co.uk, 0
+prestigio.com, 0
+presto-apps.com, 0
+pretenziy.ru, 0
+prettyporno.net, 0
+prettysecrets.com, 0
+prezentacii.org, 0
+prezi-dent.ru, 0
+pr.gov.br, 0
+pricefx.eu, 0
+pricett.com, 0
+primacom.de, 0
+primaseller.com, 0
+primat.cz, 0
+primeapps.in, 0
+primeins.gr, 0
+primeminister.kz, 0
+primeton.com, 0
+print100.com, 0
+printer-spb.ru, 0
+printmod.ru, 0
+print-post.com, 0
+printui.com, 0
+prinzeugen.net, 0
+priscillaelmusical.es, 0
+prisonlegalnews.org, 0
+prissa.com.mx, 0
+priusfreunde.de, 0
+privatedns.biz, 0
+private-immobilienangebote.de, 0
+privatelink.de, 0
+privatportal.sk, 0
+privesc.eu, 0
+privet.com, 0
+privoz.pl, 0
+prizel.ru, 0
+prizrenpost.com, 0
+prncloud.com, 0
+prnwatch.com, 0
+pro2e.com.tw, 0
+proball.ru, 0
+proberry.ru, 0
+pro-bike.ru, 0
+probiznesmen.ru, 0
+procd.net, 0
+process-one.net, 0
+proc.ru, 0
+procvetok.com, 0
+prodaman.ru, 0
+prodj.com.ua, 0
+produccion.gob.ar, 0
+productimpossible.com, 0
+profbuh8.ru, 0
+professionals-security.com, 0
+proffstore.com, 0
+profhariz.com, 0
+profibeer.ru, 0
+proficredit.cz, 0
+profile.ir, 0
+profine-group.com, 0
+profitero.com, 0
+profitquery.com, 0
+profi.travel, 0
+profitserver.ru, 0
+profizoo.cz, 0
+profpoint.ru, 0
+proftpd.org, 0
+prog-8.com, 0
+progamer.ru, 0
+proginov.fr, 0
+proglas.cz, 0
+prognoznazavtra.ru, 0
+prognoz.ru, 0
+pro-gorod.ru, 0
+programcini.com, 0
+programmy.club, 0
+programster.org, 0
+progs-shool.ru, 0
+prohelvetia.ch, 0
+proimei.info, 0
+projectagora.com, 0
+projectfacts.de, 0
+projectfly.co.uk, 0
+projecthax.com, 0
+projectsatbangalore.com, 0
+projectsmd.in, 0
+proliancesurgeons.com, 0
+prologicwebdesign.com, 0
+promentconsulting.com, 0
+promodo.com, 0
+promo.it, 0
+promosigratis.net, 0
+promostore.de, 0
+promptcloud.com, 0
+pronetdigital.com.br, 0
+pronosticoextendido.net, 0
+prontotour.com, 0
+proofpoint.com, 0
+proofy.io, 0
+propertytorenovate.co.uk, 0
+propertywala.com, 0
+property.works, 0
+prophpbb.com, 0
+pro-porno.net, 0
+pro-psixology.ru, 0
+proshivka.pro, 0
+prosmart.by, 0
+prospective.ch, 0
+prospero.ru, 0
+prostitutkifor.me, 0
+prostitutkixxx.org, 0
+prostovpn.org, 0
+prota4u.org, 0
+prota.info, 0
+prota.space, 0
+protect-software.com, 0
+protegetuordenador.com, 0
+protek.ru, 0
+protiprudu.org, 0
+protolabs.com, 0
+provadaordem.com.br, 0
+provectus.com, 0
+proviasnac.gob.pe, 0
+provincia.biella.it, 0
+provinciasondrio.gov.it, 0
+proweb.kz, 0
+proxmox.com, 0
+proxy-base.com, 0
+proxy-base.org, 0
+proxy-listen.de, 0
+proxylite.net, 0
+proxyssl.org, 0
+prsa.pl, 0
+prusa3d.com, 0
+prusa3d.cz, 0
+prusa3d.it, 0
+prusaprinters.org, 0
+przemekz.pl, 0
+psa-photo.org, 0
+psarips.com, 0
+psati.ru, 0
+psbl.org, 0
+ps-box.ru, 0
+psd1.org, 0
+psd2htmlconverter.com, 0
+psefan.com, 0
+psikologofisi.com, 0
+psim.us, 0
+pskovedu.ru, 0
+pskovline.ru, 0
+psmanaged.com, 0
+psne.jp, 0
+psnine.com, 0
+pspro.ir, 0
+pspx.ru, 0
+psru.ac.th, 0
+ps-sale.ru, 0
+pss.sk, 0
+p-stats.com, 0
+pstorage.space, 0
+pstu.ru, 0
+psu.ac.th, 0
+psu.by, 0
+psu.kz, 0
+psu.ru, 0
+psuti.ru, 0
+psy525.cn, 0
+psylab.cc, 0
+psysovet.ru, 0
+pszone.fr, 0
+pte.hu, 0
+pthor.ch, 0
+pti.org.br, 0
+ptsecurity.com, 0
+pttreader.com, 0
+ptyxjy.com, 0
+puahome.com, 0
+publbox.com, 0
+publiacqua.it, 0
+publiccloud.com.br, 0
+public-cyprus.com.cy, 0
+public.gr, 0
+publicitas.ch, 0
+publicitas.com, 0
+publicvm.com, 0
+publishernews.ru, 0
+pubprosud.fr, 0
+pub.ro, 0
+pubyun.com, 0
+puc.edu, 0
+puc-rio.br, 0
+pudding.cc, 0
+pudong.gov.cn, 0
+pu.edu.tw, 0
+puet.edu.ua, 0
+pullywood.com, 0
+pulsar.guru, 0
+pulsepad.com.ua, 0
+punchbaby.com, 0
+punjab.gov.pk, 0
+punto.ar, 0
+punycoder.com, 0
+purchasebear.com, 0
+purdue.edu, 0
+pure-ana.com, 0
+puredata.info, 0
+pureftpd.org, 0
+puregamemedia.fr, 0
+purepassion.ru, 0
+puretechltd.com, 0
+purgatoryresort.com, 0
+puritys.me, 0
+purnov.com, 0
+pushall.ru, 0
+pushclouds.cc, 0
+put.ac.ir, 0
+putanastars.net, 0
+putao.com, 0
+putihome.org, 0
+putler.com, 0
+puxbao.com, 0
+pvision.ru, 0
+pvr8.ir, 0
+pwlab.com, 0
+pwnz.org, 0
+pxgrids.com, 0
+pycon.org, 0
+pypa.io, 0
+pypi.org, 0
+pythian.com, 0
+pythonanywhere.com, 0
+python.org, 0
+pythontutor.com, 0
+pyw.cn, 0
+pyyx.com, 0
+pzacademy.com, 0
+pz.gov.ua, 0
+pzoom.com, 0
+pzu.com.ua, 0
+q1.com, 0
+q32.link, 0
+q4yy.com, 0
+q9tech.com, 0
+qapa.fr, 0
+qazit.com, 0
+qbear.ru, 0
+qbsw.sk, 0
+qc.to, 0
+qdac.cc, 0
+qdaily.com, 0
+qdcdc.com, 0
+qdealit.com, 0
+qdgjj.com, 0
+qdingzhi.com, 0
+qdu.edu.cn, 0
+qduoj.com, 0
+qdxin.cn, 0
+qeeka.com, 0
+qfang.com, 0
+qfiz.win, 0
+qhfz.edu.cn, 0
+qhimg.com, 0
+qhmsg.com, 0
+qiankunhaoche.com, 0
+qianmi.com, 0
+qianqian.com, 0
+qichacha.com, 0
+qichetong.com, 0
+qida.com, 0
+qidaile.com, 0
+qidapp.cn, 0
+qierukou.com, 0
+qietu.cn, 0
+qiezzi.com, 0
+qifu.me, 0
+qihoo.net, 0
+qihu.com, 0
+qijianvpnn.com, 0
+qikan.com, 0
+qikoo.com, 0
+qiku.com, 0
+qiling.org, 0
+qilong.com, 0
+qima-inc.com, 0
+qin27.com, 0
+qing5.com, 0
+qinggukeji.com, 0
+qingguo.com, 0
+qingk.cn, 0
+qingningzi.com, 0
+qingtaoke.com, 0
+qingting.fm, 0
+qingyunvpn.com, 0
+qingzhuyi.com, 0
+qinqinbaby.com, 0
+qinsmoon.com, 0
+qinzhou.gov.cn, 0
+qip.ru, 0
+qispine.com, 0
+qitt.ru, 0
+qiushibaike.com, 0
+qizhao.com, 0
+qlcl.edu.vn, 0
+qlean.ru, 0
+qlmoney.com, 0
+qls.com.au, 0
+qlu.edu.cn, 0
+qnapclub.it, 0
+qnap.community, 0
+qnbar.com, 0
+qnet.it, 0
+qnoddns.org.cn, 0
+qoop.me, 0
+qortex.com, 0
+qov.tw, 0
+qpolitical.com, 0
+qqyou.com, 0
+qrcb.com.cn, 0
+qrd.by, 0
+qrp-labs.com, 0
+qrserver.com, 0
+qrz.ru, 0
+qsban.cn, 0
+qsng.cn, 0
+qspfw.com, 0
+qsrmagazine.com, 0
+qswoo.com, 0
+qtdev.org, 0
+qtech.ru, 0
+qth.spb.ru, 0
+quadcept.com, 0
+qualaroo.com, 0
+qualiteconstruction.com, 0
+quality.co.jp, 0
+qualitytelecom.es, 0
+quankan.tv, 0
+quanmin.tv, 0
+queeky.com, 0
+queer.de, 0
+queezie.com, 0
+queisser.ru, 0
+quentrix.com, 0
+quepasada.cc, 0
+quepasanoticias.com, 0
+queromaisdicas.com.br, 0
+querylist.cc, 0
+questoria.ru, 0
+qugirl.com, 0
+quickchange.cc, 0
+quickclickhosting.com, 0
+quickim.co.il, 0
+quickmobile.com, 0
+quickqx.net, 0
+quicktickets.ru, 0
+quik.ru, 0
+quilt.idv.tw, 0
+quintagroup.com, 0
+quint.dk, 0
+quirinale.it, 0
+quitoque.fr, 0
+quizgroup.com, 0
+quizofkings.com, 0
+quizzclub.com, 0
+quji.com, 0
+qumaiyao.com, 0
+qumi.com, 0
+quna.com, 0
+qunar.com, 0
+qunar.it, 0
+qunarzz.com, 0
+qunhequnhe.com, 0
+qun.hk, 0
+qupai.me, 0
+qupeiyin.cn, 0
+qupeiyin.com, 0
+qutke.com, 0
+quumii.com, 0
+quyiyuan.com, 0
+quyundong.com, 0
+qxiazai.com, 0
+qycloud.com.cn, 0
+qycn.com, 0
+qydev.com, 0
+qyvideo.net, 0
+qzzn.com, 0
+r23.ru, 0
+r4ruby.com, 0
+r52.ru, 0
+r99.no, 0
+rabita.az, 0
+rabotakaliningrad.ru, 0
+rabota.tomsk.ru, 0
+racco.com.br, 0
+racedepartment.com, 0
+racefornuts.com, 0
+rachelcruze.com, 0
+rachum.com, 0
+radarservices.com, 0
+radec.com.mx, 0
+rad.eu, 0
+radia.sk, 0
+radicalphilosophy.com, 0
+radicasys.com, 0
+radicenter.eu, 0
+radikal.ru, 0
+radimrehurek.com, 0
+radinpars.com, 0
+radinsan.com, 0
+radio1.si, 0
+radio5.com.pl, 0
+radioantena.si, 0
+radio.cn, 0
+radioheart.ru, 0
+radiojackie.com, 0
+radiola.audio, 0
+radiolan.sk, 0
+radiopotok.ru, 0
+radio-shop.ru, 0
+radioskonto.lv, 0
+radioson.ru, 0
+radiostudent.si, 0
+radiotrucker.com, 0
+radioweb.jp, 0
+rad-net.de, 0
+radom.pl, 0
+radpardazesh.com, 0
+raduga-ufa.ru, 0
+radver.ru, 0
+ra.ee, 0
+raf.edu.rs, 0
+ragan.com, 0
+ragazzeinvendita.com, 0
+rageline.com, 0
+rahvaraamat.ee, 0
+rahyarserver.com, 0
+raiffeisen.ru, 0
+rai.it, 0
+rails365.net, 0
+rainbow-ic.biz, 0
+rainfly.cn, 0
+rainintl.com, 0
+rainyman.net, 0
+rajagiritech.ac.in, 0
+rajax.me, 0
+rajveteranu.cz, 0
+rallets.com, 0
+ranbot.hk, 0
+rand.com, 0
+randymc.de, 0
+ranez.ru, 0
+rangde.org, 0
+raphaelhertzog.com, 0
+rapida.ru, 0
+rapidomaine.biz, 0
+rapidomaine.fr, 0
+rapidpich.ir, 0
+rapidshopper.ca, 0
+rapidsms.org, 0
+rapidswholesale.com, 0
+rapixel.com, 0
+rara.jp, 0
+raremaps.com, 0
+rare-technologies.com, 0
+rarupload.com, 0
+rasana.ir, 0
+raschet.by, 0
+rashtak.ir, 0
+raskesider.no, 0
+ratbv.ro, 0
+ratesphere.com, 0
+ratioform.de, 0
+ratowealth.com, 0
+ratpdev.com, 0
+raviplacement.com, 0
+ravnaqbank.uz, 0
+rayaneh.com, 0
+rayanpack.com, 0
+raybt.ru, 0
+rayshobby.net, 0
+rayvision.com, 0
+razumei.ru, 0
+rbauto.ru, 0
+rbc.ch, 0
+rbc.ua, 0
+rblive.de, 0
+rbrauto.ru, 0
+rbru.ac.th, 0
+rbt.asia, 0
+rcf.it, 0
+rcforum.ru, 0
+rcfp.org, 0
+rcitsakha.ru, 0
+rcntec.com, 0
+rcokoit.ru, 0
+rcscomponents.kiev.ua, 0
+rcsearch.ru, 0
+rc-sme.ru, 0
+rctw.net, 0
+rcxue.com, 0
+rd-forum.ru, 0
+rdf.ru, 0
+rdfzcygj.cn, 0
+rdrom.ru, 0
+rdrop.com, 0
+reachoutandread.org, 0
+readfree.me, 0
+readnotify.com, 0
+readovka.ru, 0
+reagent.com.cn, 0
+realblackfriday.ru, 0
+realestate.ru, 0
+realeyz.de, 0
+realfevr.com, 0
+realgreenled.com, 0
+realidadvenezolana.com, 0
+realistic.photos, 0
+realschulebayern.de, 0
+realsociedad.com, 0
+realtycalendar.ru, 0
+realtyvision.ru, 0
+realweb.ru, 0
+reasondigital.com, 0
+reber.com, 0
+rebex.net, 0
+rebooo.com, 0
+reca.ca, 0
+recaro-cs.com, 0
+rechargedeal.in, 0
+redbook.tw, 0
+redcafestore.com, 0
+redcom.ru, 0
+reddingo.com, 0
+redesul.com.br, 0
+red-gate.com, 0
+redhome.cc, 0
+redirectme.net, 0
+redmatter.com, 0
+rednager.xyz, 0
+rednoise.org, 0
+redserver.su, 0
+redshift3d.com, 0
+redsign.ru, 0
+redtubelive.com, 0
+redzoneaction.org, 0
+reedoun.com, 0
+reeleezee.nl, 0
+refdb.ru, 0
+reflexplanning.com, 0
+refog.com, 0
+reformagkh.ru, 0
+refurb.me, 0
+refurb-tracker.com, 0
+regard.ru, 0
+regel.it, 0
+regenbogen.com, 0
+regione.fvg.it, 0
+regione.puglia.it, 0
+regionoperator.ru, 0
+regionsanmartin.gob.pe, 0
+regiontrud.ru, 0
+registrodirecto.es, 0
+registru.md, 0
+registry.net.za, 0
+regruhosting.ru, 0
+regtaim.ru, 0
+rehau-portal.ru, 0
+reifensuche.com, 0
+reikartz.com, 0
+reimu.net, 0
+reincarnationics.com, 0
+reinforce.cn, 0
+reiseguiden.no, 0
+reisenthel.com, 0
+rekab.ir, 0
+rekini.lv, 0
+reklama-online.ru, 0
+relap.io, 0
+remediobarato.com, 0
+remisesetprivileges.fr, 0
+remont3.ru, 0
+remora.cx, 0
+remorques-discount.com, 0
+remotewebaccess.com, 0
+rem.uz, 0
+remzona.by, 0
+renate.cc, 0
+renault.ru, 0
+renderfarming.net, 0
+renderpeople.com, 0
+rendezvenyhelyszinek.hu, 0
+rendi.hu, 0
+renegades-ast.it, 0
+renegraeber.de, 0
+renhe.cn, 0
+renjk.com, 0
+rennsimulanten.de, 0
+renovolive.com, 0
+renren66.com, 0
+renren.com, 0
+renrencui.org, 0
+renshuu.org, 0
+rentacenter.com, 0
+rentalhomes.com, 0
+rentbay.co.za, 0
+rentbook.co.za, 0
+rentner-die-zocken.de, 0
+rentong.com.tw, 0
+renwey.com, 0
+repaik.com, 0
+repetiruem.ru, 0
+repetitors.info, 0
+replaymod.com, 0
+reportbee.com, 0
+reportermagazin.cz, 0
+reportuk.org, 0
+researchcatalogue.net, 0
+researchgateway.ac.nz, 0
+researchmfg.com, 0
+reseauenscene.fr, 0
+reseguiden.se, 0
+resertrip.com, 0
+reservationcounter.com, 0
+reska.co.id, 0
+res-mods.ru, 0
+resmush.it, 0
+resortragaz.ch, 0
+respondi.com, 0
+restate.ru, 0
+restore.com.ua, 0
+restore-iphone-data.com, 0
+resto.ru, 0
+restosducoeur.org, 0
+restostar.com, 0
+restr.net, 0
+resumegames.com, 0
+reteaste.tv, 0
+retently.com, 0
+retouch-weblab.com, 0
+retrojeans.com, 0
+retrovisionlatino.net, 0
+ret.ru, 0
+revda-info.ru, 0
+reveal-sound.com, 0
+revell.de, 0
+reverse4you.org, 0
+reviewtrackers.com, 0
+revision.co.zw, 0
+revistamoi.com, 0
+revizto.com, 0
+revolt.tv, 0
+rewriteim.jp, 0
+reyhansoft.com, 0
+rezeptwelt.de, 0
+rezo-zero.com, 0
+rfchost.com, 0
+rfei.ru, 0
+rfelements.com, 0
+rf.gd, 0
+rfgsi.com, 0
+rficb.ru, 0
+rfj.ch, 0
+rfmeteo.ru, 0
+rgsu.ru, 0
+rgtfo-me.it, 0
+rgups.ru, 0
+rgyan.com, 0
+rgz.one, 0
+rhbrasil.com.br, 0
+rhcloud.com, 0
+rhh520.cn, 0
+rhoen-klinikum-ag.com, 0
+ria.com, 0
+ricercare-imprese.it, 0
+ridero.eu, 0
+ridersdeal.com, 0
+riffle.be, 0
+riftcat.com, 0
+rigaskarte.info, 0
+rightathome.net, 0
+rightknights.com, 0
+right-to-love.name, 0
+rigol.com, 0
+rigpa.org, 0
+rii.kz, 0
+rijigu.com, 0
+rimi.lt, 0
+rincondelatecnologia.com, 0
+rings.ru, 0
+riolis.ru, 0
+ripn.net, 0
+ripost.hu, 0
+rippletek.com, 0
+risan-penza.ru, 0
+risda.gov.my, 0
+riseba.lv, 0
+risenenergy.com, 0
+rising-gods.de, 0
+risk.az, 0
+risparmiatelo.it, 0
+riss.ru, 0
+riteforge.com, 0
+ritehite.com, 0
+ritekit.com, 0
+rite.ly, 0
+ritepush.com, 0
+ritetag.com, 0
+ritlabs.com, 0
+ritmo.ir, 0
+ritmonexx.ru, 0
+rivalfox.com, 0
+rivalregions.com, 0
+rixcloud.com, 0
+rizhiyi.com, 0
+rjb.ch, 0
+rj.gov.br, 0
+rjh.com.cn, 0
+rk1.ru, 0
+rk.gov.ru, 0
+rkiau.ac.ir, 0
+rkomi.ru, 0
+rlp.de, 0
+rls.tv, 0
+rlu.ru, 0
+rmc.edu.my, 0
+rmis36.ru, 0
+rmu.edu, 0
+rmutsb.ac.th, 0
+rmutsv.ac.th, 0
+rnarod.su, 0
+rncb.ru, 0
+rn.gov.br, 0
+rnids.rs, 0
+rnp.br, 0
+rnz.de, 0
+roadoor.com, 0
+roadrules.com.ua, 0
+robfors.com, 0
+robodesk.biz, 0
+robofinist.ru, 0
+roboforex.ae, 0
+roboforex.co.id, 0
+roboforex.com, 0
+roboforex.ru, 0
+robom.ru, 0
+roboname.com, 0
+robot-trading.de, 0
+robrobinette.com, 0
+roche.com, 0
+roche.de, 0
+rock-chips.com, 0
+rocketbeans.tv, 0
+rocketchange.ru, 0
+rocket-exp.com, 0
+rockhard.de, 0
+roc.nl, 0
+rodina.tv, 0
+roebx.com, 0
+roederer.fr, 0
+rohan.co.uk, 0
+rohost.com, 0
+roidmi.com, 0
+roiland.com, 0
+roklen24.cz, 0
+rolecosplay.com, 0
+rolotec.ch, 0
+romana.ru, 0
+roman.com.tr, 0
+romanrm.net, 0
+romeo1052.net, 0
+romhacking.ru, 0
+romme-palast.de, 0
+ronasit.com, 0
+roncoo.com, 0
+ronc.ru, 0
+rongcapital.cn, 0
+ronghedai.com, 0
+rongkecloud.com, 0
+roninwear.com, 0
+root86.com, 0
+root9b.com, 0
+root.bg, 0
+root.cz, 0
+rootnerds.com, 0
+rootshell.be, 0
+roov.org, 0
+roowei.com, 0
+rooydad.org, 0
+rooyeshnews.com, 0
+ropestore.com.br, 0
+roposo.com, 0
+rosalab.ru, 0
+rosalinux.ru, 0
+rosan.com, 0
+rosario3.com, 0
+rosariocultura.gob.ar, 0
+rosario.gov.ar, 0
+roscadastr.com, 0
+roscosmos.ru, 0
+roseltorg.ru, 0
+rosen-group.com, 0
+rosinter.ru, 0
+rosix.ru, 0
+rosjb.com, 0
+roskazna.ru, 0
+roskonkursy.ru, 0
+rosminzdrav.ru, 0
+rosneft-lubricants.ru, 0
+rosrealt.ru, 0
+rosreestr.ru, 0
+rossia.org, 0
+rossiya-airlines.com, 0
+rossoverdi.com, 0
+rostec.ru, 0
+rosterbot.com, 0
+rostobr.ru, 0
+rostov-gorod.ru, 0
+rostrud.ru, 0
+roszavod.ru, 0
+rotfront.su, 0
+rot-weiss-erfurt.de, 0
+routdata.com, 0
+routemobile.com, 0
+routeradar.nl, 0
+routerclub.com, 0
+rouxa365.gr, 0
+royal-forest.org, 0
+royalkids.fr, 0
+royalquest.com, 0
+royalquest.ru, 0
+royalrobbins.com, 0
+royaninstitute.org, 0
+rozanehshop.ir, 0
+rozhlas.cz, 0
+rpg-city.de, 0
+rpicn.org, 0
+rpn.gov.ru, 0
+rp.ru, 0
+rpsofts.com, 0
+rqbao.com, 0
+rqnoj.cn, 0
+rrabbit.cc, 0
+rrc24.com, 0
+rrc.ru, 0
+rrjc.com, 0
+rscc.ru, 0
+rsc.org.uk, 0
+rsmu.ru, 0
+rsnet.ru, 0
+rs.ro, 0
+rsr-olymp.ru, 0
+rs.ru, 0
+rssi.ru, 0
+r-stahl.com, 0
+rst.com.pl, 0
+rstore.in, 0
+rtc.bt, 0
+rte.ie, 0
+rtfund.com, 0
+rt-mart.com.cn, 0
+rtn.ch, 0
+rtr.at, 0
+rt.ru, 0
+rt-thread.org, 0
+rtv.rs, 0
+rtvs.sk, 0
+ru.ac.bd, 0
+ruan8.com, 0
+ruanman.net, 0
+ruanmei.com, 0
+rubarius.ru, 0
+ruberi.ru, 0
+rubezh.ru, 0
+rubhoz.com, 0
+rubikscube.info, 0
+ru-board.com, 0
+rubot.ovh, 0
+ruby-china.org, 0
+ruby-doc.org, 0
+ruby-forum.com, 0
+rubygroupe.jp, 0
+rucountry.ru, 0
+rudnikov.com, 0
+rugion.ru, 0
+ruguoapp.com, 0
+ruijie.com.cn, 0
+ru.is, 0
+rukzakoff.ru, 0
+rula.net, 0
+rulaws.ru, 0
+rummycircle.com, 0
+runeapps.org, 0
+ru.net, 0
+runff.com, 0
+runivers.ru, 0
+runningquotient.com, 0
+ruonu.com, 0
+ruooo.com, 0
+rupar.puglia.it, 0
+rusanu.com, 0
+rusat.com, 0
+rusdosug.com, 0
+ruselectronics.ru, 0
+rusempire.ru, 0
+rusevik.ru, 0
+rusfolder.com, 0
+rusfont.ru, 0
+rushydro.ru, 0
+rushy.fr, 0
+rusnano.com, 0
+rusnavi.org, 0
+ruspo.ru, 0
+rusreinfo.ru, 0
+russian-belgium.be, 0
+russian.space, 0
+russkaja-ohota.ru, 0
+rust1.ru, 0
+rustelekom.net, 0
+rustest.ru, 0
+rusticae.es, 0
+rustorrents.info, 0
+rutracker.cr, 0
+rutracker.net, 0
+rutracker.org, 0
+ruvape.club, 0
+ruvr.ru, 0
+ruweber.ru, 0
+rvm.io, 0
+r-v-s.su, 0
+rvv.de, 0
+rwth-aachen.de, 0
+ryady.ru, 0
+rybbaby.com, 0
+rybnik.pl, 0
+rynek-rolny.pl, 0
+rz.com, 0
+rzd-bonus.ru, 0
+rzeszow.pl, 0
+rzgmu.ru, 0
+s1homes.com, 0
+s3d4.cn, 0
+s4yy.com, 0
+saafi.com, 0
+sabayon.org, 0
+sabbuy.com, 0
+sabinahuang.com, 0
+sac.net.cn, 0
+sac.org.ar, 0
+sad6sotok.ru, 0
+sadaf22.com, 0
+sadalestikls.lv, 0
+sadc.int, 0
+sadeco.ir, 0
+sadkomed.ru, 0
+sadlyunfriended.com, 0
+sadovnik.mobi, 0
+sa.edu.au, 0
+saemes.fr, 0
+saezlive.net, 0
+safariran.ir, 0
+safarme.com, 0
+safc.com, 0
+safe2choose.org, 0
+safebridge.net, 0
+safedog.cn, 0
+safegoldgroup.com, 0
+safelayer.com, 0
+safer-networking.org, 0
+saferoadplus.com, 0
+safetree.com.cn, 0
+safe-ws.eu, 0
+saguenay.ca, 0
+sahamyab.com, 0
+sa-help.com, 0
+sahra.org.za, 0
+saibaba.org, 0
+saicgmac.com, 0
+saic-gm.com, 0
+saicmaxus.com, 0
+sai.co.za, 0
+saihs.edu.tw, 0
+sailingworld.com, 0
+saimanet.kg, 0
+saimatelecom.kg, 0
+saintpaul.edu, 0
+saintsouth.net, 0
+saipujianshen.com, 0
+saitama-u.ac.jp, 0
+saitreport.ru, 0
+saix.net, 0
+sakhalinenergy.ru, 0
+sakhtafzarmag.com, 0
+sak.sk, 0
+sakura.ne.jp, 0
+salairemoyen.com, 0
+salam.sch.ir, 0
+salatigakota.go.id, 0
+saldocuentarut.com, 0
+saleshood.com, 0
+sallyq.com.tw, 0
+salmon.com, 0
+salomon.ro, 0
+salon24.pl, 0
+salongweb.com, 0
+salonwith.com, 0
+salto.bz, 0
+saltwatersportsman.com, 0
+saludnqn.gob.ar, 0
+salzburgerland.com, 0
+samaraintour.ru, 0
+sambaum.ch, 0
+samberi.com, 0
+samedi.de, 0
+samemes.com.br, 0
+samenblog.com, 0
+sameroom.io, 0
+samesound.ru, 0
+samgasu.ru, 0
+samgau.com, 0
+samgups.ru, 0
+samihost.com, 0
+samohodoff.ru, 0
+samo.ru, 0
+sa-mp-servers.com, 0
+samregion.ru, 0
+samsung-fun.ru, 0
+samuraj-cz.com, 0
+samvirkebryggeriet.no, 0
+sandai.net, 0
+sandbox-immobilienscout24.de, 0
+sanderstechnology.com, 0
+sandilands.info, 0
+sandino.net, 0
+sandpay.com.cn, 0
+sangfor.com, 0
+sangfor.com.cn, 0
+sangoma.com, 0
+sangon.com, 0
+sanistaal.com, 0
+sanjieke.cn, 0
+sankai.com, 0
+sanog.org, 0
+sanquan.com, 0
+sanstv.ru, 0
+santaclaus-embassy.com, 0
+santech.ru, 0
+santegidio.org, 0
+sanwen8.cn, 0
+sanwen.net, 0
+sapagroup.com, 0
+sapient.com, 0
+sapo.pt, 0
+sarasavi.lk, 0
+sardex.net, 0
+sarnovosti.ru, 0
+saro.me, 0
+sarrc.ru, 0
+sarvserver.com, 0
+sarvssl.com, 0
+sasac.gov.cn, 0
+saschina.org, 0
+sasek.tv, 0
+saske.sk, 0
+saskialund.de, 0
+sata.direct, 0
+satc.edu.br, 0
+sat-chit-ananda.org, 0
+satellogic.com, 0
+satel.pl, 0
+satisfaction-fnac.com, 0
+satka74.ru, 0
+satlyk.org, 0
+sat-online.ch, 0
+satterley.com.au, 0
+saturn-r.ru, 0
+satway.ru, 0
+saucontds.com, 0
+saudubna.ru, 0
+savage.ru, 0
+savechange.ru, 0
+savehrolling.com, 0
+saverglass.com, 0
+saveur.com, 0
+savevpn.cc, 0
+savjee.be, 0
+sa-voice.com, 0
+savoir-inutile.com, 0
+savvytime.com, 0
+sayamatravel.com, 0
+saystory.co.kr, 0
+sbar.com.cn, 0
+sbarjatiya.com, 0
+sb-dji.com, 0
+sberbankaktivno.ru, 0
+sberbank-ast.ru, 0
+sberbank.ua, 0
+sberinsurance-online.ru, 0
+sbk-studio.de, 0
+sbras.ru, 0
+sbrf.com.ua, 0
+sbroker.de, 0
+sbro.me, 0
+sbsart.com, 0
+sbs.edu.cn, 0
+sbsub.com, 0
+sbwml.cn, 0
+sbx-media.com, 0
+scala-ffb.de, 0
+scalebay.ru, 0
+scaleforum.ru, 0
+scalp-trading.com, 0
+scam.su, 0
+scanadu.com, 0
+scanbot.io, 0
+scand.com, 0
+scbn.org, 0
+scenedownloads.pw, 0
+scga.gov.cn, 0
+sc.gov.cn, 0
+schaeferhunde.de, 0
+schaffenburg.org, 0
+schaffner.com, 0
+schafkopf-palast.de, 0
+schieb.de, 0
+schlemann.com, 0
+schneider-electric.cn, 0
+schneider-electric.com, 0
+schneidersladen.de, 0
+schnick-schnack-schnuck.net, 0
+schokokeks.org, 0
+school2100.com, 0
+schooldeskus.com, 0
+school.nz, 0
+schoolofhaskell.com, 0
+schoolpal.cn, 0
+school-scout.de, 0
+schoolsoft.com, 0
+schornsteinfabrik.de, 0
+schule.de, 0
+schullv.de, 0
+schul-webportal.de, 0
+schwarzkopf.de, 0
+schweizmobil.ch, 0
+sci99.com, 0
+science-education.ru, 0
+science.ma, 0
+scienceontheweb.net, 0
+scientificrussia.ru, 0
+scientology.net, 0
+sci-hub.ac, 0
+sci-nnov.ru, 0
+scloud.ru, 0
+scmcc.com.cn, 0
+sc-nm.si, 0
+scoffoni.net, 0
+scoop.co.nz, 0
+scoop.it, 0
+scoop.ng, 0
+scorecloud.com, 0
+scotthelme.co.uk, 0
+scottlogic.com, 0
+scotweb.co.uk, 0
+scout.org.hk, 0
+scoutwiki.org, 0
+scrabble-word-finder.com, 0
+scrcu.com.cn, 0
+screen9.com, 0
+screenbid.com, 0
+screencastify.com, 0
+screenshotlink.ru, 0
+screenstore.tk, 0
+scriptbuy.ir, 0
+scriptmania.com, 0
+scriptux.ir, 0
+scrunch.com, 0
+scryde.ru, 0
+scsb.com.tw, 0
+scs-laboutique.com, 0
+scssoft.com, 0
+sctu.edu.cn, 0
+sctv.com, 0
+scubadiving.com, 0
+scu.edu.cn, 0
+scut.edu.cn, 0
+sdada.edu.cn, 0
+sde.ru, 0
+sdewt.com, 0
+sdf.org, 0
+sdi.bg, 0
+sdk.cn, 0
+sdl.com, 0
+sdln.net, 0
+sdnu.edu.cn, 0
+sdska.ru, 0
+sdsmt.edu, 0
+sdsz.com.cn, 0
+sd.ua, 0
+sdu.edu.cn, 0
+sdvor.com, 0
+sdwfhrss.gov.cn, 0
+sdw.org, 0
+sd-xbmc.org, 0
+sdyunban.com, 0
+se7enkills.net, 0
+se7en.ws, 0
+seacadets.org, 0
+sea.com.ua, 0
+seafile.com, 0
+sea-group.org, 0
+seamwork.com, 0
+searates.com, 0
+searchanise.com, 0
+searchevolution.com, 0
+search-for-it.com, 0
+searchmedia.ws, 0
+searchx.ch, 0
+searu.org, 0
+seasiaconsulting.com, 0
+seasone.ru, 0
+seaters.com, 0
+seattle.gov, 0
+seatwave.com, 0
+seatwave.de, 0
+seatwave.es, 0
+seatwave.ie, 0
+seatwave.it, 0
+seayo.com, 0
+sebastian.expert, 0
+sebraemg.com.br, 0
+sec.gob.mx, 0
+seckin.com.tr, 0
+seclub.org, 0
+second24.ru, 0
+secp.gov.pk, 0
+secpulse.com, 0
+secretescapes.com, 0
+secureauthservice.com, 0
+securehost.ir, 0
+securelink.be, 0
+securenowindia.com, 0
+secureordering.com, 0
+secureprofile.ru, 0
+securerwsoft.de, 0
+secureserver.net, 0
+securitasdirect.fr, 0
+securitythinkerz.com, 0
+secutix.com, 0
+secv.com, 0
+sec-wiki.com, 0
+secye.com, 0
+sedittyhair.com, 0
+sedmitza.ru, 0
+sedns.cn, 0
+seec.com.tw, 0
+seeed.cc, 0
+seeleit.com, 0
+seemallorca.com, 0
+seetv.tv, 0
+seeyon.com, 0
+seezislab.com, 0
+se.gov.br, 0
+seg-social.pt, 0
+segurancajato.com.br, 0
+seibert-media.net, 0
+seidal.com, 0
+seidensticker.com, 0
+seis.ac.cn, 0
+seiyon.net, 0
+sejdemse.net, 0
+sekorm.com, 0
+sektaschool.ru, 0
+seldatdirect.com, 0
+selectedrecs.com, 0
+selenic.com, 0
+selestial.com, 0
+selfhost.bz, 0
+selfhost.de, 0
+selfhost.eu, 0
+selfhtml.org, 0
+selfip.biz, 0
+selfip.com, 0
+selfip.net, 0
+selfip.org, 0
+selfmadetrip.com, 0
+selfnation.ch, 0
+selfrance.org, 0
+sellercloud.com, 0
+sellercloudlocal.com, 0
+sellercube.com, 0
+sellerlabs.com, 0
+sellermania.com, 0
+seller-online.com, 0
+sellfile.ir, 0
+selpics.com, 0
+selzir.com, 0
+sem-bw.org, 0
+semesteratsea.org, 0
+semiaccurate.com, 0
+semicvetic.com, 0
+semilab.hu, 0
+seminuevos.com, 0
+semmel.de, 0
+sem-tem.ru, 0
+senado.gov.br, 0
+senai.br, 0
+sendpulse.com, 0
+sendsay.ru, 0
+sendsms.az, 0
+sendyit.com, 0
+sengled.com, 0
+sense.com, 0
+sensorika.uz, 0
+sensorytechnologies.com, 0
+sentres.com, 0
+seodollars.com, 0
+seofangfa.com, 0
+seolib.ru, 0
+seomon.com, 0
+seo-protools.com, 0
+seopult.pro, 0
+seopult.ru, 0
+seo-summary.de, 0
+seoul.co.kr, 0
+seo-united.de, 0
+seowhy.com, 0
+sepidwebhost.com, 0
+septgame.com, 0
+seresco.es, 0
+serg-casper.ru, 0
+sergeisokolov.com, 0
+serifgungor.com, 0
+serj.ws, 0
+sertification.org, 0
+servebbs.com, 0
+servebeer.com, 0
+serveftp.com, 0
+serveftp.net, 0
+serveftp.org, 0
+servegame.com, 0
+servehttp.com, 0
+servel.cl, 0
+serveminecraft.net, 0
+server4u.cz, 0
+server4you.de, 0
+server4you.net, 0
+serverdale.com, 0
+server-he.de, 0
+server.ir, 0
+serveriran.net, 0
+server-it.net, 0
+servernesia.com, 0
+servernews.ru, 0
+serveromat.com, 0
+serverprofi24.com, 0
+serverprofi24.de, 0
+serverprofi24.net, 0
+server-sponsoring.com, 0
+service-schematics.ru, 0
+servispckupka.cz, 0
+servisvk.ru, 0
+servyou.com.cn, 0
+sestosg.net, 0
+setca.org, 0
+setia.pl, 0
+setmore.com, 0
+setonhill.edu, 0
+setti.info, 0
+seu.edu.cn, 0
+se-unsa.org, 0
+sevaft.cn, 0
+sevastopol.press, 0
+sev-eishockey.de, 0
+seven-sky.net, 0
+severstalgroup.com, 0
+sevidi.ru, 0
+sevpolitforum.ru, 0
+sevsu.ru, 0
+sevt.cz, 0
+sexacg.com, 0
+sexchats.ru, 0
+sexhotgames.com, 0
+sexkompas.me, 0
+sexlikereal.com, 0
+seznamzbozi.cz, 0
+sfacg.com, 0
+sf-addon.com, 0
+sfe8.com, 0
+sfedu.ru, 0
+sf-express.com, 0
+sff.gr, 0
+sfgame.cz, 0
+sfgame.de, 0
+sfgame.es, 0
+sfgame.fr, 0
+sfgame.gr, 0
+sfgame.hu, 0
+sfgame.it, 0
+sfgame.net, 0
+sfgame.pl, 0
+sfgame.ru, 0
+sfgame.sk, 0
+sfgame.us, 0
+sfgame.web.tr, 0
+sf-helper.com, 0
+sflep.com, 0
+sf-misis.ru, 0
+sformat.ru, 0
+sfs.gov.ua, 0
+sfuh.tk, 0
+sfu-kras.ru, 0
+sfworldwide.com, 0
+sfy.ru, 0
+sg-autorepondeur.com, 0
+sgcc.com.cn, 0
+sgcc.uz, 0
+sgd.de, 0
+sgeb.bg, 0
+sglgroup.com, 0
+sgmw.com.cn, 0
+sgroshi.com.ua, 0
+sguo.com, 0
+sg-video.com, 0
+sgyy.com.cn, 0
+shab.ch, 0
+shade3d.jp, 0
+shadeyouvpn.com, 0
+shadowcraft.ru, 0
+shadowfly.org, 0
+shadowpad.jp, 0
+shadowsky.site, 0
+shadowsock.club, 0
+shadowsocks.im, 0
+shahinsoft.ir, 0
+shahroodut.ac.ir, 0
+shairart.com, 0
+shallmap.com, 0
+shamana.co, 0
+shanbay.com, 0
+shandongair.com.cn, 0
+shanghaidisneyresort.com, 0
+shanghai-electric.com, 0
+shanghaitech.edu.cn, 0
+shantou.gov.cn, 0
+shaogood.com, 0
+shaozi.info, 0
+shapingrain.com, 0
+sharaland.ru, 0
+sharcnet.ca, 0
+shardsonline.com, 0
+sharedbox.com, 0
+shareinstock.com, 0
+shareitforpcdl.com, 0
+sharengo.it, 0
+sharepoint.cn, 0
+sharesdk.cn, 0
+sharklasers.com, 0
+shatel.ir, 0
+shatelland.com, 0
+shatura.com, 0
+shatura.ru, 0
+shayuvpnn.com, 0
+shdf.gov.cn, 0
+shd.ru, 0
+shebaoonline.com, 0
+sheedantivirus.ir, 0
+sheencity.com, 0
+shengcaijinrong.com, 0
+shengchifoundation.org, 0
+shengjingvip.com, 0
+shengri.cn, 0
+shengyeji.com, 0
+shenzhan.in, 0
+shenzhenware.com, 0
+shenzhong.net, 0
+sherbrooke.qc.ca, 0
+sheridanc.on.ca, 0
+sherlock-holm.es, 0
+sherweb.com, 0
+shetabha.com, 0
+shgb.gov.cn, 0
+shgcx.org, 0
+sh.gov.cn, 0
+shhyolkovo.ru, 0
+shiep.edu.cn, 0
+shiftelearning.com, 0
+shiftinglight.com, 0
+shiftphones.com, 0
+shikimori.org, 0
+shimadzu.com.cn, 0
+shina.ru, 0
+shineon.cc, 0
+shinezone.com, 0
+shintorg48.ru, 0
+shippable.com, 0
+shipxy.com, 0
+shiqichan.com, 0
+shiqichuban.com, 0
+shirazwebhost.com, 0
+shirazwebhost.ir, 0
+shitou.com, 0
+shlyahten.ru, 0
+shmarathon.com, 0
+shmh.gov.cn, 0
+shmtu.edu.cn, 0
+shmu.sk, 0
+shockmodels.su, 0
+shoe.org, 0
+shoessale.com.ua, 0
+shomaresaz.ir, 0
+shom.fr, 0
+shooshmall.com, 0
+shooter.cn, 0
+shoot-n-joy.ru, 0
+shopandroid.com, 0
+shop-apotheke.com, 0
+shopbuilder.cz, 0
+shopbuilder.hr, 0
+shopbuilder.ro, 0
+shopbuilder.sk, 0
+shopcar.ir, 0
+shopdutyfree.eu, 0
+shop.hu, 0
+shopinamerica.am, 0
+shoplex.com, 0
+shop-lining.com, 0
+shop-logistics.ru, 0
+shopmania.bg, 0
+shopmania.biz, 0
+shopmania.com, 0
+shopmania.com.br, 0
+shopmania.com.mx, 0
+shopmania.co.uk, 0
+shopmania.co.za, 0
+shopmania.de, 0
+shopmania.es, 0
+shopmania.fr, 0
+shopmania.hr, 0
+shopmania.hu, 0
+shopmania.in, 0
+shopmania.it, 0
+shopmania.nl, 0
+shopmania.pl, 0
+shopmania.pt, 0
+shopmania.ro, 0
+shopmania.rs, 0
+shopmaster2.ru, 0
+shopnctest.com, 0
+shopozz.ru, 0
+shoppal.in, 0
+shoptimize.in, 0
+shop.unas.hu, 0
+shopvote.de, 0
+shorten.id, 0
+short.id, 0
+shost.ca, 0
+shoujichahao.com, 0
+shoujiduoduo.com, 0
+shouqianba.com, 0
+shouqu.me, 0
+shoushang.com, 0
+shouyeren.org, 0
+showapi.com, 0
+showjet.ru, 0
+showpark.info, 0
+showradyo.com.tr, 0
+shox.hu, 0
+shpt188.com, 0
+shrinktheweb.com, 0
+shtorm.com, 0
+shtrih-m.ru, 0
+shtukishop.ru, 0
+shuaigay.top, 0
+shuax.com, 0
+shufe.edu.cn, 0
+shunde.gov.cn, 0
+shunwang.com, 0
+shunxingkeji.com, 0
+shupl.edu.cn, 0
+shurup.net.ua, 0
+shuxuejia.com, 0
+shwebook.com, 0
+shwilling.com, 0
+shyaway.com, 0
+shyling.com, 0
+siamchart.com, 0
+siaranku.com, 0
+sia.ru, 0
+siasun.com, 0
+siava.ru, 0
+siberianet.ru, 0
+sibername.com, 0
+sibintek.ru, 0
+sibpsa.ru, 0
+sibsau.ru, 0
+sibstrin.ru, 0
+sibsutis.ru, 0
+sibvaleo.tv, 0
+sicau.edu.cn, 0
+sickoo.com, 0
+sicofi.com.mx, 0
+sidechef.com, 0
+sidex.ru, 0
+sidsavara.com, 0
+siedlce.pl, 0
+siedle.de, 0
+sielok.hu, 0
+sigaretnik.ru, 0
+sigfox.com, 0
+sigmabeauty.com, 0
+sigmasport.com, 0
+signfiles.com, 0
+sigsiu.net, 0
+sihaidiaoyu.com, 0
+sikoauktioner.se, 0
+silagames.com, 0
+silamp.it, 0
+silextimes.com, 0
+silhouette-ac.com, 0
+silijiren.info, 0
+silk.co, 0
+silkenowak.de, 0
+sil.org.pg, 0
+siluyuncang.com, 0
+silverspoons.ru, 0
+sim-auf-reisen.de, 0
+simm.ac.cn, 0
+simpatias.org, 0
+simple-aja.info, 0
+simplefx.com, 0
+simplemachines.ru, 0
+simplementegenial.cc, 0
+simpleminecraft.ru, 0
+simplenetkeeper.com, 0
+simplesite.com, 0
+simpleso.gr, 0
+simple-talk.com, 0
+simplewebrtc.com, 0
+simplix.info, 0
+simplix.ks.ua, 0
+simplytest.me, 0
+simpress.com.br, 0
+simuwang.com, 0
+sinaapp.com, 0
+sina.com.cn, 0
+sinam.net, 0
+sinchew.com.my, 0
+sindiconet.com.br, 0
+sinerji.gen.tr, 0
+sinica.edu.tw, 0
+sininonton.com, 0
+sinochem.com, 0
+sinofsx.com, 0
+sinonimus.ru, 0
+sinopec.com, 0
+sinopharm.com, 0
+sinosig.com, 0
+sinosoft.info, 0
+sintagespareas.gr, 0
+sintek-nn.ru, 0
+sinyi.com.tw, 0
+sioeye.cn, 0
+sioeye.com, 0
+sipac.gov.cn, 0
+sipo.gov.cn, 0
+sipsolutions.net, 0
+sipwise.com, 0
+sirvoy.com, 0
+sisalu.com.br, 0
+si-shell.net, 0
+sistel.es, 0
+sistemagorod.ru, 0
+sistemdestekuzmani.com, 0
+sisustusweb.ee, 0
+site40.net, 0
+site88.net, 0
+siteclinic.ru, 0
+siteencore.com, 0
+siteguarding.com, 0
+sitelement.sk, 0
+siterobot.com, 0
+site.ua, 0
+sito.ir, 0
+situstarget.com, 0
+siwatcher.ru, 0
+siwe.com.cn, 0
+sixsenses.com, 0
+sixtea.com, 0
+sjcamhd.com, 0
+sjc.edu.hk, 0
+sjedu.cn, 0
+sjtu.cn, 0
+sjtu.edu.cn, 0
+sjz.io, 0
+sk3w.se, 0
+skalnik.pl, 0
+skat-palast.de, 0
+skat-ups.ru, 0
+skauting.cz, 0
+skbank.com.tw, 0
+skechers.cn, 0
+sketchengine.co.uk, 0
+sketchpark.ru, 0
+skierniewice.pl, 0
+skifmusic.ru, 0
+skinak.ir, 0
+skincrates.com, 0
+skinpay.com, 0
+skinrenewal.co.za, 0
+skiosvetimany.cz, 0
+skiprefer.com, 0
+sk.kz, 0
+skn1.com, 0
+sknt.ru, 0
+skobbler.com, 0
+skobeeff.ru, 0
+skoda.com.cn, 0
+skoda.lv, 0
+skokie68.org, 0
+skoltech.ru, 0
+skr.de, 0
+skritter.com, 0
+skrivanek.cz, 0
+sktelecom.com, 0
+skuonline.ru, 0
+sky4buy.com, 0
+skyany.com, 0
+skybuy.ru, 0
+skycenter.aero, 0
+skydreamer.fr, 0
+skydreamer.info, 0
+skyf-host.com, 0
+skyfox.org, 0
+skygear.ru, 0
+skyinsurance.co.uk, 0
+skyluxtravel.com, 0
+skynetonline.solutions, 0
+skyocean.com, 0
+skyprep.com, 0
+skyrim-online.com, 0
+skytells.net, 0
+skywayinvestgroup.com, 0
+slack.com, 0
+slack-files.com, 0
+slack-imgs.com, 0
+slack-redir.net, 0
+slacky.eu, 0
+slatarow.de, 0
+slaters.co.uk, 0
+slav-dom.ru, 0
+slavia.by, 0
+slavyansk2.ru, 0
+slavyanskaya-kultura.ru, 0
+sldc.eu, 0
+sleep-calculator.com, 0
+slevadne.cz, 0
+slevhouse.cz, 0
+slicedinvoices.com, 0
+slidego.com, 0
+slide-life.ru, 0
+slinuxer.com, 0
+slio.cn, 0
+slitheriogameplay.com, 0
+slotboss.co.uk, 0
+slotboss.se, 0
+sloty-besplatno.net, 0
+slovodel.com, 0
+slunecnice.cz, 0
+slv.cz, 0
+small.kz, 0
+smarket.net.cn, 0
+smarp.com, 0
+smarpshare.com, 0
+smartafisha.ru, 0
+smartapps.fr, 0
+smartdollar.com, 0
+smartdot.com, 0
+smartdrugsforcollege.com, 0
+smarterdeal.co.uk, 0
+smartflowsheet.com, 0
+smarthosts.org, 0
+smarthoverboarder.fr, 0
+smarthoverboarder.it, 0
+smartisan.com, 0
+smartjobboard.com, 0
+smartlab.co.za, 0
+smartland.am, 0
+smartlog.jp, 0
+smartmedia.ws, 0
+smartmetrics.co, 0
+smart.net.ly, 0
+smartnweb.de, 0
+smartserials.com, 0
+smarttbot.com, 0
+smarty.cz, 0
+smartytoys.ru, 0
+smash.com, 0
+sma.so, 0
+smasurf.com, 0
+smath.info, 0
+sm.de, 0
+smec-cn.com, 0
+smed.ru, 0
+smetnoedelo.ru, 0
+smeup.com, 0
+sm.gov.cn, 0
+sm.gov.ua, 0
+smh.re, 0
+smi2.ru, 0
+sm-komandor.ru, 0
+smmplanner.com, 0
+smokepack.ru, 0
+smokingirl.org, 0
+smoothscroll.net, 0
+smotreshka.tv, 0
+smotri.com, 0
+smotriuchis.ru, 0
+smow.de, 0
+smsbrana.cz, 0
+smsdengi.com, 0
+smshare.fr, 0
+smshosting.it, 0
+smsmoney.ee, 0
+smspinigai.lt, 0
+sms-track.ru, 0
+smstronic.com, 0
+smter.ru, 0
+sm.ua, 0
+smuc.ac.kr, 0
+smvdu.ac.in, 0
+smxe.cn, 0
+smydh.cn, 0
+smyl.es, 0
+snacksbazzar.com, 0
+snacktools.net, 0
+snaga.si, 0
+snap2sex.nl, 0
+snapapp.com, 0
+snapchatonlineloginz.com, 0
+snapgene.com, 0
+snappii.com, 0
+snh48.com, 0
+snips.ai, 0
+snoska.ru, 0
+snowsports.org, 0
+snowtrails.com, 0
+snpmarket.com, 0
+snptc.com, 0
+snrt.ma, 0
+snssdk.com, 0
+snu.ac.kr, 0
+snugr.be, 0
+snv.sk, 0
+soargames.com, 0
+sobi.pro, 0
+sobs.com.au, 0
+sobt5.org, 0
+sobug.com, 0
+soccer-plaza.jp, 0
+sociafluence.com, 0
+social-health.net, 0
+social-net.me, 0
+socialquantum.ru, 0
+socialssap.org, 0
+socialsweethearts.de, 0
+socialtheater.com, 0
+socialtools.ru, 0
+social-touch.com, 0
+societe.com, 0
+socionet.ru, 0
+so.com, 0
+sodrk.ru, 0
+soe.com.ua, 0
+sofa-framework.org, 0
+sofotos.org, 0
+softconf.com, 0
+softether.net, 0
+softkey.ru, 0
+softline.com.pl, 0
+softlinegroup.com, 0
+softmath.com, 0
+softonit.ru, 0
+softros.com, 0
+softserveinc.com, 0
+softwareschmiede.org, 0
+softwaresystems.com, 0
+software.travel, 0
+sog-ict.nl, 0
+sogo.com.tw, 0
+sogou.com, 0
+so.gov.pl, 0
+sohucs.com, 0
+soireejumpin.fr, 0
+soiro.ru, 0
+sojson.com, 0
+sojump.cn, 0
+sojump.com, 0
+sojump.hk, 0
+sokka.cn, 0
+sokolniki.com, 0
+sokolov.ru, 0
+soku.com, 0
+solarcentury.com, 0
+solarianprogrammer.com, 0
+solarmanpv.com, 0
+solax-portal.com, 0
+solestruck.com, 0
+solidapps.co.uk, 0
+solidot.org, 0
+solid-profit.com, 0
+soloaffitti.it, 0
+solonetwork.com.br, 0
+solvege.net, 0
+solvvy.com, 0
+somebox.ru, 0
+somitel.pt, 0
+somonair.com, 0
+sonapresse.com, 0
+songo.com, 0
+sonikelf.ru, 0
+sonnenstaatland.com, 0
+soonnet.org, 0
+soorati.com, 0
+soorensystem.ir, 0
+sopot.pl, 0
+soprasteria.com, 0
+soroki.com, 0
+sorucevapla.com, 0
+sorz.org, 0
+sosista.com, 0
+sosobta.cn, 0
+sosobtc.com, 0
+sosowifi.com, 0
+sos.pl, 0
+sostronk.com, 0
+sotel.de, 0
+soti.net, 0
+sotis-online.ru, 0
+sotovikmobile.ru, 0
+soujuw.com, 0
+soujuw.net, 0
+soulkeepers.eu, 0
+soundcloudgroups.com, 0
+soundcream.net, 0
+soundgasm.net, 0
+so-ups.ru, 0
+sourcefabric.org, 0
+sourceguardian.ir, 0
+soushiti.com, 0
+southernexposure.com, 0
+southernfund.com, 0
+southmoney.com, 0
+southplainscollege.edu, 0
+souyidai.com, 0
+souz-m.ru, 0
+sov5.com, 0
+sovkusom.ru, 0
+sovtime.ru, 0
+soyoung.com, 0
+sp2all.ru, 0
+sp2.org, 0
+spacebagel.com, 0
+spacedock.info, 0
+spaceinvasion.info, 0
+spacem.cn, 0
+spaceorigin.fr, 0
+spaces.ru, 0
+spaceweb.hu, 0
+spac.me, 0
+spagobi.org, 0
+spagoworld.org, 0
+spanishprograms.com, 0
+spankwiki.org, 0
+spankwirecams.com, 0
+spanwords.info, 0
+spar.ch, 0
+sparcs.org, 0
+spar-dich-schlau.de, 0
+sparinc.com, 0
+sparkasse-landshut.de, 0
+spark.ru, 0
+sparrowsms.com, 0
+spawtz.com, 0
+spaziorc.net, 0
+spbappo.ru, 0
+spbgasu.ru, 0
+spbgut.ru, 0
+spbstu.ru, 0
+spb.su, 0
+spbu.ru, 0
+spbvedomosti.ru, 0
+spca.org.hk, 0
+spddl.de, 0
+spdns.de, 0
+spdns.org, 0
+speak-up.com, 0
+specialist.ru, 0
+spec-komp.com, 0
+specregion.ru, 0
+speech-guru.com, 0
+speechpad.pw, 0
+speechpad.ru, 0
+speedify.com, 0
+speedinvoice3.net, 0
+speedx.co, 0
+speedyshare.com, 0
+speeed.cn, 0
+speiyou.cn, 0
+speiyou.com, 0
+sperasoft.com, 0
+spesifikasiharga.com, 0
+spfu.gov.ua, 0
+sp.gov.br, 0
+sphero.com, 0
+spi0n.com, 0
+spigit.com, 0
+spihk.com, 0
+spikcompany.ru, 0
+spiketime.de, 0
+spinbackup.com, 0
+spir.fr, 0
+spitalspiridon.ro, 0
+spi.uz, 0
+spk.ru, 0
+splatterladder.com, 0
+splento.com, 0
+spl.info, 0
+splio.com, 0
+splitmetrics.com, 0
+splius.lt, 0
+spoilertime.com, 0
+spolo.org, 0
+spongepowered.org, 0
+sponsorpay.com, 0
+sportbedarf.de, 0
+sportbro.cc, 0
+sportcity74.ru, 0
+sportdiver.com, 0
+sportfishingmag.com, 0
+sportfort.ru, 0
+sporthit.ru, 0
+sportourism.id, 0
+sportovnidum.cz, 0
+sportovnivozy.cz, 0
+sportplayer.io, 0
+sportrider.com, 0
+sport-sante.fr, 0
+sportsbet.com.au, 0
+sportsbetting.ag, 0
+sportsbikeshop.co.uk, 0
+sportsboom.tv, 0
+sportse.ru, 0
+sportspar.de, 0
+sports.ru, 0
+sportvision.rs, 0
+spot.im, 0
+spotsoon.com, 0
+sprashivai.ru, 0
+spravka333333.ru, 0
+spravka-mdv.ru, 0
+spravkatver.ru, 0
+spray.pk, 0
+spring96.org, 0
+springstreetads.com, 0
+sprintground.com, 0
+sprintinet.ru, 0
+sprit.org, 0
+sprucemeadows.com, 0
+spruethmagers.com, 0
+sprut.ru, 0
+spsdmasna.cz, 0
+spsd.net, 0
+spsejecna.cz, 0
+spsostrov.cz, 0
+spsr.ru, 0
+spurssh.com, 0
+sputnikipogrom.com, 0
+spybot.info, 0
+spyshop.pl, 0
+spyzer.ru, 0
+sqli.com, 0
+sqlitebrowser.org, 0
+sqlservercentral.com, 0
+s-quad.com, 0
+squick.me, 0
+squidge.org, 0
+squiresgardencentres.co.uk, 0
+squirt.org, 0
+squnity.com, 0
+sqybus.fr, 0
+sram.com, 0
+srb2.org, 0
+srcf.net, 0
+srgame.cc, 0
+srh-hochschule-berlin.de, 0
+srlabs.de, 0
+srovnanicen.cz, 0
+srt.gob.ar, 0
+srvgame.ru, 0
+sscat.cn, 0
+ssdax.com, 0
+ssd-life.com, 0
+ssd-life.ru, 0
+sse.com.cn, 0
+sseinfo.com, 0
+ssh91.net, 0
+sshida.com, 0
+s-shot.ru, 0
+ssig33.com, 0
+ssjoy.org, 0
+ssjsq.net, 0
+sskaje.me, 0
+ssl-brn.de, 0
+ssllabs.com, 0
+sslpost.com, 0
+sslunblocker.com, 0
+ssm.gob.mx, 0
+ssmu.ru, 0
+ssn.gob.ar, 0
+ssorz.com, 0
+sspaas.com, 0
+sspanda.com, 0
+ssrj.com, 0
+ssr-russia.ru, 0
+ssspeed.net, 0
+sstl.co.uk, 0
+ssuu.org, 0
+ssvpn.vip, 0
+ssw.com.au, 0
+ss.wtf, 0
+stac.co.ao, 0
+stackage.org, 0
+stacktile.io, 0
+stadium.ru, 0
+stadtfeuerwehr-weiz.at, 0
+stadt-helmstedt.de, 0
+stadtmobil.de, 0
+stadttheater-giessen.de, 0
+staffpoint.fi, 0
+staforceteam.ru, 0
+stagend.com, 0
+stahl.de, 0
+stairways.com, 0
+stalcraft.ru, 0
+stalker.land, 0
+stalker-shop.ru, 0
+stamboomforum.nl, 0
+stample.co, 0
+stampsy.com, 0
+standa.lt, 0
+standardfacile.com, 0
+stanford.edu, 0
+stanfy.com, 0
+stanmus.ru, 0
+staradworld.com, 0
+staramba.com, 0
+staraya-moneta.ru, 0
+starchefs.com, 0
+star-citizens.de, 0
+starduster.me, 0
+starfandom.com, 0
+star-force.com, 0
+stargard.pl, 0
+stargatesys.com, 0
+starislandgames.com, 0
+starleaf.com, 0
+starline-online.ru, 0
+starlink.ru, 0
+starmediafilm.com, 0
+stars-cloud.com, 0
+starship.xyz, 0
+startcomca.com, 0
+startcom.org, 0
+startdedicated.com, 0
+startdedicated.de, 0
+startdedicated.net, 0
+startsearch.org, 0
+startsmile.ru, 0
+startssl.com, 0
+startss.today, 0
+startus.cc, 0
+state.ak.us, 0
+state-of-mind.de, 0
+state.or.us, 0
+statfuse.com, 0
+statgrad.org, 0
+status301.net, 0
+statusmoto.ru, 0
+stat.uz, 0
+staubli.com, 0
+stavregion.ru, 0
+stayfriends.de, 0
+stayge.net, 0
+stays.io, 0
+stb.com.mk, 0
+st-clair.net, 0
+stcn.com, 0
+stealthy.co, 0
+steam.az, 0
+steambroker.com, 0
+steammoney.com, 0
+steamrepcn.com, 0
+steam-trader.com, 0
+steelalborz.com, 0
+steelorse.com, 0
+stefanini.com, 0
+steinberg.de, 0
+steinberg.fr, 0
+steinberg.net, 0
+steinigke.de, 0
+stelderverspeek.com, 0
+stellenticket.de, 0
+stepan.com, 0
+stepclub.ru, 0
+stephencleary.com, 0
+stephenwebster.com, 0
+sterlinginfosystems.com, 0
+stetsom.com.br, 0
+stevecookhealth.com, 0
+stevejenkins.com, 0
+stewardship.com, 0
+stfalcon.com, 0
+stforex.com, 0
+sth.ac.at, 0
+stickyadstv.com, 0
+stiesia.ac.id, 0
+stirileprotv.ro, 0
+stiripesurse.ro, 0
+stis.ac.id, 0
+st-link.com.cn, 0
+stlouisfed.org, 0
+stluke.com.ph, 0
+sto.cc, 0
+stockfuse.com, 0
+stockinthechannel.com, 0
+stockinthechannel.co.uk, 0
+sto.cn, 0
+stolle.ru, 0
+stoloto.ru, 0
+stomatorg.ru, 0
+stom.ru, 0
+storeapps.org, 0
+storemags.com, 0
+storii.com, 0
+stormss.us, 0
+stormway.ru, 0
+stor.re, 0
+storymixmedia.com, 0
+storyworth.com, 0
+stradeanas.it, 0
+strafbuch.de, 0
+strangled.net, 0
+strategya.com, 0
+strategyanalytics.com, 0
+strategy-p.co.jp, 0
+stratoserver.net, 0
+stray.love, 0
+str.by, 0
+streamatehelp.com, 0
+streamatemodels.com, 0
+streamcatcher.de, 0
+streamcraft.net, 0
+streamenergybilling.com, 0
+streamify.me, 0
+streamingtank.com, 0
+streamjar.tv, 0
+streampub.net, 0
+streeetchypants.com, 0
+streetbank.com, 0
+streetmeatasia.com, 0
+strelkacard.ru, 0
+stressfree.pl, 0
+strmama.ru, 0
+stroeerdigitalpublishing.de, 0
+stroi-baza.ru, 0
+stroi-ka.by, 0
+stroitelstvosovety.ru, 0
+strollup.in, 0
+stronazen.pl, 0
+stronger.se, 0
+stroygigant.ru, 0
+stroylandiya.ru, 0
+stroysvoimirukami.ru, 0
+strunz.com, 0
+sts-niendorf.de, 0
+studierenplus.de, 0
+studio-fashion.com, 0
+studiorent.ru, 0
+studio-seo.org, 0
+studybay.com, 0
+studystays.com.au, 0
+stu.edu.vn, 0
+stuffio.com, 0
+stuq.org, 0
+sturmtools.ru, 0
+stusz.com, 0
+stuttcars.com, 0
+stylingandroid.com, 0
+stylished.de, 0
+su0.ru, 0
+suanfazu.com, 0
+subfactory.fr, 0
+sublinet.com, 0
+submail.cn, 0
+subnets.ru, 0
+suche6.ch, 0
+sudact.ru, 0
+suda.edu.cn, 0
+sudanzip.com, 0
+sudmed.ru, 0
+sudoku-knacker.de, 0
+suedostschweiz.ch, 0
+su.edu, 0
+sues.edu.cn, 0
+sufficientvelocity.com, 0
+suffieldacademy.org, 0
+sugon.com, 0
+suitaweb.net, 0
+suiyueyule.com, 0
+suketiawan.com, 0
+sukl.sk, 0
+sulinet.hu, 0
+sulrevendas.com.br, 0
+sumanet.cz, 0
+sumaou.com, 0
+sumavision.com, 0
+sumdu.edu.ua, 0
+summa-prefis.com, 0
+sumochka.com, 0
+sumpay.cn, 0
+sumtel.ru, 0
+sunagesh.com, 0
+sunallies.com, 0
+sunbox.cc, 0
+suncco.com, 0
+sundaynews.co.zw, 0
+sundray.com.cn, 0
+sundukup.ru, 0
+sunfar.com.tw, 0
+suninfo.com, 0
+suning.cn, 0
+suning.com, 0
+suninian.com, 0
+sunkei.edu.hk, 0
+sunland.org.cn, 0
+sunlands.com, 0
+sunmnet.com, 0
+sunny-dessous.de, 0
+sunnyos.com, 0
+sunrav.ru, 0
+sunrise74.com, 0
+sunshine-live.de, 0
+sunskypars.ir, 0
+suntech-power.com, 0
+suntektech.com, 0
+sunwenqi.cn, 0
+suonuo.net, 0
+supaprice.co.uk, 0
+supardi.net, 0
+supbiotech.fr, 0
+supcon.com, 0
+superb.net, 0
+superbotanik.net, 0
+super-cena.rs, 0
+superguiaargentina.com.ar, 0
+superhosting.cz, 0
+supermagnete.at, 0
+supermagnete.ch, 0
+supermagnete.de, 0
+supermagnete.es, 0
+supermagnete.fr, 0
+supermagnete.it, 0
+supermap.com, 0
+supernano.com, 0
+superpedestrian.com, 0
+superphysique.org, 0
+supersoused.cz, 0
+supersyntages.gr, 0
+supertelahd.com, 0
+supertransporte.gov.co, 0
+supervia.com.br, 0
+super-warez.net, 0
+superweibu.com, 0
+supl.biz, 0
+suplementosbrasil.org, 0
+suppore.cn, 0
+sura.ru, 0
+surbtc.com, 0
+surebak.com, 0
+sureserver.com, 0
+suresupport.com, 0
+surfingbird.com, 0
+surfingbird.ru, 0
+surlybrewing.com, 0
+surong360.com, 0
+suroot.com, 0
+surpk.ru, 0
+surplussales.com, 0
+surprizim.net, 0
+surtime.com, 0
+surveylegend.com, 0
+survivaldub.com, 0
+sushishop.ru, 0
+sustc.edu.cn, 0
+sust.edu.cn, 0
+susu.ru, 0
+sut.ru, 0
+suuntoshop.ir, 0
+suwalki.pl, 0
+suwon.ac.kr, 0
+suws.org.uk, 0
+suxilog.com, 0
+suzlon.com, 0
+suzuki-china.com, 0
+sv98.de, 0
+svadbagolik.ru, 0
+svadebka.ws, 0
+svarecky-obchod.cz, 0
+svarforum.cz, 0
+svastour.ru, 0
+svcc.edu, 0
+sv.co, 0
+sven.de, 0
+svenskenergi.se, 0
+sverbihina.com, 0
+svetofor.info, 0
+svetosila.ru, 0
+s-vfu.ru, 0
+svgc.ru, 0
+svicenter.com, 0
+svijet-medija.hr, 0
+svirel.org, 0
+svlfg.de, 0
+svmed.spb.ru, 0
+svobodni.cz, 0
+svoy-golos.ru, 0
+svp-team.com, 0
+svsbb.sk, 0
+svyaznoy.ru, 0
+svyturioarena.lt, 0
+svzt.ru, 0
+swagbucks.com, 0
+swagelok.com.cn, 0
+swamiji.tv, 0
+swannetoscar.com, 0
+swan.sk, 0
+swcszx.com, 0
+sweatband.com, 0
+sweek.com, 0
+sweet211.ru, 0
+swfmax.com, 0
+swfr.de, 0
+swidnik.pl, 0
+swiftirc.net, 0
+swiftzer.net, 0
+swi.mx, 0
+swis.cn, 0
+swissgolden.com, 0
+swissmedical.com.ar, 0
+swjoy.com, 0
+swjtu.edu.cn, 0
+swoop.com, 0
+swpu.edu.cn, 0
+sws.cz, 0
+swsu.org, 0
+swsu.ru, 0
+swu.edu.cn, 0
+swufe.edu.cn, 0
+swust.edu.cn, 0
+sxcert.com, 0
+sxchfz.com, 0
+sxe-injected.com, 0
+sxrczx.com, 0
+syau.edu.cn, 0
+sydneynewyearseve.com, 0
+sygic.com, 0
+sygnity.pl, 0
+syischina.com, 0
+symmetry.com, 0
+symphonic-net.com, 0
+symptoma.com, 0
+synchronkartei.de, 0
+synchronoss.com, 0
+syncis.com, 0
+syncthing.net, 0
+sync-video.com, 0
+syndriver.com, 0
+synergize.co, 0
+synevo.by, 0
+synlab.org.cn, 0
+synology.me, 0
+syronex.com, 0
+sysadmin.ru, 0
+sys-advisor.com, 0
+sys-con.com, 0
+sysfx.com, 0
+syslinux.org, 0
+syssel.net, 0
+systech.hu, 0
+systec.ru, 0
+systena.co.jp, 0
+systextil.com.br, 0
+systtech.ru, 0
+systutorials.com, 0
+sysucc.org.cn, 0
+sysu.edu.cn, 0
+sytes.net, 0
+syure.com, 0
+sz12333.gov.cn, 0
+sz189.cn, 0
+szaic.gov.cn, 0
+szamlakozpont.hu, 0
+szcredit.com.cn, 0
+szcredit.org.cn, 0
+szeged.hu, 0
+szft.gov.cn, 0
+szgaj.cn, 0
+szgalaxy.com, 0
+sz.gov.cn, 0
+szgs.gov.cn, 0
+szhome.com, 0
+sziit.edu.cn, 0
+sz-its.cn, 0
+szjs.gov.cn, 0
+szjzz.gov.cn, 0
+szmb.gov.cn, 0
+szm.com, 0
+szmqs.gov.cn, 0
+szn-ural.ru, 0
+szone-online.net, 0
+szone-online.so, 0
+szpilot.com.cn, 0
+szrtc.cn, 0
+szsce.si, 0
+szscjg.gov.cn, 0
+szse.cn, 0
+szsi.gov.cn, 0
+szsti.gov.cn, 0
+sztb.gov.cn, 0
+szu.edu.cn, 0
+szvc.com.cn, 0
+szweb.cn, 0
+szweiflr.cn, 0
+sz-ybbs.ac.at, 0
+szybko.pl, 0
+szzfgjj.com, 0
+t2bot.ru, 0
+t2cksec.net, 0
+t4vps.eu, 0
+t4-wiki.de, 0
+table.co, 0
+tablepress.org, 0
+tabletki.ua, 0
+tablette-store.com, 0
+tabloidpulsa.co.id, 0
+tabnak.ir, 0
+tabris.ru, 0
+tabsbook.ru, 0
+tabstabs.com, 0
+tacr.cz, 0
+tactileo.fr, 0
+ta.de, 0
+tado.com, 0
+tagancity.ru, 0
+tagan.ru, 0
+tagplus.com.br, 0
+tagul.com, 0
+taifedu.gov.sa, 0
+taifungbank.com, 0
+tailtarget.com, 0
+taimen.com, 0
+taimyr24.ru, 0
+taipeifubon.com.tw, 0
+taipit.ru, 0
+taizhou.gov.cn, 0
+tajinfo.org, 0
+takcloud.com, 0
+takeeateasy.be, 0
+takeeateasy.fr, 0
+takibu.com, 0
+taknet.ir, 0
+takprosto.cc, 0
+taktaktak.ru, 0
+taktaserver.ir, 0
+takufile.com, 0
+talicai.com, 0
+talkabroad.com, 0
+talkfunnel.com, 0
+talkingcoder.com, 0
+talkingdata.com, 0
+talkmate.com, 0
+taller.su, 0
+tallynine.com, 0
+talon.by, 0
+tamasha.ir, 0
+tamera.org, 0
+tamilrockers.in, 0
+tangrui.wang, 0
+tangtao.net.cn, 0
+tanteng.me, 0
+tanzpol.org, 0
+taobao-0.com, 0
+taobaokhv.ru, 0
+taoche.com, 0
+taocrm.com, 0
+taodaxiang.com, 0
+taofl.cn, 0
+taokezhushou.com, 0
+taomee.com, 0
+taoqian123.com, 0
+taoqueqiao.com, 0
+taoshijie.com, 0
+taotaosou.com, 0
+taozj.org, 0
+tapgerine.com, 0
+tapki.com, 0
+ta.pl, 0
+tapochek.net, 0
+tappx.com, 0
+tarelki.com.ua, 0
+targethunter.net, 0
+tarlogic.com, 0
+tarr.hu, 0
+taschibra.com.br, 0
+tas-ix.net, 0
+taskobox.com, 0
+taskrow.com, 0
+tasnim.co, 0
+tataelxsi.co.in, 0
+tatar-inform.ru, 0
+tatar.ru, 0
+tatenergosbyt.ru, 0
+tatler.ru, 0
+tatneft.ru, 0
+tattelecom.ru, 0
+tattoomaster-shop.ru, 0
+tatukgis.com, 0
+tauernspakaprun.com, 0
+tavanir.org.ir, 0
+taxfreeshops.jp, 0
+taximaxim.com, 0
+taxisaturn.ru, 0
+taxnet.ru, 0
+taxo-parei-sto-kranio.com, 0
+taydoo-photographic.de, 0
+tayfunozer.com, 0
+taylors.edu.my, 0
+tazablog.com, 0
+tazzobikes.com, 0
+tbsign.cn, 0
+tca.com.br, 0
+tcc-clan.de, 0
+tcc.com.ua, 0
+tcdn.co, 0
+tc.edu.tw, 0
+tcgolestan.ir, 0
+tchkcdn.com, 0
+tci-dm.jp, 0
+tcl.com, 0
+tclkuyu.com, 0
+tczew.pl, 0
+tdf.fr, 0
+tdk.com, 0
+tdmu.edu.ua, 0
+tdx.com.cn, 0
+tdyun.com, 0
+teacher-of-russia.ru, 0
+teachersammy.com, 0
+teachers.io, 0
+teachfirst.de, 0
+teachvideo.ru, 0
+team29.org, 0
+teambition.net, 0
+teammelli.ir, 0
+teamshub.com, 0
+teamspeak-connection.de, 0
+team-ulm.de, 0
+teamxlink.co.uk, 0
+teanazar.com, 0
+teasermedia.net, 0
+teatrviktuka.ru, 0
+tecadmin.net, 0
+tecart.de, 0
+teccart.qc.ca, 0
+techglimpse.com, 0
+techloop.io, 0
+techmart.ir, 0
+techmeme.com, 0
+techno4ever.fm, 0
+technoblood.com, 0
+technocity.ru, 0
+techno-co.ru, 0
+technodom.kz, 0
+techold.ru, 0
+tech-on-air.com, 0
+techprom.ru, 0
+techraptor.net, 0
+techshot.ir, 0
+techwarelabs.com, 0
+techytalk.info, 0
+tecnoandroid.it, 0
+tecnohardclan.com, 0
+tecnolegis.com, 0
+tecno-mobile.com, 0
+tecnova.com.br, 0
+tecpt.com, 0
+tecsanpedro.edu.mx, 0
+tedliou.com, 0
+tedox.de, 0
+teflexpress.co.uk, 0
+teg.cn, 0
+tehiku.nz, 0
+tehnika4u.ru, 0
+tehnocentr.ru, 0
+tehnoland.lv, 0
+tehnomaks.ru, 0
+tehnomarket-ural.ru, 0
+tehnomir.com.ua, 0
+tehnorama.ru, 0
+tehnosila.ru, 0
+tehnoskarb.com.ua, 0
+tehprime.ru, 0
+tehrannews.ir, 0
+tekirdagnethaber.com, 0
+tekken-net.kr, 0
+teknic.com, 0
+teknikbilimler.net, 0
+teknokrat.ac.id, 0
+teknomobil.org, 0
+teknostation.net, 0
+tekscan.com, 0
+tekzen.com.tr, 0
+telconet.net, 0
+tele2.kz, 0
+telecable.es, 0
+telecamera.ru, 0
+telecentro.com.ar, 0
+telecom.by, 0
+telecomjs.com, 0
+telecom.kz, 0
+telefen.com, 0
+telefonica.de, 0
+telegraf.uz, 0
+telegramfriends.com, 0
+telekarta.tv, 0
+telekom.com, 0
+telekritika.ua, 0
+telemw.com, 0
+telenet.be, 0
+telenet.ru, 0
+telenor.dk, 0
+teleos.ru, 0
+tele-plus.ru, 0
+teleport.org, 0
+teleschau.de, 0
+teletal.hu, 0
+teletrade-asia.com, 0
+teletrade-dj.com, 0
+teletrade.ru, 0
+telin.co.id, 0
+telkomsel.com, 0
+tellefsen.net, 0
+telonko.com, 0
+telsome.es, 0
+teltec.de, 0
+template-help.com, 0
+templatemonster.com, 0
+templates.com, 0
+tempodisconti.it, 0
+temptationgifts.com, 0
+tencent.click, 0
+tendata.cn, 0
+tenddata.com, 0
+tenderplan.ru, 0
+tengrinews.kz, 0
+tennis-classim.net, 0
+tennisplayer.net, 0
+tenpointcrossbows.com, 0
+tensquaregames.com, 0
+tentorium.ru, 0
+tenvis.com, 0
+tera-byte.com, 0
+teralytics.net, 0
+teraserver.ir, 0
+tercihkitabevi.com, 0
+terema.com.br, 0
+teremok.ru, 0
+terra.im, 0
+terra.org, 0
+terrapinn.com, 0
+terredepeche.com, 0
+tesbuys.com, 0
+teshehui.com, 0
+tesli.com, 0
+tesoon.com, 0
+tesser.ru, 0
+testberichte.de, 0
+testdebit.info, 0
+testerhome.com, 0
+testforhost.com, 0
+testfreaks.com, 0
+test-hf.su, 0
+testkrok.org.ua, 0
+testomato.com, 0
+testvelocidad.eu, 0
+testwo.com, 0
+tetimes.com, 0
+tetranet.com.ua, 0
+tet.tv, 0
+teutloff-bs.de, 0
+texnoera.com, 0
+text-compare.com, 0
+textgears.com, 0
+textory.io, 0
+text.ru, 0
+tezign.com, 0
+tf2mart.net, 0
+tfb.ru, 0
+tfedu.net, 0
+tfm.ro, 0
+tfreeca2.com, 0
+tfshops.com, 0
+tfzq.com, 0
+tga-arsh.ir, 0
+tgl.ru, 0
+tgram.ru, 0
+th7.cn, 0
+thaiadpoint.com, 0
+thaibulksms.com, 0
+thaicsgo.com, 0
+thaigovno.com, 0
+thajsky-raj.cz, 0
+thalesgroup.com, 0
+thalia.hu, 0
+thali.ch, 0
+thanks-shine.com, 0
+thatvidieu.com, 0
+the5fire.com, 0
+thebeautyeffect.com, 0
+thebeautyplace.com, 0
+thebeerplanet.com.br, 0
+thebigchoice.com, 0
+thebigplans.ru, 0
+theblueprint.ru, 0
+thebreakroom.org, 0
+the-bride.ru, 0
+thecheat.co.kr, 0
+thecodecampus.de, 0
+thecoffeecompass.com, 0
+thecompletewebhosting.com, 0
+thecryptochat.net, 0
+thecus.com, 0
+thecustomizewindows.com, 0
+thedoschool.org, 0
+thedrakehotel.ca, 0
+theearthawaits.com, 0
+thefirstgive.com, 0
+thegeeksalive.com, 0
+theidentitypages.com, 0
+the-impish-ink.de, 0
+theindependentsf.com, 0
+thejesuitpost.org, 0
+thekcs.net, 0
+the-ken.com, 0
+thekua.com, 0
+thelibrarystore.com, 0
+thelife.com, 0
+thelongdark.ru, 0
+themaclife.com, 0
+themall.bg, 0
+themall.it, 0
+themefarmer.com, 0
+themient.com, 0
+themill.com, 0
+themusic.today, 0
+thenct.org.za, 0
+thenews.kz, 0
+theparkingspot.com, 0
+theprayerbook.info, 0
+theqarena.com, 0
+therange.co.uk, 0
+therealistictrader.com, 0
+therme.sk, 0
+thermomix.com, 0
+thesecretsofyoga.com, 0
+thesocietea.org, 0
+thesparxitsolutions.com, 0
+thestar.com.my, 0
+thestation.ru, 0
+thesycon.de, 0
+theteenboy.com, 0
+thewaiting-room.net, 0
+thewalrus.ru, 0
+thewatchtv.com, 0
+thewebtemplate.com, 0
+thg-kiel.de, 0
+thiememeulenhoff.nl, 0
+thinformatics.com, 0
+thinkingstorm.com, 0
+thinklocal.co.za, 0
+thinkmobiles.com, 0
+thinstuff.com, 0
+thirtymall.com, 0
+thisismyjam.com, 0
+thmmy.gr, 0
+thngs.co, 0
+thosmos.org, 0
+threema.ch, 0
+thruhere.net, 0
+thtf.com.cn, 0
+thuis.nl, 0
+thumbalizr.com, 0
+thumbnail-download.com, 0
+thunderforest.com, 0
+thunderquote.com, 0
+thunderstorm.pw, 0
+thus.ch, 0
+thuthuatvoz.com, 0
+ti8m.ch, 0
+tiancity.com, 0
+tianhong.cn, 0
+tianjinwe.com, 0
+tiantian8.com, 0
+tiantian.tv, 0
+tianti.io, 0
+tianyabagua.cn, 0
+tianyancha.com, 0
+tibame.com, 0
+ticka.it, 0
+tickeos.de, 0
+ticketflap.com, 0
+ticketgo.com.tw, 0
+tickets.az, 0
+tickets.com.tr, 0
+tickets.co.th, 0
+tickets.kz, 0
+tickets.pl, 0
+tickets.ru, 0
+tickets.ua, 0
+tickmill.com, 0
+tickmill.co.uk, 0
+ticp.net, 0
+ticsystem.co, 0
+ticwear.com, 0
+tidbits.com, 0
+tiendatiger.es, 0
+tienve.org, 0
+tierschutz-shop.de, 0
+tiff.net, 0
+tigase.org, 0
+tigergaming.com, 0
+tigra66.ru, 0
+tigrimigri.com, 0
+tilaa.com, 0
+tilab.com, 0
+timeface.cn, 0
+timeledger.com, 0
+timemanagement.es, 0
+time-master.ru, 0
+timepill.net, 0
+time.sc, 0
+timetoact.de, 0
+timetotrade.com, 0
+timios.com, 0
+timr.com, 0
+tingyun.com, 0
+tinkerpatch.com, 0
+tinned-software.net, 0
+tinohempel.de, 0
+tinper.org, 0
+tinycammonitor.com, 0
+tion.ru, 0
+tipdm.com, 0
+tiplanet.org, 0
+tipplap.hu, 0
+tipsport.sk, 0
+tiseagles.com, 0
+tiskarik.cz, 0
+tiss.edu, 0
+tiszacipo.hu, 0
+tita.com, 0
+titanic-magazin.de, 0
+titanix.net, 0
+titanpad.com, 0
+titans-servers.com, 0
+titrari.ro, 0
+titus.de, 0
+tixforgigs.com, 0
+tiyubisai.com, 0
+tizen.org, 0
+tjfdc.com.cn, 0
+tjms.jus.br, 0
+tjmt.jus.br, 0
+tjosm.com, 0
+tjournal.ru, 0
+tjpa.jus.br, 0
+tjto.jus.br, 0
+tju.edu.cn, 0
+tkbbank.ru, 0
+tk-chel.ru, 0
+tkgorod.ru, 0
+tl50.com, 0
+tlgrm.es, 0
+tlgrm.eu, 0
+tlgrm.ru, 0
+tlinx.cn, 0
+t-l.ru, 0
+tlushim.co.il, 0
+tmcaz.com, 0
+tmcnet.com, 0
+tmea.org, 0
+tmetric.com, 0
+tmg.nl, 0
+tmm-express.com, 0
+tmon.co.kr, 0
+tmoncorp.com, 0
+tmp.com, 0
+tmpyh.com, 0
+tmsf.com, 0
+tms.pl, 0
+tmweb.ru, 0
+tmy123.com, 0
+tn.edu.tw, 0
+tn.kz, 0
+tnpu.edu.ua, 0
+tns.lv, 0
+tns-ua.com, 0
+tntmusic.ru, 0
+tntrade.sk, 0
+tny.im, 0
+tobacco.com.cn, 0
+tobaccofreekids.org, 0
+tobem.jp, 0
+tobitcoin.biz, 0
+tochka.net, 0
+tocpeople.com, 0
+tode.cz, 0
+todoautos.com.pe, 0
+todogrowled.com, 0
+todojuguete.es, 0
+tofour.net, 0
+togas.com, 0
+togojoy.com, 0
+to.gov.br, 0
+tohkalove.com, 0
+toi-moi.com, 0
+toislam.ws, 0
+tokaweb.ir, 0
+tokheim.com, 0
+tokiohotel-fanclub.de, 0
+toko.edu.tw, 0
+tokotoukan.com, 0
+tokyo-city.ru, 0
+tokyo.jp, 0
+tokyonothot.com, 0
+tokyotower.co.jp, 0
+tolk-a.com, 0
+tol.org, 0
+tomato.it, 0
+tomica.ru, 0
+tomintech.ru, 0
+tomoon.cn, 0
+tom.ru, 0
+tomsarkgh.am, 0
+tomsk.gov.ru, 0
+ton.eu, 0
+tongbu.com, 0
+tongda2000.com, 0
+tonghuacun.com, 0
+tongji.cn, 0
+tongji.edu.cn, 0
+tonusclub.ru, 0
+tonyhead.com, 0
+tonytemplates.com, 0
+toobug.net, 0
+toontownrewritten.com, 0
+toorot.com, 0
+tootoo.cn, 0
+top1game.com, 0
+top54.city, 0
+top55.info, 0
+top-channel.tv, 0
+topchrono.biz, 0
+topease.net, 0
+topfiles.ws, 0
+tophouse.ru, 0
+topide.com, 0
+top-inspector.ru, 0
+topkeren.com, 0
+toplist.cz, 0
+toplist.sk, 0
+topmedia.uz, 0
+topmovies31.xyz, 0
+topschool.com, 0
+top-shop.ru, 0
+top.st, 0
+top-technologies.ru, 0
+topthink.com, 0
+topwatch.ru, 0
+topzone.pw, 0
+torah-box.com, 0
+torchystacos.com, 0
+toread.com.cn, 0
+torgpit.ru, 0
+torhub.net, 0
+torquato.de, 0
+torrentbit.net, 0
+torrento.org, 0
+torrentsafe.com, 0
+torrentsgame.net, 0
+torrent-tv.in.ua, 0
+torshovsport.no, 0
+torun.pl, 0
+tosunkaya.com, 0
+totalk12.com, 0
+totaltele.com, 0
+toteme.com, 0
+totheglory.im, 0
+totogaming.am, 0
+touch-device.ru, 0
+touhou-online.net, 0
+touki.ru, 0
+tour-box.ru, 0
+touricoholidays.com, 0
+tourismthailand.org, 0
+tourister.ru, 0
+tourolib.org, 0
+toutapprendre.com, 0
+toutemonannee.com, 0
+toutrix.com, 0
+touzi.com, 0
+tovid.io, 0
+towerhamlets.sch.uk, 0
+toyota.si, 0
+toyshop.cz, 0
+toysperiod.com, 0
+tpay.me, 0
+tpg.ua, 0
+tplaboratorioquimico.com, 0
+tplink.com, 0
+tp-link.com.cn, 0
+tpprf.ru, 0
+tproger.ru, 0
+tpsgv.be, 0
+tpu.ru, 0
+tq.cn, 0
+trabzonspor.org.tr, 0
+trackglobe.com, 0
+trackingmore.com, 0
+trackmanic.com, 0
+trackntrade.com, 0
+trackofthewolf.com, 0
+trackpadmagic.com, 0
+trackvia.com, 0
+tractorpoint.com, 0
+tracuuhoso.com, 0
+trade-groups.ru, 0
+trademachines.com, 0
+trademachines.de, 0
+trademachines.es, 0
+trademe.co.nz, 0
+traderacademy.ru, 0
+traderguide.in, 0
+tradesmax.com, 0
+tradesystemjp.com, 0
+traditio.wiki, 0
+tradzone.net, 0
+trafficrouter.io, 0
+traffic.ru, 0
+trafficstore.com, 0
+traficantes.net, 0
+trafi.com, 0
+trailerloop.de, 0
+trainpix.org, 0
+tramitesadistancia.gob.ar, 0
+trandent.com, 0
+transantiago.cl, 0
+transelectrica.ro, 0
+transformaniatime.com, 0
+transformify.org, 0
+transgd.com.cn, 0
+transindex.ro, 0
+translatesong.com, 0
+transmissionbt.com, 0
+transparencytoolkit.org, 0
+transportes.gov.br, 0
+transposh.org, 0
+transvilles.com, 0
+trantect.com, 0
+travelata.ru, 0
+travelbook.de, 0
+travelclub.es, 0
+travelcodex.com, 0
+travelsim.com, 0
+travelsim.ua, 0
+traystatus.com, 0
+trc.com, 0
+tre-al.jus.br, 0
+treasury.govt.nz, 0
+treatstock.com, 0
+trecnutrition.com, 0
+trecone.com, 0
+treds.co.uk, 0
+trendmagazin.ch, 0
+trendsideas.com, 0
+trenino-rosso-bernina.it, 0
+treolan.ru, 0
+tresorit.com, 0
+tretyakovgallery.ru, 0
+trexle.com, 0
+trialssherpabot.net, 0
+trian.net, 0
+trianz.com, 0
+triblio.com, 0
+tribuna.com, 0
+trifork.com, 0
+trinitigame.com, 0
+trinitydesktop.org, 0
+trinity-parts.ru, 0
+trioo.com, 0
+tripinview.com, 0
+tripplus.cc, 0
+tripsecrets.ru, 0
+tripsta.com, 0
+tripsta.net, 0
+trishara.com, 0
+tritiumnet.org, 0
+triumf.ca, 0
+triya.ru, 0
+tri-z.ru, 0
+trkraduga.ru, 0
+troi.de, 0
+trojmiasto.pl, 0
+trollhattan.se, 0
+trovamoda.com, 0
+trovoacademy.com, 0
+trt16.jus.br, 0
+trt22.jus.br, 0
+trt23.jus.br, 0
+trt24.jus.br, 0
+trtworld.com, 0
+truba.com, 0
+trucksale.ru, 0
+trucnet.com, 0
+trud.bg, 0
+trueconf.com, 0
+truefitness.com, 0
+true.io, 0
+truelaunchbar.com, 0
+truffls.de, 0
+trusek.com, 0
+trus-tech.com, 0
+trust-holod.ru, 0
+trustie.net, 0
+trustpay.eu, 0
+trustutn.org, 0
+tryndex.kz, 0
+trystack.cn, 0
+trytek.ru, 0
+ts3.cloud, 0
+tsagi.ru, 0
+tsargrad.tv, 0
+tsb.kz, 0
+tsci.com.cn, 0
+ts-coach.com, 0
+tseaudio.com, 0
+tse.moe, 0
+tsemporium.com, 0
+tsf.org.tr, 0
+tsign.cn, 0
+tsinetwork.ca, 0
+tsinghua.edu.cn, 0
+ts.kg, 0
+tsk-praha.cz, 0
+tsn.at, 0
+tsn.ua, 0
+tspu.ru, 0
+tssgroup.sk, 0
+tstn.ru, 0
+tsu.ac.th, 0
+tsu.edu, 0
+ttdoc.cn, 0
+ttdyy.tv, 0
+tthd.org, 0
+ttkd.cn, 0
+ttkdex.com, 0
+ttlsa.com, 0
+ttl.tj, 0
+tts.lt, 0
+ttwanda.com, 0
+ttyplus.com, 0
+ttz.com, 0
+ttzx.tv, 0
+tuan800.com, 0
+tuanche.com, 0
+tuanimg.com, 0
+tuars.com, 0
+tubeadvertising.eu, 0
+tubemate-download.com, 0
+tubeshopitalia.it, 0
+tuchuang.org, 0
+tucson-club.ru, 0
+tudelft.nl, 0
+tudip.com, 0
+tudor.lu, 0
+tudou.com, 0
+tuggle.co, 0
+tugraz.at, 0
+tuhocmang.com, 0
+tuigirl.com, 0
+tuit.uz, 0
+tu.koszalin.pl, 0
+tularegion.org, 0
+tulipsport.com, 0
+tuliu.com, 0
+tulotero.es, 0
+tuluoluo.com, 0
+tumar.fm, 0
+tumba.ch, 0
+tumix.ru, 0
+tunayachting.com.tr, 0
+tuneeca.com, 0
+tunestotube.com, 0
+tungee.com, 0
+tuningblog.eu, 0
+tunisietelecom.tn, 0
+tuntron.com, 0
+tuputech.com, 0
+turboconsult.cz, 0
+turbojetbooking.com, 0
+turbo-tec.eu, 0
+turchese.it, 0
+turiba.lv, 0
+turkegitimsen.org.tr, 0
+turkiyeburslari.gov.tr, 0
+turkiye.gov.tr, 0
+turku.center, 0
+turris.cz, 0
+tursvodka.ru, 0
+turtleacademy.com, 0
+tusdk.com, 0
+tushev.org, 0
+tus.si, 0
+tusur.ru, 0
+tutanota.com, 0
+tutanota.de, 0
+tutor.cz, 0
+tuttocollezioni.com, 0
+tuttoformazione.com, 0
+tutuapp.com, 0
+tutuapp.vip, 0
+tu-varna.bg, 0
+tuv.com, 0
+tuwlab.com, 0
+tuxedocomputers.com, 0
+tv189.com, 0
+tv5.zp.ua, 0
+tvalacarta.info, 0
+tvcollect.me, 0
+tvcom.cz, 0
+tvdom.tv, 0
+tvfeed.in, 0
+tvfinternational.com, 0
+tv-impulse.ru, 0
+tvk6.ru, 0
+tv-nasha.ru, 0
+tvoe.ru, 0
+tvoi-instrument.com, 0
+tvoysad.ru, 0
+tvpublica.com.ar, 0
+tvsale.ru, 0
+tvservice.org, 0
+tvtune.net, 0
+tw1.ru, 0
+twbbs.org, 0
+twc.edu.hk, 0
+tweakboxapp.com, 0
+tweepsmap.com, 0
+twgg.org, 0
+twgogo.org, 0
+twickets.co.uk, 0
+twicopy.org, 0
+twistedmatrix.com, 0
+twitteroauth.com, 0
+twomini.com, 0
+twotiger.com, 0
+twrx.ru, 0
+twt.de, 0
+twzoa.info, 0
+txhack.cn, 0
+txiaohe.cn, 0
+txslicai.com, 0
+txslicai.com.cn, 0
+txvpn.top, 0
+txvpn.wang, 0
+tyc.edu.tw, 0
+tychy.pl, 0
+tynsoe.org, 0
+tyntec.com, 0
+typcn.com, 0
+typecho.me, 0
+typecodes.com, 0
+typhon.net, 0
+typo3.org, 0
+typografos.gr, 0
+typtest.ru, 0
+tyresystem.de, 0
+tyr.gift, 0
+tysa.ru, 0
+tyumedia.ru, 0
+tzbao.com, 0
+tzit.cn, 0
+tzqby.xyz, 0
+tzrl.com, 0
+tzyee.com, 0
+u9yy.com, 0
+uabc.mx, 0
+uade.edu.ar, 0
+uaes.com, 0
+ua.fm, 0
+ua.gov.tr, 0
+uakino.net, 0
+ualinux.com, 0
+uama.com.cn, 0
+uamaster.com, 0
+uapa.ru, 0
+uapeer.eu, 0
+uatoday.tv, 0
+ubejournal.biz, 0
+uberchord.com, 0
+uberfacil.com, 0
+uberspace.de, 0
+ubiobio.cl, 0
+uboachan.net, 0
+ub.ua, 0
+ubuntu-gr.org, 0
+ubuntukylin.com, 0
+uc.ac.id, 0
+ucasal.edu.ar, 0
+ucbuyco.com, 0
+uc.cl, 0
+ucdok.com, 0
+uc.edu, 0
+uce.edu.ec, 0
+uchat.co.kr, 0
+uchile.cl, 0
+uchil.net, 0
+uchiuroki.ru, 0
+uci.cu, 0
+uciran.ir, 0
+uclv.cu, 0
+uclv.edu.cu, 0
+ucoin.net, 0
+ucol.mx, 0
+ucoz.com, 0
+ucoz.net, 0
+ucoz.ru, 0
+ucpaas.com, 0
+uc.pt, 0
+ucptt.com, 0
+ucw.cz, 0
+uczc.cn, 0
+udg.edu, 0
+udg.mx, 0
+udinra.com, 0
+udi.pl, 0
+udmprof.ru, 0
+u-doktora.ru, 0
+uds18.ru, 0
+uedsc.com, 0
+uef.edu.vn, 0
+ueh.edu.vn, 0
+uel.br, 0
+uelzener.de, 0
+uem.mz, 0
+ueq.com, 0
+uer.ca, 0
+uerj.br, 0
+uesocc.edu.sv, 0
+uestc.edu.cn, 0
+ueuo.com, 0
+ufa1.ru, 0
+ufa.ie, 0
+ufanet.ru, 0
+ufcfan.org, 0
+ufg.br, 0
+ufh.com.cn, 0
+ufibox.com, 0
+ufight.gr, 0
+ufmg.br, 0
+ufms.br, 0
+ufmt.br, 0
+ufoots.com, 0
+ufosend.com, 0
+ufpa.br, 0
+ufpb.br, 0
+ufrr.br, 0
+ufs.br, 0
+ufscar.br, 0
+ufs-online.ru, 0
+uft.edu.br, 0
+ufu.br, 0
+ufvjm.edu.br, 0
+ugg2nd.de, 0
+ugirls.com, 0
+ugm.ac.id, 0
+ugmk-telecom.ru, 0
+ugranow.ru, 0
+ugx-mods.com, 0
+uhc.gg, 0
+uhdog.com, 0
+uhrforum.de, 0
+ui001.com, 0
+uia.org, 0
+uilim.ru, 0
+uji.es, 0
+ujipin.com, 0
+ujs.edu.cn, 0
+uk2group.com, 0
+ukbiz.top, 0
+ukc.gov.ua, 0
+ukdefencejournal.org.uk, 0
+ukim.edu.mk, 0
+ukim.mk, 0
+ukipme.com, 0
+u-kor.cn, 0
+ukravto.ua, 0
+ukrdc.net, 0
+ukrdomen.com, 0
+ukrmap.biz, 0
+ukrmedia.center, 0
+ukroboronprom.com.ua, 0
+ukrstat.gov.ua, 0
+ukrtelecom.ua, 0
+uk.to, 0
+ulanovka.ru, 0
+ulbra.br, 0
+ulivingstyle.com, 0
+ulpgc.es, 0
+ultiboss.jp, 0
+ultimate-community.de, 0
+ultimedecathlon.com, 0
+ultradox.com, 0
+ulugov.uz, 0
+ulyaoth.net, 0
+umail.uz, 0
+umanis.com, 0
+umantis.com, 0
+umbro.com.br, 0
+umc.br, 0
+umich.mx, 0
+uminho.pt, 0
+umkbw.de, 0
+umnieroditeli.ru, 0
+umpay.com, 0
+umukunzi.rw, 0
+umu.se, 0
+umweltinstitut.org, 0
+um.wroc.pl, 0
+unacar.mx, 0
+unachi.ac.pa, 0
+unam.edu.ar, 0
+unam.mx, 0
+unand.ac.id, 0
+unas.bg, 0
+unas.eu, 0
+unas.hu, 0
+unasus.gov.br, 0
+unblockall.com, 0
+unblockbook.biz, 0
+unblockcn.com, 0
+unca.edu, 0
+unctv.org, 0
+undelete-file.ru, 0
+undiksha.ac.id, 0
+undip.ac.id, 0
+undo.it, 0
+unecon.ru, 0
+uned.es, 0
+unesp.br, 0
+unet.by, 0
+unet.cz, 0
+unet.edu.ve, 0
+unexplainablestore.com, 0
+ung.si, 0
+uni-altai.ru, 0
+unian.info, 0
+unian.net, 0
+unian.ua, 0
+uniara.com.br, 0
+uni-augsburg.de, 0
+uniba.it, 0
+uniba.sk, 0
+unibratec.edu.br, 0
+unic.ac.cy, 0
+unicamp.br, 0
+unicard.ge, 0
+unic.edu.ru, 0
+unicef-irc.org, 0
+unicen.edu.ar, 0
+uniconf.ru, 0
+unideb.hu, 0
+unident.se, 0
+uni.edu.ni, 0
+unifemm.edu.br, 0
+unifenas.br, 0
+unifesp.br, 0
+uniforminsignia.org, 0
+uni-frankfurt.de, 0
+uni-freiburg.de, 0
+unigroup.com.cn, 0
+uni-heidelberg.de, 0
+unihost.com, 0
+uni-kassel.de, 0
+unila.edu.mx, 0
+unilever.com, 0
+unilever.com.cn, 0
+uni-lj.si, 0
+unimagdalena.edu.co, 0
+uni-mainz.de, 0
+unimal.ac.id, 0
+uni-mb.si, 0
+unimedmaringa.com.br, 0
+unimednatal.com.br, 0
+unimedribeirao.net, 0
+unimedrio.com.br, 0
+unimontes.br, 0
+uni-mysore.ac.in, 0
+uni-net.com.tw, 0
+unionesarda.it, 0
+unionpay.com, 0
+unionpayintl.com, 0
+unipdu.ac.id, 0
+unipus.cn, 0
+uniqa.ro, 0
+unisi.it, 0
+uni-sofia.bg, 0
+unisonserver.com, 0
+unistroyrf.ru, 0
+unitbv.ro, 0
+unitconverterpro.com, 0
+unitech-mo.ru, 0
+unitedbank.cn, 0
+united-host.de, 0
+unitequipment.com, 0
+unitins.br, 0
+unitraklub.pl, 0
+unium.ru, 0
+univadis.de, 0
+univap.br, 0
+universal-job.ch, 0
+universal.se, 0
+universiada.eu, 0
+universitego.com, 0
+university.kg, 0
+universityofsantamonica.edu, 0
+universtudio.ru, 0
+univertv.org, 0
+uniview.com, 0
+univille.edu.br, 0
+uni-weimar.de, 0
+unix4lyfe.org, 0
+unixstorm.org, 0
+uniyar.ac.ru, 0
+unlimitedworld.de, 0
+unlp.edu.ar, 0
+unmo.ba, 0
+unode50.com, 0
+unoentrerios.com.ar, 0
+unpa.me, 0
+unq.edu.ar, 0
+unr.edu.ar, 0
+unrulydude.com, 0
+unsa.org, 0
+untan.ac.id, 0
+unternehmertum.de, 0
+untis.at, 0
+unybook.com, 0
+unyoo.com, 0
+unyp.cz, 0
+uoc.gr, 0
+uooc.online, 0
+uop.edu.jo, 0
+uoradea.ro, 0
+up3d.com, 0
+upaep.mx, 0
+upagge.com, 0
+upaiyun.com, 0
+upb.edu.co, 0
+upc.edu.cn, 0
+upchina.com, 0
+upclinic.ru, 0
+upclve.com, 0
+upcomingcons.com, 0
+updressed.com, 0
+upendo.tv, 0
+upenny.cn, 0
+upessencia.com.br, 0
+upg-ploiesti.ro, 0
+upit.ro, 0
+uplab.ru, 0
+upla.cl, 0
+upl.uz, 0
+upm.my, 0
+upp.edu.mx, 0
+uprav.ru, 0
+uprm.edu, 0
+upromania.ro, 0
+upr.si, 0
+upservers.net, 0
+upsrv.ru, 0
+upward.org, 0
+upxin.net, 0
+uqer.io, 0
+uralairlines.ru, 0
+ural.net, 0
+uralplit.ru, 0
+uralpolit.ru, 0
+uran.ua, 0
+urban3p.ru, 0
+urbanterror.info, 0
+urbaonline.com, 0
+urbistat.it, 0
+urc.ac.ru, 0
+ur.de, 0
+ureport.in, 0
+urfu.ru, 0
+urgent-curier.ro, 0
+url.ph, 0
+url.tw, 0
+urmia.ir, 0
+urokidoma.org, 0
+ursprung.at, 0
+urssaf.fr, 0
+urss.ru, 0
+urwork.cn, 0
+usabilitytools.com, 0
+usa.cc, 0
+usach.cl, 0
+usaedu.net, 0
+usaip.eu, 0
+usc.edu, 0
+usc.edu.cn, 0
+useed.fr, 0
+usefulblogging.com, 0
+useley.com, 0
+usembassy.gov, 0
+usens.com, 0
+userbase.be, 0
+userful.com, 0
+usermd.net, 0
+users.pub, 0
+useso.com, 0
+usfleettracking.com, 0
+us.jobs, 0
+uslugi.mosreg.ru, 0
+uspard.com, 0
+usp.br, 0
+usports.ru, 0
+ustalk.com, 0
+ustc.edu.cn, 0
+ustclug.org, 0
+ustcsoft.com, 0
+us.to, 0
+u-strasbg.fr, 0
+ustrotting.com, 0
+usu.edu, 0
+usuhs.edu, 0
+usurt.ru, 0
+usx.edu.cn, 0
+utags.edu.mx, 0
+utaipei.edu.tw, 0
+uta-net.com, 0
+utazom.com, 0
+utazzitthon.hu, 0
+utb.ru, 0
+utbs.ws, 0
+utgjiu.ro, 0
+uticanational.com, 0
+utmn.ru, 0
+utn.edu.ar, 0
+utorrent.info, 0
+utorrent-russian.com, 0
+utouu.com, 0
+utp.br, 0
+utp.edu.br, 0
+utsource.net, 0
+utwente.nl, 0
+uulian.com, 0
+uuoobe.kr, 0
+uurun.com, 0
+uuu.com.tw, 0
+uvanet.br, 0
+uv.cl, 0
+uvm.cl, 0
+uwdress.com, 0
+uwebdesign.ru, 0
+uwec.edu, 0
+uwewe.com, 0
+uwm.edu.pl, 0
+uwow.biz, 0
+uwowhead.ru, 0
+uxiaor.com, 0
+uxin.com, 0
+uxinuxin.com, 0
+uxuejiaoyu.cc, 0
+uxuejiaoyu.com, 0
+uybor.uz, 0
+uyun.cn, 0
+uzasne-darky.cz, 0
+uzbekenergo.uz, 0
+uzcard.uz, 0
+uzer.me, 0
+uzex.uz, 0
+uzfor.net, 0
+uzh.ch, 0
+uzinfocom.uz, 0
+uznature.uz, 0
+uztelecom.uz, 0
+uztor.net, 0
+v1.cn, 0
+v1game.cn, 0
+v1.ru, 0
+v1.spb.ru, 0
+v2v.net, 0
+v5cg.com, 0
+v5kf.com, 0
+vaecn.com, 0
+vagas.pro, 0
+vahdeals.com, 0
+vainahtelecom.ru, 0
+valahia.ro, 0
+vala-network.eu, 0
+valetudo.ru, 0
+vallexm.ru, 0
+valsun.cn, 0
+valuehost.ru, 0
+vam.ac.uk, 0
+vanet.eu.com, 0
+vanfun.com, 0
+vansfans.cn, 0
+vapez.ro, 0
+vapteke.ru, 0
+vardex.ru, 0
+variable.pp.ua, 0
+variety-store.ru, 0
+variflight.com, 0
+varton.ru, 0
+varus.ua, 0
+vasco.com, 0
+vasco.eu, 0
+vashgorod.ru, 0
+vatrus.info, 0
+vatti.com.cn, 0
+vavato.com, 0
+vavruska.info, 0
+v-avto.ru, 0
+vayaentradas.com, 0
+vaz.ru, 0
+vbg.de, 0
+vbill.cn, 0
+vbordele.org, 0
+vbs-hobby.fr, 0
+vbuddisme.ru, 0
+vbz.hr, 0
+vc4a.com, 0
+vc-enable.co.uk, 0
+vcfboard.com, 0
+vclhk.com, 0
+vc.ru, 0
+vctms.co.uk, 0
+vdongchina.com, 0
+vdv-kavkaz.ru, 0
+vedanta.org, 0
+veeam.com, 0
+veekn.com, 0
+veeseo.com, 0
+veeshop.ro, 0
+veestro.com, 0
+veganisme.org, 0
+vegeweb.org, 0
+vehicle-rent.com, 0
+vejska.cz, 0
+veka.ru, 0
+vekrosta.ru, 0
+velex.ir, 0
+velosite.ru, 0
+veloxnet.hu, 0
+venco.com.pl, 0
+vendev.info, 0
+vendor.kz, 0
+venetolavoro.it, 0
+venez.fr, 0
+venganzasdelpasado.com.ar, 0
+venompvp.org, 0
+vent-al.ru, 0
+vente-privee.com, 0
+vento.ru, 0
+venturesafrica.com, 0
+verbinet.com, 0
+verbraucherschutz.de, 0
+verbraucherzentrale.it, 0
+verespg.hu, 0
+vergleichen-und-sparen.de, 0
+vericant.com, 0
+verifiedinvesting.com, 0
+verifiedvolunteers.com, 0
+veripark.com, 0
+versand-status.de, 0
+version6.ru, 0
+verybank.ru, 0
+verycloud.cn, 0
+verygames.net, 0
+veschichka.com, 0
+vestacp.com, 0
+vesti.kz, 0
+vestiprim.ru, 0
+vestum.ru, 0
+vexer.ru, 0
+veyseloglu.az, 0
+vfavk.net, 0
+vfe.cc, 0
+vfl.ru, 0
+v-front.de, 0
+vgg.ru, 0
+vgn.at, 0
+vhall.com, 0
+vhod.cc, 0
+vhostgo.com, 0
+vhost.wf, 0
+viacep.com.br, 0
+via.de, 0
+viadurini.it, 0
+viaflats.com, 0
+viajas.com, 0
+viaprinto.de, 0
+vibease.com, 0
+vibus.de, 0
+vic.edu.au, 0
+vic.gov.au, 0
+vicp.cc, 0
+vicp.io, 0
+vicp.net, 0
+victorz.ru, 0
+vidanet.hu, 0
+vidapositiva.com, 0
+vide-greniers.org, 0
+videoboom.cc, 0
+videochaty.ru, 0
+videociety.de, 0
+videoforme.ru, 0
+videogamesawesome.com, 0
+videoigr.net, 0
+videojatekbolt.hu, 0
+videojj.com, 0
+videolist.am, 0
+video-nvidia.com, 0
+videoplusfrance.com, 0
+videoregforum.ru, 0
+videoseed.ru, 0
+videosmile.ru, 0
+videostir.com, 0
+videvo.net, 0
+vidido.ua, 0
+vidmatedownloadapp.com, 0
+vidonme.cn, 0
+vidown.cn, 0
+vidproxy.com, 0
+vidri.com.sv, 0
+vid.ru, 0
+viemar.com.br, 0
+vietget.net, 0
+vietmap.vn, 0
+vietpn.com, 0
+viewdns.net, 0
+viewlayer.cn, 0
+viewnetcam.com, 0
+vifnet.pl, 0
+vigodnee.ru, 0
+viis.lv, 0
+vikingco.com, 0
+vikingcruises.com, 0
+vikingrivercruises.com, 0
+vilavi.com, 0
+vilaviniteca.es, 0
+villacarte.com, 0
+villamariavivo.com, 0
+ville-courbevoie.fr, 0
+ville-gennevilliers.fr, 0
+vilniausenergija.lt, 0
+vilynx.com, 0
+vimcar.com, 0
+vimcar.de, 0
+vimentis.ch, 0
+vimp.com, 0
+vinamsolutions.com, 0
+vinastar.net, 0
+vincross.com, 0
+viniti.ru, 0
+vin.li, 0
+vipautoliker.com, 0
+vipbaiduyun.com, 0
+vipc.cn, 0
+v-ipc.ru, 0
+vipedp2.com, 0
+vipfreepremium.com, 0
+vipgaming.ru, 0
+vipip.ru, 0
+vip-member.net, 0
+vipmro.net, 0
+vipreading.com, 0
+vipshop.com, 0
+vipsmt.com, 0
+vipspravka.org, 0
+vipvpn.racing, 0
+vip-weapon.ru, 0
+vip-wifi.com, 0
+vipwifi.com, 0
+vira20.ir, 0
+virag.si, 0
+viral-alert.com, 0
+viralsection.com, 0
+virink.com, 0
+virnet.co.za, 0
+virten.net, 0
+virt-manager.org, 0
+virt-mir.ru, 0
+virtual-college.co.uk, 0
+virtuallyboring.com, 0
+virtualsoccer.ru, 0
+virtuemart.net, 0
+virtuosgames.com, 0
+virtuozzo.com, 0
+virus-removal-guide.com, 0
+virus-removal-guide.net, 0
+visaszales.lv, 0
+visicom.com, 0
+vision.com.tw, 0
+visitantalya.com, 0
+visitporno.net, 0
+vismedia.ru, 0
+vistula.edu.pl, 0
+visual3d.cn, 0
+visualead.com, 0
+visualwatermark.com, 0
+vitacom.ro, 0
+vitalia.cz, 0
+vitalitygames.com, 0
+vitamax.ru, 0
+vitaminking.com.au, 0
+vitek.ru, 0
+vitnik.com, 0
+vitreum.lv, 0
+viva.com.do, 0
+vivasexe.com, 0
+vivavivu.com, 0
+vivaxis.com, 0
+vivendi.com, 0
+viventor.com, 0
+vivo.xyz, 0
+vivt.ru, 0
+vizio.com, 0
+vizzlo.com, 0
+vjiangyin.net, 0
+vkernel.ro, 0
+v-key.com, 0
+vkfake.ru, 0
+vki.at, 0
+vkjust.com, 0
+vko.cn, 0
+vkonline.ru, 0
+vkreg.ru, 0
+vladislav.ua, 0
+vladis.ru, 0
+vladmama.ru, 0
+vlc.de, 0
+vlc-forum.de, 0
+vlion.cn, 0
+vludus.com, 0
+vluki.ru, 0
+vmcsubastas.com, 0
+vmmo.ru, 0
+vmoe.info, 0
+vmou.ac.in, 0
+vmovier.cc, 0
+vnc.biz, 0
+vn.cz, 0
+vnebo.mobi, 0
+vnet.cn, 0
+vnmu.edu.ua, 0
+vnutri.org, 0
+vobile.cn, 0
+voc.com.cn, 0
+vocier.com, 0
+vodafone.it, 0
+vodjk.com, 0
+vodokanal.kiev.ua, 0
+voffka.com, 0
+vogu35.ru, 0
+vogue.ru, 0
+voicecloud.cn, 0
+voiceofgreaterassam.com, 0
+voice-server.ru, 0
+voipgateapi.com, 0
+voipgate.com, 0
+volgadmin.ru, 0
+volga-dnepr.com, 0
+volganet.ru, 0
+volgaspot.ru, 0
+volksbuehne-berlin.de, 0
+volksschauspiele.de, 0
+volkswagen.de, 0
+volkszaehler.org, 0
+volleyball-verband.de, 0
+volnistye.ru, 0
+volnorez.com, 0
+volosfull.ru, 0
+voltmarket.ru, 0
+voltra.by, 0
+vonvon.me, 0
+vooc.net, 0
+voodoo.com, 0
+voodoo.community, 0
+voprosoff.net, 0
+voriginale.tv, 0
+vorlagen.de, 0
+vorwaerts.de, 0
+vorwerk.at, 0
+vorwerk.com, 0
+vorwerk.co.uk, 0
+vorwerk.cz, 0
+vorwerk.de, 0
+vorwerk.es, 0
+vorwerk.fr, 0
+vorwerk.it, 0
+vostok.ru, 0
+votobo.com, 0
+votonia.ru, 0
+votrube.ru, 0
+voubs.bg, 0
+voxbone.com, 0
+voximplant.com, 0
+voxygen.fr, 0
+voyhoy.com, 0
+voz48.xyz, 0
+vp.gov.lv, 0
+vpndaquan.net.cn, 0
+vpngatecn.com, 0
+vpnhot.com, 0
+vpnmaster.cn, 0
+vpnme.me, 0
+vpnxx.net, 0
+vpo.ca, 0
+vpphoangha.vn, 0
+vprka.com, 0
+vps-10.com, 0
+vpsgroups.com, 0
+vpsi.cloud, 0
+vpsps.com, 0
+vpsville.ru, 0
+vqs.com, 0
+vrach42.ru, 0
+vrame.org, 0
+vrheads.com, 0
+vrn.ru, 0
+vrsa.lt, 0
+v-running.com, 0
+vsactivity.com, 0
+vsadu.ru, 0
+vsathletics.com, 0
+vsbt174.ru, 0
+vsdaria.com, 0
+vse.cz, 0
+vse.fm, 0
+vsehristiane.com, 0
+vsei.ua, 0
+vsekroham.ru, 0
+vseloterei.com, 0
+vsemayki.com, 0
+vsem.cz, 0
+vsemetri.com, 0
+vsepro1s.ru, 0
+vserpg.ru, 0
+vserver.de, 0
+vsesorta.ru, 0
+vsestudent.cz, 0
+vshabakeh.com, 0
+vsibiri.info, 0
+vsim.lt, 0
+vslg.cz, 0
+vslu.ru, 0
+vsopen.ru, 0
+vso-software.fr, 0
+vspp.cz, 0
+vsu.by, 0
+vsu.ru, 0
+vtambove.ru, 0
+vtb.az, 0
+vtb-bank.by, 0
+vtb-bank.kz, 0
+vtbnpf.ru, 0
+vtech.com, 0
+vtechda.com, 0
+vt.edu, 0
+vten.ru, 0
+vtkbank.ru, 0
+vtrhome.net, 0
+vtrois.com, 0
+vtrspeed.com, 0
+vtrspeed.net, 0
+vtrus.net, 0
+vttl.be, 0
+vtt.ru, 0
+vtverdohleb.org.ua, 0
+vucdjursland.dk, 0
+vucke.sk, 0
+vuze.camera, 0
+vv881.com, 0
+vvic.com, 0
+vvo.aero, 0
+vvoso.com, 0
+vvsu.ru, 0
+vvwall.com, 0
+vw-bus.ru, 0
+vwr.com, 0
+vxianchang.cn, 0
+vydy.net, 0
+vyos.io, 0
+vyos.net, 0
+vzlomcheats.com, 0
+vzlomcheatshack.com, 0
+vzlom-igr.com, 0
+w1.fi, 0
+w3cboy.com, 0
+w3template.ir, 0
+w69b.com, 0
+wacai.com, 0
+wacaiyun.com, 0
+wacom.pl, 0
+wadmz.com, 0
+wa.edu.au, 0
+wagner-group.com, 0
+wahaha.com.cn, 0
+waikato.ac.nz, 0
+waiqin365.com, 0
+waitalone.cn, 0
+waitsun.com, 0
+waixingrenlc.com, 0
+wakeboardingmag.com, 0
+wakku.to, 0
+walatao.com, 0
+walibi.nl, 0
+walkclass.com, 0
+wallbox.ru, 0
+wall.cz, 0
+wallegro.ru, 0
+wallpai.com, 0
+wallpaperfusion.com, 0
+wallpapers.pub, 0
+wally.me, 0
+wan5d.com, 0
+wanadev.fr, 0
+wanchongchong.com, 0
+wancom.net.pk, 0
+wanderland.ch, 0
+wandoujia.com, 0
+wanfangdata.com.cn, 0
+wang1314.com, 0
+wangfujing.com, 0
+wangfz.com, 0
+wang-guanjia.com, 0
+wanghailin.cn, 0
+wanghualang.com, 0
+wangjubao.com, 0
+wangjunfeng.com, 0
+wangye.org, 0
+wanhu.com.cn, 0
+wankr.com.cn, 0
+wanmei.com, 0
+wanxiaohong.cn, 0
+wanzi.tv, 0
+waqu.com, 0
+warabi.or.jp, 0
+warcis.com, 0
+wardahshop.com, 0
+warez-bb.org, 0
+warlegend.net, 0
+warmen.cc, 0
+warspear-online.com, 0
+wartapost.com, 0
+warwick.ac.uk, 0
+wasai.org, 0
+washabich.de, 0
+wa-sta.net, 0
+wasu.com, 0
+watches.ru, 0
+watchhyper.com, 0
+watchrecon.com, 0
+waterskimag.com, 0
+watsons.com.tw, 0
+watsons.ua, 0
+watsupafrica.com, 0
+wave.io, 0
+waww.ir, 0
+waylens.com, 0
+waysofhistory.com, 0
+wazizu.com, 0
+wb21.com, 0
+wb-community.com, 0
+wb-fernstudium.de, 0
+wbiao.cn, 0
+wciu.com, 0
+wdj168.com, 0
+wdw88.com, 0
+wdwd.com, 0
+we7.cc, 0
+wealthnavi.com, 0
+wearemarketing.com, 0
+weaver.com.cn, 0
+web4008.com, 0
+web4.hu, 0
+webads.eu, 0
+webalfa.net, 0
+web-alpha.com, 0
+webanetlabs.net, 0
+webanketa.com, 0
+webartex.ru, 0
+webassign.com, 0
+webassign.net, 0
+webbankir.com, 0
+webb-site.com, 0
+webcamfuck.me, 0
+webceo.com, 0
+webdavsystem.com, 0
+webdesign.org, 0
+webd.pl, 0
+webdux.com, 0
+webeden.co.uk, 0
+webei.cn, 0
+web-entity.com, 0
+webernetz.net, 0
+web-experiment.info, 0
+webfoss.com, 0
+webfungame.com, 0
+webhop.me, 0
+webhop.net, 0
+webhostbox.net, 0
+webhostingdiscussion.net, 0
+webid-gateway.de, 0
+webid-solutions.de, 0
+webim.ru, 0
+webinar.fm, 0
+webin.info, 0
+weblap-keszites.co.hu, 0
+webmaster.kitchen, 0
+webmaster-ucoz.ru, 0
+weborama.com, 0
+weborama.fr, 0
+webpass.net, 0
+webpixeltechnologies.com, 0
+webplatform.org, 0
+webpro.co.jp, 0
+webptt.com, 0
+webraketa.com, 0
+web-republic.de, 0
+we.bs, 0
+webscore.ru, 0
+webseiten.cc, 0
+webseo.com, 0
+websequencediagrams.com, 0
+web-service4u.de, 0
+websistent.com, 0
+website.tk, 0
+websmsapp.com, 0
+webspacecontrol.com, 0
+webstarterz.com, 0
+webstrane.info, 0
+webstream.eu, 0
+webtatic.com, 0
+webtechub.com, 0
+webtemp.no, 0
+webterren.com, 0
+web-tinker.com, 0
+webtm.ru, 0
+webtransfer.com, 0
+webtre.com, 0
+webtrn.cn, 0
+webtropia.com, 0
+webuntis.com, 0
+weclassroom.com, 0
+weclick.ir, 0
+weco.net, 0
+weddywood.ru, 0
+wedgewoodbanquet.com, 0
+wednet.edu, 0
+wedos.com, 0
+wedos.net, 0
+weeaboo.com, 0
+weeazy.com, 0
+weekdone.com, 0
+weeker.jp, 0
+weflow.io, 0
+weibo.cn, 0
+weiboyi.com, 0
+weichai.com, 0
+weicps.cn, 0
+weidian.com, 0
+weiguda.com, 0
+weijuju.com, 0
+weimi.cc, 0
+weiosx.com, 0
+weiphone.com, 0
+weiphone.net, 0
+weismarkets.com, 0
+weitaming.com, 0
+weixinshu.com, 0
+weiyin.cc, 0
+wejherowo.pl, 0
+wek.ru, 0
+welcomechile.com, 0
+welcomeuruguay.com, 0
+welfulloutdoors.com, 0
+welian.com, 0
+welldonesoft.com, 0
+wellgames.com, 0
+wellingtoncdsb.ca, 0
+wellnessfitnessnutritionstore.com, 0
+welovedance.ru, 0
+wendashi.cc, 0
+wenidc.com, 0
+wenjf.com, 0
+wenjuan.com, 0
+wenjuan.net, 0
+wenming.cn, 0
+wenzelnet.de, 0
+wenzhanghui.com, 0
+werkswelt.de, 0
+weru.de, 0
+wesmirch.com, 0
+westcall.net, 0
+westcall.spb.ru, 0
+westend.hu, 0
+westhome.spb.ru, 0
+westland.ru, 0
+westsib.ru, 0
+westtown.edu, 0
+westwin.com, 0
+west.xyz, 0
+wettforum.info, 0
+wetu.com, 0
+weyes.cn, 0
+weyes.com.cn, 0
+wffuture.ru, 0
+wfu.edu, 0
+wg263.com, 0
+wget.ca, 0
+wghostk.com, 0
+wg-volunteers.ru, 0
+wgwinto.com, 0
+wh1.su, 0
+whalevpn.cc, 0
+whaley.cn, 0
+whaller.com, 0
+whatled.com, 0
+whatpulse.org, 0
+whatshelp.io, 0
+whhd.gov.cn, 0
+whir.net, 0
+whiskybase.com, 0
+whitelabelwebserver.com, 0
+whitetown.com, 0
+whmcsadmintheme.com, 0
+whnet.edu.cn, 0
+whois7.ru, 0
+wholikesu.net, 0
+whoneedstv.com, 0
+wh.to, 0
+whu.edu.cn, 0
+whyun.com, 0
+wiaa.com, 0
+wiair.com, 0
+wiconnect.fr, 0
+wicp.net, 0
+wicwuzhen.cn, 0
+wide.ad.jp, 0
+widoobiz.com, 0
+widuu.com, 0
+wienit.at, 0
+wifimapper.com, 0
+wifispc.com, 0
+wig-supplier.com, 0
+wigwam.com, 0
+wiidatabase.de, 0
+wiipu.com, 0
+wikem.org, 0
+wik-end.com, 0
+wiki8.com, 0
+wikiart.org, 0
+wikimart.ru, 0
+wikimonde.com, 0
+wikin.cn, 0
+wikiscan.org, 0
+wikishoper.ru, 0
+wikium.ru, 0
+wildbags.ru, 0
+wilddogapp.com, 0
+wildo.ru, 0
+williamlong.info, 0
+winasdaq.com, 0
+winbo.cn, 0
+winbo.top, 0
+wincatalog.com, 0
+wincomi.com, 0
+windobona.at, 0
+windows10screensavers.net, 0
+windowsazure.cn, 0
+windowsbox.hu, 0
+windowscentral.com, 0
+windowsforum.kr, 0
+windows-phone.su, 0
+windows-security.org, 0
+windows-soft.ru, 0
+windscribe.com, 0
+wineselectors.com.au, 0
+winesou.com, 0
+winestreet.ru, 0
+wingoads.com, 0
+wingroad.ru, 0
+wingsofart.ru, 0
+wingtech.com, 0
+winhelp.us, 0
+winhong.com, 0
+winneryun.com, 0
+winnetnews.com, 0
+winni.in, 0
+winployee.com, 0
+wintalent.cn, 0
+winxuan.com, 0
+winyer.cn, 0
+wiscom.com.cn, 0
+wisconsinhistory.org, 0
+wise2c.com, 0
+wisecrm.com, 0
+wisemedia.cn, 0
+wisenjoy.com, 0
+wishmindr.com, 0
+withmybaby.com, 0
+wittur.com.cn, 0
+wittycircle.com, 0
+witze-charts.de, 0
+wizardfox.net, 0
+wizardofodds.com, 0
+wizardofvegas.com, 0
+wizzley.com, 0
+wjdaily.com, 0
+wkbins.com, 0
+wkinfo.com.cn, 0
+wko.at, 0
+wktk.so, 0
+wkzuche.com, 0
+wlcpu.com, 0
+wlwx.cn, 0
+wmasteru.org, 0
+wmd.ru, 0
+wmrs.ru, 0
+wm.ru, 0
+wmv-dresden.de, 0
+wnmu.edu, 0
+wnp.com.hk, 0
+woax-it.com, 0
+woca.club, 0
+wodzislaw.pl, 0
+wogibtswas.de, 0
+woheni.de, 0
+wolfpaulus.com, 0
+wolf.ua, 0
+wolterskluwer.de, 0
+womanadvice.ru, 0
+woman.ru, 0
+womenonweb.org, 0
+womenshairlossproject.com, 0
+wondershare.cn, 0
+wonsterscript.com, 0
+woodgears.ca, 0
+woodward.edu, 0
+wooplus.com, 0
+wordassociations.net, 0
+work28.com, 0
+workaround.org, 0
+workingmother.com, 0
+worklohas.com, 0
+work-microwave.com, 0
+workout-italia.it, 0
+worksection.com, 0
+work-way.com, 0
+worldcubeassociation.org, 0
+worldoftrucks.ru, 0
+worldserial.info, 0
+worldskills.ru, 0
+worldtravelserver.com, 0
+world-xxx.com, 0
+woshidai.com, 0
+wosign.com, 0
+wo.tc, 0
+wotcase.ru, 0
+wotreplays.ru, 0
+wots.com.ua, 0
+wovn.io, 0
+wowdsgn.com, 0
+wowgirls.com, 0
+wow-impulse.net, 0
+wowtrack.org, 0
+wowtv.sx, 0
+wowworks.ru, 0
+wowzonegc.ir, 0
+woyun.la, 0
+woy-wo.uz, 0
+wpcp.org, 0
+wpdesigner.ir, 0
+wpiao.cn, 0
+wpmayor.com, 0
+wppage.ru, 0
+wpscdn.cn, 0
+wps.cn, 0
+wp-statistics.com, 0
+wpweb.com, 0
+wpweixin.net, 0
+wpzhiku.com, 0
+wpzt.cn, 0
+wrealu24.pl, 0
+wrestling-infos.de, 0
+wroclaw.pl, 0
+wrps.org, 0
+wsdltophp.com, 0
+wsgf.org, 0
+wsgjp.com.cn, 0
+wsgvet.com, 0
+wsisp.net, 0
+wsloan.com, 0
+wsms.ru, 0
+wso.wroc.pl, 0
+wstvb.com, 0
+wszuie.pl, 0
+wtfismyip.com, 0
+wtigga.com, 0
+wtsolutions.cn, 0
+wtu.edu.cn, 0
+wuage.com, 0
+wuestenrot.sk, 0
+wug.cz, 0
+wulian.cc, 0
+wumart.com, 0
+wuminhao.com, 0
+wunderkarten.de, 0
+wunschimmo.de, 0
+wunschkuechen24.de, 0
+wusa5.com, 0
+wust.edu.cn, 0
+wusunyinyue.cn, 0
+wutnews.net, 0
+wuyatv.com, 0
+wuzhicms.com, 0
+wvo-dbg.de, 0
+wware.org, 0
+www.astrakhan.ru, 0
+www.chita.ru, 0
+www.gov.lk, 0
+www.uz, 0
+wxchina.com, 0
+wxdm.net, 0
+wxfenxiao.com, 0
+wxliu.com, 0
+wxrrd.com, 0
+wxwgood.com, 0
+wycliffe.org.au, 0
+wykxsw.com, 0
+wyscout.com, 0
+wzhrss.gov.cn, 0
+x25.pl, 0
+x431.com, 0
+x4jdm.com, 0
+x5aa.com, 0
+x5.ru, 0
+x64dbg.com, 0
+xaau.edu.cn, 0
+xacbank.com, 0
+xaecong.com, 0
+xakfor.net, 0
+xalapa.gob.mx, 0
+xalkiadakis.gr, 0
+xalqbank.az, 0
+xanlosch.de, 0
+xap.com, 0
+xarakiri.ru, 0
+xbls.ninja, 0
+xbmc-kodi.cz, 0
+xbpmo.com, 0
+xbsafe.cn, 0
+xchange.cc, 0
+xcloud.cc, 0
+xcloudgame.com, 0
+xd.com, 0
+xdevs.com, 0
+xdf.cn, 0
+x-diesel.com, 0
+xdjd.cn, 0
+xeenho.com, 0
+xenderdownloadapp.com, 0
+xenderdownloads.com, 0
+xenforo.rocks, 0
+xenics.com, 0
+xenos.org, 0
+xf315.org, 0
+xfce.org, 0
+xfile.ro, 0
+xfplay.com, 0
+xfsub.com, 0
+xfxb.net, 0
+xg1.li, 0
+xgate.com.hk, 0
+xgen.hu, 0
+xgimi.com, 0
+xgm.guru, 0
+xhecom.com, 0
+xhmart.com, 0
+xhu.edu.cn, 0
+xialuoli.com, 0
+xiamenair.com, 0
+xiangha.com, 0
+xiangjins.com, 0
+xiangta.cc, 0
+xiangzhan.com, 0
+xianrou.com, 0
+xianyugame.com, 0
+xiaobingss.com, 0
+xiaodao.la, 0
+xiaoduotech.com, 0
+xiaoheiban.cn, 0
+xiaoji001.com, 0
+xiaokakeji.com, 0
+xiaokaxiu.com, 0
+xiaolaoer.com, 0
+xiaomilaile.com, 0
+xiaomishu.com, 0
+xiaopinjuben.com, 0
+xiaoyaoji.com.cn, 0
+xiaoying.tv, 0
+xiaoyoucai.com, 0
+xiaozhu.com, 0
+xiaoz.me, 0
+xiashu.cc, 0
+xiazai3.net, 0
+xiazaidown.com, 0
+xibao100.com, 0
+xibaoxiao.com, 0
+xici.com, 0
+xici.net, 0
+xicp.cn, 0
+xicp.net, 0
+xidorn.com, 0
+ximalaya.com, 0
+xincheping.com, 0
+xinchou.com, 0
+xin.com, 0
+xinedome.de, 0
+xineurope.com, 0
+xinfuka.net, 0
+xingk.cc, 0
+xingshulin.com, 0
+xingyun.net, 0
+xingzikeji.com, 0
+xinhua08.com, 0
+xinhuamed.com.cn, 0
+xinhuanet.com, 0
+xinhua.org, 0
+xinit.ru, 0
+xiniugushi.com, 0
+xinmin.cn, 0
+xinqixi.com, 0
+xinshangshangxin.com, 0
+xinux.net, 0
+xinxindai.com, 0
+xiph.org, 0
+xitieba.com, 0
+xiu8.com, 0
+xiu.com, 0
+xixi123.com, 0
+xiyoucn.com, 0
+xizi.com, 0
+xjatc.com, 0
+xjnu.edu.cn, 0
+xjtag.com, 0
+xjtlu.edu.cn, 0
+xjtu.edu.cn, 0
+xju.edu.cn, 0
+xjy.cn, 0
+xkb.com.cn, 0
+xlm.pl, 0
+xl.pt, 0
+xlzd.me, 0
+xmcimg.com, 0
+xmeye.net, 0
+xmisp.com, 0
+xmjl.com, 0
+xmjydj.com, 0
+xmmandarinonline.com, 0
+xm-n-tax.gov.cn, 0
+xmp.net, 0
+xmpp.jp, 0
+xmpp.org, 0
+xmt.cn, 0
+xmusik.me, 0
+xmyuzhou.com.cn, 0
+xn--12c4db3b2bb9h.net, 0
+xn--1-btbl6aqcj8hc.xn--p1ai, 0
+xn--2i0b10rwthi7fqvp1hd.com, 0
+xn--41a.ws, 0
+xn------7cdbxfuat6afkbmmhefunjo4bs9u.xn--p1ai, 0
+xn----7sbabalf0fh7h4b.xn--p1ai, 0
+xn--80aaaac8algcbgbck3fl0q.xn--p1ai, 0
+xn--80aaej4apiv2bzg.xn--p1ai, 0
+xn--80abemlex2i.xn--p1ai, 0
+xn--80accn9dh.xn--90ais, 0
+xn--80aealaaatcuj2bbdbr2agjd6hzh.xn--p1ai, 0
+xn--80aeopmfjx.xn--80aswg, 0
+xn--80ahclcbajtrv5ae6c.xn--p1ai, 0
+xn----8sbbilafpyxcf8a.xn--p1ai, 0
+xn--90agc8a6d.xn--d1acj3b, 0
+xn--90agrrk8e.xn--p1ai, 0
+xn--b1a3bf.xn--p1ai, 0
+xn--b1acdcqi5ci.xn--p1ai, 0
+xn--c1acndtdamdoc1ib.xn--p1ai, 0
+xn--c1afjenhpy1e1a.xn--p1ai, 0
+xn--c1arjr.xn--p1ai, 0
+xn--c1avg.xn--p1ai, 0
+xn--d1acnqm.xn--j1amh, 0
+xn----dtbofgvdd5ah.xn--p1ai, 0
+xn--e1agfw6a0bt.xn--p1ai, 0
+xn--e1apcdqc2g.xn--p1ai, 0
+xn--f1ae4a2b.xn--p1ai, 0
+xn--i2ru8q2qg.com, 0
+xnw.com, 0
+xn----ymcba3adxu7lezvuj.sa.com, 0
+xocka.ru, 0
+x-omics.org, 0
+xopom.com, 0
+xosobinhduong.com.vn, 0
+xpg.com.br, 0
+xpir.ru, 0
+xpsss.com, 0
+xquartz.org, 0
+xrea.com, 0
+xrnm.com, 0
+xrule34.com, 0
+xs4all.nl, 0
+xsdzq.cn, 0
+xskygames.pl, 0
+xsph.ru, 0
+xssec.org, 0
+xsteach.com, 0
+xsunucu.com, 0
+xtbg.ac.cn, 0
+xtcrm.com, 0
+xtern.ru, 0
+xthor.bz, 0
+xtion.net, 0
+xtrade.com, 0
+xtrance.info, 0
+xtreme.pt, 0
+xtrim.ru, 0
+xtrlarge.com, 0
+xtronics.com, 0
+xuanlove.net, 0
+xuanruanjian.com, 0
+xuanwo.org, 0
+xubiji.com, 0
+xueda.com, 0
+xueshandai.com, 0
+xujc.com, 0
+xuni99.com, 0
+xunjiepdf.com, 0
+xunleiyy.com, 0
+xunyou.com, 0
+xura.com, 0
+xuri.me, 0
+xuulm.com, 0
+xuuue.cn, 0
+xvhost.com, 0
+xvid.com, 0
+xvideoslive.com, 0
+xwall.pro, 0
+xweb.cn, 0
+xwhosp.com.cn, 0
+xwiki.com, 0
+xwiki.org, 0
+xwis.net, 0
+xwjr.com, 0
+xwsd.com, 0
+xxshe.com, 0
+xxt.cn, 0
+xxx3tube.com, 0
+xxxooo.link, 0
+xyaz.cn, 0
+xydeyou.com, 0
+xyfunds.com.cn, 0
+xyiege.com, 0
+xyu.tv, 0
+xyy001.com, 0
+xyzq.com.cn, 0
+xzcblog.com, 0
+xz.gov.cn, 0
+xzmc.edu.cn, 0
+xzn.ir, 0
+y3600.com, 0
+yablyk.com, 0
+yabumi.cc, 0
+yachtbooker.com, 0
+yachtingmagazine.com, 0
+yachtsys.com, 0
+yaduo.com, 0
+yagla.ru, 0
+yaguo.ru, 0
+yahooeu.org, 0
+yahooeu.ru, 0
+yaidu.ru, 0
+yakitoriya.ru, 0
+yalova.edu.tr, 0
+yamaha-motor.co.th, 0
+yamobi.ru, 0
+yanagou.com, 0
+yanfabu.com, 0
+yangchangxi.com, 0
+yangcong345.com, 0
+yangshitianqi.com, 0
+yangtuner.com, 0
+yangzhou.gov.cn, 0
+yanimsoft.ir, 0
+yanke.info, 0
+yanny.link, 0
+yanue.net, 0
+yaociyuan.com, 0
+yaoex.com, 0
+yaomaitong.cn, 0
+yaostrov.ru, 0
+yaou369.com, 0
+yaozh.com, 0
+ya-pluss.ru, 0
+yarcom.ru, 0
+yar-edudep.ru, 0
+yarik-sat.ru, 0
+yastaff.ru, 0
+yat-net.com, 0
+yatong.info, 0
+yatta.de, 0
+yavix.ru, 0
+yavuz-selim.com, 0
+yazuo.com, 0
+ybook.vn, 0
+ybren.com, 0
+ybtcard.com, 0
+ybu.edu.cn, 0
+yburlan.ru, 0
+ycgame.com, 0
+ydidc.top, 0
+ydniu.com, 0
+ydy7.com, 0
+ydybt.net, 0
+yeahka.com, 0
+yealink.com, 0
+yeastar.com, 0
+yeeyi.com, 0
+yeezon.com, 0
+yeezyboost750sale.net, 0
+yeezytrainers.net, 0
+yeint.ru, 0
+yellowdog.co, 0
+yephy.com, 0
+yepster.me, 0
+yerevan.am, 0
+yeshigeek.com, 0
+yesilgazete.org, 0
+yesmywine.com, 0
+yestae.com, 0
+yeti.com, 0
+yfcloud.com, 0
+yfdxs.com, 0
+ygopro.co, 0
+ygqq.com, 0
+ygyhg.com, 0
+yhcd.net, 0
+yht.co.jp, 0
+yhz66.com, 0
+yibei.com, 0
+yibizi.com, 0
+yicai.com, 0
+yiche.com, 0
+yicp.io, 0
+yidai.com, 0
+yidianda.com, 0
+yifile.com, 0
+yifufaka.com, 0
+yigoonet.com, 0
+yiguo.com, 0
+yihu.cn, 0
+yiiframework.com.ua, 0
+yijiakan.com, 0
+yikuaiqu.com, 0
+yilingshop.com, 0
+yilingsj.com, 0
+yilushang.net, 0
+yiminbang.com, 0
+yimishiji.com, 0
+yimu100.com, 0
+yingxiong.com, 0
+yingyanso.com, 0
+yinhu.com, 0
+yiqifa.com, 0
+yiqiniu.com, 0
+yiran.com, 0
+yishu.com, 0
+yisi148.com, 0
+yiso.me, 0
+yit.com, 0
+yithemes.com, 0
+yiyult.com, 0
+yiyunbaby.cn, 0
+yizhihongxing.com, 0
+yjc.ir, 0
+yjk.im, 0
+yjsnpi.nu, 0
+ylc.edu.tw, 0
+ylsoftware.com, 0
+ymanz.com, 0
+ymg360.com, 0
+ymq365.com, 0
+ynairport.com, 0
+ynet.com, 0
+ynet.sk, 0
+yngou.com, 0
+yngs.gov.cn, 0
+ynjy.cn, 0
+ynlib.cn, 0
+ynnu.edu.cn, 0
+ynot.com, 0
+ynszlyy.com, 0
+ynu.edu.cn, 0
+yo-ad.cn, 0
+yoga.com, 0
+yoga-masters.com, 0
+yohotour.com, 0
+yokogawa.com, 0
+yoncu.com, 0
+yongche.org, 0
+yonghappy.com, 0
+yonghui.cn, 0
+yongjinbao.com.cn, 0
+yonyou.com, 0
+yonyouup.com, 0
+yoochoose.com, 0
+yoochoose.net, 0
+yooooo.us, 0
+yooread.com, 0
+yooz.fr, 0
+yotuku.cn, 0
+youchew.net, 0
+youdao.com, 0
+youdian.in, 0
+yougou.com, 0
+youguoquan.com, 0
+youhack.ru, 0
+youhaosuda.com, 0
+youhaovip.com, 0
+youhuashu.com, 0
+youidraw.com, 0
+youjizzlive.com, 0
+youkeshu.com, 0
+youkeyun.com, 0
+youku.com, 0
+you-mp3.net, 0
+youngwriterssociety.com, 0
+youread.me, 0
+yourmechanic.com, 0
+your-pictionary.com, 0
+yoursafe.cn, 0
+your-server.de, 0
+yourski.ru, 0
+yourtion.com, 0
+youscan.io, 0
+youss.co, 0
+youtubers.me, 0
+youwager.eu, 0
+youweather.com, 0
+youxia.org, 0
+youxi.com, 0
+youxiniao.com, 0
+youyuanapp.com, 0
+youzhuan.com, 0
+yovole.com, 0
+yoya.com, 0
+yoyi.com.cn, 0
+yoytourdumonde.fr, 0
+ypc.edu.cn, 0
+yper.co, 0
+ypfbtransporte.com, 0
+ypmate.com, 0
+ypt.or.id, 0
+yq24.net, 0
+yrce.cn, 0
+yrom.net, 0
+ys137.com, 0
+ys7.com, 0
+yscredit.com, 0
+ysepay.com, 0
+ysmu.ru, 0
+ysn.ru, 0
+ysu.edu.cn, 0
+ytdestek.com, 0
+ytvpn.net.cn, 0
+yu0123456.com, 0
+yuadon.com, 0
+yuanbao365.com, 0
+yuanlai521.com, 0
+yubaibaii.com, 0
+yueing.org, 0
+yuejiadai.com, 0
+yueus.com, 0
+yuewen.com, 0
+yufan.me, 0
+yugcontract.ua, 0
+yugiohcardmarket.eu, 0
+yugiohgameonline.com.br, 0
+yuhong.com.cn, 0
+yui-nya.com, 0
+yulong.com, 0
+yumama.com, 0
+yunaq.com, 0
+yunaw.com, 0
+yunbore.com, 0
+yuncaijing.com, 0
+yundun.cn, 0
+yundun.com, 0
+yuneec.cn, 0
+yunhou.com, 0
+yunifang.com, 0
+yunjiazheng.com, 0
+yunjiweidian.com, 0
+yunpan.cn, 0
+yunserver.com, 0
+yunshanmeicai.com, 0
+yuntech.edu.tw, 0
+yuntoo.com, 0
+yunyichong.com, 0
+yunyuejuan.net, 0
+yunyy.cc, 0
+yunzhijia.com, 0
+yusen-logistics.com, 0
+yushuangqi.com, 0
+yusupov-palace.ru, 0
+yutong.com, 0
+yuuby.com, 0
+yuugames.com.cn, 0
+yuying360.com, 0
+yuyue.com.cn, 0
+yuzhoutuofu.com, 0
+ywhuo.com, 0
+ywtywt.com, 0
+ywu.cn, 0
+yxlady.com, 0
+yxsvpn.com, 0
+yy4480.org, 0
+yy6080.org, 0
+yybei.cn, 0
+yywkt.org, 0
+yznu.cn, 0
+z0download.com, 0
+z3news.com, 0
+zaba.hr, 0
+zabedu.ru, 0
+zabi.cz, 0
+zaixiaoren.com, 0
+zajecaronline.com, 0
+zakka.com.tw, 0
+zakonyprolidi.cz, 0
+zakopane.pl, 0
+zamel.pl, 0
+zampdsp.com, 0
+zankhakasia.ru, 0
+zaodula.com, 0
+zaoshu.io, 0
+zapable.com, 0
+zap-hosting.com, 0
+za.pl, 0
+zap.md, 0
+zapr.in, 0
+zapster.it, 0
+zapster.ru, 0
+zapto.org, 0
+zarayef.com, 0
+zarfund.com, 0
+zargaripour.com, 0
+zarinp.al, 0
+zarovi.cz, 0
+zarulem.by, 0
+zastavok.net, 0
+zatlanka.cz, 0
+zatunen.com, 0
+zavod.co.rs, 0
+zaymer.ru, 0
+zaymiprosto.ru, 0
+zbgl.net, 0
+zbj.com, 0
+zbytb.com, 0
+zc8hr.com, 0
+zcckj.com, 0
+zcmu.edu.cn, 0
+zczj.com, 0
+zdfans.com, 0
+zdomo.com, 0
+zdorov.li, 0
+zdraivery.ru, 0
+zdrav26.ru, 0
+zdrav36.ru, 0
+zdrav.spb.ru, 0
+zdrojak.cz, 0
+zdsoft.com, 0
+zdw.krakow.pl, 0
+ze.am, 0
+zebrablinds.ca, 0
+zebraboss.com, 0
+zeeandco.co.uk, 0
+zeemono.com, 0
+zeitnitz.eu, 0
+zelenaya.net, 0
+zelluloza.ru, 0
+zen.co.uk, 0
+zenden.ru, 0
+zendmin.com, 0
+zeneakademia.hu, 0
+zengram.ru, 0
+zenhotels.com, 0
+zenitel.com, 0
+zenius.net, 0
+zenmate.com, 0
+zenpage.cn, 0
+zenserv.fr, 0
+zentaizone.com, 0
+zephyrproject.org, 0
+zepire.com, 0
+zepo.ir, 0
+zerobest.net, 0
+zerohour-productions.net, 0
+zero.kz, 0
+zetail.com.tw, 0
+zetes.com, 0
+zeto.com.ua, 0
+zfilm-hd.net, 0
+zf-projects.ru, 0
+zgboke.com, 0
+zggtxhw.com, 0
+zgny.com.cn, 0
+zgpingshu.com, 0
+zh30.com, 0
+zhacker.net, 0
+zhaishuge.com, 0
+zhanad.com, 0
+zhangge.net, 0
+zhangziran.com, 0
+zhaodl.xyz, 0
+zhaoj.in, 0
+zhaokeli.com, 0
+zhaopin.com, 0
+zhaorannote.cn, 0
+zhaoshangdai.com, 0
+zhaosuliao.com, 0
+zhbor.com, 0
+zhcw.com, 0
+zhe800.com, 0
+zhenai.com, 0
+zhenfund.com, 0
+zhengjie.com, 0
+zhengxianjun.com, 0
+zhibs.net, 0
+zhidx.com, 0
+zhihedongfang.com, 0
+zhiku8.com, 0
+zhimei360.com, 0
+zhique.com, 0
+zhisheji.com, 0
+zhitanska.com, 0
+zhitouwang.cn, 0
+zhiwei.li, 0
+zhiwo.com, 0
+zhiyanblog.com, 0
+zhizaoyun.com, 0
+zhizishe.com, 0
+zhiziyun.com, 0
+zhizuobiao.com, 0
+zhjtong.com, 0
+zhong5.cn, 0
+zhongan.com, 0
+zhonganonline.com, 0
+zhongguowangshi.com, 0
+zhongjiu.cn, 0
+zhongye.net, 0
+zhongziso.com, 0
+zhou92.com, 0
+zhoulujun.cn, 0
+zhovner.com, 0
+zhuang.ba, 0
+zhuankezhijia.com, 0
+zhuanyejun.com, 0
+zhuanyejun.net, 0
+zhuatieba.com, 0
+zhubaoleyuan.com, 0
+zhufaner.com, 0
+zhujike.com, 0
+zhujiwu.me, 0
+zhuna.cn, 0
+zhushou001.com, 0
+zhuwei.me, 0
+zhuzi.me, 0
+zhyk.ru, 0
+ziferblat.net, 0
+zige.la, 0
+ziguangcn.com, 0
+zigzag.kr, 0
+zijilai.com.cn, 0
+zik.ua, 0
+zilanhua.com, 0
+zilingo.com, 0
+zinceuro.sk, 0
+zionrd.com, 0
+zip-anime.xyz, 0
+zip-area.com, 0
+zipbob.net, 0
+zip.ch, 0
+ziping.ir, 0
+zipy.co.il, 0
+zitian.cn, 0
+ziwork.com, 0
+ziy.cc, 0
+ziyonet.uz, 0
+ziyoufang.com, 0
+ziyuanmao.com, 0
+zj.com, 0
+zjds.gov.cn, 0
+zjjt365.com, 0
+zjjw.com, 0
+zjmax.com, 0
+zjport.gov.cn, 0
+zjsafety.gov.cn, 0
+zju.edu.cn, 0
+zjuqsc.com, 0
+zjut.edu.cn, 0
+zju.tools, 0
+zjzwfw.gov.cn, 0
+zkteco.com, 0
+zkungfu.com, 0
+zlatmax.ru, 0
+zlavadna.sk, 0
+zlfund.cn, 0
+zlqh.com, 0
+zlx3323.top, 0
+zm123.com, 0
+zmap.io, 0
+zmirrordemo.com, 0
+zmodo.com, 0
+znakomstva.ru, 0
+znaxyar.ru, 0
+znds.com, 0
+znojmo.cz, 0
+zntec.cn, 0
+zockerbuden.community, 0
+zoc-max.sk, 0
+zodgame.us, 0
+zodio.com, 0
+zol.com.cn, 0
+zomake.com, 0
+zomro.com, 0
+zonakz.net, 0
+zonazvuka.ru, 0
+zone-game.info, 0
+zoobax.com, 0
+zoo-bazar.com, 0
+zoodshoor.com, 0
+zoo.gr, 0
+zoolnews.com, 0
+zoomlion.com, 0
+zoomsquare.com, 0
+zoomsquare.de, 0
+zoossoft.cn, 0
+zori.pt, 0
+zor.uz, 0
+zoublog.com, 0
+zoznamrealit.sk, 0
+zoznamtovaru.sk, 0
+z-payment.com, 0
+z-payment.info, 0
+zph.com.cn, 0
+zproxy.de, 0
+zpua.com.ua, 0
+zqgame.com, 0
+zqu.edu.cn, 0
+zqzhibo.com, 0
+zrbao.com, 0
+zrss.si, 0
+zryhyy.com.cn, 0
+zsben.cz, 0
+zsedu.net, 0
+zs.gov.cn, 0
+zsnet.com, 0
+zsnso.ru, 0
+zt.com, 0
+ztedevice.com, 0
+z-telecom.net, 0
+z-terra.ru, 0
+ztgame.com, 0
+ztmao.com, 0
+ztm.poznan.pl, 0
+ztydata.cn, 0
+zuadr.com, 0
+zuanbank.com, 0
+zu.edu.ua, 0
+zug4.me, 0
+zugunder.com, 0
+zuimc.com, 0
+zun.com, 0
+zupoec.com, 0
+zurich.at, 0
+zust.edu.cn, 0
+zveronline.ru, 0
+zvuk.me, 0
+zwettl.at, 0
+zwwysoft.com, 0
+zxcnw.com, 0
+zxc.science, 0
+zxdl.pw, 0
+zxerp.com, 0
+zx-pk.ru, 0
+zxtsg.com, 0
+zxzxzx.info, 0
+zy127.com, 0
+zycao.com, 0
+zychal.net, 0
+zyctd.com, 0
+zye.cc, 0
+zygames.com, 0
+zylsl.com, 0
+zyns.com, 0
+zype.com, 0
+zyq108.com, 0
+zyxel.by, 0
+zyxr.com, 0
+zzidc.com, 0
+zz.vc, 0
+zzy.cn, 0
+zzz.com.ua, 0
+zzz.sk, 0
+%%
diff --git a/chromium/net/data/websocket/OWNERS b/chromium/net/data/websocket/OWNERS
index 4e835c170be..f1ec1be7d1c 100644
--- a/chromium/net/data/websocket/OWNERS
+++ b/chromium/net/data/websocket/OWNERS
@@ -1,3 +1,6 @@
ricea@chromium.org
tyoshino@chromium.org
yhirano@chromium.org
+
+# TEAM: blink-network-stack@google.com
+# COMPONENT: Blink>Network>WebSockets
diff --git a/chromium/net/der/encode_values.cc b/chromium/net/der/encode_values.cc
index 3c217d35860..abfb78067c3 100644
--- a/chromium/net/der/encode_values.cc
+++ b/chromium/net/der/encode_values.cc
@@ -2,15 +2,17 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#include "base/time/time.h"
#include "net/der/encode_values.h"
+#include "base/time/time.h"
+#include "net/der/parse_values.h"
+
namespace net {
namespace der {
bool EncodeTimeAsGeneralizedTime(const base::Time& time,
- der::GeneralizedTime* generalized_time) {
+ GeneralizedTime* generalized_time) {
base::Time::Exploded exploded;
time.UTCExplode(&exploded);
if (!exploded.HasValidValues())
diff --git a/chromium/net/der/encode_values.h b/chromium/net/der/encode_values.h
index f931d0e8f3d..48a68fa07c5 100644
--- a/chromium/net/der/encode_values.h
+++ b/chromium/net/der/encode_values.h
@@ -6,7 +6,6 @@
#define NET_DER_ENCODE_VALUES_H_
#include "net/base/net_export.h"
-#include "net/der/parse_values.h"
namespace base {
class Time;
@@ -16,6 +15,8 @@ namespace net {
namespace der {
+struct GeneralizedTime;
+
// Encodes |time|, a UTC-based time, to DER |generalized_time|, for comparing
// against other GeneralizedTime objects.
NET_EXPORT bool EncodeTimeAsGeneralizedTime(const base::Time& time,
@@ -25,4 +26,4 @@ NET_EXPORT bool EncodeTimeAsGeneralizedTime(const base::Time& time,
} // namespace net
-#endif // NET_DER_ENCODE_VALUES_H
+#endif // NET_DER_ENCODE_VALUES_H_
diff --git a/chromium/net/der/encode_values_unittest.cc b/chromium/net/der/encode_values_unittest.cc
index 940e1f54547..bf4fd1045ab 100644
--- a/chromium/net/der/encode_values_unittest.cc
+++ b/chromium/net/der/encode_values_unittest.cc
@@ -2,8 +2,10 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#include "base/time/time.h"
#include "net/der/encode_values.h"
+
+#include "base/time/time.h"
+#include "net/der/parse_values.h"
#include "testing/gtest/include/gtest/gtest.h"
namespace net {
diff --git a/chromium/net/der/input.cc b/chromium/net/der/input.cc
index 1693e5bdb7e..76d101057f8 100644
--- a/chromium/net/der/input.cc
+++ b/chromium/net/der/input.cc
@@ -2,12 +2,13 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
+#include "net/der/input.h"
+
#include <string.h>
#include <algorithm>
#include "base/logging.h"
-#include "net/der/input.h"
namespace net {
diff --git a/chromium/net/der/input_unittest.cc b/chromium/net/der/input_unittest.cc
index 40fdc0c531a..5ae4ceb5af7 100644
--- a/chromium/net/der/input_unittest.cc
+++ b/chromium/net/der/input_unittest.cc
@@ -2,8 +2,9 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#include "base/logging.h"
#include "net/der/input.h"
+
+#include "base/logging.h"
#include "testing/gtest/include/gtest/gtest.h"
namespace net {
diff --git a/chromium/net/der/parse_values.cc b/chromium/net/der/parse_values.cc
index 903daafdc0d..23217e71cfa 100644
--- a/chromium/net/der/parse_values.cc
+++ b/chromium/net/der/parse_values.cc
@@ -2,11 +2,11 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
+#include "net/der/parse_values.h"
+
#include <tuple>
#include "base/logging.h"
-#include "base/numerics/safe_math.h"
-#include "net/der/parse_values.h"
namespace net {
diff --git a/chromium/net/der/parse_values_unittest.cc b/chromium/net/der/parse_values_unittest.cc
index 07d7541a62e..6671d3b33d4 100644
--- a/chromium/net/der/parse_values_unittest.cc
+++ b/chromium/net/der/parse_values_unittest.cc
@@ -2,10 +2,11 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
+#include "net/der/parse_values.h"
+
#include <stdint.h>
#include "base/macros.h"
-#include "net/der/parse_values.h"
#include "testing/gtest/include/gtest/gtest.h"
namespace net {
diff --git a/chromium/net/der/parser.cc b/chromium/net/der/parser.cc
index 5ab5ad82886..7b8273d4f25 100644
--- a/chromium/net/der/parser.cc
+++ b/chromium/net/der/parser.cc
@@ -2,11 +2,10 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#include "base/logging.h"
-#include "base/numerics/safe_math.h"
-#include "net/der/parse_values.h"
#include "net/der/parser.h"
+#include "net/der/parse_values.h"
+
namespace net {
namespace der {
diff --git a/chromium/net/der/parser.h b/chromium/net/der/parser.h
index d83a37569f4..fa96ba907e0 100644
--- a/chromium/net/der/parser.h
+++ b/chromium/net/der/parser.h
@@ -9,7 +9,6 @@
#include "base/compiler_specific.h"
#include "base/macros.h"
-#include "base/time/time.h"
#include "net/base/net_export.h"
#include "net/der/input.h"
#include "net/der/tag.h"
diff --git a/chromium/net/der/parser_unittest.cc b/chromium/net/der/parser_unittest.cc
index 15356526c77..435b4a418ba 100644
--- a/chromium/net/der/parser_unittest.cc
+++ b/chromium/net/der/parser_unittest.cc
@@ -2,11 +2,10 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#include "base/logging.h"
-#include "base/numerics/safe_math.h"
+#include "net/der/parser.h"
+
#include "net/der/input.h"
#include "net/der/parse_values.h"
-#include "net/der/parser.h"
#include "testing/gtest/include/gtest/gtest.h"
namespace net {
diff --git a/chromium/net/der/tag.cc b/chromium/net/der/tag.cc
index a8240243943..bdd5a6bfc9a 100644
--- a/chromium/net/der/tag.cc
+++ b/chromium/net/der/tag.cc
@@ -2,9 +2,10 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#include "base/logging.h"
#include "net/der/tag.h"
+#include "base/logging.h"
+
namespace net {
namespace der {
diff --git a/chromium/net/disk_cache/backend_unittest.cc b/chromium/net/disk_cache/backend_unittest.cc
index e92dd9b2f59..2f401c8cfcb 100644
--- a/chromium/net/disk_cache/backend_unittest.cc
+++ b/chromium/net/disk_cache/backend_unittest.cc
@@ -126,6 +126,7 @@ class DiskCacheBackendTest : public DiskCacheTestWithCache {
void BackendDoomRecent();
void BackendDoomBetween();
void BackendCalculateSizeOfAllEntries();
+ void BackendCalculateSizeOfEntriesBetween();
void BackendTransaction(const std::string& name, int num_entries, bool load);
void BackendRecoverInsert();
void BackendRecoverRemove();
@@ -1872,6 +1873,70 @@ TEST_F(DiskCacheBackendTest, SimpleCacheCalculateSizeOfAllEntries) {
BackendCalculateSizeOfAllEntries();
}
+void DiskCacheBackendTest::BackendCalculateSizeOfEntriesBetween() {
+ InitCache();
+
+ EXPECT_EQ(0, CalculateSizeOfEntriesBetween(base::Time(), base::Time::Max()));
+
+ Time start = Time::Now();
+
+ disk_cache::Entry* entry;
+ ASSERT_THAT(CreateEntry("first", &entry), IsOk());
+ entry->Close();
+ FlushQueueForTest();
+
+ AddDelay();
+ Time middle = Time::Now();
+ AddDelay();
+
+ ASSERT_THAT(CreateEntry("second", &entry), IsOk());
+ entry->Close();
+ ASSERT_THAT(CreateEntry("third_entry", &entry), IsOk());
+ entry->Close();
+ FlushQueueForTest();
+
+ AddDelay();
+ Time end = Time::Now();
+
+ int size_1 = GetEntryMetadataSize("first");
+ int size_2 = GetEntryMetadataSize("second");
+ int size_3 = GetEntryMetadataSize("third_entry");
+
+ ASSERT_EQ(3, cache_->GetEntryCount());
+ ASSERT_EQ(CalculateSizeOfAllEntries(),
+ CalculateSizeOfEntriesBetween(base::Time(), base::Time::Max()));
+
+ int start_end = CalculateSizeOfEntriesBetween(start, end);
+ ASSERT_EQ(CalculateSizeOfAllEntries(), start_end);
+ ASSERT_EQ(size_1 + size_2 + size_3, start_end);
+
+ ASSERT_EQ(size_1, CalculateSizeOfEntriesBetween(start, middle));
+ ASSERT_EQ(size_2 + size_3, CalculateSizeOfEntriesBetween(middle, end));
+
+ // After dooming the entries, the size should be back to zero.
+ ASSERT_THAT(DoomAllEntries(), IsOk());
+ EXPECT_EQ(0, CalculateSizeOfEntriesBetween(base::Time(), base::Time::Max()));
+}
+
+TEST_F(DiskCacheBackendTest, CalculateSizeOfEntriesBetween) {
+ InitCache();
+ ASSERT_EQ(net::ERR_NOT_IMPLEMENTED,
+ CalculateSizeOfEntriesBetween(base::Time(), base::Time::Max()));
+}
+
+TEST_F(DiskCacheBackendTest, MemoryOnlyCalculateSizeOfEntriesBetween) {
+ SetMemoryOnlyMode();
+ BackendCalculateSizeOfEntriesBetween();
+}
+
+TEST_F(DiskCacheBackendTest, SimpleCacheCalculateSizeOfEntriesBetween) {
+ // Use net::APP_CACHE to make size estimations deterministic via
+ // non-optimistic writes.
+ SetCacheType(net::APP_CACHE);
+ SetSimpleCacheMode();
+ BackendCalculateSizeOfEntriesBetween();
+}
+
void DiskCacheBackendTest::BackendTransaction(const std::string& name,
int num_entries, bool load) {
success_ = false;
diff --git a/chromium/net/disk_cache/blockfile/eviction.cc b/chromium/net/disk_cache/blockfile/eviction.cc
index 52fca5fb7d0..68f65b4bdcb 100644
--- a/chromium/net/disk_cache/blockfile/eviction.cc
+++ b/chromium/net/disk_cache/blockfile/eviction.cc
@@ -275,12 +275,10 @@ void Eviction::ReportTrimTimes(EntryImpl* entry) {
backend_->FirstEviction();
} else {
// This is an old file, but we may want more reports from this user so
- // lets save some create_time.
- Time::Exploded old = {0};
- old.year = 2009;
- old.month = 3;
- old.day_of_month = 1;
- header_->create_time = Time::FromLocalExploded(old).ToInternalValue();
+ // lets save some create_time. Conversion cannot fail here.
+ const base::Time time_2009_3_1 =
+ base::Time::FromInternalValue(12985574400000000);
+ header_->create_time = time_2009_3_1.ToInternalValue();
}
}
}
diff --git a/chromium/net/disk_cache/blockfile/file_ios.cc b/chromium/net/disk_cache/blockfile/file_ios.cc
index b2a6d6ef400..47ff7f8edf9 100644
--- a/chromium/net/disk_cache/blockfile/file_ios.cc
+++ b/chromium/net/disk_cache/blockfile/file_ios.cc
@@ -14,7 +14,7 @@
#include "base/location.h"
#include "base/logging.h"
#include "base/macros.h"
-#include "base/threading/worker_pool.h"
+#include "base/task_scheduler/post_task.h"
#include "net/base/net_errors.h"
#include "net/disk_cache/blockfile/in_flight_io.h"
#include "net/disk_cache/disk_cache.h"
@@ -121,8 +121,12 @@ void FileInFlightIO::PostRead(disk_cache::File *file, void* buf, size_t buf_len,
new FileBackgroundIO(file, buf, buf_len, offset, callback, this));
file->AddRef(); // Balanced on OnOperationComplete()
- base::WorkerPool::PostTask(FROM_HERE,
- base::Bind(&FileBackgroundIO::Read, operation.get()), true);
+ base::PostTaskWithTraits(
+ FROM_HERE, base::TaskTraits()
+ .WithShutdownBehavior(
+ base::TaskShutdownBehavior::CONTINUE_ON_SHUTDOWN)
+ .MayBlock(),
+ base::Bind(&FileBackgroundIO::Read, operation.get()));
OnOperationPosted(operation.get());
}
@@ -133,8 +137,12 @@ void FileInFlightIO::PostWrite(disk_cache::File* file, const void* buf,
new FileBackgroundIO(file, buf, buf_len, offset, callback, this));
file->AddRef(); // Balanced on OnOperationComplete()
- base::WorkerPool::PostTask(FROM_HERE,
- base::Bind(&FileBackgroundIO::Write, operation.get()), true);
+ base::PostTaskWithTraits(
+ FROM_HERE, base::TaskTraits()
+ .WithShutdownBehavior(
+ base::TaskShutdownBehavior::CONTINUE_ON_SHUTDOWN)
+ .MayBlock(),
+ base::Bind(&FileBackgroundIO::Write, operation.get()));
OnOperationPosted(operation.get());
}
@@ -258,6 +266,8 @@ size_t File::GetLength() {
DCHECK(base_file_.IsValid());
int64_t len = base_file_.GetLength();
+ if (len < 0)
+ return 0;
if (len > static_cast<int64_t>(std::numeric_limits<uint32_t>::max()))
return std::numeric_limits<uint32_t>::max();
diff --git a/chromium/net/disk_cache/blockfile/file_posix.cc b/chromium/net/disk_cache/blockfile/file_posix.cc
index cdde5b0d45e..828200588a9 100644
--- a/chromium/net/disk_cache/blockfile/file_posix.cc
+++ b/chromium/net/disk_cache/blockfile/file_posix.cc
@@ -139,6 +139,8 @@ size_t File::GetLength() {
DCHECK(base_file_.IsValid());
int64_t len = base_file_.GetLength();
+ if (len < 0)
+ return 0;
if (len > static_cast<int64_t>(std::numeric_limits<uint32_t>::max()))
return std::numeric_limits<uint32_t>::max();
diff --git a/chromium/net/disk_cache/blockfile/in_flight_io.cc b/chromium/net/disk_cache/blockfile/in_flight_io.cc
index cc65384aeaa..3694b75fc78 100644
--- a/chromium/net/disk_cache/blockfile/in_flight_io.cc
+++ b/chromium/net/disk_cache/blockfile/in_flight_io.cc
@@ -11,7 +11,6 @@
#include "base/task_runner.h"
#include "base/threading/thread_restrictions.h"
#include "base/threading/thread_task_runner_handle.h"
-#include "base/trace_event/trace_event.h"
namespace disk_cache {
@@ -26,7 +25,6 @@ void BackgroundIO::OnIOSignalled() {
// TODO(pkasting): Remove ScopedTracker below once crbug.com/477117 is fixed.
tracked_objects::ScopedTracker tracking_profile(
FROM_HERE_WITH_EXPLICIT_FUNCTION("477117 BackgroundIO::OnIOSignalled"));
- TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("net"), "BackgroundIO::OnIOSignalled");
if (controller_)
controller_->InvokeCallback(this, false);
}
diff --git a/chromium/net/disk_cache/blockfile/stats.h b/chromium/net/disk_cache/blockfile/stats.h
index 34b54c6ef53..bb4aed81c2b 100644
--- a/chromium/net/disk_cache/blockfile/stats.h
+++ b/chromium/net/disk_cache/blockfile/stats.h
@@ -15,10 +15,6 @@
#include "net/base/net_export.h"
#include "net/disk_cache/blockfile/addr.h"
-namespace base {
-class HistogramSamples;
-} // namespace base
-
namespace disk_cache {
using StatsItems = base::StringPairs;
diff --git a/chromium/net/disk_cache/cache_creator.cc b/chromium/net/disk_cache/disk_cache.cc
index 3f807fbf266..81676ebd420 100644
--- a/chromium/net/disk_cache/cache_creator.cc
+++ b/chromium/net/disk_cache/disk_cache.cc
@@ -8,7 +8,6 @@
#include "base/macros.h"
#include "base/metrics/field_trial.h"
#include "base/single_thread_task_runner.h"
-#include "base/strings/stringprintf.h"
#include "net/base/cache_type.h"
#include "net/base/net_errors.h"
#include "net/disk_cache/blockfile/backend_impl.h"
@@ -89,8 +88,7 @@ CacheCreator::CacheCreator(
net_log_(net_log) {
}
-CacheCreator::~CacheCreator() {
-}
+CacheCreator::~CacheCreator() {}
int CacheCreator::Run() {
#if defined(OS_ANDROID)
@@ -102,14 +100,14 @@ int CacheCreator::Run() {
(backend_type_ == net::CACHE_BACKEND_DEFAULT &&
kSimpleBackendIsDefault)) {
disk_cache::SimpleBackendImpl* simple_cache =
- new disk_cache::SimpleBackendImpl(
- path_, max_bytes_, type_, thread_, net_log_);
+ new disk_cache::SimpleBackendImpl(path_, max_bytes_, type_, thread_,
+ net_log_);
created_cache_.reset(simple_cache);
return simple_cache->Init(
base::Bind(&CacheCreator::OnIOComplete, base::Unretained(this)));
}
- // Avoid references to blockfile functions on Android to reduce binary size.
+// Avoid references to blockfile functions on Android to reduce binary size.
#if defined(OS_ANDROID)
return net::ERR_FAILED;
#else
@@ -177,17 +175,16 @@ int CreateCacheBackend(
return *backend ? net::OK : net::ERR_FAILED;
}
DCHECK(thread.get());
- CacheCreator* creator = new CacheCreator(path,
- force,
- max_bytes,
- type,
- backend_type,
- kNone,
- thread,
- net_log,
- backend,
- callback);
+ CacheCreator* creator =
+ new CacheCreator(path, force, max_bytes, type, backend_type, kNone,
+ thread, net_log, backend, callback);
return creator->Run();
}
+int Backend::CalculateSizeOfEntriesBetween(base::Time initial_time,
+ base::Time end_time,
+ const CompletionCallback& callback) {
+ return net::ERR_NOT_IMPLEMENTED;
+}
+
} // namespace disk_cache
diff --git a/chromium/net/disk_cache/disk_cache.h b/chromium/net/disk_cache/disk_cache.h
index f71bc81964b..09924065c4b 100644
--- a/chromium/net/disk_cache/disk_cache.h
+++ b/chromium/net/disk_cache/disk_cache.h
@@ -19,6 +19,7 @@
#include "base/time/time.h"
#include "net/base/cache_type.h"
#include "net/base/completion_callback.h"
+#include "net/base/net_errors.h"
#include "net/base/net_export.h"
namespace base {
@@ -149,8 +150,19 @@ class NET_EXPORT Backend {
// Calculate the total size of the cache. The return value is the size in
// bytes or a net error code. If this method returns ERR_IO_PENDING,
// the |callback| will be invoked when the operation completes.
- virtual int CalculateSizeOfAllEntries(
- const CompletionCallback& callback) = 0;
+ virtual int CalculateSizeOfAllEntries(const CompletionCallback& callback) = 0;
+
+ // Calculate the size of all cache entries accessed between |initial_time| and
+ // |end_time|.
+ // The return value is the size in bytes or a net error code. The default
+ // implementation returns ERR_NOT_IMPLEMENTED and should only be overwritten
+ // if there is an efficient way for the backend to determine the size for a
+ // subset of the cache without reading the whole cache from disk.
+ // If this method returns ERR_IO_PENDING, the |callback| will be invoked when
+ // the operation completes.
+ virtual int CalculateSizeOfEntriesBetween(base::Time initial_time,
+ base::Time end_time,
+ const CompletionCallback& callback);
// Returns an iterator which will enumerate all entries of the cache in an
// undefined order.
diff --git a/chromium/net/disk_cache/disk_cache_perftest.cc b/chromium/net/disk_cache/disk_cache_perftest.cc
index b4ad47dc618..eeef3b71d73 100644
--- a/chromium/net/disk_cache/disk_cache_perftest.cc
+++ b/chromium/net/disk_cache/disk_cache_perftest.cc
@@ -62,7 +62,7 @@ class DiskCachePerfTest : public DiskCacheTestWithCache {
~DiskCachePerfTest() override {
if (saved_fd_limit_ < kFdLimitForCacheTests)
- MaybeSetFdLimit(kFdLimitForCacheTests);
+ MaybeSetFdLimit(saved_fd_limit_);
}
protected:
diff --git a/chromium/net/disk_cache/disk_cache_test_base.cc b/chromium/net/disk_cache/disk_cache_test_base.cc
index 84ba9c676f2..030c7bd35e0 100644
--- a/chromium/net/disk_cache/disk_cache_test_base.cc
+++ b/chromium/net/disk_cache/disk_cache_test_base.cc
@@ -179,6 +179,15 @@ int DiskCacheTestWithCache::CalculateSizeOfAllEntries() {
return cb.GetResult(rv);
}
+int DiskCacheTestWithCache::CalculateSizeOfEntriesBetween(
+ const base::Time initial_time,
+ const base::Time end_time) {
+ net::TestCompletionCallback cb;
+ int rv = cache_->CalculateSizeOfEntriesBetween(initial_time, end_time,
+ cb.callback());
+ return cb.GetResult(rv);
+}
+
std::unique_ptr<DiskCacheTestWithCache::TestIterator>
DiskCacheTestWithCache::CreateIterator() {
return std::unique_ptr<TestIterator>(
diff --git a/chromium/net/disk_cache/disk_cache_test_base.h b/chromium/net/disk_cache/disk_cache_test_base.h
index c94f5ac82ed..b9564f930e2 100644
--- a/chromium/net/disk_cache/disk_cache_test_base.h
+++ b/chromium/net/disk_cache/disk_cache_test_base.h
@@ -12,6 +12,7 @@
#include "base/files/file_path.h"
#include "base/files/scoped_temp_dir.h"
#include "base/macros.h"
+#include "base/test/scoped_async_task_scheduler.h"
#include "base/threading/thread.h"
#include "net/base/cache_type.h"
#include "net/disk_cache/disk_cache.h"
@@ -56,6 +57,12 @@ class DiskCacheTest : public PlatformTest {
private:
base::ScopedTempDir temp_dir_;
std::unique_ptr<base::MessageLoop> message_loop_;
+
+ // Use a ScopedAsyncTaskScheduler instead of a ScopedTaskScheduler to allow
+ // disk_cache::InFlightIO::WaitForPendingIO to wait for TaskScheduler tasks
+ // from the main thread using WaitableEvents (this wouldn't work if
+ // TaskScheduler tasks ran on the main thread).
+ base::test::ScopedAsyncTaskScheduler scoped_async_task_scheduler_;
};
// Provides basic support for cache related tests.
@@ -131,6 +138,8 @@ class DiskCacheTestWithCache : public DiskCacheTest {
int DoomEntriesBetween(const base::Time initial_time,
const base::Time end_time);
int CalculateSizeOfAllEntries();
+ int CalculateSizeOfEntriesBetween(const base::Time initial_time,
+ const base::Time end_time);
int DoomEntriesSince(const base::Time initial_time);
std::unique_ptr<TestIterator> CreateIterator();
void FlushQueueForTest();
diff --git a/chromium/net/disk_cache/memory/mem_backend_impl.cc b/chromium/net/disk_cache/memory/mem_backend_impl.cc
index ad9dfedcfab..7ded277b2a6 100644
--- a/chromium/net/disk_cache/memory/mem_backend_impl.cc
+++ b/chromium/net/disk_cache/memory/mem_backend_impl.cc
@@ -181,7 +181,6 @@ int MemBackendImpl::DoomEntriesBetween(Time initial_time,
const CompletionCallback& callback) {
if (end_time.is_null())
end_time = Time::Max();
-
DCHECK_GE(end_time, initial_time);
base::LinkNode<MemEntryImpl>* node = lru_list_.head();
@@ -206,6 +205,26 @@ int MemBackendImpl::CalculateSizeOfAllEntries(
return current_size_;
}
+int MemBackendImpl::CalculateSizeOfEntriesBetween(
+ base::Time initial_time,
+ base::Time end_time,
+ const CompletionCallback& callback) {
+ if (end_time.is_null())
+ end_time = Time::Max();
+ DCHECK_GE(end_time, initial_time);
+
+ int size = 0;
+ base::LinkNode<MemEntryImpl>* node = lru_list_.head();
+ while (node != lru_list_.end() && node->value()->GetLastUsed() < initial_time)
+ node = node->next();
+ while (node != lru_list_.end() && node->value()->GetLastUsed() < end_time) {
+ MemEntryImpl* entry = node->value();
+ size += entry->GetStorageSize();
+ node = node->next();
+ }
+ return size;
+}
+
class MemBackendImpl::MemIterator final : public Backend::Iterator {
public:
explicit MemIterator(base::WeakPtr<MemBackendImpl> backend)
diff --git a/chromium/net/disk_cache/memory/mem_backend_impl.h b/chromium/net/disk_cache/memory/mem_backend_impl.h
index 30417c69cab..024da855016 100644
--- a/chromium/net/disk_cache/memory/mem_backend_impl.h
+++ b/chromium/net/disk_cache/memory/mem_backend_impl.h
@@ -91,6 +91,10 @@ class NET_EXPORT_PRIVATE MemBackendImpl final : public Backend {
int DoomEntriesSince(base::Time initial_time,
const CompletionCallback& callback) override;
int CalculateSizeOfAllEntries(const CompletionCallback& callback) override;
+ int CalculateSizeOfEntriesBetween(
+ base::Time initial_time,
+ base::Time end_time,
+ const CompletionCallback& callback) override;
std::unique_ptr<Iterator> CreateIterator() override;
void GetStats(base::StringPairs* stats) override {}
void OnExternalCacheHit(const std::string& key) override;
diff --git a/chromium/net/disk_cache/net_log_parameters.h b/chromium/net/disk_cache/net_log_parameters.h
index 86c5c3cc5b1..d8bbe930591 100644
--- a/chromium/net/disk_cache/net_log_parameters.h
+++ b/chromium/net/disk_cache/net_log_parameters.h
@@ -64,4 +64,4 @@ net::NetLogParametersCallback CreateNetLogGetAvailableRangeResultCallback(
} // namespace disk_cache
-#endif // NET_DISK_CACHE_NET_LOG_CACHE_PARAMETERS_H_
+#endif // NET_DISK_CACHE_NET_LOG_PARAMETERS_H_
diff --git a/chromium/net/disk_cache/simple/simple_backend_impl.cc b/chromium/net/disk_cache/simple/simple_backend_impl.cc
index 30fade471fd..e5645e357eb 100644
--- a/chromium/net/disk_cache/simple/simple_backend_impl.cc
+++ b/chromium/net/disk_cache/simple/simple_backend_impl.cc
@@ -458,6 +458,15 @@ int SimpleBackendImpl::CalculateSizeOfAllEntries(
&SimpleBackendImpl::IndexReadyForSizeCalculation, AsWeakPtr(), callback));
}
+int SimpleBackendImpl::CalculateSizeOfEntriesBetween(
+ base::Time initial_time,
+ base::Time end_time,
+ const CompletionCallback& callback) {
+ return index_->ExecuteWhenReady(
+ base::Bind(&SimpleBackendImpl::IndexReadyForSizeBetweenCalculation,
+ AsWeakPtr(), initial_time, end_time, callback));
+}
+
class SimpleBackendImpl::SimpleIterator final : public Iterator {
public:
explicit SimpleIterator(base::WeakPtr<SimpleBackendImpl> backend)
@@ -573,6 +582,18 @@ void SimpleBackendImpl::IndexReadyForSizeCalculation(
callback.Run(result);
}
+void SimpleBackendImpl::IndexReadyForSizeBetweenCalculation(
+ base::Time initial_time,
+ base::Time end_time,
+ const CompletionCallback& callback,
+ int result) {
+ if (result == net::OK) {
+ result =
+ static_cast<int>(index_->GetCacheSizeBetween(initial_time, end_time));
+ }
+ callback.Run(result);
+}
+
// static
SimpleBackendImpl::DiskStatResult SimpleBackendImpl::InitCacheStructureOnDisk(
const base::FilePath& path,
diff --git a/chromium/net/disk_cache/simple/simple_backend_impl.h b/chromium/net/disk_cache/simple/simple_backend_impl.h
index 3516847e1f7..a0b4b9c4282 100644
--- a/chromium/net/disk_cache/simple/simple_backend_impl.h
+++ b/chromium/net/disk_cache/simple/simple_backend_impl.h
@@ -110,6 +110,10 @@ class NET_EXPORT_PRIVATE SimpleBackendImpl : public Backend,
int DoomEntriesSince(base::Time initial_time,
const CompletionCallback& callback) override;
int CalculateSizeOfAllEntries(const CompletionCallback& callback) override;
+ int CalculateSizeOfEntriesBetween(
+ base::Time initial_time,
+ base::Time end_time,
+ const CompletionCallback& callback) override;
std::unique_ptr<Iterator> CreateIterator() override;
void GetStats(base::StringPairs* stats) override;
void OnExternalCacheHit(const std::string& key) override;
@@ -148,6 +152,13 @@ class NET_EXPORT_PRIVATE SimpleBackendImpl : public Backend,
void IndexReadyForSizeCalculation(const CompletionCallback& callback,
int result);
+ // Calculates the size all cache entries between |initial_time| and
+ // |end_time|. Invoked when the index is ready.
+ void IndexReadyForSizeBetweenCalculation(base::Time initial_time,
+ base::Time end_time,
+ const CompletionCallback& callback,
+ int result);
+
// Try to create the directory if it doesn't exist. This must run on the IO
// thread.
static DiskStatResult InitCacheStructureOnDisk(
diff --git a/chromium/net/disk_cache/simple/simple_entry_format.h b/chromium/net/disk_cache/simple/simple_entry_format.h
index 30a369358fb..eec9d68c7f4 100644
--- a/chromium/net/disk_cache/simple/simple_entry_format.h
+++ b/chromium/net/disk_cache/simple/simple_entry_format.h
@@ -9,10 +9,6 @@
#include "net/base/net_export.h"
-namespace base {
-class Time;
-}
-
namespace disk_cache {
const uint64_t kSimpleInitialMagicNumber = UINT64_C(0xfcfb6d1ba7725c30);
diff --git a/chromium/net/disk_cache/simple/simple_entry_impl.cc b/chromium/net/disk_cache/simple/simple_entry_impl.cc
index 8bc20fcbbde..23136ba60e5 100644
--- a/chromium/net/disk_cache/simple/simple_entry_impl.cc
+++ b/chromium/net/disk_cache/simple/simple_entry_impl.cc
@@ -205,7 +205,7 @@ SimpleEntryImpl::SimpleEntryImpl(net::CacheType cache_type,
void SimpleEntryImpl::SetActiveEntryProxy(
std::unique_ptr<ActiveEntryProxy> active_entry_proxy) {
DCHECK(!active_entry_proxy_);
- active_entry_proxy_.reset(active_entry_proxy.release());
+ active_entry_proxy_ = std::move(active_entry_proxy);
}
int SimpleEntryImpl::OpenEntry(Entry** out_entry,
diff --git a/chromium/net/disk_cache/simple/simple_experiment_unittest.cc b/chromium/net/disk_cache/simple/simple_experiment_unittest.cc
index ca187e413bf..66d04000ed9 100644
--- a/chromium/net/disk_cache/simple/simple_experiment_unittest.cc
+++ b/chromium/net/disk_cache/simple/simple_experiment_unittest.cc
@@ -10,6 +10,7 @@
#include <utility>
#include "base/feature_list.h"
+#include "base/memory/ptr_util.h"
#include "base/metrics/field_trial.h"
#include "base/metrics/field_trial_param_associator.h"
#include "base/optional.h"
diff --git a/chromium/net/disk_cache/simple/simple_index.cc b/chromium/net/disk_cache/simple/simple_index.cc
index e68e7468f20..a654faf3718 100644
--- a/chromium/net/disk_cache/simple/simple_index.cc
+++ b/chromium/net/disk_cache/simple/simple_index.cc
@@ -220,16 +220,14 @@ std::unique_ptr<SimpleIndex::HashList> SimpleIndex::GetEntriesBetween(
end_time = base::Time::Max();
else
end_time += EntryMetadata::GetUpperEpsilonForTimeComparisons();
- const base::Time extended_end_time =
- end_time.is_null() ? base::Time::Max() : end_time;
- DCHECK(extended_end_time >= initial_time);
+ DCHECK(end_time >= initial_time);
+
std::unique_ptr<HashList> ret_hashes(new HashList());
- for (EntrySet::iterator it = entries_set_.begin(), end = entries_set_.end();
- it != end; ++it) {
- EntryMetadata& metadata = it->second;
+ for (const auto& entry : entries_set_) {
+ const EntryMetadata& metadata = entry.second;
base::Time entry_time = metadata.GetLastUsedTime();
- if (initial_time <= entry_time && entry_time < extended_end_time)
- ret_hashes->push_back(it->first);
+ if (initial_time <= entry_time && entry_time < end_time)
+ ret_hashes->push_back(entry.first);
}
return ret_hashes;
}
@@ -248,6 +246,28 @@ uint64_t SimpleIndex::GetCacheSize() const {
return cache_size_;
}
+uint64_t SimpleIndex::GetCacheSizeBetween(base::Time initial_time,
+ base::Time end_time) const {
+ DCHECK_EQ(true, initialized_);
+
+ if (!initial_time.is_null())
+ initial_time -= EntryMetadata::GetLowerEpsilonForTimeComparisons();
+ if (end_time.is_null())
+ end_time = base::Time::Max();
+ else
+ end_time += EntryMetadata::GetUpperEpsilonForTimeComparisons();
+
+ DCHECK(end_time >= initial_time);
+ uint64_t size = 0;
+ for (const auto& entry : entries_set_) {
+ const EntryMetadata& metadata = entry.second;
+ base::Time entry_time = metadata.GetLastUsedTime();
+ if (initial_time <= entry_time && entry_time < end_time)
+ size += metadata.GetEntrySize();
+ }
+ return size;
+}
+
void SimpleIndex::Insert(uint64_t entry_hash) {
DCHECK(io_thread_checker_.CalledOnValidThread());
// Upon insert we don't know yet the size of the entry.
diff --git a/chromium/net/disk_cache/simple/simple_index.h b/chromium/net/disk_cache/simple/simple_index.h
index fee2a1e93e0..1adb0ecc48a 100644
--- a/chromium/net/disk_cache/simple/simple_index.h
+++ b/chromium/net/disk_cache/simple/simple_index.h
@@ -155,6 +155,12 @@ class NET_EXPORT_PRIVATE SimpleIndex
// index has been initialized.
uint64_t GetCacheSize() const;
+ // Returns the size of the cache entries accessed between |initial_time| and
+ // |end_time| in bytes. Can only be called after the index has been
+ // initialized.
+ uint64_t GetCacheSizeBetween(const base::Time initial_time,
+ const base::Time end_time) const;
+
// Returns whether the index has been initialized yet.
bool initialized() const { return initialized_; }
diff --git a/chromium/net/disk_cache/simple/simple_index_file_unittest.cc b/chromium/net/disk_cache/simple/simple_index_file_unittest.cc
index 5d49fb254e3..54ce8955a08 100644
--- a/chromium/net/disk_cache/simple/simple_index_file_unittest.cc
+++ b/chromium/net/disk_cache/simple/simple_index_file_unittest.cc
@@ -15,7 +15,6 @@
#include "base/pickle.h"
#include "base/run_loop.h"
#include "base/single_thread_task_runner.h"
-#include "base/strings/stringprintf.h"
#include "base/threading/thread.h"
#include "base/threading/thread_task_runner_handle.h"
#include "base/time/time.h"
diff --git a/chromium/net/disk_cache/simple/simple_net_log_parameters.h b/chromium/net/disk_cache/simple/simple_net_log_parameters.h
index ac9d003650a..39b105a4408 100644
--- a/chromium/net/disk_cache/simple/simple_net_log_parameters.h
+++ b/chromium/net/disk_cache/simple/simple_net_log_parameters.h
@@ -2,8 +2,8 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#ifndef NET_DISK_CACHE_SIMPLE_NET_LOG_PARAMETERS_H_
-#define NET_DISK_CACHE_SIMPLE_NET_LOG_PARAMETERS_H_
+#ifndef NET_DISK_CACHE_SIMPLE_SIMPLE_NET_LOG_PARAMETERS_H_
+#define NET_DISK_CACHE_SIMPLE_SIMPLE_NET_LOG_PARAMETERS_H_
#include "net/log/net_log_parameters_callback.h"
@@ -29,4 +29,4 @@ net::NetLogParametersCallback CreateNetLogSimpleEntryCreationCallback(
} // namespace disk_cache
-#endif // NET_DISK_CACHE_SIMPLE_NET_LOG_PARAMETERS_H_
+#endif // NET_DISK_CACHE_SIMPLE_SIMPLE_NET_LOG_PARAMETERS_H_
diff --git a/chromium/net/disk_cache/simple/simple_synchronous_entry.cc b/chromium/net/disk_cache/simple/simple_synchronous_entry.cc
index aac3d1143a3..2512656873d 100644
--- a/chromium/net/disk_cache/simple/simple_synchronous_entry.cc
+++ b/chromium/net/disk_cache/simple/simple_synchronous_entry.cc
@@ -16,7 +16,6 @@
#include "base/metrics/histogram_macros.h"
#include "base/numerics/safe_conversions.h"
#include "base/sha1.h"
-#include "base/strings/stringprintf.h"
#include "base/timer/elapsed_timer.h"
#include "crypto/secure_hash.h"
#include "net/base/hash_value.h"
diff --git a/chromium/net/disk_cache/simple/simple_test_util.cc b/chromium/net/disk_cache/simple/simple_test_util.cc
index 9463b63eab4..0251f3ad914 100644
--- a/chromium/net/disk_cache/simple/simple_test_util.cc
+++ b/chromium/net/disk_cache/simple/simple_test_util.cc
@@ -37,8 +37,10 @@ bool RemoveKeySHA256FromEntry(const std::string& key,
File entry_file(entry_file_path, flags);
if (!entry_file.IsValid())
return false;
- int file_length = entry_file.GetLength();
+ int64_t file_length = entry_file.GetLength();
SimpleFileEOF eof_record;
+ if (file_length < static_cast<int64_t>(sizeof(eof_record)))
+ return false;
if (entry_file.Read(file_length - sizeof(eof_record),
reinterpret_cast<char*>(&eof_record),
sizeof(eof_record)) != sizeof(eof_record)) {
@@ -73,8 +75,10 @@ bool CorruptKeySHA256FromEntry(const std::string& key,
File entry_file(entry_file_path, flags);
if (!entry_file.IsValid())
return false;
- int file_length = entry_file.GetLength();
+ int64_t file_length = entry_file.GetLength();
SimpleFileEOF eof_record;
+ if (file_length < static_cast<int64_t>(sizeof(eof_record)))
+ return false;
if (entry_file.Read(file_length - sizeof(eof_record),
reinterpret_cast<char*>(&eof_record),
sizeof(eof_record)) != sizeof(eof_record)) {
@@ -105,8 +109,10 @@ bool CorruptStream0LengthFromEntry(const std::string& key,
File entry_file(entry_file_path, flags);
if (!entry_file.IsValid())
return false;
- int file_length = entry_file.GetLength();
+ int64_t file_length = entry_file.GetLength();
SimpleFileEOF eof_record;
+ if (file_length < static_cast<int64_t>(sizeof(eof_record)))
+ return false;
if (entry_file.Read(file_length - sizeof(eof_record),
reinterpret_cast<char*>(&eof_record),
sizeof(eof_record)) != sizeof(eof_record)) {
diff --git a/chromium/net/dns/address_sorter_posix.cc b/chromium/net/dns/address_sorter_posix.cc
index 965543c0a27..e354de20223 100644
--- a/chromium/net/dns/address_sorter_posix.cc
+++ b/chromium/net/dns/address_sorter_posix.cc
@@ -397,4 +397,3 @@ std::unique_ptr<AddressSorter> AddressSorter::CreateAddressSorter() {
}
} // namespace net
-
diff --git a/chromium/net/dns/address_sorter_unittest.cc b/chromium/net/dns/address_sorter_unittest.cc
index 6c023997a33..b9069df0c80 100644
--- a/chromium/net/dns/address_sorter_unittest.cc
+++ b/chromium/net/dns/address_sorter_unittest.cc
@@ -10,6 +10,8 @@
#include "base/bind.h"
#include "base/logging.h"
+#include "base/message_loop/message_loop.h"
+#include "base/test/scoped_task_scheduler.h"
#include "net/base/address_list.h"
#include "net/base/ip_address.h"
#include "net/base/test_completion_callback.h"
@@ -38,6 +40,8 @@ void OnSortComplete(AddressList* result_buf,
}
TEST(AddressSorterTest, Sort) {
+ base::test::ScopedTaskScheduler scoped_task_scheduler(
+ base::MessageLoop::current());
int expected_result = OK;
#if defined(OS_WIN)
EnsureWinsockInit();
diff --git a/chromium/net/dns/address_sorter_win.cc b/chromium/net/dns/address_sorter_win.cc
index 71ad0c0b71d..a085af5c3e2 100644
--- a/chromium/net/dns/address_sorter_win.cc
+++ b/chromium/net/dns/address_sorter_win.cc
@@ -13,7 +13,7 @@
#include "base/logging.h"
#include "base/macros.h"
#include "base/memory/free_deleter.h"
-#include "base/threading/worker_pool.h"
+#include "base/task_scheduler/post_task.h"
#include "net/base/address_list.h"
#include "net/base/ip_address.h"
#include "net/base/ip_endpoint.h"
@@ -39,7 +39,7 @@ class AddressSorterWin : public AddressSorter {
}
private:
- // Executes the SIO_ADDRESS_LIST_SORT ioctl on the WorkerPool, and
+ // Executes the SIO_ADDRESS_LIST_SORT ioctl asynchronously, and
// performs the necessary conversions to/from AddressList.
class Job : public base::RefCountedThreadSafe<Job> {
public:
@@ -73,21 +73,19 @@ class AddressSorterWin : public AddressSorter {
input_buffer_->Address[i].iSockaddrLength = addr_len;
}
- if (!base::WorkerPool::PostTaskAndReply(
- FROM_HERE,
- base::Bind(&Job::Run, this),
- base::Bind(&Job::OnComplete, this),
- false /* task is slow */)) {
- LOG(ERROR) << "WorkerPool::PostTaskAndReply failed";
- OnComplete();
- }
+ base::PostTaskWithTraitsAndReply(
+ FROM_HERE, base::TaskTraits()
+ .WithShutdownBehavior(
+ base::TaskShutdownBehavior::CONTINUE_ON_SHUTDOWN)
+ .MayBlock(),
+ base::Bind(&Job::Run, this), base::Bind(&Job::OnComplete, this));
}
private:
friend class base::RefCountedThreadSafe<Job>;
~Job() {}
- // Executed on the WorkerPool.
+ // Executed asynchronously in TaskScheduler.
void Run() {
SOCKET sock = socket(AF_INET6, SOCK_DGRAM, IPPROTO_UDP);
if (sock == INVALID_SOCKET)
@@ -147,4 +145,3 @@ std::unique_ptr<AddressSorter> AddressSorter::CreateAddressSorter() {
}
} // namespace net
-
diff --git a/chromium/net/dns/dns_client.cc b/chromium/net/dns/dns_client.cc
index 109c3af1e69..883eb01c357 100644
--- a/chromium/net/dns/dns_client.cc
+++ b/chromium/net/dns/dns_client.cc
@@ -103,4 +103,3 @@ std::unique_ptr<DnsClient> DnsClient::CreateClientForTesting(
}
} // namespace net
-
diff --git a/chromium/net/dns/dns_client.h b/chromium/net/dns/dns_client.h
index 303d68e6775..7809a9103d6 100644
--- a/chromium/net/dns/dns_client.h
+++ b/chromium/net/dns/dns_client.h
@@ -61,4 +61,3 @@ class NET_EXPORT DnsClient {
} // namespace net
#endif // NET_DNS_DNS_CLIENT_H_
-
diff --git a/chromium/net/dns/dns_config_service.cc b/chromium/net/dns/dns_config_service.cc
index 0f839478a4c..1a7a59d5df4 100644
--- a/chromium/net/dns/dns_config_service.cc
+++ b/chromium/net/dns/dns_config_service.cc
@@ -233,4 +233,3 @@ void DnsConfigService::OnCompleteConfig() {
}
} // namespace net
-
diff --git a/chromium/net/dns/dns_config_service.h b/chromium/net/dns/dns_config_service.h
index 5c372262a6c..e0fd54a6f3b 100644
--- a/chromium/net/dns/dns_config_service.h
+++ b/chromium/net/dns/dns_config_service.h
@@ -28,8 +28,6 @@ class Value;
namespace net {
-class IPAddress;
-
// Default to 1 second timeout (before exponential backoff).
const int64_t kDnsDefaultTimeoutMs = 1000;
diff --git a/chromium/net/dns/dns_config_service_posix.cc b/chromium/net/dns/dns_config_service_posix.cc
index ba8a3691331..c9c9d9231af 100644
--- a/chromium/net/dns/dns_config_service_posix.cc
+++ b/chromium/net/dns/dns_config_service_posix.cc
@@ -31,6 +31,8 @@
#if defined(OS_ANDROID)
#include <sys/system_properties.h>
+#include "base/android/build_info.h"
+#include "net/android/network_library.h"
#include "net/base/network_change_notifier.h"
#endif
@@ -170,6 +172,14 @@ ConfigParsePosixResult ReadDnsConfig(DnsConfig* config) {
// TODO(juliatuttle): Depend on libcutils, then switch this (and other uses of
// __system_property_get) to property_get.
ConfigParsePosixResult ReadDnsConfig(DnsConfig* dns_config) {
+ if (base::android::BuildInfo::GetInstance()->sdk_int() >=
+ base::android::SDK_VERSION_MARSHMALLOW) {
+ dns_config->nameservers.clear();
+ net::android::GetDnsServers(&dns_config->nameservers);
+ if (dns_config->nameservers.empty())
+ return CONFIG_PARSE_POSIX_NO_NAMESERVERS;
+ return CONFIG_PARSE_POSIX_OK;
+ }
char property_value[PROP_VALUE_MAX];
__system_property_get("net.dns1", property_value);
std::string dns1_string = property_value;
diff --git a/chromium/net/dns/dns_config_service_unittest.cc b/chromium/net/dns/dns_config_service_unittest.cc
index 99c29e5445a..351830963ff 100644
--- a/chromium/net/dns/dns_config_service_unittest.cc
+++ b/chromium/net/dns/dns_config_service_unittest.cc
@@ -244,4 +244,3 @@ TEST_F(DnsConfigServiceTest, WatchFailure) {
}
} // namespace net
-
diff --git a/chromium/net/dns/dns_config_service_win.h b/chromium/net/dns/dns_config_service_win.h
index 47a1c05e165..96870e9f18c 100644
--- a/chromium/net/dns/dns_config_service_win.h
+++ b/chromium/net/dns/dns_config_service_win.h
@@ -148,4 +148,3 @@ class NET_EXPORT_PRIVATE DnsConfigServiceWin : public DnsConfigService {
} // namespace net
#endif // NET_DNS_DNS_CONFIG_SERVICE_WIN_H_
-
diff --git a/chromium/net/dns/dns_config_service_win_unittest.cc b/chromium/net/dns/dns_config_service_win_unittest.cc
index 5975e88a3b4..091c090a918 100644
--- a/chromium/net/dns/dns_config_service_win_unittest.cc
+++ b/chromium/net/dns/dns_config_service_win_unittest.cc
@@ -443,4 +443,3 @@ TEST(DnsConfigServiceWinTest, HaveNRPT) {
} // namespace
} // namespace net
-
diff --git a/chromium/net/dns/dns_config_watcher_mac.h b/chromium/net/dns/dns_config_watcher_mac.h
index d3e9924626c..3ff44d908be 100644
--- a/chromium/net/dns/dns_config_watcher_mac.h
+++ b/chromium/net/dns/dns_config_watcher_mac.h
@@ -2,6 +2,9 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
+#ifndef NET_DNS_DNS_CONFIG_WATCHER_MAC_H_
+#define NET_DNS_DNS_CONFIG_WATCHER_MAC_H_
+
#include "base/callback_forward.h"
#include "net/dns/dns_config_service_posix.h"
#include "net/dns/notify_watcher_mac.h"
@@ -24,3 +27,5 @@ class DnsConfigWatcher {
} // namespace internal
} // namespace net
+
+#endif // NET_DNS_DNS_CONFIG_WATCHER_MAC_H_
diff --git a/chromium/net/dns/dns_hosts.cc b/chromium/net/dns/dns_hosts.cc
index 568a9ce5558..7d45711372a 100644
--- a/chromium/net/dns/dns_hosts.cc
+++ b/chromium/net/dns/dns_hosts.cc
@@ -215,4 +215,3 @@ bool ParseHostsFile(const base::FilePath& path, DnsHosts* dns_hosts) {
}
} // namespace net
-
diff --git a/chromium/net/dns/dns_hosts.h b/chromium/net/dns/dns_hosts.h
index e55772b7e35..423258ba2dc 100644
--- a/chromium/net/dns/dns_hosts.h
+++ b/chromium/net/dns/dns_hosts.h
@@ -75,4 +75,3 @@ bool NET_EXPORT_PRIVATE ParseHostsFile(const base::FilePath& path,
} // namespace net
#endif // NET_DNS_DNS_HOSTS_H_
-
diff --git a/chromium/net/dns/dns_hosts_unittest.cc b/chromium/net/dns/dns_hosts_unittest.cc
index 72722017206..e2729f6e1f4 100644
--- a/chromium/net/dns/dns_hosts_unittest.cc
+++ b/chromium/net/dns/dns_hosts_unittest.cc
@@ -183,4 +183,3 @@ TEST(DnsHostsTest, HostsParser_EndsWithNewlineAndToken) {
} // namespace
} // namespace net
-
diff --git a/chromium/net/dns/dns_protocol.h b/chromium/net/dns/dns_protocol.h
index f80886338ac..416738a2bed 100644
--- a/chromium/net/dns/dns_protocol.h
+++ b/chromium/net/dns/dns_protocol.h
@@ -128,7 +128,6 @@ static const uint16_t kTypeNSEC = 47;
// DNS reply codes (RCODEs).
//
// https://www.iana.org/assignments/dns-parameters/dns-parameters.xhtml#dns-parameters-6
-static const uint8_t kRcodeMask = 0xf;
static const uint8_t kRcodeNOERROR = 0;
static const uint8_t kRcodeFORMERR = 1;
static const uint8_t kRcodeSERVFAIL = 2;
diff --git a/chromium/net/dns/dns_response.cc b/chromium/net/dns/dns_response.cc
index 98967899156..f168a255f39 100644
--- a/chromium/net/dns/dns_response.cc
+++ b/chromium/net/dns/dns_response.cc
@@ -19,6 +19,12 @@
namespace net {
+namespace {
+
+const uint8_t kRcodeMask = 0xf;
+
+} // namespace
+
DnsResourceRecord::DnsResourceRecord() {
}
@@ -221,12 +227,12 @@ bool DnsResponse::IsValid() const {
uint16_t DnsResponse::flags() const {
DCHECK(parser_.IsValid());
- return base::NetToHost16(header()->flags) & ~(dns_protocol::kRcodeMask);
+ return base::NetToHost16(header()->flags) & ~(kRcodeMask);
}
uint8_t DnsResponse::rcode() const {
DCHECK(parser_.IsValid());
- return base::NetToHost16(header()->flags) & dns_protocol::kRcodeMask;
+ return base::NetToHost16(header()->flags) & kRcodeMask;
}
unsigned DnsResponse::answer_count() const {
diff --git a/chromium/net/dns/dns_session.h b/chromium/net/dns/dns_session.h
index 1ffa40c219d..a97132eec0e 100644
--- a/chromium/net/dns/dns_session.h
+++ b/chromium/net/dns/dns_session.h
@@ -23,12 +23,10 @@
namespace base {
class BucketRanges;
-class SampleVector;
}
namespace net {
-class ClientSocketFactory;
class DatagramClientSocket;
class NetLog;
struct NetLogSource;
diff --git a/chromium/net/dns/dns_session_unittest.cc b/chromium/net/dns/dns_session_unittest.cc
index c75e30e98cb..d228556f427 100644
--- a/chromium/net/dns/dns_session_unittest.cc
+++ b/chromium/net/dns/dns_session_unittest.cc
@@ -9,8 +9,8 @@
#include <utility>
#include "base/bind.h"
+#include "base/memory/ptr_util.h"
#include "base/rand_util.h"
-#include "base/stl_util.h"
#include "net/base/ip_address.h"
#include "net/dns/dns_protocol.h"
#include "net/dns/dns_socket_pool.h"
@@ -56,7 +56,7 @@ class TestClientSocketFactory : public ClientSocketFactory {
void ClearSSLSessionCache() override { NOTIMPLEMENTED(); }
private:
- std::list<SocketDataProvider*> data_providers_;
+ std::list<std::unique_ptr<SocketDataProvider>> data_providers_;
};
struct PoolEvent {
@@ -187,14 +187,13 @@ TestClientSocketFactory::CreateDatagramClientSocket(
// We're not actually expecting to send or receive any data, so use the
// simplest SocketDataProvider with no data supplied.
SocketDataProvider* data_provider = new StaticSocketDataProvider();
- data_providers_.push_back(data_provider);
+ data_providers_.push_back(base::WrapUnique(data_provider));
std::unique_ptr<MockUDPClientSocket> socket(
new MockUDPClientSocket(data_provider, net_log));
return std::move(socket);
}
TestClientSocketFactory::~TestClientSocketFactory() {
- base::STLDeleteElements(&data_providers_);
}
TEST_F(DnsSessionTest, AllocateFree) {
diff --git a/chromium/net/dns/dns_socket_pool.cc b/chromium/net/dns/dns_socket_pool.cc
index bf90c28c573..1070953ec49 100644
--- a/chromium/net/dns/dns_socket_pool.cc
+++ b/chromium/net/dns/dns_socket_pool.cc
@@ -6,8 +6,8 @@
#include "base/logging.h"
#include "base/macros.h"
+#include "base/memory/ptr_util.h"
#include "base/rand_util.h"
-#include "base/stl_util.h"
#include "net/base/address_list.h"
#include "net/base/ip_endpoint.h"
#include "net/base/net_errors.h"
@@ -146,7 +146,7 @@ class DefaultDnsSocketPool : public DnsSocketPool {
private:
void FillPool(unsigned server_index, unsigned size);
- typedef std::vector<DatagramClientSocket*> SocketVector;
+ typedef std::vector<std::unique_ptr<DatagramClientSocket>> SocketVector;
std::vector<SocketVector> pools_;
@@ -176,11 +176,6 @@ void DefaultDnsSocketPool::Initialize(
}
DefaultDnsSocketPool::~DefaultDnsSocketPool() {
- unsigned num_servers = pools_.size();
- for (unsigned server_index = 0; server_index < num_servers; ++server_index) {
- SocketVector& pool = pools_[server_index];
- base::STLDeleteElements(&pool);
- }
}
std::unique_ptr<DatagramClientSocket> DefaultDnsSocketPool::AllocateSocket(
@@ -201,11 +196,11 @@ std::unique_ptr<DatagramClientSocket> DefaultDnsSocketPool::AllocateSocket(
}
unsigned socket_index = GetRandomInt(0, pool.size() - 1);
- DatagramClientSocket* socket = pool[socket_index];
- pool[socket_index] = pool.back();
+ std::unique_ptr<DatagramClientSocket> socket = std::move(pool[socket_index]);
+ pool[socket_index] = std::move(pool.back());
pool.pop_back();
- return std::unique_ptr<DatagramClientSocket>(socket);
+ return socket;
}
void DefaultDnsSocketPool::FreeSocket(
@@ -218,11 +213,11 @@ void DefaultDnsSocketPool::FillPool(unsigned server_index, unsigned size) {
SocketVector& pool = pools_[server_index];
for (unsigned pool_index = pool.size(); pool_index < size; ++pool_index) {
- DatagramClientSocket* socket =
- CreateConnectedSocket(server_index).release();
+ std::unique_ptr<DatagramClientSocket> socket =
+ CreateConnectedSocket(server_index);
if (!socket)
break;
- pool.push_back(socket);
+ pool.push_back(std::move(socket));
}
}
diff --git a/chromium/net/dns/dns_test_util.cc b/chromium/net/dns/dns_test_util.cc
index 24ce6fbb375..2de2c69bdd4 100644
--- a/chromium/net/dns/dns_test_util.cc
+++ b/chromium/net/dns/dns_test_util.cc
@@ -57,6 +57,13 @@ class MockTransaction : public DnsTransaction,
(hostname.compare(0, prefix.size(), prefix) == 0)) {
result_ = rules[i].result;
delayed_ = rules[i].delay;
+
+ // Fill in an IP address for the result if one was not specified.
+ if (result_.ip.empty() && result_.type == MockDnsClientRule::OK) {
+ result_.ip = qtype_ == dns_protocol::kTypeA
+ ? IPAddress::IPv4Localhost()
+ : IPAddress::IPv6Localhost();
+ }
break;
}
}
@@ -86,7 +93,7 @@ class MockTransaction : public DnsTransaction,
private:
void Finish() {
- switch (result_) {
+ switch (result_.type) {
case MockDnsClientRule::EMPTY:
case MockDnsClientRule::OK: {
std::string qname;
@@ -101,22 +108,21 @@ class MockTransaction : public DnsTransaction,
reinterpret_cast<dns_protocol::Header*>(buffer);
header->flags |= dns_protocol::kFlagResponse;
- if (MockDnsClientRule::OK == result_) {
+ if (MockDnsClientRule::OK == result_.type) {
const uint16_t kPointerToQueryName =
static_cast<uint16_t>(0xc000 | sizeof(*header));
const uint32_t kTTL = 86400; // One day.
// Size of RDATA which is a IPv4 or IPv6 address.
- size_t rdata_size = qtype_ == dns_protocol::kTypeA
- ? IPAddress::kIPv4AddressSize
- : IPAddress::kIPv6AddressSize;
+ EXPECT_TRUE(result_.ip.IsValid());
+ size_t rdata_size = result_.ip.size();
// 12 is the sum of sizes of the compressed name reference, TYPE,
// CLASS, TTL and RDLENGTH.
size_t answer_size = 12 + rdata_size;
- // Write answer with loopback IP address.
+ // Write the answer using the expected IP address.
header->ancount = base::HostToNet16(1);
base::BigEndianWriter writer(buffer + nbytes, answer_size);
writer.WriteU16(kPointerToQueryName);
@@ -124,14 +130,7 @@ class MockTransaction : public DnsTransaction,
writer.WriteU16(dns_protocol::kClassIN);
writer.WriteU32(kTTL);
writer.WriteU16(static_cast<uint16_t>(rdata_size));
- if (qtype_ == dns_protocol::kTypeA) {
- char kIPv4Loopback[] = { 0x7f, 0, 0, 1 };
- writer.WriteBytes(kIPv4Loopback, sizeof(kIPv4Loopback));
- } else {
- char kIPv6Loopback[] = { 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 1 };
- writer.WriteBytes(kIPv6Loopback, sizeof(kIPv6Loopback));
- }
+ writer.WriteBytes(result_.ip.bytes().data(), rdata_size);
nbytes += answer_size;
}
EXPECT_TRUE(response.InitParse(nbytes, query));
diff --git a/chromium/net/dns/dns_test_util.h b/chromium/net/dns/dns_test_util.h
index 21769fc1231..133c33fa978 100644
--- a/chromium/net/dns/dns_test_util.h
+++ b/chromium/net/dns/dns_test_util.h
@@ -158,18 +158,27 @@ class DnsClient;
class MockTransactionFactory;
struct MockDnsClientRule {
- enum Result {
+ enum ResultType {
FAIL, // Fail asynchronously with ERR_NAME_NOT_RESOLVED.
TIMEOUT, // Fail asynchronously with ERR_DNS_TIMEOUT.
EMPTY, // Return an empty response.
- OK, // Return a response with loopback address.
+ OK, // Return an IP address (the accompanying IP is an argument in the
+ // Result structure, or understood as localhost when unspecified).
+ };
+
+ struct Result {
+ explicit Result(const IPAddress& ip) : type(OK), ip(ip) {}
+ explicit Result(ResultType type) : type(type) {}
+
+ ResultType type;
+ IPAddress ip;
};
// If |delay| is true, matching transactions will be delayed until triggered
// by the consumer.
MockDnsClientRule(const std::string& prefix_arg,
uint16_t qtype_arg,
- Result result_arg,
+ const Result& result_arg,
bool delay)
: result(result_arg),
prefix(prefix_arg),
diff --git a/chromium/net/dns/dns_transaction.h b/chromium/net/dns/dns_transaction.h
index f81cc554086..cd56fc46ef5 100644
--- a/chromium/net/dns/dns_transaction.h
+++ b/chromium/net/dns/dns_transaction.h
@@ -77,4 +77,3 @@ class NET_EXPORT_PRIVATE DnsTransactionFactory {
} // namespace net
#endif // NET_DNS_DNS_TRANSACTION_H_
-
diff --git a/chromium/net/dns/fuzzed_host_resolver.h b/chromium/net/dns/fuzzed_host_resolver.h
index 945225b7a67..cc14578be32 100644
--- a/chromium/net/dns/fuzzed_host_resolver.h
+++ b/chromium/net/dns/fuzzed_host_resolver.h
@@ -2,8 +2,8 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#ifndef NET_DNS_FUZZED_HOST_RESOLVER_
-#define NET_DNS_FUZZED_HOST_RESOLVER_
+#ifndef NET_DNS_FUZZED_HOST_RESOLVER_H_
+#define NET_DNS_FUZZED_HOST_RESOLVER_H_
#include <stdint.h>
@@ -23,10 +23,8 @@ class FuzzedDataProvider;
namespace net {
class AddressList;
-class ClientSocketFactory;
class DnsClient;
class NetLog;
-class ScopedDefaultHostResolverProc;
// HostResolver that uses a fuzzer to determine what results to return. It
// inherits from HostResolverImpl, unlike MockHostResolver, so more closely
@@ -80,4 +78,4 @@ class FuzzedHostResolver : public HostResolverImpl {
} // namespace net
-#endif // NET_DNS_FUZZED_HOST_RESOLVER_
+#endif // NET_DNS_FUZZED_HOST_RESOLVER_H_
diff --git a/chromium/net/dns/host_cache.cc b/chromium/net/dns/host_cache.cc
index 881f5140b6f..1ff1755e8b1 100644
--- a/chromium/net/dns/host_cache.cc
+++ b/chromium/net/dns/host_cache.cc
@@ -11,6 +11,7 @@
#include "base/strings/string_number_conversions.h"
#include "base/trace_event/trace_event.h"
#include "net/base/net_errors.h"
+#include "net/base/trace_constants.h"
#include "net/dns/dns_util.h"
namespace net {
@@ -162,7 +163,7 @@ void HostCache::Set(const Key& key,
const Entry& entry,
base::TimeTicks now,
base::TimeDelta ttl) {
- TRACE_EVENT0("net", "HostCache::Set");
+ TRACE_EVENT0(kNetTracingCategory, "HostCache::Set");
DCHECK(CalledOnValidThread());
if (caching_is_disabled())
return;
diff --git a/chromium/net/dns/host_resolver_impl.cc b/chromium/net/dns/host_resolver_impl.cc
index fceb67e33a5..c078986f251 100644
--- a/chromium/net/dns/host_resolver_impl.cc
+++ b/chromium/net/dns/host_resolver_impl.cc
@@ -30,7 +30,6 @@
#include "base/metrics/sparse_histogram.h"
#include "base/profiler/scoped_tracker.h"
#include "base/single_thread_task_runner.h"
-#include "base/stl_util.h"
#include "base/strings/string_util.h"
#include "base/strings/utf_string_conversions.h"
#include "base/threading/thread_task_runner_handle.h"
@@ -44,6 +43,7 @@
#include "net/base/ip_address.h"
#include "net/base/ip_endpoint.h"
#include "net/base/net_errors.h"
+#include "net/base/trace_constants.h"
#include "net/base/url_util.h"
#include "net/dns/address_sorter.h"
#include "net/dns/dns_client.h"
@@ -182,6 +182,16 @@ enum DnsResolveStatus {
// For more details: https://www.icann.org/news/announcement-2-2014-08-01-en
const uint8_t kIcanNameCollisionIp[] = {127, 0, 53, 53};
+bool ContainsIcannNameCollisionIp(const AddressList& addr_list) {
+ for (const auto& endpoint : addr_list) {
+ const IPAddress& addr = endpoint.address();
+ if (addr.IsIPv4() && IPAddressStartsWith(addr, kIcanNameCollisionIp)) {
+ return true;
+ }
+ }
+ return false;
+}
+
void UmaAsyncDnsResolveStatus(DnsResolveStatus result) {
UMA_HISTOGRAM_ENUMERATION("AsyncDNS.ResolveStatus",
result,
@@ -738,16 +748,6 @@ class HostResolverImpl::ProcTask
&results,
&os_error);
- // Fail the resolution if the result contains 127.0.53.53. See the comment
- // block of kIcanNameCollisionIp for details on why.
- for (const auto& it : results) {
- const IPAddress& cur = it.address();
- if (cur.IsIPv4() && IPAddressStartsWith(cur, kIcanNameCollisionIp)) {
- error = ERR_ICANN_NAME_COLLISION;
- break;
- }
- }
-
network_task_runner_->PostTask(
FROM_HERE, base::Bind(&ProcTask::OnLookupComplete, this, results,
start_time, attempt_number, error, os_error));
@@ -770,7 +770,7 @@ class HostResolverImpl::ProcTask
const uint32_t attempt_number,
int error,
const int os_error) {
- TRACE_EVENT0("net", "ProcTask::OnLookupComplete");
+ TRACE_EVENT0(kNetTracingCategory, "ProcTask::OnLookupComplete");
DCHECK(network_task_runner_->BelongsToCurrentThread());
// If results are empty, we should return an error.
bool empty_list_on_ok = (error == OK && results.empty());
@@ -1457,9 +1457,7 @@ class HostResolverImpl::Job : public PrioritizedDispatcher::Job,
requests_.front()->info(),
&addr_list)) {
// This will destroy the Job.
- CompleteRequests(
- HostCache::Entry(OK, MakeAddressListForRequest(addr_list)),
- base::TimeDelta());
+ CompleteRequests(MakeCacheEntry(OK, addr_list), base::TimeDelta());
return true;
}
return false;
@@ -1499,6 +1497,25 @@ class HostResolverImpl::Job : public PrioritizedDispatcher::Job,
DCHECK_EQ(1u, num_occupied_job_slots_);
}
+ // MakeCacheEntry() and MakeCacheEntryWithTTL() are helpers to build a
+ // HostCache::Entry(). The address list is omited from the cache entry
+ // for errors.
+ HostCache::Entry MakeCacheEntry(int net_error,
+ const AddressList& addr_list) const {
+ return HostCache::Entry(
+ net_error,
+ net_error == OK ? MakeAddressListForRequest(addr_list) : AddressList());
+ }
+
+ HostCache::Entry MakeCacheEntryWithTTL(int net_error,
+ const AddressList& addr_list,
+ base::TimeDelta ttl) const {
+ return HostCache::Entry(
+ net_error,
+ net_error == OK ? MakeAddressListForRequest(addr_list) : AddressList(),
+ ttl);
+ }
+
AddressList MakeAddressListForRequest(const AddressList& list) const {
if (requests_.empty())
return list;
@@ -1618,15 +1635,16 @@ class HostResolverImpl::Job : public PrioritizedDispatcher::Job,
}
}
+ if (ContainsIcannNameCollisionIp(addr_list))
+ net_error = ERR_ICANN_NAME_COLLISION;
+
base::TimeDelta ttl =
base::TimeDelta::FromSeconds(kNegativeCacheEntryTTLSeconds);
if (net_error == OK)
ttl = base::TimeDelta::FromSeconds(kCacheEntryTTLSeconds);
// Don't store the |ttl| in cache since it's not obtained from the server.
- CompleteRequests(
- HostCache::Entry(net_error, MakeAddressListForRequest(addr_list)),
- ttl);
+ CompleteRequests(MakeCacheEntry(net_error, addr_list), ttl);
}
void StartDnsTask() {
@@ -1708,9 +1726,12 @@ class HostResolverImpl::Job : public PrioritizedDispatcher::Job,
base::TimeDelta bounded_ttl =
std::max(ttl, base::TimeDelta::FromSeconds(kMinimumTTLSeconds));
- CompleteRequests(
- HostCache::Entry(net_error, MakeAddressListForRequest(addr_list), ttl),
- bounded_ttl);
+ if (ContainsIcannNameCollisionIp(addr_list)) {
+ CompleteRequestsWithError(ERR_ICANN_NAME_COLLISION);
+ } else {
+ CompleteRequests(MakeCacheEntryWithTTL(net_error, addr_list, ttl),
+ bounded_ttl);
+ }
}
void OnFirstDnsTransactionComplete() override {
@@ -1768,7 +1789,7 @@ class HostResolverImpl::Job : public PrioritizedDispatcher::Job,
DCHECK(!requests_.empty());
- if (entry.error() == OK) {
+ if (entry.error() == OK || entry.error() == ERR_ICANN_NAME_COLLISION) {
// Record this histogram here, when we know the system has a valid DNS
// configuration.
UMA_HISTOGRAM_BOOLEAN("AsyncDNS.HaveDnsConfig",
@@ -1895,9 +1916,9 @@ HostResolverImpl::HostResolverImpl(const Options& options, NetLog* net_log)
HostResolverImpl::~HostResolverImpl() {
// Prevent the dispatcher from starting new jobs.
dispatcher_->SetLimitsToZero();
- // It's now safe for Jobs to call KillDsnTask on destruction, because
+ // It's now safe for Jobs to call KillDnsTask on destruction, because
// OnJobComplete will not start any new jobs.
- base::STLDeleteValues(&jobs_);
+ jobs_.clear();
NetworkChangeNotifier::RemoveIPAddressObserver(this);
NetworkChangeNotifier::RemoveConnectionTypeObserver(this);
@@ -1948,7 +1969,7 @@ int HostResolverImpl::Resolve(const RequestInfo& info,
// Next we need to attach our request to a "job". This job is responsible for
// calling "getaddrinfo(hostname)" on a worker thread.
- JobMap::iterator jobit = jobs_.find(key);
+ auto jobit = jobs_.find(key);
Job* job;
if (jobit == jobs_.end()) {
job = new Job(weak_ptr_factory_.GetWeakPtr(), key, priority,
@@ -1966,14 +1987,14 @@ int HostResolverImpl::Resolve(const RequestInfo& info,
return rv;
}
}
- jobs_.insert(jobit, std::make_pair(key, job));
+ jobs_[key] = base::WrapUnique(job);
} else {
- job = jobit->second;
+ job = jobit->second.get();
}
// Can't complete synchronously. Create and attach request.
- std::unique_ptr<RequestImpl> req(new RequestImpl(
- source_net_log, info, priority, callback, addresses, job));
+ auto req = base::MakeUnique<RequestImpl>(source_net_log, info, priority,
+ callback, addresses, job);
job->AddRequest(req.get());
*out_req = std::move(req);
@@ -2302,9 +2323,11 @@ void HostResolverImpl::CacheResult(const Key& key,
void HostResolverImpl::RemoveJob(Job* job) {
DCHECK(job);
- JobMap::iterator it = jobs_.find(job->key());
- if (it != jobs_.end() && it->second == job)
+ auto it = jobs_.find(job->key());
+ if (it != jobs_.end() && it->second.get() == job) {
+ it->second.release();
jobs_.erase(it);
+ }
}
HostResolverImpl::Key HostResolverImpl::GetEffectiveKeyForRequest(
@@ -2335,12 +2358,14 @@ HostResolverImpl::Key HostResolverImpl::GetEffectiveKeyForRequest(
}
bool HostResolverImpl::IsIPv6Reachable(const NetLogWithSource& net_log) {
- base::TimeTicks now = base::TimeTicks::Now();
+ // Cache the result for kIPv6ProbePeriodMs (measured from after
+ // IsGloballyReachable() completes).
bool cached = true;
- if ((now - last_ipv6_probe_time_).InMilliseconds() > kIPv6ProbePeriodMs) {
+ if ((base::TimeTicks::Now() - last_ipv6_probe_time_).InMilliseconds() >
+ kIPv6ProbePeriodMs) {
last_ipv6_probe_result_ =
IsGloballyReachable(IPAddress(kIPv6ProbeAddress), net_log);
- last_ipv6_probe_time_ = now;
+ last_ipv6_probe_time_ = base::TimeTicks::Now();
cached = false;
}
net_log.AddEvent(NetLogEventType::HOST_RESOLVER_IMPL_IPV6_REACHABILITY_CHECK,
@@ -2358,10 +2383,10 @@ void HostResolverImpl::AbortAllInProgressJobs() {
// In Abort, a Request callback could spawn new Jobs with matching keys, so
// first collect and remove all running jobs from |jobs_|.
std::vector<std::unique_ptr<Job>> jobs_to_abort;
- for (JobMap::iterator it = jobs_.begin(); it != jobs_.end(); ) {
- Job* job = it->second;
+ for (auto it = jobs_.begin(); it != jobs_.end();) {
+ Job* job = it->second.get();
if (job->is_running()) {
- jobs_to_abort.push_back(base::WrapUnique(job));
+ jobs_to_abort.push_back(std::move(it->second));
jobs_.erase(it++);
} else {
DCHECK(job->is_queued());
@@ -2398,7 +2423,7 @@ void HostResolverImpl::AbortDnsTasks() {
dispatcher_->SetLimits(
PrioritizedDispatcher::Limits(limits.reserved_slots.size(), 0));
- for (JobMap::iterator it = jobs_.begin(); it != jobs_.end(); ++it)
+ for (auto it = jobs_.begin(); it != jobs_.end(); ++it)
it->second->AbortDnsTask();
dispatcher_->SetLimits(limits);
}
@@ -2413,8 +2438,8 @@ void HostResolverImpl::TryServingAllJobsFromHosts() {
// Life check to bail once |this| is deleted.
base::WeakPtr<HostResolverImpl> self = weak_ptr_factory_.GetWeakPtr();
- for (JobMap::iterator it = jobs_.begin(); self.get() && it != jobs_.end();) {
- Job* job = it->second;
+ for (auto it = jobs_.begin(); self.get() && it != jobs_.end();) {
+ Job* job = it->second.get();
++it;
// This could remove |job| from |jobs_|, but iterator will remain valid.
job->ServeFromHosts();
diff --git a/chromium/net/dns/host_resolver_impl.h b/chromium/net/dns/host_resolver_impl.h
index 373f2297ea0..0ad7146dfc9 100644
--- a/chromium/net/dns/host_resolver_impl.h
+++ b/chromium/net/dns/host_resolver_impl.h
@@ -179,8 +179,8 @@ class NET_EXPORT HostResolverImpl
class LoopbackProbeJob;
class DnsTask;
class RequestImpl;
- typedef HostCache::Key Key;
- typedef std::map<Key, Job*> JobMap;
+ using Key = HostCache::Key;
+ using JobMap = std::map<Key, std::unique_ptr<Job>>;
// Number of consecutive failures of DnsTask (with successful fallback to
// ProcTask) before the DnsClient is disabled until the next DNS change.
@@ -263,7 +263,7 @@ class NET_EXPORT HostResolverImpl
const HostCache::Entry& entry,
base::TimeDelta ttl);
- // Removes |job| from |jobs_|, only if it exists.
+ // Removes |job| from |jobs_|, only if it exists, but does not delete it.
void RemoveJob(Job* job);
// Aborts all in progress jobs with ERR_NETWORK_CHANGED and notifies their
diff --git a/chromium/net/dns/host_resolver_impl_unittest.cc b/chromium/net/dns/host_resolver_impl_unittest.cc
index 0dbed080e9e..0b4807a9851 100644
--- a/chromium/net/dns/host_resolver_impl_unittest.cc
+++ b/chromium/net/dns/host_resolver_impl_unittest.cc
@@ -1486,9 +1486,9 @@ TEST_F(HostResolverImplTest, MultipleAttempts) {
// If a host resolves to a list that includes 127.0.53.53, this is treated as
// an error. 127.0.53.53 is a localhost address, however it has been given a
-// special significance by ICANN to help surfance name collision resulting from
+// special significance by ICANN to help surface name collision resulting from
// the new gTLDs.
-TEST_F(HostResolverImplTest, NameCollision127_0_53_53) {
+TEST_F(HostResolverImplTest, NameCollisionIcann) {
proc_->AddRuleForAllFamilies("single", "127.0.53.53");
proc_->AddRuleForAllFamilies("multiple", "127.0.0.1,127.0.53.53");
proc_->AddRuleForAllFamilies("ipv6", "::127.0.53.53");
@@ -1503,6 +1503,12 @@ TEST_F(HostResolverImplTest, NameCollision127_0_53_53) {
EXPECT_THAT(request->Resolve(), IsError(ERR_IO_PENDING));
EXPECT_THAT(request->WaitForResult(), IsError(ERR_ICANN_NAME_COLLISION));
+ // ERR_ICANN_NAME_COLLISION is cached like any other error, using a
+ // fixed TTL for failed entries from proc-based resolver. That said, the
+ // fixed TTL is 0, so it will never be cached.
+ request = CreateRequest("single");
+ EXPECT_THAT(request->ResolveFromCache(), IsError(ERR_DNS_CACHE_MISS));
+
request = CreateRequest("multiple");
EXPECT_THAT(request->Resolve(), IsError(ERR_IO_PENDING));
EXPECT_THAT(request->WaitForResult(), IsError(ERR_ICANN_NAME_COLLISION));
@@ -1615,6 +1621,16 @@ class HostResolverImplDnsTest : public HostResolverImplTest {
MockDnsClientRule::OK, true);
AddDnsRule("4slow_6timeout", dns_protocol::kTypeAAAA,
MockDnsClientRule::TIMEOUT, false);
+ AddDnsRule("4collision", dns_protocol::kTypeA, IPAddress(127, 0, 53, 53),
+ false);
+ AddDnsRule("4collision", dns_protocol::kTypeAAAA, MockDnsClientRule::EMPTY,
+ false);
+ AddDnsRule("6collision", dns_protocol::kTypeA, MockDnsClientRule::EMPTY,
+ false);
+ // This isn't the expected IP for collisions (but looks close to it).
+ AddDnsRule("6collision", dns_protocol::kTypeAAAA,
+ IPAddress(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 127, 0, 53, 53),
+ false);
CreateResolver();
}
@@ -1633,6 +1649,22 @@ class HostResolverImplDnsTest : public HostResolverImplTest {
// Adds a rule to |dns_rules_|. Must be followed by |CreateResolver| to apply.
void AddDnsRule(const std::string& prefix,
uint16_t qtype,
+ MockDnsClientRule::ResultType result_type,
+ bool delay) {
+ return AddDnsRule(prefix, qtype, MockDnsClientRule::Result(result_type),
+ delay);
+ }
+
+ void AddDnsRule(const std::string& prefix,
+ uint16_t qtype,
+ const IPAddress& result_ip,
+ bool delay) {
+ return AddDnsRule(prefix, qtype, MockDnsClientRule::Result(result_ip),
+ delay);
+ }
+
+ void AddDnsRule(const std::string& prefix,
+ uint16_t qtype,
MockDnsClientRule::Result result,
bool delay) {
dns_rules_.push_back(MockDnsClientRule(prefix, qtype, result, delay));
@@ -1792,6 +1824,34 @@ TEST_F(HostResolverImplDnsTest, DnsTaskUnspec) {
EXPECT_TRUE(requests_[3]->HasAddress("192.168.1.101", 80));
}
+TEST_F(HostResolverImplDnsTest, NameCollisionIcann) {
+ ChangeDnsConfig(CreateValidDnsConfig());
+
+ // When the resolver returns an A record with 127.0.53.53 it should be mapped
+ // to a special error.
+ EXPECT_THAT(CreateRequest("4collision", 80)->Resolve(),
+ IsError(ERR_IO_PENDING));
+
+ EXPECT_THAT(requests_[0]->WaitForResult(), IsError(ERR_ICANN_NAME_COLLISION));
+
+ // When the resolver returns an AAAA record with ::127.0.53.53 it should
+ // work just like any other IP. (Despite having the same suffix, it is not
+ // considered special)
+ EXPECT_THAT(CreateRequest("6collision", 80)->Resolve(),
+ IsError(ERR_IO_PENDING));
+
+ EXPECT_THAT(requests_[1]->WaitForResult(), IsError(OK));
+ EXPECT_TRUE(requests_[1]->HasAddress("::127.0.53.53", 80));
+
+ // The mock responses for 4collision (and 6collision) have a TTL of 1 day.
+ // Test whether the ERR_ICANN_NAME_COLLISION failure was cached.
+ // On the one hand caching the failure makes sense, as the error is derived
+ // from the IP in the response. However for consistency with the the proc-
+ // based implementation the TTL is unused.
+ EXPECT_THAT(CreateRequest("4collision", 80)->ResolveFromCache(),
+ IsError(ERR_DNS_CACHE_MISS));
+}
+
TEST_F(HostResolverImplDnsTest, ServeFromHosts) {
// Initially, use empty HOSTS file.
DnsConfig config = CreateValidDnsConfig();
diff --git a/chromium/net/dns/host_resolver_mojo.cc b/chromium/net/dns/host_resolver_mojo.cc
index 3c311c4a2a8..ac4183adb7b 100644
--- a/chromium/net/dns/host_resolver_mojo.cc
+++ b/chromium/net/dns/host_resolver_mojo.cc
@@ -7,6 +7,7 @@
#include <utility>
#include "base/callback_helpers.h"
+#include "base/memory/ptr_util.h"
#include "mojo/public/cpp/bindings/binding.h"
#include "net/base/address_list.h"
#include "net/base/net_errors.h"
@@ -89,7 +90,7 @@ int HostResolverMojo::Resolve(const RequestInfo& info,
interfaces::HostResolverRequestClientPtr handle;
std::unique_ptr<Job> job(new Job(key, addresses, callback,
- mojo::GetProxy(&handle),
+ mojo::MakeRequest(&handle),
host_cache_weak_factory_.GetWeakPtr()));
request->reset(new RequestImpl(std::move(job)));
diff --git a/chromium/net/dns/mdns_cache.h b/chromium/net/dns/mdns_cache.h
index a2d3d0fc0e5..60987953904 100644
--- a/chromium/net/dns/mdns_cache.h
+++ b/chromium/net/dns/mdns_cache.h
@@ -17,7 +17,6 @@
namespace net {
-class ParsedDnsRecord;
class RecordParsed;
// mDNS Cache
diff --git a/chromium/net/dns/mdns_client_impl.cc b/chromium/net/dns/mdns_client_impl.cc
index 67c5ac5b333..8dbd6d3277e 100644
--- a/chromium/net/dns/mdns_client_impl.cc
+++ b/chromium/net/dns/mdns_client_impl.cc
@@ -12,7 +12,6 @@
#include "base/location.h"
#include "base/memory/ptr_util.h"
#include "base/single_thread_task_runner.h"
-#include "base/stl_util.h"
#include "base/threading/thread_task_runner_handle.h"
#include "base/time/clock.h"
#include "base/time/default_clock.h"
@@ -208,7 +207,6 @@ MDnsClientImpl::Core::Core(base::Clock* clock, base::Timer* timer)
}
MDnsClientImpl::Core::~Core() {
- base::STLDeleteValues(&listeners_);
}
bool MDnsClientImpl::Core::Init(MDnsSocketFactory* socket_factory) {
@@ -348,17 +346,12 @@ void MDnsClientImpl::Core::AlertListeners(
void MDnsClientImpl::Core::AddListener(
MDnsListenerImpl* listener) {
ListenerKey key(listener->GetName(), listener->GetType());
- std::pair<ListenerMap::iterator, bool> observer_insert_result =
- listeners_.insert(make_pair(
- key, static_cast<base::ObserverList<MDnsListenerImpl>*>(NULL)));
- // If an equivalent key does not exist, actually create the observer list.
- if (observer_insert_result.second)
- observer_insert_result.first->second =
- new base::ObserverList<MDnsListenerImpl>();
+ std::unique_ptr<base::ObserverList<MDnsListenerImpl>>& observer_list =
+ listeners_[key];
- base::ObserverList<MDnsListenerImpl>* observer_list =
- observer_insert_result.first->second;
+ if (!observer_list)
+ observer_list = base::MakeUnique<base::ObserverList<MDnsListenerImpl>>();
observer_list->AddObserver(listener);
}
@@ -385,7 +378,6 @@ void MDnsClientImpl::Core::RemoveListener(MDnsListenerImpl* listener) {
void MDnsClientImpl::Core::CleanupObserverList(const ListenerKey& key) {
ListenerMap::iterator found = listeners_.find(key);
if (found != listeners_.end() && !found->second->might_have_observers()) {
- delete found->second;
listeners_.erase(found);
}
}
diff --git a/chromium/net/dns/mdns_client_impl.h b/chromium/net/dns/mdns_client_impl.h
index ec0536c6264..f86de96f222 100644
--- a/chromium/net/dns/mdns_client_impl.h
+++ b/chromium/net/dns/mdns_client_impl.h
@@ -148,7 +148,8 @@ class NET_EXPORT_PRIVATE MDnsClientImpl : public MDnsClient {
FRIEND_TEST_ALL_PREFIXES(MDnsTest, CacheCleanupWithShortTTL);
typedef std::pair<std::string, uint16_t> ListenerKey;
- typedef std::map<ListenerKey, base::ObserverList<MDnsListenerImpl>*>
+ typedef std::map<ListenerKey,
+ std::unique_ptr<base::ObserverList<MDnsListenerImpl>>>
ListenerMap;
// Alert listeners of an update to the cache.
diff --git a/chromium/net/dns/mojo_host_resolver_impl.cc b/chromium/net/dns/mojo_host_resolver_impl.cc
index f8f08d8b249..e61387ab740 100644
--- a/chromium/net/dns/mojo_host_resolver_impl.cc
+++ b/chromium/net/dns/mojo_host_resolver_impl.cc
@@ -6,7 +6,6 @@
#include <utility>
-#include "base/stl_util.h"
#include "net/base/address_list.h"
#include "net/base/net_errors.h"
#include "net/base/network_interfaces.h"
@@ -26,6 +25,8 @@ class MojoHostResolverImpl::Job {
interfaces::HostResolverRequestClientPtr client);
~Job();
+ void set_iter(std::list<Job>::iterator iter) { iter_ = iter; }
+
void Start();
private:
@@ -36,6 +37,9 @@ class MojoHostResolverImpl::Job {
void OnConnectionError();
MojoHostResolverImpl* resolver_service_;
+ // This Job's iterator in |resolver_service_|, so the Job may be removed on
+ // completion.
+ std::list<Job>::iterator iter_;
net::HostResolver* resolver_;
net::HostResolver::RequestInfo request_info_;
const NetLogWithSource net_log_;
@@ -51,7 +55,6 @@ MojoHostResolverImpl::MojoHostResolverImpl(net::HostResolver* resolver,
MojoHostResolverImpl::~MojoHostResolverImpl() {
DCHECK(thread_checker_.CalledOnValidThread());
- base::STLDeleteElements(&pending_jobs_);
}
void MojoHostResolverImpl::Resolve(
@@ -64,17 +67,17 @@ void MojoHostResolverImpl::Resolve(
// IP address.
request_info->set_host_port_pair(HostPortPair(GetHostName(), 80));
}
- Job* job =
- new Job(this, resolver_, *request_info, net_log_, std::move(client));
- pending_jobs_.insert(job);
+
+ pending_jobs_.emplace_front(this, resolver_, *request_info, net_log_,
+ std::move(client));
+ auto job = pending_jobs_.begin();
+ job->set_iter(job);
job->Start();
}
-void MojoHostResolverImpl::DeleteJob(Job* job) {
+void MojoHostResolverImpl::DeleteJob(std::list<Job>::iterator job) {
DCHECK(thread_checker_.CalledOnValidThread());
- size_t num_erased = pending_jobs_.erase(job);
- DCHECK(num_erased);
- delete job;
+ pending_jobs_.erase(job);
}
MojoHostResolverImpl::Job::Job(
@@ -93,6 +96,9 @@ MojoHostResolverImpl::Job::Job(
}
void MojoHostResolverImpl::Job::Start() {
+ // The caller is responsible for setting up |iter_|.
+ DCHECK_EQ(this, &*iter_);
+
DVLOG(1) << "Resolve " << request_info_.host_port_pair().ToString();
int result =
resolver_->Resolve(request_info_, DEFAULT_PRIORITY, &result_,
@@ -117,7 +123,7 @@ void MojoHostResolverImpl::Job::OnResolveDone(int result) {
DVLOG(1) << address.ToString();
}
client_->ReportResult(result, result_);
- resolver_service_->DeleteJob(this);
+ resolver_service_->DeleteJob(iter_);
}
void MojoHostResolverImpl::Job::OnConnectionError() {
@@ -126,7 +132,7 @@ void MojoHostResolverImpl::Job::OnConnectionError() {
DCHECK(resolver_service_);
DVLOG(1) << "Connection error on request for "
<< request_info_.host_port_pair().ToString();
- resolver_service_->DeleteJob(this);
+ resolver_service_->DeleteJob(iter_);
}
} // namespace net
diff --git a/chromium/net/dns/mojo_host_resolver_impl.h b/chromium/net/dns/mojo_host_resolver_impl.h
index 8c9eb48cc44..cdfa1c8a42d 100644
--- a/chromium/net/dns/mojo_host_resolver_impl.h
+++ b/chromium/net/dns/mojo_host_resolver_impl.h
@@ -5,7 +5,8 @@
#ifndef NET_DNS_MOJO_HOST_RESOLVER_IMPL_H_
#define NET_DNS_MOJO_HOST_RESOLVER_IMPL_H_
-#include <set>
+#include <list>
+#include <memory>
#include "base/macros.h"
#include "base/threading/thread_checker.h"
@@ -36,8 +37,8 @@ class MojoHostResolverImpl {
private:
class Job;
- // Removes |job| from the set of pending jobs, and deletes it.
- void DeleteJob(Job* job);
+ // Removes |job| from the set of pending jobs.
+ void DeleteJob(std::list<Job>::iterator job);
// Resolver for resolving incoming requests. Not owned.
net::HostResolver* resolver_;
@@ -46,8 +47,7 @@ class MojoHostResolverImpl {
const NetLogWithSource net_log_;
// All pending jobs, so they can be cancelled when this service is destroyed.
- // Owns all jobs.
- std::set<Job*> pending_jobs_;
+ std::list<Job> pending_jobs_;
base::ThreadChecker thread_checker_;
diff --git a/chromium/net/dns/mojo_host_resolver_impl_unittest.cc b/chromium/net/dns/mojo_host_resolver_impl_unittest.cc
index 9405c71afb1..1b6722eddbe 100644
--- a/chromium/net/dns/mojo_host_resolver_impl_unittest.cc
+++ b/chromium/net/dns/mojo_host_resolver_impl_unittest.cc
@@ -8,6 +8,7 @@
#include <string>
#include <utility>
+#include "base/memory/ptr_util.h"
#include "base/run_loop.h"
#include "base/time/time.h"
#include "mojo/public/cpp/bindings/binding.h"
@@ -162,7 +163,7 @@ class MojoHostResolverImplTest : public testing::Test {
TEST_F(MojoHostResolverImplTest, Resolve) {
interfaces::HostResolverRequestClientPtr client_ptr;
- TestRequestClient client(mojo::GetProxy(&client_ptr));
+ TestRequestClient client(mojo::MakeRequest(&client_ptr));
resolver_service_->Resolve(CreateRequest("example.com", 80, false),
std::move(client_ptr));
@@ -176,7 +177,7 @@ TEST_F(MojoHostResolverImplTest, Resolve) {
TEST_F(MojoHostResolverImplTest, ResolveSynchronous) {
interfaces::HostResolverRequestClientPtr client_ptr;
- TestRequestClient client(mojo::GetProxy(&client_ptr));
+ TestRequestClient client(mojo::MakeRequest(&client_ptr));
mock_host_resolver_.set_synchronous_mode(true);
@@ -192,9 +193,9 @@ TEST_F(MojoHostResolverImplTest, ResolveSynchronous) {
TEST_F(MojoHostResolverImplTest, ResolveMultiple) {
interfaces::HostResolverRequestClientPtr client1_ptr;
- TestRequestClient client1(mojo::GetProxy(&client1_ptr));
+ TestRequestClient client1(mojo::MakeRequest(&client1_ptr));
interfaces::HostResolverRequestClientPtr client2_ptr;
- TestRequestClient client2(mojo::GetProxy(&client2_ptr));
+ TestRequestClient client2(mojo::MakeRequest(&client2_ptr));
mock_host_resolver_.set_ondemand_mode(true);
@@ -220,9 +221,9 @@ TEST_F(MojoHostResolverImplTest, ResolveMultiple) {
TEST_F(MojoHostResolverImplTest, ResolveDuplicate) {
interfaces::HostResolverRequestClientPtr client1_ptr;
- TestRequestClient client1(mojo::GetProxy(&client1_ptr));
+ TestRequestClient client1(mojo::MakeRequest(&client1_ptr));
interfaces::HostResolverRequestClientPtr client2_ptr;
- TestRequestClient client2(mojo::GetProxy(&client2_ptr));
+ TestRequestClient client2(mojo::MakeRequest(&client2_ptr));
mock_host_resolver_.set_ondemand_mode(true);
@@ -248,7 +249,7 @@ TEST_F(MojoHostResolverImplTest, ResolveDuplicate) {
TEST_F(MojoHostResolverImplTest, ResolveFailure) {
interfaces::HostResolverRequestClientPtr client_ptr;
- TestRequestClient client(mojo::GetProxy(&client_ptr));
+ TestRequestClient client(mojo::MakeRequest(&client_ptr));
resolver_service_->Resolve(CreateRequest("failure.fail", 80, false),
std::move(client_ptr));
@@ -261,7 +262,7 @@ TEST_F(MojoHostResolverImplTest, ResolveFailure) {
TEST_F(MojoHostResolverImplTest, DestroyClient) {
interfaces::HostResolverRequestClientPtr client_ptr;
std::unique_ptr<TestRequestClient> client(
- new TestRequestClient(mojo::GetProxy(&client_ptr)));
+ new TestRequestClient(mojo::MakeRequest(&client_ptr)));
mock_host_resolver_.set_ondemand_mode(true);
diff --git a/chromium/net/dns/mojo_host_struct_traits.cc b/chromium/net/dns/mojo_host_struct_traits.cc
index 9772fd2c139..09f167323a1 100644
--- a/chromium/net/dns/mojo_host_struct_traits.cc
+++ b/chromium/net/dns/mojo_host_struct_traits.cc
@@ -6,6 +6,7 @@
#include <utility>
+#include "base/memory/ptr_util.h"
#include "net/base/address_list.h"
namespace mojo {
diff --git a/chromium/net/dns/serial_worker.cc b/chromium/net/dns/serial_worker.cc
index 8a715f37f83..7ac87cc0666 100644
--- a/chromium/net/dns/serial_worker.cc
+++ b/chromium/net/dns/serial_worker.cc
@@ -97,4 +97,3 @@ void SerialWorker::RetryWork() {
}
} // namespace net
-
diff --git a/chromium/net/dns/serial_worker.h b/chromium/net/dns/serial_worker.h
index c48a61b1e26..14398a8ed0b 100644
--- a/chromium/net/dns/serial_worker.h
+++ b/chromium/net/dns/serial_worker.h
@@ -94,4 +94,3 @@ class NET_EXPORT_PRIVATE SerialWorker
} // namespace net
#endif // NET_DNS_SERIAL_WORKER_H_
-
diff --git a/chromium/net/dns/serial_worker_unittest.cc b/chromium/net/dns/serial_worker_unittest.cc
index 1c544db650a..1f940fefbaf 100644
--- a/chromium/net/dns/serial_worker_unittest.cc
+++ b/chromium/net/dns/serial_worker_unittest.cc
@@ -164,4 +164,3 @@ TEST_F(SerialWorkerTest, ExecuteAndSerializeReads) {
} // namespace
} // namespace net
-
diff --git a/chromium/net/docs/bug-triage-labels.md b/chromium/net/docs/bug-triage-labels.md
index aea97fd9d73..4b4d8b5c34c 100644
--- a/chromium/net/docs/bug-triage-labels.md
+++ b/chromium/net/docs/bug-triage-labels.md
@@ -2,21 +2,6 @@
## Some network component caveats
-* **UI>Browser>Downloads**
-
- Despite the name, this covers all issues related to downloading a file
- except saving entire pages (which is **Blink>SavePage**), not just UI
- issues. Most downloads bugs will have the word "download" or "save as" in
- the description. Issues with the HTTP server for the Chrome binaries are
- not downloads bugs.
-
-* **UI>Browser>SafeBrowsing**
-
- Bugs that have to do with the process by which a URL or file is determined
- to be dangerous based on our databases, or the resulting interstitials.
- Determination of danger based purely on content-type or file extension
- belongs in **UI>Browser>Downloads**, not SafeBrowsing.
-
* **Internals>Network>SSL**
This includes issues that should be also tagged as **Security>UX**
@@ -67,6 +52,21 @@
Bugs in these areas often receive the **Internals>Network** component, though
they fall largely outside the purview of the network stack team:
+* **UI>Browser>Downloads**
+
+ Despite the name, this covers all issues related to downloading a file
+ except saving entire pages (which is **Blink>SavePage**), not just UI
+ issues. Most downloads bugs will have the word "download" or "save as" in
+ the description. Issues with the HTTP server for the Chrome binaries are
+ not downloads bugs.
+
+* **UI>Browser>SafeBrowsing**
+
+ Bugs that have to do with the process by which a URL or file is determined
+ to be dangerous based on our databases, or the resulting interstitials.
+ Determination of danger based purely on content-type or file extension
+ belongs in **UI>Browser>Downloads**, not SafeBrowsing.
+
* **Blink>Forms**
Issues submitting forms, forms having weird data, forms sending the wrong
diff --git a/chromium/net/docs/bug-triage-suggested-workflow.md b/chromium/net/docs/bug-triage-suggested-workflow.md
index 651447669a7..b41944ac6af 100644
--- a/chromium/net/docs/bug-triage-suggested-workflow.md
+++ b/chromium/net/docs/bug-triage-suggested-workflow.md
@@ -6,12 +6,12 @@
* Look at new unconfirmed bugs since noon PST on the last triager's rotation.
[Use this issue tracker
- query](https://code.google.com/p/chromium/issues/list?can=2&q=status%3Aunconfirmed&sort=-id&num=1000).
+ query](https://bugs.chromium.org/p/chromium/issues/list?q=status%3Aunconfirmed&sort=-id&num=1000).
* Read the title of the bug.
-* If a bug looks like it might be network/download/safe-browsing related,
- middle click (or command-click on OSX) to open it in a new tab.
+* If a bug looks like it might be network related, middle click (or
+ command-click on OSX) to open it in a new tab.
* If a user provides a crash ID for a crasher for a bug that could be
net-related, look at the crash stack at
@@ -184,8 +184,8 @@ For each alert that fires, determine if it's a real alert and file a bug if so.
mark it as WontFix.
* On Windows, you may want to look for weird dlls associated with the crashes.
- This generally needs crashes from a fair number of different users to reach
- any conclusions.
+ This generally needs crashes from a fair number of different users to reach
+ any conclusions.
* To get a list of loaded modules in related crash dumps, select
modules->3rd party in the left pane. It can be difficult to distinguish
between safe dlls and those likely to cause problems, but even if you're
diff --git a/chromium/net/docs/bug-triage.md b/chromium/net/docs/bug-triage.md
index 22b61b61a04..b257802ae87 100644
--- a/chromium/net/docs/bug-triage.md
+++ b/chromium/net/docs/bug-triage.md
@@ -91,7 +91,7 @@ uniform, predictable two day commitment for all triagers.
its status should be set to Available. Future triagers should ignore bugs
with this status, unless investigating stale bugs.
-* Follow up on [Needs-Feedback issues for all components owned by the network stack team](https://bugs.chromium.org/p/chromium/issues/list?can=2&q=component%3AInternals%3ENetwork%2CUI%3EBrowser%3EDownloads+-component%3AInternals%3ENetwork%3EDataProxy+-component%3AInternals%3ENetwork%3EDataUse+-component%3AInternals%3ENetwork%3EVPN+Needs%3DFeedback&sort=-modified).
+* Follow up on [Needs-Feedback issues for all components owned by the network stack team](https://bugs.chromium.org/p/chromium/issues/list?q=component%3AInternals%3ENetwork+-component%3AInternals%3ENetwork%3EDataProxy+-component%3AInternals%3ENetwork%3EDataUse+-component%3AInternals%3ENetwork%3EVPN+Needs%3DFeedback&sort=-modified).
* Remove label once feedback is provided. Continue to investigate, if
the previous section applies.
diff --git a/chromium/net/docs/crash-course-in-net-internals.md b/chromium/net/docs/crash-course-in-net-internals.md
index 529c7d2c2a7..9187f858e3b 100644
--- a/chromium/net/docs/crash-course-in-net-internals.md
+++ b/chromium/net/docs/crash-course-in-net-internals.md
@@ -14,77 +14,138 @@ about:net-internals provides a view of browser activity from net/'s perspective.
For this reason, it lacks knowledge of tabs, navigation, frames, resource types,
etc.
-The top level network stack object is the URLRequestContext. The Events View
+The leftmost column presents a list of views. Most debugging is done with the
+Events view, which will be all this document covers.
+
+The top level network stack object is the URLRequestContext. The Events view
has information for all Chrome URLRequestContexts that are hooked up to the
-single, global, ChromeNetLog object. This includes both incognito and non-
-incognito profiles, among other things. The Events view only shows events for
-the period that net-internals was open and running, and is incrementally updated
-as events occur. The code attempts to add a top level event for URLRequests
-that were active when the tab was opened, to help debug hung requests, but
-that's best-effort only, and only includes requests for the current profile and
-the system URLRequestContext.
+single, global, ChromeNetLog object. This includes both incognito and
+non-incognito profiles, among other things. The Events view only shows events
+for the period that net-internals was open and running, and is incrementally
+updated as events occur. The code attempts to add a top level event for
+URLRequests that were active when the about:net-internals tab was opened, to
+help debug hung requests, but that's best-effort only, and only includes
+requests for the current profile and the system URLRequestContext.
The other views are all snapshots of the current state of the main
URLRequestContext's components, and are updated on a 5 second timer. These will
-show objects that were created before about:net-internals was opened. Most
-debugging is done with the Events view (which will be all this document
-covers), but it's good to be aware of this distinction.
+show objects that were created before about:net-internals was opened.
# Events vs Sources
-The Event View shows events logged by the NetLog. The NetLog model is that
+The Events view shows events logged by the NetLog. The NetLog model is that
long-lived network stack objects, called sources, emit events over their
-lifetime. When looking at the code, a "NetLogWithSource" object contains a source
-ID, and a pointer to the NetLog the source emits events to. Some events have a
-beginning and end point (during which other subevents may occur), and some only
-occur at a single point in time. Generally only one event can be occuring for a
-source at a time. If there can be multiple events doing completely independent
-thing, the code often uses new sources to represent the parallelism.
+lifetime. A NetLogWithSource object contains a source ID, a NetLogSourceType,
+and a pointer to the NetLog the source emits events to.
+
+The Events view has a list of sources in a column adjacent to the list of views.
+Sources that include an event with a net_error parameter with negative value
+(that is, some kind of ERR_) are shown with red background. Sources whose
+opening event has not ended yet are shown with white background. Other events
+have green background. The search queries corresponding to the first two kinds
+are `is:error` and `is:active`.
+
+When one or more sources are selected, corresponding events show up in another
+column to the right, sorted by source, and by time within each source. There
+are two time values: t is measured from some reference point common to all
+sources, and st is measured from the first event for each source. Time is
+displayed in milliseconds.
+
+Since the network stack is asynchronous, events from different sources will
+often be interlaced in time, but Events view does not feature showing events from
+different sources ordered by time. Large time gaps in the event list of a
+single source usually mean that time is spent in the context of another source.
+
+Some events come in pairs: a beginning and end event, between which other events
+may occur. They are shown with + and - prefixes, respectively. The begin event
+has a dt value which shows the duration. If the end event was captured, then
+duration is calculated as the time difference between the begin and the end
+events. Otherwise the time elapsed from the begin event until capturing
+was stopped is displayed (a lower bound for actual duration), followed by a +
+sign (for example, "dt=120+").
+
+If there are no other events in between the begin and end, and the end event has
+no parameters, then they are collapsed in a single line without a sign prefix.
+
+Some other events only occur at a single point in time, and will not have either
+a sign prefix, or a dt duration value.
+
+Generally only one event can be occuring for a source at a time. If there can
+be multiple events doing completely independent things, the code often uses new
+sources to represent the parallelism.
+
+Most, but not all events correspond to a source. Exceptions are global events,
+which have no source, and show up as individual entries in the source list.
+Examples of global events include NETWORK_CHANGED, DNS_CONFIG_CHANGED, and
+PROXY_CONFIG_CHANGED.
+
+# Common source types
"Sources" correspond to certain net objects, however, multiple layers of net/
will often log to a single source. Here are the main source types and what they
-include (Excluding HTTP2 [SPDY]/QUIC):
+include (excluding HTTP2 [SPDY]/QUIC):
* URL_REQUEST: This corresponds to the URLRequest object. It includes events
from all the URLRequestJobs, HttpCache::Transactions, NetworkTransactions,
HttpStreamFactoryImpl::Requests, HttpStream implementations, and
HttpStreamParsers used to service a response. If the URL_REQUEST follows HTTP
redirects, it will include each redirect. This is a lot of stuff, but generally
-only object is doing work at a time. This event source includes the full URL
-and generally includes the request / response headers (Except when the cache
+only one object is doing work at a time. This event source includes the full
+URL and generally includes the request / response headers (except when the cache
handles the response).
-* HTTP_STREAM_JOB: This corresponds to HttpStreamFactoryImpl::Job (Note that
+* HTTP_STREAM_JOB: This corresponds to HttpStreamFactoryImpl::Job (note that
one Request can have multiple Jobs). It also includes its proxy and DNS
-lookups. HTTP_STREAM_JOB log events are separate from URL_REQUEST because
-two stream jobs may be created and races against each other, in some cases -
-one for one for QUIC, and one for HTTP. One of the final events of this source
-indicates how an HttpStream was created (Reusing an existing SOCKET /
-HTTP2_SESSION / QUIC_SESSION, or creating a new one).
-
-* CONNECT_JOB: This corresponds to the ConnectJob subclasses that each socket
-pool uses. A successful CONNECT_JOB return a SOCKET. The events here vary a
+lookups. HTTP_STREAM_JOB log events are separate from URL_REQUEST because two
+stream jobs may be created and races against each other, in some cases -- one
+for QUIC, and one for HTTP.
+
+ One of the final events of this source, before the
+ HTTP_STREAM_JOB_BOUND_TO_REQUEST event, indicates how an HttpStream was
+ created:
+
+ + A SOCKET_POOL_BOUND_TO_CONNECT_JOB event means that a new TCP socket was
+ created, whereas a SOCKET_POOL_REUSED_AN_EXISTING_SOCKET event indicates that
+ an existing TCP socket was reused for a non-HTTP/2 request.
+
+ + An HTTP2_SESSION_POOL_IMPORTED_SESSION_FROM_SOCKET event indicates that a
+ new HTTP/2 session was opened by this Job.
+
+ + An HTTP2_SESSION_POOL_FOUND_EXISTING_SESSION event indicates that the request
+ was served on a preexisting HTTP/2 session.
+
+ + An HTTP2_SESSION_POOL_FOUND_EXISTING_SESSION_FROM_IP_POOL event means that
+ the request was pooled to a preexisting HTTP/2 session which had a different
+ SpdySessionKey, but DNS resolution resulted in the same IP, and the
+ certificate matches.
+
+ + There are currently no events logged for opening new QUIC sessions or
+ reusing existing ones.
+
+* \*_CONNECT_JOB: This corresponds to the ConnectJob subclasses that each socket
+pool uses. A successful CONNECT_JOB returns a SOCKET. The events here vary a
lot by job type. Their main event is generally either to create a socket, or
-request a socket from another socket pool (Which creates another CONNECT_JOB)
-and then do some extra work on top of that - like establish an SSL connection on
+request a socket from another socket pool (which creates another CONNECT_JOB)
+and then do some extra work on top of that -- like establish an SSL connection on
top of a TCP connection.
* SOCKET: These correspond to TCPSockets, but may also have other classes
-layered on top of them (Like an SSLClientSocket). This is a bit different from
+layered on top of them (like an SSLClientSocket). This is a bit different from
the other classes, where the name corresponds to the topmost class, instead of
the bottommost one. This is largely an artifact of the fact the socket is
-created first, and then SSL (Or a proxy connection) is layered on top of it.
+created first, and then SSL (or a proxy connection) is layered on top of it.
SOCKETs may be reused between multiple requests, and a request may end up
getting a socket created for another request.
-* HOST_RESOLVER_IMPL_JOB: These correspond to HostResolverImpl::Job. The
+* HOST_RESOLVER_IMPL_JOB: These correspond to HostResolverImpl::Job. They
include information about how long the lookup was queued, each DNS request that
-was attempted (With the platform or built-in resolver) and all the other sources
+was attempted (with the platform or built-in resolver) and all the other sources
that are waiting on the job.
-When one source depends on another, the code generally logs an event with
-"source_dependency" value to both sources, which lets you jump between the two
-related events.
+When one source depends on another, the code generally logs an event at both
+sources with a `source_dependency` value pointing to the other source. These
+are clickable in the UI, adding the referred source to the list of selected
+sources.
# Debugging
@@ -96,9 +157,9 @@ you can search for "redirect". However, you often won't have much information
about the actual problem. There are two filters in net-internals that can help
in a lot of cases:
-* "type:URL_REQUEST is:error" will restrict the list to URL_REQUEST object with
-an error of some sort (red background). Cache errors are often non-fatal, so
-you should generally ignore those, and look for a more interesting one.
+* "type:URL_REQUEST is:error" will restrict the source list to URL_REQUEST
+objects with an error of some sort. Cache errors are often non-fatal, so you
+should generally ignore those, and look for a more interesting one.
* "type:URL_REQUEST sort:duration" will show the longest-lived requests first.
This is often useful in finding hung or slow requests.
@@ -107,14 +168,11 @@ For a list of other filter commands, you can mouse over the question mark on
about:net-internals.
Once you locate the problematic request, the next is to figure out where the
-problem is - it's often one of the last events, though it could also be related
-to response or request headers. You can use "source_dependency" links to drill
-down into other related sources, or up from layers below URL_REQUEST.
-
-You can use the name of an event to search for the code responsible for that
-event, and try to deduce what went wrong before/after a particular event. Note
-that the event names used in net-internals are not the entire string names, so
-you should not do an entire string match.
+problem is -- it's often one of the last events, though it could also be related
+to response or request headers. You can use `source_dependency` links to
+navigate between related sources. You can use the name of an event to search
+for the code responsible for that event, and try to deduce what went wrong
+before/after a particular event.
Some things to look for while debugging:
@@ -122,8 +180,7 @@ Some things to look for while debugging:
* Changing networks and entering / exiting suspend mode can have all sorts of
fun and exciting effects on underway network activity. Network changes log a
-top level NETWORK_CHANGED event with no source - the event itself is treated as
-its own source. Suspend events are currently not logged.
+top level NETWORK_CHANGED event. Suspend events are currently not logged.
* URL_REQUEST_DELEGATE / DELEGATE_INFO events mean a URL_REQUEST is blocked on a
URLRequest::Delegate or the NetworkDelegate, which are implemented outside the
@@ -136,7 +193,8 @@ ResourceDispatcherHost.
* Sockets are often reused between requests. If a request is on a stale
(reused) socket, what was the previous request that used the socket, how long
-ago was it made?
+ago was it made? (Look at SOCKET_IN_USE events, and the HTTP_STREAM_JOBS they
+point to via the `source_dependency` value.)
* SSL negotation is a process fraught with peril, particularly with broken
proxies. These will generally stall or fail in the SSL_CONNECT phase at the
@@ -146,15 +204,15 @@ SOCKET layer.
issued by the media and PDF code.
* Late binding: HTTP_STREAM_JOBs are not associated with any CONNECT_JOB until
-a CONNECT_JOB actually connects. This is so the highest priority pending job
-gets the first available socket (Which may be a new socket, or an old one that's
-freed up). For this reason, it can be a little tricky to relate hung
-HTTP_STREAM_JOBs to CONNECT_JOBs.
+a CONNECT_JOB actually connects. This is so the highest priority pending
+HTTP_STREAM_JOB gets the first available socket (which may be a new socket, or
+an old one that's freed up). For this reason, it can be a little tricky to
+relate hung HTTP_STREAM_JOBs to CONNECT_JOBs.
* Each CONNECT_JOB belongs to a "group", which has a limit of 6 connections. If
-all CONNECT_JOBs beling to a group (The CONNECT_JOB's description field) are
+all CONNECT_JOBs belonging to a group (the CONNECT_JOB's description field) are
stalled waiting on an available socket, the group probably has 6 sockets that
-that are hung - either hung trying to connect, or used by stalled requests and
+that are hung -- either hung trying to connect, or used by stalled requests and
thus outside the socket pool's control.
* There's a limit on number of DNS resolutions that can be started at once. If
diff --git a/chromium/net/extras/sqlite/sqlite_channel_id_store.cc b/chromium/net/extras/sqlite/sqlite_channel_id_store.cc
index 238577fd18d..ebcf7ec74ba 100644
--- a/chromium/net/extras/sqlite/sqlite_channel_id_store.cc
+++ b/chromium/net/extras/sqlite/sqlite_channel_id_store.cc
@@ -227,8 +227,7 @@ void SQLiteChannelIDStore::Backend::LoadInBackground(
smt.ColumnBlobAsVector(2, &public_key_from_db);
std::unique_ptr<crypto::ECPrivateKey> key(
crypto::ECPrivateKey::CreateFromEncryptedPrivateKeyInfo(
- ChannelIDService::kEPKIPassword, private_key_from_db,
- public_key_from_db));
+ private_key_from_db, public_key_from_db));
if (!key)
continue;
std::unique_ptr<DefaultChannelIDStore::ChannelID> channel_id(
@@ -498,8 +497,7 @@ void SQLiteChannelIDStore::Backend::Commit() {
add_statement.Reset(true);
add_statement.BindString(0, po->channel_id().server_identifier());
std::vector<uint8_t> private_key, public_key;
- if (!po->channel_id().key()->ExportEncryptedPrivateKey(
- ChannelIDService::kEPKIPassword, 1, &private_key))
+ if (!po->channel_id().key()->ExportEncryptedPrivateKey(&private_key))
continue;
if (!po->channel_id().key()->ExportPublicKey(&public_key))
continue;
diff --git a/chromium/net/extras/sqlite/sqlite_channel_id_store.h b/chromium/net/extras/sqlite/sqlite_channel_id_store.h
index fc85458c43e..9a5901d293a 100644
--- a/chromium/net/extras/sqlite/sqlite_channel_id_store.h
+++ b/chromium/net/extras/sqlite/sqlite_channel_id_store.h
@@ -19,8 +19,6 @@ class FilePath;
class SequencedTaskRunner;
}
-class GURL;
-
namespace net {
// Implements the DefaultChannelIDStore::PersistentStore interface
diff --git a/chromium/net/extras/sqlite/sqlite_channel_id_store_unittest.cc b/chromium/net/extras/sqlite/sqlite_channel_id_store_unittest.cc
index 8be7a4b5f03..7c9b223e3e1 100644
--- a/chromium/net/extras/sqlite/sqlite_channel_id_store_unittest.cc
+++ b/chromium/net/extras/sqlite/sqlite_channel_id_store_unittest.cc
@@ -65,8 +65,8 @@ class SQLiteChannelIDStoreTest : public testing::Test {
ASSERT_TRUE(asn1::ExtractSPKIFromDERCert(*cert_data, &spki));
std::vector<uint8_t> public_key(spki.size());
memcpy(public_key.data(), spki.data(), spki.size());
- *key = crypto::ECPrivateKey::CreateFromEncryptedPrivateKeyInfo(
- ChannelIDService::kEPKIPassword, private_key, public_key);
+ *key = crypto::ECPrivateKey::CreateFromEncryptedPrivateKeyInfo(private_key,
+ public_key);
}
static base::Time GetTestCertExpirationTime() {
@@ -84,7 +84,9 @@ class SQLiteChannelIDStoreTest : public testing::Test {
exploded_time.minute = 22;
exploded_time.second = 39;
exploded_time.millisecond = 0;
- return base::Time::FromUTCExploded(exploded_time);
+ base::Time out_time;
+ EXPECT_TRUE(base::Time::FromUTCExploded(exploded_time, &out_time));
+ return out_time;
}
static base::Time GetTestCertCreationTime() {
@@ -98,7 +100,9 @@ class SQLiteChannelIDStoreTest : public testing::Test {
exploded_time.minute = 22;
exploded_time.second = 39;
exploded_time.millisecond = 0;
- return base::Time::FromUTCExploded(exploded_time);
+ base::Time out_time;
+ EXPECT_TRUE(base::Time::FromUTCExploded(exploded_time, &out_time));
+ return out_time;
}
void SetUp() override {
diff --git a/chromium/net/extras/sqlite/sqlite_persistent_cookie_store.h b/chromium/net/extras/sqlite/sqlite_persistent_cookie_store.h
index b8c1caad5eb..6350457d37d 100644
--- a/chromium/net/extras/sqlite/sqlite_persistent_cookie_store.h
+++ b/chromium/net/extras/sqlite/sqlite_persistent_cookie_store.h
@@ -15,8 +15,6 @@
#include "base/memory/ref_counted.h"
#include "net/cookies/cookie_monster.h"
-class Task;
-
namespace base {
class FilePath;
class SequencedTaskRunner;
diff --git a/chromium/net/filter/gzip_source_stream.cc b/chromium/net/filter/gzip_source_stream.cc
index de1a2de33cb..aff449f4b94 100644
--- a/chromium/net/filter/gzip_source_stream.cc
+++ b/chromium/net/filter/gzip_source_stream.cc
@@ -10,6 +10,7 @@
#include "base/bind.h"
#include "base/bit_cast.h"
#include "base/logging.h"
+#include "base/memory/ref_counted.h"
#include "net/base/io_buffer.h"
#include "third_party/zlib/zlib.h"
@@ -21,6 +22,14 @@ const char kDeflate[] = "DEFLATE";
const char kGzip[] = "GZIP";
const char kGzipFallback[] = "GZIP_FALLBACK";
+// For deflate streams, if more than this many bytes have been received without
+// an error and without adding a Zlib header, assume the original stream had a
+// Zlib header. In practice, don't need nearly this much data, but since the
+// detection logic is a heuristic, best to be safe. Data is freed once it's been
+// determined whether the stream has a zlib header or not, so larger values
+// shouldn't affect memory usage, in practice.
+const int kMaxZlibHeaderSniffBytes = 1000;
+
} // namespace
GzipSourceStream::~GzipSourceStream() {
@@ -42,9 +51,9 @@ std::unique_ptr<GzipSourceStream> GzipSourceStream::Create(
GzipSourceStream::GzipSourceStream(std::unique_ptr<SourceStream> upstream,
SourceStream::SourceType type)
: FilterSourceStream(type, std::move(upstream)),
- zlib_header_added_(false),
gzip_footer_bytes_left_(0),
- input_state_(STATE_START) {}
+ input_state_(STATE_START),
+ replay_state_(STATE_COMPRESSED_BODY) {}
bool GzipSourceStream::Init() {
zlib_stream_.reset(new z_stream);
@@ -81,7 +90,7 @@ int GzipSourceStream::FilterData(IOBuffer* output_buffer,
IOBuffer* input_buffer,
int input_buffer_size,
int* consumed_bytes,
- bool /*upstream_end_reached*/) {
+ bool upstream_end_reached) {
*consumed_bytes = 0;
char* input_data = input_buffer->data();
int input_data_size = input_buffer_size;
@@ -92,7 +101,7 @@ int GzipSourceStream::FilterData(IOBuffer* output_buffer,
switch (state) {
case STATE_START: {
if (type() == TYPE_DEFLATE) {
- input_state_ = STATE_COMPRESSED_BODY;
+ input_state_ = STATE_SNIFFING_DEFLATE_HEADER;
break;
}
// If this stream is not really gzipped as detected by
@@ -106,6 +115,8 @@ int GzipSourceStream::FilterData(IOBuffer* output_buffer,
break;
}
case STATE_GZIP_HEADER: {
+ DCHECK_NE(TYPE_DEFLATE, type());
+
const size_t kGzipFooterBytes = 8;
const char* end = nullptr;
GZipHeader::Status status =
@@ -125,11 +136,9 @@ int GzipSourceStream::FilterData(IOBuffer* output_buffer,
}
break;
}
- case STATE_COMPRESSED_BODY: {
- DCHECK(!state_compressed_entered);
- DCHECK_LE(0, input_data_size);
+ case STATE_SNIFFING_DEFLATE_HEADER: {
+ DCHECK_EQ(TYPE_DEFLATE, type());
- state_compressed_entered = true;
zlib_stream_.get()->next_in = bit_cast<Bytef*>(input_data);
zlib_stream_.get()->avail_in = input_data_size;
zlib_stream_.get()->next_out = bit_cast<Bytef*>(output_buffer->data());
@@ -137,24 +146,84 @@ int GzipSourceStream::FilterData(IOBuffer* output_buffer,
int ret = inflate(zlib_stream_.get(), Z_NO_FLUSH);
- // Sometimes misconfigured servers omit the zlib header, relying on
- // clients to splice it back in.
- if (ret < 0 && !zlib_header_added_) {
- zlib_header_added_ = true;
+ // On error, try adding a zlib header and replaying the response. Note
+ // that data just received doesn't have to be replayed, since it hasn't
+ // been removed from input_data yet, only data from previous FilterData
+ // calls needs to be replayed.
+ if (ret != Z_STREAM_END && ret != Z_OK) {
if (!InsertZlibHeader())
return ERR_CONTENT_DECODING_FAILED;
- zlib_stream_.get()->next_in = bit_cast<Bytef*>(input_data);
- zlib_stream_.get()->avail_in = input_data_size;
- zlib_stream_.get()->next_out =
- bit_cast<Bytef*>(output_buffer->data());
- zlib_stream_.get()->avail_out = output_buffer_size;
+ input_state_ = STATE_REPLAY_DATA;
+ // |replay_state_| should still have its initial value.
+ DCHECK_EQ(STATE_COMPRESSED_BODY, replay_state_);
+ break;
+ }
- ret = inflate(zlib_stream_.get(), Z_NO_FLUSH);
- // TODO(xunjieli): add a histogram to see how often this happens. The
- // original bug for this behavior was ancient and maybe it doesn't
- // happen in the wild any more? crbug.com/649339
+ int bytes_used = input_data_size - zlib_stream_.get()->avail_in;
+ bytes_out = output_buffer_size - zlib_stream_.get()->avail_out;
+ // If any bytes are output, enough total bytes have been received, or at
+ // the end of the stream, assume the response had a valid Zlib header.
+ if (bytes_out > 0 ||
+ bytes_used + replay_data_.size() >= kMaxZlibHeaderSniffBytes ||
+ ret == Z_STREAM_END) {
+ std::move(replay_data_);
+ if (ret == Z_STREAM_END) {
+ input_state_ = STATE_GZIP_FOOTER;
+ } else {
+ input_state_ = STATE_COMPRESSED_BODY;
+ }
+ } else {
+ replay_data_.append(input_data, bytes_used);
}
+
+ input_data_size -= bytes_used;
+ input_data += bytes_used;
+ break;
+ }
+ case STATE_REPLAY_DATA: {
+ DCHECK_EQ(TYPE_DEFLATE, type());
+
+ if (replay_data_.empty()) {
+ std::move(replay_data_);
+ input_state_ = replay_state_;
+ break;
+ }
+
+ // Call FilterData recursively, after updating |input_state_|, with
+ // |replay_data_|. This recursive call makes handling data from
+ // |replay_data_| and |input_buffer| much simpler than the alternative
+ // operations, though it's not pretty.
+ input_state_ = replay_state_;
+ int bytes_used;
+ scoped_refptr<IOBuffer> replay_buffer(
+ new WrappedIOBuffer(replay_data_.data()));
+ int result =
+ FilterData(output_buffer, output_buffer_size, replay_buffer.get(),
+ replay_data_.size(), &bytes_used, upstream_end_reached);
+ replay_data_.erase(0, bytes_used);
+ // Back up resulting state, and return state to STATE_REPLAY_DATA.
+ replay_state_ = input_state_;
+ input_state_ = STATE_REPLAY_DATA;
+
+ // On error, or if bytes were read, just return result immediately.
+ // Could continue consuming data in the success case, but simplest not
+ // to.
+ if (result != 0)
+ return result;
+ break;
+ }
+ case STATE_COMPRESSED_BODY: {
+ DCHECK(!state_compressed_entered);
+ DCHECK_LE(0, input_data_size);
+
+ state_compressed_entered = true;
+ zlib_stream_.get()->next_in = bit_cast<Bytef*>(input_data);
+ zlib_stream_.get()->avail_in = input_data_size;
+ zlib_stream_.get()->next_out = bit_cast<Bytef*>(output_buffer->data());
+ zlib_stream_.get()->avail_out = output_buffer_size;
+
+ int ret = inflate(zlib_stream_.get(), Z_NO_FLUSH);
if (ret != Z_STREAM_END && ret != Z_OK)
return ERR_CONTENT_DECODING_FAILED;
diff --git a/chromium/net/filter/gzip_source_stream.h b/chromium/net/filter/gzip_source_stream.h
index 46f296af0c3..1a038049351 100644
--- a/chromium/net/filter/gzip_source_stream.h
+++ b/chromium/net/filter/gzip_source_stream.h
@@ -9,8 +9,6 @@
#include <string>
#include "base/macros.h"
-#include "base/memory/ref_counted.h"
-#include "net/base/io_buffer.h"
#include "net/base/net_export.h"
#include "net/filter/filter_source_stream.h"
#include "net/filter/gzip_header.h"
@@ -44,6 +42,16 @@ class NET_EXPORT_PRIVATE GzipSourceStream : public FilterSourceStream {
STATE_START,
// Gzip header of the input stream is being processed.
STATE_GZIP_HEADER,
+ // Deflate responses may or may not have a zlib header. In this state until
+ // enough has been inflated that this stream most likely has a zlib header,
+ // or until a zlib header has been added. Data is appended to |replay_data_|
+ // in case it needs to be replayed after adding a header.
+ STATE_SNIFFING_DEFLATE_HEADER,
+ // If a zlib header has to be added to the response, this state will replay
+ // data passed to inflate before it was determined that no zlib header was
+ // present.
+ // See https://crbug.com/677001
+ STATE_REPLAY_DATA,
// The input stream is being decoded.
STATE_COMPRESSED_BODY,
// Gzip footer of the input stream is being processed.
@@ -84,9 +92,10 @@ class NET_EXPORT_PRIVATE GzipSourceStream : public FilterSourceStream {
// FilterData(), with InsertZlibHeader() being the exception as a workaround.
std::unique_ptr<z_stream> zlib_stream_;
- // A flag used by FilterData() to record whether we've successfully added
- // a zlib header to this stream.
- bool zlib_header_added_;
+ // While in STATE_SNIFFING_DEFLATE_HEADER, it may be determined that a zlib
+ // header needs to be added, and all received data needs to be replayed. In
+ // that case, this buffer holds the data to be replayed.
+ std::string replay_data_;
// Used to parse the gzip header in gzip stream.
// It is used when the decoding mode is GZIP_SOURCE_STREAM_GZIP.
@@ -98,6 +107,9 @@ class NET_EXPORT_PRIVATE GzipSourceStream : public FilterSourceStream {
// Tracks the state of the input stream.
InputState input_state_;
+ // Used when replaying data.
+ InputState replay_state_;
+
DISALLOW_COPY_AND_ASSIGN(GzipSourceStream);
};
diff --git a/chromium/net/filter/gzip_source_stream_unittest.cc b/chromium/net/filter/gzip_source_stream_unittest.cc
index f0cb1802a47..ed4daaf9b45 100644
--- a/chromium/net/filter/gzip_source_stream_unittest.cc
+++ b/chromium/net/filter/gzip_source_stream_unittest.cc
@@ -26,17 +26,31 @@ namespace {
const int kBigBufferSize = 4096;
const int kSmallBufferSize = 1;
+enum class ReadResultType {
+ // Each call to AddReadResult is a separate read from the lower layer
+ // SourceStream.
+ EVERYTHING_AT_ONCE,
+ // Whenever AddReadResult is called, each byte is actually a separate read
+ // result.
+ ONE_BYTE_AT_A_TIME,
+};
+
// How many bytes to leave unused at the end of |source_data_|. This margin is
// present so that tests that need to append data after the zlib EOF do not run
// out of room in the output buffer.
const size_t kEOFMargin = 64;
struct GzipTestParam {
- GzipTestParam(int buf_size, MockSourceStream::Mode read_mode)
- : buffer_size(buf_size), mode(read_mode) {}
+ GzipTestParam(int buf_size,
+ MockSourceStream::Mode read_mode,
+ ReadResultType read_result_type)
+ : buffer_size(buf_size),
+ mode(read_mode),
+ read_result_type(read_result_type) {}
const int buffer_size;
const MockSourceStream::Mode mode;
+ const ReadResultType read_result_type;
};
} // namespace
@@ -63,19 +77,23 @@ class GzipSourceStreamTest : public ::testing::TestWithParam<GzipTestParam> {
output_buffer_ = new IOBuffer(output_buffer_size_);
std::unique_ptr<MockSourceStream> source(new MockSourceStream());
+ if (GetParam().read_result_type == ReadResultType::ONE_BYTE_AT_A_TIME)
+ source->set_read_one_byte_at_a_time(true);
source_ = source.get();
stream_ = GzipSourceStream::Create(std::move(source), type);
}
- // If MockSourceStream::Mode is ASYNC, completes 1 read from |mock_stream| and
- // wait for |callback| to complete. If Mode is not ASYNC, does nothing and
- // returns |previous_result|.
- int CompleteReadIfAsync(int previous_result,
- TestCompletionCallback* callback,
- MockSourceStream* mock_stream) {
+ // If MockSourceStream::Mode is ASYNC, completes reads from |mock_stream|
+ // until there's no pending read, and then returns |callback|'s result, once
+ // it's invoked. If Mode is not ASYNC, does nothing and returns
+ // |previous_result|.
+ int CompleteReadsIfAsync(int previous_result,
+ TestCompletionCallback* callback,
+ MockSourceStream* mock_stream) {
if (GetParam().mode == MockSourceStream::ASYNC) {
EXPECT_EQ(ERR_IO_PENDING, previous_result);
- mock_stream->CompleteNextRead();
+ while (mock_stream->awaiting_completion())
+ mock_stream->CompleteNextRead();
return callback->WaitForResult();
}
return previous_result;
@@ -104,7 +122,7 @@ class GzipSourceStreamTest : public ::testing::TestWithParam<GzipTestParam> {
int rv = stream_->Read(output_buffer(), output_buffer_size(),
callback.callback());
if (rv == ERR_IO_PENDING)
- rv = CompleteReadIfAsync(rv, &callback, source());
+ rv = CompleteReadsIfAsync(rv, &callback, source());
if (rv == OK)
break;
if (rv < OK)
@@ -133,15 +151,34 @@ class GzipSourceStreamTest : public ::testing::TestWithParam<GzipTestParam> {
INSTANTIATE_TEST_CASE_P(
GzipSourceStreamTests,
GzipSourceStreamTest,
- ::testing::Values(GzipTestParam(kBigBufferSize, MockSourceStream::SYNC),
- GzipTestParam(kSmallBufferSize, MockSourceStream::SYNC),
- GzipTestParam(kBigBufferSize, MockSourceStream::ASYNC),
+ ::testing::Values(GzipTestParam(kBigBufferSize,
+ MockSourceStream::SYNC,
+ ReadResultType::EVERYTHING_AT_ONCE),
+ GzipTestParam(kSmallBufferSize,
+ MockSourceStream::SYNC,
+ ReadResultType::EVERYTHING_AT_ONCE),
+ GzipTestParam(kBigBufferSize,
+ MockSourceStream::ASYNC,
+ ReadResultType::EVERYTHING_AT_ONCE),
GzipTestParam(kSmallBufferSize,
- MockSourceStream::ASYNC)));
+ MockSourceStream::ASYNC,
+ ReadResultType::EVERYTHING_AT_ONCE),
+ GzipTestParam(kBigBufferSize,
+ MockSourceStream::SYNC,
+ ReadResultType::ONE_BYTE_AT_A_TIME),
+ GzipTestParam(kSmallBufferSize,
+ MockSourceStream::SYNC,
+ ReadResultType::ONE_BYTE_AT_A_TIME),
+ GzipTestParam(kBigBufferSize,
+ MockSourceStream::ASYNC,
+ ReadResultType::ONE_BYTE_AT_A_TIME),
+ GzipTestParam(kSmallBufferSize,
+ MockSourceStream::ASYNC,
+ ReadResultType::ONE_BYTE_AT_A_TIME)));
TEST_P(GzipSourceStreamTest, EmptyStream) {
Init(SourceStream::TYPE_DEFLATE);
- source()->AddReadResult("", 0, OK, GetParam().mode);
+ source()->AddReadResult(nullptr, 0, OK, GetParam().mode);
TestCompletionCallback callback;
std::string actual_output;
int result = ReadStream(&actual_output);
@@ -153,7 +190,7 @@ TEST_P(GzipSourceStreamTest, DeflateOneBlock) {
Init(SourceStream::TYPE_DEFLATE);
source()->AddReadResult(encoded_data(), encoded_data_len(), OK,
GetParam().mode);
- source()->AddReadResult(encoded_data(), 0, OK, GetParam().mode);
+ source()->AddReadResult(nullptr, 0, OK, GetParam().mode);
std::string actual_output;
int rv = ReadStream(&actual_output);
EXPECT_EQ(static_cast<int>(source_data_len()), rv);
@@ -165,7 +202,7 @@ TEST_P(GzipSourceStreamTest, GzipOneBloc) {
Init(SourceStream::TYPE_GZIP);
source()->AddReadResult(encoded_data(), encoded_data_len(), OK,
GetParam().mode);
- source()->AddReadResult(encoded_data(), 0, OK, GetParam().mode);
+ source()->AddReadResult(nullptr, 0, OK, GetParam().mode);
std::string actual_output;
int rv = ReadStream(&actual_output);
EXPECT_EQ(static_cast<int>(source_data_len()), rv);
@@ -178,8 +215,7 @@ TEST_P(GzipSourceStreamTest, DeflateTwoReads) {
source()->AddReadResult(encoded_data(), 10, OK, GetParam().mode);
source()->AddReadResult(encoded_data() + 10, encoded_data_len() - 10, OK,
GetParam().mode);
- source()->AddReadResult(encoded_data() + encoded_data_len(), 0, OK,
- GetParam().mode);
+ source()->AddReadResult(nullptr, 0, OK, GetParam().mode);
std::string actual_output;
int rv = ReadStream(&actual_output);
EXPECT_EQ(static_cast<int>(source_data_len()), rv);
@@ -196,7 +232,7 @@ TEST_P(GzipSourceStreamTest, PassThroughAfterEOF) {
source()->AddReadResult(encoded_data_with_trailing_data.c_str(),
encoded_data_len() + sizeof(test_data), OK,
GetParam().mode);
- source()->AddReadResult(encoded_data(), 0, OK, GetParam().mode);
+ source()->AddReadResult(nullptr, 0, OK, GetParam().mode);
// Compressed and uncompressed data get returned as separate Read() results,
// so this test has to call Read twice.
std::string actual_output;
@@ -214,7 +250,7 @@ TEST_P(GzipSourceStreamTest, MissingZlibHeader) {
source()->AddReadResult(encoded_data() + kZlibHeaderLen,
encoded_data_len() - kZlibHeaderLen, OK,
GetParam().mode);
- source()->AddReadResult(encoded_data(), 0, OK, GetParam().mode);
+ source()->AddReadResult(nullptr, 0, OK, GetParam().mode);
std::string actual_output;
int rv = ReadStream(&actual_output);
EXPECT_EQ(static_cast<int>(source_data_len()), rv);
@@ -224,9 +260,12 @@ TEST_P(GzipSourceStreamTest, MissingZlibHeader) {
TEST_P(GzipSourceStreamTest, CorruptGzipHeader) {
Init(SourceStream::TYPE_GZIP);
- encoded_data()[0] = 0;
- source()->AddReadResult(encoded_data(), encoded_data_len(), OK,
- GetParam().mode);
+ encoded_data()[1] = 0;
+ int read_len = encoded_data_len();
+ // Needed to a avoid a DCHECK that all reads were consumed.
+ if (GetParam().read_result_type == ReadResultType::ONE_BYTE_AT_A_TIME)
+ read_len = 2;
+ source()->AddReadResult(encoded_data(), read_len, OK, GetParam().mode);
std::string actual_output;
int rv = ReadStream(&actual_output);
EXPECT_EQ(ERR_CONTENT_DECODING_FAILED, rv);
@@ -237,7 +276,7 @@ TEST_P(GzipSourceStreamTest, GzipFallback) {
Init(SourceStream::TYPE_GZIP_FALLBACK);
source()->AddReadResult(source_data(), source_data_len(), OK,
GetParam().mode);
- source()->AddReadResult(source_data(), 0, OK, GetParam().mode);
+ source()->AddReadResult(nullptr, 0, OK, GetParam().mode);
std::string actual_output;
int rv = ReadStream(&actual_output);
@@ -250,50 +289,21 @@ TEST_P(GzipSourceStreamTest, GzipFallback) {
// as produced by gzip(1).
TEST_P(GzipSourceStreamTest, GzipCorrectness) {
Init(SourceStream::TYPE_GZIP);
- char plain_data[] = "Hello, World!";
- unsigned char gzip_data[] = {
- // From:
- // echo -n 'Hello, World!' | gzip | xxd -i | sed -e 's/^/ /'
- // The footer is the last 8 bytes.
- 0x1f, 0x8b, 0x08, 0x00, 0x2b, 0x02, 0x84, 0x55, 0x00, 0x03, 0xf3,
- 0x48, 0xcd, 0xc9, 0xc9, 0xd7, 0x51, 0x08, 0xcf, 0x2f, 0xca, 0x49,
- 0x51, 0x04, 0x00, 0xd0, 0xc3, 0x4a, 0xec, 0x0d, 0x00, 0x00, 0x00};
- source()->AddReadResult(reinterpret_cast<char*>(gzip_data), sizeof(gzip_data),
- OK, GetParam().mode);
- source()->AddReadResult(
- reinterpret_cast<char*>(gzip_data) + sizeof(gzip_data), 0, OK,
- GetParam().mode);
- std::string actual_output;
- int rv = ReadStream(&actual_output);
- EXPECT_EQ(static_cast<int>(strlen(plain_data)), rv);
- EXPECT_EQ(plain_data, actual_output);
- EXPECT_EQ("GZIP", stream()->Description());
-}
-
-// Only test synchronous read because it's not straightforward to know how many
-// MockSourceStream reads to complete in order for GzipSourceStream to return.
-TEST_P(GzipSourceStreamTest, GzipCorrectnessWithSmallInputBuffer) {
- Init(SourceStream::TYPE_GZIP);
- char plain_data[] = "Hello, World!";
- unsigned char gzip_data[] = {
+ const char kDecompressedData[] = "Hello, World!";
+ const unsigned char kGzipData[] = {
// From:
// echo -n 'Hello, World!' | gzip | xxd -i | sed -e 's/^/ /'
// The footer is the last 8 bytes.
0x1f, 0x8b, 0x08, 0x00, 0x2b, 0x02, 0x84, 0x55, 0x00, 0x03, 0xf3,
0x48, 0xcd, 0xc9, 0xc9, 0xd7, 0x51, 0x08, 0xcf, 0x2f, 0xca, 0x49,
0x51, 0x04, 0x00, 0xd0, 0xc3, 0x4a, 0xec, 0x0d, 0x00, 0x00, 0x00};
- size_t gzip_data_len = sizeof(gzip_data);
- // Add a sequence of small reads.
- for (size_t i = 0; i < gzip_data_len; i++) {
- source()->AddReadResult(reinterpret_cast<char*>(gzip_data) + i, 1, OK,
- MockSourceStream::SYNC);
- }
- source()->AddReadResult(reinterpret_cast<char*>(gzip_data) + gzip_data_len, 0,
- OK, MockSourceStream::SYNC);
+ source()->AddReadResult(reinterpret_cast<const char*>(kGzipData),
+ sizeof(kGzipData), OK, GetParam().mode);
+ source()->AddReadResult(nullptr, 0, OK, GetParam().mode);
std::string actual_output;
int rv = ReadStream(&actual_output);
- EXPECT_EQ(static_cast<int>(strlen(plain_data)), rv);
- EXPECT_EQ(plain_data, actual_output);
+ EXPECT_EQ(static_cast<int>(strlen(kDecompressedData)), rv);
+ EXPECT_EQ(kDecompressedData, actual_output);
EXPECT_EQ("GZIP", stream()->Description());
}
@@ -301,23 +311,83 @@ TEST_P(GzipSourceStreamTest, GzipCorrectnessWithSmallInputBuffer) {
// implementation can handle missing footer.
TEST_P(GzipSourceStreamTest, GzipCorrectnessWithoutFooter) {
Init(SourceStream::TYPE_GZIP);
- char plain_data[] = "Hello, World!";
- unsigned char gzip_data[] = {
+ const char kDecompressedData[] = "Hello, World!";
+ const unsigned char kGzipData[] = {
// From:
// echo -n 'Hello, World!' | gzip | xxd -i | sed -e 's/^/ /'
// with the 8 footer bytes removed.
0x1f, 0x8b, 0x08, 0x00, 0x2b, 0x02, 0x84, 0x55, 0x00,
0x03, 0xf3, 0x48, 0xcd, 0xc9, 0xc9, 0xd7, 0x51, 0x08,
0xcf, 0x2f, 0xca, 0x49, 0x51, 0x04, 0x00};
- source()->AddReadResult(reinterpret_cast<char*>(gzip_data), sizeof(gzip_data),
- OK, GetParam().mode);
- source()->AddReadResult(reinterpret_cast<char*>(gzip_data), 0, OK,
- GetParam().mode);
+ source()->AddReadResult(reinterpret_cast<const char*>(kGzipData),
+ sizeof(kGzipData), OK, GetParam().mode);
+ source()->AddReadResult(nullptr, 0, OK, GetParam().mode);
std::string actual_output;
int rv = ReadStream(&actual_output);
- EXPECT_EQ(static_cast<int>(strlen(plain_data)), rv);
- EXPECT_EQ(plain_data, actual_output);
+ EXPECT_EQ(static_cast<int>(strlen(kDecompressedData)), rv);
+ EXPECT_EQ(kDecompressedData, actual_output);
EXPECT_EQ("GZIP", stream()->Description());
}
+// Test with the same compressed data as the above tests, but uses deflate with
+// header and checksum. Tests the Z_STREAM_END case in
+// STATE_SNIFFING_DEFLATE_HEADER.
+TEST_P(GzipSourceStreamTest, DeflateWithAdler32) {
+ Init(SourceStream::TYPE_DEFLATE);
+ const char kDecompressedData[] = "Hello, World!";
+ const unsigned char kGzipData[] = {0x78, 0x01, 0xf3, 0x48, 0xcd, 0xc9, 0xc9,
+ 0xd7, 0x51, 0x08, 0xcf, 0x2f, 0xca, 0x49,
+ 0x51, 0x04, 0x00, 0x1f, 0x9e, 0x04, 0x6a};
+ source()->AddReadResult(reinterpret_cast<const char*>(kGzipData),
+ sizeof(kGzipData), OK, GetParam().mode);
+ source()->AddReadResult(nullptr, 0, OK, GetParam().mode);
+ std::string actual_output;
+ int rv = ReadStream(&actual_output);
+ EXPECT_EQ(static_cast<int>(strlen(kDecompressedData)), rv);
+ EXPECT_EQ(kDecompressedData, actual_output);
+ EXPECT_EQ("DEFLATE", stream()->Description());
+}
+
+TEST_P(GzipSourceStreamTest, DeflateWithBadAdler32) {
+ Init(SourceStream::TYPE_DEFLATE);
+ const unsigned char kGzipData[] = {0x78, 0x01, 0xf3, 0x48, 0xcd, 0xc9, 0xc9,
+ 0xd7, 0x51, 0x08, 0xcf, 0x2f, 0xca, 0x49,
+ 0x51, 0x04, 0x00, 0xFF, 0xFF, 0xFF, 0xFF};
+ source()->AddReadResult(reinterpret_cast<const char*>(kGzipData),
+ sizeof(kGzipData), OK, GetParam().mode);
+ std::string actual_output;
+ int rv = ReadStream(&actual_output);
+ EXPECT_EQ(ERR_CONTENT_DECODING_FAILED, rv);
+ EXPECT_EQ("DEFLATE", stream()->Description());
+}
+
+TEST_P(GzipSourceStreamTest, DeflateWithoutHeaderWithAdler32) {
+ Init(SourceStream::TYPE_DEFLATE);
+ const char kDecompressedData[] = "Hello, World!";
+ const unsigned char kGzipData[] = {0xf3, 0x48, 0xcd, 0xc9, 0xc9, 0xd7, 0x51,
+ 0x08, 0xcf, 0x2f, 0xca, 0x49, 0x51, 0x04,
+ 0x00, 0x1f, 0x9e, 0x04, 0x6a};
+ source()->AddReadResult(reinterpret_cast<const char*>(kGzipData),
+ sizeof(kGzipData), OK, GetParam().mode);
+ source()->AddReadResult(nullptr, 0, OK, GetParam().mode);
+ std::string actual_output;
+ int rv = ReadStream(&actual_output);
+ EXPECT_EQ(static_cast<int>(strlen(kDecompressedData)), rv);
+ EXPECT_EQ(kDecompressedData, actual_output);
+ EXPECT_EQ("DEFLATE", stream()->Description());
+}
+
+TEST_P(GzipSourceStreamTest, DeflateWithoutHeaderWithBadAdler32) {
+ Init(SourceStream::TYPE_DEFLATE);
+ const unsigned char kGzipData[] = {0xf3, 0x48, 0xcd, 0xc9, 0xc9, 0xd7, 0x51,
+ 0x08, 0xcf, 0x2f, 0xca, 0x49, 0x51, 0x04,
+ 0x00, 0xFF, 0xFF, 0xFF, 0xFF};
+ source()->AddReadResult(reinterpret_cast<const char*>(kGzipData),
+ sizeof(kGzipData), OK, GetParam().mode);
+ std::string actual_output;
+ int rv = ReadStream(&actual_output);
+ EXPECT_EQ(ERR_CONTENT_DECODING_FAILED, rv);
+ EXPECT_EQ("DEFLATE", stream()->Description());
+}
+
} // namespace net
diff --git a/chromium/net/filter/mock_source_stream.cc b/chromium/net/filter/mock_source_stream.cc
index bdf56c6a4e1..7dceef28c71 100644
--- a/chromium/net/filter/mock_source_stream.cc
+++ b/chromium/net/filter/mock_source_stream.cc
@@ -6,18 +6,21 @@
#include "base/logging.h"
#include "net/base/io_buffer.h"
+#include "testing/gtest/include/gtest/gtest.h"
namespace net {
MockSourceStream::MockSourceStream()
: SourceStream(SourceStream::TYPE_NONE),
+ read_one_byte_at_a_time_(false),
awaiting_completion_(false),
dest_buffer_(nullptr),
dest_buffer_size_(0) {}
MockSourceStream::~MockSourceStream() {
DCHECK(!awaiting_completion_);
- DCHECK(results_.empty());
+ // All data should have been consumed.
+ EXPECT_TRUE(results_.empty());
}
int MockSourceStream::Read(IOBuffer* dest_buffer,
@@ -58,10 +61,24 @@ void MockSourceStream::AddReadResult(const char* data,
int len,
Error error,
Mode mode) {
- // The read result must be between 0 and 32k (inclusive) because the read
- // buffer used in FilterSourceStream is 32k.
- DCHECK_GE(32 * 1024, len);
- DCHECK_LE(0, len);
+ if (error != OK) {
+ // Doesn't make any sense to have both an error and data.
+ DCHECK_EQ(len, 0);
+ } else {
+ // The read result must be between 0 and 32k (inclusive) because the read
+ // buffer used in FilterSourceStream is 32k.
+ DCHECK_GE(32 * 1024, len);
+ DCHECK_LE(0, len);
+ }
+
+ if (len > 0 && read_one_byte_at_a_time_) {
+ for (int i = 0; i < len; ++i) {
+ QueuedResult result(data + i, 1, OK, mode);
+ results_.push(result);
+ }
+ return;
+ }
+
QueuedResult result(data, len, error, mode);
results_.push(result);
}
diff --git a/chromium/net/filter/mock_source_stream.h b/chromium/net/filter/mock_source_stream.h
index 9c88bef7cb8..4d854444c42 100644
--- a/chromium/net/filter/mock_source_stream.h
+++ b/chromium/net/filter/mock_source_stream.h
@@ -46,6 +46,18 @@ class MockSourceStream : public SourceStream {
// pending read.
void CompleteNextRead();
+ // Affects behavior or AddReadResult. When set to true, each character in
+ // |data| passed to AddReadResult will be read as an individual byte, instead
+ // of all at once. Default to false.
+ // Note that setting it only affects future calls to AddReadResult, not
+ // previous ones.
+ void set_read_one_byte_at_a_time(bool read_one_byte_at_a_time) {
+ read_one_byte_at_a_time_ = read_one_byte_at_a_time;
+ }
+
+ // Returns true if a read is waiting to be completed.
+ bool awaiting_completion() const { return awaiting_completion_; }
+
private:
struct QueuedResult {
QueuedResult(const char* data, int len, Error error, Mode mode);
@@ -56,6 +68,7 @@ class MockSourceStream : public SourceStream {
const Mode mode;
};
+ bool read_one_byte_at_a_time_;
std::queue<QueuedResult> results_;
bool awaiting_completion_;
scoped_refptr<IOBuffer> dest_buffer_;
diff --git a/chromium/net/ftp/ftp_directory_listing_parser.cc b/chromium/net/ftp/ftp_directory_listing_parser.cc
index 151c1b9df56..1096ae01f62 100644
--- a/chromium/net/ftp/ftp_directory_listing_parser.cc
+++ b/chromium/net/ftp/ftp_directory_listing_parser.cc
@@ -28,7 +28,7 @@ int FillInRawName(const std::string& encoding,
std::vector<FtpDirectoryListingEntry>* entries) {
for (size_t i = 0; i < entries->size(); i++) {
if (!base::UTF16ToCodepage(entries->at(i).name, encoding.c_str(),
- base::OnStringConversionError::FAIL,
+ base::OnStringConversionError::SUBSTITUTE,
&entries->at(i).raw_name)) {
return ERR_ENCODING_CONVERSION_FAILED;
}
@@ -91,7 +91,7 @@ int DecodeAndParse(const std::string& text,
base::string16 converted_text;
if (base::CodepageToUTF16(text, encoding_name,
- base::OnStringConversionError::FAIL,
+ base::OnStringConversionError::SUBSTITUTE,
&converted_text)) {
const char* const kNewlineSeparators[] = {"\n", "\r\n"};
diff --git a/chromium/net/ftp/ftp_directory_listing_parser_ls.cc b/chromium/net/ftp/ftp_directory_listing_parser_ls.cc
index 9d1b7116758..9ce1973756d 100644
--- a/chromium/net/ftp/ftp_directory_listing_parser_ls.cc
+++ b/chromium/net/ftp/ftp_directory_listing_parser_ls.cc
@@ -52,9 +52,8 @@ bool TwoColumnDateListingToTime(const base::string16& date,
if (!time_exploded.HasValidValues())
return false;
- // We don't know the time zone of the server, so just use local time.
- *result = base::Time::FromLocalExploded(time_exploded);
- return true;
+ // We don't know the time zone of the server, so just use UTC.
+ return base::Time::FromUTCExploded(time_exploded, result);
}
// Returns the column index of the end of the date listing and detected
diff --git a/chromium/net/ftp/ftp_directory_listing_parser_unittest.cc b/chromium/net/ftp/ftp_directory_listing_parser_unittest.cc
index 583426d98d7..a7f5bcfb3da 100644
--- a/chromium/net/ftp/ftp_directory_listing_parser_unittest.cc
+++ b/chromium/net/ftp/ftp_directory_listing_parser_unittest.cc
@@ -48,8 +48,9 @@ TEST_P(FtpDirectoryListingParserTest, Parse) {
mock_current_time_exploded.day_of_month = 15;
mock_current_time_exploded.hour = 12;
mock_current_time_exploded.minute = 45;
- base::Time mock_current_time(
- base::Time::FromLocalExploded(mock_current_time_exploded));
+ base::Time mock_current_time;
+ EXPECT_TRUE(base::Time::FromUTCExploded(mock_current_time_exploded,
+ &mock_current_time));
SCOPED_TRACE(base::StringPrintf("Test case: %s", param.name));
@@ -109,7 +110,7 @@ TEST_P(FtpDirectoryListingParserTest, Parse) {
EXPECT_EQ(size, entry.size);
base::Time::Exploded time_exploded;
- entry.last_modified.LocalExplode(&time_exploded);
+ entry.last_modified.UTCExplode(&time_exploded);
EXPECT_EQ(year, time_exploded.year);
EXPECT_EQ(month, time_exploded.month);
EXPECT_EQ(day_of_month, time_exploded.day_of_month);
@@ -157,6 +158,7 @@ const FtpTestParam kTestParams[] = {
{"dir-listing-ls-31", OK},
{"dir-listing-ls-32", OK}, // busybox
{"dir-listing-ls-33", OK},
+ {"dir-listing-ls-34", OK}, // Broken encoding. Should not fail.
{"dir-listing-netware-1", OK},
{"dir-listing-netware-2", OK},
diff --git a/chromium/net/ftp/ftp_directory_listing_parser_unittest.h b/chromium/net/ftp/ftp_directory_listing_parser_unittest.h
index 3cbe17ad2d6..f010299ff5e 100644
--- a/chromium/net/ftp/ftp_directory_listing_parser_unittest.h
+++ b/chromium/net/ftp/ftp_directory_listing_parser_unittest.h
@@ -49,7 +49,7 @@ class FtpDirectoryListingParserTest : public testing::Test {
EXPECT_EQ(test_case.size, entry.size);
base::Time::Exploded time_exploded;
- entry.last_modified.LocalExplode(&time_exploded);
+ entry.last_modified.UTCExplode(&time_exploded);
// Only test members displayed on the directory listing.
EXPECT_EQ(test_case.year, time_exploded.year);
@@ -68,11 +68,14 @@ class FtpDirectoryListingParserTest : public testing::Test {
mock_current_time_exploded.day_of_month = 15;
mock_current_time_exploded.hour = 12;
mock_current_time_exploded.minute = 45;
- return base::Time::FromLocalExploded(mock_current_time_exploded);
+
+ base::Time out_time;
+ EXPECT_TRUE(
+ base::Time::FromUTCExploded(mock_current_time_exploded, &out_time));
+ return out_time;
}
};
} // namespace net
#endif // NET_FTP_FTP_DIRECTORY_LISTING_PARSER_UNITTEST_H_
-
diff --git a/chromium/net/ftp/ftp_directory_listing_parser_vms.cc b/chromium/net/ftp/ftp_directory_listing_parser_vms.cc
index 8139ee0bc24..8f1bfe1dd83 100644
--- a/chromium/net/ftp/ftp_directory_listing_parser_vms.cc
+++ b/chromium/net/ftp/ftp_directory_listing_parser_vms.cc
@@ -6,6 +6,7 @@
#include <vector>
+#include "base/numerics/safe_math.h"
#include "base/strings/string_number_conversions.h"
#include "base/strings/string_split.h"
#include "base/strings/string_util.h"
@@ -55,6 +56,24 @@ bool ParseVmsFilename(const base::string16& raw_filename,
return true;
}
+// VMS's directory listing gives file size in blocks. The exact file size is
+// unknown both because it is measured in blocks, but also because the block
+// size is unknown (but assumed to be 512 bytes).
+bool ApproximateFilesizeFromBlockCount(int64_t num_blocks, int64_t* out_size) {
+ if (num_blocks < 0)
+ return false;
+
+ const int kBlockSize = 512;
+ base::CheckedNumeric<int64_t> num_bytes = num_blocks;
+ num_bytes *= kBlockSize;
+
+ if (!num_bytes.IsValid())
+ return false; // Block count is too large.
+
+ *out_size = num_bytes.ValueOrDie();
+ return true;
+}
+
bool ParseVmsFilesize(const base::string16& input, int64_t* size) {
if (base::ContainsOnlyChars(input, base::ASCIIToUTF16("*"))) {
// Response consisting of asterisks means unknown size.
@@ -62,17 +81,9 @@ bool ParseVmsFilesize(const base::string16& input, int64_t* size) {
return true;
}
- // VMS's directory listing gives us file size in blocks. We assume that
- // the block size is 512 bytes. It doesn't give accurate file size, but is the
- // best information we have.
- const int kBlockSize = 512;
-
- if (base::StringToInt64(input, size)) {
- if (*size < 0)
- return false;
- *size *= kBlockSize;
- return true;
- }
+ int64_t num_blocks;
+ if (base::StringToInt64(input, &num_blocks))
+ return ApproximateFilesizeFromBlockCount(num_blocks, size);
std::vector<base::StringPiece16> parts =
base::SplitStringPiece(input, base::ASCIIToUTF16("/"),
@@ -90,8 +101,7 @@ bool ParseVmsFilesize(const base::string16& input, int64_t* size) {
if (blocks_used < 0 || blocks_allocated < 0)
return false;
- *size = blocks_used * kBlockSize;
- return true;
+ return ApproximateFilesizeFromBlockCount(blocks_used, size);
}
bool LooksLikeVmsFileProtectionListingPart(const base::string16& input) {
@@ -192,9 +202,8 @@ bool VmsDateListingToTime(const std::vector<base::string16>& columns,
if (!base::StringToInt(time_parts[1], &time_exploded.minute))
return false;
- // We don't know the time zone of the server, so just use local time.
- *time = base::Time::FromLocalExploded(time_exploded);
- return true;
+ // We don't know the time zone of the server, so just use UTC.
+ return base::Time::FromUTCExploded(time_exploded, time);
}
} // namespace
diff --git a/chromium/net/ftp/ftp_directory_listing_parser_vms_unittest.cc b/chromium/net/ftp/ftp_directory_listing_parser_vms_unittest.cc
index f566481b548..24d158876f1 100644
--- a/chromium/net/ftp/ftp_directory_listing_parser_vms_unittest.cc
+++ b/chromium/net/ftp/ftp_directory_listing_parser_vms_unittest.cc
@@ -21,36 +21,33 @@ typedef FtpDirectoryListingParserTest FtpDirectoryListingParserVmsTest;
TEST_F(FtpDirectoryListingParserVmsTest, Good) {
const struct SingleLineTestData good_cases[] = {
- { "README.TXT;4 2 18-APR-2000 10:40:39.90",
- FtpDirectoryListingEntry::FILE, "readme.txt", 1024,
- 2000, 4, 18, 10, 40 },
- { ".WELCOME;1 2 13-FEB-2002 23:32:40.47",
- FtpDirectoryListingEntry::FILE, ".welcome", 1024,
- 2002, 2, 13, 23, 32 },
- { "FILE.;1 2 13-FEB-2002 23:32:40.47",
- FtpDirectoryListingEntry::FILE, "file.", 1024,
- 2002, 2, 13, 23, 32 },
- { "EXAMPLE.TXT;1 1 4-NOV-2009 06:02 [JOHNDOE] (RWED,RWED,,)",
- FtpDirectoryListingEntry::FILE, "example.txt", 512,
- 2009, 11, 4, 6, 2 },
- { "ANNOUNCE.TXT;2 1/16 12-MAR-2005 08:44:57 [SYSTEM] (RWED,RWED,RE,RE)",
- FtpDirectoryListingEntry::FILE, "announce.txt", 512,
- 2005, 3, 12, 8, 44 },
- { "TEST.DIR;1 1 4-MAR-1999 22:14:34 [UCX$NOBO,ANONYMOUS] (RWE,RWE,RWE,RWE)",
- FtpDirectoryListingEntry::DIRECTORY, "test", -1,
- 1999, 3, 4, 22, 14 },
- { "ANNOUNCE.TXT;2 1 12-MAR-2005 08:44:57 [X] (,,,)",
- FtpDirectoryListingEntry::FILE, "announce.txt", 512,
- 2005, 3, 12, 8, 44 },
- { "ANNOUNCE.TXT;2 1 12-MAR-2005 08:44:57 [X] (R,RW,RWD,RE)",
- FtpDirectoryListingEntry::FILE, "announce.txt", 512,
- 2005, 3, 12, 8, 44 },
- { "ANNOUNCE.TXT;2 1 12-MAR-2005 08:44:57 [X] (ED,RED,WD,WED)",
- FtpDirectoryListingEntry::FILE, "announce.txt", 512,
- 2005, 3, 12, 8, 44 },
- { "VMS721.ISO;2 ****** 6-MAY-2008 09:29 [ANONY,ANONYMOUS] (RE,RWED,RE,RE)",
- FtpDirectoryListingEntry::FILE, "vms721.iso", -1,
- 2008, 5, 6, 9, 29 },
+ {"README.TXT;4 2 18-APR-2000 10:40:39.90",
+ FtpDirectoryListingEntry::FILE, "readme.txt", 1024, 2000, 4, 18, 10, 40},
+ {".WELCOME;1 2 13-FEB-2002 23:32:40.47",
+ FtpDirectoryListingEntry::FILE, ".welcome", 1024, 2002, 2, 13, 23, 32},
+ {"FILE.;1 2 13-FEB-2002 23:32:40.47", FtpDirectoryListingEntry::FILE,
+ "file.", 1024, 2002, 2, 13, 23, 32},
+ {"EXAMPLE.TXT;1 1 4-NOV-2009 06:02 [JOHNDOE] (RWED,RWED,,)",
+ FtpDirectoryListingEntry::FILE, "example.txt", 512, 2009, 11, 4, 6, 2},
+ {"ANNOUNCE.TXT;2 1/16 12-MAR-2005 08:44:57 [SYSTEM] (RWED,RWED,RE,RE)",
+ FtpDirectoryListingEntry::FILE, "announce.txt", 512, 2005, 3, 12, 8, 44},
+ {"TEST.DIR;1 1 4-MAR-1999 22:14:34 [UCX$NOBO,ANONYMOUS] "
+ "(RWE,RWE,RWE,RWE)",
+ FtpDirectoryListingEntry::DIRECTORY, "test", -1, 1999, 3, 4, 22, 14},
+ {"ANNOUNCE.TXT;2 1 12-MAR-2005 08:44:57 [X] (,,,)",
+ FtpDirectoryListingEntry::FILE, "announce.txt", 512, 2005, 3, 12, 8, 44},
+ {"ANNOUNCE.TXT;2 1 12-MAR-2005 08:44:57 [X] (R,RW,RWD,RE)",
+ FtpDirectoryListingEntry::FILE, "announce.txt", 512, 2005, 3, 12, 8, 44},
+ {"ANNOUNCE.TXT;2 1 12-MAR-2005 08:44:57 [X] (ED,RED,WD,WED)",
+ FtpDirectoryListingEntry::FILE, "announce.txt", 512, 2005, 3, 12, 8, 44},
+ {"VMS721.ISO;2 ****** 6-MAY-2008 09:29 [ANONY,ANONYMOUS] "
+ "(RE,RWED,RE,RE)",
+ FtpDirectoryListingEntry::FILE, "vms721.iso", -1, 2008, 5, 6, 9, 29},
+ // This has an unusually large allocated block size (INT64_MAX), but
+ // shouldn't matter as it is not used.
+ {"ANNOUNCE.TXT;2 1/9223372036854775807 12-MAR-2005 08:44:57 [SYSTEM] "
+ "(RWED,RWED,RE,RE)",
+ FtpDirectoryListingEntry::FILE, "announce.txt", 512, 2005, 3, 12, 8, 44},
};
for (size_t i = 0; i < arraysize(good_cases); i++) {
SCOPED_TRACE(base::StringPrintf("Test[%" PRIuS "]: %s", i,
@@ -76,37 +73,47 @@ TEST_F(FtpDirectoryListingParserVmsTest, Good) {
TEST_F(FtpDirectoryListingParserVmsTest, Bad) {
const char* const bad_cases[] = {
- "garbage",
-
- // Missing file version number.
- "README.TXT 2 18-APR-2000 10:40:39",
-
- // Missing extension.
- "README;1 2 18-APR-2000 10:40:39",
-
- // Malformed file size.
- "README.TXT;1 garbage 18-APR-2000 10:40:39",
- "README.TXT;1 -2 18-APR-2000 10:40:39",
-
- // Malformed date.
- "README.TXT;1 2 APR-2000 10:40:39",
- "README.TXT;1 2 -18-APR-2000 10:40:39",
- "README.TXT;1 2 18-APR 10:40:39",
- "README.TXT;1 2 18-APR-2000 10",
- "README.TXT;1 2 18-APR-2000 10:40.25",
- "README.TXT;1 2 18-APR-2000 10:40.25.25",
-
- // Malformed security information.
- "X.TXT;2 1 12-MAR-2005 08:44:57 (RWED,RWED,RE,RE)",
- "X.TXT;2 1 12-MAR-2005 08:44:57 [SYSTEM]",
- "X.TXT;2 1 12-MAR-2005 08:44:57 (SYSTEM) (RWED,RWED,RE,RE)",
- "X.TXT;2 1 12-MAR-2005 08:44:57 [SYSTEM] [RWED,RWED,RE,RE]",
- "X.TXT;2 1 12-MAR-2005 08:44:57 [X] (RWED)",
- "X.TXT;2 1 12-MAR-2005 08:44:57 [X] (RWED,RWED,RE,RE,RE)",
- "X.TXT;2 1 12-MAR-2005 08:44:57 [X] (RWED,RWEDRWED,RE,RE)",
- "X.TXT;2 1 12-MAR-2005 08:44:57 [X] (RWED,DEWR,RE,RE)",
- "X.TXT;2 1 12-MAR-2005 08:44:57 [X] (RWED,RWED,Q,RE)",
- "X.TXT;2 1 12-MAR-2005 08:44:57 [X] (RWED,RRWWEEDD,RE,RE)",
+ "garbage",
+
+ // Missing file version number.
+ "README.TXT 2 18-APR-2000 10:40:39",
+
+ // Missing extension.
+ "README;1 2 18-APR-2000 10:40:39",
+
+ // Malformed file size.
+ "README.TXT;1 garbage 18-APR-2000 10:40:39",
+ "README.TXT;1 -2 18-APR-2000 10:40:39",
+
+ // Malformed date.
+ "README.TXT;1 2 APR-2000 10:40:39",
+ "README.TXT;1 2 -18-APR-2000 10:40:39", "README.TXT;1 2 18-APR 10:40:39",
+ "README.TXT;1 2 18-APR-2000 10", "README.TXT;1 2 18-APR-2000 10:40.25",
+ "README.TXT;1 2 18-APR-2000 10:40.25.25",
+
+ // Malformed security information.
+ "X.TXT;2 1 12-MAR-2005 08:44:57 (RWED,RWED,RE,RE)",
+ "X.TXT;2 1 12-MAR-2005 08:44:57 [SYSTEM]",
+ "X.TXT;2 1 12-MAR-2005 08:44:57 (SYSTEM) (RWED,RWED,RE,RE)",
+ "X.TXT;2 1 12-MAR-2005 08:44:57 [SYSTEM] [RWED,RWED,RE,RE]",
+ "X.TXT;2 1 12-MAR-2005 08:44:57 [X] (RWED)",
+ "X.TXT;2 1 12-MAR-2005 08:44:57 [X] (RWED,RWED,RE,RE,RE)",
+ "X.TXT;2 1 12-MAR-2005 08:44:57 [X] (RWED,RWEDRWED,RE,RE)",
+ "X.TXT;2 1 12-MAR-2005 08:44:57 [X] (RWED,DEWR,RE,RE)",
+ "X.TXT;2 1 12-MAR-2005 08:44:57 [X] (RWED,RWED,Q,RE)",
+ "X.TXT;2 1 12-MAR-2005 08:44:57 [X] (RWED,RRWWEEDD,RE,RE)",
+
+ // Block size (INT64_MAX) is too large -- will overflow when
+ // multiplying by 512 to calculate the file size in bytes.
+ "README.TXT;1 9223372036854775807 18-APR-2000 10:40:39.90",
+ "README.TXT;1 9223372036854775807/9223372036854775807 18-APR-2000 "
+ "10:40:39.90",
+
+ // Block size (larger than INT64_MAX) is too large -- will fail to
+ // parse to an int64_t
+ "README.TXT;1 19223372036854775807 18-APR-2000 10:40:39.90",
+ "README.TXT;1 19223372036854775807/19223372036854775807 18-APR-2000 "
+ "10:40:39.90",
};
for (size_t i = 0; i < arraysize(bad_cases); i++) {
SCOPED_TRACE(base::StringPrintf("Test[%" PRIuS "]: %s", i, bad_cases[i]));
diff --git a/chromium/net/ftp/ftp_network_session.cc b/chromium/net/ftp/ftp_network_session.cc
index 65dd218a4d4..37a7cbee74d 100644
--- a/chromium/net/ftp/ftp_network_session.cc
+++ b/chromium/net/ftp/ftp_network_session.cc
@@ -12,4 +12,3 @@ FtpNetworkSession::FtpNetworkSession(HostResolver* host_resolver)
FtpNetworkSession::~FtpNetworkSession() {}
} // namespace net
-
diff --git a/chromium/net/ftp/ftp_network_transaction.cc b/chromium/net/ftp/ftp_network_transaction.cc
index 8ecde3104de..dbe1154f826 100644
--- a/chromium/net/ftp/ftp_network_transaction.cc
+++ b/chromium/net/ftp/ftp_network_transaction.cc
@@ -16,6 +16,7 @@
#include "net/base/address_list.h"
#include "net/base/escape.h"
#include "net/base/net_errors.h"
+#include "net/base/parse_number.h"
#include "net/base/port_util.h"
#include "net/base/url_util.h"
#include "net/ftp/ftp_request_info.h"
@@ -35,8 +36,8 @@ const char kCRLF[] = "\r\n";
const int kCtrlBufLen = 1024;
-// Returns true if |input| can be safely used as a part of FTP command.
-bool IsValidFTPCommandString(const std::string& input) {
+// Returns true if |input| can be safely used as a part of an FTP command.
+bool IsValidFTPCommandSubstring(const std::string& input) {
// RFC 959 only allows ASCII strings, but at least Firefox can send non-ASCII
// characters in the command if the request path contains them. To be
// compatible, we do the same and allow non-ASCII characters in a command.
@@ -123,25 +124,32 @@ int GetNetErrorCodeForFtpResponseCode(int response_code) {
bool ExtractPortFromEPSVResponse(const FtpCtrlResponse& response, int* port) {
if (response.lines.size() != 1)
return false;
- const char* ptr = response.lines[0].c_str();
- while (*ptr && *ptr != '(')
- ++ptr;
- if (!*ptr)
- return false;
- char sep = *(++ptr);
- if (!sep || isdigit(sep) || *(++ptr) != sep || *(++ptr) != sep)
+
+ base::StringPiece epsv_line(response.lines[0]);
+ size_t start = epsv_line.find('(');
+ // If the line doesn't have a '(' or doesn't have enough characters after the
+ // first '(', fail.
+ if (start == base::StringPiece::npos || epsv_line.length() - start < 7)
return false;
- if (!isdigit(*(++ptr)))
+
+ char separator = epsv_line[start + 1];
+
+ // Make sure we have "(<d><d><d>...", where <d> is not a number.
+ if ((separator >= '0' && separator <= '9') ||
+ epsv_line[start + 2] != separator || epsv_line[start + 3] != separator) {
return false;
- *port = *ptr - '0';
- while (isdigit(*(++ptr))) {
- *port *= 10;
- *port += *ptr - '0';
}
- if (*ptr != sep)
+
+ // Skip over those characters.
+ start += 4;
+
+ // Make sure there's a terminal <d>.
+ size_t end = epsv_line.find(separator, start);
+ if (end == base::StringPiece::npos)
return false;
- return true;
+ return ParseInt32(epsv_line.substr(start, end - start),
+ ParseIntFormat::NON_NEGATIVE, port);
}
// There are two way we can receive IP address and port.
@@ -190,13 +198,15 @@ bool ExtractPortFromPASVResponse(const FtpCtrlResponse& response, int* port) {
// Ignore the IP address supplied in the response. We are always going
// to connect back to the same server to prevent FTP PASV port scanning.
- int p0, p1;
- if (!base::StringToInt(pieces[4], &p0))
+ uint32_t p0, p1;
+ if (!ParseUint32(pieces[4], &p0))
return false;
- if (!base::StringToInt(pieces[5], &p1))
+ if (!ParseUint32(pieces[5], &p1))
+ return false;
+ if (p0 > 0xFF || p1 > 0xFF)
return false;
- *port = (p0 << 8) + p1;
+ *port = (p0 << 8) + p1;
return true;
}
@@ -417,7 +427,9 @@ int FtpNetworkTransaction::ProcessCtrlResponse() {
}
// We may get multiple responses for some commands,
- // see http://crbug.com/18036.
+ // see http://crbug.com/18036. Consume all responses, regardless of whether
+ // they make sense. On unexpected responses, SendFtpCommand expects all data
+ // to have already been consumed, even when sending the QUIT command.
while (ctrl_response_buffer_->ResponseAvailable() && rv == OK) {
response = ctrl_response_buffer_->PopResponse();
@@ -430,7 +442,8 @@ int FtpNetworkTransaction::ProcessCtrlResponse() {
break;
default:
// Multiple responses for other commands are invalid.
- return Stop(ERR_INVALID_RESPONSE);
+ rv = Stop(ERR_INVALID_RESPONSE);
+ break;
}
}
@@ -449,7 +462,7 @@ int FtpNetworkTransaction::SendFtpCommand(const std::string& command,
DCHECK(!write_command_buf_.get());
DCHECK(!write_buf_.get());
- if (!IsValidFTPCommandString(command)) {
+ if (!IsValidFTPCommandSubstring(command)) {
// Callers should validate the command themselves and return a more specific
// error code.
NOTREACHED();
@@ -492,7 +505,7 @@ std::string FtpNetworkTransaction::GetRequestPathForFtpCommand(
UnescapeRule::SPACES |
UnescapeRule::URL_SPECIAL_CHARS_EXCEPT_PATH_SEPARATORS;
// This may unescape to non-ASCII characters, but we allow that. See the
- // comment for IsValidFTPCommandString.
+ // comment for IsValidFTPCommandSubstring.
path = UnescapeURLComponent(path, unescape_rules);
if (system_type_ == SYSTEM_TYPE_VMS) {
@@ -502,7 +515,7 @@ std::string FtpNetworkTransaction::GetRequestPathForFtpCommand(
path = FtpUtil::UnixFilePathToVMS(path);
}
- DCHECK(IsValidFTPCommandString(path));
+ DCHECK(IsValidFTPCommandSubstring(path));
return path;
}
@@ -743,7 +756,7 @@ int FtpNetworkTransaction::DoCtrlWriteComplete(int result) {
int FtpNetworkTransaction::DoCtrlWriteUSER() {
std::string command = "USER " + base::UTF16ToUTF8(credentials_.username());
- if (!IsValidFTPCommandString(command))
+ if (!IsValidFTPCommandSubstring(command))
return Stop(ERR_MALFORMED_IDENTITY);
next_state_ = STATE_CTRL_READ;
@@ -753,6 +766,8 @@ int FtpNetworkTransaction::DoCtrlWriteUSER() {
int FtpNetworkTransaction::ProcessResponseUSER(
const FtpCtrlResponse& response) {
switch (GetErrorClass(response.status_code)) {
+ case ERROR_CLASS_INITIATED:
+ return Stop(ERR_INVALID_RESPONSE);
case ERROR_CLASS_OK:
next_state_ = STATE_CTRL_WRITE_SYST;
break;
@@ -763,9 +778,6 @@ int FtpNetworkTransaction::ProcessResponseUSER(
case ERROR_CLASS_PERMANENT_ERROR:
response_.needs_auth = true;
return Stop(GetNetErrorCodeForFtpResponseCode(response.status_code));
- default:
- NOTREACHED();
- return Stop(ERR_UNEXPECTED);
}
return OK;
}
@@ -774,7 +786,7 @@ int FtpNetworkTransaction::ProcessResponseUSER(
int FtpNetworkTransaction::DoCtrlWritePASS() {
std::string command = "PASS " + base::UTF16ToUTF8(credentials_.password());
- if (!IsValidFTPCommandString(command))
+ if (!IsValidFTPCommandSubstring(command))
return Stop(ERR_MALFORMED_IDENTITY);
next_state_ = STATE_CTRL_READ;
@@ -784,6 +796,8 @@ int FtpNetworkTransaction::DoCtrlWritePASS() {
int FtpNetworkTransaction::ProcessResponsePASS(
const FtpCtrlResponse& response) {
switch (GetErrorClass(response.status_code)) {
+ case ERROR_CLASS_INITIATED:
+ return Stop(ERR_INVALID_RESPONSE);
case ERROR_CLASS_OK:
next_state_ = STATE_CTRL_WRITE_SYST;
break;
@@ -793,9 +807,6 @@ int FtpNetworkTransaction::ProcessResponsePASS(
case ERROR_CLASS_PERMANENT_ERROR:
response_.needs_auth = true;
return Stop(GetNetErrorCodeForFtpResponseCode(response.status_code));
- default:
- NOTREACHED();
- return Stop(ERR_UNEXPECTED);
}
return OK;
}
@@ -853,9 +864,6 @@ int FtpNetworkTransaction::ProcessResponseSYST(
// Server does not recognize the SYST command so proceed.
next_state_ = STATE_CTRL_WRITE_PWD;
break;
- default:
- NOTREACHED();
- return Stop(ERR_UNEXPECTED);
}
return OK;
}
@@ -888,6 +896,11 @@ int FtpNetworkTransaction::ProcessResponsePWD(const FtpCtrlResponse& response) {
line = FtpUtil::VMSPathToUnix(line);
if (!line.empty() && line.back() == '/')
line.erase(line.length() - 1);
+ // Fail if the "path" contains characters not allowed in commands.
+ // This does mean that files with CRs or LFs in their names aren't
+ // handled, but that's probably for the best.
+ if (!IsValidFTPCommandSubstring(line))
+ return Stop(ERR_INVALID_RESPONSE);
current_remote_directory_ = line;
next_state_ = STATE_CTRL_WRITE_TYPE;
break;
@@ -898,9 +911,6 @@ int FtpNetworkTransaction::ProcessResponsePWD(const FtpCtrlResponse& response) {
return Stop(GetNetErrorCodeForFtpResponseCode(response.status_code));
case ERROR_CLASS_PERMANENT_ERROR:
return Stop(GetNetErrorCodeForFtpResponseCode(response.status_code));
- default:
- NOTREACHED();
- return Stop(ERR_UNEXPECTED);
}
return OK;
}
@@ -934,9 +944,6 @@ int FtpNetworkTransaction::ProcessResponseTYPE(
return Stop(GetNetErrorCodeForFtpResponseCode(response.status_code));
case ERROR_CLASS_PERMANENT_ERROR:
return Stop(GetNetErrorCodeForFtpResponseCode(response.status_code));
- default:
- NOTREACHED();
- return Stop(ERR_UNEXPECTED);
}
return OK;
}
@@ -972,9 +979,6 @@ int FtpNetworkTransaction::ProcessResponseEPSV(
use_epsv_ = false;
next_state_ = STATE_CTRL_WRITE_PASV;
return OK;
- default:
- NOTREACHED();
- return Stop(ERR_UNEXPECTED);
}
return OK;
}
@@ -1009,9 +1013,6 @@ int FtpNetworkTransaction::ProcessResponsePASV(
return Stop(GetNetErrorCodeForFtpResponseCode(response.status_code));
case ERROR_CLASS_PERMANENT_ERROR:
return Stop(GetNetErrorCodeForFtpResponseCode(response.status_code));
- default:
- NOTREACHED();
- return Stop(ERR_UNEXPECTED);
}
return OK;
}
@@ -1045,9 +1046,6 @@ int FtpNetworkTransaction::ProcessResponseRETR(
return Stop(GetNetErrorCodeForFtpResponseCode(response.status_code));
case ERROR_CLASS_PERMANENT_ERROR:
return Stop(GetNetErrorCodeForFtpResponseCode(response.status_code));
- default:
- NOTREACHED();
- return Stop(ERR_UNEXPECTED);
}
return OK;
@@ -1091,9 +1089,6 @@ int FtpNetworkTransaction::ProcessResponseSIZE(
return Stop(GetNetErrorCodeForFtpResponseCode(response.status_code));
}
break;
- default:
- NOTREACHED();
- return Stop(ERR_UNEXPECTED);
}
// If the resource is known beforehand to be a file, RETR should be issued,
@@ -1137,9 +1132,6 @@ int FtpNetworkTransaction::ProcessResponseCWD(const FtpCtrlResponse& response) {
return ProcessResponseCWDNotADirectory();
return Stop(GetNetErrorCodeForFtpResponseCode(response.status_code));
- default:
- NOTREACHED();
- return Stop(ERR_UNEXPECTED);
}
return OK;
@@ -1197,9 +1189,6 @@ int FtpNetworkTransaction::ProcessResponseLIST(
return Stop(GetNetErrorCodeForFtpResponseCode(response.status_code));
case ERROR_CLASS_PERMANENT_ERROR:
return Stop(GetNetErrorCodeForFtpResponseCode(response.status_code));
- default:
- NOTREACHED();
- return Stop(ERR_UNEXPECTED);
}
return OK;
}
diff --git a/chromium/net/ftp/ftp_network_transaction_unittest.cc b/chromium/net/ftp/ftp_network_transaction_unittest.cc
index 3c75f42fda8..33ae12385d2 100644
--- a/chromium/net/ftp/ftp_network_transaction_unittest.cc
+++ b/chromium/net/ftp/ftp_network_transaction_unittest.cc
@@ -109,13 +109,13 @@ class FtpSocketDataProvider : public SocketDataProvider {
"227 Entering Extended Passive Mode (|||31744|)\r\n");
case PRE_LIST_PASV:
return Verify("PASV\r\n", data, PRE_LIST,
- "227 Entering Passive Mode 127,0,0,1,123,456\r\n");
+ "227 Entering Passive Mode 127,0,0,1,123,123\r\n");
case PRE_RETR_EPSV:
return Verify("EPSV\r\n", data, PRE_RETR,
"227 Entering Extended Passive Mode (|||31744|)\r\n");
case PRE_RETR_PASV:
return Verify("PASV\r\n", data, PRE_RETR,
- "227 Entering Passive Mode 127,0,0,1,123,456\r\n");
+ "227 Entering Passive Mode 127,0,0,1,123,123\r\n");
case PRE_NOPASV:
// Use unallocated 599 FTP error code to make sure it falls into the
// generic ERR_FTP_FAILED bucket.
@@ -841,15 +841,33 @@ class FtpSocketDataProviderCloseConnection : public FtpSocketDataProvider {
DISALLOW_COPY_AND_ASSIGN(FtpSocketDataProviderCloseConnection);
};
+class BorkedFtpSocketDataProvider : public FtpSocketDataProvider {
+ public:
+ BorkedFtpSocketDataProvider() {}
+ ~BorkedFtpSocketDataProvider() override {}
+
+ MockWriteResult OnWrite(const std::string& data) override {
+ switch (state()) {
+ case PRE_USER:
+ return Verify("USER anonymous\r\n", data, PRE_PASSWD, "957 Spam\r\n");
+ default:
+ return FtpSocketDataProvider::OnWrite(data);
+ }
+ }
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(BorkedFtpSocketDataProvider);
+};
+
class FtpNetworkTransactionTest
: public PlatformTest,
public ::testing::WithParamInterface<int> {
public:
- FtpNetworkTransactionTest()
- : host_resolver_(new MockHostResolver),
- transaction_(host_resolver_.get(), &mock_socket_factory_) {
+ FtpNetworkTransactionTest() : host_resolver_(new MockHostResolver) {
+ SetUpTransaction();
+
scoped_refptr<RuleBasedHostResolverProc> rules(
- new RuleBasedHostResolverProc(NULL));
+ new RuleBasedHostResolverProc(nullptr));
if (GetFamily() == AF_INET) {
rules->AddIPLiteralRule("*", "127.0.0.1", "127.0.0.1");
} else if (GetFamily() == AF_INET6) {
@@ -860,6 +878,15 @@ class FtpNetworkTransactionTest
host_resolver_->set_rules(rules.get());
}
+ // Sets up an FtpNetworkTransaction and MocketClientSocketFactory, replacing
+ // the default one. Only needs to be called if a test runs multiple
+ // transactions.
+ void SetUpTransaction() {
+ mock_socket_factory_.reset(new MockClientSocketFactory());
+ transaction_.reset(new FtpNetworkTransaction(host_resolver_.get(),
+ mock_socket_factory_.get()));
+ }
+
protected:
// Accessor to make code refactoring-friendly, e.g. when we change the way
// parameters are passed (like more parameters).
@@ -879,7 +906,7 @@ class FtpNetworkTransactionTest
// Expect EPSV usage for non-IPv4 control connections.
ctrl_socket->set_use_epsv((GetFamily() != AF_INET));
- mock_socket_factory_.AddSocketDataProvider(ctrl_socket);
+ mock_socket_factory_->AddSocketDataProvider(ctrl_socket);
std::string mock_data("mock-data");
MockRead data_reads[] = {
@@ -892,27 +919,26 @@ class FtpNetworkTransactionTest
std::unique_ptr<StaticSocketDataProvider> data_socket(
new StaticSocketDataProvider(data_reads, arraysize(data_reads), NULL,
0));
- mock_socket_factory_.AddSocketDataProvider(data_socket.get());
+ mock_socket_factory_->AddSocketDataProvider(data_socket.get());
FtpRequestInfo request_info = GetRequestInfo(request);
- EXPECT_EQ(LOAD_STATE_IDLE, transaction_.GetLoadState());
+ EXPECT_EQ(LOAD_STATE_IDLE, transaction_->GetLoadState());
ASSERT_EQ(ERR_IO_PENDING,
- transaction_.Start(&request_info, callback_.callback(),
- NetLogWithSource()));
- EXPECT_NE(LOAD_STATE_IDLE, transaction_.GetLoadState());
+ transaction_->Start(&request_info, callback_.callback(),
+ NetLogWithSource()));
+ EXPECT_NE(LOAD_STATE_IDLE, transaction_->GetLoadState());
ASSERT_EQ(expected_result, callback_.WaitForResult());
if (expected_result == OK) {
scoped_refptr<IOBuffer> io_buffer(new IOBuffer(kBufferSize));
memset(io_buffer->data(), 0, kBufferSize);
- ASSERT_EQ(ERR_IO_PENDING,
- transaction_.Read(io_buffer.get(), kBufferSize,
- callback_.callback()));
+ ASSERT_EQ(ERR_IO_PENDING, transaction_->Read(io_buffer.get(), kBufferSize,
+ callback_.callback()));
ASSERT_EQ(static_cast<int>(mock_data.length()),
callback_.WaitForResult());
EXPECT_EQ(mock_data, std::string(io_buffer->data(), mock_data.length()));
// Do another Read to detect that the data socket is now closed.
- int rv = transaction_.Read(io_buffer.get(), kBufferSize,
- callback_.callback());
+ int rv = transaction_->Read(io_buffer.get(), kBufferSize,
+ callback_.callback());
if (rv == ERR_IO_PENDING) {
EXPECT_EQ(0, callback_.WaitForResult());
} else {
@@ -920,7 +946,7 @@ class FtpNetworkTransactionTest
}
}
EXPECT_EQ(FtpSocketDataProvider::QUIT, ctrl_socket->state());
- EXPECT_EQ(LOAD_STATE_IDLE, transaction_.GetLoadState());
+ EXPECT_EQ(LOAD_STATE_IDLE, transaction_->GetLoadState());
}
void TransactionFailHelper(FtpSocketDataProvider* ctrl_socket,
@@ -934,8 +960,8 @@ class FtpNetworkTransactionTest
}
std::unique_ptr<MockHostResolver> host_resolver_;
- MockClientSocketFactory mock_socket_factory_;
- FtpNetworkTransaction transaction_;
+ std::unique_ptr<MockClientSocketFactory> mock_socket_factory_;
+ std::unique_ptr<FtpNetworkTransaction> transaction_;
TestCompletionCallback callback_;
};
@@ -946,12 +972,12 @@ TEST_P(FtpNetworkTransactionTest, FailedLookup) {
rules->AddSimulatedFailure("badhost");
host_resolver_->set_rules(rules.get());
- EXPECT_EQ(LOAD_STATE_IDLE, transaction_.GetLoadState());
+ EXPECT_EQ(LOAD_STATE_IDLE, transaction_->GetLoadState());
ASSERT_EQ(ERR_IO_PENDING,
- transaction_.Start(&request_info, callback_.callback(),
- NetLogWithSource()));
+ transaction_->Start(&request_info, callback_.callback(),
+ NetLogWithSource()));
ASSERT_THAT(callback_.WaitForResult(), IsError(ERR_NAME_NOT_RESOLVED));
- EXPECT_EQ(LOAD_STATE_IDLE, transaction_.GetLoadState());
+ EXPECT_EQ(LOAD_STATE_IDLE, transaction_->GetLoadState());
}
// Check that when determining the host, the square brackets decorating IPv6
@@ -977,27 +1003,27 @@ TEST_P(FtpNetworkTransactionTest, DirectoryTransaction) {
FtpSocketDataProviderDirectoryListing ctrl_socket;
ExecuteTransaction(&ctrl_socket, "ftp://host", OK);
- EXPECT_TRUE(transaction_.GetResponseInfo()->is_directory_listing);
- EXPECT_EQ(-1, transaction_.GetResponseInfo()->expected_content_size);
+ EXPECT_TRUE(transaction_->GetResponseInfo()->is_directory_listing);
+ EXPECT_EQ(-1, transaction_->GetResponseInfo()->expected_content_size);
EXPECT_EQ((GetFamily() == AF_INET) ? "127.0.0.1" : "::1",
- transaction_.GetResponseInfo()->socket_address.host());
- EXPECT_EQ(21, transaction_.GetResponseInfo()->socket_address.port());
+ transaction_->GetResponseInfo()->socket_address.host());
+ EXPECT_EQ(21, transaction_->GetResponseInfo()->socket_address.port());
}
TEST_P(FtpNetworkTransactionTest, DirectoryTransactionWithPasvFallback) {
FtpSocketDataProviderDirectoryListingWithPasvFallback ctrl_socket;
ExecuteTransaction(&ctrl_socket, "ftp://host", OK);
- EXPECT_TRUE(transaction_.GetResponseInfo()->is_directory_listing);
- EXPECT_EQ(-1, transaction_.GetResponseInfo()->expected_content_size);
+ EXPECT_TRUE(transaction_->GetResponseInfo()->is_directory_listing);
+ EXPECT_EQ(-1, transaction_->GetResponseInfo()->expected_content_size);
}
TEST_P(FtpNetworkTransactionTest, DirectoryTransactionWithTypecode) {
FtpSocketDataProviderDirectoryListing ctrl_socket;
ExecuteTransaction(&ctrl_socket, "ftp://host/;type=d", OK);
- EXPECT_TRUE(transaction_.GetResponseInfo()->is_directory_listing);
- EXPECT_EQ(-1, transaction_.GetResponseInfo()->expected_content_size);
+ EXPECT_TRUE(transaction_->GetResponseInfo()->is_directory_listing);
+ EXPECT_EQ(-1, transaction_->GetResponseInfo()->expected_content_size);
}
TEST_P(FtpNetworkTransactionTest, DirectoryTransactionMultilineWelcome) {
@@ -1054,10 +1080,10 @@ TEST_P(FtpNetworkTransactionTest, DownloadTransaction) {
ExecuteTransaction(&ctrl_socket, "ftp://host/file", OK);
// We pass an artificial value of 18 as a response to the SIZE command.
- EXPECT_EQ(18, transaction_.GetResponseInfo()->expected_content_size);
+ EXPECT_EQ(18, transaction_->GetResponseInfo()->expected_content_size);
EXPECT_EQ((GetFamily() == AF_INET) ? "127.0.0.1" : "::1",
- transaction_.GetResponseInfo()->socket_address.host());
- EXPECT_EQ(21, transaction_.GetResponseInfo()->socket_address.port());
+ transaction_->GetResponseInfo()->socket_address.host());
+ EXPECT_EQ(21, transaction_->GetResponseInfo()->socket_address.port());
}
TEST_P(FtpNetworkTransactionTest, DownloadTransactionWithPasvFallback) {
@@ -1065,7 +1091,7 @@ TEST_P(FtpNetworkTransactionTest, DownloadTransactionWithPasvFallback) {
ExecuteTransaction(&ctrl_socket, "ftp://host/file", OK);
// We pass an artificial value of 18 as a response to the SIZE command.
- EXPECT_EQ(18, transaction_.GetResponseInfo()->expected_content_size);
+ EXPECT_EQ(18, transaction_->GetResponseInfo()->expected_content_size);
}
TEST_P(FtpNetworkTransactionTest, DownloadTransactionWithTypecodeA) {
@@ -1074,7 +1100,7 @@ TEST_P(FtpNetworkTransactionTest, DownloadTransactionWithTypecodeA) {
ExecuteTransaction(&ctrl_socket, "ftp://host/file;type=a", OK);
// We pass an artificial value of 18 as a response to the SIZE command.
- EXPECT_EQ(18, transaction_.GetResponseInfo()->expected_content_size);
+ EXPECT_EQ(18, transaction_->GetResponseInfo()->expected_content_size);
}
TEST_P(FtpNetworkTransactionTest, DownloadTransactionWithTypecodeI) {
@@ -1082,7 +1108,7 @@ TEST_P(FtpNetworkTransactionTest, DownloadTransactionWithTypecodeI) {
ExecuteTransaction(&ctrl_socket, "ftp://host/file;type=i", OK);
// We pass an artificial value of 18 as a response to the SIZE command.
- EXPECT_EQ(18, transaction_.GetResponseInfo()->expected_content_size);
+ EXPECT_EQ(18, transaction_->GetResponseInfo()->expected_content_size);
}
TEST_P(FtpNetworkTransactionTest, DownloadTransactionMultilineWelcome) {
@@ -1161,9 +1187,37 @@ TEST_P(FtpNetworkTransactionTest, DownloadTransactionEvilPasvUnsafePort4) {
ExecuteTransaction(&ctrl_socket, "ftp://host/file", ERR_UNSAFE_PORT);
}
+TEST_P(FtpNetworkTransactionTest, DownloadTransactionEvilPasvInvalidPort1) {
+ // Unsafe. 8 * 256 + 1 = 2049, which is used by nfs.
+ FtpSocketDataProviderEvilPasv ctrl_socket(
+ "227 Portscan (127,0,0,1,256,100)\r\n", FtpSocketDataProvider::PRE_QUIT);
+ ExecuteTransaction(&ctrl_socket, "ftp://host/file", ERR_INVALID_RESPONSE);
+}
+
+TEST_P(FtpNetworkTransactionTest, DownloadTransactionEvilPasvInvalidPort2) {
+ // Unsafe. 8 * 256 + 1 = 2049, which is used by nfs.
+ FtpSocketDataProviderEvilPasv ctrl_socket(
+ "227 Portscan (127,0,0,1,100,256)\r\n", FtpSocketDataProvider::PRE_QUIT);
+ ExecuteTransaction(&ctrl_socket, "ftp://host/file", ERR_INVALID_RESPONSE);
+}
+
+TEST_P(FtpNetworkTransactionTest, DownloadTransactionEvilPasvInvalidPort3) {
+ // Unsafe. 8 * 256 + 1 = 2049, which is used by nfs.
+ FtpSocketDataProviderEvilPasv ctrl_socket(
+ "227 Portscan (127,0,0,1,-100,100)\r\n", FtpSocketDataProvider::PRE_QUIT);
+ ExecuteTransaction(&ctrl_socket, "ftp://host/file", ERR_INVALID_RESPONSE);
+}
+
+TEST_P(FtpNetworkTransactionTest, DownloadTransactionEvilPasvInvalidPort4) {
+ // Unsafe. 8 * 256 + 1 = 2049, which is used by nfs.
+ FtpSocketDataProviderEvilPasv ctrl_socket(
+ "227 Portscan (127,0,0,1,100,-100)\r\n", FtpSocketDataProvider::PRE_QUIT);
+ ExecuteTransaction(&ctrl_socket, "ftp://host/file", ERR_INVALID_RESPONSE);
+}
+
TEST_P(FtpNetworkTransactionTest, DownloadTransactionEvilPasvUnsafeHost) {
FtpSocketDataProviderEvilPasv ctrl_socket(
- "227 Portscan (10,1,2,3,123,456)\r\n", FtpSocketDataProvider::PRE_RETR);
+ "227 Portscan (10,1,2,3,123,123)\r\n", FtpSocketDataProvider::PRE_RETR);
ctrl_socket.set_use_epsv(GetFamily() != AF_INET);
std::string mock_data("mock-data");
MockRead data_reads[] = {
@@ -1172,21 +1226,21 @@ TEST_P(FtpNetworkTransactionTest, DownloadTransactionEvilPasvUnsafeHost) {
StaticSocketDataProvider data_socket1;
StaticSocketDataProvider data_socket2(data_reads, arraysize(data_reads),
NULL, 0);
- mock_socket_factory_.AddSocketDataProvider(&ctrl_socket);
- mock_socket_factory_.AddSocketDataProvider(&data_socket1);
- mock_socket_factory_.AddSocketDataProvider(&data_socket2);
+ mock_socket_factory_->AddSocketDataProvider(&ctrl_socket);
+ mock_socket_factory_->AddSocketDataProvider(&data_socket1);
+ mock_socket_factory_->AddSocketDataProvider(&data_socket2);
FtpRequestInfo request_info = GetRequestInfo("ftp://host/file");
// Start the transaction.
ASSERT_EQ(ERR_IO_PENDING,
- transaction_.Start(&request_info, callback_.callback(),
- NetLogWithSource()));
+ transaction_->Start(&request_info, callback_.callback(),
+ NetLogWithSource()));
ASSERT_THAT(callback_.WaitForResult(), IsOk());
// The transaction fires the callback when we can start reading data. That
// means that the data socket should be open.
MockTCPClientSocket* data_socket =
- static_cast<MockTCPClientSocket*>(transaction_.data_socket_.get());
+ static_cast<MockTCPClientSocket*>(transaction_->data_socket_.get());
ASSERT_TRUE(data_socket);
ASSERT_TRUE(data_socket->IsConnected());
@@ -1291,6 +1345,16 @@ TEST_P(FtpNetworkTransactionTest, DownloadTransactionEvilEpsvUnsafePort4) {
ExecuteTransaction(&ctrl_socket, "ftp://host/file", ERR_UNSAFE_PORT);
}
+TEST_P(FtpNetworkTransactionTest, DownloadTransactionEvilEpsvInvalidPort) {
+ // This test makes no sense for IPv4 connections (we don't use EPSV there).
+ if (GetFamily() == AF_INET)
+ return;
+
+ FtpSocketDataProviderEvilEpsv ctrl_socket("227 Portscan (|||4294973296|)\r\n",
+ FtpSocketDataProvider::PRE_QUIT);
+ ExecuteTransaction(&ctrl_socket, "ftp://host/file", ERR_INVALID_RESPONSE);
+}
+
TEST_P(FtpNetworkTransactionTest, DownloadTransactionEvilEpsvWeirdSep) {
// This test makes no sense for IPv4 connections (we don't use EPSV there).
if (GetFamily() == AF_INET)
@@ -1351,7 +1415,7 @@ TEST_P(FtpNetworkTransactionTest,
ExecuteTransaction(&ctrl_socket, "ftp://host/foo%2f..%2fbar%5c", OK);
// We pass an artificial value of 18 as a response to the SIZE command.
- EXPECT_EQ(18, transaction_.GetResponseInfo()->expected_content_size);
+ EXPECT_EQ(18, transaction_->GetResponseInfo()->expected_content_size);
}
TEST_P(FtpNetworkTransactionTest, EvilRestartUser) {
@@ -1359,13 +1423,13 @@ TEST_P(FtpNetworkTransactionTest, EvilRestartUser) {
ctrl_socket1.InjectFailure(FtpSocketDataProvider::PRE_PASSWD,
FtpSocketDataProvider::PRE_QUIT,
"530 Login authentication failed\r\n");
- mock_socket_factory_.AddSocketDataProvider(&ctrl_socket1);
+ mock_socket_factory_->AddSocketDataProvider(&ctrl_socket1);
FtpRequestInfo request_info = GetRequestInfo("ftp://host/file");
ASSERT_EQ(ERR_IO_PENDING,
- transaction_.Start(&request_info, callback_.callback(),
- NetLogWithSource()));
+ transaction_->Start(&request_info, callback_.callback(),
+ NetLogWithSource()));
ASSERT_THAT(callback_.WaitForResult(), IsError(ERR_FTP_FAILED));
MockRead ctrl_reads[] = {
@@ -1378,12 +1442,11 @@ TEST_P(FtpNetworkTransactionTest, EvilRestartUser) {
};
StaticSocketDataProvider ctrl_socket2(ctrl_reads, arraysize(ctrl_reads),
ctrl_writes, arraysize(ctrl_writes));
- mock_socket_factory_.AddSocketDataProvider(&ctrl_socket2);
+ mock_socket_factory_->AddSocketDataProvider(&ctrl_socket2);
ASSERT_EQ(ERR_IO_PENDING,
- transaction_.RestartWithAuth(
- AuthCredentials(
- base::ASCIIToUTF16("foo\nownz0red"),
- base::ASCIIToUTF16("innocent")),
+ transaction_->RestartWithAuth(
+ AuthCredentials(base::ASCIIToUTF16("foo\nownz0red"),
+ base::ASCIIToUTF16("innocent")),
callback_.callback()));
EXPECT_THAT(callback_.WaitForResult(), IsError(ERR_MALFORMED_IDENTITY));
}
@@ -1393,13 +1456,13 @@ TEST_P(FtpNetworkTransactionTest, EvilRestartPassword) {
ctrl_socket1.InjectFailure(FtpSocketDataProvider::PRE_PASSWD,
FtpSocketDataProvider::PRE_QUIT,
"530 Login authentication failed\r\n");
- mock_socket_factory_.AddSocketDataProvider(&ctrl_socket1);
+ mock_socket_factory_->AddSocketDataProvider(&ctrl_socket1);
FtpRequestInfo request_info = GetRequestInfo("ftp://host/file");
ASSERT_EQ(ERR_IO_PENDING,
- transaction_.Start(&request_info, callback_.callback(),
- NetLogWithSource()));
+ transaction_->Start(&request_info, callback_.callback(),
+ NetLogWithSource()));
ASSERT_THAT(callback_.WaitForResult(), IsError(ERR_FTP_FAILED));
MockRead ctrl_reads[] = {
@@ -1414,9 +1477,9 @@ TEST_P(FtpNetworkTransactionTest, EvilRestartPassword) {
};
StaticSocketDataProvider ctrl_socket2(ctrl_reads, arraysize(ctrl_reads),
ctrl_writes, arraysize(ctrl_writes));
- mock_socket_factory_.AddSocketDataProvider(&ctrl_socket2);
+ mock_socket_factory_->AddSocketDataProvider(&ctrl_socket2);
ASSERT_EQ(ERR_IO_PENDING,
- transaction_.RestartWithAuth(
+ transaction_->RestartWithAuth(
AuthCredentials(base::ASCIIToUTF16("innocent"),
base::ASCIIToUTF16("foo\nownz0red")),
callback_.callback()));
@@ -1446,7 +1509,7 @@ TEST_P(FtpNetworkTransactionTest, DownloadTransactionBigSize) {
FtpSocketDataProvider::PRE_CWD);
ExecuteTransaction(&ctrl_socket, "ftp://host/file", OK);
EXPECT_EQ(3204427776LL,
- transaction_.GetResponseInfo()->expected_content_size);
+ transaction_->GetResponseInfo()->expected_content_size);
}
// Regression test for http://crbug.com/25023.
@@ -1660,6 +1723,91 @@ TEST_P(FtpNetworkTransactionTest, ZeroLengthDirInPWD) {
OK);
}
+TEST_P(FtpNetworkTransactionTest, UnexpectedInitiatedResponseForDirectory) {
+ // The states for a directory listing where an initiated response will cause
+ // an error. Includes all commands sent on the directory listing path, except
+ // CWD, SIZE, LIST, and QUIT commands.
+ FtpSocketDataProvider::State kFailingStates[] = {
+ FtpSocketDataProvider::PRE_USER, FtpSocketDataProvider::PRE_PASSWD,
+ FtpSocketDataProvider::PRE_SYST, FtpSocketDataProvider::PRE_PWD,
+ FtpSocketDataProvider::PRE_TYPE,
+ GetFamily() != AF_INET ? FtpSocketDataProvider::PRE_LIST_EPSV
+ : FtpSocketDataProvider::PRE_LIST_PASV,
+ FtpSocketDataProvider::PRE_CWD,
+ };
+
+ for (FtpSocketDataProvider::State state : kFailingStates) {
+ SetUpTransaction();
+ FtpSocketDataProviderDirectoryListing ctrl_socket;
+ ctrl_socket.InjectFailure(state, FtpSocketDataProvider::PRE_QUIT,
+ "157 Foo\r\n");
+ ExecuteTransaction(&ctrl_socket, "ftp://host/", ERR_INVALID_RESPONSE);
+ }
+}
+
+TEST_P(FtpNetworkTransactionTest, UnexpectedInitiatedResponseForFile) {
+ // The states for a download where an initiated response will cause an error.
+ // Includes all commands sent on the file download path, except CWD, SIZE, and
+ // QUIT commands.
+ const FtpSocketDataProvider::State kFailingStates[] = {
+ FtpSocketDataProvider::PRE_USER, FtpSocketDataProvider::PRE_PASSWD,
+ FtpSocketDataProvider::PRE_SYST, FtpSocketDataProvider::PRE_PWD,
+ FtpSocketDataProvider::PRE_TYPE,
+ GetFamily() != AF_INET ? FtpSocketDataProvider::PRE_RETR_EPSV
+ : FtpSocketDataProvider::PRE_RETR_PASV,
+ FtpSocketDataProvider::PRE_CWD};
+
+ for (FtpSocketDataProvider::State state : kFailingStates) {
+ LOG(ERROR) << "??: " << state;
+ SetUpTransaction();
+ FtpSocketDataProviderFileDownload ctrl_socket;
+ ctrl_socket.InjectFailure(state, FtpSocketDataProvider::PRE_QUIT,
+ "157 Foo\r\n");
+ ExecuteTransaction(&ctrl_socket, "ftp://host/file", ERR_INVALID_RESPONSE);
+ }
+}
+
+// Make sure that receiving extra unexpected responses correctly results in
+// sending a QUIT message, without triggering a DCHECK.
+TEST_P(FtpNetworkTransactionTest, ExtraResponses) {
+ FtpSocketDataProviderDirectoryListing ctrl_socket;
+ ctrl_socket.InjectFailure(FtpSocketDataProvider::PRE_TYPE,
+ FtpSocketDataProvider::PRE_QUIT,
+ "157 Foo\r\n"
+ "157 Bar\r\n"
+ "157 Trombones\r\n");
+ ExecuteTransaction(&ctrl_socket, "ftp://host/", ERR_INVALID_RESPONSE);
+}
+
+// Make sure that receiving extra unexpected responses to a QUIT message
+// correctly results in ending the transaction with an error, without triggering
+// a DCHECK.
+TEST_P(FtpNetworkTransactionTest, ExtraQuitResponses) {
+ FtpSocketDataProviderDirectoryListing ctrl_socket;
+ ctrl_socket.InjectFailure(FtpSocketDataProvider::PRE_QUIT,
+ FtpSocketDataProvider::QUIT,
+ "221 Foo\r\n"
+ "221 Bar\r\n"
+ "221 Trombones\r\n");
+ ExecuteTransaction(&ctrl_socket, "ftp://host/", ERR_INVALID_RESPONSE);
+}
+
+TEST_P(FtpNetworkTransactionTest, InvalidRemoteDirectory) {
+ FtpSocketDataProviderFileDownload ctrl_socket;
+ TransactionFailHelper(
+ &ctrl_socket, "ftp://host/file", FtpSocketDataProvider::PRE_PWD,
+ FtpSocketDataProvider::PRE_QUIT,
+ "257 \"foo\rbar\" is your current location\r\n", ERR_INVALID_RESPONSE);
+}
+
+TEST_P(FtpNetworkTransactionTest, InvalidRemoteDirectory2) {
+ FtpSocketDataProviderFileDownload ctrl_socket;
+ TransactionFailHelper(
+ &ctrl_socket, "ftp://host/file", FtpSocketDataProvider::PRE_PWD,
+ FtpSocketDataProvider::PRE_QUIT,
+ "257 \"foo\nbar\" is your current location\r\n", ERR_INVALID_RESPONSE);
+}
+
INSTANTIATE_TEST_CASE_P(FTP,
FtpNetworkTransactionTest,
::testing::Values(AF_INET, AF_INET6));
diff --git a/chromium/net/ftp/ftp_util.cc b/chromium/net/ftp/ftp_util.cc
index 00b23b7c10b..a66845300f4 100644
--- a/chromium/net/ftp/ftp_util.cc
+++ b/chromium/net/ftp/ftp_util.cc
@@ -45,12 +45,12 @@ std::string FtpUtil::UnixFilePathToVMS(const std::string& unix_path) {
// It's an absolute path.
if (tokens.empty()) {
- DCHECK_EQ(1U, unix_path.length());
+ // It's just "/" or a series of slashes, which all mean the same thing.
return "[]";
}
if (tokens.size() == 1)
- return unix_path.substr(1); // Drop the leading slash.
+ return tokens.front(); // Return without leading slashes.
std::string result(tokens[0] + ":[");
if (tokens.size() == 2) {
@@ -272,7 +272,7 @@ bool FtpUtil::LsDateListingToTime(const base::string16& month,
// Guess the year.
base::Time::Exploded current_exploded;
- current_time.LocalExplode(&current_exploded);
+ current_time.UTCExplode(&current_exploded);
// If it's not possible for the parsed date to be in the current year,
// use the previous year.
@@ -285,9 +285,8 @@ bool FtpUtil::LsDateListingToTime(const base::string16& month,
}
}
- // We don't know the time zone of the listing, so just use local time.
- *result = base::Time::FromLocalExploded(time_exploded);
- return true;
+ // We don't know the time zone of the listing, so just use UTC.
+ return base::Time::FromUTCExploded(time_exploded, result);
}
// static
@@ -348,9 +347,8 @@ bool FtpUtil::WindowsDateListingToTime(const base::string16& date,
}
}
- // We don't know the time zone of the server, so just use local time.
- *result = base::Time::FromLocalExploded(time_exploded);
- return true;
+ // We don't know the time zone of the server, so just use UTC.
+ return base::Time::FromUTCExploded(time_exploded, result);
}
// static
diff --git a/chromium/net/ftp/ftp_util_unittest.cc b/chromium/net/ftp/ftp_util_unittest.cc
index a6f2ff019ef..8342fb4e534 100644
--- a/chromium/net/ftp/ftp_util_unittest.cc
+++ b/chromium/net/ftp/ftp_util_unittest.cc
@@ -34,6 +34,11 @@ TEST(FtpUtilTest, UnixFilePathToVMS) {
{ "a/b", "[.a]b" },
{ "a/b/c", "[.a.b]c" },
{ "a/b/c/d", "[.a.b.c]d" },
+ // Extra slashes shouldn't matter.
+ { "/////", "[]" },
+ { "/////a", "a" },
+ { "//a//b///c", "a:[b]c" },
+ { "a//b///c", "[.a.b]c" },
};
for (size_t i = 0; i < arraysize(kTestCases); i++) {
EXPECT_EQ(kTestCases[i].expected_output,
@@ -47,26 +52,30 @@ TEST(FtpUtilTest, UnixDirectoryPathToVMS) {
const char* input;
const char* expected_output;
} kTestCases[] = {
- { "", "" },
- { "/", "" },
- { "/a", "a:[000000]" },
- { "/a/", "a:[000000]" },
- { "/a/b", "a:[b]" },
- { "/a/b/", "a:[b]" },
- { "/a/b/c", "a:[b.c]" },
- { "/a/b/c/", "a:[b.c]" },
- { "/a/b/c/d", "a:[b.c.d]" },
- { "/a/b/c/d/", "a:[b.c.d]" },
- { "/a/b/c/d/e", "a:[b.c.d.e]" },
- { "/a/b/c/d/e/", "a:[b.c.d.e]" },
- { "a", "[.a]" },
- { "a/", "[.a]" },
- { "a/b", "[.a.b]" },
- { "a/b/", "[.a.b]" },
- { "a/b/c", "[.a.b.c]" },
- { "a/b/c/", "[.a.b.c]" },
- { "a/b/c/d", "[.a.b.c.d]" },
- { "a/b/c/d/", "[.a.b.c.d]" },
+ { "", "" },
+ { "/", "" },
+ { "/a", "a:[000000]" },
+ { "/a/", "a:[000000]" },
+ { "/a/b", "a:[b]" },
+ { "/a/b/", "a:[b]" },
+ { "/a/b/c", "a:[b.c]" },
+ { "/a/b/c/", "a:[b.c]" },
+ { "/a/b/c/d", "a:[b.c.d]" },
+ { "/a/b/c/d/", "a:[b.c.d]" },
+ { "/a/b/c/d/e", "a:[b.c.d.e]" },
+ { "/a/b/c/d/e/", "a:[b.c.d.e]" },
+ { "a", "[.a]" },
+ { "a/", "[.a]" },
+ { "a/b", "[.a.b]" },
+ { "a/b/", "[.a.b]" },
+ { "a/b/c", "[.a.b.c]" },
+ { "a/b/c/", "[.a.b.c]" },
+ { "a/b/c/d", "[.a.b.c.d]" },
+ { "a/b/c/d/", "[.a.b.c.d]" },
+ // Extra slashes shouldn't matter.
+ { "/////", "" },
+ { "//a//b///c//", "a:[b.c]" },
+ { "a//b///c//", "[.a.b.c]" },
};
for (size_t i = 0; i < arraysize(kTestCases); i++) {
EXPECT_EQ(kTestCases[i].expected_output,
@@ -175,7 +184,7 @@ TEST(FtpUtilTest, LsDateListingToTime) {
UTF8ToUTF16(kTestCases[i].rest), mock_current_time, &time));
base::Time::Exploded time_exploded;
- time.LocalExplode(&time_exploded);
+ time.UTCExplode(&time_exploded);
EXPECT_EQ(kTestCases[i].expected_year, time_exploded.year);
EXPECT_EQ(kTestCases[i].expected_month, time_exploded.month);
EXPECT_EQ(kTestCases[i].expected_day_of_month, time_exploded.day_of_month);
@@ -215,7 +224,7 @@ TEST(FtpUtilTest, WindowsDateListingToTime) {
&time));
base::Time::Exploded time_exploded;
- time.LocalExplode(&time_exploded);
+ time.UTCExplode(&time_exploded);
EXPECT_EQ(kTestCases[i].expected_year, time_exploded.year);
EXPECT_EQ(kTestCases[i].expected_month, time_exploded.month);
EXPECT_EQ(kTestCases[i].expected_day_of_month, time_exploded.day_of_month);
diff --git a/chromium/net/http/bidirectional_stream.h b/chromium/net/http/bidirectional_stream.h
index e7fdd6e4ae9..22d7101ebe2 100644
--- a/chromium/net/http/bidirectional_stream.h
+++ b/chromium/net/http/bidirectional_stream.h
@@ -20,8 +20,6 @@
#include "net/http/http_stream_factory.h"
#include "net/log/net_log_with_source.h"
-class GURL;
-
namespace net {
class HttpAuthController;
diff --git a/chromium/net/http/bidirectional_stream_unittest.cc b/chromium/net/http/bidirectional_stream_unittest.cc
index e55508f41bc..0b54fd1536c 100644
--- a/chromium/net/http/bidirectional_stream_unittest.cc
+++ b/chromium/net/http/bidirectional_stream_unittest.cc
@@ -578,15 +578,11 @@ TEST_F(BidirectionalStreamTest,
// BidirectionalStreamSpdyImpl.
TEST_F(BidirectionalStreamTest, TestReadDataAfterClose) {
SpdySerializedFrame req(spdy_util_.ConstructSpdyGet(kDefaultUrl, 1, LOWEST));
- // Empty DATA frame with an END_STREAM flag.
- SpdySerializedFrame end_stream(
- spdy_util_.ConstructSpdyDataFrame(1, nullptr, 0, true));
MockWrite writes[] = {
CreateMockWrite(req, 0),
};
const char* const kExtraResponseHeaders[] = {"header-name", "header-value"};
-
SpdySerializedFrame resp(
spdy_util_.ConstructSpdyGetReply(kExtraResponseHeaders, 1, 1));
@@ -1012,10 +1008,6 @@ TEST_F(BidirectionalStreamTest, TestCoalesceSmallDataBuffers) {
// read even if the read queue is empty.
TEST_F(BidirectionalStreamTest, TestCompleteAsyncRead) {
SpdySerializedFrame req(spdy_util_.ConstructSpdyGet(kDefaultUrl, 1, LOWEST));
- // Empty DATA frame with an END_STREAM flag.
- SpdySerializedFrame end_stream(
- spdy_util_.ConstructSpdyDataFrame(1, nullptr, 0, true));
-
MockWrite writes[] = {CreateMockWrite(req, 0)};
SpdySerializedFrame resp(spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
@@ -1069,14 +1061,9 @@ TEST_F(BidirectionalStreamTest, TestCompleteAsyncRead) {
TEST_F(BidirectionalStreamTest, TestBuffering) {
SpdySerializedFrame req(spdy_util_.ConstructSpdyGet(kDefaultUrl, 1, LOWEST));
- // Empty DATA frame with an END_STREAM flag.
- SpdySerializedFrame end_stream(
- spdy_util_.ConstructSpdyDataFrame(1, nullptr, 0, true));
-
MockWrite writes[] = {CreateMockWrite(req, 0)};
const char* const kExtraResponseHeaders[] = {"header-name", "header-value"};
-
SpdySerializedFrame resp(
spdy_util_.ConstructSpdyGetReply(kExtraResponseHeaders, 1, 1));
@@ -1148,16 +1135,11 @@ TEST_F(BidirectionalStreamTest, TestBuffering) {
TEST_F(BidirectionalStreamTest, TestBufferingWithTrailers) {
SpdySerializedFrame req(spdy_util_.ConstructSpdyGet(kDefaultUrl, 1, LOWEST));
- // Empty DATA frame with an END_STREAM flag.
- SpdySerializedFrame end_stream(
- spdy_util_.ConstructSpdyDataFrame(1, nullptr, 0, true));
-
MockWrite writes[] = {
CreateMockWrite(req, 0),
};
const char* const kExtraResponseHeaders[] = {"header-name", "header-value"};
-
SpdySerializedFrame resp(
spdy_util_.ConstructSpdyGetReply(kExtraResponseHeaders, 1, 1));
@@ -1238,9 +1220,6 @@ TEST_F(BidirectionalStreamTest, DeleteStreamAfterSendData) {
};
SpdySerializedFrame resp(spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
- SpdySerializedFrame response_body_frame(
- spdy_util_.ConstructSpdyDataFrame(1, false));
-
MockRead reads[] = {
CreateMockRead(resp, 1),
MockRead(ASYNC, ERR_IO_PENDING, 2), // Force a pause.
@@ -1427,7 +1406,6 @@ TEST_F(BidirectionalStreamTest, DeleteStreamDuringOnHeadersReceived) {
};
const char* const kExtraResponseHeaders[] = {"header-name", "header-value"};
-
SpdySerializedFrame resp(
spdy_util_.ConstructSpdyGetReply(kExtraResponseHeaders, 1, 1));
@@ -1477,7 +1455,6 @@ TEST_F(BidirectionalStreamTest, DeleteStreamDuringOnDataRead) {
};
const char* const kExtraResponseHeaders[] = {"header-name", "header-value"};
-
SpdySerializedFrame resp(
spdy_util_.ConstructSpdyGetReply(kExtraResponseHeaders, 1, 1));
@@ -1531,7 +1508,6 @@ TEST_F(BidirectionalStreamTest, DeleteStreamDuringOnTrailersReceived) {
};
const char* const kExtraResponseHeaders[] = {"header-name", "header-value"};
-
SpdySerializedFrame resp(
spdy_util_.ConstructSpdyGetReply(kExtraResponseHeaders, 1, 1));
@@ -1631,17 +1607,12 @@ TEST_F(BidirectionalStreamTest, DeleteStreamDuringOnFailed) {
TEST_F(BidirectionalStreamTest, TestHonorAlternativeServiceHeader) {
SpdySerializedFrame req(spdy_util_.ConstructSpdyGet(kDefaultUrl, 1, LOWEST));
- // Empty DATA frame with an END_STREAM flag.
- SpdySerializedFrame end_stream(
- spdy_util_.ConstructSpdyDataFrame(1, nullptr, 0, true));
-
MockWrite writes[] = {CreateMockWrite(req, 0)};
std::string alt_svc_header_value = NextProtoToString(kProtoQUIC);
alt_svc_header_value.append("=\"www.example.org:443\"");
const char* const kExtraResponseHeaders[] = {"alt-svc",
alt_svc_header_value.c_str()};
-
SpdySerializedFrame resp(
spdy_util_.ConstructSpdyGetReply(kExtraResponseHeaders, 1, 1));
SpdySerializedFrame body_frame(spdy_util_.ConstructSpdyDataFrame(1, true));
diff --git a/chromium/net/http/disk_cache_based_quic_server_info.h b/chromium/net/http/disk_cache_based_quic_server_info.h
index ebdd65ffdb8..1ee59d23e32 100644
--- a/chromium/net/http/disk_cache_based_quic_server_info.h
+++ b/chromium/net/http/disk_cache_based_quic_server_info.h
@@ -15,7 +15,7 @@
#include "net/base/completion_callback.h"
#include "net/base/net_export.h"
#include "net/disk_cache/disk_cache.h"
-#include "net/quic/core/crypto/quic_server_info.h"
+#include "net/quic/chromium/quic_server_info.h"
namespace net {
diff --git a/chromium/net/http/disk_cache_based_quic_server_info_unittest.cc b/chromium/net/http/disk_cache_based_quic_server_info_unittest.cc
index 569b86522a1..d4d338eef78 100644
--- a/chromium/net/http/disk_cache_based_quic_server_info_unittest.cc
+++ b/chromium/net/http/disk_cache_based_quic_server_info_unittest.cc
@@ -12,7 +12,7 @@
#include "base/run_loop.h"
#include "net/base/net_errors.h"
#include "net/http/mock_http_cache.h"
-#include "net/quic/core/crypto/quic_server_info.h"
+#include "net/quic/chromium/quic_server_info.h"
#include "net/quic/core/quic_server_id.h"
#include "net/test/gtest_util.h"
#include "testing/gmock/include/gmock/gmock.h"
diff --git a/chromium/net/http/failing_http_transaction_factory.h b/chromium/net/http/failing_http_transaction_factory.h
index 47156a2abe2..0830d57c1a6 100644
--- a/chromium/net/http/failing_http_transaction_factory.h
+++ b/chromium/net/http/failing_http_transaction_factory.h
@@ -2,8 +2,8 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#ifndef NET_FAILING_HTTP_TRANSACTION_FACTORY_H_
-#define NET_FAILING_HTTP_TRANSACTION_FACTORY_H_
+#ifndef NET_HTTP_FAILING_HTTP_TRANSACTION_FACTORY_H_
+#define NET_HTTP_FAILING_HTTP_TRANSACTION_FACTORY_H_
#include <memory>
@@ -40,4 +40,4 @@ class NET_EXPORT FailingHttpTransactionFactory : public HttpTransactionFactory {
} // namespace net
-#endif // NET_FAILING_HTTP_TRANSACTION_FACTORY_H_
+#endif // NET_HTTP_FAILING_HTTP_TRANSACTION_FACTORY_H_
diff --git a/chromium/net/http/http_auth_challenge_tokenizer.h b/chromium/net/http/http_auth_challenge_tokenizer.h
index ef5bf12c2b2..fe8f6b06fa7 100644
--- a/chromium/net/http/http_auth_challenge_tokenizer.h
+++ b/chromium/net/http/http_auth_challenge_tokenizer.h
@@ -2,8 +2,8 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#ifndef NET_HTTP_HTTP_AUTH_CHALLENGE_TOKENIZER_
-#define NET_HTTP_HTTP_AUTH_CHALLENGE_TOKENIZER_
+#ifndef NET_HTTP_HTTP_AUTH_CHALLENGE_TOKENIZER_H_
+#define NET_HTTP_HTTP_AUTH_CHALLENGE_TOKENIZER_H_
#include <string>
@@ -59,4 +59,4 @@ class NET_EXPORT_PRIVATE HttpAuthChallengeTokenizer {
} // namespace net
-#endif // NET_HTTP_HTTP_AUTH_CHALLENGE_TOKENIZER_
+#endif // NET_HTTP_HTTP_AUTH_CHALLENGE_TOKENIZER_H_
diff --git a/chromium/net/http/http_auth_gssapi_posix.cc b/chromium/net/http/http_auth_gssapi_posix.cc
index 09c15b78a1f..c8302353b7f 100644
--- a/chromium/net/http/http_auth_gssapi_posix.cc
+++ b/chromium/net/http/http_auth_gssapi_posix.cc
@@ -430,7 +430,7 @@ base::NativeLibrary GSSAPISharedLibrary::LoadSharedLibrary() {
} else {
static const char* const kDefaultLibraryNames[] = {
#if defined(OS_MACOSX)
- "/System/Library/Frameworks/Kerberos.framework/Kerberos"
+ "/System/Library/Frameworks/GSS.framework/GSS"
#elif defined(OS_OPENBSD)
"libgssapi.so" // Heimdal - OpenBSD
#else
diff --git a/chromium/net/http/http_auth_gssapi_posix.h b/chromium/net/http/http_auth_gssapi_posix.h
index 6a657616dcc..18cccebf845 100644
--- a/chromium/net/http/http_auth_gssapi_posix.h
+++ b/chromium/net/http/http_auth_gssapi_posix.h
@@ -15,18 +15,7 @@
#include "net/http/http_auth.h"
#if defined(OS_MACOSX)
-// The OSX 10.9+ SDKs mark the functions in Kereberos.framework as deprecated,
-// so the warnings must be manually suppressed.
-#if defined(MAC_OS_X_VERSION_10_9) && \
- MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_9
-#define GSSKRB_APPLE_DEPRECATED(x)
-#endif
-
-// Chrome supports OSX 10.6, which doesn't have access to GSS.framework. Chrome
-// always dlopens libgssapi_krb5.dylib, which is provided by
-// Kerberos.framework. On OSX 10.7+ this is an ABI compatible shim that loads
-// GSS.framework.
-#include <Kerberos/gssapi.h>
+#include <GSS/gssapi.h>
#elif defined(OS_FREEBSD)
#include <gssapi/gssapi.h>
#else
diff --git a/chromium/net/http/http_cache.cc b/chromium/net/http/http_cache.cc
index 54cf5713979..bab16394f75 100644
--- a/chromium/net/http/http_cache.cc
+++ b/chromium/net/http/http_cache.cc
@@ -43,7 +43,7 @@
#include "net/http/http_response_info.h"
#include "net/http/http_util.h"
#include "net/log/net_log_with_source.h"
-#include "net/quic/core/crypto/quic_server_info.h"
+#include "net/quic/chromium/quic_server_info.h"
#if defined(OS_POSIX)
#include <unistd.h>
diff --git a/chromium/net/http/http_cache.h b/chromium/net/http/http_cache.h
index 00b3954fb08..2aae2fcf27e 100644
--- a/chromium/net/http/http_cache.h
+++ b/chromium/net/http/http_cache.h
@@ -47,19 +47,10 @@ class Entry;
namespace net {
-class CertVerifier;
-class ChannelIDService;
-class HostResolver;
-class HttpAuthHandlerFactory;
class HttpNetworkSession;
class HttpResponseInfo;
-class HttpServerProperties;
class IOBuffer;
class NetLog;
-class NetworkDelegate;
-class ProxyService;
-class SSLConfigService;
-class TransportSecurityState;
class ViewCacheHelper;
struct HttpRequestInfo;
@@ -181,7 +172,7 @@ class NET_EXPORT HttpCache : public HttpTransactionFactory,
// Get/Set the cache's clock. These are public only for testing.
void SetClockForTesting(std::unique_ptr<base::Clock> clock) {
- clock_.reset(clock.release());
+ clock_ = std::move(clock);
}
base::Clock* clock() const { return clock_.get(); }
diff --git a/chromium/net/http/http_cache_lookup_manager.cc b/chromium/net/http/http_cache_lookup_manager.cc
new file mode 100644
index 00000000000..d4d8a2e023e
--- /dev/null
+++ b/chromium/net/http/http_cache_lookup_manager.cc
@@ -0,0 +1,71 @@
+// Copyright 2016 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.
+
+#include "net/http/http_cache_lookup_manager.h"
+
+#include "base/memory/ptr_util.h"
+#include "net/base/load_flags.h"
+
+namespace net {
+
+HttpCacheLookupManager::LookupTransaction::LookupTransaction(
+ std::unique_ptr<ServerPushHelper> server_push_helper)
+ : push_helper_(std::move(server_push_helper)),
+ request_(new HttpRequestInfo()),
+ transaction_(nullptr) {}
+
+HttpCacheLookupManager::LookupTransaction::~LookupTransaction() {}
+
+int HttpCacheLookupManager::LookupTransaction::StartLookup(
+ HttpCache* cache,
+ const CompletionCallback& callback,
+ const NetLogWithSource& net_log) {
+ request_->url = push_helper_->GetURL();
+ request_->method = "GET";
+ request_->load_flags = LOAD_ONLY_FROM_CACHE | LOAD_SKIP_CACHE_VALIDATION;
+ cache->CreateTransaction(DEFAULT_PRIORITY, &transaction_);
+ return transaction_->Start(request_.get(), callback, net_log);
+}
+
+void HttpCacheLookupManager::LookupTransaction::CancelPush() {
+ DCHECK(push_helper_.get());
+ push_helper_->Cancel();
+}
+
+HttpCacheLookupManager::HttpCacheLookupManager(HttpCache* http_cache,
+ const NetLogWithSource& net_log)
+ : net_log_(net_log), http_cache_(http_cache), weak_factory_(this) {}
+
+HttpCacheLookupManager::~HttpCacheLookupManager() {}
+
+void HttpCacheLookupManager::OnPush(
+ std::unique_ptr<ServerPushHelper> push_helper) {
+ GURL pushed_url = push_helper->GetURL();
+
+ // There's a pending lookup transaction sent over already.
+ if (base::ContainsKey(lookup_transactions_, pushed_url))
+ return;
+
+ auto lookup = base::MakeUnique<LookupTransaction>(std::move(push_helper));
+
+ int rv = lookup->StartLookup(
+ http_cache_, base::Bind(&HttpCacheLookupManager::OnLookupComplete,
+ weak_factory_.GetWeakPtr(), pushed_url),
+ net_log_);
+
+ if (rv == ERR_IO_PENDING)
+ lookup_transactions_[pushed_url] = std::move(lookup);
+}
+
+void HttpCacheLookupManager::OnLookupComplete(const GURL& url, int rv) {
+ auto it = lookup_transactions_.find(url);
+ DCHECK(it != lookup_transactions_.end());
+
+ if (rv == OK)
+ it->second->CancelPush();
+
+ lookup_transactions_.erase(it);
+}
+
+} // namespace net
diff --git a/chromium/net/http/http_cache_lookup_manager.h b/chromium/net/http/http_cache_lookup_manager.h
new file mode 100644
index 00000000000..45cfa009ac6
--- /dev/null
+++ b/chromium/net/http/http_cache_lookup_manager.h
@@ -0,0 +1,63 @@
+// Copyright 2016 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.
+
+#ifndef NET_HTTP_HTTP_CACHE_LOOKUP_MANAGER_H_
+#define NET_HTTP_HTTP_CACHE_LOOKUP_MANAGER_H_
+
+#include "net/base/net_export.h"
+#include "net/http/http_cache.h"
+#include "net/http/http_cache_transaction.h"
+#include "net/spdy/server_push_delegate.h"
+
+namespace net {
+
+// An implementation of ServerPushDelegate that issues an HttpCache::Transaction
+// to lookup whether the response to the pushed URL is cached and cancel the
+// push in that case.
+class NET_EXPORT_PRIVATE HttpCacheLookupManager : public ServerPushDelegate {
+ public:
+ // |http_cache| MUST outlive the HttpCacheLookupManager.
+ HttpCacheLookupManager(HttpCache* http_cache,
+ const NetLogWithSource& net_log);
+ ~HttpCacheLookupManager() override;
+
+ void OnPush(std::unique_ptr<ServerPushHelper> push_helper) override;
+
+ // Invoked when the HttpCache::Transaction for |url| finishes to cancel the
+ // server push if the response to the server push is found cached.
+ void OnLookupComplete(const GURL& url, int rv);
+
+ private:
+ // A class that takes the ownership of ServerPushHelper, issues and owns an
+ // HttpCache::Transaction which lookups the response in cache for the server
+ // push.
+ class LookupTransaction {
+ public:
+ LookupTransaction(std::unique_ptr<ServerPushHelper> push_helper);
+ ~LookupTransaction();
+
+ // Issues an HttpCache::Transaction to lookup whether the response is cached
+ // without header validation.
+ int StartLookup(HttpCache* cache,
+ const CompletionCallback& callback,
+ const NetLogWithSource& net_log);
+
+ void CancelPush();
+
+ private:
+ std::unique_ptr<ServerPushHelper> push_helper_;
+ std::unique_ptr<HttpRequestInfo> request_;
+ std::unique_ptr<HttpTransaction> transaction_;
+ };
+
+ NetLogWithSource net_log_;
+ // HttpCache must outlive the HttpCacheLookupManager.
+ HttpCache* http_cache_;
+ std::map<GURL, std::unique_ptr<LookupTransaction>> lookup_transactions_;
+ base::WeakPtrFactory<HttpCacheLookupManager> weak_factory_;
+};
+
+} // namespace net
+
+#endif // NET_HTTP_HTTP_CACHE_LOOKUP_MANAGER_H_
diff --git a/chromium/net/http/http_cache_lookup_manager_unittest.cc b/chromium/net/http/http_cache_lookup_manager_unittest.cc
new file mode 100644
index 00000000000..439aee74a38
--- /dev/null
+++ b/chromium/net/http/http_cache_lookup_manager_unittest.cc
@@ -0,0 +1,288 @@
+// Copyright (c) 2016 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.
+
+#include <string>
+
+#include "base/memory/ptr_util.h"
+#include "base/run_loop.h"
+#include "net/base/net_errors.h"
+#include "net/base/test_completion_callback.h"
+#include "net/http/http_cache_lookup_manager.h"
+#include "net/http/http_transaction_test_util.h"
+#include "net/http/mock_http_cache.h"
+#include "net/test/gtest_util.h"
+#include "testing/gmock/include/gmock/gmock.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+using net::test::IsOk;
+
+namespace net {
+
+namespace {
+
+class MockServerPushHelper : public ServerPushDelegate::ServerPushHelper {
+ public:
+ explicit MockServerPushHelper(const GURL& url) : request_url_(url) {}
+
+ const GURL& GetURL() override { return request_url_; }
+
+ MOCK_METHOD0(Cancel, void());
+
+ private:
+ const GURL request_url_;
+};
+
+std::unique_ptr<MockTransaction> CreateMockTransaction(const GURL& url) {
+ MockTransaction mock_trans = {
+ url.spec().c_str(), "GET", base::Time(), "", LOAD_NORMAL,
+ "HTTP/1.1 200 OK",
+ "Date: Wed, 28 Nov 2007 09:40:09 GMT\n"
+ "Last-Modified: Wed, 28 Nov 2007 00:40:09 GMT\n",
+ base::Time(), "<html><body>Google Blah Blah</body></html>",
+ TEST_MODE_NORMAL, nullptr, nullptr, nullptr, 0, 0, OK};
+ return base::MakeUnique<MockTransaction>(mock_trans);
+}
+
+void PopulateCacheEntry(HttpCache* cache, const GURL& request_url) {
+ TestCompletionCallback callback;
+
+ std::unique_ptr<MockTransaction> mock_trans =
+ CreateMockTransaction(request_url);
+ AddMockTransaction(mock_trans.get());
+
+ MockHttpRequest request(*(mock_trans.get()));
+
+ std::unique_ptr<HttpTransaction> trans;
+ int rv = cache->CreateTransaction(DEFAULT_PRIORITY, &trans);
+ EXPECT_THAT(rv, IsOk());
+ ASSERT_TRUE(trans.get());
+
+ rv = trans->Start(&request, callback.callback(), NetLogWithSource());
+ base::RunLoop().RunUntilIdle();
+
+ if (rv == ERR_IO_PENDING)
+ rv = callback.WaitForResult();
+
+ ASSERT_EQ(mock_trans->return_code, rv);
+ if (OK != rv)
+ return;
+
+ const HttpResponseInfo* response = trans->GetResponseInfo();
+ ASSERT_TRUE(response);
+
+ std::string content;
+ rv = ReadTransaction(trans.get(), &content);
+
+ EXPECT_THAT(rv, IsOk());
+ std::string expected(mock_trans->data);
+ EXPECT_EQ(expected, content);
+ RemoveMockTransaction(mock_trans.get());
+}
+
+} // namespace
+
+TEST(HttpCacheLookupManagerTest, ServerPushMissCache) {
+ MockHttpCache mock_cache;
+ HttpCacheLookupManager push_delegate(mock_cache.http_cache(),
+ NetLogWithSource());
+ GURL request_url("http://www.example.com/pushed.jpg");
+
+ std::unique_ptr<MockServerPushHelper> push_helper =
+ base::MakeUnique<MockServerPushHelper>(request_url);
+ MockServerPushHelper* push_helper_ptr = push_helper.get();
+
+ // Receive a server push and should not cancel the push.
+ EXPECT_CALL(*push_helper_ptr, Cancel()).Times(0);
+ push_delegate.OnPush(std::move(push_helper));
+ base::RunLoop().RunUntilIdle();
+
+ // Make sure no network transaction is created.
+ EXPECT_EQ(0, mock_cache.network_layer()->transaction_count());
+ EXPECT_EQ(0, mock_cache.disk_cache()->open_count());
+ EXPECT_EQ(0, mock_cache.disk_cache()->create_count());
+}
+
+TEST(HttpCacheLookupManagerTest, ServerPushDoNotCreateCacheEntry) {
+ MockHttpCache mock_cache;
+ HttpCacheLookupManager push_delegate(mock_cache.http_cache(),
+ NetLogWithSource());
+ GURL request_url("http://www.example.com/pushed.jpg");
+
+ std::unique_ptr<MockServerPushHelper> push_helper =
+ base::MakeUnique<MockServerPushHelper>(request_url);
+ MockServerPushHelper* push_helper_ptr = push_helper.get();
+
+ // Receive a server push and should not cancel the push.
+ EXPECT_CALL(*push_helper_ptr, Cancel()).Times(0);
+ push_delegate.OnPush(std::move(push_helper));
+ base::RunLoop().RunUntilIdle();
+
+ // Receive another server push for the same url.
+ std::unique_ptr<MockServerPushHelper> push_helper2 =
+ base::MakeUnique<MockServerPushHelper>(request_url);
+ MockServerPushHelper* push_helper_ptr2 = push_helper2.get();
+ EXPECT_CALL(*push_helper_ptr2, Cancel()).Times(0);
+ push_delegate.OnPush(std::move(push_helper2));
+ base::RunLoop().RunUntilIdle();
+
+ // Verify no network transaction is created.
+ EXPECT_EQ(0, mock_cache.network_layer()->transaction_count());
+ EXPECT_EQ(0, mock_cache.disk_cache()->open_count());
+ // Verify no cache entry is created for server push lookup.
+ EXPECT_EQ(0, mock_cache.disk_cache()->create_count());
+}
+
+TEST(HttpCacheLookupManagerTest, ServerPushHitCache) {
+ MockHttpCache mock_cache;
+ HttpCacheLookupManager push_delegate(mock_cache.http_cache(),
+ NetLogWithSource());
+ GURL request_url("http://www.example.com/pushed.jpg");
+
+ // Populate the cache entry so that the cache lookup for server push hits.
+ PopulateCacheEntry(mock_cache.http_cache(), request_url);
+ EXPECT_EQ(1, mock_cache.network_layer()->transaction_count());
+ EXPECT_EQ(0, mock_cache.disk_cache()->open_count());
+ EXPECT_EQ(1, mock_cache.disk_cache()->create_count());
+
+ // Add another mock transaction since the OnPush will create a new cache
+ // transaction.
+ std::unique_ptr<MockTransaction> mock_trans =
+ CreateMockTransaction(request_url);
+ AddMockTransaction(mock_trans.get());
+
+ std::unique_ptr<MockServerPushHelper> push_helper =
+ base::MakeUnique<MockServerPushHelper>(request_url);
+ MockServerPushHelper* push_helper_ptr = push_helper.get();
+
+ // Receive a server push and should cancel the push.
+ EXPECT_CALL(*push_helper_ptr, Cancel()).Times(1);
+ push_delegate.OnPush(std::move(push_helper));
+ base::RunLoop().RunUntilIdle();
+
+ // Make sure no new net layer transaction is created.
+ EXPECT_EQ(1, mock_cache.network_layer()->transaction_count());
+ EXPECT_EQ(1, mock_cache.disk_cache()->open_count());
+ EXPECT_EQ(1, mock_cache.disk_cache()->create_count());
+
+ RemoveMockTransaction(mock_trans.get());
+}
+
+// Test when a server push is received while the HttpCacheLookupManager has a
+// pending lookup transaction for the same URL, the new server push will not
+// send a new lookup transaction and should not be canceled.
+TEST(HttpCacheLookupManagerTest, ServerPushPendingLookup) {
+ MockHttpCache mock_cache;
+ HttpCacheLookupManager push_delegate(mock_cache.http_cache(),
+ NetLogWithSource());
+ GURL request_url("http://www.example.com/pushed.jpg");
+
+ // Populate the cache entry so that the cache lookup for server push hits.
+ PopulateCacheEntry(mock_cache.http_cache(), request_url);
+ EXPECT_EQ(1, mock_cache.network_layer()->transaction_count());
+ EXPECT_EQ(0, mock_cache.disk_cache()->open_count());
+ EXPECT_EQ(1, mock_cache.disk_cache()->create_count());
+
+ // Add another mock transaction since the OnPush will create a new cache
+ // transaction.
+ std::unique_ptr<MockTransaction> mock_trans =
+ CreateMockTransaction(request_url);
+ AddMockTransaction(mock_trans.get());
+
+ std::unique_ptr<MockServerPushHelper> push_helper =
+ base::MakeUnique<MockServerPushHelper>(request_url);
+ MockServerPushHelper* push_helper_ptr = push_helper.get();
+
+ // Receive a server push and should cancel the push eventually.
+ EXPECT_CALL(*push_helper_ptr, Cancel()).Times(1);
+ push_delegate.OnPush(std::move(push_helper));
+
+ std::unique_ptr<MockServerPushHelper> push_helper2 =
+ base::MakeUnique<MockServerPushHelper>(request_url);
+ MockServerPushHelper* push_helper_ptr2 = push_helper2.get();
+
+ // Receive another server push and should not cancel the push.
+ EXPECT_CALL(*push_helper_ptr2, Cancel()).Times(0);
+ push_delegate.OnPush(std::move(push_helper2));
+
+ base::RunLoop().RunUntilIdle();
+
+ // Make sure no new net layer transaction is created.
+ EXPECT_EQ(1, mock_cache.network_layer()->transaction_count());
+ EXPECT_EQ(1, mock_cache.disk_cache()->open_count());
+ EXPECT_EQ(1, mock_cache.disk_cache()->create_count());
+
+ RemoveMockTransaction(mock_trans.get());
+}
+
+// Test the server push lookup is based on the full url.
+TEST(HttpCacheLookupManagerTest, ServerPushLookupOnUrl) {
+ MockHttpCache mock_cache;
+ HttpCacheLookupManager push_delegate(mock_cache.http_cache(),
+ NetLogWithSource());
+ GURL request_url("http://www.example.com/pushed.jpg?u=0");
+ GURL request_url2("http://www.example.com/pushed.jpg?u=1");
+
+ // Populate the cache entry so that the cache lookup for server push hits.
+ PopulateCacheEntry(mock_cache.http_cache(), request_url);
+ EXPECT_EQ(1, mock_cache.network_layer()->transaction_count());
+ EXPECT_EQ(0, mock_cache.disk_cache()->open_count());
+ EXPECT_EQ(1, mock_cache.disk_cache()->create_count());
+
+ // Add another mock transaction since the OnPush will create a new cache
+ // transaction.
+ std::unique_ptr<MockTransaction> mock_trans =
+ CreateMockTransaction(request_url);
+ AddMockTransaction(mock_trans.get());
+
+ std::unique_ptr<MockServerPushHelper> push_helper =
+ base::MakeUnique<MockServerPushHelper>(request_url);
+ MockServerPushHelper* push_helper_ptr = push_helper.get();
+
+ // Receive a server push and should cancel the push eventually.
+ EXPECT_CALL(*push_helper_ptr, Cancel()).Times(1);
+ push_delegate.OnPush(std::move(push_helper));
+ // Run until the lookup transaction finishes for the first server push.
+ base::RunLoop().RunUntilIdle();
+ EXPECT_EQ(1, mock_cache.network_layer()->transaction_count());
+ EXPECT_EQ(1, mock_cache.disk_cache()->open_count());
+ EXPECT_EQ(1, mock_cache.disk_cache()->create_count());
+ RemoveMockTransaction(mock_trans.get());
+
+ AddMockTransaction(mock_trans.get());
+ // Receive the second server push with same url after the first lookup
+ // finishes, and should cancel the push.
+ std::unique_ptr<MockServerPushHelper> push_helper2 =
+ base::MakeUnique<MockServerPushHelper>(request_url);
+ MockServerPushHelper* push_helper_ptr2 = push_helper2.get();
+
+ EXPECT_CALL(*push_helper_ptr2, Cancel()).Times(1);
+ push_delegate.OnPush(std::move(push_helper2));
+ // Run until the lookup transaction finishes for the second server push.
+ base::RunLoop().RunUntilIdle();
+ EXPECT_EQ(1, mock_cache.network_layer()->transaction_count());
+ EXPECT_EQ(2, mock_cache.disk_cache()->open_count());
+ EXPECT_EQ(1, mock_cache.disk_cache()->create_count());
+ RemoveMockTransaction(mock_trans.get());
+
+ std::unique_ptr<MockTransaction> mock_trans3 =
+ CreateMockTransaction(request_url2);
+ AddMockTransaction(mock_trans3.get());
+ // Receive the third server push with a different url after lookup for a
+ // similar server push has been completed, should not cancel the push.
+ std::unique_ptr<MockServerPushHelper> push_helper3 =
+ base::MakeUnique<MockServerPushHelper>(request_url2);
+ MockServerPushHelper* push_helper_ptr3 = push_helper3.get();
+
+ EXPECT_CALL(*push_helper_ptr3, Cancel()).Times(0);
+ push_delegate.OnPush(std::move(push_helper3));
+
+ base::RunLoop().RunUntilIdle();
+ // Make sure no new net layer transaction is created.
+ EXPECT_EQ(1, mock_cache.network_layer()->transaction_count());
+ EXPECT_EQ(2, mock_cache.disk_cache()->open_count());
+ EXPECT_EQ(1, mock_cache.disk_cache()->create_count());
+ RemoveMockTransaction(mock_trans3.get());
+}
+
+} // namespace net
diff --git a/chromium/net/http/http_cache_transaction.cc b/chromium/net/http/http_cache_transaction.cc
index 717522eb695..24002d75215 100644
--- a/chromium/net/http/http_cache_transaction.cc
+++ b/chromium/net/http/http_cache_transaction.cc
@@ -28,10 +28,12 @@
#include "base/strings/stringprintf.h"
#include "base/threading/thread_task_runner_handle.h"
#include "base/time/clock.h"
+#include "base/trace_event/trace_event.h"
#include "base/values.h"
#include "net/base/auth.h"
#include "net/base/load_flags.h"
#include "net/base/load_timing_info.h"
+#include "net/base/trace_constants.h"
#include "net/base/upload_data_stream.h"
#include "net/cert/cert_status_flags.h"
#include "net/cert/x509_certificate.h"
@@ -189,6 +191,7 @@ HttpCache::Transaction::Transaction(RequestPriority priority, HttpCache* cache)
total_sent_bytes_(0),
websocket_handshake_stream_base_create_helper_(NULL),
weak_factory_(this) {
+ TRACE_EVENT0("io", "HttpCacheTransaction::Transaction");
static_assert(HttpCache::Transaction::kNumValidationHeaders ==
arraysize(kValidationHeaders),
"invalid number of validation headers");
@@ -198,6 +201,7 @@ HttpCache::Transaction::Transaction(RequestPriority priority, HttpCache* cache)
}
HttpCache::Transaction::~Transaction() {
+ TRACE_EVENT0("io", "HttpCacheTransaction::~Transaction");
// We may have to issue another IO, but we should never invoke the callback_
// after this point.
callback_.Reset();
@@ -961,6 +965,7 @@ int HttpCache::Transaction::DoGetBackendComplete(int result) {
}
int HttpCache::Transaction::DoInitEntry() {
+ TRACE_EVENT0("io", "HttpCacheTransaction::DoInitEntry");
DCHECK(!new_entry_);
if (!cache_.get())
@@ -976,6 +981,7 @@ int HttpCache::Transaction::DoInitEntry() {
}
int HttpCache::Transaction::DoOpenEntry() {
+ TRACE_EVENT0("io", "HttpCacheTransaction::DoOpenEntry");
DCHECK(!new_entry_);
next_state_ = STATE_OPEN_ENTRY_COMPLETE;
cache_pending_ = true;
@@ -985,6 +991,7 @@ int HttpCache::Transaction::DoOpenEntry() {
}
int HttpCache::Transaction::DoOpenEntryComplete(int result) {
+ TRACE_EVENT0("io", "HttpCacheTransaction::DoOpenEntryComplete");
// It is important that we go to STATE_ADD_TO_ENTRY whenever the result is
// OK, otherwise the cache will end up with an active entry without any
// transaction attached.
@@ -1027,6 +1034,7 @@ int HttpCache::Transaction::DoOpenEntryComplete(int result) {
}
int HttpCache::Transaction::DoDoomEntry() {
+ TRACE_EVENT0("io", "HttpCacheTransaction::DoDoomEntry");
next_state_ = STATE_DOOM_ENTRY_COMPLETE;
cache_pending_ = true;
if (first_cache_access_since_.is_null())
@@ -1036,6 +1044,7 @@ int HttpCache::Transaction::DoDoomEntry() {
}
int HttpCache::Transaction::DoDoomEntryComplete(int result) {
+ TRACE_EVENT0("io", "HttpCacheTransaction::DoDoomEntryComplete");
net_log_.EndEventWithNetErrorCode(NetLogEventType::HTTP_CACHE_DOOM_ENTRY,
result);
next_state_ = STATE_CREATE_ENTRY;
@@ -1046,6 +1055,7 @@ int HttpCache::Transaction::DoDoomEntryComplete(int result) {
}
int HttpCache::Transaction::DoCreateEntry() {
+ TRACE_EVENT0("io", "HttpCacheTransaction::DoCreateEntry");
DCHECK(!new_entry_);
next_state_ = STATE_CREATE_ENTRY_COMPLETE;
cache_pending_ = true;
@@ -1054,6 +1064,7 @@ int HttpCache::Transaction::DoCreateEntry() {
}
int HttpCache::Transaction::DoCreateEntryComplete(int result) {
+ TRACE_EVENT0("io", "HttpCacheTransaction::DoCreateEntryComplete");
// It is important that we go to STATE_ADD_TO_ENTRY whenever the result is
// OK, otherwise the cache will end up with an active entry without any
// transaction attached.
@@ -1084,6 +1095,7 @@ int HttpCache::Transaction::DoCreateEntryComplete(int result) {
}
int HttpCache::Transaction::DoAddToEntry() {
+ TRACE_EVENT0("io", "HttpCacheTransaction::DoAddToEntry");
DCHECK(new_entry_);
cache_pending_ = true;
next_state_ = STATE_ADD_TO_ENTRY_COMPLETE;
@@ -1125,6 +1137,7 @@ int HttpCache::Transaction::DoAddToEntry() {
}
int HttpCache::Transaction::DoAddToEntryComplete(int result) {
+ TRACE_EVENT0("io", "HttpCacheTransaction::DoAddToEntryComplete");
net_log_.EndEventWithNetErrorCode(NetLogEventType::HTTP_CACHE_ADD_TO_ENTRY,
result);
const TimeDelta entry_lock_wait =
@@ -1177,6 +1190,7 @@ int HttpCache::Transaction::DoAddToEntryComplete(int result) {
}
int HttpCache::Transaction::DoCacheReadResponse() {
+ TRACE_EVENT0("io", "HttpCacheTransaction::DoCacheReadResponse");
DCHECK(entry_);
next_state_ = STATE_CACHE_READ_RESPONSE_COMPLETE;
@@ -1189,6 +1203,7 @@ int HttpCache::Transaction::DoCacheReadResponse() {
}
int HttpCache::Transaction::DoCacheReadResponseComplete(int result) {
+ TRACE_EVENT0("io", "HttpCacheTransaction::DoCacheReadResponseComplete");
net_log_.EndEventWithNetErrorCode(NetLogEventType::HTTP_CACHE_READ_INFO,
result);
if (result != io_buf_len_ ||
@@ -1236,6 +1251,7 @@ int HttpCache::Transaction::DoCacheReadResponseComplete(int result) {
}
int HttpCache::Transaction::DoCacheToggleUnusedSincePrefetch() {
+ TRACE_EVENT0("io", "HttpCacheTransaction::DoCacheToggleUnusedSincePrefetch");
// Write back the toggled value for the next use of this entry.
response_.unused_since_prefetch = !response_.unused_since_prefetch;
@@ -1249,6 +1265,9 @@ int HttpCache::Transaction::DoCacheToggleUnusedSincePrefetch() {
int HttpCache::Transaction::DoCacheToggleUnusedSincePrefetchComplete(
int result) {
+ TRACE_EVENT0(
+ kNetTracingCategory,
+ "HttpCacheTransaction::DoCacheToggleUnusedSincePrefetchComplete");
// Restore the original value for this transaction.
response_.unused_since_prefetch = !response_.unused_since_prefetch;
next_state_ = STATE_CACHE_DISPATCH_VALIDATION;
@@ -1256,6 +1275,7 @@ int HttpCache::Transaction::DoCacheToggleUnusedSincePrefetchComplete(
}
int HttpCache::Transaction::DoCacheDispatchValidation() {
+ TRACE_EVENT0("io", "HttpCacheTransaction::DoCacheDispatchValidation");
// We now have access to the cache entry.
//
// o if we are a reader for the transaction, then we can start reading the
@@ -1337,6 +1357,7 @@ int HttpCache::Transaction::DoCompletePartialCacheValidation(int result) {
}
int HttpCache::Transaction::DoSendRequest() {
+ TRACE_EVENT0("io", "HttpCacheTransaction::DoSendRequest");
DCHECK(mode_ & WRITE || mode_ == NONE);
DCHECK(!network_trans_.get());
@@ -1364,6 +1385,7 @@ int HttpCache::Transaction::DoSendRequest() {
}
int HttpCache::Transaction::DoSendRequestComplete(int result) {
+ TRACE_EVENT0("io", "HttpCacheTransaction::DoSendRequestComplete");
if (!cache_.get())
return ERR_UNEXPECTED;
@@ -1399,6 +1421,7 @@ int HttpCache::Transaction::DoSendRequestComplete(int result) {
// We received the response headers and there is no error.
int HttpCache::Transaction::DoSuccessfulSendRequest() {
+ TRACE_EVENT0("io", "HttpCacheTransaction::DoSuccessfulSendRequest");
DCHECK(!new_response_);
const HttpResponseInfo* new_response = network_trans_->GetResponseInfo();
@@ -1504,6 +1527,7 @@ int HttpCache::Transaction::DoSuccessfulSendRequest() {
// We received 304 or 206 and we want to update the cached response headers.
int HttpCache::Transaction::DoUpdateCachedResponse() {
+ TRACE_EVENT0("io", "HttpCacheTransaction::DoUpdateCachedResponse");
next_state_ = STATE_UPDATE_CACHED_RESPONSE_COMPLETE;
int rv = OK;
// Update the cached response based on the headers and properties of
@@ -1541,16 +1565,21 @@ int HttpCache::Transaction::DoUpdateCachedResponse() {
}
int HttpCache::Transaction::DoCacheWriteUpdatedResponse() {
+ TRACE_EVENT0("io", "HttpCacheTransaction::DoCacheWriteUpdatedResponse");
+
next_state_ = STATE_CACHE_WRITE_UPDATED_RESPONSE_COMPLETE;
return WriteResponseInfoToEntry(false);
}
int HttpCache::Transaction::DoCacheWriteUpdatedResponseComplete(int result) {
+ TRACE_EVENT0("io",
+ "HttpCacheTransaction::DoCacheWriteUpdatedResponseComplete");
next_state_ = STATE_UPDATE_CACHED_RESPONSE_COMPLETE;
return OnWriteResponseInfoToEntryComplete(result);
}
int HttpCache::Transaction::DoUpdateCachedResponseComplete(int result) {
+ TRACE_EVENT0("io", "HttpCacheTransaction::DoUpdateCachedResponseComplete");
if (mode_ == UPDATE) {
DCHECK(!handling_206_);
// We got a "not modified" response and already updated the corresponding
@@ -1583,6 +1612,7 @@ int HttpCache::Transaction::DoUpdateCachedResponseComplete(int result) {
}
int HttpCache::Transaction::DoOverwriteCachedResponse() {
+ TRACE_EVENT0("io", "HttpCacheTransaction::DoOverwriteCachedResponse");
if (mode_ & READ) {
next_state_ = STATE_PARTIAL_HEADERS_RECEIVED;
return OK;
@@ -1617,16 +1647,19 @@ int HttpCache::Transaction::DoOverwriteCachedResponse() {
}
int HttpCache::Transaction::DoCacheWriteResponse() {
+ TRACE_EVENT0("io", "HttpCacheTransaction::DoCacheWriteResponse");
next_state_ = STATE_CACHE_WRITE_RESPONSE_COMPLETE;
return WriteResponseInfoToEntry(truncated_);
}
int HttpCache::Transaction::DoCacheWriteResponseComplete(int result) {
+ TRACE_EVENT0("io", "HttpCacheTransaction::DoCacheWriteResponseComplete");
next_state_ = STATE_TRUNCATE_CACHED_DATA;
return OnWriteResponseInfoToEntryComplete(result);
}
int HttpCache::Transaction::DoTruncateCachedData() {
+ TRACE_EVENT0("io", "HttpCacheTransaction::DoTruncateCachedData");
next_state_ = STATE_TRUNCATE_CACHED_DATA_COMPLETE;
if (!entry_)
return OK;
@@ -1637,6 +1670,7 @@ int HttpCache::Transaction::DoTruncateCachedData() {
}
int HttpCache::Transaction::DoTruncateCachedDataComplete(int result) {
+ TRACE_EVENT0("io", "HttpCacheTransaction::DoInitEntry");
if (entry_) {
if (net_log_.IsCapturing()) {
net_log_.EndEventWithNetErrorCode(NetLogEventType::HTTP_CACHE_WRITE_DATA,
@@ -1649,6 +1683,7 @@ int HttpCache::Transaction::DoTruncateCachedDataComplete(int result) {
}
int HttpCache::Transaction::DoTruncateCachedMetadata() {
+ TRACE_EVENT0("io", "HttpCacheTransaction::DoTruncateCachedMetadata");
next_state_ = STATE_TRUNCATE_CACHED_METADATA_COMPLETE;
if (!entry_)
return OK;
@@ -1659,6 +1694,7 @@ int HttpCache::Transaction::DoTruncateCachedMetadata() {
}
int HttpCache::Transaction::DoTruncateCachedMetadataComplete(int result) {
+ TRACE_EVENT0("io", "HttpCacheTransaction::DoTruncateCachedMetadataComplete");
if (entry_) {
if (net_log_.IsCapturing()) {
net_log_.EndEventWithNetErrorCode(NetLogEventType::HTTP_CACHE_WRITE_INFO,
@@ -1693,6 +1729,7 @@ int HttpCache::Transaction::DoPartialHeadersReceived() {
}
int HttpCache::Transaction::DoCacheReadMetadata() {
+ TRACE_EVENT0("io", "HttpCacheTransaction::DoCacheReadMetadata");
DCHECK(entry_);
DCHECK(!response_.metadata.get());
next_state_ = STATE_CACHE_READ_METADATA_COMPLETE;
@@ -1708,6 +1745,7 @@ int HttpCache::Transaction::DoCacheReadMetadata() {
}
int HttpCache::Transaction::DoCacheReadMetadataComplete(int result) {
+ TRACE_EVENT0("io", "HttpCacheTransaction::DoCacheReadMetadataComplete");
net_log_.EndEventWithNetErrorCode(NetLogEventType::HTTP_CACHE_READ_INFO,
result);
if (result != response_.metadata->size())
@@ -1716,11 +1754,13 @@ int HttpCache::Transaction::DoCacheReadMetadataComplete(int result) {
}
int HttpCache::Transaction::DoNetworkRead() {
+ TRACE_EVENT0("io", "HttpCacheTransaction::DoNetworkRead");
next_state_ = STATE_NETWORK_READ_COMPLETE;
return network_trans_->Read(read_buf_.get(), io_buf_len_, io_callback_);
}
int HttpCache::Transaction::DoNetworkReadComplete(int result) {
+ TRACE_EVENT0("io", "HttpCacheTransaction::DoNetworkReadComplete");
DCHECK(mode_ & WRITE || mode_ == NONE);
if (!cache_.get())
@@ -1736,6 +1776,7 @@ int HttpCache::Transaction::DoNetworkReadComplete(int result) {
}
int HttpCache::Transaction::DoCacheReadData() {
+ TRACE_EVENT0("io", "HttpCacheTransaction::DoCacheReadData");
if (request_->method == "HEAD")
return 0;
@@ -1755,6 +1796,7 @@ int HttpCache::Transaction::DoCacheReadData() {
}
int HttpCache::Transaction::DoCacheReadDataComplete(int result) {
+ TRACE_EVENT0("io", "HttpCacheTransaction::DoCacheReadDataComplete");
if (net_log_.IsCapturing()) {
net_log_.EndEventWithNetErrorCode(NetLogEventType::HTTP_CACHE_READ_DATA,
result);
@@ -1783,6 +1825,7 @@ int HttpCache::Transaction::DoCacheReadDataComplete(int result) {
}
int HttpCache::Transaction::DoCacheWriteData(int num_bytes) {
+ TRACE_EVENT0("io", "HttpCacheTransaction::DoCacheWriteData");
next_state_ = STATE_CACHE_WRITE_DATA_COMPLETE;
write_len_ = num_bytes;
if (entry_) {
@@ -1799,6 +1842,7 @@ int HttpCache::Transaction::DoCacheWriteData(int num_bytes) {
}
int HttpCache::Transaction::DoCacheWriteDataComplete(int result) {
+ TRACE_EVENT0("io", "HttpCacheTransaction::DoCacheWriteDataComplete");
if (entry_) {
if (net_log_.IsCapturing()) {
net_log_.EndEventWithNetErrorCode(NetLogEventType::HTTP_CACHE_WRITE_DATA,
@@ -1843,11 +1887,14 @@ int HttpCache::Transaction::DoCacheWriteDataComplete(int result) {
}
int HttpCache::Transaction::DoCacheWriteTruncatedResponse() {
+ TRACE_EVENT0("io", "HttpCacheTransaction::DoCacheWriteTruncatedResponse");
next_state_ = STATE_CACHE_WRITE_TRUNCATED_RESPONSE_COMPLETE;
return WriteResponseInfoToEntry(true);
}
int HttpCache::Transaction::DoCacheWriteTruncatedResponseComplete(int result) {
+ TRACE_EVENT0("io", "HttpCacheTransaction::DoCacheWriteTruncatedResponse");
+
return OnWriteResponseInfoToEntryComplete(result);
}
diff --git a/chromium/net/http/http_cache_unittest.cc b/chromium/net/http/http_cache_unittest.cc
index f845f16c719..60c7ed7c8d7 100644
--- a/chromium/net/http/http_cache_unittest.cc
+++ b/chromium/net/http/http_cache_unittest.cc
@@ -501,7 +501,7 @@ void Verify206Response(const std::string& response, int start, int end) {
int64_t range_start, range_end, object_size;
ASSERT_TRUE(
- headers->GetContentRange(&range_start, &range_end, &object_size));
+ headers->GetContentRangeFor206(&range_start, &range_end, &object_size));
int64_t content_length = headers->GetContentLength();
int length = end - start + 1;
@@ -1221,6 +1221,50 @@ TEST(HttpCache, SimpleGET_LoadValidateCache_Implicit) {
EXPECT_EQ(1, cache.disk_cache()->create_count());
}
+// Tests that |unused_since_prefetch| is updated accordingly (e.g. it is set to
+// true after a prefetch and set back to false when the prefetch is used).
+TEST(HttpCache, SimpleGET_UnusedSincePrefetch) {
+ MockHttpCache cache;
+ HttpResponseInfo response_info;
+
+ // A normal load does not have |unused_since_prefetch| set.
+ RunTransactionTestWithResponseInfoAndGetTiming(
+ cache.http_cache(), kSimpleGET_Transaction, &response_info,
+ BoundTestNetLog().bound(), nullptr);
+ EXPECT_FALSE(response_info.unused_since_prefetch);
+ EXPECT_FALSE(response_info.was_cached);
+
+ // The prefetch itself does not have |unused_since_prefetch| set.
+ MockTransaction prefetch_transaction(kSimpleGET_Transaction);
+ prefetch_transaction.load_flags |= LOAD_PREFETCH;
+ RunTransactionTestWithResponseInfoAndGetTiming(
+ cache.http_cache(), prefetch_transaction, &response_info,
+ BoundTestNetLog().bound(), nullptr);
+ EXPECT_FALSE(response_info.unused_since_prefetch);
+ EXPECT_TRUE(response_info.was_cached);
+
+ // A duplicated prefetch has |unused_since_prefetch| set.
+ RunTransactionTestWithResponseInfoAndGetTiming(
+ cache.http_cache(), prefetch_transaction, &response_info,
+ BoundTestNetLog().bound(), nullptr);
+ EXPECT_TRUE(response_info.unused_since_prefetch);
+ EXPECT_TRUE(response_info.was_cached);
+
+ // |unused_since_prefetch| is still true after two prefetches in a row.
+ RunTransactionTestWithResponseInfoAndGetTiming(
+ cache.http_cache(), kSimpleGET_Transaction, &response_info,
+ BoundTestNetLog().bound(), nullptr);
+ EXPECT_TRUE(response_info.unused_since_prefetch);
+ EXPECT_TRUE(response_info.was_cached);
+
+ // The resource has now been used, back to normal behavior.
+ RunTransactionTestWithResponseInfoAndGetTiming(
+ cache.http_cache(), kSimpleGET_Transaction, &response_info,
+ BoundTestNetLog().bound(), nullptr);
+ EXPECT_FALSE(response_info.unused_since_prefetch);
+ EXPECT_TRUE(response_info.was_cached);
+}
+
static void PreserveRequestHeaders_Handler(const HttpRequestInfo* request,
std::string* response_status,
std::string* response_headers,
@@ -7694,6 +7738,7 @@ TEST(HttpCache, NetworkBytesRange) {
class HttpCachePrefetchValidationTest : public ::testing::Test {
protected:
+ static const int kNumSecondsPerMinute = 60;
static const int kMaxAgeSecs = 100;
static const int kRequireValidationSecs = kMaxAgeSecs + 1;
diff --git a/chromium/net/http/http_log_util.h b/chromium/net/http/http_log_util.h
index 3b8103c2223..ead8e7b1bb1 100644
--- a/chromium/net/http/http_log_util.h
+++ b/chromium/net/http/http_log_util.h
@@ -2,8 +2,8 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#ifndef NET_HTTP_HTTP_LOG_UTIL_
-#define NET_HTTP_HTTP_LOG_UTIL_
+#ifndef NET_HTTP_HTTP_LOG_UTIL_H_
+#define NET_HTTP_HTTP_LOG_UTIL_H_
#include <string>
@@ -39,4 +39,4 @@ std::unique_ptr<base::ListValue> ElideSpdyHeaderBlockForNetLog(
} // namespace net
-#endif // NET_HTTP_HTTP_LOG_UTIL_
+#endif // NET_HTTP_HTTP_LOG_UTIL_H_
diff --git a/chromium/net/http/http_network_session.cc b/chromium/net/http/http_network_session.cc
index e2e7107bcc1..c64755a7072 100644
--- a/chromium/net/http/http_network_session.cc
+++ b/chromium/net/http/http_network_session.cc
@@ -15,19 +15,23 @@
#include "base/profiler/scoped_tracker.h"
#include "base/strings/string_number_conversions.h"
#include "base/strings/string_util.h"
+#include "base/strings/stringprintf.h"
+#include "base/trace_event/memory_allocator_dump.h"
+#include "base/trace_event/process_memory_dump.h"
#include "base/values.h"
-#include "net/base/network_throttle_manager.h"
+#include "net/base/network_throttle_manager_impl.h"
#include "net/http/http_auth_handler_factory.h"
#include "net/http/http_response_body_drainer.h"
#include "net/http/http_stream_factory_impl.h"
#include "net/http/url_security_manager.h"
#include "net/proxy/proxy_service.h"
+#include "net/quic/chromium/quic_crypto_client_stream_factory.h"
#include "net/quic/chromium/quic_stream_factory.h"
#include "net/quic/core/crypto/quic_random.h"
-#include "net/quic/core/quic_clock.h"
-#include "net/quic/core/quic_crypto_client_stream_factory.h"
-#include "net/quic/core/quic_protocol.h"
+#include "net/quic/core/quic_packets.h"
+#include "net/quic/core/quic_tag.h"
#include "net/quic/core/quic_utils.h"
+#include "net/quic/platform/impl/quic_chromium_clock.h"
#include "net/socket/client_socket_factory.h"
#include "net/socket/client_socket_pool_manager_impl.h"
#include "net/socket/next_proto.h"
@@ -68,20 +72,46 @@ const int32_t kSpdyStreamMaxRecvWindowSize = 6 * 1024 * 1024; // 6 MB
// and does not consume "too much" memory.
const int32_t kQuicSocketReceiveBufferSize = 1024 * 1024; // 1MB
+namespace {
+
+// Keep all HTTP2 parameters in |http2_settings|, even the ones that are not
+// implemented, to be sent to the server.
+// Set default values for settings that |http2_settings| does not specify.
+SettingsMap AddDefaultHttp2Settings(SettingsMap http2_settings) {
+ // Set default values only if |http2_settings| does not have
+ // a value set for given setting.
+ SettingsMap::iterator it = http2_settings.find(SETTINGS_HEADER_TABLE_SIZE);
+ if (it == http2_settings.end())
+ http2_settings[SETTINGS_HEADER_TABLE_SIZE] = kSpdyMaxHeaderTableSize;
+
+ it = http2_settings.find(SETTINGS_MAX_CONCURRENT_STREAMS);
+ if (it == http2_settings.end())
+ http2_settings[SETTINGS_MAX_CONCURRENT_STREAMS] =
+ kSpdyMaxConcurrentPushedStreams;
+
+ it = http2_settings.find(SETTINGS_INITIAL_WINDOW_SIZE);
+ if (it == http2_settings.end())
+ http2_settings[SETTINGS_INITIAL_WINDOW_SIZE] = kSpdyStreamMaxRecvWindowSize;
+
+ return http2_settings;
+}
+
+} // unnamed namespace
+
HttpNetworkSession::Params::Params()
- : client_socket_factory(NULL),
- host_resolver(NULL),
- cert_verifier(NULL),
- channel_id_service(NULL),
- transport_security_state(NULL),
- cert_transparency_verifier(NULL),
- ct_policy_enforcer(NULL),
- proxy_service(NULL),
- ssl_config_service(NULL),
- http_auth_handler_factory(NULL),
- net_log(NULL),
- host_mapping_rules(NULL),
- socket_performance_watcher_factory(NULL),
+ : client_socket_factory(nullptr),
+ host_resolver(nullptr),
+ cert_verifier(nullptr),
+ channel_id_service(nullptr),
+ transport_security_state(nullptr),
+ cert_transparency_verifier(nullptr),
+ ct_policy_enforcer(nullptr),
+ proxy_service(nullptr),
+ ssl_config_service(nullptr),
+ http_auth_handler_factory(nullptr),
+ net_log(nullptr),
+ host_mapping_rules(nullptr),
+ socket_performance_watcher_factory(nullptr),
ignore_certificate_errors(false),
testing_fixed_http_port(0),
testing_fixed_https_port(0),
@@ -89,13 +119,11 @@ HttpNetworkSession::Params::Params()
enable_spdy_ping_based_connection_checking(true),
enable_http2(true),
spdy_session_max_recv_window_size(kSpdySessionMaxRecvWindowSize),
- spdy_stream_max_recv_window_size(kSpdyStreamMaxRecvWindowSize),
time_func(&base::TimeTicks::Now),
enable_http2_alternative_service_with_different_host(false),
enable_quic_alternative_service_with_different_host(true),
enable_quic(false),
disable_quic_on_timeout_with_open_streams(false),
- enable_quic_port_selection(true),
quic_always_require_handshake_confirmation(false),
quic_disable_connection_pooling(false),
quic_load_server_info_timeout_srtt_multiplier(0.25f),
@@ -106,8 +134,8 @@ HttpNetworkSession::Params::Params()
quic_socket_receive_buffer_size(kQuicSocketReceiveBufferSize),
quic_delay_tcp_race(true),
quic_max_server_configs_stored_in_properties(0u),
- quic_clock(NULL),
- quic_random(NULL),
+ quic_clock(nullptr),
+ quic_random(nullptr),
quic_max_packet_length(kDefaultMaxPacketSize),
enable_user_alternate_protocol_ports(false),
quic_crypto_client_stream_factory(
@@ -125,9 +153,10 @@ HttpNetworkSession::Params::Params()
quic_force_hol_blocking(false),
quic_race_cert_verification(false),
quic_do_not_fragment(false),
- proxy_delegate(NULL),
+ proxy_delegate(nullptr),
enable_token_binding(false),
- http_09_on_non_default_ports_enabled(true) {
+ http_09_on_non_default_ports_enabled(false),
+ restrict_to_one_preconnect_for_proxies(false) {
quic_supported_versions.push_back(QUIC_VERSION_35);
}
@@ -143,6 +172,7 @@ HttpNetworkSession::HttpNetworkSession(const Params& params)
http_auth_handler_factory_(params.http_auth_handler_factory),
proxy_service_(params.proxy_service),
ssl_config_service_(params.ssl_config_service),
+ push_delegate_(nullptr),
quic_stream_factory_(
params.net_log,
params.host_resolver,
@@ -160,11 +190,10 @@ HttpNetworkSession::HttpNetworkSession(const Params& params)
params.socket_performance_watcher_factory,
params.quic_crypto_client_stream_factory,
params.quic_random ? params.quic_random : QuicRandom::GetInstance(),
- params.quic_clock ? params.quic_clock : new QuicClock(),
+ params.quic_clock ? params.quic_clock : new QuicChromiumClock(),
params.quic_max_packet_length,
params.quic_user_agent_id,
params.quic_supported_versions,
- params.enable_quic_port_selection,
params.quic_always_require_handshake_confirmation,
params.quic_disable_connection_pooling,
params.quic_load_server_info_timeout_srtt_multiplier,
@@ -194,12 +223,12 @@ HttpNetworkSession::HttpNetworkSession(const Params& params)
params.transport_security_state,
params.enable_spdy_ping_based_connection_checking,
params.spdy_session_max_recv_window_size,
- params.spdy_stream_max_recv_window_size,
+ AddDefaultHttp2Settings(params.http2_settings),
params.time_func,
params.proxy_delegate),
http_stream_factory_(new HttpStreamFactoryImpl(this, false)),
http_stream_factory_for_websocket_(new HttpStreamFactoryImpl(this, true)),
- network_stream_throttler_(NetworkThrottleManager::CreateThrottler()),
+ network_stream_throttler_(new NetworkThrottleManagerImpl()),
params_(params) {
DCHECK(proxy_service_);
DCHECK(ssl_config_service_.get());
@@ -289,14 +318,12 @@ std::unique_ptr<base::Value> HttpNetworkSession::SpdySessionPoolInfoToValue()
std::unique_ptr<base::Value> HttpNetworkSession::QuicInfoToValue() const {
std::unique_ptr<base::DictionaryValue> dict(new base::DictionaryValue());
dict->Set("sessions", quic_stream_factory_.QuicStreamFactoryInfoToValue());
- dict->SetBoolean("quic_enabled", params_.enable_quic);
- dict->SetBoolean("enable_quic_port_selection",
- params_.enable_quic_port_selection);
+ dict->SetBoolean("quic_enabled", IsQuicEnabled());
std::unique_ptr<base::ListValue> connection_options(new base::ListValue);
for (QuicTagVector::const_iterator it =
params_.quic_connection_options.begin();
it != params_.quic_connection_options.end(); ++it) {
- connection_options->AppendString("'" + QuicUtils::TagToString(*it) + "'");
+ connection_options->AppendString("'" + QuicTagToString(*it) + "'");
}
dict->Set("connection_options", std::move(connection_options));
@@ -357,12 +384,21 @@ bool HttpNetworkSession::IsProtocolEnabled(NextProto protocol) const {
case kProtoHTTP2:
return params_.enable_http2;
case kProtoQUIC:
- return params_.enable_quic;
+ return IsQuicEnabled();
}
NOTREACHED();
return false;
}
+void HttpNetworkSession::SetServerPushDelegate(
+ std::unique_ptr<ServerPushDelegate> push_delegate) {
+ DCHECK(!push_delegate_ && push_delegate);
+
+ push_delegate_ = std::move(push_delegate);
+ spdy_session_pool_.set_server_push_delegate(push_delegate_.get());
+ quic_stream_factory_.set_server_push_delegate(push_delegate_.get());
+}
+
void HttpNetworkSession::GetAlpnProtos(NextProtoVector* alpn_protos) const {
*alpn_protos = next_protos_;
}
@@ -380,6 +416,36 @@ void HttpNetworkSession::GetSSLConfig(const HttpRequestInfo& request,
}
}
+void HttpNetworkSession::DumpMemoryStats(
+ base::trace_event::ProcessMemoryDump* pmd,
+ const std::string& parent_absolute_name) const {
+ std::string name = base::StringPrintf("net/http_network_session_%p", this);
+ base::trace_event::MemoryAllocatorDump* http_network_session_dump =
+ pmd->GetAllocatorDump(name);
+ if (http_network_session_dump == nullptr) {
+ http_network_session_dump = pmd->CreateAllocatorDump(name);
+ normal_socket_pool_manager_->DumpMemoryStats(
+ pmd, http_network_session_dump->absolute_name());
+ spdy_session_pool_.DumpMemoryStats(
+ pmd, http_network_session_dump->absolute_name());
+ }
+ // Create an empty row under parent's dump so size can be attributed correctly
+ // if |this| is shared between URLRequestContexts.
+ base::trace_event::MemoryAllocatorDump* empty_row_dump =
+ pmd->CreateAllocatorDump(base::StringPrintf(
+ "%s/http_network_session", parent_absolute_name.c_str()));
+ pmd->AddOwnershipEdge(empty_row_dump->guid(),
+ http_network_session_dump->guid());
+}
+
+bool HttpNetworkSession::IsQuicEnabled() const {
+ return params_.enable_quic;
+}
+
+void HttpNetworkSession::DisableQuic() {
+ params_.enable_quic = false;
+}
+
ClientSocketPoolManager* HttpNetworkSession::GetSocketPoolManager(
SocketPoolType pool_type) {
switch (pool_type) {
diff --git a/chromium/net/http/http_network_session.h b/chromium/net/http/http_network_session.h
index f45ea432d5f..bf6436896aa 100644
--- a/chromium/net/http/http_network_session.h
+++ b/chromium/net/http/http_network_session.h
@@ -28,11 +28,15 @@
#include "net/http/http_stream_factory.h"
#include "net/quic/chromium/quic_stream_factory.h"
#include "net/socket/next_proto.h"
+#include "net/spdy/spdy_protocol.h"
#include "net/spdy/spdy_session_pool.h"
#include "net/ssl/ssl_client_auth_cache.h"
namespace base {
class Value;
+namespace trace_event {
+class ProcessMemoryDump;
+}
}
namespace net {
@@ -55,7 +59,6 @@ class ProxyDelegate;
class ProxyService;
class QuicClock;
class QuicCryptoClientStreamFactory;
-class QuicServerInfoFactory;
class SocketPerformanceWatcherFactory;
class SOCKSClientSocketPool;
class SSLClientSocketPool;
@@ -63,6 +66,12 @@ class SSLConfigService;
class TransportClientSocketPool;
class TransportSecurityState;
+// Specifies the maximum HPACK dynamic table size the server is allowed to set.
+const uint32_t kSpdyMaxHeaderTableSize = 64 * 1024;
+
+// Specifies the maximum concurrent streams server could send (via push).
+const uint32_t kSpdyMaxConcurrentPushedStreams = 1000;
+
// This class holds session objects used by HttpNetworkTransaction objects.
class NET_EXPORT HttpNetworkSession
: NON_EXPORTED_BASE(public base::NonThreadSafe),
@@ -96,7 +105,9 @@ class NET_EXPORT HttpNetworkSession
bool enable_spdy_ping_based_connection_checking;
bool enable_http2;
size_t spdy_session_max_recv_window_size;
- size_t spdy_stream_max_recv_window_size;
+ // HTTP/2 connection settings.
+ // Unknown settings will still be sent to the server.
+ SettingsMap http2_settings;
// Source of time for SPDY connections.
SpdySessionPool::TimeFunc time_func;
// Whether to enable HTTP/2 Alt-Svc entries with hostname different than
@@ -110,9 +121,6 @@ class NET_EXPORT HttpNetworkSession
bool enable_quic;
// Disable QUIC if a connection times out with open streams.
bool disable_quic_on_timeout_with_open_streams;
- // Instruct QUIC to use consistent ephemeral ports when talking to
- // the same server.
- bool enable_quic_port_selection;
// Disables QUIC's 0-RTT behavior.
bool quic_always_require_handshake_confirmation;
// Disables QUIC connection pooling.
@@ -195,6 +203,10 @@ class NET_EXPORT HttpNetworkSession
// Enable HTTP/0.9 for HTTP/HTTPS on ports other than the default one for
// each protocol.
bool http_09_on_non_default_ports_enabled;
+
+ // If true, only one pending preconnect is allowed to proxies that support
+ // request priorities.
+ bool restrict_to_one_preconnect_for_proxies;
};
enum SocketPoolType {
@@ -270,6 +282,8 @@ class NET_EXPORT HttpNetworkSession
bool IsProtocolEnabled(NextProto protocol) const;
+ void SetServerPushDelegate(std::unique_ptr<ServerPushDelegate> push_delegate);
+
// Populates |*alpn_protos| with protocols to be used with ALPN.
void GetAlpnProtos(NextProtoVector* alpn_protos) const;
@@ -279,6 +293,17 @@ class NET_EXPORT HttpNetworkSession
SSLConfig* server_config,
SSLConfig* proxy_config) const;
+ // Dumps memory allocation stats. |parent_dump_absolute_name| is the name
+ // used by the parent MemoryAllocatorDump in the memory dump hierarchy.
+ void DumpMemoryStats(base::trace_event::ProcessMemoryDump* pmd,
+ const std::string& parent_absolute_name) const;
+
+ // Evaluates if QUIC is enabled for new streams.
+ bool IsQuicEnabled() const;
+
+ // Disable QUIC for new streams.
+ void DisableQuic();
+
private:
friend class HttpNetworkSessionPeer;
@@ -304,6 +329,7 @@ class NET_EXPORT HttpNetworkSession
SSLClientAuthCache ssl_client_auth_cache_;
std::unique_ptr<ClientSocketPoolManager> normal_socket_pool_manager_;
std::unique_ptr<ClientSocketPoolManager> websocket_socket_pool_manager_;
+ std::unique_ptr<ServerPushDelegate> push_delegate_;
QuicStreamFactory quic_stream_factory_;
SpdySessionPool spdy_session_pool_;
std::unique_ptr<HttpStreamFactory> http_stream_factory_;
diff --git a/chromium/net/http/http_network_session_peer.h b/chromium/net/http/http_network_session_peer.h
index e162c7e67b1..b07d130d3ba 100644
--- a/chromium/net/http/http_network_session_peer.h
+++ b/chromium/net/http/http_network_session_peer.h
@@ -17,7 +17,6 @@ class ClientSocketPoolManager;
class HttpNetworkSession;
class HttpStreamFactory;
class NetworkThrottleManager;
-class ProxyService;
class NET_EXPORT_PRIVATE HttpNetworkSessionPeer {
public:
diff --git a/chromium/net/http/http_network_transaction.cc b/chromium/net/http/http_network_transaction.cc
index a8a7d1ae7b7..b7ceb430bd9 100644
--- a/chromium/net/http/http_network_transaction.cc
+++ b/chromium/net/http/http_network_transaction.cc
@@ -21,7 +21,6 @@
#include "base/stl_util.h"
#include "base/strings/string_number_conversions.h"
#include "base/strings/string_util.h"
-#include "base/strings/stringprintf.h"
#include "base/time/time.h"
#include "base/values.h"
#include "build/build_config.h"
@@ -592,9 +591,10 @@ void HttpNetworkTransaction::GetConnectionAttempts(
*out = connection_attempts_;
}
-void HttpNetworkTransaction::OnThrottleStateChanged() {
+void HttpNetworkTransaction::OnThrottleUnblocked(
+ NetworkThrottleManager::Throttle* throttle) {
// TODO(rdsmith): This DCHECK is dependent on the only transition
- // being from throttled->unthrottled. That is true right now, but may not
+ // being from blocked->unblocked. That is true right now, but may not
// be so in the future.
DCHECK_EQ(STATE_THROTTLE_COMPLETE, next_state_);
@@ -797,11 +797,12 @@ int HttpNetworkTransaction::DoLoop(int result) {
}
int HttpNetworkTransaction::DoThrottle() {
+ DCHECK(!throttle_);
throttle_ = session_->throttler()->CreateThrottle(
this, priority_, (request_->load_flags & LOAD_IGNORE_LIMITS) != 0);
next_state_ = STATE_THROTTLE_COMPLETE;
- if (throttle_->IsThrottled()) {
+ if (throttle_->IsBlocked()) {
net_log_.BeginEvent(NetLogEventType::HTTP_TRANSACTION_THROTTLED);
return ERR_IO_PENDING;
}
@@ -811,7 +812,7 @@ int HttpNetworkTransaction::DoThrottle() {
int HttpNetworkTransaction::DoThrottleComplete() {
DCHECK(throttle_);
- DCHECK(!throttle_->IsThrottled());
+ DCHECK(!throttle_->IsBlocked());
next_state_ = STATE_NOTIFY_BEFORE_CREATE_STREAM;
diff --git a/chromium/net/http/http_network_transaction.h b/chromium/net/http/http_network_transaction.h
index aa49723c23c..9d9a5629882 100644
--- a/chromium/net/http/http_network_transaction.h
+++ b/chromium/net/http/http_network_transaction.h
@@ -38,14 +38,12 @@ class ECPrivateKey;
namespace net {
class BidirectionalStreamImpl;
-class ClientSocketHandle;
class HttpAuthController;
class HttpNetworkSession;
class HttpStream;
class HttpStreamRequest;
class IOBuffer;
class ProxyInfo;
-class SpdySession;
class SSLPrivateKey;
struct HttpRequestInfo;
@@ -124,23 +122,14 @@ class NET_EXPORT_PRIVATE HttpNetworkTransaction
void GetConnectionAttempts(ConnectionAttempts* out) const override;
// NetworkThrottleManager::Delegate methods:
- void OnThrottleStateChanged() override;
+ void OnThrottleUnblocked(NetworkThrottleManager::Throttle* throttle) override;
private:
- friend class HttpNetworkTransactionSSLTest;
-
- FRIEND_TEST_ALL_PREFIXES(HttpNetworkTransactionTest,
- ResetStateForRestart);
- FRIEND_TEST_ALL_PREFIXES(HttpNetworkTransactionTest, EnableNPN);
- FRIEND_TEST_ALL_PREFIXES(HttpNetworkTransactionTest, DisableNPN);
- FRIEND_TEST_ALL_PREFIXES(SpdyNetworkTransactionTest,
- WindowUpdateReceived);
- FRIEND_TEST_ALL_PREFIXES(SpdyNetworkTransactionTest,
- WindowUpdateSent);
- FRIEND_TEST_ALL_PREFIXES(SpdyNetworkTransactionTest,
- WindowUpdateOverflow);
- FRIEND_TEST_ALL_PREFIXES(SpdyNetworkTransactionTest,
- FlowControlStallResume);
+ FRIEND_TEST_ALL_PREFIXES(HttpNetworkTransactionTest, ResetStateForRestart);
+ FRIEND_TEST_ALL_PREFIXES(SpdyNetworkTransactionTest, WindowUpdateReceived);
+ FRIEND_TEST_ALL_PREFIXES(SpdyNetworkTransactionTest, WindowUpdateSent);
+ FRIEND_TEST_ALL_PREFIXES(SpdyNetworkTransactionTest, WindowUpdateOverflow);
+ FRIEND_TEST_ALL_PREFIXES(SpdyNetworkTransactionTest, FlowControlStallResume);
FRIEND_TEST_ALL_PREFIXES(SpdyNetworkTransactionTest,
FlowControlStallResumeAfterSettings);
FRIEND_TEST_ALL_PREFIXES(SpdyNetworkTransactionTest,
diff --git a/chromium/net/http/http_network_transaction_ssl_unittest.cc b/chromium/net/http/http_network_transaction_ssl_unittest.cc
index b8636d38430..5ad359b44ba 100644
--- a/chromium/net/http/http_network_transaction_ssl_unittest.cc
+++ b/chromium/net/http/http_network_transaction_ssl_unittest.cc
@@ -11,6 +11,7 @@
#include "base/memory/ref_counted.h"
#include "base/run_loop.h"
#include "base/threading/thread.h"
+#include "base/threading/thread_task_runner_handle.h"
#include "net/base/request_priority.h"
#include "net/cert/ct_policy_enforcer.h"
#include "net/cert/mock_cert_verifier.h"
@@ -37,36 +38,6 @@ namespace net {
namespace {
-class TLS10SSLConfigService : public SSLConfigService {
- public:
- TLS10SSLConfigService() {
- ssl_config_.version_min = SSL_PROTOCOL_VERSION_TLS1;
- ssl_config_.version_max = SSL_PROTOCOL_VERSION_TLS1;
- }
-
- void GetSSLConfig(SSLConfig* config) override { *config = ssl_config_; }
-
- private:
- ~TLS10SSLConfigService() override {}
-
- SSLConfig ssl_config_;
-};
-
-class TLS12SSLConfigService : public SSLConfigService {
- public:
- TLS12SSLConfigService() {
- ssl_config_.version_min = SSL_PROTOCOL_VERSION_TLS1;
- ssl_config_.version_max = SSL_PROTOCOL_VERSION_TLS1_2;
- }
-
- void GetSSLConfig(SSLConfig* config) override { *config = ssl_config_; }
-
- private:
- ~TLS12SSLConfigService() override {}
-
- SSLConfig ssl_config_;
-};
-
class TokenBindingSSLConfigService : public SSLConfigService {
public:
TokenBindingSSLConfigService() {
@@ -86,7 +57,7 @@ class TokenBindingSSLConfigService : public SSLConfigService {
class HttpNetworkTransactionSSLTest : public testing::Test {
protected:
void SetUp() override {
- ssl_config_service_ = new TLS10SSLConfigService;
+ ssl_config_service_ = new TokenBindingSSLConfigService;
session_params_.ssl_config_service = ssl_config_service_.get();
auth_handler_factory_.reset(new HttpAuthHandlerMock::Factory());
@@ -112,10 +83,6 @@ class HttpNetworkTransactionSSLTest : public testing::Test {
return request_info;
}
- SSLConfig& GetServerSSLConfig(HttpNetworkTransaction* trans) {
- return trans->server_ssl_config_;
- }
-
scoped_refptr<SSLConfigService> ssl_config_service_;
std::unique_ptr<HttpAuthHandlerMock::Factory> auth_handler_factory_;
std::unique_ptr<ProxyService> proxy_service_;
@@ -133,8 +100,6 @@ class HttpNetworkTransactionSSLTest : public testing::Test {
#if !defined(OS_IOS)
TEST_F(HttpNetworkTransactionSSLTest, TokenBinding) {
- ssl_config_service_ = new TokenBindingSSLConfigService;
- session_params_.ssl_config_service = ssl_config_service_.get();
ChannelIDService channel_id_service(new DefaultChannelIDStore(NULL),
base::ThreadTaskRunnerHandle::Get());
session_params_.channel_id_service = &channel_id_service;
@@ -185,8 +150,6 @@ TEST_F(HttpNetworkTransactionSSLTest, TokenBinding) {
}
TEST_F(HttpNetworkTransactionSSLTest, NoTokenBindingOverHttp) {
- ssl_config_service_ = new TokenBindingSSLConfigService;
- session_params_.ssl_config_service = ssl_config_service_.get();
ChannelIDService channel_id_service(new DefaultChannelIDStore(NULL),
base::ThreadTaskRunnerHandle::Get());
session_params_.channel_id_service = &channel_id_service;
@@ -218,9 +181,6 @@ TEST_F(HttpNetworkTransactionSSLTest, NoTokenBindingOverHttp) {
// Regression test for https://crbug.com/667683.
TEST_F(HttpNetworkTransactionSSLTest, TokenBindingAsync) {
- ssl_config_service_ = new TokenBindingSSLConfigService;
- session_params_.ssl_config_service = ssl_config_service_.get();
-
// Create a separate thread for ChannelIDService
// so that asynchronous Channel ID creation can be delayed.
base::Thread channel_id_thread("ThreadForChannelIDService");
@@ -241,14 +201,14 @@ TEST_F(HttpNetworkTransactionSSLTest, TokenBindingAsync) {
StaticSocketDataProvider data(reads, arraysize(reads), nullptr, 0);
mock_socket_factory_.AddSocketDataProvider(&data);
- HttpNetworkSession session(session_params_);
- HttpNetworkTransaction trans(DEFAULT_PRIORITY, &session);
-
HttpRequestInfo request_info;
request_info.url = GURL("https://www.example.com/");
request_info.method = "GET";
request_info.token_binding_referrer = "encrypted.example.com";
+ HttpNetworkSession session(session_params_);
+ HttpNetworkTransaction trans(DEFAULT_PRIORITY, &session);
+
TestCompletionCallback callback;
int rv = trans.Start(&request_info, callback.callback(), NetLogWithSource());
EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
diff --git a/chromium/net/http/http_network_transaction_unittest.cc b/chromium/net/http/http_network_transaction_unittest.cc
index daec89d43ff..ce38cf20002 100644
--- a/chromium/net/http/http_network_transaction_unittest.cc
+++ b/chromium/net/http/http_network_transaction_unittest.cc
@@ -135,7 +135,7 @@ class TestNetworkStreamThrottler : public NetworkThrottleManager {
void UnthrottleAllRequests() {
std::set<TestThrottle*> outstanding_throttles_copy(outstanding_throttles_);
for (auto& throttle : outstanding_throttles_copy) {
- if (throttle->IsThrottled())
+ if (throttle->IsBlocked())
throttle->Unthrottle();
}
}
@@ -162,7 +162,11 @@ class TestNetworkStreamThrottler : public NetworkThrottleManager {
~TestThrottle() override { throttler_->OnThrottleDestroyed(this); }
// Throttle
- bool IsThrottled() const override { return throttled_; }
+ bool IsBlocked() const override { return throttled_; }
+ RequestPriority Priority() const override {
+ NOTREACHED();
+ return IDLE;
+ }
void SetPriority(RequestPriority priority) override {
throttler_->SetPriorityCalled(priority);
}
@@ -176,7 +180,7 @@ class TestNetworkStreamThrottler : public NetworkThrottleManager {
EXPECT_TRUE(throttled_);
throttled_ = false;
- delegate_->OnThrottleStateChanged();
+ delegate_->OnThrottleUnblocked(this);
}
bool throttled_;
@@ -843,10 +847,10 @@ TEST_F(HttpNetworkTransactionTest, SimpleGETNoHeadersWeirdPort) {
std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
+ HttpRequestInfo request;
std::unique_ptr<HttpTransaction> trans(
new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
- HttpRequestInfo request;
request.method = "GET";
request.url = GURL("http://www.example.com:2000/");
TestCompletionCallback callback;
@@ -866,10 +870,10 @@ TEST_F(HttpNetworkTransactionTest, SimpleGETNoHeadersWeirdPortAllowed) {
session_deps_.http_09_on_non_default_ports_enabled = true;
std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
+ HttpRequestInfo request;
std::unique_ptr<HttpTransaction> trans(
new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
- HttpRequestInfo request;
request.method = "GET";
request.url = GURL("http://www.example.com:2000/");
TestCompletionCallback callback;
@@ -4780,7 +4784,7 @@ TEST_F(HttpNetworkTransactionTest, HttpsProxySpdyGetWithProxyAuth) {
"proxy-authenticate", "Basic realm=\"MyRealm1\""
};
SpdySerializedFrame resp_authentication(spdy_util_.ConstructSpdyReplyError(
- "407 Proxy Authentication Required", kExtraAuthenticationHeaders,
+ "407", kExtraAuthenticationHeaders,
arraysize(kExtraAuthenticationHeaders) / 2, 1));
SpdySerializedFrame body_authentication(
spdy_util_.ConstructSpdyDataFrame(1, true));
@@ -4788,7 +4792,7 @@ TEST_F(HttpNetworkTransactionTest, HttpsProxySpdyGetWithProxyAuth) {
SpdySerializedFrame body_data(spdy_util_.ConstructSpdyDataFrame(3, true));
MockRead spdy_reads[] = {
CreateMockRead(resp_authentication, 1),
- CreateMockRead(body_authentication, 2),
+ CreateMockRead(body_authentication, 2, SYNCHRONOUS),
CreateMockRead(resp_data, 4),
CreateMockRead(body_data, 5),
MockRead(ASYNC, 0, 6),
@@ -5251,9 +5255,9 @@ TEST_F(HttpNetworkTransactionTest,
MockRead spdy_reads[] = {
CreateMockRead(conn_resp1, 1, ASYNC),
CreateMockRead(wrapped_get_resp1, 3, ASYNC),
- CreateMockRead(wrapped_body1, 4, ASYNC),
+ CreateMockRead(wrapped_body1, 4, SYNCHRONOUS),
CreateMockRead(wrapped_get_resp2, 6, ASYNC),
- CreateMockRead(wrapped_body2, 7, ASYNC),
+ CreateMockRead(wrapped_body2, 7, SYNCHRONOUS),
MockRead(ASYNC, 0, 8),
};
@@ -7869,7 +7873,7 @@ TEST_F(HttpNetworkTransactionTest, RedirectOfHttpsConnectViaSpdyProxy) {
"http://login.example.com/",
};
SpdySerializedFrame resp(spdy_util_.ConstructSpdyReplyError(
- "302 Redirect", kExtraHeaders, arraysize(kExtraHeaders) / 2, 1));
+ "302", kExtraHeaders, arraysize(kExtraHeaders) / 2, 1));
MockRead data_reads[] = {
CreateMockRead(resp, 1), MockRead(ASYNC, 0, 3), // EOF
};
@@ -7965,7 +7969,7 @@ TEST_F(HttpNetworkTransactionTest, ErrorResponseToHttpsConnectViaSpdyProxy) {
"http://login.example.com/",
};
SpdySerializedFrame resp(spdy_util_.ConstructSpdyReplyError(
- "404 Not Found", kExtraHeaders, arraysize(kExtraHeaders) / 2, 1));
+ "404", kExtraHeaders, arraysize(kExtraHeaders) / 2, 1));
SpdySerializedFrame body(spdy_util_.ConstructSpdyDataFrame(
1, "The host does not exist", 23, true));
MockRead data_reads[] = {
@@ -8153,15 +8157,18 @@ TEST_F(HttpNetworkTransactionTest, CrossOriginSPDYProxyPush) {
BoundTestNetLog log;
session_deps_.net_log = log.bound().net_log();
- session_deps_.proxy_delegate.reset(proxy_delegate.release());
+ session_deps_.proxy_delegate = std::move(proxy_delegate);
std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
SpdySerializedFrame stream1_syn(
spdy_util_.ConstructSpdyGet("http://www.example.org/", 1, LOWEST));
+ SpdySerializedFrame stream2_priority(
+ spdy_util_.ConstructSpdyPriority(2, 1, IDLE, true));
MockWrite spdy_writes[] = {
CreateMockWrite(stream1_syn, 0, ASYNC),
+ CreateMockWrite(stream2_priority, 3, ASYNC),
};
SpdySerializedFrame stream1_reply(
@@ -8178,9 +8185,9 @@ TEST_F(HttpNetworkTransactionTest, CrossOriginSPDYProxyPush) {
MockRead spdy_reads[] = {
CreateMockRead(stream1_reply, 1, ASYNC),
CreateMockRead(stream2_syn, 2, ASYNC),
- CreateMockRead(stream1_body, 3, ASYNC),
- CreateMockRead(stream2_body, 4, ASYNC),
- MockRead(SYNCHRONOUS, ERR_IO_PENDING, 5), // Force a hang
+ CreateMockRead(stream1_body, 4, ASYNC),
+ CreateMockRead(stream2_body, 5, ASYNC),
+ MockRead(SYNCHRONOUS, ERR_IO_PENDING, 6), // Force a hang
};
SequencedSocketData spdy_data(spdy_reads, arraysize(spdy_reads), spdy_writes,
@@ -8264,7 +8271,7 @@ TEST_F(HttpNetworkTransactionTest, CrossOriginProxyPushCorrectness) {
session_deps_.net_log = log.bound().net_log();
// Enable cross-origin push.
- session_deps_.proxy_delegate.reset(proxy_delegate.release());
+ session_deps_.proxy_delegate = std::move(proxy_delegate);
std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
@@ -8345,15 +8352,18 @@ TEST_F(HttpNetworkTransactionTest, SameOriginProxyPushCorrectness) {
session_deps_.net_log = log.bound().net_log();
// Enable cross-origin push.
- session_deps_.proxy_delegate.reset(proxy_delegate.release());
+ session_deps_.proxy_delegate = std::move(proxy_delegate);
std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
SpdySerializedFrame stream1_syn(
spdy_util_.ConstructSpdyGet("http://www.example.org/", 1, LOWEST));
+ SpdySerializedFrame stream2_priority(
+ spdy_util_.ConstructSpdyPriority(2, 1, IDLE, true));
MockWrite spdy_writes[] = {
CreateMockWrite(stream1_syn, 0, ASYNC),
+ CreateMockWrite(stream2_priority, 3, ASYNC),
};
SpdySerializedFrame stream1_reply(
@@ -8372,9 +8382,9 @@ TEST_F(HttpNetworkTransactionTest, SameOriginProxyPushCorrectness) {
MockRead spdy_reads[] = {
CreateMockRead(stream1_reply, 1, ASYNC),
CreateMockRead(stream2_syn, 2, ASYNC),
- CreateMockRead(stream1_body, 3, ASYNC),
- CreateMockRead(stream2_body, 4, ASYNC),
- MockRead(SYNCHRONOUS, ERR_IO_PENDING, 5), // Force a hang
+ CreateMockRead(stream1_body, 4, ASYNC),
+ CreateMockRead(stream2_body, 5, ASYNC),
+ MockRead(SYNCHRONOUS, ERR_IO_PENDING, 6), // Force a hang
};
SequencedSocketData spdy_data(spdy_reads, arraysize(spdy_reads), spdy_writes,
@@ -10389,8 +10399,8 @@ TEST_F(HttpNetworkTransactionTest, IdentifyQuicBroken) {
// Mark the QUIC alternative service as broken.
http_server_properties->MarkAlternativeServiceBroken(alternative_service);
- HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
HttpRequestInfo request;
+ HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
request.method = "GET";
request.url = GURL(origin_url);
TestCompletionCallback callback;
@@ -10462,8 +10472,8 @@ TEST_F(HttpNetworkTransactionTest, IdentifyQuicNotBroken) {
const AlternativeServiceVector alternative_service_vector =
http_server_properties->GetAlternativeServices(server);
- HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
HttpRequestInfo request;
+ HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
request.method = "GET";
request.url = GURL(origin_url);
TestCompletionCallback callback;
@@ -13814,8 +13824,8 @@ TEST_F(HttpNetworkTransactionTest, AlternativeServiceNotOnHttp11) {
http_server_properties->SetAlternativeService(server, alternative_service,
expiration);
- HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
HttpRequestInfo request;
+ HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
request.method = "GET";
request.url = GURL("https://www.example.org:443");
TestCompletionCallback callback;
@@ -13989,8 +13999,8 @@ TEST_F(HttpNetworkTransactionTest, AlternativeServiceShouldNotPoolToHttp11) {
expiration);
// First transaction to alternative to open an HTTP/1.1 socket.
- HttpNetworkTransaction trans1(DEFAULT_PRIORITY, session.get());
HttpRequestInfo request1;
+ HttpNetworkTransaction trans1(DEFAULT_PRIORITY, session.get());
request1.method = "GET";
request1.url = GURL(alternative_url);
request1.load_flags = 0;
@@ -14013,8 +14023,8 @@ TEST_F(HttpNetworkTransactionTest, AlternativeServiceShouldNotPoolToHttp11) {
// finds one which is HTTP/1.1, and should ignore it, and should not try to
// open other connections to alternative server. The Job to server fails, so
// this request fails.
- HttpNetworkTransaction trans2(DEFAULT_PRIORITY, session.get());
HttpRequestInfo request2;
+ HttpNetworkTransaction trans2(DEFAULT_PRIORITY, session.get());
request2.method = "GET";
request2.url = GURL(origin_url);
request2.load_flags = 0;
@@ -14025,8 +14035,8 @@ TEST_F(HttpNetworkTransactionTest, AlternativeServiceShouldNotPoolToHttp11) {
// Another transaction to alternative. This is to test that the HTTP/1.1
// socket is still open and in the pool.
- HttpNetworkTransaction trans3(DEFAULT_PRIORITY, session.get());
HttpRequestInfo request3;
+ HttpNetworkTransaction trans3(DEFAULT_PRIORITY, session.get());
request3.method = "GET";
request3.url = GURL(alternative_url);
request3.load_flags = 0;
@@ -15136,11 +15146,11 @@ TEST_F(HttpNetworkTransactionTest, SetStreamRequestPriorityOnStart) {
FakeStreamFactory* fake_factory = new FakeStreamFactory();
peer.SetHttpStreamFactory(std::unique_ptr<HttpStreamFactory>(fake_factory));
+ HttpRequestInfo request;
HttpNetworkTransaction trans(LOW, session.get());
ASSERT_FALSE(fake_factory->last_stream_request());
- HttpRequestInfo request;
TestCompletionCallback callback;
EXPECT_EQ(ERR_IO_PENDING,
trans.Start(&request, callback.callback(), NetLogWithSource()));
@@ -15159,9 +15169,9 @@ TEST_F(HttpNetworkTransactionTest, SetStreamRequestPriority) {
FakeStreamFactory* fake_factory = new FakeStreamFactory();
peer.SetHttpStreamFactory(std::unique_ptr<HttpStreamFactory>(fake_factory));
+ HttpRequestInfo request;
HttpNetworkTransaction trans(LOW, session.get());
- HttpRequestInfo request;
TestCompletionCallback callback;
EXPECT_EQ(ERR_IO_PENDING,
trans.Start(&request, callback.callback(), NetLogWithSource()));
@@ -15184,9 +15194,9 @@ TEST_F(HttpNetworkTransactionTest, SetStreamPriority) {
FakeStreamFactory* fake_factory = new FakeStreamFactory();
peer.SetHttpStreamFactory(std::unique_ptr<HttpStreamFactory>(fake_factory));
+ HttpRequestInfo request;
HttpNetworkTransaction trans(LOW, session.get());
- HttpRequestInfo request;
TestCompletionCallback callback;
EXPECT_EQ(ERR_IO_PENDING,
trans.Start(&request, callback.callback(), NetLogWithSource()));
@@ -15216,11 +15226,11 @@ TEST_F(HttpNetworkTransactionTest, CreateWebSocketHandshakeStream) {
peer.SetHttpStreamFactoryForWebSocket(
std::unique_ptr<HttpStreamFactory>(fake_factory));
+ HttpRequestInfo request;
HttpNetworkTransaction trans(LOW, session.get());
trans.SetWebSocketHandshakeStreamCreateHelper(
&websocket_stream_create_helper);
- HttpRequestInfo request;
TestCompletionCallback callback;
request.method = "GET";
request.url = GURL(test_cases[i]);
diff --git a/chromium/net/http/http_proxy_client_socket.cc b/chromium/net/http/http_proxy_client_socket.cc
index 82538dff80e..ed8c8d3fb60 100644
--- a/chromium/net/http/http_proxy_client_socket.cc
+++ b/chromium/net/http/http_proxy_client_socket.cc
@@ -8,7 +8,6 @@
#include "base/bind_helpers.h"
#include "base/profiler/scoped_tracker.h"
#include "base/strings/string_util.h"
-#include "base/strings/stringprintf.h"
#include "base/values.h"
#include "net/base/auth.h"
#include "net/base/host_port_pair.h"
@@ -175,9 +174,9 @@ bool HttpProxyClientSocket::WasEverUsed() const {
return false;
}
-bool HttpProxyClientSocket::WasNpnNegotiated() const {
+bool HttpProxyClientSocket::WasAlpnNegotiated() const {
if (transport_.get() && transport_->socket()) {
- return transport_->socket()->WasNpnNegotiated();
+ return transport_->socket()->WasAlpnNegotiated();
}
NOTREACHED();
return false;
diff --git a/chromium/net/http/http_proxy_client_socket.h b/chromium/net/http/http_proxy_client_socket.h
index e383dd796b7..f49f557a710 100644
--- a/chromium/net/http/http_proxy_client_socket.h
+++ b/chromium/net/http/http_proxy_client_socket.h
@@ -25,7 +25,6 @@
namespace net {
-class AddressList;
class ClientSocketHandle;
class GrowableIOBuffer;
class HttpStream;
@@ -69,7 +68,7 @@ class NET_EXPORT_PRIVATE HttpProxyClientSocket : public ProxyClientSocket {
void SetSubresourceSpeculation() override;
void SetOmniboxSpeculation() override;
bool WasEverUsed() const override;
- bool WasNpnNegotiated() const override;
+ bool WasAlpnNegotiated() const override;
NextProto GetNegotiatedProtocol() const override;
bool GetSSLInfo(SSLInfo* ssl_info) override;
void GetConnectionAttempts(ConnectionAttempts* out) const override;
diff --git a/chromium/net/http/http_proxy_client_socket_pool.cc b/chromium/net/http/http_proxy_client_socket_pool.cc
index ad69060925d..5d49616a436 100644
--- a/chromium/net/http/http_proxy_client_socket_pool.cc
+++ b/chromium/net/http/http_proxy_client_socket_pool.cc
@@ -91,7 +91,8 @@ HttpProxyConnectJob::HttpProxyConnectJob(
priority,
respect_limits,
delegate,
- NetLogWithSource::Make(net_log, NetLogSourceType::CONNECT_JOB)),
+ NetLogWithSource::Make(net_log,
+ NetLogSourceType::HTTP_PROXY_CONNECT_JOB)),
client_socket_(new HttpProxyClientSocketWrapper(
group_name,
priority,
diff --git a/chromium/net/http/http_proxy_client_socket_pool.h b/chromium/net/http/http_proxy_client_socket_pool.h
index 4373fd207d5..5a258eb7121 100644
--- a/chromium/net/http/http_proxy_client_socket_pool.h
+++ b/chromium/net/http/http_proxy_client_socket_pool.h
@@ -32,7 +32,6 @@ class ProxyDelegate;
class SSLClientSocketPool;
class SSLSocketParams;
class SpdySessionPool;
-class SpdyStream;
class TransportClientSocketPool;
class TransportSocketParams;
diff --git a/chromium/net/http/http_proxy_client_socket_pool_unittest.cc b/chromium/net/http/http_proxy_client_socket_pool_unittest.cc
index d798e8e7ec8..19b0a4f6197 100644
--- a/chromium/net/http/http_proxy_client_socket_pool_unittest.cc
+++ b/chromium/net/http/http_proxy_client_socket_pool_unittest.cc
@@ -649,7 +649,7 @@ TEST_P(HttpProxyClientSocketPoolTest, TunnelSetupRedirect) {
};
const int responseHeadersSize = arraysize(responseHeaders) / 2;
SpdySerializedFrame resp(spdy_util_.ConstructSpdyReplyError(
- "302 Found", responseHeaders, responseHeadersSize, 1));
+ "302", responseHeaders, responseHeadersSize, 1));
MockRead spdy_reads[] = {
CreateMockRead(resp, 1, ASYNC), MockRead(ASYNC, 0, 2),
};
diff --git a/chromium/net/http/http_proxy_client_socket_wrapper.cc b/chromium/net/http/http_proxy_client_socket_wrapper.cc
index f389141d2f7..f5e258e86cd 100644
--- a/chromium/net/http/http_proxy_client_socket_wrapper.cc
+++ b/chromium/net/http/http_proxy_client_socket_wrapper.cc
@@ -234,9 +234,9 @@ bool HttpProxyClientSocketWrapper::WasEverUsed() const {
return false;
}
-bool HttpProxyClientSocketWrapper::WasNpnNegotiated() const {
+bool HttpProxyClientSocketWrapper::WasAlpnNegotiated() const {
if (transport_socket_)
- return transport_socket_->WasNpnNegotiated();
+ return transport_socket_->WasAlpnNegotiated();
return false;
}
diff --git a/chromium/net/http/http_proxy_client_socket_wrapper.h b/chromium/net/http/http_proxy_client_socket_wrapper.h
index eb8dd7ac2a7..d6184a88bed 100644
--- a/chromium/net/http/http_proxy_client_socket_wrapper.h
+++ b/chromium/net/http/http_proxy_client_socket_wrapper.h
@@ -97,7 +97,7 @@ class HttpProxyClientSocketWrapper : public ProxyClientSocket {
void SetSubresourceSpeculation() override;
void SetOmniboxSpeculation() override;
bool WasEverUsed() const override;
- bool WasNpnNegotiated() const override;
+ bool WasAlpnNegotiated() const override;
NextProto GetNegotiatedProtocol() const override;
bool GetSSLInfo(SSLInfo* ssl_info) override;
void GetConnectionAttempts(ConnectionAttempts* out) const override;
diff --git a/chromium/net/http/http_response_headers.cc b/chromium/net/http/http_response_headers.cc
index dd0977c3dca..b849d784855 100644
--- a/chromium/net/http/http_response_headers.cc
+++ b/chromium/net/http/http_response_headers.cc
@@ -1303,118 +1303,20 @@ int64_t HttpResponseHeaders::GetInt64HeaderValue(
return result;
}
-// From RFC 2616 14.16:
-// content-range-spec =
-// bytes-unit SP byte-range-resp-spec "/" ( instance-length | "*" )
-// byte-range-resp-spec = (first-byte-pos "-" last-byte-pos) | "*"
-// instance-length = 1*DIGIT
-// bytes-unit = "bytes"
-bool HttpResponseHeaders::GetContentRange(int64_t* first_byte_position,
- int64_t* last_byte_position,
- int64_t* instance_length) const {
+bool HttpResponseHeaders::GetContentRangeFor206(
+ int64_t* first_byte_position,
+ int64_t* last_byte_position,
+ int64_t* instance_length) const {
size_t iter = 0;
std::string content_range_spec;
- *first_byte_position = *last_byte_position = *instance_length = -1;
- if (!EnumerateHeader(&iter, kContentRange, &content_range_spec))
- return false;
-
- // If the header value is empty, we have an invalid header.
- if (content_range_spec.empty())
- return false;
-
- size_t space_position = content_range_spec.find(' ');
- if (space_position == std::string::npos)
- return false;
-
- // Invalid header if it doesn't contain "bytes-unit".
- std::string::const_iterator content_range_spec_begin =
- content_range_spec.begin();
- std::string::const_iterator content_range_spec_end =
- content_range_spec.begin() + space_position;
- HttpUtil::TrimLWS(&content_range_spec_begin, &content_range_spec_end);
- if (!base::LowerCaseEqualsASCII(
- base::StringPiece(content_range_spec_begin, content_range_spec_end),
- "bytes")) {
+ if (!EnumerateHeader(&iter, kContentRange, &content_range_spec)) {
+ *first_byte_position = *last_byte_position = *instance_length = -1;
return false;
}
- size_t slash_position = content_range_spec.find('/', space_position + 1);
- if (slash_position == std::string::npos)
- return false;
-
- // Obtain the part behind the space and before slash.
- std::string::const_iterator byte_range_resp_spec_begin =
- content_range_spec.begin() + space_position + 1;
- std::string::const_iterator byte_range_resp_spec_end =
- content_range_spec.begin() + slash_position;
- HttpUtil::TrimLWS(&byte_range_resp_spec_begin, &byte_range_resp_spec_end);
-
- // Parse the byte-range-resp-spec part.
- std::string byte_range_resp_spec(byte_range_resp_spec_begin,
- byte_range_resp_spec_end);
- // If byte-range-resp-spec != "*".
- if (!base::LowerCaseEqualsASCII(byte_range_resp_spec, "*")) {
- size_t minus_position = byte_range_resp_spec.find('-');
- if (minus_position != std::string::npos) {
- // Obtain first-byte-pos.
- std::string::const_iterator first_byte_pos_begin =
- byte_range_resp_spec.begin();
- std::string::const_iterator first_byte_pos_end =
- byte_range_resp_spec.begin() + minus_position;
- HttpUtil::TrimLWS(&first_byte_pos_begin, &first_byte_pos_end);
-
- bool ok = base::StringToInt64(StringPiece(first_byte_pos_begin,
- first_byte_pos_end),
- first_byte_position);
-
- // Obtain last-byte-pos.
- std::string::const_iterator last_byte_pos_begin =
- byte_range_resp_spec.begin() + minus_position + 1;
- std::string::const_iterator last_byte_pos_end =
- byte_range_resp_spec.end();
- HttpUtil::TrimLWS(&last_byte_pos_begin, &last_byte_pos_end);
-
- ok &= base::StringToInt64(StringPiece(last_byte_pos_begin,
- last_byte_pos_end),
- last_byte_position);
- if (!ok) {
- *first_byte_position = *last_byte_position = -1;
- return false;
- }
- if (*first_byte_position < 0 || *last_byte_position < 0 ||
- *first_byte_position > *last_byte_position)
- return false;
- } else {
- return false;
- }
- }
-
- // Parse the instance-length part.
- // If instance-length == "*".
- std::string::const_iterator instance_length_begin =
- content_range_spec.begin() + slash_position + 1;
- std::string::const_iterator instance_length_end =
- content_range_spec.end();
- HttpUtil::TrimLWS(&instance_length_begin, &instance_length_end);
-
- if (base::StartsWith(
- base::StringPiece(instance_length_begin, instance_length_end), "*",
- base::CompareCase::SENSITIVE)) {
- return false;
- } else if (!base::StringToInt64(StringPiece(instance_length_begin,
- instance_length_end),
- instance_length)) {
- *instance_length = -1;
- return false;
- }
-
- // We have all the values; let's verify that they make sense for a 206
- // response.
- if (*first_byte_position < 0 || *last_byte_position < 0 ||
- *instance_length < 0 || *instance_length - 1 < *last_byte_position)
- return false;
-
- return true;
+ return HttpUtil::ParseContentRangeHeaderFor206(
+ content_range_spec, first_byte_position, last_byte_position,
+ instance_length);
}
std::unique_ptr<base::Value> HttpResponseHeaders::NetLogCallback(
diff --git a/chromium/net/http/http_response_headers.h b/chromium/net/http/http_response_headers.h
index 39404cfd9f2..6dc14a9ac82 100644
--- a/chromium/net/http/http_response_headers.h
+++ b/chromium/net/http/http_response_headers.h
@@ -292,16 +292,16 @@ class NET_EXPORT HttpResponseHeaders
// such header in the response.
int64_t GetInt64HeaderValue(const std::string& header) const;
- // Extracts the values in a Content-Range header and returns true if they are
- // valid for a 206 response; otherwise returns false.
+ // Extracts the values in a Content-Range header and returns true if all three
+ // values are present and valid for a 206 response; otherwise returns false.
// The following values will be outputted:
// |*first_byte_position| = inclusive position of the first byte of the range
// |*last_byte_position| = inclusive position of the last byte of the range
// |*instance_length| = size in bytes of the object requested
- // If any of the above values is unknown, its value will be -1.
- bool GetContentRange(int64_t* first_byte_position,
- int64_t* last_byte_position,
- int64_t* instance_length) const;
+ // If this method returns false, then all of the outputs will be -1.
+ bool GetContentRangeFor206(int64_t* first_byte_position,
+ int64_t* last_byte_position,
+ int64_t* instance_length) const;
// Returns true if the response is chunk-encoded.
bool IsChunkEncoded() const;
diff --git a/chromium/net/http/http_response_headers_unittest.cc b/chromium/net/http/http_response_headers_unittest.cc
index 041972b76df..f24d1830470 100644
--- a/chromium/net/http/http_response_headers_unittest.cc
+++ b/chromium/net/http/http_response_headers_unittest.cc
@@ -780,9 +780,12 @@ TEST_P(RequiresValidationTest, RequiresValidation) {
const RequiresValidationTestData test = GetParam();
base::Time request_time, response_time, current_time;
- base::Time::FromString("Wed, 28 Nov 2007 00:40:09 GMT", &request_time);
- base::Time::FromString("Wed, 28 Nov 2007 00:40:12 GMT", &response_time);
- base::Time::FromString("Wed, 28 Nov 2007 00:45:20 GMT", &current_time);
+ ASSERT_TRUE(
+ base::Time::FromString("Wed, 28 Nov 2007 00:40:09 GMT", &request_time));
+ ASSERT_TRUE(
+ base::Time::FromString("Wed, 28 Nov 2007 00:40:12 GMT", &response_time));
+ ASSERT_TRUE(
+ base::Time::FromString("Wed, 28 Nov 2007 00:45:20 GMT", &current_time));
std::string headers(test.headers);
HeadersToRaw(&headers);
@@ -1338,7 +1341,7 @@ class ContentRangeTest
public ::testing::WithParamInterface<ContentRangeTestData> {
};
-TEST_P(ContentRangeTest, GetContentRange) {
+TEST_P(ContentRangeTest, GetContentRangeFor206) {
const ContentRangeTestData test = GetParam();
std::string headers(test.headers);
@@ -1348,9 +1351,8 @@ TEST_P(ContentRangeTest, GetContentRange) {
int64_t first_byte_position;
int64_t last_byte_position;
int64_t instance_size;
- bool return_value = parsed->GetContentRange(&first_byte_position,
- &last_byte_position,
- &instance_size);
+ bool return_value = parsed->GetContentRangeFor206(
+ &first_byte_position, &last_byte_position, &instance_size);
EXPECT_EQ(test.expected_return_value, return_value);
EXPECT_EQ(test.expected_first_byte_position, first_byte_position);
EXPECT_EQ(test.expected_last_byte_position, last_byte_position);
@@ -1363,99 +1365,16 @@ const ContentRangeTestData content_range_tests[] = {
"Content-Range:",
false, -1, -1, -1},
{"HTTP/1.1 206 Partial Content\n"
- "Content-Range: megabytes 0-10/50",
- false, -1, -1, -1},
- {"HTTP/1.1 206 Partial Content\n"
- "Content-Range: 0-10/50",
- false, -1, -1, -1},
- {"HTTP/1.1 206 Partial Content\n"
- "Content-Range: Bytes 0-50/51",
- true, 0, 50, 51},
- {"HTTP/1.1 206 Partial Content\n"
"Content-Range: bytes 0-50/51",
true, 0, 50, 51},
{"HTTP/1.1 206 Partial Content\n"
- "Content-Range: bytes\t0-50/51",
- false, -1, -1, -1},
- {"HTTP/1.1 206 Partial Content\n"
- "Content-Range: bytes 0-50/51",
- true, 0, 50, 51},
- {"HTTP/1.1 206 Partial Content\n"
- "Content-Range: bytes 0 - 50 \t / \t51",
- true, 0, 50, 51},
- {"HTTP/1.1 206 Partial Content\n"
- "Content-Range: bytes 0\t-\t50\t/\t51\t",
- true, 0, 50, 51},
- {"HTTP/1.1 206 Partial Content\n"
- "Content-Range: \tbytes\t\t\t 0\t-\t50\t/\t51\t",
- true, 0, 50, 51},
- {"HTTP/1.1 206 Partial Content\n"
- "Content-Range: \t bytes \t 0 - 50 / 5 1",
- false, 0, 50, -1},
- {"HTTP/1.1 206 Partial Content\n"
- "Content-Range: \t bytes \t 0 - 5 0 / 51",
- false, -1, -1, -1},
- {"HTTP/1.1 206 Partial Content\n"
"Content-Range: bytes 50-0/51",
- false, 50, 0, -1},
- {"HTTP/1.1 416 Requested range not satisfiable\n"
- "Content-Range: bytes * /*",
false, -1, -1, -1},
{"HTTP/1.1 416 Requested range not satisfiable\n"
- "Content-Range: bytes * / * ",
+ "Content-Range: bytes */*",
false, -1, -1, -1},
{"HTTP/1.1 206 Partial Content\n"
"Content-Range: bytes 0-50/*",
- false, 0, 50, -1},
- {"HTTP/1.1 206 Partial Content\n"
- "Content-Range: bytes 0-50 / * ",
- false, 0, 50, -1},
- {"HTTP/1.1 206 Partial Content\n"
- "Content-Range: bytes 0-10000000000/10000000001",
- true, 0, 10000000000ll, 10000000001ll},
- {"HTTP/1.1 206 Partial Content\n"
- "Content-Range: bytes 0-10000000000/10000000000",
- false, 0, 10000000000ll, 10000000000ll},
- // 64 bit wraparound.
- {"HTTP/1.1 206 Partial Content\n"
- "Content-Range: bytes 0 - 9223372036854775807 / 100",
- false, 0, std::numeric_limits<int64_t>::max(), 100},
- // 64 bit wraparound.
- {"HTTP/1.1 206 Partial Content\n"
- "Content-Range: bytes 0 - 100 / -9223372036854775808",
- false, 0, 100, std::numeric_limits<int64_t>::min()},
- {"HTTP/1.1 206 Partial Content\n"
- "Content-Range: bytes */50",
- false, -1, -1, 50},
- {"HTTP/1.1 206 Partial Content\n"
- "Content-Range: bytes 0-50/10",
- false, 0, 50, 10},
- {"HTTP/1.1 206 Partial Content\n"
- "Content-Range: bytes 40-50/45",
- false, 40, 50, 45},
- {"HTTP/1.1 206 Partial Content\n"
- "Content-Range: bytes 0-50/-10",
- false, 0, 50, -10},
- {"HTTP/1.1 206 Partial Content\n"
- "Content-Range: bytes 0-0/1",
- true, 0, 0, 1},
- {"HTTP/1.1 206 Partial Content\n"
- "Content-Range: bytes 0-40000000000000000000/40000000000000000001",
- false, -1, -1, -1},
- {"HTTP/1.1 206 Partial Content\n"
- "Content-Range: bytes 1-/100",
- false, -1, -1, -1},
- {"HTTP/1.1 206 Partial Content\n"
- "Content-Range: bytes -/100",
- false, -1, -1, -1},
- {"HTTP/1.1 206 Partial Content\n"
- "Content-Range: bytes -1/100",
- false, -1, -1, -1},
- {"HTTP/1.1 206 Partial Content\n"
- "Content-Range: bytes 0-1233/*",
- false, 0, 1233, -1},
- {"HTTP/1.1 206 Partial Content\n"
- "Content-Range: bytes -123 - -1/100",
false, -1, -1, -1},
};
diff --git a/chromium/net/http/http_response_info.cc b/chromium/net/http/http_response_info.cc
index 02bfefa8dfc..48a7a249c04 100644
--- a/chromium/net/http/http_response_info.cc
+++ b/chromium/net/http/http_response_info.cc
@@ -438,6 +438,7 @@ bool HttpResponseInfo::DidUseQuic() const {
case CONNECTION_INFO_QUIC_34:
case CONNECTION_INFO_QUIC_35:
case CONNECTION_INFO_QUIC_36:
+ case CONNECTION_INFO_QUIC_37:
return true;
case NUM_OF_CONNECTION_INFOS:
NOTREACHED();
@@ -480,6 +481,8 @@ std::string HttpResponseInfo::ConnectionInfoToString(
return "http/2+quic/35";
case CONNECTION_INFO_QUIC_36:
return "http/2+quic/36";
+ case CONNECTION_INFO_QUIC_37:
+ return "http/2+quic/37";
case CONNECTION_INFO_HTTP0_9:
return "http/0.9";
case CONNECTION_INFO_HTTP1_0:
diff --git a/chromium/net/http/http_response_info.h b/chromium/net/http/http_response_info.h
index 83bc630bfa6..0182b61eba4 100644
--- a/chromium/net/http/http_response_info.h
+++ b/chromium/net/http/http_response_info.h
@@ -47,6 +47,7 @@ class NET_EXPORT HttpResponseInfo {
CONNECTION_INFO_QUIC_34 = 12,
CONNECTION_INFO_QUIC_35 = 13,
CONNECTION_INFO_QUIC_36 = 14,
+ CONNECTION_INFO_QUIC_37 = 15,
NUM_OF_CONNECTION_INFOS,
};
diff --git a/chromium/net/http/http_server_properties_impl.cc b/chromium/net/http/http_server_properties_impl.cc
index 264bfb068a4..7fee0c7d2fa 100644
--- a/chromium/net/http/http_server_properties_impl.cc
+++ b/chromium/net/http/http_server_properties_impl.cc
@@ -15,7 +15,6 @@
#include "base/single_thread_task_runner.h"
#include "base/stl_util.h"
#include "base/strings/string_util.h"
-#include "base/strings/stringprintf.h"
#include "base/threading/thread_task_runner_handle.h"
#include "base/values.h"
diff --git a/chromium/net/http/http_server_properties_manager.cc b/chromium/net/http/http_server_properties_manager.cc
index dbc03f99222..dfcd04e6c7b 100644
--- a/chromium/net/http/http_server_properties_manager.cc
+++ b/chromium/net/http/http_server_properties_manager.cc
@@ -12,7 +12,6 @@
#include "base/single_thread_task_runner.h"
#include "base/stl_util.h"
#include "base/strings/string_number_conversions.h"
-#include "base/strings/stringprintf.h"
#include "base/threading/thread_task_runner_handle.h"
#include "base/values.h"
#include "net/base/ip_address.h"
@@ -24,13 +23,13 @@ namespace net {
namespace {
// Time to wait before starting an update the http_server_properties_impl_ cache
-// from preferences. Scheduling another update during this period will reset the
-// timer.
+// from preferences. Scheduling another update during this period will be a
+// no-op.
const int64_t kUpdateCacheDelayMs = 1000;
// Time to wait before starting an update the preferences from the
// http_server_properties_impl_ cache. Scheduling another update during this
-// period will reset the timer.
+// period will be a no-op.
const int64_t kUpdatePrefsDelayMs = 60000;
// "version" 0 indicates, http_server_properties doesn't have "version"
@@ -74,8 +73,9 @@ HttpServerPropertiesManager::PrefDelegate::~PrefDelegate() {}
HttpServerPropertiesManager::HttpServerPropertiesManager(
PrefDelegate* pref_delegate,
- scoped_refptr<base::SequencedTaskRunner> network_task_runner)
- : pref_task_runner_(base::ThreadTaskRunnerHandle::Get()),
+ scoped_refptr<base::SingleThreadTaskRunner> pref_task_runner,
+ scoped_refptr<base::SingleThreadTaskRunner> network_task_runner)
+ : pref_task_runner_(pref_task_runner),
pref_delegate_(pref_delegate),
setting_prefs_(false),
network_task_runner_(network_task_runner) {
@@ -84,6 +84,7 @@ HttpServerPropertiesManager::HttpServerPropertiesManager(
new base::WeakPtrFactory<HttpServerPropertiesManager>(this));
pref_weak_ptr_ = pref_weak_ptr_factory_->GetWeakPtr();
pref_cache_update_timer_.reset(new base::OneShotTimer);
+ pref_cache_update_timer_->SetTaskRunner(pref_task_runner_);
pref_delegate_->StartListeningForUpdates(
base::Bind(&HttpServerPropertiesManager::OnHttpServerPropertiesChanged,
base::Unretained(this)));
@@ -101,7 +102,7 @@ void HttpServerPropertiesManager::InitializeOnNetworkThread() {
http_server_properties_impl_.reset(new HttpServerPropertiesImpl());
network_prefs_update_timer_.reset(new base::OneShotTimer);
-
+ network_prefs_update_timer_->SetTaskRunner(network_task_runner_);
pref_task_runner_->PostTask(
FROM_HERE,
base::Bind(&HttpServerPropertiesManager::UpdateCacheFromPrefsOnPrefThread,
@@ -356,8 +357,10 @@ void HttpServerPropertiesManager::SetMaxServerConfigsStoredInProperties(
//
void HttpServerPropertiesManager::ScheduleUpdateCacheOnPrefThread() {
DCHECK(pref_task_runner_->RunsTasksOnCurrentThread());
- // Cancel pending updates, if any.
- pref_cache_update_timer_->Stop();
+ // Do not schedule a new update if there is already one scheduled.
+ if (pref_cache_update_timer_->IsRunning())
+ return;
+
StartCacheUpdateTimerOnPrefThread(
base::TimeDelta::FromMilliseconds(kUpdateCacheDelayMs));
}
@@ -780,8 +783,10 @@ void HttpServerPropertiesManager::UpdateCacheFromPrefsOnNetworkThread(
void HttpServerPropertiesManager::ScheduleUpdatePrefsOnNetworkThread(
Location location) {
DCHECK(network_task_runner_->RunsTasksOnCurrentThread());
- // Cancel pending updates, if any.
- network_prefs_update_timer_->Stop();
+ // Do not schedule a new update if there is already one scheduled.
+ if (network_prefs_update_timer_->IsRunning())
+ return;
+
StartPrefsUpdateTimerOnNetworkThread(
base::TimeDelta::FromMilliseconds(kUpdatePrefsDelayMs));
// TODO(rtenneti): Delete the following histogram after collecting some data.
diff --git a/chromium/net/http/http_server_properties_manager.h b/chromium/net/http/http_server_properties_manager.h
index bb43e874a52..e20ef59db1c 100644
--- a/chromium/net/http/http_server_properties_manager.h
+++ b/chromium/net/http/http_server_properties_manager.h
@@ -22,10 +22,8 @@
#include "net/http/http_server_properties.h"
#include "net/http/http_server_properties_impl.h"
-class PrefService;
-
namespace base {
-class SequencedTaskRunner;
+class SingleThreadTaskRunner;
}
namespace net {
@@ -42,8 +40,14 @@ class IPAddress;
// changes are received from, and the network thread, which owns it, and it
// persists the changes from network stack whether server supports SPDY or not.
//
-// It must be constructed on the pref thread, to set up |pref_task_runner_| and
-// the prefs listeners.
+// There are two SingleThreadTaskRunners:
+// |pref_task_runner_| should be bound with the pref thread and is used to post
+// cache update to the pref thread;
+// |network_task_runner_| should be bound with the network thread and is used
+// to post pref update to the cache thread.
+//
+// It must be constructed with correct task runners passed in to set up
+// |pref_task_runner_| and |network_task_runner| as well as the prefs listeners.
//
// ShutdownOnPrefThread must be called from pref thread before destruction, to
// release the prefs listeners on the pref thread.
@@ -83,10 +87,15 @@ class NET_EXPORT HttpServerPropertiesManager : public HttpServerProperties {
// passed as a raw pointer rather than a scoped_refptr currently because
// the test uses gmock and it doesn't forward move semantics properly.
//
- // Must be constructed on the Pref thread.
+ // There are two SingleThreadTaskRunners:
+ // |pref_task_runner| should be bound with the pref thread and is used to post
+ // cache update to the pref thread;
+ // |network_task_runner| should be bound with the network thread and is used
+ // to post pref update to the cache thread.
HttpServerPropertiesManager(
PrefDelegate* pref_delegate,
- scoped_refptr<base::SequencedTaskRunner> network_task_runner);
+ scoped_refptr<base::SingleThreadTaskRunner> pref_task_runner,
+ scoped_refptr<base::SingleThreadTaskRunner> network_task_runner);
~HttpServerPropertiesManager() override;
// Initialize on Network thread.
@@ -279,7 +288,7 @@ class NET_EXPORT HttpServerPropertiesManager : public HttpServerProperties {
// Pref thread
// -----------
- const scoped_refptr<base::SequencedTaskRunner> pref_task_runner_;
+ const scoped_refptr<base::SingleThreadTaskRunner> pref_task_runner_;
base::WeakPtr<HttpServerPropertiesManager> pref_weak_ptr_;
@@ -293,7 +302,7 @@ class NET_EXPORT HttpServerPropertiesManager : public HttpServerProperties {
// Network thread
// --------------
- const scoped_refptr<base::SequencedTaskRunner> network_task_runner_;
+ const scoped_refptr<base::SingleThreadTaskRunner> network_task_runner_;
// Used to post |prefs::kHttpServerProperties| pref update tasks.
std::unique_ptr<base::OneShotTimer> network_prefs_update_timer_;
diff --git a/chromium/net/http/http_server_properties_manager_unittest.cc b/chromium/net/http/http_server_properties_manager_unittest.cc
index 97b5a249984..262f73f8885 100644
--- a/chromium/net/http/http_server_properties_manager_unittest.cc
+++ b/chromium/net/http/http_server_properties_manager_unittest.cc
@@ -16,6 +16,7 @@
#include "base/single_thread_task_runner.h"
#include "base/strings/string_number_conversions.h"
#include "base/strings/stringprintf.h"
+#include "base/test/test_mock_time_task_runner.h"
#include "base/test/test_simple_task_runner.h"
#include "base/threading/thread_task_runner_handle.h"
#include "base/values.h"
@@ -29,7 +30,9 @@ namespace net {
namespace {
using base::StringPrintf;
+using base::TestMockTimeTaskRunner;
using ::testing::_;
+using ::testing::AtLeast;
using ::testing::Invoke;
using ::testing::Mock;
using ::testing::StrictMock;
@@ -78,8 +81,13 @@ class TestingHttpServerPropertiesManager : public HttpServerPropertiesManager {
public:
TestingHttpServerPropertiesManager(
HttpServerPropertiesManager::PrefDelegate* pref_delegate,
- scoped_refptr<base::SingleThreadTaskRunner> io_task_runner)
- : HttpServerPropertiesManager(pref_delegate, io_task_runner) {
+ scoped_refptr<base::SingleThreadTaskRunner> pref_task_runner,
+ scoped_refptr<base::SingleThreadTaskRunner> net_task_runner)
+ : HttpServerPropertiesManager(pref_delegate,
+ pref_task_runner,
+ net_task_runner),
+ pref_update_delay_(base::TimeDelta()),
+ cache_update_delay_(base::TimeDelta()) {
InitializeOnNetworkThread();
}
@@ -91,7 +99,7 @@ class TestingHttpServerPropertiesManager : public HttpServerPropertiesManager {
// Post tasks without a delay during tests.
void StartPrefsUpdateTimerOnNetworkThread(base::TimeDelta delay) override {
HttpServerPropertiesManager::StartPrefsUpdateTimerOnNetworkThread(
- base::TimeDelta());
+ pref_update_delay_);
}
void UpdateCacheFromPrefsOnUIConcrete() {
@@ -101,7 +109,7 @@ class TestingHttpServerPropertiesManager : public HttpServerPropertiesManager {
// Post tasks without a delay during tests.
void StartCacheUpdateTimerOnPrefThread(base::TimeDelta delay) override {
HttpServerPropertiesManager::StartCacheUpdateTimerOnPrefThread(
- base::TimeDelta());
+ cache_update_delay_);
}
void UpdatePrefsFromCacheOnNetworkThreadConcrete(
@@ -119,6 +127,12 @@ class TestingHttpServerPropertiesManager : public HttpServerPropertiesManager {
DETECTED_CORRUPTED_PREFS);
}
+ void set_pref_update_delay(base::TimeDelta delay) {
+ pref_update_delay_ = delay;
+ }
+ void set_cache_update_delay(base::TimeDelta delay) {
+ cache_update_delay_ = delay;
+ }
MOCK_METHOD0(UpdateCacheFromPrefsOnPrefThread, void());
MOCK_METHOD1(UpdatePrefsFromCacheOnNetworkThread, void(const base::Closure&));
MOCK_METHOD1(ScheduleUpdatePrefsOnNetworkThread, void(Location location));
@@ -138,6 +152,9 @@ class TestingHttpServerPropertiesManager : public HttpServerPropertiesManager {
const base::Closure& completion));
private:
+ // Time delays used in test for posting tasks. Default to zero.
+ base::TimeDelta pref_update_delay_;
+ base::TimeDelta cache_update_delay_;
DISALLOW_COPY_AND_ASSIGN(TestingHttpServerPropertiesManager);
};
@@ -149,14 +166,31 @@ static const int kHttpServerPropertiesVersions[] = {3, 4, 5};
class HttpServerPropertiesManagerTest : public testing::TestWithParam<int> {
protected:
- HttpServerPropertiesManagerTest() {}
+ HttpServerPropertiesManagerTest()
+ : pref_test_task_runner_(new TestMockTimeTaskRunner()),
+ net_test_task_runner_(new TestMockTimeTaskRunner()) {}
void SetUp() override {
one_day_from_now_ = base::Time::Now() + base::TimeDelta::FromDays(1);
pref_delegate_ = new MockPrefDelegate;
http_server_props_manager_.reset(
new StrictMock<TestingHttpServerPropertiesManager>(
- pref_delegate_, base::ThreadTaskRunnerHandle::Get()));
+ pref_delegate_, pref_test_task_runner_, net_test_task_runner_));
+
+ ExpectCacheUpdate();
+ EXPECT_FALSE(net_test_task_runner_->HasPendingTask());
+ pref_test_task_runner_->FastForwardUntilNoTasksRemain();
+ EXPECT_FALSE(net_test_task_runner_->HasPendingTask());
+ EXPECT_FALSE(pref_test_task_runner_->HasPendingTask());
+ }
+
+ void SetUpWithNonTaskRunner() {
+ pref_delegate_ = new MockPrefDelegate;
+ http_server_props_manager_.reset(
+ new StrictMock<TestingHttpServerPropertiesManager>(
+ pref_delegate_, base::ThreadTaskRunnerHandle::Get(),
+ net_test_task_runner_));
+
ExpectCacheUpdate();
base::RunLoop().RunUntilIdle();
}
@@ -165,6 +199,8 @@ class HttpServerPropertiesManagerTest : public testing::TestWithParam<int> {
if (http_server_props_manager_.get())
http_server_props_manager_->ShutdownOnPrefThread();
base::RunLoop().RunUntilIdle();
+ pref_test_task_runner_->FastForwardUntilNoTasksRemain();
+ net_test_task_runner_->FastForwardUntilNoTasksRemain();
http_server_props_manager_.reset();
}
@@ -183,25 +219,19 @@ class HttpServerPropertiesManagerTest : public testing::TestWithParam<int> {
ScheduleUpdatePrefsOnNetworkThreadConcrete));
}
- void ExpectScheduleUpdatePrefsOnNetworkThreadRepeatedly() {
+ void ExpectScheduleUpdatePrefsOnNetworkThreadRepeatedly(int times) {
EXPECT_CALL(*http_server_props_manager_,
ScheduleUpdatePrefsOnNetworkThread(_))
+ .Times(AtLeast(times))
.WillRepeatedly(Invoke(http_server_props_manager_.get(),
&TestingHttpServerPropertiesManager::
ScheduleUpdatePrefsOnNetworkThreadConcrete));
}
- void ExpectPrefsUpdate() {
- EXPECT_CALL(*http_server_props_manager_,
- UpdatePrefsFromCacheOnNetworkThread(_))
- .WillOnce(Invoke(http_server_props_manager_.get(),
- &TestingHttpServerPropertiesManager::
- UpdatePrefsFromCacheOnNetworkThreadConcrete));
- }
-
- void ExpectPrefsUpdateRepeatedly() {
+ void ExpectPrefsUpdate(int times) {
EXPECT_CALL(*http_server_props_manager_,
UpdatePrefsFromCacheOnNetworkThread(_))
+ .Times(times)
.WillRepeatedly(
Invoke(http_server_props_manager_.get(),
&TestingHttpServerPropertiesManager::
@@ -218,6 +248,8 @@ class HttpServerPropertiesManagerTest : public testing::TestWithParam<int> {
std::unique_ptr<TestingHttpServerPropertiesManager>
http_server_props_manager_;
base::Time one_day_from_now_;
+ scoped_refptr<TestMockTimeTaskRunner> pref_test_task_runner_;
+ scoped_refptr<TestMockTimeTaskRunner> net_test_task_runner_;
private:
DISALLOW_COPY_AND_ASSIGN(HttpServerPropertiesManagerTest);
@@ -356,7 +388,14 @@ TEST_P(HttpServerPropertiesManagerTest,
pref_delegate_->SetPrefs(http_server_properties_dict);
pref_delegate_->SetPrefs(http_server_properties_dict);
- base::RunLoop().RunUntilIdle();
+ EXPECT_TRUE(pref_test_task_runner_->HasPendingTask());
+ EXPECT_FALSE(net_test_task_runner_->HasPendingTask());
+ pref_test_task_runner_->FastForwardUntilNoTasksRemain();
+ EXPECT_TRUE(net_test_task_runner_->HasPendingTask());
+ net_test_task_runner_->FastForwardUntilNoTasksRemain();
+ EXPECT_FALSE(pref_test_task_runner_->HasPendingTask());
+ EXPECT_FALSE(net_test_task_runner_->HasPendingTask());
+
Mock::VerifyAndClearExpectations(http_server_props_manager_.get());
// Verify SupportsSpdy.
@@ -447,8 +486,8 @@ TEST_P(HttpServerPropertiesManagerTest,
TEST_P(HttpServerPropertiesManagerTest, BadCachedHostPortPair) {
ExpectCacheUpdate();
- // The prefs are automaticalls updated in the case corruption is detected.
- ExpectPrefsUpdate();
+ // The prefs are automatically updated in the case corruption is detected.
+ ExpectPrefsUpdate(1);
ExpectScheduleUpdatePrefsOnNetworkThread();
base::DictionaryValue* server_pref_dict = new base::DictionaryValue;
@@ -459,7 +498,7 @@ TEST_P(HttpServerPropertiesManagerTest, BadCachedHostPortPair) {
// Set up alternative_service for www.google.com:65536.
std::unique_ptr<base::DictionaryValue> alternative_service_dict(
new base::DictionaryValue);
- alternative_service_dict->SetString("protocol_str", "npn-h2");
+ alternative_service_dict->SetString("protocol_str", "h2");
alternative_service_dict->SetInteger("port", 80);
base::ListValue* alternative_service_list = new base::ListValue;
alternative_service_list->Append(std::move(alternative_service_dict));
@@ -508,7 +547,16 @@ TEST_P(HttpServerPropertiesManagerTest, BadCachedHostPortPair) {
// Set up the pref.
pref_delegate_->SetPrefs(http_server_properties_dict);
- base::RunLoop().RunUntilIdle();
+ EXPECT_TRUE(pref_test_task_runner_->HasPendingTask());
+ EXPECT_FALSE(net_test_task_runner_->HasPendingTask());
+ pref_test_task_runner_->FastForwardUntilNoTasksRemain();
+ EXPECT_FALSE(pref_test_task_runner_->HasPendingTask());
+ EXPECT_TRUE(net_test_task_runner_->HasPendingTask());
+ net_test_task_runner_->FastForwardUntilNoTasksRemain();
+ EXPECT_TRUE(pref_test_task_runner_->HasPendingTask());
+ pref_test_task_runner_->FastForwardUntilNoTasksRemain();
+ EXPECT_FALSE(net_test_task_runner_->HasPendingTask());
+ EXPECT_FALSE(net_test_task_runner_->HasPendingTask());
Mock::VerifyAndClearExpectations(http_server_props_manager_.get());
// Verify that nothing is set.
@@ -528,8 +576,8 @@ TEST_P(HttpServerPropertiesManagerTest, BadCachedHostPortPair) {
TEST_P(HttpServerPropertiesManagerTest, BadCachedAltProtocolPort) {
ExpectCacheUpdate();
- // The prefs are automaticalls updated in the case corruption is detected.
- ExpectPrefsUpdate();
+ // The prefs are automatically updated in the case corruption is detected.
+ ExpectPrefsUpdate(1);
ExpectScheduleUpdatePrefsOnNetworkThread();
base::DictionaryValue* server_pref_dict = new base::DictionaryValue;
@@ -540,7 +588,7 @@ TEST_P(HttpServerPropertiesManagerTest, BadCachedAltProtocolPort) {
// Set up alternative_service for www.google.com:80.
std::unique_ptr<base::DictionaryValue> alternative_service_dict(
new base::DictionaryValue);
- alternative_service_dict->SetString("protocol_str", "npn-h2");
+ alternative_service_dict->SetString("protocol_str", "h2");
alternative_service_dict->SetInteger("port", 65536);
base::ListValue* alternative_service_list = new base::ListValue;
alternative_service_list->Append(std::move(alternative_service_dict));
@@ -572,7 +620,16 @@ TEST_P(HttpServerPropertiesManagerTest, BadCachedAltProtocolPort) {
// Set up the pref.
pref_delegate_->SetPrefs(http_server_properties_dict);
- base::RunLoop().RunUntilIdle();
+ EXPECT_TRUE(pref_test_task_runner_->HasPendingTask());
+ EXPECT_FALSE(net_test_task_runner_->HasPendingTask());
+ pref_test_task_runner_->FastForwardUntilNoTasksRemain();
+ EXPECT_FALSE(pref_test_task_runner_->HasPendingTask());
+ EXPECT_TRUE(net_test_task_runner_->HasPendingTask());
+ net_test_task_runner_->FastForwardUntilNoTasksRemain();
+ EXPECT_TRUE(pref_test_task_runner_->HasPendingTask());
+ pref_test_task_runner_->FastForwardUntilNoTasksRemain();
+ EXPECT_FALSE(net_test_task_runner_->HasPendingTask());
+ EXPECT_FALSE(net_test_task_runner_->HasPendingTask());
Mock::VerifyAndClearExpectations(http_server_props_manager_.get());
// Verify alternative service is not set.
@@ -581,7 +638,7 @@ TEST_P(HttpServerPropertiesManagerTest, BadCachedAltProtocolPort) {
}
TEST_P(HttpServerPropertiesManagerTest, SupportsSpdy) {
- ExpectPrefsUpdate();
+ ExpectPrefsUpdate(1);
ExpectScheduleUpdatePrefsOnNetworkThread();
// Post an update task to the network thread. SetSupportsSpdy calls
@@ -596,14 +653,82 @@ TEST_P(HttpServerPropertiesManagerTest, SupportsSpdy) {
http_server_props_manager_->SetSupportsSpdy(spdy_server, true);
// Run the task.
- base::RunLoop().RunUntilIdle();
+ EXPECT_TRUE(net_test_task_runner_->HasPendingTask());
+ EXPECT_FALSE(pref_test_task_runner_->HasPendingTask());
+ net_test_task_runner_->FastForwardUntilNoTasksRemain();
+ EXPECT_TRUE(pref_test_task_runner_->HasPendingTask());
+ pref_test_task_runner_->FastForwardUntilNoTasksRemain();
+ EXPECT_FALSE(net_test_task_runner_->HasPendingTask());
+ EXPECT_FALSE(pref_test_task_runner_->HasPendingTask());
EXPECT_TRUE(http_server_props_manager_->SupportsRequestPriority(spdy_server));
Mock::VerifyAndClearExpectations(http_server_props_manager_.get());
}
+// Regression test for crbug.com/670519. Test that there is only one pref update
+// scheduled if multiple updates happen in a given time period. Subsequent pref
+// update could also be scheduled once the previous scheduled update is
+// completed.
+TEST_P(HttpServerPropertiesManagerTest,
+ SinglePrefUpdateForTwoSpdyServerCacheChanges) {
+ http_server_props_manager_->set_pref_update_delay(
+ base::TimeDelta::FromMilliseconds(60));
+ ExpectPrefsUpdate(2);
+ ExpectScheduleUpdatePrefsOnNetworkThreadRepeatedly(3);
+
+ // Post an update task to the network thread. SetSupportsSpdy calls
+ // ScheduleUpdatePrefsOnNetworkThread with a delay of 60ms.
+ url::SchemeHostPort spdy_server("https", "mail.google.com", 443);
+ EXPECT_FALSE(
+ http_server_props_manager_->SupportsRequestPriority(spdy_server));
+ http_server_props_manager_->SetSupportsSpdy(spdy_server, true);
+ // The pref update task should be scheduled to network thread.
+ EXPECT_EQ(1u, net_test_task_runner_->GetPendingTaskCount());
+
+ // Move forward the task runner with 20ms.
+ net_test_task_runner_->FastForwardBy(base::TimeDelta::FromMilliseconds(20));
+
+ // Set another spdy server to trigger another call to
+ // ScheduleUpdatePrefsOnNetworkThread. There should be no new update posted to
+ // the network thread.
+ url::SchemeHostPort spdy_server2("https", "drive.google.com", 443);
+ http_server_props_manager_->SetSupportsSpdy(spdy_server2, true);
+ EXPECT_EQ(1u, net_test_task_runner_->GetPendingTaskCount());
+ EXPECT_FALSE(pref_test_task_runner_->HasPendingTask());
+
+ // Move forward another 40ms. The pref update should be executed.
+ net_test_task_runner_->FastForwardBy(base::TimeDelta::FromMilliseconds(40));
+ EXPECT_FALSE(net_test_task_runner_->HasPendingTask());
+ EXPECT_TRUE(pref_test_task_runner_->HasPendingTask());
+ pref_test_task_runner_->FastForwardUntilNoTasksRemain();
+ EXPECT_FALSE(net_test_task_runner_->HasPendingTask());
+ EXPECT_FALSE(pref_test_task_runner_->HasPendingTask());
+
+ EXPECT_TRUE(http_server_props_manager_->SupportsRequestPriority(spdy_server));
+ EXPECT_TRUE(
+ http_server_props_manager_->SupportsRequestPriority(spdy_server2));
+ // Set the third spdy server to trigger one more call to
+ // ScheduleUpdatePrefsOnNetworkThread. A new update task should be posted to
+ // network thread now since the previous one is completed.
+ url::SchemeHostPort spdy_server3("https", "maps.google.com", 443);
+ http_server_props_manager_->SetSupportsSpdy(spdy_server3, true);
+ EXPECT_FALSE(pref_test_task_runner_->HasPendingTask());
+ EXPECT_EQ(1u, net_test_task_runner_->GetPendingTaskCount());
+
+ // Run the task.
+ EXPECT_TRUE(net_test_task_runner_->HasPendingTask());
+ EXPECT_FALSE(pref_test_task_runner_->HasPendingTask());
+ net_test_task_runner_->FastForwardUntilNoTasksRemain();
+ EXPECT_TRUE(pref_test_task_runner_->HasPendingTask());
+ pref_test_task_runner_->FastForwardUntilNoTasksRemain();
+ EXPECT_FALSE(net_test_task_runner_->HasPendingTask());
+ EXPECT_FALSE(pref_test_task_runner_->HasPendingTask());
+
+ Mock::VerifyAndClearExpectations(http_server_props_manager_.get());
+}
+
TEST_P(HttpServerPropertiesManagerTest, GetAlternativeServices) {
- ExpectPrefsUpdate();
+ ExpectPrefsUpdate(1);
ExpectScheduleUpdatePrefsOnNetworkThread();
url::SchemeHostPort spdy_server_mail("http", "mail.google.com", 80);
@@ -617,7 +742,14 @@ TEST_P(HttpServerPropertiesManagerTest, GetAlternativeServices) {
spdy_server_mail, alternative_service, one_day_from_now_);
// Run the task.
- base::RunLoop().RunUntilIdle();
+ EXPECT_FALSE(pref_test_task_runner_->HasPendingTask());
+ EXPECT_TRUE(net_test_task_runner_->HasPendingTask());
+ net_test_task_runner_->FastForwardUntilNoTasksRemain();
+ EXPECT_TRUE(pref_test_task_runner_->HasPendingTask());
+ EXPECT_FALSE(net_test_task_runner_->HasPendingTask());
+ pref_test_task_runner_->FastForwardUntilNoTasksRemain();
+ EXPECT_FALSE(pref_test_task_runner_->HasPendingTask());
+ EXPECT_FALSE(net_test_task_runner_->HasPendingTask());
Mock::VerifyAndClearExpectations(http_server_props_manager_.get());
AlternativeServiceVector alternative_service_vector =
@@ -627,7 +759,7 @@ TEST_P(HttpServerPropertiesManagerTest, GetAlternativeServices) {
}
TEST_P(HttpServerPropertiesManagerTest, SetAlternativeServices) {
- ExpectPrefsUpdate();
+ ExpectPrefsUpdate(1);
ExpectScheduleUpdatePrefsOnNetworkThread();
url::SchemeHostPort spdy_server_mail("http", "mail.google.com", 80);
@@ -648,7 +780,14 @@ TEST_P(HttpServerPropertiesManagerTest, SetAlternativeServices) {
spdy_server_mail, alternative_service_info_vector);
// Run the task.
- base::RunLoop().RunUntilIdle();
+ EXPECT_FALSE(pref_test_task_runner_->HasPendingTask());
+ EXPECT_TRUE(net_test_task_runner_->HasPendingTask());
+ net_test_task_runner_->FastForwardUntilNoTasksRemain();
+ EXPECT_TRUE(pref_test_task_runner_->HasPendingTask());
+ EXPECT_FALSE(net_test_task_runner_->HasPendingTask());
+ pref_test_task_runner_->FastForwardUntilNoTasksRemain();
+ EXPECT_FALSE(pref_test_task_runner_->HasPendingTask());
+ EXPECT_FALSE(net_test_task_runner_->HasPendingTask());
Mock::VerifyAndClearExpectations(http_server_props_manager_.get());
AlternativeServiceVector alternative_service_vector =
@@ -665,17 +804,17 @@ TEST_P(HttpServerPropertiesManagerTest, SetAlternativeServicesEmpty) {
443);
http_server_props_manager_->SetAlternativeServices(
spdy_server_mail, AlternativeServiceInfoVector());
- // ExpectScheduleUpdatePrefsOnNetworkThread() should not be called.
- // Run the task.
- base::RunLoop().RunUntilIdle();
+ // ExpectScheduleUpdatePrefsOnNetworkThread() should not be called.
+ EXPECT_FALSE(pref_test_task_runner_->HasPendingTask());
+ EXPECT_FALSE(net_test_task_runner_->HasPendingTask());
Mock::VerifyAndClearExpectations(http_server_props_manager_.get());
EXPECT_FALSE(HasAlternativeService(spdy_server_mail));
}
TEST_P(HttpServerPropertiesManagerTest, ConfirmAlternativeService) {
- ExpectPrefsUpdate();
+ ExpectPrefsUpdate(1);
url::SchemeHostPort spdy_server_mail("http", "mail.google.com", 80);
EXPECT_FALSE(HasAlternativeService(spdy_server_mail));
@@ -711,7 +850,14 @@ TEST_P(HttpServerPropertiesManagerTest, ConfirmAlternativeService) {
alternative_service));
// Run the task.
- base::RunLoop().RunUntilIdle();
+ EXPECT_FALSE(pref_test_task_runner_->HasPendingTask());
+ EXPECT_TRUE(net_test_task_runner_->HasPendingTask());
+ net_test_task_runner_->FastForwardUntilNoTasksRemain();
+ EXPECT_TRUE(pref_test_task_runner_->HasPendingTask());
+ pref_test_task_runner_->FastForwardUntilNoTasksRemain();
+ EXPECT_FALSE(net_test_task_runner_->HasPendingTask());
+ EXPECT_FALSE(pref_test_task_runner_->HasPendingTask());
+
Mock::VerifyAndClearExpectations(http_server_props_manager_.get());
EXPECT_FALSE(http_server_props_manager_->IsAlternativeServiceBroken(
@@ -721,7 +867,7 @@ TEST_P(HttpServerPropertiesManagerTest, ConfirmAlternativeService) {
}
TEST_P(HttpServerPropertiesManagerTest, SupportsQuic) {
- ExpectPrefsUpdate();
+ ExpectPrefsUpdate(1);
ExpectScheduleUpdatePrefsOnNetworkThread();
IPAddress address;
@@ -733,7 +879,14 @@ TEST_P(HttpServerPropertiesManagerTest, SupportsQuic) {
http_server_props_manager_->SetSupportsQuic(true, actual_address);
// Run the task.
- base::RunLoop().RunUntilIdle();
+ EXPECT_FALSE(pref_test_task_runner_->HasPendingTask());
+ EXPECT_TRUE(net_test_task_runner_->HasPendingTask());
+ net_test_task_runner_->FastForwardUntilNoTasksRemain();
+ EXPECT_TRUE(pref_test_task_runner_->HasPendingTask());
+ pref_test_task_runner_->FastForwardUntilNoTasksRemain();
+ EXPECT_FALSE(net_test_task_runner_->HasPendingTask());
+ EXPECT_FALSE(pref_test_task_runner_->HasPendingTask());
+
Mock::VerifyAndClearExpectations(http_server_props_manager_.get());
EXPECT_TRUE(http_server_props_manager_->GetSupportsQuic(&address));
@@ -741,7 +894,7 @@ TEST_P(HttpServerPropertiesManagerTest, SupportsQuic) {
}
TEST_P(HttpServerPropertiesManagerTest, ServerNetworkStats) {
- ExpectPrefsUpdate();
+ ExpectPrefsUpdate(1);
ExpectScheduleUpdatePrefsOnNetworkThread();
url::SchemeHostPort mail_server("http", "mail.google.com", 80);
@@ -755,7 +908,14 @@ TEST_P(HttpServerPropertiesManagerTest, ServerNetworkStats) {
http_server_props_manager_->SetServerNetworkStats(mail_server, stats1);
// Run the task.
- base::RunLoop().RunUntilIdle();
+ EXPECT_FALSE(pref_test_task_runner_->HasPendingTask());
+ EXPECT_TRUE(net_test_task_runner_->HasPendingTask());
+ net_test_task_runner_->FastForwardUntilNoTasksRemain();
+ EXPECT_TRUE(pref_test_task_runner_->HasPendingTask());
+ pref_test_task_runner_->FastForwardUntilNoTasksRemain();
+ EXPECT_FALSE(net_test_task_runner_->HasPendingTask());
+ EXPECT_FALSE(pref_test_task_runner_->HasPendingTask());
+
Mock::VerifyAndClearExpectations(http_server_props_manager_.get());
const ServerNetworkStats* stats2 =
@@ -764,7 +924,7 @@ TEST_P(HttpServerPropertiesManagerTest, ServerNetworkStats) {
}
TEST_P(HttpServerPropertiesManagerTest, QuicServerInfo) {
- ExpectPrefsUpdate();
+ ExpectPrefsUpdate(1);
ExpectScheduleUpdatePrefsOnNetworkThread();
QuicServerId mail_quic_server_id("mail.google.com", 80);
@@ -778,7 +938,14 @@ TEST_P(HttpServerPropertiesManagerTest, QuicServerInfo) {
quic_server_info1);
// Run the task.
- base::RunLoop().RunUntilIdle();
+ EXPECT_FALSE(pref_test_task_runner_->HasPendingTask());
+ EXPECT_TRUE(net_test_task_runner_->HasPendingTask());
+ net_test_task_runner_->FastForwardUntilNoTasksRemain();
+ EXPECT_TRUE(pref_test_task_runner_->HasPendingTask());
+ pref_test_task_runner_->FastForwardUntilNoTasksRemain();
+ EXPECT_FALSE(net_test_task_runner_->HasPendingTask());
+ EXPECT_FALSE(pref_test_task_runner_->HasPendingTask());
+
Mock::VerifyAndClearExpectations(http_server_props_manager_.get());
EXPECT_EQ(quic_server_info1, *http_server_props_manager_->GetQuicServerInfo(
@@ -786,8 +953,12 @@ TEST_P(HttpServerPropertiesManagerTest, QuicServerInfo) {
}
TEST_P(HttpServerPropertiesManagerTest, Clear) {
- ExpectPrefsUpdate();
- ExpectScheduleUpdatePrefsOnNetworkThreadRepeatedly();
+ // This task expect to run the QuitWhenIdleClosure in the current thread,
+ // thus can not mock the pref task runner.
+ SetUpWithNonTaskRunner();
+
+ ExpectPrefsUpdate(1);
+ ExpectScheduleUpdatePrefsOnNetworkThreadRepeatedly(5);
url::SchemeHostPort spdy_server("https", "mail.google.com", 443);
http_server_props_manager_->SetSupportsSpdy(spdy_server, true);
@@ -807,6 +978,9 @@ TEST_P(HttpServerPropertiesManagerTest, Clear) {
// Run the task.
base::RunLoop().RunUntilIdle();
+ EXPECT_TRUE(net_test_task_runner_->HasPendingTask());
+ net_test_task_runner_->FastForwardUntilNoTasksRemain();
+ EXPECT_FALSE(net_test_task_runner_->HasPendingTask());
EXPECT_TRUE(http_server_props_manager_->SupportsRequestPriority(spdy_server));
EXPECT_TRUE(HasAlternativeService(spdy_server));
@@ -821,11 +995,13 @@ TEST_P(HttpServerPropertiesManagerTest, Clear) {
Mock::VerifyAndClearExpectations(http_server_props_manager_.get());
- ExpectPrefsUpdate();
+ ExpectPrefsUpdate(1);
// Clear http server data, time out if we do not get a completion callback.
http_server_props_manager_->Clear(base::MessageLoop::QuitWhenIdleClosure());
+
base::RunLoop().Run();
+ EXPECT_FALSE(net_test_task_runner_->HasPendingTask());
EXPECT_FALSE(
http_server_props_manager_->SupportsRequestPriority(spdy_server));
@@ -911,7 +1087,14 @@ TEST_P(HttpServerPropertiesManagerTest, BadSupportsQuic) {
// Set up the pref.
pref_delegate_->SetPrefs(http_server_properties_dict);
- base::RunLoop().RunUntilIdle();
+ EXPECT_FALSE(net_test_task_runner_->HasPendingTask());
+ EXPECT_TRUE(pref_test_task_runner_->HasPendingTask());
+ pref_test_task_runner_->FastForwardUntilNoTasksRemain();
+ EXPECT_TRUE(net_test_task_runner_->HasPendingTask());
+ net_test_task_runner_->FastForwardUntilNoTasksRemain();
+ EXPECT_FALSE(net_test_task_runner_->HasPendingTask());
+ EXPECT_FALSE(pref_test_task_runner_->HasPendingTask());
+
Mock::VerifyAndClearExpectations(http_server_props_manager_.get());
// Verify alternative service.
@@ -937,7 +1120,7 @@ TEST_P(HttpServerPropertiesManagerTest, BadSupportsQuic) {
}
TEST_P(HttpServerPropertiesManagerTest, UpdateCacheWithPrefs) {
- ExpectScheduleUpdatePrefsOnNetworkThreadRepeatedly();
+ ExpectScheduleUpdatePrefsOnNetworkThreadRepeatedly(5);
const url::SchemeHostPort server_www("http", "www.google.com", 80);
const url::SchemeHostPort server_mail("http", "mail.google.com", 80);
@@ -980,10 +1163,16 @@ TEST_P(HttpServerPropertiesManagerTest, UpdateCacheWithPrefs) {
http_server_props_manager_->SetSupportsQuic(true, actual_address);
// Update cache.
- ExpectPrefsUpdate();
+ ExpectPrefsUpdate(1);
ExpectCacheUpdate();
http_server_props_manager_->ScheduleUpdateCacheOnPrefThread();
- base::RunLoop().RunUntilIdle();
+
+ EXPECT_TRUE(net_test_task_runner_->HasPendingTask());
+ EXPECT_TRUE(pref_test_task_runner_->HasPendingTask());
+ net_test_task_runner_->FastForwardUntilNoTasksRemain();
+ pref_test_task_runner_->FastForwardUntilNoTasksRemain();
+ EXPECT_FALSE(net_test_task_runner_->HasPendingTask());
+ EXPECT_FALSE(pref_test_task_runner_->HasPendingTask());
// Verify preferences.
const char expected_json[] =
@@ -1011,12 +1200,50 @@ TEST_P(HttpServerPropertiesManagerTest, UpdateCacheWithPrefs) {
EXPECT_EQ(expected_json, preferences_json);
}
+TEST_P(HttpServerPropertiesManagerTest,
+ SingleCacheUpdateForMultipleUpdatesScheduled) {
+ http_server_props_manager_->set_cache_update_delay(
+ base::TimeDelta::FromMilliseconds(60));
+
+ // Update cache.
+ ExpectCacheUpdate();
+
+ EXPECT_EQ(0u, pref_test_task_runner_->GetPendingTaskCount());
+ // Update cache.
+ http_server_props_manager_->ScheduleUpdateCacheOnPrefThread();
+ EXPECT_EQ(1u, pref_test_task_runner_->GetPendingTaskCount());
+
+ // Move forward the task runner 20ms.
+ pref_test_task_runner_->FastForwardBy(base::TimeDelta::FromMilliseconds(20));
+ // Schedule a new cache update within the time window should be a no-op.
+ http_server_props_manager_->ScheduleUpdateCacheOnPrefThread();
+ EXPECT_EQ(1u, pref_test_task_runner_->GetPendingTaskCount());
+
+ // Move forward the task runner 40ms, now the cache update should be
+ // exectured.
+ pref_test_task_runner_->FastForwardBy(base::TimeDelta::FromMilliseconds(40));
+
+ // Since this test has no pref corruption, there shouldn't be any pref update.
+ EXPECT_FALSE(net_test_task_runner_->HasPendingTask());
+ EXPECT_FALSE(pref_test_task_runner_->HasPendingTask());
+
+ // Schedule one more cache update. The task should be successfully scheduled
+ // on pref task runner.
+ ExpectCacheUpdate();
+ http_server_props_manager_->ScheduleUpdateCacheOnPrefThread();
+ EXPECT_EQ(1u, pref_test_task_runner_->GetPendingTaskCount());
+
+ pref_test_task_runner_->FastForwardUntilNoTasksRemain();
+ EXPECT_FALSE(pref_test_task_runner_->HasPendingTask());
+ EXPECT_FALSE(net_test_task_runner_->HasPendingTask());
+}
+
TEST_P(HttpServerPropertiesManagerTest, AddToAlternativeServiceMap) {
std::unique_ptr<base::Value> server_value = base::JSONReader::Read(
"{\"alternative_service\":[{\"port\":443,\"protocol_str\":\"h2\"},"
"{\"port\":123,\"protocol_str\":\"quic\","
"\"expiration\":\"9223372036854775807\"},{\"host\":\"example.org\","
- "\"port\":1234,\"protocol_str\":\"npn-h2\","
+ "\"port\":1234,\"protocol_str\":\"h2\","
"\"expiration\":\"13758804000000000\"}]}");
ASSERT_TRUE(server_value);
base::DictionaryValue* server_dict;
@@ -1063,7 +1290,7 @@ TEST_P(HttpServerPropertiesManagerTest, AddToAlternativeServiceMap) {
// Regression test for https://crbug.com/615497.
TEST_P(HttpServerPropertiesManagerTest, DoNotLoadAltSvcForInsecureOrigins) {
std::unique_ptr<base::Value> server_value = base::JSONReader::Read(
- "{\"alternative_service\":[{\"port\":443,\"protocol_str\":\"npn-h2\","
+ "{\"alternative_service\":[{\"port\":443,\"protocol_str\":\"h2\","
"\"expiration\":\"9223372036854775807\"}]}");
ASSERT_TRUE(server_value);
base::DictionaryValue* server_dict;
@@ -1081,7 +1308,7 @@ TEST_P(HttpServerPropertiesManagerTest, DoNotLoadAltSvcForInsecureOrigins) {
// Do not persist expired or broken alternative service entries to disk.
TEST_P(HttpServerPropertiesManagerTest,
DoNotPersistExpiredOrBrokenAlternativeService) {
- ExpectScheduleUpdatePrefsOnNetworkThreadRepeatedly();
+ ExpectScheduleUpdatePrefsOnNetworkThreadRepeatedly(2);
AlternativeServiceInfoVector alternative_service_info_vector;
@@ -1111,10 +1338,16 @@ TEST_P(HttpServerPropertiesManagerTest,
server, alternative_service_info_vector);
// Update cache.
- ExpectPrefsUpdate();
+ ExpectPrefsUpdate(1);
ExpectCacheUpdate();
http_server_props_manager_->ScheduleUpdateCacheOnPrefThread();
- base::RunLoop().RunUntilIdle();
+
+ EXPECT_TRUE(net_test_task_runner_->HasPendingTask());
+ EXPECT_TRUE(pref_test_task_runner_->HasPendingTask());
+ net_test_task_runner_->FastForwardUntilNoTasksRemain();
+ pref_test_task_runner_->FastForwardUntilNoTasksRemain();
+ EXPECT_FALSE(net_test_task_runner_->HasPendingTask());
+ EXPECT_FALSE(pref_test_task_runner_->HasPendingTask());
const base::DictionaryValue& pref_dict =
pref_delegate_->GetServerProperties();
@@ -1149,7 +1382,7 @@ TEST_P(HttpServerPropertiesManagerTest, DoNotLoadExpiredAlternativeService) {
new base::ListValue);
std::unique_ptr<base::DictionaryValue> expired_dict(
new base::DictionaryValue);
- expired_dict->SetString("protocol_str", "npn-h2");
+ expired_dict->SetString("protocol_str", "h2");
expired_dict->SetString("host", "expired.example.com");
expired_dict->SetInteger("port", 443);
base::Time time_one_day_ago =
@@ -1159,7 +1392,7 @@ TEST_P(HttpServerPropertiesManagerTest, DoNotLoadExpiredAlternativeService) {
alternative_service_list->Append(std::move(expired_dict));
std::unique_ptr<base::DictionaryValue> valid_dict(new base::DictionaryValue);
- valid_dict->SetString("protocol_str", "npn-h2");
+ valid_dict->SetString("protocol_str", "h2");
valid_dict->SetString("host", "valid.example.com");
valid_dict->SetInteger("port", 443);
valid_dict->SetString(
@@ -1195,7 +1428,11 @@ TEST_P(HttpServerPropertiesManagerTest, ShutdownWithPendingUpdateCache0) {
http_server_props_manager_->ShutdownOnPrefThread();
http_server_props_manager_.reset();
// Run the task after shutdown and deletion.
- base::RunLoop().RunUntilIdle();
+ EXPECT_FALSE(net_test_task_runner_->HasPendingTask());
+ EXPECT_TRUE(pref_test_task_runner_->HasPendingTask());
+ pref_test_task_runner_->FastForwardUntilNoTasksRemain();
+ EXPECT_FALSE(net_test_task_runner_->HasPendingTask());
+ EXPECT_FALSE(pref_test_task_runner_->HasPendingTask());
}
TEST_P(HttpServerPropertiesManagerTest, ShutdownWithPendingUpdateCache1) {
@@ -1204,21 +1441,29 @@ TEST_P(HttpServerPropertiesManagerTest, ShutdownWithPendingUpdateCache1) {
// Shutdown comes before the task is executed.
http_server_props_manager_->ShutdownOnPrefThread();
// Run the task after shutdown, but before deletion.
- base::RunLoop().RunUntilIdle();
+ EXPECT_FALSE(net_test_task_runner_->HasPendingTask());
+ EXPECT_TRUE(pref_test_task_runner_->HasPendingTask());
+ pref_test_task_runner_->FastForwardUntilNoTasksRemain();
+ EXPECT_FALSE(net_test_task_runner_->HasPendingTask());
+ EXPECT_FALSE(pref_test_task_runner_->HasPendingTask());
+
Mock::VerifyAndClearExpectations(http_server_props_manager_.get());
http_server_props_manager_.reset();
- base::RunLoop().RunUntilIdle();
+ EXPECT_FALSE(net_test_task_runner_->HasPendingTask());
+ EXPECT_FALSE(pref_test_task_runner_->HasPendingTask());
}
TEST_P(HttpServerPropertiesManagerTest, ShutdownWithPendingUpdateCache2) {
http_server_props_manager_->UpdateCacheFromPrefsOnUIConcrete();
// Shutdown comes before the task is executed.
http_server_props_manager_->ShutdownOnPrefThread();
- // Run the task after shutdown, but before deletion.
- base::RunLoop().RunUntilIdle();
+ // There should be no tasks to run.
+ EXPECT_FALSE(net_test_task_runner_->HasPendingTask());
+ EXPECT_FALSE(pref_test_task_runner_->HasPendingTask());
Mock::VerifyAndClearExpectations(http_server_props_manager_.get());
http_server_props_manager_.reset();
- base::RunLoop().RunUntilIdle();
+ EXPECT_FALSE(net_test_task_runner_->HasPendingTask());
+ EXPECT_FALSE(pref_test_task_runner_->HasPendingTask());
}
//
@@ -1231,20 +1476,32 @@ TEST_P(HttpServerPropertiesManagerTest, ShutdownWithPendingUpdatePrefs0) {
http_server_props_manager_->ShutdownOnPrefThread();
http_server_props_manager_.reset();
// Run the task after shutdown and deletion.
- base::RunLoop().RunUntilIdle();
+ EXPECT_TRUE(net_test_task_runner_->HasPendingTask());
+ EXPECT_FALSE(pref_test_task_runner_->HasPendingTask());
+ net_test_task_runner_->FastForwardUntilNoTasksRemain();
+ EXPECT_FALSE(net_test_task_runner_->HasPendingTask());
+ EXPECT_FALSE(pref_test_task_runner_->HasPendingTask());
}
TEST_P(HttpServerPropertiesManagerTest, ShutdownWithPendingUpdatePrefs1) {
- ExpectPrefsUpdate();
+ ExpectPrefsUpdate(1);
// Post an update task.
http_server_props_manager_->ScheduleUpdatePrefsOnNetworkThread();
// Shutdown comes before the task is executed.
http_server_props_manager_->ShutdownOnPrefThread();
// Run the task after shutdown, but before deletion.
- base::RunLoop().RunUntilIdle();
+ EXPECT_TRUE(net_test_task_runner_->HasPendingTask());
+ EXPECT_FALSE(pref_test_task_runner_->HasPendingTask());
+ net_test_task_runner_->FastForwardUntilNoTasksRemain();
+ EXPECT_TRUE(pref_test_task_runner_->HasPendingTask());
+ pref_test_task_runner_->FastForwardUntilNoTasksRemain();
+ EXPECT_FALSE(net_test_task_runner_->HasPendingTask());
+ EXPECT_FALSE(pref_test_task_runner_->HasPendingTask());
+
Mock::VerifyAndClearExpectations(http_server_props_manager_.get());
http_server_props_manager_.reset();
- base::RunLoop().RunUntilIdle();
+ EXPECT_FALSE(net_test_task_runner_->HasPendingTask());
+ EXPECT_FALSE(pref_test_task_runner_->HasPendingTask());
}
TEST_P(HttpServerPropertiesManagerTest, ShutdownWithPendingUpdatePrefs2) {
@@ -1254,10 +1511,15 @@ TEST_P(HttpServerPropertiesManagerTest, ShutdownWithPendingUpdatePrefs2) {
// Shutdown comes before the task is executed.
http_server_props_manager_->ShutdownOnPrefThread();
// Run the task after shutdown, but before deletion.
- base::RunLoop().RunUntilIdle();
+ EXPECT_FALSE(net_test_task_runner_->HasPendingTask());
+ EXPECT_TRUE(pref_test_task_runner_->HasPendingTask());
+ pref_test_task_runner_->FastForwardUntilNoTasksRemain();
+ EXPECT_FALSE(net_test_task_runner_->HasPendingTask());
+ EXPECT_FALSE(pref_test_task_runner_->HasPendingTask());
Mock::VerifyAndClearExpectations(http_server_props_manager_.get());
http_server_props_manager_.reset();
- base::RunLoop().RunUntilIdle();
+ EXPECT_FALSE(net_test_task_runner_->HasPendingTask());
+ EXPECT_FALSE(pref_test_task_runner_->HasPendingTask());
}
} // namespace net
diff --git a/chromium/net/http/http_status_line_validator.cc b/chromium/net/http/http_status_line_validator.cc
deleted file mode 100644
index 5b8284cb5a3..00000000000
--- a/chromium/net/http/http_status_line_validator.cc
+++ /dev/null
@@ -1,136 +0,0 @@
-// Copyright 2015 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.
-
-#include "net/http/http_status_line_validator.h"
-
-#include <vector>
-
-#include "base/strings/string_split.h"
-#include "base/strings/string_util.h"
-
-namespace net {
-
-using base::StringPiece;
-
-HttpStatusLineValidator::StatusLineStatus
-HttpStatusLineValidator::ValidateStatusLine(const StringPiece& status_line) {
- std::vector<StringPiece> fields = base::SplitStringPiece(
- status_line, " ", base::KEEP_WHITESPACE, base::SPLIT_WANT_NONEMPTY);
- // Permissively split fields, meaning:
- // 1) Extra whitespace separating fields ignored
- // 2) Extra leading/trailing whitespace removed
- std::vector<StringPiece> loose_fields = base::SplitStringPiece(
- status_line, " ", base::KEEP_WHITESPACE, base::SPLIT_WANT_ALL);
-
- // Fields: HTTP-version status-code reason-phrase
- if (fields.empty() || loose_fields.empty())
- return STATUS_LINE_EMPTY;
-
- StatusLineStatus rv = CheckHttpVersionSyntax(fields[0]);
- if (rv != STATUS_LINE_OK)
- return rv;
-
- if (fields.size() < 2)
- return STATUS_LINE_MISSING_STATUS_CODE;
-
- rv = CheckStatusCodeSyntax(fields[1]);
- if (rv != STATUS_LINE_OK)
- return rv;
-
- // At this point the field splitting could be wrong, so check for extra
- // whitespace/padding on the result code.
- // Note that there is no such thing as "extra whitespace" on the
- // reason-phrase, since spaces are legal inside it.
- if (loose_fields[1] != fields[1])
- return STATUS_LINE_EXCESS_WHITESPACE;
-
- // An empty reason phrase will cause there to be only two fields in |fields|
- // but more than that in |loose_fields|.
- if (loose_fields.size() < 3)
- return STATUS_LINE_MISSING_REASON_PHRASE;
- return CheckReasonPhraseSyntax(fields, 2);
-}
-
-HttpStatusLineValidator::StatusLineStatus
-HttpStatusLineValidator::CheckHttpVersionSyntax(const StringPiece& version) {
- static const char kProtoName[] = "HTTP";
- static const char kDigits[] = "0123456789";
- if (!base::StartsWith(version, kProtoName,
- base::CompareCase::INSENSITIVE_ASCII)) {
- return STATUS_LINE_NOT_HTTP;
- }
- if (!base::StartsWith(version, kProtoName, base::CompareCase::SENSITIVE))
- return STATUS_LINE_HTTP_CASE_MISMATCH;
- // Okay, definitely "HTTP" at the start. Now check for the separating slash
- // and version number components:
- size_t slash = version.find('/');
- if (slash != strlen(kProtoName))
- return STATUS_LINE_HTTP_NO_VERSION;
- StringPiece rest = version.substr(slash + 1);
- size_t sep = rest.find('.');
- if (sep == StringPiece::npos) {
- return STATUS_LINE_INVALID_VERSION;
- }
- StringPiece major = rest.substr(0, sep);
- if (major.length() == 0)
- return STATUS_LINE_INVALID_VERSION;
- StringPiece minor = rest.substr(sep + 1);
- if (minor.length() == 0)
- return STATUS_LINE_INVALID_VERSION;
- if (major.find_first_not_of(kDigits) != major.npos ||
- minor.find_first_not_of(kDigits) != minor.npos) {
- return STATUS_LINE_INVALID_VERSION;
- }
-
- if (major.length() != 1 || minor.length() != 1)
- return STATUS_LINE_MULTI_DIGIT_VERSION;
-
- // It is now known that version looks like:
- // HTTP/x.y
- // For single digits x and y.
- // Check that x == '1' and y == '0' or '1'
- if (major[0] != '1' || (minor[0] != '0' && minor[0] != '1')) {
- if (major[0] == '0' && minor[0] == '9')
- return STATUS_LINE_EXPLICIT_0_9;
- else
- return STATUS_LINE_UNKNOWN_VERSION;
- }
- return STATUS_LINE_OK;
-}
-
-HttpStatusLineValidator::StatusLineStatus
-HttpStatusLineValidator::CheckStatusCodeSyntax(const StringPiece& status_code) {
- if (status_code.length() < 3)
- return STATUS_LINE_INVALID_STATUS_CODE;
- if (!isdigit(status_code[0]) || !isdigit(status_code[1]) ||
- !isdigit(status_code[2])) {
- return STATUS_LINE_INVALID_STATUS_CODE;
- }
- if (status_code.length() > 3)
- return STATUS_LINE_STATUS_CODE_TRAILING;
- // The only valid codes are 1xx through 5xx, see RFC 7231 S6
- if (status_code[0] < '1' || status_code[0] > '5')
- return STATUS_LINE_RESERVED_STATUS_CODE;
- return STATUS_LINE_OK;
-}
-
-HttpStatusLineValidator::StatusLineStatus
-HttpStatusLineValidator::CheckReasonPhraseSyntax(
- const std::vector<StringPiece>& fields,
- size_t start_index) {
- for (size_t i = start_index; i < fields.size(); ++i) {
- for (size_t j = 0; j < fields[i].length(); ++j) {
- // VCHAR is any "visible" ASCII character, meaning any non-control
- // character, so >= ' ' but not DEL (\x7f).
- // obs-text is any character between \x80 and \xff.
- // HTAB is \t, SP is ' '
- char c = fields[i][j];
- if (c == '\x7f' || (c < ' ' && c != '\t'))
- return STATUS_LINE_REASON_DISALLOWED_CHARACTER;
- }
- }
- return STATUS_LINE_OK;
-}
-
-} // namespace net
diff --git a/chromium/net/http/http_status_line_validator.h b/chromium/net/http/http_status_line_validator.h
deleted file mode 100644
index 1a12cd03e48..00000000000
--- a/chromium/net/http/http_status_line_validator.h
+++ /dev/null
@@ -1,88 +0,0 @@
-// Copyright 2015 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.
-
-#ifndef NET_HTTP_HTTP_STATUS_LINE_VALIDATOR_H_
-#define NET_HTTP_HTTP_STATUS_LINE_VALIDATOR_H_
-
-#include <stddef.h>
-
-#include <vector>
-
-#include "base/macros.h"
-#include "base/strings/string_piece.h"
-#include "net/base/net_export.h"
-
-namespace net {
-
-class HttpStatusLineValidator {
- public:
- // RFC 7230 S3.1.2:
- // status-line = HTTP-version SP status-code SP reason-phrase CRLF
- // status-code = 3DIGIT
- // reason-phrase = *( HTAB / SP / VCHAR / obs-text )
- // And from RFC 7230 S2.6:
- // HTTP-version = HTTP-name "/" DIGIT "." DIGIT
- // HTTP-name = "\x48\x54\x54\x50" ; ie, "HTTP" in uppercase
- enum StatusLineStatus {
- // No violations found.
- STATUS_LINE_OK = 0,
- // ""
- STATUS_LINE_EMPTY = 1,
- // "xyzzy"
- STATUS_LINE_NOT_HTTP = 2,
- // "HtTp/1.1 ..."
- STATUS_LINE_HTTP_CASE_MISMATCH = 3,
- // "HTTP" or "HTTP/"
- STATUS_LINE_HTTP_NO_VERSION = 4,
- // "HTTP/abc" or "HTTP/1" or "HTTP/1."
- STATUS_LINE_INVALID_VERSION = 5,
- // "HTTP/1.234 ..."
- STATUS_LINE_MULTI_DIGIT_VERSION = 6,
- // "HTTP/3.0 ..."
- STATUS_LINE_UNKNOWN_VERSION = 7,
- // "HTTP/0.9 ..."
- STATUS_LINE_EXPLICIT_0_9 = 8,
- // "HTTP/1.1"
- STATUS_LINE_MISSING_STATUS_CODE = 9,
- // "HTTP/1.1 abc"
- STATUS_LINE_INVALID_STATUS_CODE = 10,
- // "HTTP/1.1 123a"
- STATUS_LINE_STATUS_CODE_TRAILING = 11,
- // "HTTP/1.1 404", note that "HTTP/1.1 404 " is a valid empty reason phrase
- STATUS_LINE_MISSING_REASON_PHRASE = 12,
- // "HTTP/1.1 200 \x01"
- STATUS_LINE_REASON_DISALLOWED_CHARACTER = 13,
- // "HTTP/1.1 200 OK"
- STATUS_LINE_EXCESS_WHITESPACE = 14,
- // "HTTP/1.1 600 OK"
- STATUS_LINE_RESERVED_STATUS_CODE = 15,
-
- STATUS_LINE_MAX
- };
-
- // Checks for violations of the RFC 7230 S3.1.2 status-line grammar, and
- // returns the first violation found, or STATUS_LINE_OK if the status line
- // looks conforming.
- static StatusLineStatus NET_EXPORT_PRIVATE ValidateStatusLine(
- const base::StringPiece& status_line);
-
- private:
- static StatusLineStatus CheckHttpVersionSyntax(
- const base::StringPiece& version);
- static StatusLineStatus CheckStatusCodeSyntax(
- const base::StringPiece& status_code);
- // Checks |fields| against the reason-phrase syntax in RFC 7230 S3.1.2, ie:
- // reason-phrase = *( HTAB / SP / VCHAR / obs-text )
- // Note that the HTTP stream parser ignores the reason-phrase entirely, so
- // this check is needlessly pedantic.
- static StatusLineStatus CheckReasonPhraseSyntax(
- const std::vector<base::StringPiece>& fields,
- size_t start_index);
-
- DISALLOW_IMPLICIT_CONSTRUCTORS(HttpStatusLineValidator);
-};
-
-} // namespace net
-
-#endif // NET_HTTP_HTTP_STATUS_LINE_VALIDATOR_H_
diff --git a/chromium/net/http/http_status_line_validator_unittest.cc b/chromium/net/http/http_status_line_validator_unittest.cc
deleted file mode 100644
index 43a8bf2360f..00000000000
--- a/chromium/net/http/http_status_line_validator_unittest.cc
+++ /dev/null
@@ -1,88 +0,0 @@
-// Copyright 2015 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.
-
-#include "net/http/http_status_line_validator.h"
-
-#include "testing/gtest/include/gtest/gtest.h"
-
-namespace net {
-namespace {
-
-using Status = HttpStatusLineValidator::StatusLineStatus;
-
-struct ValidatorTestData {
- const char* name;
- const char* status_line;
- const Status expected_status;
-};
-
-class ValidatorTest : public ::testing::Test,
- public ::testing::WithParamInterface<ValidatorTestData> {
- public:
- ValidatorTest() {}
- ~ValidatorTest() override {}
-};
-
-std::string TestName(testing::TestParamInfo<ValidatorTestData> info) {
- return info.param.name;
-}
-
-TEST_P(ValidatorTest, Validate) {
- const ValidatorTestData test = GetParam();
-
- EXPECT_EQ(HttpStatusLineValidator::ValidateStatusLine(test.status_line),
- test.expected_status);
-}
-
-const ValidatorTestData validator_tests[] = {
- {"Http10_Ok", "HTTP/1.0 200 OK", Status::STATUS_LINE_OK},
- {"Http11_Ok", "HTTP/1.1 200 OK", Status::STATUS_LINE_OK},
- {"Empty", "", Status::STATUS_LINE_EMPTY},
- {"NotHttp", "xyzzy", Status::STATUS_LINE_NOT_HTTP},
- {"CaseMismatch", "HtTp/1.1 200 OK", Status::STATUS_LINE_HTTP_CASE_MISMATCH},
- {"NoVersion", "HTTP 200 OK", Status::STATUS_LINE_HTTP_NO_VERSION},
- {"InvalidVersion_0", "HTTP/a.b 200 OK",
- Status::STATUS_LINE_INVALID_VERSION},
- {"InvalidVersion_1", "HTTP/1.a 200 OK",
- Status::STATUS_LINE_INVALID_VERSION},
- {"InvalidVersion_2", "HTTP/a.1 200 OK",
- Status::STATUS_LINE_INVALID_VERSION},
- {"InvalidVersion_3", "HTTP/1 200 OK", Status::STATUS_LINE_INVALID_VERSION},
- {"InvalidVersion_4", "HTTP/1. 200 OK", Status::STATUS_LINE_INVALID_VERSION},
- {"MultiDigit_0", "HTTP/10.0 200 OK",
- Status::STATUS_LINE_MULTI_DIGIT_VERSION},
- {"MultiDigit_1", "HTTP/1.00 200 OK",
- Status::STATUS_LINE_MULTI_DIGIT_VERSION},
- {"UnknownVersion_0", "HTTP/1.2 200 OK",
- Status::STATUS_LINE_UNKNOWN_VERSION},
- {"UnknownVersion_1", "HTTP/2.0 200 OK",
- Status::STATUS_LINE_UNKNOWN_VERSION},
- {"Explicit09", "HTTP/0.9 200 OK", Status::STATUS_LINE_EXPLICIT_0_9},
- {"MissingStatusCode", "HTTP/1.0", Status::STATUS_LINE_MISSING_STATUS_CODE},
- {"InvalidStatusCode_0", "HTTP/1.0 abc OK",
- Status::STATUS_LINE_INVALID_STATUS_CODE},
- {"InvalidStatusCode_1", "HTTP/1.0 17 OK",
- Status::STATUS_LINE_INVALID_STATUS_CODE},
- {"StatusCodeTrailing", "HTTP/1.0 200a OK",
- Status::STATUS_LINE_STATUS_CODE_TRAILING},
- {"MissingReasonPhrase", "HTTP/1.0 200",
- Status::STATUS_LINE_MISSING_REASON_PHRASE},
- {"EmptyReasonPhrase_Ok", "HTTP/1.0 200 ", Status::STATUS_LINE_OK},
- {"ReasonDisallowedCharacter", "HTTP/1.0 200 OK\x01",
- Status::STATUS_LINE_REASON_DISALLOWED_CHARACTER},
- {"ExcessWhitespace", "HTTP/1.0 200 OK",
- Status::STATUS_LINE_EXCESS_WHITESPACE},
- {"ReasonWhitespace_Ok", "HTTP/1.0 200 OK", Status::STATUS_LINE_OK},
- {"ReservedStatusCode_0", "HTTP/1.0 099 OK",
- Status::STATUS_LINE_RESERVED_STATUS_CODE},
- {"ReservedStatusCode_1", "HTTP/1.0 600 OK",
- Status::STATUS_LINE_RESERVED_STATUS_CODE}};
-
-INSTANTIATE_TEST_CASE_P(HttpStatusLineValidator,
- ValidatorTest,
- testing::ValuesIn(validator_tests),
- TestName);
-
-} // namespace
-} // namespace net
diff --git a/chromium/net/http/http_stream_factory.cc b/chromium/net/http/http_stream_factory.cc
index 8bff8df3912..36e587ebdf2 100644
--- a/chromium/net/http/http_stream_factory.cc
+++ b/chromium/net/http/http_stream_factory.cc
@@ -15,7 +15,7 @@
#include "net/base/port_util.h"
#include "net/http/http_network_session.h"
#include "net/http/http_response_headers.h"
-#include "net/quic/core/quic_protocol.h"
+#include "net/quic/core/quic_packets.h"
#include "net/spdy/spdy_alt_svc_wire_format.h"
#include "url/gurl.h"
diff --git a/chromium/net/http/http_stream_factory.h b/chromium/net/http/http_stream_factory.h
index 7a094f6613b..c4a95798cc5 100644
--- a/chromium/net/http/http_stream_factory.h
+++ b/chromium/net/http/http_stream_factory.h
@@ -22,23 +22,15 @@
// introduce any link dependency to net/websockets.
#include "net/websockets/websocket_handshake_stream_base.h"
-class GURL;
-
-namespace base {
-class Value;
-}
-
namespace net {
class AuthCredentials;
class BidirectionalStreamImpl;
class HostMappingRules;
-class HostPortPair;
class HttpAuthController;
class HttpNetworkSession;
class HttpResponseHeaders;
class HttpResponseInfo;
-class HttpServerProperties;
class HttpStream;
class NetLogWithSource;
class ProxyInfo;
diff --git a/chromium/net/http/http_stream_factory_impl.cc b/chromium/net/http/http_stream_factory_impl.cc
index 5ba08cf0beb..38d942e7a16 100644
--- a/chromium/net/http/http_stream_factory_impl.cc
+++ b/chromium/net/http/http_stream_factory_impl.cc
@@ -5,9 +5,11 @@
#include "net/http/http_stream_factory_impl.h"
#include <string>
+#include <tuple>
#include "base/logging.h"
#include "base/memory/ptr_util.h"
+#include "base/metrics/histogram_macros.h"
#include "base/stl_util.h"
#include "base/strings/string_util.h"
#include "net/http/http_network_session.h"
@@ -16,10 +18,12 @@
#include "net/http/http_stream_factory_impl_job_controller.h"
#include "net/http/http_stream_factory_impl_request.h"
#include "net/http/transport_security_state.h"
+#include "net/proxy/proxy_info.h"
#include "net/quic/core/quic_server_id.h"
#include "net/spdy/bidirectional_stream_spdy_impl.h"
#include "net/spdy/spdy_http_stream.h"
#include "url/gurl.h"
+#include "url/scheme_host_port.h"
#include "url/url_constants.h"
namespace net {
@@ -84,6 +88,7 @@ class DefaultJobFactory : public HttpStreamFactoryImpl::JobFactory {
alternative_proxy_server, net_log);
}
};
+
} // anonymous namespace
HttpStreamFactoryImpl::HttpStreamFactoryImpl(HttpNetworkSession* session,
@@ -239,4 +244,86 @@ void HttpStreamFactoryImpl::OnJobControllerComplete(JobController* controller) {
NOTREACHED();
}
+HttpStreamFactoryImpl::PreconnectingProxyServer::PreconnectingProxyServer(
+ ProxyServer proxy_server,
+ PrivacyMode privacy_mode)
+ : proxy_server(proxy_server), privacy_mode(privacy_mode) {}
+
+bool HttpStreamFactoryImpl::PreconnectingProxyServer::operator<(
+ const PreconnectingProxyServer& other) const {
+ return std::tie(proxy_server, privacy_mode) <
+ std::tie(other.proxy_server, other.privacy_mode);
+}
+
+bool HttpStreamFactoryImpl::PreconnectingProxyServer::operator==(
+ const PreconnectingProxyServer& other) const {
+ return proxy_server == other.proxy_server &&
+ privacy_mode == other.privacy_mode;
+}
+
+bool HttpStreamFactoryImpl::OnInitConnection(const JobController& controller,
+ const ProxyInfo& proxy_info,
+ PrivacyMode privacy_mode) {
+ if (!controller.is_preconnect()) {
+ // Connection initialization can be skipped only for the preconnect jobs.
+ return false;
+ }
+
+ if (!session_->params().restrict_to_one_preconnect_for_proxies ||
+ !ProxyServerSupportsPriorities(proxy_info)) {
+ return false;
+ }
+
+ PreconnectingProxyServer preconnecting_proxy_server(proxy_info.proxy_server(),
+ privacy_mode);
+
+ if (base::ContainsKey(preconnecting_proxy_servers_,
+ preconnecting_proxy_server)) {
+ UMA_HISTOGRAM_EXACT_LINEAR("Net.PreconnectSkippedToProxyServers", 1, 2);
+ // Skip preconnect to the proxy server since we are already preconnecting
+ // (probably via some other job).
+ return true;
+ }
+
+ // Add the proxy server to the set of preconnecting proxy servers.
+ // The maximum size of |preconnecting_proxy_servers_|.
+ static const size_t kMaxPreconnectingServerSize = 3;
+ if (preconnecting_proxy_servers_.size() >= kMaxPreconnectingServerSize) {
+ // Erase the first entry. A better approach (at the cost of higher memory
+ // overhead) may be to erase the least recently used entry.
+ preconnecting_proxy_servers_.erase(preconnecting_proxy_servers_.begin());
+ }
+
+ preconnecting_proxy_servers_.insert(preconnecting_proxy_server);
+ DCHECK_GE(kMaxPreconnectingServerSize, preconnecting_proxy_servers_.size());
+ // The first preconnect should be allowed.
+ return false;
+}
+
+void HttpStreamFactoryImpl::OnStreamReady(const ProxyInfo& proxy_info,
+ PrivacyMode privacy_mode) {
+ if (proxy_info.is_empty())
+ return;
+ preconnecting_proxy_servers_.erase(
+ PreconnectingProxyServer(proxy_info.proxy_server(), privacy_mode));
+}
+
+bool HttpStreamFactoryImpl::ProxyServerSupportsPriorities(
+ const ProxyInfo& proxy_info) const {
+ if (proxy_info.is_empty() || !proxy_info.proxy_server().is_valid())
+ return false;
+
+ if (!proxy_info.proxy_server().is_https())
+ return false;
+
+ HostPortPair host_port_pair = proxy_info.proxy_server().host_port_pair();
+ DCHECK(!host_port_pair.IsEmpty());
+
+ url::SchemeHostPort scheme_host_port("https", host_port_pair.host(),
+ host_port_pair.port());
+
+ return session_->http_server_properties()->SupportsRequestPriority(
+ scheme_host_port);
+}
+
} // namespace net
diff --git a/chromium/net/http/http_stream_factory_impl.h b/chromium/net/http/http_stream_factory_impl.h
index 92301356d30..6c214368a3c 100644
--- a/chromium/net/http/http_stream_factory_impl.h
+++ b/chromium/net/http/http_stream_factory_impl.h
@@ -16,6 +16,7 @@
#include "base/memory/ref_counted.h"
#include "net/base/host_port_pair.h"
#include "net/base/net_export.h"
+#include "net/base/privacy_mode.h"
#include "net/base/request_priority.h"
#include "net/http/http_stream_factory.h"
#include "net/proxy/proxy_server.h"
@@ -25,6 +26,7 @@
namespace net {
class HttpNetworkSession;
+class ProxyInfo;
class SpdySession;
class NetLogWithSource;
@@ -84,6 +86,20 @@ class NET_EXPORT_PRIVATE HttpStreamFactoryImpl : public HttpStreamFactory {
typedef std::map<SpdySessionKey, RequestSet> SpdySessionRequestMap;
typedef std::set<std::unique_ptr<JobController>> JobControllerSet;
+ // |PreconnectingProxyServer| holds information of a connection to a single
+ // proxy server.
+ struct PreconnectingProxyServer {
+ PreconnectingProxyServer(ProxyServer proxy_server,
+ PrivacyMode privacy_mode);
+
+ // Needed to be an element of std::set.
+ bool operator<(const PreconnectingProxyServer& other) const;
+ bool operator==(const PreconnectingProxyServer& other) const;
+
+ const ProxyServer proxy_server;
+ const PrivacyMode privacy_mode;
+ };
+
// Values must not be changed or reused. Keep in sync with identically named
// enum in histograms.xml.
enum AlternativeServiceType {
@@ -129,6 +145,21 @@ class NET_EXPORT_PRIVATE HttpStreamFactoryImpl : public HttpStreamFactory {
// from |job_controller_set_|.
void OnJobControllerComplete(JobController* controller);
+ // Returns true if a connection to the proxy server contained in |proxy_info|
+ // that has privacy mode |privacy_mode| can be skipped by a job controlled by
+ // |controller|.
+ bool OnInitConnection(const JobController& controller,
+ const ProxyInfo& proxy_info,
+ PrivacyMode privacy_mode);
+
+ // Notifies |this| that a stream to the proxy server contained in |proxy_info|
+ // with privacy mode |privacy_mode| is ready.
+ void OnStreamReady(const ProxyInfo& proxy_info, PrivacyMode privacy_mode);
+
+ // Returns true if |proxy_info| contains a proxy server that supports request
+ // priorities.
+ bool ProxyServerSupportsPriorities(const ProxyInfo& proxy_info) const;
+
HttpNetworkSession* const session_;
// All Requests are handed out to clients. By the time HttpStreamFactoryImpl
@@ -146,9 +177,14 @@ class NET_EXPORT_PRIVATE HttpStreamFactoryImpl : public HttpStreamFactory {
// Factory used by job controllers for creating jobs.
std::unique_ptr<JobFactory> job_factory_;
+ // Set of proxy servers that support request priorities to which subsequent
+ // preconnects should be skipped.
+ std::set<PreconnectingProxyServer> preconnecting_proxy_servers_;
+
SpdySessionRequestMap spdy_session_request_map_;
const bool for_websockets_;
+
DISALLOW_COPY_AND_ASSIGN(HttpStreamFactoryImpl);
};
diff --git a/chromium/net/http/http_stream_factory_impl_job.cc b/chromium/net/http/http_stream_factory_impl_job.cc
index e91febf82cd..2cd3bcbe0b6 100644
--- a/chromium/net/http/http_stream_factory_impl_job.cc
+++ b/chromium/net/http/http_stream_factory_impl_job.cc
@@ -18,13 +18,13 @@
#include "base/stl_util.h"
#include "base/strings/string_number_conversions.h"
#include "base/strings/string_util.h"
-#include "base/strings/stringprintf.h"
#include "base/threading/thread_task_runner_handle.h"
#include "base/trace_event/trace_event.h"
#include "base/values.h"
#include "build/build_config.h"
#include "net/base/port_util.h"
#include "net/base/proxy_delegate.h"
+#include "net/base/trace_constants.h"
#include "net/cert/cert_verifier.h"
#include "net/http/bidirectional_stream_impl.h"
#include "net/http/http_basic_stream.h"
@@ -231,7 +231,7 @@ HttpStreamFactoryImpl::Job::Job(Delegate* delegate,
DCHECK(origin_url_.SchemeIs(url::kHttpsScheme));
}
if (IsQuicAlternative()) {
- DCHECK(session_->params().enable_quic);
+ DCHECK(session_->IsQuicEnabled());
using_quic_ = true;
}
}
@@ -386,7 +386,7 @@ void HttpStreamFactoryImpl::Job::OnStreamReadyCallback() {
MaybeCopyConnectionAttemptsFromSocketOrHandle();
- delegate_->OnStreamReady(this, server_ssl_config_, proxy_info_);
+ delegate_->OnStreamReady(this, server_ssl_config_);
// |this| may be deleted after this call.
}
@@ -476,6 +476,8 @@ void HttpStreamFactoryImpl::Job::OnHttpsProxyTunnelResponseCallback(
}
void HttpStreamFactoryImpl::Job::OnPreconnectsComplete() {
+ DCHECK(!new_spdy_session_);
+
if (new_spdy_session_.get()) {
delegate_->OnNewSpdySessionReady(this, new_spdy_session_,
spdy_session_direct_);
@@ -501,14 +503,12 @@ int HttpStreamFactoryImpl::Job::OnHostResolution(
}
void HttpStreamFactoryImpl::Job::OnIOComplete(int result) {
- TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("net"),
- "HttpStreamFactoryImpl::Job::OnIOComplete");
+ TRACE_EVENT0(kNetTracingCategory, "HttpStreamFactoryImpl::Job::OnIOComplete");
RunLoop(result);
}
int HttpStreamFactoryImpl::Job::RunLoop(int result) {
- TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("net"),
- "HttpStreamFactoryImpl::Job::RunLoop");
+ TRACE_EVENT0(kNetTracingCategory, "HttpStreamFactoryImpl::Job::RunLoop");
result = DoLoop(result);
if (result == ERR_IO_PENDING)
@@ -737,7 +737,7 @@ int HttpStreamFactoryImpl::Job::DoResolveProxyComplete(int result) {
ProxyServer::SCHEME_HTTPS | ProxyServer::SCHEME_SOCKS4 |
ProxyServer::SCHEME_SOCKS5;
- if (session_->params().enable_quic)
+ if (session_->IsQuicEnabled())
supported_proxies |= ProxyServer::SCHEME_QUIC;
proxy_info_.RemoveProxiesWithoutScheme(supported_proxies);
@@ -768,7 +768,7 @@ int HttpStreamFactoryImpl::Job::DoResolveProxyComplete(int result) {
}
bool HttpStreamFactoryImpl::Job::ShouldForceQuic() const {
- return session_->params().enable_quic &&
+ return session_->IsQuicEnabled() &&
(base::ContainsKey(session_->params().origins_to_force_quic_on,
HostPortPair()) ||
base::ContainsKey(session_->params().origins_to_force_quic_on,
@@ -807,6 +807,11 @@ int HttpStreamFactoryImpl::Job::DoInitConnectionImpl() {
DCHECK(proxy_info_.proxy_server().is_valid());
next_state_ = STATE_INIT_CONNECTION_COMPLETE;
+ if (delegate_->OnInitConnection(proxy_info_)) {
+ // Return since the connection initialization can be skipped.
+ return OK;
+ }
+
using_ssl_ = origin_url_.SchemeIs(url::kHttpsScheme) ||
origin_url_.SchemeIs(url::kWssScheme);
using_spdy_ = false;
@@ -814,11 +819,11 @@ int HttpStreamFactoryImpl::Job::DoInitConnectionImpl() {
if (ShouldForceQuic())
using_quic_ = true;
- DCHECK(!using_quic_ || session_->params().enable_quic);
+ DCHECK(!using_quic_ || session_->IsQuicEnabled());
if (proxy_info_.is_quic()) {
using_quic_ = true;
- DCHECK(session_->params().enable_quic);
+ DCHECK(session_->IsQuicEnabled());
}
if (proxy_info_.is_https() || proxy_info_.is_quic()) {
@@ -1012,7 +1017,7 @@ int HttpStreamFactoryImpl::Job::DoInitConnectionComplete(int result) {
} else {
SSLClientSocket* ssl_socket =
static_cast<SSLClientSocket*>(connection_->socket());
- if (ssl_socket->WasNpnNegotiated()) {
+ if (ssl_socket->WasAlpnNegotiated()) {
was_alpn_negotiated_ = true;
negotiated_protocol_ = ssl_socket->GetNegotiatedProtocol();
net_log_.AddEvent(
diff --git a/chromium/net/http/http_stream_factory_impl_job.h b/chromium/net/http/http_stream_factory_impl_job.h
index 6ed6157c500..ffb55813a09 100644
--- a/chromium/net/http/http_stream_factory_impl_job.h
+++ b/chromium/net/http/http_stream_factory_impl_job.h
@@ -40,7 +40,6 @@ class HttpStream;
class SpdySessionPool;
class NetLog;
struct SSLConfig;
-class QuicHttpStream;
// An HttpStreamRequestImpl exists for each stream which is in progress of being
// created for the StreamFactory.
@@ -52,9 +51,7 @@ class HttpStreamFactoryImpl::Job {
virtual ~Delegate() {}
// Invoked when |job| has an HttpStream ready.
- virtual void OnStreamReady(Job* job,
- const SSLConfig& used_ssl_config,
- const ProxyInfo& used_proxy_info) = 0;
+ virtual void OnStreamReady(Job* job, const SSLConfig& used_ssl_config) = 0;
// Invoked when |job| has a BidirectionalStream ready.
virtual void OnBidirectionalStreamImplReady(
@@ -101,6 +98,10 @@ class HttpStreamFactoryImpl::Job {
const ProxyInfo& used_proxy_info,
HttpAuthController* auth_controller) = 0;
+ // Returns true if the connection initialization to the proxy server
+ // contained in |proxy_info| can be skipped.
+ virtual bool OnInitConnection(const ProxyInfo& proxy_info) = 0;
+
// Invoked when |job| has completed proxy resolution. The delegate may
// create an alternative proxy server job to fetch the request.
virtual void OnResolveProxyComplete(
diff --git a/chromium/net/http/http_stream_factory_impl_job_controller.cc b/chromium/net/http/http_stream_factory_impl_job_controller.cc
index 83d10def31c..5a020451f0a 100644
--- a/chromium/net/http/http_stream_factory_impl_job_controller.cc
+++ b/chromium/net/http/http_stream_factory_impl_job_controller.cc
@@ -11,6 +11,7 @@
#include "base/metrics/histogram_macros.h"
#include "base/strings/string_number_conversions.h"
#include "base/strings/string_util.h"
+#include "base/threading/thread_task_runner_handle.h"
#include "base/values.h"
#include "net/base/host_mapping_rules.h"
#include "net/base/proxy_delegate.h"
@@ -26,6 +27,10 @@
namespace net {
+// The maximum time to wait for the alternate job to complete before resuming
+// the main job.
+const int kMaxDelayTimeForMainJobSecs = 3;
+
// Returns parameters associated with the delay of the HTTP stream job.
std::unique_ptr<base::Value> NetLogHttpStreamJobDelayCallback(
base::TimeDelta delay,
@@ -49,8 +54,10 @@ HttpStreamFactoryImpl::JobController::JobController(
alternative_job_failed_(false),
job_bound_(false),
main_job_is_blocked_(false),
+ main_job_is_resumed_(false),
bound_job_(nullptr),
can_start_alternative_proxy_job_(false),
+ privacy_mode_(PRIVACY_MODE_DISABLED),
ptr_factory_(this) {
DCHECK(factory);
}
@@ -78,6 +85,8 @@ HttpStreamFactoryImpl::Request* HttpStreamFactoryImpl::JobController::Start(
DCHECK(factory_);
DCHECK(!request_);
+ privacy_mode_ = request_info.privacy_mode;
+
request_ = new Request(request_info.url, this, delegate,
websocket_handshake_stream_create_helper, net_log,
stream_type);
@@ -96,6 +105,8 @@ void HttpStreamFactoryImpl::JobController::Preconnect(
DCHECK(!main_job_);
DCHECK(!alternative_job_);
+ privacy_mode_ = request_info.privacy_mode;
+
is_preconnect_ = true;
HostPortPair destination(HostPortPair::FromURL(request_info.url));
GURL origin_url = ApplyHostMappingRules(request_info.url, &destination);
@@ -151,13 +162,6 @@ void HttpStreamFactoryImpl::JobController::OnRequestComplete() {
} else {
DCHECK(bound_job_->job_type() == ALTERNATIVE);
alternative_job_.reset();
- // If ResumeMainJob() is not executed, reset |main_job_|. Otherwise,
- // OnOrphanedJobComplete() will clean up |this| when the job completes.
- // Use |main_job_is_blocked_| and |!main_job_wait_time_.is_zero()| instead
- // of |main_job_|->is_waiting() because |main_job_| can be in proxy
- // resolution step.
- if (main_job_ && (main_job_is_blocked_ || !main_job_wait_time_.is_zero()))
- main_job_.reset();
}
bound_job_ = nullptr;
}
@@ -182,10 +186,11 @@ void HttpStreamFactoryImpl::JobController::SetPriority(
void HttpStreamFactoryImpl::JobController::OnStreamReady(
Job* job,
- const SSLConfig& used_ssl_config,
- const ProxyInfo& used_proxy_info) {
+ const SSLConfig& used_ssl_config) {
DCHECK(job);
+ factory_->OnStreamReady(job->proxy_info(), privacy_mode_);
+
if (IsJobOrphaned(job)) {
// We have bound a job to the associated Request, |job| has been orphaned.
OnOrphanedJobComplete(job);
@@ -202,7 +207,7 @@ void HttpStreamFactoryImpl::JobController::OnStreamReady(
DCHECK(!factory_->for_websockets_);
DCHECK_EQ(HttpStreamRequest::HTTP_STREAM, request_->stream_type());
OnJobSucceeded(job);
- request_->OnStreamReady(used_ssl_config, used_proxy_info, stream.release());
+ request_->OnStreamReady(used_ssl_config, job->proxy_info(), stream.release());
}
void HttpStreamFactoryImpl::JobController::OnBidirectionalStreamImplReady(
@@ -378,6 +383,11 @@ void HttpStreamFactoryImpl::JobController::OnNeedsProxyAuth(
auth_controller);
}
+bool HttpStreamFactoryImpl::JobController::OnInitConnection(
+ const ProxyInfo& proxy_info) {
+ return factory_->OnInitConnection(*this, proxy_info, privacy_mode_);
+}
+
void HttpStreamFactoryImpl::JobController::OnResolveProxyComplete(
Job* job,
const HttpRequestInfo& request_info,
@@ -424,6 +434,7 @@ void HttpStreamFactoryImpl::JobController::OnNewSpdySessionReady(
bool direct) {
DCHECK(job);
DCHECK(job->using_spdy());
+ DCHECK(!is_preconnect_);
bool is_job_orphaned = IsJobOrphaned(job);
@@ -515,6 +526,10 @@ void HttpStreamFactoryImpl::JobController::AddConnectionAttemptsToRequest(
}
void HttpStreamFactoryImpl::JobController::ResumeMainJob() {
+ if (main_job_is_resumed_)
+ return;
+
+ main_job_is_resumed_ = true;
main_job_->net_log().AddEvent(
NetLogEventType::HTTP_STREAM_JOB_DELAYED,
base::Bind(&NetLogHttpStreamJobDelayCallback, main_job_wait_time_));
@@ -526,15 +541,24 @@ void HttpStreamFactoryImpl::JobController::ResumeMainJob() {
void HttpStreamFactoryImpl::JobController::MaybeResumeMainJob(
Job* job,
const base::TimeDelta& delay) {
+ DCHECK(delay == base::TimeDelta() || delay == main_job_wait_time_);
DCHECK(job == main_job_.get() || job == alternative_job_.get());
- if (!main_job_is_blocked_ || job != alternative_job_.get() || !main_job_)
+ if (job != alternative_job_.get() || !main_job_)
return;
main_job_is_blocked_ = false;
- if (!main_job_->is_waiting())
+ if (!main_job_->is_waiting()) {
+ // There are two cases where the main job is not in WAIT state:
+ // 1) The main job hasn't got to waiting state, do not yet post a task to
+ // resume since that will happen in ShouldWait().
+ // 2) The main job has passed waiting state, so the main job does not need
+ // to be resumed.
return;
+ }
+
+ main_job_wait_time_ = delay;
base::ThreadTaskRunnerHandle::Get()->PostDelayedTask(
FROM_HERE,
@@ -623,8 +647,10 @@ const NetLogWithSource* HttpStreamFactoryImpl::JobController::GetNetLog(
void HttpStreamFactoryImpl::JobController::MaybeSetWaitTimeForMainJob(
const base::TimeDelta& delay) {
- if (main_job_is_blocked_)
- main_job_wait_time_ = delay;
+ if (main_job_is_blocked_) {
+ main_job_wait_time_ = std::min(
+ delay, base::TimeDelta::FromSeconds(kMaxDelayTimeForMainJobSecs));
+ }
}
WebSocketHandshakeStreamBase::CreateHelper* HttpStreamFactoryImpl::
@@ -735,7 +761,17 @@ void HttpStreamFactoryImpl::JobController::OrphanUnboundJob() {
} else if (bound_job_->job_type() == ALTERNATIVE && main_job_) {
// Orphan main job.
factory_->request_map_.erase(main_job_.get());
- main_job_->Orphan();
+ // If ResumeMainJob() is not executed, reset |main_job_|. Otherwise,
+ // OnOrphanedJobComplete() will clean up |this| when the job completes.
+ // Use |main_job_is_blocked_| and |!main_job_wait_time_.is_zero()| instead
+ // of |main_job_|->is_waiting() because |main_job_| can be in proxy
+ // resolution step.
+ if (main_job_ && (main_job_is_blocked_ || !main_job_wait_time_.is_zero())) {
+ DCHECK(alternative_job_);
+ main_job_.reset();
+ } else {
+ main_job_->Orphan();
+ }
}
}
@@ -948,7 +984,7 @@ HttpStreamFactoryImpl::JobController::GetAlternativeServiceForInternal(
}
quic_all_broken = false;
- if (!session_->params().enable_quic)
+ if (!session_->IsQuicEnabled())
continue;
if (!IsQuicWhitelistedForHost(origin.host()))
@@ -1048,7 +1084,7 @@ bool HttpStreamFactoryImpl::JobController::
if (alternative_proxy_server->is_quic()) {
// Check that QUIC is enabled globally, and it is not disabled.
- if (!session_->params().enable_quic ||
+ if (!session_->IsQuicEnabled() ||
session_->quic_stream_factory()->IsQuicDisabled()) {
return false;
}
diff --git a/chromium/net/http/http_stream_factory_impl_job_controller.h b/chromium/net/http/http_stream_factory_impl_job_controller.h
index d3b80d03251..c6a99ac12c2 100644
--- a/chromium/net/http/http_stream_factory_impl_job_controller.h
+++ b/chromium/net/http/http_stream_factory_impl_job_controller.h
@@ -6,6 +6,7 @@
#define NET_HTTP_HTTP_STREAM_FACTORY_IMPL_JOB_CONTROLLER_H_
#include "net/base/host_port_pair.h"
+#include "net/base/privacy_mode.h"
#include "net/http/http_stream_factory_impl_job.h"
#include "net/http/http_stream_factory_impl_request.h"
@@ -69,9 +70,7 @@ class HttpStreamFactoryImpl::JobController
// From HttpStreamFactoryImpl::Job::Delegate.
// Invoked when |job| has an HttpStream ready.
- void OnStreamReady(Job* job,
- const SSLConfig& used_ssl_config,
- const ProxyInfo& used_proxy_info) override;
+ void OnStreamReady(Job* job, const SSLConfig& used_ssl_config) override;
// Invoked when |job| has a BidirectionalStream ready.
void OnBidirectionalStreamImplReady(
@@ -117,6 +116,8 @@ class HttpStreamFactoryImpl::JobController
const ProxyInfo& used_proxy_info,
HttpAuthController* auth_controller) override;
+ bool OnInitConnection(const ProxyInfo& proxy_info) override;
+
void OnResolveProxyComplete(
Job* job,
const HttpRequestInfo& request_info,
@@ -167,6 +168,8 @@ class HttpStreamFactoryImpl::JobController
WebSocketHandshakeStreamBase::CreateHelper*
websocket_handshake_stream_create_helper() override;
+ bool is_preconnect() const { return is_preconnect_; }
+
private:
friend class JobControllerPeer;
@@ -290,6 +293,10 @@ class HttpStreamFactoryImpl::JobController
// True if the main job has to wait for the alternative job: i.e., the main
// job must not create a connection until it is resumed.
bool main_job_is_blocked_;
+
+ // True if the main job was blocked and has been resumed in ResumeMainJob().
+ bool main_job_is_resumed_;
+
// Waiting time for the main job before it is resumed.
base::TimeDelta main_job_wait_time_;
@@ -300,6 +307,9 @@ class HttpStreamFactoryImpl::JobController
// True if an alternative proxy server job can be started to fetch |request_|.
bool can_start_alternative_proxy_job_;
+ // Privacy mode that should be used for fetching the resource.
+ PrivacyMode privacy_mode_;
+
base::WeakPtrFactory<JobController> ptr_factory_;
};
diff --git a/chromium/net/http/http_stream_factory_impl_job_controller_unittest.cc b/chromium/net/http/http_stream_factory_impl_job_controller_unittest.cc
index 7a4c7e65e78..d4f94a3e4af 100644
--- a/chromium/net/http/http_stream_factory_impl_job_controller_unittest.cc
+++ b/chromium/net/http/http_stream_factory_impl_job_controller_unittest.cc
@@ -9,6 +9,7 @@
#include "base/memory/ptr_util.h"
#include "base/run_loop.h"
#include "base/test/histogram_tester.h"
+#include "base/test/scoped_mock_time_message_loop_task_runner.h"
#include "base/threading/platform_thread.h"
#include "net/base/test_proxy_delegate.h"
#include "net/dns/mock_host_resolver.h"
@@ -126,12 +127,12 @@ class HttpStreamFactoryImplJobControllerTest
test_proxy_delegate->set_alternative_proxy_server(
ProxyServer::FromPacString("QUIC myproxy.org:443"));
EXPECT_TRUE(test_proxy_delegate->alternative_proxy_server().is_quic());
- session_deps_.proxy_delegate.reset(test_proxy_delegate.release());
+ session_deps_.proxy_delegate = std::move(test_proxy_delegate);
if (use_alternative_proxy) {
std::unique_ptr<ProxyService> proxy_service =
ProxyService::CreateFixedFromPacResult("HTTPS myproxy.org:443");
- session_deps_.proxy_service.reset(proxy_service.release());
+ session_deps_.proxy_service = std::move(proxy_service);
}
session_ = SpdySessionDependencies::SpdyCreateSession(&session_deps_);
factory_ =
@@ -239,8 +240,7 @@ TEST_F(HttpStreamFactoryImplJobControllerTest,
EXPECT_CALL(request_delegate_, OnStreamReady(_, _, http_stream))
.WillOnce(Invoke(DeleteHttpStreamPointer));
- job_controller_->OnStreamReady(job_factory_.main_job(), SSLConfig(),
- ProxyInfo());
+ job_controller_->OnStreamReady(job_factory_.main_job(), SSLConfig());
}
// Test we cancel Jobs correctly when the Request is explicitly canceled
@@ -358,8 +358,7 @@ TEST_F(HttpStreamFactoryImplJobControllerTest,
EXPECT_CALL(request_delegate_, OnStreamReady(_, _, http_stream))
.WillOnce(Invoke(DeleteHttpStreamPointer));
- job_controller_->OnStreamReady(job_factory_.main_job(), SSLConfig(),
- ProxyInfo());
+ job_controller_->OnStreamReady(job_factory_.main_job(), SSLConfig());
// JobController shouldn't report the status of second job as request
// is already successfully served.
@@ -373,8 +372,9 @@ TEST_F(HttpStreamFactoryImplJobControllerTest,
EXPECT_TRUE(HttpStreamFactoryImplPeer::IsJobControllerDeleted(factory_));
}
-// Tests that if alt job succeeds and main job is blocked, |request_| completion
-// will clean up JobController. Regression test for crbug.com/678768.
+// Tests that if alt job succeeds and main job is blocked, main job should be
+// cancelled immediately. |request_| completion will clean up the JobController.
+// Regression test for crbug.com/678768.
TEST_F(HttpStreamFactoryImplJobControllerTest,
AltJobSucceedsMainJobBlockedControllerDestroyed) {
ProxyConfig proxy_config;
@@ -407,12 +407,10 @@ TEST_F(HttpStreamFactoryImplJobControllerTest,
job_factory_.alternative_job()->SetStream(http_stream);
EXPECT_CALL(request_delegate_, OnStreamReady(_, _, http_stream))
.WillOnce(Invoke(DeleteHttpStreamPointer));
- job_controller_->OnStreamReady(job_factory_.alternative_job(), SSLConfig(),
- ProxyInfo());
+ job_controller_->OnStreamReady(job_factory_.alternative_job(), SSLConfig());
- EXPECT_TRUE(job_controller_->main_job());
+ EXPECT_FALSE(job_controller_->main_job());
EXPECT_TRUE(job_controller_->alternative_job());
- EXPECT_TRUE(JobControllerPeer::main_job_is_blocked(job_controller_));
// Invoke OnRequestComplete() which should delete |job_controller_| from
// |factory_|.
@@ -470,9 +468,7 @@ TEST_F(HttpStreamFactoryImplJobControllerTest,
EXPECT_CALL(request_delegate_, OnStreamReady(_, _, http_stream))
.WillOnce(Invoke(DeleteHttpStreamPointer));
- job_controller_->OnStreamReady(job_factory_.main_job(), SSLConfig(),
- ProxyInfo());
-
+ job_controller_->OnStreamReady(job_factory_.main_job(), SSLConfig());
// Invoke OnRequestComplete() which should not delete |job_controller_| from
// |factory_| because alt job is yet to finish.
request_.reset();
@@ -487,8 +483,7 @@ TEST_F(HttpStreamFactoryImplJobControllerTest,
new HttpBasicStream(base::MakeUnique<ClientSocketHandle>(), false, false);
job_factory_.alternative_job()->SetStream(http_stream2);
// This should not call request_delegate_::OnStreamReady.
- job_controller_->OnStreamReady(job_factory_.alternative_job(), SSLConfig(),
- ProxyInfo());
+ job_controller_->OnStreamReady(job_factory_.alternative_job(), SSLConfig());
// Make sure that controller does not leak.
EXPECT_TRUE(HttpStreamFactoryImplPeer::IsJobControllerDeleted(factory_));
}
@@ -533,8 +528,7 @@ TEST_F(HttpStreamFactoryImplJobControllerTest,
EXPECT_CALL(request_delegate_, OnStreamReady(_, _, http_stream))
.WillOnce(Invoke(DeleteHttpStreamPointer));
- job_controller_->OnStreamReady(job_factory_.alternative_job(), SSLConfig(),
- ProxyInfo());
+ job_controller_->OnStreamReady(job_factory_.alternative_job(), SSLConfig());
VerifyBrokenAlternateProtocolMapping(request_info, false);
}
@@ -578,8 +572,7 @@ TEST_F(HttpStreamFactoryImplJobControllerTest,
EXPECT_CALL(request_delegate_, OnStreamReady(_, _, http_stream))
.WillOnce(Invoke(DeleteHttpStreamPointer));
- job_controller_->OnStreamReady(job_factory_.main_job(), SSLConfig(),
- ProxyInfo());
+ job_controller_->OnStreamReady(job_factory_.main_job(), SSLConfig());
VerifyBrokenAlternateProtocolMapping(request_info, true);
}
@@ -629,8 +622,7 @@ TEST_F(HttpStreamFactoryImplJobControllerTest, GetLoadStateAfterMainJobFailed) {
EXPECT_CALL(request_delegate_, OnStreamReady(_, _, http_stream))
.WillOnce(Invoke(DeleteHttpStreamPointer));
- job_controller_->OnStreamReady(job_factory_.alternative_job(), SSLConfig(),
- ProxyInfo());
+ job_controller_->OnStreamReady(job_factory_.alternative_job(), SSLConfig());
}
TEST_F(HttpStreamFactoryImplJobControllerTest, DoNotResumeMainJobBeforeWait) {
@@ -822,6 +814,7 @@ TEST_F(HttpStreamFactoryImplJobControllerTest,
}
TEST_F(HttpStreamFactoryImplJobControllerTest, DelayedTCP) {
+ base::ScopedMockTimeMessageLoopTaskRunner test_task_runner;
HangingResolver* resolver = new HangingResolver();
session_deps_.host_resolver.reset(resolver);
@@ -851,16 +844,147 @@ TEST_F(HttpStreamFactoryImplJobControllerTest, DelayedTCP) {
DEFAULT_PRIORITY, SSLConfig(), SSLConfig()));
EXPECT_TRUE(job_controller_->main_job());
EXPECT_TRUE(job_controller_->alternative_job());
+ EXPECT_TRUE(job_controller_->main_job()->is_waiting());
// The alternative job stalls as host resolution hangs when creating the QUIC
// request and controller should resume the main job after delay.
- // Verify the waiting time for delayed main job.
- EXPECT_CALL(*job_factory_.main_job(), Resume())
- .WillOnce(Invoke(testing::CreateFunctor(
- &JobControllerPeer::VerifyWaitingTimeForMainJob, job_controller_,
- base::TimeDelta::FromMicroseconds(15))));
+ EXPECT_TRUE(test_task_runner->HasPendingTask());
+ EXPECT_EQ(1u, test_task_runner->GetPendingTaskCount());
+ EXPECT_CALL(*job_factory_.main_job(), Resume()).Times(1);
+ test_task_runner->FastForwardBy(base::TimeDelta::FromMicroseconds(15));
+ EXPECT_FALSE(test_task_runner->HasPendingTask());
- base::RunLoop().RunUntilIdle();
+ EXPECT_TRUE(job_controller_->main_job());
+ EXPECT_TRUE(job_controller_->alternative_job());
+
+ // |alternative_job| fails but should not report status to Request.
+ EXPECT_CALL(request_delegate_, OnStreamFailed(_, _)).Times(0);
+
+ EXPECT_FALSE(JobControllerPeer::main_job_is_blocked(job_controller_));
+ // OnStreamFailed will post a task to resume the main job immediately but
+ // won't call Resume() on the main job since it's been resumed already.
+ EXPECT_CALL(*job_factory_.main_job(), Resume()).Times(0);
+ job_controller_->OnStreamFailed(job_factory_.alternative_job(),
+ ERR_NETWORK_CHANGED, SSLConfig());
+ EXPECT_EQ(1u, test_task_runner->GetPendingTaskCount());
+ test_task_runner->RunUntilIdle();
+}
+
+// Test that main job is blocked for kMaxDelayTimeForMainJob(3s) if
+// http_server_properties cached an inappropriate large srtt for the server,
+// which would potentially delay the main job for a extremely long time in
+// delayed tcp case.
+TEST_F(HttpStreamFactoryImplJobControllerTest, DelayedTCPWithLargeSrtt) {
+ // Overrides the main thread's message loop with a mock tick clock so that we
+ // could verify the main job is resumed with appropriate delay.
+ base::ScopedMockTimeMessageLoopTaskRunner test_task_runner;
+ // The max delay time should be in sync with .cc file.
+ base::TimeDelta kMaxDelayTimeForMainJob = base::TimeDelta::FromSeconds(3);
+ HangingResolver* resolver = new HangingResolver();
+ session_deps_.host_resolver.reset(resolver);
+
+ HttpRequestInfo request_info;
+ request_info.method = "GET";
+ request_info.url = GURL("https://www.google.com");
+
+ Initialize(false);
+
+ // Enable delayed TCP and set a extremely large time delay for waiting job.
+ QuicStreamFactory* quic_stream_factory = session_->quic_stream_factory();
+ test::QuicStreamFactoryPeer::SetDelayTcpRace(quic_stream_factory, true);
+ quic_stream_factory->set_require_confirmation(false);
+ ServerNetworkStats stats1;
+ stats1.srtt = base::TimeDelta::FromSeconds(100);
+ session_->http_server_properties()->SetServerNetworkStats(
+ url::SchemeHostPort(GURL("https://www.google.com")), stats1);
+
+ // Set a SPDY alternative service for the server.
+ url::SchemeHostPort server(request_info.url);
+ AlternativeService alternative_service(kProtoQUIC, server.host(), 443);
+ SetAlternativeService(request_info, alternative_service);
+
+ request_.reset(
+ job_controller_->Start(request_info, &request_delegate_, nullptr,
+ NetLogWithSource(), HttpStreamRequest::HTTP_STREAM,
+ DEFAULT_PRIORITY, SSLConfig(), SSLConfig()));
+ EXPECT_TRUE(job_controller_->main_job());
+ EXPECT_TRUE(job_controller_->alternative_job());
+ EXPECT_TRUE(job_controller_->main_job()->is_waiting());
+
+ // The alternative job stalls as host resolution hangs when creating the QUIC
+ // request and controller should resume the main job after delay.
+ EXPECT_TRUE(test_task_runner->HasPendingTask());
+ EXPECT_EQ(1u, test_task_runner->GetPendingTaskCount());
+
+ EXPECT_CALL(*job_factory_.main_job(), Resume()).Times(1);
+ // Move forward the task runner with kMaxDelayTimeForMainJob and verify the
+ // main job is resumed.
+ test_task_runner->FastForwardBy(kMaxDelayTimeForMainJob);
+ EXPECT_FALSE(test_task_runner->HasPendingTask());
+}
+
+TEST_F(HttpStreamFactoryImplJobControllerTest,
+ ResumeMainJobImmediatelyOnStreamFailed) {
+ // Overrides the main thread's message loop with a mock tick clock so that we
+ // could verify the main job is resumed with appropriate delay.
+ base::ScopedMockTimeMessageLoopTaskRunner test_task_runner;
+
+ HangingResolver* resolver = new HangingResolver();
+ session_deps_.host_resolver.reset(resolver);
+
+ HttpRequestInfo request_info;
+ request_info.method = "GET";
+ request_info.url = GURL("https://www.google.com");
+
+ Initialize(false);
+
+ // Enable delayed TCP and set time delay for waiting job.
+ QuicStreamFactory* quic_stream_factory = session_->quic_stream_factory();
+ test::QuicStreamFactoryPeer::SetDelayTcpRace(quic_stream_factory, true);
+ quic_stream_factory->set_require_confirmation(false);
+ ServerNetworkStats stats1;
+ stats1.srtt = base::TimeDelta::FromMicroseconds(10);
+ session_->http_server_properties()->SetServerNetworkStats(
+ url::SchemeHostPort(GURL("https://www.google.com")), stats1);
+
+ // Set a SPDY alternative service for the server.
+ url::SchemeHostPort server(request_info.url);
+ AlternativeService alternative_service(kProtoQUIC, server.host(), 443);
+ SetAlternativeService(request_info, alternative_service);
+
+ // The alternative job stalls as host resolution hangs when creating the QUIC
+ // request and controller should resume the main job with delay.
+ // OnStreamFailed should resume the main job immediately.
+ request_.reset(
+ job_controller_->Start(request_info, &request_delegate_, nullptr,
+ NetLogWithSource(), HttpStreamRequest::HTTP_STREAM,
+ DEFAULT_PRIORITY, SSLConfig(), SSLConfig()));
+ EXPECT_TRUE(job_controller_->main_job());
+ EXPECT_TRUE(job_controller_->alternative_job());
+ EXPECT_TRUE(job_controller_->main_job()->is_waiting());
+
+ EXPECT_TRUE(test_task_runner->HasPendingTask());
+ EXPECT_EQ(1u, test_task_runner->GetPendingTaskCount());
+
+ // |alternative_job| fails but should not report status to Request.
+ EXPECT_CALL(request_delegate_, OnStreamFailed(_, _)).Times(0);
+ job_controller_->OnStreamFailed(job_factory_.alternative_job(),
+ ERR_NETWORK_CHANGED, SSLConfig());
+ EXPECT_EQ(2u, test_task_runner->GetPendingTaskCount());
+
+ // Verify the main job will be resumed immediately.
+ EXPECT_CALL(*job_factory_.main_job(), Resume()).Times(1);
+ // Execute tasks that have no remaining delay. Tasks with nonzero delay will
+ // remain queued.
+ test_task_runner->RunUntilIdle();
+
+ // Verify there is another task to resume main job with delay but should
+ // not call Resume() on the main job as main job has been resumed.
+ EXPECT_TRUE(test_task_runner->HasPendingTask());
+ EXPECT_EQ(1u, test_task_runner->GetPendingTaskCount());
+ EXPECT_CALL(*job_factory_.main_job(), Resume()).Times(0);
+ test_task_runner->FastForwardBy(base::TimeDelta::FromMicroseconds(15));
+ EXPECT_FALSE(test_task_runner->HasPendingTask());
}
// Verifies that the alternative proxy server job is not created if the URL
@@ -1055,8 +1179,7 @@ TEST_F(HttpStreamFactoryImplJobControllerTest,
EXPECT_CALL(request_delegate_, OnStreamReady(_, _, http_stream))
.WillOnce(Invoke(DeleteHttpStreamPointer));
- job_controller_->OnStreamReady(job_factory_.main_job(), SSLConfig(),
- ProxyInfo());
+ job_controller_->OnStreamReady(job_factory_.main_job(), SSLConfig());
// JobController shouldn't report the status of alternative server job as
// request is already successfully served.
diff --git a/chromium/net/http/http_stream_factory_impl_request.h b/chromium/net/http/http_stream_factory_impl_request.h
index 16f1e719036..91cb0d7a0c1 100644
--- a/chromium/net/http/http_stream_factory_impl_request.h
+++ b/chromium/net/http/http_stream_factory_impl_request.h
@@ -20,9 +20,7 @@
namespace net {
class BidirectionalStreamImpl;
-class ClientSocketHandle;
class HttpStream;
-class SpdySession;
class HttpStreamFactoryImpl::Request : public HttpStreamRequest {
public:
diff --git a/chromium/net/http/http_stream_factory_impl_request_unittest.cc b/chromium/net/http/http_stream_factory_impl_request_unittest.cc
index 6de0bab70b2..f8b1c393314 100644
--- a/chromium/net/http/http_stream_factory_impl_request_unittest.cc
+++ b/chromium/net/http/http_stream_factory_impl_request_unittest.cc
@@ -6,6 +6,7 @@
#include <memory>
+#include "base/memory/ptr_util.h"
#include "base/run_loop.h"
#include "net/http/http_stream_factory_impl.h"
#include "net/http/http_stream_factory_impl_job.h"
diff --git a/chromium/net/http/http_stream_factory_impl_unittest.cc b/chromium/net/http/http_stream_factory_impl_unittest.cc
index 9ea8df492aa..550c7074ff7 100644
--- a/chromium/net/http/http_stream_factory_impl_unittest.cc
+++ b/chromium/net/http/http_stream_factory_impl_unittest.cc
@@ -15,7 +15,9 @@
#include "base/macros.h"
#include "base/memory/ptr_util.h"
#include "base/run_loop.h"
+#include "base/test/histogram_tester.h"
#include "net/base/port_util.h"
+#include "net/base/privacy_mode.h"
#include "net/base/test_completion_callback.h"
#include "net/base/test_proxy_delegate.h"
#include "net/cert/ct_policy_enforcer.h"
@@ -35,14 +37,15 @@
#include "net/http/transport_security_state.h"
#include "net/log/net_log_with_source.h"
#include "net/proxy/proxy_info.h"
+#include "net/proxy/proxy_server.h"
#include "net/proxy/proxy_service.h"
-#include "net/quic/core/quic_http_utils.h"
+#include "net/quic/chromium/mock_crypto_client_stream_factory.h"
+#include "net/quic/chromium/quic_http_utils.h"
+#include "net/quic/chromium/quic_test_packet_maker.h"
#include "net/quic/core/quic_server_id.h"
#include "net/quic/test_tools/crypto_test_utils.h"
-#include "net/quic/test_tools/mock_crypto_client_stream_factory.h"
#include "net/quic/test_tools/mock_random.h"
#include "net/quic/test_tools/quic_stream_factory_peer.h"
-#include "net/quic/test_tools/quic_test_packet_maker.h"
#include "net/quic/test_tools/quic_test_utils.h"
#include "net/socket/client_socket_handle.h"
#include "net/socket/mock_client_socket_pool_manager.h"
@@ -386,6 +389,9 @@ class CapturePreconnectsSocketPool : public ParentPool {
return last_num_streams_;
}
+ // Resets |last_num_streams_| to its default value.
+ void reset_last_num_streams() { last_num_streams_ = -1; }
+
int RequestSocket(const std::string& group_name,
const void* socket_params,
RequestPriority priority,
@@ -1215,6 +1221,179 @@ TEST_F(HttpStreamFactoryTest, QuicDisablePreConnectIfZeroRtt) {
}
}
+// Verify that only one preconnect job succeeds to a proxy server that supports
+// request priorities.
+TEST_F(HttpStreamFactoryTest, OnlyOnePreconnectToProxyServer) {
+ for (bool set_http_server_properties : {false, true}) {
+ for (int num_streams = 1; num_streams < 3; ++num_streams) {
+ base::HistogramTester histogram_tester;
+ GURL url = GURL("http://www.google.com");
+ std::unique_ptr<ProxyService> proxy_service =
+ ProxyService::CreateFixedFromPacResult("HTTPS myproxy.org:443");
+
+ // Set up the proxy server as a server that supports request priorities.
+ HttpServerPropertiesImpl http_server_properties;
+ if (set_http_server_properties) {
+ url::SchemeHostPort spdy_server("https", "myproxy.org", 443);
+ http_server_properties.SetSupportsSpdy(spdy_server, true);
+ }
+
+ SpdySessionDependencies session_deps;
+ HttpNetworkSession::Params params =
+ SpdySessionDependencies::CreateSessionParams(&session_deps);
+ params.enable_quic = true;
+ params.proxy_service = proxy_service.get();
+ params.http_server_properties = &http_server_properties;
+ ASSERT_TRUE(params.restrict_to_one_preconnect_for_proxies);
+
+ std::unique_ptr<HttpNetworkSession> session(
+ new HttpNetworkSession(params));
+
+ HttpNetworkSessionPeer peer(session.get());
+ HostPortPair proxy_host("myproxy.org", 443);
+
+ for (int preconnect_request = 0; preconnect_request < 2;
+ ++preconnect_request) {
+ CapturePreconnectsHttpProxySocketPool* http_proxy_pool =
+ new CapturePreconnectsHttpProxySocketPool(
+ session_deps.host_resolver.get(),
+ session_deps.cert_verifier.get(),
+ session_deps.transport_security_state.get(),
+ session_deps.cert_transparency_verifier.get(),
+ session_deps.ct_policy_enforcer.get());
+ CapturePreconnectsSSLSocketPool* ssl_conn_pool =
+ new CapturePreconnectsSSLSocketPool(
+ session_deps.host_resolver.get(),
+ session_deps.cert_verifier.get(),
+ session_deps.transport_security_state.get(),
+ session_deps.cert_transparency_verifier.get(),
+ session_deps.ct_policy_enforcer.get());
+
+ std::unique_ptr<MockClientSocketPoolManager> mock_pool_manager(
+ new MockClientSocketPoolManager);
+ mock_pool_manager->SetSocketPoolForHTTPProxy(
+ proxy_host, base::WrapUnique(http_proxy_pool));
+ mock_pool_manager->SetSocketPoolForSSLWithProxy(
+ proxy_host, base::WrapUnique(ssl_conn_pool));
+ peer.SetClientSocketPoolManager(std::move(mock_pool_manager));
+
+ HttpRequestInfo request;
+ request.method = "GET";
+ request.url = url;
+ request.load_flags = 0;
+
+ if (preconnect_request == 0) {
+ // First preconnect job should succeed.
+ session->http_stream_factory()->PreconnectStreams(num_streams,
+ request);
+ EXPECT_EQ(-1, ssl_conn_pool->last_num_streams());
+ EXPECT_EQ(num_streams, http_proxy_pool->last_num_streams());
+ } else {
+ // Second preconnect job should not succeed.
+ session->http_stream_factory()->PreconnectStreams(num_streams,
+ request);
+ EXPECT_EQ(-1, ssl_conn_pool->last_num_streams());
+ if (set_http_server_properties) {
+ EXPECT_EQ(-1, http_proxy_pool->last_num_streams());
+ } else {
+ EXPECT_EQ(num_streams, http_proxy_pool->last_num_streams());
+ }
+ }
+ }
+ // Preconnects should be skipped only to proxy servers that support
+ // request priorities.
+ if (set_http_server_properties) {
+ histogram_tester.ExpectUniqueSample(
+ "Net.PreconnectSkippedToProxyServers", 1, 1);
+ } else {
+ histogram_tester.ExpectTotalCount("Net.PreconnectSkippedToProxyServers",
+ 0);
+ }
+ }
+ }
+}
+
+// Verify that preconnect to a HTTP2 proxy server with a privacy mode different
+// than that of the in-flight preconnect job succeeds.
+TEST_F(HttpStreamFactoryTest, ProxyServerPreconnectDifferentPrivacyModes) {
+ int num_streams = 1;
+ base::HistogramTester histogram_tester;
+ GURL url = GURL("http://www.google.com");
+ std::unique_ptr<ProxyService> proxy_service =
+ ProxyService::CreateFixedFromPacResult("HTTPS myproxy.org:443");
+
+ // Set up the proxy server as a server that supports request priorities.
+ HttpServerPropertiesImpl http_server_properties;
+
+ url::SchemeHostPort spdy_server("https", "myproxy.org", 443);
+ http_server_properties.SetSupportsSpdy(spdy_server, true);
+
+ SpdySessionDependencies session_deps;
+ HttpNetworkSession::Params params =
+ SpdySessionDependencies::CreateSessionParams(&session_deps);
+ params.enable_quic = true;
+ params.proxy_service = proxy_service.get();
+ params.http_server_properties = &http_server_properties;
+ ASSERT_TRUE(params.restrict_to_one_preconnect_for_proxies);
+
+ std::unique_ptr<HttpNetworkSession> session(new HttpNetworkSession(params));
+
+ HttpNetworkSessionPeer peer(session.get());
+ HostPortPair proxy_host("myproxy.org", 443);
+
+ CapturePreconnectsHttpProxySocketPool* http_proxy_pool =
+ new CapturePreconnectsHttpProxySocketPool(
+ session_deps.host_resolver.get(), session_deps.cert_verifier.get(),
+ session_deps.transport_security_state.get(),
+ session_deps.cert_transparency_verifier.get(),
+ session_deps.ct_policy_enforcer.get());
+ CapturePreconnectsSSLSocketPool* ssl_conn_pool =
+ new CapturePreconnectsSSLSocketPool(
+ session_deps.host_resolver.get(), session_deps.cert_verifier.get(),
+ session_deps.transport_security_state.get(),
+ session_deps.cert_transparency_verifier.get(),
+ session_deps.ct_policy_enforcer.get());
+
+ std::unique_ptr<MockClientSocketPoolManager> mock_pool_manager(
+ new MockClientSocketPoolManager);
+ mock_pool_manager->SetSocketPoolForHTTPProxy(
+ proxy_host, base::WrapUnique(http_proxy_pool));
+ mock_pool_manager->SetSocketPoolForSSLWithProxy(
+ proxy_host, base::WrapUnique(ssl_conn_pool));
+ peer.SetClientSocketPoolManager(std::move(mock_pool_manager));
+
+ HttpRequestInfo request_privacy_mode_disabled;
+ request_privacy_mode_disabled.method = "GET";
+ request_privacy_mode_disabled.url = url;
+ request_privacy_mode_disabled.load_flags = 0;
+
+ // First preconnect job should succeed.
+ session->http_stream_factory()->PreconnectStreams(
+ num_streams, request_privacy_mode_disabled);
+ EXPECT_EQ(-1, ssl_conn_pool->last_num_streams());
+ EXPECT_EQ(num_streams, http_proxy_pool->last_num_streams());
+ http_proxy_pool->reset_last_num_streams();
+
+ // Second preconnect job with same privacy mode should not succeed.
+ session->http_stream_factory()->PreconnectStreams(
+ num_streams + 1, request_privacy_mode_disabled);
+ EXPECT_EQ(-1, ssl_conn_pool->last_num_streams());
+ EXPECT_EQ(-1, http_proxy_pool->last_num_streams());
+
+ // Next request with a different privacy mode should succeed.
+ HttpRequestInfo request_privacy_mode_enabled;
+ request_privacy_mode_enabled.method = "GET";
+ request_privacy_mode_enabled.url = url;
+ request_privacy_mode_enabled.load_flags = 0;
+ request_privacy_mode_enabled.privacy_mode = PRIVACY_MODE_ENABLED;
+
+ // Request with a different privacy mode should succeed.
+ session->http_stream_factory()->PreconnectStreams(
+ num_streams, request_privacy_mode_enabled);
+ EXPECT_EQ(-1, ssl_conn_pool->last_num_streams());
+ EXPECT_EQ(num_streams, http_proxy_pool->last_num_streams());
+}
+
namespace {
TEST_F(HttpStreamFactoryTest, PrivacyModeDisablesChannelId) {
@@ -1509,6 +1688,87 @@ TEST_F(HttpStreamFactoryTest, RequestHttpStreamOverProxy) {
EXPECT_FALSE(waiter.used_proxy_info().is_direct());
}
+// Verifies that once a stream has been created to a proxy server (that supports
+// request priorities) the next preconnect job can again open new sockets.
+TEST_F(HttpStreamFactoryTest, RequestHttpStreamOverProxyWithPreconnects) {
+ SpdySessionDependencies session_deps(
+ ProxyService::CreateFixed("https://myproxy.org:443"));
+
+ // Set up the proxy server as a server that supports request priorities.
+ std::unique_ptr<HttpServerPropertiesImpl> http_server_properties(
+ new HttpServerPropertiesImpl());
+ url::SchemeHostPort spdy_server("https", "myproxy.org", 443);
+ http_server_properties->SetSupportsSpdy(spdy_server, true);
+ session_deps.http_server_properties = std::move(http_server_properties);
+
+ StaticSocketDataProvider socket_data;
+ socket_data.set_connect_data(MockConnect(ASYNC, OK));
+ session_deps.socket_factory->AddSocketDataProvider(&socket_data);
+
+ SSLSocketDataProvider ssl_data(ASYNC, OK);
+ session_deps.socket_factory->AddSSLSocketDataProvider(&ssl_data);
+
+ std::unique_ptr<HttpNetworkSession> session(
+ SpdySessionDependencies::SpdyCreateSession(&session_deps));
+
+ // Now preconnect a request. Only the first preconnect should succeed.
+ HttpRequestInfo request_info;
+ request_info.method = "GET";
+ request_info.url = GURL("http://www.google.com");
+ request_info.load_flags = 0;
+
+ base::HistogramTester histogram_tester;
+ const int num_preconnects = 5;
+
+ // First preconnect would be successful. The next |num_preconnects-1| would be
+ // skipped.
+ for (int preconnect_request = 1; preconnect_request <= num_preconnects;
+ ++preconnect_request) {
+ session->http_stream_factory()->PreconnectStreams(1, request_info);
+ base::RunLoop().RunUntilIdle();
+ while (GetSocketPoolGroupCount(session->GetSocketPoolForHTTPProxy(
+ HttpNetworkSession::NORMAL_SOCKET_POOL,
+ HostPortPair("myproxy.org", 443))) == 0) {
+ base::RunLoop().RunUntilIdle();
+ }
+ }
+
+ histogram_tester.ExpectUniqueSample("Net.PreconnectSkippedToProxyServers", 1,
+ num_preconnects - 1);
+
+ // Start a request. This should cause subsequent preconnect to proxy server to
+ // succeed.
+ SSLConfig ssl_config;
+ StreamRequestWaiter waiter;
+ std::unique_ptr<HttpStreamRequest> request(
+ session->http_stream_factory()->RequestStream(
+ request_info, DEFAULT_PRIORITY, ssl_config, ssl_config, &waiter,
+ NetLogWithSource()));
+ waiter.WaitForStream();
+ EXPECT_TRUE(waiter.stream_done());
+ ASSERT_TRUE(nullptr != waiter.stream());
+ EXPECT_TRUE(nullptr == waiter.websocket_stream());
+
+ EXPECT_EQ(1, GetSocketPoolGroupCount(session->GetSocketPoolForHTTPProxy(
+ HttpNetworkSession::NORMAL_SOCKET_POOL,
+ HostPortPair("myproxy.org", 443))));
+ EXPECT_FALSE(waiter.used_proxy_info().is_direct());
+
+ for (int preconnect_request = 1; preconnect_request <= num_preconnects;
+ ++preconnect_request) {
+ session->http_stream_factory()->PreconnectStreams(1, request_info);
+ base::RunLoop().RunUntilIdle();
+ EXPECT_EQ(1, GetSocketPoolGroupCount(session->GetSocketPoolForHTTPProxy(
+ HttpNetworkSession::NORMAL_SOCKET_POOL,
+ HostPortPair("myproxy.org", 443))));
+ }
+
+ // First preconnect would be successful since the stream to the proxy server
+ // has suceeded. The next |num_preconnects-1| would be skipped.
+ histogram_tester.ExpectUniqueSample("Net.PreconnectSkippedToProxyServers", 1,
+ 2 * (num_preconnects - 1));
+}
+
TEST_F(HttpStreamFactoryTest, RequestWebSocketBasicHandshakeStream) {
SpdySessionDependencies session_deps(ProxyService::CreateDirect());
@@ -1643,7 +1903,7 @@ TEST_F(HttpStreamFactoryTest, RequestWebSocketBasicHandshakeStreamOverProxy) {
EXPECT_FALSE(waiter.used_proxy_info().is_direct());
}
-TEST_F(HttpStreamFactoryTest, RequestSpdyHttpStream) {
+TEST_F(HttpStreamFactoryTest, RequestSpdyHttpStreamHttpsURL) {
SpdySessionDependencies session_deps(ProxyService::CreateDirect());
MockRead mock_read(SYNCHRONOUS, ERR_IO_PENDING);
@@ -1689,6 +1949,60 @@ TEST_F(HttpStreamFactoryTest, RequestSpdyHttpStream) {
EXPECT_TRUE(waiter.used_proxy_info().is_direct());
}
+TEST_F(HttpStreamFactoryTest, RequestSpdyHttpStreamHttpURL) {
+ url::SchemeHostPort scheme_host_port("http", "myproxy.org", 443);
+ auto session_deps = base::MakeUnique<SpdySessionDependencies>(
+ ProxyService::CreateFixedFromPacResult("HTTPS myproxy.org:443"));
+ std::unique_ptr<ProxyService> proxy_service =
+ ProxyService::CreateFixedFromPacResult("HTTPS myproxy.org:443");
+
+ MockRead mock_read(SYNCHRONOUS, ERR_IO_PENDING);
+ SequencedSocketData socket_data(&mock_read, 1, nullptr, 0);
+ socket_data.set_connect_data(MockConnect(ASYNC, OK));
+ session_deps->socket_factory->AddSocketDataProvider(&socket_data);
+
+ SSLSocketDataProvider ssl_socket_data(ASYNC, OK);
+ ssl_socket_data.next_proto = kProtoHTTP2;
+ session_deps->socket_factory->AddSSLSocketDataProvider(&ssl_socket_data);
+ session_deps->proxy_service = std::move(proxy_service);
+
+ std::unique_ptr<HttpNetworkSession> session(
+ SpdySessionDependencies::SpdyCreateSession(session_deps.get()));
+
+ HttpServerProperties* http_server_properties =
+ session->spdy_session_pool()->http_server_properties();
+ EXPECT_FALSE(http_server_properties->GetSupportsSpdy(scheme_host_port));
+
+ // Now request a stream.
+ HttpRequestInfo request_info;
+ request_info.method = "GET";
+ request_info.url = GURL("http://www.google.com");
+ request_info.load_flags = 0;
+
+ SSLConfig ssl_config;
+ StreamRequestWaiter waiter;
+ std::unique_ptr<HttpStreamRequest> request(
+ session->http_stream_factory()->RequestStream(
+ request_info, DEFAULT_PRIORITY, ssl_config, ssl_config, &waiter,
+ NetLogWithSource()));
+ waiter.WaitForStream();
+ EXPECT_TRUE(waiter.stream_done());
+ EXPECT_TRUE(nullptr == waiter.websocket_stream());
+ ASSERT_TRUE(nullptr != waiter.stream());
+
+ EXPECT_EQ(1, GetSpdySessionCount(session.get()));
+ EXPECT_EQ(0, GetSocketPoolGroupCount(session->GetTransportSocketPool(
+ HttpNetworkSession::NORMAL_SOCKET_POOL)));
+ EXPECT_EQ(0, GetSocketPoolGroupCount(session->GetSSLSocketPool(
+ HttpNetworkSession::NORMAL_SOCKET_POOL)));
+ EXPECT_EQ(0, GetSocketPoolGroupCount(session->GetTransportSocketPool(
+ HttpNetworkSession::WEBSOCKET_SOCKET_POOL)));
+ EXPECT_EQ(0, GetSocketPoolGroupCount(session->GetSSLSocketPool(
+ HttpNetworkSession::WEBSOCKET_SOCKET_POOL)));
+ EXPECT_FALSE(waiter.used_proxy_info().is_direct());
+ EXPECT_TRUE(http_server_properties->GetSupportsSpdy(scheme_host_port));
+}
+
TEST_F(HttpStreamFactoryTest, RequestBidirectionalStreamImpl) {
SpdySessionDependencies session_deps(ProxyService::CreateDirect());
@@ -1848,11 +2162,15 @@ TEST_P(HttpStreamFactoryBidirectionalQuicTest,
SpdyPriority priority =
ConvertRequestPriorityToQuicPriority(DEFAULT_PRIORITY);
size_t spdy_headers_frame_length;
+ QuicStreamOffset header_stream_offset = 0;
+ mock_quic_data.AddWrite(client_packet_maker().MakeSettingsPacket(
+ 1, SETTINGS_MAX_HEADER_LIST_SIZE, kDefaultMaxUncompressedHeaderSize, true,
+ &header_stream_offset));
mock_quic_data.AddWrite(client_packet_maker().MakeRequestHeadersPacket(
- 1, test::kClientDataStreamId1, /*should_include_version=*/true,
+ 2, test::kClientDataStreamId1, /*should_include_version=*/true,
/*fin=*/true, priority,
client_packet_maker().GetRequestHeaders("GET", "https", "/"),
- &spdy_headers_frame_length));
+ &spdy_headers_frame_length, &header_stream_offset));
size_t spdy_response_headers_frame_length;
mock_quic_data.AddRead(server_packet_maker().MakeResponseHeadersPacket(
1, test::kClientDataStreamId1, /*should_include_version=*/false,
@@ -1971,11 +2289,15 @@ TEST_P(HttpStreamFactoryBidirectionalQuicTest,
SpdyPriority priority =
ConvertRequestPriorityToQuicPriority(DEFAULT_PRIORITY);
size_t spdy_headers_frame_length;
+ QuicStreamOffset header_stream_offset = 0;
+ mock_quic_data.AddWrite(client_packet_maker().MakeSettingsPacket(
+ 1, SETTINGS_MAX_HEADER_LIST_SIZE, kDefaultMaxUncompressedHeaderSize, true,
+ &header_stream_offset));
mock_quic_data.AddWrite(client_packet_maker().MakeRequestHeadersPacket(
- 1, test::kClientDataStreamId1, /*should_include_version=*/true,
+ 2, test::kClientDataStreamId1, /*should_include_version=*/true,
/*fin=*/true, priority,
client_packet_maker().GetRequestHeaders("GET", "https", "/"),
- &spdy_headers_frame_length));
+ &spdy_headers_frame_length, &header_stream_offset));
size_t spdy_response_headers_frame_length;
mock_quic_data.AddRead(server_packet_maker().MakeResponseHeadersPacket(
1, test::kClientDataStreamId1, /*should_include_version=*/false,
diff --git a/chromium/net/http/http_stream_factory_test_util.cc b/chromium/net/http/http_stream_factory_test_util.cc
index 62d89c2c3f4..50d083073d7 100644
--- a/chromium/net/http/http_stream_factory_test_util.cc
+++ b/chromium/net/http/http_stream_factory_test_util.cc
@@ -33,7 +33,9 @@ MockHttpStreamFactoryImplJob::MockHttpStreamFactoryImplJob(
proxy_ssl_config,
destination,
origin_url,
- net_log) {}
+ net_log) {
+ DCHECK(!is_waiting());
+}
MockHttpStreamFactoryImplJob::MockHttpStreamFactoryImplJob(
HttpStreamFactoryImpl::Job::Delegate* delegate,
diff --git a/chromium/net/http/http_stream_parser.cc b/chromium/net/http/http_stream_parser.cc
index 91fea5376d9..7da5adaf13d 100644
--- a/chromium/net/http/http_stream_parser.cc
+++ b/chromium/net/http/http_stream_parser.cc
@@ -20,7 +20,6 @@
#include "net/http/http_request_headers.h"
#include "net/http/http_request_info.h"
#include "net/http/http_response_headers.h"
-#include "net/http/http_status_line_validator.h"
#include "net/http/http_util.h"
#include "net/log/net_log_event_type.h"
#include "net/socket/client_socket_handle.h"
@@ -32,23 +31,6 @@ namespace net {
namespace {
-enum HttpHeaderParserEvent {
- HEADER_PARSER_INVOKED = 0,
- // Obsolete: HEADER_HTTP_09_RESPONSE = 1,
- HEADER_ALLOWED_TRUNCATED_HEADERS = 2,
- HEADER_SKIPPED_WS_PREFIX = 3,
- HEADER_SKIPPED_NON_WS_PREFIX = 4,
- HEADER_HTTP_09_RESPONSE_OVER_HTTP = 5,
- HEADER_HTTP_09_RESPONSE_OVER_SSL = 6,
- HEADER_HTTP_09_ON_REUSED_SOCKET = 7,
- NUM_HEADER_EVENTS
-};
-
-void RecordHeaderParserEvent(HttpHeaderParserEvent header_event) {
- UMA_HISTOGRAM_ENUMERATION("Net.HttpHeaderParserEvent", header_event,
- NUM_HEADER_EVENTS);
-}
-
const uint64_t kMaxMergedHeaderAndBodySize = 1400;
const size_t kRequestBodyBufferSize = 1 << 14; // 16KB
@@ -860,7 +842,6 @@ int HttpStreamParser::HandleReadHeaderResult(int result) {
// The response looks to be a truncated set of HTTP headers.
io_state_ = STATE_READ_BODY_COMPLETE;
end_offset = read_buf_->offset();
- RecordHeaderParserEvent(HEADER_ALLOWED_TRUNCATED_HEADERS);
} else {
// The response is apparently using HTTP/0.9. Treat the entire response
// as the body.
@@ -977,54 +958,32 @@ int HttpStreamParser::ParseResponseHeaders(int end_offset) {
scoped_refptr<HttpResponseHeaders> headers;
DCHECK_EQ(0, read_buf_unused_offset_);
- RecordHeaderParserEvent(HEADER_PARSER_INVOKED);
-
- if (response_header_start_offset_ > 0) {
- bool has_non_whitespace_in_prefix = false;
- for (int i = 0; i < response_header_start_offset_; ++i) {
- if (!strchr(" \t\r\n", read_buf_->StartOfBuffer()[i])) {
- has_non_whitespace_in_prefix = true;
- break;
- }
- }
- if (has_non_whitespace_in_prefix) {
- RecordHeaderParserEvent(HEADER_SKIPPED_NON_WS_PREFIX);
- } else {
- RecordHeaderParserEvent(HEADER_SKIPPED_WS_PREFIX);
- }
- }
-
if (response_header_start_offset_ >= 0) {
received_bytes_ += end_offset;
- std::string raw_headers =
- HttpUtil::AssembleRawHeaders(read_buf_->StartOfBuffer(), end_offset);
- ValidateStatusLine(
- std::string(read_buf_->StartOfBuffer(), raw_headers.find('\0')));
- headers = new HttpResponseHeaders(raw_headers);
+ headers = new HttpResponseHeaders(
+ HttpUtil::AssembleRawHeaders(read_buf_->StartOfBuffer(), end_offset));
} else {
// Enough data was read -- there is no status line, so this is HTTP/0.9, or
// the server is broken / doesn't speak HTTP.
// If the port is not the default for the scheme, assume it's not a real
// HTTP/0.9 response, and fail the request.
- // TODO(crbug.com/624462): Further restrict the cases in which we allow
- // HTTP/0.9.
- std::string scheme(request_->url.scheme());
+ base::StringPiece scheme = request_->url.scheme_piece();
if (!http_09_on_non_default_ports_enabled_ &&
- url::DefaultPortForScheme(scheme.c_str(), scheme.length()) !=
+ url::DefaultPortForScheme(scheme.data(), scheme.length()) !=
request_->url.EffectiveIntPort()) {
- return ERR_INVALID_HTTP_RESPONSE;
+ // Allow Shoutcast responses over HTTP, as it's somewhat common and relies
+ // on HTTP/0.9 on weird ports to work.
+ // See
+ // https://groups.google.com/a/chromium.org/forum/#!topic/blink-dev/qS63pYso4P0
+ if (read_buf_->offset() < 3 || scheme != "http" ||
+ !base::LowerCaseEqualsASCII(
+ base::StringPiece(read_buf_->StartOfBuffer(), 3), "icy")) {
+ return ERR_INVALID_HTTP_RESPONSE;
+ }
}
headers = new HttpResponseHeaders(std::string("HTTP/0.9 200 OK"));
-
- if (request_->url.SchemeIsCryptographic()) {
- RecordHeaderParserEvent(HEADER_HTTP_09_RESPONSE_OVER_SSL);
- } else {
- RecordHeaderParserEvent(HEADER_HTTP_09_RESPONSE_OVER_HTTP);
- }
- if (connection_->is_reused())
- RecordHeaderParserEvent(HEADER_HTTP_09_ON_REUSED_SOCKET);
}
// Check for multiple Content-Length headers when the response is not
@@ -1222,13 +1181,6 @@ bool HttpStreamParser::ShouldMergeRequestHeadersAndBody(
return false;
}
-void HttpStreamParser::ValidateStatusLine(const std::string& status_line) {
- HttpStatusLineValidator::StatusLineStatus status =
- HttpStatusLineValidator::ValidateStatusLine(status_line);
- UMA_HISTOGRAM_ENUMERATION("Net.HttpStatusLineStatus", status,
- HttpStatusLineValidator::STATUS_LINE_MAX);
-}
-
bool HttpStreamParser::SendRequestBuffersEmpty() {
return request_headers_ == nullptr && request_body_send_buf_ == nullptr &&
request_body_read_buf_ == nullptr;
diff --git a/chromium/net/http/http_stream_parser.h b/chromium/net/http/http_stream_parser.h
index 2791f3291bd..6a0248202c2 100644
--- a/chromium/net/http/http_stream_parser.h
+++ b/chromium/net/http/http_stream_parser.h
@@ -32,7 +32,6 @@ struct HttpRequestInfo;
class HttpRequestHeaders;
class HttpResponseInfo;
class IOBuffer;
-class IOBufferWithSize;
class SSLCertRequestInfo;
class SSLInfo;
class UploadDataStream;
@@ -195,9 +194,6 @@ class NET_EXPORT_PRIVATE HttpStreamParser {
// Examine the parsed headers to try to determine the response body size.
void CalculateResponseBodySize();
- // Uploads statistics about status line compliance with RFC 7230.
- void ValidateStatusLine(const std::string& status_line);
-
// Check if buffers used to send the request are empty.
bool SendRequestBuffersEmpty();
diff --git a/chromium/net/http/http_stream_parser_unittest.cc b/chromium/net/http/http_stream_parser_unittest.cc
index 030adffdd5d..e9d9cde27f3 100644
--- a/chromium/net/http/http_stream_parser_unittest.cc
+++ b/chromium/net/http/http_stream_parser_unittest.cc
@@ -19,7 +19,6 @@
#include "base/memory/ref_counted.h"
#include "base/run_loop.h"
#include "base/strings/string_piece.h"
-#include "base/strings/stringprintf.h"
#include "base/threading/thread_task_runner_handle.h"
#include "net/base/chunked_upload_data_stream.h"
#include "net/base/elements_upload_data_stream.h"
@@ -1214,6 +1213,12 @@ class SimpleGetRunner {
reads_.push_back(MockRead(SYNCHRONOUS, sequence_number_++, data.data()));
}
+ // Simple overload - the above method requires using std::strings that outlive
+ // the function call. This version works with inlined C-style strings.
+ void AddRead(const char* data) {
+ reads_.push_back(MockRead(SYNCHRONOUS, sequence_number_++, data));
+ }
+
void SetupParserAndSendRequest() {
reads_.push_back(MockRead(SYNCHRONOUS, 0, sequence_number_++)); // EOF
@@ -1282,50 +1287,55 @@ TEST(HttpStreamParser, Http09PortTests) {
const char* url;
bool http_09_on_non_default_ports_enabled;
- // Expected result when trying to read headers.
- Error expected_header_error;
+ // Expected result when trying to read headers and response is an HTTP/0.9
+ // non-Shoutcast response.
+ Error expected_09_header_error;
+
+ // Expected result when trying to read headers for a shoutcast response.
+ Error expected_shoutcast_header_error;
};
const TestCase kTestCases[] = {
// Default ports should work for HTTP/0.9, regardless of whether the port
// is explicitly specified or not.
- {"http://foo.com/", false, OK},
- {"http://foo.com:80/", false, OK},
- {"https://foo.com/", false, OK},
- {"https://foo.com:443/", false, OK},
+ {"http://foo.com/", false, OK, OK},
+ {"http://foo.com:80/", false, OK, OK},
+ {"https://foo.com/", false, OK, OK},
+ {"https://foo.com:443/", false, OK, OK},
// Non-standard ports should not support HTTP/0.9, by default.
- {"http://foo.com:8080/", false, ERR_INVALID_HTTP_RESPONSE},
- {"https://foo.com:8080/", false, ERR_INVALID_HTTP_RESPONSE},
- {"http://foo.com:443/", false, ERR_INVALID_HTTP_RESPONSE},
- {"https://foo.com:80/", false, ERR_INVALID_HTTP_RESPONSE},
+ {"http://foo.com:8080/", false, ERR_INVALID_HTTP_RESPONSE, OK},
+ {"https://foo.com:8080/", false, ERR_INVALID_HTTP_RESPONSE,
+ ERR_INVALID_HTTP_RESPONSE},
+ {"http://foo.com:443/", false, ERR_INVALID_HTTP_RESPONSE, OK},
+ {"https://foo.com:80/", false, ERR_INVALID_HTTP_RESPONSE,
+ ERR_INVALID_HTTP_RESPONSE},
// Allowing non-default ports should not break the default ones.
- {"http://foo.com/", true, OK},
- {"http://foo.com:80/", true, OK},
- {"https://foo.com/", true, OK},
- {"https://foo.com:443/", true, OK},
+ {"http://foo.com/", true, OK, OK},
+ {"http://foo.com:80/", true, OK, OK},
+ {"https://foo.com/", true, OK, OK},
+ {"https://foo.com:443/", true, OK, OK},
// Check that non-default ports works.
- {"http://foo.com:8080/", true, OK},
- {"https://foo.com:8080/", true, OK},
- {"http://foo.com:443/", true, OK},
- {"https://foo.com:80/", true, OK},
+ {"http://foo.com:8080/", true, OK, OK},
+ {"https://foo.com:8080/", true, OK, OK},
+ {"http://foo.com:443/", true, OK, OK},
+ {"https://foo.com:80/", true, OK, OK},
};
- std::string response = "hello\r\nworld\r\n";
- int response_size = response.size();
+ const std::string kResponse = "hello\r\nworld\r\n";
for (const auto& test_case : kTestCases) {
SimpleGetRunner get_runner;
get_runner.set_url(GURL(test_case.url));
get_runner.set_http_09_on_non_default_ports_enabled(
test_case.http_09_on_non_default_ports_enabled);
- get_runner.AddRead(response);
+ get_runner.AddRead(kResponse);
get_runner.SetupParserAndSendRequest();
- get_runner.ReadHeadersExpectingError(test_case.expected_header_error);
- if (test_case.expected_header_error != OK)
+ get_runner.ReadHeadersExpectingError(test_case.expected_09_header_error);
+ if (test_case.expected_09_header_error != OK)
continue;
ASSERT_TRUE(get_runner.response_info()->headers);
@@ -1333,12 +1343,74 @@ TEST(HttpStreamParser, Http09PortTests) {
get_runner.response_info()->headers->GetStatusLine());
EXPECT_EQ(0, get_runner.parser()->received_bytes());
- int read_lengths[] = {response_size, 0};
- get_runner.ReadBody(response_size, read_lengths);
- EXPECT_EQ(response_size, get_runner.parser()->received_bytes());
+ int read_lengths[] = {kResponse.size(), 0};
+ get_runner.ReadBody(kResponse.size(), read_lengths);
+ EXPECT_EQ(kResponse.size(),
+ static_cast<size_t>(get_runner.parser()->received_bytes()));
EXPECT_EQ(HttpResponseInfo::CONNECTION_INFO_HTTP0_9,
get_runner.response_info()->connection_info);
}
+
+ const std::string kShoutcastResponse = "ICY 200 blah\r\n\r\n";
+ for (const auto& test_case : kTestCases) {
+ SimpleGetRunner get_runner;
+ get_runner.set_url(GURL(test_case.url));
+ get_runner.set_http_09_on_non_default_ports_enabled(
+ test_case.http_09_on_non_default_ports_enabled);
+ get_runner.AddRead(kShoutcastResponse);
+ get_runner.SetupParserAndSendRequest();
+
+ get_runner.ReadHeadersExpectingError(
+ test_case.expected_shoutcast_header_error);
+ if (test_case.expected_shoutcast_header_error != OK)
+ continue;
+
+ ASSERT_TRUE(get_runner.response_info()->headers);
+ EXPECT_EQ("HTTP/0.9 200 OK",
+ get_runner.response_info()->headers->GetStatusLine());
+
+ EXPECT_EQ(0, get_runner.parser()->received_bytes());
+ int read_lengths[] = {kShoutcastResponse.size(), 0};
+ get_runner.ReadBody(kShoutcastResponse.size(), read_lengths);
+ EXPECT_EQ(kShoutcastResponse.size(),
+ static_cast<size_t>(get_runner.parser()->received_bytes()));
+ EXPECT_EQ(HttpResponseInfo::CONNECTION_INFO_HTTP0_9,
+ get_runner.response_info()->connection_info);
+ }
+}
+
+// Make sure that Shoutcast is recognized when receiving one byte at a time.
+TEST(HttpStreamParser, ShoutcastSingleByteReads) {
+ SimpleGetRunner get_runner;
+ get_runner.set_url(GURL("http://foo.com:8080/"));
+ get_runner.set_http_09_on_non_default_ports_enabled(false);
+ get_runner.AddRead("i");
+ get_runner.AddRead("c");
+ get_runner.AddRead("Y");
+ // Needed because HttpStreamParser::Read returns ERR_CONNECTION_CLOSED on
+ // small response headers, which HttpNetworkTransaction replaces with net::OK.
+ // TODO(mmenke): Can we just change that behavior?
+ get_runner.AddRead(" Extra stuff");
+ get_runner.SetupParserAndSendRequest();
+
+ get_runner.ReadHeadersExpectingError(OK);
+ EXPECT_EQ("HTTP/0.9 200 OK",
+ get_runner.response_info()->headers->GetStatusLine());
+}
+
+// Make sure that Shoutcast is recognized when receiving any string starting
+// with "ICY", regardless of capitalization, and without a space following it
+// (The latter behavior is just to match HTTP detection).
+TEST(HttpStreamParser, ShoutcastWeirdHeader) {
+ SimpleGetRunner get_runner;
+ get_runner.set_url(GURL("http://foo.com:8080/"));
+ get_runner.set_http_09_on_non_default_ports_enabled(false);
+ get_runner.AddRead("iCyCreamSundae");
+ get_runner.SetupParserAndSendRequest();
+
+ get_runner.ReadHeadersExpectingError(OK);
+ EXPECT_EQ("HTTP/0.9 200 OK",
+ get_runner.response_info()->headers->GetStatusLine());
}
// Make sure that HTTP/0.9 isn't allowed in the truncated header case on a weird
diff --git a/chromium/net/http/http_transaction_test_util.cc b/chromium/net/http/http_transaction_test_util.cc
index 556033a0580..a5b57461df5 100644
--- a/chromium/net/http/http_transaction_test_util.cc
+++ b/chromium/net/http/http_transaction_test_util.cc
@@ -11,6 +11,7 @@
#include "base/bind.h"
#include "base/location.h"
#include "base/message_loop/message_loop.h"
+#include "base/run_loop.h"
#include "base/single_thread_task_runner.h"
#include "base/strings/stringprintf.h"
#include "base/threading/thread_task_runner_handle.h"
@@ -568,8 +569,10 @@ int ReadTransaction(HttpTransaction* trans, std::string* result) {
do {
scoped_refptr<IOBuffer> buf(new IOBuffer(256));
rv = trans->Read(buf.get(), 256, callback.callback());
- if (rv == ERR_IO_PENDING)
+ if (rv == ERR_IO_PENDING) {
rv = callback.WaitForResult();
+ base::RunLoop().RunUntilIdle();
+ }
if (rv > 0)
content.append(buf->data(), rv);
diff --git a/chromium/net/http/http_transaction_test_util.h b/chromium/net/http/http_transaction_test_util.h
index 718fe2727bc..e936ac9de01 100644
--- a/chromium/net/http/http_transaction_test_util.h
+++ b/chromium/net/http/http_transaction_test_util.h
@@ -2,8 +2,8 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#ifndef NET_HTTP_HTTP_TRANSACTION_UNITTEST_H_
-#define NET_HTTP_HTTP_TRANSACTION_UNITTEST_H_
+#ifndef NET_HTTP_HTTP_TRANSACTION_TEST_UTIL_H_
+#define NET_HTTP_HTTP_TRANSACTION_TEST_UTIL_H_
#include "net/http/http_transaction.h"
@@ -355,4 +355,4 @@ int ReadTransaction(HttpTransaction* trans, std::string* result);
} // namespace net
-#endif // NET_HTTP_HTTP_TRANSACTION_UNITTEST_H_
+#endif // NET_HTTP_HTTP_TRANSACTION_TEST_UTIL_H_
diff --git a/chromium/net/http/http_util.cc b/chromium/net/http/http_util.cc
index 99b7192c838..62bed8c449c 100644
--- a/chromium/net/http/http_util.cc
+++ b/chromium/net/http/http_util.cc
@@ -165,34 +165,6 @@ void HttpUtil::ParseContentType(const std::string& content_type_str,
}
// static
-// Parse the Range header according to RFC 2616 14.35.1
-// ranges-specifier = byte-ranges-specifier
-// byte-ranges-specifier = bytes-unit "=" byte-range-set
-// byte-range-set = 1#( byte-range-spec | suffix-byte-range-spec )
-// byte-range-spec = first-byte-pos "-" [last-byte-pos]
-// first-byte-pos = 1*DIGIT
-// last-byte-pos = 1*DIGIT
-bool HttpUtil::ParseRanges(const std::string& headers,
- std::vector<HttpByteRange>* ranges) {
- std::string ranges_specifier;
- HttpUtil::HeadersIterator it(headers.begin(), headers.end(), "\r\n");
-
- while (it.GetNext()) {
- // Look for "Range" header.
- if (!base::LowerCaseEqualsASCII(it.name(), "range"))
- continue;
- ranges_specifier = it.values();
- // We just care about the first "Range" header, so break here.
- break;
- }
-
- if (ranges_specifier.empty())
- return false;
-
- return ParseRangeHeader(ranges_specifier, ranges);
-}
-
-// static
bool HttpUtil::ParseRangeHeader(const std::string& ranges_specifier,
std::vector<HttpByteRange>* ranges) {
size_t equal_char_offset = ranges_specifier.find('=');
@@ -209,8 +181,9 @@ bool HttpUtil::ParseRangeHeader(const std::string& ranges_specifier,
TrimLWS(&bytes_unit_begin, &bytes_unit_end);
// "bytes" unit identifier is not found.
if (!base::LowerCaseEqualsASCII(
- base::StringPiece(bytes_unit_begin, bytes_unit_end), "bytes"))
+ base::StringPiece(bytes_unit_begin, bytes_unit_end), "bytes")) {
return false;
+ }
ValuesIterator byte_range_set_iterator(byte_range_set_begin,
byte_range_set_end, ',');
@@ -265,6 +238,58 @@ bool HttpUtil::ParseRangeHeader(const std::string& ranges_specifier,
}
// static
+// From RFC 2616 14.16:
+// content-range-spec =
+// bytes-unit SP byte-range-resp-spec "/" ( instance-length | "*" )
+// byte-range-resp-spec = (first-byte-pos "-" last-byte-pos) | "*"
+// instance-length = 1*DIGIT
+// bytes-unit = "bytes"
+bool HttpUtil::ParseContentRangeHeaderFor206(
+ base::StringPiece content_range_spec,
+ int64_t* first_byte_position,
+ int64_t* last_byte_position,
+ int64_t* instance_length) {
+ *first_byte_position = *last_byte_position = *instance_length = -1;
+ content_range_spec = TrimLWS(content_range_spec);
+
+ size_t space_position = content_range_spec.find(' ');
+ if (space_position == base::StringPiece::npos)
+ return false;
+
+ // Invalid header if it doesn't contain "bytes-unit".
+ if (!base::LowerCaseEqualsASCII(
+ TrimLWS(content_range_spec.substr(0, space_position)), "bytes")) {
+ return false;
+ }
+
+ size_t minus_position = content_range_spec.find('-', space_position + 1);
+ if (minus_position == base::StringPiece::npos)
+ return false;
+ size_t slash_position = content_range_spec.find('/', minus_position + 1);
+ if (slash_position == base::StringPiece::npos)
+ return false;
+
+ if (base::StringToInt64(
+ TrimLWS(content_range_spec.substr(
+ space_position + 1, minus_position - (space_position + 1))),
+ first_byte_position) &&
+ *first_byte_position >= 0 &&
+ base::StringToInt64(
+ TrimLWS(content_range_spec.substr(
+ minus_position + 1, slash_position - (minus_position + 1))),
+ last_byte_position) &&
+ *last_byte_position >= *first_byte_position &&
+ base::StringToInt64(
+ TrimLWS(content_range_spec.substr(slash_position + 1)),
+ instance_length) &&
+ *instance_length > *last_byte_position) {
+ return true;
+ }
+ *first_byte_position = *last_byte_position = *instance_length = -1;
+ return false;
+}
+
+// static
bool HttpUtil::ParseRetryAfterHeader(const std::string& retry_after_string,
base::Time now,
base::TimeDelta* retry_after) {
@@ -287,30 +312,8 @@ bool HttpUtil::ParseRetryAfterHeader(const std::string& retry_after_string,
return true;
}
-// static
-bool HttpUtil::HasHeader(const std::string& headers, const char* name) {
- size_t name_len = strlen(name);
- std::string::const_iterator it =
- std::search(headers.begin(),
- headers.end(),
- name,
- name + name_len,
- base::CaseInsensitiveCompareASCII<char>());
- if (it == headers.end())
- return false;
-
- // ensure match is prefixed by newline
- if (it != headers.begin() && it[-1] != '\n')
- return false;
-
- // ensure match is suffixed by colon
- if (it + name_len >= headers.end() || it[name_len] != ':')
- return false;
-
- return true;
-}
-
namespace {
+
// A header string containing any of the following fields will cause
// an error. The list comes from the XMLHttpRequest standard.
// http://www.w3.org/TR/XMLHttpRequest/#the-setrequestheader-method
@@ -337,7 +340,8 @@ const char* const kForbiddenHeaderFields[] = {
"user-agent",
"via",
};
-} // anonymous namespace
+
+} // namespace
// static
bool HttpUtil::IsSafeHeader(const std::string& name) {
@@ -370,32 +374,6 @@ bool HttpUtil::IsValidHeaderValue(const base::StringPiece& value) {
}
// static
-std::string HttpUtil::StripHeaders(const std::string& headers,
- const char* const headers_to_remove[],
- size_t headers_to_remove_len) {
- std::string stripped_headers;
- HttpUtil::HeadersIterator it(headers.begin(), headers.end(), "\r\n");
-
- while (it.GetNext()) {
- bool should_remove = false;
- for (size_t i = 0; i < headers_to_remove_len; ++i) {
- if (base::LowerCaseEqualsASCII(
- base::StringPiece(it.name_begin(), it.name_end()),
- headers_to_remove[i])) {
- should_remove = true;
- break;
- }
- }
- if (!should_remove) {
- // Assume that name and values are on the same line.
- stripped_headers.append(it.name_begin(), it.values_end());
- stripped_headers.append("\r\n");
- }
- }
- return stripped_headers;
-}
-
-// static
bool HttpUtil::IsNonCoalescingHeader(std::string::const_iterator name_begin,
std::string::const_iterator name_end) {
// NOTE: "set-cookie2" headers do not support expires attributes, so we don't
@@ -426,7 +404,8 @@ bool HttpUtil::IsNonCoalescingHeader(std::string::const_iterator name_begin,
}
bool HttpUtil::IsLWS(char c) {
- return strchr(HTTP_LWS, c) != NULL;
+ const base::StringPiece kWhiteSpaceCharacters(HTTP_LWS);
+ return kWhiteSpaceCharacters.find(c) != base::StringPiece::npos;
}
// static
@@ -781,16 +760,6 @@ std::string HttpUtil::GenerateAcceptLanguageHeader(
return lang_list_with_q;
}
-void HttpUtil::AppendHeaderIfMissing(const char* header_name,
- const std::string& header_value,
- std::string* headers) {
- if (header_value.empty())
- return;
- if (HttpUtil::HasHeader(*headers, header_name))
- return;
- *headers += std::string(header_name) + ": " + header_value + "\r\n";
-}
-
bool HttpUtil::HasStrongValidators(HttpVersion version,
const std::string& etag_header,
const std::string& last_modified_header,
diff --git a/chromium/net/http/http_util.h b/chromium/net/http/http_util.h
index 8658b578837..267b9640094 100644
--- a/chromium/net/http/http_util.h
+++ b/chromium/net/http/http_util.h
@@ -6,6 +6,7 @@
#define NET_HTTP_HTTP_UTIL_H_
#include <stddef.h>
+#include <stdint.h>
#include <string>
#include <vector>
@@ -45,20 +46,25 @@ class NET_EXPORT HttpUtil {
bool* had_charset,
std::string* boundary);
- // Scans the headers and look for the first "Range" header in |headers|,
- // if "Range" exists and the first one of it is well formatted then returns
- // true, |ranges| will contain a list of valid ranges. If return
- // value is false then values in |ranges| should not be used. The format of
- // "Range" header is defined in RFC 7233 Section 2.1.
+ // Parses the value of a "Range" header as defined in RFC 7233 Section 2.1.
// https://tools.ietf.org/html/rfc7233#section-2.1
- static bool ParseRanges(const std::string& headers,
- std::vector<HttpByteRange>* ranges);
-
- // Same thing as ParseRanges except the Range header is known and its value
- // is directly passed in, rather than requiring searching through a string.
+ // Returns false on failure.
static bool ParseRangeHeader(const std::string& range_specifier,
std::vector<HttpByteRange>* ranges);
+ // Extracts the values in a Content-Range header and returns true if all three
+ // values are present and valid for a 206 response; otherwise returns false.
+ // The following values will be outputted:
+ // |*first_byte_position| = inclusive position of the first byte of the range
+ // |*last_byte_position| = inclusive position of the last byte of the range
+ // |*instance_length| = size in bytes of the object requested
+ // If this method returns false, then all of the outputs will be -1.
+ static bool ParseContentRangeHeaderFor206(
+ base::StringPiece content_range_spec,
+ int64_t* first_byte_position,
+ int64_t* last_byte_position,
+ int64_t* instance_length);
+
// Parses a Retry-After header that is either an absolute date/time or a
// number of seconds in the future. Interprets absolute times as relative to
// |now|. If |retry_after_string| is successfully parsed and indicates a time
@@ -68,11 +74,6 @@ class NET_EXPORT HttpUtil {
base::Time now,
base::TimeDelta* retry_after);
- // Scans the '\r\n'-delimited headers for the given header name. Returns
- // true if a match is found. Input is assumed to be well-formed.
- // TODO(darin): kill this
- static bool HasHeader(const std::string& headers, const char* name);
-
// Returns true if it is safe to allow users and scripts to specify the header
// named |name|.
static bool IsSafeHeader(const std::string& name);
@@ -84,14 +85,6 @@ class NET_EXPORT HttpUtil {
// a fully RFC-2616-compliant header value validation.
static bool IsValidHeaderValue(const base::StringPiece& value);
- // Strips all header lines from |headers| whose name matches
- // |headers_to_remove|. |headers_to_remove| is a list of null-terminated
- // lower-case header names, with array length |headers_to_remove_len|.
- // Returns the stripped header lines list, separated by "\r\n".
- static std::string StripHeaders(const std::string& headers,
- const char* const headers_to_remove[],
- size_t headers_to_remove_len);
-
// Multiple occurances of some headers cannot be coalesced into a comma-
// separated list since their values are (or contain) unquoted HTTP-date
// values, which may contain a comma (see RFC 2616 section 3.3.1).
@@ -185,10 +178,8 @@ class NET_EXPORT HttpUtil {
// is a workaround to avoid later code from incorrectly interpreting it as
// a line terminator.
//
- // TODO(eroman): we should use \n as the canonical line separator rather than
- // \0 to avoid this problem. Unfortunately the persistence layer
- // is already dependent on newlines being replaced by NULL so
- // this is hard to change without breaking things.
+ // TODO(crbug.com/671799): Should remove or internalize this to
+ // HttpResponseHeaders.
static std::string AssembleRawHeaders(const char* buf, int buf_len);
// Converts assembled "raw headers" back to the HTTP response format. That is
@@ -214,12 +205,6 @@ class NET_EXPORT HttpUtil {
static std::string GenerateAcceptLanguageHeader(
const std::string& raw_language_list);
- // Helper. If |*headers| already contains |header_name| do nothing,
- // otherwise add <header_name> ": " <header_value> to the end of the list.
- static void AppendHeaderIfMissing(const char* header_name,
- const std::string& header_value,
- std::string* headers);
-
// Returns true if the parameters describe a response with a strong etag or
// last-modified header. See section 13.3.3 of RFC 2616.
// An empty string should be passed for missing headers.
diff --git a/chromium/net/http/http_util_unittest.cc b/chromium/net/http/http_util_unittest.cc
index f2c2146215e..3560e2f4776 100644
--- a/chromium/net/http/http_util_unittest.cc
+++ b/chromium/net/http/http_util_unittest.cc
@@ -3,6 +3,7 @@
// found in the LICENSE file.
#include <algorithm>
+#include <limits>
#include "base/strings/string_util.h"
#include "net/http/http_util.h"
@@ -99,49 +100,6 @@ TEST(HttpUtilTest, IsSafeHeader) {
}
}
-TEST(HttpUtilTest, HasHeader) {
- static const struct {
- const char* const headers;
- const char* const name;
- bool expected_result;
- } tests[] = {
- { "", "foo", false },
- { "foo\r\nbar", "foo", false },
- { "ffoo: 1", "foo", false },
- { "foo: 1", "foo", true },
- { "foo: 1\r\nbar: 2", "foo", true },
- { "fOO: 1\r\nbar: 2", "foo", true },
- { "g: 0\r\nfoo: 1\r\nbar: 2", "foo", true },
- };
- for (size_t i = 0; i < arraysize(tests); ++i) {
- bool result = HttpUtil::HasHeader(tests[i].headers, tests[i].name);
- EXPECT_EQ(tests[i].expected_result, result);
- }
-}
-
-TEST(HttpUtilTest, StripHeaders) {
- static const char* const headers =
- "Origin: origin\r\n"
- "Content-Type: text/plain\r\n"
- "Cookies: foo1\r\n"
- "Custom: baz\r\n"
- "COOKIES: foo2\r\n"
- "Server: Apache\r\n"
- "OrIGin: origin2\r\n";
-
- static const char* const header_names[] = {
- "origin", "content-type", "cookies"
- };
-
- static const char* const expected_stripped_headers =
- "Custom: baz\r\n"
- "Server: Apache\r\n";
-
- EXPECT_EQ(expected_stripped_headers,
- HttpUtil::StripHeaders(headers, header_names,
- arraysize(header_names)));
-}
-
TEST(HttpUtilTest, HeadersIterator) {
std::string headers = "foo: 1\t\r\nbar: hello world\r\nbaz: 3 \r\n";
@@ -378,6 +336,7 @@ TEST(HttpUtilTest, LocateEndOfAdditionalHeaders) {
}
}
TEST(HttpUtilTest, AssembleRawHeaders) {
+ // clang-format off
struct {
const char* const input; // with '|' representing '\0'
const char* const expected_result; // with '\0' changed to '|'
@@ -679,7 +638,19 @@ TEST(HttpUtilTest, AssembleRawHeaders) {
"HTTP/1.0 200 OK\nFoo: 1|Foo2: 3\nBar: 2\n\n",
"HTTP/1.0 200 OK|Foo: 1Foo2: 3|Bar: 2||"
},
+
+ // The embedded NUL at the start of the line (before "Blah:") should not be
+ // interpreted as LWS (as that would mistake it for a header line
+ // continuation).
+ {
+ "HTTP/1.0 200 OK\n"
+ "Foo: 1\n"
+ "|Blah: 3\n"
+ "Bar: 2\n\n",
+ "HTTP/1.0 200 OK|Foo: 1|Blah: 3|Bar: 2||"
+ },
};
+ // clang-format on
for (size_t i = 0; i < arraysize(tests); ++i) {
std::string input = tests[i].input;
std::replace(input.begin(), input.end(), '|', '\0');
@@ -830,145 +801,75 @@ TEST(HttpUtilTest, ParseContentType) {
}
}
-TEST(HttpUtilTest, ParseRanges) {
+TEST(HttpUtilTest, ParseContentRangeHeader) {
const struct {
- const char* const headers;
+ const char* const content_range_header_spec;
bool expected_return_value;
- size_t expected_ranges_size;
- const struct {
- int64_t expected_first_byte_position;
- int64_t expected_last_byte_position;
- int64_t expected_suffix_length;
- } expected_ranges[10];
+ int64_t expected_first_byte_position;
+ int64_t expected_last_byte_position;
+ int64_t expected_instance_length;
} tests[] = {
- { "Range: bytes=0-10",
- true,
- 1,
- { {0, 10, -1}, }
- },
- { "Range: bytes=10-0",
- false,
- 0,
- {}
- },
- { "Range: BytES=0-10",
- true,
- 1,
- { {0, 10, -1}, }
- },
- { "Range: megabytes=0-10",
- false,
- 0,
- {}
- },
- { "Range: bytes0-10",
- false,
- 0,
- {}
- },
- { "Range: bytes=0-0,0-10,10-20,100-200,100-,-200",
- true,
- 6,
- { {0, 0, -1},
- {0, 10, -1},
- {10, 20, -1},
- {100, 200, -1},
- {100, -1, -1},
- {-1, -1, 200},
- }
- },
- { "Range: bytes=0-10\r\n"
- "Range: bytes=0-10,10-20,100-200,100-,-200",
- true,
- 1,
- { {0, 10, -1}
- }
- },
- { "Range: bytes=",
- false,
- 0,
- {}
- },
- { "Range: bytes=-",
- false,
- 0,
- {}
- },
- { "Range: bytes=0-10-",
- false,
- 0,
- {}
- },
- { "Range: bytes=-0-10",
- false,
- 0,
- {}
- },
- { "Range: bytes =0-10\r\n",
- true,
- 1,
- { {0, 10, -1}
- }
- },
- { "Range: bytes= 0-10 \r\n",
- true,
- 1,
- { {0, 10, -1}
- }
- },
- { "Range: bytes = 0 - 10 \r\n",
- true,
- 1,
- { {0, 10, -1}
- }
- },
- { "Range: bytes= 0-1 0\r\n",
- false,
- 0,
- {}
- },
- { "Range: bytes= 0- -10\r\n",
- false,
- 0,
- {}
- },
- { "Range: bytes= 0 - 1 , 10 -20, 100- 200 , 100-, -200 \r\n",
- true,
- 5,
- { {0, 1, -1},
- {10, 20, -1},
- {100, 200, -1},
- {100, -1, -1},
- {-1, -1, 200},
- }
- },
+ {"", false, -1, -1, -1},
+ {"megabytes 0-10/50", false, -1, -1, -1},
+ {"0-10/50", false, -1, -1, -1},
+ {"Bytes 0-50/51", true, 0, 50, 51},
+ {"bytes 0-50/51", true, 0, 50, 51},
+ {"bytes\t0-50/51", false, -1, -1, -1},
+ {" bytes 0-50/51", true, 0, 50, 51},
+ {" bytes 0 - 50 \t / \t51", true, 0, 50, 51},
+ {"bytes 0\t-\t50\t/\t51\t", true, 0, 50, 51},
+ {" \tbytes\t\t\t 0\t-\t50\t/\t51\t", true, 0, 50, 51},
+ {"\t bytes \t 0 - 50 / 5 1", false, -1, -1, -1},
+ {"\t bytes \t 0 - 5 0 / 51", false, -1, -1, -1},
+ {"bytes 50-0/51", false, -1, -1, -1},
+ {"bytes * /*", false, -1, -1, -1},
+ {"bytes * / * ", false, -1, -1, -1},
+ {"bytes 0-50/*", false, -1, -1, -1},
+ {"bytes 0-50 / * ", false, -1, -1, -1},
+ {"bytes 0-10000000000/10000000001", true, 0, 10000000000ll,
+ 10000000001ll},
+ {"bytes 0-10000000000/10000000000", false, -1, -1, -1},
+ // 64 bit wraparound.
+ {"bytes 0 - 9223372036854775807 / 100", false, -1, -1, -1},
+ // 64 bit wraparound.
+ {"bytes 0 - 100 / -9223372036854775808", false, -1, -1, -1},
+ {"bytes */50", false, -1, -1, -1},
+ {"bytes 0-50/10", false, -1, -1, -1},
+ {"bytes 40-50/45", false, -1, -1, -1},
+ {"bytes 0-50/-10", false, -1, -1, -1},
+ {"bytes 0-0/1", true, 0, 0, 1},
+ {"bytes 0-40000000000000000000/40000000000000000001", false, -1, -1, -1},
+ {"bytes 1-/100", false, -1, -1, -1},
+ {"bytes -/100", false, -1, -1, -1},
+ {"bytes -1/100", false, -1, -1, -1},
+ {"bytes 0-1233/*", false, -1, -1, -1},
+ {"bytes -123 - -1/100", false, -1, -1, -1},
};
- for (size_t i = 0; i < arraysize(tests); ++i) {
- std::vector<HttpByteRange> ranges;
- bool return_value = HttpUtil::ParseRanges(std::string(tests[i].headers),
- &ranges);
- EXPECT_EQ(tests[i].expected_return_value, return_value);
- if (return_value) {
- EXPECT_EQ(tests[i].expected_ranges_size, ranges.size());
- for (size_t j = 0; j < ranges.size(); ++j) {
- EXPECT_EQ(tests[i].expected_ranges[j].expected_first_byte_position,
- ranges[j].first_byte_position());
- EXPECT_EQ(tests[i].expected_ranges[j].expected_last_byte_position,
- ranges[j].last_byte_position());
- EXPECT_EQ(tests[i].expected_ranges[j].expected_suffix_length,
- ranges[j].suffix_length());
- }
- }
+ for (const auto& test : tests) {
+ int64_t first_byte_position, last_byte_position, instance_length;
+ EXPECT_EQ(test.expected_return_value,
+ HttpUtil::ParseContentRangeHeaderFor206(
+ test.content_range_header_spec, &first_byte_position,
+ &last_byte_position, &instance_length))
+ << test.content_range_header_spec;
+ EXPECT_EQ(test.expected_first_byte_position, first_byte_position)
+ << test.content_range_header_spec;
+ EXPECT_EQ(test.expected_last_byte_position, last_byte_position)
+ << test.content_range_header_spec;
+ EXPECT_EQ(test.expected_instance_length, instance_length)
+ << test.content_range_header_spec;
}
}
TEST(HttpUtilTest, ParseRetryAfterHeader) {
base::Time::Exploded now_exploded = {2014, 11, 4, 5, 22, 39, 30, 0};
- base::Time now = base::Time::FromUTCExploded(now_exploded);
+ base::Time now;
+ EXPECT_TRUE(base::Time::FromUTCExploded(now_exploded, &now));
base::Time::Exploded later_exploded = {2015, 1, 5, 1, 12, 34, 56, 0};
- base::Time later = base::Time::FromUTCExploded(later_exploded);
+ base::Time later;
+ EXPECT_TRUE(base::Time::FromUTCExploded(later_exploded, &later));
const struct {
const char* retry_after_string;
@@ -1408,4 +1309,17 @@ TEST(HttpUtilTest, IsToken) {
EXPECT_FALSE(HttpUtil::IsToken("\xff"));
}
+TEST(HttpUtilTest, IsLWS) {
+ EXPECT_FALSE(HttpUtil::IsLWS('\v'));
+ EXPECT_FALSE(HttpUtil::IsLWS('\0'));
+ EXPECT_FALSE(HttpUtil::IsLWS('1'));
+ EXPECT_FALSE(HttpUtil::IsLWS('a'));
+ EXPECT_FALSE(HttpUtil::IsLWS('.'));
+ EXPECT_FALSE(HttpUtil::IsLWS('\n'));
+ EXPECT_FALSE(HttpUtil::IsLWS('\r'));
+
+ EXPECT_TRUE(HttpUtil::IsLWS('\t'));
+ EXPECT_TRUE(HttpUtil::IsLWS(' '));
+}
+
} // namespace net
diff --git a/chromium/net/http/mock_gssapi_library_posix.cc b/chromium/net/http/mock_gssapi_library_posix.cc
index ce21159a034..2e4c3c1198b 100644
--- a/chromium/net/http/mock_gssapi_library_posix.cc
+++ b/chromium/net/http/mock_gssapi_library_posix.cc
@@ -480,4 +480,3 @@ OM_uint32 MockGSSAPILibrary::inquire_context(
} // namespace test
} // namespace net
-
diff --git a/chromium/net/http/mock_gssapi_library_posix.h b/chromium/net/http/mock_gssapi_library_posix.h
index 07f2542805b..8fc2336b766 100644
--- a/chromium/net/http/mock_gssapi_library_posix.h
+++ b/chromium/net/http/mock_gssapi_library_posix.h
@@ -180,4 +180,3 @@ class MockGSSAPILibrary : public GSSAPILibrary {
} // namespace net
#endif // NET_HTTP_MOCK_GSSAPI_LIBRARY_POSIX_H_
-
diff --git a/chromium/net/http/partial_data.cc b/chromium/net/http/partial_data.cc
index 915aaa4bb92..dceea25bcb0 100644
--- a/chromium/net/http/partial_data.cc
+++ b/chromium/net/http/partial_data.cc
@@ -274,7 +274,7 @@ bool PartialData::ResponseHeadersOK(const HttpResponseHeaders* headers) {
}
int64_t start, end, total_length;
- if (!headers->GetContentRange(&start, &end, &total_length))
+ if (!headers->GetContentRangeFor206(&start, &end, &total_length))
return false;
if (total_length <= 0)
return false;
diff --git a/chromium/net/http/proxy_client_socket.h b/chromium/net/http/proxy_client_socket.h
index bfe49d18789..ea4f29e0747 100644
--- a/chromium/net/http/proxy_client_socket.h
+++ b/chromium/net/http/proxy_client_socket.h
@@ -12,8 +12,6 @@
#include "net/socket/ssl_client_socket.h"
#include "net/socket/stream_socket.h"
-class GURL;
-
namespace net {
class HostPortPair;
@@ -21,7 +19,6 @@ class HttpAuthController;
class HttpStream;
class HttpResponseInfo;
class HttpRequestHeaders;
-struct HttpRequestInfo;
class HttpAuthController;
class NetLogWithSource;
diff --git a/chromium/net/http/transport_security_state.cc b/chromium/net/http/transport_security_state.cc
index 9b42febf5f1..5f82c2897b5 100644
--- a/chromium/net/http/transport_security_state.cc
+++ b/chromium/net/http/transport_security_state.cc
@@ -645,6 +645,10 @@ bool DecodeHSTSPreload(const std::string& hostname, PreloadResult* out) {
std::string SerializeExpectStapleResponseStatus(
OCSPVerifyResult::ResponseStatus status) {
switch (status) {
+ case OCSPVerifyResult::NOT_CHECKED:
+ // Reports shouldn't be sent for this response status.
+ NOTREACHED();
+ return "NOT_CHECKED";
case OCSPVerifyResult::MISSING:
return "MISSING";
case OCSPVerifyResult::PROVIDED:
@@ -662,6 +666,7 @@ std::string SerializeExpectStapleResponseStatus(
case OCSPVerifyResult::PARSE_RESPONSE_DATA_ERROR:
return "PARSE_RESPONSE_DATA_ERROR";
}
+ NOTREACHED();
return std::string();
}
@@ -682,7 +687,7 @@ std::string SerializeExpectStapleRevocationStatus(
bool SerializeExpectStapleReport(const HostPortPair& host_port_pair,
const SSLInfo& ssl_info,
- const std::string& ocsp_response,
+ base::StringPiece ocsp_response,
std::string* out_serialized_report) {
DCHECK(ssl_info.is_issued_by_known_root);
base::DictionaryValue report;
@@ -789,7 +794,7 @@ TransportSecurityState::PKPStatus TransportSecurityState::CheckPublicKeyPins(
void TransportSecurityState::CheckExpectStaple(
const HostPortPair& host_port_pair,
const SSLInfo& ssl_info,
- const std::string& ocsp_response) {
+ base::StringPiece ocsp_response) {
DCHECK(CalledOnValidThread());
if (!enable_static_expect_staple_ || !report_sender_ ||
!ssl_info.is_issued_by_known_root) {
@@ -803,7 +808,11 @@ void TransportSecurityState::CheckExpectStaple(
if (!GetStaticExpectStapleState(host_port_pair.host(), &expect_staple_state))
return;
- // No report needed if a stapled OCSP response was provided.
+ // No report needed if OCSP details were not checked on this connection.
+ if (ssl_info.ocsp_result.response_status == OCSPVerifyResult::NOT_CHECKED)
+ return;
+
+ // No report needed if a stapled OCSP response was provided and it was valid.
if (ssl_info.ocsp_result.response_status == OCSPVerifyResult::PROVIDED &&
ssl_info.ocsp_result.revocation_status == OCSPRevocationStatus::GOOD) {
return;
diff --git a/chromium/net/http/transport_security_state.h b/chromium/net/http/transport_security_state.h
index fc40b7d1413..a55cf62d417 100644
--- a/chromium/net/http/transport_security_state.h
+++ b/chromium/net/http/transport_security_state.h
@@ -322,7 +322,7 @@ class NET_EXPORT TransportSecurityState
// for OCSP responses behind MITM proxies are not useful to site owners.
void CheckExpectStaple(const HostPortPair& host_port_pair,
const SSLInfo& ssl_info,
- const std::string& ocsp_response);
+ base::StringPiece ocsp_response);
// Returns true if connections to |host|, using the validated certificate
// |validated_certificate_chain|, are expected to be accompanied with
@@ -477,6 +477,7 @@ class NET_EXPORT TransportSecurityState
private:
friend class TransportSecurityStateTest;
+ friend class TransportSecurityStateStaticFuzzer;
FRIEND_TEST_ALL_PREFIXES(HttpSecurityHeadersTest, UpdateDynamicPKPOnly);
FRIEND_TEST_ALL_PREFIXES(HttpSecurityHeadersTest, UpdateDynamicPKPMaxAge0);
FRIEND_TEST_ALL_PREFIXES(HttpSecurityHeadersTest, NoClobberPins);
diff --git a/chromium/net/http/transport_security_state_static.h b/chromium/net/http/transport_security_state_static.h
index 03a1740faf4..7b3069b2c19 100644
--- a/chromium/net/http/transport_security_state_static.h
+++ b/chromium/net/http/transport_security_state_static.h
@@ -2,9 +2,7 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-// This file is automatically generated by
-// transport_security_state_static_generate.go.
-// You can find it at https://github.com/chromium/hstspreload/.
+// This file is generated by net/tools/transport_security_state_generator/.
#ifndef NET_HTTP_TRANSPORT_SECURITY_STATE_STATIC_H_
#define NET_HTTP_TRANSPORT_SECURITY_STATE_STATIC_H_
@@ -288,116 +286,108 @@ enum SecondLevelDomainName {
DOMAIN_GOOGLESOURCE_COM,
DOMAIN_NIGHTX_UK,
DOMAIN_FIREBASEIO_COM,
+ DOMAIN_CRBUG_COM,
+ DOMAIN_CROSBUG_COM,
+ DOMAIN_CRREV_COM,
+ DOMAIN_ME_UK,
+ DOMAIN_THEMATHEMATICIAN_UK,
// Boundary value for UMA_HISTOGRAM_ENUMERATION.
DOMAIN_NUM_EVENTS,
};
// These are SubjectPublicKeyInfo hashes for public key pinning. The
// hashes are SHA256 digests.
+static const char kSPKIHash_AAACertificateServices[] =
+ "\xbd\x15\x3e\xd7\xb0\x43\x4f\x68\x86\xb1\x7b\xce\x8b\xbe\x84\xed"
+ "\x34\x0c\x71\x32\xd7\x02\xa8\xf4\xfa\x31\x8f\x75\x6e\xcb\xd6\xf3";
-static const char kSPKIHash_TestSPKI[] =
- "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
- "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00";
+static const char kSPKIHash_AddTrustClass1CARoot[] =
+ "\x05\x2b\x68\x71\x07\xec\x84\xe8\x73\x03\x82\x45\x2e\xc2\xa2\x74"
+ "\x51\x74\x5d\x74\x85\xa5\x7d\x6f\x46\x4e\x0d\xa7\xa1\xb6\xaf\x2a";
-static const char kSPKIHash_VeriSignClass3_G3[] =
- "\x49\x5a\x96\xba\x6b\xad\x78\x24\x07\xbd\x52\x1a\x00\xba\xce\x65"
- "\x7b\xb3\x55\x55\x5e\x4b\xb7\xf8\x14\x6c\x71\xbb\xa5\x7e\x7a\xce";
+static const char kSPKIHash_AddTrustExternalCARoot[] =
+ "\x94\x2a\x69\x16\xa6\xe4\xae\x52\x77\x11\xc5\x45\x02\x47\xa2\xa7"
+ "\x4f\xb8\xe1\x56\xa8\x25\x4c\xa6\x6e\x73\x9a\x11\x49\x3b\xb4\x45";
-static const char kSPKIHash_GoogleBackup2048[] =
- "\x20\xf3\x1b\x0c\x08\xcb\x55\x21\xa7\xb4\x63\xb7\x58\xfe\x77\x5f"
- "\xfc\xe2\x94\x25\x67\x75\xec\xf9\x60\x9d\xbe\xbc\x9b\xe1\x26\xc0";
+static const char kSPKIHash_AddTrustPublicCARoot[] =
+ "\x38\x61\xd7\xb6\x96\x1f\xcd\xb2\x12\x04\x56\xff\x6f\xc2\xeb\x77"
+ "\x04\xb1\xa7\x41\xb4\xbd\x93\x3a\x83\x76\xf5\xe1\x91\x5c\xa6\x98";
-static const char kSPKIHash_GoogleG2[] =
- "\xec\x72\x29\x69\xcb\x64\x20\x0a\xb6\x63\x8f\x68\xac\x53\x8e\x40"
- "\xab\xab\x5b\x19\xa6\x48\x56\x61\x04\x2a\x10\x61\xc4\x61\x27\x76";
+static const char kSPKIHash_AddTrustQualifiedCARoot[] =
+ "\xc7\x3a\xfc\x2e\xba\x77\x0d\x0c\xbc\x1e\xe4\x1f\x25\x2b\x52\xe8"
+ "\xa9\x3d\x12\xb7\x2d\xcc\xec\x03\x1d\x8d\x83\x9c\xbf\x81\x8a\x79";
-static const char kSPKIHash_GeoTrustGlobal[] =
- "\x87\xaf\x34\xd6\x6f\xb3\xf2\xfd\xf3\x6e\x09\x11\x1e\x9a\xba\x2f"
- "\x6f\x44\xb2\x07\xf3\x86\x3f\x3d\x0b\x54\xb2\x50\x23\x90\x9a\xa5";
+static const char kSPKIHash_BaltimoreCyberTrustRoot[] =
+ "\x63\xd9\xaf\x9b\x47\xb1\x06\x4d\x49\xa1\x0e\x7b\x7f\xd5\x66\xdb"
+ "\xc8\xca\xa3\x99\x45\x9b\xfc\x28\x29\xc5\x71\xad\x8c\x6e\xf3\x4a";
-static const char kSPKIHash_GeoTrustPrimary[] =
- "\x49\x05\x46\x66\x23\xab\x41\x78\xbe\x92\xac\x5c\xbd\x65\x84\xf7"
- "\xa1\xe1\x7f\x27\x65\x2d\x5a\x85\xaf\x89\x50\x4e\xa2\x39\xaa\xaa";
+static const char kSPKIHash_COMODOCertificationAuthority[] =
+ "\x00\x6d\x7b\xe7\x55\x5d\xd8\x20\x26\x44\x2c\x4f\x1a\x27\xa8\x0e"
+ "\x89\xa1\x98\x9c\xb8\x7b\x34\x44\x8e\xd2\x19\x4c\x18\x19\x6d\x5e";
-static const char kSPKIHash_RapidSSL[] =
- "\x95\x3d\x3d\x80\xf5\x1e\x41\xf6\xd8\xae\x5c\x51\xb6\x9b\x07\xae"
- "\x30\xdb\x96\x3f\x51\xa7\x3f\xae\xed\xa8\xdf\x0a\xb8\x38\xa8\x33";
+static const char kSPKIHash_COMODORSADomainValidationSecureServerCA[] =
+ "\x92\x53\xb6\xde\x74\xf6\x7a\x11\x43\x5c\x27\xf1\xdd\xe1\xd3\x0d"
+ "\x11\x12\x33\x3d\xda\xb2\x3d\x66\xb8\xef\xb8\x68\x87\x63\x8a\xe6";
-static const char kSPKIHash_DigiCertEVRoot[] =
- "\x5a\x88\x96\x47\x22\x0e\x54\xd6\xbd\x8a\x16\x81\x72\x24\x52\x0b"
- "\xb5\xc7\x8e\x58\x98\x4b\xd5\x70\x50\x63\x88\xb9\xde\x0f\x07\x5f";
+static const char kSPKIHash_DSTRootCAX3[] =
+ "\x56\x3b\x3c\xaf\x8c\xfe\xf3\x4c\x23\x35\xca\xf5\x60\xa7\xa9\x59"
+ "\x06\xe8\x48\x84\x62\xeb\x75\xac\x59\x78\x48\x30\xdf\x9e\x5b\x2b";
static const char kSPKIHash_DigiCertAssuredIDRoot[] =
"\x23\xf2\xed\xff\x3e\xde\x90\x25\x9a\x9e\x30\xf4\x0a\xf8\xf9\x12"
"\xa5\xe5\xb3\x69\x4e\x69\x38\x44\x03\x41\xf6\x06\x0e\x01\x4f\xfa";
+static const char kSPKIHash_DigiCertECCSecureServerCA[] =
+ "\x3d\x95\xcd\xde\x54\x40\xcb\xef\x2d\x04\xa9\x36\x3b\x1e\x85\xee"
+ "\x32\x25\x9f\x3a\xf6\x63\x39\xb0\xa9\xcd\xc9\x9f\x27\xd7\xa0\x2c";
+
+static const char kSPKIHash_DigiCertEVRoot[] =
+ "\x5a\x88\x96\x47\x22\x0e\x54\xd6\xbd\x8a\x16\x81\x72\x24\x52\x0b"
+ "\xb5\xc7\x8e\x58\x98\x4b\xd5\x70\x50\x63\x88\xb9\xde\x0f\x07\x5f";
+
static const char kSPKIHash_DigiCertGlobalRoot[] =
"\xaf\xf9\x88\x90\x6d\xde\x12\x95\x5d\x9b\xeb\xbf\x92\x8f\xdc\xc3"
"\x1c\xce\x32\x8d\x5b\x93\x84\xf2\x1c\x89\x41\xca\x26\xe2\x03\x91";
-static const char kSPKIHash_Tor1[] =
- "\x6d\x8c\xfd\x25\x30\xe4\xf3\xd5\xf7\xaa\xed\xdf\x82\xcc\x06\xfa"
- "\x50\x50\xb2\x8e\x6f\x23\x43\x75\x7f\x44\x71\xe2\x0a\x38\x9c\xba";
-
-static const char kSPKIHash_Tor2[] =
- "\xc5\x70\xb1\x85\x37\x67\xee\xec\x57\x9d\xe2\x52\x6d\x00\xaa\xa0"
- "\x0b\xee\x5b\x76\x6d\x42\x5d\xa9\x0d\x54\xdf\xda\xc7\xb0\x4b\xcc";
-
-static const char kSPKIHash_Tor3[] =
- "\x0a\x57\x82\xd6\xac\x14\x47\xc2\x4f\x80\x7d\x67\x5e\xf4\x9e\xd9"
- "\x51\xf1\x0d\xee\x7f\x29\xf3\x6c\xf7\xa1\x2e\xb1\xb7\xd2\x39\xfa";
-
-static const char kSPKIHash_VeriSignClass1[] =
- "\x2d\xc9\x47\x0b\xe6\x3e\xf4\xac\xf1\xbd\x82\x86\x09\x40\x2b\xb7"
- "\xb8\x7b\xd9\x96\x38\xa6\x43\x93\x4e\x88\x68\x2d\x1b\xe8\xc3\x08";
-
-static const char kSPKIHash_VeriSignClass3_G4[] =
- "\x51\x92\x43\x8e\xc3\x69\xd7\xee\x0c\xe7\x1f\x5c\x6d\xb7\x5f\x94"
- "\x1e\xfb\xf7\x2e\x58\x44\x17\x15\xe9\x9e\xab\x04\xc2\xc8\xac\xee";
-
-static const char kSPKIHash_VeriSignClass4_G3[] =
- "\x56\x7b\x82\x11\xfd\x20\xd3\xd2\x83\xee\x0c\xd7\xce\x06\x72\xcb"
- "\x9d\x99\xbc\x5b\x48\x7a\x58\xc9\xd5\x4e\xc6\x7f\x77\xd4\xa8\xf5";
+static const char kSPKIHash_EntrustRootEC1[] =
+ "\xfe\xa2\xb7\xd6\x45\xfb\xa7\x3d\x75\x3c\x1e\xc9\xa7\x87\x0c\x40"
+ "\xe1\xf7\xb0\xc5\x61\xe9\x27\xb9\x85\xbf\x71\x18\x66\xe3\x6f\x22";
-static const char kSPKIHash_VeriSignClass1_G3[] =
- "\x22\x07\x6e\x5a\xef\x44\xbb\x9a\x41\x6a\x28\xb7\xd1\xc4\x43\x22"
- "\xd7\x05\x9f\x60\xfe\xff\xa5\xca\xf6\xc5\xbe\x84\x47\x89\x13\x03";
+static const char kSPKIHash_Entrust_2048[] =
+ "\x1e\xa3\xc5\xe4\x3e\xd6\x6c\x2d\xa2\x98\x3a\x42\xa4\xa7\x9b\x1e"
+ "\x90\x67\x86\xce\x9f\x1b\x58\x62\x14\x19\xa0\x04\x63\xa8\x7d\x38";
-static const char kSPKIHash_VeriSignClass2_G3[] =
- "\x70\x06\xa3\x83\x11\xe5\x8f\xb1\x93\x48\x42\x33\x21\x82\x10\xc6"
- "\x61\x25\xa0\xe4\xa8\x26\xae\xd5\x39\xac\x56\x1d\xfb\xfb\xd9\x03";
+static const char kSPKIHash_Entrust_EV[] =
+ "\x6d\xbf\xae\x00\xd3\x7b\x9c\xd7\x3f\x8f\xb4\x7d\xe6\x59\x17\xaf"
+ "\x00\xe0\xdd\xdf\x42\xdb\xce\xac\x20\xc1\x7c\x02\x75\xee\x20\x95";
-static const char kSPKIHash_VeriSignClass3_G2[] =
- "\x02\x3c\x81\xcc\xe8\xe7\xc6\x4f\xa9\x42\xd3\xc1\x50\x48\x70\x7d"
- "\x35\xd9\xbb\x5b\x87\xf4\xf5\x44\xc5\xbf\x1b\xc5\x64\x3a\xf2\xfa";
+static const char kSPKIHash_Entrust_G2[] =
+ "\x76\xee\x85\x90\x37\x4c\x71\x54\x37\xbb\xca\x6b\xba\x60\x28\xea"
+ "\xdd\xe2\xdc\x6d\xbb\xb8\xc3\xf6\x10\xe8\x51\xf1\x1d\x1a\xb7\xf5";
-static const char kSPKIHash_VeriSignClass2_G2[] =
- "\xda\x80\x0b\x80\xb2\xa8\x7d\x39\x9e\x66\xfa\x19\xd7\x2f\xdf\x49"
- "\x98\x3b\x47\xd8\xcf\x32\x2c\x7c\x79\x50\x3a\x0c\x7e\x28\xfe\xaf";
+static const char kSPKIHash_Entrust_SSL[] =
+ "\x9e\xcc\x51\x36\x8e\x86\xe3\x46\x0f\x66\xc2\x95\xe4\x94\x2d\xd5"
+ "\x30\x80\xf2\x7b\x1e\x41\x0a\xff\x2d\x1a\xa9\xd4\xe6\xbc\x7e\x7c";
-static const char kSPKIHash_VeriSignClass3_G5[] =
- "\x25\xb4\x1b\x50\x6e\x49\x30\x95\x28\x23\xa6\xeb\x9f\x1d\x31\xde"
- "\xf6\x45\xea\x38\xa5\xc6\xc6\xa9\x6d\x71\x95\x7e\x38\x4d\xf0\x58";
+static const char kSPKIHash_FacebookBackup[] =
+ "\xab\x83\xce\xd8\x6d\x9c\x6e\x46\x61\x67\xcd\xbe\x26\x09\x91\x53"
+ "\x21\x8c\xa0\x07\xa8\xcc\x0f\x81\x49\x75\x57\x41\x60\x7c\x5d\x64";
-static const char kSPKIHash_VeriSignUniversal[] =
- "\x96\x7b\x0c\xd9\x3f\xce\xf7\xf2\x7c\xe2\xc2\x45\x76\x7a\xe9\xb0"
- "\x5a\x77\x6b\x06\x49\xf9\x96\x5b\x62\x90\x96\x84\x69\x68\x68\x72";
+static const char kSPKIHash_GTECyberTrustGlobalRoot[] =
+ "\x10\x69\xfa\x47\xa0\xaa\x4f\x8c\xf7\x11\x1b\x1c\xae\xa3\x65\xee"
+ "\xae\xd1\x0b\xff\xf3\x26\x60\xde\xf6\xe0\x61\x4b\xfa\xe7\x08\x75";
-static const char kSPKIHash_Twitter1[] =
- "\xbd\x4f\x4c\xe3\xc2\xf3\x0f\xf0\x85\xdf\x8c\x04\xe4\xf3\xdf\xe2"
- "\x70\x70\x47\x2a\x2c\xcb\x4e\x97\xdb\x52\x74\x6a\x9f\x32\x4b\x9b";
+static const char kSPKIHash_GeoTrustGlobal[] =
+ "\x87\xaf\x34\xd6\x6f\xb3\xf2\xfd\xf3\x6e\x09\x11\x1e\x9a\xba\x2f"
+ "\x6f\x44\xb2\x07\xf3\x86\x3f\x3d\x0b\x54\xb2\x50\x23\x90\x9a\xa5";
static const char kSPKIHash_GeoTrustGlobal2[] =
"\x17\x75\x5a\x5c\x29\x5f\x3d\x2d\x72\xe6\xf0\x31\xa1\xf0\x7f\x40"
"\x0c\x58\x8b\x9e\x58\x2b\x22\xf1\x7e\xae\x31\xa1\x59\x0d\x11\x85";
-static const char kSPKIHash_GeoTrustUniversal[] =
- "\x96\x99\x22\x5c\x5d\xe5\x2e\x56\xcd\xd3\x2d\xf2\xe9\x6d\x1c\xfe"
- "\xa5\xaa\x3c\xa0\xbb\x52\xcd\x89\x33\xc2\x3b\x5c\x27\x44\x38\x20";
-
-static const char kSPKIHash_GeoTrustUniversal2[] =
- "\x7c\xaa\x03\x46\x51\x24\x59\x0c\x60\x1e\x56\x7e\x52\x14\x8e\x95"
- "\x2c\x0c\xff\xe8\x90\x00\x53\x0f\xe0\xd9\x5b\x6d\x50\xea\xae\x41";
+static const char kSPKIHash_GeoTrustPrimary[] =
+ "\x49\x05\x46\x66\x23\xab\x41\x78\xbe\x92\xac\x5c\xbd\x65\x84\xf7"
+ "\xa1\xe1\x7f\x27\x65\x2d\x5a\x85\xaf\x89\x50\x4e\xa2\x39\xaa\xaa";
static const char kSPKIHash_GeoTrustPrimary_G2[] =
"\xbc\xfb\x44\xaa\xb9\xad\x02\x10\x15\x70\x6b\x41\x21\xea\x76\x1c"
@@ -407,54 +397,122 @@ static const char kSPKIHash_GeoTrustPrimary_G3[] =
"\xab\x98\x49\x52\x76\xad\xf1\xec\xaf\xf2\x8f\x35\xc5\x30\x48\x78"
"\x1e\x5c\x17\x18\xda\xb9\xc8\xe6\x7a\x50\x4f\x4f\x6a\x51\x32\x8f";
-static const char kSPKIHash_Entrust_2048[] =
- "\x1e\xa3\xc5\xe4\x3e\xd6\x6c\x2d\xa2\x98\x3a\x42\xa4\xa7\x9b\x1e"
- "\x90\x67\x86\xce\x9f\x1b\x58\x62\x14\x19\xa0\x04\x63\xa8\x7d\x38";
+static const char kSPKIHash_GeoTrustUniversal[] =
+ "\x96\x99\x22\x5c\x5d\xe5\x2e\x56\xcd\xd3\x2d\xf2\xe9\x6d\x1c\xfe"
+ "\xa5\xaa\x3c\xa0\xbb\x52\xcd\x89\x33\xc2\x3b\x5c\x27\x44\x38\x20";
-static const char kSPKIHash_Entrust_EV[] =
- "\x6d\xbf\xae\x00\xd3\x7b\x9c\xd7\x3f\x8f\xb4\x7d\xe6\x59\x17\xaf"
- "\x00\xe0\xdd\xdf\x42\xdb\xce\xac\x20\xc1\x7c\x02\x75\xee\x20\x95";
+static const char kSPKIHash_GeoTrustUniversal2[] =
+ "\x7c\xaa\x03\x46\x51\x24\x59\x0c\x60\x1e\x56\x7e\x52\x14\x8e\x95"
+ "\x2c\x0c\xff\xe8\x90\x00\x53\x0f\xe0\xd9\x5b\x6d\x50\xea\xae\x41";
-static const char kSPKIHash_Entrust_G2[] =
- "\x76\xee\x85\x90\x37\x4c\x71\x54\x37\xbb\xca\x6b\xba\x60\x28\xea"
- "\xdd\xe2\xdc\x6d\xbb\xb8\xc3\xf6\x10\xe8\x51\xf1\x1d\x1a\xb7\xf5";
+static const char kSPKIHash_GlobalSignRootCA[] =
+ "\x2b\xce\xe8\x58\x15\x8c\xf5\x46\x5f\xc9\xd7\x6f\x0d\xfa\x31\x2f"
+ "\xef\x25\xa4\xdc\xa8\x50\x1d\xa9\xb4\x6b\x67\xd1\xfb\xfa\x1b\x64";
-static const char kSPKIHash_Entrust_SSL[] =
- "\x9e\xcc\x51\x36\x8e\x86\xe3\x46\x0f\x66\xc2\x95\xe4\x94\x2d\xd5"
- "\x30\x80\xf2\x7b\x1e\x41\x0a\xff\x2d\x1a\xa9\xd4\xe6\xbc\x7e\x7c";
+static const char kSPKIHash_GlobalSignRootCA_R2[] =
+ "\x8a\x27\xb5\x55\x7b\x4b\xec\x7c\xc0\x30\x5f\xbf\x3d\x53\xd1\xf7"
+ "\x1c\xd3\xf3\x49\x10\xc5\xd6\x5e\x27\xec\xdd\xb8\x20\x77\xba\x3d";
-static const char kSPKIHash_AAACertificateServices[] =
- "\xbd\x15\x3e\xd7\xb0\x43\x4f\x68\x86\xb1\x7b\xce\x8b\xbe\x84\xed"
- "\x34\x0c\x71\x32\xd7\x02\xa8\xf4\xfa\x31\x8f\x75\x6e\xcb\xd6\xf3";
+static const char kSPKIHash_GlobalSignRootCA_R3[] =
+ "\x70\x6b\xb1\x01\x7c\x85\x5c\x59\x16\x9b\xad\x5c\x17\x81\xcf\x59"
+ "\x7f\x12\xd2\xca\xd2\xf6\x3d\x1a\x4a\xa3\x74\x93\x80\x0f\xfb\x80";
-static const char kSPKIHash_AddTrustClass1CARoot[] =
- "\x05\x2b\x68\x71\x07\xec\x84\xe8\x73\x03\x82\x45\x2e\xc2\xa2\x74"
- "\x51\x74\x5d\x74\x85\xa5\x7d\x6f\x46\x4e\x0d\xa7\xa1\xb6\xaf\x2a";
+static const char kSPKIHash_GoDaddyRoot_G2[] =
+ "\x2a\x8f\x2d\x8a\xf0\xeb\x12\x38\x98\xf7\x4c\x86\x6a\xc3\xfa\x66"
+ "\x90\x54\xe2\x3c\x17\xbc\x7a\x95\xbd\x02\x34\x19\x2d\xc6\x35\xd0";
-static const char kSPKIHash_AddTrustExternalCARoot[] =
- "\x94\x2a\x69\x16\xa6\xe4\xae\x52\x77\x11\xc5\x45\x02\x47\xa2\xa7"
- "\x4f\xb8\xe1\x56\xa8\x25\x4c\xa6\x6e\x73\x9a\x11\x49\x3b\xb4\x45";
+static const char kSPKIHash_GoDaddySecure[] =
+ "\x32\xb6\x4b\x66\x72\x7a\x20\x63\xe4\x06\x6f\x3b\x95\x8c\xb0\xaa"
+ "\xee\x57\x6a\x5e\xce\xfd\x95\x33\x99\xbb\x88\x74\x73\x1d\x95\x87";
-static const char kSPKIHash_AddTrustPublicCARoot[] =
- "\x38\x61\xd7\xb6\x96\x1f\xcd\xb2\x12\x04\x56\xff\x6f\xc2\xeb\x77"
- "\x04\xb1\xa7\x41\xb4\xbd\x93\x3a\x83\x76\xf5\xe1\x91\x5c\xa6\x98";
+static const char kSPKIHash_GoogleBackup2048[] =
+ "\x20\xf3\x1b\x0c\x08\xcb\x55\x21\xa7\xb4\x63\xb7\x58\xfe\x77\x5f"
+ "\xfc\xe2\x94\x25\x67\x75\xec\xf9\x60\x9d\xbe\xbc\x9b\xe1\x26\xc0";
-static const char kSPKIHash_AddTrustQualifiedCARoot[] =
- "\xc7\x3a\xfc\x2e\xba\x77\x0d\x0c\xbc\x1e\xe4\x1f\x25\x2b\x52\xe8"
- "\xa9\x3d\x12\xb7\x2d\xcc\xec\x03\x1d\x8d\x83\x9c\xbf\x81\x8a\x79";
+static const char kSPKIHash_GoogleG2[] =
+ "\xec\x72\x29\x69\xcb\x64\x20\x0a\xb6\x63\x8f\x68\xac\x53\x8e\x40"
+ "\xab\xab\x5b\x19\xa6\x48\x56\x61\x04\x2a\x10\x61\xc4\x61\x27\x76";
-static const char kSPKIHash_COMODOCertificationAuthority[] =
- "\x00\x6d\x7b\xe7\x55\x5d\xd8\x20\x26\x44\x2c\x4f\x1a\x27\xa8\x0e"
- "\x89\xa1\x98\x9c\xb8\x7b\x34\x44\x8e\xd2\x19\x4c\x18\x19\x6d\x5e";
+static const char kSPKIHash_LetsEncryptAuthorityBackup_X2_X4[] =
+ "\xb1\x11\xdd\x8a\x1c\x20\x91\xa8\x9b\xd4\xfd\x60\xc5\x7f\x07\x16"
+ "\xcc\xe5\x0f\xee\xff\x81\x37\xcd\xbe\xe0\x32\x6e\x02\xcf\x36\x2b";
+
+static const char kSPKIHash_LetsEncryptAuthorityPrimary_X1_X3[] =
+ "\x60\xb8\x75\x75\x44\x7d\xcb\xa2\xa3\x6b\x7d\x11\xac\x09\xfb\x24"
+ "\xa9\xdb\x40\x6f\xee\x12\xd2\xcc\x90\x18\x05\x17\x61\x6e\x8a\x18";
+
+static const char kSPKIHash_RapidSSL[] =
+ "\x95\x3d\x3d\x80\xf5\x1e\x41\xf6\xd8\xae\x5c\x51\xb6\x9b\x07\xae"
+ "\x30\xdb\x96\x3f\x51\xa7\x3f\xae\xed\xa8\xdf\x0a\xb8\x38\xa8\x33";
static const char kSPKIHash_SecureCertificateServices[] =
"\x46\x91\xcb\xfd\xe8\x4a\x6b\x60\x52\xdd\xbe\x15\x2b\xb0\xc2\x16"
"\xae\x25\xa8\x6e\x57\x47\x81\x3d\xbc\x0f\x14\x7f\x33\x85\x70\xbe";
+static const char kSPKIHash_SpiderOak2[] =
+ "\xed\x8d\xd4\x9f\x16\xdf\x7c\xbf\x1a\x14\xf5\xec\x38\x90\x69\x19"
+ "\xab\x20\xa4\x39\xa7\x82\x92\x21\x03\x11\x8a\x75\x04\x64\x95\x04";
+
+static const char kSPKIHash_SpiderOak3[] =
+ "\x2e\x41\x11\xe7\x8b\xce\x76\x5c\xa0\xa5\x3b\x1b\x62\xf9\x69\x32"
+ "\xad\x42\x13\xf9\x43\x00\x6d\x40\x3f\xdc\x66\x76\xdc\x2f\x57\x60";
+
+static const char kSPKIHash_Swehack[] =
+ "\x15\xd6\x9f\x7c\x4e\xfd\xf6\xb5\x5b\xde\x8c\x80\xba\x12\x76\x98"
+ "\x15\xbf\x5c\x9c\x03\xd3\xb5\x1a\x8d\xbd\x86\xe9\x8c\x12\x00\x4c";
+
+static const char kSPKIHash_SwehackBackup[] =
+ "\xcf\xa7\x2e\xb3\x00\x3a\x13\x5b\xe0\x16\x40\xa3\x52\xc6\xc4\x62"
+ "\x8d\x0b\x7f\x76\x8f\xf0\xcf\x18\x3a\xfc\x24\xa2\x21\xb3\x0c\x2a";
+
+static const char kSPKIHash_SymantecClass3EVG3[] =
+ "\x80\xcc\x56\x3a\xb5\xf8\x3c\xc4\x1e\xb0\xaf\x6a\x14\xd6\xd8\x07"
+ "\x18\xc1\x7e\x35\x2f\x96\x49\xff\xbc\xdd\x67\xf8\xbf\x65\x13\x91";
+
+static const char kSPKIHash_TestSPKI[] =
+ "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
+ "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00";
+
+static const char kSPKIHash_ThawtePremiumServer[] =
+ "\xf5\x3c\x22\x05\x98\x17\xdd\x96\xf4\x00\x65\x16\x39\xd2\xf8\x57"
+ "\xe2\x10\x70\xa5\x9a\xbe\xd9\x07\x94\x00\xd9\xf6\x95\x50\x69\x00";
+
+static const char kSPKIHash_ThawtePrimaryRootCA[] =
+ "\x1d\x75\xd0\x83\x1b\x9e\x08\x85\x39\x4d\x32\xc7\xa1\xbf\xdb\x3d"
+ "\xbc\x1c\x28\xe2\xb0\xe8\x39\x1f\xb1\x35\x98\x1d\xbc\x5b\xa9\x36";
+
+static const char kSPKIHash_ThawtePrimaryRootCA_G2[] =
+ "\x67\xdc\x4f\x32\xfa\x10\xe7\xd0\x1a\x79\xa0\x73\xaa\x0c\x9e\x02"
+ "\x12\xec\x2f\xfc\x3d\x77\x9e\x0a\xa7\xf9\xc0\xf0\xe1\xc2\xc8\x93";
+
+static const char kSPKIHash_ThawtePrimaryRootCA_G3[] =
+ "\x19\x06\xc6\x12\x4d\xbb\x43\x85\x78\xd0\x0e\x06\x6d\x50\x54\xc6"
+ "\xc3\x7f\x0f\xa6\x02\x8c\x05\x54\x5e\x09\x94\xed\xda\xec\x86\x29";
+
+static const char kSPKIHash_TheGoDaddyGroupClass2[] =
+ "\x56\x32\xd9\x7b\xfa\x77\x5b\xf3\xc9\x9d\xde\xa5\x2f\xc2\x55\x34"
+ "\x10\x86\x40\x16\x72\x9c\x52\xdd\x65\x24\xc8\xa9\xc3\xb4\x48\x9f";
+
+static const char kSPKIHash_Tor1[] =
+ "\x6d\x8c\xfd\x25\x30\xe4\xf3\xd5\xf7\xaa\xed\xdf\x82\xcc\x06\xfa"
+ "\x50\x50\xb2\x8e\x6f\x23\x43\x75\x7f\x44\x71\xe2\x0a\x38\x9c\xba";
+
+static const char kSPKIHash_Tor2[] =
+ "\xc5\x70\xb1\x85\x37\x67\xee\xec\x57\x9d\xe2\x52\x6d\x00\xaa\xa0"
+ "\x0b\xee\x5b\x76\x6d\x42\x5d\xa9\x0d\x54\xdf\xda\xc7\xb0\x4b\xcc";
+
+static const char kSPKIHash_Tor3[] =
+ "\x0a\x57\x82\xd6\xac\x14\x47\xc2\x4f\x80\x7d\x67\x5e\xf4\x9e\xd9"
+ "\x51\xf1\x0d\xee\x7f\x29\xf3\x6c\xf7\xa1\x2e\xb1\xb7\xd2\x39\xfa";
+
static const char kSPKIHash_TrustedCertificateServices[] =
"\xe2\xd8\x91\xef\xb7\x38\x66\x91\x05\xd5\x30\xde\x5e\xd7\x2e\x2b"
"\x2a\xc3\xf4\xa6\x70\x78\xb5\x34\x9b\x3f\xda\xca\x49\x6f\x5e\xb8";
+static const char kSPKIHash_Twitter1[] =
+ "\xbd\x4f\x4c\xe3\xc2\xf3\x0f\xf0\x85\xdf\x8c\x04\xe4\xf3\xdf\xe2"
+ "\x70\x70\x47\x2a\x2c\xcb\x4e\x97\xdb\x52\x74\x6a\x9f\x32\x4b\x9b";
+
static const char kSPKIHash_UTNDATACorpSGC[] =
"\x40\x02\xfc\xd3\x11\xd0\x73\x31\x56\x7e\x71\xbc\xd9\x71\xe4\x60"
"\x48\xc8\xdc\xe8\xd1\x65\x97\x11\x75\x3b\x3d\xaa\x2a\x26\x9a\xfa";
@@ -471,77 +529,45 @@ static const char kSPKIHash_UTNUSERFirstObject[] =
"\x0f\xe1\x4c\x26\x4b\x17\xbb\x6f\x0d\x65\x3e\x7a\x70\xeb\x36\x3d"
"\xbf\x54\xbe\x15\x80\x39\xed\xda\xe5\xc2\x57\x11\xdf\x48\xc1\x03";
-static const char kSPKIHash_GTECyberTrustGlobalRoot[] =
- "\x10\x69\xfa\x47\xa0\xaa\x4f\x8c\xf7\x11\x1b\x1c\xae\xa3\x65\xee"
- "\xae\xd1\x0b\xff\xf3\x26\x60\xde\xf6\xe0\x61\x4b\xfa\xe7\x08\x75";
-
-static const char kSPKIHash_BaltimoreCyberTrustRoot[] =
- "\x63\xd9\xaf\x9b\x47\xb1\x06\x4d\x49\xa1\x0e\x7b\x7f\xd5\x66\xdb"
- "\xc8\xca\xa3\x99\x45\x9b\xfc\x28\x29\xc5\x71\xad\x8c\x6e\xf3\x4a";
-
-static const char kSPKIHash_GlobalSignRootCA[] =
- "\x2b\xce\xe8\x58\x15\x8c\xf5\x46\x5f\xc9\xd7\x6f\x0d\xfa\x31\x2f"
- "\xef\x25\xa4\xdc\xa8\x50\x1d\xa9\xb4\x6b\x67\xd1\xfb\xfa\x1b\x64";
-
-static const char kSPKIHash_GlobalSignRootCA_R2[] =
- "\x8a\x27\xb5\x55\x7b\x4b\xec\x7c\xc0\x30\x5f\xbf\x3d\x53\xd1\xf7"
- "\x1c\xd3\xf3\x49\x10\xc5\xd6\x5e\x27\xec\xdd\xb8\x20\x77\xba\x3d";
-
-static const char kSPKIHash_GlobalSignRootCA_R3[] =
- "\x70\x6b\xb1\x01\x7c\x85\x5c\x59\x16\x9b\xad\x5c\x17\x81\xcf\x59"
- "\x7f\x12\xd2\xca\xd2\xf6\x3d\x1a\x4a\xa3\x74\x93\x80\x0f\xfb\x80";
-
-static const char kSPKIHash_EntrustRootEC1[] =
- "\xfe\xa2\xb7\xd6\x45\xfb\xa7\x3d\x75\x3c\x1e\xc9\xa7\x87\x0c\x40"
- "\xe1\xf7\xb0\xc5\x61\xe9\x27\xb9\x85\xbf\x71\x18\x66\xe3\x6f\x22";
-
-static const char kSPKIHash_TheGoDaddyGroupClass2[] =
- "\x56\x32\xd9\x7b\xfa\x77\x5b\xf3\xc9\x9d\xde\xa5\x2f\xc2\x55\x34"
- "\x10\x86\x40\x16\x72\x9c\x52\xdd\x65\x24\xc8\xa9\xc3\xb4\x48\x9f";
-
-static const char kSPKIHash_GoDaddyRoot_G2[] =
- "\x2a\x8f\x2d\x8a\xf0\xeb\x12\x38\x98\xf7\x4c\x86\x6a\xc3\xfa\x66"
- "\x90\x54\xe2\x3c\x17\xbc\x7a\x95\xbd\x02\x34\x19\x2d\xc6\x35\xd0";
-
-static const char kSPKIHash_GoDaddySecure[] =
- "\x32\xb6\x4b\x66\x72\x7a\x20\x63\xe4\x06\x6f\x3b\x95\x8c\xb0\xaa"
- "\xee\x57\x6a\x5e\xce\xfd\x95\x33\x99\xbb\x88\x74\x73\x1d\x95\x87";
+static const char kSPKIHash_VeriSignClass1[] =
+ "\x2d\xc9\x47\x0b\xe6\x3e\xf4\xac\xf1\xbd\x82\x86\x09\x40\x2b\xb7"
+ "\xb8\x7b\xd9\x96\x38\xa6\x43\x93\x4e\x88\x68\x2d\x1b\xe8\xc3\x08";
-static const char kSPKIHash_ThawtePremiumServer[] =
- "\xf5\x3c\x22\x05\x98\x17\xdd\x96\xf4\x00\x65\x16\x39\xd2\xf8\x57"
- "\xe2\x10\x70\xa5\x9a\xbe\xd9\x07\x94\x00\xd9\xf6\x95\x50\x69\x00";
+static const char kSPKIHash_VeriSignClass1_G3[] =
+ "\x22\x07\x6e\x5a\xef\x44\xbb\x9a\x41\x6a\x28\xb7\xd1\xc4\x43\x22"
+ "\xd7\x05\x9f\x60\xfe\xff\xa5\xca\xf6\xc5\xbe\x84\x47\x89\x13\x03";
-static const char kSPKIHash_ThawtePrimaryRootCA_G2[] =
- "\x67\xdc\x4f\x32\xfa\x10\xe7\xd0\x1a\x79\xa0\x73\xaa\x0c\x9e\x02"
- "\x12\xec\x2f\xfc\x3d\x77\x9e\x0a\xa7\xf9\xc0\xf0\xe1\xc2\xc8\x93";
+static const char kSPKIHash_VeriSignClass2_G2[] =
+ "\xda\x80\x0b\x80\xb2\xa8\x7d\x39\x9e\x66\xfa\x19\xd7\x2f\xdf\x49"
+ "\x98\x3b\x47\xd8\xcf\x32\x2c\x7c\x79\x50\x3a\x0c\x7e\x28\xfe\xaf";
-static const char kSPKIHash_ThawtePrimaryRootCA_G3[] =
- "\x19\x06\xc6\x12\x4d\xbb\x43\x85\x78\xd0\x0e\x06\x6d\x50\x54\xc6"
- "\xc3\x7f\x0f\xa6\x02\x8c\x05\x54\x5e\x09\x94\xed\xda\xec\x86\x29";
+static const char kSPKIHash_VeriSignClass2_G3[] =
+ "\x70\x06\xa3\x83\x11\xe5\x8f\xb1\x93\x48\x42\x33\x21\x82\x10\xc6"
+ "\x61\x25\xa0\xe4\xa8\x26\xae\xd5\x39\xac\x56\x1d\xfb\xfb\xd9\x03";
-static const char kSPKIHash_ThawtePrimaryRootCA[] =
- "\x1d\x75\xd0\x83\x1b\x9e\x08\x85\x39\x4d\x32\xc7\xa1\xbf\xdb\x3d"
- "\xbc\x1c\x28\xe2\xb0\xe8\x39\x1f\xb1\x35\x98\x1d\xbc\x5b\xa9\x36";
+static const char kSPKIHash_VeriSignClass3_G2[] =
+ "\x02\x3c\x81\xcc\xe8\xe7\xc6\x4f\xa9\x42\xd3\xc1\x50\x48\x70\x7d"
+ "\x35\xd9\xbb\x5b\x87\xf4\xf5\x44\xc5\xbf\x1b\xc5\x64\x3a\xf2\xfa";
-static const char kSPKIHash_SymantecClass3EVG3[] =
- "\x80\xcc\x56\x3a\xb5\xf8\x3c\xc4\x1e\xb0\xaf\x6a\x14\xd6\xd8\x07"
- "\x18\xc1\x7e\x35\x2f\x96\x49\xff\xbc\xdd\x67\xf8\xbf\x65\x13\x91";
+static const char kSPKIHash_VeriSignClass3_G3[] =
+ "\x49\x5a\x96\xba\x6b\xad\x78\x24\x07\xbd\x52\x1a\x00\xba\xce\x65"
+ "\x7b\xb3\x55\x55\x5e\x4b\xb7\xf8\x14\x6c\x71\xbb\xa5\x7e\x7a\xce";
-static const char kSPKIHash_DigiCertECCSecureServerCA[] =
- "\x3d\x95\xcd\xde\x54\x40\xcb\xef\x2d\x04\xa9\x36\x3b\x1e\x85\xee"
- "\x32\x25\x9f\x3a\xf6\x63\x39\xb0\xa9\xcd\xc9\x9f\x27\xd7\xa0\x2c";
+static const char kSPKIHash_VeriSignClass3_G4[] =
+ "\x51\x92\x43\x8e\xc3\x69\xd7\xee\x0c\xe7\x1f\x5c\x6d\xb7\x5f\x94"
+ "\x1e\xfb\xf7\x2e\x58\x44\x17\x15\xe9\x9e\xab\x04\xc2\xc8\xac\xee";
-static const char kSPKIHash_FacebookBackup[] =
- "\xab\x83\xce\xd8\x6d\x9c\x6e\x46\x61\x67\xcd\xbe\x26\x09\x91\x53"
- "\x21\x8c\xa0\x07\xa8\xcc\x0f\x81\x49\x75\x57\x41\x60\x7c\x5d\x64";
+static const char kSPKIHash_VeriSignClass3_G5[] =
+ "\x25\xb4\x1b\x50\x6e\x49\x30\x95\x28\x23\xa6\xeb\x9f\x1d\x31\xde"
+ "\xf6\x45\xea\x38\xa5\xc6\xc6\xa9\x6d\x71\x95\x7e\x38\x4d\xf0\x58";
-static const char kSPKIHash_SpiderOak2[] =
- "\xed\x8d\xd4\x9f\x16\xdf\x7c\xbf\x1a\x14\xf5\xec\x38\x90\x69\x19"
- "\xab\x20\xa4\x39\xa7\x82\x92\x21\x03\x11\x8a\x75\x04\x64\x95\x04";
+static const char kSPKIHash_VeriSignClass4_G3[] =
+ "\x56\x7b\x82\x11\xfd\x20\xd3\xd2\x83\xee\x0c\xd7\xce\x06\x72\xcb"
+ "\x9d\x99\xbc\x5b\x48\x7a\x58\xc9\xd5\x4e\xc6\x7f\x77\xd4\xa8\xf5";
-static const char kSPKIHash_SpiderOak3[] =
- "\x2e\x41\x11\xe7\x8b\xce\x76\x5c\xa0\xa5\x3b\x1b\x62\xf9\x69\x32"
- "\xad\x42\x13\xf9\x43\x00\x6d\x40\x3f\xdc\x66\x76\xdc\x2f\x57\x60";
+static const char kSPKIHash_VeriSignUniversal[] =
+ "\x96\x7b\x0c\xd9\x3f\xce\xf7\xf2\x7c\xe2\xc2\x45\x76\x7a\xe9\xb0"
+ "\x5a\x77\x6b\x06\x49\xf9\x96\x5b\x62\x90\x96\x84\x69\x68\x68\x72";
static const char kSPKIHash_YahooBackup1[] =
"\xd9\xf4\x40\x51\x7c\xb1\x97\x80\x35\xfd\x71\xeb\x28\xd0\x66\x73"
@@ -551,42 +577,19 @@ static const char kSPKIHash_YahooBackup2[] =
"\x76\x89\x67\x6e\xdc\xc4\x06\x71\x0b\xc7\xff\x65\x38\x44\x36\xd9"
"\xee\x8e\x64\xef\xd0\x35\xbe\x95\x49\x25\xf6\x5c\x70\x37\x13\xb0";
-static const char kSPKIHash_LetsEncryptAuthorityPrimary_X1_X3[] =
- "\x60\xb8\x75\x75\x44\x7d\xcb\xa2\xa3\x6b\x7d\x11\xac\x09\xfb\x24"
- "\xa9\xdb\x40\x6f\xee\x12\xd2\xcc\x90\x18\x05\x17\x61\x6e\x8a\x18";
-
-static const char kSPKIHash_LetsEncryptAuthorityBackup_X2_X4[] =
- "\xb1\x11\xdd\x8a\x1c\x20\x91\xa8\x9b\xd4\xfd\x60\xc5\x7f\x07\x16"
- "\xcc\xe5\x0f\xee\xff\x81\x37\xcd\xbe\xe0\x32\x6e\x02\xcf\x36\x2b";
-
-static const char kSPKIHash_DSTRootCAX3[] =
- "\x56\x3b\x3c\xaf\x8c\xfe\xf3\x4c\x23\x35\xca\xf5\x60\xa7\xa9\x59"
- "\x06\xe8\x48\x84\x62\xeb\x75\xac\x59\x78\x48\x30\xdf\x9e\x5b\x2b";
-
-static const char kSPKIHash_Swehack[] =
- "\x15\xd6\x9f\x7c\x4e\xfd\xf6\xb5\x5b\xde\x8c\x80\xba\x12\x76\x98"
- "\x15\xbf\x5c\x9c\x03\xd3\xb5\x1a\x8d\xbd\x86\xe9\x8c\x12\x00\x4c";
-
-static const char kSPKIHash_SwehackBackup[] =
- "\xcf\xa7\x2e\xb3\x00\x3a\x13\x5b\xe0\x16\x40\xa3\x52\xc6\xc4\x62"
- "\x8d\x0b\x7f\x76\x8f\xf0\xcf\x18\x3a\xfc\x24\xa2\x21\xb3\x0c\x2a";
-
-static const char kSPKIHash_COMODORSADomainValidationSecureServerCA[] =
- "\x92\x53\xb6\xde\x74\xf6\x7a\x11\x43\x5c\x27\xf1\xdd\xe1\xd3\x0d"
- "\x11\x12\x33\x3d\xda\xb2\x3d\x66\xb8\xef\xb8\x68\x87\x63\x8a\xe6";
-
static const char* const kExpectCTReportURIs[] = {
"https://clients3.google.com/ct_upload",
"https://log.getdropbox.com/log/expectct",
+ NULL,
};
+
static const char* const kExpectStapleReportURIs[] = {
"https://report.badssl.com/expect-staple",
"https://log.getdropbox.com/log/ocsp_expect_staple",
"https://reporting.caddyserver.com/expect-staple",
"https://asac.casa/expectstaple.jsp",
+ NULL,
};
-// The following is static data describing the hosts that are hardcoded with
-// certificate pins or HSTS information.
// kNoRejectedPublicKeys is a placeholder for when no public keys are rejected.
static const char* const kNoRejectedPublicKeys[] = {
@@ -596,10 +599,37 @@ static const char* const kNoRejectedPublicKeys[] = {
// kNoReportURI is a placeholder for when a pinset does not have a report URI.
static const char kNoReportURI[] = "";
-static const char* const kTestAcceptableCerts[] = {
- kSPKIHash_TestSPKI,
+static const char* const kDropboxAcceptableCerts[] = {
+ kSPKIHash_DigiCertAssuredIDRoot,
+ kSPKIHash_DigiCertGlobalRoot,
+ kSPKIHash_DigiCertEVRoot,
+ kSPKIHash_EntrustRootEC1,
+ kSPKIHash_Entrust_G2,
+ kSPKIHash_Entrust_EV,
+ kSPKIHash_Entrust_2048,
+ kSPKIHash_GeoTrustGlobal,
+ kSPKIHash_GeoTrustPrimary_G2,
+ kSPKIHash_GeoTrustPrimary_G3,
+ kSPKIHash_GeoTrustPrimary,
+ kSPKIHash_TheGoDaddyGroupClass2,
+ kSPKIHash_GoDaddyRoot_G2,
+ kSPKIHash_GoDaddySecure,
+ kSPKIHash_ThawtePremiumServer,
+ kSPKIHash_ThawtePrimaryRootCA_G2,
+ kSPKIHash_ThawtePrimaryRootCA_G3,
+ kSPKIHash_ThawtePrimaryRootCA,
NULL,
};
+static const char kDropboxReportURI[] = "https://log.getdropbox.com/hpkp";
+
+static const char* const kFacebookAcceptableCerts[] = {
+ kSPKIHash_SymantecClass3EVG3,
+ kSPKIHash_DigiCertECCSecureServerCA,
+ kSPKIHash_DigiCertEVRoot,
+ kSPKIHash_FacebookBackup,
+ NULL,
+};
+
static const char* const kGoogleAcceptableCerts[] = {
kSPKIHash_GoogleBackup2048,
kSPKIHash_GoogleG2,
@@ -608,41 +638,56 @@ static const char* const kGoogleAcceptableCerts[] = {
NULL,
};
static const char kGoogleReportURI[] = "http://clients3.google.com/cert_upload_json";
-static const char* const kTorAcceptableCerts[] = {
- kSPKIHash_RapidSSL,
- kSPKIHash_DigiCertEVRoot,
- kSPKIHash_Tor1,
- kSPKIHash_Tor2,
- kSPKIHash_Tor3,
+
+static const char* const kNightxAcceptableCerts[] = {
kSPKIHash_LetsEncryptAuthorityPrimary_X1_X3,
kSPKIHash_LetsEncryptAuthorityBackup_X2_X4,
- NULL,
-};
-static const char* const kTwitterComAcceptableCerts[] = {
- kSPKIHash_VeriSignClass1,
kSPKIHash_VeriSignClass3_G4,
- kSPKIHash_VeriSignClass4_G3,
- kSPKIHash_VeriSignClass3_G3,
- kSPKIHash_VeriSignClass1_G3,
- kSPKIHash_VeriSignClass2_G3,
- kSPKIHash_VeriSignClass3_G2,
- kSPKIHash_VeriSignClass2_G2,
kSPKIHash_VeriSignClass3_G5,
kSPKIHash_VeriSignUniversal,
- kSPKIHash_GeoTrustGlobal,
- kSPKIHash_GeoTrustGlobal2,
- kSPKIHash_GeoTrustUniversal,
- kSPKIHash_GeoTrustUniversal2,
- kSPKIHash_GeoTrustPrimary,
- kSPKIHash_GeoTrustPrimary_G2,
- kSPKIHash_GeoTrustPrimary_G3,
kSPKIHash_DigiCertGlobalRoot,
kSPKIHash_DigiCertEVRoot,
kSPKIHash_DigiCertAssuredIDRoot,
- kSPKIHash_Twitter1,
+ kSPKIHash_COMODOCertificationAuthority,
+ kSPKIHash_AddTrustExternalCARoot,
NULL,
};
-static const char kTwitterComReportURI[] = "http://l.twimg.com/i/hpkp_report";
+static const char kNightxReportURI[] = "http://l.nightx.uk/report/hpkp";
+
+static const char* const kSpideroakAcceptableCerts[] = {
+ kSPKIHash_GeoTrustGlobal,
+ kSPKIHash_DigiCertEVRoot,
+ kSPKIHash_SpiderOak2,
+ kSPKIHash_SpiderOak3,
+ NULL,
+};
+
+static const char* const kSwehackComAcceptableCerts[] = {
+ kSPKIHash_Swehack,
+ kSPKIHash_LetsEncryptAuthorityPrimary_X1_X3,
+ kSPKIHash_LetsEncryptAuthorityBackup_X2_X4,
+ kSPKIHash_DSTRootCAX3,
+ kSPKIHash_SwehackBackup,
+ kSPKIHash_COMODORSADomainValidationSecureServerCA,
+ NULL,
+};
+
+static const char* const kTestAcceptableCerts[] = {
+ kSPKIHash_TestSPKI,
+ NULL,
+};
+
+static const char* const kTorAcceptableCerts[] = {
+ kSPKIHash_RapidSSL,
+ kSPKIHash_DigiCertEVRoot,
+ kSPKIHash_Tor1,
+ kSPKIHash_Tor2,
+ kSPKIHash_Tor3,
+ kSPKIHash_LetsEncryptAuthorityPrimary_X1_X3,
+ kSPKIHash_LetsEncryptAuthorityBackup_X2_X4,
+ NULL,
+};
+
static const char* const kTwitterCDNAcceptableCerts[] = {
kSPKIHash_VeriSignClass1,
kSPKIHash_VeriSignClass3_G4,
@@ -689,42 +734,33 @@ static const char* const kTwitterCDNAcceptableCerts[] = {
NULL,
};
static const char kTwitterCDNReportURI[] = "http://l.twimg.com/i/hpkp_report";
-static const char* const kDropboxAcceptableCerts[] = {
- kSPKIHash_DigiCertAssuredIDRoot,
- kSPKIHash_DigiCertGlobalRoot,
- kSPKIHash_DigiCertEVRoot,
- kSPKIHash_EntrustRootEC1,
- kSPKIHash_Entrust_G2,
- kSPKIHash_Entrust_EV,
- kSPKIHash_Entrust_2048,
+
+static const char* const kTwitterComAcceptableCerts[] = {
+ kSPKIHash_VeriSignClass1,
+ kSPKIHash_VeriSignClass3_G4,
+ kSPKIHash_VeriSignClass4_G3,
+ kSPKIHash_VeriSignClass3_G3,
+ kSPKIHash_VeriSignClass1_G3,
+ kSPKIHash_VeriSignClass2_G3,
+ kSPKIHash_VeriSignClass3_G2,
+ kSPKIHash_VeriSignClass2_G2,
+ kSPKIHash_VeriSignClass3_G5,
+ kSPKIHash_VeriSignUniversal,
kSPKIHash_GeoTrustGlobal,
+ kSPKIHash_GeoTrustGlobal2,
+ kSPKIHash_GeoTrustUniversal,
+ kSPKIHash_GeoTrustUniversal2,
+ kSPKIHash_GeoTrustPrimary,
kSPKIHash_GeoTrustPrimary_G2,
kSPKIHash_GeoTrustPrimary_G3,
- kSPKIHash_GeoTrustPrimary,
- kSPKIHash_TheGoDaddyGroupClass2,
- kSPKIHash_GoDaddyRoot_G2,
- kSPKIHash_GoDaddySecure,
- kSPKIHash_ThawtePremiumServer,
- kSPKIHash_ThawtePrimaryRootCA_G2,
- kSPKIHash_ThawtePrimaryRootCA_G3,
- kSPKIHash_ThawtePrimaryRootCA,
- NULL,
-};
-static const char kDropboxReportURI[] = "https://log.getdropbox.com/hpkp";
-static const char* const kFacebookAcceptableCerts[] = {
- kSPKIHash_SymantecClass3EVG3,
- kSPKIHash_DigiCertECCSecureServerCA,
- kSPKIHash_DigiCertEVRoot,
- kSPKIHash_FacebookBackup,
- NULL,
-};
-static const char* const kSpideroakAcceptableCerts[] = {
- kSPKIHash_GeoTrustGlobal,
+ kSPKIHash_DigiCertGlobalRoot,
kSPKIHash_DigiCertEVRoot,
- kSPKIHash_SpiderOak2,
- kSPKIHash_SpiderOak3,
+ kSPKIHash_DigiCertAssuredIDRoot,
+ kSPKIHash_Twitter1,
NULL,
};
+static const char kTwitterComReportURI[] = "http://l.twimg.com/i/hpkp_report";
+
static const char* const kYahooAcceptableCerts[] = {
kSPKIHash_VeriSignClass2_G2,
kSPKIHash_VeriSignClass2_G3,
@@ -743,29 +779,6 @@ static const char* const kYahooAcceptableCerts[] = {
kSPKIHash_YahooBackup2,
NULL,
};
-static const char* const kSwehackComAcceptableCerts[] = {
- kSPKIHash_Swehack,
- kSPKIHash_LetsEncryptAuthorityPrimary_X1_X3,
- kSPKIHash_LetsEncryptAuthorityBackup_X2_X4,
- kSPKIHash_DSTRootCAX3,
- kSPKIHash_SwehackBackup,
- kSPKIHash_COMODORSADomainValidationSecureServerCA,
- NULL,
-};
-static const char* const kNightxAcceptableCerts[] = {
- kSPKIHash_LetsEncryptAuthorityPrimary_X1_X3,
- kSPKIHash_LetsEncryptAuthorityBackup_X2_X4,
- kSPKIHash_VeriSignClass3_G4,
- kSPKIHash_VeriSignClass3_G5,
- kSPKIHash_VeriSignUniversal,
- kSPKIHash_DigiCertGlobalRoot,
- kSPKIHash_DigiCertEVRoot,
- kSPKIHash_DigiCertAssuredIDRoot,
- kSPKIHash_COMODOCertificationAuthority,
- kSPKIHash_AddTrustExternalCARoot,
- NULL,
-};
-static const char kNightxReportURI[] = "http://l.nightx.uk/report/hpkp";
struct Pinset {
const char* const* const accepted_pins;
@@ -774,17 +787,17 @@ struct Pinset {
};
static const struct Pinset kPinsets[] = {
- {kTestAcceptableCerts, kNoRejectedPublicKeys, kNoReportURI},
- {kGoogleAcceptableCerts, kNoRejectedPublicKeys, kGoogleReportURI},
- {kTorAcceptableCerts, kNoRejectedPublicKeys, kNoReportURI},
- {kTwitterComAcceptableCerts, kNoRejectedPublicKeys, kTwitterComReportURI},
- {kTwitterCDNAcceptableCerts, kNoRejectedPublicKeys, kTwitterCDNReportURI},
{kDropboxAcceptableCerts, kNoRejectedPublicKeys, kDropboxReportURI},
{kFacebookAcceptableCerts, kNoRejectedPublicKeys, kNoReportURI},
+ {kGoogleAcceptableCerts, kNoRejectedPublicKeys, kGoogleReportURI},
+ {kNightxAcceptableCerts, kNoRejectedPublicKeys, kNightxReportURI},
{kSpideroakAcceptableCerts, kNoRejectedPublicKeys, kNoReportURI},
- {kYahooAcceptableCerts, kNoRejectedPublicKeys, kNoReportURI},
{kSwehackComAcceptableCerts, kNoRejectedPublicKeys, kNoReportURI},
- {kNightxAcceptableCerts, kNoRejectedPublicKeys, kNightxReportURI},
+ {kTestAcceptableCerts, kNoRejectedPublicKeys, kNoReportURI},
+ {kTorAcceptableCerts, kNoRejectedPublicKeys, kNoReportURI},
+ {kTwitterCDNAcceptableCerts, kNoRejectedPublicKeys, kTwitterCDNReportURI},
+ {kTwitterComAcceptableCerts, kNoRejectedPublicKeys, kTwitterComReportURI},
+ {kYahooAcceptableCerts, kNoRejectedPublicKeys, kNoReportURI},
};
// kHSTSHuffmanTree describes a Huffman tree. The nodes of the tree are pairs
@@ -793,13691 +806,15539 @@ static const struct Pinset kPinsets[] = {
// uint8_t value has the MSB set then it represents a literal leaf value.
// Otherwise it's a pointer to the n'th element of the array.
static const uint8_t kHSTSHuffmanTree[] = {
- 0xb1, 0xb2, 0xc1, 0xb7, 0x01, 0xb5, 0xb6, 0x02, 0x03, 0xf1, 0x00, 0x04,
- 0xfa, 0x05, 0x06, 0xf7, 0xf0, 0x07, 0xf5, 0xe4, 0x08, 0x09, 0xf9, 0xe6,
- 0x0b, 0xed, 0xf2, 0x0c, 0x0a, 0x0d, 0xef, 0xe9, 0x80, 0x0f, 0x0e, 0x10,
- 0xb8, 0xb9, 0xb3, 0x12, 0xb4, 0xb0, 0x13, 0x14, 0xae, 0x15, 0xf8, 0xea,
- 0x16, 0x17, 0xeb, 0x18, 0xe3, 0x19, 0x1a, 0xe1, 0x1b, 0xff, 0xe2, 0xe7,
- 0xec, 0x1d, 0xe5, 0x1e, 0xf6, 0xad, 0x20, 0xe8, 0xf3, 0x21, 0xf4, 0xee,
- 0x22, 0x23, 0x1f, 0x24, 0x1c, 0x25, 0x11, 0x26,
+ 0xf7, 0xf9, 0xf0, 0x00, 0xf5, 0xe4, 0x01, 0x02, 0xad, 0xe6, 0x04, 0xed,
+ 0xf2, 0x05, 0x03, 0x06, 0xef, 0xe9, 0x80, 0x08, 0x07, 0x09, 0xb8, 0xb9,
+ 0xb3, 0x0b, 0xb4, 0xb0, 0x0c, 0x0d, 0xae, 0x0e, 0xf8, 0xea, 0x0f, 0x10,
+ 0xeb, 0x11, 0xe3, 0x12, 0x13, 0xe1, 0x14, 0xff, 0xe2, 0xe7, 0xec, 0x16,
+ 0xe5, 0x17, 0xb1, 0xb2, 0xc1, 0xb7, 0x1a, 0xb5, 0xb6, 0x1b, 0x1c, 0xf1,
+ 0x19, 0x1d, 0xfa, 0x1e, 0xf6, 0x1f, 0xe8, 0x20, 0xf3, 0x21, 0xf4, 0xee,
+ 0x22, 0x23, 0x18, 0x24, 0x15, 0x25, 0x0a, 0x26,
};
static const uint8_t kPreloadedHSTSData[] = {
- 0xf6, 0xec, 0xdb, 0xaa, 0x22, 0x52, 0xf3, 0x77, 0xf5, 0x8a, 0xd1, 0xe7,
+ 0xf6, 0xec, 0xdb, 0xaa, 0x42, 0x52, 0xf3, 0x75, 0xf5, 0x8a, 0xd1, 0xe7,
0x9c, 0xc6, 0xf7, 0xdf, 0x4b, 0x17, 0xfe, 0x6e, 0x63, 0xea, 0x47, 0xbc,
- 0xac, 0x5f, 0xb5, 0x9e, 0xef, 0x65, 0x8b, 0x9a, 0x11, 0x87, 0xd3, 0x87,
- 0xd7, 0xf1, 0x0a, 0x2f, 0xb4, 0x4b, 0x17, 0xfc, 0xe3, 0xc2, 0x83, 0xfc,
- 0x4b, 0x16, 0x8c, 0xc4, 0xcf, 0xe2, 0x22, 0x3c, 0x21, 0xb8, 0x5f, 0xe3,
- 0x0b, 0xa3, 0x73, 0x56, 0x2e, 0x00, 0x96, 0x2f, 0x40, 0xa3, 0xd6, 0x2e,
- 0xef, 0xcb, 0x17, 0xff, 0xd3, 0xf9, 0x81, 0x31, 0xbd, 0xc2, 0x73, 0xcb,
- 0x17, 0xfd, 0x87, 0xef, 0xcf, 0xfc, 0x08, 0xb1, 0x6e, 0x2c, 0x50, 0xcf,
- 0x39, 0x8f, 0x2f, 0x84, 0x10, 0x72, 0xb1, 0x7f, 0xf1, 0x66, 0xda, 0x92,
- 0x76, 0xee, 0x0b, 0x15, 0x04, 0xd0, 0x46, 0x32, 0xf0, 0x9e, 0xf9, 0x0f,
- 0x89, 0x6f, 0xe0, 0xca, 0x7d, 0xf7, 0x58, 0xbc, 0x5d, 0xf1, 0x62, 0xb0,
- 0xf3, 0x04, 0x5d, 0x77, 0x8c, 0x58, 0xb9, 0x9d, 0x62, 0xff, 0x46, 0x66,
- 0xcf, 0x22, 0x65, 0x8a, 0xc3, 0xe5, 0xf8, 0xc8, 0x5c, 0x5a, 0xff, 0xf0,
- 0x82, 0xfc, 0xdf, 0xef, 0xf9, 0xcd, 0x41, 0x62, 0xff, 0xee, 0x3f, 0x42,
- 0xc0, 0x0b, 0x9f, 0x12, 0xc5, 0xff, 0x30, 0x18, 0xbb, 0xf7, 0xe5, 0x62,
- 0xff, 0xfb, 0xee, 0x26, 0xee, 0x1a, 0xce, 0xe0, 0xe7, 0x58, 0xbf, 0xdf,
- 0x32, 0x2e, 0x3f, 0x61, 0xac, 0x5b, 0xb5, 0x8a, 0x94, 0x4f, 0x62, 0x93,
- 0x1c, 0xd4, 0xa7, 0x37, 0x8a, 0x0e, 0x8e, 0x50, 0xd7, 0xbf, 0xe0, 0x70,
- 0x7f, 0x68, 0x67, 0x16, 0x2f, 0xfe, 0x6e, 0x84, 0x26, 0x30, 0x7f, 0x73,
- 0x56, 0x2f, 0xe7, 0x93, 0x94, 0xc4, 0xb1, 0x7f, 0x4c, 0x9c, 0xa6, 0x25,
- 0x8b, 0xe9, 0x21, 0x73, 0xe7, 0xb5, 0xc2, 0xda, 0x94, 0xc5, 0x1c, 0xeb,
- 0xf0, 0xa2, 0xb1, 0x2c, 0x5f, 0xe8, 0x16, 0x74, 0x2c, 0xe2, 0xc5, 0x61,
- 0xe2, 0xb0, 0x8d, 0xff, 0xc2, 0x3f, 0xcb, 0x3b, 0xf1, 0x37, 0xd6, 0x2f,
- 0xff, 0xd0, 0x26, 0xf3, 0x1f, 0x92, 0x39, 0xfc, 0xc1, 0x62, 0xb8, 0x89,
- 0x93, 0x11, 0x6e, 0xce, 0x2c, 0x5e, 0x66, 0xdd, 0x51, 0x16, 0x95, 0x03,
- 0xe5, 0xc2, 0x4d, 0xc5, 0xef, 0xff, 0xef, 0xb6, 0x13, 0x7b, 0x9c, 0xdf,
- 0xef, 0xd2, 0x78, 0xb1, 0x7d, 0xe2, 0x63, 0x56, 0x2f, 0xd3, 0xac, 0xef,
- 0xcb, 0x16, 0x7d, 0x22, 0xa7, 0xeb, 0xa0, 0x23, 0xbd, 0x1e, 0x43, 0x58,
- 0xbf, 0x39, 0xbe, 0xd4, 0xac, 0x5b, 0x8b, 0x17, 0xe6, 0x3f, 0xa6, 0x0b,
- 0x17, 0x8d, 0xc1, 0xac, 0x56, 0x8f, 0x61, 0x84, 0x84, 0x51, 0x7f, 0xff,
- 0xdf, 0xcd, 0x4f, 0x43, 0x34, 0xc0, 0xcd, 0x69, 0xcd, 0x9d, 0x2c, 0x5f,
- 0x83, 0x9e, 0x8d, 0xf5, 0x8b, 0xfd, 0xe6, 0x3b, 0x41, 0xb4, 0xb1, 0x52,
- 0x7b, 0xce, 0x57, 0x7b, 0x86, 0x79, 0x62, 0xa0, 0xb8, 0xf4, 0x37, 0x9d,
- 0x46, 0x3d, 0xf8, 0x6c, 0x31, 0xa9, 0x10, 0x72, 0x10, 0x3e, 0x2e, 0xe9,
- 0x0c, 0x83, 0x08, 0x2e, 0xf7, 0x96, 0x2f, 0xff, 0x85, 0xee, 0x0f, 0xf3,
- 0xc9, 0xf8, 0xa7, 0x8b, 0x17, 0xff, 0xcd, 0xfc, 0x2d, 0x6b, 0x3b, 0x87,
- 0x9c, 0xeb, 0x15, 0x04, 0x5c, 0x9a, 0x30, 0x25, 0x1b, 0xb7, 0x95, 0x8b,
- 0xbf, 0x8b, 0x17, 0xc7, 0x70, 0xf8, 0xb1, 0x7f, 0xff, 0xfb, 0x32, 0x28,
- 0x99, 0xb6, 0xe7, 0xf3, 0xa6, 0x0f, 0xf3, 0xc1, 0x8d, 0x96, 0x2f, 0xff,
- 0x1a, 0xfa, 0xf7, 0x7b, 0xbe, 0x07, 0x0d, 0x96, 0x28, 0xe8, 0xef, 0x01,
- 0x27, 0x9e, 0xef, 0xf9, 0x8c, 0x2c, 0x8b, 0x52, 0x1a, 0xc5, 0x39, 0xf5,
- 0x88, 0xc2, 0xe2, 0x0d, 0x62, 0xb1, 0x3c, 0x2d, 0xc6, 0x3f, 0x1b, 0x88,
- 0x64, 0x37, 0xf1, 0xdf, 0xbe, 0x4f, 0x6b, 0x17, 0xfe, 0xc2, 0xf0, 0x98,
- 0x7c, 0x93, 0x56, 0x2f, 0xf4, 0x87, 0xc0, 0x7b, 0xdd, 0xac, 0x54, 0x9f,
- 0xb7, 0x8f, 0xef, 0xe9, 0x1f, 0x7c, 0x98, 0x96, 0x2a, 0x51, 0xef, 0x08,
- 0x53, 0x70, 0x86, 0xe6, 0xe8, 0xb1, 0x7d, 0x3b, 0x9c, 0x4b, 0x14, 0xe6,
- 0xf4, 0x86, 0x6e, 0x7f, 0xac, 0x50, 0xcd, 0xb7, 0x41, 0xfb, 0xf7, 0x63,
- 0xd3, 0x41, 0x62, 0xff, 0x08, 0x05, 0x9b, 0x19, 0x05, 0x8b, 0xc2, 0x9d,
- 0x96, 0x2f, 0x9f, 0x4d, 0x05, 0x8b, 0xd3, 0xee, 0x1c, 0xf0, 0x3e, 0x3d,
- 0x52, 0x8d, 0x3f, 0x95, 0x13, 0xb5, 0xff, 0x8b, 0xdf, 0xc8, 0x07, 0x3d,
- 0xf1, 0x62, 0xff, 0xbb, 0xe7, 0x9f, 0x6d, 0x9f, 0xcb, 0x17, 0xff, 0xb6,
- 0x1e, 0x9b, 0x72, 0xce, 0x9a, 0x7e, 0x2c, 0x54, 0xa2, 0x2c, 0x47, 0xb7,
- 0xff, 0x17, 0xbe, 0xd0, 0x35, 0xbc, 0x26, 0x58, 0xb8, 0x72, 0xb1, 0x52,
- 0x9a, 0x56, 0xa1, 0x98, 0xc4, 0x44, 0x8b, 0x70, 0x19, 0x62, 0xfe, 0xdf,
- 0x59, 0x08, 0xec, 0x58, 0xa7, 0x3c, 0x91, 0x0b, 0xdf, 0xe7, 0xe8, 0xfd,
- 0x0e, 0xfe, 0x58, 0xb0, 0xd6, 0x2f, 0xf7, 0x27, 0x51, 0x44, 0xff, 0x58,
- 0xbf, 0x66, 0x85, 0x20, 0x58, 0xa1, 0x9f, 0x87, 0x04, 0x83, 0x36, 0xbf,
- 0xb5, 0x27, 0xc2, 0x3a, 0xc5, 0xfe, 0x27, 0xe3, 0x97, 0x70, 0x58, 0xad,
- 0x1f, 0x00, 0x65, 0xb7, 0x3e, 0xcb, 0x17, 0xef, 0xe0, 0x0c, 0x3a, 0xc5,
- 0xe3, 0x81, 0xd6, 0x2f, 0xed, 0x37, 0x1b, 0x3e, 0xb1, 0x4c, 0x79, 0x42,
- 0x1d, 0xae, 0x22, 0x57, 0xce, 0x97, 0x4c, 0x7a, 0xc5, 0xff, 0x4e, 0x72,
- 0x2f, 0xb8, 0x7e, 0x58, 0xbf, 0xd2, 0x79, 0x8c, 0x0c, 0x30, 0xd6, 0x28,
- 0x69, 0xaf, 0xbc, 0x2b, 0x4e, 0x47, 0xc1, 0xa0, 0x87, 0x75, 0x2a, 0xc2,
- 0xb2, 0x14, 0xef, 0x09, 0x06, 0x8e, 0x0a, 0xff, 0x8f, 0x9a, 0xd3, 0xf4,
- 0x6d, 0xd6, 0x2f, 0xec, 0xc1, 0xf4, 0x9f, 0xac, 0x5f, 0xe7, 0xfe, 0x6e,
- 0xcf, 0xb2, 0xc5, 0xff, 0xdb, 0xea, 0x4d, 0x92, 0xf4, 0x6a, 0x8d, 0x41,
- 0x45, 0x8b, 0x04, 0x58, 0xbc, 0x15, 0x21, 0xac, 0x5f, 0xc7, 0x17, 0xc6,
- 0x36, 0x58, 0xbf, 0xb5, 0x9f, 0x7e, 0xc9, 0x62, 0xf8, 0xd0, 0x4f, 0x96,
- 0x2d, 0xf9, 0x3d, 0x27, 0x2e, 0xbf, 0xf1, 0x66, 0xdf, 0xc0, 0x9e, 0x7d,
- 0x2c, 0x5f, 0xdf, 0x21, 0x31, 0xbb, 0xac, 0x5f, 0xfb, 0x3c, 0x6b, 0xef,
- 0xee, 0x66, 0xcb, 0x17, 0xf4, 0xeb, 0x06, 0xd0, 0x58, 0xad, 0x93, 0x87,
- 0x1c, 0x20, 0x77, 0x26, 0x74, 0x1e, 0x86, 0x06, 0x21, 0x5c, 0x5c, 0x58,
- 0xa9, 0x55, 0x17, 0x05, 0x71, 0x8a, 0x64, 0x75, 0x04, 0xc3, 0x7f, 0xdb,
- 0x99, 0xe7, 0x80, 0x79, 0xf5, 0x8b, 0xff, 0xff, 0x3f, 0xa4, 0xe4, 0xc6,
- 0xfd, 0xfd, 0x30, 0x8a, 0x13, 0xad, 0x96, 0x2f, 0xf8, 0xa7, 0x36, 0xf7,
- 0x33, 0x65, 0x8b, 0xff, 0xb8, 0xe1, 0xfb, 0x98, 0x72, 0x90, 0xd6, 0x2f,
- 0xff, 0x31, 0x48, 0x27, 0xef, 0xa1, 0x31, 0xd6, 0x2f, 0xff, 0x38, 0x35,
- 0x30, 0x7e, 0x72, 0x75, 0x05, 0x8b, 0xff, 0xb9, 0x91, 0x14, 0x9f, 0x5a,
- 0x9e, 0xd6, 0x2b, 0x48, 0x90, 0xf2, 0x55, 0xff, 0x08, 0x2e, 0x3c, 0xf7,
- 0x33, 0xeb, 0x15, 0x27, 0xc2, 0xc4, 0x75, 0xda, 0x73, 0xfa, 0x46, 0xf4,
- 0x67, 0x37, 0xfd, 0xbe, 0x16, 0x6d, 0xb0, 0x89, 0x62, 0xd1, 0xeb, 0x17,
- 0xda, 0xe6, 0x06, 0xb1, 0x7e, 0x22, 0x9e, 0xcc, 0x93, 0x73, 0x82, 0xb7,
- 0xff, 0x6a, 0x4d, 0x92, 0x9d, 0xe5, 0xfe, 0xb1, 0x7f, 0xee, 0x98, 0x3f,
- 0xcf, 0x06, 0x36, 0x58, 0xbf, 0x9f, 0x9a, 0xd4, 0xc1, 0x62, 0xff, 0xf7,
- 0x85, 0xa6, 0xe7, 0x9e, 0x3b, 0x01, 0x2b, 0x14, 0xb0, 0xe7, 0x9b, 0x58,
- 0x8d, 0x8d, 0xd0, 0x59, 0xee, 0xff, 0xb6, 0xfe, 0x7b, 0x84, 0xf1, 0x2c,
- 0x5f, 0xcf, 0x85, 0xdc, 0x38, 0xb1, 0x7d, 0xb1, 0xc4, 0x6a, 0xc5, 0xff,
- 0xee, 0x3f, 0x61, 0xe6, 0xf2, 0x42, 0x68, 0x2c, 0x5b, 0x36, 0x45, 0x06,
- 0x8b, 0x80, 0x4d, 0x7f, 0xff, 0xb0, 0x86, 0x39, 0x03, 0x98, 0x7e, 0x3f,
- 0xa7, 0xb0, 0xd6, 0x2f, 0xf8, 0xbd, 0xcf, 0x66, 0x07, 0xc5, 0x8b, 0x9b,
- 0xeb, 0x15, 0x87, 0xa3, 0xd9, 0xd5, 0xff, 0xdf, 0x7f, 0x73, 0xef, 0x82,
- 0x2f, 0x2c, 0x5f, 0xff, 0xa2, 0x84, 0x83, 0x59, 0xbc, 0xc1, 0xf4, 0xfc,
- 0x58, 0xbf, 0x30, 0x39, 0x09, 0x58, 0xa9, 0x47, 0x2c, 0x08, 0xb1, 0x10,
- 0x95, 0xef, 0xe9, 0xed, 0x87, 0xfc, 0x58, 0xbf, 0x67, 0xe3, 0x70, 0xb2,
- 0x35, 0xac, 0x54, 0xb2, 0x00, 0xa0, 0x7a, 0x36, 0xec, 0x8f, 0x67, 0x73,
- 0x87, 0x74, 0xd1, 0xe7, 0xe3, 0x1c, 0x62, 0xf2, 0x86, 0xdf, 0x0d, 0xbd,
- 0x1c, 0xc8, 0x8e, 0x83, 0x2e, 0xbf, 0xa1, 0x14, 0x27, 0x5b, 0x2c, 0x5f,
- 0xfb, 0x3c, 0xc4, 0x06, 0x39, 0xdd, 0x62, 0xfe, 0x92, 0x80, 0x3a, 0x01,
- 0x62, 0xf6, 0xef, 0xb2, 0xc5, 0xff, 0xff, 0x85, 0xfc, 0x1f, 0xbf, 0x87,
- 0xcf, 0xfd, 0x9f, 0xd3, 0xee, 0x2c, 0x5f, 0xf4, 0xf9, 0xe0, 0xfa, 0xd3,
- 0xac, 0x5f, 0xf8, 0x89, 0x8d, 0x33, 0x5a, 0x6e, 0xd6, 0x2f, 0x73, 0x09,
- 0x62, 0xff, 0x77, 0xfc, 0x1e, 0x9b, 0x75, 0x8a, 0xc4, 0x49, 0xba, 0x0b,
- 0x0e, 0x54, 0xaa, 0x21, 0x81, 0x89, 0xa7, 0xbd, 0x98, 0x38, 0xf9, 0x36,
- 0x72, 0x19, 0x77, 0x60, 0x45, 0x8b, 0xf1, 0x84, 0x59, 0x1e, 0xb1, 0x46,
- 0x9e, 0x21, 0x83, 0x37, 0xfb, 0x44, 0x2e, 0xfc, 0x52, 0xb1, 0x60, 0xa2,
- 0xc5, 0x82, 0x2c, 0x54, 0x9e, 0xf0, 0x0d, 0x02, 0x0b, 0x5d, 0x9d, 0xa4,
- 0x5a, 0x52, 0x2c, 0x0d, 0x1a, 0x90, 0x0c, 0x5f, 0xef, 0x66, 0x80, 0x77,
- 0xe2, 0x44, 0x61, 0xa7, 0xb8, 0xe3, 0x58, 0xbf, 0xa1, 0xf7, 0xe9, 0x91,
- 0x2c, 0x54, 0xa2, 0x41, 0xd1, 0xd8, 0x62, 0xfe, 0x83, 0x97, 0xa4, 0x0b,
- 0x14, 0xb1, 0x78, 0x62, 0x98, 0x8d, 0xc8, 0x0b, 0x6f, 0x8a, 0x7b, 0xe2,
- 0xc5, 0x68, 0xf5, 0xba, 0x19, 0xdf, 0xff, 0xff, 0x49, 0x6e, 0xde, 0x6e,
- 0xc1, 0xee, 0x61, 0x13, 0x1a, 0x66, 0xb4, 0xdd, 0xac, 0x5f, 0x48, 0x0f,
- 0x8b, 0x14, 0x04, 0x51, 0x7a, 0x10, 0x17, 0xfc, 0x3e, 0x73, 0x34, 0x3f,
- 0xe2, 0xc5, 0xff, 0xe0, 0x9e, 0x90, 0xe7, 0x9f, 0x6e, 0x98, 0x35, 0x8b,
- 0xfb, 0xef, 0xbc, 0x9d, 0xd6, 0x2f, 0xf6, 0x1d, 0xbb, 0x36, 0x1d, 0xac,
- 0x5f, 0xf6, 0x0d, 0xf8, 0x36, 0x60, 0xd6, 0x2f, 0x7b, 0xcd, 0xa3, 0xf0,
- 0x01, 0xbd, 0xfe, 0x90, 0x6c, 0xd0, 0x98, 0xf5, 0x8b, 0xff, 0xfb, 0x8f,
- 0xef, 0xe0, 0xf3, 0x79, 0xf3, 0x96, 0x76, 0xb1, 0x52, 0x9b, 0x1e, 0x42,
- 0x78, 0x8c, 0xfc, 0x6f, 0x7f, 0xfe, 0x2c, 0x03, 0x10, 0x0c, 0x3f, 0x84,
- 0xdb, 0x4a, 0xc5, 0x62, 0xb7, 0x0e, 0xe1, 0x8c, 0xe5, 0x11, 0x1d, 0x14,
- 0x76, 0x5e, 0x40, 0xbd, 0xe7, 0xd2, 0xc5, 0xa3, 0x23, 0x77, 0x56, 0xa2,
- 0x14, 0x1e, 0x8d, 0x63, 0x13, 0x1b, 0x0e, 0xd0, 0x9b, 0x84, 0x21, 0x87,
- 0x1e, 0x6e, 0x4e, 0xe6, 0x9b, 0x1a, 0xee, 0xf1, 0xf9, 0xf7, 0x19, 0xe3,
- 0xc2, 0x9e, 0x28, 0x7b, 0x6a, 0x37, 0x83, 0xc2, 0x27, 0xf2, 0xca, 0xd9,
- 0x2c, 0x07, 0x81, 0x72, 0xf2, 0x95, 0x7f, 0xca, 0x42, 0x8f, 0xa5, 0x7c,
- 0x0a, 0x15, 0xc1, 0xc2, 0x0a, 0x3a, 0x31, 0x03, 0x27, 0x0b, 0x02, 0x31,
- 0xdf, 0xff, 0xfc, 0xc7, 0x8c, 0x7d, 0x68, 0x5a, 0xd4, 0x96, 0x1a, 0xff,
- 0xfe, 0x18, 0xb1, 0x78, 0x5e, 0xc5, 0x8b, 0xff, 0x16, 0x77, 0xbc, 0xff,
- 0x35, 0x8b, 0x15, 0xa3, 0xdc, 0xf0, 0xed, 0xff, 0xc6, 0x87, 0x1f, 0xb0,
- 0xe3, 0x6e, 0xbd, 0x7f, 0x1c, 0xb1, 0x7e, 0x9d, 0x9b, 0x5b, 0xac, 0x5c,
- 0xfd, 0x16, 0x2f, 0x4f, 0xb8, 0xb1, 0x7b, 0x82, 0x3e, 0x8f, 0x80, 0x05,
- 0x44, 0x33, 0x51, 0xa9, 0x1f, 0x4f, 0x0b, 0xab, 0xfd, 0x80, 0xe6, 0x6e,
- 0xc3, 0x58, 0xbf, 0x13, 0x07, 0xce, 0x2c, 0x56, 0x1e, 0xee, 0x8d, 0x2f,
- 0x85, 0xec, 0x25, 0x8b, 0xed, 0xd9, 0xb7, 0x54, 0x54, 0x45, 0xe3, 0x67,
- 0x8b, 0x17, 0xf7, 0xe7, 0xd3, 0xd8, 0x6b, 0x17, 0xc5, 0x07, 0x3a, 0xc5,
- 0xfa, 0x18, 0x4e, 0x35, 0x8a, 0xc4, 0x4b, 0xb8, 0xf3, 0x18, 0x78, 0x8a,
- 0xfc, 0xe4, 0x36, 0xdd, 0x62, 0xb6, 0x4d, 0x33, 0x44, 0x47, 0x86, 0x47,
- 0x43, 0xab, 0xef, 0xe6, 0xb1, 0x62, 0xf3, 0xc4, 0x11, 0x62, 0xa4, 0xf0,
- 0xbe, 0x45, 0x7c, 0xdf, 0x9f, 0xac, 0x5e, 0x3f, 0x25, 0x62, 0xb7, 0x37,
- 0xe2, 0x22, 0xb6, 0xcb, 0x17, 0xff, 0xcc, 0x6f, 0x5f, 0x1b, 0x25, 0x0c,
- 0xfb, 0x9d, 0x62, 0xc2, 0x93, 0xe6, 0x21, 0x3b, 0x84, 0x62, 0xc5, 0xe1,
- 0xc9, 0xd6, 0x2f, 0x8d, 0x30, 0xb7, 0x58, 0xa1, 0x9e, 0x19, 0xa3, 0xb7,
- 0xff, 0xd0, 0xda, 0x35, 0x4c, 0x69, 0xb6, 0xfa, 0xeb, 0xd7, 0xf1, 0xcb,
- 0x17, 0xf3, 0x37, 0x7f, 0xcc, 0x58, 0xa9, 0x4c, 0x51, 0xd7, 0x00, 0x46,
- 0x4d, 0x17, 0xed, 0x3e, 0xef, 0xd1, 0x62, 0xf4, 0xe1, 0x2c, 0x5f, 0xce,
- 0x71, 0xe9, 0xb7, 0x58, 0xa1, 0x9e, 0x57, 0xc6, 0xef, 0xcc, 0x6e, 0x7d,
- 0x96, 0x2b, 0x0f, 0x28, 0x44, 0x57, 0xff, 0xf0, 0x89, 0x8d, 0xeb, 0xe3,
- 0x64, 0xa1, 0x9f, 0x73, 0xac, 0x5f, 0x6b, 0x59, 0x1c, 0xb1, 0x47, 0x44,
- 0x23, 0x2f, 0x5f, 0xe9, 0x28, 0x0f, 0xee, 0x75, 0x8b, 0xff, 0xff, 0x67,
- 0xb3, 0xd9, 0xa0, 0x1d, 0xa1, 0x3c, 0x7e, 0x3f, 0x7e, 0x58, 0xa3, 0x51,
- 0x3f, 0xc3, 0x3b, 0xfe, 0xce, 0xf7, 0x26, 0xce, 0xf7, 0x58, 0xbf, 0xdd,
- 0xee, 0x4d, 0x9d, 0xee, 0xb1, 0x7e, 0x68, 0x14, 0xf3, 0xa9, 0xf9, 0xe1,
- 0xe5, 0xf0, 0x79, 0xf6, 0x58, 0xbe, 0x29, 0xce, 0xd6, 0x2a, 0x4f, 0x17,
- 0xc4, 0x77, 0x86, 0xfd, 0x16, 0x2d, 0x19, 0x2c, 0x97, 0x78, 0x46, 0x38,
- 0x38, 0x45, 0x64, 0x6d, 0xbb, 0xc2, 0x21, 0xd8, 0x0f, 0x08, 0x8f, 0xc6,
- 0x74, 0xc7, 0x65, 0x0b, 0xfe, 0x42, 0x97, 0xd0, 0xc1, 0xe9, 0x09, 0x73,
- 0x21, 0x06, 0x10, 0x86, 0xf7, 0xe6, 0x3d, 0x62, 0xf8, 0x98, 0x3f, 0xac,
- 0x5f, 0xb8, 0x26, 0x20, 0x2c, 0x5f, 0x61, 0x3f, 0x96, 0x2f, 0x7f, 0x00,
- 0xb1, 0x7b, 0x0f, 0x18, 0xe8, 0xa9, 0x88, 0x83, 0xc4, 0x71, 0xc5, 0x01,
- 0x08, 0x6f, 0xfb, 0xef, 0xaf, 0xb7, 0x30, 0xc5, 0x8b, 0x86, 0x4b, 0x17,
- 0xf4, 0x07, 0xa7, 0x16, 0xcb, 0x17, 0xfa, 0x7c, 0xdf, 0xea, 0x39, 0x58,
- 0xbf, 0x45, 0x3f, 0x16, 0xcb, 0x17, 0xe6, 0x87, 0x9f, 0x65, 0x8a, 0xc3,
- 0xd4, 0x72, 0xbb, 0xcd, 0xe7, 0x58, 0xba, 0x63, 0x31, 0x34, 0x6e, 0xce,
- 0x9c, 0x5c, 0xe6, 0x1f, 0x84, 0x4f, 0x08, 0x28, 0x6a, 0x84, 0xf9, 0x1d,
- 0x4d, 0xec, 0x0f, 0x16, 0x2f, 0x98, 0xe5, 0x2b, 0x17, 0xff, 0x39, 0x4f,
- 0x9f, 0x4e, 0x7c, 0x1a, 0xc5, 0x11, 0xf1, 0x84, 0x21, 0xba, 0x76, 0x58,
- 0xac, 0x37, 0x62, 0x23, 0xb8, 0x5f, 0x58, 0xbf, 0x9a, 0x1d, 0xf2, 0x76,
- 0x58, 0xbd, 0xb3, 0x06, 0xb1, 0x7d, 0xcf, 0xb4, 0x16, 0x2b, 0x63, 0xc2,
- 0x61, 0xfb, 0xfe, 0x6e, 0xcb, 0x3a, 0x69, 0xf8, 0xb1, 0x7e, 0x79, 0x83,
- 0x41, 0x62, 0xb6, 0x4c, 0x38, 0x63, 0x1a, 0x72, 0x39, 0x17, 0xce, 0xef,
- 0xec, 0xd8, 0x73, 0x83, 0x58, 0xbe, 0x1f, 0xde, 0x25, 0x8b, 0x06, 0xb1,
- 0x58, 0x7c, 0xac, 0x5d, 0xe2, 0x4b, 0xf1, 0x30, 0x4c, 0xd9, 0x62, 0xff,
- 0x81, 0x25, 0x9e, 0xe4, 0x9d, 0x62, 0xf0, 0x6d, 0xf5, 0x8b, 0xa4, 0x6b,
- 0x15, 0x26, 0xd7, 0xe3, 0xd7, 0x8a, 0x63, 0xd6, 0x2f, 0xfb, 0x3d, 0xf6,
- 0xde, 0x48, 0x6b, 0x17, 0xf8, 0xbd, 0xcd, 0x64, 0x9d, 0x62, 0xa4, 0xfb,
- 0x18, 0xe6, 0xfc, 0xe4, 0x42, 0x8f, 0x58, 0xbf, 0xee, 0x60, 0xf3, 0x50,
- 0x9d, 0x2c, 0x54, 0x9f, 0x1e, 0x8a, 0xad, 0xb2, 0xc5, 0x49, 0xb4, 0xc2,
- 0x1b, 0xed, 0xe7, 0x46, 0xac, 0x5f, 0xa0, 0xde, 0x83, 0x2c, 0x5f, 0x48,
- 0x01, 0x2b, 0x17, 0xfa, 0x75, 0xb6, 0x1f, 0x0e, 0xb1, 0x52, 0x7f, 0xc4,
- 0x51, 0xc2, 0x2b, 0xfe, 0x21, 0xe6, 0x86, 0xcc, 0x35, 0x8b, 0x09, 0x62,
- 0xa4, 0xf2, 0x98, 0xe2, 0x96, 0x2c, 0x4b, 0x1b, 0x13, 0x2f, 0xdb, 0x69,
- 0x9b, 0xcb, 0x14, 0xe7, 0x92, 0xc4, 0x17, 0x1c, 0x6b, 0x17, 0xdf, 0x7f,
- 0xc6, 0x05, 0x57, 0xa9, 0x87, 0x0b, 0xbc, 0x8c, 0xb8, 0xd8, 0x58, 0xee,
- 0x5a, 0xe5, 0x51, 0x36, 0xe8, 0x80, 0xf0, 0x8b, 0xfc, 0x2d, 0xf8, 0x3f,
- 0xe8, 0x51, 0x86, 0xef, 0x1c, 0xea, 0x10, 0x82, 0xf7, 0x30, 0x96, 0x2f,
- 0xb7, 0x66, 0xdd, 0x51, 0x5e, 0x97, 0xff, 0x48, 0x07, 0xf9, 0xe6, 0x1e,
- 0x63, 0xd6, 0x2b, 0x47, 0xf0, 0x73, 0x1b, 0xf3, 0x84, 0xdc, 0x5b, 0x2c,
- 0x5a, 0x0b, 0x16, 0x3a, 0xc5, 0xe2, 0x98, 0x2c, 0x54, 0x9e, 0x03, 0x09,
- 0x78, 0x4a, 0xe9, 0x02, 0xc5, 0xef, 0xcf, 0x6b, 0x17, 0x4f, 0x6b, 0x14,
- 0x69, 0xb6, 0xf8, 0xf5, 0xf6, 0x79, 0xf6, 0x58, 0xbf, 0xb6, 0x32, 0x39,
- 0x88, 0x0b, 0x17, 0xfe, 0x62, 0x06, 0x7a, 0x49, 0xc0, 0xb1, 0x52, 0x7d,
- 0xf1, 0xc6, 0x76, 0x8c, 0x82, 0xa7, 0x5c, 0x84, 0xa6, 0x88, 0x99, 0xb4,
- 0x05, 0xa2, 0x4d, 0x8e, 0x22, 0x32, 0x12, 0x57, 0xfd, 0x08, 0xcc, 0xd6,
- 0xec, 0xdb, 0xaa, 0x24, 0x62, 0xff, 0xd9, 0xe2, 0x60, 0x61, 0x66, 0x96,
- 0x2d, 0x18, 0xc8, 0x87, 0x24, 0xbb, 0xff, 0xd1, 0x87, 0x68, 0x46, 0x66,
- 0xb7, 0x66, 0xdd, 0x51, 0x3c, 0x17, 0xed, 0x6e, 0xcd, 0xba, 0xa2, 0x7f,
- 0x2e, 0xe8, 0xeb, 0x17, 0xe8, 0xc3, 0xb4, 0x23, 0x30, 0xf4, 0x1c, 0xde,
- 0xff, 0xf4, 0x61, 0xda, 0x11, 0x99, 0xad, 0xd9, 0xb7, 0x54, 0x50, 0xc5,
- 0xff, 0xfd, 0x87, 0x98, 0x46, 0x18, 0x52, 0x3f, 0xe6, 0xf9, 0xa5, 0x8b,
- 0xff, 0x34, 0x23, 0x33, 0x5b, 0xb3, 0x6e, 0xa8, 0xa2, 0x0b, 0xf9, 0xb7,
- 0x8c, 0x03, 0xec, 0xb1, 0x47, 0x44, 0x1f, 0x45, 0x0b, 0xff, 0x42, 0x30,
- 0x5c, 0xeb, 0x3c, 0x98, 0x2c, 0x54, 0x61, 0xf5, 0x49, 0x2d, 0xff, 0xa2,
- 0x7f, 0xf7, 0x9e, 0x1e, 0x1d, 0x62, 0xff, 0xf3, 0x46, 0x0d, 0x89, 0xb7,
- 0xea, 0x63, 0x1d, 0x62, 0xfe, 0x7f, 0x3e, 0x98, 0x0b, 0x17, 0xd9, 0xec,
- 0x02, 0xc5, 0xf8, 0x84, 0xd0, 0xe2, 0xc5, 0x8e, 0xb1, 0x7f, 0xdd, 0x33,
- 0xb8, 0x69, 0x9a, 0x0b, 0x17, 0x89, 0xa3, 0x20, 0x8c, 0x52, 0x2d, 0xf1,
- 0x14, 0x71, 0x41, 0x82, 0x57, 0xf4, 0x51, 0x9c, 0x29, 0xd9, 0x62, 0xfa,
- 0x4a, 0x7e, 0xb1, 0x7d, 0x9a, 0x93, 0xac, 0x50, 0xcf, 0x0f, 0xe4, 0x37,
- 0xff, 0xef, 0xe1, 0x61, 0xbf, 0x68, 0x7c, 0x36, 0x30, 0xeb, 0x17, 0x99,
- 0xb7, 0x54, 0x52, 0x25, 0xf4, 0x30, 0xb6, 0x58, 0xad, 0xcf, 0x36, 0x22,
- 0xaa, 0x82, 0x32, 0x75, 0x0a, 0x5b, 0xf0, 0xbc, 0x53, 0xf5, 0x8b, 0xff,
- 0x74, 0x6d, 0x71, 0xbf, 0xc9, 0xd9, 0x62, 0xfd, 0x31, 0x6a, 0x4e, 0xb1,
- 0x5f, 0x3e, 0xbe, 0x21, 0x5f, 0xfc, 0xdd, 0xf3, 0xe1, 0xc8, 0x3a, 0x98,
- 0x75, 0x8b, 0xfd, 0x09, 0xd6, 0xd3, 0xad, 0x96, 0x2f, 0xfe, 0xf7, 0x24,
- 0xe5, 0x83, 0xfe, 0x79, 0x62, 0xff, 0xa7, 0xa6, 0x69, 0xb6, 0x6e, 0x2c,
- 0x52, 0xc5, 0x75, 0x3c, 0x71, 0x1d, 0xd4, 0xa3, 0x97, 0x0d, 0x81, 0x08,
- 0xbb, 0xff, 0xc5, 0x9f, 0xf1, 0x48, 0x30, 0x9a, 0x0b, 0x17, 0xf8, 0xa4,
- 0xfc, 0x07, 0x99, 0x62, 0xff, 0x37, 0x8e, 0xfe, 0xfb, 0xac, 0x5a, 0x32,
- 0x55, 0xec, 0x64, 0x3a, 0xe2, 0x28, 0x68, 0x49, 0x80, 0x88, 0xa3, 0x30,
- 0xe1, 0x9f, 0x91, 0xcc, 0x33, 0xbf, 0xde, 0x26, 0x34, 0xed, 0x05, 0x8b,
- 0xe2, 0x6f, 0x71, 0x62, 0xcd, 0x04, 0x76, 0x8e, 0x12, 0xfb, 0x9a, 0x5f,
- 0xfa, 0x32, 0x7f, 0x9a, 0xe8, 0xdf, 0x65, 0x8b, 0xa3, 0x7d, 0xd6, 0x2e,
- 0xc3, 0xac, 0x5f, 0x43, 0x42, 0xdd, 0x62, 0xd1, 0x81, 0x43, 0xda, 0x91,
- 0xee, 0xc5, 0xee, 0xce, 0x8b, 0x17, 0xff, 0xb7, 0xcf, 0x49, 0x7b, 0x8c,
- 0x42, 0xc5, 0x8b, 0x46, 0x70, 0xf8, 0x8c, 0x19, 0xa1, 0xa6, 0xce, 0xf0,
- 0x9d, 0xe9, 0x09, 0xeb, 0xff, 0xd0, 0x8c, 0xd3, 0x01, 0xbc, 0xfa, 0xc3,
- 0xac, 0x5f, 0xfb, 0xbe, 0x41, 0xf9, 0xc9, 0xd4, 0x16, 0x2f, 0x9c, 0xec,
- 0x11, 0x62, 0xff, 0x6f, 0x27, 0xe7, 0xa6, 0x0b, 0x15, 0x27, 0xb2, 0xe4,
- 0x97, 0x7f, 0x16, 0x2e, 0x90, 0xd6, 0x2f, 0xe1, 0x68, 0x1d, 0x47, 0x12,
- 0xc5, 0xa3, 0x20, 0x88, 0x21, 0x90, 0x7c, 0x5f, 0x83, 0x14, 0xc9, 0xb1,
- 0x02, 0x31, 0xcb, 0xfa, 0x19, 0xff, 0xb4, 0x16, 0x2f, 0xf4, 0xe8, 0xb3,
- 0x63, 0x20, 0xb1, 0x7f, 0x1d, 0xfd, 0xf1, 0x1a, 0xb1, 0x7f, 0xdf, 0x76,
- 0x04, 0x88, 0x2f, 0x2b, 0x17, 0x9e, 0x28, 0xcd, 0x91, 0x43, 0x86, 0xbe,
- 0x30, 0xbf, 0xf6, 0xf1, 0x83, 0x7e, 0xac, 0x5b, 0xca, 0xc5, 0x62, 0x22,
- 0x99, 0x16, 0xff, 0xfe, 0xc1, 0xfe, 0x4c, 0x8c, 0xf1, 0x30, 0x39, 0xc9,
- 0x02, 0x45, 0xa3, 0x25, 0x99, 0x00, 0x34, 0x1d, 0xe3, 0x15, 0xed, 0x80,
- 0xf3, 0xa7, 0x7f, 0x8e, 0x89, 0x8f, 0x01, 0x1d, 0x7f, 0x8a, 0x7a, 0x46,
- 0xb3, 0x1c, 0x43, 0x7f, 0xd3, 0x19, 0x84, 0xe6, 0xcf, 0x16, 0x2f, 0x73,
- 0x38, 0xb1, 0x7d, 0xc9, 0xee, 0x0b, 0x17, 0xc2, 0x08, 0x39, 0x58, 0xae,
- 0xcf, 0x9a, 0x21, 0xdf, 0x92, 0x5f, 0xff, 0x7e, 0x7e, 0xe6, 0xf3, 0x98,
- 0x40, 0x8e, 0xc5, 0x8b, 0xc4, 0x0e, 0x2c, 0x5f, 0x4f, 0x06, 0xeb, 0x17,
- 0xdb, 0xb3, 0x6e, 0xa8, 0x94, 0x0b, 0xff, 0x48, 0x0e, 0xd0, 0xfc, 0xb6,
- 0x96, 0x2a, 0x09, 0x80, 0xe2, 0x99, 0xa3, 0xba, 0x22, 0x23, 0x1b, 0xff,
- 0xdf, 0x7d, 0x8e, 0x2d, 0x03, 0x9c, 0x61, 0xac, 0x5f, 0xf7, 0xe7, 0x51,
- 0x3f, 0xe6, 0x25, 0x8b, 0xfe, 0x6d, 0x6d, 0xa9, 0x83, 0x69, 0x62, 0xff,
- 0x30, 0x65, 0x80, 0x90, 0x2c, 0x5f, 0xec, 0x1e, 0x0e, 0x4b, 0xcb, 0x15,
- 0x04, 0x4f, 0x91, 0xd7, 0x0c, 0xef, 0xe6, 0x81, 0x3c, 0x9a, 0xb1, 0x7f,
- 0x60, 0x0e, 0xd0, 0xc5, 0x8b, 0xba, 0x3a, 0xc5, 0xff, 0xcd, 0xdf, 0x36,
- 0xc0, 0xc4, 0x53, 0xc5, 0x8b, 0xfe, 0xe4, 0x9f, 0x3c, 0xc2, 0x0b, 0xac,
- 0x5f, 0xe9, 0xe0, 0xf4, 0xe2, 0xd9, 0x62, 0xd9, 0xe3, 0xf2, 0xe8, 0x7b,
- 0x76, 0xa5, 0x62, 0xff, 0x40, 0xc8, 0x60, 0x26, 0x0b, 0x14, 0x33, 0xcc,
- 0xd0, 0xbd, 0xf4, 0x1f, 0x50, 0x58, 0xbc, 0xc3, 0xc5, 0x8a, 0xc3, 0xe1,
- 0x88, 0x8b, 0x84, 0x77, 0xfd, 0x0c, 0xf9, 0x67, 0xbe, 0xeb, 0x17, 0xff,
- 0x9b, 0x67, 0xd6, 0x9f, 0xb8, 0x79, 0xbb, 0x58, 0xbf, 0xff, 0xfe, 0xf3,
- 0x90, 0xa1, 0x9c, 0x2c, 0xd8, 0xc8, 0x78, 0xd7, 0xef, 0x83, 0xc2, 0x58,
- 0xbd, 0xff, 0x1d, 0x62, 0xe8, 0x46, 0x4a, 0xf1, 0x36, 0x46, 0x65, 0xba,
- 0x53, 0xa6, 0xc5, 0x0d, 0xa3, 0x97, 0xfc, 0xb5, 0x8b, 0x40, 0x32, 0x50,
- 0xb9, 0xe4, 0x35, 0xbc, 0x5f, 0x1c, 0x70, 0x62, 0x68, 0x48, 0x40, 0x5a,
- 0x32, 0x0b, 0xf8, 0x4d, 0x3d, 0x8f, 0x5b, 0x3e, 0xfb, 0x24, 0x2d, 0x5d,
- 0x50, 0xe5, 0x06, 0x6f, 0x4a, 0x49, 0x79, 0x7a, 0x11, 0xf3, 0xda, 0x3a,
- 0x97, 0x10, 0x78, 0xc3, 0xfe, 0x54, 0x08, 0x57, 0x85, 0xd0, 0xc9, 0x7f,
- 0x91, 0xa6, 0x0a, 0x99, 0x48, 0x12, 0x91, 0x19, 0x7e, 0x84, 0x66, 0x88,
- 0x4b, 0x17, 0xfe, 0x68, 0x46, 0x66, 0xb7, 0x66, 0xdd, 0x51, 0x39, 0x97,
- 0x66, 0x96, 0x2f, 0xf7, 0x33, 0xf3, 0xb6, 0x69, 0x62, 0xff, 0x36, 0xf1,
- 0x86, 0x1c, 0xa7, 0x63, 0xcb, 0xc1, 0x7b, 0x46, 0x1d, 0x1d, 0x3d, 0x21,
- 0x37, 0x6e, 0x2c, 0x5d, 0x09, 0x58, 0xbf, 0xf3, 0x42, 0x33, 0x35, 0xbb,
- 0x36, 0xea, 0x8a, 0x24, 0xb8, 0x30, 0xd6, 0x2d, 0x19, 0xb2, 0x24, 0xf7,
- 0x12, 0x38, 0xb8, 0x6a, 0x17, 0x05, 0x9b, 0x2c, 0x5f, 0xdc, 0xe4, 0x80,
- 0xcd, 0x96, 0x2f, 0xf3, 0x6a, 0x01, 0x67, 0x40, 0x3a, 0xc5, 0x61, 0xf6,
- 0x08, 0xc6, 0xf3, 0xf7, 0xc5, 0x8b, 0xc5, 0x27, 0x58, 0xbf, 0xe2, 0x6e,
- 0xfc, 0xde, 0x83, 0x2c, 0x5f, 0xdf, 0xcc, 0xf7, 0xf1, 0x62, 0xb6, 0x45,
- 0x03, 0x8f, 0x00, 0x73, 0xc7, 0x37, 0xfd, 0xad, 0xfe, 0xf1, 0xef, 0x9b,
- 0x2c, 0x5a, 0x56, 0x28, 0x47, 0x9f, 0xd0, 0xfa, 0xfd, 0xc7, 0xcd, 0x1a,
- 0xb1, 0x7d, 0x27, 0x1f, 0xd6, 0x2a, 0x07, 0x99, 0xe2, 0x9b, 0xf6, 0xa7,
- 0xa3, 0xf4, 0x58, 0xbd, 0x13, 0x9d, 0x62, 0xfc, 0xde, 0xf6, 0x69, 0x62,
- 0x86, 0x7e, 0x4e, 0x58, 0x43, 0xd7, 0xfd, 0xf7, 0xd0, 0xc4, 0xda, 0x82,
- 0xc5, 0xf7, 0x0f, 0x3c, 0x58, 0xbf, 0xe7, 0xe6, 0x0e, 0x10, 0xf8, 0x96,
- 0x2f, 0xdc, 0x8a, 0x0e, 0x05, 0x8a, 0xc4, 0x43, 0xee, 0x46, 0xe7, 0x57,
- 0x8e, 0xc0, 0x58, 0xbf, 0xed, 0xdb, 0x5b, 0x0d, 0x98, 0xd5, 0x8b, 0xf7,
- 0xbd, 0x3a, 0x02, 0xc5, 0x6e, 0x7c, 0xbf, 0x3c, 0xa9, 0x45, 0x2e, 0x42,
- 0x0a, 0xff, 0xdd, 0xe7, 0x9f, 0xb0, 0xf3, 0xbf, 0x2c, 0x5f, 0x89, 0xba,
- 0x49, 0xab, 0x15, 0x27, 0xda, 0xe8, 0x77, 0xf6, 0x0c, 0xc1, 0xb1, 0xd6,
- 0x2f, 0xff, 0xd8, 0x50, 0xeb, 0x83, 0x7e, 0x77, 0xe1, 0x37, 0x16, 0x2f,
- 0xf4, 0xec, 0x64, 0x73, 0x10, 0x16, 0x2e, 0x84, 0x64, 0x6c, 0xbc, 0x1e,
- 0x38, 0x45, 0x64, 0x30, 0x77, 0x84, 0x67, 0x6e, 0x0f, 0x09, 0x48, 0x8b,
- 0x7f, 0x0c, 0x12, 0x86, 0xa7, 0xa1, 0x27, 0xd0, 0x80, 0x32, 0xf3, 0x16,
- 0x2f, 0xee, 0x17, 0x58, 0xdc, 0x6e, 0xb1, 0x7f, 0x4b, 0xfb, 0xf3, 0xa5,
- 0x8b, 0xff, 0x16, 0x02, 0x41, 0xad, 0x48, 0x6b, 0x17, 0xc4, 0x59, 0xe5,
- 0x8b, 0x46, 0x4a, 0x30, 0xbe, 0x6b, 0xc2, 0xd3, 0x0f, 0xeb, 0x49, 0xfc,
- 0x02, 0x3b, 0x2a, 0x96, 0x52, 0xae, 0xa3, 0x15, 0xe4, 0x31, 0x85, 0x48,
- 0x50, 0xbf, 0xff, 0xff, 0x6c, 0x64, 0x7c, 0x6b, 0x0b, 0xf5, 0xeb, 0xf8,
- 0xe8, 0xc2, 0x8d, 0x51, 0xb0, 0x52, 0x3e, 0x35, 0x19, 0xd7, 0xaf, 0xe3,
- 0x96, 0x2f, 0xda, 0xdd, 0x9b, 0x75, 0x44, 0x38, 0x5f, 0xc2, 0xdf, 0x4f,
- 0x24, 0xb1, 0x7e, 0x72, 0xf4, 0x9d, 0x62, 0xd1, 0x98, 0x88, 0xcf, 0x9b,
- 0xc7, 0x17, 0x5f, 0xd8, 0x67, 0xe5, 0xf4, 0xb1, 0x7f, 0x61, 0x9f, 0x97,
- 0xd2, 0xc5, 0xfd, 0x86, 0x7e, 0x5f, 0x4b, 0x17, 0xf6, 0x19, 0xf9, 0x7d,
- 0x2c, 0x5f, 0xd8, 0x67, 0xe5, 0xf4, 0xb1, 0x7f, 0x61, 0x9f, 0x97, 0xd2,
- 0xc5, 0xff, 0xc1, 0x60, 0x53, 0xf2, 0x20, 0x9b, 0xfe, 0x43, 0x58, 0xbf,
- 0xf3, 0x8f, 0x0e, 0x59, 0xdf, 0x99, 0x62, 0xff, 0x6b, 0x37, 0xfc, 0xf7,
- 0x05, 0x8b, 0x06, 0xb1, 0x52, 0x79, 0x38, 0x6d, 0x4b, 0x17, 0xf7, 0x39,
- 0x20, 0x33, 0x65, 0x8b, 0xff, 0x31, 0xbb, 0xfd, 0xf5, 0xa9, 0x0d, 0x62,
- 0xb0, 0xfc, 0xc8, 0xc6, 0xfb, 0x61, 0xce, 0xcb, 0x17, 0x85, 0xc9, 0x58,
- 0xbf, 0xfb, 0x7f, 0xc9, 0xaf, 0xc0, 0xb5, 0x0a, 0x37, 0xd6, 0x2c, 0x25,
- 0x8b, 0xfa, 0x7d, 0xf9, 0xec, 0x0b, 0x15, 0x1e, 0x89, 0x33, 0xa9, 0x70,
- 0x4a, 0xe2, 0x25, 0x8b, 0xed, 0xd9, 0xb7, 0x54, 0x45, 0xe5, 0xfe, 0xce,
- 0xc1, 0xc6, 0x7d, 0x96, 0x2f, 0xc4, 0xc0, 0x6e, 0x2c, 0x5f, 0xb2, 0x28,
- 0x37, 0x16, 0x2b, 0x13, 0xd4, 0xec, 0x95, 0xe1, 0x61, 0x11, 0x9e, 0x85,
- 0x88, 0xc7, 0xc6, 0xa6, 0x13, 0xdf, 0xed, 0xbf, 0x9f, 0xc7, 0xd9, 0x62,
- 0xf4, 0x87, 0xe5, 0x8b, 0x36, 0x8f, 0x4c, 0x8d, 0x6e, 0x14, 0x7a, 0xc5,
- 0xc2, 0xd2, 0xc5, 0x40, 0xd9, 0xb0, 0xdd, 0xef, 0xbe, 0x96, 0x2f, 0x8a,
- 0x63, 0xe2, 0x58, 0xa3, 0x9e, 0x1f, 0xc7, 0x6f, 0xf9, 0xb5, 0x08, 0xa0,
- 0xfa, 0x82, 0xc5, 0xf0, 0x47, 0x28, 0x96, 0x2e, 0x0e, 0x25, 0x8b, 0xfb,
- 0x07, 0xfc, 0x03, 0x2c, 0x5f, 0x48, 0x82, 0xfc, 0x58, 0xa8, 0x23, 0x3b,
- 0x0e, 0xd8, 0x97, 0x83, 0x41, 0x96, 0xdf, 0xe7, 0x07, 0x00, 0x07, 0xf2,
- 0xc5, 0xfa, 0x4e, 0x0d, 0xc0, 0xb1, 0x58, 0x7b, 0xce, 0x69, 0x71, 0x9c,
- 0x58, 0xbf, 0x69, 0xb9, 0xb4, 0xac, 0x5a, 0x0b, 0x15, 0x27, 0xa9, 0x83,
- 0x2c, 0x53, 0x7f, 0x81, 0xee, 0x7f, 0x1c, 0x6b, 0x16, 0xd9, 0x62, 0xb4,
- 0x78, 0xe4, 0x69, 0x60, 0xd6, 0x2f, 0xd3, 0xad, 0x4e, 0xcb, 0x17, 0xf8,
- 0xa4, 0xe6, 0x0f, 0xf2, 0xb1, 0x58, 0x7e, 0x04, 0x27, 0xe2, 0x9b, 0xf3,
- 0x40, 0xf3, 0x05, 0x8b, 0x1d, 0x62, 0xa5, 0x1f, 0x0f, 0x09, 0x1f, 0x96,
- 0xf8, 0xa2, 0xf9, 0xc6, 0xdc, 0x58, 0xbe, 0xeb, 0xec, 0xd2, 0xc5, 0x49,
- 0xe3, 0xee, 0x45, 0x79, 0xa1, 0x8b, 0x17, 0xf3, 0x16, 0xfa, 0x87, 0x16,
- 0x28, 0x8f, 0x2c, 0x43, 0x97, 0xfb, 0x0f, 0x9b, 0xee, 0xff, 0x58, 0xbd,
- 0x06, 0x82, 0xc5, 0xfb, 0xf9, 0x01, 0xf6, 0xb1, 0x4e, 0x7f, 0x91, 0x1a,
- 0xf8, 0x76, 0xee, 0x76, 0xb1, 0x7d, 0xe8, 0x49, 0xa9, 0x17, 0xd8, 0x3f,
- 0x71, 0x62, 0xb1, 0x11, 0xe7, 0x2f, 0x61, 0x92, 0x24, 0xbf, 0xfe, 0x66,
- 0xf0, 0xdd, 0x88, 0x7f, 0x93, 0x0e, 0xb1, 0x7b, 0x0c, 0x0a, 0x2c, 0x5f,
- 0xbb, 0x87, 0x1c, 0xd5, 0x8a, 0x93, 0xcd, 0xc2, 0x2a, 0xd2, 0x2f, 0x0a,
- 0x13, 0x97, 0xe0, 0x02, 0x48, 0xd5, 0x8b, 0xdb, 0xb4, 0x16, 0x2a, 0x4f,
- 0x1f, 0x0a, 0x6f, 0x8c, 0x28, 0x82, 0x2c, 0x57, 0xcf, 0x1c, 0x04, 0x17,
- 0xe6, 0xec, 0x4d, 0xe5, 0x8b, 0xa3, 0x89, 0x62, 0xfe, 0x3b, 0x96, 0x1e,
- 0x56, 0x2f, 0xb6, 0xf6, 0x7d, 0x62, 0xb0, 0xf4, 0x18, 0xb2, 0xfe, 0x06,
- 0x10, 0xb9, 0x2b, 0x17, 0xfc, 0xf0, 0x7f, 0x88, 0xe7, 0x75, 0x8a, 0x93,
- 0xe6, 0xf1, 0x6d, 0xa3, 0x02, 0x8c, 0xea, 0x40, 0xa9, 0x74, 0x68, 0x5d,
- 0x1b, 0x17, 0x05, 0xb2, 0xe0, 0xb0, 0xba, 0x35, 0x17, 0x4a, 0x9e, 0xd0,
- 0x87, 0x81, 0x00, 0xdf, 0xf2, 0x3f, 0x4d, 0xe1, 0x95, 0xda, 0xcb, 0xb1,
- 0xc5, 0x0f, 0x0d, 0x42, 0x9c, 0xee, 0x9f, 0x8d, 0xad, 0xa1, 0x0e, 0x06,
- 0xd2, 0x8c, 0xb3, 0x90, 0xf6, 0xf4, 0x2d, 0x44, 0x45, 0xd0, 0xa6, 0x39,
- 0xa8, 0xc8, 0x43, 0x5f, 0xf3, 0x6f, 0x19, 0x0c, 0xd6, 0x41, 0x62, 0xec,
- 0xe2, 0xc5, 0xff, 0xff, 0xf1, 0x34, 0x66, 0x08, 0x2e, 0xe6, 0xbf, 0xbf,
- 0x8f, 0x0e, 0x75, 0xc3, 0x66, 0x0b, 0x17, 0xec, 0xe1, 0xc7, 0x2b, 0x17,
- 0xff, 0xcd, 0xb6, 0xa7, 0x6e, 0x31, 0x0b, 0x7c, 0xe2, 0xc5, 0xfb, 0x5b,
- 0xb3, 0x6e, 0xa8, 0x99, 0x0b, 0xcd, 0x08, 0xc9, 0x44, 0x4e, 0x29, 0x5a,
- 0x33, 0x64, 0xf0, 0x20, 0x7b, 0xb8, 0xbe, 0xa1, 0x0c, 0x78, 0x58, 0xdf,
- 0xfd, 0xf7, 0xd4, 0x23, 0x07, 0x87, 0x19, 0xd6, 0x2e, 0x3f, 0x16, 0x2f,
- 0x33, 0x1d, 0x62, 0xd1, 0x9a, 0x36, 0x9f, 0x18, 0xbd, 0xec, 0x3a, 0xc5,
- 0xdf, 0x3a, 0xc5, 0xfb, 0x5b, 0xb3, 0x6e, 0xa8, 0xb7, 0x8b, 0x46, 0x49,
- 0xf6, 0x0c, 0x77, 0x06, 0x2d, 0x1c, 0xb1, 0x76, 0x12, 0xc5, 0xa3, 0x18,
- 0xd5, 0xc7, 0x0a, 0xdc, 0xc1, 0x16, 0x2f, 0xf0, 0x24, 0x62, 0x6d, 0x41,
- 0x62, 0xff, 0xcd, 0x08, 0xcc, 0xd6, 0xec, 0xdb, 0xaa, 0x29, 0x32, 0xd1,
- 0x98, 0x89, 0xd7, 0x19, 0x39, 0xa5, 0xd1, 0xbc, 0x68, 0xb1, 0x7f, 0xec,
- 0x2c, 0xf6, 0x9c, 0xdf, 0x89, 0x62, 0xc7, 0x58, 0xbf, 0xe1, 0x37, 0x7a,
- 0xd0, 0xa2, 0xe2, 0xc5, 0x40, 0xf3, 0xf8, 0x25, 0x7f, 0xde, 0x26, 0x0f,
- 0xcf, 0xd8, 0x6b, 0x17, 0x1f, 0xb5, 0x8b, 0xfb, 0x3c, 0x53, 0x27, 0x58,
- 0xbf, 0xbb, 0x01, 0x9a, 0x60, 0x2c, 0x5d, 0xf8, 0xc0, 0xaa, 0x70, 0x83,
- 0x22, 0xc8, 0x47, 0x76, 0x44, 0x73, 0xcf, 0x8c, 0xb1, 0x65, 0x46, 0xcd,
- 0xc5, 0x2c, 0xc6, 0x9d, 0x0a, 0x76, 0xfe, 0x4b, 0xa4, 0x76, 0x0d, 0x3e,
- 0xf2, 0x12, 0xde, 0x61, 0xe9, 0x0c, 0x93, 0x23, 0xbb, 0xbf, 0xb3, 0x5b,
- 0xb3, 0x6e, 0xa8, 0x87, 0x4b, 0xfd, 0x9c, 0xe4, 0x80, 0xcd, 0x96, 0x2f,
- 0xfd, 0xfc, 0x22, 0x6f, 0x7e, 0x0e, 0xb1, 0x7f, 0x6b, 0xe1, 0xb0, 0xe3,
- 0x06, 0x7e, 0x7e, 0x36, 0xa8, 0xc4, 0x7c, 0x34, 0x2b, 0xef, 0xda, 0xdd,
- 0x9b, 0x75, 0x44, 0xb0, 0x5f, 0x60, 0x0e, 0xeb, 0x17, 0xe8, 0xc3, 0xb4,
- 0x23, 0x30, 0xf6, 0x63, 0x8d, 0xef, 0xf9, 0xc7, 0x87, 0x7d, 0xdc, 0x6b,
- 0x17, 0xed, 0x6e, 0xcd, 0xba, 0xa2, 0x30, 0x2d, 0x19, 0x27, 0xe1, 0x87,
- 0x37, 0x83, 0x93, 0xac, 0x5c, 0x5b, 0xac, 0x5f, 0xe6, 0x1e, 0x04, 0x69,
- 0x3a, 0xc5, 0x61, 0xe6, 0x7c, 0x62, 0xf4, 0x1c, 0x6b, 0x17, 0xb5, 0x3d,
- 0xac, 0x5f, 0xb3, 0x59, 0x9d, 0xac, 0x5f, 0xa1, 0x9c, 0x6e, 0x2c, 0x5e,
- 0xc2, 0x1a, 0xc5, 0xff, 0xd1, 0xcc, 0x40, 0xcf, 0x49, 0x38, 0x16, 0x2d,
- 0x19, 0x89, 0xbb, 0xee, 0xd5, 0x11, 0x0b, 0x0e, 0x90, 0xf0, 0x8a, 0x03,
- 0x28, 0x30, 0x72, 0xff, 0xfc, 0xc0, 0x8e, 0xc8, 0xc2, 0x6f, 0x43, 0x3d,
- 0x83, 0x58, 0xbf, 0xff, 0x39, 0xdf, 0x51, 0x9e, 0x8e, 0xcf, 0xfa, 0x7b,
- 0x0d, 0x62, 0x89, 0x33, 0x4e, 0x3e, 0x79, 0x6a, 0xec, 0xe2, 0xc5, 0x82,
- 0x2c, 0x5a, 0x32, 0x06, 0xae, 0x21, 0x7b, 0xde, 0x78, 0x96, 0x2f, 0xff,
- 0xff, 0xfa, 0x48, 0x47, 0xd4, 0xf9, 0xf7, 0x71, 0xfe, 0x77, 0xfc, 0xec,
- 0x77, 0xf3, 0x44, 0xde, 0x58, 0xbe, 0x72, 0x60, 0x2c, 0x5e, 0xc0, 0xe3,
- 0x3b, 0x45, 0xbf, 0x21, 0x2d, 0x7f, 0x73, 0x6f, 0xe0, 0x19, 0x62, 0xff,
- 0xff, 0xa1, 0xc8, 0xcd, 0xfe, 0xd1, 0x6f, 0xfc, 0xd0, 0x53, 0xf1, 0x1f,
- 0x8b, 0x17, 0xd3, 0xf1, 0x79, 0x62, 0xfd, 0x9e, 0x04, 0xee, 0xb1, 0x7f,
- 0xfa, 0x7c, 0xe0, 0x98, 0x0f, 0xf2, 0x5b, 0xac, 0x5f, 0x77, 0x06, 0x25,
- 0x8b, 0xc7, 0x7e, 0x2c, 0x5a, 0x4e, 0x78, 0x00, 0x23, 0xbf, 0xa2, 0x7f,
- 0xbe, 0xa2, 0x58, 0xbf, 0xed, 0x6c, 0x20, 0x61, 0x18, 0x75, 0x8b, 0x74,
- 0x58, 0xa9, 0x44, 0x03, 0x98, 0x1c, 0xf2, 0xf9, 0xc8, 0x0e, 0xb1, 0x7d,
- 0xbb, 0x36, 0xea, 0x88, 0xf4, 0xa8, 0x1e, 0x96, 0x88, 0x6f, 0xff, 0x47,
- 0x94, 0xb0, 0xdf, 0x87, 0x91, 0x81, 0x62, 0xfb, 0x8d, 0xdf, 0x45, 0x8b,
- 0x46, 0x41, 0x31, 0x4c, 0x84, 0x03, 0x11, 0x79, 0x32, 0xff, 0xff, 0xd1,
- 0x9b, 0x4c, 0x4e, 0x4f, 0xbb, 0x7d, 0x83, 0xea, 0x32, 0x00, 0xd6, 0x2a,
- 0x08, 0xbe, 0xdd, 0x2a, 0xff, 0xb7, 0x6d, 0x37, 0xe2, 0xcf, 0x2c, 0x5f,
- 0xfe, 0x16, 0x7f, 0x08, 0x18, 0x5e, 0xfe, 0x2c, 0x5e, 0x9d, 0x44, 0xb1,
- 0x73, 0x46, 0x3a, 0x28, 0x48, 0xef, 0x89, 0x17, 0xde, 0x7e, 0xc3, 0x58,
- 0xbf, 0xf4, 0x27, 0x5b, 0x6b, 0x4f, 0xee, 0x2c, 0x5d, 0x3d, 0xe1, 0xf3,
- 0x44, 0x4b, 0x7f, 0xff, 0x8f, 0x18, 0xc1, 0xb6, 0xce, 0x1b, 0x18, 0xe5,
- 0xe9, 0xe2, 0xc5, 0x4a, 0xf8, 0x0e, 0xd0, 0xd5, 0x19, 0xf7, 0x65, 0xee,
- 0xeb, 0x11, 0x1e, 0x8a, 0x7f, 0x08, 0xa6, 0x94, 0xf2, 0x50, 0xc5, 0xf4,
- 0x28, 0x8c, 0x2e, 0xbf, 0xd9, 0xce, 0x48, 0x0c, 0xd9, 0x62, 0xfd, 0x24,
- 0xf3, 0xc5, 0x8b, 0xf3, 0x75, 0xf6, 0x6e, 0xb1, 0x7f, 0xff, 0x87, 0x2d,
- 0xaf, 0x86, 0xc3, 0xf7, 0xf0, 0x89, 0xbc, 0xb1, 0x68, 0xc1, 0xa3, 0x9d,
- 0xcd, 0xbe, 0x4d, 0xc2, 0xba, 0x8c, 0x4f, 0xbf, 0x68, 0xea, 0xaf, 0xfc,
- 0x10, 0x4c, 0x38, 0xe7, 0xe6, 0x6c, 0xb1, 0x7f, 0xef, 0xbe, 0xa0, 0x64,
- 0x33, 0xec, 0xb1, 0x7b, 0x82, 0x02, 0xc5, 0xef, 0x36, 0xeb, 0x17, 0x02,
- 0x56, 0x2f, 0xf8, 0xa7, 0xa8, 0x0e, 0x66, 0x99, 0x62, 0x9c, 0xf4, 0xfc,
- 0x2f, 0x7c, 0x4c, 0x1c, 0x66, 0x26, 0x6b, 0xba, 0x2f, 0x68, 0x0c, 0x3d,
- 0xc7, 0x1b, 0xf6, 0xb7, 0x66, 0xdd, 0x51, 0x61, 0x97, 0xfa, 0x05, 0x39,
- 0xcc, 0x25, 0x8b, 0xb9, 0xc5, 0x8b, 0x9e, 0x0b, 0x17, 0xbd, 0x87, 0x58,
- 0xb1, 0xd6, 0x2b, 0x0d, 0x7f, 0x87, 0x6d, 0x19, 0x88, 0xe6, 0xec, 0xdf,
- 0x46, 0x20, 0x18, 0x24, 0x6b, 0xe8, 0xc0, 0x16, 0x2c, 0x5e, 0x6f, 0xf1,
- 0x62, 0xee, 0xfc, 0xb1, 0x7f, 0x0b, 0x67, 0x21, 0x1d, 0x62, 0xa4, 0xf2,
- 0x08, 0x66, 0xfa, 0x63, 0xe6, 0x25, 0x8b, 0xd2, 0x5b, 0x2c, 0x5a, 0x56,
- 0x2f, 0xa4, 0x10, 0x3a, 0xc5, 0x7c, 0xda, 0x10, 0x8d, 0x0d, 0x31, 0xc7,
- 0x65, 0x88, 0x83, 0xe4, 0xde, 0x51, 0xbf, 0xff, 0xe9, 0x9e, 0x46, 0x78,
- 0x6e, 0x7e, 0xe1, 0xce, 0xe1, 0x9a, 0xd9, 0x62, 0xa3, 0x11, 0x72, 0x49,
- 0x76, 0x9d, 0x95, 0x0f, 0xea, 0x3f, 0xab, 0xfd, 0x19, 0x9a, 0xdd, 0x9b,
- 0x75, 0x45, 0xce, 0x5d, 0xfe, 0x8b, 0x17, 0x8c, 0x90, 0xd6, 0x2f, 0xfb,
- 0x3b, 0x0c, 0xc2, 0xce, 0x98, 0xb1, 0x7f, 0x09, 0xbb, 0xf7, 0xdd, 0x62,
- 0xbe, 0x88, 0xb2, 0x1f, 0xe1, 0xed, 0xe8, 0x08, 0x6b, 0x17, 0x6d, 0xc5,
- 0x8b, 0xe1, 0x04, 0xc2, 0x58, 0xb9, 0x8e, 0xb1, 0x7c, 0xfa, 0xd3, 0x2c,
- 0x5f, 0xfd, 0x84, 0x08, 0xec, 0xf7, 0xdc, 0x80, 0xb1, 0x7d, 0xc9, 0x23,
- 0x56, 0x2b, 0x11, 0x17, 0xc2, 0x23, 0x11, 0xaf, 0xfb, 0x3d, 0xf6, 0x87,
- 0xa6, 0x0b, 0x17, 0xa4, 0xbc, 0xb1, 0x5f, 0x3d, 0x51, 0x1c, 0xd8, 0x0b,
- 0x17, 0x61, 0xd6, 0x2a, 0x4d, 0x4b, 0x09, 0x5f, 0xff, 0xb4, 0xe7, 0x93,
- 0x7e, 0xdc, 0x01, 0xdb, 0xbf, 0x2c, 0x5e, 0x29, 0xed, 0x62, 0xf9, 0xb5,
- 0x08, 0xc1, 0xab, 0x35, 0xc8, 0x52, 0xf6, 0x5e, 0x71, 0xef, 0x8c, 0x91,
- 0x27, 0x21, 0x45, 0xe8, 0x42, 0x86, 0x96, 0x60, 0xf8, 0x45, 0x8b, 0xff,
- 0xff, 0xff, 0xa4, 0x2d, 0xc3, 0x6d, 0xff, 0xd7, 0xaf, 0xe3, 0xa3, 0x36,
- 0x11, 0xb1, 0xae, 0x42, 0xbd, 0xed, 0xb6, 0xe7, 0xeb, 0xd7, 0xf1, 0xcb,
- 0x15, 0x2d, 0xbf, 0x1e, 0xd0, 0x83, 0x84, 0x2d, 0xf2, 0x56, 0xa6, 0xeb,
- 0x6f, 0x49, 0x1b, 0xd4, 0x6c, 0x67, 0x8d, 0x2f, 0xf2, 0x9c, 0x7c, 0x62,
- 0x29, 0x6f, 0x41, 0x21, 0x8d, 0x7f, 0xdc, 0x3e, 0x75, 0x86, 0x0e, 0x56,
- 0x2f, 0xda, 0xdd, 0x9b, 0x75, 0x44, 0x3c, 0x5f, 0xfe, 0xfb, 0xc9, 0xd8,
- 0x66, 0x04, 0x92, 0x82, 0xc5, 0xff, 0xff, 0xef, 0xe1, 0xfe, 0x59, 0xd1,
- 0xb7, 0x8c, 0xe7, 0x24, 0x1e, 0x29, 0x3f, 0x16, 0x2d, 0x19, 0x29, 0x9d,
- 0xe1, 0xdf, 0x0d, 0xfc, 0x99, 0x70, 0x56, 0x35, 0xac, 0x5f, 0xf4, 0xfe,
- 0x76, 0xd4, 0xe0, 0xd6, 0x2f, 0xff, 0x73, 0x0a, 0x61, 0xfc, 0xfb, 0xe1,
- 0x2c, 0x5f, 0xfb, 0x4f, 0xc9, 0x1b, 0x13, 0x9d, 0x62, 0xbe, 0x8b, 0xde,
- 0x1c, 0xf4, 0x47, 0xbd, 0xed, 0xc0, 0xb1, 0x7f, 0xb5, 0x2f, 0xe2, 0x93,
- 0xac, 0x5f, 0xe1, 0x73, 0xa8, 0xc9, 0xbe, 0xb1, 0x7f, 0xff, 0x60, 0xdf,
- 0x98, 0x5c, 0xdf, 0xee, 0x45, 0x9d, 0xac, 0x5f, 0xff, 0xe6, 0x36, 0x2e,
- 0x4f, 0xba, 0x99, 0xe7, 0x21, 0x43, 0x38, 0xb1, 0x5f, 0x46, 0x01, 0x2d,
- 0x5f, 0xff, 0x0b, 0xcf, 0xef, 0x4f, 0x5f, 0xe6, 0x16, 0xeb, 0x17, 0xe7,
- 0xd3, 0x7a, 0x35, 0xac, 0x5f, 0xff, 0xff, 0x7f, 0x35, 0xa9, 0xee, 0x06,
- 0x79, 0xc8, 0x50, 0xce, 0x16, 0x6c, 0x64, 0x16, 0x2f, 0xff, 0xc5, 0x9c,
- 0x76, 0xdb, 0x06, 0x77, 0x8e, 0x93, 0xac, 0x5f, 0x6e, 0xcd, 0xba, 0xa2,
- 0x26, 0x2f, 0xd8, 0xfe, 0xd0, 0x96, 0x2f, 0xa3, 0xff, 0x26, 0xac, 0x5f,
- 0xff, 0xed, 0x16, 0x6d, 0x83, 0xc0, 0xc5, 0xac, 0xdf, 0xf3, 0xd1, 0x62,
- 0xec, 0xd9, 0x62, 0x96, 0x2f, 0x84, 0x7c, 0x1a, 0xc7, 0x42, 0x65, 0x4a,
- 0x2f, 0x3b, 0x65, 0x08, 0x49, 0x7e, 0xf7, 0x36, 0xc0, 0xd6, 0x2f, 0xfb,
- 0xc2, 0x37, 0xaf, 0xf0, 0x0c, 0xb1, 0x58, 0x89, 0xa6, 0x32, 0x11, 0x5d,
- 0x84, 0xb1, 0x7f, 0xbc, 0x26, 0xef, 0xf3, 0xd1, 0x62, 0xfd, 0x9b, 0x63,
- 0xf1, 0x62, 0xa0, 0xaf, 0xbc, 0x64, 0x46, 0xa9, 0x6e, 0x5c, 0xf0, 0x81,
- 0xd2, 0xb9, 0xcc, 0x58, 0xa0, 0xa3, 0x7d, 0xe1, 0x77, 0x84, 0xba, 0x1b,
- 0xdf, 0xf3, 0x31, 0x03, 0x4f, 0x26, 0xac, 0x5f, 0xff, 0xff, 0xff, 0x03,
- 0x38, 0xd1, 0xfd, 0x7d, 0xf7, 0x9e, 0x75, 0xcd, 0x6b, 0x3e, 0x59, 0xe9,
- 0x3f, 0x5c, 0xd3, 0x43, 0x16, 0x2e, 0x16, 0xcb, 0x16, 0xc5, 0x8b, 0x9c,
- 0x2e, 0xb1, 0x44, 0x78, 0xbd, 0x06, 0x43, 0x11, 0xbf, 0xfd, 0xf3, 0x0a,
- 0x7b, 0xfe, 0x0c, 0x4d, 0xba, 0xc5, 0xfc, 0x73, 0x08, 0xb3, 0x65, 0x8b,
- 0xf0, 0x7a, 0xcf, 0xf1, 0x62, 0xa4, 0xf6, 0x70, 0xbe, 0xa0, 0x8c, 0x62,
- 0x85, 0x35, 0xfd, 0xe2, 0x9d, 0xdc, 0x96, 0x2f, 0xc5, 0x3b, 0xb9, 0x2c,
- 0x5f, 0xa7, 0xb8, 0x39, 0xfa, 0x9e, 0xa7, 0x8b, 0x6f, 0xc0, 0xe7, 0x5c,
- 0x1a, 0xc5, 0xfe, 0x70, 0xf0, 0xb3, 0xbf, 0x2c, 0x56, 0x22, 0x81, 0xd0,
- 0x74, 0x57, 0x76, 0x04, 0x58, 0xbd, 0xbb, 0x8d, 0x62, 0xe2, 0x1e, 0x1b,
- 0x77, 0x19, 0xbd, 0xcc, 0x1a, 0xc5, 0x31, 0xe3, 0xf8, 0xaa, 0xfc, 0xfd,
- 0x4f, 0xbc, 0x4b, 0x14, 0xc7, 0x9c, 0x44, 0x37, 0xfe, 0x3f, 0xc5, 0xbf,
- 0x5c, 0xfb, 0x69, 0x62, 0xff, 0xef, 0x73, 0x92, 0xfd, 0xfb, 0xd2, 0x75,
- 0x8b, 0xfe, 0x9f, 0xcf, 0x43, 0xc9, 0x6c, 0xb1, 0x7f, 0xf0, 0xbd, 0xc2,
- 0x10, 0xbd, 0x09, 0x35, 0x62, 0xf7, 0x18, 0x96, 0x2f, 0xff, 0xd3, 0xa0,
- 0x7e, 0x7a, 0x45, 0x32, 0x7e, 0x60, 0xd6, 0x2f, 0xfb, 0xff, 0x9e, 0x90,
- 0xcd, 0x4a, 0xc5, 0xfe, 0x99, 0x8b, 0x3a, 0x3e, 0x96, 0x2b, 0xe8, 0xc8,
- 0x65, 0x82, 0x3b, 0xbf, 0xf8, 0x4d, 0xb1, 0x61, 0xce, 0xfa, 0xe2, 0xc5,
- 0x62, 0xa1, 0xf8, 0x91, 0x88, 0xef, 0x88, 0xfe, 0x87, 0x20, 0x65, 0xd7,
- 0xf8, 0x98, 0x04, 0xd0, 0x25, 0x8b, 0xf7, 0xb0, 0x13, 0xa5, 0x8b, 0x9f,
- 0xd2, 0x7b, 0x2e, 0x63, 0x7d, 0xb7, 0xc5, 0xb2, 0xc5, 0x4a, 0xb6, 0xac,
- 0x94, 0xc4, 0xd0, 0xb7, 0x11, 0x5d, 0xee, 0xc7, 0xd1, 0x62, 0xfb, 0x63,
- 0xce, 0x96, 0x2f, 0xb7, 0x11, 0x1a, 0xb1, 0x73, 0x32, 0xc5, 0x41, 0x10,
- 0x0c, 0x42, 0x44, 0x86, 0x12, 0xdf, 0xf9, 0xbb, 0xe4, 0x51, 0xee, 0x5e,
- 0xe2, 0xc5, 0xff, 0xed, 0x4c, 0x5c, 0xdf, 0xef, 0xef, 0x38, 0x45, 0x8b,
- 0x87, 0xf5, 0x8c, 0x3c, 0xfb, 0xff, 0xde, 0x86, 0x6b, 0x4d, 0x0c, 0x3c,
- 0xee, 0xb1, 0x7f, 0xfb, 0x1a, 0x02, 0x1e, 0x3b, 0x74, 0x9d, 0x2c, 0x56,
- 0x22, 0xf5, 0x8a, 0x04, 0x97, 0x7f, 0xb5, 0x3f, 0x61, 0xc0, 0xeb, 0x17,
- 0xfd, 0xe1, 0x7e, 0x47, 0xf7, 0x02, 0xc5, 0xff, 0x4c, 0x31, 0xcb, 0x24,
- 0xd5, 0x8b, 0xff, 0xf7, 0xe7, 0x40, 0xe6, 0x0f, 0xc2, 0x6d, 0xf3, 0x4b,
- 0x15, 0x1e, 0x8c, 0x88, 0x8e, 0xbc, 0x6f, 0x77, 0x8e, 0xb1, 0x7a, 0x39,
- 0xb4, 0xb1, 0x7f, 0xda, 0x9f, 0x0f, 0xe2, 0x6e, 0x2c, 0x5f, 0xf6, 0x73,
- 0x82, 0x2d, 0x8d, 0x89, 0x62, 0xfd, 0x87, 0x3c, 0x8d, 0x62, 0xff, 0xc6,
- 0x6d, 0xc9, 0x7e, 0xfd, 0x27, 0x58, 0xbf, 0xfb, 0x8c, 0xdb, 0xe6, 0xf2,
- 0x53, 0xba, 0xc5, 0xb2, 0x24, 0x57, 0xfc, 0xa3, 0x88, 0x57, 0xa7, 0x5c,
- 0x58, 0xbf, 0xd0, 0x9f, 0xe6, 0x7b, 0x8b, 0x17, 0xfe, 0x2c, 0xe6, 0xff,
- 0x70, 0x8f, 0xc5, 0x8a, 0x88, 0xfd, 0x3a, 0x19, 0xdf, 0x31, 0x99, 0xb2,
- 0xc5, 0x61, 0xe4, 0x88, 0x96, 0xfe, 0xd8, 0xcd, 0x3c, 0x8d, 0x62, 0xff,
- 0xfb, 0x3a, 0x60, 0xfe, 0x26, 0xe1, 0x93, 0xa0, 0x2c, 0x53, 0xa2, 0x0f,
- 0xe6, 0x17, 0xfd, 0x30, 0x33, 0x35, 0xcc, 0x0d, 0x62, 0xff, 0x42, 0x4d,
- 0x7f, 0xb6, 0xcb, 0x17, 0xfc, 0x01, 0x94, 0xc3, 0xfc, 0x02, 0xc5, 0xcc,
- 0x6a, 0xc5, 0x6c, 0x8c, 0x27, 0x3b, 0xd1, 0xa9, 0x1d, 0x5e, 0x21, 0x0d,
- 0x62, 0x86, 0xba, 0xff, 0x90, 0xfc, 0xec, 0xd1, 0xc6, 0x22, 0x20, 0xd1,
- 0xd7, 0xe1, 0xd8, 0x03, 0x62, 0x86, 0xd7, 0xa1, 0x48, 0x28, 0x72, 0x18,
- 0x79, 0x7f, 0xd8, 0x5e, 0xe7, 0xe5, 0xb4, 0xb1, 0x7e, 0x26, 0x72, 0x02,
- 0xc5, 0xf8, 0x31, 0x4e, 0xb6, 0x58, 0xae, 0xa7, 0xa2, 0x19, 0x35, 0xff,
- 0xce, 0xc0, 0xd4, 0x97, 0xbf, 0x90, 0x58, 0xbf, 0xda, 0xc9, 0xee, 0x0e,
- 0x75, 0x8b, 0xfb, 0x27, 0xb8, 0x39, 0xd6, 0x2f, 0xa7, 0x77, 0x2e, 0xa7,
- 0xc5, 0xa3, 0x4b, 0xe6, 0x7d, 0x62, 0xc5, 0xfe, 0xfb, 0x9f, 0xdc, 0x7d,
- 0x2c, 0x56, 0x27, 0xc4, 0xf0, 0x89, 0xf9, 0x29, 0x42, 0x97, 0xc7, 0x42,
- 0x21, 0xb9, 0xce, 0xb1, 0x7d, 0x0f, 0x99, 0xc5, 0x8b, 0xec, 0xd8, 0xc8,
- 0x2c, 0x5c, 0xc6, 0x2a, 0x21, 0x72, 0xbb, 0x3e, 0xf2, 0x25, 0x11, 0x2d,
- 0x44, 0x8b, 0x5f, 0x42, 0x1a, 0xfd, 0xfc, 0xd8, 0x44, 0xb1, 0x7c, 0xda,
- 0x9e, 0x8b, 0x14, 0x33, 0xcd, 0x01, 0x4d, 0xfc, 0x39, 0x71, 0xe1, 0xd6,
- 0x2f, 0xef, 0xb1, 0x7b, 0x3e, 0xb1, 0x7d, 0x0c, 0x62, 0x58, 0xbf, 0xdb,
- 0x64, 0x08, 0x4d, 0xc5, 0x8a, 0xc4, 0x57, 0xb9, 0x6c, 0x45, 0xac, 0x43,
- 0x7a, 0x4f, 0x05, 0x8b, 0xff, 0xe7, 0x3c, 0x9b, 0xd7, 0x82, 0x2c, 0x18,
- 0xb6, 0x58, 0xbc, 0x42, 0x35, 0x62, 0xfb, 0xe1, 0xb6, 0xcb, 0x15, 0xda,
- 0x2d, 0x34, 0x3a, 0x4a, 0x9e, 0x1e, 0xbf, 0xdb, 0x31, 0x9f, 0xfe, 0x69,
- 0x62, 0xf3, 0xcc, 0x4b, 0x15, 0x87, 0xa7, 0xf3, 0x6b, 0x46, 0x05, 0x5b,
- 0xd5, 0xd9, 0x86, 0xfe, 0xc6, 0x50, 0x1f, 0x19, 0x96, 0x4e, 0x72, 0x9b,
- 0x0b, 0x3e, 0xce, 0x1e, 0x1e, 0xd1, 0x43, 0xdf, 0x51, 0x8d, 0x9e, 0x1f,
- 0x5f, 0x97, 0x14, 0xd0, 0xc8, 0x01, 0xe1, 0x46, 0xa1, 0xc9, 0xda, 0xdf,
- 0x4a, 0xa3, 0x14, 0x62, 0x9d, 0x1d, 0xa3, 0xa1, 0xa2, 0x64, 0x3b, 0xc2,
- 0x42, 0x42, 0xff, 0xf0, 0x23, 0x3d, 0x91, 0x14, 0x9f, 0xc3, 0xfa, 0xc5,
- 0xfb, 0x35, 0xc7, 0x95, 0x8b, 0xc1, 0x6a, 0x16, 0x46, 0xcb, 0x17, 0xfe,
- 0xd0, 0xb6, 0xcf, 0xc4, 0x52, 0x35, 0x8b, 0xf6, 0x70, 0x36, 0xd2, 0xc5,
- 0xfe, 0xde, 0x7f, 0x27, 0xf8, 0x96, 0x2f, 0x4e, 0x1a, 0xb1, 0x58, 0x7a,
- 0x44, 0x6b, 0x7c, 0xd0, 0xfe, 0x2c, 0x5f, 0xdf, 0xcc, 0xf7, 0xf1, 0x62,
- 0x86, 0x79, 0xfe, 0x22, 0xbe, 0x6e, 0xc7, 0xda, 0xc5, 0xfb, 0x9f, 0x9e,
- 0xf8, 0xb1, 0x6f, 0xc9, 0xe7, 0xb9, 0x2d, 0xe3, 0x75, 0xda, 0xc5, 0xe3,
- 0x27, 0xb5, 0x8b, 0xc7, 0x11, 0xd6, 0x2a, 0x4d, 0xee, 0x0f, 0xdf, 0x3f,
- 0x41, 0x04, 0x58, 0xbf, 0xa4, 0xb0, 0x63, 0x95, 0x8a, 0xc3, 0xd3, 0xd1,
- 0x3d, 0xff, 0x98, 0x8d, 0x6f, 0x4f, 0x98, 0x0b, 0x17, 0xc3, 0x32, 0x49,
- 0x62, 0xf0, 0xb5, 0x05, 0x8b, 0xff, 0xf7, 0x85, 0xa6, 0xe6, 0x17, 0xf3,
- 0x0a, 0x1c, 0x58, 0xad, 0x8f, 0xc9, 0xc7, 0xaa, 0x51, 0x6e, 0xd0, 0x95,
- 0xa5, 0x8b, 0xf3, 0x67, 0xb0, 0xeb, 0x17, 0x02, 0x64, 0xd9, 0x90, 0x65,
- 0xff, 0xfd, 0x9d, 0x0b, 0x39, 0x87, 0x92, 0x37, 0xef, 0x27, 0x58, 0xbf,
- 0x0b, 0x40, 0xeb, 0x2b, 0x17, 0x7d, 0x96, 0x2f, 0xff, 0xb6, 0xda, 0x4b,
- 0x3c, 0xfd, 0x87, 0x9d, 0xf9, 0x62, 0xe7, 0x35, 0x62, 0xc2, 0x58, 0xac,
- 0x44, 0xab, 0x8b, 0xc4, 0xa9, 0xc1, 0x8b, 0xee, 0x7e, 0x40, 0xb1, 0x7f,
- 0xb4, 0x03, 0xb4, 0x3a, 0xf9, 0x62, 0xd1, 0xeb, 0x15, 0x87, 0x98, 0x69,
- 0xbd, 0xf7, 0xa4, 0xba, 0x2c, 0x5f, 0xff, 0x0a, 0x05, 0x87, 0xf4, 0x32,
- 0x3d, 0x88, 0x0b, 0x17, 0xa7, 0x3b, 0x58, 0xa5, 0x8a, 0x23, 0x53, 0xe1,
- 0xdb, 0xff, 0xa7, 0x53, 0xbc, 0xb8, 0x1b, 0xc2, 0x58, 0xaf, 0xa6, 0x06,
- 0x44, 0x9e, 0x7b, 0x8e, 0x20, 0xbb, 0x91, 0x91, 0xa2, 0xfd, 0x5c, 0x6b,
- 0x27, 0x92, 0xf8, 0x20, 0x8d, 0xef, 0x1b, 0xf7, 0x71, 0xec, 0x99, 0xd7,
- 0x74, 0xe4, 0x72, 0x1f, 0xc3, 0xd4, 0x0b, 0x24, 0x55, 0xc5, 0xbf, 0x43,
- 0x00, 0x47, 0x91, 0xcd, 0xe6, 0x46, 0x4b, 0x5a, 0x64, 0x94, 0x82, 0x7f,
- 0xea, 0xd1, 0xeb, 0x17, 0xf9, 0x81, 0xdf, 0x89, 0xbe, 0xb1, 0x7f, 0x3f,
- 0x60, 0xd6, 0x0d, 0x62, 0x9c, 0xfe, 0x34, 0x2b, 0xf3, 0x4b, 0xce, 0xd0,
- 0x58, 0xb8, 0x71, 0x98, 0x79, 0x5f, 0x2e, 0xbf, 0xbb, 0x83, 0x6c, 0x66,
- 0xeb, 0x17, 0xff, 0xff, 0xd8, 0xe4, 0xde, 0x92, 0x6d, 0xa7, 0x5d, 0x70,
- 0x85, 0xe2, 0xc0, 0x4a, 0xc5, 0xf3, 0xc3, 0x91, 0x98, 0x8a, 0xde, 0x19,
- 0xd4, 0xa6, 0x33, 0x90, 0xdd, 0xa9, 0x54, 0x63, 0xf9, 0x41, 0x57, 0xf6,
- 0xb3, 0xcf, 0xf1, 0x2c, 0x5f, 0xff, 0xff, 0xf7, 0x52, 0xcf, 0x4e, 0x77,
- 0xee, 0xb9, 0x0f, 0xe3, 0xc3, 0x9d, 0x4c, 0x2c, 0xf7, 0x0c, 0x3a, 0xc5,
- 0xa3, 0x70, 0xaa, 0x32, 0xa3, 0x42, 0xeb, 0xee, 0x3e, 0xc1, 0x55, 0x8b,
- 0xf0, 0x88, 0x9e, 0x0b, 0x15, 0x1b, 0xa2, 0x18, 0x28, 0x6f, 0xc2, 0x8b,
- 0xff, 0x46, 0xe1, 0x57, 0xda, 0x7a, 0xef, 0xcc, 0x58, 0xba, 0x35, 0x12,
- 0xc5, 0xd9, 0xa5, 0x8b, 0xe0, 0xa7, 0xd8, 0x28, 0xb1, 0x5f, 0x3c, 0x26,
- 0x17, 0xb8, 0x11, 0x2c, 0x54, 0x6e, 0x8e, 0x50, 0xa2, 0x67, 0xd7, 0xe3,
- 0x88, 0x6f, 0xfd, 0x90, 0x26, 0x36, 0x2e, 0x4f, 0x96, 0x2f, 0xbc, 0xfa,
- 0xc5, 0x8a, 0x0b, 0x67, 0xc5, 0x88, 0x17, 0xfd, 0x9e, 0x33, 0x66, 0xd3,
- 0xc4, 0xb1, 0x7f, 0x42, 0x35, 0x6c, 0x15, 0x8d, 0x61, 0x62, 0xc5, 0xe2,
- 0xcf, 0xac, 0x5f, 0xce, 0x7c, 0x9d, 0x1a, 0xb1, 0x43, 0x3c, 0xad, 0xc7,
- 0x2f, 0x05, 0xa8, 0x5b, 0x8d, 0x16, 0x2d, 0x1c, 0xb1, 0x7f, 0xb3, 0x9c,
- 0xc7, 0x2d, 0xd6, 0x28, 0x28, 0x9c, 0x70, 0x54, 0x9e, 0x34, 0x3c, 0x8d,
- 0xa1, 0x21, 0x1a, 0xc8, 0xc0, 0x60, 0x42, 0xb7, 0xb4, 0xdc, 0x58, 0xbf,
- 0xa3, 0x73, 0x3f, 0xfc, 0xd9, 0x62, 0xe8, 0xee, 0xd6, 0x2d, 0xf5, 0x8a,
- 0xea, 0x88, 0x18, 0xdc, 0x74, 0x2d, 0x9b, 0x08, 0x72, 0xff, 0x82, 0xbc,
- 0xc2, 0x2c, 0x6d, 0xd6, 0x2c, 0xcb, 0x15, 0x1b, 0x9e, 0x6f, 0x67, 0x97,
- 0x1b, 0x2b, 0x17, 0xa2, 0xe4, 0xac, 0x5f, 0x0f, 0x0a, 0x25, 0x8b, 0x9f,
- 0xcb, 0x14, 0xe6, 0xeb, 0xe4, 0x74, 0x73, 0xf8, 0xf2, 0xc5, 0xfe, 0xef,
- 0xdd, 0xc0, 0x44, 0x6a, 0xc5, 0xff, 0xa6, 0x22, 0xce, 0x8c, 0x73, 0xba,
- 0xc5, 0x31, 0xfc, 0x08, 0xe2, 0xfc, 0x00, 0x37, 0x7c, 0x58, 0xbf, 0xff,
- 0xe1, 0xbe, 0x6a, 0x22, 0xce, 0x9f, 0xc1, 0xcf, 0x39, 0x26, 0xac, 0x5b,
- 0xee, 0x89, 0x31, 0x15, 0x5f, 0xfe, 0x78, 0xa1, 0x9d, 0xc3, 0xa9, 0xd9,
- 0x89, 0x62, 0xe6, 0x08, 0xb1, 0x7f, 0xff, 0xb9, 0x9e, 0xeb, 0xfc, 0xde,
- 0x43, 0x2c, 0x1f, 0xde, 0x25, 0x8a, 0xd9, 0x56, 0x8e, 0x42, 0x40, 0xd8,
- 0x4d, 0x6f, 0x0b, 0x4f, 0x94, 0x32, 0x6f, 0x86, 0x6f, 0xff, 0xff, 0xff,
- 0xff, 0xff, 0xf0, 0xe3, 0x5f, 0x50, 0xb5, 0x8d, 0x8d, 0x0a, 0xf5, 0x0b,
- 0x71, 0xaa, 0x13, 0xd7, 0x02, 0xd8, 0x5a, 0xe7, 0x58, 0xd7, 0x1a, 0xc6,
- 0x3e, 0xa1, 0x6b, 0x1a, 0x05, 0x63, 0x6e, 0xb1, 0xac, 0x71, 0xbe, 0x75,
- 0x0a, 0x48, 0x54, 0x2b, 0xd4, 0x29, 0x21, 0x6a, 0x15, 0xeb, 0x1a, 0xe3,
- 0x68, 0xda, 0x35, 0xac, 0x5e, 0x8d, 0x41, 0x48, 0xd9, 0x62, 0xfe, 0x8d,
- 0x41, 0x4e, 0xbd, 0x39, 0xe5, 0x8a, 0x0a, 0x2e, 0xcc, 0x85, 0x65, 0x7c,
- 0xc6, 0x8e, 0xd1, 0xb4, 0x77, 0xf1, 0xac, 0xb6, 0xf0, 0x50, 0x89, 0x62,
- 0xfd, 0x1b, 0x85, 0x45, 0xe7, 0x58, 0xbf, 0xdd, 0xcf, 0xb3, 0x3b, 0x82,
- 0xc5, 0xfd, 0x8f, 0xe2, 0x9e, 0xd6, 0x2c, 0x6a, 0xc5, 0x46, 0xe8, 0xc7,
- 0x0a, 0x10, 0x46, 0xa3, 0x28, 0xd6, 0x6b, 0x1c, 0x5b, 0x7b, 0x81, 0xec,
- 0xb1, 0x6f, 0xac, 0x5c, 0x5b, 0x2c, 0x50, 0x50, 0xf2, 0xb6, 0x20, 0x10,
- 0x95, 0xd1, 0xd1, 0xba, 0xc5, 0xed, 0x73, 0x8b, 0x17, 0x17, 0x16, 0x28,
- 0x2a, 0x6d, 0x7a, 0x0f, 0x58, 0x6b, 0x16, 0x1a, 0xc5, 0x31, 0xa4, 0xe0,
- 0x95, 0xe3, 0xce, 0xeb, 0x14, 0x14, 0x46, 0xf4, 0x6c, 0xaa, 0x16, 0x25,
- 0xe1, 0x05, 0xfd, 0x1a, 0x48, 0x6d, 0xbc, 0xac, 0x5f, 0xd1, 0xac, 0x28,
- 0x51, 0xd2, 0x75, 0x8a, 0x8d, 0x0f, 0xbe, 0x35, 0x9a, 0x5e, 0x8d, 0x71,
- 0x6c, 0xb1, 0x7f, 0xfe, 0x1f, 0x5c, 0xe1, 0x6d, 0xb3, 0x47, 0xf5, 0xeb,
- 0xf8, 0xe5, 0x8b, 0xf9, 0x8b, 0x6f, 0xcc, 0x7a, 0xc5, 0xe3, 0x99, 0xc5,
- 0x8b, 0xd0, 0x90, 0x2c, 0x50, 0xcf, 0xb7, 0x0c, 0x58, 0x7e, 0xfd, 0xf6,
- 0xf3, 0x41, 0x62, 0xff, 0x05, 0x7a, 0xf0, 0x07, 0xce, 0x2c, 0x5f, 0x16,
- 0x66, 0x96, 0x2e, 0xfb, 0x2c, 0x56, 0x8d, 0xc7, 0x42, 0x1b, 0xfc, 0x67,
- 0x59, 0x29, 0x84, 0xac, 0x53, 0x9e, 0xc3, 0x11, 0xde, 0xdf, 0x6f, 0xac,
- 0x5f, 0xf0, 0x3a, 0xf2, 0x5f, 0x66, 0xf2, 0xc5, 0xfa, 0x78, 0x16, 0xb1,
- 0xbc, 0x6e, 0xb1, 0x71, 0xce, 0xb1, 0x4e, 0x88, 0xee, 0x1e, 0x08, 0xea,
- 0xfd, 0x3c, 0x17, 0xdd, 0x62, 0xba, 0xa6, 0x0b, 0x08, 0x57, 0x70, 0xbe,
- 0x96, 0x2f, 0xd0, 0x6d, 0x36, 0xeb, 0x17, 0x3c, 0x4b, 0x15, 0x27, 0x83,
- 0x85, 0x37, 0xf8, 0xb3, 0xb8, 0x13, 0x6c, 0xb1, 0x5a, 0x3d, 0x4e, 0x10,
- 0x5f, 0xb8, 0x26, 0x20, 0x2c, 0x57, 0x53, 0xca, 0xf1, 0x15, 0xfc, 0x59,
- 0xd0, 0xb3, 0x8b, 0x14, 0x73, 0xd2, 0x01, 0x25, 0xee, 0x38, 0x16, 0x2f,
- 0x9c, 0xa7, 0x8b, 0x15, 0x87, 0xc0, 0xe4, 0x5f, 0x1d, 0xbf, 0xf6, 0x6c,
- 0x6b, 0x0f, 0x44, 0xc1, 0xac, 0x5f, 0xa4, 0xe6, 0x37, 0x96, 0x2f, 0x06,
- 0x18, 0x69, 0x17, 0xbd, 0xfc, 0x48, 0x8c, 0x34, 0x37, 0xe7, 0x35, 0x88,
- 0x0b, 0x16, 0x62, 0x3d, 0x8f, 0x18, 0x5f, 0xff, 0xfd, 0x3b, 0x75, 0xe0,
- 0xa7, 0xbf, 0x7f, 0x0f, 0x9e, 0x29, 0x00, 0x25, 0x62, 0xe8, 0xec, 0x58,
- 0xbe, 0xf4, 0x59, 0xe5, 0x8b, 0x0d, 0x62, 0xc1, 0x16, 0x28, 0x68, 0xd9,
- 0xc7, 0x56, 0x1a, 0x11, 0x21, 0x82, 0x55, 0x2a, 0xfd, 0x47, 0x1c, 0xee,
- 0x8b, 0x7e, 0x82, 0x08, 0x51, 0x14, 0x3f, 0xef, 0xdf, 0x20, 0xb2, 0x38,
- 0x22, 0xc5, 0xcc, 0xcb, 0x16, 0xfb, 0x9e, 0x4b, 0x19, 0xdf, 0x9f, 0xa6,
- 0x0b, 0x8b, 0x17, 0xff, 0x85, 0x3d, 0xff, 0x36, 0x90, 0xfb, 0x87, 0x16,
- 0x2a, 0x4f, 0xe7, 0x85, 0x57, 0xff, 0xf0, 0x35, 0x3d, 0x75, 0x3e, 0xee,
- 0x12, 0x6e, 0x98, 0x35, 0x8b, 0xe3, 0x38, 0xc0, 0x58, 0xba, 0x2f, 0xac,
- 0x5f, 0xf8, 0xfd, 0x71, 0xf4, 0xe7, 0x93, 0x56, 0x29, 0xcf, 0x69, 0x86,
- 0x6f, 0xfc, 0xf1, 0x75, 0xfc, 0xbe, 0x85, 0x1e, 0xb1, 0x7f, 0x30, 0xe0,
- 0x52, 0x75, 0x8a, 0xea, 0x9c, 0x94, 0x90, 0xe9, 0x87, 0xef, 0xc0, 0x20,
- 0x24, 0x5b, 0xff, 0xef, 0x90, 0xbd, 0xd4, 0xb0, 0x27, 0x9f, 0x02, 0x2c,
- 0x5c, 0xe0, 0x58, 0xad, 0xcf, 0xb0, 0x22, 0xad, 0xc2, 0xfa, 0xc5, 0xef,
- 0x0a, 0x3d, 0x62, 0xf8, 0x26, 0xb9, 0xc5, 0x8a, 0xc3, 0xc7, 0x72, 0x1b,
- 0xdc, 0xcd, 0x96, 0x2f, 0xbc, 0x53, 0xb2, 0xc5, 0x4a, 0x39, 0x4d, 0x25,
- 0xd2, 0xfb, 0x10, 0x08, 0x7a, 0xff, 0xec, 0x2e, 0xfd, 0xd7, 0x80, 0x3e,
- 0x71, 0x62, 0xfd, 0x3a, 0xee, 0x1c, 0x58, 0xbf, 0xff, 0x39, 0x6f, 0xcf,
- 0x0c, 0xa7, 0xbf, 0xbe, 0x12, 0xc5, 0xf8, 0x5e, 0x7d, 0xa5, 0x62, 0xb1,
- 0x1e, 0x1b, 0xa4, 0x1c, 0xa8, 0x95, 0x6f, 0xf7, 0xe7, 0x6d, 0x4e, 0x0d,
- 0x62, 0xfd, 0x1f, 0x1b, 0x02, 0x4e, 0xb1, 0x7e, 0x7e, 0x7b, 0x3e, 0xb1,
- 0x7f, 0xa4, 0xa7, 0x92, 0xe7, 0x58, 0xbc, 0xde, 0xe2, 0xc5, 0x1a, 0x79,
- 0xda, 0x31, 0xbc, 0x10, 0x72, 0xb1, 0x52, 0x98, 0xee, 0x1a, 0x6e, 0x62,
- 0xee, 0xc2, 0x23, 0xbf, 0xfc, 0xc4, 0x2c, 0xf1, 0x37, 0xcb, 0x34, 0xb1,
- 0x7b, 0xec, 0x17, 0x58, 0xbf, 0x74, 0x14, 0x33, 0x8b, 0x17, 0xfe, 0x78,
- 0xba, 0xce, 0x10, 0xff, 0x2b, 0x17, 0xb9, 0x83, 0x58, 0xa9, 0x3d, 0xd0,
- 0x20, 0x5f, 0x01, 0xc8, 0x4b, 0x15, 0x88, 0xcb, 0x68, 0x44, 0x08, 0x86,
- 0xf0, 0xf3, 0x65, 0x8b, 0xdd, 0x27, 0x4b, 0x17, 0xf3, 0x44, 0xff, 0x10,
- 0x16, 0x2b, 0x0f, 0xb1, 0xc7, 0xbe, 0x3f, 0x7d, 0x1f, 0xd6, 0x42, 0x8b,
- 0x17, 0xf8, 0xa6, 0x3b, 0x09, 0xcd, 0x58, 0xbf, 0xde, 0x6e, 0xf8, 0xdd,
- 0x86, 0xb1, 0x69, 0x58, 0xbc, 0xf2, 0x4b, 0x15, 0xa3, 0x59, 0xe1, 0x1a,
- 0x0a, 0x36, 0x31, 0xa3, 0x86, 0x96, 0x16, 0x9a, 0x51, 0xbc, 0x32, 0xfb,
- 0x8c, 0x95, 0xe7, 0x0b, 0x63, 0xe1, 0x61, 0x14, 0xa3, 0x1d, 0x47, 0x52,
- 0x78, 0xce, 0x7f, 0x1a, 0xc8, 0x12, 0x42, 0xe8, 0xe5, 0x0e, 0xcf, 0x42,
- 0x7f, 0xa1, 0x6c, 0x71, 0x61, 0x86, 0xa1, 0x18, 0xef, 0x1d, 0xe0, 0xb1,
- 0x61, 0x2c, 0x5f, 0xb5, 0x9d, 0x27, 0xb5, 0x8b, 0xc5, 0x9e, 0x58, 0xbf,
- 0xfd, 0xdc, 0x39, 0xc9, 0x7e, 0xfd, 0xe9, 0x3a, 0xc5, 0x69, 0x12, 0x84,
- 0x56, 0x18, 0xe5, 0xff, 0xb6, 0xc2, 0x90, 0xfc, 0x6b, 0x71, 0x62, 0xff,
- 0x67, 0x46, 0x7d, 0xf0, 0x96, 0x2e, 0x2f, 0x61, 0xfa, 0x92, 0x0d, 0xfe,
- 0xfc, 0xbf, 0x81, 0x30, 0x58, 0xbd, 0xe7, 0xc5, 0x8b, 0xd8, 0x37, 0x58,
- 0xbe, 0xee, 0x12, 0x75, 0x8a, 0xea, 0x7b, 0x92, 0x39, 0xe1, 0xca, 0x74,
- 0x75, 0x70, 0xac, 0x38, 0x47, 0xde, 0x17, 0xb8, 0xb1, 0x7f, 0xff, 0xfc,
- 0x6f, 0x52, 0xc3, 0x4d, 0xee, 0x1c, 0xea, 0x59, 0xf2, 0xc0, 0xfa, 0xf5,
- 0xfc, 0x72, 0xc5, 0xff, 0x47, 0xb7, 0xa2, 0x83, 0xea, 0x25, 0x8b, 0xf7,
- 0x5d, 0xe4, 0x3e, 0xd6, 0x2f, 0xfa, 0x60, 0x1b, 0x6b, 0xd3, 0x8b, 0x17,
- 0xff, 0xff, 0xfd, 0xce, 0xbf, 0xcd, 0xa4, 0x3e, 0xe1, 0xce, 0xa2, 0xdf,
- 0x5a, 0x9e, 0xb1, 0x1b, 0xdf, 0x5e, 0xbf, 0x8e, 0x58, 0xbf, 0xbb, 0xeb,
- 0x16, 0x66, 0xeb, 0x14, 0x15, 0x5c, 0xb9, 0x0b, 0x63, 0xb3, 0x0a, 0x6c,
- 0x8e, 0x3f, 0x73, 0x57, 0x1e, 0x68, 0x47, 0x00, 0xfc, 0x8b, 0xbc, 0x72,
- 0x28, 0x56, 0xdf, 0xbf, 0x20, 0x98, 0xf5, 0x8b, 0x8e, 0xeb, 0x14, 0xb1,
- 0x40, 0x34, 0x61, 0x8b, 0xdf, 0xd0, 0x81, 0xe2, 0x90, 0x8b, 0x16, 0x02,
- 0xc5, 0x3a, 0x2d, 0x00, 0x9c, 0x44, 0x42, 0x32, 0xba, 0x3a, 0x56, 0x2f,
- 0x49, 0xae, 0xb1, 0x7e, 0x98, 0xba, 0xe6, 0xcb, 0x17, 0xc3, 0x9e, 0x4a,
- 0xc5, 0xd2, 0x75, 0x8b, 0xa7, 0xb5, 0x8b, 0xfb, 0x98, 0x7e, 0x83, 0xc5,
- 0x8b, 0xed, 0xb6, 0x17, 0x96, 0x2b, 0xaa, 0x34, 0xe4, 0xb0, 0x64, 0x51,
- 0x0b, 0xf0, 0x60, 0x46, 0x14, 0x49, 0xb1, 0xf0, 0x6b, 0xd0, 0xf0, 0xba,
- 0x3a, 0x37, 0x58, 0xbf, 0xfc, 0x09, 0x2d, 0xfa, 0xe1, 0x0a, 0x19, 0xc5,
- 0x8b, 0xf0, 0x34, 0xfd, 0x81, 0x62, 0xfd, 0xe6, 0x83, 0x81, 0x62, 0xfe,
- 0xeb, 0xdf, 0x8a, 0x46, 0xb1, 0x66, 0xed, 0x10, 0x64, 0x55, 0xc2, 0x8b,
- 0xff, 0x08, 0xf3, 0x9c, 0x2c, 0xe8, 0xcb, 0x17, 0xf3, 0x16, 0x6c, 0x64,
- 0x16, 0x2f, 0xd3, 0x13, 0x36, 0x96, 0x28, 0x07, 0xaf, 0xc2, 0xfa, 0xed,
- 0x3b, 0xcf, 0xc3, 0x3f, 0x86, 0xbe, 0x84, 0xb5, 0xee, 0xb0, 0xdd, 0x62,
- 0xfe, 0xeb, 0xc6, 0x9e, 0xe0, 0xb1, 0x70, 0x38, 0xb1, 0x4e, 0x79, 0x2c,
- 0x63, 0x7f, 0xfd, 0xd4, 0xb3, 0xcf, 0x9b, 0x14, 0xf9, 0xce, 0xb1, 0x7f,
- 0xdc, 0xeb, 0x85, 0x22, 0x0b, 0xf1, 0x62, 0xf7, 0x5e, 0xe0, 0xb1, 0x7f,
- 0x8f, 0xf7, 0xf1, 0x49, 0xd6, 0x2f, 0x8f, 0x20, 0xe2, 0xc5, 0x4a, 0xec,
- 0x46, 0x47, 0x3c, 0x69, 0xab, 0xc7, 0xb8, 0x74, 0x9f, 0xb5, 0x00, 0x80,
- 0x94, 0x38, 0x7e, 0x22, 0x10, 0xcc, 0xee, 0x84, 0x68, 0xb1, 0x7e, 0x8d,
- 0xcd, 0x1c, 0xec, 0xb1, 0x7f, 0xff, 0x6b, 0xa9, 0x67, 0x4c, 0xd4, 0x3a,
- 0xc8, 0xda, 0x2e, 0x2c, 0x5f, 0xfe, 0xd7, 0xc3, 0x61, 0xf5, 0x30, 0x00,
- 0x70, 0x8b, 0x17, 0xff, 0x60, 0x61, 0x0e, 0x27, 0x3e, 0x10, 0x16, 0x2f,
- 0xff, 0xfd, 0xdc, 0x9a, 0x58, 0x3f, 0xbc, 0x5d, 0x79, 0x9d, 0xc3, 0x58,
- 0x1a, 0xc5, 0x3a, 0x2e, 0x89, 0x1e, 0xb1, 0x38, 0xf6, 0x62, 0x28, 0xc3,
- 0x2f, 0xe9, 0x37, 0x07, 0x1d, 0x1b, 0xac, 0x5f, 0x78, 0x53, 0xb2, 0xc5,
- 0xfd, 0x06, 0xd7, 0x1c, 0x6b, 0x17, 0xf6, 0x7f, 0x0f, 0x3b, 0xac, 0x5c,
- 0x3c, 0x58, 0xa9, 0x3f, 0x38, 0x17, 0x39, 0x75, 0xf9, 0xf4, 0xfd, 0x31,
- 0x62, 0xa0, 0x99, 0x23, 0x9b, 0xfa, 0x12, 0xe1, 0x0b, 0x6f, 0xa3, 0xb3,
- 0x52, 0xb1, 0x7f, 0x4f, 0x3f, 0x25, 0xe5, 0x8b, 0xff, 0xfb, 0xb8, 0x70,
- 0xf8, 0x5d, 0x42, 0x3f, 0xf6, 0x7c, 0xd2, 0xc5, 0xa3, 0xd6, 0x2c, 0x62,
- 0xc5, 0xef, 0x67, 0x16, 0x2a, 0x08, 0xd3, 0xc2, 0xdd, 0xd8, 0x40, 0x2a,
- 0x21, 0x3b, 0xff, 0xfc, 0x59, 0xbf, 0xdc, 0xb0, 0x5d, 0xfb, 0xab, 0x07,
- 0x86, 0xac, 0x5e, 0x7d, 0xb8, 0xb1, 0x7f, 0xec, 0xdd, 0xb6, 0xfe, 0x6f,
- 0x84, 0xb1, 0x7b, 0x36, 0x12, 0xc5, 0x83, 0xea, 0x8e, 0x1c, 0x65, 0xf8,
- 0xf1, 0x20, 0x5f, 0x85, 0x3f, 0x29, 0x58, 0xbf, 0xfd, 0xac, 0x7d, 0xba,
- 0xf2, 0x5f, 0x66, 0xf2, 0xc5, 0x8d, 0x19, 0xfa, 0x61, 0x3d, 0xfd, 0x0e,
- 0x1a, 0x29, 0xed, 0x62, 0xfb, 0x06, 0xd0, 0x58, 0xae, 0xcf, 0x4c, 0x33,
- 0x1b, 0xed, 0x4c, 0xec, 0xb1, 0x7d, 0x14, 0xf9, 0x96, 0x2f, 0xf4, 0xed,
- 0xc9, 0x89, 0xfa, 0x2c, 0x5e, 0x88, 0x70, 0x58, 0xad, 0x8f, 0x5b, 0x0d,
- 0xee, 0x60, 0xf8, 0x8b, 0xe1, 0x11, 0x98, 0xf3, 0x7b, 0xa7, 0x8c, 0x58,
- 0xa9, 0x54, 0xe7, 0x90, 0xb8, 0x77, 0xb2, 0x87, 0x10, 0x67, 0xb7, 0x4f,
- 0x16, 0x2e, 0x92, 0x58, 0xaf, 0x1a, 0xd3, 0x05, 0xef, 0xf9, 0xf5, 0xb0,
- 0x81, 0x85, 0x8b, 0x17, 0x44, 0x75, 0x8b, 0xfd, 0x0e, 0x78, 0x58, 0x3e,
- 0xb1, 0x1e, 0x90, 0x0e, 0x6f, 0xff, 0xb0, 0x7f, 0x10, 0x7c, 0x7f, 0x7d,
- 0xd8, 0x0b, 0x15, 0xda, 0x27, 0xc9, 0x3a, 0xe3, 0xc1, 0x62, 0xff, 0xf4,
- 0xeb, 0x73, 0x41, 0x8c, 0x5d, 0xc3, 0x8b, 0x15, 0x03, 0xe5, 0xe0, 0xc5,
- 0xf6, 0x6a, 0x4e, 0xb1, 0x78, 0xb3, 0xa7, 0x53, 0xc4, 0x22, 0x2b, 0xff,
- 0xfe, 0xe1, 0x60, 0xdc, 0x3e, 0xa5, 0x81, 0x3c, 0xfc, 0x14, 0xe9, 0x62,
- 0xb4, 0x9b, 0x5f, 0x21, 0x99, 0xe3, 0x5b, 0xfc, 0x46, 0x96, 0x3f, 0x7e,
- 0x58, 0xb7, 0x45, 0x8a, 0xc3, 0xc8, 0xe1, 0xa5, 0x4a, 0x27, 0xc4, 0xfd,
- 0x7f, 0x83, 0xd6, 0x1c, 0xec, 0x4b, 0x17, 0xd3, 0x9f, 0xe2, 0xc5, 0xcf,
- 0xb2, 0xc5, 0x44, 0x6e, 0xbc, 0x45, 0x4c, 0x89, 0x00, 0x37, 0x5f, 0xed,
- 0xcb, 0x07, 0xf6, 0xe2, 0xc5, 0xfc, 0x0c, 0x21, 0xfe, 0x56, 0x2f, 0xef,
- 0xb9, 0x00, 0xc3, 0xac, 0x53, 0x9e, 0xe7, 0x8b, 0x6e, 0x1b, 0xac, 0x5f,
- 0xff, 0xdf, 0x7c, 0x2c, 0x71, 0xe4, 0x81, 0xb7, 0x6d, 0x2c, 0x5f, 0xed,
- 0xa4, 0xe5, 0x3d, 0x81, 0x62, 0xa5, 0x35, 0x58, 0x42, 0x43, 0x72, 0x1e,
- 0xc5, 0xd9, 0x62, 0xfd, 0xfe, 0xad, 0x9c, 0x58, 0xa9, 0x3f, 0xac, 0x50,
- 0xb0, 0x96, 0x2f, 0xef, 0x14, 0xc3, 0x3c, 0xb1, 0x7c, 0x45, 0x9e, 0x58,
- 0xbb, 0x61, 0x2c, 0x5d, 0x26, 0xac, 0x52, 0xc5, 0xcd, 0xc5, 0x8a, 0x39,
- 0xa3, 0x0c, 0x32, 0xfb, 0x0c, 0xc3, 0xac, 0x5f, 0x1a, 0x2d, 0x1a, 0xb1,
- 0x7c, 0x03, 0xbf, 0x16, 0x28, 0xd3, 0xc9, 0xd1, 0x35, 0xe6, 0xd4, 0x3a,
- 0xa6, 0xa7, 0x25, 0xae, 0x42, 0x71, 0x9f, 0x9d, 0x91, 0x11, 0x8d, 0x95,
- 0xd5, 0xb0, 0x49, 0x8d, 0xc7, 0x66, 0x3b, 0xfc, 0x8d, 0x63, 0xb4, 0x47,
- 0x87, 0xc6, 0xa5, 0xcf, 0x1e, 0x10, 0x1f, 0x96, 0x3a, 0xd0, 0xb2, 0x28,
- 0xfc, 0x78, 0x40, 0x28, 0xd9, 0x6f, 0xfd, 0xa7, 0xd9, 0x8e, 0x5d, 0x88,
- 0x96, 0x2d, 0x1e, 0xb1, 0x6f, 0x2c, 0x5d, 0x20, 0x58, 0xbf, 0xfc, 0xe2,
- 0x0b, 0xcf, 0x5e, 0x08, 0x07, 0xcf, 0x2c, 0x57, 0x67, 0xd1, 0xa1, 0x7b,
- 0xff, 0xb7, 0xfc, 0xf3, 0xda, 0x9e, 0xfe, 0xeb, 0x17, 0xfe, 0x9d, 0xf9,
- 0x2f, 0xdf, 0xa4, 0xeb, 0x14, 0xb1, 0x7b, 0x42, 0x8f, 0x58, 0xa8, 0x1a,
- 0xdf, 0x06, 0x5c, 0x69, 0xd6, 0x2a, 0x51, 0xdc, 0x48, 0xe2, 0x6d, 0x8e,
- 0x21, 0xbe, 0x07, 0x36, 0xf2, 0xc5, 0xfc, 0xdf, 0x92, 0x98, 0x2c, 0x5f,
- 0xff, 0xfb, 0xd9, 0x25, 0x9b, 0x93, 0x6d, 0x3a, 0xd4, 0xfb, 0xf8, 0x35,
- 0x8b, 0xee, 0x85, 0x9c, 0xea, 0x89, 0x7c, 0x2c, 0xbf, 0xfe, 0xc2, 0xc3,
- 0x7e, 0xd0, 0xf8, 0x6c, 0x61, 0xd6, 0x2f, 0xfc, 0xc6, 0xf5, 0xf3, 0x31,
- 0x75, 0xd9, 0x62, 0xa5, 0x38, 0xe7, 0x85, 0xe7, 0xcf, 0x09, 0x4a, 0xfc,
- 0x0c, 0x3c, 0xee, 0xb1, 0x79, 0xbd, 0xc5, 0x8b, 0x85, 0xb2, 0xc5, 0x40,
- 0xdb, 0x68, 0x76, 0xfd, 0x90, 0xfb, 0x41, 0x62, 0xa2, 0x3c, 0x9f, 0x90,
- 0xd8, 0xa5, 0x19, 0x7e, 0x85, 0x45, 0xdf, 0x8f, 0x58, 0xbf, 0xff, 0xff,
- 0xfb, 0xdc, 0x92, 0xeb, 0xb9, 0x0b, 0x6f, 0xe0, 0xf4, 0xdd, 0x7d, 0xcf,
- 0xe3, 0x8f, 0xcd, 0xf8, 0x01, 0x62, 0xff, 0x31, 0x19, 0xff, 0xc8, 0xd6,
- 0x2f, 0xff, 0xbd, 0xc9, 0xce, 0xba, 0x9f, 0x3e, 0xee, 0x35, 0x8b, 0xbb,
- 0x0d, 0x62, 0xc1, 0xac, 0x5d, 0xbf, 0x51, 0x9a, 0xde, 0xc6, 0xab, 0x88,
- 0xb0, 0x13, 0xfd, 0xee, 0xe4, 0xd5, 0x8b, 0xff, 0xff, 0xb5, 0x3d, 0x7f,
- 0x81, 0x3d, 0x3a, 0xdc, 0xb3, 0xda, 0x17, 0x70, 0xe2, 0xc5, 0xe0, 0xff,
- 0x84, 0x89, 0x8f, 0x0f, 0xdf, 0x0a, 0x26, 0x1a, 0xc5, 0xfb, 0x3d, 0xac,
- 0x0d, 0x62, 0xdb, 0xf5, 0x3c, 0xdf, 0x92, 0x54, 0xa2, 0xb1, 0xe1, 0x03,
- 0x76, 0xa0, 0xb1, 0x7f, 0xf0, 0xb0, 0x8d, 0xeb, 0xf2, 0xcf, 0x71, 0x62,
- 0xff, 0x1a, 0xdc, 0xcf, 0x19, 0xb2, 0xc5, 0xf7, 0x5d, 0xc3, 0x95, 0x8a,
- 0x81, 0xef, 0x1c, 0xde, 0xa5, 0x70, 0xf6, 0x05, 0x98, 0x37, 0xdc, 0x29,
- 0x9e, 0x1c, 0x9a, 0x8d, 0x9c, 0xe4, 0xdf, 0x18, 0x68, 0x52, 0xdf, 0xa3,
- 0x6d, 0x3c, 0x9a, 0xb1, 0x7e, 0xf7, 0xe5, 0xf7, 0x58, 0xa3, 0x4f, 0x5f,
- 0xc5, 0xd7, 0xc4, 0xcd, 0xf5, 0x8b, 0xff, 0xfd, 0x87, 0xd6, 0x9f, 0xa9,
- 0x77, 0x81, 0x96, 0x0b, 0x0d, 0x58, 0xa1, 0xa2, 0x17, 0xe4, 0x34, 0x48,
- 0xcb, 0xe4, 0x2a, 0x2f, 0xd9, 0xcf, 0x36, 0x96, 0x2f, 0xff, 0x73, 0x18,
- 0xba, 0xf3, 0xb9, 0x29, 0xe2, 0xc5, 0xa1, 0xf3, 0xf3, 0xf1, 0x45, 0xfd,
- 0x23, 0x9f, 0xcc, 0x16, 0x2f, 0xf4, 0xfb, 0xab, 0x6e, 0xfd, 0x16, 0x2b,
- 0x47, 0xca, 0x45, 0xb7, 0xff, 0xfe, 0x7e, 0xfc, 0xdf, 0x2c, 0x1f, 0xde,
- 0x2e, 0x6f, 0x8e, 0x51, 0x2c, 0x5f, 0xff, 0x4f, 0xba, 0x90, 0x82, 0x75,
- 0xcf, 0x47, 0x67, 0x96, 0x2a, 0x53, 0x75, 0x78, 0x46, 0xe8, 0x84, 0x4d,
- 0xd7, 0x37, 0x96, 0x2f, 0xfe, 0xfc, 0x9b, 0xd7, 0xc4, 0xde, 0x9f, 0x2c,
- 0x5f, 0xdd, 0xc1, 0xfe, 0x23, 0xac, 0x5c, 0xfb, 0x2c, 0x57, 0x53, 0xc8,
- 0xf1, 0x85, 0x7d, 0x19, 0x40, 0x17, 0x28, 0x47, 0xdf, 0x83, 0x6f, 0xc5,
- 0x1b, 0xac, 0x5f, 0xf6, 0x0f, 0xaf, 0x8d, 0x70, 0xf8, 0xb1, 0x6c, 0xd1,
- 0xf7, 0x74, 0x30, 0xbf, 0xfd, 0x24, 0xdd, 0x7e, 0xcf, 0xce, 0x39, 0xd6,
- 0x2f, 0xe6, 0xf9, 0xb3, 0xa6, 0x58, 0xbe, 0xd6, 0x0b, 0x65, 0x8b, 0xff,
- 0x6a, 0x2e, 0xbc, 0x97, 0xd9, 0xbc, 0xb1, 0x52, 0x9d, 0x50, 0xe1, 0x45,
- 0xf2, 0x92, 0x4a, 0xf1, 0x70, 0x89, 0x2f, 0xff, 0x08, 0x81, 0xce, 0xbc,
- 0x17, 0xa7, 0xdc, 0x58, 0xbf, 0xee, 0x6b, 0x59, 0xfe, 0xe1, 0xc5, 0x8a,
- 0xc4, 0x45, 0x09, 0x3a, 0xe6, 0x02, 0xc5, 0xff, 0xf7, 0x52, 0x9e, 0x4e,
- 0xc5, 0x83, 0xfb, 0xc4, 0xb1, 0x7f, 0xff, 0xf7, 0x34, 0x53, 0x17, 0x53,
- 0x3c, 0xf0, 0xce, 0xfd, 0x9d, 0x0b, 0x38, 0xb1, 0x5a, 0x46, 0x51, 0x29,
- 0x54, 0x13, 0x25, 0xf1, 0x10, 0xa1, 0xc3, 0x4b, 0x17, 0xff, 0xfe, 0x92,
- 0xdd, 0xbe, 0x4c, 0x0e, 0xbe, 0xcf, 0x96, 0x7b, 0xee, 0xb1, 0x4b, 0x17,
- 0xf4, 0xb9, 0x36, 0x8d, 0x58, 0xbb, 0xdd, 0x4d, 0x37, 0x3f, 0x0c, 0xbc,
- 0x69, 0xb2, 0xb1, 0x68, 0x2c, 0x53, 0x9b, 0x18, 0x87, 0xef, 0xfe, 0xce,
- 0xe1, 0xd7, 0x22, 0xfc, 0x91, 0xab, 0x15, 0x29, 0xbe, 0x1a, 0x19, 0xdc,
- 0x29, 0x74, 0xc2, 0x72, 0x1b, 0xfd, 0xa2, 0xcd, 0xf2, 0x63, 0xd6, 0x2f,
- 0xfe, 0x2f, 0x73, 0xa3, 0xfa, 0x70, 0xa2, 0x58, 0xbf, 0xf6, 0xb6, 0xcc,
- 0xe0, 0xc9, 0xbe, 0xb1, 0x7e, 0xd3, 0xf2, 0x7b, 0x58, 0xa9, 0x47, 0x26,
- 0x1b, 0x3a, 0x33, 0x1f, 0xdf, 0xff, 0xa1, 0xc0, 0x0a, 0x2e, 0xb8, 0xfa,
- 0x73, 0xc9, 0xab, 0x17, 0xf0, 0x56, 0x28, 0x3f, 0xb8, 0xb1, 0x7b, 0x86,
- 0x71, 0x62, 0xb6, 0x3d, 0x33, 0x9a, 0x5d, 0x20, 0x58, 0xbf, 0x17, 0xbf,
- 0x81, 0x16, 0x2f, 0xd1, 0x71, 0xb4, 0x6a, 0xc5, 0xe6, 0x0f, 0x52, 0x7a,
- 0xb8, 0x55, 0x7e, 0x89, 0xca, 0x4e, 0xb1, 0x7e, 0x97, 0xda, 0x4d, 0x58,
- 0xb1, 0xb2, 0x7a, 0x3f, 0x28, 0xbe, 0xeb, 0xdc, 0x1d, 0x62, 0x88, 0xf3,
- 0xbc, 0x51, 0x7f, 0x38, 0x46, 0x83, 0x92, 0xc5, 0xfc, 0x6b, 0x40, 0xa4,
- 0xeb, 0x15, 0x27, 0xfb, 0x84, 0x2e, 0x5d, 0x7f, 0x61, 0xf8, 0x53, 0xa5,
- 0x8a, 0x82, 0xb1, 0xce, 0xce, 0x5e, 0x15, 0xb1, 0x11, 0xe9, 0xb3, 0xf1,
- 0xa7, 0x11, 0x65, 0xf3, 0xee, 0xda, 0x58, 0xbc, 0x76, 0x0d, 0x62, 0xdc,
- 0x81, 0xe0, 0xb1, 0x1d, 0xf6, 0x74, 0x6d, 0x2c, 0x5f, 0xc3, 0xc2, 0x87,
- 0xf1, 0x62, 0xa4, 0xf4, 0x5c, 0x92, 0xff, 0xf6, 0x38, 0x7d, 0x4b, 0x00,
- 0x58, 0xd1, 0x2c, 0x5f, 0x3e, 0xb0, 0xd5, 0x8b, 0x73, 0xa9, 0xf7, 0x47,
- 0x25, 0xdf, 0xf7, 0xdf, 0x51, 0x7d, 0xb3, 0x4b, 0x17, 0xff, 0xff, 0xf0,
- 0x38, 0x58, 0xdd, 0xf5, 0x1f, 0xc5, 0xd4, 0xb3, 0xb8, 0x60, 0xb6, 0x2c,
- 0x6e, 0xd6, 0x2b, 0x11, 0xed, 0xb9, 0x6b, 0x9d, 0x5e, 0xce, 0x41, 0x62,
- 0xe6, 0xdd, 0x51, 0x4c, 0x16, 0x35, 0x62, 0xbe, 0x7a, 0xac, 0x3a, 0x22,
- 0x5b, 0xf6, 0xcc, 0x7e, 0x47, 0x2c, 0x5f, 0xf1, 0x48, 0x24, 0x27, 0xf3,
- 0x8b, 0x15, 0x2a, 0xc5, 0x76, 0x78, 0xc8, 0xe1, 0x37, 0x84, 0x23, 0x97,
- 0x31, 0x6d, 0xff, 0xfe, 0xf7, 0x0c, 0xe7, 0x5c, 0x87, 0xe5, 0xf4, 0x03,
- 0xb4, 0x16, 0x2f, 0xf8, 0xbb, 0x87, 0x3d, 0x3a, 0x89, 0x62, 0xf1, 0x67,
- 0xd6, 0x2f, 0xfb, 0x71, 0x37, 0xf3, 0xcd, 0xf5, 0x8a, 0x19, 0xeb, 0x76,
- 0x39, 0x58, 0x8b, 0x5f, 0x42, 0x4a, 0xff, 0xcd, 0xde, 0x3e, 0x9c, 0xf2,
- 0x6a, 0xc5, 0xe3, 0x24, 0x96, 0x2f, 0x63, 0x81, 0x62, 0xd8, 0xb1, 0x6c,
- 0x01, 0xad, 0xe8, 0x39, 0x73, 0xec, 0xb1, 0x4b, 0x0c, 0x5c, 0x5d, 0xac,
- 0x58, 0xb7, 0x7d, 0x51, 0x76, 0x49, 0x5c, 0x40, 0x10, 0xd5, 0xec, 0xef,
- 0xcb, 0x15, 0x8a, 0xa7, 0x9e, 0x31, 0xad, 0x13, 0xb4, 0x3e, 0xa3, 0x91,
- 0x6f, 0x60, 0xb4, 0xb1, 0x7a, 0x4b, 0xcb, 0x16, 0x89, 0x62, 0xff, 0x01,
- 0xe1, 0xf7, 0x20, 0x2c, 0x5f, 0x0b, 0x3b, 0x25, 0x8a, 0xd8, 0xfa, 0x5c,
- 0x4c, 0xe6, 0x76, 0x0d, 0x62, 0xe7, 0x1a, 0xc5, 0x47, 0x9a, 0xae, 0x09,
- 0xdf, 0xee, 0xe4, 0x3e, 0x10, 0xa2, 0x58, 0xb8, 0x71, 0x2c, 0x5f, 0xf6,
- 0xb0, 0x7f, 0x90, 0xce, 0x25, 0x8b, 0xfb, 0xf8, 0x37, 0x2f, 0x2c, 0x5b,
- 0x65, 0x8b, 0xbf, 0xc5, 0x8a, 0x34, 0xd5, 0xb0, 0x9d, 0xfc, 0x4c, 0x1f,
- 0xb3, 0xeb, 0x17, 0xd1, 0xd3, 0xac, 0x58, 0xa9, 0x4f, 0x53, 0x16, 0x74,
- 0x48, 0x73, 0x7f, 0x8c, 0xf8, 0xec, 0x35, 0x88, 0xe2, 0x13, 0x0b, 0xaf,
- 0xdf, 0x11, 0xb9, 0xb2, 0xc5, 0xfb, 0x0e, 0x76, 0x3a, 0xc5, 0xc7, 0x02,
- 0xc5, 0x75, 0x47, 0x68, 0xe1, 0x05, 0xa2, 0xb0, 0x14, 0x5b, 0xee, 0xae,
- 0x29, 0xa5, 0xa3, 0x5f, 0xda, 0x9f, 0x13, 0x01, 0x62, 0xb4, 0x7b, 0xa1,
- 0x0c, 0x2f, 0xee, 0xe0, 0x53, 0x9c, 0x58, 0xbf, 0xf3, 0x67, 0xdb, 0xed,
- 0x9f, 0x65, 0x8b, 0xfd, 0x16, 0x61, 0xa6, 0xcc, 0x4b, 0x17, 0xfe, 0xc7,
- 0xdf, 0x3d, 0x25, 0xee, 0x2c, 0x5f, 0xfb, 0x82, 0x09, 0xd7, 0x86, 0xea,
- 0x49, 0x62, 0xba, 0xa2, 0x0d, 0xcf, 0xab, 0xaa, 0x69, 0x1f, 0x2e, 0x23,
- 0xc0, 0x90, 0xba, 0xae, 0xd7, 0x6d, 0x9e, 0x70, 0x11, 0xa3, 0x6c, 0xbf,
- 0xbd, 0x9b, 0x66, 0xa2, 0x58, 0xbf, 0x7f, 0xa8, 0x26, 0x3d, 0x62, 0xff,
- 0xf9, 0xf9, 0xd7, 0xed, 0xcf, 0x4c, 0x5c, 0xfe, 0x2c, 0x54, 0xa2, 0xc5,
- 0x8c, 0x00, 0x5d, 0x4b, 0x17, 0xf0, 0x9c, 0x6e, 0x4e, 0xb1, 0x63, 0x5c,
- 0xdc, 0x1c, 0x32, 0xfc, 0xdc, 0xfb, 0x41, 0x62, 0xf9, 0xa0, 0xe7, 0x58,
- 0xbf, 0x6e, 0xda, 0xcd, 0xd6, 0x2f, 0xf8, 0x5d, 0xc3, 0x9d, 0x79, 0xed,
- 0xd6, 0x2f, 0xe2, 0xf4, 0x30, 0x1c, 0x58, 0xbc, 0x6b, 0x73, 0xaa, 0x26,
- 0x34, 0x54, 0xc8, 0x15, 0xf4, 0x7e, 0xfa, 0x17, 0x55, 0xa4, 0xdd, 0x3e,
- 0x4e, 0x1c, 0x64, 0xb7, 0xf3, 0xfd, 0x9f, 0x69, 0x58, 0xbd, 0x09, 0xed,
- 0x62, 0xfe, 0x37, 0x5a, 0xce, 0xf8, 0xb1, 0x7f, 0xfe, 0x2c, 0xef, 0xdd,
- 0x7e, 0xdd, 0x3a, 0x8f, 0xe2, 0xd9, 0x62, 0xfd, 0xf9, 0xdb, 0x03, 0x58,
- 0xbf, 0x3e, 0x74, 0x6d, 0x2c, 0x54, 0xa2, 0xc8, 0x6b, 0xfc, 0x2a, 0xbf,
- 0xb9, 0x07, 0xe0, 0x8e, 0xb1, 0x47, 0x3d, 0xef, 0x17, 0xdf, 0xd9, 0xc8,
- 0x38, 0x31, 0x62, 0xf4, 0x33, 0xcb, 0x15, 0x03, 0xca, 0xf1, 0x6d, 0x4a,
- 0xa5, 0x2c, 0x38, 0xec, 0xb5, 0xc7, 0x9a, 0x34, 0x11, 0x36, 0x5d, 0xd6,
- 0x39, 0x62, 0xff, 0xf0, 0xdf, 0x03, 0xeb, 0xc9, 0x7d, 0x9b, 0xcb, 0x17,
- 0xcf, 0xc9, 0xed, 0x62, 0xfe, 0xdb, 0xab, 0x41, 0xc9, 0x62, 0xa0, 0x8b,
- 0xde, 0xc7, 0x7e, 0x9a, 0x44, 0x77, 0xee, 0xf7, 0x29, 0xe8, 0xb1, 0x7f,
- 0x07, 0xd6, 0x22, 0x71, 0xac, 0x5f, 0xfc, 0x02, 0x17, 0x0b, 0x3d, 0xc7,
- 0xe2, 0xc5, 0x61, 0xfb, 0x11, 0x95, 0xfc, 0xda, 0x8a, 0x0f, 0xf5, 0x8b,
- 0xfc, 0x2d, 0xbe, 0xfd, 0x32, 0x25, 0x8b, 0xf8, 0xcf, 0xfe, 0x4b, 0x75,
- 0x8b, 0xe2, 0x93, 0xf1, 0x62, 0xfb, 0x3e, 0xc7, 0x58, 0xb9, 0xbb, 0xe1,
- 0xfa, 0x78, 0xc0, 0xc2, 0x2a, 0x95, 0x42, 0xd8, 0x7a, 0xf0, 0xa2, 0x62,
- 0x0e, 0x17, 0x8a, 0x15, 0x97, 0xf8, 0x7f, 0x9d, 0x0d, 0xce, 0xb1, 0x77,
- 0x38, 0xb1, 0x6c, 0x58, 0xbf, 0xe7, 0x35, 0xfc, 0x58, 0x13, 0xae, 0x8d,
- 0x4f, 0x41, 0x8b, 0xfc, 0xe4, 0x0c, 0x3b, 0x76, 0xb1, 0x5b, 0xa3, 0x92,
- 0x25, 0xde, 0x8a, 0x97, 0xff, 0xf8, 0xb3, 0x7f, 0x7a, 0x7d, 0xc8, 0x8b,
- 0x03, 0xeb, 0x21, 0x45, 0x8b, 0xff, 0x6f, 0x27, 0xfe, 0x73, 0x1c, 0x96,
- 0x2a, 0x51, 0x4f, 0xf6, 0x9b, 0xff, 0xff, 0x42, 0x75, 0xdc, 0x39, 0xd7,
- 0x82, 0x9e, 0xc9, 0xbd, 0xf6, 0x89, 0x62, 0xfd, 0xa9, 0xe9, 0x3a, 0x58,
- 0xbe, 0x9d, 0xf0, 0xeb, 0x17, 0xfb, 0xae, 0x73, 0x8f, 0x81, 0xac, 0x54,
- 0x47, 0xb3, 0xa2, 0x3b, 0xff, 0xff, 0xec, 0x71, 0xf5, 0xcf, 0xbe, 0xbe,
- 0xdd, 0x7f, 0x83, 0x2c, 0x6e, 0xf3, 0x65, 0x8a, 0x74, 0x51, 0xfc, 0x8e,
- 0xfe, 0x62, 0xea, 0x39, 0x25, 0x8b, 0xdb, 0x6f, 0xe5, 0x8a, 0x95, 0x60,
- 0xb9, 0x0d, 0xbe, 0xc8, 0x9d, 0xcb, 0x91, 0x93, 0x08, 0x88, 0xc2, 0xeb,
- 0xff, 0xcf, 0xe1, 0x36, 0xdb, 0xfd, 0xc6, 0xe4, 0xb1, 0x7b, 0xc6, 0xba,
- 0xc5, 0x05, 0xcf, 0xa4, 0x92, 0xef, 0xb0, 0xf3, 0xba, 0xc5, 0xfd, 0xbb,
- 0xed, 0x9d, 0xf9, 0x62, 0xa0, 0x7a, 0x81, 0x91, 0xda, 0x39, 0x62, 0xfe,
- 0x07, 0x59, 0xdd, 0x8c, 0x58, 0xbf, 0xe9, 0xc2, 0x87, 0x59, 0xe9, 0x2b,
- 0x14, 0x6a, 0x20, 0x88, 0x57, 0xc6, 0x57, 0xed, 0x60, 0xda, 0x0b, 0x15,
- 0x28, 0xfd, 0x78, 0x52, 0xb1, 0x85, 0xe9, 0xd4, 0x16, 0x2f, 0xff, 0xf6,
- 0x85, 0xdc, 0x39, 0xd6, 0x48, 0x7f, 0x98, 0xec, 0xd4, 0xac, 0x57, 0x57,
- 0x67, 0xcf, 0x1a, 0x20, 0x05, 0xa8, 0xac, 0xbd, 0x6d, 0x18, 0x8c, 0x23,
- 0xcc, 0x1c, 0xea, 0x46, 0x47, 0x6a, 0x6c, 0xa0, 0xfd, 0xe5, 0x5a, 0xf7,
- 0x28, 0x29, 0xe3, 0xb2, 0x8a, 0x71, 0x47, 0x52, 0xf1, 0xcf, 0x2c, 0x03,
- 0xf3, 0xc1, 0xa0, 0x87, 0x89, 0x4e, 0x16, 0x72, 0x59, 0x7f, 0xa7, 0x12,
- 0x05, 0x0d, 0x9e, 0x91, 0xbb, 0x06, 0x64, 0x10, 0x76, 0xff, 0xfc, 0x5b,
- 0xf5, 0xfc, 0xbe, 0x9c, 0xef, 0x1d, 0x27, 0x58, 0xbd, 0xc9, 0xed, 0x62,
- 0xf6, 0xd9, 0xb2, 0xc5, 0xfc, 0x5e, 0x01, 0x4e, 0x96, 0x2f, 0xf3, 0x07,
- 0xd5, 0x86, 0xdb, 0x2c, 0x5f, 0xff, 0xff, 0x7b, 0x9b, 0x3e, 0x17, 0x8e,
- 0x29, 0x2f, 0x67, 0x1f, 0x08, 0x72, 0x4b, 0x17, 0xff, 0x7b, 0x83, 0xfc,
- 0xc7, 0x0b, 0xef, 0xa5, 0x8a, 0xc4, 0xc9, 0xf4, 0x5a, 0xc6, 0xe2, 0x7a,
- 0xbd, 0x0e, 0xf7, 0x58, 0xbf, 0x98, 0x38, 0x89, 0xc6, 0xb1, 0x74, 0x00,
- 0xb1, 0x76, 0xc7, 0x58, 0xae, 0xa6, 0xc5, 0xc6, 0x2f, 0xff, 0xc4, 0xfb,
- 0x75, 0x7c, 0x2c, 0xdc, 0x27, 0xb0, 0xeb, 0x17, 0x8f, 0x3b, 0xac, 0x5e,
- 0xef, 0xf9, 0x11, 0xfb, 0x81, 0x66, 0xff, 0xfe, 0x3b, 0xf7, 0x0e, 0x16,
- 0x0f, 0xf3, 0x1d, 0x9a, 0x95, 0x8b, 0xff, 0xfb, 0x36, 0x62, 0xf7, 0x27,
- 0x7e, 0xa7, 0x3b, 0x96, 0xeb, 0x17, 0xf4, 0x39, 0x14, 0x26, 0x25, 0x8a,
- 0x1a, 0x24, 0x3b, 0x5f, 0xbf, 0xfd, 0x83, 0xfb, 0xc5, 0xd5, 0xff, 0x27,
- 0x95, 0x8b, 0xe6, 0x9e, 0xe0, 0xb1, 0x61, 0x91, 0xf7, 0xf1, 0x32, 0xa5,
- 0x17, 0x4d, 0x09, 0x3b, 0xe8, 0x14, 0x9d, 0x62, 0xf1, 0x49, 0xd6, 0x2f,
- 0xfb, 0xf9, 0xbc, 0xeb, 0xb8, 0x73, 0xa9, 0xbe, 0x81, 0x15, 0xff, 0xdd,
- 0x4b, 0x3b, 0xce, 0x7c, 0xb0, 0xd5, 0x8a, 0xed, 0x13, 0x51, 0x29, 0xdf,
- 0xee, 0xba, 0xc7, 0xfc, 0x8d, 0x62, 0xa4, 0xf6, 0x88, 0x96, 0xd1, 0xb2,
- 0xc5, 0xd3, 0x1e, 0xb1, 0x52, 0xbd, 0x32, 0x35, 0xac, 0x1e, 0x36, 0x34,
- 0x67, 0x3c, 0xd1, 0x07, 0xd8, 0x1a, 0x13, 0x20, 0x35, 0x28, 0xea, 0x05,
- 0x1a, 0xc7, 0x42, 0x03, 0x05, 0xef, 0xb0, 0x8d, 0x8f, 0x58, 0xbf, 0xff,
- 0xff, 0x7d, 0xfd, 0xfc, 0xd4, 0xf4, 0xea, 0x71, 0x04, 0xeb, 0x9d, 0xc3,
- 0x04, 0x40, 0xe2, 0xc5, 0xbc, 0xe8, 0xb3, 0xe1, 0x35, 0xff, 0xf1, 0x45,
- 0xf9, 0x7d, 0x39, 0xde, 0x3a, 0x4e, 0xb1, 0x73, 0x9d, 0x62, 0xff, 0xfb,
- 0xb8, 0x13, 0xc5, 0xd4, 0xb3, 0xdc, 0x7d, 0x2c, 0x53, 0xa2, 0xf2, 0x25,
- 0x20, 0xc5, 0xef, 0xf3, 0x16, 0x0f, 0x1f, 0xeb, 0x17, 0xf9, 0xe2, 0xfb,
- 0x14, 0xca, 0xc5, 0x76, 0x7c, 0x67, 0x31, 0xbf, 0xff, 0xda, 0xd6, 0x0f,
- 0xaf, 0x70, 0x9d, 0xb5, 0x9c, 0xe4, 0xf6, 0xb1, 0x7f, 0xe0, 0x3e, 0x6b,
- 0xaf, 0x49, 0x1c, 0x7a, 0xc5, 0x1d, 0x1a, 0x01, 0x91, 0x84, 0x67, 0xbb,
- 0xf0, 0x58, 0xb8, 0x1c, 0x58, 0xb8, 0x78, 0xb1, 0x7f, 0x6e, 0x5d, 0xe6,
- 0xba, 0xc0, 0xf1, 0xf8, 0x31, 0xd0, 0x62, 0xff, 0xf0, 0xa4, 0xbd, 0xce,
- 0xb3, 0xcd, 0x4f, 0x16, 0x2f, 0xf3, 0x42, 0x2f, 0xbf, 0x7e, 0x58, 0xbf,
- 0xd0, 0xe4, 0x9b, 0xe7, 0xd9, 0x62, 0xff, 0x08, 0xbd, 0x3d, 0x1b, 0xeb,
- 0x17, 0xfe, 0x60, 0xfd, 0x9f, 0xc2, 0x68, 0x2c, 0x54, 0x0f, 0xcc, 0x8d,
- 0x6f, 0xff, 0xbb, 0xc1, 0x11, 0xbe, 0xd4, 0xf6, 0x0e, 0x4a, 0xc5, 0xfc,
- 0x7c, 0x2f, 0x47, 0x62, 0xc5, 0xf9, 0xb8, 0x79, 0x25, 0x8b, 0xe3, 0xce,
- 0x79, 0x62, 0xf4, 0xef, 0xd7, 0x0f, 0xe4, 0x8c, 0x23, 0x89, 0xef, 0xd2,
- 0x5e, 0xea, 0x35, 0x8b, 0xfa, 0x4f, 0x98, 0x46, 0xac, 0x5f, 0xbd, 0xd4,
- 0x1d, 0x81, 0x62, 0x9d, 0x10, 0x9f, 0x2a, 0x11, 0x6d, 0xff, 0xef, 0xbe,
- 0xff, 0xce, 0xbc, 0x17, 0xe6, 0x3d, 0x62, 0xfe, 0x29, 0xee, 0x0e, 0x4b,
- 0x14, 0xb1, 0x7f, 0xb3, 0xe5, 0x9e, 0xfb, 0xac, 0x50, 0xcf, 0xac, 0x8b,
- 0x7c, 0x19, 0x7f, 0xde, 0x98, 0x72, 0x28, 0x4e, 0xcb, 0x16, 0xcc, 0x4c,
- 0x9b, 0xb8, 0x5e, 0x78, 0xba, 0xff, 0xfb, 0xdf, 0xc0, 0x75, 0x3c, 0xe7,
- 0x87, 0x84, 0xb1, 0x6d, 0x2c, 0x58, 0x35, 0x8b, 0xf9, 0x87, 0xad, 0x0b,
- 0x65, 0x8b, 0xf4, 0xe1, 0x7a, 0x39, 0x62, 0xd1, 0xa2, 0xc5, 0x62, 0x25,
- 0x8d, 0x12, 0xdc, 0x4c, 0xe6, 0x1c, 0x2a, 0xbe, 0xf3, 0xeb, 0x16, 0x2d,
- 0xdf, 0x53, 0xed, 0xc4, 0xbb, 0x73, 0x13, 0x7e, 0x68, 0xd5, 0x2f, 0xff,
- 0xff, 0xfb, 0xe2, 0xe1, 0x60, 0xf1, 0xff, 0xd7, 0x7f, 0xb8, 0x4f, 0x8b,
- 0x85, 0x9b, 0x37, 0x53, 0x4d, 0x58, 0xad, 0x97, 0xae, 0x86, 0x99, 0xd9,
- 0xb4, 0x50, 0xa9, 0xd1, 0x09, 0xe1, 0x99, 0xf8, 0x64, 0x14, 0x6a, 0xbe,
- 0x8e, 0xe4, 0x21, 0x75, 0xff, 0xfc, 0x58, 0x1e, 0x6d, 0xd6, 0x3f, 0x18,
- 0xde, 0xba, 0x0f, 0x4b, 0x17, 0xff, 0xfb, 0x03, 0xcd, 0x87, 0xf1, 0x16,
- 0xe5, 0x9e, 0xfb, 0xf6, 0xb1, 0x7f, 0xff, 0xe1, 0x77, 0x0e, 0x75, 0xc7,
- 0x04, 0x96, 0x77, 0xe1, 0xfc, 0x41, 0xac, 0x5f, 0xff, 0xfe, 0x7c, 0x3e,
- 0x7d, 0xf0, 0xfd, 0x4b, 0x3d, 0xfc, 0x87, 0xdf, 0x0e, 0xb1, 0x7f, 0xff,
- 0xf4, 0x1f, 0x85, 0x9d, 0x3f, 0x91, 0x7e, 0x4a, 0x2e, 0xad, 0xbb, 0xf4,
- 0x58, 0xbf, 0xfc, 0x1f, 0x70, 0xe1, 0x67, 0x4f, 0x6b, 0x03, 0x58, 0xbf,
- 0xfc, 0xf8, 0x19, 0x67, 0x33, 0xff, 0x7e, 0x2c, 0x5b, 0x3b, 0x4c, 0x49,
- 0x9e, 0x7c, 0xa1, 0x7f, 0xff, 0x3e, 0x06, 0x59, 0xb6, 0x0b, 0xc4, 0xc6,
- 0xb7, 0x16, 0x2f, 0xfd, 0x9a, 0xfc, 0xf5, 0x6f, 0x0a, 0x56, 0x2f, 0xfe,
- 0xe6, 0x6f, 0xd7, 0xb8, 0x70, 0x9e, 0x25, 0x8b, 0xff, 0xff, 0x16, 0x74,
- 0xfe, 0x6b, 0x59, 0xee, 0x04, 0xf4, 0xf3, 0xef, 0x8b, 0x16, 0x9f, 0x22,
- 0xe4, 0x34, 0xaa, 0x74, 0xc8, 0xb5, 0x0f, 0x9b, 0xff, 0xfe, 0xc2, 0x37,
- 0xae, 0xa7, 0xa3, 0xfb, 0x98, 0x6b, 0xe9, 0xbb, 0x58, 0xbf, 0xff, 0xff,
- 0xbd, 0x9f, 0x2c, 0xe9, 0xd7, 0x35, 0x3e, 0x7d, 0xdc, 0x7d, 0x67, 0xc5,
- 0x3d, 0xc1, 0x62, 0xb6, 0x5d, 0x99, 0xdd, 0x9b, 0x4c, 0x9f, 0x72, 0x28,
- 0xe2, 0x38, 0x6d, 0xe8, 0xdf, 0x4c, 0x28, 0x08, 0xd9, 0x52, 0xcd, 0xe8,
- 0x79, 0xf1, 0x11, 0x4f, 0x23, 0x5f, 0x9b, 0x9a, 0x6e, 0x2c, 0x5f, 0xfe,
- 0x71, 0xf5, 0x3b, 0xf5, 0x91, 0xb4, 0x5c, 0x58, 0xbf, 0x7d, 0xfd, 0x87,
- 0x58, 0xb4, 0x16, 0x2f, 0xfe, 0xfb, 0x90, 0xcc, 0xdc, 0xb3, 0xf8, 0xb1,
- 0x7f, 0xec, 0x7d, 0xb8, 0xff, 0xfc, 0xec, 0xb1, 0x7f, 0x7b, 0xbd, 0xdf,
- 0xf1, 0x2c, 0x50, 0x55, 0x1e, 0x30, 0x28, 0x88, 0x48, 0x91, 0x78, 0x81,
- 0x52, 0x9c, 0x76, 0xd1, 0xa0, 0x5f, 0xe3, 0x4b, 0x3a, 0x16, 0x71, 0x62,
- 0xa0, 0xa8, 0x57, 0x51, 0xdb, 0x11, 0x55, 0xfb, 0x9c, 0x92, 0xdd, 0x62,
- 0xff, 0xf8, 0xa2, 0xeb, 0xfd, 0xdf, 0x98, 0x3d, 0xb0, 0x35, 0x8a, 0xc3,
- 0xff, 0x62, 0x9b, 0xde, 0xce, 0x2c, 0x5b, 0x6f, 0x9b, 0xdf, 0x10, 0x5f,
- 0xa1, 0x3d, 0xc3, 0x8b, 0x17, 0xff, 0xff, 0xfe, 0xc2, 0x37, 0xab, 0xfc,
- 0x51, 0x91, 0x3f, 0xa4, 0xe4, 0xc6, 0xfd, 0xe3, 0x33, 0xfd, 0x82, 0x46,
- 0x91, 0x7f, 0xff, 0x9f, 0x5f, 0xce, 0xdb, 0xbe, 0xa7, 0x21, 0x7b, 0xaf,
- 0x4e, 0x2c, 0x5f, 0xff, 0xf9, 0xc3, 0x18, 0xb5, 0xd4, 0x53, 0xb7, 0x37,
- 0xf8, 0xbf, 0xdb, 0x06, 0xb1, 0x7f, 0xff, 0x67, 0x49, 0x2e, 0xbc, 0x7d,
- 0x30, 0x18, 0xa2, 0x95, 0x8a, 0xdd, 0x1a, 0x7f, 0x76, 0xbf, 0xe2, 0xc1,
- 0x07, 0xd6, 0x7a, 0x47, 0xac, 0x5b, 0x6e, 0xd5, 0x38, 0x39, 0x51, 0xe1,
- 0x49, 0xc8, 0xcf, 0x42, 0x12, 0x56, 0x2a, 0xf8, 0x14, 0xa9, 0x8b, 0xff,
- 0xc1, 0x39, 0x91, 0x77, 0x0e, 0x39, 0xda, 0x25, 0x8b, 0xf1, 0x67, 0xbe,
- 0xeb, 0x17, 0xfe, 0xfb, 0xe6, 0xf3, 0xef, 0xbe, 0x2c, 0x56, 0x22, 0xd4,
- 0xd5, 0x00, 0x84, 0xf7, 0x0f, 0x16, 0x2a, 0x5b, 0x81, 0x5c, 0x87, 0x23,
- 0xc6, 0xc9, 0xfa, 0x73, 0x13, 0x4a, 0x57, 0x29, 0x7d, 0x62, 0x87, 0x04,
- 0x71, 0x95, 0xd9, 0xa5, 0x8b, 0x04, 0x58, 0xb4, 0x68, 0xb1, 0x7a, 0x7f,
- 0x8b, 0x16, 0x3a, 0xc5, 0xfe, 0x68, 0x61, 0xd8, 0x80, 0xb1, 0x7d, 0x9f,
- 0x98, 0x96, 0x2a, 0x34, 0x3e, 0x7f, 0x89, 0x31, 0x95, 0xdc, 0xc5, 0x8b,
- 0x8f, 0xbf, 0x53, 0xca, 0x73, 0x3b, 0xfd, 0xb0, 0xf4, 0xfd, 0xc3, 0x8b,
- 0x16, 0x8f, 0x58, 0xbf, 0x7d, 0xce, 0x52, 0xb1, 0x7c, 0x22, 0x07, 0x16,
- 0x28, 0x07, 0x95, 0xe2, 0x7b, 0xff, 0xf7, 0x1f, 0x08, 0x1d, 0x4b, 0x3a,
- 0x16, 0x73, 0xa2, 0xc5, 0xff, 0x3e, 0x10, 0x3a, 0x85, 0xac, 0x6f, 0x1b,
- 0xac, 0x5f, 0x6e, 0x59, 0xd3, 0xaa, 0x29, 0x78, 0xb3, 0x7f, 0xc6, 0xb7,
- 0xb9, 0x11, 0x38, 0x6b, 0x17, 0xcc, 0x77, 0xe2, 0xc5, 0xfb, 0xec, 0x77,
- 0xe2, 0xc5, 0x1a, 0x88, 0x6f, 0x9e, 0x70, 0x8a, 0xb4, 0x8f, 0x52, 0x86,
- 0x25, 0xff, 0xef, 0x8b, 0x08, 0xde, 0xbe, 0xee, 0x18, 0x4b, 0x17, 0xfb,
- 0x18, 0xfd, 0x63, 0xa4, 0xeb, 0x17, 0xff, 0xa1, 0x3c, 0xf8, 0xb5, 0x9e,
- 0xf3, 0x9d, 0x62, 0x86, 0x8d, 0x1d, 0xd3, 0xbb, 0x38, 0xbf, 0xf1, 0x60,
- 0x8d, 0xd3, 0xc9, 0xf1, 0x62, 0xff, 0xfc, 0x29, 0xea, 0x58, 0x3f, 0xb9,
- 0xa3, 0x93, 0x40, 0xb1, 0x58, 0x9e, 0x0e, 0xa1, 0xf0, 0x73, 0x22, 0x3e,
- 0xbf, 0xfd, 0xef, 0xe0, 0x4f, 0x45, 0x91, 0xec, 0x40, 0x58, 0xbf, 0xd2,
- 0x76, 0x2e, 0xe1, 0x2b, 0x14, 0x48, 0x83, 0xf2, 0x85, 0xff, 0xf6, 0x4f,
- 0x7d, 0x7a, 0x7b, 0xae, 0xa7, 0xf3, 0x12, 0xc5, 0xff, 0x9c, 0x1d, 0x4b,
- 0x3a, 0x3e, 0x99, 0x62, 0xff, 0xf6, 0xba, 0xfe, 0x5f, 0xdc, 0x9d, 0xb3,
- 0x8b, 0x15, 0x88, 0x8e, 0x12, 0x0d, 0x3a, 0x65, 0x5f, 0x22, 0xf4, 0x39,
- 0xaf, 0x83, 0xeb, 0xc8, 0x96, 0x2d, 0xe5, 0x8a, 0x93, 0x74, 0xc5, 0x17,
- 0xfe, 0x2d, 0x8b, 0x3a, 0x70, 0x53, 0xda, 0xc5, 0xff, 0x7e, 0x7b, 0xea,
- 0x16, 0x74, 0x03, 0xac, 0x5f, 0x67, 0x49, 0x25, 0x8b, 0xee, 0xe0, 0xf1,
- 0xcb, 0x15, 0xf3, 0xca, 0xf1, 0x1d, 0x0d, 0x16, 0x1c, 0x84, 0x75, 0x4a,
- 0x63, 0x5b, 0x43, 0xca, 0xa5, 0x7f, 0x4a, 0x06, 0xf8, 0xbe, 0xf2, 0xdf,
- 0x79, 0x1f, 0x77, 0x9b, 0xc5, 0x19, 0xcd, 0xfb, 0xa0, 0x4f, 0x67, 0xd6,
- 0x2c, 0x4b, 0x16, 0xdd, 0x62, 0xff, 0xd9, 0xc1, 0x49, 0xbc, 0x9d, 0x44,
- 0xb1, 0x4e, 0x89, 0x2d, 0x16, 0xf4, 0x11, 0x0c, 0x4e, 0xff, 0xf8, 0x4c,
- 0x5d, 0x7d, 0xf9, 0xf7, 0x3e, 0xd0, 0x58, 0xb9, 0x86, 0xb1, 0x7f, 0x16,
- 0x45, 0x01, 0x04, 0x58, 0xbe, 0x80, 0xb6, 0xf2, 0xc5, 0xb5, 0x03, 0xed,
- 0x34, 0x5f, 0xb3, 0x1b, 0x9b, 0x75, 0x8b, 0xf6, 0xb2, 0x39, 0xc0, 0xb1,
- 0x7f, 0xb7, 0xfb, 0xfc, 0x85, 0xb2, 0xc5, 0xfa, 0x7b, 0x06, 0xa5, 0x62,
- 0xa0, 0x7b, 0xfe, 0x36, 0xad, 0x91, 0x58, 0x50, 0x8a, 0xbd, 0xec, 0x0b,
- 0xac, 0x5f, 0x40, 0xa4, 0xeb, 0x14, 0x15, 0x4c, 0xbe, 0x61, 0x89, 0x85,
- 0x02, 0x21, 0xb8, 0x1f, 0x58, 0xa5, 0x8b, 0xce, 0x58, 0xb1, 0x6e, 0x61,
- 0xa7, 0x88, 0x32, 0xf3, 0xcf, 0x16, 0x2f, 0xde, 0x01, 0x85, 0x05, 0x8b,
- 0xc6, 0x67, 0x16, 0x2d, 0x38, 0x79, 0x06, 0x95, 0x5f, 0xfc, 0x7e, 0xa5,
- 0x9f, 0xf1, 0x63, 0x44, 0xb1, 0x76, 0x7d, 0x62, 0xa5, 0x34, 0xec, 0x3f,
- 0xf9, 0x39, 0x32, 0x08, 0x9e, 0x39, 0x1a, 0xd2, 0xb1, 0x7f, 0xf7, 0x70,
- 0xd3, 0x9d, 0xa6, 0x29, 0x89, 0x62, 0xff, 0xfe, 0xe6, 0x0f, 0x52, 0x1f,
- 0x5f, 0xb3, 0xf3, 0xf8, 0x05, 0x8a, 0x35, 0x16, 0xd1, 0x08, 0x92, 0x3d,
- 0xd8, 0x35, 0x8a, 0xea, 0xcf, 0x67, 0x0a, 0x0b, 0x85, 0x45, 0x24, 0x5f,
- 0x68, 0x66, 0xc2, 0x90, 0x05, 0x91, 0x84, 0xee, 0x7e, 0xd0, 0xbf, 0xe4,
- 0x6c, 0xde, 0x8e, 0x4c, 0x51, 0x87, 0x74, 0x31, 0xbe, 0xe1, 0x67, 0x45,
- 0x8b, 0xe1, 0x43, 0x38, 0xb1, 0x79, 0xe4, 0x6b, 0x14, 0x03, 0xe3, 0x22,
- 0x40, 0xc8, 0xef, 0x0b, 0xdc, 0x58, 0xbf, 0x04, 0xfe, 0x08, 0xeb, 0x14,
- 0x47, 0x92, 0x21, 0xeb, 0xf3, 0xfb, 0x98, 0x05, 0x8b, 0xdd, 0x1f, 0xa2,
- 0xc5, 0xf1, 0xf8, 0xd0, 0x58, 0xb7, 0xf0, 0xf1, 0x04, 0x43, 0x7f, 0xfd,
- 0x9a, 0xed, 0xa2, 0xeb, 0xf7, 0xd1, 0x66, 0xcb, 0x17, 0xff, 0xfb, 0xdf,
- 0x98, 0xba, 0x96, 0x7d, 0xfd, 0xc1, 0x6e, 0x29, 0x58, 0xa3, 0x51, 0x72,
- 0xca, 0x97, 0x0a, 0x39, 0x62, 0x88, 0xdf, 0x06, 0x47, 0x76, 0x01, 0x62,
- 0xff, 0xe2, 0x01, 0x63, 0xc5, 0xf9, 0x23, 0x56, 0x29, 0xcf, 0x6d, 0x85,
- 0xef, 0x10, 0x8e, 0xb1, 0x7e, 0xe7, 0x9e, 0x7b, 0x58, 0xbf, 0xe9, 0xfe,
- 0x0c, 0x51, 0x31, 0x2c, 0x54, 0x0f, 0x8b, 0x85, 0x37, 0x67, 0x45, 0x8b,
- 0xff, 0xfe, 0x68, 0xba, 0xf3, 0x99, 0xfd, 0x6b, 0x03, 0x2c, 0x0d, 0x80,
- 0xb1, 0x7e, 0x92, 0xfb, 0x41, 0x62, 0xff, 0xbd, 0x9b, 0x4f, 0x1f, 0x58,
- 0xb1, 0x7a, 0x47, 0x2b, 0x14, 0x33, 0xfc, 0xec, 0x9c, 0xe7, 0x34, 0xb1,
- 0x4b, 0x17, 0xfd, 0xec, 0xda, 0x78, 0xfa, 0xc5, 0x8b, 0xd2, 0x39, 0x58,
- 0xbd, 0xc6, 0x8b, 0xaa, 0x27, 0x64, 0xc3, 0x03, 0x3b, 0x0c, 0x39, 0xcd,
- 0xb0, 0x93, 0xe1, 0xf4, 0x70, 0x97, 0xd1, 0xa0, 0x5a, 0xc6, 0xd1, 0xa2,
- 0xc5, 0xf3, 0xb1, 0x0d, 0x62, 0xc1, 0xf5, 0x3d, 0xb1, 0x9d, 0x5f, 0xb1,
- 0xbb, 0x87, 0x16, 0x2f, 0xe6, 0x8b, 0xd8, 0x5e, 0x58, 0xa0, 0x1e, 0xb8,
- 0x65, 0x35, 0x04, 0xcb, 0x9e, 0x11, 0x3c, 0x84, 0x15, 0xf6, 0xff, 0x7d,
- 0xd6, 0x2f, 0x85, 0xf9, 0x3a, 0xc5, 0xff, 0xf0, 0xb5, 0xa9, 0x2c, 0x35,
- 0xff, 0xfc, 0x31, 0x62, 0xa5, 0x13, 0x38, 0x4b, 0xa2, 0x3b, 0xef, 0xc8,
- 0x89, 0x62, 0xf8, 0x4d, 0xdf, 0x96, 0x2e, 0x2f, 0x2c, 0x5f, 0xff, 0xfc,
- 0x6e, 0x6b, 0x4e, 0x7e, 0xb1, 0x40, 0x47, 0xee, 0x1c, 0xe4, 0xeb, 0x75,
- 0x8b, 0xbe, 0xcb, 0x16, 0x67, 0x44, 0x97, 0x47, 0xbb, 0xe7, 0x36, 0x4e,
- 0xb1, 0x7f, 0x49, 0x7b, 0xf8, 0x35, 0x8a, 0x93, 0xd0, 0xe1, 0x1d, 0xf0,
- 0x24, 0x72, 0xb1, 0x78, 0x43, 0x95, 0x8b, 0xff, 0xe7, 0x1b, 0xb7, 0x9d,
- 0xbd, 0xd7, 0x8f, 0x12, 0xc5, 0x4b, 0x26, 0x8b, 0x67, 0x88, 0x10, 0x8d,
- 0xb3, 0x23, 0x1e, 0x35, 0xf3, 0x72, 0x0e, 0xdf, 0xdc, 0x8a, 0x29, 0x65,
- 0x1a, 0x86, 0x99, 0xcb, 0xbe, 0x44, 0xc4, 0x85, 0x0a, 0x9e, 0x3c, 0xf8,
- 0x87, 0xa1, 0x14, 0x70, 0xed, 0x82, 0x2c, 0x58, 0x35, 0x8b, 0xdb, 0x4e,
- 0xcb, 0x14, 0xb1, 0x7f, 0x61, 0xc7, 0xfc, 0xe2, 0xc5, 0xfb, 0x6e, 0xbb,
- 0xbe, 0xcb, 0x17, 0xf7, 0x37, 0xdd, 0x88, 0xd5, 0x8a, 0x8d, 0x48, 0x99,
- 0xd8, 0x33, 0x45, 0xde, 0x2e, 0xbf, 0xc5, 0xd7, 0xa7, 0x70, 0xe4, 0x4b,
- 0x17, 0xfd, 0x0e, 0x7d, 0xf0, 0xb3, 0xa2, 0xc5, 0xff, 0xfe, 0x1f, 0xf3,
- 0xde, 0x62, 0xdf, 0x1f, 0x4e, 0x79, 0x35, 0x62, 0xdd, 0xac, 0x5b, 0xa2,
- 0xc5, 0x6c, 0x69, 0xf4, 0x27, 0x7e, 0xfb, 0x47, 0xc8, 0x16, 0x28, 0x69,
- 0xa5, 0x76, 0x76, 0xe7, 0x4d, 0x08, 0x80, 0x84, 0x57, 0xee, 0xa6, 0x6d,
- 0x3b, 0x2c, 0x5f, 0x8b, 0x3e, 0xde, 0x58, 0xa8, 0x1e, 0xac, 0x45, 0xd7,
- 0xf1, 0xaf, 0xdf, 0x05, 0xc5, 0x8b, 0xc1, 0x78, 0xe7, 0x58, 0xad, 0x1f,
- 0xc1, 0x11, 0x88, 0xc6, 0xff, 0xfb, 0xe2, 0x09, 0xe9, 0xe7, 0x84, 0xc6,
- 0x4e, 0x96, 0x2f, 0xc5, 0x9b, 0x6a, 0x56, 0x2e, 0x21, 0x8c, 0xff, 0x38,
- 0xa9, 0x7c, 0x3e, 0xb3, 0x1e, 0xb1, 0x52, 0xae, 0xaf, 0x23, 0x8e, 0x78,
- 0xc7, 0x85, 0x0a, 0xa3, 0x0b, 0x6f, 0xff, 0xd0, 0xe7, 0xa7, 0x61, 0x77,
- 0xc1, 0x39, 0x49, 0xd6, 0x2f, 0xba, 0xf4, 0xc1, 0xac, 0x57, 0x67, 0xff,
- 0xe5, 0x8b, 0xfd, 0x3d, 0x4b, 0x3a, 0x67, 0xd6, 0x2c, 0xeb, 0x17, 0xfc,
- 0x22, 0xeb, 0x13, 0xec, 0x28, 0x96, 0x2f, 0xec, 0x1c, 0x50, 0x98, 0xf5,
- 0x8b, 0xdc, 0xcd, 0x96, 0x2f, 0xfe, 0xf1, 0xb3, 0xdc, 0x39, 0xdc, 0x24,
- 0xd5, 0x8b, 0x1d, 0x62, 0xfe, 0x39, 0x31, 0xbf, 0x7e, 0xa7, 0xb9, 0xb2,
- 0x55, 0xff, 0x1f, 0x8d, 0x10, 0x4f, 0xe6, 0xcb, 0x15, 0x28, 0x85, 0xc4,
- 0x7a, 0xd9, 0x39, 0x1d, 0x1f, 0xfc, 0xcb, 0xd0, 0xff, 0xbf, 0xf6, 0xdd,
- 0x4b, 0x3d, 0xcf, 0xe1, 0xab, 0x17, 0x61, 0x2c, 0x5e, 0x84, 0x81, 0x62,
- 0x86, 0x6c, 0xf0, 0x5a, 0xfb, 0x83, 0x60, 0x2c, 0x5f, 0xcf, 0xa7, 0x3c,
- 0x9a, 0xb1, 0x7f, 0xb3, 0xff, 0x9e, 0xda, 0x3d, 0x62, 0xee, 0x75, 0xc3,
- 0xe5, 0xe1, 0x75, 0x76, 0x8b, 0x70, 0x42, 0x22, 0xb4, 0x98, 0x01, 0x43,
- 0x5e, 0xf8, 0x1c, 0x8f, 0xdd, 0x62, 0xa5, 0x3c, 0x67, 0x8d, 0xd8, 0x45,
- 0x17, 0xed, 0xff, 0x3a, 0x89, 0x62, 0xef, 0x3a, 0xc5, 0x7c, 0xf0, 0xb8,
- 0x57, 0x7e, 0x06, 0x78, 0xcd, 0x96, 0x2f, 0xf1, 0x60, 0x61, 0x3d, 0x9f,
- 0x58, 0xbf, 0xff, 0xff, 0xe7, 0xcf, 0x6e, 0xfe, 0x2c, 0x37, 0xed, 0xec,
- 0xdb, 0xae, 0x45, 0xdc, 0x39, 0xef, 0xe7, 0x6b, 0x17, 0xf7, 0x33, 0xfe,
- 0x73, 0x56, 0x2f, 0xfb, 0x9f, 0x14, 0x5d, 0x43, 0x8f, 0xed, 0x62, 0xe1,
- 0x1a, 0xb1, 0x7f, 0xfe, 0x17, 0x70, 0xe7, 0x70, 0x6e, 0xfa, 0x8f, 0xee,
- 0x75, 0x8b, 0xf6, 0x39, 0x61, 0xab, 0x17, 0xde, 0xcf, 0xf5, 0xd2, 0x21,
- 0x3e, 0xbb, 0x60, 0xe2, 0x54, 0x3b, 0xa3, 0x6e, 0x42, 0x6f, 0xc5, 0xf1,
- 0xc8, 0x81, 0x21, 0x3b, 0x7e, 0xe6, 0x78, 0xcd, 0x96, 0x2d, 0xe5, 0x8b,
- 0x71, 0x62, 0xef, 0xf5, 0x34, 0xd2, 0x76, 0x25, 0x70, 0x7e, 0x94, 0x40,
- 0x62, 0x7d, 0xed, 0xa0, 0x6a, 0xc5, 0x4a, 0xb8, 0x6c, 0x94, 0x90, 0xd0,
- 0xf0, 0x11, 0x75, 0x46, 0xcc, 0xdd, 0x00, 0xb5, 0x14, 0x91, 0x38, 0x4e,
- 0x31, 0xe4, 0x36, 0x8d, 0x23, 0xdc, 0xd9, 0xe3, 0xa2, 0xfc, 0xa0, 0xa6,
- 0x77, 0x29, 0x75, 0x17, 0xf7, 0x70, 0xe7, 0x59, 0x25, 0x8b, 0xf0, 0x88,
- 0x79, 0xc5, 0x8b, 0xff, 0xa0, 0xdc, 0xcd, 0x9b, 0xdb, 0x60, 0x6b, 0x17,
- 0xfd, 0x9f, 0xea, 0x63, 0x47, 0xff, 0x16, 0x2f, 0xef, 0xe6, 0xf0, 0x93,
- 0xac, 0x5f, 0xef, 0xe4, 0x18, 0xb3, 0xb5, 0x8a, 0xc3, 0xe2, 0xf1, 0x7d,
- 0xff, 0xff, 0xa1, 0x3b, 0x77, 0x0e, 0x39, 0xbd, 0x79, 0x9b, 0xb9, 0xc5,
- 0xad, 0x96, 0x2f, 0xfd, 0xbb, 0x8f, 0xae, 0x78, 0x9f, 0xb5, 0x8b, 0xde,
- 0xdc, 0x6b, 0x17, 0xfb, 0x03, 0xeb, 0xf7, 0xc3, 0xac, 0x5f, 0xff, 0x6d,
- 0x8e, 0x5e, 0x2c, 0xe9, 0xd7, 0x81, 0x92, 0xc5, 0xcc, 0x0e, 0xa8, 0xa9,
- 0xd8, 0x7f, 0x86, 0xd5, 0xda, 0x73, 0xce, 0xea, 0x50, 0xeb, 0xbf, 0xfd,
- 0xbb, 0xff, 0xed, 0xc2, 0xc0, 0x0b, 0x8b, 0x17, 0xff, 0x3f, 0xfe, 0xdc,
- 0x2c, 0x00, 0xb8, 0xb1, 0x7f, 0xc4, 0x42, 0x60, 0x79, 0x80, 0xb1, 0x7e,
- 0x7f, 0x73, 0x0d, 0xea, 0x8c, 0x7d, 0xd2, 0xdd, 0x12, 0xfe, 0xfe, 0x17,
- 0x72, 0x6a, 0xc5, 0xfc, 0xc5, 0xe1, 0x6b, 0x65, 0x8a, 0x95, 0xca, 0x9d,
- 0x8c, 0x5c, 0xa0, 0x08, 0xe5, 0x0a, 0x1f, 0x47, 0x7f, 0xd2, 0x1f, 0x81,
- 0xa7, 0x98, 0x5f, 0x77, 0x7e, 0x58, 0xb0, 0x45, 0x8a, 0xea, 0x6b, 0x46,
- 0x33, 0x68, 0x96, 0x2f, 0xf8, 0xfe, 0x29, 0xd3, 0xfb, 0x8b, 0x14, 0xe7,
- 0x98, 0xc2, 0x77, 0xff, 0x8d, 0xe6, 0xff, 0x16, 0xc5, 0x81, 0xe6, 0xcb,
- 0x15, 0x87, 0xe0, 0xe4, 0x17, 0xfe, 0x7c, 0x8b, 0xaf, 0x27, 0xed, 0x1e,
- 0xb1, 0x7f, 0x9b, 0xbf, 0xe7, 0x80, 0xcb, 0x17, 0x64, 0x4b, 0x17, 0xff,
- 0xf6, 0x7b, 0xaf, 0xf3, 0xf8, 0x22, 0xdf, 0xae, 0x38, 0xd6, 0x2b, 0x11,
- 0x56, 0xe6, 0x82, 0x18, 0xbf, 0xf4, 0xff, 0xae, 0xb3, 0x6c, 0x63, 0xac,
- 0x5e, 0x72, 0x89, 0x62, 0xff, 0x8a, 0x41, 0xdc, 0x39, 0x21, 0xac, 0x5c,
- 0x6c, 0x4b, 0x17, 0xdf, 0x9e, 0xfa, 0xc4, 0x7a, 0xa1, 0x0e, 0xef, 0xfd,
- 0x85, 0xd4, 0xb3, 0xff, 0x61, 0xac, 0x57, 0x8f, 0xf8, 0x47, 0xf5, 0x89,
- 0x89, 0x72, 0x1e, 0x17, 0xfb, 0x36, 0xeb, 0x16, 0xc0, 0xd2, 0xc5, 0x40,
- 0xf8, 0xbc, 0x51, 0x7f, 0xef, 0x1b, 0x25, 0x11, 0xa2, 0x98, 0x96, 0x2e,
- 0xd4, 0xac, 0x5e, 0xd3, 0x9d, 0x62, 0xa4, 0xda, 0x08, 0x5e, 0xa2, 0x44,
- 0xb9, 0x3b, 0xdf, 0xfe, 0x68, 0xfe, 0xa3, 0xfc, 0xf5, 0x88, 0x98, 0x35,
- 0x8b, 0xff, 0xf8, 0x7d, 0x78, 0xf1, 0xd2, 0x40, 0xfe, 0x16, 0x3f, 0xd6,
- 0x2f, 0xff, 0x3c, 0x74, 0x90, 0x3f, 0x85, 0x8f, 0xf5, 0x8b, 0xd8, 0x7e,
- 0xa4, 0x8a, 0x8e, 0x2f, 0x54, 0x13, 0x30, 0x28, 0x7d, 0xdd, 0x3c, 0x58,
- 0xbf, 0xee, 0xf2, 0x7b, 0x88, 0xa4, 0xeb, 0x17, 0xe6, 0x2c, 0x16, 0xcb,
- 0x17, 0x0a, 0x3d, 0x62, 0xfc, 0x59, 0xdc, 0x38, 0xb1, 0x7c, 0x7c, 0xf7,
- 0x3a, 0x9f, 0x64, 0x71, 0x40, 0x41, 0xbb, 0xff, 0xed, 0xb0, 0x7d, 0x4e,
- 0xd0, 0xd3, 0xec, 0xc7, 0x58, 0xbf, 0xbb, 0xe7, 0xf1, 0xb4, 0xb1, 0x7f,
- 0xff, 0xfe, 0xc7, 0xe9, 0x9c, 0xfc, 0xf7, 0xd4, 0xef, 0xd4, 0xb3, 0x92,
- 0x6f, 0x27, 0x5b, 0xac, 0x5f, 0xff, 0xcf, 0x9d, 0x90, 0xbd, 0x3f, 0xeb,
- 0xd1, 0xfd, 0x14, 0xac, 0x5f, 0xfe, 0xef, 0x35, 0xd7, 0xf9, 0x17, 0xe4,
- 0x8d, 0x58, 0xb9, 0xcf, 0xa4, 0x57, 0x93, 0x05, 0x3a, 0x7d, 0x2c, 0xa8,
- 0x45, 0xfe, 0x8c, 0xe6, 0xff, 0xd2, 0x5e, 0x98, 0x39, 0x1b, 0x2b, 0x17,
- 0xed, 0xdf, 0x98, 0x35, 0x8b, 0xff, 0xe1, 0x47, 0xfd, 0x8a, 0x2e, 0xba,
- 0xcf, 0x37, 0x6b, 0x1f, 0x35, 0x35, 0xb3, 0x24, 0xa0, 0x64, 0x06, 0xc3,
- 0xbf, 0x72, 0xee, 0xe3, 0xb5, 0x78, 0x5c, 0xc5, 0x1a, 0x99, 0xca, 0x3e,
- 0x2e, 0x08, 0x53, 0xfa, 0x51, 0xb7, 0x44, 0x10, 0xd9, 0xaf, 0xff, 0x36,
- 0xdf, 0x97, 0xf7, 0x27, 0x6c, 0xe2, 0xc5, 0xf7, 0x5d, 0xb3, 0x8b, 0x15,
- 0x87, 0xe2, 0x74, 0xbb, 0xfd, 0xad, 0xa5, 0xf5, 0x84, 0xb1, 0x78, 0xde,
- 0x44, 0xb1, 0x58, 0x7a, 0x7d, 0x99, 0xd8, 0xeb, 0x1d, 0x4d, 0x15, 0xf4,
- 0x4f, 0x9b, 0x2c, 0x5e, 0x2c, 0x1a, 0xc5, 0xf8, 0x18, 0x2d, 0x6c, 0xb1,
- 0x71, 0x9c, 0x58, 0xbc, 0x3f, 0xca, 0xc7, 0x52, 0xe6, 0xb0, 0xfc, 0x44,
- 0x87, 0x7d, 0xd7, 0xed, 0x12, 0xc5, 0x4a, 0x63, 0x98, 0x49, 0xd9, 0x21,
- 0x42, 0x37, 0x84, 0x37, 0xed, 0xe7, 0xf2, 0x75, 0x8b, 0xe9, 0xc0, 0xf6,
- 0x58, 0xac, 0x3c, 0xd2, 0x29, 0xbd, 0x1c, 0x2f, 0x2c, 0x5f, 0xb7, 0x9f,
- 0xc9, 0xd6, 0x2f, 0xde, 0xe1, 0x39, 0xab, 0x17, 0xfc, 0xc6, 0xe6, 0xf3,
- 0xf9, 0x3a, 0xc5, 0xf0, 0xf5, 0xa9, 0x58, 0xbe, 0x37, 0xed, 0x05, 0x8a,
- 0xc3, 0xc7, 0x72, 0x3a, 0x8d, 0x93, 0x34, 0x81, 0x06, 0x10, 0x9c, 0xa4,
- 0x8a, 0x43, 0x84, 0x0d, 0xfb, 0x99, 0x84, 0x6a, 0xc5, 0xff, 0xee, 0xe1,
- 0xc8, 0x9c, 0xb0, 0x78, 0x46, 0xac, 0x5f, 0xff, 0xfe, 0x1b, 0xf4, 0x71,
- 0xfd, 0xfa, 0x84, 0xf0, 0xbb, 0x87, 0x3f, 0x9e, 0x91, 0xac, 0x57, 0x68,
- 0xf4, 0x62, 0x81, 0x26, 0x5e, 0x32, 0x40, 0xb1, 0x7f, 0xb7, 0xdd, 0xc3,
- 0x18, 0xb4, 0xb1, 0x47, 0x3d, 0x62, 0x1e, 0xbf, 0x02, 0x4f, 0x3a, 0x58,
- 0xbf, 0xfd, 0xb0, 0xf4, 0xdb, 0x96, 0x74, 0xd3, 0xf1, 0x62, 0xa5, 0x53,
- 0x96, 0x46, 0xaa, 0xf0, 0x86, 0x62, 0x11, 0x14, 0x5d, 0xee, 0x2c, 0x5f,
- 0xf9, 0xb9, 0xd6, 0x62, 0x7f, 0xb1, 0xd6, 0x2f, 0xef, 0x7d, 0xa2, 0x30,
- 0xeb, 0x14, 0xb1, 0x6f, 0xac, 0x57, 0xcb, 0xe6, 0x0c, 0xbb, 0x38, 0xb1,
- 0x73, 0x69, 0x62, 0xc0, 0x81, 0xae, 0xd0, 0xbd, 0xce, 0x05, 0x8b, 0x0d,
- 0x62, 0xe6, 0x87, 0x53, 0x52, 0x60, 0xbd, 0xbd, 0x27, 0xff, 0xf5, 0x0a,
- 0x89, 0x38, 0x36, 0x41, 0x02, 0x79, 0x43, 0x32, 0xe3, 0x98, 0xb1, 0x74,
- 0x8d, 0x62, 0xee, 0x3a, 0xc5, 0xdd, 0x81, 0x62, 0xbe, 0x78, 0xe1, 0x71,
- 0x71, 0x0b, 0xdf, 0xfa, 0x27, 0xe1, 0x9d, 0x81, 0x9f, 0x65, 0x8b, 0xee,
- 0xc1, 0xa9, 0x58, 0xb7, 0x3a, 0x9f, 0x3c, 0xa1, 0xdc, 0x37, 0x58, 0xa9,
- 0x6d, 0x5d, 0x36, 0x86, 0x06, 0x52, 0x81, 0xf7, 0x8d, 0x41, 0xe3, 0xb2,
- 0xd4, 0xe2, 0x0f, 0xd4, 0xda, 0x39, 0xb0, 0x21, 0x13, 0x07, 0x21, 0x35,
- 0xd0, 0xa6, 0xff, 0xba, 0xff, 0x02, 0x3f, 0x9e, 0x0b, 0x17, 0xf7, 0x86,
- 0x26, 0xd4, 0x16, 0x2f, 0x74, 0xfe, 0x2c, 0x5f, 0x39, 0xe7, 0xeb, 0x17,
- 0xe6, 0xff, 0x51, 0xca, 0xc5, 0x41, 0x1a, 0xf8, 0x7a, 0xe5, 0xff, 0x1f,
- 0xf1, 0x15, 0xfd, 0xe2, 0x98, 0x67, 0x96, 0x2f, 0xb0, 0x9a, 0x0b, 0x17,
- 0xde, 0xe1, 0x9c, 0xea, 0x79, 0xd1, 0xb1, 0x6d, 0xe9, 0xf7, 0x16, 0x2f,
- 0xe7, 0xdb, 0x3e, 0x2f, 0x2c, 0x51, 0x1e, 0x67, 0x87, 0x6d, 0x8b, 0x17,
- 0xb9, 0x26, 0xac, 0x57, 0xcd, 0x7f, 0x84, 0x6d, 0x12, 0xc5, 0xfd, 0x82,
- 0xcf, 0xef, 0xb2, 0xc5, 0xff, 0xe9, 0xff, 0x51, 0xce, 0xdd, 0x45, 0xb4,
- 0xfd, 0x62, 0xa5, 0x12, 0x9c, 0x13, 0x11, 0x85, 0xfb, 0xae, 0x0f, 0x09,
- 0x62, 0xbb, 0x3d, 0x82, 0x2f, 0xbd, 0xf9, 0x1a, 0xc5, 0x4a, 0x69, 0x99,
- 0x18, 0x6c, 0x44, 0x57, 0xff, 0x8d, 0x2c, 0xdf, 0xee, 0x13, 0xdf, 0x78,
- 0x96, 0x2f, 0xff, 0xdd, 0x77, 0xfb, 0x8c, 0xa5, 0xb6, 0xdf, 0xed, 0xa5,
- 0x8a, 0x74, 0x54, 0x89, 0x3e, 0xfe, 0xcd, 0x01, 0xcb, 0xcb, 0x17, 0x77,
- 0xda, 0xc5, 0x8f, 0xd4, 0xf1, 0xce, 0x5b, 0x7e, 0xf3, 0xec, 0x4c, 0xb1,
- 0x7d, 0x9e, 0x9f, 0xac, 0x5f, 0x36, 0xb0, 0xeb, 0x17, 0xfe, 0xe7, 0x50,
- 0x9e, 0xcf, 0xf9, 0xce, 0xb1, 0x43, 0x3e, 0x6f, 0x11, 0x5d, 0xb4, 0xac,
- 0x54, 0x11, 0xd5, 0xf2, 0x82, 0x84, 0x47, 0x88, 0xaf, 0xef, 0xb4, 0x0f,
- 0xa7, 0x58, 0xbf, 0xf1, 0xad, 0xee, 0x78, 0xa7, 0xb8, 0x2c, 0x5f, 0x4f,
- 0x5e, 0x69, 0x62, 0x8d, 0x3e, 0x6d, 0x20, 0xdf, 0xd9, 0x8c, 0x5e, 0xe2,
- 0xc5, 0xf8, 0xa6, 0x19, 0xe5, 0x8a, 0x23, 0xd3, 0xf1, 0x65, 0x99, 0x62,
- 0xa5, 0x15, 0x10, 0x76, 0xf1, 0x0d, 0xf8, 0x85, 0x13, 0x0d, 0x62, 0xff,
- 0x3f, 0x8c, 0xd4, 0xfe, 0x56, 0x2f, 0xff, 0xfa, 0x74, 0xfb, 0x0a, 0x3f,
- 0xa9, 0x77, 0x31, 0xfd, 0x5a, 0x2c, 0x65, 0x8b, 0xc7, 0x1c, 0x68, 0xb1,
- 0x6e, 0x2c, 0x56, 0x1b, 0x57, 0x23, 0xb1, 0xd6, 0x2f, 0x6b, 0x3b, 0x58,
- 0xbd, 0x8f, 0xb2, 0xc5, 0xf4, 0x9c, 0xee, 0xb1, 0x6c, 0xd8, 0xdf, 0xf8,
- 0x76, 0xff, 0xff, 0xa7, 0xe7, 0x33, 0x7e, 0xa6, 0xc9, 0x6f, 0xd5, 0xf5,
- 0xa7, 0x0d, 0x62, 0x86, 0x99, 0x2f, 0xc7, 0xc0, 0x24, 0x4b, 0xbc, 0x27,
- 0xbe, 0xc3, 0x8b, 0xcb, 0x17, 0x98, 0x1b, 0x2c, 0x5f, 0xfa, 0x77, 0x2c,
- 0xe8, 0x13, 0x4d, 0xda, 0xc5, 0xfe, 0x7c, 0xec, 0x26, 0x9b, 0xb5, 0x8b,
- 0x67, 0x0f, 0xec, 0x22, 0x25, 0x69, 0x18, 0x45, 0x09, 0x9b, 0xe7, 0x36,
- 0x4e, 0xb1, 0x7d, 0xb0, 0xb5, 0xba, 0xc5, 0xff, 0xec, 0xf1, 0x4e, 0xfd,
- 0x4b, 0x39, 0xf1, 0x2c, 0x5f, 0xe7, 0x2c, 0xf3, 0x73, 0x16, 0x2f, 0xf3,
- 0xe7, 0x61, 0x34, 0xdd, 0xac, 0x5b, 0x22, 0x3e, 0x80, 0x86, 0x37, 0xfc,
- 0x6c, 0x94, 0x33, 0xee, 0x75, 0x8b, 0x98, 0xde, 0xa9, 0xc3, 0xc9, 0x3e,
- 0xc4, 0x7f, 0x26, 0x28, 0x5a, 0x78, 0xaa, 0xfb, 0x9c, 0x93, 0xac, 0x5f,
- 0x7e, 0x7a, 0x4a, 0xc5, 0x39, 0xe3, 0xb1, 0x1d, 0x4a, 0xed, 0x84, 0x0a,
- 0x70, 0xd1, 0xe3, 0xcc, 0xd2, 0x51, 0x4a, 0x6c, 0xe9, 0x0b, 0x1a, 0x96,
- 0x67, 0x7e, 0x42, 0x58, 0xd8, 0x47, 0x3c, 0x73, 0x9a, 0x86, 0xf9, 0xda,
- 0x5a, 0x31, 0x40, 0x20, 0x94, 0x67, 0x82, 0x9d, 0xdf, 0xb0, 0x6b, 0x16,
- 0xd9, 0x62, 0xba, 0x1a, 0x68, 0xe1, 0x3b, 0xcf, 0x21, 0x16, 0x2f, 0xff,
- 0xf8, 0x19, 0xee, 0x75, 0xfe, 0x6f, 0x9b, 0xf5, 0xe0, 0xcb, 0x3e, 0xb1,
- 0x7e, 0x1b, 0x93, 0x0d, 0x62, 0xf7, 0x07, 0xda, 0xc5, 0xef, 0xc6, 0xda,
- 0x58, 0xb8, 0x1b, 0xac, 0x5f, 0xfe, 0xc8, 0xbf, 0x24, 0x69, 0x67, 0xbe,
- 0x25, 0x8a, 0xea, 0x88, 0x73, 0x48, 0xfe, 0x33, 0x7d, 0xb8, 0x9a, 0x0b,
- 0x15, 0xd5, 0x1f, 0xb0, 0x85, 0x37, 0x66, 0x74, 0x34, 0xf9, 0xfb, 0x1e,
- 0x76, 0xdd, 0x46, 0x49, 0x74, 0x71, 0x2c, 0x5f, 0xda, 0xfe, 0x68, 0x58,
- 0xb1, 0x7f, 0xff, 0x67, 0x70, 0xe7, 0xbf, 0x27, 0x97, 0x1f, 0x59, 0x0a,
- 0x2c, 0x5f, 0xfe, 0x28, 0x9c, 0xfa, 0xce, 0xe1, 0xc1, 0x44, 0xb1, 0x7f,
- 0xf8, 0xb7, 0xfb, 0x7b, 0xae, 0xb3, 0xcd, 0xda, 0xc5, 0x62, 0x65, 0x8e,
- 0x5c, 0xcc, 0x42, 0x4e, 0xbd, 0xde, 0x1a, 0xb1, 0x7f, 0x66, 0xdb, 0x0b,
- 0x5b, 0x2c, 0x5b, 0x5f, 0x3d, 0x12, 0x1f, 0xbf, 0x68, 0x89, 0xbe, 0xb1,
- 0x7f, 0x17, 0x5d, 0xf8, 0x01, 0xac, 0x54, 0xa2, 0x01, 0xc9, 0xd8, 0x9e,
- 0xff, 0xfe, 0x7e, 0x7f, 0x35, 0xa9, 0xdb, 0xae, 0x10, 0xff, 0x2b, 0x17,
- 0xfe, 0x17, 0x3a, 0x9c, 0xcf, 0xb7, 0xe5, 0x62, 0xfd, 0x9e, 0x16, 0x76,
- 0xb1, 0x78, 0xdc, 0xed, 0x62, 0xe9, 0x8b, 0xa9, 0xe4, 0x78, 0xa6, 0xb1,
- 0x31, 0x82, 0x5d, 0x14, 0x22, 0xef, 0xfc, 0x6f, 0xe7, 0x3e, 0xf9, 0xa8,
- 0x96, 0x2f, 0xff, 0xde, 0xc7, 0x3f, 0x52, 0xcd, 0xdf, 0x5a, 0x7d, 0x96,
- 0x28, 0x91, 0x30, 0x1a, 0x05, 0xff, 0xff, 0xf8, 0x45, 0xd4, 0x36, 0xee,
- 0x1a, 0x60, 0x75, 0xe0, 0xa7, 0xbf, 0xe3, 0x96, 0x1a, 0xb1, 0x7f, 0xff,
- 0xff, 0xb7, 0xcd, 0xcb, 0x3d, 0xf1, 0x7d, 0xbb, 0x87, 0x3d, 0xac, 0x0f,
- 0x1c, 0x7e, 0xe3, 0xac, 0x5f, 0xfb, 0x3c, 0x52, 0x0e, 0xb8, 0xe3, 0x58,
- 0xbf, 0xff, 0xd8, 0x73, 0xcc, 0x59, 0xc7, 0xc0, 0x73, 0xae, 0x38, 0xd6,
- 0x2f, 0xde, 0x16, 0x17, 0x57, 0x45, 0x09, 0x1f, 0xdf, 0xf1, 0xf0, 0xfd,
- 0x4f, 0x1f, 0xd2, 0x0b, 0x17, 0xff, 0xff, 0xb3, 0xae, 0x8c, 0xe4, 0xf5,
- 0xe3, 0xe1, 0x45, 0xcf, 0x3e, 0x6c, 0x52, 0xb1, 0x5a, 0x47, 0xe9, 0xcf,
- 0xfe, 0x85, 0x7f, 0xfd, 0xad, 0x67, 0xb9, 0xf7, 0xce, 0xbf, 0x04, 0xac,
- 0x54, 0xaa, 0xb2, 0x79, 0x46, 0x02, 0x30, 0xbf, 0xff, 0xa7, 0xf8, 0x33,
- 0x45, 0x3f, 0xcf, 0x49, 0xdb, 0xcb, 0x15, 0x2a, 0xfc, 0x70, 0x8f, 0xf2,
- 0xcf, 0x04, 0x6f, 0x7f, 0xf8, 0x18, 0xd1, 0x75, 0xe6, 0x6b, 0x59, 0xda,
- 0xc5, 0xff, 0xd8, 0x45, 0x9f, 0xc1, 0xfc, 0x51, 0x2c, 0x5f, 0xf6, 0x49,
- 0x6f, 0x9e, 0xfb, 0xac, 0x5e, 0xfc, 0xc4, 0xb1, 0x7f, 0xff, 0xfc, 0xf1,
- 0x7f, 0x39, 0xac, 0xdf, 0xaf, 0xdf, 0x0b, 0x3a, 0x16, 0x0c, 0x44, 0xb1,
- 0x7f, 0xf8, 0xa4, 0xfd, 0xf9, 0xc7, 0xd7, 0x59, 0xe5, 0x8b, 0xf6, 0x16,
- 0xe6, 0x1d, 0x62, 0xff, 0xef, 0xe4, 0x94, 0x45, 0x9e, 0xe3, 0x2c, 0x5a,
- 0x06, 0xaa, 0x22, 0x74, 0xed, 0x22, 0x7c, 0xe0, 0x87, 0xb9, 0x08, 0x0f,
- 0x26, 0x84, 0x2a, 0xbe, 0x9d, 0xf5, 0x8b, 0x17, 0xfe, 0x09, 0xe9, 0xe4,
- 0x50, 0x6d, 0x6c, 0xb1, 0x7b, 0xce, 0x6a, 0xc5, 0xd8, 0x7e, 0xa7, 0xc5,
- 0x1b, 0x22, 0x5f, 0xfc, 0xfb, 0x31, 0xce, 0xfd, 0x46, 0xfd, 0x16, 0x2a,
- 0x09, 0x81, 0x0e, 0x10, 0xba, 0x34, 0xbd, 0x13, 0xc7, 0xac, 0x5f, 0xc6,
- 0x68, 0x07, 0x7e, 0x2c, 0x5f, 0xf8, 0x1c, 0xeb, 0xfc, 0x1e, 0xb3, 0xb5,
- 0x8a, 0xec, 0xfc, 0xdc, 0xc2, 0xff, 0xfe, 0xf3, 0xed, 0x83, 0xea, 0x76,
- 0x86, 0x9f, 0x66, 0x3a, 0xc5, 0xfe, 0xd9, 0x8e, 0x53, 0xa8, 0x96, 0x2f,
- 0xf6, 0x1a, 0x03, 0xe7, 0x5d, 0x62, 0x25, 0x1d, 0x7e, 0xff, 0xff, 0x1a,
- 0x71, 0x1c, 0x41, 0x38, 0xfb, 0x7f, 0x22, 0x83, 0x04, 0x58, 0xbf, 0xfc,
- 0x5b, 0xff, 0x00, 0x01, 0x07, 0xdc, 0x38, 0xb1, 0x52, 0x8b, 0x97, 0x6a,
- 0xac, 0x4f, 0x73, 0xb8, 0x5b, 0x6a, 0x30, 0x5b, 0xe0, 0x33, 0x44, 0xb1,
- 0x69, 0x58, 0xbd, 0x85, 0xb7, 0x53, 0x69, 0xb9, 0x1d, 0xf6, 0xfd, 0x79,
- 0x8b, 0x17, 0xff, 0x6b, 0xac, 0x5f, 0x11, 0xaf, 0x84, 0x6a, 0xc5, 0xb3,
- 0x0f, 0xc0, 0x44, 0xd7, 0xf8, 0xbd, 0xe2, 0x60, 0x71, 0x62, 0xf8, 0x1d,
- 0x4f, 0xa5, 0x8a, 0x93, 0xd9, 0x11, 0x9d, 0xfb, 0xab, 0x6e, 0x58, 0xb1,
- 0x7f, 0xf6, 0x34, 0x5d, 0x7f, 0x2f, 0xb4, 0x9a, 0xb1, 0x47, 0x44, 0x9b,
- 0x10, 0x80, 0xaa, 0xff, 0xba, 0x6b, 0x3b, 0x87, 0x05, 0x12, 0xc5, 0xff,
- 0xef, 0x4e, 0x84, 0x77, 0xe7, 0x5e, 0x43, 0x8b, 0x17, 0xff, 0x03, 0x9e,
- 0xfe, 0x1f, 0x79, 0x23, 0x56, 0x29, 0xd1, 0xa8, 0xc7, 0xe2, 0x4e, 0xbf,
- 0xed, 0x6d, 0x3b, 0x6c, 0x2d, 0x6c, 0xb1, 0x7f, 0xfe, 0x29, 0x37, 0xa9,
- 0xc4, 0xfc, 0x9f, 0x9c, 0xcd, 0xd6, 0x2f, 0xff, 0x4b, 0xfb, 0x8e, 0x5d,
- 0xc3, 0xaf, 0x06, 0xb1, 0x7f, 0xee, 0xb1, 0x7c, 0x46, 0xbe, 0x11, 0xab,
- 0x17, 0xff, 0xe9, 0x8f, 0xeb, 0xdc, 0x27, 0x6e, 0xe1, 0xc2, 0x63, 0x56,
- 0x2f, 0xf1, 0x75, 0xe0, 0xa3, 0x85, 0xa5, 0x8a, 0xc4, 0x6e, 0xfd, 0x10,
- 0x4b, 0xf7, 0xff, 0xff, 0xb3, 0x76, 0xdb, 0xaf, 0x1e, 0x3a, 0x48, 0x1e,
- 0x08, 0x52, 0x58, 0xfe, 0x58, 0xbf, 0xff, 0xbd, 0x25, 0x9b, 0x75, 0xd8,
- 0x5a, 0x87, 0xa6, 0x2e, 0x2c, 0x5d, 0x3d, 0xfd, 0x1b, 0xc1, 0x1f, 0x6a,
- 0x55, 0x81, 0x1c, 0xff, 0xeb, 0x7c, 0x8c, 0xa8, 0x51, 0x86, 0xdf, 0xc5,
- 0x9d, 0x0b, 0x38, 0xb1, 0x7b, 0xb6, 0x25, 0x8a, 0xea, 0x79, 0x78, 0x5d,
- 0x7f, 0x9c, 0x1d, 0x5f, 0xee, 0x75, 0x8a, 0x19, 0xec, 0x11, 0x1d, 0xff,
- 0xdd, 0x79, 0xf1, 0x75, 0xf7, 0x39, 0x3a, 0x58, 0xbf, 0xff, 0xa7, 0x40,
- 0xeb, 0x3d, 0x1b, 0xf3, 0xad, 0x67, 0xb8, 0xb1, 0x5b, 0x22, 0xab, 0xe9,
- 0x77, 0xfe, 0x84, 0xf8, 0x5b, 0xf5, 0xe7, 0x9d, 0x62, 0xff, 0xfb, 0xf3,
- 0xb7, 0x52, 0xce, 0x8d, 0xff, 0xcf, 0x6b, 0x17, 0xff, 0xfd, 0xdf, 0x1f,
- 0x03, 0xeb, 0xfc, 0xf7, 0x33, 0x6e, 0xb8, 0xe3, 0x58, 0xa1, 0xa3, 0x0b,
- 0x15, 0x6f, 0xfd, 0xe7, 0xee, 0x05, 0x3d, 0x42, 0x6e, 0xb1, 0x7f, 0xfa,
- 0x4e, 0x59, 0xd0, 0xb3, 0xa6, 0x6a, 0x0b, 0x15, 0x88, 0x91, 0x24, 0x5b,
- 0xff, 0xe9, 0xee, 0x1c, 0xfb, 0xe7, 0xbb, 0x83, 0xfd, 0x62, 0xff, 0x8b,
- 0x35, 0x9b, 0xe3, 0x8d, 0x62, 0xfe, 0xdb, 0xd1, 0x14, 0x9d, 0x62, 0xfb,
- 0xfd, 0xe1, 0xab, 0x17, 0xe6, 0x98, 0xa6, 0x25, 0x8b, 0xf6, 0x0f, 0xe2,
- 0x0d, 0x62, 0xba, 0x9e, 0x99, 0x14, 0xda, 0x77, 0x44, 0xdc, 0x4f, 0x17,
- 0xff, 0xed, 0xb1, 0xc6, 0x42, 0xff, 0x59, 0x1b, 0x45, 0xc5, 0x8b, 0xfb,
- 0x52, 0x31, 0x61, 0xab, 0x15, 0x88, 0x88, 0x75, 0x9b, 0xfb, 0x3e, 0xfa,
- 0xfb, 0x2c, 0x5f, 0xbe, 0xfa, 0xfb, 0x2c, 0x5d, 0x81, 0xf5, 0x3d, 0x5c,
- 0x2d, 0xa9, 0x5d, 0x74, 0xc8, 0x65, 0xf6, 0x48, 0xf1, 0x82, 0xc5, 0x0b,
- 0x3d, 0x10, 0xfd, 0x49, 0x8e, 0x0a, 0x19, 0x7c, 0x85, 0x97, 0x9d, 0xaf,
- 0xbd, 0x98, 0x35, 0x8a, 0xd9, 0xbb, 0x37, 0x1c, 0x61, 0x86, 0xc6, 0x8b,
- 0xbc, 0xe5, 0xef, 0x72, 0x99, 0x9e, 0x38, 0x18, 0x8d, 0xb5, 0x29, 0xc0,
- 0xee, 0x1f, 0x85, 0x28, 0x23, 0x12, 0x28, 0xc0, 0xf9, 0x2c, 0xc3, 0xd3,
- 0xcd, 0xc1, 0x21, 0x65, 0x7d, 0xf7, 0xc8, 0x96, 0x2f, 0xf6, 0x07, 0xd4,
- 0x8b, 0x3b, 0x58, 0xbe, 0x7e, 0x60, 0xfa, 0x9e, 0xce, 0xc4, 0x77, 0xd0,
- 0xc2, 0xfa, 0xc5, 0xfe, 0xf1, 0x67, 0xbf, 0x9b, 0x2c, 0x5f, 0x4c, 0x78,
- 0xa2, 0x58, 0xbb, 0x58, 0xb1, 0x7b, 0x3d, 0xc5, 0x8b, 0xf8, 0x27, 0x9c,
- 0x98, 0xeb, 0x14, 0xb1, 0x7d, 0xcc, 0x9d, 0xba, 0x9b, 0xb3, 0x97, 0xd6,
- 0xc8, 0xa9, 0x88, 0x5f, 0xcb, 0x17, 0xbe, 0xc6, 0xac, 0x5f, 0xee, 0xba,
- 0xce, 0xe0, 0xe7, 0x58, 0xad, 0x22, 0x1f, 0xc6, 0x41, 0x8f, 0x5f, 0xf9,
- 0xb5, 0xfc, 0xf4, 0x93, 0x81, 0x62, 0xc1, 0x16, 0x2f, 0x6c, 0x7d, 0xd6,
- 0x2f, 0xcf, 0x85, 0x9d, 0x16, 0x2f, 0xb1, 0xe2, 0xeb, 0xd9, 0xe4, 0x7c,
- 0x82, 0xef, 0x4a, 0xc5, 0xd3, 0xa5, 0x8b, 0xfc, 0x2f, 0x66, 0x1c, 0x01,
- 0xac, 0x5e, 0xcd, 0xba, 0xc4, 0x79, 0x80, 0x17, 0xae, 0xd1, 0x34, 0x4c,
- 0x77, 0xbc, 0xfb, 0x2c, 0x5a, 0x39, 0x62, 0xa0, 0x6c, 0xe3, 0xc7, 0xaf,
- 0xf6, 0xef, 0xcc, 0x1f, 0x51, 0xac, 0x5f, 0xdd, 0xc3, 0x9d, 0x7c, 0xeb,
- 0x16, 0xcf, 0x9f, 0x48, 0x66, 0xf7, 0xff, 0xe2, 0x93, 0xf5, 0x1f, 0xc5,
- 0xd6, 0x63, 0xff, 0x27, 0x58, 0xbf, 0xf4, 0x27, 0x01, 0xfc, 0xc2, 0xdd,
- 0x62, 0xff, 0xf7, 0xdc, 0x87, 0xd4, 0xcd, 0xcb, 0x3f, 0x8b, 0x17, 0xfc,
- 0xde, 0xe4, 0x50, 0x11, 0x79, 0x62, 0xb1, 0x18, 0xd1, 0x1f, 0x01, 0x36,
- 0xff, 0xbe, 0xe7, 0x9c, 0x2f, 0x71, 0x62, 0xff, 0xff, 0x0b, 0xda, 0x14,
- 0x5d, 0x7d, 0x17, 0xc4, 0x0f, 0x3e, 0x04, 0x58, 0xbe, 0x9d, 0xe4, 0xfd,
- 0x51, 0xa5, 0xb9, 0x81, 0x1c, 0x54, 0xaf, 0x3a, 0x0c, 0xd3, 0x23, 0x57,
- 0xdc, 0xc5, 0xcf, 0x62, 0x5c, 0xd4, 0x35, 0x99, 0x58, 0xa1, 0x1b, 0xe2,
- 0x80, 0x91, 0xfa, 0xdf, 0xfe, 0x68, 0xba, 0xb1, 0x41, 0xcf, 0xd6, 0x49,
- 0x62, 0xff, 0xfd, 0x8c, 0x7e, 0xa6, 0xb7, 0x7f, 0xcf, 0xfe, 0x7c, 0xb1,
- 0x58, 0x8a, 0x6d, 0x26, 0xdf, 0x66, 0x03, 0x8b, 0x17, 0x38, 0x6b, 0x17,
- 0xb5, 0x14, 0x16, 0x2f, 0xfd, 0x9d, 0xfb, 0xaf, 0x27, 0xed, 0x1e, 0xb1,
- 0x43, 0x3f, 0xcc, 0x18, 0xd0, 0xfd, 0xff, 0xcf, 0xdc, 0x39, 0xd4, 0x6f,
- 0xd2, 0x46, 0xb1, 0x7b, 0xb9, 0x8f, 0x58, 0xa5, 0x8b, 0xfe, 0xf7, 0x70,
- 0x7f, 0xf7, 0x07, 0x58, 0xba, 0x62, 0x88, 0xf2, 0x38, 0x19, 0x46, 0xa3,
- 0x89, 0x92, 0x84, 0xd3, 0x7d, 0x9f, 0x6e, 0x8b, 0x17, 0xf4, 0x33, 0xf9,
- 0xd3, 0x8b, 0x16, 0xc1, 0x9e, 0xa4, 0x44, 0x97, 0xff, 0xdf, 0x17, 0x3a,
- 0xfd, 0xfd, 0xfc, 0xd4, 0xf4, 0x58, 0xbf, 0x71, 0xf3, 0xb3, 0xac, 0x5e,
- 0xcd, 0x71, 0x62, 0x86, 0x89, 0xbf, 0x2a, 0xf4, 0x29, 0xbf, 0xb5, 0x82,
- 0xfc, 0x9d, 0x62, 0xf6, 0x60, 0x16, 0x2e, 0xce, 0xfa, 0x9e, 0x51, 0x17,
- 0x56, 0x22, 0xac, 0x9f, 0x2f, 0xd3, 0xdf, 0xf3, 0x65, 0x8b, 0xff, 0x38,
- 0x7d, 0x75, 0x30, 0xe4, 0x81, 0x62, 0x88, 0xfb, 0x3c, 0x55, 0x7e, 0xcf,
- 0xf5, 0xe9, 0xba, 0xc5, 0xd2, 0x71, 0xae, 0x3e, 0x64, 0x27, 0x8d, 0x8c,
- 0x43, 0x50, 0x84, 0x28, 0xdb, 0xbd, 0x08, 0xd1, 0x10, 0xdd, 0xac, 0x58,
- 0xbf, 0xfb, 0x52, 0x18, 0x42, 0x90, 0xfb, 0x87, 0x16, 0x2d, 0x2b, 0x17,
- 0xcf, 0xa6, 0xed, 0x62, 0xde, 0x73, 0x69, 0xc1, 0x1a, 0x1a, 0x29, 0x1d,
- 0xfa, 0xff, 0x98, 0xb7, 0xfb, 0x9c, 0xa5, 0x62, 0xff, 0xe1, 0x93, 0x45,
- 0x14, 0xf8, 0x19, 0xc5, 0x8b, 0xff, 0xe2, 0x9d, 0xbf, 0x2f, 0xee, 0x39,
- 0x77, 0x05, 0x8b, 0x8e, 0x62, 0xc5, 0xa2, 0x58, 0xa5, 0x8a, 0x92, 0xff,
- 0x42, 0x75, 0x27, 0xae, 0xe7, 0x17, 0xb6, 0xc0, 0xd6, 0x2f, 0xf0, 0xfa,
- 0xcc, 0x43, 0x60, 0xd6, 0x2e, 0x7e, 0x9d, 0x4f, 0x5d, 0xc7, 0xef, 0xff,
- 0xff, 0x13, 0x9b, 0xf6, 0x8b, 0xa9, 0x08, 0x27, 0x5c, 0xee, 0x18, 0x22,
- 0x07, 0x16, 0x2f, 0xff, 0x9e, 0x1e, 0xe6, 0x74, 0xd6, 0x03, 0x8d, 0xba,
- 0xc5, 0xfe, 0xc6, 0x37, 0xa8, 0x6c, 0x1a, 0xc5, 0xff, 0xfe, 0xcd, 0xfa,
- 0x96, 0x7d, 0xf3, 0x9d, 0x71, 0xff, 0x9b, 0xac, 0x5b, 0x06, 0x89, 0xcf,
- 0x9c, 0x5f, 0xb9, 0x3d, 0x1c, 0x96, 0x2f, 0xfb, 0xda, 0x14, 0x3b, 0x86,
- 0x79, 0x62, 0xf9, 0xe4, 0xb6, 0x58, 0xa7, 0x3d, 0xef, 0x9e, 0x51, 0xd5,
- 0x1f, 0xfe, 0x10, 0x05, 0x0e, 0xff, 0x14, 0x74, 0x84, 0x3d, 0xff, 0xfc,
- 0x21, 0xb1, 0x03, 0xaf, 0xb3, 0xf3, 0xed, 0x60, 0xd6, 0x2f, 0x8e, 0xee,
- 0x1a, 0xc5, 0xfe, 0xd3, 0x73, 0xa8, 0x7c, 0xd9, 0x62, 0xa5, 0x31, 0x58,
- 0x2e, 0x32, 0xe8, 0x88, 0xe8, 0x97, 0x0d, 0xf8, 0xef, 0xe9, 0x70, 0x97,
- 0xfe, 0x7f, 0x72, 0x7d, 0xf9, 0xec, 0x0b, 0x17, 0x8b, 0x25, 0x62, 0xfe,
- 0x9d, 0xbe, 0xf8, 0x35, 0x8a, 0xc3, 0xc9, 0xd0, 0xdd, 0xff, 0xf3, 0xf3,
- 0xa8, 0xfe, 0x2e, 0xb2, 0xe3, 0x33, 0x4b, 0x17, 0xd3, 0x17, 0x1d, 0x62,
- 0xff, 0x49, 0xe6, 0x30, 0x30, 0xc3, 0x58, 0xa9, 0x5f, 0xcf, 0x84, 0x2e,
- 0xc6, 0x45, 0x87, 0x1b, 0xa3, 0x3c, 0xe6, 0xf4, 0x47, 0x3a, 0x84, 0x49,
- 0xc8, 0x49, 0x58, 0x21, 0x1d, 0xff, 0xfd, 0x09, 0xd1, 0xa7, 0x27, 0xee,
- 0x1c, 0x1e, 0x9f, 0x65, 0x8b, 0xff, 0xfd, 0xc7, 0x10, 0xfa, 0x9a, 0x4c,
- 0x31, 0x67, 0xfa, 0xc5, 0x12, 0xc5, 0xb2, 0x24, 0x64, 0x71, 0x7e, 0xf4,
- 0xc5, 0xc5, 0x8b, 0x84, 0x35, 0x8b, 0xa7, 0xcb, 0x17, 0xf7, 0x08, 0xb0,
- 0x1c, 0x58, 0xa8, 0x8f, 0x73, 0x43, 0x1e, 0x17, 0xbf, 0xff, 0xf3, 0x0f,
- 0x09, 0xbd, 0xcc, 0xd0, 0x01, 0x39, 0xdf, 0xb8, 0xeb, 0x16, 0x8d, 0xd6,
- 0x2b, 0xab, 0xb8, 0x34, 0x99, 0x41, 0xbb, 0x22, 0x65, 0x78, 0xfb, 0xbc,
- 0x6f, 0x9d, 0x9d, 0xbc, 0xf4, 0xb6, 0xa3, 0x56, 0xfc, 0xe4, 0xf3, 0x52,
- 0x16, 0xca, 0x37, 0x5f, 0x14, 0x89, 0xe8, 0x33, 0x08, 0xe6, 0xbb, 0xde,
- 0xcf, 0xac, 0x5e, 0xe6, 0x6e, 0xb1, 0x7e, 0x83, 0x8f, 0x09, 0x62, 0xba,
- 0x9e, 0x2c, 0x8f, 0x5e, 0xe3, 0xe9, 0x62, 0xff, 0xe6, 0x7f, 0x42, 0x4b,
- 0xdc, 0x71, 0xac, 0x54, 0x9f, 0x07, 0xc7, 0x6e, 0xd6, 0x2c, 0x5e, 0xf3,
- 0xf4, 0x58, 0xa0, 0x1b, 0x62, 0x17, 0xbe, 0x80, 0x9b, 0xcb, 0x17, 0x4c,
- 0x7a, 0xc5, 0xc2, 0x8f, 0x58, 0xbd, 0x25, 0x2b, 0x15, 0xb9, 0xe8, 0x68,
- 0x68, 0xe3, 0x75, 0x28, 0xc3, 0xc2, 0x07, 0x73, 0xbe, 0xf7, 0x18, 0x0b,
- 0x17, 0xff, 0xc2, 0xdb, 0xac, 0xbf, 0xf7, 0x90, 0x1d, 0xa0, 0xb1, 0x7f,
- 0xe7, 0xea, 0xfa, 0x16, 0xcd, 0xad, 0xd6, 0x28, 0xd4, 0x4b, 0xfd, 0x52,
- 0xf9, 0xfe, 0xdb, 0x2c, 0x5f, 0x3e, 0xed, 0xa5, 0x8b, 0xf4, 0x91, 0xcd,
- 0x35, 0x62, 0xff, 0x3f, 0x1c, 0x41, 0x71, 0xca, 0xc5, 0xe9, 0xf4, 0xac,
- 0x54, 0x11, 0x40, 0x32, 0x3f, 0x15, 0x74, 0x37, 0xbf, 0xba, 0x96, 0x0e,
- 0x40, 0xb1, 0x7c, 0x77, 0x2d, 0xd6, 0x28, 0x67, 0xa5, 0xf2, 0xfb, 0xec,
- 0xf3, 0xf1, 0x62, 0xb0, 0xf1, 0x38, 0x45, 0x7a, 0x3b, 0x06, 0xb1, 0x77,
- 0x9d, 0x62, 0xa4, 0xdb, 0xb9, 0x05, 0xe8, 0x49, 0xd6, 0x2e, 0x63, 0x16,
- 0x2b, 0xe6, 0xd7, 0x83, 0xb7, 0xfe, 0xf7, 0xdf, 0x30, 0x65, 0x81, 0xac,
- 0x56, 0x1e, 0xfb, 0x90, 0xdf, 0x69, 0xfb, 0x82, 0xc5, 0xff, 0xb9, 0x31,
- 0x67, 0xdf, 0x5f, 0x65, 0x8b, 0xfb, 0x59, 0xfe, 0xe1, 0xc5, 0x8b, 0xb3,
- 0xeb, 0x17, 0x73, 0x16, 0x28, 0x68, 0xc1, 0x72, 0x4d, 0x1f, 0x9c, 0xc1,
- 0x85, 0xef, 0x69, 0xcd, 0x58, 0xbf, 0xf1, 0xf1, 0xfc, 0xde, 0xfc, 0xf9,
- 0x62, 0xe7, 0xfa, 0xc5, 0xb1, 0x62, 0xff, 0xf8, 0x58, 0xff, 0xcd, 0xfe,
- 0xfd, 0x43, 0x3e, 0xeb, 0x17, 0xbd, 0x81, 0xac, 0x5b, 0x62, 0x3f, 0x3f,
- 0x2a, 0xd1, 0xd1, 0x58, 0x28, 0x42, 0x5e, 0xd8, 0x5e, 0x58, 0xbe, 0xfb,
- 0xb0, 0x16, 0x2b, 0x0f, 0x07, 0xc3, 0xf6, 0x95, 0x8b, 0x7d, 0x62, 0xd9,
- 0xb1, 0xa3, 0x34, 0x46, 0xc1, 0xac, 0x5f, 0x45, 0x9a, 0xce, 0xa6, 0xef,
- 0x85, 0x17, 0x77, 0xc5, 0x8a, 0x1a, 0x7f, 0xd9, 0x0c, 0x30, 0x34, 0xf9,
- 0xfc, 0x47, 0x57, 0xff, 0x84, 0x5d, 0x73, 0x5b, 0x1f, 0x39, 0xfc, 0x58,
- 0xbe, 0x0b, 0x93, 0x79, 0x62, 0xb6, 0x3f, 0x31, 0x26, 0xdf, 0xf7, 0x53,
- 0xb9, 0x67, 0xbe, 0xeb, 0x17, 0xed, 0x98, 0xbd, 0xc5, 0x8b, 0xb9, 0x2b,
- 0x17, 0xe6, 0xdb, 0xac, 0x3c, 0xb1, 0x5b, 0x1e, 0x1f, 0xc5, 0xef, 0xc4,
- 0x09, 0x7e, 0x8b, 0x17, 0xe8, 0x8c, 0xe4, 0xe2, 0xc5, 0x39, 0xe9, 0xb1,
- 0x4d, 0xf9, 0xb4, 0x5d, 0xba, 0xc5, 0xe8, 0xa7, 0xcb, 0x15, 0x29, 0xd2,
- 0xc0, 0x8f, 0x0e, 0x9d, 0xb3, 0xee, 0xde, 0x20, 0x11, 0x45, 0xe9, 0x71,
- 0xac, 0x5e, 0xfb, 0x12, 0xc5, 0x05, 0x59, 0x86, 0x3b, 0x31, 0x42, 0x10,
- 0x63, 0x8c, 0x6b, 0x0b, 0x4d, 0x85, 0xd6, 0xe4, 0x8f, 0x0c, 0x38, 0xa1,
- 0xab, 0xa5, 0x83, 0xc2, 0xcf, 0xf0, 0xe1, 0x64, 0x80, 0x0f, 0x14, 0xa3,
- 0xcf, 0x4a, 0x67, 0xe8, 0xc4, 0x18, 0xe5, 0xf7, 0x05, 0x3b, 0x2c, 0x5c,
- 0xfd, 0xac, 0x58, 0x2a, 0xb1, 0x77, 0xe3, 0xd6, 0x2f, 0xee, 0xbc, 0x7f,
- 0xb9, 0xd6, 0x2f, 0x7a, 0x4e, 0xb1, 0x51, 0xb1, 0xff, 0x40, 0x5b, 0xb1,
- 0xb2, 0x30, 0xbf, 0xff, 0xb1, 0xc1, 0x25, 0x9d, 0xf9, 0xbb, 0x81, 0x9c,
- 0x02, 0xc5, 0xb6, 0x58, 0xae, 0xa7, 0xe1, 0x05, 0xdb, 0xbb, 0x35, 0x62,
- 0xfe, 0x3b, 0x43, 0x58, 0x1a, 0xc5, 0xbb, 0x19, 0xe4, 0xe0, 0xd5, 0xfe,
- 0xf7, 0x3a, 0xe7, 0xf0, 0x96, 0x2b, 0x0f, 0x75, 0x8a, 0x2f, 0x73, 0xd8,
- 0xb1, 0x7d, 0xec, 0x6d, 0xd6, 0x28, 0x2a, 0x78, 0x18, 0x3b, 0x7f, 0xbe,
- 0xe7, 0xfe, 0x01, 0x96, 0x2f, 0xfd, 0x85, 0x9a, 0xdf, 0xf8, 0x0e, 0x2c,
- 0x5f, 0x6f, 0x84, 0x05, 0x8b, 0xff, 0x7e, 0x4a, 0x77, 0xd4, 0xe1, 0x2c,
- 0x50, 0xd1, 0xa4, 0xe6, 0x6c, 0x7f, 0xe2, 0x3b, 0xc7, 0x98, 0x2c, 0x5f,
- 0xd9, 0xb4, 0x9a, 0xdc, 0x58, 0xbf, 0xfe, 0xfb, 0xeb, 0xed, 0xd7, 0x3b,
- 0x86, 0x6b, 0x65, 0x8b, 0xfb, 0xee, 0x37, 0xd6, 0xeb, 0x17, 0xd9, 0xbe,
- 0x76, 0xb1, 0x7f, 0xfe, 0x6e, 0xc7, 0xa2, 0x60, 0xcb, 0x00, 0x0c, 0x02,
- 0xc5, 0xdd, 0xf3, 0xaa, 0x70, 0x92, 0x76, 0x31, 0xdc, 0x2f, 0xdd, 0x53,
- 0xe5, 0xfe, 0x24, 0xbd, 0x14, 0x86, 0xb1, 0x7e, 0xf1, 0x66, 0x69, 0x62,
- 0xff, 0x7e, 0x5c, 0x9b, 0x46, 0xac, 0x5f, 0xd2, 0xe4, 0xda, 0x35, 0x62,
- 0xfb, 0x5a, 0x7d, 0x75, 0x3e, 0x0f, 0x99, 0xdf, 0xc5, 0x91, 0x69, 0xba,
- 0x2c, 0x5f, 0xb2, 0x2d, 0x37, 0x45, 0x8a, 0x58, 0xb6, 0xfd, 0x4f, 0x9c,
- 0x8c, 0x3a, 0x15, 0xd0, 0x11, 0xb6, 0x50, 0xa2, 0xa9, 0x4e, 0xa1, 0xc7,
- 0xda, 0x36, 0x2b, 0xc5, 0x87, 0x58, 0xb7, 0x6b, 0x17, 0x34, 0x20, 0x6b,
- 0xf8, 0x39, 0x7f, 0xff, 0xfb, 0xa9, 0xe7, 0x3d, 0xd7, 0x20, 0xfd, 0x0b,
- 0x39, 0xd6, 0x46, 0xd1, 0x71, 0x62, 0xf0, 0x7c, 0x02, 0xc5, 0xfd, 0x87,
- 0x1b, 0x36, 0xeb, 0x17, 0x16, 0xfd, 0x4f, 0x37, 0xe3, 0xf5, 0x04, 0x7e,
- 0x34, 0x33, 0x2d, 0x8b, 0x15, 0x8c, 0x8e, 0xed, 0xc9, 0x1e, 0x12, 0xd1,
- 0x42, 0xc7, 0x50, 0xca, 0x3b, 0x03, 0x4a, 0x7b, 0x04, 0xa1, 0xb2, 0x63,
- 0x14, 0x65, 0x11, 0xc4, 0xf7, 0xb9, 0xe7, 0x58, 0xbd, 0x10, 0x3b, 0x58,
- 0xbf, 0xec, 0x87, 0xe5, 0xf5, 0xa9, 0x58, 0xb8, 0xde, 0xbb, 0x9f, 0xa8,
- 0x07, 0x78, 0x41, 0x7b, 0x81, 0x7e, 0x2c, 0x54, 0x9f, 0x0f, 0x67, 0xf7,
- 0xc0, 0x00, 0xa3, 0xd6, 0x2c, 0x05, 0x8b, 0xde, 0xe4, 0xac, 0x5f, 0x0b,
- 0xb8, 0x71, 0x62, 0xdd, 0x64, 0xf0, 0xb4, 0x3b, 0x7e, 0xd6, 0xd3, 0xad,
- 0x96, 0x2f, 0xce, 0x5e, 0x30, 0xeb, 0x15, 0x27, 0xa8, 0x02, 0xbb, 0xd0,
- 0xe6, 0x2c, 0x5f, 0x82, 0xa5, 0x38, 0x05, 0x8a, 0xd1, 0xe4, 0x00, 0x76,
- 0xf3, 0x39, 0x2c, 0x5f, 0x85, 0x11, 0x49, 0xd6, 0x2f, 0x3e, 0x07, 0xd4,
- 0xf1, 0x38, 0x37, 0x7f, 0xf9, 0xcf, 0x9c, 0xea, 0x59, 0xa0, 0x64, 0x4b,
- 0x17, 0xf7, 0x01, 0x99, 0xae, 0x2c, 0x5e, 0x13, 0x71, 0x62, 0xb6, 0x54,
- 0x31, 0x07, 0xdc, 0x69, 0x3b, 0x37, 0xcd, 0x7c, 0x98, 0x61, 0x75, 0xfe,
- 0x0c, 0xf2, 0xfa, 0x14, 0x7a, 0xc5, 0xc4, 0x25, 0x8a, 0x58, 0xb6, 0xba,
- 0x9a, 0x3e, 0x0b, 0xdf, 0xba, 0xf7, 0x01, 0x6c, 0xb1, 0x7f, 0xdb, 0xe3,
- 0xfe, 0x75, 0x87, 0x58, 0xa9, 0x44, 0x84, 0x0a, 0x48, 0xba, 0xb1, 0x31,
- 0x91, 0x43, 0xae, 0xff, 0xfe, 0x7d, 0x75, 0xc7, 0xc2, 0x37, 0xef, 0x87,
- 0xcd, 0xd6, 0x2f, 0xfb, 0x3b, 0x87, 0x3b, 0x80, 0xb4, 0xb1, 0x7f, 0xff,
- 0xe3, 0xf3, 0x7f, 0xce, 0xfd, 0xc0, 0x84, 0x3e, 0xae, 0x6b, 0x10, 0x16,
- 0x2f, 0xff, 0xf6, 0xda, 0x93, 0xf0, 0x53, 0xd6, 0x75, 0x23, 0xfc, 0x9d,
- 0x62, 0xb1, 0x1a, 0xee, 0xe7, 0x7f, 0xd0, 0xeb, 0x3d, 0x7d, 0xfc, 0x25,
- 0x8a, 0xc4, 0xf3, 0x9d, 0x73, 0x51, 0x8a, 0x31, 0x0d, 0xf8, 0x1c, 0x7e,
- 0xc3, 0x58, 0xbf, 0xc2, 0x2e, 0xe1, 0xc2, 0x1a, 0xc5, 0xff, 0xec, 0x9e,
- 0xe1, 0xc2, 0xcf, 0x96, 0x06, 0xb1, 0x7e, 0xee, 0x4f, 0xb4, 0xac, 0x5f,
- 0x77, 0x07, 0xfa, 0xc5, 0xd9, 0xdf, 0xcf, 0x3b, 0xc5, 0x57, 0xe8, 0xa1,
- 0x25, 0x05, 0x8b, 0xfd, 0xdf, 0x50, 0x9e, 0xc2, 0xd9, 0x62, 0xb1, 0x35,
- 0xe3, 0x4d, 0x75, 0x09, 0x80, 0x17, 0x08, 0xa6, 0xfe, 0xed, 0xa0, 0x52,
- 0x75, 0x8b, 0xff, 0xa3, 0xce, 0x42, 0x0f, 0x58, 0xe4, 0x05, 0x8b, 0xff,
- 0xfe, 0x28, 0xbf, 0x9d, 0xc2, 0x48, 0x7d, 0x4b, 0x3a, 0x69, 0xf8, 0xb1,
- 0x7f, 0xc5, 0x17, 0x8b, 0x36, 0x62, 0x58, 0xa9, 0x47, 0x63, 0xa4, 0x09,
- 0xae, 0xfd, 0xbf, 0x53, 0xb7, 0x96, 0x2f, 0xff, 0xfe, 0xd3, 0xed, 0xd7,
- 0xf9, 0xe2, 0x98, 0xbf, 0x9b, 0x4f, 0x7e, 0x16, 0xeb, 0x15, 0x88, 0xa5,
- 0xd1, 0x65, 0xff, 0xff, 0xd2, 0x6f, 0xe7, 0xa9, 0x60, 0x8d, 0xeb, 0xdc,
- 0x38, 0xe4, 0x64, 0xec, 0xb1, 0x7e, 0x20, 0x70, 0x84, 0xb1, 0x7e, 0xc1,
- 0x4e, 0xb6, 0x58, 0xbc, 0xf8, 0x4b, 0x16, 0xec, 0x8f, 0x13, 0x85, 0x35,
- 0x89, 0x87, 0x3b, 0xd0, 0x9b, 0x2f, 0xff, 0xb0, 0x21, 0x61, 0xd8, 0xbd,
- 0xce, 0xb2, 0x1a, 0xc5, 0x4a, 0xb9, 0xfc, 0x8c, 0x69, 0xe1, 0xa7, 0xf8,
- 0xcc, 0x04, 0x5f, 0x7f, 0xef, 0x1c, 0xed, 0x17, 0x52, 0xc0, 0xd6, 0x2f,
- 0xff, 0x03, 0x83, 0x13, 0x6a, 0x1f, 0x7c, 0x3a, 0xc5, 0xff, 0x8b, 0xbc,
- 0xe0, 0xa2, 0x29, 0x3a, 0xc5, 0x62, 0x22, 0xf4, 0x97, 0x7f, 0x8d, 0xfc,
- 0xbe, 0xd2, 0x6a, 0xc5, 0xfe, 0x7e, 0xfe, 0xc7, 0x7e, 0x2c, 0x53, 0x9f,
- 0x51, 0x1b, 0x53, 0xa2, 0xb3, 0x90, 0x8c, 0xae, 0xa9, 0xd0, 0xc2, 0x37,
- 0xab, 0xff, 0x73, 0x3b, 0x83, 0xe8, 0xbb, 0xc5, 0x8b, 0xff, 0x45, 0xec,
- 0x16, 0xba, 0xb0, 0xc4, 0xb1, 0x7e, 0x39, 0x67, 0x71, 0xeb, 0x16, 0x3e,
- 0x1f, 0x7f, 0x10, 0xef, 0xf0, 0xa2, 0x2c, 0xfb, 0x79, 0x62, 0xb6, 0x4c,
- 0x2b, 0x21, 0x5e, 0x44, 0xf7, 0xfe, 0x10, 0x38, 0x59, 0xce, 0x48, 0x6b,
- 0x17, 0xf1, 0x6d, 0x1d, 0xf3, 0x34, 0xb1, 0x50, 0x3f, 0x46, 0x40, 0xbe,
- 0x0f, 0xae, 0xce, 0xb1, 0x7e, 0x0c, 0x7f, 0x63, 0xac, 0x5f, 0xee, 0xe1,
- 0xce, 0xbc, 0xf3, 0xac, 0x54, 0x9f, 0x13, 0x95, 0x56, 0x22, 0xa7, 0xf0,
- 0x89, 0xbf, 0xf6, 0x07, 0xe1, 0xbe, 0x77, 0x0e, 0x2c, 0x5f, 0xef, 0xcb,
- 0x93, 0x68, 0xd5, 0x8b, 0xff, 0xc7, 0xeb, 0x82, 0x0b, 0xbf, 0xdc, 0xec,
- 0x35, 0x8b, 0x64, 0x48, 0x83, 0x11, 0x9d, 0xff, 0x1f, 0x39, 0xd6, 0x22,
- 0x93, 0xac, 0x5f, 0xf9, 0x87, 0xd4, 0x65, 0x22, 0x1e, 0x2c, 0x5f, 0xff,
- 0xb9, 0xb3, 0x75, 0x1f, 0xe7, 0x5a, 0xce, 0x93, 0xda, 0xc5, 0xff, 0xa4,
- 0xa1, 0xd4, 0xc0, 0x92, 0x50, 0x58, 0xa1, 0xaa, 0x2f, 0x72, 0x7d, 0x43,
- 0x10, 0xe5, 0x20, 0x3c, 0xf2, 0x00, 0x6b, 0x97, 0xff, 0xd9, 0xb7, 0x51,
- 0xe9, 0xf6, 0xf3, 0xe1, 0x6c, 0xb1, 0x7f, 0xf6, 0x7b, 0x9d, 0x7e, 0xe1,
- 0xb1, 0x1a, 0xb1, 0x52, 0x89, 0xc3, 0xaa, 0x5f, 0xde, 0x06, 0x04, 0xc2,
- 0x58, 0xbf, 0xe1, 0x49, 0x75, 0x7f, 0x4c, 0x4b, 0x17, 0x68, 0x1d, 0x4f,
- 0xa8, 0xe5, 0xf7, 0xdd, 0x30, 0x5b, 0xac, 0x5f, 0xff, 0xf3, 0x6b, 0xf9,
- 0xe7, 0xc2, 0xdb, 0x93, 0x84, 0x3f, 0xca, 0xc5, 0xb4, 0xb1, 0x7f, 0x60,
- 0x4f, 0x39, 0x6c, 0xb1, 0x77, 0xba, 0xec, 0x78, 0x44, 0x25, 0x7f, 0xff,
- 0xc0, 0xc8, 0xba, 0xfd, 0x9f, 0xd2, 0x52, 0x0c, 0x92, 0x02, 0xc5, 0xff,
- 0xf9, 0xf3, 0x5d, 0xc1, 0xbb, 0xd6, 0x3f, 0xe4, 0x6b, 0x15, 0x29, 0xf4,
- 0x61, 0x87, 0x64, 0xcd, 0x0a, 0x60, 0x18, 0x79, 0x9a, 0xff, 0xff, 0xdd,
- 0xe6, 0xc2, 0x09, 0xd7, 0xb8, 0x7a, 0x43, 0xeb, 0x9a, 0x00, 0x25, 0x62,
- 0xff, 0xb2, 0x28, 0xe1, 0x7b, 0x3b, 0xf2, 0xc5, 0xec, 0xd0, 0xd6, 0x2e,
- 0x98, 0x2c, 0x5f, 0xff, 0x73, 0xae, 0xa7, 0x7c, 0x28, 0xa1, 0x9e, 0xe2,
- 0xc5, 0x62, 0x31, 0xce, 0x7e, 0x01, 0xd1, 0x0b, 0xdf, 0xf9, 0x8b, 0x3f,
- 0x9e, 0xd6, 0x06, 0xb1, 0x7f, 0xff, 0xb9, 0x82, 0xd1, 0xbd, 0x7e, 0xf9,
- 0xee, 0x75, 0x2c, 0x1a, 0xc5, 0x6c, 0x8a, 0x4f, 0x1f, 0x5f, 0x8d, 0xeb,
- 0xd2, 0x01, 0x55, 0x8b, 0xff, 0xff, 0xe1, 0x1a, 0x42, 0xf4, 0x59, 0xe7,
- 0xee, 0x05, 0x25, 0x9f, 0x7c, 0xd4, 0x4b, 0x15, 0x28, 0xb2, 0xc3, 0x3a,
- 0xc4, 0x7b, 0xf7, 0x0d, 0x6b, 0xe0, 0xd8, 0x80, 0xb1, 0x7f, 0xd8, 0x1f,
- 0xe4, 0xdc, 0xf7, 0x16, 0x2f, 0xfe, 0x62, 0xd8, 0xe2, 0x71, 0xb9, 0x3a,
- 0xc5, 0x62, 0x28, 0x5c, 0x8c, 0x33, 0xbb, 0xee, 0xfd, 0xf7, 0x58, 0xbf,
- 0x77, 0x01, 0x4f, 0x96, 0x2b, 0x0f, 0x3a, 0x22, 0x4b, 0xfe, 0xdb, 0xf3,
- 0xd7, 0x9f, 0x18, 0xd6, 0x2f, 0xf7, 0x7f, 0xcf, 0x6b, 0x03, 0x58, 0xa7,
- 0x3f, 0x41, 0x1f, 0x5f, 0xff, 0xd0, 0x9d, 0x77, 0x0e, 0x75, 0xfc, 0xb9,
- 0x36, 0x8d, 0x58, 0xbf, 0xff, 0x64, 0x1f, 0xa1, 0x67, 0x3a, 0xe7, 0xdb,
- 0xb0, 0x2c, 0x5e, 0x2c, 0x82, 0xc5, 0xa1, 0xd4, 0xfd, 0x7c, 0xb3, 0x7f,
- 0xee, 0xc7, 0xf1, 0x37, 0x0b, 0x06, 0xb1, 0x58, 0x7d, 0x42, 0x2a, 0xbf,
- 0xfb, 0x66, 0x2e, 0xba, 0xd3, 0x9b, 0x84, 0xb1, 0x7f, 0xcd, 0xef, 0x64,
- 0x50, 0x7f, 0x2c, 0x5f, 0xd8, 0x69, 0xad, 0xee, 0x2c, 0x5f, 0x67, 0xdb,
- 0xcb, 0x17, 0x31, 0xfa, 0x9e, 0x91, 0x18, 0x54, 0xa2, 0xeb, 0xf0, 0x8c,
- 0xb8, 0x01, 0xac, 0x5f, 0x47, 0x66, 0xa5, 0x62, 0xb4, 0x6f, 0xba, 0x0c,
- 0xdf, 0xff, 0x1f, 0x9f, 0x92, 0xf6, 0xa7, 0xfb, 0xbf, 0x16, 0x2f, 0x3c,
- 0x9d, 0x62, 0xce, 0xb1, 0x71, 0x75, 0xd1, 0xad, 0xf0, 0xe5, 0x62, 0x33,
- 0xdc, 0x8d, 0x9f, 0xae, 0xc2, 0x58, 0xa9, 0x5c, 0x8e, 0xc8, 0x4b, 0x76,
- 0x43, 0xf8, 0xcf, 0x98, 0x87, 0x91, 0x80, 0xfa, 0x33, 0x41, 0x16, 0xdf,
- 0xfd, 0x9e, 0xe7, 0x5d, 0x63, 0xfe, 0x46, 0xb1, 0x7f, 0xdf, 0xfc, 0xf7,
- 0xd4, 0x33, 0xee, 0xb1, 0x7b, 0x76, 0x8f, 0x58, 0xbf, 0xb3, 0xda, 0xd6,
- 0x41, 0x62, 0x96, 0x2f, 0xd9, 0xf2, 0xcd, 0xd6, 0x28, 0x06, 0xd0, 0x83,
- 0x29, 0xd1, 0x47, 0x11, 0x0f, 0x98, 0xaf, 0x67, 0x7e, 0x58, 0xbf, 0xd8,
- 0x37, 0xe9, 0xe7, 0xd2, 0xc5, 0xd9, 0xce, 0xa8, 0x83, 0x8f, 0x30, 0x61,
- 0xea, 0x64, 0xe9, 0x4a, 0x36, 0x6b, 0xf8, 0xfd, 0x5f, 0x66, 0xf2, 0xc5,
- 0xfe, 0x3f, 0xe5, 0xf4, 0x28, 0xf5, 0x8a, 0x93, 0xe8, 0xc3, 0x1b, 0xf6,
- 0xe5, 0x3e, 0xe2, 0xc5, 0xff, 0xb2, 0x43, 0xfe, 0x79, 0xf3, 0x8b, 0x17,
- 0xe7, 0xd8, 0x98, 0xeb, 0x15, 0x28, 0x8f, 0xd1, 0x4f, 0x8f, 0xab, 0x66,
- 0xfc, 0x90, 0x71, 0xfb, 0x62, 0x09, 0xb1, 0xc4, 0xef, 0x2f, 0xbf, 0xb8,
- 0xfe, 0xde, 0x33, 0x68, 0xa1, 0x53, 0xa9, 0x5f, 0x27, 0x8c, 0x1f, 0xf2,
- 0x9d, 0x19, 0x6c, 0x11, 0x9f, 0x94, 0x7a, 0xfc, 0x86, 0x4f, 0xa7, 0x42,
- 0xc5, 0x08, 0x9e, 0x91, 0xf5, 0x99, 0x09, 0x00, 0x90, 0xaf, 0xbe, 0x14,
- 0x90, 0xd6, 0x2f, 0xfa, 0x4e, 0x58, 0x3d, 0x3e, 0xcb, 0x17, 0xff, 0xf8,
- 0x3f, 0x8a, 0x7b, 0xeb, 0xad, 0x4e, 0xc4, 0xcd, 0xa3, 0x56, 0x2f, 0xf1,
- 0x60, 0xb0, 0xd8, 0x01, 0x62, 0x99, 0x13, 0x61, 0xb3, 0xd4, 0x11, 0xef,
- 0x90, 0xd4, 0xbf, 0xfe, 0x9d, 0xba, 0xfe, 0x5f, 0xdc, 0x9d, 0xb3, 0x8b,
- 0x17, 0xff, 0x4e, 0xbc, 0xf8, 0x10, 0xe2, 0x92, 0x58, 0xbc, 0x6c, 0xe9,
- 0x62, 0xff, 0xfa, 0x7a, 0xfd, 0xba, 0x75, 0xc3, 0x9e, 0x74, 0x6a, 0xc5,
- 0xf8, 0x07, 0xcc, 0xf2, 0xc5, 0xfe, 0xeb, 0xac, 0xf9, 0x64, 0x4b, 0x17,
- 0xf8, 0xfd, 0x7c, 0x52, 0x7e, 0x2c, 0x56, 0x1f, 0x63, 0x9b, 0x56, 0x22,
- 0xd0, 0xa1, 0x29, 0x7f, 0xff, 0xbe, 0xc0, 0xe7, 0x52, 0xce, 0x85, 0x9c,
- 0xc3, 0xce, 0xeb, 0x17, 0xff, 0xff, 0xda, 0x11, 0xdf, 0x9d, 0x62, 0x80,
- 0x8b, 0xdd, 0x7f, 0x30, 0x72, 0xc3, 0xca, 0xc5, 0xb8, 0xb1, 0x7e, 0xf7,
- 0x5d, 0xfc, 0x75, 0x8a, 0x94, 0x60, 0xb4, 0x20, 0x84, 0x25, 0x5b, 0x2a,
- 0xec, 0x89, 0x17, 0xe3, 0xc5, 0x18, 0x5f, 0x09, 0xbd, 0x19, 0x2d, 0xf6,
- 0x1b, 0x30, 0x58, 0xbd, 0x25, 0xba, 0xc5, 0xc2, 0x3f, 0x53, 0xc0, 0x34,
- 0x8e, 0xe3, 0x5d, 0x62, 0xff, 0xff, 0x16, 0x0e, 0x7d, 0xce, 0xbe, 0x08,
- 0x53, 0xc1, 0x4f, 0x6b, 0x17, 0x61, 0xab, 0x16, 0xe7, 0x53, 0xfd, 0x96,
- 0x5b, 0xfe, 0xc1, 0x0f, 0xac, 0xf2, 0x60, 0xb1, 0x7c, 0x5e, 0x7f, 0xac,
- 0x57, 0x53, 0xdd, 0x63, 0xbb, 0xfb, 0xfd, 0x79, 0xf9, 0xed, 0x62, 0xfe,
- 0xcd, 0xe7, 0xae, 0x41, 0x62, 0xa4, 0xf8, 0xbe, 0x65, 0x40, 0x45, 0x37,
- 0xa1, 0x0b, 0x51, 0xbb, 0xab, 0xf4, 0x8d, 0x44, 0xf3, 0x29, 0xb3, 0x2d,
- 0x05, 0x26, 0xf1, 0xbf, 0x77, 0x18, 0xcb, 0x93, 0xb4, 0xb3, 0xf2, 0x85,
- 0x37, 0x0c, 0x7d, 0x09, 0x51, 0x46, 0x59, 0x7b, 0x69, 0x89, 0x62, 0xf3,
- 0x10, 0x16, 0x2f, 0xdf, 0x30, 0xbb, 0x02, 0xc5, 0xff, 0x75, 0x09, 0xec,
- 0xff, 0x9c, 0xeb, 0x17, 0xff, 0x6c, 0xde, 0xd6, 0x6c, 0xc5, 0xee, 0x2c,
- 0x56, 0xc8, 0xcb, 0xc1, 0xcd, 0xca, 0xdc, 0xfa, 0xff, 0x6b, 0x3f, 0xde,
- 0x0a, 0x25, 0x8b, 0xff, 0xfa, 0x1f, 0xc7, 0x87, 0x30, 0x85, 0xe2, 0xc0,
- 0x4a, 0xc5, 0x9d, 0x62, 0xda, 0xc3, 0xea, 0x02, 0xcd, 0xff, 0xf6, 0x7b,
- 0xf8, 0x31, 0x7b, 0x93, 0xc1, 0x71, 0x62, 0xfe, 0x9c, 0x2d, 0xcc, 0x3a,
- 0xc5, 0xfe, 0xf0, 0xa7, 0x36, 0x30, 0xeb, 0x17, 0xfe, 0xfc, 0x90, 0xa2,
- 0xce, 0x72, 0x56, 0x2d, 0x1f, 0xf4, 0x7a, 0xf9, 0x44, 0xc2, 0xf0, 0x86,
- 0xd7, 0xfd, 0xcf, 0x7e, 0x7d, 0xcf, 0xba, 0xc5, 0x75, 0x54, 0x7f, 0x30,
- 0xa0, 0x68, 0xc7, 0x04, 0x93, 0x71, 0xc6, 0xb1, 0x7e, 0xc2, 0xf0, 0x04,
- 0xb1, 0x7f, 0xf8, 0xf3, 0xbf, 0xb9, 0x80, 0x9c, 0xee, 0x0b, 0x17, 0xc6,
- 0xbe, 0xee, 0xb1, 0x74, 0xc3, 0x0f, 0xc3, 0xc9, 0x94, 0x16, 0xa8, 0xdc,
- 0xf8, 0xc1, 0x42, 0x62, 0xfb, 0x6c, 0x68, 0x96, 0x2f, 0xff, 0xfc, 0xfd,
- 0x0b, 0x39, 0xd7, 0xcf, 0xd7, 0x3d, 0x3b, 0xbf, 0x49, 0xfa, 0xc5, 0xff,
- 0xff, 0xdf, 0xc2, 0xdb, 0xae, 0xff, 0x17, 0xe7, 0x40, 0xfe, 0x78, 0xa7,
- 0x75, 0x8b, 0xfc, 0x39, 0x07, 0x5c, 0xef, 0xcb, 0x17, 0xff, 0xcd, 0xa6,
- 0xff, 0x70, 0xcf, 0x75, 0xdf, 0x91, 0xeb, 0x17, 0xf9, 0xbd, 0xc8, 0xa0,
- 0xff, 0x58, 0xbf, 0x9e, 0x0d, 0xef, 0xba, 0xc5, 0xff, 0xf3, 0x1c, 0x7f,
- 0x9d, 0x16, 0x0f, 0xec, 0x1a, 0xc5, 0x0d, 0x34, 0x1d, 0xcd, 0xc9, 0x63,
- 0xc6, 0xbd, 0x0b, 0x6f, 0xb3, 0xb8, 0x71, 0x62, 0xfd, 0x1e, 0x32, 0xcf,
- 0xac, 0x57, 0xcf, 0x3d, 0x89, 0x2f, 0xfa, 0x77, 0xeb, 0x1a, 0x1b, 0xf7,
- 0x3a, 0xc5, 0xf1, 0x1d, 0xfc, 0xb1, 0x71, 0xf8, 0xb1, 0x79, 0xb8, 0xeb,
- 0x17, 0xf7, 0xbf, 0x9d, 0x07, 0x2b, 0x15, 0x27, 0xc8, 0x01, 0x81, 0x0e,
- 0x5f, 0xf1, 0x9b, 0x61, 0x31, 0xdb, 0xeb, 0x17, 0xcf, 0xa2, 0x65, 0x8a,
- 0xd9, 0x71, 0x7a, 0x04, 0x83, 0x73, 0x78, 0xee, 0x22, 0x84, 0xe1, 0xc8,
- 0x59, 0x0c, 0xa1, 0x0d, 0xe2, 0xee, 0x87, 0x57, 0x8d, 0x60, 0xd6, 0x2f,
- 0xfd, 0xf7, 0xef, 0xda, 0x9f, 0x3f, 0x45, 0x8b, 0xfd, 0xce, 0x4b, 0xec,
- 0xde, 0x58, 0xbf, 0xee, 0x30, 0x61, 0x1f, 0x08, 0x6b, 0x17, 0xf6, 0x7b,
- 0x18, 0xa2, 0x58, 0xbe, 0xce, 0x4e, 0x96, 0x2c, 0x6f, 0xcf, 0x3c, 0x8b,
- 0x6d, 0x09, 0x47, 0x36, 0x1a, 0x0a, 0x11, 0x56, 0x82, 0xc5, 0xe1, 0x88,
- 0x0b, 0x17, 0xff, 0xf4, 0xc7, 0xf5, 0x7c, 0x2c, 0xfb, 0xe1, 0x77, 0x0e,
- 0x2c, 0x5f, 0xe0, 0x8f, 0x9d, 0xfd, 0xf1, 0x62, 0xc5, 0xda, 0x24, 0xc0,
- 0xbd, 0x7f, 0x67, 0xb9, 0xf7, 0x35, 0x62, 0xfb, 0x9f, 0x73, 0x56, 0x2f,
- 0xdb, 0x66, 0x8b, 0x08, 0xf4, 0xfc, 0x5f, 0x78, 0xec, 0x35, 0x8b, 0xfa,
- 0x10, 0x7e, 0x08, 0xeb, 0x15, 0x27, 0x99, 0xd8, 0xed, 0xfe, 0x21, 0x43,
- 0x22, 0x98, 0xf5, 0x8a, 0x95, 0x44, 0x23, 0x12, 0xc8, 0x58, 0xfd, 0xf0,
- 0xa1, 0x13, 0xe2, 0x2b, 0x05, 0x16, 0x2f, 0x6e, 0xe7, 0x58, 0xbf, 0x7f,
- 0x3d, 0x23, 0x58, 0xb9, 0xb4, 0xb1, 0x58, 0x7b, 0xb1, 0x0f, 0x78, 0xa2,
- 0xf1, 0x92, 0x4b, 0x17, 0x89, 0xa0, 0xb1, 0x7e, 0xc3, 0x71, 0xe2, 0x58,
- 0xbd, 0x9f, 0xeb, 0x87, 0x8a, 0x43, 0x97, 0x49, 0x2c, 0x5c, 0xc1, 0xf5,
- 0x45, 0x5f, 0x98, 0x8c, 0x33, 0xac, 0x4c, 0x64, 0xa1, 0xb5, 0x7f, 0xfb,
- 0x07, 0xd4, 0x4c, 0x67, 0x84, 0xdb, 0x4a, 0xc5, 0xf4, 0x9f, 0x87, 0x58,
- 0xbf, 0x37, 0xba, 0xee, 0x1a, 0xc5, 0xff, 0xb0, 0xdf, 0xe7, 0xb8, 0x53,
- 0x05, 0x8a, 0x94, 0x6e, 0xba, 0x73, 0x11, 0x88, 0xb6, 0xfb, 0x6f, 0x3e,
- 0xcb, 0x17, 0xef, 0x31, 0xdf, 0xcb, 0x15, 0x87, 0x9a, 0x44, 0xb7, 0x86,
- 0xe3, 0x58, 0xbf, 0xff, 0xf0, 0xa7, 0x5d, 0x67, 0xf2, 0x3e, 0xbe, 0x7c,
- 0x09, 0xdc, 0x1b, 0xb5, 0x8b, 0xc0, 0x68, 0xf5, 0x8b, 0xf7, 0x0a, 0x62,
- 0xf2, 0xc5, 0x0d, 0x1b, 0x44, 0x3b, 0xc7, 0x4f, 0x10, 0x5f, 0xff, 0xde,
- 0x16, 0x9b, 0x9e, 0x7e, 0xbf, 0xcd, 0x98, 0xb7, 0x58, 0xb0, 0x5a, 0xac,
- 0x53, 0x9f, 0xc7, 0x17, 0xed, 0x05, 0x8a, 0x94, 0xf8, 0x72, 0x1f, 0x4d,
- 0x0b, 0x4f, 0x10, 0xdf, 0xfc, 0x6c, 0x96, 0xfd, 0x5f, 0x5a, 0x70, 0xd6,
- 0x2f, 0xbe, 0xe0, 0x0d, 0x62, 0xf1, 0x6f, 0x2b, 0x17, 0xff, 0x8a, 0x7b,
- 0xe3, 0x68, 0xf3, 0xdc, 0x38, 0xb1, 0x7f, 0xff, 0xfb, 0x3d, 0xc6, 0x8b,
- 0xa9, 0x67, 0x70, 0xc1, 0x6c, 0x58, 0x3f, 0xbc, 0x4b, 0x14, 0x74, 0x64,
- 0x7d, 0x32, 0xe2, 0xf2, 0xc5, 0xff, 0xee, 0x4c, 0x3d, 0x9f, 0x2c, 0xf7,
- 0xdd, 0x62, 0xa4, 0xf8, 0x1c, 0x5e, 0xe1, 0x1a, 0xb1, 0x5d, 0x55, 0x07,
- 0x1a, 0x92, 0xe4, 0x9a, 0x87, 0x2f, 0xe1, 0x07, 0xe2, 0x0b, 0xc7, 0xfb,
- 0x2c, 0x5e, 0xea, 0x61, 0xd6, 0x2f, 0xd2, 0x30, 0x92, 0x75, 0x8b, 0xfe,
- 0xf7, 0x3a, 0x99, 0xff, 0x88, 0xd5, 0x8b, 0xff, 0x02, 0x2f, 0xb8, 0x09,
- 0xbb, 0x82, 0xc5, 0x2c, 0x53, 0x1e, 0x6f, 0x10, 0x6b, 0xaa, 0x36, 0x24,
- 0xab, 0x21, 0x1b, 0x7b, 0xe6, 0xf9, 0x62, 0xfd, 0xef, 0x7b, 0x03, 0x58,
- 0xa9, 0x3c, 0x97, 0x1f, 0xa9, 0x4e, 0xd3, 0xb1, 0xd3, 0xc3, 0xe4, 0x0f,
- 0xd7, 0x8f, 0x3b, 0xac, 0x5d, 0xac, 0x58, 0xbd, 0x8e, 0x35, 0x8b, 0x71,
- 0x62, 0xe2, 0xcd, 0xcd, 0x77, 0x63, 0x97, 0xfe, 0xfc, 0x97, 0x5d, 0x49,
- 0x8c, 0x4b, 0x17, 0x9f, 0x09, 0x62, 0xe9, 0x89, 0x62, 0xfd, 0x3a, 0xd3,
- 0x47, 0xac, 0x53, 0x9e, 0x18, 0x86, 0x2f, 0xfe, 0xc0, 0x75, 0xfb, 0xfb,
- 0x84, 0xf1, 0x2c, 0x5f, 0xf8, 0xb3, 0x9d, 0x78, 0x03, 0xe7, 0x16, 0x2b,
- 0x64, 0xdd, 0x37, 0x2d, 0x3a, 0x07, 0x17, 0xbc, 0x43, 0xd1, 0x1e, 0xcc,
- 0xb1, 0x7f, 0xf4, 0x41, 0x3f, 0x9e, 0xc0, 0x1d, 0xa2, 0x58, 0xa8, 0xd1,
- 0x54, 0x6c, 0x8f, 0x64, 0x77, 0x24, 0xb8, 0x21, 0x1b, 0xff, 0xf7, 0x5e,
- 0xe1, 0x3f, 0xeb, 0xfc, 0xf7, 0xa7, 0x40, 0x58, 0xbf, 0xf7, 0x3f, 0x9b,
- 0x4f, 0x64, 0xe1, 0xac, 0x51, 0xd1, 0x3a, 0x05, 0xcb, 0xfc, 0xc4, 0x0e,
- 0xa1, 0xe7, 0xd6, 0x2f, 0xfc, 0x08, 0xec, 0xfb, 0xc9, 0xd8, 0x6b, 0x15,
- 0x03, 0xf7, 0x23, 0x6b, 0xfb, 0x59, 0x02, 0x93, 0xac, 0x5f, 0xb2, 0x05,
- 0x27, 0x58, 0xb8, 0x81, 0xd4, 0xf5, 0x34, 0x5b, 0x7f, 0xff, 0xfe, 0x87,
- 0x38, 0x29, 0xf3, 0x8f, 0x0a, 0x2e, 0xa5, 0x9a, 0x92, 0xf7, 0xf0, 0x22,
- 0xc5, 0xff, 0xa7, 0x1f, 0xdf, 0x92, 0x9d, 0xd6, 0x2f, 0xe3, 0xf7, 0x3f,
- 0xfc, 0xac, 0x5e, 0xee, 0x1c, 0xd8, 0xfb, 0x30, 0xf6, 0xb1, 0x35, 0x6e,
- 0xcb, 0xf5, 0x0f, 0x2b, 0x71, 0x62, 0xa5, 0x55, 0x6e, 0x42, 0x68, 0x51,
- 0xe5, 0x98, 0x6d, 0x7f, 0x31, 0x03, 0xa9, 0xb1, 0xeb, 0x17, 0xbe, 0xf0,
- 0x58, 0xb6, 0x47, 0x9e, 0x8f, 0x0d, 0x2d, 0xb2, 0xc5, 0xf4, 0xfb, 0x00,
- 0xb1, 0x4b, 0x15, 0xb1, 0xae, 0x0b, 0x91, 0x5f, 0xc3, 0x62, 0x83, 0x9d,
- 0x62, 0xff, 0xec, 0x87, 0xda, 0x13, 0xed, 0x60, 0xd6, 0x2f, 0xda, 0xce,
- 0xe1, 0xc5, 0x8b, 0xf7, 0xda, 0x1f, 0x75, 0x8b, 0xdb, 0xff, 0x16, 0x2b,
- 0x63, 0xf0, 0x81, 0x56, 0x8a, 0x2f, 0xe0, 0x73, 0xa8, 0x39, 0xa5, 0x8a,
- 0xc3, 0xe2, 0x63, 0x0b, 0xfe, 0xee, 0x75, 0xb7, 0x5c, 0x71, 0xac, 0x5d,
- 0x13, 0xac, 0x5f, 0xfd, 0x9e, 0xeb, 0x90, 0xfe, 0x3c, 0x38, 0xb1, 0x50,
- 0x55, 0x1f, 0x85, 0x4e, 0x82, 0xc4, 0xc0, 0x2d, 0x28, 0xc5, 0x84, 0x41,
- 0xd0, 0xf6, 0x38, 0x62, 0xfb, 0xf1, 0xa6, 0xf1, 0xcb, 0x17, 0xff, 0xb3,
- 0x52, 0xe3, 0xc3, 0xf5, 0xe4, 0x8d, 0x62, 0xfd, 0xdc, 0x24, 0x12, 0xb1,
- 0x7f, 0xec, 0xf7, 0xb1, 0xfa, 0x16, 0x71, 0x62, 0xba, 0xa2, 0xcf, 0x12,
- 0xfe, 0x53, 0x7e, 0x2c, 0xfb, 0x79, 0x62, 0xbb, 0x3d, 0x83, 0x98, 0xdf,
- 0x6b, 0x22, 0x95, 0x8b, 0xfe, 0x78, 0xe9, 0x3f, 0x3f, 0x87, 0x58, 0xbe,
- 0x7e, 0x99, 0xa5, 0x8a, 0x0a, 0x27, 0xbd, 0x31, 0x9c, 0x39, 0x19, 0xc8,
- 0xfe, 0x79, 0x7d, 0xd7, 0x7d, 0x83, 0x58, 0xbf, 0x8b, 0x00, 0x79, 0x82,
- 0xc5, 0xf8, 0xb3, 0xdf, 0x75, 0x8a, 0x19, 0xea, 0x06, 0x5b, 0x7e, 0xdb,
- 0xa8, 0xa6, 0x25, 0x8b, 0xb8, 0x75, 0x8b, 0xff, 0xfe, 0x29, 0x07, 0x70,
- 0xe0, 0xa7, 0xc5, 0x83, 0x7c, 0xd4, 0x4b, 0x15, 0x28, 0xcf, 0x62, 0x3e,
- 0x16, 0xf8, 0x62, 0xba, 0xba, 0x4f, 0xf9, 0x87, 0x56, 0xd2, 0x9f, 0x07,
- 0x19, 0x36, 0x4e, 0x4c, 0x9b, 0x09, 0xfd, 0xc7, 0xfb, 0x8c, 0xa1, 0xe5,
- 0x2d, 0x47, 0xb0, 0x45, 0x1c, 0x66, 0xa3, 0x04, 0xfc, 0xa6, 0x86, 0x94,
- 0xa6, 0x09, 0x43, 0x25, 0x2b, 0x43, 0x92, 0xe7, 0xbd, 0x2c, 0xa4, 0x52,
- 0x99, 0x7a, 0x29, 0x99, 0x1a, 0x65, 0xf6, 0x44, 0x21, 0xac, 0x5f, 0xa0,
- 0xfa, 0xce, 0xd6, 0x2f, 0x73, 0xf8, 0xb1, 0x7e, 0xce, 0x6d, 0x81, 0xac,
- 0x5f, 0xfd, 0xf1, 0x0f, 0xe2, 0xf7, 0x3e, 0x28, 0x96, 0x2f, 0xb8, 0x29,
- 0xd2, 0xc5, 0x6e, 0x98, 0x07, 0x64, 0x91, 0x14, 0xfc, 0x74, 0x8a, 0xb8,
- 0x93, 0x78, 0xbd, 0xc5, 0x8b, 0xff, 0xcf, 0xa7, 0xce, 0xfa, 0xfa, 0x22,
- 0x93, 0xac, 0x5f, 0xfd, 0x8d, 0xdf, 0x51, 0xce, 0xdd, 0x4d, 0x35, 0x62,
- 0xb7, 0x44, 0xd7, 0x69, 0xb7, 0xf4, 0x9c, 0xb3, 0x6c, 0x58, 0xbd, 0xee,
- 0x7f, 0x0f, 0x4b, 0xe4, 0xb7, 0xff, 0xe3, 0xf7, 0x0e, 0x6b, 0xb9, 0xf7,
- 0x27, 0xef, 0xe5, 0x8b, 0xfe, 0xc3, 0x4b, 0x3d, 0xf7, 0x0d, 0x62, 0xfd,
- 0x81, 0xe0, 0xce, 0xb1, 0x7f, 0x7f, 0x39, 0x3a, 0xdd, 0x62, 0xfe, 0x86,
- 0x75, 0x7d, 0x09, 0x62, 0xff, 0x9f, 0x08, 0x6f, 0xd2, 0x46, 0xb1, 0x74,
- 0xf7, 0xd5, 0x13, 0x11, 0x17, 0xfc, 0xc2, 0xa5, 0x3c, 0x67, 0x33, 0xd2,
- 0xcf, 0xce, 0x8a, 0x18, 0x37, 0x47, 0x8d, 0x62, 0xff, 0xef, 0x3e, 0xa7,
- 0x0b, 0xdc, 0xc2, 0x58, 0xbf, 0xfe, 0xdb, 0x37, 0x1f, 0xdf, 0x0d, 0xea,
- 0x68, 0xa5, 0x62, 0xfe, 0xcd, 0x6b, 0x3d, 0xc5, 0x8b, 0xf8, 0x98, 0xd3,
- 0xb4, 0x16, 0x2f, 0x41, 0xfd, 0xf3, 0xdc, 0xf1, 0x75, 0xb6, 0x58, 0xbf,
- 0x61, 0xcb, 0x3b, 0x58, 0xbf, 0xbc, 0xfd, 0x24, 0xb7, 0x58, 0xae, 0x1e,
- 0xc1, 0x85, 0x17, 0x7f, 0x16, 0x2f, 0xe3, 0xce, 0xfd, 0x78, 0x6a, 0xc5,
- 0xfa, 0x0e, 0x40, 0xe2, 0xc5, 0xfa, 0x4e, 0xff, 0x95, 0x8b, 0xc4, 0x67,
- 0xd6, 0x2f, 0xf6, 0x7b, 0xef, 0xec, 0xdd, 0x62, 0xe7, 0xed, 0x62, 0xfa,
- 0x70, 0xb7, 0x58, 0xae, 0xa9, 0xa4, 0x40, 0x8f, 0x05, 0xe2, 0x33, 0xd1,
- 0x43, 0x13, 0x90, 0xf7, 0x0d, 0x3c, 0x31, 0x7e, 0x06, 0x0d, 0xa0, 0xb1,
- 0x7f, 0xfa, 0x64, 0xfd, 0x47, 0xf9, 0xeb, 0xf9, 0x8f, 0x58, 0xa8, 0xd9,
- 0x5f, 0x6c, 0x8d, 0xba, 0x14, 0x50, 0xb2, 0x39, 0x9f, 0xe3, 0xb3, 0x67,
- 0xf2, 0x28, 0xbf, 0xff, 0xda, 0xce, 0x66, 0xf9, 0xa9, 0xf3, 0xee, 0xe3,
- 0x8a, 0x56, 0x2f, 0xe6, 0xd8, 0x21, 0x67, 0x6b, 0x17, 0x43, 0x9a, 0x44,
- 0x9f, 0x98, 0xaf, 0xef, 0xcc, 0x04, 0xc6, 0x2c, 0x5f, 0x87, 0xfc, 0x2f,
- 0x2c, 0x54, 0x0f, 0x5e, 0x22, 0xfa, 0xed, 0x15, 0x25, 0x08, 0x6b, 0xfe,
- 0xd3, 0xe0, 0x7e, 0xf3, 0x12, 0xc5, 0xdd, 0x9a, 0xb1, 0x73, 0xf7, 0xd4,
- 0xf4, 0xc6, 0x73, 0x79, 0xc1, 0x8b, 0x17, 0xd1, 0x33, 0x41, 0x62, 0xe6,
- 0x1a, 0xc5, 0x39, 0xba, 0x01, 0x1d, 0xb9, 0x03, 0xf6, 0xc5, 0x6b, 0xff,
- 0xd8, 0x18, 0x4f, 0xe7, 0xb0, 0x07, 0x68, 0x96, 0x2f, 0xd9, 0x3a, 0x80,
- 0x16, 0x2a, 0x53, 0xbe, 0xd3, 0xdb, 0x42, 0x98, 0x89, 0xc4, 0x9d, 0x7f,
- 0xe6, 0xe8, 0x59, 0xec, 0x01, 0x0d, 0x62, 0xc0, 0x58, 0xa7, 0x3d, 0x18,
- 0x8f, 0xef, 0xfb, 0xfb, 0x3e, 0x17, 0x70, 0xe2, 0xc5, 0xff, 0x7e, 0x2f,
- 0xe7, 0x70, 0xc2, 0x58, 0xbf, 0xdf, 0xcd, 0xcb, 0x05, 0x1e, 0xb1, 0x52,
- 0x7e, 0x5d, 0x9d, 0xdf, 0xee, 0xbc, 0xc2, 0x9d, 0x44, 0xb1, 0x7b, 0xbc,
- 0xdd, 0x62, 0xff, 0xf6, 0x6f, 0xcc, 0xf4, 0x58, 0x69, 0x60, 0x16, 0x2b,
- 0x48, 0xa1, 0xe1, 0xb0, 0x63, 0xf7, 0xff, 0xfd, 0x86, 0xf5, 0xc3, 0x74,
- 0xfd, 0x96, 0x78, 0x40, 0x3b, 0x41, 0x62, 0xa5, 0x50, 0x66, 0x42, 0xb5,
- 0xe1, 0x86, 0x23, 0x1b, 0xfc, 0xfa, 0x1b, 0xc0, 0x5a, 0x58, 0xa8, 0x1f,
- 0xd6, 0xe8, 0xd4, 0xb1, 0x7f, 0x4e, 0xbc, 0xf9, 0xda, 0xc5, 0xff, 0x48,
- 0xb7, 0xef, 0xcf, 0x84, 0xb1, 0x5f, 0x3e, 0x82, 0x2e, 0xbe, 0x84, 0x83,
- 0x8b, 0x17, 0xf3, 0xf6, 0x0d, 0x30, 0xd6, 0x2f, 0x66, 0x80, 0xb1, 0x7e,
- 0xe3, 0xe1, 0x01, 0x62, 0xd8, 0xe7, 0x89, 0xc1, 0xdb, 0xf3, 0x80, 0x19,
- 0xa5, 0x8b, 0xe1, 0xfe, 0x60, 0xb1, 0x51, 0xb2, 0x73, 0x83, 0x74, 0xc2,
- 0x1f, 0x91, 0x93, 0x9f, 0x09, 0x8c, 0x28, 0xb0, 0x51, 0x62, 0xf4, 0x6b,
- 0x8d, 0xe3, 0x65, 0x8b, 0xf3, 0x61, 0x39, 0xab, 0x17, 0xbd, 0x9f, 0x58,
- 0xa0, 0xb0, 0xfc, 0x88, 0xb8, 0x21, 0x3d, 0xf6, 0x67, 0xf8, 0xb1, 0x7f,
- 0xff, 0xff, 0xcf, 0xbf, 0xf2, 0x7b, 0xda, 0x71, 0xfb, 0x04, 0x96, 0xed,
- 0xf2, 0x60, 0x75, 0xdf, 0xbe, 0x2c, 0x5f, 0xff, 0x4e, 0xde, 0xee, 0x02,
- 0x23, 0x7a, 0xbf, 0x47, 0x58, 0xad, 0xd1, 0xe2, 0x50, 0x9a, 0xb9, 0xce,
- 0xb1, 0x7d, 0xd7, 0xb1, 0x12, 0xc5, 0xfe, 0xc0, 0xfa, 0xc8, 0x24, 0x0b,
- 0x17, 0xff, 0xfd, 0x06, 0xef, 0xa9, 0x08, 0x27, 0x5c, 0xee, 0x18, 0x22,
- 0x07, 0x16, 0x2f, 0x1d, 0x8e, 0xb1, 0x5b, 0x23, 0x0b, 0xb3, 0x66, 0x6f,
- 0xa8, 0x93, 0x58, 0x39, 0x47, 0x41, 0x70, 0x90, 0xe8, 0xbf, 0xe8, 0xdb,
- 0xde, 0x72, 0xee, 0x1c, 0x58, 0xbe, 0x8f, 0xfe, 0x47, 0xac, 0x5e, 0x8e,
- 0x70, 0xba, 0xc5, 0x75, 0x5c, 0x66, 0x8d, 0x9a, 0x76, 0x84, 0x40, 0xcd,
- 0x72, 0x53, 0x59, 0xa9, 0x0c, 0x81, 0x1c, 0x53, 0x7f, 0xf8, 0xa4, 0xfd,
- 0x7f, 0x9d, 0xfb, 0x1a, 0x25, 0x8b, 0xff, 0xff, 0xee, 0xf8, 0x29, 0xef,
- 0xaf, 0xf0, 0x7d, 0x4b, 0x04, 0x6f, 0x5e, 0x00, 0x0f, 0xe5, 0x8b, 0xff,
- 0xff, 0x60, 0xce, 0x79, 0xf7, 0x33, 0xdc, 0xd3, 0xe6, 0xe5, 0x83, 0x58,
- 0xbf, 0xfd, 0xe1, 0x4e, 0x6d, 0xd7, 0x8e, 0x4f, 0xa5, 0x8b, 0x06, 0x48,
- 0xb8, 0x31, 0xb2, 0xa5, 0x36, 0xac, 0x8d, 0x02, 0xfd, 0x25, 0xdb, 0x6c,
- 0xb1, 0x7f, 0x3e, 0xb3, 0xcd, 0xda, 0xc5, 0xfd, 0x13, 0x8f, 0x0e, 0xeb,
- 0x17, 0xff, 0xff, 0xfd, 0xbc, 0xfe, 0x4f, 0xec, 0xe7, 0x27, 0x5a, 0x92,
- 0xcd, 0xb0, 0x5c, 0x14, 0x45, 0x27, 0x58, 0xbf, 0xff, 0xf3, 0xcf, 0x8b,
- 0x3d, 0xfc, 0xeb, 0xdf, 0x1c, 0xdc, 0xf8, 0xbc, 0xb1, 0x52, 0x99, 0x96,
- 0x17, 0x7e, 0x12, 0xb7, 0x85, 0xa3, 0x56, 0x28, 0x69, 0xd9, 0x9e, 0x36,
- 0x08, 0xe3, 0x4b, 0xf3, 0x00, 0xc6, 0xd9, 0x62, 0xff, 0xff, 0xed, 0xba,
- 0xfb, 0x67, 0xcd, 0x6d, 0xd6, 0x28, 0x3f, 0xf0, 0x7d, 0xe0, 0x45, 0x8a,
- 0xc4, 0x71, 0x39, 0xd0, 0x8a, 0xaf, 0x38, 0x25, 0x62, 0xff, 0x75, 0x2c,
- 0xd3, 0xc9, 0xd6, 0x2f, 0xfd, 0xa6, 0xf6, 0xb1, 0xff, 0x23, 0x58, 0xbf,
- 0x86, 0x59, 0xf6, 0xf2, 0xc5, 0xfb, 0xdd, 0xc1, 0xf4, 0xb1, 0x58, 0x7a,
- 0xfc, 0x2d, 0xad, 0x93, 0x06, 0x18, 0xe6, 0x8d, 0x01, 0x09, 0x5b, 0xd2,
- 0x39, 0x58, 0xbf, 0x83, 0x8a, 0x05, 0x20, 0x58, 0xbd, 0xa6, 0x31, 0x62,
- 0xfd, 0x3e, 0x3b, 0xf9, 0x62, 0x98, 0xf1, 0x84, 0x3d, 0x7f, 0xe1, 0x4e,
- 0xdd, 0x64, 0xa7, 0x50, 0x58, 0xbe, 0x2e, 0xf0, 0xeb, 0x15, 0xb2, 0x21,
- 0x4e, 0x42, 0x1a, 0x0d, 0xff, 0xa4, 0xd0, 0x82, 0xc2, 0x88, 0xc3, 0xac,
- 0x5f, 0xf0, 0x79, 0xa1, 0xbe, 0x7b, 0x8b, 0x17, 0xff, 0x85, 0xce, 0xbf,
- 0x67, 0x27, 0xd4, 0x23, 0x96, 0x2f, 0x7a, 0x49, 0x62, 0xef, 0x1d, 0x62,
- 0xb0, 0xda, 0x6e, 0x39, 0x7f, 0xf7, 0xfb, 0x87, 0x3a, 0x96, 0x1f, 0x42,
- 0x58, 0xb6, 0x75, 0x3e, 0xac, 0x21, 0xb0, 0x00, 0x98, 0xaf, 0x21, 0xdb,
- 0x7f, 0xff, 0xf9, 0xf0, 0x9b, 0xdf, 0x98, 0xba, 0x96, 0x7d, 0xfd, 0xc1,
- 0x6e, 0x29, 0x58, 0xbc, 0x09, 0x3a, 0xc5, 0xe3, 0x4b, 0x3a, 0xa2, 0x5a,
- 0x36, 0x79, 0xa9, 0x57, 0x81, 0x90, 0xfb, 0xec, 0xc9, 0xd1, 0x1a, 0x34,
- 0xf1, 0x43, 0x16, 0xff, 0xf8, 0x41, 0x7e, 0xb3, 0xf7, 0xf7, 0x1c, 0xbb,
- 0x82, 0xc5, 0xff, 0xe6, 0x37, 0x08, 0x5e, 0xfe, 0x74, 0x1c, 0xac, 0x5f,
- 0xfd, 0x9e, 0xc7, 0xdb, 0x37, 0x78, 0xb8, 0xb1, 0x70, 0x54, 0x28, 0xb1,
- 0x7f, 0xec, 0xc0, 0x73, 0xae, 0xb8, 0x3e, 0x2c, 0x5f, 0xed, 0x66, 0xff,
- 0x7d, 0x44, 0xb1, 0x7f, 0x67, 0x32, 0x48, 0xd5, 0x8a, 0xea, 0x98, 0x5c,
- 0x68, 0x8c, 0x32, 0x0c, 0x42, 0xf9, 0xb5, 0xff, 0xf7, 0xdf, 0xae, 0x45,
- 0xdc, 0x39, 0xef, 0xe7, 0x6b, 0x17, 0xff, 0xf0, 0xc9, 0xbf, 0xfe, 0xe4,
- 0x21, 0x49, 0xfa, 0x9c, 0x2e, 0xb1, 0x44, 0xa9, 0x8b, 0xd1, 0xab, 0xf4,
- 0x51, 0x0d, 0x5a, 0xfb, 0xda, 0x11, 0xd6, 0x2f, 0xff, 0xf6, 0x1c, 0xef,
- 0xdf, 0x53, 0x4d, 0xc2, 0xf1, 0xa2, 0x9d, 0x2c, 0x5b, 0x77, 0x44, 0x5e,
- 0x89, 0x2f, 0xff, 0x4f, 0xc8, 0x4d, 0x1f, 0xd7, 0xb8, 0x49, 0xab, 0x15,
- 0x87, 0xf5, 0xa2, 0x9b, 0xff, 0x0a, 0x2e, 0xbe, 0xe3, 0xf5, 0x91, 0xac,
- 0x5e, 0x90, 0x71, 0x62, 0xe9, 0x0d, 0x62, 0xa0, 0x6d, 0x48, 0x76, 0xec,
- 0x8e, 0x58, 0xbf, 0xdd, 0x7f, 0x2f, 0xb6, 0x0d, 0x62, 0xdd, 0xe1, 0xf8,
- 0x11, 0x07, 0x41, 0xaa, 0x95, 0xd4, 0x6c, 0x95, 0x72, 0xf1, 0xa6, 0x7c,
- 0x85, 0xa1, 0xd5, 0x7f, 0x3f, 0xdc, 0xec, 0x35, 0x8a, 0x58, 0xb8, 0x81,
- 0x03, 0x72, 0x32, 0xdb, 0xe6, 0xe8, 0xfa, 0x58, 0xbd, 0x02, 0x75, 0x8a,
- 0xd1, 0xe0, 0x1c, 0x92, 0xa5, 0x11, 0xd8, 0xd9, 0x7f, 0x7d, 0x8b, 0xd8,
- 0x75, 0x8b, 0xce, 0x5e, 0x58, 0xbf, 0xa1, 0xc6, 0x38, 0xb8, 0xb1, 0x70,
- 0x19, 0x62, 0xff, 0xff, 0xde, 0xe7, 0xdf, 0xa9, 0x60, 0xa7, 0xbf, 0xe0,
- 0x1b, 0xb8, 0x71, 0x62, 0xa5, 0x10, 0xee, 0x2f, 0x52, 0x99, 0x06, 0xc5,
- 0xac, 0x39, 0xe8, 0x5b, 0x5c, 0xd0, 0x58, 0xb3, 0xac, 0x5d, 0x9f, 0xf9,
- 0xa8, 0x8e, 0x17, 0xbd, 0x24, 0x6a, 0xc5, 0xfe, 0x8f, 0xeb, 0x81, 0x3f,
- 0x3e, 0x58, 0xbe, 0xd6, 0xd9, 0xba, 0xc5, 0x61, 0xf0, 0x39, 0xdd, 0x7d,
- 0x13, 0xbe, 0x7d, 0xa9, 0x75, 0x05, 0x7b, 0x2d, 0x0e, 0x56, 0x7e, 0x4e,
- 0x1d, 0x1b, 0x2d, 0xeb, 0x78, 0x4f, 0x77, 0x2a, 0xa1, 0xe7, 0x89, 0x62,
- 0x84, 0x56, 0xa3, 0xb7, 0x39, 0x47, 0xe5, 0x5f, 0x34, 0x66, 0x80, 0x44,
- 0x29, 0x7b, 0x9c, 0x9d, 0xac, 0xf4, 0x64, 0x42, 0x8d, 0x06, 0x39, 0xa8,
- 0x24, 0x33, 0x2f, 0xd9, 0xee, 0x37, 0x6b, 0x17, 0xfc, 0x58, 0x18, 0x40,
- 0x9e, 0xcf, 0xac, 0x5f, 0xe2, 0x63, 0x73, 0x08, 0xd5, 0x8b, 0xb7, 0xc5,
- 0x8a, 0x1a, 0x2c, 0xb7, 0x29, 0x39, 0xf3, 0x19, 0xd2, 0xc5, 0xff, 0xdd,
- 0x72, 0x2e, 0xe1, 0xcf, 0x7f, 0x3b, 0x58, 0xbf, 0xe7, 0xce, 0xcb, 0xaf,
- 0x30, 0x96, 0x2f, 0x7d, 0xf4, 0xb1, 0x5f, 0x3d, 0x70, 0x87, 0x57, 0xfa,
- 0x12, 0x3e, 0xa3, 0x78, 0x96, 0x2f, 0xfb, 0xaf, 0x8b, 0x03, 0xc7, 0xe2,
- 0xc5, 0xff, 0xb0, 0xd9, 0x2d, 0xfa, 0xf4, 0xe0, 0x6b, 0x17, 0xff, 0xfe,
- 0xf3, 0x44, 0x59, 0xb3, 0x75, 0x2e, 0xf0, 0x32, 0xc1, 0x61, 0xab, 0x15,
- 0x1b, 0xa7, 0xf5, 0xb0, 0x66, 0xf0, 0xa2, 0xec, 0x92, 0x23, 0x7f, 0x9d,
- 0x84, 0x46, 0xba, 0x7c, 0xb1, 0x7b, 0xf2, 0x05, 0x8b, 0xfd, 0xf7, 0x04,
- 0xf9, 0xfa, 0x2c, 0x5f, 0xa1, 0xcf, 0x4e, 0xcb, 0x17, 0xd0, 0xe0, 0xa2,
- 0x58, 0xbf, 0x3c, 0x87, 0x31, 0x2c, 0x57, 0x67, 0x9c, 0xe4, 0xb7, 0x8a,
- 0x40, 0xb1, 0x7d, 0xe6, 0x20, 0x2c, 0x5f, 0xff, 0x98, 0xd3, 0x40, 0xd1,
- 0x04, 0x29, 0x0f, 0xb8, 0x71, 0x62, 0x98, 0xff, 0xc8, 0x8a, 0xbc, 0x8b,
- 0xb3, 0x21, 0x37, 0x7a, 0x1d, 0x42, 0xab, 0x17, 0x8d, 0xce, 0x2c, 0x5e,
- 0x16, 0x0d, 0x62, 0xe2, 0x89, 0x62, 0xf9, 0xa3, 0xe4, 0x0b, 0x15, 0x1b,
- 0x2e, 0x97, 0xcc, 0xa3, 0x71, 0xba, 0xe0, 0xbe, 0xe3, 0xbd, 0x9a, 0xc4,
- 0xf0, 0xd0, 0xdd, 0x01, 0x49, 0x12, 0x70, 0x78, 0x43, 0xa1, 0x8c, 0x5e,
- 0xe7, 0x9d, 0x62, 0x96, 0x2f, 0xf4, 0x27, 0x6e, 0x7d, 0x86, 0xb1, 0x7f,
- 0x8b, 0x03, 0xf1, 0xad, 0xc5, 0x8b, 0xb3, 0xaf, 0x67, 0xd5, 0x11, 0xad,
- 0xf8, 0xf3, 0xf6, 0xfa, 0xc5, 0xe6, 0x86, 0x2c, 0x56, 0x1e, 0x27, 0x0a,
- 0x2d, 0xa5, 0x8b, 0xee, 0x4e, 0xb8, 0xb1, 0x4b, 0x17, 0xf7, 0x9f, 0xa4,
- 0x96, 0xeb, 0x15, 0x87, 0xe3, 0xd8, 0x94, 0x44, 0x66, 0x06, 0x5e, 0x9c,
- 0xd2, 0xc5, 0x75, 0x3d, 0xa2, 0x3e, 0xbd, 0xf7, 0x35, 0x62, 0xe9, 0xc5,
- 0x8a, 0xea, 0x9a, 0x18, 0xe1, 0xd8, 0x69, 0x1e, 0x87, 0xaf, 0xff, 0x40,
- 0xa7, 0xa9, 0xca, 0x4d, 0xf3, 0xec, 0xb1, 0x7f, 0xf4, 0xfc, 0xb3, 0xda,
- 0x9e, 0xbc, 0x3a, 0xc5, 0x76, 0x89, 0x3f, 0x26, 0xdf, 0x75, 0x98, 0x69,
- 0x62, 0xf7, 0x34, 0x75, 0x8b, 0xff, 0xba, 0xfb, 0x58, 0x1e, 0x6c, 0x58,
- 0x1a, 0xc5, 0x75, 0x57, 0xa9, 0x23, 0xa3, 0x76, 0xc8, 0xee, 0x1e, 0x1b,
- 0x20, 0x24, 0x22, 0x5f, 0x0f, 0x5d, 0x20, 0x58, 0xbf, 0x6b, 0xa9, 0x74,
- 0x0d, 0x62, 0xff, 0xfc, 0x68, 0x22, 0xe7, 0x5f, 0x1e, 0x7f, 0x85, 0xde,
- 0x2c, 0x5f, 0x1b, 0x1c, 0x2f, 0x2c, 0x5b, 0x8b, 0x17, 0x98, 0x12, 0xb1,
- 0x5a, 0x3d, 0x63, 0x94, 0x7c, 0x4a, 0xf3, 0x45, 0x2b, 0x17, 0xbf, 0x9a,
- 0x58, 0xae, 0xa9, 0xaf, 0xc8, 0xbc, 0x0b, 0x9a, 0x16, 0x21, 0x97, 0x84,
- 0x1d, 0xbf, 0xb6, 0x8a, 0x11, 0xb6, 0xb6, 0x58, 0xbe, 0x30, 0xb3, 0xa2,
- 0xc5, 0xf3, 0x8f, 0x06, 0xb1, 0x5d, 0x9e, 0x39, 0xc9, 0x6d, 0x12, 0xc5,
- 0xd2, 0x75, 0x8b, 0x79, 0x62, 0xb4, 0x6a, 0x58, 0x5e, 0x86, 0x7b, 0x9f,
- 0x3c, 0xbe, 0x91, 0xb4, 0x16, 0x2f, 0x7b, 0x38, 0xb1, 0x79, 0x88, 0xd5,
- 0x8b, 0xff, 0x63, 0x76, 0x08, 0xa1, 0x3a, 0xd9, 0x62, 0xf6, 0xa6, 0x25,
- 0x8b, 0x84, 0x1a, 0xc5, 0xcd, 0xda, 0xc5, 0x61, 0xb1, 0xe0, 0xcd, 0x6c,
- 0x98, 0x69, 0xa4, 0x47, 0x1d, 0xf8, 0xeb, 0x21, 0x79, 0x3e, 0xfa, 0x0c,
- 0x51, 0xcb, 0x17, 0xdf, 0xc0, 0x32, 0xc5, 0x99, 0x62, 0xba, 0x9b, 0x38,
- 0x88, 0xae, 0x86, 0xcb, 0x17, 0xbd, 0x30, 0x58, 0xbe, 0xc8, 0x9f, 0x4b,
- 0x17, 0xf7, 0xdb, 0xb0, 0x18, 0x75, 0x8b, 0xec, 0xf6, 0x1d, 0x62, 0xff,
- 0x71, 0x81, 0x82, 0xd6, 0xcb, 0x17, 0xd1, 0x4f, 0x99, 0x62, 0xba, 0xa3,
- 0xae, 0x47, 0x70, 0x8d, 0x8c, 0x7c, 0x44, 0x23, 0x5b, 0xff, 0xec, 0x92,
- 0x04, 0xbf, 0xbf, 0x87, 0xc1, 0xac, 0x5d, 0x3a, 0x58, 0xbd, 0xe8, 0x32,
- 0xc5, 0xc2, 0xd9, 0x62, 0xb6, 0x3c, 0xd6, 0x17, 0x30, 0x76, 0xec, 0xe2,
- 0xc5, 0xd2, 0x6a, 0xc5, 0x6c, 0x9a, 0x7c, 0x15, 0x8d, 0x84, 0xd1, 0xcc,
- 0x3c, 0x2f, 0x7f, 0x30, 0x73, 0xec, 0xd9, 0x62, 0xfd, 0xfc, 0x2e, 0xc4,
- 0xb1, 0x7f, 0x3e, 0xbb, 0x81, 0x4a, 0xc5, 0xfa, 0x7d, 0x07, 0xf2, 0xc5,
- 0xfd, 0xf9, 0xee, 0x19, 0xe5, 0x8a, 0x81, 0xeb, 0x8c, 0xa2, 0xb4, 0x8d,
- 0x0f, 0x94, 0xfa, 0x10, 0xb7, 0xfd, 0xb6, 0xb2, 0x28, 0x39, 0x1a, 0xb1,
- 0x7f, 0xd2, 0x5e, 0xd3, 0xf4, 0xc1, 0xac, 0x53, 0x1f, 0xb4, 0x71, 0xe5,
- 0xd9, 0xe5, 0x8b, 0x44, 0xb1, 0x5f, 0x35, 0x44, 0x2f, 0x51, 0xba, 0xfd,
- 0xfc, 0xbf, 0xe3, 0xfb, 0xc6, 0x5f, 0x12, 0xc9, 0xd6, 0x3e, 0x48, 0xd2,
- 0x94, 0xc9, 0x48, 0x50, 0xff, 0x8e, 0x85, 0x59, 0x89, 0xd7, 0xff, 0xfd,
- 0xbf, 0xdf, 0xe2, 0xf7, 0x5c, 0x1b, 0xf3, 0xbf, 0x09, 0xb8, 0xb1, 0x7e,
- 0x13, 0x78, 0x0c, 0xb1, 0x5d, 0x51, 0x29, 0xe6, 0xcb, 0xfb, 0x20, 0x42,
- 0x6e, 0x2c, 0x50, 0xcf, 0x48, 0x32, 0x5b, 0xfd, 0xb7, 0xdf, 0x3d, 0xc7,
- 0x58, 0xa5, 0x8a, 0x93, 0xc0, 0xe1, 0xa5, 0xef, 0xbe, 0x96, 0x2f, 0xe2,
- 0x17, 0x35, 0xce, 0x2c, 0x56, 0x8f, 0x33, 0xa0, 0xed, 0xfb, 0xb0, 0xd8,
- 0x80, 0xb1, 0x71, 0x1a, 0xb1, 0x6e, 0x39, 0xe1, 0x08, 0xaa, 0xe6, 0xfa,
- 0xc5, 0xff, 0x8f, 0x26, 0xfb, 0xf9, 0xe9, 0x02, 0xc5, 0xf9, 0x87, 0x38,
- 0x4b, 0x16, 0x35, 0x62, 0xb6, 0x44, 0x83, 0x8b, 0xfd, 0x00, 0x89, 0xae,
- 0xce, 0x2c, 0x5c, 0xe7, 0x58, 0xb3, 0xf8, 0xd7, 0x08, 0x5e, 0xff, 0xbc,
- 0x4d, 0xf3, 0xce, 0x79, 0x62, 0xf8, 0xe5, 0x9b, 0xf5, 0x3d, 0xee, 0xc9,
- 0xaf, 0xff, 0xb3, 0x66, 0x2d, 0xfa, 0xf2, 0x4e, 0xdd, 0xf9, 0x62, 0xe2,
- 0x89, 0x62, 0xa5, 0x15, 0x1a, 0x3c, 0x65, 0x4b, 0xfd, 0x1f, 0xfc, 0xdb,
- 0x5a, 0x95, 0x8a, 0x58, 0xbf, 0xb8, 0x61, 0xf5, 0xa9, 0x58, 0xbf, 0xf9,
- 0xa1, 0x84, 0x32, 0x98, 0x0f, 0x8b, 0x16, 0xcc, 0x3f, 0xff, 0x06, 0x74,
- 0x30, 0xbf, 0xee, 0xbc, 0x14, 0xf6, 0x2c, 0xfa, 0xc5, 0xdc, 0x0a, 0x2c,
- 0x5f, 0xfe, 0x2c, 0x3c, 0xef, 0xd4, 0xcd, 0xb6, 0x6e, 0xd6, 0x2f, 0xe1,
- 0x1c, 0xed, 0x0e, 0xbe, 0x3e, 0xd0, 0x83, 0x97, 0xe1, 0x40, 0xcd, 0x71,
- 0x62, 0xa0, 0x98, 0xf7, 0xe1, 0x54, 0x49, 0x37, 0x83, 0x6d, 0x96, 0x2c,
- 0xeb, 0x14, 0xe7, 0xcb, 0xf3, 0x50, 0x0f, 0xdf, 0x87, 0x91, 0x7d, 0xd6,
- 0x2f, 0xb2, 0x2f, 0xba, 0xc5, 0xb7, 0xea, 0x79, 0x83, 0x29, 0xbf, 0xff,
- 0x4e, 0xa7, 0x7c, 0x3c, 0xef, 0x07, 0xe0, 0x8e, 0xb1, 0x52, 0xbd, 0xed,
- 0xb3, 0x1e, 0x36, 0xc4, 0xcd, 0xa8, 0x5b, 0xfe, 0x37, 0x06, 0x2e, 0x28,
- 0x5b, 0xfa, 0x3b, 0x81, 0x3d, 0x47, 0x15, 0xdf, 0xda, 0xc9, 0x36, 0x49,
- 0x62, 0xff, 0xff, 0x74, 0xeb, 0xbf, 0xc4, 0x3d, 0x3e, 0xc5, 0x9e, 0x7c,
- 0x0d, 0x62, 0xe6, 0xfa, 0xc5, 0xd1, 0xb8, 0x51, 0x62, 0xf1, 0x31, 0xd6,
- 0x2f, 0xfc, 0xdd, 0xf7, 0x01, 0x6d, 0xd7, 0xd8, 0xb1, 0x7f, 0x1a, 0xd1,
- 0x13, 0x9d, 0x62, 0xff, 0xff, 0xec, 0x09, 0x14, 0xff, 0x3c, 0x53, 0x17,
- 0x5c, 0x2c, 0xee, 0x0f, 0xc5, 0x8b, 0xff, 0xfb, 0xed, 0x11, 0xc4, 0x4c,
- 0x6f, 0x33, 0x7f, 0x8a, 0x3d, 0x62, 0x80, 0x8d, 0x8e, 0x3b, 0x51, 0x26,
- 0x55, 0xe8, 0xc1, 0xef, 0xff, 0xc5, 0xee, 0x75, 0xef, 0xd9, 0xb4, 0xf1,
- 0xf5, 0x8b, 0x15, 0x28, 0x82, 0x11, 0x4d, 0xe8, 0x6d, 0x2b, 0x17, 0xde,
- 0xe7, 0x70, 0x58, 0xb4, 0xac, 0x57, 0x53, 0xd4, 0xc1, 0xe0, 0x12, 0xda,
- 0x25, 0x8b, 0xef, 0xbe, 0xa2, 0x58, 0xae, 0xa6, 0xde, 0x21, 0x3b, 0xf8,
- 0xb0, 0x78, 0xff, 0x58, 0xaf, 0x9e, 0x87, 0x09, 0x2e, 0xce, 0x2c, 0x5e,
- 0x16, 0x12, 0xc5, 0xff, 0xfb, 0xb8, 0x73, 0xae, 0x08, 0x2e, 0xff, 0x62,
- 0xce, 0x8b, 0x17, 0xfe, 0x3e, 0x77, 0x0e, 0x34, 0xf7, 0x05, 0x8a, 0xdd,
- 0x1a, 0x5a, 0x17, 0x38, 0xe7, 0xd7, 0xaf, 0xfd, 0xa8, 0xb9, 0x3a, 0x68,
- 0x3f, 0xd6, 0x2e, 0x33, 0x65, 0x8a, 0xc4, 0xe3, 0x1e, 0x1e, 0x8c, 0x7c,
- 0x48, 0x17, 0xa4, 0xb6, 0x58, 0xa8, 0x2e, 0xf7, 0x8c, 0xb7, 0x1a, 0x3b,
- 0x17, 0x72, 0x1d, 0x0e, 0x7e, 0x3f, 0x12, 0x76, 0xf4, 0xa4, 0x3e, 0x87,
- 0xf5, 0x1b, 0xc7, 0xb9, 0xc0, 0x14, 0x8c, 0x78, 0x2b, 0x28, 0xe6, 0x34,
- 0x8c, 0x0a, 0x36, 0x9e, 0x30, 0x0b, 0x71, 0x9c, 0x85, 0x90, 0xac, 0x0b,
- 0x58, 0xc4, 0xa3, 0x54, 0x2e, 0x63, 0x59, 0x6c, 0xd6, 0x36, 0x7b, 0x4f,
- 0x0f, 0xc2, 0x7b, 0xc8, 0x75, 0x87, 0x76, 0x5b, 0x4d, 0x63, 0x69, 0x0d,
- 0xdb, 0xd7, 0x32, 0x7d, 0xd6, 0x00, 0x4f, 0x4a, 0xf1, 0x8a, 0x9d, 0xe1,
- 0xaa, 0xeb, 0x8c, 0xf4, 0xe9, 0xcf, 0xdb, 0x90, 0xe6, 0xa6, 0xa1, 0x82,
- 0x94, 0x3c, 0x17, 0x8e, 0x58, 0xad, 0x60, 0xb7, 0x2d, 0x2f, 0x3f, 0xad,
- 0x56, 0x10, 0xa7, 0xd6, 0xfa, 0x4e, 0x4d, 0x07, 0x1e, 0xdc, 0x75, 0x20,
- 0x7c, 0xca, 0x45, 0x00, 0x49, 0xea, 0x1b, 0xf7, 0xa4, 0x9c, 0x0b, 0x17,
- 0xec, 0x19, 0x4e, 0xeb, 0x17, 0x8b, 0xd1, 0x98, 0x79, 0xff, 0x27, 0xbf,
- 0xff, 0x85, 0xbc, 0x67, 0x7e, 0xd4, 0xe7, 0x71, 0xb0, 0xd9, 0x8d, 0x58,
- 0xa8, 0xc5, 0xc1, 0xd9, 0x97, 0x00, 0xe6, 0xb7, 0xfa, 0x3d, 0x9f, 0xdc,
- 0x72, 0x58, 0xbf, 0x6b, 0x76, 0x6d, 0xd5, 0x14, 0xe9, 0x76, 0x76, 0xb1,
- 0x7e, 0xc2, 0xdf, 0x25, 0x62, 0xdf, 0x58, 0xbf, 0xf8, 0x44, 0xe5, 0x3f,
- 0x73, 0xe7, 0x16, 0x2b, 0x87, 0xa8, 0x21, 0x2b, 0xb4, 0x75, 0x8b, 0xec,
- 0x26, 0x35, 0x62, 0xa5, 0x35, 0xbc, 0x35, 0xec, 0xdf, 0x43, 0x07, 0x7b,
- 0x01, 0x14, 0x70, 0xc5, 0xf6, 0x67, 0xdd, 0x62, 0xe8, 0x99, 0x62, 0xfb,
- 0xcc, 0x46, 0xac, 0x54, 0x9b, 0xbe, 0xc6, 0x2f, 0x8d, 0x68, 0x46, 0x0c,
- 0xff, 0x4c, 0x5c, 0xa8, 0xc4, 0xc8, 0x8d, 0x87, 0x25, 0xff, 0xfa, 0x11,
- 0x99, 0x0f, 0xe3, 0xc3, 0x93, 0xe9, 0x1a, 0xc5, 0xe8, 0x0b, 0x4b, 0x17,
- 0xef, 0x0b, 0xf2, 0x75, 0x8b, 0xfa, 0x70, 0xba, 0xe6, 0xcb, 0x17, 0xbb,
- 0x6d, 0x96, 0x2e, 0xce, 0x2c, 0x54, 0x9b, 0x6c, 0x1f, 0xbe, 0xdb, 0x69,
- 0xed, 0x62, 0xfe, 0x6d, 0xbd, 0xc6, 0x02, 0xc5, 0xda, 0x8c, 0xc4, 0xc8,
- 0x3b, 0x1e, 0xd1, 0x4f, 0xd9, 0x58, 0x7e, 0x38, 0x9a, 0xa5, 0x3e, 0x17,
- 0x8d, 0xe2, 0xfd, 0xad, 0xd9, 0xb7, 0x54, 0x54, 0x65, 0xff, 0x9a, 0x11,
- 0x99, 0xad, 0xd9, 0xb7, 0x54, 0x4d, 0x05, 0xff, 0xe2, 0xc8, 0xa0, 0xda,
- 0x81, 0x67, 0x46, 0x58, 0xbd, 0x39, 0xda, 0xc5, 0xe6, 0xda, 0x56, 0x28,
- 0x8d, 0xd0, 0x87, 0x6b, 0x13, 0x2c, 0x39, 0xbf, 0x14, 0x3d, 0x08, 0x5b,
- 0xfc, 0x63, 0x74, 0x8c, 0xf3, 0xec, 0xb1, 0x51, 0x87, 0xfb, 0x28, 0x57,
- 0xff, 0xec, 0xff, 0xda, 0x01, 0xe3, 0xf4, 0x26, 0x9e, 0x2c, 0x5f, 0xfb,
- 0xe2, 0xfb, 0x3f, 0x7c, 0x93, 0x56, 0x2d, 0xe8, 0x22, 0x5d, 0xd5, 0xaf,
- 0xf4, 0xe8, 0xc2, 0x6f, 0x71, 0x62, 0xb0, 0xf7, 0x3e, 0x51, 0x7e, 0xd8,
- 0xcd, 0xa7, 0x65, 0x8b, 0xed, 0xd9, 0xb7, 0x54, 0x55, 0xe5, 0x61, 0xef,
- 0x68, 0xb6, 0xff, 0xdb, 0xcf, 0xa1, 0x27, 0x26, 0x82, 0xc5, 0xff, 0x72,
- 0x61, 0xf9, 0x0d, 0x89, 0x62, 0xcf, 0xb9, 0xfc, 0x78, 0xfe, 0xff, 0xda,
- 0xdb, 0x93, 0xb9, 0x31, 0xf8, 0xb1, 0x5f, 0x3e, 0x96, 0x28, 0xbf, 0xfb,
- 0xc0, 0xc1, 0xff, 0x06, 0x37, 0xed, 0x62, 0xfd, 0xd2, 0x4b, 0xe2, 0x58,
- 0xbf, 0xf3, 0x77, 0x0e, 0x66, 0xe3, 0xce, 0xd6, 0x2b, 0x0f, 0xb1, 0x8a,
- 0xac, 0x6a, 0xc5, 0xfc, 0xe3, 0x1c, 0xea, 0x56, 0x2e, 0x93, 0x56, 0x2f,
- 0xdc, 0x26, 0x9e, 0x2c, 0x5f, 0xfe, 0xfb, 0x40, 0x3c, 0x7e, 0x84, 0xd3,
- 0xc5, 0x8b, 0xff, 0xfc, 0xe3, 0x3b, 0x31, 0x6e, 0x3f, 0xce, 0x0d, 0xcb,
- 0x65, 0x8b, 0x67, 0xd1, 0x56, 0x49, 0x75, 0x28, 0xf9, 0x84, 0x34, 0xaf,
- 0xfb, 0xd9, 0xdf, 0xb3, 0x08, 0xd5, 0x8b, 0xff, 0xcf, 0xd0, 0x73, 0x9d,
- 0xfd, 0xf5, 0x27, 0x58, 0xbf, 0xf7, 0xe2, 0x6f, 0x7b, 0xbd, 0xdc, 0x96,
- 0x2b, 0x11, 0x1c, 0xc9, 0x97, 0xec, 0xff, 0xf2, 0x25, 0x8b, 0xff, 0xf0,
- 0x08, 0x47, 0x30, 0x63, 0x90, 0x1e, 0x73, 0xcb, 0x17, 0xf3, 0x7b, 0x99,
- 0xdf, 0x96, 0x28, 0x68, 0xaf, 0xec, 0xa4, 0x95, 0xed, 0x18, 0x35, 0xdb,
- 0x4c, 0x7f, 0xde, 0x30, 0x2e, 0xc8, 0x75, 0x0b, 0x23, 0x90, 0x7c, 0x4c,
- 0x2e, 0x5b, 0xe8, 0xc4, 0x7a, 0x13, 0x87, 0x0c, 0x83, 0x21, 0xa1, 0x7e,
- 0xd6, 0xec, 0xdb, 0xaa, 0x2b, 0x62, 0xff, 0xa1, 0x19, 0x9a, 0xdd, 0x9b,
- 0x75, 0x44, 0x82, 0x5f, 0x61, 0xe6, 0x3d, 0x62, 0xd1, 0x98, 0x8a, 0x76,
- 0x37, 0xe2, 0x5d, 0xf1, 0xdc, 0xa5, 0x62, 0xfd, 0xad, 0xd9, 0xb7, 0x54,
- 0x48, 0x65, 0xfd, 0xa1, 0x74, 0x90, 0xce, 0xb1, 0x7f, 0x16, 0x73, 0xd0,
- 0x95, 0x8b, 0xcd, 0x08, 0xc9, 0x45, 0xbe, 0x10, 0xb9, 0xbf, 0x43, 0x2b,
- 0xff, 0xb6, 0x8c, 0x30, 0xfd, 0x73, 0x4d, 0xee, 0x2c, 0x54, 0x62, 0x27,
- 0x5d, 0x42, 0xfe, 0xf3, 0x8f, 0x0a, 0x25, 0x8b, 0xd9, 0xd3, 0x16, 0x2b,
- 0x0f, 0x30, 0x8b, 0xaf, 0xf1, 0x0b, 0x93, 0x9a, 0x02, 0xc5, 0xe3, 0x72,
- 0x3d, 0x62, 0xf3, 0x1b, 0x19, 0x87, 0xa8, 0x69, 0x9d, 0xb9, 0x18, 0x8a,
- 0xb2, 0x74, 0xbc, 0xcd, 0xba, 0xe3, 0x03, 0x2a, 0x4f, 0x57, 0x72, 0xbb,
- 0xf4, 0x6b, 0x0a, 0x6d, 0xb6, 0xcb, 0x16, 0xdd, 0x62, 0xfc, 0x7e, 0xe1,
- 0x87, 0x58, 0xb4, 0x7a, 0xc5, 0x46, 0xb4, 0x44, 0xe1, 0xbc, 0x42, 0x7f,
- 0x2a, 0xb8, 0x3f, 0x2c, 0x5e, 0xe3, 0x9a, 0xb1, 0x43, 0x36, 0xfd, 0x8c,
- 0xdd, 0x1a, 0x6c, 0xb1, 0x7f, 0xdf, 0x9f, 0x70, 0x29, 0xc8, 0xd0, 0x96,
- 0x2a, 0x37, 0x3e, 0x18, 0x0f, 0x5f, 0x7b, 0xd8, 0x11, 0x62, 0xc4, 0xb1,
- 0x78, 0x2d, 0x23, 0xa3, 0x75, 0x8b, 0xd3, 0x1d, 0x1b, 0xac, 0x50, 0x5a,
- 0x1e, 0x94, 0x96, 0xd9, 0xd6, 0x28, 0x28, 0x89, 0xc0, 0xb6, 0xc7, 0x1a,
- 0xca, 0x2f, 0xff, 0x46, 0xb8, 0xd6, 0x14, 0xfc, 0x9c, 0x9b, 0xef, 0xa5,
- 0x8b, 0x76, 0xb1, 0x71, 0x41, 0x62, 0xf7, 0xb0, 0x0b, 0x16, 0x25, 0x8b,
- 0xe1, 0x0d, 0xa3, 0xd6, 0x29, 0xcd, 0xbf, 0x04, 0x6f, 0x0b, 0xd8, 0xb1,
- 0x74, 0xc4, 0xb1, 0x7f, 0x1f, 0x37, 0x26, 0x8f, 0x58, 0xbd, 0x8f, 0xb2,
- 0xc5, 0x8c, 0x58, 0xac, 0x3e, 0x1d, 0x18, 0x88, 0x76, 0xfc, 0x39, 0xf3,
- 0x0d, 0x62, 0xc7, 0x58, 0xb9, 0xfa, 0x2c, 0x54, 0x9e, 0x9b, 0x94, 0x78,
- 0x4a, 0xf7, 0x41, 0x41, 0x62, 0xf7, 0xf3, 0x8b, 0x16, 0x65, 0x8a, 0x19,
- 0xae, 0xf0, 0xed, 0x0d, 0x52, 0x8e, 0x09, 0xc7, 0x8b, 0xc4, 0xa9, 0xa2,
- 0x0f, 0x8e, 0xf1, 0xe7, 0xd0, 0x81, 0xe8, 0x5a, 0x62, 0x75, 0xf6, 0x77,
- 0x0f, 0x2c, 0x5f, 0xc5, 0x3d, 0xc1, 0xc9, 0x62, 0xf7, 0x1f, 0xa2, 0xc5,
- 0x6c, 0x7e, 0x03, 0x24, 0xf1, 0x6d, 0x89, 0x62, 0xfb, 0x0e, 0xc3, 0x58,
- 0xbf, 0x0e, 0x4b, 0x68, 0xf5, 0x8b, 0xfd, 0x26, 0x98, 0x00, 0x4f, 0x6b,
- 0x15, 0x27, 0xc7, 0xb1, 0x65, 0xf9, 0xbe, 0xe7, 0xc5, 0x8a, 0xc4, 0x6f,
- 0xfc, 0x44, 0xa1, 0x0b, 0xd0, 0x8a, 0xfe, 0x33, 0x22, 0x70, 0x71, 0x62,
- 0xfe, 0xcd, 0xff, 0x33, 0x12, 0xc5, 0xfb, 0x5a, 0x9c, 0x25, 0x8b, 0x47,
- 0x2c, 0x53, 0xa3, 0x76, 0x24, 0x2f, 0x98, 0x31, 0x78, 0x89, 0xef, 0x10,
- 0x38, 0xb1, 0x7e, 0x6d, 0x8c, 0xc8, 0x96, 0x2f, 0x00, 0xcd, 0x96, 0x2f,
- 0x8f, 0x9d, 0xf1, 0x62, 0xdc, 0x93, 0xc4, 0x72, 0x0b, 0xda, 0xc3, 0xac,
- 0x56, 0x23, 0x3c, 0x87, 0x78, 0xdf, 0xe2, 0x6b, 0xd1, 0xd9, 0xda, 0xc5,
- 0xc1, 0x8d, 0x62, 0xf6, 0xe5, 0x1e, 0xb1, 0x7f, 0xc1, 0xfd, 0xda, 0x1e,
- 0x7d, 0x96, 0x2d, 0x05, 0x8a, 0x63, 0xcd, 0xf1, 0xdd, 0x7d, 0x15, 0x0c,
- 0x32, 0x4d, 0xd7, 0x0b, 0x4b, 0x17, 0xdd, 0x26, 0x7b, 0x58, 0xbf, 0xf0,
- 0x33, 0xbe, 0x19, 0xa7, 0x3e, 0x2c, 0x5c, 0xf1, 0x2c, 0x57, 0x67, 0xb3,
- 0xa4, 0x1b, 0xf6, 0xdb, 0xfd, 0xe2, 0x58, 0xa9, 0x46, 0x6e, 0x3f, 0x39,
- 0x1d, 0xf6, 0xdc, 0xed, 0xd6, 0x2f, 0xff, 0x4f, 0x70, 0x73, 0x87, 0x84,
- 0x3f, 0xca, 0xc5, 0x62, 0xab, 0x47, 0x3b, 0xd4, 0x32, 0x4e, 0x5c, 0x50,
- 0xe5, 0xe1, 0x68, 0x89, 0x6f, 0xcc, 0x33, 0x24, 0x96, 0x2f, 0xf3, 0x8a,
- 0x3f, 0xf3, 0x9b, 0x2c, 0x5f, 0xfb, 0x5e, 0x30, 0x9b, 0x7c, 0x2d, 0xd6,
- 0x2e, 0x6f, 0x2c, 0x5c, 0xf1, 0xcb, 0x15, 0x11, 0xb1, 0x38, 0xbd, 0xfe,
- 0xce, 0x98, 0x59, 0xdf, 0x96, 0x2a, 0x4f, 0x5f, 0xe4, 0x57, 0x48, 0x45,
- 0x8b, 0xff, 0x06, 0xd0, 0xd6, 0x3f, 0xe4, 0x6b, 0x16, 0xed, 0x62, 0xf1,
- 0x77, 0xc5, 0x8b, 0xe7, 0x1e, 0x12, 0xc5, 0x49, 0xe9, 0x38, 0x9f, 0x07,
- 0xaf, 0xee, 0xf9, 0x87, 0x98, 0xf5, 0x8b, 0xcc, 0xdb, 0xaa, 0x2c, 0x42,
- 0xf1, 0x9e, 0xe2, 0xc5, 0x49, 0xfd, 0xee, 0x65, 0xa2, 0xab, 0xed, 0x31,
- 0x79, 0x62, 0xc0, 0x58, 0xad, 0x1b, 0x40, 0x84, 0x57, 0xdf, 0x26, 0x8f,
- 0x58, 0xbf, 0xb5, 0xf6, 0xe6, 0x18, 0xb1, 0x77, 0xc4, 0xb1, 0x7d, 0xc3,
- 0x0a, 0x0b, 0x14, 0x33, 0x79, 0xe1, 0x8b, 0xd3, 0xad, 0x96, 0x2a, 0x51,
- 0x9e, 0xe4, 0xac, 0xd6, 0x61, 0x0d, 0xfb, 0xed, 0xc9, 0x8f, 0x58, 0xb6,
- 0x96, 0x28, 0x8d, 0xe8, 0x8a, 0xec, 0x1a, 0xc5, 0xdc, 0x75, 0x8a, 0x73,
- 0x54, 0x01, 0x3b, 0xff, 0x43, 0x39, 0xef, 0xe3, 0xea, 0x0b, 0x14, 0xe7,
- 0xbe, 0x22, 0x0b, 0xfa, 0x67, 0xb3, 0xb0, 0xd6, 0x2f, 0xf0, 0xc0, 0x2f,
- 0x70, 0x51, 0xeb, 0x17, 0x14, 0x16, 0x2a, 0x4f, 0x40, 0x47, 0x37, 0xfb,
- 0x79, 0xcd, 0x00, 0x1e, 0x58, 0xbf, 0xe7, 0x21, 0xea, 0x60, 0xda, 0x58,
- 0xbe, 0x9e, 0xe1, 0xc5, 0x8a, 0xd9, 0x79, 0x8a, 0x05, 0x18, 0x6f, 0xbc,
- 0x32, 0x7b, 0x21, 0x71, 0x98, 0xa1, 0x23, 0xa8, 0x54, 0x1d, 0x8f, 0xf0,
- 0xf2, 0x67, 0x82, 0x85, 0x4f, 0x08, 0x7c, 0xfc, 0x22, 0x1e, 0x86, 0xa1,
- 0x9c, 0x5d, 0xc7, 0x58, 0xbe, 0xd4, 0x91, 0xab, 0x17, 0xde, 0x72, 0x0d,
- 0x62, 0xfa, 0x22, 0x7d, 0x96, 0x2c, 0xd8, 0x78, 0xfd, 0x91, 0xde, 0x84,
- 0xc7, 0xac, 0x50, 0xd1, 0x91, 0x82, 0xe6, 0xb5, 0x44, 0x4f, 0x7c, 0xfc,
- 0x98, 0x96, 0x2f, 0xfe, 0xf6, 0x6d, 0xc9, 0xd3, 0x41, 0xfe, 0xb1, 0x5a,
- 0x3e, 0x8f, 0x11, 0xd9, 0xd6, 0x2c, 0xeb, 0x16, 0x81, 0xa6, 0x88, 0x02,
- 0x37, 0x77, 0x1e, 0xb1, 0x7d, 0x1d, 0x9a, 0x95, 0x8a, 0x11, 0xe0, 0x98,
- 0x39, 0x7a, 0x21, 0x69, 0x62, 0xe9, 0xe2, 0xc5, 0xfe, 0x19, 0x4f, 0xb8,
- 0x23, 0xac, 0x5e, 0x71, 0x12, 0xc5, 0x89, 0x62, 0xe9, 0x25, 0x8b, 0xfa,
- 0x78, 0x66, 0xd3, 0xb2, 0xc5, 0x1a, 0x8b, 0xf8, 0x85, 0xce, 0x68, 0x43,
- 0x9c, 0x11, 0x30, 0x5a, 0xf0, 0xdf, 0x4b, 0x17, 0xd1, 0xff, 0x14, 0x7a,
- 0xc5, 0x4a, 0x74, 0x38, 0x46, 0xf0, 0xde, 0x65, 0x91, 0x0e, 0xdf, 0xf0,
- 0xb6, 0x2c, 0x1f, 0xc4, 0x6a, 0xc5, 0x4a, 0xad, 0x63, 0x51, 0x3f, 0x28,
- 0x28, 0x93, 0x2f, 0xbf, 0xc1, 0x4a, 0xc5, 0xb8, 0xb1, 0x7f, 0xfb, 0x3b,
- 0xec, 0x0d, 0xee, 0x39, 0x77, 0x05, 0x8b, 0xfc, 0x2d, 0xbb, 0x87, 0xc5,
- 0xa5, 0x8b, 0xff, 0xa7, 0x39, 0x84, 0x37, 0x04, 0x92, 0xc5, 0xe2, 0x9d,
- 0x96, 0x2b, 0x11, 0xea, 0xe2, 0x5f, 0x4d, 0x23, 0x81, 0x20, 0xdf, 0x7f,
- 0xb6, 0x8f, 0x58, 0xb8, 0x5a, 0x58, 0xbd, 0xa9, 0x3a, 0xc5, 0xc6, 0x4a,
- 0xc5, 0x49, 0xb5, 0xc1, 0xdb, 0xfd, 0x20, 0xd6, 0xa4, 0xfc, 0x58, 0xa9,
- 0x54, 0x4d, 0x08, 0xc6, 0x0e, 0x8e, 0xc4, 0xfc, 0x4d, 0xf0, 0xfd, 0xf0,
- 0xcc, 0x0a, 0x41, 0x62, 0xfc, 0x0d, 0xfe, 0xe1, 0x75, 0x8b, 0xdf, 0xc0,
- 0x2c, 0x5f, 0xdd, 0xf3, 0xf2, 0xfe, 0x58, 0xb9, 0xbc, 0xb1, 0x4e, 0x78,
- 0xc7, 0x2f, 0xbc, 0xd9, 0xf5, 0x8b, 0xa4, 0x0b, 0x15, 0x26, 0xcf, 0xe3,
- 0x97, 0x0a, 0x39, 0x62, 0xf1, 0x4e, 0xcb, 0x17, 0x4f, 0xd6, 0x29, 0xcd,
- 0xa7, 0x07, 0x6f, 0xa4, 0x00, 0x65, 0x8b, 0xff, 0xd9, 0xdc, 0x08, 0x5e,
- 0x67, 0x29, 0x1a, 0xc5, 0x39, 0xf5, 0xf8, 0x8a, 0xfe, 0x39, 0x64, 0xc7,
- 0xc4, 0xb1, 0x60, 0x2c, 0x54, 0x9e, 0x1b, 0x98, 0xdd, 0xe8, 0x2c, 0x5e,
- 0x69, 0xed, 0x62, 0xa3, 0x45, 0x58, 0x38, 0x53, 0xb9, 0x76, 0x98, 0xfe,
- 0xa8, 0x44, 0x1c, 0x4f, 0xf4, 0x22, 0xe3, 0x99, 0x0c, 0x20, 0x08, 0x31,
- 0x7d, 0xac, 0xef, 0x8b, 0x17, 0xd8, 0x79, 0x8f, 0x58, 0xad, 0x1e, 0x4f,
- 0x09, 0x2f, 0x37, 0xb8, 0xb1, 0x7c, 0x42, 0xf7, 0x16, 0x2f, 0xff, 0x40,
- 0xe5, 0x3a, 0x91, 0xe4, 0x53, 0xf5, 0x8a, 0xd8, 0xfb, 0x74, 0x47, 0x4e,
- 0x8a, 0xd6, 0x84, 0x55, 0xed, 0xdb, 0x8b, 0x17, 0x19, 0xda, 0xc5, 0x61,
- 0xb8, 0xf8, 0xf5, 0xd3, 0xd1, 0x62, 0xf0, 0x9b, 0x8b, 0x14, 0x33, 0x6d,
- 0xd0, 0x66, 0xce, 0xb1, 0x7f, 0xd3, 0xee, 0x73, 0xd3, 0xd8, 0x6b, 0x17,
- 0x9c, 0x30, 0xba, 0xc5, 0xef, 0xe6, 0xcb, 0x16, 0x7d, 0x1e, 0x07, 0xc8,
- 0xad, 0xda, 0xc5, 0x41, 0x39, 0xec, 0x5e, 0x75, 0x68, 0x88, 0xf4, 0x23,
- 0xf7, 0xc3, 0x09, 0xef, 0xfc, 0xff, 0xee, 0x19, 0xec, 0xef, 0xcb, 0x17,
- 0xfb, 0xf8, 0x7c, 0x6d, 0x6c, 0xb1, 0x50, 0x3f, 0x51, 0xa0, 0xdd, 0x1a,
- 0x12, 0xc5, 0xfb, 0xde, 0x68, 0x71, 0x62, 0xf6, 0x6a, 0x56, 0x2f, 0x16,
- 0x1d, 0x62, 0x38, 0xbc, 0xbf, 0x0f, 0x22, 0x60, 0x2c, 0x5f, 0xf8, 0x59,
- 0xd8, 0xfa, 0x7f, 0x1a, 0x25, 0x8a, 0xed, 0x1b, 0xf1, 0x22, 0x88, 0xbb,
- 0xa1, 0x4d, 0xa0, 0xb1, 0x7b, 0xbe, 0x32, 0xc5, 0xf6, 0x60, 0x7c, 0x58,
- 0xa9, 0x3d, 0x3c, 0x12, 0xf0, 0xf5, 0xba, 0x2c, 0x5c, 0x22, 0x58, 0xb0,
- 0x5d, 0x62, 0xdd, 0x16, 0x2a, 0x55, 0x19, 0xec, 0x45, 0x90, 0xfb, 0xd4,
- 0x25, 0x00, 0x5b, 0xc1, 0x4f, 0x0b, 0xf4, 0x16, 0xbf, 0xb7, 0x9f, 0x7f,
- 0x00, 0xb1, 0x7f, 0x19, 0x9a, 0xcc, 0x89, 0x62, 0x88, 0xf7, 0xb8, 0x5f,
- 0x7e, 0xef, 0x93, 0xae, 0x2c, 0x5f, 0xf6, 0xbb, 0xf6, 0x7f, 0xf9, 0x12,
- 0xc5, 0xdf, 0xdd, 0x62, 0xf8, 0x1c, 0x32, 0x3d, 0x62, 0xff, 0x7b, 0x83,
- 0x13, 0x6a, 0x0b, 0x15, 0x87, 0xba, 0xc5, 0x17, 0xfb, 0x6e, 0xe1, 0xc2,
- 0x78, 0x96, 0x2f, 0xbc, 0x42, 0xd9, 0x62, 0xa4, 0xf6, 0xc8, 0xde, 0xa5,
- 0x39, 0x8c, 0x21, 0x72, 0xa6, 0x3c, 0x27, 0x61, 0x3d, 0xdf, 0xda, 0x80,
- 0x33, 0x22, 0x58, 0xb8, 0x46, 0x2c, 0x5f, 0xf6, 0x10, 0x78, 0x43, 0xfc,
- 0xac, 0x5c, 0xf1, 0xcb, 0x16, 0x08, 0xb1, 0x52, 0x6b, 0x84, 0x35, 0x7e,
- 0x98, 0x70, 0x5b, 0xac, 0x53, 0x1e, 0x50, 0x08, 0x2f, 0xdf, 0x7e, 0x92,
- 0x4b, 0x17, 0x31, 0x8b, 0x14, 0x33, 0xc1, 0x11, 0x4d, 0xdc, 0x89, 0x62,
- 0xf6, 0x8c, 0xe2, 0xc5, 0x62, 0x76, 0x86, 0x97, 0xee, 0x33, 0xa8, 0x58,
- 0x13, 0x17, 0x88, 0xba, 0x0c, 0xdf, 0xf7, 0x0d, 0xd4, 0x8f, 0xf3, 0xd1,
- 0x62, 0xff, 0xfc, 0x5e, 0x2c, 0xe0, 0x6c, 0x5b, 0x7b, 0xf8, 0x4b, 0x17,
- 0xd0, 0x33, 0xf2, 0xb1, 0x7f, 0x3c, 0x4e, 0x42, 0x31, 0x62, 0xff, 0xc5,
- 0x27, 0x97, 0x81, 0x4e, 0xeb, 0x17, 0xb5, 0x30, 0x58, 0xa9, 0x4c, 0x09,
- 0x95, 0x48, 0x93, 0xc5, 0xfd, 0x0f, 0x6f, 0x3e, 0xa2, 0x58, 0xbd, 0xe7,
- 0xd9, 0x62, 0xc7, 0xc3, 0x79, 0xe1, 0xeb, 0x47, 0xac, 0x54, 0x9b, 0xb6,
- 0x26, 0xbe, 0x32, 0x42, 0x71, 0x62, 0xdc, 0x58, 0xbf, 0xc5, 0x3d, 0xf7,
- 0xc6, 0x8f, 0x58, 0xbf, 0xe2, 0x63, 0xf3, 0x0f, 0x31, 0xeb, 0x17, 0xe9,
- 0x1e, 0x34, 0x7a, 0xc5, 0x11, 0xf2, 0xf4, 0x3b, 0xbf, 0xf3, 0xec, 0xc5,
- 0xf6, 0xe4, 0xc7, 0xac, 0x5e, 0x37, 0x23, 0xd6, 0x29, 0x62, 0xef, 0xc9,
- 0xa6, 0xb7, 0xe4, 0x34, 0xb1, 0x6c, 0x19, 0xb9, 0x39, 0x6d, 0xe7, 0x0e,
- 0x3d, 0x62, 0xec, 0x02, 0xc5, 0x68, 0xdc, 0x11, 0x0d, 0x3a, 0x69, 0x1f,
- 0x23, 0x28, 0x53, 0xf1, 0x7a, 0xff, 0xf6, 0x9c, 0xf3, 0xdf, 0xe4, 0x64,
- 0xd1, 0xeb, 0x14, 0x35, 0x55, 0x78, 0x4c, 0x71, 0x2e, 0x47, 0xcb, 0xe4,
- 0x1b, 0xed, 0xff, 0x3a, 0x58, 0xbc, 0xf9, 0xa5, 0x8a, 0xec, 0xf0, 0x0c,
- 0x24, 0xbf, 0xc0, 0x13, 0x19, 0xf9, 0x82, 0xc5, 0x4a, 0xf1, 0x06, 0x36,
- 0x3c, 0x67, 0xff, 0x86, 0x0b, 0x4a, 0xca, 0x14, 0x24, 0x43, 0x24, 0xb4,
- 0x16, 0x2d, 0x2b, 0x15, 0x26, 0x8c, 0x84, 0xaf, 0xbf, 0x3d, 0x84, 0x58,
- 0xb0, 0x45, 0x8a, 0xdc, 0xdd, 0x39, 0x35, 0x0c, 0xfe, 0xbb, 0x59, 0xb0,
- 0xd6, 0x2f, 0xc4, 0xc7, 0x9f, 0xac, 0x56, 0x1b, 0x97, 0x12, 0xbf, 0xfd,
- 0x27, 0x98, 0x0c, 0xa7, 0xed, 0x9a, 0x58, 0xb8, 0xf2, 0xb1, 0x62, 0x58,
- 0xa5, 0x8a, 0x81, 0xfe, 0x62, 0x47, 0x85, 0xe3, 0x84, 0x6f, 0xa7, 0xf3,
- 0x1e, 0xb1, 0x7c, 0x11, 0xcb, 0xeb, 0x14, 0x47, 0x92, 0x10, 0x96, 0xf7,
- 0xb0, 0x0b, 0x17, 0xf1, 0xdf, 0x9c, 0x71, 0xac, 0x5e, 0x6d, 0x1a, 0xb1,
- 0x42, 0x3c, 0xc0, 0xcb, 0xaf, 0xe2, 0xce, 0x85, 0x9c, 0x58, 0xb9, 0xf4,
- 0xb1, 0x5b, 0x9e, 0x2f, 0xcb, 0xad, 0xc5, 0x8b, 0xfd, 0x1f, 0xd4, 0xc9,
- 0x26, 0x35, 0x62, 0xff, 0x41, 0xb0, 0xb3, 0xdc, 0x58, 0xbf, 0xb8, 0xc6,
- 0x4f, 0x6c, 0xb1, 0x7e, 0xcc, 0x2e, 0xfc, 0xb1, 0x7f, 0xb3, 0xe5, 0x9e,
- 0xfb, 0xac, 0x50, 0xcf, 0x6b, 0xc5, 0x15, 0x29, 0x94, 0xe0, 0x97, 0x67,
- 0x4c, 0x64, 0x08, 0x44, 0xde, 0x96, 0xd2, 0xc5, 0xff, 0x07, 0x3c, 0x78,
- 0x39, 0x62, 0xc5, 0x0c, 0xf5, 0x30, 0x72, 0xf1, 0xf9, 0xc5, 0x8a, 0x58,
- 0xbd, 0xf7, 0x89, 0x62, 0xc7, 0x73, 0x54, 0xc1, 0x95, 0x27, 0xda, 0xc9,
- 0x17, 0xfe, 0xce, 0xe1, 0xf9, 0xe1, 0xbf, 0x95, 0x8a, 0x95, 0xd4, 0xf8,
- 0x2e, 0x77, 0x09, 0xb7, 0x84, 0x3c, 0x44, 0x7a, 0x69, 0xfb, 0x41, 0x46,
- 0x99, 0xc8, 0x51, 0x7a, 0x11, 0xc1, 0x08, 0x2f, 0xa2, 0x29, 0x3a, 0xc5,
- 0xff, 0x43, 0xed, 0x07, 0xd3, 0xf1, 0x62, 0xff, 0xfb, 0xf1, 0x98, 0x3f,
- 0xce, 0xce, 0x73, 0x8b, 0x75, 0x8a, 0xed, 0x11, 0xec, 0x73, 0x7d, 0xe6,
- 0x6d, 0x96, 0x2d, 0x1c, 0xb1, 0x74, 0x38, 0xb1, 0x66, 0x81, 0xad, 0xec,
- 0x56, 0xfb, 0xce, 0x41, 0xa4, 0x58, 0x4b, 0x16, 0x9c, 0x36, 0xbf, 0x23,
- 0xbb, 0x34, 0xb1, 0x7f, 0x8b, 0xdc, 0xef, 0x8d, 0x1e, 0xb1, 0x7f, 0x60,
- 0xe3, 0xf3, 0xb8, 0xf5, 0x8a, 0x58, 0xa6, 0x3f, 0x92, 0x38, 0x08, 0x6b,
- 0x50, 0x54, 0xca, 0xf0, 0xb2, 0x8f, 0x23, 0x65, 0x00, 0x2e, 0x11, 0x28,
- 0xa1, 0x21, 0x78, 0xcf, 0x89, 0x62, 0xfd, 0xdf, 0x24, 0xb6, 0x58, 0xbf,
- 0xe1, 0x45, 0xdf, 0x26, 0x27, 0xe8, 0xb1, 0x58, 0x7d, 0x27, 0x2a, 0xbf,
- 0xcf, 0xcf, 0xb1, 0x4c, 0xac, 0x5c, 0x2f, 0xac, 0x5f, 0xe2, 0xdf, 0xde,
- 0x68, 0x71, 0x62, 0xb4, 0x7f, 0xc7, 0x31, 0x10, 0xc5, 0xff, 0xf6, 0x7f,
- 0xb8, 0x72, 0x28, 0x39, 0x7a, 0x40, 0xb1, 0x7f, 0x49, 0xca, 0x7b, 0x82,
+ 0xac, 0x5f, 0xb5, 0x9e, 0xeb, 0x65, 0x8b, 0x9a, 0x11, 0x87, 0xd3, 0x87,
+ 0xd7, 0xfe, 0xc7, 0x04, 0x81, 0x88, 0x58, 0xb1, 0x7f, 0x10, 0xa2, 0xfb,
+ 0x44, 0xb1, 0x7f, 0xce, 0x3c, 0x28, 0x3f, 0xc4, 0xb1, 0x68, 0xcc, 0x4d,
+ 0xee, 0x22, 0x23, 0xc2, 0x18, 0x8b, 0xf8, 0x79, 0xe3, 0x0b, 0xa3, 0x73,
+ 0x56, 0x2e, 0x00, 0x96, 0x2f, 0x40, 0xa3, 0xd6, 0x2e, 0xeb, 0xcb, 0x17,
+ 0xff, 0xd3, 0xf9, 0x81, 0x31, 0xbd, 0x42, 0x73, 0xcb, 0x17, 0xfd, 0x87,
+ 0xeb, 0xcf, 0xfc, 0xee, 0x58, 0xb7, 0x16, 0x28, 0x67, 0x9e, 0xc7, 0xb7,
+ 0xc2, 0xee, 0x1c, 0xac, 0x5f, 0xfc, 0x59, 0xb6, 0xa4, 0x9d, 0xba, 0x82,
+ 0xc5, 0x41, 0x34, 0x31, 0x8c, 0xbc, 0x27, 0xfe, 0x43, 0xe2, 0x6b, 0xf8,
+ 0x22, 0x9f, 0x7d, 0xd6, 0x2f, 0x17, 0x5c, 0x58, 0xac, 0x3c, 0xc1, 0x17,
+ 0x5d, 0xe0, 0xd6, 0x2e, 0x67, 0x58, 0xbf, 0xd1, 0x99, 0xb3, 0xc8, 0x99,
+ 0x62, 0xb0, 0xf9, 0x7e, 0x33, 0xdf, 0x8b, 0x5f, 0xfe, 0x17, 0x7f, 0xcd,
+ 0xfe, 0xff, 0x9c, 0xd4, 0x16, 0x2f, 0xfe, 0xe3, 0xf6, 0x2c, 0x00, 0xb9,
+ 0xf1, 0x2c, 0x5f, 0xf3, 0x01, 0x8b, 0xaf, 0x7e, 0x56, 0x2f, 0xff, 0xbe,
+ 0xe2, 0x6e, 0xa1, 0xac, 0xea, 0x0e, 0x75, 0x8b, 0xfd, 0xf0, 0xe2, 0xe3,
+ 0xf4, 0x12, 0xc5, 0xba, 0x58, 0xa9, 0x44, 0xf6, 0x29, 0x31, 0xcd, 0x4a,
+ 0x73, 0x98, 0xa2, 0xe8, 0xe5, 0x0d, 0x7b, 0xfe, 0x07, 0x07, 0xf6, 0x86,
+ 0x71, 0x62, 0xff, 0xe6, 0xec, 0x42, 0x60, 0xc7, 0xf7, 0x35, 0x62, 0xfe,
+ 0x79, 0x39, 0x4c, 0x4b, 0x17, 0xf4, 0xc9, 0xca, 0x62, 0x58, 0xbe, 0x92,
+ 0x17, 0x3e, 0x7b, 0x5c, 0x2d, 0xa9, 0x4c, 0x51, 0xce, 0xbf, 0x0a, 0x2b,
+ 0x12, 0xc5, 0xfe, 0x81, 0x67, 0x62, 0xce, 0x2c, 0x56, 0x1e, 0x2b, 0x08,
+ 0xdf, 0xfc, 0x23, 0xfc, 0xb3, 0xaf, 0x13, 0x7d, 0x62, 0xff, 0xfd, 0x02,
+ 0x6f, 0x31, 0xf9, 0x23, 0x9f, 0xcc, 0x16, 0x2b, 0x88, 0x99, 0x0d, 0x16,
+ 0xec, 0xe2, 0xc5, 0xe6, 0x6d, 0xd5, 0x21, 0x69, 0x50, 0x3e, 0x5c, 0x24,
+ 0xdc, 0x5e, 0xff, 0xfe, 0xfb, 0x61, 0x37, 0xb9, 0xcd, 0xfe, 0xfd, 0xa7,
+ 0x8b, 0x17, 0xde, 0x26, 0x35, 0x62, 0xfd, 0x3a, 0xce, 0xbc, 0xb1, 0x67,
+ 0xd2, 0x2a, 0x7e, 0xba, 0x02, 0x3b, 0xd1, 0xe4, 0x35, 0x8b, 0xf3, 0x9b,
+ 0xed, 0x4a, 0xc5, 0xb8, 0xb1, 0x7e, 0x63, 0xfa, 0x60, 0xb1, 0x78, 0xdc,
+ 0x1a, 0xc5, 0x68, 0xf6, 0x18, 0x48, 0x45, 0x17, 0xff, 0xfd, 0xfc, 0xd4,
+ 0xf6, 0x0f, 0x4c, 0x0c, 0xd6, 0x9c, 0xd9, 0xd2, 0xc5, 0xf8, 0x29, 0xec,
+ 0xdf, 0x58, 0xbf, 0xde, 0x63, 0xb4, 0x1b, 0x4b, 0x15, 0x27, 0xbc, 0xe5,
+ 0x77, 0xb8, 0x1f, 0x96, 0x2a, 0x0b, 0x8f, 0x43, 0x79, 0xd4, 0x63, 0xdf,
+ 0x86, 0xc3, 0x1a, 0x91, 0x07, 0x21, 0x03, 0xe2, 0xee, 0xd0, 0xc8, 0x0c,
+ 0x82, 0xff, 0xfc, 0x2e, 0xf8, 0x66, 0x1c, 0x9b, 0xaf, 0x18, 0x67, 0xe3,
+ 0x96, 0x2e, 0xf7, 0x96, 0x2f, 0xff, 0x85, 0xee, 0x0f, 0xf3, 0xc9, 0xf8,
+ 0xa7, 0x8b, 0x17, 0xff, 0xcd, 0xfc, 0x2d, 0x6b, 0x3a, 0x87, 0x9c, 0xeb,
+ 0x15, 0x29, 0x8e, 0xc1, 0x90, 0xd1, 0x81, 0x28, 0xdd, 0xbc, 0xac, 0x5d,
+ 0xfc, 0x58, 0xbe, 0x3b, 0x85, 0xc5, 0x8b, 0xff, 0xff, 0xd9, 0x91, 0x44,
+ 0xcd, 0xb7, 0x3f, 0x9d, 0xb0, 0x7f, 0x9e, 0x0c, 0x6c, 0xb1, 0x7f, 0xf8,
+ 0xd7, 0xd7, 0xba, 0xdd, 0xf0, 0x28, 0x6c, 0xb1, 0x47, 0x47, 0x78, 0x09,
+ 0x3c, 0xf7, 0x7f, 0xcc, 0x19, 0x64, 0x5a, 0x90, 0x96, 0x29, 0xcf, 0xac,
+ 0x46, 0x17, 0x10, 0x4b, 0x15, 0x89, 0xe1, 0x6e, 0x31, 0xf8, 0xdc, 0x42,
+ 0x21, 0xbf, 0x8e, 0xfd, 0x72, 0x7a, 0x58, 0xbf, 0xf6, 0x17, 0x84, 0xc3,
+ 0xe4, 0x9a, 0xb1, 0x7f, 0xa4, 0x2e, 0x03, 0xde, 0xe9, 0x62, 0xa4, 0xfd,
+ 0xbc, 0x7f, 0x7f, 0x48, 0xfa, 0xe4, 0xc4, 0xb1, 0x52, 0x8f, 0x78, 0x42,
+ 0x9b, 0x84, 0x37, 0x37, 0x65, 0x8b, 0xe9, 0xdc, 0xe2, 0x58, 0xa7, 0x37,
+ 0xa4, 0x33, 0x73, 0xfd, 0x62, 0x86, 0x6d, 0xbb, 0x0f, 0xdf, 0xba, 0x1e,
+ 0x9a, 0x0b, 0x17, 0xed, 0x0f, 0x24, 0x0b, 0x17, 0xf0, 0x0b, 0x36, 0x0e,
+ 0x0b, 0x14, 0xe7, 0xb0, 0x22, 0x8b, 0xc2, 0x9d, 0x96, 0x2f, 0x9f, 0x4d,
+ 0x05, 0x8b, 0xd3, 0xee, 0x1c, 0xf0, 0x3e, 0x3d, 0x52, 0x98, 0xb7, 0xe1,
+ 0x04, 0x4c, 0x37, 0xfe, 0x2f, 0x7f, 0x20, 0x14, 0xf5, 0xc5, 0x8b, 0xfe,
+ 0xeb, 0x9e, 0x7d, 0xb6, 0x7f, 0x2c, 0x5f, 0xf1, 0x14, 0x9b, 0xad, 0x38,
+ 0x4b, 0x17, 0xff, 0xb6, 0x1e, 0x9b, 0x72, 0xce, 0xda, 0x7e, 0x2c, 0x54,
+ 0xa3, 0x17, 0x0f, 0x44, 0x75, 0x7f, 0xf1, 0x7b, 0xed, 0x03, 0x5b, 0xc2,
+ 0x65, 0x8b, 0x87, 0x2b, 0x15, 0x29, 0xc8, 0x6a, 0x30, 0x66, 0x2e, 0x24,
+ 0x5b, 0x80, 0xcb, 0x17, 0xf6, 0xfa, 0xc8, 0x47, 0x62, 0xc5, 0x39, 0xe4,
+ 0x88, 0x5e, 0xff, 0x3f, 0x67, 0xec, 0x77, 0xf2, 0xc5, 0x86, 0xb1, 0x7f,
+ 0xb9, 0x3a, 0x8a, 0x27, 0xfa, 0xc5, 0xfb, 0x34, 0x29, 0x02, 0xc5, 0x0c,
+ 0xfc, 0x38, 0x24, 0x11, 0xb5, 0xfd, 0xa9, 0x3e, 0x11, 0xd6, 0x2f, 0xf1,
+ 0x3f, 0x1c, 0xba, 0x82, 0xc5, 0x68, 0xf8, 0x02, 0x2d, 0xb9, 0xf6, 0x58,
+ 0xbf, 0x7f, 0x00, 0x19, 0xd6, 0x2f, 0x1c, 0x0e, 0xb1, 0x7f, 0x69, 0xb8,
+ 0xd9, 0xf5, 0x8a, 0x63, 0xca, 0x10, 0xed, 0x71, 0x12, 0xbe, 0x74, 0xba,
+ 0x63, 0xd6, 0x2f, 0xf6, 0x72, 0x2f, 0xb8, 0x5e, 0x58, 0xbf, 0xf8, 0x8a,
+ 0x7a, 0xfb, 0xfb, 0x82, 0x8f, 0x58, 0xa9, 0x3f, 0xe7, 0x36, 0xbf, 0x8f,
+ 0x31, 0x81, 0x04, 0x12, 0xc5, 0xb8, 0xb1, 0x52, 0x78, 0xec, 0x6b, 0x43,
+ 0x4f, 0xbd, 0xe1, 0x5a, 0x72, 0x3e, 0x42, 0x63, 0xb9, 0x9e, 0xa5, 0x5d,
+ 0x06, 0x42, 0x9d, 0xe1, 0x20, 0xd2, 0x84, 0xaf, 0xf8, 0xf9, 0xad, 0x3f,
+ 0x66, 0xdd, 0x62, 0xfe, 0xcc, 0x1f, 0x69, 0xfa, 0xc5, 0xfe, 0x7f, 0xe6,
+ 0xec, 0xfb, 0x2c, 0x5f, 0xfd, 0xbe, 0xa4, 0xd9, 0x2f, 0x46, 0xa8, 0xd5,
+ 0xde, 0x2c, 0x5b, 0xb9, 0x62, 0xf7, 0x7a, 0x43, 0x58, 0xbf, 0x8e, 0x2f,
+ 0x8c, 0x6c, 0xb1, 0x7f, 0x6b, 0x3e, 0xfd, 0x12, 0xc5, 0xf1, 0xa0, 0x9f,
+ 0x2c, 0x5b, 0xf2, 0x7a, 0x4e, 0x5d, 0x7f, 0xe2, 0xcd, 0xbf, 0x9d, 0xde,
+ 0x7d, 0x2c, 0x5f, 0xdf, 0x21, 0x31, 0xbb, 0xac, 0x5f, 0xf6, 0x67, 0x3d,
+ 0xfc, 0xde, 0x56, 0x2f, 0xfd, 0x9e, 0x35, 0xf7, 0xf7, 0x33, 0x65, 0x8b,
+ 0xfa, 0x75, 0x83, 0x68, 0x2c, 0x56, 0xc9, 0xe0, 0x8e, 0x10, 0x3b, 0x93,
+ 0x3a, 0x14, 0x46, 0x1d, 0x8e, 0x43, 0x42, 0xb8, 0xb8, 0xb1, 0x7f, 0x63,
+ 0x77, 0xff, 0x6d, 0x96, 0x2a, 0x55, 0x84, 0xc1, 0x60, 0x62, 0xb9, 0x1f,
+ 0x19, 0x37, 0x88, 0x5e, 0xff, 0xb7, 0x0f, 0xcf, 0x00, 0xb3, 0xeb, 0x17,
+ 0xff, 0xfe, 0x7f, 0x49, 0xc9, 0x8d, 0xfb, 0xfa, 0x61, 0x14, 0x27, 0x5b,
+ 0x2c, 0x5f, 0xf1, 0x4e, 0x6d, 0xee, 0x66, 0xcb, 0x17, 0xff, 0x71, 0xc2,
+ 0xf7, 0x30, 0xe5, 0x21, 0x2c, 0x5f, 0xfe, 0x62, 0x90, 0x4f, 0xdf, 0x42,
+ 0x63, 0xac, 0x5f, 0xfe, 0x70, 0x6a, 0x60, 0xfc, 0xe4, 0xea, 0x0b, 0x17,
+ 0xff, 0x73, 0x22, 0x29, 0x3e, 0xb5, 0x3d, 0x2c, 0x56, 0x91, 0x21, 0xe4,
+ 0xab, 0xfe, 0x17, 0x7e, 0x3c, 0xf7, 0x33, 0xeb, 0x15, 0x27, 0xc4, 0xc4,
+ 0x75, 0xd2, 0x74, 0x1a, 0x46, 0xf4, 0x67, 0x57, 0xfd, 0xbe, 0x16, 0x6d,
+ 0xb0, 0x89, 0x62, 0xd1, 0xeb, 0x17, 0xda, 0xe6, 0x04, 0xb1, 0x7e, 0x22,
+ 0x9e, 0x83, 0x93, 0x73, 0x82, 0xb7, 0xff, 0x6a, 0x4d, 0x92, 0x9d, 0xe5,
+ 0xfe, 0xb1, 0x7f, 0xee, 0xd8, 0x3f, 0xcf, 0x06, 0x36, 0x58, 0xbf, 0x9f,
+ 0x9a, 0xd4, 0xc1, 0x62, 0xf1, 0x34, 0x16, 0x2f, 0xcf, 0x1d, 0x80, 0x95,
+ 0x8b, 0xf7, 0x85, 0xa6, 0xe6, 0x1e, 0x37, 0x87, 0x29, 0x61, 0xcd, 0xf5,
+ 0x62, 0x61, 0xdb, 0xa0, 0xb4, 0x2c, 0xaf, 0xfb, 0x6f, 0xe7, 0xb8, 0x4f,
+ 0x12, 0xc5, 0xfc, 0xf8, 0x5d, 0x43, 0x8b, 0x17, 0xdb, 0x1c, 0x46, 0xac,
+ 0x5f, 0xfe, 0xe3, 0xf4, 0x16, 0x6f, 0x24, 0x26, 0x82, 0xc5, 0xb3, 0x64,
+ 0x50, 0x68, 0xb8, 0x04, 0xd7, 0xff, 0xfb, 0x08, 0x63, 0x90, 0x38, 0x67,
+ 0xe3, 0xfa, 0x7a, 0x09, 0x62, 0xff, 0x8b, 0xdc, 0xf6, 0x60, 0x5c, 0x58,
+ 0xb9, 0xbe, 0xb1, 0x58, 0x7a, 0x3d, 0x1d, 0x5f, 0xfd, 0xf7, 0xf7, 0x3e,
+ 0xf8, 0x22, 0xf2, 0xc5, 0xff, 0xfa, 0x28, 0x48, 0x35, 0x9b, 0xcc, 0x1f,
+ 0x4f, 0xc5, 0x8b, 0xf3, 0x03, 0x90, 0x95, 0x8a, 0x94, 0x72, 0xc0, 0x8b,
+ 0x11, 0x09, 0x5e, 0xfe, 0x9e, 0x98, 0x7f, 0xc5, 0x8b, 0xff, 0xda, 0xf0,
+ 0x98, 0x32, 0xf7, 0xc4, 0xd0, 0x58, 0xbe, 0xfc, 0x6f, 0xdf, 0x23, 0x5a,
+ 0xc5, 0x4a, 0x20, 0x71, 0x32, 0xa5, 0x91, 0x51, 0x03, 0xd1, 0xb7, 0x64,
+ 0x7b, 0x5b, 0x9c, 0x3b, 0xa6, 0x8f, 0x3f, 0x1a, 0x93, 0x1a, 0x94, 0x36,
+ 0xf8, 0x6d, 0xe8, 0xe6, 0x44, 0x74, 0x14, 0x2b, 0xef, 0xd1, 0x42, 0x75,
+ 0xb2, 0xc5, 0xe8, 0xd3, 0x3b, 0x2c, 0x54, 0x0f, 0x3d, 0x8a, 0xef, 0xfd,
+ 0x9e, 0x62, 0x03, 0x1c, 0xee, 0xb1, 0x7f, 0x49, 0x40, 0x1d, 0x80, 0xb1,
+ 0x7b, 0x77, 0xd9, 0x62, 0xff, 0xff, 0xc2, 0xfe, 0x0f, 0xdf, 0xc3, 0xe7,
+ 0xfe, 0xcf, 0xe9, 0xf7, 0x16, 0x2f, 0xfa, 0x7c, 0xf0, 0x7d, 0x69, 0xd6,
+ 0x2f, 0xfc, 0x44, 0xc6, 0x87, 0xad, 0x37, 0x4b, 0x17, 0xb9, 0x84, 0xb1,
+ 0x7f, 0xba, 0xfe, 0x0f, 0x4d, 0xba, 0xc5, 0x62, 0x24, 0xdd, 0x05, 0x87,
+ 0x2a, 0x55, 0x08, 0xc0, 0x84, 0xd3, 0xde, 0x8c, 0x1c, 0x7c, 0x9b, 0x39,
+ 0x0c, 0xbb, 0xff, 0xd8, 0x3f, 0xe3, 0x91, 0x66, 0xec, 0x4b, 0x17, 0x67,
+ 0x72, 0xc5, 0xf8, 0x32, 0x2c, 0x8f, 0x58, 0xa9, 0x44, 0x61, 0xa8, 0xe1,
+ 0x8d, 0x5f, 0xed, 0x10, 0xba, 0xf1, 0x4a, 0xc5, 0xbb, 0xc5, 0x8b, 0x77,
+ 0x2c, 0x54, 0x9f, 0x00, 0x0d, 0x3b, 0x85, 0xee, 0xce, 0x92, 0x2d, 0x29,
+ 0x16, 0x06, 0x8d, 0x48, 0x06, 0x2f, 0xf7, 0xb3, 0x40, 0x3b, 0xf1, 0x22,
+ 0x30, 0xd3, 0xdc, 0x71, 0xac, 0x5f, 0xff, 0xb7, 0xfb, 0x17, 0xb9, 0xa9,
+ 0x17, 0x89, 0xfb, 0x2c, 0x5f, 0xbe, 0xfd, 0xb2, 0x25, 0x8a, 0xd9, 0x10,
+ 0x70, 0x58, 0xa9, 0x4c, 0x19, 0xd1, 0xda, 0x13, 0x77, 0xf4, 0x1c, 0xbd,
+ 0x20, 0x58, 0xa5, 0x8b, 0xc3, 0x14, 0xc4, 0x6e, 0x40, 0x5b, 0x7c, 0x53,
+ 0xd7, 0x16, 0x2b, 0x47, 0xad, 0xd8, 0xce, 0xff, 0xff, 0xfa, 0x4b, 0x76,
+ 0xf3, 0x74, 0x0f, 0x73, 0x08, 0x98, 0xd0, 0xf5, 0xa6, 0xe9, 0x62, 0xfa,
+ 0x40, 0x7c, 0x58, 0xa0, 0x22, 0x8b, 0xd0, 0x80, 0xbf, 0xe1, 0xf3, 0x99,
+ 0xa1, 0xff, 0x16, 0x2f, 0xff, 0x77, 0x7a, 0x42, 0x9e, 0x7d, 0xbb, 0x60,
+ 0xd6, 0x2f, 0xef, 0xbe, 0xf2, 0x77, 0x58, 0xbf, 0xd8, 0x76, 0xe8, 0xd8,
+ 0x74, 0xb1, 0x7f, 0xd8, 0x37, 0xe0, 0xd9, 0x82, 0x58, 0xbd, 0xef, 0x36,
+ 0x8f, 0xc0, 0x06, 0xf7, 0xfa, 0x41, 0xb3, 0x42, 0x63, 0xd6, 0x2f, 0xff,
+ 0xee, 0x3f, 0xbf, 0x83, 0xcd, 0xe7, 0xce, 0x59, 0xd2, 0xc5, 0x4a, 0x6c,
+ 0x79, 0x09, 0xe2, 0x33, 0xf1, 0xbd, 0xff, 0xf8, 0xb0, 0x0c, 0x40, 0x0c,
+ 0xfe, 0x13, 0x6d, 0x2b, 0x15, 0x8a, 0xdc, 0x7a, 0x86, 0x33, 0x94, 0x44,
+ 0x74, 0x51, 0xd9, 0xf9, 0x02, 0xf7, 0x9f, 0x4b, 0x16, 0x8c, 0x8d, 0xdd,
+ 0x79, 0xbf, 0x78, 0x3d, 0x1a, 0xc6, 0x26, 0x36, 0x3d, 0xa1, 0x37, 0x08,
+ 0x43, 0x0e, 0x3c, 0xfc, 0x9d, 0xcd, 0x36, 0x3c, 0x1d, 0xe5, 0x00, 0x75,
+ 0x19, 0xe3, 0xc2, 0x9e, 0x28, 0xce, 0x75, 0x1e, 0x21, 0xe1, 0x15, 0xf9,
+ 0x78, 0x2c, 0x98, 0x03, 0xce, 0xfc, 0xbc, 0xa5, 0x9e, 0xf2, 0x92, 0x09,
+ 0xe9, 0x67, 0x82, 0x87, 0xb0, 0x50, 0x91, 0x8e, 0x8e, 0x1c, 0x39, 0xc3,
+ 0x3e, 0xe6, 0x3b, 0xff, 0xff, 0x98, 0xf1, 0x8f, 0xad, 0x0b, 0x5a, 0x92,
+ 0xc3, 0x5f, 0xff, 0xc0, 0xd6, 0x2f, 0x0b, 0xd8, 0xb1, 0x7f, 0xe2, 0xce,
+ 0xb7, 0x9f, 0xe6, 0xb1, 0x62, 0xb4, 0x7b, 0x9e, 0x1d, 0xbf, 0xc2, 0xea,
+ 0x36, 0xe1, 0xdf, 0x8b, 0x17, 0xff, 0x1a, 0x14, 0x7e, 0xc3, 0x8d, 0x8c,
+ 0x33, 0xf1, 0xcb, 0x17, 0xe9, 0xd9, 0xb5, 0xba, 0xc5, 0xcf, 0xd9, 0x62,
+ 0xf4, 0xfb, 0x8b, 0x17, 0xb8, 0x23, 0xe8, 0xf8, 0x00, 0x54, 0x43, 0x35,
+ 0x1a, 0x91, 0xf0, 0xf0, 0xb8, 0xbf, 0xd8, 0x0e, 0x66, 0xec, 0x35, 0x8b,
+ 0xf1, 0x30, 0x5c, 0xe2, 0xc5, 0x61, 0xee, 0xe8, 0xd2, 0xf8, 0x5e, 0xc2,
+ 0x58, 0xbe, 0xdd, 0x9b, 0x75, 0x49, 0x44, 0x5e, 0x36, 0x78, 0xb1, 0x7f,
+ 0x7e, 0x7d, 0x3d, 0x04, 0xb1, 0x67, 0x58, 0xbe, 0x28, 0x39, 0xd6, 0x2f,
+ 0xd0, 0xc2, 0x71, 0xac, 0x56, 0x22, 0xa1, 0xc7, 0xbe, 0x60, 0xc2, 0x3e,
+ 0x22, 0xbf, 0xc4, 0x26, 0x80, 0x87, 0x8b, 0x17, 0xe7, 0x21, 0xb6, 0xeb,
+ 0x15, 0xb2, 0x73, 0xba, 0x22, 0x3c, 0x36, 0x78, 0x8f, 0xd8, 0xce, 0xfb,
+ 0xf9, 0xac, 0x58, 0xbc, 0xf1, 0x77, 0x2c, 0x5f, 0x66, 0xc7, 0xf2, 0xc5,
+ 0x49, 0xf3, 0xfc, 0x88, 0x88, 0x6f, 0x49, 0x6e, 0xb1, 0x7c, 0xdf, 0x9f,
+ 0xac, 0x5e, 0x7c, 0x09, 0x62, 0xf1, 0xf9, 0x2b, 0x15, 0xb1, 0xfc, 0xee,
+ 0x3b, 0x1e, 0x44, 0x21, 0xdb, 0x6c, 0xb1, 0x7f, 0x7d, 0x88, 0x61, 0xf4,
+ 0xb1, 0x7f, 0xfc, 0xc6, 0x99, 0xe3, 0x64, 0xa1, 0x9f, 0x73, 0xac, 0x58,
+ 0x52, 0x89, 0x57, 0x13, 0x23, 0x0b, 0x84, 0x1a, 0xc5, 0xe1, 0xc9, 0xd6,
+ 0x2f, 0x8d, 0x0c, 0xb7, 0x58, 0xa1, 0x9e, 0x19, 0xa3, 0xb7, 0xda, 0x79,
+ 0x3a, 0xc5, 0xff, 0xf4, 0x36, 0x8d, 0x53, 0x1a, 0x6d, 0xbe, 0x8c, 0x33,
+ 0xf1, 0xcb, 0x17, 0xf3, 0x37, 0x5f, 0xcc, 0x58, 0xa9, 0x4c, 0xd1, 0xd7,
+ 0x18, 0x8c, 0x04, 0x44, 0xcd, 0x7e, 0xd3, 0xee, 0xfd, 0x96, 0x2f, 0x4e,
+ 0x12, 0xc5, 0xfc, 0xe7, 0x1e, 0x9b, 0x75, 0x8a, 0x19, 0xe5, 0x7c, 0x6e,
+ 0xfc, 0xc6, 0xe7, 0xd9, 0x62, 0xb0, 0xf2, 0x84, 0x45, 0x7f, 0xff, 0x08,
+ 0x98, 0xd3, 0x3c, 0x6c, 0x94, 0x33, 0xee, 0x75, 0x8b, 0xed, 0x6b, 0x23,
+ 0x96, 0x28, 0xe8, 0x83, 0x65, 0xdb, 0xfd, 0x25, 0x01, 0xfd, 0xce, 0xb1,
+ 0x7f, 0xff, 0xde, 0xcf, 0x66, 0x80, 0x76, 0x84, 0xf1, 0xf8, 0xfd, 0x79,
+ 0x62, 0xf6, 0xcc, 0x4b, 0x15, 0x88, 0x84, 0x13, 0x3d, 0x1a, 0x8d, 0x9e,
+ 0x42, 0xde, 0xff, 0xb3, 0xad, 0xc9, 0xb3, 0xad, 0xd6, 0x2f, 0xf7, 0x5b,
+ 0x93, 0x67, 0x5b, 0xac, 0x5f, 0x9a, 0x05, 0x3c, 0x30, 0xfc, 0xf0, 0xf2,
+ 0xf6, 0xc2, 0xf2, 0xc5, 0xdb, 0x0d, 0x62, 0xb0, 0xdc, 0x30, 0xfd, 0xf0,
+ 0x59, 0xf6, 0x58, 0xbe, 0x29, 0xce, 0x96, 0x2a, 0x4f, 0x17, 0xc4, 0x77,
+ 0x86, 0xfd, 0x96, 0x2d, 0x19, 0x2c, 0xb9, 0x4d, 0x88, 0xa1, 0x19, 0x98,
+ 0xe1, 0x15, 0x91, 0xdf, 0x6f, 0x0b, 0xa7, 0x85, 0x31, 0xe1, 0xad, 0xf8,
+ 0xd9, 0xd9, 0x1c, 0xa1, 0x7f, 0xc8, 0x52, 0x7a, 0x1f, 0x7d, 0xa1, 0x39,
+ 0x1c, 0xea, 0x1b, 0x27, 0x71, 0x0d, 0xed, 0xe0, 0x75, 0x8b, 0xdf, 0x98,
+ 0xf5, 0x8b, 0xe2, 0x60, 0xbe, 0xb1, 0x7e, 0xe0, 0x98, 0x80, 0xb1, 0x7d,
+ 0x84, 0xfe, 0x58, 0xbd, 0xfc, 0x02, 0xc5, 0xec, 0x3c, 0x64, 0xa3, 0x21,
+ 0xc7, 0xe2, 0x20, 0xf1, 0x1c, 0x71, 0x47, 0x71, 0x0d, 0xff, 0x7d, 0xf5,
+ 0xf6, 0xe6, 0x06, 0xb1, 0x70, 0xc9, 0x62, 0xfe, 0x80, 0xf4, 0xe2, 0xd9,
+ 0x62, 0xfd, 0xac, 0xe6, 0x04, 0xb1, 0x7f, 0xa7, 0xcd, 0xf3, 0x07, 0x2b,
+ 0x17, 0xe8, 0xa7, 0xe2, 0xd9, 0x62, 0xfc, 0xd0, 0xf3, 0xec, 0xb1, 0x58,
+ 0x7a, 0x8e, 0x57, 0x79, 0xbc, 0xeb, 0x17, 0x4c, 0x66, 0x26, 0xdd, 0xd1,
+ 0xd3, 0x8b, 0xe8, 0xc0, 0xe5, 0x3f, 0x84, 0x47, 0x08, 0x28, 0x6a, 0x95,
+ 0x79, 0x1e, 0xf5, 0xec, 0x0b, 0x16, 0x2f, 0x98, 0xe5, 0x2b, 0x17, 0xff,
+ 0x39, 0x4f, 0x9f, 0x4e, 0x7c, 0x1a, 0xc5, 0x11, 0xf1, 0xf7, 0x10, 0xdd,
+ 0x3b, 0x2c, 0x56, 0x1b, 0xc1, 0x12, 0x5c, 0x2f, 0xac, 0x5f, 0xcd, 0x0e,
+ 0xb9, 0x3b, 0x2c, 0x5e, 0xd9, 0x82, 0x58, 0xbe, 0xe7, 0xda, 0x0b, 0x15,
+ 0xb1, 0xe1, 0x30, 0xfd, 0xff, 0x37, 0x45, 0x9d, 0xb4, 0xfc, 0x58, 0xbf,
+ 0x3c, 0xc1, 0xa0, 0xb1, 0x5b, 0x26, 0x1c, 0x31, 0x8d, 0x39, 0x1c, 0x8b,
+ 0xe7, 0x77, 0xf6, 0x6c, 0x39, 0xc1, 0xac, 0x5f, 0xe6, 0xfb, 0x61, 0xdf,
+ 0x8b, 0x17, 0xc3, 0xfb, 0xc4, 0xb1, 0x60, 0x96, 0x2b, 0x11, 0x2e, 0x69,
+ 0x73, 0x19, 0x78, 0x92, 0xfc, 0x4d, 0xdd, 0x9b, 0x2c, 0x5f, 0xf0, 0x24,
+ 0xb3, 0xdc, 0x93, 0xac, 0x5e, 0x09, 0xbe, 0xb1, 0x74, 0x8d, 0x62, 0xa4,
+ 0xda, 0xfc, 0x7a, 0xf1, 0x4c, 0x7a, 0xc5, 0xff, 0x67, 0xbe, 0xdb, 0xc9,
+ 0x0d, 0x62, 0xff, 0x17, 0xb9, 0xac, 0x93, 0xac, 0x54, 0x9f, 0x63, 0x1c,
+ 0xdf, 0x9c, 0x88, 0x51, 0xeb, 0x17, 0xfd, 0xcc, 0x1e, 0x6a, 0x13, 0xa5,
+ 0x8a, 0x93, 0xe3, 0xd1, 0x55, 0xb6, 0x58, 0xa9, 0x36, 0x98, 0x43, 0x7f,
+ 0x67, 0xfe, 0x22, 0xd9, 0x62, 0xf4, 0xe8, 0xd5, 0x8b, 0xb3, 0x4b, 0x15,
+ 0xb9, 0xb5, 0xf0, 0xf5, 0xfa, 0x0d, 0xe8, 0x32, 0xc5, 0xf4, 0x80, 0x12,
+ 0xb1, 0x7f, 0xa7, 0x5b, 0x61, 0xf0, 0xeb, 0x15, 0x27, 0xfc, 0x45, 0x1c,
+ 0x22, 0xbf, 0xe2, 0x1e, 0x68, 0x6c, 0xc3, 0x58, 0xb0, 0x96, 0x2a, 0x4f,
+ 0x29, 0x8e, 0x29, 0x62, 0xc4, 0xb1, 0xb1, 0x32, 0xfd, 0xb6, 0x99, 0xbc,
+ 0xb1, 0x4e, 0x79, 0x2c, 0x41, 0x71, 0xc6, 0xb1, 0x7d, 0xf7, 0xfc, 0x67,
+ 0x7a, 0xbe, 0x94, 0x38, 0x5e, 0x64, 0x65, 0xc6, 0xc3, 0x8f, 0x73, 0xc7,
+ 0x2b, 0x89, 0xb7, 0x44, 0x07, 0x84, 0x5f, 0xe1, 0x6e, 0x43, 0xfc, 0x64,
+ 0xf4, 0x28, 0x02, 0x77, 0x8e, 0x75, 0xee, 0x20, 0xbd, 0xcc, 0x25, 0x8b,
+ 0xed, 0xd9, 0xb7, 0x54, 0x97, 0xa5, 0xff, 0xd2, 0x01, 0xfe, 0x79, 0x87,
+ 0x98, 0xf5, 0x8a, 0xd1, 0xfc, 0x1c, 0xc6, 0xfc, 0xfd, 0xdb, 0x8b, 0x65,
+ 0x8b, 0x41, 0x62, 0xc7, 0x58, 0xbc, 0x53, 0x05, 0x8a, 0x93, 0xc0, 0x61,
+ 0x2f, 0x09, 0x5d, 0x20, 0x58, 0xbd, 0xf9, 0xe9, 0x62, 0xe9, 0xe9, 0x62,
+ 0xf7, 0x1c, 0xd5, 0x8a, 0x34, 0xf5, 0x3e, 0x3d, 0xe1, 0x8b, 0xec, 0xf3,
+ 0xec, 0xb1, 0x7f, 0x6c, 0x1c, 0x73, 0x10, 0x16, 0x2f, 0xfc, 0xc4, 0x0c,
+ 0xf4, 0x93, 0x81, 0x62, 0xa4, 0xfb, 0xe3, 0x8c, 0xed, 0x19, 0x05, 0x54,
+ 0x59, 0x09, 0x4d, 0x11, 0x33, 0x70, 0x0b, 0x44, 0xd7, 0x1c, 0x60, 0x1c,
+ 0x24, 0xaf, 0xc7, 0xf7, 0x1b, 0xa5, 0x8b, 0xfe, 0x84, 0x66, 0x6b, 0x76,
+ 0x6d, 0xd5, 0x22, 0x31, 0x7f, 0xec, 0xf1, 0x30, 0x30, 0xb3, 0x4b, 0x17,
+ 0xff, 0xde, 0xeb, 0x77, 0xd1, 0x9a, 0x9d, 0x9b, 0x5b, 0xac, 0x5a, 0x32,
+ 0x53, 0x07, 0x62, 0xa2, 0x4b, 0xe1, 0xe5, 0xff, 0xe8, 0xc3, 0xb4, 0x23,
+ 0x33, 0x5b, 0xb3, 0x6e, 0xa9, 0x1e, 0x0b, 0xf6, 0xb7, 0x66, 0xdd, 0x52,
+ 0x3f, 0x97, 0x76, 0x75, 0x8b, 0xf4, 0x61, 0xda, 0x11, 0x98, 0x7a, 0x0e,
+ 0x6f, 0x7f, 0xfa, 0x30, 0xed, 0x08, 0xcc, 0xd6, 0xec, 0xdb, 0xaa, 0x48,
+ 0x62, 0xff, 0xfe, 0xc3, 0xcc, 0x23, 0x03, 0x29, 0x1f, 0xf3, 0x7c, 0xd2,
+ 0xc5, 0xfb, 0x5b, 0xb3, 0x6e, 0xa9, 0x22, 0x0b, 0xe9, 0x29, 0xe9, 0x62,
+ 0xf3, 0x42, 0x33, 0x0f, 0x66, 0x3c, 0xde, 0xfe, 0x6d, 0xe3, 0x00, 0xfb,
+ 0x2c, 0x51, 0xcf, 0xaf, 0xb1, 0xc5, 0xff, 0xa1, 0x18, 0x2e, 0x19, 0x3c,
+ 0x98, 0x2c, 0x54, 0x61, 0xf4, 0x49, 0x25, 0xff, 0xa2, 0x7f, 0xf5, 0x9e,
+ 0x1e, 0x1d, 0x62, 0xff, 0xf3, 0x46, 0x0d, 0x89, 0xb7, 0x30, 0x36, 0x3a,
+ 0xc5, 0xfc, 0xfe, 0x7d, 0x30, 0x16, 0x2f, 0xf0, 0xbd, 0xf9, 0x29, 0xf2,
+ 0xc5, 0xf6, 0x7b, 0x00, 0xb1, 0x7e, 0x21, 0x34, 0x38, 0xb1, 0x63, 0xac,
+ 0x5f, 0xf7, 0x6c, 0xea, 0x1a, 0x66, 0x82, 0xc5, 0xe2, 0x68, 0xc8, 0x23,
+ 0xe3, 0x45, 0xa4, 0x67, 0xe2, 0x28, 0xe2, 0x80, 0xc4, 0xaf, 0xe8, 0xa3,
+ 0x38, 0x53, 0xb2, 0xc5, 0xf4, 0x94, 0xfd, 0x62, 0xfb, 0x35, 0x27, 0x58,
+ 0xa1, 0x9e, 0x1f, 0xc8, 0x6f, 0xff, 0xdf, 0xc2, 0xc3, 0x7e, 0xd0, 0xf8,
+ 0x4c, 0x19, 0xd6, 0x2f, 0x33, 0x6e, 0xa9, 0x24, 0x4b, 0xe8, 0x61, 0x6c,
+ 0xb1, 0x5b, 0x9e, 0x6c, 0x45, 0x55, 0x04, 0x64, 0xea, 0x14, 0xb7, 0xe1,
+ 0x78, 0xa7, 0xeb, 0x17, 0xfe, 0xec, 0xda, 0xe3, 0x7f, 0x93, 0xb2, 0xc5,
+ 0xfa, 0x62, 0xd4, 0x9d, 0x62, 0xbe, 0x7d, 0x7c, 0x42, 0xbf, 0xf9, 0xba,
+ 0xe7, 0xc2, 0x90, 0x18, 0x19, 0xd6, 0x2f, 0xf4, 0x27, 0x5b, 0x4e, 0xb6,
+ 0x58, 0xbf, 0xfb, 0xdc, 0x93, 0x96, 0x0f, 0xf9, 0xe5, 0x8b, 0xfe, 0x9e,
+ 0xd9, 0xa6, 0xd9, 0xb8, 0xb1, 0x4b, 0x14, 0x61, 0xe3, 0x88, 0xee, 0xa5,
+ 0x1c, 0x98, 0x6c, 0x08, 0x45, 0xdf, 0xb3, 0xf2, 0x50, 0x58, 0xbf, 0xfb,
+ 0x3f, 0xe2, 0x90, 0x61, 0x34, 0x16, 0x28, 0xe7, 0xd2, 0x44, 0xf7, 0xff,
+ 0xdf, 0x9f, 0x70, 0xc0, 0xdb, 0xcd, 0xa6, 0xee, 0x58, 0xbe, 0xe0, 0x3c,
+ 0xcb, 0x17, 0x14, 0x8c, 0xfe, 0x0e, 0xab, 0x7f, 0xdf, 0xcd, 0xe4, 0xce,
+ 0x6a, 0x25, 0x8b, 0xfb, 0xc7, 0x7f, 0x7d, 0xd6, 0x2a, 0x07, 0xd6, 0xc7,
+ 0xb6, 0x8c, 0x95, 0xce, 0x3c, 0x87, 0x5c, 0x45, 0x0d, 0x09, 0x30, 0x11,
+ 0x14, 0x65, 0xdc, 0x84, 0xe7, 0xa1, 0x32, 0x1c, 0x25, 0xef, 0xf7, 0x89,
+ 0x8d, 0x3b, 0x41, 0x62, 0xf8, 0x9b, 0xdc, 0x58, 0xb3, 0x41, 0x1f, 0xa3,
+ 0x85, 0x3e, 0xe6, 0x97, 0xfe, 0x8c, 0x9f, 0xe6, 0xbb, 0x37, 0xd9, 0x62,
+ 0xe8, 0xdf, 0x75, 0x8b, 0xb0, 0xeb, 0x17, 0xd0, 0xd0, 0xb7, 0x58, 0xbf,
+ 0xd2, 0xfb, 0x60, 0xc3, 0x3a, 0xc5, 0xa3, 0x3b, 0xc4, 0x47, 0xc8, 0xf7,
+ 0x42, 0xff, 0x25, 0xbb, 0x3b, 0x2c, 0x5f, 0xfe, 0xdf, 0x3d, 0x25, 0xee,
+ 0x31, 0x0b, 0x16, 0x2d, 0x19, 0xc3, 0xe2, 0x0c, 0x66, 0x86, 0x9d, 0x5b,
+ 0xc3, 0x4b, 0xb4, 0x2b, 0x6f, 0xfe, 0x8c, 0xd3, 0x01, 0xbc, 0xfa, 0xc3,
+ 0xac, 0x5e, 0x07, 0x9d, 0x62, 0xa0, 0x7c, 0x84, 0x8f, 0x7f, 0xee, 0xb9,
+ 0x07, 0xe7, 0x27, 0x50, 0x58, 0xbe, 0x73, 0xb7, 0x72, 0xc5, 0xfe, 0xde,
+ 0x4f, 0xcf, 0x4c, 0x16, 0x2a, 0x4f, 0x69, 0xc9, 0x6e, 0xfe, 0x2c, 0x5d,
+ 0x21, 0x2c, 0x5f, 0xc2, 0xd0, 0x0c, 0x1c, 0x4b, 0x16, 0x8c, 0x82, 0x20,
+ 0x46, 0x41, 0xf1, 0x7e, 0x0c, 0x53, 0x26, 0xc4, 0x08, 0xc7, 0x2f, 0xfd,
+ 0x8e, 0x09, 0x03, 0x10, 0xb1, 0x62, 0xfe, 0x86, 0x7f, 0xed, 0x05, 0x8b,
+ 0xfd, 0x3a, 0x2c, 0xd8, 0x38, 0x2c, 0x5f, 0xc7, 0x7f, 0x7c, 0x46, 0xac,
+ 0x5f, 0xf7, 0xdd, 0x81, 0x22, 0xef, 0xe5, 0x62, 0xf3, 0xc5, 0x19, 0xb2,
+ 0x28, 0xb0, 0xd7, 0xc6, 0x17, 0xfe, 0xde, 0x30, 0x6e, 0x63, 0x16, 0xf2,
+ 0xb1, 0x58, 0x88, 0x96, 0x45, 0xbf, 0xff, 0xb0, 0x7f, 0x90, 0xe3, 0x3c,
+ 0x4c, 0x0e, 0x72, 0x40, 0x91, 0x68, 0xc9, 0x67, 0x49, 0x0d, 0x07, 0x78,
+ 0xd1, 0xfa, 0x6d, 0x3c, 0xf2, 0xb7, 0xe3, 0xe6, 0x68, 0x50, 0x02, 0x38,
+ 0x32, 0x29, 0xf1, 0xe7, 0x68, 0xd6, 0x63, 0x88, 0x6f, 0xfa, 0x63, 0x30,
+ 0x9c, 0xd9, 0xe2, 0xc5, 0xff, 0xee, 0xf6, 0x36, 0x33, 0x07, 0x25, 0xe7,
+ 0xf8, 0x96, 0x2f, 0xff, 0x36, 0xfd, 0x49, 0xaf, 0x3d, 0x0c, 0x5d, 0x2c,
+ 0x5e, 0xe6, 0x71, 0x62, 0xfb, 0x93, 0xd4, 0x16, 0x2f, 0x85, 0xdc, 0x39,
+ 0x58, 0xbf, 0xfd, 0xc1, 0xe3, 0x9a, 0xfc, 0xe4, 0xea, 0x0b, 0x15, 0xba,
+ 0x60, 0x3d, 0x27, 0xc4, 0x3b, 0xf2, 0x4e, 0x13, 0x5f, 0xff, 0xf0, 0xba,
+ 0xe7, 0x33, 0xfa, 0xd6, 0x05, 0x9d, 0x9c, 0xba, 0xf2, 0xc5, 0xff, 0xb2,
+ 0x1f, 0x9d, 0x66, 0x11, 0xab, 0x17, 0xff, 0xdf, 0x9f, 0xb9, 0xbc, 0xe6,
+ 0x10, 0x23, 0xb1, 0x62, 0xf1, 0x03, 0x8b, 0x17, 0xd3, 0xc1, 0xba, 0xc5,
+ 0xf6, 0xec, 0xdb, 0xaa, 0x45, 0x02, 0xff, 0x1d, 0xa1, 0xf9, 0x6d, 0x2c,
+ 0x5f, 0xf0, 0xca, 0x7a, 0x33, 0x9a, 0x95, 0x8b, 0x48, 0x0f, 0xb8, 0x23,
+ 0x3a, 0x82, 0x6b, 0x38, 0xa6, 0x68, 0xee, 0x88, 0x8a, 0x13, 0xf7, 0xff,
+ 0xbe, 0xfb, 0x1c, 0x5a, 0x07, 0x38, 0xc3, 0x58, 0xbf, 0xef, 0xce, 0xa2,
+ 0x7f, 0xcc, 0x4b, 0x17, 0xfc, 0xda, 0xdb, 0x53, 0x06, 0xd2, 0xc5, 0xfe,
+ 0x60, 0x8b, 0x01, 0x20, 0x58, 0xbf, 0xd8, 0x3c, 0x1c, 0x97, 0x96, 0x2a,
+ 0x08, 0x9f, 0x23, 0xae, 0x19, 0xdf, 0xfa, 0x76, 0x2c, 0xe8, 0x0d, 0xd7,
+ 0x16, 0x2f, 0xe6, 0x81, 0x3c, 0x9a, 0xb1, 0x7f, 0x68, 0x03, 0x66, 0xfa,
+ 0xc5, 0xf8, 0x07, 0x68, 0x62, 0xc5, 0x49, 0xeb, 0x61, 0x75, 0xfd, 0xee,
+ 0x4f, 0x0f, 0xdc, 0xb1, 0x67, 0x58, 0xa2, 0x3c, 0x3e, 0xc6, 0x57, 0xff,
+ 0x37, 0x5c, 0xdb, 0x02, 0x11, 0x4f, 0x16, 0x2f, 0xfa, 0x76, 0x3b, 0xeb,
+ 0x82, 0x3a, 0xc5, 0xfe, 0x93, 0xe7, 0x98, 0x5d, 0xfa, 0xc5, 0x7c, 0xfc,
+ 0xf8, 0x77, 0x7f, 0xa7, 0x83, 0xd3, 0x8b, 0x65, 0x8b, 0xfe, 0x60, 0x4e,
+ 0x79, 0x88, 0x0b, 0x16, 0xcf, 0x22, 0x3b, 0xb1, 0x10, 0x46, 0xb7, 0x6a,
+ 0x56, 0x2f, 0xf4, 0x03, 0x86, 0x02, 0x60, 0xb1, 0x43, 0x3c, 0xcd, 0x0b,
+ 0xdf, 0xfd, 0xd7, 0x8b, 0x36, 0x3e, 0x1f, 0x09, 0x62, 0xfa, 0x0f, 0xa8,
+ 0x2c, 0x5e, 0x61, 0xe2, 0xc5, 0xff, 0x71, 0xba, 0x2c, 0xf7, 0xdd, 0x62,
+ 0xff, 0x16, 0x73, 0x5a, 0xce, 0x2c, 0x56, 0x26, 0x24, 0xe4, 0x51, 0x22,
+ 0xf0, 0x8f, 0xc3, 0x9d, 0x8e, 0x6f, 0xf6, 0x7c, 0xb3, 0xdf, 0x75, 0x8b,
+ 0xf4, 0x27, 0xf3, 0xd9, 0x62, 0xff, 0xc3, 0xfb, 0x9b, 0xf9, 0x86, 0x04,
+ 0xb1, 0x7f, 0xa7, 0xe5, 0x9e, 0xfb, 0xac, 0x54, 0x11, 0x9f, 0xd1, 0x93,
+ 0x95, 0x09, 0x06, 0xff, 0xcf, 0xad, 0x3f, 0x50, 0xf3, 0x74, 0xb1, 0x7e,
+ 0xd9, 0xc6, 0x29, 0x58, 0xb3, 0x6c, 0x7d, 0x5a, 0x41, 0xbf, 0xc1, 0x67,
+ 0x5e, 0x0c, 0x5b, 0x2c, 0x5f, 0xce, 0x6c, 0x93, 0x1a, 0xb1, 0x7f, 0xff,
+ 0xf1, 0x0a, 0x19, 0xc2, 0xcd, 0x83, 0x87, 0x8d, 0x7e, 0xb8, 0x3c, 0x25,
+ 0x8b, 0xfa, 0x70, 0xb5, 0xa9, 0x58, 0xa3, 0x51, 0x9e, 0xe5, 0xda, 0x75,
+ 0xa9, 0x4c, 0xe3, 0xd1, 0x84, 0x5e, 0xff, 0x8e, 0xb1, 0x74, 0x23, 0x3b,
+ 0xed, 0x99, 0xd5, 0x31, 0xab, 0x6c, 0x9c, 0x36, 0xcc, 0x8e, 0x5f, 0x74,
+ 0xf7, 0x4d, 0x8a, 0x1b, 0x5a, 0x2f, 0x3a, 0x0f, 0xe1, 0x06, 0xcc, 0x60,
+ 0x23, 0x28, 0xd2, 0x39, 0x1c, 0xb7, 0xa3, 0x28, 0x8e, 0x85, 0x38, 0x71,
+ 0xb0, 0x77, 0x14, 0xdf, 0xff, 0xb3, 0xf1, 0x9d, 0x43, 0xd2, 0x16, 0x1d,
+ 0xca, 0x0b, 0x16, 0x8c, 0x83, 0x3b, 0x45, 0xa9, 0xa4, 0xbe, 0x8d, 0x4a,
+ 0xb6, 0x7f, 0x0f, 0x78, 0x5a, 0xf9, 0xc1, 0xca, 0x11, 0xde, 0x98, 0xcc,
+ 0xf3, 0x8a, 0x11, 0xf3, 0xee, 0xba, 0x97, 0x86, 0x78, 0xe3, 0xfe, 0x88,
+ 0x08, 0x57, 0xf7, 0xe8, 0x64, 0xbf, 0xc8, 0xe2, 0xc5, 0x4e, 0xb6, 0xee,
+ 0xa7, 0xd6, 0x5f, 0xa1, 0x19, 0xa2, 0x12, 0xc5, 0xff, 0x9a, 0x11, 0x99,
+ 0xad, 0xd9, 0xb7, 0x54, 0x8e, 0x65, 0xd9, 0xa5, 0x8b, 0xfd, 0xcc, 0xfc,
+ 0xed, 0x9a, 0x58, 0xbf, 0xcd, 0xbc, 0x60, 0x67, 0x29, 0xd8, 0xf2, 0xf0,
+ 0x5e, 0xd1, 0x87, 0x47, 0x4f, 0x68, 0x4d, 0xdb, 0x8b, 0x17, 0x42, 0x56,
+ 0x2f, 0xfc, 0xd0, 0x8c, 0xcd, 0x6e, 0xcd, 0xba, 0xa4, 0x89, 0x2e, 0x08,
+ 0x25, 0x8b, 0x46, 0x6c, 0x89, 0x3d, 0xc4, 0x8e, 0x2e, 0x12, 0x85, 0xdd,
+ 0xf3, 0x65, 0x8b, 0xfc, 0xe0, 0x6f, 0x7e, 0x4d, 0x58, 0xbf, 0xb9, 0xc9,
+ 0x00, 0x7b, 0x2c, 0x5f, 0xe6, 0xd4, 0x3b, 0xe7, 0x60, 0x3a, 0xc5, 0x61,
+ 0xf6, 0x88, 0xc6, 0xf3, 0xf5, 0xc5, 0x8b, 0xc5, 0x27, 0x58, 0xbf, 0xe2,
+ 0x6e, 0xbc, 0xde, 0x83, 0x2c, 0x5f, 0xdf, 0xcc, 0xf7, 0xf1, 0x62, 0xb6,
+ 0x45, 0x03, 0x8f, 0x00, 0x73, 0xc7, 0x37, 0x89, 0xb7, 0x58, 0xbf, 0xed,
+ 0x6f, 0xf7, 0x8f, 0x7c, 0xd9, 0x62, 0xd2, 0xb1, 0x42, 0x3c, 0xfe, 0xc7,
+ 0xd7, 0xee, 0x3e, 0x68, 0xd5, 0x8b, 0xe9, 0x38, 0xfe, 0xb1, 0x50, 0x3c,
+ 0xcf, 0x14, 0xdf, 0xb5, 0x3d, 0x9f, 0xb2, 0xc5, 0xe8, 0x9c, 0xeb, 0x17,
+ 0xe6, 0xf7, 0xb3, 0x4b, 0x14, 0x33, 0xf2, 0x72, 0xc2, 0x1e, 0xbf, 0xbc,
+ 0xd0, 0xe3, 0x8d, 0x62, 0xff, 0x3e, 0x86, 0x26, 0xd4, 0x16, 0x2b, 0x0f,
+ 0x8b, 0xe5, 0xd7, 0xdb, 0xbb, 0x77, 0x2c, 0x5f, 0x70, 0xf3, 0xc5, 0x8b,
+ 0xfe, 0x7e, 0x60, 0xe1, 0x0f, 0x89, 0x62, 0xfd, 0xc8, 0xa0, 0xe0, 0x58,
+ 0xbd, 0xdf, 0xcf, 0x96, 0x2b, 0x11, 0x53, 0xb9, 0x1b, 0x9d, 0x08, 0xaa,
+ 0xf1, 0xd8, 0x0b, 0x17, 0xfd, 0xbb, 0x6b, 0x61, 0xb3, 0x1a, 0xb1, 0x7e,
+ 0xf7, 0xa7, 0x40, 0x58, 0xad, 0xcf, 0x97, 0xe7, 0x95, 0x28, 0xa5, 0xc8,
+ 0x41, 0x5f, 0xfb, 0xac, 0xf3, 0xf4, 0x16, 0x75, 0xe5, 0x8b, 0xf1, 0x37,
+ 0x69, 0x35, 0x62, 0xa4, 0xfb, 0x5d, 0x0e, 0xfe, 0xc1, 0x86, 0x36, 0x3a,
+ 0xc5, 0xff, 0xfb, 0x0a, 0x06, 0x60, 0xdf, 0x9d, 0x78, 0x4d, 0xc5, 0x8b,
+ 0xdc, 0x10, 0x4b, 0x17, 0xfa, 0x76, 0x0e, 0x39, 0x88, 0x0b, 0x17, 0x42,
+ 0x32, 0x36, 0x5f, 0x1e, 0x91, 0xf1, 0xc2, 0x87, 0x21, 0x82, 0x69, 0xee,
+ 0xed, 0x9d, 0x38, 0x3c, 0x25, 0x22, 0x84, 0x7e, 0x88, 0x7f, 0x0c, 0xf2,
+ 0x87, 0x0f, 0xa1, 0x27, 0xd8, 0x80, 0x22, 0xf8, 0xe5, 0x70, 0xc7, 0xef,
+ 0x46, 0xfd, 0xf7, 0x1c, 0xb1, 0x7f, 0x70, 0x8c, 0x8d, 0xc6, 0xeb, 0x17,
+ 0xf4, 0xbf, 0xbf, 0x3a, 0x58, 0xbf, 0xf1, 0x60, 0x24, 0x1a, 0xd4, 0x84,
+ 0xb1, 0x7c, 0x45, 0x9e, 0x58, 0xb4, 0x64, 0x6b, 0x47, 0x74, 0x96, 0xfc,
+ 0xd3, 0x85, 0xa1, 0x9f, 0xd6, 0x95, 0x37, 0x02, 0x50, 0xad, 0x4b, 0x2f,
+ 0x73, 0x51, 0x8a, 0xf2, 0x18, 0xc2, 0xa4, 0xea, 0xdf, 0xff, 0xff, 0xb6,
+ 0x0e, 0x3e, 0x35, 0xf7, 0xe6, 0x19, 0xf8, 0xe8, 0xc2, 0x8d, 0x51, 0xb7,
+ 0x79, 0x1f, 0x1a, 0x83, 0x30, 0xcf, 0xc7, 0x2c, 0x5f, 0xb5, 0xbb, 0x36,
+ 0xea, 0x90, 0x70, 0xbf, 0x85, 0xbe, 0x9e, 0x49, 0x62, 0xfc, 0xe5, 0xe9,
+ 0x3a, 0xc5, 0xa3, 0x31, 0x11, 0x9f, 0x37, 0x8e, 0x2e, 0xbf, 0xb0, 0x3f,
+ 0xcb, 0xe9, 0x62, 0xfc, 0x1f, 0xe5, 0xf4, 0xb1, 0x73, 0x86, 0xb1, 0x58,
+ 0x78, 0x2e, 0x53, 0x7f, 0x60, 0x7f, 0x97, 0xd2, 0xc5, 0xfd, 0x81, 0xfe,
+ 0x5f, 0x4b, 0x17, 0xf6, 0x07, 0xf9, 0x7d, 0x2c, 0x5f, 0xd8, 0x1f, 0xe5,
+ 0xf4, 0xb1, 0x7f, 0xf7, 0x7c, 0xef, 0x3f, 0x22, 0xee, 0xdf, 0xf2, 0x12,
+ 0xc5, 0xff, 0x9c, 0x78, 0x72, 0xce, 0xbc, 0xcb, 0x17, 0xfb, 0x59, 0xbf,
+ 0xe7, 0xa8, 0x2c, 0x58, 0x25, 0x8a, 0x93, 0xc9, 0xc3, 0x6a, 0x58, 0xbf,
+ 0xb9, 0xc9, 0x00, 0x7b, 0x2c, 0x5f, 0xf9, 0x8d, 0xdf, 0xef, 0xad, 0x48,
+ 0x4b, 0x15, 0x87, 0xe6, 0x46, 0x37, 0xdb, 0x0e, 0x76, 0x58, 0xbc, 0x2e,
+ 0x4a, 0xc5, 0xff, 0xdb, 0xfe, 0x4d, 0x7e, 0x77, 0xd7, 0xbc, 0x6f, 0xac,
+ 0x58, 0x4b, 0x17, 0xf4, 0xfb, 0xf3, 0xd0, 0x16, 0x2a, 0x3d, 0x12, 0xa7,
+ 0x54, 0xe0, 0x95, 0xec, 0x63, 0xac, 0x52, 0xc5, 0x8b, 0xa3, 0x50, 0x43,
+ 0x97, 0xdb, 0xb3, 0x6e, 0xa9, 0x0b, 0xcb, 0xfd, 0x9d, 0x03, 0x8c, 0xfb,
+ 0x2c, 0x5f, 0x89, 0x80, 0xdc, 0x58, 0xbf, 0x64, 0x50, 0x6e, 0x2c, 0x56,
+ 0x2a, 0x0e, 0xe8, 0x95, 0xe1, 0x65, 0x12, 0xde, 0x89, 0x88, 0xc7, 0xc6,
+ 0xa1, 0x93, 0xdf, 0xed, 0xbf, 0x9f, 0xc7, 0xd9, 0x62, 0xf4, 0x85, 0xe5,
+ 0x8b, 0x36, 0x8f, 0x4c, 0x8d, 0x6e, 0x14, 0x7a, 0xc5, 0xfd, 0xcf, 0xb1,
+ 0xdf, 0x8b, 0x17, 0x0b, 0x4b, 0x15, 0x03, 0xe1, 0x38, 0xdb, 0x17, 0x5e,
+ 0xfb, 0xe9, 0x62, 0xf8, 0xa6, 0x3e, 0x25, 0x8a, 0x39, 0xe1, 0xfc, 0x76,
+ 0xff, 0x9b, 0x50, 0x8a, 0x0f, 0xa8, 0x2c, 0x5f, 0x77, 0x39, 0x44, 0xb1,
+ 0x70, 0x51, 0x2c, 0x5f, 0xd8, 0x3f, 0xe0, 0x19, 0x62, 0xfa, 0x45, 0xdf,
+ 0xf1, 0x62, 0xa0, 0x8d, 0x0c, 0x3b, 0x62, 0x6e, 0x0d, 0x04, 0x5b, 0x7f,
+ 0xde, 0x70, 0x71, 0xba, 0x80, 0x16, 0x2f, 0xf3, 0x83, 0x80, 0x03, 0xf9,
+ 0x62, 0xfd, 0x27, 0x06, 0xe0, 0x58, 0xa9, 0x44, 0xce, 0x1d, 0xb9, 0xa5,
+ 0xc1, 0xf1, 0x62, 0xfd, 0xa6, 0xe6, 0xd2, 0xb1, 0x68, 0x2c, 0x54, 0x9e,
+ 0xa6, 0x0c, 0xb1, 0x4d, 0xfe, 0x07, 0xb9, 0xfc, 0x71, 0xac, 0x5b, 0x65,
+ 0x8a, 0xd1, 0xe3, 0x91, 0xa5, 0x82, 0x58, 0xbf, 0x4e, 0xb5, 0x3b, 0x2c,
+ 0x5f, 0xe2, 0x93, 0x86, 0x3f, 0xca, 0xc5, 0x61, 0xf8, 0x10, 0x9f, 0x8a,
+ 0x6f, 0xcd, 0x03, 0xcc, 0x16, 0x2c, 0x75, 0x8a, 0x94, 0x7c, 0x3c, 0x24,
+ 0x7e, 0x5b, 0xe2, 0x8b, 0xe7, 0x1b, 0x71, 0x62, 0xf8, 0xcf, 0x66, 0x96,
+ 0x2a, 0x4f, 0x1b, 0x72, 0x2b, 0xe0, 0x67, 0x5e, 0x58, 0xbc, 0xd0, 0xc5,
+ 0x8b, 0xf9, 0x8b, 0x7d, 0x43, 0x8b, 0x15, 0xd1, 0xf7, 0x91, 0x20, 0x87,
+ 0x2f, 0xf6, 0x1f, 0x37, 0xdd, 0xfe, 0xb1, 0x7a, 0x0d, 0x05, 0x8b, 0xf7,
+ 0xf2, 0x03, 0xe9, 0x62, 0x9c, 0xff, 0x22, 0x35, 0xf0, 0xed, 0xdc, 0xe9,
+ 0x62, 0xfb, 0xd0, 0x93, 0x52, 0x2f, 0xb0, 0x7e, 0xe2, 0xc5, 0x62, 0x23,
+ 0xce, 0x5e, 0xc3, 0x24, 0x49, 0x7f, 0xfc, 0xcd, 0xe1, 0xbb, 0x10, 0xff,
+ 0x21, 0x9d, 0x62, 0xf6, 0x07, 0xde, 0x2c, 0x5f, 0xba, 0x87, 0x1c, 0xd5,
+ 0x8a, 0x93, 0xce, 0xc2, 0x3a, 0xd2, 0x2f, 0x4a, 0x13, 0xb7, 0xe0, 0x02,
+ 0x48, 0xd5, 0x8b, 0xdb, 0xb4, 0x16, 0x2a, 0x4f, 0x1f, 0x0a, 0x6f, 0x83,
+ 0x28, 0xbb, 0x96, 0x2b, 0xe7, 0x90, 0x02, 0x0b, 0xf3, 0x74, 0x26, 0xf2,
+ 0xc5, 0xd1, 0xc4, 0xb1, 0x7f, 0x1d, 0xcb, 0x0f, 0x2b, 0x17, 0xdb, 0x7b,
+ 0x3e, 0xb1, 0x58, 0x7a, 0x0c, 0x59, 0x7f, 0x03, 0x08, 0x5c, 0x95, 0x8b,
+ 0xff, 0x16, 0x6c, 0x59, 0xef, 0xcc, 0x16, 0x2f, 0xf9, 0xe0, 0xff, 0x11,
+ 0xce, 0xeb, 0x15, 0x28, 0xa4, 0x22, 0xdf, 0x1f, 0x5a, 0x33, 0xbc, 0x6c,
+ 0x06, 0x7b, 0xd6, 0xf8, 0xd0, 0x82, 0x36, 0x2e, 0xef, 0xb2, 0xee, 0xf8,
+ 0x5d, 0x1a, 0x8b, 0xa5, 0x5b, 0x68, 0x43, 0xc0, 0x80, 0x6f, 0xf9, 0x28,
+ 0xbb, 0x78, 0x65, 0xf5, 0x08, 0x77, 0x71, 0x8a, 0x1e, 0x5a, 0x87, 0x11,
+ 0xe1, 0x03, 0xf8, 0xda, 0xda, 0x10, 0xc0, 0x84, 0x89, 0x46, 0x75, 0xc8,
+ 0x7b, 0xfa, 0x16, 0xc2, 0x22, 0xec, 0x53, 0x1c, 0xd4, 0x1c, 0x31, 0x2f,
+ 0xf9, 0xb7, 0x8c, 0x86, 0x6b, 0x20, 0xb1, 0x76, 0x71, 0x62, 0xff, 0xff,
+ 0xf8, 0x9a, 0x33, 0x05, 0xdf, 0xb9, 0xaf, 0xef, 0xe3, 0xc3, 0x86, 0x61,
+ 0xb3, 0x05, 0x8b, 0xf6, 0x70, 0xe3, 0x95, 0x8b, 0xff, 0xe6, 0xdb, 0x53,
+ 0xb7, 0x18, 0x85, 0xbe, 0x71, 0x62, 0xfd, 0xad, 0xd9, 0xb7, 0x54, 0x8c,
+ 0x85, 0xe6, 0x84, 0x64, 0xa2, 0x27, 0x14, 0xae, 0x7e, 0x2c, 0x5a, 0x33,
+ 0x64, 0xf5, 0xe0, 0x7b, 0xb8, 0xbe, 0xa1, 0x0c, 0x78, 0x58, 0xf8, 0xd6,
+ 0xff, 0xef, 0xbe, 0xa1, 0x18, 0x3c, 0x38, 0xce, 0xb1, 0x71, 0xf8, 0xb1,
+ 0x79, 0x98, 0xeb, 0x16, 0x8c, 0xd1, 0xb4, 0xf8, 0xc5, 0xef, 0x61, 0xd6,
+ 0x2e, 0xf9, 0xd6, 0x2f, 0xda, 0xdd, 0x9b, 0x75, 0x49, 0xbc, 0x5a, 0x32,
+ 0x4f, 0xb0, 0x63, 0xb8, 0x31, 0x68, 0xe5, 0x8b, 0xb0, 0x96, 0x2d, 0x18,
+ 0xc6, 0xae, 0x38, 0x56, 0xe6, 0xee, 0x58, 0xbf, 0xc0, 0x91, 0x89, 0xb5,
+ 0x05, 0x8b, 0xff, 0x34, 0x23, 0x33, 0x5b, 0xb3, 0x6e, 0xa9, 0x24, 0xcb,
+ 0x46, 0x62, 0x27, 0x9c, 0x68, 0xe6, 0x97, 0x46, 0xf1, 0xa2, 0xc5, 0xff,
+ 0xb0, 0xb3, 0xda, 0x73, 0x7e, 0x25, 0x8b, 0x1d, 0x62, 0xff, 0x84, 0xdd,
+ 0x6b, 0x42, 0x8b, 0x8b, 0x15, 0x03, 0xcf, 0xe0, 0x95, 0xff, 0x78, 0x98,
+ 0x2f, 0x3f, 0x41, 0x2c, 0x5c, 0x7e, 0x96, 0x2f, 0xec, 0xf1, 0x4c, 0x9d,
+ 0x62, 0xfe, 0xe8, 0x01, 0xe9, 0x80, 0xb1, 0x77, 0xe3, 0x3b, 0xd4, 0xe1,
+ 0x06, 0x45, 0x90, 0x8e, 0xe8, 0x88, 0xe7, 0x9f, 0x19, 0x62, 0xca, 0x8d,
+ 0x9b, 0xa5, 0x39, 0x8d, 0x32, 0x15, 0x82, 0xa6, 0x4b, 0xd0, 0x76, 0xdd,
+ 0x3e, 0xf2, 0x12, 0xde, 0x61, 0xed, 0x0c, 0xa0, 0xe3, 0xbb, 0xbf, 0xb3,
+ 0x5b, 0xb3, 0x6e, 0xa9, 0x07, 0x4b, 0xff, 0xdd, 0xa6, 0x3c, 0xc6, 0xf4,
+ 0xee, 0xe5, 0x2b, 0x17, 0xfb, 0x39, 0xc9, 0x00, 0x7b, 0x2c, 0x5f, 0xfb,
+ 0xf8, 0x44, 0xde, 0xfc, 0x1d, 0x62, 0xfe, 0xd7, 0xc2, 0x61, 0xc6, 0x4a,
+ 0x30, 0x86, 0x9f, 0xe3, 0x6a, 0x8c, 0x4d, 0x51, 0xa1, 0xfd, 0x7e, 0xd6,
+ 0xec, 0xdb, 0xaa, 0x45, 0x82, 0xfb, 0x00, 0x77, 0x58, 0xbf, 0x46, 0x1d,
+ 0xa1, 0x19, 0x87, 0xb3, 0x1c, 0x6f, 0x7f, 0xce, 0x3c, 0x3b, 0xee, 0xe3,
+ 0x58, 0xbf, 0x6b, 0x76, 0x6d, 0xd5, 0x21, 0x81, 0x68, 0xc9, 0x3f, 0x0c,
+ 0x39, 0xbc, 0x14, 0x9d, 0x62, 0xe2, 0xdd, 0x62, 0xff, 0x30, 0xf3, 0xb9,
+ 0xa4, 0xeb, 0x15, 0x87, 0x9b, 0xf1, 0x8b, 0xd0, 0x71, 0xac, 0x5d, 0x3d,
+ 0x2c, 0x5f, 0xcf, 0xf6, 0x3f, 0xc4, 0xb1, 0x5a, 0x3c, 0x6f, 0x0c, 0x5f,
+ 0xb3, 0x59, 0x9d, 0x2c, 0x5f, 0xa1, 0x9c, 0x6e, 0x2c, 0x5e, 0xc2, 0x1a,
+ 0xc5, 0xff, 0xd1, 0xcc, 0x40, 0xcf, 0x49, 0x38, 0x16, 0x2d, 0x19, 0x89,
+ 0xe1, 0x6e, 0xd7, 0x11, 0x0b, 0x31, 0x91, 0x10, 0x8a, 0x02, 0x28, 0x0c,
+ 0x72, 0xff, 0xfc, 0xc0, 0x8e, 0xc8, 0xc2, 0x6f, 0x43, 0x3d, 0x83, 0x58,
+ 0xbf, 0xff, 0x39, 0xdf, 0x51, 0x9e, 0x8e, 0xcf, 0xfa, 0x7a, 0x09, 0x62,
+ 0x89, 0x33, 0x4e, 0x3e, 0x79, 0x6a, 0xec, 0xe2, 0xc5, 0xbb, 0x96, 0x2d,
+ 0x19, 0x03, 0x59, 0x10, 0xbd, 0xef, 0x3c, 0x4b, 0x17, 0xff, 0xff, 0xfd,
+ 0x24, 0x23, 0xea, 0x7c, 0xfb, 0xb8, 0xff, 0x3b, 0xfe, 0x76, 0x3b, 0xf9,
+ 0xa2, 0x6f, 0x2c, 0x5f, 0x39, 0x30, 0x16, 0x2f, 0x60, 0x51, 0x9d, 0x22,
+ 0xdf, 0x90, 0x96, 0xbf, 0xb9, 0xb7, 0xf0, 0x0c, 0xb1, 0x7f, 0xff, 0xd0,
+ 0xe4, 0x66, 0xff, 0x68, 0xb7, 0xfe, 0x6b, 0xbc, 0xfc, 0x47, 0xe2, 0xc5,
+ 0xf4, 0xfc, 0x5e, 0x58, 0xbf, 0x67, 0x81, 0x3b, 0xac, 0x5f, 0xfd, 0xe7,
+ 0x04, 0xc0, 0x7f, 0x92, 0xdd, 0x62, 0xfb, 0x91, 0x4c, 0x7a, 0xc5, 0x49,
+ 0xf6, 0x62, 0x2d, 0xf7, 0x50, 0x62, 0x58, 0xbc, 0x77, 0xe2, 0xc5, 0xa4,
+ 0xe7, 0x80, 0x02, 0x3b, 0xfa, 0x27, 0xfb, 0xea, 0x25, 0x8b, 0xfe, 0xd6,
+ 0xc2, 0x06, 0x10, 0x67, 0x58, 0xb7, 0x65, 0x8a, 0x94, 0x40, 0x39, 0x81,
+ 0xcf, 0x2f, 0x9c, 0x80, 0xeb, 0x17, 0xdb, 0xb3, 0x6e, 0xa9, 0x0f, 0x4a,
+ 0x81, 0xe9, 0x68, 0x86, 0xff, 0xf4, 0x79, 0x4b, 0x0d, 0xf8, 0x79, 0x18,
+ 0x16, 0x2f, 0xb8, 0xdd, 0x76, 0x58, 0xb4, 0x64, 0x13, 0x14, 0xc8, 0x40,
+ 0x31, 0x17, 0x93, 0x2f, 0xff, 0xfd, 0x19, 0xb4, 0xc4, 0xe4, 0xfb, 0xb7,
+ 0xd8, 0x23, 0x06, 0x40, 0x1a, 0xc5, 0x41, 0x17, 0xbb, 0xa5, 0x5f, 0xbd,
+ 0xc1, 0x6a, 0x0b, 0x17, 0xfd, 0xbb, 0x69, 0xbf, 0x16, 0x79, 0x62, 0xff,
+ 0xf0, 0xb3, 0xf8, 0x40, 0xc2, 0xf7, 0xf1, 0x62, 0xf4, 0xea, 0x25, 0x8b,
+ 0x46, 0x3a, 0x28, 0x48, 0xef, 0x89, 0x15, 0x89, 0x81, 0x34, 0x32, 0xef,
+ 0xbc, 0xfd, 0x04, 0xb1, 0x7f, 0xe8, 0x4e, 0xb6, 0xd6, 0x9f, 0xdc, 0x58,
+ 0xba, 0x7a, 0xc3, 0xe6, 0x88, 0x96, 0xff, 0xff, 0x1e, 0x31, 0x82, 0x6d,
+ 0x9c, 0x26, 0x0d, 0xcb, 0xd3, 0xc5, 0x8a, 0x95, 0xf8, 0xfd, 0xa1, 0xaa,
+ 0x33, 0xee, 0x8b, 0xdd, 0xda, 0x22, 0x3d, 0x42, 0x57, 0xec, 0x0d, 0x29,
+ 0xe0, 0xa3, 0x26, 0xf4, 0x23, 0x43, 0x2e, 0xbf, 0xd9, 0xce, 0x48, 0x03,
+ 0xd9, 0x62, 0xfd, 0x24, 0xf3, 0xc5, 0x8b, 0xf3, 0x19, 0xec, 0xdd, 0x62,
+ 0xff, 0xff, 0x0e, 0x5b, 0x5f, 0x09, 0x87, 0xef, 0xe1, 0x13, 0x79, 0x62,
+ 0xd1, 0x83, 0x47, 0x33, 0x9b, 0x7c, 0x9b, 0x85, 0x55, 0x18, 0x9f, 0x7e,
+ 0xd1, 0xd5, 0x5f, 0xd0, 0x6d, 0x6d, 0xf1, 0x2c, 0x5f, 0xb9, 0x20, 0x0f,
+ 0x65, 0x8b, 0x64, 0x47, 0xb7, 0xc3, 0x0b, 0x9c, 0xeb, 0x17, 0xfc, 0x26,
+ 0x1c, 0x73, 0xf3, 0x36, 0x58, 0xaf, 0x9e, 0xa7, 0x70, 0xbd, 0xff, 0xbe,
+ 0xfa, 0x80, 0x70, 0xcf, 0xb2, 0xc5, 0xee, 0x08, 0x0b, 0x17, 0xbc, 0xdb,
+ 0xac, 0x5c, 0x09, 0x58, 0xbf, 0xe2, 0x93, 0x00, 0x70, 0xf4, 0xcb, 0x14,
+ 0xe7, 0xa5, 0xe1, 0x7b, 0xfc, 0x42, 0xdc, 0xf3, 0xad, 0xd6, 0x2f, 0xfd,
+ 0xe7, 0x83, 0xfc, 0x47, 0x3b, 0xac, 0x5f, 0x13, 0x05, 0x18, 0x35, 0x40,
+ 0xb8, 0xf9, 0xb9, 0x2f, 0x48, 0x0c, 0x3d, 0xc7, 0x01, 0x10, 0x86, 0x6d,
+ 0x68, 0xf5, 0x8b, 0xf6, 0xb7, 0x66, 0xdd, 0x52, 0x61, 0x97, 0xfa, 0x05,
+ 0x39, 0xcc, 0x25, 0x8b, 0xb9, 0xc5, 0x8b, 0xde, 0xc3, 0xac, 0x58, 0xeb,
+ 0x15, 0x86, 0xbf, 0xc3, 0xb6, 0x8c, 0x94, 0x72, 0x60, 0xaf, 0x46, 0xfa,
+ 0x31, 0x24, 0x7b, 0xe8, 0xc0, 0x16, 0x2c, 0x5e, 0x6f, 0xf1, 0x62, 0xee,
+ 0xbc, 0xb1, 0x7f, 0x0b, 0x67, 0x21, 0x1d, 0x62, 0xa4, 0xf2, 0x08, 0x66,
+ 0xfa, 0x63, 0xe6, 0x25, 0x8b, 0xd2, 0x5b, 0x2c, 0x5a, 0x56, 0x2f, 0xa4,
+ 0x10, 0x3a, 0xc5, 0x7c, 0xda, 0x10, 0x8d, 0x0d, 0x31, 0xc7, 0x65, 0x88,
+ 0x83, 0xe4, 0xde, 0x51, 0xbd, 0xac, 0x35, 0x62, 0xff, 0xf0, 0xdc, 0xfd,
+ 0x43, 0x9d, 0x43, 0x35, 0xb2, 0xc5, 0xf4, 0xcf, 0x23, 0x06, 0x7d, 0xbe,
+ 0x1e, 0xa8, 0xc4, 0x79, 0x94, 0x2e, 0x2b, 0x65, 0x4b, 0xda, 0x94, 0x69,
+ 0x7f, 0xff, 0x8d, 0x8c, 0xe7, 0xba, 0xdd, 0xcb, 0x53, 0xe7, 0xdd, 0xc6,
+ 0xb1, 0x52, 0x89, 0x51, 0x16, 0xdf, 0xe8, 0xcc, 0xd6, 0xec, 0xdb, 0xaa,
+ 0x4e, 0x72, 0xff, 0xb9, 0x84, 0x03, 0xe0, 0xb8, 0xb1, 0x77, 0xfb, 0x2c,
+ 0x5a, 0x56, 0x2f, 0x07, 0x21, 0x2c, 0x5f, 0xf6, 0x74, 0x10, 0x65, 0x9d,
+ 0xb1, 0x62, 0xfe, 0x13, 0x75, 0xef, 0xba, 0xc5, 0x6c, 0x89, 0xcf, 0x88,
+ 0x90, 0xff, 0x0f, 0x6f, 0x40, 0x43, 0x58, 0xbf, 0xe8, 0x3e, 0xa1, 0xe3,
+ 0x73, 0x4b, 0x17, 0x6d, 0xc5, 0x8b, 0xe1, 0x77, 0x61, 0x2c, 0x5e, 0x79,
+ 0x02, 0xc5, 0xff, 0x67, 0x47, 0x61, 0xfe, 0x49, 0x62, 0xbe, 0x7a, 0xa4,
+ 0x39, 0x73, 0x1d, 0x62, 0xf9, 0xf5, 0xa6, 0x58, 0xbf, 0xfb, 0x08, 0x11,
+ 0xd9, 0xef, 0xb9, 0x01, 0x62, 0xfb, 0x92, 0x46, 0xac, 0x56, 0x22, 0x2f,
+ 0x84, 0x41, 0xa3, 0x5f, 0xf6, 0x7b, 0xed, 0x0f, 0x4c, 0x16, 0x2f, 0x49,
+ 0x79, 0x62, 0xbe, 0x7a, 0xa2, 0x39, 0xb0, 0x16, 0x2e, 0xc3, 0xac, 0x54,
+ 0x9a, 0x96, 0x12, 0xbf, 0xff, 0x69, 0xcf, 0x26, 0xfd, 0xb8, 0x03, 0xb7,
+ 0x5e, 0x58, 0xbc, 0x53, 0xd2, 0xc5, 0xf3, 0x6a, 0x11, 0x92, 0xb8, 0x7e,
+ 0x33, 0x9c, 0x85, 0xb7, 0x47, 0xb1, 0x0f, 0x1c, 0xef, 0xe3, 0x2c, 0xf4,
+ 0x44, 0x3c, 0x85, 0x17, 0xa1, 0x0a, 0x12, 0x58, 0x63, 0xfd, 0xcb, 0x17,
+ 0xff, 0xff, 0xff, 0x4f, 0x7d, 0xc3, 0x6d, 0xfe, 0x61, 0x9f, 0x8e, 0x8c,
+ 0xd8, 0x46, 0xc6, 0xb9, 0xef, 0x7a, 0xdb, 0x6d, 0xce, 0x61, 0x9f, 0x8e,
+ 0x58, 0xa9, 0x6f, 0x01, 0x36, 0x84, 0x24, 0x21, 0x6f, 0x92, 0xc7, 0xf7,
+ 0x5c, 0x7a, 0x4d, 0x4e, 0xa5, 0x47, 0x1e, 0x37, 0x2f, 0xcb, 0x44, 0xf1,
+ 0x10, 0xa7, 0x21, 0x3b, 0xa1, 0xdd, 0x7f, 0xdc, 0x3e, 0x19, 0x0c, 0x1c,
+ 0xac, 0x5f, 0xb5, 0xbb, 0x36, 0xea, 0x90, 0x78, 0xbf, 0xfd, 0xf7, 0x93,
+ 0xb0, 0xc3, 0xee, 0x92, 0x82, 0xc5, 0xff, 0xff, 0xef, 0xe1, 0xfe, 0x59,
+ 0xd9, 0xb7, 0x8c, 0xe7, 0x24, 0x1e, 0x29, 0x3f, 0x16, 0x2d, 0x19, 0x29,
+ 0x9d, 0xe1, 0xd7, 0x0d, 0xfc, 0x9b, 0x7f, 0xf9, 0xbd, 0x27, 0x29, 0x62,
+ 0x29, 0x82, 0xc5, 0xdd, 0xec, 0x6b, 0x58, 0xbf, 0xdd, 0xef, 0xf0, 0x07,
+ 0x9d, 0x2c, 0x5e, 0xf8, 0xa0, 0xb1, 0x7f, 0xd3, 0xf9, 0xdb, 0x53, 0x83,
+ 0x58, 0xbf, 0xfd, 0xcc, 0x29, 0x87, 0xf3, 0xef, 0x84, 0xb1, 0x7f, 0xed,
+ 0x3f, 0x24, 0x6c, 0x4e, 0x75, 0x8a, 0xe9, 0x1b, 0x7f, 0x1e, 0xe1, 0xcf,
+ 0x64, 0x7b, 0xde, 0xdc, 0x0b, 0x17, 0xfb, 0x52, 0xfe, 0x29, 0x3a, 0xc5,
+ 0xfd, 0x3a, 0xd4, 0x99, 0x2b, 0x17, 0xf7, 0x0c, 0x19, 0x37, 0xd6, 0x28,
+ 0x8f, 0x74, 0x45, 0xd7, 0xff, 0xf6, 0x0d, 0xf9, 0x85, 0xcd, 0xfe, 0xe4,
+ 0x59, 0xd2, 0xc5, 0xff, 0xfe, 0x63, 0x62, 0xe4, 0xf8, 0xc0, 0xfc, 0xe4,
+ 0x28, 0x67, 0x16, 0x2b, 0xe8, 0xbf, 0x25, 0xab, 0xff, 0xe1, 0x79, 0xfd,
+ 0xe9, 0x33, 0xf9, 0x85, 0xba, 0xc5, 0xf9, 0xf4, 0xde, 0x8d, 0x6b, 0x17,
+ 0xf0, 0x32, 0x12, 0x0e, 0x2c, 0x5f, 0xff, 0xfe, 0xcd, 0x6a, 0x7a, 0x80,
+ 0x7e, 0x72, 0x14, 0x33, 0x85, 0x9b, 0x07, 0x05, 0x8a, 0x94, 0x54, 0xfc,
+ 0xba, 0xff, 0xfc, 0x59, 0xc7, 0x6d, 0xb0, 0x67, 0x78, 0xe9, 0x3a, 0xc5,
+ 0xf6, 0xec, 0xdb, 0xaa, 0x42, 0x62, 0xfd, 0x8f, 0xed, 0x09, 0x62, 0xfa,
+ 0x3f, 0xf2, 0x6a, 0xc5, 0xff, 0xfe, 0xd1, 0x66, 0xd8, 0x3c, 0x08, 0x5a,
+ 0xcd, 0xff, 0x3d, 0x96, 0x2e, 0xcd, 0x96, 0x29, 0x62, 0xf8, 0x47, 0xc1,
+ 0xac, 0x76, 0x26, 0x54, 0xa2, 0xf3, 0xa6, 0x5e, 0xe2, 0x4b, 0xff, 0xfe,
+ 0x6f, 0x4f, 0x62, 0xce, 0x6c, 0xd9, 0xce, 0x31, 0xb3, 0xa5, 0x8b, 0xf7,
+ 0xb9, 0xb6, 0x04, 0xb1, 0x7f, 0xde, 0x11, 0xa6, 0x7f, 0x00, 0xcb, 0x15,
+ 0x89, 0x81, 0x39, 0x9b, 0x34, 0x08, 0xae, 0xc2, 0x58, 0xbf, 0xde, 0x13,
+ 0x75, 0xf9, 0xec, 0xb1, 0x7e, 0xcd, 0xb1, 0xf8, 0xb1, 0x50, 0x5c, 0xad,
+ 0x19, 0x11, 0xaa, 0x3b, 0xc3, 0x5d, 0xc8, 0xb4, 0xae, 0x73, 0x16, 0x28,
+ 0x28, 0xf9, 0x78, 0x77, 0xe1, 0x2e, 0xc6, 0xf7, 0xfc, 0xcc, 0x40, 0xd3,
+ 0xc9, 0xab, 0x17, 0xff, 0xdf, 0x7e, 0xa1, 0x2d, 0x03, 0x30, 0xed, 0xd2,
+ 0xc5, 0xff, 0xff, 0xff, 0xf0, 0x33, 0x8d, 0x1e, 0x67, 0xbe, 0xf3, 0xc3,
+ 0x33, 0x5a, 0xcf, 0x96, 0x7a, 0x4e, 0x66, 0x69, 0xa1, 0x8b, 0x17, 0x0b,
+ 0x65, 0x8b, 0x62, 0xc5, 0xcf, 0xdf, 0xac, 0x51, 0x1e, 0x37, 0x61, 0x90,
+ 0x84, 0x6f, 0xff, 0x7c, 0x32, 0x9e, 0xbf, 0x83, 0x13, 0x6e, 0xb1, 0x7f,
+ 0x1c, 0x32, 0x2c, 0xd9, 0x62, 0xfc, 0x16, 0xb3, 0xfc, 0x58, 0xa9, 0x3d,
+ 0x9c, 0x2f, 0xa8, 0x23, 0x18, 0xa1, 0x4d, 0x7f, 0x78, 0xa7, 0x77, 0x25,
+ 0x8b, 0xf1, 0x4e, 0xee, 0x4b, 0x17, 0xe9, 0xea, 0x0e, 0x73, 0x0f, 0x53,
+ 0xc5, 0xb7, 0xe0, 0x70, 0xcc, 0x1a, 0xc5, 0xfe, 0x70, 0xb0, 0xb3, 0xaf,
+ 0x2c, 0x5c, 0xdb, 0x2c, 0x56, 0x22, 0xd9, 0xd0, 0x34, 0x54, 0xc6, 0x97,
+ 0x67, 0x72, 0xc5, 0xed, 0xdc, 0x6b, 0x17, 0x10, 0xf0, 0xdc, 0x38, 0xd5,
+ 0xee, 0x60, 0xd6, 0x29, 0x8f, 0x1f, 0xc5, 0x57, 0xe7, 0x30, 0xfb, 0xc4,
+ 0xb1, 0x4c, 0x79, 0xa4, 0x43, 0x7f, 0xe3, 0xfc, 0x5b, 0x99, 0x9f, 0x6d,
+ 0x2c, 0x5f, 0xfd, 0xee, 0x72, 0x5f, 0xaf, 0x7a, 0x4e, 0xb1, 0x7f, 0xd3,
+ 0xf9, 0xec, 0x79, 0x2d, 0x96, 0x2f, 0xfe, 0x17, 0xb8, 0x42, 0x17, 0xa1,
+ 0x26, 0xac, 0x5e, 0xe3, 0x12, 0xc5, 0xff, 0xfa, 0x74, 0x0f, 0xcf, 0x68,
+ 0xa6, 0x4f, 0xcc, 0x1a, 0xc5, 0xff, 0x7f, 0xf3, 0xda, 0x19, 0xa9, 0x58,
+ 0xbf, 0xd3, 0x31, 0x67, 0x67, 0xd2, 0xc5, 0x7d, 0x19, 0x0c, 0xb0, 0x47,
+ 0x77, 0xff, 0x09, 0xb6, 0x2c, 0x39, 0xdf, 0x5c, 0x58, 0xac, 0x54, 0x3f,
+ 0x12, 0x31, 0x1d, 0xf1, 0x1f, 0xd0, 0xe4, 0x08, 0xba, 0xff, 0x13, 0x00,
+ 0x9a, 0x04, 0xb1, 0x7e, 0xf6, 0x02, 0x74, 0xb1, 0x73, 0xfa, 0x4f, 0x65,
+ 0xcc, 0x6f, 0xb6, 0xf8, 0xb6, 0x58, 0xa9, 0x56, 0xd3, 0x92, 0x98, 0x5a,
+ 0x16, 0xe2, 0x2b, 0xbd, 0xd0, 0xfb, 0x2c, 0x5f, 0x6c, 0x79, 0xd2, 0xc5,
+ 0xf6, 0xe2, 0x23, 0x56, 0x2e, 0x66, 0x58, 0xa8, 0x22, 0x01, 0x88, 0x48,
+ 0x90, 0x32, 0x5b, 0xed, 0x0d, 0xf4, 0xb1, 0x7e, 0x8f, 0x72, 0xf7, 0x16,
+ 0x2f, 0x37, 0x5c, 0x30, 0xf3, 0xa2, 0x23, 0xbf, 0xfd, 0xa9, 0x8b, 0x9b,
+ 0xfd, 0xfd, 0xe7, 0xee, 0x58, 0xb8, 0x7f, 0x58, 0xc3, 0xd0, 0xbf, 0xfd,
+ 0xe8, 0x66, 0xb4, 0xd0, 0xc3, 0xce, 0xeb, 0x17, 0xff, 0xfc, 0x59, 0xef,
+ 0xb9, 0x99, 0xe8, 0x67, 0x9f, 0xa8, 0x14, 0xac, 0x5f, 0xfa, 0x02, 0x1e,
+ 0x3b, 0x76, 0x9d, 0x2c, 0x5b, 0x1d, 0x14, 0xcc, 0xcd, 0x58, 0x99, 0xfb,
+ 0x14, 0x0a, 0x1e, 0x37, 0xfb, 0x53, 0xf6, 0x1c, 0x0e, 0xb1, 0x7f, 0xde,
+ 0x17, 0xe4, 0x7f, 0x70, 0x2c, 0x5f, 0xf4, 0xc3, 0x1c, 0xb2, 0x4d, 0x58,
+ 0xbf, 0xff, 0x7e, 0x74, 0x0e, 0x60, 0xfc, 0x26, 0xdf, 0x34, 0xb1, 0x51,
+ 0xe8, 0xc8, 0x88, 0xeb, 0xc6, 0xf7, 0x78, 0xeb, 0x17, 0xa3, 0x9b, 0x4b,
+ 0x17, 0xfd, 0xa9, 0xf0, 0xfe, 0x26, 0xe2, 0xc5, 0xff, 0x67, 0x38, 0x22,
+ 0xd8, 0xd8, 0x96, 0x2f, 0xd8, 0x73, 0xc8, 0xd6, 0x2f, 0xfc, 0x1e, 0xdc,
+ 0x97, 0xeb, 0xd2, 0x75, 0x8b, 0xff, 0xb8, 0xcd, 0xbe, 0x6f, 0x25, 0x3b,
+ 0xac, 0x54, 0x48, 0xaf, 0xf9, 0x47, 0x10, 0xaf, 0xff, 0x1f, 0x99, 0x0f,
+ 0xc9, 0x0b, 0x9c, 0x95, 0x8a, 0xc3, 0xfb, 0x63, 0x1b, 0xd3, 0xae, 0x2c,
+ 0x5f, 0xe8, 0x4f, 0xf3, 0x3d, 0xc5, 0x8b, 0xff, 0xb1, 0xc0, 0x58, 0xfd,
+ 0x9f, 0x4c, 0xb1, 0x7f, 0xe2, 0xce, 0x6f, 0xf7, 0xee, 0x7e, 0x2c, 0x54,
+ 0x48, 0xb8, 0xf1, 0x9f, 0x64, 0x3b, 0xe6, 0x0f, 0x36, 0x58, 0xac, 0x3d,
+ 0x71, 0x19, 0xdf, 0xdb, 0x07, 0xa7, 0x91, 0xac, 0x5f, 0xff, 0x67, 0x6c,
+ 0x1f, 0xc4, 0xdc, 0x0e, 0x74, 0x05, 0x8a, 0x74, 0x41, 0xfc, 0xc2, 0xff,
+ 0xa6, 0x01, 0xe6, 0xb9, 0x81, 0x2c, 0x5f, 0xe8, 0x49, 0xaf, 0xf6, 0xd9,
+ 0x62, 0xff, 0x80, 0x32, 0x98, 0x7f, 0x80, 0x58, 0xb9, 0x8d, 0x58, 0xad,
+ 0x91, 0x84, 0xe7, 0x7a, 0x35, 0x23, 0xab, 0xfe, 0xcf, 0xfa, 0x18, 0x4e,
+ 0x35, 0x8b, 0xc4, 0x21, 0xac, 0x50, 0xd7, 0x9b, 0xb2, 0x1f, 0x9d, 0x1a,
+ 0x38, 0xc4, 0x44, 0x1a, 0x3a, 0xfc, 0x6c, 0xe0, 0x20, 0x28, 0xcb, 0x3d,
+ 0x0a, 0x41, 0x43, 0x90, 0x23, 0xc0, 0xce, 0x2f, 0xfb, 0x0b, 0xdc, 0xfc,
+ 0xb6, 0x96, 0x2f, 0xf4, 0x1f, 0x5a, 0x66, 0x02, 0xc5, 0xf8, 0x99, 0xc8,
+ 0x0b, 0x17, 0xe0, 0x85, 0x3a, 0xd9, 0x62, 0x8c, 0x3d, 0x10, 0x89, 0xaf,
+ 0xfe, 0x76, 0x06, 0xa4, 0xbd, 0xfc, 0x82, 0xc5, 0xfe, 0xd6, 0x4f, 0x50,
+ 0x73, 0xac, 0x5f, 0xd9, 0x3d, 0x41, 0xce, 0xb1, 0x7d, 0x3b, 0xb9, 0x18,
+ 0x7c, 0x5a, 0x34, 0xbe, 0x67, 0xd6, 0x2c, 0x5f, 0xef, 0xb9, 0xfd, 0xc7,
+ 0xd2, 0xc5, 0x62, 0xa1, 0x3e, 0x8e, 0x1e, 0x10, 0x9f, 0x24, 0x28, 0x52,
+ 0xf8, 0xe4, 0x44, 0x37, 0x39, 0xd6, 0x2f, 0xa1, 0xf0, 0xf8, 0xb1, 0x7d,
+ 0x9b, 0x07, 0x05, 0x8b, 0x98, 0x35, 0x48, 0x2e, 0x57, 0x47, 0xde, 0x44,
+ 0xa2, 0x25, 0xa8, 0x91, 0x6b, 0xe8, 0x43, 0x5f, 0xbf, 0x9b, 0x08, 0x96,
+ 0x2f, 0x9b, 0x53, 0xd9, 0x62, 0x86, 0x79, 0xa0, 0x29, 0xbf, 0x87, 0x2e,
+ 0x3c, 0x3a, 0xc5, 0xfd, 0xf6, 0x2f, 0x67, 0xd6, 0x2f, 0xa1, 0x8c, 0x4b,
+ 0x17, 0xfb, 0x6c, 0x81, 0x09, 0xb8, 0xb1, 0x7b, 0xdf, 0x75, 0x8a, 0xc4,
+ 0x66, 0x39, 0x6c, 0x45, 0xac, 0x42, 0x23, 0x4b, 0xd2, 0x78, 0x2c, 0x5f,
+ 0xff, 0x39, 0xe4, 0xd3, 0x38, 0x22, 0xc1, 0x8b, 0x65, 0x8b, 0xc4, 0x23,
+ 0x56, 0x2f, 0xbe, 0x13, 0x6c, 0xb1, 0x5d, 0x22, 0xcf, 0x43, 0xa4, 0xa7,
+ 0xe1, 0xeb, 0xfd, 0xb3, 0x07, 0xff, 0xe6, 0x96, 0x2f, 0x3c, 0xc4, 0xb1,
+ 0x58, 0x7a, 0x7f, 0x36, 0xb4, 0x64, 0x6e, 0xe8, 0x6c, 0x7b, 0xd4, 0x68,
+ 0xd8, 0x8e, 0x63, 0x14, 0xd9, 0x02, 0x03, 0xe3, 0x84, 0x7e, 0x4e, 0xc6,
+ 0x9b, 0x0b, 0x4d, 0xce, 0x3a, 0x52, 0x78, 0x7a, 0x45, 0x0f, 0x7d, 0x46,
+ 0x62, 0x78, 0xc1, 0xbf, 0x2e, 0x25, 0xa1, 0x90, 0x08, 0x45, 0x14, 0x78,
+ 0xbc, 0x9e, 0xa2, 0xf4, 0xae, 0x41, 0x46, 0x47, 0xd9, 0xda, 0x3a, 0x1d,
+ 0xc1, 0xc3, 0xef, 0xba, 0x12, 0x17, 0xfe, 0xfb, 0xf5, 0xe0, 0xcb, 0x3b,
+ 0x62, 0xc5, 0xff, 0x64, 0x45, 0x27, 0xf0, 0xfe, 0xb1, 0x70, 0x23, 0x37,
+ 0x3f, 0xcf, 0x21, 0x5f, 0xb3, 0x5c, 0x79, 0x58, 0xbd, 0xdf, 0x5e, 0xf9,
+ 0x1b, 0x2c, 0x5f, 0xfb, 0x42, 0xdb, 0x3f, 0x11, 0x48, 0xd6, 0x2f, 0xd9,
+ 0xc0, 0x9b, 0x4b, 0x17, 0xfb, 0x79, 0xfc, 0x9f, 0xe2, 0x58, 0xbd, 0x38,
+ 0x6a, 0xc5, 0x61, 0xe9, 0x11, 0xad, 0xf3, 0x43, 0xf8, 0xb1, 0x7f, 0x7f,
+ 0x33, 0xdf, 0xc5, 0x8a, 0x19, 0xe7, 0xf8, 0x8a, 0xf9, 0xba, 0x1f, 0x4b,
+ 0x17, 0xee, 0x7e, 0x7a, 0xe2, 0xc5, 0xbf, 0x27, 0x9e, 0xe4, 0xb7, 0x8d,
+ 0xd7, 0x4b, 0x17, 0x83, 0x9e, 0x96, 0x2f, 0x1c, 0x47, 0x58, 0xa9, 0x37,
+ 0xb8, 0x3f, 0x7c, 0xfd, 0x85, 0xdc, 0xb1, 0x7f, 0x49, 0x60, 0xc7, 0x2b,
+ 0x15, 0x87, 0xa9, 0xa2, 0x8b, 0xff, 0x31, 0x1a, 0xde, 0x9f, 0x30, 0x16,
+ 0x2f, 0x07, 0x24, 0xb1, 0x68, 0x2c, 0x50, 0xcd, 0x79, 0xa3, 0xb7, 0x85,
+ 0xa8, 0x2c, 0x5f, 0xff, 0xbc, 0x2d, 0x37, 0x30, 0xbf, 0x98, 0x50, 0xe2,
+ 0xc5, 0x6c, 0x7e, 0x4e, 0x3d, 0x52, 0x8b, 0x66, 0x84, 0xa5, 0x2c, 0x5f,
+ 0x9b, 0x3d, 0x87, 0x58, 0xb8, 0x13, 0x26, 0xcc, 0x83, 0x2f, 0xff, 0xec,
+ 0xec, 0x59, 0xcc, 0x3c, 0x91, 0xbf, 0x79, 0x3a, 0xc5, 0xf3, 0x8b, 0xbf,
+ 0xe2, 0xc5, 0xf6, 0x80, 0x64, 0xac, 0x50, 0xcf, 0x30, 0x45, 0x17, 0x7d,
+ 0x96, 0x2f, 0xff, 0xb6, 0xda, 0x4b, 0x3c, 0xfd, 0x05, 0x9d, 0x79, 0x62,
+ 0xe7, 0x35, 0x62, 0xc2, 0x58, 0xac, 0x44, 0xab, 0x8b, 0xc4, 0xa9, 0xc1,
+ 0x8b, 0xee, 0x7e, 0x40, 0xb1, 0x7f, 0xb4, 0x03, 0xb4, 0x0c, 0xf2, 0xc5,
+ 0xa3, 0xd6, 0x2b, 0x0f, 0x2c, 0xd3, 0x6b, 0xef, 0x49, 0x76, 0x58, 0xbf,
+ 0xfe, 0x14, 0x0b, 0x0f, 0xe8, 0x64, 0x7b, 0x10, 0x16, 0x2f, 0x4e, 0x74,
+ 0xb1, 0x4b, 0x14, 0x46, 0xa7, 0xc3, 0xb7, 0xff, 0x4e, 0xa7, 0x79, 0x70,
+ 0x37, 0x84, 0xb1, 0x5f, 0x4c, 0x0c, 0x89, 0x3c, 0xf7, 0x1c, 0x41, 0x7f,
+ 0xba, 0xd6, 0x1a, 0xd9, 0xf5, 0x8b, 0xb9, 0x19, 0x1a, 0x32, 0x14, 0xe3,
+ 0x59, 0x3c, 0x98, 0xc1, 0x04, 0x6f, 0x78, 0xdf, 0xbb, 0x8f, 0x44, 0xce,
+ 0xbb, 0xa7, 0x33, 0x90, 0xfe, 0x32, 0x30, 0x2c, 0x91, 0x57, 0x21, 0x4f,
+ 0xe8, 0x5b, 0x88, 0xf2, 0x39, 0xb8, 0x38, 0xc9, 0x7b, 0x90, 0x2b, 0x4c,
+ 0x9c, 0xb0, 0x52, 0x21, 0x6d, 0x1e, 0xb1, 0x7f, 0x98, 0x1d, 0x78, 0x9b,
+ 0xeb, 0x17, 0xf3, 0xf4, 0x0d, 0x60, 0xd6, 0x29, 0xcf, 0xe3, 0x42, 0xbf,
+ 0x34, 0xbc, 0xed, 0x05, 0x8b, 0x87, 0x19, 0x87, 0x95, 0xf2, 0xeb, 0xfb,
+ 0xa8, 0x36, 0xc1, 0xee, 0xb1, 0x7f, 0xff, 0xfd, 0x8e, 0x4d, 0xe9, 0x26,
+ 0xda, 0x74, 0x66, 0x10, 0xbc, 0x58, 0x09, 0x58, 0xbe, 0x78, 0x72, 0x33,
+ 0x11, 0x59, 0xc3, 0x3a, 0x94, 0xc6, 0x32, 0x1b, 0x95, 0x2a, 0x8c, 0x7f,
+ 0x28, 0x2a, 0xfe, 0xd6, 0x79, 0xfe, 0x25, 0x8b, 0xff, 0xff, 0xfe, 0x30,
+ 0xb3, 0xd3, 0x9d, 0x78, 0xcc, 0x87, 0xf1, 0xe1, 0xc3, 0x03, 0x2c, 0xf7,
+ 0x03, 0x3a, 0xc5, 0xa3, 0x7e, 0xf5, 0x18, 0xf1, 0xa1, 0x75, 0xf7, 0x1f,
+ 0x6e, 0xf5, 0x62, 0xec, 0xee, 0x58, 0xbf, 0x08, 0x89, 0xe0, 0xb1, 0x51,
+ 0xba, 0x28, 0xbb, 0xc3, 0x82, 0x29, 0xe0, 0xd5, 0xff, 0xa3, 0x7e, 0xf5,
+ 0xf6, 0x93, 0x37, 0xe6, 0x2c, 0x5f, 0xdd, 0xef, 0x26, 0x21, 0x69, 0x62,
+ 0xc4, 0xb1, 0x5d, 0xf6, 0x78, 0xd1, 0xa8, 0xd6, 0xd1, 0xeb, 0x17, 0x66,
+ 0x96, 0x2f, 0xbb, 0xcf, 0xb7, 0x78, 0xb1, 0x5f, 0x3c, 0x46, 0x17, 0xb8,
+ 0x11, 0x2c, 0x54, 0x6e, 0x9a, 0xa7, 0x79, 0x09, 0x21, 0x97, 0xfd, 0x66,
+ 0x38, 0x86, 0xff, 0xd9, 0x02, 0x63, 0x62, 0xe4, 0xf9, 0x62, 0xfb, 0xcf,
+ 0xac, 0x58, 0xae, 0xfb, 0x3e, 0x2c, 0x40, 0xbf, 0xec, 0xf0, 0x7b, 0x36,
+ 0x9e, 0x25, 0x8b, 0xfa, 0x11, 0xab, 0x6e, 0xf6, 0x35, 0xf7, 0xc5, 0x8b,
+ 0xc5, 0x9f, 0x58, 0xbf, 0x9c, 0xf9, 0x3a, 0x35, 0x62, 0x86, 0x79, 0x5b,
+ 0x8e, 0x5e, 0xef, 0xaf, 0x7d, 0xc6, 0x8b, 0x16, 0x8e, 0x58, 0xbf, 0xd9,
+ 0xce, 0x63, 0x96, 0xeb, 0x15, 0xde, 0x27, 0x27, 0xde, 0x94, 0x46, 0x87,
+ 0x91, 0xb4, 0x24, 0xa3, 0x59, 0x18, 0x0c, 0x88, 0x56, 0xf6, 0x9b, 0x8b,
+ 0x17, 0xf4, 0x6e, 0x1f, 0xff, 0x9b, 0x2c, 0x5d, 0x1d, 0xd2, 0xc5, 0xff,
+ 0x67, 0x62, 0xce, 0x19, 0xe0, 0x96, 0x2d, 0xf5, 0x8a, 0x31, 0x17, 0xd1,
+ 0xb8, 0xef, 0x7d, 0x9b, 0x10, 0xe0, 0x8f, 0x6f, 0xfb, 0xbd, 0xe6, 0x11,
+ 0x63, 0x6e, 0xb1, 0x66, 0x58, 0xa8, 0xdc, 0xf3, 0xba, 0x3d, 0xb8, 0xd9,
+ 0x58, 0xbd, 0x17, 0x25, 0x62, 0xf8, 0x78, 0x51, 0x2c, 0x5c, 0xfe, 0x58,
+ 0xa7, 0x37, 0x5f, 0x23, 0xbf, 0xf7, 0xb3, 0xfd, 0xde, 0x17, 0x50, 0xe2,
+ 0xc5, 0x1d, 0x17, 0xbe, 0x58, 0xee, 0x20, 0xbf, 0xdd, 0x7b, 0xa8, 0x08,
+ 0x8d, 0x58, 0xbf, 0xf4, 0xc4, 0x59, 0xd9, 0x8e, 0x77, 0x58, 0xa6, 0x3f,
+ 0x81, 0x1c, 0x5f, 0x80, 0x06, 0xeb, 0x8b, 0x17, 0xff, 0xfc, 0x37, 0xcd,
+ 0x44, 0x59, 0xdb, 0xf8, 0x39, 0xe7, 0x24, 0xd5, 0x8b, 0x7d, 0xd1, 0x26,
+ 0x22, 0xab, 0xff, 0xcf, 0x14, 0x33, 0xa8, 0x18, 0x76, 0x62, 0x58, 0xb9,
+ 0xbb, 0x96, 0x2f, 0xec, 0xff, 0x81, 0x9d, 0x2c, 0x5f, 0xff, 0xee, 0x67,
+ 0x8c, 0xfe, 0x6f, 0x21, 0x16, 0x0f, 0xef, 0x12, 0xc5, 0xfb, 0xc2, 0x9c,
+ 0xd9, 0x62, 0xb6, 0x56, 0xfd, 0x90, 0xd5, 0x36, 0x15, 0x7b, 0xc2, 0xd3,
+ 0xe5, 0x0c, 0x98, 0x43, 0x5e, 0x2f, 0x0d, 0x92, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0x0e, 0x35, 0x99, 0xdf, 0x58, 0xd8, 0xde, 0xf4, 0xce, 0xfb,
+ 0x8d, 0x50, 0x93, 0x33, 0xbe, 0xfb, 0xeb, 0x86, 0x46, 0xb8, 0xd6, 0x31,
+ 0x99, 0xdf, 0x58, 0xd3, 0xbd, 0x8d, 0x8c, 0x8d, 0x63, 0x8d, 0xf0, 0xce,
+ 0xf2, 0x7b, 0xde, 0xf4, 0xce, 0xf2, 0x7b, 0xeb, 0xde, 0x99, 0x1a, 0xe3,
+ 0x68, 0xda, 0x35, 0xac, 0x5e, 0x8d, 0x5d, 0xe4, 0x6c, 0xb1, 0x7f, 0x46,
+ 0xae, 0xf0, 0xce, 0xdc, 0xf2, 0xc5, 0x77, 0x8b, 0xcc, 0xbd, 0xec, 0xba,
+ 0x68, 0xd2, 0x12, 0x11, 0xb4, 0x78, 0x71, 0xac, 0xba, 0xf7, 0x78, 0x44,
+ 0xb1, 0x7e, 0x8d, 0xfb, 0xd1, 0x79, 0xd6, 0x2f, 0xf7, 0x53, 0xec, 0xce,
+ 0xa0, 0xb1, 0x7f, 0x63, 0xf8, 0xa7, 0xa5, 0x8b, 0x47, 0x2c, 0x58, 0xd5,
+ 0x8a, 0x8d, 0xd1, 0xbd, 0xde, 0x10, 0xc6, 0xa3, 0x38, 0xd6, 0x6b, 0xf2,
+ 0xd8, 0xe1, 0x5b, 0xdc, 0x0b, 0x65, 0x8b, 0x7d, 0x62, 0xe2, 0xd9, 0x62,
+ 0xbb, 0xc3, 0xca, 0xd8, 0x80, 0x42, 0x57, 0x47, 0x46, 0xeb, 0x17, 0xb5,
+ 0xce, 0x2c, 0x5c, 0x5c, 0x58, 0xae, 0xf4, 0xda, 0xf6, 0x1e, 0xb0, 0xd6,
+ 0x2c, 0x35, 0x8a, 0x63, 0x49, 0xc1, 0x2b, 0xc7, 0x9d, 0xd6, 0x2b, 0xbc,
+ 0x46, 0xfc, 0x6c, 0xab, 0xdf, 0x13, 0x30, 0x82, 0xfe, 0x8d, 0x24, 0x26,
+ 0xde, 0x56, 0x2f, 0xe8, 0xd7, 0xde, 0x14, 0x74, 0x9d, 0x62, 0xa3, 0x43,
+ 0xf0, 0x8d, 0x66, 0x97, 0xa3, 0x5c, 0x5b, 0x2c, 0x5f, 0xff, 0x86, 0x66,
+ 0x70, 0xb6, 0xd9, 0xa3, 0xcc, 0x33, 0xf1, 0xcb, 0x17, 0xff, 0xfe, 0x63,
+ 0x0b, 0x22, 0x7d, 0x8c, 0x16, 0xfa, 0xd4, 0x98, 0x67, 0xe3, 0x96, 0x2f,
+ 0xfe, 0x73, 0xc9, 0x64, 0x0c, 0x0b, 0x7c, 0x58, 0xbf, 0x98, 0xb6, 0xfc,
+ 0xc7, 0xac, 0x5e, 0x38, 0x7c, 0x58, 0xbd, 0x09, 0x02, 0xc5, 0xa3, 0x75,
+ 0x8a, 0x1a, 0x21, 0x30, 0xc5, 0x87, 0xe3, 0x87, 0x6f, 0xdf, 0x6f, 0x34,
+ 0x16, 0x2f, 0xf7, 0x7a, 0x67, 0x00, 0x7c, 0xe2, 0xc5, 0xf1, 0x66, 0x69,
+ 0x62, 0xef, 0xb2, 0xc5, 0x68, 0xdc, 0x76, 0x21, 0xbf, 0xc1, 0x99, 0x25,
+ 0x30, 0x95, 0x8a, 0x73, 0xd7, 0x62, 0x3b, 0xdb, 0xed, 0xf5, 0x8b, 0xfe,
+ 0x01, 0x9c, 0x97, 0xd9, 0xbc, 0xb1, 0x7e, 0x9e, 0x77, 0xd6, 0x37, 0x8d,
+ 0xd6, 0x2e, 0x39, 0xd6, 0x29, 0xd1, 0x1d, 0xc3, 0xb1, 0x1d, 0xdf, 0xa7,
+ 0x82, 0xfb, 0xac, 0x51, 0x89, 0x82, 0xc2, 0x15, 0xdc, 0x2f, 0xa5, 0x8b,
+ 0xf4, 0x1b, 0x4d, 0xba, 0xc5, 0xcf, 0x12, 0xc5, 0x49, 0xe0, 0xe1, 0x4d,
+ 0xd1, 0x7d, 0x62, 0xff, 0x16, 0x75, 0x02, 0x6d, 0x96, 0x2b, 0x47, 0xda,
+ 0x02, 0x0e, 0x0c, 0xdf, 0x6e, 0x2d, 0x44, 0xb1, 0x7d, 0x81, 0xe1, 0xab,
+ 0x17, 0xee, 0x09, 0x88, 0x0b, 0x14, 0x62, 0x28, 0x70, 0xbc, 0x89, 0xbc,
+ 0x49, 0x7f, 0x16, 0x76, 0x2c, 0xe2, 0xc5, 0x1c, 0xfa, 0x80, 0x79, 0x7b,
+ 0x8e, 0x05, 0x8b, 0xe7, 0x29, 0xe2, 0xc5, 0x61, 0xf0, 0x39, 0x17, 0xc7,
+ 0x6f, 0xfd, 0x9b, 0x1a, 0xc3, 0xd1, 0x30, 0x4b, 0x17, 0xdc, 0x16, 0x80,
+ 0xb1, 0x73, 0x79, 0x62, 0xe9, 0x3f, 0x46, 0xec, 0x32, 0x4b, 0xc1, 0x04,
+ 0x12, 0x45, 0xef, 0x7f, 0x12, 0x23, 0x0d, 0x0d, 0xf9, 0xcd, 0x62, 0x02,
+ 0xc5, 0x98, 0x8f, 0x63, 0xc6, 0x17, 0xff, 0xff, 0x4e, 0xc6, 0x70, 0x53,
+ 0xd7, 0xbf, 0x87, 0xcf, 0x14, 0x80, 0x12, 0xb1, 0x74, 0x76, 0x2c, 0x5f,
+ 0x7a, 0x2c, 0xf2, 0xc5, 0x86, 0xb1, 0x6e, 0xe5, 0x8a, 0x1a, 0x36, 0x71,
+ 0xd1, 0x86, 0x84, 0x48, 0x18, 0x95, 0x4a, 0xe5, 0xe8, 0xe5, 0x12, 0xe8,
+ 0xb7, 0xef, 0x80, 0x85, 0x39, 0x43, 0xfe, 0xfd, 0xf2, 0xef, 0x91, 0xdd,
+ 0xcb, 0x17, 0x33, 0x2c, 0x5b, 0xee, 0x79, 0x6c, 0x6b, 0x7e, 0x7e, 0xd8,
+ 0x2e, 0x2c, 0x5f, 0xfe, 0x14, 0xf5, 0xfc, 0xda, 0x42, 0xea, 0x1c, 0x58,
+ 0xa9, 0x3f, 0x9e, 0x15, 0x5f, 0xff, 0xc0, 0xd4, 0x99, 0xa9, 0xf7, 0x50,
+ 0x93, 0x74, 0xc1, 0x2c, 0x5f, 0x07, 0xc6, 0x02, 0xc5, 0xd1, 0x7d, 0x62,
+ 0xff, 0xc7, 0x33, 0x1f, 0x4e, 0x79, 0x35, 0x62, 0x9c, 0xf6, 0x58, 0x66,
+ 0xff, 0xcf, 0x11, 0x9f, 0x97, 0xd0, 0xa3, 0xd6, 0x2f, 0xe6, 0x1c, 0x0a,
+ 0x4e, 0xb1, 0x46, 0x27, 0x1f, 0x24, 0x3a, 0x60, 0xfb, 0xe8, 0x08, 0x09,
+ 0x12, 0xff, 0xfb, 0xe4, 0x2f, 0x18, 0x59, 0xdd, 0xe7, 0xce, 0xe5, 0x8b,
+ 0x9c, 0x0b, 0x15, 0xb9, 0xf6, 0xf7, 0x2b, 0x5c, 0x2f, 0xac, 0x5f, 0xfd,
+ 0xd7, 0x0c, 0xe0, 0xa7, 0xac, 0xcf, 0x2c, 0x5e, 0xf0, 0xa3, 0xd6, 0x2f,
+ 0xbb, 0xb5, 0xce, 0x2c, 0x56, 0x1e, 0x43, 0x90, 0xde, 0xe6, 0x6c, 0xb1,
+ 0x7d, 0xe2, 0x9d, 0x96, 0x2a, 0x53, 0x2f, 0x34, 0x99, 0xc6, 0x35, 0x09,
+ 0x06, 0x20, 0x10, 0xf5, 0xff, 0xd8, 0x5d, 0x78, 0xce, 0x00, 0xf9, 0xc5,
+ 0x8b, 0xf4, 0xeb, 0xa8, 0x71, 0x62, 0xff, 0xfc, 0xe5, 0xbf, 0x3c, 0x32,
+ 0x9e, 0xbe, 0xf8, 0x4b, 0x17, 0xe1, 0x79, 0xf6, 0x95, 0x8a, 0xc4, 0x77,
+ 0xee, 0x8e, 0x72, 0xa2, 0x55, 0xbf, 0xdf, 0x9d, 0xb5, 0x38, 0x35, 0x8b,
+ 0xf4, 0x7c, 0x6c, 0x09, 0x3a, 0xc5, 0xf9, 0xf9, 0xec, 0xfa, 0xc5, 0xfe,
+ 0x92, 0x9e, 0x4b, 0x9d, 0x62, 0xf3, 0x7b, 0x8b, 0x14, 0x69, 0xe7, 0x68,
+ 0xc6, 0xf7, 0x70, 0xe5, 0x62, 0xa5, 0x31, 0xec, 0x34, 0xdc, 0xc5, 0xdd,
+ 0x84, 0x47, 0x7f, 0xf9, 0x88, 0x59, 0xe2, 0x6f, 0x96, 0x69, 0x62, 0xf7,
+ 0xdb, 0xbf, 0x58, 0xbf, 0x76, 0x14, 0x33, 0x8b, 0x17, 0xff, 0xb3, 0xe6,
+ 0x49, 0x36, 0x8d, 0x32, 0x74, 0xb1, 0x7f, 0xe7, 0x88, 0xc9, 0xc2, 0x1f,
+ 0xe5, 0x62, 0xf7, 0x30, 0x6b, 0x15, 0x27, 0xb8, 0x03, 0xfb, 0xe0, 0x39,
+ 0x09, 0x62, 0xb1, 0x31, 0x6d, 0xca, 0xda, 0x15, 0x02, 0x21, 0xbc, 0x3c,
+ 0xd9, 0x62, 0xf7, 0x69, 0xd2, 0xc5, 0xfc, 0xd1, 0x3f, 0xc4, 0x05, 0x8a,
+ 0xc3, 0xec, 0x71, 0xef, 0x8f, 0xdf, 0x47, 0x99, 0x3d, 0xe2, 0xc5, 0xf1,
+ 0x19, 0x83, 0x58, 0xbf, 0xc5, 0x31, 0xd8, 0x4e, 0x6a, 0xc5, 0xfe, 0xf3,
+ 0x75, 0xc6, 0xe8, 0x25, 0x8b, 0xfe, 0xd0, 0x30, 0x13, 0x0e, 0x62, 0xc5,
+ 0xa5, 0x62, 0xf3, 0xc9, 0x2c, 0x54, 0x9f, 0x2e, 0x8e, 0x7c, 0x23, 0x5d,
+ 0xe3, 0x68, 0xad, 0x1a, 0x98, 0xa0, 0xee, 0x38, 0x65, 0x61, 0xf1, 0xa5,
+ 0x1b, 0xc3, 0x2b, 0xa8, 0xc9, 0x5e, 0x73, 0xd2, 0x3e, 0x16, 0x91, 0x4a,
+ 0x2e, 0xd4, 0x7e, 0x67, 0x8d, 0x2b, 0xf1, 0xad, 0x01, 0x27, 0xbf, 0x47,
+ 0x28, 0xce, 0x3d, 0x0a, 0xee, 0xc5, 0xa1, 0x16, 0x47, 0x11, 0x86, 0x6b,
+ 0xdd, 0x09, 0xcb, 0xc7, 0x78, 0x2c, 0x58, 0x4b, 0x17, 0xed, 0x67, 0x69,
+ 0xe9, 0x62, 0xf1, 0x67, 0x96, 0x2f, 0xff, 0x75, 0x0e, 0x72, 0x5f, 0xaf,
+ 0x7a, 0x4e, 0xb1, 0x5a, 0x44, 0xa1, 0x15, 0x84, 0x39, 0x7b, 0x33, 0xcb,
+ 0x17, 0xfe, 0xdb, 0x0a, 0x42, 0xf1, 0xad, 0xc5, 0x8b, 0xfd, 0x9d, 0x99,
+ 0xf7, 0xc2, 0x58, 0xb8, 0xbd, 0x87, 0xea, 0x48, 0x37, 0xfb, 0xf2, 0xfe,
+ 0x04, 0xc1, 0x62, 0xf7, 0x9f, 0x16, 0x2f, 0x60, 0xdd, 0x62, 0xfb, 0xa8,
+ 0x49, 0xd6, 0x28, 0xc3, 0xdc, 0x91, 0xcf, 0x0e, 0x53, 0xa3, 0xa7, 0x85,
+ 0x61, 0x42, 0x3e, 0xf0, 0xbd, 0xc5, 0x8b, 0xff, 0xff, 0xe3, 0x4c, 0x2c,
+ 0x34, 0xde, 0xa1, 0xc3, 0x0b, 0x3e, 0x58, 0x11, 0x86, 0x7e, 0x39, 0x62,
+ 0xff, 0xa3, 0xdb, 0xd1, 0x41, 0xf5, 0x12, 0xc5, 0xf8, 0xcd, 0xe4, 0x2e,
+ 0x96, 0x2f, 0xfa, 0x60, 0x13, 0x6b, 0xd3, 0x8b, 0x17, 0xff, 0xff, 0xfd,
+ 0xc3, 0x3f, 0x9b, 0x48, 0x5d, 0x43, 0x86, 0x0b, 0x7d, 0x6a, 0x4c, 0x88,
+ 0xde, 0x8c, 0x33, 0xf1, 0xcb, 0x17, 0xf7, 0x46, 0x45, 0x99, 0xba, 0xc5,
+ 0xff, 0xff, 0xfb, 0xb8, 0xcf, 0xfe, 0x4f, 0xae, 0x85, 0x11, 0x85, 0x9b,
+ 0xb8, 0xc8, 0xc3, 0x3f, 0x1c, 0xb1, 0x5d, 0xea, 0xea, 0xdf, 0x7d, 0x8e,
+ 0xcc, 0x29, 0x86, 0x61, 0x91, 0xbd, 0x6e, 0x6a, 0xe3, 0xcd, 0x08, 0xa0,
+ 0x1f, 0x91, 0x6f, 0x8e, 0x45, 0x0a, 0x8e, 0xc6, 0x57, 0xff, 0xff, 0xff,
+ 0xff, 0x39, 0x9f, 0xce, 0x0a, 0x7a, 0x2c, 0xf7, 0x3e, 0x73, 0x3e, 0xf8,
+ 0x59, 0xd9, 0xf0, 0xb3, 0xa8, 0x71, 0xcd, 0x30, 0xcf, 0xc7, 0x2c, 0x5f,
+ 0xbf, 0x20, 0x98, 0xf5, 0x8b, 0x8e, 0xeb, 0x14, 0xb1, 0x40, 0x34, 0x61,
+ 0x0b, 0xdf, 0xd0, 0x81, 0xe2, 0x9e, 0xe5, 0x8b, 0x01, 0x62, 0x9d, 0x16,
+ 0xa0, 0x4e, 0x22, 0x21, 0x19, 0xdd, 0x1d, 0x2b, 0x17, 0xa4, 0xd7, 0x58,
+ 0xbf, 0x4c, 0x46, 0x66, 0xcb, 0x17, 0xc3, 0x9e, 0x4a, 0xc5, 0xd2, 0x75,
+ 0x8b, 0xa7, 0xa5, 0x8b, 0xfb, 0x98, 0x7e, 0xc3, 0xc5, 0x8b, 0xed, 0xb6,
+ 0x17, 0x96, 0x28, 0xc4, 0x69, 0x49, 0x58, 0xc8, 0xa2, 0x17, 0xe0, 0xc0,
+ 0x8c, 0x28, 0x93, 0x61, 0xe0, 0xd7, 0xa1, 0xdf, 0x74, 0x74, 0x6e, 0xb1,
+ 0x7f, 0xf8, 0x12, 0x5b, 0x99, 0x84, 0x28, 0x67, 0x16, 0x2f, 0xc0, 0xd3,
+ 0xf4, 0x05, 0x8b, 0xf7, 0x9a, 0x0e, 0x05, 0x8b, 0xf8, 0xce, 0xbc, 0x52,
+ 0x35, 0x8b, 0x37, 0x48, 0x82, 0x22, 0xae, 0x14, 0x5f, 0x67, 0xde, 0x0b,
+ 0x17, 0xf6, 0x70, 0xb3, 0xb3, 0x2c, 0x5c, 0x23, 0x98, 0x7a, 0x12, 0x45,
+ 0x7f, 0x31, 0x66, 0xc1, 0xc1, 0x62, 0xfd, 0x31, 0x33, 0x69, 0x62, 0x80,
+ 0x7a, 0xfc, 0x2f, 0xae, 0x93, 0xf9, 0xfc, 0x33, 0x79, 0x08, 0x5f, 0x42,
+ 0x16, 0xf1, 0x90, 0xdd, 0x62, 0xfe, 0x33, 0x8d, 0x3d, 0x41, 0x62, 0xe0,
+ 0x71, 0x62, 0x9c, 0xf2, 0x18, 0xc2, 0xff, 0xf8, 0xc2, 0xcf, 0x3e, 0x6c,
+ 0x53, 0xe7, 0x3a, 0xc5, 0xff, 0x70, 0xcc, 0x29, 0x17, 0x7f, 0xc5, 0x8b,
+ 0xc6, 0x75, 0x05, 0x8b, 0xfc, 0x7f, 0xbf, 0x8a, 0x4e, 0xb1, 0x7c, 0x79,
+ 0x07, 0x16, 0x2b, 0xbe, 0xab, 0xe9, 0xf3, 0x1c, 0x5e, 0x47, 0x38, 0x69,
+ 0xab, 0xca, 0x19, 0x3a, 0x77, 0xda, 0x00, 0x40, 0x49, 0xfc, 0x3f, 0x11,
+ 0x00, 0x46, 0x77, 0x42, 0x34, 0x58, 0xbf, 0x46, 0xe6, 0x8e, 0x76, 0x58,
+ 0xbf, 0xff, 0xb4, 0x61, 0x67, 0x6c, 0xd4, 0x0c, 0x91, 0xb4, 0x5c, 0x58,
+ 0xbf, 0xfd, 0xaf, 0x84, 0xc3, 0x30, 0x30, 0x01, 0xfb, 0x96, 0x2f, 0xfe,
+ 0xc0, 0xbb, 0x8e, 0x27, 0x3e, 0x10, 0x16, 0x2f, 0xff, 0xfd, 0xd4, 0x9a,
+ 0x58, 0x3f, 0xbc, 0x46, 0x73, 0x3a, 0x86, 0xb0, 0x25, 0x8a, 0x74, 0x5d,
+ 0x12, 0x45, 0x62, 0x71, 0xac, 0xc0, 0x51, 0x86, 0x5f, 0xd2, 0x6e, 0x0e,
+ 0x3a, 0x37, 0x58, 0xbe, 0xf0, 0xa7, 0x65, 0x8b, 0xf3, 0x6b, 0x8e, 0x35,
+ 0x8b, 0xf0, 0xc3, 0xeb, 0x06, 0xb1, 0x50, 0x3d, 0x32, 0x28, 0xbf, 0xb3,
+ 0xf8, 0x79, 0xdd, 0x62, 0xe1, 0xe2, 0xc5, 0x49, 0xf3, 0x40, 0x85, 0xcb,
+ 0xaf, 0xcf, 0xa7, 0xed, 0x8b, 0x15, 0x04, 0xda, 0x9c, 0xdf, 0xd0, 0xdd,
+ 0xee, 0x2d, 0xbe, 0x8e, 0xcd, 0x4a, 0xc5, 0xfd, 0x3c, 0xfc, 0x97, 0x96,
+ 0x2f, 0xfe, 0xc2, 0x33, 0xb9, 0xff, 0xb3, 0xe6, 0x96, 0x2f, 0xff, 0xb3,
+ 0xde, 0x90, 0x8c, 0xcf, 0xe0, 0x8b, 0x75, 0x8b, 0xdd, 0x43, 0x87, 0x44,
+ 0xd7, 0xd2, 0x2d, 0x1e, 0xb1, 0x60, 0xd6, 0x2f, 0x7b, 0x38, 0xb1, 0x50,
+ 0x4d, 0x0b, 0x21, 0x8f, 0xb9, 0xb0, 0x05, 0x44, 0x27, 0x7f, 0xff, 0x8b,
+ 0x37, 0xfb, 0x96, 0x0b, 0xaf, 0x18, 0xc1, 0x61, 0xab, 0x17, 0x9f, 0x6e,
+ 0x2c, 0x5f, 0xfb, 0x37, 0x6d, 0xbf, 0x9b, 0xe1, 0x2c, 0x5e, 0xcd, 0x84,
+ 0xb1, 0x60, 0x8c, 0x47, 0x06, 0x32, 0x7c, 0x78, 0x90, 0x2f, 0xc2, 0x9f,
+ 0x94, 0xac, 0x5f, 0xfe, 0xd6, 0x3e, 0xc6, 0x72, 0x5f, 0x66, 0xf2, 0xc5,
+ 0x8d, 0x19, 0xf9, 0xe1, 0x3d, 0xfd, 0x0e, 0x1a, 0x29, 0xe9, 0x62, 0xfb,
+ 0x06, 0xd0, 0x58, 0xae, 0x8f, 0x4c, 0x23, 0x1b, 0xed, 0x4c, 0xec, 0xb1,
+ 0x7d, 0x14, 0xf9, 0x96, 0x2f, 0xf4, 0xed, 0xc9, 0x89, 0xfb, 0x2c, 0x5e,
+ 0x88, 0x70, 0x58, 0xad, 0x8f, 0x5b, 0x0d, 0xee, 0x60, 0xb8, 0x8b, 0xe1,
+ 0x11, 0x86, 0xf3, 0x7b, 0xb7, 0x83, 0x58, 0xa9, 0x54, 0xe3, 0x90, 0xb6,
+ 0x77, 0xb2, 0x87, 0x10, 0x47, 0xb7, 0x4f, 0x16, 0x2e, 0x92, 0x58, 0xaf,
+ 0x1a, 0xd0, 0xc5, 0xef, 0xf9, 0xf5, 0xb0, 0x81, 0x85, 0x8b, 0x17, 0x44,
+ 0x75, 0x8b, 0xfd, 0x0e, 0x78, 0x58, 0x33, 0x22, 0x3d, 0x20, 0x1c, 0xdf,
+ 0xff, 0x60, 0xfe, 0x20, 0xb8, 0xfe, 0xfb, 0xb0, 0x16, 0x2b, 0xa4, 0x4f,
+ 0x12, 0x6d, 0xc7, 0x82, 0xc5, 0xff, 0xe9, 0xd6, 0xe6, 0x83, 0x18, 0xba,
+ 0x87, 0x16, 0x2a, 0x07, 0xcb, 0xc1, 0x8b, 0xec, 0xd4, 0x9d, 0x62, 0xf1,
+ 0x67, 0x63, 0x0f, 0x10, 0x88, 0xaf, 0xff, 0xfb, 0x85, 0x83, 0x70, 0x8c,
+ 0x2c, 0xee, 0xf3, 0xf0, 0x53, 0xa5, 0x8a, 0xd2, 0x6d, 0x5c, 0x86, 0x67,
+ 0x8d, 0x2f, 0xf1, 0x1a, 0x58, 0xfd, 0x79, 0x62, 0xdd, 0x96, 0x2b, 0x0f,
+ 0x23, 0x86, 0x95, 0x28, 0x9f, 0x13, 0xf5, 0xb7, 0x58, 0xbf, 0xc1, 0x6b,
+ 0x0e, 0x76, 0x25, 0x8b, 0xe9, 0xcf, 0xf1, 0x62, 0xe7, 0xd9, 0x62, 0xa2,
+ 0x37, 0x5e, 0x22, 0xa3, 0xa2, 0x8d, 0x84, 0xc0, 0xdd, 0x7f, 0xb7, 0x2c,
+ 0x1f, 0xdb, 0x8b, 0x17, 0xf0, 0x30, 0x87, 0xf9, 0x58, 0xbf, 0xbe, 0xe4,
+ 0x00, 0xce, 0xb1, 0x4e, 0x7b, 0x9e, 0x2d, 0xb8, 0x6e, 0xb1, 0x7f, 0xff,
+ 0x7d, 0xf0, 0xb1, 0xc7, 0x92, 0x06, 0xdd, 0xb4, 0xb1, 0x7f, 0xb6, 0x93,
+ 0x94, 0xf4, 0x05, 0x8b, 0xf8, 0xcc, 0xd6, 0xf3, 0x8b, 0x15, 0x29, 0xc2,
+ 0x42, 0x12, 0x1b, 0x90, 0xf4, 0x2e, 0xcb, 0x01, 0x9a, 0xdf, 0x00, 0x5a,
+ 0x95, 0x8b, 0xe3, 0x1b, 0x38, 0xb1, 0x46, 0x9e, 0x37, 0xc8, 0xea, 0x51,
+ 0x8f, 0x90, 0xa4, 0xb0, 0x96, 0x2f, 0xf9, 0xa3, 0xcb, 0x07, 0x25, 0xe5,
+ 0x8b, 0xfd, 0x33, 0xc7, 0xd9, 0x8e, 0xb1, 0x7e, 0x29, 0x86, 0x79, 0x62,
+ 0xb1, 0x12, 0x84, 0x75, 0xe3, 0x3b, 0xb3, 0x65, 0x8b, 0xe2, 0x2c, 0xf2,
+ 0xc5, 0xdb, 0x09, 0x62, 0xe9, 0x35, 0x62, 0x96, 0x2e, 0x6e, 0x2c, 0x51,
+ 0xcd, 0x18, 0x41, 0x97, 0xd8, 0x1e, 0x1d, 0x62, 0xf8, 0xd1, 0x68, 0xd5,
+ 0x8b, 0xe0, 0x1d, 0xf8, 0xb1, 0x46, 0x9e, 0x4e, 0x89, 0xaf, 0x36, 0xa0,
+ 0x62, 0x6d, 0x9d, 0xe9, 0x74, 0x8c, 0x39, 0x09, 0xc6, 0x7e, 0x76, 0x44,
+ 0x41, 0xb6, 0x51, 0x8d, 0x92, 0xf4, 0x6e, 0x3b, 0x31, 0xde, 0xe4, 0x73,
+ 0xdd, 0x22, 0xbc, 0x6c, 0xfa, 0x97, 0x42, 0x78, 0x40, 0x7e, 0x58, 0xdb,
+ 0x43, 0x14, 0xa5, 0x3d, 0x70, 0x98, 0x52, 0x84, 0xaf, 0xfd, 0xa7, 0xd9,
+ 0x8e, 0x5d, 0x08, 0x96, 0x2d, 0x1e, 0xb1, 0x6f, 0x2c, 0x5d, 0x20, 0x58,
+ 0xbf, 0xfc, 0xe2, 0xef, 0xe4, 0xce, 0x08, 0x07, 0xcf, 0x2c, 0x57, 0x47,
+ 0xd1, 0xa1, 0x7b, 0xff, 0xb7, 0xfc, 0xf3, 0xda, 0x9e, 0xbe, 0xeb, 0x17,
+ 0xf4, 0x39, 0x82, 0xd0, 0x16, 0x2f, 0xd9, 0xcc, 0x72, 0x58, 0xbe, 0x28,
+ 0x9c, 0xfd, 0x1e, 0xaf, 0xcb, 0xef, 0xfd, 0x3b, 0xf2, 0x5f, 0xaf, 0x49,
+ 0xd6, 0x29, 0x62, 0xe1, 0x47, 0xac, 0x5f, 0xdb, 0x60, 0x58, 0xe3, 0x58,
+ 0xad, 0x1e, 0x57, 0x06, 0xea, 0x07, 0xf1, 0xe5, 0x6b, 0x8d, 0x3a, 0xc5,
+ 0x4a, 0x79, 0x2d, 0x09, 0xc2, 0x3a, 0x14, 0x2e, 0x23, 0x88, 0xaf, 0x81,
+ 0xcd, 0xbc, 0xb1, 0x7f, 0x37, 0xe4, 0xa6, 0x0b, 0x17, 0xff, 0xfe, 0xf6,
+ 0x49, 0x66, 0xe4, 0xdb, 0x4e, 0xb5, 0x3e, 0xfe, 0x0d, 0x62, 0xfb, 0xb1,
+ 0x67, 0x0c, 0x44, 0xbe, 0x16, 0x5f, 0xff, 0x61, 0x61, 0xbf, 0x68, 0x7c,
+ 0x26, 0x0c, 0xeb, 0x17, 0xfe, 0x63, 0x4c, 0xf3, 0x31, 0x19, 0xb2, 0xc5,
+ 0x4a, 0x71, 0x6f, 0x0b, 0xcf, 0x9d, 0x92, 0x95, 0xf8, 0x18, 0x79, 0xdd,
+ 0x62, 0xf3, 0x7b, 0x8b, 0x17, 0x0b, 0x65, 0x8a, 0x81, 0xb6, 0xd0, 0xed,
+ 0xfb, 0x21, 0xf6, 0x82, 0xc5, 0x44, 0x79, 0x3f, 0x21, 0xb1, 0x4a, 0x32,
+ 0xfd, 0x0a, 0x8b, 0xbf, 0x1e, 0xb1, 0x7f, 0xff, 0xff, 0xf7, 0xb9, 0x24,
+ 0x66, 0xe4, 0x2d, 0xbf, 0x83, 0xd3, 0x19, 0xee, 0x7f, 0x1c, 0x7e, 0x6f,
+ 0xc0, 0x0b, 0x17, 0xf9, 0x88, 0x3f, 0xfe, 0x46, 0xb1, 0x7f, 0xfd, 0xee,
+ 0x4e, 0x19, 0xa9, 0xf3, 0xee, 0xe3, 0x58, 0xbb, 0xa0, 0x96, 0x2c, 0x12,
+ 0xc5, 0xdb, 0x98, 0x33, 0x5b, 0xd0, 0xd5, 0x71, 0x15, 0xc2, 0x7e, 0xbd,
+ 0xd4, 0x9a, 0xb1, 0x7f, 0xff, 0xf6, 0xa4, 0xcf, 0xe7, 0x77, 0xa7, 0x5b,
+ 0x96, 0x7b, 0x42, 0xea, 0x1c, 0x58, 0xbc, 0x17, 0xf0, 0x91, 0x31, 0xe1,
+ 0xfb, 0xe1, 0x44, 0xc3, 0x58, 0xbf, 0x67, 0xb5, 0x81, 0x2c, 0x5b, 0x73,
+ 0x0f, 0x37, 0xe4, 0x95, 0x28, 0xab, 0x78, 0x40, 0xdd, 0xa8, 0x2c, 0x5f,
+ 0xfc, 0x2c, 0x23, 0x4c, 0xf9, 0x67, 0xb8, 0xb1, 0x7f, 0xfe, 0x0e, 0x42,
+ 0xdf, 0xee, 0x7c, 0xe8, 0xcc, 0xeb, 0xcb, 0x17, 0xf3, 0x73, 0x3c, 0x1e,
+ 0xcb, 0x14, 0x62, 0x23, 0x0d, 0x5c, 0xbe, 0x33, 0x70, 0xa5, 0x62, 0xa0,
+ 0x79, 0x67, 0x25, 0xa9, 0x5c, 0xb0, 0x81, 0x66, 0x0d, 0xf5, 0x0a, 0x47,
+ 0x87, 0x16, 0xa3, 0x66, 0x39, 0x37, 0xc6, 0x1a, 0x31, 0xdb, 0xf4, 0x6d,
+ 0xa7, 0x93, 0x56, 0x2f, 0xde, 0xfc, 0xbe, 0xeb, 0x14, 0x69, 0xeb, 0xf8,
+ 0xba, 0xf8, 0x99, 0xbe, 0xb1, 0x7f, 0xff, 0xb0, 0xfa, 0xd3, 0x98, 0x5d,
+ 0x60, 0x45, 0x82, 0xc3, 0x56, 0x28, 0x68, 0x84, 0xf9, 0x0d, 0x12, 0x32,
+ 0xb9, 0x0a, 0x7b, 0xf6, 0x73, 0xcd, 0xa5, 0x8b, 0xff, 0xdc, 0xc6, 0x23,
+ 0x39, 0xd4, 0x94, 0xf1, 0x62, 0xd0, 0xf9, 0xf9, 0x78, 0xa2, 0xfe, 0x91,
+ 0xcf, 0xe6, 0x0b, 0x17, 0xfa, 0x7c, 0x63, 0x6e, 0xfd, 0x96, 0x2b, 0x47,
+ 0xc8, 0x45, 0xb7, 0xff, 0xfe, 0x7e, 0xbc, 0xdf, 0x2c, 0x1f, 0xde, 0x2e,
+ 0x6f, 0x8e, 0x51, 0x2c, 0x5f, 0xff, 0x4f, 0x8c, 0x21, 0x77, 0x19, 0x9e,
+ 0x8e, 0xcf, 0x2c, 0x54, 0xa6, 0xe6, 0xf0, 0x8c, 0xd1, 0x08, 0x9b, 0xae,
+ 0x6f, 0x2c, 0x5f, 0xe3, 0x3c, 0x4d, 0xe9, 0xf2, 0xc5, 0xff, 0x40, 0xc9,
+ 0x33, 0xdc, 0x14, 0x7a, 0xc5, 0xdf, 0x93, 0x4f, 0xd3, 0x46, 0x97, 0xf7,
+ 0x50, 0x7f, 0x88, 0xeb, 0x17, 0x3e, 0xcb, 0x14, 0x61, 0xe4, 0x78, 0xc2,
+ 0xbe, 0x99, 0x20, 0x21, 0x16, 0x4e, 0xd7, 0xe0, 0x9b, 0xf1, 0x46, 0xeb,
+ 0x17, 0xfd, 0x83, 0x33, 0xc6, 0xb8, 0x5c, 0x58, 0xb6, 0x68, 0xfb, 0x7b,
+ 0x18, 0x5f, 0xfe, 0x08, 0x7f, 0x9d, 0x7d, 0xf0, 0xb3, 0xb2, 0xc5, 0xff,
+ 0xe9, 0x26, 0x33, 0xec, 0xfc, 0xe3, 0x9d, 0x62, 0xff, 0xed, 0x4b, 0x8f,
+ 0x3f, 0x86, 0x9a, 0xcb, 0x17, 0xf3, 0x7c, 0xd9, 0xd3, 0x2c, 0x5f, 0x6b,
+ 0x05, 0xb2, 0xc5, 0xfe, 0xd6, 0x39, 0x6d, 0x3b, 0xac, 0x5f, 0xa5, 0xf6,
+ 0x6f, 0x2c, 0x5e, 0xd4, 0x46, 0x61, 0xee, 0x70, 0xd2, 0xa5, 0x54, 0x40,
+ 0xe1, 0x45, 0x85, 0x3f, 0x4c, 0x64, 0x92, 0x45, 0xf1, 0x70, 0xa1, 0x01,
+ 0x7f, 0xf8, 0x44, 0x0e, 0x19, 0xc1, 0x7a, 0x7d, 0xc5, 0x8b, 0xfe, 0xe6,
+ 0xb5, 0x9f, 0xea, 0x1c, 0x58, 0xac, 0x44, 0x48, 0x93, 0x6e, 0x60, 0x2c,
+ 0x5f, 0xff, 0x18, 0x53, 0xc9, 0xd8, 0xb0, 0x7f, 0x78, 0x96, 0x2f, 0xff,
+ 0xfe, 0xe6, 0x8a, 0x62, 0x30, 0x3f, 0x3c, 0x33, 0xaf, 0x67, 0x62, 0xce,
+ 0x2c, 0x56, 0x91, 0x90, 0x4a, 0x35, 0x04, 0xc8, 0xfc, 0x44, 0x28, 0x6f,
+ 0xd2, 0xc5, 0xff, 0xf1, 0x30, 0x0c, 0xf6, 0x7c, 0xb3, 0xdf, 0x75, 0x8b,
+ 0xff, 0xfc, 0xc6, 0x99, 0xdd, 0xe7, 0x23, 0x79, 0x38, 0x43, 0xfc, 0xac,
+ 0x5f, 0x49, 0x6e, 0xdf, 0x45, 0xa7, 0x93, 0xef, 0xff, 0x9b, 0x4d, 0xfe,
+ 0xa1, 0x9e, 0x62, 0x0c, 0x0b, 0x14, 0xb1, 0x7f, 0x4b, 0x93, 0x68, 0xd5,
+ 0x8b, 0xbc, 0x61, 0xa6, 0xe7, 0xe1, 0x97, 0x8d, 0x36, 0x56, 0x2d, 0x05,
+ 0x8a, 0x73, 0x63, 0x10, 0xfd, 0xff, 0xd9, 0xd4, 0x0c, 0xc8, 0xbf, 0x24,
+ 0x6a, 0xc5, 0x4a, 0xa4, 0xc3, 0x61, 0x81, 0xb9, 0xcf, 0x50, 0x8a, 0xd3,
+ 0x01, 0xc8, 0x6f, 0xf6, 0x8b, 0x37, 0xc9, 0x8f, 0x58, 0xbf, 0xff, 0xef,
+ 0xe7, 0x46, 0x6d, 0x8e, 0x5e, 0xcd, 0xbd, 0xc2, 0x63, 0x56, 0x2f, 0xfd,
+ 0xee, 0x76, 0x7f, 0x4e, 0x14, 0x4b, 0x15, 0xf4, 0x55, 0x93, 0x55, 0xff,
+ 0xb5, 0xb6, 0x67, 0x06, 0x4d, 0xf5, 0x8b, 0xf6, 0x9f, 0x93, 0xd2, 0xc5,
+ 0x4a, 0x6d, 0x79, 0x0e, 0x17, 0x22, 0x63, 0xfb, 0xff, 0xf4, 0x38, 0x01,
+ 0x44, 0x66, 0x3e, 0x9c, 0xf2, 0x6a, 0xc5, 0xfd, 0xde, 0xc5, 0x07, 0xf7,
+ 0x16, 0x2f, 0x70, 0x3e, 0x2c, 0x56, 0xc7, 0xa8, 0x73, 0x5b, 0xa4, 0x0b,
+ 0x17, 0xe2, 0xf7, 0xf3, 0xb9, 0x62, 0xfd, 0x17, 0x1b, 0x46, 0xac, 0x5e,
+ 0x60, 0xb5, 0x27, 0xad, 0x85, 0x77, 0xe8, 0x9c, 0xa4, 0xeb, 0x17, 0xe9,
+ 0x7d, 0xa4, 0xd5, 0x8b, 0x1b, 0x27, 0xa3, 0xf2, 0x8b, 0xe3, 0x3a, 0x83,
+ 0xac, 0x51, 0x1e, 0x6f, 0x8a, 0x2f, 0xe7, 0xee, 0x68, 0x39, 0x2c, 0x5f,
+ 0xc6, 0xb4, 0x0a, 0x4e, 0xb1, 0x52, 0x7f, 0xd8, 0x42, 0xe5, 0xf7, 0xf1,
+ 0xfc, 0x6f, 0xc5, 0xdc, 0xb1, 0x7e, 0x3f, 0x0a, 0x74, 0xb1, 0x7f, 0xd1,
+ 0xe3, 0x11, 0x78, 0xe4, 0xeb, 0x15, 0x28, 0x98, 0xc3, 0x41, 0x14, 0x5f,
+ 0xfb, 0xcf, 0xa6, 0x21, 0xfe, 0x78, 0xb1, 0x50, 0x57, 0xf5, 0xd1, 0xfb,
+ 0xc2, 0xb6, 0x22, 0x3d, 0x36, 0xfe, 0x34, 0xe2, 0x86, 0x27, 0x8b, 0xaf,
+ 0x9f, 0x76, 0xd2, 0xc5, 0xe3, 0xb0, 0x4b, 0x16, 0xe4, 0x0f, 0x05, 0x88,
+ 0xef, 0xb3, 0xb3, 0x69, 0x62, 0xfe, 0x1e, 0x14, 0x3f, 0x8b, 0x15, 0x27,
+ 0xa2, 0xe4, 0x97, 0xff, 0xb1, 0xc2, 0x30, 0xb0, 0x05, 0x8d, 0x12, 0xc5,
+ 0xf3, 0xeb, 0x0d, 0x58, 0xb7, 0x0c, 0x3e, 0xd8, 0xe4, 0xab, 0xfe, 0xfb,
+ 0xea, 0x2f, 0xb6, 0x69, 0x62, 0xff, 0xff, 0xfe, 0x07, 0x0b, 0x1b, 0xa3,
+ 0x07, 0xf1, 0x18, 0x59, 0xd4, 0x30, 0x5b, 0x16, 0x37, 0x4b, 0x15, 0x88,
+ 0xf3, 0xdc, 0xb1, 0xce, 0xaf, 0xff, 0xb5, 0x8c, 0x11, 0x83, 0x29, 0xdc,
+ 0xe4, 0xeb, 0x17, 0xb3, 0x90, 0x58, 0xb9, 0xb7, 0x54, 0x93, 0x05, 0x8d,
+ 0x58, 0xaf, 0x9e, 0xab, 0x0e, 0x88, 0x96, 0xfd, 0xb3, 0x1f, 0x91, 0xcb,
+ 0x17, 0xfb, 0x86, 0x45, 0xcf, 0xc8, 0xd6, 0x2f, 0xf4, 0x82, 0x7b, 0xbf,
+ 0x9c, 0x58, 0xa8, 0x8f, 0xb4, 0x8d, 0xef, 0xff, 0xf7, 0xb9, 0x86, 0xbe,
+ 0x8c, 0x0f, 0xcf, 0xf7, 0x37, 0xee, 0xb1, 0x52, 0xb8, 0x39, 0xb3, 0xc6,
+ 0x47, 0x00, 0x69, 0x7e, 0xf0, 0xa6, 0x72, 0xe6, 0x84, 0xd0, 0x64, 0x57,
+ 0xfb, 0x7c, 0x26, 0x39, 0x1d, 0x62, 0xff, 0xff, 0x7b, 0x81, 0xf0, 0xcc,
+ 0x87, 0xe5, 0xf4, 0x03, 0xb4, 0x16, 0x2f, 0xf8, 0xba, 0x87, 0x3d, 0x3a,
+ 0x89, 0x62, 0xf1, 0x67, 0xd6, 0x2f, 0xfb, 0x71, 0x37, 0xf3, 0xcd, 0xf5,
+ 0x8a, 0x19, 0xeb, 0x74, 0x39, 0x58, 0x8b, 0x5f, 0x42, 0x4a, 0xff, 0xcd,
+ 0xd6, 0x3e, 0x9c, 0xf2, 0x6a, 0xc5, 0xe0, 0xe4, 0x96, 0x2f, 0x63, 0x81,
+ 0x62, 0xd8, 0xb1, 0x6c, 0x01, 0xad, 0xec, 0x39, 0x73, 0xec, 0xb1, 0x4b,
+ 0x0c, 0x5c, 0x5d, 0xac, 0x58, 0xb7, 0x46, 0x22, 0xec, 0x92, 0xb8, 0x80,
+ 0x21, 0xab, 0xd9, 0xd7, 0x96, 0x2a, 0x55, 0x67, 0xe1, 0x9b, 0xc6, 0x33,
+ 0xa2, 0x76, 0x87, 0xd4, 0x72, 0x25, 0xec, 0x16, 0x96, 0x2f, 0x49, 0x79,
+ 0x62, 0xd1, 0x2c, 0x5f, 0xe0, 0x3c, 0x3e, 0xe4, 0x05, 0x8b, 0xe1, 0x67,
+ 0x44, 0xb1, 0x5b, 0x1f, 0x4b, 0x89, 0x9c, 0xce, 0xc1, 0x2c, 0x5c, 0xe3,
+ 0x58, 0xa8, 0xf3, 0x55, 0xc1, 0x3b, 0xfd, 0xd4, 0x85, 0xc2, 0x14, 0x4b,
+ 0x17, 0x0e, 0x25, 0x8b, 0xfe, 0xd6, 0x0f, 0xf2, 0x11, 0xc4, 0xb1, 0x7f,
+ 0x7f, 0x06, 0xe5, 0xe5, 0x8b, 0x6c, 0xb1, 0x77, 0xf8, 0xb1, 0x46, 0x9a,
+ 0xb6, 0x13, 0xbf, 0x89, 0x82, 0xf6, 0x7d, 0x62, 0xfa, 0x3a, 0x75, 0x8b,
+ 0x15, 0x29, 0xea, 0x62, 0xce, 0x89, 0x0e, 0x6f, 0xf1, 0x9f, 0x1d, 0x84,
+ 0xb1, 0x1c, 0x42, 0x19, 0x75, 0xfb, 0xe2, 0x37, 0x36, 0x58, 0xbf, 0x61,
+ 0xce, 0xc7, 0x58, 0xb8, 0xe0, 0x58, 0xa3, 0x11, 0xda, 0x38, 0x41, 0x68,
+ 0xac, 0x05, 0x16, 0xfb, 0xab, 0x89, 0x69, 0x68, 0xd7, 0xf6, 0xa7, 0xc4,
+ 0xc0, 0x58, 0xad, 0x1e, 0xef, 0x71, 0x85, 0xfd, 0xd4, 0x0a, 0x73, 0x8b,
+ 0x17, 0xfe, 0x6c, 0xfb, 0x7d, 0xb3, 0xec, 0xb1, 0x7f, 0xa2, 0xcc, 0x34,
+ 0xd9, 0x89, 0x62, 0xff, 0xd8, 0xfb, 0xe7, 0xa4, 0xbd, 0xc5, 0x8b, 0xff,
+ 0x70, 0x5d, 0xc6, 0x70, 0xdd, 0x49, 0x2c, 0x51, 0x88, 0x83, 0x73, 0xea,
+ 0x31, 0x34, 0x7f, 0x97, 0x11, 0xe7, 0x74, 0x2e, 0xab, 0xa5, 0xdb, 0x57,
+ 0x9c, 0x03, 0x68, 0xdb, 0x2f, 0xef, 0x66, 0xd9, 0xa8, 0x96, 0x2f, 0xdf,
+ 0x30, 0x13, 0x1e, 0xb1, 0x7f, 0xfc, 0xfc, 0x33, 0xed, 0xcf, 0x4c, 0x5c,
+ 0xfe, 0x2c, 0x54, 0xa2, 0xbd, 0x8c, 0x00, 0x5b, 0x4b, 0x17, 0xf0, 0x9c,
+ 0x6e, 0x4e, 0xb1, 0x63, 0x5c, 0xdc, 0x1c, 0x32, 0xfc, 0xdc, 0xfb, 0x41,
+ 0x62, 0xf9, 0xa0, 0xe7, 0x58, 0xbf, 0x6e, 0xda, 0xcd, 0xd6, 0x2f, 0xf8,
+ 0x5d, 0x43, 0x86, 0x73, 0xdb, 0xac, 0x5f, 0xc5, 0xe8, 0x60, 0x38, 0xb1,
+ 0x78, 0xd6, 0xe1, 0x88, 0x97, 0xd1, 0x53, 0x1f, 0xd7, 0xd1, 0xf7, 0xe8,
+ 0x5c, 0xd6, 0x93, 0x72, 0xf9, 0x38, 0x51, 0x91, 0xdf, 0xbe, 0xcf, 0xb4,
+ 0xac, 0x5f, 0x37, 0xdb, 0xa5, 0x8a, 0x73, 0xcb, 0xec, 0x51, 0x7a, 0x13,
+ 0xd2, 0xc5, 0xfc, 0x6e, 0xb5, 0x9d, 0x71, 0x62, 0xff, 0xfc, 0x59, 0xd7,
+ 0x8c, 0xfb, 0x76, 0x30, 0x7f, 0x16, 0xcb, 0x17, 0xef, 0xce, 0xd8, 0x12,
+ 0xc5, 0xf9, 0xf3, 0xb3, 0x69, 0x62, 0xa5, 0x16, 0x03, 0x5d, 0xe1, 0x55,
+ 0xfd, 0xc8, 0x3f, 0x04, 0x75, 0x8a, 0x39, 0xef, 0x78, 0xbe, 0xfe, 0xce,
+ 0x41, 0xc1, 0x8b, 0x17, 0xa1, 0x9e, 0x58, 0xa8, 0x1e, 0x57, 0x8b, 0x6a,
+ 0x55, 0x48, 0xe4, 0x20, 0xfa, 0x23, 0x71, 0xe6, 0x8c, 0xfc, 0x4d, 0x97,
+ 0xfc, 0x59, 0xe1, 0x00, 0xed, 0x05, 0x8b, 0xff, 0xc3, 0x7c, 0x08, 0xce,
+ 0x4b, 0xec, 0xde, 0x58, 0xbf, 0xfe, 0xd8, 0xb3, 0xda, 0x73, 0x73, 0xef,
+ 0x91, 0x2c, 0x5f, 0x3f, 0x27, 0xa5, 0x8b, 0xfb, 0x63, 0x1a, 0x0e, 0x4b,
+ 0x15, 0xb2, 0x65, 0x1d, 0x1c, 0xe9, 0x33, 0xea, 0x24, 0x47, 0x7e, 0xeb,
+ 0x72, 0x9e, 0xcb, 0x17, 0xf0, 0x46, 0x44, 0x4e, 0x35, 0x8b, 0xff, 0x80,
+ 0x42, 0xe1, 0x67, 0xb8, 0xfc, 0x58, 0xac, 0x3f, 0x52, 0x31, 0xbf, 0x19,
+ 0xc2, 0x9d, 0x2c, 0x5f, 0x3f, 0x8a, 0x56, 0x2d, 0x87, 0x3c, 0xae, 0x14,
+ 0xdf, 0xcd, 0xa8, 0xa0, 0xff, 0x58, 0xbf, 0xc2, 0xdb, 0xef, 0xdb, 0x22,
+ 0x58, 0xbf, 0x83, 0xff, 0xe4, 0xb7, 0x58, 0xbe, 0x29, 0x3f, 0x16, 0x2f,
+ 0xb3, 0xec, 0x75, 0x8b, 0x9b, 0xae, 0x1f, 0xa7, 0x8c, 0x03, 0x22, 0xa9,
+ 0x55, 0x2b, 0x89, 0x8f, 0x0a, 0x1f, 0xb5, 0x31, 0x3f, 0x0b, 0xc5, 0x0a,
+ 0xcb, 0xfc, 0x3f, 0xce, 0x86, 0xe7, 0x58, 0xbb, 0x9c, 0x58, 0xb6, 0x2c,
+ 0x5f, 0xf3, 0x9a, 0xfe, 0x2c, 0xee, 0x33, 0x46, 0xa7, 0xb0, 0xc5, 0xff,
+ 0xec, 0xe7, 0xdf, 0xf9, 0xad, 0x67, 0xb8, 0xb1, 0x7f, 0x10, 0x30, 0xed,
+ 0xd2, 0xc5, 0xf7, 0xfe, 0xfc, 0x58, 0xa7, 0x3d, 0x16, 0x2e, 0xad, 0xd3,
+ 0x6c, 0x89, 0x74, 0x95, 0x3b, 0x42, 0x6e, 0xff, 0xff, 0x16, 0x6f, 0xef,
+ 0x4f, 0xb9, 0x11, 0x60, 0x46, 0x4f, 0x78, 0xb1, 0x7f, 0xed, 0xe4, 0xff,
+ 0xce, 0x63, 0x92, 0xc5, 0x4a, 0x29, 0xfe, 0xd3, 0x7f, 0xff, 0xe8, 0x4e,
+ 0xba, 0x87, 0x0c, 0xe0, 0xa7, 0xa2, 0x6f, 0x7d, 0xa2, 0x58, 0xbf, 0x6a,
+ 0x7b, 0x4e, 0x96, 0x2f, 0xff, 0xff, 0x61, 0x7d, 0xf3, 0x7f, 0xce, 0x9b,
+ 0x9f, 0x6e, 0xa1, 0xcf, 0x71, 0xd6, 0x2f, 0xa7, 0x7c, 0x3a, 0xc5, 0xfe,
+ 0x33, 0x39, 0xc7, 0xc0, 0x96, 0x2a, 0x23, 0xd8, 0xd1, 0x1d, 0xff, 0xff,
+ 0xf6, 0x38, 0xcc, 0xcf, 0xbe, 0xbe, 0xc6, 0x7f, 0x06, 0x58, 0xdd, 0x66,
+ 0xcb, 0x14, 0xe8, 0xa1, 0xf9, 0x1d, 0xff, 0xff, 0x60, 0xba, 0x34, 0x0d,
+ 0x17, 0x33, 0x58, 0x3f, 0xe0, 0xba, 0x58, 0xbf, 0x98, 0x8c, 0x1c, 0x92,
+ 0xc5, 0xed, 0xb7, 0xf2, 0xc5, 0x4a, 0xbf, 0x5c, 0x87, 0x6f, 0x44, 0x4e,
+ 0xe3, 0xf2, 0xae, 0x46, 0xe3, 0xe2, 0x21, 0x35, 0x86, 0x5b, 0x7f, 0xf9,
+ 0xfc, 0x26, 0xdb, 0x7f, 0xb8, 0xdc, 0x96, 0x2f, 0x78, 0xd7, 0x58, 0xae,
+ 0xfc, 0xfa, 0x49, 0x2e, 0xfb, 0x0f, 0x3b, 0xac, 0x5f, 0xdb, 0xbe, 0xd9,
+ 0xd7, 0x96, 0x2a, 0x07, 0xa8, 0x11, 0x1d, 0xa3, 0x96, 0x2f, 0xe0, 0x19,
+ 0x3b, 0xb0, 0x6b, 0x17, 0xfd, 0x38, 0x50, 0x32, 0x7b, 0x4a, 0xc5, 0x1a,
+ 0x88, 0x02, 0x15, 0xf1, 0x8d, 0xfb, 0x58, 0x36, 0x82, 0xc5, 0x4a, 0x3e,
+ 0xde, 0x14, 0x6c, 0x61, 0x7a, 0x75, 0x05, 0x8b, 0xff, 0xf8, 0x5d, 0x43,
+ 0x86, 0x49, 0x0f, 0xf3, 0x1d, 0x9a, 0x95, 0x8b, 0xf8, 0x51, 0x18, 0x76,
+ 0xf2, 0xc5, 0x69, 0x12, 0x3f, 0x60, 0xa3, 0x1d, 0xeb, 0x74, 0x68, 0x81,
+ 0xdf, 0x51, 0x59, 0x7a, 0xda, 0x3e, 0xc8, 0x47, 0xc0, 0x39, 0xdb, 0xbc,
+ 0x8e, 0xd4, 0xd9, 0x41, 0x9b, 0xcb, 0xed, 0xea, 0x51, 0x2b, 0xca, 0x82,
+ 0x8a, 0x77, 0x2b, 0x53, 0x9c, 0x07, 0x96, 0xa7, 0xf9, 0xe1, 0x80, 0x43,
+ 0xbc, 0xa7, 0x1a, 0x79, 0x38, 0x3d, 0xe9, 0xdc, 0xd1, 0x43, 0xcf, 0xb4,
+ 0x6e, 0xa1, 0x19, 0x77, 0x42, 0xba, 0xff, 0xfc, 0x5b, 0x99, 0xf9, 0x7d,
+ 0x39, 0xde, 0x3a, 0x4e, 0xb1, 0x7b, 0x93, 0xd2, 0xc5, 0xed, 0xb3, 0x65,
+ 0x8b, 0xf8, 0xbc, 0x02, 0x9d, 0x2c, 0x5f, 0xe6, 0x08, 0xc6, 0x1b, 0x6c,
+ 0xb1, 0x7f, 0xff, 0xfd, 0xee, 0x6c, 0xf8, 0x5e, 0x38, 0xa4, 0xbd, 0x9c,
+ 0x7c, 0x21, 0xc9, 0x2c, 0x5f, 0xfd, 0xee, 0x0f, 0xf3, 0x1c, 0x2f, 0xbe,
+ 0x96, 0x2b, 0x13, 0x26, 0xd1, 0x6b, 0x1b, 0x09, 0xea, 0xf4, 0x3a, 0xdd,
+ 0x62, 0xff, 0xc7, 0xd6, 0x74, 0x3c, 0x72, 0x35, 0x62, 0xf1, 0x38, 0xd6,
+ 0x2e, 0x60, 0x8c, 0x3d, 0xc8, 0x90, 0x2e, 0x80, 0x16, 0x2e, 0xd8, 0xeb,
+ 0x14, 0x61, 0xb1, 0x71, 0x8b, 0xff, 0xf1, 0x3e, 0xc6, 0x3e, 0x16, 0x6f,
+ 0xdd, 0xec, 0x3a, 0xc5, 0xe3, 0xce, 0xeb, 0x17, 0xba, 0xfe, 0x44, 0x7e,
+ 0xe0, 0x59, 0xbf, 0xff, 0x8e, 0xfd, 0x43, 0x85, 0x83, 0xfc, 0xc7, 0x66,
+ 0xa5, 0x62, 0xff, 0xfe, 0xcd, 0x98, 0xbd, 0xc9, 0xdc, 0xc3, 0x9d, 0xcb,
+ 0x75, 0x8b, 0xfa, 0x1c, 0x8a, 0x13, 0x12, 0xc5, 0x0d, 0x11, 0xfd, 0x2f,
+ 0x5f, 0xfe, 0xc1, 0xfd, 0xe2, 0x31, 0xff, 0x27, 0x95, 0x8b, 0xe6, 0x9e,
+ 0xa0, 0xb1, 0x61, 0x91, 0xf7, 0x71, 0x2e, 0xa5, 0x17, 0x2d, 0x09, 0x2b,
+ 0xe8, 0x14, 0x9d, 0x62, 0xf1, 0x49, 0xd6, 0x2f, 0xfb, 0xf9, 0xbc, 0xeb,
+ 0xa8, 0x70, 0xc3, 0x7d, 0x02, 0x2b, 0xff, 0x8c, 0x2c, 0xeb, 0x39, 0xf2,
+ 0xc3, 0x56, 0x2b, 0xa4, 0x4c, 0x44, 0xa5, 0x7f, 0x8c, 0xd6, 0x3f, 0xe4,
+ 0x6b, 0x15, 0x27, 0xb2, 0x44, 0xb6, 0x8d, 0x96, 0x2e, 0x98, 0xf5, 0x8a,
+ 0x95, 0xee, 0xe1, 0xac, 0xe0, 0xf1, 0xb1, 0xa2, 0xb9, 0xe6, 0x9f, 0x3e,
+ 0xc2, 0xd0, 0x98, 0x01, 0xa9, 0x47, 0x4c, 0x28, 0xd5, 0x7b, 0x10, 0x06,
+ 0x2f, 0x7d, 0x84, 0x6c, 0x7a, 0xc5, 0xff, 0xff, 0xfb, 0xef, 0xef, 0xe6,
+ 0xa7, 0xb1, 0x87, 0x17, 0x71, 0x99, 0xd4, 0x30, 0x44, 0x0e, 0x2c, 0x5b,
+ 0xce, 0x8b, 0x2e, 0x13, 0x5f, 0xff, 0x14, 0x5f, 0x97, 0xd3, 0x9d, 0xe3,
+ 0xa4, 0xeb, 0x17, 0x39, 0xd6, 0x2f, 0x3c, 0xee, 0xb1, 0x7f, 0xfd, 0xd4,
+ 0x09, 0xe2, 0x30, 0xb3, 0xdc, 0x7d, 0x2c, 0x53, 0xa3, 0x62, 0x25, 0x22,
+ 0x17, 0x08, 0x76, 0xff, 0x31, 0x60, 0xf1, 0xfe, 0xb1, 0x7f, 0x9e, 0x2f,
+ 0xb1, 0x4c, 0xac, 0x57, 0x47, 0xc6, 0x73, 0x1b, 0xff, 0xfd, 0xad, 0x60,
+ 0xcc, 0xea, 0x13, 0xb6, 0xb3, 0x9c, 0x9e, 0x96, 0x2f, 0xfc, 0x07, 0xcd,
+ 0x19, 0xda, 0x47, 0x1e, 0xb1, 0x47, 0x46, 0x70, 0x44, 0x7d, 0xcc, 0xd7,
+ 0x7e, 0x0b, 0x17, 0x03, 0x8b, 0x17, 0x0f, 0x16, 0x2f, 0xed, 0xcb, 0xac,
+ 0xd1, 0x90, 0x3c, 0x7e, 0x0c, 0x76, 0x18, 0xbf, 0xfc, 0x29, 0x2f, 0x70,
+ 0xc9, 0xe6, 0xa7, 0x8b, 0x17, 0xf9, 0xa1, 0x17, 0xdf, 0xaf, 0x2c, 0x5f,
+ 0xe8, 0x72, 0x4d, 0xf3, 0xec, 0xb1, 0x7f, 0x84, 0x5e, 0x9e, 0xcd, 0xf5,
+ 0x8b, 0xff, 0x30, 0x5e, 0xcf, 0xe1, 0x34, 0x16, 0x2a, 0x07, 0xe6, 0x46,
+ 0xb7, 0xfb, 0x0d, 0x32, 0x77, 0xc3, 0xac, 0x5f, 0xfe, 0xc1, 0x11, 0xbe,
+ 0xd4, 0xf4, 0x0e, 0x4a, 0xc5, 0x62, 0x20, 0xba, 0x36, 0xbf, 0x8f, 0x85,
+ 0xe8, 0xec, 0x58, 0xbf, 0x37, 0x0f, 0x24, 0xb1, 0x7c, 0x79, 0xcf, 0x2c,
+ 0x5e, 0x9d, 0xcc, 0xc3, 0xf9, 0x23, 0x08, 0xe2, 0x7b, 0xf4, 0x97, 0x8c,
+ 0x1a, 0xc5, 0xfd, 0x27, 0xcc, 0x23, 0x56, 0x2f, 0xde, 0x30, 0x1d, 0x01,
+ 0x62, 0x9d, 0x10, 0x5f, 0x29, 0x11, 0x6d, 0xff, 0xef, 0xbe, 0xff, 0xc3,
+ 0x38, 0x2f, 0xcc, 0x7a, 0xc5, 0xfc, 0x53, 0xd4, 0x1c, 0x96, 0x29, 0x62,
+ 0xff, 0x67, 0xcb, 0x3d, 0xf7, 0x58, 0xa1, 0x9f, 0x59, 0x16, 0xf8, 0x32,
+ 0xff, 0xbd, 0x30, 0xe4, 0x50, 0x9d, 0x96, 0x2d, 0x98, 0x99, 0x2f, 0x50,
+ 0xbb, 0xf1, 0x75, 0xff, 0xff, 0xb7, 0x18, 0xb6, 0x0c, 0x9b, 0xd2, 0x07,
+ 0x83, 0xf8, 0xa4, 0x0b, 0x17, 0xff, 0xfc, 0x2e, 0x7d, 0xa0, 0x67, 0x9c,
+ 0xc2, 0xc3, 0xe4, 0x96, 0xcb, 0x17, 0xff, 0xde, 0xfe, 0x00, 0xc3, 0xce,
+ 0x78, 0x78, 0x4b, 0x16, 0xd2, 0xc5, 0x82, 0x58, 0xbf, 0x98, 0x7a, 0xd0,
+ 0xb6, 0x58, 0xbf, 0x4e, 0x17, 0xa3, 0x96, 0x2d, 0x1a, 0x2c, 0x56, 0x22,
+ 0x58, 0xd1, 0x2d, 0xc4, 0xce, 0x61, 0xc2, 0xab, 0xef, 0x3e, 0xb1, 0x62,
+ 0xdd, 0x18, 0x7d, 0xb8, 0x97, 0x58, 0x9b, 0xe3, 0x46, 0xa7, 0x58, 0xa9,
+ 0xeb, 0x4d, 0xdc, 0x8f, 0x92, 0xff, 0xff, 0xff, 0xbe, 0x2e, 0x16, 0x0f,
+ 0x1f, 0xe6, 0x6f, 0xf7, 0xee, 0xf8, 0xb8, 0x59, 0xb3, 0x18, 0x69, 0xab,
+ 0x15, 0xb3, 0x20, 0x2c, 0x69, 0x7d, 0x1b, 0x45, 0x0a, 0x9d, 0x42, 0x8c,
+ 0xf0, 0x9c, 0xfc, 0x31, 0x4a, 0x35, 0x4f, 0x4a, 0xb5, 0xee, 0x37, 0xbf,
+ 0xff, 0x8b, 0x02, 0xcd, 0x8c, 0x8f, 0xc6, 0x34, 0xcd, 0x05, 0xa5, 0x8b,
+ 0xff, 0xfd, 0x81, 0x66, 0xc3, 0xf8, 0x8b, 0x72, 0xcf, 0x7d, 0xfa, 0x58,
+ 0xbf, 0xff, 0xfe, 0x87, 0x09, 0x8d, 0xfe, 0x7f, 0xa9, 0x30, 0xb0, 0x59,
+ 0xef, 0xe6, 0xd2, 0xb1, 0x7f, 0xff, 0xe1, 0x75, 0x0e, 0x19, 0x8e, 0x09,
+ 0x2c, 0xeb, 0xc3, 0xf8, 0x82, 0x58, 0xbf, 0xff, 0xfc, 0xf8, 0x7c, 0xfb,
+ 0xe1, 0xcc, 0x2c, 0xf7, 0xf2, 0x1f, 0x7c, 0x3a, 0xc5, 0xff, 0xff, 0xd0,
+ 0x7e, 0x16, 0x76, 0xfe, 0x45, 0xf9, 0x28, 0x8c, 0x6d, 0xdf, 0xb2, 0xc5,
+ 0xff, 0xe0, 0xba, 0x87, 0x0b, 0x3b, 0x7b, 0x58, 0x12, 0xc5, 0xff, 0xe7,
+ 0xc0, 0x8b, 0x39, 0x9f, 0xfb, 0xf1, 0x62, 0xd9, 0xd2, 0x62, 0x2c, 0xf1,
+ 0xe5, 0x0b, 0xff, 0xf9, 0xf0, 0x22, 0xcd, 0xb0, 0x5e, 0x26, 0x35, 0xb8,
+ 0xb1, 0x7f, 0xec, 0xd7, 0xe4, 0xc6, 0xf0, 0xa5, 0x62, 0xff, 0xee, 0x66,
+ 0xe6, 0x75, 0x0e, 0x13, 0xc4, 0xb1, 0x7f, 0xfb, 0x59, 0xee, 0x77, 0x7a,
+ 0x79, 0xf7, 0xc5, 0x8b, 0xff, 0x36, 0xb9, 0xe7, 0xcd, 0x8a, 0x56, 0x2f,
+ 0xc5, 0x9d, 0xbf, 0x9a, 0x44, 0x5f, 0x13, 0x6d, 0x3e, 0x4c, 0x50, 0x28,
+ 0x6a, 0x53, 0xa7, 0x05, 0xa8, 0xd4, 0xef, 0xff, 0xfb, 0x08, 0xd3, 0x35,
+ 0x3d, 0x9f, 0xdc, 0xc3, 0x5f, 0x4d, 0xd2, 0xc5, 0xff, 0xff, 0xfd, 0xec,
+ 0xf9, 0x67, 0x63, 0x33, 0x53, 0xe7, 0xdd, 0xc6, 0x64, 0xf8, 0xa7, 0xa8,
+ 0x2c, 0x56, 0xcb, 0xce, 0x3b, 0xb2, 0x74, 0xc9, 0xa7, 0xff, 0xb8, 0x94,
+ 0x70, 0xdc, 0x36, 0xf4, 0x7b, 0xa1, 0x94, 0xf7, 0x35, 0xd4, 0xb6, 0x04,
+ 0xef, 0x48, 0x61, 0x14, 0xf9, 0x35, 0xf9, 0xb9, 0xa6, 0xe2, 0xc5, 0xff,
+ 0xe7, 0x19, 0x87, 0x73, 0x24, 0x6d, 0x17, 0x16, 0x2f, 0xf7, 0xe7, 0x63,
+ 0x0b, 0x06, 0xb1, 0x7e, 0xf6, 0x44, 0x28, 0x96, 0x2a, 0x23, 0xe0, 0xee,
+ 0x35, 0xbf, 0x7d, 0xfd, 0x87, 0x58, 0xb4, 0x16, 0x2f, 0xfe, 0xfb, 0x90,
+ 0xc3, 0xdc, 0xb3, 0xf8, 0xb1, 0x7f, 0xe8, 0x7a, 0x60, 0x79, 0xc2, 0x1a,
+ 0xc5, 0xfe, 0xdb, 0x8f, 0xff, 0xce, 0xcb, 0x16, 0xce, 0x8f, 0xd1, 0xcf,
+ 0xaf, 0xef, 0x75, 0xbb, 0xfe, 0x25, 0x8a, 0x31, 0x37, 0x2e, 0xf4, 0x9a,
+ 0x05, 0x11, 0x09, 0x14, 0x2e, 0x78, 0x4f, 0x52, 0xaa, 0x0b, 0x69, 0x43,
+ 0xf7, 0xf8, 0xd2, 0xce, 0xc5, 0x9c, 0x58, 0xa8, 0x2b, 0x0b, 0xd4, 0xaa,
+ 0xa2, 0x2c, 0xbf, 0x73, 0x92, 0x5b, 0xac, 0x5f, 0xff, 0x14, 0x46, 0x7f,
+ 0x77, 0xe6, 0x0f, 0x6c, 0x09, 0x62, 0xb0, 0xff, 0x98, 0xa6, 0xf7, 0xb3,
+ 0x8b, 0x16, 0xdb, 0xe6, 0xf7, 0xc4, 0x17, 0xe8, 0x4f, 0x50, 0xe2, 0xc5,
+ 0xff, 0xff, 0xff, 0xb0, 0x8d, 0x31, 0xfe, 0x28, 0xc8, 0x9f, 0xd2, 0x72,
+ 0x63, 0x7e, 0xf1, 0x99, 0xfe, 0x81, 0x23, 0x48, 0xbf, 0xff, 0xcf, 0xaf,
+ 0xe7, 0x4d, 0xd1, 0x87, 0x21, 0x78, 0xce, 0xdc, 0x58, 0xbf, 0xff, 0xf3,
+ 0x84, 0x31, 0x68, 0xc1, 0x4e, 0xdc, 0xdf, 0xe2, 0xff, 0x4c, 0x12, 0xc5,
+ 0xff, 0xfd, 0x9d, 0xa4, 0x8c, 0xe3, 0xe9, 0x80, 0xc5, 0x14, 0xac, 0x56,
+ 0xe8, 0xd1, 0xfb, 0xad, 0xff, 0x16, 0x08, 0x23, 0x27, 0xb4, 0x7a, 0xc5,
+ 0xb6, 0xe9, 0x53, 0x53, 0x95, 0x1e, 0x14, 0x7c, 0x8c, 0xe7, 0xb8, 0x92,
+ 0xb1, 0x57, 0x98, 0xa5, 0x49, 0x5f, 0xff, 0xd8, 0xe0, 0xe1, 0x81, 0xf9,
+ 0xf8, 0x59, 0xd9, 0xc6, 0xb1, 0x7f, 0xec, 0x8b, 0xa8, 0x71, 0xce, 0xd1,
+ 0x2c, 0x5b, 0xbb, 0x48, 0xa0, 0xe2, 0xf5, 0xf8, 0xb3, 0xdf, 0x75, 0x8b,
+ 0xff, 0x7d, 0xf3, 0x79, 0xf7, 0xdf, 0x16, 0x2b, 0x11, 0x22, 0x69, 0x67,
+ 0x71, 0x3d, 0xc3, 0xc5, 0x8a, 0x96, 0xef, 0xaf, 0x23, 0x00, 0x78, 0xdb,
+ 0xbf, 0x58, 0x51, 0x34, 0xb4, 0xf2, 0x97, 0xcc, 0x28, 0xd7, 0x23, 0x8c,
+ 0xee, 0xcd, 0x2c, 0x5b, 0xb9, 0x62, 0xd1, 0xa2, 0xc5, 0xe9, 0xfe, 0x2c,
+ 0x58, 0xeb, 0x17, 0xf9, 0xa1, 0x87, 0x62, 0x02, 0xc5, 0xf6, 0x7e, 0x62,
+ 0x58, 0xa8, 0xd0, 0xf9, 0xfe, 0x24, 0xc6, 0x57, 0x73, 0x16, 0x2e, 0x3e,
+ 0xe6, 0x1e, 0x53, 0x99, 0xdf, 0xb4, 0xfd, 0x43, 0x8b, 0x17, 0xff, 0xf0,
+ 0xfe, 0xf8, 0x7c, 0xdf, 0xf9, 0xd4, 0x09, 0xe2, 0x58, 0xbf, 0xe9, 0x7d,
+ 0x3c, 0x46, 0x7b, 0x8b, 0x17, 0xfe, 0x2c, 0x33, 0xd1, 0x14, 0x9c, 0xcc,
+ 0x44, 0xc7, 0xd7, 0x6d, 0xb0, 0xd3, 0x19, 0xd4, 0x30, 0xad, 0x1e, 0xb1,
+ 0x7e, 0xfb, 0x9c, 0xa5, 0x62, 0xf8, 0x44, 0x0e, 0x2c, 0x50, 0x0f, 0x2b,
+ 0xc4, 0xf7, 0xff, 0xee, 0x3e, 0x10, 0x0c, 0x2c, 0xec, 0x59, 0xce, 0xcb,
+ 0x17, 0xfc, 0xf8, 0x40, 0x33, 0xbe, 0xb1, 0xbc, 0x6e, 0xb1, 0x7d, 0xb9,
+ 0x67, 0x63, 0x11, 0x49, 0xc5, 0x8b, 0xfe, 0x35, 0xbd, 0xc8, 0x89, 0xc2,
+ 0x58, 0xbe, 0x63, 0xbf, 0x16, 0x2f, 0xdf, 0x63, 0xbf, 0x16, 0x28, 0xd4,
+ 0x43, 0x7c, 0xf3, 0x84, 0x55, 0xa4, 0x7a, 0x14, 0x30, 0xef, 0xff, 0x7c,
+ 0x58, 0x46, 0x99, 0xee, 0xa1, 0x84, 0xb1, 0x7f, 0xb1, 0x8e, 0x64, 0x74,
+ 0x9d, 0x62, 0xff, 0xf4, 0x27, 0x9f, 0x16, 0xb3, 0xde, 0x73, 0xac, 0x50,
+ 0xd1, 0x9f, 0xba, 0x6f, 0x46, 0xf7, 0xfe, 0x2c, 0x11, 0xba, 0x79, 0x3e,
+ 0x2c, 0x5f, 0xc2, 0x2c, 0xd8, 0x5d, 0x2c, 0x5f, 0xff, 0x49, 0x85, 0x83,
+ 0xfb, 0x9a, 0x39, 0x34, 0x0b, 0x15, 0xa4, 0x41, 0x08, 0xc2, 0xb1, 0x50,
+ 0x5e, 0xa1, 0xec, 0x73, 0x22, 0x86, 0x05, 0xff, 0xd3, 0x9c, 0xf7, 0x24,
+ 0xd3, 0x00, 0x12, 0xc5, 0xfe, 0xd1, 0xbe, 0x36, 0x4a, 0x25, 0x8b, 0xff,
+ 0xde, 0xfe, 0x77, 0x7a, 0x2c, 0x8f, 0x62, 0x02, 0xc5, 0xfe, 0x93, 0xb1,
+ 0x75, 0x09, 0x58, 0xac, 0x45, 0xd9, 0x1b, 0xf9, 0x46, 0xff, 0xfb, 0x27,
+ 0xa3, 0x3b, 0x78, 0xcd, 0x4f, 0xe6, 0x25, 0x8b, 0xff, 0x38, 0x0c, 0x2c,
+ 0xec, 0xfa, 0x65, 0x8b, 0xff, 0xda, 0x33, 0xf2, 0xfe, 0xe4, 0xed, 0x9c,
+ 0x58, 0xac, 0x44, 0x60, 0x90, 0x2f, 0xfe, 0x07, 0xe5, 0xfd, 0xc7, 0x2e,
+ 0xa0, 0xb1, 0x4e, 0x9b, 0xbf, 0xcb, 0xbd, 0x0e, 0x21, 0x11, 0x5f, 0x04,
+ 0x67, 0x22, 0x58, 0xb7, 0x96, 0x2a, 0x4d, 0xcb, 0x13, 0xdf, 0xf8, 0xb6,
+ 0x2c, 0xed, 0xc1, 0x4f, 0x4b, 0x17, 0xfd, 0xf9, 0xe8, 0xce, 0xf9, 0xd8,
+ 0x0e, 0xb1, 0x7d, 0x9d, 0xa4, 0x96, 0x2f, 0xba, 0x83, 0xc7, 0x2c, 0x57,
+ 0xcf, 0x2b, 0xc4, 0x74, 0x34, 0x58, 0x72, 0x11, 0xd5, 0x29, 0x8d, 0x6d,
+ 0x0f, 0x2a, 0x96, 0x47, 0x94, 0x0c, 0x31, 0x7d, 0xe5, 0xe2, 0x92, 0x3f,
+ 0x25, 0x3d, 0x79, 0xec, 0x51, 0x9c, 0xdf, 0xbb, 0x77, 0x7b, 0x3e, 0xb1,
+ 0x62, 0x58, 0xb6, 0xeb, 0x17, 0xfe, 0xce, 0x0a, 0x4d, 0xe4, 0xea, 0x25,
+ 0x8a, 0x74, 0x49, 0xe8, 0xbb, 0xb0, 0x88, 0x42, 0x77, 0xff, 0xc2, 0x62,
+ 0x33, 0xdf, 0x9f, 0x73, 0xed, 0x05, 0x8b, 0x98, 0x6b, 0x17, 0xf1, 0x64,
+ 0x50, 0x17, 0x72, 0xc5, 0xf4, 0x05, 0xb7, 0x96, 0x2d, 0xa8, 0x1f, 0x71,
+ 0xa2, 0xfd, 0x19, 0x5f, 0xff, 0xff, 0xff, 0xbd, 0xcf, 0xe3, 0x8f, 0xf9,
+ 0xbb, 0xeb, 0x4e, 0x13, 0xe1, 0x1b, 0xcc, 0x1f, 0xc5, 0xb1, 0x8d, 0x16,
+ 0x32, 0xc5, 0xcd, 0xba, 0xc5, 0xfb, 0x59, 0x1c, 0xe0, 0x58, 0xbf, 0xdb,
+ 0xfd, 0xfe, 0x42, 0xd9, 0x62, 0xfd, 0x3d, 0x03, 0x52, 0xb1, 0x50, 0x3d,
+ 0xff, 0x1b, 0x56, 0xc8, 0xac, 0x28, 0x45, 0x5e, 0xf6, 0x77, 0xeb, 0x17,
+ 0xd0, 0x29, 0x3a, 0xc5, 0x18, 0x9f, 0x27, 0x7b, 0x0b, 0x49, 0x86, 0x26,
+ 0x14, 0x08, 0x8a, 0xe0, 0x7d, 0x62, 0x96, 0x2f, 0x39, 0x62, 0xc5, 0xb9,
+ 0x86, 0x9e, 0x20, 0xcb, 0xcf, 0x3c, 0x58, 0xbf, 0x78, 0x01, 0x94, 0x16,
+ 0x2f, 0x07, 0x9c, 0x58, 0xb4, 0xe1, 0xe4, 0x1a, 0x55, 0x7f, 0xf1, 0xcc,
+ 0x2c, 0xff, 0x8b, 0x1a, 0x25, 0x8b, 0xb3, 0xeb, 0x15, 0x29, 0xa6, 0xe1,
+ 0xff, 0xc9, 0xc9, 0x90, 0x44, 0xf1, 0xc8, 0xb6, 0x95, 0x8b, 0xff, 0xba,
+ 0x86, 0x9c, 0xed, 0x31, 0x4c, 0x4b, 0x17, 0xff, 0xf7, 0x30, 0x7a, 0x90,
+ 0x8c, 0xfb, 0x3f, 0x3f, 0x80, 0x58, 0xa3, 0x51, 0x6b, 0x10, 0x89, 0x23,
+ 0xdd, 0x83, 0x58, 0xa3, 0x1b, 0x27, 0x6e, 0xf0, 0x5f, 0xbd, 0x15, 0x91,
+ 0x7d, 0xa1, 0x9b, 0x0a, 0x51, 0xd6, 0x46, 0x31, 0xb9, 0xfb, 0x42, 0xff,
+ 0x92, 0x86, 0xfd, 0x1d, 0x30, 0xa3, 0x0d, 0xec, 0x63, 0x7d, 0xc2, 0xce,
+ 0xcb, 0x17, 0xc2, 0x86, 0x71, 0x62, 0xf3, 0xc8, 0xd6, 0x28, 0x07, 0xc6,
+ 0x44, 0x81, 0x11, 0xde, 0x17, 0xb8, 0xb1, 0x7e, 0xee, 0xfe, 0x08, 0xeb,
+ 0x14, 0x47, 0x94, 0x21, 0xeb, 0xf3, 0xfb, 0x98, 0x05, 0x8b, 0xdd, 0x9f,
+ 0xb2, 0xc5, 0xf1, 0xf8, 0xd0, 0x58, 0xb7, 0xf0, 0xf1, 0x04, 0x43, 0x7f,
+ 0xfd, 0x9a, 0xe9, 0xa2, 0x33, 0xef, 0xa2, 0xcd, 0x96, 0x2f, 0xff, 0xf7,
+ 0xbf, 0x31, 0x18, 0x59, 0xf7, 0xf7, 0x05, 0xb8, 0xa5, 0x62, 0x8d, 0x45,
+ 0xbb, 0x29, 0xdc, 0x28, 0xe5, 0x8a, 0x23, 0x7c, 0x11, 0x1d, 0xd8, 0x05,
+ 0x8b, 0xff, 0x88, 0x05, 0x8f, 0x17, 0xe4, 0x8d, 0x58, 0xa7, 0x3d, 0xb6,
+ 0x17, 0xbc, 0x42, 0x3a, 0xc5, 0xfb, 0x9e, 0x79, 0xe9, 0x62, 0xff, 0xa7,
+ 0xf8, 0x31, 0x44, 0xc4, 0xb1, 0x50, 0x3e, 0x2e, 0x14, 0xdd, 0x9d, 0x96,
+ 0x2f, 0xff, 0xf9, 0xa2, 0x33, 0x9c, 0xcf, 0xeb, 0x58, 0x11, 0x60, 0x4c,
+ 0x05, 0x8b, 0xf4, 0x97, 0xda, 0x0b, 0x17, 0xfd, 0xec, 0xda, 0x78, 0xfa,
+ 0xc5, 0x8b, 0xd2, 0x39, 0x58, 0xa1, 0x9f, 0xe7, 0x44, 0xe7, 0x39, 0xa5,
+ 0x8a, 0x58, 0xbf, 0xef, 0x66, 0xd3, 0xc7, 0xd6, 0x2c, 0x5e, 0x91, 0xca,
+ 0xc5, 0xee, 0x34, 0x46, 0x22, 0x76, 0x4c, 0x30, 0x33, 0xa0, 0xc3, 0x9c,
+ 0xdb, 0x09, 0x3d, 0xff, 0x47, 0x07, 0x7d, 0x1a, 0x77, 0xd6, 0x36, 0x8d,
+ 0x16, 0x2f, 0x9d, 0x88, 0x6b, 0x16, 0x08, 0xc3, 0xdc, 0x19, 0xdd, 0xfb,
+ 0x1b, 0xa8, 0x71, 0x62, 0xff, 0xf6, 0x86, 0x19, 0x19, 0xe7, 0xdc, 0x9f,
+ 0x65, 0x8b, 0xf4, 0x5e, 0xc2, 0xf2, 0xc5, 0x61, 0xfb, 0xb2, 0x75, 0x01,
+ 0x18, 0x01, 0x42, 0x82, 0xa0, 0x9c, 0xeb, 0xc2, 0x2b, 0x90, 0xea, 0xbe,
+ 0xdf, 0xef, 0xba, 0xc5, 0xf0, 0xbf, 0x27, 0x58, 0xbf, 0xfe, 0x16, 0xb5,
+ 0x25, 0x86, 0xbf, 0xff, 0x81, 0xac, 0x5f, 0xfd, 0x08, 0x31, 0x6d, 0x07,
+ 0xde, 0x4e, 0xb1, 0x52, 0x8d, 0xfc, 0x25, 0xd1, 0x1b, 0x28, 0xde, 0xee,
+ 0xe7, 0x4b, 0x17, 0xa4, 0x44, 0xb1, 0x58, 0x6f, 0xbe, 0x45, 0x7c, 0x26,
+ 0xeb, 0xcb, 0x17, 0xfa, 0x77, 0xc3, 0xe9, 0xb4, 0xb1, 0x4b, 0x16, 0x23,
+ 0x4f, 0x03, 0xc6, 0x97, 0xd9, 0x81, 0x77, 0xeb, 0x17, 0xff, 0xff, 0x1b,
+ 0x9a, 0xd3, 0x9c, 0xc8, 0xa0, 0x23, 0xf5, 0x0e, 0x72, 0x75, 0xba, 0xc5,
+ 0xdf, 0x65, 0x8b, 0x33, 0xa2, 0x47, 0xb3, 0xd5, 0xf3, 0x9b, 0x27, 0x58,
+ 0xbf, 0xa4, 0xbd, 0xfc, 0x1a, 0xc5, 0x49, 0xe8, 0x70, 0x8e, 0xf8, 0x12,
+ 0x39, 0x58, 0xbc, 0x21, 0xca, 0xc5, 0xf3, 0x1d, 0xfc, 0xb1, 0x7f, 0xfc,
+ 0xe3, 0x76, 0xf3, 0xb7, 0x8c, 0xe3, 0xc4, 0xb1, 0x52, 0xcb, 0x35, 0xd9,
+ 0xe6, 0x04, 0x23, 0x6c, 0xc8, 0xc7, 0x0d, 0x7c, 0xdc, 0x83, 0xa7, 0xf7,
+ 0x22, 0x8a, 0x5c, 0xae, 0xa3, 0x19, 0x3b, 0xc7, 0xc8, 0x19, 0x90, 0x05,
+ 0x05, 0x0b, 0x9e, 0x3c, 0xf8, 0x87, 0xb1, 0x10, 0x43, 0xb1, 0xc4, 0x56,
+ 0xee, 0x58, 0xb0, 0x4b, 0x17, 0xb6, 0x9d, 0x96, 0x29, 0x62, 0xfe, 0xc3,
+ 0x8f, 0xf9, 0xc5, 0x8b, 0xf6, 0xc6, 0x6e, 0xfb, 0x2c, 0x5f, 0xfb, 0xe5,
+ 0x9d, 0x7b, 0xf8, 0x2d, 0xd6, 0x2f, 0xee, 0x6f, 0xbb, 0x11, 0xab, 0x15,
+ 0x1a, 0x91, 0xb3, 0xb0, 0x66, 0x8b, 0x98, 0xb7, 0xc8, 0x37, 0xf8, 0x8c,
+ 0xed, 0xd4, 0x39, 0x12, 0xc5, 0xff, 0xdd, 0x9b, 0x46, 0x71, 0xfd, 0x25,
+ 0xba, 0xc5, 0xfd, 0xf7, 0xc2, 0xce, 0xcb, 0x16, 0x86, 0x1f, 0xb7, 0x12,
+ 0x2f, 0xff, 0xf0, 0xff, 0x9e, 0xf3, 0x16, 0xf8, 0xfa, 0x73, 0xc9, 0xab,
+ 0x16, 0xe9, 0x62, 0xdd, 0x96, 0x2b, 0x63, 0x4f, 0xa1, 0x3b, 0xf7, 0xda,
+ 0x3e, 0x40, 0xb1, 0x43, 0x4e, 0xb3, 0xa8, 0x58, 0x39, 0x3b, 0x42, 0x23,
+ 0xb8, 0x8a, 0xfc, 0x60, 0x7b, 0x4e, 0xcb, 0x17, 0xe2, 0xcf, 0xb7, 0x96,
+ 0x2a, 0x07, 0xa9, 0x11, 0x6d, 0xfc, 0x6b, 0xf5, 0xc1, 0x71, 0x62, 0xf7,
+ 0x7f, 0x1c, 0xeb, 0x15, 0xa3, 0xf9, 0x22, 0x31, 0x18, 0xdf, 0xff, 0x7c,
+ 0x5d, 0xde, 0x9e, 0x78, 0x4c, 0x1c, 0xe9, 0x62, 0xfc, 0x59, 0xb6, 0xa5,
+ 0x62, 0xe2, 0x18, 0xcf, 0xf7, 0x8a, 0xb7, 0xc3, 0x32, 0x63, 0xd6, 0x2a,
+ 0x57, 0x07, 0xf2, 0x3f, 0xc7, 0x8c, 0x90, 0x50, 0xab, 0x0c, 0xb6, 0xff,
+ 0xfd, 0x0e, 0x7a, 0x76, 0x17, 0x5c, 0x13, 0x94, 0x9d, 0x62, 0xf8, 0xce,
+ 0xd8, 0x35, 0x8a, 0xe8, 0xff, 0xbc, 0xb1, 0x7f, 0xa4, 0xc2, 0xce, 0xd9,
+ 0xf5, 0x8b, 0x3a, 0xc5, 0x2c, 0x5f, 0xf0, 0x88, 0xc8, 0x9f, 0x61, 0x44,
+ 0xb1, 0x7f, 0x60, 0xe2, 0x84, 0xc7, 0xac, 0x5f, 0xff, 0xfa, 0x19, 0xe2,
+ 0xcf, 0x73, 0xf8, 0x69, 0x85, 0x86, 0x81, 0x86, 0xb1, 0x76, 0x6c, 0xb1,
+ 0x5d, 0x22, 0x1b, 0x8d, 0xd7, 0xff, 0x78, 0xd9, 0xea, 0x1c, 0xea, 0x12,
+ 0x6a, 0xc5, 0x8e, 0xb1, 0x7f, 0x1c, 0x98, 0xdf, 0xb9, 0x87, 0xb9, 0xb2,
+ 0x55, 0xff, 0x1f, 0x8d, 0x17, 0x77, 0xf3, 0x65, 0x8a, 0x94, 0x42, 0xe2,
+ 0x35, 0x46, 0xea, 0x8a, 0x36, 0x0c, 0xd1, 0xf7, 0xe1, 0x71, 0xe8, 0xc1,
+ 0x6f, 0xf8, 0xc2, 0xcf, 0x73, 0xf8, 0x6a, 0xc5, 0xf4, 0x5f, 0x7e, 0x2c,
+ 0x56, 0xc7, 0xbf, 0xe3, 0xbb, 0xb0, 0x96, 0x2f, 0x42, 0x40, 0xb1, 0x43,
+ 0x36, 0x78, 0x2d, 0x7d, 0xc1, 0xb0, 0x16, 0x2f, 0xe7, 0xd3, 0x9e, 0x4d,
+ 0x58, 0xbf, 0xd9, 0xff, 0xcf, 0x4d, 0x1e, 0xb1, 0x77, 0x0c, 0xc3, 0xe5,
+ 0xe1, 0x75, 0x74, 0x8b, 0x60, 0x42, 0x22, 0xb4, 0x8f, 0xf2, 0x86, 0xb5,
+ 0xf0, 0x39, 0x1f, 0xba, 0xc5, 0x4a, 0x74, 0x8f, 0x1a, 0xa8, 0x89, 0xef,
+ 0xdb, 0xfe, 0x75, 0x12, 0xc5, 0xfd, 0xac, 0xe3, 0x31, 0xd6, 0x2e, 0xf3,
+ 0xac, 0x57, 0xcf, 0xbd, 0x8a, 0xf8, 0x5b, 0x7e, 0x06, 0x78, 0x3d, 0x96,
+ 0x2f, 0xf1, 0x9f, 0xfc, 0xf0, 0x5c, 0x58, 0xbf, 0xff, 0xbf, 0x3d, 0x19,
+ 0x13, 0xfa, 0x4e, 0x4c, 0x6f, 0xdd, 0x62, 0xff, 0x16, 0x05, 0xdd, 0xec,
+ 0xfa, 0xc5, 0xff, 0xff, 0xff, 0x3e, 0x7b, 0x77, 0xf1, 0x61, 0xbf, 0x6f,
+ 0x66, 0xc6, 0x64, 0x5d, 0x43, 0x9e, 0xfe, 0x74, 0xb1, 0x7f, 0x73, 0x3f,
+ 0xe7, 0x35, 0x62, 0xff, 0xb9, 0xf1, 0x44, 0x60, 0x51, 0xfd, 0x2c, 0x5c,
+ 0x23, 0x56, 0x2f, 0xff, 0xc2, 0xea, 0x1c, 0xea, 0x0d, 0xd1, 0x83, 0xfb,
+ 0x9d, 0x62, 0xfd, 0x8e, 0x58, 0x6a, 0xc5, 0xf7, 0xb3, 0xe6, 0x69, 0x10,
+ 0x7f, 0x5c, 0xa1, 0xaa, 0x78, 0x89, 0x7b, 0x46, 0xfc, 0x84, 0xd7, 0x8b,
+ 0xe3, 0x90, 0xfb, 0xa1, 0x39, 0x51, 0x2b, 0x25, 0x0a, 0x55, 0x75, 0xfb,
+ 0x99, 0xe0, 0xf6, 0x58, 0xb7, 0x96, 0x2d, 0xc5, 0x8b, 0xbe, 0x61, 0xa6,
+ 0x93, 0xa1, 0x2b, 0x82, 0xf4, 0x9f, 0xfe, 0x27, 0xde, 0xda, 0x06, 0xac,
+ 0x54, 0xae, 0x25, 0x64, 0xb5, 0x06, 0x85, 0x68, 0x8b, 0x6a, 0x36, 0x6c,
+ 0x1b, 0xfb, 0xea, 0x2b, 0x22, 0x70, 0x9d, 0x17, 0xc8, 0x6d, 0x1a, 0x47,
+ 0xb9, 0xab, 0xca, 0x39, 0xfc, 0xa6, 0x06, 0x85, 0x21, 0x4e, 0x3c, 0x5f,
+ 0xdd, 0x43, 0x86, 0x49, 0x2c, 0x5f, 0x84, 0x43, 0xce, 0x2c, 0x5f, 0xf9,
+ 0xb9, 0x9b, 0x37, 0xb6, 0xc0, 0x96, 0x2f, 0xec, 0xdc, 0xc0, 0x4c, 0x4b,
+ 0x15, 0x03, 0xf2, 0xfa, 0x0d, 0xff, 0xfc, 0x42, 0x68, 0xf3, 0x25, 0xc0,
+ 0xf0, 0xfb, 0x90, 0x16, 0x2f, 0xfb, 0x3e, 0x60, 0x6d, 0x1f, 0xfc, 0x58,
+ 0xbf, 0xbf, 0x9b, 0xc2, 0x4e, 0xb1, 0x7f, 0xbf, 0x90, 0x62, 0xce, 0x96,
+ 0x2b, 0x0f, 0x8b, 0xc5, 0xf7, 0xff, 0xfe, 0x84, 0xed, 0xd4, 0x38, 0xe6,
+ 0x99, 0xcc, 0xdd, 0xce, 0x2d, 0x6c, 0xb1, 0x7f, 0xed, 0xdc, 0x66, 0x67,
+ 0x89, 0xfa, 0x58, 0xbd, 0xed, 0xc6, 0xb1, 0x7d, 0xde, 0x94, 0xc1, 0x62,
+ 0xff, 0x60, 0x46, 0x7d, 0xf0, 0xeb, 0x17, 0xff, 0xdb, 0x63, 0x97, 0x8b,
+ 0x3b, 0x19, 0xc0, 0x89, 0x62, 0xe6, 0x01, 0x88, 0xce, 0x8d, 0x87, 0xf6,
+ 0x27, 0xe1, 0xad, 0x74, 0x9e, 0x93, 0xba, 0x14, 0x61, 0xf7, 0xff, 0xb7,
+ 0x7f, 0xfd, 0xb8, 0x58, 0x01, 0x71, 0x62, 0xff, 0xe7, 0xff, 0xdb, 0x85,
+ 0x80, 0x17, 0x16, 0x2f, 0xf8, 0x88, 0x4c, 0x0f, 0x30, 0x16, 0x2f, 0xcf,
+ 0xee, 0x61, 0xa6, 0x23, 0x1f, 0x74, 0xb7, 0x44, 0xbf, 0xbf, 0x85, 0xd4,
+ 0x9a, 0xb1, 0x7f, 0x31, 0x78, 0x5a, 0xd9, 0x62, 0xa5, 0x76, 0x17, 0x63,
+ 0x07, 0x84, 0xd7, 0xc8, 0x80, 0xba, 0x50, 0xa0, 0xf4, 0x7e, 0x7d, 0xa1,
+ 0xfa, 0x12, 0x70, 0x65, 0xf7, 0x75, 0xe5, 0x8b, 0x77, 0x2c, 0x51, 0x86,
+ 0xb8, 0x63, 0x36, 0x89, 0x62, 0xff, 0x8f, 0xe2, 0x9d, 0x3f, 0xb8, 0xb1,
+ 0x4e, 0x79, 0x8c, 0x27, 0x7f, 0xf8, 0xde, 0x6f, 0xf1, 0x6c, 0x58, 0x16,
+ 0x6c, 0xb1, 0x58, 0x7e, 0x0e, 0x41, 0x7f, 0xd9, 0x11, 0x9c, 0x9f, 0xb4,
+ 0x7a, 0xc5, 0xff, 0xff, 0xf4, 0xf5, 0xac, 0xf7, 0x9c, 0xfc, 0xfe, 0x6d,
+ 0x9a, 0xfc, 0x8d, 0xe7, 0xb9, 0x62, 0x9d, 0x17, 0xff, 0x3e, 0xbf, 0xcd,
+ 0xd7, 0xf3, 0xc0, 0x65, 0x8b, 0xb2, 0x25, 0x8b, 0xff, 0xfb, 0x3c, 0x67,
+ 0xf3, 0xf8, 0x22, 0xdc, 0xcc, 0x71, 0xac, 0x56, 0x22, 0xa5, 0xcd, 0x04,
+ 0x31, 0x7f, 0xe9, 0xf9, 0x9a, 0xcd, 0xb1, 0x8e, 0xb1, 0x79, 0xca, 0x25,
+ 0x8b, 0xfe, 0x29, 0x07, 0x50, 0xe4, 0x84, 0xb1, 0x71, 0xb1, 0x2c, 0x5f,
+ 0x7e, 0x7a, 0x32, 0x23, 0xd5, 0xee, 0x3b, 0xbf, 0xf6, 0x11, 0x85, 0x9f,
+ 0xfb, 0x0d, 0x62, 0xbc, 0x7f, 0xa2, 0x3f, 0xac, 0x4c, 0x47, 0x90, 0xef,
+ 0xbf, 0xd9, 0xb1, 0x91, 0x6c, 0x0d, 0x2c, 0x54, 0x0f, 0x87, 0xc5, 0x17,
+ 0xfe, 0xf1, 0xb2, 0x51, 0x1a, 0x29, 0x89, 0x62, 0xed, 0x4a, 0xc5, 0xed,
+ 0x39, 0xd6, 0x2a, 0x4d, 0xa0, 0x85, 0xea, 0x24, 0x4b, 0x93, 0xbd, 0xff,
+ 0xe6, 0x8f, 0x30, 0x7f, 0x93, 0x22, 0x26, 0x09, 0x62, 0xff, 0xfe, 0x19,
+ 0x9c, 0x78, 0xe9, 0x20, 0x7f, 0x0b, 0x1f, 0xeb, 0x17, 0xff, 0x9e, 0x3a,
+ 0x48, 0x1f, 0xc2, 0xc7, 0xfa, 0xc5, 0xec, 0x39, 0x84, 0x8a, 0x7e, 0x2e,
+ 0xd4, 0x13, 0x2c, 0x28, 0x7c, 0x5b, 0x8b, 0x17, 0xf9, 0x8d, 0xc1, 0xfc,
+ 0x5d, 0x2c, 0x54, 0x9e, 0x41, 0x09, 0x5f, 0xfa, 0x7a, 0x33, 0x92, 0xfb,
+ 0x37, 0x96, 0x2f, 0xf6, 0x4f, 0x51, 0x14, 0x9d, 0x62, 0xb0, 0xfd, 0x7a,
+ 0x41, 0xb8, 0x46, 0xac, 0x5f, 0x16, 0x0b, 0x65, 0x8a, 0xf9, 0xbc, 0x61,
+ 0x9b, 0xa7, 0x75, 0x8b, 0x84, 0x6a, 0xc5, 0xf7, 0x24, 0x1c, 0x58, 0xb8,
+ 0x51, 0xeb, 0x17, 0xe2, 0xce, 0xa1, 0xc5, 0x8b, 0xe3, 0xe7, 0xb8, 0x62,
+ 0x2e, 0x37, 0x20, 0xf8, 0xc7, 0x06, 0x63, 0x88, 0xfb, 0x86, 0xef, 0xff,
+ 0xb6, 0xc1, 0x98, 0x76, 0x86, 0x9f, 0x66, 0x3a, 0xc5, 0xfd, 0xd7, 0x3f,
+ 0x8d, 0xa5, 0x8b, 0xff, 0xff, 0xf6, 0x3f, 0x6c, 0xe7, 0xe7, 0xa3, 0x0e,
+ 0xe6, 0x16, 0x72, 0x4d, 0xe4, 0xeb, 0x75, 0x8b, 0xff, 0xf9, 0xf3, 0xa2,
+ 0x17, 0xa7, 0xe6, 0x76, 0x7f, 0x45, 0x2b, 0x17, 0xff, 0xba, 0xcd, 0x19,
+ 0xfc, 0x8b, 0xf2, 0x46, 0xac, 0x5c, 0xe7, 0xd2, 0x2b, 0x49, 0x7e, 0x9d,
+ 0x3e, 0x46, 0x53, 0x22, 0xff, 0x46, 0x6b, 0x7f, 0xe9, 0x2f, 0x4c, 0x1c,
+ 0x8d, 0x95, 0x8b, 0xf6, 0xef, 0xcc, 0x1a, 0xc5, 0xff, 0xf0, 0xa3, 0xfe,
+ 0xc5, 0x11, 0x9a, 0xcf, 0x37, 0x4b, 0x1f, 0x35, 0x35, 0xb3, 0x2c, 0x50,
+ 0x70, 0xdf, 0x36, 0x19, 0x7b, 0x97, 0x75, 0x1d, 0x93, 0xc2, 0xe6, 0x28,
+ 0xd3, 0xce, 0xe1, 0xf8, 0x4a, 0x82, 0x31, 0x6f, 0x4a, 0x5a, 0xec, 0x82,
+ 0x13, 0x35, 0xff, 0xe6, 0xdb, 0xf2, 0xfe, 0xe4, 0xed, 0x9c, 0x58, 0xbe,
+ 0x33, 0x6c, 0xe2, 0xc5, 0x61, 0xf8, 0x1d, 0x2e, 0xff, 0xf6, 0x34, 0x46,
+ 0x31, 0x7a, 0x2c, 0xd6, 0x2c, 0x5f, 0xed, 0x6d, 0x2f, 0xac, 0x25, 0x8b,
+ 0xc6, 0xf2, 0x25, 0x8a, 0xc3, 0xd3, 0xe8, 0xce, 0xc7, 0x58, 0x30, 0xd1,
+ 0x5f, 0xff, 0xe6, 0x3b, 0x17, 0xa2, 0xcd, 0x61, 0x9e, 0xee, 0xf6, 0x47,
+ 0xac, 0x5f, 0x44, 0xf9, 0xb2, 0xc5, 0xe2, 0xc1, 0xac, 0x5f, 0x81, 0x82,
+ 0xd6, 0xcb, 0x17, 0x07, 0xc5, 0x8b, 0xc3, 0xfc, 0xac, 0x18, 0x5c, 0xd6,
+ 0x1f, 0x80, 0x90, 0xef, 0x8c, 0xfb, 0x44, 0xb1, 0x52, 0x9c, 0x0e, 0xc4,
+ 0x78, 0xd1, 0xd1, 0x21, 0x42, 0x33, 0x84, 0x37, 0xed, 0xe7, 0xf2, 0x75,
+ 0x8b, 0xe9, 0xc0, 0xb6, 0x58, 0xac, 0x3c, 0xd2, 0x29, 0xbd, 0x1c, 0x2f,
+ 0x2c, 0x5f, 0xb7, 0x9f, 0xc9, 0xd6, 0x2f, 0xde, 0xe1, 0x39, 0xab, 0x17,
+ 0xfc, 0xc6, 0xe6, 0xf3, 0xf9, 0x3a, 0xc5, 0xf0, 0xf5, 0xa9, 0x58, 0xbe,
+ 0x37, 0xed, 0x05, 0x8a, 0xc3, 0xc7, 0x72, 0x3a, 0x8d, 0x93, 0x34, 0x81,
+ 0x06, 0x10, 0x9c, 0xa4, 0x8a, 0x42, 0x84, 0x0d, 0xfb, 0x99, 0x84, 0x6a,
+ 0xc5, 0xff, 0xee, 0xa1, 0xc8, 0x9c, 0xb0, 0x78, 0x46, 0xac, 0x5e, 0x1b,
+ 0x1d, 0x62, 0xff, 0xef, 0x0b, 0xa8, 0x73, 0xf9, 0xe9, 0x1a, 0xc5, 0xff,
+ 0x0d, 0xfb, 0x38, 0xfe, 0xe6, 0x61, 0xf2, 0x77, 0x0e, 0xd7, 0x49, 0x96,
+ 0x31, 0x40, 0xa1, 0x61, 0x78, 0x39, 0x02, 0xc5, 0xfe, 0xdf, 0x77, 0x08,
+ 0x62, 0xd2, 0xc5, 0x1c, 0xf5, 0x88, 0x7a, 0xfc, 0x09, 0x3c, 0xe9, 0x62,
+ 0xff, 0xf6, 0xc3, 0xd3, 0x6e, 0x59, 0xdb, 0x4f, 0xc5, 0x8a, 0x95, 0x56,
+ 0x19, 0x1c, 0x6b, 0xc2, 0x31, 0x88, 0x44, 0x51, 0x77, 0xb8, 0xb1, 0x7f,
+ 0xe6, 0xe1, 0x93, 0x13, 0xfd, 0x8e, 0xb1, 0x7f, 0x7b, 0xed, 0x10, 0x67,
+ 0x58, 0xa5, 0x8b, 0x7d, 0x62, 0xbe, 0x5f, 0x30, 0x65, 0xd9, 0xc5, 0x8b,
+ 0x9b, 0x4b, 0x16, 0x04, 0x0d, 0x76, 0x85, 0xee, 0x70, 0x2c, 0x58, 0x6b,
+ 0x17, 0x34, 0x0c, 0x35, 0x21, 0x8b, 0xdb, 0xd2, 0x7f, 0xdf, 0x50, 0xa8,
+ 0x93, 0x81, 0x64, 0x00, 0x27, 0x94, 0x32, 0xee, 0x38, 0x6b, 0x17, 0x48,
+ 0xd6, 0x2e, 0xe3, 0xac, 0x5d, 0xd0, 0x16, 0x2b, 0xe7, 0x8f, 0xdf, 0x8b,
+ 0x88, 0x5e, 0xe7, 0x09, 0x62, 0xff, 0xd1, 0x3f, 0x03, 0xe8, 0x0c, 0xfb,
+ 0x2c, 0x5f, 0x74, 0x0d, 0x4a, 0xc5, 0x18, 0x7c, 0xf2, 0x87, 0x43, 0x45,
+ 0x0f, 0x1f, 0xee, 0x1b, 0xac, 0x54, 0xb7, 0x15, 0x7b, 0x43, 0x4f, 0x29,
+ 0x7e, 0x5b, 0xc6, 0xb5, 0xd1, 0x0b, 0xca, 0x41, 0xd4, 0xe4, 0x6f, 0xd4,
+ 0xda, 0x39, 0x90, 0x21, 0x13, 0x07, 0x21, 0xab, 0xd8, 0x8e, 0xff, 0x8c,
+ 0xfe, 0x77, 0x3f, 0x9e, 0x0b, 0x17, 0xf7, 0x86, 0x26, 0xd4, 0x16, 0x2f,
+ 0x76, 0xfe, 0x2c, 0x5f, 0x39, 0xe7, 0xeb, 0x17, 0xe6, 0xf9, 0x83, 0x95,
+ 0x8a, 0x82, 0x35, 0xb0, 0xf5, 0xcb, 0xfe, 0x3f, 0xe2, 0x2b, 0xcd, 0x17,
+ 0x16, 0x2f, 0x43, 0x38, 0xb1, 0x7f, 0x78, 0xa6, 0x19, 0xe5, 0x8b, 0xec,
+ 0x26, 0x82, 0xc5, 0xc1, 0xf0, 0xc3, 0xce, 0x8d, 0x8b, 0x69, 0xd1, 0x41,
+ 0xc6, 0xba, 0xd2, 0x38, 0x3d, 0x0b, 0xeb, 0xd3, 0xee, 0x2c, 0x5f, 0xcf,
+ 0xb6, 0x7c, 0x5e, 0x58, 0xa2, 0x3c, 0xcf, 0x0e, 0xdb, 0x16, 0x2f, 0x72,
+ 0x4d, 0x58, 0xaf, 0x9a, 0xff, 0x08, 0xda, 0x25, 0x8b, 0xfb, 0x05, 0x9f,
+ 0xdf, 0x65, 0x8b, 0xff, 0xd3, 0xf3, 0x07, 0x3b, 0x18, 0x2d, 0xa7, 0xeb,
+ 0x15, 0x28, 0x92, 0xe0, 0x98, 0x8c, 0x2f, 0xc6, 0x60, 0xf0, 0x96, 0x2b,
+ 0xa3, 0xd7, 0x22, 0xfb, 0xdf, 0x91, 0xac, 0x54, 0xa6, 0x93, 0x91, 0x85,
+ 0x44, 0x45, 0x7f, 0xf8, 0xd2, 0xcd, 0xfe, 0xfd, 0xde, 0xfb, 0xc4, 0xb1,
+ 0x7f, 0xfe, 0x33, 0x7f, 0xb8, 0xca, 0x5b, 0x6d, 0xfe, 0xda, 0x58, 0xa7,
+ 0x45, 0x48, 0x94, 0x2f, 0xec, 0xd0, 0x1c, 0xbc, 0xb1, 0x77, 0x5d, 0x2c,
+ 0x58, 0xe6, 0x1e, 0x39, 0xcb, 0x6f, 0xde, 0x7d, 0x89, 0x96, 0x2f, 0xff,
+ 0xd9, 0x84, 0x69, 0x81, 0xf9, 0xfe, 0xe6, 0xfd, 0xd6, 0x2f, 0x9f, 0x8f,
+ 0xd9, 0x62, 0xff, 0xfb, 0x6f, 0xb7, 0x0c, 0xfb, 0x3f, 0x9c, 0x78, 0xb1,
+ 0x7d, 0x9e, 0x9f, 0xac, 0x5e, 0x36, 0x62, 0x58, 0xbe, 0x6d, 0x61, 0xd6,
+ 0x2f, 0xfd, 0xc3, 0x3b, 0xbd, 0x9f, 0xf3, 0x9d, 0x62, 0x86, 0x7c, 0xde,
+ 0x22, 0xb4, 0xac, 0x5f, 0xf4, 0xf4, 0x08, 0xa1, 0x3a, 0xd9, 0x62, 0xb6,
+ 0x3c, 0xef, 0x88, 0xd4, 0x15, 0x17, 0x8c, 0xa2, 0x25, 0x8d, 0x12, 0x7d,
+ 0x45, 0x88, 0x8a, 0x10, 0xbe, 0x70, 0xbf, 0xbe, 0xd0, 0x3e, 0x9d, 0x62,
+ 0xff, 0xc6, 0xb7, 0xb9, 0xe2, 0x9e, 0xa0, 0xb1, 0x7d, 0x26, 0x73, 0x4b,
+ 0x14, 0x69, 0xf2, 0xe9, 0x06, 0xfe, 0xcc, 0x62, 0xf7, 0x16, 0x2f, 0xc5,
+ 0x30, 0xcf, 0x2c, 0x51, 0x1e, 0x9f, 0x8b, 0x2f, 0xfe, 0x37, 0xde, 0x9d,
+ 0x00, 0xcd, 0xbf, 0xe5, 0x8b, 0x32, 0xc5, 0x4a, 0x3c, 0xa0, 0xec, 0xc4,
+ 0x3e, 0x4a, 0xbf, 0x10, 0xa2, 0x61, 0xac, 0x5f, 0xe7, 0xf0, 0x7a, 0x9f,
+ 0xca, 0xc5, 0xff, 0xff, 0x4e, 0x9f, 0x61, 0x47, 0x98, 0x5d, 0x4c, 0x79,
+ 0x8d, 0x16, 0x32, 0xc5, 0xfd, 0x06, 0xd8, 0xc8, 0xfd, 0xd6, 0x2f, 0x1c,
+ 0x71, 0xa2, 0xc5, 0xb8, 0xb1, 0x58, 0x6d, 0x5c, 0x8e, 0xc7, 0x58, 0xbd,
+ 0xac, 0xe9, 0x62, 0xf6, 0x3e, 0xcb, 0x17, 0xd2, 0x73, 0xba, 0xc5, 0xb3,
+ 0x63, 0x7f, 0xe1, 0xdb, 0xff, 0xfe, 0x9f, 0x9c, 0x3d, 0xcc, 0x36, 0x4b,
+ 0x73, 0x1f, 0x5a, 0x70, 0x96, 0x28, 0x69, 0x91, 0xfc, 0x7c, 0x02, 0x44,
+ 0xbb, 0xc2, 0x7b, 0xec, 0x38, 0xbc, 0xb1, 0x7f, 0xfd, 0x9d, 0xcf, 0xa6,
+ 0x07, 0x30, 0x7f, 0x16, 0xcb, 0x17, 0x98, 0x1b, 0x2c, 0x5f, 0xfa, 0x77,
+ 0x2c, 0xed, 0xdd, 0xa6, 0xe9, 0x62, 0xff, 0x3e, 0x75, 0xdd, 0xa6, 0xe9,
+ 0x62, 0xd9, 0xc3, 0xfd, 0xee, 0x45, 0xa7, 0x4c, 0x67, 0x4a, 0x85, 0x09,
+ 0xbb, 0xe7, 0x36, 0x4e, 0xb1, 0x7d, 0xb0, 0xb5, 0xba, 0xc5, 0xff, 0xec,
+ 0xf1, 0x4e, 0xe6, 0x16, 0x73, 0xe2, 0x58, 0xbf, 0xce, 0x59, 0xe6, 0xe6,
+ 0x2c, 0x5f, 0xfd, 0x14, 0x1c, 0x2f, 0x7f, 0x23, 0xb8, 0xcb, 0x17, 0xf9,
+ 0xf3, 0xae, 0xed, 0x37, 0x4b, 0x16, 0xc8, 0x91, 0x67, 0xa3, 0x1e, 0xe4,
+ 0xab, 0xfe, 0x36, 0x4a, 0x19, 0xf7, 0x3a, 0xc5, 0xcc, 0x69, 0x89, 0xf6,
+ 0xc9, 0xa6, 0xc4, 0x7f, 0x26, 0x28, 0x7f, 0x78, 0xe6, 0xfb, 0x9c, 0x93,
+ 0xac, 0x5f, 0x7e, 0x7b, 0x4a, 0xc5, 0x39, 0xe3, 0xb1, 0x1d, 0x4a, 0xf4,
+ 0xec, 0x0a, 0x70, 0xd3, 0xa7, 0x07, 0x8e, 0x37, 0x49, 0x45, 0x2c, 0xa7,
+ 0xb4, 0x2c, 0x2a, 0x5b, 0x02, 0xec, 0x8c, 0xa0, 0xd7, 0x47, 0x8e, 0x67,
+ 0x50, 0xdf, 0x3b, 0x4b, 0x4a, 0x58, 0x03, 0xb9, 0x47, 0x0a, 0x29, 0xed,
+ 0x8b, 0x04, 0xb1, 0x6d, 0x96, 0x2b, 0xb1, 0xa6, 0x8e, 0x13, 0xbc, 0xf3,
+ 0xdc, 0xb1, 0x68, 0x2c, 0x5f, 0xff, 0xf0, 0x33, 0xdc, 0x33, 0xf9, 0xbe,
+ 0x6e, 0x67, 0x06, 0x59, 0xf5, 0x8b, 0xf0, 0xdc, 0x98, 0x6b, 0x17, 0xb8,
+ 0x3e, 0x96, 0x2f, 0x7e, 0x36, 0xd2, 0xc5, 0xc0, 0xdd, 0x62, 0xff, 0xf6,
+ 0x45, 0xf9, 0x23, 0x4b, 0x3d, 0xf1, 0x2c, 0x51, 0x88, 0x87, 0x34, 0x8f,
+ 0xe3, 0x37, 0xdb, 0x89, 0xa0, 0xb1, 0x46, 0x23, 0xf2, 0x10, 0xa6, 0xe8,
+ 0xca, 0x86, 0x9f, 0xb6, 0xe3, 0xfd, 0x09, 0x3b, 0x5e, 0xa3, 0x23, 0xba,
+ 0x38, 0x96, 0x2f, 0xa0, 0x60, 0x67, 0x58, 0xbf, 0xb5, 0xfc, 0xd0, 0xb1,
+ 0x62, 0xff, 0xfe, 0xce, 0xa1, 0xcf, 0x7e, 0x4f, 0x2e, 0x33, 0x27, 0xbc,
+ 0x58, 0xbf, 0xa1, 0xcc, 0x16, 0x80, 0xb1, 0x7f, 0x67, 0x50, 0xe0, 0xa2,
+ 0x58, 0xbf, 0x67, 0x31, 0xc9, 0x62, 0xf8, 0xa2, 0x73, 0xf4, 0x88, 0x6d,
+ 0x17, 0xfc, 0xc6, 0xff, 0xf1, 0x6f, 0xf6, 0xf1, 0x9a, 0xcf, 0x37, 0x4b,
+ 0x15, 0x89, 0xd5, 0xb9, 0x73, 0x43, 0xa0, 0x49, 0x17, 0xf3, 0x30, 0xd9,
+ 0xbb, 0x2c, 0x5e, 0xeb, 0x0d, 0x58, 0xbf, 0xb3, 0x6d, 0x85, 0xad, 0x96,
+ 0x2d, 0xa3, 0x0f, 0xff, 0xe5, 0xc4, 0x3f, 0x7f, 0xce, 0x46, 0xf8, 0x65,
+ 0x3d, 0x2c, 0x5f, 0xb4, 0x44, 0xdf, 0x58, 0xbf, 0xfe, 0x26, 0xea, 0x1f,
+ 0xcf, 0x8a, 0x78, 0xc0, 0x58, 0xbf, 0xdd, 0xec, 0x8f, 0xf9, 0xbc, 0xac,
+ 0x5d, 0x9c, 0x31, 0x11, 0x3d, 0xe2, 0x85, 0xfc, 0x46, 0x6f, 0xc0, 0x0d,
+ 0x62, 0xa5, 0x38, 0x4c, 0x35, 0x73, 0xaf, 0xc2, 0xc1, 0x8d, 0x2f, 0xff,
+ 0xe7, 0xe7, 0xf3, 0x5a, 0x9d, 0x8c, 0xc2, 0x1f, 0xe5, 0x62, 0xff, 0xc2,
+ 0xe1, 0x87, 0x0f, 0xed, 0xf9, 0x58, 0xbf, 0x67, 0x85, 0x9d, 0x2c, 0x5e,
+ 0x37, 0x3a, 0x58, 0xba, 0x62, 0x30, 0xf2, 0x3c, 0x53, 0x58, 0x98, 0xa9,
+ 0x2e, 0x0a, 0x11, 0x57, 0xfe, 0x37, 0xf3, 0x9f, 0x7c, 0xd4, 0x4b, 0x17,
+ 0xff, 0xef, 0x63, 0x9c, 0xc2, 0xcd, 0xdf, 0x5a, 0x7d, 0x96, 0x28, 0x91,
+ 0x2e, 0x12, 0x05, 0xff, 0xff, 0xf8, 0x44, 0x60, 0x4d, 0xd4, 0x34, 0xc0,
+ 0x33, 0x82, 0x9e, 0xbf, 0x8e, 0x58, 0x6a, 0xc5, 0xff, 0xff, 0xfe, 0xdf,
+ 0x37, 0x2c, 0xf7, 0xc5, 0xf6, 0xea, 0x1c, 0xf6, 0xb0, 0x2c, 0x71, 0xfb,
+ 0x8e, 0xb1, 0x7f, 0x38, 0xcc, 0x87, 0x34, 0xb1, 0x7f, 0xec, 0xf1, 0x48,
+ 0x0c, 0xc7, 0x1a, 0xc5, 0xff, 0xfe, 0xc3, 0x9e, 0x62, 0xce, 0x3e, 0x03,
+ 0x86, 0x63, 0x8d, 0x62, 0xf8, 0x58, 0x46, 0x3a, 0x27, 0xc8, 0xfa, 0xb4,
+ 0x98, 0x3f, 0xa1, 0x9f, 0x7f, 0xc7, 0xc3, 0x98, 0x78, 0xfe, 0xd0, 0x58,
+ 0xbf, 0xff, 0xfd, 0x86, 0x68, 0x3e, 0x49, 0x9c, 0x7c, 0x28, 0xb9, 0xe7,
+ 0xcd, 0x8a, 0x56, 0x2f, 0xff, 0xff, 0x7f, 0x04, 0x73, 0x32, 0x2c, 0xeb,
+ 0xcc, 0x09, 0x33, 0xc3, 0x9f, 0x71, 0x62, 0xb4, 0x9b, 0x01, 0xca, 0x7e,
+ 0x83, 0xc7, 0xab, 0xff, 0xed, 0x6b, 0x3d, 0xcf, 0xbe, 0x19, 0xf0, 0x4a,
+ 0xc5, 0x4a, 0xb8, 0x87, 0x95, 0xf2, 0x23, 0xeb, 0xff, 0xfa, 0x7f, 0x83,
+ 0x34, 0x53, 0xfc, 0xf4, 0x9d, 0xbc, 0xb1, 0x52, 0xb9, 0x8b, 0x84, 0x7f,
+ 0x9c, 0x10, 0x11, 0xbd, 0xff, 0xe0, 0x63, 0x44, 0x67, 0x33, 0x5a, 0xce,
+ 0x96, 0x2f, 0xfe, 0xc2, 0x2c, 0xfe, 0x0f, 0xe2, 0x89, 0x62, 0xff, 0xb2,
+ 0x4b, 0x7c, 0xf7, 0xdd, 0x62, 0xf7, 0xe6, 0x25, 0x8b, 0xff, 0xc0, 0x9f,
+ 0xf5, 0x0e, 0x16, 0x00, 0x5c, 0x58, 0xbf, 0xff, 0xfe, 0x78, 0xbf, 0x9c,
+ 0xd6, 0x6e, 0x67, 0xdf, 0x0b, 0x3b, 0x16, 0x0c, 0x44, 0xb1, 0x7f, 0xf8,
+ 0xa4, 0xfd, 0x79, 0xc6, 0x66, 0xb3, 0xcb, 0x17, 0xec, 0x2d, 0xc3, 0x3a,
+ 0xc5, 0xff, 0xdf, 0xc9, 0x28, 0x8b, 0x3d, 0xc6, 0x58, 0xb4, 0x0d, 0x54,
+ 0xd6, 0xe9, 0xba, 0x44, 0xf9, 0xc0, 0x07, 0x89, 0x33, 0x8f, 0xfe, 0x4c,
+ 0xee, 0x2a, 0xbe, 0x9d, 0xf5, 0x8b, 0x17, 0xfe, 0xee, 0xf4, 0xf2, 0x28,
+ 0x36, 0xb6, 0x58, 0xbd, 0xe7, 0x35, 0x62, 0xc7, 0x30, 0xf8, 0xe3, 0x64,
+ 0x5b, 0xfe, 0xf7, 0x24, 0x0c, 0x42, 0xc5, 0x8a, 0xc3, 0xe6, 0x11, 0x75,
+ 0xff, 0xcf, 0xb3, 0x1c, 0xee, 0x60, 0xdf, 0xb2, 0xc5, 0x41, 0x35, 0x51,
+ 0xc3, 0xb3, 0x44, 0x37, 0xa2, 0x78, 0xf5, 0x8b, 0xf8, 0x3d, 0x00, 0xef,
+ 0xc5, 0x8b, 0xff, 0x03, 0x86, 0x7f, 0x07, 0xac, 0xe9, 0x62, 0xba, 0x3f,
+ 0x27, 0x30, 0xbf, 0xff, 0xbc, 0xfb, 0x60, 0xcc, 0x3b, 0x43, 0x4f, 0xb3,
+ 0x1d, 0x62, 0xff, 0x6c, 0xc7, 0x29, 0xd4, 0x4b, 0x17, 0xfb, 0x0d, 0x01,
+ 0xf0, 0xcd, 0x62, 0x24, 0xdd, 0x7a, 0xff, 0xff, 0x1a, 0x71, 0x1c, 0x5d,
+ 0xdc, 0x7d, 0xbf, 0x91, 0x41, 0xbb, 0x96, 0x2f, 0xff, 0x16, 0xff, 0xc0,
+ 0x00, 0x41, 0x75, 0x0e, 0x2c, 0x54, 0xa2, 0xed, 0xdb, 0x2b, 0x13, 0xdc,
+ 0xea, 0x16, 0xba, 0x8c, 0x1a, 0xf8, 0x0c, 0xd1, 0x2c, 0x5a, 0x56, 0x2f,
+ 0x61, 0x6c, 0x61, 0xb4, 0xdc, 0x8e, 0xfb, 0x73, 0x39, 0x8b, 0x17, 0xff,
+ 0x68, 0xc8, 0xbe, 0x23, 0x5f, 0x08, 0xd5, 0x8b, 0x66, 0x1f, 0x70, 0x89,
+ 0x6f, 0xf1, 0x7b, 0xc4, 0xc0, 0xe2, 0xc5, 0xf0, 0x0c, 0x3e, 0x96, 0x2a,
+ 0x4f, 0x60, 0x46, 0x77, 0xe3, 0x1b, 0x72, 0xc5, 0x8b, 0xff, 0xb1, 0xa2,
+ 0x33, 0xf2, 0xfb, 0x49, 0xab, 0x14, 0x74, 0x48, 0xb1, 0x08, 0x0a, 0x6f,
+ 0xff, 0xf0, 0x5a, 0xc7, 0x07, 0x0c, 0xea, 0x0e, 0x5e, 0xc7, 0x1a, 0xc5,
+ 0xfd, 0x0e, 0x60, 0xb4, 0x05, 0x8b, 0xfb, 0x3a, 0x87, 0x05, 0x12, 0xc5,
+ 0xfb, 0x39, 0x8e, 0x4b, 0x16, 0xed, 0xd2, 0x21, 0xb4, 0x5f, 0xf3, 0x1b,
+ 0xff, 0xde, 0x9d, 0x08, 0xef, 0xc3, 0x39, 0x0e, 0x2c, 0x5f, 0xfb, 0x63,
+ 0x45, 0x31, 0x19, 0x08, 0x62, 0xc5, 0xff, 0xb9, 0xef, 0xe1, 0xf7, 0x92,
+ 0x35, 0x62, 0xb1, 0x10, 0xa0, 0x44, 0xa9, 0x54, 0x2c, 0xf0, 0xe9, 0x63,
+ 0x91, 0x43, 0x4a, 0xff, 0xb5, 0xb4, 0xed, 0xb0, 0xb5, 0xb2, 0xc5, 0xff,
+ 0xfc, 0xfd, 0x7b, 0xd2, 0x73, 0x3f, 0x3d, 0x03, 0x3d, 0xc5, 0x8b, 0xff,
+ 0xf1, 0x49, 0xa6, 0x1c, 0x4f, 0xc9, 0xf9, 0xc3, 0xdd, 0x62, 0xff, 0xf4,
+ 0xbf, 0xb8, 0xe5, 0xd4, 0x0c, 0xe0, 0xd6, 0x2f, 0xfc, 0x64, 0x5f, 0x11,
+ 0xaf, 0x84, 0x6a, 0xc5, 0xff, 0xfa, 0x63, 0xcc, 0xea, 0x13, 0xb7, 0x50,
+ 0xe1, 0x31, 0xab, 0x17, 0xf8, 0x8c, 0xe0, 0xa3, 0x85, 0xa5, 0x8a, 0xc4,
+ 0x6d, 0x7d, 0x0c, 0x4b, 0xd7, 0xff, 0xff, 0xb3, 0x76, 0xd8, 0xce, 0x3c,
+ 0x74, 0x90, 0x3d, 0xdc, 0x52, 0x58, 0xfe, 0x58, 0xbf, 0xff, 0xbd, 0x25,
+ 0x9b, 0x19, 0xb0, 0xb5, 0x0f, 0x4c, 0x5c, 0x58, 0xba, 0x7a, 0xfa, 0x37,
+ 0x7b, 0x9f, 0x6a, 0x55, 0xae, 0x61, 0xf9, 0xd7, 0xfe, 0xb5, 0xc8, 0xc9,
+ 0x85, 0x18, 0x65, 0xfc, 0x59, 0xd8, 0xb3, 0x8b, 0x17, 0xb1, 0xc2, 0x58,
+ 0xb9, 0x89, 0x62, 0xb7, 0x36, 0x7d, 0x0e, 0xd1, 0x88, 0x84, 0xc6, 0x1b,
+ 0xfc, 0xe0, 0x31, 0xfe, 0xe7, 0x58, 0xa1, 0x9e, 0xb9, 0x11, 0xdf, 0xfc,
+ 0x67, 0x3e, 0x23, 0x3d, 0xce, 0x4e, 0x96, 0x2f, 0xff, 0xe9, 0xd0, 0x0c,
+ 0x9e, 0xcd, 0xf9, 0xd6, 0xb3, 0xdc, 0x58, 0xad, 0x91, 0x4f, 0xf4, 0x9b,
+ 0xff, 0x42, 0x7c, 0x2d, 0xcc, 0xe7, 0x9d, 0x62, 0xff, 0xfb, 0xf3, 0xb1,
+ 0x85, 0x9d, 0x9b, 0xff, 0x9e, 0x96, 0x2f, 0xff, 0xfb, 0xae, 0x3e, 0x04,
+ 0x67, 0xf3, 0xdc, 0xcd, 0x8c, 0xc7, 0x1a, 0xc5, 0x0d, 0x17, 0xf8, 0xa9,
+ 0x7f, 0xef, 0x3f, 0x50, 0x29, 0x33, 0xbb, 0x75, 0x8b, 0xff, 0xd2, 0x72,
+ 0xce, 0xc5, 0x9d, 0xb3, 0x50, 0x58, 0xac, 0x44, 0x89, 0x22, 0xdf, 0xfb,
+ 0x9f, 0x7c, 0xf7, 0x50, 0x7f, 0xac, 0x5f, 0xff, 0xfd, 0xce, 0x61, 0x1b,
+ 0x8e, 0x3d, 0x49, 0xfa, 0x84, 0x9b, 0xf7, 0xc5, 0x8b, 0x75, 0x04, 0x59,
+ 0xe2, 0x05, 0xff, 0xf8, 0x2e, 0x6f, 0xf1, 0x1f, 0xac, 0xf9, 0x75, 0x21,
+ 0x2c, 0x54, 0xa2, 0x17, 0x0a, 0x6f, 0xf8, 0xb3, 0x59, 0xbe, 0x38, 0xd6,
+ 0x2f, 0xed, 0xbd, 0x11, 0x49, 0xd6, 0x2f, 0xbf, 0xd6, 0x1a, 0xb1, 0x7e,
+ 0x69, 0x8a, 0x62, 0x58, 0xbf, 0x60, 0xfe, 0x20, 0x96, 0x28, 0xc3, 0xd3,
+ 0x22, 0x9b, 0x4e, 0xe8, 0x9a, 0x89, 0xe2, 0xff, 0xfd, 0xb6, 0x38, 0xc8,
+ 0x5f, 0x32, 0x46, 0xd1, 0x71, 0x62, 0xfe, 0xd4, 0x8c, 0x58, 0x6a, 0xc5,
+ 0x62, 0x21, 0xdd, 0x62, 0xfe, 0xcf, 0xbe, 0xbe, 0xcb, 0x17, 0xef, 0xbe,
+ 0xbe, 0xcb, 0x17, 0x60, 0x46, 0x1e, 0xae, 0x16, 0xd4, 0xaf, 0x38, 0xe4,
+ 0x32, 0x3a, 0x24, 0x78, 0xc0, 0x62, 0x85, 0x9e, 0xa3, 0x59, 0xf9, 0x0b,
+ 0x1c, 0x14, 0x32, 0xb9, 0x0b, 0x1f, 0x3b, 0x5f, 0x7b, 0x30, 0x6b, 0x15,
+ 0xb3, 0xa0, 0xf8, 0x1c, 0xa4, 0x33, 0x63, 0x61, 0xde, 0x76, 0x43, 0xa9,
+ 0x56, 0x2f, 0x1e, 0xec, 0x46, 0xda, 0x94, 0xde, 0x77, 0x0f, 0xc2, 0x88,
+ 0x11, 0x87, 0x94, 0xa4, 0x5e, 0x4b, 0xa2, 0xf4, 0xfd, 0x7f, 0x74, 0x2e,
+ 0x2f, 0xff, 0x9f, 0x4d, 0x13, 0xfc, 0xc9, 0x8f, 0xf4, 0xc4, 0xb1, 0x79,
+ 0xf2, 0x25, 0x8b, 0xfb, 0xf9, 0xef, 0xb4, 0x16, 0x2a, 0x08, 0xa0, 0xfa,
+ 0xaf, 0x87, 0x6f, 0xf6, 0x04, 0x61, 0x16, 0x74, 0xb1, 0x7c, 0xfc, 0xc1,
+ 0x98, 0x7c, 0xbb, 0x18, 0x5f, 0x43, 0x0b, 0xeb, 0x17, 0xfb, 0xc5, 0x9e,
+ 0xfe, 0x6c, 0xb1, 0x7c, 0x28, 0x0a, 0x56, 0x2f, 0xa6, 0x3c, 0x51, 0x2c,
+ 0x5d, 0xac, 0x58, 0xbd, 0x9e, 0xe2, 0xc5, 0xfd, 0xdd, 0xe7, 0x26, 0x3a,
+ 0xc5, 0x2c, 0x5f, 0x73, 0x27, 0x63, 0x0d, 0xe1, 0xcc, 0x2b, 0x64, 0x54,
+ 0xc4, 0x2f, 0xe5, 0x9b, 0xdf, 0x63, 0x56, 0x2f, 0xf1, 0x9a, 0xce, 0xa0,
+ 0xe7, 0x58, 0xad, 0x22, 0x1b, 0xc6, 0x41, 0x0f, 0x5f, 0xf9, 0xb5, 0xfc,
+ 0xf4, 0x93, 0x81, 0x62, 0xdd, 0xcb, 0x17, 0xb6, 0x3e, 0xeb, 0x17, 0xe7,
+ 0xc2, 0xce, 0xcb, 0x17, 0xd8, 0xf1, 0x19, 0xd1, 0xe4, 0x7c, 0x82, 0xef,
+ 0x4a, 0xc5, 0xfd, 0xf1, 0x6c, 0x64, 0x5b, 0x2c, 0x5d, 0x3a, 0x58, 0xbf,
+ 0xc2, 0xf6, 0x61, 0xc0, 0x12, 0xc5, 0xec, 0xd8, 0xc1, 0xa2, 0x02, 0x23,
+ 0x40, 0x0b, 0xd7, 0x48, 0xdb, 0x28, 0x4b, 0xde, 0xf3, 0xec, 0xb1, 0x68,
+ 0xe5, 0x8a, 0x81, 0xb3, 0x8f, 0x1e, 0xbf, 0xdb, 0xbf, 0x30, 0x66, 0x0d,
+ 0x62, 0xfe, 0xea, 0x1c, 0x33, 0xce, 0xb1, 0x6c, 0xf9, 0xf3, 0x84, 0x6d,
+ 0x7f, 0xfe, 0x29, 0x39, 0x83, 0xf8, 0x8c, 0x98, 0xff, 0xc9, 0xd6, 0x2f,
+ 0xf9, 0xc0, 0xf0, 0xfb, 0x90, 0x16, 0x2f, 0xfd, 0x09, 0xc0, 0x7f, 0x30,
+ 0xb7, 0x58, 0xbf, 0xfd, 0xf7, 0x21, 0x98, 0x1e, 0xe5, 0x9f, 0xc5, 0x8b,
+ 0xfe, 0x6f, 0x72, 0x28, 0x08, 0xbc, 0xb1, 0x52, 0x8f, 0xdc, 0x38, 0x88,
+ 0xf8, 0x09, 0x97, 0xfd, 0xf7, 0x3c, 0xe1, 0x7b, 0x8b, 0x17, 0xff, 0xf8,
+ 0x5e, 0xd0, 0xa2, 0x33, 0xd1, 0x7c, 0x40, 0xf3, 0xe7, 0x72, 0xc5, 0xf4,
+ 0xef, 0x27, 0x31, 0x1b, 0xdb, 0x9e, 0x11, 0xc5, 0x4a, 0xf8, 0xd6, 0xc6,
+ 0x83, 0x23, 0xc8, 0xd5, 0xb7, 0x31, 0x73, 0xd8, 0x97, 0x75, 0x18, 0xb3,
+ 0x2d, 0x94, 0x22, 0xfc, 0x51, 0xdd, 0x28, 0xda, 0xff, 0xf3, 0x44, 0x63,
+ 0x14, 0x1c, 0xe6, 0x49, 0x2c, 0x5f, 0xff, 0xb1, 0x8e, 0x61, 0xad, 0xd7,
+ 0xf3, 0xff, 0x9f, 0x2c, 0x56, 0x22, 0x8f, 0x49, 0x77, 0xb0, 0x1c, 0x58,
+ 0xbf, 0xa4, 0x23, 0x38, 0x7e, 0x96, 0x2b, 0x0f, 0x3f, 0x43, 0xb7, 0x38,
+ 0x4b, 0x17, 0xb5, 0x14, 0x16, 0x2f, 0xfd, 0x9d, 0x78, 0xce, 0x4f, 0xda,
+ 0x3d, 0x62, 0x86, 0x7f, 0x78, 0x31, 0xa1, 0xfb, 0xff, 0x9f, 0xa8, 0x70,
+ 0xc1, 0xbf, 0x69, 0x1a, 0xc5, 0xee, 0xa6, 0x3d, 0x62, 0xff, 0xf4, 0xc5,
+ 0xcf, 0x75, 0x07, 0xff, 0x50, 0x75, 0x8a, 0x35, 0x17, 0x0c, 0x92, 0x22,
+ 0x1b, 0xec, 0xfb, 0x76, 0x58, 0xbf, 0xa1, 0x9f, 0xce, 0xdc, 0x58, 0xbf,
+ 0x81, 0x9d, 0x19, 0xd7, 0x16, 0x2d, 0x83, 0x44, 0x34, 0x44, 0x80, 0x30,
+ 0xbf, 0xfe, 0xf8, 0xb8, 0x67, 0xdf, 0xdf, 0xcd, 0x4f, 0x65, 0x8b, 0xf7,
+ 0x26, 0x21, 0x69, 0x62, 0xfa, 0x62, 0x16, 0x96, 0x2e, 0x03, 0x18, 0x79,
+ 0xdc, 0x2a, 0xbf, 0x71, 0xf3, 0xa3, 0xac, 0x5e, 0xcd, 0x71, 0x62, 0x86,
+ 0x98, 0xb0, 0x21, 0x45, 0xe2, 0xee, 0xc5, 0x37, 0xf6, 0xb0, 0x5f, 0x93,
+ 0xac, 0x5e, 0xcc, 0x02, 0xc5, 0xd9, 0xd1, 0x87, 0x94, 0x45, 0xd5, 0x88,
+ 0xbd, 0x28, 0x47, 0xdf, 0xa7, 0xaf, 0xe6, 0xcb, 0x17, 0xfe, 0x70, 0x8c,
+ 0xd4, 0xc3, 0x92, 0x05, 0x8a, 0x23, 0xeb, 0xf1, 0x55, 0xfb, 0x3e, 0x67,
+ 0x6d, 0xd6, 0x2e, 0x93, 0x8d, 0x74, 0x83, 0x21, 0x38, 0x6c, 0x39, 0xb5,
+ 0x0b, 0x62, 0x94, 0x13, 0xe8, 0x48, 0x88, 0x86, 0xed, 0x62, 0xc5, 0xff,
+ 0xda, 0x90, 0xbb, 0x8a, 0x42, 0xea, 0x1c, 0x58, 0xb4, 0xac, 0x5f, 0x3e,
+ 0x9b, 0xa5, 0x8b, 0x79, 0xcd, 0xa7, 0x04, 0x68, 0x68, 0xa5, 0x77, 0xfb,
+ 0xfe, 0x62, 0xdf, 0xee, 0x72, 0x95, 0x8b, 0xff, 0x86, 0x4d, 0x14, 0x53,
+ 0xe0, 0x67, 0x16, 0x2f, 0xff, 0x8a, 0x76, 0xfc, 0xbf, 0xb8, 0xe5, 0xd4,
+ 0x16, 0x2e, 0x38, 0x6b, 0x16, 0x89, 0x62, 0x96, 0x2a, 0x4b, 0xfd, 0x09,
+ 0xd4, 0x9e, 0xbb, 0x9c, 0x5e, 0xdb, 0x02, 0x58, 0xbf, 0xc3, 0x32, 0x62,
+ 0x1b, 0x04, 0xb1, 0x6e, 0xc6, 0x1e, 0xb3, 0x8f, 0xdf, 0xfd, 0xa0, 0x47,
+ 0x67, 0xbf, 0x9a, 0x7e, 0x2c, 0x5f, 0xfb, 0x38, 0x59, 0xbe, 0xec, 0x40,
+ 0x58, 0xa7, 0x45, 0x8b, 0x15, 0x71, 0x22, 0xff, 0xff, 0xf1, 0x39, 0xbf,
+ 0x68, 0x8c, 0x21, 0x77, 0x19, 0x9d, 0x43, 0x04, 0x40, 0xe2, 0xc5, 0xff,
+ 0xf3, 0xc3, 0xdc, 0xce, 0xda, 0xc0, 0x71, 0xb7, 0x58, 0xbf, 0xd8, 0xc6,
+ 0x98, 0x13, 0x04, 0xb1, 0x7f, 0xff, 0xb3, 0x73, 0x0b, 0x3e, 0xf9, 0xc3,
+ 0x31, 0xff, 0x9b, 0xac, 0x5b, 0x06, 0x89, 0x9f, 0x9b, 0xdf, 0xb9, 0x3d,
+ 0x9c, 0x96, 0x2f, 0xfb, 0xda, 0x14, 0x3a, 0x86, 0x79, 0x62, 0xf9, 0xe4,
+ 0xb6, 0x58, 0xa7, 0x3d, 0xef, 0x9e, 0x51, 0xd5, 0x1d, 0xfd, 0xfc, 0xa1,
+ 0xd9, 0xe2, 0x8e, 0xd0, 0x87, 0xbf, 0xff, 0x84, 0x36, 0x20, 0x19, 0xec,
+ 0xfc, 0xfb, 0x58, 0x35, 0x8b, 0xe3, 0xbb, 0x84, 0xb1, 0x7f, 0xb4, 0xdc,
+ 0x30, 0x2e, 0x6c, 0xb1, 0x52, 0x98, 0x74, 0x15, 0xd9, 0x70, 0x44, 0x74,
+ 0x4b, 0x9b, 0x5c, 0x8c, 0x9f, 0xd2, 0xdd, 0xef, 0xfc, 0xfe, 0xe4, 0xfb,
+ 0xf3, 0xd0, 0x16, 0x2f, 0x16, 0x4a, 0xc5, 0xfd, 0x3b, 0x7d, 0xf0, 0x6b,
+ 0x15, 0x87, 0x93, 0xa1, 0xbb, 0xff, 0xe7, 0xe1, 0x83, 0xf8, 0x8c, 0x97,
+ 0x18, 0x7a, 0x58, 0xbf, 0xfc, 0x72, 0xc0, 0x48, 0x22, 0x84, 0xeb, 0x65,
+ 0x8b, 0xe9, 0x8b, 0x8e, 0xb1, 0x7f, 0xa4, 0xf3, 0x18, 0x10, 0x41, 0x2c,
+ 0x54, 0xb2, 0x30, 0xe1, 0x0b, 0xc1, 0x91, 0x61, 0xc6, 0xe8, 0xcf, 0x3b,
+ 0x03, 0x11, 0xfe, 0xa1, 0x12, 0x72, 0x16, 0x54, 0x24, 0xce, 0xe2, 0x3b,
+ 0xff, 0xef, 0x8b, 0x86, 0x7d, 0xcc, 0xf1, 0x30, 0x38, 0xb1, 0x7f, 0xff,
+ 0x42, 0x74, 0x69, 0xc9, 0xfa, 0x87, 0x07, 0xa7, 0xd9, 0x62, 0xff, 0xff,
+ 0x71, 0xc4, 0x33, 0x0d, 0x26, 0x18, 0xb3, 0xe6, 0x45, 0x12, 0xc5, 0xb0,
+ 0x69, 0x8c, 0xc4, 0xa7, 0xc5, 0xfb, 0xd3, 0x17, 0x16, 0x2d, 0xf5, 0x8b,
+ 0x84, 0x35, 0x8b, 0xa7, 0xcb, 0x17, 0xa1, 0x27, 0x58, 0xbf, 0xb8, 0x45,
+ 0x80, 0xe2, 0xc5, 0x18, 0x88, 0xb8, 0x84, 0xb4, 0x30, 0xc2, 0xfe, 0x1d,
+ 0xbf, 0xff, 0x89, 0xbd, 0xcc, 0xd0, 0x01, 0x39, 0xd7, 0xb8, 0xeb, 0x17,
+ 0xd0, 0x9d, 0x6c, 0xb1, 0x73, 0x0f, 0x0f, 0xfe, 0x25, 0xbb, 0x46, 0xeb,
+ 0x14, 0x63, 0xe1, 0x7c, 0xcc, 0xa1, 0xcd, 0x94, 0x86, 0x35, 0x96, 0x8b,
+ 0x27, 0x79, 0x45, 0x9d, 0x1d, 0x3c, 0xf9, 0xe6, 0xa3, 0x64, 0xfc, 0xec,
+ 0x8b, 0x52, 0x53, 0xca, 0x3d, 0x4f, 0x1b, 0x8a, 0x15, 0x21, 0x43, 0x2a,
+ 0x38, 0xb6, 0xf7, 0xb3, 0xeb, 0x17, 0xb9, 0x9b, 0xac, 0x5f, 0xa0, 0xe3,
+ 0xc2, 0x58, 0xb9, 0xfa, 0x58, 0xa3, 0x0f, 0x76, 0x47, 0x86, 0x4f, 0x7b,
+ 0x8f, 0xa5, 0x8b, 0xff, 0x99, 0xfd, 0x09, 0x2f, 0x71, 0xc6, 0xb1, 0x52,
+ 0x7c, 0x1f, 0x1d, 0xbb, 0x58, 0xb1, 0x7b, 0xcf, 0xd9, 0x62, 0x80, 0x6d,
+ 0x88, 0x5e, 0xfa, 0x02, 0x6f, 0x2c, 0x5d, 0x31, 0xeb, 0x17, 0x0a, 0x3d,
+ 0x62, 0xf4, 0x94, 0xac, 0x56, 0xe7, 0xa1, 0xa1, 0xa3, 0x8d, 0xdf, 0xfd,
+ 0x9d, 0xc3, 0xd4, 0x84, 0x32, 0x6f, 0xac, 0x54, 0xa6, 0x17, 0x84, 0x0e,
+ 0xe7, 0xf3, 0x0b, 0xef, 0x71, 0x80, 0xb1, 0x7f, 0xfc, 0x2d, 0x8c, 0x97,
+ 0xfe, 0xf2, 0x03, 0xb4, 0x16, 0x2f, 0xfc, 0xe6, 0x3e, 0x85, 0xb3, 0x6b,
+ 0x75, 0x8a, 0x35, 0x12, 0xbf, 0x53, 0xbe, 0x7f, 0xb6, 0xcb, 0x17, 0xcf,
+ 0xbb, 0x69, 0x62, 0xfd, 0x24, 0x73, 0x4d, 0x58, 0xbf, 0xcf, 0xc7, 0x17,
+ 0x7e, 0x39, 0x58, 0xbd, 0x3e, 0x95, 0x8a, 0x82, 0x28, 0x46, 0x47, 0xe2,
+ 0xae, 0xc7, 0x17, 0xf1, 0x85, 0x83, 0x90, 0x2c, 0x5f, 0x1d, 0xcb, 0x75,
+ 0x8a, 0x19, 0xe8, 0xfc, 0xba, 0xfb, 0x3c, 0xfc, 0x58, 0xac, 0x3c, 0x4e,
+ 0x11, 0x5e, 0x8e, 0xc1, 0xac, 0x5d, 0xe7, 0x58, 0xa9, 0x36, 0xee, 0x41,
+ 0x7a, 0x12, 0x75, 0x8b, 0x98, 0x35, 0x8a, 0xf9, 0xb5, 0xe0, 0xed, 0xff,
+ 0xbd, 0xf7, 0xcc, 0x19, 0x60, 0x4b, 0x15, 0x87, 0xbe, 0xe4, 0x37, 0xda,
+ 0x7e, 0xa0, 0xb1, 0x7f, 0xee, 0x4c, 0x59, 0xf7, 0xd7, 0xd9, 0x62, 0xfe,
+ 0xd6, 0x7f, 0xa8, 0x71, 0x62, 0xec, 0xfa, 0xc5, 0xdc, 0xc5, 0x8a, 0x1a,
+ 0x30, 0x5c, 0x93, 0x47, 0xe7, 0x30, 0x61, 0x7b, 0xda, 0x73, 0x56, 0x2f,
+ 0xfc, 0x7c, 0x7f, 0x37, 0xbf, 0x3e, 0x58, 0xb9, 0xfe, 0xb1, 0x6c, 0x58,
+ 0xbf, 0xfe, 0x16, 0x3f, 0xf3, 0x7f, 0xb9, 0x81, 0x1f, 0x75, 0x8b, 0xde,
+ 0xc0, 0x96, 0x2d, 0xb1, 0x1f, 0x97, 0x95, 0x28, 0xe8, 0xab, 0x14, 0x20,
+ 0xef, 0x6c, 0x2f, 0x2c, 0x5f, 0x7d, 0xd8, 0x0b, 0x15, 0x87, 0x83, 0xe1,
+ 0xfb, 0x4a, 0xc5, 0xbe, 0xb1, 0x6c, 0xd8, 0xd1, 0x9a, 0x23, 0x60, 0x96,
+ 0x2f, 0xa2, 0xcd, 0x61, 0x86, 0xef, 0x85, 0x16, 0xe2, 0xc5, 0xd3, 0xf5,
+ 0x8a, 0xe8, 0xd4, 0xc4, 0x25, 0x43, 0x54, 0x5f, 0x90, 0xc2, 0x03, 0x4f,
+ 0x9f, 0xc4, 0xc5, 0x7f, 0xf8, 0x44, 0x66, 0x6b, 0x63, 0xe7, 0x3f, 0x8b,
+ 0x17, 0xdd, 0xf9, 0x37, 0x96, 0x2b, 0x63, 0xf3, 0x12, 0x65, 0xff, 0x18,
+ 0x77, 0x2c, 0xf7, 0xdd, 0x62, 0xfd, 0xb3, 0x17, 0xb8, 0xb1, 0x77, 0x25,
+ 0x62, 0xfc, 0xdb, 0x19, 0x0f, 0x2c, 0x56, 0xc7, 0x85, 0xf1, 0x7b, 0xf1,
+ 0x02, 0x5f, 0xb2, 0xc5, 0xfa, 0x20, 0xf9, 0x38, 0xb1, 0x4e, 0x7a, 0x6c,
+ 0x53, 0x7e, 0x6d, 0x17, 0x4e, 0xb1, 0x7c, 0x60, 0x46, 0x04, 0xb1, 0x74,
+ 0xf9, 0x62, 0xa4, 0xdf, 0xc4, 0x51, 0x52, 0x9f, 0x2c, 0x08, 0xf0, 0xe5,
+ 0xda, 0xfe, 0xed, 0xe2, 0x01, 0x33, 0xda, 0x0b, 0x17, 0x38, 0xd6, 0x2a,
+ 0x34, 0x35, 0x32, 0x25, 0x7b, 0xec, 0x4b, 0x15, 0xde, 0xb3, 0x53, 0x76,
+ 0x7a, 0x84, 0x23, 0xc7, 0x1b, 0x16, 0x1d, 0x9b, 0x0b, 0x8d, 0xc9, 0x1e,
+ 0x18, 0x91, 0x43, 0x53, 0x4b, 0x07, 0x85, 0x9f, 0xe1, 0xc2, 0xc9, 0x00,
+ 0x1e, 0x29, 0x4d, 0xbe, 0x95, 0x51, 0xda, 0x11, 0x61, 0x12, 0xde, 0x14,
+ 0xec, 0xb1, 0x7e, 0xe6, 0xb4, 0xe7, 0x58, 0xae, 0x1e, 0x3f, 0x87, 0xae,
+ 0x7e, 0x96, 0x2d, 0xde, 0xac, 0x5d, 0xf8, 0xf5, 0x8b, 0xf8, 0xce, 0x3f,
+ 0xdc, 0xeb, 0x17, 0xbd, 0x27, 0x58, 0xa8, 0xd8, 0xff, 0xa0, 0x2f, 0xd0,
+ 0xd9, 0x17, 0xdf, 0xff, 0xd8, 0xe0, 0x92, 0xce, 0xbc, 0xdd, 0x40, 0x3e,
+ 0x01, 0x62, 0xdb, 0x2c, 0x51, 0x87, 0xe1, 0x05, 0xdb, 0xba, 0x35, 0x62,
+ 0xfe, 0x3b, 0x43, 0x58, 0x12, 0xc5, 0xba, 0x19, 0xe4, 0xe0, 0xd5, 0xfe,
+ 0xf7, 0x0c, 0xcf, 0xe1, 0x2c, 0x56, 0x1e, 0xe3, 0x14, 0x5e, 0xe7, 0xb1,
+ 0x62, 0xff, 0xf4, 0x0b, 0x0e, 0x76, 0xe1, 0x9c, 0x91, 0xac, 0x5f, 0x7b,
+ 0x1b, 0x75, 0x8a, 0xef, 0x51, 0x17, 0x23, 0xb8, 0x97, 0x7f, 0xbe, 0xe7,
+ 0xfe, 0x01, 0x96, 0x2f, 0xfd, 0x85, 0x9a, 0xdf, 0xf8, 0x0e, 0x2c, 0x5e,
+ 0x8a, 0x46, 0xb1, 0x7d, 0xbe, 0x10, 0x16, 0x2f, 0xfd, 0xf9, 0x29, 0xdf,
+ 0x53, 0x84, 0xb1, 0x43, 0x47, 0x83, 0x99, 0xe8, 0xfd, 0x87, 0xbc, 0x47,
+ 0x78, 0xf3, 0x05, 0x8b, 0xfb, 0x36, 0x93, 0x5b, 0x8b, 0x17, 0xff, 0xdf,
+ 0x7d, 0x7d, 0x8c, 0xce, 0xa1, 0x9a, 0xd9, 0x62, 0xfe, 0xfb, 0x8d, 0xf5,
+ 0xba, 0xc5, 0xf6, 0x6f, 0x9d, 0x2c, 0x5f, 0xff, 0xb3, 0xdc, 0xfb, 0x1f,
+ 0x59, 0xd4, 0x38, 0x28, 0x96, 0x2f, 0xff, 0xcd, 0xd0, 0xf4, 0x4c, 0x11,
+ 0x60, 0x01, 0x80, 0x58, 0xbb, 0xae, 0x18, 0x9f, 0x4c, 0xa4, 0x0c, 0x77,
+ 0x0b, 0xf7, 0x53, 0xf9, 0x79, 0x12, 0x79, 0x66, 0xf4, 0x52, 0x12, 0xc5,
+ 0xfb, 0xc5, 0x99, 0xa5, 0x8b, 0xfd, 0xf9, 0x72, 0x6d, 0x1a, 0xb1, 0x7f,
+ 0x4b, 0x93, 0x68, 0xd5, 0x8b, 0xed, 0x69, 0xf4, 0x61, 0xf0, 0x7c, 0xce,
+ 0xfe, 0x2c, 0x8b, 0x4d, 0xd9, 0x62, 0xfd, 0x91, 0x69, 0xbb, 0x2c, 0x52,
+ 0xc5, 0xb7, 0x30, 0xf9, 0xc8, 0xc3, 0xb1, 0x5d, 0x01, 0x1b, 0x25, 0x0a,
+ 0x1a, 0x94, 0xe9, 0x9c, 0x7d, 0xa3, 0x60, 0xbf, 0xf7, 0x5e, 0x6e, 0xb8,
+ 0x39, 0xce, 0x96, 0x2f, 0x16, 0x1d, 0x62, 0xdd, 0x2c, 0x5a, 0x10, 0x35,
+ 0xfc, 0x1c, 0xa9, 0x44, 0xc3, 0x38, 0xdf, 0xff, 0xfe, 0x30, 0xf3, 0x9e,
+ 0x33, 0x20, 0xfd, 0x8b, 0x38, 0x64, 0x8d, 0xa2, 0xe2, 0xc5, 0xe0, 0xb8,
+ 0x05, 0x8b, 0xfb, 0x0e, 0x36, 0x6d, 0xd6, 0x2e, 0x2d, 0xcc, 0x3c, 0xdf,
+ 0x8f, 0xd4, 0x11, 0xf0, 0xd0, 0xc9, 0xbf, 0xe3, 0x39, 0x9f, 0xc1, 0x16,
+ 0xeb, 0x16, 0xc5, 0x8a, 0xc6, 0x53, 0x26, 0xe4, 0x4f, 0x09, 0x68, 0xa1,
+ 0x63, 0xa8, 0x64, 0x1e, 0x15, 0x6d, 0x2c, 0x30, 0x12, 0x89, 0x0a, 0x19,
+ 0x82, 0x8c, 0x64, 0x22, 0x78, 0xe3, 0xbb, 0xdc, 0xf3, 0xac, 0x5e, 0x88,
+ 0x1d, 0x2c, 0x5f, 0xf6, 0x43, 0xf2, 0xfa, 0xd4, 0xac, 0x5c, 0x69, 0x9b,
+ 0x9f, 0xa8, 0x07, 0x78, 0x41, 0x7b, 0x9d, 0xff, 0x16, 0x2a, 0x4f, 0x87,
+ 0xa3, 0xeb, 0xe0, 0x00, 0x51, 0xeb, 0x16, 0x02, 0xc5, 0xef, 0x72, 0x56,
+ 0x2f, 0x85, 0xd4, 0x38, 0xb1, 0x63, 0x24, 0xf0, 0xb4, 0x3b, 0x7e, 0xd6,
+ 0xd3, 0xad, 0x96, 0x2f, 0xce, 0x5e, 0x0c, 0xeb, 0x15, 0x27, 0xa8, 0x02,
+ 0xbb, 0xd0, 0xe6, 0x2c, 0x5f, 0xbb, 0xd2, 0x9c, 0x02, 0xc5, 0x68, 0xf2,
+ 0x40, 0x3b, 0x79, 0x9c, 0x96, 0x2f, 0xc2, 0x88, 0xa4, 0xeb, 0x17, 0x9f,
+ 0x02, 0x30, 0xf1, 0x38, 0x37, 0x7f, 0xf9, 0xcf, 0x9c, 0x30, 0xb3, 0x40,
+ 0xc8, 0x96, 0x2f, 0xf7, 0x50, 0x11, 0x6d, 0xb4, 0xac, 0x5f, 0x66, 0x6b,
+ 0x8b, 0x16, 0xe1, 0x87, 0xb2, 0x03, 0x7b, 0xc2, 0x6e, 0x2c, 0x56, 0xca,
+ 0x9a, 0xa0, 0xf9, 0x8d, 0x47, 0x66, 0xf9, 0xa7, 0xa1, 0x48, 0x19, 0x4d,
+ 0xfe, 0x08, 0xf2, 0xfa, 0x14, 0x7a, 0xc5, 0xc4, 0x25, 0x8a, 0x58, 0xb6,
+ 0x8c, 0x34, 0x7c, 0x17, 0xbf, 0x19, 0xd4, 0x05, 0xb2, 0xc5, 0xff, 0x6f,
+ 0x8f, 0xf9, 0xd6, 0x1d, 0x62, 0xa5, 0x11, 0xd0, 0x28, 0x22, 0xda, 0xc4,
+ 0xc5, 0xc5, 0x0e, 0x9b, 0xff, 0xf9, 0xf4, 0x66, 0x3e, 0x11, 0xbf, 0x7c,
+ 0x3e, 0x6e, 0xb1, 0x7f, 0xd9, 0xd4, 0x39, 0xd4, 0x05, 0xa5, 0x8b, 0xff,
+ 0xff, 0x1f, 0x9b, 0xfe, 0x77, 0xea, 0x04, 0x21, 0x98, 0xe6, 0xb1, 0x01,
+ 0x62, 0xff, 0xff, 0x6d, 0xa9, 0x3f, 0x05, 0x26, 0x4e, 0xa4, 0x7f, 0x93,
+ 0xac, 0x56, 0x23, 0x55, 0xdc, 0xaf, 0xfa, 0x06, 0x49, 0x9e, 0xfe, 0x12,
+ 0xc5, 0x62, 0x79, 0x2e, 0xb7, 0xa8, 0xc4, 0x98, 0x86, 0xfc, 0x0e, 0x3f,
+ 0x41, 0x2c, 0x5f, 0xe1, 0x17, 0x50, 0xe1, 0x0d, 0x62, 0xff, 0xf6, 0x4f,
+ 0x50, 0xe1, 0x67, 0xcb, 0x02, 0x58, 0xbf, 0x75, 0x27, 0xda, 0x56, 0x2f,
+ 0xba, 0x83, 0xfd, 0x62, 0xec, 0xeb, 0xe7, 0x9d, 0xe2, 0xab, 0xf4, 0x50,
+ 0x92, 0x82, 0xc5, 0xfe, 0xe8, 0xce, 0xef, 0x61, 0x6c, 0xb1, 0x58, 0x9a,
+ 0xf1, 0xa6, 0xba, 0x84, 0xc0, 0x0b, 0x84, 0x53, 0x7f, 0x74, 0xd0, 0x29,
+ 0x3a, 0xc5, 0xff, 0xd1, 0xe7, 0x21, 0x05, 0xac, 0x72, 0x02, 0xc5, 0xff,
+ 0xff, 0x14, 0x5f, 0xce, 0xa1, 0x24, 0x33, 0x0b, 0x3b, 0x69, 0xf8, 0xb1,
+ 0x7f, 0xc5, 0x17, 0x8b, 0x36, 0x62, 0x58, 0xa9, 0x47, 0x5b, 0xa4, 0x09,
+ 0xaa, 0xfd, 0xb9, 0x87, 0x6f, 0x2c, 0x5f, 0xff, 0xfd, 0xa7, 0xd8, 0xcf,
+ 0xe7, 0x8a, 0x62, 0xfe, 0x6d, 0x3d, 0x78, 0x5b, 0xac, 0x56, 0x22, 0x8f,
+ 0x45, 0x77, 0xff, 0xff, 0x49, 0xbf, 0x93, 0x0b, 0x04, 0x69, 0x9d, 0x43,
+ 0x8e, 0x41, 0xce, 0xcb, 0x17, 0xe2, 0x07, 0x08, 0x4b, 0x17, 0xec, 0x14,
+ 0xeb, 0x65, 0x8b, 0xcf, 0x84, 0xb1, 0x6e, 0x88, 0xf1, 0x38, 0x53, 0x58,
+ 0x98, 0x63, 0xbc, 0x09, 0xb2, 0xff, 0xfb, 0x3b, 0x8b, 0x0e, 0xc5, 0xee,
+ 0x19, 0x21, 0x2c, 0x54, 0xab, 0x9a, 0xc8, 0xc6, 0x5e, 0x1a, 0x3f, 0x8c,
+ 0xb8, 0x45, 0xf7, 0xfe, 0xf1, 0xce, 0xd1, 0x18, 0x58, 0x12, 0xc5, 0xff,
+ 0xe0, 0x70, 0x62, 0x6d, 0x43, 0xef, 0x87, 0x58, 0xbf, 0xf1, 0x75, 0x9c,
+ 0x14, 0x45, 0x27, 0x58, 0xac, 0x44, 0x5e, 0x92, 0xef, 0xf1, 0xbf, 0x97,
+ 0xda, 0x4d, 0x58, 0xbf, 0xcf, 0xd7, 0xd8, 0xef, 0xc5, 0x8a, 0x73, 0xea,
+ 0x23, 0x6a, 0x74, 0x56, 0x72, 0x11, 0x94, 0x62, 0x74, 0x10, 0x8d, 0xe6,
+ 0xff, 0xdc, 0xce, 0xa0, 0xfa, 0x2e, 0xb1, 0x62, 0xff, 0xd1, 0x7b, 0x05,
+ 0xa3, 0x18, 0x62, 0x58, 0xbf, 0x1c, 0xb3, 0xa8, 0xf5, 0x8b, 0x1f, 0x0f,
+ 0xbb, 0x88, 0x57, 0xf8, 0x51, 0x16, 0x7d, 0xbc, 0xb1, 0x5b, 0x26, 0x13,
+ 0x90, 0xae, 0x22, 0x7b, 0xff, 0x08, 0x1c, 0x2c, 0xe7, 0x24, 0x25, 0x8b,
+ 0xf8, 0xb6, 0x8e, 0xf8, 0x7a, 0x58, 0xa8, 0x1f, 0xa3, 0x20, 0x5f, 0x04,
+ 0x66, 0xce, 0xb1, 0x7e, 0x08, 0x7f, 0x63, 0xac, 0x5f, 0xee, 0xa1, 0xc3,
+ 0x39, 0xe7, 0x58, 0xa9, 0x3e, 0x17, 0x2a, 0xac, 0x45, 0x3f, 0xe1, 0x0f,
+ 0x7f, 0xec, 0x0b, 0xc3, 0x7c, 0xea, 0x1c, 0x58, 0xbf, 0xdf, 0x97, 0x26,
+ 0xd1, 0xab, 0x17, 0xff, 0x8e, 0x66, 0x0b, 0xbf, 0x7f, 0xb9, 0xd8, 0x6b,
+ 0x15, 0x12, 0x20, 0xc4, 0x67, 0x7f, 0x45, 0xf2, 0x60, 0x71, 0x62, 0xb0,
+ 0xf4, 0xc4, 0x49, 0x7f, 0xc7, 0xce, 0x19, 0x11, 0x49, 0xd6, 0x2f, 0xfc,
+ 0xc3, 0x30, 0x65, 0x22, 0x1e, 0x2c, 0x5f, 0xff, 0xb9, 0xb3, 0x18, 0x3f,
+ 0xce, 0xb5, 0x9d, 0xa7, 0xa5, 0x8b, 0xff, 0x49, 0x40, 0xc0, 0xfb, 0xa4,
+ 0xa0, 0xb1, 0x43, 0x54, 0xee, 0xe4, 0xfa, 0x8c, 0x5c, 0xe4, 0x20, 0x3b,
+ 0xf1, 0xf8, 0x4b, 0x77, 0xff, 0xd9, 0xb1, 0x83, 0xd3, 0xed, 0xe7, 0xc2,
+ 0xd9, 0x62, 0xff, 0xde, 0xe1, 0x9f, 0x70, 0x98, 0x8d, 0x58, 0xbf, 0xf8,
+ 0x8d, 0x06, 0xb2, 0x7a, 0x83, 0x9d, 0x62, 0xb1, 0x11, 0x0c, 0x85, 0x7f,
+ 0xec, 0x92, 0xf7, 0xba, 0x83, 0xe9, 0x62, 0xa5, 0x33, 0xb3, 0xc3, 0x6c,
+ 0x44, 0x37, 0xf7, 0x81, 0x9d, 0xd8, 0x4b, 0x17, 0xfc, 0x29, 0x23, 0x1f,
+ 0xd3, 0x12, 0xc5, 0xda, 0x01, 0x87, 0xd4, 0x73, 0x0b, 0xee, 0xd8, 0x2d,
+ 0xd6, 0x2f, 0xf6, 0x75, 0x1c, 0xfa, 0xc3, 0x56, 0x2f, 0xff, 0xf9, 0xb5,
+ 0xfc, 0xf3, 0xe1, 0x6d, 0xc9, 0xc2, 0x1f, 0xe5, 0x62, 0xda, 0x58, 0xbf,
+ 0xb3, 0xbb, 0xce, 0x5b, 0x2c, 0x5d, 0xe3, 0x36, 0x3c, 0x32, 0x12, 0xbf,
+ 0xff, 0xe0, 0x64, 0x46, 0x7d, 0x9f, 0xd2, 0x52, 0x0c, 0x92, 0x02, 0xc5,
+ 0xff, 0xf6, 0x6b, 0xa8, 0x37, 0x5a, 0xc7, 0xfc, 0x8d, 0x62, 0xff, 0x48,
+ 0x24, 0xef, 0xa8, 0x96, 0x29, 0xd1, 0x0a, 0x4a, 0x37, 0xff, 0xef, 0xe0,
+ 0x8e, 0x67, 0x25, 0xfa, 0xf7, 0xa4, 0xeb, 0x15, 0x2a, 0xb1, 0xb0, 0xbc,
+ 0xd2, 0x6e, 0x8e, 0x1a, 0x14, 0xe0, 0x2f, 0xf4, 0x3a, 0xbb, 0x88, 0x6f,
+ 0xff, 0xfd, 0xd6, 0x6c, 0x2e, 0xe3, 0x3a, 0x87, 0xa4, 0x23, 0x33, 0x40,
+ 0x04, 0xac, 0x5f, 0xf6, 0x45, 0x1c, 0x2f, 0x67, 0x5e, 0x58, 0xbd, 0x9a,
+ 0x1a, 0xc5, 0xd3, 0x05, 0x8b, 0xff, 0xee, 0x19, 0xa9, 0xdf, 0x0a, 0x28,
+ 0x67, 0xb8, 0xb1, 0x58, 0x8c, 0x63, 0x9f, 0x80, 0x74, 0x42, 0xf7, 0xfe,
+ 0x62, 0xcf, 0xe7, 0xb5, 0x81, 0x2c, 0x5f, 0xff, 0xee, 0x60, 0xb4, 0x69,
+ 0x9f, 0x7c, 0xf7, 0x0c, 0x2c, 0x1a, 0xc5, 0x6c, 0x8a, 0x2f, 0x1f, 0x5f,
+ 0x8d, 0x33, 0xb4, 0x3b, 0xd5, 0x8b, 0xff, 0xff, 0xe1, 0x1a, 0x42, 0xf4,
+ 0x59, 0xe7, 0xea, 0x05, 0x25, 0x9f, 0x7c, 0xd4, 0x4b, 0x15, 0x28, 0xb2,
+ 0xc3, 0x3a, 0xc4, 0x7b, 0xf5, 0x0d, 0x6b, 0xe0, 0x98, 0x80, 0xb1, 0x7f,
+ 0xd8, 0x17, 0xe4, 0xdc, 0xf7, 0x16, 0x2f, 0xf1, 0x6f, 0x3b, 0x94, 0x9d,
+ 0x62, 0xff, 0xf0, 0xff, 0x3a, 0xcf, 0x7b, 0x36, 0x9d, 0x96, 0x2d, 0x8e,
+ 0x88, 0x03, 0x9a, 0x5f, 0xfc, 0xc5, 0xb1, 0xc4, 0xe3, 0x72, 0x75, 0x8a,
+ 0xc4, 0xd2, 0x1c, 0x8f, 0x90, 0xbb, 0x08, 0x9e, 0xfb, 0xaf, 0x7d, 0xd6,
+ 0x2f, 0xdd, 0x40, 0x53, 0xe5, 0x8a, 0xc3, 0xce, 0x88, 0x92, 0xff, 0xb6,
+ 0xfc, 0x99, 0xcf, 0x8c, 0x6b, 0x17, 0xfb, 0xaf, 0xe7, 0xb5, 0x81, 0x2c,
+ 0x53, 0x9f, 0x98, 0x8f, 0x6f, 0xff, 0xe8, 0x4e, 0xba, 0x87, 0x0c, 0xfc,
+ 0xb9, 0x36, 0x8d, 0x58, 0xbf, 0xff, 0x64, 0x1f, 0xb1, 0x67, 0x0c, 0xcf,
+ 0xb7, 0x40, 0x58, 0xbc, 0x59, 0x05, 0x8b, 0x40, 0xc3, 0xf4, 0xf2, 0xc5,
+ 0xff, 0xba, 0x1f, 0xc4, 0xdc, 0x2c, 0x1a, 0xc5, 0x61, 0xf4, 0x88, 0xa6,
+ 0xff, 0xed, 0x98, 0x8c, 0xd6, 0x9c, 0xdc, 0x25, 0x8b, 0xfe, 0x6f, 0x7b,
+ 0x22, 0x83, 0xf9, 0x62, 0xfe, 0xc3, 0x4d, 0x6f, 0x71, 0x62, 0xfe, 0xce,
+ 0xa1, 0xc1, 0x44, 0xb1, 0x7d, 0x9f, 0x6f, 0x2c, 0x5c, 0xc7, 0x31, 0x10,
+ 0x7a, 0x30, 0x23, 0x1a, 0x94, 0x7c, 0x7e, 0x17, 0xb7, 0x00, 0x25, 0x8b,
+ 0xe8, 0xec, 0xd4, 0xac, 0x56, 0x8d, 0xf7, 0x61, 0x9b, 0xff, 0xe3, 0xf3,
+ 0xf2, 0x5e, 0xd4, 0xff, 0x77, 0xe2, 0xc5, 0xe7, 0x93, 0xac, 0x59, 0xd6,
+ 0x2b, 0x46, 0xb7, 0xc3, 0x97, 0x85, 0x20, 0x58, 0xb1, 0x18, 0x6f, 0xb4,
+ 0x43, 0x58, 0x98, 0x33, 0x91, 0xb4, 0x2f, 0x2e, 0xc2, 0x58, 0xa9, 0x5d,
+ 0x04, 0xc8, 0x4a, 0xf4, 0x43, 0xf8, 0xce, 0xd8, 0x87, 0x91, 0x9f, 0x7a,
+ 0x36, 0xb1, 0x19, 0xdf, 0xfb, 0xa8, 0x70, 0xce, 0x4c, 0x42, 0xd2, 0xc5,
+ 0xff, 0xbd, 0xc3, 0x35, 0x8f, 0xf9, 0x1a, 0xc5, 0x4a, 0x21, 0x31, 0x12,
+ 0xff, 0xbf, 0xf9, 0xe8, 0xc0, 0x8f, 0xba, 0xc5, 0xed, 0xda, 0x3d, 0x62,
+ 0xfe, 0xcf, 0x6b, 0x59, 0x05, 0x8a, 0x58, 0xbf, 0x67, 0xcb, 0x37, 0x58,
+ 0xa0, 0x1b, 0x42, 0x0c, 0xa7, 0x45, 0x1c, 0x44, 0x3e, 0x62, 0xbd, 0x9d,
+ 0x79, 0x62, 0xff, 0x60, 0xdf, 0xb7, 0x9f, 0x4b, 0x17, 0x67, 0x0c, 0x44,
+ 0x1c, 0x79, 0x83, 0x0f, 0x53, 0x27, 0x46, 0x51, 0xb2, 0xdf, 0xc7, 0x31,
+ 0xf6, 0x6f, 0x2c, 0x5e, 0xc7, 0x09, 0x62, 0xfd, 0x2f, 0xa1, 0x47, 0xac,
+ 0x58, 0xe3, 0x3c, 0x8f, 0x8e, 0xd4, 0xa2, 0x83, 0x1e, 0x2f, 0xdb, 0x94,
+ 0xfb, 0x8b, 0x17, 0xfe, 0xc9, 0x0b, 0xf9, 0xe7, 0xce, 0x2c, 0x5f, 0x9f,
+ 0x62, 0x63, 0xac, 0x54, 0xa2, 0x3f, 0x45, 0x3e, 0x3e, 0xad, 0x9d, 0x16,
+ 0xa0, 0xe3, 0xf1, 0xc4, 0x13, 0x63, 0x89, 0xde, 0x5f, 0x57, 0x51, 0xfd,
+ 0x3c, 0x66, 0x91, 0x42, 0xa7, 0x52, 0xcf, 0xcf, 0x1d, 0x3f, 0xe5, 0xb2,
+ 0xb3, 0xf8, 0x23, 0x3d, 0x28, 0xf5, 0x79, 0x1b, 0x87, 0xa7, 0x65, 0x05,
+ 0x18, 0x6f, 0x68, 0xf1, 0x03, 0x86, 0x47, 0x74, 0x2c, 0x2f, 0x85, 0x24,
+ 0x35, 0x8b, 0xfa, 0x3c, 0xc6, 0x8b, 0x19, 0x62, 0xff, 0xa4, 0xe5, 0x83,
+ 0xd3, 0xec, 0xb1, 0x7f, 0xff, 0x82, 0xf8, 0xa7, 0xa3, 0x35, 0xa9, 0xd8,
+ 0x99, 0xb4, 0x6a, 0xc5, 0xfe, 0x2c, 0x16, 0x1b, 0x00, 0x2c, 0x53, 0x22,
+ 0x68, 0x26, 0x6a, 0x94, 0xca, 0x20, 0x65, 0x90, 0xd3, 0xbf, 0xfe, 0x9d,
+ 0x8c, 0xfc, 0xbf, 0xb9, 0x3b, 0x67, 0x16, 0x2f, 0xfe, 0x9d, 0x79, 0xf3,
+ 0xb8, 0xe2, 0x92, 0x58, 0xbc, 0x6c, 0xe9, 0x62, 0xff, 0xfa, 0x4c, 0xfb,
+ 0x76, 0x33, 0x0e, 0x79, 0xd1, 0xab, 0x17, 0xe0, 0x1f, 0x33, 0xcb, 0x17,
+ 0xf8, 0xcd, 0x67, 0xcb, 0x22, 0x58, 0xbf, 0xc7, 0x33, 0xc5, 0x27, 0xe2,
+ 0xc5, 0x61, 0xf5, 0x39, 0xad, 0x62, 0x2c, 0x8a, 0x12, 0x57, 0xff, 0xfb,
+ 0xec, 0x0e, 0x18, 0x59, 0xd8, 0xb3, 0x98, 0x79, 0xdd, 0x62, 0xff, 0xff,
+ 0xfb, 0x42, 0x3b, 0xf0, 0xc8, 0xa0, 0x22, 0xf1, 0x9f, 0x98, 0x39, 0x61,
+ 0xe5, 0x62, 0xff, 0xb3, 0x99, 0xa7, 0xd9, 0x8e, 0xb1, 0x6e, 0x2c, 0x5f,
+ 0xbc, 0x66, 0xfe, 0x3a, 0xc5, 0x4a, 0x3d, 0xe1, 0x08, 0x06, 0x39, 0x10,
+ 0x95, 0x6c, 0xac, 0xae, 0x24, 0x6f, 0x8f, 0x14, 0x60, 0xfc, 0x26, 0xf4,
+ 0x6b, 0x57, 0xd8, 0x6c, 0xc1, 0x62, 0xf4, 0x96, 0xeb, 0x17, 0x08, 0xe6,
+ 0x1e, 0x01, 0xa4, 0x77, 0x1a, 0xeb, 0x17, 0xff, 0xf8, 0xb0, 0x73, 0xee,
+ 0x19, 0xee, 0xe2, 0x9e, 0x0a, 0x7a, 0x58, 0xbb, 0x0d, 0x58, 0xb7, 0x0c,
+ 0x3f, 0xd9, 0x65, 0xbf, 0xf9, 0xff, 0x9b, 0xfd, 0xc5, 0x25, 0xb2, 0xc5,
+ 0xff, 0x60, 0x86, 0x64, 0xf2, 0x60, 0xb1, 0x7c, 0x5e, 0x7f, 0xac, 0x51,
+ 0x87, 0xb8, 0xc7, 0x57, 0xf7, 0xcc, 0xe7, 0xe7, 0xa5, 0x8b, 0xff, 0xfe,
+ 0x93, 0x45, 0xf9, 0x3f, 0x22, 0x2c, 0x08, 0xb0, 0x58, 0x6a, 0xc5, 0xfd,
+ 0x9b, 0xc9, 0x99, 0x05, 0x8a, 0x94, 0x64, 0xc4, 0x63, 0xf6, 0x9a, 0xc4,
+ 0xef, 0x01, 0x0a, 0x1f, 0x43, 0xae, 0xa3, 0x77, 0x62, 0x85, 0x1a, 0x89,
+ 0xe6, 0x55, 0xf6, 0x5a, 0x45, 0x7d, 0xe3, 0x82, 0xea, 0x34, 0xa7, 0x34,
+ 0x69, 0x6f, 0xa5, 0x0a, 0x6e, 0x18, 0x7a, 0x12, 0xa2, 0x8f, 0x92, 0xf6,
+ 0xd3, 0x12, 0xc5, 0xe6, 0x20, 0x2c, 0x5f, 0xbe, 0x19, 0x74, 0x05, 0x8b,
+ 0xfe, 0x33, 0xbb, 0xd9, 0xff, 0x39, 0xd6, 0x2f, 0xfe, 0xd9, 0xbd, 0xac,
+ 0xd9, 0x8b, 0xdc, 0x58, 0xad, 0x91, 0x97, 0x83, 0x9b, 0x95, 0xb9, 0xf5,
+ 0xfe, 0xd6, 0x7f, 0xac, 0x14, 0x4b, 0x17, 0xff, 0xf4, 0x3f, 0x8f, 0x0e,
+ 0x61, 0x0b, 0xc5, 0x80, 0x95, 0x8b, 0x3a, 0xc5, 0xb5, 0x87, 0xd4, 0x05,
+ 0x9b, 0xff, 0xec, 0xf7, 0xf0, 0x62, 0xf7, 0x27, 0x82, 0xe2, 0xc5, 0xfd,
+ 0x38, 0x5b, 0x86, 0x75, 0x8b, 0xfd, 0xe1, 0x4e, 0x6c, 0x19, 0xd6, 0x2f,
+ 0xfd, 0xf9, 0x21, 0x45, 0x9c, 0xe4, 0xac, 0x5a, 0x3f, 0xe8, 0xf5, 0xf2,
+ 0x88, 0x65, 0xfd, 0xc6, 0xd7, 0xfd, 0xcf, 0x7e, 0x7d, 0xcf, 0xba, 0xc5,
+ 0x18, 0xa9, 0x02, 0x61, 0x40, 0xd1, 0x8e, 0x09, 0x2a, 0xe3, 0x8d, 0x62,
+ 0xff, 0xd8, 0x46, 0x4f, 0xdf, 0x59, 0x05, 0x8b, 0xff, 0xe2, 0x34, 0xce,
+ 0x0f, 0x44, 0xc1, 0x66, 0x79, 0x62, 0xf7, 0x80, 0x25, 0x8b, 0x63, 0x9f,
+ 0x81, 0x29, 0x5f, 0xfe, 0x3c, 0xef, 0xee, 0x60, 0x27, 0x3a, 0x82, 0xc5,
+ 0xf1, 0xaf, 0xbb, 0xac, 0x5d, 0x30, 0xc3, 0xf0, 0xf2, 0x65, 0xff, 0xe6,
+ 0xd4, 0x37, 0xfb, 0x8f, 0x4e, 0x2d, 0x96, 0x2b, 0xbe, 0xa9, 0xea, 0x48,
+ 0xc7, 0xe1, 0x5c, 0x50, 0x95, 0x11, 0x65, 0xec, 0x68, 0x96, 0x2f, 0xfc,
+ 0x50, 0x73, 0xfb, 0xf2, 0xfb, 0xac, 0x56, 0xc7, 0xb8, 0xc3, 0xb7, 0xff,
+ 0xfe, 0x7e, 0xc5, 0x9c, 0x33, 0xce, 0x66, 0x7a, 0x77, 0x7e, 0xd3, 0xf5,
+ 0x8b, 0xff, 0xff, 0xbf, 0x85, 0xb1, 0x9b, 0xfc, 0x5f, 0x9d, 0x03, 0xf9,
+ 0xe2, 0x9d, 0xd6, 0x2f, 0xe9, 0x07, 0xa3, 0xb3, 0xeb, 0x17, 0xf8, 0x72,
+ 0x03, 0x33, 0xaf, 0x2c, 0x5f, 0xff, 0x36, 0x9b, 0xfd, 0x43, 0x3c, 0x66,
+ 0xfc, 0x8f, 0x58, 0xbf, 0xff, 0x79, 0x98, 0xfc, 0x33, 0x07, 0xf1, 0x73,
+ 0x37, 0x58, 0xbf, 0xf3, 0x34, 0x0c, 0x2c, 0x09, 0x80, 0xb1, 0x7f, 0xee,
+ 0x7f, 0x18, 0x8c, 0xfc, 0xc7, 0xac, 0x5f, 0xe6, 0xf7, 0x22, 0x83, 0xfd,
+ 0x62, 0xfe, 0x78, 0x37, 0xbe, 0xeb, 0x17, 0xff, 0xcc, 0x71, 0xfe, 0x74,
+ 0x58, 0x3f, 0xb0, 0x4b, 0x14, 0x35, 0x43, 0x1b, 0x9b, 0x74, 0xaf, 0xf5,
+ 0x80, 0x1f, 0x92, 0x17, 0x8d, 0x7b, 0x16, 0xdf, 0x67, 0x50, 0xe2, 0xc5,
+ 0xfa, 0x3c, 0x65, 0x9f, 0x58, 0xaf, 0x9e, 0x7b, 0x12, 0x5f, 0x1b, 0xf7,
+ 0x3a, 0xc5, 0xfa, 0x27, 0x21, 0x4a, 0xc5, 0xe9, 0xdc, 0xc8, 0xd0, 0xf3,
+ 0x18, 0x92, 0xf8, 0x8e, 0xfe, 0x58, 0xb8, 0xfc, 0x58, 0xbc, 0xdc, 0x75,
+ 0x8b, 0xfb, 0xdf, 0xce, 0xc3, 0x95, 0x8a, 0x93, 0xe4, 0x00, 0xc0, 0x87,
+ 0x2f, 0xf8, 0x3d, 0xb0, 0x98, 0xed, 0xf5, 0x8b, 0xe7, 0xd1, 0x32, 0xc5,
+ 0x6c, 0xbb, 0x99, 0x02, 0x21, 0xb8, 0xee, 0xec, 0xf2, 0x92, 0x62, 0x86,
+ 0x29, 0xdb, 0x58, 0xe4, 0xa1, 0x0d, 0xe2, 0xee, 0xc7, 0x57, 0x8d, 0x60,
+ 0x96, 0x2f, 0xfd, 0xf7, 0xeb, 0xda, 0x9f, 0x3f, 0x65, 0x8b, 0xfd, 0xce,
+ 0x4b, 0xec, 0xde, 0x58, 0xbf, 0xee, 0x30, 0x5d, 0xcf, 0x84, 0x35, 0x8b,
+ 0xfb, 0x3d, 0x8c, 0x51, 0x2c, 0x5f, 0x67, 0x27, 0x4b, 0x16, 0x37, 0xe7,
+ 0x9e, 0x45, 0xb6, 0x84, 0xa3, 0x9f, 0x0d, 0x05, 0x08, 0xbb, 0x41, 0x62,
+ 0xf0, 0xc4, 0x05, 0x8b, 0xff, 0xfa, 0x63, 0xcc, 0x7c, 0x2c, 0xfb, 0xe1,
+ 0x75, 0x0e, 0x2c, 0x5f, 0xee, 0xe7, 0xce, 0xbe, 0xf8, 0xb1, 0x62, 0xe9,
+ 0x12, 0x60, 0x5d, 0xbf, 0xcc, 0x40, 0x3b, 0xe7, 0x4b, 0x17, 0xf6, 0x7b,
+ 0x9f, 0x73, 0x56, 0x2f, 0xb9, 0xf7, 0x35, 0x62, 0xfd, 0xb6, 0x68, 0xb0,
+ 0x8f, 0x4f, 0xc5, 0xf7, 0x8e, 0xc3, 0x58, 0xbf, 0xa1, 0x07, 0xe0, 0x8e,
+ 0xb1, 0x52, 0x79, 0x9d, 0x0e, 0xdf, 0xe2, 0x14, 0x32, 0x29, 0x8f, 0x58,
+ 0xa9, 0x54, 0xa8, 0x31, 0x2c, 0x85, 0x89, 0xa5, 0x3f, 0x84, 0x31, 0x42,
+ 0x27, 0xc4, 0x56, 0xef, 0x16, 0x2f, 0x6e, 0xe7, 0x58, 0xbf, 0x7f, 0x3d,
+ 0x23, 0x58, 0xb9, 0xb4, 0xb1, 0x58, 0x7b, 0xb1, 0x0f, 0x78, 0xa2, 0xf0,
+ 0x72, 0x4b, 0x17, 0x89, 0xa0, 0xb1, 0x7e, 0xc3, 0x71, 0xe2, 0x58, 0xbd,
+ 0x9f, 0x33, 0x0f, 0x14, 0x87, 0x2e, 0x92, 0x58, 0xb9, 0x82, 0x31, 0x15,
+ 0x5e, 0x62, 0x0c, 0xca, 0xb1, 0x31, 0x72, 0x86, 0xcd, 0xff, 0xec, 0x19,
+ 0x82, 0x60, 0xfc, 0x26, 0xda, 0x56, 0x2f, 0xa4, 0xfc, 0x3a, 0xc5, 0xf9,
+ 0xbc, 0x66, 0xe1, 0x2c, 0x5f, 0xfb, 0x0d, 0xfe, 0x7b, 0x85, 0x30, 0x58,
+ 0xa9, 0x46, 0xdb, 0xa6, 0xb1, 0x18, 0x8b, 0x2f, 0xb6, 0xf3, 0xec, 0xb1,
+ 0x7f, 0xa7, 0xa8, 0x70, 0xcf, 0x3a, 0xc5, 0xfb, 0xcc, 0x77, 0xf2, 0xc5,
+ 0x62, 0x20, 0xce, 0x4a, 0x46, 0xd7, 0x86, 0xe3, 0x58, 0xbf, 0xff, 0xf0,
+ 0xa7, 0x46, 0x4f, 0xe4, 0x66, 0x79, 0xf3, 0xbb, 0xa8, 0x37, 0x4b, 0x17,
+ 0x80, 0xd1, 0xeb, 0x17, 0xee, 0x14, 0xc5, 0xe5, 0x8a, 0x1a, 0x36, 0x48,
+ 0x77, 0x8e, 0x7e, 0x20, 0xbf, 0xff, 0xbc, 0x2d, 0x37, 0x3c, 0xe6, 0x7f,
+ 0x36, 0x62, 0xdd, 0x62, 0xdd, 0xf5, 0x58, 0xa7, 0x3f, 0x8e, 0x2f, 0x5a,
+ 0x0b, 0x17, 0xff, 0xc6, 0x3e, 0x6c, 0x64, 0x4f, 0xe7, 0xd3, 0x01, 0x62,
+ 0xa5, 0x52, 0x0e, 0x46, 0x0e, 0xd0, 0xb4, 0xf1, 0x08, 0x84, 0xaf, 0xfe,
+ 0x36, 0x4b, 0x73, 0x1f, 0x5a, 0x70, 0x96, 0x2f, 0xfd, 0xd4, 0x3f, 0x9d,
+ 0x43, 0xcf, 0x12, 0xc5, 0xe9, 0x29, 0x58, 0xbe, 0xfb, 0x80, 0x25, 0x8b,
+ 0xc5, 0xbc, 0xac, 0x5f, 0xbf, 0x3a, 0xcd, 0x96, 0x2f, 0xff, 0x14, 0xf5,
+ 0xc6, 0xd1, 0xe7, 0xa8, 0x71, 0x62, 0xff, 0xff, 0xf6, 0x7b, 0x8d, 0x11,
+ 0x85, 0x9d, 0x43, 0x05, 0xb1, 0x60, 0xfe, 0xf1, 0x2c, 0x56, 0xe8, 0xf0,
+ 0x39, 0x4f, 0xd3, 0x2e, 0x2f, 0x2c, 0x5f, 0xfe, 0xe4, 0xc3, 0xd9, 0xf2,
+ 0xcf, 0x7d, 0xd6, 0x2a, 0x4f, 0x81, 0xc5, 0xee, 0x11, 0xab, 0x14, 0x62,
+ 0xaa, 0x19, 0x48, 0x1a, 0x19, 0xa3, 0x6e, 0x49, 0xa8, 0xc3, 0x7f, 0x09,
+ 0x1f, 0x10, 0x5e, 0x3f, 0xd9, 0x62, 0xf1, 0x81, 0x9d, 0x62, 0xfd, 0x23,
+ 0xee, 0x93, 0xac, 0x5c, 0x23, 0x56, 0x2f, 0xbf, 0xf1, 0x1a, 0xb1, 0x5f,
+ 0x37, 0xc1, 0x8c, 0xdc, 0x23, 0x56, 0x2f, 0xbf, 0xf1, 0x1a, 0xb1, 0x77,
+ 0xb8, 0x61, 0xf0, 0x7c, 0x88, 0x31, 0x9b, 0xff, 0x02, 0x2f, 0xb8, 0x09,
+ 0xba, 0x82, 0xc5, 0x2c, 0x53, 0x1e, 0x6f, 0x10, 0x68, 0xc4, 0xdd, 0x26,
+ 0x19, 0x39, 0x08, 0xab, 0xdf, 0x37, 0xcb, 0x17, 0xef, 0x7b, 0xd8, 0x12,
+ 0xc5, 0x49, 0xe4, 0xb8, 0xfd, 0x4a, 0xa5, 0x4e, 0x87, 0x4f, 0x1c, 0xa0,
+ 0x21, 0x07, 0x78, 0xf3, 0xba, 0xc5, 0xda, 0xc5, 0x8b, 0xd8, 0xe3, 0x58,
+ 0xb7, 0x16, 0x2e, 0x2c, 0xdc, 0xd7, 0x74, 0x39, 0x7f, 0xef, 0xc9, 0x19,
+ 0xa9, 0x0d, 0x89, 0x62, 0xff, 0xf6, 0x98, 0xbd, 0xf6, 0x86, 0x0d, 0xa0,
+ 0xb1, 0x79, 0xf0, 0x96, 0x2e, 0x98, 0x96, 0x2f, 0xd3, 0xad, 0x34, 0x7a,
+ 0xc5, 0x39, 0xe1, 0x88, 0x62, 0xff, 0xec, 0x01, 0x9f, 0x7f, 0x70, 0x9e,
+ 0x25, 0x8b, 0x0d, 0x62, 0xf8, 0x07, 0xce, 0x2c, 0x5f, 0x16, 0x70, 0xcc,
+ 0x36, 0xbc, 0x12, 0xad, 0x93, 0xe6, 0xdc, 0xb7, 0x47, 0xe7, 0x49, 0xe2,
+ 0xf7, 0x88, 0x7b, 0x3d, 0xd9, 0x96, 0x2f, 0xfe, 0x8b, 0xbb, 0xf9, 0xec,
+ 0x01, 0xda, 0x25, 0x8a, 0x8d, 0x15, 0x86, 0xc8, 0xf6, 0x4a, 0x2b, 0x26,
+ 0x91, 0x08, 0xdf, 0xff, 0x8c, 0xea, 0x13, 0xf3, 0x3f, 0x9e, 0xf4, 0xe8,
+ 0x0b, 0x17, 0x06, 0x75, 0x8b, 0xfe, 0xfe, 0x6d, 0x3d, 0x13, 0x84, 0xb1,
+ 0x58, 0x7a, 0x9c, 0x19, 0xa3, 0xa3, 0x3c, 0x10, 0xae, 0xbf, 0xcc, 0x40,
+ 0x30, 0x2c, 0xfa, 0xc5, 0xff, 0x81, 0x1d, 0x9f, 0x79, 0x3b, 0x0d, 0x62,
+ 0xff, 0xbe, 0xe7, 0x98, 0xff, 0xe6, 0xcb, 0x14, 0xb1, 0x6e, 0x18, 0x79,
+ 0x3b, 0x1e, 0xd4, 0x11, 0xd2, 0x46, 0xa2, 0x84, 0x55, 0xfd, 0xac, 0x81,
+ 0x49, 0xd6, 0x2f, 0xd9, 0x02, 0x93, 0xac, 0x5c, 0x40, 0x30, 0xf5, 0x34,
+ 0x5b, 0x7f, 0xff, 0xfe, 0x87, 0x38, 0x29, 0xf3, 0x8f, 0x0a, 0x23, 0x0b,
+ 0x35, 0x25, 0xef, 0xe7, 0x72, 0xc5, 0xff, 0xa7, 0x1f, 0xdf, 0x92, 0x9d,
+ 0xd6, 0x2f, 0xe3, 0xf5, 0x3f, 0xfc, 0xac, 0x5e, 0xea, 0x1c, 0xd8, 0xfb,
+ 0x30, 0xf6, 0xb1, 0x35, 0x5e, 0x8b, 0xb5, 0x0f, 0x2b, 0x71, 0x62, 0xa5,
+ 0x59, 0xb6, 0x46, 0x22, 0x28, 0xf7, 0x43, 0x36, 0xbf, 0x67, 0x3e, 0xf0,
+ 0x58, 0xb6, 0xcb, 0x17, 0xd3, 0xec, 0x02, 0xc5, 0x2c, 0x56, 0xc6, 0xbb,
+ 0xbf, 0x22, 0xbf, 0xff, 0xec, 0xed, 0x86, 0x7d, 0x9f, 0xcc, 0x7c, 0x30,
+ 0x7a, 0x70, 0x96, 0x2f, 0xe1, 0xb1, 0x41, 0xce, 0xb1, 0x7f, 0xf6, 0x43,
+ 0xed, 0x09, 0xf6, 0xb0, 0x6b, 0x17, 0xed, 0x67, 0x50, 0xe2, 0xc5, 0xfb,
+ 0xed, 0x0f, 0xba, 0xc5, 0xed, 0xff, 0x8b, 0x15, 0xb1, 0xf8, 0x40, 0xab,
+ 0x45, 0x17, 0xf0, 0x38, 0x60, 0x39, 0xa5, 0x8a, 0xc3, 0xe1, 0x63, 0x0b,
+ 0xfe, 0xea, 0x75, 0xb1, 0x98, 0xe3, 0x58, 0xba, 0x27, 0x58, 0xbf, 0xfb,
+ 0x3c, 0x66, 0x43, 0xf8, 0xf0, 0xe2, 0xc5, 0x41, 0x57, 0xae, 0x14, 0x3a,
+ 0x0f, 0xc9, 0xd9, 0xa8, 0x05, 0xa5, 0x18, 0xa8, 0x88, 0x3b, 0x1e, 0x47,
+ 0x0c, 0x5f, 0x7e, 0x34, 0xde, 0x39, 0x62, 0xff, 0xf6, 0x6a, 0x5c, 0x78,
+ 0x73, 0x39, 0x23, 0x58, 0xbf, 0x75, 0x09, 0x04, 0xac, 0x5f, 0xfb, 0x3d,
+ 0xec, 0x7e, 0xc5, 0x9c, 0x58, 0xa3, 0x11, 0x65, 0x89, 0x5f, 0x29, 0xbf,
+ 0xd1, 0x73, 0x8c, 0x5b, 0x9d, 0x62, 0xfc, 0x59, 0xf6, 0xf2, 0xc5, 0x74,
+ 0x88, 0xdd, 0x18, 0x1c, 0xda, 0xf6, 0x45, 0x2b, 0x17, 0xd3, 0xfc, 0xe2,
+ 0xc5, 0x68, 0xdf, 0x90, 0xed, 0xff, 0x3c, 0x74, 0x9f, 0x9f, 0xc3, 0xac,
+ 0x5f, 0x3f, 0x6c, 0xd2, 0xc5, 0xff, 0x76, 0xea, 0x1c, 0xc1, 0x68, 0x0b,
+ 0x17, 0xdc, 0xfb, 0x1d, 0x62, 0x9c, 0xf8, 0x7c, 0x7d, 0x5d, 0xe2, 0xad,
+ 0xe9, 0x8d, 0xb1, 0xdc, 0x0e, 0x41, 0xf3, 0xc2, 0x84, 0x2d, 0xf1, 0x9b,
+ 0xec, 0x12, 0xc5, 0xfb, 0x3e, 0x67, 0xb8, 0xb1, 0x7f, 0x16, 0x00, 0xf3,
+ 0x05, 0x8b, 0xf1, 0x67, 0xbe, 0xeb, 0x14, 0x33, 0xd4, 0x08, 0xb6, 0xfd,
+ 0xb1, 0x82, 0x98, 0x96, 0x2e, 0xe1, 0xd6, 0x2f, 0xff, 0xf8, 0xa4, 0x1d,
+ 0x43, 0x82, 0x9f, 0x16, 0x0d, 0xf3, 0x51, 0x2c, 0x54, 0xa3, 0x39, 0x88,
+ 0xf8, 0x59, 0xe1, 0x8a, 0x31, 0xd6, 0x63, 0x4c, 0x3a, 0xb6, 0x94, 0xfa,
+ 0x39, 0x43, 0xb9, 0x3d, 0x06, 0x6c, 0x2b, 0xb7, 0x1f, 0xea, 0x32, 0x97,
+ 0x95, 0x1b, 0x1e, 0xe7, 0x14, 0x71, 0x7a, 0x8c, 0x0b, 0xf2, 0xbf, 0x9a,
+ 0x57, 0xa8, 0x25, 0x69, 0x14, 0xb5, 0x7e, 0x4e, 0x2d, 0x7a, 0x59, 0xf8,
+ 0xa5, 0xb9, 0x76, 0x66, 0x08, 0xa0, 0x38, 0xd3, 0x2f, 0xb2, 0x21, 0x0d,
+ 0x62, 0xfd, 0x07, 0xd6, 0x74, 0xb1, 0x7b, 0x9f, 0xc5, 0x8b, 0xf6, 0x73,
+ 0x6c, 0x09, 0x62, 0xff, 0xef, 0x88, 0x7f, 0x17, 0xb9, 0xf1, 0x44, 0xb1,
+ 0x7d, 0xc1, 0x4e, 0x96, 0x2b, 0x74, 0xc0, 0x3a, 0x24, 0x88, 0xa7, 0xe3,
+ 0xa4, 0x55, 0xc4, 0x9a, 0x58, 0xbb, 0xdc, 0x58, 0xa9, 0x34, 0x84, 0x19,
+ 0x7f, 0xf9, 0xf4, 0xf9, 0xd1, 0x9e, 0x88, 0xa4, 0xeb, 0x17, 0xff, 0x63,
+ 0x74, 0x60, 0xe7, 0x63, 0x0d, 0x35, 0x62, 0xb7, 0x44, 0xbf, 0x49, 0x97,
+ 0xf4, 0x9c, 0xb3, 0x6c, 0x58, 0xbd, 0xee, 0x7f, 0x0f, 0x4b, 0xe4, 0xb7,
+ 0xff, 0xe3, 0xf5, 0x0e, 0x6b, 0xa9, 0xf7, 0x27, 0xef, 0xe5, 0x8b, 0xfe,
+ 0xc3, 0x4b, 0x3d, 0xf7, 0x09, 0x62, 0xfd, 0x81, 0x60, 0xce, 0xb1, 0x7f,
+ 0x7f, 0x39, 0x3a, 0xdd, 0x62, 0xfe, 0x86, 0x18, 0xfa, 0x12, 0xc5, 0xff,
+ 0x3e, 0x10, 0xdf, 0xb4, 0x8d, 0x62, 0xe9, 0xe8, 0xc4, 0x4b, 0xc4, 0x5f,
+ 0xf2, 0xfa, 0x94, 0xf1, 0x1c, 0xcf, 0x4b, 0x3f, 0x3a, 0x28, 0x60, 0x5d,
+ 0x1e, 0x35, 0x8b, 0xff, 0xbc, 0xfa, 0x9c, 0x2f, 0x73, 0x09, 0x62, 0xff,
+ 0xfb, 0x6c, 0xdc, 0x7f, 0x7c, 0x34, 0xc3, 0x45, 0x2b, 0x17, 0xf6, 0x6b,
+ 0x59, 0xee, 0x2c, 0x5f, 0xc4, 0xc6, 0x9d, 0xa0, 0xb1, 0x7a, 0x0f, 0xef,
+ 0x9e, 0xe7, 0x8b, 0xad, 0xb2, 0xc5, 0xfb, 0x0e, 0x59, 0xd2, 0xc5, 0xfd,
+ 0xe7, 0xed, 0x25, 0xba, 0xc5, 0x70, 0xf6, 0x03, 0x28, 0xbb, 0xf8, 0xb1,
+ 0x7f, 0x1e, 0x77, 0x33, 0x86, 0xac, 0x5f, 0xa0, 0xe4, 0x0e, 0x2c, 0x5f,
+ 0xa4, 0xef, 0xf9, 0x58, 0xbc, 0x41, 0xfd, 0x62, 0xff, 0x67, 0xbe, 0xfe,
+ 0xcd, 0xd6, 0x2e, 0x7e, 0x96, 0x2f, 0xa7, 0x0b, 0x75, 0x8a, 0x31, 0x34,
+ 0x78, 0x11, 0xe0, 0xbc, 0x46, 0x5a, 0x28, 0x62, 0x72, 0x1e, 0xe1, 0xa7,
+ 0x86, 0x2f, 0xc0, 0xc1, 0xb4, 0x16, 0x2f, 0xff, 0x4c, 0x9c, 0xc1, 0xfe,
+ 0x4c, 0xfc, 0xc7, 0xac, 0x54, 0x6c, 0xaf, 0xa2, 0x46, 0xdd, 0x0a, 0x28,
+ 0x58, 0x9c, 0xcf, 0xf1, 0xd9, 0x33, 0xf1, 0x14, 0x5f, 0xff, 0xed, 0x67,
+ 0x33, 0x7c, 0xd4, 0xf9, 0xf7, 0x71, 0xc5, 0x2b, 0x17, 0xf3, 0x6d, 0xdc,
+ 0x59, 0xd2, 0xc5, 0xd0, 0xe6, 0x91, 0x29, 0xe6, 0x2b, 0xfb, 0xf3, 0x01,
+ 0x30, 0x6b, 0x17, 0xe1, 0xff, 0x0b, 0xcb, 0x15, 0x03, 0xd7, 0x88, 0xbe,
+ 0xba, 0x45, 0x49, 0x42, 0x1a, 0xff, 0xb4, 0xf8, 0x17, 0xbc, 0xc4, 0xb1,
+ 0x77, 0x46, 0xac, 0x5c, 0xfd, 0x18, 0x7a, 0x63, 0x39, 0xbc, 0xe0, 0xc5,
+ 0x8b, 0xe8, 0x99, 0xa0, 0xb1, 0x73, 0x0d, 0x62, 0x9c, 0xdd, 0x00, 0x8e,
+ 0xdc, 0x81, 0xfb, 0x62, 0xb5, 0xff, 0xec, 0x0b, 0xbb, 0xf9, 0xec, 0x01,
+ 0xda, 0x25, 0x8b, 0xf6, 0x4e, 0xa0, 0x05, 0x8a, 0x94, 0xef, 0xb4, 0xf6,
+ 0xd0, 0xa5, 0x22, 0x71, 0x27, 0xdf, 0xf9, 0xbb, 0x16, 0x7b, 0x00, 0x43,
+ 0x58, 0xb0, 0x16, 0x29, 0xcf, 0x46, 0x23, 0xfb, 0xfe, 0xfe, 0xcf, 0x85,
+ 0xd4, 0x38, 0xb1, 0x7f, 0xdf, 0x8b, 0xf9, 0xd4, 0x30, 0x96, 0x2f, 0xf7,
+ 0xf3, 0x72, 0xc1, 0x47, 0xac, 0x54, 0x9f, 0x97, 0x47, 0x77, 0xf8, 0xce,
+ 0x61, 0x4e, 0xa2, 0x58, 0xbd, 0xd6, 0x6e, 0xb1, 0x7f, 0xfb, 0x37, 0xe6,
+ 0x7a, 0x2c, 0x34, 0xb0, 0x0b, 0x15, 0xa4, 0x50, 0x70, 0xd4, 0x21, 0xfb,
+ 0xff, 0xfe, 0xc3, 0x4c, 0xc3, 0x74, 0xfd, 0x16, 0x78, 0x40, 0x3b, 0x41,
+ 0x62, 0xa5, 0x50, 0x56, 0x42, 0xb5, 0xe1, 0x84, 0x23, 0x1b, 0xfc, 0xfa,
+ 0x1b, 0xc0, 0x5a, 0x58, 0xa8, 0x1f, 0xd6, 0xe8, 0xd4, 0xb1, 0x7f, 0x4e,
+ 0xbc, 0xf9, 0xd2, 0xc5, 0xff, 0x48, 0xb7, 0xeb, 0xcf, 0x84, 0xb1, 0x5f,
+ 0x3e, 0x82, 0x2e, 0xbe, 0x84, 0x83, 0x8b, 0x17, 0xf3, 0xf4, 0x0d, 0x30,
+ 0xd6, 0x2f, 0x66, 0x80, 0xb1, 0x7e, 0xe3, 0xe1, 0x01, 0x62, 0xd8, 0xe7,
+ 0x89, 0xc1, 0xdb, 0xf3, 0x80, 0x19, 0xa5, 0x8b, 0xe1, 0xfe, 0x60, 0xb1,
+ 0x51, 0xb2, 0x73, 0x83, 0x74, 0xc2, 0x1f, 0x91, 0x93, 0x9f, 0x09, 0x83,
+ 0x28, 0xb7, 0x78, 0xb1, 0x7a, 0x35, 0xc6, 0xf1, 0xb2, 0xc5, 0xf9, 0xb0,
+ 0x9c, 0xd5, 0x8b, 0xde, 0xcf, 0xac, 0x57, 0x7c, 0x3f, 0x22, 0x2e, 0xee,
+ 0x27, 0xbe, 0xcc, 0xff, 0x16, 0x2f, 0xff, 0xff, 0xf9, 0xf7, 0xfe, 0x4f,
+ 0x5b, 0x4e, 0x3f, 0x40, 0x92, 0xdd, 0xbe, 0x4c, 0x03, 0x37, 0xeb, 0x8b,
+ 0x17, 0xff, 0xd3, 0xb7, 0xba, 0x80, 0x88, 0xd3, 0x1f, 0xb3, 0xac, 0x56,
+ 0xe8, 0xef, 0x28, 0x4c, 0xdc, 0xe7, 0x58, 0xbe, 0x33, 0xa1, 0x12, 0xc5,
+ 0xfe, 0xc0, 0x8c, 0x90, 0x48, 0x16, 0x2f, 0xff, 0xfa, 0x0d, 0xd1, 0x84,
+ 0x2e, 0xe3, 0x33, 0xa8, 0x60, 0x88, 0x1c, 0x58, 0xbc, 0x76, 0x3a, 0xc5,
+ 0x6c, 0x8c, 0x0e, 0x8d, 0x59, 0xba, 0xa2, 0x4d, 0x54, 0xe5, 0x1d, 0x85,
+ 0xfb, 0xa1, 0xcb, 0x7f, 0xd1, 0xb7, 0xbc, 0xe5, 0xd4, 0x38, 0xb1, 0x7d,
+ 0x1f, 0xfc, 0x8f, 0x58, 0xbd, 0x1c, 0xfd, 0xfa, 0xc5, 0x18, 0xb8, 0xcd,
+ 0x1b, 0x34, 0xed, 0x08, 0x91, 0x9b, 0xe4, 0xa6, 0x63, 0x52, 0x59, 0x02,
+ 0x38, 0xa6, 0xff, 0xf1, 0x49, 0xcc, 0xfe, 0x75, 0xec, 0x68, 0x96, 0x2f,
+ 0xff, 0xff, 0xba, 0xe0, 0xa7, 0xa3, 0x3f, 0x83, 0x30, 0xb0, 0x46, 0x99,
+ 0xc0, 0x01, 0xfc, 0xb1, 0x7f, 0xe1, 0x4f, 0x76, 0xb3, 0xdc, 0x9d, 0x96,
+ 0x2f, 0xff, 0xf1, 0xcf, 0x3e, 0xe6, 0x7b, 0x9a, 0x7c, 0xdc, 0xb0, 0x6b,
+ 0x16, 0xcd, 0x91, 0x48, 0x34, 0x3b, 0xff, 0xde, 0x14, 0xe6, 0xc6, 0x71,
+ 0xc9, 0xf4, 0xb1, 0x60, 0x88, 0xfd, 0x03, 0x29, 0xa9, 0x4f, 0x1b, 0x23,
+ 0x9d, 0xbf, 0x49, 0x74, 0xdb, 0x2c, 0x5f, 0xcf, 0xac, 0xf3, 0x74, 0xb1,
+ 0x7f, 0x44, 0xe3, 0xc3, 0xba, 0xc5, 0xff, 0xff, 0xff, 0x6f, 0x3f, 0x93,
+ 0xfb, 0x39, 0xc9, 0xd6, 0xa4, 0xb3, 0x6c, 0x17, 0x05, 0x11, 0x49, 0xd6,
+ 0x2f, 0xff, 0xfc, 0xf3, 0xe2, 0xcf, 0x7f, 0x0c, 0xeb, 0x8e, 0x6e, 0x7c,
+ 0x5e, 0x58, 0xa9, 0x4c, 0xc7, 0x0b, 0xbf, 0x09, 0x5b, 0xc2, 0xd1, 0xab,
+ 0x14, 0x34, 0xec, 0x8f, 0x1a, 0xfc, 0x71, 0xa5, 0xf9, 0x80, 0x1b, 0x6c,
+ 0xb1, 0x7f, 0xff, 0xf6, 0xc6, 0x7b, 0x67, 0xcd, 0x6c, 0x64, 0x50, 0x7f,
+ 0xe0, 0xfa, 0xce, 0xe5, 0x8a, 0xc4, 0x70, 0xb9, 0xd0, 0x8a, 0xaf, 0x38,
+ 0x25, 0x62, 0xff, 0x18, 0x59, 0xa7, 0x93, 0xac, 0x5f, 0xfb, 0x4d, 0xed,
+ 0x63, 0xfe, 0x46, 0xb1, 0x7f, 0x0c, 0xb3, 0xed, 0xe5, 0x8b, 0xf7, 0xba,
+ 0x83, 0xe9, 0x62, 0xb0, 0xf5, 0xf8, 0x5b, 0x5b, 0x26, 0x0a, 0x31, 0xcd,
+ 0x19, 0x82, 0x12, 0xb7, 0x0e, 0x56, 0x2f, 0xfe, 0xee, 0xfb, 0x44, 0x61,
+ 0x66, 0xc1, 0xc1, 0x62, 0xa4, 0xf8, 0xf0, 0x5e, 0xfe, 0x0a, 0x28, 0x14,
+ 0x81, 0x62, 0xf6, 0x98, 0x35, 0x8b, 0xf4, 0xf8, 0xef, 0xe5, 0x8a, 0x63,
+ 0xc6, 0x10, 0xf5, 0xff, 0x85, 0x3b, 0x19, 0x25, 0x3a, 0x82, 0xc5, 0xf1,
+ 0x75, 0x87, 0x58, 0xad, 0x91, 0x08, 0x72, 0x10, 0x90, 0x2f, 0xfd, 0x26,
+ 0xf7, 0x0b, 0x0a, 0x20, 0xce, 0xb1, 0x7f, 0xc1, 0x66, 0x86, 0xf9, 0xee,
+ 0x2c, 0x5f, 0xfe, 0x17, 0x0c, 0xfb, 0x39, 0x3e, 0xa1, 0x1c, 0xb1, 0x7b,
+ 0xd2, 0x4b, 0x17, 0x78, 0xeb, 0x15, 0x86, 0xd3, 0x71, 0xcb, 0xff, 0xbf,
+ 0xd4, 0x38, 0x61, 0x61, 0xf4, 0x25, 0x8b, 0x61, 0x87, 0xd3, 0x84, 0x36,
+ 0x00, 0x13, 0x12, 0xe4, 0x3a, 0xef, 0xff, 0xff, 0x3e, 0x13, 0x7b, 0xf3,
+ 0x11, 0x85, 0x9f, 0x7f, 0x70, 0x5b, 0x8a, 0x56, 0x2f, 0x02, 0x4e, 0xb1,
+ 0x78, 0xd2, 0xc3, 0x11, 0x2b, 0x1b, 0x3c, 0x54, 0xab, 0xbb, 0xc8, 0x7d,
+ 0x74, 0x64, 0xe8, 0xad, 0x1a, 0x60, 0xa1, 0x89, 0x7e, 0xfe, 0x7a, 0x46,
+ 0xb1, 0x7f, 0xfb, 0xbf, 0x32, 0x7e, 0xfe, 0xe3, 0x97, 0x50, 0x58, 0xad,
+ 0x1f, 0xc8, 0x8a, 0x2f, 0xff, 0x31, 0xb8, 0x42, 0xf7, 0xf3, 0xb0, 0xe5,
+ 0x62, 0xff, 0xec, 0xf6, 0x3e, 0xd9, 0xbb, 0xc5, 0xc5, 0x8b, 0xbb, 0xde,
+ 0xf1, 0x62, 0xff, 0xd9, 0x80, 0xe1, 0x9a, 0xe0, 0xf8, 0xb1, 0x7f, 0xb5,
+ 0x9b, 0xfd, 0xf5, 0x12, 0xc5, 0xfd, 0x9c, 0xc9, 0x23, 0x56, 0x28, 0xc4,
+ 0xc3, 0x23, 0x44, 0x61, 0x91, 0x62, 0x0f, 0xcd, 0xaf, 0xff, 0xbe, 0xe6,
+ 0x64, 0x5d, 0x43, 0x9e, 0xfe, 0x74, 0xb1, 0x7f, 0xff, 0x0c, 0x9b, 0xff,
+ 0xea, 0x7b, 0x8a, 0x4e, 0x61, 0xfb, 0xf5, 0x8a, 0x25, 0x4c, 0x5e, 0x8d,
+ 0x63, 0xb2, 0x80, 0x4a, 0xb7, 0xde, 0xd0, 0x8e, 0xb1, 0x7f, 0xff, 0xb0,
+ 0xe7, 0x7e, 0x8c, 0x34, 0xdc, 0x2f, 0x1a, 0x29, 0xd2, 0xc5, 0xb7, 0x74,
+ 0x45, 0x68, 0x92, 0xe1, 0x12, 0xc5, 0xfe, 0x68, 0xf3, 0x3a, 0x84, 0x9a,
+ 0xb1, 0x7a, 0x7e, 0x5d, 0x1e, 0x88, 0x85, 0xeb, 0x11, 0x5b, 0xa7, 0xab,
+ 0xff, 0xff, 0xff, 0x38, 0xff, 0x9b, 0xbe, 0xb4, 0xe1, 0x3e, 0x11, 0xbc,
+ 0xc1, 0xfc, 0x5b, 0x18, 0xd1, 0x63, 0x2c, 0x5f, 0xf4, 0x46, 0x7b, 0x8e,
+ 0x64, 0x8d, 0x62, 0xb1, 0x1b, 0x42, 0x84, 0xed, 0xe9, 0x07, 0x16, 0x2e,
+ 0x90, 0x96, 0x2a, 0x06, 0xd4, 0x87, 0x6e, 0xc8, 0xe5, 0x8b, 0xfc, 0x67,
+ 0xe5, 0xf6, 0xc1, 0xac, 0x5b, 0xac, 0x3e, 0xf2, 0x20, 0xec, 0x35, 0x7f,
+ 0x84, 0x17, 0x22, 0xd3, 0x76, 0x58, 0xa9, 0x5e, 0x38, 0xc9, 0x50, 0x8f,
+ 0x1b, 0xf7, 0xe1, 0xf8, 0xd0, 0xcb, 0x23, 0x6b, 0xf9, 0xfe, 0xe7, 0x61,
+ 0xac, 0x52, 0xc5, 0x81, 0x03, 0x72, 0x32, 0xdb, 0xff, 0xee, 0x44, 0x58,
+ 0x17, 0xf3, 0xbb, 0xd2, 0x0e, 0x2c, 0x51, 0x1f, 0xe7, 0x89, 0xef, 0x9b,
+ 0xb3, 0xe9, 0x62, 0xf4, 0x09, 0xd6, 0x2b, 0x47, 0x80, 0x72, 0x4a, 0x94,
+ 0x41, 0xe3, 0x0d, 0xfd, 0xf6, 0x2f, 0x61, 0xd6, 0x2f, 0x39, 0x79, 0x62,
+ 0xfe, 0x87, 0x18, 0xe2, 0xe2, 0xc5, 0xc0, 0x65, 0x8b, 0xff, 0xff, 0x7b,
+ 0x9f, 0x73, 0x0b, 0x05, 0x3d, 0x7f, 0x00, 0xdd, 0x43, 0x8b, 0x15, 0x28,
+ 0x86, 0x71, 0x7a, 0x94, 0xc7, 0xf6, 0x2d, 0x61, 0xcf, 0x42, 0xd6, 0xe6,
+ 0x82, 0xc5, 0x9d, 0x62, 0xec, 0xff, 0xcd, 0x44, 0x70, 0xbd, 0xe9, 0x23,
+ 0x56, 0x2f, 0xf4, 0x79, 0x99, 0xdd, 0xf9, 0xf2, 0xc5, 0xf6, 0xb6, 0xcd,
+ 0xd6, 0x2b, 0x0f, 0x81, 0xce, 0xeb, 0xe8, 0x9d, 0xf3, 0xed, 0x4b, 0xaa,
+ 0xeb, 0xd9, 0xf8, 0x72, 0xb3, 0x32, 0x70, 0xd4, 0xd9, 0x6f, 0x7b, 0xc2,
+ 0x7b, 0xa9, 0x54, 0xcf, 0x3c, 0x4b, 0x14, 0x22, 0x75, 0x28, 0x48, 0xe5,
+ 0x1f, 0x95, 0x78, 0xd1, 0x99, 0x82, 0x14, 0xe5, 0x2f, 0x6f, 0x93, 0xe2,
+ 0xfe, 0x8e, 0x90, 0x51, 0xa0, 0x47, 0x35, 0x77, 0x43, 0x32, 0xfd, 0x9e,
+ 0xe3, 0x74, 0xb1, 0x7f, 0xc5, 0x81, 0x77, 0x77, 0x7b, 0x3e, 0xb1, 0x7f,
+ 0x89, 0x8d, 0xcc, 0x23, 0x56, 0x2e, 0xdf, 0x16, 0x28, 0x68, 0xb4, 0xdc,
+ 0xa4, 0xe8, 0x0c, 0x67, 0x4b, 0x17, 0xff, 0x19, 0x91, 0x75, 0x0e, 0x7b,
+ 0xf9, 0xd2, 0xc5, 0xff, 0x3e, 0x74, 0x46, 0x73, 0x09, 0x62, 0xf7, 0xdf,
+ 0x4b, 0x15, 0xf3, 0xd6, 0xee, 0x39, 0xbf, 0xd0, 0x91, 0x98, 0x37, 0x89,
+ 0x62, 0xff, 0x8c, 0xf1, 0x60, 0x58, 0xfc, 0x58, 0xbf, 0xf6, 0x1b, 0x25,
+ 0xb9, 0x9d, 0xb8, 0x12, 0xc5, 0xff, 0xff, 0xbc, 0xd1, 0x16, 0x6c, 0xc6,
+ 0x17, 0x58, 0x11, 0x60, 0xb0, 0xd5, 0x8a, 0x8d, 0xd3, 0xf5, 0xd8, 0x33,
+ 0x78, 0x50, 0x74, 0x4b, 0x11, 0xb7, 0xce, 0xbb, 0x91, 0x6d, 0xe5, 0x8b,
+ 0xc2, 0x1c, 0xac, 0x54, 0x9a, 0xfc, 0x12, 0xbd, 0xf9, 0x02, 0xc5, 0xfe,
+ 0xfb, 0x82, 0x7c, 0xfd, 0x96, 0x2f, 0xd0, 0xe7, 0xa7, 0x65, 0x8b, 0xe8,
+ 0x70, 0x51, 0x2c, 0x5f, 0x9e, 0x42, 0x98, 0x96, 0x2b, 0xa3, 0xce, 0x72,
+ 0x5b, 0xfd, 0x87, 0x6d, 0xbe, 0x2d, 0x96, 0x2f, 0x14, 0x81, 0x62, 0xfb,
+ 0xcc, 0x40, 0x58, 0xbf, 0xff, 0x31, 0xa6, 0x81, 0xa2, 0xee, 0x29, 0x0b,
+ 0xa8, 0x71, 0x62, 0x99, 0x10, 0x04, 0x45, 0x5e, 0x45, 0xe8, 0x70, 0x9c,
+ 0xbd, 0x03, 0x3b, 0xd5, 0x8b, 0xc6, 0xe7, 0x16, 0x2f, 0x0b, 0x06, 0xb1,
+ 0x71, 0x44, 0xb1, 0x7c, 0xd1, 0xf2, 0x05, 0x8a, 0x8d, 0x97, 0x66, 0xa6,
+ 0x51, 0x90, 0xe1, 0x4b, 0x83, 0xfb, 0x8e, 0xf4, 0x6b, 0x13, 0xc7, 0xc8,
+ 0x9a, 0x1e, 0x60, 0x29, 0x22, 0x4e, 0x0f, 0x08, 0x74, 0x21, 0x8b, 0xdc,
+ 0xf3, 0xac, 0x52, 0xc5, 0xfe, 0x84, 0xed, 0xcf, 0xb0, 0xd6, 0x2f, 0xf1,
+ 0x60, 0x5e, 0x35, 0xb8, 0xb1, 0x76, 0x19, 0xd1, 0xf5, 0x44, 0x6b, 0x7e,
+ 0x3c, 0xfd, 0xbe, 0xb1, 0x79, 0xa1, 0x8b, 0x15, 0x87, 0x89, 0xc2, 0x8b,
+ 0x69, 0x62, 0xfb, 0x93, 0xae, 0x2c, 0x52, 0xc5, 0xfd, 0xe7, 0xed, 0x25,
+ 0xba, 0xc5, 0x61, 0xf8, 0xf4, 0x25, 0x11, 0x18, 0x61, 0x97, 0xa7, 0x34,
+ 0xb1, 0x46, 0x1e, 0xd1, 0x1f, 0x5e, 0xfb, 0x9a, 0xb1, 0x74, 0xe2, 0xc5,
+ 0x18, 0x9a, 0x10, 0xe1, 0xd8, 0x69, 0x16, 0x87, 0xaf, 0xff, 0x40, 0xa4,
+ 0xc3, 0x94, 0x9b, 0xe7, 0xd9, 0x62, 0xff, 0xdf, 0x2c, 0xf6, 0xa4, 0xce,
+ 0x1d, 0x62, 0xfe, 0x93, 0x23, 0xf1, 0x8d, 0x58, 0xa9, 0x3f, 0x28, 0x90,
+ 0x2b, 0xa4, 0x70, 0x7a, 0x17, 0xd7, 0xc6, 0x4c, 0x34, 0xb1, 0x7b, 0x9a,
+ 0x3a, 0xc5, 0xff, 0xc6, 0x7b, 0x58, 0x16, 0x6c, 0x58, 0x12, 0xc5, 0x18,
+ 0xb8, 0x43, 0x23, 0xa3, 0x76, 0xc8, 0xed, 0x9e, 0x32, 0x50, 0x14, 0x91,
+ 0x27, 0x87, 0xae, 0x90, 0x2c, 0x5f, 0xb4, 0x61, 0x76, 0x09, 0x62, 0xff,
+ 0xfc, 0x68, 0x22, 0xe1, 0x9e, 0x3c, 0xff, 0x0b, 0xac, 0x58, 0xbe, 0x36,
+ 0x38, 0x5e, 0x58, 0xb7, 0x16, 0x2f, 0x30, 0x25, 0x62, 0xb4, 0x7a, 0xc7,
+ 0x28, 0xf8, 0x95, 0xe6, 0x8a, 0x56, 0x2f, 0x7f, 0x34, 0xb1, 0x46, 0x26,
+ 0xbb, 0x22, 0xf0, 0x2d, 0x68, 0x58, 0x04, 0x5f, 0xdc, 0x3b, 0x7f, 0x6d,
+ 0x14, 0x23, 0x6d, 0x6c, 0xb1, 0x7c, 0x19, 0x67, 0x65, 0x8b, 0xe7, 0x1e,
+ 0x0d, 0x62, 0xba, 0x3c, 0x73, 0x92, 0xda, 0x25, 0x8b, 0xe0, 0x79, 0x86,
+ 0xb1, 0x74, 0x9d, 0x62, 0xde, 0x58, 0xad, 0x1a, 0x96, 0x17, 0xa1, 0x9f,
+ 0xfe, 0x84, 0xfe, 0x99, 0x7d, 0x23, 0x68, 0x2c, 0x5f, 0xc5, 0xb4, 0x9d,
+ 0xbc, 0xb1, 0x76, 0x71, 0x62, 0xa4, 0xf1, 0x7c, 0x5d, 0x79, 0x88, 0xd5,
+ 0x8b, 0xff, 0x63, 0x74, 0x08, 0xa1, 0x3a, 0xd9, 0x62, 0xf6, 0xa6, 0x25,
+ 0x8b, 0x84, 0x12, 0xc5, 0xcd, 0xd2, 0xc5, 0x61, 0xb1, 0xe0, 0xcd, 0x6c,
+ 0x9a, 0xb1, 0xac, 0xe7, 0x21, 0xf8, 0xeb, 0x21, 0x79, 0x3e, 0xfa, 0x0c,
+ 0x51, 0xcb, 0x17, 0xdf, 0xc0, 0x32, 0xc5, 0x99, 0x62, 0x8c, 0x36, 0x71,
+ 0x11, 0x5d, 0x0d, 0x96, 0x2f, 0x7a, 0x60, 0xb1, 0x7d, 0x91, 0x3e, 0x96,
+ 0x2f, 0xef, 0xb7, 0x40, 0x0c, 0xeb, 0x17, 0xd9, 0xec, 0x3a, 0xc5, 0xa5,
+ 0x62, 0xff, 0x71, 0x81, 0x82, 0xd6, 0xcb, 0x17, 0xd1, 0x4f, 0x99, 0x62,
+ 0x8c, 0x47, 0xe4, 0x8e, 0xe1, 0x1b, 0x18, 0x80, 0x8b, 0xc2, 0x22, 0x35,
+ 0xbf, 0xfe, 0xc9, 0x20, 0x4b, 0xfb, 0xf8, 0x7c, 0x1a, 0xc5, 0xd3, 0xa5,
+ 0x8b, 0xde, 0x83, 0x2c, 0x5c, 0x2d, 0x96, 0x2b, 0x63, 0xcd, 0x61, 0x70,
+ 0xc7, 0x6e, 0xce, 0x2c, 0x5d, 0x26, 0xac, 0x56, 0xc9, 0xad, 0xc1, 0x88,
+ 0xd8, 0x4d, 0x1c, 0xc3, 0xc2, 0xf7, 0xbd, 0x9b, 0x2c, 0x5f, 0x9c, 0xb6,
+ 0x0f, 0xa5, 0x8b, 0x98, 0x29, 0x3c, 0x91, 0x8f, 0x5f, 0xbf, 0x85, 0xd0,
+ 0x96, 0x2f, 0xe7, 0xd7, 0x50, 0x29, 0x58, 0xbf, 0x4f, 0xa0, 0xfe, 0x58,
+ 0xbf, 0xbf, 0x3d, 0x43, 0x3c, 0xb1, 0x50, 0x3d, 0x71, 0x94, 0x56, 0x91,
+ 0xa1, 0xf2, 0x9f, 0x42, 0x16, 0xff, 0xb6, 0xd6, 0x45, 0x07, 0x23, 0x56,
+ 0x2f, 0xfa, 0x4b, 0xda, 0x7e, 0xd8, 0x35, 0x8a, 0x63, 0xf6, 0x8e, 0x3c,
+ 0xbb, 0x3c, 0xb1, 0x68, 0x96, 0x2b, 0xe6, 0xa8, 0x85, 0xea, 0x37, 0x64,
+ 0x4d, 0xcb, 0xfe, 0x42, 0x89, 0xe3, 0x85, 0x89, 0x64, 0xeb, 0x1f, 0x23,
+ 0x69, 0x4e, 0x05, 0x09, 0xb1, 0x43, 0xf6, 0x3a, 0x15, 0x61, 0xa7, 0x5f,
+ 0xff, 0xf6, 0xff, 0x7f, 0x8b, 0xc6, 0x60, 0xdf, 0x9d, 0x78, 0x4d, 0xc5,
+ 0x8b, 0xf0, 0x9b, 0xc0, 0x65, 0x8a, 0x31, 0x12, 0x7e, 0x6b, 0xbf, 0xb2,
+ 0x04, 0x26, 0xe2, 0xc5, 0x0c, 0xf4, 0x42, 0x24, 0xbf, 0xdb, 0x7d, 0xf3,
+ 0xdc, 0x75, 0x8a, 0x58, 0xa9, 0x3c, 0x0e, 0x1a, 0x5e, 0x32, 0x60, 0xb1,
+ 0x7b, 0xef, 0xa5, 0x8b, 0xf8, 0x85, 0xcd, 0x73, 0x8b, 0x17, 0xb3, 0xa8,
+ 0x2c, 0x54, 0x48, 0x88, 0xd0, 0xf7, 0x61, 0xd0, 0x8b, 0xef, 0xdd, 0x04,
+ 0xc4, 0x05, 0x8b, 0x88, 0xd5, 0x8b, 0xff, 0xcc, 0x51, 0x30, 0x35, 0xa7,
+ 0x27, 0x89, 0x62, 0xdc, 0x74, 0x46, 0x08, 0xab, 0xb0, 0xc5, 0xcd, 0xf5,
+ 0x8b, 0xff, 0x1e, 0x4d, 0xf7, 0xf3, 0xd2, 0x05, 0x8b, 0xf3, 0x0e, 0x70,
+ 0x96, 0x2c, 0x6a, 0xc5, 0x6c, 0x89, 0x07, 0x17, 0xfa, 0x01, 0x13, 0x5d,
+ 0x9c, 0x58, 0xb9, 0xce, 0xb1, 0x67, 0xf1, 0xae, 0x10, 0xbd, 0xff, 0x78,
+ 0x9b, 0xe7, 0x9c, 0xf2, 0xc5, 0xf1, 0xcb, 0x37, 0x30, 0xf7, 0xba, 0x26,
+ 0xbf, 0xfe, 0xcd, 0x98, 0xb7, 0x33, 0x92, 0x76, 0xeb, 0xcb, 0x17, 0x14,
+ 0x4b, 0x15, 0x28, 0xa6, 0xd1, 0xdb, 0x29, 0xdf, 0xe8, 0xff, 0xe6, 0xda,
+ 0xd4, 0xac, 0x52, 0xc5, 0xfd, 0xc0, 0xcf, 0xad, 0x4a, 0xc5, 0xff, 0xcd,
+ 0x0c, 0x21, 0x94, 0xc0, 0x7c, 0x58, 0xb6, 0x61, 0xff, 0xf8, 0x33, 0xb1,
+ 0x85, 0xff, 0x19, 0xc1, 0x4f, 0x42, 0xcf, 0xac, 0x5d, 0xce, 0xf1, 0x62,
+ 0xff, 0xf1, 0x61, 0xe7, 0x73, 0x03, 0xdb, 0x66, 0xe9, 0x62, 0xfe, 0x11,
+ 0xce, 0xd0, 0x33, 0xc7, 0xdb, 0xdc, 0x3b, 0x7f, 0xdc, 0x33, 0xbb, 0xd9,
+ 0x10, 0xa2, 0x58, 0xbb, 0x5c, 0x58, 0xb8, 0x50, 0xc3, 0xd9, 0x0d, 0x06,
+ 0xa0, 0x9b, 0xcf, 0xe1, 0x52, 0x50, 0xa2, 0xbc, 0x13, 0x6c, 0xb1, 0x67,
+ 0x58, 0xa7, 0x3e, 0xaf, 0x9d, 0x00, 0x7e, 0xfc, 0x3c, 0x8b, 0xee, 0xb1,
+ 0x7d, 0x91, 0x7d, 0xd6, 0x2d, 0xb9, 0x87, 0x98, 0x32, 0x9b, 0xff, 0xf4,
+ 0xea, 0x77, 0xc3, 0xce, 0xf0, 0x7e, 0x08, 0xeb, 0x15, 0x2c, 0x80, 0x6d,
+ 0x98, 0xf2, 0x15, 0x31, 0x43, 0x37, 0x50, 0xc7, 0xfc, 0x6d, 0xcc, 0x5c,
+ 0x50, 0xb7, 0xf4, 0xa1, 0x81, 0x3d, 0x47, 0x15, 0x5d, 0x13, 0x2c, 0x5f,
+ 0xda, 0xc9, 0x36, 0x49, 0x62, 0xff, 0xff, 0x76, 0x33, 0x7f, 0x88, 0x7a,
+ 0x7d, 0x8b, 0x3c, 0xf8, 0x12, 0xc5, 0xcd, 0xf5, 0x8b, 0xa3, 0x7e, 0xf1,
+ 0x62, 0xf1, 0x31, 0xd6, 0x2f, 0xfc, 0xdd, 0x75, 0x01, 0x6c, 0x67, 0xb1,
+ 0x62, 0xfe, 0x35, 0xa2, 0x27, 0x3a, 0xc5, 0x8e, 0xb1, 0x7f, 0xff, 0xf6,
+ 0x77, 0x45, 0x3f, 0xcf, 0x14, 0xc4, 0x66, 0x16, 0x75, 0x07, 0xe2, 0xc5,
+ 0xff, 0xfd, 0xf6, 0x88, 0xe2, 0x26, 0x37, 0x99, 0xbf, 0xc5, 0x1e, 0xb1,
+ 0x52, 0x8e, 0xa0, 0x09, 0x71, 0xda, 0x89, 0x34, 0x8f, 0x46, 0x33, 0x7f,
+ 0xfe, 0x2f, 0x70, 0xce, 0xbd, 0x9b, 0x4f, 0x1f, 0x58, 0xb1, 0x52, 0x88,
+ 0x11, 0x14, 0xde, 0x86, 0xd2, 0xb1, 0x7d, 0xee, 0x75, 0x05, 0x8b, 0x4a,
+ 0xc5, 0x18, 0x7a, 0x98, 0x3c, 0x02, 0x5b, 0x44, 0xb1, 0x7d, 0xf7, 0xd4,
+ 0x4b, 0x14, 0x61, 0xb7, 0x88, 0x4e, 0xfe, 0x2c, 0x1e, 0x3f, 0xd6, 0x2b,
+ 0xe7, 0x9f, 0xc2, 0x3b, 0xb3, 0x8b, 0x17, 0x85, 0x84, 0xb1, 0x7f, 0xfe,
+ 0xea, 0x1c, 0x33, 0x05, 0xdf, 0xbf, 0xd8, 0xb3, 0xb2, 0xc5, 0xff, 0x67,
+ 0x50, 0xe3, 0x4f, 0x50, 0x58, 0xbf, 0xfe, 0xe6, 0x36, 0x8c, 0x9f, 0x8b,
+ 0xc4, 0xc6, 0xac, 0x51, 0xd1, 0x19, 0xc3, 0xbb, 0xff, 0xfc, 0x69, 0x99,
+ 0x07, 0xec, 0x59, 0xcf, 0xe3, 0x8f, 0x0e, 0xb1, 0x5b, 0xa7, 0x47, 0xa1,
+ 0x73, 0x8e, 0x7e, 0x1d, 0x44, 0x47, 0x7f, 0xed, 0x45, 0xc9, 0xd3, 0x41,
+ 0xfe, 0xb1, 0x70, 0x7b, 0x2c, 0x56, 0x2a, 0x6f, 0x78, 0xf1, 0x59, 0x40,
+ 0x90, 0x2f, 0x49, 0x6c, 0xb1, 0x52, 0xbe, 0x0d, 0x01, 0x81, 0x96, 0xe3,
+ 0x3f, 0x42, 0xee, 0x45, 0xa1, 0xcf, 0xca, 0x0d, 0x27, 0x6f, 0x4b, 0x24,
+ 0xec, 0x83, 0x51, 0xbc, 0xa2, 0x3f, 0x8e, 0xf2, 0x39, 0xae, 0xf6, 0x52,
+ 0x94, 0x69, 0x1a, 0x0c, 0x6d, 0x3e, 0x13, 0xdf, 0x71, 0xab, 0xf7, 0xc8,
+ 0x5d, 0x77, 0xd6, 0x31, 0x48, 0xd5, 0x0b, 0xc8, 0xd6, 0x5b, 0x35, 0xa3,
+ 0xe6, 0xd3, 0xdf, 0x10, 0xa4, 0x11, 0x8e, 0xb3, 0x1f, 0xcb, 0x7c, 0xbe,
+ 0x6d, 0x23, 0x33, 0x7a, 0xf5, 0xa3, 0xaa, 0xcc, 0x51, 0xe9, 0x90, 0xf1,
+ 0x56, 0x35, 0x7a, 0xaf, 0xbf, 0xcf, 0x58, 0xf4, 0xfe, 0xf0, 0xf4, 0x5a,
+ 0x9c, 0xf0, 0x0a, 0x5f, 0x0f, 0x7f, 0x1d, 0x71, 0x5b, 0x16, 0x4e, 0x5a,
+ 0xda, 0xef, 0x5a, 0xd9, 0x11, 0x4f, 0xe7, 0xf6, 0x9c, 0xf9, 0x0a, 0x3d,
+ 0xa8, 0xea, 0x47, 0xd8, 0x74, 0x9b, 0x9e, 0xe9, 0xfc, 0x4b, 0xf7, 0xa4,
+ 0x9c, 0x0b, 0x17, 0xec, 0x19, 0x4e, 0xeb, 0x17, 0x8b, 0xd1, 0x98, 0x79,
+ 0xff, 0x27, 0xbf, 0xf7, 0xcb, 0x3b, 0x38, 0xf5, 0x27, 0x58, 0xbf, 0xfb,
+ 0xda, 0x9c, 0xea, 0x36, 0x1b, 0x31, 0xab, 0x17, 0x85, 0xbc, 0x64, 0xa2,
+ 0x2f, 0xa4, 0x0a, 0x8c, 0x5c, 0x85, 0x99, 0x71, 0x8f, 0x0c, 0x0b, 0xfd,
+ 0x1e, 0xcf, 0xee, 0x39, 0x2c, 0x5f, 0xe1, 0x34, 0x7e, 0x00, 0x0c, 0xb1,
+ 0x7e, 0xd6, 0xec, 0xdb, 0xaa, 0x49, 0xd2, 0xec, 0xe9, 0x62, 0xfe, 0x89,
+ 0xc2, 0x17, 0xbc, 0xb1, 0x7e, 0xc2, 0xdf, 0x25, 0x62, 0xdf, 0x58, 0xbf,
+ 0xf8, 0x44, 0xe5, 0x3f, 0x73, 0xe7, 0x16, 0x2b, 0x87, 0xa8, 0x21, 0x2b,
+ 0xb4, 0x75, 0x8b, 0xff, 0x88, 0x62, 0x1e, 0xa7, 0xef, 0x84, 0xb1, 0x7f,
+ 0xcd, 0xce, 0x61, 0xac, 0x40, 0x58, 0xa9, 0x3f, 0xc2, 0x43, 0xbc, 0x4c,
+ 0x6a, 0xc5, 0x9d, 0x62, 0xb0, 0xd7, 0x1a, 0x3b, 0x52, 0xaa, 0x2c, 0x66,
+ 0xb8, 0x6d, 0xd1, 0xbb, 0x8c, 0x68, 0xc4, 0xef, 0x60, 0x22, 0xe4, 0x25,
+ 0x23, 0x93, 0xaf, 0xb3, 0x3e, 0xeb, 0x17, 0xee, 0xbd, 0xe9, 0x3a, 0xc5,
+ 0xd1, 0x32, 0xc5, 0xf7, 0x98, 0x8d, 0x58, 0xa9, 0x37, 0x7d, 0x0c, 0x5f,
+ 0x1a, 0xd0, 0x8c, 0x1a, 0x29, 0xdc, 0x84, 0x36, 0x5a, 0x8c, 0x4e, 0x14,
+ 0xd8, 0xce, 0xaf, 0xff, 0xd0, 0x8c, 0xc8, 0x7f, 0x1e, 0x1c, 0x9f, 0x48,
+ 0xd6, 0x2f, 0x40, 0x5a, 0x58, 0xbf, 0x78, 0x5f, 0x93, 0xac, 0x5f, 0xd3,
+ 0x84, 0x66, 0x6c, 0xb1, 0x7b, 0xa6, 0xd9, 0x62, 0xec, 0xe2, 0xc5, 0x49,
+ 0xb6, 0xc1, 0xfb, 0xed, 0xb6, 0x9e, 0x96, 0x2f, 0xe6, 0xdb, 0xdc, 0x60,
+ 0x2c, 0x5d, 0xa8, 0xcc, 0x4c, 0x7f, 0xa1, 0xed, 0x14, 0xfd, 0x91, 0x87,
+ 0xe3, 0x89, 0xaa, 0x53, 0xe0, 0x78, 0xdd, 0xef, 0xda, 0xdd, 0x9b, 0x75,
+ 0x49, 0x46, 0x5f, 0xf9, 0xa1, 0x19, 0x9a, 0xdd, 0x9b, 0x75, 0x48, 0xd0,
+ 0x5f, 0xfe, 0x2c, 0x8a, 0x0d, 0xa8, 0x16, 0x76, 0x65, 0x8b, 0xd3, 0x9d,
+ 0x2c, 0x5e, 0x6d, 0xa5, 0x62, 0x88, 0xdd, 0x08, 0x76, 0xb1, 0x32, 0xc3,
+ 0x9b, 0xf1, 0x43, 0xd0, 0x85, 0xbf, 0xc1, 0xb7, 0x68, 0xcf, 0x3e, 0xcb,
+ 0x15, 0x18, 0x7f, 0xb2, 0x85, 0x7f, 0xfe, 0xcf, 0xfd, 0xa0, 0x16, 0x3f,
+ 0x62, 0x69, 0xe2, 0xc5, 0xff, 0xbe, 0x2f, 0xb3, 0xf5, 0xc9, 0x35, 0x62,
+ 0xde, 0x82, 0x25, 0xdd, 0x5a, 0xff, 0x4e, 0x83, 0x26, 0xf7, 0x16, 0x2b,
+ 0x0f, 0x73, 0xe5, 0x17, 0xe1, 0x79, 0x82, 0xf2, 0xc5, 0xfb, 0x60, 0xf6,
+ 0x9d, 0x96, 0x2f, 0xb7, 0x66, 0xdd, 0x52, 0x57, 0x95, 0xb2, 0x22, 0x30,
+ 0xab, 0x45, 0xb7, 0xfe, 0xde, 0x7d, 0x09, 0x39, 0x34, 0x16, 0x2f, 0xfb,
+ 0x93, 0x0f, 0xc8, 0x4c, 0x4b, 0x16, 0x7d, 0xcf, 0xe3, 0xc7, 0xf7, 0xfe,
+ 0xd6, 0xdc, 0x9d, 0xc9, 0x8f, 0xc5, 0x8a, 0xf9, 0xf4, 0xb1, 0x45, 0xff,
+ 0xde, 0x06, 0x0f, 0xf8, 0x31, 0xbf, 0x4b, 0x17, 0xee, 0xd2, 0x5f, 0x12,
+ 0xc5, 0xff, 0x9b, 0xa8, 0x73, 0x37, 0x1e, 0x74, 0xb1, 0x58, 0x7d, 0x8c,
+ 0x55, 0x63, 0x56, 0x2f, 0xe7, 0x18, 0xe7, 0x52, 0xb1, 0x73, 0x12, 0xc5,
+ 0xd2, 0x6a, 0xc5, 0xf4, 0x7e, 0x78, 0x96, 0x2f, 0xdc, 0x26, 0x9e, 0x2c,
+ 0x5f, 0xfe, 0xfb, 0x40, 0x2c, 0x7e, 0xc4, 0xd3, 0xc5, 0x8b, 0xff, 0xfc,
+ 0xe3, 0x3b, 0x31, 0x6e, 0x3f, 0xce, 0x0d, 0xcb, 0x65, 0x8b, 0x67, 0xd1,
+ 0x56, 0x49, 0x75, 0x28, 0xf9, 0x84, 0x34, 0xaf, 0xfb, 0xd9, 0xd7, 0xb3,
+ 0x08, 0xd5, 0x8b, 0xff, 0xcf, 0xd8, 0x73, 0x9d, 0x7d, 0xf5, 0x27, 0x58,
+ 0xbf, 0xf7, 0xe2, 0x6f, 0x7b, 0xad, 0xdc, 0x96, 0x2b, 0x11, 0x1c, 0xc9,
+ 0x97, 0xec, 0xff, 0xf2, 0x25, 0x8b, 0xff, 0xf0, 0x08, 0x47, 0x0c, 0x63,
+ 0x90, 0x1e, 0x73, 0xcb, 0x17, 0xf3, 0x7b, 0x99, 0xd7, 0x96, 0x28, 0x68,
+ 0xaf, 0xe8, 0xa4, 0x95, 0xed, 0x18, 0x35, 0xe2, 0x8c, 0x85, 0x4e, 0xf1,
+ 0x88, 0xf4, 0x43, 0xa8, 0x59, 0x1c, 0x83, 0xe2, 0x6c, 0x5b, 0xdf, 0x8b,
+ 0x10, 0xc7, 0xa3, 0x1e, 0xec, 0x4e, 0x14, 0x32, 0x03, 0x86, 0x85, 0xfb,
+ 0x5b, 0xb3, 0x6e, 0xa9, 0x2d, 0x8b, 0xfe, 0x84, 0x66, 0x6b, 0x76, 0x6d,
+ 0xd5, 0x22, 0x09, 0x7d, 0x87, 0x98, 0xf5, 0x8b, 0x46, 0x62, 0x29, 0xd8,
+ 0xdf, 0x89, 0x77, 0xc7, 0x72, 0x95, 0x8b, 0xf6, 0xb7, 0x66, 0xdd, 0x52,
+ 0x21, 0x97, 0xf6, 0x85, 0xda, 0x42, 0x3a, 0xc5, 0xfc, 0x59, 0xcf, 0x42,
+ 0x56, 0x2f, 0x34, 0x23, 0x25, 0x16, 0xf8, 0x42, 0xe6, 0xfd, 0x8c, 0xaf,
+ 0xfe, 0xec, 0xfe, 0x9f, 0x96, 0x7b, 0x52, 0xb1, 0x7f, 0x8e, 0x66, 0x69,
+ 0xbd, 0xc5, 0x8b, 0xb6, 0x8c, 0xc3, 0xfa, 0x0d, 0x16, 0xa3, 0x11, 0xf8,
+ 0xf0, 0xca, 0xbf, 0xbc, 0xe3, 0xc2, 0x89, 0x62, 0xf6, 0x76, 0xc5, 0x8a,
+ 0xc3, 0xcc, 0x22, 0xeb, 0xfc, 0x42, 0xe4, 0xe6, 0x80, 0xb1, 0x78, 0xdc,
+ 0x8f, 0x58, 0xbc, 0xc6, 0xc6, 0x61, 0xea, 0x1a, 0x67, 0x6e, 0x46, 0x22,
+ 0xac, 0x9d, 0x2f, 0x33, 0x6e, 0xb9, 0x40, 0xca, 0x93, 0xd5, 0xdc, 0xae,
+ 0xfd, 0x1a, 0xfb, 0xcd, 0xb6, 0xd9, 0x62, 0xdb, 0xac, 0x5f, 0x8f, 0xd4,
+ 0x30, 0xeb, 0x16, 0x8f, 0x58, 0xa8, 0xd6, 0x88, 0xac, 0x38, 0x88, 0x4f,
+ 0xe5, 0x57, 0x05, 0xe5, 0x8b, 0xdc, 0x73, 0x56, 0x28, 0x66, 0xdf, 0xa1,
+ 0x9b, 0xa3, 0x4d, 0x96, 0x2f, 0xfb, 0xf3, 0xee, 0x77, 0x9c, 0x8d, 0x09,
+ 0x62, 0xa3, 0x73, 0xe2, 0x80, 0xf5, 0xfd, 0x25, 0xef, 0xe4, 0x16, 0x2f,
+ 0x7b, 0x3b, 0x96, 0x2b, 0x47, 0x9b, 0xe2, 0xdb, 0x12, 0xc5, 0xee, 0xfa,
+ 0x47, 0x46, 0xeb, 0x17, 0xa6, 0x3a, 0x37, 0x58, 0xae, 0xfa, 0x1e, 0x9c,
+ 0x97, 0x59, 0xd6, 0x2b, 0xbc, 0x44, 0xf7, 0x7d, 0xb2, 0x46, 0xb2, 0x9b,
+ 0xff, 0xd1, 0xae, 0x35, 0xf7, 0x9f, 0x93, 0x93, 0x7d, 0xf4, 0xb1, 0x6e,
+ 0x96, 0x2e, 0x28, 0x2c, 0x5e, 0xf6, 0x01, 0x62, 0xc4, 0xb1, 0x7c, 0x21,
+ 0xb4, 0x7a, 0xc5, 0x39, 0xb7, 0xe0, 0x8d, 0xe1, 0x7b, 0x16, 0x2e, 0x98,
+ 0x96, 0x2f, 0xe3, 0xe6, 0xe4, 0xd1, 0xeb, 0x17, 0xb1, 0xf6, 0x58, 0xb0,
+ 0x6b, 0x15, 0x87, 0xc3, 0xa3, 0x11, 0x0e, 0xd8, 0x6b, 0x17, 0x87, 0x3e,
+ 0x58, 0x62, 0xca, 0xc7, 0x58, 0xb9, 0xfb, 0x2c, 0x54, 0x9e, 0xb3, 0x95,
+ 0xf8, 0x4a, 0xf7, 0x61, 0x41, 0x62, 0xf7, 0xf3, 0x8b, 0x16, 0x65, 0x8a,
+ 0x19, 0xae, 0xf0, 0xed, 0xec, 0x3c, 0xac, 0x50, 0xd5, 0x41, 0x60, 0x9c,
+ 0x78, 0xbc, 0x4a, 0x9a, 0x20, 0xf8, 0xef, 0x1e, 0x7d, 0x09, 0x6e, 0xc5,
+ 0xa1, 0xa7, 0x77, 0x10, 0xdf, 0x67, 0x50, 0xf2, 0xc5, 0xfc, 0x53, 0xd4,
+ 0x1c, 0x96, 0x2f, 0x71, 0xfb, 0x2c, 0x56, 0xc7, 0xe0, 0x32, 0x4f, 0x16,
+ 0xd8, 0x96, 0x2f, 0xb0, 0xec, 0x35, 0x8b, 0xf0, 0xe4, 0xb6, 0x8f, 0x58,
+ 0xbf, 0xd2, 0x68, 0x60, 0x04, 0xf4, 0xb1, 0x52, 0x7c, 0x7b, 0x16, 0x5f,
+ 0x9b, 0xee, 0x7c, 0x58, 0xac, 0x46, 0xff, 0xc4, 0x4a, 0x10, 0xbd, 0x88,
+ 0xaf, 0xe0, 0xf2, 0x27, 0x07, 0x16, 0x2f, 0xec, 0xdf, 0xf3, 0x31, 0x2c,
+ 0x5f, 0xb5, 0xa9, 0xc2, 0x58, 0xb4, 0x72, 0xc5, 0x3a, 0x37, 0x62, 0x42,
+ 0xf9, 0x83, 0x17, 0x88, 0x9e, 0xf0, 0x58, 0x12, 0xc5, 0xe1, 0xe7, 0xd6,
+ 0x2b, 0x46, 0xf3, 0xb8, 0x7e, 0xf1, 0x03, 0x8b, 0x17, 0xe6, 0xd8, 0x3c,
+ 0x89, 0x62, 0xf0, 0x03, 0xd9, 0x62, 0xf8, 0xf9, 0xd7, 0x16, 0x2d, 0xc9,
+ 0x3c, 0x47, 0x20, 0xbd, 0xac, 0x3a, 0xc5, 0x62, 0x33, 0xc8, 0x77, 0x8d,
+ 0xfe, 0x26, 0xa5, 0x8b, 0xb3, 0xa5, 0x8a, 0xec, 0x69, 0x23, 0x83, 0x2e,
+ 0x08, 0x6b, 0x17, 0xb7, 0x28, 0xf5, 0x8b, 0xfe, 0x0b, 0xee, 0xd0, 0xf3,
+ 0xec, 0xb1, 0x68, 0x2c, 0x53, 0x1e, 0x6f, 0x8e, 0xeb, 0xe8, 0xa8, 0x61,
+ 0x92, 0x6e, 0xb8, 0x5a, 0x58, 0xbf, 0x84, 0x6e, 0x1e, 0x77, 0x58, 0xbe,
+ 0xed, 0x33, 0xd2, 0xc5, 0xff, 0x81, 0x9d, 0x70, 0x3d, 0x39, 0xf1, 0x62,
+ 0xe7, 0x89, 0x62, 0xba, 0x3d, 0x9d, 0x20, 0xdf, 0xb6, 0xdf, 0xef, 0x12,
+ 0xc5, 0x4a, 0x33, 0x71, 0xf9, 0xc8, 0xef, 0xb6, 0xe7, 0x4e, 0xb1, 0x7f,
+ 0xfa, 0x7a, 0x83, 0x9c, 0x2c, 0x21, 0xfe, 0x56, 0x2a, 0x57, 0x00, 0x32,
+ 0x1e, 0x6e, 0xbf, 0xa8, 0x67, 0x1c, 0xbb, 0xe3, 0x05, 0x0f, 0xde, 0x16,
+ 0x88, 0x96, 0xfc, 0xc3, 0x0e, 0x49, 0x62, 0xff, 0x38, 0xa3, 0xff, 0x39,
+ 0xb2, 0xc5, 0xff, 0xb5, 0xe0, 0xc9, 0xb7, 0xc2, 0xdd, 0x62, 0xe6, 0xf2,
+ 0xc5, 0xcf, 0x1c, 0xb1, 0x51, 0x1b, 0x13, 0x8b, 0xdf, 0x7f, 0x0d, 0x75,
+ 0x8b, 0xfd, 0x9d, 0xb0, 0xb3, 0xaf, 0x2c, 0x54, 0x9f, 0xd6, 0xe4, 0x5f,
+ 0x23, 0xba, 0x7b, 0x96, 0x2f, 0xfc, 0x13, 0x43, 0x58, 0xff, 0x91, 0xac,
+ 0x5b, 0xa5, 0x8b, 0xc5, 0xd7, 0x16, 0x2f, 0x9c, 0x78, 0x4b, 0x15, 0x27,
+ 0xa4, 0xe2, 0x7c, 0x1e, 0xbf, 0xba, 0xe6, 0x1e, 0x63, 0xd6, 0x2f, 0xf6,
+ 0xc2, 0xdb, 0xdf, 0x61, 0xac, 0x5e, 0x66, 0xdd, 0x52, 0x62, 0x17, 0x83,
+ 0xf7, 0x16, 0x2a, 0x51, 0x65, 0xb1, 0x96, 0xe6, 0xfa, 0x2a, 0xbe, 0xd3,
+ 0x17, 0x96, 0x2c, 0x05, 0x8a, 0xd1, 0xb4, 0xee, 0x22, 0xbe, 0xf9, 0x34,
+ 0x7a, 0xc5, 0xfd, 0xaf, 0xb7, 0x30, 0x35, 0x8b, 0xbe, 0x25, 0x8b, 0xee,
+ 0x06, 0x50, 0x58, 0xa1, 0x9b, 0xcf, 0x0c, 0x5e, 0x9d, 0x6c, 0xb1, 0x52,
+ 0x8c, 0xf7, 0x25, 0x66, 0xb0, 0xc8, 0x6f, 0xdf, 0x6e, 0x4c, 0x7a, 0xc5,
+ 0xb4, 0xb1, 0x44, 0x6f, 0x44, 0x57, 0x73, 0x84, 0xb1, 0x7f, 0xe8, 0x67,
+ 0x3d, 0xfc, 0x7d, 0x41, 0x62, 0x9c, 0xf5, 0xc4, 0x31, 0x7f, 0x4c, 0xf4,
+ 0x76, 0x1a, 0xc5, 0xfe, 0x18, 0x05, 0xee, 0x0a, 0x3d, 0x62, 0xe9, 0xdd,
+ 0x62, 0xe9, 0xec, 0xb1, 0x7f, 0x61, 0x0b, 0x34, 0x6a, 0xc5, 0xc5, 0x05,
+ 0x8a, 0x94, 0x57, 0xb9, 0xcf, 0xc6, 0x3c, 0x32, 0x22, 0xeb, 0xfb, 0x98,
+ 0x46, 0x40, 0x0b, 0x17, 0xf4, 0xe6, 0x80, 0x0f, 0x2c, 0x54, 0x0f, 0x77,
+ 0x72, 0xfb, 0xfe, 0x72, 0x1e, 0xa6, 0x0d, 0xa5, 0x8b, 0xe9, 0xea, 0x1c,
+ 0x58, 0xad, 0x97, 0xde, 0xa0, 0x51, 0x86, 0xfb, 0xc3, 0xb3, 0xa2, 0xf7,
+ 0x1a, 0x8a, 0x12, 0x3a, 0x86, 0xf9, 0xdc, 0xbf, 0x0f, 0x36, 0x78, 0x27,
+ 0x7e, 0x10, 0xfa, 0x1b, 0xa2, 0x85, 0x2f, 0x62, 0x30, 0x8e, 0x2e, 0xe3,
+ 0xac, 0x5f, 0x6a, 0x48, 0xd5, 0x8b, 0xef, 0x39, 0x04, 0xb1, 0x7d, 0x11,
+ 0x3e, 0xcb, 0x16, 0x6c, 0x3c, 0x7e, 0x88, 0xef, 0x42, 0x63, 0xd6, 0x28,
+ 0x68, 0xc8, 0xc1, 0x73, 0x5a, 0xa2, 0x27, 0xbe, 0x7e, 0x4c, 0x4b, 0x17,
+ 0xff, 0x7b, 0x36, 0xe4, 0xe9, 0xa0, 0xff, 0x58, 0xad, 0x1f, 0x47, 0x88,
+ 0xec, 0xeb, 0x16, 0x75, 0x8b, 0x40, 0xd3, 0x44, 0x01, 0x1b, 0xba, 0x8f,
+ 0x58, 0xbe, 0x8e, 0xcd, 0x4a, 0xc5, 0x08, 0xf0, 0x43, 0x1c, 0xbd, 0x10,
+ 0xb4, 0xb1, 0x74, 0xf1, 0x62, 0xff, 0x0c, 0xa7, 0xdc, 0x11, 0xd6, 0x2f,
+ 0x38, 0x89, 0x62, 0xc4, 0xb1, 0x74, 0x92, 0xc5, 0xfd, 0x3c, 0x0f, 0x69,
+ 0xd9, 0x62, 0x8d, 0x45, 0xfc, 0x42, 0xe7, 0x34, 0x21, 0xce, 0x08, 0x86,
+ 0x2d, 0x73, 0xe9, 0x62, 0xf3, 0xe0, 0x16, 0x28, 0x66, 0xcc, 0x85, 0xef,
+ 0xa3, 0xfe, 0x28, 0xf5, 0x8a, 0x94, 0xf5, 0xf0, 0x8d, 0xe1, 0xbc, 0xd0,
+ 0x8c, 0x11, 0x05, 0xff, 0x0b, 0x62, 0xc1, 0xfc, 0x46, 0xac, 0x54, 0xab,
+ 0x11, 0x35, 0x13, 0xf2, 0x90, 0x09, 0x46, 0xfb, 0xfc, 0x14, 0xac, 0x5b,
+ 0x8b, 0x17, 0xff, 0xb3, 0xae, 0x80, 0xde, 0xe3, 0x97, 0x50, 0x58, 0xbf,
+ 0xc2, 0xdb, 0xa8, 0x7c, 0x5a, 0x58, 0xbf, 0xfa, 0x73, 0x98, 0x43, 0x70,
+ 0x49, 0x2c, 0x5e, 0x29, 0xd9, 0x62, 0xb1, 0x1e, 0xae, 0x25, 0xf4, 0xd2,
+ 0x38, 0x12, 0x0d, 0xf7, 0xfa, 0x68, 0xf5, 0x8b, 0x85, 0xa5, 0x8b, 0xda,
+ 0x93, 0xac, 0x5c, 0x1c, 0xac, 0x54, 0x9b, 0x5c, 0x1d, 0xbf, 0xd2, 0x0d,
+ 0x6a, 0x4f, 0xc5, 0x8a, 0x95, 0x44, 0xd0, 0x8c, 0x60, 0xe8, 0xec, 0x4f,
+ 0xc4, 0xdf, 0x0f, 0xdf, 0x0c, 0x3e, 0xf2, 0x0b, 0x17, 0xe0, 0x6f, 0xf7,
+ 0xef, 0xd6, 0x2f, 0x7f, 0x00, 0xb1, 0x7f, 0x75, 0xcf, 0xcb, 0xf9, 0x62,
+ 0xe6, 0xf2, 0xc5, 0x39, 0xe3, 0x1c, 0xbe, 0xf3, 0x67, 0xd6, 0x2e, 0x90,
+ 0x2c, 0x5f, 0x39, 0x48, 0xd6, 0x2a, 0x4f, 0x53, 0xe3, 0x9c, 0x17, 0xbf,
+ 0xc0, 0x7d, 0x69, 0xfa, 0x02, 0xc5, 0xc2, 0x8e, 0x58, 0xbc, 0x53, 0xb2,
+ 0xc5, 0xd3, 0xf5, 0x8a, 0x73, 0x69, 0xc1, 0xdb, 0xe9, 0x00, 0x19, 0x62,
+ 0xff, 0xf6, 0x75, 0x02, 0x17, 0x99, 0xca, 0x46, 0xb1, 0x4e, 0x7d, 0x7e,
+ 0x22, 0xbf, 0xb8, 0x22, 0xf3, 0xc1, 0x62, 0xfe, 0x39, 0x64, 0xc7, 0xc4,
+ 0xb1, 0x60, 0x2c, 0x54, 0x9e, 0x1b, 0x98, 0xdd, 0xe8, 0x2c, 0x5e, 0x69,
+ 0xe9, 0x62, 0xa3, 0x45, 0x6a, 0xb8, 0x55, 0xb9, 0x7e, 0x98, 0xfe, 0xea,
+ 0x02, 0xe2, 0x35, 0xe2, 0x7f, 0xa1, 0x16, 0x22, 0x18, 0xe7, 0x10, 0xc8,
+ 0x3b, 0x86, 0x2f, 0xb5, 0x9d, 0x71, 0x62, 0xfb, 0x0f, 0x31, 0xeb, 0x15,
+ 0xa3, 0xc9, 0xe1, 0x25, 0xe6, 0xf7, 0x16, 0x2f, 0x88, 0x5e, 0xe2, 0xc5,
+ 0xff, 0xe8, 0x1c, 0xa7, 0x52, 0x3c, 0x8a, 0x7e, 0xb1, 0x5b, 0x1f, 0x6e,
+ 0x88, 0xe9, 0xd1, 0x5a, 0xd0, 0x8a, 0xbd, 0xbb, 0x71, 0x62, 0xe0, 0xfa,
+ 0x58, 0xac, 0x37, 0x1f, 0x1e, 0xba, 0x7b, 0x2c, 0x5e, 0x13, 0x71, 0x62,
+ 0x86, 0x6d, 0xbb, 0x0c, 0xd9, 0xd6, 0x2f, 0xfa, 0x7d, 0xce, 0x7a, 0x7a,
+ 0x09, 0x62, 0xf3, 0x85, 0xdf, 0xac, 0x5e, 0xfe, 0x6c, 0xb1, 0x67, 0xd1,
+ 0xe0, 0xfc, 0x8e, 0xdd, 0x2c, 0x54, 0x13, 0x9f, 0xc5, 0xe7, 0x56, 0x88,
+ 0x8f, 0x42, 0x3f, 0x7d, 0x0c, 0x9e, 0xff, 0xcf, 0xfe, 0xa1, 0x9e, 0xce,
+ 0xbc, 0xb1, 0x7f, 0xbf, 0x87, 0xc6, 0xd6, 0xcb, 0x15, 0x03, 0xf5, 0x1a,
+ 0x0d, 0xd1, 0xa1, 0x2c, 0x5f, 0xbd, 0xe6, 0x87, 0x16, 0x2f, 0x66, 0xa5,
+ 0x62, 0xf1, 0x61, 0xd6, 0x23, 0x8b, 0xcb, 0xd2, 0x52, 0xb1, 0x7e, 0x1e,
+ 0x44, 0xc0, 0x58, 0xbf, 0xf0, 0xb3, 0xa1, 0xf6, 0xfe, 0x34, 0x4b, 0x15,
+ 0xd2, 0x3e, 0xa2, 0x45, 0xf9, 0x70, 0x86, 0xfb, 0x14, 0xdf, 0xec, 0xeb,
+ 0xbb, 0xf9, 0xd4, 0x16, 0x2d, 0x05, 0x8b, 0xdd, 0x71, 0x96, 0x2f, 0xb3,
+ 0x02, 0xe2, 0xc5, 0x49, 0xe9, 0xe0, 0x97, 0x87, 0xad, 0xd9, 0x62, 0xe1,
+ 0x12, 0xc5, 0xbb, 0xf5, 0x8b, 0x76, 0x58, 0xa9, 0x55, 0x2b, 0xb1, 0x16,
+ 0x46, 0x2d, 0x12, 0x76, 0xa1, 0x18, 0x02, 0xde, 0x0a, 0x78, 0x5f, 0xb0,
+ 0xbd, 0xf7, 0xbf, 0x80, 0x58, 0xbd, 0x3e, 0xe2, 0xc5, 0xb7, 0x93, 0xc0,
+ 0xf1, 0x1d, 0xfc, 0x1e, 0x6b, 0x32, 0x25, 0x8a, 0x23, 0xd7, 0xe1, 0x45,
+ 0xfb, 0xae, 0x4e, 0xb8, 0xb1, 0x7f, 0xba, 0xf6, 0x7f, 0xf9, 0x12, 0xc5,
+ 0xb1, 0x62, 0xb4, 0x78, 0xfd, 0xf9, 0xb5, 0xee, 0x77, 0x1a, 0xb1, 0x6d,
+ 0xd6, 0x2c, 0x4b, 0x15, 0xf3, 0x48, 0x42, 0x77, 0xc0, 0xe0, 0x71, 0xeb,
+ 0x17, 0xfb, 0xdc, 0x18, 0x9b, 0x50, 0x58, 0xac, 0x3d, 0xd6, 0x28, 0xbf,
+ 0xdb, 0x75, 0x0e, 0x13, 0xc4, 0xb1, 0x7f, 0x7d, 0x88, 0x61, 0xf4, 0xb1,
+ 0x7d, 0xe2, 0x16, 0xcb, 0x15, 0x28, 0x8b, 0x73, 0x72, 0x30, 0xa9, 0x54,
+ 0xa9, 0x84, 0x2e, 0xe3, 0xa2, 0x76, 0x46, 0x27, 0xd1, 0x42, 0xae, 0xfe,
+ 0xd4, 0x01, 0x99, 0x12, 0xc5, 0xc2, 0x0d, 0x62, 0xff, 0xb0, 0x82, 0xc2,
+ 0x1f, 0xe5, 0x62, 0xe7, 0x8e, 0x58, 0xb7, 0x72, 0xc5, 0x9a, 0x4d, 0x78,
+ 0x86, 0xaf, 0xdf, 0x7e, 0xd2, 0x4b, 0x17, 0x30, 0x6b, 0x14, 0x33, 0xc1,
+ 0x11, 0x4d, 0xdc, 0x89, 0x62, 0xf6, 0x83, 0xe2, 0xc5, 0x62, 0x6d, 0xe6,
+ 0x97, 0xee, 0x33, 0xa6, 0x72, 0x66, 0xf1, 0x17, 0x61, 0x9b, 0xb0, 0xd5,
+ 0x8b, 0x9f, 0x4b, 0x15, 0x26, 0xbf, 0xe3, 0x17, 0xfc, 0x50, 0xe1, 0x8c,
+ 0x6f, 0xdd, 0x62, 0xff, 0x1b, 0xa9, 0x1f, 0xe7, 0xb2, 0xc5, 0x0d, 0x12,
+ 0x58, 0x41, 0xc3, 0xbb, 0xfc, 0xfc, 0xc1, 0xb4, 0x1d, 0x62, 0xff, 0xfc,
+ 0x5e, 0x2c, 0xe0, 0x4c, 0x5b, 0x7b, 0xf8, 0x4b, 0x17, 0xc2, 0x8a, 0x7a,
+ 0x58, 0xbe, 0x80, 0x7f, 0x95, 0x8b, 0xf9, 0xe2, 0x72, 0x10, 0x6b, 0x17,
+ 0xfe, 0x29, 0x3c, 0xbc, 0x0a, 0x77, 0x58, 0xba, 0x60, 0xb1, 0x7c, 0xfd,
+ 0xa6, 0x25, 0x8a, 0xd1, 0xbc, 0xf8, 0xbd, 0x4a, 0x6c, 0xfb, 0xaa, 0xb1,
+ 0x29, 0x12, 0x78, 0xbf, 0xb3, 0xcd, 0xe7, 0xd4, 0x4b, 0x17, 0xbc, 0xfb,
+ 0x2c, 0x58, 0xf8, 0x6f, 0x3c, 0x3d, 0x68, 0xf5, 0x8a, 0x93, 0x76, 0xc4,
+ 0xd7, 0xc1, 0xcf, 0x77, 0x16, 0x2d, 0xc5, 0x8b, 0xfc, 0x53, 0xd7, 0x5c,
+ 0x68, 0xf5, 0x8b, 0xef, 0xb8, 0x5c, 0x58, 0xbf, 0xe2, 0x63, 0xf3, 0x0f,
+ 0x31, 0xeb, 0x17, 0xe9, 0x1e, 0x34, 0x7a, 0xc5, 0x11, 0xf2, 0xf6, 0x3b,
+ 0xbf, 0xf3, 0xec, 0xc5, 0xf6, 0xe4, 0xc7, 0xac, 0x5e, 0x37, 0x23, 0xd6,
+ 0x29, 0x62, 0xef, 0xc9, 0xa6, 0xb7, 0xe4, 0x34, 0xb1, 0x6c, 0x19, 0xb9,
+ 0x39, 0x6d, 0xe7, 0x0a, 0x3d, 0x62, 0xec, 0x02, 0xc5, 0x68, 0xdc, 0x11,
+ 0x0d, 0x62, 0x7a, 0x2f, 0x08, 0x9f, 0x91, 0x94, 0x29, 0xf8, 0xbd, 0x7f,
+ 0xfb, 0x4e, 0x79, 0xeb, 0xf2, 0x32, 0x68, 0xf5, 0x8a, 0x1a, 0xae, 0x1c,
+ 0x27, 0x38, 0x97, 0x25, 0x04, 0xf9, 0x4a, 0xff, 0xf9, 0xa0, 0x06, 0x06,
+ 0x75, 0xee, 0x72, 0x40, 0xb1, 0x7d, 0xbf, 0xe7, 0x4b, 0x17, 0xdb, 0xfe,
+ 0x42, 0x58, 0xbc, 0xf9, 0xa5, 0x8a, 0xe8, 0xf9, 0x63, 0xc9, 0x03, 0x25,
+ 0xbf, 0xc0, 0x13, 0x07, 0xf9, 0x82, 0xc5, 0x4b, 0x20, 0xc3, 0x23, 0x28,
+ 0xdc, 0xbd, 0xe3, 0x99, 0xfc, 0x33, 0xda, 0x58, 0x01, 0x29, 0x0a, 0x16,
+ 0xc1, 0x1a, 0x5a, 0x0b, 0x16, 0x95, 0x8a, 0x93, 0x46, 0x42, 0x57, 0xdf,
+ 0x9e, 0xbb, 0x96, 0x2d, 0xdc, 0xb1, 0x5b, 0x9b, 0xc7, 0x27, 0xa1, 0x9f,
+ 0xe7, 0x4b, 0x76, 0x1a, 0xc5, 0xf8, 0x98, 0xf3, 0xf5, 0x8a, 0xc3, 0x72,
+ 0xe2, 0x57, 0xff, 0xa4, 0xf3, 0x01, 0x94, 0xfd, 0xb3, 0x4b, 0x17, 0x1e,
+ 0x56, 0x2f, 0x7e, 0x63, 0xd6, 0x2e, 0x16, 0x2c, 0x58, 0x96, 0x29, 0x62,
+ 0xa0, 0x8b, 0x3c, 0x48, 0xdc, 0x5c, 0x04, 0x1e, 0x17, 0x8e, 0x11, 0xbe,
+ 0x17, 0xb8, 0x05, 0x8b, 0xe9, 0xfc, 0xc7, 0xac, 0x5f, 0x77, 0x39, 0x7d,
+ 0x62, 0x86, 0x7d, 0xc4, 0x49, 0xdc, 0x4b, 0x7b, 0xd8, 0x05, 0x8b, 0xf8,
+ 0xef, 0xce, 0x38, 0xd6, 0x2f, 0x36, 0x8d, 0x58, 0xa1, 0x1e, 0x60, 0x45,
+ 0xd7, 0xf1, 0x67, 0x62, 0xce, 0x2c, 0x5c, 0xfa, 0x58, 0xad, 0xcf, 0x17,
+ 0xe5, 0xd6, 0xe2, 0xc5, 0xfe, 0x8f, 0x30, 0x39, 0x26, 0x35, 0x62, 0xff,
+ 0x41, 0xb0, 0xb3, 0xdc, 0x58, 0xbf, 0xb8, 0xc1, 0xcf, 0x4c, 0xb1, 0x7e,
+ 0xcc, 0x2e, 0xbc, 0xb1, 0x7f, 0xb3, 0xe5, 0x9e, 0xfb, 0xac, 0x50, 0xcf,
+ 0x6b, 0xc5, 0x15, 0x29, 0x94, 0x60, 0x97, 0x47, 0x2c, 0x64, 0x08, 0x44,
+ 0xde, 0x96, 0xd2, 0xc5, 0xff, 0x05, 0x3c, 0x78, 0x39, 0x62, 0xc5, 0xf6,
+ 0x10, 0x38, 0xb1, 0x43, 0x3f, 0x6c, 0x1c, 0xe1, 0xc5, 0xe3, 0xf3, 0x8b,
+ 0x14, 0xb1, 0x7b, 0xef, 0x12, 0xc5, 0x8e, 0xe6, 0xa9, 0x83, 0x2a, 0x4f,
+ 0xb5, 0x92, 0x2f, 0xfd, 0x9d, 0x43, 0xf3, 0xc3, 0x7f, 0x2b, 0x15, 0x2b,
+ 0xc0, 0x70, 0x5c, 0xea, 0x1a, 0x4f, 0x0c, 0x88, 0x8c, 0x74, 0xd3, 0xf6,
+ 0x82, 0x8d, 0x2f, 0x90, 0xc4, 0xf4, 0x26, 0xfb, 0x88, 0x2f, 0xa2, 0x29,
+ 0x3a, 0xc5, 0xff, 0x43, 0xed, 0x07, 0xd3, 0xf1, 0x62, 0xff, 0xc3, 0xfc,
+ 0xec, 0xe7, 0x38, 0xb7, 0x58, 0xbe, 0x04, 0xfe, 0x25, 0x8b, 0xbf, 0x19,
+ 0x87, 0xcc, 0x04, 0x2a, 0xe9, 0x19, 0xed, 0x09, 0xfb, 0xef, 0x33, 0x6c,
+ 0xb1, 0x68, 0xe5, 0x8b, 0xa1, 0xc5, 0x8b, 0x34, 0x0d, 0x6f, 0x42, 0xb7,
+ 0xde, 0x72, 0x09, 0x22, 0xc2, 0x58, 0xb4, 0xe1, 0xb5, 0xf9, 0x1d, 0xd9,
+ 0xa5, 0x8b, 0xfc, 0x5e, 0xe7, 0x5c, 0x68, 0xf5, 0x8b, 0xfb, 0x07, 0x1f,
+ 0x9d, 0x47, 0xac, 0x52, 0xc5, 0x31, 0xfc, 0x91, 0xc7, 0x71, 0xad, 0x41,
+ 0x55, 0x5b, 0xc3, 0xca, 0x3c, 0xa1, 0x94, 0x00, 0xb8, 0x44, 0xa2, 0x84,
+ 0x85, 0xe0, 0xfe, 0x25, 0x8b, 0xf7, 0x5c, 0x92, 0xd9, 0x62, 0xff, 0x85,
+ 0x17, 0x5c, 0x98, 0x9f, 0xb2, 0xc5, 0x61, 0xf4, 0x9c, 0xaa, 0xf7, 0x0c,
+ 0x89, 0x62, 0xff, 0xa6, 0x3f, 0x08, 0x50, 0xce, 0x2c, 0x5f, 0xe7, 0xe7,
+ 0xd8, 0xa6, 0x56, 0x2e, 0x17, 0xd6, 0x2f, 0xf1, 0x6f, 0xef, 0x34, 0x38,
+ 0xb1, 0x5b, 0x22, 0xe7, 0x47, 0x67, 0x31, 0x10, 0xc5, 0xff, 0xf6, 0x7f,
+ 0xa8, 0x72, 0x28, 0x39, 0x7a, 0x40, 0xb1, 0x7f, 0x49, 0xca, 0x7a, 0x82,
0xc5, 0x3a, 0x20, 0x3e, 0xa5, 0x71, 0x6e, 0xb1, 0x7b, 0x5a, 0xc5, 0x8b,
- 0xdd, 0xc3, 0x8b, 0x16, 0x7e, 0x1b, 0xc0, 0xc7, 0x6b, 0x0f, 0xef, 0xea,
- 0x97, 0xfc, 0x0f, 0x7f, 0x08, 0x9b, 0xcb, 0x17, 0xdb, 0x1d, 0xbc, 0xb1,
- 0x7f, 0xe9, 0x0f, 0xec, 0x3f, 0xc9, 0x6c, 0xb1, 0x52, 0x7c, 0x9a, 0x24,
- 0xbe, 0xd6, 0x30, 0x45, 0x8b, 0xf1, 0x60, 0xbd, 0xc5, 0x8b, 0xd2, 0x1c,
- 0x16, 0x2f, 0xf7, 0xb9, 0xac, 0xe4, 0xf6, 0xb1, 0x6c, 0x58, 0xac, 0x3c,
- 0x62, 0x35, 0xbd, 0xa9, 0x3a, 0xc5, 0xec, 0x6d, 0xd6, 0x2b, 0x74, 0x5f,
- 0x3b, 0x26, 0x88, 0x08, 0x76, 0xff, 0xd2, 0x19, 0x9b, 0x73, 0x0f, 0x31,
- 0xeb, 0x15, 0xb2, 0xbb, 0x51, 0xc2, 0xbf, 0x78, 0x4e, 0xb9, 0x0c, 0x50,
- 0x9c, 0xd1, 0x09, 0xc9, 0x3f, 0x0e, 0x6f, 0x1e, 0x5d, 0xce, 0xd6, 0x2e,
- 0x0e, 0x25, 0x8b, 0xa1, 0x1e, 0xb1, 0x76, 0x71, 0x62, 0xe0, 0x9a, 0x58,
- 0xa9, 0x5d, 0x69, 0xc9, 0xc5, 0x47, 0x84, 0xb1, 0xc6, 0x58, 0x68, 0xc1,
- 0xb0, 0x82, 0xf7, 0x7c, 0x6b, 0x17, 0xff, 0x6b, 0x71, 0x30, 0xf0, 0x87,
- 0xf7, 0x58, 0xbf, 0x67, 0xfb, 0x87, 0x16, 0x2f, 0xf8, 0x4d, 0xc1, 0xfc,
- 0x4c, 0x6a, 0xc5, 0xf8, 0xf1, 0x9b, 0xf4, 0x0d, 0x62, 0x9d, 0x12, 0xdf,
- 0x2a, 0x30, 0xee, 0xe3, 0xca, 0xc5, 0xf0, 0xc5, 0x3f, 0x58, 0xbc, 0xfd,
- 0x31, 0x62, 0xff, 0xb7, 0x26, 0xe7, 0x05, 0x3b, 0xac, 0x56, 0x22, 0x4f,
- 0x42, 0xfe, 0x23, 0x10, 0xf5, 0xfe, 0xfb, 0xf7, 0xed, 0x6a, 0x56, 0x2e,
- 0x33, 0x75, 0x8b, 0xff, 0x33, 0xfa, 0x18, 0x69, 0x60, 0x16, 0x2f, 0xdd,
- 0xc0, 0xb0, 0x6b, 0x17, 0xf3, 0xfa, 0x28, 0x4f, 0x6b, 0x15, 0x04, 0x58,
- 0xfc, 0x68, 0x8f, 0xba, 0x14, 0xdd, 0x81, 0xac, 0x52, 0xc5, 0x7c, 0xd2,
- 0x78, 0x62, 0xff, 0x42, 0x7b, 0xc3, 0xce, 0xeb, 0x17, 0x31, 0xd6, 0x2f,
- 0xe7, 0xe7, 0xde, 0x5d, 0x62, 0xff, 0xfc, 0x59, 0x9b, 0xfe, 0x63, 0xcb,
- 0x3d, 0x8e, 0x05, 0x8a, 0x3a, 0x20, 0x98, 0xb2, 0xe7, 0x8e, 0x58, 0xbf,
- 0x77, 0x3c, 0x68, 0xf5, 0x8b, 0x61, 0xcf, 0x18, 0x86, 0xaf, 0xc5, 0x14,
- 0xfe, 0x56, 0x29, 0x62, 0xec, 0x1a, 0xc5, 0xc0, 0x6e, 0xcd, 0x1f, 0x40,
- 0xcb, 0xfb, 0xdc, 0xf9, 0x30, 0x16, 0x2f, 0x76, 0xd1, 0xeb, 0x17, 0xf9,
- 0xb6, 0xfb, 0xf4, 0xc8, 0x96, 0x2b, 0xe7, 0xb0, 0x19, 0x0d, 0x4a, 0x2a,
- 0x72, 0x10, 0xd7, 0xc0, 0xe4, 0x92, 0xc5, 0xfe, 0xd7, 0xd9, 0xf8, 0xfd,
- 0x16, 0x2e, 0x35, 0xd6, 0x2a, 0x4f, 0xbf, 0x08, 0x98, 0xd6, 0xff, 0xd8,
- 0x44, 0xde, 0xeb, 0x09, 0x3a, 0xc5, 0xb7, 0x58, 0xaf, 0x9e, 0x90, 0x8f,
- 0xef, 0xcd, 0xe1, 0x31, 0x8b, 0x17, 0xff, 0xfc, 0x22, 0x86, 0x0f, 0xf3,
- 0xd3, 0xc5, 0x93, 0xf7, 0xc2, 0x58, 0xa8, 0xd1, 0x7e, 0x76, 0x46, 0x07,
- 0x0d, 0xbc, 0x86, 0x1e, 0xe7, 0x8f, 0x0e, 0x68, 0xf6, 0x28, 0x88, 0x74,
- 0x6a, 0x78, 0x4c, 0xfd, 0xa1, 0x89, 0x80, 0x96, 0x50, 0xd8, 0xe4, 0x25,
- 0x7c, 0xfc, 0x22, 0x23, 0x0a, 0x6f, 0xe0, 0xe7, 0x5a, 0x68, 0x96, 0x2f,
- 0xf8, 0x73, 0xb9, 0x80, 0x04, 0xf6, 0xb1, 0x7b, 0x8d, 0xda, 0xc5, 0xee,
- 0x31, 0x2c, 0x5f, 0xf3, 0x6b, 0x0e, 0xf1, 0xd2, 0x75, 0x8a, 0xdd, 0x16,
- 0x4e, 0x7b, 0xc1, 0xe1, 0x0e, 0x5f, 0x37, 0x23, 0xcc, 0x58, 0xbf, 0x76,
- 0x31, 0xbf, 0x16, 0x2f, 0x6b, 0x38, 0xb1, 0x7c, 0x73, 0x20, 0xeb, 0x15,
- 0x27, 0xd7, 0x85, 0x4e, 0x3b, 0x7d, 0xe9, 0xee, 0x0b, 0x17, 0xf3, 0x82,
- 0x38, 0x9c, 0x0b, 0x17, 0x60, 0x16, 0x2b, 0x63, 0xeb, 0xd1, 0x21, 0x18,
- 0x5e, 0x27, 0x95, 0x8b, 0xf7, 0x23, 0xb3, 0x46, 0xac, 0x5a, 0x7b, 0x3c,
- 0x8f, 0x0d, 0xdf, 0xf9, 0x9f, 0xd9, 0xa0, 0x1d, 0xa0, 0xb1, 0x7f, 0x67,
- 0xbe, 0xc3, 0x75, 0x8a, 0xf9, 0xf5, 0xc7, 0x1f, 0x5e, 0x23, 0x7e, 0xb1,
- 0x78, 0x7f, 0x75, 0x8a, 0x73, 0xe0, 0x62, 0x51, 0x0f, 0x5f, 0x4e, 0xb5,
- 0x2b, 0x17, 0xf1, 0x30, 0x78, 0x40, 0x58, 0xad, 0x8f, 0x3e, 0x22, 0x2b,
- 0xc5, 0x3b, 0x2c, 0x53, 0x1e, 0x09, 0x12, 0x5e, 0xf6, 0x18, 0xb1, 0x52,
- 0xb9, 0x5b, 0x90, 0xe2, 0x34, 0xf7, 0xf0, 0x92, 0x68, 0x4b, 0x93, 0xbf,
- 0x21, 0xe6, 0x28, 0x5e, 0x84, 0x20, 0xb0, 0x96, 0x2f, 0x82, 0x34, 0xe9,
- 0x62, 0xfe, 0x29, 0x84, 0xf4, 0x95, 0x8b, 0x01, 0x62, 0xfc, 0x6b, 0x10,
- 0xa2, 0x58, 0xa9, 0x37, 0x82, 0x12, 0xbe, 0x13, 0x84, 0x3a, 0xc5, 0xfd,
- 0xd3, 0x4d, 0x2f, 0x1c, 0xb1, 0x7f, 0x40, 0xb3, 0xfb, 0x4a, 0xc5, 0xb6,
- 0x58, 0xae, 0xcf, 0x05, 0xcb, 0xad, 0x8b, 0x15, 0x89, 0xc5, 0xf6, 0x24,
- 0xe4, 0x91, 0x35, 0x68, 0x80, 0xe4, 0xac, 0xe6, 0x44, 0x57, 0xdd, 0xec,
- 0x31, 0x2c, 0x5b, 0x75, 0x8b, 0xa3, 0xb6, 0x58, 0xbd, 0xd1, 0xf4, 0xb1,
- 0x43, 0x37, 0x7f, 0x1c, 0xbc, 0xe2, 0xd2, 0xc5, 0xc5, 0x05, 0x8a, 0x94,
- 0x64, 0x8c, 0x9b, 0x13, 0xb8, 0x43, 0xd0, 0x76, 0xf8, 0x72, 0xda, 0x58,
- 0xbf, 0xa1, 0xf7, 0xe9, 0x83, 0x58, 0xad, 0x1e, 0x91, 0x11, 0x5a, 0x56,
- 0x2c, 0xeb, 0x14, 0xc7, 0x86, 0x44, 0x21, 0x88, 0xde, 0xcd, 0x4a, 0xc5,
- 0xf4, 0x41, 0xc9, 0xab, 0x17, 0xc6, 0x99, 0x17, 0x16, 0x2d, 0xf5, 0x8b,
- 0x4a, 0xc5, 0xbc, 0xe6, 0x8c, 0x20, 0x95, 0x68, 0xfc, 0x89, 0x2a, 0xd1,
- 0xcb, 0x17, 0x66, 0xeb, 0x14, 0xc6, 0xb7, 0xc2, 0xb7, 0xa3, 0xa4, 0xeb,
- 0x15, 0xb1, 0xe0, 0x1a, 0x41, 0x7f, 0x98, 0xd3, 0x3f, 0xf9, 0x82, 0xc5,
- 0x4a, 0x73, 0x98, 0x38, 0xf0, 0x98, 0x68, 0x47, 0x47, 0x12, 0x5f, 0xfb,
- 0xf8, 0x31, 0xbf, 0x79, 0xdf, 0x96, 0x2f, 0xee, 0xa3, 0x31, 0xb5, 0xa5,
- 0x8b, 0x4a, 0xc5, 0x6c, 0x88, 0x41, 0xa0, 0xc4, 0x65, 0x7f, 0x87, 0x9e,
- 0xfc, 0x96, 0xeb, 0x17, 0xa5, 0xe3, 0x96, 0x2f, 0xbd, 0xc3, 0x0e, 0xb1,
- 0x4c, 0x78, 0x82, 0x1f, 0xbf, 0xf8, 0xdc, 0xef, 0x9f, 0xce, 0x99, 0xee,
- 0x2c, 0x5a, 0x0b, 0x17, 0xfe, 0x79, 0x39, 0xe5, 0xf9, 0x86, 0x2c, 0x5f,
- 0xf8, 0xa7, 0xbe, 0x49, 0xdb, 0xbf, 0x2c, 0x51, 0xa8, 0xd9, 0x8f, 0x49,
- 0xe0, 0x97, 0x43, 0xeb, 0xff, 0xfe, 0x04, 0x96, 0xed, 0xf2, 0x60, 0x6a,
- 0x77, 0xcd, 0x69, 0xd6, 0x2f, 0xf7, 0x3a, 0x37, 0x24, 0xa2, 0x58, 0xbf,
- 0x8d, 0xf3, 0xfb, 0x34, 0xb1, 0x68, 0x96, 0x2f, 0xf8, 0x7d, 0x73, 0x93,
- 0x9a, 0x02, 0xc5, 0xef, 0x99, 0xc5, 0x8a, 0x93, 0xed, 0xc1, 0x36, 0x3b,
- 0xbe, 0xe7, 0x1c, 0xeb, 0x17, 0xb9, 0xf7, 0x58, 0xbf, 0x87, 0xe2, 0x6e,
- 0xf8, 0xb1, 0x4b, 0x14, 0xe6, 0xec, 0x21, 0x7d, 0x2c, 0x5f, 0xdc, 0x7e,
- 0xf3, 0xbf, 0x2c, 0x57, 0x66, 0xf3, 0xc1, 0x97, 0x1c, 0x6b, 0x17, 0x6d,
- 0x2b, 0x15, 0x28, 0xb0, 0x65, 0xef, 0x11, 0x08, 0x62, 0xe7, 0x82, 0xc5,
- 0xf8, 0x36, 0xd3, 0x76, 0xb1, 0x7a, 0x73, 0xb5, 0x8a, 0x93, 0xc7, 0x22,
- 0xab, 0x04, 0x58, 0xbe, 0xce, 0x38, 0x16, 0x29, 0x62, 0xd1, 0x2c, 0x44,
- 0x4c, 0xa9, 0x5d, 0x93, 0xd8, 0xc8, 0x6f, 0x19, 0x0f, 0xae, 0xd0, 0xe2,
- 0x66, 0xd1, 0xb7, 0xe1, 0x38, 0xc5, 0x80, 0x23, 0x28, 0xc2, 0x38, 0x77,
- 0xe5, 0xe0, 0xc8, 0x23, 0x85, 0x0c, 0x2e, 0xbf, 0xe8, 0x3f, 0x81, 0x3f,
- 0x33, 0x8b, 0x17, 0xe8, 0x7e, 0x48, 0xd5, 0x8b, 0x84, 0x05, 0x8a, 0x88,
- 0xff, 0x18, 0xec, 0x21, 0x4d, 0x05, 0x1f, 0x68, 0x00, 0x2a, 0xf5, 0x1a,
- 0x42, 0x0e, 0x36, 0x27, 0x0b, 0x70, 0xc1, 0x0b, 0x54, 0x09, 0x95, 0x57,
- 0xb4, 0x61, 0x10, 0x8f, 0xb0, 0x72, 0xf3, 0x32, 0x7b, 0x3c, 0xd8, 0xf3,
- 0x77, 0x96, 0xf9, 0xdc, 0xa6, 0xb7, 0x96, 0x3d, 0x1f, 0x0f, 0x28, 0xa5,
- 0x36, 0xea, 0x58, 0x69, 0xe5, 0x3a, 0x7e, 0x90, 0x4e, 0xd3, 0xcc, 0xe0,
- 0x96, 0x36, 0x17, 0x70, 0x29, 0xdf, 0x1e, 0x52, 0x04, 0x3d, 0x3b, 0x8e,
- 0x29, 0x44, 0x9d, 0x23, 0x39, 0x0e, 0x1b, 0xf1, 0xd1, 0xe5, 0x19, 0x3c,
- 0xd6, 0x12, 0x36, 0xcb, 0xb7, 0x95, 0x8b, 0xe6, 0xde, 0x74, 0xb1, 0x41,
- 0x9b, 0xb0, 0x83, 0x17, 0xe9, 0xef, 0x1f, 0xeb, 0x17, 0x07, 0x8b, 0x17,
- 0xf0, 0x27, 0xfd, 0xc3, 0x8b, 0x17, 0xf9, 0xfb, 0x03, 0x7f, 0x23, 0x96,
- 0x2f, 0xfc, 0xf3, 0xef, 0xb1, 0xb8, 0x40, 0x58, 0xbf, 0xfc, 0xda, 0xea,
- 0xde, 0xeb, 0xee, 0xf7, 0x72, 0x58, 0xad, 0xd3, 0x35, 0x72, 0x88, 0x86,
- 0x34, 0x61, 0xf3, 0x7e, 0x87, 0xd7, 0xee, 0x45, 0x9a, 0x65, 0x8b, 0xe9,
- 0xdd, 0x99, 0x62, 0xf6, 0xb2, 0x0b, 0x17, 0x39, 0xd6, 0x29, 0xcf, 0xfc,
- 0xe5, 0x3e, 0x22, 0x08, 0x3b, 0x7f, 0x67, 0xa5, 0xcf, 0xc5, 0x8b, 0xd2,
- 0x07, 0x58, 0xbf, 0xa6, 0x19, 0xac, 0xe2, 0xc5, 0xfb, 0xf9, 0xe9, 0xfa,
- 0xc5, 0xf8, 0xbc, 0x42, 0xd9, 0x62, 0x86, 0x7f, 0xcc, 0x5a, 0x22, 0x8b,
- 0xff, 0xda, 0xd0, 0xa1, 0xac, 0x9e, 0xe0, 0xe7, 0x58, 0xbe, 0x37, 0xcf,
- 0xa5, 0x8b, 0xa2, 0x75, 0x8a, 0xc4, 0x44, 0x3a, 0x63, 0x12, 0x5e, 0xe1,
- 0x9c, 0x58, 0xbf, 0xff, 0x64, 0xf7, 0x0e, 0x7f, 0x3d, 0xc2, 0x6e, 0xfc,
- 0xb1, 0x7f, 0xf4, 0x3c, 0x2d, 0xa3, 0x3e, 0xc7, 0x7e, 0x2c, 0x5e, 0xdd,
- 0xba, 0x2c, 0x5f, 0xfb, 0xe2, 0xef, 0x92, 0x76, 0xef, 0xcb, 0x16, 0xc3,
- 0x53, 0x03, 0xed, 0x5f, 0x49, 0x5e, 0x20, 0xbf, 0xf7, 0xa4, 0xfc, 0x97,
- 0xd9, 0xbc, 0xb1, 0x7f, 0x34, 0x7b, 0x67, 0x7e, 0x58, 0xae, 0xcf, 0xc3,
- 0xe7, 0xf7, 0xf6, 0x0d, 0xfb, 0x26, 0x58, 0xbe, 0x73, 0x64, 0x22, 0xc5,
- 0x31, 0xe9, 0x11, 0x6d, 0x62, 0x25, 0x44, 0xeb, 0x63, 0x56, 0x2f, 0xd9,
- 0xe2, 0x9d, 0x96, 0x28, 0x66, 0xef, 0x42, 0x77, 0xd3, 0xe8, 0x32, 0xc5,
- 0xf6, 0x82, 0x49, 0x2c, 0x58, 0x96, 0x2a, 0x4d, 0xa8, 0x64, 0x97, 0xfd,
- 0xce, 0x8d, 0x13, 0x8c, 0x5a, 0x58, 0xbf, 0xff, 0xe9, 0x01, 0xda, 0x05,
- 0x9d, 0xf9, 0xbf, 0x3e, 0xe0, 0xa3, 0xd6, 0x2e, 0x29, 0x58, 0xa8, 0x91,
- 0x7b, 0xf3, 0xdf, 0x35, 0x5d, 0xf8, 0xc9, 0x64, 0x35, 0x64, 0x6b, 0x2f,
- 0x0d, 0xa8, 0x8f, 0x74, 0x5a, 0x78, 0x4d, 0x7e, 0x16, 0xcc, 0x5a, 0x51,
- 0x91, 0x72, 0x34, 0xaf, 0x2e, 0xf4, 0x21, 0x0d, 0x5c, 0xc8, 0x6f, 0x54,
- 0x63, 0x30, 0xd2, 0x69, 0x67, 0x97, 0xf6, 0x6b, 0x76, 0x6d, 0xd5, 0x16,
- 0x69, 0x7f, 0xfe, 0x6d, 0x34, 0x23, 0x37, 0x2c, 0xdb, 0x5d, 0xc8, 0xd6,
- 0x2e, 0xc3, 0xac, 0x5f, 0x7b, 0x53, 0xc5, 0x8a, 0xdc, 0xdd, 0x10, 0xbd,
- 0xfe, 0xce, 0x72, 0x40, 0x66, 0xcb, 0x17, 0xe7, 0xd0, 0x79, 0xf5, 0x8b,
- 0xef, 0xbb, 0x12, 0xc5, 0x7c, 0xf2, 0xbc, 0x53, 0x7f, 0xfd, 0xf7, 0xe3,
- 0xf8, 0xb3, 0xa0, 0xe6, 0x2f, 0xac, 0x5f, 0xe0, 0x4f, 0x1d, 0xbb, 0x0d,
- 0x62, 0xfd, 0xa7, 0xd8, 0x51, 0xeb, 0x17, 0xbe, 0xe3, 0x58, 0xb0, 0xb0,
- 0xf2, 0xa2, 0x2d, 0xbd, 0x13, 0x0d, 0x62, 0xff, 0xd8, 0xd1, 0x77, 0xee,
- 0xa1, 0xbc, 0xac, 0x54, 0x9f, 0x0e, 0x87, 0xaf, 0xf6, 0x61, 0xa3, 0x27,
- 0xd9, 0x62, 0xff, 0xe3, 0x8b, 0xff, 0x63, 0x73, 0x59, 0xe5, 0x8a, 0x19,
- 0xfd, 0x1c, 0xd2, 0xff, 0xe9, 0xdf, 0x99, 0x31, 0x66, 0xd8, 0x4b, 0x17,
- 0xfb, 0x39, 0x3a, 0xd3, 0xf4, 0x58, 0xad, 0x8f, 0xeb, 0xe8, 0xb5, 0x88,
- 0xbf, 0x68, 0x4e, 0x5e, 0x6c, 0xf2, 0xc5, 0xff, 0xb8, 0xfa, 0xcf, 0x49,
- 0x38, 0x16, 0x2f, 0xf9, 0xe0, 0xff, 0x11, 0xce, 0xeb, 0x17, 0xf3, 0x10,
- 0x3d, 0x31, 0x2c, 0x57, 0x8f, 0x9e, 0x38, 0xe6, 0xfb, 0x5f, 0x68, 0xc9,
- 0x5c, 0x82, 0x19, 0x0e, 0x42, 0x03, 0x72, 0x27, 0x52, 0x3b, 0xff, 0xe1,
- 0x12, 0x51, 0xad, 0x70, 0x9b, 0xc3, 0x86, 0x42, 0x92, 0xf4, 0x42, 0x31,
- 0x62, 0xff, 0xb2, 0x28, 0x36, 0xb6, 0xf8, 0x96, 0x2f, 0xf7, 0xbf, 0x8f,
- 0xb1, 0xe5, 0x62, 0xfe, 0xf1, 0x4e, 0x7d, 0x96, 0x2f, 0xfd, 0x3a, 0x07,
- 0xb9, 0xfc, 0x71, 0xac, 0x59, 0x96, 0x2e, 0x7f, 0xac, 0x54, 0x6e, 0x6a,
- 0x20, 0x23, 0x6d, 0x96, 0x2f, 0x42, 0x7b, 0x58, 0xb6, 0x49, 0xb1, 0x88,
- 0x4e, 0xf9, 0xc9, 0xb6, 0x58, 0xbf, 0xef, 0xbb, 0x03, 0x05, 0xad, 0x96,
- 0x2f, 0xed, 0x8c, 0x8e, 0x62, 0x02, 0xc5, 0xff, 0x98, 0x81, 0x9e, 0x92,
- 0x70, 0x2c, 0x54, 0x9f, 0x7c, 0x71, 0x9d, 0x4a, 0xa8, 0xf1, 0x90, 0x61,
- 0xe7, 0x66, 0x9f, 0x2c, 0x66, 0x72, 0x57, 0xe1, 0x37, 0x88, 0x8c, 0x85,
- 0x4d, 0xbe, 0xb1, 0x7e, 0xfc, 0xf3, 0xee, 0xb1, 0x7f, 0xe7, 0xf4, 0x9c,
- 0x98, 0xdf, 0xba, 0xc5, 0xd3, 0xf5, 0x8b, 0xfc, 0xde, 0x84, 0x9b, 0x84,
- 0xb1, 0x7f, 0x16, 0x74, 0xfb, 0x41, 0x62, 0xf3, 0x6b, 0x8b, 0x16, 0x8c,
- 0xd9, 0x30, 0xec, 0x12, 0x88, 0xa3, 0xe7, 0xc4, 0x2f, 0xe3, 0x30, 0xcb,
- 0xea, 0x31, 0x50, 0x68, 0x48, 0xe7, 0xaf, 0xa7, 0x62, 0x12, 0xc5, 0xff,
- 0xfe, 0xcf, 0x3f, 0x3d, 0xfc, 0x38, 0x1b, 0x59, 0xd3, 0x06, 0xb1, 0x7f,
- 0x84, 0xdb, 0x6b, 0x0f, 0x19, 0xf4, 0x42, 0xf0, 0x8e, 0xa3, 0x19, 0x77,
- 0x7b, 0x9e, 0x3c, 0xe8, 0xbb, 0x4e, 0xb2, 0x14, 0x2d, 0x6e, 0x0a, 0x76,
- 0xb1, 0x78, 0xe6, 0x69, 0x62, 0xf9, 0x8e, 0xc7, 0x58, 0xbf, 0x84, 0x6c,
- 0x86, 0x23, 0x56, 0x29, 0xcf, 0xce, 0x21, 0xf0, 0xc8, 0xae, 0x70, 0xd6,
- 0x2f, 0xe9, 0x0f, 0x3d, 0xc8, 0xf5, 0x8a, 0xf9, 0xe5, 0x10, 0xc5, 0x9d,
- 0x62, 0xfd, 0x3e, 0x8e, 0x73, 0xac, 0x51, 0xcd, 0xe0, 0x04, 0x6e, 0xe1,
- 0xab, 0x17, 0xdc, 0x29, 0x0d, 0x62, 0xf6, 0xf9, 0xf5, 0x8b, 0xb9, 0x2b,
- 0x17, 0xe1, 0x73, 0xd3, 0xc5, 0x8a, 0x81, 0xe0, 0x44, 0x2f, 0x70, 0xb8,
- 0xb1, 0x7d, 0xdb, 0x8b, 0xb5, 0x8a, 0x94, 0x5f, 0x3a, 0xf4, 0x44, 0x62,
- 0x18, 0xbf, 0x8a, 0x4f, 0xc7, 0xd9, 0x62, 0xf1, 0x68, 0x4b, 0x15, 0x03,
- 0xcb, 0x72, 0xeb, 0x83, 0xd2, 0xc5, 0xf8, 0x4e, 0x16, 0x05, 0x42, 0x8b,
- 0x17, 0x9f, 0x0e, 0xb1, 0x78, 0x5d, 0xf1, 0x62, 0xfc, 0x67, 0x8a, 0x40,
- 0xb1, 0x51, 0x1f, 0x26, 0x87, 0x3a, 0x0f, 0xdf, 0xb6, 0x14, 0x05, 0x2b,
- 0x15, 0x27, 0xb8, 0xe6, 0x57, 0xce, 0x77, 0x08, 0xb1, 0x70, 0x8c, 0x58,
- 0xbc, 0x59, 0xc5, 0x8a, 0x93, 0xd9, 0x88, 0x90, 0xc1, 0x9b, 0xcf, 0x21,
- 0xac, 0x5f, 0x7d, 0xfb, 0xe2, 0xc5, 0xd3, 0xda, 0xc5, 0xd3, 0xf5, 0x8b,
- 0xef, 0x3b, 0x18, 0xb1, 0x68, 0xe5, 0x8b, 0x1a, 0xb1, 0x4e, 0x6a, 0x04,
- 0x2b, 0x51, 0xe8, 0xbe, 0x88, 0x90, 0xe3, 0x1c, 0x17, 0x31, 0x2e, 0xf9,
- 0xe3, 0x9c, 0x0b, 0x17, 0x07, 0x2b, 0x17, 0xbc, 0xdf, 0x58, 0xb9, 0xa0,
- 0xb1, 0x4e, 0x6d, 0x0e, 0x3b, 0x63, 0x56, 0x28, 0xd3, 0x67, 0xa2, 0x0b,
- 0x8f, 0x18, 0x14, 0x5e, 0xd2, 0x98, 0x48, 0x0d, 0xeb, 0x17, 0x4d, 0x21,
- 0xec, 0x65, 0xe1, 0xc3, 0x14, 0x21, 0xf4, 0x42, 0x71, 0x9f, 0xc3, 0xd9,
- 0x9e, 0x7c, 0x60, 0x28, 0x6d, 0xf4, 0x4f, 0x0c, 0x94, 0xc7, 0xfb, 0xb1,
- 0xd6, 0x2c, 0x35, 0x8b, 0x1d, 0x62, 0xb0, 0xd2, 0x30, 0x95, 0x89, 0x62,
- 0xff, 0xa1, 0x19, 0x9a, 0xdd, 0x9b, 0x75, 0x45, 0x00, 0x56, 0x1e, 0xe3,
- 0x08, 0xdf, 0xe7, 0x3c, 0xc7, 0xff, 0x36, 0x58, 0xbc, 0xda, 0x35, 0x62,
- 0xff, 0xe8, 0xe6, 0x20, 0x67, 0xa4, 0x9c, 0x0b, 0x16, 0x8c, 0x82, 0x6d,
- 0xf8, 0x74, 0x77, 0xbf, 0x90, 0x06, 0x6e, 0x60, 0xf5, 0xf6, 0x78, 0xcd,
- 0x96, 0x2f, 0xde, 0xe4, 0x8e, 0x56, 0x28, 0xe7, 0x9a, 0x44, 0xb7, 0x40,
- 0xeb, 0x17, 0xf3, 0xf2, 0x22, 0x91, 0xac, 0x52, 0xc5, 0xdd, 0xc1, 0x62,
- 0xbb, 0x34, 0xba, 0x0c, 0xa1, 0x9f, 0xab, 0x29, 0xde, 0x92, 0xdd, 0x62,
- 0xf7, 0x9b, 0x4b, 0x17, 0xc2, 0x3e, 0x7d, 0x62, 0xd3, 0xd9, 0xe0, 0x7c,
- 0x76, 0xff, 0xd3, 0x85, 0xee, 0x4f, 0xa4, 0x6b, 0x17, 0xe9, 0x2c, 0xef,
- 0xcb, 0x17, 0xdc, 0x83, 0x81, 0x62, 0x8e, 0x79, 0x7e, 0x28, 0xb7, 0x45,
- 0x8b, 0x79, 0x62, 0xa0, 0x69, 0xb7, 0x14, 0xbf, 0x9f, 0xf2, 0x53, 0xe5,
- 0x8b, 0x47, 0x2c, 0x58, 0x0b, 0x15, 0x26, 0x9c, 0x42, 0xb7, 0x86, 0xce,
- 0xb1, 0x52, 0xab, 0x56, 0x04, 0x39, 0x08, 0xd3, 0x48, 0x5d, 0x74, 0xe5,
- 0x0d, 0x08, 0x82, 0x48, 0xe1, 0x17, 0x94, 0xc4, 0x41, 0x7a, 0x29, 0x82,
- 0xc5, 0xfe, 0x7f, 0xb1, 0x7b, 0x37, 0x58, 0xb7, 0x96, 0x2a, 0x07, 0x8b,
- 0xa3, 0x3b, 0x46, 0x62, 0x21, 0x78, 0xc7, 0x7f, 0xd3, 0xef, 0xe1, 0xf3,
- 0x58, 0xb1, 0x7d, 0x16, 0x66, 0xeb, 0x17, 0xef, 0x1a, 0xdc, 0x8c, 0xd1,
- 0xee, 0x18, 0x71, 0x50, 0x46, 0x58, 0x70, 0x87, 0xbf, 0xfb, 0xdc, 0x8c,
- 0x0b, 0x71, 0xa8, 0x2b, 0x1a, 0x81, 0xcc, 0x58, 0xbf, 0xf7, 0x3e, 0xf1,
- 0x93, 0xd3, 0xa0, 0xa0, 0xb1, 0x51, 0x8a, 0xb0, 0x26, 0x3f, 0x06, 0x29,
- 0x13, 0x05, 0xf7, 0xc9, 0xbc, 0xb1, 0x77, 0x3c, 0xb1, 0x69, 0x58, 0xb7,
- 0xd6, 0x28, 0xe6, 0x8c, 0x42, 0x37, 0xc1, 0x5e, 0x9d, 0xf1, 0x62, 0xf0,
- 0xf0, 0xeb, 0x17, 0xff, 0x79, 0xc5, 0xc3, 0x0f, 0xad, 0x39, 0xab, 0x17,
- 0xff, 0xee, 0x93, 0xf7, 0x1f, 0xe6, 0x1c, 0x6f, 0xbf, 0x16, 0x2f, 0xfe,
- 0x3b, 0x6b, 0x6f, 0xe4, 0x4c, 0x46, 0xac, 0x5f, 0xf4, 0xfe, 0x76, 0xd4,
- 0xe0, 0xd6, 0x2f, 0xee, 0x49, 0xca, 0x62, 0x58, 0xb7, 0xd6, 0x2f, 0x18,
- 0x51, 0x2c, 0x5b, 0xd8, 0x6c, 0x40, 0x25, 0x76, 0x6c, 0xb1, 0x58, 0x6f,
- 0x88, 0x9a, 0xf9, 0xcf, 0x31, 0x2c, 0x56, 0xca, 0x86, 0xe0, 0x3a, 0xe9,
- 0x07, 0x57, 0xfa, 0x38, 0x0e, 0x4a, 0x13, 0xb1, 0xc3, 0xf7, 0xff, 0x85,
- 0xa8, 0x67, 0x1c, 0x41, 0x72, 0x93, 0xac, 0x5b, 0x8b, 0x17, 0xee, 0x4f,
- 0xdf, 0xa2, 0xc5, 0xfd, 0xf6, 0x6f, 0xcc, 0x16, 0x2f, 0x86, 0xe4, 0x05,
- 0x8a, 0xea, 0x88, 0xbc, 0x12, 0x72, 0xa6, 0x2d, 0xbf, 0xfe, 0xd6, 0xc3,
- 0xfb, 0xeb, 0x93, 0xa8, 0x9f, 0xeb, 0x17, 0xfe, 0x07, 0x09, 0x8d, 0xce,
- 0x8f, 0xa5, 0x8b, 0xff, 0x9f, 0xe2, 0xfb, 0x3f, 0x7c, 0x93, 0x56, 0x2b,
- 0x11, 0x0f, 0xe4, 0x1b, 0xc2, 0x1e, 0x2c, 0x5f, 0xda, 0xf1, 0x49, 0xf8,
- 0xb1, 0x7f, 0xfe, 0xd0, 0xd8, 0x8d, 0xfe, 0x47, 0xe9, 0xcf, 0x26, 0xac,
- 0x56, 0x22, 0x20, 0x45, 0xd6, 0x8e, 0x58, 0xa9, 0x4f, 0x63, 0x21, 0xb4,
- 0xe4, 0x5f, 0x85, 0x28, 0x08, 0xaf, 0x36, 0xb1, 0x62, 0xe1, 0x01, 0x62,
- 0xf7, 0x24, 0x0b, 0x17, 0xd0, 0x72, 0xc5, 0x8a, 0xf1, 0xbe, 0x0c, 0x76,
- 0xfb, 0x76, 0x6d, 0xd5, 0x16, 0xf9, 0x7a, 0x39, 0xbc, 0xb1, 0x7c, 0x66,
- 0x16, 0xeb, 0x17, 0xe9, 0x38, 0x1b, 0xcb, 0x16, 0x7d, 0x1e, 0x61, 0x12,
- 0x5e, 0x8b, 0x00, 0xb1, 0x7e, 0x33, 0x6f, 0xce, 0x96, 0x2b, 0x74, 0xe8,
- 0x3b, 0x1c, 0x75, 0x6d, 0x11, 0x1c, 0xc7, 0xed, 0x8c, 0x4d, 0xe1, 0xeb,
- 0xfe, 0x7f, 0xcf, 0x73, 0x1f, 0x9d, 0xac, 0x5f, 0xe3, 0x36, 0x61, 0xfe,
- 0x78, 0xb1, 0x7f, 0xff, 0xcd, 0x10, 0xdf, 0x5f, 0xc1, 0x94, 0xee, 0xdb,
- 0x14, 0x9d, 0x62, 0xff, 0xb4, 0x2e, 0x7d, 0xa0, 0x07, 0x58, 0xb3, 0x81,
- 0x14, 0x3e, 0x67, 0xbe, 0xf7, 0x1b, 0xcb, 0x17, 0xfe, 0xd6, 0x47, 0xc5,
- 0xf6, 0x3b, 0xf1, 0x62, 0xec, 0xdb, 0x0f, 0x9b, 0x44, 0x75, 0xba, 0x72,
- 0x5f, 0x86, 0xb9, 0x42, 0x3a, 0xfd, 0xe9, 0xdb, 0x06, 0xb1, 0x60, 0xd6,
- 0x2f, 0xf9, 0x8b, 0x7e, 0x4f, 0xda, 0x3d, 0x62, 0xa0, 0x7f, 0x06, 0x94,
- 0xf8, 0x4e, 0xf1, 0x3c, 0x4b, 0x17, 0xf6, 0x44, 0x44, 0xdf, 0x58, 0xac,
- 0x3c, 0xa3, 0x8e, 0xdf, 0x3e, 0x6b, 0xa2, 0xc5, 0xf7, 0x70, 0xda, 0x56,
- 0x2f, 0x48, 0x71, 0xcb, 0x15, 0x87, 0x8d, 0xa2, 0x5b, 0xed, 0xfd, 0x9b,
- 0xac, 0x5e, 0x8e, 0x14, 0xac, 0x52, 0xc5, 0x61, 0xac, 0x22, 0x0a, 0xc3,
- 0xf0, 0xf2, 0x8d, 0xef, 0xce, 0x96, 0x2f, 0xdf, 0x7d, 0x7d, 0x96, 0x2f,
- 0xff, 0x7e, 0x76, 0xf6, 0x7c, 0xb3, 0xdf, 0x75, 0x8b, 0xc7, 0xc1, 0xac,
- 0x58, 0xeb, 0x17, 0xfa, 0x76, 0x1e, 0x07, 0xc8, 0xc9, 0x45, 0xf6, 0x0e,
- 0xc4, 0x50, 0xc9, 0x46, 0x0e, 0xd4, 0x13, 0xe6, 0xc8, 0x48, 0xfe, 0x1b,
- 0xf7, 0x8f, 0x9d, 0xac, 0x5f, 0xfc, 0x4c, 0x0e, 0x0e, 0x7d, 0xc6, 0xd9,
- 0x62, 0x86, 0x7c, 0x7e, 0x1e, 0xbc, 0xfe, 0xe2, 0xc5, 0xed, 0x0a, 0x25,
- 0x8b, 0xdb, 0x31, 0xf4, 0x6f, 0x3c, 0x3b, 0x7d, 0x0e, 0x19, 0xc5, 0x8a,
- 0x94, 0x5b, 0x3a, 0xf7, 0x8c, 0xef, 0xb3, 0xdc, 0xc5, 0x8b, 0xf9, 0xbb,
- 0x1b, 0x96, 0xcb, 0x17, 0xfb, 0x23, 0xf4, 0xe7, 0x93, 0x56, 0x2a, 0x51,
- 0x11, 0xa2, 0x2f, 0x97, 0xde, 0xe7, 0xc6, 0xb1, 0x7e, 0x33, 0xc5, 0x20,
- 0x58, 0xa3, 0x9e, 0x3f, 0x41, 0xeb, 0xfd, 0xbb, 0x6b, 0x6e, 0x9e, 0x12,
- 0xc5, 0xc5, 0x2b, 0x17, 0xff, 0x7b, 0x8f, 0xc9, 0x2c, 0xf7, 0xdd, 0x62,
- 0xff, 0xcc, 0x13, 0x4e, 0x6e, 0x7d, 0xe0, 0xb1, 0x7f, 0xe0, 0x08, 0xb7,
- 0x61, 0xfe, 0x78, 0xb1, 0x70, 0xb1, 0x62, 0xff, 0x80, 0xfe, 0x26, 0xf4,
- 0x8d, 0x62, 0xf1, 0x67, 0xd6, 0x2b, 0x74, 0xdf, 0xb4, 0x72, 0x71, 0x6f,
- 0xa1, 0x81, 0x04, 0x90, 0x38, 0x2f, 0xd0, 0xe2, 0xff, 0x9f, 0x98, 0x39,
- 0x89, 0xce, 0xb1, 0x7e, 0x1c, 0xc7, 0x88, 0xeb, 0x17, 0xfe, 0xcd, 0xb6,
- 0x10, 0xe7, 0x52, 0x35, 0x8b, 0xf7, 0x9f, 0x53, 0xd1, 0x62, 0xff, 0x9b,
- 0x93, 0x84, 0x3f, 0xca, 0xc5, 0xfe, 0xfc, 0x8d, 0xfa, 0x48, 0xd6, 0x2f,
- 0xfb, 0x59, 0xdf, 0xc9, 0xa3, 0xf6, 0x58, 0xb6, 0x0c, 0xfc, 0xce, 0x6b,
- 0x6e, 0x69, 0x1a, 0x25, 0x0a, 0xaa, 0x24, 0xca, 0x39, 0x0f, 0xba, 0x95,
- 0xc0, 0xcc, 0x8e, 0x8b, 0x77, 0x47, 0x39, 0xd1, 0x63, 0x46, 0xd3, 0x7e,
- 0x33, 0x3e, 0xc7, 0x58, 0xb8, 0x46, 0xac, 0x5f, 0x1e, 0x29, 0x31, 0x62,
- 0xe9, 0xfa, 0xc5, 0xff, 0x82, 0x31, 0xcc, 0xd0, 0x0e, 0xfc, 0x58, 0xad,
- 0xd1, 0x82, 0x72, 0x96, 0x19, 0x22, 0x50, 0x82, 0xf7, 0xf0, 0x80, 0xe4,
- 0x2d, 0x2c, 0x5e, 0x72, 0xf2, 0xc5, 0xc2, 0xed, 0x62, 0xff, 0x9a, 0x1e,
- 0xe6, 0x07, 0xf7, 0x58, 0xbd, 0xdb, 0x7d, 0x62, 0x8e, 0x8b, 0xb6, 0x2e,
- 0x00, 0xe1, 0x0c, 0x88, 0xea, 0xfe, 0xe6, 0x0f, 0xef, 0xa5, 0x8b, 0xfd,
- 0x3c, 0xce, 0xfc, 0xfa, 0x58, 0xbf, 0x9b, 0x6e, 0x98, 0x5b, 0x2c, 0x54,
- 0x48, 0x93, 0xd1, 0x74, 0x71, 0xa5, 0xfe, 0xf8, 0x88, 0x7f, 0x70, 0xd6,
- 0x2f, 0xfe, 0x88, 0x43, 0x62, 0x07, 0x57, 0x3f, 0x96, 0x2b, 0xe7, 0xfb,
- 0xe3, 0x5b, 0xda, 0x9f, 0x2c, 0x5f, 0xfa, 0x7c, 0x26, 0xda, 0x7f, 0x27,
- 0x58, 0xbf, 0xa2, 0x61, 0xfd, 0xce, 0xb1, 0x7f, 0x79, 0xf0, 0x72, 0x75,
- 0x8a, 0xed, 0x13, 0x7e, 0x3f, 0x0c, 0xbe, 0xf9, 0xb6, 0x11, 0x2c, 0x5d,
- 0xc2, 0x58, 0xbf, 0xbb, 0xe4, 0xef, 0x87, 0x58, 0xbe, 0x3e, 0xf8, 0x4b,
- 0x15, 0x2a, 0x92, 0xb2, 0x16, 0x3a, 0x22, 0x68, 0x5c, 0x11, 0x97, 0x08,
- 0xc4, 0x2e, 0x61, 0x85, 0x2c, 0x5f, 0xfe, 0xc7, 0x37, 0xf9, 0x85, 0xbe,
- 0x77, 0xe5, 0x8b, 0xff, 0xfa, 0x61, 0x87, 0x9d, 0xfd, 0xcc, 0x04, 0xe7,
- 0x70, 0x58, 0xad, 0x22, 0x9c, 0x92, 0xef, 0xa4, 0x8a, 0x56, 0x2f, 0x9b,
- 0xee, 0x75, 0x8a, 0x88, 0xf0, 0x88, 0x82, 0xff, 0x41, 0xc1, 0x14, 0x1b,
- 0x4b, 0x17, 0xff, 0xf3, 0x3f, 0xa6, 0x0f, 0xa0, 0x02, 0x63, 0xb3, 0x46,
- 0xac, 0x5d, 0xbe, 0x96, 0x2f, 0xf8, 0x03, 0x29, 0x87, 0xf8, 0x05, 0x8b,
- 0x12, 0xc5, 0x68, 0xf2, 0xd8, 0xea, 0xa5, 0x52, 0x88, 0xe1, 0x66, 0xec,
- 0x91, 0x11, 0x7c, 0xd7, 0xcb, 0xc2, 0x64, 0xbf, 0x36, 0xd3, 0xf6, 0x58,
- 0xbf, 0xb4, 0xdb, 0x79, 0xbe, 0xb1, 0x78, 0xa4, 0xd5, 0x8b, 0xec, 0x8f,
- 0x6f, 0xac, 0x5c, 0xde, 0xdc, 0xf0, 0xb8, 0x3b, 0x52, 0x89, 0xf2, 0x71,
- 0xbf, 0xe2, 0xcf, 0x7b, 0x22, 0x68, 0x96, 0x2f, 0xec, 0xf3, 0x6e, 0xf0,
- 0x58, 0xbd, 0x10, 0xbe, 0xb1, 0x70, 0xce, 0xb1, 0x7e, 0xc8, 0xa1, 0x3d,
- 0xac, 0x56, 0x1f, 0x09, 0xa3, 0xe4, 0x31, 0x7f, 0x0b, 0xbd, 0xb6, 0xc0,
- 0xd6, 0x2f, 0xff, 0xf3, 0xc4, 0x53, 0xcd, 0xfe, 0xe5, 0x14, 0xf0, 0x98,
- 0xd5, 0x8b, 0xa4, 0x96, 0x2b, 0x74, 0xf0, 0xdc, 0x86, 0x23, 0xaf, 0xc2,
- 0x3f, 0x85, 0xdd, 0x0c, 0xc3, 0x62, 0xbd, 0xf0, 0xd9, 0x62, 0xff, 0xe1,
- 0x73, 0xed, 0x11, 0x60, 0x05, 0xc5, 0x8b, 0xf6, 0x17, 0xa7, 0x8b, 0x17,
- 0x98, 0x8d, 0x58, 0xb4, 0x16, 0x2f, 0xb3, 0xa3, 0xe9, 0x62, 0xfe, 0x00,
- 0xb9, 0x1f, 0x9d, 0xac, 0x54, 0x47, 0xae, 0x02, 0x4a, 0xc4, 0x46, 0x33,
- 0x4d, 0xff, 0x9b, 0xbe, 0xf8, 0xe3, 0xc0, 0xf8, 0xb1, 0x52, 0xb9, 0x1f,
- 0x92, 0xa2, 0x9d, 0xbb, 0x43, 0xdf, 0x46, 0x62, 0x72, 0x85, 0x4f, 0x08,
- 0x6f, 0xff, 0x9b, 0xbd, 0x66, 0x76, 0x1f, 0xc5, 0x3d, 0xf1, 0x62, 0xfc,
- 0xdb, 0x6e, 0xc3, 0x58, 0xbf, 0xfa, 0x7c, 0xe0, 0xe3, 0x76, 0x07, 0xe8,
+ 0xdd, 0x43, 0x8b, 0x16, 0x7e, 0x1b, 0xc0, 0x87, 0x6b, 0x0f, 0xef, 0xea,
+ 0x97, 0xfb, 0xdf, 0xc2, 0x26, 0xf2, 0xc5, 0xfe, 0x2c, 0xf6, 0xb4, 0x2d,
+ 0x96, 0x28, 0x07, 0xce, 0x46, 0x57, 0xdb, 0x1d, 0xbc, 0xb1, 0x7f, 0xe9,
+ 0x0b, 0xec, 0x3f, 0xc9, 0x6c, 0xb1, 0x52, 0x7c, 0x9a, 0x24, 0xbe, 0xd6,
+ 0x37, 0x72, 0xc5, 0xe7, 0x8e, 0x95, 0x8b, 0xec, 0x17, 0xb8, 0xb1, 0x4c,
+ 0x78, 0x44, 0x3f, 0x7a, 0x42, 0x82, 0xc5, 0xfe, 0xf7, 0x35, 0x9c, 0x9e,
+ 0x96, 0x2d, 0x8b, 0x15, 0x87, 0x8c, 0x46, 0xb7, 0xb5, 0x27, 0x58, 0xbd,
+ 0x8d, 0xba, 0xc5, 0x6e, 0x8b, 0xe7, 0x64, 0xd1, 0x01, 0x0e, 0xdf, 0xfa,
+ 0x42, 0x0f, 0x6e, 0x61, 0xe6, 0x3d, 0x62, 0xb6, 0x5c, 0x4f, 0x1c, 0x2f,
+ 0xb7, 0x84, 0xeb, 0xc2, 0x22, 0x28, 0x42, 0xe8, 0x84, 0xec, 0xff, 0x86,
+ 0xf7, 0x8f, 0x2e, 0xe7, 0x4b, 0x17, 0x05, 0x12, 0xc5, 0xd0, 0x8f, 0x58,
+ 0xbb, 0x38, 0xb1, 0x77, 0x76, 0x96, 0x2a, 0x57, 0x99, 0x60, 0x43, 0x93,
+ 0xa5, 0x0f, 0x09, 0xc3, 0x8c, 0xb0, 0xd0, 0x63, 0x7d, 0xc2, 0xf7, 0x7c,
+ 0x6b, 0x17, 0xff, 0x6b, 0x71, 0x30, 0xf0, 0x87, 0xf7, 0x58, 0xbf, 0x67,
+ 0xfa, 0x87, 0x16, 0x2f, 0xf8, 0x4d, 0xc1, 0xfc, 0x4c, 0x6a, 0xc5, 0xf8,
+ 0xf1, 0x9b, 0xf6, 0x09, 0x62, 0x9d, 0x12, 0xdf, 0x2a, 0x0c, 0xee, 0xe3,
+ 0xca, 0xc5, 0xf0, 0xc5, 0x3f, 0x58, 0xbf, 0x34, 0x78, 0x42, 0xe9, 0x62,
+ 0xf3, 0xf6, 0xc5, 0x8b, 0xfe, 0xdc, 0x9b, 0x9c, 0x14, 0xee, 0xb1, 0x58,
+ 0x8c, 0x1d, 0x0b, 0xfc, 0x8f, 0xc5, 0xc2, 0x1e, 0xbf, 0xdf, 0x7e, 0xbd,
+ 0xad, 0x4a, 0xc5, 0xc1, 0xee, 0xb1, 0x63, 0x56, 0x2f, 0xfc, 0xcf, 0xe8,
+ 0x61, 0xa5, 0x80, 0x58, 0xbf, 0x75, 0x02, 0xc1, 0xac, 0x5f, 0xcf, 0xe8,
+ 0xa1, 0x3d, 0x2c, 0x54, 0x11, 0x88, 0x68, 0xd7, 0xc4, 0xc8, 0xfb, 0xb1,
+ 0x4d, 0xd8, 0x12, 0xc5, 0x2c, 0x57, 0xcd, 0x27, 0x86, 0x2f, 0xf4, 0x27,
+ 0xac, 0x3c, 0xee, 0xb1, 0x7f, 0x60, 0x51, 0xf2, 0x39, 0x58, 0xb1, 0xd6,
+ 0x2b, 0x47, 0x86, 0xc6, 0x37, 0xf3, 0xf3, 0xef, 0x2e, 0xb1, 0x7f, 0xfe,
+ 0x2c, 0xcd, 0xff, 0x31, 0xe5, 0x9e, 0xc7, 0x02, 0xc5, 0x1d, 0x10, 0x4c,
+ 0x59, 0x73, 0xc7, 0x2c, 0x5f, 0xba, 0x9e, 0x34, 0x7a, 0xc5, 0xb0, 0xe7,
+ 0x8c, 0x43, 0x57, 0xe2, 0x8a, 0x7f, 0x2b, 0x17, 0xf6, 0x8d, 0xf7, 0xc5,
+ 0x05, 0x8a, 0x58, 0xbb, 0x06, 0xb1, 0x66, 0xe8, 0xd1, 0xf6, 0x0c, 0xa9,
+ 0x3f, 0xd0, 0x2a, 0x5f, 0xde, 0xe7, 0xc9, 0x80, 0xb1, 0x7b, 0xa6, 0x8f,
+ 0x58, 0xbf, 0xcd, 0xb7, 0xdf, 0xb6, 0x44, 0xb1, 0x5f, 0x3d, 0x80, 0x88,
+ 0x6a, 0x51, 0x53, 0x90, 0x86, 0xbd, 0xac, 0xf2, 0xc5, 0xd2, 0x4b, 0x16,
+ 0x06, 0x1b, 0x3e, 0x0e, 0xdf, 0xdf, 0x67, 0xe3, 0xf6, 0x58, 0xbb, 0x87,
+ 0x58, 0xad, 0x1e, 0x38, 0x8b, 0xee, 0x35, 0xd6, 0x2a, 0x51, 0x4f, 0x8d,
+ 0xac, 0x45, 0x7f, 0xec, 0x22, 0x6f, 0x19, 0x09, 0x3a, 0xc5, 0xb7, 0x58,
+ 0xaf, 0x9e, 0x88, 0x8f, 0xaf, 0xbc, 0x26, 0x0d, 0x62, 0xec, 0xf2, 0xc5,
+ 0x31, 0xbb, 0x8e, 0x24, 0xbf, 0xff, 0xe1, 0x14, 0x30, 0x7f, 0x9e, 0xde,
+ 0x2c, 0x9f, 0xbe, 0x12, 0xc5, 0x46, 0x8c, 0x93, 0x29, 0x18, 0x1c, 0x36,
+ 0xf2, 0x1e, 0x3b, 0xa4, 0xbc, 0x3e, 0x63, 0xdc, 0x22, 0x21, 0xd3, 0xc1,
+ 0xe1, 0x47, 0xf6, 0x86, 0x26, 0x04, 0x29, 0x4a, 0x19, 0x5c, 0x8c, 0x03,
+ 0xcf, 0xc2, 0x5d, 0x0c, 0x8e, 0xfe, 0x0a, 0x75, 0xa6, 0x89, 0x62, 0xff,
+ 0x87, 0x3b, 0x86, 0x00, 0x4f, 0x4b, 0x17, 0xa0, 0x2e, 0x96, 0x2f, 0x71,
+ 0xba, 0x58, 0xbd, 0xc6, 0x25, 0x8b, 0xfe, 0x6d, 0x61, 0xde, 0x3a, 0x4e,
+ 0xb1, 0x5b, 0xa3, 0x47, 0xa3, 0xd7, 0x1f, 0xe0, 0xf0, 0x87, 0x2f, 0x9b,
+ 0x91, 0xe1, 0xac, 0x5f, 0xba, 0x18, 0xdf, 0x8b, 0x17, 0xb5, 0x9c, 0x58,
+ 0xbe, 0x38, 0x70, 0x75, 0x8a, 0x93, 0xeb, 0xc2, 0xa7, 0x1d, 0xbe, 0xf4,
+ 0xf5, 0x05, 0x8b, 0xf9, 0xc1, 0x1c, 0x4e, 0x05, 0x8b, 0xb0, 0x0b, 0x15,
+ 0xb1, 0xf5, 0xe8, 0x90, 0x8c, 0x2f, 0x13, 0xca, 0xc5, 0xfb, 0x91, 0xd9,
+ 0xa3, 0x56, 0x2d, 0x3d, 0x1e, 0x47, 0x86, 0xef, 0x0a, 0x27, 0x58, 0xbf,
+ 0xf3, 0x3f, 0xb3, 0x40, 0x3b, 0x41, 0x62, 0xfe, 0xcf, 0x7d, 0x86, 0xeb,
+ 0x15, 0xa4, 0x44, 0xfc, 0x7a, 0x38, 0xfa, 0xf1, 0x1b, 0xf5, 0x8b, 0xc3,
+ 0xfb, 0xac, 0x53, 0x9f, 0x73, 0x19, 0x88, 0x7a, 0xfa, 0x75, 0xa9, 0x58,
+ 0xbf, 0x89, 0x82, 0xc2, 0x02, 0xc5, 0x6c, 0x79, 0xf1, 0x11, 0x5e, 0x29,
+ 0xd9, 0x62, 0x98, 0xf0, 0x48, 0x92, 0xfe, 0xcf, 0x61, 0xb3, 0xc5, 0x8b,
+ 0xde, 0xc0, 0xd6, 0x2a, 0x57, 0x4d, 0x32, 0x30, 0x13, 0x52, 0xff, 0x09,
+ 0x26, 0x84, 0xb9, 0x3b, 0xf2, 0x31, 0xf1, 0x42, 0xf6, 0x38, 0x83, 0xb8,
+ 0xba, 0xc2, 0x58, 0xbe, 0xee, 0x69, 0xd2, 0xc5, 0xfc, 0x53, 0x09, 0xed,
+ 0x2b, 0x16, 0x02, 0xc5, 0xf8, 0xd6, 0x21, 0x44, 0xb1, 0x52, 0x6f, 0x04,
+ 0x25, 0x7c, 0x27, 0xee, 0x3a, 0xc5, 0xfd, 0xdb, 0x4d, 0x2f, 0x1c, 0xb1,
+ 0x7f, 0x40, 0xb3, 0xfb, 0x4a, 0xc5, 0xb6, 0x58, 0xae, 0x8f, 0x05, 0xcb,
+ 0xad, 0x8b, 0x15, 0x89, 0xc6, 0xf4, 0x24, 0xe4, 0xb1, 0x35, 0x68, 0x80,
+ 0xe4, 0xcc, 0xe6, 0x44, 0x57, 0xdd, 0x6c, 0x31, 0x2c, 0x5b, 0x75, 0x8b,
+ 0xa3, 0xb6, 0x58, 0xbd, 0xd9, 0xf4, 0xb1, 0x43, 0x37, 0x7f, 0x1c, 0xbc,
+ 0xe2, 0xd2, 0xc5, 0xc5, 0x05, 0x8a, 0x94, 0x64, 0x8c, 0x9b, 0x13, 0xb8,
+ 0x43, 0xd8, 0x76, 0xf4, 0xb6, 0x96, 0x2c, 0xcb, 0x14, 0x33, 0x5a, 0x68,
+ 0xe5, 0xfd, 0x0f, 0xbf, 0x6c, 0x1a, 0xc5, 0x68, 0xf4, 0x88, 0x8a, 0xd2,
+ 0xb1, 0x67, 0x58, 0xb4, 0x6b, 0x58, 0xa6, 0x3d, 0xb2, 0x21, 0x08, 0x44,
+ 0x31, 0x1b, 0xd9, 0xa9, 0x58, 0xbe, 0x88, 0x29, 0x35, 0x62, 0xf8, 0xd0,
+ 0xe2, 0xe2, 0xc5, 0xbe, 0xb1, 0x69, 0x58, 0xb7, 0x9c, 0xd1, 0xf7, 0x09,
+ 0x56, 0x8f, 0xcc, 0x92, 0xad, 0x1c, 0xb1, 0x76, 0x6e, 0xb1, 0x4c, 0x6b,
+ 0x7c, 0x2b, 0x7a, 0x3a, 0x4e, 0xb1, 0x5b, 0x1e, 0x01, 0xa4, 0x17, 0xf9,
+ 0x8d, 0x0f, 0xff, 0x98, 0x2c, 0x54, 0xa7, 0x3b, 0x83, 0x8f, 0x09, 0x96,
+ 0x84, 0x74, 0x71, 0x25, 0xff, 0xbf, 0x83, 0x1b, 0xf5, 0x9d, 0x79, 0x62,
+ 0xfe, 0x30, 0x61, 0xb6, 0xb4, 0xb1, 0x69, 0x58, 0xad, 0x91, 0x06, 0x34,
+ 0x18, 0x8c, 0x6f, 0xf0, 0xf3, 0xdf, 0x92, 0xdd, 0x62, 0xf4, 0xbc, 0x72,
+ 0xc5, 0xf7, 0xb8, 0x19, 0xd6, 0x29, 0x8f, 0x10, 0x43, 0xf7, 0xff, 0x1b,
+ 0x9d, 0x73, 0xf9, 0xdb, 0x3d, 0xc5, 0x8b, 0x41, 0x62, 0xff, 0xcf, 0x27,
+ 0x3c, 0xbf, 0x30, 0x35, 0x8b, 0xff, 0x14, 0xf5, 0xc9, 0x3b, 0x75, 0xe5,
+ 0x8a, 0x35, 0x1b, 0x31, 0xe9, 0x3c, 0x12, 0xec, 0x7d, 0x7f, 0xff, 0xc0,
+ 0x92, 0xdd, 0xbe, 0x4c, 0x0d, 0x4e, 0xf9, 0xad, 0x3a, 0xc5, 0xfe, 0xe7,
+ 0x66, 0xe4, 0x94, 0x4b, 0x17, 0xf1, 0xbe, 0x7f, 0x66, 0x96, 0x2d, 0x12,
+ 0xc5, 0xff, 0x0c, 0xcc, 0xe4, 0xe6, 0x80, 0xb1, 0x7b, 0xe1, 0xf1, 0x62,
+ 0xa4, 0xfb, 0x30, 0x4d, 0x8e, 0xaf, 0xb9, 0xc7, 0x3a, 0xc5, 0xee, 0x7d,
+ 0xd6, 0x2f, 0xe1, 0xf8, 0x9b, 0xae, 0x2c, 0x52, 0xc5, 0x39, 0xbb, 0xee,
+ 0x2f, 0xa5, 0x8b, 0xfb, 0x8f, 0xd6, 0x75, 0xe5, 0x8a, 0xe8, 0xde, 0x78,
+ 0x32, 0xe3, 0x8d, 0x62, 0xed, 0xa5, 0x62, 0xa5, 0x16, 0x2c, 0xbf, 0xe2,
+ 0x21, 0x0c, 0x5c, 0xf0, 0x58, 0xbf, 0x04, 0xda, 0x6e, 0x96, 0x2f, 0x4e,
+ 0x74, 0xb1, 0x52, 0x78, 0xe4, 0x55, 0x6e, 0xe5, 0x8b, 0xec, 0xe3, 0x81,
+ 0x62, 0x96, 0x2d, 0x12, 0xc4, 0x44, 0xca, 0x95, 0xd9, 0x4d, 0x8c, 0x86,
+ 0xf1, 0x90, 0xfa, 0xe9, 0x0e, 0x26, 0x6d, 0x1b, 0x7e, 0x13, 0x6c, 0x58,
+ 0x02, 0x32, 0x8c, 0x27, 0x87, 0x7e, 0x5e, 0x08, 0x82, 0x38, 0x54, 0x32,
+ 0xeb, 0xfe, 0x71, 0x93, 0x7a, 0x0f, 0xd9, 0x62, 0xfa, 0x1f, 0xc3, 0xac,
+ 0x5f, 0xf9, 0xb7, 0xfb, 0x0f, 0xf2, 0x5b, 0x2c, 0x57, 0x47, 0xc6, 0x72,
+ 0x3b, 0xfe, 0x83, 0xf8, 0x13, 0xf0, 0xf8, 0xb1, 0x7e, 0x87, 0xe4, 0x8d,
+ 0x58, 0xb8, 0x40, 0x58, 0xa9, 0x4c, 0xf3, 0x21, 0x3b, 0x11, 0x1b, 0x1d,
+ 0xf7, 0x14, 0xd7, 0x78, 0xfc, 0xc9, 0x3d, 0xeb, 0xd4, 0x69, 0x08, 0x48,
+ 0xd9, 0xd3, 0xbe, 0xe1, 0x81, 0xdf, 0x54, 0x29, 0x95, 0xbb, 0xb4, 0x63,
+ 0x10, 0x8f, 0xb0, 0x73, 0x90, 0xb9, 0x48, 0x06, 0x36, 0x3d, 0x2d, 0xe5,
+ 0xdb, 0xf5, 0x29, 0xad, 0xe5, 0xd9, 0x47, 0xc6, 0x1b, 0x14, 0xa6, 0xed,
+ 0x4b, 0x6f, 0x3c, 0xb7, 0x8f, 0xd2, 0x81, 0x5a, 0x7c, 0xf8, 0x12, 0xd8,
+ 0xbb, 0xf7, 0x02, 0x9e, 0xed, 0xe5, 0x26, 0xcf, 0xd3, 0xca, 0xa2, 0x94,
+ 0x73, 0xda, 0x33, 0x90, 0xa3, 0x24, 0x8e, 0x8f, 0x64, 0x39, 0xe6, 0xbe,
+ 0xe9, 0x45, 0x97, 0xfb, 0xbe, 0xfb, 0xd6, 0xf7, 0xe7, 0xcb, 0x17, 0x6f,
+ 0x2b, 0x17, 0xcd, 0xbc, 0xe9, 0x62, 0x82, 0x37, 0x7d, 0xc3, 0x17, 0xe9,
+ 0xeb, 0x1f, 0xeb, 0x17, 0x05, 0x8b, 0x17, 0xf0, 0x27, 0xfd, 0x43, 0x8b,
+ 0x17, 0xf9, 0xfa, 0x03, 0x7f, 0x23, 0x96, 0x2f, 0xfc, 0xf3, 0xef, 0xb1,
+ 0xb8, 0x40, 0x58, 0xbf, 0xfc, 0xda, 0x31, 0xbc, 0x67, 0xba, 0xdd, 0xc9,
+ 0x62, 0xb7, 0x4c, 0xcd, 0xca, 0x22, 0x18, 0xd1, 0x87, 0xcd, 0xfb, 0x1f,
+ 0x5f, 0xb9, 0x16, 0x69, 0x96, 0x2f, 0xa7, 0x76, 0x65, 0x8b, 0xda, 0xc8,
+ 0x2c, 0x5c, 0xe7, 0x58, 0xa7, 0x3f, 0xf3, 0x94, 0xf8, 0x8b, 0xb8, 0x76,
+ 0xfe, 0xcf, 0x4b, 0x9f, 0x8b, 0x17, 0xa4, 0x0e, 0xb1, 0x7f, 0x4c, 0x33,
+ 0x59, 0xc5, 0x8b, 0xf7, 0xf3, 0xd3, 0xf5, 0x8b, 0xf1, 0x78, 0x85, 0xb2,
+ 0xc5, 0x0c, 0xff, 0x98, 0xb4, 0x45, 0x17, 0xff, 0xb5, 0xa1, 0x43, 0x59,
+ 0x3d, 0x41, 0xce, 0xb1, 0x7c, 0x6f, 0x9f, 0x4b, 0x17, 0x44, 0xeb, 0x15,
+ 0x88, 0x88, 0x74, 0xc6, 0x24, 0xbd, 0xc0, 0xf8, 0xb1, 0x7f, 0xfe, 0xc9,
+ 0xea, 0x1c, 0xfe, 0x7b, 0x84, 0xdd, 0x79, 0x62, 0xfe, 0x3e, 0xb5, 0x9e,
+ 0xe2, 0xc5, 0xff, 0x0b, 0x68, 0xcf, 0xb1, 0xdf, 0x8b, 0x16, 0x84, 0x9f,
+ 0x6f, 0x8b, 0xef, 0x6e, 0xdd, 0x96, 0x2f, 0xf8, 0xf3, 0xee, 0x6b, 0x4e,
+ 0x12, 0xc5, 0xff, 0xbe, 0x2e, 0xb9, 0x27, 0x6e, 0xbc, 0xb1, 0x6c, 0x35,
+ 0x38, 0x8e, 0xa1, 0x89, 0xa2, 0x70, 0x10, 0x78, 0xee, 0xff, 0xde, 0x93,
+ 0xf2, 0x5f, 0x66, 0xf2, 0xc5, 0xfc, 0xd1, 0xed, 0x9d, 0x79, 0x62, 0xba,
+ 0x3f, 0x0f, 0x9f, 0xdf, 0xd8, 0x37, 0xe8, 0x99, 0x62, 0xf9, 0xcd, 0x9e,
+ 0xe5, 0x8a, 0x63, 0xd3, 0x22, 0xda, 0xc4, 0x4b, 0x09, 0xda, 0xc6, 0xac,
+ 0x5f, 0xb3, 0xc5, 0x3b, 0x2c, 0x50, 0xcd, 0xde, 0x84, 0xef, 0xff, 0xcc,
+ 0xfa, 0x9e, 0x7e, 0x5c, 0xb3, 0x53, 0xd9, 0x62, 0xfa, 0x7d, 0x06, 0x58,
+ 0xbe, 0xd7, 0x74, 0x92, 0xc5, 0x89, 0x62, 0xa4, 0xdb, 0x04, 0x4b, 0x7f,
+ 0xdc, 0xec, 0xd1, 0x38, 0xc5, 0xa5, 0x8b, 0xff, 0xfe, 0x90, 0x1d, 0xa0,
+ 0x59, 0xd7, 0x9b, 0xf3, 0xee, 0x0a, 0x3d, 0x62, 0xe2, 0x95, 0x8a, 0x89,
+ 0x17, 0xbf, 0x3d, 0xf3, 0x55, 0xdf, 0x8c, 0x8d, 0x6c, 0x9d, 0x29, 0x7b,
+ 0xc8, 0xd6, 0x1e, 0x1b, 0x51, 0x1f, 0x68, 0xb4, 0xf0, 0x9a, 0xfc, 0x2d,
+ 0x98, 0xb4, 0xa3, 0xa7, 0xe4, 0x6b, 0xbe, 0x5d, 0x11, 0x0f, 0x65, 0x40,
+ 0x96, 0x03, 0x86, 0xf5, 0x46, 0x33, 0x63, 0x26, 0x98, 0xe9, 0x7f, 0x66,
+ 0xb7, 0x66, 0xdd, 0x52, 0x66, 0x97, 0xff, 0xe6, 0xd3, 0x42, 0x33, 0x72,
+ 0xcd, 0xb5, 0xd4, 0x8d, 0x62, 0xec, 0x3a, 0xc5, 0xf8, 0xa7, 0xd0, 0x12,
+ 0xc5, 0xf7, 0xb5, 0x3c, 0x58, 0xad, 0xcf, 0x8b, 0xe2, 0xe4, 0x51, 0x7f,
+ 0xb3, 0x9c, 0x90, 0x07, 0xb2, 0xc5, 0xff, 0xf4, 0x27, 0x91, 0x42, 0x4f,
+ 0xd4, 0x39, 0x9b, 0xac, 0x5f, 0x9f, 0x41, 0x67, 0xd6, 0x2f, 0x88, 0x4d,
+ 0x12, 0xc5, 0xf7, 0xdd, 0x89, 0x62, 0xba, 0x46, 0x0f, 0xd5, 0x00, 0x53,
+ 0xe2, 0x3b, 0xff, 0xef, 0xbf, 0x1f, 0xc5, 0x9d, 0x87, 0x31, 0x7d, 0x62,
+ 0xff, 0x02, 0x78, 0xed, 0xd0, 0x4b, 0x17, 0xed, 0x3e, 0xc2, 0x8f, 0x58,
+ 0xbd, 0xf7, 0x1a, 0xc5, 0x85, 0x87, 0x95, 0x11, 0x6d, 0xe8, 0x98, 0x6b,
+ 0x17, 0xfe, 0xc6, 0x8b, 0xaf, 0x18, 0x13, 0xca, 0xc5, 0x49, 0xf0, 0x68,
+ 0x7a, 0xff, 0x66, 0x1a, 0x32, 0x7d, 0x96, 0x2f, 0xfe, 0x38, 0xbf, 0xf6,
+ 0x37, 0x35, 0x9e, 0x58, 0xa1, 0x9f, 0xd1, 0xcd, 0x2f, 0xfe, 0x9d, 0xf9,
+ 0x93, 0x16, 0x6d, 0x84, 0xb1, 0x7f, 0xb3, 0x93, 0xad, 0x3f, 0x65, 0x8a,
+ 0xd8, 0xfe, 0xbe, 0x8b, 0x58, 0x8b, 0xf6, 0x84, 0xe5, 0xe6, 0xcf, 0x2c,
+ 0x5f, 0xfb, 0x8f, 0xac, 0xf4, 0x93, 0x81, 0x62, 0xff, 0xe0, 0x49, 0x6e,
+ 0xd0, 0x78, 0xec, 0xd2, 0xc5, 0xff, 0x3c, 0x1f, 0xe2, 0x39, 0xdd, 0x62,
+ 0xfe, 0x62, 0x07, 0xa6, 0x25, 0x8a, 0xe9, 0x15, 0xde, 0x47, 0x8e, 0x39,
+ 0xbe, 0xd7, 0xda, 0x32, 0x57, 0x5e, 0x06, 0x5f, 0x90, 0xf7, 0xdc, 0xf9,
+ 0xd4, 0x8e, 0xff, 0xf8, 0x44, 0x14, 0x6b, 0x5c, 0x26, 0xf0, 0xe0, 0x70,
+ 0xeb, 0xbd, 0x10, 0x83, 0x58, 0xbf, 0xec, 0x8a, 0x0d, 0xad, 0xbe, 0x25,
+ 0x8b, 0xfd, 0xef, 0xe3, 0xec, 0x79, 0x58, 0xbe, 0xce, 0xcd, 0xa5, 0x8b,
+ 0xf1, 0x4e, 0x7d, 0x96, 0x28, 0x07, 0x95, 0xe2, 0x4b, 0xff, 0x4e, 0x81,
+ 0xee, 0x7f, 0x1c, 0x6b, 0x16, 0x65, 0x8b, 0x9f, 0xeb, 0x15, 0x1b, 0x9a,
+ 0x88, 0x08, 0xdb, 0x65, 0x8b, 0xd0, 0x9e, 0x96, 0x2d, 0x92, 0x6c, 0x62,
+ 0x13, 0xbe, 0x72, 0x6d, 0x96, 0x2f, 0xfb, 0xee, 0xc0, 0xc1, 0x6b, 0x65,
+ 0x8b, 0xfb, 0x60, 0xe3, 0x98, 0x80, 0xb1, 0x7f, 0xe6, 0x20, 0x67, 0xa4,
+ 0x9c, 0x0b, 0x15, 0x27, 0xdf, 0x1c, 0x67, 0x52, 0xab, 0x3c, 0x64, 0x18,
+ 0x79, 0xd3, 0xf7, 0xc8, 0x99, 0x9c, 0x95, 0xf8, 0x4d, 0xe2, 0x20, 0xe1,
+ 0x53, 0x7c, 0x43, 0x0f, 0xa5, 0x8b, 0x7d, 0x62, 0xfd, 0xf9, 0xe7, 0xdd,
+ 0x62, 0xff, 0xcf, 0xe9, 0x39, 0x31, 0xbf, 0x75, 0x8b, 0xa7, 0xeb, 0x17,
+ 0xf9, 0xbd, 0x09, 0x37, 0x09, 0x62, 0xfe, 0x2c, 0xed, 0xf6, 0x82, 0xc5,
+ 0xe6, 0xd7, 0x16, 0x2d, 0x19, 0x29, 0x99, 0xec, 0x4b, 0x82, 0x51, 0x14,
+ 0x7c, 0xf8, 0x85, 0xfc, 0x66, 0x11, 0x7d, 0x46, 0x2a, 0x3e, 0xee, 0x8f,
+ 0x0e, 0xfa, 0x76, 0x21, 0x2c, 0x5f, 0xff, 0xec, 0xf3, 0xf3, 0xdf, 0xc3,
+ 0x81, 0xb5, 0x9d, 0xb0, 0x6b, 0x17, 0xf8, 0x4d, 0xb6, 0xb0, 0xf1, 0x9f,
+ 0x44, 0x2f, 0x08, 0xea, 0x31, 0x9a, 0x97, 0xb9, 0xe3, 0xcf, 0x1a, 0xb4,
+ 0xee, 0xa9, 0x42, 0xda, 0xee, 0xf3, 0xa5, 0x8b, 0xc7, 0x0f, 0x4b, 0x16,
+ 0x3a, 0xc5, 0xe3, 0xb1, 0xd6, 0x29, 0xcd, 0x7b, 0x09, 0x5f, 0xc2, 0x36,
+ 0x42, 0x11, 0xab, 0x14, 0xe8, 0x9f, 0x89, 0x38, 0x21, 0xfb, 0x9c, 0x25,
+ 0x8b, 0x83, 0x3a, 0xc5, 0xf6, 0x7b, 0x91, 0xeb, 0x16, 0x98, 0x1b, 0xf0,
+ 0x86, 0x6b, 0xe7, 0xfc, 0x4a, 0xf6, 0x75, 0x8b, 0xf4, 0xfa, 0x39, 0xce,
+ 0xb1, 0x47, 0x37, 0x80, 0x11, 0xbb, 0x86, 0xac, 0x5f, 0x70, 0xa4, 0x25,
+ 0x8b, 0xdb, 0xe7, 0xd6, 0x2e, 0xe4, 0xac, 0x5f, 0x85, 0xcf, 0x4f, 0x16,
+ 0x2a, 0x07, 0x81, 0x10, 0xbd, 0xc2, 0xe2, 0xc5, 0xf7, 0x4e, 0x2e, 0x96,
+ 0x2a, 0x51, 0x7c, 0xeb, 0xd1, 0x11, 0x88, 0x62, 0xfe, 0x29, 0x3f, 0x1f,
+ 0x65, 0x8b, 0xc5, 0xa1, 0x2c, 0x54, 0x0f, 0x2d, 0xcb, 0xae, 0x0b, 0x4b,
+ 0x17, 0xe1, 0x3f, 0x7c, 0xef, 0x7b, 0xc5, 0x8b, 0xcf, 0x87, 0x58, 0xbc,
+ 0x2e, 0xb8, 0xb1, 0x7e, 0x0f, 0xc5, 0x20, 0x58, 0xa8, 0x8f, 0x93, 0x43,
+ 0x9d, 0x87, 0xef, 0xdb, 0x0a, 0x02, 0x95, 0x8a, 0x93, 0xdc, 0x73, 0x2b,
+ 0xe7, 0x3b, 0xf7, 0x2c, 0x5c, 0x20, 0xd6, 0x2f, 0x16, 0x71, 0x62, 0xa4,
+ 0xf6, 0xa2, 0x25, 0x0c, 0x66, 0xe1, 0x6e, 0xb1, 0x7f, 0x75, 0x08, 0xb3,
+ 0xfc, 0x58, 0xba, 0x42, 0x58, 0xa9, 0x3c, 0x97, 0x31, 0xbe, 0xfb, 0xf5,
+ 0xc5, 0x8b, 0xa7, 0xa5, 0x8b, 0xa7, 0xeb, 0x17, 0xde, 0x76, 0x0d, 0x62,
+ 0xd1, 0xcb, 0x16, 0x35, 0x62, 0x9c, 0xd4, 0x08, 0x56, 0xa3, 0xd1, 0x7d,
+ 0x11, 0x21, 0xc6, 0x38, 0x2e, 0x1a, 0x5d, 0xf3, 0xc7, 0x38, 0x16, 0x2e,
+ 0x0a, 0x56, 0x2f, 0x79, 0xbe, 0xb1, 0x73, 0x41, 0x62, 0x9c, 0xda, 0x1c,
+ 0x76, 0xc6, 0xac, 0x51, 0xa6, 0xcf, 0x44, 0x17, 0x1e, 0x33, 0xbc, 0x5f,
+ 0x9d, 0x98, 0x5e, 0x8e, 0x15, 0xf8, 0xba, 0x69, 0x0f, 0x43, 0x2f, 0x0e,
+ 0x18, 0xa1, 0x0f, 0xa2, 0x13, 0x8c, 0xfe, 0x1f, 0x2c, 0xf5, 0xc3, 0x0f,
+ 0x31, 0x0a, 0x1b, 0xdd, 0x93, 0xc2, 0x25, 0x0d, 0xfe, 0xec, 0x75, 0x8b,
+ 0x0d, 0x62, 0xc7, 0x58, 0xac, 0x34, 0x8c, 0x25, 0x62, 0x58, 0xbf, 0xe8,
+ 0x46, 0x66, 0xb7, 0x66, 0xdd, 0x52, 0x40, 0x15, 0x87, 0xb8, 0xc2, 0x37,
+ 0xf9, 0xcf, 0x31, 0xff, 0xcd, 0x96, 0x2f, 0xdb, 0xc8, 0x05, 0xdc, 0xb1,
+ 0x79, 0xb4, 0x6a, 0xc5, 0xff, 0xd1, 0xcc, 0x40, 0xcf, 0x49, 0x38, 0x16,
+ 0x2d, 0x19, 0x04, 0xe7, 0x30, 0xe8, 0xef, 0x7f, 0x20, 0x63, 0x70, 0x8b,
+ 0x43, 0x1e, 0xb7, 0x65, 0x8b, 0xec, 0xf0, 0x7b, 0x2c, 0x5f, 0xbd, 0xc9,
+ 0x1c, 0xac, 0x56, 0x1f, 0x09, 0xc5, 0x08, 0x96, 0xe8, 0x1d, 0x62, 0xfe,
+ 0x7e, 0x44, 0x52, 0x35, 0x8a, 0x58, 0xbb, 0xa8, 0x2c, 0x57, 0x46, 0x97,
+ 0x41, 0x94, 0x33, 0xf5, 0x65, 0x3b, 0xd2, 0x5b, 0xac, 0x5e, 0xf3, 0x69,
+ 0x62, 0xf8, 0x47, 0xcf, 0xac, 0x5a, 0x7a, 0x3c, 0x0f, 0x8e, 0xdd, 0x01,
+ 0xac, 0x5f, 0xfa, 0x70, 0xbd, 0xc9, 0xf4, 0x8d, 0x62, 0xfd, 0x25, 0x9d,
+ 0x79, 0x62, 0xfb, 0x90, 0x70, 0x2c, 0x51, 0xcf, 0x2f, 0xc5, 0x16, 0xec,
+ 0xb1, 0x6f, 0x2c, 0x54, 0x0d, 0x36, 0xe2, 0x97, 0xf3, 0xfe, 0x4a, 0x7c,
+ 0xb1, 0x68, 0xe5, 0x8b, 0x01, 0x62, 0xa4, 0xd3, 0x88, 0x56, 0xf0, 0xd9,
+ 0xd6, 0x2a, 0x55, 0x7c, 0xc0, 0xb7, 0x21, 0x1a, 0x69, 0x0b, 0xae, 0xe8,
+ 0xa0, 0xe3, 0x0d, 0x08, 0x82, 0x48, 0xe1, 0x17, 0x94, 0xc4, 0x41, 0x7a,
+ 0x29, 0x82, 0xc5, 0xfe, 0x7f, 0xb1, 0x7b, 0x37, 0x58, 0xb7, 0x96, 0x2a,
+ 0x07, 0x8b, 0xa3, 0x3b, 0x46, 0x62, 0x21, 0x78, 0xc7, 0x7f, 0xbb, 0xcf,
+ 0xb6, 0xc5, 0x30, 0x58, 0xbf, 0xdf, 0xce, 0x81, 0x25, 0xba, 0xc5, 0xff,
+ 0x4f, 0xbf, 0x87, 0xcd, 0x62, 0xc5, 0xf4, 0x59, 0x9b, 0xac, 0x5f, 0xbc,
+ 0x6b, 0x72, 0x33, 0xbd, 0x46, 0x56, 0x1c, 0xe8, 0xd4, 0x33, 0x8a, 0x82,
+ 0x6b, 0x01, 0x43, 0xd6, 0xfe, 0x8d, 0x5d, 0xec, 0x6a, 0x07, 0x31, 0x62,
+ 0xfe, 0x6f, 0x75, 0x0c, 0xf2, 0xc5, 0xef, 0x72, 0x33, 0xbe, 0xcf, 0xbc,
+ 0x34, 0x0b, 0xff, 0x73, 0xef, 0x19, 0x3d, 0xbb, 0x0a, 0x0b, 0x15, 0x18,
+ 0xae, 0xa6, 0x65, 0x45, 0x34, 0x26, 0x44, 0x7f, 0x7d, 0xf2, 0x6f, 0x2c,
+ 0x5d, 0xcf, 0x2c, 0x5a, 0x56, 0x2d, 0xf5, 0x8a, 0x39, 0xa3, 0x10, 0x8d,
+ 0xf7, 0x7b, 0xdb, 0xae, 0x2c, 0x5e, 0x1e, 0x1d, 0x62, 0xff, 0xef, 0x38,
+ 0xb8, 0x19, 0xf5, 0xa7, 0x35, 0x62, 0xff, 0xfd, 0xda, 0x7e, 0xe3, 0xfc,
+ 0xc3, 0x8d, 0xf7, 0xe2, 0xc5, 0xff, 0xc7, 0x6d, 0x6d, 0xfc, 0x89, 0x88,
+ 0xd5, 0x8b, 0xfe, 0x9f, 0xce, 0xda, 0x9c, 0x1a, 0xc5, 0xfd, 0xc9, 0x39,
+ 0x4c, 0x4b, 0x16, 0xfa, 0xc5, 0xe0, 0xca, 0x25, 0x8b, 0x7b, 0x0d, 0x88,
+ 0x04, 0xae, 0xcd, 0x96, 0x2b, 0x0d, 0xf1, 0x13, 0x5f, 0xff, 0x39, 0x80,
+ 0x00, 0xa7, 0x9a, 0x30, 0xcf, 0xc7, 0x2c, 0x5f, 0x39, 0xe6, 0x25, 0x8a,
+ 0xd9, 0x53, 0x9c, 0x07, 0x5d, 0x20, 0xea, 0xff, 0x47, 0x01, 0xc9, 0x42,
+ 0x74, 0x43, 0xf1, 0xcb, 0x17, 0xff, 0x85, 0xa8, 0x67, 0x1c, 0x5d, 0xf9,
+ 0x49, 0xd6, 0x2d, 0xc5, 0x8b, 0xf7, 0x27, 0xef, 0xd9, 0x62, 0xfe, 0xfb,
+ 0x37, 0xe6, 0x0b, 0x17, 0xc3, 0x72, 0x02, 0xc5, 0x18, 0x88, 0xbc, 0x12,
+ 0x72, 0xa6, 0x2d, 0xbf, 0xfe, 0xd6, 0xc3, 0xfb, 0xeb, 0x93, 0xa8, 0x9f,
+ 0xeb, 0x17, 0xfe, 0x07, 0x09, 0x8d, 0xce, 0xcf, 0xa5, 0x8b, 0xff, 0x9f,
+ 0xe2, 0xfb, 0x3f, 0x5c, 0x93, 0x56, 0x2b, 0x11, 0x0f, 0xe4, 0x1b, 0xc2,
+ 0x1e, 0x2c, 0x5f, 0xda, 0xf1, 0x49, 0xf8, 0xb1, 0x7f, 0xfe, 0xd0, 0xd8,
+ 0x8d, 0xfe, 0x47, 0xe9, 0xcf, 0x26, 0xac, 0x56, 0x22, 0x20, 0x45, 0xd6,
+ 0x8e, 0x58, 0xa9, 0x4f, 0x63, 0x21, 0xb4, 0xe4, 0x5f, 0x85, 0x28, 0x08,
+ 0xaf, 0x36, 0xb1, 0x62, 0xe1, 0x01, 0x62, 0xf7, 0x24, 0x0b, 0x17, 0xd0,
+ 0x72, 0xc5, 0x8a, 0xf1, 0xbe, 0x08, 0x76, 0xfb, 0x76, 0x6d, 0xd5, 0x26,
+ 0xf9, 0x7a, 0x39, 0xbc, 0xb1, 0x7c, 0x1e, 0x16, 0xeb, 0x17, 0xe9, 0x38,
+ 0x1b, 0xcb, 0x17, 0xfd, 0x3b, 0xc9, 0xf0, 0x01, 0x84, 0xb1, 0x67, 0xd2,
+ 0x22, 0x08, 0x93, 0xb8, 0xa2, 0xf4, 0x58, 0x05, 0x8b, 0xf0, 0x7b, 0x7e,
+ 0x74, 0xb1, 0x5b, 0xa7, 0xdb, 0xd0, 0xe3, 0xab, 0x68, 0x88, 0xe6, 0x3f,
+ 0x85, 0x43, 0x1b, 0xf8, 0x7a, 0xff, 0x9f, 0xf3, 0xd4, 0xc7, 0xe7, 0x4b,
+ 0x17, 0xf8, 0x3d, 0x98, 0x7f, 0x9e, 0x2c, 0x5f, 0xff, 0xf3, 0x44, 0x37,
+ 0xd7, 0xf0, 0x65, 0x3b, 0xb6, 0xc5, 0x27, 0x58, 0xbf, 0xed, 0x0b, 0x9f,
+ 0x68, 0x01, 0xd6, 0x2c, 0xe0, 0x45, 0x0f, 0x99, 0xef, 0xbd, 0xc6, 0xf2,
+ 0xc5, 0xff, 0xb5, 0x91, 0xf1, 0x7d, 0x8e, 0xfc, 0x58, 0xbb, 0x36, 0xc3,
+ 0xe6, 0xd1, 0x1d, 0x6e, 0x9c, 0x97, 0xe1, 0xae, 0x50, 0x8e, 0xbf, 0x7a,
+ 0x76, 0xc1, 0xac, 0x58, 0x25, 0x8b, 0xfe, 0x62, 0xdf, 0x93, 0xf6, 0x8f,
+ 0x58, 0xa8, 0x1f, 0xc1, 0xa5, 0x3e, 0x13, 0xbc, 0x4f, 0x12, 0xc5, 0xfd,
+ 0x91, 0x11, 0x37, 0xd6, 0x2b, 0x0f, 0x28, 0xe3, 0xb7, 0xcf, 0x9a, 0xec,
+ 0xb1, 0x7d, 0xd4, 0x36, 0x95, 0x8b, 0xd2, 0x14, 0x72, 0xc5, 0x61, 0xe3,
+ 0x68, 0x96, 0xfb, 0x7f, 0x66, 0xeb, 0x17, 0xa3, 0x85, 0x2b, 0x14, 0xb1,
+ 0x58, 0x6b, 0x08, 0x82, 0xb0, 0xfc, 0x3c, 0xa3, 0x7b, 0xf3, 0xa5, 0x8b,
+ 0xf7, 0xdf, 0x5f, 0x65, 0x8b, 0xff, 0xdf, 0x9d, 0xbd, 0x9f, 0x2c, 0xf7,
+ 0xdd, 0x62, 0xf1, 0xf0, 0x6b, 0x16, 0x3a, 0xc5, 0xfe, 0x9d, 0x87, 0x81,
+ 0x72, 0x32, 0x51, 0x7d, 0x83, 0xb1, 0x14, 0x32, 0x50, 0x63, 0xb5, 0x04,
+ 0xf9, 0xb2, 0x12, 0x3f, 0x86, 0xfd, 0xd9, 0xa5, 0x8b, 0xc7, 0xce, 0x96,
+ 0x2f, 0xfe, 0x26, 0x07, 0x07, 0x3e, 0xe3, 0x6c, 0xb1, 0x5b, 0x1f, 0xd0,
+ 0xc5, 0xfc, 0x3d, 0x79, 0xfd, 0xc5, 0x8b, 0xda, 0x14, 0x4b, 0x17, 0xb6,
+ 0x63, 0xe8, 0xde, 0x78, 0x76, 0xfa, 0x1c, 0x0f, 0x8b, 0x15, 0x28, 0xc4,
+ 0x76, 0xcf, 0x19, 0xdf, 0x67, 0xb9, 0x8b, 0x17, 0xf3, 0x74, 0x37, 0x2d,
+ 0x96, 0x2f, 0xf6, 0x47, 0xe9, 0xcf, 0x26, 0xac, 0x54, 0xa2, 0x23, 0x44,
+ 0x5f, 0x2f, 0xbd, 0xcf, 0x8d, 0x62, 0xfc, 0x1f, 0x8a, 0x40, 0xb1, 0x47,
+ 0x3c, 0x7e, 0xc3, 0xd7, 0xfb, 0x76, 0xd6, 0xdd, 0xbc, 0x25, 0x8b, 0x8a,
+ 0x56, 0x2f, 0xfe, 0xf7, 0x1f, 0x92, 0x59, 0xef, 0xba, 0xc5, 0xff, 0x9b,
+ 0xbb, 0x4e, 0x6e, 0x7d, 0xe0, 0xb1, 0x7f, 0xe0, 0x08, 0xb7, 0x61, 0xfe,
+ 0x78, 0xb1, 0x70, 0xb1, 0x62, 0xff, 0x80, 0xfe, 0x26, 0xf4, 0x8d, 0x62,
+ 0xf1, 0x67, 0xd6, 0x2b, 0x74, 0xdf, 0xf4, 0x72, 0x71, 0x6f, 0xa1, 0x81,
+ 0x08, 0x90, 0x38, 0x2f, 0xd8, 0xe2, 0xff, 0x9f, 0x98, 0x39, 0x89, 0xce,
+ 0xb1, 0x7e, 0x1c, 0xc7, 0x88, 0xeb, 0x17, 0xfe, 0xcd, 0xb6, 0x10, 0xe7,
+ 0x52, 0x35, 0x8b, 0xf7, 0x9f, 0x53, 0xd9, 0x62, 0xff, 0x9b, 0x93, 0x84,
+ 0x3f, 0xca, 0xc5, 0xf9, 0xa3, 0xce, 0xde, 0x58, 0xbf, 0xdf, 0x91, 0xbf,
+ 0x69, 0x1a, 0xc5, 0xff, 0x6b, 0x3a, 0xf9, 0x34, 0x7e, 0xcb, 0x16, 0xc1,
+ 0x9f, 0x99, 0xcd, 0x6d, 0xcd, 0x23, 0xf3, 0xe6, 0xe5, 0x09, 0xea, 0x24,
+ 0xd8, 0x39, 0x19, 0x35, 0x4a, 0xe2, 0x36, 0x47, 0x47, 0xbb, 0xa3, 0x9c,
+ 0xe8, 0xb1, 0xa3, 0xa1, 0xbf, 0xd3, 0xee, 0x68, 0xa6, 0x25, 0x8b, 0xf0,
+ 0x79, 0xf6, 0x3a, 0xc5, 0xc2, 0x35, 0x62, 0xf8, 0xf1, 0x48, 0x6b, 0x17,
+ 0x4f, 0xd6, 0x2f, 0xfd, 0xdc, 0xc7, 0x0f, 0x40, 0x3b, 0xf1, 0x62, 0xb6,
+ 0x47, 0xb6, 0xe6, 0x87, 0x29, 0x61, 0x92, 0x25, 0xee, 0x17, 0xbf, 0x84,
+ 0x07, 0x21, 0x69, 0x62, 0xf3, 0x97, 0x96, 0x2e, 0x17, 0x4b, 0x17, 0xfc,
+ 0xd0, 0xf7, 0x30, 0x2f, 0xba, 0xc5, 0xee, 0x9b, 0xeb, 0x14, 0x74, 0x5d,
+ 0xb1, 0x70, 0x07, 0x08, 0x64, 0x47, 0x57, 0xf7, 0x30, 0x7f, 0x7d, 0x2c,
+ 0x5f, 0xe9, 0xe6, 0x75, 0xe7, 0xd2, 0xc5, 0xfc, 0xdb, 0x76, 0xc2, 0xd9,
+ 0x62, 0xa2, 0x44, 0x9e, 0x8b, 0xa3, 0x8d, 0x2f, 0xf7, 0xc4, 0x43, 0xfb,
+ 0x84, 0xb1, 0x7f, 0xf4, 0x42, 0x1b, 0x10, 0x0c, 0x73, 0xf9, 0x62, 0xbe,
+ 0x7f, 0x9e, 0x35, 0xbf, 0xfa, 0x40, 0x29, 0x0f, 0x72, 0xcf, 0xe2, 0xc5,
+ 0xed, 0x4f, 0x96, 0x2f, 0xfd, 0x3e, 0x13, 0x6d, 0x3f, 0x93, 0xac, 0x5f,
+ 0xd1, 0x30, 0xfe, 0xe7, 0x58, 0xbf, 0xbc, 0xf8, 0x39, 0x3a, 0xc5, 0x74,
+ 0x89, 0xbf, 0x1f, 0x84, 0x5f, 0x7c, 0xdb, 0x08, 0x96, 0x2e, 0xe1, 0x2c,
+ 0x5f, 0xdd, 0x72, 0x77, 0xc3, 0xac, 0x5f, 0x1f, 0x7c, 0x25, 0x8a, 0x95,
+ 0x51, 0xd9, 0x0b, 0x07, 0x22, 0xd2, 0x2b, 0x42, 0xe0, 0x8c, 0xb8, 0x46,
+ 0x21, 0x70, 0xcc, 0x29, 0x62, 0xff, 0xf6, 0x39, 0xbf, 0xcc, 0x2d, 0xf3,
+ 0xaf, 0x2c, 0x5f, 0xff, 0xd3, 0x0c, 0x3c, 0xef, 0xee, 0x60, 0x27, 0x3a,
+ 0x82, 0xc5, 0x69, 0x14, 0xe4, 0x97, 0x7d, 0x24, 0x52, 0xb1, 0x7c, 0xdf,
+ 0x73, 0xac, 0x54, 0x47, 0x84, 0x44, 0x17, 0xfa, 0x0e, 0x08, 0xa0, 0xda,
+ 0x58, 0xbe, 0xed, 0x9e, 0xe2, 0xc5, 0xff, 0xf9, 0xfd, 0x30, 0x7d, 0x00,
+ 0x13, 0x1d, 0x9a, 0x35, 0x62, 0xb0, 0xff, 0x98, 0x96, 0xed, 0xf4, 0xb1,
+ 0x7f, 0xc0, 0x19, 0x4c, 0x3f, 0xc0, 0x2c, 0x58, 0x96, 0x2b, 0x47, 0x96,
+ 0xc7, 0x55, 0x2a, 0xa4, 0x47, 0x0b, 0x37, 0x64, 0x88, 0x8b, 0xf0, 0xb3,
+ 0xf1, 0x00, 0x99, 0x2f, 0xcd, 0xb4, 0xfd, 0x96, 0x2f, 0xed, 0x36, 0xde,
+ 0x6f, 0xac, 0x5e, 0x29, 0x35, 0x62, 0xfb, 0x23, 0xdb, 0xeb, 0x17, 0x37,
+ 0xb7, 0x3c, 0x2e, 0x0e, 0xd4, 0xa2, 0x7c, 0x9c, 0x6f, 0xf8, 0xb3, 0xde,
+ 0xc8, 0x9a, 0x25, 0x8b, 0xfb, 0x3c, 0xdb, 0xbc, 0x16, 0x2f, 0x44, 0x2f,
+ 0xac, 0x5c, 0x33, 0xac, 0x5f, 0xb2, 0x28, 0x4f, 0x4b, 0x15, 0x87, 0xc2,
+ 0x68, 0xf9, 0x0c, 0x5f, 0xc2, 0xeb, 0x6d, 0xb0, 0x25, 0x8b, 0xff, 0xfc,
+ 0xf1, 0x14, 0xf3, 0x7f, 0xb9, 0x45, 0x3c, 0x26, 0x35, 0x62, 0xe9, 0x25,
+ 0x8a, 0xdd, 0x3c, 0x37, 0x21, 0x88, 0xeb, 0xf0, 0x8f, 0xe1, 0x77, 0x63,
+ 0x30, 0x98, 0xaf, 0x7c, 0x26, 0x58, 0xbf, 0xf8, 0x5c, 0xfb, 0x44, 0x58,
+ 0x01, 0x71, 0x62, 0xfd, 0x85, 0xe9, 0xe2, 0xc5, 0xa0, 0xb1, 0x7d, 0x9d,
+ 0x9f, 0x4b, 0x17, 0xf0, 0x05, 0xc8, 0xfc, 0xe9, 0x62, 0xa2, 0x3d, 0x70,
+ 0x12, 0x56, 0x22, 0x31, 0x9a, 0x6f, 0xfc, 0xdd, 0x75, 0xc7, 0x1e, 0x05,
+ 0xc5, 0x8a, 0x95, 0xc7, 0x2c, 0x95, 0x14, 0xed, 0xda, 0x1e, 0xfa, 0x31,
+ 0x42, 0xcf, 0x84, 0x37, 0xff, 0xcd, 0xd6, 0xb3, 0x3a, 0x0b, 0xe2, 0x9e,
+ 0xb8, 0xb1, 0x7d, 0xb6, 0xec, 0x35, 0x8b, 0xf7, 0x6c, 0x89, 0xf8, 0xb1,
+ 0x4c, 0x7a, 0x02, 0x25, 0xbf, 0xfa, 0x7c, 0xe0, 0xe3, 0x74, 0x07, 0xec,
0xb1, 0x7c, 0xdb, 0xb6, 0xcb, 0x17, 0x79, 0xf4, 0x7d, 0x7c, 0x47, 0xbf,
0x31, 0x0f, 0xf2, 0xb1, 0x7c, 0x07, 0x23, 0x56, 0x29, 0x8f, 0x28, 0x04,
- 0xf4, 0x14, 0x74, 0x72, 0xc1, 0x52, 0x28, 0xd0, 0xec, 0x2d, 0x90, 0xcc,
- 0xa4, 0x6d, 0x9e, 0xa1, 0x0d, 0x91, 0xca, 0x14, 0xc8, 0xfc, 0x8d, 0x72,
- 0xde, 0x3c, 0xfe, 0xe1, 0x66, 0xef, 0x51, 0xe4, 0x31, 0x4a, 0x50, 0xd4,
- 0x6a, 0x67, 0x85, 0xb7, 0xe7, 0x20, 0x9a, 0x32, 0x40, 0x46, 0x0c, 0x52,
- 0xc9, 0x79, 0x2b, 0x2f, 0xd3, 0x9f, 0x22, 0x7b, 0x8e, 0x54, 0x32, 0x12,
- 0xa1, 0x1d, 0xee, 0x9d, 0x96, 0x2e, 0x6f, 0x2c, 0x5f, 0xd0, 0xc2, 0x26,
- 0x82, 0xc5, 0xe6, 0xee, 0x30, 0x67, 0xb6, 0x71, 0x8f, 0x0b, 0xdf, 0xa0,
- 0x66, 0xd3, 0xb2, 0xc5, 0xec, 0x2d, 0xd6, 0x2f, 0x37, 0x71, 0x9c, 0x3c,
- 0x93, 0x0b, 0x2a, 0x31, 0x58, 0x79, 0x4a, 0x4a, 0x14, 0x23, 0x6f, 0x40,
- 0x50, 0x58, 0xbf, 0xa0, 0xda, 0xdb, 0xe2, 0x58, 0xbf, 0x72, 0x40, 0x66,
- 0xcb, 0x16, 0xc8, 0x8f, 0x6f, 0x86, 0x17, 0xcf, 0x1c, 0x40, 0x58, 0xbd,
- 0xee, 0x76, 0xb1, 0x7f, 0xef, 0x3c, 0x1f, 0xe2, 0x39, 0xdd, 0x62, 0xe1,
- 0xc6, 0x41, 0x32, 0x41, 0xbc, 0xb1, 0x47, 0x09, 0x4c, 0x1f, 0xbc, 0x7c,
- 0x25, 0x8b, 0xfd, 0x9c, 0xe4, 0x80, 0xcd, 0x96, 0x2f, 0xc7, 0x92, 0x9e,
- 0xd6, 0x2e, 0x6d, 0xd6, 0x2f, 0xfb, 0xd1, 0x41, 0xb5, 0xb7, 0xc4, 0xb1,
- 0x5b, 0x1f, 0xee, 0xe5, 0x1d, 0x8c, 0x5e, 0xdd, 0xe0, 0xb1, 0x7f, 0xfb,
- 0x52, 0x3c, 0x8a, 0x0d, 0xad, 0xbe, 0x25, 0x8b, 0xff, 0x8c, 0xdf, 0xac,
- 0xeb, 0x4e, 0x4d, 0xba, 0xc5, 0xe8, 0xe2, 0x02, 0xc5, 0xfe, 0x8a, 0x36,
- 0xc7, 0xe8, 0xc7, 0x58, 0xa7, 0x3d, 0xbf, 0x10, 0x5e, 0x7f, 0x89, 0x62,
- 0xff, 0x63, 0xef, 0xf7, 0xef, 0xcb, 0x17, 0xcf, 0xec, 0x02, 0xc5, 0xff,
- 0x75, 0xf4, 0xf5, 0x89, 0x9b, 0x4b, 0x17, 0xfd, 0x91, 0x41, 0xb5, 0xb7,
- 0xc4, 0xb1, 0x74, 0xc4, 0xb1, 0x7f, 0xc7, 0x8a, 0x0d, 0xad, 0xbe, 0x25,
- 0x8b, 0xcc, 0x40, 0x24, 0x48, 0xf8, 0xf0, 0xc1, 0x8a, 0x3a, 0x61, 0xf1,
- 0xd0, 0xcf, 0xa9, 0x57, 0xc0, 0x31, 0xcc, 0x85, 0x9b, 0x99, 0x68, 0x78,
- 0xe9, 0xad, 0x0a, 0x40, 0xb9, 0x0f, 0x07, 0x7c, 0x6a, 0x64, 0x66, 0x37,
- 0x46, 0xf1, 0xa2, 0xc5, 0xe3, 0xb7, 0x6b, 0x17, 0x80, 0xdf, 0x58, 0xbf,
- 0xff, 0xef, 0xbc, 0x50, 0x11, 0xa5, 0x9d, 0xf9, 0x8f, 0xee, 0x66, 0xcb,
- 0x17, 0xfd, 0xe7, 0x3f, 0x3f, 0x81, 0xb2, 0xc5, 0xdd, 0x1d, 0x62, 0xf6,
- 0x0c, 0x6b, 0x17, 0xb5, 0x86, 0x2c, 0x5f, 0xb0, 0x67, 0x28, 0x2c, 0x56,
- 0x8f, 0x18, 0xe3, 0xd7, 0xfd, 0x30, 0x0d, 0xb5, 0xac, 0x31, 0x62, 0xfd,
- 0x9e, 0xd4, 0x9d, 0x62, 0xfc, 0x7f, 0x70, 0x51, 0xeb, 0x17, 0xfb, 0xdf,
- 0xc2, 0x26, 0xf2, 0xc5, 0xec, 0x0e, 0x30, 0x28, 0xa9, 0x8a, 0x48, 0xb0,
- 0x7b, 0x71, 0xde, 0xda, 0xe2, 0x3a, 0xf8, 0xcb, 0x31, 0x91, 0x17, 0x0e,
- 0xcc, 0x28, 0x08, 0x5b, 0x6e, 0x46, 0x2b, 0xcf, 0xda, 0x58, 0x6d, 0xe3,
- 0xe1, 0xd6, 0x2f, 0xfb, 0xee, 0xc0, 0xc1, 0x6b, 0x65, 0x8b, 0xfd, 0xe7,
- 0xf7, 0x3e, 0xf1, 0x98, 0x7a, 0xfe, 0x1d, 0xa9, 0x64, 0x71, 0x3d, 0x20,
- 0x24, 0x50, 0x8d, 0xbf, 0x48, 0x3e, 0x23, 0x16, 0x2e, 0x17, 0x6b, 0x17,
- 0xec, 0xd6, 0x67, 0x6b, 0x17, 0x6d, 0x19, 0xf3, 0xeb, 0x01, 0x51, 0x0c,
- 0xdf, 0xff, 0xe7, 0xf0, 0x9b, 0x68, 0xcc, 0x87, 0xe7, 0x59, 0x84, 0x6a,
- 0xc5, 0x69, 0x14, 0x41, 0x73, 0xeb, 0xff, 0xff, 0xb7, 0x6d, 0x37, 0xe1,
- 0x9e, 0xc1, 0xf1, 0x8f, 0x9a, 0xda, 0x7b, 0x58, 0xbf, 0xb0, 0x6c, 0x7c,
- 0x25, 0x8b, 0xff, 0xec, 0x10, 0x5f, 0x09, 0x9f, 0xed, 0xef, 0xca, 0xc5,
- 0x3a, 0x3c, 0x74, 0xe9, 0xf2, 0xcb, 0xf6, 0xb7, 0x66, 0xdd, 0x51, 0x4a,
- 0x17, 0xff, 0xcd, 0xe2, 0xcd, 0xb5, 0x3f, 0x7f, 0xe6, 0x96, 0x2f, 0xff,
- 0x98, 0x78, 0x3f, 0xe1, 0x00, 0xf9, 0xac, 0x58, 0xbb, 0x81, 0xac, 0x5f,
- 0xfb, 0xf2, 0x03, 0xb4, 0x39, 0xc0, 0xd6, 0x2f, 0x34, 0x23, 0x25, 0x35,
- 0xdc, 0x2f, 0x01, 0xb9, 0x27, 0xf1, 0x38, 0xc1, 0x9b, 0xff, 0x3e, 0xed,
- 0xa6, 0x83, 0xf0, 0x0b, 0x17, 0xed, 0x6e, 0xcd, 0xba, 0xa2, 0x4e, 0x2e,
- 0x84, 0x64, 0x9f, 0xb6, 0x1f, 0xd1, 0xd3, 0x0f, 0x68, 0x70, 0x5f, 0xf6,
- 0x45, 0x06, 0xd6, 0xdf, 0x12, 0xc5, 0xfb, 0xf9, 0xa7, 0xe2, 0xc5, 0xda,
- 0x8c, 0x19, 0xf2, 0x78, 0xf2, 0xff, 0x9a, 0x19, 0x02, 0x13, 0x71, 0x62,
- 0xf4, 0xc4, 0xcb, 0x17, 0xf7, 0x98, 0xe5, 0x27, 0x58, 0xbe, 0x72, 0xc8,
- 0x2c, 0x50, 0xd1, 0x47, 0xf3, 0x8f, 0x0e, 0x84, 0x2d, 0xbe, 0xdc, 0x84,
- 0x6a, 0xc5, 0xda, 0x8c, 0xc3, 0xe4, 0x63, 0xfa, 0x8c, 0x4f, 0xcd, 0xe1,
- 0x18, 0xd1, 0x9c, 0x54, 0xca, 0xd9, 0xf7, 0xda, 0xbd, 0xa2, 0x85, 0x34,
- 0x10, 0x79, 0xf1, 0x3c, 0x64, 0xab, 0x83, 0x65, 0x07, 0x6f, 0x1e, 0x8b,
- 0xcf, 0x65, 0xc7, 0xc6, 0xf9, 0x14, 0x71, 0x7a, 0x8d, 0xc4, 0xf7, 0xcd,
- 0xbf, 0xfa, 0x5f, 0x6b, 0x4f, 0x9b, 0x02, 0x54, 0x39, 0x4f, 0x22, 0x72,
- 0xd3, 0x75, 0xfa, 0x94, 0x8c, 0x28, 0xd3, 0x7a, 0x4e, 0xbb, 0xdb, 0x8b,
- 0x17, 0xed, 0x6e, 0xcd, 0xba, 0xa2, 0x1f, 0x2f, 0xfc, 0xd0, 0x8c, 0xcd,
- 0x6e, 0xcd, 0xba, 0xa2, 0x53, 0x2d, 0x18, 0x34, 0x4c, 0xe0, 0x91, 0xcd,
- 0xef, 0xf4, 0x66, 0x6b, 0x76, 0x6d, 0xd5, 0x11, 0x39, 0x7a, 0x34, 0x0b,
- 0x61, 0x45, 0x8b, 0xf3, 0xfb, 0x82, 0x3a, 0xc5, 0xf8, 0x47, 0x26, 0x35,
- 0x62, 0xf7, 0xe6, 0x25, 0x8b, 0xbb, 0x82, 0xc5, 0x44, 0x88, 0x9d, 0x14,
- 0xfc, 0xa4, 0x43, 0xd7, 0xf8, 0x5d, 0x98, 0x31, 0x7b, 0x8b, 0x17, 0xff,
- 0xa3, 0x51, 0xa1, 0xc7, 0xec, 0x38, 0xdb, 0xaf, 0x5f, 0xc7, 0x2c, 0x5f,
- 0x6e, 0xcd, 0xba, 0xa2, 0x31, 0x2f, 0xff, 0x9a, 0x1c, 0x29, 0xcd, 0xc7,
- 0xa7, 0x16, 0xeb, 0x17, 0xfc, 0x26, 0x3b, 0x6b, 0x59, 0xda, 0xc5, 0x69,
- 0x17, 0x84, 0x63, 0xc5, 0x1b, 0xf7, 0x1f, 0xa4, 0x9d, 0x62, 0xf7, 0x70,
- 0xd9, 0x62, 0xdf, 0x93, 0xca, 0xc2, 0xab, 0xfd, 0x1a, 0xba, 0x05, 0xaf,
- 0x5e, 0xbf, 0x8e, 0x58, 0xbf, 0x74, 0x6e, 0x4c, 0x16, 0x2f, 0xee, 0x7b,
- 0xbd, 0xdf, 0xeb, 0x17, 0xbe, 0xe1, 0xac, 0x5d, 0x09, 0xf9, 0xe7, 0x80,
- 0xc6, 0xff, 0xfe, 0x11, 0x31, 0xbd, 0x7c, 0x6c, 0x94, 0x33, 0xee, 0x75,
- 0x8b, 0x7d, 0x62, 0xfa, 0x7b, 0x83, 0x2c, 0x53, 0x9b, 0x58, 0x84, 0xaf,
- 0xa4, 0xfb, 0x81, 0x62, 0xf1, 0x93, 0x12, 0xc5, 0xff, 0xf4, 0x36, 0x8d,
- 0x53, 0x1a, 0x6d, 0xbe, 0xba, 0xf5, 0xfc, 0x72, 0xc5, 0x62, 0x33, 0x3e,
- 0x42, 0xc4, 0x80, 0x1f, 0xbf, 0x69, 0xf7, 0x7e, 0x8b, 0x17, 0xe1, 0x7a,
- 0x7b, 0x82, 0xc5, 0xec, 0xef, 0xcb, 0x17, 0xfb, 0x0b, 0xf9, 0xe9, 0x1a,
- 0xc5, 0xd9, 0xe9, 0x3d, 0x07, 0x1e, 0xbf, 0xf7, 0x8d, 0x92, 0x86, 0x7d,
- 0xce, 0xb1, 0x7f, 0xc6, 0xc9, 0x43, 0x3e, 0xe7, 0x58, 0xbe, 0x11, 0x31,
- 0xbd, 0x4f, 0xe3, 0xc7, 0xf7, 0x6f, 0xba, 0xc5, 0xfb, 0x40, 0x7f, 0xca,
- 0xc5, 0x1c, 0xff, 0x78, 0x76, 0x21, 0xab, 0xdd, 0xc2, 0x34, 0x58, 0xbf,
- 0xbf, 0xee, 0x67, 0x70, 0x58, 0xa7, 0x3d, 0x41, 0x12, 0x5e, 0x7d, 0x47,
- 0x2c, 0x5f, 0xba, 0xc4, 0x52, 0x35, 0x8b, 0xc6, 0x42, 0x3d, 0x62, 0xd1,
- 0x81, 0x63, 0x21, 0x3e, 0x61, 0x6d, 0xb1, 0xf4, 0x0e, 0x32, 0x32, 0x2d,
- 0xde, 0x7b, 0x26, 0x74, 0xc8, 0x9e, 0x4e, 0x5b, 0xf8, 0xd7, 0xd8, 0xec,
- 0x05, 0x64, 0xf5, 0xc8, 0xc8, 0x3d, 0x08, 0x31, 0x10, 0xc7, 0x10, 0x04,
- 0x2b, 0xbf, 0xfd, 0x18, 0x76, 0x84, 0x66, 0x6b, 0x76, 0x6d, 0xd5, 0x13,
- 0xc9, 0x7b, 0xa4, 0xfd, 0x62, 0xd2, 0xb1, 0x52, 0x6c, 0x34, 0x3f, 0x7d,
- 0x25, 0x0e, 0x2c, 0x5d, 0x9c, 0x58, 0xbf, 0xf3, 0x7a, 0x74, 0x28, 0x6a,
- 0x60, 0xb1, 0x71, 0x9c, 0x58, 0xbd, 0xe9, 0x3a, 0xc5, 0xf3, 0x96, 0x74,
- 0x58, 0xbf, 0x7a, 0x49, 0xc0, 0xb1, 0x7f, 0xd3, 0xb6, 0x7a, 0x49, 0xc0,
- 0xb1, 0x79, 0x88, 0x18, 0x7b, 0xe6, 0x13, 0xd7, 0xd1, 0x69, 0x1d, 0x08,
- 0x2a, 0xd2, 0x75, 0xa0, 0x20, 0x0b, 0x91, 0x10, 0xbf, 0x0f, 0xfc, 0x32,
- 0x64, 0x34, 0x69, 0x62, 0xff, 0x46, 0xff, 0x88, 0x01, 0x4d, 0x71, 0x62,
- 0x96, 0x2f, 0x0f, 0x0e, 0xb1, 0x6e, 0x7c, 0xd4, 0x88, 0x32, 0xe8, 0x18,
- 0xb1, 0x7c, 0x26, 0xd4, 0x16, 0x2f, 0x78, 0xcd, 0x96, 0x2f, 0xff, 0x13,
- 0x41, 0xfe, 0x28, 0xa1, 0x3a, 0xd9, 0x62, 0xf1, 0xc5, 0x1e, 0xb1, 0x7b,
- 0xb8, 0x6e, 0xb1, 0x7e, 0x61, 0xfe, 0x78, 0xb1, 0x7f, 0x7f, 0xf3, 0xdb,
- 0x47, 0xac, 0x52, 0xc5, 0x61, 0xbe, 0xe1, 0x95, 0xa3, 0x02, 0xaa, 0x82,
- 0xc2, 0xd4, 0x32, 0x5a, 0x60, 0x4e, 0x31, 0x9c, 0x23, 0xf9, 0x00, 0x13,
- 0x02, 0xe4, 0x24, 0x41, 0xc6, 0x6a, 0x8c, 0x56, 0x50, 0x1c, 0xa7, 0x9a,
- 0x96, 0x7c, 0x96, 0xc7, 0x10, 0xa4, 0x4a, 0x7e, 0x33, 0x2f, 0x4e, 0xb2,
- 0x5f, 0xb5, 0xbb, 0x36, 0xea, 0x88, 0x80, 0xbf, 0xf3, 0x42, 0x33, 0x35,
- 0xbb, 0x36, 0xea, 0x89, 0x50, 0xbf, 0xb4, 0x2f, 0xc9, 0x6e, 0xb1, 0x7f,
- 0x6e, 0xf8, 0x13, 0xf2, 0xb1, 0x52, 0x7b, 0xf8, 0x5f, 0x7f, 0x7b, 0x08,
- 0xa7, 0x65, 0x8b, 0x46, 0x62, 0x66, 0x67, 0x37, 0x28, 0x57, 0xf8, 0x82,
- 0xfb, 0xa4, 0x96, 0xcb, 0x17, 0xed, 0x6e, 0xcd, 0xba, 0xa2, 0x28, 0x2f,
- 0xda, 0x93, 0xcf, 0x6b, 0x17, 0xf6, 0xa4, 0xfe, 0xc0, 0x2c, 0x5e, 0x38,
- 0x86, 0xb1, 0x7f, 0xe7, 0xf4, 0x52, 0xf9, 0xd1, 0xe3, 0xd6, 0x2d, 0xf7,
- 0x3e, 0x1e, 0x83, 0xd7, 0x8e, 0x28, 0xf5, 0x8b, 0xf7, 0xb9, 0xf1, 0x71,
- 0x62, 0xff, 0x43, 0x06, 0x4c, 0xc3, 0x58, 0xa9, 0x3d, 0xc6, 0x2a, 0xbf,
- 0xf0, 0x9b, 0x4d, 0x0f, 0x3f, 0x04, 0xb1, 0x7f, 0xd3, 0xd9, 0x67, 0xb9,
- 0x27, 0x58, 0xa2, 0x3f, 0x81, 0x1f, 0xdf, 0xf7, 0xf0, 0x6f, 0xcc, 0x20,
- 0x2c, 0x5e, 0x90, 0x62, 0xc5, 0xa3, 0x25, 0x56, 0x3e, 0x12, 0xb9, 0xbe,
- 0x8a, 0x5a, 0x11, 0xe0, 0x29, 0x27, 0xde, 0x42, 0x63, 0xc4, 0x26, 0x1c,
- 0x5f, 0xe8, 0xcc, 0xd6, 0xec, 0xdb, 0xaa, 0x23, 0x22, 0xfd, 0xad, 0xd9,
- 0xb7, 0x54, 0x4c, 0xa5, 0xfa, 0x19, 0xe6, 0xdd, 0x62, 0xfd, 0x18, 0x76,
- 0x84, 0x66, 0x1f, 0x07, 0x66, 0xf7, 0x05, 0x42, 0x8b, 0x17, 0x76, 0x25,
- 0x8b, 0xf6, 0xb7, 0x66, 0xdd, 0x51, 0x52, 0x16, 0x25, 0x8b, 0xa0, 0x75,
- 0x8b, 0xe3, 0xe6, 0x79, 0x62, 0xe0, 0xb8, 0x5d, 0x62, 0xfe, 0x83, 0x8c,
- 0xb3, 0xa2, 0xc5, 0x8c, 0x58, 0xbc, 0x10, 0x40, 0x58, 0xb4, 0x64, 0x68,
- 0x99, 0xec, 0x08, 0x30, 0x66, 0x3c, 0xdf, 0x42, 0x2c, 0x30, 0x17, 0x22,
- 0xf1, 0x00, 0x8b, 0xc2, 0x09, 0xdf, 0xb5, 0xbb, 0x36, 0xea, 0x8a, 0xe8,
- 0xbf, 0xbe, 0xfa, 0xd3, 0x41, 0x62, 0xd1, 0x98, 0x7c, 0xbc, 0x37, 0xbc,
- 0x64, 0x9d, 0x62, 0xfd, 0xad, 0xd9, 0xb7, 0x54, 0x58, 0xa5, 0xa3, 0x24,
- 0xf5, 0x70, 0x7a, 0xff, 0xa7, 0x9c, 0x93, 0xfb, 0x37, 0x58, 0xbe, 0xdd,
- 0x9b, 0x75, 0x44, 0xf4, 0x5f, 0x8e, 0xd0, 0x8c, 0xcd, 0xcf, 0xaf, 0x47,
- 0x57, 0x83, 0x6d, 0xd6, 0x2f, 0xef, 0xcb, 0xe9, 0xc2, 0xeb, 0x17, 0x82,
- 0xef, 0xc5, 0x8b, 0xf9, 0xf6, 0x69, 0xef, 0x8b, 0x17, 0xe9, 0x78, 0xe7,
- 0x08, 0xb1, 0x7d, 0x3d, 0xb0, 0x45, 0x8b, 0x83, 0x8c, 0xc4, 0x78, 0xee,
- 0x3e, 0xe6, 0x3f, 0x21, 0x62, 0xf2, 0x2c, 0xbf, 0xfd, 0x25, 0x19, 0x9f,
- 0x6e, 0xa7, 0x9c, 0xf2, 0xc5, 0xff, 0xff, 0xe1, 0xe0, 0x71, 0x85, 0x86,
- 0x9a, 0xde, 0xe3, 0x94, 0x53, 0xbe, 0xb3, 0xb5, 0x8b, 0xff, 0xff, 0xf7,
- 0x9b, 0x50, 0x8c, 0xce, 0x09, 0xbb, 0xc2, 0x90, 0xcc, 0xf3, 0xc3, 0x3b,
- 0xf2, 0xc5, 0xff, 0xfe, 0x79, 0x2f, 0x46, 0x7d, 0xe4, 0xb6, 0xf7, 0x7b,
- 0xb9, 0x2c, 0x5f, 0xb3, 0xdf, 0x70, 0xd6, 0x2f, 0xfd, 0xcc, 0x26, 0x37,
- 0xef, 0x24, 0xb1, 0x7f, 0xd9, 0x9f, 0x7d, 0xff, 0x91, 0x84, 0x7c, 0xde,
- 0x29, 0xbe, 0x72, 0x36, 0x56, 0x2f, 0x13, 0x44, 0xb1, 0x7b, 0x82, 0x25,
- 0x8b, 0xfe, 0x9f, 0xb8, 0xff, 0x30, 0xe2, 0xc5, 0x70, 0xf5, 0xba, 0x0e,
- 0xdf, 0x8a, 0x62, 0x98, 0xf5, 0x8a, 0x82, 0x39, 0x30, 0x89, 0xdc, 0xfc,
- 0x49, 0x7b, 0xcd, 0xba, 0xc5, 0xfa, 0x41, 0xc7, 0xed, 0x62, 0xcf, 0xd9,
- 0xe3, 0xfc, 0x7a, 0xff, 0x66, 0xb6, 0x9e, 0x38, 0xd6, 0x2e, 0x62, 0x58,
- 0xbf, 0xec, 0x3c, 0xff, 0xd8, 0xfd, 0x16, 0x2f, 0xe9, 0x3e, 0x84, 0xdc,
- 0x58, 0xa3, 0x9f, 0xf7, 0x05, 0xbc, 0x75, 0x7a, 0x70, 0x6b, 0x17, 0x9f,
- 0x36, 0x58, 0xb1, 0xab, 0x17, 0x7d, 0xe3, 0xcd, 0x86, 0x87, 0x6e, 0xef,
- 0xcb, 0x17, 0xe8, 0x49, 0x4c, 0x4b, 0x17, 0xf7, 0xdf, 0x9a, 0xce, 0xd6,
- 0x2f, 0xf4, 0xfb, 0x8f, 0x14, 0x81, 0x62, 0xa5, 0x14, 0x9d, 0x8c, 0xc4,
- 0x51, 0xf2, 0xfb, 0xd8, 0x5b, 0xac, 0x5f, 0xa2, 0xdf, 0xf3, 0xb2, 0xc5,
- 0x61, 0xe4, 0xb0, 0xed, 0xf0, 0x9b, 0x38, 0xb1, 0x7d, 0xe1, 0x37, 0x16,
- 0x2f, 0xce, 0x58, 0x79, 0x58, 0xec, 0xd1, 0xdf, 0xdb, 0x6c, 0xe5, 0x30,
- 0x58, 0xbd, 0xb9, 0xb2, 0xb1, 0x7c, 0xfc, 0x11, 0xd6, 0x2f, 0xa7, 0xf3,
- 0x05, 0x8b, 0xd3, 0xe7, 0x58, 0xbf, 0x33, 0xf7, 0xec, 0x58, 0xbf, 0x19,
- 0x3a, 0x93, 0xac, 0x54, 0x11, 0x64, 0x32, 0x3d, 0x11, 0x00, 0x73, 0x85,
- 0x17, 0x9e, 0x7c, 0xb1, 0x50, 0x4e, 0x77, 0x0d, 0xfb, 0x2f, 0x78, 0x68,
- 0x86, 0x95, 0x7c, 0x3f, 0xb6, 0x96, 0x2a, 0x4f, 0xcd, 0x94, 0x2f, 0x9f,
- 0xd3, 0xa5, 0x8b, 0xef, 0x7a, 0x7c, 0xb1, 0x7a, 0x26, 0xf2, 0xc5, 0x7c,
- 0xf8, 0xd8, 0x88, 0xc2, 0x3b, 0xed, 0xc4, 0xd0, 0x58, 0xbf, 0xd0, 0x90,
- 0x45, 0x09, 0xd9, 0x62, 0xf1, 0x49, 0xab, 0x15, 0x11, 0xe9, 0x9c, 0xda,
- 0xfb, 0xd0, 0x61, 0xac, 0x54, 0xa2, 0xf7, 0x1d, 0xd8, 0x8e, 0xff, 0xa5,
- 0xfd, 0xc7, 0x2e, 0xe0, 0xb1, 0x74, 0xe9, 0x62, 0xfe, 0xd6, 0x74, 0x92,
- 0xf2, 0xc5, 0xff, 0x77, 0xbb, 0x9b, 0x84, 0xe6, 0xac, 0x5b, 0x34, 0x7d,
- 0x7e, 0x2f, 0xaf, 0xa3, 0x89, 0x8e, 0x4a, 0x10, 0x57, 0xf4, 0x33, 0xff,
- 0x68, 0x2c, 0x5d, 0xb6, 0xcb, 0x17, 0xec, 0xf8, 0xcc, 0xe2, 0xc5, 0xc3,
- 0x8c, 0x96, 0x46, 0x4c, 0x21, 0x04, 0x32, 0x8c, 0x85, 0x91, 0xa5, 0xfb,
- 0xa6, 0x3c, 0x34, 0xe2, 0x84, 0x3e, 0x88, 0x3f, 0x29, 0x55, 0xa1, 0x06,
- 0x50, 0xec, 0xe4, 0x61, 0xfe, 0x33, 0x0c, 0xb8, 0xc1, 0xab, 0xe7, 0xd7,
- 0xd9, 0x62, 0xfe, 0x70, 0xc6, 0xcc, 0x6a, 0xc5, 0xfd, 0x11, 0x49, 0xe3,
- 0x33, 0xe7, 0xa3, 0xc2, 0x2b, 0xfd, 0xbb, 0xea, 0x30, 0xee, 0x35, 0x8b,
- 0xb9, 0xe5, 0x8b, 0xfb, 0xef, 0xce, 0x66, 0x96, 0x2e, 0xce, 0x2c, 0x5f,
- 0xfb, 0x35, 0xdc, 0x9f, 0xed, 0x9a, 0x58, 0xbb, 0x80, 0x58, 0xbf, 0x13,
- 0x1c, 0xa5, 0x62, 0xfe, 0x17, 0x3e, 0xd0, 0x8c, 0x8d, 0x11, 0xb5, 0xb8,
- 0xc3, 0x17, 0x10, 0xb8, 0x67, 0xe6, 0x0c, 0x5e, 0xda, 0x63, 0xd6, 0x2f,
- 0xed, 0x6d, 0x23, 0xc2, 0x58, 0xbb, 0x5e, 0x58, 0xbf, 0x67, 0xb8, 0xe7,
- 0x58, 0xbf, 0xfd, 0x3d, 0xfb, 0x22, 0x7d, 0x7b, 0x82, 0x8f, 0x58, 0xbc,
- 0xdd, 0xc6, 0x4a, 0x37, 0xf0, 0x85, 0x8b, 0x88, 0x63, 0xc5, 0x15, 0x2b,
- 0x8f, 0xd9, 0x1b, 0x47, 0x68, 0xfa, 0x8c, 0x4b, 0x91, 0xb1, 0x54, 0x1b,
- 0x0f, 0x91, 0xa6, 0xf6, 0xff, 0xf8, 0x44, 0x94, 0x32, 0xbd, 0x4e, 0x7c,
- 0xa8, 0xc6, 0xcb, 0xfe, 0x63, 0x33, 0x7a, 0xc5, 0x76, 0xff, 0xff, 0x6b,
- 0xde, 0x98, 0x7e, 0x5f, 0x52, 0x5e, 0xe0, 0xa5, 0x62, 0xff, 0xbc, 0x2d,
- 0x8c, 0x8b, 0x82, 0xed, 0x62, 0xf3, 0x7f, 0x8b, 0x17, 0x0e, 0x33, 0x11,
- 0x7b, 0xe6, 0x00, 0xd0, 0x2f, 0x48, 0x82, 0xeb, 0x17, 0xed, 0x6f, 0xf7,
- 0xe2, 0xc5, 0x39, 0xe5, 0x88, 0x86, 0xef, 0x4a, 0xc5, 0x05, 0x0d, 0xc7,
- 0x64, 0x37, 0xb6, 0x8e, 0x8d, 0xd6, 0x2f, 0xf6, 0x74, 0x2c, 0xe0, 0x0e,
- 0xb1, 0x41, 0x61, 0xee, 0x11, 0x3d, 0xf9, 0xfe, 0x4d, 0x12, 0xc5, 0xf8,
- 0x47, 0x3b, 0x44, 0xb1, 0x7e, 0x7e, 0xf3, 0x36, 0x58, 0xb6, 0x7c, 0xf4,
- 0xfa, 0x15, 0x5d, 0x1d, 0x1b, 0xac, 0x5e, 0x0b, 0x70, 0x1a, 0xc5, 0xfa,
- 0x18, 0x3e, 0xb8, 0xb1, 0x7e, 0x67, 0xdb, 0x52, 0xb1, 0x7d, 0xde, 0xee,
- 0x4b, 0x17, 0xef, 0x10, 0x9a, 0x36, 0x58, 0xa0, 0xa2, 0x76, 0x21, 0x52,
- 0x68, 0xd9, 0xec, 0x2d, 0x94, 0x85, 0x84, 0x12, 0x49, 0xf2, 0xaf, 0x14,
- 0x18, 0x49, 0x71, 0xc0, 0xb1, 0x7f, 0xc1, 0x50, 0xcd, 0xde, 0x28, 0x08,
- 0xd5, 0x8b, 0xf6, 0x79, 0xc5, 0xc5, 0x8b, 0x82, 0x81, 0x6a, 0xb1, 0x41,
- 0x44, 0x54, 0x46, 0x83, 0x01, 0x6a, 0x8b, 0x1a, 0x8a, 0x2f, 0xd1, 0xac,
- 0x29, 0xcd, 0x79, 0x62, 0xff, 0x18, 0x59, 0xad, 0x4e, 0xeb, 0x14, 0x14,
- 0x3e, 0x98, 0xd8, 0xd2, 0xfb, 0x47, 0xf7, 0x6b, 0x17, 0xe8, 0xdc, 0x2a,
- 0x7e, 0x1a, 0xb1, 0x73, 0xf1, 0x62, 0xc1, 0xac, 0x50, 0x50, 0xf7, 0xb7,
- 0x34, 0x30, 0x5e, 0xfd, 0x1b, 0x85, 0x66, 0x07, 0x58, 0xba, 0x63, 0xd6,
- 0x2c, 0x35, 0x8a, 0xf9, 0xac, 0xf0, 0xd5, 0xff, 0xa3, 0x54, 0x69, 0x1b,
- 0x05, 0x63, 0x68, 0xd8, 0x2c, 0x8d, 0x82, 0x8b, 0x17, 0xfe, 0x8d, 0x71,
- 0xb0, 0x59, 0x1a, 0xe3, 0x58, 0x54, 0x2b, 0x1b, 0x85, 0x16, 0x2f, 0xfc,
- 0x16, 0x46, 0xa8, 0xd6, 0x16, 0x46, 0xb0, 0xa8, 0x5a, 0xc6, 0xb0, 0xa2,
- 0xc5, 0xff, 0x7c, 0x70, 0x8c, 0x87, 0x0a, 0x30, 0x2a, 0x9a, 0x84, 0x68,
- 0xdc, 0x16, 0xad, 0xf4, 0x14, 0x54, 0x8a, 0x15, 0x5e, 0x0b, 0x58, 0xdc,
- 0x6f, 0xc1, 0x53, 0xb3, 0x12, 0xc5, 0xfd, 0x2f, 0xef, 0x49, 0xd6, 0x2e,
- 0x1c, 0x7a, 0xc5, 0x46, 0xe7, 0xe7, 0x1a, 0xca, 0xfb, 0x2d, 0xbd, 0xbe,
- 0x7d, 0x22, 0xee, 0x69, 0x62, 0xe9, 0xe2, 0xc5, 0xb4, 0xb1, 0x63, 0xac,
- 0x51, 0xcd, 0xdf, 0x85, 0xc3, 0x12, 0xbf, 0xff, 0xde, 0x33, 0x53, 0xf9,
- 0xcd, 0xc6, 0xe5, 0xb1, 0xe6, 0x0b, 0x17, 0x6a, 0x56, 0x29, 0xcf, 0xe8,
- 0x0c, 0x77, 0xda, 0xd3, 0x41, 0x62, 0xff, 0x66, 0xf3, 0xd7, 0xec, 0x75,
- 0x8a, 0x93, 0xd9, 0xf9, 0x1d, 0xff, 0xc4, 0x29, 0xea, 0xcf, 0xe8, 0x67,
- 0x16, 0x2f, 0xfe, 0xfc, 0xf1, 0x8c, 0xff, 0xdf, 0xbe, 0x2c, 0x5f, 0xf3,
- 0xc9, 0x67, 0x4d, 0x4f, 0x16, 0x2b, 0x74, 0x40, 0x7d, 0x1e, 0xf4, 0x4e,
- 0x1a, 0xc5, 0xf8, 0x02, 0x84, 0x19, 0x62, 0x9c, 0xf2, 0x0c, 0x1f, 0xbd,
- 0x13, 0x86, 0xb1, 0x76, 0x41, 0x62, 0x9c, 0xdb, 0x30, 0xfd, 0x1c, 0xfd,
- 0xc0, 0xb1, 0x7f, 0xe7, 0xeb, 0xf7, 0x68, 0x79, 0xf6, 0x58, 0xac, 0x3e,
- 0x3f, 0x91, 0x5f, 0xbc, 0x03, 0x0a, 0x25, 0x8b, 0xff, 0x37, 0x3a, 0xf3,
- 0x99, 0x08, 0x4a, 0xc5, 0xb8, 0xb1, 0x7f, 0x4e, 0xef, 0xb3, 0x12, 0xc5,
- 0xff, 0xf8, 0x98, 0xd7, 0xd4, 0xc2, 0x19, 0xc0, 0x02, 0x56, 0x2f, 0xf3,
- 0x78, 0x59, 0x84, 0x6a, 0xc5, 0x0d, 0x35, 0x5c, 0x21, 0x34, 0xae, 0x24,
- 0x1d, 0x09, 0x7c, 0xb8, 0x0a, 0xb7, 0xe2, 0x91, 0x8b, 0x8b, 0x16, 0x12,
- 0xc5, 0xf4, 0x94, 0xc4, 0xb1, 0x44, 0x6d, 0x3c, 0x25, 0x74, 0xe9, 0x62,
- 0xc1, 0x75, 0x8b, 0xd3, 0xf9, 0x58, 0xa9, 0x46, 0x2e, 0x2e, 0x1a, 0x41,
- 0x10, 0xb9, 0x0b, 0x5f, 0xf8, 0xb0, 0x5b, 0x96, 0x6c, 0x64, 0x16, 0x2f,
- 0xec, 0xd0, 0x1b, 0x00, 0xb1, 0x7f, 0xd3, 0xad, 0x38, 0x4d, 0xc5, 0xb2,
- 0xc5, 0xcc, 0x7e, 0xa7, 0xd7, 0x18, 0x5b, 0x76, 0x9c, 0x91, 0xbc, 0x12,
- 0x15, 0x97, 0xcf, 0xf3, 0x0e, 0xb1, 0x7b, 0xdb, 0x32, 0xc5, 0xff, 0xe7,
- 0x37, 0xae, 0x13, 0x77, 0xc3, 0x4d, 0x65, 0x8a, 0xdd, 0x12, 0x2e, 0x48,
- 0x43, 0xd7, 0xdd, 0xb7, 0xe5, 0x62, 0xff, 0x85, 0x9a, 0x2c, 0xf7, 0xdd,
- 0x62, 0xfe, 0x87, 0x53, 0xb7, 0xa5, 0x62, 0xa0, 0x7d, 0x1d, 0x9c, 0x5f,
- 0xfd, 0xc2, 0xc0, 0x46, 0x7d, 0xf7, 0x6d, 0x2c, 0x5d, 0x98, 0xb1, 0x52,
- 0x98, 0x63, 0xc2, 0x2d, 0x88, 0xc3, 0x48, 0xb8, 0x83, 0x58, 0xbf, 0x70,
- 0x84, 0xd0, 0x58, 0xbf, 0xfd, 0xc7, 0x3f, 0x7c, 0x6f, 0x0b, 0xbe, 0x4a,
- 0xc5, 0xfd, 0xe8, 0xa0, 0xda, 0x35, 0x62, 0xec, 0xdd, 0x62, 0xf0, 0xf0,
- 0xd6, 0x3c, 0x9f, 0x18, 0xdf, 0x7e, 0x4f, 0xba, 0xc5, 0x4a, 0x65, 0xb8,
- 0x31, 0xd9, 0x43, 0x42, 0x5b, 0xc6, 0x77, 0x08, 0x0b, 0x17, 0xef, 0x7d,
- 0xc4, 0x17, 0x58, 0xa8, 0x1e, 0x2e, 0x0c, 0x5f, 0x66, 0x11, 0xab, 0x17,
- 0xd0, 0xd9, 0x8d, 0x58, 0xbf, 0xf8, 0xa7, 0xdc, 0xc2, 0x17, 0x84, 0x6a,
- 0xc5, 0x75, 0x3e, 0xae, 0x12, 0xd7, 0x11, 0xa3, 0xe2, 0x11, 0x42, 0x32,
- 0xf0, 0xf3, 0xeb, 0x17, 0xa2, 0x70, 0xd6, 0x2c, 0x38, 0x1b, 0xc7, 0x1d,
- 0xbf, 0xfd, 0x9b, 0x8d, 0xc8, 0xcc, 0xd6, 0xa7, 0xa2, 0xc5, 0xff, 0xdd,
- 0x66, 0x4a, 0x4f, 0xd7, 0xaf, 0xe3, 0x96, 0x2a, 0x51, 0x80, 0x02, 0x62,
- 0x4d, 0xbf, 0xf7, 0x51, 0xe1, 0x38, 0x39, 0xf7, 0x58, 0xbf, 0xd0, 0x9c,
- 0x21, 0xc9, 0xd6, 0x2b, 0x47, 0xe4, 0x17, 0x40, 0xbd, 0xd0, 0x50, 0x58,
- 0xbf, 0xf7, 0x1b, 0xa8, 0xf3, 0xdc, 0x6e, 0xd6, 0x2f, 0xfd, 0xfc, 0x8b,
- 0xef, 0xf9, 0xd4, 0xac, 0x5c, 0xdd, 0xac, 0x5e, 0x29, 0x8f, 0x58, 0xbf,
- 0xcd, 0xc6, 0xf8, 0x8b, 0x65, 0x8a, 0x23, 0xeb, 0xf0, 0xc0, 0x87, 0xeb,
- 0xab, 0x3d, 0x33, 0x65, 0x38, 0x42, 0xa4, 0x6f, 0x58, 0x43, 0xdc, 0x31,
- 0x5e, 0x54, 0xdc, 0x51, 0x95, 0xea, 0x32, 0x73, 0xc3, 0x17, 0xf1, 0x9d,
- 0x94, 0x6d, 0xdc, 0x8d, 0x93, 0xd1, 0x98, 0x8a, 0x14, 0x1d, 0x09, 0x83,
- 0x20, 0x31, 0x08, 0x24, 0x2a, 0xae, 0xe0, 0x96, 0x2f, 0x4c, 0x74, 0x6e,
- 0xb1, 0x6d, 0x2c, 0x5d, 0x3a, 0x58, 0xbc, 0x58, 0x11, 0x62, 0xf9, 0xa7,
- 0xb8, 0x2c, 0x5d, 0x9f, 0x58, 0xbf, 0x6b, 0xb8, 0x7a, 0x56, 0x2f, 0x67,
- 0x4c, 0x58, 0xac, 0x3c, 0x82, 0x2a, 0xae, 0xa8, 0xe9, 0xdc, 0x49, 0x85,
- 0xf8, 0x3d, 0x1c, 0x46, 0x62, 0xfd, 0xf6, 0x1d, 0xfc, 0xb1, 0x52, 0x9d,
- 0x2c, 0x06, 0x35, 0x18, 0x77, 0x97, 0x6e, 0x16, 0x96, 0x2c, 0x75, 0x8a,
- 0xdc, 0xd5, 0x1c, 0x62, 0xfb, 0x22, 0x73, 0xac, 0x5d, 0xa0, 0x2c, 0x5c,
- 0xd8, 0xb1, 0x5d, 0x9a, 0xed, 0x0c, 0x5e, 0x26, 0xf2, 0xc5, 0xe2, 0x7e,
- 0x2c, 0x5e, 0x2c, 0xed, 0x62, 0xec, 0xed, 0x62, 0xc1, 0x85, 0x4f, 0xb6,
- 0x47, 0x36, 0x1c, 0x18, 0xed, 0xd3, 0xf5, 0x8b, 0xed, 0x74, 0x63, 0xac,
- 0x5f, 0xdb, 0x9c, 0xa7, 0xb0, 0x2c, 0x5c, 0xc7, 0x58, 0xbd, 0xc8, 0x4a,
- 0xc5, 0xfb, 0x99, 0x98, 0xeb, 0x15, 0x87, 0x86, 0x01, 0xdb, 0xff, 0xcf,
- 0xd6, 0x62, 0x7f, 0x6a, 0x77, 0x16, 0xeb, 0x17, 0x80, 0xdd, 0xac, 0x5f,
- 0x67, 0xa4, 0x35, 0x8a, 0xc3, 0xc1, 0x21, 0xeb, 0xff, 0xcf, 0xd7, 0xf9,
- 0x13, 0xf7, 0xcf, 0xe6, 0xeb, 0x17, 0x17, 0x16, 0x2f, 0xfa, 0x19, 0xec,
- 0x16, 0xec, 0x4b, 0x17, 0xc4, 0xde, 0xe2, 0xc5, 0x40, 0xfc, 0xbb, 0x17,
- 0x39, 0xcd, 0xe9, 0xcd, 0x2c, 0x5f, 0xfe, 0xdd, 0xb4, 0xde, 0x7e, 0x49,
- 0x48, 0x16, 0x2d, 0x0f, 0x9f, 0x29, 0x83, 0x97, 0xec, 0x0a, 0x93, 0x8d,
- 0x62, 0xbb, 0x47, 0x4e, 0xa1, 0x2a, 0x02, 0x9a, 0x95, 0xd2, 0xdd, 0x9b,
- 0x60, 0x44, 0x35, 0x1c, 0x84, 0x7e, 0xe8, 0xee, 0x2f, 0x11, 0x2e, 0x8c,
- 0x0e, 0xb4, 0x02, 0x1e, 0x42, 0x43, 0xc4, 0x02, 0x8e, 0xaa, 0xf8, 0x67,
- 0x0f, 0x8b, 0x17, 0xfb, 0x7f, 0xbe, 0x9f, 0x20, 0xb1, 0x71, 0xae, 0xb1,
- 0x40, 0x3c, 0xce, 0x1a, 0x5e, 0x73, 0x0e, 0xb1, 0x63, 0xac, 0x5c, 0xe3,
- 0x58, 0xa6, 0x3c, 0x7e, 0x0f, 0x18, 0x25, 0x7b, 0xf2, 0x4b, 0x17, 0xb8,
- 0x10, 0x22, 0xc5, 0xf7, 0x58, 0x00, 0xeb, 0x17, 0xb5, 0x83, 0x58, 0xbf,
- 0xba, 0x96, 0x02, 0x40, 0xb1, 0x78, 0xb3, 0x8b, 0x17, 0xdb, 0x08, 0x18,
- 0x47, 0x97, 0xd0, 0xbe, 0xff, 0x37, 0xa6, 0x2e, 0x39, 0xd6, 0x28, 0xd4,
- 0x6b, 0xe9, 0xa3, 0xe7, 0x77, 0xfa, 0x60, 0x59, 0xdf, 0xb1, 0x62, 0xfd,
- 0xbb, 0xf7, 0xb1, 0x2c, 0x5f, 0xfc, 0xdb, 0xc9, 0x0e, 0x28, 0x4e, 0xb6,
- 0x58, 0xae, 0xcf, 0xcb, 0xe5, 0x76, 0xe2, 0xc5, 0x39, 0xb5, 0xe1, 0x1d,
- 0xe3, 0xe1, 0xd6, 0x2f, 0xda, 0x66, 0x6f, 0x2c, 0x50, 0xcf, 0x10, 0x87,
- 0x6f, 0xff, 0xbd, 0xc1, 0xeb, 0x1c, 0xdf, 0x86, 0xc5, 0xb2, 0xc5, 0xf1,
- 0x0f, 0x0d, 0x58, 0xbd, 0xf1, 0x1d, 0x62, 0xee, 0x83, 0x58, 0xa0, 0xb6,
- 0xb9, 0x05, 0x2e, 0x30, 0x69, 0x19, 0x7e, 0x0e, 0x76, 0x44, 0xf0, 0xfd,
- 0xd1, 0x8f, 0xe1, 0xb4, 0xcc, 0x9c, 0x21, 0xf2, 0x98, 0x88, 0xc3, 0x1e,
- 0xbf, 0x61, 0x14, 0xec, 0xb1, 0x6e, 0xd6, 0x34, 0x69, 0xe9, 0x62, 0xe2,
- 0x82, 0xc5, 0x39, 0xa3, 0x10, 0x65, 0xfb, 0x91, 0x49, 0x6c, 0xb1, 0x58,
- 0x89, 0x03, 0x51, 0xbc, 0x41, 0x7b, 0xac, 0x36, 0x58, 0xbf, 0xe2, 0x7d,
- 0x4e, 0x17, 0xc4, 0xb1, 0x78, 0xef, 0xc5, 0x8b, 0xf1, 0x1a, 0xf9, 0xc5,
- 0x8b, 0xff, 0x41, 0xb5, 0xb7, 0xc5, 0xb0, 0x3c, 0xb1, 0x7f, 0x9c, 0x07,
- 0x68, 0x61, 0x2c, 0x5f, 0xbe, 0xfc, 0x71, 0xac, 0x5e, 0x79, 0x3a, 0xc5,
- 0xb5, 0x03, 0xc4, 0xf9, 0x45, 0xf3, 0x79, 0xb7, 0x58, 0xa7, 0x3c, 0xb0,
- 0xca, 0x2f, 0x84, 0x17, 0xe6, 0xcb, 0x17, 0xfe, 0x0d, 0x81, 0x9b, 0xfd,
- 0x81, 0xc5, 0x8a, 0x93, 0xea, 0xc2, 0x9b, 0xf7, 0x24, 0x06, 0x6c, 0xb1,
- 0x7f, 0xee, 0x37, 0x72, 0x4c, 0x3c, 0x35, 0x62, 0x8d, 0x54, 0xbe, 0xe3,
- 0xb1, 0x14, 0x69, 0x0f, 0xf0, 0xc1, 0x28, 0x46, 0x70, 0x83, 0xc5, 0x77,
- 0xff, 0xe7, 0xef, 0x9f, 0x0d, 0xbd, 0x24, 0xc4, 0x29, 0x58, 0xbf, 0xff,
- 0x75, 0xfe, 0x0d, 0xcb, 0x0f, 0xdf, 0x84, 0xdc, 0x58, 0xa0, 0x22, 0xb7,
- 0xa2, 0xad, 0xc1, 0x8d, 0x62, 0xff, 0xf7, 0xbf, 0x87, 0x03, 0x6b, 0x3a,
- 0x60, 0xd6, 0x2e, 0x9f, 0xac, 0x58, 0x6b, 0x14, 0x73, 0x52, 0x42, 0xf6,
- 0x35, 0x62, 0xf1, 0x02, 0x56, 0x2e, 0x21, 0xf5, 0x35, 0xfc, 0x13, 0xbb,
- 0x3c, 0xb1, 0x7e, 0xe0, 0x6c, 0x5b, 0x2c, 0x5f, 0x49, 0xf0, 0x0b, 0x15,
- 0x87, 0x99, 0xb9, 0x55, 0x4a, 0x6e, 0xf8, 0xea, 0xc9, 0xe0, 0x2e, 0x26,
- 0x3b, 0xfc, 0x4c, 0x1f, 0x56, 0xdf, 0x16, 0x2f, 0x89, 0xa3, 0xfb, 0x58,
- 0xbd, 0xc6, 0xdd, 0x62, 0xbc, 0x78, 0x82, 0x26, 0xbf, 0xf0, 0x87, 0xf7,
- 0x9e, 0x9a, 0x33, 0x8b, 0x15, 0xa3, 0xe5, 0x22, 0x2b, 0xef, 0x47, 0x67,
- 0xd6, 0x2f, 0x70, 0x72, 0xb1, 0x7f, 0xb3, 0x79, 0x21, 0x34, 0x16, 0x2f,
- 0xff, 0xed, 0xf3, 0xbf, 0x7d, 0xf5, 0x2d, 0x00, 0x66, 0x44, 0xb1, 0x7f,
- 0xbd, 0x9b, 0x88, 0x0d, 0x8b, 0x14, 0x6a, 0x31, 0x08, 0xcf, 0x8b, 0xb4,
- 0x6a, 0x62, 0x2d, 0x0e, 0x1a, 0x94, 0xe0, 0x70, 0x84, 0x51, 0x9b, 0xde,
- 0xe3, 0x74, 0x58, 0xb7, 0x16, 0x2d, 0x8b, 0x14, 0xe6, 0x8c, 0x20, 0x95,
- 0xf3, 0x78, 0x02, 0x58, 0xbc, 0x52, 0x6a, 0xc5, 0xff, 0xde, 0xe6, 0x06,
- 0x63, 0x16, 0x9f, 0x75, 0x8a, 0xdd, 0x10, 0xfd, 0x91, 0x86, 0x3b, 0x7f,
- 0x9c, 0xc3, 0xe6, 0x11, 0xab, 0x15, 0xda, 0x6a, 0x47, 0x42, 0x68, 0x54,
- 0x80, 0xce, 0xff, 0xb0, 0x9a, 0x1c, 0x80, 0x7b, 0x2c, 0x5f, 0x43, 0x8e,
- 0x4b, 0x17, 0xdf, 0xde, 0x77, 0x58, 0xbf, 0xf6, 0xe4, 0xdf, 0x6e, 0xf3,
- 0xbf, 0x2c, 0x5f, 0xe2, 0x63, 0x74, 0xf2, 0x6a, 0xc5, 0x41, 0x1e, 0xfd,
- 0x9d, 0xb9, 0x10, 0x89, 0x43, 0x41, 0xb1, 0x8b, 0x17, 0xdb, 0x06, 0xd0,
- 0x58, 0xbf, 0xfa, 0x74, 0x23, 0x93, 0x1a, 0x3d, 0x05, 0xd6, 0x2f, 0x63,
- 0x1d, 0x62, 0x8d, 0x3e, 0x6d, 0x25, 0x54, 0xa6, 0x19, 0xda, 0x5b, 0x89,
- 0xb4, 0x22, 0xef, 0x8b, 0xce, 0x75, 0x8b, 0xd3, 0x30, 0x58, 0xc3, 0x45,
- 0x7f, 0x4f, 0x27, 0xf3, 0xc5, 0x8b, 0xdb, 0xbe, 0xeb, 0x17, 0xf1, 0x34,
- 0x1f, 0xe2, 0x58, 0xbd, 0x1d, 0x9f, 0x58, 0xbb, 0x50, 0x93, 0xec, 0xf8,
- 0xff, 0x8b, 0x6b, 0x48, 0xd3, 0x68, 0x4c, 0xdd, 0xec, 0x58, 0xa9, 0x66,
- 0xec, 0xec, 0x61, 0x02, 0x1c, 0x95, 0x2c, 0x6c, 0x65, 0x5d, 0x92, 0xbc,
- 0x72, 0x1a, 0x47, 0xfc, 0xa6, 0x06, 0x8e, 0x1c, 0xa5, 0x23, 0x71, 0x8c,
- 0x50, 0xfe, 0x30, 0x9e, 0xfc, 0xfc, 0x21, 0x79, 0x62, 0xf8, 0x1c, 0x30,
- 0x0b, 0x17, 0xff, 0x8d, 0x6c, 0xef, 0xde, 0x9c, 0xe8, 0xfb, 0xac, 0x5e,
- 0x72, 0x02, 0xc5, 0xff, 0xa1, 0xc9, 0x29, 0xde, 0x5f, 0xeb, 0x17, 0xfb,
- 0x52, 0x5e, 0xfe, 0x41, 0x62, 0xbb, 0x3f, 0x1e, 0x87, 0xd7, 0xf8, 0xb3,
- 0x9e, 0x66, 0x25, 0x8a, 0x35, 0x33, 0x1f, 0xa7, 0x34, 0x23, 0x7a, 0x12,
- 0xdf, 0x04, 0x09, 0x31, 0xeb, 0x17, 0xff, 0xde, 0x72, 0x14, 0x33, 0x83,
- 0x13, 0x6a, 0x0b, 0x16, 0x9e, 0xa7, 0xf4, 0x61, 0x55, 0xff, 0x8e, 0xd0,
- 0xcf, 0xbe, 0xbe, 0xcb, 0x17, 0x3e, 0xb4, 0x7d, 0x00, 0x2a, 0xbf, 0xff,
- 0x8b, 0x0d, 0xc2, 0xeb, 0xcf, 0x7f, 0x0e, 0x64, 0x81, 0x62, 0xa5, 0x11,
- 0x78, 0x5b, 0x7f, 0x84, 0xdc, 0x78, 0x9c, 0x35, 0x8a, 0x95, 0x6b, 0xcf,
- 0x1a, 0xb7, 0xe3, 0xb2, 0x22, 0x1b, 0xfe, 0x0c, 0x98, 0xdc, 0x1b, 0x92,
- 0xc5, 0xef, 0xc9, 0x2c, 0x5f, 0x7b, 0xcd, 0xba, 0xc5, 0xde, 0x3a, 0xc5,
- 0xa3, 0x96, 0x2a, 0x07, 0xa3, 0xd9, 0x27, 0xc6, 0x2a, 0x51, 0xad, 0xb9,
- 0xcb, 0x36, 0xdf, 0x0f, 0x4e, 0x1a, 0xc5, 0xfd, 0x99, 0xb6, 0x67, 0x96,
- 0x2e, 0x37, 0xa2, 0xc5, 0xec, 0x10, 0xd6, 0x2b, 0x64, 0x44, 0x8c, 0x90,
- 0x8b, 0x78, 0x37, 0x7e, 0xc8, 0x48, 0x38, 0xb1, 0x7f, 0xff, 0x7e, 0x79,
- 0x90, 0xfc, 0x9c, 0x98, 0xd2, 0xc0, 0x2c, 0x54, 0x11, 0x05, 0xe2, 0x8b,
- 0xfe, 0xd7, 0x5f, 0xe0, 0xca, 0x77, 0x58, 0xa9, 0x3d, 0xf7, 0x23, 0xbc,
- 0xe5, 0xe5, 0x8b, 0xe9, 0xdf, 0x34, 0xb1, 0x7d, 0xf9, 0xe9, 0x8b, 0x17,
- 0xf3, 0x74, 0x78, 0x9c, 0x35, 0x8a, 0x3a, 0x25, 0x08, 0x73, 0xc4, 0x66,
- 0x12, 0x5f, 0xe1, 0x6b, 0x63, 0xce, 0x79, 0x62, 0xff, 0xb9, 0x27, 0x1f,
- 0xe4, 0xb7, 0x58, 0xb9, 0xcb, 0x0f, 0xbc, 0xd3, 0x5a, 0x94, 0x6c, 0x0e,
- 0x15, 0x97, 0xfd, 0xb6, 0x6f, 0x22, 0xfe, 0x69, 0x62, 0x96, 0x2e, 0x80,
- 0xa4, 0xf1, 0xf8, 0x77, 0x7e, 0x6d, 0x02, 0x3b, 0x16, 0x2f, 0x05, 0x7a,
- 0x79, 0x62, 0x86, 0x79, 0xfd, 0x0a, 0xef, 0x7c, 0xce, 0x8b, 0x17, 0x3e,
- 0xcb, 0x17, 0xfd, 0x27, 0x2c, 0xdf, 0x4e, 0x05, 0x8b, 0x0d, 0x62, 0xf7,
- 0x39, 0x8b, 0x16, 0x1c, 0x9a, 0xf6, 0x12, 0xa8, 0x23, 0x1b, 0x44, 0x3c,
- 0x18, 0x13, 0x45, 0xf9, 0x9f, 0x7c, 0x25, 0x8b, 0xff, 0xb3, 0x08, 0xdd,
- 0x3f, 0x38, 0xc6, 0xac, 0x57, 0xcf, 0xb0, 0xc2, 0x7b, 0xfd, 0x0c, 0x7e,
- 0x70, 0x52, 0xb1, 0x7f, 0x0f, 0x0a, 0x1f, 0xc5, 0x8b, 0xff, 0xff, 0xd9,
- 0xcf, 0xe6, 0xa4, 0x9b, 0xb8, 0x7e, 0x7d, 0xe9, 0xef, 0xf2, 0x75, 0x8a,
- 0x94, 0x6c, 0x39, 0x99, 0xcb, 0x6f, 0xf7, 0xdf, 0xa3, 0xee, 0x61, 0xd6,
- 0x2f, 0xfd, 0xe9, 0x3f, 0x7b, 0xbf, 0x79, 0xa5, 0x8b, 0xf7, 0xf3, 0x4f,
- 0xc5, 0x8b, 0xc4, 0xf0, 0xdd, 0x14, 0x5d, 0x9c, 0x79, 0x0a, 0xff, 0x7c,
- 0x5b, 0x45, 0x99, 0xba, 0xc5, 0xdd, 0xf9, 0x62, 0xfc, 0x4c, 0x3c, 0x35,
- 0x62, 0xfa, 0x13, 0x9e, 0x58, 0xbb, 0x01, 0x27, 0x95, 0xd9, 0x45, 0xfd,
- 0x3e, 0xc7, 0x10, 0x5d, 0x62, 0x98, 0xf7, 0x80, 0x5b, 0x7f, 0xd9, 0xb6,
- 0x0f, 0x0a, 0x63, 0xd6, 0x2f, 0xff, 0xfd, 0xc9, 0x80, 0x79, 0xf3, 0x3c,
- 0x52, 0x06, 0xf0, 0x0c, 0x28, 0x2c, 0x54, 0xab, 0xd0, 0xda, 0x1f, 0x70,
- 0x86, 0x80, 0xd0, 0x98, 0xdc, 0x10, 0xc1, 0x22, 0x1f, 0x1d, 0xdf, 0xfe,
- 0x2f, 0x47, 0x64, 0x50, 0x6d, 0x6c, 0x39, 0x58, 0xbf, 0xff, 0x8a, 0x13,
- 0xe6, 0xff, 0x1d, 0xbc, 0x03, 0x0a, 0x0b, 0x17, 0xde, 0xf6, 0x47, 0xac,
- 0x5f, 0xf4, 0xe4, 0x3f, 0x8f, 0x0e, 0x2c, 0x57, 0x0f, 0x7b, 0xc4, 0xd7,
- 0xe1, 0xc5, 0xf1, 0x47, 0xac, 0x57, 0x67, 0xa0, 0x44, 0x55, 0x89, 0xbd,
- 0x3a, 0x7b, 0x46, 0x13, 0x7e, 0xd1, 0x3e, 0x1a, 0xb1, 0x7e, 0x9f, 0xbf,
- 0x70, 0x58, 0xb8, 0xf0, 0x58, 0xbf, 0xe6, 0xcd, 0xc7, 0x9a, 0x03, 0xac,
- 0x57, 0x53, 0xfa, 0x19, 0x4f, 0xc6, 0x2f, 0xf7, 0x7c, 0x30, 0x9e, 0x46,
- 0xb1, 0x7f, 0xf4, 0xef, 0x27, 0x92, 0x61, 0xe1, 0xab, 0x15, 0xa4, 0x55,
- 0x11, 0x88, 0x43, 0x5b, 0xfb, 0xbe, 0x7d, 0x98, 0xeb, 0x15, 0x29, 0xd6,
- 0x3c, 0x69, 0x86, 0x18, 0xdf, 0xe8, 0x70, 0xa4, 0x0c, 0x75, 0x8b, 0xf3,
- 0x77, 0xed, 0xa5, 0x62, 0xa4, 0xf7, 0x48, 0xce, 0xfc, 0x6e, 0x0b, 0x5b,
- 0x2c, 0x5f, 0x4e, 0xe2, 0x95, 0x8a, 0xd1, 0xe7, 0x06, 0x57, 0x7f, 0x3e,
- 0xb6, 0x10, 0x31, 0x62, 0xfc, 0x10, 0x47, 0xc1, 0xac, 0x5e, 0xd3, 0x01,
- 0x62, 0xff, 0xd3, 0x9d, 0xfb, 0x0e, 0xc4, 0x05, 0x8b, 0xe9, 0xc2, 0xdd,
- 0x62, 0xbe, 0x7c, 0x1e, 0x3e, 0xbe, 0xef, 0xd2, 0x75, 0x8a, 0x94, 0x61,
- 0x9a, 0xfb, 0xd9, 0x15, 0x89, 0x62, 0xfe, 0x76, 0x87, 0x9f, 0x65, 0x8b,
- 0xfb, 0xcf, 0xf7, 0x2f, 0x2c, 0x57, 0x53, 0xec, 0xf8, 0x89, 0x85, 0xd7,
- 0xf7, 0x1f, 0x3a, 0x36, 0x96, 0x2a, 0x07, 0xc2, 0x73, 0x2b, 0xff, 0x64,
- 0x78, 0xff, 0x3f, 0x9f, 0x71, 0x62, 0xff, 0xf4, 0xe7, 0x7e, 0xfc, 0xf8,
- 0xa4, 0x1c, 0x58, 0xba, 0x40, 0xb1, 0x77, 0xce, 0xb1, 0x7f, 0xfe, 0x11,
- 0x7b, 0x92, 0x46, 0xfd, 0xf0, 0x9a, 0x0b, 0x17, 0xff, 0xf0, 0xa0, 0xe5,
- 0x82, 0x07, 0x5c, 0xe1, 0x09, 0xb6, 0x58, 0xa8, 0x22, 0xc7, 0x4a, 0x95,
- 0xba, 0x60, 0x7c, 0x17, 0xf4, 0x32, 0x6a, 0x57, 0x09, 0xb6, 0x23, 0xc2,
- 0xf7, 0x87, 0x73, 0x43, 0xf8, 0x88, 0xbc, 0x84, 0x28, 0xd3, 0x6f, 0xdb,
- 0x1d, 0xbd, 0x2b, 0x17, 0xe1, 0xb1, 0x08, 0xeb, 0x17, 0xfe, 0x10, 0x33,
- 0x7c, 0xd6, 0x9a, 0x0b, 0x17, 0x6c, 0x4b, 0x17, 0xff, 0x09, 0xa0, 0x71,
- 0x7b, 0xf2, 0x20, 0xba, 0xc5, 0xd2, 0x75, 0x8a, 0x94, 0xc2, 0xb0, 0xa7,
- 0x45, 0x0c, 0x80, 0x43, 0x1c, 0x4a, 0xbf, 0xff, 0xf3, 0x74, 0x1c, 0xf3,
- 0xdd, 0xee, 0xe5, 0xef, 0xe0, 0xc5, 0xee, 0x2c, 0x5f, 0xfe, 0x68, 0xa7,
- 0xb2, 0x63, 0x70, 0x6d, 0x05, 0x8b, 0xdb, 0x60, 0x6b, 0x17, 0xce, 0x08,
- 0x84, 0xb1, 0x50, 0x47, 0xf8, 0xdc, 0x74, 0x96, 0x43, 0xf7, 0xb6, 0x7d,
- 0x2c, 0x5f, 0xf0, 0x7a, 0xc9, 0xee, 0x0e, 0x75, 0x8b, 0xfe, 0xe3, 0xf7,
- 0xe8, 0xa1, 0x3d, 0xac, 0x5f, 0xb9, 0xee, 0x67, 0x96, 0x2a, 0x51, 0x43,
- 0xc3, 0xb1, 0x1e, 0xdf, 0x82, 0xef, 0x13, 0x86, 0xb1, 0x7f, 0x14, 0xc4,
- 0x26, 0x31, 0x62, 0x84, 0x7b, 0xa6, 0x17, 0x5d, 0x9f, 0x58, 0xbf, 0xff,
- 0x78, 0x98, 0x1c, 0xfc, 0xc1, 0xcb, 0x0f, 0x2b, 0x17, 0x83, 0x0c, 0x34,
- 0x8b, 0xe3, 0x35, 0x30, 0x48, 0x8c, 0x34, 0x37, 0xf7, 0x9f, 0xdc, 0xfb,
- 0xf1, 0x15, 0x71, 0xce, 0x95, 0x2a, 0xad, 0x0d, 0x3c, 0x78, 0x5f, 0xb4,
- 0x23, 0x3c, 0x46, 0x28, 0x61, 0x5d, 0xee, 0xd6, 0x2f, 0xf3, 0xeb, 0x61,
- 0x03, 0x09, 0x62, 0xf7, 0xe4, 0xeb, 0x14, 0x73, 0xea, 0x0b, 0x8c, 0x98,
- 0x69, 0x7d, 0xdf, 0x27, 0xb5, 0x8b, 0xb3, 0x8b, 0x17, 0xa0, 0x53, 0xd4,
- 0xde, 0x31, 0x2d, 0xd1, 0x3a, 0xc5, 0xff, 0xfd, 0x09, 0x2c, 0xf7, 0xdf,
- 0x3d, 0x27, 0x7d, 0x41, 0x62, 0xbb, 0x45, 0x1e, 0x8c, 0xbc, 0x31, 0x7f,
- 0x1c, 0xc2, 0xce, 0x98, 0xb1, 0x7e, 0xce, 0x08, 0xbc, 0xb1, 0x4e, 0x88,
- 0x96, 0x31, 0x23, 0x0b, 0xff, 0xf4, 0xeb, 0x69, 0xfb, 0x3e, 0xb4, 0xe7,
- 0x8d, 0xc2, 0xda, 0xc5, 0x4b, 0x7f, 0xbf, 0x09, 0x70, 0xc3, 0x8c, 0x7b,
- 0x21, 0x70, 0x6c, 0x63, 0xdb, 0xc7, 0x19, 0xdb, 0x73, 0xbe, 0x45, 0x0e,
- 0xad, 0x4e, 0x3c, 0x9e, 0x3f, 0xaf, 0xc7, 0xc0, 0x08, 0x49, 0x94, 0xe4,
- 0xa7, 0x23, 0x8a, 0xf4, 0xe0, 0x38, 0xa1, 0xa1, 0xd2, 0x39, 0xc0, 0x85,
- 0xb7, 0xfd, 0xdc, 0x39, 0xcc, 0x1b, 0x79, 0x62, 0xe2, 0x65, 0x8b, 0xc0,
- 0x7d, 0xd6, 0x2f, 0x14, 0xc1, 0x63, 0xa9, 0x7d, 0x77, 0x53, 0x70, 0xf8,
- 0x5c, 0xd2, 0xfd, 0xe9, 0x10, 0x5f, 0x8b, 0x14, 0xe7, 0xb9, 0xa2, 0xfb,
- 0x9e, 0x39, 0x62, 0xe8, 0x8e, 0xb1, 0x7e, 0xcd, 0x78, 0x5f, 0x58, 0xad,
- 0x1e, 0xe0, 0x06, 0x8c, 0x19, 0xb6, 0x2c, 0x5b, 0x16, 0x23, 0xcb, 0x1b,
- 0xed, 0x13, 0x74, 0x58, 0xbd, 0x8c, 0x4b, 0x16, 0x0d, 0x62, 0xee, 0xb8,
- 0xb1, 0x4c, 0x6b, 0x3c, 0x27, 0x52, 0xa9, 0x90, 0x70, 0xf8, 0xc7, 0xd3,
- 0x50, 0x5c, 0x8f, 0x44, 0x87, 0x47, 0xbf, 0xb5, 0xf7, 0x92, 0xd9, 0x62,
- 0xf4, 0xf2, 0x0b, 0x17, 0xf1, 0x44, 0x68, 0x1a, 0x25, 0x8b, 0xff, 0xf6,
- 0x7b, 0xf9, 0x0d, 0x4f, 0xd9, 0xfd, 0x3f, 0x58, 0xa7, 0x44, 0x29, 0x18,
- 0xde, 0x07, 0x31, 0x62, 0xf8, 0x23, 0x4f, 0x6b, 0x17, 0xfb, 0x4e, 0x17,
- 0xdf, 0xf2, 0x1a, 0xc5, 0xe1, 0x16, 0xeb, 0x17, 0xed, 0x6d, 0xb3, 0x06,
- 0xb1, 0x58, 0x79, 0x46, 0x0f, 0x57, 0x68, 0xcb, 0x72, 0x5d, 0x42, 0x12,
- 0xfb, 0xf8, 0x06, 0x58, 0xbe, 0xfb, 0xf7, 0xe5, 0x8b, 0x9a, 0x1d, 0x4f,
- 0x1a, 0x22, 0x2b, 0x06, 0xb1, 0x7a, 0x4a, 0x0b, 0x17, 0xff, 0x98, 0x3f,
- 0x67, 0xfa, 0x96, 0x1b, 0x3c, 0x58, 0xa8, 0x1f, 0x49, 0x0e, 0x59, 0x96,
- 0x2f, 0x4f, 0xf8, 0xb1, 0x5d, 0x9a, 0xe7, 0x11, 0xbf, 0xf4, 0xef, 0xd7,
- 0x0a, 0x44, 0x17, 0xe2, 0xc5, 0xfd, 0xc9, 0xcd, 0x61, 0x2c, 0x5f, 0x34,
- 0x27, 0x65, 0x8b, 0xfc, 0xde, 0x7f, 0xb1, 0xfa, 0xe1, 0xe7, 0xfc, 0xb2,
- 0xff, 0xdc, 0xc2, 0x1f, 0x5c, 0x1b, 0xf4, 0x58, 0xbf, 0xfb, 0x8d, 0xdf,
- 0x39, 0x84, 0x08, 0xec, 0x58, 0xbf, 0xf7, 0x26, 0x3b, 0x3d, 0x08, 0x67,
- 0x16, 0x2f, 0xff, 0xc3, 0xcf, 0x71, 0xf9, 0xc9, 0xf0, 0x9b, 0x69, 0x58,
- 0xb3, 0xee, 0x89, 0x8d, 0x21, 0x50, 0xd5, 0xa2, 0xf6, 0x61, 0x13, 0xe6,
- 0x93, 0xce, 0x42, 0x50, 0x94, 0xe2, 0x57, 0x90, 0xba, 0x43, 0x82, 0xfb,
- 0x5f, 0xc2, 0x58, 0xbf, 0xff, 0x16, 0x3f, 0x1f, 0x52, 0x2f, 0x45, 0x38,
- 0x35, 0x8a, 0x95, 0xcc, 0x37, 0x97, 0x80, 0xd0, 0x8d, 0x11, 0x15, 0xf8,
- 0xc8, 0x38, 0x38, 0xb1, 0x7b, 0x26, 0x56, 0x2f, 0x8a, 0x0e, 0x75, 0x8b,
- 0xf1, 0x9c, 0x0f, 0x3e, 0xb1, 0x5b, 0x1f, 0x43, 0x0d, 0xf0, 0x8a, 0xfe,
- 0x00, 0x4f, 0x3e, 0xb6, 0x58, 0xa1, 0xa3, 0xcf, 0x50, 0x92, 0x22, 0xfb,
- 0xf8, 0xba, 0x99, 0xc9, 0xc5, 0x8b, 0xe9, 0xf3, 0x7d, 0x62, 0xee, 0x6c,
+ 0xf5, 0xde, 0x3a, 0x5a, 0x4e, 0xf4, 0x8a, 0x34, 0x3b, 0xef, 0xb2, 0x19,
+ 0x95, 0x3f, 0xb4, 0x21, 0xe1, 0x0d, 0xa1, 0xca, 0x13, 0xc9, 0x47, 0xe6,
+ 0xbb, 0xef, 0x1e, 0x7f, 0x50, 0xb3, 0x77, 0xa8, 0xf2, 0x18, 0xa5, 0x28,
+ 0x6a, 0x37, 0x83, 0xc2, 0xdb, 0xf3, 0x97, 0x8d, 0x1a, 0xc8, 0x23, 0x15,
+ 0x29, 0x6d, 0x3c, 0x96, 0x2f, 0xe9, 0xce, 0x11, 0x37, 0xc7, 0x42, 0x90,
+ 0x38, 0x46, 0x77, 0x3b, 0xdd, 0x3b, 0x2c, 0x5c, 0xde, 0x58, 0xbf, 0xa1,
+ 0x84, 0x4d, 0x05, 0x8b, 0xcd, 0xd4, 0x60, 0xcf, 0x6c, 0xe3, 0x1e, 0x17,
+ 0xbf, 0x40, 0x3d, 0xa7, 0x65, 0x8b, 0xd8, 0x5b, 0xac, 0x5e, 0x6e, 0xa3,
+ 0x38, 0x79, 0x21, 0x96, 0x54, 0x62, 0xb1, 0xe2, 0x94, 0xb2, 0x28, 0x46,
+ 0xde, 0x80, 0xa0, 0xb1, 0x7f, 0x41, 0xb5, 0xb7, 0xc4, 0xb1, 0x7e, 0xe4,
+ 0x80, 0x3d, 0x96, 0x2d, 0x91, 0x1e, 0xdf, 0x0c, 0x2f, 0x9e, 0x38, 0x80,
+ 0xb1, 0x7b, 0xdc, 0xe9, 0x62, 0xff, 0xde, 0x78, 0x3f, 0xc4, 0x73, 0xba,
+ 0xc5, 0xc3, 0x8c, 0x82, 0x64, 0x83, 0x79, 0x62, 0x8e, 0x12, 0x86, 0x3f,
+ 0x78, 0xf8, 0x4b, 0x17, 0xfb, 0x39, 0xc9, 0x00, 0x7b, 0x2c, 0x5f, 0x8f,
+ 0x25, 0x3d, 0x2c, 0x5c, 0xdb, 0xac, 0x5f, 0xf7, 0xa2, 0x83, 0x6b, 0x6f,
+ 0x89, 0x62, 0xff, 0x38, 0xb8, 0x02, 0x16, 0xcb, 0x15, 0xb2, 0x2c, 0xb7,
+ 0x28, 0xe8, 0x63, 0xc7, 0xb7, 0xfe, 0xe3, 0x8f, 0x30, 0x8d, 0x18, 0xd6,
+ 0x2f, 0x6e, 0xf0, 0x58, 0xbf, 0xfd, 0xa9, 0x1e, 0x45, 0x06, 0xd6, 0xdf,
+ 0x12, 0xc5, 0xff, 0xc1, 0xee, 0x64, 0xeb, 0x4e, 0x4d, 0xba, 0xc5, 0xe8,
+ 0xe2, 0x02, 0xc5, 0xce, 0x4b, 0x17, 0x0b, 0x75, 0x8b, 0xfd, 0x14, 0x6d,
+ 0x8f, 0xd9, 0x8e, 0xb1, 0x4e, 0x88, 0xa3, 0x90, 0x70, 0x5b, 0xc3, 0x37,
+ 0x9f, 0xe2, 0x58, 0xbf, 0x9f, 0x7f, 0xbf, 0x5e, 0x58, 0xbf, 0x98, 0x7f,
+ 0x92, 0xd9, 0x62, 0xb0, 0xf7, 0xbe, 0x61, 0x7c, 0xfe, 0xc0, 0x2c, 0x5f,
+ 0xf1, 0x9e, 0x93, 0x22, 0x66, 0xd2, 0xc5, 0xff, 0x64, 0x50, 0x6d, 0x6d,
+ 0xf1, 0x2c, 0x5d, 0x31, 0x2c, 0x5f, 0xf1, 0xe2, 0x83, 0x6b, 0x6f, 0x89,
+ 0x62, 0xf3, 0x10, 0x09, 0x12, 0x3e, 0x3c, 0x0c, 0x62, 0x8e, 0x98, 0x6c,
+ 0x74, 0x33, 0x6a, 0x57, 0x3c, 0xc6, 0x39, 0x90, 0xe8, 0xe9, 0x01, 0xcf,
+ 0xf4, 0x3c, 0x74, 0xd6, 0x86, 0x97, 0x7e, 0x79, 0xc7, 0xbf, 0x10, 0x87,
+ 0x19, 0x7d, 0xd1, 0xbc, 0x68, 0xb1, 0x78, 0xed, 0xd2, 0xc5, 0xe0, 0x37,
+ 0xd6, 0x2f, 0xff, 0xfb, 0xef, 0x14, 0x04, 0x69, 0x67, 0x5e, 0x63, 0xfb,
+ 0x99, 0xb2, 0xc5, 0xff, 0x79, 0xcf, 0xcf, 0xe0, 0x4c, 0xb1, 0x77, 0x67,
+ 0x58, 0xbd, 0x83, 0x1a, 0xc5, 0xed, 0x60, 0x6b, 0x17, 0xec, 0x19, 0xca,
+ 0x0b, 0x15, 0xa3, 0xc6, 0x38, 0xf5, 0xff, 0x4c, 0x02, 0x6d, 0x6b, 0x03,
+ 0x58, 0xbf, 0x67, 0xb5, 0x27, 0x58, 0xbf, 0x1f, 0xdc, 0x14, 0x7a, 0xc5,
+ 0xfe, 0xf7, 0xf0, 0x89, 0xbc, 0xb1, 0x7b, 0x02, 0x8c, 0xef, 0x15, 0x31,
+ 0x49, 0x16, 0x0f, 0x6e, 0x3b, 0xd3, 0x5c, 0x47, 0x5f, 0x19, 0x66, 0x32,
+ 0x22, 0xe1, 0xd8, 0x65, 0x1d, 0xc5, 0xb6, 0xe4, 0x62, 0xbe, 0x1d, 0xa5,
+ 0x8e, 0xde, 0x3e, 0x1d, 0x62, 0xff, 0xbe, 0xec, 0x0c, 0x16, 0xb6, 0x58,
+ 0xbf, 0xde, 0x7f, 0x73, 0xef, 0x19, 0x87, 0xaf, 0xe1, 0xda, 0x96, 0x50,
+ 0x3b, 0xd2, 0x4b, 0x85, 0x08, 0xdb, 0xf4, 0x83, 0xe2, 0x0d, 0x62, 0xe1,
+ 0x74, 0xb1, 0x7e, 0xcd, 0x66, 0x74, 0xb1, 0x76, 0xd1, 0x9f, 0x3e, 0xb0,
+ 0x15, 0x10, 0xcd, 0xff, 0xfe, 0x7f, 0x09, 0xb6, 0x8c, 0xc8, 0x7e, 0x75,
+ 0x98, 0x46, 0xac, 0x56, 0x91, 0x45, 0xdf, 0x9f, 0x5f, 0xff, 0xfd, 0xbb,
+ 0x69, 0xbf, 0x0c, 0xf6, 0x0f, 0x8c, 0x7c, 0xd6, 0xd3, 0xd2, 0xc5, 0xfd,
+ 0x83, 0x63, 0xe1, 0x2c, 0x5f, 0xff, 0x60, 0xbb, 0xfc, 0x26, 0x7f, 0xb7,
+ 0xbf, 0x2b, 0x14, 0xe8, 0xf2, 0xd3, 0xa7, 0xcb, 0x2f, 0xda, 0xdd, 0x9b,
+ 0x75, 0x49, 0x28, 0x5f, 0xff, 0x37, 0x8b, 0x36, 0xd4, 0xfd, 0xff, 0x9a,
+ 0x58, 0xbf, 0xfe, 0x61, 0xe0, 0xff, 0x84, 0x03, 0xe6, 0xb1, 0x62, 0xee,
+ 0x04, 0xb1, 0x7f, 0xef, 0xc8, 0x0e, 0xd0, 0xe7, 0x02, 0x58, 0xbc, 0xd0,
+ 0x8c, 0x94, 0xd7, 0x70, 0xbc, 0x06, 0xe4, 0x9f, 0xc4, 0xe0, 0xc6, 0x6f,
+ 0xfc, 0xfb, 0xb6, 0x9a, 0x0f, 0xc0, 0x2c, 0x5f, 0xb5, 0xbb, 0x36, 0xea,
+ 0x91, 0x38, 0xba, 0x11, 0x92, 0x7e, 0xd8, 0x7f, 0x47, 0x4c, 0x3d, 0xa1,
+ 0xc1, 0x7f, 0xd9, 0x14, 0x1b, 0x5b, 0x7c, 0x4b, 0x17, 0xff, 0xb3, 0xaf,
+ 0x4e, 0x05, 0x90, 0x90, 0x71, 0x62, 0xfd, 0xfc, 0xd3, 0xf1, 0x62, 0xff,
+ 0x67, 0x03, 0x1f, 0xe7, 0xa5, 0x8b, 0xb5, 0x18, 0x34, 0x72, 0x91, 0xe7,
+ 0x92, 0xe3, 0x8a, 0x2f, 0xf9, 0xa1, 0x90, 0x21, 0x37, 0x16, 0x2f, 0x4c,
+ 0x4c, 0xb1, 0x7f, 0x79, 0x8e, 0x52, 0x75, 0x8b, 0xe7, 0x2c, 0x82, 0xc5,
+ 0x0d, 0x14, 0x7f, 0x38, 0xf0, 0xef, 0x71, 0x6d, 0xf6, 0xe4, 0x23, 0x56,
+ 0x2e, 0xd4, 0x66, 0x1f, 0x2b, 0x20, 0x54, 0x62, 0xa9, 0x27, 0x8c, 0x35,
+ 0xa3, 0x56, 0xa9, 0x96, 0x7e, 0x4d, 0xb5, 0xa1, 0xf6, 0x85, 0x39, 0x8c,
+ 0x7a, 0x8a, 0x84, 0x72, 0x71, 0x40, 0xd9, 0x41, 0xdb, 0xc7, 0xa2, 0xf3,
+ 0xe7, 0xf1, 0xf1, 0xcd, 0x45, 0x1f, 0x56, 0xa3, 0x76, 0x3d, 0xfa, 0x40,
+ 0xfe, 0x9a, 0xfa, 0xd4, 0x80, 0x10, 0x4a, 0xc7, 0x29, 0xf7, 0x1e, 0x5a,
+ 0x90, 0xef, 0x52, 0xda, 0xc5, 0x1a, 0x6f, 0x69, 0xe1, 0x8b, 0x71, 0x62,
+ 0xfd, 0xad, 0xd9, 0xb7, 0x54, 0x83, 0xe5, 0xff, 0x9a, 0x11, 0x99, 0xad,
+ 0xd9, 0xb7, 0x54, 0x8a, 0x65, 0xa3, 0x06, 0x89, 0x9c, 0x12, 0x39, 0xbd,
+ 0xfe, 0x8c, 0xcd, 0x6e, 0xcd, 0xba, 0xa4, 0x27, 0x2f, 0x46, 0x9d, 0xf7,
+ 0xde, 0x2c, 0x5f, 0x9f, 0xdc, 0x11, 0xd6, 0x2f, 0xc2, 0x39, 0x31, 0xab,
+ 0x17, 0xbf, 0x31, 0x2c, 0x5d, 0xd4, 0x16, 0x2a, 0x24, 0x44, 0xe8, 0xa7,
+ 0xe5, 0x22, 0x1e, 0xbf, 0xc2, 0xe8, 0x31, 0x8b, 0xdc, 0x58, 0xbf, 0xfd,
+ 0x1a, 0x8d, 0x0a, 0x3f, 0x61, 0xc6, 0xc6, 0x19, 0xf8, 0xe5, 0x8b, 0xed,
+ 0xd9, 0xb7, 0x54, 0x86, 0x25, 0xff, 0xf3, 0x43, 0x85, 0x39, 0xb8, 0xf4,
+ 0xe2, 0xdd, 0x62, 0xff, 0x84, 0xc7, 0x6d, 0x6b, 0x3a, 0x58, 0xad, 0x22,
+ 0xf0, 0x8c, 0x78, 0xa3, 0x7e, 0xe3, 0xf6, 0x93, 0xac, 0x5e, 0xea, 0x1b,
+ 0x2c, 0x54, 0x9e, 0x56, 0x15, 0x5f, 0x66, 0xc7, 0xf2, 0xc5, 0x7c, 0xf1,
+ 0x08, 0x82, 0xff, 0x46, 0xae, 0xdd, 0xf5, 0x30, 0xcf, 0xc7, 0x2c, 0x5f,
+ 0xbb, 0x37, 0x26, 0x0b, 0x17, 0xf7, 0x3d, 0xd6, 0xef, 0xf5, 0x8b, 0xdf,
+ 0x70, 0x96, 0x2e, 0x84, 0xfc, 0xf3, 0xc0, 0x63, 0x7f, 0x7d, 0x88, 0x61,
+ 0xf4, 0xb1, 0x7f, 0xfc, 0xc6, 0x99, 0xe3, 0x64, 0xa1, 0x9f, 0x73, 0xac,
+ 0x58, 0x4e, 0x88, 0x22, 0x30, 0xb7, 0xd6, 0x2f, 0xa7, 0xa8, 0x32, 0xc5,
+ 0x39, 0xb5, 0x88, 0x4a, 0xfa, 0x4f, 0xb8, 0x16, 0x2f, 0x07, 0x31, 0x2c,
+ 0x5f, 0xff, 0x43, 0x68, 0xd5, 0x31, 0xa6, 0xdb, 0xe8, 0xc3, 0x3f, 0x1c,
+ 0xb1, 0x58, 0x8c, 0xaf, 0x90, 0xb1, 0x20, 0x07, 0xef, 0xda, 0x7d, 0xdf,
+ 0xb2, 0xc5, 0xf8, 0x5e, 0x9e, 0xa0, 0xb1, 0x7b, 0x3a, 0xf2, 0xc5, 0xfe,
+ 0xc2, 0xfe, 0x7a, 0x46, 0xb1, 0x76, 0x7a, 0x4f, 0x41, 0xc7, 0xaf, 0xfd,
+ 0xe3, 0x64, 0xa1, 0x9f, 0x73, 0xac, 0x5f, 0xf1, 0xb2, 0x50, 0xcf, 0xb9,
+ 0xd6, 0x2f, 0x84, 0x4c, 0x69, 0x87, 0xf1, 0xe3, 0xfb, 0xb7, 0xdd, 0x62,
+ 0xfd, 0xa0, 0x3f, 0xe5, 0x62, 0x8e, 0x7f, 0x9c, 0x3a, 0x10, 0xd5, 0xee,
+ 0xa1, 0x1a, 0x2c, 0x5f, 0xdf, 0xf7, 0x33, 0xa8, 0x2c, 0x53, 0x9e, 0xa0,
+ 0x89, 0x2f, 0x3e, 0xa3, 0x96, 0x2f, 0xc6, 0x44, 0x52, 0x35, 0x8b, 0xc1,
+ 0xc2, 0x3d, 0x62, 0xd1, 0x9d, 0xf1, 0x91, 0xa9, 0x30, 0xb8, 0xd8, 0xfa,
+ 0x07, 0x19, 0x19, 0x06, 0xf0, 0xbd, 0xe8, 0x85, 0xd2, 0xe2, 0x79, 0x3c,
+ 0x2b, 0xff, 0x19, 0x33, 0x1d, 0x80, 0xac, 0x9e, 0xb9, 0x18, 0xff, 0xa1,
+ 0x06, 0x22, 0x18, 0xe2, 0x0e, 0xe2, 0xab, 0xff, 0xd1, 0x87, 0x68, 0x46,
+ 0x66, 0xb7, 0x66, 0xdd, 0x52, 0x3c, 0x97, 0xbb, 0x4f, 0xd6, 0x2d, 0x2b,
+ 0x15, 0x26, 0xc3, 0x43, 0xf7, 0xd2, 0x50, 0xe2, 0xc5, 0xd9, 0xc5, 0x8b,
+ 0xff, 0x37, 0xa7, 0x42, 0x86, 0xa6, 0x0b, 0x17, 0x07, 0xc5, 0x8b, 0xde,
+ 0x93, 0xac, 0x5f, 0x39, 0x67, 0x65, 0x8b, 0xf7, 0xa4, 0x9c, 0x0b, 0x17,
+ 0xfd, 0x3b, 0x67, 0xa4, 0x9c, 0x0b, 0x17, 0x98, 0x81, 0x87, 0xbe, 0x19,
+ 0x3d, 0x7d, 0x16, 0x91, 0xd0, 0x82, 0xad, 0x27, 0x5a, 0x02, 0x0e, 0xfc,
+ 0x88, 0x85, 0xf8, 0x7f, 0xe1, 0x90, 0xe1, 0xa3, 0x4b, 0x17, 0xfa, 0x37,
+ 0xfc, 0x40, 0xef, 0x35, 0xc5, 0x8a, 0x58, 0xbc, 0x3c, 0x3a, 0xc5, 0xb9,
+ 0xf3, 0x52, 0x20, 0xcb, 0xa0, 0x1a, 0xc5, 0xf0, 0x9b, 0x50, 0x58, 0xbd,
+ 0xe0, 0xf6, 0x58, 0xbf, 0xe6, 0x2f, 0x48, 0x34, 0xda, 0x58, 0xbf, 0xfc,
+ 0x4d, 0x07, 0xf8, 0xa2, 0x84, 0xeb, 0x65, 0x8b, 0xc7, 0x14, 0x7a, 0xc5,
+ 0xee, 0xa1, 0xba, 0xc5, 0xf9, 0x87, 0xf9, 0xe2, 0xc5, 0xfd, 0xff, 0xcf,
+ 0x4d, 0x1e, 0xb1, 0x4b, 0x15, 0x86, 0xfb, 0x86, 0x56, 0x8c, 0xef, 0x55,
+ 0x22, 0x77, 0xd4, 0x32, 0x5a, 0xa0, 0x4e, 0x31, 0x9c, 0x23, 0xd1, 0x07,
+ 0xce, 0x00, 0x99, 0xdf, 0x90, 0x91, 0x07, 0x19, 0xaa, 0x31, 0x5b, 0x90,
+ 0x52, 0xac, 0xef, 0xfe, 0x8c, 0xe7, 0x8a, 0x40, 0xde, 0x14, 0xac, 0x54,
+ 0xb6, 0x16, 0x9b, 0x1c, 0x42, 0x92, 0x33, 0xf8, 0xcf, 0xbd, 0x3b, 0x5c,
+ 0x11, 0x85, 0xfb, 0x5b, 0xb3, 0x6e, 0xa9, 0x08, 0x0b, 0xff, 0x34, 0x23,
+ 0x33, 0x5b, 0xb3, 0x6e, 0xa9, 0x15, 0x0b, 0xfb, 0x42, 0xfc, 0x96, 0xeb,
+ 0x17, 0xf6, 0xef, 0x9d, 0xdf, 0x95, 0x8a, 0x93, 0xe0, 0xc2, 0xfb, 0xfb,
+ 0xd8, 0x45, 0x3b, 0x2c, 0x5a, 0x33, 0x13, 0x34, 0x39, 0xb9, 0x42, 0xc3,
+ 0xc4, 0x17, 0xf6, 0x69, 0xa2, 0xdf, 0x65, 0x8b, 0xd2, 0x5b, 0x2c, 0x50,
+ 0xcf, 0x3b, 0xb1, 0x8d, 0xfb, 0x5b, 0xb3, 0x6e, 0xa9, 0x0a, 0x0b, 0xf6,
+ 0xa4, 0xf3, 0xd2, 0xc5, 0xfd, 0xa9, 0x3f, 0xb0, 0x0b, 0x17, 0x8e, 0x21,
+ 0xac, 0x5f, 0xf9, 0xfd, 0x14, 0xbe, 0x76, 0x78, 0xf5, 0x8b, 0x7d, 0xcf,
+ 0x87, 0xb0, 0xf5, 0xe3, 0x8a, 0x3d, 0x62, 0xfd, 0xee, 0x7c, 0x5c, 0x58,
+ 0xbf, 0xd0, 0xc1, 0x93, 0x30, 0xd6, 0x2f, 0xec, 0xd0, 0x08, 0x40, 0x58,
+ 0xa9, 0x44, 0x53, 0x15, 0x00, 0xca, 0xff, 0xc2, 0x6d, 0x34, 0x3c, 0xfc,
+ 0x12, 0xc5, 0xff, 0x4f, 0x45, 0x9e, 0xe4, 0x9d, 0x62, 0x88, 0xfe, 0x04,
+ 0x7f, 0x7f, 0xdf, 0xc1, 0xbf, 0x30, 0x80, 0xb1, 0x7a, 0x41, 0x8b, 0x16,
+ 0x8c, 0x95, 0x60, 0x58, 0x48, 0xe6, 0xfa, 0x29, 0x68, 0x47, 0x80, 0xa4,
+ 0xa1, 0x57, 0xc8, 0x53, 0x78, 0x84, 0x33, 0x8b, 0xfd, 0x19, 0x9a, 0xdd,
+ 0x9b, 0x75, 0x48, 0x64, 0x5f, 0xb5, 0xbb, 0x36, 0xea, 0x91, 0x94, 0xbf,
+ 0x43, 0x3c, 0xdb, 0xac, 0x5f, 0xa3, 0x0e, 0xd0, 0x8c, 0xc3, 0xe0, 0xe8,
+ 0xde, 0xee, 0xf7, 0xbc, 0x58, 0xbb, 0xa1, 0x2c, 0x5f, 0xb5, 0xbb, 0x36,
+ 0xea, 0x92, 0x90, 0xb1, 0x2c, 0x5d, 0x03, 0xac, 0x5f, 0x1f, 0x33, 0xcb,
+ 0x17, 0x77, 0xfd, 0xfa, 0xc5, 0xfd, 0x07, 0x19, 0x67, 0x65, 0x8b, 0x06,
+ 0xb1, 0x7c, 0x5f, 0xce, 0x96, 0x2f, 0x77, 0x08, 0x0b, 0x16, 0x8c, 0x8d,
+ 0x13, 0x65, 0x81, 0x16, 0x0c, 0xc7, 0x9b, 0xe8, 0x45, 0x86, 0x3b, 0xf2,
+ 0x2f, 0x11, 0x08, 0xbc, 0x31, 0x3e, 0xe2, 0x3b, 0xf6, 0xb7, 0x66, 0xdd,
+ 0x52, 0x5d, 0x17, 0xf7, 0xdf, 0x5a, 0x68, 0x2c, 0x5a, 0x33, 0x0f, 0x97,
+ 0x86, 0xf7, 0x83, 0x93, 0xac, 0x5f, 0xb5, 0xbb, 0x36, 0xea, 0x93, 0x14,
+ 0xb4, 0x64, 0x9e, 0xae, 0x0f, 0x5f, 0xf4, 0xf3, 0x92, 0x7f, 0x66, 0xeb,
+ 0x17, 0xdb, 0xb3, 0x6e, 0xa9, 0x1e, 0x8b, 0xf1, 0xda, 0x11, 0x99, 0xb9,
+ 0xf5, 0xe8, 0xea, 0xf0, 0x4d, 0xba, 0xc5, 0xfd, 0xf9, 0x7d, 0x3f, 0x7e,
+ 0xb1, 0x7b, 0xbf, 0x7e, 0x2c, 0x5f, 0xcf, 0xb3, 0x4f, 0x5c, 0x58, 0xbf,
+ 0x4b, 0xc7, 0x3f, 0x72, 0xc5, 0xf4, 0xf4, 0xdd, 0xcb, 0x17, 0x05, 0x19,
+ 0x88, 0xf5, 0xdc, 0x7d, 0xcc, 0xbe, 0x44, 0xc5, 0xe4, 0x5b, 0x7f, 0xfa,
+ 0x4a, 0x33, 0x3e, 0xc6, 0x1e, 0x73, 0xcb, 0x17, 0xff, 0xff, 0x87, 0x81,
+ 0x46, 0x16, 0x1a, 0x6b, 0x7b, 0x8e, 0x51, 0x4e, 0xfa, 0xce, 0x96, 0x2f,
+ 0xff, 0xff, 0xde, 0x6d, 0x42, 0x33, 0x38, 0x26, 0xeb, 0x0a, 0x42, 0x0f,
+ 0xcf, 0x0c, 0xeb, 0xcb, 0x17, 0xff, 0xf9, 0xe4, 0xbd, 0x19, 0xf7, 0x92,
+ 0xdb, 0xdd, 0x6e, 0xe4, 0xb1, 0x7e, 0xcf, 0x7d, 0xc2, 0x58, 0xbf, 0xf7,
+ 0x30, 0x98, 0xdf, 0xbc, 0x92, 0xc5, 0xff, 0x66, 0x7d, 0xf7, 0xfe, 0x46,
+ 0x11, 0xf3, 0x78, 0xa6, 0xf9, 0xc8, 0xd9, 0x58, 0xbc, 0x4d, 0x12, 0xc5,
+ 0x2c, 0x5c, 0x22, 0x58, 0xa9, 0x34, 0x7c, 0x0c, 0xbf, 0xe9, 0xfb, 0x8f,
+ 0xf3, 0x0e, 0x2c, 0x57, 0x0f, 0x67, 0xb1, 0x05, 0xf8, 0xa6, 0x29, 0x8f,
+ 0x58, 0xa8, 0x26, 0x15, 0x84, 0x4f, 0x09, 0x9f, 0x12, 0x5e, 0x92, 0x95,
+ 0x8b, 0xde, 0x6d, 0xd6, 0x2f, 0xd2, 0x0e, 0x3f, 0x4b, 0x16, 0x7e, 0x8f,
+ 0x1f, 0xe3, 0xd7, 0xfb, 0x35, 0xb4, 0xf1, 0xc6, 0xb1, 0x73, 0x12, 0xc5,
+ 0xfe, 0x21, 0x36, 0xda, 0xc3, 0xac, 0x5f, 0xf6, 0x1e, 0x7f, 0xec, 0x7e,
+ 0xcb, 0x17, 0xf4, 0x9f, 0x42, 0x6e, 0x2c, 0x51, 0xd1, 0x65, 0xf1, 0x6e,
+ 0x1a, 0x78, 0xea, 0xf4, 0xe0, 0xd6, 0x2f, 0x3e, 0x6c, 0xb1, 0x63, 0x56,
+ 0x2e, 0xfb, 0xc7, 0x9b, 0x0d, 0x0e, 0xdf, 0x71, 0xc9, 0xd6, 0x2e, 0xeb,
+ 0xcb, 0x17, 0xe8, 0x49, 0x4c, 0x4b, 0x17, 0xf7, 0xdf, 0x9a, 0xce, 0x96,
+ 0x2f, 0xf4, 0xfb, 0x8f, 0x14, 0x81, 0x62, 0xa5, 0x14, 0x9d, 0x0c, 0xc4,
+ 0x51, 0xf2, 0xfb, 0xd3, 0xad, 0x96, 0x2f, 0x61, 0x6e, 0xb1, 0x7e, 0x8b,
+ 0x7f, 0xce, 0xcb, 0x14, 0xb1, 0x50, 0x3f, 0x3c, 0x1e, 0x61, 0xd1, 0x16,
+ 0x5f, 0xf4, 0x24, 0x8b, 0x3d, 0xf7, 0x58, 0xbf, 0xbc, 0xe4, 0xe0, 0xe2,
+ 0xc5, 0x39, 0xf2, 0x08, 0xde, 0xf3, 0x67, 0x16, 0x2a, 0x4d, 0xe8, 0x88,
+ 0x6f, 0xbc, 0x26, 0xe2, 0xc5, 0xc7, 0x95, 0x8e, 0x8d, 0x1d, 0xfd, 0x3d,
+ 0x78, 0x4d, 0xc5, 0x8a, 0xc3, 0xd7, 0x34, 0xa2, 0xec, 0x3a, 0xc5, 0x9c,
+ 0x8d, 0xcc, 0x71, 0x15, 0xfd, 0xb6, 0xce, 0x53, 0x05, 0x8b, 0xdb, 0x9b,
+ 0x2b, 0x17, 0xe3, 0xb6, 0x9a, 0x0b, 0x17, 0xcf, 0xc1, 0x1d, 0x62, 0xf7,
+ 0xe6, 0x0b, 0x17, 0xdb, 0x1e, 0x60, 0xb1, 0x52, 0x78, 0x2c, 0x3b, 0x7d,
+ 0xee, 0x0a, 0x56, 0x2c, 0xeb, 0x14, 0x46, 0xd3, 0xc4, 0x77, 0xdd, 0xd2,
+ 0x5b, 0x2c, 0x54, 0x9e, 0x33, 0x90, 0x5f, 0x99, 0xfa, 0xf6, 0x2c, 0x5f,
+ 0x83, 0x9d, 0x49, 0xd6, 0x2b, 0x64, 0xe5, 0xe0, 0x50, 0x36, 0x4d, 0x42,
+ 0x68, 0x04, 0x1c, 0x28, 0xbc, 0xf3, 0xe5, 0x8a, 0x82, 0xa8, 0x7c, 0x28,
+ 0xe8, 0xbd, 0xe3, 0xb6, 0x09, 0x7a, 0xfb, 0x45, 0x9b, 0x2c, 0x5f, 0x0f,
+ 0xed, 0xa5, 0x8a, 0x94, 0x4c, 0x3a, 0x93, 0x11, 0xdf, 0x3f, 0xa7, 0x4b,
+ 0x17, 0xde, 0xf4, 0xf9, 0x62, 0xf4, 0x4d, 0xe5, 0x8a, 0xf9, 0xf1, 0xb1,
+ 0x10, 0x64, 0x77, 0xdb, 0x89, 0xa0, 0xb1, 0x7f, 0x48, 0x22, 0x84, 0xec,
+ 0xb1, 0x6d, 0x96, 0x2a, 0x07, 0x86, 0xe6, 0x17, 0x8a, 0x4d, 0x58, 0xa8,
+ 0x8d, 0xf1, 0xc8, 0x6f, 0xbd, 0x06, 0x1a, 0xc5, 0x4a, 0x3a, 0xb2, 0x14,
+ 0xac, 0x45, 0x7f, 0x9f, 0x4d, 0xd7, 0xa6, 0x0b, 0x17, 0xdc, 0x21, 0x7d,
+ 0x62, 0xff, 0xa5, 0xfd, 0xc7, 0x2e, 0xa0, 0xb1, 0x74, 0xe9, 0x62, 0xfe,
+ 0xd6, 0x76, 0x92, 0xf2, 0xc5, 0xff, 0x75, 0xbb, 0x9b, 0x84, 0xe6, 0xac,
+ 0x5b, 0x34, 0x7d, 0x7e, 0x2f, 0xbe, 0x26, 0x07, 0x16, 0x2a, 0x09, 0xad,
+ 0xe1, 0xa7, 0xc8, 0xd8, 0xe4, 0xa1, 0x05, 0xe2, 0x7b, 0xfa, 0x19, 0xff,
+ 0xb4, 0x16, 0x2d, 0xb2, 0xc5, 0xf4, 0x38, 0xc7, 0x58, 0xad, 0x8d, 0xb3,
+ 0x09, 0xdf, 0xb3, 0xe3, 0x0f, 0x8b, 0x17, 0x0e, 0x32, 0x59, 0x9d, 0x7b,
+ 0x20, 0xc1, 0x88, 0x65, 0x19, 0x0e, 0x63, 0x4f, 0x77, 0x4c, 0xe8, 0xbd,
+ 0xe1, 0x8b, 0x14, 0x2c, 0x75, 0x0d, 0xbf, 0xcb, 0xf2, 0x68, 0x48, 0x14,
+ 0x63, 0x3c, 0x8e, 0x37, 0xcb, 0x41, 0x32, 0x06, 0x43, 0x7c, 0xfa, 0xfb,
+ 0x2c, 0x5f, 0xce, 0x10, 0xd9, 0x8d, 0x58, 0xbf, 0xa2, 0x29, 0x3c, 0x66,
+ 0x7c, 0xf4, 0x78, 0x45, 0x7f, 0xb7, 0x7d, 0x46, 0x1d, 0xc6, 0xb1, 0x77,
+ 0x3c, 0xb1, 0x7f, 0x7d, 0xf9, 0xcc, 0xd2, 0xc5, 0xff, 0xcc, 0xfe, 0x72,
+ 0xf0, 0xbf, 0x1e, 0x4b, 0x17, 0x67, 0x16, 0x2f, 0xfd, 0x9a, 0xea, 0x4f,
+ 0xf6, 0xcd, 0x2c, 0x5d, 0xc0, 0x2c, 0x5f, 0x89, 0x8e, 0x52, 0xb1, 0x7f,
+ 0x0b, 0x9f, 0x68, 0x46, 0x46, 0x89, 0x90, 0x6e, 0x31, 0xf2, 0xe6, 0x46,
+ 0x21, 0x70, 0x8f, 0xc3, 0x18, 0xbd, 0xb4, 0xc7, 0xac, 0x5f, 0xda, 0xda,
+ 0x47, 0x84, 0xb1, 0x76, 0xbc, 0xb1, 0x7e, 0xcf, 0x71, 0xce, 0xb1, 0x7d,
+ 0x03, 0xf4, 0x12, 0xc5, 0xff, 0xe9, 0xeb, 0xd9, 0x13, 0xeb, 0xdc, 0x14,
+ 0x7a, 0xc5, 0xe6, 0xea, 0x32, 0x53, 0x05, 0xc2, 0x16, 0x2e, 0x21, 0x8e,
+ 0x14, 0x78, 0x9a, 0xa5, 0x74, 0x8f, 0x23, 0x85, 0xe9, 0x1f, 0x51, 0xac,
+ 0x72, 0x39, 0x6a, 0x83, 0x6b, 0xca, 0x34, 0xce, 0x9f, 0xff, 0x08, 0x92,
+ 0x86, 0x57, 0xab, 0x36, 0x9a, 0x8c, 0x6d, 0xfc, 0x26, 0x33, 0x77, 0xad,
+ 0x92, 0x6f, 0xff, 0xf6, 0xbd, 0xe9, 0x87, 0xe5, 0xf5, 0x25, 0xee, 0x0a,
+ 0x56, 0x2f, 0xfb, 0xc2, 0xd8, 0x38, 0xb8, 0x2e, 0x96, 0x2f, 0x37, 0xf8,
+ 0xb1, 0x68, 0xcc, 0x45, 0xef, 0x98, 0x02, 0x40, 0xbe, 0xd1, 0xdb, 0xcb,
+ 0x17, 0x47, 0xc7, 0xac, 0x5f, 0x41, 0xcb, 0x16, 0x2f, 0xee, 0x67, 0xbf,
+ 0x80, 0x58, 0xbf, 0x78, 0xa7, 0x3a, 0x58, 0xbb, 0x68, 0xc7, 0x45, 0xc4,
+ 0x79, 0x1c, 0x43, 0xde, 0x21, 0x0c, 0xba, 0x86, 0x9a, 0x7e, 0xa1, 0xe3,
+ 0x7a, 0x45, 0xdf, 0xac, 0x5f, 0xb5, 0xbf, 0xdf, 0x8b, 0x14, 0xe7, 0x98,
+ 0x22, 0x2b, 0xbd, 0x2b, 0x15, 0xde, 0x1b, 0x8e, 0x88, 0x6f, 0x6d, 0x1d,
+ 0x1b, 0xac, 0x5f, 0x9b, 0x62, 0x98, 0x2c, 0x5f, 0xec, 0xec, 0x59, 0xc0,
+ 0x1d, 0x62, 0xbb, 0xe2, 0x21, 0x3e, 0x4e, 0x45, 0x17, 0xe7, 0xf9, 0x34,
+ 0x4b, 0x17, 0xe1, 0x1c, 0xed, 0x12, 0xc5, 0xf9, 0xfa, 0xcc, 0xd9, 0x62,
+ 0xd9, 0xf3, 0xd3, 0xec, 0x55, 0x74, 0x74, 0x6e, 0xb1, 0x7b, 0xbe, 0xe0,
+ 0x35, 0x8b, 0xf4, 0x30, 0x66, 0x62, 0xc5, 0xf9, 0x9f, 0x6d, 0x4a, 0xc5,
+ 0xf7, 0x5b, 0xb9, 0x2c, 0x5f, 0xbc, 0x42, 0x68, 0xd9, 0x62, 0xbb, 0xc4,
+ 0xf0, 0x3b, 0xd3, 0x58, 0xd9, 0xef, 0xbe, 0xca, 0x7b, 0xe1, 0x04, 0x92,
+ 0xfc, 0xa7, 0xc5, 0x01, 0x92, 0x5c, 0x70, 0x2c, 0x5f, 0xf7, 0x7a, 0x11,
+ 0xbb, 0xc5, 0x01, 0x1a, 0xb1, 0x7e, 0xcf, 0x38, 0xb8, 0xb1, 0x77, 0x79,
+ 0xdf, 0x55, 0x8b, 0xf4, 0x69, 0x1a, 0x7b, 0x52, 0xb1, 0x5d, 0xe2, 0x37,
+ 0xa3, 0x41, 0x8e, 0xfa, 0xa3, 0x46, 0xa2, 0x88, 0x12, 0xdf, 0xa3, 0x5f,
+ 0x79, 0xcd, 0x79, 0x62, 0xff, 0x06, 0x59, 0xad, 0x4e, 0xeb, 0x15, 0xde,
+ 0x1f, 0x54, 0x6c, 0x6b, 0x7d, 0xa3, 0xfb, 0xa5, 0x8b, 0xf4, 0x6f, 0xde,
+ 0x9f, 0x86, 0xac, 0x5c, 0xfc, 0x58, 0xb0, 0x4b, 0x15, 0xde, 0x1e, 0xfe,
+ 0xe6, 0xa1, 0x8b, 0xdf, 0xa3, 0x7e, 0xf6, 0x60, 0x75, 0x8b, 0xa6, 0x3d,
+ 0x62, 0xc3, 0x58, 0xaf, 0x9a, 0xcf, 0x0d, 0x5f, 0xfa, 0x35, 0x46, 0x91,
+ 0xb7, 0x7b, 0x1b, 0x46, 0xdd, 0xf2, 0x36, 0xef, 0x16, 0x2f, 0xfd, 0x1a,
+ 0xe3, 0x6e, 0xf9, 0x1a, 0xe3, 0x5f, 0x7b, 0xde, 0xc6, 0xfd, 0xe2, 0xc5,
+ 0xff, 0xbb, 0xe4, 0x6a, 0x8d, 0x7d, 0xf2, 0x35, 0xf7, 0xbd, 0xf5, 0x8d,
+ 0x7d, 0xe2, 0xc5, 0xff, 0x7c, 0x70, 0x8c, 0x87, 0x0a, 0x33, 0xbd, 0x4d,
+ 0x72, 0x34, 0x71, 0xef, 0xab, 0x9d, 0x77, 0x8a, 0x95, 0x3b, 0xd5, 0xfe,
+ 0xfa, 0xc6, 0xfb, 0x7e, 0xef, 0x4e, 0xcc, 0x4b, 0x17, 0xf4, 0xbf, 0xbd,
+ 0x27, 0x58, 0xb8, 0x71, 0xeb, 0x15, 0x1b, 0x9f, 0xa4, 0x6b, 0x2c, 0xe8,
+ 0xb6, 0xf6, 0xf9, 0xf4, 0x8b, 0xb9, 0xa5, 0x8b, 0xa7, 0x8b, 0x16, 0xd2,
+ 0xc5, 0x8e, 0xb1, 0x47, 0x37, 0x7e, 0x17, 0x08, 0x4a, 0xff, 0xf1, 0xcb,
+ 0x3a, 0x3e, 0x6f, 0x25, 0x3b, 0xac, 0x5f, 0xff, 0xb5, 0x3f, 0x9c, 0xdc,
+ 0x6e, 0x5b, 0x1e, 0x60, 0xb1, 0x6f, 0x62, 0x28, 0x43, 0x4b, 0xbb, 0x52,
+ 0xb1, 0x4e, 0x78, 0x00, 0x29, 0xbe, 0xd6, 0x9a, 0x0b, 0x17, 0xfb, 0x37,
+ 0x93, 0x3e, 0xc7, 0x58, 0xa9, 0x3d, 0x8f, 0x91, 0xdf, 0xfc, 0x42, 0x93,
+ 0x19, 0xfd, 0x0c, 0xe2, 0xc5, 0xff, 0xdf, 0x9e, 0x30, 0x7f, 0xfb, 0xf5,
+ 0xc5, 0x8b, 0xfe, 0x79, 0x2c, 0xed, 0xa9, 0xe2, 0xc5, 0x6e, 0x88, 0x0f,
+ 0xa3, 0xde, 0x89, 0xc2, 0x58, 0xbf, 0x00, 0x50, 0x83, 0x2c, 0x53, 0x9e,
+ 0x40, 0x63, 0xf7, 0xa2, 0x70, 0x96, 0x2e, 0xc8, 0x2c, 0x53, 0x9b, 0x66,
+ 0x1f, 0xa3, 0x9f, 0xb8, 0x16, 0x2f, 0xfc, 0xe6, 0x7d, 0xda, 0x1e, 0x7d,
+ 0x96, 0x2f, 0x36, 0xa0, 0xb1, 0x58, 0x7f, 0xff, 0x22, 0x12, 0x05, 0xfb,
+ 0xc0, 0x0c, 0xa2, 0x58, 0xbf, 0xf3, 0x70, 0xce, 0x73, 0x21, 0x09, 0x58,
+ 0xb7, 0x16, 0x2f, 0xe9, 0xdd, 0xf6, 0x62, 0x58, 0xbf, 0xff, 0x13, 0x1a,
+ 0xfa, 0x98, 0x43, 0x38, 0x00, 0x4a, 0xc5, 0xfe, 0x6f, 0x0b, 0x30, 0x8d,
+ 0x58, 0xa1, 0xa6, 0xc3, 0x85, 0xc6, 0x95, 0xc4, 0x81, 0xa1, 0x2f, 0x97,
+ 0x01, 0x56, 0xfc, 0x52, 0x31, 0x71, 0x62, 0xc2, 0x58, 0xbe, 0x92, 0x98,
+ 0x96, 0x28, 0x8d, 0xa7, 0x84, 0xae, 0x9d, 0x2c, 0x5b, 0xbf, 0x58, 0xbd,
+ 0x3f, 0x95, 0x8a, 0x94, 0x63, 0x62, 0xe1, 0xa4, 0x11, 0x0b, 0x90, 0xbd,
+ 0xff, 0x8b, 0x05, 0xb9, 0x66, 0xc1, 0xc1, 0x62, 0xfe, 0xcd, 0x01, 0xb0,
+ 0x0b, 0x17, 0xfd, 0x3a, 0xd3, 0xf7, 0x6e, 0x2d, 0x96, 0x2e, 0x63, 0x98,
+ 0x7d, 0x91, 0x85, 0xb7, 0x69, 0xc9, 0x1b, 0xdd, 0xd0, 0xad, 0xbe, 0x7f,
+ 0x86, 0x75, 0x8b, 0x3a, 0xc5, 0xdb, 0x32, 0xc5, 0x7c, 0xd4, 0xf8, 0x46,
+ 0xff, 0xf3, 0x9a, 0x66, 0x13, 0x75, 0xc3, 0x4d, 0x65, 0x8a, 0xdd, 0x17,
+ 0x8e, 0x9a, 0x44, 0x37, 0xdd, 0x37, 0xe5, 0x62, 0xff, 0x85, 0x9a, 0x2c,
+ 0xf7, 0xdd, 0x62, 0xfe, 0x81, 0x87, 0x6f, 0x4a, 0xc5, 0x40, 0xf9, 0xfa,
+ 0x38, 0xbf, 0xfb, 0x85, 0x80, 0x8c, 0xfb, 0xee, 0xda, 0x58, 0xbb, 0x31,
+ 0x62, 0xa5, 0x30, 0xb7, 0x84, 0x53, 0x11, 0x84, 0x91, 0x71, 0x04, 0xb1,
+ 0x7e, 0xe1, 0x09, 0xa0, 0xb1, 0x7f, 0xfb, 0x8e, 0x7e, 0xb8, 0xde, 0x17,
+ 0x5c, 0x95, 0x8b, 0xfb, 0xd1, 0x41, 0xb4, 0x6a, 0xc5, 0xd9, 0xba, 0xc5,
+ 0xe1, 0xe1, 0xac, 0x79, 0x3e, 0x31, 0xbe, 0xfc, 0x9f, 0x75, 0x8a, 0x94,
+ 0xcb, 0x70, 0x63, 0xa2, 0x86, 0x84, 0xb7, 0x8c, 0xee, 0x10, 0x16, 0x2f,
+ 0xde, 0xfb, 0x8b, 0xbf, 0x58, 0xa8, 0x1e, 0x36, 0x0c, 0x5f, 0x66, 0x11,
+ 0xab, 0x17, 0xd0, 0xd9, 0x8d, 0x58, 0xbf, 0xf8, 0xa7, 0xdc, 0xc2, 0x17,
+ 0x84, 0x6a, 0xc5, 0x18, 0x7d, 0x5c, 0x25, 0xae, 0x23, 0x43, 0xc4, 0x22,
+ 0x84, 0x65, 0xe1, 0xe7, 0xd6, 0x2f, 0x44, 0xe1, 0x2c, 0x58, 0x70, 0x37,
+ 0x8e, 0x3b, 0x7f, 0xfb, 0x37, 0x1b, 0x90, 0x79, 0xad, 0x4f, 0x65, 0x8b,
+ 0xff, 0x8c, 0x99, 0x29, 0x39, 0x86, 0x7e, 0x39, 0x62, 0xa5, 0x17, 0xa0,
+ 0x26, 0x24, 0xdb, 0xff, 0x18, 0x3c, 0x27, 0x07, 0x3e, 0xeb, 0x17, 0xfa,
+ 0x13, 0x84, 0x39, 0x3a, 0xc5, 0x68, 0xfc, 0x7b, 0xf3, 0xfb, 0xef, 0x6b,
+ 0x06, 0xb1, 0x7d, 0xa6, 0x23, 0x56, 0x2e, 0x14, 0x16, 0x2a, 0x4f, 0x79,
+ 0x88, 0xfb, 0x11, 0xdf, 0xfb, 0x8c, 0x60, 0xf3, 0xdc, 0x6e, 0x96, 0x2f,
+ 0xfd, 0xfc, 0x8b, 0xef, 0xf9, 0xd4, 0xac, 0x5c, 0xdd, 0x2c, 0x5e, 0x29,
+ 0x8f, 0x58, 0xbf, 0xcd, 0xc6, 0xf8, 0x8b, 0x65, 0x8a, 0x23, 0xeb, 0xf0,
+ 0xc0, 0x87, 0xe8, 0xc6, 0xc1, 0xbb, 0x65, 0x38, 0x46, 0x20, 0x37, 0x9c,
+ 0x21, 0xea, 0x18, 0x8f, 0x2b, 0x0e, 0x28, 0xcb, 0x35, 0x19, 0x39, 0xe1,
+ 0xe3, 0xf8, 0xce, 0x8a, 0x36, 0xee, 0x46, 0xc9, 0xe8, 0xcb, 0x85, 0x09,
+ 0xfe, 0xd0, 0x85, 0x08, 0xbc, 0x34, 0x1e, 0xe8, 0x55, 0x5d, 0xc1, 0x2c,
+ 0x5e, 0x98, 0xe8, 0xdd, 0x62, 0xda, 0x58, 0xba, 0x74, 0xb1, 0x78, 0xb3,
+ 0xb9, 0x62, 0xf9, 0xa7, 0xa8, 0x2c, 0x5d, 0x9f, 0x58, 0xbf, 0x6b, 0xa8,
+ 0x7a, 0x56, 0x2f, 0x67, 0x6c, 0x58, 0xac, 0x3c, 0x82, 0x2a, 0xa3, 0x11,
+ 0xd5, 0xb8, 0x93, 0x0b, 0xf0, 0x7e, 0x38, 0x8c, 0x35, 0xfb, 0xec, 0x3b,
+ 0xf9, 0x62, 0xa5, 0x3a, 0x58, 0x0c, 0x6a, 0x30, 0xff, 0x2e, 0x5c, 0x2d,
+ 0x2c, 0x58, 0xeb, 0x15, 0xb9, 0xaa, 0x38, 0xc5, 0xf6, 0x44, 0xe7, 0x58,
+ 0xbb, 0x40, 0x58, 0xb9, 0xb1, 0x62, 0xba, 0x35, 0xda, 0x18, 0xbc, 0x4d,
+ 0xe5, 0x8b, 0xc4, 0xfc, 0x58, 0xbc, 0x59, 0xd2, 0xc5, 0xd9, 0xd2, 0xc5,
+ 0x82, 0xef, 0x4f, 0xb6, 0x47, 0x36, 0x1c, 0x18, 0xed, 0xd3, 0xf5, 0x8b,
+ 0xed, 0x76, 0x63, 0xac, 0x5f, 0xdb, 0x9c, 0xa7, 0xa0, 0x2c, 0x5c, 0xc7,
+ 0x58, 0xbd, 0xc8, 0x4a, 0xc5, 0xfb, 0x99, 0x98, 0xeb, 0x15, 0x87, 0x86,
+ 0x01, 0xdb, 0xff, 0xce, 0x64, 0xc4, 0xfe, 0xd4, 0xee, 0x2d, 0xd6, 0x2f,
+ 0x01, 0xba, 0x58, 0xbe, 0xcf, 0x48, 0x4b, 0x15, 0x87, 0x82, 0x43, 0xd7,
+ 0xff, 0x9c, 0xcf, 0xe4, 0x4f, 0xd7, 0x3f, 0x9b, 0xac, 0x5c, 0x5c, 0x58,
+ 0xbf, 0xe8, 0x67, 0xb0, 0x5b, 0xb1, 0x2c, 0x5f, 0x13, 0x7b, 0x8b, 0x15,
+ 0x03, 0xf2, 0xe8, 0x5c, 0xe7, 0x37, 0xa7, 0x34, 0xb1, 0x7f, 0xfb, 0x76,
+ 0xd3, 0x79, 0xf9, 0x25, 0x20, 0x58, 0xb4, 0x3e, 0x7c, 0xa1, 0x8e, 0x5f,
+ 0xb3, 0xbd, 0x27, 0x1a, 0xc5, 0x74, 0x8e, 0xad, 0x42, 0x54, 0x05, 0x35,
+ 0x2b, 0xa5, 0xbb, 0x36, 0xc0, 0x88, 0x6a, 0x39, 0x08, 0xfd, 0xd2, 0x1c,
+ 0x5e, 0x22, 0x5d, 0x18, 0x1d, 0x68, 0x04, 0x3c, 0x84, 0x7f, 0x88, 0x05,
+ 0x1d, 0x55, 0xf0, 0xce, 0x17, 0x16, 0x2f, 0xf6, 0xff, 0x7d, 0x3e, 0x41,
+ 0x62, 0xe3, 0x5d, 0x62, 0xfe, 0x2c, 0x2d, 0x9f, 0x4b, 0x17, 0xf1, 0x66,
+ 0xdb, 0x4c, 0x7a, 0xc5, 0x01, 0x15, 0x7c, 0x34, 0xec, 0x31, 0xdc, 0x5b,
+ 0x7b, 0x60, 0xce, 0xb1, 0x79, 0xc3, 0x3a, 0xc5, 0x8e, 0xb1, 0x73, 0x8d,
+ 0x62, 0x9c, 0xf9, 0xd8, 0x83, 0x83, 0xc1, 0x89, 0x5e, 0xfc, 0x92, 0xc5,
+ 0xee, 0x77, 0x77, 0x2c, 0x5f, 0x19, 0x00, 0x1d, 0x62, 0xf6, 0xb0, 0x6b,
+ 0x17, 0xf1, 0x85, 0x80, 0x90, 0x2c, 0x5e, 0x2c, 0xe2, 0xc5, 0xf6, 0xc2,
+ 0x06, 0x11, 0xe5, 0x76, 0x2e, 0xbf, 0xcd, 0xe9, 0x8b, 0x8e, 0x75, 0x8b,
+ 0xf0, 0x8f, 0xed, 0xa3, 0x96, 0x28, 0xd4, 0xc1, 0x34, 0xcf, 0xf3, 0xbe,
+ 0x1a, 0x5f, 0xe9, 0x81, 0x67, 0x5e, 0xc5, 0x8b, 0xf6, 0xef, 0xd6, 0xc4,
+ 0xb1, 0x7f, 0xf3, 0x6f, 0x24, 0x38, 0xa1, 0x3a, 0xd9, 0x62, 0xba, 0x3f,
+ 0x2f, 0x95, 0xdb, 0x8b, 0x14, 0xe6, 0xd7, 0x84, 0x77, 0x8f, 0x87, 0x58,
+ 0xbe, 0x39, 0xe4, 0xeb, 0x17, 0xed, 0x33, 0x37, 0x96, 0x28, 0x67, 0xce,
+ 0xc3, 0xa4, 0x47, 0x7f, 0xfd, 0xee, 0x0f, 0x58, 0xe6, 0xfc, 0x26, 0x2d,
+ 0x96, 0x2d, 0xb2, 0xc5, 0xe1, 0xe1, 0xab, 0x15, 0xa3, 0x62, 0x42, 0x77,
+ 0xbe, 0x23, 0xac, 0x5d, 0xd8, 0x6b, 0x15, 0xdf, 0x6b, 0xb8, 0xd3, 0x0d,
+ 0x08, 0x42, 0xa4, 0x67, 0x78, 0x39, 0xd1, 0x23, 0xc6, 0x53, 0xa3, 0xff,
+ 0xc3, 0x69, 0xa1, 0x0f, 0xc2, 0xdf, 0x42, 0x10, 0x44, 0x01, 0x0f, 0x5f,
+ 0xb0, 0x8a, 0x76, 0x58, 0xb7, 0x4b, 0x1a, 0x34, 0xf4, 0xb1, 0x71, 0x41,
+ 0x62, 0x9c, 0xd1, 0x88, 0x32, 0xff, 0xb5, 0x84, 0x0e, 0x7b, 0x9d, 0x2c,
+ 0x5f, 0xb9, 0x14, 0x96, 0xcb, 0x15, 0x88, 0xcb, 0x35, 0x19, 0x88, 0x3c,
+ 0x77, 0x78, 0xc8, 0x6c, 0xb1, 0x7f, 0xc4, 0xfa, 0x9c, 0x2f, 0x89, 0x62,
+ 0xf1, 0xdf, 0x8b, 0x17, 0xe2, 0x35, 0xf3, 0x8b, 0x17, 0xfe, 0x83, 0x6b,
+ 0x6f, 0x8b, 0x60, 0x79, 0x62, 0xff, 0x38, 0x0e, 0xd0, 0xc2, 0x58, 0xbf,
+ 0x7d, 0xf8, 0xe3, 0x58, 0xbc, 0xf2, 0x75, 0x8b, 0x6a, 0x07, 0x89, 0xf2,
+ 0x8b, 0xe6, 0xf3, 0x6e, 0xb1, 0x4e, 0x79, 0x61, 0x14, 0x5f, 0x0b, 0xbf,
+ 0xe6, 0xcb, 0x17, 0xfe, 0x09, 0x81, 0x9b, 0xfd, 0x81, 0xc5, 0x8a, 0x93,
+ 0xeb, 0xc2, 0xab, 0xf7, 0x24, 0x01, 0xec, 0xb1, 0x7f, 0xff, 0x84, 0x45,
+ 0x9e, 0xfb, 0xe4, 0x3f, 0x9a, 0x67, 0xec, 0xb1, 0x7f, 0xcd, 0xd4, 0x93,
+ 0x0f, 0x0d, 0x58, 0xa0, 0x22, 0x67, 0x8c, 0x14, 0x6a, 0xad, 0xd7, 0x1d,
+ 0x88, 0xa3, 0x48, 0x7f, 0x86, 0x09, 0x42, 0x37, 0x84, 0x1e, 0x86, 0x25,
+ 0xff, 0xf9, 0xfa, 0xe7, 0xc2, 0x6f, 0x49, 0x31, 0x0a, 0x56, 0x2f, 0xff,
+ 0xc6, 0x7f, 0x06, 0xe5, 0x87, 0xeb, 0xc2, 0x6e, 0x2c, 0x50, 0x11, 0x59,
+ 0xd9, 0x56, 0xe0, 0x86, 0xb1, 0x7f, 0xfb, 0xdf, 0xc3, 0x81, 0xb5, 0x9d,
+ 0xb0, 0x6b, 0x17, 0x4f, 0xd6, 0x2c, 0x35, 0x8a, 0x39, 0xa9, 0x21, 0x7b,
+ 0x1a, 0xb1, 0x78, 0x81, 0x2b, 0x17, 0x10, 0xcc, 0x35, 0xfc, 0x13, 0xbb,
+ 0x3c, 0xb1, 0x7e, 0xe0, 0x4c, 0x5b, 0x2c, 0x5f, 0x49, 0xf0, 0x0b, 0x15,
+ 0x87, 0x99, 0xb9, 0x55, 0x4a, 0x6e, 0xd8, 0xea, 0xc9, 0xe0, 0x2d, 0x26,
+ 0x3b, 0xcd, 0xbe, 0x2c, 0x5f, 0xff, 0x84, 0xc1, 0xe7, 0xa4, 0xb3, 0x59,
+ 0x08, 0x4a, 0xc5, 0xe2, 0x60, 0x8c, 0x3f, 0x12, 0x1d, 0xbe, 0x26, 0x8f,
+ 0xe9, 0x62, 0xf7, 0x1b, 0x75, 0x8a, 0xf1, 0xe2, 0x08, 0x9a, 0xff, 0xc2,
+ 0x1f, 0xde, 0x7b, 0x68, 0x3e, 0x2c, 0x56, 0x8f, 0x94, 0x88, 0xaf, 0xbd,
+ 0x1d, 0x9f, 0x58, 0xbd, 0xc1, 0xca, 0xc5, 0xfe, 0xcd, 0xe4, 0x84, 0xd0,
+ 0x58, 0xbf, 0xff, 0xb7, 0xce, 0xbd, 0xf7, 0xd4, 0xb4, 0x01, 0x99, 0x12,
+ 0xc5, 0x1a, 0x89, 0x02, 0x33, 0xa3, 0x51, 0xa0, 0xd0, 0xad, 0xa9, 0x4c,
+ 0xff, 0x08, 0x45, 0x0f, 0x6b, 0xdc, 0x6e, 0xcb, 0x16, 0xe2, 0xc5, 0xb1,
+ 0x62, 0x9c, 0xd1, 0xf7, 0x09, 0x5f, 0x37, 0x80, 0x25, 0x8b, 0xc5, 0x26,
+ 0xac, 0x5f, 0xfd, 0xee, 0x60, 0x41, 0xb1, 0x69, 0xf7, 0x58, 0xad, 0xd1,
+ 0x0f, 0xd1, 0x18, 0x43, 0xb7, 0xf0, 0x67, 0xcc, 0x23, 0x56, 0x2e, 0x90,
+ 0x2c, 0x53, 0x9e, 0x30, 0x65, 0xf5, 0xd2, 0x70, 0xe7, 0x42, 0x68, 0x55,
+ 0x01, 0xe6, 0xff, 0x13, 0x43, 0x90, 0x0b, 0x65, 0x8b, 0xff, 0xff, 0x89,
+ 0x81, 0x85, 0xb6, 0x05, 0x9a, 0xd9, 0xf9, 0xfc, 0xf4, 0x76, 0x2c, 0x56,
+ 0x22, 0xaf, 0xc6, 0xd7, 0xd0, 0xe3, 0x92, 0xc5, 0xf7, 0xf7, 0x9d, 0xd6,
+ 0x2f, 0xfd, 0xb9, 0x37, 0xdb, 0xac, 0xeb, 0xcb, 0x17, 0xf8, 0x98, 0xdd,
+ 0x3c, 0x9a, 0xb1, 0x50, 0x46, 0xf7, 0x44, 0x4e, 0x44, 0x22, 0x50, 0x90,
+ 0x6c, 0x1a, 0xc5, 0xf6, 0xc1, 0x34, 0x16, 0x2f, 0xfe, 0x9d, 0x08, 0xe4,
+ 0xc6, 0x8f, 0x5d, 0xfa, 0xc5, 0xec, 0x63, 0xac, 0x51, 0xa7, 0xcf, 0xa4,
+ 0xba, 0x94, 0xc3, 0x7a, 0x4b, 0x71, 0x36, 0x84, 0x65, 0xf1, 0x79, 0xce,
+ 0xb1, 0x7a, 0x66, 0x0b, 0x18, 0x68, 0xaf, 0xe9, 0xe4, 0xfe, 0x78, 0xb1,
+ 0x7b, 0x77, 0xdd, 0x62, 0xf3, 0xfd, 0x96, 0x2f, 0xcd, 0x07, 0xf8, 0x96,
+ 0x29, 0x8f, 0x10, 0x87, 0x2f, 0x47, 0x67, 0xd6, 0x2e, 0xd4, 0x25, 0x14,
+ 0x7f, 0x63, 0xf1, 0x05, 0x69, 0x30, 0xb6, 0x86, 0x85, 0xde, 0xc5, 0x8a,
+ 0x96, 0x7c, 0x8e, 0xc7, 0x90, 0x20, 0xc9, 0x62, 0x86, 0xc6, 0x5d, 0xd1,
+ 0x2b, 0xc7, 0x1f, 0xa8, 0x5c, 0x7e, 0x50, 0xdb, 0x47, 0x76, 0x52, 0xb6,
+ 0x78, 0xc6, 0x28, 0xcd, 0x83, 0x28, 0xbf, 0x3f, 0x08, 0x5e, 0x58, 0xbe,
+ 0x07, 0x03, 0x02, 0xc5, 0xff, 0xe3, 0x5b, 0x3a, 0xf7, 0xa7, 0x3b, 0x3e,
+ 0xeb, 0x17, 0x9c, 0x80, 0xb1, 0x7f, 0xe8, 0x72, 0x4a, 0x77, 0x97, 0xfa,
+ 0xc5, 0xfd, 0x25, 0xef, 0xe4, 0x16, 0x2e, 0xd7, 0x16, 0x2b, 0x47, 0x8a,
+ 0xc5, 0xb5, 0xd2, 0x29, 0x3b, 0x42, 0x0e, 0xff, 0x16, 0x73, 0xcc, 0xc4,
+ 0xb1, 0x46, 0xa6, 0xd5, 0xf4, 0xe6, 0x86, 0x07, 0x62, 0xbb, 0xee, 0xee,
+ 0xe9, 0x8f, 0x58, 0xbf, 0xfe, 0xf3, 0x90, 0xa1, 0x9c, 0x18, 0x9b, 0x50,
+ 0x58, 0xb4, 0x98, 0x7f, 0x81, 0x96, 0x5f, 0xf8, 0xed, 0x0c, 0xfb, 0xeb,
+ 0xec, 0xb1, 0x6d, 0x68, 0xf9, 0xc0, 0x53, 0x7e, 0xe4, 0x45, 0x23, 0x58,
+ 0xa7, 0x3d, 0x1f, 0x14, 0x5f, 0xff, 0xc5, 0x86, 0xe1, 0x19, 0xcf, 0x7f,
+ 0x0e, 0x1c, 0x81, 0x62, 0xa4, 0xff, 0xb0, 0x86, 0xff, 0x09, 0xb8, 0xf1,
+ 0x38, 0x4b, 0x15, 0x2a, 0xf6, 0xde, 0x38, 0xff, 0xc7, 0xee, 0x44, 0x17,
+ 0xfc, 0x11, 0x31, 0xb8, 0x37, 0x25, 0x8b, 0xdf, 0x92, 0x58, 0xbe, 0xf7,
+ 0x9b, 0x75, 0x8b, 0xbc, 0x75, 0x8b, 0x47, 0x2c, 0x54, 0x0f, 0x47, 0xa2,
+ 0x4f, 0x8c, 0x54, 0xa3, 0x5b, 0x73, 0x96, 0x6d, 0xbe, 0x1e, 0x9c, 0x25,
+ 0x8b, 0xfb, 0x33, 0x6c, 0xcf, 0x2c, 0x5c, 0x6f, 0x65, 0x8b, 0xd8, 0x21,
+ 0xac, 0x56, 0xc8, 0x89, 0x19, 0x21, 0x16, 0xf0, 0x6e, 0xfd, 0x90, 0x90,
+ 0x71, 0x62, 0xff, 0xfe, 0xfc, 0xf3, 0x21, 0xf9, 0x39, 0x31, 0xa5, 0x80,
+ 0x58, 0xa8, 0x22, 0x0b, 0xc5, 0x17, 0xfd, 0xa3, 0x3f, 0x83, 0x29, 0xdd,
+ 0x62, 0xa4, 0xf7, 0x9c, 0x8e, 0xf3, 0x97, 0x96, 0x2f, 0x6f, 0x9a, 0x58,
+ 0xbd, 0xd9, 0xb7, 0x58, 0xa9, 0x37, 0xd8, 0x3d, 0x7d, 0xf9, 0xed, 0x8b,
+ 0x17, 0xf3, 0x76, 0x78, 0x9c, 0x25, 0x8a, 0x3a, 0x33, 0x89, 0x6b, 0xc3,
+ 0xe1, 0x92, 0x5f, 0xe1, 0x6b, 0x63, 0xce, 0x79, 0x62, 0xff, 0xb9, 0x27,
+ 0x1f, 0xe4, 0xb7, 0x58, 0xb9, 0xcb, 0x0f, 0xbc, 0xd3, 0x5b, 0x8b, 0x65,
+ 0x8a, 0x94, 0x78, 0x0e, 0x15, 0x98, 0x59, 0x7f, 0xdb, 0x66, 0xf2, 0x2f,
+ 0xe6, 0x96, 0x29, 0x62, 0xc2, 0x93, 0xc7, 0xe1, 0xdd, 0xf7, 0xdb, 0xa8,
+ 0x2c, 0x54, 0x0f, 0x2f, 0x72, 0x7b, 0xf3, 0x68, 0x11, 0xd8, 0xb1, 0x7b,
+ 0xbd, 0xed, 0xe5, 0x8a, 0x19, 0xe8, 0x76, 0x2b, 0xbd, 0xf0, 0xfb, 0x2c,
+ 0x5c, 0xfb, 0x2c, 0x5f, 0xf4, 0x9c, 0xb3, 0x7d, 0x38, 0x16, 0x2c, 0x35,
+ 0x8b, 0xdc, 0xe6, 0x2c, 0x58, 0x72, 0x6b, 0xd8, 0x4a, 0xa0, 0x8c, 0x6d,
+ 0x10, 0xf0, 0x60, 0x4d, 0x17, 0xe6, 0x7d, 0xf0, 0x96, 0x2f, 0xfe, 0xcc,
+ 0x23, 0x74, 0xfc, 0xe3, 0x1a, 0xb1, 0x5f, 0x3e, 0xc0, 0xc9, 0xef, 0xf4,
+ 0x31, 0xf9, 0xc1, 0x4a, 0xc5, 0xfc, 0x3c, 0x28, 0x7f, 0x16, 0x2f, 0xff,
+ 0xff, 0x67, 0x3f, 0x9a, 0x92, 0x6e, 0xa1, 0xf9, 0xf7, 0xa7, 0xaf, 0xc9,
+ 0xd6, 0x2a, 0x51, 0xb0, 0xe6, 0x67, 0x2d, 0xbf, 0xdf, 0x7e, 0xcf, 0xb8,
+ 0x67, 0x58, 0xbf, 0xf7, 0xa4, 0xfd, 0x6e, 0xfd, 0x66, 0x96, 0x2f, 0xdf,
+ 0xcd, 0x3f, 0x16, 0x2f, 0x13, 0xc3, 0x74, 0x51, 0x74, 0x71, 0xe4, 0x2b,
+ 0xfd, 0xf1, 0x6d, 0x16, 0x66, 0xeb, 0x17, 0x75, 0xe5, 0x8b, 0xf7, 0x5e,
+ 0x29, 0xc5, 0x8b, 0xf1, 0x30, 0xf0, 0xd5, 0x8b, 0xe8, 0x4e, 0x79, 0x62,
+ 0xec, 0x01, 0x87, 0xe5, 0x25, 0x1d, 0x14, 0x5f, 0xd3, 0xec, 0x71, 0x77,
+ 0xeb, 0x14, 0xc7, 0xda, 0x03, 0xbb, 0xfe, 0xcd, 0xb0, 0x78, 0x53, 0x1e,
+ 0xb1, 0x7f, 0xff, 0xee, 0x4c, 0x02, 0xcf, 0x87, 0xe2, 0x90, 0x37, 0x80,
+ 0x19, 0x41, 0x62, 0xa5, 0x70, 0x1f, 0x68, 0x7d, 0xc2, 0x1a, 0x03, 0x42,
+ 0x63, 0x70, 0x43, 0xe0, 0x88, 0x7c, 0x77, 0x7f, 0xf8, 0xbd, 0x1d, 0x91,
+ 0x41, 0xb5, 0xb0, 0xe5, 0x62, 0xff, 0xfe, 0x28, 0x4f, 0x9b, 0xfc, 0x76,
+ 0xf0, 0x03, 0x28, 0x2c, 0x52, 0xc5, 0xef, 0x64, 0x7a, 0xc5, 0x39, 0xac,
+ 0xf0, 0x65, 0xff, 0x4e, 0x43, 0xf8, 0xf0, 0xe2, 0xc5, 0x70, 0xf6, 0x3c,
+ 0x41, 0x7e, 0x1c, 0x5f, 0x14, 0x7a, 0xc5, 0x74, 0x7a, 0x04, 0x45, 0x58,
+ 0x9d, 0x03, 0xa7, 0xb4, 0x65, 0xf7, 0xed, 0x13, 0xe1, 0xab, 0x17, 0xe9,
+ 0xfb, 0xf5, 0x05, 0x8b, 0x8f, 0x05, 0x8b, 0xfd, 0x9d, 0x78, 0xc8, 0xe7,
+ 0x35, 0x62, 0xfd, 0xd7, 0xa3, 0x9c, 0xd5, 0x8b, 0xc7, 0x7f, 0x18, 0x7d,
+ 0x18, 0x75, 0x7f, 0xcd, 0x9b, 0x8f, 0x34, 0x07, 0x58, 0xa3, 0x13, 0x15,
+ 0x19, 0x4e, 0x42, 0x03, 0xe6, 0x77, 0xfb, 0xae, 0x06, 0x4f, 0x23, 0x58,
+ 0xbf, 0xfa, 0x77, 0x93, 0xc9, 0x30, 0xf0, 0xd5, 0x8a, 0xd2, 0x2f, 0x09,
+ 0x0f, 0xb8, 0xd6, 0xfe, 0xeb, 0x9f, 0x66, 0x3a, 0xc5, 0x4a, 0xa5, 0xa7,
+ 0x8f, 0xe4, 0x33, 0x2b, 0xfd, 0x0e, 0x14, 0x81, 0x8e, 0xb1, 0x7e, 0x6e,
+ 0xbd, 0xb4, 0xac, 0x54, 0x9e, 0xe9, 0x19, 0xdf, 0x8d, 0xc1, 0x6b, 0x65,
+ 0x8b, 0xdb, 0x8a, 0x56, 0x2f, 0xff, 0x8d, 0x6e, 0x6a, 0x7d, 0xfc, 0x3e,
+ 0x6b, 0x16, 0x2a, 0x4f, 0xbb, 0xc3, 0xd5, 0xa4, 0x5d, 0x05, 0x09, 0x9b,
+ 0xf9, 0xf5, 0xb0, 0x81, 0x8b, 0x17, 0xee, 0xe1, 0x1f, 0x06, 0xb1, 0x7b,
+ 0x4c, 0x05, 0x8b, 0xff, 0x4e, 0x75, 0xec, 0x3b, 0x10, 0x16, 0x2f, 0xa7,
+ 0x0b, 0x75, 0x8a, 0xf9, 0xf0, 0x78, 0xfa, 0xfb, 0xaf, 0x49, 0xd6, 0x2a,
+ 0x51, 0x86, 0x6b, 0xef, 0x44, 0x56, 0x25, 0x8b, 0xf9, 0xda, 0x1e, 0x7d,
+ 0x96, 0x2f, 0xef, 0x3f, 0xdc, 0xbc, 0xb1, 0x46, 0x1f, 0x67, 0xc4, 0x43,
+ 0x2e, 0xbf, 0xb8, 0xf9, 0xd9, 0xb4, 0xb1, 0x7f, 0xfb, 0x83, 0x29, 0x1f,
+ 0xe7, 0xdc, 0x33, 0x16, 0x2a, 0x08, 0xab, 0x39, 0x8f, 0x8b, 0xef, 0xfd,
+ 0x91, 0xe3, 0xfc, 0xfe, 0x7d, 0xc5, 0x8b, 0xff, 0xd3, 0x9d, 0x7b, 0xf3,
+ 0xe2, 0x90, 0x71, 0x62, 0xff, 0xfb, 0x38, 0x60, 0x0e, 0x21, 0xeb, 0xbf,
+ 0xe0, 0x67, 0x58, 0xba, 0x40, 0xb1, 0x76, 0x0d, 0x62, 0xef, 0x9d, 0x62,
+ 0xff, 0xfc, 0x22, 0xf7, 0x24, 0x8d, 0xfb, 0xe1, 0x34, 0x16, 0x2f, 0xff,
+ 0xe1, 0x41, 0xcb, 0x04, 0x03, 0x33, 0x84, 0x26, 0xd9, 0x62, 0xa0, 0x8b,
+ 0x0d, 0x2a, 0x54, 0x13, 0x73, 0xdd, 0x6a, 0x3c, 0x5f, 0x82, 0xfe, 0x86,
+ 0x45, 0x4a, 0xe8, 0x96, 0xc5, 0x38, 0x5e, 0xf0, 0xef, 0x68, 0xd2, 0x08,
+ 0xc3, 0xc8, 0x42, 0x8e, 0xf6, 0xfd, 0xb1, 0xdb, 0xd2, 0xb1, 0x7e, 0x1b,
+ 0x10, 0x8e, 0xb1, 0x7f, 0xe1, 0x03, 0x37, 0xcd, 0x69, 0xa0, 0xb1, 0x76,
+ 0xc4, 0xb1, 0x7f, 0xf0, 0x9a, 0x07, 0x17, 0xbf, 0x22, 0xef, 0xd6, 0x2e,
+ 0x93, 0xac, 0x54, 0xa6, 0x17, 0x85, 0x3a, 0x28, 0x64, 0x02, 0x18, 0xe2,
+ 0x5d, 0xff, 0xff, 0x9b, 0xb0, 0xe7, 0x9e, 0xeb, 0x77, 0x2f, 0x7f, 0x06,
+ 0x2f, 0x71, 0x62, 0xff, 0xf3, 0x45, 0x3d, 0x13, 0x1b, 0x83, 0x68, 0x2c,
+ 0x5e, 0xdb, 0x02, 0x58, 0xbe, 0x70, 0x44, 0x25, 0x8a, 0x82, 0x3f, 0xc6,
+ 0xe3, 0xa4, 0xb2, 0x1f, 0xbd, 0xb3, 0xe9, 0x62, 0xff, 0x82, 0xd6, 0x4f,
+ 0x50, 0x73, 0xac, 0x5f, 0xf7, 0x1f, 0xaf, 0x45, 0x09, 0xe9, 0x62, 0xfd,
+ 0xcf, 0x73, 0x3c, 0xb1, 0x52, 0x8a, 0x1e, 0x1d, 0x88, 0xf6, 0xfd, 0xdf,
+ 0xbc, 0x4e, 0x12, 0xc5, 0xfc, 0x53, 0x10, 0x98, 0x35, 0x8a, 0x11, 0xef,
+ 0x06, 0x5f, 0x76, 0x7d, 0x62, 0xff, 0xfd, 0xe2, 0x60, 0x73, 0xf3, 0x07,
+ 0x2c, 0x3c, 0xac, 0x5e, 0x08, 0x20, 0x92, 0x2f, 0x83, 0xd4, 0xc1, 0x22,
+ 0x30, 0xd0, 0xdf, 0xde, 0x7f, 0x73, 0xef, 0xc4, 0x55, 0xc7, 0x3a, 0x54,
+ 0xaa, 0xb5, 0x34, 0xf1, 0xe1, 0x7e, 0xd0, 0x8d, 0xf1, 0x18, 0xa1, 0x85,
+ 0x77, 0xba, 0x58, 0xbf, 0xcf, 0xad, 0x84, 0x0c, 0x25, 0x8b, 0xdf, 0x93,
+ 0xac, 0x51, 0xcf, 0xab, 0xbf, 0x19, 0x0c, 0xd2, 0xfb, 0xae, 0x4f, 0x4b,
+ 0x17, 0x67, 0x16, 0x2f, 0x40, 0xa4, 0xc3, 0x78, 0xc4, 0xb7, 0x44, 0xeb,
+ 0x17, 0xff, 0xf4, 0x24, 0xb3, 0xdf, 0x7c, 0xf4, 0x9d, 0xf5, 0x05, 0x8a,
+ 0xe9, 0x14, 0x5a, 0x31, 0xf0, 0xc5, 0xfc, 0x70, 0xcb, 0x3b, 0x62, 0xc5,
+ 0xfb, 0x38, 0x22, 0xf2, 0xc5, 0x3a, 0x22, 0x58, 0xc4, 0x8c, 0x2f, 0xff,
+ 0xb5, 0xb4, 0xfd, 0x9f, 0x5a, 0x73, 0xc6, 0xfd, 0xf6, 0xb1, 0x7e, 0xea,
+ 0x49, 0xce, 0xb1, 0x52, 0x88, 0x5c, 0x5d, 0xa9, 0x74, 0x75, 0x10, 0x9c,
+ 0x03, 0x1c, 0x63, 0xd9, 0x0b, 0x83, 0x63, 0x1d, 0xde, 0x3d, 0xee, 0xa1,
+ 0x8a, 0xee, 0x71, 0x43, 0xab, 0x53, 0x96, 0x07, 0x94, 0x43, 0xf9, 0x51,
+ 0xc0, 0x84, 0xa1, 0x4e, 0xf6, 0x72, 0x38, 0xcf, 0x4e, 0x04, 0x0a, 0x1a,
+ 0x1d, 0xa3, 0x9c, 0xee, 0x85, 0x95, 0xff, 0x75, 0x0e, 0x73, 0x06, 0xde,
+ 0x58, 0xb8, 0x99, 0x62, 0xf0, 0x1f, 0x75, 0x8b, 0xc5, 0x30, 0x58, 0x30,
+ 0xbe, 0xb8, 0xc3, 0x70, 0xf8, 0x1c, 0xd2, 0xfd, 0xe9, 0x17, 0x7f, 0xc5,
+ 0x8a, 0x73, 0xdc, 0xd1, 0x75, 0xcf, 0x1c, 0xb1, 0x74, 0x47, 0x58, 0xbf,
+ 0x66, 0xbc, 0x2f, 0xac, 0x56, 0x8f, 0x70, 0x03, 0x41, 0x8c, 0xdb, 0x16,
+ 0x2d, 0x8b, 0x11, 0xe5, 0x8d, 0xf6, 0x89, 0xbb, 0x2c, 0x5e, 0xc6, 0x25,
+ 0x8b, 0x04, 0xb1, 0x71, 0x98, 0xb1, 0x4c, 0x6a, 0xfc, 0x27, 0x52, 0xa9,
+ 0x88, 0x70, 0xf7, 0xc7, 0xd3, 0x50, 0x5c, 0x8f, 0x44, 0x87, 0x46, 0xbf,
+ 0x7d, 0xe4, 0xb6, 0x58, 0xba, 0x34, 0x09, 0x62, 0xfb, 0xcd, 0xd0, 0x16,
+ 0x2f, 0xfe, 0xf0, 0xba, 0x87, 0x3f, 0x9e, 0x91, 0xac, 0x54, 0x11, 0x12,
+ 0xc3, 0xdd, 0xc4, 0x95, 0xa4, 0x71, 0xfa, 0x16, 0x37, 0xa7, 0x90, 0x58,
+ 0xbf, 0x8a, 0x23, 0x40, 0xd1, 0x2c, 0x5f, 0xff, 0xb3, 0xdf, 0xc8, 0x6a,
+ 0x7e, 0xcf, 0xe9, 0xfa, 0xc5, 0x3a, 0x21, 0x48, 0xc6, 0xf0, 0x39, 0x8b,
+ 0x17, 0xdd, 0xcd, 0x3d, 0x2c, 0x5f, 0xed, 0x3f, 0x7f, 0xbf, 0xe4, 0x25,
+ 0x8b, 0xc2, 0x2d, 0xd6, 0x2f, 0xda, 0xdb, 0x66, 0x09, 0x62, 0xb0, 0xf2,
+ 0x83, 0x1e, 0xae, 0x91, 0x9a, 0xe4, 0xda, 0x84, 0x2d, 0xfe, 0x68, 0x45,
+ 0xf7, 0xeb, 0xcb, 0x17, 0xfd, 0xbb, 0x6b, 0x69, 0xdf, 0x0e, 0xb1, 0x60,
+ 0x96, 0x2f, 0x49, 0x41, 0x62, 0xff, 0xf3, 0x05, 0xec, 0xf9, 0x85, 0x86,
+ 0xcf, 0x16, 0x2a, 0x07, 0xd0, 0x43, 0x96, 0x65, 0x8b, 0xd3, 0xfe, 0x2c,
+ 0x57, 0x46, 0xb9, 0xc4, 0x6f, 0xfd, 0x3b, 0x99, 0x85, 0x22, 0xef, 0xf8,
+ 0xb1, 0x7f, 0x72, 0x73, 0x58, 0x4b, 0x17, 0xcd, 0x09, 0xd9, 0x62, 0xff,
+ 0x37, 0x9f, 0xec, 0x73, 0x30, 0xf3, 0xfe, 0x59, 0x7f, 0xee, 0x61, 0x0c,
+ 0xcc, 0x1b, 0xf6, 0x58, 0xbf, 0xfb, 0x8d, 0xd7, 0x39, 0x84, 0x08, 0xec,
+ 0x58, 0xbf, 0xf7, 0x26, 0x3b, 0x3d, 0x08, 0x67, 0x16, 0x2f, 0xff, 0xc3,
+ 0xcf, 0x71, 0xf9, 0xc9, 0xf0, 0x9b, 0x69, 0x58, 0xb3, 0xee, 0x89, 0x8d,
+ 0x21, 0x50, 0xd5, 0xc2, 0x6e, 0x6d, 0xd1, 0xe4, 0x4f, 0x7a, 0x4f, 0x39,
+ 0x09, 0x42, 0x53, 0x89, 0x3e, 0x41, 0xed, 0x0e, 0x0b, 0xdf, 0xc2, 0x58,
+ 0xbe, 0xdf, 0xf8, 0x35, 0x8a, 0xd1, 0xe0, 0x06, 0x39, 0x7f, 0xfe, 0x2c,
+ 0x7e, 0x3e, 0xa4, 0x5e, 0x8a, 0x70, 0x6b, 0x15, 0x2b, 0xa1, 0x6f, 0x2e,
+ 0xe5, 0xa1, 0xb6, 0x22, 0x3b, 0xf0, 0x70, 0x70, 0x71, 0x62, 0xf6, 0x4c,
+ 0xac, 0x5f, 0x14, 0x1c, 0xeb, 0x17, 0xe0, 0xf8, 0x16, 0x7d, 0x62, 0xb6,
+ 0x3e, 0x86, 0x1b, 0xe1, 0x15, 0xfc, 0x0e, 0xef, 0x3e, 0xb6, 0x58, 0xa1,
+ 0xa3, 0xd3, 0x50, 0x92, 0x22, 0xfb, 0xf8, 0x8c, 0x0f, 0x93, 0x8b, 0x17,
+ 0xf7, 0xfc, 0x6b, 0xf5, 0xc5, 0x8b, 0xe9, 0xf3, 0x7d, 0x62, 0xee, 0x6c,
0xb1, 0x79, 0x8e, 0xeb, 0x15, 0xb1, 0xeb, 0x8c, 0x8b, 0x43, 0x37, 0xde,
- 0x9e, 0xc3, 0x58, 0xa9, 0x64, 0x74, 0x6c, 0x5d, 0x90, 0xa2, 0xdc, 0x87,
- 0xf3, 0xb5, 0x6d, 0x19, 0xe0, 0x0d, 0x05, 0x08, 0x70, 0xcc, 0x2f, 0xfc,
- 0x39, 0x93, 0xe7, 0x04, 0xdd, 0xac, 0x5f, 0xff, 0x08, 0xcf, 0x14, 0x81,
- 0xbc, 0x03, 0x0a, 0x0b, 0x14, 0xe8, 0x91, 0xf1, 0xfd, 0xfb, 0x6e, 0xa0,
- 0xec, 0x0b, 0x17, 0xef, 0x7b, 0x08, 0xeb, 0x17, 0xff, 0x30, 0x27, 0xf8,
- 0x39, 0xe4, 0x81, 0x62, 0xff, 0xfe, 0xce, 0x61, 0x6a, 0x60, 0xe7, 0xce,
- 0xe1, 0x10, 0x96, 0x2f, 0xfe, 0xee, 0x1e, 0xfb, 0x1f, 0x37, 0x9e, 0x2c,
- 0x54, 0xa2, 0x8c, 0x4b, 0x97, 0xfa, 0x43, 0xef, 0xcf, 0x26, 0xac, 0x54,
- 0xa7, 0x28, 0xe5, 0xcc, 0x50, 0x50, 0xe6, 0xf1, 0x15, 0xc1, 0xfd, 0x62,
- 0xff, 0xf4, 0x96, 0xe6, 0x69, 0x80, 0xfe, 0xfc, 0xac, 0x5f, 0x36, 0xcc,
- 0x4b, 0x17, 0xef, 0x7f, 0x00, 0xcb, 0x15, 0xd9, 0xe5, 0x11, 0x15, 0xfc,
- 0x7e, 0xbf, 0xc0, 0x32, 0xc5, 0xfc, 0x1f, 0x33, 0x0b, 0x65, 0x8b, 0xe3,
- 0x3e, 0xfe, 0x58, 0xa9, 0x45, 0x2e, 0x11, 0x39, 0x87, 0x0b, 0xef, 0xed,
- 0x61, 0x0a, 0x74, 0xb1, 0x7f, 0xfd, 0x39, 0xd9, 0xad, 0xcc, 0x72, 0x6f,
- 0x71, 0x62, 0xfa, 0x79, 0x3d, 0x16, 0x2f, 0xfe, 0x92, 0x6f, 0x42, 0x4d,
- 0x60, 0xfc, 0xb1, 0x51, 0xb2, 0x39, 0x74, 0x5b, 0xf4, 0xf1, 0x12, 0x5e,
- 0xea, 0xdb, 0xac, 0x54, 0xae, 0x6b, 0x42, 0x3b, 0x6d, 0xd3, 0x00, 0x33,
- 0xc8, 0xce, 0xbd, 0x18, 0xf8, 0x44, 0x2b, 0xf1, 0x87, 0x3b, 0xc7, 0xac,
- 0x5f, 0xb0, 0xbc, 0xe7, 0x58, 0xa8, 0x1e, 0xa1, 0xcb, 0x6d, 0xc5, 0x8b,
- 0x9b, 0x8b, 0x15, 0x86, 0xa5, 0x84, 0xaf, 0x72, 0x60, 0xb1, 0x7d, 0x3a,
- 0x9d, 0xd6, 0x2b, 0x0f, 0x00, 0x87, 0x6f, 0xb5, 0xf7, 0x31, 0x62, 0xfe,
- 0x87, 0x3c, 0xf3, 0xda, 0xc5, 0xf1, 0xcc, 0x92, 0x58, 0xbe, 0x71, 0xe1,
- 0xd6, 0x2f, 0x99, 0x88, 0x0b, 0x16, 0x0e, 0x4f, 0x0c, 0xd2, 0x2a, 0x58,
- 0xb8, 0x47, 0x58, 0xbf, 0xc1, 0xb4, 0x59, 0x09, 0x8f, 0x58, 0xbf, 0x04,
- 0x14, 0x4f, 0x12, 0xc5, 0x3a, 0x2c, 0xa2, 0x29, 0xf8, 0x67, 0x06, 0x04,
- 0x71, 0x7f, 0xec, 0x1e, 0xa7, 0xcf, 0xbb, 0x8d, 0x62, 0xff, 0x9c, 0xff,
- 0xed, 0xa3, 0xfd, 0xc5, 0x8b, 0xfb, 0x76, 0xff, 0xf0, 0x6b, 0x15, 0x27,
- 0xda, 0x23, 0xeb, 0xc2, 0x0f, 0xcb, 0x17, 0x83, 0x60, 0xd6, 0x2c, 0x05,
- 0x8a, 0x93, 0x62, 0x60, 0xfd, 0xf7, 0xb8, 0x21, 0xac, 0x5f, 0x9f, 0xb8,
- 0x7b, 0x75, 0x8b, 0xfd, 0x2d, 0xaf, 0x86, 0xc3, 0x48, 0xb8, 0x30, 0xd2,
- 0x28, 0x67, 0x9c, 0x19, 0xa5, 0xcf, 0x1e, 0x91, 0x18, 0x68, 0xe8, 0x08,
- 0xc9, 0xf4, 0x27, 0x2f, 0xdb, 0xbf, 0x3e, 0xeb, 0x17, 0xfd, 0x20, 0xfc,
- 0xf0, 0x9a, 0x25, 0x8a, 0xec, 0xf8, 0x88, 0xa6, 0xf1, 0xe4, 0xeb, 0x17,
- 0xa0, 0x2f, 0x2c, 0x54, 0x9b, 0xb1, 0x0e, 0xd4, 0xae, 0xd8, 0xec, 0x96,
- 0x35, 0xfc, 0x20, 0xec, 0x91, 0xcb, 0xe2, 0x8c, 0x63, 0x49, 0x47, 0x85,
- 0x67, 0xc8, 0x40, 0xa0, 0x44, 0x3c, 0x87, 0x6f, 0xa1, 0x15, 0x1c, 0xbb,
- 0x7f, 0xff, 0xf0, 0x5b, 0xe9, 0xb7, 0x23, 0x5e, 0xd1, 0xa0, 0x53, 0x51,
- 0x17, 0xb0, 0x7d, 0x7a, 0xfe, 0x39, 0x62, 0xf8, 0x87, 0xf6, 0x58, 0xba,
- 0x0e, 0xb1, 0x7b, 0x1a, 0x3d, 0x62, 0xf6, 0xb0, 0x6b, 0x15, 0x1a, 0x26,
- 0x19, 0x90, 0x97, 0x72, 0x2d, 0x0b, 0xf4, 0x1f, 0xbd, 0xf9, 0xd2, 0xc5,
- 0xde, 0xe2, 0xc5, 0xf8, 0xfa, 0xd4, 0xec, 0xb1, 0x70, 0x0a, 0x4f, 0x0b,
- 0x06, 0x2f, 0xf1, 0x67, 0x8a, 0x7b, 0x82, 0xc5, 0x61, 0xef, 0x31, 0x5d,
- 0xfb, 0xbe, 0x4e, 0x8d, 0x58, 0xb8, 0x3e, 0x2f, 0x31, 0x02, 0xd8, 0xb1,
- 0x58, 0x6d, 0xfc, 0x4d, 0x5b, 0x22, 0x0b, 0xb6, 0x2b, 0xee, 0xe0, 0x15,
- 0xed, 0x62, 0xf7, 0x3a, 0xc1, 0x62, 0xff, 0xfc, 0x31, 0x36, 0xff, 0x6e,
- 0x4c, 0x7e, 0x61, 0x1a, 0xb1, 0x5d, 0x9f, 0xce, 0x88, 0x2d, 0xf5, 0x8b,
- 0xff, 0x70, 0x65, 0x23, 0xfc, 0xfb, 0x8b, 0x15, 0x27, 0xa3, 0xc1, 0x2a,
- 0x94, 0xd7, 0x70, 0x95, 0xa1, 0x46, 0x27, 0x4b, 0xff, 0xfe, 0xc0, 0xf2,
- 0x1f, 0xc7, 0x87, 0x3b, 0xe3, 0xf9, 0xcb, 0x65, 0x8b, 0xbf, 0x12, 0xc5,
- 0xfe, 0xfb, 0xb4, 0x3c, 0xfb, 0x2c, 0x5f, 0x39, 0x7a, 0x56, 0x2f, 0xf9,
- 0xf4, 0xc0, 0x09, 0xec, 0xfa, 0xc5, 0x7c, 0xf7, 0x3c, 0x43, 0x7f, 0xce,
- 0x19, 0x67, 0x9c, 0x40, 0x58, 0xbe, 0x72, 0x33, 0x8b, 0x17, 0xc5, 0x07,
- 0x3a, 0xc5, 0xbd, 0x27, 0x8a, 0xc4, 0x77, 0xe3, 0xbc, 0x4e, 0x1a, 0xc5,
- 0x49, 0xe8, 0x39, 0x35, 0xf6, 0x87, 0x3b, 0x2c, 0x5c, 0x78, 0xe5, 0x8a,
- 0x73, 0x7e, 0xc4, 0x97, 0xf1, 0x67, 0xb9, 0x20, 0x58, 0xbf, 0x7d, 0x8e,
- 0xfc, 0x58, 0xbf, 0x7b, 0x84, 0xe6, 0xac, 0x54, 0x0f, 0x47, 0x45, 0x15,
- 0xf4, 0x50, 0x33, 0xf5, 0xce, 0x1a, 0xc5, 0xc6, 0x6c, 0xb1, 0x7b, 0xbe,
- 0x61, 0x1b, 0x2f, 0x0c, 0x5f, 0x83, 0xd6, 0x98, 0x35, 0x8b, 0xa4, 0xeb,
- 0x17, 0xff, 0xff, 0xcf, 0xc3, 0x35, 0x3f, 0x9c, 0x3b, 0x94, 0x25, 0xfe,
- 0xfb, 0x93, 0xf4, 0x58, 0xbe, 0x0f, 0xd9, 0xf1, 0xa2, 0x53, 0x82, 0xf5,
- 0x29, 0x96, 0x61, 0x93, 0x42, 0xfe, 0xfc, 0x6e, 0x6b, 0x3c, 0xb1, 0x7f,
- 0xf6, 0x1b, 0x82, 0xd3, 0x0e, 0x7f, 0x2b, 0x14, 0xe7, 0xdb, 0xc2, 0x9b,
- 0x81, 0xc5, 0x8b, 0xff, 0x13, 0x07, 0xbf, 0xdf, 0xa3, 0xe9, 0x62, 0xf0,
- 0xff, 0x2b, 0x14, 0x33, 0xdf, 0x31, 0x0a, 0x82, 0xac, 0x8f, 0x69, 0x85,
- 0xec, 0x23, 0xff, 0xc4, 0x0d, 0xda, 0x3b, 0x19, 0x78, 0x48, 0x47, 0x91,
- 0x6a, 0x19, 0xdf, 0x5f, 0x68, 0x5f, 0x94, 0x70, 0x1c, 0x85, 0x07, 0x88,
- 0x44, 0xef, 0x7a, 0x26, 0xd2, 0xc5, 0xff, 0x7b, 0xf8, 0x01, 0x4f, 0x66,
- 0x2c, 0x5f, 0xff, 0xf9, 0x9f, 0xd3, 0xf2, 0xcf, 0x7d, 0xcc, 0x84, 0xf4,
- 0x72, 0x02, 0xc5, 0xfb, 0x7c, 0x3c, 0xf1, 0x62, 0xf0, 0x88, 0x6b, 0x17,
- 0xff, 0x63, 0xec, 0x79, 0x67, 0x83, 0x71, 0x62, 0xff, 0x30, 0x0c, 0x8e,
- 0x62, 0x02, 0xc5, 0x7c, 0xfe, 0x89, 0x0e, 0xfe, 0x7f, 0x70, 0x78, 0x4b,
- 0x17, 0xa7, 0xb8, 0x2c, 0x5f, 0xcf, 0xee, 0x61, 0xb1, 0x40, 0xf2, 0xf4,
- 0x5b, 0x7f, 0xfb, 0x3f, 0x85, 0xee, 0x67, 0x42, 0x9e, 0xd6, 0x2a, 0x55,
- 0x41, 0xf6, 0x3d, 0xf3, 0xc6, 0x6c, 0x01, 0x4f, 0xa1, 0x2f, 0xd1, 0xb0,
- 0x34, 0x6b, 0x9f, 0xb5, 0x8b, 0xd2, 0x5e, 0x58, 0xb9, 0xf4, 0xb1, 0x5b,
- 0x1b, 0x3c, 0x1c, 0xbf, 0x7f, 0xbc, 0x14, 0x4b, 0x17, 0xfa, 0x0e, 0x7f,
- 0xf6, 0xd1, 0xeb, 0x17, 0xf8, 0x21, 0x60, 0xff, 0x3d, 0x16, 0x2f, 0x9b,
- 0x53, 0x05, 0x8b, 0xee, 0xf0, 0x51, 0x2c, 0x5f, 0xf8, 0x53, 0xa3, 0x58,
- 0xcf, 0x3c, 0x16, 0x2f, 0xf9, 0xbb, 0xeb, 0xdf, 0x30, 0x8d, 0x58, 0xad,
- 0x93, 0x81, 0x19, 0x0f, 0x65, 0x6e, 0x70, 0x73, 0x7f, 0x91, 0x11, 0x2f,
- 0x90, 0x6f, 0xbf, 0x1e, 0xe7, 0x58, 0xbc, 0x52, 0x05, 0x8a, 0xea, 0x78,
- 0x5c, 0x26, 0xbf, 0xbc, 0xc7, 0x3c, 0x9d, 0x62, 0xc7, 0xc3, 0xd2, 0xec,
- 0x92, 0xff, 0x77, 0xfc, 0x8b, 0xef, 0xa5, 0x8b, 0xff, 0xf8, 0x9b, 0xcc,
- 0x78, 0x3f, 0xb3, 0xbf, 0x7c, 0xce, 0x2c, 0x54, 0xa2, 0xef, 0x0a, 0x18,
- 0xda, 0xfc, 0xc5, 0x9d, 0xca, 0xc5, 0xfe, 0xfc, 0x9f, 0x7f, 0xbc, 0x4b,
- 0x16, 0x98, 0xd8, 0xf7, 0x7b, 0x27, 0xbe, 0x6e, 0x76, 0xcb, 0x17, 0xfd,
- 0x0e, 0x7d, 0xb7, 0x92, 0x1a, 0xc5, 0xe0, 0x7b, 0xeb, 0x17, 0xee, 0xbe,
- 0x35, 0xf8, 0xb1, 0x50, 0x45, 0x3f, 0x64, 0x60, 0x3a, 0xf0, 0xf5, 0xff,
- 0xff, 0xb5, 0x83, 0xe3, 0x47, 0xbf, 0x7f, 0x67, 0x84, 0x8f, 0xe2, 0x35,
- 0x62, 0xc0, 0x58, 0xa6, 0x46, 0x0f, 0x0f, 0x8c, 0x71, 0xb8, 0x0c, 0xb1,
- 0x7d, 0xbe, 0x31, 0xd6, 0x2a, 0x4d, 0xd3, 0x8b, 0xdf, 0xb9, 0xfc, 0x03,
- 0x2c, 0x54, 0xaf, 0x6b, 0xc1, 0xeb, 0x23, 0xcc, 0x78, 0xf0, 0x75, 0x08,
- 0xa6, 0x8e, 0x54, 0x9a, 0xb8, 0x3f, 0x7b, 0x8f, 0xba, 0xc5, 0xf6, 0x48,
- 0x82, 0xeb, 0x17, 0xb4, 0x78, 0xe5, 0x8b, 0xf0, 0xf9, 0xc7, 0x3a, 0xc5,
- 0x6c, 0x79, 0x44, 0x43, 0x7e, 0xdd, 0xb6, 0xc0, 0xd6, 0x2f, 0xd3, 0xa1,
- 0xe1, 0x2c, 0x50, 0xd1, 0xc9, 0x8e, 0x04, 0x45, 0xe2, 0xbb, 0xf4, 0xc7,
- 0x3f, 0xc4, 0xb1, 0x76, 0x6e, 0xb1, 0x70, 0xf7, 0x58, 0xbe, 0x22, 0xc3,
- 0x56, 0x2b, 0x0d, 0xd8, 0x86, 0x6f, 0x69, 0xfe, 0xb1, 0x50, 0x44, 0x86,
- 0xea, 0x64, 0x41, 0x7c, 0x13, 0xce, 0x6a, 0xc5, 0xd2, 0x62, 0xc5, 0x70,
- 0xdf, 0x47, 0x13, 0x5f, 0xfd, 0x20, 0x9f, 0x9c, 0x98, 0xdf, 0xba, 0xc5,
- 0xa3, 0x65, 0x8b, 0xff, 0x66, 0xb3, 0xc6, 0x67, 0xd8, 0x0b, 0x17, 0xff,
- 0xd8, 0x46, 0xe6, 0xb6, 0x90, 0xf3, 0xf8, 0x4b, 0x17, 0xe9, 0x20, 0xdb,
- 0xb5, 0x8a, 0xc3, 0xf9, 0xfa, 0x85, 0xff, 0x8a, 0x29, 0xc2, 0xdb, 0x3b,
- 0xf2, 0xc5, 0xfb, 0xdc, 0x3e, 0xa5, 0x62, 0xa0, 0x9a, 0x10, 0xe1, 0x70,
- 0xc4, 0x24, 0x81, 0x7f, 0xc6, 0xeb, 0xcd, 0xa6, 0x8e, 0x95, 0x8b, 0xf7,
- 0xb9, 0xe7, 0xd9, 0x62, 0xa4, 0xf9, 0xd8, 0xf6, 0xff, 0xbf, 0x3b, 0xc8,
- 0x18, 0x80, 0xb1, 0x7f, 0x03, 0xae, 0x71, 0x89, 0x62, 0xff, 0xe1, 0x49,
- 0x31, 0xb1, 0x14, 0x83, 0x8b, 0x14, 0x34, 0x56, 0x91, 0xcf, 0x8b, 0xef,
- 0xc1, 0x51, 0xb9, 0x6e, 0xb1, 0x4e, 0x7b, 0x8c, 0x5f, 0x7c, 0x1b, 0x49,
- 0xd6, 0x2f, 0xee, 0x08, 0xf3, 0x83, 0x58, 0xbf, 0x37, 0x36, 0x7d, 0x2c,
- 0x5f, 0x69, 0xc5, 0xb2, 0xe2, 0xf5, 0x2f, 0x6e, 0x2d, 0x97, 0x17, 0xa9,
- 0x7f, 0xec, 0x7e, 0x98, 0x58, 0x36, 0x82, 0xe2, 0xf5, 0x2f, 0xcc, 0x5d,
- 0xc2, 0x30, 0x68, 0xa9, 0xe1, 0x88, 0x65, 0xb7, 0x30, 0x45, 0x8a, 0x1a,
- 0x67, 0x87, 0x86, 0x91, 0x28, 0xde, 0x73, 0xca, 0xc5, 0xdc, 0x75, 0x8b,
- 0xcc, 0xc4, 0xb1, 0x63, 0x78, 0x6c, 0xbc, 0x2f, 0x78, 0x85, 0xb2, 0xc5,
- 0x31, 0xe3, 0x78, 0xa2, 0xb1, 0x52, 0xa3, 0xc6, 0xd5, 0xa3, 0x52, 0x84,
- 0xa5, 0x46, 0x8c, 0x8d, 0x69, 0x8c, 0x08, 0x67, 0x79, 0x0b, 0xb7, 0x6e,
- 0xd1, 0x21, 0xd1, 0x1a, 0x35, 0x92, 0x85, 0x47, 0x23, 0x29, 0xf1, 0x00,
- 0xa5, 0x3b, 0xdf, 0xfc, 0x5f, 0x6e, 0x16, 0x1a, 0x6e, 0x47, 0xac, 0x5f,
- 0xcc, 0x7f, 0xce, 0x0d, 0x62, 0xb0, 0xfd, 0x49, 0x22, 0xe0, 0xa4, 0x68,
- 0xb1, 0x7e, 0x9c, 0x2f, 0x71, 0x62, 0xf3, 0xce, 0x96, 0x2a, 0x36, 0x3e,
- 0x43, 0x90, 0xfc, 0x9e, 0xff, 0xed, 0x39, 0xe6, 0x3c, 0xb0, 0xfd, 0xca,
- 0xc5, 0x40, 0xfe, 0xe2, 0x34, 0xbe, 0x68, 0x4c, 0x7a, 0xc5, 0xe2, 0x61,
- 0xac, 0x5e, 0xe6, 0xcc, 0xb1, 0x4e, 0x6e, 0x8c, 0x1c, 0xbf, 0xde, 0x7d,
- 0x4e, 0xf9, 0xd1, 0x62, 0xe3, 0xba, 0xc5, 0xfd, 0x23, 0x7e, 0x92, 0x35,
- 0x8b, 0xf7, 0xa4, 0xa6, 0x25, 0x8a, 0x94, 0x52, 0x6c, 0x6c, 0x31, 0x76,
- 0x2f, 0xbf, 0x61, 0xf4, 0xdd, 0xac, 0x56, 0xc9, 0xc4, 0x8d, 0x7c, 0xa1,
- 0x8b, 0xc3, 0xcb, 0xf4, 0x33, 0xa4, 0xc1, 0x62, 0xf6, 0x6a, 0x56, 0x2f,
- 0xed, 0x0f, 0x0d, 0x30, 0xeb, 0x17, 0x34, 0x7a, 0xc5, 0xee, 0x98, 0x35,
- 0x8b, 0xf9, 0xe7, 0xd0, 0x34, 0x6b, 0x17, 0x89, 0xf6, 0x58, 0xad, 0xd5,
- 0xf5, 0x77, 0x0f, 0xf7, 0x8e, 0xb3, 0x48, 0x7f, 0x2a, 0x61, 0xc2, 0x31,
- 0x10, 0xd0, 0x63, 0xe1, 0x0b, 0xec, 0x1a, 0xc5, 0xfe, 0x70, 0xe5, 0xc7,
- 0x87, 0x58, 0xb3, 0xe1, 0xe3, 0x44, 0x27, 0x7f, 0x42, 0x7e, 0xfd, 0xc1,
- 0x62, 0xff, 0xc5, 0x3b, 0xfe, 0x7a, 0x68, 0xce, 0x2c, 0x5e, 0x6d, 0x6c,
- 0xb1, 0x4b, 0x16, 0x2d, 0xcd, 0x54, 0x43, 0xd7, 0xfa, 0x1c, 0xee, 0x18,
- 0x23, 0x56, 0x2f, 0xa2, 0xd4, 0xec, 0xb1, 0x6f, 0xac, 0x31, 0xa5, 0xbf,
- 0x9f, 0xbe, 0x7f, 0x37, 0x58, 0xbe, 0xfe, 0x3c, 0x4b, 0x17, 0xb2, 0x46,
- 0xb1, 0x7f, 0x4f, 0x4c, 0xff, 0xe5, 0x62, 0xfd, 0x9e, 0xe6, 0x44, 0xb1,
- 0xf3, 0x5f, 0x7f, 0xff, 0xfd, 0x9d, 0xf1, 0xf0, 0x3e, 0xb9, 0xdc, 0x38,
- 0xfe, 0xe3, 0xf6, 0x31, 0x8b, 0x65, 0x8b, 0xff, 0x4e, 0xe5, 0x91, 0x7c,
- 0x5a, 0x89, 0x62, 0x96, 0x29, 0xd1, 0xa6, 0x50, 0x85, 0x08, 0x85, 0x7f,
- 0xa4, 0x8d, 0x09, 0xec, 0xfa, 0xc5, 0xff, 0xf9, 0xc8, 0x7d, 0x4c, 0xf3,
- 0xf1, 0x9c, 0x85, 0x05, 0x8b, 0xe6, 0xdb, 0xee, 0xb1, 0x43, 0x57, 0x43,
- 0x8d, 0xbd, 0x94, 0x3a, 0xe4, 0x44, 0x3a, 0x30, 0x39, 0x19, 0x25, 0xfa,
- 0x30, 0xc1, 0x1a, 0xf4, 0x36, 0x8e, 0x57, 0xbc, 0x2d, 0x41, 0x62, 0xff,
- 0xc7, 0x61, 0xea, 0x7d, 0xfc, 0x1a, 0xc5, 0xfc, 0xde, 0x01, 0x85, 0x05,
- 0x8b, 0xf6, 0xdb, 0xfe, 0x74, 0xb1, 0x7f, 0x99, 0x83, 0x03, 0x7b, 0x8b,
- 0x17, 0x19, 0xc5, 0x8a, 0x19, 0xe6, 0xfc, 0xd2, 0xf8, 0x51, 0x4f, 0x6b,
- 0x17, 0xb1, 0xe2, 0x58, 0xbf, 0xf0, 0xe7, 0xcd, 0x0c, 0xe8, 0xc3, 0x58,
- 0xb9, 0xf4, 0xb1, 0x73, 0xec, 0xb1, 0xb1, 0x6f, 0x7e, 0x92, 0x21, 0x1d,
- 0x62, 0xd0, 0xf1, 0xe7, 0x98, 0x51, 0x5d, 0x55, 0x1b, 0xc8, 0xf6, 0xc7,
- 0xf8, 0x5e, 0x6b, 0xc6, 0xe4, 0x51, 0x12, 0x9c, 0x75, 0xa1, 0x4d, 0x77,
- 0x31, 0x62, 0xff, 0xb3, 0x5b, 0x3f, 0x3f, 0x9c, 0x58, 0xbf, 0x3c, 0x60,
- 0x61, 0x86, 0x91, 0x7f, 0xe3, 0x5b, 0xbe, 0xbf, 0x63, 0xbf, 0x16, 0x2d,
- 0x30, 0x3f, 0x23, 0x97, 0xdd, 0x9f, 0x58, 0xbb, 0x02, 0xeb, 0x17, 0x60,
- 0xd6, 0x2f, 0xde, 0x01, 0x85, 0x05, 0x8a, 0x19, 0xee, 0x1a, 0x36, 0xc2,
- 0xf7, 0xe6, 0xd6, 0xf3, 0xe5, 0x8b, 0x9f, 0x4b, 0x15, 0xf3, 0xc0, 0x11,
- 0x4d, 0xb7, 0x58, 0xb9, 0x86, 0xb1, 0x7f, 0x69, 0xb9, 0xf6, 0x82, 0xc5,
- 0xbb, 0x58, 0xb9, 0xc3, 0x58, 0xb8, 0xc0, 0x2c, 0x54, 0x46, 0xc4, 0x03,
- 0x17, 0xa0, 0xc3, 0x58, 0xb8, 0x30, 0xd6, 0x2a, 0x08, 0xe2, 0xc1, 0x7d,
- 0xcb, 0x9d, 0x13, 0x84, 0x41, 0x8e, 0xdc, 0x60, 0x12, 0x23, 0x0f, 0x5e,
- 0x99, 0x37, 0x9f, 0x46, 0x99, 0x7f, 0x0b, 0xb8, 0x79, 0xfb, 0x58, 0xbf,
- 0xd8, 0x77, 0x1e, 0xc2, 0xe2, 0xc5, 0xff, 0xfc, 0x08, 0xec, 0xd4, 0xf9,
- 0xf7, 0x71, 0xed, 0x25, 0x2b, 0x17, 0xb3, 0xbf, 0x2c, 0x5b, 0x08, 0xff,
- 0x38, 0xbd, 0x5f, 0x46, 0xbf, 0x21, 0x63, 0x7f, 0xce, 0x3c, 0x3b, 0xc4,
- 0xe1, 0xac, 0x5f, 0xff, 0x4b, 0xf6, 0x0d, 0x60, 0xe7, 0x4f, 0xd8, 0x16,
- 0x2f, 0x8d, 0xfb, 0x41, 0x62, 0xf4, 0x3f, 0x23, 0x3f, 0x57, 0x51, 0xbf,
- 0xff, 0xdf, 0x67, 0xf4, 0xc0, 0x43, 0xc3, 0x33, 0x5e, 0x17, 0xd6, 0x2c,
- 0xcb, 0x15, 0x27, 0xe7, 0xc6, 0x2b, 0xff, 0xcc, 0x3c, 0xc2, 0x37, 0x9c,
- 0xc2, 0x02, 0xc5, 0xf7, 0xc4, 0xc6, 0xca, 0x77, 0xd9, 0x0a, 0xfd, 0x42,
- 0x94, 0xe4, 0x37, 0x8a, 0x7e, 0xb1, 0x7f, 0xff, 0x41, 0xb9, 0xc9, 0xcd,
- 0x85, 0x01, 0xe8, 0x98, 0x35, 0x8b, 0xff, 0xf3, 0xc1, 0xfc, 0x52, 0x01,
- 0x93, 0x72, 0x11, 0x2c, 0x5f, 0xf7, 0xb4, 0x28, 0x77, 0x0c, 0xf2, 0xc5,
- 0xff, 0x67, 0x3e, 0xd0, 0x1e, 0x82, 0xeb, 0x14, 0xe7, 0xf4, 0x47, 0x94,
- 0x34, 0xf1, 0x8d, 0x5e, 0x71, 0xc0, 0x2e, 0xf4, 0x86, 0x7d, 0xfd, 0xa6,
- 0x84, 0xe8, 0x0b, 0x17, 0xff, 0xfb, 0xed, 0x0f, 0xcb, 0x6b, 0x9c, 0xcf,
- 0xbf, 0x05, 0xb2, 0xc5, 0xb3, 0x48, 0x90, 0xf9, 0x75, 0xff, 0xf6, 0xa5,
- 0xa1, 0xa9, 0xfb, 0x3e, 0xf8, 0x4b, 0x15, 0x29, 0xac, 0x42, 0x1c, 0x4e,
- 0x51, 0x5f, 0x5e, 0x40, 0xe4, 0x61, 0x1e, 0x9d, 0x04, 0xbf, 0x8e, 0xd0,
- 0xda, 0x28, 0xe5, 0x8b, 0xe3, 0xef, 0x09, 0x58, 0xbd, 0x08, 0xf8, 0x2c,
- 0x5e, 0xfb, 0xf1, 0x62, 0xf1, 0x92, 0x4b, 0x15, 0x27, 0xb7, 0x02, 0x1f,
- 0x0e, 0xdf, 0xec, 0xe4, 0x5f, 0x70, 0xfc, 0xb1, 0x7e, 0xdb, 0x30, 0x8d,
- 0x58, 0xa9, 0x3d, 0xf6, 0x36, 0xbf, 0x9c, 0xfb, 0xe1, 0x6e, 0xb1, 0x7c,
- 0xdb, 0x73, 0xeb, 0x15, 0xa3, 0xd3, 0xe1, 0x7d, 0x75, 0x65, 0x7e, 0x41,
- 0xcc, 0x6d, 0xfd, 0xc7, 0x36, 0xf3, 0xcd, 0x27, 0x41, 0x63, 0x42, 0x7f,
- 0xe4, 0x23, 0x7c, 0xe7, 0x60, 0xa2, 0xc5, 0xe6, 0x63, 0xac, 0x5e, 0xfb,
- 0xf9, 0x62, 0xdd, 0x02, 0xa7, 0x9f, 0xf1, 0x63, 0x07, 0x2f, 0xf3, 0x1d,
- 0xe4, 0xf8, 0x4b, 0x17, 0xf7, 0xe7, 0x5e, 0xcd, 0xd6, 0x28, 0x67, 0xc1,
- 0xe3, 0x1b, 0xf4, 0x23, 0x9f, 0xe2, 0x58, 0xac, 0x3c, 0xe6, 0x22, 0xb8,
- 0xd6, 0x58, 0xbe, 0xc2, 0x14, 0x4b, 0x17, 0xcf, 0xd2, 0x46, 0xb1, 0x7f,
- 0xfe, 0xe3, 0x7b, 0x85, 0x9c, 0x9e, 0xc1, 0xec, 0xe2, 0xc5, 0x76, 0x89,
- 0xd3, 0x91, 0xf8, 0x92, 0xed, 0x44, 0xb1, 0x63, 0xac, 0x5d, 0xa9, 0x58,
- 0xa9, 0x3c, 0x21, 0x8c, 0xe0, 0x95, 0x4b, 0x6e, 0xfb, 0x08, 0x70, 0x0c,
- 0x9f, 0x25, 0xe8, 0x3c, 0xae, 0x8d, 0x42, 0x20, 0xe2, 0xff, 0x85, 0x63,
- 0x52, 0xc8, 0xc1, 0x0f, 0x12, 0x87, 0x57, 0x88, 0x05, 0x0b, 0x58, 0xe7,
- 0x3b, 0xd1, 0xed, 0x2b, 0x17, 0xcd, 0x0d, 0x4a, 0xc5, 0x99, 0x62, 0x9c,
- 0xf4, 0x88, 0x7f, 0x84, 0x57, 0xff, 0xff, 0xff, 0xfa, 0x3b, 0x0e, 0xd0,
- 0x7e, 0x03, 0x01, 0xf6, 0x78, 0x48, 0xfe, 0x23, 0x65, 0xc9, 0xbd, 0x30,
- 0x6e, 0x9f, 0x68, 0x2c, 0x5f, 0xbe, 0xfd, 0x33, 0x65, 0x8a, 0x74, 0x74,
- 0xf2, 0x17, 0xd7, 0xff, 0xd1, 0x3c, 0xf5, 0x11, 0x84, 0xc3, 0xfe, 0x79,
- 0x62, 0xff, 0x0b, 0xdf, 0xcd, 0x3f, 0x16, 0x29, 0xd1, 0x0f, 0xf5, 0x3b,
- 0xec, 0xc3, 0xca, 0xc5, 0xee, 0x34, 0x4b, 0x17, 0xfe, 0x1c, 0x94, 0x42,
- 0xfb, 0x7e, 0x56, 0x2f, 0x8f, 0x3d, 0xc1, 0x62, 0xff, 0xd9, 0xd2, 0x46,
- 0x59, 0xec, 0x02, 0xc5, 0xd8, 0x4b, 0x16, 0xce, 0xcf, 0x57, 0xa1, 0xfd,
- 0xfb, 0xfe, 0x98, 0x1d, 0x62, 0xe3, 0x00, 0xb1, 0x4e, 0x8e, 0x5d, 0x3c,
- 0xfc, 0xa8, 0x05, 0x37, 0x6d, 0x05, 0x8b, 0x44, 0xb1, 0x52, 0x6b, 0x0c,
- 0x19, 0xbc, 0xe4, 0x35, 0x8b, 0xc5, 0x83, 0x58, 0xbf, 0xe3, 0xe7, 0xa4,
- 0x02, 0x60, 0x2c, 0x5f, 0xfc, 0xe3, 0x6f, 0x3f, 0x32, 0x19, 0xf5, 0x8b,
- 0x98, 0x22, 0xc5, 0xec, 0xef, 0xcb, 0x15, 0xf3, 0xfa, 0xf2, 0x18, 0x41,
- 0x9b, 0xfb, 0x35, 0x3e, 0xe6, 0x2c, 0x5f, 0xff, 0x37, 0x70, 0x98, 0x60,
- 0xf9, 0x30, 0x92, 0x58, 0xbf, 0xfb, 0x93, 0x0c, 0x18, 0x4c, 0x2c, 0x02,
- 0xc5, 0x62, 0x3c, 0x9c, 0xc4, 0x8b, 0x7c, 0x9f, 0x7f, 0x71, 0xbe, 0xf2,
- 0x05, 0x8b, 0xf1, 0x7b, 0x98, 0x4b, 0x17, 0xff, 0x76, 0x0d, 0x33, 0x77,
- 0x0e, 0x18, 0x75, 0x8b, 0xf6, 0x7b, 0xd9, 0xb2, 0xc5, 0x80, 0xb1, 0x78,
- 0xc2, 0x81, 0x1b, 0xb3, 0x0a, 0x69, 0xd1, 0xbc, 0xc4, 0xe0, 0x84, 0x25,
- 0xfb, 0x4d, 0xd0, 0x23, 0x2c, 0x54, 0xaf, 0xa9, 0xc2, 0x31, 0x61, 0xc2,
- 0xbb, 0x72, 0x2e, 0xc8, 0x5c, 0x7b, 0x51, 0x92, 0x1d, 0xa3, 0xe4, 0x2c,
- 0x38, 0x01, 0xc2, 0x8e, 0x97, 0x87, 0x5e, 0x8c, 0x2f, 0xa1, 0x9d, 0xf8,
- 0x29, 0x1b, 0x46, 0xf1, 0xde, 0x58, 0xbf, 0xdb, 0x78, 0xff, 0xc0, 0x32,
- 0xc5, 0xf6, 0x13, 0x9a, 0xb1, 0x50, 0x44, 0x91, 0xce, 0xfa, 0x1a, 0xdd,
- 0xb8, 0x45, 0x8b, 0xdc, 0x87, 0xd6, 0x28, 0x8d, 0xcf, 0x86, 0xef, 0xff,
- 0xdc, 0x26, 0xe7, 0xf2, 0x19, 0xf7, 0xd7, 0xd9, 0x62, 0xff, 0x9c, 0xd2,
- 0xcf, 0xfe, 0x7c, 0xb1, 0x7d, 0x9e, 0x7e, 0x2c, 0x57, 0x68, 0xaf, 0xd2,
- 0xa1, 0x1c, 0xdf, 0x67, 0x7b, 0x74, 0x58, 0xbf, 0x83, 0xe4, 0xfa, 0x46,
- 0xb1, 0x7b, 0xd1, 0x1d, 0x62, 0xa4, 0xf3, 0xb0, 0xbe, 0xff, 0x70, 0x6c,
- 0x79, 0xf6, 0xeb, 0x17, 0xf8, 0x78, 0x42, 0x86, 0x71, 0x62, 0xbb, 0x3e,
- 0x82, 0x35, 0xbd, 0xc1, 0x01, 0x62, 0xd8, 0xb1, 0x5d, 0x9a, 0xfe, 0x83,
- 0xd7, 0x16, 0xeb, 0x15, 0x26, 0xf1, 0x89, 0x2f, 0xf1, 0x9e, 0x2c, 0xd9,
- 0xf4, 0xb1, 0x7a, 0x5c, 0x6b, 0x17, 0xff, 0xdb, 0x8d, 0xcb, 0x6e, 0x7b,
- 0xbd, 0xdf, 0xf1, 0x2c, 0x5c, 0x3e, 0xd6, 0x2e, 0x2d, 0xf0, 0xfb, 0xcd,
- 0x56, 0xbe, 0x60, 0x98, 0x4b, 0x17, 0x9f, 0x8e, 0xb1, 0x4c, 0x7d, 0xbc,
- 0x2e, 0xf1, 0x1d, 0xfd, 0x9b, 0xcf, 0xe4, 0xeb, 0x15, 0x2b, 0x93, 0x98,
- 0xd6, 0xf0, 0xcf, 0xd1, 0x81, 0xdd, 0x5a, 0x11, 0x00, 0x84, 0x69, 0x0f,
- 0xf0, 0xd4, 0x50, 0xf8, 0x0c, 0xba, 0xff, 0xd2, 0x60, 0x05, 0x08, 0x37,
- 0xc4, 0xb1, 0x7b, 0x30, 0xd5, 0x8b, 0xe8, 0x48, 0x38, 0xb1, 0x43, 0x3c,
- 0x0c, 0x1d, 0xad, 0x91, 0x45, 0xdc, 0x20, 0x6f, 0xbc, 0x26, 0x25, 0x8b,
- 0xff, 0xf1, 0xe2, 0xd4, 0xff, 0x3d, 0x30, 0x6e, 0x83, 0x95, 0x8b, 0xb3,
- 0x4b, 0x17, 0xee, 0x3b, 0x31, 0xab, 0x15, 0xd4, 0xdf, 0xf6, 0x2f, 0x7e,
- 0x1f, 0xe4, 0x02, 0x58, 0xba, 0x60, 0xb1, 0x6d, 0x40, 0xf0, 0x34, 0x53,
- 0x7b, 0xed, 0x12, 0xc5, 0xff, 0xf9, 0xb9, 0xcc, 0x6d, 0xfd, 0xf6, 0x3e,
- 0xb3, 0x65, 0x8b, 0xfc, 0xe3, 0x70, 0xbc, 0x93, 0xac, 0x54, 0xa7, 0x9b,
- 0xb4, 0x25, 0xf1, 0x93, 0x72, 0x8d, 0x0f, 0x7d, 0x5e, 0xff, 0xf9, 0xcd,
- 0xc7, 0x3e, 0xa4, 0x41, 0x76, 0xff, 0x16, 0x2f, 0xf3, 0x43, 0x07, 0xae,
- 0x71, 0x62, 0xf6, 0x18, 0x35, 0x8b, 0xfe, 0xcd, 0xbf, 0x91, 0x7d, 0xcd,
- 0x58, 0xbf, 0xb3, 0xb0, 0x67, 0xb8, 0xb1, 0x7e, 0x92, 0xee, 0x1c, 0x58,
- 0xf9, 0xaf, 0xa9, 0x46, 0x11, 0x0f, 0x09, 0xae, 0xff, 0xfa, 0x73, 0x98,
- 0x5e, 0xfe, 0x0c, 0x5e, 0xe2, 0xc5, 0xd3, 0xf5, 0x8a, 0x23, 0xe6, 0xe2,
- 0x7d, 0xff, 0xfb, 0x37, 0x6f, 0x75, 0xcd, 0x6c, 0x7c, 0xe7, 0x25, 0x62,
- 0xa0, 0x7f, 0x5e, 0x21, 0xbc, 0x79, 0x82, 0xc5, 0xfb, 0x9f, 0xfc, 0x92,
- 0xc5, 0xfc, 0xfe, 0x6f, 0x87, 0x1e, 0xb1, 0x7f, 0xff, 0xff, 0xf6, 0xb0,
- 0x1e, 0xfb, 0x1f, 0xaf, 0x04, 0xf0, 0x11, 0xbf, 0x68, 0x75, 0xf0, 0xbc,
- 0xfe, 0xe7, 0xdd, 0x62, 0xf9, 0xcd, 0xc1, 0xac, 0x5e, 0x37, 0x06, 0xb1,
- 0x76, 0x1f, 0xa9, 0xe0, 0xb9, 0x1d, 0x6c, 0x9c, 0x6e, 0x0e, 0x9a, 0x51,
- 0xa3, 0x2f, 0x43, 0xa2, 0xfe, 0x9d, 0xa3, 0xb3, 0x52, 0xb1, 0x7f, 0x45,
- 0xfc, 0xe3, 0x12, 0xc5, 0xfd, 0xdc, 0x0c, 0xe4, 0xe2, 0xc5, 0x61, 0xef,
- 0x39, 0x75, 0xe0, 0x3f, 0xd6, 0x2f, 0xfc, 0x3c, 0xee, 0x1c, 0xf7, 0x18,
- 0x0b, 0x15, 0xa3, 0xfe, 0x01, 0x00, 0x87, 0x6f, 0xf0, 0xb9, 0xf6, 0x84,
- 0x3e, 0xb1, 0x7d, 0xce, 0x60, 0x6b, 0x17, 0xfe, 0x33, 0xbe, 0xbf, 0x6e,
- 0xfc, 0x60, 0x16, 0x2f, 0xf0, 0x63, 0xfe, 0x74, 0xcd, 0x2c, 0x5f, 0xfc,
- 0xe7, 0xeb, 0xbf, 0xdf, 0xfb, 0xbf, 0x16, 0x2f, 0xf6, 0x43, 0x04, 0x17,
- 0x62, 0x58, 0xbf, 0xfa, 0x61, 0xf9, 0xef, 0xd3, 0xf6, 0x8f, 0x58, 0xbf,
- 0xcc, 0x0e, 0x78, 0xb2, 0x0b, 0x15, 0x29, 0x98, 0xe8, 0xdf, 0xe9, 0x24,
- 0x6d, 0xe4, 0x8b, 0xff, 0xfc, 0xe5, 0x9d, 0xf8, 0xd6, 0xf7, 0xe7, 0xf9,
- 0xd1, 0xa0, 0xb1, 0x7c, 0xc0, 0xf0, 0x5d, 0x62, 0xff, 0x61, 0xe2, 0x83,
- 0x16, 0xcb, 0x17, 0xb3, 0x09, 0x62, 0xb6, 0x64, 0x44, 0x0d, 0x53, 0x78,
- 0x7b, 0x77, 0x18, 0x73, 0xc7, 0x5f, 0x12, 0x8e, 0xa3, 0x0d, 0x39, 0x7f,
- 0xcd, 0x40, 0x49, 0xe8, 0xde, 0x3a, 0x24, 0x86, 0xc6, 0x61, 0x38, 0x43,
- 0x5b, 0xf8, 0xb3, 0x6d, 0xa6, 0x3d, 0x62, 0xfc, 0x7f, 0x16, 0x41, 0x62,
- 0xff, 0xa7, 0x5c, 0x2c, 0x3c, 0xee, 0xb1, 0x76, 0xff, 0x58, 0xb8, 0xa5,
- 0x62, 0xfd, 0xcf, 0xc8, 0x7c, 0x58, 0xbf, 0x8d, 0xef, 0xdf, 0x7f, 0xac,
- 0x50, 0xcf, 0x6f, 0x45, 0x57, 0xf9, 0xf5, 0x3d, 0x01, 0xc8, 0x2c, 0x5f,
- 0xff, 0xe1, 0x1d, 0xf8, 0x59, 0xad, 0x64, 0x5f, 0xcd, 0x67, 0x6b, 0x14,
- 0x34, 0x4c, 0x68, 0xda, 0xe9, 0x3a, 0xc5, 0x49, 0xba, 0xf9, 0x1d, 0x7d,
- 0x38, 0x56, 0x71, 0xf4, 0x3d, 0x2f, 0xfb, 0x8d, 0xf7, 0x1e, 0xef, 0xb2,
- 0xc5, 0xfe, 0x68, 0x60, 0xf9, 0xc9, 0x58, 0xbf, 0xbd, 0xf9, 0x3c, 0x44,
- 0xb1, 0x52, 0x89, 0xdc, 0x3b, 0x01, 0x9d, 0x46, 0xec, 0xef, 0xb9, 0x8f,
- 0xbf, 0x29, 0x1c, 0xa6, 0xc3, 0xdb, 0x73, 0x27, 0x28, 0xd1, 0xcb, 0x47,
- 0x3c, 0x28, 0x69, 0x5c, 0x5e, 0x58, 0xbc, 0x2d, 0x6c, 0xb1, 0x7b, 0x71,
- 0x4a, 0xc5, 0xe0, 0xdb, 0xeb, 0x17, 0xb0, 0x0c, 0xb1, 0x52, 0x88, 0xe8,
- 0x0b, 0xb8, 0xfe, 0x87, 0xbe, 0x3d, 0x7d, 0x82, 0xd6, 0xcb, 0x17, 0xfe,
- 0xe8, 0xfe, 0x00, 0x8b, 0x8e, 0x35, 0x8b, 0xf4, 0xf7, 0xe9, 0xd2, 0xc5,
- 0xfb, 0x39, 0xf1, 0x6c, 0xb1, 0x6d, 0x75, 0x45, 0xc6, 0x12, 0x1d, 0x07,
- 0xe5, 0x37, 0xff, 0xf9, 0xa0, 0x64, 0x3f, 0x82, 0x0b, 0xe1, 0x1a, 0x45,
- 0x91, 0x2c, 0x54, 0xa2, 0xa8, 0xe8, 0x97, 0xfd, 0xd4, 0x64, 0xc6, 0x9a,
- 0xc1, 0xac, 0x5f, 0x9f, 0x50, 0x8a, 0x56, 0x2f, 0xfe, 0xfe, 0x13, 0x1b,
- 0xf7, 0xf4, 0x1d, 0x62, 0xbe, 0x7d, 0xbc, 0x29, 0xac, 0x46, 0x6b, 0xc2,
- 0xae, 0xfd, 0x85, 0xb3, 0xe9, 0x62, 0xce, 0xb1, 0x5f, 0x37, 0x31, 0xc5,
- 0x17, 0xff, 0xc2, 0xdc, 0xce, 0xc0, 0xdc, 0x6d, 0x3f, 0x60, 0x58, 0xbf,
- 0x4f, 0xcb, 0x0d, 0x58, 0xa7, 0x3f, 0xdf, 0xaa, 0xdf, 0xa6, 0x2f, 0xbe,
- 0x96, 0x2f, 0xf6, 0xb7, 0xfb, 0x94, 0xc1, 0x62, 0xfd, 0xee, 0x48, 0x36,
- 0x58, 0xa9, 0x3d, 0xe1, 0x1a, 0x5f, 0xfe, 0xc1, 0xcc, 0x27, 0x9c, 0xc8,
- 0x42, 0x56, 0x2f, 0x9b, 0x53, 0x05, 0x8b, 0xff, 0xf9, 0xc9, 0x9c, 0x81,
- 0xa9, 0xfb, 0x3f, 0xa7, 0xeb, 0x17, 0xff, 0x98, 0x81, 0xd7, 0x9c, 0x98,
- 0xa0, 0xf1, 0x2c, 0x50, 0xd3, 0x31, 0x39, 0x09, 0x24, 0xf8, 0x8a, 0x39,
- 0x5e, 0xff, 0xfe, 0x9f, 0x3e, 0xee, 0x3e, 0x37, 0x70, 0xc2, 0xc1, 0xac,
- 0x5f, 0x7b, 0x82, 0xd9, 0x62, 0xff, 0xff, 0xbb, 0xd4, 0x8b, 0xc2, 0x3e,
- 0x99, 0x80, 0x59, 0xd1, 0xf4, 0xb1, 0x4e, 0x88, 0xe6, 0x25, 0xbf, 0xf4,
- 0x0c, 0x1b, 0x6d, 0x87, 0x6e, 0x2c, 0x5f, 0xf4, 0x27, 0xf3, 0xef, 0xb1,
- 0xd6, 0x2a, 0x4f, 0xe8, 0x48, 0x37, 0xff, 0x89, 0xc1, 0xee, 0xf7, 0x7d,
- 0x19, 0x23, 0x58, 0xbf, 0xc4, 0xf9, 0xbc, 0xfb, 0x8b, 0x17, 0xfd, 0xf3,
- 0x06, 0x2f, 0x70, 0x12, 0xb1, 0x52, 0x8b, 0xc7, 0x4d, 0x63, 0x3b, 0xff,
- 0xf3, 0xf7, 0x02, 0x9f, 0xe7, 0x49, 0xef, 0xf9, 0xb2, 0xc5, 0xef, 0x3e,
- 0xcb, 0x14, 0x35, 0xd2, 0xbd, 0xc8, 0x5e, 0x3b, 0x8d, 0x26, 0x9e, 0x1d,
- 0x25, 0x09, 0xbf, 0x43, 0x77, 0xa1, 0x69, 0x8b, 0x37, 0xbe, 0xff, 0x58,
- 0xbf, 0x0a, 0x4b, 0xdc, 0x58, 0xbc, 0x7c, 0x1a, 0xc5, 0xff, 0xf0, 0x0f,
- 0x87, 0xc2, 0x63, 0xcc, 0x0c, 0xe2, 0xc5, 0xc3, 0x95, 0x8b, 0xf0, 0x19,
- 0xc6, 0xeb, 0x15, 0x26, 0xf9, 0x85, 0xef, 0x9c, 0xdc, 0x08, 0xb1, 0x7c,
- 0xc7, 0xe3, 0x2c, 0x5e, 0x93, 0xca, 0xc5, 0xfe, 0x67, 0xdc, 0x9b, 0x37,
- 0x58, 0xbf, 0x4f, 0xbe, 0xd1, 0x2c, 0x70, 0xd9, 0xd6, 0xc9, 0xe0, 0x8c,
- 0xa3, 0xb1, 0xdd, 0x42, 0x38, 0x87, 0xf8, 0x4b, 0xd0, 0x8a, 0x39, 0x3e,
- 0xfd, 0xa1, 0x6f, 0xf9, 0x58, 0xbf, 0xb5, 0x14, 0x1f, 0xdc, 0x58, 0xa9,
- 0x3d, 0xac, 0x2a, 0xb9, 0x83, 0x58, 0xa2, 0x37, 0x01, 0x90, 0x5b, 0x8b,
- 0x17, 0xa2, 0x70, 0xd6, 0x2e, 0xcd, 0x49, 0xb1, 0x71, 0x2b, 0xfd, 0x13,
- 0x44, 0xdd, 0xc3, 0x8b, 0x17, 0xf3, 0x6c, 0xf1, 0x38, 0x6b, 0x17, 0xfe,
- 0x79, 0x37, 0xab, 0xf9, 0x8c, 0x8f, 0x58, 0xbf, 0xfe, 0xcf, 0xf5, 0x1e,
- 0x45, 0x06, 0xd6, 0xdf, 0x12, 0xc5, 0xcc, 0x19, 0x22, 0x6b, 0xc8, 0xb5,
- 0x29, 0xac, 0xe1, 0x53, 0x1b, 0x94, 0x32, 0xaf, 0xd8, 0x5b, 0x60, 0x6b,
- 0x17, 0xe6, 0x3f, 0xdc, 0x35, 0x8a, 0xd8, 0xf4, 0x86, 0x53, 0x7f, 0xf4,
- 0xfb, 0x09, 0xcd, 0x01, 0xe6, 0x0b, 0x17, 0xfd, 0x3b, 0x19, 0x0f, 0x89,
- 0xb6, 0x58, 0xbf, 0xcd, 0xee, 0x6f, 0xbb, 0xf6, 0xb1, 0x7f, 0xcf, 0xbe,
- 0x44, 0xc5, 0xb0, 0x55, 0x62, 0xb1, 0x31, 0xa7, 0x23, 0xd2, 0x23, 0x1e,
- 0x91, 0xbd, 0xa3, 0x65, 0x8b, 0xf4, 0xeb, 0x59, 0xf5, 0x8b, 0xff, 0xa7,
- 0x0b, 0xf2, 0xe0, 0x6f, 0x09, 0x62, 0xf3, 0x43, 0xcb, 0x17, 0xff, 0xd2,
- 0x68, 0x78, 0xfd, 0x03, 0x61, 0xce, 0x1d, 0x62, 0xfe, 0x26, 0x36, 0x4f,
- 0x2b, 0x14, 0x15, 0x4c, 0x7a, 0x02, 0xfa, 0x28, 0x3a, 0x11, 0x0e, 0x89,
- 0x4e, 0xe3, 0x4d, 0x58, 0xbf, 0x89, 0xb7, 0xc2, 0xdd, 0x62, 0xb6, 0x3c,
- 0x87, 0x1a, 0xbd, 0x1a, 0xa3, 0xc0, 0xb1, 0x7f, 0xff, 0x09, 0xb5, 0x0e,
- 0xbf, 0xc8, 0xa7, 0xd8, 0x79, 0xfa, 0xc5, 0xa3, 0xd6, 0x2f, 0xee, 0x33,
- 0x18, 0xc6, 0x2c, 0x5f, 0x40, 0x43, 0x8c, 0x8d, 0x11, 0x92, 0x32, 0x73,
- 0x57, 0xbc, 0x2b, 0x7f, 0x1d, 0xbb, 0x0a, 0x67, 0xd6, 0x2f, 0x06, 0xdc,
- 0x58, 0xbf, 0x8f, 0x38, 0x5e, 0xe2, 0xc5, 0xfa, 0x76, 0xc8, 0x3a, 0xc5,
- 0xfe, 0x92, 0xc7, 0xd9, 0xb8, 0xb1, 0x78, 0xc1, 0xc6, 0x62, 0x36, 0x3e,
- 0x67, 0xc1, 0xef, 0x16, 0x98, 0x51, 0x7d, 0x39, 0xdc, 0x16, 0x2a, 0x24,
- 0xee, 0x7f, 0x19, 0xb0, 0x18, 0x2f, 0xfb, 0x6d, 0x9f, 0x7e, 0xe1, 0x21,
- 0x16, 0x2f, 0xbf, 0xfc, 0xed, 0x62, 0xfe, 0x61, 0xc9, 0x48, 0x16, 0x2f,
- 0x9f, 0x98, 0x39, 0x3d, 0x08, 0xe2, 0x4b, 0xf3, 0x73, 0xd9, 0xf5, 0x8b,
- 0x7d, 0x62, 0xff, 0xc2, 0x1b, 0x10, 0x3c, 0xfd, 0xf1, 0x62, 0xff, 0xff,
- 0x69, 0xb8, 0x67, 0x8b, 0x3a, 0x30, 0x07, 0xa2, 0x60, 0xd6, 0x2d, 0xe8,
- 0x22, 0x90, 0x48, 0x17, 0xbe, 0xc3, 0x58, 0xbf, 0xe7, 0x93, 0xf5, 0xc1,
- 0xbf, 0x45, 0x8a, 0xc4, 0xce, 0x1e, 0x16, 0xdf, 0x29, 0xe0, 0xed, 0xf7,
- 0x5f, 0x39, 0xd6, 0x2a, 0x57, 0x5b, 0x07, 0x2a, 0x93, 0x0e, 0x37, 0x84,
- 0x83, 0x9d, 0x34, 0x6c, 0x02, 0x41, 0xbe, 0x14, 0x3e, 0xeb, 0x17, 0xff,
- 0xe7, 0xde, 0x4f, 0xc6, 0xd6, 0x1c, 0x5b, 0xb4, 0x16, 0x2f, 0xf9, 0xb4,
- 0xde, 0x7d, 0x30, 0x16, 0x2e, 0x7e, 0x8b, 0x17, 0xfa, 0x49, 0xbe, 0x22,
- 0xd9, 0x62, 0xff, 0xce, 0x6c, 0x8d, 0xc9, 0xb4, 0x6a, 0xc5, 0xff, 0xec,
- 0xef, 0xdd, 0xf9, 0xc3, 0xc1, 0xb4, 0x16, 0x2b, 0x11, 0x18, 0x03, 0xfb,
- 0x7d, 0x62, 0xfe, 0x7d, 0x00, 0xef, 0xc5, 0x8a, 0xd9, 0x3e, 0xc8, 0x11,
- 0xee, 0xaf, 0x1e, 0x70, 0x71, 0x92, 0x85, 0xf8, 0x88, 0xa3, 0x84, 0xaf,
- 0x1f, 0x84, 0xb1, 0x7f, 0xff, 0xf7, 0x7c, 0xc8, 0x3f, 0xbf, 0x84, 0x00,
- 0x4f, 0xcb, 0x06, 0xc7, 0x58, 0xa9, 0x44, 0x73, 0x8e, 0xde, 0x1c, 0x9d,
- 0x62, 0xff, 0xff, 0xe2, 0x6d, 0xbc, 0x26, 0xef, 0xce, 0x19, 0x9e, 0x72,
- 0x14, 0x33, 0x8b, 0x17, 0xf0, 0x32, 0x29, 0xef, 0x8b, 0x17, 0xfd, 0x85,
- 0xbf, 0x5c, 0x1b, 0xf4, 0x58, 0xbf, 0xd8, 0x7e, 0xae, 0x6e, 0x0d, 0x62,
- 0xbe, 0x7e, 0x7e, 0x3d, 0xbf, 0xff, 0xc4, 0xc1, 0xff, 0x0e, 0xc1, 0xfb,
- 0x98, 0x18, 0xdc, 0xeb, 0x17, 0xbf, 0x91, 0x2c, 0x5f, 0xf0, 0xb4, 0xcd,
- 0x0f, 0x67, 0xd6, 0x2f, 0xc0, 0xee, 0x12, 0x11, 0x62, 0xfe, 0xcd, 0x64,
- 0x52, 0x6a, 0xc5, 0x61, 0xed, 0xf8, 0xb2, 0xff, 0xff, 0xee, 0x7e, 0x7f,
- 0x2f, 0xd8, 0x35, 0x83, 0x9f, 0x71, 0xcb, 0xb8, 0x2c, 0x50, 0xd5, 0x71,
- 0xe3, 0xab, 0xc2, 0x8e, 0x22, 0x2f, 0xb1, 0xf0, 0x7b, 0xd0, 0x94, 0x0c,
- 0x86, 0xf0, 0xdc, 0xeb, 0x17, 0xfb, 0xbd, 0xdf, 0x3f, 0xae, 0x2c, 0x5f,
- 0xf1, 0x39, 0xfa, 0xb8, 0x0c, 0x02, 0xc5, 0x6c, 0x7e, 0x44, 0x6d, 0x7f,
- 0x8d, 0x2c, 0xdb, 0x61, 0x12, 0xc5, 0x4a, 0xe3, 0x26, 0x4b, 0x00, 0x77,
- 0xd6, 0x84, 0x78, 0x88, 0xaf, 0x03, 0xc1, 0x75, 0x8b, 0xd0, 0x7d, 0x2c,
- 0x5f, 0xfc, 0x39, 0x3f, 0x09, 0xbf, 0x9a, 0xc5, 0x8b, 0xfb, 0xed, 0x09,
- 0xe4, 0x16, 0x2f, 0xfb, 0x3e, 0xfd, 0xf3, 0xe2, 0xe2, 0xc5, 0x6e, 0x7d,
- 0x20, 0x2e, 0xae, 0xd1, 0xd9, 0xf1, 0xd2, 0x85, 0x65, 0x4a, 0x68, 0x79,
- 0x18, 0x75, 0xff, 0xc0, 0x7f, 0xf1, 0xb7, 0xfc, 0xc7, 0x8d, 0x62, 0xff,
- 0xfc, 0xd1, 0xfd, 0x63, 0x85, 0x3d, 0x73, 0x84, 0x26, 0xd9, 0x62, 0x80,
- 0x8a, 0x91, 0x24, 0xdf, 0x71, 0x9f, 0x65, 0x8b, 0xdc, 0xda, 0x56, 0x2b,
- 0x63, 0xc1, 0xc2, 0x3b, 0x82, 0xb1, 0x2c, 0x5f, 0xff, 0xde, 0xce, 0x9d,
- 0x63, 0x85, 0x3d, 0x73, 0x84, 0x26, 0xd9, 0x62, 0xff, 0xa1, 0x3e, 0xf4,
- 0xb1, 0xf6, 0x58, 0xac, 0x44, 0xff, 0x6c, 0xb7, 0xff, 0xb3, 0xec, 0xc7,
- 0x26, 0xd3, 0xcf, 0x16, 0x2d, 0x87, 0x3e, 0xae, 0x84, 0x77, 0xed, 0x82,
- 0x4f, 0x7c, 0x58, 0xbf, 0xf8, 0x1e, 0xe3, 0x1c, 0xb3, 0xff, 0x75, 0x8b,
- 0xe0, 0x0f, 0x09, 0x62, 0xa4, 0xf9, 0x99, 0x12, 0xb1, 0x54, 0x43, 0xb2,
- 0x1c, 0x8b, 0xf1, 0x93, 0x31, 0x49, 0x42, 0x4e, 0xd1, 0x2c, 0x5e, 0xc2,
- 0x35, 0x62, 0xa4, 0xd8, 0x60, 0x9d, 0xfe, 0xde, 0x61, 0xef, 0xb0, 0xd6,
- 0x2f, 0xcf, 0x1d, 0x9a, 0x35, 0x62, 0xfb, 0xa1, 0x67, 0x16, 0x2f, 0xe2,
- 0x63, 0x4b, 0x00, 0xb1, 0x4e, 0x7a, 0x27, 0x24, 0xbf, 0xfb, 0x21, 0xec,
- 0xf9, 0x67, 0xbe, 0xeb, 0x16, 0x95, 0x8a, 0xf9, 0xea, 0x32, 0x1d, 0xe0,
- 0x18, 0x05, 0x8b, 0x41, 0x62, 0xfa, 0x7d, 0xce, 0xae, 0x6c, 0x7c, 0x3f,
- 0x71, 0xb0, 0x58, 0xbf, 0x7d, 0xfa, 0x3e, 0xeb, 0x17, 0x67, 0xe0, 0x78,
- 0x9b, 0x8c, 0xd6, 0xca, 0x90, 0xf0, 0x7c, 0xe6, 0xac, 0xfb, 0xc7, 0x5f,
- 0x29, 0x47, 0x3e, 0xde, 0x0c, 0x30, 0xd2, 0x2f, 0xfd, 0xa2, 0x13, 0x19,
- 0x91, 0x49, 0xd6, 0x23, 0x0d, 0x0d, 0xe8, 0x9c, 0x35, 0x8b, 0xdf, 0x10,
- 0x16, 0x2d, 0xf7, 0x37, 0xb1, 0x0f, 0xdb, 0x75, 0x8a, 0x94, 0x65, 0x64,
- 0x24, 0x34, 0x4f, 0x7f, 0xa4, 0x79, 0x09, 0x2d, 0xd6, 0x2a, 0x5d, 0x44,
- 0x1e, 0xd1, 0xd5, 0x42, 0x1d, 0xe3, 0x5f, 0xc9, 0xdc, 0xce, 0xe1, 0x30,
- 0xf1, 0xef, 0x47, 0xc6, 0x1f, 0x14, 0x75, 0x7a, 0x8e, 0xac, 0xf1, 0xb2,
- 0xfe, 0x78, 0x3d, 0xa5, 0x31, 0x02, 0x30, 0xc2, 0x9c, 0x85, 0xe4, 0x73,
- 0x1e, 0x96, 0xb2, 0x29, 0x5a, 0x61, 0xc6, 0xa6, 0x61, 0x9d, 0xf3, 0xe9,
- 0x80, 0xb1, 0x7f, 0x87, 0xf9, 0xd8, 0xb3, 0xb5, 0x8b, 0xc3, 0xfc, 0xac,
- 0x51, 0xcf, 0xd0, 0x04, 0x5c, 0x35, 0xbe, 0xd6, 0xb3, 0xeb, 0x17, 0xf7,
- 0xdc, 0x20, 0x41, 0x1a, 0xb1, 0x7f, 0x36, 0x9f, 0x80, 0x75, 0x8a, 0x94,
- 0x42, 0x6e, 0x47, 0xf3, 0x4b, 0x05, 0xd6, 0x2e, 0x2e, 0x2c, 0x59, 0xd6,
- 0x2f, 0xed, 0x73, 0xf2, 0x5e, 0x58, 0xba, 0x40, 0xb1, 0x6f, 0x49, 0xe2,
- 0xf0, 0xba, 0xff, 0xf6, 0xb6, 0x33, 0xcf, 0xf1, 0x1c, 0xed, 0x05, 0x8b,
- 0x05, 0xd6, 0x2f, 0xfb, 0xd3, 0xae, 0x7e, 0x4b, 0xcb, 0x17, 0x72, 0x56,
- 0x2f, 0x1c, 0x72, 0xb1, 0x7f, 0x8b, 0xcd, 0x17, 0x27, 0xcb, 0x14, 0xe7,
- 0xa2, 0xc3, 0xb7, 0xce, 0xd9, 0xba, 0xc5, 0xff, 0xb3, 0xa1, 0x67, 0x22,
- 0x29, 0x1a, 0xc5, 0xf6, 0xe3, 0x9d, 0x96, 0x2e, 0x04, 0xac, 0x5e, 0xe3,
- 0xe9, 0x62, 0xb0, 0xf6, 0x40, 0x4b, 0xe1, 0x7b, 0xfd, 0x0c, 0x27, 0x1e,
- 0x12, 0xc5, 0xdc, 0x8c, 0x94, 0xfc, 0x70, 0x5a, 0x23, 0x9f, 0xb4, 0x00,
- 0x80, 0x88, 0xb9, 0x09, 0x9f, 0x17, 0x53, 0x2a, 0xc3, 0xf4, 0xa3, 0xfb,
- 0xee, 0xc6, 0xdb, 0x2c, 0x5d, 0xc9, 0x58, 0xbc, 0x71, 0xca, 0xc5, 0xfe,
- 0x2f, 0x34, 0x5c, 0x9f, 0x2c, 0x53, 0x9e, 0x8b, 0x0e, 0xdf, 0x3b, 0x66,
- 0xeb, 0x17, 0xfe, 0xce, 0x85, 0x9c, 0x88, 0xa4, 0x6b, 0x17, 0xdb, 0x8e,
- 0x76, 0x58, 0xbf, 0xa2, 0x03, 0xc7, 0xb4, 0x4b, 0x17, 0x9c, 0x1c, 0x58,
- 0xb8, 0x12, 0xb1, 0x7b, 0x8f, 0xa5, 0x8b, 0xb2, 0x25, 0x8a, 0xc4, 0x60,
- 0xee, 0x4b, 0xf3, 0x30, 0x0e, 0xf8, 0x5c, 0xc1, 0xdb, 0xfb, 0x09, 0xc7,
- 0x84, 0xb1, 0x7e, 0xc2, 0x26, 0xf2, 0xc5, 0xfb, 0x6f, 0x66, 0x1d, 0x62,
- 0xa0, 0x7f, 0x5f, 0x2b, 0x62, 0x6b, 0xf8, 0x98, 0x78, 0x6c, 0x64, 0xaf,
- 0x34, 0x40, 0x58, 0x62, 0xf8, 0xad, 0xbc, 0xae, 0xa7, 0x2b, 0x88, 0x97,
- 0xed, 0x00, 0x20, 0x22, 0x2e, 0x46, 0x03, 0xe8, 0x69, 0x5f, 0xfd, 0xa9,
- 0xef, 0x85, 0x27, 0xce, 0xfc, 0xb1, 0x7f, 0xfe, 0x61, 0xe6, 0x11, 0xa6,
- 0x14, 0x96, 0xcf, 0xa5, 0x8b, 0xcd, 0xad, 0x97, 0x20, 0x91, 0x7d, 0x0c,
- 0xee, 0x0b, 0x90, 0x48, 0xbd, 0xc7, 0x1a, 0xe4, 0x12, 0x2e, 0x0c, 0x35,
- 0xc8, 0x24, 0x56, 0xe8, 0xad, 0x88, 0xaf, 0xc6, 0x21, 0x95, 0x5c, 0xde,
- 0x4c, 0x82, 0x42, 0x30, 0xf0, 0x2f, 0xff, 0xfe, 0x19, 0x48, 0xff, 0x3e,
- 0xe4, 0xfa, 0x47, 0x3e, 0xc3, 0x80, 0x35, 0x8b, 0xfb, 0x3f, 0x98, 0x46,
- 0xac, 0x5e, 0x62, 0x07, 0x56, 0x4e, 0xac, 0xcf, 0x4c, 0x6a, 0x1b, 0xa7,
- 0x46, 0x28, 0xd0, 0xb8, 0x73, 0xe7, 0x2b, 0xf7, 0xda, 0x13, 0x05, 0x8b,
- 0xe8, 0xec, 0x6f, 0xac, 0x5f, 0xf3, 0x10, 0x33, 0xa1, 0x0a, 0x0b, 0x15,
- 0x1e, 0x98, 0x97, 0xe1, 0x16, 0x02, 0x8f, 0x12, 0xdf, 0xe8, 0x83, 0x9e,
- 0xc7, 0x3c, 0x58, 0xac, 0x3f, 0xd7, 0x46, 0xb4, 0x16, 0x2e, 0x23, 0x56,
- 0x2f, 0xe8, 0x0b, 0x6f, 0x3e, 0xc9, 0x17, 0xf1, 0x67, 0xb9, 0x27, 0x58,
- 0xbe, 0xd0, 0x1f, 0xcb, 0x17, 0xba, 0x4f, 0x16, 0x2f, 0x98, 0x7f, 0xc5,
- 0x8b, 0xc3, 0x73, 0xac, 0x5f, 0xfb, 0xf3, 0xe7, 0x29, 0x3c, 0xf1, 0x62,
- 0xef, 0xee, 0xb1, 0x68, 0xf5, 0x8a, 0xea, 0x98, 0xcc, 0x96, 0xe1, 0x19,
- 0xa3, 0xec, 0x45, 0xc1, 0xd1, 0x1e, 0x84, 0x19, 0xa7, 0x4f, 0x5a, 0x21,
- 0x8f, 0xc6, 0x95, 0x7f, 0xd2, 0x50, 0x29, 0x03, 0x1d, 0x62, 0xff, 0xa2,
- 0x77, 0x29, 0xd3, 0x71, 0x62, 0xf7, 0xb3, 0xeb, 0x14, 0xb1, 0x76, 0xef,
- 0xf3, 0xe1, 0xe1, 0xc4, 0x70, 0xed, 0xf7, 0xb4, 0x23, 0xac, 0x5c, 0xfb,
- 0x2c, 0x53, 0x9b, 0xcf, 0x12, 0x5f, 0x4f, 0xc5, 0xa5, 0x8b, 0xdf, 0x6f,
- 0x2c, 0x56, 0xc7, 0xc1, 0x11, 0x07, 0x08, 0xee, 0x9f, 0xac, 0x5a, 0x56,
- 0x3c, 0x5b, 0xdf, 0xe7, 0x80, 0x9b, 0x9f, 0x75, 0x8b, 0xb3, 0xa2, 0xc5,
- 0xfb, 0xa3, 0x1f, 0x3e, 0xb1, 0x7f, 0xd9, 0xee, 0xf7, 0x7d, 0x7f, 0x16,
- 0x2b, 0x0f, 0x97, 0xe5, 0x56, 0x82, 0x45, 0xe6, 0xd6, 0xc9, 0x14, 0x91,
- 0x52, 0x6f, 0x37, 0x12, 0x38, 0xf5, 0xe9, 0x06, 0xe9, 0x11, 0x86, 0xba,
- 0xff, 0xef, 0xb4, 0x0b, 0x38, 0x23, 0x4e, 0x1a, 0xc5, 0x76, 0x9c, 0x09,
- 0xdf, 0x8a, 0x11, 0x7e, 0x31, 0xbc, 0x50, 0xfa, 0xc5, 0xee, 0xe1, 0xc5,
- 0x8a, 0x95, 0x46, 0x79, 0x1d, 0xa1, 0xd0, 0xd8, 0x76, 0xfd, 0x85, 0xb3,
- 0xe9, 0x62, 0xd1, 0xcb, 0x16, 0x6d, 0x8d, 0xe9, 0x14, 0x5f, 0xb4, 0x03,
- 0xbf, 0x16, 0x2f, 0xe3, 0x0a, 0x1c, 0xf8, 0xd6, 0x30, 0xd4, 0xdf, 0xde,
- 0xe0, 0x19, 0xb4, 0xb1, 0x7d, 0x3b, 0xbf, 0x16, 0x2f, 0x84, 0xda, 0x82,
- 0xc5, 0x8e, 0xb1, 0x68, 0x0c, 0xda, 0xc4, 0x47, 0x7f, 0xff, 0xf7, 0xbd,
- 0x0c, 0xff, 0xda, 0x11, 0xd9, 0xce, 0x0b, 0x9e, 0xe6, 0x06, 0xb1, 0x76,
- 0x44, 0xb1, 0x7c, 0x00, 0x0b, 0x8c, 0x89, 0x03, 0x1e, 0x2a, 0x53, 0x79,
- 0xd8, 0xbb, 0x16, 0x1a, 0x17, 0x17, 0xff, 0x67, 0x7e, 0xe3, 0x94, 0x81,
- 0x8e, 0xb1, 0x7f, 0x66, 0xa2, 0xfb, 0x81, 0x62, 0xff, 0xfe, 0xcf, 0x7d,
- 0xc3, 0x9d, 0x34, 0x27, 0x9f, 0xc0, 0x2c, 0x54, 0x11, 0x14, 0x45, 0xf7,
- 0x40, 0x6b, 0x17, 0xa1, 0x3d, 0xac, 0x5d, 0x83, 0x58, 0xbe, 0xc8, 0x9c,
- 0xeb, 0x15, 0xb2, 0x6c, 0x06, 0xc3, 0x3b, 0xb2, 0x28, 0x86, 0x3c, 0x3c,
- 0x18, 0xbd, 0xfa, 0x62, 0x84, 0x81, 0x22, 0xe2, 0x02, 0xc5, 0xef, 0x8a,
- 0x3d, 0x62, 0xfe, 0xf3, 0xe9, 0xf6, 0x95, 0x8a, 0xc3, 0xe6, 0xdc, 0x5c,
- 0xc2, 0x1b, 0xff, 0xf7, 0xf1, 0xe1, 0xce, 0xbe, 0xfe, 0x0c, 0x5e, 0xe2,
- 0xc5, 0x6e, 0x98, 0xc6, 0xa1, 0x1f, 0xe3, 0x0b, 0x9e, 0x25, 0x8b, 0xf8,
- 0xbd, 0x16, 0x6b, 0x16, 0x2c, 0x03, 0x9e, 0x33, 0x0c, 0x5a, 0x35, 0xac,
- 0x5f, 0xfb, 0xdf, 0xc1, 0x8b, 0xdc, 0x8a, 0x56, 0x2c, 0xeb, 0x17, 0xfd,
- 0xb0, 0xa0, 0x3f, 0x89, 0x89, 0x62, 0xfe, 0x79, 0x3e, 0xd8, 0x1a, 0xc5,
- 0xfb, 0x36, 0x3e, 0x1d, 0x62, 0xf7, 0x1f, 0x4b, 0x14, 0x47, 0x8d, 0xe2,
- 0x9b, 0xf8, 0x98, 0x00, 0x17, 0x16, 0x2f, 0x49, 0xe3, 0x06, 0x98, 0x86,
- 0x08, 0xe8, 0xef, 0x8e, 0xbe, 0x21, 0xb1, 0xbc, 0x4e, 0xbc, 0xc8, 0xd4,
- 0x6a, 0x35, 0xa7, 0xf2, 0xf1, 0xe3, 0xd6, 0x2e, 0x23, 0x3c, 0x6f, 0x4c,
- 0xfa, 0x52, 0x88, 0x2f, 0xf8, 0x0e, 0x5e, 0xef, 0x8d, 0x1e, 0xb1, 0x7e,
- 0xfe, 0x6d, 0xee, 0x2c, 0x56, 0x8f, 0x9f, 0xe7, 0xb7, 0xff, 0xdc, 0xe6,
- 0x1e, 0x63, 0xf5, 0x8f, 0xf9, 0x1a, 0xc5, 0xe9, 0xef, 0x8b, 0x15, 0x03,
- 0xf0, 0xd2, 0x95, 0xec, 0xd8, 0x4b, 0x15, 0x88, 0xd2, 0x68, 0x49, 0x11,
- 0x15, 0xcc, 0x75, 0x8b, 0xff, 0xa2, 0x26, 0x0f, 0x52, 0xf0, 0x6e, 0x2c,
- 0x51, 0xcf, 0x71, 0x85, 0xef, 0xc5, 0x80, 0x33, 0xb5, 0x8b, 0xff, 0x9e,
- 0x74, 0x0f, 0xe7, 0x1b, 0xb8, 0x2c, 0x5b, 0xdd, 0x4f, 0xbf, 0xe5, 0x57,
- 0xfb, 0x85, 0x91, 0x42, 0x7b, 0x58, 0xac, 0x3d, 0xff, 0x15, 0x54, 0xb7,
- 0xbe, 0x10, 0xa6, 0x0b, 0x8c, 0x83, 0x23, 0xe8, 0x34, 0xdf, 0xb8, 0x4c,
- 0x3c, 0x36, 0xb4, 0x91, 0xf9, 0x4a, 0x6c, 0xfe, 0x04, 0xf2, 0x8e, 0xe3,
- 0x93, 0xbc, 0xfe, 0x8e, 0x08, 0x50, 0x8e, 0x8e, 0x87, 0x7d, 0xff, 0xfb,
- 0x6d, 0x6b, 0x06, 0xc7, 0xfb, 0x78, 0xa6, 0x25, 0x8b, 0xff, 0xff, 0xc2,
- 0xd0, 0xa2, 0x26, 0x07, 0x39, 0x86, 0xe0, 0xb4, 0xc3, 0x9f, 0xca, 0xc5,
- 0xff, 0xef, 0x4f, 0xb9, 0xa9, 0x2f, 0x7f, 0x20, 0xb1, 0x7f, 0xdc, 0x2c,
- 0xff, 0x8a, 0x40, 0xb1, 0x6e, 0x2c, 0x56, 0x22, 0x50, 0xd4, 0xaf, 0x1c,
- 0x5f, 0xce, 0x64, 0xf7, 0x3d, 0xac, 0x5f, 0xff, 0xf4, 0x6a, 0xeb, 0x08,
- 0x4f, 0xbd, 0xd7, 0x85, 0x8f, 0xe7, 0x60, 0x2c, 0x5f, 0xc2, 0x9d, 0x69,
- 0xf6, 0x58, 0xbf, 0xf8, 0x46, 0xe1, 0x7f, 0x06, 0x37, 0xed, 0x62, 0xfe,
- 0x8c, 0x7f, 0x6b, 0x20, 0xb1, 0x5b, 0x9f, 0xbb, 0xa3, 0x5f, 0xdf, 0x7e,
- 0x82, 0x04, 0x16, 0x2f, 0xf7, 0x25, 0xf5, 0xac, 0xd9, 0x62, 0xfe, 0x84,
- 0x83, 0xee, 0x1a, 0xc5, 0xf7, 0x38, 0x2e, 0xd6, 0x2f, 0xc3, 0xfc, 0x90,
- 0x96, 0x2e, 0xfe, 0x2c, 0x54, 0x9f, 0x23, 0x12, 0x88, 0xa2, 0xff, 0x1c,
- 0xb0, 0x6f, 0xfe, 0x2c, 0x5b, 0xeb, 0x17, 0xbd, 0x3b, 0x2c, 0x53, 0x9b,
- 0x0f, 0x09, 0x5f, 0xcd, 0x0f, 0xbb, 0x41, 0x62, 0xa5, 0x16, 0x18, 0xc6,
- 0xe4, 0x17, 0xb1, 0xc0, 0xb1, 0x7f, 0xd1, 0x9f, 0x61, 0x90, 0x9b, 0x65,
- 0x8b, 0xc6, 0xe8, 0x0b, 0x14, 0x69, 0xee, 0x6e, 0x7b, 0x7e, 0x17, 0x42,
- 0x68, 0x2c, 0x5f, 0xfe, 0xfc, 0x64, 0xfb, 0x58, 0x3e, 0xb9, 0xdf, 0x96,
- 0x2e, 0x62, 0x58, 0xac, 0x3e, 0x76, 0x51, 0xbf, 0xa1, 0x31, 0x63, 0x81,
- 0x62, 0xd1, 0x81, 0x62, 0xe5, 0xa8, 0xdc, 0x32, 0x14, 0xc6, 0x91, 0x76,
- 0x63, 0x11, 0xa1, 0xe1, 0x27, 0xf8, 0x6e, 0x85, 0xcb, 0x49, 0xe3, 0x84,
- 0x9e, 0x84, 0x88, 0x42, 0x0b, 0x84, 0x1a, 0xc5, 0xf4, 0xc7, 0x8e, 0x56,
- 0x2f, 0xbd, 0xc7, 0xd2, 0xc5, 0xef, 0x88, 0xc5, 0x8a, 0x93, 0xc2, 0x08,
- 0x47, 0x7f, 0x08, 0xce, 0x3e, 0x12, 0xc5, 0xd9, 0x12, 0xc5, 0xc6, 0x44,
- 0xb1, 0x4e, 0x6c, 0x98, 0x62, 0xd3, 0x11, 0xff, 0xf1, 0x82, 0xf0, 0x61,
- 0x86, 0x91, 0x69, 0x48, 0x8c, 0x34, 0x37, 0x43, 0x65, 0x8a, 0x81, 0xbd,
- 0x39, 0x25, 0xef, 0xc8, 0x16, 0x2f, 0xe8, 0xdb, 0xf2, 0x09, 0x8f, 0x58,
- 0xaf, 0x1e, 0x99, 0x83, 0xb7, 0x44, 0x75, 0x8b, 0xb0, 0x6b, 0x15, 0x26,
- 0xc0, 0x43, 0x37, 0x7f, 0x4b, 0x17, 0x00, 0x0b, 0x17, 0xbf, 0x1b, 0x06,
- 0xb1, 0x7d, 0x16, 0x66, 0xeb, 0x15, 0x2c, 0xa5, 0xed, 0x95, 0xe1, 0x18,
- 0x68, 0xcc, 0x32, 0x73, 0x94, 0xd8, 0x6f, 0x6e, 0x33, 0xdb, 0x3c, 0x50,
- 0xa2, 0xd4, 0x21, 0x99, 0xd3, 0x8a, 0x7e, 0x20, 0x10, 0xc7, 0x41, 0x80,
- 0xc9, 0x2f, 0x6e, 0xf2, 0xb1, 0x7b, 0x33, 0x4b, 0x15, 0x03, 0x72, 0x31,
- 0xdb, 0xff, 0xde, 0x8b, 0x35, 0xa6, 0x8b, 0x35, 0x9e, 0x58, 0xac, 0x3e,
- 0xd7, 0x21, 0xbf, 0xe8, 0x3f, 0xa1, 0x3a, 0x9d, 0xd6, 0x2d, 0x1e, 0xb1,
- 0x71, 0x43, 0xa9, 0xe7, 0xc0, 0xea, 0xfd, 0x3a, 0xd6, 0x7d, 0x62, 0xb0,
- 0xf5, 0xcd, 0x2f, 0xbf, 0xb6, 0x8a, 0x11, 0xb6, 0xb6, 0x58, 0xbf, 0xfc,
- 0x03, 0xb4, 0x3a, 0xc8, 0xf6, 0x3c, 0xe9, 0x62, 0xf9, 0xe4, 0xbc, 0xb1,
- 0x7b, 0x66, 0x25, 0x8b, 0xb5, 0xb2, 0xc5, 0xb1, 0x62, 0xb4, 0x8b, 0x6f,
- 0xa7, 0x78, 0x84, 0x43, 0xa1, 0x8c, 0xdf, 0xf8, 0xd1, 0x72, 0x0f, 0xad,
- 0x84, 0x05, 0x8b, 0x8b, 0x16, 0x2f, 0x19, 0xd9, 0x2c, 0x5f, 0x9c, 0x07,
- 0x68, 0x2c, 0x5f, 0x67, 0x60, 0xe2, 0xc5, 0x68, 0xf3, 0x08, 0xa2, 0xee,
- 0xc3, 0x58, 0xbe, 0xc8, 0xf9, 0x3a, 0xc5, 0x61, 0xf0, 0x31, 0x0f, 0x06,
- 0xaf, 0xfd, 0xe9, 0x3f, 0x52, 0xc0, 0x19, 0xda, 0xc5, 0xfe, 0xe3, 0x7f,
- 0x79, 0x71, 0xac, 0x51, 0xa9, 0xe4, 0x3a, 0x19, 0xc5, 0xbf, 0x0c, 0xb2,
- 0x2d, 0xf2, 0x1d, 0xe7, 0x3c, 0xac, 0x5e, 0x9d, 0xe0, 0xb1, 0x79, 0xe4,
- 0xeb, 0x17, 0x30, 0xd6, 0x2b, 0x46, 0xcf, 0xc3, 0x97, 0x9b, 0x37, 0x58,
- 0xbf, 0x6d, 0xfc, 0x03, 0x2c, 0x56, 0xc7, 0xce, 0x69, 0x0e, 0x87, 0x6f,
- 0xbe, 0x3c, 0x25, 0x8b, 0xff, 0xc6, 0x78, 0xa4, 0x0d, 0xe0, 0x18, 0x50,
- 0x58, 0xbb, 0xa0, 0xd6, 0x2a, 0x4f, 0x99, 0x93, 0x2f, 0xfd, 0xd2, 0x4b,
- 0xdc, 0x7e, 0x98, 0x35, 0x8b, 0xff, 0xcf, 0xae, 0xbc, 0xe6, 0x16, 0xec,
- 0x40, 0x58, 0xa9, 0x44, 0x77, 0xd0, 0xa9, 0x62, 0xe7, 0xd2, 0xc5, 0x46,
- 0xb3, 0x47, 0xf0, 0xca, 0x8d, 0xd7, 0x81, 0x32, 0x1d, 0xcf, 0x28, 0x4f,
- 0x4b, 0x9f, 0x1c, 0x68, 0x5c, 0x70, 0xc7, 0xd0, 0x88, 0x14, 0x2b, 0xba,
- 0x22, 0xdf, 0xff, 0xbd, 0x24, 0xe0, 0xce, 0xfd, 0xa7, 0x0e, 0x27, 0x58,
- 0xbf, 0x36, 0x1e, 0x77, 0x58, 0xbc, 0x4c, 0x05, 0x8b, 0xc3, 0xfb, 0xac,
- 0x56, 0x22, 0xe0, 0xd5, 0x7f, 0x94, 0x18, 0x39, 0x7f, 0xe6, 0xf7, 0x03,
- 0xcf, 0x81, 0xbc, 0xb1, 0x7e, 0x06, 0x0d, 0xa0, 0xb1, 0x7d, 0xd0, 0x4c,
- 0x4b, 0x17, 0xda, 0x3c, 0xf1, 0x62, 0xff, 0xfb, 0x30, 0xa6, 0x1e, 0xfb,
- 0x1c, 0xb3, 0xa2, 0xc5, 0xf6, 0x7a, 0x77, 0xea, 0x7e, 0x44, 0x47, 0x5b,
- 0x26, 0xec, 0x33, 0xed, 0x20, 0x11, 0x40, 0x70, 0x96, 0xbc, 0x60, 0xe2,
- 0x58, 0xbf, 0xf7, 0x47, 0x20, 0x63, 0xc4, 0xdd, 0xac, 0x5c, 0xe4, 0xb1,
- 0x7f, 0xfd, 0x9b, 0xcf, 0x5f, 0xce, 0x01, 0x88, 0x58, 0xb1, 0x52, 0x8a,
- 0x78, 0x20, 0xfc, 0x5a, 0xfd, 0xa1, 0x8a, 0x40, 0xb1, 0x7f, 0xf3, 0x9c,
- 0x98, 0xde, 0x7e, 0x4b, 0xcb, 0x17, 0xf9, 0xb4, 0xd9, 0x13, 0x9d, 0x62,
- 0xfd, 0xc6, 0xfb, 0xf1, 0x62, 0xe3, 0x20, 0xb1, 0x7f, 0x06, 0x58, 0x01,
- 0x71, 0x62, 0xff, 0xd8, 0x4d, 0xfc, 0x73, 0xc8, 0xd6, 0x2a, 0x4f, 0xad,
- 0xcb, 0xee, 0x9d, 0x2c, 0x51, 0xa8, 0xbb, 0xd4, 0x21, 0x03, 0x20, 0xbf,
- 0xff, 0xfd, 0x0e, 0x7d, 0x9f, 0xc2, 0xd3, 0x73, 0x0a, 0x60, 0x3d, 0x3f,
- 0x70, 0x58, 0xbc, 0x60, 0x40, 0xd6, 0x2f, 0xff, 0x81, 0x83, 0xf7, 0x1f,
- 0xdf, 0xce, 0x83, 0x95, 0x8b, 0x9f, 0xb5, 0x8a, 0xd9, 0x11, 0x9a, 0x22,
- 0xf2, 0x95, 0xfc, 0xcf, 0xe8, 0x9c, 0x35, 0x8b, 0xf8, 0x7f, 0x90, 0xdb,
- 0xcb, 0x17, 0xfe, 0xc2, 0x37, 0x35, 0xef, 0x3e, 0x96, 0x2f, 0x7d, 0x8d,
- 0x58, 0xbd, 0xb3, 0xea, 0x51, 0x19, 0x85, 0xfe, 0x3f, 0xaf, 0xa3, 0xec,
- 0xa1, 0x77, 0x7f, 0x18, 0x7e, 0xb9, 0xdf, 0x96, 0x2f, 0xff, 0xe6, 0xd6,
- 0x1d, 0xbb, 0xd4, 0xf9, 0xc1, 0xc6, 0xed, 0x62, 0xde, 0xe2, 0x23, 0xfc,
- 0x67, 0x7f, 0x84, 0x6f, 0x59, 0xeb, 0xc7, 0x58, 0xa9, 0x4c, 0x63, 0x21,
- 0x6c, 0x45, 0x37, 0xfe, 0x06, 0x69, 0xc1, 0x80, 0xd1, 0xd6, 0x2f, 0xff,
- 0x1b, 0x3c, 0xd4, 0xfc, 0xb3, 0xd2, 0x75, 0x8b, 0xdd, 0x48, 0x2e, 0xb1,
- 0x7f, 0xf4, 0x88, 0x2f, 0x07, 0x34, 0xd9, 0x2f, 0x2c, 0x5f, 0xc7, 0x68,
- 0x70, 0x4e, 0xb1, 0x4b, 0x16, 0x11, 0xcd, 0xd1, 0x85, 0xd7, 0xff, 0x67,
- 0xbe, 0xf0, 0x7d, 0x6c, 0x20, 0x2c, 0x5f, 0xe8, 0x67, 0x0c, 0xd8, 0x44,
- 0xb1, 0x5b, 0x9f, 0xe0, 0x91, 0xaf, 0xf1, 0x67, 0x47, 0x89, 0xc3, 0x58,
- 0xa8, 0x27, 0x49, 0xa2, 0x3f, 0xc2, 0x10, 0xa1, 0x49, 0xc2, 0x3b, 0xff,
- 0xf8, 0x4d, 0xb6, 0xe2, 0xdb, 0xd9, 0xf2, 0xcf, 0x7d, 0xd6, 0x2f, 0xd3,
- 0x11, 0x0b, 0x8b, 0x15, 0x8a, 0xb2, 0x5e, 0x3e, 0xef, 0xaa, 0x79, 0x7a,
- 0xe7, 0x25, 0x8b, 0xbc, 0x6a, 0xc5, 0xf6, 0x9e, 0x2e, 0x2c, 0x5e, 0x62,
- 0x06, 0x1b, 0xdd, 0x0c, 0xd4, 0xb2, 0x92, 0xb6, 0x51, 0x84, 0x31, 0xf0,
- 0xbc, 0xd2, 0x9d, 0xd1, 0x22, 0x33, 0xd4, 0x38, 0xfe, 0x6e, 0xd1, 0x82,
- 0x14, 0xa4, 0x4e, 0x19, 0xfa, 0x58, 0x47, 0x44, 0x38, 0xe5, 0x3b, 0xe2,
- 0xf4, 0xc7, 0x2c, 0x5e, 0x9e, 0x92, 0xb1, 0x7a, 0x4b, 0xcb, 0x17, 0xd3,
- 0xa6, 0xfa, 0xc5, 0x0c, 0xdf, 0x74, 0x1c, 0xbb, 0x22, 0x58, 0xbf, 0xd9,
- 0xb9, 0x67, 0x47, 0x1a, 0xc5, 0xf7, 0xc4, 0x79, 0x58, 0xa5, 0x8a, 0x58,
- 0xb3, 0x1c, 0xb8, 0xe0, 0x65, 0xc2, 0x0b, 0xac, 0x5f, 0x7f, 0x00, 0xcb,
- 0x17, 0xde, 0x7f, 0x89, 0x62, 0xfe, 0xcd, 0x77, 0x0f, 0x4a, 0xc5, 0xd3,
- 0x1e, 0x16, 0xa7, 0xa4, 0x61, 0x1d, 0x46, 0xea, 0x86, 0x64, 0x95, 0xd7,
- 0x22, 0x23, 0xf8, 0xc3, 0x1a, 0x91, 0xd8, 0x89, 0x7a, 0x0e, 0x04, 0x74,
- 0xb4, 0x64, 0x6f, 0x19, 0xc0, 0xd8, 0x56, 0x51, 0x9c, 0x69, 0x19, 0xfc,
- 0x6d, 0x0b, 0xc0, 0xb6, 0x56, 0x16, 0x42, 0x0c, 0x2d, 0x65, 0x3d, 0x46,
- 0xa8, 0x5d, 0x46, 0xb3, 0xb9, 0xa7, 0xb5, 0x6d, 0x48, 0x22, 0x84, 0xea,
- 0xa0, 0xe9, 0xec, 0x19, 0x68, 0x33, 0x4d, 0x97, 0x95, 0xbd, 0x25, 0x47,
- 0xb9, 0xe0, 0x17, 0x9e, 0x80, 0x8f, 0x8f, 0xca, 0x2a, 0x4a, 0x5e, 0xa9,
- 0x4a, 0x67, 0xa4, 0xae, 0x7e, 0xbc, 0xa8, 0x6a, 0x44, 0xe0, 0x27, 0x86,
- 0x82, 0xf1, 0xa6, 0x95, 0x3c, 0x97, 0x96, 0xa6, 0xd7, 0xd5, 0xff, 0x38,
- 0xa9, 0x6f, 0x5d, 0x23, 0xa5, 0x0e, 0x18, 0xd1, 0xd3, 0xc4, 0xc6, 0x53,
- 0x49, 0x42, 0x4b, 0x0c, 0xbf, 0x46, 0xaf, 0x13, 0x01, 0x62, 0xfe, 0x8d,
- 0xa3, 0x6f, 0x13, 0x01, 0x62, 0xf9, 0xfa, 0x34, 0x7a, 0xc5, 0xf7, 0x27,
- 0x40, 0x58, 0xbf, 0x6c, 0x79, 0xee, 0x32, 0x37, 0x45, 0x84, 0x68, 0x5d,
- 0x03, 0x8e, 0x13, 0xd3, 0x2e, 0x1c, 0x8a, 0x5e, 0x85, 0xf3, 0x90, 0x1d,
- 0x62, 0xf3, 0x1f, 0x8b, 0x15, 0x03, 0x7d, 0xd0, 0x86, 0xfc, 0x7c, 0x76,
- 0x02, 0xc5, 0xf6, 0xec, 0xdb, 0xaa, 0x28, 0xa2, 0xff, 0xfc, 0xc0, 0x9d,
- 0xfe, 0xfc, 0xfb, 0xfb, 0xf8, 0x4b, 0x15, 0xa4, 0x43, 0x11, 0x8d, 0xff,
- 0xa7, 0xce, 0x09, 0x87, 0xb8, 0x14, 0x58, 0xbf, 0x6f, 0x25, 0x20, 0x58,
- 0xbe, 0xf1, 0xaf, 0xba, 0xc5, 0x31, 0xe6, 0xf0, 0xa2, 0xfe, 0xc0, 0x19,
- 0xa6, 0x02, 0xc5, 0xe6, 0x84, 0x64, 0xa7, 0x5f, 0x90, 0xad, 0xd1, 0x17,
- 0xe1, 0x21, 0xe2, 0x1b, 0xff, 0xa5, 0xb4, 0x42, 0x6e, 0xf3, 0xec, 0xb1,
- 0x7f, 0xfe, 0x6f, 0x31, 0xc7, 0xfc, 0x87, 0x3f, 0x25, 0xe5, 0x8b, 0xff,
- 0xe7, 0x88, 0xa7, 0xdc, 0xf7, 0x7b, 0xb9, 0x6c, 0xb1, 0x7f, 0xfd, 0x9f,
- 0xf3, 0x86, 0xf9, 0x07, 0xd3, 0x01, 0x62, 0x86, 0x8a, 0x2e, 0x29, 0xda,
- 0x33, 0x15, 0xcb, 0x1e, 0x3d, 0x2f, 0xb3, 0x92, 0x1f, 0x21, 0xef, 0x7f,
- 0xa3, 0x33, 0x5b, 0xb3, 0x6e, 0xa8, 0xba, 0x0b, 0xff, 0xa3, 0x1a, 0x11,
- 0x99, 0xad, 0xd9, 0xb7, 0x54, 0x49, 0x65, 0xfd, 0x20, 0xc3, 0xce, 0xeb,
- 0x17, 0xed, 0x6e, 0xcd, 0xba, 0xa2, 0xf2, 0x2f, 0xd9, 0xef, 0x39, 0x21,
- 0x08, 0xee, 0x6e, 0x8b, 0x16, 0x8c, 0x1a, 0x2b, 0xb0, 0xb8, 0x8d, 0xe3,
- 0x8c, 0x2a, 0x63, 0x5e, 0xf6, 0xda, 0x58, 0x8c, 0x21, 0x39, 0x90, 0xa5,
- 0xde, 0x38, 0x28, 0xa3, 0x06, 0x3b, 0xff, 0xeb, 0x39, 0x36, 0x8c, 0x0c,
- 0xb3, 0x3d, 0x16, 0xe4, 0xe0, 0x07, 0x97, 0x84, 0x8b, 0xd2, 0x30, 0x7b,
- 0xff, 0xd1, 0x87, 0x68, 0x46, 0x66, 0xb7, 0x66, 0xdd, 0x51, 0x2c, 0x97,
- 0xd1, 0xb9, 0xb1, 0xd1, 0xba, 0xc5, 0xa3, 0x65, 0x8b, 0x04, 0x58, 0xb7,
- 0xd6, 0x2a, 0x37, 0x37, 0xb1, 0xa0, 0xb8, 0x85, 0x2f, 0xf3, 0x8f, 0xf8,
- 0xe4, 0x6a, 0xc5, 0xef, 0xb1, 0xab, 0x17, 0xdf, 0x6f, 0x09, 0x62, 0xfb,
- 0xf3, 0x1e, 0x75, 0x8b, 0xc0, 0x73, 0xac, 0x5f, 0xfb, 0x3e, 0xf0, 0x2c,
- 0xc1, 0x05, 0xd6, 0x2f, 0xbb, 0x6d, 0x62, 0xc5, 0xff, 0xb1, 0xfa, 0x39,
- 0x0a, 0x19, 0xc5, 0x8b, 0xfc, 0x3e, 0xb3, 0xed, 0x60, 0xd6, 0x2e, 0x32,
- 0x39, 0x62, 0xa4, 0xf4, 0xbe, 0x6d, 0x78, 0x5b, 0xb2, 0xc5, 0x41, 0x3e,
- 0xbd, 0xcc, 0xdc, 0x7a, 0x3c, 0x8f, 0x44, 0xc7, 0x1d, 0xfa, 0x09, 0x11,
- 0xfa, 0x12, 0x26, 0x10, 0xdf, 0xbc, 0x26, 0x87, 0x16, 0x2f, 0xb0, 0x36,
- 0x02, 0xc5, 0x0c, 0xf3, 0x08, 0xa6, 0xff, 0x81, 0xd5, 0xfd, 0xc9, 0xd0,
- 0x16, 0x2f, 0xdc, 0x63, 0x7e, 0xeb, 0x17, 0x4e, 0xcb, 0x17, 0xfe, 0x62,
- 0xf6, 0x10, 0xa1, 0x9c, 0x58, 0xbf, 0xf6, 0x1f, 0x8d, 0x03, 0x39, 0x38,
- 0xb1, 0x51, 0xe8, 0x94, 0xf8, 0xc7, 0x8f, 0x6f, 0x3e, 0xde, 0x58, 0xbf,
- 0xff, 0xff, 0xff, 0xc2, 0xea, 0x59, 0x13, 0xf0, 0x47, 0xea, 0x46, 0xf5,
- 0xdf, 0xef, 0xf7, 0x92, 0xf6, 0xa7, 0xdf, 0xc3, 0xf5, 0xeb, 0xf8, 0xe5,
- 0x8a, 0x95, 0x42, 0xd8, 0x78, 0xf0, 0xbd, 0xf1, 0x98, 0x63, 0xd7, 0xbe,
- 0x1b, 0x2c, 0x5f, 0xc7, 0x92, 0x37, 0x36, 0x58, 0xb9, 0x8e, 0xb1, 0x7f,
- 0xe6, 0xd4, 0x27, 0xdf, 0x91, 0x05, 0xd6, 0x2a, 0x34, 0x45, 0x3e, 0x0f,
- 0x78, 0xbc, 0x42, 0xf7, 0xe1, 0x79, 0xff, 0x2b, 0x17, 0xfe, 0xfc, 0xfd,
- 0xcd, 0xf7, 0x18, 0x0b, 0x17, 0xfc, 0xd0, 0xe0, 0xbd, 0x3e, 0xe2, 0xc5,
- 0xfc, 0x5e, 0xd4, 0xb6, 0xeb, 0x16, 0xe8, 0xb1, 0x7e, 0xc3, 0xf9, 0xf6,
- 0x58, 0xba, 0x78, 0xe6, 0xf7, 0x82, 0x97, 0x37, 0x16, 0x2f, 0xff, 0xcc,
- 0xd0, 0x6f, 0xf5, 0xcd, 0x85, 0xe7, 0xfc, 0xac, 0x56, 0xc7, 0xdd, 0x10,
- 0xbd, 0xc2, 0xd2, 0xc5, 0xfa, 0x1c, 0x68, 0xec, 0x58, 0xbc, 0xcd, 0xba,
- 0xa2, 0x33, 0x2f, 0xf4, 0xf7, 0x09, 0xd1, 0xe0, 0xb1, 0x7f, 0xff, 0xdc,
- 0xf7, 0x9f, 0xfd, 0xc3, 0x84, 0x2c, 0x34, 0xd7, 0x68, 0x2c, 0x5b, 0x00,
- 0x89, 0xff, 0x1a, 0xdf, 0xff, 0xf4, 0x33, 0xab, 0x78, 0x53, 0xd4, 0x65,
- 0x3a, 0xd3, 0xe1, 0xd6, 0x2a, 0x53, 0x85, 0xdc, 0xaf, 0x50, 0xc9, 0x62,
- 0x8b, 0xf9, 0xe4, 0xfb, 0x60, 0x6b, 0x17, 0x14, 0x16, 0x2c, 0x75, 0x8b,
- 0xf3, 0xeb, 0xed, 0x19, 0xa3, 0xd8, 0x39, 0x79, 0x82, 0xf6, 0xfa, 0xc5,
- 0xd3, 0xa5, 0x8b, 0x3e, 0xe6, 0xa7, 0xa0, 0x95, 0xff, 0xfc, 0x3c, 0xde,
- 0x7f, 0x27, 0xea, 0x42, 0x6f, 0x4e, 0x96, 0x2e, 0xe0, 0x96, 0x2a, 0x07,
- 0xeb, 0xda, 0xed, 0xfe, 0xec, 0x1c, 0x7f, 0x14, 0xac, 0x5f, 0x3e, 0x9b,
- 0x4b, 0x17, 0x72, 0x3d, 0x62, 0xa0, 0x6f, 0x7c, 0x45, 0x7f, 0xff, 0x43,
- 0x39, 0xe1, 0x6d, 0xbf, 0xde, 0x2f, 0xce, 0xd8, 0xb1, 0x52, 0x98, 0xae,
- 0x11, 0xb3, 0x88, 0x88, 0x6f, 0xfe, 0xe3, 0x8b, 0x98, 0x42, 0x86, 0x71,
- 0x62, 0xff, 0xff, 0xf8, 0x85, 0x0c, 0xe6, 0x78, 0x4d, 0xef, 0xe6, 0xff,
- 0x78, 0xbf, 0x3b, 0x62, 0xc5, 0xd3, 0xda, 0xc5, 0xe7, 0x2d, 0xd6, 0x29,
- 0xd1, 0x69, 0xc7, 0xff, 0x0c, 0x5f, 0xfd, 0xee, 0x3f, 0x8a, 0x44, 0xda,
- 0x35, 0x62, 0xe7, 0x3a, 0xc5, 0x82, 0xee, 0x7b, 0x81, 0x11, 0x6f, 0xe9,
- 0xec, 0x36, 0xff, 0x16, 0x2b, 0x66, 0x42, 0x3c, 0x0a, 0x06, 0x81, 0x87,
- 0x5b, 0xb5, 0xbc, 0x26, 0x62, 0x24, 0xd4, 0x73, 0xa7, 0x84, 0xd7, 0xde,
- 0x0a, 0x3b, 0x3e, 0x1d, 0xfa, 0x1f, 0x02, 0x84, 0x58, 0x42, 0xdb, 0xfc,
- 0xc1, 0xfd, 0xe7, 0x52, 0xb1, 0x7f, 0xff, 0xfe, 0x61, 0xf3, 0xf8, 0x72,
- 0x7d, 0xba, 0x9c, 0x44, 0xc6, 0xfc, 0xb3, 0xda, 0xc5, 0x8a, 0xd2, 0x2e,
- 0x08, 0xce, 0xff, 0xff, 0x7d, 0xfd, 0xe7, 0xe1, 0x9b, 0x4e, 0xc5, 0x80,
- 0x17, 0x16, 0x2f, 0xde, 0x73, 0xcc, 0x4b, 0x17, 0xff, 0xff, 0xf8, 0x84,
- 0x13, 0xae, 0xff, 0x17, 0xa4, 0xb3, 0x6e, 0x6f, 0xf1, 0x17, 0x79, 0x3f,
- 0x2c, 0x58, 0xbf, 0xb2, 0x7a, 0xcf, 0x0e, 0xb1, 0x58, 0x8e, 0xd7, 0x29,
- 0xe4, 0x25, 0x6c, 0x4b, 0x17, 0xf3, 0x07, 0xe2, 0x63, 0x56, 0x2b, 0x0f,
- 0x00, 0x84, 0x6a, 0x08, 0x93, 0xf3, 0x9d, 0xf6, 0xb4, 0xdc, 0x58, 0xbf,
- 0x7f, 0x09, 0x8e, 0xb1, 0x7d, 0xdf, 0xe7, 0x8b, 0x17, 0xa2, 0x62, 0x58,
- 0xbf, 0xf8, 0x78, 0xe4, 0x6e, 0x7e, 0x5c, 0x6b, 0x17, 0xdb, 0xc9, 0x79,
- 0x62, 0xfb, 0x6f, 0xc9, 0xab, 0x17, 0xa7, 0xdc, 0x58, 0xbf, 0xf6, 0x1b,
- 0xc9, 0xc2, 0x1f, 0xe5, 0x62, 0xb8, 0x7b, 0x62, 0x1d, 0xbe, 0x90, 0x37,
- 0x96, 0x2b, 0xaa, 0x76, 0xb0, 0x23, 0xc2, 0x78, 0x89, 0x34, 0x3a, 0x74,
- 0x36, 0x23, 0xe4, 0x20, 0x23, 0x88, 0xaf, 0xc1, 0x09, 0x83, 0x1a, 0xc5,
- 0xfd, 0xad, 0xb5, 0x83, 0xc5, 0x8b, 0xf9, 0x8b, 0x6d, 0x60, 0xd6, 0x2a,
- 0x4f, 0x74, 0x45, 0xf7, 0xff, 0x79, 0xf4, 0xc0, 0xeb, 0xdc, 0x24, 0xeb,
- 0x17, 0xff, 0x49, 0xcd, 0x6d, 0x60, 0x38, 0xdb, 0xac, 0x5f, 0x8a, 0x61,
- 0xc6, 0x58, 0xa9, 0x4d, 0x7a, 0x10, 0x88, 0x72, 0x12, 0x48, 0xe8, 0x8d,
- 0x7e, 0xfb, 0x94, 0xfd, 0x62, 0xff, 0x7e, 0x4e, 0x13, 0x1a, 0x25, 0x8a,
- 0x19, 0xee, 0xee, 0x4f, 0x71, 0x1a, 0xb1, 0x6f, 0xac, 0x5f, 0xfd, 0xf9,
- 0x1f, 0x52, 0xce, 0x72, 0x77, 0x58, 0xbf, 0xff, 0xfb, 0xce, 0x7d, 0x3e,
- 0x76, 0x42, 0xf4, 0xff, 0xaf, 0x47, 0xf4, 0x52, 0xb1, 0x58, 0x8d, 0x07,
- 0x12, 0xf2, 0x3d, 0xfe, 0x3f, 0xdb, 0xcc, 0x40, 0x58, 0xbf, 0xed, 0xfa,
- 0xee, 0xfc, 0x11, 0x6e, 0xb1, 0x7f, 0xff, 0xff, 0xfb, 0x85, 0x80, 0x04,
- 0x97, 0x5d, 0xfe, 0x2f, 0x49, 0x66, 0xdc, 0xdf, 0xe2, 0x2e, 0xf2, 0x7e,
- 0x58, 0xb1, 0x52, 0x98, 0xd6, 0x19, 0x86, 0x7f, 0x78, 0xc9, 0x02, 0xc5,
- 0xfc, 0x58, 0x3f, 0xc8, 0x6b, 0x16, 0x62, 0x3c, 0xce, 0x83, 0xd7, 0x64,
- 0x16, 0x2f, 0xc0, 0x19, 0x67, 0xd6, 0x2a, 0x55, 0x9b, 0x0c, 0x8f, 0x21,
- 0xd0, 0xf1, 0xa4, 0x69, 0xf0, 0xe5, 0x0c, 0x2f, 0x7f, 0x79, 0xbf, 0xd4,
- 0x72, 0xb1, 0x7b, 0xce, 0x4b, 0x17, 0xee, 0x3f, 0xb4, 0xeb, 0x17, 0xf4,
- 0x39, 0xc6, 0x28, 0x2c, 0x5e, 0xdb, 0x9c, 0x58, 0xb8, 0x31, 0xac, 0x5f,
- 0x7d, 0x84, 0x75, 0x8b, 0xff, 0xb0, 0x27, 0x82, 0x14, 0xf8, 0x53, 0xda,
- 0xc5, 0xc2, 0xd2, 0xc5, 0xbd, 0xf3, 0xe1, 0xe2, 0x4d, 0x3a, 0x2b, 0x0a,
- 0x10, 0x95, 0x29, 0xd6, 0x76, 0x60, 0xe3, 0x8c, 0x50, 0x45, 0xde, 0x1f,
- 0x14, 0x31, 0x6e, 0x61, 0xac, 0x5f, 0xa0, 0xc4, 0x2d, 0xd6, 0x2b, 0x73,
- 0xc0, 0xec, 0x5e, 0xe6, 0xdd, 0x62, 0xe9, 0x8f, 0x58, 0xbf, 0x8a, 0x77,
- 0xdb, 0x03, 0x58, 0xad, 0x8f, 0x88, 0x2e, 0x31, 0xe1, 0xab, 0xff, 0x79,
- 0x88, 0x1d, 0x4c, 0xce, 0xc3, 0x58, 0xbe, 0xf7, 0xa4, 0xeb, 0x17, 0xd0,
- 0xf3, 0xec, 0xb1, 0x7f, 0xfe, 0x92, 0x9e, 0x75, 0x7f, 0xef, 0x24, 0x59,
- 0xe5, 0x8a, 0xc4, 0x70, 0x1a, 0x88, 0xc4, 0x7c, 0x24, 0xbf, 0xfe, 0x93,
- 0x8a, 0x76, 0xeb, 0xac, 0x7f, 0xc8, 0xd6, 0x2f, 0x98, 0x8c, 0xe2, 0xc5,
- 0xe2, 0xcd, 0xd6, 0x2f, 0xf9, 0xfc, 0xe7, 0x8b, 0x8e, 0x4b, 0x17, 0xff,
- 0xf6, 0xb3, 0xdc, 0xfb, 0x40, 0x53, 0x9e, 0x9e, 0xe0, 0xb1, 0x5b, 0xa2,
- 0x57, 0x47, 0x37, 0xfe, 0x97, 0xd7, 0xbd, 0x93, 0xa0, 0x2c, 0x5b, 0xd2,
- 0x7c, 0x51, 0x12, 0x5f, 0xb7, 0x7d, 0x1e, 0x0b, 0x17, 0xf8, 0xf9, 0xa0,
- 0x10, 0x80, 0xb1, 0x68, 0x2c, 0x54, 0x13, 0xcf, 0xc2, 0x37, 0x8c, 0x53,
- 0xe5, 0x0c, 0x54, 0x61, 0xa5, 0xf8, 0x13, 0xe9, 0x1a, 0xc5, 0x4a, 0xe3,
- 0xde, 0x42, 0x19, 0xe3, 0x14, 0xf9, 0xe3, 0x4a, 0x21, 0x12, 0xe5, 0xfe,
- 0xf1, 0x37, 0x5d, 0xf7, 0xc5, 0x8b, 0xe7, 0xdd, 0xb4, 0xb1, 0x7f, 0xfc,
- 0x2f, 0x73, 0xb8, 0x49, 0x03, 0x9d, 0x44, 0x4b, 0x17, 0xa7, 0xd2, 0xb1,
- 0x50, 0x44, 0x98, 0xc8, 0xfa, 0x2a, 0x5f, 0xd3, 0xf1, 0x77, 0x0e, 0x2c,
- 0x5e, 0x71, 0x05, 0xd6, 0x2f, 0xf4, 0xe9, 0x88, 0xb0, 0xd5, 0x8a, 0x23,
- 0xd3, 0xf1, 0x0d, 0xe1, 0x78, 0x4b, 0x14, 0xe6, 0xfc, 0xe4, 0x37, 0xff,
- 0xf0, 0xa0, 0xfc, 0x93, 0xef, 0xf7, 0x8b, 0xf3, 0xb6, 0x2c, 0x5e, 0xfe,
- 0x12, 0xc5, 0x76, 0xa9, 0x61, 0xe1, 0x95, 0x11, 0x97, 0xe1, 0x84, 0x44,
- 0x02, 0x5e, 0xbb, 0xf1, 0x2c, 0x5f, 0x64, 0x59, 0x12, 0xc5, 0xfb, 0x42,
- 0xf6, 0x6c, 0xb1, 0x7d, 0x9a, 0x1c, 0xac, 0x5b, 0x9d, 0x4f, 0xc2, 0x49,
- 0x08, 0xaa, 0xdf, 0x58, 0xae, 0xcf, 0x1d, 0x8d, 0x6f, 0x88, 0x4c, 0x62,
- 0xc5, 0xd8, 0x4b, 0x16, 0x9d, 0x8d, 0xcc, 0x08, 0xef, 0xdd, 0xbe, 0xee,
- 0x35, 0x8a, 0x74, 0xdf, 0x1a, 0x1a, 0x00, 0x5b, 0x30, 0x9e, 0xf6, 0x66,
- 0xeb, 0x17, 0xfd, 0xee, 0x66, 0x80, 0x42, 0x02, 0xc5, 0xff, 0xd3, 0xee,
- 0x7e, 0x5f, 0xdc, 0x9d, 0x96, 0x2f, 0xd9, 0xa9, 0x8b, 0x8b, 0x15, 0xa3,
- 0xee, 0xfa, 0x2d, 0xff, 0xfc, 0xfc, 0x2c, 0xda, 0x77, 0xfb, 0xc5, 0xf9,
- 0xdb, 0x16, 0x2f, 0x37, 0xe5, 0x62, 0xa0, 0x7f, 0x3e, 0x5d, 0xbe, 0xf7,
- 0xc5, 0x1c, 0xb1, 0x7f, 0xb2, 0x74, 0xd0, 0x7f, 0xac, 0x5f, 0xe7, 0x0f,
- 0x93, 0xf6, 0x8f, 0x58, 0xad, 0x1f, 0x4f, 0x8c, 0xaf, 0xde, 0xff, 0x78,
- 0x11, 0x62, 0xf6, 0x3e, 0xcb, 0x14, 0x34, 0xee, 0x3b, 0x84, 0xdb, 0x91,
- 0x1e, 0x12, 0x1f, 0x22, 0xe1, 0x65, 0xe9, 0xf7, 0x16, 0x2f, 0xdc, 0x63,
- 0x7e, 0xeb, 0x17, 0xfd, 0x1e, 0x3f, 0x8b, 0x9d, 0xc1, 0x96, 0x2e, 0x7f,
- 0xe1, 0xf4, 0x08, 0xa6, 0xa5, 0x5b, 0x9e, 0x4a, 0x60, 0x76, 0x26, 0x84,
- 0x2d, 0xb1, 0x62, 0xfe, 0x84, 0xc2, 0x4f, 0x05, 0x8a, 0xd8, 0xdf, 0xb8,
- 0x8d, 0xfc, 0xe6, 0x99, 0xc9, 0xc5, 0x8b, 0xb2, 0x36, 0x58, 0xad, 0x1e,
- 0x59, 0x85, 0xf7, 0xff, 0x6a, 0x41, 0xf7, 0x9d, 0x00, 0xf0, 0x58, 0xbe,
- 0x8b, 0xee, 0x05, 0x8b, 0xe9, 0xfc, 0x81, 0x62, 0xa5, 0x11, 0x66, 0xa2,
- 0xc7, 0x12, 0x5f, 0xff, 0x89, 0x83, 0xf6, 0x7f, 0xa8, 0x50, 0x29, 0x1b,
- 0x85, 0xa8, 0x54, 0x28, 0xb1, 0x76, 0x7d, 0x62, 0xff, 0xe0, 0x1d, 0xcb,
- 0x00, 0x58, 0xd1, 0x2c, 0x56, 0x1e, 0xd0, 0x85, 0xef, 0xf3, 0xfd, 0xe4,
- 0xa2, 0x12, 0xc5, 0xe9, 0xf8, 0x55, 0x62, 0xfd, 0x98, 0x5d, 0xf9, 0x62,
- 0xff, 0x85, 0xa6, 0xe7, 0x5f, 0x6c, 0x1a, 0xc5, 0x9f, 0x47, 0xcf, 0xe2,
- 0x8a, 0x94, 0x71, 0x39, 0x9b, 0x42, 0x22, 0xfb, 0x6f, 0xe7, 0x96, 0x2f,
- 0xfa, 0x0c, 0x40, 0xea, 0x1e, 0x7d, 0x62, 0xfd, 0x17, 0x38, 0xf1, 0x2c,
- 0x5f, 0xf0, 0xf5, 0x82, 0xfc, 0x9f, 0x16, 0x2b, 0x11, 0x40, 0xe7, 0x82,
- 0x2b, 0xbf, 0xfd, 0xd3, 0x3a, 0x99, 0xe7, 0xd3, 0xec, 0xc7, 0x58, 0xbf,
- 0xc4, 0x03, 0x3f, 0xf6, 0xd9, 0x62, 0xb1, 0x10, 0xce, 0xa1, 0x7d, 0x1d,
- 0x9a, 0x95, 0x8b, 0xff, 0xfa, 0x3b, 0x3a, 0x96, 0x6c, 0x64, 0x3a, 0xf3,
- 0x8e, 0x1f, 0x16, 0x2d, 0x9b, 0x22, 0x2c, 0x04, 0xb5, 0xf4, 0x6a, 0x94,
- 0x2b, 0x2a, 0x57, 0x71, 0xb1, 0xb1, 0xe1, 0x5d, 0x11, 0x9e, 0xa1, 0xa1,
- 0xf8, 0xc0, 0xd8, 0xcb, 0x90, 0xc4, 0xf4, 0x71, 0x36, 0xf2, 0xc5, 0xff,
- 0xed, 0x4f, 0xd9, 0xfd, 0x3f, 0x2e, 0xdd, 0x62, 0xa2, 0x3d, 0xb2, 0x12,
- 0xbf, 0xf7, 0xe7, 0x40, 0xd6, 0xa4, 0xfc, 0x58, 0xbf, 0x37, 0x09, 0xe5,
- 0x62, 0xff, 0xe7, 0xd0, 0xfe, 0x2d, 0x66, 0xff, 0xc5, 0x8b, 0xf3, 0xe9,
- 0x82, 0x3a, 0xc5, 0x40, 0xfb, 0xf7, 0x46, 0xbf, 0xb6, 0x6d, 0x88, 0x5e,
- 0x58, 0xbf, 0xe7, 0x07, 0xf7, 0x7e, 0x60, 0xd6, 0x2c, 0x05, 0x8a, 0xd1,
- 0xe6, 0x11, 0xd5, 0xf7, 0x84, 0xde, 0x58, 0xbc, 0x26, 0xf2, 0xc5, 0x75,
- 0x3c, 0x0f, 0x11, 0xde, 0xe9, 0x9a, 0x58, 0xa9, 0x3c, 0x3c, 0x24, 0xbf,
- 0x02, 0x7a, 0x61, 0x2c, 0x5e, 0x62, 0x02, 0xc5, 0x31, 0xe2, 0x88, 0xa6,
- 0xa5, 0x56, 0x06, 0x11, 0x1a, 0x81, 0xdc, 0x25, 0x5c, 0x8d, 0x9f, 0x0a,
- 0x14, 0x9c, 0x65, 0xbe, 0xe3, 0xf9, 0xd6, 0x2e, 0x10, 0xd6, 0x2a, 0x36,
- 0x37, 0x42, 0x22, 0xbf, 0xa2, 0x7f, 0xeb, 0x0e, 0xb1, 0x7c, 0x67, 0x27,
- 0x16, 0x2e, 0x70, 0xd6, 0x2e, 0x09, 0x8b, 0x14, 0xc8, 0x83, 0x01, 0x7f,
- 0x08, 0xfc, 0x31, 0x7f, 0x72, 0x7d, 0xcf, 0xba, 0xc5, 0xf8, 0xb0, 0xfa,
- 0xc5, 0x8b, 0xed, 0xa0, 0xc3, 0x58, 0xbd, 0xd3, 0x06, 0xb1, 0x73, 0xfd,
- 0x62, 0xb4, 0x6d, 0xbe, 0x3f, 0x58, 0x8d, 0x03, 0x97, 0x31, 0x38, 0x96,
- 0xaf, 0xf6, 0xff, 0xce, 0xfc, 0x61, 0xd6, 0x2f, 0xdf, 0x9d, 0x1e, 0x0b,
- 0x17, 0x87, 0x9e, 0x58, 0xbf, 0xff, 0xe2, 0xdd, 0xbc, 0xdd, 0x83, 0xe1,
- 0xb1, 0x6d, 0xfe, 0xda, 0x3d, 0x62, 0xff, 0xf0, 0x8e, 0x60, 0xc7, 0x20,
- 0x3c, 0xe7, 0x96, 0x2c, 0x09, 0x45, 0xd1, 0x37, 0x5f, 0xb3, 0xbf, 0x67,
- 0x6b, 0x17, 0xfb, 0x0b, 0xaf, 0xe7, 0x23, 0xd6, 0x2f, 0xfc, 0xfe, 0xe6,
- 0x0e, 0x22, 0x91, 0xac, 0x5f, 0x01, 0xfb, 0x82, 0xc5, 0xfe, 0x92, 0xf3,
- 0xec, 0x52, 0xb1, 0x7f, 0xf9, 0xf4, 0xfb, 0x49, 0x67, 0xf4, 0x2e, 0x8b,
- 0x15, 0x2a, 0xa8, 0x60, 0x70, 0x32, 0x9e, 0xe1, 0xaf, 0xa2, 0x73, 0x95,
- 0x7c, 0xdc, 0x07, 0xe4, 0x49, 0xe3, 0x2b, 0xff, 0xd2, 0x5b, 0xb7, 0x98,
- 0xd3, 0x36, 0x9d, 0x96, 0x2f, 0xfc, 0xe3, 0x17, 0xb8, 0xde, 0x63, 0x56,
- 0x2f, 0xec, 0x0f, 0xb8, 0x73, 0xa9, 0xa8, 0x8e, 0x64, 0xeb, 0xff, 0xfb,
- 0x0b, 0x0d, 0xfb, 0x45, 0xf6, 0x37, 0x35, 0x9e, 0x58, 0xbf, 0xf8, 0xc9,
- 0xec, 0xc2, 0x2c, 0x7e, 0xfc, 0xb1, 0x4e, 0x8e, 0xdf, 0xa5, 0x32, 0xe5,
- 0x46, 0xee, 0xee, 0x8a, 0x34, 0x6f, 0x99, 0x44, 0x7b, 0x43, 0x82, 0x12,
- 0x8d, 0xc7, 0x0f, 0x6c, 0xa4, 0x44, 0x1b, 0x1d, 0x56, 0xe4, 0x5d, 0xc7,
- 0xc8, 0xf1, 0xec, 0x45, 0x1f, 0x36, 0xa5, 0xf1, 0x1e, 0x50, 0xcf, 0xe7,
- 0x48, 0x9a, 0x56, 0x00, 0x23, 0xdf, 0x0b, 0xa1, 0x14, 0xb9, 0x0e, 0x4f,
- 0x26, 0x7a, 0x5d, 0xa0, 0xa1, 0x69, 0xd2, 0x15, 0x31, 0xd1, 0x86, 0x19,
- 0x2b, 0x70, 0x24, 0xa0, 0xcb, 0xf0, 0x53, 0x6d, 0x9f, 0xeb, 0x17, 0xfd,
- 0xe9, 0x1e, 0xb5, 0x27, 0xe2, 0xc5, 0xfd, 0x2d, 0xa3, 0x24, 0x0b, 0x17,
- 0xfa, 0x18, 0x40, 0xcc, 0x1a, 0xc5, 0xfe, 0x92, 0xf1, 0x49, 0xf8, 0xb1,
- 0x50, 0x3e, 0x41, 0x99, 0x5c, 0x6e, 0xeb, 0x17, 0xf1, 0xe1, 0x33, 0xc7,
- 0x58, 0xbf, 0x1b, 0x25, 0x9c, 0x58, 0xb9, 0x80, 0xb1, 0x52, 0x7d, 0x8e,
- 0x5a, 0xc5, 0x17, 0xc3, 0x66, 0xed, 0x62, 0xfe, 0x7e, 0xdf, 0x79, 0x31,
- 0x62, 0x98, 0xf4, 0xc8, 0x8e, 0xf3, 0x98, 0x75, 0x8b, 0xf6, 0x67, 0xfc,
- 0xeb, 0x17, 0xf8, 0x8a, 0x7b, 0x3b, 0x79, 0x62, 0xff, 0xd0, 0x71, 0x99,
- 0xee, 0xf7, 0x73, 0xac, 0x5f, 0xb3, 0xfd, 0xb4, 0x7a, 0xc5, 0xff, 0xef,
- 0xe1, 0x13, 0x7a, 0x4b, 0xd1, 0xd8, 0xb1, 0x43, 0x4c, 0x4d, 0xc9, 0xe2,
- 0x33, 0x24, 0x3f, 0x16, 0x5c, 0xdd, 0x16, 0x2f, 0xf6, 0xd9, 0xe9, 0x27,
- 0x02, 0xc5, 0x6e, 0x79, 0x8e, 0x33, 0x7f, 0x9b, 0x61, 0xfe, 0x79, 0xda,
- 0xc5, 0xff, 0xdb, 0x67, 0xa4, 0x9c, 0x19, 0xdf, 0x96, 0x2f, 0xf4, 0x50,
- 0x6d, 0x6d, 0xf1, 0x2c, 0x5a, 0x25, 0x8a, 0x58, 0xbe, 0x62, 0x07, 0xa4,
- 0xbf, 0xc1, 0x3a, 0x94, 0x67, 0x9d, 0x16, 0x39, 0x5a, 0xef, 0x46, 0x46,
- 0x8b, 0xac, 0x52, 0x5e, 0x33, 0xac, 0x84, 0x91, 0xc8, 0xbf, 0x08, 0x66,
- 0x7f, 0x01, 0x07, 0x23, 0x31, 0xf4, 0x25, 0xa3, 0x88, 0x8c, 0x8c, 0x16,
- 0xff, 0xff, 0xe1, 0x77, 0x08, 0xc6, 0x2f, 0x61, 0xf8, 0x3f, 0xce, 0x86,
- 0xcc, 0x1a, 0xc5, 0xee, 0x80, 0x75, 0x8b, 0xfd, 0x26, 0xf7, 0x0f, 0x48,
- 0x6b, 0x17, 0xe9, 0x0f, 0x52, 0x75, 0x8a, 0x81, 0xf0, 0x11, 0xbd, 0xe9,
- 0x0e, 0x30, 0x2c, 0x45, 0x06, 0x3f, 0xd4, 0x63, 0x26, 0x53, 0x27, 0xda,
- 0x4a, 0x1b, 0x1e, 0x8c, 0x5e, 0xff, 0xf4, 0x61, 0xda, 0x11, 0x99, 0xad,
- 0xd9, 0xb7, 0x54, 0x4d, 0x25, 0xff, 0xe8, 0xc3, 0xb4, 0x23, 0x33, 0x5b,
- 0xb3, 0x6e, 0xa8, 0x9c, 0x4b, 0xc0, 0x29, 0x58, 0xbf, 0x41, 0xc8, 0x0e,
- 0xb1, 0x7e, 0x86, 0x7a, 0x10, 0x58, 0xbf, 0xdd, 0x27, 0xfd, 0x4a, 0x60,
- 0xb1, 0x7f, 0xfb, 0x7d, 0xb3, 0xed, 0x85, 0x22, 0x0b, 0xf1, 0x62, 0xfd,
- 0xad, 0xd9, 0xb7, 0x54, 0x50, 0x25, 0xfe, 0x13, 0x16, 0xf0, 0x1c, 0x7a,
- 0xc5, 0xe6, 0x84, 0x64, 0x11, 0x7d, 0x89, 0xe0, 0x37, 0xbf, 0xfc, 0xf2,
- 0x76, 0x1e, 0xa7, 0xdf, 0xc1, 0xac, 0x5f, 0x70, 0xbb, 0x82, 0xc5, 0xa3,
- 0x25, 0x50, 0x8e, 0x0e, 0x76, 0x4e, 0xe5, 0x27, 0x87, 0xaf, 0xd0, 0xfc,
- 0x93, 0x74, 0x6f, 0x1b, 0x2c, 0x5e, 0xfb, 0x9d, 0x62, 0xfb, 0x76, 0x6d,
- 0xd5, 0x17, 0x01, 0x7f, 0x87, 0xf9, 0x8e, 0xcd, 0x4a, 0xc5, 0x68, 0xf9,
- 0xc8, 0xc6, 0xee, 0xf8, 0xb1, 0x7c, 0x6e, 0xec, 0x35, 0x8b, 0xa4, 0xc5,
- 0x8b, 0xf8, 0xb3, 0xdb, 0xbf, 0x16, 0x2e, 0x97, 0x58, 0xbc, 0x26, 0x82,
- 0xc5, 0xa0, 0xb4, 0x15, 0xf3, 0x66, 0x43, 0xb7, 0xf8, 0xa1, 0x2e, 0x3c,
- 0x3a, 0xc5, 0x46, 0xc9, 0xf3, 0x0c, 0x8b, 0x21, 0x09, 0xd9, 0x0b, 0x8c,
- 0xe8, 0x94, 0xe3, 0x1f, 0x2e, 0xf2, 0x48, 0x88, 0x2f, 0xd0, 0x8c, 0x34,
- 0x2a, 0x6a, 0xc5, 0xf9, 0xc7, 0xf7, 0x35, 0x62, 0xec, 0xe8, 0xb1, 0x78,
- 0xd8, 0xc6, 0xdc, 0xf0, 0xbc, 0x53, 0x51, 0x89, 0xa1, 0x4c, 0x25, 0x5d,
- 0xd6, 0xff, 0x05, 0x23, 0x70, 0xac, 0x01, 0x07, 0x58, 0xbf, 0x8f, 0x3e,
- 0x14, 0x4c, 0xb1, 0x7b, 0xb8, 0x71, 0x62, 0x96, 0x2c, 0xcc, 0x6a, 0xc0,
- 0x3f, 0x7e, 0x8a, 0x12, 0x50, 0x58, 0xa5, 0x8a, 0xc3, 0x6a, 0x45, 0x37,
- 0xec, 0x34, 0xb0, 0x0b, 0x16, 0x02, 0xc5, 0x40, 0xdd, 0x11, 0x45, 0xe0,
- 0x60, 0x6b, 0x17, 0xc5, 0x39, 0xf5, 0x8a, 0x93, 0x7f, 0xb0, 0xf5, 0xcf,
- 0x18, 0x16, 0x27, 0x9f, 0x28, 0x5a, 0x5a, 0x25, 0xaf, 0x2c, 0x98, 0xbf,
- 0x7b, 0xef, 0xba, 0xc5, 0xfe, 0xf7, 0x7b, 0xbf, 0x3e, 0xeb, 0x17, 0x8d,
- 0xfb, 0xac, 0x56, 0x1e, 0xa0, 0x8d, 0xaa, 0x3d, 0x12, 0x64, 0xe5, 0x7e,
- 0xd6, 0xec, 0xdb, 0xaa, 0x24, 0x92, 0xe8, 0x46, 0x49, 0xee, 0x61, 0x2d,
- 0x7d, 0x38, 0x86, 0x8d, 0x66, 0xfe, 0x83, 0x6b, 0x6f, 0x89, 0x62, 0xfd,
- 0xc9, 0x01, 0x9b, 0x2c, 0x5f, 0xa4, 0xd8, 0xc1, 0xe4, 0x47, 0xb7, 0xc3,
- 0x0b, 0xfd, 0x39, 0x18, 0x76, 0x60, 0x8b, 0x15, 0x18, 0x8f, 0xe7, 0x84,
- 0x21, 0x21, 0xdf, 0xb0, 0x30, 0x0b, 0x8b, 0x17, 0x06, 0x05, 0x8b, 0xfe,
- 0xfc, 0xeb, 0x3c, 0x52, 0x75, 0x8b, 0xe3, 0x74, 0xc1, 0xac, 0x56, 0xe7,
- 0xba, 0xe7, 0x17, 0xf9, 0xbc, 0x59, 0xb3, 0x12, 0xc5, 0xfa, 0x62, 0x29,
- 0x1a, 0xc5, 0xc6, 0x86, 0xb1, 0x78, 0xbb, 0x95, 0x8b, 0xf9, 0xf6, 0x14,
- 0x5d, 0xca, 0xc5, 0xf9, 0xb5, 0xb0, 0xe5, 0x62, 0xa4, 0xf6, 0xa0, 0x63,
- 0x7f, 0x61, 0x37, 0x70, 0xe2, 0xc5, 0xff, 0xf8, 0x44, 0xc6, 0xf8, 0xd9,
- 0x28, 0x67, 0xdc, 0xeb, 0x17, 0x37, 0x6b, 0x17, 0x77, 0x8b, 0x17, 0xe3,
- 0xb7, 0xde, 0x25, 0x8a, 0x73, 0xc1, 0x61, 0x8a, 0xd1, 0xfc, 0xf9, 0x66,
- 0xf3, 0xea, 0x0b, 0x17, 0xff, 0xec, 0xde, 0x7f, 0x27, 0xdf, 0xef, 0xec,
- 0xc3, 0xac, 0x5f, 0x8f, 0xac, 0x1f, 0x96, 0x2f, 0xf3, 0x0e, 0x7a, 0x39,
- 0x6c, 0xb1, 0x7c, 0x09, 0x78, 0x96, 0x2f, 0xee, 0xcc, 0xf1, 0x48, 0x16,
- 0x2f, 0xee, 0xfd, 0x25, 0x9c, 0x58, 0xa9, 0x3d, 0xe7, 0x30, 0xa9, 0x47,
- 0xfb, 0x94, 0x80, 0xd4, 0x50, 0x81, 0xbf, 0xb6, 0xfb, 0x80, 0x5c, 0x58,
- 0xbe, 0xfc, 0x91, 0xab, 0x14, 0xc7, 0xa6, 0x10, 0xc2, 0xfc, 0xc4, 0x42,
- 0xd9, 0x62, 0xc3, 0x58, 0xa5, 0x8b, 0xec, 0xe8, 0x29, 0x58, 0xb6, 0xce,
- 0x6c, 0x08, 0x32, 0xb6, 0x3e, 0x86, 0x42, 0xb9, 0xa3, 0x36, 0x5d, 0xc7,
- 0x19, 0x56, 0x3b, 0x1a, 0x45, 0xb9, 0x97, 0x65, 0x0e, 0x35, 0x13, 0xbe,
- 0x88, 0x4e, 0x5c, 0xd0, 0xcf, 0x01, 0x11, 0x0e, 0xf2, 0x35, 0x5f, 0x42,
- 0x4c, 0x32, 0x38, 0xe8, 0x48, 0x5f, 0xfd, 0xb4, 0x67, 0x61, 0x30, 0xb3,
- 0xed, 0xc5, 0x8a, 0xd9, 0xf6, 0x0e, 0x21, 0x78, 0xb2, 0xbb, 0xaa, 0xc4,
- 0xbe, 0x09, 0x4e, 0x1c, 0x97, 0x35, 0xe9, 0xc8, 0xce, 0x93, 0xbf, 0xa1,
- 0x23, 0x11, 0xbe, 0x8f, 0xfb, 0xc7, 0xac, 0x5f, 0xb5, 0xe2, 0x17, 0x96,
- 0x2f, 0xfc, 0x6b, 0x46, 0x66, 0xb7, 0x66, 0xdd, 0x51, 0x6a, 0x17, 0xdc,
- 0x9f, 0x71, 0x62, 0xff, 0xcd, 0x08, 0xcc, 0xd6, 0xec, 0xdb, 0xaa, 0x25,
- 0x52, 0xc1, 0xac, 0x5e, 0x7e, 0xe0, 0xb1, 0x4e, 0x6c, 0x7e, 0x27, 0x4b,
- 0x15, 0x29, 0xb9, 0xe1, 0x49, 0xa5, 0x3d, 0xa8, 0x9c, 0x8f, 0xd0, 0x81,
- 0x08, 0x41, 0x7f, 0xfe, 0xc3, 0x79, 0xbc, 0x1a, 0x63, 0x78, 0xd5, 0xd7,
- 0xaf, 0xe3, 0x96, 0x2f, 0xff, 0xff, 0xe0, 0xb0, 0x5b, 0x6c, 0xd1, 0xf1,
- 0xf9, 0x30, 0xf8, 0x5f, 0xb7, 0x99, 0x8d, 0xe3, 0x57, 0x5e, 0xbf, 0x8e,
- 0x58, 0xbf, 0x81, 0xd7, 0xaf, 0xe3, 0xa3, 0x1d, 0x31, 0x9e, 0x8d, 0x75,
- 0x18, 0x9e, 0xc0, 0x52, 0x38, 0x5b, 0xfb, 0x35, 0xbb, 0x36, 0xea, 0x88,
- 0xa4, 0xbf, 0xf3, 0x31, 0xf3, 0x40, 0x21, 0x01, 0x62, 0xff, 0xbd, 0xcc,
- 0xd0, 0x08, 0x40, 0x58, 0xb8, 0x99, 0x62, 0xa4, 0xf4, 0x06, 0x75, 0x77,
- 0x19, 0x62, 0xf7, 0x25, 0x96, 0x2b, 0x0d, 0x9b, 0x8b, 0xdf, 0xe2, 0x60,
- 0x73, 0xd9, 0xba, 0xc5, 0xfb, 0x07, 0xb6, 0x06, 0xb1, 0x71, 0xe3, 0x3e,
- 0x9a, 0xf9, 0x42, 0x3b, 0x8a, 0x9e, 0x1f, 0xe8, 0x69, 0x51, 0x89, 0xfd,
- 0xb4, 0x73, 0x77, 0xed, 0x6e, 0xcd, 0xba, 0xa2, 0x34, 0x2f, 0xe2, 0x71,
- 0xe9, 0xf6, 0x58, 0xb4, 0x66, 0x1f, 0x2b, 0x9b, 0xdf, 0xf8, 0x0f, 0x3e,
- 0x8c, 0xfe, 0x3f, 0xd6, 0x2f, 0x46, 0xb8, 0xe8, 0xdd, 0x62, 0xf8, 0x28,
- 0x16, 0xe3, 0x5c, 0x6b, 0x58, 0xbe, 0x7f, 0xb9, 0xd6, 0x2e, 0x17, 0xd6,
- 0x2f, 0xa3, 0x58, 0x5b, 0x8d, 0x71, 0xad, 0x62, 0xf6, 0xa6, 0x25, 0x8b,
- 0xf7, 0xda, 0x27, 0x3a, 0xc5, 0x39, 0xe3, 0x9c, 0x7a, 0xff, 0xb0, 0xef,
- 0xac, 0xe4, 0x52, 0xb1, 0x7b, 0xd9, 0xf5, 0x8a, 0x19, 0xeb, 0x78, 0xe6,
- 0xff, 0x7b, 0xce, 0xdd, 0x27, 0xcb, 0x17, 0xff, 0xf8, 0x5c, 0xfe, 0x0c,
- 0xc3, 0x38, 0xe6, 0x79, 0xf9, 0x11, 0x8b, 0x15, 0x28, 0x9d, 0x63, 0x5b,
- 0xff, 0xd1, 0x3b, 0xfe, 0x2c, 0xf4, 0xfa, 0x46, 0xb1, 0x67, 0x58, 0xbc,
- 0xec, 0x1a, 0x45, 0xff, 0x4f, 0xe7, 0x6d, 0x4e, 0x0d, 0x62, 0xff, 0xd3,
- 0x3d, 0x24, 0xa6, 0x29, 0x89, 0x62, 0xfd, 0x17, 0x1b, 0x3c, 0xb1, 0x7f,
- 0xb5, 0xa9, 0xef, 0x9f, 0x1a, 0xc5, 0xbf, 0x27, 0xbe, 0xe5, 0x37, 0xff,
- 0xd3, 0xf9, 0x8b, 0x82, 0xf0, 0x85, 0x14, 0xf4, 0x58, 0xa9, 0x56, 0x46,
- 0xee, 0xf1, 0xf0, 0xbf, 0x88, 0x87, 0x49, 0x67, 0x11, 0xf8, 0xe9, 0x1c,
- 0xfa, 0x13, 0xfd, 0x09, 0xaf, 0xe7, 0xe4, 0x59, 0xa9, 0x58, 0xbe, 0xdd,
- 0x9b, 0x75, 0x45, 0x3e, 0x5f, 0xfb, 0xed, 0xee, 0x37, 0x6c, 0x40, 0x58,
- 0xbf, 0xb8, 0x64, 0x87, 0xa9, 0x58, 0xb3, 0xe8, 0xfb, 0xce, 0x7f, 0x77,
- 0xa5, 0x62, 0xb4, 0x8d, 0xef, 0xc2, 0x83, 0xc4, 0xf7, 0xc1, 0xef, 0x10,
- 0x55, 0x62, 0xff, 0xf0, 0xb9, 0xf6, 0x84, 0xf8, 0xa4, 0x1c, 0x58, 0xbf,
- 0xec, 0xe9, 0xf7, 0x8e, 0xcd, 0x1a, 0xb1, 0x7b, 0xef, 0xed, 0x22, 0x27,
- 0x89, 0x57, 0xff, 0x3c, 0x67, 0xf3, 0xed, 0xd1, 0xf9, 0xda, 0xc5, 0xfe,
- 0x7f, 0x3f, 0xbe, 0x2f, 0x2c, 0x5f, 0xff, 0x85, 0xb6, 0xa7, 0xac, 0xf4,
- 0x14, 0x4d, 0xa9, 0xe8, 0xb1, 0x7c, 0x01, 0x0b, 0x4b, 0x17, 0xd2, 0x7d,
- 0x32, 0xc5, 0xfe, 0x9f, 0x7d, 0xa2, 0xeb, 0x8b, 0x17, 0xff, 0x4c, 0xea,
- 0x78, 0xfa, 0xd3, 0xf1, 0x62, 0xa2, 0x3f, 0x9f, 0x1b, 0x54, 0x49, 0xdf,
- 0x69, 0x28, 0xe6, 0x80, 0x5e, 0x22, 0x4f, 0x42, 0x6e, 0xfe, 0xcc, 0xdf,
- 0xd9, 0xba, 0xc5, 0xff, 0x34, 0x1c, 0x7f, 0x98, 0x71, 0x62, 0xfc, 0x2f,
- 0x7a, 0x7a, 0x2c, 0x5f, 0xfd, 0x31, 0x44, 0xe0, 0x98, 0xa2, 0xc0, 0x2c,
- 0x5a, 0x74, 0x7e, 0x64, 0x57, 0x7d, 0xd1, 0xf9, 0xda, 0xc5, 0xbe, 0xe7,
- 0x98, 0xc4, 0xd7, 0x7c, 0x4b, 0x15, 0x86, 0xf8, 0x44, 0xd7, 0xec, 0xfb,
- 0x97, 0x96, 0x2e, 0x68, 0x96, 0x2f, 0xfe, 0x39, 0x0b, 0xef, 0xac, 0xe4,
- 0x52, 0xb1, 0x7f, 0xff, 0xfe, 0x9f, 0x39, 0x37, 0x39, 0x9e, 0xfb, 0x1f,
- 0xf8, 0x53, 0x3c, 0x61, 0x74, 0x58, 0xbe, 0x68, 0x9f, 0xeb, 0x17, 0xff,
- 0xb5, 0x8f, 0x17, 0x05, 0x3d, 0x94, 0xf9, 0x62, 0xfd, 0xd0, 0x51, 0xf2,
- 0x05, 0x8a, 0x82, 0x74, 0x3d, 0x93, 0xb8, 0xc6, 0x91, 0x4f, 0x08, 0x1f,
- 0x11, 0x89, 0x2e, 0xf7, 0x85, 0xa5, 0x8b, 0xf8, 0x45, 0x80, 0x17, 0x16,
- 0x2b, 0xb3, 0xcc, 0xe0, 0xf5, 0xff, 0xbd, 0xa1, 0x45, 0xcd, 0xda, 0x2e,
- 0x2c, 0x56, 0x1f, 0x38, 0x88, 0xee, 0x01, 0x8b, 0x17, 0xf1, 0x4f, 0x8a,
- 0x7c, 0xb1, 0x50, 0x3c, 0x56, 0x19, 0xbd, 0x13, 0xf1, 0x62, 0xf9, 0xe7,
- 0x58, 0xb1, 0x7e, 0x9f, 0x77, 0x9e, 0x93, 0x7f, 0xf1, 0xeb, 0xff, 0x44,
- 0x22, 0xdb, 0x9b, 0xb4, 0x5c, 0x58, 0xa9, 0x44, 0x0e, 0x1e, 0xdc, 0xdc,
- 0x58, 0xbf, 0x0a, 0x28, 0x98, 0xd5, 0x8b, 0xfe, 0xf4, 0xf6, 0xd1, 0x6a,
- 0x7a, 0x2c, 0x54, 0x7a, 0x20, 0x38, 0x2f, 0xe2, 0xca, 0x58, 0xbd, 0xf7,
- 0xd2, 0xc5, 0x46, 0xc6, 0xa4, 0x41, 0x96, 0xc5, 0x8b, 0x46, 0x46, 0xec,
- 0xfe, 0x20, 0xa1, 0x60, 0x54, 0xea, 0x34, 0x22, 0x8d, 0x63, 0x13, 0x2e,
- 0x9b, 0x68, 0x4d, 0x64, 0x61, 0x86, 0x9a, 0xef, 0x0b, 0x47, 0x8f, 0xca,
- 0x25, 0xd3, 0x97, 0xfe, 0x33, 0x66, 0x8f, 0x04, 0xa3, 0x1d, 0xe3, 0x37,
- 0xa1, 0xc2, 0x28, 0x50, 0xc7, 0x2e, 0x04, 0x26, 0xbf, 0xfd, 0x18, 0x76,
- 0x84, 0x66, 0x6b, 0x76, 0x6d, 0xd5, 0x13, 0x51, 0x7f, 0xf4, 0x0a, 0x63,
- 0x26, 0x2c, 0x21, 0x62, 0xc5, 0xfd, 0x9a, 0xdd, 0x9b, 0x75, 0x45, 0x76,
- 0x5f, 0xfe, 0xc0, 0x8f, 0xe7, 0x87, 0x52, 0x9f, 0x71, 0x62, 0xff, 0xe9,
- 0x39, 0x9e, 0x72, 0x14, 0x33, 0x8b, 0x17, 0x88, 0x86, 0xb1, 0x78, 0xf3,
- 0xf5, 0x8a, 0x58, 0xb8, 0x38, 0xcf, 0xa3, 0x5c, 0x09, 0xa4, 0x8a, 0x21,
- 0xc0, 0xc7, 0x6f, 0xfa, 0x33, 0x3e, 0xfa, 0xf0, 0x99, 0x62, 0xa3, 0x13,
- 0xa9, 0x78, 0xc4, 0xf8, 0xb5, 0x70, 0x1d, 0x62, 0xc3, 0x58, 0xba, 0x4e,
- 0xb1, 0x5f, 0x35, 0x3c, 0x12, 0xb4, 0x72, 0xc5, 0x89, 0x62, 0xb6, 0x34,
- 0xc7, 0x15, 0xbb, 0x69, 0x58, 0xbe, 0xdd, 0x9b, 0x75, 0x45, 0x7c, 0x5e,
- 0x0c, 0x30, 0xd2, 0x2c, 0x49, 0x11, 0x86, 0x86, 0xb4, 0x7e, 0xc7, 0x52,
- 0xbf, 0xdf, 0xc3, 0x5a, 0x7b, 0x08, 0xb1, 0x7a, 0x13, 0xda, 0xc5, 0xf7,
- 0x60, 0x92, 0x58, 0xbb, 0xee, 0xb1, 0x6c, 0x93, 0x75, 0xe2, 0x3b, 0x81,
- 0xf5, 0x8b, 0x85, 0xc5, 0x8b, 0xb3, 0xeb, 0x14, 0x33, 0x5f, 0x10, 0xc5,
- 0xcd, 0xd1, 0x62, 0xfa, 0x02, 0x2d, 0x96, 0x2f, 0xe6, 0xf7, 0x27, 0x36,
- 0x58, 0xa8, 0x8f, 0x48, 0x32, 0x4b, 0xdc, 0x90, 0x2c, 0x57, 0xcf, 0x07,
- 0xc4, 0x96, 0x95, 0x8b, 0xe2, 0x6e, 0xf8, 0xb1, 0x58, 0x7a, 0xdc, 0x22,
- 0xf0, 0x8d, 0xe0, 0xf3, 0x4b, 0x16, 0xf2, 0xc5, 0xec, 0x9e, 0xd6, 0x2f,
- 0xf9, 0xf5, 0x9b, 0x3c, 0x30, 0x6b, 0x17, 0xfb, 0x40, 0xf7, 0x18, 0x18,
- 0xb1, 0x4e, 0x8b, 0xad, 0x0f, 0x7c, 0x49, 0x87, 0x44, 0x73, 0x7b, 0xe4,
- 0x05, 0x8b, 0xe0, 0x9f, 0x11, 0x8b, 0x17, 0xa2, 0xc8, 0x96, 0x2c, 0xeb,
- 0x15, 0xd9, 0xeb, 0xc4, 0x4e, 0x71, 0xfb, 0x69, 0x62, 0x96, 0x29, 0xcb,
- 0xed, 0x09, 0x52, 0xc5, 0x9d, 0x62, 0xdb, 0x1a, 0x5e, 0xfc, 0x32, 0xdd,
- 0x16, 0x2b, 0xe7, 0xf0, 0xc7, 0x82, 0x28, 0xbe, 0xc2, 0x98, 0x2c, 0x5a,
- 0x30, 0x2c, 0x5e, 0x32, 0x94, 0x0d, 0x91, 0xe0, 0x45, 0x90, 0x8e, 0xdc,
- 0x8a, 0x23, 0x7d, 0x2c, 0x1c, 0x95, 0x91, 0xc0, 0x44, 0x51, 0x81, 0x72,
- 0x1d, 0x1e, 0x48, 0x13, 0xa4, 0x74, 0x31, 0xcc, 0x2e, 0xbf, 0xfd, 0x18,
- 0x76, 0x84, 0x66, 0x6b, 0x76, 0x6d, 0xd5, 0x13, 0xd9, 0x60, 0xba, 0xc5,
- 0xff, 0x0d, 0xb7, 0x9d, 0xc4, 0x43, 0x58, 0xbf, 0xfe, 0x78, 0x72, 0x3f,
- 0xe2, 0xdf, 0x36, 0xea, 0x3d, 0x2c, 0x5f, 0xf0, 0xda, 0x3e, 0x74, 0x36,
- 0x8f, 0x58, 0xbe, 0x90, 0x8d, 0xda, 0xc5, 0xe7, 0x20, 0x2c, 0x56, 0xc9,
- 0x8a, 0x40, 0xef, 0x4b, 0x3f, 0x3f, 0xe8, 0x4b, 0x7f, 0xf0, 0xb5, 0x16,
- 0x9f, 0x66, 0x3b, 0xf1, 0x62, 0xfc, 0xe3, 0x9d, 0x71, 0x62, 0xff, 0xec,
- 0xfe, 0x7b, 0xbd, 0xdf, 0x5f, 0xc5, 0x8b, 0xf6, 0xb7, 0x66, 0xdd, 0x51,
- 0x70, 0x97, 0xc7, 0x17, 0xb8, 0xb1, 0x7f, 0xbe, 0xf0, 0x10, 0x26, 0x25,
- 0x8b, 0xff, 0x3f, 0x46, 0x8b, 0x8f, 0xa9, 0x3a, 0xc5, 0xfd, 0x2f, 0xad,
- 0x38, 0x6b, 0x17, 0xbf, 0x91, 0x2c, 0x5b, 0xeb, 0x14, 0x33, 0x60, 0xc3,
- 0xd6, 0x8c, 0x0a, 0xab, 0x7c, 0x98, 0xca, 0xb6, 0x4e, 0x82, 0x38, 0xca,
- 0x31, 0x18, 0xd3, 0x77, 0x24, 0x88, 0xd4, 0xe8, 0x22, 0x5e, 0xbf, 0xfa,
- 0x31, 0xa1, 0x19, 0x9a, 0xdd, 0x9b, 0x75, 0x44, 0x9e, 0x5f, 0xf9, 0xe2,
- 0x8c, 0x91, 0x4f, 0xa4, 0x0b, 0x17, 0xdf, 0x92, 0x35, 0x62, 0xfd, 0xa8,
- 0xb3, 0x03, 0x58, 0xb8, 0xd8, 0xc8, 0x8f, 0x34, 0xc2, 0x3a, 0x97, 0x47,
- 0xe3, 0xb4, 0xa2, 0xc8, 0x42, 0x47, 0x0a, 0x4d, 0xac, 0x08, 0xf7, 0x8d,
- 0xf3, 0xb5, 0xf8, 0xa3, 0xef, 0xd4, 0xf3, 0x5f, 0xe3, 0x0f, 0xe4, 0xbd,
- 0xbe, 0x90, 0xad, 0x0d, 0x64, 0xc8, 0x47, 0xdf, 0xe8, 0xcc, 0xd6, 0xec,
- 0xdb, 0xaa, 0x22, 0xa2, 0xfd, 0xad, 0xd9, 0xb7, 0x54, 0x53, 0x25, 0xfc,
- 0xff, 0xc6, 0xec, 0x0b, 0x16, 0x8c, 0xc3, 0xe5, 0x8e, 0x37, 0xbf, 0xfd,
- 0x18, 0x76, 0x84, 0x66, 0x6b, 0x76, 0x6d, 0xd5, 0x13, 0x39, 0x7f, 0xfa,
- 0x30, 0xed, 0x08, 0xcc, 0xd6, 0xec, 0xdb, 0xaa, 0x28, 0xd2, 0xb6, 0x4e,
+ 0x9e, 0x82, 0x58, 0xa9, 0x64, 0xae, 0xec, 0x51, 0x90, 0xa2, 0xdc, 0x87,
+ 0xf3, 0xbe, 0xad, 0x19, 0xe8, 0x0d, 0x08, 0xbc, 0x50, 0x88, 0x08, 0xc2,
+ 0xfc, 0xfc, 0xe6, 0x47, 0xac, 0x5f, 0xf8, 0x73, 0x27, 0xce, 0x09, 0xba,
+ 0x58, 0xbf, 0xfe, 0x10, 0x7e, 0x29, 0x03, 0x78, 0x01, 0x94, 0x16, 0x2a,
+ 0x08, 0xbc, 0x72, 0xbf, 0x1f, 0xdf, 0xb6, 0x30, 0x1d, 0x01, 0x62, 0xfd,
+ 0xef, 0x61, 0x1d, 0x62, 0xff, 0xe6, 0x04, 0xff, 0x07, 0x3c, 0x90, 0x2c,
+ 0x5f, 0xff, 0xd9, 0xcc, 0x2d, 0x4c, 0x1c, 0xf9, 0xd4, 0x22, 0x12, 0xc5,
+ 0xff, 0xdd, 0x43, 0xdf, 0x63, 0xe6, 0xf3, 0xc5, 0x8a, 0x94, 0x51, 0x89,
+ 0x72, 0xff, 0x48, 0x5d, 0x79, 0xe4, 0xd5, 0x8a, 0x94, 0xe4, 0xdc, 0xb5,
+ 0x8a, 0x0a, 0x1c, 0xde, 0x22, 0xbf, 0xf8, 0x5b, 0x7d, 0xc7, 0x91, 0xbc,
+ 0x6f, 0xdf, 0x3b, 0xd5, 0x8b, 0x7d, 0x62, 0x88, 0xfb, 0x82, 0x5c, 0xbf,
+ 0xfd, 0x25, 0xb8, 0x7a, 0x60, 0x3f, 0xbf, 0x2b, 0x17, 0xcd, 0xb3, 0x12,
+ 0xc5, 0xfb, 0xdf, 0xc0, 0x32, 0xc5, 0x74, 0x79, 0x44, 0x45, 0x7f, 0x1c,
+ 0xcf, 0xe0, 0x19, 0x62, 0xfe, 0x0b, 0x99, 0x85, 0xb2, 0xc5, 0xf0, 0x7f,
+ 0x7f, 0x2c, 0x54, 0xa2, 0x93, 0x08, 0x9c, 0xbf, 0x85, 0xf7, 0xf6, 0xb0,
+ 0x85, 0x3a, 0x58, 0xbc, 0x03, 0x20, 0xb1, 0x7f, 0xcd, 0xcc, 0x72, 0x6f,
+ 0x71, 0x62, 0xff, 0x09, 0x83, 0xe0, 0x4d, 0xd2, 0xc5, 0xe9, 0xce, 0x8d,
+ 0x3e, 0xe2, 0x37, 0xbe, 0x9e, 0x4f, 0x65, 0x8b, 0xff, 0xa4, 0x9b, 0xd0,
+ 0x93, 0x58, 0x2f, 0x2c, 0x54, 0x6c, 0x9a, 0xb4, 0x96, 0xea, 0x11, 0xbf,
+ 0x33, 0x11, 0x25, 0xe3, 0x1b, 0x75, 0x8a, 0x95, 0xdd, 0xa8, 0x47, 0x85,
+ 0xbc, 0x2e, 0x80, 0x45, 0xc8, 0xce, 0x7d, 0x1c, 0x87, 0x72, 0xa5, 0xf8,
+ 0x33, 0x9d, 0xe3, 0xd6, 0x2f, 0xd8, 0x5e, 0x73, 0xac, 0x54, 0x0f, 0x50,
+ 0xe5, 0xb6, 0xe2, 0xc5, 0xcd, 0xc5, 0x8a, 0xc3, 0x52, 0xc2, 0x57, 0xb9,
+ 0x30, 0x58, 0xbe, 0x9d, 0x4e, 0xeb, 0x15, 0x87, 0x80, 0x43, 0xb7, 0xbe,
+ 0xe1, 0xac, 0x58, 0x35, 0x8a, 0x58, 0xa1, 0x17, 0xe1, 0x89, 0xd6, 0x8f,
+ 0x78, 0x23, 0xdb, 0xdf, 0x10, 0xd6, 0x2f, 0xe8, 0x73, 0xcf, 0x3d, 0x2c,
+ 0x5f, 0x1c, 0x39, 0x25, 0x8b, 0xe7, 0x1e, 0x1d, 0x62, 0xf9, 0x98, 0x80,
+ 0xb1, 0x77, 0xbc, 0xb1, 0x60, 0xa4, 0xf6, 0xcd, 0x22, 0x11, 0x0d, 0x2c,
+ 0x5c, 0x23, 0xac, 0x5f, 0xe0, 0x9a, 0x2c, 0x84, 0xc7, 0xac, 0x5f, 0xbb,
+ 0x85, 0x13, 0xc4, 0xb1, 0x4e, 0x8c, 0x08, 0x8d, 0xbe, 0x19, 0xc1, 0x81,
+ 0x1c, 0x5f, 0xfb, 0x07, 0xa9, 0xf3, 0xee, 0xe3, 0x58, 0xbf, 0xe7, 0x3f,
+ 0xfa, 0x68, 0xff, 0x71, 0x62, 0xfe, 0xdd, 0xbf, 0xfc, 0x1a, 0xc5, 0x49,
+ 0xf6, 0x88, 0xfa, 0xf0, 0x82, 0xf2, 0xc5, 0xe0, 0x98, 0x25, 0x8b, 0x01,
+ 0x62, 0xa4, 0xd8, 0x86, 0x3f, 0x7d, 0xee, 0x08, 0x6b, 0x17, 0xe7, 0xea,
+ 0x1e, 0xdd, 0x62, 0xff, 0x4b, 0x6b, 0xe1, 0x30, 0xd2, 0x2e, 0x08, 0x24,
+ 0x8a, 0x19, 0xe7, 0x04, 0x69, 0x73, 0xc7, 0xa4, 0x46, 0x1a, 0x3a, 0x02,
+ 0x32, 0x7d, 0x09, 0xcb, 0xf6, 0xef, 0xcf, 0xba, 0xc5, 0xff, 0x48, 0x3f,
+ 0x3c, 0x26, 0x89, 0x62, 0xfe, 0x99, 0x29, 0x04, 0xac, 0x57, 0x48, 0x8d,
+ 0x22, 0x9f, 0x1c, 0xde, 0x3c, 0x9d, 0x62, 0xf4, 0x05, 0xe5, 0x8a, 0x93,
+ 0x76, 0x21, 0xda, 0x95, 0xe8, 0xbd, 0x92, 0xc6, 0xbf, 0x8f, 0xdb, 0x91,
+ 0xf4, 0x3c, 0xe5, 0xf1, 0x46, 0x7d, 0xa4, 0xa3, 0xc2, 0xb3, 0xe4, 0x20,
+ 0x50, 0x22, 0x1e, 0x43, 0xb7, 0xd0, 0xb5, 0x8e, 0x6b, 0xbf, 0xff, 0xfb,
+ 0xbe, 0xfb, 0x6d, 0xc8, 0xd7, 0xb4, 0x69, 0xde, 0x6a, 0x22, 0xf6, 0x0c,
+ 0xc3, 0x3f, 0x1c, 0xb1, 0x7c, 0x43, 0xfb, 0x2c, 0x5d, 0x07, 0x58, 0xbd,
+ 0x8d, 0x1e, 0xb1, 0x7b, 0x58, 0x35, 0x8a, 0x8d, 0x13, 0x0c, 0xc8, 0x4b,
+ 0xb9, 0x16, 0x85, 0xfb, 0x0f, 0xde, 0xfc, 0xe9, 0x62, 0xef, 0x71, 0x62,
+ 0xfc, 0x7d, 0x6a, 0x76, 0x58, 0xb8, 0x05, 0x27, 0x85, 0x83, 0x17, 0xf8,
+ 0xb3, 0xc5, 0x3d, 0x41, 0x62, 0xfa, 0x48, 0x5c, 0x58, 0xac, 0x44, 0x03,
+ 0x15, 0xf0, 0xce, 0xfd, 0xd7, 0x27, 0x46, 0xac, 0x5c, 0x17, 0x17, 0x58,
+ 0x81, 0x6c, 0x58, 0xbe, 0x8b, 0x33, 0x75, 0x8a, 0xc3, 0xdb, 0xf1, 0x30,
+ 0x42, 0x35, 0xb2, 0x2d, 0x7a, 0x84, 0x35, 0xf7, 0x50, 0xef, 0x7a, 0x58,
+ 0xbd, 0xc3, 0x20, 0xb1, 0x7f, 0xfe, 0x18, 0x9b, 0x7f, 0xb7, 0x26, 0x3f,
+ 0x30, 0x8d, 0x58, 0xae, 0x8f, 0xe3, 0x43, 0xf6, 0xfa, 0xc5, 0xff, 0xb8,
+ 0x32, 0x91, 0xfe, 0x7d, 0xc5, 0x8a, 0x93, 0xd1, 0xe0, 0x95, 0x4a, 0x6c,
+ 0x58, 0x54, 0xd0, 0xa3, 0x13, 0xa5, 0xef, 0xf7, 0x0d, 0x62, 0xff, 0xff,
+ 0xb0, 0x2c, 0x87, 0xf1, 0xe1, 0xce, 0xb8, 0xfe, 0x72, 0xd9, 0x62, 0xef,
+ 0xc4, 0xb1, 0x7f, 0xbe, 0xed, 0x0f, 0x3e, 0xcb, 0x17, 0xce, 0x5e, 0x95,
+ 0x8b, 0xfe, 0x7d, 0x30, 0x3b, 0xbd, 0x9f, 0x58, 0xaf, 0x9e, 0xef, 0x88,
+ 0x6f, 0xf9, 0xc2, 0x2c, 0xf3, 0x88, 0x0b, 0x17, 0xce, 0x41, 0xf1, 0x62,
+ 0xf8, 0xa0, 0xe7, 0x58, 0xb7, 0xa4, 0xf1, 0x58, 0x8e, 0xfc, 0x77, 0x89,
+ 0xc2, 0x58, 0xa9, 0x3d, 0x07, 0x26, 0xbe, 0xd0, 0xe7, 0x65, 0x8b, 0x8f,
+ 0x1c, 0xb1, 0x4e, 0x6f, 0xd8, 0x92, 0xfe, 0x2c, 0xf7, 0x24, 0x0b, 0x17,
+ 0xef, 0xb1, 0xdf, 0x8b, 0x17, 0xef, 0x70, 0x9c, 0xd5, 0x8a, 0x81, 0xe8,
+ 0xe8, 0xa2, 0xbe, 0x8a, 0x06, 0x7e, 0xb9, 0xc2, 0x58, 0xb8, 0x3d, 0x96,
+ 0x2f, 0x75, 0xcc, 0x23, 0x65, 0xe1, 0x8b, 0xf0, 0x5a, 0xd3, 0x04, 0xb1,
+ 0x74, 0x9d, 0x62, 0xff, 0xff, 0xf7, 0x03, 0xd4, 0xfe, 0x70, 0xee, 0x50,
+ 0x97, 0xfb, 0xee, 0x4f, 0xd9, 0x62, 0xff, 0xff, 0x7f, 0x0a, 0x41, 0xc1,
+ 0x36, 0x6f, 0x24, 0x26, 0x82, 0xc5, 0x3a, 0x35, 0xfc, 0xf1, 0x7c, 0x17,
+ 0xb3, 0xe3, 0x4c, 0x43, 0x90, 0xee, 0xa9, 0x4e, 0xbb, 0x0c, 0x9a, 0x33,
+ 0xbb, 0xf1, 0xb9, 0xac, 0xf2, 0xc5, 0xfe, 0x6f, 0x16, 0x6c, 0x1c, 0x16,
+ 0x2f, 0xfe, 0xc3, 0x70, 0x5a, 0x61, 0xcf, 0xe5, 0x62, 0x9d, 0x14, 0x44,
+ 0x53, 0xc3, 0x5b, 0x81, 0xc5, 0x8b, 0xff, 0x13, 0x05, 0xbf, 0xdf, 0xb3,
+ 0xe9, 0x62, 0xf0, 0xff, 0x2b, 0x14, 0x33, 0xdf, 0x0d, 0x0a, 0xbb, 0xd6,
+ 0x52, 0x2c, 0xc3, 0x7e, 0x12, 0x91, 0x46, 0x81, 0x84, 0x3b, 0xb4, 0x74,
+ 0x32, 0xf0, 0x91, 0x8f, 0x22, 0xd4, 0x33, 0xbe, 0xbe, 0xd0, 0xbf, 0x29,
+ 0x40, 0x5c, 0x86, 0xb7, 0x8b, 0x84, 0xef, 0x7a, 0x26, 0xd2, 0xc5, 0xff,
+ 0x7b, 0xf8, 0x01, 0x4f, 0x41, 0xac, 0x5f, 0xff, 0xf9, 0x9f, 0xd3, 0xf2,
+ 0xcf, 0x7d, 0xc3, 0x84, 0xf6, 0x72, 0x02, 0xc5, 0xfb, 0x7c, 0x3c, 0xf1,
+ 0x62, 0xf0, 0x88, 0x6b, 0x17, 0xff, 0x63, 0xec, 0x79, 0x67, 0x83, 0x71,
+ 0x62, 0xff, 0x30, 0x03, 0x8e, 0x62, 0x02, 0xc5, 0x7c, 0xfe, 0x89, 0x0e,
+ 0xfe, 0x7f, 0x70, 0x78, 0x4b, 0x17, 0xa7, 0xa8, 0x2c, 0x5f, 0xcf, 0xee,
+ 0x61, 0xb1, 0x40, 0xf2, 0xf4, 0x5b, 0x7f, 0xfb, 0x3f, 0x85, 0xee, 0x67,
+ 0x62, 0x9e, 0x96, 0x2a, 0x55, 0x41, 0xf4, 0x3d, 0xf3, 0xc6, 0x6c, 0x01,
+ 0x4f, 0xa1, 0x2f, 0xd9, 0xb0, 0x24, 0x6b, 0x9f, 0xa5, 0x8b, 0xd2, 0x5e,
+ 0x58, 0xb9, 0xf4, 0xb1, 0x5b, 0x1b, 0x3c, 0x1c, 0xbf, 0x7f, 0xac, 0x14,
+ 0x4b, 0x17, 0xfa, 0x0e, 0x7f, 0xf4, 0xd1, 0xeb, 0x17, 0xf4, 0x8e, 0x3b,
+ 0x35, 0x2b, 0x17, 0xf1, 0x60, 0xff, 0x3d, 0x96, 0x2b, 0xe7, 0xbf, 0xdc,
+ 0x61, 0x7c, 0xda, 0x98, 0x2c, 0x5f, 0x75, 0x82, 0x89, 0x62, 0xff, 0xc2,
+ 0x9d, 0x1a, 0xc1, 0xf9, 0xe0, 0xb1, 0x7f, 0xcd, 0xd1, 0x9d, 0x73, 0x08,
+ 0xd5, 0x8a, 0xd9, 0x3c, 0xd1, 0x90, 0xf4, 0x56, 0xf0, 0x97, 0x39, 0x2f,
+ 0xc8, 0x88, 0x97, 0xc8, 0x37, 0xdf, 0x8f, 0x73, 0xac, 0x5e, 0x29, 0x02,
+ 0xc5, 0x18, 0x78, 0x5c, 0x26, 0xbf, 0xbc, 0xc7, 0x3c, 0x9d, 0x62, 0xc7,
+ 0xc3, 0xd1, 0xe8, 0x8e, 0xff, 0x75, 0xfc, 0x8b, 0xef, 0xa5, 0x8b, 0xff,
+ 0xf8, 0x9b, 0xcc, 0x78, 0x3f, 0xb3, 0xaf, 0x7c, 0x3e, 0x2c, 0x54, 0xa2,
+ 0xef, 0x0a, 0x18, 0xda, 0xfc, 0xc5, 0x9d, 0x4a, 0xc5, 0xfe, 0xfc, 0x9f,
+ 0x7f, 0xbc, 0x4b, 0x16, 0x98, 0xd8, 0xf7, 0x7a, 0x27, 0xbe, 0x6e, 0x74,
+ 0xcb, 0x17, 0xfd, 0x0e, 0x7d, 0xb7, 0x92, 0x1a, 0xc5, 0xbc, 0xb1, 0x78,
+ 0x1e, 0xfa, 0xc5, 0xf8, 0xcf, 0x1a, 0xfc, 0x58, 0xa8, 0x22, 0xe3, 0xa2,
+ 0x36, 0x3a, 0x00, 0x97, 0x87, 0xaf, 0xff, 0xfd, 0xac, 0x1f, 0x1a, 0x3d,
+ 0xfa, 0xfb, 0x3c, 0x24, 0x7f, 0x11, 0xab, 0x16, 0x02, 0xc5, 0x32, 0x33,
+ 0x78, 0x94, 0x1b, 0x8d, 0xc0, 0x65, 0x8b, 0xed, 0xf1, 0x8e, 0xb1, 0x52,
+ 0x6e, 0x9c, 0x5e, 0xfd, 0xcf, 0xe0, 0x19, 0x62, 0xa5, 0x7d, 0x12, 0x0f,
+ 0x59, 0x28, 0x61, 0xe3, 0xc5, 0xd4, 0x22, 0x9a, 0x3b, 0x22, 0x6a, 0xe0,
+ 0xfd, 0xee, 0x3e, 0xeb, 0x17, 0xd9, 0x22, 0xef, 0xd6, 0x2f, 0x68, 0xf1,
+ 0xcb, 0x17, 0xe1, 0xf3, 0x8e, 0x75, 0x8a, 0xd8, 0xf2, 0x88, 0x86, 0xfd,
+ 0xbb, 0x6d, 0x81, 0x2c, 0x5f, 0xa7, 0x43, 0xc2, 0x58, 0xa1, 0xa3, 0x97,
+ 0x1c, 0x48, 0x8b, 0xc5, 0x77, 0xe9, 0x8e, 0x7f, 0x89, 0x62, 0xec, 0xdd,
+ 0x62, 0xe1, 0xee, 0xb1, 0x7c, 0x45, 0x86, 0xac, 0x56, 0x1b, 0xb1, 0x0c,
+ 0xd8, 0x0b, 0x17, 0xb4, 0xff, 0x58, 0xa8, 0x22, 0x8b, 0x75, 0x37, 0x20,
+ 0x21, 0x2b, 0xef, 0xe0, 0x19, 0x62, 0xfb, 0xbb, 0xce, 0x6a, 0xc5, 0xd2,
+ 0x1a, 0xc5, 0x44, 0x7c, 0x3c, 0x22, 0x8e, 0x27, 0xbf, 0xfa, 0x41, 0x3f,
+ 0x39, 0x31, 0xbf, 0x75, 0x8b, 0x46, 0xcb, 0x17, 0xfe, 0xcd, 0x67, 0x83,
+ 0xcf, 0xb0, 0x16, 0x2f, 0xff, 0xb0, 0x8d, 0xcd, 0x6d, 0x21, 0x67, 0xf0,
+ 0x96, 0x2f, 0xd2, 0x41, 0x37, 0x4b, 0x15, 0x87, 0xf3, 0xf5, 0x0b, 0xff,
+ 0x14, 0x53, 0x85, 0xb6, 0x75, 0xe5, 0x8b, 0xf7, 0xb8, 0x7d, 0x4a, 0xc5,
+ 0x41, 0x34, 0x21, 0xc2, 0xe1, 0x88, 0x49, 0x02, 0xff, 0x6b, 0xcd, 0xa6,
+ 0x8e, 0x95, 0x8b, 0xcc, 0x40, 0x58, 0xa3, 0x4f, 0x4b, 0x73, 0x6b, 0xf7,
+ 0xb9, 0xe7, 0xd9, 0x62, 0xa4, 0xf3, 0x98, 0x92, 0xff, 0xbf, 0x3b, 0xc8,
+ 0x18, 0x80, 0xb1, 0x7f, 0xf4, 0xb9, 0x4f, 0x9f, 0x4f, 0xe1, 0x2c, 0x5f,
+ 0xc0, 0x33, 0x38, 0xc4, 0xb1, 0x7f, 0xf0, 0xa4, 0x98, 0xd8, 0x8a, 0x41,
+ 0xc5, 0x8a, 0x1a, 0x3b, 0xbe, 0x72, 0x48, 0x5e, 0x2e, 0xbf, 0x77, 0xa3,
+ 0x72, 0xdd, 0x62, 0x9c, 0xfa, 0x98, 0xf2, 0xf8, 0x26, 0x93, 0xac, 0x5f,
+ 0xdc, 0x11, 0xe7, 0x06, 0xb1, 0x7e, 0x6e, 0x6c, 0xfa, 0x58, 0xbe, 0xd3,
+ 0x8b, 0x65, 0xc9, 0xea, 0x5e, 0xdc, 0x5b, 0x2e, 0x4f, 0x52, 0xff, 0xd8,
+ 0xfd, 0xb0, 0xb0, 0x6d, 0x05, 0xc9, 0xea, 0x5f, 0x98, 0xba, 0x84, 0x60,
+ 0xd1, 0x53, 0xc3, 0x10, 0x8b, 0x6e, 0x6e, 0xe5, 0x8a, 0x1a, 0x67, 0xa7,
+ 0x86, 0x91, 0x28, 0xde, 0x73, 0xca, 0xc5, 0xfe, 0xda, 0x33, 0x9a, 0x79,
+ 0xf2, 0xc5, 0xdc, 0x75, 0x8b, 0xcc, 0xc4, 0xb1, 0x79, 0xfe, 0x25, 0x8b,
+ 0x1b, 0xc3, 0xcf, 0xf0, 0xbc, 0x70, 0xdd, 0xe2, 0x16, 0xcb, 0x14, 0xc7,
+ 0xaf, 0xe3, 0x9a, 0xc5, 0x57, 0x6f, 0x1b, 0x5e, 0x8d, 0x58, 0x70, 0xa1,
+ 0xbd, 0x51, 0xa3, 0x28, 0x8a, 0x63, 0x03, 0x19, 0xde, 0x43, 0x35, 0xe1,
+ 0x3b, 0xa3, 0x33, 0xa2, 0x34, 0x6b, 0x25, 0x0e, 0x1e, 0x46, 0xf1, 0xe2,
+ 0x01, 0x4a, 0xde, 0xb0, 0x4b, 0x17, 0xee, 0x7f, 0x42, 0xec, 0xb1, 0x7f,
+ 0xf1, 0x7d, 0xb8, 0x58, 0x69, 0xb9, 0x1e, 0xb1, 0x7f, 0x31, 0xff, 0x38,
+ 0x35, 0x8a, 0xc3, 0xf5, 0x24, 0x8b, 0xbb, 0xc8, 0xd1, 0x62, 0xfd, 0x38,
+ 0x5e, 0xe2, 0xc5, 0xe7, 0x9d, 0x2c, 0x5b, 0xcb, 0x15, 0x1b, 0x1f, 0xb9,
+ 0xc8, 0xbe, 0x4f, 0xe1, 0xcb, 0xff, 0xb4, 0xe7, 0x98, 0xf2, 0xc3, 0xf5,
+ 0x2b, 0x15, 0x04, 0x44, 0x44, 0x83, 0x7c, 0xd0, 0x98, 0xf5, 0x8b, 0xc4,
+ 0xc3, 0x58, 0xbd, 0xcd, 0x99, 0x62, 0x9c, 0xdd, 0x06, 0x39, 0x7f, 0xbc,
+ 0xfa, 0x9d, 0xf3, 0xb2, 0xc5, 0xc7, 0x75, 0x8b, 0xfa, 0x46, 0xfd, 0xa4,
+ 0x6b, 0x17, 0xef, 0x49, 0x4c, 0x4b, 0x15, 0x28, 0xa4, 0xd8, 0xd8, 0x62,
+ 0xec, 0x5f, 0x7e, 0xc3, 0xe9, 0xba, 0x58, 0xad, 0x93, 0x89, 0x1a, 0xf9,
+ 0x43, 0x17, 0x87, 0x97, 0xe8, 0x67, 0x69, 0x82, 0xc5, 0xf6, 0xba, 0x90,
+ 0x96, 0x2f, 0x66, 0xa5, 0x62, 0xfe, 0xd0, 0xf0, 0xd0, 0xce, 0xb1, 0x73,
+ 0x47, 0xac, 0x5e, 0xed, 0x83, 0x58, 0xbf, 0x9e, 0x7d, 0x03, 0x46, 0xb1,
+ 0x78, 0x9f, 0x65, 0x8a, 0x82, 0xe6, 0x8e, 0xf0, 0xa1, 0xea, 0x31, 0xf7,
+ 0x8e, 0xb7, 0x48, 0x67, 0x2a, 0xf9, 0x2b, 0x0e, 0x11, 0x88, 0x86, 0x82,
+ 0x1f, 0xee, 0x2f, 0xb0, 0x4b, 0x17, 0xf9, 0xc2, 0x97, 0x1e, 0x1d, 0x62,
+ 0xcf, 0x87, 0x8d, 0x10, 0x9d, 0xf7, 0xdf, 0xa8, 0x2c, 0x5e, 0x26, 0x82,
+ 0xc5, 0xa1, 0x27, 0x81, 0x84, 0x97, 0xfe, 0x29, 0xdf, 0xf3, 0xdb, 0x41,
+ 0xf1, 0x62, 0xf3, 0x6b, 0x65, 0x8a, 0x58, 0xb1, 0x6e, 0x6a, 0xa2, 0x1e,
+ 0xbf, 0xd0, 0xe7, 0x50, 0xc1, 0x1a, 0xb1, 0x7d, 0x16, 0xa7, 0x65, 0x8b,
+ 0x7d, 0x61, 0x8d, 0x2d, 0xfc, 0xfd, 0x73, 0xf9, 0xba, 0xc5, 0xf7, 0xf1,
+ 0xe2, 0x58, 0xbd, 0x92, 0x35, 0x8b, 0xfa, 0x7b, 0x67, 0xff, 0x2b, 0x17,
+ 0xec, 0xf7, 0x32, 0x25, 0x8f, 0x9a, 0xfb, 0xff, 0xff, 0xec, 0xeb, 0x8f,
+ 0x81, 0x19, 0x9d, 0x43, 0x8f, 0xee, 0x3f, 0x43, 0x18, 0xb6, 0x58, 0xbf,
+ 0xf4, 0xee, 0x59, 0x17, 0xc5, 0xa8, 0x96, 0x2f, 0xff, 0xcf, 0xae, 0x78,
+ 0xd9, 0xea, 0x1c, 0xea, 0x12, 0x6a, 0xc5, 0x2c, 0x53, 0xa6, 0x5a, 0x50,
+ 0x84, 0xe2, 0x17, 0x72, 0xdd, 0xfe, 0x92, 0x37, 0xbb, 0xd9, 0xf5, 0x8b,
+ 0xff, 0x67, 0x46, 0xb7, 0x30, 0x9c, 0xd5, 0x8b, 0xff, 0xe2, 0x19, 0x81,
+ 0xf9, 0xf8, 0xce, 0x42, 0x82, 0xc5, 0x4a, 0x24, 0x5d, 0x02, 0xf9, 0xb6,
+ 0xfb, 0xac, 0x50, 0xd7, 0x19, 0xb1, 0xb7, 0xa2, 0x87, 0x5c, 0x88, 0x87,
+ 0x46, 0x07, 0x23, 0x24, 0xbf, 0x46, 0xcc, 0x24, 0x4e, 0xd0, 0xc8, 0x8e,
+ 0x21, 0xbc, 0x2d, 0x41, 0x62, 0xff, 0xc7, 0x61, 0xea, 0x7d, 0xfc, 0x1a,
+ 0xc5, 0xfc, 0xde, 0x00, 0x65, 0x05, 0x8b, 0xf3, 0x78, 0x38, 0xe6, 0x58,
+ 0xbf, 0x6d, 0xbf, 0xe7, 0x4b, 0x17, 0xf9, 0x98, 0x20, 0x37, 0xb8, 0xb1,
+ 0x70, 0x7c, 0x58, 0xa1, 0x9e, 0x6f, 0xcd, 0x2f, 0x85, 0x14, 0xf4, 0xb1,
+ 0x7b, 0x1e, 0x25, 0x8b, 0xff, 0x0e, 0x7c, 0xd0, 0xce, 0xcc, 0x35, 0x8b,
+ 0x9f, 0x4b, 0x17, 0x3e, 0xcb, 0x1b, 0x16, 0xf7, 0xe9, 0x22, 0x11, 0xd6,
+ 0x2d, 0x0f, 0x1e, 0x78, 0x65, 0x14, 0x62, 0xa6, 0x39, 0x1e, 0xd8, 0xfe,
+ 0x05, 0xf8, 0x58, 0x6b, 0xc6, 0xe4, 0x51, 0x12, 0x9c, 0x75, 0xa1, 0x4d,
+ 0x77, 0x31, 0x62, 0xff, 0xb3, 0x5b, 0x3f, 0x3f, 0x9c, 0x58, 0xbf, 0x3c,
+ 0x60, 0x41, 0x04, 0x91, 0x7f, 0xe3, 0x5b, 0xa3, 0x3e, 0xc7, 0x7e, 0x2c,
+ 0x5a, 0x60, 0x7e, 0x27, 0x2f, 0xbb, 0x3e, 0xb1, 0x76, 0x77, 0xeb, 0x17,
+ 0x60, 0xd6, 0x2f, 0xde, 0x00, 0x65, 0x05, 0x8a, 0x19, 0xee, 0x9a, 0x38,
+ 0xc2, 0xf7, 0xe6, 0xd6, 0xf3, 0xe5, 0x8b, 0x9f, 0x4b, 0x15, 0xf3, 0xc0,
+ 0x11, 0x4d, 0xb7, 0x58, 0xb9, 0x86, 0xb1, 0x7f, 0x69, 0xb9, 0xf6, 0x82,
+ 0xc5, 0xba, 0x58, 0xb9, 0xc2, 0x58, 0xb8, 0x30, 0x2c, 0x54, 0x46, 0xc4,
+ 0x03, 0x17, 0xa0, 0xc3, 0x58, 0xb8, 0x20, 0x96, 0x2a, 0x08, 0xe2, 0xc1,
+ 0x7d, 0xcb, 0x9d, 0x13, 0x84, 0x41, 0x0e, 0xdc, 0x18, 0x12, 0x23, 0x0f,
+ 0x5e, 0x99, 0x37, 0x9f, 0x46, 0x99, 0x7f, 0x0b, 0xa8, 0x79, 0xfa, 0x58,
+ 0xbf, 0xd8, 0x77, 0x1e, 0xc2, 0xe2, 0xc5, 0xff, 0xfc, 0x08, 0xec, 0xd4,
+ 0xf9, 0xf7, 0x71, 0xed, 0x25, 0x2b, 0x17, 0xb3, 0xaf, 0x2c, 0x5b, 0x08,
+ 0xff, 0x38, 0xbd, 0x5f, 0x46, 0xbf, 0x21, 0x63, 0x7f, 0xce, 0x3c, 0x3b,
+ 0xc4, 0xe1, 0x2c, 0x5f, 0xff, 0x4b, 0xf4, 0x0d, 0x60, 0xe7, 0x4f, 0xd0,
+ 0x16, 0x2f, 0x8d, 0xfb, 0x41, 0x62, 0xf4, 0x3f, 0x23, 0x3f, 0x57, 0x51,
+ 0xbf, 0xff, 0xdf, 0x67, 0xf4, 0xc0, 0x43, 0xc0, 0xf3, 0x5e, 0x17, 0xd6,
+ 0x2c, 0xcb, 0x15, 0x27, 0xe7, 0xc6, 0x2b, 0xff, 0xcc, 0x3c, 0xc2, 0x37,
+ 0x9c, 0xc2, 0x02, 0xc5, 0xf7, 0xc4, 0xc6, 0xca, 0x77, 0xd9, 0x0a, 0xfd,
+ 0x42, 0x94, 0xe4, 0x37, 0x8a, 0x7e, 0xb1, 0x7f, 0xff, 0x41, 0xb9, 0xc9,
+ 0xcd, 0x85, 0x01, 0xe8, 0x98, 0x25, 0x8b, 0xff, 0xf3, 0xc1, 0xfc, 0x52,
+ 0x01, 0x93, 0x72, 0x11, 0x2c, 0x5f, 0xf7, 0xb4, 0x28, 0x75, 0x0c, 0xf2,
+ 0xc5, 0xff, 0x67, 0x3e, 0xd0, 0x1e, 0xbb, 0xf5, 0x8a, 0x73, 0xfb, 0x23,
+ 0xca, 0x1a, 0x78, 0xe6, 0xaf, 0x38, 0xe0, 0x17, 0x7b, 0x43, 0x42, 0xfe,
+ 0xd3, 0x42, 0x74, 0x05, 0x8b, 0xff, 0xfd, 0xf6, 0x87, 0xe5, 0xb5, 0xce,
+ 0x67, 0xdf, 0x82, 0xd9, 0x62, 0xd9, 0xa4, 0x48, 0x7c, 0xba, 0xff, 0xfb,
+ 0x52, 0xd0, 0xd4, 0xfd, 0x9f, 0x7c, 0x25, 0x8a, 0x94, 0xd6, 0x21, 0x0e,
+ 0x27, 0x28, 0xaf, 0xaf, 0x20, 0xf2, 0x30, 0x8f, 0x4e, 0x82, 0xdf, 0xc7,
+ 0x68, 0x6d, 0x14, 0x72, 0xc5, 0xf1, 0xf7, 0x84, 0xac, 0x5e, 0x84, 0x7c,
+ 0x16, 0x2f, 0x7d, 0xf8, 0xb1, 0x78, 0x39, 0x25, 0x8a, 0x93, 0xdb, 0x81,
+ 0x0f, 0x87, 0x6f, 0xf6, 0x72, 0x2f, 0xb8, 0x5e, 0x58, 0xbf, 0x6d, 0x98,
+ 0x46, 0xac, 0x54, 0x9e, 0xfb, 0x1b, 0x5f, 0xce, 0x7d, 0xf0, 0xb7, 0x58,
+ 0xbe, 0x6d, 0xb9, 0xf5, 0x8a, 0xd1, 0xe9, 0xf0, 0xbe, 0x8c, 0x65, 0x7f,
+ 0x41, 0xd0, 0x6d, 0xfd, 0x47, 0x36, 0xf3, 0xcd, 0x47, 0x41, 0x63, 0x42,
+ 0x7f, 0xe4, 0x23, 0x7c, 0xe7, 0x6e, 0xf1, 0x62, 0xf3, 0x31, 0xd6, 0x2f,
+ 0x7d, 0xfc, 0xb1, 0x6e, 0xdd, 0xe9, 0xe8, 0x7c, 0x5c, 0x31, 0xcb, 0xfc,
+ 0xc7, 0x79, 0x3e, 0x12, 0xc5, 0xfd, 0xf9, 0xd7, 0xb3, 0x75, 0x8a, 0x19,
+ 0xf0, 0x78, 0xc6, 0xfd, 0x08, 0xe7, 0xf8, 0x96, 0x2b, 0x0f, 0x39, 0x88,
+ 0xac, 0xcb, 0x17, 0x4f, 0x16, 0x28, 0xd3, 0x50, 0xc2, 0x37, 0xd8, 0x42,
+ 0x89, 0x62, 0xf9, 0xfb, 0x48, 0xd6, 0x2f, 0xff, 0xdc, 0x6f, 0x70, 0xb3,
+ 0x93, 0xd0, 0x3d, 0x9c, 0x58, 0xae, 0x91, 0x3a, 0x72, 0x3f, 0x12, 0x5f,
+ 0xf6, 0xff, 0x76, 0xdf, 0x9e, 0x75, 0x8b, 0xdc, 0x0c, 0xeb, 0x16, 0x61,
+ 0x9e, 0xd7, 0x8e, 0xee, 0xd4, 0x4b, 0x16, 0x3a, 0xc5, 0xda, 0x95, 0x8a,
+ 0x93, 0xc2, 0x18, 0xce, 0x09, 0x54, 0x68, 0xdf, 0x38, 0xcc, 0xe7, 0x24,
+ 0x23, 0x02, 0x1b, 0x3e, 0x4e, 0x46, 0x3c, 0xb1, 0xad, 0x42, 0x50, 0xe2,
+ 0xff, 0x85, 0x5b, 0x52, 0xc9, 0x41, 0x0f, 0x12, 0x87, 0x5f, 0x92, 0x05,
+ 0x0b, 0xe0, 0xa1, 0x17, 0x1c, 0xd3, 0x7a, 0x3d, 0xa5, 0x62, 0xf9, 0xa1,
+ 0xa9, 0x58, 0xb3, 0x2c, 0x53, 0x9e, 0x91, 0x0f, 0xf0, 0x8a, 0xff, 0xff,
+ 0xff, 0xff, 0x47, 0x61, 0xda, 0x0f, 0xc0, 0x60, 0x3e, 0xcf, 0x09, 0x1f,
+ 0xc4, 0x6c, 0xb9, 0x37, 0xa6, 0x0d, 0xdb, 0xed, 0x05, 0x8b, 0xf7, 0xdf,
+ 0xb6, 0x6c, 0xb1, 0x4e, 0x8e, 0x9e, 0x42, 0xfa, 0xff, 0xfa, 0x27, 0x93,
+ 0x04, 0x19, 0x30, 0xff, 0x9e, 0x58, 0xbf, 0xc2, 0xf7, 0xf3, 0x4f, 0xc5,
+ 0x8a, 0x74, 0x43, 0x7d, 0x4a, 0xfe, 0xfb, 0x98, 0x40, 0x12, 0xc5, 0xf6,
+ 0x61, 0xe5, 0x62, 0xe6, 0x89, 0x62, 0xfd, 0x87, 0x72, 0x02, 0xc5, 0x70,
+ 0xdf, 0x84, 0x31, 0x70, 0xa5, 0x62, 0xff, 0xa4, 0xa2, 0x17, 0xdb, 0xf2,
+ 0xb1, 0x7f, 0xa7, 0xec, 0xf0, 0x71, 0xac, 0x56, 0xc8, 0x82, 0x18, 0xb9,
+ 0x1c, 0xdf, 0x1e, 0x7a, 0x82, 0xc5, 0xff, 0xb3, 0xb4, 0x8c, 0xb3, 0xd8,
+ 0x05, 0x8b, 0xb0, 0x96, 0x2d, 0x9d, 0x1e, 0xaf, 0x63, 0xfb, 0xf7, 0xfd,
+ 0x30, 0x3a, 0xc5, 0xc1, 0x81, 0x62, 0x9d, 0x1c, 0xba, 0x79, 0xf9, 0x50,
+ 0x0a, 0x6e, 0xda, 0x0b, 0x16, 0x89, 0x62, 0xa4, 0xd6, 0x06, 0x33, 0x79,
+ 0xc8, 0x6b, 0x17, 0x8b, 0x06, 0xb1, 0x7f, 0xc7, 0xcf, 0x48, 0x04, 0xc0,
+ 0x58, 0xbf, 0xf9, 0xc6, 0xde, 0x7e, 0x64, 0x33, 0xeb, 0x17, 0x37, 0x72,
+ 0xc5, 0xdd, 0x79, 0x62, 0xfd, 0x9b, 0x1c, 0x5f, 0x58, 0xac, 0x3c, 0x32,
+ 0x19, 0xaf, 0xa3, 0x03, 0xc8, 0x7d, 0xcb, 0xb7, 0xf6, 0x6a, 0x7d, 0xcc,
+ 0x58, 0xbf, 0xfe, 0x6e, 0xa1, 0x30, 0xc1, 0xf2, 0x61, 0x24, 0xb1, 0x7f,
+ 0xf7, 0x26, 0x18, 0x3e, 0xec, 0x2c, 0x02, 0xc5, 0x62, 0x3d, 0x5c, 0xcc,
+ 0x8b, 0x7c, 0x9f, 0x7f, 0x71, 0xbe, 0xf2, 0x05, 0x8b, 0xf1, 0x7b, 0x98,
+ 0x4b, 0x17, 0xff, 0x74, 0x0d, 0x33, 0x75, 0x0e, 0x06, 0x75, 0x8b, 0xf6,
+ 0x7b, 0xd9, 0xb2, 0xc5, 0x80, 0xb1, 0x78, 0x32, 0x81, 0x1b, 0xb0, 0xca,
+ 0x6f, 0xff, 0xff, 0x61, 0xaf, 0xf9, 0x3e, 0xd8, 0x16, 0x6b, 0x67, 0xe7,
+ 0xf3, 0xd1, 0xd8, 0xb1, 0x4e, 0x9a, 0xdb, 0x13, 0x82, 0x10, 0x9c, 0x33,
+ 0xbf, 0x69, 0xbb, 0x77, 0x32, 0xc5, 0x4b, 0x24, 0x32, 0x11, 0x8b, 0x0e,
+ 0x15, 0xa6, 0x91, 0x6e, 0x5f, 0xd3, 0x03, 0xc2, 0x93, 0x51, 0x8a, 0x9d,
+ 0xa3, 0xe4, 0x2c, 0x38, 0x01, 0xc2, 0x8f, 0xbb, 0x87, 0x5e, 0x8e, 0x23,
+ 0xb2, 0x0d, 0xfb, 0xbc, 0x8d, 0xa3, 0x78, 0xef, 0x2c, 0x5f, 0xed, 0xbc,
+ 0x7f, 0xe0, 0x19, 0x62, 0xfb, 0x09, 0xcd, 0x58, 0xa8, 0x22, 0x4c, 0xe7,
+ 0x9d, 0x8d, 0x6d, 0xdc, 0xb1, 0x7f, 0xc6, 0x48, 0xdc, 0x9b, 0x46, 0xac,
+ 0x56, 0xe7, 0x9e, 0x01, 0x5b, 0xdc, 0x87, 0xd6, 0x28, 0x8f, 0x07, 0xc4,
+ 0x77, 0xfe, 0x6f, 0xc6, 0x61, 0xd9, 0x8a, 0x0b, 0x17, 0xff, 0xee, 0x13,
+ 0x73, 0xf9, 0x0c, 0xfb, 0xeb, 0xec, 0xb1, 0x7f, 0x8d, 0x2c, 0xff, 0xe7,
+ 0xcb, 0x17, 0x31, 0xab, 0x14, 0xe7, 0x98, 0xc6, 0x97, 0xd9, 0xe7, 0xe2,
+ 0xc5, 0x18, 0x99, 0x17, 0x48, 0x1a, 0x85, 0x01, 0x10, 0x5f, 0x67, 0x5b,
+ 0x76, 0x58, 0xbf, 0x82, 0xe4, 0xfa, 0x46, 0xb1, 0x7b, 0xd1, 0x1d, 0x62,
+ 0xa4, 0xf3, 0xb0, 0xbe, 0xff, 0x70, 0x6c, 0x79, 0xf6, 0xeb, 0x17, 0xf8,
+ 0x78, 0x42, 0x86, 0x71, 0x62, 0xba, 0x3e, 0x82, 0x35, 0xbd, 0xc1, 0x01,
+ 0x62, 0xd8, 0xb1, 0x5d, 0x1a, 0xfe, 0xc3, 0xd7, 0x16, 0xeb, 0x15, 0x26,
+ 0xf1, 0x89, 0x2f, 0xf0, 0x7e, 0x2c, 0xd9, 0xf4, 0xb1, 0x7a, 0x5c, 0x6b,
+ 0x17, 0xff, 0xdb, 0x8d, 0xcb, 0x6e, 0x7b, 0xad, 0xdf, 0xf1, 0x2c, 0x5c,
+ 0x3e, 0x96, 0x2e, 0x2d, 0xf0, 0xfb, 0xcd, 0x56, 0xbe, 0x6e, 0xec, 0x25,
+ 0x8b, 0xcf, 0xc7, 0x58, 0xa6, 0x3e, 0xee, 0x17, 0x78, 0x92, 0xfe, 0xcd,
+ 0xe7, 0xf2, 0x75, 0x8a, 0x95, 0xd7, 0xcc, 0x86, 0x13, 0xc6, 0x87, 0xa4,
+ 0x43, 0xba, 0xb4, 0x22, 0x01, 0x08, 0xd2, 0x1f, 0xe1, 0xa8, 0xa1, 0xf2,
+ 0x11, 0x75, 0xff, 0xa4, 0x30, 0x0a, 0x10, 0x6f, 0x89, 0x62, 0xf6, 0x61,
+ 0xab, 0x17, 0xd0, 0x90, 0x71, 0x62, 0x86, 0x78, 0x18, 0x3b, 0x5b, 0x22,
+ 0x8b, 0xa8, 0x40, 0xdf, 0x78, 0x4c, 0x4b, 0x17, 0xff, 0xe3, 0xc5, 0xa9,
+ 0xfe, 0x7a, 0x60, 0xdd, 0x87, 0x2b, 0x17, 0x66, 0x96, 0x2f, 0xdc, 0x76,
+ 0x63, 0x56, 0x28, 0xc3, 0x7f, 0xd0, 0xbd, 0xfe, 0x92, 0x31, 0xfd, 0xf9,
+ 0x58, 0xbf, 0x0f, 0xf2, 0x01, 0x2c, 0x5d, 0x30, 0x58, 0xb6, 0xa0, 0x78,
+ 0x1a, 0x29, 0xbd, 0xf6, 0x89, 0x62, 0xff, 0xfc, 0xdc, 0xe6, 0x36, 0xfe,
+ 0xfb, 0x1f, 0x59, 0xb2, 0xc5, 0xfe, 0x71, 0xbf, 0x7f, 0x24, 0xeb, 0x15,
+ 0x2a, 0x80, 0x36, 0x84, 0xb8, 0xc8, 0xf1, 0xcf, 0x72, 0x8d, 0x0f, 0x7d,
+ 0x5e, 0xff, 0xf9, 0xcd, 0xc7, 0x3e, 0xa4, 0x5d, 0xfb, 0x7f, 0x8b, 0x17,
+ 0xf9, 0xa1, 0x83, 0xd7, 0x38, 0xb1, 0x7b, 0x03, 0x1a, 0xc5, 0xff, 0x66,
+ 0xdf, 0xc8, 0xbe, 0xe6, 0xac, 0x5f, 0xd9, 0xd0, 0x33, 0xdc, 0x58, 0xbf,
+ 0x49, 0x75, 0x0e, 0x2c, 0x7c, 0xd7, 0xd4, 0xa3, 0x08, 0x87, 0x84, 0xd7,
+ 0x7f, 0xfd, 0x39, 0xcc, 0x2f, 0x7f, 0x06, 0x2f, 0x71, 0x62, 0xe9, 0xfa,
+ 0xc5, 0x11, 0xf3, 0x71, 0x3e, 0xff, 0xfd, 0x9b, 0xb7, 0x8c, 0xcd, 0x6c,
+ 0x7c, 0xe7, 0x25, 0x62, 0xa0, 0x7f, 0x3e, 0x21, 0xbc, 0x79, 0x82, 0xc5,
+ 0xfb, 0x9f, 0xfc, 0x92, 0xc5, 0xfc, 0xfe, 0x6f, 0x85, 0x1e, 0xb1, 0x7f,
+ 0xff, 0xff, 0xf6, 0xb0, 0x1e, 0xfb, 0x1c, 0xce, 0x09, 0xe0, 0x23, 0x7e,
+ 0xd0, 0x33, 0xc2, 0xf3, 0xfb, 0x9f, 0x75, 0x8b, 0xe7, 0x37, 0x06, 0xb1,
+ 0x78, 0xdc, 0x1a, 0xc5, 0xd8, 0x73, 0x0f, 0x05, 0xc8, 0xeb, 0x64, 0xe2,
+ 0xb0, 0x74, 0xd2, 0x8d, 0x19, 0x7a, 0x1c, 0xd7, 0xf4, 0xed, 0x1d, 0x9a,
+ 0x95, 0x8b, 0xfa, 0x2f, 0xe7, 0x18, 0x96, 0x2f, 0xee, 0xa0, 0x1f, 0x27,
+ 0x16, 0x2b, 0x0f, 0x79, 0xcb, 0xaf, 0x01, 0xfe, 0xb1, 0x7f, 0xe1, 0xe7,
+ 0x50, 0xe7, 0xb8, 0xc0, 0x58, 0xad, 0x1f, 0xf0, 0x08, 0x04, 0x3b, 0x79,
+ 0xe3, 0xa5, 0x62, 0xfe, 0xe7, 0xda, 0x10, 0xfa, 0xc5, 0x31, 0xe7, 0x08,
+ 0x7e, 0xfb, 0x9c, 0xc0, 0x96, 0x2f, 0xfc, 0x1f, 0x46, 0x7d, 0xba, 0xf0,
+ 0x60, 0x58, 0xbf, 0xc1, 0x0f, 0xf9, 0xdb, 0x34, 0xb1, 0x7f, 0xf3, 0x9c,
+ 0xcd, 0xfe, 0xff, 0xdd, 0xf8, 0xb1, 0x7f, 0xb2, 0x18, 0x2e, 0xfd, 0x89,
+ 0x62, 0xff, 0xe9, 0x87, 0xe7, 0xaf, 0x4f, 0xda, 0x3d, 0x62, 0xff, 0xcf,
+ 0xbe, 0x11, 0x9c, 0xe3, 0xc4, 0xb1, 0x7f, 0x98, 0x1c, 0xf1, 0x64, 0x16,
+ 0x2a, 0x53, 0x72, 0xd1, 0xbf, 0xd2, 0x08, 0xdf, 0x89, 0x1e, 0x41, 0xbf,
+ 0xff, 0xce, 0x59, 0xd7, 0x8d, 0x6f, 0x7e, 0x7f, 0x9d, 0x9a, 0x0b, 0x17,
+ 0xcc, 0x0f, 0x77, 0xeb, 0x17, 0xfb, 0x0f, 0x14, 0x18, 0xb6, 0x58, 0xbd,
+ 0x98, 0x4b, 0x15, 0xb3, 0x24, 0x34, 0x6a, 0xbb, 0xc3, 0xdb, 0xa8, 0xc3,
+ 0x5e, 0x3a, 0xc8, 0x94, 0x75, 0x18, 0x69, 0xdf, 0x7e, 0x42, 0x02, 0x4f,
+ 0x47, 0x71, 0xd9, 0x58, 0x26, 0x30, 0xca, 0x3b, 0x8d, 0x6f, 0xe2, 0xcd,
+ 0xb6, 0x98, 0xf5, 0x8b, 0xf1, 0xfc, 0x59, 0x05, 0x8b, 0xfe, 0x9d, 0x70,
+ 0xb0, 0xf3, 0xba, 0xc5, 0xdb, 0xfd, 0x62, 0xe2, 0x95, 0x8b, 0xf7, 0x3f,
+ 0x21, 0x71, 0x62, 0xfe, 0x37, 0xaf, 0x7d, 0xfe, 0xb1, 0x43, 0x3d, 0xbd,
+ 0x15, 0x5f, 0xe7, 0xd4, 0xf6, 0x07, 0x20, 0xb1, 0x7f, 0xff, 0x84, 0x77,
+ 0xe1, 0x66, 0xb5, 0x91, 0x7f, 0x35, 0x9d, 0x2c, 0x50, 0xd1, 0x31, 0xa3,
+ 0x6b, 0xa4, 0xeb, 0x15, 0x26, 0xeb, 0xe4, 0x75, 0xf4, 0xe1, 0x59, 0xc7,
+ 0xd0, 0xf4, 0xbf, 0xee, 0x37, 0xdc, 0x7b, 0xbe, 0xcb, 0x17, 0xf9, 0xa1,
+ 0x83, 0xe7, 0x25, 0x62, 0xfe, 0xf7, 0xe4, 0xf1, 0x12, 0xc5, 0x4a, 0x27,
+ 0x70, 0xec, 0x06, 0x75, 0x1b, 0xb3, 0xf0, 0xa6, 0x51, 0x16, 0x52, 0x5e,
+ 0x0d, 0x87, 0xbe, 0xe6, 0x4e, 0x51, 0xa3, 0x96, 0x8e, 0x78, 0x50, 0xd2,
+ 0xb8, 0xbc, 0xb1, 0x78, 0x5a, 0xd9, 0x62, 0xff, 0x86, 0xfa, 0x91, 0x71,
+ 0xfb, 0x2c, 0x5e, 0xdc, 0x52, 0xb1, 0x78, 0x26, 0xfa, 0xc5, 0xec, 0x03,
+ 0x2c, 0x54, 0xa3, 0x26, 0x02, 0xf8, 0x3e, 0xe7, 0x7a, 0x1e, 0xf8, 0xf5,
+ 0xf6, 0x0b, 0x5b, 0x2c, 0x5f, 0xfb, 0xb3, 0xf8, 0x02, 0x2e, 0x38, 0xd6,
+ 0x2f, 0xd3, 0xd7, 0xa7, 0x4b, 0x17, 0xec, 0xe7, 0xc5, 0xb2, 0xc5, 0xb4,
+ 0x62, 0x2e, 0x30, 0x90, 0xe8, 0x3f, 0x29, 0xbf, 0xff, 0xcd, 0x00, 0xe1,
+ 0xfc, 0x17, 0x7f, 0x84, 0x69, 0x16, 0x44, 0xb1, 0x52, 0x8a, 0xa3, 0xa1,
+ 0xdf, 0xf1, 0x83, 0x26, 0x34, 0xd6, 0x09, 0x62, 0xff, 0xb0, 0x79, 0xd4,
+ 0x03, 0xe0, 0x16, 0x2f, 0xcf, 0xa8, 0x45, 0x2b, 0x17, 0xff, 0x7f, 0x09,
+ 0x8d, 0xfb, 0xfa, 0x0e, 0xb1, 0x5a, 0x45, 0x4f, 0xcf, 0x38, 0x53, 0x58,
+ 0x98, 0xb3, 0xc3, 0x9a, 0xfd, 0x85, 0xb3, 0xe9, 0x62, 0xce, 0xb1, 0x5f,
+ 0x37, 0x31, 0xc5, 0x17, 0xff, 0xc2, 0xdc, 0x3e, 0x80, 0xdc, 0x6d, 0x3f,
+ 0x40, 0x58, 0xbf, 0x4f, 0xcb, 0x0d, 0x58, 0xa7, 0x3f, 0xdf, 0xaa, 0xdf,
+ 0xa6, 0x2f, 0xbe, 0x96, 0x2f, 0xf6, 0xb7, 0xfb, 0x94, 0xc1, 0x62, 0xfd,
+ 0xee, 0x48, 0x36, 0x58, 0xa9, 0x3d, 0xe1, 0x1a, 0x5f, 0xfe, 0xc1, 0xcc,
+ 0x27, 0x9c, 0xc8, 0x42, 0x56, 0x2f, 0x9b, 0x53, 0x05, 0x8b, 0xff, 0xf9,
+ 0xc9, 0x9c, 0x81, 0xa9, 0xfb, 0x3f, 0xa7, 0xeb, 0x17, 0xff, 0x98, 0x80,
+ 0x67, 0x39, 0x31, 0x41, 0xe2, 0x58, 0xa1, 0xa6, 0x60, 0x72, 0x12, 0x49,
+ 0xf1, 0x14, 0x72, 0xbd, 0xff, 0xfd, 0x3e, 0x7d, 0xdc, 0x7c, 0x6e, 0xa1,
+ 0x85, 0x83, 0x58, 0xbf, 0x3f, 0xb8, 0x2d, 0x96, 0x2f, 0xfc, 0xe7, 0x9f,
+ 0x67, 0x40, 0x3c, 0xac, 0x5f, 0xfa, 0x01, 0x8d, 0xb6, 0xc3, 0xb7, 0x16,
+ 0x2f, 0xfa, 0x13, 0xf9, 0xf7, 0xd8, 0xeb, 0x15, 0x27, 0xf4, 0x24, 0x1b,
+ 0xff, 0xc4, 0xe0, 0xf7, 0x5b, 0xbe, 0x83, 0x91, 0xac, 0x5f, 0xe2, 0x7c,
+ 0xde, 0x7d, 0xc5, 0x8b, 0xfe, 0xf8, 0x63, 0x17, 0xb8, 0x09, 0x58, 0xa9,
+ 0x45, 0xe3, 0xa6, 0xb1, 0x9d, 0xff, 0xf9, 0xfa, 0x81, 0x4f, 0xf3, 0xb4,
+ 0xf5, 0xfc, 0xd9, 0x62, 0xf7, 0x9f, 0x65, 0x8a, 0x1a, 0xe7, 0x26, 0xe4,
+ 0x2f, 0x1d, 0xbe, 0x93, 0x4e, 0xb7, 0xf2, 0xa2, 0x85, 0xcf, 0xa1, 0xbb,
+ 0xd8, 0xb4, 0x35, 0x9b, 0xfc, 0xc3, 0xdf, 0xe2, 0x60, 0xd6, 0x2f, 0x7d,
+ 0xfe, 0xb1, 0x7e, 0x14, 0x97, 0xb8, 0xb1, 0x78, 0xf8, 0x35, 0x8b, 0xff,
+ 0xe0, 0x1f, 0x0f, 0x84, 0xc7, 0x98, 0x07, 0xc5, 0x8b, 0x87, 0x2b, 0x17,
+ 0xe0, 0x33, 0x8d, 0xd6, 0x2a, 0x4d, 0xf3, 0x0b, 0xdf, 0xdd, 0x41, 0xb3,
+ 0xaf, 0x2c, 0x5e, 0x37, 0x3b, 0x96, 0x2a, 0x4f, 0x45, 0xcc, 0x2f, 0x98,
+ 0xfc, 0x65, 0x8b, 0xd2, 0x79, 0x58, 0xbf, 0xcc, 0xfb, 0x93, 0x66, 0xeb,
+ 0x17, 0xe9, 0xf7, 0xda, 0x25, 0x8e, 0x1b, 0x3a, 0xd9, 0x50, 0x68, 0xca,
+ 0x3a, 0x1d, 0xd4, 0x23, 0x89, 0xc3, 0x84, 0x1d, 0x88, 0xa3, 0x93, 0xef,
+ 0xda, 0x16, 0xff, 0x95, 0x8b, 0xfb, 0x51, 0x41, 0xfd, 0xc5, 0x8a, 0x93,
+ 0xda, 0xc2, 0xab, 0x98, 0x25, 0x8a, 0x23, 0x70, 0x11, 0x05, 0xb8, 0xb1,
+ 0x7a, 0x27, 0x09, 0x62, 0xec, 0xd4, 0x9b, 0x17, 0x12, 0xbf, 0xd1, 0x34,
+ 0x4d, 0xd4, 0x38, 0xb1, 0x7f, 0x36, 0xcf, 0x13, 0x84, 0xb1, 0x7f, 0xe7,
+ 0x93, 0x4c, 0x7f, 0x30, 0x71, 0xeb, 0x17, 0xff, 0xd9, 0xf3, 0x07, 0x91,
+ 0x41, 0xb5, 0xb7, 0xc4, 0xb1, 0x73, 0x04, 0x48, 0x98, 0xf2, 0x25, 0x4a,
+ 0x6a, 0xf8, 0x54, 0xc6, 0xe5, 0x0c, 0x8b, 0xf6, 0x16, 0xd8, 0x12, 0xc5,
+ 0xf9, 0x8f, 0xf7, 0x09, 0x62, 0xb6, 0x3d, 0x21, 0x94, 0xdf, 0xfd, 0x3e,
+ 0xc2, 0x73, 0x40, 0x79, 0x82, 0xc5, 0xff, 0x4e, 0xc1, 0xc3, 0xe2, 0x6d,
+ 0x96, 0x2f, 0xf3, 0x7b, 0x9b, 0xee, 0xfd, 0x2c, 0x5f, 0xf3, 0xef, 0x91,
+ 0x31, 0x6d, 0xde, 0xac, 0x56, 0x26, 0x36, 0xe4, 0x7a, 0x44, 0x63, 0xd2,
+ 0x37, 0xb4, 0x6c, 0xb1, 0x7e, 0x9d, 0x6b, 0x3e, 0xb1, 0x7f, 0xf4, 0xe1,
+ 0x7e, 0x5c, 0x0d, 0xe1, 0x2c, 0x5e, 0x68, 0x79, 0x62, 0xff, 0xfa, 0x4d,
+ 0x0b, 0x1f, 0xb0, 0x4c, 0x39, 0xc3, 0xac, 0x5f, 0xc4, 0xc6, 0xc9, 0xe5,
+ 0x62, 0xbb, 0xd4, 0xc7, 0xa0, 0x2f, 0xa2, 0x83, 0xa1, 0x10, 0xe8, 0x94,
+ 0xee, 0x34, 0xd5, 0x8b, 0xf8, 0x9b, 0x7c, 0x2d, 0xd6, 0x2f, 0xff, 0xfb,
+ 0x3d, 0x9d, 0xbf, 0x87, 0x60, 0x8f, 0x3f, 0xf6, 0x3f, 0x65, 0x8a, 0xd9,
+ 0x16, 0x4e, 0x34, 0x45, 0xd7, 0xa3, 0x54, 0x78, 0x16, 0x2f, 0xff, 0xe1,
+ 0x36, 0xa0, 0x67, 0xf2, 0x29, 0xf6, 0x1e, 0x7e, 0xb1, 0x7d, 0x17, 0x69,
+ 0x25, 0x8b, 0xfa, 0x4e, 0xe4, 0x02, 0x58, 0xbf, 0xb8, 0xcc, 0x1b, 0x06,
+ 0xb1, 0x7d, 0x01, 0x0e, 0x32, 0x34, 0x4c, 0x10, 0x64, 0xe4, 0xbb, 0xc2,
+ 0x5f, 0x16, 0x5f, 0x9e, 0x62, 0x29, 0x58, 0xbf, 0x8e, 0xdd, 0x77, 0x99,
+ 0xf5, 0x8b, 0xc1, 0x37, 0x16, 0x2f, 0xe3, 0xce, 0x17, 0xb8, 0xb1, 0x7e,
+ 0x9d, 0xb2, 0x0e, 0xb1, 0x7f, 0xa4, 0xb1, 0xf6, 0x6e, 0x2c, 0x5e, 0x0c,
+ 0x71, 0x90, 0x4c, 0x03, 0x09, 0xfe, 0x69, 0xc1, 0xef, 0x16, 0x86, 0x51,
+ 0x7d, 0x39, 0xd4, 0x16, 0x2a, 0x24, 0xfe, 0xff, 0x1b, 0x50, 0x1b, 0xaf,
+ 0xfb, 0x6d, 0x9f, 0x7e, 0xa1, 0x3d, 0xcb, 0x17, 0xdf, 0xfe, 0x74, 0xb1,
+ 0x7f, 0x30, 0xe4, 0xa4, 0x0b, 0x17, 0xcf, 0xcc, 0x1c, 0x9e, 0x84, 0x71,
+ 0x25, 0xf9, 0xb9, 0xec, 0xfa, 0xc5, 0xbe, 0xb1, 0x7f, 0xe1, 0x0d, 0x88,
+ 0x1e, 0x7e, 0xb8, 0xb1, 0x7f, 0xfb, 0x05, 0xdf, 0x99, 0x90, 0xfe, 0x3c,
+ 0x38, 0xb1, 0x7f, 0xff, 0xb4, 0xdc, 0x0f, 0xc5, 0x9d, 0x98, 0x03, 0xd1,
+ 0x30, 0x4b, 0x16, 0xf4, 0x11, 0xe9, 0xc4, 0x01, 0x28, 0x5e, 0xfb, 0x0d,
+ 0x62, 0xff, 0x9e, 0x4e, 0x66, 0x0d, 0xfb, 0x2c, 0x56, 0x27, 0x28, 0xf1,
+ 0x83, 0x7c, 0xdb, 0x83, 0xb7, 0xc6, 0x79, 0xce, 0xb1, 0x52, 0xbc, 0xa6,
+ 0x39, 0x65, 0xd8, 0x71, 0xbc, 0x24, 0x5c, 0xe9, 0xa3, 0xbc, 0x12, 0x15,
+ 0xf0, 0xa1, 0xf7, 0x58, 0xbf, 0xff, 0x3e, 0xf2, 0x7e, 0x36, 0xb0, 0xe2,
+ 0xdd, 0xa0, 0xb1, 0x7f, 0xcd, 0xa6, 0xf3, 0xe9, 0x80, 0xb1, 0x73, 0xf6,
+ 0x58, 0xbf, 0xd2, 0x4d, 0xf1, 0x16, 0xcb, 0x17, 0xfe, 0x73, 0x64, 0x6e,
+ 0x4d, 0xa3, 0x56, 0x2f, 0xff, 0x67, 0x5e, 0xeb, 0xce, 0x16, 0x0d, 0xa0,
+ 0xb1, 0x58, 0x88, 0xc0, 0x1f, 0xdb, 0xeb, 0x17, 0xf3, 0xe8, 0x07, 0x7e,
+ 0x2c, 0x56, 0xc9, 0xf6, 0x40, 0x8f, 0x75, 0x78, 0xf3, 0x83, 0x8c, 0x94,
+ 0x2f, 0xc4, 0x45, 0x1c, 0x25, 0x78, 0xfc, 0x25, 0x8b, 0xff, 0xff, 0xba,
+ 0xe6, 0x41, 0xfd, 0xfc, 0x20, 0x02, 0x7e, 0x58, 0x36, 0x3a, 0xc5, 0xf7,
+ 0xba, 0x6f, 0xac, 0x54, 0xa2, 0xc9, 0xc7, 0x7c, 0xe3, 0x74, 0x9d, 0x62,
+ 0xff, 0xee, 0x67, 0x5e, 0x6f, 0x44, 0xcd, 0xa5, 0x8a, 0x19, 0xee, 0xf8,
+ 0x5e, 0xff, 0xff, 0xe2, 0x6d, 0xbc, 0x26, 0xeb, 0xce, 0x10, 0x7e, 0x72,
+ 0x14, 0x33, 0x8b, 0x17, 0xf0, 0x32, 0x29, 0xeb, 0x8b, 0x17, 0xfd, 0x85,
+ 0xb9, 0x98, 0x37, 0xec, 0xb1, 0x7f, 0xb0, 0xe6, 0x39, 0xb8, 0x35, 0x8a,
+ 0xf9, 0xf8, 0xf8, 0xf2, 0xff, 0xff, 0x13, 0x05, 0xfc, 0x3b, 0x05, 0xee,
+ 0x60, 0x43, 0x73, 0xac, 0x5e, 0xfe, 0x44, 0xb1, 0x7f, 0xc2, 0xd3, 0x34,
+ 0x3d, 0x9f, 0x58, 0xbf, 0x03, 0xa8, 0x4f, 0x72, 0xc5, 0xfd, 0x9a, 0xc8,
+ 0xa4, 0xd5, 0x8a, 0xc3, 0xdc, 0xf1, 0x6d, 0xff, 0xff, 0xdc, 0xfc, 0xfe,
+ 0x5f, 0xa0, 0x6b, 0x07, 0x3e, 0xe3, 0x97, 0x50, 0x58, 0xa1, 0xaa, 0xe2,
+ 0xc7, 0x57, 0x85, 0x0c, 0x44, 0x5f, 0x63, 0xe0, 0xf7, 0xa1, 0x2a, 0x11,
+ 0x0d, 0xe1, 0xb9, 0xd6, 0x2f, 0xf7, 0x5b, 0xbe, 0x7f, 0x5c, 0x58, 0xbf,
+ 0xe2, 0x73, 0x98, 0xe0, 0x0c, 0x0b, 0x15, 0xb1, 0xf8, 0x91, 0xb5, 0xfe,
+ 0x34, 0xb3, 0x6d, 0x84, 0x4b, 0x15, 0x2b, 0x8c, 0xf9, 0x2c, 0x11, 0xdf,
+ 0x5a, 0x11, 0xc2, 0x22, 0xbc, 0x0f, 0x77, 0xeb, 0x17, 0xa0, 0xfa, 0x58,
+ 0xbf, 0xf8, 0x72, 0x7e, 0x13, 0x7f, 0x35, 0x8b, 0x17, 0xf7, 0xda, 0x13,
+ 0xc8, 0x2c, 0x5f, 0xf6, 0x7d, 0xfa, 0xe7, 0xc5, 0xc5, 0x8a, 0xdc, 0xfa,
+ 0x40, 0x5d, 0x5d, 0x23, 0xb3, 0xe3, 0xa5, 0x0a, 0xca, 0x94, 0xd1, 0x32,
+ 0x30, 0xfb, 0xff, 0x80, 0xff, 0xe3, 0x6f, 0xf9, 0x8f, 0x1a, 0xc5, 0xff,
+ 0xf9, 0xa3, 0xcc, 0x8e, 0x14, 0x99, 0x9c, 0x21, 0x36, 0xcb, 0x14, 0x04,
+ 0x53, 0x89, 0x26, 0xff, 0xfe, 0xdc, 0x4d, 0xd7, 0x8c, 0x0f, 0xce, 0x42,
+ 0x86, 0x71, 0x62, 0xfb, 0x8c, 0xfb, 0x2c, 0x5e, 0xe6, 0xd2, 0xb1, 0x5b,
+ 0x1e, 0x0e, 0x11, 0xdd, 0xde, 0xc4, 0xb1, 0x7f, 0xff, 0x7b, 0x3b, 0x19,
+ 0x1c, 0x29, 0x33, 0x38, 0x42, 0x6d, 0x96, 0x2f, 0xfa, 0x13, 0xef, 0x4b,
+ 0x1f, 0x65, 0x8a, 0xc4, 0x4e, 0xf4, 0xc7, 0x7f, 0xfb, 0x3e, 0xcc, 0x72,
+ 0x6d, 0x3c, 0xf1, 0x62, 0xd8, 0x73, 0xea, 0xec, 0x47, 0x7e, 0xdb, 0xba,
+ 0x7a, 0xe2, 0xc5, 0xff, 0xc0, 0xf7, 0x18, 0xe5, 0x9f, 0xfb, 0xac, 0x5f,
+ 0x00, 0x78, 0x4b, 0x15, 0x27, 0xcc, 0xc8, 0x95, 0x8a, 0xba, 0x3a, 0x23,
+ 0x78, 0x50, 0x9c, 0x8b, 0xf1, 0x92, 0xb1, 0x49, 0x42, 0x52, 0xd1, 0x2c,
+ 0x5e, 0xc2, 0x35, 0x62, 0xa4, 0xd8, 0x60, 0x9d, 0xfe, 0xde, 0x61, 0xef,
+ 0xb0, 0xd6, 0x2f, 0xcf, 0x1d, 0x9a, 0x35, 0x62, 0xfb, 0xb1, 0x67, 0x16,
+ 0x2f, 0xe2, 0x63, 0x4b, 0x00, 0xb1, 0x4e, 0x7a, 0x27, 0x24, 0xbf, 0xfb,
+ 0x21, 0xec, 0xf9, 0x67, 0xbe, 0xeb, 0x16, 0x95, 0x8a, 0xf9, 0xea, 0x32,
+ 0x1d, 0xe0, 0x06, 0x05, 0x8b, 0x41, 0x62, 0xfa, 0x7d, 0xc3, 0x1c, 0xd8,
+ 0xf8, 0x7e, 0xe3, 0x60, 0xb1, 0x7e, 0xfb, 0xf6, 0x7d, 0xd6, 0x2e, 0xcf,
+ 0xc0, 0xf1, 0x37, 0x19, 0xad, 0x95, 0x21, 0x60, 0xf9, 0xcd, 0x59, 0xf7,
+ 0x8e, 0xbe, 0x52, 0x8e, 0x7c, 0xbc, 0x10, 0x41, 0x24, 0x5f, 0xfb, 0x44,
+ 0x26, 0x0f, 0x22, 0x93, 0xac, 0x46, 0x1a, 0x1b, 0xd1, 0x38, 0x4b, 0x17,
+ 0xbe, 0x20, 0x2c, 0x5b, 0xee, 0x6f, 0x62, 0x1f, 0xb6, 0xeb, 0x15, 0x28,
+ 0xca, 0xc8, 0x48, 0x68, 0x9e, 0xff, 0x48, 0xf2, 0x12, 0x5b, 0xac, 0x54,
+ 0xba, 0xb7, 0x0d, 0xa3, 0xb6, 0x84, 0x67, 0x03, 0x60, 0xc9, 0xd8, 0x5d,
+ 0xe1, 0x41, 0xd1, 0xb3, 0xca, 0x2a, 0x8f, 0x8c, 0x42, 0x28, 0xea, 0x75,
+ 0x1d, 0x61, 0xe3, 0x65, 0xfc, 0xfb, 0x0b, 0x4a, 0x62, 0x04, 0x66, 0x05,
+ 0x39, 0xe5, 0xc8, 0xe6, 0x7d, 0x2e, 0xdc, 0x52, 0xb9, 0x42, 0x8d, 0x4c,
+ 0x33, 0x3b, 0xe7, 0xd3, 0x01, 0x62, 0xff, 0x0f, 0xf3, 0xb1, 0x67, 0x4b,
+ 0x17, 0x87, 0xf9, 0x58, 0xa3, 0x9f, 0xa0, 0x08, 0xb8, 0x6b, 0x7d, 0xad,
+ 0x67, 0xd6, 0x2f, 0xef, 0xbf, 0x77, 0x70, 0x8d, 0x58, 0xbf, 0x9b, 0x4f,
+ 0xc0, 0x3a, 0xc5, 0x4a, 0x21, 0xb7, 0x23, 0xf9, 0xb5, 0xbb, 0xf5, 0x8b,
+ 0x8b, 0x8b, 0x16, 0x75, 0x8b, 0xfb, 0x5c, 0xfc, 0x97, 0x96, 0x2e, 0x90,
+ 0x2c, 0x5b, 0xd2, 0x78, 0xbc, 0x2e, 0xbf, 0xfd, 0xad, 0x83, 0xf3, 0xfc,
+ 0x47, 0x3b, 0x41, 0x62, 0xdd, 0xfa, 0xc5, 0xff, 0x7a, 0x75, 0xcf, 0xc9,
+ 0x79, 0x62, 0xee, 0x4a, 0xc5, 0xe3, 0x8e, 0x56, 0x2f, 0xf1, 0x79, 0xa2,
+ 0xe4, 0xf9, 0x62, 0x9c, 0xf4, 0x58, 0x76, 0xf9, 0xdb, 0x37, 0x58, 0xbf,
+ 0xf6, 0x76, 0x2c, 0xe4, 0x45, 0x23, 0x58, 0xbe, 0xdc, 0x73, 0xb2, 0xc5,
+ 0xc0, 0x95, 0x8b, 0xdc, 0x7d, 0x2c, 0x56, 0x1e, 0xc8, 0x09, 0x7c, 0x2f,
+ 0x7f, 0xa1, 0x84, 0xe3, 0xc2, 0x58, 0xbb, 0x91, 0x92, 0x9f, 0x96, 0x0b,
+ 0xc4, 0x73, 0xf6, 0x80, 0x10, 0x11, 0x17, 0x21, 0x33, 0xe2, 0xea, 0x65,
+ 0x58, 0x9e, 0x94, 0x81, 0x7d, 0xd0, 0xdb, 0x65, 0x8b, 0xb9, 0x2b, 0x17,
+ 0x8e, 0x39, 0x58, 0xbf, 0xc5, 0xe6, 0x8b, 0x93, 0xe5, 0x8a, 0x73, 0xd1,
+ 0x61, 0xdb, 0xe7, 0x6c, 0xdd, 0x62, 0xff, 0xd9, 0xd8, 0xb3, 0x91, 0x14,
+ 0x8d, 0x62, 0xfb, 0x71, 0xce, 0xcb, 0x17, 0xf4, 0x40, 0x78, 0xf6, 0x89,
+ 0x62, 0xf3, 0x83, 0x8b, 0x17, 0x02, 0x56, 0x2f, 0x71, 0xf4, 0xb1, 0x76,
+ 0x44, 0xb1, 0x58, 0x8c, 0x1d, 0xc9, 0x7e, 0x66, 0x01, 0xdf, 0x0b, 0x86,
+ 0x3b, 0x7f, 0x61, 0x38, 0xf0, 0x96, 0x2f, 0xd8, 0x44, 0xde, 0x58, 0xbf,
+ 0x6d, 0xec, 0xc3, 0xac, 0x54, 0x0f, 0xeb, 0xe5, 0x6c, 0x4d, 0x7f, 0x13,
+ 0x0f, 0x0d, 0x8c, 0x95, 0xe6, 0xa8, 0x0b, 0x8c, 0x5f, 0x15, 0xb7, 0x95,
+ 0xd6, 0xe5, 0x71, 0x12, 0xfd, 0xa0, 0x04, 0x04, 0x45, 0xc8, 0xc0, 0x7d,
+ 0x0d, 0x2b, 0xff, 0xb5, 0x3d, 0x70, 0xa4, 0xf9, 0xd7, 0x96, 0x2f, 0xff,
+ 0xcc, 0x3c, 0xc2, 0x34, 0x32, 0x92, 0xd9, 0xf4, 0xb1, 0x79, 0xb5, 0xb2,
+ 0xee, 0x12, 0x2f, 0xa1, 0x9d, 0x41, 0x77, 0x09, 0x17, 0xb8, 0xe3, 0x5d,
+ 0xc2, 0x45, 0xc1, 0x04, 0xbb, 0x84, 0x8a, 0xdd, 0x15, 0xb1, 0x15, 0xf8,
+ 0xc4, 0x22, 0xab, 0x9b, 0xc9, 0xb8, 0x48, 0x46, 0x1e, 0x05, 0xff, 0xff,
+ 0xc3, 0x29, 0x1f, 0xe7, 0xdc, 0x9f, 0x48, 0xe7, 0xd8, 0x70, 0x04, 0xb1,
+ 0x7f, 0x67, 0xf3, 0x08, 0xd5, 0x8b, 0xcc, 0x40, 0x31, 0x93, 0xaf, 0x33,
+ 0xd3, 0x5a, 0x86, 0xe9, 0xd1, 0x8a, 0x34, 0x2e, 0x1c, 0xf9, 0xca, 0xfd,
+ 0xf6, 0x84, 0xc1, 0x62, 0xfa, 0x3b, 0x1b, 0xeb, 0x17, 0xfc, 0xc4, 0x0c,
+ 0xec, 0x42, 0x82, 0xc5, 0x47, 0xa6, 0x23, 0xf8, 0x45, 0x00, 0xa3, 0xc4,
+ 0xb7, 0xfa, 0x20, 0xa7, 0xa1, 0xcf, 0x16, 0x2b, 0x0f, 0xf5, 0xd1, 0xad,
+ 0x05, 0x8b, 0x88, 0xd5, 0x8b, 0xfa, 0x02, 0xdb, 0xcf, 0xb2, 0x45, 0xfc,
+ 0x59, 0xee, 0x49, 0xd6, 0x2e, 0x7f, 0x2c, 0x5b, 0xcb, 0x17, 0x68, 0x06,
+ 0x1a, 0x97, 0x17, 0xbd, 0xda, 0x78, 0xb1, 0x7c, 0xc3, 0xfe, 0x2c, 0x5e,
+ 0x1b, 0x9d, 0x62, 0xff, 0xdf, 0x9f, 0x39, 0x49, 0xe7, 0x8b, 0x17, 0x7f,
+ 0x75, 0x8b, 0x47, 0xac, 0x51, 0x89, 0xa6, 0x4a, 0xb6, 0x16, 0x9a, 0x3e,
+ 0xc4, 0x5c, 0x1d, 0x11, 0xef, 0x70, 0xcd, 0x3a, 0xa0, 0x98, 0x86, 0x3f,
+ 0x1b, 0xed, 0xff, 0x49, 0x40, 0xa4, 0x0c, 0x75, 0x8b, 0xfe, 0x89, 0xdc,
+ 0xa7, 0x4d, 0xc5, 0x8b, 0xde, 0xcf, 0xac, 0x52, 0xc5, 0xdb, 0xbf, 0xcf,
+ 0x87, 0x87, 0x11, 0xc3, 0xb7, 0xde, 0xd0, 0x8e, 0xb1, 0x73, 0xec, 0xb1,
+ 0x4e, 0x6f, 0x3c, 0x49, 0x7d, 0x3f, 0x16, 0x96, 0x2f, 0xff, 0xf8, 0xe2,
+ 0xe6, 0xd8, 0x16, 0x6b, 0x67, 0xe7, 0xf3, 0xd1, 0xd8, 0xb1, 0x7b, 0xed,
+ 0xe5, 0x8a, 0xd9, 0x19, 0xb1, 0x10, 0x1c, 0x8f, 0x8d, 0xb7, 0x4f, 0xd6,
+ 0x2d, 0x2b, 0x1e, 0x2d, 0xef, 0xf3, 0xc0, 0x4d, 0xcf, 0xba, 0xc5, 0xff,
+ 0x3f, 0x6c, 0x30, 0xdd, 0x67, 0x16, 0x2e, 0xce, 0xcb, 0x17, 0xee, 0xcc,
+ 0x7c, 0xfa, 0xc5, 0xff, 0x67, 0xba, 0xdd, 0xf5, 0xfc, 0x58, 0xac, 0x3e,
+ 0x5f, 0x95, 0x5a, 0x09, 0x17, 0x9b, 0x5b, 0x24, 0x52, 0x45, 0x49, 0xbc,
+ 0xdc, 0x48, 0xe3, 0xd7, 0xa4, 0x1b, 0xa4, 0x46, 0x1a, 0xeb, 0xff, 0xbe,
+ 0xd0, 0x2c, 0xe0, 0x8d, 0x38, 0x4b, 0x14, 0x34, 0xef, 0xba, 0x3d, 0x3b,
+ 0xf1, 0x42, 0x2f, 0xc6, 0x37, 0x8a, 0x1f, 0x58, 0xbd, 0xd4, 0x38, 0xb1,
+ 0x52, 0xa9, 0xf7, 0x23, 0xf1, 0x3a, 0x83, 0x0e, 0xdf, 0xb0, 0xb6, 0x7d,
+ 0x2c, 0x5a, 0x39, 0x62, 0xcd, 0xb1, 0xbd, 0x22, 0x8b, 0xf6, 0x80, 0x77,
+ 0xe2, 0xc5, 0xfc, 0x19, 0x43, 0x9f, 0x1a, 0xc6, 0x1a, 0x9b, 0xfb, 0xdc,
+ 0x03, 0x36, 0x96, 0x2f, 0xa7, 0x77, 0xe2, 0xc5, 0xf0, 0x9b, 0x50, 0x58,
+ 0xb1, 0xd6, 0x2d, 0x01, 0x9b, 0x58, 0x88, 0xef, 0xff, 0xfe, 0xf7, 0xa1,
+ 0x9f, 0xfb, 0x42, 0x3b, 0x39, 0xc1, 0x73, 0xdc, 0xc0, 0x96, 0x2e, 0xc8,
+ 0x96, 0x2f, 0x80, 0x01, 0x71, 0x91, 0x20, 0x1b, 0xc5, 0x4a, 0x6f, 0x3b,
+ 0x17, 0x62, 0xc3, 0x42, 0xe2, 0xff, 0xec, 0xeb, 0xdc, 0x72, 0x90, 0x31,
+ 0xd6, 0x2f, 0xec, 0xd4, 0x5f, 0x70, 0x2c, 0x5f, 0xff, 0xd9, 0xef, 0xb8,
+ 0x53, 0xa6, 0x84, 0xf3, 0xf8, 0x05, 0x8a, 0x82, 0x22, 0x88, 0xbe, 0xe8,
+ 0x0d, 0x62, 0xf4, 0x27, 0xa5, 0x8b, 0xb0, 0x6b, 0x17, 0xd9, 0x13, 0x9d,
+ 0x62, 0xb6, 0x4d, 0x80, 0xd8, 0x67, 0x74, 0x45, 0x10, 0xc7, 0x87, 0x82,
+ 0x17, 0xbf, 0x4c, 0x50, 0x90, 0x24, 0x5c, 0x40, 0x58, 0xbf, 0x7d, 0xe4,
+ 0xbc, 0xb1, 0x68, 0xf5, 0x8b, 0x7d, 0xcd, 0xe0, 0x89, 0xef, 0xef, 0x3e,
+ 0x9f, 0x69, 0x58, 0xac, 0x45, 0x3e, 0xea, 0x61, 0x93, 0x5f, 0xff, 0xbf,
+ 0x8f, 0x0e, 0x19, 0xef, 0xe0, 0xc5, 0xee, 0x2c, 0x56, 0xe9, 0xac, 0xea,
+ 0x1a, 0x1e, 0x31, 0xbc, 0x79, 0x8f, 0x58, 0xb9, 0xe2, 0x58, 0xbf, 0x8b,
+ 0xd1, 0x66, 0xb1, 0x62, 0x8e, 0x78, 0xcc, 0x31, 0x5d, 0x22, 0x1c, 0x0c,
+ 0xd6, 0x8d, 0x6b, 0x17, 0xfe, 0xf7, 0xf0, 0x62, 0xf7, 0x22, 0x95, 0x8b,
+ 0x3a, 0xc5, 0xff, 0x6c, 0x28, 0x0f, 0xe2, 0x62, 0x58, 0xbf, 0x9e, 0x4f,
+ 0xb6, 0x04, 0xb1, 0x7e, 0xcd, 0x8f, 0x87, 0x58, 0xbd, 0xc7, 0xd2, 0xc5,
+ 0x11, 0xe3, 0x78, 0xa6, 0xfe, 0x26, 0x00, 0x05, 0xc5, 0x8b, 0xd2, 0x78,
+ 0xc1, 0xa6, 0x21, 0x82, 0x3a, 0x3b, 0xe3, 0xaf, 0x88, 0x6c, 0x6f, 0x13,
+ 0xaf, 0x0e, 0x35, 0x1a, 0x8d, 0x69, 0xfc, 0xbc, 0x78, 0xf5, 0x8b, 0x98,
+ 0xaf, 0x1d, 0xdb, 0x42, 0xf8, 0xa5, 0x0e, 0xdf, 0xf0, 0x1c, 0xbd, 0xd7,
+ 0x1a, 0x3d, 0x62, 0xfd, 0xfc, 0xdb, 0xdc, 0x58, 0xad, 0x1f, 0x3f, 0xcf,
+ 0x6f, 0xff, 0xb9, 0xcc, 0x3c, 0xc7, 0xeb, 0x1f, 0xf2, 0x35, 0x8b, 0xd3,
+ 0xd7, 0x16, 0x2a, 0x07, 0xe1, 0xa5, 0x2b, 0xd9, 0xb0, 0x96, 0x2b, 0x11,
+ 0xa4, 0xd0, 0x92, 0x22, 0x2b, 0x98, 0xeb, 0x17, 0xff, 0x44, 0x4c, 0x16,
+ 0xa5, 0xe0, 0xdc, 0x58, 0xa3, 0x9e, 0xe3, 0x0b, 0xdf, 0x8b, 0x00, 0x1f,
+ 0x4b, 0x17, 0xff, 0x3c, 0xe8, 0x1f, 0xce, 0x37, 0x50, 0x58, 0xb7, 0x8c,
+ 0x3e, 0xff, 0x95, 0x5f, 0xee, 0x16, 0x45, 0x09, 0xe9, 0x62, 0xb0, 0xf7,
+ 0xbc, 0x53, 0x52, 0xdf, 0xb7, 0xc2, 0x98, 0x34, 0x32, 0x0c, 0x94, 0x36,
+ 0x69, 0xc7, 0x50, 0x98, 0x78, 0xd1, 0xf4, 0xad, 0xf9, 0x53, 0xac, 0xfe,
+ 0x04, 0xf2, 0x8e, 0xe3, 0x93, 0xcc, 0xde, 0x8e, 0x1c, 0x50, 0x8e, 0x8e,
+ 0x87, 0x75, 0xff, 0xfb, 0x6d, 0x6b, 0x06, 0xc7, 0xfb, 0x78, 0xa6, 0x25,
+ 0x8b, 0xff, 0xff, 0xc2, 0xd0, 0xa2, 0x26, 0x07, 0x39, 0x86, 0xe0, 0xb4,
+ 0xc3, 0x9f, 0xca, 0xc5, 0xff, 0xef, 0x4f, 0xb9, 0xa9, 0x2f, 0x7f, 0x20,
+ 0xb1, 0x7f, 0xdc, 0x2c, 0xff, 0x8a, 0x40, 0xb1, 0x6e, 0x2c, 0x56, 0x22,
+ 0x50, 0xd4, 0xaf, 0x1c, 0x5f, 0xce, 0x1c, 0xf5, 0x3d, 0x2c, 0x5f, 0xff,
+ 0xf4, 0x6a, 0x32, 0x10, 0x9f, 0x78, 0xce, 0x16, 0x3f, 0x9d, 0x80, 0xb1,
+ 0x7f, 0xfd, 0x3a, 0x33, 0x0e, 0xdf, 0x6f, 0xbf, 0x5c, 0x58, 0xbf, 0x85,
+ 0x3a, 0xd3, 0xec, 0xb1, 0x7f, 0xf0, 0x8d, 0xc2, 0xfe, 0x0c, 0x6f, 0xd2,
+ 0xc5, 0xfd, 0x18, 0xfe, 0xd6, 0x41, 0x62, 0xb7, 0x3f, 0x77, 0x46, 0xbf,
+ 0xbe, 0xfd, 0x84, 0x08, 0x2c, 0x5f, 0xee, 0x4b, 0xeb, 0x59, 0xb2, 0xc5,
+ 0xfd, 0x09, 0x07, 0xdc, 0x25, 0x8b, 0xee, 0x70, 0x5d, 0x2c, 0x5f, 0x87,
+ 0xf9, 0x21, 0x2c, 0x5d, 0xfc, 0x58, 0xa9, 0x3e, 0x46, 0x25, 0x11, 0x45,
+ 0xfe, 0x39, 0x60, 0xdf, 0xfc, 0x58, 0xb7, 0xd6, 0x2f, 0x7a, 0x76, 0x58,
+ 0xa7, 0x36, 0x1e, 0x12, 0xbf, 0x9a, 0x1f, 0x76, 0x82, 0xc5, 0x4a, 0x2c,
+ 0x31, 0x8d, 0xc8, 0x2f, 0x63, 0x81, 0x62, 0xff, 0xa3, 0x3e, 0xc3, 0x21,
+ 0x36, 0xcb, 0x17, 0x8d, 0xd0, 0x16, 0x28, 0xd3, 0xdc, 0xdc, 0xf6, 0xfc,
+ 0x2e, 0xc4, 0xd0, 0x58, 0xbf, 0xfd, 0xf8, 0xc9, 0xf6, 0xb0, 0x66, 0x67,
+ 0x5e, 0x58, 0xb9, 0x89, 0x62, 0xb0, 0xf9, 0x99, 0x42, 0xfe, 0x84, 0xc5,
+ 0x8e, 0x05, 0x8b, 0x46, 0x77, 0xc5, 0xd0, 0x3d, 0x9b, 0x86, 0xa3, 0x90,
+ 0xa6, 0x34, 0x8b, 0xa3, 0x18, 0x8d, 0x0f, 0x09, 0x3f, 0xc3, 0x77, 0xbf,
+ 0x2d, 0x27, 0x8e, 0x12, 0x7a, 0x12, 0x1d, 0xc4, 0x17, 0x08, 0x25, 0x8b,
+ 0xe9, 0x8f, 0x1c, 0xac, 0x5f, 0x7b, 0x8f, 0xa5, 0x8b, 0xdf, 0x10, 0x6b,
+ 0x15, 0x27, 0x85, 0xdc, 0x47, 0x7f, 0x08, 0x3e, 0x3e, 0x12, 0xc5, 0xd9,
+ 0x12, 0xc5, 0xc1, 0xc4, 0xb1, 0x4e, 0x6c, 0x98, 0x62, 0xd3, 0x11, 0xff,
+ 0xf1, 0x82, 0xf0, 0x41, 0x04, 0x91, 0x69, 0x48, 0x8c, 0x34, 0x37, 0x43,
+ 0x65, 0x8a, 0x81, 0xbd, 0x39, 0x25, 0xef, 0xc8, 0x16, 0x2f, 0xe8, 0xdb,
+ 0xf2, 0x09, 0x8f, 0x58, 0xaf, 0x1e, 0x98, 0x63, 0xb7, 0xcd, 0x3d, 0x9d,
+ 0x62, 0xe8, 0x8e, 0xb1, 0x76, 0x0d, 0x62, 0xa4, 0xd8, 0x08, 0x66, 0xef,
+ 0xe9, 0x62, 0xe0, 0x01, 0x62, 0xf7, 0xe3, 0x60, 0x96, 0x2f, 0xa2, 0xcc,
+ 0xdd, 0x62, 0xa5, 0x95, 0xc3, 0xb2, 0xbc, 0x23, 0x0d, 0x19, 0x86, 0x4e,
+ 0x99, 0x9b, 0x0e, 0xfd, 0xc6, 0x7a, 0x67, 0x8a, 0x14, 0x7a, 0x84, 0x33,
+ 0x3a, 0x11, 0x1f, 0x14, 0xfc, 0x40, 0x21, 0x8e, 0xc3, 0x01, 0x12, 0x5e,
+ 0xdd, 0xe5, 0x62, 0xe1, 0x71, 0x62, 0xec, 0xd2, 0xc5, 0x6c, 0x6b, 0xf0,
+ 0x62, 0xa0, 0x7d, 0xa3, 0x4c, 0xbf, 0xfd, 0xe8, 0xb3, 0x5a, 0x68, 0xb3,
+ 0x59, 0xe5, 0x8b, 0xfb, 0x58, 0x42, 0x9d, 0x2c, 0x56, 0x22, 0x6d, 0xc8,
+ 0xbc, 0x99, 0x7f, 0xd0, 0x7f, 0x42, 0x75, 0x3b, 0xac, 0x5a, 0x3d, 0x62,
+ 0xe2, 0x81, 0x87, 0x9f, 0x03, 0xab, 0xf4, 0xeb, 0x59, 0xf5, 0x8a, 0xc3,
+ 0xd6, 0x34, 0xba, 0xfe, 0xda, 0x28, 0x46, 0xda, 0xd9, 0x62, 0xf7, 0xe7,
+ 0xeb, 0x17, 0xff, 0x80, 0x76, 0x81, 0x92, 0x3d, 0x8f, 0x3a, 0x58, 0xbe,
+ 0x79, 0x2f, 0x2c, 0x5e, 0xd9, 0x89, 0x62, 0xed, 0x6c, 0xb1, 0x6c, 0x58,
+ 0xa1, 0xa3, 0x4b, 0x43, 0xbf, 0x4d, 0xf1, 0x08, 0x87, 0x42, 0x19, 0xbf,
+ 0xf1, 0xa2, 0xe4, 0x1f, 0x5b, 0x08, 0x0b, 0x17, 0x16, 0x2c, 0x5e, 0x0f,
+ 0xa2, 0x58, 0xbf, 0x38, 0x0e, 0xd0, 0x58, 0xbe, 0xce, 0x81, 0xc5, 0x8a,
+ 0xd1, 0xe6, 0x11, 0x45, 0xdd, 0x04, 0xb1, 0x7d, 0x91, 0xf2, 0x75, 0x8a,
+ 0xc3, 0xe0, 0x62, 0x1e, 0x0d, 0x5f, 0xfb, 0xd2, 0x73, 0x0b, 0x00, 0x1f,
+ 0x4b, 0x17, 0xfb, 0x8d, 0xfd, 0xe5, 0xc6, 0xb1, 0x46, 0xa7, 0x8e, 0xe8,
+ 0x67, 0x16, 0xfc, 0x32, 0xc8, 0xb7, 0xc8, 0x57, 0x9c, 0xf2, 0xb1, 0x7a,
+ 0x77, 0x82, 0xc5, 0xd3, 0xc5, 0x8b, 0xcf, 0x27, 0x58, 0xb9, 0x86, 0xb1,
+ 0x43, 0x3c, 0xad, 0x0b, 0xf8, 0x72, 0xf3, 0x66, 0xeb, 0x17, 0xed, 0xbf,
+ 0x80, 0x65, 0x8a, 0xd8, 0xfd, 0x4d, 0x2f, 0xd0, 0xed, 0xff, 0x30, 0x43,
+ 0x72, 0xd8, 0x3e, 0x96, 0x2f, 0xbe, 0x3c, 0x25, 0x8b, 0xff, 0xc1, 0xf8,
+ 0xa4, 0x0d, 0xe0, 0x06, 0x50, 0x58, 0xbb, 0xb0, 0xd6, 0x2a, 0x4f, 0x99,
+ 0x93, 0x2f, 0xfd, 0xda, 0x4b, 0xdc, 0x7e, 0xd8, 0x35, 0x8b, 0xfe, 0xe7,
+ 0x30, 0xb7, 0x62, 0x02, 0xc5, 0xf7, 0x1c, 0x2e, 0x2c, 0x5c, 0xfa, 0x30,
+ 0xf7, 0x78, 0x73, 0x52, 0x8c, 0xdf, 0xc2, 0x7e, 0x96, 0x2e, 0x7d, 0x2c,
+ 0x54, 0x6b, 0x34, 0x7f, 0x0c, 0xa8, 0xdd, 0x7b, 0x4b, 0x23, 0x0a, 0x79,
+ 0x43, 0xfa, 0x5c, 0xf8, 0xe3, 0x43, 0x74, 0x8c, 0x78, 0x7b, 0xe8, 0x44,
+ 0x0a, 0x1d, 0xbd, 0x92, 0xaf, 0xff, 0xde, 0x92, 0x70, 0x67, 0x5e, 0xd3,
+ 0x85, 0x13, 0xac, 0x5f, 0x9b, 0x0f, 0x3b, 0xac, 0x5e, 0x26, 0x02, 0xc5,
+ 0xfc, 0xdb, 0x7d, 0xe4, 0x96, 0x2f, 0x0f, 0xee, 0xb1, 0x58, 0x8e, 0x53,
+ 0x55, 0xfe, 0x50, 0x10, 0xe0, 0x65, 0xb7, 0xfe, 0x6f, 0x70, 0x2c, 0xf8,
+ 0x1b, 0xcb, 0x17, 0xe0, 0x60, 0xda, 0x0b, 0x17, 0x37, 0x65, 0x8b, 0x76,
+ 0x58, 0xb0, 0xdc, 0xd6, 0xb0, 0xcd, 0xf7, 0x61, 0x31, 0x2c, 0x5f, 0x68,
+ 0xf3, 0xc5, 0x8b, 0xff, 0xec, 0xc2, 0x98, 0x7b, 0xec, 0x72, 0xce, 0xcb,
+ 0x17, 0xd9, 0xe9, 0xdc, 0xc3, 0xf2, 0x22, 0x3a, 0xd9, 0x3d, 0x51, 0xa6,
+ 0x69, 0x00, 0x0a, 0xa4, 0x4a, 0x14, 0x25, 0xac, 0x35, 0x8b, 0x87, 0x12,
+ 0xc5, 0x6e, 0x6a, 0xc3, 0x12, 0xbf, 0xf7, 0x67, 0x20, 0x63, 0xc4, 0xdd,
+ 0x2c, 0x5c, 0xe4, 0xb1, 0x7f, 0xfd, 0x9b, 0xc9, 0x9f, 0x9c, 0x03, 0x10,
+ 0xb1, 0x62, 0xa5, 0x14, 0xd0, 0x41, 0xf8, 0xb5, 0xf0, 0xc5, 0x20, 0x58,
+ 0xbd, 0x9d, 0x41, 0x62, 0xb4, 0x78, 0x21, 0x11, 0xdf, 0xfc, 0xe7, 0x26,
+ 0x37, 0x9f, 0x92, 0xf2, 0xc5, 0xfe, 0x6d, 0x36, 0x44, 0xe7, 0x58, 0xbf,
+ 0x71, 0xbe, 0xfc, 0x58, 0xba, 0x60, 0xb1, 0x68, 0x2c, 0x57, 0xcd, 0x48,
+ 0x62, 0xf7, 0xf0, 0x45, 0x80, 0x17, 0x16, 0x2f, 0xfd, 0x84, 0xdf, 0xc7,
+ 0x3c, 0x8d, 0x62, 0xa4, 0xfa, 0xdc, 0xbe, 0xe9, 0xd2, 0xc5, 0x1a, 0x8c,
+ 0x4d, 0x42, 0x34, 0x22, 0x0b, 0xff, 0xff, 0xd0, 0xe7, 0xd9, 0xfc, 0x2d,
+ 0x37, 0x30, 0xa6, 0x03, 0xd3, 0xf5, 0x05, 0x8b, 0xc1, 0xf7, 0x04, 0xb1,
+ 0x7f, 0xfc, 0x0c, 0x1f, 0xb8, 0xfe, 0xfe, 0x76, 0x1c, 0xac, 0x5c, 0xfd,
+ 0x2c, 0x56, 0xc8, 0x8d, 0xd1, 0x1f, 0x94, 0xad, 0xb2, 0xc5, 0xf9, 0xfd,
+ 0x13, 0x84, 0xb1, 0x58, 0x6f, 0x58, 0x4e, 0xfe, 0x1f, 0xe4, 0x26, 0xf2,
+ 0xc5, 0xff, 0xb0, 0x8d, 0xcd, 0x7b, 0xcf, 0xa5, 0x8b, 0xdf, 0x63, 0x56,
+ 0x2f, 0x6c, 0xfa, 0x94, 0x46, 0x61, 0x7f, 0x8f, 0xeb, 0xe8, 0xeb, 0x28,
+ 0x55, 0xdf, 0xc1, 0x9c, 0xcc, 0xeb, 0xcb, 0x17, 0xff, 0xf3, 0x6b, 0x0e,
+ 0xdd, 0x6a, 0x7c, 0xe0, 0xe3, 0x74, 0xb1, 0x6f, 0x71, 0x11, 0xde, 0x32,
+ 0xbf, 0xfd, 0xe8, 0x61, 0x38, 0xf2, 0x12, 0x0e, 0x2c, 0x5f, 0xe1, 0x1a,
+ 0x64, 0x99, 0xc7, 0x58, 0xa9, 0x4d, 0x7b, 0x21, 0x6a, 0xc5, 0x24, 0x93,
+ 0x7f, 0xe0, 0x66, 0x9c, 0x18, 0x0d, 0x1d, 0x62, 0xff, 0xf1, 0xb3, 0xcd,
+ 0x4f, 0xcb, 0x3d, 0x27, 0x58, 0xbc, 0x61, 0x77, 0xeb, 0x17, 0xff, 0x48,
+ 0xbb, 0xf8, 0x39, 0xa6, 0xc9, 0x79, 0x62, 0xfe, 0x3b, 0x43, 0x82, 0x75,
+ 0x8a, 0x58, 0xb0, 0x8e, 0x6e, 0x83, 0x2e, 0xbf, 0xfb, 0x3d, 0xf7, 0x83,
+ 0xeb, 0x61, 0x01, 0x62, 0xff, 0x43, 0x38, 0x1e, 0xc2, 0x25, 0x8a, 0xdc,
+ 0xff, 0x04, 0x8d, 0x7f, 0x8b, 0x3b, 0x3c, 0x4e, 0x12, 0xc5, 0x41, 0x3a,
+ 0x5d, 0x11, 0xfe, 0x10, 0xa5, 0x0a, 0x4e, 0x11, 0xdf, 0xff, 0xc2, 0x6d,
+ 0xb7, 0x16, 0xde, 0xcf, 0x96, 0x7b, 0xee, 0xb1, 0x7e, 0x98, 0x88, 0x5c,
+ 0x58, 0xac, 0x55, 0x94, 0xf1, 0xf7, 0xfd, 0x53, 0xcb, 0xd7, 0x39, 0x2c,
+ 0x5d, 0xe3, 0x56, 0x2f, 0xb4, 0xf1, 0x71, 0x62, 0xf3, 0x10, 0x30, 0xde,
+ 0xe8, 0x66, 0xa5, 0x96, 0xe5, 0xb4, 0x22, 0x61, 0x0c, 0x9c, 0x70, 0x34,
+ 0x8f, 0x74, 0x48, 0x8c, 0xf5, 0x18, 0xaf, 0xcd, 0xda, 0x30, 0x52, 0x95,
+ 0x6f, 0xc3, 0xff, 0x4b, 0x09, 0xec, 0x87, 0x1c, 0xa7, 0x7c, 0x5e, 0x98,
+ 0xe5, 0x8b, 0xd3, 0xda, 0x56, 0x2f, 0x49, 0x79, 0x62, 0xfa, 0x74, 0xdf,
+ 0x58, 0xa1, 0x9b, 0xee, 0xc3, 0x97, 0x64, 0x4b, 0x17, 0xfb, 0x37, 0x2c,
+ 0xec, 0xe3, 0x58, 0xbe, 0xf8, 0x8f, 0x2b, 0x14, 0xb1, 0x4b, 0x16, 0x63,
+ 0x97, 0x1c, 0x0c, 0xb8, 0x5d, 0xfa, 0xc5, 0xf7, 0xf0, 0x0c, 0xb1, 0x7d,
+ 0xe7, 0xf8, 0x96, 0x2f, 0xec, 0xd7, 0x50, 0xf4, 0xac, 0x5d, 0x31, 0xfd,
+ 0xf5, 0x3d, 0x20, 0xc8, 0xea, 0x37, 0x54, 0x37, 0x24, 0xae, 0xb9, 0x11,
+ 0x1f, 0xc6, 0x18, 0xd4, 0x8e, 0xc4, 0x4b, 0xd8, 0x77, 0xb9, 0xd2, 0xd1,
+ 0x91, 0xbc, 0x6a, 0xc6, 0x7d, 0xec, 0xa6, 0xb8, 0xd2, 0x37, 0x98, 0xda,
+ 0x19, 0x9d, 0xf6, 0x59, 0xdf, 0x21, 0x09, 0xdf, 0x59, 0x51, 0x51, 0xaa,
+ 0x17, 0xd1, 0xac, 0xee, 0x6b, 0x08, 0xcd, 0xa9, 0x05, 0x30, 0x9e, 0x98,
+ 0x1d, 0x62, 0xd3, 0x96, 0x92, 0x70, 0xd9, 0x7a, 0xfb, 0xd2, 0xaa, 0x7a,
+ 0x9f, 0x3c, 0x79, 0xf6, 0x08, 0xf9, 0x40, 0x11, 0x52, 0xa6, 0xb5, 0x4a,
+ 0xd0, 0x3d, 0x2a, 0xa7, 0xf5, 0xfa, 0x13, 0x52, 0xa1, 0x01, 0x3e, 0x1f,
+ 0xdf, 0xc6, 0xa6, 0x54, 0xfe, 0xce, 0x5a, 0xcd, 0xef, 0x5a, 0x17, 0x61,
+ 0x52, 0xff, 0xfb, 0x4a, 0x13, 0x0a, 0x1a, 0x71, 0xd3, 0xde, 0x81, 0xd3,
+ 0xb9, 0xbb, 0xa5, 0x8a, 0x5f, 0xa3, 0x57, 0x89, 0x80, 0xb1, 0x7f, 0x46,
+ 0xd1, 0xb7, 0x89, 0x80, 0xb1, 0x7c, 0xfd, 0x9a, 0x3d, 0x62, 0xe6, 0x35,
+ 0x62, 0xfb, 0x93, 0xa0, 0x2c, 0x5f, 0xb6, 0x3c, 0xf5, 0x19, 0x1b, 0xa3,
+ 0x22, 0x34, 0x2e, 0x81, 0xc3, 0x13, 0xf0, 0x62, 0x99, 0x71, 0xa0, 0x52,
+ 0xfc, 0xef, 0x9c, 0x80, 0xeb, 0x17, 0x98, 0xfc, 0x58, 0xa8, 0x1b, 0xee,
+ 0xc4, 0x37, 0xe3, 0xe3, 0xb0, 0x16, 0x2f, 0xb7, 0x66, 0xdd, 0x52, 0x45,
+ 0x17, 0xff, 0xe6, 0x04, 0xef, 0xf7, 0xe7, 0xdf, 0xdf, 0xc2, 0x58, 0xad,
+ 0x22, 0x18, 0x8c, 0x6f, 0xfd, 0x3e, 0x70, 0x4c, 0x3d, 0xce, 0xf1, 0x62,
+ 0xfd, 0xbc, 0x94, 0x81, 0x62, 0xfb, 0xc6, 0xbe, 0xeb, 0x14, 0xc7, 0x9b,
+ 0xc2, 0x8b, 0xfb, 0x00, 0x1e, 0x98, 0x0b, 0x17, 0x9a, 0x11, 0x92, 0x9d,
+ 0x86, 0x42, 0xb7, 0x44, 0x5f, 0x84, 0x8f, 0x88, 0x6f, 0xfe, 0x96, 0xd1,
+ 0x09, 0xba, 0xcf, 0xb2, 0xc5, 0xfc, 0xe0, 0x63, 0x7e, 0xeb, 0x17, 0xff,
+ 0xde, 0x63, 0x8f, 0xf9, 0x0e, 0x7e, 0x4b, 0xcb, 0x15, 0x87, 0xfc, 0xc5,
+ 0xd7, 0xff, 0xcf, 0x11, 0x4f, 0xb9, 0xee, 0xb7, 0x72, 0xd9, 0x62, 0xff,
+ 0xfb, 0x3f, 0xe7, 0x09, 0xf2, 0x0f, 0xa6, 0x02, 0xc5, 0x0d, 0x14, 0x5c,
+ 0x53, 0xb4, 0x66, 0x2b, 0xe0, 0x3c, 0x7a, 0x7f, 0x67, 0x28, 0x60, 0xf2,
+ 0x18, 0x57, 0xfa, 0x33, 0x35, 0xbb, 0x36, 0xea, 0x93, 0xa0, 0xbf, 0xfa,
+ 0x31, 0xa1, 0x19, 0x9a, 0xdd, 0x9b, 0x75, 0x48, 0x96, 0x5f, 0xd2, 0x0c,
+ 0x3c, 0xee, 0xb1, 0x7e, 0xd6, 0xec, 0xdb, 0xaa, 0x4f, 0x22, 0xfd, 0x9e,
+ 0xf3, 0x92, 0x10, 0x8e, 0xe6, 0xec, 0xb1, 0x68, 0xc1, 0xa2, 0xbb, 0x0b,
+ 0x88, 0xde, 0x38, 0xc2, 0xa6, 0x38, 0x47, 0xdd, 0xa5, 0xcd, 0x42, 0x14,
+ 0x39, 0x0a, 0x5d, 0xe3, 0xaa, 0x8a, 0x31, 0x63, 0xbf, 0xfe, 0xb8, 0x84,
+ 0x69, 0x4a, 0x45, 0x9a, 0xda, 0x47, 0x27, 0x12, 0xbc, 0xc6, 0x24, 0x5e,
+ 0xd1, 0x83, 0xdf, 0xfe, 0x8c, 0x3b, 0x42, 0x33, 0x35, 0xbb, 0x36, 0xea,
+ 0x91, 0x64, 0xbe, 0x8d, 0xcd, 0x8e, 0x8d, 0xd6, 0x2d, 0x1b, 0x2c, 0x5b,
+ 0xb9, 0x62, 0xdf, 0x58, 0xa8, 0xdc, 0xdf, 0x46, 0x82, 0xe2, 0x15, 0xbf,
+ 0xdf, 0xce, 0xa1, 0xa7, 0xe9, 0x62, 0xff, 0x38, 0xff, 0x8e, 0x46, 0xac,
+ 0x5e, 0xfb, 0x1a, 0xb1, 0x7d, 0xf6, 0xf0, 0x96, 0x2f, 0xbf, 0x31, 0xe7,
+ 0x58, 0xbc, 0x07, 0x3a, 0xc5, 0xff, 0xb3, 0xef, 0x02, 0xcc, 0x17, 0x7e,
+ 0xb1, 0x7d, 0xd3, 0x6b, 0x16, 0x2f, 0xfd, 0x8f, 0xd9, 0xc8, 0x50, 0xce,
+ 0x2c, 0x5f, 0xe1, 0x99, 0x3e, 0xd6, 0x0d, 0x62, 0xe0, 0xe3, 0x96, 0x2a,
+ 0x4f, 0x47, 0xe6, 0xb7, 0x85, 0xbb, 0x2c, 0x56, 0xca, 0x88, 0x60, 0x6d,
+ 0xb9, 0x9b, 0x8f, 0x47, 0x91, 0xe8, 0x98, 0xe3, 0xbf, 0x42, 0x22, 0x3f,
+ 0x42, 0x40, 0x32, 0x1b, 0xf7, 0x84, 0xd0, 0xe2, 0xc5, 0xf6, 0x04, 0xc0,
+ 0x58, 0xa1, 0x9e, 0x61, 0x14, 0xdf, 0xf0, 0x0c, 0x7f, 0x72, 0x74, 0x05,
+ 0x8b, 0xfb, 0x99, 0xa6, 0x86, 0x2c, 0x5f, 0x31, 0xbf, 0x75, 0x8a, 0x23,
+ 0xd0, 0xe1, 0x6d, 0xd3, 0xb2, 0xc5, 0xff, 0x98, 0xbd, 0x84, 0x28, 0x67,
+ 0x16, 0x2f, 0xfd, 0x87, 0xe3, 0x40, 0x3e, 0x4e, 0x2c, 0x54, 0x7a, 0x25,
+ 0x3e, 0x31, 0xe3, 0xdb, 0xcf, 0xb7, 0x96, 0x2f, 0xff, 0xff, 0xff, 0xf0,
+ 0x8c, 0x2c, 0x89, 0xf8, 0x23, 0x98, 0x46, 0x99, 0xbf, 0xdf, 0xef, 0x25,
+ 0xed, 0x4f, 0xbf, 0x87, 0x30, 0xcf, 0xc7, 0x2c, 0x54, 0xaa, 0x58, 0xc8,
+ 0x45, 0xbc, 0x2d, 0x7c, 0x66, 0x10, 0xf5, 0xef, 0x84, 0xcb, 0x17, 0xf1,
+ 0xe4, 0x8d, 0xcd, 0x96, 0x2e, 0x63, 0xac, 0x5f, 0xf9, 0xb5, 0x09, 0xf7,
+ 0xe4, 0x5d, 0xfa, 0xc5, 0x46, 0x88, 0xa8, 0xc1, 0xef, 0x17, 0x88, 0x5e,
+ 0xfc, 0x2f, 0x3f, 0xe5, 0x62, 0xff, 0xdf, 0x9f, 0xb9, 0xbe, 0xe3, 0x01,
+ 0x62, 0xff, 0x9a, 0x1c, 0x17, 0xa7, 0xdc, 0x58, 0xbf, 0x7b, 0x52, 0xdb,
+ 0xac, 0x5f, 0xf1, 0x61, 0x67, 0xb5, 0x31, 0x2c, 0x51, 0x1f, 0x0f, 0x0a,
+ 0x6d, 0xd9, 0x62, 0xfd, 0x87, 0xf3, 0xec, 0xb1, 0x74, 0xf1, 0xcd, 0xef,
+ 0x05, 0x2e, 0x6e, 0x2c, 0x5f, 0xff, 0x99, 0xa0, 0xdf, 0x33, 0x36, 0x17,
+ 0x9f, 0xf2, 0xb1, 0x5b, 0x1f, 0x6c, 0x42, 0xf7, 0x0b, 0x4b, 0x17, 0xe8,
+ 0x71, 0xa3, 0xb1, 0x62, 0xfd, 0x26, 0x48, 0xe0, 0xb1, 0x73, 0x6e, 0xa9,
+ 0x0c, 0xca, 0x73, 0xce, 0x62, 0x9b, 0xfd, 0x3d, 0x42, 0x74, 0x78, 0x2c,
+ 0x5f, 0xff, 0xf7, 0x3d, 0xe7, 0xff, 0x50, 0xe1, 0x0b, 0x0d, 0x35, 0xda,
+ 0x0b, 0x16, 0xc0, 0x22, 0x7f, 0xc6, 0xb7, 0xff, 0xfd, 0x0c, 0x31, 0xbc,
+ 0x29, 0x30, 0x65, 0x3a, 0xd3, 0xe1, 0xd6, 0x2a, 0x53, 0xc7, 0xdd, 0xe7,
+ 0x50, 0xbf, 0x62, 0x8b, 0xf9, 0xe4, 0xfb, 0x60, 0x4b, 0x17, 0x14, 0x16,
+ 0x2c, 0x75, 0x8b, 0xed, 0x7d, 0xa3, 0x34, 0x7b, 0x07, 0x2f, 0x0c, 0x5e,
+ 0xff, 0xdd, 0x19, 0xe9, 0x33, 0x83, 0x78, 0x96, 0x29, 0xd1, 0x1c, 0xc9,
+ 0x56, 0xfa, 0xc5, 0xd3, 0xa5, 0x8b, 0x3e, 0xe6, 0xa7, 0xb0, 0x95, 0xff,
+ 0xfc, 0x3c, 0xde, 0x7f, 0x27, 0x30, 0x84, 0xde, 0x9d, 0x2c, 0x5d, 0xc1,
+ 0x2c, 0x54, 0x0f, 0xd3, 0xa5, 0xcb, 0xfd, 0xd0, 0x38, 0xfe, 0x29, 0x58,
+ 0xbe, 0x7d, 0x36, 0x96, 0x2e, 0xe4, 0x7a, 0xc5, 0x40, 0xde, 0xf8, 0x8a,
+ 0xff, 0xfe, 0x86, 0x73, 0xc2, 0xdb, 0x7f, 0xbc, 0x5f, 0x9d, 0xb1, 0x62,
+ 0xa5, 0x31, 0x5c, 0x23, 0x67, 0x11, 0x10, 0xdf, 0xfd, 0xc7, 0x17, 0x30,
+ 0x85, 0x0c, 0xe2, 0xc5, 0xff, 0xff, 0xf1, 0x0a, 0x19, 0xcc, 0xf0, 0x9b,
+ 0xdf, 0xcd, 0xfe, 0xf1, 0x7e, 0x76, 0xc5, 0x8b, 0xa7, 0xa5, 0x8b, 0xce,
+ 0x5b, 0xac, 0x53, 0xa2, 0xd3, 0x8f, 0xfe, 0x18, 0xbf, 0xfb, 0xdc, 0x7f,
+ 0x14, 0x89, 0xb4, 0x6a, 0xc5, 0xce, 0x75, 0x8b, 0x77, 0xee, 0x7b, 0x9d,
+ 0xc8, 0xb7, 0xf4, 0xf4, 0x13, 0x7f, 0x8b, 0x15, 0xb3, 0x24, 0xf6, 0x05,
+ 0x03, 0x40, 0xc8, 0x4d, 0xee, 0xbc, 0xf0, 0x98, 0x88, 0x93, 0x51, 0xef,
+ 0x9e, 0x32, 0x8f, 0xa5, 0x14, 0x76, 0x5c, 0x3b, 0xf4, 0x3e, 0x05, 0x08,
+ 0xbe, 0xe2, 0xfb, 0xfc, 0xc1, 0x7d, 0xe7, 0x52, 0xb1, 0x7f, 0xff, 0xfe,
+ 0x61, 0xf3, 0xf8, 0x72, 0x7d, 0x8c, 0x38, 0x89, 0x8d, 0xf9, 0x67, 0xb5,
+ 0x8b, 0x15, 0xa4, 0x5b, 0x91, 0x9d, 0xff, 0xfc, 0xfe, 0xf3, 0xf0, 0x3d,
+ 0xa7, 0x62, 0xc0, 0x0b, 0x8b, 0x17, 0xff, 0xf6, 0x6d, 0xdd, 0xe7, 0xe1,
+ 0x9f, 0xcf, 0x96, 0x7b, 0x8b, 0x15, 0xf4, 0x5f, 0x12, 0xf5, 0xfb, 0xce,
+ 0x79, 0x89, 0x62, 0xff, 0xff, 0xff, 0x10, 0xbb, 0x8c, 0xdf, 0xe2, 0xf4,
+ 0x96, 0x6d, 0xcd, 0xfe, 0x22, 0xeb, 0x27, 0xe5, 0x8b, 0x17, 0xf6, 0x49,
+ 0x93, 0xc3, 0xac, 0x56, 0x23, 0xb1, 0xca, 0x79, 0x09, 0x5b, 0x12, 0xc5,
+ 0xfc, 0xc1, 0x78, 0x98, 0xd5, 0x8a, 0xc3, 0xc0, 0x21, 0x1a, 0x82, 0x24,
+ 0xfc, 0xe7, 0x7d, 0xad, 0x37, 0x16, 0x2f, 0xdf, 0xc2, 0x63, 0xac, 0x5f,
+ 0x75, 0xf9, 0xe2, 0xc5, 0xe8, 0x98, 0x96, 0x2f, 0xfe, 0x1e, 0x39, 0x1b,
+ 0x9f, 0x97, 0x1a, 0xc5, 0xf6, 0xf2, 0x5e, 0x58, 0xbe, 0xdb, 0xf2, 0x6a,
+ 0xc5, 0xe9, 0xf7, 0x16, 0x2f, 0xfd, 0x86, 0xf2, 0x70, 0x87, 0xf9, 0x58,
+ 0xae, 0x1e, 0xd8, 0x87, 0x6f, 0xa4, 0x0d, 0xe5, 0x8a, 0x31, 0x3b, 0x58,
+ 0x11, 0xe1, 0x3c, 0x44, 0x9a, 0x1d, 0x3a, 0x1b, 0x11, 0xf2, 0x10, 0x11,
+ 0xc4, 0x57, 0xee, 0xe2, 0x60, 0x86, 0xb1, 0x7f, 0x6b, 0x6d, 0x60, 0xf1,
+ 0x62, 0xfe, 0x62, 0xdb, 0x58, 0x35, 0x8a, 0x93, 0xdd, 0x11, 0x7d, 0xff,
+ 0xde, 0x7d, 0x30, 0x0c, 0xea, 0x12, 0x75, 0x8b, 0xff, 0xa4, 0xe6, 0xb6,
+ 0xb0, 0x1c, 0x6d, 0xd6, 0x2f, 0xc5, 0x30, 0xe3, 0x2c, 0x54, 0xa6, 0xbd,
+ 0x08, 0x44, 0xb9, 0x09, 0x23, 0xf6, 0x46, 0xbf, 0x7d, 0xca, 0x7e, 0xb1,
+ 0x7f, 0xbf, 0x27, 0xee, 0xc6, 0x89, 0x62, 0x86, 0x7b, 0xdb, 0x93, 0xdc,
+ 0x46, 0xac, 0x5b, 0xeb, 0x17, 0xff, 0x7e, 0x46, 0x61, 0x67, 0x39, 0x3b,
+ 0xac, 0x5f, 0xff, 0xfd, 0xe7, 0x3e, 0x9f, 0x3a, 0x21, 0x7a, 0x7e, 0x67,
+ 0x67, 0xf4, 0x52, 0xb1, 0x58, 0x8c, 0xe7, 0x12, 0xf2, 0x35, 0xfe, 0x3f,
+ 0xdb, 0xcc, 0x40, 0x58, 0xbf, 0xed, 0xcc, 0xdd, 0xf8, 0x22, 0xdd, 0x62,
+ 0xff, 0xff, 0xff, 0xf7, 0x0b, 0x00, 0x09, 0x23, 0x37, 0xf8, 0xbd, 0x25,
+ 0x9b, 0x73, 0x7f, 0x88, 0xba, 0xc9, 0xf9, 0x62, 0xc5, 0x4a, 0x63, 0x18,
+ 0x66, 0x11, 0xf5, 0xe0, 0xe4, 0x0b, 0x17, 0xf1, 0x60, 0xff, 0x21, 0x2c,
+ 0x59, 0x88, 0xf3, 0x3b, 0x0f, 0x5d, 0x90, 0x58, 0xbf, 0x00, 0x65, 0x9f,
+ 0x58, 0xa9, 0x56, 0x64, 0x32, 0x3c, 0x87, 0x33, 0xc6, 0x8d, 0xa7, 0xc3,
+ 0x94, 0x30, 0xbd, 0xfd, 0xe6, 0xf9, 0x83, 0x95, 0x8b, 0xde, 0x72, 0x58,
+ 0xbf, 0x71, 0xfd, 0xa7, 0x58, 0xbb, 0x38, 0xb1, 0x7d, 0xc6, 0x28, 0x2c,
+ 0x5a, 0x10, 0x37, 0x3c, 0x17, 0xbd, 0xb7, 0x38, 0xb1, 0x70, 0x43, 0x58,
+ 0xbe, 0xfb, 0x08, 0xeb, 0x17, 0xff, 0x67, 0x77, 0xbb, 0x8a, 0x7c, 0x29,
+ 0xe9, 0x62, 0xe1, 0x69, 0x62, 0xde, 0xf9, 0xf1, 0xf1, 0x2e, 0x9d, 0x15,
+ 0xc5, 0x08, 0x6a, 0x94, 0xf7, 0xfa, 0x2f, 0x71, 0xc6, 0x61, 0x22, 0x7f,
+ 0x0f, 0x8a, 0x18, 0xf7, 0x30, 0xd6, 0x2f, 0xd0, 0x62, 0x16, 0xeb, 0x15,
+ 0xb9, 0xe0, 0x74, 0x2f, 0x73, 0x6e, 0xb1, 0x74, 0xc7, 0xac, 0x5f, 0xc5,
+ 0x3b, 0xed, 0x81, 0x2c, 0x56, 0xc7, 0xc5, 0xdf, 0x8c, 0x78, 0x6a, 0xff,
+ 0xde, 0x62, 0x01, 0x81, 0xe7, 0x41, 0x2c, 0x5f, 0x7b, 0xd2, 0x75, 0x8b,
+ 0xe8, 0x79, 0xf6, 0x58, 0xbf, 0xff, 0x49, 0x4f, 0x0c, 0x7f, 0xef, 0x24,
+ 0x59, 0xe5, 0x8a, 0xc4, 0x6f, 0x1a, 0x86, 0xc4, 0x7c, 0x24, 0xbf, 0xfe,
+ 0x93, 0x8a, 0x76, 0x33, 0x58, 0xff, 0x91, 0xac, 0x5f, 0x31, 0x07, 0xc5,
+ 0x8b, 0xc5, 0x9b, 0xac, 0x5f, 0xf3, 0xf9, 0xcf, 0x17, 0x1c, 0x96, 0x2f,
+ 0xff, 0xed, 0x67, 0xb9, 0xf6, 0x80, 0xa7, 0x3d, 0x3d, 0x41, 0x62, 0xb7,
+ 0x44, 0xae, 0x8e, 0x6f, 0xfd, 0x2f, 0xaf, 0x7b, 0x27, 0x40, 0x58, 0xb7,
+ 0xa4, 0xf8, 0xa2, 0x24, 0xbf, 0x6e, 0xfa, 0x3c, 0x16, 0x2f, 0xf1, 0xf3,
+ 0x40, 0x21, 0x01, 0x62, 0xd0, 0x58, 0xa8, 0x27, 0x9f, 0x84, 0x6f, 0x18,
+ 0xa7, 0xca, 0x18, 0xa8, 0x33, 0x4b, 0xf0, 0x27, 0xd2, 0x35, 0x8a, 0x95,
+ 0xc7, 0x9c, 0x84, 0x33, 0xc6, 0x27, 0xf3, 0xc6, 0x94, 0x40, 0x25, 0xcb,
+ 0xe1, 0xb8, 0xb7, 0x58, 0xbf, 0xde, 0x26, 0x33, 0x7d, 0xf1, 0x62, 0xf9,
+ 0xf7, 0x6d, 0x2c, 0x5f, 0xff, 0x0b, 0xdc, 0xea, 0x12, 0x40, 0xe1, 0x82,
+ 0x25, 0x8b, 0xd3, 0xe9, 0x58, 0xa8, 0x22, 0x48, 0x64, 0x7d, 0x94, 0xef,
+ 0xe9, 0xf8, 0xba, 0x87, 0x16, 0x2f, 0x38, 0xbb, 0xf5, 0x8b, 0xfd, 0x3a,
+ 0x62, 0x2c, 0x35, 0x62, 0x88, 0xf5, 0x3c, 0x45, 0x78, 0x5e, 0x12, 0xc5,
+ 0x39, 0xbf, 0x39, 0x0d, 0xff, 0xfc, 0x28, 0x3f, 0x24, 0xfb, 0xfd, 0xe2,
+ 0xfc, 0xed, 0x8b, 0x17, 0xbf, 0x84, 0xb1, 0x58, 0xa9, 0xef, 0xa2, 0x47,
+ 0x86, 0x44, 0x46, 0x5f, 0x86, 0x19, 0x10, 0x09, 0x7a, 0xef, 0xc4, 0xb1,
+ 0x7d, 0x91, 0x64, 0x4b, 0x17, 0xed, 0x0b, 0xd9, 0xb2, 0xc5, 0xf6, 0x68,
+ 0x72, 0xb1, 0x6e, 0x18, 0x7e, 0x12, 0x48, 0x45, 0x56, 0xfa, 0xc5, 0x74,
+ 0x78, 0xcc, 0x69, 0x7c, 0x42, 0x60, 0xd6, 0x2e, 0xc2, 0x58, 0xb4, 0xec,
+ 0x6e, 0x60, 0x47, 0x7e, 0xe9, 0xf7, 0x71, 0xac, 0x53, 0xa6, 0xf6, 0xd0,
+ 0xcf, 0x02, 0xd8, 0x64, 0xf7, 0xb3, 0x37, 0x58, 0xbf, 0xee, 0x06, 0x59,
+ 0xee, 0x06, 0x75, 0x8b, 0xfd, 0xcc, 0xd0, 0x08, 0x40, 0x58, 0xac, 0x3f,
+ 0x0f, 0x1e, 0x5f, 0xfd, 0x3e, 0xe7, 0xe5, 0xfd, 0xc9, 0xd9, 0x62, 0xfd,
+ 0x9a, 0x98, 0xb8, 0xb1, 0x5a, 0x3e, 0xef, 0xa2, 0xdf, 0xff, 0xcf, 0xc2,
+ 0xcd, 0xa7, 0x7f, 0xbc, 0x5f, 0x9d, 0xb1, 0x62, 0xf3, 0x7e, 0x56, 0x2a,
+ 0x07, 0xf3, 0xe5, 0xdb, 0xef, 0x7c, 0x51, 0xcb, 0x17, 0xfb, 0x27, 0x4d,
+ 0x07, 0xfa, 0xc5, 0xfe, 0x70, 0xb9, 0x3f, 0x68, 0xf5, 0x8a, 0xd1, 0xf4,
+ 0xf8, 0xca, 0xfd, 0xef, 0xf5, 0x9d, 0xcb, 0x17, 0xb1, 0xf6, 0x58, 0xa1,
+ 0xa7, 0x73, 0xd4, 0x26, 0xdc, 0x88, 0xf0, 0x90, 0xf9, 0x17, 0x0b, 0x6f,
+ 0x4f, 0xb8, 0xb1, 0x7e, 0xe3, 0x1b, 0xf7, 0x58, 0xbf, 0xe8, 0xf1, 0xfc,
+ 0x5c, 0xea, 0x0c, 0xb1, 0x73, 0xff, 0x0f, 0xa0, 0x45, 0x35, 0x2a, 0xd6,
+ 0xf2, 0x52, 0x43, 0xb1, 0x34, 0x21, 0x6d, 0x8b, 0x17, 0xf4, 0x26, 0x12,
+ 0x78, 0x2c, 0x56, 0xc6, 0xfd, 0xc4, 0x6f, 0xff, 0x84, 0xda, 0x86, 0xff,
+ 0x71, 0xe9, 0xc5, 0xb2, 0xc5, 0xfc, 0xe6, 0x87, 0xc9, 0xc5, 0x8b, 0xb2,
+ 0x36, 0x58, 0xad, 0x1e, 0x58, 0x65, 0xf7, 0xff, 0x6a, 0x41, 0xf7, 0x9d,
+ 0x00, 0xf0, 0x58, 0xbe, 0x8b, 0xee, 0x05, 0x8b, 0xe9, 0xfc, 0x81, 0x62,
+ 0xa5, 0x11, 0x66, 0xa2, 0xc7, 0x12, 0x5f, 0xff, 0x89, 0x82, 0xf6, 0x7c,
+ 0xce, 0xf3, 0xbc, 0x8d, 0xfb, 0xeb, 0xde, 0xf7, 0x8b, 0x17, 0x67, 0xd6,
+ 0x2f, 0xfe, 0x01, 0xdc, 0xb0, 0x05, 0x8d, 0x12, 0xc5, 0x61, 0xed, 0x08,
+ 0x5e, 0xff, 0x3f, 0xde, 0x4a, 0x21, 0x2c, 0x5e, 0x9f, 0xf7, 0xab, 0x17,
+ 0xec, 0xc2, 0xeb, 0xcb, 0x17, 0xfc, 0x2d, 0x37, 0x0c, 0xf6, 0xc1, 0x2c,
+ 0x59, 0xf4, 0x7c, 0xde, 0x28, 0xa9, 0x47, 0x13, 0x99, 0xb4, 0x22, 0x2f,
+ 0xb6, 0xfe, 0x79, 0x62, 0xff, 0xa0, 0xc4, 0x03, 0x02, 0xcf, 0xac, 0x5f,
+ 0xa2, 0xe7, 0x1e, 0x25, 0x8b, 0xfe, 0x1e, 0xb0, 0x5f, 0x93, 0xe2, 0xc5,
+ 0x62, 0x27, 0xdc, 0xec, 0x45, 0x77, 0xff, 0xbb, 0x61, 0x81, 0xf9, 0xf4,
+ 0xfb, 0x31, 0xd6, 0x2f, 0xf1, 0x00, 0x3f, 0xfd, 0xb6, 0x58, 0xac, 0x44,
+ 0x2b, 0xa7, 0xdf, 0x47, 0x66, 0xa5, 0x62, 0xff, 0xfe, 0x8e, 0xc3, 0x0b,
+ 0x36, 0x0e, 0x06, 0x73, 0x8e, 0x17, 0x16, 0x2d, 0x9b, 0x22, 0x24, 0x04,
+ 0xb5, 0xf4, 0x69, 0x94, 0x2a, 0xaa, 0x57, 0x86, 0x46, 0x43, 0x90, 0x9e,
+ 0x78, 0x57, 0x44, 0x67, 0xa8, 0x6a, 0x7e, 0x30, 0x36, 0x32, 0xe4, 0x30,
+ 0xfd, 0x1c, 0x35, 0xbc, 0xb1, 0x7f, 0xfb, 0x53, 0xf6, 0x7f, 0x4f, 0xcb,
+ 0xa7, 0x58, 0xa8, 0x8f, 0x6c, 0x84, 0xaf, 0xfd, 0xf9, 0xd0, 0x35, 0xa9,
+ 0x3f, 0x16, 0x2f, 0xcd, 0xc2, 0x79, 0x58, 0xbf, 0xf9, 0xf4, 0x3f, 0x8b,
+ 0x59, 0xbf, 0xf1, 0x62, 0xfc, 0xfa, 0x6e, 0xe7, 0x58, 0xa8, 0x1f, 0x86,
+ 0xe8, 0xd7, 0xf6, 0xcd, 0xb1, 0x0b, 0xcb, 0x17, 0xfd, 0x81, 0x7f, 0x00,
+ 0x79, 0xd2, 0xc5, 0xff, 0x38, 0x3f, 0xbb, 0xf3, 0x06, 0xb1, 0x60, 0x2c,
+ 0x56, 0x8f, 0x30, 0x8e, 0xaf, 0xbc, 0x26, 0xf2, 0xc5, 0xfa, 0x7d, 0xac,
+ 0x1a, 0xc5, 0xf7, 0xb5, 0x83, 0x58, 0xb7, 0x0c, 0x3c, 0xb9, 0x28, 0xbc,
+ 0x26, 0xf2, 0xc5, 0x18, 0x8b, 0x33, 0xb7, 0x78, 0xa2, 0xf7, 0x6c, 0xd2,
+ 0xc5, 0x49, 0xe8, 0x61, 0x8d, 0xf8, 0x13, 0xdb, 0x09, 0x62, 0xf3, 0x10,
+ 0x16, 0x29, 0x8f, 0x14, 0x45, 0x35, 0x2a, 0xde, 0xf0, 0x88, 0xd4, 0x0e,
+ 0xa1, 0x2c, 0xe4, 0x7a, 0x30, 0x68, 0x43, 0x14, 0x64, 0x9c, 0x65, 0xbe,
+ 0xe3, 0xf9, 0xd6, 0x2e, 0x10, 0xd6, 0x2a, 0x36, 0x37, 0x42, 0x22, 0xbf,
+ 0xa2, 0x7f, 0xeb, 0x0e, 0xb1, 0x7c, 0x1f, 0x27, 0x16, 0x2e, 0x70, 0x96,
+ 0x2e, 0xee, 0xc5, 0x8a, 0x64, 0x42, 0x00, 0xbf, 0x84, 0x7e, 0x18, 0xbf,
+ 0xb9, 0x3e, 0xe7, 0xdd, 0x62, 0xfc, 0x58, 0x7d, 0x62, 0xc5, 0xf6, 0xd0,
+ 0x61, 0xac, 0x5e, 0xed, 0x83, 0x58, 0xb9, 0xfe, 0xb1, 0x5a, 0x36, 0xdf,
+ 0x1f, 0xac, 0x46, 0x81, 0xcb, 0x98, 0x9c, 0x4b, 0x57, 0xfb, 0x7f, 0xe7,
+ 0x5e, 0x0c, 0xeb, 0x17, 0xef, 0xce, 0x8f, 0x05, 0x8b, 0xc3, 0xcf, 0x2c,
+ 0x5f, 0xff, 0xf1, 0x6e, 0xde, 0x6e, 0x81, 0xf0, 0x98, 0xb6, 0xff, 0x4d,
+ 0x1e, 0xb1, 0x7f, 0xf8, 0x47, 0x0c, 0x63, 0x90, 0x1e, 0x73, 0xcb, 0x16,
+ 0x04, 0xa2, 0xe8, 0x9b, 0xaf, 0xd9, 0xd7, 0xb3, 0xa5, 0x8b, 0xfd, 0x84,
+ 0x67, 0xe7, 0x23, 0xd6, 0x2f, 0xfc, 0xfe, 0xe6, 0x0e, 0x22, 0x91, 0xac,
+ 0x5f, 0x01, 0xfa, 0x82, 0xc5, 0xfe, 0x92, 0xf3, 0xec, 0x52, 0xb1, 0x7f,
+ 0xf9, 0xf4, 0xfb, 0x49, 0x67, 0xf4, 0x2e, 0xcb, 0x15, 0x2a, 0xa8, 0x20,
+ 0x70, 0x32, 0x9e, 0xa1, 0xaf, 0xa2, 0x73, 0x95, 0x7c, 0xd8, 0x07, 0xe4,
+ 0x49, 0xe3, 0x2b, 0xff, 0xd2, 0x5b, 0xb7, 0x98, 0xd0, 0xf6, 0x9d, 0x96,
+ 0x2f, 0xfc, 0xe3, 0x17, 0xb8, 0xde, 0x63, 0x56, 0x2f, 0xec, 0x0b, 0xa8,
+ 0x70, 0xc3, 0x51, 0x1c, 0xc9, 0xd7, 0xff, 0xf6, 0x16, 0x1b, 0xf6, 0x8b,
+ 0xec, 0x6e, 0x6b, 0x3c, 0xb1, 0x7f, 0xf0, 0x73, 0xd0, 0x64, 0x58, 0xfd,
+ 0x79, 0x62, 0x9d, 0x1d, 0x9f, 0x49, 0x65, 0xca, 0x8d, 0xdd, 0xfc, 0x64,
+ 0x68, 0xe1, 0x32, 0x96, 0x76, 0x87, 0x7c, 0x25, 0x3c, 0x8e, 0x1f, 0x99,
+ 0x49, 0x7e, 0x36, 0x3b, 0x0d, 0xe1, 0xc1, 0xd4, 0x74, 0x2f, 0x1e, 0xc4,
+ 0x51, 0xf2, 0xea, 0x5e, 0xf9, 0xe5, 0x26, 0x7e, 0x74, 0x81, 0xa5, 0x71,
+ 0x82, 0x3e, 0xae, 0xfd, 0x08, 0xa5, 0xf4, 0x72, 0x7a, 0x7f, 0xd3, 0x90,
+ 0x22, 0x86, 0x3f, 0x68, 0x55, 0x47, 0x46, 0x18, 0x1c, 0xad, 0xbe, 0xe9,
+ 0x41, 0x77, 0xee, 0xf3, 0x6d, 0x9f, 0xeb, 0x17, 0xfd, 0xe9, 0x1e, 0xb5,
+ 0x27, 0xe2, 0xc5, 0xfd, 0x2d, 0xa0, 0xe4, 0x0b, 0x17, 0xfa, 0x18, 0x40,
+ 0xcc, 0x1a, 0xc5, 0xfe, 0x92, 0xf1, 0x49, 0xf8, 0xb1, 0x7f, 0x86, 0xe5,
+ 0xe2, 0x90, 0x2c, 0x5c, 0x5b, 0x2c, 0x54, 0x11, 0x5c, 0x33, 0x2d, 0xcc,
+ 0x9c, 0xca, 0xfe, 0xfc, 0xc4, 0x27, 0xd2, 0xc5, 0xc6, 0xee, 0xb1, 0x7f,
+ 0x1e, 0x13, 0x3c, 0x75, 0x8b, 0xdb, 0x0b, 0x65, 0x8b, 0xf1, 0xb2, 0x59,
+ 0xc5, 0x8b, 0x98, 0x0b, 0x15, 0x28, 0x8c, 0xc2, 0xd7, 0x20, 0x62, 0x8b,
+ 0xe1, 0xb3, 0x74, 0xb1, 0x7f, 0x3f, 0x4f, 0xbc, 0x86, 0xb1, 0x70, 0xb7,
+ 0x58, 0xa6, 0x3e, 0xc2, 0x23, 0xe1, 0x85, 0xe7, 0x0c, 0xeb, 0x17, 0xc5,
+ 0xc0, 0xf8, 0xb1, 0x7e, 0xcc, 0xff, 0x9d, 0x62, 0xff, 0x11, 0x4f, 0x47,
+ 0x6f, 0x2c, 0x5f, 0xfa, 0x0e, 0x30, 0xfd, 0xd6, 0xee, 0x75, 0x8b, 0xff,
+ 0x99, 0xfc, 0x2d, 0x37, 0x0c, 0x08, 0x96, 0x2f, 0xff, 0x7f, 0x08, 0x9b,
+ 0xd2, 0x5e, 0x8e, 0xc5, 0x8a, 0x1a, 0x65, 0xae, 0x4f, 0x11, 0x9f, 0xd0,
+ 0xfc, 0x8d, 0x73, 0x76, 0x58, 0xbf, 0xdb, 0x67, 0xa4, 0x9c, 0x0b, 0x15,
+ 0xb9, 0xe6, 0x38, 0xcd, 0xfe, 0x6d, 0x87, 0xf9, 0xe7, 0x4b, 0x17, 0xff,
+ 0x6d, 0x9e, 0x92, 0x70, 0x67, 0x5e, 0x58, 0xbf, 0xd1, 0x41, 0xb5, 0xb7,
+ 0xc4, 0xb1, 0x68, 0x96, 0x29, 0x62, 0xf9, 0x88, 0x1e, 0x92, 0xff, 0x04,
+ 0xea, 0x51, 0x9e, 0x74, 0x58, 0xe5, 0x6b, 0xbd, 0x19, 0x1a, 0x2f, 0x44,
+ 0xc9, 0x80, 0xce, 0xb2, 0x1b, 0x9b, 0x9e, 0x9c, 0xbf, 0xf0, 0xa6, 0x68,
+ 0x52, 0x80, 0xb7, 0xbf, 0x1e, 0xe4, 0x6a, 0x3e, 0x84, 0xbc, 0x71, 0x10,
+ 0x71, 0x82, 0xdf, 0xff, 0xfc, 0x2e, 0xa1, 0x18, 0xc5, 0xec, 0x3f, 0x07,
+ 0xf9, 0xd0, 0xd9, 0x82, 0x58, 0xbd, 0xd8, 0x0e, 0xb1, 0x7f, 0xa4, 0xde,
+ 0xa1, 0xe9, 0x09, 0x62, 0xfd, 0x21, 0x6a, 0x4e, 0xb1, 0x50, 0x3e, 0x02,
+ 0x37, 0xbd, 0x21, 0x46, 0x77, 0xc4, 0x50, 0x63, 0xfd, 0x46, 0x32, 0xba,
+ 0x72, 0x91, 0x30, 0x50, 0xfd, 0xf4, 0x62, 0xf7, 0xff, 0xa3, 0x0e, 0xd0,
+ 0x8c, 0xcd, 0x6e, 0xcd, 0xba, 0xa4, 0x69, 0x2f, 0xff, 0x46, 0x1d, 0xa1,
+ 0x19, 0x9a, 0xdd, 0x9b, 0x75, 0x48, 0xe2, 0x5e, 0x01, 0x4a, 0xc5, 0xfa,
+ 0x0e, 0x40, 0x75, 0x8b, 0xf4, 0x33, 0xd0, 0x82, 0xc5, 0xfe, 0xed, 0x3f,
+ 0x30, 0xa6, 0x0b, 0x17, 0xff, 0xb7, 0xdb, 0x3e, 0xd8, 0x52, 0x2e, 0xff,
+ 0x8b, 0x17, 0xed, 0x6e, 0xcd, 0xba, 0xa4, 0x81, 0x2f, 0xf0, 0x98, 0xb7,
+ 0x80, 0xe3, 0xd6, 0x2f, 0xff, 0xd9, 0xa9, 0xe7, 0xa1, 0x84, 0xe3, 0x80,
+ 0xe3, 0xd6, 0x2f, 0x34, 0x23, 0x20, 0x98, 0xbe, 0x28, 0x00, 0xdf, 0x87,
+ 0x17, 0xff, 0x9e, 0x4e, 0xc3, 0xd4, 0xfb, 0xf8, 0x35, 0x8b, 0xee, 0x17,
+ 0x50, 0x58, 0xb4, 0x64, 0xaa, 0x77, 0xc1, 0xce, 0x89, 0xdc, 0xa4, 0xf1,
+ 0xa6, 0xfd, 0x47, 0xc9, 0x37, 0x46, 0xf1, 0xb2, 0xc5, 0xef, 0xb9, 0xd6,
+ 0x2f, 0xb7, 0x66, 0xdd, 0x52, 0x70, 0x17, 0xf8, 0x7f, 0x98, 0xec, 0xd4,
+ 0xac, 0x56, 0x8f, 0x9c, 0x8c, 0x6e, 0xeb, 0x8b, 0x17, 0xc6, 0xee, 0xc3,
+ 0x58, 0xba, 0x43, 0x58, 0xbf, 0x8b, 0x3d, 0xbb, 0xf1, 0x62, 0xe9, 0x75,
+ 0x8b, 0x86, 0x25, 0x8b, 0xf6, 0x7f, 0x76, 0xd9, 0x62, 0xff, 0xbc, 0x52,
+ 0x06, 0xf0, 0xa5, 0x62, 0xf0, 0x9a, 0x0b, 0x16, 0x82, 0xd0, 0x57, 0xcd,
+ 0x99, 0x0e, 0xdf, 0xe2, 0x84, 0xb8, 0xf0, 0xeb, 0x15, 0x1b, 0x2a, 0x60,
+ 0x19, 0x16, 0x42, 0x13, 0xa2, 0x17, 0x19, 0xd1, 0x29, 0xc6, 0x3e, 0x5c,
+ 0x01, 0x62, 0x18, 0xe1, 0x57, 0x9a, 0xc4, 0x41, 0x7e, 0x84, 0x61, 0xbd,
+ 0xe9, 0xab, 0x17, 0xe7, 0x1f, 0xdc, 0xd5, 0x8b, 0xb3, 0xb2, 0xc5, 0xe3,
+ 0x63, 0x1b, 0x73, 0xc2, 0xf1, 0x4d, 0x46, 0x26, 0xd5, 0x30, 0xbc, 0x77,
+ 0x6b, 0xfd, 0xde, 0x46, 0xfd, 0xec, 0x01, 0x07, 0x58, 0xbf, 0x8f, 0x3e,
+ 0x14, 0x4c, 0xb1, 0x7d, 0xe6, 0x6d, 0x96, 0x2f, 0x75, 0x0e, 0x2c, 0x52,
+ 0xc5, 0x99, 0x8d, 0x58, 0x07, 0xef, 0xd1, 0x42, 0x4a, 0x0b, 0x14, 0xb1,
+ 0x58, 0x6d, 0x48, 0xa6, 0xfd, 0x86, 0x96, 0x01, 0x62, 0xc0, 0x58, 0xa8,
+ 0x1b, 0xa2, 0x28, 0xbc, 0x0c, 0x09, 0x62, 0xf8, 0xa7, 0x3e, 0xb1, 0x52,
+ 0x6f, 0xf6, 0x1e, 0xb9, 0xe3, 0x3b, 0xe2, 0x7e, 0x92, 0x89, 0xd1, 0x7e,
+ 0x93, 0x89, 0x6b, 0xcb, 0x21, 0xaf, 0xde, 0xfb, 0xee, 0xb1, 0x7f, 0xbd,
+ 0xd6, 0xef, 0xcf, 0xba, 0xc5, 0xe3, 0x7e, 0xeb, 0x15, 0x87, 0xa8, 0x23,
+ 0x6a, 0x8f, 0x44, 0x99, 0x39, 0x5f, 0xb5, 0xbb, 0x36, 0xea, 0x91, 0x24,
+ 0xba, 0x11, 0x92, 0x7b, 0x98, 0x4b, 0x5f, 0x4e, 0x5d, 0xa3, 0x68, 0xbf,
+ 0xa0, 0xda, 0xdb, 0xe2, 0x58, 0xbf, 0x72, 0x40, 0x1e, 0xcb, 0x17, 0xe9,
+ 0x36, 0x30, 0x79, 0x11, 0xed, 0xf0, 0xc2, 0xff, 0x4e, 0x46, 0x1d, 0x9b,
+ 0xb9, 0x62, 0xa3, 0x11, 0xfe, 0xf0, 0x84, 0x24, 0x3b, 0xf6, 0x04, 0x01,
+ 0x71, 0x62, 0xe0, 0x80, 0xb1, 0x7f, 0xdf, 0x9d, 0x67, 0x8a, 0x4e, 0xb1,
+ 0x7c, 0x6e, 0x98, 0x25, 0x8a, 0xdc, 0xf7, 0x5c, 0xe2, 0xff, 0x37, 0x8b,
+ 0x36, 0x62, 0x58, 0xbf, 0x4c, 0x45, 0x23, 0x58, 0xb8, 0xd0, 0x96, 0x2f,
+ 0x17, 0x52, 0xb1, 0x7f, 0x3e, 0xc2, 0x8b, 0xa9, 0x58, 0xbf, 0x36, 0xb6,
+ 0x1c, 0xac, 0x54, 0x9e, 0xd4, 0x0c, 0x69, 0x62, 0xf9, 0xba, 0x87, 0x16,
+ 0x2d, 0x9a, 0x36, 0x04, 0x19, 0x7f, 0xfe, 0x11, 0x31, 0xbe, 0x36, 0x4a,
+ 0x19, 0xf7, 0x3a, 0xc5, 0xcd, 0xd2, 0xc5, 0xdd, 0x62, 0xc5, 0xf8, 0xed,
+ 0xf7, 0x89, 0x62, 0x9c, 0xf0, 0x58, 0x62, 0xb4, 0x7f, 0x3e, 0x59, 0xbc,
+ 0xfa, 0x82, 0xc5, 0xff, 0xfb, 0x37, 0x9f, 0xc9, 0xf7, 0xfb, 0xfb, 0x30,
+ 0xeb, 0x17, 0xe3, 0xeb, 0x07, 0xe5, 0x8b, 0xfc, 0xc3, 0x9e, 0xce, 0x5b,
+ 0x2c, 0x5f, 0x02, 0x5e, 0x25, 0x8b, 0xfb, 0xa0, 0xfc, 0x52, 0x05, 0x8b,
+ 0xfb, 0xaf, 0x49, 0x67, 0x16, 0x2a, 0x4f, 0x79, 0xcc, 0x2a, 0x51, 0xfe,
+ 0xe5, 0x20, 0x35, 0x14, 0x20, 0x6f, 0xed, 0xbe, 0xe0, 0x17, 0x16, 0x2f,
+ 0xbf, 0x24, 0x6a, 0xc5, 0x31, 0xe9, 0xf7, 0x18, 0x5f, 0x98, 0x88, 0x5b,
+ 0x2c, 0x58, 0x6b, 0x14, 0xb1, 0x7d, 0x9d, 0x85, 0x2b, 0x16, 0xd9, 0xcd,
+ 0x81, 0x06, 0x56, 0xc7, 0xd0, 0xc8, 0x57, 0x34, 0x66, 0xcb, 0xbd, 0xe3,
+ 0x2a, 0xc7, 0x63, 0x48, 0xb7, 0x32, 0xe8, 0xa1, 0xc6, 0xa2, 0x77, 0xd2,
+ 0x89, 0xc9, 0x5a, 0x19, 0xe0, 0x22, 0x21, 0xde, 0x46, 0xab, 0xe8, 0x49,
+ 0x84, 0x49, 0x1d, 0x09, 0x0b, 0xff, 0xb6, 0x8c, 0xeb, 0xbb, 0x0b, 0x3e,
+ 0xdc, 0x58, 0xad, 0x9f, 0x7b, 0x7e, 0x17, 0x95, 0xa9, 0xba, 0xb4, 0x4b,
+ 0xe0, 0x95, 0xad, 0xc9, 0xc3, 0xdf, 0x4e, 0x60, 0xf6, 0x9e, 0x25, 0xee,
+ 0x8c, 0x46, 0xfa, 0x3f, 0xef, 0x1e, 0xb1, 0x7e, 0xd7, 0x88, 0x5e, 0x58,
+ 0xbf, 0xf1, 0xad, 0x19, 0x9a, 0xdd, 0x9b, 0x75, 0x49, 0xa8, 0x5f, 0x72,
+ 0x7d, 0xc5, 0x8b, 0xff, 0x34, 0x23, 0x33, 0x5b, 0xb3, 0x6e, 0xa9, 0x15,
+ 0x4b, 0x04, 0xb1, 0x79, 0xfa, 0x82, 0xc5, 0x39, 0xb1, 0xf8, 0x9d, 0x2c,
+ 0x54, 0xa6, 0xe7, 0x85, 0x26, 0x94, 0xf4, 0xa2, 0x72, 0x3f, 0x42, 0x07,
+ 0xb8, 0x82, 0xff, 0xfd, 0x86, 0xf3, 0x78, 0x34, 0xc6, 0xf1, 0xa8, 0xc3,
+ 0x3f, 0x1c, 0xb1, 0x7f, 0xff, 0xff, 0x77, 0xc1, 0x6d, 0xb3, 0x47, 0xc7,
+ 0xe4, 0xc3, 0xfd, 0xff, 0x4f, 0x33, 0x1b, 0xc6, 0xa3, 0x0c, 0xfc, 0x72,
+ 0xc5, 0xfc, 0x03, 0x0c, 0xfc, 0x74, 0x63, 0xa6, 0x2f, 0xd9, 0xa6, 0xa3,
+ 0x13, 0xd5, 0xef, 0x23, 0x84, 0xbf, 0xb3, 0x5b, 0xb3, 0x6e, 0xa9, 0x0a,
+ 0x4b, 0xff, 0x33, 0x1f, 0x34, 0x02, 0x10, 0x16, 0x2f, 0xfb, 0xdc, 0xcd,
+ 0x00, 0x84, 0x05, 0x8b, 0x89, 0x96, 0x2a, 0x4f, 0x40, 0x67, 0x57, 0xf9,
+ 0xfa, 0xf3, 0x31, 0xf8, 0xb1, 0x77, 0x19, 0x62, 0xf7, 0x25, 0x96, 0x2a,
+ 0x07, 0xcf, 0x86, 0x8e, 0x2f, 0x7c, 0x5b, 0x4e, 0x96, 0x2f, 0xe6, 0x07,
+ 0x3d, 0x9b, 0xac, 0x54, 0x9e, 0x91, 0x11, 0xdf, 0xb0, 0x7b, 0x60, 0x4b,
+ 0x17, 0x1e, 0x33, 0xe9, 0xef, 0x94, 0x23, 0xb9, 0x08, 0x8f, 0x3f, 0xf6,
+ 0x20, 0xa8, 0xc5, 0x50, 0x0d, 0x28, 0x6e, 0xfd, 0xad, 0xd9, 0xb7, 0x54,
+ 0x86, 0x85, 0xfc, 0x4e, 0x3d, 0x3e, 0xcb, 0x16, 0x8c, 0xc3, 0xe5, 0x73,
+ 0x7b, 0xff, 0x01, 0xe7, 0xd1, 0x9f, 0xc7, 0xfa, 0xc5, 0xe8, 0xd7, 0x1d,
+ 0x1b, 0xac, 0x5f, 0x77, 0x9d, 0xf7, 0x1a, 0xe3, 0x5a, 0xc5, 0xf3, 0xfd,
+ 0xce, 0xb1, 0x70, 0xbe, 0xb1, 0x7d, 0x1a, 0xfb, 0xee, 0x35, 0xc6, 0xb5,
+ 0x8b, 0xda, 0x98, 0x96, 0x2f, 0xdf, 0x68, 0x9c, 0xeb, 0x14, 0xe7, 0x8e,
+ 0x71, 0xeb, 0xfe, 0xc3, 0xbe, 0xb3, 0x91, 0x4a, 0xc5, 0xef, 0x67, 0xd6,
+ 0x28, 0x67, 0xad, 0xe3, 0x9b, 0xfd, 0xef, 0x3b, 0x76, 0x9f, 0x2c, 0x5f,
+ 0xff, 0xe1, 0x73, 0xf8, 0x30, 0xc3, 0xe3, 0x87, 0xe7, 0xe4, 0x41, 0xac,
+ 0x54, 0xa2, 0x75, 0x8d, 0x6f, 0xff, 0x44, 0xef, 0xf8, 0xb3, 0xd3, 0xe9,
+ 0x1a, 0xc5, 0x9d, 0x62, 0xf3, 0xb0, 0x49, 0x17, 0xfd, 0x3f, 0x9d, 0xb5,
+ 0x38, 0x35, 0x8b, 0xff, 0x4c, 0xf6, 0x92, 0x98, 0xa6, 0x25, 0x8b, 0xf4,
+ 0x5c, 0x6c, 0xf2, 0xc5, 0xfe, 0xd6, 0xa7, 0xae, 0x7c, 0x6b, 0x16, 0xfc,
+ 0x9e, 0xfb, 0x94, 0xdf, 0xff, 0x4f, 0xe6, 0x2e, 0x0b, 0xc2, 0x14, 0x53,
+ 0xd9, 0x62, 0xa5, 0x59, 0x1b, 0xbb, 0xc7, 0xc2, 0xfe, 0x22, 0x1d, 0x25,
+ 0x9c, 0x47, 0xe3, 0xa4, 0x73, 0xe8, 0x4f, 0xf6, 0x26, 0xbf, 0x9f, 0x91,
+ 0x66, 0xa5, 0x62, 0xe1, 0xec, 0xb1, 0x7d, 0xbb, 0x36, 0xea, 0x92, 0x7c,
+ 0xbf, 0xf7, 0xdb, 0xdc, 0x6e, 0x98, 0x80, 0xb1, 0x7f, 0x70, 0x39, 0x0b,
+ 0x52, 0xb1, 0x67, 0xd1, 0xf7, 0x9c, 0xfe, 0xef, 0x4a, 0xc5, 0xfc, 0xfe,
+ 0x16, 0x9b, 0x8b, 0x15, 0xa4, 0xc3, 0x3f, 0x0a, 0x0f, 0x13, 0xf6, 0x17,
+ 0xbe, 0x0b, 0x78, 0xbb, 0xd5, 0x8b, 0xff, 0xc2, 0xe7, 0xda, 0x13, 0xe2,
+ 0x90, 0x71, 0x62, 0xff, 0xb3, 0xb7, 0xde, 0x3b, 0x34, 0x6a, 0xc5, 0xef,
+ 0xbf, 0xb4, 0x88, 0x9e, 0x25, 0x5f, 0xfa, 0x33, 0xf9, 0xf6, 0xec, 0xfc,
+ 0xe9, 0x62, 0xff, 0x7d, 0xf4, 0xfe, 0x68, 0x96, 0x29, 0xcf, 0xe6, 0x24,
+ 0x5b, 0xfc, 0xfe, 0x7f, 0x7c, 0x5e, 0x58, 0xbf, 0xff, 0x0b, 0x6d, 0x49,
+ 0x93, 0xd8, 0x51, 0x36, 0xa7, 0xb2, 0xc5, 0xf0, 0x04, 0x2d, 0x2c, 0x5f,
+ 0x49, 0xf4, 0xcb, 0x17, 0xfa, 0x7d, 0xf6, 0x88, 0xcc, 0x58, 0xbf, 0xb3,
+ 0xcf, 0xe6, 0x89, 0x62, 0xff, 0xe9, 0x9d, 0x4f, 0x1f, 0x5a, 0x7e, 0x2c,
+ 0x54, 0x48, 0xa6, 0xe1, 0xaf, 0x8b, 0xaa, 0x24, 0xf4, 0x34, 0x44, 0x73,
+ 0x40, 0x2e, 0x91, 0x27, 0xa1, 0x91, 0x7f, 0x66, 0x6f, 0xec, 0xdd, 0x62,
+ 0xed, 0x7d, 0x62, 0xff, 0x9a, 0x0e, 0x3f, 0xcc, 0x38, 0xb1, 0x7e, 0x17,
+ 0xbd, 0x3d, 0x96, 0x2f, 0xfe, 0x98, 0xa2, 0x70, 0x4c, 0x51, 0x60, 0x16,
+ 0x2d, 0x3a, 0x3f, 0x32, 0x2b, 0xbe, 0xec, 0xfc, 0xe9, 0x62, 0xdf, 0x73,
+ 0xcc, 0x62, 0x6b, 0xbe, 0x25, 0x8a, 0xc3, 0x7c, 0x22, 0x6b, 0x77, 0x2c,
+ 0x5f, 0xb3, 0xee, 0x5e, 0x58, 0xb9, 0xa2, 0x58, 0xb9, 0xbc, 0xb1, 0x7f,
+ 0xe2, 0x17, 0xdf, 0x59, 0xc8, 0xa5, 0x62, 0xa2, 0x3d, 0x63, 0x8b, 0xdf,
+ 0xdc, 0x26, 0xdb, 0x69, 0x58, 0xbf, 0xff, 0xff, 0x4f, 0x9c, 0x9b, 0x9c,
+ 0xcf, 0x7d, 0x8f, 0xfc, 0x29, 0x9e, 0x30, 0xbb, 0x2c, 0x5f, 0x34, 0x4f,
+ 0xf5, 0x8b, 0xff, 0xda, 0xc7, 0x8b, 0x82, 0x9e, 0x8a, 0x7c, 0xb1, 0x7e,
+ 0xec, 0x28, 0xf9, 0x02, 0xc5, 0x4a, 0xa1, 0x98, 0x0a, 0xf4, 0x4e, 0xed,
+ 0xd1, 0xe4, 0x7a, 0x2f, 0x3c, 0x20, 0x7c, 0x46, 0x24, 0xbb, 0xde, 0x16,
+ 0x96, 0x2f, 0xe1, 0x16, 0x00, 0x5c, 0x58, 0xae, 0x8f, 0x33, 0x83, 0xd7,
+ 0xfe, 0xf6, 0x85, 0x17, 0x37, 0x68, 0xb8, 0xb1, 0x58, 0x7c, 0xe2, 0x23,
+ 0xb8, 0x01, 0xac, 0x5f, 0xf4, 0x53, 0x00, 0xc0, 0x01, 0x41, 0x62, 0xfe,
+ 0x29, 0xf1, 0x4f, 0x96, 0x2a, 0x08, 0x82, 0xc1, 0x96, 0x3d, 0xbd, 0x13,
+ 0xf1, 0x62, 0xf9, 0xe7, 0x58, 0xb1, 0x7e, 0x9f, 0x75, 0x9e, 0x93, 0x7f,
+ 0xf1, 0xeb, 0xff, 0x44, 0x22, 0xdb, 0x9b, 0xb4, 0x5c, 0x58, 0xa9, 0x44,
+ 0x0e, 0x1e, 0xdc, 0xdc, 0x58, 0xbf, 0x0a, 0x28, 0x98, 0xd5, 0x8b, 0xfe,
+ 0xf4, 0xf4, 0xd1, 0x6a, 0x7b, 0x2c, 0x54, 0x7a, 0x20, 0x38, 0x2f, 0xe2,
+ 0xca, 0x58, 0xbf, 0xb4, 0x28, 0x16, 0x74, 0xb1, 0x7b, 0xef, 0xa5, 0x8a,
+ 0x8d, 0x8f, 0x63, 0x03, 0x04, 0x5f, 0x6c, 0x58, 0xb4, 0x64, 0x6e, 0xd8,
+ 0xfd, 0xf7, 0x85, 0x9d, 0xe9, 0xe4, 0x68, 0x45, 0x1a, 0xc6, 0x26, 0x5d,
+ 0x3e, 0xd0, 0x9a, 0x19, 0x76, 0x46, 0x4a, 0x6a, 0x2e, 0xf0, 0xb5, 0x79,
+ 0x4f, 0xb1, 0x2e, 0xe8, 0xbc, 0xe3, 0x1f, 0x8c, 0xd9, 0xa5, 0x1c, 0x94,
+ 0x67, 0x5c, 0x85, 0x1f, 0xa1, 0xdc, 0x28, 0x50, 0xc7, 0x42, 0x2f, 0xb8,
+ 0xce, 0xff, 0xf4, 0x61, 0xda, 0x11, 0x99, 0xad, 0xd9, 0xb7, 0x54, 0x8d,
+ 0x45, 0xff, 0xd0, 0x29, 0x8c, 0x98, 0xb0, 0x85, 0x8b, 0x17, 0xed, 0x6e,
+ 0xcd, 0xba, 0xa4, 0xbb, 0x2e, 0xc2, 0x58, 0xac, 0x3c, 0xd7, 0x37, 0xba,
+ 0x3f, 0xcb, 0x17, 0xff, 0xb3, 0xb9, 0xfc, 0xf0, 0x30, 0xa7, 0xdc, 0x58,
+ 0xbf, 0xfa, 0x4e, 0x1f, 0x9c, 0x85, 0x0c, 0xe2, 0xc5, 0xe2, 0x21, 0xac,
+ 0x5e, 0x3c, 0xfd, 0x62, 0x96, 0x2e, 0x0a, 0x32, 0x08, 0xf2, 0xf8, 0xd8,
+ 0x13, 0x49, 0x14, 0x43, 0x81, 0x0e, 0xdf, 0xf4, 0x66, 0x7d, 0xf5, 0xe1,
+ 0x32, 0xc5, 0x46, 0x27, 0x6a, 0xf1, 0x89, 0x71, 0x9e, 0xee, 0xbb, 0x96,
+ 0x2e, 0x03, 0xac, 0x58, 0x6b, 0x17, 0x49, 0xd6, 0x2b, 0xe6, 0xa7, 0x82,
+ 0x56, 0x8e, 0x58, 0xb1, 0x2c, 0x56, 0xc6, 0x98, 0xe2, 0xb7, 0x6d, 0x2b,
+ 0x17, 0xdb, 0xb3, 0x6e, 0xa9, 0x2f, 0x8b, 0xc1, 0x04, 0x12, 0x45, 0x89,
+ 0x22, 0x30, 0xd0, 0xdf, 0x98, 0x5d, 0xff, 0xc4, 0xb1, 0x5a, 0x45, 0x21,
+ 0xd4, 0xbc, 0x49, 0x7f, 0xbf, 0x86, 0xb4, 0xf5, 0xdc, 0xb1, 0x7a, 0x13,
+ 0xd2, 0xc5, 0xf7, 0x40, 0x92, 0x58, 0xbb, 0xee, 0xb1, 0x6c, 0x93, 0x75,
+ 0xe2, 0x3b, 0x81, 0xf5, 0x8b, 0x85, 0xc5, 0x8b, 0xb3, 0xeb, 0x14, 0x33,
+ 0x5f, 0x10, 0xc5, 0xcd, 0xd9, 0x62, 0xfa, 0x02, 0x2d, 0x96, 0x2f, 0xe6,
+ 0xf7, 0x27, 0x36, 0x58, 0xa8, 0x8f, 0x48, 0x22, 0x4b, 0xdc, 0x90, 0x2c,
+ 0x57, 0xcf, 0x07, 0xc4, 0x96, 0x95, 0x8b, 0xe2, 0x6e, 0xb8, 0xb1, 0x58,
+ 0x7a, 0xdc, 0x22, 0xf0, 0x8d, 0xe0, 0xb3, 0x4b, 0x16, 0xf2, 0xc5, 0xec,
+ 0x9e, 0x96, 0x2f, 0xf9, 0xf5, 0x9b, 0x3c, 0x30, 0x6b, 0x17, 0xfb, 0x40,
+ 0xf7, 0x18, 0x18, 0xb1, 0x4e, 0x8b, 0xad, 0x0f, 0x7c, 0x49, 0x87, 0x44,
+ 0x73, 0x7b, 0xe4, 0x05, 0x8b, 0xee, 0xef, 0x88, 0x35, 0x8b, 0xd1, 0x64,
+ 0x4b, 0x16, 0x75, 0x8a, 0xe8, 0xf6, 0x22, 0x28, 0x38, 0xfd, 0xb4, 0xb1,
+ 0x4b, 0x14, 0xe5, 0xf6, 0x84, 0xa9, 0x62, 0xce, 0xb1, 0x6d, 0x8d, 0x2f,
+ 0x7e, 0x19, 0x6e, 0xcb, 0x15, 0xf3, 0xf8, 0x63, 0xc1, 0x14, 0x5f, 0x61,
+ 0x4c, 0x16, 0x2d, 0x19, 0xde, 0x2f, 0x46, 0x77, 0xc1, 0xc9, 0x40, 0xd9,
+ 0x1e, 0x04, 0x59, 0x0b, 0xcd, 0xcc, 0x22, 0x38, 0xd2, 0xc1, 0xc9, 0x59,
+ 0x1c, 0x04, 0x45, 0x18, 0x17, 0x21, 0xd1, 0xe4, 0x81, 0x3a, 0xc7, 0x43,
+ 0x1c, 0x32, 0xeb, 0xff, 0xd1, 0x87, 0x68, 0x46, 0x66, 0xb7, 0x66, 0xdd,
+ 0x52, 0x3d, 0x96, 0xef, 0xd6, 0x2f, 0xf8, 0x6d, 0xbc, 0xee, 0x22, 0x1a,
+ 0xc5, 0xff, 0xf3, 0xc3, 0x91, 0xff, 0x16, 0xf9, 0xb1, 0x83, 0xd2, 0xc5,
+ 0xff, 0xfd, 0x9e, 0x21, 0x6e, 0xd1, 0xf3, 0xd9, 0xb4, 0x37, 0xd2, 0xc5,
+ 0xff, 0x0d, 0xa3, 0xe7, 0x43, 0x68, 0xf5, 0x8b, 0xe9, 0xee, 0x6e, 0x96,
+ 0x2f, 0x39, 0x01, 0x62, 0xb6, 0x4d, 0xd2, 0x07, 0x71, 0x2c, 0x69, 0x83,
+ 0xe7, 0xfd, 0x89, 0xaf, 0xfe, 0x16, 0xa2, 0xd3, 0xec, 0xc7, 0x7e, 0x2c,
+ 0x5f, 0x9c, 0x73, 0xae, 0x2c, 0x5f, 0xfd, 0x9f, 0xcf, 0x75, 0xbb, 0xeb,
+ 0xf8, 0xb1, 0x7e, 0xd6, 0xec, 0xdb, 0xaa, 0x4e, 0x12, 0xf8, 0xe2, 0xf7,
+ 0x16, 0x2f, 0x68, 0x43, 0x58, 0xbf, 0x9e, 0x02, 0x04, 0xc4, 0xb1, 0x58,
+ 0x79, 0xbf, 0x1e, 0xbf, 0xf3, 0xf6, 0x68, 0xb8, 0xfa, 0x93, 0xac, 0x5f,
+ 0xd2, 0xfa, 0xd3, 0x84, 0xb1, 0x7f, 0xec, 0x70, 0x48, 0x18, 0x85, 0x8b,
+ 0x17, 0xbf, 0x91, 0x2c, 0x5b, 0xeb, 0x14, 0x33, 0x60, 0xc3, 0xd6, 0x8c,
+ 0xef, 0x57, 0x18, 0x26, 0x38, 0xbd, 0x97, 0x20, 0x8e, 0x32, 0x8c, 0x46,
+ 0x34, 0xdd, 0xdc, 0x62, 0x21, 0x3a, 0x09, 0x17, 0x09, 0xb2, 0xff, 0xe8,
+ 0xc6, 0x84, 0x66, 0x6b, 0x76, 0x6d, 0xd5, 0x22, 0x79, 0x7f, 0xe7, 0x8a,
+ 0x32, 0x45, 0x3e, 0x90, 0x2c, 0x5f, 0x7e, 0x48, 0xd5, 0x8b, 0xf6, 0xa2,
+ 0xcc, 0x09, 0x62, 0xe3, 0x63, 0x22, 0x3c, 0xd0, 0xc8, 0xea, 0x5d, 0x43,
+ 0xa6, 0xd2, 0xac, 0xa1, 0x09, 0x3c, 0x29, 0x36, 0xb2, 0x3c, 0xde, 0x3a,
+ 0x6e, 0x97, 0xe2, 0x94, 0x91, 0xa9, 0xec, 0x5f, 0xc6, 0x45, 0xc9, 0xcb,
+ 0xfe, 0xd0, 0xbb, 0x09, 0x64, 0x38, 0x47, 0xdf, 0xe8, 0xcc, 0xd6, 0xec,
+ 0xdb, 0xaa, 0x42, 0xa2, 0xfd, 0xad, 0xd9, 0xb7, 0x54, 0x93, 0x25, 0xfc,
+ 0xff, 0xc6, 0xe8, 0x0b, 0x16, 0x8c, 0xc3, 0xe5, 0x8e, 0x37, 0xbf, 0xfd,
+ 0x18, 0x76, 0x84, 0x66, 0x6b, 0x76, 0x6d, 0xd5, 0x23, 0x39, 0x7f, 0xfa,
+ 0x30, 0xed, 0x08, 0xcc, 0xd6, 0xec, 0xdb, 0xaa, 0x48, 0xd2, 0xb6, 0x4e,
0x54, 0x70, 0xaa, 0x34, 0xb7, 0xcb, 0xf7, 0xfe, 0x68, 0x46, 0x66, 0xb7,
- 0x66, 0xdd, 0x51, 0x1d, 0x17, 0x03, 0xa2, 0xc5, 0xfc, 0x59, 0xee, 0x49,
+ 0x66, 0xdd, 0x52, 0x1d, 0x17, 0x03, 0xb2, 0xc5, 0xfc, 0x59, 0xee, 0x49,
0xd6, 0x2f, 0x6b, 0x36, 0x58, 0xbd, 0x3e, 0xe2, 0xc5, 0xed, 0x6d, 0x19,
- 0xf4, 0x41, 0x70, 0x6b, 0xc5, 0xa6, 0x0f, 0x5f, 0xfe, 0x21, 0x78, 0x46,
- 0xfb, 0xbd, 0xdf, 0x5c, 0x58, 0xbf, 0xfc, 0x26, 0x78, 0x38, 0x38, 0x2e,
+ 0xf4, 0x41, 0x70, 0x6b, 0xc5, 0xa1, 0x8f, 0x5f, 0xfe, 0x21, 0x78, 0x46,
+ 0xfb, 0xad, 0xdf, 0x5c, 0x58, 0xbf, 0xfc, 0x26, 0x78, 0x38, 0x38, 0x2e,
0x7c, 0x4b, 0x17, 0xd9, 0xa2, 0x95, 0x8b, 0xda, 0x84, 0x66, 0x22, 0xef,
0x89, 0xfe, 0x4b, 0xa8, 0xc5, 0x44, 0xb3, 0x0d, 0x27, 0x8c, 0x3e, 0xe1,
- 0x7d, 0x62, 0xfd, 0x1b, 0x05, 0x75, 0xce, 0x2c, 0x5e, 0xdc, 0x5b, 0xac,
- 0x5c, 0x22, 0x58, 0xbf, 0xec, 0x3f, 0x1e, 0x3b, 0x35, 0x2b, 0x15, 0xb9,
- 0xf9, 0x47, 0x90, 0x04, 0x17, 0xbf, 0x78, 0xff, 0x71, 0xac, 0x5f, 0x70,
- 0x47, 0x75, 0x8b, 0xd2, 0x71, 0xac, 0x5c, 0x1f, 0xd6, 0x29, 0xcf, 0x64,
- 0x88, 0xc3, 0x1d, 0xbf, 0x61, 0x0f, 0x36, 0x58, 0xbf, 0xe7, 0xd7, 0x0b,
- 0x07, 0xf9, 0x58, 0xbd, 0x9d, 0x8d, 0x62, 0xed, 0x62, 0xc5, 0xf4, 0xce,
- 0xf8, 0x33, 0x6b, 0xa1, 0xea, 0x74, 0x66, 0x7c, 0xa0, 0x9b, 0x6f, 0xd9,
- 0xad, 0xc4, 0x6a, 0xc5, 0xff, 0x6f, 0x27, 0xc7, 0x3c, 0xc7, 0xac, 0x5f,
- 0x3e, 0x99, 0xd6, 0x2f, 0xfc, 0x58, 0x6b, 0x45, 0xcf, 0xc8, 0xd6, 0x2f,
- 0x44, 0xde, 0x58, 0xbe, 0xdd, 0x9b, 0x75, 0x45, 0x34, 0x5e, 0x0d, 0xbe,
- 0xb1, 0x7f, 0x4e, 0xf9, 0xbf, 0xc4, 0xb1, 0x6c, 0xec, 0xf3, 0x8e, 0x3d,
- 0x7f, 0xec, 0x21, 0xcf, 0x50, 0xb3, 0xa0, 0x1d, 0x62, 0xe9, 0x25, 0x8a,
- 0xe1, 0xee, 0xf4, 0x47, 0xbf, 0x3f, 0x3d, 0x9f, 0x58, 0xbf, 0xcf, 0xac,
- 0x8a, 0x44, 0x17, 0x58, 0xa1, 0xaa, 0x6e, 0xc2, 0xb3, 0x4f, 0x1c, 0x86,
- 0x24, 0x0d, 0x0f, 0x13, 0xff, 0x21, 0x0b, 0xe2, 0x4e, 0x85, 0x17, 0xda,
- 0x61, 0xba, 0xc5, 0xff, 0xed, 0xdb, 0x5c, 0xfb, 0x3f, 0x39, 0x9c, 0x58,
- 0xbf, 0xff, 0xec, 0x2f, 0x71, 0xf7, 0xc2, 0xe6, 0xff, 0x7f, 0xee, 0x66,
- 0xcb, 0x17, 0xfd, 0xc6, 0xef, 0x22, 0x9f, 0xf1, 0x62, 0xcf, 0xf4, 0x78,
- 0x92, 0x5f, 0x9a, 0xef, 0xf6, 0xb6, 0xe6, 0xb5, 0x21, 0xac, 0x5f, 0xd9,
- 0xb6, 0x6f, 0x83, 0x58, 0xbf, 0xfb, 0xae, 0xff, 0x7f, 0xee, 0xdc, 0xfc,
- 0xac, 0x57, 0xd1, 0xc6, 0xc6, 0x84, 0x6f, 0xc2, 0xfb, 0xff, 0x7d, 0xcb,
- 0x6e, 0x0a, 0x75, 0x12, 0xc5, 0xff, 0xfb, 0x36, 0x9e, 0x3e, 0xb3, 0xae,
- 0x39, 0x49, 0xd6, 0x2a, 0x08, 0x96, 0xf2, 0x0d, 0xe8, 0x1e, 0x0b, 0x17,
- 0xec, 0xdf, 0xd9, 0xba, 0xc5, 0x84, 0xb1, 0x58, 0x6f, 0x22, 0x2a, 0xbe,
- 0xf7, 0x18, 0x0b, 0x17, 0xe0, 0x9f, 0xc2, 0x35, 0x62, 0xe6, 0xed, 0x62,
- 0xff, 0x4f, 0xb9, 0xa7, 0x3e, 0x2c, 0x5e, 0x07, 0x9d, 0x62, 0xff, 0x73,
- 0x77, 0xd6, 0x9f, 0x65, 0x8a, 0x94, 0x76, 0x61, 0x1e, 0xe5, 0x7d, 0x8c,
- 0x31, 0x9f, 0x07, 0x6f, 0xff, 0xed, 0x85, 0xa8, 0xb9, 0xb4, 0xc5, 0xcf,
- 0xe0, 0xdf, 0xa2, 0xc5, 0xff, 0xfe, 0xfb, 0x1a, 0x59, 0x0f, 0xcc, 0x33,
- 0xe5, 0x8d, 0xb2, 0xc5, 0xf1, 0xb2, 0x5b, 0xac, 0x5f, 0xf6, 0x69, 0xa5,
- 0xca, 0x4e, 0xb1, 0x7f, 0xff, 0xfd, 0x3d, 0xef, 0xfc, 0xeb, 0xfc, 0xdf,
- 0xef, 0xfc, 0x26, 0x37, 0x3a, 0x4f, 0x6b, 0x17, 0xed, 0xba, 0xfc, 0x1d,
- 0x16, 0x2b, 0x64, 0xf4, 0x06, 0xc6, 0x6b, 0x07, 0x09, 0x3a, 0x1b, 0x19,
- 0x08, 0x4b, 0xfe, 0xe9, 0xbf, 0xdc, 0x1f, 0x73, 0xac, 0x5f, 0xdd, 0x64,
- 0x8d, 0xfb, 0xac, 0x5f, 0x61, 0x48, 0x6b, 0x17, 0xcf, 0xb6, 0x0d, 0x62,
- 0xa0, 0x7e, 0xb1, 0x18, 0x78, 0x8a, 0xb1, 0x34, 0x47, 0x62, 0x68, 0x59,
- 0x5d, 0xa1, 0x2c, 0x5f, 0x67, 0xcc, 0xd2, 0xc5, 0x1c, 0xde, 0x10, 0xc5,
- 0xdb, 0x47, 0xac, 0x5c, 0x78, 0xe5, 0x8b, 0xf9, 0x8b, 0x7e, 0xbb, 0x71,
- 0x62, 0x8d, 0x3e, 0x90, 0x0e, 0x08, 0x6e, 0xff, 0x6f, 0xb8, 0xb4, 0x0f,
- 0x89, 0x62, 0xfe, 0x92, 0xf4, 0x76, 0x79, 0x62, 0xff, 0x98, 0x1b, 0xbe,
- 0xb4, 0xfb, 0x2c, 0x5f, 0xe6, 0x03, 0x7b, 0xd9, 0xf5, 0x8a, 0x82, 0x27,
- 0xa2, 0x30, 0x0c, 0xee, 0xfb, 0xef, 0x9a, 0x58, 0xbb, 0xe2, 0x58, 0xb4,
- 0x16, 0x2f, 0xf6, 0xd9, 0xbf, 0x89, 0xa2, 0x58, 0xa8, 0xd1, 0x38, 0xac,
- 0x86, 0xb3, 0x99, 0x00, 0x8b, 0xa0, 0xc1, 0x82, 0x57, 0xbe, 0x18, 0x16,
- 0x2d, 0xe5, 0x8a, 0x73, 0x63, 0xf1, 0xfb, 0x87, 0x2b, 0x17, 0xff, 0xef,
- 0x70, 0xce, 0x6a, 0x47, 0x9f, 0xdf, 0x0b, 0x65, 0x8a, 0x93, 0xf0, 0xc1,
- 0x7b, 0xfa, 0x5c, 0x0d, 0xe1, 0x2c, 0x5f, 0xfb, 0x01, 0x99, 0x14, 0x45,
- 0x23, 0x58, 0xbf, 0xf6, 0x80, 0x32, 0x98, 0x7f, 0x80, 0x58, 0xac, 0x4d,
- 0x70, 0xf0, 0x90, 0xf9, 0x01, 0x16, 0x88, 0xfe, 0xf7, 0xa6, 0x0b, 0x17,
- 0xfc, 0x2f, 0x7f, 0x22, 0x84, 0xf6, 0xb1, 0x7f, 0xf8, 0x9b, 0xd9, 0xee,
- 0x67, 0xf2, 0x3f, 0xcb, 0x15, 0xf4, 0x52, 0x90, 0xef, 0x43, 0xcb, 0xff,
- 0x3e, 0xb4, 0xfb, 0x71, 0xc1, 0xc5, 0x8b, 0x44, 0xb1, 0x73, 0x7d, 0x62,
- 0xfd, 0x9f, 0x62, 0x1a, 0xc5, 0x6c, 0x7a, 0x30, 0x13, 0x00, 0xbd, 0xff,
- 0xfd, 0x91, 0xec, 0x40, 0xe6, 0xff, 0x7f, 0xe4, 0x97, 0x96, 0x2e, 0x93,
- 0x56, 0x2f, 0x74, 0x7d, 0x2c, 0x58, 0x96, 0x2b, 0x0d, 0x83, 0x0f, 0xdf,
- 0x0b, 0x8e, 0x75, 0x8b, 0xd1, 0xaa, 0x35, 0x46, 0xa5, 0x8a, 0x01, 0xe9,
- 0xf0, 0x8e, 0xcd, 0x12, 0x25, 0x00, 0xe5, 0x7f, 0x3c, 0x9f, 0x6c, 0x0d,
- 0x62, 0xff, 0xfb, 0x3d, 0xfc, 0x86, 0x98, 0xbd, 0xf6, 0x82, 0xc5, 0xd2,
- 0x05, 0x8b, 0xfc, 0xdd, 0xce, 0xef, 0xbc, 0x66, 0x91, 0x2a, 0x45, 0xe6,
- 0x27, 0xd6, 0x2b, 0x46, 0xdc, 0xc5, 0xe1, 0x23, 0x11, 0x87, 0xd7, 0x4a,
- 0x1b, 0x9c, 0x85, 0xf5, 0xe6, 0x8b, 0x8b, 0x17, 0xe2, 0xe7, 0xf2, 0x3d,
- 0x62, 0xda, 0x58, 0xac, 0x37, 0xa6, 0x15, 0xdf, 0x81, 0xf9, 0x87, 0x16,
- 0x2f, 0xf0, 0xe4, 0x64, 0x26, 0x31, 0x62, 0xf1, 0x08, 0xd5, 0x8b, 0xc1,
- 0xb6, 0xcb, 0x17, 0xfd, 0x20, 0x6f, 0x00, 0xc2, 0x82, 0xc5, 0x7c, 0xf6,
- 0x48, 0x7e, 0xa5, 0x1e, 0xa3, 0x29, 0x23, 0x4f, 0x3b, 0xda, 0x32, 0x34,
- 0x6e, 0x14, 0xc2, 0xd4, 0x62, 0x61, 0x4b, 0xb1, 0xac, 0x21, 0x04, 0x38,
- 0x7d, 0x64, 0xa9, 0xc3, 0x61, 0x27, 0xbc, 0x7e, 0xdd, 0xc3, 0x45, 0xc8,
- 0xe2, 0x5a, 0xd4, 0x61, 0xbf, 0x96, 0xd4, 0xcd, 0xe0, 0x84, 0x49, 0x47,
- 0x75, 0xc8, 0xfc, 0x3d, 0x38, 0x72, 0x27, 0x48, 0xe5, 0xb3, 0x23, 0x16,
- 0xbb, 0x68, 0xe5, 0x8b, 0xff, 0xec, 0xf3, 0xfc, 0x5f, 0x67, 0xef, 0x92,
- 0x6a, 0xc5, 0xf3, 0x90, 0x1d, 0x62, 0xfb, 0x76, 0x6d, 0xd5, 0x15, 0x51,
- 0x50, 0x3d, 0x2d, 0x10, 0xdf, 0xf9, 0xa1, 0x19, 0x9a, 0xdd, 0x9b, 0x75,
- 0x44, 0xda, 0x5f, 0xf9, 0x9f, 0xd0, 0x9d, 0x69, 0xa0, 0xb1, 0x68, 0xcd,
- 0x93, 0x6f, 0x18, 0xe6, 0x42, 0x8c, 0xe4, 0x5f, 0x50, 0xbf, 0xd1, 0x99,
- 0xad, 0xd9, 0xb7, 0x54, 0x57, 0xe5, 0xfb, 0x5b, 0xb3, 0x6e, 0xa8, 0xb1,
- 0x8b, 0x82, 0x41, 0x62, 0xd1, 0x98, 0x7a, 0x31, 0x1b, 0xdf, 0xfe, 0xfc,
- 0xed, 0x90, 0xfc, 0xbe, 0xb0, 0x96, 0x2f, 0xcf, 0x90, 0x98, 0x2c, 0x5d,
- 0xb4, 0x64, 0x47, 0xe1, 0xc4, 0x9b, 0xc2, 0x2f, 0x2c, 0x5f, 0x8c, 0xd1,
- 0x93, 0x12, 0xc5, 0xf6, 0xff, 0x93, 0x56, 0x2f, 0x4f, 0xb8, 0xb1, 0x7e,
- 0xf1, 0x4e, 0x76, 0xb1, 0x58, 0x8b, 0x3f, 0x8e, 0xf0, 0xb3, 0xc4, 0xa6,
- 0x0e, 0xdf, 0xe8, 0x61, 0x03, 0x30, 0x6b, 0x17, 0xfd, 0xb4, 0xf1, 0x81,
- 0xc7, 0x1a, 0xc5, 0xf9, 0xf4, 0x64, 0x5c, 0x58, 0xb7, 0x96, 0x2f, 0x85,
- 0x0c, 0xe2, 0xc3, 0x16, 0x57, 0xf8, 0x59, 0xad, 0xfe, 0xfc, 0x58, 0xa8,
- 0x26, 0x1f, 0xa3, 0x2f, 0x9d, 0x11, 0xef, 0x0c, 0x6f, 0xfc, 0x68, 0xbd,
- 0xcf, 0x77, 0xbb, 0x92, 0xc5, 0xfc, 0xef, 0x21, 0xcc, 0x4b, 0x17, 0xf4,
- 0x87, 0x1c, 0x67, 0xd9, 0x62, 0xc1, 0x75, 0x8a, 0xd1, 0xe4, 0x88, 0xce,
- 0xfc, 0x38, 0xd2, 0x34, 0x23, 0x56, 0x2f, 0xbd, 0xc6, 0xed, 0x62, 0xa3,
- 0x73, 0xd8, 0x93, 0x4b, 0xfe, 0x21, 0x6d, 0x14, 0x27, 0x5b, 0x2c, 0x5d,
- 0xaf, 0x2c, 0x5e, 0x67, 0x12, 0xc5, 0xf3, 0x43, 0x06, 0xb1, 0x7f, 0x7b,
- 0x34, 0x3c, 0x25, 0x8b, 0x60, 0xcf, 0x3f, 0xc4, 0x57, 0x43, 0x16, 0x2f,
- 0xe6, 0x6f, 0x7b, 0x3e, 0xb1, 0x7f, 0xfb, 0x0e, 0x4c, 0x69, 0x60, 0x3a,
- 0x87, 0x1b, 0x2c, 0x51, 0xa8, 0x96, 0xd0, 0xb9, 0x16, 0xdf, 0xfc, 0x4d,
- 0xdf, 0x0e, 0xde, 0xe0, 0xa0, 0xb1, 0x7f, 0x83, 0x90, 0xd8, 0xbb, 0xf2,
- 0xc5, 0xfb, 0x5e, 0xfe, 0x6c, 0xb1, 0x6f, 0x2c, 0x54, 0x9f, 0x96, 0x1b,
- 0x7c, 0xaa, 0xfe, 0xf3, 0x9f, 0xb8, 0x71, 0x62, 0xd1, 0x98, 0xb8, 0xcc,
- 0x6a, 0x53, 0xa1, 0xe9, 0xdc, 0xef, 0x5f, 0x26, 0x63, 0xd0, 0x0c, 0x13,
- 0x5f, 0x21, 0x7b, 0xe3, 0x03, 0x21, 0x70, 0x10, 0xb6, 0xff, 0xd1, 0x9e,
- 0x7e, 0xbe, 0xfb, 0xc8, 0x16, 0x2a, 0x31, 0x7b, 0x2f, 0x53, 0xb7, 0xe0,
- 0x86, 0x45, 0x4a, 0xff, 0xa3, 0xcf, 0xd8, 0xdf, 0xb5, 0xbb, 0x36, 0xea,
- 0x8b, 0x54, 0xbf, 0x6b, 0x76, 0x6d, 0xd5, 0x14, 0x11, 0x76, 0xdf, 0x58,
- 0xbf, 0xe2, 0x9f, 0x72, 0x28, 0x3c, 0x4b, 0x17, 0x9a, 0x11, 0x98, 0x88,
- 0xb0, 0x1b, 0xf8, 0x66, 0xfd, 0x21, 0xc7, 0x66, 0x96, 0x2d, 0x19, 0x89,
- 0x98, 0x9e, 0x18, 0x46, 0x21, 0xdf, 0x7b, 0x4d, 0xf5, 0x8b, 0xfb, 0xef,
- 0xb6, 0xc2, 0xe2, 0xc5, 0xf4, 0x33, 0xdb, 0xac, 0x5f, 0x64, 0x4e, 0x75,
- 0x8b, 0xff, 0x08, 0xbd, 0xfc, 0x08, 0xe0, 0xc5, 0x8b, 0xfd, 0xbb, 0xf3,
- 0x07, 0xb7, 0x6b, 0x17, 0xda, 0x9f, 0x71, 0x62, 0xf1, 0x66, 0xcb, 0x17,
- 0xf7, 0xf2, 0x0e, 0x0c, 0x58, 0xb6, 0x0c, 0xfb, 0x77, 0x23, 0xf0, 0xed,
- 0xfd, 0x27, 0x6e, 0xfd, 0x05, 0x8b, 0xfd, 0x9f, 0xe6, 0x89, 0xf7, 0x58,
- 0xac, 0x54, 0x2f, 0xb9, 0x1f, 0x66, 0x31, 0x12, 0x1c, 0x8f, 0xe8, 0x05,
- 0x0a, 0x4e, 0x1a, 0xf8, 0xbe, 0xf4, 0x53, 0xb2, 0xc5, 0xff, 0xb3, 0xaf,
- 0xa1, 0x9f, 0xfb, 0x41, 0x62, 0xed, 0x79, 0x62, 0xfe, 0xc8, 0xb8, 0xfd,
- 0x86, 0xb1, 0x7f, 0x9e, 0x3a, 0x7d, 0xf6, 0x89, 0x62, 0xf6, 0x7e, 0x32,
- 0x51, 0xc0, 0x31, 0xf6, 0x41, 0x21, 0x8e, 0x18, 0xdc, 0xc1, 0xc6, 0x27,
- 0x83, 0xe8, 0xd9, 0xaf, 0xe0, 0xb5, 0x0a, 0x7a, 0x3b, 0x3e, 0xb1, 0x7f,
- 0x10, 0x26, 0x3d, 0x8e, 0xb1, 0x7f, 0x8d, 0x86, 0x3f, 0xda, 0x25, 0x8a,
- 0x93, 0xe5, 0x73, 0x0b, 0xf7, 0xf3, 0x79, 0x3a, 0xc5, 0xe9, 0x28, 0x96,
- 0x2f, 0xff, 0x45, 0x3d, 0x1b, 0x5c, 0xe3, 0xeb, 0x0d, 0x58, 0xbc, 0xd9,
- 0xa5, 0x8b, 0xfc, 0xf1, 0x4f, 0x46, 0xd7, 0x16, 0x2d, 0xc5, 0x8a, 0x93,
- 0xc8, 0x23, 0x6b, 0xff, 0xa4, 0x02, 0xf7, 0x0a, 0x42, 0x4e, 0xcb, 0x17,
- 0x6a, 0x56, 0x2a, 0x09, 0xcb, 0x0c, 0x83, 0x72, 0x97, 0x1d, 0xd2, 0x77,
- 0xd9, 0x3a, 0x10, 0x04, 0x47, 0xbd, 0xf6, 0xe2, 0xc5, 0xcf, 0xc5, 0x8b,
- 0xf3, 0x90, 0xa7, 0x4b, 0x14, 0xe7, 0xb7, 0xe1, 0xd1, 0x0b, 0xde, 0x66,
- 0xdd, 0x51, 0x71, 0x17, 0xfc, 0xfd, 0x3f, 0xbb, 0xf3, 0x06, 0xb1, 0x5b,
- 0x9f, 0x36, 0x8a, 0xaf, 0xf9, 0x8f, 0xc7, 0xce, 0x8d, 0xa5, 0x8b, 0xf8,
- 0x4d, 0xd8, 0xf3, 0x4b, 0x15, 0xa4, 0x46, 0x11, 0x1f, 0x0e, 0xaf, 0xff,
- 0xf7, 0xdc, 0x65, 0x2d, 0xb0, 0x6d, 0xfe, 0x75, 0xe4, 0xf1, 0x62, 0xff,
- 0xfd, 0x03, 0x3f, 0x06, 0xf3, 0x00, 0x44, 0xdd, 0x06, 0xb1, 0x71, 0x91,
- 0x2c, 0x5f, 0xf7, 0x31, 0xc0, 0x67, 0x9b, 0xeb, 0x17, 0xf7, 0x7b, 0xbf,
- 0x3e, 0xeb, 0x15, 0xb2, 0x21, 0x3e, 0x35, 0xe3, 0xab, 0xff, 0xe8, 0x4f,
- 0x81, 0xd7, 0x3f, 0xac, 0x00, 0xa2, 0x58, 0xb1, 0xab, 0x17, 0x44, 0xeb,
- 0x15, 0x86, 0xad, 0x84, 0xef, 0xf7, 0x4c, 0xf7, 0x3a, 0x4f, 0xd6, 0x2a,
- 0x07, 0xaf, 0xf1, 0xfb, 0xfd, 0xf9, 0x07, 0x30, 0x80, 0xb1, 0x58, 0x99,
- 0x5b, 0xc3, 0x59, 0x88, 0xaf, 0xf1, 0x7a, 0x18, 0x4e, 0x35, 0x8b, 0xfe,
- 0x26, 0x07, 0x3f, 0x25, 0xe5, 0x8a, 0xc3, 0xea, 0xf1, 0x95, 0xfb, 0x0e,
- 0xe1, 0x06, 0xb1, 0x74, 0x9d, 0x62, 0xa4, 0xf8, 0xa3, 0xc8, 0x74, 0x55,
- 0x7f, 0x08, 0x98, 0xd8, 0x01, 0x62, 0xdd, 0xac, 0x5e, 0x8e, 0xcf, 0xac,
- 0x5b, 0x7c, 0x36, 0x7e, 0x13, 0xbc, 0x11, 0xf6, 0x58, 0xac, 0x3c, 0x76,
- 0x27, 0xbf, 0x7c, 0x46, 0xe1, 0x2c, 0x5f, 0x9b, 0x5e, 0x29, 0x58, 0xbb,
- 0xce, 0xb1, 0x71, 0x9b, 0x2c, 0x54, 0x0d, 0x89, 0x0b, 0xdf, 0x87, 0x91,
- 0xf3, 0xf5, 0x8b, 0xc1, 0x1f, 0x75, 0x8a, 0x1a, 0x3b, 0x37, 0x29, 0x89,
- 0x63, 0x44, 0x01, 0x0a, 0xef, 0xf1, 0xda, 0x1c, 0x71, 0xe2, 0xc5, 0xe3,
- 0x67, 0x8b, 0x17, 0xf4, 0xc4, 0xdf, 0x98, 0xf5, 0x8b, 0xff, 0xd0, 0x13,
- 0x74, 0x33, 0xfc, 0x14, 0x70, 0xb4, 0xb1, 0x7f, 0x81, 0x20, 0x62, 0x16,
- 0x2c, 0x54, 0x11, 0x6d, 0xd9, 0x8b, 0xa9, 0xdf, 0xfa, 0x21, 0x40, 0xce,
- 0x93, 0xf6, 0xe8, 0xb1, 0x52, 0x9a, 0x56, 0x43, 0x51, 0x8c, 0x2f, 0xe1,
- 0x47, 0xb7, 0x85, 0x2b, 0x14, 0xb1, 0x74, 0xec, 0xb1, 0x5d, 0x9e, 0xaf,
- 0x0c, 0x42, 0x06, 0x5f, 0xf6, 0x7f, 0xc5, 0x20, 0xea, 0xeb, 0x17, 0xe2,
- 0xf1, 0x31, 0xab, 0x14, 0xb1, 0x58, 0x6d, 0x23, 0x8a, 0x29, 0x91, 0x86,
- 0x46, 0x5c, 0x6e, 0xbf, 0x8e, 0xdd, 0x27, 0x41, 0x16, 0x2f, 0xfc, 0xe3,
- 0xce, 0x87, 0xc8, 0x77, 0x05, 0x8b, 0xf3, 0x71, 0x88, 0x0b, 0x17, 0xf3,
- 0xf4, 0x81, 0xe6, 0x25, 0x8b, 0xff, 0x4e, 0x11, 0xe7, 0xe1, 0x18, 0x22,
- 0xc5, 0x40, 0xfc, 0xb4, 0x63, 0x7f, 0xd8, 0x7c, 0xd6, 0x6d, 0x81, 0xac,
- 0x5f, 0xfe, 0xfc, 0xf4, 0xf7, 0x1f, 0xdf, 0xc0, 0x9c, 0x58, 0xa9, 0x4e,
- 0xe3, 0x0c, 0x8d, 0x42, 0x78, 0x4c, 0xfc, 0x88, 0x07, 0x54, 0xb1, 0x7f,
- 0x6c, 0xd9, 0xec, 0x3a, 0xc5, 0x46, 0xe6, 0xe9, 0x83, 0x2f, 0xc3, 0x62,
- 0xc0, 0x8b, 0x17, 0xff, 0xb0, 0xbc, 0xc0, 0xeb, 0xe2, 0x60, 0x71, 0x62,
- 0xfe, 0xcd, 0x37, 0x85, 0x2b, 0x17, 0xff, 0xcc, 0x52, 0xe1, 0x38, 0xfc,
- 0xcf, 0xe4, 0x72, 0xc5, 0x0c, 0xff, 0xfa, 0x16, 0xdf, 0xff, 0xce, 0x36,
- 0xef, 0xae, 0x3c, 0x24, 0xa7, 0xa7, 0x99, 0x62, 0xff, 0xe7, 0x21, 0x43,
- 0x39, 0xc7, 0x1e, 0x2c, 0x54, 0xa7, 0x6f, 0xb1, 0x4c, 0x50, 0xca, 0xf9,
- 0x27, 0x97, 0x6d, 0x18, 0x16, 0x36, 0x33, 0x13, 0x28, 0xe2, 0x10, 0xd1,
- 0xc8, 0xc8, 0x37, 0x2f, 0xed, 0x91, 0xe1, 0xbb, 0x14, 0x6b, 0x9a, 0x87,
- 0xf9, 0xcc, 0x7f, 0x0a, 0x96, 0x8c, 0x30, 0x09, 0xc5, 0x1b, 0xef, 0x23,
- 0x4b, 0xf4, 0x7c, 0xd1, 0xd0, 0x95, 0x32, 0x3d, 0xcb, 0xf8, 0x28, 0x14,
- 0xd3, 0x34, 0x16, 0x2f, 0xf4, 0x6e, 0x51, 0xa7, 0xa3, 0xa3, 0x41, 0xac,
- 0x5f, 0xe0, 0xa6, 0x08, 0xcf, 0xc9, 0xab, 0x17, 0x30, 0x55, 0x62, 0xfe,
- 0x2f, 0xe7, 0x62, 0xdd, 0x62, 0x82, 0xa8, 0x85, 0x23, 0xa3, 0x06, 0xef,
- 0xc1, 0x6c, 0x2a, 0x39, 0x1a, 0xc5, 0xf0, 0x5b, 0x01, 0xb2, 0xb1, 0x7d,
- 0x86, 0x4e, 0x96, 0x2a, 0x36, 0x3c, 0xd2, 0x2a, 0xbf, 0xf3, 0xf7, 0x1a,
- 0xb9, 0xae, 0xbd, 0x7f, 0x1c, 0xb1, 0x7d, 0xd7, 0xaf, 0xe3, 0x96, 0x2f,
- 0xba, 0xf5, 0xfc, 0x72, 0xc5, 0xe9, 0xf6, 0xeb, 0x15, 0x1e, 0x7e, 0x91,
- 0x15, 0xfc, 0xae, 0x82, 0xd5, 0x1e, 0xc3, 0x86, 0x1d, 0xf6, 0x8f, 0xee,
- 0xd6, 0x2f, 0xde, 0x01, 0x85, 0x05, 0x8b, 0xa7, 0x5d, 0x4f, 0x3d, 0x89,
- 0x6f, 0xfe, 0x34, 0x38, 0xfd, 0x87, 0x1b, 0x75, 0xeb, 0xf8, 0xe5, 0x8b,
- 0xe1, 0x6d, 0xa9, 0x58, 0xbe, 0x9c, 0xd4, 0x16, 0x2a, 0x35, 0x22, 0x81,
- 0xd6, 0x88, 0x92, 0xe1, 0xba, 0xc5, 0xef, 0x41, 0x96, 0x2f, 0x73, 0xb7,
- 0x58, 0xbc, 0xdd, 0x31, 0x62, 0xb6, 0x37, 0x9c, 0x1e, 0xa7, 0x44, 0x93,
- 0x0b, 0xf1, 0x66, 0xf9, 0xcb, 0xdc, 0x58, 0xbe, 0xdd, 0x9b, 0x75, 0x45,
- 0xd2, 0x5f, 0x88, 0x5e, 0x9e, 0x2c, 0x5f, 0xff, 0xd2, 0x1f, 0x8d, 0x6e,
- 0x75, 0x97, 0x2c, 0xef, 0xd8, 0xb1, 0x7e, 0xe4, 0x82, 0x37, 0xfa, 0xc5,
- 0x1a, 0x98, 0x3e, 0x88, 0xbe, 0x62, 0x45, 0x1e, 0x5e, 0xbe, 0x61, 0x40,
- 0xeb, 0x17, 0xe3, 0x20, 0xe0, 0xe2, 0xc5, 0xfb, 0xdc, 0x9c, 0xd9, 0x62,
- 0x86, 0x7a, 0x7a, 0x2a, 0xaf, 0xa2, 0x61, 0x9d, 0xaf, 0x89, 0x87, 0x2b,
- 0x17, 0x06, 0x6a, 0xc5, 0xfe, 0x9e, 0x8c, 0x53, 0xd3, 0x8b, 0x17, 0xf7,
- 0xe4, 0xcf, 0x8b, 0x8b, 0x15, 0x28, 0xa1, 0xc2, 0x1f, 0x8d, 0x04, 0x36,
- 0xbf, 0xf7, 0x39, 0x14, 0x02, 0xfd, 0x7a, 0xfe, 0x39, 0x62, 0xf4, 0x24,
- 0xeb, 0x15, 0x1b, 0x9f, 0x58, 0xd3, 0xaf, 0xe8, 0x4f, 0x6d, 0xc8, 0x2c,
- 0x5f, 0xff, 0xfb, 0xc4, 0xc0, 0xe6, 0xff, 0x78, 0x8b, 0x03, 0xfe, 0x1e,
- 0x78, 0xb1, 0x7f, 0xa2, 0xd4, 0xf7, 0x07, 0x3a, 0xc5, 0x4a, 0x29, 0x09,
- 0xba, 0xff, 0xdd, 0x24, 0xbd, 0xc1, 0x7b, 0x34, 0xb1, 0x7f, 0xff, 0xf9,
- 0xfa, 0x85, 0xac, 0x6e, 0x16, 0xff, 0x2e, 0x32, 0x91, 0x6e, 0x1b, 0x0e,
- 0x7b, 0xe2, 0xc5, 0x4a, 0x3c, 0x30, 0x84, 0x90, 0x6f, 0xa0, 0x13, 0x3c,
- 0xb1, 0x7d, 0xc9, 0x09, 0xc5, 0x8a, 0x93, 0xca, 0x08, 0x4b, 0x77, 0x82,
- 0x2c, 0x5b, 0xeb, 0x17, 0xfe, 0xf4, 0xc5, 0xc2, 0xc1, 0xfc, 0x4b, 0x14,
- 0xe7, 0xa5, 0xe1, 0x2b, 0xf1, 0xa6, 0x98, 0x5b, 0xac, 0x54, 0xa2, 0xeb,
- 0x1b, 0x1c, 0x86, 0xfb, 0x73, 0xbc, 0x7a, 0xc5, 0xcc, 0x35, 0x8b, 0xf4,
- 0x1e, 0x61, 0x1e, 0xb1, 0x5d, 0x4f, 0x0b, 0x05, 0xef, 0x0f, 0x06, 0xb1,
- 0x76, 0xb6, 0x58, 0xa9, 0x46, 0x10, 0xda, 0x70, 0x8d, 0xc7, 0x6f, 0x0a,
- 0x4c, 0x58, 0xbf, 0xff, 0xfb, 0xf9, 0xd3, 0x59, 0xcc, 0xd6, 0xf3, 0x9e,
- 0x2c, 0xe7, 0x30, 0x6b, 0x17, 0xfb, 0x69, 0x2d, 0xc6, 0x67, 0x16, 0x2f,
- 0x9c, 0xdc, 0x1a, 0xc5, 0xff, 0xc0, 0x72, 0x30, 0xd7, 0xf3, 0x03, 0x8b,
- 0x17, 0xfc, 0xf8, 0x5f, 0xcf, 0x48, 0xd6, 0x2f, 0xfc, 0xe5, 0xa9, 0xf3,
- 0xee, 0xe3, 0x58, 0xad, 0x93, 0x15, 0xd1, 0xb8, 0x08, 0xfc, 0x8d, 0xd0,
- 0xde, 0xf0, 0x8d, 0x02, 0xc5, 0xfd, 0x3e, 0xe0, 0xb7, 0x0b, 0xac, 0x50,
- 0xcf, 0x4f, 0xa0, 0xfd, 0xf6, 0xff, 0x90, 0xd6, 0x2a, 0x55, 0x39, 0x64,
- 0x71, 0x0d, 0x0a, 0x10, 0xb9, 0x25, 0xff, 0x7d, 0xc3, 0xf7, 0x7b, 0xbf,
- 0xd6, 0x2e, 0x0b, 0x84, 0x58, 0xbf, 0x08, 0x11, 0x17, 0x96, 0x2f, 0xb5,
- 0x9d, 0xca, 0xc5, 0xfd, 0xf7, 0xf4, 0x1b, 0xeb, 0x14, 0x34, 0x6b, 0x47,
- 0x9e, 0xe8, 0x79, 0x8a, 0x84, 0x47, 0x7f, 0xa2, 0x83, 0x6b, 0x6f, 0x89,
- 0x62, 0xfa, 0x28, 0x0b, 0x65, 0x8b, 0x98, 0xc5, 0x8b, 0xff, 0x7b, 0xaf,
- 0x18, 0xb7, 0xfb, 0xe9, 0x62, 0xb6, 0x3d, 0xac, 0x18, 0xa9, 0x46, 0xce,
- 0x1b, 0xf2, 0x10, 0x17, 0xb4, 0xfd, 0xac, 0x5f, 0xe9, 0xf3, 0x6c, 0x27,
- 0x82, 0xc5, 0xc6, 0x7d, 0x62, 0xe1, 0x18, 0xb1, 0x5f, 0x44, 0x21, 0x0f,
- 0x18, 0x68, 0x10, 0x66, 0xff, 0xfc, 0xd0, 0x29, 0xe6, 0x77, 0xb9, 0x36,
- 0x77, 0xba, 0xc5, 0xff, 0xf3, 0x13, 0x6c, 0x53, 0xdb, 0x8c, 0xa7, 0x65,
- 0x8b, 0xfe, 0x7f, 0xe7, 0x60, 0x80, 0xf1, 0x62, 0xd1, 0x91, 0xbb, 0x66,
- 0xf4, 0x14, 0x36, 0x8d, 0x21, 0x98, 0x16, 0x1a, 0x46, 0xa8, 0x40, 0x4c,
- 0x63, 0x9b, 0x3f, 0x42, 0x19, 0xc3, 0x86, 0x36, 0x46, 0x6b, 0xbc, 0x38,
- 0xde, 0x18, 0x71, 0xf0, 0xa8, 0x88, 0x9f, 0x51, 0xe1, 0x9d, 0xdf, 0xf0,
- 0xdd, 0x68, 0x77, 0x80, 0xe8, 0xa5, 0x48, 0x72, 0x32, 0x1f, 0x46, 0x4a,
- 0x28, 0x5b, 0xf4, 0x3f, 0x0d, 0x5e, 0x39, 0x3e, 0xfd, 0x1b, 0x85, 0x3b,
- 0xe1, 0xd6, 0x2e, 0x98, 0xe5, 0x8b, 0xfd, 0x07, 0xf7, 0x27, 0x58, 0xb1,
- 0x7f, 0xf8, 0xbc, 0xe7, 0xfc, 0xb9, 0x36, 0x8d, 0x58, 0xbf, 0x9b, 0xd2,
- 0x79, 0x25, 0x8b, 0xdd, 0x05, 0x05, 0x8a, 0xc4, 0x4a, 0xe9, 0x27, 0xa1,
- 0x65, 0xff, 0xc6, 0x9b, 0x25, 0xef, 0x14, 0xfb, 0x8b, 0x17, 0xfd, 0xc1,
- 0x7a, 0x0f, 0xd3, 0xee, 0xb1, 0x4e, 0x88, 0x23, 0xa3, 0x5f, 0xd9, 0x9c,
- 0xdf, 0xd2, 0xb1, 0x7e, 0xf6, 0x7a, 0x7b, 0x58, 0xbf, 0xb6, 0x9f, 0x31,
- 0xa2, 0x58, 0xa5, 0x8b, 0xfc, 0x59, 0x9d, 0xef, 0x3b, 0x2c, 0x5f, 0xfd,
- 0x3a, 0x07, 0x5e, 0x7e, 0x4e, 0xc4, 0xb1, 0x7f, 0xc2, 0xf3, 0xfd, 0xcd,
- 0xfb, 0xac, 0x5f, 0xfd, 0xae, 0x7d, 0xe7, 0xde, 0x68, 0x71, 0x62, 0xff,
- 0x4e, 0x8c, 0xff, 0xf0, 0x0b, 0x15, 0x04, 0x7d, 0x0d, 0x19, 0xce, 0xbe,
- 0x8b, 0x7f, 0x71, 0xfc, 0x42, 0x82, 0xc5, 0xe3, 0xcc, 0x7a, 0xc5, 0xf7,
- 0x88, 0x50, 0x58, 0xac, 0x3c, 0x37, 0x20, 0xbe, 0xf3, 0x9f, 0x9d, 0x51,
- 0x23, 0xc7, 0x1b, 0xfa, 0x0d, 0x06, 0x2d, 0xd6, 0x29, 0x62, 0xd2, 0xb1,
- 0x43, 0x2f, 0x48, 0x32, 0xdc, 0x58, 0xa9, 0x36, 0x3e, 0x1f, 0xbf, 0xfd,
- 0x9e, 0x90, 0xcc, 0xdb, 0x98, 0x79, 0x8f, 0x58, 0xbf, 0x86, 0x52, 0x18,
- 0xf1, 0x62, 0xc7, 0x58, 0xbf, 0x9a, 0x1a, 0x70, 0xdd, 0x62, 0xf8, 0xa4,
- 0x7a, 0x58, 0xbd, 0xbc, 0xec, 0xb1, 0x7f, 0xe7, 0x83, 0xeb, 0xb9, 0x29,
- 0xe2, 0xc5, 0x6c, 0x7f, 0xfb, 0x91, 0x78, 0x7e, 0xd1, 0x91, 0xba, 0xe2,
- 0x74, 0x86, 0x64, 0x65, 0xfd, 0xc3, 0x36, 0x23, 0xcf, 0xbe, 0x11, 0x07,
- 0x14, 0x3c, 0x5d, 0x1c, 0x24, 0x64, 0x2b, 0x6b, 0xb5, 0xd6, 0x3d, 0x14,
- 0x9e, 0x71, 0xfa, 0xfb, 0x03, 0x8d, 0xce, 0xb1, 0x7f, 0x14, 0xf6, 0x76,
- 0xf2, 0xc5, 0xff, 0xe0, 0xd8, 0x7f, 0x9e, 0xfd, 0x3f, 0x68, 0xf5, 0x8b,
- 0x3e, 0x8f, 0xf7, 0xe5, 0xd7, 0xff, 0xfc, 0x2d, 0x43, 0x9f, 0x67, 0xd6,
- 0xb4, 0x2e, 0xdf, 0x4d, 0xc5, 0x8b, 0xf6, 0x07, 0xcc, 0xfa, 0xc5, 0xff,
- 0xb7, 0x9c, 0xfc, 0xf8, 0xa7, 0xcb, 0x17, 0xf3, 0x17, 0xe7, 0x50, 0x58,
- 0xad, 0x1f, 0x5f, 0x0f, 0xaf, 0x49, 0x44, 0xb1, 0x7e, 0xd7, 0x38, 0xc4,
- 0xb1, 0x5f, 0x3c, 0x51, 0x0e, 0xde, 0x17, 0xf8, 0xb1, 0x7f, 0xe6, 0x37,
- 0x7f, 0xbc, 0x5a, 0x90, 0xd6, 0x2f, 0x4e, 0x77, 0xb9, 0xf0, 0x90, 0xf5,
- 0xff, 0xcc, 0x7e, 0x78, 0x98, 0x1d, 0xfa, 0x35, 0x2c, 0x5b, 0xda, 0x3f,
- 0xf1, 0x19, 0xdf, 0xf8, 0x98, 0x3f, 0x67, 0xda, 0x26, 0x58, 0xbf, 0xff,
- 0x00, 0x13, 0xd7, 0xf3, 0xe1, 0x6f, 0xf9, 0x26, 0x58, 0xbf, 0xff, 0x10,
- 0x9a, 0x3f, 0x21, 0xfc, 0x37, 0x07, 0x10, 0x96, 0x2b, 0x11, 0x65, 0xf5,
- 0x8b, 0xb7, 0xc5, 0x8b, 0xfa, 0x60, 0xfd, 0xfb, 0x16, 0x2f, 0xff, 0x9b,
- 0xb8, 0x73, 0xbf, 0x13, 0x7f, 0x3b, 0xf2, 0xc5, 0x4a, 0x2e, 0xcd, 0x22,
- 0xd0, 0xc3, 0x17, 0x5f, 0x6b, 0x8f, 0xa5, 0x8b, 0xfd, 0x82, 0x0b, 0xef,
- 0xf7, 0x89, 0x62, 0xff, 0x08, 0xdc, 0xfb, 0x7b, 0x8b, 0x17, 0xff, 0xff,
- 0x3c, 0x1b, 0x9c, 0x9e, 0x67, 0xdc, 0xa4, 0xfa, 0x93, 0x18, 0x96, 0x2f,
- 0xff, 0xfe, 0xce, 0x19, 0xe7, 0xe8, 0xfe, 0x84, 0xfd, 0xe7, 0xdf, 0x13,
- 0x1d, 0x62, 0xa5, 0x1c, 0x70, 0x6f, 0xae, 0x26, 0x75, 0xe8, 0xc6, 0x2f,
- 0xdc, 0x9f, 0x99, 0x12, 0xc5, 0x39, 0xea, 0xf8, 0xaa, 0xa5, 0x50, 0x6e,
- 0x11, 0xb4, 0x79, 0x37, 0xa1, 0x27, 0x58, 0xbe, 0x87, 0xf0, 0xeb, 0x17,
- 0x8b, 0x3e, 0xb1, 0x52, 0x6f, 0xe0, 0x47, 0x4b, 0x17, 0xf6, 0x0f, 0x58,
- 0xf1, 0x2c, 0x5f, 0xed, 0x8b, 0x3b, 0xf6, 0x06, 0xb1, 0x7e, 0xef, 0xd3,
- 0x81, 0x91, 0xf2, 0x18, 0x5d, 0x51, 0xa2, 0x2c, 0x31, 0xc2, 0xfe, 0x3b,
- 0xfb, 0x82, 0xd9, 0x62, 0xee, 0x41, 0x62, 0xff, 0xfb, 0x06, 0x2f, 0x73,
- 0x7f, 0xbf, 0x04, 0xdd, 0xac, 0x5f, 0xff, 0xff, 0x89, 0x8d, 0xcd, 0x02,
- 0x7d, 0xc1, 0xfe, 0x78, 0x32, 0x63, 0x75, 0x9d, 0xf1, 0x62, 0xff, 0x88,
- 0x5b, 0x7b, 0x98, 0x40, 0x58, 0xbc, 0xd0, 0xe0, 0xd1, 0x7e, 0x64, 0x21,
- 0x6b, 0xe9, 0xa6, 0x0a, 0x31, 0x2a, 0xc4, 0xef, 0x8d, 0x30, 0xf4, 0x6c,
- 0x97, 0xfb, 0x5a, 0x68, 0x6d, 0x81, 0xac, 0x52, 0xc5, 0xd1, 0x09, 0x62,
- 0xb0, 0xf6, 0xfe, 0x6c, 0x18, 0x65, 0xff, 0x7c, 0xcf, 0x3e, 0x9f, 0x69,
- 0x58, 0xbf, 0xff, 0x85, 0x02, 0x78, 0x16, 0x7b, 0x93, 0x01, 0xcf, 0x96,
- 0x2f, 0xfd, 0x3d, 0xef, 0xf7, 0xd6, 0x9a, 0x0b, 0x17, 0xfb, 0x62, 0xce,
- 0xfd, 0x81, 0xac, 0x5f, 0xc3, 0x6e, 0xfd, 0x87, 0x39, 0xfb, 0x98, 0x83,
- 0x7d, 0xa9, 0x0f, 0x8b, 0x17, 0xbf, 0x91, 0x2c, 0x5f, 0xfe, 0x2f, 0x73,
- 0x1c, 0xf8, 0x39, 0x84, 0xe1, 0xe1, 0x78, 0x92, 0x9d, 0x1c, 0xa2, 0x84,
- 0x45, 0x41, 0x52, 0x3e, 0x17, 0xb9, 0xdf, 0x23, 0xb6, 0xbf, 0xfb, 0x07,
- 0x30, 0x9d, 0x49, 0x8c, 0x4b, 0x17, 0xfe, 0xe9, 0x90, 0x38, 0xdf, 0xa4,
- 0x8d, 0x62, 0xff, 0xf9, 0xfe, 0x23, 0x9d, 0xa1, 0xf6, 0x3b, 0xf1, 0x62,
- 0x8e, 0x8d, 0x66, 0x43, 0xf2, 0x1d, 0xcd, 0x19, 0xb3, 0x37, 0xaa, 0x0d,
- 0x39, 0x09, 0x4d, 0xd9, 0xfb, 0x8c, 0x0a, 0x22, 0x8d, 0x47, 0x59, 0xf9,
- 0x49, 0x2c, 0x6a, 0x05, 0xc2, 0x86, 0x87, 0x23, 0xe5, 0xf4, 0xad, 0x93,
- 0x23, 0x19, 0xaf, 0xb3, 0xc5, 0x0a, 0x9c, 0x23, 0x7f, 0x71, 0xfc, 0x42,
- 0x82, 0xc5, 0xf9, 0xfc, 0x42, 0x82, 0xc5, 0xc7, 0xe7, 0x53, 0xd6, 0xe1,
- 0x75, 0xfd, 0x38, 0x0c, 0xc1, 0xac, 0x5b, 0xce, 0x7b, 0x84, 0x61, 0x7e,
- 0xe1, 0xe4, 0xa2, 0x58, 0xbf, 0x8b, 0xc7, 0x9c, 0xf2, 0xc5, 0xfb, 0xdf,
- 0x93, 0x09, 0x62, 0xd0, 0x93, 0xd6, 0xc2, 0xdb, 0xff, 0x79, 0xf7, 0x71,
- 0xb1, 0x1b, 0x2b, 0x17, 0x86, 0xe6, 0xac, 0x5f, 0xf4, 0xf7, 0xf6, 0xe7,
- 0xa4, 0x35, 0x8a, 0x94, 0x4c, 0x61, 0xfe, 0x87, 0xaf, 0xfb, 0x04, 0x17,
- 0x78, 0x9f, 0x09, 0x62, 0xff, 0xdb, 0x90, 0xbd, 0xcd, 0x3f, 0x60, 0x58,
- 0xbf, 0x10, 0xb6, 0xee, 0x3d, 0x62, 0xb0, 0xfc, 0x3c, 0x85, 0x58, 0x8c,
- 0xd6, 0x85, 0x65, 0x82, 0xab, 0x17, 0x0b, 0xeb, 0x17, 0xe2, 0xcf, 0xb7,
- 0x96, 0x2f, 0xe8, 0x36, 0x74, 0x91, 0xac, 0x50, 0x54, 0xf5, 0x82, 0xc2,
- 0x7b, 0xf4, 0x6c, 0x15, 0xd7, 0x38, 0xb1, 0x7c, 0xe2, 0x84, 0xac, 0x5f,
- 0x67, 0x72, 0x75, 0x8b, 0xe7, 0x29, 0x02, 0xc5, 0xff, 0xf0, 0xf0, 0xfc,
- 0x13, 0x3c, 0x1f, 0x58, 0x35, 0x8b, 0xff, 0xff, 0x69, 0xfa, 0x48, 0xdc,
- 0x9b, 0x46, 0xf5, 0xfb, 0x70, 0x39, 0x1a, 0xc5, 0xfe, 0xfc, 0xed, 0xa9,
- 0xc1, 0xac, 0x5f, 0xa7, 0xa3, 0x66, 0x96, 0x2e, 0xcd, 0x96, 0x2e, 0x1c,
- 0xac, 0x51, 0x86, 0xbc, 0x20, 0xc5, 0x4a, 0x2c, 0x3e, 0x68, 0x25, 0x8b,
- 0xf3, 0x45, 0x07, 0xf2, 0xc5, 0xe1, 0xb4, 0x16, 0x2f, 0xe0, 0x8f, 0xd3,
- 0xd9, 0xf5, 0x8a, 0xc3, 0xcf, 0x10, 0xed, 0xfd, 0x9e, 0x73, 0xbe, 0x96,
- 0x2f, 0xe9, 0x83, 0xf7, 0xec, 0x58, 0xb0, 0xc6, 0x7b, 0x7a, 0x2d, 0xbe,
- 0xc2, 0x98, 0x2c, 0x54, 0x9e, 0x4f, 0x8a, 0x2f, 0xff, 0x7e, 0x60, 0x3f,
- 0xcf, 0x7e, 0x73, 0xf1, 0x62, 0xe1, 0x41, 0x62, 0x98, 0xf9, 0x3a, 0x26,
- 0x5c, 0x79, 0x58, 0xb4, 0xac, 0x56, 0x1a, 0x8d, 0x0b, 0xd4, 0x17, 0x0c,
- 0x8d, 0x22, 0xdc, 0x8d, 0xc8, 0x74, 0x9f, 0xf8, 0xc8, 0x40, 0x5e, 0x4f,
- 0x1e, 0x86, 0x2f, 0x48, 0x42, 0x84, 0x4b, 0xbf, 0xed, 0x73, 0xef, 0xbe,
- 0xe2, 0xd9, 0x62, 0xfe, 0x0f, 0x3a, 0x10, 0xa0, 0xb1, 0x7f, 0x08, 0xdc,
- 0x20, 0x98, 0xb1, 0x78, 0x2e, 0xfd, 0xac, 0x5f, 0xff, 0xef, 0xb9, 0xce,
- 0xe1, 0xf3, 0xbd, 0xdf, 0x34, 0x39, 0xed, 0x62, 0xff, 0xfa, 0x61, 0x9c,
- 0x72, 0x01, 0x67, 0xbf, 0x8b, 0x16, 0x86, 0xe8, 0xb2, 0x26, 0x5a, 0xed,
- 0x1f, 0xba, 0x86, 0xa5, 0x4a, 0x78, 0xb8, 0x7c, 0x46, 0x22, 0x8c, 0xb6,
- 0xfd, 0xc2, 0xcf, 0xe2, 0xc5, 0xff, 0xff, 0x48, 0xff, 0x9d, 0xf8, 0x9b,
- 0xe0, 0x6e, 0x71, 0xb5, 0xba, 0xc5, 0xe3, 0x8b, 0xeb, 0x17, 0xe9, 0x89,
- 0x9b, 0x4b, 0x17, 0xfd, 0x3c, 0xfe, 0x74, 0x9c, 0xed, 0x62, 0xde, 0x94,
- 0x40, 0xf0, 0x7b, 0xc5, 0x17, 0xdb, 0x47, 0x31, 0xab, 0x17, 0xfb, 0x33,
- 0x0d, 0x35, 0xa0, 0xb1, 0x58, 0x9d, 0x09, 0xa4, 0xef, 0x0e, 0x9f, 0x9a,
- 0xf8, 0xa2, 0xfb, 0x9b, 0xfa, 0x56, 0x2f, 0xf3, 0x9d, 0xf5, 0xc8, 0x4a,
- 0xc5, 0x61, 0xeb, 0xf8, 0x92, 0xfc, 0xdb, 0x61, 0x6e, 0xb1, 0x7f, 0xf0,
- 0x7c, 0xdf, 0xef, 0xdf, 0xb5, 0xa9, 0x58, 0xbe, 0x60, 0xfa, 0xc1, 0x62,
- 0x9c, 0xfb, 0xc9, 0x26, 0xff, 0xda, 0xf3, 0x43, 0x9d, 0x05, 0xa7, 0x58,
- 0xbf, 0xf9, 0xb8, 0x4c, 0x68, 0xfe, 0x26, 0xe2, 0xc5, 0x4a, 0x21, 0xc4,
- 0x85, 0x7f, 0xff, 0xcc, 0x19, 0x99, 0xa2, 0x6e, 0xe1, 0xbc, 0xfb, 0x99,
- 0xdf, 0x96, 0x2f, 0xc5, 0x80, 0x90, 0x2c, 0x5f, 0xdb, 0x19, 0x9f, 0x6e,
- 0xd6, 0x2f, 0xf4, 0x1c, 0xa2, 0x83, 0xfd, 0x62, 0xf7, 0x04, 0x75, 0x8b,
- 0xff, 0xed, 0x6b, 0x39, 0xc1, 0x17, 0x30, 0xf3, 0x1e, 0xb1, 0x69, 0x82,
- 0x3f, 0x70, 0x9e, 0x23, 0x1f, 0x1a, 0x06, 0x3d, 0x58, 0xac, 0xe9, 0xc8,
- 0x75, 0x09, 0x8f, 0xc2, 0x9d, 0x88, 0x8a, 0x36, 0x8b, 0xf7, 0x47, 0xd6,
- 0x0d, 0x62, 0xff, 0xfb, 0x9f, 0x7e, 0x7b, 0xf8, 0x37, 0xe6, 0x12, 0xc5,
- 0x8b, 0x0f, 0xe4, 0x45, 0x57, 0xf8, 0x9b, 0x46, 0xfb, 0x37, 0x58, 0xb7,
- 0xe4, 0xf6, 0xf0, 0x9a, 0xfc, 0xdf, 0x81, 0x6e, 0xb1, 0x7f, 0xa4, 0xf8,
- 0xe7, 0x98, 0xf5, 0x8b, 0xfd, 0x03, 0xf1, 0xcb, 0xb8, 0x2c, 0x56, 0xe7,
- 0xd5, 0x11, 0xad, 0xfe, 0x7d, 0x31, 0x03, 0x09, 0x62, 0xff, 0x79, 0xcb,
- 0x3b, 0x84, 0xac, 0x5f, 0xfd, 0xad, 0x34, 0x38, 0x58, 0x73, 0x3b, 0x58,
- 0xa9, 0x3f, 0xac, 0x33, 0xbf, 0xff, 0x86, 0xcc, 0x6e, 0x7a, 0x7e, 0xcf,
- 0xce, 0x48, 0x16, 0x2f, 0xf9, 0xe0, 0x59, 0xf2, 0x68, 0x2c, 0x5f, 0xff,
- 0xa1, 0x84, 0x3f, 0xce, 0x14, 0x80, 0xed, 0x05, 0x8a, 0x24, 0x45, 0x18,
- 0x6f, 0x79, 0x9b, 0x75, 0x44, 0x98, 0x5f, 0xb6, 0x63, 0x8d, 0xd6, 0x2f,
- 0x04, 0x7e, 0x2c, 0x54, 0x11, 0x2b, 0xb9, 0x1b, 0x95, 0x04, 0x29, 0xbd,
- 0x1b, 0x46, 0xe1, 0x55, 0x8b, 0xff, 0x33, 0xfa, 0x7e, 0xe7, 0x61, 0xac,
- 0x54, 0x6a, 0x3e, 0x9f, 0x96, 0x5f, 0xfe, 0xe0, 0xff, 0x3f, 0x93, 0xeb,
- 0x4f, 0xba, 0xc5, 0x6e, 0x7e, 0x8c, 0x51, 0x7f, 0xff, 0xfb, 0x37, 0x91,
- 0x6f, 0xf9, 0xd7, 0x5c, 0x27, 0xef, 0x86, 0x6c, 0x58, 0x35, 0x8b, 0xfd,
- 0xd1, 0x8f, 0x86, 0xcf, 0x16, 0x2f, 0x77, 0x0e, 0x75, 0x45, 0x9e, 0x3e,
- 0xdf, 0xec, 0xef, 0xde, 0x68, 0x71, 0x62, 0xa5, 0x34, 0x1c, 0x86, 0xae,
- 0x8d, 0xef, 0xf1, 0x37, 0xb9, 0xb8, 0x89, 0x62, 0xff, 0xf8, 0x0e, 0x00,
- 0xf1, 0xfa, 0x16, 0x7b, 0xee, 0xb1, 0x7b, 0x6f, 0x3a, 0xc5, 0xff, 0xc4,
- 0xc1, 0xf0, 0x36, 0x1c, 0xf7, 0xc5, 0x8b, 0x62, 0xc5, 0x68, 0xf6, 0x3c,
- 0x8f, 0x7e, 0xe3, 0x34, 0x38, 0xb1, 0x7d, 0xf1, 0x16, 0xcb, 0x17, 0x3f,
- 0x6b, 0x17, 0xf3, 0x43, 0x98, 0x40, 0x58, 0xb3, 0x75, 0x4c, 0xa4, 0x6e,
- 0xdd, 0x91, 0x31, 0x40, 0x5c, 0x93, 0xc3, 0x16, 0xd6, 0x27, 0xbb, 0xf8,
- 0xde, 0xaf, 0xff, 0xe6, 0xd8, 0xa7, 0xbe, 0xf7, 0x13, 0x68, 0x19, 0xdf,
- 0x96, 0x2b, 0x15, 0x50, 0x3c, 0xa1, 0x12, 0x2f, 0xbf, 0xe6, 0x87, 0x30,
- 0xa7, 0xbe, 0x2c, 0x5f, 0xfe, 0x3b, 0x76, 0x3d, 0x63, 0x9a, 0x39, 0x25,
- 0x8b, 0xd0, 0x70, 0x2c, 0x56, 0x1f, 0x47, 0x12, 0xef, 0xff, 0x1a, 0xdc,
- 0xd6, 0xb3, 0x60, 0x1e, 0x60, 0xb1, 0x7d, 0xef, 0x4e, 0x96, 0x2b, 0xc7,
- 0xe0, 0x62, 0x6d, 0x41, 0x16, 0x81, 0xc2, 0x46, 0xff, 0xff, 0xdf, 0xc8,
- 0x7f, 0x06, 0x53, 0xb9, 0x92, 0x1e, 0x73, 0x8c, 0x6a, 0xc5, 0x4a, 0x26,
- 0x3c, 0x53, 0x7f, 0xd0, 0xfc, 0x91, 0xa1, 0x77, 0xed, 0x62, 0xff, 0xb0,
- 0x6d, 0x0f, 0x71, 0x80, 0xb1, 0x5d, 0x9f, 0xc0, 0x67, 0xf7, 0xff, 0x8a,
- 0x43, 0x33, 0xc5, 0x20, 0xce, 0xfc, 0xb1, 0x7f, 0xb3, 0x5f, 0x29, 0xee,
- 0x0b, 0x17, 0x37, 0x78, 0x88, 0x03, 0x13, 0x29, 0xd1, 0xa6, 0x28, 0x52,
- 0x5f, 0xff, 0xfd, 0xbb, 0x11, 0x4f, 0x71, 0x14, 0xed, 0x07, 0xe7, 0x24,
- 0x85, 0x1e, 0xb1, 0x7f, 0xee, 0xc3, 0xf7, 0xde, 0x4b, 0x37, 0x58, 0xa9,
- 0x45, 0xbb, 0xbb, 0x5f, 0xf8, 0x98, 0xe0, 0x7d, 0x3f, 0x60, 0x58, 0xbe,
- 0xc7, 0xd6, 0xcb, 0x14, 0x33, 0xe2, 0x0b, 0x9f, 0xdf, 0xd2, 0x3d, 0x8f,
- 0x3a, 0x58, 0xb8, 0x12, 0xb1, 0x67, 0x34, 0xf1, 0xbc, 0x5f, 0x50, 0x66,
- 0xeb, 0x8c, 0x9b, 0x21, 0x26, 0x69, 0x26, 0xf0, 0xab, 0x72, 0x0d, 0x46,
- 0xf2, 0x79, 0x4b, 0xbf, 0x95, 0xa8, 0x03, 0x62, 0x8f, 0xb7, 0x91, 0xb6,
- 0xfa, 0x1b, 0xc2, 0x84, 0x1f, 0x46, 0xcb, 0xf8, 0x60, 0x0a, 0xf0, 0x11,
- 0xcb, 0x17, 0x82, 0x04, 0x95, 0x8b, 0xff, 0xb0, 0x3f, 0xb7, 0xb9, 0x3f,
- 0x32, 0x25, 0x8b, 0xff, 0xd9, 0xaf, 0xb3, 0xf8, 0x5a, 0x6e, 0x98, 0xb1,
- 0x43, 0x44, 0x9f, 0xd2, 0x2f, 0xfa, 0x62, 0x84, 0x83, 0x40, 0x95, 0x8b,
- 0xf4, 0x83, 0xdd, 0x20, 0xb1, 0x73, 0x8d, 0x62, 0x88, 0xf0, 0xb8, 0x57,
- 0x7f, 0x14, 0xf6, 0x76, 0xf2, 0xc5, 0xfe, 0xdf, 0xc2, 0xfe, 0xa4, 0x35,
- 0x8b, 0xff, 0xb3, 0xbf, 0xe0, 0xff, 0x91, 0x41, 0x96, 0x2a, 0x4f, 0xf4,
+ 0x7d, 0x62, 0xfd, 0x1b, 0x77, 0xba, 0xe7, 0x16, 0x2f, 0x6e, 0x2d, 0xd6,
+ 0x2e, 0x11, 0x2c, 0x5f, 0xf6, 0x1f, 0x8f, 0x1d, 0x9a, 0x95, 0x8a, 0xdc,
+ 0xfc, 0xa3, 0xc8, 0x3b, 0x85, 0xef, 0xde, 0x3f, 0xdc, 0x6b, 0x17, 0xdc,
+ 0x11, 0xdd, 0x62, 0xf4, 0x9c, 0x6b, 0x17, 0x05, 0xf5, 0x8a, 0x73, 0xd9,
+ 0x22, 0x30, 0x87, 0x6f, 0xd8, 0x43, 0xcd, 0x96, 0x2f, 0xf9, 0xf5, 0xc2,
+ 0xc1, 0xfe, 0x56, 0x2f, 0x67, 0x43, 0x58, 0xbb, 0x58, 0xb1, 0x7d, 0x33,
+ 0xbe, 0x0c, 0xda, 0xe8, 0x7a, 0x9d, 0x19, 0x9f, 0x28, 0x26, 0xdb, 0xf6,
+ 0x6b, 0x71, 0x1a, 0xb1, 0x7f, 0xdb, 0xc9, 0xf1, 0xcf, 0x31, 0xeb, 0x17,
+ 0xcf, 0xa6, 0x75, 0x8b, 0xff, 0x16, 0x1a, 0xd1, 0x73, 0xf2, 0x35, 0x8b,
+ 0xd1, 0x37, 0x96, 0x2f, 0xb7, 0x66, 0xdd, 0x52, 0x4d, 0x17, 0x82, 0x6f,
+ 0xac, 0x5f, 0xd3, 0xbe, 0x6f, 0xf1, 0x2c, 0x5b, 0x3a, 0x3c, 0xe3, 0x8f,
+ 0x5f, 0xfb, 0x08, 0x72, 0x67, 0x7c, 0xec, 0x07, 0x58, 0xba, 0x49, 0x62,
+ 0xb8, 0x7b, 0xbd, 0x91, 0xef, 0xcf, 0xcf, 0x67, 0xd6, 0x2f, 0xf3, 0xeb,
+ 0x22, 0x91, 0x77, 0xeb, 0x14, 0x35, 0x4d, 0xf8, 0x56, 0x69, 0xe3, 0x90,
+ 0xc4, 0x81, 0xa1, 0xe2, 0x7f, 0xe4, 0x21, 0x7c, 0x49, 0xd8, 0xa2, 0xfb,
+ 0x4c, 0x37, 0x58, 0xbf, 0xfd, 0xbb, 0x6b, 0x9f, 0x67, 0xe7, 0x33, 0x8b,
+ 0x17, 0xff, 0xfd, 0x85, 0xee, 0x3e, 0xf8, 0x5c, 0xdf, 0xef, 0xfd, 0xc3,
+ 0xd9, 0x62, 0xff, 0xb8, 0xdd, 0x64, 0x53, 0xfe, 0x2c, 0x59, 0xfe, 0x8f,
+ 0x12, 0x4b, 0xf3, 0x5d, 0xfe, 0xd6, 0xdc, 0xd6, 0xa4, 0x25, 0x8b, 0xfb,
+ 0x36, 0xcd, 0xf0, 0x6b, 0x17, 0xff, 0x19, 0xbf, 0xdf, 0xfb, 0xb7, 0x3f,
+ 0x2b, 0x15, 0xf4, 0x71, 0x31, 0xa1, 0x1b, 0xf0, 0xbe, 0xff, 0xdf, 0x72,
+ 0xdb, 0x82, 0x9d, 0x44, 0xb1, 0x7f, 0xfe, 0xcd, 0xa7, 0x8f, 0xac, 0x33,
+ 0x1c, 0xa4, 0xeb, 0x15, 0x04, 0x4a, 0xf9, 0x06, 0xf7, 0xa7, 0x8b, 0x17,
+ 0x1e, 0x0b, 0x15, 0x26, 0xd6, 0x03, 0xb7, 0xec, 0xdf, 0xd9, 0xba, 0xc5,
+ 0x84, 0xb1, 0x58, 0x6f, 0x22, 0x2a, 0xbe, 0xf7, 0x18, 0x0b, 0x17, 0xee,
+ 0xef, 0xe1, 0x1a, 0xb1, 0x73, 0x74, 0xb1, 0x7f, 0xa7, 0xdc, 0xd3, 0x9f,
+ 0x16, 0x2f, 0x03, 0xce, 0xb1, 0x7f, 0xb9, 0xbb, 0xeb, 0x4f, 0xb2, 0xc5,
+ 0x4a, 0x3b, 0x70, 0x8f, 0x72, 0xce, 0x86, 0x18, 0xcf, 0x83, 0xb7, 0xff,
+ 0xf6, 0xc2, 0xd4, 0x5c, 0xda, 0x62, 0xe7, 0xf0, 0x6f, 0xd9, 0x62, 0xff,
+ 0xff, 0x7d, 0x8d, 0x2c, 0x87, 0xe6, 0x19, 0xf2, 0xc6, 0xd9, 0x62, 0xf8,
+ 0xd9, 0x2d, 0xd6, 0x2f, 0xfb, 0x34, 0xd2, 0xe5, 0x27, 0x58, 0xbf, 0xfb,
+ 0xf3, 0xbb, 0xef, 0x80, 0x3c, 0xe9, 0x62, 0xff, 0xff, 0xfa, 0x7a, 0xdf,
+ 0xf8, 0x67, 0xf3, 0x7f, 0xbf, 0xf0, 0x98, 0xdc, 0xed, 0x3d, 0x2c, 0x5f,
+ 0xb6, 0x33, 0xe0, 0xec, 0xb1, 0x5b, 0x2a, 0x14, 0x1b, 0x19, 0xac, 0x1c,
+ 0x24, 0xf1, 0xb7, 0x64, 0x60, 0xe1, 0x07, 0x7f, 0xb9, 0x31, 0xf9, 0xd9,
+ 0xf4, 0xb1, 0x7f, 0xb7, 0xfb, 0x83, 0xee, 0x75, 0x8a, 0x39, 0xf6, 0xf6,
+ 0x38, 0xbf, 0x8c, 0x92, 0x37, 0xee, 0xb1, 0x7d, 0x85, 0x21, 0x2c, 0x5f,
+ 0x3f, 0x01, 0x8b, 0x17, 0xcf, 0xb6, 0x0d, 0x62, 0xa0, 0x89, 0x68, 0x8b,
+ 0xf4, 0x45, 0xe2, 0x2a, 0xc4, 0xf5, 0x5e, 0x1b, 0xad, 0x0b, 0xab, 0xb4,
+ 0x25, 0x8b, 0xec, 0xf8, 0x7a, 0x58, 0xa3, 0x9b, 0xc2, 0x18, 0xbb, 0x68,
+ 0xf5, 0x8b, 0x85, 0xd2, 0xc5, 0xc7, 0x8e, 0x58, 0xbf, 0x98, 0xb7, 0x33,
+ 0x6e, 0x2c, 0x51, 0xa8, 0x81, 0x38, 0xe0, 0x06, 0x44, 0x37, 0x7f, 0xb7,
+ 0xdc, 0x5a, 0x07, 0xc4, 0xb1, 0x7f, 0x49, 0x7a, 0x3b, 0x3c, 0xb1, 0x7f,
+ 0xcc, 0x0d, 0xdf, 0x5a, 0x7d, 0x96, 0x2f, 0xf3, 0x01, 0xbd, 0xec, 0xfa,
+ 0xc5, 0x41, 0x13, 0xd1, 0x18, 0x04, 0x77, 0x7d, 0xf7, 0xcd, 0x2c, 0x5d,
+ 0xf1, 0x2c, 0x5a, 0x0b, 0x17, 0xfb, 0x6c, 0xdf, 0xc4, 0xd1, 0x2c, 0x54,
+ 0x68, 0x9c, 0x56, 0x43, 0x59, 0xcc, 0x80, 0x45, 0xd8, 0x60, 0x31, 0x2b,
+ 0xdf, 0x08, 0x0b, 0x16, 0xf2, 0xc5, 0x39, 0xb1, 0xf8, 0xfd, 0xc3, 0x95,
+ 0x8b, 0xff, 0xf7, 0xb8, 0x1f, 0x35, 0x23, 0xcf, 0xef, 0x85, 0xb2, 0xc5,
+ 0x49, 0xf8, 0x60, 0xbd, 0xfd, 0x2e, 0x06, 0xf0, 0x96, 0x2f, 0xfd, 0x80,
+ 0xcc, 0x8a, 0x22, 0x91, 0xac, 0x5f, 0xfb, 0x40, 0x19, 0x4c, 0x3f, 0xc0,
+ 0x2c, 0x56, 0x26, 0xb8, 0x78, 0x48, 0x7c, 0x80, 0x8b, 0x44, 0x7f, 0x7b,
+ 0xd3, 0x05, 0x8b, 0xfe, 0x17, 0xbf, 0x91, 0x42, 0x7a, 0x58, 0xbf, 0xfc,
+ 0x4d, 0xec, 0xf7, 0x33, 0xf9, 0x1f, 0xe5, 0x8a, 0xfa, 0x29, 0x48, 0x77,
+ 0xb1, 0xe5, 0xff, 0x9f, 0x5a, 0x7d, 0xb8, 0xe0, 0xe2, 0xc5, 0xa2, 0x58,
+ 0xb9, 0xbe, 0xb1, 0x7d, 0xf6, 0x21, 0xac, 0x5d, 0x31, 0x2c, 0x56, 0x1b,
+ 0xa0, 0x11, 0x56, 0xc8, 0x84, 0x80, 0x98, 0x14, 0x6f, 0xff, 0xec, 0x8f,
+ 0x62, 0x07, 0x37, 0xfb, 0xff, 0x24, 0xbc, 0xb1, 0x74, 0x9a, 0xb1, 0x7b,
+ 0xb3, 0xe9, 0x62, 0xc4, 0xb1, 0x58, 0x6c, 0x18, 0x7e, 0xf8, 0x5c, 0x73,
+ 0xac, 0x5e, 0x8d, 0x51, 0xaa, 0x35, 0x2c, 0x50, 0x0f, 0x4f, 0x84, 0x76,
+ 0x68, 0x91, 0x28, 0x07, 0x2b, 0xf9, 0xe4, 0xfb, 0x60, 0x4b, 0x17, 0xff,
+ 0xd9, 0xef, 0xe4, 0x34, 0xc5, 0xef, 0xb4, 0x16, 0x2e, 0x90, 0x2c, 0x5f,
+ 0xe6, 0xea, 0x77, 0x7d, 0xe3, 0x34, 0x89, 0x52, 0x2f, 0x0d, 0x3e, 0xb1,
+ 0x5b, 0xd6, 0xe6, 0x2f, 0x0c, 0x48, 0x8c, 0x7e, 0xba, 0x50, 0xdc, 0xe4,
+ 0x2f, 0xaf, 0x34, 0x5c, 0x58, 0xbf, 0x17, 0x3f, 0x91, 0xeb, 0x16, 0xd2,
+ 0xc5, 0x61, 0xbd, 0x0c, 0xae, 0xfc, 0x0f, 0xcc, 0x38, 0xb1, 0x7f, 0x87,
+ 0x23, 0x21, 0x30, 0x6b, 0x17, 0x88, 0x46, 0xac, 0x5e, 0x09, 0xb6, 0x58,
+ 0xbf, 0xe9, 0x03, 0x78, 0x01, 0x94, 0x16, 0x2b, 0xe7, 0xb2, 0x43, 0xf5,
+ 0x28, 0xf5, 0x19, 0x49, 0x1a, 0x79, 0xde, 0xd1, 0x91, 0xa3, 0x73, 0x81,
+ 0xdf, 0x51, 0x89, 0x85, 0x36, 0xc6, 0xd0, 0x84, 0x10, 0xe1, 0xf5, 0x92,
+ 0xa7, 0x4d, 0x84, 0x9e, 0xf1, 0xfa, 0xf5, 0x0d, 0x07, 0x58, 0x89, 0x73,
+ 0x51, 0x87, 0x7e, 0x70, 0xfd, 0x9d, 0x01, 0x0a, 0x12, 0x8f, 0x23, 0x91,
+ 0xf8, 0x7a, 0x71, 0xb4, 0x4e, 0x91, 0xcb, 0x61, 0xc6, 0x2d, 0x68, 0x2c,
+ 0x5d, 0xb4, 0x72, 0xc5, 0xff, 0xf6, 0x79, 0xfe, 0x2f, 0xb3, 0xf5, 0xc9,
+ 0x35, 0x62, 0xf9, 0xc8, 0x0e, 0xb1, 0x7d, 0xbb, 0x36, 0xea, 0x92, 0xa8,
+ 0xa8, 0x1e, 0x96, 0x88, 0x6f, 0xfc, 0xd0, 0x8c, 0xcd, 0x6e, 0xcd, 0xba,
+ 0xa4, 0x6d, 0x2f, 0xfc, 0xcf, 0xe8, 0x4e, 0xb4, 0xd0, 0x58, 0xb4, 0x64,
+ 0x6c, 0x9c, 0x0e, 0xc2, 0x43, 0x1c, 0xc8, 0x51, 0x9c, 0x8b, 0xea, 0x17,
+ 0xfa, 0x33, 0x35, 0xbb, 0x36, 0xea, 0x92, 0xfc, 0xbf, 0x6b, 0x76, 0x6d,
+ 0xd5, 0x26, 0x31, 0x77, 0x74, 0x16, 0x2d, 0x19, 0x87, 0xa5, 0x11, 0xbd,
+ 0xff, 0xef, 0xce, 0xd9, 0x0f, 0xcb, 0xeb, 0x09, 0x62, 0xfc, 0xf9, 0x09,
+ 0x82, 0xc5, 0xdb, 0x46, 0x44, 0x7e, 0x1c, 0x49, 0xbf, 0xec, 0x8a, 0x0d,
+ 0xad, 0xbe, 0x25, 0x8b, 0xc2, 0x2f, 0x2c, 0x5f, 0x83, 0xd0, 0x73, 0x12,
+ 0xc5, 0xc0, 0x75, 0x8b, 0xdf, 0x93, 0x56, 0x28, 0xd3, 0x6b, 0xb8, 0xbd,
+ 0xde, 0xe2, 0xc5, 0xce, 0x75, 0x8a, 0x93, 0x5f, 0xc1, 0x8b, 0xf7, 0x8a,
+ 0x73, 0xa5, 0x8a, 0x1a, 0x6a, 0x98, 0x79, 0xf1, 0xde, 0x30, 0xf9, 0x48,
+ 0x32, 0x0b, 0xe3, 0x3c, 0xdf, 0x58, 0xb8, 0xa2, 0x58, 0xbf, 0xd0, 0xc2,
+ 0x06, 0x60, 0xd6, 0x2f, 0xfb, 0x69, 0xe3, 0x03, 0x8e, 0x35, 0x8b, 0xf3,
+ 0xe8, 0x38, 0xb8, 0xb1, 0x6f, 0x2c, 0x5f, 0x0a, 0x19, 0xc5, 0x86, 0x2c,
+ 0xaf, 0xf0, 0xb3, 0x5b, 0xfd, 0xf8, 0xb1, 0x50, 0x4c, 0x3f, 0x46, 0x5f,
+ 0x3a, 0x23, 0xde, 0x18, 0xdf, 0xf8, 0xd1, 0x7b, 0x9e, 0xeb, 0x77, 0x25,
+ 0x8b, 0xf4, 0xff, 0xf3, 0xd2, 0xc5, 0xfc, 0xef, 0x21, 0x4c, 0x4b, 0x17,
+ 0xf4, 0x85, 0x1c, 0x1f, 0xd9, 0x62, 0xdd, 0xfa, 0xc5, 0x68, 0xf2, 0x84,
+ 0x67, 0x7e, 0x1c, 0x69, 0x1a, 0x11, 0xab, 0x17, 0xde, 0xe3, 0x74, 0xb1,
+ 0x51, 0xb9, 0xec, 0x49, 0xa5, 0xfd, 0x17, 0x5c, 0x7e, 0xb8, 0xb1, 0x7f,
+ 0x85, 0xb4, 0x50, 0x9d, 0x6c, 0xb1, 0x4e, 0x7d, 0x44, 0x65, 0x76, 0xbc,
+ 0xb1, 0x79, 0x9c, 0x4b, 0x17, 0xba, 0x6e, 0xe5, 0x8b, 0xe6, 0x86, 0x0d,
+ 0x62, 0xfe, 0xf6, 0x68, 0x78, 0x4b, 0x14, 0x33, 0xcf, 0xf1, 0x15, 0x4a,
+ 0x24, 0xb1, 0xc2, 0xe8, 0x62, 0xc5, 0xfc, 0xcd, 0xef, 0x67, 0xd6, 0x2f,
+ 0xff, 0x61, 0xc9, 0x8d, 0x2c, 0x01, 0x81, 0x46, 0xcb, 0x14, 0x6a, 0x25,
+ 0x74, 0x2e, 0x45, 0xb7, 0xff, 0x13, 0x75, 0xc3, 0xb7, 0xb8, 0x28, 0x2c,
+ 0x5f, 0xfb, 0x1f, 0xb6, 0x17, 0x50, 0xcf, 0x2c, 0x5f, 0xe0, 0xa4, 0x26,
+ 0x2e, 0xbc, 0xb1, 0x7e, 0xd7, 0xbf, 0x9b, 0x2c, 0x5b, 0xcb, 0x15, 0x27,
+ 0xe5, 0x86, 0xdf, 0x2a, 0xbf, 0xbc, 0xe7, 0xea, 0x1c, 0x58, 0xb4, 0x64,
+ 0xaf, 0x52, 0x40, 0x93, 0x23, 0x27, 0x35, 0x2b, 0xa4, 0x37, 0x29, 0xd3,
+ 0xc1, 0xde, 0xbf, 0x09, 0x06, 0x20, 0x00, 0xc1, 0x42, 0xbb, 0x90, 0xb6,
+ 0xf1, 0x80, 0x48, 0xc1, 0xc2, 0xcb, 0xb8, 0xb6, 0xf6, 0x9f, 0x4b, 0x17,
+ 0xf9, 0xcc, 0xf7, 0xde, 0x40, 0xb1, 0x68, 0xc9, 0x3d, 0x1f, 0x0e, 0xd4,
+ 0x63, 0x22, 0x17, 0x53, 0xdf, 0x80, 0x8d, 0x7e, 0xa5, 0x94, 0xa2, 0xf4,
+ 0xa0, 0xcb, 0xf6, 0xb7, 0x66, 0xdd, 0x52, 0x6a, 0x97, 0xed, 0x6e, 0xcd,
+ 0xba, 0xa4, 0x82, 0x2e, 0xdb, 0xeb, 0x17, 0xfc, 0x53, 0xee, 0x45, 0x07,
+ 0x89, 0x62, 0xf3, 0x42, 0x33, 0x11, 0x16, 0x03, 0x7f, 0x0c, 0xdf, 0xa4,
+ 0x28, 0xec, 0xd2, 0xc5, 0xa3, 0x31, 0x33, 0x13, 0xc3, 0x08, 0x34, 0x3b,
+ 0xef, 0x69, 0xbe, 0xb1, 0x7f, 0x7d, 0xf6, 0xd8, 0x5c, 0x58, 0xbe, 0x86,
+ 0x7b, 0x75, 0x8b, 0xdb, 0xe9, 0xd6, 0x2f, 0xb2, 0x27, 0x3a, 0xc5, 0xe7,
+ 0x0f, 0xcb, 0x17, 0xfe, 0x11, 0x7b, 0xf9, 0xdc, 0xe0, 0xc5, 0x8b, 0xfd,
+ 0xbb, 0xf3, 0x07, 0xb7, 0x4b, 0x17, 0xda, 0x9f, 0x71, 0x62, 0xf1, 0x66,
+ 0xcb, 0x17, 0xf7, 0xf2, 0x0e, 0x0c, 0x58, 0xb6, 0x0c, 0xfb, 0x77, 0x23,
+ 0xf0, 0xed, 0xfd, 0x27, 0x6e, 0xbd, 0x05, 0x8b, 0xfd, 0x9f, 0xe6, 0x89,
+ 0xf7, 0x58, 0xac, 0x54, 0xa9, 0xb9, 0x1f, 0x46, 0x2e, 0x49, 0x10, 0xf6,
+ 0x88, 0xce, 0x3d, 0xf4, 0x12, 0x85, 0x27, 0x0d, 0x7c, 0x5f, 0x7a, 0x29,
+ 0xd9, 0x62, 0xf9, 0xfe, 0xdc, 0x58, 0xbf, 0xf6, 0x19, 0xe8, 0x67, 0xfe,
+ 0xd0, 0x58, 0xbd, 0xf7, 0xf2, 0xc5, 0xda, 0xf2, 0xc5, 0xfd, 0x91, 0x71,
+ 0xfa, 0x09, 0x62, 0xff, 0x3c, 0x74, 0xfb, 0xed, 0x12, 0xc5, 0xec, 0xfc,
+ 0x64, 0xa6, 0x3d, 0x01, 0xf1, 0x91, 0x44, 0x80, 0xc3, 0xa4, 0x31, 0xc3,
+ 0x1b, 0x98, 0x28, 0xc5, 0x46, 0x9e, 0x8e, 0xf6, 0xfe, 0xef, 0xaf, 0x79,
+ 0xe8, 0xec, 0xfa, 0xc5, 0xfc, 0x40, 0x98, 0xf6, 0x3a, 0xc5, 0xfe, 0x36,
+ 0x18, 0xff, 0x68, 0x96, 0x2a, 0x4f, 0x95, 0xcc, 0x2f, 0xdf, 0xcd, 0xe4,
+ 0xeb, 0x17, 0xa4, 0xa2, 0x58, 0xbf, 0xfd, 0x14, 0xf6, 0x6d, 0x73, 0x8f,
+ 0xac, 0x35, 0x62, 0xf3, 0x66, 0x96, 0x2f, 0xf3, 0xc5, 0x3d, 0x9b, 0x5c,
+ 0x58, 0xb7, 0x16, 0x2a, 0x4f, 0x20, 0x8d, 0xaf, 0xfe, 0x90, 0x0b, 0xdc,
+ 0x29, 0xee, 0x9d, 0x96, 0x2e, 0xd4, 0xac, 0x54, 0x13, 0x97, 0x19, 0x06,
+ 0xe5, 0x2e, 0x3b, 0xa4, 0xef, 0xb2, 0x76, 0x20, 0xee, 0x48, 0xbd, 0xf6,
+ 0xe2, 0xc5, 0xcf, 0xc5, 0x8b, 0xf3, 0x90, 0xa7, 0x4b, 0x14, 0xe7, 0xb7,
+ 0xe1, 0xd1, 0x0b, 0xdf, 0xec, 0xed, 0xee, 0x16, 0x41, 0x62, 0xfe, 0xed,
+ 0xee, 0x16, 0x41, 0x62, 0xfd, 0xfc, 0x26, 0x88, 0xc3, 0xe5, 0xc3, 0x5b,
+ 0xcc, 0xdb, 0xaa, 0x4e, 0x22, 0xff, 0x9f, 0xb7, 0xf7, 0x7e, 0x60, 0xd6,
+ 0x2b, 0x73, 0xe6, 0xd1, 0x55, 0xff, 0x31, 0xf8, 0xf9, 0xd9, 0xb4, 0xb1,
+ 0x7f, 0x09, 0xba, 0x1e, 0x69, 0x62, 0x9d, 0x33, 0x0d, 0x42, 0x90, 0x88,
+ 0xf8, 0x75, 0x7f, 0xff, 0xbe, 0xe3, 0x29, 0x6d, 0x82, 0x6f, 0xf0, 0xce,
+ 0x4f, 0x16, 0x2f, 0xff, 0xd0, 0x0f, 0xf0, 0x6f, 0x30, 0x04, 0x4d, 0xd8,
+ 0x6b, 0x17, 0x07, 0x12, 0xc5, 0xff, 0x73, 0x1c, 0x01, 0xf9, 0xbe, 0xb1,
+ 0x7c, 0xd1, 0x39, 0xd6, 0x2f, 0xee, 0xb7, 0x7e, 0x7d, 0xd6, 0x2b, 0x64,
+ 0x53, 0xfc, 0x68, 0x8e, 0xbc, 0x47, 0x7f, 0xfd, 0x09, 0xf0, 0x0c, 0xcf,
+ 0xeb, 0x00, 0x28, 0x96, 0x2c, 0x6a, 0xc5, 0xd1, 0x3a, 0xc5, 0x61, 0xab,
+ 0x61, 0x3b, 0xfd, 0xdb, 0x3d, 0xce, 0xd3, 0xf5, 0x8a, 0x81, 0xeb, 0xfc,
+ 0x7e, 0xff, 0x7e, 0x41, 0xcc, 0x20, 0x2c, 0x56, 0x26, 0x54, 0xf0, 0xd5,
+ 0x62, 0x2b, 0xfc, 0x5e, 0x86, 0x13, 0x8d, 0x62, 0xff, 0x89, 0x81, 0xcf,
+ 0xc9, 0x79, 0x62, 0xb0, 0xfa, 0xbc, 0x65, 0x7e, 0xc3, 0xbf, 0x70, 0xd6,
+ 0x2e, 0x93, 0xac, 0x54, 0x9f, 0x1c, 0x79, 0x0e, 0x8a, 0xef, 0xe1, 0x13,
+ 0x1b, 0x00, 0x2c, 0x5b, 0xa5, 0x8b, 0xd1, 0xd9, 0xf5, 0x8b, 0x6f, 0x86,
+ 0xcf, 0xc2, 0x77, 0xbb, 0x9f, 0x65, 0x8a, 0xc3, 0xc8, 0x62, 0x7b, 0xf7,
+ 0xc4, 0x6e, 0x12, 0xc5, 0xf9, 0xb5, 0xe2, 0x95, 0x8b, 0xbc, 0xeb, 0x17,
+ 0x07, 0xb2, 0xc5, 0x40, 0xd8, 0x90, 0xbd, 0xf8, 0x79, 0x1f, 0x3f, 0x58,
+ 0xbf, 0x6f, 0x3f, 0x7e, 0xcb, 0x17, 0xbb, 0x9f, 0x75, 0x8a, 0x1a, 0x63,
+ 0x1b, 0x94, 0xc4, 0xb1, 0xa2, 0x02, 0x2b, 0xee, 0x2b, 0xbf, 0xc7, 0x68,
+ 0x71, 0xc7, 0x8b, 0x17, 0x8d, 0x9e, 0x2c, 0x5f, 0xd3, 0x13, 0x7e, 0x63,
+ 0xd6, 0x2f, 0xff, 0x40, 0x4d, 0xd8, 0x3f, 0xf0, 0x51, 0xc2, 0xd2, 0xc5,
+ 0xfe, 0x04, 0x81, 0x88, 0x58, 0xb1, 0x50, 0x45, 0xb7, 0x46, 0x2e, 0xa7,
+ 0x7f, 0x07, 0xda, 0x7e, 0xdd, 0x96, 0x2f, 0xdd, 0xa7, 0xed, 0xd9, 0x62,
+ 0xf4, 0x42, 0x81, 0x87, 0xbe, 0x19, 0x9d, 0x4a, 0x73, 0x59, 0x0d, 0x46,
+ 0x84, 0x7d, 0xfc, 0x28, 0xf6, 0xf0, 0xa5, 0x62, 0x96, 0x2e, 0x9d, 0x96,
+ 0x2b, 0xa3, 0xd5, 0xe1, 0x8f, 0x70, 0x65, 0xff, 0x67, 0xfc, 0x52, 0x03,
+ 0x1d, 0x62, 0xfc, 0x5e, 0x26, 0x35, 0x62, 0x96, 0x2b, 0x0d, 0xa4, 0x71,
+ 0x45, 0x32, 0x30, 0xc8, 0xcf, 0x8d, 0xb7, 0xf1, 0xdb, 0xb4, 0xeb, 0xb9,
+ 0x62, 0xff, 0xce, 0x3c, 0xec, 0x7c, 0x87, 0x50, 0x58, 0xbf, 0x37, 0x18,
+ 0x80, 0xb1, 0x7f, 0x3f, 0x68, 0x1e, 0x62, 0x58, 0xbf, 0xf4, 0xe1, 0x1e,
+ 0x7f, 0xdc, 0xdd, 0xcb, 0x15, 0x03, 0xf4, 0xd1, 0x8d, 0xff, 0x61, 0xf3,
+ 0x59, 0xb6, 0x04, 0xb1, 0x7f, 0xfb, 0xf3, 0xdb, 0xdc, 0x7f, 0x7f, 0x3b,
+ 0xb8, 0xb1, 0x52, 0x9d, 0xe6, 0x19, 0x9a, 0x84, 0xf0, 0x9b, 0xf9, 0x10,
+ 0x0e, 0xa9, 0x62, 0xfe, 0xd9, 0xb3, 0xd8, 0x75, 0x8a, 0x8d, 0xcd, 0xd3,
+ 0x06, 0x5f, 0x86, 0xc5, 0x9d, 0xcb, 0x17, 0xff, 0xb0, 0xbc, 0xc0, 0x33,
+ 0xc4, 0xc0, 0xe2, 0xc5, 0xfd, 0x9a, 0x6f, 0x0a, 0x56, 0x2f, 0xff, 0x98,
+ 0xa5, 0xfb, 0xb8, 0xfc, 0xcf, 0xe4, 0x72, 0xc5, 0x0d, 0x10, 0x1d, 0x8b,
+ 0x6f, 0xff, 0xe7, 0x1b, 0x74, 0x66, 0x3c, 0x24, 0xa7, 0xb7, 0x99, 0x62,
+ 0xff, 0xe7, 0x21, 0x43, 0x39, 0xc7, 0x1e, 0x2c, 0x54, 0xa7, 0x71, 0xb1,
+ 0x54, 0x50, 0xca, 0xf9, 0x2f, 0x97, 0x2d, 0x19, 0xdf, 0x1b, 0x31, 0x49,
+ 0x94, 0x77, 0x08, 0x69, 0x64, 0x78, 0x7b, 0xa0, 0xf4, 0xc6, 0xf1, 0x80,
+ 0x45, 0x1b, 0x3e, 0xa3, 0x00, 0x39, 0x8f, 0xe1, 0x54, 0xd1, 0x9c, 0x01,
+ 0x70, 0xa3, 0xcd, 0xe4, 0x6a, 0x1e, 0x8f, 0xaa, 0x3a, 0x12, 0xa1, 0xc7,
+ 0xbb, 0x7f, 0x77, 0x9d, 0xe6, 0x99, 0xa0, 0xb1, 0x7f, 0xa3, 0x72, 0x8d,
+ 0x3d, 0x1d, 0x1a, 0x0d, 0x62, 0xfa, 0x19, 0x1c, 0xeb, 0x17, 0xfb, 0xbc,
+ 0xc1, 0x07, 0xf9, 0x35, 0x62, 0xe6, 0xef, 0x56, 0x2f, 0xe2, 0xfe, 0x74,
+ 0x2d, 0xd6, 0x2b, 0xbd, 0x44, 0x39, 0x1d, 0x86, 0x39, 0x7e, 0xef, 0xbe,
+ 0xf4, 0x72, 0x35, 0x8b, 0xff, 0xfe, 0x8d, 0xfb, 0xef, 0xf2, 0xe3, 0x29,
+ 0x16, 0xe1, 0x30, 0xe7, 0xae, 0x2c, 0x5f, 0x77, 0xd8, 0x0d, 0x95, 0x8b,
+ 0x8b, 0xa5, 0x8b, 0xec, 0x0e, 0x74, 0xb1, 0x51, 0xb1, 0xf3, 0x46, 0xb2,
+ 0xb2, 0x18, 0xbf, 0xf3, 0xf5, 0x1a, 0xb9, 0xa3, 0x0c, 0xfc, 0x72, 0xc5,
+ 0xf1, 0x86, 0x7e, 0x39, 0x62, 0xf8, 0xc3, 0x3f, 0x1c, 0xb1, 0x7a, 0x7d,
+ 0xba, 0xc5, 0x47, 0x9f, 0x84, 0x45, 0x3f, 0x29, 0xae, 0xfa, 0xa3, 0xc0,
+ 0x70, 0xbd, 0xbe, 0xd1, 0xfd, 0xd2, 0xc5, 0xfb, 0xc0, 0x0c, 0xa0, 0xb1,
+ 0x74, 0xe8, 0xc3, 0xcf, 0x62, 0x5b, 0xff, 0x8d, 0x0a, 0x3f, 0x61, 0xc6,
+ 0xc6, 0x19, 0xf8, 0xe5, 0x8b, 0xe1, 0x6d, 0xa9, 0x58, 0xbe, 0x9c, 0xd4,
+ 0x16, 0x2a, 0x35, 0x22, 0x79, 0xd6, 0x08, 0x92, 0xe1, 0xba, 0xc5, 0xef,
+ 0x41, 0x96, 0x2f, 0x73, 0xa7, 0x58, 0xbc, 0xdd, 0xb1, 0x62, 0xb6, 0x37,
+ 0x9c, 0x1e, 0xa7, 0x44, 0x93, 0x0b, 0xf1, 0x66, 0xf9, 0xcb, 0xdc, 0x58,
+ 0xbe, 0xdd, 0x9b, 0x75, 0x49, 0xd2, 0x5f, 0x88, 0x5e, 0x9e, 0x2c, 0x5f,
+ 0xff, 0xd2, 0x17, 0x8d, 0x6e, 0x19, 0x2e, 0x59, 0xd7, 0xb1, 0x62, 0xfd,
+ 0xc9, 0x04, 0x6f, 0xf5, 0x8a, 0x35, 0x30, 0x6d, 0x11, 0x7c, 0xc4, 0x8a,
+ 0x3c, 0xbb, 0x7f, 0xc6, 0x8b, 0xdc, 0x33, 0xcf, 0xba, 0xc5, 0xf0, 0x7f,
+ 0x9d, 0x2c, 0x5e, 0x14, 0x0e, 0xb1, 0x52, 0x78, 0x4c, 0x49, 0x7e, 0x0e,
+ 0x0e, 0x0e, 0x2c, 0x5f, 0xbd, 0xc9, 0xcd, 0x96, 0x28, 0x67, 0xa7, 0xa2,
+ 0xab, 0xec, 0xd8, 0xfe, 0x58, 0xaf, 0xa2, 0xe5, 0x9c, 0xc8, 0x8a, 0xf8,
+ 0x98, 0x72, 0xb1, 0x70, 0x46, 0xac, 0x5f, 0xe9, 0xec, 0xc5, 0x3d, 0xb8,
+ 0xb1, 0x7f, 0x7e, 0x43, 0xf8, 0xb8, 0xb1, 0x52, 0x8a, 0x1c, 0x21, 0xf8,
+ 0xd7, 0x71, 0xb5, 0xff, 0xb9, 0xc8, 0xa1, 0xdf, 0x98, 0x67, 0xe3, 0x96,
+ 0x2f, 0x42, 0x4e, 0xb1, 0x51, 0xb9, 0xf5, 0x0d, 0x36, 0xfe, 0x84, 0xf4,
+ 0xdc, 0x82, 0xc5, 0xff, 0xff, 0xbc, 0x4c, 0x0e, 0x6f, 0xf7, 0x88, 0xb0,
+ 0x2f, 0xe1, 0xe7, 0x8b, 0x17, 0xfa, 0x2d, 0x4f, 0x50, 0x73, 0xac, 0x54,
+ 0xa2, 0x90, 0x9b, 0xaf, 0xfd, 0xda, 0x4b, 0xdc, 0x17, 0xb3, 0x4b, 0x17,
+ 0xfe, 0x68, 0xbd, 0xc7, 0xd7, 0x4d, 0x12, 0xc5, 0xff, 0xff, 0xe7, 0x33,
+ 0xbe, 0xb1, 0xbf, 0x7d, 0xfe, 0x5c, 0x65, 0x22, 0xdc, 0x26, 0x1c, 0xf5,
+ 0xc5, 0x8a, 0x94, 0xcc, 0xf0, 0x85, 0x90, 0x49, 0x0a, 0xfa, 0x1d, 0xd9,
+ 0xe5, 0x8b, 0xfc, 0xff, 0x62, 0x18, 0x7d, 0x2c, 0x5f, 0x72, 0x7b, 0xb8,
+ 0xb1, 0x52, 0x88, 0x11, 0x13, 0x77, 0x1a, 0xdd, 0xee, 0xe5, 0x8b, 0x7d,
+ 0x62, 0xff, 0xde, 0x98, 0xb8, 0x58, 0x3f, 0x89, 0x62, 0x9c, 0xf4, 0xbc,
+ 0x25, 0x7e, 0x34, 0xd0, 0xcb, 0x75, 0x8b, 0xff, 0xfc, 0xfe, 0x7f, 0x60,
+ 0x0c, 0x9e, 0xb9, 0x21, 0x8b, 0xee, 0xb1, 0x52, 0x98, 0xf6, 0x36, 0xb9,
+ 0x0b, 0x16, 0xdf, 0x6e, 0x77, 0x8f, 0x58, 0xb9, 0x86, 0xb1, 0x7e, 0x83,
+ 0xcc, 0x23, 0xd6, 0x28, 0xc3, 0xc2, 0xc1, 0x7b, 0xc3, 0xc1, 0xac, 0x5d,
+ 0xad, 0x96, 0x2a, 0x51, 0x82, 0x36, 0x9c, 0x22, 0x71, 0xdb, 0xc2, 0x90,
+ 0xd6, 0x2f, 0xff, 0xfe, 0xfe, 0x76, 0xd6, 0x73, 0x35, 0xbc, 0xe7, 0x8b,
+ 0x39, 0xcc, 0x1a, 0xc5, 0xfe, 0xda, 0x4b, 0x71, 0x87, 0xc5, 0x8b, 0xe7,
+ 0x37, 0x06, 0xb1, 0x7f, 0xf0, 0x1c, 0x83, 0x35, 0xfc, 0xc0, 0xe2, 0xc5,
+ 0xff, 0x3e, 0x17, 0xf3, 0xd2, 0x35, 0x8b, 0xff, 0x39, 0x6a, 0x7c, 0xfb,
+ 0xb8, 0xd6, 0x2b, 0x64, 0xc5, 0x74, 0x6e, 0x02, 0x3f, 0x23, 0x76, 0x37,
+ 0xbc, 0x23, 0x40, 0xb1, 0x7f, 0x4f, 0xb8, 0x2d, 0xfb, 0xf5, 0x8a, 0x19,
+ 0xea, 0x76, 0x1f, 0xbe, 0xdf, 0xf2, 0x12, 0xc5, 0x4a, 0xa7, 0x3c, 0x8e,
+ 0x21, 0xa1, 0x45, 0xdf, 0x92, 0x5f, 0xf7, 0xdc, 0x2f, 0x75, 0xbb, 0xfd,
+ 0x62, 0xf4, 0x4e, 0x75, 0x8b, 0xbb, 0xfe, 0xe5, 0x8b, 0xf0, 0x81, 0x11,
+ 0x79, 0x62, 0xfb, 0x59, 0xd4, 0xac, 0x5f, 0xdf, 0x7f, 0x41, 0xbe, 0xb1,
+ 0x43, 0x47, 0xb6, 0x1e, 0xc7, 0x8f, 0x68, 0x81, 0x8a, 0x84, 0x47, 0x7f,
+ 0xa2, 0x83, 0x6b, 0x6f, 0x89, 0x62, 0xf4, 0x05, 0xb2, 0xc5, 0xf3, 0x90,
+ 0xe5, 0x62, 0xa2, 0x3c, 0x0f, 0x8f, 0xdc, 0xc1, 0xac, 0x5f, 0xfb, 0xc6,
+ 0x71, 0x8b, 0x7f, 0xbe, 0x96, 0x2b, 0x63, 0xd9, 0xc1, 0x8a, 0x94, 0xc5,
+ 0x71, 0xdf, 0x8f, 0x97, 0xb4, 0xfd, 0x2c, 0x5f, 0xe9, 0xf3, 0x6c, 0x27,
+ 0x82, 0xc5, 0xfd, 0xf7, 0x69, 0xf6, 0x2c, 0x5c, 0x1f, 0xd6, 0x2e, 0x10,
+ 0x6b, 0x15, 0xf4, 0x58, 0x10, 0xf0, 0x46, 0x81, 0x96, 0x77, 0x0c, 0xdf,
+ 0xff, 0x9a, 0x05, 0x3c, 0xce, 0xb7, 0x26, 0xce, 0xb7, 0x58, 0xbf, 0xfe,
+ 0x62, 0x6d, 0x8a, 0x7a, 0x71, 0x94, 0xec, 0xb1, 0x7f, 0xcf, 0xfc, 0xe8,
+ 0x10, 0x1e, 0x2c, 0x5f, 0xde, 0xcf, 0x87, 0x17, 0x16, 0x2d, 0x19, 0x1b,
+ 0xb6, 0xd8, 0x7d, 0xe1, 0xc7, 0x7a, 0x8f, 0x1a, 0x42, 0xb3, 0xbe, 0x1a,
+ 0xf7, 0xd4, 0xd6, 0x35, 0x43, 0x6e, 0x63, 0x29, 0xd9, 0xfe, 0x10, 0xcb,
+ 0x1c, 0x31, 0xb2, 0x33, 0x43, 0x52, 0xf7, 0x8c, 0xe5, 0xe1, 0x9f, 0x1f,
+ 0x0a, 0x88, 0x89, 0xf5, 0x28, 0x18, 0xf0, 0xbb, 0xfc, 0x6a, 0x0d, 0x0f,
+ 0xb0, 0x1d, 0x14, 0xa9, 0x1e, 0x46, 0x85, 0xe8, 0xdb, 0x45, 0x0d, 0xfe,
+ 0xc9, 0xc1, 0x2b, 0xc7, 0x27, 0xf7, 0x1d, 0x5f, 0xa3, 0x7e, 0xf3, 0xae,
+ 0x1d, 0x62, 0xe9, 0x8e, 0x58, 0xbf, 0xd0, 0x7f, 0x72, 0x75, 0x8b, 0x17,
+ 0xff, 0x8b, 0xce, 0x7f, 0xcb, 0x93, 0x68, 0xd5, 0x8b, 0xf9, 0xbd, 0x27,
+ 0x92, 0x58, 0xbd, 0xd8, 0x50, 0x58, 0xac, 0x44, 0xae, 0x92, 0x7b, 0x16,
+ 0x5f, 0xfc, 0x69, 0xb2, 0x5e, 0xf1, 0x4f, 0xb8, 0xb1, 0x7f, 0xdc, 0x17,
+ 0xa0, 0xfd, 0xbe, 0xeb, 0x14, 0xe8, 0x82, 0x3a, 0x35, 0xfb, 0x39, 0xbf,
+ 0xa5, 0x62, 0xfe, 0x8b, 0x98, 0x79, 0x8f, 0x58, 0xac, 0x3d, 0xbf, 0x94,
+ 0xdf, 0xbd, 0x9e, 0x9e, 0x96, 0x2f, 0xed, 0xa7, 0xcc, 0x68, 0x96, 0x29,
+ 0x73, 0x8b, 0x97, 0xf8, 0xb3, 0x3a, 0xde, 0x76, 0x58, 0xbf, 0xfa, 0x74,
+ 0x03, 0x39, 0xf9, 0x3b, 0x12, 0xc5, 0xff, 0x0b, 0xcf, 0xf7, 0x37, 0xee,
+ 0xb1, 0x7f, 0x48, 0x33, 0xb4, 0x8d, 0x62, 0xff, 0xed, 0x73, 0xef, 0x3e,
+ 0xf3, 0x43, 0x8b, 0x17, 0xfa, 0x74, 0x1f, 0xff, 0x80, 0x58, 0xa8, 0x26,
+ 0x50, 0x34, 0x5d, 0xce, 0x9c, 0xbf, 0xe8, 0xb7, 0xf7, 0x1f, 0xc4, 0x28,
+ 0x2c, 0x5e, 0x3c, 0xc7, 0xac, 0x5f, 0x78, 0x85, 0x05, 0x8a, 0xc3, 0xc3,
+ 0x72, 0x0b, 0xef, 0x39, 0xf8, 0x62, 0x24, 0x78, 0xe3, 0x7f, 0x41, 0xa0,
+ 0xc5, 0xba, 0xc5, 0x2c, 0x5a, 0x56, 0x28, 0x65, 0xe9, 0x06, 0x5b, 0x8b,
+ 0x15, 0x26, 0xc7, 0xc3, 0xf7, 0xff, 0xb3, 0xd2, 0x10, 0x7b, 0x73, 0x0f,
+ 0x31, 0xeb, 0x17, 0xf0, 0xca, 0x42, 0x1e, 0x2c, 0x52, 0xc5, 0xf9, 0xb7,
+ 0xdd, 0xc0, 0xb1, 0x47, 0x36, 0xde, 0x0c, 0xbf, 0x9a, 0x1a, 0x70, 0x9d,
+ 0x62, 0xf8, 0xa4, 0x7a, 0x58, 0xbd, 0xbc, 0xec, 0xb1, 0x7f, 0xe7, 0x83,
+ 0xeb, 0xa9, 0x29, 0xe2, 0xc5, 0x6c, 0x7f, 0xfb, 0x91, 0x78, 0x7e, 0xd1,
+ 0x91, 0xba, 0xe6, 0xe4, 0x8c, 0xe4, 0x6b, 0xbd, 0x43, 0x72, 0x23, 0xbf,
+ 0xbe, 0x11, 0x07, 0x14, 0x3c, 0xc9, 0x1c, 0x42, 0x1c, 0x2b, 0x6b, 0xa5,
+ 0xdf, 0x1d, 0x14, 0x9e, 0x74, 0x32, 0xfb, 0x02, 0x8d, 0xce, 0xb1, 0x7f,
+ 0xd8, 0x5b, 0x8d, 0xfb, 0x48, 0xd6, 0x2f, 0xe2, 0x9e, 0x8e, 0xde, 0x58,
+ 0xbf, 0xfc, 0x13, 0x0f, 0xf3, 0xd7, 0xa7, 0xed, 0x1e, 0xb1, 0x67, 0xd1,
+ 0xfe, 0xfc, 0xba, 0xff, 0xff, 0x85, 0xa8, 0x73, 0xec, 0xfa, 0xd6, 0x85,
+ 0xd3, 0xe9, 0xb8, 0xb1, 0x7e, 0xc0, 0xb9, 0x9f, 0x58, 0xbf, 0xf6, 0xf3,
+ 0x9f, 0x9f, 0x14, 0xf9, 0x62, 0xfe, 0x62, 0xfc, 0xea, 0x0b, 0x15, 0xa3,
+ 0xeb, 0xe1, 0xf5, 0xe9, 0x28, 0x96, 0x2f, 0xda, 0xe7, 0x18, 0x96, 0x2b,
+ 0xe7, 0x8a, 0x21, 0xdb, 0xff, 0xe2, 0x17, 0x50, 0x88, 0x9e, 0x2f, 0x3f,
+ 0x41, 0x2c, 0x5e, 0x17, 0xf8, 0xb1, 0x7f, 0xe6, 0x37, 0x7f, 0xbc, 0x5a,
+ 0x90, 0x96, 0x2f, 0x4e, 0x75, 0xb9, 0xf0, 0x90, 0xf5, 0xff, 0xcc, 0x7e,
+ 0x78, 0x98, 0x1d, 0x7a, 0x35, 0x2c, 0x56, 0x8f, 0xfc, 0x46, 0x75, 0x04,
+ 0xd5, 0xfd, 0x19, 0xad, 0xff, 0x89, 0x82, 0xf6, 0x7d, 0xa2, 0x65, 0x8b,
+ 0xff, 0xf0, 0x01, 0x26, 0x7e, 0x7c, 0x2d, 0xff, 0x24, 0xcb, 0x17, 0xff,
+ 0xe2, 0x13, 0x47, 0xe4, 0x3f, 0x86, 0xe0, 0xe2, 0x12, 0xc5, 0x62, 0x2c,
+ 0x7e, 0xaf, 0x76, 0xf8, 0xb1, 0x7f, 0x4c, 0x1f, 0xaf, 0x62, 0xc5, 0xff,
+ 0xf3, 0x75, 0x0e, 0x75, 0xe2, 0x6f, 0xe7, 0x5e, 0x58, 0xa9, 0x45, 0xd9,
+ 0xa4, 0x5a, 0x18, 0x62, 0xeb, 0xfe, 0x11, 0x31, 0xa6, 0x1f, 0xae, 0x2c,
+ 0x5f, 0x6b, 0x8f, 0xa5, 0x8b, 0xfd, 0x82, 0xef, 0xf7, 0xfb, 0xc4, 0xb1,
+ 0x7f, 0x84, 0x6e, 0x7d, 0xbd, 0xc5, 0x8b, 0xff, 0xff, 0x9e, 0x0d, 0xce,
+ 0x4f, 0x33, 0xee, 0x52, 0x7d, 0x48, 0x6c, 0x4b, 0x17, 0xff, 0xff, 0x67,
+ 0x03, 0xf3, 0xf6, 0x7f, 0x42, 0x7e, 0xf3, 0xef, 0x89, 0x8e, 0xb1, 0x52,
+ 0x8e, 0x38, 0x37, 0xd7, 0x13, 0x3a, 0xf4, 0x63, 0x17, 0xee, 0x4f, 0xc3,
+ 0x89, 0x62, 0x9c, 0xf5, 0x7c, 0x55, 0x52, 0xa8, 0x3b, 0x08, 0xda, 0x3c,
+ 0xab, 0xd0, 0x93, 0xac, 0x5f, 0x40, 0xb3, 0xeb, 0x14, 0xb1, 0x7f, 0x60,
+ 0xf5, 0x8f, 0x12, 0xc5, 0xfe, 0xd8, 0xb3, 0xaf, 0x60, 0x4b, 0x17, 0xee,
+ 0xbd, 0x38, 0x11, 0x1f, 0x20, 0x65, 0xd5, 0x1a, 0x22, 0xc3, 0x1c, 0x2f,
+ 0xe3, 0xbf, 0xb8, 0x2d, 0x96, 0x2e, 0xe4, 0x16, 0x2f, 0xff, 0xb0, 0x62,
+ 0xf7, 0x37, 0xfb, 0xf0, 0x4d, 0xd2, 0xc5, 0xff, 0xff, 0xf8, 0x98, 0xdc,
+ 0xd0, 0x27, 0xdc, 0x1f, 0xe7, 0x83, 0x26, 0x37, 0x59, 0xd7, 0x16, 0x2f,
+ 0xf8, 0x85, 0xb7, 0xb9, 0x84, 0x05, 0x8b, 0xcd, 0x0e, 0x0d, 0x17, 0xe1,
+ 0xc2, 0x16, 0xbe, 0x9a, 0x60, 0xa3, 0x12, 0xac, 0x4e, 0xf8, 0xd3, 0x0f,
+ 0x46, 0xc9, 0x7f, 0x31, 0x00, 0x9b, 0xcb, 0x17, 0xf6, 0x9a, 0x1b, 0x60,
+ 0x4b, 0x15, 0x1e, 0x7b, 0x9a, 0x2c, 0xa5, 0x8b, 0xa2, 0x12, 0xc5, 0x61,
+ 0xe5, 0x7c, 0x94, 0x20, 0xcb, 0xfe, 0xf8, 0x7e, 0x7d, 0x3e, 0xd2, 0xb1,
+ 0x7f, 0xff, 0x0a, 0x04, 0xf0, 0x2c, 0xf7, 0x26, 0x03, 0x9f, 0x2c, 0x5f,
+ 0xfa, 0x7a, 0xdf, 0xef, 0xad, 0x34, 0x16, 0x2f, 0xf6, 0xc5, 0x9d, 0x7b,
+ 0x02, 0x58, 0xbf, 0x86, 0xdd, 0x7b, 0x0e, 0x73, 0xf7, 0x0d, 0x06, 0xfb,
+ 0x52, 0x17, 0x16, 0x2f, 0x7f, 0x22, 0x58, 0xbf, 0xfc, 0x5e, 0xe6, 0x39,
+ 0xf0, 0x73, 0x09, 0xc3, 0xc2, 0xf1, 0x25, 0x3a, 0x39, 0x45, 0x08, 0x8a,
+ 0x82, 0xa4, 0x7c, 0x2f, 0x73, 0xbe, 0x47, 0x6d, 0x7f, 0xf6, 0x0e, 0x61,
+ 0x3a, 0x90, 0xd8, 0x96, 0x2f, 0xfd, 0xdb, 0x20, 0x71, 0xbf, 0x69, 0x1a,
+ 0xc5, 0xff, 0xf3, 0xfc, 0x47, 0x3b, 0x43, 0xec, 0x77, 0xe2, 0xc5, 0x1d,
+ 0x1a, 0xcc, 0x87, 0xe4, 0x3b, 0x9a, 0x33, 0x66, 0x75, 0x74, 0x1a, 0x72,
+ 0x12, 0x9b, 0xb3, 0xf5, 0x1b, 0xcc, 0x45, 0x5a, 0x8e, 0xac, 0xe7, 0x9f,
+ 0x94, 0x96, 0xc6, 0xa0, 0x1d, 0x28, 0x69, 0x72, 0x3e, 0x5f, 0x4b, 0x24,
+ 0x0e, 0x31, 0x9a, 0x76, 0xc2, 0x77, 0xf0, 0xb8, 0x2a, 0x76, 0xad, 0xfd,
+ 0xc7, 0xf1, 0x0a, 0x0b, 0x17, 0xe7, 0xf1, 0x0a, 0x0b, 0x17, 0x1f, 0x86,
+ 0x1e, 0xb7, 0x0b, 0xaf, 0xe9, 0xc0, 0x66, 0x0d, 0x62, 0xde, 0x73, 0xdb,
+ 0x22, 0xfb, 0xf7, 0x0f, 0x25, 0x12, 0xc5, 0xfc, 0x5e, 0x3c, 0xe7, 0x96,
+ 0x2f, 0xde, 0xfc, 0x86, 0x4b, 0x16, 0x84, 0x9e, 0xb6, 0x16, 0xdf, 0xfb,
+ 0xcf, 0xbb, 0x8d, 0x88, 0xd9, 0x58, 0xbc, 0x37, 0x35, 0x62, 0xff, 0xa7,
+ 0xaf, 0xb7, 0x3d, 0x21, 0x2c, 0x54, 0xa2, 0x63, 0x0f, 0xf4, 0x3d, 0x7f,
+ 0xff, 0x3c, 0x1f, 0xd2, 0x7c, 0xeb, 0xd2, 0x7c, 0xeb, 0xcb, 0x9c, 0x60,
+ 0xbf, 0xec, 0x17, 0x7e, 0xf1, 0x3e, 0x12, 0xc5, 0xff, 0xb7, 0x21, 0x7b,
+ 0x9a, 0x7e, 0x80, 0xb1, 0x7e, 0x21, 0x6d, 0xd4, 0x7a, 0xc5, 0x61, 0xf8,
+ 0x79, 0x0a, 0xa5, 0x33, 0x7c, 0x69, 0x68, 0x56, 0xdb, 0xbd, 0x58, 0xb8,
+ 0x5f, 0x58, 0xbf, 0x16, 0x7d, 0xbc, 0xb1, 0x7f, 0x41, 0xb3, 0xb4, 0x8d,
+ 0x62, 0xbb, 0xd3, 0xd6, 0xef, 0x84, 0xf7, 0xe8, 0xdb, 0xbd, 0xd7, 0x38,
+ 0xb1, 0x7c, 0xe2, 0x84, 0xac, 0x5f, 0x67, 0x52, 0x75, 0x8b, 0xe7, 0x29,
+ 0x02, 0xc5, 0xff, 0xf0, 0xf0, 0xfc, 0x13, 0x3c, 0x1f, 0x58, 0x35, 0x8b,
+ 0xff, 0xff, 0x69, 0xfb, 0x48, 0xdc, 0x9b, 0x46, 0x99, 0xf6, 0xe0, 0x52,
+ 0x35, 0x8b, 0xfd, 0xf9, 0xdb, 0x53, 0x83, 0x58, 0xbf, 0x4f, 0x66, 0xcd,
+ 0x2c, 0x5d, 0x9b, 0x2c, 0x5c, 0x39, 0x58, 0xa0, 0xcd, 0x7f, 0x70, 0xc5,
+ 0x4a, 0x2c, 0x7e, 0x68, 0x25, 0x8b, 0xf3, 0x45, 0x07, 0xf2, 0xc5, 0xe1,
+ 0xb4, 0x16, 0x2f, 0xee, 0xe7, 0xed, 0xec, 0xfa, 0xc5, 0x61, 0xe8, 0x08,
+ 0x76, 0xfe, 0xcf, 0x39, 0xdf, 0x4b, 0x17, 0xf4, 0xc1, 0xfa, 0xf6, 0x2c,
+ 0x58, 0x63, 0x3d, 0xbd, 0x16, 0xdf, 0xff, 0xb6, 0xc8, 0x10, 0x9b, 0x9e,
+ 0xc8, 0xa0, 0xfe, 0x58, 0xbe, 0xc2, 0x98, 0x2c, 0x54, 0xa2, 0x83, 0x0a,
+ 0x3c, 0xaf, 0x7f, 0xfb, 0xf3, 0x01, 0xfe, 0x7a, 0xf3, 0x9f, 0x8b, 0x17,
+ 0x0a, 0x0b, 0x14, 0xc7, 0xc9, 0xd9, 0x32, 0xe3, 0xca, 0xc5, 0xa5, 0x62,
+ 0xb0, 0xd4, 0x68, 0x5e, 0xa0, 0xb9, 0x2e, 0x69, 0x16, 0xe4, 0x6e, 0x43,
+ 0xa4, 0xff, 0xc6, 0x42, 0x02, 0xf2, 0x79, 0xf4, 0x63, 0x9d, 0xa1, 0x25,
+ 0xdc, 0x97, 0x7f, 0xda, 0xe7, 0xdf, 0x7d, 0xc5, 0xb2, 0xc5, 0xfc, 0x16,
+ 0x76, 0x21, 0x41, 0x62, 0xfe, 0x11, 0xb8, 0x5d, 0xd8, 0xb1, 0x7b, 0xbf,
+ 0x7e, 0x96, 0x2f, 0xff, 0xf7, 0xdc, 0xe7, 0x70, 0xb9, 0xd6, 0xef, 0x9a,
+ 0x1c, 0xf4, 0xb1, 0x7f, 0xfd, 0x30, 0xce, 0x39, 0x00, 0xb3, 0xdf, 0xc5,
+ 0x8b, 0x43, 0x74, 0x59, 0x13, 0x2d, 0x74, 0x8f, 0xed, 0x43, 0x56, 0xa5,
+ 0x3c, 0x7c, 0x3e, 0x23, 0x11, 0x46, 0x5f, 0x7e, 0x7f, 0x14, 0x9d, 0x62,
+ 0xf8, 0xb3, 0xf8, 0xb1, 0x5f, 0x3c, 0x8e, 0x13, 0xdf, 0xff, 0xf4, 0x8f,
+ 0xf9, 0xd7, 0x89, 0xbe, 0x06, 0xe7, 0x1b, 0x5b, 0xac, 0x5e, 0x38, 0xbe,
+ 0xb1, 0x7e, 0x98, 0x99, 0xb4, 0xb1, 0x7f, 0xd3, 0xcf, 0xe7, 0x69, 0xce,
+ 0x96, 0x2d, 0xe9, 0x44, 0x0f, 0x07, 0xbc, 0x51, 0x7d, 0xb4, 0x73, 0x1a,
+ 0xb1, 0x7f, 0xb3, 0x30, 0xd3, 0x5a, 0x0b, 0x15, 0x89, 0xce, 0x1a, 0x44,
+ 0xf0, 0xe9, 0xf9, 0xaf, 0x8a, 0x2f, 0xb9, 0xbf, 0xa5, 0x62, 0xff, 0x9e,
+ 0x74, 0x08, 0xec, 0xed, 0xb2, 0xc5, 0xfe, 0x73, 0xbe, 0xb9, 0x09, 0x58,
+ 0xac, 0x44, 0xb7, 0xc9, 0x3c, 0x7f, 0x7e, 0x6d, 0xb0, 0xb7, 0x58, 0xbf,
+ 0xf8, 0x2e, 0x6f, 0xf7, 0xeb, 0xda, 0xd4, 0xac, 0x5f, 0x30, 0x46, 0x41,
+ 0x62, 0x9c, 0xfb, 0x89, 0x26, 0xff, 0xda, 0xf3, 0x43, 0x9d, 0x85, 0xa7,
+ 0x58, 0xbf, 0xf9, 0xb8, 0x4c, 0x68, 0xfe, 0x26, 0xe2, 0xc5, 0x4a, 0x21,
+ 0xc4, 0x85, 0x7f, 0xff, 0xcc, 0x10, 0x79, 0xa2, 0x6e, 0xa1, 0xbc, 0xfb,
+ 0x99, 0xd7, 0x96, 0x2f, 0xc5, 0x80, 0x90, 0x2c, 0x5f, 0xdb, 0x07, 0x9f,
+ 0x6e, 0x96, 0x2f, 0xf4, 0x1c, 0xa2, 0x83, 0xfd, 0x62, 0xf7, 0x04, 0x75,
+ 0x8b, 0xff, 0xed, 0x6b, 0x39, 0xc1, 0x17, 0x30, 0xf3, 0x1e, 0xb1, 0x69,
+ 0x82, 0x3f, 0x70, 0x9e, 0x23, 0x1f, 0x1a, 0x04, 0x3d, 0x58, 0xad, 0x1d,
+ 0xcb, 0xf5, 0x09, 0x7f, 0xc2, 0x9d, 0x88, 0x8a, 0x36, 0x8b, 0xf7, 0x67,
+ 0xd6, 0x0d, 0x62, 0xff, 0xfb, 0x9f, 0x7e, 0x7b, 0xf8, 0x37, 0xe6, 0x12,
+ 0xc5, 0x8b, 0x0f, 0xe4, 0x45, 0x57, 0xf8, 0x9b, 0x46, 0xfb, 0x37, 0x58,
+ 0xa9, 0x3d, 0xbc, 0x26, 0xbf, 0xe1, 0x37, 0x0c, 0xd0, 0x9b, 0x8b, 0x15,
+ 0xf3, 0xdb, 0x22, 0x0b, 0xf3, 0x7e, 0x05, 0xba, 0xc5, 0xfe, 0x93, 0xe3,
+ 0x9e, 0x63, 0xd6, 0x2f, 0xf4, 0x0f, 0xc7, 0x2e, 0xa0, 0xb1, 0x5b, 0x9f,
+ 0x54, 0x46, 0xb7, 0xf9, 0xf4, 0xc4, 0x0c, 0x25, 0x8b, 0xfd, 0xe7, 0x2c,
+ 0xea, 0x12, 0xb1, 0x7f, 0xf6, 0xb4, 0xd0, 0xe1, 0x61, 0xc3, 0xe9, 0x62,
+ 0xa4, 0xfe, 0xb0, 0xce, 0xff, 0xfe, 0x1b, 0x31, 0xb9, 0xe9, 0xfb, 0x3f,
+ 0x39, 0x20, 0x58, 0xbf, 0xe7, 0x81, 0x67, 0xc9, 0xa0, 0xb1, 0x7f, 0xfe,
+ 0x86, 0x10, 0xff, 0x38, 0x52, 0x03, 0xb4, 0x16, 0x28, 0x91, 0x14, 0x19,
+ 0xbd, 0xe6, 0x6d, 0xd5, 0x22, 0x61, 0x7e, 0xd9, 0x8e, 0x37, 0x58, 0xbd,
+ 0xdc, 0xfc, 0x58, 0xa8, 0x22, 0x5b, 0x72, 0x37, 0x2a, 0xee, 0x29, 0xbd,
+ 0x1b, 0x46, 0xfd, 0xea, 0xc5, 0xff, 0x99, 0xfd, 0x3f, 0x73, 0xb0, 0xd6,
+ 0x2a, 0x35, 0x1f, 0x57, 0xcb, 0x6f, 0xff, 0x70, 0x7f, 0x9f, 0xc9, 0xf5,
+ 0xa7, 0xdd, 0x62, 0xb7, 0x3f, 0x46, 0x28, 0xbf, 0xff, 0xfd, 0x9b, 0xc8,
+ 0xb7, 0xfc, 0xe8, 0xcc, 0x27, 0xeb, 0x81, 0xec, 0x58, 0x35, 0x8b, 0xfd,
+ 0xd9, 0x8f, 0x86, 0xcf, 0x16, 0x2f, 0x75, 0x0e, 0x18, 0x8b, 0x2c, 0x7c,
+ 0xbf, 0xd9, 0xd7, 0xbc, 0xd0, 0xe2, 0xc5, 0x4a, 0x67, 0xf9, 0x0d, 0x4d,
+ 0x1b, 0x5f, 0xe2, 0x6f, 0x73, 0x71, 0x12, 0xc5, 0xff, 0xf0, 0x1c, 0x01,
+ 0x63, 0xf6, 0x2c, 0xf7, 0xdd, 0x62, 0xf6, 0xde, 0x75, 0x8b, 0xff, 0x89,
+ 0x82, 0xe0, 0x4c, 0x39, 0xeb, 0x8b, 0x16, 0xc5, 0x8a, 0xd1, 0xec, 0x79,
+ 0x1e, 0xfd, 0xc6, 0x68, 0x71, 0x62, 0xfb, 0xe2, 0x2d, 0x96, 0x2e, 0x7e,
+ 0x96, 0x2f, 0xe6, 0x87, 0x30, 0x80, 0xb1, 0x66, 0x31, 0x32, 0x91, 0xbb,
+ 0x74, 0x44, 0xc5, 0x1d, 0xf9, 0x27, 0x86, 0x2d, 0xac, 0x4f, 0x77, 0xf1,
+ 0xbd, 0x5f, 0xff, 0xcd, 0xb1, 0x4f, 0x5d, 0x6e, 0x26, 0xd0, 0x33, 0xaf,
+ 0x2c, 0x56, 0x2a, 0xa0, 0x79, 0x42, 0x24, 0x5f, 0x7f, 0xcd, 0x0e, 0x61,
+ 0x4f, 0x5c, 0x58, 0xbf, 0xfc, 0x76, 0xe8, 0x7a, 0xc7, 0x34, 0x72, 0x4b,
+ 0x17, 0xa0, 0xe0, 0x58, 0xac, 0x3e, 0x8e, 0x25, 0xdf, 0xfe, 0x35, 0xb9,
+ 0xad, 0x66, 0xc0, 0x3c, 0xc1, 0x62, 0xfb, 0xde, 0x9d, 0x2c, 0x57, 0x8f,
+ 0xc0, 0x34, 0xda, 0x82, 0x2d, 0x02, 0x84, 0x8d, 0xff, 0xff, 0xbf, 0x90,
+ 0xfe, 0x0c, 0xa7, 0x70, 0xe4, 0x2c, 0xe7, 0x18, 0xd5, 0x8b, 0xff, 0xde,
+ 0x06, 0x85, 0x0e, 0x6a, 0x7d, 0x87, 0x58, 0xa9, 0x47, 0x27, 0x8a, 0x44,
+ 0xdf, 0x7f, 0xd0, 0xfc, 0x91, 0xbd, 0xfb, 0xf4, 0xb1, 0x7f, 0xd8, 0x36,
+ 0x87, 0xb8, 0xc0, 0x58, 0xae, 0x8f, 0xe4, 0x24, 0x0b, 0xff, 0xc5, 0x21,
+ 0x07, 0xe2, 0x90, 0x67, 0x5e, 0x58, 0xbf, 0xd9, 0xaf, 0x94, 0xf5, 0x05,
+ 0x8b, 0x9b, 0xac, 0x44, 0x00, 0x69, 0x97, 0xf6, 0xa7, 0xf2, 0xdb, 0xac,
+ 0x53, 0xa6, 0x02, 0x28, 0x52, 0x06, 0x5f, 0x7f, 0xff, 0xe6, 0x22, 0x9e,
+ 0xa2, 0x29, 0xda, 0x0f, 0xce, 0x49, 0x0a, 0x3d, 0x62, 0xff, 0xc3, 0xc3,
+ 0x96, 0x7b, 0xef, 0xde, 0xac, 0x56, 0xe8, 0xb2, 0x76, 0xfb, 0xff, 0x74,
+ 0x17, 0xbe, 0xf2, 0x59, 0xba, 0xc5, 0x49, 0xf2, 0x39, 0x1d, 0xff, 0x89,
+ 0x8e, 0x07, 0xd3, 0xf4, 0x05, 0x8b, 0xec, 0x7d, 0x6c, 0xb1, 0x43, 0x3e,
+ 0x2e, 0xfc, 0xfe, 0xfe, 0x91, 0xec, 0x79, 0xd2, 0xc5, 0xc0, 0x95, 0x8b,
+ 0x39, 0xa7, 0x8d, 0xe2, 0xfa, 0x83, 0x3b, 0x24, 0x64, 0x39, 0x09, 0x33,
+ 0x49, 0x37, 0x85, 0x5b, 0x90, 0x6a, 0x37, 0xa3, 0xca, 0x5d, 0xfc, 0xad,
+ 0x40, 0x1b, 0x14, 0xa3, 0x9e, 0x47, 0x53, 0xe8, 0xd3, 0x05, 0x08, 0x2e,
+ 0xcd, 0xb7, 0xf0, 0xc1, 0xde, 0xf0, 0x11, 0xcb, 0x17, 0xbb, 0xbb, 0xa5,
+ 0x62, 0xff, 0xec, 0x0b, 0xed, 0xee, 0x4f, 0xc3, 0x89, 0x62, 0xff, 0xff,
+ 0x98, 0xd3, 0x66, 0x1c, 0x30, 0xe2, 0x7f, 0xb9, 0xc5, 0xa9, 0x58, 0xbf,
+ 0xfb, 0x5f, 0x67, 0xf0, 0xb4, 0xdd, 0xb1, 0x62, 0xff, 0xf1, 0xb1, 0x7d,
+ 0xf5, 0xe8, 0x61, 0x38, 0xd6, 0x2b, 0x11, 0x24, 0x24, 0x6a, 0x1a, 0x6c,
+ 0xda, 0x48, 0xfc, 0x3f, 0x2f, 0xfa, 0x62, 0x84, 0x83, 0x40, 0x95, 0x8b,
+ 0xf4, 0x83, 0xdd, 0xa0, 0xb1, 0x73, 0x8d, 0x62, 0x88, 0xf0, 0xb8, 0x57,
+ 0x7f, 0x14, 0xf4, 0x76, 0xf2, 0xc5, 0xfe, 0xdf, 0xc2, 0xfe, 0xa4, 0x25,
+ 0x8b, 0xff, 0xb3, 0xaf, 0xe0, 0xff, 0x91, 0x41, 0x96, 0x2a, 0x4f, 0xf4,
0xe6, 0xf7, 0xff, 0xff, 0x9e, 0x4b, 0xdb, 0xfd, 0xfd, 0x91, 0x14, 0x9f,
- 0x3e, 0xfa, 0xfb, 0x2c, 0x5f, 0xf3, 0xe0, 0x7b, 0xfe, 0x5e, 0x39, 0x62,
- 0xff, 0xff, 0xff, 0x3f, 0x70, 0xfc, 0x91, 0xb8, 0x53, 0x0c, 0x3b, 0x76,
+ 0x3e, 0xfa, 0xfb, 0x2c, 0x5f, 0xf3, 0xe0, 0x5b, 0xfe, 0x5e, 0x39, 0x62,
+ 0xff, 0xff, 0xff, 0x3f, 0x50, 0xfc, 0x91, 0xb8, 0x53, 0x0c, 0x3b, 0x74,
0x3d, 0x63, 0x9a, 0x39, 0x25, 0x8b, 0xff, 0xd2, 0x50, 0xc1, 0x6b, 0x60,
0x66, 0x0d, 0x62, 0xff, 0x6e, 0xfa, 0xe4, 0x52, 0xcb, 0x17, 0xf9, 0xfc,
- 0x09, 0xf9, 0x9c, 0x58, 0xbe, 0x68, 0x49, 0x2c, 0x5f, 0x85, 0xcf, 0xb4,
- 0x20, 0x7a, 0xdf, 0x35, 0xbf, 0x98, 0x18, 0x43, 0x82, 0xc5, 0xff, 0xde,
- 0x35, 0xc3, 0xe7, 0xf3, 0xa4, 0xf6, 0xb1, 0x7f, 0xbf, 0x8e, 0x39, 0x2d,
- 0xd6, 0x2e, 0x6e, 0xfa, 0x9f, 0xef, 0x92, 0xa8, 0xd4, 0xfb, 0xbb, 0x4a,
- 0xd4, 0x22, 0xc8, 0xff, 0x90, 0xaa, 0xb3, 0x8d, 0x74, 0x47, 0x72, 0x38,
- 0x9f, 0x34, 0x42, 0x78, 0x55, 0xfc, 0x84, 0x2e, 0xed, 0xc3, 0xdf, 0x4a,
- 0x7c, 0xbf, 0x0e, 0x79, 0xe7, 0x58, 0xbf, 0x66, 0xc7, 0x78, 0x96, 0x2a,
- 0x57, 0xab, 0xff, 0x3b, 0x8a, 0xd0, 0x98, 0x22, 0x8b, 0xff, 0xcc, 0x40,
- 0x04, 0xe7, 0x47, 0x2e, 0xfc, 0xb1, 0x7d, 0xe7, 0x3b, 0x2c, 0x5f, 0x07,
- 0xf1, 0x6e, 0xb1, 0x63, 0x56, 0x2f, 0xef, 0xf2, 0x7d, 0x23, 0x58, 0xa9,
- 0x3e, 0x7c, 0x26, 0x71, 0x3a, 0x94, 0xc0, 0x31, 0x2f, 0xd0, 0x89, 0xbf,
- 0xfc, 0x26, 0xfb, 0x0e, 0x07, 0xfc, 0x98, 0x4b, 0x17, 0x8a, 0x4e, 0xb1,
- 0x7e, 0x7e, 0x7e, 0x74, 0xb1, 0x51, 0x1e, 0x27, 0xc7, 0x2e, 0x7f, 0x2c,
- 0x5f, 0x9f, 0x63, 0xce, 0xeb, 0x16, 0xf9, 0xcf, 0x07, 0xc2, 0xf7, 0xff,
- 0xfd, 0xad, 0x84, 0x0e, 0xbe, 0xe6, 0x7b, 0xae, 0x7a, 0x70, 0xa0, 0xb1,
- 0x52, 0x89, 0x47, 0x28, 0xbf, 0xfe, 0xdf, 0x53, 0xf2, 0xcf, 0x64, 0x60,
- 0x61, 0x86, 0x91, 0x7f, 0xfd, 0x3b, 0xb7, 0x79, 0xad, 0x66, 0xd3, 0xc7,
- 0x58, 0xa6, 0x45, 0x41, 0x2b, 0xd4, 0x15, 0x52, 0xee, 0x68, 0xd0, 0x8f,
- 0xe4, 0x3e, 0x3d, 0x0c, 0x9b, 0xd8, 0x77, 0x58, 0xbf, 0x6e, 0x2d, 0xca,
- 0x56, 0x2f, 0xe0, 0xcc, 0xd6, 0x98, 0x6b, 0x17, 0xd1, 0x7e, 0x7c, 0xb1,
- 0x4e, 0x7a, 0xbc, 0x31, 0xa1, 0xa2, 0xf3, 0x71, 0xc8, 0x9f, 0xef, 0xe8,
- 0xd5, 0x1a, 0xfc, 0x16, 0xc2, 0x91, 0xeb, 0x17, 0xde, 0xdc, 0x5b, 0x2c,
- 0x5f, 0xdc, 0x38, 0x8a, 0x1c, 0x58, 0xa2, 0x3d, 0x5f, 0x13, 0x5f, 0xfd,
- 0xdc, 0x0a, 0x61, 0xa9, 0xf3, 0x79, 0x62, 0xf8, 0x41, 0x78, 0xe7, 0x58,
- 0xbf, 0xe1, 0x99, 0x3d, 0xc7, 0x66, 0xa5, 0x62, 0xe9, 0x82, 0xc5, 0x4a,
- 0x39, 0x70, 0x85, 0xd1, 0x58, 0xa8, 0x8f, 0xaf, 0x8f, 0xa6, 0xe2, 0xc5,
- 0xff, 0x6d, 0x9b, 0xc9, 0xdf, 0x9b, 0xac, 0x5f, 0xfb, 0x5f, 0x67, 0xf0,
- 0x18, 0x72, 0xb1, 0x52, 0x7f, 0x4e, 0x79, 0x7c, 0x28, 0xf9, 0x82, 0xc5,
- 0xff, 0x9b, 0xd3, 0xae, 0x7e, 0x4b, 0xcb, 0x17, 0xec, 0x83, 0xb7, 0x45,
- 0x8a, 0xfa, 0x23, 0x48, 0x9b, 0x87, 0xd5, 0x04, 0xef, 0xb1, 0x17, 0xf0,
- 0x9d, 0x14, 0x2b, 0x6f, 0x1d, 0xbe, 0xb1, 0x7f, 0xf8, 0xa6, 0x1a, 0xd0,
- 0xbb, 0x7d, 0x37, 0x16, 0x2f, 0xff, 0xb9, 0x86, 0x96, 0x7b, 0x99, 0x02,
- 0x60, 0xd6, 0x2c, 0xff, 0x44, 0xdf, 0x92, 0xe9, 0xd1, 0xc1, 0xd2, 0x17,
- 0x17, 0xfa, 0x4b, 0xd8, 0x52, 0x6a, 0xc5, 0xe9, 0xff, 0x16, 0x2b, 0xa1,
- 0xe7, 0x84, 0x32, 0xbf, 0xe9, 0x3f, 0xbf, 0x85, 0x20, 0x58, 0xbf, 0x1e,
- 0x61, 0x1f, 0xba, 0xc5, 0xf8, 0xa4, 0x5e, 0xe2, 0xc5, 0x00, 0xf5, 0x7c,
- 0x5b, 0x7f, 0xdc, 0x83, 0xf8, 0x06, 0x14, 0x16, 0x2b, 0x63, 0xdd, 0xec,
- 0x8a, 0xfe, 0x2c, 0xf7, 0xcc, 0x0d, 0x62, 0xfd, 0x91, 0x41, 0x89, 0x62,
- 0xfd, 0x9d, 0x08, 0x5c, 0x58, 0xaf, 0x1e, 0x91, 0x85, 0x15, 0xda, 0x29,
- 0x4f, 0x08, 0x2a, 0xc4, 0x79, 0x3c, 0x32, 0x6a, 0x55, 0x50, 0x63, 0xc3,
- 0x93, 0x6a, 0x3d, 0xcb, 0xff, 0xfd, 0xbf, 0xdc, 0xe4, 0xfb, 0x4f, 0xb8,
- 0x67, 0xbf, 0x83, 0x58, 0xbf, 0x37, 0xfa, 0x8e, 0x56, 0x2b, 0xb4, 0x47,
- 0x79, 0x92, 0xff, 0xbd, 0xc2, 0xc1, 0xff, 0x3c, 0xb1, 0x7f, 0xc6, 0xf5,
- 0x33, 0x35, 0x1c, 0xc6, 0xac, 0x58, 0x2e, 0xb1, 0x52, 0x7b, 0x0c, 0x85,
- 0x7f, 0xfe, 0x63, 0x7f, 0x2f, 0x07, 0x2f, 0x43, 0x35, 0x8b, 0x17, 0xff,
- 0xfd, 0xfc, 0x3e, 0x14, 0x3e, 0xe7, 0x13, 0xe9, 0xe3, 0x85, 0x2b, 0x14,
- 0x48, 0xbc, 0xf2, 0xa5, 0x4a, 0x76, 0x78, 0x48, 0x50, 0x91, 0x14, 0x37,
- 0x2f, 0xff, 0x61, 0x7d, 0xb8, 0x58, 0x69, 0xb9, 0x1e, 0xb1, 0x7f, 0xd3,
- 0xdc, 0x05, 0xb0, 0xdf, 0xa2, 0xc5, 0x6e, 0x88, 0xbf, 0xa6, 0xdf, 0xfb,
- 0xbf, 0x61, 0x0b, 0xc0, 0x98, 0x2c, 0x5d, 0x1c, 0x6a, 0xc5, 0x81, 0x87,
- 0xb8, 0xc8, 0x17, 0xff, 0x3f, 0x30, 0x7b, 0xce, 0xd3, 0x9e, 0x58, 0xbf,
- 0x0b, 0xfe, 0x98, 0x96, 0x2f, 0xff, 0xef, 0xb6, 0xbe, 0xe5, 0x83, 0xd3,
- 0x8b, 0x63, 0x0e, 0xb1, 0x7f, 0xf9, 0xe1, 0x84, 0x03, 0xb0, 0xff, 0x24,
- 0xb1, 0x7f, 0xfa, 0x77, 0x7f, 0x39, 0xfa, 0xf1, 0x86, 0x35, 0x8a, 0xe2,
- 0x25, 0x7c, 0x91, 0x7f, 0xb3, 0x91, 0x7d, 0xc3, 0xf2, 0xc5, 0xfe, 0xfb,
- 0x1c, 0x79, 0xd4, 0xeb, 0x17, 0xfd, 0xad, 0x4e, 0x36, 0xbb, 0x82, 0xc5,
- 0xfc, 0xf1, 0x69, 0xc3, 0xd9, 0x62, 0xe0, 0x4a, 0xc5, 0x4a, 0x3b, 0x86,
- 0x6c, 0xe6, 0xdf, 0x3a, 0x01, 0x8d, 0xff, 0xbe, 0xfd, 0x32, 0x3c, 0x64,
- 0xda, 0x58, 0xbe, 0x16, 0xdd, 0xc7, 0xac, 0x56, 0xe7, 0xd8, 0x48, 0x77,
- 0xf3, 0x8c, 0xf2, 0x39, 0x58, 0xbf, 0xd2, 0x79, 0x8c, 0x0c, 0x30, 0xd6,
- 0x28, 0x6a, 0xd0, 0x1e, 0x1e, 0x5c, 0x8c, 0x47, 0xd0, 0xb4, 0x8e, 0x22,
- 0x08, 0x5b, 0x7f, 0xfa, 0x76, 0x2c, 0xcd, 0xbc, 0x6c, 0x94, 0x16, 0x2f,
- 0xf6, 0xdf, 0x63, 0xbf, 0x1d, 0x62, 0xff, 0x0d, 0x98, 0x33, 0x33, 0xb5,
- 0x8b, 0x31, 0x1f, 0x57, 0x8d, 0x2a, 0x57, 0x67, 0x72, 0x10, 0x1b, 0x93,
- 0x7d, 0x15, 0xa5, 0xb5, 0x13, 0x68, 0x70, 0xb5, 0xbf, 0xe1, 0xfe, 0x70,
- 0x65, 0x9d, 0x16, 0x2f, 0xcc, 0x7f, 0x66, 0xeb, 0x17, 0xfe, 0x8f, 0xfe,
- 0x60, 0xcb, 0x36, 0x95, 0x8a, 0xf9, 0xf5, 0x08, 0xa6, 0xff, 0xfd, 0xf7,
- 0x2c, 0xd8, 0xe2, 0xfe, 0x7d, 0xbb, 0x02, 0xc5, 0xff, 0x85, 0xee, 0x19,
- 0xb7, 0x00, 0x09, 0x58, 0xbf, 0xcf, 0xc7, 0x10, 0x5c, 0x72, 0xb1, 0x43,
- 0x3f, 0xaf, 0x21, 0xdc, 0x28, 0x96, 0x2f, 0x06, 0x18, 0x69, 0x17, 0xdb,
- 0x1d, 0xf8, 0x91, 0x18, 0x68, 0x6e, 0x91, 0xac, 0x54, 0xa2, 0x21, 0x8e,
- 0x88, 0xde, 0xfc, 0x67, 0xdb, 0xf2, 0xb1, 0x7f, 0xcf, 0xc9, 0x84, 0x5f,
- 0x70, 0x2c, 0x5f, 0xec, 0xef, 0x59, 0x1c, 0xe0, 0x58, 0xa8, 0x2b, 0x08,
- 0x1c, 0x29, 0x0d, 0x22, 0x78, 0x68, 0xea, 0x15, 0x47, 0x2d, 0xf9, 0x49,
- 0x1d, 0x5f, 0xff, 0xb8, 0x59, 0xff, 0x14, 0x82, 0x13, 0x3c, 0x75, 0x8b,
- 0x7d, 0x62, 0xbb, 0x3e, 0x53, 0x14, 0xef, 0xde, 0xe7, 0xb8, 0x14, 0x58,
- 0xbf, 0x4e, 0x13, 0x1d, 0x62, 0xff, 0xcd, 0x0f, 0xbf, 0x60, 0xd3, 0x0d,
- 0x62, 0xf7, 0xb5, 0x8b, 0x17, 0x0c, 0x35, 0x8b, 0xff, 0xf6, 0x74, 0x92,
- 0xf1, 0xe7, 0x08, 0x79, 0xdf, 0x96, 0x2f, 0x31, 0x6f, 0x28, 0x8c, 0xd8,
- 0x77, 0x43, 0x34, 0xe9, 0xc2, 0xb1, 0x20, 0x0b, 0x88, 0x98, 0x50, 0xcc,
- 0xbf, 0x6b, 0x69, 0xd6, 0xcb, 0x17, 0xe7, 0x2f, 0x18, 0x75, 0x8a, 0x93,
- 0xd4, 0x01, 0x5d, 0xef, 0x3c, 0x4b, 0x17, 0xd9, 0x9a, 0xe2, 0xc5, 0xb9,
- 0x87, 0x80, 0x01, 0xea, 0x82, 0x22, 0x3c, 0xc3, 0x7a, 0x43, 0x75, 0x8b,
- 0xff, 0xf7, 0xdf, 0x7f, 0xe7, 0xbe, 0xec, 0x0f, 0xb8, 0x16, 0x2f, 0xff,
- 0x7f, 0x39, 0xcc, 0x38, 0xdf, 0xa4, 0x8d, 0x62, 0xfe, 0x93, 0xc5, 0xf7,
- 0xd2, 0xc5, 0xfb, 0x98, 0x76, 0xed, 0x62, 0xfc, 0x6f, 0x5c, 0xcd, 0x2c,
- 0x56, 0x1e, 0xa0, 0x8a, 0x6f, 0xdc, 0x7c, 0x20, 0x2c, 0x56, 0x8f, 0x23,
- 0x84, 0x37, 0xb5, 0x91, 0xeb, 0x17, 0xff, 0x85, 0xcf, 0xbe, 0x44, 0xfb,
- 0x67, 0x7e, 0x58, 0xbf, 0xe0, 0xcc, 0xdb, 0x98, 0x79, 0x8f, 0x58, 0xbf,
- 0xfc, 0x2e, 0xf3, 0x46, 0x7b, 0x98, 0x6b, 0xe9, 0x62, 0xff, 0xf3, 0xef,
- 0x84, 0x3d, 0x36, 0xf9, 0xdf, 0x96, 0x2a, 0x51, 0xb5, 0xf4, 0x0e, 0x27,
- 0x5f, 0xf9, 0xc8, 0xcc, 0x8b, 0x8f, 0xd8, 0x6b, 0x17, 0xcc, 0x0f, 0x05,
- 0xd6, 0x28, 0x6a, 0xe2, 0xf0, 0x77, 0x75, 0x68, 0x93, 0x35, 0x0c, 0xb3,
- 0x91, 0x11, 0x07, 0xa3, 0x27, 0xe8, 0x5e, 0x1a, 0x15, 0xfb, 0x3b, 0xf7,
- 0xe5, 0x62, 0xff, 0xc3, 0xc8, 0x3f, 0xe7, 0x9e, 0x75, 0x8b, 0xf3, 0xf4,
- 0xf4, 0xe2, 0xc5, 0xfe, 0x7e, 0x9d, 0xc9, 0x4f, 0x16, 0x2f, 0xe9, 0x2f,
- 0xb3, 0x1d, 0x62, 0xa0, 0x7c, 0x20, 0x35, 0xaf, 0xa6, 0x26, 0xc5, 0x3c,
- 0x3e, 0xf4, 0x22, 0xaa, 0x57, 0x67, 0xb2, 0x5d, 0x73, 0x47, 0x5d, 0x7f,
- 0x4f, 0xb8, 0x61, 0x41, 0x62, 0xfa, 0x77, 0xc2, 0x58, 0xbf, 0x9f, 0x9c,
- 0x9d, 0x43, 0x47, 0xa3, 0xf2, 0xfb, 0xf8, 0xcc, 0xd4, 0x73, 0x1a, 0xb1,
- 0x7e, 0xcd, 0x47, 0x31, 0xab, 0x17, 0x67, 0x3a, 0x9e, 0xf9, 0x86, 0x77,
- 0xff, 0xa2, 0x29, 0xf7, 0x3d, 0xde, 0xee, 0x5b, 0x2c, 0x5f, 0xf1, 0x7b,
- 0x4c, 0xdd, 0xc3, 0x8b, 0x17, 0xfc, 0x6e, 0x11, 0x93, 0xac, 0x1a, 0xc5,
- 0x61, 0xfa, 0x08, 0xea, 0xff, 0x98, 0xde, 0xbf, 0x90, 0x4c, 0x7a, 0xc5,
- 0xfa, 0x19, 0xd1, 0xf4, 0xb1, 0x7f, 0x83, 0x33, 0x22, 0xe1, 0xf8, 0xb1,
- 0x52, 0x7c, 0x4c, 0x55, 0x58, 0x9e, 0xa3, 0x98, 0x7e, 0x18, 0x4c, 0x42,
- 0x50, 0xa1, 0xbf, 0xff, 0xf0, 0x0c, 0x2c, 0xd6, 0xb0, 0x3c, 0x8f, 0xc2,
- 0x90, 0x1d, 0xa0, 0xb1, 0x7f, 0xff, 0xfd, 0xbe, 0x13, 0xf7, 0xc2, 0xcf,
- 0x73, 0x20, 0x4c, 0x1f, 0x7e, 0x13, 0x71, 0x62, 0xfb, 0xde, 0x93, 0xac,
- 0x5e, 0x2c, 0xe0, 0x11, 0x44, 0x1b, 0xfd, 0x9c, 0x93, 0x45, 0xe9, 0x18,
- 0x8d, 0xff, 0xfd, 0xee, 0x08, 0x7f, 0x7c, 0x89, 0x9e, 0x3d, 0xfb, 0x82,
- 0xc5, 0xff, 0xfc, 0x58, 0x06, 0x20, 0x6b, 0x58, 0x1e, 0x01, 0xbb, 0x58,
- 0xa2, 0x45, 0xdf, 0x98, 0x2f, 0xbd, 0xb6, 0x06, 0xb1, 0x7f, 0xf0, 0x24,
- 0xc1, 0xce, 0xa2, 0xfb, 0x81, 0x62, 0x9c, 0xfb, 0x00, 0x4b, 0x7f, 0xf3,
- 0x96, 0xc7, 0x17, 0x7e, 0x26, 0xfa, 0xc5, 0xf8, 0x85, 0xe9, 0xe2, 0xc5,
- 0xd3, 0xbc, 0x9f, 0x77, 0xd1, 0xaf, 0xd1, 0x41, 0xf5, 0xc5, 0x8b, 0xfe,
- 0x9d, 0xe4, 0xf8, 0x36, 0x3a, 0xc5, 0x68, 0xf8, 0xc2, 0x15, 0x5f, 0xfd,
- 0xad, 0x49, 0xf8, 0x61, 0x14, 0xf6, 0xb1, 0x7c, 0x61, 0x4e, 0xeb, 0x15,
- 0xb1, 0xf5, 0x47, 0xa3, 0x53, 0xa2, 0xd1, 0xa1, 0x1d, 0x7f, 0xf4, 0x39,
- 0x92, 0x37, 0x26, 0xd1, 0xab, 0x17, 0xed, 0x4e, 0x0d, 0xd6, 0x2f, 0xef,
- 0xb8, 0xc7, 0x81, 0xac, 0x5f, 0xb5, 0x9d, 0x3f, 0x9d, 0x4f, 0x5b, 0x72,
- 0x7a, 0x94, 0x6e, 0xb4, 0x26, 0xaf, 0xff, 0xff, 0x81, 0xcc, 0x87, 0xe5,
- 0xf4, 0x00, 0x4e, 0xb0, 0x46, 0x8d, 0xf4, 0xdc, 0x58, 0xbf, 0xfe, 0xfe,
- 0x43, 0xae, 0xff, 0x7f, 0x77, 0xbb, 0xe9, 0x62, 0xa5, 0x1a, 0x9e, 0x7e,
- 0xbf, 0xd3, 0xb6, 0xef, 0x25, 0x05, 0x8b, 0xff, 0xf8, 0x2e, 0xfe, 0xfc,
- 0xeb, 0x4f, 0xdf, 0xf3, 0x0b, 0x75, 0x8a, 0x82, 0xef, 0xfb, 0xc3, 0xaf,
- 0x50, 0x8e, 0x3c, 0x23, 0xff, 0x1a, 0x20, 0x23, 0x03, 0x28, 0x7d, 0x78,
- 0x88, 0x46, 0x97, 0xfa, 0x73, 0x9a, 0xce, 0xe0, 0xb1, 0x7f, 0xfb, 0xd2,
- 0x7d, 0xd8, 0x78, 0x19, 0x9a, 0x82, 0xc5, 0xff, 0xbf, 0x24, 0x6e, 0xef,
- 0x25, 0x05, 0x8b, 0xdb, 0x74, 0x1a, 0xc5, 0x40, 0xf8, 0x08, 0xfe, 0xf0,
- 0x6c, 0x1a, 0xc5, 0xff, 0x9b, 0x5d, 0x49, 0xbd, 0x06, 0x1a, 0xc5, 0xff,
- 0xfc, 0xe4, 0x3d, 0x66, 0xff, 0x9f, 0xe6, 0xb5, 0x26, 0xac, 0x5f, 0xf3,
- 0x07, 0xec, 0xfe, 0xa3, 0xc6, 0xb1, 0x50, 0x46, 0xd7, 0xd0, 0x09, 0x72,
- 0xfe, 0x66, 0xf4, 0x73, 0xee, 0xb1, 0x7f, 0xf8, 0xdc, 0xfb, 0x7b, 0x9d,
- 0xc0, 0x4d, 0xe5, 0x8b, 0xed, 0x3e, 0x7d, 0x62, 0xfe, 0xc3, 0x33, 0x4e,
- 0x4b, 0x15, 0xa3, 0xcf, 0xe8, 0x45, 0x7f, 0xff, 0xff, 0x73, 0x93, 0xad,
- 0xf7, 0xfb, 0xc4, 0xcd, 0xac, 0xef, 0xdd, 0xee, 0x26, 0x2e, 0xfc, 0xb1,
- 0x7f, 0x79, 0xe2, 0xf6, 0x47, 0xac, 0x56, 0x91, 0x85, 0xe8, 0x48, 0x5f,
- 0xf1, 0xd8, 0x66, 0x04, 0x92, 0x82, 0xc5, 0xff, 0x6e, 0x28, 0xfe, 0x38,
- 0x79, 0xa5, 0x8a, 0x93, 0xfb, 0xdc, 0xf2, 0xff, 0xff, 0x72, 0x4d, 0xce,
- 0x31, 0x7b, 0x0a, 0x77, 0x29, 0x3a, 0xc5, 0xff, 0xdf, 0x78, 0x89, 0x83,
- 0xf6, 0x7c, 0xeb, 0x17, 0xbf, 0x27, 0x58, 0xbf, 0x3e, 0x71, 0x89, 0x62,
- 0xf8, 0x5a, 0x6e, 0x6e, 0x88, 0x9f, 0xa3, 0x78, 0x76, 0xbb, 0x4c, 0xc3,
- 0xd0, 0xe8, 0xbf, 0xfd, 0xcc, 0xd7, 0x5d, 0xfe, 0xfd, 0x1c, 0x86, 0xb1,
- 0x4e, 0x7f, 0x3c, 0x2a, 0xbf, 0xff, 0x31, 0x6c, 0x3f, 0xce, 0xb5, 0x9c,
- 0xe0, 0x89, 0x62, 0xa5, 0x5e, 0x5e, 0x43, 0x99, 0xe1, 0x46, 0xd1, 0xe5,
- 0x86, 0x43, 0x7f, 0xe7, 0x18, 0xbd, 0xc9, 0x27, 0xc5, 0x8b, 0xfe, 0x3c,
- 0xeb, 0xa6, 0x6a, 0x62, 0x58, 0xbf, 0xff, 0x69, 0xc5, 0xb7, 0xbf, 0x2f,
- 0xad, 0x39, 0x6c, 0xb1, 0x7e, 0x29, 0x80, 0x55, 0x96, 0x2f, 0xe7, 0xd1,
- 0x4f, 0x70, 0x58, 0xbf, 0xb3, 0x45, 0x3d, 0xc1, 0x62, 0xe6, 0x2c, 0x3d,
- 0xce, 0x17, 0x5f, 0xfd, 0x39, 0xa8, 0x37, 0xbe, 0xc4, 0x05, 0x8b, 0xff,
- 0xf7, 0xc5, 0xdf, 0xb8, 0xdd, 0xef, 0x1d, 0x9c, 0xe6, 0x2c, 0x5f, 0xf3,
- 0x1d, 0xbd, 0xf6, 0x20, 0x2c, 0x5f, 0xfe, 0x6d, 0x1a, 0x64, 0x87, 0x9c,
- 0xe3, 0x1a, 0xb1, 0x43, 0x54, 0x5f, 0x8a, 0xfb, 0xc2, 0x1f, 0xe5, 0x7e,
- 0x43, 0xe8, 0xba, 0x19, 0xc5, 0xff, 0xe7, 0x22, 0x90, 0xfd, 0x9b, 0x46,
- 0xa8, 0xd4, 0x14, 0x58, 0xac, 0x46, 0x4b, 0x37, 0x5f, 0xfb, 0x5b, 0x9e,
- 0x7b, 0xe6, 0x74, 0xc5, 0x8b, 0x9a, 0x3d, 0x62, 0xf3, 0x68, 0xd5, 0x8b,
- 0xff, 0xfa, 0x22, 0x91, 0xe7, 0x7e, 0xc8, 0x49, 0x6c, 0x7c, 0x58, 0xbb,
- 0x0e, 0xb1, 0x7f, 0xe2, 0xc1, 0xbb, 0x16, 0xc7, 0xc5, 0x8b, 0xc0, 0x8e,
- 0xc1, 0x9e, 0xa1, 0x82, 0xf5, 0xa4, 0xc1, 0x7e, 0x3c, 0x50, 0xb0, 0xbe,
- 0xf3, 0x6b, 0x8b, 0x17, 0xee, 0xb1, 0xd9, 0xa9, 0x58, 0xad, 0x8f, 0x40,
- 0x88, 0xea, 0x55, 0x04, 0xec, 0x87, 0x91, 0x8f, 0xb4, 0x21, 0x6f, 0xc3,
- 0xc8, 0xa7, 0xeb, 0x17, 0xff, 0xff, 0xef, 0x7d, 0xa1, 0x9a, 0x83, 0xf7,
- 0x9d, 0x30, 0x6e, 0x1f, 0xd9, 0xfd, 0x3f, 0x58, 0xb4, 0x9a, 0x8a, 0xe2,
- 0x29, 0xbf, 0xe8, 0x3f, 0xb9, 0xbc, 0xfb, 0x8b, 0x17, 0xf0, 0x3a, 0xe0,
- 0xda, 0x0b, 0x15, 0x11, 0xf5, 0xb1, 0xdd, 0x8d, 0x58, 0xbf, 0xfb, 0x37,
- 0xfc, 0xff, 0x35, 0xa9, 0x35, 0x62, 0xfd, 0x9a, 0xd4, 0x9a, 0xb1, 0x7c,
- 0x4e, 0x0e, 0x4a, 0x20, 0xb4, 0x27, 0xf4, 0x6b, 0xfe, 0xfb, 0x00, 0xed,
- 0x06, 0xe2, 0xc5, 0xfe, 0x68, 0x42, 0x61, 0xbf, 0x16, 0x2b, 0x0f, 0xb8,
- 0x47, 0x37, 0xfd, 0x90, 0xfb, 0x43, 0xcf, 0xb2, 0xc5, 0xff, 0xff, 0xcf,
- 0xef, 0xe0, 0xe0, 0xfe, 0xc3, 0xf1, 0xa1, 0x1d, 0x9c, 0xe6, 0x2c, 0x54,
- 0x15, 0x5c, 0xe4, 0x24, 0xde, 0x14, 0x9f, 0x85, 0x98, 0x08, 0x78, 0x75,
- 0x7f, 0xf9, 0xb6, 0xfb, 0xc9, 0x64, 0x4f, 0xa7, 0x58, 0xbf, 0xff, 0x67,
- 0x42, 0x17, 0x35, 0x30, 0x7f, 0x39, 0x41, 0x62, 0xa0, 0xde, 0x0b, 0x0e,
- 0x53, 0xbe, 0x4f, 0xca, 0x9b, 0x09, 0xfe, 0xcd, 0x1e, 0x15, 0xd1, 0xe4,
- 0x31, 0x43, 0xe7, 0x45, 0xe7, 0x31, 0xfc, 0xe3, 0x3b, 0x2c, 0x80, 0xf4,
- 0xa5, 0x9a, 0x72, 0x51, 0x57, 0xa5, 0xd7, 0x86, 0xcc, 0x62, 0x4d, 0xff,
- 0x7d, 0xb8, 0xe4, 0x53, 0xda, 0xc5, 0xfe, 0x7f, 0xcf, 0x70, 0xc3, 0xac,
- 0x5f, 0x61, 0x38, 0xf8, 0x7d, 0x91, 0xc7, 0x17, 0xc6, 0x85, 0xdf, 0xb5,
- 0x8b, 0xff, 0x7b, 0x86, 0x79, 0xca, 0x7b, 0x82, 0xc5, 0x68, 0xfa, 0x88,
- 0xa6, 0xfc, 0x59, 0xf6, 0xf2, 0xc5, 0xff, 0xa1, 0x25, 0xb1, 0x9a, 0x21,
- 0x41, 0x62, 0xf7, 0x33, 0x4b, 0x17, 0xf1, 0x30, 0xc1, 0xd8, 0x16, 0x2b,
- 0x11, 0xab, 0x1e, 0x43, 0x11, 0x3f, 0xd0, 0x78, 0x3b, 0x7f, 0xf3, 0x14,
- 0x34, 0xdd, 0xfe, 0x73, 0x8b, 0x17, 0xff, 0x6e, 0xfa, 0xfe, 0x45, 0xf7,
- 0xd6, 0xcb, 0x17, 0xff, 0x8b, 0x03, 0x60, 0x75, 0xf7, 0xe5, 0xf7, 0x58,
- 0xbe, 0xf6, 0xd8, 0x35, 0x8b, 0xfe, 0x73, 0x4c, 0xd0, 0x0e, 0xfc, 0x58,
- 0xa3, 0x51, 0x5b, 0x12, 0x6c, 0x71, 0x25, 0xff, 0xc5, 0x80, 0xce, 0x8e,
- 0x68, 0x1b, 0xcb, 0x17, 0xfe, 0x7e, 0xf8, 0x06, 0x21, 0xc4, 0x25, 0x8b,
- 0xc1, 0x86, 0x1a, 0xc5, 0xff, 0xc5, 0x20, 0xc1, 0xf3, 0x0f, 0x3b, 0xa4,
- 0x46, 0x1a, 0x1a, 0x02, 0x2e, 0x7c, 0xc5, 0x7f, 0xbe, 0xf8, 0x39, 0x2f,
- 0x2c, 0x54, 0x13, 0x54, 0x3c, 0x3f, 0xfa, 0x11, 0xdf, 0xf9, 0x81, 0xbf,
- 0xde, 0x22, 0x90, 0x2c, 0x56, 0x1f, 0xc3, 0x9c, 0x5f, 0xda, 0xc0, 0x9f,
- 0x61, 0xac, 0x5f, 0xf7, 0x7d, 0x4b, 0x3a, 0x69, 0xf8, 0xb1, 0x7f, 0x70,
- 0xb3, 0x63, 0x20, 0xb1, 0x58, 0x7d, 0xc7, 0x3e, 0xbf, 0xb7, 0xfb, 0xc9,
- 0x6e, 0xb1, 0x52, 0x7a, 0x18, 0x43, 0x7f, 0xb5, 0x3e, 0x7d, 0xdc, 0x6b,
- 0x17, 0xe8, 0x45, 0x99, 0xba, 0xc5, 0xfe, 0x16, 0xd2, 0xe3, 0xc3, 0xac,
- 0x5b, 0x4b, 0x14, 0x14, 0x45, 0x24, 0x9a, 0x11, 0x51, 0x86, 0x97, 0xe0,
- 0xf0, 0xed, 0xda, 0xc5, 0xf0, 0x31, 0xa3, 0xd6, 0x2a, 0x4f, 0x3d, 0xca,
- 0xaa, 0x0b, 0xf0, 0x39, 0x1b, 0xc9, 0xa9, 0xbd, 0xa2, 0x3c, 0x3d, 0x7f,
- 0x28, 0x05, 0x88, 0x0a, 0x1d, 0xdc, 0x86, 0x27, 0xa1, 0x1f, 0x7b, 0x9d,
- 0x4d, 0x58, 0xbd, 0xb4, 0xfd, 0x62, 0xba, 0x9b, 0xf2, 0x21, 0xbf, 0x7f,
- 0xdc, 0x14, 0x7a, 0xc5, 0xc1, 0x85, 0x16, 0x2a, 0x4f, 0x2b, 0xb2, 0xdb,
- 0xfe, 0x26, 0x37, 0xdc, 0x27, 0x35, 0x62, 0xfd, 0xef, 0x39, 0xf8, 0xb1,
- 0x73, 0x3a, 0xc5, 0xfb, 0xbf, 0x74, 0xc2, 0x58, 0xbf, 0x37, 0xa0, 0xc3,
- 0x58, 0xb1, 0xb8, 0x7a, 0x64, 0x57, 0x6f, 0xac, 0x5d, 0x9f, 0x58, 0xa8,
- 0x1a, 0x9f, 0x09, 0x56, 0x26, 0x7a, 0xe7, 0x5f, 0x29, 0x66, 0x9f, 0x28,
- 0x59, 0xd6, 0x2f, 0xf8, 0x0d, 0x9b, 0x1e, 0x73, 0xcb, 0x17, 0xff, 0xf4,
- 0x94, 0x9a, 0x52, 0x69, 0x91, 0xd3, 0xa9, 0xde, 0x56, 0x2b, 0x48, 0x98,
- 0x0c, 0xe6, 0xff, 0xa7, 0x67, 0x3f, 0xb3, 0x0e, 0xb1, 0x7f, 0xfd, 0x27,
- 0x29, 0xec, 0x03, 0xc3, 0xed, 0x81, 0xac, 0x5f, 0xdf, 0x9e, 0xbb, 0xbe,
- 0xcb, 0x17, 0xfe, 0x63, 0xe6, 0x8d, 0x34, 0x45, 0xe5, 0x8b, 0xfd, 0x3e,
- 0xe7, 0x1c, 0xa2, 0x58, 0xaf, 0x9f, 0xa9, 0x20, 0xdf, 0xf8, 0x36, 0x28,
- 0x7c, 0x53, 0xdf, 0x16, 0x2f, 0xff, 0xe6, 0x3e, 0xb3, 0xa4, 0x97, 0xb3,
- 0xef, 0xaf, 0xb2, 0xc5, 0xff, 0x37, 0xb9, 0xef, 0x34, 0x38, 0xb1, 0x51,
- 0x23, 0xdf, 0x44, 0x3f, 0x41, 0x25, 0xbb, 0xff, 0x9b, 0x4d, 0x0c, 0xe3,
- 0x7b, 0x22, 0x58, 0xbf, 0xef, 0x6a, 0x73, 0xbe, 0xad, 0xc5, 0x8b, 0xf3,
- 0x68, 0xa6, 0x0b, 0x17, 0xec, 0x1f, 0xde, 0x25, 0x8a, 0xd1, 0xe8, 0x11,
- 0x3d, 0xff, 0xff, 0x00, 0xed, 0x0c, 0xdc, 0x62, 0x37, 0xbe, 0x30, 0x33,
- 0xbf, 0x2c, 0x5f, 0xfb, 0x22, 0x0f, 0x3b, 0xf7, 0xa4, 0xeb, 0x15, 0x28,
- 0xae, 0xfb, 0x65, 0xfc, 0x5b, 0x3e, 0xba, 0x41, 0x62, 0xff, 0xff, 0x7b,
- 0xd3, 0x02, 0x6f, 0xc9, 0xff, 0x83, 0x6e, 0xc9, 0x62, 0xfd, 0x9d, 0xe3,
- 0x47, 0xac, 0x5f, 0xfe, 0xf7, 0xf3, 0xa7, 0xdf, 0xaf, 0x38, 0xe7, 0x58,
- 0xa9, 0x4c, 0x2f, 0x0c, 0x7e, 0xc0, 0xc5, 0x77, 0xfd, 0x07, 0xd7, 0x72,
- 0x53, 0xc5, 0x8b, 0xc1, 0xb6, 0xcb, 0x17, 0xfd, 0x39, 0xb6, 0xa7, 0xcd,
- 0xe5, 0x8a, 0x74, 0x48, 0xfc, 0xe4, 0x43, 0xf4, 0x16, 0xd7, 0xbe, 0xa6,
- 0x15, 0x3b, 0x12, 0x40, 0xe4, 0x6a, 0x59, 0x1c, 0xf6, 0xe7, 0xbd, 0xa2,
- 0x6a, 0x11, 0x9f, 0x86, 0x79, 0x46, 0x5b, 0xe8, 0x66, 0x5f, 0xd0, 0x98,
- 0xb1, 0xc0, 0xb1, 0x68, 0xc0, 0xa3, 0xfb, 0x71, 0x46, 0x82, 0xd1, 0xb3,
- 0x70, 0x5a, 0x95, 0xcc, 0xe3, 0x2e, 0xd2, 0x9d, 0x21, 0x1f, 0x10, 0xe5,
- 0xf0, 0x65, 0x3c, 0x40, 0xd8, 0xc1, 0x77, 0x9e, 0xe6, 0xee, 0x5f, 0x7b,
- 0xc6, 0x2f, 0x1e, 0x65, 0x14, 0xb4, 0x1d, 0x4b, 0xc7, 0x3c, 0xa8, 0x3f,
- 0xcf, 0x36, 0xb4, 0xb7, 0xe0, 0x4a, 0x6b, 0x29, 0xec, 0x7e, 0x57, 0x94,
- 0x9e, 0xa4, 0x92, 0x0a, 0x1d, 0x81, 0xb6, 0x47, 0x46, 0xbe, 0x64, 0xfa,
- 0x10, 0x48, 0x67, 0x5f, 0xf7, 0xdf, 0xa9, 0x67, 0x9b, 0xa2, 0xc5, 0xf8,
- 0xcf, 0xb7, 0xe5, 0x62, 0xfd, 0x0e, 0xe4, 0x86, 0xb1, 0x50, 0x55, 0xa0,
- 0x6c, 0xa4, 0x23, 0x9e, 0x11, 0x4d, 0xff, 0xed, 0x60, 0x63, 0xfe, 0x44,
- 0x59, 0xa8, 0x2c, 0x5e, 0xd6, 0x47, 0xac, 0x5f, 0xde, 0x14, 0x22, 0x90,
- 0x8b, 0x17, 0xfe, 0x90, 0xcc, 0xdb, 0x98, 0x79, 0x8f, 0x58, 0xad, 0x23,
- 0x8c, 0xe9, 0x9f, 0x20, 0xf1, 0x95, 0xff, 0xf3, 0x1e, 0x75, 0xbe, 0x84,
- 0x6e, 0x84, 0xdc, 0x58, 0xac, 0x44, 0x80, 0x8f, 0x6f, 0xf6, 0xb7, 0x13,
- 0x0c, 0xf2, 0xb1, 0x7f, 0xf4, 0xe8, 0xcf, 0x3f, 0xbf, 0x83, 0x75, 0x8b,
- 0xfc, 0x5d, 0x83, 0x38, 0xd1, 0xeb, 0x17, 0xfc, 0x53, 0xb1, 0x9f, 0xfb,
- 0x47, 0xac, 0x5f, 0x4e, 0x0f, 0xb5, 0x8a, 0xc4, 0x4c, 0x7c, 0xdf, 0xa1,
- 0xf5, 0xff, 0xf7, 0xe3, 0x27, 0xd2, 0x32, 0xc8, 0x7e, 0x60, 0xb1, 0x78,
- 0x36, 0x0d, 0x62, 0xfe, 0x66, 0xf4, 0x73, 0xee, 0xb1, 0x77, 0x40, 0x8b,
- 0x17, 0xff, 0xf8, 0x9c, 0x1c, 0xd6, 0x6f, 0xf9, 0xfe, 0x6b, 0x52, 0x6a,
- 0xc5, 0xff, 0xb3, 0x6d, 0x9f, 0xda, 0x14, 0x81, 0x62, 0x9d, 0x14, 0x7e,
- 0x62, 0xbf, 0xbf, 0x23, 0x72, 0xc5, 0x8a, 0x95, 0x5e, 0x5b, 0x1a, 0xe4,
- 0x37, 0x7b, 0x31, 0x8f, 0x52, 0xd0, 0xf8, 0x0c, 0x7d, 0x0b, 0xf1, 0x11,
- 0x5e, 0x0b, 0x02, 0x90, 0x58, 0xbc, 0x4d, 0xc5, 0x8b, 0xff, 0x4f, 0xb3,
- 0x50, 0x7e, 0xf3, 0xa2, 0xc5, 0xff, 0xf8, 0x9c, 0x41, 0x7f, 0xe6, 0x6a,
- 0x0f, 0xde, 0x74, 0x58, 0xaf, 0xa2, 0xe2, 0x38, 0x70, 0xc4, 0x1b, 0xf3,
- 0xf4, 0x2c, 0xe2, 0xc4, 0x61, 0xb4, 0xbd, 0x25, 0xe5, 0x8a, 0x81, 0xec,
- 0x0c, 0xf2, 0xf3, 0x6b, 0x65, 0x8b, 0xfd, 0xbb, 0xc8, 0x0f, 0x30, 0x58,
- 0xbf, 0xd9, 0xee, 0x3e, 0xf8, 0x4b, 0x17, 0x06, 0x1a, 0xc5, 0xff, 0x85,
- 0xb3, 0x7b, 0xdd, 0xee, 0xe4, 0xb1, 0x79, 0xb7, 0x8c, 0xc4, 0xc0, 0xf7,
- 0x22, 0xf8, 0xf1, 0x1a, 0x06, 0x66, 0x60, 0xd5, 0xfb, 0x4d, 0x07, 0xfa,
- 0xc5, 0xff, 0xda, 0xe7, 0xdc, 0x3f, 0xbe, 0xcc, 0x4b, 0x15, 0x27, 0xdc,
- 0xc5, 0x17, 0xef, 0x77, 0xbb, 0xfd, 0x7a, 0x89, 0x17, 0xff, 0xc5, 0xd8,
- 0x0e, 0x2e, 0xff, 0x9d, 0x33, 0xdc, 0x58, 0xbf, 0x45, 0x09, 0xd6, 0xcb,
- 0x17, 0xfe, 0x38, 0x8c, 0xcd, 0x6c, 0x26, 0x1a, 0xc5, 0xf8, 0x26, 0x6b,
- 0x02, 0x2c, 0x56, 0x23, 0xbb, 0x4a, 0xa7, 0x2b, 0xfa, 0x15, 0xf1, 0xfe,
- 0xc3, 0x58, 0xbd, 0x8e, 0x05, 0x8a, 0xc3, 0x7f, 0xe2, 0x3b, 0x46, 0x46,
- 0xf0, 0x9f, 0x0e, 0x0a, 0x1a, 0x05, 0xa8, 0xd4, 0xc3, 0x22, 0x10, 0xb3,
- 0x19, 0x16, 0x4e, 0xc8, 0x9a, 0x79, 0xbd, 0x3e, 0xeb, 0xb8, 0x70, 0xc7,
- 0x93, 0x44, 0xff, 0xa8, 0x5f, 0x7e, 0x1f, 0x6d, 0x7f, 0x3b, 0x05, 0x1d,
- 0xcf, 0x25, 0x8a, 0x7a, 0x11, 0xbd, 0x25, 0x37, 0x07, 0x0d, 0xc8, 0xe2,
- 0x03, 0x23, 0x26, 0x08, 0xf7, 0x50, 0x87, 0x9e, 0x78, 0xeb, 0x89, 0x1e,
- 0xe5, 0x83, 0x69, 0x64, 0xf0, 0x96, 0xfd, 0x22, 0x3c, 0x11, 0xae, 0x94,
- 0xe0, 0xbf, 0x2b, 0x1d, 0x1f, 0x56, 0x99, 0x82, 0xc5, 0x07, 0x75, 0xc2,
- 0x82, 0xc5, 0x2c, 0x5f, 0x0f, 0xf2, 0x1a, 0xc5, 0x49, 0xb0, 0xc0, 0xcb,
- 0xfb, 0x93, 0x14, 0x1e, 0x25, 0x8b, 0x44, 0xb1, 0x7a, 0x5b, 0xcb, 0x15,
- 0x26, 0xbf, 0x82, 0x77, 0xfd, 0xe9, 0x27, 0x06, 0x77, 0xe5, 0x8b, 0xe8,
- 0xe6, 0x20, 0x2c, 0x5b, 0x6c, 0x3d, 0xe3, 0x0e, 0x6f, 0xe6, 0x20, 0x7a,
- 0x62, 0x58, 0xa9, 0x3d, 0x78, 0xe2, 0x9a, 0x02, 0x77, 0xe4, 0x91, 0xc1,
- 0xff, 0x2f, 0x99, 0x0d, 0x5b, 0xb3, 0xb5, 0x8b, 0xfd, 0xd2, 0x75, 0x0f,
- 0xb4, 0x16, 0x2f, 0x1d, 0xc0, 0xb1, 0x7b, 0xee, 0x1a, 0xc5, 0xf3, 0x6b,
- 0x78, 0xc8, 0x22, 0x27, 0x06, 0x38, 0x6d, 0xe1, 0xdb, 0xff, 0xd0, 0x6e,
- 0x46, 0x14, 0xe7, 0xa7, 0xb8, 0x2c, 0x5e, 0x35, 0xf4, 0xb1, 0x74, 0x81,
- 0x62, 0xff, 0x80, 0x09, 0x18, 0x9b, 0x50, 0x58, 0xbe, 0xf7, 0xa4, 0xeb,
- 0x17, 0x9c, 0x71, 0x8e, 0x89, 0x2f, 0x8f, 0x70, 0x5c, 0xc3, 0xab, 0xff,
- 0x4c, 0x23, 0x0c, 0x90, 0xcc, 0x8b, 0x8b, 0x16, 0x7d, 0xd1, 0x30, 0x05,
- 0x1a, 0x8c, 0x55, 0xa1, 0xb4, 0x36, 0x5d, 0x5f, 0xd1, 0xbb, 0xdf, 0xf9,
- 0xb7, 0x8c, 0x10, 0x1e, 0x19, 0x05, 0x8b, 0xff, 0xec, 0xf3, 0xfc, 0x5f,
- 0x67, 0xef, 0x92, 0x6a, 0xc5, 0xfb, 0x5b, 0xb3, 0x6e, 0xa8, 0x8d, 0x4b,
- 0xff, 0xef, 0xb8, 0x6c, 0x5b, 0xea, 0x5e, 0x0d, 0xc5, 0x8b, 0xf0, 0xbc,
- 0x28, 0xa5, 0x62, 0xfc, 0x23, 0x7e, 0xd0, 0x58, 0xbc, 0xd9, 0xe5, 0x8b,
- 0x3c, 0x0f, 0x18, 0x65, 0x57, 0xdf, 0x7e, 0x8e, 0xb1, 0x77, 0x7c, 0x58,
- 0xac, 0x37, 0xa6, 0x92, 0x5a, 0x33, 0x65, 0x42, 0x03, 0x43, 0xc5, 0x1d,
- 0xcd, 0xfe, 0xa0, 0xce, 0x1e, 0x64, 0xbf, 0xff, 0xdd, 0x24, 0xbd, 0x18,
- 0xdd, 0x18, 0x78, 0x36, 0x3b, 0x0d, 0x62, 0xfd, 0xad, 0xd9, 0xb7, 0x54,
- 0x54, 0xa5, 0xec, 0x03, 0x2c, 0x5b, 0x75, 0x44, 0x34, 0x52, 0xc5, 0x31,
- 0xac, 0x01, 0x05, 0xcc, 0x75, 0x8b, 0x46, 0x62, 0x2d, 0xbe, 0x6e, 0xc9,
- 0x04, 0x41, 0x7d, 0xe6, 0xec, 0x0b, 0x17, 0xff, 0xb3, 0xee, 0x67, 0x9c,
- 0x85, 0x0c, 0xe2, 0xc5, 0xfe, 0xcf, 0x93, 0x7b, 0xd2, 0xb1, 0x78, 0x9a,
- 0x31, 0x91, 0x41, 0xe2, 0x43, 0x12, 0xaf, 0x46, 0xe1, 0x6e, 0x36, 0x58,
- 0xbf, 0x31, 0xf6, 0x68, 0xf5, 0x8b, 0xed, 0xd9, 0xb7, 0x54, 0x47, 0xc5,
- 0xfb, 0x72, 0x13, 0x18, 0xb1, 0x69, 0x58, 0xa9, 0x37, 0x63, 0x2a, 0xad,
- 0x22, 0x30, 0xed, 0x97, 0xfb, 0x8f, 0xf0, 0xdb, 0x50, 0x58, 0xbf, 0xcf,
- 0xae, 0xae, 0x3c, 0x3a, 0xc5, 0xcd, 0xa5, 0x8a, 0xf9, 0xe6, 0x31, 0xad,
- 0xf6, 0x79, 0xc2, 0x8b, 0x17, 0x7c, 0x4b, 0x17, 0xfc, 0x31, 0x7b, 0x99,
- 0x07, 0xfa, 0xc5, 0x0c, 0xf4, 0x9c, 0x62, 0xee, 0xf8, 0xb1, 0x63, 0x56,
- 0x2b, 0x0d, 0x64, 0x70, 0xcd, 0xff, 0x67, 0x42, 0xce, 0x19, 0xa3, 0x56,
- 0x2f, 0xe6, 0x6d, 0xbd, 0x9b, 0xac, 0x5f, 0xfb, 0x40, 0xdf, 0xef, 0x11,
- 0x48, 0x16, 0x2a, 0x23, 0xf0, 0x11, 0x7d, 0xfe, 0x86, 0x47, 0xb1, 0x02,
- 0x36, 0x58, 0xbf, 0xc4, 0x2d, 0xcf, 0x3a, 0xdd, 0x62, 0xf7, 0xa7, 0x16,
- 0x2f, 0xfe, 0xf4, 0x24, 0xde, 0xb3, 0xee, 0x48, 0x16, 0x2c, 0x58, 0x7c,
- 0x8c, 0x39, 0x74, 0x23, 0x23, 0x75, 0xc5, 0xdd, 0x8b, 0xb2, 0x17, 0x1d,
- 0x91, 0xc5, 0x08, 0x13, 0x90, 0xb3, 0xc0, 0x13, 0x48, 0x8f, 0x90, 0xad,
- 0xf1, 0x18, 0x8e, 0xcc, 0x84, 0xd5, 0x6e, 0xba, 0xfc, 0xd3, 0x94, 0x17,
- 0xf4, 0x67, 0x1a, 0x7b, 0x82, 0xc5, 0xfd, 0xb4, 0xeb, 0x4d, 0x05, 0x8b,
- 0xef, 0xc9, 0x1a, 0xb1, 0x44, 0x7a, 0x5e, 0x2f, 0xbf, 0xb4, 0xc0, 0x6c,
- 0xd2, 0xc5, 0xf6, 0x85, 0x9b, 0x2c, 0x5f, 0xc7, 0xce, 0x63, 0x12, 0xc5,
- 0xc5, 0xb2, 0xc5, 0x49, 0xe2, 0x08, 0xb2, 0xf3, 0x14, 0x4b, 0x15, 0x88,
- 0xa6, 0xfb, 0x43, 0x10, 0xdf, 0xd9, 0xaf, 0x14, 0xf6, 0xb1, 0x7f, 0x7e,
- 0x5f, 0xa6, 0x0d, 0x62, 0xff, 0xcd, 0xb4, 0xfd, 0xf4, 0xf2, 0x75, 0x8b,
- 0xfd, 0x3a, 0xc2, 0xf6, 0x7d, 0x62, 0xec, 0x8c, 0x94, 0xfb, 0xc6, 0x43,
- 0xf8, 0x69, 0x80, 0xbb, 0xc5, 0xd1, 0xc5, 0xe6, 0x1f, 0x51, 0xaa, 0xbb,
- 0x8f, 0x29, 0xce, 0xfa, 0x33, 0x83, 0x1a, 0xc5, 0x46, 0x2b, 0x70, 0x99,
- 0x63, 0x87, 0x2d, 0xbf, 0xff, 0xc2, 0xd1, 0xad, 0xcc, 0x1c, 0xf7, 0xc3,
- 0x3c, 0x6b, 0x9a, 0xb1, 0x7b, 0x8d, 0xc5, 0x8b, 0xec, 0xd1, 0x32, 0xc5,
- 0x49, 0xbe, 0x71, 0xda, 0x82, 0x31, 0x22, 0x85, 0x2d, 0xde, 0xd9, 0x62,
- 0xf0, 0x66, 0xee, 0xb1, 0x7e, 0xef, 0xb8, 0x67, 0x96, 0x28, 0x8f, 0x97,
- 0x83, 0x22, 0x21, 0xbf, 0xfd, 0x1a, 0x8d, 0x0e, 0x3f, 0x61, 0xc6, 0xdd,
- 0x7a, 0xfe, 0x39, 0x62, 0xff, 0xc2, 0x6d, 0x40, 0xb3, 0x93, 0xa5, 0x8b,
- 0xed, 0xd9, 0xb7, 0x54, 0x58, 0xe5, 0xfa, 0x7e, 0x4c, 0x62, 0xc5, 0xc2,
- 0xd2, 0xc5, 0x68, 0xfc, 0x4e, 0x62, 0xc5, 0x17, 0xfb, 0x1c, 0xb6, 0xf6,
- 0x7d, 0x62, 0xe6, 0xe2, 0xc5, 0xfd, 0xb1, 0x9a, 0xd6, 0x69, 0x62, 0xf1,
- 0xf9, 0x2b, 0x15, 0x03, 0xe5, 0x61, 0x71, 0x18, 0xdf, 0xf1, 0x31, 0xbf,
- 0x79, 0x2d, 0x96, 0x2f, 0xff, 0xf6, 0x17, 0xb9, 0xd7, 0x86, 0x4e, 0x81,
- 0x1c, 0xff, 0xce, 0x8b, 0x17, 0xf1, 0x7b, 0x42, 0x93, 0xac, 0x5f, 0xff,
- 0x89, 0x8d, 0xeb, 0xe3, 0x64, 0xa1, 0x9f, 0x73, 0xac, 0x54, 0xa3, 0xbd,
- 0x9a, 0x44, 0x5d, 0x7f, 0x01, 0xbd, 0xc9, 0x35, 0x62, 0xf8, 0xd3, 0x0b,
- 0x75, 0x8b, 0x62, 0xc5, 0x1a, 0x6d, 0xfa, 0x13, 0x5f, 0xe7, 0xf4, 0xe8,
- 0xdf, 0xba, 0xc5, 0xff, 0xf4, 0x36, 0x8d, 0x53, 0x1a, 0x6d, 0xbe, 0xba,
- 0xf5, 0xfc, 0x72, 0xc5, 0xff, 0x67, 0x49, 0x87, 0x70, 0xcf, 0x2c, 0x56,
- 0x26, 0xc4, 0xec, 0xcc, 0x48, 0x03, 0x42, 0x68, 0xbf, 0x67, 0x43, 0x22,
- 0xe2, 0xc5, 0xcf, 0x05, 0x8b, 0xfd, 0x85, 0xfc, 0xf4, 0x8d, 0x62, 0xfd,
- 0x9d, 0x3e, 0xd0, 0x58, 0xb7, 0x9c, 0xf7, 0x08, 0xca, 0x86, 0x89, 0x9c,
- 0x73, 0xbf, 0xe8, 0x3f, 0x8c, 0xd4, 0xfe, 0x56, 0x2f, 0xff, 0xcf, 0xc3,
- 0x3b, 0x06, 0x74, 0x7f, 0x4e, 0x14, 0x16, 0x2f, 0xcf, 0xef, 0x3f, 0x96,
- 0x2f, 0xff, 0xc2, 0x26, 0x37, 0xc6, 0xc9, 0x43, 0x3e, 0xe7, 0x58, 0xbe,
- 0xd6, 0xb2, 0x39, 0x62, 0xed, 0xf7, 0x58, 0xbf, 0x68, 0x0f, 0xf9, 0x58,
- 0xae, 0xa9, 0xbc, 0x40, 0xeb, 0x16, 0x0e, 0x50, 0xca, 0xdc, 0x26, 0x10,
- 0xd5, 0xfd, 0xcc, 0xf4, 0x33, 0x8b, 0x17, 0xf0, 0xf0, 0xef, 0xf9, 0x58,
- 0xbe, 0xd6, 0x64, 0x4b, 0x15, 0x27, 0xa1, 0x85, 0xb6, 0x8c, 0x96, 0x49,
- 0x3e, 0xd0, 0x8e, 0x81, 0x70, 0xd9, 0xb2, 0x15, 0xe6, 0x97, 0x3c, 0x26,
- 0x22, 0x2e, 0x3c, 0x65, 0x1f, 0x8e, 0x41, 0x91, 0xca, 0x18, 0xdc, 0x8e,
- 0x6b, 0xcc, 0xa6, 0x3f, 0x5f, 0xfa, 0x34, 0xfc, 0xb8, 0xca, 0x45, 0xba,
- 0xc5, 0xde, 0xc5, 0x8b, 0x46, 0xeb, 0x14, 0x16, 0x1f, 0x97, 0x68, 0x8e,
- 0x2f, 0x79, 0xf5, 0x12, 0xc5, 0xf4, 0x3c, 0x21, 0xac, 0x51, 0xa7, 0x85,
- 0xd8, 0xf5, 0xfe, 0xce, 0x8f, 0xde, 0x66, 0xcb, 0x17, 0xff, 0xfb, 0x03,
- 0x13, 0x17, 0x4e, 0x18, 0xdb, 0x45, 0x07, 0x10, 0x5d, 0x62, 0xa3, 0x64,
- 0x50, 0xfc, 0xda, 0xff, 0xff, 0xfd, 0xfc, 0x67, 0xe7, 0xf0, 0x1d, 0x79,
- 0x83, 0xc3, 0xbf, 0x70, 0x29, 0x34, 0x0b, 0x17, 0xf1, 0x30, 0x7e, 0xcf,
- 0xac, 0x50, 0x51, 0x16, 0x71, 0x42, 0x16, 0xe3, 0x9a, 0xb1, 0x41, 0x53,
- 0xc6, 0x8d, 0x45, 0xb7, 0xe2, 0xcf, 0xb7, 0x96, 0x2f, 0x46, 0xb0, 0xa0,
- 0x16, 0x28, 0x2a, 0x79, 0xf1, 0xa8, 0x9e, 0xff, 0xa3, 0x70, 0xa8, 0xb3,
- 0x45, 0x20, 0x58, 0xb0, 0xd6, 0x28, 0x28, 0x7a, 0x81, 0x62, 0x15, 0xfe,
- 0x0a, 0x7f, 0x01, 0x3a, 0xe2, 0xc5, 0xff, 0x82, 0xa1, 0x6c, 0x00, 0x91,
- 0xfc, 0x41, 0x16, 0x2f, 0xec, 0xde, 0x7c, 0xfd, 0x16, 0x2f, 0xfd, 0x81,
- 0xf3, 0x1f, 0x9e, 0xc8, 0xf5, 0x8a, 0xf9, 0xf9, 0x11, 0x85, 0xef, 0x88,
- 0x6b, 0x17, 0x3e, 0xeb, 0x17, 0xfe, 0x6e, 0xc0, 0xde, 0x01, 0x85, 0x05,
- 0x8b, 0xfe, 0xe1, 0x4c, 0xc7, 0xea, 0x4e, 0xb1, 0x70, 0x5b, 0x8d, 0xd6,
- 0x2f, 0xfc, 0x7e, 0x14, 0xcf, 0x67, 0x70, 0x2c, 0x5f, 0xf1, 0x4f, 0xd9,
- 0xf8, 0xfd, 0x16, 0x2c, 0x7e, 0xa8, 0xd6, 0x8d, 0xce, 0xe4, 0x8c, 0xc3,
- 0xfb, 0xe7, 0xe7, 0x25, 0x62, 0xb0, 0xfb, 0x3e, 0x95, 0x7f, 0x64, 0x21,
- 0xa1, 0x05, 0x56, 0x2b, 0x64, 0xf5, 0xc7, 0x1c, 0x19, 0x10, 0xdf, 0xf4,
- 0xc4, 0xfe, 0xe3, 0x94, 0x4b, 0x17, 0xfd, 0xc2, 0x99, 0xec, 0xee, 0x05,
- 0x8b, 0xff, 0xa4, 0x1f, 0x8f, 0x73, 0xfb, 0x8d, 0xda, 0xc5, 0xff, 0x4e,
- 0x98, 0xe5, 0x9d, 0xf9, 0x62, 0xb7, 0x44, 0x11, 0xd2, 0x6e, 0xcd, 0x96,
- 0x2e, 0x1c, 0xac, 0x51, 0x86, 0xbc, 0x20, 0xc5, 0x39, 0xfb, 0x89, 0x4e,
- 0xff, 0xe6, 0x21, 0x67, 0xdd, 0xb6, 0x29, 0x58, 0xbf, 0xf7, 0xdf, 0xa9,
- 0x9b, 0x96, 0x7f, 0x16, 0x2f, 0xe0, 0x71, 0xbd, 0xe6, 0x58, 0xa3, 0x4f,
- 0xc1, 0x90, 0xaf, 0xf7, 0x26, 0x23, 0xcf, 0xb8, 0xb1, 0x71, 0xf7, 0x58,
- 0xbf, 0xe6, 0x1b, 0xf7, 0x0f, 0x3e, 0x96, 0x2f, 0xfb, 0x40, 0x2c, 0x8a,
- 0x0f, 0x12, 0xc5, 0xff, 0xb6, 0x7d, 0xfe, 0xe3, 0x1e, 0x06, 0xb1, 0x52,
- 0x7f, 0xae, 0x77, 0x43, 0x5d, 0xeb, 0xc2, 0x1d, 0xc7, 0x9e, 0x3e, 0xfd,
- 0x1b, 0x9c, 0xeb, 0xf1, 0x99, 0x00, 0x84, 0xa1, 0x65, 0xc2, 0x2f, 0x1a,
- 0xf4, 0x19, 0x09, 0x0b, 0x7b, 0xf7, 0xde, 0x4b, 0xcb, 0x17, 0xf6, 0x13,
- 0x77, 0x0e, 0x2c, 0x5f, 0xb2, 0x3f, 0x8d, 0xd1, 0x62, 0xc1, 0xe8, 0xf6,
- 0xf8, 0x5d, 0x71, 0x1a, 0xb1, 0x7f, 0x77, 0xf7, 0x92, 0xd9, 0x62, 0xec,
- 0x1a, 0xc5, 0x0d, 0x30, 0x9c, 0x84, 0x13, 0x14, 0x88, 0x63, 0xa1, 0x7d,
- 0xfb, 0xec, 0x79, 0x25, 0x8b, 0xee, 0x7d, 0xc3, 0x58, 0xbf, 0xfa, 0x28,
- 0xf7, 0xdb, 0xf9, 0x11, 0x60, 0x6b, 0x17, 0xe6, 0xd4, 0x73, 0x7d, 0x62,
- 0xfd, 0xc9, 0xf3, 0xf4, 0x58, 0xad, 0xcf, 0x57, 0xc5, 0x77, 0x7f, 0xeb,
- 0x17, 0xe9, 0x0f, 0xd9, 0xf5, 0x8b, 0x8c, 0xc5, 0x8b, 0xe1, 0xe7, 0x7e,
- 0x58, 0xa9, 0x37, 0x8e, 0x31, 0x5d, 0x53, 0xaa, 0xc2, 0x73, 0x49, 0x1e,
- 0x14, 0x01, 0x72, 0x32, 0x18, 0xe3, 0x2d, 0xff, 0x46, 0x9a, 0xdb, 0xc5,
- 0x31, 0xa7, 0x6b, 0x17, 0xf1, 0x48, 0x21, 0xbe, 0xcb, 0x17, 0xff, 0x4c,
- 0x84, 0xfe, 0x30, 0xf3, 0x0e, 0xb1, 0x77, 0xb9, 0x11, 0xfa, 0x7c, 0xc2,
- 0xdb, 0xac, 0x5e, 0x04, 0x6f, 0xf5, 0x8a, 0x0b, 0x66, 0xdb, 0x82, 0x77,
- 0xf6, 0xb6, 0xdf, 0xed, 0x1e, 0xb1, 0x7c, 0x2e, 0x7f, 0x16, 0x2f, 0xff,
- 0x3f, 0xc4, 0x3f, 0xce, 0xff, 0x13, 0x18, 0xb1, 0x5a, 0x46, 0x5b, 0x13,
- 0x91, 0xa7, 0x88, 0xef, 0xff, 0x60, 0x4c, 0xdf, 0xdd, 0xc3, 0x08, 0x0c,
- 0xb1, 0x7f, 0xff, 0xf3, 0x97, 0x4c, 0x19, 0x33, 0x74, 0xc8, 0xff, 0x47,
- 0xbf, 0x8a, 0x40, 0xb1, 0x79, 0xc4, 0x05, 0x8b, 0xff, 0xd9, 0xd1, 0xb3,
- 0x53, 0xe7, 0xdd, 0xc6, 0xb1, 0x6e, 0xe3, 0xd1, 0xc1, 0x13, 0xc1, 0x0e,
- 0xde, 0x3b, 0xe9, 0x62, 0xb0, 0xf5, 0xc0, 0x75, 0x7b, 0x18, 0x96, 0x2f,
- 0x7e, 0x62, 0x58, 0xb9, 0xfc, 0xe6, 0xe5, 0x86, 0xee, 0x80, 0xd6, 0x2f,
- 0xf6, 0xc2, 0x1f, 0xf3, 0xa7, 0x16, 0x2f, 0xfe, 0xc0, 0xf8, 0x59, 0x14,
- 0x04, 0x5e, 0x58, 0xbe, 0x84, 0x7b, 0x9d, 0x62, 0xfb, 0x8c, 0xd1, 0xeb,
- 0x17, 0xdf, 0xfc, 0xc7, 0xac, 0x5f, 0xb3, 0xf1, 0xee, 0x4c, 0x7e, 0x3e,
- 0x26, 0x30, 0x96, 0xb6, 0x4c, 0xf0, 0x8e, 0x3a, 0x42, 0xde, 0xff, 0xfd,
- 0xbe, 0x74, 0x7d, 0x47, 0x36, 0xd1, 0xda, 0xcf, 0xf1, 0x62, 0xb1, 0x13,
- 0x0c, 0x71, 0x7e, 0x88, 0xef, 0xae, 0x2c, 0x5f, 0xf7, 0xdf, 0xdd, 0xc1,
- 0xfd, 0xc5, 0x8b, 0xff, 0xff, 0x82, 0x16, 0x37, 0x42, 0xce, 0x9f, 0xc2,
- 0xc7, 0xd3, 0x77, 0x0e, 0x2c, 0x6e, 0x6e, 0xef, 0xf6, 0x6c, 0xcf, 0xbe,
- 0x12, 0xc5, 0x62, 0x2e, 0x7a, 0x42, 0x1a, 0xfc, 0xcf, 0xbe, 0x12, 0xc5,
- 0xf3, 0xef, 0x84, 0xb1, 0x74, 0xf3, 0xa9, 0xe4, 0xb1, 0x3d, 0xff, 0xef,
- 0xcf, 0x79, 0xb1, 0x08, 0x5e, 0x9f, 0xac, 0x5f, 0xf3, 0xef, 0xf7, 0xf7,
- 0x1b, 0xb5, 0x8b, 0xec, 0x1e, 0x7f, 0x74, 0x43, 0xfd, 0x32, 0xb1, 0x36,
- 0x1d, 0x39, 0x14, 0x2d, 0x6f, 0xf6, 0xee, 0x1e, 0x44, 0xd1, 0xeb, 0x15,
- 0xa3, 0xed, 0xf9, 0xa5, 0xff, 0xff, 0x8b, 0x0e, 0x42, 0x01, 0xb1, 0xee,
- 0x43, 0xcd, 0x83, 0x13, 0x6c, 0xb1, 0x41, 0x45, 0x70, 0x13, 0x2b, 0xb3,
- 0x08, 0xaf, 0xff, 0xf4, 0x87, 0xfc, 0xd3, 0x1f, 0x3d, 0xfc, 0xc3, 0xe6,
- 0xeb, 0x17, 0xff, 0xb9, 0xbb, 0x37, 0x4d, 0x63, 0xfe, 0x46, 0xb1, 0x7f,
- 0xfb, 0x02, 0x16, 0x74, 0x2c, 0x01, 0xe6, 0x0b, 0x15, 0xba, 0x26, 0x22,
- 0x4c, 0xa9, 0x4c, 0x7b, 0x21, 0xf3, 0x7f, 0x16, 0x7b, 0x98, 0x1a, 0xc5,
- 0xf8, 0x36, 0x22, 0x95, 0x8b, 0x09, 0x62, 0xd0, 0xea, 0x6e, 0x78, 0x4f,
- 0x66, 0xed, 0x12, 0x1a, 0x67, 0xa8, 0xd1, 0x97, 0xe7, 0x30, 0xba, 0xc8,
- 0xcc, 0x37, 0x3b, 0x78, 0xe1, 0x23, 0xd6, 0xa2, 0x2a, 0xd4, 0x7d, 0x9f,
- 0x97, 0x42, 0x51, 0xac, 0x8a, 0x16, 0xf7, 0x77, 0xc5, 0x8b, 0xda, 0x14,
- 0x16, 0x2d, 0xf9, 0x36, 0xee, 0x33, 0x7f, 0xdb, 0x3f, 0xe2, 0x68, 0x3f,
- 0xd6, 0x2f, 0xe0, 0x16, 0x6c, 0x64, 0x16, 0x2f, 0x81, 0x1c, 0x2f, 0x2c,
- 0x56, 0x1e, 0xbe, 0x8c, 0x2f, 0xf7, 0x4f, 0xb8, 0xff, 0x9c, 0x58, 0xbf,
- 0xff, 0xe1, 0x0b, 0xb2, 0xce, 0x9d, 0x47, 0x9e, 0x86, 0x7f, 0xed, 0x05,
- 0x8b, 0xfe, 0x3f, 0x3f, 0x9e, 0x29, 0x3a, 0xc5, 0xe2, 0xce, 0x12, 0x29,
- 0x63, 0x9b, 0x29, 0x93, 0x10, 0xe9, 0x0d, 0xbb, 0xff, 0xda, 0xd4, 0xed,
- 0x81, 0xf7, 0x0f, 0x08, 0x6b, 0x17, 0xd9, 0x84, 0x6a, 0xc5, 0xff, 0x9c,
- 0xdc, 0x83, 0xb7, 0x4f, 0xba, 0xc5, 0xa5, 0xd1, 0x63, 0xa4, 0xff, 0x91,
- 0x5f, 0x98, 0xd8, 0xe7, 0x35, 0x62, 0xa5, 0x53, 0x6b, 0xc6, 0x63, 0xf8,
- 0x6d, 0x91, 0xa5, 0xfe, 0x2f, 0x46, 0xcd, 0xe1, 0x4a, 0xc5, 0xfd, 0x02,
- 0xce, 0xfc, 0xcb, 0x17, 0xf0, 0xfc, 0x6b, 0x90, 0xd6, 0x2a, 0x51, 0x2a,
- 0xc7, 0x02, 0x2e, 0xbe, 0x3b, 0x87, 0xc5, 0x8b, 0xfc, 0xdb, 0x7b, 0x8c,
- 0xd1, 0xeb, 0x15, 0xb1, 0xed, 0xf4, 0x24, 0xbf, 0xbe, 0xf1, 0x33, 0x41,
- 0x62, 0xe3, 0xc1, 0x62, 0xe7, 0xd6, 0xe7, 0x8c, 0x61, 0x75, 0xff, 0xa4,
- 0xfb, 0xfd, 0xfd, 0x98, 0x75, 0x8b, 0xee, 0x1d, 0xc0, 0xb1, 0x5f, 0x3e,
- 0x20, 0x1f, 0xdf, 0xfc, 0xe5, 0xb6, 0x6f, 0x3d, 0x05, 0x3c, 0x58, 0xbe,
- 0xd6, 0xd2, 0x6a, 0xc5, 0x9d, 0x62, 0xe6, 0x37, 0x0d, 0xb7, 0x89, 0x6a,
- 0x51, 0x96, 0x32, 0x22, 0x7d, 0xbf, 0xd9, 0xbc, 0xc7, 0xec, 0xc4, 0xb1,
- 0x7f, 0x8a, 0x66, 0x3f, 0x52, 0x75, 0x8b, 0xfe, 0x92, 0xdd, 0xbc, 0xc6,
- 0xf5, 0x23, 0xec, 0xe1, 0xbd, 0xff, 0xe2, 0xcf, 0x99, 0xce, 0x08, 0xfc,
- 0x6e, 0xd6, 0x2f, 0x81, 0x8e, 0xcb, 0x17, 0x80, 0xe6, 0x2c, 0x5f, 0xd8,
- 0x59, 0xd1, 0xf4, 0xb1, 0x7f, 0xfe, 0x73, 0x8e, 0x7f, 0x9d, 0x23, 0xdc,
- 0x87, 0x9b, 0x2c, 0x5f, 0xa4, 0xbd, 0xc7, 0xdd, 0x11, 0x1f, 0x2e, 0xbe,
- 0x09, 0x3f, 0xe2, 0xc5, 0x1a, 0x9e, 0x4e, 0xea, 0x2c, 0x9a, 0x02, 0x1f,
- 0x42, 0x98, 0x21, 0xfd, 0xff, 0x36, 0xb6, 0xfb, 0xe6, 0xa2, 0x58, 0xbf,
- 0xf9, 0x98, 0x81, 0xcc, 0x8f, 0x89, 0x99, 0x62, 0xff, 0xff, 0xfe, 0x7f,
- 0xc7, 0xb9, 0x67, 0xbd, 0x3b, 0x0c, 0xa6, 0x41, 0xe8, 0x61, 0x13, 0x41,
- 0x62, 0xff, 0xb3, 0xd8, 0x76, 0xd3, 0xc4, 0xb1, 0x58, 0x8c, 0x12, 0x84,
- 0x45, 0x6e, 0x9b, 0x44, 0x47, 0x7e, 0x8c, 0x1e, 0xff, 0x48, 0x82, 0xe5,
- 0x3e, 0xe2, 0xc5, 0xfa, 0x1c, 0xdb, 0x03, 0x58, 0xb1, 0x2c, 0x5f, 0xfc,
- 0x72, 0x63, 0x78, 0xe2, 0xe6, 0x47, 0xac, 0x56, 0x1e, 0xcb, 0x88, 0xdf,
- 0xbb, 0x80, 0x9b, 0xcb, 0x16, 0x91, 0x9e, 0x57, 0x88, 0x2f, 0x66, 0xb6,
- 0x58, 0xbc, 0xc5, 0x12, 0xc5, 0x7c, 0xdd, 0xb0, 0xf5, 0xe6, 0x6d, 0xd5,
- 0x16, 0x81, 0x7f, 0xff, 0xb0, 0x73, 0xbb, 0x96, 0xdc, 0xdf, 0xee, 0x31,
- 0xe1, 0x2c, 0x5f, 0x9b, 0x5b, 0x60, 0x6b, 0x17, 0x98, 0x30, 0x9d, 0x51,
- 0x19, 0xbb, 0x15, 0xfc, 0x09, 0x29, 0xf7, 0x16, 0x2f, 0x6a, 0x7c, 0xb1,
- 0x7f, 0x48, 0xbc, 0x4f, 0xd1, 0x62, 0xfe, 0xf7, 0x30, 0xd7, 0xd4, 0x47,
- 0x99, 0xa1, 0xda, 0x95, 0x5f, 0xfb, 0x43, 0x38, 0x6c, 0x5b, 0x90, 0x6a,
- 0x16, 0xc0, 0x3a, 0x31, 0xe6, 0xfd, 0xbf, 0x3d, 0x9a, 0x58, 0xbf, 0xbd,
- 0xd7, 0x0d, 0x7d, 0x2c, 0x5e, 0x83, 0x81, 0x62, 0xff, 0xbb, 0xf4, 0x9b,
- 0x1e, 0xe2, 0x1a, 0xc5, 0xfc, 0xfe, 0xfb, 0x11, 0xab, 0x15, 0x28, 0xe5,
- 0x72, 0xa8, 0x8c, 0x58, 0x77, 0x87, 0xf7, 0xdf, 0x26, 0x8f, 0x58, 0xbc,
- 0x21, 0x69, 0x62, 0xf1, 0x4e, 0x96, 0x2e, 0xd4, 0x51, 0x1b, 0xae, 0x0f,
- 0x5f, 0xff, 0xee, 0x31, 0x7e, 0x7a, 0x7f, 0x3d, 0x8c, 0x5b, 0xe0, 0xd6,
- 0x2f, 0xff, 0xf3, 0xcf, 0x9f, 0xf3, 0xcf, 0xe7, 0x35, 0x9b, 0xe7, 0x96,
- 0x2f, 0xfe, 0x90, 0x70, 0xb2, 0x3c, 0x73, 0xee, 0x2c, 0x59, 0x89, 0x14,
- 0xfc, 0x60, 0xb6, 0xa5, 0x32, 0xff, 0xc6, 0x11, 0x7f, 0x6d, 0xd6, 0x28,
- 0x4e, 0xcb, 0x17, 0xf6, 0x74, 0x98, 0x4e, 0x96, 0x2a, 0x55, 0x27, 0xe2,
- 0xfb, 0xc6, 0xbc, 0xc5, 0xe4, 0x69, 0x7e, 0x1c, 0xc4, 0xe7, 0x58, 0xbf,
- 0x83, 0x2c, 0xd8, 0xc8, 0x2c, 0x5f, 0xef, 0x73, 0xa9, 0x91, 0xd9, 0xc5,
- 0x8b, 0xf6, 0x73, 0xd9, 0xba, 0xc5, 0xf8, 0x78, 0x06, 0x95, 0x8b, 0xff,
- 0xff, 0x36, 0xa1, 0xc7, 0x1e, 0x6b, 0x67, 0xe7, 0xd8, 0x1c, 0xc2, 0x58,
- 0xa8, 0x22, 0xf3, 0x0a, 0x78, 0x4f, 0x4e, 0x9a, 0xbb, 0x18, 0x8a, 0x1e,
- 0xf7, 0xed, 0x8e, 0xcc, 0x4b, 0x17, 0xfd, 0xdf, 0xe7, 0xa7, 0xfb, 0x68,
- 0xf5, 0x8b, 0xfd, 0xd3, 0xf8, 0x5b, 0x3f, 0x16, 0x2f, 0xf0, 0x31, 0xf9,
- 0xc9, 0x02, 0xc5, 0x49, 0xf4, 0xb1, 0xb5, 0x4a, 0x3c, 0xb0, 0xa3, 0x90,
- 0xaa, 0xbf, 0xf0, 0xe3, 0xb3, 0x83, 0xfb, 0xeb, 0x65, 0x8b, 0xff, 0xec,
- 0x0f, 0xc7, 0x9c, 0xf7, 0xf3, 0x0b, 0x75, 0x8a, 0x94, 0x4a, 0x7d, 0x12,
- 0xfe, 0xe9, 0xac, 0xf3, 0x76, 0xb1, 0x7f, 0xbb, 0xfe, 0x6e, 0x59, 0xb2,
- 0xc5, 0xe0, 0xa0, 0x56, 0x34, 0x58, 0xbe, 0xc2, 0x83, 0xac, 0x5f, 0xfd,
- 0x9a, 0xd3, 0x40, 0xc2, 0x6f, 0x71, 0x62, 0xa4, 0xf9, 0xa0, 0x43, 0x5a,
- 0x45, 0x97, 0xa1, 0x23, 0x7f, 0xb4, 0x01, 0x64, 0x52, 0x75, 0x8a, 0x94,
- 0xd1, 0x5e, 0x1d, 0x0c, 0x51, 0x7f, 0xa2, 0xfc, 0xfb, 0xf3, 0x12, 0xc5,
- 0x4b, 0x6f, 0x27, 0xb1, 0x2c, 0x25, 0x7f, 0x8e, 0x1b, 0x99, 0x08, 0x93,
- 0x5a, 0xf7, 0x8d, 0x71, 0xe5, 0x31, 0xc7, 0xc7, 0x91, 0x11, 0xce, 0xa5,
- 0x9b, 0x1e, 0x35, 0x7f, 0xca, 0x97, 0x64, 0xd2, 0x8e, 0x03, 0x91, 0x93,
- 0x7a, 0x18, 0xe2, 0x22, 0xe9, 0x1b, 0xb1, 0x86, 0x77, 0xff, 0xa4, 0xb7,
- 0x1f, 0xe7, 0xbf, 0xcf, 0x4c, 0x58, 0xbf, 0xff, 0xfc, 0xff, 0x11, 0x33,
- 0x74, 0xdf, 0xef, 0xec, 0x3f, 0x1f, 0x08, 0x0c, 0xb1, 0x7f, 0xc4, 0x3e,
- 0x30, 0xdb, 0xb2, 0x58, 0xbf, 0xfe, 0xee, 0x05, 0x2c, 0x37, 0xdf, 0x3e,
- 0xde, 0x58, 0xa8, 0x26, 0x01, 0x8e, 0xee, 0x73, 0x60, 0x2c, 0x5e, 0x1f,
- 0xe5, 0x62, 0xfb, 0x3b, 0xf3, 0x2c, 0x5b, 0x9d, 0x4f, 0x00, 0x87, 0x6c,
- 0x2d, 0x1f, 0xdf, 0x94, 0xad, 0x8b, 0x17, 0xff, 0x87, 0xf9, 0x97, 0xf7,
- 0x1c, 0xbb, 0x82, 0xc5, 0x84, 0x33, 0xdb, 0x21, 0x1b, 0xb0, 0xeb, 0x17,
- 0xff, 0xc6, 0xbe, 0xb3, 0xbf, 0x7d, 0xcc, 0x91, 0xca, 0xc5, 0xcc, 0x4b,
- 0x17, 0x9c, 0xb1, 0x62, 0xff, 0xdc, 0xfc, 0x9f, 0xdc, 0x26, 0xef, 0x63,
- 0x63, 0x01, 0x6b, 0xff, 0x77, 0xd3, 0xf1, 0xef, 0xe2, 0x93, 0xac, 0x56,
- 0x26, 0x3d, 0xdc, 0x20, 0xd9, 0x5a, 0xf4, 0xec, 0xeb, 0x15, 0x2b, 0x85,
- 0x19, 0x1a, 0x69, 0xb0, 0xaa, 0x78, 0x41, 0xe8, 0x9d, 0xa3, 0x35, 0x23,
- 0x5b, 0xfa, 0x2f, 0xc8, 0x6c, 0x4b, 0x17, 0xe8, 0xa1, 0x3a, 0xd9, 0x62,
- 0xa4, 0xf6, 0xb6, 0x2f, 0xbf, 0xff, 0xed, 0x60, 0xc9, 0x9b, 0xa7, 0x32,
- 0x3f, 0xc5, 0x99, 0xa8, 0x96, 0x2f, 0xc5, 0xee, 0xa7, 0xd9, 0x62, 0xf8,
- 0x47, 0x6f, 0x2c, 0x5f, 0xff, 0x9f, 0x62, 0xce, 0x9f, 0x7f, 0x77, 0x09,
- 0x28, 0x96, 0x2a, 0x51, 0x50, 0x32, 0xcf, 0x91, 0xdf, 0xff, 0xf9, 0xf4,
- 0xf9, 0xd3, 0x36, 0xc7, 0xf4, 0x9c, 0x98, 0xdf, 0xba, 0xc5, 0xff, 0xd0,
- 0x96, 0x87, 0x57, 0x89, 0xf0, 0x96, 0x2f, 0xbc, 0x6b, 0xee, 0xb1, 0x7f,
- 0xff, 0x9e, 0x4b, 0xda, 0x9f, 0xb7, 0x0b, 0x01, 0xcf, 0x3a, 0xc5, 0xff,
- 0x3f, 0xa4, 0xef, 0xe1, 0x4a, 0xc5, 0xfe, 0x98, 0x75, 0x8a, 0x3d, 0xc9,
- 0x62, 0xd9, 0xc3, 0xf1, 0xf1, 0xc5, 0xff, 0x84, 0xdd, 0xf0, 0xb3, 0xa3,
- 0x41, 0x62, 0xff, 0xa2, 0x29, 0x3f, 0xe7, 0xa1, 0xd6, 0x2f, 0xff, 0x41,
- 0xf4, 0x06, 0xf6, 0x45, 0x07, 0xf2, 0xc5, 0xfb, 0xcf, 0x1d, 0x9b, 0x2c,
- 0x5e, 0x0a, 0x46, 0xe1, 0x45, 0x8b, 0xff, 0xb0, 0x3e, 0xad, 0xe2, 0xcd,
- 0x98, 0x96, 0x2f, 0xf7, 0x33, 0xef, 0xc1, 0x6c, 0xb1, 0x7c, 0xf1, 0xd9,
- 0xb2, 0xc5, 0xcd, 0xdf, 0x54, 0x7c, 0x46, 0xa2, 0xcd, 0x8a, 0xf8, 0x8d,
- 0xe3, 0x5b, 0x9b, 0xb5, 0x8a, 0xc4, 0xfd, 0xbb, 0x3c, 0xe4, 0x68, 0x7e,
- 0x5f, 0xb3, 0x8d, 0x71, 0xdb, 0x72, 0xfe, 0xdb, 0x22, 0x45, 0xf9, 0x29,
- 0x43, 0x3f, 0x84, 0xfe, 0x94, 0x6f, 0x7f, 0xdf, 0x7f, 0x71, 0xbb, 0x00,
- 0x6b, 0x17, 0x86, 0xdb, 0x2c, 0x5d, 0xad, 0xb7, 0x3d, 0xa3, 0x0f, 0x2f,
- 0xff, 0x82, 0x1e, 0x64, 0xa2, 0xea, 0x52, 0x7d, 0x62, 0xc5, 0xff, 0xed,
- 0xb4, 0xfe, 0xd8, 0x5a, 0x87, 0x23, 0xdd, 0x62, 0x99, 0x14, 0x82, 0x53,
- 0xa9, 0x5f, 0x82, 0x72, 0x2f, 0xce, 0xc4, 0x34, 0x38, 0x4a, 0x1a, 0xb7,
- 0xfd, 0x86, 0x33, 0x76, 0xcc, 0x1a, 0xc5, 0xfd, 0x9e, 0xc2, 0x68, 0x96,
- 0x2f, 0xed, 0x3e, 0xe5, 0x3f, 0x58, 0xbf, 0xe1, 0x37, 0x9a, 0x0d, 0xdc,
- 0x16, 0x2f, 0xe8, 0x45, 0xf7, 0xef, 0xcb, 0x17, 0xc6, 0x67, 0x7e, 0x58,
- 0xa9, 0x3d, 0x66, 0x31, 0xbb, 0x5c, 0x58, 0xa9, 0x4d, 0x76, 0x07, 0x58,
- 0x5b, 0xb9, 0x77, 0x21, 0x21, 0x1c, 0x41, 0x7f, 0x9c, 0x78, 0x7e, 0xb8,
- 0x35, 0x8b, 0x9b, 0x8b, 0x17, 0xf8, 0x3e, 0x78, 0xb3, 0x37, 0x58, 0xbf,
- 0x38, 0x71, 0xb8, 0x56, 0x37, 0x58, 0xbf, 0xfe, 0x16, 0xb5, 0x25, 0x86,
- 0xbf, 0xff, 0x86, 0x2c, 0x58, 0x2e, 0xb1, 0x5a, 0x3e, 0x71, 0x28, 0xdf,
- 0x4e, 0xa6, 0x25, 0x8b, 0xfd, 0x3d, 0x43, 0x62, 0x29, 0x58, 0xbc, 0x52,
- 0x75, 0x8b, 0x4a, 0xc5, 0x44, 0x6b, 0x4e, 0x39, 0x7f, 0x8e, 0x22, 0xf7,
- 0x05, 0xa5, 0x8a, 0x82, 0xa1, 0xd1, 0x9a, 0xe0, 0xb9, 0xa6, 0xba, 0x84,
- 0xf9, 0xc8, 0x80, 0x46, 0x4c, 0x31, 0xc4, 0x57, 0xef, 0xb1, 0xe4, 0x96,
- 0x2f, 0x82, 0x7e, 0x49, 0x62, 0xda, 0x58, 0xbd, 0xac, 0xc5, 0x8a, 0xd8,
- 0xf4, 0x80, 0x48, 0x10, 0x4a, 0xff, 0xfe, 0xef, 0x93, 0x0d, 0x66, 0xd3,
- 0xac, 0xf3, 0xf6, 0x1a, 0xc5, 0x8d, 0x58, 0xad, 0x8f, 0xc8, 0x97, 0xee,
- 0xe7, 0x16, 0x2f, 0xff, 0x60, 0xc9, 0x98, 0x3f, 0x77, 0x09, 0x0d, 0x62,
- 0xee, 0xe1, 0xa3, 0xe4, 0xf8, 0xc5, 0xf4, 0x50, 0x6d, 0x2c, 0x5e, 0x0b,
- 0xc7, 0x3a, 0xc5, 0x00, 0xf2, 0x04, 0x49, 0x7c, 0x3d, 0xb0, 0x35, 0x8a,
- 0x94, 0xd1, 0x32, 0x10, 0xce, 0xee, 0x22, 0x2b, 0xff, 0x82, 0x08, 0xff,
- 0x93, 0xc5, 0x1e, 0xe3, 0x58, 0xbf, 0xec, 0x3e, 0x6f, 0x3f, 0x93, 0xac,
- 0x5f, 0xfc, 0xc5, 0xbf, 0x0b, 0x39, 0xc7, 0xe8, 0xb1, 0x6f, 0x7c, 0xff,
- 0xd8, 0xe6, 0xfd, 0x91, 0x44, 0xdc, 0x58, 0xbf, 0xfe, 0xcf, 0x77, 0x09,
- 0x00, 0x24, 0x7f, 0x10, 0x45, 0x8a, 0xf9, 0xff, 0x11, 0x55, 0x6c, 0x8c,
- 0x6e, 0xe1, 0x4b, 0x4e, 0x9d, 0xdb, 0x47, 0x23, 0x7f, 0x98, 0x65, 0x30,
- 0x72, 0x58, 0xbf, 0x36, 0xdb, 0x4f, 0x6b, 0x15, 0xb1, 0xee, 0x78, 0xc6,
- 0xf8, 0x3f, 0x3e, 0xcb, 0x15, 0x27, 0x90, 0xc4, 0x77, 0xf1, 0x77, 0x0f,
- 0x08, 0x6b, 0x17, 0xe0, 0xc4, 0xda, 0x1a, 0xc5, 0xfe, 0xe3, 0xfa, 0x22,
- 0x93, 0xac, 0x51, 0x1e, 0xf7, 0x0a, 0xaf, 0xd1, 0xf8, 0x47, 0x75, 0x8a,
- 0x94, 0x6c, 0xbc, 0x23, 0x98, 0x86, 0xf8, 0xa7, 0x03, 0x58, 0xbc, 0x58,
- 0x05, 0x8b, 0xff, 0xe7, 0xeb, 0x1e, 0xfb, 0x75, 0xfe, 0x44, 0x58, 0x1a,
- 0xc5, 0xf4, 0x59, 0x9b, 0x2c, 0x5f, 0xb8, 0xfe, 0x29, 0x58, 0xbb, 0x3f,
- 0xc3, 0xcb, 0xf1, 0x25, 0x83, 0x0a, 0xa6, 0x1f, 0xa2, 0x2f, 0x8e, 0x7a,
- 0x14, 0x97, 0xf0, 0x7e, 0x29, 0x3f, 0x16, 0x29, 0x8f, 0xf4, 0x49, 0xd7,
- 0xe8, 0xbf, 0x80, 0x65, 0x8a, 0x95, 0xfb, 0x08, 0x47, 0xd1, 0x91, 0xfd,
- 0xea, 0x19, 0x9f, 0x87, 0xc9, 0x47, 0x7d, 0xd0, 0x86, 0xff, 0xff, 0xbf,
- 0x9e, 0xf3, 0x6d, 0x9e, 0x3b, 0x88, 0xa2, 0x2c, 0x0d, 0x62, 0xff, 0xcd,
- 0xaf, 0x67, 0x60, 0x66, 0x89, 0x62, 0xff, 0x8b, 0x03, 0xfe, 0x1e, 0x78,
- 0xb1, 0x7f, 0xd8, 0xf0, 0xfc, 0xfd, 0xcd, 0x58, 0xbf, 0xc4, 0xc0, 0xe6,
- 0xff, 0x78, 0x8f, 0xc8, 0x8e, 0x68, 0x69, 0xb2, 0x44, 0xd1, 0xe8, 0x59,
- 0x5f, 0xef, 0x77, 0x0c, 0xe8, 0x2f, 0xac, 0x5e, 0x1f, 0xf1, 0x62, 0xfe,
- 0xf7, 0xf2, 0x10, 0x02, 0xc5, 0xff, 0xf1, 0x60, 0xff, 0x3d, 0x3f, 0x8c,
- 0x59, 0x1e, 0xb1, 0x52, 0x98, 0x68, 0xcd, 0xf0, 0xe0, 0x87, 0x43, 0x2f,
- 0xbf, 0xc4, 0xcd, 0xd2, 0x1d, 0x00, 0xb1, 0x7f, 0xfd, 0xc9, 0x8b, 0xf3,
- 0xd0, 0xb0, 0x7f, 0x9e, 0x2c, 0x50, 0xd1, 0x13, 0xe3, 0x7b, 0xed, 0xe4,
- 0x1c, 0x58, 0xbf, 0xbe, 0xe1, 0xc7, 0x48, 0x16, 0x2f, 0xff, 0x1d, 0xfb,
- 0x87, 0x0b, 0x37, 0xf0, 0x89, 0x62, 0xff, 0x73, 0x23, 0xc0, 0xcd, 0x12,
- 0xc5, 0xff, 0xfb, 0x91, 0xee, 0x59, 0xd1, 0xb8, 0x18, 0xb1, 0xfe, 0xb1,
- 0x7f, 0xfb, 0x3d, 0xc7, 0xcd, 0x48, 0x38, 0xfd, 0x16, 0x2b, 0x13, 0xa1,
- 0xdc, 0x8e, 0x22, 0x43, 0x99, 0x7d, 0x33, 0x86, 0xf1, 0xcb, 0x57, 0xc7,
- 0x1c, 0xc1, 0x62, 0xff, 0xdf, 0xce, 0x91, 0xee, 0x21, 0xe0, 0xd6, 0x2a,
- 0x4f, 0x9f, 0xc4, 0x76, 0xf2, 0xc5, 0xef, 0xe7, 0x96, 0x2f, 0xfb, 0x82,
- 0xd4, 0x37, 0x26, 0x08, 0xb1, 0x71, 0x60, 0xcf, 0x6b, 0xc3, 0xb6, 0x66,
- 0x44, 0xc7, 0x9b, 0x2f, 0xa1, 0xc7, 0x1a, 0xc5, 0xcf, 0xc5, 0x8b, 0x01,
- 0xcd, 0xd1, 0xc8, 0xea, 0x57, 0x20, 0xf2, 0x53, 0x9b, 0xc3, 0x41, 0xa1,
- 0x72, 0x26, 0x1b, 0x9e, 0x25, 0x8b, 0x3a, 0xc5, 0xe2, 0xdd, 0xb4, 0x6a,
- 0x78, 0x31, 0x7f, 0xff, 0x68, 0xa6, 0x7b, 0xeb, 0xcf, 0x14, 0x8f, 0xf3,
- 0xe5, 0x8b, 0x9f, 0xeb, 0x17, 0xff, 0xe7, 0x37, 0x06, 0x76, 0x6d, 0xb5,
- 0x80, 0x04, 0xac, 0x5f, 0x40, 0x98, 0xc5, 0x8b, 0xf9, 0xbd, 0xcf, 0x3e,
- 0xcb, 0x17, 0xf8, 0x6c, 0x0d, 0x69, 0x80, 0xb1, 0x7d, 0xad, 0xe3, 0xc3,
- 0x58, 0xbe, 0x34, 0x2a, 0xc1, 0xac, 0x5f, 0xdf, 0xc8, 0x74, 0x69, 0x58,
- 0xac, 0x44, 0x0b, 0x14, 0xf8, 0xa6, 0x9d, 0x1c, 0x65, 0x0b, 0x5a, 0x95,
- 0x4a, 0xf8, 0x65, 0x1e, 0xbb, 0xa1, 0x76, 0x56, 0x22, 0x31, 0x46, 0x25,
- 0x7e, 0xc7, 0xfc, 0x8d, 0x62, 0xe9, 0x8f, 0x58, 0xbe, 0xd1, 0x67, 0x4d,
- 0x1e, 0x0f, 0xc9, 0xef, 0x34, 0x7b, 0xac, 0x5f, 0xf8, 0xcf, 0x1a, 0xe6,
- 0xce, 0x14, 0xac, 0x5b, 0xb5, 0x8b, 0xff, 0xce, 0xcd, 0x17, 0xbf, 0x90,
- 0xfb, 0xf4, 0x58, 0xbf, 0xfe, 0xcf, 0x73, 0x03, 0xcf, 0xbe, 0x85, 0x20,
- 0x58, 0xbf, 0xfe, 0x2c, 0xf7, 0x18, 0xfa, 0xc7, 0xfc, 0x8d, 0x62, 0xa5,
- 0x1f, 0xb1, 0xe2, 0x64, 0x99, 0xe5, 0x0b, 0xf1, 0x9e, 0x29, 0x02, 0xc5,
- 0x4a, 0x7f, 0xbd, 0x9d, 0x68, 0x7c, 0xf1, 0x9e, 0xf4, 0x3e, 0xbf, 0x4f,
- 0xb3, 0xf2, 0xb1, 0x7f, 0x9b, 0x40, 0x16, 0xe7, 0x75, 0x8b, 0xf6, 0xba,
- 0xef, 0x9d, 0x16, 0x2f, 0xf8, 0xa2, 0xfe, 0x16, 0x38, 0xd6, 0x2b, 0x0f,
- 0x98, 0x45, 0xd7, 0xff, 0x9c, 0x89, 0xbc, 0xc7, 0x2c, 0xcd, 0x2c, 0x5e,
- 0xda, 0x2c, 0x58, 0xbf, 0xfe, 0xe9, 0x9b, 0xe9, 0x9b, 0xb8, 0x72, 0x3d,
- 0xc9, 0x62, 0xa4, 0xfd, 0x58, 0x7e, 0xff, 0xe8, 0xf7, 0xcf, 0xcf, 0x4e,
- 0x7e, 0x7b, 0x58, 0xa9, 0x4f, 0x85, 0xe1, 0x37, 0x1e, 0x43, 0xf8, 0x5d,
- 0xf0, 0x82, 0xfa, 0x7d, 0x87, 0x58, 0xbf, 0xf7, 0x3f, 0x81, 0xfd, 0xc3,
- 0x2c, 0x58, 0xa0, 0x1f, 0x17, 0x42, 0x2b, 0xf7, 0x70, 0x29, 0x3a, 0xc5,
- 0xff, 0xff, 0xfe, 0x3c, 0x7b, 0xfc, 0x18, 0xc5, 0xbe, 0x77, 0x0e, 0x3f,
- 0xb8, 0xfd, 0xc0, 0xa7, 0xf2, 0xb1, 0x7f, 0x67, 0xdf, 0x35, 0x12, 0xc5,
- 0xff, 0xb3, 0xb8, 0x71, 0xfc, 0xc5, 0x8b, 0x17, 0xfb, 0x0f, 0xfc, 0x89,
- 0xa2, 0x58, 0xbf, 0x3e, 0xdf, 0x99, 0xea, 0x7e, 0x7e, 0x3e, 0xae, 0xa8,
- 0xe1, 0xc8, 0x50, 0xdf, 0x4f, 0x3a, 0x12, 0xc5, 0xf4, 0xf3, 0xa1, 0x2c,
- 0x5d, 0xd0, 0x96, 0x2f, 0xf3, 0xfb, 0x99, 0xd3, 0x36, 0x0a, 0x9f, 0x0c,
- 0x6c, 0x49, 0xc2, 0x4b, 0xff, 0xdf, 0x9e, 0xf3, 0x53, 0xe7, 0xdd, 0xc6,
- 0xb1, 0x78, 0x5a, 0x89, 0x62, 0xfb, 0x22, 0xcf, 0x0c, 0xfa, 0xb8, 0x97,
- 0x67, 0x1a, 0x71, 0xfb, 0xc2, 0x2b, 0xf0, 0xcc, 0xa9, 0x56, 0xd9, 0x85,
- 0x3f, 0x96, 0x05, 0x7f, 0x3e, 0xd2, 0x53, 0x12, 0xc5, 0xfd, 0xec, 0x8b,
- 0x82, 0x3a, 0xc5, 0xdd, 0xfe, 0x3c, 0xf7, 0x98, 0xba, 0xf9, 0xb5, 0xf1,
- 0x2c, 0x5f, 0xff, 0x3f, 0xb8, 0xfe, 0x9f, 0x70, 0xb3, 0x03, 0x58, 0xa9,
- 0x45, 0x1c, 0x0c, 0x70, 0x8e, 0xff, 0xff, 0xce, 0x59, 0xe9, 0x38, 0x62,
- 0x6d, 0xba, 0xe7, 0xdf, 0x5f, 0x65, 0x8b, 0xf1, 0xa6, 0xb7, 0xb8, 0xb1,
- 0x7f, 0xfd, 0x9b, 0x30, 0xdc, 0x5b, 0xe9, 0xc3, 0x89, 0xd6, 0x2a, 0x51,
- 0xd9, 0x8d, 0xda, 0x2b, 0xbf, 0x8e, 0xc3, 0xfb, 0x12, 0xc5, 0xcc, 0x11,
- 0x62, 0xf7, 0xdc, 0x35, 0x8b, 0xf7, 0x70, 0xe1, 0x61, 0xcd, 0xbf, 0x86,
- 0x6f, 0xfb, 0xb8, 0x72, 0x2d, 0x37, 0xb8, 0xb1, 0x7f, 0xff, 0xfd, 0x81,
- 0x3a, 0xfd, 0xfa, 0xf1, 0xc5, 0xd8, 0xff, 0x33, 0xee, 0x47, 0xb9, 0x74,
- 0x58, 0xbf, 0xff, 0xff, 0xfe, 0xcf, 0x48, 0x79, 0xe2, 0x90, 0xc2, 0x75,
- 0xfb, 0xf5, 0xe3, 0x8b, 0xb1, 0xfe, 0x67, 0xdc, 0x8f, 0x72, 0xe8, 0xb1,
- 0x7f, 0xff, 0xec, 0x72, 0x37, 0xaf, 0xdf, 0xaf, 0x1c, 0x5d, 0x9d, 0x98,
- 0x86, 0xb1, 0x7b, 0xf3, 0xac, 0x4e, 0xc0, 0xa1, 0x13, 0xc8, 0x5b, 0xdf,
- 0xff, 0xff, 0xff, 0xfe, 0xd6, 0xb1, 0xcb, 0x6e, 0xbf, 0x7e, 0xbb, 0xfd,
- 0xfe, 0xc1, 0xf5, 0x04, 0xc5, 0xd7, 0xf9, 0x9d, 0x4b, 0x07, 0xf6, 0xeb,
- 0x98, 0x1f, 0x96, 0x2f, 0xff, 0xff, 0xfb, 0xef, 0xf6, 0x0f, 0xa8, 0x26,
- 0x2e, 0xbf, 0xcc, 0xea, 0x58, 0x3f, 0xb7, 0x5c, 0xc0, 0xfc, 0xb1, 0x7f,
- 0xce, 0x2e, 0xce, 0xcc, 0x43, 0x58, 0xbf, 0xfd, 0x1e, 0xe1, 0x0d, 0xd6,
- 0x0f, 0xaf, 0xdf, 0xae, 0xe8, 0xd6, 0xe4, 0x27, 0x6f, 0xff, 0xff, 0x48,
- 0xff, 0x99, 0xd3, 0xaf, 0xdf, 0xaf, 0x1c, 0x5d, 0x9d, 0x98, 0x86, 0xb1,
- 0x7f, 0xff, 0xec, 0x29, 0xd7, 0x5f, 0xbf, 0x5e, 0x38, 0xbb, 0x3b, 0x31,
- 0x0d, 0x62, 0x86, 0xad, 0x7f, 0x12, 0xb5, 0x1d, 0xb9, 0xdc, 0xbe, 0xfb,
- 0x7f, 0xf6, 0x74, 0xe3, 0x8b, 0xb1, 0xfe, 0x74, 0xb1, 0x68, 0xba, 0xa2,
- 0x64, 0x94, 0x6b, 0x17, 0x84, 0x1a, 0x77, 0x96, 0xfc, 0x53, 0xbc, 0x0e,
- 0xb1, 0x7f, 0xfb, 0x23, 0xfe, 0x28, 0xbf, 0x91, 0x42, 0x7b, 0x58, 0xbf,
- 0xfb, 0x99, 0x17, 0xe7, 0xa6, 0x7f, 0xf2, 0xb1, 0x43, 0x46, 0x0e, 0x8a,
- 0x7c, 0xa3, 0x7f, 0x98, 0x1c, 0x3b, 0x77, 0xe5, 0x8a, 0x58, 0xbf, 0xee,
- 0x10, 0x85, 0xe8, 0x49, 0xab, 0x15, 0xd9, 0xe3, 0xf8, 0x32, 0xb1, 0x19,
- 0xec, 0x60, 0x27, 0xcb, 0xff, 0x66, 0xda, 0x99, 0xf3, 0xfe, 0x56, 0x2f,
- 0xfc, 0xf1, 0x70, 0x99, 0x87, 0xf7, 0x58, 0xbf, 0x8b, 0x39, 0xf9, 0x1a,
- 0xc5, 0x49, 0xf5, 0xe1, 0xf5, 0xff, 0xff, 0xf1, 0x4f, 0xf0, 0xb1, 0xc6,
- 0x09, 0xee, 0x1c, 0x36, 0x64, 0xb7, 0xc1, 0xac, 0x51, 0x26, 0x8b, 0xc8,
- 0x54, 0xf8, 0x82, 0xff, 0xc6, 0xbf, 0x8b, 0x21, 0xae, 0x71, 0x62, 0xff,
- 0xba, 0x0e, 0x78, 0x2d, 0x85, 0x12, 0xc5, 0xa0, 0xe7, 0xfe, 0xc8, 0x17,
- 0xff, 0x61, 0xc5, 0x06, 0x1f, 0x5f, 0x1c, 0x0b, 0x17, 0xf4, 0xc5, 0x9d,
- 0x1f, 0x4b, 0x17, 0xff, 0xa1, 0xf6, 0x86, 0xe4, 0xc1, 0x02, 0x04, 0x75,
- 0x8a, 0x94, 0x40, 0xe1, 0x85, 0xed, 0x61, 0x2c, 0x5f, 0xec, 0xf1, 0xb8,
- 0xc4, 0x05, 0x8a, 0x73, 0xcf, 0x88, 0x72, 0xa5, 0x38, 0x1f, 0x93, 0x14,
- 0x32, 0x78, 0xe1, 0x7e, 0xec, 0x7f, 0x70, 0xd6, 0x2f, 0xfe, 0x10, 0xf0,
- 0x85, 0x07, 0x1e, 0x01, 0x62, 0xa4, 0xfb, 0xdc, 0xae, 0xff, 0xe1, 0x31,
- 0xfc, 0x59, 0xb1, 0x67, 0x6b, 0x17, 0xfd, 0x9b, 0xcf, 0xde, 0x48, 0x6b,
- 0x17, 0xff, 0x7f, 0x03, 0x16, 0x3f, 0xf9, 0x3b, 0x2c, 0x5c, 0xe2, 0xd8,
- 0xff, 0xbb, 0x38, 0xad, 0x9b, 0x6a, 0x81, 0xca, 0x08, 0xc8, 0x5c, 0x6f,
- 0x2e, 0x42, 0x28, 0xce, 0x35, 0x18, 0xd1, 0xcb, 0x99, 0x90, 0x13, 0xc9,
- 0xc5, 0x1d, 0xe7, 0x23, 0x73, 0xf4, 0xa3, 0x5e, 0x90, 0xb0, 0x0c, 0x80,
- 0x24, 0x30, 0xef, 0xa2, 0x83, 0xc4, 0xb1, 0x71, 0x6c, 0xb1, 0x7c, 0x0d,
- 0x34, 0x72, 0xc5, 0x75, 0x3e, 0x38, 0xd0, 0x97, 0xb1, 0x8b, 0xfc, 0x5b,
- 0x60, 0xce, 0xfe, 0x58, 0xbf, 0xd1, 0xef, 0xb7, 0x26, 0x62, 0x58, 0xb3,
- 0x88, 0xfb, 0x03, 0x34, 0xbc, 0xfd, 0x42, 0xeb, 0x16, 0x08, 0xb1, 0x77,
- 0xc2, 0x2c, 0x5f, 0xfe, 0xce, 0x9f, 0x68, 0x01, 0xbb, 0x03, 0xf6, 0xb1,
- 0x6f, 0x49, 0xf4, 0x7c, 0x6a, 0xff, 0xfb, 0x5b, 0x4c, 0x7f, 0x0b, 0x3d,
- 0xe7, 0xd6, 0xeb, 0x17, 0xf6, 0x6d, 0xc2, 0xce, 0x8b, 0x17, 0xfa, 0x4f,
- 0x31, 0x81, 0x86, 0x1a, 0xc5, 0x41, 0x36, 0x27, 0x7c, 0x62, 0x7f, 0x2a,
- 0x84, 0x30, 0xbf, 0xff, 0x33, 0x0f, 0xf3, 0xd3, 0xf2, 0x78, 0xa3, 0xdc,
- 0x6b, 0x17, 0x7c, 0xc5, 0x8b, 0xfe, 0x36, 0x36, 0xfb, 0xe9, 0x9f, 0xa2,
- 0xc5, 0x8d, 0x58, 0xa9, 0x6e, 0xf6, 0xf2, 0xb6, 0xfb, 0x78, 0xdf, 0x63,
- 0xe1, 0x47, 0xf2, 0x86, 0x8e, 0x14, 0x92, 0xf8, 0xb6, 0x21, 0x93, 0x10,
- 0x6f, 0xff, 0xd0, 0xce, 0x31, 0x03, 0xf9, 0x3e, 0xe4, 0x81, 0x62, 0xf9,
- 0x8e, 0xd0, 0x58, 0xbf, 0xd8, 0x58, 0xfa, 0x6e, 0x8b, 0x17, 0xff, 0xec,
- 0x39, 0xc5, 0xff, 0xb3, 0x1b, 0x9a, 0xcf, 0x2c, 0x5d, 0xf7, 0xea, 0x88,
- 0x92, 0x33, 0xbd, 0x87, 0x95, 0x8b, 0xff, 0x13, 0x0c, 0xb0, 0x7f, 0x9e,
- 0x2c, 0x56, 0x1e, 0xcb, 0x8e, 0x5f, 0xed, 0xf0, 0xb0, 0x26, 0x0d, 0x62,
- 0xf1, 0x93, 0xa5, 0x8b, 0xfd, 0x87, 0x6f, 0xe7, 0x60, 0x58, 0xbf, 0xc7,
- 0x9d, 0x78, 0xa7, 0x65, 0x8b, 0xfb, 0x8e, 0x4d, 0xa3, 0x56, 0x2b, 0x63,
- 0xe2, 0x39, 0xa5, 0xf6, 0xfd, 0x9b, 0xba, 0xc5, 0xe3, 0x24, 0x0b, 0x17,
- 0xb5, 0x3c, 0x58, 0xa7, 0x3e, 0x30, 0x14, 0x78, 0x7a, 0xfb, 0xa4, 0x96,
- 0xeb, 0x17, 0xff, 0xf4, 0x96, 0x03, 0x98, 0x3f, 0xce, 0xc7, 0x11, 0x0d,
- 0x62, 0xfd, 0xd8, 0x02, 0x18, 0x1a, 0xc5, 0xff, 0xe6, 0x03, 0x7f, 0x0e,
- 0xdf, 0xce, 0xc0, 0xb1, 0x4e, 0x8f, 0x9f, 0x92, 0xb2, 0xd9, 0x17, 0xdf,
- 0x9f, 0xde, 0x98, 0x2c, 0x5d, 0x3d, 0xac, 0x5f, 0x34, 0x33, 0xa2, 0xc5,
- 0x41, 0x73, 0x6c, 0x6a, 0x86, 0xc2, 0xaf, 0x78, 0x44, 0x39, 0x06, 0x8d,
- 0x7e, 0x3c, 0xd0, 0x96, 0x28, 0x43, 0x7a, 0x32, 0x7e, 0x87, 0x51, 0xc5,
- 0x01, 0x06, 0x2f, 0xe2, 0xf4, 0xf3, 0xce, 0xb1, 0x7f, 0xfe, 0x62, 0xdf,
- 0xdc, 0xcd, 0xb9, 0x3d, 0x67, 0xa1, 0x2c, 0x5f, 0x73, 0x8e, 0x75, 0x8b,
- 0xff, 0xf0, 0xbb, 0x1e, 0xe2, 0xc8, 0xf8, 0xb1, 0x82, 0x44, 0xeb, 0x17,
- 0x3f, 0x96, 0x2f, 0xec, 0xf1, 0x4c, 0x9d, 0x62, 0xf8, 0x7f, 0x9e, 0x87,
- 0x3c, 0x3f, 0x8b, 0xdf, 0xfe, 0xc1, 0xfe, 0x7a, 0x7d, 0xc3, 0x2c, 0xdd,
- 0x62, 0xe9, 0x8b, 0x11, 0x10, 0x47, 0x77, 0xfc, 0x32, 0x98, 0x61, 0xe7,
- 0x75, 0x8b, 0xfb, 0xb1, 0x8f, 0x1b, 0x65, 0x8b, 0xfb, 0x03, 0xd6, 0x7f,
- 0x8b, 0x17, 0xff, 0xb4, 0xdb, 0xe7, 0x47, 0xd4, 0x73, 0x6d, 0x1c, 0xb1,
- 0x7f, 0xfe, 0xfb, 0xf4, 0x2c, 0x0f, 0x1f, 0xcf, 0xa6, 0x02, 0xc5, 0xe2,
- 0x91, 0xac, 0x5f, 0x43, 0x3f, 0x8b, 0x17, 0xb6, 0x11, 0x2c, 0x5b, 0x9d,
- 0x53, 0x9e, 0x93, 0x9d, 0x8c, 0x06, 0x5f, 0xba, 0xa4, 0x4a, 0xcc, 0x38,
- 0x61, 0x15, 0xff, 0xf0, 0xc9, 0x9b, 0xff, 0xc6, 0x1e, 0x61, 0xd6, 0x2b,
- 0xb4, 0x64, 0xc4, 0xf9, 0x70, 0x50, 0x28, 0xb1, 0x7c, 0xec, 0x43, 0x58,
- 0xbf, 0xbe, 0xf1, 0x33, 0x6c, 0xb1, 0x7a, 0x70, 0x0b, 0x16, 0x90, 0xaa,
- 0x23, 0x06, 0x41, 0xb9, 0x0c, 0x45, 0xf5, 0x2b, 0xac, 0x38, 0x5a, 0xeb,
- 0x5a, 0x23, 0x3c, 0x65, 0x4d, 0x2a, 0x50, 0x10, 0xb1, 0xbe, 0x7d, 0x8f,
- 0x2b, 0x17, 0xf4, 0xeb, 0x69, 0xd6, 0xcb, 0x17, 0xff, 0x89, 0x83, 0xfc,
- 0xc1, 0xcb, 0x0f, 0x2b, 0x17, 0xff, 0x67, 0x7e, 0x9c, 0xd6, 0xa6, 0x42,
- 0x2c, 0x58, 0x38, 0x91, 0x1c, 0x49, 0x16, 0x89, 0x62, 0xff, 0x6d, 0x81,
- 0xcf, 0xc4, 0x4b, 0x15, 0x27, 0x90, 0xe2, 0x75, 0x04, 0xd4, 0x32, 0x17,
- 0xdf, 0x72, 0xbf, 0x7f, 0x37, 0xc0, 0xd6, 0x2f, 0xfb, 0xa3, 0x10, 0x3f,
- 0x80, 0x65, 0x8b, 0xf3, 0x9b, 0xe7, 0xd9, 0x62, 0xff, 0xf6, 0x60, 0x0f,
- 0x31, 0x70, 0x7f, 0x6d, 0x96, 0x29, 0xd1, 0x61, 0xf3, 0xa2, 0x2a, 0xbf,
- 0xfb, 0xf2, 0x78, 0x8b, 0x03, 0xf6, 0x7d, 0x62, 0xe1, 0x6c, 0xb1, 0x52,
- 0x7b, 0xe3, 0x46, 0xbe, 0x8b, 0x33, 0x65, 0x8b, 0xff, 0xff, 0xfe, 0xe3,
- 0x0f, 0xb8, 0x71, 0xc7, 0x87, 0xf6, 0x77, 0xf9, 0xe8, 0x6c, 0xff, 0x07,
- 0xf9, 0xed, 0x62, 0xb6, 0x45, 0xf7, 0x09, 0x2f, 0xf9, 0xf0, 0xff, 0x7e,
- 0x99, 0x12, 0xc5, 0xff, 0x8b, 0x3b, 0x87, 0x35, 0x3e, 0xe2, 0xc5, 0xfc,
- 0x5f, 0xc0, 0x49, 0x2c, 0x52, 0xc5, 0xfa, 0x1a, 0x9c, 0x1a, 0xc5, 0xce,
- 0x2e, 0xcd, 0xa1, 0x06, 0x5f, 0xf0, 0xb5, 0xc6, 0x21, 0xe0, 0x16, 0x2f,
- 0xff, 0xf6, 0x43, 0x7f, 0xbf, 0xe7, 0x35, 0x0f, 0x14, 0x9f, 0x8b, 0x17,
- 0xfd, 0x87, 0xe4, 0x9d, 0xbb, 0xf2, 0xc5, 0xff, 0x36, 0xc2, 0x9c, 0x21,
- 0x6c, 0xb1, 0x7f, 0xa2, 0xd6, 0x3f, 0xe4, 0x6b, 0x15, 0x88, 0xa8, 0xd1,
- 0xd3, 0x1d, 0x53, 0xa6, 0xe1, 0xf3, 0x9e, 0x46, 0x13, 0x7f, 0xf4, 0xf0,
- 0xb0, 0xd7, 0xff, 0xf2, 0x3d, 0x62, 0xff, 0x85, 0xe8, 0xfe, 0x63, 0x90,
- 0xd6, 0x2f, 0x85, 0x3d, 0x8d, 0x62, 0xff, 0x61, 0xf2, 0x28, 0x3e, 0x2c,
- 0x54, 0xae, 0xf8, 0x8e, 0x1b, 0x5b, 0xc2, 0x35, 0xe1, 0xbf, 0x1e, 0x48,
- 0x73, 0xb6, 0x40, 0xe3, 0x07, 0xa3, 0x9c, 0x11, 0xb7, 0x44, 0x70, 0xcf,
- 0x0c, 0x24, 0xb8, 0x67, 0x58, 0xbe, 0x63, 0x98, 0x75, 0x8b, 0xd3, 0xad,
- 0x96, 0x2b, 0xc7, 0x84, 0x10, 0x92, 0xfd, 0x27, 0x2c, 0x1a, 0xc5, 0xb8,
- 0xb1, 0x61, 0x00, 0xdc, 0xf8, 0x9e, 0xf0, 0x47, 0x0d, 0x62, 0xa5, 0x7f,
- 0xcf, 0x27, 0x89, 0xa2, 0x86, 0x7b, 0x2d, 0x09, 0x74, 0x21, 0x3d, 0x82,
- 0xab, 0x17, 0xd8, 0xff, 0x12, 0xc5, 0xfa, 0x4b, 0x3a, 0x32, 0xc5, 0xb7,
- 0x88, 0xf2, 0xb4, 0x45, 0x6d, 0xd6, 0x2b, 0x64, 0x4e, 0xe9, 0x80, 0xc2,
- 0xab, 0xff, 0x9f, 0x76, 0xd6, 0xff, 0x7e, 0x8c, 0x75, 0x8b, 0xff, 0xb5,
- 0x3f, 0x9e, 0xa1, 0xb1, 0x14, 0xac, 0x5c, 0xfe, 0xe2, 0x23, 0x4c, 0x48,
- 0xbf, 0xff, 0xe6, 0x37, 0x83, 0x7c, 0xef, 0x77, 0x26, 0xec, 0xf3, 0x3c,
- 0x58, 0xbf, 0xfc, 0x79, 0xdf, 0xdc, 0xc0, 0x4e, 0x77, 0x05, 0x8b, 0xe3,
- 0x5f, 0x77, 0x58, 0xba, 0x61, 0x87, 0xe1, 0xe4, 0xca, 0xfa, 0x60, 0x85,
- 0x0d, 0x8b, 0xc3, 0xc8, 0x2c, 0x5e, 0x8f, 0x70, 0xd6, 0x2f, 0x1a, 0xfb,
- 0xac, 0x5f, 0x9f, 0xa1, 0x67, 0x3a, 0x9e, 0xef, 0xc7, 0x7c, 0x43, 0x7f,
- 0xdd, 0x30, 0x71, 0x66, 0x11, 0xab, 0x17, 0xff, 0xa1, 0x3c, 0xfc, 0x97,
- 0xbf, 0x1e, 0xe7, 0x58, 0xa2, 0x44, 0x4f, 0x8f, 0x2f, 0xfd, 0x27, 0xe3,
- 0xea, 0x7c, 0xfd, 0x16, 0x2f, 0xd1, 0xef, 0xf6, 0x89, 0x62, 0xde, 0x93,
- 0xec, 0xfa, 0x05, 0xfd, 0x3b, 0x93, 0x77, 0xe5, 0x8b, 0xe2, 0x13, 0x41,
- 0x62, 0xff, 0x73, 0x53, 0xb3, 0x6b, 0x75, 0x8b, 0xed, 0xa3, 0xa4, 0xeb,
- 0x14, 0xe7, 0xba, 0x61, 0xb5, 0xff, 0xa7, 0xbf, 0x70, 0x47, 0xce, 0xfc,
- 0xb1, 0x50, 0x55, 0x3c, 0xf0, 0xd7, 0x8f, 0x84, 0x71, 0xc9, 0xf8, 0x5f,
- 0xe7, 0xfe, 0x84, 0x57, 0xe9, 0xf6, 0xd8, 0x1a, 0xc5, 0xba, 0x2c, 0x5f,
- 0xfb, 0xbd, 0xc9, 0xb6, 0x68, 0x3f, 0xd6, 0x2b, 0x47, 0xfe, 0x72, 0xa1,
- 0x0a, 0x5f, 0xce, 0x2d, 0xb9, 0x30, 0x58, 0xbc, 0xe0, 0xe2, 0xc5, 0xf6,
- 0x6d, 0xd3, 0xcb, 0x15, 0x87, 0x86, 0x21, 0xdb, 0xff, 0xb8, 0xdd, 0xfb,
- 0xd9, 0xb8, 0xc5, 0xb2, 0xc5, 0xb3, 0x73, 0xea, 0xf1, 0x0d, 0xff, 0xf4,
- 0x3a, 0xe4, 0x08, 0x4d, 0xcf, 0xe0, 0x19, 0x62, 0xfc, 0x3d, 0xc5, 0x91,
- 0xeb, 0x17, 0xfe, 0x29, 0xef, 0xf2, 0xe4, 0xc3, 0x58, 0xa8, 0x8f, 0xa8,
- 0xe5, 0xb7, 0xdc, 0xc2, 0x35, 0x62, 0xfa, 0x72, 0x0c, 0xb1, 0x5d, 0x9e,
- 0x27, 0xc8, 0xef, 0xff, 0xed, 0xfe, 0xd1, 0xfd, 0x70, 0x66, 0xe3, 0xe8,
- 0xb3, 0xa2, 0xc5, 0xff, 0xfe, 0xfe, 0x7a, 0x3b, 0x09, 0xe7, 0xb2, 0xce,
- 0x93, 0x81, 0xac, 0x5f, 0xff, 0x85, 0xa6, 0xe4, 0x88, 0x2f, 0x3f, 0xc6,
- 0x2d, 0xd6, 0x2b, 0x88, 0xbd, 0xf3, 0x25, 0xf0, 0x23, 0x40, 0xa8, 0x51,
- 0x62, 0x9c, 0xf5, 0x34, 0x47, 0x52, 0xa8, 0x7c, 0x6c, 0xf8, 0x46, 0xd1,
- 0xba, 0x5f, 0xe1, 0xf4, 0x92, 0xf6, 0x01, 0x62, 0xfd, 0x3e, 0xfc, 0xf9,
- 0x62, 0xe2, 0x02, 0xc5, 0x6c, 0x7e, 0x9a, 0x35, 0x62, 0x8b, 0xfc, 0xdd,
- 0xf3, 0x59, 0xfe, 0x2c, 0x52, 0xc5, 0xfc, 0x2e, 0xe2, 0x72, 0xc5, 0x8b,
- 0xff, 0xff, 0xc2, 0xd7, 0xf2, 0x28, 0x9b, 0x51, 0x7b, 0xe2, 0x07, 0x31,
- 0xfa, 0x0e, 0x56, 0x2f, 0xf9, 0xff, 0xcd, 0x39, 0x49, 0xd6, 0x2f, 0xe9,
- 0xe4, 0x7b, 0xf7, 0xe5, 0x8b, 0xfa, 0x79, 0x11, 0x64, 0x4b, 0x14, 0xe9,
- 0x8b, 0xc7, 0xbf, 0x68, 0xe3, 0xe6, 0x57, 0xef, 0x7d, 0x88, 0xd5, 0x8b,
- 0xfc, 0x10, 0x84, 0x2d, 0xdc, 0xd5, 0x8b, 0x79, 0x62, 0x96, 0x2f, 0x9c,
- 0x33, 0xb7, 0x65, 0xf7, 0x84, 0xaf, 0xf0, 0xb6, 0x1f, 0xf0, 0xa5, 0x62,
- 0xa5, 0x18, 0x5b, 0xab, 0x11, 0xc5, 0xfe, 0x7c, 0x0e, 0x28, 0x39, 0x2c,
- 0x5f, 0xff, 0x49, 0xe3, 0xde, 0x64, 0xb5, 0x8e, 0x7c, 0x58, 0xbf, 0xfb,
- 0x07, 0xf9, 0x0f, 0xb8, 0x78, 0x43, 0x58, 0xbf, 0x81, 0x8e, 0x79, 0x8f,
- 0x58, 0xbf, 0x07, 0x87, 0x7f, 0x2c, 0x5f, 0xfc, 0x0f, 0xb8, 0xbd, 0xcf,
- 0x8b, 0x3c, 0xb1, 0x76, 0x71, 0x62, 0xe6, 0xf2, 0xc5, 0xa1, 0xa3, 0x5d,
- 0xf1, 0x7a, 0x94, 0x62, 0x31, 0x48, 0x9d, 0x2b, 0x13, 0x22, 0xe4, 0x3d,
- 0x2b, 0x65, 0xcb, 0x51, 0xc6, 0x8d, 0x88, 0x1b, 0xc3, 0xae, 0x3c, 0xbe,
- 0x23, 0x42, 0x4f, 0xf4, 0x6d, 0x54, 0x14, 0x5d, 0x4a, 0xc9, 0xcc, 0x1b,
- 0xff, 0xd9, 0xa8, 0xdb, 0x9e, 0x27, 0xef, 0x9d, 0x7c, 0xb1, 0x7f, 0xfe,
- 0xc8, 0xf6, 0x20, 0x6d, 0x81, 0x86, 0xc4, 0x52, 0xb1, 0x7f, 0xfb, 0x24,
- 0xb3, 0x72, 0xcf, 0x09, 0x83, 0x58, 0xbf, 0xf8, 0xbf, 0x93, 0xdb, 0x3f,
- 0x0c, 0x35, 0x62, 0xff, 0xfd, 0x07, 0xf7, 0x51, 0xfe, 0x74, 0x59, 0xd1,
- 0xbc, 0xb1, 0x52, 0x89, 0xf8, 0x91, 0xaf, 0xff, 0xb6, 0x62, 0xf7, 0x04,
- 0x5e, 0xf7, 0xd8, 0x6b, 0x17, 0xfd, 0x80, 0x8e, 0xc6, 0x1e, 0x71, 0x62,
- 0xff, 0xe7, 0xf7, 0xf1, 0xe1, 0xcc, 0xef, 0xcb, 0x15, 0x05, 0x46, 0x83,
- 0x58, 0xc8, 0x74, 0x31, 0x19, 0x28, 0xf0, 0xee, 0xfe, 0x29, 0x87, 0xf8,
- 0x05, 0x8b, 0xfe, 0x01, 0x67, 0xb8, 0xcc, 0x4b, 0x17, 0xff, 0x0b, 0x22,
- 0xc7, 0xdc, 0xb3, 0xf8, 0xb1, 0x60, 0x0d, 0x15, 0x3b, 0x97, 0x11, 0xbd,
- 0xe3, 0xb7, 0x6b, 0x17, 0xff, 0xf4, 0x1c, 0x79, 0xfc, 0xda, 0x60, 0xfc,
- 0xe6, 0x47, 0xac, 0x56, 0x91, 0x64, 0x03, 0x6f, 0x0f, 0x5c, 0x23, 0x56,
- 0x2f, 0xf6, 0x7c, 0x7f, 0x92, 0xd9, 0x62, 0xc3, 0xf9, 0xe6, 0x86, 0x33,
- 0x7d, 0xfc, 0x1b, 0xac, 0x54, 0x9e, 0x5f, 0x0a, 0x6a, 0x5b, 0x5d, 0x08,
- 0x42, 0xfc, 0x71, 0x99, 0xe4, 0xb2, 0x37, 0x87, 0x9c, 0x79, 0x7e, 0xa1,
- 0xb8, 0x72, 0x8f, 0xca, 0xda, 0x68, 0x5b, 0x00, 0xbc, 0xa7, 0x5f, 0xf8,
- 0x63, 0xe9, 0x50, 0xe2, 0x8e, 0xd8, 0xc8, 0x64, 0x5f, 0xec, 0x1e, 0xda,
- 0x14, 0x81, 0x62, 0xff, 0xf8, 0x0d, 0xfc, 0x00, 0x1b, 0x59, 0xd3, 0xf8,
- 0xb1, 0x7f, 0xfe, 0xf7, 0x08, 0x42, 0xee, 0x1c, 0x1f, 0xf1, 0xfc, 0xb1,
- 0x5a, 0x46, 0xf1, 0xcd, 0x49, 0x46, 0xfe, 0x86, 0xb5, 0x27, 0xe2, 0xc5,
- 0x49, 0xef, 0x76, 0x5f, 0x7f, 0xf8, 0x9c, 0x63, 0x9f, 0x70, 0x7f, 0x92,
- 0x58, 0xb1, 0xd6, 0x2f, 0xc0, 0x72, 0x87, 0x16, 0x2b, 0xb3, 0x75, 0xe1,
- 0x2a, 0xc4, 0x52, 0xbc, 0x20, 0xef, 0xd1, 0x3f, 0xdc, 0xeb, 0x17, 0xf7,
- 0xb9, 0xf9, 0x6d, 0x2c, 0x57, 0xcf, 0x5c, 0x8a, 0x6e, 0x07, 0x16, 0x2f,
- 0xb7, 0x21, 0x71, 0x62, 0xff, 0x87, 0x87, 0x2c, 0xf7, 0xdd, 0x62, 0xf6,
- 0xa4, 0x6b, 0x17, 0xe2, 0x9d, 0xd9, 0x96, 0x2e, 0xce, 0x1a, 0x78, 0x9e,
- 0x1d, 0xbf, 0x0b, 0x40, 0x8d, 0xc2, 0xda, 0xc5, 0x62, 0x60, 0x6e, 0x49,
- 0xf7, 0xce, 0x17, 0x56, 0x26, 0xf0, 0xe4, 0x3f, 0x8c, 0x6e, 0xfb, 0x85,
- 0x3b, 0x2c, 0x5f, 0xf7, 0x85, 0xd7, 0x33, 0x7c, 0x95, 0x8a, 0xd1, 0xef,
- 0x11, 0x1d, 0xff, 0xf8, 0x21, 0x67, 0x46, 0xe3, 0xe1, 0x7e, 0x3d, 0xce,
- 0xb1, 0x68, 0x61, 0xfd, 0xb9, 0x0d, 0xe9, 0xc2, 0x58, 0xba, 0x49, 0x62,
- 0xb4, 0x6c, 0x4e, 0x37, 0x7c, 0x6e, 0xa4, 0xeb, 0x17, 0xe9, 0x8b, 0x33,
- 0x75, 0x8b, 0xb0, 0x35, 0x8b, 0xfc, 0x36, 0x71, 0x8b, 0xdc, 0x58, 0xad,
- 0x8f, 0x33, 0x06, 0x2e, 0xcd, 0x96, 0x2b, 0xaa, 0x3d, 0x24, 0x87, 0x62,
- 0x40, 0xdd, 0x63, 0x88, 0xaf, 0xf0, 0xb9, 0xf6, 0x80, 0xdd, 0x62, 0xff,
- 0xff, 0xfd, 0x25, 0xb7, 0xb9, 0x81, 0xfe, 0x7a, 0x78, 0xa7, 0xbf, 0xe3,
- 0x0f, 0x30, 0xeb, 0x17, 0xf9, 0xcb, 0xd0, 0xcd, 0x62, 0xc5, 0xfe, 0x1b,
- 0x43, 0xdc, 0x60, 0x2c, 0x5e, 0x79, 0x3a, 0xc5, 0xff, 0x63, 0x6b, 0xa7,
- 0xb1, 0xf7, 0x58, 0xba, 0x77, 0xc4, 0x45, 0xe8, 0xd0, 0x87, 0x2b, 0x64,
- 0xdf, 0x21, 0x08, 0x52, 0x85, 0xed, 0xff, 0xe3, 0xe0, 0xfd, 0xf1, 0x00,
- 0xdc, 0x2f, 0x2c, 0x5f, 0xe6, 0x63, 0x73, 0x59, 0xe5, 0x8b, 0xfb, 0x5f,
- 0x63, 0xbf, 0x16, 0x2f, 0xdf, 0xfb, 0x6d, 0x3f, 0x3e, 0x13, 0x0c, 0xef,
- 0xfc, 0xda, 0xce, 0x98, 0xe3, 0xfb, 0xac, 0x56, 0x1f, 0xf8, 0x10, 0x2b,
- 0x13, 0x4d, 0x3c, 0x65, 0x97, 0xfe, 0x60, 0x6a, 0x4b, 0xdf, 0xc8, 0x2c,
- 0x5f, 0xfe, 0x06, 0x39, 0x7b, 0x0e, 0xde, 0x03, 0x2c, 0x54, 0xaa, 0x37,
- 0xc8, 0xe2, 0x1c, 0xa4, 0x47, 0xd7, 0xb3, 0xec, 0xb1, 0x7f, 0xee, 0x0f,
- 0xf3, 0x14, 0x1f, 0x50, 0x58, 0xbc, 0x21, 0x12, 0xc5, 0xf9, 0xff, 0xfc,
- 0x1a, 0xc5, 0x2c, 0x0c, 0xf1, 0x78, 0x3b, 0x5d, 0xa2, 0xc2, 0x28, 0x43,
- 0x50, 0xd1, 0xec, 0xd0, 0xcc, 0xbf, 0xf6, 0x43, 0xed, 0x0e, 0xbe, 0x83,
- 0xac, 0x5f, 0x8b, 0x00, 0x2e, 0x2c, 0x5f, 0xe9, 0xf7, 0xf1, 0xc9, 0x96,
- 0x2b, 0x63, 0xd9, 0xd1, 0x45, 0xfe, 0x04, 0x76, 0x30, 0xf3, 0x8b, 0x17,
- 0xa3, 0xdc, 0xeb, 0x17, 0xfc, 0x0f, 0x63, 0x8f, 0x0a, 0x25, 0x8f, 0x9a,
- 0x0b, 0xe2, 0x6d, 0x1a, 0xb1, 0x79, 0x81, 0xc9, 0x3e, 0xc7, 0x49, 0xa9,
- 0x4c, 0x5b, 0x08, 0xda, 0x18, 0x57, 0xfa, 0x1e, 0xfe, 0x6a, 0x7c, 0xb1,
- 0x7f, 0x07, 0x9b, 0xef, 0x81, 0xac, 0x5c, 0x15, 0x0a, 0x2c, 0x5d, 0xbf,
- 0x45, 0x8b, 0x01, 0x62, 0xff, 0xf4, 0x39, 0x9a, 0x9e, 0x16, 0x00, 0x5c,
- 0x58, 0xac, 0x3d, 0xc6, 0x12, 0xa8, 0xd1, 0x16, 0xf2, 0x41, 0xf7, 0x7a,
- 0xc4, 0xc7, 0x7d, 0x0e, 0x9b, 0xff, 0xf6, 0x4f, 0xe7, 0xa7, 0xe6, 0x3f,
- 0xab, 0x79, 0x8d, 0x58, 0xbf, 0xfd, 0x81, 0x00, 0x79, 0x8b, 0xce, 0x2d,
- 0x71, 0x62, 0xfe, 0xcc, 0x2f, 0x47, 0x62, 0xc5, 0xef, 0xbe, 0x96, 0x28,
- 0xe7, 0x98, 0x17, 0x2f, 0xbf, 0xfb, 0x9e, 0x99, 0xd0, 0x22, 0x2c, 0x0d,
- 0x62, 0xf8, 0x00, 0x61, 0xac, 0x5d, 0x9d, 0xac, 0x5b, 0xf8, 0x6e, 0xdc,
- 0x8e, 0xbb, 0x46, 0x63, 0x13, 0x02, 0x10, 0x37, 0x8d, 0x80, 0x96, 0x2c,
- 0x75, 0x8b, 0x9b, 0xcb, 0x17, 0xbf, 0x3a, 0xd8, 0xd4, 0x9c, 0x4a, 0xff,
- 0x09, 0x8b, 0xf8, 0xd1, 0x2c, 0x5b, 0xb8, 0x8f, 0x98, 0x33, 0x3a, 0x74,
- 0x6c, 0xb4, 0x2b, 0xaa, 0x57, 0x1b, 0xf2, 0x35, 0x13, 0x4a, 0x1d, 0x71,
- 0xa3, 0x66, 0x28, 0xc3, 0xaf, 0xf9, 0x82, 0x6b, 0x08, 0x9a, 0x25, 0x8b,
- 0xbe, 0x75, 0x8a, 0x96, 0xc6, 0xde, 0x10, 0xc7, 0xc8, 0xfd, 0x7b, 0x8c,
- 0x39, 0xe3, 0x4b, 0xd2, 0x87, 0xe5, 0xf3, 0xb4, 0x67, 0x00, 0x27, 0x28,
- 0xec, 0x39, 0x39, 0x44, 0x26, 0x80, 0xce, 0xaf, 0xb5, 0x9f, 0xe2, 0xc5,
- 0xff, 0xf6, 0x10, 0xb6, 0x3e, 0x7b, 0x9f, 0x8f, 0x73, 0xac, 0x5c, 0x22,
- 0x58, 0xbe, 0xef, 0x93, 0xda, 0xc5, 0x46, 0xc8, 0xb3, 0x92, 0x30, 0xba,
- 0xa1, 0x0b, 0xdf, 0xfe, 0xfb, 0x88, 0xb6, 0xc1, 0xc4, 0x21, 0x69, 0x62,
- 0xfd, 0x13, 0xed, 0x9d, 0xac, 0x5e, 0xd0, 0xa0, 0xb1, 0x5d, 0x9e, 0x4f,
- 0x8a, 0xef, 0xee, 0xbe, 0x29, 0x3f, 0x16, 0x2f, 0xb3, 0x98, 0x1a, 0xc5,
- 0x41, 0x30, 0xc7, 0x84, 0xb3, 0x11, 0x91, 0x85, 0x2c, 0x5f, 0x60, 0xda,
- 0x0b, 0x17, 0xcd, 0xad, 0x64, 0x79, 0xae, 0x30, 0x32, 0xf1, 0x60, 0x16,
- 0x2d, 0x2b, 0x14, 0x03, 0x5b, 0xe1, 0xcb, 0x9b, 0xcb, 0x15, 0xa3, 0x71,
- 0xf2, 0x1b, 0xd3, 0xae, 0x2c, 0x5e, 0x04, 0xf6, 0xb1, 0x47, 0x37, 0x60,
- 0x1d, 0xb8, 0xcd, 0x2c, 0x5f, 0x3f, 0x1f, 0xa2, 0xc5, 0xfe, 0x2c, 0x1f,
- 0xc5, 0xdf, 0x96, 0x2b, 0x63, 0xd9, 0x34, 0x92, 0xff, 0x49, 0xcb, 0x00,
- 0x2e, 0x2c, 0x5f, 0xf6, 0xb3, 0xf9, 0xb7, 0x57, 0xe2, 0xc5, 0x62, 0x70,
- 0x4e, 0xb9, 0xf2, 0x16, 0x72, 0x22, 0x41, 0x19, 0xdf, 0xe8, 0x3f, 0x39,
- 0x3a, 0x82, 0xc5, 0xf3, 0x1e, 0x5d, 0x62, 0xfe, 0x1f, 0xda, 0x19, 0xc5,
- 0x8b, 0xde, 0x70, 0xd6, 0x28, 0x68, 0xa1, 0x88, 0xd0, 0x04, 0x21, 0x97,
- 0x5f, 0xce, 0x42, 0x86, 0x71, 0x62, 0xf4, 0x3c, 0xeb, 0x17, 0xff, 0xe8,
- 0x3f, 0xb9, 0xbf, 0xdf, 0xdd, 0xc1, 0xfd, 0xc5, 0x8b, 0xfd, 0x83, 0x9e,
- 0xe1, 0x9e, 0x58, 0xbd, 0xc8, 0x76, 0xb1, 0x76, 0x6c, 0xb1, 0x7e, 0x90,
- 0x1d, 0xa1, 0xd4, 0xdb, 0xe8, 0x7e, 0xf6, 0xd8, 0x11, 0x62, 0xfe, 0x9c,
- 0xf7, 0x1b, 0xb5, 0x8b, 0xfe, 0xf4, 0xf6, 0x06, 0xff, 0xdd, 0x62, 0xf9,
- 0xe3, 0xb3, 0x65, 0x8a, 0xc3, 0xe0, 0xf1, 0xd5, 0x8e, 0xb1, 0x7e, 0x21,
- 0x43, 0x39, 0xd4, 0xd9, 0xf4, 0x21, 0xbc, 0x1b, 0x6c, 0xb1, 0x4e, 0x7c,
- 0x1f, 0x41, 0xa9, 0x55, 0xdc, 0x69, 0xff, 0x65, 0xb1, 0x0e, 0x9d, 0x67,
- 0xed, 0x64, 0x7f, 0xc2, 0x0f, 0x46, 0x43, 0x7d, 0xf1, 0x67, 0x96, 0x2f,
- 0xfc, 0x2e, 0xe1, 0xcf, 0xe6, 0xc2, 0x25, 0x8b, 0xfd, 0xd7, 0x51, 0xee,
- 0x0c, 0x1a, 0xc5, 0xec, 0xc1, 0xac, 0x5f, 0x89, 0xbc, 0xc7, 0x58, 0xb9,
- 0xb7, 0x58, 0xbf, 0x1b, 0x82, 0xd6, 0xcb, 0x14, 0xc7, 0x86, 0x21, 0x8a,
- 0x74, 0xd1, 0x74, 0x46, 0x74, 0x2f, 0x1c, 0x98, 0x38, 0x11, 0xaa, 0xd1,
- 0x91, 0xbc, 0x30, 0xb0, 0xc2, 0x8e, 0xc1, 0x58, 0x62, 0xc6, 0x91, 0x90,
- 0xc6, 0xcf, 0x61, 0x64, 0x20, 0x02, 0xd4, 0xae, 0x35, 0x9c, 0x4c, 0xf5,
- 0x56, 0xd1, 0xeb, 0x42, 0x3f, 0xa1, 0xd3, 0x18, 0x72, 0xb8, 0x95, 0x36,
- 0x76, 0x3b, 0x7a, 0x42, 0xaf, 0x71, 0xdc, 0x3c, 0xa7, 0xc8, 0xf8, 0x43,
- 0xc5, 0x48, 0x29, 0xd4, 0xfb, 0xb1, 0xe5, 0x6d, 0x7e, 0xbe, 0x84, 0x69,
- 0xd8, 0x50, 0x4f, 0x1b, 0x05, 0xdd, 0x4a, 0x92, 0xcd, 0xca, 0xdb, 0x53,
- 0xd5, 0xa0, 0x90, 0xa3, 0x99, 0xe9, 0x1a, 0x80, 0x6d, 0xd1, 0xd2, 0x88,
- 0x8c, 0x97, 0xc6, 0x12, 0x3c, 0xcb, 0xb9, 0xf5, 0x8b, 0xdd, 0x1e, 0x56,
- 0x2d, 0x19, 0x26, 0xd8, 0x63, 0x17, 0xfd, 0x19, 0xcd, 0x48, 0xbc, 0x23,
- 0xac, 0x5f, 0xfe, 0x87, 0x23, 0x0c, 0xcd, 0x7d, 0xe2, 0x81, 0xd6, 0x2a,
- 0x08, 0x8f, 0xec, 0xfa, 0xb4, 0x8d, 0xc6, 0x85, 0xc5, 0xfc, 0x11, 0xc6,
- 0x53, 0x12, 0xc5, 0xe9, 0x62, 0x58, 0xbe, 0xcf, 0xb7, 0x96, 0x2c, 0x15,
- 0xc3, 0xed, 0xf9, 0x81, 0x0d, 0xdf, 0xc1, 0x64, 0x68, 0xde, 0xc0, 0x8b,
- 0x17, 0x05, 0xfe, 0xb1, 0x7f, 0xf4, 0x9c, 0xa7, 0xac, 0x50, 0x9d, 0x6c,
- 0xb1, 0x7f, 0xfa, 0x74, 0x28, 0xa2, 0x7f, 0xb9, 0xd8, 0x6b, 0x17, 0xf6,
- 0x1f, 0xac, 0x45, 0x12, 0xc5, 0xfd, 0x20, 0xe4, 0xe8, 0x6b, 0x17, 0xe6,
- 0xf7, 0x26, 0x3d, 0x62, 0x86, 0x88, 0xbf, 0x99, 0x11, 0x75, 0xfe, 0xe3,
- 0x9e, 0x77, 0xc3, 0xac, 0x5f, 0x8c, 0x09, 0x24, 0x05, 0x8b, 0xfb, 0x4c,
- 0x0e, 0x6a, 0x56, 0x2b, 0xe7, 0xb3, 0xc2, 0xbb, 0xe8, 0x18, 0x1e, 0x2c,
- 0x5f, 0xff, 0xf8, 0xbd, 0xc9, 0x78, 0x60, 0x42, 0xf4, 0xfe, 0x4d, 0x14,
- 0x84, 0x58, 0xbc, 0x10, 0x72, 0xb1, 0x58, 0x8b, 0x36, 0x25, 0x13, 0x7d,
- 0xf8, 0x5e, 0x8a, 0x4d, 0x58, 0xbf, 0xe9, 0xdb, 0x91, 0x39, 0xda, 0x25,
- 0x8a, 0x1a, 0xb4, 0x5d, 0xd2, 0x1e, 0x1a, 0xf1, 0xe5, 0xf1, 0x42, 0x37,
- 0xf0, 0xd5, 0x22, 0xe0, 0x85, 0x77, 0xff, 0xff, 0x60, 0x42, 0x6d, 0xc2,
- 0x46, 0x71, 0xc3, 0x2c, 0xe7, 0x56, 0xf0, 0xa5, 0x62, 0xdf, 0x58, 0xb3,
- 0xac, 0x51, 0xa6, 0x8c, 0x02, 0x55, 0xa4, 0x60, 0x72, 0x13, 0xd7, 0xf6,
- 0xed, 0xad, 0xb0, 0x35, 0x8a, 0xc3, 0xd9, 0x72, 0x8b, 0xf3, 0x45, 0xe6,
- 0x1a, 0xc5, 0xff, 0xfb, 0xf8, 0x58, 0x6f, 0xda, 0x1f, 0x0d, 0x8c, 0x3a,
- 0xc5, 0xbb, 0x58, 0xbf, 0xe9, 0x7e, 0x63, 0xfe, 0x7c, 0xb1, 0x50, 0x3c,
- 0xaf, 0x89, 0xdf, 0xd0, 0xfe, 0x7b, 0xee, 0xb1, 0x7d, 0xbb, 0x36, 0xea,
- 0x8b, 0x58, 0xbf, 0xcf, 0xbe, 0x6a, 0x0d, 0xf5, 0x8b, 0xf3, 0x78, 0x98,
- 0x0b, 0x17, 0xcf, 0xaf, 0xb7, 0x53, 0xdb, 0xe1, 0xa5, 0xff, 0x31, 0xf8,
- 0xf9, 0xd1, 0xb4, 0xb1, 0x7c, 0xfa, 0x8f, 0x1a, 0xc5, 0x41, 0x50, 0xc3,
- 0xc2, 0x8a, 0x3c, 0x8b, 0x45, 0xdf, 0x84, 0x61, 0x1d, 0x74, 0x3a, 0xbf,
- 0x64, 0x1f, 0xe2, 0x58, 0xbf, 0xc4, 0xd1, 0x8f, 0xb7, 0x80, 0xb1, 0x7f,
- 0xd0, 0x13, 0xff, 0x66, 0x21, 0xac, 0x5f, 0xf8, 0x9b, 0x53, 0x17, 0x5c,
- 0xd3, 0xac, 0x5f, 0xff, 0xb8, 0x53, 0x16, 0x9c, 0x12, 0xe1, 0x07, 0x9c,
- 0x58, 0xbf, 0x9c, 0xed, 0x16, 0x7d, 0x62, 0x9d, 0x18, 0xb1, 0x20, 0x1d,
- 0x5e, 0xfb, 0x02, 0x17, 0x96, 0x2e, 0x90, 0xd6, 0x28, 0x06, 0xf0, 0x32,
- 0x4b, 0xfc, 0x22, 0xc0, 0x8e, 0x1b, 0xac, 0x5f, 0x71, 0x8b, 0x75, 0x8a,
- 0xf9, 0xec, 0x04, 0x35, 0xbf, 0xc5, 0xe7, 0x34, 0x98, 0xeb, 0x17, 0xf4,
- 0x90, 0x02, 0x66, 0xcb, 0x16, 0xfb, 0x1f, 0x18, 0x66, 0x77, 0x4f, 0x96,
- 0x2a, 0x53, 0x40, 0xc7, 0xa7, 0x84, 0x3c, 0x45, 0x17, 0xb5, 0x27, 0x58,
- 0xbf, 0xbf, 0x9c, 0x9d, 0x82, 0x2c, 0x5f, 0xfe, 0x1c, 0x9c, 0xa7, 0xac,
- 0x50, 0x9d, 0x6c, 0xb1, 0x70, 0x06, 0xb1, 0x7d, 0xbb, 0x36, 0xea, 0x8a,
- 0x0c, 0xbf, 0xfd, 0xf9, 0xfb, 0x9b, 0x9b, 0xfe, 0x49, 0x96, 0x2b, 0x47,
- 0xf7, 0xc3, 0x1b, 0xec, 0xdf, 0x3b, 0x58, 0xba, 0x11, 0x92, 0x99, 0x38,
- 0xd3, 0xb2, 0x12, 0x7f, 0x22, 0xbf, 0xf1, 0x7b, 0xf9, 0x0f, 0xb1, 0x0d,
- 0x62, 0xb1, 0x3e, 0x66, 0x8d, 0x60, 0x4a, 0x17, 0xcf, 0xb6, 0x69, 0x62,
- 0xff, 0x04, 0x60, 0x46, 0x4f, 0x03, 0x58, 0xae, 0xcf, 0x77, 0xe4, 0x77,
- 0xa2, 0x9f, 0x2c, 0x5f, 0x3f, 0xa7, 0x8b, 0x17, 0xc2, 0xf4, 0xf1, 0x62,
- 0xa5, 0x10, 0xd8, 0x47, 0xf1, 0xe2, 0x22, 0xb6, 0xeb, 0x17, 0xf7, 0x9c,
- 0x78, 0x50, 0x58, 0xbf, 0xf6, 0x0e, 0x75, 0xb0, 0xba, 0xf2, 0x0b, 0x17,
- 0xb5, 0x9e, 0x58, 0xbf, 0xbf, 0x9e, 0xfb, 0x1d, 0x62, 0xff, 0x75, 0xf4,
- 0x9d, 0xf5, 0x12, 0xc5, 0x61, 0xf2, 0x80, 0xba, 0xfe, 0xc2, 0xdd, 0x88,
- 0x0b, 0x15, 0xd5, 0x35, 0x3c, 0x13, 0xdc, 0xb5, 0x90, 0xca, 0x10, 0x5c,
- 0x21, 0xbc, 0x6c, 0xf1, 0x62, 0xff, 0x78, 0xb0, 0x0c, 0x40, 0x58, 0xbe,
- 0x13, 0x16, 0xf8, 0x7a, 0x06, 0x0f, 0x5f, 0xe8, 0x4e, 0xb6, 0x9d, 0x6c,
- 0xb1, 0x7f, 0xbb, 0x84, 0xe7, 0xba, 0xe2, 0xc5, 0xed, 0xe7, 0x75, 0x8a,
- 0x94, 0x45, 0xe1, 0xb3, 0x1b, 0x5f, 0x8f, 0x81, 0x08, 0x0b, 0x17, 0xb0,
- 0xee, 0xb1, 0x7f, 0xf9, 0xf9, 0xb1, 0x9e, 0x72, 0x14, 0x33, 0x8b, 0x17,
- 0x9c, 0xd3, 0xac, 0x50, 0xcf, 0xab, 0x49, 0x97, 0xbd, 0x9f, 0x58, 0xbf,
- 0xd2, 0x5e, 0x9d, 0x39, 0xd6, 0x2e, 0xf3, 0xac, 0x5f, 0xff, 0x60, 0x1b,
- 0x59, 0xd3, 0x07, 0x87, 0x9d, 0xd6, 0x2e, 0xd8, 0x2e, 0xb1, 0x52, 0x9d,
- 0x30, 0xca, 0xb2, 0x10, 0xc6, 0x91, 0x7c, 0x75, 0x8c, 0x88, 0x5c, 0x4a,
- 0x37, 0x1e, 0x25, 0x8b, 0xe0, 0x08, 0xa2, 0x58, 0xb9, 0xf7, 0x58, 0xa9,
- 0x37, 0x91, 0xc4, 0x96, 0xff, 0x53, 0xf8, 0x8c, 0x55, 0xbf, 0xb5, 0xcc,
- 0xd4, 0xf1, 0x62, 0xc0, 0x58, 0xb6, 0xcb, 0x17, 0x70, 0xf2, 0x69, 0x70,
- 0x4a, 0x9c, 0xff, 0x99, 0x4e, 0xfd, 0x10, 0x18, 0xa2, 0x58, 0xb8, 0x9d,
- 0x62, 0xa4, 0xf0, 0x37, 0x2a, 0xbf, 0xe2, 0x93, 0xcb, 0x8f, 0x0e, 0xb1,
- 0x7c, 0xc0, 0xcd, 0x2c, 0x5f, 0xe0, 0x73, 0x53, 0x06, 0xd2, 0xc5, 0xf4,
- 0xc6, 0x0c, 0x6b, 0x17, 0xfb, 0x05, 0xbf, 0xe7, 0x58, 0xb1, 0x7f, 0xda,
- 0x90, 0xcb, 0x06, 0xfa, 0x58, 0xbf, 0xfe, 0xcf, 0xfd, 0x9f, 0xd2, 0x59,
- 0xfc, 0xdd, 0x62, 0xb1, 0x54, 0xd9, 0xb0, 0xab, 0x76, 0x08, 0x88, 0xbe,
- 0x6e, 0xc4, 0x44, 0x69, 0xc2, 0x61, 0x1a, 0x47, 0x1c, 0xdf, 0xff, 0xb2,
- 0x30, 0xb1, 0xca, 0x62, 0x62, 0x13, 0xec, 0xb1, 0x7f, 0x3f, 0x85, 0x13,
- 0xf9, 0x62, 0x86, 0x88, 0x58, 0x95, 0xaf, 0xfe, 0x60, 0x9c, 0xc0, 0x84,
- 0xde, 0xc0, 0x8b, 0x17, 0xf9, 0xb6, 0x6c, 0xf6, 0x1d, 0x62, 0xff, 0xff,
- 0xed, 0x01, 0x87, 0x3a, 0x09, 0xcc, 0x08, 0x40, 0x98, 0x8c, 0x08, 0x23,
- 0xac, 0x5f, 0xff, 0xcd, 0xec, 0x3e, 0x3c, 0x50, 0xfe, 0x0c, 0x5e, 0xe2,
- 0xc5, 0xff, 0xf7, 0x98, 0x32, 0xc7, 0x04, 0x59, 0xf3, 0x09, 0x62, 0xff,
- 0xfb, 0x8f, 0xb3, 0x71, 0x89, 0xbd, 0xf9, 0x89, 0x62, 0xff, 0xcc, 0x40,
- 0xcf, 0x49, 0x38, 0x16, 0x2a, 0x53, 0xb4, 0x1b, 0xdf, 0xd7, 0x3c, 0xa3,
- 0x1c, 0xa1, 0x7f, 0xff, 0xd0, 0x70, 0xdb, 0xf2, 0x3d, 0xdb, 0x6f, 0x16,
- 0x6d, 0xa9, 0x58, 0xb4, 0x64, 0x6c, 0xdd, 0x93, 0x05, 0xb3, 0x70, 0xb5,
- 0x3a, 0x99, 0x6c, 0x30, 0x8e, 0x80, 0x64, 0x19, 0x29, 0x04, 0xd7, 0x3d,
- 0xca, 0x3b, 0x37, 0x78, 0x7f, 0xc5, 0x1d, 0x66, 0x90, 0x4f, 0x28, 0x0f,
- 0xf1, 0x8c, 0x34, 0x71, 0xa0, 0x85, 0x69, 0x43, 0x13, 0x91, 0xe9, 0xfa,
- 0x5c, 0x38, 0xa3, 0x18, 0x0c, 0x92, 0x39, 0x24, 0xc8, 0xf9, 0xc2, 0x26,
- 0xdf, 0x7f, 0xf9, 0xb2, 0xc5, 0xff, 0xec, 0x8f, 0x7c, 0x3e, 0x7f, 0x18,
- 0xb7, 0x58, 0xb8, 0xd8, 0xc6, 0x3e, 0xf2, 0x24, 0xbf, 0xf3, 0x42, 0x33,
- 0x35, 0xbb, 0x36, 0xea, 0x8a, 0x2c, 0xbf, 0xc2, 0x78, 0x3f, 0xdf, 0xa2,
- 0xc5, 0xa3, 0x0e, 0x88, 0x5e, 0x28, 0x5f, 0xe8, 0xcc, 0xd6, 0xec, 0xdb,
- 0xaa, 0x2e, 0xa2, 0xff, 0xff, 0xff, 0xd1, 0xa6, 0xc1, 0x64, 0x6a, 0x8d,
- 0x61, 0x70, 0xb8, 0x59, 0xd7, 0xaf, 0xe3, 0xa3, 0x36, 0x0b, 0x58, 0xd0,
- 0x2c, 0x90, 0xa0, 0x5c, 0x1d, 0x7a, 0xfe, 0x39, 0x62, 0xa6, 0x30, 0x00,
- 0x28, 0x4a, 0x5d, 0xc6, 0xfd, 0xe3, 0x1c, 0x7a, 0x4e, 0x89, 0xe9, 0x44,
- 0xdf, 0xc6, 0x21, 0x9b, 0x4b, 0xe8, 0x05, 0x77, 0x74, 0x52, 0x8e, 0x39,
- 0x0b, 0x5f, 0x16, 0x47, 0x22, 0xdf, 0xb5, 0xbb, 0x36, 0xea, 0x88, 0x84,
- 0xb6, 0xcb, 0x17, 0xfa, 0x4f, 0x2e, 0x3c, 0x3a, 0xc5, 0xef, 0xb9, 0x2c,
- 0x5d, 0x83, 0x58, 0xb6, 0xeb, 0x15, 0xb9, 0xe3, 0x7c, 0x70, 0x85, 0xef,
- 0xb3, 0xa3, 0xe9, 0x62, 0xf9, 0xbe, 0x39, 0x58, 0xbe, 0x7d, 0x67, 0x6b,
- 0x15, 0x89, 0xad, 0x1a, 0x6f, 0xb8, 0x9f, 0x6f, 0x11, 0xe5, 0xfe, 0x24,
- 0x8e, 0x22, 0xbf, 0xfb, 0x6c, 0x0e, 0x33, 0x83, 0x13, 0x6a, 0x0b, 0x17,
- 0xc5, 0x20, 0xe2, 0xc5, 0xfd, 0xa1, 0x7f, 0xa6, 0x0d, 0x62, 0xf6, 0x60,
- 0xd6, 0x2f, 0xff, 0xff, 0x79, 0xc8, 0x50, 0xce, 0x16, 0x6c, 0x64, 0x3a,
- 0xf0, 0x40, 0x3c, 0xc1, 0x62, 0xef, 0x46, 0x44, 0x8e, 0xbd, 0x11, 0x11,
- 0x89, 0x83, 0x95, 0x18, 0x9f, 0x84, 0x1b, 0x72, 0x33, 0x6b, 0xff, 0xa3,
- 0x02, 0xf2, 0x5e, 0x30, 0xe5, 0x9b, 0x2c, 0x5a, 0x39, 0x62, 0xfa, 0x7f,
- 0x27, 0x58, 0xbe, 0xdd, 0x9b, 0x75, 0x44, 0x6c, 0x56, 0xe7, 0xa7, 0xa2,
- 0x2b, 0xda, 0x6d, 0x96, 0x2d, 0x18, 0x34, 0x54, 0xe3, 0x47, 0x88, 0xef,
- 0xf4, 0x66, 0x6b, 0x76, 0x6d, 0xd5, 0x14, 0xd9, 0x73, 0x41, 0x62, 0xfb,
- 0x76, 0x6d, 0xd5, 0x15, 0x01, 0x43, 0x3c, 0x8d, 0x0b, 0xd8, 0x35, 0x8a,
- 0x58, 0xb6, 0x76, 0x5f, 0xc4, 0x27, 0x7d, 0xff, 0xc8, 0xd6, 0x2d, 0x19,
- 0x88, 0x8b, 0xfa, 0x09, 0x84, 0xf7, 0xfa, 0x33, 0x35, 0xbb, 0x36, 0xea,
- 0x8a, 0x98, 0xb8, 0x0e, 0xb1, 0x7e, 0x17, 0x6c, 0x2d, 0x2c, 0x5b, 0x8b,
- 0x17, 0x84, 0xfa, 0x58, 0xbf, 0xbf, 0x81, 0x1f, 0x03, 0x58, 0xbe, 0xdd,
- 0x9b, 0x75, 0x45, 0x60, 0x5f, 0x7a, 0x7b, 0x82, 0xc5, 0x44, 0x88, 0x5d,
- 0x18, 0x1c, 0xc6, 0xfc, 0xe1, 0x8c, 0x5a, 0x58, 0xb6, 0xcb, 0x17, 0x19,
- 0x05, 0x8b, 0xcc, 0x5b, 0xac, 0x54, 0x9e, 0x48, 0x04, 0xfc, 0x33, 0x77,
- 0x09, 0x62, 0xe1, 0x9a, 0xb1, 0x7a, 0x40, 0xeb, 0x17, 0x1f, 0x8b, 0x17,
- 0xe6, 0x87, 0x9f, 0x65, 0x8b, 0xf7, 0x38, 0x58, 0x05, 0x8b, 0x0d, 0x62,
- 0x9c, 0xf8, 0xd8, 0xa4, 0xc2, 0x8b, 0x9e, 0x39, 0x62, 0xda, 0x58, 0xbc,
- 0xf1, 0xcd, 0x26, 0xb0, 0x43, 0x57, 0xfa, 0x33, 0x35, 0xbb, 0x36, 0xea,
- 0x88, 0xfc, 0xb8, 0x5c, 0x58, 0xbc, 0x52, 0x35, 0x8b, 0xe9, 0x83, 0x79,
- 0x62, 0xa5, 0x19, 0xd0, 0x33, 0x1a, 0x2b, 0x8c, 0x10, 0xe5, 0xf6, 0x61,
- 0x41, 0x62, 0xd2, 0xb1, 0x6d, 0x96, 0x2f, 0xcf, 0xcf, 0x09, 0x96, 0x2a,
- 0x4d, 0xd8, 0xc4, 0xea, 0x07, 0xd9, 0x89, 0x97, 0xa2, 0x16, 0x96, 0x2c,
- 0x4b, 0x17, 0xde, 0x29, 0x3a, 0xc5, 0x0c, 0xd9, 0xb8, 0x8d, 0x49, 0xf9,
- 0x7d, 0x4a, 0xfe, 0xee, 0x0d, 0x07, 0x25, 0x8b, 0xd2, 0x51, 0x2c, 0x5f,
- 0x45, 0x09, 0xed, 0x62, 0xfa, 0x78, 0xf1, 0x2c, 0x5f, 0xb3, 0xa7, 0xda,
- 0x0b, 0x15, 0x88, 0xbd, 0x34, 0xb9, 0xc7, 0x74, 0x4a, 0x44, 0x77, 0x8d,
- 0x6f, 0x2c, 0x5d, 0x9a, 0x58, 0xbc, 0x2d, 0x6c, 0xb1, 0x6f, 0x2c, 0x56,
- 0x1b, 0x16, 0x1f, 0xb8, 0xe1, 0x16, 0x2e, 0xf7, 0x96, 0x2d, 0x18, 0x16,
- 0x2f, 0x7d, 0x48, 0xbe, 0xc5, 0x43, 0x12, 0xc8, 0x51, 0x6e, 0x63, 0xdb,
- 0x9b, 0x97, 0x47, 0x8b, 0xe8, 0x64, 0xe3, 0x9f, 0x7b, 0x68, 0xca, 0x00,
- 0x8e, 0x50, 0x8d, 0xe4, 0x24, 0xfd, 0x0d, 0xe1, 0x24, 0x06, 0x3d, 0x1c,
- 0x90, 0x60, 0xf8, 0x41, 0xab, 0xff, 0xd1, 0x87, 0x68, 0x46, 0x66, 0xb7,
- 0x66, 0xdd, 0x51, 0x37, 0x97, 0xff, 0x1d, 0xa1, 0x19, 0x9a, 0xdd, 0x9b,
- 0x75, 0x44, 0xfc, 0x5e, 0x0a, 0x46, 0xe1, 0x45, 0x8b, 0xff, 0xfe, 0xf8,
- 0xbc, 0x4c, 0x6f, 0x7e, 0xd4, 0xe7, 0x6c, 0xfd, 0xb2, 0xc5, 0x82, 0x81,
- 0x44, 0x4a, 0x61, 0x5d, 0xf8, 0xf2, 0x79, 0x31, 0x62, 0xfb, 0x33, 0x5c,
- 0x58, 0xa6, 0x3c, 0xb0, 0x14, 0xdf, 0xf0, 0x55, 0xa1, 0xf7, 0xe9, 0x9b,
- 0x2c, 0x5f, 0xc6, 0x19, 0xd8, 0x4e, 0x76, 0xb1, 0x51, 0xb9, 0xfb, 0x05,
- 0x10, 0x2e, 0x68, 0x2c, 0x5f, 0xd1, 0xa4, 0xbe, 0xf2, 0x75, 0x8b, 0x9c,
- 0xeb, 0x15, 0x1b, 0xa7, 0x3c, 0x14, 0x7b, 0x0a, 0xc2, 0x5c, 0x2d, 0x95,
- 0x85, 0x82, 0xfa, 0x33, 0xbe, 0x93, 0x47, 0x2b, 0x17, 0xf8, 0x79, 0xd0,
- 0x84, 0x64, 0xac, 0x5f, 0x37, 0x70, 0x95, 0x8b, 0x05, 0x24, 0xf6, 0x43,
- 0x36, 0xbe, 0x0a, 0x6d, 0xc0, 0x2c, 0x5f, 0x9b, 0x6f, 0x08, 0xd5, 0x8b,
- 0xf6, 0xfa, 0x29, 0x82, 0xc5, 0x46, 0xb3, 0xfd, 0xd1, 0x4b, 0x15, 0xdf,
- 0xfb, 0x21, 0xf9, 0x21, 0x73, 0xee, 0xb1, 0x71, 0x87, 0x58, 0xbf, 0xb0,
- 0xd7, 0xf1, 0x4a, 0xc5, 0x46, 0x88, 0x84, 0xdc, 0xfa, 0x38, 0x66, 0xe8,
- 0x1d, 0x62, 0xfe, 0xe3, 0x1f, 0x53, 0xc5, 0x8b, 0xfe, 0xe8, 0xfb, 0x85,
- 0x32, 0x29, 0xf2, 0xc5, 0xfb, 0x53, 0xf1, 0x4a, 0xc5, 0xc1, 0xfd, 0x62,
- 0xf8, 0x29, 0x00, 0xa6, 0xcb, 0x17, 0xef, 0xe7, 0xa4, 0x6b, 0x17, 0xec,
- 0x8a, 0x13, 0xda, 0xc5, 0xfe, 0xcd, 0x7d, 0xe2, 0x81, 0xd6, 0x2b, 0xaa,
- 0xb9, 0x28, 0xdd, 0xf0, 0x29, 0x0a, 0x90, 0xac, 0x2e, 0x23, 0x51, 0xcc,
- 0x6b, 0x18, 0xc2, 0xe7, 0x41, 0x88, 0xa3, 0x43, 0x2c, 0x5a, 0x45, 0x06,
- 0x15, 0x5e, 0xd0, 0x7a, 0x58, 0xbe, 0xc3, 0xbf, 0x96, 0x2f, 0xee, 0x8f,
- 0xde, 0x66, 0xcb, 0x17, 0x61, 0x2c, 0x56, 0x1e, 0x3f, 0x0c, 0x6f, 0xe8,
- 0xda, 0x34, 0x3c, 0xe7, 0x96, 0x2f, 0xe0, 0xa3, 0xc7, 0x7d, 0xc2, 0xeb,
- 0x17, 0xf6, 0x69, 0xfd, 0xc3, 0xac, 0x54, 0x6b, 0x3e, 0x7e, 0x1c, 0xdc,
- 0x5b, 0xac, 0x5f, 0x72, 0x23, 0xf1, 0x62, 0xfc, 0x5e, 0xfb, 0x9d, 0x62,
- 0xfa, 0x21, 0x31, 0x8b, 0x15, 0x27, 0x9a, 0xc5, 0x17, 0x8f, 0x3c, 0x58,
- 0xbc, 0x4d, 0xd1, 0x62, 0xed, 0xf7, 0x58, 0xbf, 0xf6, 0x0f, 0xee, 0x7c,
- 0xe0, 0x8e, 0xb1, 0x7f, 0xb7, 0xfb, 0xfb, 0x30, 0xeb, 0x17, 0x74, 0xdd,
- 0x71, 0x81, 0x14, 0x14, 0x56, 0x14, 0x15, 0x1f, 0x8d, 0x9a, 0x63, 0x51,
- 0x0c, 0x6b, 0x84, 0xfc, 0x94, 0x38, 0xc4, 0x4e, 0x5a, 0x20, 0x38, 0xe8,
- 0x07, 0x88, 0x6b, 0x87, 0xfe, 0x34, 0xbe, 0x0a, 0xc7, 0x67, 0x6b, 0x17,
- 0xf7, 0xe5, 0xf4, 0xfa, 0x58, 0xa8, 0xdc, 0xf6, 0x37, 0x2b, 0xbf, 0x82,
- 0x8d, 0xb7, 0xde, 0x3d, 0x62, 0xfd, 0x1b, 0x85, 0x76, 0xc0, 0xd6, 0x2f,
- 0xfb, 0xaf, 0xbf, 0x87, 0xcd, 0x62, 0xc5, 0xfc, 0x16, 0xb1, 0xbc, 0x6e,
- 0x15, 0xe4, 0xac, 0x5f, 0xa3, 0x43, 0x4d, 0xc8, 0xf5, 0x8b, 0xfb, 0xce,
- 0x41, 0xe1, 0x2c, 0x5d, 0xc1, 0x2c, 0x5e, 0x01, 0x9e, 0x58, 0xc2, 0xe2,
- 0xd0, 0x58, 0xbe, 0x0a, 0xe7, 0x02, 0x8b, 0x15, 0xa3, 0x7a, 0xc2, 0x57,
- 0x74, 0xdd, 0x71, 0x80, 0x96, 0xfa, 0xc5, 0xc0, 0x02, 0xc5, 0x05, 0x15,
- 0x32, 0x85, 0x4a, 0x23, 0x43, 0x68, 0xd8, 0xd0, 0x2d, 0x9d, 0xc6, 0xb4,
- 0x4c, 0x33, 0x64, 0x52, 0x6a, 0xf1, 0x00, 0x8a, 0x0c, 0x12, 0xbd, 0x1b,
- 0x1c, 0xeb, 0x17, 0x98, 0x6e, 0xb1, 0x7f, 0xf1, 0x37, 0xb8, 0x53, 0xad,
- 0x30, 0xd6, 0x2a, 0x07, 0xbf, 0x83, 0x97, 0xf7, 0xdf, 0xc5, 0x31, 0x2c,
- 0x5c, 0xd8, 0xb1, 0x5b, 0x9e, 0x26, 0x8b, 0xaf, 0x98, 0x78, 0x75, 0x8b,
- 0xf4, 0x6b, 0x0a, 0x43, 0x41, 0x16, 0x2f, 0x6f, 0x24, 0xb1, 0x7f, 0xee,
- 0x93, 0xf7, 0x98, 0xa2, 0x9d, 0xd6, 0x2f, 0xe7, 0x18, 0xa7, 0x50, 0x58,
- 0xa8, 0xdd, 0x3f, 0x00, 0xac, 0x20, 0xa3, 0x46, 0x50, 0xb0, 0x8e, 0x35,
- 0x91, 0x61, 0xb3, 0x8e, 0xb2, 0x1d, 0xf4, 0x6d, 0xb1, 0xf8, 0xb1, 0x7f,
- 0xb5, 0xf6, 0xe3, 0x8f, 0x16, 0x2f, 0xa4, 0x9f, 0xb5, 0x8b, 0x66, 0x1e,
- 0xac, 0x46, 0x77, 0xf1, 0x39, 0xbf, 0x68, 0x2c, 0x5f, 0xff, 0x37, 0xa4,
- 0xb7, 0x73, 0x8c, 0x4d, 0xa8, 0x2c, 0x51, 0xcf, 0xf8, 0x8b, 0xaf, 0xc1,
- 0xfb, 0xd2, 0x75, 0x8a, 0x8d, 0x0f, 0x2f, 0x62, 0x1b, 0xfe, 0x6f, 0xbf,
- 0x48, 0xc0, 0xc3, 0x0d, 0x22, 0xff, 0x7d, 0xbd, 0xe6, 0x60, 0xd6, 0x2e,
- 0x91, 0xac, 0x5f, 0xb3, 0x76, 0xe3, 0xac, 0x54, 0x6c, 0xa9, 0x30, 0x2d,
- 0xbf, 0x85, 0x90, 0xf0, 0x0b, 0x52, 0x88, 0xd6, 0x85, 0xd9, 0xa7, 0xc5,
- 0xee, 0x83, 0x2c, 0x5f, 0xf4, 0x1d, 0xbb, 0x81, 0x09, 0x96, 0x2f, 0xff,
- 0xf7, 0xdf, 0x93, 0x0c, 0xfb, 0xeb, 0xed, 0x82, 0xcf, 0xac, 0x5f, 0xff,
- 0x6a, 0x5f, 0xdf, 0xc1, 0xbf, 0x30, 0x80, 0xb1, 0x60, 0xa8, 0xd1, 0xfb,
- 0x82, 0xec, 0x73, 0xc5, 0xfb, 0xb9, 0x2b, 0x17, 0xfd, 0xc7, 0x2e, 0xfc,
- 0x53, 0x8b, 0x15, 0x1b, 0xa2, 0x52, 0x08, 0xb8, 0x2f, 0x7f, 0x47, 0xce,
- 0x99, 0xa0, 0xb1, 0x7e, 0xfb, 0xb0, 0x23, 0x5a, 0xc5, 0xe9, 0xee, 0x0b,
- 0x14, 0x14, 0x45, 0x84, 0x6a, 0x34, 0xf1, 0x80, 0x42, 0xeb, 0xfd, 0x1b,
- 0x94, 0x8c, 0xc0, 0x71, 0x62, 0xff, 0xd1, 0xa0, 0x52, 0x22, 0x91, 0xe7,
- 0x7e, 0x58, 0xbf, 0xa2, 0x98, 0xe0, 0x91, 0x44, 0xb1, 0x7d, 0x83, 0x68,
- 0x2c, 0x5f, 0xec, 0x30, 0xf8, 0x59, 0x1e, 0xb1, 0x7b, 0xa6, 0xa0, 0xb1,
- 0x7b, 0x42, 0x08, 0xb1, 0x78, 0x30, 0xcd, 0x58, 0xa8, 0xdd, 0x37, 0x48,
- 0xd0, 0xea, 0x36, 0x4a, 0x0b, 0x0d, 0xc2, 0xd4, 0x8b, 0x86, 0xc2, 0x20,
- 0x0c, 0x82, 0xff, 0xfc, 0x14, 0x26, 0xf4, 0xe1, 0x40, 0xf3, 0x84, 0x35,
- 0x8b, 0xf8, 0x29, 0x07, 0xf7, 0xa5, 0x62, 0xf8, 0xb1, 0xc0, 0xb1, 0x7f,
- 0xc1, 0x48, 0x3f, 0xbf, 0x24, 0x6a, 0xc5, 0xe0, 0x1b, 0x2b, 0x15, 0x1b,
- 0x9e, 0xe0, 0x5b, 0x3e, 0xbc, 0xdf, 0x75, 0x8b, 0xf3, 0xe8, 0x00, 0x95,
- 0x8b, 0xfd, 0xe8, 0x08, 0x6c, 0x40, 0x58, 0xb9, 0xf6, 0x58, 0xbc, 0x17,
- 0x6d, 0x2c, 0x54, 0x6e, 0x9f, 0x18, 0x51, 0x58, 0x2a, 0x65, 0x1b, 0x3e,
- 0xc9, 0x6c, 0x07, 0x18, 0xa3, 0xc6, 0x82, 0x18, 0xbc, 0xd9, 0xf5, 0x8b,
- 0xf1, 0x60, 0x0c, 0xed, 0x62, 0xff, 0x9b, 0xdd, 0xc3, 0xd9, 0xa3, 0x56,
- 0x2f, 0xfc, 0xfd, 0xf0, 0xb0, 0x73, 0x9a, 0x58, 0xb9, 0xc0, 0xb1, 0x41,
- 0x44, 0x6b, 0x85, 0x83, 0x91, 0xac, 0xa8, 0x07, 0x84, 0x7d, 0x7f, 0x7f,
- 0x70, 0xa7, 0x3e, 0xeb, 0x17, 0xa3, 0x40, 0xb8, 0x51, 0x62, 0xff, 0xf4,
- 0x6f, 0x10, 0x54, 0x2d, 0x90, 0x23, 0x5f, 0x5e, 0xbf, 0x8e, 0x58, 0xa0,
- 0xb1, 0x12, 0xa0, 0x2b, 0xbf, 0xff, 0xc2, 0xea, 0x59, 0xad, 0x1f, 0xf2,
- 0x22, 0xeb, 0xd7, 0xf1, 0xcb, 0x17, 0xfe, 0x99, 0x99, 0x99, 0x9e, 0xf8,
- 0xb1, 0x7a, 0x29, 0xf2, 0xc5, 0xd3, 0x32, 0x7b, 0x51, 0x1e, 0x5c, 0x77,
- 0x58, 0xbf, 0xfd, 0xf9, 0x8b, 0xbe, 0x67, 0x71, 0xf3, 0x24, 0xb1, 0x79,
- 0xfb, 0xc5, 0x8b, 0xf6, 0x9f, 0x66, 0x3a, 0x45, 0xc1, 0x86, 0x91, 0x58,
- 0x78, 0x61, 0x94, 0xd8, 0x49, 0x11, 0x86, 0x8a, 0xf7, 0xf3, 0x75, 0x8a,
- 0x94, 0xd5, 0xf7, 0x2c, 0xf8, 0xb8, 0x13, 0xf9, 0x08, 0x23, 0x09, 0x6f,
- 0xc2, 0x8e, 0x91, 0x76, 0xb1, 0x70, 0xa0, 0xb1, 0x7f, 0xe9, 0xfe, 0x03,
- 0x07, 0xf6, 0x82, 0xc5, 0xf3, 0x14, 0x84, 0x58, 0xbf, 0xa1, 0x27, 0x9d,
- 0x69, 0x62, 0xb1, 0x1a, 0x91, 0xe5, 0xba, 0x18, 0x63, 0xe1, 0x11, 0xdf,
- 0xff, 0xde, 0x73, 0xe1, 0x7b, 0x92, 0x6f, 0x04, 0x3f, 0xba, 0xc5, 0xf8,
- 0x6e, 0x1c, 0x9d, 0x62, 0xfe, 0x87, 0x5e, 0x38, 0xb4, 0xb1, 0x7f, 0xd3,
- 0xc6, 0xd3, 0xfb, 0x98, 0xb1, 0x5d, 0x9f, 0x48, 0x0c, 0x6f, 0xff, 0x33,
- 0x96, 0x03, 0xac, 0xeb, 0x69, 0xf2, 0xc5, 0xff, 0x82, 0x3c, 0x7f, 0xe2,
- 0x98, 0xf6, 0x3a, 0xc5, 0xfe, 0xf7, 0xe4, 0xb6, 0x7e, 0x8b, 0x17, 0xee,
- 0x64, 0x23, 0xb1, 0x62, 0xf6, 0x1e, 0x7a, 0x9f, 0x0f, 0x0d, 0xaf, 0xff,
- 0xf4, 0xbc, 0x38, 0x61, 0xf0, 0x85, 0x06, 0xf0, 0x6d, 0xda, 0xc5, 0x0d,
- 0x38, 0xbf, 0xa5, 0x94, 0x2a, 0x7c, 0x69, 0x7e, 0x3b, 0x1f, 0x06, 0xb1,
- 0x7f, 0xde, 0xdf, 0xee, 0x45, 0x3d, 0xac, 0x54, 0x9f, 0x13, 0x14, 0x5f,
- 0xfa, 0x76, 0x9e, 0x3c, 0x76, 0x6a, 0x56, 0x2f, 0xe1, 0xe1, 0x6c, 0xfa,
- 0x58, 0xba, 0x42, 0x2c, 0x57, 0x55, 0x7d, 0x12, 0xb9, 0x90, 0x92, 0x78,
- 0xeb, 0xbf, 0x0a, 0x42, 0x20, 0x12, 0x0f, 0x42, 0xeb, 0xfe, 0x29, 0xeb,
- 0x14, 0x27, 0x5b, 0x2c, 0x5f, 0xec, 0x1b, 0xf4, 0xe0, 0x37, 0x58, 0xbf,
- 0xff, 0xf6, 0x74, 0x7f, 0x43, 0x01, 0xc2, 0xc0, 0x6a, 0x76, 0x6d, 0x6e,
- 0xb1, 0x74, 0xc1, 0x91, 0x4d, 0xc3, 0x7b, 0xd9, 0xb4, 0xac, 0x5f, 0xff,
- 0x60, 0x33, 0xdc, 0x7e, 0x85, 0x9e, 0xfb, 0xac, 0x5d, 0xee, 0x61, 0xf6,
- 0x90, 0xed, 0xff, 0xfc, 0xe7, 0x7d, 0x0e, 0x47, 0x8f, 0x06, 0xe6, 0x09,
- 0x62, 0x8e, 0xa8, 0x0b, 0xf0, 0xe3, 0x28, 0x4d, 0x78, 0xb2, 0xfb, 0x83,
- 0xf0, 0x96, 0x2f, 0xff, 0xfe, 0xe9, 0x3a, 0xc1, 0x93, 0x68, 0xd6, 0xf0,
- 0xbc, 0xfe, 0xe7, 0xdd, 0x62, 0xff, 0xc2, 0xe7, 0x33, 0xb8, 0x78, 0x43,
- 0x58, 0xbf, 0xda, 0x11, 0x0b, 0xc2, 0xf2, 0xc5, 0xef, 0xc9, 0x2c, 0x56,
- 0xe8, 0x93, 0x74, 0x2f, 0x1a, 0xde, 0x33, 0xdc, 0x58, 0xbe, 0x17, 0x84,
- 0x6a, 0xc5, 0x68, 0xf1, 0x08, 0x7e, 0xa5, 0x12, 0xb8, 0xe9, 0x7f, 0xa6,
- 0x22, 0x93, 0x8b, 0x65, 0x8b, 0xf3, 0x71, 0xce, 0x25, 0x8a, 0x39, 0xee,
- 0xfc, 0xd6, 0xe3, 0x43, 0x58, 0xbf, 0xfe, 0x92, 0x29, 0xd8, 0x36, 0xdb,
- 0xef, 0x24, 0xb1, 0x78, 0xb0, 0x0b, 0x15, 0x03, 0xeb, 0xc4, 0xfa, 0x95,
- 0x69, 0xdb, 0xa4, 0x39, 0x27, 0xe3, 0x9c, 0x67, 0xef, 0x11, 0x0a, 0x10,
- 0xb7, 0xcf, 0xb3, 0x1d, 0x62, 0xff, 0x48, 0x63, 0xfc, 0x96, 0xeb, 0x17,
- 0x3c, 0xac, 0x53, 0x9e, 0x59, 0x1a, 0xdf, 0x73, 0xf3, 0xc5, 0x8b, 0x8f,
- 0xc5, 0x8a, 0xc3, 0x76, 0xe4, 0x77, 0xe9, 0x30, 0xff, 0x75, 0x8b, 0xfe,
- 0xef, 0xc6, 0x6d, 0xed, 0x4f, 0x16, 0x2f, 0x63, 0xf4, 0x58, 0xac, 0x3d,
- 0xc0, 0xcf, 0xa8, 0x69, 0xc7, 0xe9, 0xb8, 0xeb, 0x64, 0x3f, 0xc8, 0x42,
- 0xdf, 0xfb, 0xf3, 0xdc, 0x30, 0xef, 0x31, 0xeb, 0x17, 0xfc, 0x0c, 0x67,
- 0xd6, 0xf3, 0xe5, 0x8b, 0xd0, 0x3c, 0xac, 0x53, 0x9e, 0xb7, 0x43, 0x9b,
- 0xfd, 0xac, 0x39, 0xf0, 0x41, 0x75, 0x8b, 0xf3, 0x6d, 0x2d, 0xba, 0xc5,
- 0xf4, 0xf2, 0x4e, 0xb1, 0x7f, 0xa7, 0x62, 0x16, 0x77, 0xe5, 0x8b, 0x19,
- 0xd4, 0xf5, 0xfe, 0x45, 0x7f, 0x4f, 0x4d, 0x39, 0xf1, 0x62, 0xa5, 0x3c,
- 0xdc, 0x84, 0xc3, 0x91, 0xfc, 0xe1, 0xa1, 0x00, 0x45, 0x77, 0xee, 0x7b,
- 0x08, 0xd5, 0x8b, 0xcc, 0x52, 0xb1, 0x7f, 0x6a, 0x47, 0x99, 0xc5, 0x8b,
- 0xfc, 0xdd, 0xf1, 0x9b, 0xbe, 0x2c, 0x54, 0x11, 0x4d, 0x11, 0x48, 0x06,
- 0xf8, 0x5b, 0x7d, 0xc6, 0x84, 0x7a, 0xc5, 0xff, 0xa1, 0xc9, 0x84, 0x83,
- 0x99, 0xd1, 0x62, 0xec, 0x3a, 0xc5, 0xe9, 0x1b, 0xac, 0x5f, 0xed, 0x19,
- 0xee, 0x6d, 0x81, 0xac, 0x5d, 0xa8, 0xf5, 0x8b, 0xfc, 0xda, 0xdf, 0x05,
- 0xad, 0x96, 0x2f, 0xfb, 0x35, 0x9f, 0x7d, 0x7d, 0x96, 0x2d, 0x3b, 0x1f,
- 0x76, 0xe6, 0xd7, 0xff, 0x7b, 0xc2, 0xec, 0xb0, 0x1c, 0x98, 0xf5, 0x8b,
- 0xff, 0xcf, 0xcc, 0x1e, 0xa4, 0x5e, 0x27, 0xe8, 0xb1, 0x7f, 0x40, 0xcc,
- 0xfb, 0x1d, 0x62, 0x96, 0x2c, 0xc4, 0x6e, 0xc3, 0x2f, 0xac, 0x47, 0xae,
- 0xe9, 0x21, 0xc2, 0x1a, 0xff, 0xe9, 0xd4, 0x37, 0xfb, 0xc4, 0x4c, 0x1a,
- 0xc5, 0xff, 0xda, 0x6d, 0x87, 0xf9, 0xe7, 0x85, 0xf5, 0x8a, 0xe2, 0x23,
- 0xbc, 0x8f, 0x7b, 0xcf, 0x12, 0xc5, 0xfd, 0x17, 0x0c, 0xc2, 0xdd, 0x62,
- 0xa0, 0xac, 0xc7, 0x07, 0x3b, 0x38, 0xd4, 0x22, 0x7f, 0x18, 0xf7, 0x21,
- 0x89, 0xe2, 0x33, 0x07, 0xab, 0x4a, 0xf3, 0x0f, 0x2d, 0x22, 0xf8, 0xb0,
- 0x11, 0xcb, 0x17, 0xd2, 0x79, 0xfa, 0xc5, 0xd3, 0xc5, 0x8b, 0xf4, 0x86,
- 0x3c, 0x3a, 0xc5, 0x9e, 0x07, 0xc4, 0x44, 0x46, 0x0b, 0xd4, 0xae, 0x7a,
- 0x64, 0xe0, 0x6b, 0x96, 0x7e, 0x10, 0xf7, 0xf3, 0x01, 0xb7, 0x6d, 0x2c,
- 0x5f, 0x03, 0x32, 0x3d, 0x62, 0xfd, 0xbb, 0x3e, 0xd8, 0xb1, 0x69, 0x39,
- 0xe7, 0x11, 0x2d, 0xff, 0xed, 0x37, 0xe1, 0x9e, 0xe3, 0x6c, 0x28, 0x2c,
- 0x5f, 0xff, 0xcd, 0x9b, 0xf3, 0xec, 0xfe, 0x80, 0xa4, 0xa6, 0x0b, 0x17,
- 0xff, 0x88, 0xa4, 0xd3, 0xfe, 0x7b, 0xf4, 0xfd, 0x62, 0x99, 0x1e, 0x24,
- 0x98, 0x25, 0xab, 0x9a, 0x0b, 0x17, 0xff, 0xef, 0x70, 0x53, 0xf9, 0x39,
- 0x60, 0x0f, 0x30, 0x58, 0xa3, 0x9f, 0x61, 0x0b, 0xde, 0x1b, 0x7d, 0x62,
- 0xff, 0xa7, 0xf3, 0xdc, 0x21, 0x3b, 0x2c, 0x5a, 0x56, 0x2e, 0x7d, 0x2c,
- 0x5b, 0x7d, 0x1a, 0x8f, 0x88, 0xdf, 0xd1, 0xe5, 0x9b, 0x60, 0x6b, 0x15,
- 0x28, 0xfb, 0xc2, 0x1d, 0x0e, 0xb3, 0x18, 0x8a, 0x2f, 0xff, 0xfb, 0x72,
- 0x7e, 0x9c, 0xfb, 0x3f, 0xa0, 0x29, 0x6f, 0x0a, 0x56, 0x2f, 0xff, 0xff,
- 0x6a, 0x4d, 0xc8, 0xb7, 0xfb, 0xc5, 0x16, 0x17, 0x8c, 0xc8, 0xbe, 0xc3,
- 0x58, 0xbf, 0xfd, 0xf7, 0x38, 0xe7, 0xac, 0x70, 0xbe, 0xfa, 0x58, 0xbf,
- 0xbd, 0x3f, 0x29, 0x82, 0xc5, 0xff, 0xff, 0x7d, 0x9f, 0xd0, 0x14, 0x94,
- 0xc2, 0x0f, 0xad, 0x84, 0x05, 0x8a, 0xea, 0x8e, 0x47, 0x50, 0xe1, 0x6d,
- 0x2c, 0x5f, 0x98, 0xd7, 0xd4, 0xc0, 0xde, 0xfc, 0xc6, 0x9d, 0x52, 0x23,
- 0x34, 0x14, 0x73, 0xf7, 0xde, 0xdb, 0x03, 0x58, 0xbb, 0x52, 0xb1, 0x66,
- 0x23, 0x79, 0xe2, 0x5b, 0xf4, 0xeb, 0x4d, 0x12, 0xc5, 0xcf, 0xda, 0xc5,
- 0xfe, 0x00, 0xb0, 0x07, 0x68, 0x2c, 0x5d, 0x92, 0xb1, 0x50, 0x3e, 0x2e,
- 0xc6, 0x0e, 0x69, 0x5b, 0x22, 0xed, 0xa1, 0x17, 0x7f, 0xf7, 0x70, 0x72,
- 0xf6, 0x38, 0xf0, 0x6b, 0x17, 0xff, 0xf3, 0xf7, 0x25, 0x3c, 0x1f, 0xe7,
- 0x8e, 0x5d, 0xc1, 0x62, 0xba, 0xa2, 0x7f, 0xe8, 0x97, 0xff, 0xfd, 0xf6,
- 0x1f, 0xdc, 0x9b, 0xd3, 0x13, 0x9a, 0xe5, 0x9d, 0x16, 0x2f, 0xf9, 0xfd,
- 0x9a, 0xd0, 0xb6, 0xe8, 0xb1, 0x7f, 0xdc, 0xcf, 0x0f, 0x30, 0x1c, 0x58,
- 0xaf, 0x9f, 0xb7, 0x8f, 0x6f, 0xf9, 0xfd, 0x9a, 0xd0, 0xb6, 0xe8, 0xb1,
- 0x70, 0x8b, 0xa9, 0xef, 0xfc, 0x8a, 0xa5, 0x39, 0x0c, 0x25, 0xe4, 0x67,
- 0x95, 0x06, 0x77, 0xa0, 0xe7, 0x46, 0xb1, 0x28, 0xd7, 0xcd, 0xe3, 0x17,
- 0xd4, 0x72, 0xbf, 0x95, 0x16, 0x07, 0x12, 0x87, 0x07, 0x25, 0x2b, 0xdf,
- 0xe9, 0x6d, 0x7c, 0x36, 0x1a, 0xc5, 0xd9, 0x05, 0x8b, 0xce, 0x39, 0x58,
- 0xa1, 0x9f, 0x3c, 0x46, 0x87, 0x17, 0xbf, 0x9f, 0xfa, 0xd3, 0xec, 0xb1,
- 0x52, 0x7b, 0xff, 0x30, 0xb8, 0x3f, 0x2c, 0x5f, 0x3f, 0x30, 0xeb, 0x17,
- 0xff, 0x10, 0xb3, 0x8f, 0xcc, 0xfe, 0x6e, 0xb1, 0x7e, 0xd1, 0xd9, 0x86,
- 0xb1, 0x7f, 0xfe, 0x63, 0xf5, 0xe0, 0xa7, 0xbc, 0xf7, 0x32, 0x77, 0x58,
- 0xac, 0x44, 0x0f, 0xca, 0x2f, 0xfe, 0x77, 0xfc, 0x59, 0xe9, 0xf4, 0x8d,
- 0x62, 0xf1, 0xad, 0xc5, 0x8b, 0xd3, 0xa0, 0x2c, 0x5a, 0x7c, 0x6e, 0xcc,
- 0x1e, 0xbe, 0xf7, 0xa4, 0x0b, 0x17, 0xc6, 0x1a, 0x61, 0xab, 0x16, 0x95,
- 0x8b, 0xff, 0xe9, 0xee, 0x0c, 0x40, 0xea, 0x07, 0xd3, 0x9a, 0xb1, 0x52,
- 0xa9, 0xde, 0x03, 0x38, 0x44, 0xf0, 0xc5, 0x88, 0x8b, 0xef, 0xe2, 0x27,
- 0x0c, 0x8e, 0x38, 0xa0, 0x20, 0x8d, 0xfd, 0x0c, 0xf3, 0x94, 0xac, 0x5f,
- 0xdd, 0xc5, 0xf9, 0x23, 0x56, 0x2f, 0xff, 0x4e, 0xb5, 0x9d, 0xfa, 0x4f,
- 0x3d, 0xc1, 0x62, 0xa4, 0xff, 0x43, 0x31, 0xb8, 0xa2, 0x58, 0xbd, 0xcf,
- 0xba, 0xc5, 0x1c, 0xda, 0xf8, 0x62, 0xff, 0xf6, 0xb0, 0x73, 0xf7, 0x83,
- 0x42, 0x74, 0xb1, 0x7d, 0xb1, 0xde, 0x0b, 0x17, 0xfe, 0x29, 0x3b, 0x38,
- 0xc5, 0xee, 0x2c, 0x5f, 0x48, 0x0c, 0x3a, 0xc5, 0xff, 0xa7, 0xdf, 0x9e,
- 0x4c, 0x05, 0xa5, 0x8b, 0xe2, 0x13, 0x41, 0x62, 0xa0, 0x8c, 0x3d, 0xcf,
- 0x88, 0x93, 0x87, 0xf7, 0xf4, 0x9e, 0x30, 0x00, 0x95, 0x8b, 0xc1, 0x79,
- 0xf2, 0xc5, 0xfc, 0xdb, 0xf5, 0x9c, 0xe2, 0xc5, 0xfa, 0x70, 0xbd, 0xc5,
- 0x8a, 0x19, 0xeb, 0x9c, 0xc2, 0xbe, 0x8c, 0xb1, 0x18, 0x84, 0x78, 0xa9,
- 0x54, 0x43, 0x90, 0xe7, 0x78, 0xc2, 0x2f, 0xbc, 0xe5, 0x05, 0x8b, 0xf3,
- 0xff, 0xd9, 0xba, 0xc5, 0xec, 0x20, 0x2c, 0x54, 0x0f, 0x9e, 0x22, 0x20,
- 0x85, 0x37, 0xb8, 0x23, 0xac, 0x5f, 0xfe, 0xfc, 0x9e, 0x45, 0xdc, 0xb9,
- 0x61, 0xab, 0x17, 0xe9, 0x8b, 0x9e, 0x75, 0x8a, 0xea, 0xb9, 0xdf, 0x30,
- 0xa9, 0xc5, 0x77, 0x21, 0xd4, 0xa6, 0xa6, 0x85, 0x08, 0x0c, 0xbc, 0x3c,
- 0x62, 0x55, 0xff, 0xfd, 0x3a, 0x9e, 0x7d, 0x9f, 0xd0, 0x14, 0x94, 0xc1,
- 0x62, 0xff, 0x0c, 0xc9, 0x8f, 0xf8, 0xb8, 0xb1, 0x7e, 0x08, 0xe7, 0xcf,
- 0x2c, 0x5f, 0xbd, 0x9e, 0x29, 0x58, 0xbf, 0x9e, 0x79, 0xd4, 0x9d, 0x62,
- 0xb6, 0x4c, 0x47, 0xb5, 0x93, 0x9c, 0x91, 0x57, 0x89, 0xef, 0x09, 0xb8,
- 0xb1, 0x74, 0x86, 0xb1, 0x5a, 0x36, 0xbc, 0x1d, 0xbf, 0xf9, 0xf8, 0xc1,
- 0xfb, 0xaf, 0x20, 0xe6, 0xac, 0x5f, 0xef, 0xe6, 0x7b, 0xec, 0x05, 0x8b,
- 0x7d, 0x62, 0xa0, 0x78, 0xac, 0x67, 0x79, 0xf6, 0x95, 0x8b, 0xa2, 0x95,
- 0x8b, 0xa7, 0xcb, 0x17, 0xe9, 0xea, 0x64, 0x5c, 0x58, 0xa9, 0x3d, 0xc3,
- 0x46, 0x08, 0x5e, 0xf8, 0x78, 0x50, 0x58, 0xbf, 0x63, 0xc3, 0xf2, 0xb1,
- 0x74, 0x5e, 0x73, 0xc9, 0xf9, 0x15, 0xff, 0xf8, 0x7f, 0x9d, 0x38, 0x24,
- 0xc9, 0x88, 0xa4, 0xeb, 0x17, 0xf8, 0xd9, 0x2f, 0x71, 0xbe, 0xb1, 0x52,
- 0x8b, 0x87, 0x2e, 0x65, 0x6b, 0xf1, 0x63, 0x16, 0xcb, 0x17, 0xf7, 0x7c,
- 0x69, 0x7d, 0x2c, 0x54, 0xab, 0x7b, 0xc8, 0x40, 0xee, 0x42, 0xf0, 0x8e,
- 0xd1, 0x0b, 0x3c, 0x94, 0x65, 0xfc, 0x2d, 0x11, 0x3d, 0x2c, 0x5d, 0x9a,
- 0x58, 0xa3, 0x4d, 0x1b, 0x06, 0x5f, 0xf6, 0x72, 0x47, 0xc9, 0x71, 0xac,
- 0x5f, 0xd3, 0xb6, 0xa7, 0x06, 0xb1, 0x7f, 0xec, 0x3f, 0x3f, 0x3d, 0xfa,
- 0x7e, 0xb1, 0x79, 0xa2, 0x95, 0x8b, 0xfb, 0xf3, 0xef, 0x49, 0xd6, 0x2f,
- 0xff, 0xed, 0x60, 0xf8, 0x42, 0xc8, 0x09, 0x87, 0xcc, 0xd2, 0xc5, 0x0d,
- 0x11, 0x2e, 0x5d, 0x5a, 0x4e, 0x3c, 0xe4, 0x3f, 0x38, 0xf1, 0x77, 0x44,
- 0x03, 0x21, 0x4d, 0x7c, 0x52, 0x7e, 0x2c, 0x5e, 0x3b, 0x76, 0xb1, 0xe3,
- 0x45, 0x77, 0xb7, 0x58, 0xbe, 0x7d, 0x03, 0x8b, 0x15, 0x87, 0xd5, 0xa2,
- 0xef, 0x0c, 0xdf, 0xc5, 0x3d, 0x40, 0x09, 0x58, 0xbe, 0x60, 0x4c, 0x16,
- 0x2f, 0x81, 0xd0, 0x2a, 0x14, 0x58, 0xbf, 0xe3, 0xe4, 0x27, 0x40, 0xc2,
- 0x58, 0xb4, 0x3e, 0x7c, 0xc6, 0x17, 0x5f, 0xcc, 0x53, 0xff, 0xca, 0xc5,
- 0xfd, 0xa6, 0x98, 0x4c, 0x16, 0x2f, 0xff, 0xd3, 0x0e, 0x7d, 0x9f, 0xd0,
- 0x14, 0x94, 0xc1, 0x62, 0xfe, 0x9d, 0xf8, 0xf2, 0x75, 0x8a, 0x24, 0x41,
- 0x71, 0x52, 0xa5, 0x1a, 0x2d, 0x0a, 0xfb, 0x84, 0x4b, 0x17, 0x66, 0xeb,
- 0x17, 0x4c, 0x3e, 0x6b, 0xfc, 0x2f, 0x5d, 0xa7, 0x4f, 0x11, 0x4e, 0xa1,
- 0xfa, 0x4a, 0xb7, 0xd2, 0x53, 0x12, 0xc5, 0xff, 0xff, 0xb1, 0xfa, 0x4e,
- 0x7e, 0x5f, 0x53, 0xe7, 0xc3, 0x9e, 0x4e, 0xb1, 0x7f, 0xfc, 0x59, 0xd3,
- 0x76, 0xd6, 0xcd, 0xe6, 0xec, 0x0b, 0x17, 0x63, 0xac, 0x5f, 0xec, 0x1b,
- 0xf0, 0x36, 0xd2, 0xc5, 0x4a, 0xe7, 0x30, 0xe1, 0xd9, 0x85, 0xdb, 0x97,
- 0xbc, 0xa2, 0xf3, 0xa2, 0x7c, 0x89, 0x9a, 0x89, 0x53, 0xc2, 0xd7, 0xf8,
- 0x9b, 0x6e, 0xe1, 0x21, 0x16, 0x2f, 0xc0, 0x9c, 0xee, 0x0b, 0x17, 0xfb,
- 0x9f, 0x63, 0x3f, 0x30, 0x58, 0xad, 0x91, 0x2b, 0xb9, 0xbf, 0x65, 0x37,
- 0xfb, 0xf2, 0x7f, 0x14, 0xf6, 0xb1, 0x76, 0x44, 0xb1, 0x7e, 0x26, 0x86,
- 0x12, 0xc5, 0xfc, 0x4d, 0xf2, 0xcd, 0x2c, 0x5e, 0x21, 0x60, 0xcf, 0x4b,
- 0xc4, 0xd7, 0xfd, 0x87, 0xce, 0x82, 0x8f, 0xc2, 0x58, 0xbf, 0xf3, 0x77,
- 0xf9, 0x70, 0x37, 0x84, 0xb1, 0x7f, 0xff, 0xa5, 0xe0, 0xdc, 0xe4, 0xe1,
- 0x4c, 0x30, 0xed, 0xda, 0xc5, 0x1d, 0x13, 0xbe, 0x3f, 0xa1, 0xa3, 0xf7,
- 0x21, 0xb5, 0x50, 0x4f, 0xd3, 0x0d, 0x19, 0xab, 0x91, 0x97, 0xdf, 0xbf,
- 0x31, 0x3f, 0xd6, 0x2e, 0x78, 0x2c, 0x50, 0xcf, 0x00, 0x8a, 0x6f, 0x72,
- 0x62, 0x58, 0xbe, 0xdb, 0x3b, 0x82, 0xc5, 0xa2, 0x58, 0xa9, 0x3d, 0x6c,
- 0x1e, 0x30, 0x96, 0xff, 0x1d, 0x8b, 0x34, 0x67, 0x96, 0x2f, 0xe6, 0xcd,
- 0x85, 0xa8, 0x2c, 0x5f, 0xff, 0x7e, 0x4e, 0xfa, 0x70, 0x92, 0x66, 0xd8,
- 0x1a, 0xc5, 0xfa, 0x60, 0x77, 0xf2, 0xc5, 0xff, 0x0e, 0x4c, 0x39, 0x4f,
- 0x70, 0x58, 0xa5, 0x8a, 0xc3, 0xc7, 0x73, 0xbb, 0xfb, 0x05, 0xb9, 0x99,
- 0xda, 0xc5, 0x41, 0x50, 0xe0, 0xdd, 0xf0, 0xbb, 0xb3, 0x48, 0x8b, 0xce,
- 0xa9, 0xc6, 0xfe, 0x84, 0x17, 0xfd, 0xa9, 0xe1, 0x84, 0x53, 0xa5, 0x8b,
- 0x9a, 0x39, 0x62, 0x9c, 0xf4, 0xce, 0x73, 0x7f, 0x7e, 0x7d, 0xfc, 0x02,
- 0xc5, 0xfe, 0x98, 0x85, 0xd9, 0x4c, 0x4b, 0x17, 0xfd, 0x30, 0x26, 0xf4,
- 0x1f, 0xa2, 0xc5, 0xe3, 0x24, 0x0b, 0x17, 0x82, 0x3e, 0xcb, 0x14, 0x74,
- 0x57, 0x7c, 0xdb, 0x87, 0x5e, 0x1e, 0xbe, 0xf7, 0xe4, 0x22, 0xc5, 0x2c,
- 0x5c, 0xf1, 0x2c, 0x54, 0x79, 0xa4, 0x00, 0x65, 0xff, 0x1b, 0x24, 0xc3,
- 0xfc, 0x81, 0x62, 0xff, 0xb2, 0x22, 0x9d, 0xb9, 0x3b, 0xac, 0x5d, 0x0c,
- 0x58, 0xad, 0x22, 0x2f, 0xe7, 0x3e, 0x3b, 0xbb, 0x98, 0xb1, 0x7e, 0x98,
- 0x9e, 0x78, 0xb1, 0x7f, 0x49, 0x98, 0x76, 0xed, 0x62, 0xff, 0xd3, 0xad,
- 0xfc, 0x59, 0xb3, 0x12, 0xc5, 0xf0, 0x1e, 0x78, 0xb1, 0x5f, 0x44, 0x87,
- 0x0b, 0xc4, 0x7f, 0x7f, 0xd3, 0xc6, 0xdd, 0xc7, 0xf7, 0x58, 0xbf, 0xc3,
- 0xd6, 0x0b, 0x77, 0x3a, 0xc5, 0xfb, 0x05, 0xbb, 0x9d, 0x62, 0xf7, 0xc5,
- 0xf5, 0x8b, 0x1f, 0x0f, 0xf3, 0x46, 0xac, 0x53, 0x7f, 0xdf, 0xce, 0x8c,
- 0x43, 0xc0, 0x2c, 0x54, 0x49, 0x91, 0x34, 0x2d, 0x7c, 0x67, 0x6f, 0xac,
- 0x54, 0xae, 0xca, 0x6d, 0x0c, 0x91, 0x90, 0xe4, 0x37, 0x3b, 0x3d, 0x74,
- 0x96, 0x85, 0x78, 0x0c, 0x08, 0x5f, 0xd0, 0xb8, 0x14, 0x6a, 0x41, 0x9b,
- 0x5b, 0x16, 0x2f, 0xfa, 0x2e, 0x4e, 0x10, 0xff, 0x2b, 0x16, 0x3a, 0xc5,
- 0x11, 0xe5, 0xf8, 0xe6, 0xfe, 0x7e, 0xbc, 0x72, 0x75, 0x8b, 0xf9, 0xb3,
- 0x40, 0x04, 0xac, 0x5f, 0x7d, 0xda, 0x0b, 0x17, 0xff, 0xff, 0xc5, 0x90,
- 0x16, 0xa7, 0x5a, 0xc1, 0xcb, 0x9b, 0x25, 0xbb, 0x79, 0x8d, 0x58, 0xac,
- 0x44, 0xfb, 0x11, 0x5f, 0x73, 0xb2, 0xd2, 0xc5, 0xfe, 0xd6, 0x7d, 0xca,
- 0x4e, 0xb1, 0x7f, 0xf4, 0xc7, 0xfc, 0xb3, 0xbf, 0x09, 0xb8, 0xb1, 0x7f,
- 0x4b, 0x6b, 0xd9, 0xf5, 0x8b, 0xff, 0xec, 0x72, 0xc8, 0xa7, 0x66, 0xd8,
- 0xef, 0xb2, 0xc5, 0xff, 0xe3, 0xe0, 0xe6, 0x13, 0xc0, 0x33, 0x76, 0xb1,
- 0x52, 0x9a, 0x11, 0xcc, 0xbe, 0x91, 0xc2, 0xd3, 0x14, 0x6b, 0xaa, 0xb4,
- 0x99, 0x5c, 0xf9, 0x0b, 0x17, 0x72, 0x19, 0x9e, 0x21, 0x14, 0x6c, 0xd7,
- 0xfd, 0xe6, 0xe6, 0x7f, 0xee, 0x75, 0x8b, 0xbf, 0xc5, 0x8b, 0xec, 0xe9,
- 0x84, 0xb1, 0x7f, 0xb9, 0x8e, 0x36, 0x7d, 0x96, 0x2a, 0x4f, 0x5b, 0x08,
- 0xef, 0xfc, 0x4c, 0x0c, 0x2f, 0x71, 0xa0, 0xb1, 0x52, 0x98, 0x21, 0xa7,
- 0x3a, 0x6e, 0xf1, 0x05, 0xf8, 0xa7, 0x69, 0xd9, 0x62, 0x86, 0x7c, 0xf1,
- 0x1f, 0x5f, 0xc3, 0x96, 0xd0, 0x04, 0xb1, 0x7f, 0x49, 0x00, 0xed, 0x05,
- 0x8b, 0xb3, 0xeb, 0x15, 0xb1, 0xf9, 0x7c, 0xbb, 0xa1, 0x6d, 0xfb, 0x4c,
- 0xfa, 0xc5, 0x8b, 0xfb, 0x06, 0x07, 0x2f, 0x2c, 0x5f, 0xbf, 0x39, 0xa8,
- 0x2c, 0x5f, 0xfc, 0x77, 0x03, 0x78, 0xb3, 0x6d, 0x4a, 0xc5, 0x2c, 0x5b,
- 0x1c, 0xf4, 0x3c, 0x89, 0x7b, 0xfe, 0x75, 0x8b, 0xff, 0xec, 0xdb, 0x52,
- 0x60, 0xdb, 0x6c, 0x3b, 0x76, 0xb1, 0x7f, 0x47, 0xe7, 0x42, 0xc8, 0x2c,
- 0x5f, 0xa0, 0x67, 0xf0, 0x22, 0xc5, 0xcf, 0x12, 0xc5, 0x39, 0xfb, 0x31,
- 0x97, 0x8b, 0x2f, 0x7f, 0xf2, 0xb1, 0x7f, 0x1a, 0xd0, 0xe3, 0x8d, 0x62,
- 0xb0, 0xf3, 0x1c, 0x76, 0xa5, 0x59, 0xc6, 0x42, 0x55, 0xcc, 0xb4, 0x4e,
- 0x72, 0xdf, 0xbc, 0x31, 0x31, 0x0e, 0xf2, 0x19, 0x3e, 0x79, 0xb8, 0x50,
- 0x58, 0xbf, 0xbe, 0xfa, 0xd6, 0x79, 0x62, 0xff, 0xfd, 0xc6, 0x8f, 0x1f,
- 0xe7, 0x1f, 0x53, 0xe9, 0xfa, 0xc5, 0x6c, 0x89, 0xdd, 0xc6, 0x3b, 0x2e,
- 0xbe, 0x63, 0xcc, 0x7a, 0xc5, 0xe1, 0xcc, 0x16, 0x2e, 0x7e, 0x7c, 0xf0,
- 0x84, 0x4b, 0x74, 0xc1, 0x62, 0xff, 0xe8, 0x3f, 0x49, 0xd6, 0x3c, 0x05,
- 0xa5, 0x8b, 0xe9, 0x07, 0x31, 0x62, 0xfc, 0xe1, 0x23, 0xd8, 0xeb, 0x15,
- 0x12, 0x25, 0x7e, 0x8d, 0xc2, 0x2b, 0x85, 0x05, 0x8a, 0xd2, 0x64, 0x5f,
- 0x2d, 0x68, 0x56, 0x74, 0x31, 0xbf, 0x1d, 0x8b, 0xb8, 0x2c, 0x5c, 0xd0,
- 0x58, 0xbf, 0x17, 0xa3, 0xa4, 0xeb, 0x15, 0x27, 0xd6, 0xc5, 0x22, 0x17,
- 0xbc, 0xe1, 0xee, 0xb1, 0x78, 0x2d, 0x85, 0x91, 0xa2, 0xc5, 0xec, 0x1e,
- 0x2c, 0x5e, 0xf3, 0x81, 0x62, 0xa3, 0xd1, 0x0c, 0x71, 0xff, 0x97, 0x78,
- 0x72, 0xfd, 0xa1, 0xe1, 0x1a, 0xb1, 0x68, 0x2c, 0x5f, 0xfa, 0x7e, 0x26,
- 0x33, 0x3a, 0x36, 0x96, 0x29, 0xcf, 0x4f, 0x82, 0x57, 0x9c, 0x86, 0xb1,
- 0x52, 0x8f, 0x96, 0x40, 0xf3, 0xe7, 0x42, 0x1b, 0xff, 0xc0, 0xf8, 0x6d,
- 0xe7, 0xe7, 0xe4, 0xbc, 0xb1, 0x7a, 0x4a, 0x56, 0x2b, 0x47, 0xcc, 0x1a,
- 0x5d, 0xfe, 0x3f, 0x1e, 0x3b, 0x35, 0x2b, 0x17, 0x1f, 0x4b, 0x17, 0x8d,
- 0x3b, 0xac, 0x56, 0x1b, 0x66, 0x18, 0xbc, 0xe7, 0x75, 0x8a, 0x94, 0x65,
- 0x61, 0x19, 0x36, 0x78, 0x7e, 0x82, 0x8f, 0xa7, 0xae, 0x16, 0xe1, 0x93,
- 0x1a, 0xca, 0x26, 0x50, 0xe6, 0xd1, 0x99, 0x42, 0x70, 0xcc, 0x73, 0xba,
- 0x79, 0x1f, 0xf6, 0xf2, 0x87, 0x3b, 0x8c, 0x0d, 0xe9, 0xe6, 0x51, 0xf1,
- 0xbe, 0x45, 0x2a, 0x63, 0x53, 0xb0, 0xa7, 0x9d, 0x1d, 0xfc, 0xf9, 0x23,
- 0x46, 0x56, 0x09, 0x44, 0xe5, 0x48, 0x32, 0xe4, 0xe0, 0x4f, 0xa7, 0x45,
- 0x05, 0x19, 0x7f, 0x48, 0xe5, 0xe3, 0xa1, 0x5e, 0x64, 0x75, 0x81, 0x23,
- 0x6d, 0xb3, 0xac, 0x5d, 0xd4, 0x0b, 0x15, 0xd4, 0xd5, 0xf0, 0x46, 0xe3,
- 0x7c, 0xb1, 0x7f, 0xff, 0xa3, 0x69, 0xc0, 0xb5, 0xd4, 0x6d, 0x1a, 0xba,
- 0x47, 0xc6, 0xb1, 0x75, 0xeb, 0xf8, 0xe5, 0x8b, 0x05, 0x16, 0x28, 0x2c,
- 0x45, 0x1c, 0x50, 0x8d, 0xbf, 0x81, 0xc8, 0x8a, 0x46, 0xb1, 0x7f, 0xdd,
- 0x30, 0x7d, 0xf8, 0xb0, 0x0b, 0x16, 0x84, 0x9f, 0x5b, 0x97, 0xde, 0xf3,
- 0x18, 0xb1, 0x71, 0x87, 0x58, 0xbd, 0xfc, 0xf2, 0xc5, 0x44, 0x6d, 0x80,
- 0x33, 0x7f, 0xd9, 0xee, 0x67, 0xbf, 0x80, 0x58, 0xbf, 0xdd, 0x67, 0xa9,
- 0xdc, 0xbc, 0xb1, 0x7f, 0x9c, 0xd6, 0x2f, 0x61, 0x2c, 0x5f, 0xe6, 0x35,
- 0xf9, 0xc6, 0x75, 0x8a, 0xc4, 0xdc, 0x5c, 0x99, 0x95, 0x08, 0x8b, 0x87,
- 0x3e, 0x37, 0xe8, 0x65, 0x73, 0x12, 0xc5, 0xff, 0xb3, 0x79, 0x04, 0x97,
- 0xa3, 0xb1, 0x62, 0xb4, 0x8b, 0xa3, 0xb1, 0xf8, 0x5a, 0xec, 0x0d, 0x62,
- 0xc7, 0x58, 0xae, 0xa6, 0xa8, 0xc1, 0x8b, 0xde, 0xc3, 0xac, 0x5f, 0x42,
- 0x70, 0x96, 0x2a, 0x4d, 0xf7, 0x87, 0x6f, 0xde, 0x92, 0x70, 0x2c, 0x5d,
- 0xdf, 0x6b, 0x17, 0x75, 0xe2, 0xc5, 0xfb, 0x42, 0xe8, 0x00, 0xd6, 0x2e,
- 0x2e, 0x2c, 0x5f, 0xd8, 0x1b, 0x00, 0xf8, 0xb1, 0x7f, 0x16, 0x78, 0x4c,
- 0x1a, 0xc5, 0x75, 0x4c, 0x6f, 0x08, 0x3b, 0x27, 0x38, 0xd7, 0xc6, 0x80,
- 0x5a, 0x42, 0xfd, 0x0b, 0xaf, 0xde, 0xe3, 0xf6, 0x1a, 0xc5, 0xff, 0xa4,
- 0xef, 0xdf, 0x05, 0x10, 0x8d, 0x58, 0xbf, 0x17, 0xbf, 0x90, 0x58, 0xbb,
- 0x98, 0xb1, 0x4e, 0x6f, 0xd8, 0xa2, 0xdd, 0xac, 0x5f, 0xd2, 0x1c, 0x76,
- 0x6a, 0x56, 0x2b, 0x0f, 0x10, 0x84, 0xef, 0xff, 0xba, 0x3e, 0xb0, 0x0d,
- 0x0e, 0x39, 0x60, 0x16, 0x2f, 0xcd, 0x80, 0x33, 0xcb, 0x17, 0xfe, 0x13,
- 0xff, 0xf9, 0xad, 0x39, 0xd6, 0x2f, 0x0e, 0x42, 0x2c, 0x5f, 0x7d, 0xda,
- 0x3d, 0x62, 0x88, 0xf1, 0x3c, 0x3f, 0x5d, 0x55, 0x11, 0x42, 0x10, 0x43,
- 0x63, 0xc2, 0x03, 0x54, 0x0e, 0x52, 0xd0, 0x83, 0xad, 0x2a, 0xbe, 0x0e,
- 0x52, 0x6d, 0xf6, 0xd3, 0xee, 0x2c, 0x5e, 0x90, 0x71, 0x62, 0xb4, 0x78,
- 0x24, 0x49, 0x7c, 0xda, 0x68, 0x2c, 0x56, 0x1e, 0x19, 0x10, 0xdb, 0xcb,
- 0x17, 0xb9, 0x20, 0x58, 0xb6, 0x76, 0x6b, 0xfc, 0x25, 0x5a, 0x3f, 0x6f,
- 0xa7, 0xdf, 0xfa, 0x43, 0xee, 0x1c, 0x6f, 0xe4, 0x4b, 0x17, 0x83, 0x0c,
- 0x35, 0x8b, 0xc4, 0xf2, 0x91, 0x18, 0x68, 0x6f, 0xff, 0xff, 0x75, 0xfc,
- 0x36, 0xe4, 0x8b, 0x8e, 0x76, 0x3c, 0xb1, 0x9d, 0x7a, 0xfe, 0x39, 0x62,
- 0xb6, 0x45, 0x91, 0x85, 0xd7, 0xf7, 0xe7, 0xe5, 0x86, 0xac, 0x5e, 0x11,
- 0x79, 0x62, 0xfe, 0x62, 0x80, 0xe7, 0x65, 0x8a, 0xc3, 0xcb, 0xf8, 0xed,
- 0xff, 0x33, 0x7d, 0x99, 0x98, 0x6b, 0x14, 0x34, 0x68, 0x47, 0xbc, 0xb1,
- 0x0d, 0xec, 0x84, 0xac, 0x5f, 0xff, 0x41, 0xfd, 0x09, 0x20, 0x31, 0x3f,
- 0x70, 0x58, 0xad, 0x1f, 0x58, 0x63, 0x97, 0xcd, 0xe9, 0x1a, 0xc5, 0xec,
- 0x2d, 0xd6, 0x2f, 0x44, 0xff, 0x58, 0xbb, 0xb8, 0x2c, 0x5f, 0xed, 0x6d,
- 0x39, 0x13, 0xe9, 0x62, 0xff, 0x1b, 0x3e, 0xe7, 0xd8, 0x4b, 0x17, 0x1e,
- 0x56, 0x2f, 0xdf, 0x72, 0xef, 0x8b, 0x17, 0xe9, 0x78, 0x37, 0x16, 0x2f,
- 0xcf, 0xb6, 0x77, 0xe5, 0x8b, 0xe2, 0xc0, 0x71, 0x62, 0xff, 0x37, 0xcb,
- 0x3a, 0x36, 0xeb, 0x17, 0x37, 0x96, 0x2f, 0x6a, 0x43, 0x58, 0xa5, 0x8a,
- 0xd1, 0xaa, 0x00, 0xf5, 0xb7, 0x58, 0xbf, 0x19, 0xac, 0x10, 0xd6, 0x2b,
- 0x0f, 0x79, 0xc8, 0x78, 0x27, 0x52, 0xa8, 0xdf, 0x06, 0x4d, 0x35, 0x73,
- 0x58, 0x85, 0xf4, 0x52, 0x72, 0x76, 0x2a, 0x22, 0x2e, 0x1a, 0xfa, 0x13,
- 0xf7, 0xf7, 0x1f, 0x5b, 0xff, 0x16, 0x2f, 0xf3, 0xff, 0xf9, 0xe7, 0xe2,
- 0xc5, 0xa1, 0xd9, 0xf1, 0x70, 0xbe, 0xfd, 0x81, 0x52, 0x71, 0xac, 0x5f,
- 0x37, 0x3a, 0x41, 0x62, 0xec, 0x1a, 0xc5, 0x1a, 0x6f, 0x3a, 0x12, 0xd4,
- 0x17, 0x01, 0xfb, 0x94, 0xab, 0xa8, 0x7f, 0x00, 0xa7, 0xcc, 0xf7, 0xe6,
- 0x28, 0x39, 0xd6, 0x2f, 0x60, 0xa3, 0x96, 0x2b, 0xab, 0x63, 0x4e, 0x15,
- 0x23, 0x8d, 0x50, 0xbc, 0x99, 0x58, 0x9b, 0x2d, 0x0e, 0x37, 0xdc, 0x96,
- 0x66, 0xf1, 0x93, 0xe8, 0x8b, 0xf1, 0x8a, 0xb4, 0x3d, 0x41, 0x09, 0xd2,
- 0x23, 0xe1, 0x10, 0xa7, 0x09, 0x3a, 0x2d, 0x47, 0x13, 0xde, 0x0a, 0x05,
- 0xb8, 0xdd, 0x62, 0xff, 0xbe, 0xd1, 0x14, 0xe6, 0xa0, 0xb1, 0x7f, 0x8c,
- 0x3e, 0x0e, 0x4b, 0x75, 0x8b, 0xff, 0x31, 0x19, 0x17, 0x1c, 0xbb, 0x82,
- 0xc5, 0xff, 0x83, 0xce, 0x13, 0xce, 0xb3, 0x65, 0x8a, 0x8f, 0x47, 0x71,
- 0xce, 0x44, 0x6b, 0xd1, 0x06, 0xf8, 0x5b, 0x4c, 0x4b, 0x17, 0xff, 0xff,
- 0xfd, 0xd7, 0xf9, 0xdc, 0x3e, 0x7e, 0xbb, 0xfc, 0x5e, 0xf6, 0x17, 0xf3,
- 0xd2, 0x3e, 0xbd, 0x7f, 0x1c, 0xb1, 0x52, 0x8c, 0x98, 0xf2, 0x5b, 0xc1,
- 0x6e, 0x35, 0x05, 0x56, 0x2f, 0xed, 0xfe, 0xc1, 0xf7, 0xc5, 0x8b, 0xf0,
- 0xdf, 0xd9, 0xba, 0xc5, 0x46, 0xb4, 0x44, 0xc9, 0x71, 0xcc, 0xaf, 0xc5,
- 0x3a, 0x6e, 0x2c, 0x5f, 0xf0, 0xf0, 0x41, 0x77, 0xfb, 0x1d, 0x62, 0xfd,
- 0x27, 0x2c, 0x89, 0x63, 0x0d, 0xed, 0xff, 0x0f, 0xf3, 0x98, 0x77, 0x95,
- 0x8b, 0xc0, 0xce, 0x2c, 0x5f, 0x37, 0x67, 0xed, 0x62, 0x80, 0x78, 0x5e,
- 0x1d, 0xa9, 0x44, 0xde, 0x3c, 0xde, 0x1c, 0xc4, 0xb1, 0x7e, 0xe6, 0x7d,
- 0xfe, 0xb1, 0x7b, 0x53, 0xd1, 0x62, 0xff, 0x13, 0x07, 0xec, 0x23, 0x56,
- 0x2f, 0x74, 0xc1, 0xac, 0x5f, 0xdf, 0x79, 0x21, 0x4a, 0xc5, 0xfe, 0x98,
+ 0x09, 0xf8, 0x7c, 0x58, 0xbe, 0x68, 0x49, 0x2c, 0x5f, 0x85, 0xcf, 0xb4,
+ 0x20, 0x7a, 0xdf, 0x35, 0xbf, 0x98, 0x18, 0x43, 0x82, 0xc5, 0xff, 0x38,
+ 0x5c, 0xfe, 0x76, 0x9e, 0x96, 0x2f, 0xe9, 0x86, 0x6c, 0x28, 0x2c, 0x5b,
+ 0xc6, 0x9f, 0x61, 0x1e, 0xdf, 0xef, 0xe3, 0x8e, 0x4b, 0x75, 0x8b, 0x9b,
+ 0xa3, 0x0f, 0x6f, 0xc5, 0x14, 0x6a, 0xa3, 0x7e, 0x92, 0xb5, 0x08, 0xb2,
+ 0x3f, 0xe4, 0x3d, 0x2c, 0xe3, 0x5d, 0x6e, 0xdc, 0xda, 0x27, 0xcd, 0x10,
+ 0x9e, 0x15, 0x7f, 0x21, 0xef, 0xdd, 0xb8, 0x7b, 0xe9, 0x58, 0xb7, 0xe1,
+ 0xcf, 0x3c, 0xeb, 0x17, 0xec, 0xd8, 0xef, 0x12, 0xc5, 0x4a, 0xff, 0x17,
+ 0xe7, 0xbd, 0xda, 0x13, 0x24, 0x51, 0x7f, 0xf9, 0x88, 0x00, 0x9c, 0xec,
+ 0xe5, 0xd7, 0x96, 0x2f, 0xbc, 0xe7, 0x65, 0x8b, 0xe0, 0xbe, 0x2d, 0xd6,
+ 0x2c, 0x6a, 0xc5, 0xfd, 0xfe, 0x4f, 0xa4, 0x6b, 0x15, 0x27, 0xcf, 0x84,
+ 0xce, 0x27, 0x52, 0x98, 0x06, 0x25, 0xfa, 0x11, 0x37, 0xff, 0xc2, 0xdb,
+ 0xee, 0x3c, 0xe6, 0x02, 0x7a, 0xe2, 0xc5, 0xff, 0xcd, 0xf6, 0x1c, 0x0f,
+ 0xf9, 0x0c, 0x96, 0x28, 0x91, 0x2e, 0x25, 0x2b, 0xc5, 0x27, 0x58, 0xbf,
+ 0x3f, 0x3f, 0x3a, 0x58, 0xa8, 0x8f, 0x13, 0xe3, 0x97, 0x3f, 0x96, 0x2f,
+ 0xcf, 0xb1, 0xe7, 0x75, 0x8b, 0x7c, 0xe7, 0x83, 0xe1, 0x7b, 0xff, 0xfe,
+ 0xd6, 0xc2, 0x01, 0x9e, 0xe6, 0x78, 0xcc, 0xf4, 0xe1, 0x41, 0x62, 0xa5,
+ 0x12, 0x4e, 0x51, 0x7f, 0xfd, 0xbe, 0xa7, 0xe5, 0x9e, 0xc8, 0xc0, 0x82,
+ 0x09, 0x22, 0xff, 0xfa, 0x77, 0x6e, 0xb3, 0x5a, 0xcd, 0xa7, 0x8e, 0xb1,
+ 0x4c, 0x8a, 0x82, 0x57, 0xa8, 0x2b, 0x11, 0xde, 0x19, 0x6c, 0xcd, 0xc8,
+ 0x7b, 0x7a, 0x19, 0x37, 0xb0, 0xee, 0xb1, 0x7e, 0xdc, 0x5b, 0x94, 0xac,
+ 0x5f, 0xc1, 0x07, 0xad, 0x30, 0xd6, 0x2f, 0xa2, 0xfc, 0xf9, 0x62, 0x9c,
+ 0xf5, 0x78, 0x63, 0x43, 0x45, 0xe6, 0xe3, 0x91, 0x3f, 0xdf, 0xd1, 0xaa,
+ 0x35, 0xfb, 0xbe, 0xfb, 0xc8, 0xf5, 0x8b, 0xef, 0x6e, 0x2d, 0x96, 0x2f,
+ 0xee, 0x1c, 0x45, 0x0e, 0x2c, 0x51, 0x1e, 0xaf, 0x89, 0xaf, 0xfe, 0xea,
+ 0x05, 0x30, 0xd4, 0xf9, 0xbc, 0xb1, 0x7c, 0x2e, 0xfe, 0x39, 0xd6, 0x2f,
+ 0xf8, 0x61, 0xcf, 0x51, 0xd9, 0xa9, 0x58, 0xba, 0x60, 0xb1, 0x52, 0x8e,
+ 0x6c, 0x21, 0x74, 0x56, 0x2b, 0x23, 0xeb, 0xe3, 0xe9, 0xb8, 0xb1, 0x7f,
+ 0xdb, 0x66, 0xf2, 0x77, 0xe6, 0xeb, 0x17, 0xfe, 0xd7, 0xd9, 0xfc, 0x06,
+ 0x1c, 0xac, 0x54, 0x9f, 0xd3, 0x9e, 0x5f, 0x0a, 0x3e, 0x60, 0xb1, 0x7f,
+ 0xe6, 0xf4, 0xeb, 0x9f, 0x92, 0xf2, 0xc5, 0xfb, 0x20, 0xed, 0xd9, 0x62,
+ 0xbe, 0x88, 0xd2, 0x26, 0xe1, 0xf5, 0x41, 0x3b, 0xec, 0x45, 0xfc, 0x27,
+ 0x45, 0x0a, 0xdb, 0xc7, 0x6f, 0xac, 0x5f, 0xe7, 0xdd, 0xc7, 0xde, 0x7f,
+ 0x65, 0x8b, 0xff, 0xc5, 0x30, 0xd6, 0x85, 0xd3, 0xe9, 0xb8, 0xb1, 0x7f,
+ 0xfd, 0xcc, 0x34, 0xb3, 0xdc, 0xc8, 0x13, 0x04, 0xb1, 0x67, 0xfa, 0x26,
+ 0xfc, 0x97, 0x4e, 0x98, 0xdf, 0x87, 0x7b, 0x43, 0x5a, 0xff, 0x49, 0x7b,
+ 0x0a, 0x4d, 0x58, 0xbd, 0x3f, 0xe2, 0xc5, 0x76, 0x3c, 0xfe, 0xe3, 0x2b,
+ 0xfe, 0x93, 0xfb, 0xf8, 0x52, 0x05, 0x8b, 0xf1, 0xe6, 0x11, 0xfb, 0xac,
+ 0x5f, 0x8a, 0x45, 0xee, 0x2c, 0x50, 0x0f, 0x57, 0xc5, 0xb7, 0xfd, 0xc8,
+ 0x3f, 0x80, 0x19, 0x41, 0x62, 0xb6, 0x3d, 0xde, 0x88, 0xaf, 0xe2, 0xcf,
+ 0x7c, 0x30, 0x96, 0x2f, 0xe0, 0xf3, 0xb1, 0x0b, 0x8b, 0x15, 0xd1, 0xf0,
+ 0x9c, 0xc2, 0xb1, 0x15, 0x0f, 0x08, 0x5a, 0x95, 0x4c, 0xb9, 0x08, 0x67,
+ 0x27, 0xd4, 0x72, 0x57, 0xff, 0xfb, 0x7f, 0xb9, 0xc9, 0xf6, 0x9f, 0x70,
+ 0x3f, 0x7f, 0x06, 0xb1, 0x7e, 0x6f, 0x98, 0x39, 0x58, 0xae, 0x91, 0x1b,
+ 0xe6, 0x4b, 0xfe, 0xf7, 0x0b, 0x07, 0xfc, 0xf2, 0xc5, 0xff, 0x1a, 0x60,
+ 0x79, 0xa8, 0xe6, 0x35, 0x62, 0xdd, 0xfa, 0xc5, 0x49, 0xec, 0x32, 0x0d,
+ 0xff, 0xf9, 0x8d, 0xfc, 0xbc, 0x1c, 0xbd, 0x0c, 0xd6, 0x2c, 0x5f, 0xff,
+ 0xf7, 0xf0, 0xf8, 0x50, 0xfb, 0x9c, 0x4f, 0xa7, 0x8e, 0x14, 0xac, 0x51,
+ 0x22, 0xf3, 0xca, 0x95, 0x29, 0xd9, 0xe1, 0x21, 0x42, 0x44, 0x50, 0xdc,
+ 0xbf, 0xfd, 0x85, 0xf6, 0xe1, 0x61, 0xa6, 0xe4, 0x7a, 0xc5, 0xff, 0xf6,
+ 0x7d, 0x87, 0x9a, 0xd6, 0x75, 0x07, 0x3a, 0xc5, 0xff, 0x4f, 0x50, 0x16,
+ 0xc3, 0x7e, 0xcb, 0x15, 0xba, 0x36, 0xf4, 0x9b, 0xf5, 0x0b, 0xb3, 0x75,
+ 0x8b, 0xff, 0x75, 0xec, 0x21, 0x78, 0x13, 0x05, 0x8b, 0xa3, 0x8d, 0x58,
+ 0xb0, 0x30, 0xf7, 0x19, 0x02, 0xff, 0xe7, 0xe6, 0x0f, 0x79, 0xda, 0x73,
+ 0xcb, 0x17, 0xfb, 0x61, 0x61, 0x1e, 0x5d, 0x62, 0xfc, 0x2f, 0xfa, 0x62,
+ 0x58, 0xbf, 0xff, 0xbe, 0xda, 0xfb, 0x96, 0x0f, 0x4e, 0x2d, 0x83, 0x3a,
+ 0xc5, 0xff, 0xe7, 0x86, 0x10, 0x0e, 0xc3, 0xfc, 0x92, 0xc5, 0xff, 0xdb,
+ 0xbf, 0x9c, 0xe6, 0x71, 0x86, 0x35, 0x8b, 0xfe, 0xcd, 0x67, 0x0c, 0xe0,
+ 0x23, 0xd6, 0x2a, 0x51, 0x0b, 0x04, 0x7a, 0xe2, 0x3b, 0xfd, 0x0c, 0xdb,
+ 0xfd, 0x9c, 0x8b, 0xee, 0x17, 0x96, 0x2f, 0xf7, 0xd8, 0xe3, 0xc3, 0x0e,
+ 0xb1, 0x7f, 0xda, 0xd4, 0xe3, 0x6b, 0xa8, 0x2c, 0x5f, 0xcf, 0x16, 0x9c,
+ 0x2d, 0x96, 0x2e, 0x04, 0xac, 0x54, 0xa3, 0xb4, 0x66, 0xce, 0x6b, 0xf3,
+ 0xa0, 0x18, 0xdf, 0xfb, 0xef, 0xdb, 0x23, 0xc6, 0x4d, 0xa5, 0x8b, 0xe1,
+ 0x6d, 0xd4, 0x7a, 0xc5, 0x6e, 0x7d, 0x84, 0x87, 0x7f, 0x38, 0xcf, 0x23,
+ 0x95, 0x8b, 0xfd, 0x27, 0x98, 0xc0, 0x82, 0x09, 0x62, 0x86, 0xae, 0x79,
+ 0xe3, 0x4c, 0xe4, 0x62, 0xbe, 0x85, 0xa4, 0x71, 0x17, 0x71, 0x6d, 0xff,
+ 0xe9, 0xd8, 0xb3, 0x36, 0xf1, 0xb2, 0x50, 0x58, 0xbf, 0xdb, 0x7d, 0x8e,
+ 0xfc, 0x75, 0x8b, 0xfc, 0x36, 0x60, 0x83, 0xce, 0x96, 0x2c, 0xc4, 0x7d,
+ 0x5e, 0x34, 0xa9, 0x5e, 0x55, 0xd8, 0xc7, 0x1d, 0x37, 0x26, 0x74, 0x5f,
+ 0x99, 0xb4, 0xbc, 0x82, 0x6f, 0x0a, 0x16, 0xb7, 0xfc, 0x3f, 0xce, 0x0c,
+ 0xb3, 0xb2, 0xc5, 0xf9, 0x8f, 0xec, 0xdd, 0x62, 0xff, 0xd1, 0xff, 0xcc,
+ 0x19, 0x66, 0xd2, 0xb1, 0x5f, 0x3e, 0xa1, 0x14, 0xdf, 0xff, 0xbe, 0xe5,
+ 0x9b, 0x1c, 0x5f, 0xcf, 0xb7, 0x40, 0x58, 0xbf, 0xf0, 0xbd, 0xc0, 0xf6,
+ 0xe0, 0x01, 0x2b, 0x17, 0xf9, 0xf8, 0xe2, 0xef, 0xc7, 0x2b, 0x14, 0x33,
+ 0xfb, 0xf2, 0x1d, 0xc2, 0x89, 0x62, 0xf0, 0x41, 0x04, 0x91, 0x7d, 0xb1,
+ 0xdf, 0x89, 0x11, 0x86, 0x86, 0xe9, 0x1a, 0xc5, 0x4a, 0x22, 0x18, 0xe8,
+ 0x8d, 0xef, 0xfe, 0x19, 0x9e, 0x29, 0x86, 0x6c, 0x28, 0x2c, 0x5f, 0x7d,
+ 0xbf, 0x2b, 0x15, 0x87, 0xd2, 0x1a, 0x3d, 0xff, 0x3f, 0x26, 0x11, 0x7d,
+ 0xc0, 0xb1, 0x7f, 0xb3, 0xad, 0x64, 0x73, 0x81, 0x62, 0xa0, 0xad, 0xac,
+ 0x70, 0xa4, 0x34, 0x89, 0xe1, 0xa5, 0xa8, 0x55, 0x1e, 0x12, 0xdf, 0x22,
+ 0x23, 0xab, 0xff, 0xf7, 0x0b, 0x3f, 0xe2, 0x90, 0x42, 0x67, 0x8e, 0xb1,
+ 0x6f, 0xac, 0x57, 0x47, 0xca, 0x1a, 0x9d, 0xa0, 0xb1, 0x7f, 0x8a, 0x1f,
+ 0xcd, 0x67, 0x4b, 0x15, 0x27, 0x8c, 0x21, 0x2b, 0xf7, 0xb9, 0xee, 0x77,
+ 0x8b, 0x17, 0xe9, 0xc2, 0x63, 0xac, 0x5f, 0xf9, 0xa1, 0xf7, 0xe8, 0x1a,
+ 0x61, 0xac, 0x5c, 0x38, 0xf5, 0x8b, 0xde, 0xd6, 0x2c, 0x5c, 0x30, 0x96,
+ 0x2f, 0xff, 0xd9, 0xda, 0x4b, 0xc7, 0x9c, 0x21, 0xe7, 0x5e, 0x58, 0xbc,
+ 0xc5, 0xb9, 0x88, 0xa7, 0x91, 0xbd, 0x87, 0x74, 0x33, 0x4e, 0xa8, 0x58,
+ 0xed, 0x4c, 0x42, 0x02, 0xf2, 0x26, 0x14, 0x39, 0xef, 0xb6, 0x9d, 0x6c,
+ 0xb1, 0x73, 0xf4, 0xb1, 0x5a, 0x37, 0xa1, 0x92, 0xdf, 0x9c, 0xbc, 0x19,
+ 0xd6, 0x2a, 0x4f, 0x2c, 0x04, 0x57, 0xbc, 0xf1, 0x2c, 0x5f, 0x66, 0x6b,
+ 0x8b, 0x16, 0xe6, 0x1e, 0x00, 0x07, 0xaa, 0x08, 0x88, 0xf3, 0x0d, 0xff,
+ 0xc7, 0x17, 0xcd, 0x6c, 0xe7, 0xf3, 0x8b, 0x17, 0xa4, 0x27, 0x58, 0xbf,
+ 0xff, 0x7d, 0xf7, 0xfe, 0x7b, 0xee, 0xc0, 0xfb, 0x81, 0x62, 0xff, 0xf1,
+ 0xac, 0x42, 0x60, 0xf9, 0xe9, 0xe8, 0x25, 0x8b, 0xff, 0xdf, 0xce, 0x73,
+ 0x0e, 0x37, 0xed, 0x23, 0x58, 0xbf, 0xa4, 0xf1, 0x7d, 0xf4, 0xb1, 0x7e,
+ 0xe6, 0x1d, 0xba, 0x58, 0xbf, 0x1a, 0x66, 0x66, 0x96, 0x2b, 0x0f, 0x4c,
+ 0x45, 0x37, 0xee, 0x3e, 0x10, 0x16, 0x2b, 0x47, 0x91, 0xc2, 0x1b, 0xda,
+ 0xc8, 0xf5, 0x8b, 0xff, 0xc2, 0xe7, 0xdf, 0x22, 0x7d, 0xb3, 0xaf, 0x2c,
+ 0x5f, 0xf0, 0x41, 0xed, 0xcc, 0x3c, 0xc7, 0xac, 0x5f, 0xfe, 0x17, 0x59,
+ 0xa0, 0xfd, 0xcc, 0x35, 0xf4, 0xb1, 0x7f, 0xf6, 0xf8, 0x43, 0xd3, 0x6f,
+ 0x9d, 0x79, 0x62, 0xff, 0xcc, 0x7c, 0x87, 0xf1, 0xe1, 0xc5, 0x8a, 0x74,
+ 0x42, 0xfd, 0x1e, 0xa5, 0x33, 0x5f, 0xa0, 0x72, 0x1a, 0x77, 0xcc, 0x0f,
+ 0x77, 0xeb, 0x15, 0xb2, 0xe1, 0xf0, 0xd1, 0xb0, 0x74, 0xd5, 0x6d, 0xd3,
+ 0xa2, 0x4c, 0xd4, 0x32, 0x8e, 0x44, 0x44, 0x1e, 0x8e, 0x08, 0x23, 0x5b,
+ 0xf6, 0x75, 0xef, 0xca, 0xc5, 0xff, 0x87, 0x90, 0x7f, 0xcf, 0x3c, 0xeb,
+ 0x17, 0xe7, 0xed, 0xe9, 0xc5, 0x8b, 0xfc, 0xfd, 0xba, 0x92, 0x9e, 0x2c,
+ 0x5f, 0xd2, 0x5f, 0x66, 0x3a, 0xc5, 0x40, 0xf8, 0x40, 0x6b, 0x5f, 0x4c,
+ 0x4d, 0x8a, 0x78, 0x7d, 0xe8, 0x45, 0x54, 0xaf, 0x2f, 0xe4, 0xe3, 0x0b,
+ 0x47, 0x79, 0x7f, 0x4f, 0xb8, 0x19, 0x41, 0x62, 0xfa, 0x77, 0xc2, 0x58,
+ 0xbf, 0x73, 0x93, 0xa8, 0x68, 0xf4, 0x7e, 0x5f, 0x76, 0xdb, 0x2c, 0x53,
+ 0x9e, 0xc8, 0x47, 0xf7, 0xf0, 0x79, 0xa8, 0xe6, 0x35, 0x62, 0xfd, 0x9a,
+ 0x8e, 0x63, 0x56, 0x2e, 0xce, 0x18, 0x7b, 0xe1, 0x99, 0xdf, 0xfe, 0x88,
+ 0xa7, 0xdc, 0xf7, 0x5b, 0xb9, 0x6c, 0xb1, 0x7f, 0xc5, 0xed, 0x33, 0x75,
+ 0x0e, 0x2c, 0x5f, 0xf1, 0xb8, 0x41, 0xce, 0xb0, 0x6b, 0x15, 0x87, 0xe8,
+ 0x23, 0xab, 0xfe, 0x63, 0x4c, 0xfc, 0x82, 0x63, 0xd6, 0x2f, 0xd0, 0xce,
+ 0xcf, 0xa5, 0x8b, 0xfc, 0x10, 0x79, 0x17, 0x0f, 0xc5, 0x8a, 0x93, 0xe2,
+ 0x62, 0xaa, 0xc4, 0xf4, 0x9c, 0xbf, 0xf0, 0xc2, 0x62, 0x12, 0x85, 0x05,
+ 0xff, 0xff, 0x80, 0x19, 0x66, 0xb5, 0x81, 0x64, 0x7e, 0x14, 0x80, 0xed,
+ 0x05, 0x8b, 0xff, 0xff, 0xed, 0xf0, 0x9f, 0xae, 0x16, 0x7b, 0x99, 0x02,
+ 0x60, 0xba, 0xf0, 0x9b, 0x8b, 0x17, 0xde, 0xf4, 0x9d, 0x62, 0xf1, 0x67,
+ 0x00, 0x8a, 0x20, 0x9f, 0xec, 0xe4, 0x9a, 0x2f, 0x68, 0xc4, 0x6f, 0xff,
+ 0xef, 0x70, 0x43, 0xfb, 0xe4, 0x4c, 0xf1, 0xef, 0xd4, 0x16, 0x2f, 0xff,
+ 0xe2, 0xc0, 0x31, 0x03, 0x5a, 0xc0, 0xb0, 0x0d, 0xd2, 0xc5, 0x12, 0x2e,
+ 0xfc, 0xc1, 0x7d, 0xed, 0xb0, 0x25, 0x8b, 0xff, 0x81, 0x21, 0x8e, 0x75,
+ 0x17, 0xdc, 0x0b, 0x14, 0xe7, 0xd8, 0x02, 0x5b, 0xff, 0x9c, 0xb6, 0x38,
+ 0xba, 0xf1, 0x37, 0xd6, 0x2f, 0xc4, 0x2f, 0x4f, 0x16, 0x2e, 0x9d, 0xe4,
+ 0xfb, 0xbe, 0x8d, 0x7e, 0x8a, 0x0f, 0xae, 0x2c, 0x5f, 0xf4, 0xef, 0x27,
+ 0xc1, 0xb1, 0xd6, 0x2b, 0x47, 0xc7, 0xdc, 0x55, 0x7f, 0xf6, 0xb5, 0x27,
+ 0xe0, 0x64, 0x53, 0xd2, 0xc5, 0xf4, 0x02, 0x17, 0x4b, 0x17, 0x8a, 0x77,
+ 0x58, 0xad, 0x8f, 0x0c, 0x32, 0x6a, 0xd9, 0x15, 0xb1, 0xf0, 0x89, 0xa7,
+ 0x47, 0xf3, 0x43, 0x4a, 0xff, 0xe8, 0x73, 0x24, 0x6e, 0x4d, 0xa3, 0x56,
+ 0x2f, 0xda, 0x9c, 0x1b, 0xac, 0x5f, 0xdf, 0x71, 0x8f, 0x02, 0x58, 0xbf,
+ 0x6b, 0x3b, 0x7f, 0x0c, 0x3d, 0x6d, 0xc9, 0xea, 0x51, 0xb8, 0xd0, 0x9a,
+ 0xbf, 0xff, 0xfe, 0x07, 0x32, 0x1f, 0x97, 0xd0, 0x01, 0x3a, 0xc1, 0x1a,
+ 0x37, 0xd3, 0x71, 0x62, 0xff, 0xfb, 0xf9, 0x03, 0x37, 0xfb, 0xfb, 0xad,
+ 0xdf, 0x4b, 0x15, 0x28, 0xd3, 0xf3, 0xf5, 0xfe, 0x9d, 0xb7, 0x79, 0x28,
+ 0x2c, 0x5f, 0xff, 0xdd, 0xfb, 0xfb, 0xf3, 0xad, 0x3f, 0x5f, 0xcc, 0x2d,
+ 0xd6, 0x2a, 0x0b, 0xc9, 0x0f, 0x0e, 0xbd, 0x42, 0x38, 0xf0, 0x8f, 0xfc,
+ 0x71, 0xc0, 0x8c, 0x08, 0xa1, 0xf3, 0xe2, 0x21, 0x1a, 0x5f, 0xe9, 0xce,
+ 0x6b, 0x3a, 0x82, 0xc5, 0xff, 0xef, 0x49, 0xf7, 0x61, 0xe0, 0x41, 0xea,
+ 0x0b, 0x17, 0xfe, 0xfc, 0x91, 0xbb, 0xbc, 0x94, 0x16, 0x2f, 0x6d, 0xd8,
+ 0x6b, 0x15, 0x03, 0xe0, 0x23, 0xfb, 0xc1, 0x30, 0x4b, 0x17, 0xfe, 0x6d,
+ 0x18, 0x4d, 0xe8, 0x30, 0xd6, 0x2f, 0xff, 0xe7, 0x21, 0xeb, 0x37, 0xfc,
+ 0xff, 0x35, 0xa9, 0x35, 0x62, 0xff, 0x98, 0x2f, 0x67, 0xf5, 0x1e, 0x35,
+ 0x8a, 0x82, 0x36, 0x7e, 0x7e, 0x4b, 0x97, 0xf3, 0x37, 0xa3, 0x9f, 0x75,
+ 0x8b, 0xff, 0xb3, 0xed, 0xee, 0x75, 0x01, 0x37, 0x96, 0x2f, 0xff, 0xe6,
+ 0x29, 0xcf, 0x45, 0xf9, 0xd8, 0xb3, 0xb3, 0x92, 0xc5, 0x1a, 0x8a, 0x16,
+ 0x46, 0xbc, 0x4d, 0x1e, 0xb1, 0x7d, 0xa7, 0xcf, 0xac, 0x5f, 0xd8, 0x1e,
+ 0x69, 0xc9, 0x62, 0x86, 0x7d, 0xda, 0x1f, 0xec, 0x45, 0x7f, 0xff, 0xff,
+ 0x73, 0x93, 0xad, 0xf7, 0xfb, 0xc4, 0xcd, 0xac, 0xeb, 0xdd, 0x6e, 0x26,
+ 0x2e, 0xbc, 0xb1, 0x7f, 0x79, 0xe2, 0xf6, 0x47, 0xac, 0x56, 0x91, 0x85,
+ 0xe8, 0x48, 0x5f, 0xf1, 0xd8, 0x61, 0xf7, 0x49, 0x41, 0x62, 0xff, 0xb7,
+ 0x14, 0x7f, 0x1c, 0x2c, 0xd2, 0xc5, 0x49, 0xfe, 0x6e, 0x7b, 0x7f, 0xff,
+ 0xb9, 0x26, 0xe7, 0x18, 0xbd, 0x85, 0x3b, 0x94, 0x9d, 0x62, 0xff, 0xef,
+ 0xbc, 0x44, 0xc1, 0x7b, 0x3e, 0x75, 0x8b, 0xdf, 0x93, 0xac, 0x5f, 0x9f,
+ 0x38, 0xc4, 0xb1, 0x7c, 0x2d, 0x37, 0x37, 0x44, 0x4f, 0xd1, 0xbc, 0x3b,
+ 0x5d, 0x26, 0x61, 0xe8, 0x74, 0x5f, 0xfe, 0xe6, 0x68, 0xcd, 0xfe, 0xfd,
+ 0x9c, 0x86, 0xb1, 0x7f, 0xdd, 0x6e, 0xe5, 0xb6, 0x75, 0xe5, 0x8a, 0x74,
+ 0x5a, 0xf0, 0xab, 0xc9, 0xd7, 0xff, 0xe6, 0x2d, 0x87, 0xf9, 0xd6, 0xb3,
+ 0x9c, 0x11, 0x2c, 0x54, 0xae, 0x11, 0xe4, 0x3c, 0xde, 0x14, 0x8d, 0x28,
+ 0x1c, 0x22, 0xfb, 0xff, 0x38, 0xc5, 0xee, 0x49, 0x3e, 0x2c, 0x5f, 0xf1,
+ 0xe7, 0x5d, 0xb3, 0x53, 0x12, 0xc5, 0xff, 0xfb, 0x4e, 0x2d, 0xbd, 0xf9,
+ 0x7d, 0x69, 0xcb, 0x65, 0x8b, 0xf1, 0x4c, 0x3b, 0xd6, 0x58, 0xbf, 0x9f,
+ 0x45, 0x3d, 0x41, 0x62, 0xfe, 0xcd, 0x14, 0xf5, 0x05, 0x8b, 0x98, 0xb0,
+ 0xf7, 0x38, 0x5d, 0x7f, 0xf4, 0xe6, 0xa0, 0xde, 0xfb, 0x10, 0x16, 0x2f,
+ 0xff, 0xdf, 0x17, 0x5e, 0xe3, 0x75, 0xbc, 0x76, 0x73, 0x98, 0xb1, 0x7f,
+ 0xcc, 0x76, 0xf7, 0xd8, 0x80, 0xb1, 0x7f, 0xf9, 0xb4, 0x68, 0x72, 0x16,
+ 0x73, 0x8c, 0x6a, 0xc5, 0x0d, 0x51, 0x86, 0x2b, 0xef, 0x08, 0x8f, 0x95,
+ 0xf9, 0x0f, 0xb2, 0xe8, 0x47, 0x17, 0xff, 0x9c, 0x8a, 0x42, 0xf6, 0x6d,
+ 0x1a, 0xa3, 0x57, 0x78, 0xb1, 0x58, 0x8c, 0xa6, 0x6e, 0xbf, 0xf6, 0xb7,
+ 0x3c, 0xf5, 0xcc, 0xed, 0x8b, 0x17, 0x34, 0x7a, 0xc5, 0xe6, 0xd1, 0xab,
+ 0x17, 0xff, 0xf4, 0x45, 0x23, 0xce, 0xbd, 0x90, 0x92, 0xd8, 0xf8, 0xb1,
+ 0x76, 0x1d, 0x62, 0xff, 0xc5, 0x83, 0x76, 0x2d, 0x8f, 0x8b, 0x17, 0x81,
+ 0x1d, 0x83, 0x3d, 0x40, 0xc5, 0xeb, 0x49, 0x82, 0xfc, 0x78, 0xa1, 0x61,
+ 0x7d, 0xe6, 0xd7, 0x16, 0x2f, 0xc6, 0x47, 0x66, 0xa5, 0x62, 0xb6, 0x3c,
+ 0xf2, 0x23, 0xa9, 0x54, 0x11, 0xb2, 0x1e, 0x46, 0x3e, 0xd0, 0x84, 0xbf,
+ 0x0f, 0x22, 0x9f, 0xac, 0x5f, 0xff, 0xff, 0xbd, 0xf6, 0x86, 0x6a, 0x0f,
+ 0xd6, 0x76, 0xc1, 0xb8, 0x5f, 0x67, 0xf4, 0xfd, 0x62, 0x8d, 0x45, 0x71,
+ 0x14, 0xdf, 0xff, 0xf0, 0xd8, 0x80, 0x59, 0xb1, 0xdf, 0xdf, 0xcd, 0x14,
+ 0xf4, 0xb1, 0x52, 0x88, 0x91, 0x11, 0xdf, 0xf4, 0x1f, 0xdc, 0xde, 0x7d,
+ 0xc5, 0x8b, 0xf8, 0x06, 0x60, 0xda, 0x0b, 0x15, 0x11, 0xf5, 0x31, 0xdd,
+ 0xed, 0xdf, 0x4b, 0x16, 0x35, 0x62, 0xff, 0xec, 0xdf, 0xf3, 0xfc, 0xd6,
+ 0xa4, 0xd5, 0x8b, 0xf6, 0x6b, 0x52, 0x6a, 0xc5, 0xf1, 0x38, 0x39, 0x28,
+ 0x82, 0xd0, 0x9f, 0xd1, 0xaf, 0xfb, 0xec, 0x03, 0xb4, 0x1b, 0x8b, 0x17,
+ 0xf9, 0xa1, 0x09, 0x86, 0xfc, 0x58, 0xac, 0x3e, 0xe1, 0x1c, 0xdf, 0xf6,
+ 0x43, 0xed, 0x0f, 0x3e, 0xcb, 0x17, 0x82, 0x84, 0xac, 0x5f, 0xe8, 0xec,
+ 0xfc, 0xe6, 0xa0, 0xb1, 0x6c, 0x81, 0xea, 0x00, 0x7a, 0xff, 0xff, 0xe7,
+ 0xf7, 0xf0, 0x70, 0x7f, 0x61, 0xf8, 0xd0, 0x8e, 0xce, 0x73, 0x16, 0x2a,
+ 0x0a, 0xd2, 0xf2, 0x11, 0x9d, 0x11, 0x3c, 0x28, 0x3f, 0x0b, 0x30, 0x10,
+ 0x94, 0x23, 0xb8, 0x4f, 0x7f, 0xf9, 0xb6, 0xfb, 0xc9, 0x64, 0x4f, 0xa7,
+ 0x58, 0xbf, 0xff, 0x67, 0x62, 0x17, 0x35, 0x30, 0x7f, 0x39, 0x41, 0x62,
+ 0xa0, 0xdf, 0x32, 0x8e, 0x52, 0x9e, 0x4f, 0xef, 0x1b, 0x09, 0xfe, 0x8d,
+ 0x1e, 0x15, 0xd1, 0xe4, 0x31, 0x43, 0xe3, 0x45, 0xe7, 0x86, 0x97, 0xe7,
+ 0x2d, 0x19, 0x6c, 0x07, 0xa5, 0x2c, 0xdb, 0x92, 0x8a, 0x7d, 0x39, 0x94,
+ 0x14, 0x21, 0x43, 0x49, 0xbf, 0xef, 0xb7, 0x1c, 0x8a, 0x7a, 0x58, 0xbf,
+ 0xcf, 0xf9, 0xea, 0x18, 0x75, 0x8b, 0xec, 0x27, 0x1f, 0x0f, 0xb2, 0x38,
+ 0xe2, 0xf8, 0xde, 0xfd, 0xfa, 0x58, 0xbf, 0xf7, 0xb8, 0x1f, 0x9c, 0xa7,
+ 0xa8, 0x2c, 0x56, 0x8f, 0xac, 0x8a, 0xaf, 0xc5, 0x9f, 0x6f, 0x2c, 0x5f,
+ 0xfa, 0x12, 0x5b, 0x07, 0xa2, 0x14, 0x16, 0x2f, 0x73, 0x34, 0xb1, 0x7f,
+ 0x13, 0x0c, 0x1d, 0x01, 0x62, 0xb1, 0x1a, 0xb1, 0xe4, 0x31, 0x13, 0xfd,
+ 0x07, 0x83, 0xb7, 0xff, 0x31, 0x43, 0x4d, 0xd7, 0xe7, 0x38, 0xb1, 0x7f,
+ 0xf6, 0xef, 0xaf, 0xe4, 0x5f, 0x7d, 0x6c, 0xb1, 0x7d, 0x91, 0xc2, 0xd2,
+ 0xc5, 0xff, 0xe2, 0xc0, 0x98, 0x06, 0x7b, 0xf2, 0xfb, 0xac, 0x5f, 0x7b,
+ 0x6c, 0x1a, 0xc5, 0xff, 0x39, 0xa1, 0xe8, 0x07, 0x7e, 0x2c, 0x51, 0x88,
+ 0xd2, 0x34, 0x9a, 0x24, 0xc8, 0xe2, 0x4b, 0xff, 0x8b, 0x01, 0x9d, 0x9c,
+ 0xd0, 0x37, 0x96, 0x2f, 0xfc, 0xfd, 0x70, 0x0c, 0x43, 0x88, 0x4b, 0x17,
+ 0x82, 0x08, 0x25, 0x8b, 0xff, 0x8a, 0x41, 0x83, 0xe6, 0x1e, 0x77, 0x48,
+ 0x8c, 0x34, 0x34, 0x04, 0x5c, 0xf9, 0x8a, 0xff, 0x7d, 0xf0, 0x72, 0x5e,
+ 0x58, 0xa8, 0x26, 0xa8, 0x78, 0x7f, 0xf6, 0x23, 0xbf, 0xf3, 0x03, 0x7f,
+ 0xbc, 0x45, 0x20, 0x58, 0xac, 0x3f, 0x87, 0x38, 0xbf, 0xb5, 0x9d, 0xdf,
+ 0x61, 0xac, 0x5f, 0xff, 0xd9, 0x0f, 0xb4, 0x30, 0x85, 0xe7, 0xf9, 0x08,
+ 0xd5, 0x8b, 0xfe, 0xe8, 0xc2, 0xce, 0xda, 0x7e, 0x2c, 0x5f, 0xdc, 0x2c,
+ 0xd8, 0x38, 0x2c, 0x56, 0x1f, 0x69, 0xcf, 0x6f, 0xed, 0xfe, 0xf2, 0x5b,
+ 0xac, 0x54, 0x9e, 0x86, 0x10, 0xdf, 0xed, 0x4f, 0x9f, 0x77, 0x1a, 0xc5,
+ 0xfa, 0x11, 0x66, 0x6e, 0xb1, 0x7f, 0x85, 0xb4, 0xb8, 0xf0, 0xeb, 0x16,
+ 0xd2, 0xc5, 0x77, 0x88, 0xa4, 0x93, 0x42, 0x2a, 0x0c, 0xd2, 0xfc, 0x16,
+ 0x1d, 0xba, 0x58, 0xbe, 0x06, 0x34, 0x7a, 0xc5, 0x49, 0xe7, 0xb9, 0x55,
+ 0x41, 0x90, 0x23, 0x91, 0xbd, 0x1a, 0x9b, 0xd2, 0x23, 0xc6, 0x35, 0xf9,
+ 0x41, 0xec, 0x40, 0x03, 0x12, 0x8c, 0x63, 0x90, 0xc4, 0xf4, 0x24, 0x2f,
+ 0x70, 0xc3, 0x56, 0x2f, 0x6d, 0x3f, 0x58, 0xa3, 0x0d, 0xf1, 0x10, 0x5f,
+ 0xbf, 0xee, 0x0a, 0x3d, 0x62, 0xe0, 0xbb, 0xc5, 0x8a, 0x93, 0xcb, 0xe8,
+ 0xb6, 0xff, 0x89, 0x8d, 0xf7, 0x09, 0xcd, 0x58, 0xbd, 0x13, 0x12, 0xc5,
+ 0xe7, 0x3f, 0x16, 0x2d, 0xec, 0x37, 0x5e, 0x1d, 0xb9, 0x9d, 0x62, 0xfd,
+ 0xd7, 0xbb, 0x61, 0x2c, 0x5f, 0x9b, 0xd0, 0x61, 0xac, 0x58, 0xdc, 0x3d,
+ 0x32, 0x2b, 0xb7, 0xd6, 0x2e, 0xcf, 0xac, 0x54, 0x0d, 0x4f, 0x84, 0xab,
+ 0x13, 0x74, 0x77, 0x4f, 0x93, 0x33, 0x4f, 0x94, 0x2c, 0xeb, 0x17, 0xfc,
+ 0x06, 0xcd, 0x8f, 0x39, 0xe5, 0x8b, 0xff, 0xfa, 0x4a, 0x4d, 0x29, 0x34,
+ 0x38, 0xe9, 0xd4, 0xef, 0x2b, 0x15, 0xa4, 0x4c, 0x04, 0x73, 0x7f, 0xd3,
+ 0xb3, 0x9f, 0xd9, 0x87, 0x58, 0xbf, 0xfe, 0x93, 0x94, 0xf4, 0x01, 0xe1,
+ 0xf6, 0xc0, 0x96, 0x2f, 0xef, 0xc9, 0x9b, 0xbe, 0xcb, 0x17, 0xfe, 0x63,
+ 0xe6, 0x8d, 0x34, 0x45, 0xe5, 0x8b, 0xfd, 0x3e, 0xe7, 0x1c, 0xa2, 0x58,
+ 0xaf, 0x9f, 0xa9, 0x20, 0xdf, 0x13, 0x75, 0x05, 0x8b, 0xfe, 0x62, 0x87,
+ 0xc5, 0x3d, 0x71, 0x62, 0xa2, 0x3d, 0xd0, 0x88, 0xef, 0xff, 0xe6, 0x3e,
+ 0xb3, 0xb4, 0x97, 0xb3, 0xef, 0xaf, 0xb2, 0xc5, 0xff, 0x37, 0xb9, 0xef,
+ 0x34, 0x38, 0xb1, 0x51, 0x26, 0x6f, 0xa7, 0xef, 0x92, 0x12, 0xdd, 0xff,
+ 0xcd, 0xa6, 0x86, 0x71, 0xbd, 0x91, 0x2c, 0x5f, 0xf7, 0xb5, 0x39, 0xd1,
+ 0x8d, 0xc5, 0x8b, 0xfb, 0xed, 0xbc, 0x90, 0xd6, 0x2f, 0xcd, 0xa2, 0x98,
+ 0x2c, 0x5f, 0xb0, 0x7f, 0x78, 0x96, 0x28, 0xd3, 0xfe, 0xd1, 0x71, 0x13,
+ 0xdf, 0xec, 0x1c, 0xc2, 0x61, 0xe5, 0x8b, 0xff, 0xfe, 0x01, 0xda, 0x19,
+ 0xb8, 0xc4, 0x6f, 0x5c, 0x60, 0x67, 0x5e, 0x58, 0xbf, 0xf6, 0x44, 0x16,
+ 0x75, 0xef, 0x49, 0xd6, 0x2a, 0x51, 0x5d, 0xf6, 0xcb, 0xf8, 0xb6, 0x7d,
+ 0x76, 0x82, 0xc5, 0xff, 0xf7, 0xc5, 0x3a, 0xce, 0xcf, 0xcc, 0xe8, 0x72,
+ 0xb1, 0x7f, 0xff, 0xbd, 0xe9, 0x81, 0x37, 0xe4, 0xff, 0xc1, 0xb7, 0x44,
+ 0xb1, 0x7e, 0xce, 0xb1, 0xa3, 0xd6, 0x2f, 0xff, 0x7b, 0xf9, 0xdb, 0xee,
+ 0x67, 0x38, 0xe7, 0x58, 0xa9, 0x4d, 0x70, 0x66, 0x38, 0xa5, 0xf6, 0x06,
+ 0x2b, 0xbf, 0xe8, 0x3e, 0xba, 0x92, 0x9e, 0x2c, 0x5e, 0x09, 0xb6, 0x58,
+ 0xbf, 0xe9, 0xcd, 0xb5, 0x3e, 0x6f, 0x2c, 0x53, 0xa2, 0x47, 0xe7, 0x22,
+ 0x1f, 0xae, 0xfb, 0x64, 0x03, 0x4c, 0x2a, 0x76, 0x24, 0x81, 0xc8, 0xd4,
+ 0xb2, 0x3d, 0xdd, 0xcf, 0xba, 0x44, 0xd4, 0x2e, 0x4e, 0x5f, 0xf8, 0x70,
+ 0x94, 0x6f, 0xde, 0x86, 0xcd, 0xfd, 0x09, 0x8b, 0x1c, 0x0b, 0x16, 0x8c,
+ 0xef, 0x21, 0x05, 0x25, 0x1a, 0x0b, 0xc6, 0xcd, 0xdd, 0xf5, 0x2d, 0x99,
+ 0xcc, 0xbd, 0xa5, 0x3c, 0x42, 0x51, 0x28, 0xe7, 0x0b, 0x32, 0xb0, 0x5d,
+ 0x36, 0x30, 0x7d, 0xe9, 0x03, 0x5d, 0x4e, 0x2d, 0xbc, 0x62, 0xf1, 0xe6,
+ 0x51, 0x4b, 0x44, 0xd4, 0xbc, 0x73, 0xca, 0x87, 0xfc, 0xfb, 0xab, 0x4b,
+ 0xf6, 0x04, 0xb0, 0x12, 0x9f, 0xca, 0xe5, 0x7e, 0x9b, 0xea, 0x4d, 0xf8,
+ 0xa1, 0xf6, 0x13, 0x64, 0x74, 0x72, 0xc1, 0xd2, 0x13, 0xbb, 0xa1, 0xbb,
+ 0x7f, 0xdf, 0x73, 0x0b, 0x3c, 0xdd, 0x96, 0x2f, 0xc1, 0xfd, 0xbf, 0x2b,
+ 0x17, 0xe8, 0x75, 0x24, 0x35, 0x8a, 0x82, 0xad, 0x93, 0x65, 0x26, 0x1c,
+ 0xec, 0x8a, 0x6f, 0xff, 0x6b, 0x02, 0x1f, 0xf2, 0x22, 0xcd, 0x41, 0x62,
+ 0xf6, 0xb2, 0x3d, 0x62, 0xfe, 0xf0, 0xa1, 0x14, 0xf7, 0x2c, 0x5f, 0xfa,
+ 0x42, 0x0f, 0x6e, 0x61, 0xe6, 0x3d, 0x62, 0xb4, 0x8e, 0x43, 0xa6, 0x7c,
+ 0x83, 0xc6, 0x77, 0xff, 0xcc, 0x79, 0xd6, 0xfa, 0x11, 0xba, 0x13, 0x71,
+ 0x62, 0xb1, 0x12, 0x02, 0x3d, 0xbf, 0xda, 0xdc, 0x4c, 0x33, 0xca, 0xc5,
+ 0xff, 0xd3, 0xa0, 0xfc, 0xfe, 0xfe, 0x0d, 0xd6, 0x2f, 0xf1, 0x74, 0x0c,
+ 0xe3, 0x47, 0xac, 0x5f, 0xf1, 0x4e, 0xc1, 0xff, 0xed, 0x1e, 0xb1, 0x7d,
+ 0x38, 0x3e, 0x96, 0x2b, 0x11, 0x31, 0xf3, 0x7e, 0xc7, 0xd7, 0xff, 0xdf,
+ 0x8c, 0x9f, 0x48, 0xcb, 0x21, 0xf9, 0x82, 0xc5, 0xe0, 0x98, 0x25, 0x8b,
+ 0xf9, 0x9b, 0xd1, 0xcf, 0xba, 0xc5, 0xdd, 0xbb, 0x96, 0x2f, 0xfe, 0x92,
+ 0xd8, 0xb3, 0xdc, 0xce, 0xa0, 0xb1, 0x7f, 0xff, 0x89, 0xc1, 0xcd, 0x66,
+ 0xff, 0x9f, 0xe6, 0xb5, 0x26, 0xac, 0x5f, 0xfb, 0x36, 0xd9, 0xfd, 0xa1,
+ 0x48, 0x16, 0x29, 0xd1, 0x47, 0xe6, 0x2b, 0xfb, 0xf2, 0x37, 0x2c, 0x58,
+ 0xa9, 0x56, 0x71, 0xb1, 0xae, 0x43, 0x77, 0xa3, 0x18, 0xf5, 0x2d, 0x0f,
+ 0x80, 0xc7, 0x83, 0xbe, 0x87, 0x40, 0x88, 0xaf, 0x77, 0xce, 0xf2, 0x0b,
+ 0x17, 0x89, 0xb8, 0xb1, 0x7f, 0xe9, 0xf6, 0x6a, 0x0f, 0xd6, 0x76, 0x58,
+ 0xbf, 0xff, 0x13, 0x8b, 0xbf, 0xfe, 0x66, 0xa0, 0xfd, 0x67, 0x65, 0x8a,
+ 0xfa, 0x2e, 0x63, 0x87, 0x03, 0x41, 0xbf, 0x3f, 0x62, 0xce, 0x2c, 0x46,
+ 0x1b, 0x4b, 0xd2, 0x5e, 0x58, 0xa8, 0x1e, 0xc0, 0xcf, 0x2f, 0x36, 0xb6,
+ 0x58, 0xbf, 0xdb, 0xbc, 0x80, 0xf3, 0x05, 0x8b, 0xfd, 0x9e, 0xe3, 0xef,
+ 0x84, 0xb1, 0x70, 0x41, 0x2c, 0x5f, 0xf8, 0x5b, 0x37, 0xbd, 0xd6, 0xee,
+ 0x4b, 0x17, 0x9b, 0x78, 0xcc, 0x4c, 0x0f, 0x72, 0x2f, 0x8f, 0x11, 0xa0,
+ 0x46, 0x61, 0x8d, 0x5f, 0xb4, 0xd0, 0x7f, 0xac, 0x5f, 0xfd, 0xae, 0x7d,
+ 0xc2, 0xfb, 0xec, 0xc4, 0xb1, 0x52, 0x7d, 0xcc, 0x51, 0x7e, 0xf7, 0x5b,
+ 0xbf, 0xd7, 0x38, 0x91, 0x7e, 0x88, 0x9b, 0xa8, 0x2c, 0x5f, 0xfe, 0xe8,
+ 0x07, 0x17, 0x5f, 0xce, 0xd9, 0xee, 0x2c, 0x56, 0x8f, 0xe8, 0x8a, 0xaf,
+ 0xd1, 0x42, 0x75, 0xb2, 0xc5, 0xff, 0x8e, 0x20, 0xf3, 0x5b, 0x09, 0x86,
+ 0xb1, 0x7e, 0xee, 0xcd, 0x67, 0x72, 0xc5, 0x62, 0x2f, 0x34, 0x42, 0x72,
+ 0xbf, 0xa1, 0x5f, 0x1f, 0xec, 0x35, 0x8b, 0xd8, 0xe0, 0x58, 0xac, 0x37,
+ 0xfe, 0x23, 0xb4, 0x64, 0x6f, 0x0a, 0xdd, 0x7e, 0xf0, 0xd7, 0xbe, 0xa3,
+ 0x53, 0x0c, 0x88, 0x42, 0xcc, 0x6f, 0xb9, 0x3c, 0x24, 0x69, 0xe6, 0xf5,
+ 0x86, 0x37, 0x50, 0xf2, 0x8f, 0x26, 0x89, 0xff, 0x50, 0xbe, 0xfc, 0x6c,
+ 0xad, 0x88, 0x59, 0xe2, 0x8e, 0xeb, 0x92, 0xd6, 0xbd, 0x09, 0xae, 0xd2,
+ 0x9c, 0x42, 0x86, 0xe4, 0x71, 0x00, 0x71, 0xb7, 0x77, 0x3d, 0xd4, 0x23,
+ 0x0c, 0x59, 0x1d, 0x73, 0xfd, 0xd4, 0xb1, 0xad, 0x35, 0x9e, 0x12, 0xff,
+ 0xa5, 0x76, 0x02, 0x35, 0xf2, 0x9c, 0xc7, 0xe5, 0x66, 0x9d, 0xea, 0xe0,
+ 0x60, 0x58, 0xb0, 0x06, 0xb8, 0x50, 0x58, 0xa5, 0x8b, 0xe1, 0xfe, 0x42,
+ 0x58, 0xa9, 0x36, 0x18, 0x19, 0x7f, 0x72, 0x62, 0x83, 0xc4, 0xb1, 0x68,
+ 0x96, 0x2f, 0xcc, 0x06, 0xcd, 0xd6, 0x2f, 0x4b, 0x79, 0x62, 0xa4, 0xf5,
+ 0xc8, 0x4f, 0x85, 0x17, 0xfd, 0xe9, 0x27, 0x06, 0x75, 0xe5, 0x8b, 0xe8,
+ 0xe6, 0x20, 0x2c, 0x5b, 0x6c, 0x3d, 0xe0, 0xce, 0x6f, 0xe6, 0x20, 0x7a,
+ 0x62, 0x58, 0xa9, 0x3d, 0x78, 0xe2, 0x9a, 0x02, 0x7e, 0x84, 0x91, 0xc1,
+ 0xff, 0x42, 0x1c, 0x38, 0x71, 0x5d, 0x9d, 0x2c, 0x5f, 0xee, 0xd3, 0xa8,
+ 0x7d, 0xa0, 0xb1, 0x78, 0xee, 0x05, 0x8b, 0xdf, 0x70, 0x96, 0x2f, 0x9b,
+ 0x5b, 0xc6, 0x41, 0x11, 0x38, 0x31, 0xc3, 0x6f, 0x0e, 0xdf, 0xfe, 0x83,
+ 0x72, 0x30, 0xa7, 0x3d, 0x3d, 0x41, 0x62, 0xf1, 0xaf, 0xa5, 0x8b, 0xa4,
+ 0x0b, 0x17, 0xfc, 0x00, 0x48, 0xc4, 0xda, 0x82, 0xc5, 0xf7, 0xbd, 0x27,
+ 0x58, 0xbc, 0xe3, 0x8c, 0x74, 0x49, 0x7c, 0x7b, 0x82, 0xe1, 0x9d, 0x5f,
+ 0xfa, 0x61, 0x18, 0x1c, 0x84, 0x1c, 0x5c, 0x58, 0xb3, 0xee, 0x89, 0x80,
+ 0x28, 0xd4, 0x62, 0xad, 0x5d, 0xa1, 0xbc, 0xea, 0xfe, 0x8d, 0xde, 0xff,
+ 0xcd, 0xbc, 0x60, 0x80, 0xf0, 0xc8, 0x2c, 0x5f, 0xff, 0x67, 0x9f, 0xe2,
+ 0xfb, 0x3f, 0x5c, 0x93, 0x56, 0x2f, 0xda, 0xdd, 0x9b, 0x75, 0x48, 0x6a,
+ 0x5f, 0xff, 0x7d, 0xc2, 0x62, 0xdf, 0x52, 0xf0, 0x6e, 0x2c, 0x5f, 0x85,
+ 0xe1, 0x45, 0x2b, 0x17, 0xe1, 0x1b, 0xf6, 0x82, 0xc5, 0xe6, 0xcf, 0x2c,
+ 0x59, 0xe0, 0x78, 0xc3, 0x2a, 0xbe, 0xfb, 0xf6, 0x75, 0x8b, 0xba, 0xe2,
+ 0xc5, 0x61, 0xbd, 0x34, 0x92, 0xd1, 0x9b, 0x2a, 0x10, 0x1a, 0x1e, 0x28,
+ 0xee, 0x6f, 0xf5, 0x06, 0x70, 0xf3, 0x25, 0xff, 0xfe, 0xed, 0x25, 0xe8,
+ 0xc6, 0xec, 0xc3, 0xc1, 0xb1, 0xd8, 0x6b, 0x17, 0xed, 0x6e, 0xcd, 0xba,
+ 0xa4, 0xa5, 0x2f, 0x60, 0x19, 0x62, 0xdb, 0xae, 0x41, 0xa2, 0x96, 0x29,
+ 0x8d, 0x60, 0x08, 0x2e, 0x63, 0xac, 0x5a, 0x33, 0x11, 0x6d, 0xf3, 0x76,
+ 0x48, 0x22, 0x0b, 0xef, 0x37, 0x40, 0x58, 0xbf, 0xfd, 0x9f, 0x70, 0xfc,
+ 0xe4, 0x28, 0x67, 0x16, 0x2f, 0xf6, 0x7c, 0x9b, 0xde, 0x95, 0x8b, 0xc4,
+ 0xd1, 0x8c, 0x8a, 0x0f, 0x12, 0x06, 0x95, 0x7a, 0x37, 0xef, 0xb8, 0xd9,
+ 0x62, 0xfc, 0xc7, 0xd9, 0xa3, 0xd6, 0x2f, 0xb7, 0x66, 0xdd, 0x52, 0x1f,
+ 0x17, 0xed, 0xc8, 0x4c, 0x1a, 0xc5, 0xa5, 0x62, 0xa4, 0xdd, 0x8c, 0xaa,
+ 0xfe, 0x73, 0x40, 0x79, 0x82, 0xc5, 0x69, 0x17, 0x67, 0x6c, 0x22, 0x0b,
+ 0x88, 0xd5, 0x8b, 0xf7, 0xc2, 0x6d, 0x41, 0x62, 0xdc, 0xc3, 0xc2, 0x71,
+ 0x8b, 0xfc, 0xfa, 0x31, 0xc7, 0x87, 0x58, 0xb9, 0xb4, 0xb1, 0x5f, 0x3c,
+ 0xb6, 0x34, 0xbe, 0xcf, 0x3f, 0x78, 0xb1, 0x77, 0xc4, 0xb1, 0x7f, 0xc3,
+ 0x17, 0xb9, 0x90, 0x7f, 0xac, 0x50, 0xcf, 0x49, 0xc6, 0x2e, 0xeb, 0x8b,
+ 0x16, 0x35, 0x62, 0xb0, 0xd6, 0x47, 0x0c, 0xdf, 0xf6, 0x76, 0x2c, 0xe0,
+ 0x7a, 0x35, 0x62, 0xfe, 0x66, 0xdb, 0xd9, 0xba, 0xc5, 0xff, 0xb4, 0x0d,
+ 0xfe, 0xf1, 0x14, 0x81, 0x62, 0xa2, 0x3f, 0x01, 0x17, 0xdf, 0xe8, 0x64,
+ 0x7b, 0x10, 0x23, 0x65, 0x8b, 0xfc, 0x42, 0xdc, 0xf3, 0xad, 0xd6, 0x2f,
+ 0x7a, 0x71, 0x62, 0xff, 0xef, 0x42, 0x4d, 0x32, 0x7d, 0xc9, 0x02, 0xc5,
+ 0x8b, 0x0f, 0x8d, 0x87, 0x2e, 0x84, 0x64, 0x6e, 0xb9, 0x97, 0xb1, 0x7e,
+ 0x43, 0x9f, 0xa7, 0x18, 0x9c, 0x4e, 0x42, 0xcf, 0x20, 0x4d, 0x22, 0x3e,
+ 0x42, 0xb7, 0xc4, 0x62, 0x3b, 0x0e, 0x13, 0x35, 0xba, 0xef, 0x3b, 0x4e,
+ 0x87, 0x5f, 0xd1, 0x9c, 0x69, 0xea, 0x0b, 0x17, 0xf6, 0xd3, 0xad, 0x34,
+ 0x16, 0x2f, 0xbf, 0x24, 0x6a, 0xc5, 0x11, 0xe9, 0x78, 0xbe, 0xfe, 0xd3,
+ 0x01, 0xb3, 0x4b, 0x17, 0x9b, 0xd1, 0xcb, 0x17, 0xda, 0x16, 0x6c, 0xb1,
+ 0x7f, 0x1f, 0x39, 0x8c, 0x4b, 0x17, 0x16, 0xcb, 0x15, 0x27, 0x88, 0x22,
+ 0xcb, 0xcc, 0x51, 0x2c, 0x56, 0x22, 0x9b, 0xed, 0x0c, 0x43, 0x7f, 0x66,
+ 0xbc, 0x53, 0xd2, 0xc5, 0xfd, 0xf9, 0x7e, 0xd8, 0x35, 0x8b, 0xff, 0x36,
+ 0xd3, 0xf7, 0xd3, 0xc9, 0xd6, 0x2f, 0xf4, 0xeb, 0x0b, 0xd9, 0xf5, 0x8b,
+ 0xb2, 0x32, 0x55, 0x07, 0x8c, 0x84, 0xe5, 0xbf, 0x86, 0x30, 0x0b, 0xbc,
+ 0x5d, 0x1c, 0x5e, 0x19, 0xf5, 0x1a, 0xac, 0x70, 0xf2, 0xa4, 0xef, 0xa3,
+ 0x38, 0x31, 0xac, 0x54, 0x62, 0xb9, 0xe9, 0x96, 0x94, 0x72, 0xdb, 0xff,
+ 0xfc, 0x2d, 0x1a, 0xdc, 0xc1, 0xcf, 0x5c, 0x0f, 0xc6, 0xb9, 0xab, 0x17,
+ 0xb8, 0xdc, 0x58, 0xbe, 0xcd, 0x13, 0x2c, 0x54, 0x9b, 0xe7, 0x1d, 0xa8,
+ 0x23, 0x12, 0x28, 0x52, 0xdd, 0xed, 0x96, 0x2f, 0x04, 0x6e, 0xeb, 0x17,
+ 0xee, 0xba, 0x86, 0x79, 0x62, 0x88, 0xf9, 0x78, 0x32, 0x22, 0x1b, 0xff,
+ 0xd1, 0xa8, 0xd0, 0xa3, 0xf6, 0x1c, 0x6c, 0x61, 0x9f, 0x8e, 0x58, 0xbf,
+ 0xf0, 0x9b, 0x50, 0x2c, 0xe4, 0xe9, 0x62, 0xec, 0x1a, 0xc5, 0xf6, 0xec,
+ 0xdb, 0xaa, 0x4c, 0x72, 0xfd, 0x3f, 0x26, 0x0d, 0x62, 0xe1, 0x69, 0x62,
+ 0x86, 0x88, 0x8d, 0x0b, 0x9c, 0xc5, 0x8a, 0x2f, 0xf6, 0x39, 0x6d, 0xec,
+ 0xfa, 0xc5, 0xcf, 0x1c, 0xb1, 0x7d, 0x9b, 0x1f, 0xcb, 0x15, 0xf3, 0x7c,
+ 0x43, 0x57, 0x37, 0x16, 0x2f, 0xed, 0x83, 0xd6, 0xb3, 0x4b, 0x17, 0x8f,
+ 0xc9, 0x58, 0xa8, 0x1f, 0x2b, 0x0b, 0x88, 0xc6, 0xff, 0x89, 0x8d, 0xfb,
+ 0xc9, 0x6c, 0xb1, 0x7f, 0xff, 0xb0, 0xbd, 0xc3, 0x38, 0x1c, 0xe8, 0x11,
+ 0xcf, 0xfc, 0xec, 0xb1, 0x7f, 0x17, 0xb4, 0x29, 0x3a, 0xc5, 0xfd, 0xf6,
+ 0x21, 0x87, 0xd2, 0xc5, 0xff, 0xf3, 0x1a, 0x67, 0x8d, 0x92, 0x86, 0x7d,
+ 0xce, 0xb1, 0x4e, 0x88, 0x22, 0x30, 0xa9, 0x4c, 0xe5, 0x9a, 0x05, 0x0b,
+ 0x0b, 0xf8, 0x0d, 0xee, 0x49, 0xab, 0x17, 0xc6, 0x86, 0x5b, 0xac, 0x5b,
+ 0x16, 0x28, 0xd3, 0x6f, 0xd8, 0x9a, 0xff, 0x3f, 0xa7, 0x46, 0xfd, 0xd6,
+ 0x2f, 0xff, 0xa1, 0xb4, 0x6a, 0x98, 0xd3, 0x6d, 0xf4, 0x61, 0x9f, 0x8e,
+ 0x58, 0xbf, 0xec, 0xed, 0x30, 0xea, 0x19, 0xe5, 0x8a, 0xc4, 0xd8, 0x1d,
+ 0x99, 0x89, 0x00, 0x68, 0x4c, 0xd7, 0xdd, 0x83, 0x8b, 0x8b, 0x17, 0x0b,
+ 0x75, 0x8a, 0xc3, 0xc1, 0xe1, 0x45, 0xcf, 0x05, 0x8b, 0xfd, 0x85, 0xfc,
+ 0xf4, 0x8d, 0x62, 0xfd, 0x9d, 0xbe, 0xd0, 0x58, 0xb7, 0x9c, 0xf7, 0x08,
+ 0xca, 0xfe, 0x1f, 0xdf, 0x70, 0xc4, 0xb1, 0x43, 0x46, 0x56, 0x39, 0xb9,
+ 0x35, 0xff, 0x41, 0xfc, 0x1e, 0xa7, 0xf2, 0xb1, 0x7f, 0xfe, 0x7e, 0x07,
+ 0xd0, 0x33, 0xb3, 0xfa, 0x70, 0xa0, 0xb1, 0x7e, 0x7f, 0x79, 0xfc, 0xb1,
+ 0x7f, 0xfe, 0x11, 0x31, 0xbe, 0x36, 0x4a, 0x19, 0xf7, 0x3a, 0xc5, 0xf6,
+ 0xb5, 0x91, 0xcb, 0x17, 0x6f, 0xba, 0xc5, 0xfb, 0x40, 0x7f, 0xca, 0xc5,
+ 0x18, 0x9b, 0xc4, 0x0e, 0xb1, 0x60, 0xe5, 0x0c, 0xad, 0xc2, 0x61, 0x0d,
+ 0x5f, 0x8e, 0xf3, 0xa8, 0x2c, 0x5f, 0xb3, 0xd0, 0xce, 0x2c, 0x53, 0x9e,
+ 0x87, 0x0a, 0x2f, 0xe1, 0xe1, 0xdf, 0xf2, 0xb1, 0x7d, 0xac, 0xc8, 0x96,
+ 0x2a, 0x4f, 0x43, 0x0b, 0x6d, 0x19, 0x2c, 0xaa, 0xad, 0xa1, 0x1d, 0x02,
+ 0xe1, 0xb2, 0x64, 0x31, 0x8d, 0x3c, 0xdd, 0xc5, 0xe1, 0x0b, 0x11, 0x71,
+ 0xe3, 0x72, 0xfc, 0x72, 0x8d, 0x08, 0x82, 0x87, 0x5f, 0x23, 0xa6, 0xf4,
+ 0x2d, 0x03, 0x71, 0xbf, 0xf4, 0x69, 0xf9, 0x71, 0x94, 0x8b, 0x75, 0x8b,
+ 0xbd, 0x8b, 0x16, 0x8d, 0xd6, 0x2b, 0xbe, 0x1f, 0x97, 0x48, 0x8e, 0x2f,
+ 0x79, 0xf5, 0x12, 0xc5, 0xf4, 0x3c, 0x21, 0xac, 0x51, 0xa7, 0x85, 0xd0,
+ 0xf5, 0xfe, 0xce, 0xcf, 0xd6, 0x66, 0xcb, 0x17, 0xff, 0xfb, 0x02, 0x13,
+ 0x17, 0x6e, 0x06, 0xdb, 0x45, 0x07, 0x17, 0x7e, 0xb1, 0x51, 0xb2, 0x28,
+ 0xbe, 0x6d, 0x7f, 0xff, 0xfe, 0xfe, 0x33, 0xf3, 0xf8, 0x03, 0x39, 0x83,
+ 0xc3, 0xbf, 0x50, 0x29, 0x34, 0x0b, 0x17, 0xf1, 0x30, 0x5e, 0xcf, 0xac,
+ 0x57, 0x78, 0x8b, 0x28, 0xa1, 0x09, 0x71, 0xcd, 0x58, 0xae, 0xf4, 0xf1,
+ 0xe3, 0x51, 0x75, 0xf8, 0xb3, 0xed, 0xe5, 0x8b, 0xd1, 0xaf, 0xbc, 0x02,
+ 0xc5, 0x77, 0xa7, 0xa1, 0x1a, 0x89, 0xef, 0xfa, 0x37, 0xef, 0x45, 0x9a,
+ 0x29, 0x02, 0xc5, 0x86, 0xb1, 0x5d, 0xe1, 0xea, 0xf7, 0xc4, 0x3b, 0xfd,
+ 0xde, 0x7f, 0x01, 0x3a, 0xe2, 0xc5, 0xff, 0xbb, 0xde, 0xfb, 0x00, 0x24,
+ 0x7f, 0x17, 0x72, 0xc5, 0xfd, 0x9b, 0xcf, 0x9f, 0xb2, 0xc5, 0xff, 0xb0,
+ 0x2e, 0x63, 0xf3, 0xd9, 0x1e, 0xb1, 0x5f, 0x3f, 0x22, 0x30, 0xbd, 0xf1,
+ 0x0d, 0x62, 0xe7, 0xdd, 0x62, 0xff, 0xcd, 0xd0, 0x1b, 0xc0, 0x0c, 0xa0,
+ 0xb1, 0x7f, 0xdc, 0x29, 0x98, 0xfd, 0x49, 0xd6, 0x2e, 0xef, 0xb8, 0xdd,
+ 0x62, 0xff, 0xc7, 0xe1, 0x4c, 0xf4, 0x77, 0x02, 0xc5, 0xff, 0x14, 0xfd,
+ 0x9f, 0x8f, 0xd9, 0x62, 0xc7, 0x31, 0x1a, 0xf1, 0xb9, 0xdc, 0x92, 0x06,
+ 0x7f, 0x7c, 0xfc, 0xe4, 0xac, 0x56, 0x1f, 0x5f, 0xd2, 0x6f, 0xec, 0x84,
+ 0x34, 0x2e, 0xf5, 0x62, 0xb6, 0x4f, 0x60, 0x71, 0xc1, 0x91, 0x0d, 0xff,
+ 0x4c, 0x4f, 0xee, 0x39, 0x44, 0xb1, 0x7f, 0x8a, 0x67, 0xa3, 0xb8, 0x16,
+ 0x2f, 0xcc, 0x33, 0xc9, 0xab, 0x15, 0xc3, 0xdc, 0x11, 0x9d, 0xff, 0xd2,
+ 0x0f, 0xc7, 0xb9, 0xfd, 0xc6, 0xe9, 0x62, 0xff, 0xa7, 0x4c, 0x72, 0xce,
+ 0xbc, 0xb1, 0x5b, 0xa2, 0x08, 0xe9, 0x37, 0x66, 0xcb, 0x17, 0x0e, 0x56,
+ 0x28, 0x33, 0x5f, 0xdc, 0x31, 0x4e, 0x7f, 0x02, 0x53, 0xbf, 0xf9, 0x88,
+ 0x59, 0xf7, 0x6d, 0x8a, 0x56, 0x2f, 0xfd, 0xf7, 0x30, 0x3d, 0xcb, 0x3f,
+ 0x8b, 0x17, 0xf0, 0x38, 0xde, 0xf3, 0x2c, 0x51, 0xa7, 0xde, 0xc8, 0x37,
+ 0xfb, 0x93, 0x11, 0xe7, 0xdc, 0x58, 0xb8, 0xfb, 0xac, 0x5f, 0xf3, 0x0d,
+ 0xfa, 0x87, 0x9f, 0x4b, 0x17, 0xfd, 0xa0, 0x16, 0x45, 0x07, 0x89, 0x62,
+ 0xff, 0x1f, 0x8f, 0x1d, 0x9a, 0x95, 0x8b, 0xff, 0x6c, 0xfb, 0xfd, 0xc6,
+ 0x3c, 0x09, 0x62, 0xa5, 0x16, 0x78, 0x76, 0xe6, 0xd4, 0x35, 0xe7, 0x4c,
+ 0x21, 0xdc, 0x79, 0xe3, 0xf0, 0xd1, 0xb9, 0xe1, 0x2d, 0xf8, 0xc7, 0x00,
+ 0x42, 0x50, 0xb1, 0xe1, 0x17, 0x8d, 0x7b, 0x0c, 0xf7, 0x43, 0xb6, 0xfd,
+ 0xf7, 0x92, 0xf2, 0xc5, 0xfd, 0x84, 0xdd, 0x43, 0x8b, 0x17, 0xb6, 0xd4,
+ 0xac, 0x5f, 0x47, 0xf1, 0xbb, 0x2c, 0x5f, 0xfb, 0x08, 0x11, 0xd9, 0x1c,
+ 0xe5, 0xe5, 0x8a, 0xc3, 0xeb, 0xe1, 0x45, 0x82, 0xd2, 0x36, 0x18, 0xbb,
+ 0x90, 0x89, 0xb8, 0x8d, 0x58, 0xbf, 0x7d, 0xe4, 0xb6, 0x58, 0xbf, 0xa1,
+ 0x27, 0x62, 0x95, 0x8a, 0xe8, 0xf5, 0x34, 0x51, 0x60, 0x96, 0x2c, 0x35,
+ 0x8a, 0xd8, 0xd2, 0xe0, 0x9d, 0x0d, 0x50, 0x7e, 0x43, 0xfd, 0x8e, 0xc4,
+ 0xd9, 0xd9, 0x22, 0xfd, 0xf6, 0x3c, 0x92, 0xc5, 0xf7, 0x3e, 0xe1, 0x2c,
+ 0x5f, 0xfd, 0x14, 0x7b, 0xed, 0xfc, 0x88, 0xb0, 0x25, 0x8b, 0xf3, 0x6a,
+ 0x39, 0xbe, 0xb1, 0x7e, 0xe4, 0xf9, 0xfb, 0x2c, 0x56, 0xe7, 0xab, 0xe2,
+ 0xbb, 0xbf, 0xf5, 0x8b, 0xf4, 0x85, 0xec, 0xfa, 0xc5, 0xc1, 0xe2, 0xc5,
+ 0xf0, 0xf3, 0xaf, 0x2c, 0x54, 0x9b, 0xc7, 0x18, 0xa3, 0x13, 0xaa, 0xc2,
+ 0x73, 0x49, 0x1e, 0x14, 0x1d, 0xf9, 0x19, 0x0c, 0x71, 0x96, 0xff, 0xa3,
+ 0x4d, 0x6d, 0xe2, 0x98, 0xd3, 0xa5, 0x8b, 0xf8, 0xa4, 0x10, 0xdf, 0x65,
+ 0x8b, 0xff, 0xa6, 0x7b, 0xbf, 0x8c, 0x3c, 0xc3, 0xac, 0x5d, 0xee, 0x44,
+ 0x7e, 0xbf, 0x30, 0xb6, 0xeb, 0x17, 0x81, 0x1b, 0xfd, 0x62, 0xbb, 0xec,
+ 0xdb, 0x70, 0x4e, 0xfe, 0xd6, 0xdb, 0xfd, 0xa3, 0xd6, 0x2f, 0x85, 0xcf,
+ 0xe2, 0xc5, 0xff, 0xe7, 0xf8, 0x87, 0xf9, 0xdf, 0xe2, 0x60, 0xd6, 0x2b,
+ 0x48, 0xcc, 0x62, 0x82, 0x34, 0xf1, 0x1d, 0xff, 0xec, 0xee, 0xcd, 0xfd,
+ 0xd4, 0x30, 0x80, 0xcb, 0x17, 0xff, 0xff, 0x39, 0x76, 0xc1, 0x93, 0x37,
+ 0x6c, 0x8f, 0xf4, 0x7b, 0xf8, 0xa4, 0x0b, 0x17, 0x9c, 0x40, 0x58, 0xbf,
+ 0xfd, 0x9d, 0x9b, 0x35, 0x3e, 0x7d, 0xdc, 0x6b, 0x16, 0xea, 0x3d, 0x1c,
+ 0x11, 0x3c, 0x10, 0xed, 0xe3, 0xbe, 0x96, 0x2b, 0x0f, 0x5c, 0x07, 0x57,
+ 0xb1, 0x89, 0x62, 0xf7, 0xe6, 0x25, 0x8b, 0x9f, 0xce, 0x6e, 0x58, 0x6e,
+ 0xe8, 0x0d, 0x62, 0xff, 0x6c, 0x21, 0xff, 0x3b, 0x71, 0x62, 0xff, 0xec,
+ 0x0b, 0x85, 0x91, 0x40, 0x45, 0xe5, 0x8b, 0xe8, 0x47, 0xb9, 0xd6, 0x2f,
+ 0xb8, 0xcd, 0x1e, 0xb1, 0x7d, 0xff, 0xcc, 0x7a, 0xc5, 0xfb, 0x3f, 0x1e,
+ 0xe4, 0xc7, 0xe3, 0xe2, 0x60, 0xc9, 0x6b, 0x64, 0xcf, 0x08, 0xe3, 0xb4,
+ 0x2d, 0xef, 0xff, 0xdb, 0xe7, 0x67, 0xd4, 0x73, 0x6d, 0x1d, 0xac, 0xff,
+ 0x16, 0x2b, 0x11, 0x30, 0xc7, 0x17, 0xe8, 0x8e, 0xfa, 0xe2, 0xc5, 0xff,
+ 0x7d, 0xfd, 0xd4, 0x1f, 0xdc, 0x58, 0xbf, 0xff, 0xfb, 0xb8, 0xb1, 0xbb,
+ 0x16, 0x76, 0xfe, 0x16, 0x3e, 0x9b, 0xa8, 0x71, 0x63, 0x73, 0x77, 0x7f,
+ 0xb3, 0x66, 0x7d, 0xf0, 0x96, 0x2b, 0x11, 0x75, 0xda, 0x10, 0xf7, 0xe6,
+ 0x7d, 0xf0, 0x96, 0x2f, 0x9f, 0x7c, 0x25, 0x8b, 0x70, 0xc3, 0xc9, 0x62,
+ 0x7b, 0xff, 0xfe, 0xeb, 0xf3, 0xda, 0x2c, 0x6e, 0xb9, 0x8e, 0x5b, 0x66,
+ 0x77, 0x2c, 0x54, 0xa2, 0x55, 0x8a, 0x2f, 0xff, 0x7e, 0x7a, 0xcd, 0x88,
+ 0x42, 0xf4, 0xfd, 0x62, 0xff, 0x9f, 0x7f, 0xbf, 0xb8, 0xdd, 0x2c, 0x5f,
+ 0x60, 0xf3, 0xfb, 0xa2, 0x1f, 0xe9, 0x95, 0x89, 0xf4, 0xea, 0x30, 0x72,
+ 0x85, 0x45, 0xfe, 0xdd, 0xc2, 0xc8, 0x9a, 0x3d, 0x62, 0xb4, 0x7e, 0x7f,
+ 0x3a, 0xbf, 0xff, 0xf1, 0x61, 0xc8, 0x40, 0x36, 0x3d, 0xc8, 0x79, 0xb0,
+ 0x42, 0x6d, 0x96, 0x2b, 0xbc, 0x5c, 0x0f, 0x99, 0x6f, 0x78, 0x45, 0x7f,
+ 0xff, 0xa4, 0x2f, 0xe6, 0x98, 0xf9, 0xef, 0xe6, 0x1f, 0x37, 0x58, 0xbf,
+ 0xfd, 0xcd, 0xd9, 0xbb, 0x6b, 0x1f, 0xf2, 0x35, 0x8b, 0xff, 0xd9, 0xdc,
+ 0x59, 0xd8, 0xb0, 0x07, 0x98, 0x2c, 0x56, 0xe8, 0x99, 0x89, 0x32, 0xa5,
+ 0x31, 0xfc, 0x87, 0xd5, 0xfc, 0x59, 0xee, 0x60, 0x4b, 0x17, 0xe0, 0x98,
+ 0x8a, 0x56, 0x2c, 0x25, 0x8b, 0x40, 0xc3, 0x73, 0xc2, 0x7b, 0x37, 0x48,
+ 0x8f, 0xd3, 0x3d, 0x46, 0x8c, 0xc8, 0x79, 0x85, 0xde, 0x46, 0x63, 0xb9,
+ 0xdb, 0xc7, 0x0b, 0x1e, 0xb5, 0x11, 0x56, 0xa3, 0xec, 0xfc, 0xe1, 0x81,
+ 0x46, 0xb8, 0x28, 0x5b, 0x5d, 0xd7, 0x16, 0x2f, 0x68, 0x50, 0x58, 0xb7,
+ 0xe4, 0xdb, 0xb8, 0xcd, 0xff, 0x6c, 0xff, 0x89, 0xa0, 0xff, 0x58, 0xbf,
+ 0x80, 0x59, 0xb0, 0x70, 0x58, 0xbe, 0x04, 0x70, 0xbc, 0xb1, 0x58, 0x7a,
+ 0xfa, 0x30, 0xbf, 0xdd, 0xbe, 0xe3, 0xfe, 0x71, 0x62, 0xff, 0xff, 0x84,
+ 0x2e, 0x8b, 0x3b, 0x18, 0x3c, 0xf4, 0x33, 0xff, 0x68, 0x2c, 0x5f, 0xf1,
+ 0xf9, 0xfc, 0xf1, 0x49, 0xd6, 0x2f, 0x16, 0x70, 0x91, 0x49, 0x1c, 0xd7,
+ 0x4c, 0x98, 0x7f, 0x68, 0x6d, 0x5f, 0xfe, 0xd6, 0xa7, 0x6c, 0x0b, 0xa8,
+ 0x78, 0x43, 0x58, 0xbe, 0xcc, 0x23, 0x56, 0x2f, 0xfc, 0xe6, 0xe4, 0x1d,
+ 0xbb, 0x7d, 0xd6, 0x2d, 0x2e, 0x8b, 0x1d, 0x27, 0xfc, 0x8a, 0xfc, 0xc6,
+ 0xc7, 0x39, 0xab, 0x15, 0x2a, 0x9b, 0x1e, 0x33, 0x0f, 0xc3, 0x6c, 0x8d,
+ 0x2f, 0xf1, 0x7a, 0x36, 0x6f, 0x0a, 0x56, 0x2f, 0xe8, 0x16, 0x75, 0xe6,
+ 0x58, 0xbf, 0x87, 0xe3, 0x5c, 0x86, 0xb1, 0x52, 0x89, 0x56, 0x38, 0x11,
+ 0x75, 0xf1, 0xdc, 0x2e, 0x2c, 0x5f, 0xe6, 0xdb, 0xdc, 0x66, 0x8f, 0x58,
+ 0xad, 0x8f, 0x6f, 0xb1, 0x25, 0xfd, 0xf7, 0x89, 0x9a, 0x0b, 0x17, 0x1e,
+ 0x0b, 0x17, 0x3e, 0xb7, 0x3c, 0x60, 0xcb, 0xaf, 0xfd, 0x27, 0xdf, 0xef,
+ 0xec, 0xc3, 0xac, 0x5f, 0x70, 0xee, 0x05, 0x8a, 0xf9, 0xf1, 0x00, 0xfe,
+ 0xff, 0xe7, 0x2d, 0xb3, 0x79, 0xec, 0x29, 0xe2, 0xc5, 0xf6, 0xb6, 0x93,
+ 0x56, 0x2c, 0xeb, 0x17, 0x31, 0xb8, 0x6d, 0xbc, 0x4b, 0x52, 0x8c, 0xb1,
+ 0x91, 0x13, 0xed, 0xfe, 0xcd, 0xe6, 0x3f, 0x66, 0x25, 0x8b, 0xfc, 0x53,
+ 0x31, 0xfa, 0x93, 0xac, 0x5f, 0xe2, 0xdd, 0xbc, 0xc6, 0x98, 0x47, 0xd9,
+ 0xc3, 0x7b, 0xff, 0xd9, 0xc0, 0x49, 0x78, 0x7f, 0x92, 0xd9, 0x62, 0xa5,
+ 0x12, 0xba, 0x4b, 0xbf, 0xfc, 0x59, 0xf0, 0xf9, 0xc1, 0x1f, 0x8d, 0xd2,
+ 0xc5, 0xf0, 0x31, 0xd9, 0x62, 0xf0, 0x1c, 0x35, 0x8b, 0xfb, 0x0b, 0x3b,
+ 0x3e, 0x96, 0x2f, 0xff, 0xce, 0x71, 0xcf, 0xf3, 0xb4, 0x7b, 0x90, 0xf3,
+ 0x65, 0x8b, 0xf4, 0x97, 0xb8, 0xfb, 0xa2, 0x23, 0xe5, 0xd7, 0xdd, 0xd3,
+ 0xfe, 0x2c, 0x51, 0xa9, 0xcd, 0xee, 0x44, 0xc9, 0xa0, 0x21, 0xf4, 0x29,
+ 0xbb, 0x8f, 0xef, 0xf9, 0xb5, 0xb7, 0xdf, 0x35, 0x12, 0xc5, 0xff, 0xcc,
+ 0xc4, 0x0e, 0x64, 0x7c, 0x4c, 0xcb, 0x17, 0xff, 0xff, 0xf3, 0xfe, 0x3d,
+ 0xcb, 0x3d, 0xe9, 0xd8, 0x65, 0x32, 0x0f, 0x43, 0x08, 0x9a, 0x0b, 0x17,
+ 0xfd, 0x9e, 0xc3, 0xb6, 0x9e, 0x25, 0x8a, 0xc4, 0x60, 0x94, 0x22, 0x2b,
+ 0x74, 0xda, 0x22, 0x3b, 0xf4, 0x60, 0xf7, 0xfa, 0x45, 0xdf, 0x94, 0xfb,
+ 0x8b, 0x17, 0xe8, 0x73, 0x6c, 0x09, 0x62, 0xc4, 0xb1, 0x7f, 0xf1, 0xc9,
+ 0x8d, 0xe3, 0x8b, 0x99, 0x1e, 0xb1, 0x58, 0x7b, 0x2e, 0x23, 0x7e, 0xea,
+ 0x02, 0x6f, 0x2c, 0x5a, 0x46, 0x79, 0x5e, 0x20, 0xbd, 0x9a, 0xd9, 0x62,
+ 0xf3, 0x14, 0x4b, 0x15, 0xf3, 0x76, 0xc3, 0xd7, 0x99, 0xb7, 0x54, 0x9a,
+ 0x05, 0xff, 0xfe, 0xc1, 0xce, 0xee, 0x5b, 0x73, 0x7f, 0xb8, 0xc7, 0x84,
+ 0xb1, 0x7e, 0x6d, 0x6d, 0x81, 0x2c, 0x5e, 0x60, 0xbb, 0x8c, 0x44, 0x66,
+ 0xec, 0x57, 0xf0, 0x24, 0xa7, 0xdc, 0x58, 0xbd, 0xa9, 0xf2, 0xc5, 0xfd,
+ 0x22, 0xf1, 0x3f, 0x65, 0x8b, 0xfb, 0xdc, 0xc3, 0x5f, 0x51, 0x1e, 0x66,
+ 0x87, 0x6a, 0x55, 0x7f, 0xed, 0x0c, 0xe1, 0xb1, 0x6e, 0x41, 0xa8, 0x5b,
+ 0x00, 0xe8, 0x37, 0x9b, 0xf6, 0xfc, 0xf6, 0x69, 0x62, 0xfe, 0xf1, 0x98,
+ 0x6b, 0xe9, 0x62, 0xf4, 0x1c, 0x0b, 0x17, 0xf4, 0xf5, 0x01, 0xe9, 0x96,
+ 0x2f, 0xe9, 0x36, 0x3d, 0xc4, 0x35, 0x8b, 0x74, 0x03, 0xe1, 0xf1, 0x7d,
+ 0xfc, 0xfe, 0xfb, 0x11, 0xab, 0x15, 0x29, 0x97, 0xb9, 0x54, 0x46, 0x0c,
+ 0xfd, 0xc2, 0x9b, 0xef, 0x93, 0x47, 0xac, 0x5e, 0x10, 0xb4, 0xb1, 0x78,
+ 0xa7, 0x4b, 0x17, 0x6a, 0x28, 0x8d, 0xd7, 0x07, 0xaf, 0xff, 0xf7, 0x18,
+ 0xbf, 0x3d, 0xbf, 0x9e, 0xc6, 0x2d, 0xf0, 0x6b, 0x17, 0xec, 0xcf, 0x61,
+ 0xd6, 0x2f, 0xff, 0xf3, 0xcf, 0x9f, 0xf3, 0xcf, 0xe7, 0x35, 0x9b, 0xe7,
+ 0x96, 0x2f, 0xfe, 0x90, 0x70, 0xb2, 0x3c, 0x73, 0xee, 0x2c, 0x59, 0xbe,
+ 0x8c, 0xe2, 0x27, 0xe3, 0x05, 0x4a, 0x6c, 0x7f, 0x8c, 0xbe, 0xff, 0xe9,
+ 0xde, 0x4f, 0x9a, 0xd3, 0x05, 0xdc, 0xb1, 0x5a, 0x3f, 0x2e, 0xe2, 0x9b,
+ 0xfb, 0x63, 0x22, 0x84, 0xec, 0xb1, 0x7f, 0x67, 0x69, 0x84, 0xe9, 0x62,
+ 0xa5, 0x57, 0x56, 0x2f, 0xbc, 0xa0, 0x46, 0x25, 0x23, 0x3b, 0xf0, 0xe6,
+ 0x27, 0x3a, 0xc5, 0xfe, 0x81, 0x9f, 0xcc, 0x2d, 0xd6, 0x2f, 0xe0, 0x8b,
+ 0x36, 0x0e, 0x0b, 0x17, 0xc1, 0xc7, 0x67, 0x16, 0x2f, 0xe1, 0x0b, 0xdc,
+ 0x68, 0x96, 0x2f, 0xfe, 0xe6, 0x1a, 0x59, 0xb3, 0x7a, 0x26, 0x58, 0xbb,
+ 0xdc, 0x31, 0x13, 0xa7, 0x27, 0xf1, 0x85, 0xfb, 0x39, 0xec, 0xdd, 0x62,
+ 0xfc, 0x3c, 0x03, 0x4a, 0xc5, 0xff, 0xff, 0x9b, 0x50, 0xe3, 0x8f, 0x35,
+ 0xb3, 0xf3, 0xec, 0x0e, 0x61, 0x2c, 0x54, 0x11, 0x79, 0x85, 0x3c, 0x27,
+ 0xa9, 0x54, 0x56, 0xe6, 0xad, 0x0c, 0xe1, 0x43, 0xe6, 0xfd, 0xb1, 0xd9,
+ 0x89, 0x62, 0xff, 0xba, 0xfc, 0xf6, 0xff, 0x4d, 0x1e, 0xb1, 0x7f, 0xff,
+ 0xfc, 0x69, 0x31, 0xe7, 0xd8, 0x7c, 0x1e, 0x47, 0xf8, 0xb0, 0x00, 0x98,
+ 0xbc, 0xb1, 0x7f, 0xbb, 0x7f, 0x0b, 0x67, 0xe2, 0xc5, 0xfe, 0x06, 0x3f,
+ 0x39, 0x20, 0x58, 0xa9, 0x3e, 0x96, 0x36, 0xa9, 0x4d, 0xcb, 0x0a, 0x19,
+ 0x07, 0x90, 0xe9, 0xbf, 0xf0, 0xe3, 0xb3, 0x83, 0xfb, 0xeb, 0x65, 0x8b,
+ 0xff, 0xec, 0x0b, 0xc7, 0x9c, 0xf7, 0xf3, 0x0b, 0x75, 0x8a, 0x94, 0x4a,
+ 0x7d, 0x12, 0xfe, 0xed, 0xac, 0xf3, 0x74, 0xb1, 0x7f, 0xba, 0xfe, 0x6e,
+ 0x59, 0xb2, 0xc5, 0xee, 0xf3, 0xbd, 0x8d, 0x16, 0x2f, 0xb0, 0xa0, 0xeb,
+ 0x17, 0xff, 0x66, 0xb4, 0xd0, 0x0c, 0x9b, 0xdc, 0x58, 0xa9, 0x3e, 0x68,
+ 0x10, 0xd6, 0x91, 0x69, 0xe8, 0x49, 0xdf, 0xed, 0x00, 0x59, 0x14, 0x9d,
+ 0x62, 0xa5, 0x34, 0x77, 0x87, 0x53, 0x14, 0x5f, 0xfd, 0xbf, 0xde, 0x22,
+ 0x60, 0xb3, 0xaf, 0x2c, 0x5f, 0xdf, 0x9f, 0x7e, 0x62, 0x58, 0xac, 0x3f,
+ 0x78, 0x92, 0x2a, 0x5b, 0xab, 0xad, 0x89, 0x61, 0x2b, 0xf8, 0x70, 0xdc,
+ 0xc8, 0x44, 0x9a, 0xd7, 0xbc, 0x6b, 0x8f, 0x2b, 0x2a, 0x3e, 0x3c, 0x98,
+ 0x8e, 0x75, 0x2c, 0xdc, 0xf1, 0xd0, 0xfe, 0x59, 0x9b, 0x27, 0x14, 0xa5,
+ 0x4e, 0x47, 0x71, 0xe8, 0x6a, 0x08, 0x8b, 0xb4, 0x6f, 0x01, 0xc2, 0xaa,
+ 0xff, 0xf4, 0x96, 0xe3, 0xfc, 0xf5, 0xf9, 0xed, 0x8b, 0x17, 0xff, 0xff,
+ 0x9f, 0xe2, 0x26, 0x6e, 0xdb, 0xfd, 0xfd, 0x87, 0xe3, 0xe1, 0x01, 0x96,
+ 0x2f, 0xf8, 0x87, 0xc6, 0x1b, 0x74, 0x4b, 0x17, 0xff, 0xdd, 0x40, 0xa5,
+ 0x86, 0xfb, 0xe7, 0xdb, 0xcb, 0x15, 0x04, 0xc0, 0x31, 0xdd, 0xce, 0x6f,
+ 0xfe, 0x6d, 0x60, 0xfe, 0xc7, 0x0e, 0x49, 0x62, 0xc0, 0x58, 0xbc, 0x3f,
+ 0xca, 0xc5, 0xf6, 0x75, 0xe6, 0x58, 0xb7, 0x0c, 0x3c, 0x02, 0x1d, 0xad,
+ 0x1f, 0xd7, 0x94, 0xa9, 0x91, 0xc0, 0x28, 0x5f, 0x5b, 0x16, 0x2f, 0xff,
+ 0x0f, 0xf3, 0x2f, 0xee, 0x39, 0x75, 0x05, 0x8b, 0x08, 0x67, 0xb6, 0x42,
+ 0x37, 0x61, 0xd6, 0x2f, 0xff, 0x8d, 0x7d, 0x67, 0x5e, 0xfb, 0x87, 0x23,
+ 0x95, 0x8b, 0x98, 0x96, 0x2f, 0x39, 0x62, 0xc5, 0xff, 0xb9, 0xf9, 0x3f,
+ 0xb8, 0x4d, 0xd6, 0xc6, 0xc6, 0x02, 0xd7, 0xfe, 0xeb, 0xb7, 0xe3, 0xdf,
+ 0xc5, 0x27, 0x58, 0xac, 0x4c, 0x7b, 0xa8, 0x41, 0xb2, 0xb5, 0xe9, 0xd9,
+ 0xd6, 0x2a, 0x57, 0x23, 0x32, 0x34, 0xd3, 0x63, 0x0f, 0x78, 0x41, 0x68,
+ 0x9d, 0xa3, 0x35, 0x23, 0x5b, 0xfa, 0x2f, 0xc8, 0x4c, 0x4b, 0x17, 0xe8,
+ 0xa1, 0x3a, 0xd9, 0x62, 0xfe, 0xcd, 0x69, 0x82, 0xee, 0x58, 0xa9, 0x44,
+ 0x66, 0xc5, 0xe7, 0x2b, 0xbf, 0xff, 0x05, 0xf2, 0x66, 0xeb, 0xc2, 0x6f,
+ 0xbe, 0x12, 0xc5, 0xff, 0xff, 0x6b, 0x06, 0x4c, 0xdd, 0xb9, 0x91, 0xfe,
+ 0x2c, 0xcd, 0x44, 0xb1, 0x7e, 0x2f, 0x18, 0x7d, 0x96, 0x2f, 0x84, 0x76,
+ 0xf2, 0xc5, 0xff, 0xf9, 0xf6, 0x2c, 0xed, 0xf7, 0xf7, 0x50, 0x92, 0x89,
+ 0x62, 0xa5, 0x14, 0xe3, 0x2b, 0xf9, 0x1d, 0xff, 0xff, 0x9f, 0x4f, 0x9d,
+ 0xb3, 0x6c, 0x7f, 0x49, 0xc9, 0x8d, 0xfb, 0xac, 0x5f, 0xfd, 0x09, 0x68,
+ 0x18, 0xf1, 0x3e, 0x12, 0xc5, 0xf7, 0x8d, 0x7d, 0xd6, 0x2f, 0xff, 0xf3,
+ 0xc9, 0x7b, 0x53, 0xf6, 0xe1, 0x60, 0x39, 0xe7, 0x58, 0xbf, 0xe7, 0xf4,
+ 0x9d, 0xfc, 0x29, 0x58, 0xbf, 0xd3, 0x03, 0x22, 0x8f, 0x72, 0x58, 0xb6,
+ 0x70, 0xfc, 0x3c, 0x71, 0x7f, 0xe1, 0x37, 0x5c, 0x2c, 0xec, 0xd0, 0x58,
+ 0xbf, 0xe8, 0x8a, 0x4f, 0xf9, 0xec, 0x75, 0x8b, 0xff, 0xd0, 0x7d, 0x01,
+ 0xbd, 0x91, 0x41, 0xfc, 0xb1, 0x7e, 0xf3, 0xc7, 0x66, 0xcb, 0x17, 0xbb,
+ 0xc8, 0xdf, 0xbc, 0x58, 0xbf, 0xfb, 0x02, 0x31, 0xbc, 0x59, 0xb3, 0x12,
+ 0xc5, 0xa5, 0x62, 0xff, 0x73, 0x3e, 0xfc, 0x16, 0xcb, 0x17, 0xcf, 0x1d,
+ 0x9b, 0x2c, 0x5c, 0xdd, 0x18, 0x98, 0x54, 0x6a, 0x2c, 0xd8, 0xb4, 0x68,
+ 0xbc, 0x11, 0xf1, 0xad, 0xcd, 0xd2, 0xc5, 0x62, 0xa1, 0x5e, 0x8f, 0x39,
+ 0x1a, 0xaf, 0x9b, 0x2c, 0xe3, 0x5c, 0x94, 0xdc, 0xbf, 0xa6, 0xc8, 0x91,
+ 0x3e, 0x4a, 0x50, 0xce, 0xe1, 0x3f, 0xa5, 0x2b, 0x5f, 0xf7, 0xdf, 0xdc,
+ 0x6e, 0x80, 0x12, 0xc5, 0xe1, 0xb6, 0xcb, 0x15, 0xb9, 0xed, 0x06, 0x79,
+ 0x76, 0x01, 0x62, 0xda, 0xd8, 0xdd, 0x80, 0x92, 0xff, 0xfb, 0xb8, 0xf3,
+ 0x25, 0x11, 0x85, 0x27, 0xd6, 0x2c, 0x5f, 0xfe, 0xdb, 0x4f, 0xed, 0x85,
+ 0xa8, 0x72, 0x3d, 0xd6, 0x29, 0x91, 0x48, 0x25, 0x3a, 0x96, 0x41, 0xa6,
+ 0x18, 0x3a, 0xaf, 0xe7, 0x69, 0x5a, 0x31, 0xc2, 0x86, 0x65, 0xff, 0x60,
+ 0x6c, 0xdd, 0x33, 0x04, 0xb1, 0x7f, 0x67, 0xb0, 0x9a, 0x25, 0x8b, 0xfb,
+ 0x4f, 0xb9, 0x4f, 0xd6, 0x2f, 0xf8, 0x4d, 0xe6, 0x83, 0x75, 0x05, 0x8b,
+ 0xff, 0x8c, 0xe6, 0xff, 0x70, 0xb0, 0xd9, 0xe2, 0xc5, 0xfd, 0x08, 0xbe,
+ 0xfd, 0x79, 0x62, 0xf8, 0x3c, 0xeb, 0xcb, 0x15, 0x27, 0xac, 0xc6, 0x37,
+ 0x6b, 0x8b, 0x15, 0x29, 0xd3, 0x40, 0xeb, 0x0b, 0x77, 0x2e, 0xf9, 0xd7,
+ 0x21, 0x3f, 0x1c, 0x41, 0x7f, 0x9c, 0x78, 0x73, 0x30, 0x6b, 0x17, 0x37,
+ 0x16, 0x2f, 0xf0, 0x5c, 0xf1, 0x66, 0x6e, 0xb1, 0x7e, 0x70, 0xa3, 0x7e,
+ 0xf6, 0x37, 0x58, 0xbf, 0xfe, 0x16, 0xb5, 0x25, 0x86, 0xbf, 0xff, 0x81,
+ 0xac, 0x5b, 0xbf, 0x58, 0xad, 0x1f, 0x40, 0x94, 0x6f, 0xa7, 0x53, 0x12,
+ 0xc5, 0xfe, 0x93, 0x02, 0x62, 0x29, 0x58, 0xbc, 0x52, 0x75, 0x8b, 0x4a,
+ 0xc5, 0x44, 0x6b, 0x4e, 0x39, 0x7f, 0x8e, 0x22, 0xf7, 0x05, 0xa5, 0x8a,
+ 0x82, 0xa1, 0xd1, 0x9a, 0x60, 0xb9, 0xa6, 0xba, 0x85, 0x09, 0xc8, 0x80,
+ 0x46, 0x4c, 0x11, 0xc4, 0x57, 0xef, 0xb1, 0xe4, 0x96, 0x2f, 0xbb, 0xbf,
+ 0x24, 0xb1, 0x6d, 0x2c, 0x5e, 0xd6, 0x62, 0xc5, 0x6c, 0x7a, 0x60, 0x25,
+ 0xee, 0x12, 0xbf, 0xff, 0xba, 0xe4, 0xc3, 0x59, 0xb4, 0xeb, 0x3c, 0xfd,
+ 0x04, 0xb1, 0x63, 0x56, 0x2b, 0x63, 0xf2, 0x25, 0xfb, 0xb9, 0xc5, 0x8b,
+ 0xff, 0xd8, 0x32, 0x66, 0x0b, 0xdd, 0x42, 0x42, 0x58, 0xbb, 0xa8, 0x68,
+ 0xf9, 0x3e, 0x31, 0x7d, 0x14, 0x1b, 0x4b, 0x17, 0xbb, 0xf8, 0xe7, 0x58,
+ 0xa0, 0x1e, 0x48, 0x89, 0x2f, 0x87, 0xb6, 0x04, 0xb1, 0x52, 0x9a, 0x2e,
+ 0x42, 0x19, 0xde, 0x04, 0x45, 0x7d, 0xbb, 0x67, 0x16, 0x2f, 0xfd, 0xb4,
+ 0x9b, 0xfc, 0x21, 0x60, 0xd6, 0x2f, 0xfc, 0x23, 0xfe, 0x4f, 0x14, 0x7b,
+ 0x8d, 0x62, 0x89, 0x10, 0x9d, 0xc8, 0x17, 0xfd, 0x87, 0xcd, 0xe7, 0xf2,
+ 0x75, 0x8b, 0xff, 0x98, 0xb7, 0xe1, 0x67, 0x38, 0xfd, 0x96, 0x2d, 0xef,
+ 0x9f, 0xfb, 0x1c, 0xdf, 0xb2, 0x28, 0x9b, 0x8b, 0x17, 0xff, 0xd9, 0xee,
+ 0xa1, 0x20, 0x04, 0x8f, 0xe2, 0xee, 0x58, 0xaf, 0x9f, 0xf9, 0x15, 0x56,
+ 0xc8, 0xc7, 0xea, 0x14, 0xd5, 0x8a, 0x8f, 0x1e, 0x14, 0xed, 0x1b, 0x5d,
+ 0xfd, 0x91, 0xfb, 0xfd, 0xfb, 0x96, 0x2f, 0xf8, 0xa2, 0xc1, 0xc5, 0x07,
+ 0xfa, 0xc5, 0x9c, 0x8f, 0xc0, 0x46, 0xb7, 0xf9, 0x86, 0x53, 0x07, 0x25,
+ 0x8b, 0xf3, 0x6d, 0xb4, 0xf4, 0xb1, 0x5b, 0x1e, 0xe7, 0x8c, 0x6f, 0x82,
+ 0xf3, 0xec, 0xb1, 0x52, 0x79, 0x0c, 0x47, 0x7f, 0x17, 0x50, 0xf0, 0x86,
+ 0xb1, 0x7e, 0x08, 0x4d, 0xa1, 0xac, 0x5f, 0xee, 0x3f, 0xa2, 0x29, 0x3a,
+ 0xc5, 0x11, 0xef, 0x70, 0xaa, 0xfd, 0x1f, 0x84, 0x77, 0x58, 0xa9, 0x46,
+ 0xcb, 0xc2, 0x39, 0x88, 0x6f, 0x8a, 0x70, 0x25, 0x8b, 0xc5, 0x80, 0x58,
+ 0xbf, 0xfe, 0x73, 0x23, 0xdf, 0x63, 0x3f, 0x91, 0x16, 0x04, 0xb1, 0x7d,
+ 0x16, 0x66, 0xcb, 0x17, 0xee, 0x3f, 0x8a, 0x56, 0x2e, 0xcf, 0xf0, 0xf2,
+ 0xfc, 0x49, 0x60, 0xbb, 0xd4, 0xc3, 0x74, 0x45, 0xf1, 0xcf, 0x42, 0x8a,
+ 0xfe, 0x0b, 0xc5, 0x27, 0xe2, 0xc5, 0x31, 0xff, 0x09, 0x3e, 0xfd, 0x17,
+ 0xf0, 0x0c, 0xb1, 0x52, 0xc8, 0xda, 0x84, 0x7d, 0x59, 0x29, 0xf2, 0x3e,
+ 0x15, 0x5a, 0x86, 0x57, 0xe1, 0xf2, 0x51, 0xde, 0xf6, 0x21, 0xbf, 0xff,
+ 0xef, 0xe7, 0xbc, 0xdb, 0x67, 0x8e, 0xe2, 0x28, 0x8b, 0x02, 0x58, 0xbf,
+ 0xe2, 0xc0, 0xbf, 0x87, 0x9e, 0x2c, 0x5f, 0xf6, 0x3c, 0x3f, 0x3f, 0x73,
+ 0x56, 0x2f, 0xf1, 0x30, 0x39, 0xbf, 0xde, 0x23, 0xf2, 0x23, 0x9a, 0x1a,
+ 0x64, 0x9e, 0x86, 0xd5, 0xfe, 0xf7, 0x50, 0xce, 0xc2, 0xfa, 0xc5, 0xe1,
+ 0xff, 0x16, 0x2f, 0xef, 0x7f, 0x21, 0x00, 0x2c, 0x5f, 0xe6, 0x6d, 0x8f,
+ 0x3e, 0xe2, 0xc5, 0xfb, 0x18, 0xb2, 0x3d, 0x62, 0xfe, 0x2c, 0x1f, 0xe7,
+ 0xb1, 0xcf, 0x77, 0xe6, 0x95, 0x29, 0xa7, 0x8c, 0xa7, 0x0e, 0x08, 0x74,
+ 0x28, 0x46, 0x5f, 0xe2, 0x66, 0xed, 0x0e, 0xc0, 0x58, 0xbf, 0xfe, 0xe4,
+ 0xc5, 0xf9, 0xec, 0x58, 0x3f, 0xcf, 0x16, 0x28, 0x68, 0x89, 0xf1, 0xbd,
+ 0xf6, 0xf2, 0x0e, 0x2c, 0x5f, 0xf6, 0x6f, 0x9e, 0xfb, 0x30, 0x4b, 0x17,
+ 0x48, 0x16, 0x2f, 0x7d, 0xc2, 0xd1, 0xe8, 0xc7, 0x1d, 0x5f, 0xfe, 0x3b,
+ 0xf5, 0x0e, 0x16, 0x6f, 0xe1, 0x12, 0xc5, 0xfe, 0xe6, 0x47, 0x81, 0x9a,
+ 0x25, 0x8b, 0xff, 0xf7, 0x23, 0xdc, 0xb3, 0xb3, 0x70, 0x21, 0x63, 0xfd,
+ 0x62, 0xff, 0xf6, 0x7b, 0x8f, 0x9a, 0x90, 0x71, 0xfb, 0x2c, 0x56, 0x27,
+ 0xef, 0xb9, 0x1c, 0x4e, 0xa7, 0x37, 0xfa, 0x67, 0x0d, 0xe3, 0x96, 0xaf,
+ 0x8e, 0x39, 0x82, 0xc5, 0xff, 0xbf, 0x9d, 0xa3, 0xdc, 0x43, 0xc1, 0xac,
+ 0x5b, 0xcb, 0x15, 0x27, 0xf3, 0xe2, 0x30, 0xd1, 0x2f, 0xff, 0xfa, 0x1c,
+ 0x03, 0x79, 0xb5, 0xc2, 0xcf, 0x08, 0x07, 0x68, 0x2c, 0x5b, 0xcb, 0x17,
+ 0xbf, 0x9e, 0x58, 0xbf, 0xee, 0x0b, 0x50, 0xdc, 0x9b, 0xb9, 0x62, 0xe2,
+ 0xc1, 0x9e, 0xdf, 0x87, 0x6c, 0xdd, 0x26, 0x00, 0xcc, 0xfe, 0x6d, 0xbe,
+ 0x87, 0x1c, 0x6b, 0x17, 0x3f, 0x16, 0x2c, 0x07, 0x37, 0x47, 0x23, 0xa9,
+ 0x5d, 0x75, 0xc9, 0x59, 0xcf, 0x0e, 0x26, 0x8c, 0xbc, 0x4e, 0x17, 0x3c,
+ 0x4b, 0x16, 0x75, 0x8b, 0xc5, 0xbb, 0x68, 0xd4, 0xf0, 0x62, 0xff, 0xfe,
+ 0xd1, 0x4c, 0xf4, 0x67, 0x3c, 0x52, 0x3f, 0xcf, 0x96, 0x2e, 0x7f, 0xac,
+ 0x5f, 0xff, 0x9c, 0xdc, 0x19, 0xd9, 0xb6, 0xd6, 0x00, 0x12, 0xb1, 0x77,
+ 0xc2, 0x58, 0xbe, 0x81, 0x30, 0x6b, 0x17, 0xf3, 0x7b, 0x9e, 0x7d, 0x96,
+ 0x2f, 0xf0, 0xd8, 0x1a, 0xd3, 0x01, 0x62, 0xfb, 0x5b, 0xc7, 0x84, 0xb1,
+ 0x7c, 0x6f, 0x7a, 0xc1, 0x2c, 0x5f, 0xdf, 0xc8, 0x76, 0x69, 0x58, 0xac,
+ 0x44, 0x13, 0x14, 0xf8, 0xaa, 0x9d, 0x1c, 0x85, 0x0b, 0x6a, 0x95, 0x4e,
+ 0x18, 0x65, 0x1e, 0xb9, 0xa1, 0x73, 0xab, 0x30, 0xc9, 0x11, 0x8a, 0x31,
+ 0x3b, 0xf6, 0x3f, 0xe4, 0x6b, 0x17, 0x4c, 0x7a, 0xc5, 0xf6, 0x8b, 0x3b,
+ 0x68, 0xf0, 0x7e, 0x4f, 0x7c, 0xc1, 0x42, 0x3d, 0x62, 0xf3, 0x47, 0xba,
+ 0xc5, 0xff, 0x83, 0xf1, 0xae, 0x6c, 0xe1, 0x4a, 0xc5, 0xba, 0x58, 0xbf,
+ 0xf3, 0x85, 0xfc, 0xe7, 0x3f, 0x31, 0xeb, 0x17, 0xff, 0x9d, 0x9a, 0x2f,
+ 0x7f, 0x21, 0xf7, 0xec, 0xb1, 0x7f, 0xfd, 0x9e, 0xe6, 0x05, 0x9f, 0x7d,
+ 0x0a, 0x40, 0xb1, 0x7f, 0xfc, 0x59, 0xee, 0x31, 0xf5, 0x8f, 0xf9, 0x1a,
+ 0xc5, 0x4a, 0x68, 0x1b, 0x89, 0xc7, 0xa1, 0x92, 0x67, 0x94, 0x2f, 0xc1,
+ 0xf8, 0xa4, 0x0b, 0x15, 0x2a, 0x9d, 0x86, 0x75, 0xd1, 0x3e, 0x87, 0xcf,
+ 0x1c, 0x07, 0x64, 0xdb, 0xf4, 0xfb, 0x3f, 0x2b, 0x17, 0xf9, 0xb4, 0x01,
+ 0x6e, 0x77, 0x58, 0xbf, 0xff, 0xdd, 0x0f, 0x77, 0x1b, 0x7f, 0x36, 0x2c,
+ 0xed, 0x1e, 0xfd, 0x96, 0x2f, 0xda, 0x33, 0x7c, 0xec, 0xb1, 0x7f, 0xc5,
+ 0x17, 0xf0, 0xb1, 0xc6, 0xb1, 0x58, 0x7c, 0xa2, 0x2d, 0xbf, 0xfc, 0xe4,
+ 0x4d, 0xe6, 0x39, 0x66, 0x69, 0x62, 0xf6, 0xd1, 0x62, 0xc5, 0xff, 0xf7,
+ 0x6c, 0xdf, 0x4c, 0xdd, 0x43, 0x91, 0xee, 0x4b, 0x15, 0x27, 0xea, 0xc3,
+ 0xf7, 0xff, 0x47, 0xbe, 0x7e, 0x7b, 0x73, 0xf3, 0xd2, 0xc5, 0x4a, 0xa4,
+ 0xac, 0x35, 0x78, 0x67, 0xc7, 0x90, 0xfe, 0x17, 0x7c, 0x20, 0xbe, 0x9f,
+ 0x61, 0xd6, 0x2f, 0xfd, 0xcf, 0xe0, 0x5f, 0x70, 0x8b, 0x16, 0x28, 0x07,
+ 0xc5, 0xd8, 0x8a, 0xfd, 0xd4, 0x0a, 0x4e, 0xb1, 0x7f, 0xff, 0xff, 0x8f,
+ 0x1e, 0xff, 0x06, 0x31, 0x6f, 0x9d, 0x43, 0x8f, 0xee, 0x3f, 0x50, 0x29,
+ 0xfc, 0xac, 0x5f, 0xd9, 0xf7, 0xcd, 0x44, 0xb1, 0x7f, 0xec, 0xea, 0x1c,
+ 0x7f, 0x31, 0x62, 0xc5, 0xfe, 0xc3, 0xff, 0x22, 0x68, 0x96, 0x2f, 0xcf,
+ 0xb7, 0xe6, 0x4c, 0x3f, 0x3f, 0x1f, 0x51, 0x88, 0xe0, 0xc8, 0x50, 0xdf,
+ 0x4f, 0x3b, 0x12, 0xc5, 0xf4, 0xf3, 0xb1, 0x2c, 0x5d, 0xd8, 0x96, 0x2f,
+ 0xf3, 0xfb, 0x99, 0xdb, 0x36, 0xef, 0x4f, 0x86, 0x36, 0x24, 0xe1, 0x25,
+ 0xff, 0xef, 0xcf, 0x59, 0xa9, 0xf3, 0xee, 0xe3, 0x58, 0xbc, 0x2d, 0x44,
+ 0xb1, 0x7a, 0x2c, 0xf0, 0xcf, 0xab, 0x89, 0x77, 0xff, 0xfe, 0x2d, 0xcc,
+ 0xd4, 0xed, 0xec, 0x6e, 0xc6, 0x4e, 0x17, 0xb9, 0x2b, 0x15, 0x88, 0xa4,
+ 0x63, 0x4a, 0x1a, 0xa1, 0xbd, 0xe1, 0x13, 0xf8, 0xdc, 0x6f, 0xc5, 0x14,
+ 0x1c, 0x96, 0x29, 0xcf, 0x99, 0x8f, 0xaa, 0x57, 0x0f, 0x30, 0xa7, 0xf2,
+ 0xfc, 0xef, 0xe7, 0xda, 0x4a, 0x62, 0x58, 0xbf, 0xbd, 0x91, 0x70, 0x47,
+ 0x58, 0xbb, 0xaf, 0xc7, 0x9e, 0xf3, 0x17, 0x5f, 0x36, 0xbe, 0x25, 0x8b,
+ 0xff, 0xe7, 0xf7, 0x1f, 0xd3, 0xee, 0x16, 0x60, 0x4b, 0x17, 0xfe, 0xc2,
+ 0xdf, 0xee, 0x3c, 0xd4, 0x4b, 0x15, 0x28, 0xe3, 0x81, 0x8e, 0x11, 0xc4,
+ 0x9f, 0x7f, 0xff, 0xe7, 0x2c, 0xf4, 0x9c, 0x21, 0x36, 0xc6, 0x67, 0xdf,
+ 0x5f, 0x65, 0x8b, 0xf1, 0xa6, 0xb7, 0xb8, 0xb1, 0x7f, 0xfd, 0x9b, 0x30,
+ 0xdc, 0x5b, 0xe9, 0xc2, 0x89, 0xd6, 0x2a, 0x51, 0xd7, 0x8d, 0xba, 0x2b,
+ 0xbf, 0x8e, 0xc3, 0xfb, 0x12, 0xc5, 0xcd, 0xdc, 0xb1, 0x7b, 0xee, 0x12,
+ 0xc5, 0xfb, 0xa8, 0x70, 0xb0, 0xe6, 0xe3, 0xc3, 0x57, 0xfd, 0xd4, 0x39,
+ 0x16, 0x9b, 0xdc, 0x58, 0xbf, 0xff, 0xff, 0xff, 0xfb, 0x59, 0x16, 0x00,
+ 0xcf, 0xb9, 0x9b, 0xfd, 0xfe, 0xc1, 0x18, 0x09, 0x88, 0xcf, 0xe6, 0x18,
+ 0x58, 0x3f, 0xb1, 0x99, 0x81, 0x79, 0x62, 0xff, 0xfe, 0xfb, 0xfd, 0x82,
+ 0xe7, 0xdf, 0xbb, 0x37, 0xfe, 0x62, 0xc5, 0xff, 0xbf, 0x33, 0xee, 0x47,
+ 0xb9, 0x76, 0x58, 0xbe, 0x66, 0x21, 0xac, 0x5e, 0x71, 0x74, 0x33, 0xe4,
+ 0x3a, 0x1d, 0xfd, 0x9d, 0xc6, 0x7d, 0xcc, 0xdd, 0x1e, 0xfc, 0x86, 0x1d,
+ 0xff, 0xfd, 0xf7, 0xfb, 0x05, 0xcf, 0xbf, 0x76, 0x6f, 0xfc, 0xc5, 0x8b,
+ 0xff, 0x7e, 0x67, 0xdc, 0x8f, 0x72, 0xec, 0xb1, 0x7c, 0xcc, 0x43, 0x58,
+ 0xbc, 0xe2, 0xe8, 0x67, 0xc8, 0x74, 0x3b, 0xff, 0xcd, 0xd1, 0x83, 0x71,
+ 0x77, 0x19, 0xf7, 0x33, 0x74, 0x7b, 0xf2, 0x18, 0x77, 0xff, 0xff, 0x02,
+ 0x62, 0x33, 0xf9, 0x86, 0x16, 0x0f, 0xec, 0x66, 0x60, 0x5e, 0x58, 0xbf,
+ 0xef, 0xbf, 0x76, 0x6f, 0xfc, 0xc5, 0x8b, 0xf7, 0xdf, 0xec, 0x11, 0x88,
+ 0xb1, 0xe3, 0xad, 0xff, 0xf9, 0xc5, 0xd0, 0xff, 0x33, 0xee, 0x47, 0xb9,
+ 0x76, 0x58, 0xbf, 0xff, 0xb3, 0xd2, 0x16, 0x78, 0xa4, 0x2e, 0xe3, 0x3e,
+ 0xe6, 0x6e, 0x89, 0xce, 0x20, 0xdf, 0xff, 0xdf, 0x7f, 0xb0, 0x5c, 0xfb,
+ 0xf7, 0x66, 0xff, 0xcc, 0x58, 0xbf, 0xe7, 0x17, 0x47, 0x66, 0x21, 0xac,
+ 0x5f, 0xf6, 0x39, 0x1a, 0x67, 0xdc, 0xcd, 0xd1, 0x31, 0xc5, 0xfb, 0xdf,
+ 0x9d, 0x62, 0xe3, 0x3e, 0xa3, 0x47, 0x28, 0xef, 0x39, 0x18, 0x8d, 0xff,
+ 0xff, 0xff, 0x7d, 0xfe, 0xc1, 0x18, 0x09, 0x88, 0xcf, 0xe6, 0x18, 0x58,
+ 0x3f, 0xb1, 0x99, 0x81, 0x79, 0x62, 0xff, 0xdf, 0x99, 0xf7, 0x23, 0xdc,
+ 0xbb, 0x2c, 0x5f, 0x33, 0x10, 0xd6, 0x2f, 0x38, 0xba, 0x19, 0xf2, 0x1d,
+ 0x0e, 0xff, 0xed, 0x6b, 0x1c, 0xb6, 0x33, 0xee, 0x66, 0xe9, 0x98, 0xf2,
+ 0x1f, 0xb7, 0xff, 0xff, 0xfd, 0xf7, 0xfb, 0x04, 0x60, 0x26, 0x23, 0x3f,
+ 0x98, 0x61, 0x60, 0xfe, 0xc6, 0x66, 0x05, 0xe5, 0x8b, 0xff, 0x7e, 0x67,
+ 0xdc, 0x8f, 0x72, 0xec, 0xb1, 0x7c, 0xcc, 0x43, 0x58, 0xbc, 0xe2, 0xe8,
+ 0x67, 0xc8, 0x74, 0x3b, 0xff, 0xd1, 0xef, 0xdc, 0x6e, 0xb0, 0x66, 0x7d,
+ 0xcc, 0xdd, 0x33, 0x1e, 0x43, 0xf6, 0xff, 0xff, 0xff, 0xbe, 0xff, 0x60,
+ 0x8c, 0x04, 0xc4, 0x67, 0xf3, 0x0c, 0x2c, 0x1f, 0xd8, 0xcc, 0xc0, 0xbc,
+ 0xb1, 0x7f, 0xef, 0xcc, 0xfb, 0x91, 0xee, 0x5d, 0x96, 0x2f, 0x99, 0x88,
+ 0x6b, 0x17, 0x9c, 0x5d, 0x0c, 0xf9, 0x0e, 0x87, 0x7f, 0xf4, 0x8f, 0xf9,
+ 0x9d, 0x8c, 0xfb, 0x99, 0xba, 0x66, 0x3c, 0x87, 0xed, 0xff, 0xff, 0xc0,
+ 0x98, 0x8c, 0xfe, 0x61, 0x85, 0x83, 0xfb, 0x19, 0x98, 0x17, 0x96, 0x2f,
+ 0xfb, 0xef, 0xdd, 0x9b, 0xff, 0x31, 0x62, 0xff, 0xff, 0xff, 0x6b, 0x81,
+ 0x91, 0xa6, 0x7b, 0x98, 0x10, 0xc5, 0xc3, 0x3e, 0xe6, 0x6f, 0xf7, 0xfb,
+ 0x04, 0x62, 0x2c, 0x78, 0xeb, 0x7f, 0xff, 0xf0, 0x26, 0x23, 0x3f, 0x98,
+ 0x61, 0x60, 0xfe, 0xc6, 0x66, 0x05, 0xe5, 0x8b, 0xfe, 0xfb, 0xf7, 0x66,
+ 0xff, 0xcc, 0x58, 0xbf, 0x7d, 0xfe, 0xc1, 0x18, 0x8b, 0x1e, 0x3a, 0xdf,
+ 0xf3, 0x8b, 0xa3, 0xb3, 0x10, 0xd6, 0x2f, 0xfc, 0x17, 0xe3, 0xdc, 0x8c,
+ 0xfb, 0x99, 0xb9, 0xfd, 0x71, 0x06, 0xff, 0xff, 0xe0, 0x4c, 0x46, 0x7f,
+ 0x30, 0xc2, 0xc1, 0xfd, 0x8c, 0xcc, 0x0b, 0xcb, 0x17, 0xfd, 0xf7, 0xee,
+ 0xcd, 0xff, 0x98, 0xb1, 0x7e, 0xfb, 0xfd, 0x82, 0x31, 0x16, 0x3c, 0x75,
+ 0xbf, 0xff, 0x38, 0xba, 0x1f, 0xe6, 0x7d, 0xc8, 0xf7, 0x2e, 0xcb, 0x17,
+ 0xfc, 0x2c, 0xcd, 0x19, 0xf7, 0x33, 0x74, 0x4e, 0x71, 0x06, 0xe2, 0x99,
+ 0x4f, 0xf0, 0x28, 0xea, 0x6f, 0xfd, 0xf9, 0x9f, 0x72, 0x3d, 0xcb, 0xb2,
+ 0xc5, 0xf3, 0x31, 0x0d, 0x62, 0xff, 0xda, 0x33, 0xee, 0x67, 0x1c, 0x5d,
+ 0x0c, 0xf9, 0x0e, 0x87, 0x7f, 0xff, 0xf0, 0x26, 0x23, 0x3f, 0x98, 0x61,
+ 0x60, 0xfe, 0xc6, 0x66, 0x05, 0xe5, 0x8b, 0xfe, 0xfb, 0xf7, 0x66, 0xff,
+ 0xcc, 0x58, 0xbf, 0x7d, 0xfe, 0xc1, 0x18, 0x8b, 0x1e, 0x3a, 0xdf, 0xf3,
+ 0x8b, 0xa3, 0xb3, 0x10, 0xd6, 0x2f, 0xff, 0xf1, 0xcc, 0xce, 0x63, 0x91,
+ 0xa6, 0x60, 0xcc, 0xfb, 0x99, 0xb9, 0xfd, 0x71, 0x06, 0xa5, 0x50, 0x06,
+ 0x47, 0x09, 0x43, 0x55, 0x82, 0x52, 0xa6, 0x2f, 0xff, 0xfe, 0x04, 0xc4,
+ 0x67, 0xf3, 0x0c, 0x2c, 0x1f, 0xd8, 0xcc, 0xc0, 0xbc, 0xb1, 0x7f, 0xdf,
+ 0x7e, 0xec, 0xdf, 0xf9, 0x8b, 0x17, 0xff, 0xff, 0xff, 0x9c, 0x8c, 0xfe,
+ 0x0c, 0xcf, 0xcc, 0x99, 0xfc, 0xe8, 0x1a, 0x93, 0x3e, 0xe6, 0x6f, 0xf7,
+ 0xfb, 0x04, 0x62, 0x2c, 0x78, 0xeb, 0x52, 0xc8, 0x39, 0xc9, 0xe9, 0x98,
+ 0xf8, 0x6e, 0x5f, 0xff, 0xfc, 0x09, 0x88, 0xcf, 0xe6, 0x18, 0x58, 0x3f,
+ 0xb1, 0x99, 0x81, 0x79, 0x62, 0xff, 0xbe, 0xfd, 0xd9, 0xbf, 0xf3, 0x16,
+ 0x2f, 0xdf, 0x7f, 0xb0, 0x46, 0x22, 0xc7, 0x8e, 0xb7, 0xff, 0xe7, 0x17,
+ 0x43, 0xfc, 0xcf, 0xb9, 0x1e, 0xe5, 0xd9, 0x62, 0xff, 0xf4, 0xe8, 0x03,
+ 0x71, 0x77, 0x19, 0xf7, 0x33, 0x74, 0x4e, 0x71, 0x06, 0xa5, 0xb6, 0x46,
+ 0x1c, 0xf1, 0xa6, 0x47, 0x25, 0xa8, 0xe5, 0x8f, 0x1d, 0x1f, 0xe9, 0x2a,
+ 0x1c, 0x8e, 0x3e, 0xff, 0xff, 0x7b, 0x98, 0x3f, 0xbf, 0x1c, 0x5d, 0x1d,
+ 0x98, 0x86, 0xb1, 0x7f, 0x36, 0xe3, 0xfc, 0xe9, 0x62, 0xff, 0xff, 0xfe,
+ 0x9d, 0x67, 0xbd, 0x3a, 0x07, 0xb3, 0xa0, 0x37, 0x1c, 0x5d, 0x1d, 0x98,
+ 0x86, 0xb1, 0x52, 0x98, 0xce, 0x30, 0xfc, 0xbe, 0xf6, 0x37, 0x4b, 0x17,
+ 0xff, 0xd9, 0xbe, 0x6b, 0x37, 0xfe, 0x73, 0x82, 0xf2, 0xc5, 0xff, 0xfd,
+ 0x31, 0x7f, 0x30, 0xb0, 0x7f, 0x6c, 0xc0, 0xbc, 0xb1, 0x7f, 0xdf, 0x7e,
+ 0xec, 0xdf, 0xf9, 0x8b, 0x17, 0xef, 0xbf, 0xd8, 0x28, 0x93, 0x05, 0xf8,
+ 0xe8, 0x14, 0xb8, 0xb5, 0x7f, 0xff, 0x4c, 0x5f, 0xcc, 0x2c, 0x1f, 0xdb,
+ 0x30, 0x2f, 0x2c, 0x5f, 0xde, 0xe4, 0x7b, 0x97, 0x65, 0x8a, 0x58, 0xbf,
+ 0x9c, 0x5d, 0x0f, 0xf3, 0x26, 0xff, 0x46, 0x77, 0x67, 0x61, 0xaa, 0x6c,
+ 0xde, 0x33, 0x40, 0x2e, 0x72, 0x13, 0x36, 0x88, 0xc5, 0xc6, 0xd2, 0x9c,
+ 0x15, 0xbf, 0xd3, 0xbe, 0x7f, 0xef, 0xba, 0xc5, 0x63, 0x76, 0xb4, 0xd5,
+ 0xd7, 0x80, 0x0d, 0x6f, 0xc5, 0x3b, 0xc0, 0xeb, 0x17, 0xff, 0xb2, 0x3f,
+ 0xe2, 0x8b, 0xf9, 0x14, 0x27, 0xa5, 0x8b, 0xf9, 0xb9, 0xd8, 0xf2, 0x6a,
+ 0xc5, 0xff, 0xdc, 0xc8, 0xbf, 0x3d, 0xb3, 0xff, 0x95, 0x8a, 0x1a, 0x3c,
+ 0xb4, 0x52, 0x75, 0x1f, 0x18, 0xdf, 0xe6, 0x07, 0x0e, 0xdd, 0x79, 0x62,
+ 0x96, 0x2f, 0xfb, 0x84, 0x21, 0x7a, 0x12, 0x6a, 0xc5, 0x74, 0x78, 0xfe,
+ 0x0c, 0xac, 0x46, 0xe3, 0x1e, 0x89, 0xf2, 0xff, 0xd9, 0xb6, 0xa6, 0x7c,
+ 0xff, 0x95, 0x8b, 0xff, 0x3c, 0x5c, 0x26, 0x61, 0xfd, 0xd6, 0x2f, 0xe2,
+ 0xce, 0x7e, 0x46, 0xb1, 0x7e, 0x98, 0xf0, 0x47, 0xfd, 0x62, 0xa5, 0x13,
+ 0x58, 0x7d, 0xf2, 0xdb, 0xff, 0xff, 0xe2, 0x9f, 0xe1, 0x63, 0x8c, 0x13,
+ 0xd4, 0x38, 0x6c, 0xc9, 0x6f, 0x83, 0x58, 0xa2, 0x4e, 0x0b, 0x90, 0xd8,
+ 0xf1, 0x75, 0xff, 0x8d, 0x7f, 0x16, 0x43, 0x5c, 0xe2, 0xc5, 0xff, 0x76,
+ 0x1c, 0xf0, 0x5b, 0x0a, 0x25, 0x8b, 0x41, 0xcf, 0xfd, 0x90, 0x2f, 0xfe,
+ 0xc3, 0x8a, 0x0c, 0x33, 0x3c, 0x70, 0x2c, 0x5f, 0xd3, 0x16, 0x76, 0x7d,
+ 0x2c, 0x5f, 0xfe, 0x87, 0xda, 0x1b, 0x93, 0x77, 0x77, 0x77, 0x3a, 0xc5,
+ 0x4a, 0x21, 0x30, 0xc2, 0xf6, 0xb0, 0x96, 0x2f, 0xf6, 0x78, 0xdc, 0x62,
+ 0x02, 0xc5, 0x39, 0xe7, 0xc4, 0x39, 0x52, 0x9c, 0x1f, 0xc9, 0x8a, 0x19,
+ 0x7c, 0x70, 0xbf, 0x74, 0x3f, 0xb8, 0x4b, 0x17, 0xff, 0x08, 0x78, 0x42,
+ 0x83, 0x8f, 0x00, 0xb1, 0x52, 0x7d, 0xee, 0x57, 0x7f, 0xf0, 0x98, 0xfe,
+ 0x2c, 0xd8, 0xb3, 0xa5, 0x8b, 0xfe, 0xcd, 0xe7, 0xef, 0x24, 0x35, 0x8b,
+ 0xff, 0xbf, 0x81, 0x0b, 0x1f, 0xfc, 0x9d, 0x96, 0x2e, 0x71, 0x6c, 0x7f,
+ 0xdd, 0x1c, 0x56, 0xce, 0xb8, 0x54, 0x72, 0x9c, 0x72, 0x18, 0xbb, 0xce,
+ 0x30, 0x45, 0x1b, 0xce, 0xa3, 0x27, 0x39, 0x73, 0x32, 0x82, 0xbb, 0x98,
+ 0x29, 0x41, 0x7c, 0x8e, 0xc3, 0xd2, 0x8d, 0xfb, 0x42, 0xc0, 0x22, 0x0e,
+ 0xe8, 0x61, 0xdf, 0x45, 0x07, 0x89, 0x62, 0xe2, 0xd9, 0x62, 0xf8, 0x1a,
+ 0x68, 0xe5, 0x8a, 0x30, 0xf8, 0xe3, 0x42, 0x5e, 0x86, 0x2f, 0xf1, 0x6d,
+ 0x83, 0x3b, 0xf9, 0x62, 0xff, 0x47, 0xbe, 0xdc, 0x99, 0x89, 0x62, 0xce,
+ 0x23, 0xec, 0x08, 0xd2, 0xf3, 0x99, 0xdf, 0xac, 0x5b, 0xb9, 0x62, 0xef,
+ 0xf7, 0x2c, 0x5f, 0xfe, 0xce, 0xdf, 0x68, 0x01, 0xba, 0x03, 0xf4, 0xb1,
+ 0x52, 0x7d, 0x3f, 0x1b, 0xb6, 0x2c, 0x57, 0x8d, 0x97, 0x62, 0x1b, 0xff,
+ 0xf4, 0xf0, 0xee, 0x5e, 0xe6, 0x3f, 0x8a, 0x4e, 0xb1, 0x7f, 0xd0, 0xe7,
+ 0xf0, 0xf1, 0xef, 0xc5, 0x8b, 0xff, 0xdb, 0x4c, 0x7f, 0x0b, 0x3d, 0xe7,
+ 0xd6, 0xeb, 0x15, 0xd2, 0x23, 0x34, 0x7b, 0x7d, 0xb1, 0xda, 0x0b, 0x17,
+ 0xf6, 0x6d, 0xc2, 0xce, 0xcb, 0x17, 0xfa, 0x4f, 0x31, 0x81, 0x04, 0x12,
+ 0xc5, 0x41, 0x53, 0x23, 0xc2, 0xc3, 0x44, 0x6d, 0x0d, 0xf2, 0x24, 0xf1,
+ 0x27, 0x71, 0x85, 0xff, 0xf9, 0x98, 0x7f, 0x9e, 0xdf, 0x93, 0xc5, 0x1e,
+ 0xe3, 0x58, 0xbb, 0xe1, 0xac, 0x5f, 0xf1, 0xb1, 0xb7, 0xdf, 0x4c, 0xfd,
+ 0x96, 0x2c, 0x6a, 0xc5, 0x4b, 0xb4, 0x82, 0xcb, 0x5c, 0xec, 0xf1, 0xc1,
+ 0xc7, 0xc2, 0x8b, 0xe5, 0x0d, 0x2a, 0x1c, 0x9c, 0x38, 0xb6, 0x21, 0x90,
+ 0xd0, 0x6f, 0xff, 0xd0, 0xce, 0x31, 0x03, 0xf9, 0x3e, 0xe4, 0x81, 0x62,
+ 0xf9, 0x8e, 0xd0, 0x58, 0xbf, 0xd8, 0x58, 0xfa, 0x6e, 0xcb, 0x17, 0xff,
+ 0xec, 0x39, 0xc5, 0xff, 0xb3, 0x1b, 0x9a, 0xcf, 0x2c, 0x5d, 0xf7, 0x31,
+ 0x11, 0x24, 0x67, 0x7b, 0x0f, 0x2b, 0x17, 0xfe, 0x26, 0x19, 0x60, 0xff,
+ 0x3c, 0x58, 0xac, 0x3d, 0x97, 0x1c, 0xbf, 0xdb, 0xe1, 0x67, 0x76, 0x0d,
+ 0x62, 0xf0, 0x73, 0xa5, 0x8b, 0xfd, 0x87, 0x6f, 0xe7, 0x40, 0x58, 0xbf,
+ 0xc7, 0x9d, 0x78, 0xa7, 0x65, 0x8b, 0xfb, 0x8e, 0x4d, 0xa3, 0x56, 0x2b,
+ 0x63, 0xe2, 0x39, 0xa5, 0xfc, 0xfc, 0x6f, 0x0a, 0x56, 0x2f, 0xb7, 0xe8,
+ 0xdd, 0xd6, 0x2f, 0x07, 0x20, 0x58, 0xbd, 0xa9, 0xe2, 0xc5, 0x62, 0x24,
+ 0x1c, 0xb4, 0x05, 0x1e, 0x1e, 0xbe, 0xed, 0x25, 0xba, 0xc5, 0xff, 0xfd,
+ 0x25, 0x80, 0xe6, 0x0f, 0xf3, 0xb1, 0xc4, 0x43, 0x58, 0xbf, 0x74, 0x0e,
+ 0xe0, 0xc2, 0x58, 0xbf, 0xfc, 0xc0, 0x6f, 0xe1, 0xdb, 0xf9, 0xd0, 0x16,
+ 0x2f, 0xff, 0xfe, 0x9c, 0x03, 0x44, 0x3c, 0x6d, 0xff, 0x99, 0x16, 0x37,
+ 0x74, 0x4e, 0xb1, 0x4e, 0x9b, 0x7f, 0xc9, 0x59, 0x6c, 0x8c, 0x04, 0x95,
+ 0x7e, 0x7f, 0x7a, 0x60, 0xb1, 0x74, 0xf4, 0xb1, 0x7c, 0xd0, 0xce, 0xcb,
+ 0x15, 0x05, 0xd9, 0x91, 0xaa, 0x1b, 0x0a, 0xbd, 0xe1, 0x0e, 0xe4, 0x1a,
+ 0x36, 0xf8, 0xf3, 0x42, 0x58, 0xa1, 0x67, 0xe8, 0xea, 0xbb, 0x24, 0x47,
+ 0x14, 0x77, 0x0c, 0x5f, 0xc5, 0xe9, 0xe7, 0x9d, 0x62, 0xff, 0xfc, 0xc5,
+ 0xbf, 0xb9, 0x9b, 0x72, 0x4c, 0x9e, 0xc4, 0xb1, 0x7d, 0xce, 0x39, 0xd6,
+ 0x2f, 0xff, 0xc2, 0xe8, 0x7b, 0x8b, 0x23, 0xe2, 0xc6, 0xee, 0x89, 0xd6,
+ 0x2e, 0x7f, 0x2c, 0x5f, 0xd9, 0xe2, 0x99, 0x3a, 0xc5, 0xf0, 0xff, 0x3d,
+ 0x8e, 0x78, 0x7f, 0x17, 0xbf, 0xfd, 0x83, 0xfc, 0xf6, 0xfb, 0x84, 0x59,
+ 0xba, 0xc5, 0xd3, 0x16, 0x22, 0x20, 0x8e, 0xef, 0xf1, 0x4c, 0x30, 0xf3,
+ 0xba, 0xc5, 0xe1, 0xbe, 0x96, 0x28, 0x67, 0xa1, 0xa3, 0x3b, 0xfb, 0xa1,
+ 0x8f, 0x1b, 0x65, 0x8b, 0xfb, 0x02, 0xd6, 0x7f, 0x8b, 0x17, 0xff, 0xb4,
+ 0xdb, 0xe7, 0x67, 0xd4, 0x73, 0x6d, 0x1c, 0xb1, 0x7f, 0xfe, 0xfb, 0xf6,
+ 0x2c, 0x0b, 0x1f, 0xcf, 0xa6, 0x02, 0xc5, 0xe1, 0x10, 0x16, 0x2e, 0x91,
+ 0xac, 0x53, 0x9b, 0x42, 0x1d, 0xbe, 0x86, 0x7f, 0x16, 0x2f, 0x6c, 0x22,
+ 0x58, 0xb7, 0x0c, 0x4e, 0xfa, 0x48, 0xb6, 0x30, 0x19, 0x7e, 0xea, 0x91,
+ 0x42, 0x29, 0x87, 0xc3, 0x22, 0xbf, 0xfe, 0x19, 0x33, 0x7f, 0xf8, 0xc3,
+ 0xcc, 0x3a, 0xc5, 0xff, 0xf8, 0x7a, 0xcd, 0xff, 0x9f, 0x60, 0x88, 0x42,
+ 0x02, 0xc5, 0x74, 0x99, 0x2c, 0x50, 0x80, 0x24, 0xdb, 0xbb, 0xce, 0xf1,
+ 0x62, 0xf9, 0xd8, 0x86, 0xb1, 0x7f, 0x7d, 0xe2, 0x66, 0xd9, 0x62, 0xf4,
+ 0xe0, 0x16, 0x2d, 0x3d, 0xea, 0x23, 0x86, 0x45, 0xb9, 0x0c, 0x45, 0xf5,
+ 0x2b, 0xc8, 0x58, 0x5a, 0xeb, 0x3a, 0x23, 0x3c, 0x65, 0x6d, 0x2d, 0x80,
+ 0x10, 0xc5, 0xbc, 0x6f, 0x9d, 0x62, 0xf6, 0xc7, 0x95, 0x8a, 0x93, 0x78,
+ 0xe3, 0xd7, 0xf4, 0xeb, 0x69, 0xd6, 0xcb, 0x17, 0xf4, 0x91, 0x9e, 0x83,
+ 0xac, 0x5f, 0xfe, 0x26, 0x0b, 0xf3, 0x07, 0x2c, 0x3c, 0xac, 0x5f, 0xfd,
+ 0x9d, 0x7a, 0x73, 0x5a, 0x99, 0xee, 0x58, 0xb0, 0x51, 0x22, 0x3c, 0x92,
+ 0x2d, 0x12, 0xc5, 0xfe, 0xdb, 0x02, 0x9f, 0x88, 0x96, 0x2a, 0x4f, 0x21,
+ 0xc4, 0xea, 0x09, 0xbf, 0x8c, 0xc3, 0x21, 0x7b, 0xf7, 0x2b, 0xf7, 0xf3,
+ 0x7c, 0x09, 0x62, 0xff, 0xbb, 0x31, 0x03, 0xf8, 0x06, 0x58, 0xbf, 0x39,
+ 0xbe, 0x7d, 0x96, 0x2f, 0xff, 0x66, 0x00, 0xf3, 0x17, 0x07, 0xf6, 0xd9,
+ 0x62, 0x9d, 0x16, 0x1f, 0x3a, 0x22, 0xab, 0xff, 0xbf, 0x27, 0x88, 0xb0,
+ 0x2f, 0x67, 0xd6, 0x2e, 0x16, 0xcb, 0x15, 0x27, 0xbe, 0x34, 0x6b, 0xe8,
+ 0xb3, 0x36, 0x58, 0xbf, 0xff, 0xff, 0xee, 0x30, 0xfa, 0x87, 0x1c, 0x78,
+ 0x7f, 0x67, 0x5f, 0x9e, 0xc6, 0xcf, 0xf0, 0x7f, 0x9e, 0x96, 0x2b, 0x64,
+ 0x5f, 0x70, 0x92, 0xfe, 0x3f, 0xdf, 0xb6, 0x44, 0xb1, 0x7f, 0x37, 0x5f,
+ 0x6c, 0xd2, 0xc5, 0x9f, 0x0f, 0x7d, 0x8c, 0x6f, 0xff, 0x68, 0x47, 0x3b,
+ 0x36, 0xc7, 0x9f, 0x71, 0x62, 0xff, 0xc5, 0x9d, 0x43, 0x9a, 0x9f, 0x71,
+ 0x62, 0xff, 0xef, 0xce, 0x80, 0x3d, 0x61, 0x60, 0x4b, 0x17, 0xf1, 0x7f,
+ 0x01, 0x24, 0xb1, 0x4b, 0x17, 0xe8, 0x6a, 0x70, 0x6b, 0x17, 0x38, 0xba,
+ 0x36, 0x84, 0x19, 0x7f, 0xc2, 0xd7, 0x18, 0x87, 0x80, 0x58, 0xbf, 0xff,
+ 0xd9, 0x0d, 0xfe, 0xff, 0x9c, 0xd4, 0x3c, 0x52, 0x7e, 0x2c, 0x5f, 0xf6,
+ 0x1f, 0x92, 0x76, 0xeb, 0xcb, 0x17, 0xfc, 0xdb, 0x0a, 0x70, 0x85, 0xb2,
+ 0xc5, 0xfe, 0x8b, 0x58, 0xff, 0x91, 0xac, 0x56, 0x22, 0xa3, 0x47, 0x4c,
+ 0x75, 0x4e, 0x9b, 0x87, 0xce, 0x79, 0x18, 0x4d, 0xff, 0xd3, 0xc2, 0xc3,
+ 0x5f, 0xff, 0xc8, 0xf5, 0x8b, 0xfe, 0x17, 0xa3, 0xf9, 0x8e, 0x43, 0x58,
+ 0xbe, 0x14, 0xf4, 0x35, 0x8b, 0xfd, 0x87, 0xc8, 0xa0, 0xf8, 0xb1, 0x52,
+ 0xbd, 0x96, 0x38, 0x6d, 0x6f, 0x08, 0xd7, 0x86, 0xfc, 0x7c, 0x20, 0xf4,
+ 0x4a, 0x74, 0xcf, 0xa0, 0x32, 0x2f, 0x18, 0x3d, 0x1c, 0xe0, 0x8d, 0xbb,
+ 0x23, 0x84, 0x78, 0x19, 0x25, 0xc3, 0x3a, 0xc5, 0xe8, 0xec, 0x3a, 0xc5,
+ 0xf3, 0x1c, 0x33, 0xac, 0x5e, 0x9d, 0x6c, 0xb1, 0x4e, 0x7c, 0x5e, 0x20,
+ 0xee, 0x24, 0xbf, 0x49, 0xcb, 0x06, 0xb1, 0x6e, 0x2c, 0x58, 0x40, 0x37,
+ 0x3e, 0x27, 0xbd, 0xdc, 0xe1, 0x2c, 0x54, 0xb2, 0x49, 0xf2, 0x7c, 0x36,
+ 0x28, 0x77, 0x33, 0xd0, 0x9a, 0xbb, 0x89, 0xed, 0xde, 0xac, 0x5f, 0x63,
+ 0xfc, 0x4b, 0x17, 0xe9, 0x2c, 0xec, 0xcb, 0x16, 0xde, 0x23, 0xca, 0xd1,
+ 0x15, 0xb7, 0x58, 0xad, 0x91, 0x3d, 0xa6, 0x10, 0xca, 0xaf, 0xfe, 0x7d,
+ 0xdb, 0x5b, 0xfd, 0xfb, 0x31, 0xd6, 0x2f, 0xfe, 0xd4, 0xfe, 0x4c, 0x09,
+ 0x88, 0xa5, 0x62, 0xe7, 0xf7, 0x11, 0x18, 0x1a, 0x45, 0xfc, 0x53, 0x9f,
+ 0xc2, 0x58, 0xbf, 0xff, 0xc6, 0xf0, 0x6f, 0x9d, 0x6e, 0xe4, 0xdd, 0x1e,
+ 0x67, 0x8b, 0x15, 0x88, 0x8e, 0x62, 0xbb, 0xff, 0xc7, 0x9d, 0xfd, 0xcc,
+ 0x04, 0xe7, 0x50, 0x58, 0xbe, 0x35, 0xf7, 0x75, 0x8b, 0xa6, 0x18, 0x7e,
+ 0x1e, 0x4c, 0xaf, 0xa2, 0xf4, 0xa1, 0x23, 0x78, 0x79, 0x05, 0x8b, 0xd1,
+ 0xee, 0x12, 0xc5, 0xe3, 0x5f, 0x75, 0x8b, 0xf3, 0xf6, 0x2c, 0xe1, 0x87,
+ 0xbb, 0xf1, 0xdf, 0x10, 0xdd, 0xd1, 0x2c, 0x5f, 0xf7, 0x6c, 0x1c, 0x59,
+ 0x84, 0x6a, 0xc5, 0xff, 0xe8, 0x4f, 0x3f, 0x25, 0xef, 0xc7, 0xb9, 0xd6,
+ 0x28, 0x91, 0x13, 0xe3, 0xcb, 0xfe, 0x99, 0xf7, 0x0b, 0x18, 0x96, 0x2f,
+ 0xfd, 0x27, 0xe3, 0xea, 0x7c, 0xfd, 0x96, 0x2f, 0xd1, 0xef, 0xf6, 0x89,
+ 0x62, 0xa4, 0xfb, 0x3e, 0x81, 0x46, 0xa3, 0x0f, 0xd0, 0xa2, 0xbf, 0xa7,
+ 0x72, 0x6e, 0xbc, 0xb1, 0x7c, 0x42, 0x68, 0x2c, 0x5f, 0xee, 0x6a, 0x76,
+ 0x6d, 0x6e, 0xb1, 0x7d, 0xb4, 0x74, 0x9d, 0x62, 0x9c, 0xf7, 0x43, 0x36,
+ 0xbf, 0xf4, 0xf5, 0xee, 0x08, 0xf9, 0xd7, 0x96, 0x2f, 0xec, 0x35, 0xbc,
+ 0x52, 0xb1, 0x50, 0x56, 0x77, 0x89, 0xaf, 0x0a, 0x18, 0xf8, 0x72, 0x9c,
+ 0xa7, 0x85, 0xfe, 0x7f, 0xec, 0x44, 0x1a, 0x15, 0xfa, 0x7d, 0xb6, 0x04,
+ 0xb1, 0x6e, 0xcb, 0x17, 0xf8, 0x9b, 0x66, 0x83, 0xfd, 0x62, 0xff, 0xfd,
+ 0xbb, 0xe9, 0xf3, 0xb7, 0xf3, 0x09, 0x9b, 0xb2, 0xc5, 0xba, 0xdd, 0x11,
+ 0x5e, 0x33, 0xad, 0x23, 0xcc, 0xe5, 0x42, 0x84, 0xf5, 0xfc, 0xe2, 0xdb,
+ 0x93, 0x05, 0x8b, 0xf8, 0x98, 0x23, 0x36, 0x1a, 0xc5, 0xe7, 0x07, 0x16,
+ 0x2f, 0xb3, 0x6e, 0xde, 0x58, 0xac, 0x3c, 0x31, 0x0e, 0xdf, 0xfd, 0xc6,
+ 0xeb, 0xde, 0xcd, 0xc6, 0x2d, 0x96, 0x2d, 0x9b, 0x9f, 0x57, 0x88, 0x6f,
+ 0xff, 0x19, 0x90, 0x21, 0x37, 0x3f, 0x80, 0x65, 0x8b, 0xff, 0x7b, 0x81,
+ 0xf2, 0x4b, 0x66, 0x82, 0xc5, 0x41, 0x11, 0x78, 0x95, 0x7e, 0x1e, 0xe2,
+ 0xc8, 0xf5, 0x8b, 0xfd, 0xd7, 0xe5, 0xc9, 0x86, 0xb1, 0x77, 0x47, 0x58,
+ 0xb1, 0x49, 0xe6, 0x61, 0x9d, 0x44, 0x89, 0xe3, 0xbc, 0xdf, 0x73, 0x08,
+ 0xd5, 0x8b, 0xe9, 0xc8, 0x32, 0xc5, 0x74, 0x78, 0x9f, 0x23, 0xbf, 0xff,
+ 0xb7, 0xfb, 0x47, 0x99, 0x83, 0x37, 0x1f, 0x45, 0x9d, 0x96, 0x2f, 0xff,
+ 0xf7, 0xf3, 0xd1, 0xd8, 0x4f, 0x3d, 0x16, 0x76, 0x9c, 0x09, 0x62, 0xff,
+ 0xfc, 0x2d, 0x37, 0x24, 0x5d, 0xfc, 0xff, 0x18, 0xb7, 0x58, 0xae, 0x22,
+ 0xfb, 0xcc, 0x97, 0xc0, 0x8d, 0x3b, 0xde, 0xf1, 0x62, 0x9c, 0xf5, 0xb4,
+ 0x47, 0x52, 0xa8, 0x88, 0x6d, 0x18, 0x46, 0xd1, 0xbb, 0x5f, 0xe1, 0xf6,
+ 0x92, 0xf6, 0x01, 0x62, 0xfd, 0x3e, 0xfc, 0xf9, 0x62, 0xe2, 0x02, 0xc5,
+ 0x6c, 0x7e, 0x9a, 0x35, 0x62, 0x8b, 0xfc, 0xdd, 0x73, 0x59, 0xfe, 0x2c,
+ 0x52, 0xc5, 0xfc, 0x2e, 0xa2, 0x72, 0xc5, 0x8b, 0xff, 0xff, 0xc2, 0xd7,
+ 0xf2, 0x28, 0x9b, 0x51, 0x7b, 0xe2, 0x07, 0x31, 0xfb, 0x0e, 0x56, 0x2f,
+ 0xf9, 0xff, 0xcd, 0x39, 0x49, 0xd6, 0x2f, 0xdc, 0x88, 0xb2, 0x25, 0x8b,
+ 0xfe, 0x68, 0x8b, 0x07, 0xf9, 0xe2, 0xc5, 0x49, 0xf1, 0xe1, 0x55, 0x3a,
+ 0x67, 0x31, 0xef, 0xdf, 0x84, 0xdd, 0xfb, 0xdf, 0x62, 0x35, 0x62, 0xff,
+ 0x77, 0x10, 0x85, 0xbb, 0x9a, 0xb1, 0x6f, 0x2c, 0x52, 0xc5, 0xf3, 0x84,
+ 0x76, 0xe8, 0xbe, 0xf0, 0x95, 0xfe, 0x16, 0xc3, 0xfe, 0x14, 0xac, 0x54,
+ 0xa3, 0x0f, 0x75, 0x72, 0x38, 0xbf, 0xcf, 0x81, 0x45, 0x07, 0x25, 0x8b,
+ 0xff, 0xe9, 0x3c, 0x7b, 0xcc, 0x96, 0xb1, 0xcf, 0x8b, 0x17, 0xff, 0x60,
+ 0xff, 0x21, 0x75, 0x0f, 0x08, 0x6b, 0x17, 0xf0, 0x31, 0xcf, 0x31, 0xeb,
+ 0x17, 0xe0, 0xb0, 0xef, 0xe5, 0x8b, 0xff, 0x81, 0xf7, 0x17, 0xb9, 0xf1,
+ 0x67, 0x96, 0x2e, 0xce, 0x2c, 0x5c, 0xde, 0x58, 0xb4, 0x34, 0x6b, 0xbe,
+ 0x2f, 0x52, 0x8c, 0x46, 0x29, 0x13, 0xa5, 0x62, 0x64, 0x5c, 0x87, 0xa5,
+ 0x6c, 0xb9, 0xa0, 0x38, 0xda, 0x30, 0xe3, 0x78, 0x76, 0x47, 0x97, 0xc4,
+ 0x68, 0x49, 0xfe, 0x8d, 0xaa, 0xbb, 0xc5, 0xd6, 0x5c, 0x9c, 0xdc, 0xbf,
+ 0xfd, 0x9a, 0x8d, 0xb9, 0xe2, 0x7e, 0xb8, 0x67, 0x96, 0x2f, 0xff, 0xd9,
+ 0x1e, 0xc4, 0x0d, 0xb0, 0x20, 0x98, 0x8a, 0x56, 0x2f, 0xff, 0x64, 0x96,
+ 0x6e, 0x59, 0xe1, 0x30, 0x4b, 0x17, 0xff, 0x17, 0xf2, 0x7a, 0x67, 0xe0,
+ 0x66, 0xac, 0x5f, 0xf8, 0x7f, 0x9d, 0x16, 0x76, 0x6f, 0x2c, 0x5f, 0x7e,
+ 0x3d, 0xce, 0xb1, 0x7a, 0x0f, 0xe3, 0x0f, 0x9b, 0x10, 0x2a, 0x51, 0xbf,
+ 0x14, 0x2b, 0x2f, 0xff, 0xb6, 0x62, 0xf7, 0x04, 0x5e, 0xf7, 0xd8, 0x6b,
+ 0x17, 0xfd, 0x80, 0x8e, 0xc6, 0x1e, 0x71, 0x62, 0xff, 0xe7, 0xf7, 0xf1,
+ 0xe1, 0xcc, 0xeb, 0xcb, 0x15, 0x05, 0x4f, 0x23, 0x58, 0xc8, 0xca, 0x18,
+ 0xa0, 0x94, 0x78, 0x77, 0x7f, 0x14, 0xc3, 0xfc, 0x02, 0xc5, 0xff, 0x00,
+ 0xb3, 0xdc, 0x66, 0x25, 0x8b, 0xff, 0x85, 0x91, 0x63, 0xee, 0x59, 0xfc,
+ 0x58, 0xb0, 0x06, 0x8a, 0x9d, 0xcb, 0x88, 0xde, 0xf1, 0xdb, 0xa5, 0x8b,
+ 0xff, 0xfa, 0x0e, 0x3c, 0xfe, 0x6d, 0x30, 0x7e, 0x73, 0x23, 0xd6, 0x2b,
+ 0x48, 0xb2, 0x01, 0xb7, 0x87, 0xaf, 0xf8, 0x58, 0xff, 0xe1, 0xdf, 0x8b,
+ 0x17, 0x08, 0xd5, 0x8b, 0xfd, 0x9f, 0x1f, 0xe4, 0xb6, 0x58, 0xb0, 0xfe,
+ 0x79, 0xa1, 0x0c, 0xdf, 0x7f, 0x06, 0xeb, 0x15, 0x27, 0x97, 0xc2, 0x9a,
+ 0x96, 0xe2, 0x92, 0x10, 0xbe, 0x1c, 0x6f, 0x59, 0x2e, 0xfd, 0xe3, 0x81,
+ 0x8f, 0x35, 0x88, 0xbf, 0x50, 0xde, 0x3c, 0x2c, 0xff, 0x2b, 0x89, 0xa1,
+ 0x6c, 0x02, 0xf2, 0x9d, 0x9a, 0xe1, 0x97, 0xa5, 0x65, 0x8a, 0x3b, 0x70,
+ 0x8c, 0x03, 0x86, 0x8d, 0xfe, 0xc1, 0xed, 0xa1, 0x48, 0x16, 0x2f, 0xff,
+ 0x80, 0xdf, 0xc0, 0x01, 0xb5, 0x9d, 0xbf, 0x8b, 0x17, 0xff, 0xef, 0x70,
+ 0x84, 0x2e, 0xa1, 0xc1, 0xff, 0x1f, 0xcb, 0x15, 0xa4, 0x6f, 0x1c, 0xd4,
+ 0x94, 0x6f, 0xe8, 0x6b, 0x52, 0x7e, 0x2c, 0x54, 0x9e, 0xf7, 0x45, 0xf7,
+ 0xfa, 0x7d, 0xc1, 0xfe, 0x49, 0x62, 0xff, 0xa1, 0x9e, 0x7e, 0xa0, 0x52,
+ 0xb1, 0x78, 0x9c, 0x63, 0x3e, 0xcf, 0x19, 0xd8, 0xeb, 0x17, 0xe0, 0x39,
+ 0x43, 0x8b, 0x15, 0xd1, 0xba, 0xf0, 0x95, 0x62, 0x23, 0x9d, 0xb2, 0xfd,
+ 0x13, 0xfd, 0xce, 0xb1, 0x7f, 0x7b, 0x9f, 0x96, 0xd2, 0xc5, 0x7c, 0xf5,
+ 0xc8, 0xa6, 0xe0, 0x71, 0x62, 0xfb, 0x72, 0x17, 0x16, 0x2f, 0xf8, 0x78,
+ 0x72, 0xcf, 0x7d, 0xd6, 0x2f, 0x6a, 0x46, 0xb1, 0x7e, 0x29, 0xdd, 0x99,
+ 0x62, 0xec, 0xe1, 0xa7, 0x89, 0xe1, 0xdb, 0xe0, 0xb3, 0xdc, 0x58, 0xbc,
+ 0x6b, 0xfd, 0x62, 0xfc, 0x2d, 0x02, 0x37, 0xef, 0xb5, 0x8a, 0xc4, 0xd1,
+ 0x9c, 0x93, 0xef, 0x8c, 0x5c, 0x02, 0x4e, 0x0f, 0x56, 0x27, 0xa8, 0xe4,
+ 0x3f, 0x8d, 0x7a, 0xff, 0x6b, 0x06, 0x67, 0x3f, 0x2b, 0x17, 0xdc, 0x29,
+ 0xd9, 0x62, 0xff, 0xbc, 0x23, 0x33, 0x37, 0xc9, 0x58, 0xad, 0x1e, 0xe9,
+ 0x11, 0xdf, 0xff, 0xbb, 0x8b, 0x3b, 0x37, 0x1f, 0x0b, 0xf1, 0xee, 0x75,
+ 0x8b, 0x43, 0x0f, 0xf1, 0xc8, 0x6f, 0x4e, 0x12, 0xc5, 0xd2, 0x4b, 0x15,
+ 0xa3, 0x62, 0x71, 0xbb, 0xe3, 0x75, 0x27, 0x58, 0xbf, 0x4c, 0x59, 0x9b,
+ 0xac, 0x5e, 0x8d, 0xe3, 0x68, 0xdd, 0x62, 0xec, 0x09, 0x62, 0xff, 0x0d,
+ 0x9c, 0x62, 0xf7, 0x16, 0x2b, 0x63, 0xcc, 0xc1, 0x8b, 0xb3, 0x65, 0x8a,
+ 0x31, 0x32, 0x19, 0x21, 0xd8, 0x90, 0xd2, 0x90, 0x9e, 0x63, 0x88, 0xaf,
+ 0xf9, 0xc8, 0xb0, 0x7f, 0x9e, 0xcb, 0x17, 0xf8, 0x5c, 0xfb, 0x40, 0x6e,
+ 0xb1, 0x7f, 0xff, 0xfe, 0x92, 0xdb, 0xdc, 0xc0, 0xbf, 0x3d, 0xbc, 0x53,
+ 0xd7, 0xf1, 0x87, 0x98, 0x75, 0x8b, 0xfc, 0xe5, 0xe8, 0x66, 0xb1, 0x62,
+ 0xff, 0x0d, 0xa1, 0xee, 0x30, 0x16, 0x2f, 0x3c, 0x9d, 0x62, 0xff, 0xb1,
+ 0xb5, 0xdb, 0xd8, 0xfb, 0xac, 0x5d, 0x3b, 0xe2, 0x22, 0xf4, 0x68, 0x43,
+ 0x95, 0xb2, 0x6f, 0x90, 0x84, 0x29, 0x42, 0xf6, 0xff, 0xf1, 0xf0, 0x7e,
+ 0xf8, 0x80, 0x6e, 0x17, 0x96, 0x2f, 0xf3, 0x31, 0xb9, 0xac, 0xf2, 0xc5,
+ 0xfd, 0xaf, 0xb1, 0xdf, 0x8b, 0x17, 0xef, 0xfd, 0xb6, 0x9f, 0x9f, 0x08,
+ 0x66, 0x77, 0xfe, 0x6d, 0x67, 0x6c, 0x71, 0xfd, 0xd6, 0x2b, 0x0f, 0xfc,
+ 0x08, 0x17, 0xff, 0xf7, 0x1f, 0x9c, 0x93, 0x30, 0x6d, 0x01, 0xeb, 0x0e,
+ 0xb1, 0x58, 0x9d, 0x49, 0xe3, 0x2c, 0xf1, 0x0d, 0xff, 0x98, 0x1a, 0x92,
+ 0xf7, 0xf2, 0x0b, 0x17, 0xff, 0x81, 0x8e, 0x5e, 0xc3, 0xb7, 0x80, 0xcb,
+ 0x15, 0x2a, 0xa8, 0x32, 0x3e, 0x47, 0x36, 0x11, 0xf5, 0xfd, 0xf6, 0x2d,
+ 0xb0, 0x6b, 0x17, 0xb3, 0xec, 0xb1, 0x7f, 0xee, 0x0f, 0xf3, 0x14, 0x1f,
+ 0x50, 0x58, 0xbc, 0x21, 0x12, 0xc5, 0xf9, 0xff, 0xfc, 0x1a, 0xc5, 0x2c,
+ 0x0c, 0xf1, 0x78, 0x3b, 0x5d, 0x22, 0xc2, 0x28, 0x43, 0x5f, 0xfc, 0x53,
+ 0x20, 0xe6, 0x47, 0xe8, 0x5d, 0x96, 0x28, 0xc4, 0xdb, 0x46, 0x5c, 0xd0,
+ 0xcc, 0x01, 0x55, 0xff, 0xb2, 0x1f, 0x68, 0x19, 0xe8, 0x3a, 0xc5, 0xf8,
+ 0xb0, 0x02, 0xe2, 0xc5, 0xfe, 0x9f, 0x7f, 0x1c, 0x99, 0x62, 0xb6, 0x3d,
+ 0x9d, 0x14, 0x5f, 0x30, 0xf3, 0x8b, 0x17, 0xd9, 0xb0, 0x70, 0x58, 0xb8,
+ 0x11, 0xd8, 0x78, 0xe4, 0x45, 0x7a, 0x3d, 0xce, 0xb1, 0x7f, 0xc0, 0xf6,
+ 0x38, 0xf0, 0xa2, 0x58, 0xf9, 0xa0, 0xbe, 0x26, 0xd1, 0xab, 0x17, 0x98,
+ 0x1c, 0x93, 0xec, 0x74, 0x9a, 0x94, 0xd5, 0xb1, 0xa9, 0xa1, 0x77, 0x7f,
+ 0xa1, 0xef, 0xe6, 0xa7, 0xcb, 0x17, 0xf0, 0x59, 0xbe, 0xf8, 0x12, 0xc5,
+ 0xdd, 0xef, 0x78, 0xb1, 0x76, 0xfd, 0x96, 0x2c, 0x05, 0x8b, 0xff, 0xd0,
+ 0xe6, 0x6a, 0x78, 0x58, 0x01, 0x71, 0x62, 0xb0, 0xf7, 0x18, 0x4a, 0xa3,
+ 0x44, 0x5c, 0xc9, 0x17, 0xdd, 0xeb, 0x13, 0x1f, 0xf4, 0x3a, 0xef, 0xff,
+ 0xd9, 0x3f, 0x9e, 0xdf, 0x98, 0xf3, 0x1b, 0xcc, 0x6a, 0xc5, 0xff, 0xec,
+ 0xee, 0x01, 0xe6, 0x2f, 0x38, 0xb5, 0xc5, 0x8b, 0xfb, 0x30, 0xbd, 0x1d,
+ 0x8b, 0x17, 0xbe, 0xfa, 0x58, 0xa3, 0x9e, 0x67, 0x7e, 0x5f, 0x7f, 0xf7,
+ 0x3d, 0x33, 0xa0, 0x44, 0x58, 0x12, 0xc5, 0xf0, 0x00, 0xc3, 0x58, 0xbb,
+ 0x3a, 0x58, 0xb7, 0xf0, 0xdd, 0xb9, 0x1d, 0x74, 0x8c, 0xd6, 0x27, 0x04,
+ 0x20, 0x6f, 0x1b, 0x01, 0x2c, 0x58, 0xeb, 0x17, 0x37, 0x96, 0x2f, 0x7e,
+ 0x75, 0xb1, 0xa9, 0x38, 0x95, 0xfe, 0x13, 0x17, 0xf1, 0xa2, 0x58, 0xb7,
+ 0x51, 0x1f, 0x30, 0x46, 0x74, 0xe8, 0xd9, 0x68, 0x57, 0x54, 0xae, 0x39,
+ 0x64, 0x6a, 0x66, 0x94, 0x3a, 0xdb, 0x46, 0xd0, 0x51, 0x87, 0x5f, 0xf3,
+ 0x77, 0x6b, 0x08, 0x9a, 0x25, 0x8b, 0xbe, 0x75, 0x8a, 0x96, 0xd1, 0x2e,
+ 0x11, 0x8e, 0x64, 0xa4, 0xc3, 0x4d, 0x7a, 0x8c, 0x39, 0xe3, 0x78, 0x8f,
+ 0x5e, 0xd1, 0xcf, 0xe7, 0x14, 0x1a, 0x3a, 0xf0, 0x21, 0x94, 0x7d, 0xfc,
+ 0x9c, 0xa5, 0x13, 0x40, 0x47, 0x77, 0xda, 0xcf, 0xf1, 0x62, 0xff, 0xfb,
+ 0x08, 0x5b, 0x1f, 0x3d, 0xcf, 0xc7, 0xb9, 0xd6, 0x2f, 0xdf, 0x93, 0xc8,
+ 0x16, 0x2c, 0x4b, 0x14, 0xe6, 0xe4, 0x45, 0x17, 0xdd, 0x72, 0x7a, 0x58,
+ 0xa8, 0xd9, 0x1e, 0xb2, 0x47, 0xdf, 0xc2, 0x34, 0x88, 0x2f, 0xff, 0x7d,
+ 0xc4, 0x5b, 0x60, 0xe2, 0x10, 0xb4, 0xb1, 0x7a, 0x37, 0xef, 0x23, 0x75,
+ 0x8b, 0xbb, 0x47, 0xac, 0x58, 0x71, 0xb9, 0xe5, 0x04, 0x5b, 0x7e, 0x89,
+ 0xf6, 0xce, 0x96, 0x2f, 0x68, 0x50, 0x58, 0xae, 0x8f, 0x27, 0xc5, 0x77,
+ 0xf1, 0x9e, 0x29, 0x3f, 0x16, 0x2f, 0xb3, 0x98, 0x12, 0xc5, 0x41, 0x38,
+ 0x3c, 0x84, 0xbb, 0xbb, 0xb1, 0x19, 0x17, 0xd2, 0xc5, 0xf6, 0x0d, 0xa0,
+ 0xb1, 0x7c, 0xda, 0xd6, 0x47, 0x9a, 0xe0, 0xc3, 0x2f, 0x16, 0x01, 0x62,
+ 0xd2, 0xb1, 0x40, 0x35, 0xbe, 0x1c, 0xb9, 0xbc, 0xb1, 0x5a, 0x37, 0x1f,
+ 0x21, 0xbd, 0x3a, 0xe2, 0xc5, 0xe0, 0x4f, 0x4b, 0x14, 0x73, 0x76, 0x01,
+ 0xdb, 0x83, 0xd2, 0xc5, 0xf3, 0xf1, 0xfb, 0x2c, 0x5f, 0xe2, 0xc1, 0xfc,
+ 0x5d, 0x79, 0x62, 0xb6, 0x3d, 0x93, 0x49, 0x2f, 0xf4, 0x9c, 0xb0, 0x02,
+ 0xe2, 0xc5, 0xff, 0x6b, 0x3f, 0x9b, 0x18, 0xfc, 0x58, 0xac, 0x4e, 0x05,
+ 0xd7, 0x3e, 0x42, 0xce, 0x44, 0x48, 0x23, 0x3b, 0xfd, 0x07, 0xe7, 0x27,
+ 0x50, 0x58, 0xbe, 0x63, 0xcb, 0xac, 0x5f, 0xc3, 0xfb, 0x43, 0x38, 0xb1,
+ 0x7b, 0xce, 0x12, 0xc5, 0x0d, 0x14, 0x31, 0x1a, 0x00, 0x84, 0x22, 0xeb,
+ 0xff, 0xa2, 0xfb, 0x1c, 0xb3, 0xb1, 0x67, 0x16, 0x2f, 0xe7, 0x21, 0x43,
+ 0x38, 0xb1, 0x7a, 0x1e, 0x75, 0x8b, 0xff, 0xf4, 0x1f, 0xdc, 0xdf, 0xef,
+ 0xee, 0xa0, 0xfe, 0xe2, 0xc5, 0xfe, 0xc1, 0xcf, 0x50, 0xcf, 0x2c, 0x5e,
+ 0xe4, 0x3a, 0x58, 0xbb, 0x36, 0x58, 0xbf, 0x48, 0x0e, 0xd0, 0x30, 0xdb,
+ 0xe8, 0x7e, 0xf6, 0xd9, 0xdc, 0xb1, 0x7f, 0x4e, 0x7b, 0x8d, 0xd2, 0xc5,
+ 0xff, 0x7a, 0x7a, 0x03, 0x7f, 0xee, 0xb1, 0x7c, 0xf1, 0xd9, 0xb2, 0xc5,
+ 0x61, 0xf0, 0x78, 0xea, 0xc7, 0x58, 0xbf, 0x10, 0xa1, 0x9c, 0x30, 0xd9,
+ 0xf6, 0x21, 0xbc, 0x13, 0x6c, 0xb1, 0x4e, 0x7b, 0xff, 0x40, 0xa9, 0x56,
+ 0x67, 0x87, 0xe6, 0xa3, 0x74, 0x5b, 0x10, 0xe9, 0xd6, 0x7e, 0xd6, 0x47,
+ 0xdc, 0x21, 0xf4, 0x64, 0x17, 0xdf, 0x16, 0x79, 0x62, 0xff, 0xc2, 0xea,
+ 0x1c, 0xfe, 0x6c, 0x22, 0x58, 0xbf, 0xc6, 0x6a, 0x3d, 0xc1, 0x83, 0x58,
+ 0xbd, 0x98, 0x35, 0x8b, 0x9b, 0x75, 0x8b, 0xf1, 0xb8, 0x2d, 0x6c, 0xb1,
+ 0x4c, 0x78, 0x62, 0x18, 0xa7, 0x4c, 0x77, 0x44, 0x67, 0x42, 0xf1, 0xc7,
+ 0x72, 0xfd, 0xa3, 0x23, 0x78, 0x77, 0x91, 0xf7, 0x8e, 0xfd, 0xec, 0x31,
+ 0xa3, 0x48, 0xc8, 0x63, 0x67, 0xde, 0xf9, 0x08, 0x2e, 0xfa, 0x96, 0xc6,
+ 0xb3, 0x99, 0x9f, 0x36, 0xda, 0x57, 0x14, 0x23, 0xfb, 0x1d, 0x33, 0xd7,
+ 0x2b, 0xbb, 0xd3, 0x67, 0x7e, 0x37, 0xa4, 0x9d, 0x75, 0x28, 0x3d, 0xe5,
+ 0x44, 0xc7, 0xc2, 0x1e, 0x2a, 0x4a, 0xa6, 0xa9, 0x10, 0x27, 0x95, 0xe9,
+ 0xfb, 0x6f, 0x62, 0xd3, 0xc8, 0xc0, 0x9f, 0x18, 0xef, 0xe1, 0x62, 0x54,
+ 0xac, 0x5e, 0x57, 0x35, 0x7e, 0xad, 0xb2, 0x05, 0x1f, 0xe7, 0x68, 0xf3,
+ 0x42, 0x7a, 0x8e, 0x94, 0x42, 0x1c, 0xe1, 0x47, 0x74, 0x76, 0x17, 0x73,
+ 0xeb, 0x17, 0xbb, 0x3c, 0xac, 0x5a, 0x32, 0x4d, 0xb0, 0xc6, 0x2f, 0xfa,
+ 0x33, 0x9a, 0x91, 0x78, 0x47, 0x58, 0xbf, 0xfd, 0x0e, 0x46, 0x07, 0x9a,
+ 0xfb, 0xc5, 0x03, 0xac, 0x54, 0x11, 0x1f, 0xd1, 0xf5, 0x69, 0x1b, 0x8d,
+ 0x0b, 0x8b, 0xfb, 0xb9, 0xc6, 0x53, 0x12, 0xc5, 0xe9, 0x62, 0x58, 0xbe,
+ 0xcf, 0xb7, 0x96, 0x2d, 0xde, 0xe1, 0xf7, 0x7c, 0xc4, 0x86, 0xef, 0xee,
+ 0xf9, 0x1a, 0x37, 0xb3, 0xb9, 0x62, 0xee, 0xff, 0xeb, 0x17, 0xff, 0x49,
+ 0xca, 0x4c, 0x8a, 0x13, 0xad, 0x96, 0x2f, 0xff, 0x4e, 0x85, 0x14, 0x4f,
+ 0xf7, 0x3b, 0x0d, 0x62, 0xfe, 0xc3, 0x99, 0x11, 0x44, 0xb1, 0x7f, 0x48,
+ 0x39, 0x3a, 0x1a, 0xc5, 0xf9, 0xbd, 0xc9, 0x8f, 0x58, 0xa1, 0xa2, 0x2b,
+ 0xe6, 0x24, 0x5d, 0x7f, 0xb8, 0xe7, 0x9d, 0xf0, 0xeb, 0x17, 0xe0, 0xfb,
+ 0xa4, 0x80, 0xb1, 0x7f, 0x69, 0x81, 0xcd, 0x4a, 0xc5, 0x7c, 0xf6, 0xb8,
+ 0x59, 0x7d, 0x00, 0xc2, 0xc5, 0x8b, 0xff, 0xff, 0x17, 0xb9, 0x2f, 0x0c,
+ 0xee, 0x2f, 0x4f, 0xe4, 0xd1, 0x4f, 0x72, 0xc5, 0xee, 0xe1, 0xca, 0xc5,
+ 0x62, 0x2d, 0x98, 0x94, 0x4e, 0x37, 0xe1, 0x7a, 0x29, 0x35, 0x62, 0xff,
+ 0xa7, 0x6e, 0x44, 0xe7, 0x68, 0x96, 0x28, 0x6a, 0xd1, 0xf7, 0x47, 0x78,
+ 0x6b, 0x47, 0x97, 0xc5, 0x08, 0xef, 0xc3, 0x60, 0x8b, 0xbb, 0x8a, 0xef,
+ 0xff, 0xfe, 0xce, 0xe2, 0x6d, 0xfb, 0xa3, 0x38, 0xe1, 0x16, 0x70, 0xc6,
+ 0xf0, 0xa5, 0x62, 0xdf, 0x58, 0xb3, 0xac, 0x51, 0xa6, 0x8c, 0x02, 0x55,
+ 0xa4, 0x60, 0xf2, 0x13, 0xf7, 0xff, 0xff, 0x83, 0x32, 0x5f, 0xf3, 0xdd,
+ 0x27, 0x8f, 0x7f, 0xe0, 0x38, 0x61, 0x9f, 0x8e, 0x58, 0xbf, 0xb7, 0x6d,
+ 0x6d, 0x81, 0x2c, 0x56, 0x23, 0x7b, 0xa2, 0x87, 0x84, 0x2d, 0xf4, 0x5e,
+ 0x61, 0xac, 0x5f, 0xd2, 0xdb, 0x6c, 0x19, 0xd6, 0x29, 0x8f, 0x54, 0x89,
+ 0x2f, 0xff, 0xdf, 0xc2, 0xc3, 0x7e, 0xd0, 0xf8, 0x4c, 0x19, 0xd6, 0x2d,
+ 0xd2, 0xc5, 0xff, 0x4b, 0xf3, 0x1f, 0xf3, 0xe5, 0x8a, 0x81, 0xe5, 0x7c,
+ 0x4e, 0xfe, 0x87, 0xf3, 0xdf, 0x75, 0x8b, 0xed, 0xd9, 0xb7, 0x54, 0x9a,
+ 0xc5, 0xfe, 0x7d, 0xf3, 0x50, 0x6f, 0xac, 0x5f, 0xfa, 0x3f, 0x8e, 0x7e,
+ 0x7e, 0x4b, 0xcb, 0x17, 0xe6, 0xf1, 0x30, 0x16, 0x2f, 0x9f, 0x5f, 0x63,
+ 0x11, 0x3b, 0x86, 0x9c, 0x42, 0xbf, 0xe6, 0x3f, 0x1f, 0x3b, 0x36, 0x96,
+ 0x2f, 0x9f, 0x51, 0xe3, 0x58, 0xa8, 0x2a, 0x66, 0x78, 0x51, 0x47, 0x91,
+ 0x68, 0xbb, 0xf0, 0xce, 0x24, 0x6e, 0xc7, 0x57, 0xec, 0x83, 0xfc, 0x4b,
+ 0x17, 0xf3, 0x46, 0x3e, 0xde, 0x02, 0xc5, 0xc7, 0xec, 0xb1, 0x44, 0x79,
+ 0x82, 0x32, 0xbe, 0x18, 0x9b, 0x65, 0x8b, 0xfc, 0x27, 0xfe, 0xcc, 0x43,
+ 0x58, 0xa9, 0x3d, 0x88, 0x12, 0x5d, 0xe9, 0x58, 0xbf, 0xf1, 0x36, 0xa6,
+ 0x23, 0x33, 0x4e, 0xb1, 0x7f, 0xfe, 0xe1, 0x4c, 0x5a, 0x70, 0x4b, 0xf7,
+ 0x0f, 0x38, 0xb1, 0x7f, 0x39, 0xda, 0x2c, 0xfa, 0xc5, 0xf9, 0xb9, 0xc9,
+ 0x3a, 0xc5, 0x74, 0x98, 0x23, 0x8b, 0xc4, 0x7e, 0x75, 0x8f, 0x97, 0x5f,
+ 0x67, 0x71, 0x79, 0x62, 0xe9, 0x09, 0x62, 0x80, 0x6f, 0x42, 0x25, 0xbf,
+ 0xc2, 0x2c, 0xee, 0x70, 0x9d, 0x62, 0xfb, 0x8c, 0x5b, 0xac, 0x57, 0xcf,
+ 0x67, 0xb8, 0xda, 0xff, 0x17, 0x9c, 0xd2, 0x63, 0xac, 0x5f, 0xd2, 0x40,
+ 0xee, 0xcd, 0x96, 0x29, 0x8f, 0x90, 0x23, 0x3b, 0xe6, 0xee, 0x9d, 0x2c,
+ 0x57, 0xcf, 0x1c, 0x22, 0x2b, 0xa7, 0xcb, 0x15, 0x29, 0xc2, 0xe3, 0xdb,
+ 0xc3, 0x42, 0x22, 0x3b, 0xfe, 0xed, 0x25, 0xe8, 0xc0, 0xb3, 0xeb, 0x17,
+ 0x49, 0xd6, 0x2b, 0x0f, 0x5b, 0x47, 0xf7, 0xf7, 0xf3, 0x93, 0xb7, 0x72,
+ 0xc5, 0xff, 0xe1, 0xc9, 0xca, 0x4c, 0x8a, 0x13, 0xad, 0x96, 0x2e, 0x00,
+ 0xd6, 0x2f, 0xb7, 0x66, 0xdd, 0x52, 0x41, 0x97, 0xff, 0xbf, 0x3f, 0x73,
+ 0x73, 0x7f, 0xc9, 0x32, 0xc5, 0x68, 0xfe, 0xf8, 0x63, 0x7d, 0x9b, 0xe7,
+ 0x4b, 0x17, 0x42, 0x32, 0x53, 0x26, 0x1a, 0x6e, 0x42, 0x4f, 0xe4, 0x57,
+ 0xfd, 0xef, 0xe4, 0x3e, 0xc4, 0x35, 0x8b, 0xfd, 0x14, 0x9b, 0x1e, 0xc1,
+ 0x79, 0x62, 0x88, 0xfc, 0xfc, 0x73, 0x58, 0xa8, 0xf1, 0xa3, 0x58, 0x14,
+ 0x30, 0xef, 0x9f, 0x6c, 0xd2, 0xc5, 0xff, 0xc0, 0x0f, 0xe1, 0x07, 0xe0,
+ 0xfb, 0x98, 0x0b, 0x17, 0xfb, 0xb9, 0x81, 0x19, 0x3c, 0x09, 0x62, 0xba,
+ 0x45, 0x66, 0x88, 0xfe, 0x9d, 0x7a, 0x29, 0xf2, 0xc5, 0xf3, 0xfa, 0x78,
+ 0xb1, 0x7c, 0x2f, 0x4f, 0x16, 0x2e, 0xee, 0x95, 0x8a, 0x94, 0x57, 0x61,
+ 0x8f, 0xc7, 0x88, 0x88, 0x44, 0x76, 0xdd, 0x62, 0xfe, 0xf3, 0x8f, 0x0a,
+ 0x0b, 0x17, 0xfc, 0x39, 0xd6, 0xc2, 0x33, 0x90, 0x58, 0xbe, 0x1f, 0xf0,
+ 0x25, 0x8a, 0xc3, 0xe1, 0x73, 0xdb, 0xda, 0xcf, 0x2c, 0x5f, 0xec, 0xfe,
+ 0x7b, 0xec, 0x75, 0x8b, 0xfb, 0x0b, 0x76, 0x20, 0x2c, 0x51, 0x89, 0x9f,
+ 0x60, 0x9e, 0xf0, 0x8e, 0x62, 0x02, 0x1d, 0xe1, 0x9d, 0xc0, 0x75, 0x8b,
+ 0xc6, 0xcf, 0x16, 0x2f, 0xf7, 0x8b, 0x00, 0xc4, 0x05, 0x8b, 0xcc, 0x5b,
+ 0xe1, 0xe8, 0x06, 0x3d, 0x46, 0xa2, 0x68, 0x4c, 0xf7, 0xfa, 0x13, 0xad,
+ 0xa7, 0x5b, 0x2c, 0x5f, 0xee, 0xa1, 0x39, 0xe3, 0x31, 0x62, 0xf6, 0xf3,
+ 0xba, 0xc5, 0x4a, 0x22, 0xb0, 0xd9, 0x8d, 0x6f, 0xc7, 0xce, 0xe2, 0x02,
+ 0xc5, 0xec, 0x3b, 0xac, 0x5f, 0xfe, 0x7e, 0x6c, 0x1f, 0x9c, 0x85, 0x0c,
+ 0xe2, 0xc5, 0xe7, 0x34, 0xeb, 0x17, 0xfa, 0x77, 0xf1, 0x4e, 0x74, 0xb1,
+ 0x43, 0x44, 0xf6, 0x93, 0x0e, 0x3d, 0x7b, 0xd9, 0xf5, 0x8b, 0xf8, 0xbd,
+ 0x3a, 0x73, 0xac, 0x5f, 0xf9, 0xfc, 0x2d, 0x37, 0x0f, 0xee, 0x2c, 0x54,
+ 0x9f, 0x6b, 0x16, 0xdd, 0xe7, 0x58, 0xbf, 0xfe, 0xc0, 0x36, 0xb3, 0xb6,
+ 0x0f, 0x0f, 0x3b, 0xac, 0x5d, 0xb7, 0x7e, 0xb1, 0x52, 0xa9, 0x14, 0x65,
+ 0x79, 0x0b, 0xa3, 0x4c, 0x3f, 0x08, 0xa6, 0x20, 0x21, 0x71, 0x28, 0xdc,
+ 0x78, 0x96, 0x2f, 0x80, 0x22, 0x89, 0x62, 0xe7, 0xdd, 0x62, 0xa4, 0xde,
+ 0x47, 0x12, 0x5b, 0xe6, 0x1f, 0xc4, 0x62, 0xad, 0xfd, 0xae, 0x66, 0xa7,
+ 0x8b, 0x16, 0x02, 0xc5, 0xb6, 0x58, 0xa9, 0x34, 0xb8, 0x25, 0x6f, 0x2c,
+ 0x5b, 0x87, 0x36, 0x3e, 0x1f, 0xa7, 0x45, 0x5b, 0x42, 0x12, 0xfd, 0x10,
+ 0x18, 0xa2, 0x58, 0xb8, 0x9d, 0x62, 0xa4, 0xf0, 0x37, 0x2a, 0xbf, 0xe2,
+ 0x93, 0xcb, 0x8f, 0x0e, 0xb1, 0x7c, 0xc0, 0xcd, 0x2c, 0x5f, 0xe0, 0x73,
+ 0x53, 0x06, 0xd2, 0xc5, 0xf4, 0xc6, 0x0c, 0x6b, 0x17, 0xfb, 0x05, 0xbf,
+ 0xe7, 0x58, 0xb1, 0x7f, 0xda, 0x90, 0x8b, 0x06, 0xfa, 0x58, 0xbf, 0xfe,
+ 0xcf, 0xfd, 0x9f, 0xd2, 0x59, 0xfc, 0xdd, 0x62, 0xb1, 0x56, 0x69, 0xb0,
+ 0xd7, 0x76, 0x68, 0x88, 0xbe, 0x6e, 0xc4, 0x44, 0x69, 0xc2, 0x61, 0x1a,
+ 0x47, 0x1c, 0xdf, 0xff, 0xb2, 0x30, 0xb1, 0xca, 0x62, 0x62, 0x13, 0xec,
+ 0xb1, 0x7f, 0x3f, 0x85, 0x13, 0xf9, 0x62, 0x86, 0x88, 0x58, 0x95, 0xaf,
+ 0xfe, 0x6e, 0xee, 0x67, 0x71, 0x37, 0xb3, 0xb9, 0x62, 0xff, 0x36, 0xcd,
+ 0x9e, 0xc3, 0xac, 0x5f, 0xff, 0xfd, 0xa0, 0x30, 0xe7, 0x5d, 0xdc, 0xce,
+ 0xe2, 0x04, 0xc4, 0x1f, 0x70, 0x8e, 0xb1, 0x7f, 0xff, 0x37, 0xb0, 0xf8,
+ 0xf1, 0x43, 0xf8, 0x31, 0x7b, 0x8b, 0x17, 0xff, 0xde, 0x60, 0x8b, 0x1c,
+ 0x11, 0x67, 0xc3, 0x25, 0x8b, 0xff, 0xee, 0x3e, 0xcd, 0xc6, 0x26, 0xf7,
+ 0xe6, 0x25, 0x8b, 0xff, 0x31, 0x03, 0x3d, 0x24, 0xe0, 0x58, 0xa9, 0x4e,
+ 0xdc, 0x6f, 0xdf, 0x5c, 0xf2, 0x8c, 0x72, 0x85, 0xff, 0xff, 0x41, 0xc2,
+ 0x6f, 0xc8, 0xf7, 0x6d, 0xbc, 0x59, 0xb6, 0xa5, 0x62, 0xd1, 0x91, 0xb3,
+ 0x7f, 0x59, 0xdf, 0x67, 0x1d, 0xf5, 0x3c, 0x99, 0x6c, 0x90, 0x94, 0x4e,
+ 0x38, 0x44, 0xe4, 0xa8, 0x63, 0x5c, 0xf7, 0x74, 0xe9, 0xe5, 0xe3, 0x25,
+ 0x8a, 0x50, 0x76, 0xa1, 0x2e, 0x79, 0x4b, 0xbf, 0x8e, 0x55, 0xa3, 0x85,
+ 0x04, 0x3d, 0x8a, 0x15, 0xdc, 0x94, 0xe5, 0xe9, 0x77, 0xe2, 0x8c, 0x60,
+ 0x22, 0x48, 0xe4, 0xc0, 0xe3, 0xea, 0xee, 0x4d, 0xbe, 0xff, 0xf3, 0x65,
+ 0x8b, 0xff, 0xd9, 0x1e, 0xf8, 0x7c, 0xfe, 0x31, 0x6e, 0xb1, 0x71, 0xb1,
+ 0x8c, 0x7d, 0xe4, 0x49, 0x7f, 0xe6, 0x84, 0x66, 0x6b, 0x76, 0x6d, 0xd5,
+ 0x24, 0x59, 0x7f, 0x84, 0xf0, 0x7f, 0xbf, 0x65, 0x8b, 0x46, 0x1d, 0x10,
+ 0xbc, 0x50, 0xbf, 0xd1, 0x99, 0xad, 0xd9, 0xb7, 0x54, 0x9d, 0x45, 0xff,
+ 0xff, 0xff, 0xa3, 0x4d, 0xbb, 0xe4, 0x6a, 0x8d, 0x7d, 0xff, 0x7f, 0xdf,
+ 0x0c, 0x33, 0xf1, 0xd1, 0x9b, 0x77, 0xd6, 0x34, 0xef, 0x93, 0xde, 0x77,
+ 0xe0, 0x30, 0xcf, 0xc7, 0x2c, 0x54, 0xc6, 0x66, 0x81, 0x09, 0x4b, 0xb8,
+ 0xdf, 0xbc, 0x63, 0x8f, 0x4a, 0x68, 0x3d, 0x2e, 0xa7, 0xf8, 0xf0, 0xab,
+ 0x69, 0x7f, 0x00, 0xb4, 0x08, 0x25, 0x29, 0x27, 0x90, 0xb5, 0xf1, 0x64,
+ 0x72, 0x2d, 0xf6, 0xec, 0xdb, 0xaa, 0x42, 0x12, 0xe9, 0xd2, 0xc5, 0x68,
+ 0xf2, 0x3c, 0x63, 0x6d, 0x96, 0x2f, 0xf4, 0x9e, 0x5c, 0x78, 0x75, 0x8b,
+ 0xdf, 0x72, 0x58, 0xbb, 0x06, 0xb1, 0x6d, 0xd6, 0x2b, 0x73, 0xc6, 0xf8,
+ 0xe1, 0x0b, 0xdf, 0x67, 0x67, 0xd2, 0xc5, 0xf3, 0x7c, 0x72, 0xb1, 0x7c,
+ 0xfa, 0xce, 0x96, 0x2b, 0x13, 0x45, 0x34, 0x8b, 0x71, 0x3e, 0x9e, 0x23,
+ 0xcb, 0xfc, 0x49, 0x1c, 0x45, 0x7f, 0xf6, 0xd8, 0x14, 0x67, 0x06, 0x26,
+ 0xd4, 0x16, 0x2f, 0x8a, 0x41, 0xc5, 0x8b, 0xfb, 0x42, 0xff, 0x6c, 0x1a,
+ 0xc5, 0xec, 0xc1, 0xac, 0x5f, 0xff, 0xfe, 0xf3, 0x90, 0xa1, 0x9c, 0x2c,
+ 0xd8, 0x38, 0x19, 0xc1, 0x00, 0xf3, 0x05, 0x8b, 0xbd, 0x19, 0x12, 0x3a,
+ 0xb4, 0x44, 0x46, 0x21, 0x8e, 0x54, 0x62, 0x7d, 0xf0, 0x6d, 0xc8, 0xcd,
+ 0x6f, 0xfe, 0x8c, 0xef, 0xe4, 0xbc, 0x19, 0xcb, 0x36, 0x58, 0xb4, 0x72,
+ 0xc5, 0xf4, 0xfe, 0x4e, 0xb1, 0x7d, 0xbb, 0x36, 0xea, 0x90, 0xd8, 0xad,
+ 0xcf, 0x4f, 0x44, 0x57, 0xb4, 0xdb, 0x2c, 0x5a, 0x30, 0x68, 0xa9, 0xc6,
+ 0x8f, 0x11, 0xdf, 0xe8, 0xcc, 0xd6, 0xec, 0xdb, 0xaa, 0x49, 0xb2, 0xe6,
+ 0x82, 0xc5, 0xf4, 0xf6, 0x92, 0x58, 0xbe, 0xdd, 0x9b, 0x75, 0x49, 0x40,
+ 0x50, 0xcf, 0xaf, 0x71, 0x7d, 0x11, 0xd8, 0x25, 0x8a, 0x58, 0xb6, 0x74,
+ 0x5f, 0xc4, 0x27, 0x7d, 0xff, 0xc8, 0xd6, 0x2d, 0x19, 0x88, 0x99, 0xfa,
+ 0x78, 0x64, 0xf7, 0xfa, 0x33, 0x35, 0xbb, 0x36, 0xea, 0x92, 0x98, 0xb8,
+ 0x0e, 0xb1, 0x7e, 0x17, 0x4c, 0x2d, 0x2c, 0x5b, 0x8b, 0x17, 0x84, 0xfa,
+ 0x58, 0xbf, 0xbf, 0x9d, 0xcf, 0x81, 0x2c, 0x5f, 0x6e, 0xcd, 0xba, 0xa4,
+ 0xb0, 0x2f, 0xbd, 0x3d, 0x41, 0x62, 0xa2, 0x44, 0x36, 0x8c, 0x4e, 0x63,
+ 0x7e, 0x70, 0x86, 0x2d, 0x2c, 0x5b, 0x65, 0x8b, 0x83, 0x82, 0xc5, 0xe6,
+ 0x2d, 0xd6, 0x2a, 0x4f, 0x24, 0x02, 0x7e, 0x19, 0xbb, 0x84, 0xb1, 0x70,
+ 0xcd, 0x58, 0xbd, 0x20, 0x75, 0x8b, 0x8f, 0xc5, 0x8b, 0xf3, 0x43, 0xcf,
+ 0xb2, 0xc5, 0xfb, 0x9c, 0x2c, 0x02, 0xc5, 0x86, 0xb1, 0x4e, 0x7c, 0x6c,
+ 0x52, 0x19, 0x45, 0xcf, 0x1c, 0xb1, 0x6d, 0x2c, 0x5e, 0x78, 0xe6, 0x93,
+ 0x58, 0x21, 0xab, 0xfd, 0x19, 0x9a, 0xdd, 0x9b, 0x75, 0x48, 0x7e, 0x5c,
+ 0x2e, 0x2c, 0x5e, 0x29, 0x1a, 0xc5, 0xf4, 0xc1, 0xbc, 0xb1, 0x52, 0x8c,
+ 0xe8, 0x19, 0x8d, 0x15, 0xc6, 0x08, 0x72, 0xf6, 0x14, 0x16, 0x2f, 0x39,
+ 0x41, 0x62, 0xb0, 0xdc, 0x70, 0x72, 0xd2, 0xb1, 0x6d, 0x96, 0x2f, 0xcf,
+ 0xcf, 0x09, 0x96, 0x2f, 0x7c, 0x5d, 0x2c, 0x5e, 0xd4, 0x81, 0x62, 0xa4,
+ 0xfd, 0xc6, 0x27, 0xb9, 0x41, 0xc7, 0xea, 0x08, 0xc4, 0xc8, 0x44, 0x5e,
+ 0x88, 0x5a, 0x58, 0xb1, 0x2c, 0x5f, 0x78, 0xa4, 0xeb, 0x14, 0x33, 0x66,
+ 0xe2, 0x37, 0xf8, 0xa4, 0x0d, 0xe1, 0x4a, 0xc5, 0x4a, 0x29, 0x3e, 0xa5,
+ 0xe2, 0x0b, 0xfb, 0xa8, 0x34, 0x1c, 0x96, 0x2f, 0x49, 0x44, 0xb1, 0x7d,
+ 0x14, 0x27, 0xa5, 0x8b, 0xe9, 0xe3, 0xc4, 0xb1, 0x7e, 0xce, 0xdf, 0x68,
+ 0x2c, 0x56, 0x22, 0xf4, 0xd2, 0xe7, 0x1d, 0xd1, 0x29, 0x11, 0xde, 0x35,
+ 0xbc, 0xb1, 0x76, 0x69, 0x62, 0xf0, 0xb5, 0xb2, 0xc5, 0xbc, 0xb1, 0x58,
+ 0x6c, 0x58, 0x7e, 0xdd, 0xcb, 0x16, 0xe2, 0xc5, 0x1c, 0xd3, 0x86, 0x2b,
+ 0x77, 0xbc, 0xb1, 0x68, 0xce, 0xf8, 0xbf, 0xff, 0x22, 0xfb, 0x15, 0x0c,
+ 0x4b, 0x21, 0x47, 0xb9, 0x8f, 0x4e, 0x6e, 0x5d, 0x1e, 0x2f, 0xa1, 0x93,
+ 0x8e, 0x7d, 0xed, 0xa3, 0x28, 0x03, 0xf9, 0x43, 0x93, 0x90, 0xcb, 0xf4,
+ 0x3b, 0x04, 0x90, 0x10, 0xf4, 0x72, 0x40, 0x68, 0xdd, 0xc4, 0x57, 0xff,
+ 0xa3, 0x0e, 0xd0, 0x8c, 0xcd, 0x6e, 0xcd, 0xba, 0xa4, 0x6f, 0x2f, 0xfe,
+ 0x3b, 0x42, 0x33, 0x35, 0xbb, 0x36, 0xea, 0x91, 0xf8, 0xbd, 0xde, 0x46,
+ 0xfd, 0xe2, 0xc5, 0xff, 0xff, 0x7c, 0x5e, 0x26, 0x37, 0xaf, 0x6a, 0x73,
+ 0xa6, 0x7e, 0x99, 0x62, 0xdd, 0xe7, 0x78, 0x89, 0x6c, 0x2d, 0xbb, 0xbe,
+ 0xfb, 0xc5, 0x8b, 0xfb, 0xf9, 0x14, 0xf5, 0xc5, 0x8b, 0xf1, 0xe4, 0xf2,
+ 0x1a, 0xc5, 0xf6, 0x66, 0xb8, 0xb1, 0x46, 0x22, 0x7f, 0xbc, 0x24, 0x63,
+ 0x00, 0x14, 0xdf, 0xf7, 0x7a, 0xd0, 0xfb, 0xf6, 0xcd, 0x96, 0x2f, 0xe0,
+ 0xc3, 0xeb, 0xbb, 0x9d, 0x2c, 0x54, 0x6e, 0x7f, 0x1d, 0xe2, 0x0d, 0xe8,
+ 0x4f, 0x4b, 0x17, 0x34, 0x16, 0x2f, 0xe8, 0xd2, 0x5f, 0x79, 0x3a, 0xc5,
+ 0xee, 0xf3, 0xd8, 0xb1, 0x73, 0x9d, 0x62, 0xa3, 0x75, 0x4b, 0x1d, 0xe4,
+ 0x34, 0x7b, 0xd8, 0x5d, 0x46, 0x85, 0x9d, 0xf6, 0x3d, 0xdf, 0x05, 0xe3,
+ 0x51, 0x9e, 0x88, 0xaf, 0xa4, 0xd1, 0xca, 0xc5, 0xfe, 0x1e, 0x76, 0x21,
+ 0x07, 0x2b, 0x17, 0xcd, 0xd4, 0x25, 0x62, 0xdd, 0xe4, 0x9e, 0xc8, 0x46,
+ 0xd7, 0xdd, 0xe6, 0xdc, 0x02, 0xc5, 0xf9, 0xb6, 0xf0, 0x8d, 0x58, 0xbf,
+ 0x6f, 0xa2, 0x98, 0x2c, 0x54, 0x6b, 0x3f, 0xed, 0x15, 0x31, 0x5d, 0xff,
+ 0xb2, 0x1f, 0x92, 0x17, 0x3e, 0xeb, 0x17, 0x06, 0x75, 0x8b, 0xff, 0x99,
+ 0xfd, 0x09, 0x2f, 0x73, 0x69, 0x58, 0xbf, 0xb0, 0xd7, 0xf1, 0x4a, 0xc5,
+ 0x46, 0x88, 0xc8, 0xdc, 0xfb, 0xe3, 0x31, 0xc8, 0x97, 0x40, 0xeb, 0x17,
+ 0xa3, 0x5c, 0x69, 0x1b, 0x2c, 0x5f, 0x98, 0xfa, 0x9e, 0x2c, 0x57, 0x78,
+ 0x7a, 0xdc, 0x2e, 0xbf, 0xee, 0xcf, 0xbf, 0x79, 0x91, 0x4f, 0x96, 0x2f,
+ 0xda, 0x9f, 0x8a, 0x56, 0x2e, 0x0b, 0xeb, 0x17, 0xdd, 0xe4, 0x3b, 0xcd,
+ 0x96, 0x2f, 0xdf, 0xcf, 0x48, 0xd6, 0x2f, 0xd9, 0x14, 0x27, 0xa5, 0x8b,
+ 0xfd, 0x9a, 0xfb, 0xc5, 0x03, 0xac, 0x51, 0x8b, 0x86, 0xf1, 0xbb, 0xe7,
+ 0x79, 0x0a, 0xbe, 0xf6, 0x1f, 0x91, 0xa9, 0x1a, 0x35, 0xb7, 0x61, 0x3b,
+ 0xa1, 0x44, 0x51, 0xa1, 0x96, 0x2f, 0x22, 0x80, 0xca, 0xae, 0x0b, 0x4b,
+ 0x17, 0xef, 0x7f, 0x3b, 0x62, 0xc5, 0x68, 0xf0, 0xf8, 0x33, 0x7d, 0x87,
+ 0x7f, 0x2c, 0x5f, 0xdd, 0x9f, 0xac, 0xcd, 0x96, 0x2e, 0xc2, 0x58, 0xac,
+ 0x3c, 0x7e, 0x18, 0xdf, 0xd1, 0xb4, 0x68, 0x79, 0xcf, 0x2c, 0x5f, 0xdd,
+ 0xe3, 0xc7, 0x7d, 0xfb, 0xf5, 0x8b, 0xfb, 0x34, 0xfe, 0xe1, 0xd6, 0x2a,
+ 0x35, 0x9f, 0x4f, 0x0e, 0xee, 0x2d, 0xd6, 0x2f, 0x1e, 0x43, 0x58, 0xbe,
+ 0xe4, 0x47, 0xe2, 0xc5, 0xf8, 0xbd, 0xf7, 0x3a, 0xc5, 0xf4, 0x42, 0x60,
+ 0xd6, 0x2a, 0x4f, 0x35, 0x8a, 0x2f, 0x1e, 0x78, 0xb1, 0x78, 0x9b, 0xb2,
+ 0xc5, 0xe7, 0x90, 0x2c, 0x5d, 0xbe, 0xeb, 0x17, 0xfe, 0xc1, 0xfd, 0xcf,
+ 0x9c, 0x11, 0xd6, 0x2f, 0xf6, 0xff, 0x7f, 0x66, 0x1d, 0x62, 0xee, 0xdb,
+ 0xae, 0x50, 0x22, 0xbb, 0xc5, 0x69, 0x3d, 0xe9, 0x14, 0x6c, 0xd3, 0x1a,
+ 0x88, 0x63, 0x5c, 0x28, 0x64, 0xa3, 0x06, 0x1c, 0x7a, 0x27, 0x2d, 0x10,
+ 0x1c, 0x75, 0x87, 0x80, 0x38, 0x43, 0x5c, 0x3f, 0xf1, 0xa5, 0xf7, 0x7b,
+ 0x1d, 0x9d, 0x2c, 0x5f, 0xdf, 0x97, 0xd3, 0xe9, 0x62, 0xa3, 0x73, 0xd9,
+ 0xdc, 0xb2, 0xfe, 0xef, 0x1b, 0x6f, 0xbc, 0x7a, 0xc5, 0xfa, 0x37, 0xef,
+ 0x76, 0xc0, 0x96, 0x2f, 0xf8, 0xcf, 0x7f, 0x0f, 0x9a, 0xc5, 0x8b, 0xfb,
+ 0xbe, 0xb1, 0xbc, 0x6f, 0xde, 0xf2, 0x56, 0x2f, 0xd1, 0xa1, 0xa6, 0xe4,
+ 0x7a, 0xc5, 0xfd, 0xe7, 0x20, 0xb0, 0x96, 0x2e, 0xe0, 0x96, 0x2f, 0x00,
+ 0x3f, 0x2c, 0x61, 0x71, 0x68, 0x2c, 0x5f, 0x77, 0xb9, 0xce, 0xf1, 0x62,
+ 0xb4, 0x6f, 0xd8, 0x4a, 0xee, 0xdb, 0xae, 0x50, 0x12, 0xdf, 0x58, 0xb8,
+ 0x00, 0x58, 0xae, 0xf1, 0x53, 0x57, 0x7a, 0x51, 0x1a, 0x1b, 0xc6, 0xc6,
+ 0xbd, 0xf6, 0x75, 0x1a, 0xd1, 0xb0, 0xcd, 0x91, 0x49, 0xb3, 0xc4, 0x02,
+ 0x28, 0x0c, 0x4a, 0xf4, 0x6c, 0x73, 0xac, 0x5f, 0x46, 0xdd, 0xef, 0x8e,
+ 0xb1, 0x79, 0x86, 0xeb, 0x17, 0xff, 0x13, 0x7b, 0x85, 0x3a, 0xd3, 0x0d,
+ 0x62, 0xa0, 0x7b, 0xf8, 0x39, 0x7f, 0x7d, 0xfc, 0x53, 0x12, 0xc5, 0xcd,
+ 0x8b, 0x15, 0xb9, 0xe2, 0x68, 0xba, 0xf9, 0x87, 0x87, 0x58, 0xbf, 0x46,
+ 0xbe, 0xf2, 0x1a, 0xee, 0x58, 0xba, 0x49, 0x62, 0xfa, 0x26, 0x68, 0x2c,
+ 0x56, 0xe6, 0xe5, 0xc5, 0xaf, 0xfd, 0xda, 0x7e, 0xf3, 0x14, 0x53, 0xba,
+ 0xc5, 0xfc, 0xe3, 0x14, 0xea, 0x0b, 0x17, 0x8a, 0x34, 0xdd, 0x62, 0xa3,
+ 0x75, 0x50, 0x1d, 0xe1, 0x1f, 0x7b, 0x08, 0xd8, 0xd1, 0x97, 0xbe, 0x11,
+ 0xc6, 0xb2, 0x2c, 0x71, 0x72, 0x16, 0x43, 0xec, 0x5d, 0x7d, 0xc1, 0x68,
+ 0x0b, 0x17, 0xd1, 0xb6, 0xc7, 0xe2, 0xc5, 0xfe, 0xd7, 0xdb, 0x8e, 0x3c,
+ 0x58, 0xbe, 0x92, 0x7e, 0x96, 0x2d, 0x98, 0x7a, 0xb1, 0x19, 0xdd, 0x3e,
+ 0x58, 0xbf, 0x89, 0xcd, 0xfb, 0x41, 0x62, 0xff, 0xf9, 0xbd, 0x25, 0xbb,
+ 0x9c, 0x62, 0x6d, 0x41, 0x62, 0x8e, 0x7f, 0xc4, 0x5d, 0x6f, 0x2c, 0x5f,
+ 0x82, 0xf7, 0xa4, 0xeb, 0x14, 0x62, 0x3c, 0xa3, 0x48, 0x4a, 0xc9, 0x0e,
+ 0xc2, 0x57, 0xfc, 0xdf, 0x7e, 0xd1, 0x81, 0x04, 0x12, 0x45, 0xfe, 0xfb,
+ 0x7b, 0xcc, 0xc1, 0x2c, 0x5d, 0x23, 0x58, 0xbf, 0x66, 0xed, 0xc7, 0x58,
+ 0xbe, 0x7d, 0x98, 0xeb, 0x14, 0x62, 0xad, 0xc8, 0xd8, 0x93, 0xbe, 0xdf,
+ 0xfb, 0xe4, 0x63, 0x3d, 0xf5, 0x48, 0x8d, 0x68, 0x5d, 0x1a, 0x7c, 0x5e,
+ 0x38, 0xa2, 0xe8, 0x32, 0xc5, 0xff, 0x41, 0xdb, 0xa8, 0x10, 0x99, 0x62,
+ 0xff, 0xff, 0x7d, 0xf9, 0x30, 0xcf, 0xbe, 0xbe, 0xd8, 0x2c, 0xfa, 0xc5,
+ 0xff, 0xf6, 0xa5, 0xfd, 0xfc, 0x1b, 0xf3, 0x08, 0x0b, 0x16, 0xef, 0x46,
+ 0x8f, 0xdc, 0x17, 0x63, 0x9e, 0x2f, 0xdd, 0xc9, 0x58, 0xbf, 0xee, 0x39,
+ 0x75, 0xe2, 0x9c, 0x58, 0xa8, 0xdd, 0x12, 0xb0, 0x46, 0xc1, 0x7b, 0xfa,
+ 0x3e, 0x74, 0xcd, 0x05, 0x8b, 0xf7, 0xdd, 0x81, 0x1a, 0xd6, 0x2f, 0x4f,
+ 0x50, 0x58, 0xae, 0xf1, 0x16, 0x11, 0xa8, 0xd3, 0xc6, 0x1d, 0xc5, 0xd7,
+ 0xfa, 0x37, 0x29, 0x18, 0x60, 0xe2, 0xc5, 0xff, 0xa3, 0x4e, 0xf2, 0x22,
+ 0x91, 0xe7, 0x5e, 0x58, 0xbf, 0x4c, 0x77, 0x74, 0x51, 0x2c, 0x5e, 0x8e,
+ 0xcf, 0xac, 0x54, 0x47, 0xa3, 0xe3, 0x1b, 0xec, 0x1b, 0x41, 0x62, 0xfe,
+ 0x0c, 0xf8, 0x59, 0x1e, 0xb1, 0x7f, 0x45, 0x09, 0x8f, 0x81, 0xd6, 0x2b,
+ 0x0f, 0x92, 0x23, 0x1b, 0xd1, 0xbf, 0x5d, 0xf6, 0xb1, 0x7b, 0xb6, 0xa0,
+ 0xb1, 0x7b, 0x42, 0xee, 0x58, 0xbc, 0x10, 0x46, 0xac, 0x54, 0x6e, 0xa8,
+ 0xba, 0x34, 0x3a, 0x8d, 0xa1, 0x39, 0xdf, 0x08, 0xfb, 0xeb, 0x08, 0x62,
+ 0x22, 0xe1, 0x58, 0x88, 0x02, 0x21, 0xbf, 0xff, 0x77, 0x84, 0xde, 0x9c,
+ 0x28, 0x1e, 0x70, 0x86, 0xb1, 0x7f, 0x77, 0x90, 0x7f, 0x7a, 0x56, 0x2f,
+ 0xa7, 0x66, 0x0d, 0x62, 0xf6, 0x38, 0x16, 0x29, 0xcf, 0x00, 0x89, 0x2f,
+ 0xfb, 0xbc, 0x83, 0xfb, 0xf2, 0x46, 0xac, 0x5e, 0x01, 0xb2, 0xb1, 0x51,
+ 0xb9, 0xee, 0xf7, 0xd9, 0xfd, 0xed, 0xb3, 0x16, 0x2f, 0x37, 0xdd, 0x62,
+ 0xfc, 0xfa, 0x00, 0x25, 0x62, 0xff, 0x7a, 0x02, 0x1b, 0x10, 0x16, 0x2e,
+ 0x7d, 0x96, 0x2f, 0x77, 0xed, 0xa5, 0x8a, 0x8d, 0xd5, 0x22, 0x77, 0x8a,
+ 0xfd, 0xeb, 0x9c, 0x6c, 0xfb, 0x1a, 0xcb, 0xa4, 0x76, 0x03, 0x8c, 0x51,
+ 0xe3, 0x41, 0x0c, 0x5e, 0x6c, 0xfa, 0xc5, 0xfe, 0xef, 0x79, 0xf9, 0x29,
+ 0xd9, 0x62, 0xe8, 0xda, 0x0b, 0x15, 0xde, 0x9e, 0xb7, 0x7d, 0x9c, 0xdf,
+ 0x8b, 0x00, 0x1f, 0x4b, 0x17, 0xfc, 0xde, 0xea, 0x1e, 0xcd, 0x1a, 0xb1,
+ 0x7e, 0x8b, 0x79, 0xeb, 0xcb, 0x17, 0xfe, 0x7e, 0xb8, 0x58, 0x39, 0xcd,
+ 0x2c, 0x5c, 0xe0, 0x58, 0xae, 0xf1, 0x38, 0x78, 0xd1, 0xcb, 0xbe, 0x17,
+ 0x46, 0xb2, 0xa7, 0x3c, 0x01, 0x61, 0x1f, 0x5f, 0xdf, 0xdf, 0xbc, 0xe7,
+ 0xdd, 0x62, 0xf4, 0x69, 0xdf, 0xf7, 0x8b, 0x17, 0xff, 0xa3, 0x78, 0xbb,
+ 0xde, 0xfb, 0x20, 0x46, 0xb3, 0x0c, 0xfc, 0x72, 0xc5, 0x77, 0xc4, 0x4b,
+ 0x80, 0xb6, 0xff, 0xff, 0x08, 0xc2, 0xcd, 0x68, 0xff, 0x91, 0x11, 0x86,
+ 0x7e, 0x39, 0x62, 0xff, 0xd3, 0x33, 0x33, 0x33, 0xd7, 0x16, 0x2f, 0x45,
+ 0x3e, 0x58, 0xba, 0x66, 0x4f, 0x6a, 0x23, 0xcb, 0x8e, 0xeb, 0x17, 0xff,
+ 0xbf, 0x31, 0x75, 0xcc, 0xea, 0x3e, 0x64, 0x96, 0x2f, 0x3f, 0x58, 0xb1,
+ 0x7e, 0xd3, 0xec, 0xc7, 0x48, 0xb8, 0x20, 0x92, 0x2b, 0x0f, 0x0c, 0x22,
+ 0x9b, 0x09, 0x22, 0x30, 0xd1, 0x5e, 0xfe, 0x6e, 0xb1, 0x52, 0x9a, 0xbe,
+ 0xe5, 0x9f, 0x17, 0x02, 0x7f, 0x21, 0x04, 0x19, 0x2d, 0xf8, 0x51, 0xd2,
+ 0x2e, 0x96, 0x2e, 0x14, 0x16, 0x2f, 0xfd, 0x3f, 0xc0, 0x60, 0xfe, 0xd0,
+ 0x58, 0xbe, 0x62, 0x9e, 0xe5, 0x8b, 0xfa, 0x12, 0x79, 0xd6, 0x96, 0x2b,
+ 0x11, 0xab, 0x1e, 0x5b, 0xa1, 0x86, 0x3e, 0x11, 0x25, 0xff, 0xfd, 0xe7,
+ 0x3e, 0x17, 0xb9, 0x26, 0xf0, 0x43, 0xfb, 0xac, 0x5f, 0x86, 0xe1, 0x49,
+ 0xd6, 0x2f, 0xe8, 0x19, 0xc7, 0x16, 0x96, 0x2f, 0xfa, 0x78, 0xda, 0x7f,
+ 0x73, 0x16, 0x2b, 0xa3, 0xe8, 0x01, 0x85, 0xff, 0xe6, 0x72, 0xc0, 0x19,
+ 0x3a, 0xda, 0x7c, 0xb1, 0x7f, 0xee, 0xe7, 0x8f, 0xfc, 0x53, 0x1e, 0xc7,
+ 0x58, 0xbf, 0xde, 0xfc, 0x96, 0xcf, 0xd9, 0x62, 0xfd, 0xcc, 0x84, 0x76,
+ 0x2c, 0x5e, 0xc3, 0xc9, 0x87, 0xc3, 0xc3, 0x6b, 0xff, 0xf9, 0xe1, 0xc0,
+ 0xcf, 0x84, 0x28, 0x37, 0x82, 0x6e, 0x96, 0x2f, 0xf6, 0x98, 0x12, 0x36,
+ 0xf2, 0xc5, 0x4a, 0x24, 0x5d, 0x7a, 0x86, 0x9e, 0xcf, 0xd2, 0x8a, 0x15,
+ 0x5e, 0x86, 0x25, 0xf8, 0xec, 0x7c, 0x1a, 0xc5, 0xf8, 0xb0, 0xd7, 0x1a,
+ 0xc5, 0xff, 0x7b, 0x7f, 0xb9, 0x14, 0xf4, 0xb1, 0x52, 0x88, 0xac, 0x28,
+ 0x62, 0x8b, 0xff, 0xfa, 0x06, 0x1c, 0x5a, 0x0e, 0x39, 0x8b, 0xaf, 0x06,
+ 0x58, 0xb1, 0x7f, 0xdb, 0x4f, 0x1e, 0x3b, 0x35, 0x2b, 0x17, 0xff, 0xda,
+ 0xd4, 0x9f, 0x82, 0x9e, 0x8d, 0xd3, 0x6e, 0xb1, 0x52, 0x89, 0x06, 0x3c,
+ 0xbf, 0x87, 0x85, 0xb3, 0xe9, 0x62, 0xe9, 0xee, 0x58, 0xa3, 0x17, 0x50,
+ 0xe5, 0x73, 0x21, 0x22, 0xf1, 0xfe, 0x7e, 0x1a, 0x2c, 0x5a, 0x50, 0xf3,
+ 0x11, 0x0f, 0x62, 0xeb, 0xfe, 0x29, 0x32, 0x28, 0x4e, 0xb6, 0x58, 0xbf,
+ 0xd8, 0x37, 0xed, 0xc0, 0x6e, 0xb1, 0x7f, 0xff, 0xec, 0xec, 0xfe, 0x86,
+ 0x03, 0x85, 0x80, 0xd4, 0xec, 0xda, 0xdd, 0x62, 0xe9, 0x83, 0x22, 0x9b,
+ 0x86, 0xf7, 0xb3, 0x69, 0x58, 0xbf, 0xfe, 0xc0, 0x67, 0xb8, 0xfd, 0x8b,
+ 0x3d, 0xf7, 0x58, 0xbb, 0xdc, 0xc3, 0xed, 0x21, 0xdb, 0xff, 0xf9, 0xce,
+ 0xfa, 0x1c, 0x8f, 0x1e, 0x0d, 0xcc, 0x12, 0xc5, 0x1d, 0x50, 0x0f, 0xe1,
+ 0xc4, 0x50, 0x9a, 0xf1, 0x65, 0xf7, 0x07, 0xe1, 0x2c, 0x5f, 0xf9, 0xb4,
+ 0x69, 0x91, 0xc2, 0xfb, 0xe9, 0x62, 0xff, 0xff, 0xd3, 0xac, 0x19, 0x36,
+ 0x8d, 0x6f, 0x0b, 0xcf, 0xee, 0x7d, 0xd6, 0x28, 0x91, 0x63, 0xd9, 0x16,
+ 0xff, 0xc2, 0xe7, 0x33, 0xa8, 0x78, 0x43, 0x58, 0xbf, 0xda, 0x11, 0x0b,
+ 0xc2, 0xf2, 0xc5, 0xef, 0xc9, 0x2c, 0x56, 0xe8, 0x93, 0x74, 0x2f, 0x1a,
+ 0xde, 0x0f, 0xdc, 0x58, 0xbe, 0x17, 0x84, 0x6a, 0xc5, 0x68, 0xf1, 0x08,
+ 0x7e, 0xa5, 0x12, 0xb8, 0xe9, 0x67, 0x58, 0xbf, 0xd3, 0x11, 0x49, 0xc5,
+ 0xb2, 0xc5, 0xf9, 0xb8, 0xe7, 0x12, 0xc5, 0x47, 0x9f, 0x71, 0xc4, 0x7e,
+ 0x6b, 0x71, 0xa1, 0x2c, 0x5f, 0xff, 0x49, 0x14, 0xec, 0x13, 0x6d, 0xf7,
+ 0x92, 0x58, 0xbc, 0x58, 0x05, 0x8a, 0x81, 0xf5, 0xe2, 0x7d, 0x4a, 0xbd,
+ 0x0d, 0xd2, 0x1e, 0x1a, 0xbf, 0x8d, 0x31, 0xa1, 0x1f, 0xe3, 0x21, 0x42,
+ 0x16, 0xf9, 0xf6, 0x63, 0xac, 0x5f, 0xe9, 0x08, 0x7f, 0x92, 0xdd, 0x62,
+ 0xe7, 0x95, 0x8a, 0x73, 0xcb, 0x23, 0x5b, 0xee, 0x7e, 0x78, 0xb1, 0x71,
+ 0xf8, 0xb1, 0x58, 0x6e, 0xdc, 0x8e, 0xff, 0xf3, 0xeb, 0xf9, 0x84, 0x2f,
+ 0x42, 0x4d, 0x58, 0xbf, 0x48, 0x67, 0xfb, 0xac, 0x5f, 0xf7, 0x5e, 0x0f,
+ 0x6f, 0x6a, 0x78, 0xb1, 0x7b, 0x1f, 0xb2, 0xc5, 0x61, 0xee, 0x04, 0x7d,
+ 0x43, 0x4f, 0x67, 0x4d, 0xc7, 0x5b, 0xf8, 0xf9, 0x25, 0x72, 0x10, 0xb7,
+ 0xfe, 0xfc, 0xf5, 0x0c, 0x3b, 0xcc, 0x7a, 0xc5, 0xff, 0x03, 0x19, 0xf5,
+ 0xbc, 0xf9, 0x62, 0xf4, 0x0f, 0x2b, 0x14, 0xe7, 0xad, 0xd8, 0xe6, 0xff,
+ 0x6b, 0x0e, 0x7c, 0x17, 0x7e, 0xb1, 0x7e, 0x6d, 0xa5, 0xb7, 0x58, 0xbe,
+ 0x9e, 0x49, 0xd6, 0x2f, 0xff, 0x76, 0x92, 0x79, 0xeb, 0x69, 0x29, 0x02,
+ 0xc5, 0xfe, 0x9d, 0x88, 0x59, 0xd7, 0x96, 0x2c, 0x19, 0x88, 0xa2, 0x92,
+ 0x2f, 0xa5, 0xdf, 0xd3, 0xdb, 0x4e, 0x7c, 0x58, 0xa9, 0x54, 0x4b, 0x90,
+ 0x98, 0x72, 0x3f, 0x9c, 0xb4, 0x32, 0xc8, 0xde, 0xfd, 0xcf, 0x61, 0x1a,
+ 0xb1, 0x79, 0x8a, 0x56, 0x2f, 0xed, 0x48, 0xf3, 0x38, 0xb1, 0x7f, 0x9b,
+ 0xae, 0x33, 0x75, 0xc5, 0x8a, 0x82, 0x29, 0xa2, 0x29, 0x00, 0xdf, 0x0b,
+ 0x6f, 0xb8, 0xd0, 0x8f, 0x58, 0xbf, 0xf4, 0x39, 0x30, 0x90, 0x73, 0x3b,
+ 0x2c, 0x5d, 0x87, 0x58, 0xbd, 0x23, 0x75, 0x8b, 0xa4, 0xeb, 0x17, 0xf0,
+ 0x7e, 0xe6, 0xd8, 0x12, 0xc5, 0xfc, 0xfa, 0xeb, 0x8e, 0x6a, 0xc5, 0x47,
+ 0x9f, 0xce, 0x85, 0xfe, 0x65, 0x76, 0xf2, 0xb1, 0x68, 0xf5, 0x8b, 0xf9,
+ 0xf4, 0xdb, 0xe1, 0x2c, 0x56, 0x8f, 0x0b, 0xc2, 0xb7, 0xf9, 0xb5, 0xbe,
+ 0x0b, 0x5b, 0x2c, 0x5f, 0xf6, 0x6b, 0x3e, 0xfa, 0xfb, 0x2c, 0x5a, 0x76,
+ 0x3e, 0xed, 0xcd, 0xaf, 0xfe, 0xf7, 0x85, 0xd1, 0x60, 0x39, 0x31, 0xeb,
+ 0x17, 0xff, 0x9f, 0x98, 0x3d, 0x48, 0xbc, 0x4f, 0xd9, 0x62, 0xfe, 0x80,
+ 0x79, 0xf6, 0x3a, 0xc5, 0x2c, 0x59, 0x88, 0xdd, 0x84, 0x5f, 0x58, 0x8f,
+ 0x5d, 0xd2, 0x42, 0x84, 0x35, 0xff, 0xd3, 0xa8, 0x6f, 0xf7, 0x88, 0x98,
+ 0x25, 0x8b, 0xff, 0xb4, 0xdb, 0x0f, 0xf3, 0xcf, 0x0b, 0xeb, 0x15, 0xc4,
+ 0x47, 0x79, 0x1e, 0xf7, 0x9e, 0x25, 0x8b, 0xfa, 0x2e, 0x07, 0x85, 0xba,
+ 0xc5, 0x41, 0x70, 0x17, 0x21, 0x2a, 0x69, 0x97, 0x4b, 0x5a, 0x84, 0x87,
+ 0xe3, 0x1e, 0xe4, 0x31, 0x3c, 0x46, 0x18, 0xf5, 0x69, 0x72, 0xd0, 0xf3,
+ 0x83, 0x97, 0xc5, 0x80, 0x8e, 0x58, 0xbe, 0x93, 0xcf, 0xd6, 0x2e, 0x9e,
+ 0x2c, 0x59, 0xe0, 0x6e, 0x48, 0x8a, 0xa5, 0x76, 0x9b, 0x27, 0x3d, 0x5c,
+ 0xbb, 0xeb, 0xd7, 0xf3, 0x01, 0xb7, 0x6d, 0x2c, 0x5f, 0x03, 0x32, 0x3d,
+ 0x62, 0xfd, 0xbb, 0x3e, 0xd8, 0xb1, 0x69, 0x39, 0xe7, 0x11, 0x2d, 0xff,
+ 0xed, 0x37, 0xe1, 0x9e, 0xe3, 0x6c, 0x28, 0x2c, 0x5f, 0xff, 0xcd, 0x9b,
+ 0xf3, 0xec, 0xfe, 0x80, 0xa4, 0xa6, 0x0b, 0x17, 0xff, 0x88, 0xa4, 0xd3,
+ 0xfe, 0x7a, 0xf4, 0xfd, 0x62, 0x99, 0x1e, 0x24, 0x98, 0x25, 0xab, 0xf9,
+ 0xe6, 0x1f, 0xc2, 0x58, 0xb9, 0xa0, 0xb1, 0x7f, 0xfe, 0xf7, 0x05, 0x3f,
+ 0x93, 0x96, 0x00, 0xf3, 0x05, 0x8a, 0x39, 0xf6, 0x10, 0xbd, 0xfb, 0xa8,
+ 0x07, 0xc0, 0x2c, 0x5b, 0xeb, 0x16, 0x1e, 0x1b, 0xe6, 0x2c, 0xbf, 0xe9,
+ 0xfc, 0xf5, 0x08, 0x4e, 0xcb, 0x16, 0x95, 0x8b, 0x9f, 0x4b, 0x16, 0xdf,
+ 0x46, 0xa3, 0xe2, 0x37, 0xf4, 0x79, 0x66, 0xd8, 0x12, 0xc5, 0x4a, 0x68,
+ 0x38, 0xbf, 0xa2, 0x56, 0x63, 0x11, 0x45, 0xff, 0x8e, 0xc0, 0x91, 0x8b,
+ 0x42, 0xd2, 0xc5, 0xee, 0xcd, 0xf5, 0x8b, 0x16, 0x1e, 0xf8, 0x90, 0x2f,
+ 0xff, 0xfb, 0x72, 0x7e, 0xdc, 0xfb, 0x3f, 0xa0, 0x29, 0x6f, 0x0a, 0x56,
+ 0x2f, 0xff, 0xff, 0x6a, 0x4d, 0xc8, 0xb7, 0xfb, 0xc5, 0x16, 0x17, 0x83,
+ 0xc8, 0xbe, 0xc3, 0x58, 0xbf, 0xfd, 0xf7, 0x38, 0xe4, 0xc8, 0xe1, 0x7d,
+ 0xf4, 0xb1, 0x7f, 0x7a, 0x7e, 0x53, 0x05, 0x8b, 0xff, 0xfe, 0xfb, 0x3f,
+ 0xa0, 0x29, 0x29, 0x84, 0x1f, 0x5b, 0x08, 0x0b, 0x14, 0x62, 0x38, 0xdd,
+ 0x3f, 0x85, 0xb4, 0xb1, 0x7e, 0x63, 0x5f, 0x53, 0x03, 0x79, 0xf3, 0x0a,
+ 0x95, 0x4d, 0x0e, 0x4c, 0xcd, 0x05, 0x1c, 0xed, 0xf7, 0xb6, 0xc0, 0x96,
+ 0x2e, 0xd4, 0xac, 0x59, 0x88, 0xde, 0x78, 0x96, 0xfd, 0x3a, 0xd3, 0x44,
+ 0xb1, 0x73, 0xf4, 0xb1, 0x7f, 0x80, 0x2c, 0x01, 0xda, 0x0b, 0x17, 0x64,
+ 0xac, 0x54, 0x0f, 0x8b, 0xa1, 0x83, 0x9a, 0x56, 0xc8, 0xbb, 0x68, 0x45,
+ 0xdf, 0xfd, 0xd4, 0x1c, 0xbd, 0x8e, 0x3c, 0x1a, 0xc5, 0xff, 0xfc, 0xfd,
+ 0x49, 0x4f, 0x07, 0xf9, 0xe3, 0x97, 0x50, 0x58, 0xa3, 0x11, 0x3f, 0xf4,
+ 0x4b, 0xff, 0xfb, 0xdc, 0xc9, 0xfc, 0x99, 0xa9, 0x2c, 0xfe, 0x6e, 0xb1,
+ 0x7f, 0xff, 0x98, 0x7f, 0x72, 0x6f, 0x4c, 0x4e, 0x6b, 0x96, 0x76, 0x58,
+ 0xae, 0x91, 0x79, 0xf5, 0xbb, 0xfe, 0x7f, 0x66, 0xb4, 0x2d, 0xbb, 0x2c,
+ 0x5f, 0xf7, 0x33, 0xc3, 0xcc, 0x07, 0x16, 0x2b, 0xe7, 0xed, 0xe3, 0xdb,
+ 0xfe, 0x7f, 0x66, 0xb4, 0x2d, 0xbb, 0x2c, 0x5c, 0x22, 0x30, 0xf7, 0xfe,
+ 0x45, 0x52, 0xa8, 0x1f, 0x21, 0xc1, 0xc8, 0x7c, 0xdf, 0xed, 0xf3, 0x9f,
+ 0xe9, 0xa3, 0xd6, 0x2f, 0x0b, 0x06, 0xb1, 0x4c, 0x7a, 0xd1, 0xc7, 0x35,
+ 0x06, 0xc6, 0x64, 0x73, 0xb9, 0x98, 0x8a, 0x6b, 0xe6, 0xf1, 0x8b, 0xc7,
+ 0x97, 0x6a, 0x3d, 0x9f, 0xcb, 0x0f, 0x03, 0xe9, 0x43, 0x83, 0x92, 0xb3,
+ 0xbb, 0x42, 0x42, 0xff, 0x4b, 0x6b, 0xe1, 0x30, 0xd6, 0x2e, 0xc8, 0x2c,
+ 0x5e, 0x71, 0xca, 0xc5, 0x0c, 0xf9, 0xe2, 0x34, 0x38, 0xbd, 0xff, 0xd0,
+ 0x93, 0xea, 0x46, 0xde, 0x14, 0xac, 0x5f, 0xcf, 0xfd, 0x69, 0xf6, 0x58,
+ 0xa9, 0x45, 0x1b, 0x98, 0x7d, 0x12, 0xe0, 0xbc, 0xb1, 0x7c, 0xfc, 0xc3,
+ 0xac, 0x5f, 0xfc, 0x42, 0xce, 0x3f, 0x33, 0xf9, 0xba, 0xc5, 0xfb, 0x47,
+ 0x66, 0x1a, 0xc5, 0xff, 0xf9, 0x8e, 0x67, 0x05, 0x3d, 0x67, 0xb9, 0x93,
+ 0xba, 0xc5, 0x62, 0x20, 0x3e, 0x51, 0x7f, 0xf3, 0xbf, 0xe2, 0xcf, 0x4f,
+ 0xa4, 0x6b, 0x17, 0x8d, 0x6e, 0x2c, 0x5e, 0x9d, 0x01, 0x62, 0xd3, 0xe3,
+ 0x76, 0x18, 0xf5, 0xf7, 0xbd, 0x20, 0x58, 0xbe, 0x0c, 0xd0, 0xcd, 0x58,
+ 0xb4, 0xac, 0x5f, 0xff, 0x4f, 0x50, 0x62, 0x01, 0x80, 0x7d, 0x39, 0xab,
+ 0x15, 0x2a, 0x9d, 0x60, 0x33, 0x84, 0x4f, 0x0c, 0x48, 0x88, 0xbe, 0xfe,
+ 0x22, 0x70, 0x88, 0xe3, 0x8a, 0x3b, 0x84, 0x6f, 0xe8, 0x67, 0x9c, 0xa5,
+ 0x62, 0xfe, 0xea, 0x2f, 0xc9, 0x1a, 0xb1, 0x7f, 0xfa, 0x75, 0xac, 0xeb,
+ 0xd2, 0x79, 0xea, 0x0b, 0x15, 0x27, 0xfa, 0x11, 0x8d, 0xc5, 0x12, 0xc5,
+ 0xee, 0x7d, 0xd6, 0x28, 0xe6, 0xd7, 0xc3, 0x17, 0x74, 0xcb, 0x17, 0xff,
+ 0x60, 0xe7, 0xef, 0x06, 0x84, 0xe9, 0x62, 0xb0, 0xf6, 0xf4, 0x31, 0x7d,
+ 0xb1, 0xde, 0x0b, 0x17, 0xfe, 0x29, 0x3b, 0x38, 0xc5, 0xee, 0x2c, 0x5f,
+ 0x48, 0x03, 0x3a, 0xc5, 0xff, 0xa7, 0xdf, 0x9e, 0x4c, 0x05, 0xa5, 0x8b,
+ 0xe2, 0x13, 0x41, 0x62, 0xe6, 0x35, 0x62, 0xa0, 0x8d, 0xbd, 0xcf, 0x88,
+ 0x93, 0x87, 0xfe, 0x22, 0xbf, 0xa4, 0x5b, 0xfd, 0xf4, 0xb1, 0x7f, 0x49,
+ 0xe3, 0x00, 0x09, 0x58, 0xbd, 0xdf, 0xcf, 0x96, 0x2f, 0xe6, 0xdc, 0xc9,
+ 0xce, 0x2c, 0x5f, 0xa7, 0x0b, 0xdc, 0x58, 0xa1, 0x9e, 0xb1, 0xcb, 0xe8,
+ 0xe8, 0xfa, 0xf9, 0x78, 0x8c, 0x7b, 0x9e, 0x2f, 0x02, 0x74, 0xb1, 0x52,
+ 0xaa, 0x83, 0x21, 0xfe, 0xf1, 0xa2, 0x32, 0x05, 0xf7, 0x9c, 0xa0, 0xb1,
+ 0x7e, 0x7f, 0xfb, 0x37, 0x58, 0xbd, 0x84, 0x05, 0x8a, 0x81, 0xf3, 0xc4,
+ 0x45, 0xdc, 0x53, 0x7b, 0x82, 0x3a, 0xc5, 0xff, 0xef, 0xc9, 0xe4, 0x5d,
+ 0x4b, 0x96, 0x1a, 0xb1, 0x7e, 0x98, 0xb9, 0xe7, 0x58, 0xa3, 0x17, 0x6b,
+ 0xa6, 0x15, 0x38, 0xae, 0xef, 0x9a, 0x95, 0x82, 0xd0, 0xad, 0x01, 0x9f,
+ 0x87, 0x83, 0x4a, 0xbf, 0xff, 0xa7, 0x53, 0xcf, 0xb3, 0xfa, 0x02, 0x92,
+ 0x98, 0x2c, 0x5f, 0xe1, 0x87, 0x31, 0xff, 0x17, 0x16, 0x2f, 0xa7, 0xaf,
+ 0x3a, 0xc5, 0xfb, 0xb9, 0xcf, 0x9e, 0x58, 0xbf, 0x7b, 0x3c, 0x52, 0xb1,
+ 0x7f, 0x3c, 0xf0, 0xc2, 0x75, 0x8a, 0xd9, 0x33, 0x4e, 0x96, 0x62, 0x39,
+ 0x39, 0x19, 0x15, 0xf8, 0x9e, 0xf0, 0x9b, 0x8b, 0x17, 0x48, 0x4b, 0x15,
+ 0xa3, 0x6b, 0xc1, 0xdb, 0xff, 0x9f, 0x8c, 0x17, 0x8c, 0xe4, 0x1c, 0xd5,
+ 0x8b, 0xfd, 0x25, 0xb6, 0x0d, 0xa0, 0xb1, 0x7f, 0xbf, 0x99, 0xef, 0xb0,
+ 0x16, 0x2d, 0xf5, 0x8a, 0x81, 0xe2, 0xb1, 0x9d, 0xe7, 0xda, 0x56, 0x2e,
+ 0x8a, 0x56, 0x2e, 0x9f, 0x2c, 0x5f, 0xa4, 0xc0, 0xe2, 0xe2, 0xc5, 0xe6,
+ 0xed, 0x2b, 0x15, 0x27, 0xf2, 0x68, 0xc1, 0x0b, 0xf8, 0xb2, 0xf8, 0x78,
+ 0x50, 0x58, 0xbf, 0x63, 0xc3, 0xf2, 0xb1, 0x74, 0x5e, 0x73, 0xc9, 0xf9,
+ 0x15, 0xff, 0xf8, 0x7f, 0x9d, 0x38, 0x24, 0x39, 0x88, 0xa4, 0xeb, 0x17,
+ 0xf8, 0xd9, 0x2f, 0x71, 0xbe, 0xb1, 0x52, 0x8b, 0x87, 0x2e, 0x65, 0x6b,
+ 0xf1, 0x63, 0x16, 0xcb, 0x17, 0xff, 0x9b, 0xcf, 0xd1, 0x80, 0x13, 0x16,
+ 0xfc, 0x58, 0xbf, 0x71, 0xa5, 0xf4, 0xb1, 0x77, 0x47, 0x58, 0xa1, 0xa2,
+ 0x37, 0xa4, 0xd8, 0xf2, 0x7a, 0x95, 0xc7, 0x8c, 0x84, 0x7e, 0xe4, 0x3d,
+ 0x24, 0x3b, 0xc6, 0x88, 0x5a, 0x12, 0xc5, 0x19, 0xe7, 0x0b, 0x45, 0x0b,
+ 0x4a, 0x58, 0xbb, 0x34, 0xb1, 0x46, 0x9a, 0x36, 0x0c, 0xbf, 0xec, 0xe4,
+ 0x8f, 0x92, 0xe3, 0x58, 0xbf, 0xa7, 0x6d, 0x4e, 0x0d, 0x62, 0xff, 0xd8,
+ 0x7e, 0x7e, 0x7a, 0xf4, 0xfd, 0x62, 0xff, 0xfe, 0x8f, 0x72, 0x93, 0x99,
+ 0xc7, 0xda, 0x7f, 0xf9, 0x82, 0xc5, 0xe6, 0x8a, 0x56, 0x2f, 0xef, 0xcf,
+ 0xbd, 0x27, 0x58, 0xbf, 0xff, 0xb5, 0x83, 0xe1, 0x0b, 0x20, 0x26, 0x1f,
+ 0x33, 0x4b, 0x14, 0x34, 0x44, 0xb9, 0x75, 0x69, 0x3e, 0xe3, 0x90, 0xfc,
+ 0xe3, 0xc5, 0xc2, 0x40, 0xec, 0xbe, 0x1c, 0x29, 0xaf, 0x8a, 0x4f, 0xc5,
+ 0x8b, 0xc7, 0x6e, 0x96, 0x3c, 0x68, 0xae, 0xf6, 0xeb, 0x17, 0xcf, 0xa0,
+ 0x71, 0x62, 0xb0, 0xfa, 0xb4, 0x5d, 0xe1, 0x9b, 0xf8, 0xa4, 0xc0, 0x02,
+ 0x56, 0x2f, 0x98, 0x13, 0x05, 0x8b, 0xe0, 0x76, 0xef, 0x7b, 0xc5, 0x8b,
+ 0xfe, 0x3e, 0x42, 0x74, 0x0c, 0x25, 0x8b, 0x43, 0xe7, 0xd0, 0x19, 0x85,
+ 0xfc, 0xc5, 0x3f, 0xfc, 0xac, 0x5f, 0xda, 0x69, 0x84, 0xc1, 0x62, 0xff,
+ 0xfd, 0x30, 0xe7, 0xd9, 0xfd, 0x01, 0x49, 0x4c, 0x16, 0x2f, 0xe9, 0xdf,
+ 0x8f, 0x27, 0x58, 0xa2, 0x44, 0x17, 0x15, 0x2a, 0x51, 0xa2, 0xd0, 0xaf,
+ 0xb8, 0x44, 0xb1, 0x76, 0x6e, 0xb1, 0x74, 0xc3, 0xe6, 0xbf, 0xc2, 0xf5,
+ 0xd2, 0x74, 0xf1, 0x14, 0xea, 0x1f, 0xa4, 0xab, 0x7d, 0x25, 0x31, 0x2c,
+ 0x5f, 0xff, 0xfb, 0x1f, 0xb4, 0xe7, 0xe5, 0xf5, 0x3e, 0x7c, 0x39, 0xe4,
+ 0xeb, 0x17, 0xff, 0xff, 0xec, 0x81, 0x4e, 0xd9, 0xcf, 0xe1, 0x31, 0xad,
+ 0xbb, 0x69, 0xa0, 0xfc, 0x02, 0xc5, 0xff, 0xec, 0xed, 0xbb, 0x6b, 0x66,
+ 0xf3, 0x74, 0x05, 0x8a, 0xd2, 0x34, 0x4a, 0x10, 0x57, 0xff, 0xb0, 0x6c,
+ 0x4f, 0x83, 0x97, 0x6d, 0x96, 0x29, 0x62, 0xd9, 0xb1, 0xe9, 0xba, 0x3d,
+ 0xfe, 0xc1, 0xbf, 0x02, 0x6d, 0x2c, 0x54, 0xae, 0xfe, 0x0e, 0x1f, 0x38,
+ 0x5d, 0xb9, 0x73, 0xca, 0x31, 0x3a, 0x27, 0xc8, 0x9a, 0x33, 0xb2, 0x7a,
+ 0xf1, 0x3d, 0xfe, 0x26, 0xdb, 0xa8, 0x4f, 0x72, 0xc5, 0xf8, 0x13, 0x9d,
+ 0x41, 0x62, 0xff, 0x73, 0xec, 0x1f, 0xe6, 0x0b, 0x15, 0xb2, 0x25, 0xb7,
+ 0x38, 0xe8, 0xa6, 0xff, 0x7e, 0x4f, 0xe2, 0x9e, 0x96, 0x2e, 0xc8, 0x96,
+ 0x2f, 0xc4, 0xd0, 0xc2, 0x58, 0xbf, 0x89, 0xbe, 0x59, 0xa5, 0x8b, 0xc4,
+ 0x2c, 0x19, 0xe9, 0x78, 0x9a, 0xff, 0xb0, 0xf9, 0xd8, 0x51, 0xf8, 0x4b,
+ 0x17, 0xd3, 0xd4, 0x76, 0x2c, 0x5f, 0xf9, 0xba, 0xfc, 0xb8, 0x1b, 0xc2,
+ 0x58, 0xbf, 0xff, 0xd2, 0xf0, 0x6e, 0x72, 0x70, 0xa6, 0x18, 0x76, 0xe9,
+ 0x62, 0xb4, 0x8c, 0x33, 0x93, 0x78, 0xfe, 0xff, 0xd8, 0x0e, 0x66, 0xb6,
+ 0xd8, 0x5b, 0x2c, 0x50, 0xd3, 0x73, 0xc8, 0xc0, 0x3c, 0x61, 0x50, 0x54,
+ 0xf3, 0x86, 0x8c, 0xd5, 0xc8, 0xe9, 0x6f, 0xff, 0x8e, 0xda, 0x68, 0x4b,
+ 0xe9, 0xe1, 0x90, 0x58, 0xbf, 0x7e, 0x62, 0x7f, 0xac, 0x5c, 0xf0, 0x58,
+ 0xa1, 0x9e, 0x01, 0x14, 0xde, 0xe4, 0xc4, 0xb1, 0x7d, 0xb6, 0x75, 0x05,
+ 0x8b, 0x44, 0xb1, 0x52, 0x7a, 0xd8, 0x3c, 0x19, 0x2d, 0xfe, 0x3b, 0x16,
+ 0x68, 0x3f, 0x2c, 0x5f, 0xcd, 0x9b, 0x0b, 0x50, 0x58, 0xbf, 0xfe, 0xfc,
+ 0x9d, 0xf4, 0xfd, 0xd2, 0x1e, 0xd8, 0x12, 0xc5, 0xfa, 0x60, 0x77, 0xf2,
+ 0xc5, 0xff, 0x0e, 0x43, 0x39, 0x4f, 0x50, 0x58, 0xa5, 0x8a, 0xc3, 0xc7,
+ 0x73, 0xbb, 0xfb, 0x05, 0xb8, 0x79, 0xd2, 0xc5, 0x6c, 0xaa, 0xae, 0x10,
+ 0x8e, 0x1b, 0xbe, 0x17, 0x74, 0x69, 0x11, 0x79, 0xd5, 0x78, 0xdf, 0xd8,
+ 0x82, 0xff, 0xb5, 0x3c, 0x0c, 0x8a, 0x74, 0xb1, 0x73, 0x47, 0x2c, 0x53,
+ 0x9e, 0x99, 0xce, 0x6f, 0xef, 0xcf, 0xbf, 0x80, 0x58, 0xbf, 0xff, 0xe2,
+ 0x9d, 0xb0, 0x73, 0x0f, 0xe7, 0xda, 0x3d, 0xe3, 0xe7, 0x4b, 0x17, 0xfa,
+ 0x62, 0x17, 0x45, 0x31, 0x2c, 0x5f, 0xf4, 0xc0, 0x9b, 0xd0, 0x7e, 0xcb,
+ 0x17, 0x83, 0x90, 0x2c, 0x5e, 0xee, 0x7d, 0x96, 0x2b, 0x64, 0xc6, 0x8e,
+ 0xd7, 0xf3, 0x6e, 0x1d, 0x78, 0x7a, 0xfb, 0xdf, 0x9e, 0xe5, 0x8a, 0x58,
+ 0xb9, 0xe2, 0x58, 0xa8, 0xf3, 0x48, 0x00, 0xcb, 0xfe, 0x36, 0x49, 0x87,
+ 0xf9, 0x02, 0xc5, 0xff, 0x64, 0x45, 0x3b, 0x72, 0x77, 0x58, 0xba, 0x18,
+ 0xb1, 0x5a, 0x44, 0x5f, 0xce, 0x7c, 0x77, 0x77, 0x31, 0x62, 0xfd, 0x31,
+ 0x3c, 0xf1, 0x62, 0xfe, 0x90, 0xf0, 0xed, 0xd2, 0xc5, 0xff, 0xa7, 0x5b,
+ 0xf8, 0xb3, 0x66, 0x25, 0x8b, 0xe0, 0x3c, 0xf1, 0x62, 0xff, 0xfb, 0x3d,
+ 0xc9, 0x80, 0xd8, 0x18, 0x37, 0xe2, 0xc5, 0x7d, 0x1b, 0xfc, 0x2f, 0x11,
+ 0xfc, 0x71, 0x15, 0xff, 0x4f, 0x1b, 0x77, 0x1f, 0xdd, 0x62, 0xff, 0x0f,
+ 0x58, 0x2d, 0xdc, 0xeb, 0x17, 0xec, 0x16, 0xee, 0x75, 0x8b, 0xdf, 0x17,
+ 0xd6, 0x2c, 0x7c, 0x3f, 0xcd, 0x1a, 0xb1, 0x4d, 0xfe, 0x14, 0x0b, 0x00,
+ 0xfd, 0x2c, 0x5f, 0xec, 0xec, 0xc4, 0x3c, 0x02, 0xc5, 0x68, 0xfa, 0x3e,
+ 0x69, 0x51, 0x26, 0xe4, 0xd0, 0xb5, 0xf4, 0x26, 0xed, 0xf5, 0x8a, 0x95,
+ 0xed, 0x7d, 0xa1, 0xb8, 0x32, 0x1c, 0x8d, 0x23, 0xa4, 0xc7, 0x4a, 0x68,
+ 0x57, 0x80, 0xc0, 0x85, 0xfd, 0x18, 0x38, 0xa3, 0xb2, 0x08, 0xee, 0xd8,
+ 0xb1, 0x7f, 0xd1, 0x72, 0x70, 0x87, 0xf9, 0x58, 0xb1, 0xd6, 0x28, 0x8f,
+ 0x2f, 0xc7, 0x37, 0xf3, 0x99, 0xc7, 0x27, 0x58, 0xbf, 0x9b, 0x34, 0x00,
+ 0x4a, 0xc5, 0xf7, 0xdd, 0xa0, 0xb1, 0x7f, 0xff, 0xfc, 0x59, 0x01, 0x6a,
+ 0x75, 0xac, 0x1c, 0xb9, 0xb2, 0x5b, 0xb7, 0x98, 0xd5, 0x8a, 0xc4, 0x4f,
+ 0xb1, 0x15, 0xf7, 0x3a, 0x2d, 0x2c, 0x5f, 0xed, 0x67, 0xdc, 0xa4, 0xeb,
+ 0x17, 0xff, 0x4c, 0x7f, 0xcb, 0x3a, 0xf0, 0x9b, 0x8b, 0x17, 0xf4, 0xb6,
+ 0xbd, 0x9f, 0x58, 0xbf, 0xf8, 0xb2, 0x29, 0xd9, 0xb6, 0x3b, 0xec, 0xb1,
+ 0x7e, 0xc3, 0x74, 0xc1, 0x2c, 0x5b, 0x1c, 0xfc, 0x43, 0x47, 0xbf, 0xfc,
+ 0x7c, 0x1c, 0xc2, 0x78, 0x06, 0x6e, 0x96, 0x2a, 0x53, 0x89, 0x39, 0x97,
+ 0xd2, 0x39, 0x09, 0xe0, 0xc9, 0xe8, 0xc5, 0x72, 0x92, 0xb9, 0xf2, 0x16,
+ 0x2d, 0xe4, 0x33, 0x3c, 0x42, 0x28, 0xeb, 0x6f, 0xfb, 0xcd, 0xcc, 0xff,
+ 0xdc, 0xeb, 0x17, 0x7f, 0x8b, 0x17, 0xd9, 0xdb, 0x09, 0x62, 0xff, 0x73,
+ 0x1c, 0x6c, 0xfb, 0x2c, 0x54, 0x9e, 0xb6, 0x11, 0xdf, 0xf8, 0x98, 0x18,
+ 0x5e, 0xe3, 0x41, 0x62, 0xa5, 0x30, 0x43, 0x4e, 0x74, 0xdd, 0xe2, 0x0b,
+ 0xf1, 0x4e, 0xd3, 0xb2, 0xc5, 0xff, 0xde, 0xe0, 0x7e, 0x72, 0x14, 0x33,
+ 0x8b, 0x14, 0x34, 0x56, 0xc4, 0x7c, 0x45, 0x37, 0xf0, 0xe5, 0xb4, 0x01,
+ 0x2c, 0x5f, 0xd2, 0x40, 0x3b, 0x41, 0x62, 0xdf, 0x58, 0xbc, 0x5d, 0x79,
+ 0x62, 0xb0, 0xd8, 0x38, 0x95, 0x6c, 0x8a, 0xaf, 0x97, 0x76, 0x5d, 0xbe,
+ 0x67, 0xd6, 0x2c, 0x5f, 0xe6, 0x7e, 0x3f, 0x6f, 0xba, 0xc5, 0x68, 0xf5,
+ 0x7e, 0x43, 0x7f, 0x60, 0xc0, 0xe5, 0xe5, 0x8b, 0xf7, 0xe7, 0x35, 0x05,
+ 0x8b, 0xff, 0x8e, 0xe0, 0x6f, 0x16, 0x6d, 0xa9, 0x58, 0xa5, 0x8b, 0x63,
+ 0x9e, 0x87, 0x91, 0x2f, 0x7f, 0xce, 0xb1, 0x7f, 0xfd, 0x9b, 0x6a, 0x43,
+ 0x1b, 0x6d, 0x87, 0x6e, 0x96, 0x2f, 0xb9, 0xec, 0x3a, 0xc5, 0xfb, 0x3b,
+ 0x16, 0x41, 0x62, 0xe1, 0x7d, 0x62, 0xa3, 0xcf, 0x04, 0xe5, 0x37, 0xe8,
+ 0x07, 0xfc, 0xee, 0x58, 0xb9, 0xe2, 0x58, 0xa9, 0x46, 0x73, 0xb2, 0x31,
+ 0x2f, 0x8b, 0x6f, 0x7f, 0xf2, 0xb1, 0x7f, 0x1a, 0xd0, 0xe3, 0x8d, 0x62,
+ 0xb0, 0xf3, 0x1c, 0x76, 0xa5, 0x70, 0xcf, 0x21, 0xb4, 0xf0, 0x88, 0xd1,
+ 0x11, 0xcb, 0x7e, 0xf0, 0xc4, 0xc4, 0x3b, 0xc8, 0xc8, 0x7d, 0x08, 0x6b,
+ 0x85, 0x05, 0x8b, 0xfb, 0xef, 0xad, 0x67, 0x96, 0x2f, 0xff, 0xdc, 0x68,
+ 0xf1, 0xfe, 0x71, 0xf5, 0x3e, 0x9f, 0xac, 0x56, 0xc8, 0x9d, 0xdc, 0x63,
+ 0xa2, 0xeb, 0xe6, 0x3c, 0xc7, 0xac, 0x5e, 0x1c, 0xc1, 0x62, 0xe7, 0xe7,
+ 0xcf, 0x08, 0x44, 0xb7, 0x4c, 0x16, 0x2f, 0xfe, 0x83, 0xf6, 0x9d, 0x63,
+ 0xc0, 0x5a, 0x58, 0xbe, 0x90, 0x73, 0x16, 0x2f, 0xcf, 0xdd, 0x1e, 0xc7,
+ 0x58, 0xa8, 0x91, 0x2d, 0xf4, 0x6e, 0x11, 0x5c, 0x28, 0x2c, 0x56, 0x93,
+ 0x23, 0xf9, 0x6b, 0x42, 0xb7, 0xb1, 0x8d, 0xe3, 0xcc, 0xac, 0x5f, 0x8e,
+ 0xc5, 0xd4, 0x16, 0x2e, 0x68, 0x2c, 0x5f, 0x8b, 0xd1, 0xd2, 0x75, 0x8a,
+ 0x93, 0xeb, 0x62, 0x91, 0x0b, 0xde, 0x70, 0xb7, 0x58, 0xbd, 0xdf, 0x7d,
+ 0xf2, 0x34, 0x58, 0xbd, 0x83, 0xc5, 0x8b, 0xde, 0x70, 0x2c, 0x54, 0x7a,
+ 0x22, 0x0e, 0x3f, 0xf3, 0x0f, 0x0e, 0x5f, 0xb4, 0x3c, 0x23, 0x56, 0x2d,
+ 0x05, 0x8b, 0xff, 0x4f, 0xc4, 0xc1, 0xe7, 0x66, 0xd2, 0xc5, 0x39, 0xe9,
+ 0xf0, 0x4a, 0xf3, 0x90, 0xd6, 0x2a, 0x51, 0xf2, 0xc8, 0x1e, 0x7c, 0xec,
+ 0x43, 0x7f, 0xf8, 0x1f, 0x09, 0xbc, 0xfc, 0xfc, 0x97, 0x96, 0x2d, 0x12,
+ 0xc5, 0xe9, 0x29, 0x58, 0xad, 0x1f, 0xc8, 0x92, 0xc2, 0x13, 0xbf, 0xc7,
+ 0xe3, 0xc7, 0x66, 0xa5, 0x62, 0xe3, 0xe9, 0x62, 0xf1, 0xa7, 0x75, 0x8a,
+ 0xc3, 0x6c, 0xc3, 0x17, 0x9c, 0xee, 0xb1, 0x52, 0x8d, 0x7c, 0x30, 0x26,
+ 0xcf, 0x0f, 0xd7, 0x78, 0xfc, 0x1f, 0x1d, 0xf7, 0x0c, 0xc8, 0xd6, 0x53,
+ 0x32, 0x86, 0x76, 0x8c, 0xce, 0x13, 0xb1, 0xc3, 0x9e, 0x65, 0xc9, 0x4a,
+ 0x5b, 0xca, 0x81, 0xea, 0x30, 0x47, 0xac, 0x75, 0xe3, 0xe3, 0xe5, 0x8a,
+ 0x55, 0x1e, 0xa7, 0x91, 0x4f, 0x3c, 0x79, 0xfa, 0x45, 0x6b, 0x46, 0x64,
+ 0x09, 0x55, 0x85, 0x49, 0xc5, 0xe4, 0xe2, 0xb7, 0xa7, 0x95, 0x05, 0x19,
+ 0xdf, 0x68, 0xe6, 0x02, 0x44, 0x8e, 0x84, 0x38, 0x71, 0xd7, 0x77, 0x47,
+ 0x1b, 0x67, 0x58, 0xb8, 0xc0, 0x2c, 0x51, 0x86, 0xab, 0x82, 0x37, 0x1b,
+ 0xe5, 0x8b, 0xff, 0xfd, 0x1b, 0x4e, 0x77, 0xd7, 0x51, 0xb4, 0x6a, 0xed,
+ 0x1f, 0x1a, 0xc4, 0x61, 0x9f, 0x8e, 0x58, 0xb7, 0x78, 0xb1, 0x5d, 0xf1,
+ 0x14, 0x71, 0x42, 0x32, 0xe7, 0x35, 0x62, 0xfe, 0x07, 0x22, 0x29, 0x1a,
+ 0xc5, 0xff, 0x76, 0xc1, 0xf5, 0xe2, 0xc0, 0x2c, 0x54, 0x9f, 0x5b, 0x97,
+ 0xdf, 0xf9, 0xf4, 0x79, 0xc2, 0x18, 0x67, 0x58, 0xa8, 0x1e, 0xf9, 0xa4,
+ 0x17, 0xbc, 0xc1, 0xac, 0x5c, 0x19, 0xd6, 0x2f, 0x7f, 0x3c, 0xb1, 0x51,
+ 0x1b, 0x60, 0x0c, 0xdf, 0xf6, 0x7b, 0x99, 0xef, 0xe0, 0x16, 0x2f, 0xf1,
+ 0x92, 0x61, 0xdc, 0xbc, 0xb1, 0x7f, 0x9c, 0xd6, 0x2f, 0x61, 0x2c, 0x5f,
+ 0xe6, 0x35, 0xf9, 0xc6, 0x75, 0x8a, 0x82, 0xa4, 0xec, 0x87, 0x13, 0x91,
+ 0xb2, 0xa1, 0x11, 0x70, 0xe7, 0xc6, 0xbd, 0x8c, 0xae, 0x62, 0x58, 0xbf,
+ 0xf6, 0x6f, 0x20, 0x92, 0xf4, 0x76, 0x2c, 0x56, 0x91, 0x9a, 0x77, 0x6f,
+ 0x0b, 0x5d, 0x81, 0x2c, 0x58, 0xeb, 0x14, 0x61, 0xaa, 0x0c, 0x62, 0xfb,
+ 0x3e, 0xdd, 0xcb, 0x17, 0xbd, 0x87, 0x58, 0xbd, 0x38, 0x4b, 0x17, 0xe6,
+ 0xd0, 0x23, 0xb1, 0x62, 0xa0, 0x78, 0xce, 0x37, 0x52, 0x88, 0x4f, 0x31,
+ 0xdf, 0xbd, 0x24, 0xe0, 0x58, 0xbb, 0xae, 0x96, 0x2e, 0x33, 0x8b, 0x17,
+ 0xed, 0x0b, 0xb0, 0x02, 0x58, 0xb8, 0xb8, 0xb1, 0x7e, 0x09, 0x80, 0x7c,
+ 0x58, 0xb7, 0x16, 0x2b, 0x0d, 0xd9, 0x14, 0xdd, 0x90, 0x58, 0xbf, 0x8b,
+ 0x3c, 0x26, 0x09, 0x62, 0x8c, 0x4d, 0x7f, 0x08, 0xba, 0x27, 0x38, 0xd7,
+ 0xc6, 0x40, 0x5a, 0x4a, 0x5c, 0x1f, 0xec, 0x2f, 0x7e, 0xf7, 0x1f, 0xa0,
+ 0x96, 0x2f, 0xfd, 0x27, 0x7e, 0xb8, 0x28, 0x84, 0x6a, 0xc5, 0xf8, 0xbd,
+ 0xfc, 0x82, 0xc5, 0xdc, 0xc5, 0x8a, 0x73, 0x7e, 0xc5, 0x16, 0xe9, 0x62,
+ 0xfe, 0x90, 0xa3, 0xb3, 0x52, 0xb1, 0x58, 0x78, 0x84, 0x27, 0x7f, 0xfd,
+ 0xd9, 0xf5, 0x80, 0x68, 0x71, 0xcb, 0x00, 0xb1, 0x7e, 0x6c, 0x00, 0x7e,
+ 0x58, 0xbf, 0xbe, 0xc3, 0x61, 0x74, 0xb1, 0x7f, 0xe1, 0x3f, 0xff, 0x9a,
+ 0xd3, 0x9d, 0x62, 0xf0, 0xe7, 0xb9, 0x62, 0xfb, 0xee, 0xd1, 0xeb, 0x14,
+ 0x47, 0x8b, 0xe2, 0x0a, 0x31, 0x52, 0x94, 0x21, 0x04, 0x36, 0x3c, 0x20,
+ 0x35, 0x43, 0x72, 0x93, 0x97, 0xb4, 0x21, 0x2b, 0x4a, 0xbe, 0xc2, 0x94,
+ 0xfb, 0x7e, 0xdd, 0xc1, 0x1c, 0x6a, 0xc5, 0xf6, 0xd3, 0xee, 0x2c, 0x5e,
+ 0x90, 0x71, 0x62, 0xb4, 0x78, 0x24, 0x49, 0x7c, 0xda, 0x68, 0x2c, 0x56,
+ 0x1e, 0x19, 0x10, 0xdb, 0xcb, 0x17, 0xb9, 0x20, 0x58, 0xb6, 0x74, 0x6b,
+ 0xfc, 0x25, 0x46, 0x26, 0x51, 0xa8, 0x59, 0x7d, 0x3e, 0xff, 0xd2, 0x17,
+ 0x50, 0xe3, 0x7f, 0x22, 0x58, 0xbe, 0x1f, 0x6d, 0x6c, 0xb1, 0x78, 0x20,
+ 0x82, 0x58, 0xbc, 0x4f, 0x29, 0x11, 0x86, 0x86, 0xf1, 0xdc, 0x6b, 0x17,
+ 0xff, 0xff, 0x8c, 0xfc, 0x36, 0xe4, 0x8b, 0x8e, 0x76, 0x3c, 0xb0, 0x66,
+ 0x19, 0xf8, 0xe5, 0x8a, 0xd9, 0x19, 0x8c, 0x5c, 0x18, 0xed, 0xfd, 0xf9,
+ 0xf9, 0x61, 0xab, 0x17, 0x84, 0x5e, 0x58, 0xbf, 0x98, 0xa0, 0x39, 0xd9,
+ 0x62, 0xb0, 0xf2, 0xfe, 0x3b, 0x7f, 0xcc, 0xdf, 0x66, 0x66, 0x1a, 0xc5,
+ 0x0d, 0x1a, 0x11, 0xef, 0x2c, 0x43, 0x7b, 0x21, 0x2b, 0x17, 0xff, 0xd0,
+ 0x7f, 0x42, 0x48, 0x0c, 0x4f, 0xd4, 0x16, 0x2b, 0x47, 0xd6, 0x10, 0xe5,
+ 0xf3, 0x7a, 0x46, 0xb1, 0x7b, 0x0b, 0x75, 0x8b, 0xd1, 0x3f, 0xd6, 0x2e,
+ 0xea, 0x0b, 0x17, 0xfb, 0x5b, 0x4e, 0x44, 0xfa, 0x58, 0xbf, 0xc6, 0xcf,
+ 0xb9, 0xf6, 0x12, 0xc5, 0xc7, 0x95, 0x8b, 0xf7, 0xdc, 0xba, 0xe2, 0xc5,
+ 0xfa, 0x5e, 0x0d, 0xc5, 0x8b, 0xed, 0xb3, 0xaf, 0x2c, 0x5f, 0x39, 0xad,
+ 0xe5, 0x8a, 0x73, 0xc8, 0xd1, 0x2d, 0xa2, 0x58, 0xbd, 0x80, 0xe2, 0xc5,
+ 0x49, 0xb0, 0x21, 0x3b, 0xfc, 0xdf, 0x2c, 0xec, 0xdb, 0xac, 0x5c, 0xde,
+ 0x58, 0xbd, 0xa9, 0x09, 0x62, 0x96, 0x2b, 0x46, 0xa8, 0x03, 0xd6, 0xdd,
+ 0x62, 0xfc, 0x1e, 0xb0, 0x43, 0x58, 0xac, 0x3d, 0xe7, 0x21, 0xe0, 0x9d,
+ 0x4a, 0xaa, 0x3c, 0x19, 0x34, 0xd5, 0xcd, 0x62, 0x17, 0xd1, 0x49, 0xdb,
+ 0xd9, 0x44, 0x87, 0xf8, 0x6b, 0xe8, 0x4f, 0xdf, 0x3f, 0xc5, 0x05, 0x8b,
+ 0xbf, 0x2b, 0x17, 0xcf, 0xf1, 0x40, 0xc3, 0x75, 0x84, 0x77, 0xf7, 0x1f,
+ 0x5b, 0xff, 0x16, 0x2f, 0xb0, 0x6f, 0x05, 0x8b, 0xfc, 0xff, 0xfe, 0x79,
+ 0xf8, 0xb1, 0x68, 0x18, 0x8b, 0xce, 0x8e, 0x08, 0xbf, 0x84, 0x57, 0xec,
+ 0xef, 0x49, 0xc6, 0xb1, 0x7c, 0xdc, 0xed, 0x05, 0x8b, 0xb0, 0x6b, 0x14,
+ 0x69, 0xbc, 0xec, 0x4b, 0x50, 0x5d, 0x23, 0xea, 0x56, 0x0e, 0xa3, 0x92,
+ 0x02, 0x27, 0x9a, 0x2f, 0xcc, 0x50, 0x73, 0xac, 0x5e, 0xc1, 0x47, 0x2c,
+ 0x51, 0x8d, 0xa6, 0x87, 0x7a, 0x45, 0x1a, 0xa1, 0x79, 0x32, 0xd2, 0xb6,
+ 0x5a, 0x81, 0x18, 0xe5, 0x04, 0x64, 0xb7, 0xc7, 0x8d, 0x57, 0x46, 0xe7,
+ 0x42, 0xfc, 0x62, 0x8d, 0x18, 0x08, 0x21, 0x3a, 0x44, 0x7c, 0x22, 0x14,
+ 0xea, 0x07, 0x65, 0xb8, 0xe2, 0x7b, 0xdd, 0xe7, 0x7d, 0xc6, 0xeb, 0x17,
+ 0xfd, 0xf6, 0x88, 0xa7, 0x35, 0x05, 0x8b, 0xfc, 0x19, 0xf0, 0x72, 0x5b,
+ 0xac, 0x5f, 0xf9, 0x88, 0x38, 0xb8, 0xe5, 0xd4, 0x16, 0x2f, 0xfc, 0x16,
+ 0x70, 0x9e, 0x75, 0x9b, 0x2c, 0x54, 0x7a, 0x3b, 0x8e, 0x72, 0x23, 0x5e,
+ 0xc8, 0x37, 0xc2, 0xda, 0x62, 0x58, 0xbf, 0xff, 0xff, 0xe3, 0x3f, 0x9d,
+ 0x43, 0xe7, 0x33, 0x7f, 0x8b, 0xde, 0xc2, 0xfe, 0x7a, 0x46, 0x61, 0x9f,
+ 0x8e, 0x58, 0xa9, 0x46, 0x2c, 0x79, 0x2d, 0xee, 0xfb, 0x8d, 0x5d, 0xea,
+ 0xc5, 0xfd, 0xbf, 0xd8, 0x2e, 0xb8, 0xb1, 0x7e, 0x1b, 0xfb, 0x37, 0x58,
+ 0xa8, 0xd6, 0x88, 0xb9, 0x30, 0x39, 0x95, 0xec, 0x8b, 0x16, 0x2f, 0xc5,
+ 0x3a, 0x6e, 0x2c, 0x5f, 0xf0, 0xf0, 0x5d, 0xfb, 0xfd, 0x8e, 0xb1, 0x7c,
+ 0x72, 0xc8, 0x96, 0x30, 0xdf, 0x5f, 0xa1, 0x84, 0xd0, 0x58, 0xa9, 0x3d,
+ 0x96, 0x32, 0xbf, 0xe1, 0xfe, 0x73, 0x0e, 0xf2, 0xb1, 0x78, 0x19, 0xc5,
+ 0x8b, 0xe6, 0xe8, 0xfd, 0x2c, 0x50, 0x0f, 0x0b, 0xc3, 0xb5, 0x28, 0x9b,
+ 0xc7, 0x9b, 0xc3, 0x98, 0x96, 0x2f, 0x7d, 0xfe, 0xb1, 0x70, 0x4c, 0xb1,
+ 0x6e, 0x61, 0xb5, 0xf8, 0xed, 0xf3, 0x3c, 0x81, 0x62, 0xef, 0xca, 0xc5,
+ 0xef, 0x8a, 0x0b, 0x18, 0x5b, 0xdf, 0x84, 0xc5, 0xbf, 0x16, 0x2f, 0xf7,
+ 0x9c, 0x50, 0xe3, 0xec, 0xb1, 0x63, 0x3b, 0xd4, 0x61, 0x39, 0xc0, 0x0b,
+ 0x38, 0x53, 0x7b, 0x53, 0xd9, 0x62, 0xff, 0x13, 0x05, 0xec, 0x23, 0x56,
+ 0x2f, 0x76, 0xc1, 0xac, 0x5f, 0xdf, 0x79, 0x21, 0x4a, 0xc5, 0xfe, 0x98,
0xf3, 0x73, 0x8d, 0x1e, 0xb1, 0x7c, 0x07, 0x28, 0x96, 0x28, 0xd4, 0x44,
- 0xfc, 0xb3, 0xc7, 0x57, 0xec, 0x19, 0x80, 0xe2, 0xc5, 0xf7, 0x18, 0xa0,
+ 0xfc, 0xb3, 0xc7, 0x57, 0xec, 0x18, 0x60, 0xe2, 0xc5, 0xf7, 0x18, 0xa0,
0xb1, 0x7f, 0xff, 0xff, 0xda, 0x16, 0xb3, 0x7c, 0xd6, 0x9a, 0x19, 0xe9,
- 0xf7, 0x38, 0x26, 0x39, 0x9f, 0x6f, 0xca, 0xc5, 0x75, 0x54, 0x1d, 0x10,
- 0xff, 0xcd, 0x1a, 0x15, 0x04, 0x63, 0xc2, 0xa0, 0x84, 0x57, 0xdd, 0x1b,
- 0xee, 0xb1, 0x7f, 0xb3, 0x8c, 0xdd, 0xc1, 0xd6, 0x2f, 0xd0, 0x21, 0x37,
- 0x16, 0x2e, 0x33, 0xeb, 0x17, 0xa2, 0x11, 0x8b, 0x15, 0x26, 0xe5, 0x86,
- 0x6e, 0x2f, 0x2c, 0x5d, 0x31, 0x2c, 0x54, 0xa6, 0x0d, 0xb1, 0x23, 0x99,
- 0xfd, 0x85, 0x87, 0xc8, 0x5e, 0xfc, 0xd1, 0x72, 0x7b, 0x58, 0xae, 0xab,
- 0xb3, 0xc3, 0x64, 0xd4, 0x34, 0x8e, 0x42, 0x01, 0xee, 0x4a, 0x36, 0xf4,
- 0x6e, 0x9d, 0x15, 0x6f, 0xe9, 0x87, 0xe7, 0xa3, 0xac, 0x5f, 0x1f, 0x66,
- 0x8f, 0x58, 0xbd, 0x27, 0x95, 0x8a, 0xc3, 0xc3, 0xdc, 0x9e, 0xf7, 0xcc,
- 0xe2, 0xc5, 0xfe, 0x2f, 0x78, 0xa7, 0xdc, 0x58, 0xbc, 0x42, 0x35, 0x62,
- 0xa4, 0xf4, 0x5c, 0xce, 0xfe, 0x84, 0x83, 0xf0, 0x95, 0x8a, 0x34, 0xf3,
- 0x9c, 0x82, 0xf8, 0x45, 0x27, 0x58, 0xbc, 0xcc, 0x75, 0x8a, 0x39, 0xbe,
- 0xf9, 0x15, 0xef, 0x18, 0x75, 0x8b, 0x0d, 0x62, 0xec, 0x08, 0xb1, 0x73,
- 0x71, 0x62, 0xda, 0xec, 0xf8, 0x4e, 0x3f, 0xf1, 0x21, 0x0c, 0xd4, 0xa3,
- 0x15, 0xa1, 0x05, 0x74, 0x3c, 0xb1, 0x7d, 0x14, 0xf9, 0x96, 0x2b, 0x73,
- 0x76, 0x21, 0x8b, 0xc5, 0x9c, 0x58, 0xbc, 0x20, 0x61, 0x1b, 0xee, 0x84,
- 0x56, 0x82, 0xc5, 0x6c, 0x78, 0xbf, 0x33, 0xbf, 0xf7, 0xcc, 0x1f, 0x9f,
- 0x22, 0x93, 0xac, 0x5f, 0x0f, 0xf2, 0x05, 0x8a, 0x93, 0xe4, 0x31, 0x06,
- 0xff, 0xc4, 0xde, 0x9c, 0x0d, 0x89, 0x96, 0x2f, 0xf7, 0x56, 0x71, 0x8b,
- 0xdc, 0x58, 0xad, 0xcf, 0xc8, 0x07, 0x97, 0xa4, 0x8d, 0x58, 0xbf, 0xf7,
- 0x9c, 0x3d, 0xfe, 0xfd, 0x1c, 0x6b, 0x17, 0xfb, 0x50, 0xfe, 0x74, 0x93,
- 0xac, 0x52, 0xc5, 0xdc, 0xc5, 0x8a, 0x81, 0xa3, 0x0b, 0x86, 0x5d, 0x9b,
- 0x2c, 0x50, 0x8d, 0xe9, 0x84, 0xb7, 0x9f, 0xb0, 0xd6, 0x2f, 0x08, 0x7b,
- 0xac, 0x54, 0xa6, 0xf3, 0xb9, 0x1f, 0x63, 0xae, 0x86, 0xd0, 0x96, 0x01,
- 0x17, 0x87, 0xee, 0x21, 0x2c, 0x5f, 0x43, 0x8f, 0xd1, 0x62, 0xb6, 0x37,
- 0x8c, 0x2f, 0x7d, 0x9a, 0x91, 0xac, 0x5f, 0x45, 0xfc, 0x89, 0x62, 0xff,
- 0x0b, 0x6f, 0x14, 0x9f, 0x8b, 0x17, 0xb3, 0x59, 0xd4, 0xff, 0x18, 0x88,
- 0xc2, 0x5b, 0xc7, 0x17, 0x45, 0x8b, 0xfb, 0x21, 0xdc, 0x33, 0xcb, 0x16,
- 0xf4, 0x11, 0x21, 0x88, 0x3f, 0x20, 0xb9, 0xf7, 0x58, 0xbf, 0x1e, 0x36,
- 0x09, 0x1e, 0x35, 0x8a, 0x01, 0xe6, 0x08, 0x62, 0x96, 0x2f, 0x78, 0x47,
- 0x58, 0xbe, 0xee, 0x1f, 0x75, 0x8a, 0x93, 0xc2, 0x61, 0xeb, 0xfa, 0x4d,
- 0xf7, 0x04, 0x4b, 0x17, 0xf7, 0xa7, 0xa3, 0x90, 0x16, 0x29, 0x51, 0x07,
- 0x16, 0x02, 0xc5, 0xfc, 0xdb, 0x01, 0x88, 0x68, 0xac, 0x1a, 0x5b, 0x98,
- 0x89, 0x6d, 0xcb, 0xc8, 0x66, 0x38, 0x4a, 0x82, 0x89, 0xbc, 0x1d, 0x3b,
- 0xe4, 0x1e, 0x86, 0x2d, 0xff, 0x3e, 0x7b, 0x9a, 0xc1, 0xe2, 0xc5, 0xfd,
- 0xf6, 0x39, 0x4f, 0x6b, 0x17, 0xc7, 0xe3, 0x43, 0xe7, 0xcc, 0x61, 0xc5,
- 0xe6, 0x6d, 0x2c, 0x5f, 0xc0, 0xf9, 0x67, 0xb8, 0xb1, 0x7f, 0x16, 0x74,
- 0x2c, 0xe2, 0xc5, 0xa6, 0x23, 0xf8, 0xd0, 0xe7, 0x8b, 0xaf, 0xd3, 0x1c,
- 0xff, 0x12, 0xc5, 0x4a, 0x77, 0xf9, 0x0a, 0xde, 0x42, 0xcb, 0xc6, 0xb6,
- 0xe2, 0xc5, 0xfb, 0xf3, 0x1e, 0x28, 0x2c, 0x54, 0x9b, 0xe6, 0x12, 0xbe,
- 0x6f, 0x60, 0x6b, 0x17, 0xfc, 0x39, 0xef, 0xee, 0x3d, 0x62, 0xc5, 0x41,
- 0x99, 0x36, 0x37, 0x2c, 0x22, 0x36, 0x17, 0xdb, 0xc6, 0x4b, 0xa8, 0x72,
- 0x1e, 0x10, 0xff, 0x94, 0x1a, 0x08, 0x52, 0x94, 0x65, 0xbc, 0x84, 0x0f,
- 0xa5, 0xac, 0xf4, 0x84, 0x24, 0x70, 0xf8, 0x42, 0x3b, 0xff, 0xe3, 0x5a,
- 0x2f, 0xce, 0xde, 0x73, 0x9c, 0x5c, 0x58, 0xbc, 0xe5, 0xba, 0xc5, 0xf6,
- 0x77, 0xec, 0x58, 0xb4, 0x0e, 0x78, 0x04, 0x3b, 0x7a, 0x1e, 0xd9, 0x62,
- 0xff, 0xf1, 0x67, 0xf1, 0xb7, 0xfc, 0x90, 0x86, 0xb1, 0x7f, 0xf8, 0x13,
- 0xde, 0x6c, 0x36, 0x6d, 0xd8, 0x6b, 0x16, 0x33, 0x74, 0x4a, 0x81, 0x26,
- 0xa5, 0x30, 0x61, 0x93, 0xea, 0x16, 0x97, 0xf1, 0x7a, 0x19, 0xac, 0x58,
- 0xbf, 0x33, 0x6d, 0x84, 0xb1, 0x74, 0x73, 0x2c, 0x53, 0x1f, 0x77, 0x8b,
- 0x4c, 0x27, 0xbf, 0xda, 0xdb, 0x8d, 0xbe, 0xb1, 0x62, 0xff, 0x7e, 0x7e,
- 0xe6, 0xe0, 0x6b, 0x17, 0xf6, 0x6e, 0xdf, 0x9f, 0xac, 0x54, 0x0f, 0x8f,
- 0xe6, 0xb7, 0xff, 0x33, 0xfa, 0x4b, 0x7c, 0xf7, 0xdd, 0x62, 0xdc, 0x58,
- 0xbf, 0x38, 0x39, 0xf7, 0x58, 0xac, 0x37, 0x44, 0x25, 0x76, 0x86, 0xb1,
- 0x70, 0x61, 0xac, 0x54, 0x0d, 0x90, 0x63, 0x17, 0xa5, 0xfa, 0x24, 0x46,
- 0x1a, 0x2b, 0xfe, 0x72, 0x70, 0x73, 0x3e, 0xcb, 0x17, 0xf1, 0x60, 0x78,
- 0x43, 0x58, 0xac, 0x4e, 0x9f, 0xe4, 0x4c, 0xfb, 0xc7, 0x3f, 0x18, 0x98,
- 0x6f, 0x7f, 0x49, 0x7b, 0xf9, 0x05, 0x8b, 0xb5, 0x2b, 0x17, 0x03, 0x8b,
- 0x17, 0xf3, 0xfd, 0xcd, 0x36, 0x56, 0x28, 0x67, 0x8f, 0xe1, 0x8a, 0x74,
- 0x40, 0x18, 0xbd, 0x5a, 0x46, 0x87, 0x21, 0x5b, 0x7c, 0x42, 0x63, 0x16,
- 0x2a, 0x55, 0xd9, 0x3c, 0xa4, 0x03, 0x23, 0x27, 0x08, 0x51, 0x79, 0xcb,
- 0x16, 0x2f, 0x9c, 0xed, 0x12, 0xc5, 0xdc, 0xf2, 0xc5, 0xe7, 0x26, 0x58,
- 0xb6, 0xcb, 0x16, 0xc8, 0x1a, 0xe2, 0x1b, 0xbf, 0xe9, 0x3f, 0x5c, 0xd6,
- 0xcf, 0xb2, 0xc5, 0x41, 0x1c, 0xc3, 0x1b, 0xdc, 0x8e, 0x3d, 0x18, 0x89,
- 0x6f, 0xfc, 0x42, 0x63, 0x3a, 0xe6, 0x11, 0xab, 0x17, 0x86, 0x15, 0x25,
- 0x8b, 0xf0, 0x0b, 0x3a, 0x62, 0xc5, 0xef, 0xcc, 0xac, 0x5f, 0x9f, 0x77,
- 0x26, 0x58, 0xbf, 0x8f, 0x83, 0x92, 0xdd, 0x62, 0xba, 0xa3, 0xf0, 0x2a,
- 0x83, 0x02, 0x13, 0x94, 0xfc, 0x70, 0xc2, 0x7b, 0xc1, 0x86, 0x1a, 0x45,
- 0x24, 0x46, 0x1a, 0x1b, 0xe7, 0x0d, 0xe2, 0x48, 0xad, 0xcf, 0x0d, 0xc7,
- 0xef, 0xb5, 0x3d, 0x31, 0x62, 0xf4, 0x59, 0xf5, 0x8a, 0xc3, 0xc2, 0x62,
- 0x4b, 0xde, 0x13, 0x2c, 0x5f, 0x7b, 0x4d, 0xd1, 0x62, 0xb0, 0xf0, 0x98,
- 0x76, 0xfc, 0x77, 0xfb, 0x9d, 0x62, 0xec, 0x0b, 0xac, 0x5f, 0xdf, 0xeb,
- 0xa7, 0x9e, 0x2c, 0x54, 0x68, 0xe8, 0x64, 0x26, 0x31, 0xbd, 0xa3, 0x0b,
- 0x84, 0x2b, 0xb2, 0x77, 0x4d, 0xe9, 0xa4, 0xb1, 0x46, 0x1f, 0xa8, 0xe6,
- 0x8f, 0x0a, 0x3f, 0xcb, 0xe1, 0x68, 0xcc, 0xc1, 0x1a, 0x49, 0x43, 0x0b,
- 0x8c, 0x9e, 0x62, 0xe8, 0x40, 0x19, 0x41, 0x83, 0x77, 0xe2, 0x68, 0x60,
- 0xd6, 0x2f, 0x40, 0x58, 0xb1, 0x7e, 0xce, 0xf9, 0x30, 0x58, 0xad, 0x1e,
- 0x30, 0x63, 0xb7, 0xfd, 0xfd, 0xde, 0x40, 0x79, 0x82, 0xc5, 0xff, 0xde,
- 0x03, 0x94, 0x39, 0xb7, 0x4e, 0x3a, 0xc5, 0xef, 0xe6, 0xcb, 0x17, 0xec,
- 0x00, 0x30, 0x0b, 0x14, 0xc7, 0x8c, 0x43, 0xd7, 0xe1, 0xcf, 0xe6, 0x0b,
- 0x17, 0xf6, 0x6a, 0x4a, 0x78, 0xb1, 0x7f, 0xc7, 0x6e, 0x66, 0x9b, 0xb0,
- 0xd6, 0x2f, 0xec, 0x21, 0x7a, 0x7e, 0xb1, 0x7f, 0x73, 0x3a, 0x14, 0xf7,
- 0x87, 0xd1, 0xc3, 0xba, 0x94, 0xc0, 0x70, 0xa3, 0xd0, 0x94, 0xbf, 0x78,
- 0xcf, 0xb0, 0x16, 0x2b, 0x63, 0xde, 0xec, 0xd2, 0x86, 0xa8, 0xc7, 0xb8,
- 0x47, 0x14, 0x6f, 0xf7, 0x89, 0xf8, 0xb1, 0x79, 0xb3, 0x75, 0x8b, 0xcf,
- 0x9b, 0x2c, 0x5f, 0xc4, 0x0e, 0x7b, 0x9d, 0xac, 0x5f, 0xf8, 0x36, 0x1f,
- 0x53, 0x00, 0x07, 0x08, 0xb1, 0x7e, 0x17, 0x98, 0x1c, 0x58, 0xac, 0x44,
- 0xff, 0xcc, 0x00, 0x8d, 0x7f, 0xdb, 0x4b, 0x6e, 0x0d, 0x67, 0x6b, 0x15,
- 0xa3, 0xeb, 0x22, 0xfb, 0xe1, 0xb1, 0x01, 0x62, 0xff, 0x98, 0xef, 0xfe,
- 0xf9, 0x23, 0x58, 0xbf, 0xfa, 0x48, 0x05, 0x3d, 0xc5, 0x24, 0x05, 0x8a,
- 0xea, 0xb9, 0x93, 0x92, 0x9a, 0xdc, 0xf7, 0x43, 0x9f, 0x1d, 0x68, 0xc9,
- 0xc0, 0x42, 0x44, 0x5c, 0x3a, 0xbf, 0x75, 0x3c, 0xe7, 0x96, 0x2f, 0x02,
- 0x04, 0xb1, 0x5b, 0x1e, 0x3c, 0x0a, 0xaf, 0xd1, 0x47, 0x02, 0x3b, 0x16,
- 0x2f, 0x79, 0xbe, 0xb1, 0x7e, 0xf1, 0x49, 0xf8, 0xb1, 0x7e, 0xe3, 0x77,
- 0x87, 0x58, 0xa9, 0x3e, 0xee, 0xc7, 0x7c, 0x51, 0x7c, 0xdd, 0x3e, 0xeb,
- 0x17, 0xff, 0xd3, 0xdf, 0xf3, 0x82, 0x6d, 0x0b, 0x6c, 0xfa, 0xc5, 0x39,
- 0xfb, 0x7c, 0x92, 0xfc, 0x5e, 0xe3, 0x9d, 0x62, 0xff, 0xb5, 0xcf, 0xbe,
- 0xe2, 0xd0, 0x16, 0x2b, 0x0f, 0x91, 0x8a, 0x2f, 0xfb, 0x36, 0x3e, 0x77,
- 0xe9, 0x3a, 0xc5, 0x49, 0xed, 0x8c, 0x82, 0xfd, 0xac, 0xe8, 0xdf, 0x58,
- 0xb3, 0xac, 0x5f, 0xf3, 0x1b, 0xbf, 0xdc, 0x6d, 0x05, 0x8b, 0xed, 0xb6,
- 0x6e, 0xd6, 0x2d, 0xc7, 0x3f, 0x22, 0x11, 0x30, 0xee, 0xff, 0x87, 0xf9,
- 0xd4, 0x83, 0x38, 0xb1, 0x7f, 0xff, 0xbf, 0x25, 0x22, 0xdf, 0xcd, 0xfc,
- 0x3b, 0xf8, 0x02, 0x58, 0xa3, 0x53, 0x6a, 0x04, 0x27, 0x38, 0x69, 0xe3,
- 0x9b, 0xf0, 0xa7, 0x70, 0x09, 0x62, 0xff, 0xf1, 0xaf, 0xe2, 0xc8, 0x75,
- 0xdc, 0xe0, 0x95, 0x8b, 0xec, 0xd7, 0xdd, 0x62, 0xfc, 0xf1, 0x7d, 0xc0,
- 0xb1, 0x7f, 0xf9, 0xa0, 0x59, 0xd1, 0xa2, 0x9c, 0xf7, 0x16, 0x2a, 0x51,
- 0x2d, 0xf2, 0x26, 0x29, 0xb4, 0x72, 0xc5, 0xf0, 0xd9, 0xc6, 0xb1, 0x51,
- 0xa1, 0xb7, 0xc1, 0x5b, 0xdd, 0x30, 0x96, 0x2e, 0xfb, 0xac, 0x5e, 0xf0,
- 0x04, 0xb1, 0x7f, 0xce, 0x1c, 0x5d, 0x67, 0x5a, 0xc5, 0x8b, 0xff, 0x19,
- 0xd8, 0x33, 0xa3, 0x97, 0xb8, 0xb1, 0x52, 0x8d, 0x33, 0x47, 0x9c, 0x5e,
- 0x21, 0xee, 0x1e, 0xdf, 0xec, 0xd8, 0xcf, 0xff, 0x23, 0xd6, 0x2f, 0xf3,
- 0xf3, 0xa9, 0xba, 0xce, 0x2c, 0x5f, 0x03, 0x9e, 0x75, 0x8b, 0xff, 0x7f,
- 0x33, 0x67, 0xce, 0x93, 0xda, 0xc5, 0x49, 0xf2, 0x00, 0x8e, 0xa5, 0x1e,
- 0xbb, 0x9c, 0x87, 0x09, 0xbb, 0xff, 0xa4, 0xfa, 0xd4, 0xed, 0xe6, 0x63,
- 0x56, 0x2e, 0x90, 0xd6, 0x28, 0x07, 0xbc, 0x48, 0xd7, 0xff, 0xc2, 0x0b,
- 0xf3, 0x9b, 0xfd, 0xfb, 0xf6, 0xb5, 0x2b, 0x17, 0xf7, 0x47, 0xd6, 0x0e,
- 0x34, 0x58, 0xbe, 0x7f, 0x4e, 0x96, 0x2f, 0xfb, 0x39, 0x8f, 0xb1, 0xd8,
- 0x22, 0xc5, 0xdf, 0xc5, 0x8a, 0x81, 0xe9, 0x70, 0xee, 0xa5, 0x32, 0x3c,
- 0x58, 0xf9, 0xa8, 0x9d, 0x2f, 0x1e, 0x77, 0x58, 0xbf, 0xe6, 0x87, 0x00,
- 0xdd, 0x30, 0x6b, 0x17, 0x67, 0xf0, 0xf6, 0x7e, 0x3d, 0x7f, 0xcc, 0xfe,
- 0x98, 0x08, 0x78, 0xb1, 0x7d, 0x9e, 0x33, 0x65, 0x8b, 0xe7, 0xd7, 0xc5,
- 0xf3, 0xdd, 0xe1, 0xc5, 0xfb, 0x4f, 0xb3, 0x1d, 0x62, 0xe0, 0xc3, 0x58,
- 0xac, 0x3c, 0x30, 0xca, 0x6f, 0xe6, 0x7e, 0xf9, 0x26, 0xac, 0x58, 0x49,
- 0x11, 0x87, 0xa3, 0xf2, 0x2a, 0x3a, 0x60, 0x1f, 0x86, 0x6d, 0xff, 0xee,
- 0x9f, 0x7c, 0x2d, 0xfe, 0xe7, 0x9d, 0xd6, 0x2f, 0xe6, 0x07, 0x70, 0xcf,
- 0x2c, 0x56, 0x1f, 0xe3, 0xa6, 0xde, 0x81, 0x87, 0x58, 0xbe, 0x6e, 0xc6,
- 0x35, 0x8b, 0xd2, 0x0e, 0x2c, 0x54, 0x15, 0x57, 0x3c, 0x71, 0x3f, 0x85,
- 0x2b, 0x10, 0x70, 0x7c, 0x44, 0x97, 0xb0, 0xf1, 0xeb, 0x17, 0xfe, 0x6e,
- 0x98, 0x61, 0x4f, 0xdf, 0x65, 0x8b, 0xfd, 0x9c, 0x2c, 0xf7, 0xdd, 0x62,
- 0x86, 0x89, 0x3d, 0x10, 0x12, 0x0d, 0xfc, 0xff, 0x62, 0x73, 0xac, 0x54,
- 0x19, 0x98, 0x83, 0x87, 0x06, 0x47, 0x17, 0xba, 0x23, 0x95, 0x45, 0x0e,
- 0x4d, 0x32, 0x9e, 0x1f, 0x1f, 0x8c, 0xfc, 0x10, 0x94, 0x28, 0xd1, 0x3d,
- 0x2d, 0x0f, 0xa4, 0x3d, 0x42, 0x17, 0xdf, 0xf0, 0xf0, 0x00, 0x72, 0xeb,
- 0x1c, 0xb1, 0x4b, 0x17, 0xf6, 0x00, 0x0e, 0x51, 0xcb, 0x17, 0xf4, 0xf1,
- 0xfc, 0x52, 0xb1, 0x5d, 0x51, 0x4d, 0x27, 0xc3, 0x0c, 0xf9, 0x85, 0xfc,
- 0x67, 0xbb, 0xdd, 0xf1, 0x62, 0xfc, 0xe5, 0xec, 0x3a, 0xc5, 0x75, 0x3d,
- 0x88, 0x18, 0xdf, 0x67, 0xdc, 0x35, 0x8b, 0xfd, 0xec, 0xd0, 0x0e, 0xd0,
- 0x58, 0xbe, 0x80, 0x30, 0x0b, 0x17, 0xcd, 0x86, 0x62, 0xc5, 0xec, 0x2d,
- 0xd6, 0x2f, 0xef, 0x64, 0x45, 0x27, 0x5c, 0x40, 0x45, 0xc1, 0x04, 0xb1,
- 0x78, 0x7f, 0x95, 0x44, 0x04, 0x46, 0x1e, 0xa9, 0xce, 0xef, 0x0b, 0x46,
- 0xac, 0x56, 0xc8, 0xdc, 0x27, 0x28, 0xe4, 0xbb, 0xfa, 0x4b, 0xaf, 0x9f,
- 0x65, 0x8b, 0x8a, 0x56, 0x2a, 0x55, 0x0a, 0xec, 0x49, 0x84, 0x7d, 0x9a,
- 0x7c, 0x8d, 0xa1, 0xfc, 0x03, 0x30, 0x86, 0x17, 0xf8, 0x3c, 0xeb, 0xc2,
- 0x9d, 0x2c, 0x5f, 0xf4, 0x52, 0x1e, 0xb3, 0x77, 0xfa, 0xc5, 0xfc, 0xfb,
- 0x79, 0xa1, 0xc5, 0x8b, 0xfe, 0x7d, 0x7d, 0xb8, 0xfa, 0x95, 0x8b, 0x40,
- 0x8f, 0x9f, 0xc5, 0xf7, 0xfd, 0xec, 0xda, 0x42, 0x3e, 0xb1, 0x62, 0xfb,
- 0x0f, 0x31, 0xeb, 0x17, 0xd9, 0x85, 0xbf, 0x67, 0xc1, 0xc3, 0xba, 0xc4,
- 0xd8, 0xfb, 0x85, 0x1f, 0xe1, 0x0f, 0x7e, 0x29, 0x21, 0x4a, 0xc5, 0xfa,
- 0x4a, 0x7d, 0xc5, 0x8b, 0xb8, 0x3c, 0x3c, 0xdf, 0x93, 0x59, 0xcd, 0x45,
- 0xaf, 0x70, 0x88, 0xbf, 0xff, 0xbf, 0x3f, 0xdd, 0xf9, 0x83, 0x2c, 0x8a,
- 0x29, 0xd9, 0x62, 0xfc, 0x70, 0x6b, 0x3b, 0x58, 0xa1, 0xa2, 0x23, 0x17,
- 0xaf, 0xda, 0x71, 0x05, 0xe5, 0x62, 0xff, 0x6b, 0x3b, 0xe0, 0x1b, 0xcb,
- 0x17, 0xf9, 0xcb, 0xd2, 0x0f, 0x71, 0x62, 0xe9, 0xed, 0x62, 0xa0, 0x79,
- 0x61, 0x99, 0xdf, 0xfc, 0x53, 0x11, 0x3c, 0x5e, 0x7e, 0xc3, 0x58, 0xa8,
- 0x8f, 0xab, 0xc4, 0x75, 0x29, 0x9c, 0x9a, 0x59, 0xc8, 0x75, 0x58, 0x5b,
- 0x27, 0x23, 0xbc, 0x6b, 0x77, 0xd0, 0x6e, 0xc3, 0x58, 0xa5, 0x8a, 0x93,
- 0x62, 0x32, 0x5b, 0xfe, 0xeb, 0xad, 0x67, 0xfb, 0x87, 0x16, 0x2f, 0xff,
- 0xf6, 0x70, 0x4d, 0xde, 0x61, 0x1b, 0xce, 0x61, 0x7b, 0x8b, 0x17, 0xfd,
- 0x07, 0x2f, 0x7f, 0x21, 0x1c, 0xb1, 0x5b, 0xa3, 0x6f, 0xb3, 0xe3, 0xb0,
- 0xdf, 0xa0, 0xe3, 0xc3, 0xac, 0x5c, 0x6f, 0x45, 0x8b, 0xff, 0xbe, 0xff,
- 0x21, 0x6d, 0xbc, 0xe8, 0xd5, 0x8b, 0xfe, 0xf6, 0xa7, 0x3b, 0x0b, 0x61,
- 0x64, 0x68, 0xb1, 0x7c, 0x76, 0x61, 0xac, 0x5f, 0xf7, 0x85, 0x39, 0xb0,
- 0x5b, 0x0b, 0x23, 0x45, 0x8b, 0x98, 0x3e, 0xa9, 0xa1, 0x8c, 0xa3, 0x71,
- 0xbe, 0xd2, 0x38, 0x96, 0x61, 0x15, 0x4a, 0xfe, 0x96, 0x4a, 0x4e, 0x79,
- 0x49, 0x1a, 0x63, 0x68, 0x7d, 0x94, 0x6e, 0xb7, 0xf6, 0x82, 0x04, 0x9e,
- 0xf8, 0xb1, 0x7d, 0xee, 0x0a, 0x0b, 0x17, 0xfe, 0x9e, 0xc1, 0x8e, 0xdd,
- 0x27, 0x4b, 0x17, 0xe1, 0x47, 0x66, 0x80, 0xb1, 0x7e, 0xd0, 0x0e, 0xd0,
- 0x58, 0xac, 0x47, 0x6b, 0x1a, 0x11, 0x27, 0x10, 0x0c, 0x2c, 0xb6, 0xcb,
- 0x17, 0xee, 0xb9, 0x13, 0x9d, 0x62, 0xfe, 0x03, 0x43, 0x66, 0xd9, 0x62,
- 0xff, 0xbb, 0xf6, 0x41, 0xc8, 0x0e, 0xb1, 0x7f, 0x0b, 0x67, 0x21, 0x1d,
- 0x62, 0xa4, 0xfa, 0x08, 0xe6, 0xf8, 0xff, 0x9e, 0x8b, 0x17, 0xfe, 0xec,
- 0xd6, 0xe7, 0x89, 0xfb, 0xe2, 0xc5, 0x49, 0xf3, 0xb1, 0x2d, 0xff, 0xe1,
- 0x4f, 0x50, 0x9e, 0x7e, 0x7f, 0xb6, 0x0d, 0x62, 0xb6, 0x4e, 0xef, 0x0a,
- 0xde, 0x13, 0x1a, 0x84, 0x3f, 0x08, 0x2f, 0xfd, 0x83, 0xfb, 0x46, 0x4f,
- 0xe7, 0xb5, 0x8b, 0xfe, 0xfb, 0x71, 0xc8, 0xa7, 0xb5, 0x8b, 0xdf, 0x63,
- 0xac, 0x52, 0xc0, 0x55, 0x55, 0xce, 0xa3, 0xce, 0x3a, 0xa7, 0x10, 0xbc,
- 0x71, 0x7f, 0xc4, 0x6e, 0x89, 0xf7, 0x11, 0x2c, 0x5e, 0x13, 0x18, 0xb1,
- 0x7e, 0xf4, 0xe1, 0x4a, 0xc5, 0x39, 0xff, 0x68, 0xe8, 0x87, 0xaf, 0x18,
- 0x5e, 0x58, 0xb8, 0xec, 0xb1, 0x73, 0xec, 0xb1, 0x4e, 0x6b, 0xfe, 0x2f,
- 0x7f, 0xfb, 0xef, 0x1e, 0xfb, 0x4f, 0xa6, 0x29, 0xed, 0x62, 0xff, 0x63,
- 0x9a, 0xe3, 0x63, 0xac, 0x5f, 0xda, 0xef, 0x98, 0x46, 0xac, 0x57, 0x54,
- 0x59, 0x0d, 0x3c, 0xc3, 0x3b, 0xd2, 0x07, 0x58, 0xad, 0x93, 0x6e, 0x35,
- 0x34, 0xf0, 0xd2, 0x0c, 0xce, 0xff, 0xd2, 0xfc, 0x9f, 0x72, 0x7f, 0x2b,
- 0x17, 0xfd, 0xd7, 0x93, 0xa6, 0x83, 0xfd, 0x62, 0xff, 0xb7, 0x16, 0x3f,
- 0x7e, 0x93, 0xac, 0x59, 0xf8, 0x7e, 0xc2, 0x3b, 0xbf, 0xec, 0xd8, 0xa4,
- 0xdc, 0xef, 0xcb, 0x14, 0x6a, 0x62, 0xa7, 0x85, 0x99, 0x84, 0xf7, 0xed,
- 0xf1, 0xf8, 0x75, 0x8b, 0xff, 0xb9, 0x25, 0xe3, 0x22, 0xfb, 0xfb, 0x8b,
- 0x17, 0xd9, 0xa9, 0xe8, 0xb1, 0x5d, 0x9f, 0x5f, 0x91, 0xef, 0xe8, 0x4e,
- 0xd3, 0xc1, 0x2c, 0x5f, 0xff, 0x8f, 0x30, 0xcd, 0xc6, 0xe5, 0x9a, 0xde,
- 0x71, 0x62, 0xdb, 0xc4, 0x88, 0x40, 0x17, 0xd7, 0x68, 0xd2, 0x28, 0x53,
- 0xd1, 0xd3, 0x8e, 0x68, 0xd9, 0xaa, 0x57, 0x70, 0x72, 0x1b, 0x8f, 0x1c,
- 0xdb, 0x46, 0xb6, 0x28, 0xf1, 0xaf, 0x04, 0x9e, 0xd6, 0x2f, 0xf1, 0x60,
- 0x38, 0x63, 0x79, 0x62, 0xf7, 0x98, 0x6b, 0x17, 0x61, 0xd6, 0x2f, 0xb5,
- 0xb4, 0xc1, 0x62, 0xa4, 0xdd, 0xe0, 0xbd, 0xfd, 0xe2, 0x93, 0xf0, 0x2a,
- 0xb1, 0x73, 0xe2, 0xc5, 0xfb, 0x35, 0xa6, 0x82, 0xc5, 0xfb, 0x5a, 0x78,
- 0xb8, 0xb1, 0x50, 0x3d, 0x2c, 0x28, 0xa8, 0xd9, 0x17, 0x70, 0x32, 0xf3,
- 0x45, 0xe3, 0xed, 0x2b, 0x17, 0xfb, 0x0a, 0x7b, 0xe3, 0x6e, 0xb1, 0x46,
- 0xa2, 0x1f, 0x73, 0x50, 0xc7, 0xaf, 0x72, 0x1b, 0xac, 0x5f, 0x4c, 0x7e,
- 0xa5, 0x62, 0xb0, 0xf1, 0x38, 0x3f, 0x78, 0x07, 0xf2, 0xc5, 0x41, 0x56,
- 0x1b, 0x90, 0x44, 0x68, 0x75, 0x86, 0x8d, 0x84, 0x0e, 0xe4, 0x43, 0x7b,
- 0x78, 0x32, 0xc5, 0xff, 0x1e, 0x77, 0x7f, 0x68, 0x47, 0x58, 0xbf, 0x69,
- 0xc0, 0x61, 0xd6, 0x2b, 0xaa, 0x20, 0xf0, 0x7b, 0x47, 0x77, 0xef, 0xb6,
- 0xc3, 0xe8, 0xb1, 0x7f, 0x60, 0xfe, 0xd9, 0xa5, 0x8b, 0xfb, 0x52, 0xf0,
- 0x6e, 0x2c, 0x58, 0x22, 0xc5, 0xda, 0x7d, 0x8f, 0x06, 0x22, 0xdb, 0xff,
- 0x36, 0x61, 0x1a, 0x67, 0x84, 0x35, 0x8b, 0xfc, 0xce, 0x37, 0xce, 0xfc,
- 0xb1, 0x7a, 0x26, 0x1a, 0xc5, 0xe0, 0x8f, 0xd1, 0x62, 0xdb, 0x69, 0x1c,
- 0x3f, 0x2f, 0xf2, 0x00, 0x8c, 0xc2, 0x0f, 0x5e, 0x7e, 0xf8, 0xb1, 0x7f,
- 0xf7, 0x27, 0x6c, 0xd4, 0x45, 0x20, 0xe2, 0xc5, 0xff, 0xc1, 0x72, 0x93,
- 0xeb, 0x1f, 0xf2, 0x35, 0x8b, 0xfc, 0xff, 0xcd, 0x6b, 0x3b, 0x58, 0xbf,
- 0x44, 0x53, 0xa8, 0x2c, 0x5a, 0x60, 0x7b, 0xb8, 0x69, 0x7f, 0xf1, 0x0b,
- 0x77, 0x37, 0x9f, 0x92, 0xf2, 0xc5, 0xec, 0x2d, 0xd6, 0x2e, 0x70, 0xf0,
- 0xf8, 0xcc, 0x46, 0xa8, 0x2b, 0xbe, 0xdc, 0xc7, 0xe5, 0x8d, 0x1a, 0x78,
- 0x14, 0xfc, 0x3c, 0x24, 0x60, 0xe1, 0x48, 0x12, 0x11, 0x37, 0xda, 0x68,
- 0x44, 0xb1, 0x7f, 0xee, 0xfd, 0x85, 0x20, 0xc2, 0x02, 0xc5, 0xf7, 0x24,
- 0x01, 0x45, 0x8a, 0xc3, 0xe5, 0xe1, 0xf5, 0x1a, 0x8a, 0xa0, 0xe1, 0x13,
- 0x7d, 0xfc, 0x03, 0x2c, 0x54, 0xa7, 0x12, 0xd1, 0x9e, 0xf0, 0xaa, 0xfd,
- 0xc1, 0x3c, 0xc4, 0xb1, 0x7e, 0xe3, 0x97, 0x9d, 0x62, 0xfd, 0xe7, 0xdd,
- 0xa0, 0xb1, 0x71, 0xbc, 0x58, 0xb6, 0xa5, 0x12, 0x51, 0x14, 0xb1, 0x3f,
- 0x0a, 0x6f, 0xfd, 0x07, 0x38, 0x78, 0x43, 0xfc, 0xac, 0x5f, 0xfc, 0x53,
- 0xec, 0xcd, 0x6b, 0x27, 0x75, 0x8b, 0xfc, 0x6e, 0x68, 0x07, 0x7e, 0x2c,
- 0x57, 0x68, 0xb7, 0xf9, 0xf9, 0x21, 0xdf, 0xef, 0xbf, 0x60, 0xd3, 0x0d,
- 0x62, 0xd1, 0x2c, 0x5f, 0x76, 0x0d, 0x4a, 0x45, 0xc1, 0x86, 0x91, 0x52,
- 0x6f, 0x83, 0x24, 0xb3, 0xa4, 0x46, 0x1a, 0x1a, 0xfa, 0x25, 0x89, 0xca,
- 0xff, 0xc3, 0x17, 0x9f, 0xee, 0x6f, 0xdd, 0x62, 0xff, 0xff, 0x9e, 0x3e,
- 0x47, 0xd5, 0xa7, 0xbd, 0xff, 0x3d, 0xf1, 0xa4, 0x22, 0xc5, 0xff, 0xfe,
- 0xc0, 0x93, 0x13, 0x9e, 0x62, 0xea, 0x5d, 0xc3, 0xe2, 0x02, 0xc5, 0xc5,
- 0x19, 0x28, 0xd7, 0xc6, 0xfb, 0xc4, 0xd0, 0x58, 0xb9, 0xa2, 0x58, 0xad,
- 0xcd, 0xa1, 0xc7, 0x2e, 0x7d, 0xd6, 0x2f, 0xf0, 0x05, 0xe2, 0x9f, 0x71,
- 0x62, 0xc1, 0x16, 0x2f, 0x9b, 0xa9, 0x87, 0x58, 0xa6, 0x3e, 0xee, 0x86,
- 0x81, 0x8a, 0x5f, 0xc3, 0x7e, 0x9f, 0xc0, 0x8b, 0x16, 0x89, 0x62, 0xb0,
- 0xf1, 0x5c, 0xca, 0x96, 0x2e, 0xd8, 0x96, 0x2f, 0x73, 0x34, 0xb1, 0x7b,
- 0x77, 0xd2, 0xc5, 0xd9, 0xf5, 0x8a, 0xec, 0xda, 0xc7, 0x0f, 0x5d, 0xa8,
- 0x75, 0x5c, 0x40, 0x84, 0x32, 0xf0, 0x8b, 0xb8, 0xc5, 0xdd, 0x8f, 0x44,
- 0x5f, 0x84, 0x33, 0x3b, 0x00, 0x80, 0x2e, 0x19, 0xc1, 0x8f, 0x29, 0x5e,
- 0xe7, 0xd9, 0x62, 0xa5, 0x75, 0x55, 0xa7, 0x1c, 0x3d, 0x0c, 0x8b, 0xef,
- 0x79, 0x8e, 0xb1, 0x7e, 0x28, 0x6e, 0x2d, 0x96, 0x2f, 0x4e, 0xa2, 0x58,
- 0xa6, 0x3c, 0x91, 0x15, 0xdf, 0xff, 0xe2, 0xf4, 0xee, 0x42, 0x3e, 0x43,
- 0xf8, 0x41, 0xce, 0x96, 0x2f, 0xc7, 0x26, 0xf7, 0x16, 0x29, 0x91, 0x12,
- 0x63, 0x0d, 0x75, 0x77, 0x9d, 0x51, 0xa3, 0x6c, 0xce, 0x76, 0x6d, 0x0d,
- 0x38, 0x11, 0x8e, 0x13, 0xd9, 0x4d, 0x69, 0xee, 0x39, 0xe7, 0x95, 0x57,
- 0xaa, 0x42, 0x59, 0xe3, 0x5b, 0xfd, 0x23, 0x09, 0xa5, 0x91, 0x94, 0xf1,
- 0xa7, 0xa1, 0x8e, 0x29, 0xe4, 0xee, 0x87, 0xc1, 0xb6, 0x19, 0x0a, 0xab,
- 0xbd, 0xb2, 0xc5, 0xfc, 0xdb, 0xcc, 0x76, 0x76, 0xb1, 0x50, 0x3c, 0xbf,
- 0x8c, 0xdf, 0xcf, 0xf9, 0xdc, 0x99, 0x62, 0xe7, 0x0d, 0x62, 0xa0, 0x78,
- 0xbe, 0x2d, 0xb1, 0xab, 0x17, 0xe8, 0xe1, 0x7d, 0xf4, 0xb1, 0x7f, 0x48,
- 0x7a, 0x14, 0x81, 0x62, 0xb6, 0x3d, 0xbf, 0x16, 0x5f, 0xe2, 0x87, 0x07,
- 0xf7, 0x0d, 0x62, 0xf6, 0xcc, 0x75, 0x8b, 0xbb, 0x25, 0x8b, 0xf7, 0x70,
- 0xf9, 0x9c, 0x58, 0xb3, 0x61, 0xe2, 0x10, 0xc5, 0xce, 0x35, 0x8b, 0xf1,
- 0x4f, 0xdb, 0x8b, 0x16, 0x89, 0x62, 0xe3, 0xca, 0xc5, 0xef, 0x38, 0x6b,
- 0x8c, 0x20, 0xb9, 0x8c, 0x54, 0x40, 0xe7, 0x66, 0xae, 0xba, 0xa2, 0x2d,
- 0xc4, 0xc4, 0x85, 0x50, 0x4c, 0x7f, 0xe4, 0xa1, 0x71, 0x7f, 0x42, 0xca,
- 0xba, 0xaa, 0x8e, 0x96, 0xe7, 0x23, 0x63, 0x51, 0x47, 0x03, 0x7a, 0x76,
- 0x95, 0x8b, 0xff, 0xa6, 0x19, 0xf6, 0xec, 0x19, 0xdf, 0x96, 0x2e, 0x06,
- 0x11, 0xf1, 0xf0, 0x76, 0xfe, 0x13, 0x04, 0xfe, 0x6c, 0xb1, 0x7f, 0x85,
- 0xf7, 0xd6, 0x77, 0xe5, 0x8b, 0xfb, 0xd8, 0xf1, 0xdf, 0x95, 0x8b, 0x73,
- 0xaa, 0x25, 0xa3, 0x8c, 0x4c, 0x35, 0xbb, 0x41, 0x75, 0x8a, 0xd2, 0x63,
- 0x40, 0x86, 0x11, 0x1e, 0x5f, 0xd8, 0x40, 0xcc, 0x1a, 0xc5, 0xfc, 0xe0,
- 0xc3, 0xce, 0xeb, 0x17, 0x30, 0x6b, 0x17, 0xf3, 0x3f, 0x7c, 0x76, 0x58,
- 0xbf, 0xfd, 0xe2, 0x9c, 0xe8, 0xfe, 0x9c, 0x28, 0x2c, 0x51, 0xa7, 0xec,
- 0xe5, 0xb7, 0xff, 0xfe, 0x86, 0xff, 0x7d, 0x6c, 0x79, 0xdf, 0xf2, 0xe3,
- 0x9f, 0xcc, 0x16, 0x2f, 0x7e, 0x4d, 0x58, 0xae, 0xd1, 0x1b, 0xd1, 0xbe,
- 0xfe, 0x06, 0xb4, 0xfd, 0x81, 0x62, 0xff, 0xe8, 0x49, 0x03, 0x34, 0x03,
- 0xbf, 0x16, 0x2f, 0xf6, 0x6f, 0x3b, 0x14, 0xee, 0xb1, 0x7e, 0xdc, 0xa7,
- 0xb8, 0x2c, 0x58, 0x0b, 0x16, 0x8f, 0xea, 0x7e, 0x38, 0x6a, 0xe5, 0x57,
- 0xa4, 0xf2, 0xb1, 0x7e, 0xcf, 0x71, 0xbb, 0x58, 0xbf, 0xfd, 0xcc, 0xfb,
- 0xf0, 0x5b, 0x75, 0x8a, 0x49, 0x62, 0xe9, 0x12, 0xc5, 0xf8, 0x44, 0x03,
- 0x20, 0xb1, 0x7f, 0xbf, 0x20, 0x3b, 0x43, 0xae, 0x1e, 0x0f, 0x05, 0xe8,
- 0x69, 0x81, 0xf0, 0xa4, 0xc8, 0x47, 0xdf, 0xff, 0x8a, 0x61, 0x9f, 0x6d,
- 0x4f, 0x9c, 0x13, 0x05, 0x8b, 0xfd, 0x20, 0x8a, 0x0e, 0x20, 0xba, 0xc5,
- 0xd9, 0xce, 0xa8, 0xc3, 0x19, 0xb9, 0x8a, 0x74, 0x35, 0x44, 0x05, 0x1f,
- 0x15, 0x0d, 0x73, 0x28, 0xd8, 0x47, 0x34, 0x2b, 0xc8, 0x9b, 0xc6, 0x02,
- 0x85, 0xaf, 0x49, 0x4b, 0x17, 0xff, 0x69, 0xfb, 0x33, 0xd8, 0xf0, 0x6e,
- 0x2c, 0x5f, 0xf0, 0xb6, 0x9e, 0xb3, 0xe9, 0x1a, 0xc5, 0x69, 0x10, 0x5f,
- 0x46, 0xbe, 0x08, 0x12, 0x63, 0xd6, 0x2f, 0xff, 0xd3, 0xef, 0xe0, 0xfd,
- 0x9f, 0x2c, 0xf7, 0xdd, 0x62, 0xd3, 0xd4, 0xff, 0xb4, 0x55, 0x7c, 0xd0,
- 0x01, 0xd6, 0x2f, 0xff, 0xe9, 0x33, 0x4e, 0x79, 0x37, 0x9f, 0x7f, 0x14,
- 0x9d, 0x62, 0x8e, 0x7f, 0xe0, 0x23, 0xb6, 0xb4, 0x8c, 0xa0, 0x42, 0xa2,
- 0xff, 0x8c, 0xf3, 0x90, 0xa1, 0x9c, 0x58, 0xbc, 0xda, 0xd9, 0x62, 0xe0,
- 0xc3, 0x58, 0xbf, 0x9f, 0x3a, 0x19, 0x08, 0xcd, 0xcd, 0xc0, 0x63, 0xd5,
- 0xba, 0x2f, 0x74, 0xe5, 0x7c, 0x4d, 0xd8, 0x16, 0x2f, 0xee, 0x08, 0x07,
- 0x98, 0x2c, 0x5f, 0xd0, 0x76, 0xe9, 0xf7, 0x58, 0xbd, 0x3f, 0xe2, 0xc5,
- 0xce, 0x6f, 0x53, 0xfb, 0xc2, 0xf0, 0x17, 0xdf, 0xee, 0x67, 0x98, 0xf8,
- 0x4b, 0x14, 0x35, 0x70, 0xcf, 0x1b, 0x5e, 0xa1, 0xd6, 0x72, 0x4f, 0xc2,
- 0x7b, 0xc7, 0x97, 0xfe, 0xe6, 0x16, 0x7f, 0x37, 0xc2, 0x58, 0xbf, 0xfc,
- 0xfc, 0xc2, 0xea, 0x66, 0xa2, 0xcc, 0x0d, 0x62, 0xfb, 0x4f, 0x27, 0x58,
- 0xbf, 0xdc, 0xf7, 0xf0, 0xf9, 0x05, 0x8b, 0xff, 0xc2, 0x91, 0xe7, 0x80,
- 0x61, 0x43, 0xf8, 0xb1, 0x74, 0xf1, 0x62, 0xd2, 0xb1, 0x7f, 0xe8, 0xd2,
- 0x79, 0xcc, 0xf7, 0xda, 0x0b, 0x17, 0xff, 0xde, 0xe4, 0xfb, 0xb9, 0xff,
- 0xe7, 0xa4, 0xf1, 0x62, 0x82, 0xa8, 0x97, 0xc4, 0x4b, 0xd8, 0x08, 0xe1,
- 0xa3, 0x3b, 0x21, 0x51, 0x50, 0x4e, 0x7c, 0x66, 0x80, 0x4b, 0x28, 0x72,
- 0xdf, 0xff, 0xda, 0xc8, 0x47, 0x66, 0xff, 0x71, 0x94, 0x87, 0x84, 0xb1,
- 0x7c, 0x1b, 0x18, 0x75, 0x8b, 0xcd, 0xdc, 0xac, 0x5f, 0xb0, 0xdf, 0xb4,
- 0x3e, 0x78, 0x46, 0x12, 0xd4, 0x15, 0xb7, 0x0c, 0xf4, 0xd4, 0xe7, 0x8f,
- 0x07, 0x48, 0x45, 0x0a, 0x0a, 0x95, 0xc3, 0x9c, 0x97, 0xad, 0x7f, 0xba,
- 0x07, 0x84, 0x3f, 0xca, 0xc5, 0xfe, 0xc0, 0x0d, 0xfa, 0x48, 0xd6, 0x2f,
- 0xe7, 0x1e, 0xb0, 0xf8, 0xb1, 0x7f, 0xde, 0xe1, 0x9a, 0x9f, 0x4c, 0x16,
- 0x2f, 0xb7, 0x66, 0xdd, 0x51, 0x0c, 0x17, 0xf9, 0xe7, 0x50, 0x14, 0xe2,
- 0xc5, 0x75, 0x44, 0xf6, 0x8e, 0xc8, 0xc6, 0xf8, 0xd9, 0x28, 0x2c, 0x5f,
- 0x1c, 0xed, 0x0e, 0xa9, 0x8f, 0xe4, 0x32, 0xfc, 0x63, 0x7f, 0xe2, 0xcd,
- 0xb4, 0xe1, 0x9e, 0x78, 0xb1, 0x7f, 0xff, 0x38, 0xc2, 0x4e, 0x6b, 0x69,
- 0x19, 0x31, 0xa6, 0xca, 0xc5, 0x1a, 0x89, 0xee, 0x88, 0x17, 0xfc, 0xe0,
- 0x62, 0xf3, 0x37, 0xd6, 0x2f, 0xb7, 0x66, 0xdd, 0x71, 0x88, 0x97, 0xff,
- 0xfb, 0x37, 0xfc, 0xf7, 0x08, 0xec, 0xfe, 0xef, 0x84, 0xc6, 0xac, 0x56,
- 0x91, 0x2e, 0x46, 0x37, 0x6e, 0x05, 0x8b, 0x87, 0xda, 0xc5, 0xcd, 0xc8,
- 0x26, 0x45, 0x90, 0xce, 0x39, 0x11, 0x0c, 0xd4, 0xab, 0xd4, 0xc8, 0xd5,
- 0x1a, 0x1d, 0x82, 0x8d, 0x22, 0x96, 0x29, 0x62, 0xdb, 0x08, 0xb8, 0x8e,
- 0x0c, 0xbf, 0xdc, 0xf3, 0x77, 0x1c, 0xe6, 0xac, 0x5f, 0xb2, 0x29, 0x21,
- 0xac, 0x54, 0x9f, 0x0e, 0x8e, 0x6a, 0x5b, 0x35, 0xe8, 0x1a, 0xe1, 0x63,
- 0xce, 0x7c, 0x7e, 0x91, 0x7e, 0xc5, 0x65, 0x38, 0x15, 0xe6, 0x51, 0x42,
- 0x2e, 0xfc, 0x52, 0x0e, 0xc0, 0xb1, 0x7e, 0xc8, 0x4e, 0x80, 0xb1, 0x7f,
- 0xf6, 0xdf, 0x97, 0xf7, 0x27, 0x6c, 0xe2, 0xc5, 0xd2, 0x62, 0xc5, 0xf9,
- 0xb6, 0x29, 0x82, 0x45, 0x44, 0x78, 0x1f, 0x18, 0xbf, 0xcc, 0xfe, 0x9d,
- 0x48, 0x16, 0x2f, 0xde, 0xc3, 0xbf, 0x96, 0x2f, 0xfd, 0xe2, 0x90, 0x0c,
- 0x9f, 0xbf, 0x2c, 0x5b, 0xdf, 0x44, 0xcb, 0x19, 0x18, 0x51, 0x7c, 0xc4,
- 0x66, 0xcb, 0x17, 0xf3, 0x1b, 0x83, 0x72, 0x58, 0xaf, 0x9e, 0x89, 0x12,
- 0x54, 0x15, 0x1d, 0x9a, 0x53, 0xa2, 0x83, 0xc2, 0x18, 0xa1, 0x78, 0x1c,
- 0x21, 0xef, 0xfc, 0xfb, 0xcf, 0x1b, 0x5a, 0x70, 0xd6, 0x2f, 0x88, 0x7f,
- 0x95, 0x8b, 0xfe, 0xda, 0x07, 0x9f, 0xb3, 0x9a, 0xb1, 0x7f, 0xec, 0xe4,
- 0xfd, 0xbc, 0x64, 0x8d, 0x62, 0xff, 0x99, 0x83, 0xfb, 0x1d, 0xf8, 0xb1,
- 0x7f, 0xef, 0x39, 0x6d, 0x9d, 0xfb, 0xec, 0xb1, 0x7f, 0xf3, 0xe8, 0xdd,
- 0xfe, 0xff, 0x21, 0x6c, 0xb1, 0x52, 0x98, 0x00, 0xcf, 0xf0, 0xe4, 0x08,
- 0x17, 0xff, 0x6f, 0xad, 0x67, 0x39, 0xc6, 0x28, 0x2c, 0x5f, 0xff, 0xc3,
- 0xd1, 0x30, 0x7d, 0x5f, 0x52, 0x59, 0xfc, 0xdd, 0x62, 0x99, 0x51, 0xe1,
- 0x11, 0x72, 0x33, 0xb1, 0x1e, 0x06, 0x8d, 0x7c, 0x2c, 0xe3, 0xac, 0x5d,
- 0xc1, 0x2c, 0x5f, 0xd0, 0xfb, 0x31, 0x4a, 0xc5, 0xa7, 0x73, 0xc4, 0xec,
- 0x62, 0xfc, 0x2f, 0x68, 0x50, 0x58, 0xbf, 0xe9, 0xfb, 0xe1, 0xa6, 0xcc,
- 0x16, 0x2d, 0x84, 0x7c, 0x9e, 0x2a, 0xbf, 0x6b, 0x76, 0x6d, 0xd5, 0x10,
- 0x51, 0x7b, 0xf2, 0x75, 0x8b, 0xff, 0x4e, 0xcd, 0xed, 0x64, 0x23, 0xb1,
- 0x62, 0xe7, 0xd2, 0xc5, 0xfe, 0xf4, 0x9f, 0xdc, 0x60, 0x2c, 0x56, 0xc7,
- 0x97, 0x82, 0xf4, 0x34, 0xca, 0x70, 0x99, 0xcd, 0xc8, 0x77, 0x90, 0x8d,
- 0xbf, 0x7e, 0x4e, 0x2e, 0xd6, 0x2f, 0x72, 0x7b, 0x58, 0xbe, 0xf7, 0x24,
- 0x09, 0x17, 0x9b, 0x5b, 0x24, 0x5f, 0x08, 0x98, 0xd4, 0x8b, 0xfc, 0xfb,
- 0x67, 0xb9, 0x20, 0x48, 0xa4, 0x8b, 0xfb, 0x37, 0x9f, 0xc9, 0xd2, 0x2e,
- 0x0c, 0x34, 0x8b, 0xf8, 0xa4, 0xb6, 0x7d, 0x24, 0x56, 0x26, 0x33, 0xb9,
- 0x19, 0xc7, 0xbe, 0x46, 0x03, 0x42, 0x0c, 0x0c, 0xb8, 0xc1, 0xaa, 0x58,
- 0xb6, 0x92, 0x23, 0x0f, 0xfe, 0x5c, 0xef, 0x41, 0xfe, 0xb1, 0x4b, 0x15,
- 0xda, 0xa1, 0x17, 0x8e, 0xd9, 0x8c, 0x8c, 0x1d, 0xa8, 0x2a, 0xcd, 0x89,
- 0x37, 0xf2, 0x8e, 0xef, 0xff, 0x83, 0xe1, 0x67, 0x7e, 0x62, 0xdb, 0x3b,
- 0xf2, 0xc5, 0xfd, 0xd3, 0xab, 0x42, 0x18, 0xb1, 0x52, 0x88, 0x5c, 0x53,
- 0xbf, 0xff, 0x16, 0x78, 0x40, 0x3b, 0x40, 0xc3, 0xc7, 0x39, 0xab, 0x17,
- 0x36, 0x96, 0x2f, 0xdb, 0x60, 0xe4, 0xeb, 0x17, 0xb7, 0x93, 0x86, 0x78,
- 0x06, 0x0b, 0xda, 0x56, 0x2c, 0xff, 0x3c, 0x7f, 0x1b, 0x50, 0xd3, 0x09,
- 0xf4, 0x38, 0xaa, 0x59, 0x46, 0x38, 0xd2, 0xf2, 0x9f, 0x34, 0xa3, 0xf6,
- 0x66, 0x9c, 0x83, 0x28, 0x5f, 0x8a, 0x32, 0xab, 0xee, 0x61, 0x01, 0x62,
- 0xff, 0xfe, 0x68, 0x78, 0xa7, 0x3b, 0xcd, 0xe7, 0xdf, 0x7e, 0x8b, 0x17,
- 0x30, 0xd6, 0x28, 0xd3, 0xf4, 0x3a, 0xed, 0xff, 0xff, 0x16, 0x7b, 0xd3,
- 0xdc, 0x3a, 0xfe, 0x4e, 0x2e, 0xf9, 0xf9, 0x58, 0xbf, 0xbe, 0xe6, 0x9b,
- 0x3b, 0x2c, 0x5f, 0xd8, 0x5c, 0x72, 0xc5, 0x8b, 0xf8, 0xf8, 0x3f, 0xe6,
- 0xcb, 0x17, 0xff, 0x89, 0x8d, 0xe0, 0x3d, 0xee, 0xfd, 0x9b, 0xac, 0x5f,
- 0xbd, 0xd7, 0xda, 0x95, 0x8a, 0x94, 0x54, 0x1a, 0x5f, 0xda, 0x75, 0xef,
- 0x88, 0xeb, 0x15, 0xb2, 0xa7, 0x73, 0x61, 0x2d, 0x1e, 0x47, 0xa6, 0xbf,
- 0x98, 0x94, 0x34, 0xc2, 0x18, 0xdf, 0xfd, 0x14, 0x1c, 0x1f, 0xce, 0x98,
- 0xc7, 0x58, 0xbf, 0x8b, 0x39, 0xa9, 0xe2, 0xc5, 0xe1, 0x43, 0x16, 0x2b,
- 0xaa, 0x24, 0x59, 0x1c, 0x05, 0xb7, 0xec, 0x26, 0xf7, 0x16, 0x2f, 0xbf,
- 0x25, 0x05, 0x8b, 0xf6, 0x7c, 0x9a, 0x25, 0x8a, 0x19, 0xf8, 0xe1, 0x39,
- 0x11, 0x54, 0x11, 0x9f, 0xc8, 0x51, 0x5e, 0xd0, 0xbe, 0xb1, 0x76, 0x7d,
- 0x62, 0xfa, 0x2f, 0x8b, 0x65, 0x8a, 0x88, 0xde, 0x98, 0x2f, 0x78, 0xa4,
- 0xeb, 0x15, 0xa4, 0x4d, 0x32, 0xd8, 0x88, 0xef, 0x7e, 0x62, 0x58, 0xbe,
- 0x84, 0xc4, 0xeb, 0x14, 0x33, 0xc1, 0xec, 0x7a, 0xfe, 0xe8, 0xfa, 0x60,
- 0xfc, 0xb1, 0x7f, 0x3c, 0xeb, 0x3b, 0xf2, 0xc5, 0xfc, 0xc6, 0xe6, 0xcc,
- 0x75, 0x8b, 0xfc, 0xe4, 0xde, 0x89, 0xc3, 0x58, 0xbf, 0x3c, 0x50, 0x71,
- 0xac, 0x54, 0x9e, 0xee, 0x1a, 0x5f, 0xfb, 0x30, 0x3e, 0x77, 0x25, 0x3c,
- 0x58, 0xb6, 0xba, 0xa7, 0xbb, 0x2e, 0x18, 0x46, 0x73, 0x12, 0x2e, 0xe4,
- 0x23, 0x3c, 0x41, 0x52, 0xac, 0x39, 0xe5, 0x4f, 0xdf, 0xc7, 0x61, 0xfe,
- 0x49, 0x62, 0xf6, 0xb3, 0xeb, 0x17, 0xde, 0x17, 0xb8, 0xb1, 0x7a, 0x19,
- 0xe5, 0x8b, 0xee, 0x8f, 0x0e, 0x2c, 0x57, 0x67, 0x84, 0xe3, 0xb5, 0x88,
- 0x88, 0xd3, 0x35, 0xfe, 0x76, 0xf6, 0x6f, 0x20, 0x58, 0xbf, 0xfe, 0x67,
- 0x07, 0x30, 0xd6, 0x3e, 0xa7, 0x09, 0x62, 0xff, 0xe3, 0xb7, 0x7d, 0x45,
- 0x14, 0xf1, 0xe3, 0xd6, 0x2f, 0xfb, 0xbf, 0x06, 0xda, 0xd3, 0x1a, 0xb1,
- 0x7a, 0x7d, 0xc5, 0x8a, 0x93, 0xda, 0x23, 0xda, 0xc4, 0x63, 0x7a, 0x14,
- 0xd7, 0xb7, 0x30, 0x0b, 0x17, 0xe3, 0x8b, 0x1c, 0x6b, 0x17, 0xff, 0xf7,
- 0xb9, 0xfc, 0x08, 0xc4, 0x68, 0xf1, 0xf5, 0xa9, 0x58, 0xa9, 0x45, 0x29,
- 0xa4, 0x0c, 0x51, 0x7d, 0xf9, 0xef, 0x8b, 0x17, 0xcf, 0x9d, 0xf9, 0x62,
- 0xb0, 0xf1, 0xfc, 0x49, 0x7f, 0xff, 0xdf, 0x7d, 0x60, 0xd8, 0xf8, 0x5e,
- 0x29, 0x0f, 0x3d, 0xc5, 0x8b, 0x4a, 0xc5, 0xf4, 0xf4, 0x1c, 0xee, 0x7e,
- 0xc0, 0x65, 0xbf, 0x9b, 0xdc, 0xc2, 0x82, 0xc5, 0xff, 0x7d, 0xd8, 0x1a,
- 0x96, 0x82, 0xc5, 0xcd, 0x0f, 0x9f, 0x2f, 0x8b, 0x6b, 0xe8, 0xcd, 0xf4,
- 0x28, 0x2f, 0xff, 0xf0, 0x5e, 0x4b, 0x6e, 0x7d, 0x9f, 0xce, 0x3c, 0xe6,
- 0x69, 0x62, 0x96, 0x2d, 0x05, 0x8a, 0x81, 0x7d, 0xf0, 0xca, 0x82, 0xed,
- 0x5f, 0x65, 0xba, 0x85, 0x29, 0xc8, 0xbe, 0x66, 0x08, 0xc5, 0x0a, 0x19,
- 0x9c, 0x76, 0xf4, 0x6c, 0x82, 0x28, 0x0e, 0x10, 0x57, 0xf0, 0xfe, 0xc6,
- 0x66, 0xcb, 0x17, 0xfe, 0x07, 0xb5, 0x9b, 0x7a, 0x73, 0x8b, 0x15, 0xd4,
- 0xfc, 0x34, 0x61, 0x7f, 0xc5, 0xb1, 0x84, 0x42, 0xd1, 0xab, 0x15, 0x87,
- 0xc0, 0xe4, 0x94, 0xb1, 0x76, 0xba, 0x2c, 0x56, 0x1a, 0x66, 0x0c, 0xbf,
- 0xfe, 0x90, 0x19, 0x9f, 0xf3, 0xf6, 0x1e, 0x77, 0xe5, 0x8b, 0xff, 0xf3,
- 0x1a, 0x67, 0x60, 0x92, 0xdd, 0xbc, 0xdd, 0x81, 0x62, 0xf6, 0xf8, 0x75,
- 0x8b, 0xf4, 0xf6, 0x52, 0x6a, 0xc5, 0xff, 0xfb, 0x79, 0x16, 0xff, 0x9d,
- 0x7d, 0x87, 0xf6, 0xd2, 0xc5, 0x0d, 0x10, 0x38, 0x53, 0x7f, 0x0d, 0xbd,
- 0xc1, 0x41, 0x62, 0xa5, 0x1e, 0x19, 0x09, 0xf3, 0x08, 0xad, 0x02, 0x4d,
- 0xfa, 0x3a, 0x34, 0xab, 0xf9, 0xb5, 0x3e, 0x7e, 0x8b, 0x17, 0xff, 0x72,
- 0x63, 0x6c, 0x83, 0xfb, 0x82, 0x8f, 0x58, 0xae, 0xd1, 0x5c, 0x46, 0x5c,
- 0x2f, 0xbf, 0xff, 0xf6, 0xb5, 0x3d, 0xc3, 0xbe, 0x3e, 0xb7, 0xfe, 0x19,
- 0xa7, 0x91, 0xac, 0x5f, 0x88, 0xd3, 0x33, 0xb5, 0x8b, 0xfe, 0x6d, 0x67,
- 0x70, 0x90, 0x4a, 0xc5, 0x4a, 0x60, 0xb8, 0x60, 0xee, 0x22, 0x2b, 0xbf,
- 0xee, 0xe1, 0xec, 0xe7, 0xb2, 0x3d, 0x62, 0xff, 0xfd, 0xb9, 0xad, 0xcc,
- 0xd4, 0x1f, 0xec, 0x5d, 0xc1, 0x62, 0xff, 0xa7, 0xdc, 0xcf, 0x3f, 0x61,
- 0xac, 0x5e, 0x16, 0x8d, 0x58, 0xad, 0xcf, 0x6a, 0x38, 0xee, 0xb1, 0x1b,
- 0x06, 0xc2, 0xca, 0xa5, 0x33, 0xe6, 0x8c, 0x5a, 0xa5, 0x7c, 0x48, 0x71,
- 0xc3, 0xee, 0x8c, 0xe3, 0xff, 0x97, 0x0a, 0x51, 0xbc, 0xdf, 0xbd, 0x87,
- 0x68, 0x2c, 0x5f, 0x10, 0xba, 0x41, 0x62, 0xa0, 0x79, 0xbc, 0x28, 0xbe,
- 0xf9, 0x34, 0x16, 0x2e, 0x6e, 0x2c, 0x5f, 0xb0, 0xbf, 0x84, 0xb1, 0x7b,
- 0x63, 0x37, 0x58, 0xbe, 0x27, 0x8a, 0x3d, 0x62, 0xa5, 0x19, 0x0e, 0x45,
- 0x11, 0x17, 0xc5, 0xd8, 0x9b, 0x84, 0x37, 0xfa, 0x4b, 0x76, 0x8e, 0x6e,
- 0x8b, 0x17, 0x30, 0x16, 0x2a, 0x08, 0xa4, 0x02, 0xaf, 0x8e, 0x2f, 0xff,
- 0xfe, 0x17, 0xb9, 0xcf, 0x3e, 0x44, 0x79, 0xe4, 0x45, 0x87, 0x34, 0x52,
- 0xb1, 0x7f, 0xfc, 0x59, 0xfc, 0xeb, 0xf6, 0x7e, 0x4f, 0x4c, 0x58, 0xbf,
- 0xe8, 0x67, 0x8f, 0x38, 0x43, 0x58, 0xbf, 0x6f, 0xfc, 0xec, 0x22, 0xc5,
- 0xff, 0xf9, 0x9a, 0x0d, 0xfe, 0xb9, 0xb0, 0xbc, 0x26, 0x31, 0x51, 0x7d,
- 0x97, 0xba, 0x0b, 0xcb, 0x17, 0x48, 0xd6, 0x2a, 0x4d, 0xb8, 0x08, 0x2f,
- 0xe6, 0xf7, 0x1f, 0x8e, 0xb1, 0x7e, 0xdf, 0x6d, 0x0b, 0x65, 0x8b, 0xf6,
- 0xf2, 0x52, 0x05, 0x8a, 0xc3, 0xd5, 0x62, 0xdb, 0xfe, 0x99, 0x1b, 0xee,
- 0xe5, 0xb2, 0xc5, 0xff, 0x39, 0x77, 0x0d, 0x0a, 0x78, 0xb1, 0x76, 0x04,
- 0x58, 0xae, 0x1e, 0x98, 0x67, 0x57, 0xec, 0xd6, 0x0e, 0x56, 0x2e, 0x17,
- 0x96, 0x2f, 0xc1, 0x33, 0x08, 0x0b, 0x14, 0x35, 0x74, 0x3b, 0xba, 0xf6,
- 0xa3, 0x1e, 0x71, 0x11, 0x6e, 0xa1, 0x3a, 0x72, 0x0f, 0xc2, 0x08, 0x88,
- 0x3d, 0x08, 0xce, 0x84, 0x71, 0xc4, 0xe1, 0x06, 0x2f, 0xdf, 0xc8, 0xa6,
- 0x3d, 0x62, 0xfc, 0x3d, 0x6b, 0x03, 0x58, 0xbf, 0xf7, 0xb3, 0xf3, 0xa0,
- 0x13, 0x1a, 0xb1, 0x7c, 0x17, 0x6c, 0xe2, 0xc5, 0x6c, 0x8b, 0xb2, 0x2c,
- 0xe1, 0x50, 0x8f, 0xef, 0xe7, 0x2c, 0xf4, 0xc4, 0xb1, 0x7f, 0xbf, 0x22,
- 0xee, 0x0f, 0x1c, 0xb1, 0x7f, 0xf4, 0x39, 0x27, 0xcd, 0xc9, 0xb3, 0x75,
- 0x8b, 0xe9, 0x23, 0x46, 0xb1, 0x7f, 0xfc, 0xc5, 0xb1, 0x67, 0x7c, 0x6c,
- 0xf6, 0x1d, 0x62, 0xf3, 0x02, 0x56, 0x2f, 0xff, 0x0d, 0xcf, 0xdc, 0x38,
- 0x59, 0xa3, 0x3c, 0xb1, 0x7b, 0x4d, 0x12, 0xc5, 0x4a, 0x7c, 0x10, 0x3d,
- 0xdc, 0xb7, 0xb3, 0x8f, 0xa2, 0xb1, 0x1f, 0x13, 0xfc, 0x38, 0x24, 0xdb,
- 0xa1, 0xc5, 0x8b, 0xf8, 0x39, 0xfb, 0xf7, 0x05, 0x8b, 0xc4, 0xe6, 0xac,
- 0x5f, 0xa0, 0xfb, 0xb6, 0x96, 0x2f, 0xfe, 0x7d, 0xdc, 0x65, 0x9e, 0xe4,
- 0x9d, 0x62, 0xff, 0xf3, 0x16, 0x7a, 0x5f, 0x4e, 0x69, 0xb2, 0xb1, 0x5d,
- 0xa6, 0x06, 0x73, 0x0e, 0x0e, 0xf8, 0xa4, 0xc4, 0x4b, 0x8f, 0x8b, 0x16,
- 0xdd, 0x62, 0xff, 0xfe, 0x7d, 0x1b, 0xf9, 0x3c, 0x50, 0x72, 0xfc, 0xea,
- 0x56, 0x2c, 0x4b, 0x14, 0x03, 0xed, 0x12, 0xe5, 0x62, 0x28, 0xb9, 0x08,
- 0x0a, 0x3a, 0x38, 0x3d, 0x0b, 0x9b, 0xcf, 0xac, 0x58, 0xbc, 0x59, 0x05,
- 0x8a, 0xdc, 0xdc, 0x78, 0x72, 0xe9, 0x3a, 0xc5, 0xe2, 0x93, 0xac, 0x5f,
- 0x98, 0x73, 0x84, 0xb1, 0x52, 0x8d, 0xb7, 0x60, 0x22, 0x2e, 0x0b, 0x88,
- 0x72, 0xff, 0xf1, 0x66, 0xd3, 0xee, 0xe7, 0x42, 0xcd, 0x96, 0x2f, 0xcd,
- 0xfd, 0xdf, 0x8b, 0x15, 0xf3, 0xf5, 0x24, 0xcb, 0xfe, 0x78, 0x7b, 0xf9,
- 0xa7, 0xe2, 0xc5, 0xff, 0xfa, 0x18, 0x43, 0xfc, 0xe1, 0x48, 0x0e, 0xd0,
- 0x58, 0xa9, 0x45, 0x69, 0x10, 0x98, 0x73, 0x7f, 0x77, 0x0f, 0x3f, 0xb8,
- 0xb1, 0x7e, 0x33, 0xed, 0xb6, 0x2c, 0x59, 0xcd, 0x3d, 0xa2, 0x30, 0xbf,
- 0xd9, 0xfe, 0xe1, 0xe9, 0x3a, 0xc5, 0xfa, 0x05, 0x99, 0xb2, 0xc5, 0xda,
- 0xd9, 0x62, 0xff, 0xa2, 0x0a, 0xf9, 0xc6, 0x3c, 0x25, 0x8a, 0x93, 0xff,
- 0xc2, 0x87, 0x19, 0xbf, 0xcc, 0x39, 0x04, 0x87, 0xc5, 0x8a, 0x1a, 0x67,
- 0x78, 0x4f, 0xf8, 0x5a, 0x31, 0x65, 0xf7, 0xa1, 0xe3, 0x56, 0x2f, 0xff,
- 0xfc, 0x6c, 0x97, 0x3e, 0xcf, 0xad, 0x39, 0xcc, 0xf7, 0x7b, 0xb9, 0xd6,
- 0x2f, 0xe8, 0xe0, 0xb5, 0xeb, 0xd7, 0xf1, 0xcb, 0x88, 0x04, 0xbf, 0xde,
- 0x01, 0x85, 0x0f, 0xe2, 0xe2, 0x01, 0x2f, 0x36, 0xa0, 0xb8, 0x80, 0x4a,
- 0xc3, 0xec, 0x12, 0x15, 0xcd, 0x05, 0xc4, 0x02, 0x5f, 0x31, 0x77, 0x05,
- 0xc4, 0x02, 0x5f, 0xe7, 0xdf, 0xf8, 0x00, 0x4a, 0xe2, 0x01, 0x2f, 0x39,
- 0x0d, 0x71, 0x00, 0x94, 0x34, 0x5f, 0x1c, 0x93, 0xe6, 0x1d, 0x10, 0x6c,
- 0x6a, 0xe2, 0x01, 0x2f, 0x6a, 0x7c, 0xb8, 0x80, 0x4a, 0x5c, 0x40, 0x25,
- 0xe8, 0xe7, 0x02, 0xe2, 0x01, 0x2e, 0x93, 0xae, 0x20, 0x18, 0x28, 0x67,
- 0xdd, 0x83, 0x2e, 0x5b, 0x7c, 0xe7, 0x1c, 0xae, 0x20, 0x12, 0xf7, 0x9b,
- 0x75, 0xc4, 0x02, 0x5f, 0xf8, 0x9a, 0x11, 0x9f, 0x7d, 0xdb, 0x4b, 0x88,
- 0x04, 0xbf, 0xf9, 0xbc, 0x2d, 0x9c, 0xbd, 0xf6, 0x82, 0xe2, 0x01, 0x2e,
- 0x61, 0xae, 0x20, 0x12, 0xff, 0x13, 0x07, 0xce, 0x48, 0x17, 0x10, 0x09,
- 0x7e, 0x73, 0x58, 0x80, 0xb8, 0x80, 0x4b, 0x9f, 0x8b, 0x88, 0x04, 0xad,
- 0x1e, 0xcf, 0x8d, 0x6f, 0xff, 0x7d, 0xfd, 0xec, 0xe7, 0x5d, 0x3c, 0x9d,
- 0x71, 0x00, 0x97, 0xef, 0x14, 0xf7, 0x05, 0x44, 0x02, 0x5c, 0x09, 0x5c,
- 0x40, 0x24, 0x61, 0xb6, 0xa5, 0xc4, 0x02, 0x5f, 0x49, 0xd8, 0x6b, 0x88,
- 0x04, 0xa1, 0x9e, 0x43, 0x8c, 0xdf, 0x09, 0x8b, 0x75, 0xc4, 0x02, 0x5e,
- 0x9d, 0x6e, 0xb8, 0x80, 0x4b, 0xff, 0x67, 0x7c, 0x1c, 0xe1, 0x03, 0x8b,
- 0x88, 0x04, 0xbe, 0x39, 0x92, 0x05, 0xc4, 0x02, 0x5f, 0x34, 0x21, 0x2b,
- 0x88, 0x04, 0xac, 0x3e, 0x01, 0x18, 0xdf, 0x9b, 0x7f, 0xcf, 0x6b, 0x88,
- 0x04, 0xac, 0x4c, 0x13, 0xf0, 0xac, 0x11, 0x0d, 0xda, 0x02, 0xe2, 0x01,
- 0x2a, 0x0a, 0xf2, 0x06, 0x49, 0x90, 0x9a, 0xdc, 0x89, 0xe1, 0x1f, 0xf7,
- 0xf0, 0x10, 0xf0, 0xc3, 0xd1, 0x97, 0x88, 0xd6, 0xc7, 0x5c, 0x40, 0x25,
- 0xfb, 0x3d, 0xc6, 0xed, 0x71, 0x00, 0x97, 0xf8, 0x73, 0xbc, 0x5a, 0x9f,
- 0x2e, 0x20, 0x10, 0x66, 0xda, 0xf6, 0xa4, 0x35, 0xc4, 0x02, 0x56, 0x23,
- 0x4f, 0x75, 0x5d, 0x29, 0xdf, 0xe1, 0x34, 0x21, 0x26, 0x1d, 0x71, 0x00,
- 0x97, 0xce, 0x50, 0xe2, 0xe2, 0x01, 0x2f, 0xe6, 0x8a, 0x19, 0xdc, 0x17,
- 0x10, 0x09, 0x58, 0x8d, 0xef, 0x98, 0x01, 0x08, 0x45, 0xf7, 0xfd, 0xf9,
- 0xe4, 0x67, 0x05, 0xa0, 0x2e, 0x20, 0x18, 0x2c, 0xeb, 0x88, 0x04, 0xb9,
- 0xb6, 0x19, 0xf6, 0xfd, 0x3e, 0xed, 0x01, 0x71, 0x00, 0x97, 0xe6, 0xf7,
- 0x1f, 0xb5, 0xc4, 0x02, 0x5f, 0xce, 0x42, 0x86, 0x71, 0x71, 0x00, 0x95,
- 0x28, 0x95, 0x22, 0x5f, 0x1b, 0x54, 0xb2, 0xd9, 0xc7, 0x0b, 0xac, 0x86,
- 0xfb, 0x9f, 0xc4, 0x41, 0xa8, 0x4c, 0x7c, 0xb5, 0x8b, 0xc0, 0x56, 0x49,
- 0xfc, 0x9c, 0x1a, 0xf4, 0xa4, 0xd8, 0xe8, 0x54, 0x99, 0x0c, 0x3b, 0xde,
- 0x70, 0xd7, 0x18, 0x49, 0x79, 0x9b, 0x75, 0x44, 0x02, 0x46, 0x26, 0x2d,
- 0xdc, 0x3a, 0xef, 0xff, 0x31, 0xdb, 0xc2, 0x9e, 0xbc, 0x17, 0x49, 0x58,
- 0xbd, 0x21, 0xf1, 0x62, 0xde, 0x58, 0xbc, 0x59, 0xbe, 0xe6, 0xc1, 0xc7,
- 0xae, 0x19, 0xd6, 0x2f, 0x41, 0xf8, 0xb1, 0x7f, 0xef, 0xe6, 0xf2, 0x7e,
- 0x6d, 0x0d, 0x96, 0x2f, 0xf1, 0xf5, 0x90, 0xfc, 0xc1, 0x62, 0xe2, 0x07,
- 0x8f, 0xdc, 0xc4, 0x3b, 0xfc, 0x2f, 0x67, 0x3d, 0x9b, 0xac, 0x50, 0x5b,
- 0x4c, 0x3e, 0x21, 0x86, 0x84, 0xa0, 0x0b, 0xae, 0xe9, 0x12, 0xc5, 0xfd,
- 0xe2, 0xc0, 0x47, 0x62, 0xc5, 0x6c, 0xa9, 0x4c, 0x6f, 0xc6, 0xc6, 0x83,
- 0xda, 0x49, 0xc6, 0xef, 0xf4, 0x1f, 0xc6, 0x9b, 0x91, 0xeb, 0x17, 0xd3,
- 0xe9, 0x1a, 0xc5, 0xb6, 0x58, 0xa8, 0x1b, 0x5e, 0x84, 0x57, 0xe9, 0xd7,
- 0xda, 0x3d, 0x62, 0xff, 0x14, 0xb7, 0x9b, 0xb0, 0x2c, 0x56, 0xc7, 0xbd,
- 0xe2, 0xbb, 0xfe, 0xe1, 0x49, 0xf9, 0xbc, 0xf1, 0x62, 0xdc, 0x58, 0xbf,
- 0xd9, 0xc2, 0x6e, 0x64, 0x7a, 0xc5, 0xe9, 0x1f, 0xd6, 0x2b, 0xe7, 0xa4,
- 0x46, 0xb5, 0x88, 0xbf, 0xf9, 0xd7, 0x46, 0x4b, 0xec, 0xe9, 0x3f, 0x58,
- 0xa9, 0x4e, 0xe3, 0x21, 0x02, 0xf0, 0xe2, 0xf9, 0x8d, 0xd0, 0x95, 0x8b,
- 0xff, 0x16, 0x6f, 0xf7, 0x00, 0x05, 0x12, 0xc5, 0xf7, 0x99, 0xb4, 0xb1,
- 0x7f, 0xc3, 0xc3, 0x4b, 0x3d, 0x21, 0xac, 0x5f, 0xd9, 0xac, 0x84, 0x25,
- 0x62, 0xff, 0xf1, 0x67, 0x60, 0x6f, 0x71, 0xcb, 0xb8, 0x2c, 0x54, 0x13,
- 0x15, 0xed, 0x04, 0x04, 0x44, 0x75, 0xc2, 0xdb, 0xc3, 0x6f, 0xac, 0x5f,
- 0xb2, 0x2e, 0x4e, 0xcb, 0x16, 0xf6, 0x1e, 0x3f, 0x87, 0x6e, 0x04, 0xa4,
- 0x58, 0xd4, 0x8b, 0xdf, 0x9d, 0x96, 0x2e, 0x0c, 0x34, 0x8a, 0x73, 0xe2,
- 0x8f, 0x17, 0x88, 0x4c, 0x31, 0xeb, 0xfe, 0x83, 0xfb, 0x0f, 0xc6, 0x82,
- 0xc5, 0xb8, 0x91, 0x18, 0x7f, 0x32, 0x81, 0x58, 0x99, 0xa3, 0xc6, 0x05,
- 0x7f, 0xf6, 0x02, 0x0f, 0xe9, 0x3c, 0x90, 0xd6, 0x28, 0xe7, 0xd6, 0xc5,
- 0x17, 0xf6, 0x0f, 0xf2, 0x43, 0x58, 0xbf, 0xfd, 0x9b, 0x66, 0x7c, 0x84,
- 0xde, 0xfe, 0x2c, 0x5f, 0xde, 0xe6, 0x07, 0xf7, 0x58, 0xb7, 0x96, 0x2b,
- 0xc7, 0x82, 0x22, 0xfb, 0xfd, 0x9b, 0xf5, 0xc3, 0xce, 0xeb, 0x17, 0xe9,
- 0xdb, 0x87, 0x82, 0xc5, 0x62, 0x61, 0xaf, 0x08, 0xaf, 0x91, 0x78, 0xde,
- 0xff, 0xfa, 0x1c, 0x2e, 0xe4, 0xde, 0x4f, 0x70, 0x73, 0xac, 0x5f, 0xfd,
- 0xcf, 0x77, 0xbb, 0xeb, 0xcc, 0x0e, 0x2c, 0x57, 0x68, 0x9b, 0x25, 0x3b,
- 0xfe, 0x35, 0xf4, 0x60, 0x01, 0x3d, 0xac, 0x5f, 0x43, 0xd2, 0x1a, 0xc5,
- 0xde, 0xe6, 0x1f, 0x0f, 0x67, 0xb5, 0x1b, 0x37, 0xe9, 0xf3, 0x18, 0xde,
- 0xd2, 0x82, 0x21, 0x1b, 0x48, 0xe3, 0xc4, 0xc4, 0x13, 0x49, 0x77, 0xa6,
- 0x76, 0xbc, 0xaa, 0x68, 0x95, 0x75, 0x28, 0x98, 0xe8, 0xad, 0x19, 0x60,
- 0x25, 0x18, 0x91, 0x0f, 0xa3, 0x3a, 0x14, 0x37, 0x0c, 0x84, 0x25, 0xfe,
- 0x83, 0x8d, 0xb7, 0xe4, 0x16, 0x2f, 0x86, 0x76, 0x82, 0xc5, 0x9d, 0x62,
- 0x98, 0xda, 0x70, 0x8e, 0xb1, 0x11, 0x3e, 0x69, 0xbf, 0xce, 0x5b, 0xbe,
- 0x9c, 0x0b, 0x17, 0xb3, 0x00, 0xb1, 0x7f, 0xc7, 0xdf, 0xee, 0x3f, 0xb9,
- 0xab, 0x14, 0x74, 0x45, 0x91, 0x99, 0x83, 0x95, 0xba, 0x37, 0x7f, 0x0a,
- 0xdb, 0x4a, 0xc5, 0xf7, 0xc4, 0xc4, 0xb1, 0x6f, 0x75, 0x36, 0x63, 0x11,
- 0xbd, 0xbf, 0xc9, 0x62, 0xff, 0xef, 0x47, 0x64, 0x50, 0x6d, 0x6c, 0x39,
- 0x58, 0xae, 0xd1, 0x22, 0x72, 0x92, 0x1e, 0xbe, 0x1b, 0x03, 0x8b, 0x17,
- 0xfb, 0xab, 0xe7, 0x3f, 0x9e, 0x58, 0xac, 0x3d, 0x8e, 0x11, 0xdf, 0xfc,
- 0xd0, 0xea, 0x4f, 0x3d, 0x5c, 0xf8, 0xb1, 0x77, 0x60, 0x58, 0xb0, 0x0e,
- 0x7b, 0xe0, 0x46, 0xbe, 0xcf, 0x19, 0xb2, 0xc5, 0xe8, 0xa4, 0x35, 0x8b,
- 0xff, 0x61, 0xa6, 0xb4, 0x3c, 0xfc, 0x75, 0x8b, 0xff, 0xdf, 0x7e, 0x8f,
- 0xbe, 0xa7, 0x66, 0xd6, 0xeb, 0x17, 0xf4, 0xf7, 0x24, 0xde, 0x58, 0xb8,
- 0x80, 0xb1, 0x74, 0xf1, 0x62, 0x9c, 0xd7, 0x74, 0x17, 0xaf, 0x9f, 0xef,
- 0x45, 0xba, 0xea, 0x9b, 0xa4, 0x92, 0xe0, 0xfe, 0xe8, 0x06, 0x43, 0x32,
- 0xb4, 0xa9, 0xb8, 0xa1, 0x01, 0xe8, 0xe7, 0x2f, 0xff, 0xf7, 0xdc, 0x87,
- 0x87, 0xf4, 0xe6, 0x1c, 0x73, 0x84, 0xb1, 0x7f, 0xb3, 0xbf, 0x79, 0xa1,
- 0xc5, 0x8b, 0xfe, 0x6e, 0xfa, 0x89, 0x8c, 0x7d, 0x96, 0x2f, 0xf1, 0x92,
- 0x1e, 0xa7, 0x09, 0x62, 0xe0, 0xbc, 0x16, 0x2f, 0xcc, 0x69, 0x64, 0x4b,
- 0x15, 0x03, 0xc5, 0x21, 0xcb, 0xbb, 0x82, 0xe3, 0x00, 0x2f, 0xff, 0x60,
- 0x73, 0xec, 0x8a, 0x0f, 0xee, 0x32, 0xc5, 0x41, 0x30, 0xbe, 0xde, 0x48,
- 0x87, 0x84, 0xd7, 0xc2, 0x62, 0xdd, 0x62, 0xe0, 0x41, 0x62, 0xff, 0xc4,
- 0xde, 0x17, 0x87, 0xf7, 0x35, 0x62, 0xf4, 0xe7, 0xc8, 0xf6, 0x38, 0x31,
- 0x7e, 0x79, 0xf4, 0x8d, 0x62, 0xff, 0x9f, 0xbe, 0x78, 0xa4, 0xfc, 0x58,
- 0xbf, 0xff, 0xff, 0xff, 0x85, 0x1e, 0x4d, 0x9f, 0x63, 0x0b, 0x3a, 0x61,
- 0x31, 0xb1, 0x40, 0x5c, 0xe0, 0x6c, 0x3f, 0xb8, 0x7c, 0xc6, 0x1a, 0xc5,
- 0x1a, 0x8f, 0x7e, 0x1d, 0x5f, 0xee, 0x61, 0x37, 0x46, 0xfa, 0xc5, 0xfc,
- 0xdf, 0x89, 0x9f, 0x65, 0x8a, 0x96, 0x44, 0x4e, 0x43, 0xb5, 0xe5, 0x7b,
- 0x44, 0x79, 0xa5, 0xd3, 0x9a, 0xb4, 0x69, 0x20, 0x3e, 0x27, 0xbe, 0x18,
- 0xfa, 0x31, 0xe1, 0x12, 0x06, 0x69, 0x7f, 0xfe, 0x22, 0x17, 0x79, 0xdf,
- 0x87, 0xa6, 0xef, 0x36, 0x58, 0xbf, 0x67, 0xb5, 0x3c, 0x58, 0xa7, 0x44,
- 0x09, 0x2c, 0xdf, 0x39, 0x49, 0xd6, 0x2e, 0x98, 0x2c, 0x56, 0x1b, 0x80,
- 0x10, 0xdf, 0xc4, 0xdd, 0xcb, 0xc4, 0xb1, 0x6d, 0x96, 0x29, 0x62, 0xf4,
- 0x50, 0x9d, 0x17, 0xe0, 0x13, 0xbe, 0x93, 0x64, 0xeb, 0x17, 0xa0, 0x37,
- 0x58, 0xa8, 0x26, 0x71, 0xda, 0xcb, 0x90, 0x69, 0x34, 0xe6, 0x44, 0x47,
- 0x7f, 0x16, 0x1e, 0x74, 0x6a, 0xc5, 0xfb, 0xcf, 0xd3, 0xee, 0xb1, 0x74,
- 0x39, 0xd4, 0xf6, 0x30, 0xba, 0xfe, 0xe6, 0x30, 0xdb, 0xcb, 0x17, 0xff,
- 0xf1, 0xcc, 0xcf, 0xb1, 0xf0, 0xef, 0xec, 0x35, 0xf4, 0xb1, 0x7f, 0xa4,
- 0xf8, 0x13, 0xce, 0x1a, 0xc5, 0x4a, 0x24, 0xb8, 0xb9, 0x7f, 0xfd, 0x9a,
- 0x88, 0xa4, 0x1c, 0xdf, 0xef, 0xad, 0x96, 0x2a, 0x07, 0xeb, 0xc2, 0x2b,
- 0xf7, 0x5e, 0xb9, 0xf6, 0x58, 0xbf, 0xef, 0x39, 0x75, 0xdd, 0xb5, 0xb2,
- 0xc5, 0xff, 0x77, 0xc7, 0xee, 0x1f, 0x7f, 0xac, 0x5f, 0xf7, 0xd9, 0xfd,
- 0x0f, 0x88, 0xd5, 0x8b, 0xcd, 0xfe, 0x2c, 0x53, 0x22, 0x53, 0x87, 0x81,
- 0x9d, 0xdf, 0xd0, 0x9d, 0x00, 0xc3, 0xac, 0x5f, 0xe9, 0xe3, 0x01, 0x88,
- 0x0b, 0x17, 0xd1, 0x7d, 0xe2, 0x58, 0xbf, 0xf1, 0xa6, 0xb9, 0x6f, 0xd7,
- 0x6f, 0x9a, 0xb1, 0x58, 0x7d, 0x8e, 0x4b, 0x7f, 0xff, 0xfb, 0xef, 0xe9,
- 0xd3, 0x38, 0xc5, 0x3c, 0x9d, 0x0a, 0x0f, 0xac, 0x02, 0xc5, 0xff, 0xdd,
- 0x0b, 0x39, 0xec, 0x28, 0x67, 0x16, 0x2f, 0x8f, 0x22, 0xf2, 0xc5, 0x61,
- 0xf4, 0x32, 0x2d, 0xf4, 0x34, 0xe7, 0x58, 0xbd, 0xe1, 0x1a, 0xb1, 0x62,
- 0x63, 0xc2, 0x11, 0x1d, 0xfc, 0xff, 0x6f, 0xbf, 0x16, 0x2f, 0x79, 0xb4,
- 0xb1, 0x47, 0x3c, 0xaf, 0x16, 0xdf, 0xb2, 0x2f, 0xce, 0xcb, 0x15, 0x88,
- 0xbc, 0x67, 0x02, 0x22, 0xbf, 0xff, 0xb2, 0x2e, 0x4e, 0xc5, 0x81, 0xb6,
- 0x8d, 0xce, 0xfc, 0xb1, 0x7f, 0xe2, 0x6f, 0x71, 0xfb, 0x29, 0x0d, 0x62,
- 0xf7, 0x98, 0x96, 0x2c, 0xdd, 0x57, 0x00, 0x70, 0xc3, 0x46, 0x1f, 0x84,
- 0xf3, 0x10, 0x14, 0x37, 0xb9, 0x18, 0xf7, 0x8b, 0x4c, 0x5f, 0x08, 0x7f,
- 0x7f, 0x98, 0x0c, 0x64, 0x4d, 0xe5, 0x8a, 0xea, 0xbb, 0xb1, 0x25, 0x9f,
- 0x9c, 0xd2, 0x04, 0x29, 0x6f, 0xfa, 0x63, 0xc7, 0xf9, 0xd9, 0x89, 0x62,
- 0xfd, 0x85, 0x3d, 0xf1, 0x62, 0xff, 0xfa, 0x4e, 0x61, 0x7b, 0xe2, 0x68,
- 0x7c, 0x5c, 0x58, 0xb9, 0xfc, 0xb1, 0x71, 0xe5, 0x62, 0xf0, 0x33, 0xf2,
- 0x6b, 0x9c, 0x5e, 0xfe, 0xe7, 0xbb, 0x84, 0x98, 0xb1, 0x7f, 0xb7, 0x2c,
- 0xe9, 0xf6, 0x82, 0xc5, 0xe3, 0x81, 0xd6, 0x2f, 0xa7, 0x79, 0x3f, 0x54,
- 0x42, 0x61, 0x8b, 0x9b, 0x54, 0x19, 0x2b, 0x7d, 0xc6, 0x69, 0xa9, 0xdf,
- 0xaf, 0xa7, 0x31, 0xe1, 0x14, 0x7a, 0x10, 0x01, 0x21, 0x69, 0x7f, 0x18,
- 0x1e, 0x9f, 0x3e, 0x91, 0x7f, 0x9b, 0xd3, 0x01, 0x0f, 0x16, 0x2f, 0xbf,
- 0x39, 0xb2, 0xc5, 0x11, 0xeb, 0x70, 0xce, 0xfb, 0x8f, 0x20, 0x58, 0xbf,
- 0xef, 0x4f, 0x7e, 0xc3, 0xcf, 0xd6, 0x2f, 0xa2, 0xcc, 0x0d, 0x62, 0xfa,
- 0x0f, 0xae, 0x2c, 0x5f, 0xfc, 0x61, 0xf3, 0xd3, 0xd1, 0xfd, 0x09, 0x58,
- 0xbe, 0x7f, 0x4e, 0x96, 0x2f, 0xf9, 0xf3, 0xbf, 0x45, 0x06, 0xd2, 0xc5,
- 0x80, 0xe8, 0xa4, 0xfa, 0x39, 0x11, 0x5f, 0xfa, 0x05, 0x27, 0xfc, 0xee,
- 0xda, 0x58, 0xb9, 0xf1, 0x62, 0xbb, 0x3d, 0x50, 0x1f, 0xdf, 0x45, 0xf6,
- 0x89, 0x62, 0xfb, 0x76, 0xd6, 0xcb, 0x17, 0xa2, 0x6f, 0x2c, 0x5f, 0xb2,
- 0x28, 0x4f, 0x6b, 0x17, 0xfd, 0xf9, 0xe7, 0xdb, 0x93, 0x1e, 0xb1, 0x73,
- 0xc4, 0xb1, 0x79, 0xe4, 0x96, 0x2f, 0xdf, 0x78, 0xa7, 0x65, 0x8b, 0xf6,
- 0x68, 0x7f, 0xc5, 0x8a, 0x19, 0xf6, 0xee, 0x37, 0xc2, 0xaa, 0xfa, 0x2d,
- 0x79, 0x08, 0x5b, 0xcc, 0x40, 0x58, 0xbf, 0xbf, 0x9e, 0xe6, 0x06, 0xb1,
- 0x78, 0xa6, 0x09, 0x17, 0xfe, 0x20, 0x38, 0x40, 0x82, 0x84, 0xc7, 0xac,
- 0x58, 0xeb, 0x15, 0xd5, 0x17, 0xe3, 0x1c, 0xc2, 0xf6, 0x1c, 0x31, 0x1a,
- 0xba, 0xae, 0x64, 0xc9, 0x0e, 0xc4, 0x43, 0x3a, 0xc2, 0x4e, 0xe1, 0x8e,
- 0xf0, 0x89, 0xd1, 0x1f, 0xc9, 0x58, 0x94, 0x87, 0xb8, 0x55, 0xe8, 0x78,
- 0x84, 0x87, 0x3d, 0xfe, 0x98, 0xfc, 0xd6, 0xa7, 0x65, 0x8a, 0x96, 0xc4,
- 0x93, 0x21, 0x5e, 0xf4, 0x98, 0xaf, 0xc2, 0x39, 0xa7, 0x53, 0xc5, 0x0d,
- 0x7b, 0xda, 0x6f, 0x2c, 0x5f, 0xb9, 0xad, 0x4f, 0x96, 0x2f, 0xef, 0xb6,
- 0x00, 0xcf, 0x2c, 0x5f, 0x71, 0xf5, 0xb2, 0xc5, 0x61, 0xe9, 0xf0, 0xbe,
- 0xf7, 0x9f, 0x65, 0x8a, 0xd9, 0x1b, 0x1d, 0x8e, 0xc7, 0xbe, 0x1c, 0x86,
- 0xf6, 0x7d, 0x96, 0x2f, 0x69, 0xb7, 0x58, 0xbf, 0x4e, 0xb3, 0xbf, 0x2c,
- 0x5b, 0x86, 0x9e, 0x3f, 0xc7, 0xaf, 0xf4, 0x45, 0x83, 0xfc, 0xf1, 0x62,
- 0xff, 0x66, 0xbf, 0x21, 0x96, 0x2c, 0x5f, 0xfd, 0x80, 0x03, 0x77, 0xce,
- 0x49, 0x6e, 0xb1, 0x68, 0x2c, 0x51, 0x1e, 0xc7, 0x11, 0xaa, 0x09, 0x84,
- 0xfc, 0xa4, 0x06, 0x9d, 0x21, 0x17, 0x7f, 0xd8, 0x5b, 0xfd, 0xfa, 0x4f,
- 0x16, 0x2e, 0xf7, 0x16, 0x2a, 0x07, 0xa6, 0x47, 0x77, 0xff, 0x67, 0x82,
- 0x91, 0xb8, 0x51, 0xfb, 0xe0, 0xb8, 0xb1, 0x7f, 0xb7, 0xfb, 0x8e, 0x4b,
- 0xcb, 0x17, 0x3c, 0x16, 0x2b, 0xb3, 0xcb, 0x23, 0x4b, 0x88, 0x0b, 0x17,
- 0xed, 0x7d, 0x98, 0xeb, 0x17, 0xc2, 0x21, 0x6e, 0xb1, 0x4c, 0x79, 0x9c,
- 0x28, 0xbf, 0xbd, 0x14, 0x33, 0xb8, 0x2c, 0x57, 0x55, 0x73, 0x73, 0x1b,
- 0x63, 0xc2, 0x60, 0xe4, 0x2d, 0x09, 0xff, 0x11, 0x09, 0x8c, 0xc2, 0x1b,
- 0xfe, 0x33, 0x30, 0x5f, 0xce, 0x92, 0xb1, 0x7f, 0xe0, 0xe7, 0x5c, 0xc0,
- 0xdb, 0x46, 0xac, 0x5d, 0xbb, 0x2c, 0x5e, 0xce, 0x09, 0x62, 0xff, 0xfd,
- 0xfc, 0xdc, 0x84, 0x32, 0x93, 0x34, 0xf2, 0x4b, 0x15, 0x89, 0x83, 0xfc,
- 0xed, 0x90, 0x88, 0x63, 0xc3, 0xb7, 0xf8, 0x3c, 0xef, 0xde, 0x93, 0xac,
- 0x5f, 0x8b, 0x00, 0x2e, 0x2c, 0x5f, 0xf6, 0xef, 0x85, 0x9d, 0x1b, 0x8b,
- 0x15, 0xb1, 0xf1, 0x7c, 0xa2, 0x99, 0x17, 0x7c, 0x84, 0xc5, 0xf0, 0xc7,
- 0x87, 0x58, 0xb8, 0x12, 0x91, 0x70, 0x61, 0xa4, 0x53, 0x9b, 0x10, 0xc5,
- 0xef, 0x84, 0xda, 0x82, 0x44, 0x61, 0xa1, 0xbe, 0xcd, 0x4f, 0x16, 0x28,
- 0x67, 0xb1, 0xc3, 0x6a, 0xc4, 0x77, 0x9b, 0x0c, 0xdb, 0xff, 0xde, 0xef,
- 0x77, 0xfc, 0x74, 0xfb, 0xe6, 0x71, 0x62, 0xff, 0x1d, 0xa1, 0xb6, 0x85,
- 0xb2, 0xc5, 0x82, 0xc5, 0x8b, 0xfd, 0x30, 0x7f, 0x42, 0x7c, 0xb1, 0x70,
- 0x5f, 0x8b, 0x11, 0xac, 0xf2, 0xb4, 0x2f, 0x7d, 0x14, 0x24, 0x0b, 0x17,
- 0xfd, 0xf6, 0xf7, 0x37, 0x2c, 0xd9, 0x62, 0xf1, 0xc4, 0x6a, 0xc5, 0xe0,
- 0xb7, 0x1b, 0x46, 0xcb, 0x17, 0xfe, 0xd1, 0x30, 0x6f, 0xed, 0x08, 0xeb,
- 0x17, 0x6e, 0xeb, 0x17, 0xfe, 0x98, 0xf1, 0x6b, 0x35, 0xa9, 0xed, 0x62,
- 0xf8, 0x9f, 0xb8, 0x2c, 0x5f, 0xf3, 0xf7, 0xfc, 0x1e, 0x9b, 0x75, 0x8a,
- 0x93, 0xde, 0xd1, 0x1d, 0xf6, 0x74, 0xc2, 0x58, 0xbb, 0x06, 0xb1, 0x7e,
- 0x63, 0xe1, 0x79, 0x62, 0xa0, 0x6f, 0xb4, 0x2f, 0x7f, 0xb9, 0x8f, 0xe3,
- 0x5f, 0xeb, 0x17, 0xfd, 0xf9, 0xd4, 0xee, 0xe5, 0xba, 0xc5, 0xe3, 0x5b,
- 0x81, 0x6d, 0x51, 0xc0, 0xcb, 0xb7, 0x40, 0xec, 0x63, 0x50, 0xa1, 0xf9,
- 0x0b, 0x30, 0xf8, 0x84, 0x21, 0xa5, 0xf7, 0xbd, 0x3a, 0x58, 0xa9, 0x56,
- 0xf3, 0x84, 0x8e, 0x77, 0xe9, 0x4a, 0xe6, 0x42, 0x82, 0xa0, 0xbe, 0x47,
- 0xdc, 0x60, 0x7a, 0x8c, 0x58, 0xe5, 0x00, 0x52, 0x14, 0x20, 0x43, 0x97,
- 0x73, 0x7e, 0xfb, 0xf0, 0x5b, 0x2c, 0x5f, 0xfc, 0xe3, 0x7f, 0x4f, 0x61,
- 0xe6, 0x71, 0x62, 0xd1, 0xb2, 0xc5, 0x2c, 0x58, 0x29, 0xd4, 0xd1, 0xc6,
- 0xc2, 0xf6, 0x8d, 0x96, 0x2f, 0x9b, 0xc5, 0x2b, 0x15, 0xd4, 0xfa, 0x82,
- 0x86, 0x46, 0x8b, 0xd0, 0xd3, 0x08, 0x0e, 0x1a, 0x57, 0xff, 0xfb, 0xf3,
- 0xf7, 0x37, 0x04, 0x17, 0x7f, 0xbe, 0xa1, 0x3a, 0x58, 0xb8, 0x5a, 0x58,
- 0xa8, 0x1f, 0xe9, 0xd9, 0x6f, 0x6e, 0xfc, 0x58, 0xbe, 0x11, 0xf0, 0x6b,
- 0x15, 0xda, 0x61, 0x4f, 0x0a, 0x7f, 0x91, 0x04, 0x1e, 0xbf, 0xff, 0xb5,
- 0x01, 0x4e, 0x7f, 0x77, 0xe6, 0x0f, 0x6c, 0x0d, 0x62, 0xff, 0xb0, 0x23,
- 0x11, 0xb9, 0xdf, 0x96, 0x2f, 0xda, 0x1f, 0xde, 0x25, 0x8a, 0xf9, 0xf3,
- 0x18, 0x79, 0x7c, 0x29, 0x23, 0x56, 0x2f, 0xef, 0xb8, 0xfe, 0x23, 0x56,
- 0x2f, 0xc5, 0x31, 0x3f, 0x6b, 0x16, 0xc1, 0x9f, 0xe6, 0xe4, 0x6e, 0x61,
- 0x7b, 0xd9, 0xba, 0xc5, 0x1c, 0xf4, 0xb8, 0x69, 0x7a, 0x07, 0x02, 0xc5,
- 0xfb, 0xc5, 0x9a, 0x95, 0x8a, 0x95, 0x43, 0x86, 0xc3, 0x10, 0x10, 0xf1,
- 0xf1, 0x10, 0x63, 0xd7, 0x89, 0xcd, 0x58, 0xbf, 0xf1, 0x9c, 0x9c, 0xe6,
- 0xb4, 0xfe, 0x58, 0xac, 0x3d, 0xde, 0x0e, 0xdf, 0xa4, 0xe4, 0xe6, 0xac,
- 0x5c, 0x3f, 0xac, 0x5c, 0x6b, 0x75, 0x3c, 0x0c, 0x28, 0xbf, 0xf3, 0x70,
- 0xf2, 0xfa, 0xd3, 0x86, 0xb1, 0x7e, 0xdb, 0x07, 0x27, 0x58, 0xb7, 0x0d,
- 0x44, 0xbf, 0xcb, 0xcc, 0x3f, 0xb9, 0xc2, 0x2c, 0x5f, 0xff, 0xfd, 0xf9,
- 0xe6, 0x02, 0x7d, 0xcd, 0x66, 0xd3, 0xae, 0x7f, 0x77, 0xe2, 0xc5, 0xf6,
- 0xb4, 0xc3, 0x58, 0xbd, 0x06, 0xd2, 0xc5, 0x0d, 0x16, 0x98, 0xe8, 0xc4,
- 0x77, 0xf1, 0xf5, 0xa7, 0xec, 0x0b, 0x17, 0x8c, 0x73, 0xac, 0x5f, 0x9f,
- 0x53, 0xe7, 0x58, 0xbc, 0xdf, 0x89, 0x62, 0xa4, 0xf1, 0x7c, 0x4f, 0x7f,
- 0x14, 0xef, 0xf7, 0x08, 0xb1, 0x78, 0xd9, 0xe2, 0xc5, 0xff, 0x67, 0xbc,
- 0xe6, 0xfb, 0x37, 0x58, 0xbf, 0xa7, 0xbe, 0x67, 0x7e, 0x58, 0xbb, 0x52,
- 0xb1, 0x43, 0x3c, 0x7f, 0x18, 0x5f, 0x84, 0x43, 0x8d, 0x23, 0x45, 0x8b,
- 0xff, 0xef, 0x6a, 0x73, 0xb8, 0xe2, 0x38, 0xbc, 0x06, 0x58, 0xbf, 0xde,
- 0x7d, 0xdc, 0x73, 0xe5, 0x8b, 0xf7, 0x27, 0x7c, 0x3a, 0xc5, 0x49, 0xee,
- 0xf0, 0xd2, 0xf9, 0xfb, 0x86, 0x2c, 0x5f, 0xf1, 0xb2, 0x50, 0xcd, 0x85,
- 0x05, 0x8b, 0xfe, 0x1f, 0xe6, 0x11, 0x68, 0x5b, 0x2c, 0x57, 0x55, 0x56,
- 0x72, 0x43, 0x03, 0x01, 0x8f, 0x64, 0x20, 0xb7, 0x22, 0xec, 0xcf, 0x50,
- 0xb1, 0x01, 0x0f, 0x88, 0xcc, 0x3b, 0xa9, 0x57, 0x7b, 0xc9, 0x62, 0xd5,
- 0x05, 0xe4, 0x3e, 0xe1, 0xf1, 0xa3, 0x83, 0xc3, 0x35, 0x8b, 0xbd, 0x2f,
- 0xb6, 0xf9, 0xbb, 0xc1, 0xac, 0x5f, 0xef, 0xe4, 0x3c, 0xef, 0xda, 0xc5,
- 0xff, 0x79, 0xf6, 0x9e, 0xc1, 0xa9, 0x58, 0xbb, 0xfb, 0x2c, 0x5d, 0xe3,
- 0x56, 0x2f, 0x73, 0xd8, 0xb1, 0x6e, 0x75, 0x44, 0x56, 0xe7, 0x64, 0x32,
- 0x60, 0xcd, 0xff, 0x6c, 0xd8, 0x42, 0x86, 0x71, 0x62, 0xb0, 0xff, 0xf8,
- 0x8d, 0x7e, 0x60, 0x47, 0x39, 0xd6, 0x2f, 0xed, 0xdf, 0x82, 0x83, 0xac,
- 0x5e, 0x21, 0x71, 0x62, 0xbe, 0x79, 0x9d, 0x0b, 0xee, 0x0b, 0x23, 0x96,
- 0x2f, 0xd1, 0x61, 0x0b, 0x16, 0x2f, 0xef, 0x3f, 0x70, 0x29, 0x8d, 0x8f,
- 0x22, 0x48, 0x2f, 0xbb, 0xf7, 0xdd, 0x62, 0xf9, 0xf6, 0x0a, 0x1a, 0xb1,
- 0x60, 0x61, 0xe6, 0xee, 0x49, 0x58, 0x8b, 0xd7, 0x84, 0xad, 0xff, 0x33,
- 0xf9, 0xcb, 0xc2, 0xfa, 0xc5, 0xef, 0xbf, 0x45, 0x8b, 0x85, 0x0f, 0x9e,
- 0xb9, 0x87, 0x17, 0xff, 0x30, 0xfe, 0xfa, 0xce, 0x92, 0x51, 0x2c, 0x5f,
- 0xfd, 0xc1, 0x68, 0xb0, 0x7f, 0x90, 0xe5, 0x62, 0xd3, 0xd5, 0x11, 0x7e,
- 0x46, 0xb8, 0x7b, 0xac, 0x5d, 0x9d, 0x06, 0x78, 0x60, 0x2a, 0xbf, 0xc6,
- 0xfb, 0xbd, 0xdf, 0x5c, 0x58, 0xbf, 0x67, 0x80, 0xde, 0x58, 0xa9, 0x56,
- 0x65, 0x08, 0xca, 0x74, 0xfb, 0xf8, 0x7e, 0x88, 0xbe, 0x38, 0xe2, 0xff,
- 0xfd, 0x3f, 0x6c, 0x29, 0xd1, 0xa3, 0x13, 0x6a, 0x0b, 0x15, 0x05, 0xc8,
- 0x5e, 0x10, 0xfa, 0x5d, 0x48, 0x46, 0x6a, 0x96, 0xca, 0xb8, 0x70, 0x81,
- 0xc9, 0x47, 0x8f, 0x29, 0x85, 0xa7, 0xbd, 0xc0, 0xd7, 0xe2, 0x31, 0x4e,
- 0xe1, 0x5f, 0xff, 0xbd, 0x23, 0x03, 0x76, 0x07, 0xec, 0xcd, 0x37, 0x6b,
- 0x17, 0x39, 0xd6, 0x2e, 0x68, 0x2c, 0x5d, 0xac, 0x58, 0xa7, 0x35, 0xcc,
- 0x2f, 0x68, 0xe5, 0x8a, 0x94, 0x69, 0xc1, 0x6b, 0xe8, 0xb1, 0xc3, 0xf7,
- 0xf1, 0x43, 0x38, 0x61, 0xd6, 0x2f, 0x08, 0xbc, 0xb1, 0x58, 0x79, 0x9c,
- 0x2f, 0xbf, 0x1f, 0x80, 0x66, 0x58, 0xaf, 0x1e, 0x49, 0x84, 0x37, 0xfb,
- 0x0b, 0xaf, 0xf3, 0xb0, 0xd6, 0x2f, 0xe9, 0xfb, 0xf4, 0xc8, 0x96, 0x2b,
- 0x47, 0xce, 0x03, 0x7b, 0xf4, 0x4c, 0xc5, 0xb2, 0xc5, 0xfc, 0x20, 0x75,
- 0xdc, 0xe0, 0x58, 0xb4, 0x30, 0xf7, 0x08, 0xa6, 0xfc, 0x58, 0x01, 0x71,
- 0x62, 0xb6, 0x54, 0x55, 0x08, 0x6a, 0x64, 0x22, 0xbb, 0x7e, 0x01, 0x35,
- 0xfe, 0xee, 0x1f, 0x08, 0x12, 0x63, 0xd6, 0x2f, 0xf9, 0xfb, 0x86, 0xdb,
- 0x03, 0xb0, 0x2c, 0x56, 0x1f, 0xe7, 0xcf, 0x6f, 0x8c, 0xd3, 0x01, 0x62,
- 0xff, 0xb8, 0xf0, 0x7f, 0x4f, 0xb8, 0xb1, 0x50, 0x3d, 0xdf, 0x92, 0x5f,
- 0xfe, 0x01, 0x0b, 0x9e, 0xe4, 0xeb, 0x3b, 0xf2, 0xc5, 0xff, 0xfc, 0x50,
- 0xea, 0x61, 0x4f, 0x0b, 0x3a, 0x3f, 0xff, 0x2b, 0x17, 0xfb, 0x99, 0xa2,
- 0x9e, 0xe0, 0xb1, 0x71, 0x01, 0x62, 0xb6, 0x3c, 0xb6, 0x34, 0xa6, 0x4c,
- 0xe4, 0x88, 0x84, 0x98, 0x1c, 0x2a, 0x6f, 0xf6, 0x74, 0xcd, 0x00, 0x02,
- 0x58, 0xbf, 0xf9, 0xf5, 0xd5, 0xa6, 0x12, 0x42, 0x82, 0xc5, 0xe1, 0x8a,
- 0x56, 0x2f, 0xa7, 0x59, 0xd1, 0x62, 0xfd, 0xf7, 0x8e, 0x6d, 0x96, 0x2a,
- 0x08, 0xb2, 0x74, 0x5e, 0x0e, 0xf8, 0x92, 0xff, 0x03, 0x98, 0x59, 0xc1,
- 0x2c, 0x56, 0x1f, 0x7b, 0x1e, 0x5f, 0xe9, 0x88, 0x5c, 0xf3, 0x9d, 0x62,
- 0xd0, 0x58, 0xbf, 0xd3, 0x9d, 0xfb, 0x35, 0x2b, 0x15, 0xb1, 0xfd, 0x68,
- 0xd4, 0x84, 0xaf, 0xfd, 0x3f, 0x33, 0x85, 0x9e, 0xfe, 0x2c, 0x5f, 0xfd,
- 0xf1, 0x73, 0x93, 0xad, 0xf0, 0xcc, 0x58, 0xbd, 0x80, 0x65, 0x8b, 0xf3,
- 0xf7, 0xe3, 0x36, 0x58, 0xb7, 0x47, 0x44, 0x7f, 0xd1, 0xf8, 0x39, 0x7a,
- 0x41, 0x8b, 0x17, 0xff, 0x40, 0xd6, 0x33, 0xcf, 0xa9, 0x10, 0x5d, 0x62,
- 0xbe, 0x7c, 0xec, 0x39, 0x58, 0x8b, 0xf1, 0x42, 0x7a, 0xff, 0xb3, 0xbf,
- 0xbe, 0xc4, 0xd0, 0x58, 0xbd, 0xf9, 0xed, 0x62, 0xff, 0xff, 0x7b, 0xce,
- 0x46, 0xf5, 0xf1, 0xa2, 0xd7, 0x38, 0xf9, 0xda, 0xc5, 0xfe, 0xce, 0xfd,
- 0xfc, 0x16, 0xeb, 0x17, 0xed, 0x67, 0x46, 0xfa, 0xc5, 0xfb, 0x69, 0x29,
- 0xed, 0x62, 0x89, 0x11, 0x3c, 0x36, 0x11, 0x55, 0xfb, 0x77, 0x92, 0x82,
- 0xc5, 0x76, 0x7a, 0xe4, 0x5f, 0x58, 0x9b, 0x4b, 0x46, 0x8f, 0x52, 0xc8,
- 0x89, 0xc8, 0x69, 0xbc, 0x76, 0xfa, 0x42, 0xfc, 0x6a, 0xed, 0x09, 0xa0,
- 0x17, 0x94, 0x71, 0xbc, 0x27, 0xf1, 0xd0, 0xa3, 0x87, 0xbf, 0xff, 0x1a,
- 0xfe, 0x2c, 0x87, 0x7e, 0x27, 0xdb, 0x82, 0x58, 0xbf, 0x72, 0x4b, 0x36,
- 0x58, 0xb8, 0x72, 0xb1, 0x6e, 0x92, 0x6f, 0xc6, 0x51, 0x7f, 0xf6, 0x6b,
- 0xae, 0x7d, 0x8d, 0x21, 0x71, 0x62, 0x9d, 0x30, 0x66, 0x84, 0xb8, 0x8a,
- 0x2f, 0xfc, 0x6b, 0x6f, 0xf7, 0x8b, 0x3b, 0xf2, 0xc5, 0xf7, 0x70, 0x8a,
- 0x3d, 0x62, 0xec, 0x02, 0xc5, 0xcd, 0x06, 0x3c, 0x02, 0x29, 0xb9, 0xfe,
- 0xb1, 0x7f, 0xff, 0x6a, 0x1d, 0x47, 0xf9, 0xea, 0x59, 0xdf, 0xa7, 0x03,
- 0x58, 0xbb, 0x9c, 0x58, 0xbf, 0x4e, 0x7b, 0x8c, 0xb1, 0x7e, 0x67, 0xe0,
- 0x8d, 0x58, 0xbc, 0x18, 0x61, 0xac, 0x5c, 0x06, 0x48, 0x8c, 0x34, 0x37,
- 0xfb, 0x53, 0xd3, 0x30, 0xe3, 0x58, 0xae, 0xa9, 0xb0, 0x38, 0xbe, 0x98,
- 0x4e, 0x31, 0xf2, 0x7e, 0x25, 0x08, 0xaa, 0xfa, 0x0e, 0x46, 0xac, 0x5f,
- 0xe2, 0x63, 0x62, 0x27, 0x89, 0x62, 0xa2, 0x3d, 0x8e, 0x11, 0xdf, 0x0b,
- 0xc2, 0x65, 0x8a, 0xc3, 0xc6, 0x22, 0x3b, 0xf8, 0x13, 0x0f, 0x99, 0xc5,
- 0x8b, 0xc1, 0x70, 0xbc, 0xac, 0x5f, 0xf8, 0x27, 0x5c, 0xdd, 0xfd, 0xc1,
- 0x69, 0x62, 0xf8, 0x40, 0xc2, 0x58, 0xa7, 0x3e, 0x7e, 0x22, 0xdf, 0xce,
- 0x40, 0xdf, 0x77, 0x58, 0xbc, 0xc0, 0xc4, 0x8a, 0x82, 0xe4, 0x77, 0x66,
- 0x9a, 0x84, 0x19, 0xe3, 0x8b, 0xfc, 0x60, 0x80, 0x20, 0x23, 0x0f, 0x42,
- 0x33, 0xa1, 0x0c, 0x71, 0x7d, 0xf4, 0x8d, 0xc6, 0xb1, 0x7e, 0xe9, 0x99,
- 0xd0, 0xd5, 0x8b, 0xff, 0xee, 0xfd, 0x23, 0xc2, 0x2c, 0x37, 0x08, 0x0b,
- 0x15, 0x27, 0xf9, 0xa2, 0xdb, 0xfb, 0x9f, 0x7d, 0xdb, 0x4b, 0x17, 0xe1,
- 0xe9, 0xc5, 0xb2, 0xc5, 0xf7, 0xb8, 0xdd, 0xac, 0x5b, 0xcb, 0x15, 0x86,
- 0xd8, 0xd2, 0x4b, 0xff, 0xce, 0x6f, 0xdc, 0xcd, 0x7a, 0x13, 0x1d, 0x8b,
- 0x17, 0xf8, 0x3c, 0x2c, 0xe8, 0xfa, 0x58, 0xbc, 0xf0, 0x95, 0x8b, 0xdb,
- 0x98, 0x75, 0x8b, 0xc0, 0x30, 0xeb, 0x15, 0x11, 0xed, 0x80, 0x73, 0xc4,
- 0x17, 0xf1, 0x67, 0x60, 0x32, 0x0b, 0x17, 0x67, 0x16, 0x2f, 0xb0, 0xef,
- 0xe5, 0x8b, 0xff, 0xb3, 0xe6, 0x1f, 0x37, 0x9f, 0xc9, 0xd6, 0x2d, 0xcc,
- 0x3f, 0xf2, 0x17, 0xf1, 0x15, 0xb8, 0xb1, 0x58, 0xaa, 0xce, 0x22, 0xfd,
- 0x30, 0x7c, 0x84, 0x93, 0xf9, 0x09, 0x0f, 0x18, 0x0a, 0x15, 0xe1, 0x99,
- 0xdf, 0xbf, 0xf6, 0x1c, 0xac, 0x5e, 0xf7, 0xf1, 0x62, 0xff, 0xfd, 0x3d,
- 0x0c, 0xd3, 0x03, 0x35, 0xa7, 0x36, 0x74, 0xb1, 0x58, 0x7e, 0xda, 0x1d,
- 0xbe, 0x93, 0xf5, 0xe2, 0xc5, 0x4a, 0x39, 0x32, 0x13, 0xce, 0x43, 0x73,
- 0x1d, 0x62, 0xff, 0xfe, 0xc2, 0x29, 0x86, 0xa7, 0x85, 0x9d, 0x1f, 0xe2,
- 0x58, 0xbf, 0x99, 0xf9, 0xf9, 0x3a, 0xc5, 0xfe, 0xe7, 0xa6, 0x21, 0x77,
- 0xc5, 0x8a, 0xf9, 0xf2, 0x08, 0xb6, 0xf9, 0xf5, 0xa9, 0x58, 0xbf, 0xd9,
- 0xd3, 0x23, 0x03, 0x0c, 0x34, 0x8b, 0xc1, 0xe7, 0xd6, 0x2f, 0xd1, 0x4e,
- 0x7f, 0x8b, 0x15, 0xd5, 0x18, 0xff, 0x22, 0x22, 0x2f, 0x1e, 0x18, 0x3d,
- 0x7f, 0x82, 0xf2, 0x2d, 0xfe, 0xfa, 0x58, 0xbc, 0x76, 0xf2, 0xc5, 0xfc,
- 0x53, 0x10, 0x98, 0xc5, 0x8a, 0x89, 0x53, 0x69, 0xc5, 0xff, 0x1c, 0x28,
- 0x93, 0x3a, 0x1c, 0x98, 0x3b, 0x78, 0xef, 0xc5, 0x8b, 0xff, 0xec, 0x1b,
- 0x39, 0x37, 0x9c, 0xa1, 0xcc, 0x58, 0xbf, 0xbe, 0xda, 0x7c, 0xd2, 0xc5,
- 0x49, 0xfc, 0xb2, 0x65, 0x2c, 0x5f, 0x77, 0xbb, 0xe9, 0x62, 0xc0, 0x8d,
- 0xcd, 0x8f, 0x83, 0x2f, 0xf7, 0x4f, 0xbe, 0x41, 0xba, 0x2c, 0x5f, 0xba,
- 0x31, 0xdc, 0xeb, 0x15, 0x28, 0x8d, 0xc2, 0xc2, 0x37, 0xbd, 0xaf, 0xe2,
- 0xc5, 0xf4, 0x50, 0x98, 0x2c, 0x54, 0x9e, 0x0e, 0x0e, 0xdf, 0x49, 0x8e,
- 0x05, 0x8b, 0x85, 0xf5, 0x8b, 0xe7, 0x38, 0x50, 0xd5, 0x8b, 0xf1, 0x6b,
- 0x42, 0xfa, 0xc5, 0xfc, 0x7f, 0x14, 0xe7, 0x6b, 0x17, 0xff, 0xfb, 0xd8,
- 0xe5, 0xb3, 0x73, 0x3a, 0x3f, 0x9f, 0x8c, 0x05, 0x8b, 0xf3, 0xfb, 0x9f,
- 0x71, 0xa2, 0x3c, 0xc2, 0xea, 0xd9, 0x35, 0xb8, 0x88, 0xfe, 0x30, 0xc5,
- 0x1e, 0x85, 0xc5, 0xf4, 0xe1, 0x0d, 0x62, 0xde, 0x58, 0xb6, 0xc3, 0x36,
- 0x7b, 0x90, 0xd4, 0xb3, 0x25, 0x61, 0x0a, 0x9c, 0x84, 0xf3, 0xca, 0xd4,
- 0xfc, 0x6d, 0xcd, 0x2a, 0x7c, 0x0c, 0x65, 0x09, 0x6e, 0x43, 0x7b, 0xcd,
- 0xc2, 0x8d, 0xec, 0xc8, 0x42, 0x5f, 0xba, 0xcf, 0x26, 0x0b, 0x17, 0xfd,
- 0xf6, 0xf1, 0x83, 0x9c, 0x25, 0x8b, 0xf6, 0xf9, 0x07, 0x25, 0x8b, 0xcc,
- 0x07, 0x58, 0xbf, 0xf6, 0x74, 0x99, 0xfc, 0xed, 0x3d, 0xac, 0x5f, 0xf0,
- 0xc8, 0x5c, 0xcd, 0xb3, 0x65, 0x8b, 0xd3, 0xa2, 0x58, 0xbf, 0xfc, 0x09,
- 0x2c, 0xef, 0xcd, 0xce, 0x49, 0xd6, 0x2f, 0xff, 0x13, 0x0e, 0x47, 0xf9,
- 0xce, 0x8d, 0xa5, 0x8b, 0xfd, 0x83, 0x26, 0xe3, 0x8d, 0x62, 0xdf, 0x58,
- 0xb6, 0xd8, 0x88, 0xe2, 0x4a, 0xe1, 0x95, 0x85, 0x89, 0x86, 0xb4, 0x36,
- 0x2b, 0x49, 0xab, 0x7a, 0x32, 0x9b, 0xe3, 0xf3, 0x0e, 0xb1, 0x4e, 0x79,
- 0xac, 0x55, 0x7f, 0x4e, 0xbd, 0xec, 0x8f, 0x58, 0xbb, 0x5d, 0xac, 0x5d,
- 0x3d, 0x16, 0x28, 0x6a, 0xd2, 0x77, 0x2a, 0xd1, 0xc9, 0xca, 0x3e, 0x38,
- 0xc8, 0x21, 0x78, 0xf7, 0x88, 0x80, 0xc3, 0x10, 0x83, 0x37, 0xf1, 0x83,
- 0x29, 0xcd, 0x96, 0x2f, 0xf7, 0x0b, 0x00, 0xc4, 0x05, 0x8b, 0xff, 0x41,
- 0xbc, 0x29, 0xd4, 0x8a, 0x3d, 0x62, 0xc4, 0xb1, 0x7b, 0x69, 0x82, 0xc5,
- 0x2c, 0x54, 0x9a, 0xad, 0x87, 0xaf, 0xec, 0xf7, 0x1c, 0x3f, 0x2c, 0x5f,
- 0x40, 0x98, 0xd5, 0x8a, 0x19, 0xe9, 0x61, 0x7d, 0x0d, 0x37, 0x2e, 0xcb,
- 0xf4, 0x64, 0xc8, 0x44, 0x76, 0x1b, 0x9d, 0xfd, 0xf7, 0xf1, 0x49, 0xd6,
- 0x2f, 0xfe, 0x33, 0xd1, 0xcf, 0xcf, 0x7d, 0xd8, 0x0b, 0x17, 0xff, 0xf4,
- 0x0a, 0x5f, 0x58, 0x3d, 0x4f, 0x9f, 0x77, 0x1a, 0xc5, 0xff, 0xec, 0x1b,
- 0x1f, 0x3b, 0x86, 0x03, 0x06, 0xb1, 0x77, 0xd9, 0x62, 0xe8, 0xb8, 0xb1,
- 0x7e, 0xce, 0x8e, 0x43, 0xc3, 0x60, 0x60, 0xbd, 0xfd, 0xd7, 0xd9, 0xce,
- 0x4a, 0xc5, 0xf6, 0x77, 0xe9, 0x58, 0xbf, 0xf9, 0xb5, 0x86, 0xbe, 0xb3,
- 0xa3, 0x69, 0x62, 0xbe, 0x7d, 0x3d, 0x08, 0xef, 0xfc, 0x59, 0xad, 0x39,
- 0xf3, 0xbf, 0x2c, 0x5f, 0xfd, 0xcc, 0x10, 0x5f, 0x0e, 0xdf, 0xcd, 0xd6,
- 0x2f, 0xc1, 0x1b, 0x63, 0x20, 0xb1, 0x5d, 0x55, 0x15, 0x46, 0x3d, 0x49,
- 0xf6, 0x42, 0x67, 0x84, 0x9e, 0x3f, 0x12, 0x4d, 0xf6, 0x7f, 0x37, 0x58,
- 0xbb, 0xec, 0xb1, 0x7f, 0xef, 0xbb, 0x03, 0x0a, 0x7b, 0xe2, 0xc5, 0x87,
- 0xd4, 0xfe, 0x30, 0x8f, 0xc2, 0xf7, 0xfc, 0x50, 0xfe, 0x11, 0x48, 0x6b,
- 0x17, 0xff, 0x9b, 0x69, 0xd6, 0x9a, 0x1d, 0x40, 0x3c, 0x58, 0xac, 0x44,
- 0x29, 0x1c, 0x5e, 0xee, 0x18, 0xb1, 0x7a, 0x3c, 0xf8, 0xb1, 0x7f, 0xbc,
- 0xfa, 0x6f, 0xb1, 0xd6, 0x2f, 0xfa, 0x0f, 0x17, 0x70, 0xf8, 0x80, 0xb1,
- 0x7d, 0x9e, 0xfb, 0xca, 0x24, 0x3b, 0x20, 0x88, 0xce, 0x99, 0x1e, 0xa5,
- 0x0a, 0xeb, 0xfe, 0xd6, 0x9a, 0x1d, 0x7a, 0x4c, 0x7a, 0xc5, 0x49, 0xf3,
- 0xe1, 0x35, 0x4a, 0x73, 0xb0, 0x8d, 0xf6, 0x8d, 0x5e, 0x34, 0xed, 0x27,
- 0x52, 0xa1, 0x0a, 0x1c, 0xde, 0x94, 0xb1, 0x7e, 0xc2, 0x6f, 0x71, 0x62,
- 0xe8, 0x74, 0x58, 0xbf, 0xb9, 0xfc, 0x27, 0xe2, 0xc5, 0xfe, 0x2d, 0xcc,
- 0xf7, 0x04, 0x35, 0x8b, 0xfb, 0x70, 0xd8, 0x8a, 0x56, 0x2a, 0x08, 0xd3,
- 0x19, 0x3e, 0x86, 0x98, 0xb4, 0x8d, 0xee, 0x0b, 0xe2, 0xc5, 0xf4, 0x5f,
- 0x7d, 0x2c, 0x5f, 0x30, 0xcc, 0x3a, 0xc5, 0xd9, 0xce, 0xa7, 0xc6, 0x15,
- 0x1b, 0x81, 0x25, 0x4b, 0x23, 0x63, 0x16, 0x1e, 0x79, 0x85, 0xa3, 0x34,
- 0x28, 0x55, 0xdc, 0x13, 0xcb, 0x17, 0xff, 0xc2, 0xd6, 0x0f, 0xf2, 0xfe,
- 0xe3, 0x94, 0x16, 0x2f, 0xfb, 0x07, 0x85, 0x24, 0x29, 0x58, 0xbe, 0x0d,
- 0xbf, 0xc5, 0x8a, 0x58, 0xae, 0xcd, 0x80, 0x64, 0x97, 0xec, 0x19, 0x4f,
- 0x6b, 0x17, 0xff, 0x81, 0x9d, 0xfa, 0x7b, 0x87, 0x81, 0x30, 0x58, 0xbf,
- 0xde, 0x27, 0xef, 0x86, 0x1d, 0x62, 0xfd, 0x91, 0x41, 0xb8, 0xb1, 0x5f,
- 0x46, 0xa1, 0x14, 0x71, 0x37, 0xc6, 0xd7, 0xe6, 0x6e, 0xe1, 0xc5, 0x8b,
- 0xff, 0xce, 0x1e, 0x7b, 0xb8, 0x66, 0xbb, 0x87, 0x16, 0x2a, 0x53, 0xaa,
- 0x78, 0x7b, 0xe8, 0xf3, 0xc5, 0x35, 0xd6, 0x1a, 0x78, 0x92, 0xcf, 0xb4,
- 0xab, 0x08, 0x56, 0xa5, 0x83, 0xa6, 0x84, 0x64, 0xb0, 0x13, 0x67, 0x39,
- 0x37, 0xa6, 0x73, 0xf7, 0x28, 0x91, 0xe5, 0xe8, 0xc5, 0x2d, 0xab, 0x55,
- 0xfe, 0x71, 0xe9, 0x67, 0x3f, 0xac, 0xea, 0x1a, 0x35, 0x00, 0x4b, 0xdd,
- 0x2a, 0xed, 0x6f, 0x94, 0xc1, 0xbf, 0x56, 0x5c, 0x42, 0x9c, 0x21, 0xe9,
- 0x4a, 0xe3, 0x0d, 0x72, 0x38, 0x68, 0xc4, 0xf0, 0x92, 0x84, 0x2f, 0xa7,
- 0xcf, 0xe5, 0x8b, 0xf4, 0xfa, 0x19, 0xf5, 0x8b, 0x6b, 0xe7, 0x94, 0x44,
- 0x57, 0xb9, 0x20, 0x58, 0xac, 0x3c, 0x4f, 0x13, 0xdd, 0x1b, 0x05, 0xb5,
- 0x8b, 0xfa, 0x7a, 0x31, 0xbf, 0x75, 0x8b, 0xd8, 0x4c, 0xb1, 0x73, 0xf5,
- 0xc3, 0xcb, 0x34, 0xc2, 0xff, 0xdf, 0xc1, 0xff, 0x18, 0xb2, 0x3d, 0x62,
- 0xfe, 0x81, 0x66, 0xef, 0xe5, 0x8b, 0xff, 0x8b, 0x73, 0x5b, 0x99, 0x09,
- 0x2d, 0xd6, 0x2f, 0xb0, 0x6d, 0x05, 0x8b, 0x9f, 0x65, 0x8a, 0x01, 0xba,
- 0xf1, 0x15, 0x62, 0x61, 0xfd, 0xa0, 0x39, 0x71, 0x42, 0x02, 0xfc, 0xf2,
- 0x76, 0x1a, 0xc5, 0xfe, 0xcf, 0x96, 0x7b, 0xee, 0xb1, 0x77, 0xb9, 0xf3,
- 0xd9, 0xf1, 0x3d, 0xf0, 0xf4, 0xd0, 0x58, 0xb0, 0x45, 0x8b, 0xff, 0x3c,
- 0x9a, 0x59, 0xd1, 0xf4, 0xcb, 0x17, 0xfa, 0x4b, 0xef, 0xd3, 0x22, 0x58,
- 0xa2, 0x3f, 0x4f, 0x1f, 0xd4, 0x68, 0x8a, 0x98, 0x42, 0x22, 0xf6, 0xd9,
- 0xda, 0xc5, 0x68, 0xf3, 0x08, 0xb6, 0xff, 0x30, 0x7f, 0x7d, 0x34, 0x16,
- 0x2e, 0x9e, 0xd6, 0x2f, 0xdf, 0x98, 0xfc, 0x1a, 0xc5, 0x2c, 0x5a, 0x46,
- 0x6d, 0xc0, 0x57, 0x51, 0xc7, 0xea, 0x62, 0x7d, 0xfd, 0x24, 0x28, 0xa7,
- 0x8b, 0x17, 0xdf, 0x14, 0xf1, 0x62, 0xf3, 0x30, 0x16, 0x2e, 0x9e, 0x49,
- 0xbf, 0xd1, 0x1d, 0xfb, 0x7f, 0x4f, 0x7e, 0x58, 0xaf, 0x9e, 0xb0, 0x8a,
- 0xef, 0xfd, 0xf7, 0x29, 0xef, 0x8e, 0x79, 0x58, 0xbd, 0xc9, 0xd2, 0xc5,
- 0xff, 0xfd, 0x9d, 0xf9, 0x87, 0xf9, 0xe6, 0x3e, 0xdb, 0x37, 0x6b, 0x16,
- 0xe0, 0xd1, 0xb7, 0xb9, 0x17, 0x67, 0xc4, 0x3b, 0x5b, 0x27, 0xc5, 0xe8,
- 0xe7, 0xaa, 0x57, 0x10, 0xcd, 0x2e, 0x78, 0xc6, 0x34, 0x42, 0xd0, 0xa9,
- 0x14, 0xa0, 0x8b, 0xd0, 0xf1, 0xd6, 0x2f, 0xe2, 0xc8, 0x41, 0xb8, 0xb1,
- 0x7f, 0x49, 0x9c, 0x1f, 0x67, 0x58, 0xad, 0xcf, 0x78, 0x8b, 0x6f, 0xdc,
- 0x1c, 0x98, 0x75, 0x8b, 0xc0, 0x33, 0xcb, 0x17, 0xd9, 0xf6, 0xd2, 0xc5,
- 0x83, 0xc3, 0xc1, 0x21, 0xfa, 0xc4, 0x49, 0x33, 0x5d, 0xc3, 0x75, 0x8b,
- 0xee, 0xf9, 0x3d, 0xac, 0x5c, 0xd0, 0xea, 0x6f, 0x1c, 0x5e, 0xf1, 0xbf,
- 0x75, 0x8b, 0xff, 0xa2, 0xd4, 0xf4, 0xfc, 0xbe, 0x9e, 0x25, 0x8b, 0x6c,
- 0xb1, 0x78, 0x1a, 0x75, 0x8a, 0x82, 0x25, 0xbb, 0x1e, 0x64, 0x82, 0x13,
- 0xbe, 0x8e, 0x6c, 0xfa, 0xc5, 0xff, 0xfe, 0x90, 0xfe, 0xde, 0xe6, 0x68,
- 0xa7, 0xb8, 0x67, 0x7e, 0x58, 0xbe, 0xcf, 0x71, 0x96, 0x2c, 0x3d, 0x22,
- 0x17, 0xec, 0x77, 0xfb, 0x85, 0x87, 0x66, 0xd9, 0x62, 0xa0, 0x98, 0x33,
- 0x42, 0xa8, 0x45, 0x37, 0xf7, 0x30, 0x6f, 0xcd, 0x96, 0x2f, 0x42, 0x40,
- 0xb1, 0x7e, 0x32, 0x28, 0x4c, 0x7a, 0x45, 0x4b, 0x2d, 0x57, 0x62, 0x11,
- 0xb7, 0x64, 0x67, 0xc6, 0xce, 0x6e, 0xee, 0xd4, 0xef, 0x9a, 0x85, 0xa7,
- 0xd7, 0x5a, 0x18, 0x65, 0x1a, 0x17, 0x0d, 0x7c, 0x5e, 0x60, 0xed, 0xfc,
- 0x3d, 0x36, 0xed, 0xba, 0xc5, 0xff, 0xff, 0x05, 0xae, 0xd3, 0x1a, 0x1e,
- 0x42, 0xd6, 0x36, 0x8d, 0x7e, 0xd8, 0x1d, 0x7a, 0xfe, 0x39, 0x62, 0xdb,
- 0xac, 0x5f, 0xf8, 0x84, 0xc6, 0x67, 0x1e, 0x49, 0x62, 0xfd, 0x0e, 0x7b,
- 0xa0, 0x16, 0x28, 0xd3, 0xe9, 0xec, 0xf6, 0xf4, 0x73, 0x8d, 0x62, 0xff,
- 0x1b, 0xf6, 0x86, 0xa4, 0xd5, 0x8a, 0xd1, 0xfd, 0x1c, 0x90, 0x88, 0x2f,
- 0xc5, 0x9d, 0x1b, 0x4b, 0x17, 0xfd, 0x07, 0xfb, 0x38, 0xe4, 0x96, 0x2b,
- 0xa9, 0xf0, 0x49, 0x4d, 0xe9, 0x6d, 0x2c, 0x5f, 0x1b, 0x9c, 0x75, 0x8b,
- 0x8b, 0x75, 0x8b, 0xff, 0x04, 0x7d, 0xb5, 0x92, 0x5c, 0x75, 0x8b, 0xf1,
- 0x9e, 0xf0, 0xbe, 0xb1, 0x5d, 0x51, 0x4c, 0xe4, 0x64, 0x31, 0xd1, 0x02,
- 0xfe, 0x3f, 0xbf, 0x3d, 0x25, 0x62, 0xff, 0xd1, 0xfd, 0x77, 0xfb, 0xe9,
- 0xe4, 0xeb, 0x17, 0x8b, 0x70, 0x2c, 0x56, 0xc7, 0xc7, 0x88, 0xb7, 0xd9,
- 0xd8, 0x09, 0x62, 0xfe, 0x84, 0xfb, 0xed, 0x05, 0x8a, 0x23, 0xd1, 0xf1,
- 0x1d, 0xff, 0xbc, 0x23, 0xfe, 0x5c, 0x98, 0x6b, 0x17, 0xff, 0xd8, 0x1f,
- 0x51, 0xbe, 0x77, 0x0e, 0x13, 0x6c, 0xb1, 0x7d, 0x08, 0x37, 0x96, 0x2b,
- 0x64, 0x6b, 0x76, 0x43, 0xf3, 0xe6, 0x54, 0xbc, 0x0f, 0x89, 0x62, 0xf8,
- 0xdd, 0x30, 0x6b, 0x17, 0x6f, 0xd1, 0x62, 0xc6, 0x2a, 0x20, 0x52, 0xde,
- 0x55, 0x02, 0x85, 0x68, 0xf6, 0xbc, 0x36, 0x19, 0x05, 0x62, 0x2b, 0xdd,
- 0xfe, 0xfe, 0xdd, 0xf6, 0xf3, 0x0d, 0x62, 0xfe, 0xfc, 0xff, 0x3b, 0xf2,
- 0xc5, 0xe6, 0x9e, 0xd6, 0x2f, 0xf0, 0xb8, 0x61, 0x67, 0x70, 0x58, 0xb0,
- 0x4e, 0xa7, 0xa7, 0xf1, 0xdb, 0xf9, 0xc2, 0xfb, 0xfe, 0x43, 0x58, 0xbf,
- 0xdf, 0x73, 0x23, 0x00, 0x09, 0x48, 0xad, 0x1f, 0x64, 0x71, 0xa5, 0xff,
- 0xfb, 0x86, 0xb7, 0xa0, 0xe3, 0xe7, 0xf3, 0x0b, 0x75, 0x8b, 0xfb, 0x38,
- 0xfe, 0x9e, 0xd6, 0x2f, 0xd8, 0x76, 0x6d, 0x96, 0x2f, 0xd3, 0xbf, 0xe7,
- 0x4b, 0x17, 0xef, 0xb7, 0x27, 0x16, 0x2f, 0x7c, 0x46, 0xac, 0x5e, 0x08,
- 0x17, 0xe2, 0xc5, 0xe6, 0x3b, 0xac, 0x57, 0x54, 0x43, 0x7c, 0x9c, 0x87,
- 0xc4, 0x49, 0x78, 0xc9, 0x02, 0xc5, 0x6c, 0xac, 0x9c, 0xd3, 0x0e, 0xe1,
- 0x04, 0xf0, 0x98, 0xd1, 0x2f, 0xd5, 0xc8, 0xbb, 0xc5, 0x06, 0x42, 0xbc,
- 0x21, 0xf5, 0xff, 0xa1, 0xf3, 0x35, 0x23, 0xfe, 0x06, 0xb1, 0x7e, 0xfc,
- 0x8b, 0xb7, 0x58, 0xae, 0xcf, 0xac, 0xe8, 0x57, 0xef, 0x1f, 0x91, 0xbc,
- 0x6b, 0x58, 0xbf, 0xe2, 0x00, 0xfe, 0xc6, 0x66, 0xcb, 0x17, 0xec, 0x10,
- 0x5f, 0x38, 0xb1, 0x4e, 0x7c, 0xff, 0x3b, 0xbf, 0xfc, 0x46, 0xb3, 0x10,
- 0x08, 0x4d, 0xd8, 0x51, 0x62, 0xff, 0xbd, 0xcc, 0xf1, 0x49, 0xf8, 0xb1,
- 0x7e, 0x90, 0x31, 0x01, 0x62, 0xfc, 0x2e, 0xfc, 0xe1, 0xac, 0x5b, 0xdd,
- 0x51, 0x17, 0x03, 0x9e, 0x13, 0xd6, 0x26, 0x22, 0x50, 0xd9, 0xbf, 0xe2,
- 0xcd, 0x0f, 0xf3, 0xdc, 0x16, 0x2f, 0xff, 0x49, 0xc4, 0xc3, 0xf7, 0x7b,
- 0xb9, 0x06, 0xb1, 0x6c, 0x24, 0x43, 0x86, 0x75, 0x7f, 0xfc, 0x2d, 0x8c,
- 0x3f, 0x1f, 0x77, 0xd8, 0x36, 0xed, 0x62, 0xfe, 0xef, 0xef, 0x9a, 0x89,
- 0x62, 0x9d, 0x10, 0xec, 0xaf, 0x7f, 0xee, 0xfd, 0xbf, 0xdc, 0x7f, 0xcd,
- 0x96, 0x2f, 0xe7, 0xef, 0x9f, 0x70, 0xd6, 0x2c, 0x17, 0x58, 0xa0, 0x1e,
- 0x31, 0x18, 0x56, 0x22, 0xab, 0x50, 0x89, 0xbf, 0x9b, 0x99, 0x84, 0x6a,
- 0xc5, 0x61, 0xea, 0x08, 0x9e, 0xf3, 0x30, 0x6b, 0x15, 0x2a, 0xae, 0x87,
- 0x0a, 0xed, 0x42, 0xbf, 0xf1, 0x8f, 0x91, 0x0d, 0xf6, 0x1d, 0xc6, 0xb1,
- 0x7f, 0x9a, 0x3c, 0xd3, 0x67, 0xdc, 0x58, 0xbb, 0xdc, 0xea, 0x7b, 0x66,
- 0x11, 0x5f, 0xf3, 0x6a, 0x22, 0x90, 0x70, 0x4b, 0x15, 0x27, 0xd6, 0x33,
- 0x1b, 0xf7, 0xb0, 0x45, 0xe5, 0x8b, 0xf4, 0x38, 0x64, 0xc7, 0xac, 0x5a,
- 0x70, 0xf5, 0x58, 0xa2, 0xff, 0xdd, 0x49, 0x8d, 0xeb, 0xc0, 0x02, 0x56,
- 0x2f, 0xff, 0x6c, 0x20, 0x72, 0x0f, 0xce, 0x4e, 0xa0, 0xb1, 0x67, 0x35,
- 0x12, 0x3a, 0x44, 0xbd, 0x08, 0x46, 0xcb, 0x17, 0xee, 0xf9, 0x25, 0xe5,
- 0x8b, 0x36, 0x8f, 0x33, 0xe4, 0x75, 0x04, 0xd4, 0xb9, 0x0b, 0x6f, 0x3a,
- 0xdf, 0xff, 0xe1, 0xfe, 0x77, 0xfb, 0xc4, 0xcd, 0x03, 0x58, 0xc6, 0x8f,
- 0x58, 0xbf, 0xff, 0xf7, 0xd9, 0xf8, 0xf0, 0xc1, 0xfb, 0xf2, 0xfa, 0xd3,
- 0x96, 0xcb, 0x17, 0xc5, 0x9d, 0x31, 0x62, 0xb6, 0x47, 0xa9, 0xd9, 0xc3,
- 0x6b, 0xbb, 0x68, 0xd1, 0x62, 0xfe, 0x78, 0xa1, 0x25, 0x05, 0x8a, 0x73,
- 0xcc, 0xf8, 0xf5, 0xff, 0xfd, 0x3e, 0xe1, 0x85, 0xef, 0x89, 0xa1, 0xee,
- 0x60, 0x6b, 0x17, 0xfe, 0x9d, 0xb3, 0xd0, 0xc2, 0x71, 0xac, 0x5f, 0xff,
- 0x69, 0x9b, 0xb8, 0x73, 0xdd, 0xee, 0xfa, 0x35, 0x62, 0xfe, 0x83, 0x39,
- 0x4c, 0x16, 0x2f, 0xf1, 0xdb, 0xb7, 0x9e, 0xfc, 0xb1, 0x52, 0x7c, 0x38,
- 0x59, 0x66, 0xd9, 0x1a, 0xd0, 0x85, 0xb5, 0xff, 0x98, 0x3f, 0x67, 0xfc,
- 0xf3, 0x1e, 0xb1, 0x7f, 0xe9, 0x0f, 0x81, 0x56, 0xdf, 0x3b, 0xf2, 0xc5,
- 0x4a, 0xac, 0x7d, 0xdf, 0xb4, 0x43, 0xf5, 0xe6, 0x8c, 0x50, 0x8b, 0xbc,
- 0x85, 0x7d, 0x0f, 0xe6, 0xcb, 0x17, 0xfc, 0xe5, 0x87, 0x8e, 0xc7, 0xed,
- 0x62, 0xff, 0xff, 0x31, 0xcb, 0x3b, 0x9d, 0x69, 0xfa, 0x6b, 0x3c, 0xdd,
- 0xac, 0x50, 0xd1, 0x3d, 0xc3, 0xbb, 0xff, 0xf8, 0x70, 0xe6, 0xb3, 0xcd,
- 0xdc, 0x4c, 0x64, 0xfb, 0x8b, 0x17, 0xff, 0xf6, 0x79, 0xbb, 0xff, 0xde,
- 0x7d, 0xfc, 0xe9, 0x3a, 0x58, 0xbf, 0xff, 0xf6, 0x6b, 0x37, 0xfc, 0xf1,
- 0xb5, 0x83, 0xfb, 0x3f, 0x1c, 0xeb, 0x17, 0xff, 0xfa, 0x5a, 0x5c, 0x9b,
- 0xd0, 0x7e, 0x9a, 0xcf, 0x37, 0x6b, 0x15, 0x29, 0xd5, 0x40, 0x8f, 0x4b,
- 0xfc, 0x5d, 0x8e, 0x6b, 0xbc, 0xcc, 0x11, 0x62, 0xe9, 0x3f, 0x53, 0xeb,
- 0x3a, 0x6d, 0xf3, 0xed, 0xbc, 0x16, 0x2f, 0x16, 0x04, 0x58, 0xbf, 0xe9,
- 0xec, 0xed, 0xec, 0xef, 0xcb, 0x17, 0x36, 0xcb, 0x15, 0xda, 0xb9, 0xc7,
- 0x95, 0xaf, 0xa2, 0xf6, 0x25, 0x21, 0xe0, 0xce, 0xef, 0x7d, 0xb8, 0xb1,
- 0x6e, 0xd6, 0x2a, 0x4d, 0x80, 0xc7, 0x6f, 0xf1, 0xdb, 0x85, 0x38, 0x6a,
- 0xc5, 0x84, 0xb1, 0x7f, 0xc2, 0x17, 0xdf, 0xdf, 0x68, 0x2c, 0x5e, 0x86,
- 0x79, 0x62, 0xf9, 0xbf, 0x9a, 0x58, 0xaf, 0x9b, 0xfe, 0x83, 0xb7, 0xe1,
- 0x7f, 0x52, 0x1a, 0xc5, 0xd1, 0xcc, 0xb1, 0x74, 0xef, 0xd5, 0x34, 0x5c,
- 0x20, 0x34, 0xcc, 0xe2, 0x4c, 0xf3, 0xe2, 0x33, 0x0a, 0xaf, 0x10, 0x5f,
- 0x8b, 0x17, 0xd0, 0xfb, 0xf4, 0x58, 0xbf, 0xfd, 0x9c, 0x16, 0xff, 0x7e,
- 0xf8, 0xfd, 0x81, 0x62, 0xff, 0xf0, 0xf5, 0x8e, 0x69, 0x67, 0xbc, 0x2d,
- 0x96, 0x2f, 0x49, 0x7b, 0xaa, 0x38, 0x1c, 0x84, 0x89, 0x78, 0x9d, 0x76,
- 0x99, 0x62, 0xff, 0xee, 0x8f, 0xce, 0x61, 0x6e, 0xc4, 0x05, 0x8b, 0xfd,
- 0xf7, 0x18, 0xf0, 0x38, 0x96, 0x2f, 0x3f, 0x7c, 0x58, 0xbf, 0x67, 0x4c,
- 0x80, 0x5d, 0x62, 0x8d, 0x3c, 0xcf, 0x8f, 0x58, 0x18, 0x8e, 0xbd, 0xd1,
- 0xbd, 0x08, 0x2b, 0xe3, 0x3e, 0xde, 0x58, 0xb4, 0xe8, 0xf7, 0xce, 0x77,
- 0x4e, 0x9e, 0xae, 0x93, 0x7f, 0x1b, 0x0d, 0xff, 0xf1, 0x9a, 0xfb, 0x75,
- 0xe1, 0x66, 0xc7, 0xc3, 0xac, 0x5f, 0xbc, 0xe7, 0x68, 0x2c, 0x5e, 0x6e,
- 0xf9, 0xd4, 0xff, 0x31, 0x52, 0xde, 0x58, 0xa0, 0x1e, 0x39, 0x86, 0xb7,
- 0xff, 0xc4, 0xd9, 0xf7, 0xd7, 0xd8, 0x5f, 0xc3, 0xac, 0x5f, 0xfb, 0x7f,
- 0xb1, 0x7b, 0x87, 0x29, 0x58, 0xb8, 0xd8, 0x2c, 0x5f, 0xe9, 0xd0, 0x06,
- 0xcc, 0x6a, 0xc5, 0x61, 0xe6, 0xfc, 0x66, 0xfd, 0xf7, 0xdf, 0xf9, 0xc4,
- 0x56, 0xfa, 0x11, 0x94, 0x34, 0xd0, 0x32, 0x1f, 0x77, 0xf9, 0x8b, 0xd1,
- 0x66, 0xb1, 0x62, 0xff, 0xff, 0xb4, 0x68, 0xff, 0x3c, 0xfe, 0x77, 0x0f,
- 0x3c, 0x53, 0xc1, 0x2c, 0x5f, 0xfc, 0xff, 0x63, 0x99, 0x23, 0xd6, 0xa5,
- 0x62, 0x99, 0x16, 0x1e, 0x6b, 0xac, 0x4c, 0xb7, 0xe5, 0x0d, 0x0e, 0x3b,
- 0xe2, 0xf6, 0x7d, 0x62, 0xff, 0xf8, 0xb3, 0xa0, 0xe7, 0x53, 0x07, 0xdd,
- 0xb4, 0xb1, 0x52, 0x7e, 0x7e, 0x22, 0xbd, 0x3d, 0xf1, 0x62, 0x9c, 0xdf,
- 0xfc, 0x86, 0xff, 0x1a, 0xc3, 0xc2, 0x7f, 0x2c, 0x5e, 0xeb, 0xbc, 0x4b,
- 0x15, 0x87, 0xaa, 0x46, 0x77, 0xff, 0x4e, 0xf9, 0xac, 0xfb, 0xeb, 0xec,
- 0xb1, 0x7d, 0xe7, 0x16, 0xeb, 0x17, 0xff, 0x31, 0x85, 0x99, 0xf7, 0xdf,
- 0xf8, 0xb1, 0x52, 0x7d, 0x02, 0x24, 0xbe, 0x88, 0xa4, 0xfa, 0x46, 0x69,
- 0x42, 0xb2, 0xff, 0xf6, 0x81, 0x1d, 0x9a, 0x98, 0x3f, 0x7e, 0xc5, 0x8b,
- 0xff, 0x06, 0x58, 0x3f, 0x8b, 0x62, 0x0d, 0x62, 0x99, 0x12, 0x04, 0x9d,
- 0x7f, 0xbf, 0xf6, 0xdb, 0x53, 0xd1, 0x62, 0xf0, 0xfc, 0xeb, 0x15, 0x87,
- 0xa9, 0xc3, 0x7b, 0xfc, 0x5e, 0xfb, 0x42, 0x76, 0x58, 0xbf, 0xf7, 0x8c,
- 0x87, 0x22, 0x84, 0xeb, 0x65, 0x8a, 0xc3, 0xf8, 0xec, 0xd2, 0xff, 0xb5,
- 0x3e, 0xd6, 0xa4, 0xfc, 0x58, 0xbf, 0xfe, 0x83, 0xf8, 0xcd, 0x4f, 0xe7,
- 0xdc, 0x6e, 0xd6, 0x2f, 0xc2, 0xe7, 0xda, 0x1d, 0x53, 0x47, 0xc8, 0x4c,
- 0xc4, 0x45, 0xc3, 0xab, 0xfa, 0x13, 0xd6, 0x4e, 0x75, 0x8b, 0xf6, 0x04,
- 0x79, 0x89, 0x62, 0xd1, 0xa2, 0xc5, 0xf3, 0x03, 0x0a, 0x4f, 0xc7, 0xe6,
- 0x1c, 0x2a, 0xbf, 0xfd, 0xd3, 0xee, 0x3c, 0x73, 0x5c, 0xb3, 0xa2, 0xc5,
- 0xfa, 0x70, 0xbd, 0x1c, 0xb1, 0x7f, 0x3f, 0x60, 0xd3, 0x0d, 0x62, 0xff,
- 0xf7, 0x42, 0xce, 0x75, 0xc2, 0x14, 0x33, 0x8b, 0x14, 0xb1, 0x58, 0x7b,
- 0x27, 0x4d, 0xa3, 0xa3, 0x4f, 0xe5, 0x45, 0x08, 0x8b, 0xf7, 0xe7, 0x5c,
- 0x75, 0x8b, 0x47, 0xac, 0x5d, 0x84, 0xb1, 0x5a, 0x35, 0x7f, 0x15, 0xbc,
- 0xf3, 0x05, 0x8b, 0xd0, 0x10, 0xd6, 0x2d, 0xdf, 0x54, 0x71, 0x0c, 0xd2,
- 0x25, 0x3f, 0x90, 0xb0, 0xe5, 0x62, 0xa5, 0x56, 0x94, 0x05, 0x7f, 0x98,
- 0x8c, 0x68, 0x60, 0xd6, 0x2a, 0x57, 0xcf, 0xf2, 0x1d, 0xaf, 0x0c, 0xed,
- 0x47, 0x78, 0x50, 0xd3, 0xe4, 0xa9, 0x81, 0x15, 0x5f, 0xcf, 0xa8, 0xdb,
- 0x9e, 0x75, 0x8b, 0xa1, 0x2b, 0x17, 0xe2, 0x9f, 0xe0, 0xd6, 0x2f, 0xfe,
- 0xe4, 0x83, 0x3e, 0xfa, 0x60, 0xfc, 0xb1, 0x71, 0x6c, 0x33, 0xec, 0xe1,
- 0x3d, 0x41, 0x16, 0x39, 0x08, 0x3b, 0xf8, 0x78, 0x46, 0xea, 0x56, 0x2e,
- 0x8e, 0xed, 0x62, 0xff, 0xcf, 0xa7, 0xd9, 0xf7, 0xfc, 0xf9, 0x62, 0xa0,
- 0xe8, 0x7f, 0xc7, 0x2f, 0xb3, 0x78, 0xc8, 0x3b, 0x8f, 0x22, 0x29, 0x7e,
- 0x5a, 0x9c, 0x06, 0x3c, 0x7a, 0x9f, 0x96, 0x50, 0x08, 0x7c, 0x94, 0xa9,
- 0x0e, 0x43, 0x9b, 0xd3, 0xf6, 0x9d, 0x1f, 0xc3, 0x87, 0x24, 0x71, 0x39,
- 0x85, 0xc1, 0x07, 0x2f, 0x6f, 0xf8, 0x96, 0x2f, 0xdf, 0x78, 0xe7, 0xd2,
- 0xc5, 0xed, 0x84, 0x1a, 0xc5, 0x6e, 0x79, 0x6c, 0x57, 0x7f, 0xed, 0xff,
- 0x3d, 0xc3, 0x7f, 0xe0, 0xd6, 0x2f, 0xed, 0xff, 0x3d, 0xc3, 0xeb, 0x17,
- 0x05, 0xc2, 0x2c, 0x5e, 0x73, 0xe2, 0xc5, 0xd2, 0x6a, 0xc5, 0x41, 0x1d,
- 0x03, 0x22, 0x35, 0x0f, 0xb3, 0x1d, 0x0f, 0x06, 0x39, 0x7f, 0xc5, 0x81,
- 0xeb, 0x37, 0xfe, 0x2c, 0x5f, 0xff, 0xf9, 0xf6, 0xe0, 0xa7, 0xa9, 0x67,
- 0xde, 0x4b, 0xc6, 0x8a, 0x74, 0xb1, 0x7f, 0xfe, 0x9d, 0xbc, 0x23, 0xe7,
- 0x37, 0xfc, 0x94, 0xf1, 0x62, 0xb4, 0x8c, 0x5f, 0xb7, 0x5b, 0x75, 0x8b,
- 0xff, 0xe8, 0x38, 0x7e, 0xfe, 0x7f, 0x3b, 0x83, 0x06, 0xb1, 0x7f, 0x67,
- 0xb9, 0xb6, 0x06, 0xb1, 0x51, 0x22, 0x0f, 0x4a, 0x77, 0x8c, 0xd4, 0xac,
- 0x5f, 0xff, 0xd8, 0x3f, 0xc8, 0x65, 0x8f, 0xb4, 0x70, 0xbe, 0xfa, 0x58,
- 0xad, 0x95, 0x2c, 0x8e, 0x1f, 0xf1, 0xe4, 0x7a, 0x84, 0xb3, 0x12, 0x10,
- 0xf5, 0x4b, 0xa9, 0x78, 0xc8, 0xc2, 0xfb, 0x23, 0x7b, 0x45, 0x37, 0x14,
- 0x68, 0x8d, 0x1a, 0x98, 0xa5, 0x59, 0xdb, 0xb5, 0x8b, 0xe9, 0xdd, 0xf7,
- 0x58, 0xbd, 0xa7, 0x0d, 0x62, 0xff, 0x68, 0x5b, 0x3c, 0x0e, 0x35, 0x8b,
- 0xfd, 0xcc, 0xd0, 0xc9, 0xa0, 0xb1, 0x43, 0x44, 0x3e, 0x87, 0xb8, 0x6d,
- 0x70, 0xa2, 0x58, 0xbf, 0x4c, 0x23, 0xb6, 0x25, 0x8a, 0x39, 0xe2, 0xf8,
- 0x66, 0xfe, 0x21, 0x71, 0xf3, 0x4b, 0x17, 0xf7, 0x52, 0xc0, 0x0b, 0x8b,
- 0x15, 0x87, 0xba, 0xc5, 0xb7, 0xbf, 0x80, 0x58, 0xb4, 0xac, 0x5f, 0xff,
- 0x44, 0xcd, 0x0e, 0x49, 0xc7, 0xf9, 0x2d, 0xd6, 0x2a, 0x4f, 0x89, 0xc4,
- 0x6f, 0xf8, 0x5b, 0xe6, 0xb6, 0xd8, 0x5b, 0x2c, 0x5f, 0xf6, 0x45, 0x09,
- 0xef, 0x3b, 0xf2, 0xc5, 0xbe, 0xb1, 0x7b, 0xe6, 0x1d, 0x62, 0x86, 0x6c,
- 0x70, 0x4a, 0xba, 0xa7, 0x17, 0x24, 0x18, 0xfe, 0x72, 0x02, 0x3f, 0xf3,
- 0x6d, 0xed, 0x9f, 0xb5, 0x8b, 0xe9, 0xf8, 0xb4, 0xb1, 0x77, 0xc6, 0xb1,
- 0x73, 0x12, 0xc5, 0x4a, 0xad, 0x1d, 0xa5, 0x05, 0x3a, 0xb9, 0x0f, 0xf0,
- 0x8c, 0x31, 0x8a, 0xea, 0xb8, 0xc7, 0x01, 0x31, 0xc2, 0xaf, 0x52, 0xd1,
- 0xaf, 0x87, 0xf1, 0x6c, 0xb1, 0x7f, 0x34, 0x33, 0x61, 0x12, 0xc5, 0xd8,
- 0x35, 0x8a, 0x19, 0xe2, 0xee, 0x5d, 0x7f, 0xed, 0x64, 0x7c, 0x5f, 0x63,
- 0xbf, 0x16, 0x2f, 0xef, 0x38, 0x67, 0x7f, 0x2c, 0x5f, 0xf3, 0x16, 0xb1,
- 0xff, 0x23, 0x58, 0xb6, 0x78, 0xf9, 0x82, 0x17, 0xdb, 0x69, 0x4d, 0x7f,
- 0x1a, 0xb4, 0x47, 0xf8, 0x54, 0xd9, 0xd6, 0x2e, 0x0b, 0xe2, 0xc5, 0x61,
- 0xfa, 0x69, 0x21, 0x84, 0x6f, 0xfd, 0xd1, 0xfd, 0x09, 0xeb, 0xe9, 0x12,
- 0xc5, 0xa2, 0x58, 0xbd, 0xd3, 0x06, 0xb1, 0x7f, 0xf8, 0x4c, 0x5b, 0xf7,
- 0xc7, 0xf3, 0x96, 0xcb, 0x17, 0xe8, 0xe1, 0x7f, 0x37, 0x58, 0xb8, 0xfc,
- 0x58, 0xac, 0x4c, 0x1a, 0x24, 0x33, 0x89, 0x80, 0x7f, 0xc9, 0x82, 0x2d,
- 0xbf, 0xa7, 0xce, 0x09, 0x82, 0xc5, 0xd0, 0x65, 0x8b, 0x9b, 0x4b, 0x15,
- 0xa3, 0xdb, 0x62, 0xde, 0x0b, 0xdf, 0xdd, 0xec, 0xd0, 0x98, 0xf5, 0x8b,
- 0x8a, 0x0b, 0x15, 0x27, 0x95, 0xb1, 0x9d, 0xc1, 0xca, 0xc5, 0x75, 0x77,
- 0x97, 0x01, 0x43, 0x00, 0xac, 0x24, 0x66, 0x1e, 0xdb, 0x42, 0x3a, 0x04,
- 0x79, 0x0c, 0x23, 0x4f, 0xf7, 0x84, 0x9b, 0xc6, 0x93, 0x11, 0xf1, 0xe1,
- 0x9b, 0xfb, 0x59, 0x80, 0xd3, 0x9d, 0xe5, 0x28, 0x87, 0x91, 0x99, 0xfa,
- 0x16, 0x62, 0x78, 0x8e, 0x22, 0xbf, 0xdf, 0x70, 0x01, 0xfb, 0xe2, 0xc5,
- 0xfe, 0x93, 0xef, 0xf6, 0xec, 0x0b, 0x16, 0x0a, 0xee, 0x7d, 0x66, 0x1a,
- 0xdf, 0xd1, 0x61, 0x37, 0xf1, 0x62, 0xf6, 0x60, 0x16, 0x2a, 0x07, 0x93,
- 0xe2, 0xdb, 0xc7, 0x9c, 0x58, 0xb4, 0x4b, 0x17, 0x1f, 0x7e, 0xa6, 0xbd,
- 0xc7, 0x2f, 0xf3, 0x16, 0x3c, 0x7b, 0xfd, 0x62, 0xe3, 0xf6, 0xb1, 0x7a,
- 0x12, 0x75, 0x8b, 0xfb, 0x33, 0x9c, 0xc8, 0xf5, 0x8a, 0xec, 0xf3, 0x48,
- 0x76, 0xff, 0xa4, 0xb6, 0xe6, 0x1e, 0x63, 0xd6, 0x2f, 0xff, 0xb6, 0xf6,
- 0x73, 0xe2, 0xe4, 0xec, 0x22, 0x95, 0x8b, 0xff, 0xfe, 0x86, 0xb4, 0xfe,
- 0xe7, 0xf1, 0xc8, 0xb3, 0xbf, 0x71, 0xd6, 0x2e, 0x9f, 0xac, 0x5f, 0xc1,
- 0x7d, 0xfe, 0xc2, 0x82, 0xc5, 0xfc, 0xd1, 0x0e, 0x4b, 0x65, 0x8a, 0xd9,
- 0x39, 0x01, 0x91, 0x61, 0xe3, 0x29, 0x13, 0x30, 0x85, 0xfa, 0x1a, 0x5f,
- 0xcd, 0xe0, 0x18, 0x51, 0x2c, 0x5f, 0xef, 0xb7, 0xb8, 0x1e, 0x7d, 0x62,
- 0xf4, 0x4f, 0xf5, 0x8b, 0x9a, 0x0b, 0x15, 0x26, 0xd7, 0x43, 0xd7, 0xf7,
- 0x8b, 0x36, 0x7d, 0x2c, 0x5f, 0xb3, 0xcc, 0x40, 0x58, 0xa9, 0x3d, 0x51,
- 0x17, 0x5e, 0x09, 0x27, 0x58, 0xac, 0x4c, 0x7d, 0x9a, 0xb8, 0xea, 0x10,
- 0x86, 0xfc, 0x43, 0xfc, 0xc1, 0x62, 0xf1, 0x4e, 0xeb, 0x17, 0xec, 0x73,
- 0x5c, 0xd5, 0x8b, 0xe9, 0x86, 0x71, 0x62, 0xff, 0x98, 0x33, 0x08, 0xb3,
- 0xb8, 0x2c, 0x56, 0x22, 0x8f, 0x43, 0xbf, 0x29, 0x62, 0x2b, 0xf3, 0x78,
- 0xcf, 0xca, 0xc5, 0xe9, 0x2d, 0xd6, 0x2b, 0xe7, 0x8c, 0x10, 0xa6, 0xfc,
- 0xd9, 0xe7, 0xd9, 0x62, 0xfd, 0x86, 0xb4, 0xec, 0xb1, 0x7b, 0xde, 0x95,
- 0x8a, 0xf9, 0xe3, 0x31, 0x4d, 0xf4, 0xc5, 0xa9, 0x58, 0xb4, 0xac, 0x5b,
- 0x16, 0x2b, 0x46, 0x88, 0xe2, 0x36, 0xdd, 0x62, 0x8e, 0x7f, 0x3f, 0x45,
- 0x08, 0x43, 0x7d, 0x22, 0x0b, 0xba, 0xc5, 0xf7, 0x0a, 0x43, 0x58, 0xbf,
- 0x0f, 0xf8, 0x50, 0x58, 0xac, 0x3c, 0xb6, 0x23, 0xb9, 0xc0, 0xb1, 0x7c,
- 0xd1, 0x37, 0x96, 0x2a, 0x06, 0xeb, 0xc2, 0xf7, 0xdb, 0x1c, 0x43, 0x58,
- 0xbc, 0x11, 0xf6, 0x58, 0xb4, 0xe1, 0xe2, 0x84, 0x25, 0xbf, 0xff, 0xb3,
- 0xdc, 0x33, 0x9e, 0xfb, 0x11, 0xb9, 0xd2, 0x43, 0x58, 0xbe, 0xe7, 0x9e,
- 0x25, 0x8a, 0x3a, 0x21, 0x19, 0x82, 0xff, 0x3e, 0xa7, 0x66, 0xd6, 0xeb,
- 0x17, 0x6f, 0x12, 0xc5, 0x75, 0x5d, 0x35, 0x93, 0xe1, 0xc3, 0x2f, 0x21,
- 0x02, 0x69, 0x26, 0xed, 0xcf, 0x09, 0xad, 0x18, 0xfd, 0xc5, 0x96, 0x89,
- 0x9b, 0x90, 0xac, 0xf1, 0x14, 0x71, 0xad, 0x1d, 0x7d, 0x73, 0xd3, 0xd0,
- 0x97, 0xff, 0xb5, 0xb9, 0x67, 0x42, 0xc9, 0xd4, 0xf1, 0x62, 0xff, 0xc7,
- 0x7c, 0xef, 0x1c, 0x72, 0x11, 0x62, 0xfb, 0x0f, 0x9c, 0x58, 0xbf, 0xb2,
- 0x3f, 0xf3, 0x83, 0x58, 0xb9, 0xa2, 0xf9, 0xe9, 0x11, 0x15, 0xff, 0xc3,
- 0xfc, 0xf3, 0x34, 0x36, 0x6f, 0xac, 0x56, 0x26, 0x9d, 0xa4, 0xbe, 0x90,
- 0x92, 0x0c, 0xb6, 0x96, 0x2f, 0xf8, 0x6c, 0xc1, 0xe7, 0x18, 0x96, 0x2b,
- 0xe7, 0x88, 0x41, 0x97, 0xba, 0x37, 0xd6, 0x2e, 0x9f, 0x2c, 0x54, 0x9b,
- 0x68, 0xe1, 0xfb, 0xe9, 0xe8, 0xfd, 0x16, 0x2e, 0xc3, 0xac, 0x58, 0xde,
- 0xa6, 0xf5, 0xc9, 0xab, 0x64, 0x44, 0x93, 0x05, 0xf8, 0xdf, 0x66, 0x1d,
- 0x62, 0xff, 0xd0, 0x83, 0xef, 0x27, 0x8b, 0x92, 0xb1, 0x7f, 0xfb, 0x63,
- 0x3e, 0xf2, 0x5b, 0x00, 0xf3, 0x05, 0x8a, 0x94, 0xee, 0xb2, 0x1c, 0x0e,
- 0x46, 0xc5, 0x22, 0x41, 0xbf, 0xf8, 0xb0, 0xd3, 0x5b, 0xdc, 0x72, 0x89,
- 0x62, 0xf6, 0x41, 0xd6, 0x2d, 0x8b, 0x15, 0x11, 0xf9, 0xe9, 0x18, 0x03,
- 0x97, 0xb3, 0x62, 0x58, 0xbd, 0x82, 0xed, 0x62, 0xff, 0x49, 0x0f, 0xec,
- 0x1c, 0x4b, 0x15, 0xf3, 0xf0, 0x21, 0xdf, 0x0f, 0x5f, 0xb0, 0x6f, 0xae,
- 0x2c, 0x52, 0xc5, 0xf4, 0x1c, 0x1c, 0x58, 0xae, 0x1a, 0xf3, 0x03, 0x2f,
- 0x09, 0xb4, 0xb1, 0x7d, 0xbc, 0xe6, 0xcb, 0x14, 0xe7, 0x83, 0xa1, 0xdb,
- 0xf6, 0x7f, 0xe2, 0xf2, 0xc5, 0xef, 0x7b, 0xb5, 0x8b, 0xff, 0xbb, 0xdd,
- 0xff, 0xd4, 0x26, 0x7d, 0xce, 0xb1, 0x40, 0x3e, 0xaf, 0x0f, 0xdc, 0x2d,
- 0x2c, 0x5f, 0x4e, 0xf1, 0xd8, 0xb1, 0x58, 0x98, 0xa6, 0x88, 0x79, 0x09,
- 0x38, 0xe2, 0x23, 0x06, 0x2b, 0x65, 0x44, 0x27, 0x57, 0x0e, 0x37, 0x7b,
- 0xe3, 0x3f, 0x9b, 0xac, 0x5e, 0x66, 0x25, 0x8a, 0x58, 0xb7, 0x3c, 0x69,
- 0xc4, 0x37, 0x5d, 0x9f, 0x98, 0x69, 0x95, 0x28, 0xd1, 0x78, 0x56, 0xdf,
- 0xff, 0x9b, 0xd1, 0x14, 0x83, 0x99, 0x0f, 0xb9, 0x01, 0x62, 0xba, 0xb6,
- 0x54, 0x81, 0x43, 0x49, 0x8f, 0xdb, 0x27, 0xf0, 0x5e, 0x37, 0xcf, 0xca,
- 0x43, 0x68, 0x5f, 0xf2, 0x14, 0x1e, 0x96, 0x40, 0x22, 0x6b, 0xff, 0x13,
- 0x99, 0xde, 0x74, 0xee, 0x4c, 0x58, 0xb4, 0x16, 0x2f, 0xfd, 0xa1, 0xc8,
- 0x79, 0xf9, 0xef, 0x8b, 0x17, 0xff, 0xdc, 0x2c, 0xf3, 0x90, 0x7e, 0xe3,
- 0x77, 0xba, 0xc5, 0x9f, 0x11, 0x27, 0xda, 0x0d, 0xfd, 0xe9, 0xd1, 0x66,
- 0xcb, 0x17, 0xc6, 0x4e, 0x80, 0xb1, 0x7f, 0xbf, 0xf9, 0xda, 0x44, 0x75,
- 0x8b, 0xf4, 0x8b, 0xdd, 0x3b, 0x58, 0xb4, 0xf6, 0x7c, 0x3f, 0x35, 0xbf,
- 0xd1, 0x70, 0x50, 0x29, 0x3a, 0xc5, 0xa3, 0x45, 0x8b, 0xfc, 0x5b, 0xb7,
- 0xb9, 0x26, 0xac, 0x5f, 0xfd, 0xad, 0x30, 0x33, 0xef, 0xaf, 0xb2, 0xc5,
- 0xa0, 0xb1, 0x41, 0x54, 0x51, 0x48, 0xbf, 0x0d, 0x4c, 0x44, 0xbf, 0xf1,
- 0x31, 0xbc, 0x61, 0xfd, 0xa0, 0xb1, 0x7f, 0xd0, 0xe7, 0xc5, 0x25, 0xb0,
- 0x16, 0x2f, 0x38, 0x61, 0x75, 0x8b, 0xfc, 0x2f, 0x7f, 0x0e, 0xc7, 0x58,
- 0xbb, 0x38, 0xb1, 0x6d, 0x2c, 0x57, 0x68, 0xba, 0x88, 0xec, 0xe4, 0x5f,
- 0x34, 0x61, 0x7b, 0xff, 0xf1, 0xb9, 0xe7, 0xe7, 0xc5, 0x9e, 0x03, 0x0e,
- 0x56, 0x2f, 0xef, 0x3e, 0xc7, 0x9d, 0xd6, 0x2a, 0x09, 0xe5, 0x0e, 0x1f,
- 0x3a, 0x4b, 0xfa, 0xb5, 0xf9, 0xa1, 0xed, 0xf8, 0xb1, 0x7b, 0xd9, 0xd1,
- 0x62, 0xff, 0xc3, 0x66, 0x0f, 0xbf, 0x13, 0x7d, 0x62, 0x86, 0x88, 0x96,
- 0x2a, 0xe0, 0xfd, 0xf4, 0x1f, 0x50, 0x58, 0xbf, 0x81, 0x14, 0x1f, 0x50,
- 0x58, 0x88, 0xd1, 0xdf, 0x66, 0xed, 0xba, 0xc5, 0xf4, 0x96, 0x69, 0x62,
- 0xef, 0xe7, 0xcf, 0x17, 0x84, 0x97, 0x3e, 0xcb, 0x15, 0xb9, 0xe2, 0xf8,
- 0xb6, 0x8d, 0x4d, 0x03, 0xb5, 0x2d, 0x43, 0x2e, 0xf6, 0xd8, 0x1a, 0xc5,
- 0xfe, 0xde, 0x27, 0x38, 0x9b, 0x8b, 0x17, 0xd8, 0x2d, 0x6c, 0xb1, 0x74,
- 0xc7, 0xac, 0x50, 0xd1, 0x27, 0xd8, 0xf9, 0xcd, 0xbe, 0x49, 0x7a, 0x45,
- 0x1e, 0xb1, 0x7b, 0xef, 0xe5, 0x8a, 0xd1, 0xbd, 0x30, 0x82, 0xf4, 0x8c,
- 0x6b, 0x17, 0x60, 0x45, 0x8b, 0xe0, 0x18, 0x50, 0x58, 0xb3, 0x11, 0xbd,
- 0xf0, 0xcd, 0xfb, 0x9c, 0xc2, 0x02, 0xc5, 0x00, 0xf3, 0x48, 0x96, 0xa5,
- 0x70, 0xf1, 0xe5, 0x06, 0x34, 0x32, 0xf8, 0xf7, 0xe2, 0x21, 0x42, 0x9e,
- 0xd1, 0x2c, 0x5f, 0xf0, 0x98, 0xc8, 0xa1, 0x9d, 0xc1, 0x62, 0xbb, 0x3d,
- 0x02, 0x13, 0xbe, 0x26, 0xef, 0x8b, 0x17, 0xde, 0x01, 0xf1, 0x62, 0xbc,
- 0x78, 0xc6, 0x11, 0xd1, 0xd1, 0x16, 0x06, 0x8b, 0xa7, 0x8b, 0x17, 0xf7,
- 0x3c, 0xff, 0x10, 0x16, 0x2f, 0xa7, 0xf2, 0x35, 0x8b, 0xd3, 0xdc, 0x16,
- 0x2b, 0x74, 0x43, 0x76, 0x2f, 0x11, 0x79, 0xc8, 0xaf, 0xff, 0xef, 0xe1,
- 0x7b, 0x9d, 0x4c, 0x87, 0xf0, 0x88, 0x50, 0x58, 0xbf, 0xbf, 0x3a, 0x29,
- 0x82, 0xc5, 0xff, 0x17, 0x7e, 0xc8, 0x49, 0x6e, 0xb1, 0x63, 0x46, 0x7c,
- 0xe2, 0x2d, 0xbf, 0x7d, 0xc9, 0xb6, 0x58, 0xbf, 0xe8, 0x36, 0xbc, 0x52,
- 0x7e, 0x2c, 0x5f, 0xe9, 0x1c, 0xe8, 0x52, 0x05, 0x8b, 0xee, 0x93, 0x9a,
- 0x58, 0xbb, 0x3b, 0x58, 0xac, 0x37, 0x84, 0x49, 0x6e, 0x6e, 0x8e, 0xf8,
- 0x8a, 0x0e, 0x72, 0x4d, 0xf7, 0xff, 0xa6, 0x3c, 0xcd, 0xb9, 0xfd, 0xdf,
- 0x98, 0x35, 0x8b, 0xf7, 0xb4, 0xe2, 0xd9, 0x62, 0xa5, 0x3d, 0x73, 0xc6,
- 0x31, 0xf4, 0x40, 0xd4, 0x6e, 0x60, 0xba, 0xc5, 0xff, 0x7f, 0x1e, 0x0e,
- 0x69, 0xb8, 0xb1, 0x7f, 0xcc, 0x66, 0x10, 0xbc, 0x23, 0x56, 0x2a, 0x08,
- 0x90, 0xf0, 0xd8, 0x8e, 0xaf, 0xb4, 0xcc, 0x6a, 0xc5, 0xd3, 0x9d, 0x9e,
- 0x98, 0x66, 0x17, 0x82, 0x14, 0xac, 0x5c, 0x67, 0xd6, 0x2c, 0x52, 0x6d,
- 0xe0, 0x3d, 0x7f, 0xf9, 0x9b, 0x5b, 0x7d, 0xbd, 0xf7, 0xd4, 0x16, 0x2f,
- 0xda, 0x1f, 0xde, 0x25, 0x8b, 0xf8, 0xa7, 0xb8, 0x39, 0x2c, 0x5e, 0xfc,
- 0xe9, 0x60, 0x66, 0xb6, 0xfe, 0xc7, 0x22, 0x91, 0xac, 0x5c, 0xc1, 0x8d,
- 0x1f, 0x58, 0x97, 0xba, 0xbf, 0xcb, 0x6f, 0xf9, 0x8b, 0x3d, 0xe7, 0x0f,
- 0xcb, 0x17, 0xfc, 0x59, 0xff, 0x16, 0x34, 0x4b, 0x17, 0xff, 0xd8, 0x71,
- 0x0f, 0xaf, 0x27, 0x4d, 0x07, 0xfa, 0xc5, 0x75, 0x44, 0x51, 0x1c, 0x5f,
- 0xff, 0xfd, 0x14, 0x1c, 0xbd, 0x20, 0x09, 0xe7, 0x37, 0x59, 0x3d, 0xc1,
- 0xce, 0xb1, 0x52, 0x9a, 0xe9, 0xe1, 0x86, 0x44, 0x95, 0x2c, 0x80, 0xac,
- 0x85, 0x4e, 0xe8, 0x0f, 0x2a, 0x73, 0x51, 0x93, 0xb3, 0x29, 0x46, 0x3e,
- 0x28, 0xe9, 0xaa, 0x36, 0x74, 0xe7, 0xf2, 0xef, 0xb2, 0x8c, 0x2b, 0x2d,
- 0x3c, 0x85, 0xf1, 0xa8, 0x9b, 0xc2, 0x95, 0xca, 0x22, 0x2e, 0xfc, 0x21,
- 0x58, 0xa0, 0x10, 0xd7, 0xe4, 0xf2, 0x3f, 0xa9, 0x29, 0xb7, 0xe0, 0xb7,
- 0xdc, 0x33, 0xcb, 0x17, 0xf1, 0x64, 0x50, 0x9e, 0xd6, 0x2f, 0xfd, 0xdc,
- 0x33, 0xcf, 0xd2, 0x4b, 0x75, 0x8a, 0x81, 0xf8, 0xf8, 0xbe, 0xfe, 0x91,
- 0x76, 0xfd, 0x84, 0x58, 0xbf, 0x60, 0x79, 0xdf, 0x96, 0x2b, 0xa9, 0xee,
- 0x39, 0x95, 0xff, 0xe9, 0x21, 0x75, 0xcf, 0x64, 0xfe, 0x62, 0x58, 0xbf,
- 0xf3, 0x4b, 0x9d, 0xb6, 0x7c, 0x0d, 0x62, 0xff, 0x77, 0x0c, 0x1f, 0xf3,
- 0x65, 0x8b, 0xfe, 0xea, 0xe7, 0xc2, 0x90, 0xe5, 0x62, 0xbb, 0x4e, 0x6b,
- 0x4f, 0xdf, 0x23, 0x02, 0x59, 0x1f, 0x78, 0xda, 0xf4, 0x6f, 0x1b, 0x76,
- 0xb1, 0x7e, 0xef, 0xa9, 0x93, 0xc5, 0x8b, 0xd3, 0x0e, 0x2c, 0x5b, 0x8b,
- 0x16, 0xfc, 0x9e, 0xe7, 0xcb, 0x4c, 0x1d, 0xbf, 0x4e, 0xbb, 0x87, 0x16,
- 0x2f, 0xfa, 0x76, 0xea, 0xc1, 0x02, 0x30, 0x16, 0x2f, 0xe6, 0x80, 0x1c,
- 0xbc, 0xb1, 0x7f, 0xff, 0xda, 0x89, 0xbe, 0xfc, 0x98, 0x9f, 0xde, 0xcf,
- 0x81, 0xfa, 0x2c, 0x54, 0x6c, 0x9d, 0xdc, 0xc2, 0x17, 0x63, 0x5d, 0x15,
- 0x1d, 0x00, 0x45, 0xb7, 0xff, 0x0b, 0x59, 0xb4, 0xf2, 0x61, 0x3a, 0x58,
- 0xbd, 0xac, 0xe2, 0xc5, 0xf9, 0xcb, 0xa6, 0x41, 0x62, 0xf6, 0x3e, 0xcb,
- 0x17, 0xfd, 0x91, 0x7e, 0x7b, 0x89, 0xb7, 0x58, 0xa3, 0x51, 0x40, 0x71,
- 0xdf, 0x94, 0xf0, 0x76, 0xfe, 0x9d, 0xb3, 0xd8, 0x75, 0x8b, 0xf1, 0x9d,
- 0x7f, 0xcc, 0x58, 0xbf, 0xf1, 0x0b, 0x7f, 0xe1, 0xe2, 0x6d, 0xd6, 0x2e,
- 0x16, 0x96, 0x2b, 0x0f, 0x6a, 0x39, 0x0a, 0xa0, 0x9f, 0xdb, 0xc3, 0x97,
- 0x47, 0xc0, 0x2e, 0xe4, 0x21, 0xaf, 0x3c, 0x8d, 0x62, 0xff, 0xdf, 0x68,
- 0x72, 0x5f, 0x66, 0xf2, 0xc5, 0x1c, 0xf6, 0xc8, 0x72, 0xe0, 0x47, 0xac,
- 0x5f, 0xe2, 0x37, 0xf2, 0x73, 0x92, 0xc5, 0xfd, 0x1e, 0xf2, 0x10, 0x5e,
- 0x58, 0xbf, 0x4c, 0x59, 0x9b, 0xac, 0x5e, 0x2c, 0x08, 0xb1, 0x52, 0x8e,
- 0xa8, 0x10, 0xe0, 0xdb, 0x9a, 0x7c, 0xcc, 0x45, 0x37, 0xfe, 0x6d, 0xfa,
- 0xc9, 0x93, 0xb3, 0x71, 0x62, 0xff, 0xc5, 0x9a, 0xd4, 0xb7, 0x98, 0xd5,
- 0x8b, 0xc7, 0x6f, 0x2c, 0x5f, 0xb3, 0x4e, 0x7e, 0x2c, 0x5e, 0x69, 0xed,
- 0x62, 0xa4, 0xf1, 0x4e, 0x51, 0x5d, 0xa6, 0x09, 0xa4, 0x32, 0x3e, 0x0d,
- 0x8a, 0xff, 0x7b, 0x8f, 0xd3, 0x4f, 0xc5, 0x8b, 0x1d, 0x62, 0x96, 0x2b,
- 0x0b, 0xe6, 0x12, 0xbe, 0xf7, 0xde, 0x25, 0x8b, 0xf9, 0xf4, 0x61, 0x42,
- 0x56, 0x2a, 0x4f, 0x4a, 0x04, 0x94, 0x34, 0x48, 0x86, 0xe1, 0x73, 0xc1,
- 0x62, 0xb1, 0x32, 0x07, 0x87, 0x29, 0x12, 0x5f, 0xfe, 0xe3, 0x67, 0x47,
- 0xf4, 0x30, 0xd3, 0x71, 0x62, 0xe9, 0xdd, 0x62, 0xff, 0xb9, 0x27, 0x29,
- 0xee, 0x78, 0xb1, 0x46, 0x9e, 0x8f, 0x06, 0x2f, 0xfb, 0x22, 0x78, 0x84,
- 0x10, 0x5c, 0x58, 0xb3, 0x2c, 0x57, 0xcf, 0x3f, 0xc7, 0xd7, 0xf4, 0xc5,
- 0x84, 0x2c, 0x58, 0xbb, 0x46, 0xac, 0x54, 0x9e, 0x33, 0x96, 0xdf, 0x79,
- 0xe7, 0xb5, 0x8b, 0xec, 0xda, 0x62, 0x58, 0xa9, 0x4d, 0x05, 0xdc, 0x89,
- 0xa3, 0x84, 0x02, 0x23, 0xbf, 0xe9, 0x8a, 0x7d, 0xfc, 0xd6, 0xeb, 0x17,
- 0xff, 0xa7, 0xbe, 0xa2, 0x89, 0xbb, 0xe7, 0xf3, 0xcb, 0x17, 0xbf, 0x31,
- 0x2c, 0x57, 0x68, 0xa9, 0xf9, 0xd8, 0x45, 0x0b, 0xfd, 0x83, 0x79, 0x27,
- 0x3a, 0xc5, 0x49, 0xf2, 0x7c, 0xce, 0xa0, 0x9b, 0xb7, 0x23, 0x55, 0xbc,
- 0x28, 0x9d, 0x62, 0xe7, 0x75, 0x8a, 0x8f, 0x36, 0x84, 0x3d, 0x7e, 0xfb,
- 0x7b, 0xe6, 0x2c, 0x5c, 0xdb, 0x2c, 0x5f, 0xcc, 0x7c, 0xe8, 0xda, 0x58,
- 0xad, 0x8f, 0x1c, 0xe3, 0x17, 0xfe, 0x89, 0xff, 0x3d, 0xc2, 0x62, 0x95,
- 0x8a, 0xdd, 0x1a, 0xae, 0xe2, 0x22, 0x3b, 0xd3, 0xe3, 0xac, 0x5f, 0xff,
- 0x18, 0xe7, 0xea, 0x69, 0x0b, 0x9d, 0xee, 0xfd, 0xac, 0x58, 0xeb, 0x15,
- 0x27, 0xd5, 0xc5, 0x8a, 0x3a, 0x2a, 0x02, 0x42, 0x1e, 0xff, 0xb8, 0x2d,
- 0xa6, 0x2e, 0xa0, 0xf2, 0xc5, 0xf8, 0x6c, 0x53, 0xf5, 0x8b, 0xfd, 0xd1,
- 0xf5, 0x9d, 0x1b, 0x4b, 0x17, 0xf4, 0x27, 0xbf, 0x67, 0xd6, 0x2f, 0xff,
- 0x7b, 0x8e, 0x09, 0x87, 0x33, 0x3b, 0xf2, 0xc5, 0x62, 0x2c, 0x62, 0x37,
- 0xe1, 0x7d, 0x76, 0x9a, 0x3f, 0xcf, 0xc3, 0x86, 0xc5, 0xfe, 0xcd, 0xf0,
- 0xa7, 0x03, 0x58, 0xbf, 0xe1, 0xcf, 0xc6, 0xfd, 0x24, 0x6b, 0x17, 0xf4,
- 0xc4, 0x79, 0x1c, 0xac, 0x5f, 0xfc, 0xdf, 0x68, 0xbf, 0x3d, 0xfa, 0x7e,
- 0xb1, 0x47, 0x3f, 0x40, 0x17, 0x5f, 0xa2, 0xc7, 0x08, 0x35, 0x8a, 0x73,
- 0xcd, 0x62, 0x2b, 0xff, 0xf3, 0x45, 0xc1, 0x17, 0xb5, 0x93, 0xdc, 0x1c,
- 0xeb, 0x15, 0x29, 0xb9, 0xfe, 0x1f, 0x81, 0x90, 0x5f, 0xff, 0xc6, 0x31,
- 0x3f, 0x6f, 0x14, 0x84, 0x11, 0x82, 0xe7, 0x96, 0x2f, 0xfd, 0x3e, 0xe3,
- 0x38, 0xc5, 0xee, 0x2c, 0x54, 0xae, 0x12, 0xbc, 0x6e, 0x3f, 0x38, 0xe4,
- 0x74, 0xc2, 0x36, 0x0d, 0x86, 0xfd, 0x9d, 0xc3, 0xee, 0xb1, 0x7f, 0xf3,
- 0x96, 0x7a, 0x4f, 0xd4, 0x27, 0x4f, 0x2c, 0x5f, 0x04, 0x21, 0x6c, 0xb1,
- 0x5d, 0x51, 0x33, 0x1e, 0x52, 0x74, 0xab, 0xf7, 0xde, 0x27, 0xd9, 0x62,
- 0xed, 0x41, 0x62, 0x9c, 0xf0, 0x98, 0xaa, 0xd2, 0xb1, 0x5c, 0x36, 0x3e,
- 0x20, 0xbf, 0xe7, 0xd3, 0xed, 0x14, 0x04, 0x6a, 0xc5, 0x80, 0xb1, 0x5b,
- 0x1e, 0x7c, 0x79, 0xed, 0xfb, 0xce, 0x50, 0x95, 0x8b, 0xfb, 0xb8, 0x60,
- 0xb5, 0xb2, 0xc5, 0xff, 0xed, 0x6a, 0x4b, 0x0d, 0x7f, 0xff, 0x0c, 0x58,
- 0xac, 0x45, 0x1b, 0x93, 0x88, 0xc6, 0xf1, 0x4c, 0x16, 0x2a, 0x55, 0x15,
- 0xe4, 0x2a, 0x1d, 0xc3, 0x50, 0xc9, 0x62, 0xeb, 0xf9, 0xcd, 0x7f, 0x37,
- 0xd6, 0x2f, 0x6f, 0xf9, 0x58, 0xbb, 0x52, 0xb1, 0x50, 0x3e, 0x3e, 0xcb,
- 0xa2, 0x1e, 0xbf, 0x4b, 0xf8, 0x29, 0x1a, 0xd6, 0x2f, 0xcc, 0xe3, 0x92,
- 0x58, 0xba, 0x44, 0xb1, 0x52, 0x8a, 0x0f, 0x98, 0x91, 0x97, 0x09, 0xaf,
- 0xc2, 0x11, 0x8f, 0x1e, 0xb1, 0x70, 0x49, 0x58, 0xb8, 0xb7, 0x58, 0xa9,
- 0x36, 0x2e, 0x33, 0x7f, 0x84, 0xe5, 0x9c, 0xe6, 0x2c, 0x56, 0xc7, 0xa2,
- 0x71, 0xfb, 0xb3, 0x75, 0x8b, 0xfe, 0x6f, 0x7e, 0x78, 0x21, 0xe2, 0xc5,
- 0xf7, 0xc0, 0xde, 0x58, 0xb7, 0xd6, 0x29, 0x8d, 0xa8, 0x88, 0xef, 0xf1,
- 0x67, 0xa6, 0x02, 0xd2, 0xc5, 0x1d, 0x1b, 0x24, 0x31, 0xd1, 0xb8, 0x21,
- 0x05, 0xf8, 0x0c, 0x76, 0xed, 0x62, 0xff, 0xc7, 0x7e, 0x7e, 0x5f, 0x42,
- 0x8f, 0x58, 0xae, 0xcf, 0xad, 0xca, 0x6b, 0xaa, 0xa7, 0x89, 0x85, 0x7b,
- 0xc3, 0xf1, 0xa1, 0x57, 0x7c, 0x22, 0x93, 0xac, 0x5e, 0x6d, 0x6e, 0xb1,
- 0x7e, 0xe3, 0xf4, 0x91, 0xac, 0x57, 0x67, 0xd4, 0x02, 0x22, 0x1e, 0xbf,
- 0xe0, 0x39, 0x7a, 0x78, 0x2f, 0xac, 0x5f, 0xa4, 0xce, 0x4f, 0x16, 0x2f,
- 0xf6, 0xb6, 0x7d, 0xdf, 0x58, 0xb1, 0x78, 0x9c, 0xd5, 0x8b, 0xf3, 0x6b,
- 0x53, 0xb2, 0xc5, 0xfd, 0xe7, 0xd3, 0xf8, 0x4b, 0x16, 0x9e, 0xa9, 0x85,
- 0xec, 0x73, 0x85, 0x27, 0x35, 0xf0, 0xe9, 0x85, 0x37, 0xe3, 0x3f, 0x9d,
- 0xf1, 0x62, 0xe6, 0x8f, 0x58, 0xa1, 0x1e, 0x29, 0x85, 0x77, 0xff, 0xf4,
- 0xf3, 0x7f, 0xbf, 0xf3, 0xa6, 0x3c, 0xec, 0x21, 0xac, 0x5f, 0xff, 0xff,
- 0x4f, 0x89, 0xb7, 0x7e, 0x44, 0xfa, 0xde, 0x79, 0xe9, 0xee, 0x4c, 0xce,
- 0x2c, 0x5f, 0xee, 0x66, 0xa7, 0xa4, 0xc7, 0xac, 0x5f, 0xb0, 0xa7, 0xbe,
- 0x2c, 0x51, 0xa9, 0x9f, 0x69, 0x7b, 0xd0, 0x80, 0xe8, 0x71, 0x7f, 0xbf,
- 0x9d, 0xce, 0x9c, 0xeb, 0x17, 0xfd, 0x3b, 0xeb, 0x39, 0x8e, 0x35, 0x8b,
- 0xff, 0xcf, 0xac, 0x89, 0xf4, 0x11, 0xcc, 0xc8, 0x2c, 0x56, 0x91, 0x0d,
- 0xc3, 0x9b, 0xd2, 0x79, 0x58, 0xad, 0x1b, 0xff, 0x11, 0xdf, 0xe3, 0x93,
- 0x1a, 0xff, 0x12, 0xc5, 0xf7, 0xdd, 0x80, 0xb1, 0x69, 0xea, 0x7a, 0xde,
- 0x34, 0xbf, 0xff, 0xff, 0xee, 0x67, 0xbe, 0xc7, 0xe6, 0xb4, 0xfd, 0xf9,
- 0x98, 0xdc, 0xc8, 0x85, 0xe9, 0x0f, 0xb9, 0x58, 0xbf, 0x0a, 0x2c, 0x8e,
- 0xc5, 0x8b, 0xbe, 0xcb, 0x15, 0xc4, 0x6d, 0xfa, 0x13, 0x1d, 0x0b, 0x2f,
- 0xfb, 0xbe, 0x13, 0x9f, 0xd9, 0x1e, 0xb1, 0x76, 0x69, 0x62, 0xa4, 0xf5,
- 0x3e, 0x7b, 0x7f, 0x78, 0x98, 0x18, 0x4b, 0x17, 0x49, 0xab, 0x17, 0xcc,
- 0x0c, 0x25, 0x8a, 0x88, 0xdc, 0x90, 0xc5, 0x75, 0x44, 0x37, 0x99, 0x6a,
- 0x57, 0x04, 0x46, 0x8d, 0x90, 0xf9, 0xdd, 0xdd, 0xa3, 0x04, 0xf4, 0x22,
- 0xc5, 0x0a, 0x7b, 0xfd, 0x06, 0xed, 0xc2, 0x38, 0xd6, 0x2f, 0x80, 0xdd,
- 0xf1, 0x62, 0xe0, 0xc3, 0x58, 0xae, 0x1b, 0xe0, 0xc9, 0x2f, 0xbe, 0xd9,
- 0xf4, 0x88, 0xc3, 0x45, 0x7f, 0xfe, 0x31, 0xce, 0x2e, 0x49, 0x8e, 0x79,
- 0x8a, 0x43, 0x58, 0xb9, 0xf6, 0x58, 0xa9, 0x4c, 0xf1, 0xe1, 0x2c, 0xc6,
- 0xbd, 0x16, 0x6f, 0xb7, 0x91, 0x76, 0xb1, 0x7e, 0x33, 0x0e, 0xfa, 0x58,
- 0xbf, 0x3e, 0xbd, 0x9b, 0xac, 0x5f, 0xb7, 0x7e, 0x7d, 0xd6, 0x2f, 0xee,
- 0xdf, 0x63, 0xbf, 0x16, 0x2e, 0x3b, 0x2c, 0x5f, 0xef, 0x49, 0x6f, 0x1a,
- 0x00, 0xeb, 0x15, 0x28, 0x81, 0xf9, 0x80, 0x85, 0xef, 0x7e, 0x40, 0xb1,
- 0x78, 0x20, 0x49, 0x58, 0xbf, 0xe1, 0xfd, 0xf4, 0xfd, 0xc5, 0x2b, 0x14,
- 0xc7, 0xb8, 0x22, 0x1b, 0xa3, 0x7e, 0x8b, 0x15, 0x2a, 0x82, 0x70, 0x94,
- 0xd2, 0x9e, 0xca, 0x5e, 0x15, 0x4c, 0x5e, 0x4f, 0x3e, 0x21, 0xbf, 0xff,
- 0xbf, 0x86, 0xb4, 0xbc, 0x74, 0xf6, 0x13, 0x7f, 0xb7, 0x6b, 0x17, 0xda,
- 0x7d, 0xe5, 0x62, 0xff, 0xff, 0xff, 0xe2, 0x0b, 0x8f, 0x0c, 0x0b, 0x5c,
- 0x8d, 0x45, 0x31, 0xa0, 0x6f, 0xb0, 0x43, 0x41, 0x1a, 0x47, 0x78, 0x71,
- 0xdd, 0x7a, 0xfe, 0x39, 0x62, 0xff, 0xff, 0x4f, 0x3a, 0xf3, 0x0e, 0xdd,
- 0xfd, 0x82, 0x39, 0x37, 0x6b, 0x14, 0x34, 0xee, 0xf1, 0x8f, 0xb2, 0x33,
- 0xc3, 0x42, 0xf7, 0xfa, 0xc7, 0xac, 0x5e, 0x2d, 0xdd, 0x62, 0xf1, 0x66,
- 0xcb, 0x17, 0xdc, 0xd3, 0x86, 0xb1, 0x6f, 0xc9, 0xe0, 0xb0, 0xed, 0x4a,
- 0x29, 0xdc, 0x8d, 0x97, 0xaf, 0xff, 0xfe, 0xf1, 0x30, 0x09, 0xe7, 0xac,
- 0xf4, 0x9d, 0x71, 0xfd, 0x25, 0xb2, 0xc5, 0xf6, 0xff, 0x7d, 0x2c, 0x5d,
- 0x3e, 0xea, 0x89, 0x76, 0x73, 0xbf, 0x3e, 0xcc, 0x22, 0x58, 0xbf, 0x68,
- 0x5b, 0x0b, 0x65, 0x8b, 0xfa, 0x7c, 0x23, 0x8b, 0xcb, 0x17, 0xc7, 0x97,
- 0x8e, 0x58, 0xbf, 0xd2, 0x5f, 0x60, 0x0a, 0x25, 0x8a, 0x94, 0x5a, 0x7c,
- 0xb0, 0x45, 0xe1, 0x09, 0x68, 0x2d, 0xba, 0xd3, 0x79, 0x94, 0x77, 0xb4,
- 0xa1, 0x38, 0x4a, 0x5d, 0x1c, 0x73, 0x39, 0x1a, 0xc1, 0xb1, 0xaf, 0xee,
- 0x67, 0xdc, 0xb5, 0x57, 0x5e, 0x8f, 0x87, 0xc4, 0x53, 0x9f, 0xba, 0x96,
- 0x52, 0x78, 0xd5, 0x7f, 0x2a, 0xcd, 0xa1, 0x6e, 0x08, 0xce, 0x82, 0xf0,
- 0xa5, 0x29, 0xd7, 0x2e, 0x47, 0x6d, 0xe9, 0x49, 0x62, 0x94, 0x61, 0xd2,
- 0x1d, 0x51, 0xd0, 0xc4, 0x30, 0xbc, 0x24, 0x37, 0x2f, 0xff, 0xfd, 0xd3,
- 0x6e, 0x46, 0xbd, 0xa3, 0x40, 0xa6, 0xa2, 0x2f, 0x60, 0xfa, 0xf5, 0xfc,
- 0x72, 0xc5, 0xe2, 0x8d, 0xe0, 0xb1, 0x41, 0x6d, 0x15, 0xbf, 0x84, 0x5d,
- 0xf6, 0xb3, 0xd8, 0xb1, 0x7f, 0xb7, 0xfb, 0xfb, 0x8d, 0xda, 0xc5, 0xec,
- 0xd7, 0x45, 0x8b, 0xf6, 0x70, 0x85, 0xf5, 0x8b, 0xf4, 0x8f, 0xf3, 0xc5,
- 0x8b, 0xda, 0x32, 0x25, 0x8b, 0x8f, 0xf5, 0x8a, 0x73, 0x71, 0xc2, 0x0b,
- 0xff, 0x10, 0x0e, 0xd0, 0x29, 0xf7, 0x16, 0x2e, 0xcc, 0x58, 0xbe, 0xdf,
- 0xee, 0x62, 0xc5, 0x46, 0x89, 0xe3, 0x61, 0x71, 0xa4, 0x4e, 0x6d, 0x1e,
- 0x3f, 0xa2, 0x8f, 0xb0, 0x31, 0x00, 0x5c, 0xf8, 0xc1, 0x6b, 0xf4, 0x53,
- 0x17, 0xe5, 0x62, 0xff, 0xf1, 0x7b, 0x86, 0x79, 0xc8, 0x50, 0xce, 0x2c,
- 0x5f, 0xfb, 0x1c, 0x12, 0x08, 0x66, 0xa5, 0x62, 0xfc, 0xc5, 0xee, 0x01,
- 0x62, 0xdf, 0x23, 0xe5, 0x08, 0x7b, 0x7f, 0xc1, 0x38, 0x4d, 0x11, 0x49,
- 0xd6, 0x2d, 0x2b, 0x14, 0x23, 0xcc, 0x30, 0xee, 0xfb, 0x34, 0xd0, 0x58,
- 0xbf, 0xbf, 0x91, 0x31, 0x6c, 0xb1, 0x78, 0x30, 0xc3, 0x48, 0xbe, 0x87,
- 0xb3, 0x74, 0x88, 0xc3, 0x43, 0x7e, 0xc1, 0xb8, 0x38, 0xbb, 0xbf, 0x8a,
- 0xea, 0x8b, 0xcd, 0x28, 0x11, 0xbd, 0xdc, 0x82, 0xc5, 0xee, 0x30, 0x16,
- 0x2a, 0x4d, 0xaf, 0x63, 0x16, 0xe8, 0xb1, 0x68, 0xe5, 0x8a, 0xdc, 0xd4,
- 0x9c, 0x52, 0xfe, 0x7d, 0x3c, 0x24, 0xd5, 0x8a, 0xc3, 0xd0, 0xf1, 0x15,
- 0x4a, 0xb7, 0x1c, 0x2a, 0x78, 0x58, 0x69, 0xd4, 0xe4, 0x6d, 0x0d, 0xe0,
- 0x33, 0x14, 0x26, 0xaf, 0x8e, 0x3c, 0x25, 0x8b, 0xbd, 0xc5, 0x8b, 0xff,
- 0xc3, 0xcc, 0x37, 0xae, 0x79, 0xf9, 0xf7, 0x58, 0xbf, 0xde, 0xfc, 0xfb,
- 0x9f, 0x75, 0x8b, 0xa1, 0xb2, 0xc5, 0xf0, 0x7c, 0xc3, 0x16, 0x2f, 0x1a,
- 0x2d, 0x96, 0x2e, 0x68, 0x2c, 0x5f, 0xba, 0xe4, 0x4f, 0xb2, 0xc5, 0x75,
- 0x46, 0xac, 0x0d, 0x30, 0x64, 0xd2, 0x53, 0x90, 0x70, 0x5e, 0xff, 0xfd,
- 0xf2, 0xce, 0xe0, 0x58, 0x6b, 0xff, 0xf9, 0x1e, 0xb1, 0x6e, 0x2c, 0x5c,
- 0xc6, 0xac, 0x5f, 0xa1, 0xf9, 0x2d, 0x92, 0x2e, 0x98, 0x2c, 0x5e, 0x03,
- 0x41, 0x62, 0xbb, 0x3d, 0xdf, 0x94, 0x98, 0x2f, 0x4c, 0x8a, 0x6f, 0x3a,
- 0xdf, 0xfb, 0x3b, 0x83, 0xe1, 0x16, 0x0d, 0x62, 0xf8, 0xe2, 0xef, 0xcb,
- 0x17, 0xbf, 0x3d, 0x16, 0x2e, 0x90, 0x2c, 0x56, 0x1b, 0x63, 0x07, 0xeb,
- 0x63, 0xfc, 0xe2, 0xdd, 0x4a, 0xba, 0x1d, 0x86, 0x3b, 0x8c, 0x85, 0xd6,
- 0x74, 0xb2, 0x50, 0xb8, 0xe1, 0x17, 0xa1, 0x73, 0x7f, 0x7d, 0xc7, 0x2d,
- 0xa5, 0x8b, 0xc1, 0x05, 0xb2, 0xc5, 0x6e, 0x79, 0xc1, 0x0b, 0x6f, 0xfe,
- 0x83, 0x90, 0x35, 0x9d, 0x24, 0xbc, 0xb1, 0x79, 0xf8, 0xeb, 0x16, 0x75,
- 0x8b, 0xe6, 0x31, 0x86, 0xb1, 0x7a, 0x74, 0x6a, 0xc5, 0xa1, 0x88, 0xb3,
- 0xfa, 0x2b, 0x0e, 0x08, 0x44, 0x32, 0x3b, 0xff, 0xfc, 0x3f, 0xe7, 0xbc,
- 0xc5, 0xbf, 0x27, 0x4d, 0x13, 0xfd, 0x62, 0xfc, 0x67, 0xff, 0x91, 0x2c,
- 0x5f, 0x19, 0xf7, 0xf2, 0xc5, 0x75, 0x3c, 0xfe, 0x15, 0xd0, 0xd3, 0xfc,
- 0xee, 0x1b, 0x0e, 0x9e, 0x08, 0x58, 0xdf, 0x8d, 0x32, 0x74, 0x05, 0x8b,
- 0xfe, 0x29, 0x0f, 0x8e, 0x5d, 0xc1, 0x62, 0xff, 0xff, 0xdc, 0x03, 0xe8,
- 0x78, 0x5f, 0x7d, 0xfe, 0xfe, 0x36, 0x4a, 0x0b, 0x17, 0x82, 0xf1, 0xce,
- 0xb1, 0x74, 0xee, 0xb1, 0x5a, 0x4c, 0x38, 0x8a, 0xfc, 0x74, 0x26, 0xde,
- 0x84, 0x97, 0xfc, 0x46, 0xf1, 0xfa, 0x49, 0x79, 0x62, 0xff, 0xef, 0xb4,
- 0x58, 0x3f, 0xbf, 0x4c, 0x89, 0x62, 0xa5, 0x10, 0x6e, 0x77, 0x78, 0xc9,
- 0x8f, 0x58, 0xbb, 0xee, 0xb1, 0x60, 0x2c, 0x51, 0xa6, 0xa4, 0x85, 0xeb,
- 0x63, 0xeb, 0x74, 0xab, 0xfe, 0xf7, 0xde, 0x41, 0xb7, 0x0d, 0x58, 0xbf,
- 0x14, 0x87, 0x84, 0xb1, 0x7f, 0xdf, 0xee, 0x4d, 0x8a, 0x13, 0x1e, 0xb1,
- 0x6e, 0x0c, 0xf9, 0xf0, 0x9e, 0xb4, 0x8e, 0xc2, 0x22, 0xf4, 0x28, 0xe9,
- 0x62, 0xfe, 0x33, 0xdc, 0x7c, 0x35, 0x62, 0xfd, 0x0d, 0x3c, 0x9d, 0x62,
- 0xff, 0x6f, 0xe6, 0x7d, 0x6b, 0x16, 0x2f, 0x19, 0xd8, 0x6b, 0x15, 0xb2,
- 0x2e, 0x46, 0x19, 0xd9, 0x86, 0x8a, 0x38, 0x69, 0x52, 0xbf, 0x45, 0x92,
- 0xb3, 0x1e, 0x35, 0x6f, 0xc3, 0x3d, 0xa3, 0x78, 0x14, 0x3b, 0x6f, 0x7c,
- 0x20, 0xd6, 0x2f, 0x38, 0x25, 0x62, 0xfa, 0x19, 0xe7, 0x58, 0xbe, 0xcd,
- 0x39, 0xd6, 0x2f, 0x02, 0x40, 0xb1, 0x5d, 0x4f, 0xf7, 0xb1, 0xce, 0x11,
- 0x18, 0x45, 0x7f, 0xfa, 0x1e, 0x17, 0xf5, 0x21, 0xc1, 0xc1, 0x8b, 0x17,
- 0x31, 0xd6, 0x2b, 0x74, 0x51, 0x92, 0x07, 0x44, 0xcb, 0xff, 0xf7, 0x9b,
- 0x58, 0xe0, 0xe6, 0x7d, 0xf5, 0xf6, 0x58, 0xbf, 0xef, 0xbe, 0xa2, 0x29,
- 0x9e, 0xd6, 0x2e, 0xdf, 0x16, 0x2f, 0x69, 0xb8, 0xb1, 0x7a, 0x48, 0x6b,
- 0x17, 0xee, 0xf9, 0x16, 0x79, 0x62, 0xb1, 0x33, 0xce, 0xcc, 0x9d, 0x53,
- 0x47, 0x47, 0x18, 0xf8, 0xe9, 0x0e, 0x5f, 0xcf, 0xe2, 0x60, 0x71, 0x62,
- 0xfd, 0x27, 0xf6, 0x7d, 0x62, 0xec, 0xdd, 0x62, 0xf8, 0x02, 0x93, 0xac,
- 0x56, 0x1b, 0xb7, 0x18, 0xbd, 0x25, 0xb2, 0xc5, 0xf8, 0x41, 0xfe, 0x7a,
- 0x2c, 0x5f, 0xff, 0x17, 0xa2, 0xcd, 0x67, 0x5f, 0x02, 0x47, 0x2b, 0x17,
- 0xa4, 0xa2, 0x58, 0xa8, 0x91, 0xaf, 0xa1, 0xff, 0x8e, 0xb1, 0x61, 0x8a,
- 0x57, 0xdc, 0x79, 0xdd, 0x62, 0xfb, 0x3b, 0xf3, 0xac, 0x5f, 0xfd, 0x16,
- 0x6b, 0x18, 0xf3, 0xf7, 0x1a, 0xc5, 0x62, 0x22, 0xbe, 0x47, 0xe2, 0x3b,
- 0x62, 0xc5, 0xf8, 0xf9, 0xfe, 0xd9, 0x62, 0xa2, 0x37, 0x42, 0x11, 0xbf,
- 0x78, 0x51, 0x19, 0x2b, 0x17, 0x30, 0xd6, 0x2d, 0x90, 0x3c, 0x2d, 0x15,
- 0xd1, 0xaa, 0xcc, 0x37, 0x2d, 0xfc, 0x67, 0x45, 0x0d, 0x5e, 0x34, 0xf4,
- 0x64, 0xbf, 0xfc, 0xe3, 0x26, 0xec, 0xb3, 0xd8, 0xe0, 0x58, 0xbe, 0xdb,
- 0x66, 0x8f, 0x58, 0xbe, 0xdc, 0x62, 0xd9, 0x62, 0xf4, 0x38, 0x25, 0x8b,
- 0x9a, 0x0b, 0x17, 0xef, 0x3f, 0xe0, 0x4b, 0x14, 0x73, 0x7e, 0x42, 0xf7,
- 0xff, 0xff, 0xef, 0xce, 0x6d, 0x07, 0xf7, 0x27, 0x59, 0x18, 0xe0, 0x99,
- 0xe9, 0x32, 0x5b, 0xac, 0x5b, 0xd8, 0x99, 0x4f, 0xc9, 0x99, 0x77, 0x84,
- 0x17, 0x83, 0x0c, 0x35, 0x8b, 0xff, 0xe3, 0xe7, 0x7e, 0x2c, 0xd8, 0xf8,
- 0x7c, 0x24, 0x88, 0xc3, 0x43, 0x70, 0x60, 0x58, 0xbe, 0xef, 0x93, 0x05,
- 0x8a, 0x94, 0xc0, 0xdd, 0x8d, 0x98, 0xc0, 0x33, 0x7d, 0xb6, 0x7d, 0x96,
- 0x2f, 0x6d, 0x03, 0xac, 0x5a, 0x0b, 0x17, 0xfe, 0x7e, 0x00, 0xe2, 0xe7,
- 0x24, 0x0b, 0x17, 0xfb, 0x44, 0xc1, 0xe7, 0xd9, 0x62, 0xf9, 0xb5, 0xfc,
- 0x58, 0xbf, 0xe2, 0x6d, 0xb9, 0x9f, 0x68, 0xf5, 0x8b, 0xef, 0x4f, 0xb9,
- 0x87, 0xbc, 0xc4, 0x57, 0xef, 0xb6, 0xb3, 0x4b, 0x17, 0xfd, 0xe7, 0x04,
- 0xc3, 0x3b, 0xf2, 0xc5, 0xff, 0x3f, 0x65, 0x9e, 0xfb, 0x86, 0xb1, 0x52,
- 0x7e, 0x9a, 0x3a, 0xbf, 0xfb, 0x62, 0x16, 0xc2, 0xe7, 0xb9, 0x81, 0xac,
- 0x5f, 0xbb, 0xdd, 0xcb, 0x65, 0x8b, 0xfd, 0xf9, 0x84, 0x50, 0x62, 0x58,
- 0xaf, 0x1e, 0xf9, 0x85, 0x75, 0x28, 0xcb, 0x68, 0x54, 0x5c, 0x26, 0x58,
- 0xae, 0xaa, 0xbf, 0xb6, 0x1f, 0x80, 0x90, 0xd0, 0x32, 0x12, 0x3b, 0x9b,
- 0xea, 0x13, 0x9f, 0x87, 0x61, 0x13, 0x5f, 0xf0, 0x0b, 0x37, 0x7c, 0xf7,
- 0x16, 0x2f, 0x7a, 0x46, 0xb1, 0x7d, 0x0f, 0x08, 0x6b, 0x17, 0xe9, 0x78,
- 0x37, 0x16, 0x2f, 0xe6, 0x33, 0x22, 0x93, 0xac, 0x54, 0xa2, 0x5f, 0xb1,
- 0xdd, 0x12, 0x08, 0x9e, 0xfe, 0xcf, 0x7c, 0x53, 0xda, 0xc5, 0xf7, 0x9f,
- 0x58, 0xb1, 0x7d, 0xdf, 0x1c, 0xd1, 0x9e, 0x8e, 0x17, 0xd6, 0xca, 0x8a,
- 0x75, 0x09, 0x12, 0x86, 0x87, 0xa1, 0x1d, 0x7f, 0x70, 0xb3, 0xa7, 0xdd,
- 0x62, 0xff, 0xf4, 0x30, 0x9c, 0x78, 0x58, 0x6c, 0xf1, 0x62, 0xf6, 0xf9,
- 0xc5, 0x8a, 0xc4, 0x4a, 0xf8, 0xbc, 0x49, 0x17, 0xfe, 0x3c, 0xf6, 0x58,
- 0x0e, 0x4c, 0x7a, 0xc5, 0xfe, 0xfe, 0x6d, 0x9f, 0x7f, 0xac, 0x56, 0x91,
- 0x4a, 0x72, 0xff, 0xa1, 0x5f, 0xe1, 0x96, 0x74, 0x7d, 0x32, 0xc5, 0x46,
- 0xcb, 0xe6, 0xd3, 0x3a, 0x94, 0xf1, 0xc4, 0x08, 0xc2, 0xfa, 0x3d, 0xf3,
- 0xb5, 0x8b, 0x9b, 0x75, 0x8a, 0xd8, 0xdf, 0x31, 0x35, 0xf9, 0xf9, 0x3b,
- 0x1d, 0x76, 0x7e, 0x97, 0xe9, 0x6d, 0x00, 0x4b, 0xb3, 0xf4, 0xb9, 0xa0,
- 0xbb, 0x3f, 0x4b, 0xe1, 0x43, 0x38, 0xbb, 0x3f, 0x4a, 0x19, 0xea, 0x11,
- 0x25, 0xfa, 0x73, 0x98, 0x4b, 0xb3, 0xf4, 0xa5, 0xd9, 0xfa, 0x5c, 0xde,
- 0x5d, 0x9f, 0xa1, 0xcb, 0x9b, 0x40, 0x8f, 0xfc, 0x49, 0x97, 0xd9, 0x1c,
- 0xe0, 0x5d, 0x9f, 0xa5, 0x2e, 0xcf, 0xd2, 0xe0, 0x4a, 0xec, 0xfd, 0x2f,
- 0xfb, 0x00, 0xda, 0xce, 0x98, 0x35, 0xd9, 0xfa, 0x5f, 0xd9, 0xf7, 0xe0,
- 0xb6, 0x5d, 0x9f, 0xa5, 0x01, 0x14, 0xe4, 0x49, 0xc4, 0x7b, 0xed, 0x6d,
- 0x3e, 0x5d, 0x9f, 0xa5, 0x2e, 0xcf, 0xd3, 0x0d, 0x8d, 0xc1, 0x86, 0xbb,
- 0x3f, 0x4a, 0x82, 0xb2, 0x71, 0x9b, 0x64, 0x22, 0x7b, 0x85, 0x06, 0x89,
- 0xce, 0x65, 0xc8, 0x60, 0x79, 0x80, 0x32, 0x8b, 0xa4, 0xd4, 0xd9, 0xfa,
- 0x23, 0x11, 0x21, 0x7f, 0xdb, 0x4f, 0x4c, 0x7d, 0x66, 0xcb, 0x17, 0xff,
- 0x37, 0xf7, 0xfb, 0x93, 0x69, 0xa0, 0xb1, 0x50, 0x45, 0xde, 0x8e, 0xfc,
- 0x79, 0x7f, 0x4e, 0x19, 0x30, 0x82, 0xc5, 0xfe, 0xe6, 0x42, 0x13, 0xee,
- 0xd6, 0x2f, 0xfa, 0x74, 0x0f, 0x3b, 0x1b, 0x05, 0x8a, 0xc4, 0x66, 0x91,
- 0x87, 0x0b, 0x8c, 0x35, 0xbf, 0xf6, 0x6e, 0x3c, 0xd0, 0x6d, 0xf8, 0x96,
- 0x2e, 0x93, 0x16, 0x29, 0x62, 0xff, 0xc5, 0x91, 0x4e, 0xc0, 0x6e, 0xf8,
- 0xb1, 0x52, 0x79, 0xbc, 0x0c, 0xa4, 0x8b, 0xf3, 0xc4, 0xcd, 0x05, 0x8b,
- 0x43, 0x63, 0x69, 0x81, 0x97, 0xd1, 0x33, 0x69, 0x62, 0xb6, 0x4e, 0x0b,
- 0xb3, 0xcd, 0x21, 0x7d, 0x94, 0x95, 0x42, 0x13, 0xdc, 0xfb, 0x2c, 0x5f,
- 0xd3, 0xf2, 0x67, 0xd2, 0xc5, 0x69, 0x7e, 0x05, 0xa7, 0xb8, 0xbc, 0xb7,
- 0xd0, 0x62, 0xf8, 0xe1, 0x6e, 0x11, 0x2c, 0x5d, 0x1c, 0x6a, 0xc5, 0xf0,
- 0xc6, 0xc7, 0x58, 0xbf, 0xd9, 0xe3, 0x67, 0xa6, 0x0d, 0x62, 0xb0, 0xf6,
- 0x48, 0x8e, 0xfe, 0xe1, 0x4f, 0xc5, 0xa5, 0x8b, 0xfb, 0x85, 0x9e, 0xc0,
- 0x2c, 0x50, 0xcf, 0xef, 0xb2, 0x03, 0x97, 0x5f, 0xe2, 0xce, 0x9f, 0xed,
- 0xa3, 0xd6, 0x2f, 0xe0, 0x9e, 0x17, 0x70, 0xe2, 0xc5, 0x44, 0x7d, 0x81,
- 0x9c, 0xdf, 0xde, 0xcf, 0xce, 0x80, 0xb1, 0x7d, 0xa7, 0xce, 0x8b, 0x17,
- 0xec, 0xe6, 0x77, 0xe5, 0x8b, 0xe3, 0xc9, 0x1b, 0xd4, 0xf3, 0x58, 0x92,
- 0xff, 0xb4, 0xe7, 0xe1, 0x93, 0x91, 0x2c, 0x5f, 0xf6, 0xf2, 0x01, 0x89,
- 0xb5, 0x05, 0x8b, 0xff, 0x33, 0x6d, 0x87, 0x62, 0xee, 0x0b, 0x17, 0x98,
- 0xde, 0x61, 0xfd, 0x44, 0x77, 0x7f, 0xbd, 0xfc, 0x39, 0x92, 0x05, 0x8b,
- 0xf0, 0x50, 0xdd, 0x36, 0xeb, 0x17, 0xdc, 0x9c, 0xf2, 0xc5, 0xff, 0x99,
- 0xfd, 0x01, 0x49, 0x4c, 0x16, 0x2f, 0x37, 0x72, 0xb1, 0x6f, 0xf5, 0x47,
- 0x04, 0x6a, 0x35, 0xc2, 0xff, 0x91, 0x18, 0x7b, 0x7f, 0xfa, 0x79, 0x87,
- 0x9d, 0xdb, 0x06, 0xfd, 0x16, 0x2b, 0x11, 0x46, 0x4b, 0x17, 0xec, 0xfe,
- 0x77, 0xe5, 0x8b, 0x07, 0xd5, 0x5b, 0x5e, 0x3d, 0xe8, 0xe8, 0xa1, 0x6b,
- 0xe8, 0xed, 0xe3, 0x88, 0x6b, 0xaa, 0xec, 0x4c, 0xc3, 0xc3, 0x21, 0x38,
- 0xd2, 0xe3, 0xef, 0x9c, 0xd7, 0x0d, 0x62, 0xfb, 0xdf, 0xcd, 0x96, 0x28,
- 0xe7, 0x90, 0x44, 0x97, 0xfd, 0xac, 0xec, 0xbb, 0x7d, 0xb4, 0xb1, 0x4b,
- 0x16, 0x18, 0x0f, 0x20, 0x33, 0xca, 0x58, 0xbe, 0x66, 0x2d, 0xd6, 0x2e,
- 0x19, 0x9b, 0x1a, 0xee, 0x81, 0x95, 0x28, 0xf1, 0xc6, 0x97, 0x57, 0xbc,
- 0x70, 0x69, 0x62, 0xef, 0x12, 0xc5, 0xf8, 0x6d, 0x0f, 0xe2, 0xc5, 0xe2,
- 0x06, 0xeb, 0x14, 0x33, 0xdd, 0xc1, 0x7e, 0x14, 0x5f, 0xfe, 0xef, 0xdf,
- 0x73, 0x07, 0x98, 0x5c, 0x75, 0x8b, 0xff, 0xf4, 0x35, 0x3d, 0x1a, 0x29,
- 0x1f, 0xe4, 0xed, 0x12, 0xc5, 0xfe, 0x08, 0xdc, 0x7e, 0x45, 0x8b, 0x17,
- 0xff, 0xa7, 0x40, 0xce, 0x8f, 0xe9, 0xc2, 0x82, 0xc5, 0x75, 0x4f, 0x36,
- 0x31, 0xef, 0x0b, 0xbb, 0x4b, 0xd2, 0xc9, 0x86, 0xd6, 0xf2, 0xc5, 0xfb,
- 0x39, 0xc3, 0xf6, 0xb1, 0x6e, 0xfa, 0x9b, 0xc9, 0x12, 0xbd, 0x23, 0x95,
- 0x8a, 0x93, 0xc5, 0x39, 0x4d, 0xe7, 0x28, 0x2c, 0x54, 0xba, 0xf8, 0x4d,
- 0x9f, 0x61, 0x4b, 0x65, 0x1b, 0x9e, 0x4a, 0x7c, 0x79, 0x72, 0x71, 0xec,
- 0xf1, 0x24, 0x6a, 0x52, 0xa7, 0xe7, 0xdc, 0x5a, 0x90, 0x20, 0x04, 0x92,
- 0x9d, 0xb4, 0xe4, 0x71, 0x22, 0x8f, 0xe8, 0x38, 0x6f, 0x84, 0x21, 0xbf,
- 0x7c, 0xf3, 0x1a, 0x62, 0xc5, 0xed, 0xf6, 0x65, 0x8b, 0xa4, 0xeb, 0x17,
- 0xf4, 0xfb, 0xf3, 0xd3, 0x16, 0x28, 0x67, 0x8d, 0xb8, 0xbd, 0xdb, 0x62,
- 0xc5, 0xfd, 0x9e, 0xf8, 0x9a, 0x0b, 0x16, 0xdf, 0xaa, 0x33, 0xb1, 0x94,
- 0x04, 0x64, 0x31, 0x4b, 0x16, 0x6d, 0x1e, 0x81, 0xd1, 0x2f, 0xec, 0x3c,
- 0x4c, 0xd0, 0x58, 0xbf, 0xa4, 0xef, 0xbb, 0x8d, 0x62, 0xff, 0xfe, 0x6f,
- 0xcc, 0x23, 0x30, 0x13, 0x0e, 0x0f, 0xf3, 0xa5, 0x8b, 0x38, 0xd1, 0x75,
- 0xb9, 0x77, 0xcb, 0xaf, 0xfc, 0x6c, 0xf6, 0x53, 0xff, 0x8b, 0x75, 0x8b,
- 0xff, 0x4e, 0x16, 0x41, 0xff, 0x9d, 0x16, 0x2f, 0xfe, 0x26, 0x07, 0x35,
- 0x9b, 0xff, 0x3b, 0x58, 0xad, 0x22, 0x13, 0xc7, 0xd7, 0xd9, 0xa7, 0x35,
- 0x62, 0xfd, 0xf7, 0xe4, 0xc1, 0x62, 0xff, 0xf3, 0x1b, 0xcc, 0xe9, 0x3d,
- 0xfb, 0x82, 0x3a, 0xc5, 0x31, 0xfb, 0x91, 0x45, 0x0d, 0x1b, 0xa7, 0x23,
- 0x28, 0x4d, 0x5e, 0x3c, 0x7c, 0xac, 0x5f, 0xee, 0x49, 0x7b, 0xf2, 0x62,
- 0xc5, 0x49, 0xea, 0x78, 0x82, 0xff, 0x8d, 0x7d, 0x19, 0xa7, 0x91, 0xac,
- 0x5c, 0x41, 0x75, 0x8b, 0xe9, 0xfb, 0x9b, 0x87, 0xad, 0xa3, 0xbb, 0xff,
- 0x61, 0xda, 0x11, 0xc2, 0x1b, 0xfd, 0x62, 0xbe, 0x7f, 0x44, 0x71, 0x7e,
- 0xf7, 0x9a, 0x1c, 0x58, 0xbf, 0xc5, 0x3e, 0xee, 0x26, 0x3a, 0xc5, 0xfb,
- 0xc2, 0xf6, 0x0d, 0x62, 0xd8, 0xb1, 0x4c, 0x6e, 0xba, 0x14, 0xdf, 0xe7,
- 0xe6, 0x16, 0xc1, 0xc4, 0xb1, 0x7f, 0xb9, 0x9d, 0x7b, 0x86, 0x79, 0x62,
- 0xef, 0xe0, 0xcf, 0xb7, 0x86, 0xd5, 0x04, 0xdd, 0x46, 0x42, 0x72, 0x92,
- 0x6f, 0xf4, 0x23, 0xef, 0xda, 0x03, 0x60, 0x16, 0x2f, 0xec, 0x08, 0xfe,
- 0x78, 0x2c, 0x5f, 0x7e, 0x76, 0xe6, 0x1e, 0xbf, 0xca, 0x2f, 0x7d, 0xa0,
- 0xb1, 0x7f, 0xc6, 0x6b, 0xd0, 0x72, 0xf7, 0x16, 0x2e, 0x26, 0x34, 0xf6,
- 0x3e, 0x3b, 0x7c, 0xfc, 0x30, 0xeb, 0x17, 0xff, 0xbb, 0xf6, 0xff, 0x72,
- 0xcf, 0x72, 0x4e, 0xb1, 0x7d, 0x3b, 0xbc, 0x16, 0x2f, 0x8e, 0x59, 0xec,
- 0x3e, 0xf2, 0x4c, 0xbf, 0xff, 0x4f, 0xcb, 0x3d, 0xf7, 0xea, 0x7c, 0xf3,
- 0x79, 0x62, 0xe7, 0xe8, 0xb1, 0x5e, 0x3e, 0xf0, 0x8a, 0xd4, 0xb1, 0x7f,
- 0xc5, 0x80, 0xfc, 0xb6, 0xb1, 0x62, 0x9c, 0xf9, 0xf4, 0x49, 0xc0, 0xcb,
- 0xf7, 0xbe, 0xfa, 0x31, 0x62, 0xff, 0x9a, 0x3f, 0x9e, 0x29, 0x30, 0xeb,
- 0x15, 0x87, 0xce, 0x22, 0xaa, 0xdd, 0x52, 0xab, 0xc2, 0x4d, 0xa3, 0x0c,
- 0x28, 0x4a, 0xdf, 0xb7, 0xc3, 0xcf, 0x16, 0x2f, 0x06, 0x18, 0x69, 0x17,
- 0x8c, 0x90, 0x24, 0x46, 0x1a, 0x1b, 0xfd, 0xd1, 0xb0, 0xa1, 0x84, 0xb1,
- 0x7f, 0xcd, 0x03, 0x35, 0x9d, 0x1b, 0x4b, 0x16, 0xd2, 0xc5, 0xfe, 0x29,
- 0x81, 0xba, 0xce, 0x2c, 0x5f, 0xf9, 0xe7, 0x50, 0x35, 0xf8, 0x67, 0xd6,
- 0x2f, 0xfc, 0x45, 0x9b, 0x45, 0x09, 0xd6, 0xcb, 0x17, 0xbf, 0x90, 0x94,
- 0x64, 0x60, 0x91, 0xcd, 0x0c, 0x41, 0xa7, 0x4e, 0x10, 0x8c, 0xfd, 0x18,
- 0x25, 0xff, 0xf1, 0xca, 0x62, 0x86, 0x7f, 0xef, 0x9d, 0x92, 0xc5, 0xff,
- 0xbd, 0x25, 0x9b, 0x3e, 0xb0, 0x6b, 0x17, 0xd3, 0xf6, 0xd2, 0xc5, 0xce,
- 0x3c, 0x3e, 0x0e, 0x1f, 0x5d, 0xc0, 0xd6, 0x2f, 0xf1, 0x41, 0xcf, 0x9d,
- 0xf9, 0x62, 0xfb, 0xbd, 0xdc, 0x96, 0x28, 0x67, 0xe2, 0xc3, 0x3e, 0x34,
- 0xa5, 0x8b, 0x4c, 0x0d, 0xd0, 0x5c, 0xba, 0xb7, 0x4c, 0x04, 0x10, 0xd7,
- 0xbf, 0x75, 0x9d, 0xf3, 0x4b, 0x17, 0xfb, 0x35, 0x8d, 0xbf, 0x20, 0xb1,
- 0x7f, 0xff, 0xcf, 0xef, 0xb4, 0x23, 0x33, 0xed, 0xd8, 0x3c, 0x52, 0x7e,
- 0x2c, 0x5f, 0xfb, 0xac, 0x90, 0x8f, 0x21, 0xcf, 0x16, 0x2d, 0x83, 0x4c,
- 0x28, 0xe5, 0x7f, 0x34, 0x26, 0xab, 0xfe, 0xf3, 0x16, 0x73, 0x53, 0xc5,
- 0x8b, 0xe8, 0x48, 0x3b, 0x58, 0xbf, 0xfd, 0x81, 0xe7, 0x47, 0xe1, 0x61,
- 0xce, 0xeb, 0x17, 0xff, 0xff, 0x7e, 0x48, 0x5c, 0xfb, 0xfb, 0xf8, 0x5e,
- 0xf9, 0x67, 0x4c, 0xe2, 0xc5, 0xc3, 0x1a, 0xc5, 0x41, 0x11, 0x47, 0x72,
- 0xbf, 0xff, 0xcc, 0xfe, 0x98, 0x3e, 0xb6, 0x10, 0x23, 0xa3, 0xb0, 0x6e,
- 0xb1, 0x7f, 0xff, 0xcd, 0xd1, 0xfa, 0x10, 0xb8, 0x61, 0x48, 0xfe, 0xd0,
- 0xce, 0x2c, 0x5f, 0xc0, 0x92, 0xce, 0xfc, 0xb1, 0x73, 0x03, 0xaa, 0xa1,
- 0xbd, 0x89, 0x32, 0x1a, 0xbf, 0x23, 0x26, 0x73, 0x1a, 0xaf, 0xff, 0x18,
- 0x51, 0x1a, 0xc3, 0xfe, 0x6f, 0x9a, 0x58, 0xac, 0x5e, 0x33, 0x78, 0xec,
- 0x7f, 0x19, 0xa3, 0x21, 0x14, 0xa5, 0x3e, 0x35, 0xde, 0xf4, 0x1d, 0x62,
- 0xff, 0xbe, 0x53, 0x0f, 0xb1, 0x3a, 0xc5, 0xd3, 0xa5, 0x8a, 0x73, 0xce,
- 0xe8, 0x6f, 0x7f, 0xef, 0xe6, 0xdd, 0xf3, 0x37, 0x63, 0x16, 0x2e, 0xcf,
- 0xac, 0x53, 0x9e, 0xd0, 0x90, 0xeb, 0x66, 0xce, 0x1e, 0x10, 0xe1, 0x19,
- 0xb6, 0x47, 0x47, 0xdc, 0x22, 0x1e, 0x53, 0x34, 0x50, 0xa6, 0x3c, 0x24,
- 0x7f, 0x2a, 0x09, 0x93, 0x40, 0x94, 0x51, 0xda, 0xfa, 0x79, 0xa0, 0x4d,
- 0x3d, 0x1a, 0xc3, 0x7d, 0xb9, 0xf6, 0x58, 0xbf, 0xc5, 0xb8, 0xdf, 0xa4,
- 0x8d, 0x62, 0x86, 0x79, 0xc2, 0x18, 0xbf, 0xdc, 0x73, 0xb6, 0x9b, 0x8b,
- 0x17, 0xef, 0x7b, 0x0b, 0x65, 0x8b, 0xff, 0xcf, 0xaf, 0xcb, 0xfb, 0x8e,
- 0x5d, 0xc1, 0x62, 0xff, 0xce, 0x1e, 0xb0, 0xe7, 0x62, 0xf2, 0xc5, 0x4a,
- 0x2c, 0xb0, 0xa4, 0x92, 0xaf, 0xec, 0xdf, 0xd1, 0xd9, 0xf5, 0x8a, 0x58,
- 0xaf, 0x9b, 0xe0, 0x19, 0x5f, 0xfd, 0x17, 0xe7, 0x63, 0x3d, 0xf1, 0x34,
- 0x16, 0x2f, 0xdf, 0x9d, 0xf0, 0xeb, 0x14, 0xb1, 0x44, 0x6d, 0x42, 0x14,
- 0xdf, 0x8d, 0x14, 0x18, 0x6b, 0x17, 0xfa, 0x63, 0xfa, 0xfd, 0xb3, 0x4b,
- 0x17, 0xff, 0x78, 0xa7, 0xcf, 0x85, 0xd6, 0x7a, 0x2c, 0x5c, 0xfb, 0xac,
- 0x5e, 0xcd, 0x4a, 0xc5, 0xf7, 0xff, 0x9d, 0xac, 0x5d, 0x87, 0x8e, 0x3c,
- 0x03, 0x07, 0x2b, 0x13, 0x07, 0x73, 0x8f, 0xa3, 0x12, 0xc5, 0xa3, 0xd6,
- 0x2d, 0x12, 0xc5, 0x8e, 0xb1, 0x4e, 0x69, 0x58, 0x4e, 0x8d, 0x3d, 0x93,
- 0x9d, 0x5f, 0xb0, 0x1c, 0x98, 0x2c, 0x5f, 0x9c, 0xe3, 0x1e, 0x2c, 0x58,
- 0x04, 0x7a, 0x11, 0xc5, 0x17, 0xfd, 0xef, 0xe7, 0x3a, 0xf9, 0xf6, 0x58,
- 0xbf, 0xb2, 0x2c, 0xd0, 0xdd, 0x62, 0xa5, 0x12, 0xae, 0x54, 0x47, 0xb7,
- 0xfc, 0x4e, 0x20, 0xbf, 0x23, 0xa7, 0xcb, 0x17, 0xfb, 0x03, 0xee, 0x1e,
- 0x90, 0xd6, 0x2f, 0xec, 0x68, 0xbf, 0x31, 0xeb, 0x15, 0x27, 0xd0, 0x03,
- 0x7b, 0xfc, 0x0d, 0x3e, 0x7c, 0x5c, 0x58, 0xbd, 0x9d, 0x9d, 0x62, 0xfe,
- 0xc0, 0x04, 0xf3, 0x9d, 0x62, 0xa5, 0x10, 0x44, 0x69, 0xe1, 0xeb, 0xe8,
- 0xec, 0xd4, 0xac, 0x5f, 0xbd, 0xe3, 0x5b, 0x4b, 0x16, 0x90, 0x1e, 0x79,
- 0x12, 0xdf, 0xfc, 0xde, 0xd0, 0x8d, 0xcf, 0x38, 0x38, 0xb1, 0x79, 0xb4,
- 0x05, 0x8b, 0xd8, 0xe3, 0x58, 0xa9, 0x5f, 0x78, 0xda, 0x1c, 0xb0, 0x6b,
- 0x19, 0x0e, 0x3f, 0x39, 0x14, 0x51, 0x98, 0x9e, 0x12, 0x9f, 0x8c, 0x20,
- 0x8b, 0x79, 0x0a, 0x8f, 0x42, 0x8f, 0xa3, 0xe8, 0x64, 0xd1, 0xc8, 0xc1,
- 0x07, 0x6f, 0xbf, 0x9d, 0xc1, 0x62, 0xfb, 0x3c, 0x66, 0xcb, 0x17, 0xe2,
- 0x97, 0xee, 0x0b, 0x17, 0x83, 0x0c, 0x34, 0xc4, 0x20, 0x2f, 0xb7, 0x66,
- 0xdd, 0x31, 0x08, 0x08, 0xc3, 0x5f, 0x7f, 0xa7, 0x6e, 0xe0, 0x26, 0xf2,
- 0xc5, 0xf3, 0x6b, 0x03, 0x58, 0xad, 0x22, 0x7b, 0x88, 0xbd, 0x0d, 0xaf,
- 0x06, 0x18, 0x69, 0x88, 0x3c, 0x52, 0x62, 0x0f, 0x11, 0x86, 0xbe, 0xfe,
- 0xf3, 0x1c, 0xf2, 0x75, 0x8b, 0xf3, 0x79, 0x88, 0x0b, 0x17, 0xf6, 0x7b,
- 0xe2, 0x68, 0x2c, 0x5e, 0x0c, 0x30, 0xd6, 0x2f, 0x72, 0x4d, 0x48, 0x8c,
- 0x34, 0x37, 0xe9, 0x0f, 0x3e, 0xcb, 0x15, 0x2a, 0xa0, 0x32, 0x1e, 0xbb,
- 0xb0, 0xf6, 0x5b, 0xf2, 0xe2, 0x27, 0xf2, 0x79, 0x86, 0x35, 0x1e, 0xac,
- 0x74, 0xf2, 0xa9, 0x6f, 0xf7, 0xe7, 0xa4, 0x94, 0xf9, 0x62, 0xfe, 0xce,
- 0xe1, 0x09, 0x3a, 0xc5, 0xff, 0xee, 0x7d, 0xa1, 0x9f, 0x73, 0xf2, 0x63,
- 0xd6, 0x2f, 0x07, 0x24, 0xb1, 0x7f, 0x6f, 0xf9, 0xd6, 0x1d, 0x62, 0xff,
- 0xfe, 0xfb, 0x1c, 0xed, 0x03, 0x0b, 0xa6, 0x0f, 0x3b, 0xf2, 0xc5, 0xe9,
- 0x2d, 0xb1, 0x11, 0xdc, 0x2f, 0xbf, 0xfb, 0xf3, 0x07, 0xf6, 0x7f, 0x79,
- 0x3a, 0xc5, 0x4a, 0xa0, 0x28, 0x17, 0x8c, 0xd3, 0x0b, 0xd9, 0x37, 0x90,
- 0xab, 0xe8, 0x67, 0x7e, 0xde, 0x7f, 0x27, 0x58, 0xbf, 0xf7, 0xde, 0x22,
- 0x60, 0xfd, 0x9f, 0x58, 0xba, 0x78, 0xb1, 0x58, 0x88, 0x0d, 0xca, 0x7c,
- 0x81, 0x7f, 0xef, 0xb8, 0xe4, 0xbd, 0x9d, 0xf9, 0x62, 0xf7, 0x04, 0x4b,
- 0x17, 0xd0, 0x29, 0x1a, 0xc5, 0xe2, 0x93, 0xf0, 0xdf, 0x98, 0x3b, 0x7f,
- 0x84, 0xdc, 0x88, 0xa4, 0xeb, 0x15, 0xba, 0x39, 0x38, 0xfd, 0xe3, 0x2b,
- 0xff, 0xbe, 0xfa, 0xfb, 0x67, 0x1d, 0xb6, 0x58, 0xbf, 0xc1, 0xb7, 0xb0,
- 0xed, 0xda, 0xc5, 0xff, 0xa7, 0xd9, 0xac, 0xe6, 0x77, 0xe5, 0x8a, 0xc4,
- 0x5c, 0x7d, 0x10, 0x8d, 0x6f, 0xf8, 0xf8, 0x7c, 0x2f, 0x66, 0xeb, 0x17,
- 0xf8, 0xdc, 0xde, 0x7f, 0x27, 0x58, 0xad, 0x8f, 0xb9, 0x8e, 0x6f, 0xa7,
- 0xd2, 0x75, 0x8b, 0xf8, 0x9c, 0xde, 0xbb, 0xfd, 0x62, 0xf1, 0x9f, 0x65,
- 0x8a, 0xc3, 0xd0, 0x8e, 0x32, 0xa8, 0xd9, 0x5a, 0x8f, 0x71, 0x8a, 0x1e,
- 0x1d, 0x25, 0x09, 0xcf, 0x11, 0x06, 0xe5, 0x76, 0xb1, 0x62, 0xf7, 0xe4,
- 0x22, 0xc5, 0xfe, 0x92, 0xdf, 0xbe, 0x34, 0x7a, 0xc5, 0x75, 0x3e, 0xe1,
- 0x8b, 0xfc, 0x7e, 0xff, 0xe6, 0xe9, 0x9f, 0xcd, 0x14, 0xf7, 0x05, 0x8b,
- 0xa7, 0x65, 0x8a, 0xf9, 0xef, 0x04, 0x46, 0xbe, 0x21, 0x6c, 0x4b, 0x17,
- 0xe6, 0xe0, 0xdb, 0x75, 0x8b, 0xcf, 0xdc, 0x16, 0x2a, 0x07, 0xd4, 0x69,
- 0x18, 0x0a, 0x6f, 0xe1, 0xf3, 0x0f, 0x31, 0xeb, 0x17, 0xff, 0x70, 0x45,
- 0xac, 0x9e, 0xe1, 0x24, 0xb1, 0x7d, 0x83, 0x68, 0x2c, 0x5e, 0x13, 0x18,
- 0xb1, 0x7f, 0xb3, 0xed, 0xcf, 0xcf, 0x16, 0x2e, 0xdb, 0xb5, 0x8a, 0x19,
- 0xf5, 0xf6, 0x3c, 0x03, 0x3a, 0xea, 0x8b, 0xd6, 0x84, 0x6d, 0x41, 0x55,
- 0x40, 0xe1, 0x1f, 0xdc, 0x23, 0x98, 0xc3, 0x86, 0x21, 0xc6, 0x03, 0x7f,
- 0xb9, 0xfc, 0xe7, 0xb3, 0x75, 0x8b, 0xf1, 0x7b, 0xf9, 0x05, 0x8b, 0xcf,
- 0x26, 0xac, 0x53, 0x9f, 0xd3, 0x1a, 0x91, 0x45, 0xff, 0x61, 0x4f, 0xff,
- 0x21, 0xba, 0xc5, 0xf6, 0xff, 0x70, 0xd6, 0x2e, 0x09, 0xa5, 0x8b, 0xc6,
- 0x48, 0x16, 0x2f, 0xfb, 0x70, 0xf3, 0xbf, 0x7a, 0x4e, 0xb1, 0x7f, 0xff,
- 0xff, 0xdd, 0x4b, 0x0d, 0x7f, 0xff, 0x23, 0xfa, 0xce, 0xec, 0x67, 0x5c,
- 0x2d, 0x9f, 0x4e, 0x20, 0xbe, 0x2c, 0x56, 0xc9, 0xd0, 0x1a, 0x59, 0xd9,
- 0xc4, 0x44, 0xa7, 0x1a, 0x21, 0xe0, 0xcf, 0x6f, 0xff, 0xf4, 0xf5, 0xf4,
- 0x76, 0x75, 0xcf, 0xb1, 0x64, 0x50, 0x9e, 0xd6, 0x2f, 0xe2, 0x17, 0xb4,
- 0x28, 0x2c, 0x5f, 0xb7, 0x9f, 0xc9, 0xd2, 0x2f, 0xc4, 0xc4, 0x58, 0x91,
- 0x76, 0x6e, 0x91, 0x70, 0x61, 0xa4, 0x56, 0x22, 0x03, 0x85, 0x3e, 0x25,
- 0x0c, 0x62, 0xfd, 0x20, 0xfe, 0x04, 0x48, 0x8c, 0x37, 0xb6, 0x21, 0xa7,
- 0x23, 0x8d, 0x06, 0x43, 0xb2, 0xff, 0xe1, 0xe9, 0xb7, 0x2c, 0xe9, 0xa7,
- 0xe2, 0xc5, 0xed, 0x9f, 0x4b, 0x15, 0xb1, 0xf2, 0xfd, 0x1e, 0xa5, 0x91,
- 0x8d, 0x92, 0xe1, 0x5e, 0x54, 0x23, 0x47, 0xf4, 0x28, 0x50, 0x5c, 0x66,
- 0x96, 0x2e, 0x6f, 0xac, 0x53, 0x1b, 0x0f, 0x0c, 0xdf, 0xfd, 0xf9, 0x07,
- 0xbf, 0x90, 0xfb, 0xf4, 0x58, 0xbf, 0xfa, 0x41, 0xcc, 0xc1, 0xb1, 0x31,
- 0xab, 0x17, 0xfd, 0xee, 0x37, 0x6f, 0x3d, 0xf9, 0x62, 0xff, 0x88, 0x1f,
- 0x6f, 0x79, 0xc0, 0xb1, 0x7f, 0xfe, 0xfb, 0xf4, 0x72, 0x1f, 0x27, 0x4f,
- 0x9d, 0xf1, 0x62, 0xff, 0x67, 0x49, 0x2f, 0x40, 0x2e, 0xb1, 0x7f, 0xb7,
- 0x7e, 0x60, 0xe0, 0x17, 0x58, 0xbc, 0x31, 0x71, 0x62, 0xff, 0x66, 0x14,
- 0xc2, 0x01, 0x75, 0x8b, 0xf8, 0xa7, 0x34, 0xc0, 0x58, 0xbf, 0xf4, 0xeb,
- 0xf2, 0xff, 0x92, 0x75, 0x8b, 0xa1, 0xcc, 0x4e, 0xfb, 0x73, 0x9d, 0x2b,
- 0xfc, 0xe5, 0x8e, 0x48, 0x7b, 0xc6, 0xc1, 0x96, 0x5f, 0xc5, 0x87, 0x7e,
- 0xe0, 0xb1, 0x7f, 0xf9, 0x9f, 0xd2, 0x5b, 0xb9, 0xf8, 0x3e, 0xd6, 0x2a,
- 0x4f, 0xe7, 0xe5, 0xd7, 0xfb, 0xf3, 0x90, 0x9c, 0x02, 0xc5, 0xff, 0xe2,
- 0xce, 0xc0, 0xdc, 0x6d, 0x3f, 0x60, 0x58, 0xa1, 0x9f, 0xef, 0x0c, 0xaa,
- 0x0a, 0xeb, 0xfb, 0x8f, 0xe7, 0xd0, 0xf6, 0x0e, 0x13, 0xd7, 0xd3, 0xbe,
- 0x1d, 0x62, 0xf8, 0xe2, 0x28, 0x2c, 0x5f, 0x34, 0x52, 0x11, 0x62, 0xe9,
- 0x3a, 0xc5, 0xef, 0xb4, 0x36, 0x3d, 0xff, 0x91, 0x91, 0x2d, 0x0d, 0x18,
- 0x5e, 0x84, 0x15, 0xce, 0x1a, 0xc5, 0xfb, 0xe7, 0x9c, 0xf2, 0xc5, 0xc2,
- 0xe2, 0xc5, 0x61, 0xe0, 0x70, 0xa2, 0xf0, 0xb0, 0x6b, 0x14, 0x48, 0x96,
- 0xf2, 0xc4, 0x71, 0x0d, 0x41, 0x78, 0xf3, 0xe8, 0xed, 0x2f, 0xc8, 0xa3,
- 0x13, 0xe4, 0x2f, 0xaf, 0x74, 0x30, 0xeb, 0x17, 0xdf, 0xdb, 0x03, 0x58,
- 0xbe, 0x18, 0x8a, 0x0b, 0x16, 0xe3, 0x1e, 0x41, 0x84, 0xb7, 0xb1, 0x80,
- 0xb1, 0x79, 0x8f, 0xda, 0xc5, 0xb7, 0x19, 0xba, 0xc1, 0xcb, 0x46, 0xb5,
- 0x8b, 0xc5, 0x30, 0x58, 0xbf, 0xf6, 0x73, 0xd0, 0xc3, 0x4b, 0x00, 0xb1,
- 0x78, 0x78, 0x4b, 0x14, 0x15, 0x44, 0x78, 0xc6, 0x18, 0x70, 0x21, 0xfd,
- 0x3a, 0x3e, 0x05, 0x0b, 0x6b, 0xe7, 0xf9, 0xd9, 0x62, 0xff, 0xc1, 0x8f,
- 0x53, 0xf6, 0x1c, 0x0e, 0xb1, 0x7f, 0xff, 0xff, 0x68, 0x13, 0xee, 0x75,
- 0xf4, 0x30, 0x11, 0xd9, 0xd4, 0x78, 0x39, 0x6d, 0x61, 0x01, 0x04, 0x17,
- 0xff, 0xff, 0xff, 0xff, 0xfc, 0xf2, 0x76, 0x1e, 0xc2, 0xe7, 0x5c, 0x18,
- 0xb5, 0x0f, 0xbf, 0x5c, 0xd0, 0x27, 0xdc, 0xeb, 0xe8, 0x60, 0x23, 0xb3,
- 0xa8, 0xf0, 0x72, 0xda, 0xc2, 0x02, 0x0c, 0x2f, 0xff, 0xb9, 0xdf, 0x51,
- 0xe0, 0xe5, 0xb5, 0x84, 0x05, 0x8a, 0xfa, 0x6a, 0x3e, 0x87, 0xfd, 0xff,
- 0xff, 0xba, 0xfa, 0x18, 0x08, 0xec, 0xea, 0x3c, 0x1c, 0xb6, 0xb0, 0x80,
- 0x84, 0x17, 0xff, 0x67, 0xba, 0xef, 0xf7, 0xff, 0xdc, 0x0a, 0x84, 0x2c,
- 0xa8, 0x23, 0x2f, 0x8e, 0xd7, 0xa7, 0x68, 0xcc, 0x55, 0xf9, 0xc8, 0xf9,
- 0x7d, 0x0f, 0x4b, 0xc0, 0x9e, 0xd6, 0x2e, 0x6f, 0x2c, 0x5e, 0x2c, 0x08,
- 0xb1, 0x7d, 0x9b, 0xb6, 0xeb, 0x17, 0xe3, 0xf0, 0x36, 0xed, 0x62, 0x86,
- 0x8f, 0x37, 0x51, 0x38, 0xf3, 0x0b, 0xf8, 0x78, 0xc2, 0x4a, 0x95, 0xca,
- 0x8e, 0xc8, 0xb9, 0x38, 0x61, 0x7f, 0x64, 0x50, 0x7d, 0x71, 0x62, 0xfd,
- 0xb4, 0xf9, 0xe2, 0x58, 0xbe, 0x33, 0x93, 0x8b, 0x17, 0xe3, 0x02, 0x49,
- 0x41, 0x62, 0xb7, 0x3f, 0x8e, 0xca, 0x80, 0x47, 0x7f, 0xff, 0xbf, 0x3e,
- 0xe3, 0xfd, 0xf4, 0x59, 0xb7, 0x5c, 0x93, 0xac, 0x5f, 0x73, 0xae, 0xb1,
- 0x62, 0xfb, 0xfb, 0xbf, 0x16, 0x2a, 0x51, 0xb9, 0xb1, 0x8b, 0x31, 0x78,
- 0x96, 0xff, 0xff, 0x8c, 0x1f, 0xe6, 0x1e, 0xcc, 0x0f, 0x85, 0x9e, 0xf3,
- 0xec, 0xb1, 0x7f, 0xc3, 0x76, 0xe9, 0x3d, 0x1b, 0xeb, 0x17, 0x37, 0x6b,
- 0x16, 0xc5, 0x8b, 0x36, 0xc8, 0xce, 0xed, 0xa5, 0x8f, 0x3a, 0x0c, 0x5e,
- 0x72, 0xc5, 0x8b, 0xf6, 0xb4, 0xc0, 0x95, 0x8a, 0x81, 0xe1, 0xb0, 0xdd,
- 0x05, 0x5f, 0x09, 0x96, 0x6b, 0x4d, 0x21, 0xc6, 0xc9, 0x93, 0xf3, 0x5b,
- 0xc6, 0x04, 0xf3, 0xa8, 0x7a, 0xa6, 0x80, 0xfe, 0x12, 0x6d, 0x3c, 0xb8,
- 0x05, 0xd0, 0xbb, 0x49, 0x46, 0xb5, 0xc9, 0xcc, 0xff, 0x1d, 0x8a, 0x38,
- 0x30, 0xe3, 0x0a, 0x32, 0x11, 0x17, 0x46, 0xf1, 0xa2, 0xc5, 0xf6, 0x03,
- 0x52, 0xb1, 0x78, 0x30, 0xc3, 0x48, 0xbc, 0xc4, 0x34, 0x88, 0xc3, 0x43,
- 0x7d, 0x9a, 0xcf, 0x2c, 0x57, 0xd1, 0x28, 0x04, 0x3e, 0x17, 0xdf, 0xfc,
- 0x6b, 0x18, 0x52, 0xe3, 0xce, 0xfc, 0xb1, 0x78, 0x41, 0x7c, 0x58, 0xbc,
- 0xed, 0x05, 0x8b, 0xff, 0xd9, 0xef, 0x31, 0x1a, 0xde, 0x26, 0x02, 0xc5,
- 0x4a, 0x33, 0x1d, 0x1b, 0xe4, 0x24, 0x39, 0x7f, 0x8b, 0x3f, 0xe2, 0x90,
- 0x2c, 0x5f, 0xfe, 0x83, 0x96, 0x7a, 0x43, 0x1e, 0x9a, 0x0b, 0x17, 0xff,
- 0xf3, 0xc5, 0xce, 0x09, 0xb4, 0x2d, 0xa4, 0xd3, 0x0b, 0xcb, 0x17, 0xfe,
- 0x2c, 0xda, 0x7b, 0x84, 0x24, 0xeb, 0x17, 0xff, 0xe1, 0x4e, 0x6d, 0xa9,
- 0x78, 0x49, 0xa1, 0xe7, 0xd6, 0x28, 0x91, 0x2f, 0xe4, 0x0a, 0xc4, 0xd8,
- 0xfe, 0x94, 0x64, 0x3d, 0xef, 0x14, 0xc1, 0x62, 0xfb, 0x5a, 0x73, 0xac,
- 0x5b, 0x83, 0x37, 0xee, 0x39, 0x50, 0x44, 0xdf, 0x9d, 0x6e, 0xd8, 0x6b,
- 0x17, 0xff, 0xef, 0x4e, 0x6c, 0xde, 0xdf, 0xed, 0xa0, 0xdb, 0xb5, 0x8a,
- 0x39, 0xf9, 0x70, 0x66, 0xb6, 0x55, 0xce, 0x52, 0x8c, 0x3d, 0x09, 0x5b,
- 0xf6, 0xb3, 0x79, 0xfa, 0xc5, 0xff, 0x8b, 0x7f, 0x7b, 0x08, 0xa6, 0x3d,
- 0x62, 0xff, 0xf7, 0xdf, 0x5a, 0x7d, 0xb9, 0x87, 0x98, 0xf5, 0x8a, 0x94,
- 0x47, 0xee, 0x83, 0x7b, 0xa9, 0xb1, 0xcb, 0x17, 0xbc, 0xc3, 0x58, 0xad,
- 0x1e, 0x0f, 0x09, 0x2f, 0xed, 0xff, 0x25, 0x91, 0x2c, 0x5e, 0x83, 0x84,
- 0x58, 0xa9, 0x3c, 0xe8, 0x8b, 0xef, 0xf1, 0xbd, 0xfb, 0x53, 0x9d, 0xac,
- 0x5f, 0x01, 0xf4, 0x6a, 0x45, 0xfe, 0x96, 0xd7, 0xc3, 0x61, 0xac, 0x5f,
- 0x6b, 0x4f, 0xb2, 0xc5, 0xb7, 0x93, 0xfc, 0x19, 0x23, 0x1a, 0x5f, 0xb5,
- 0xfc, 0x38, 0x96, 0x2f, 0xd9, 0xac, 0xc8, 0x96, 0x29, 0xcf, 0x44, 0xc2,
- 0x9b, 0xf3, 0x7f, 0xa8, 0xe5, 0x62, 0xa0, 0xbf, 0x1a, 0x38, 0x7e, 0x64,
- 0xb2, 0x13, 0x4f, 0xbb, 0x85, 0xc3, 0xb2, 0x69, 0xc1, 0x88, 0x8a, 0x16,
- 0x7c, 0x84, 0x2f, 0x88, 0xaf, 0xcd, 0xad, 0x67, 0x6b, 0x17, 0xff, 0xbd,
- 0xf7, 0x60, 0x66, 0x87, 0x25, 0x05, 0x8b, 0xff, 0xdd, 0xf5, 0xec, 0x12,
- 0x5b, 0xb6, 0xc4, 0xcb, 0x15, 0x28, 0xc1, 0xc2, 0x92, 0x49, 0xbf, 0x4f,
- 0x0c, 0x28, 0x2c, 0x5e, 0xdd, 0xe0, 0xb1, 0x7f, 0xa7, 0xcd, 0xad, 0x67,
- 0x6b, 0x15, 0xd4, 0xf4, 0xbe, 0x3d, 0x7f, 0xed, 0xf3, 0x58, 0xfc, 0xfc,
- 0xf4, 0x58, 0xbf, 0xf3, 0x76, 0xc3, 0x6e, 0xf4, 0xe6, 0xac, 0x5f, 0xa4,
- 0x26, 0xd8, 0x1a, 0xc5, 0xff, 0xcd, 0x9d, 0xfb, 0x08, 0x50, 0xce, 0x2c,
- 0x5f, 0xff, 0xfc, 0xcf, 0xe7, 0xfe, 0xef, 0xd6, 0x0f, 0xf6, 0x2f, 0x43,
- 0x35, 0x8b, 0x17, 0x67, 0xd6, 0x2e, 0xc0, 0x8b, 0x15, 0x11, 0xb0, 0xf8,
- 0xbd, 0x7d, 0x18, 0x8d, 0x0a, 0x2b, 0xf3, 0x81, 0x88, 0x0b, 0x17, 0xfa,
- 0x7b, 0xe4, 0xfa, 0x46, 0xb1, 0x40, 0x3d, 0xb2, 0x27, 0xbf, 0x67, 0x33,
- 0xbf, 0x2c, 0x5f, 0xff, 0x7f, 0x1f, 0x50, 0xfb, 0x8b, 0x7f, 0xe0, 0x16,
- 0x2f, 0x70, 0xce, 0x75, 0x4c, 0x77, 0x21, 0x04, 0xc4, 0x3e, 0x29, 0xa1,
- 0xab, 0x4d, 0xec, 0x90, 0xe8, 0x3f, 0x41, 0x22, 0xcf, 0x4a, 0x25, 0xbb,
- 0x90, 0x58, 0xbd, 0xb0, 0xb8, 0xb1, 0x74, 0xc4, 0xb1, 0x7f, 0x9c, 0x9b,
- 0xdf, 0xc3, 0xac, 0x53, 0x1f, 0x49, 0x0f, 0xf8, 0x62, 0xfe, 0x83, 0xf9,
- 0xca, 0x0b, 0x17, 0xf7, 0x1d, 0xf6, 0x7f, 0xac, 0x5b, 0x52, 0x7b, 0x70,
- 0x2d, 0xbf, 0x44, 0x53, 0xee, 0x2c, 0x5f, 0xff, 0xff, 0xf4, 0xf2, 0x7d,
- 0xb6, 0x07, 0xac, 0xfb, 0x19, 0xcc, 0x35, 0x88, 0x12, 0x53, 0x17, 0xe5,
- 0x62, 0xf8, 0x4d, 0x9b, 0x2c, 0x5e, 0x3e, 0x6c, 0xb1, 0x7a, 0x0f, 0xd0,
- 0x8f, 0x04, 0xc2, 0x3b, 0xf7, 0x3e, 0xdb, 0xca, 0xc5, 0xf9, 0xb6, 0x0d,
- 0xa0, 0xb1, 0x52, 0x9d, 0x76, 0xc4, 0xe4, 0x53, 0xe8, 0x6b, 0x06, 0x6a,
- 0x61, 0x4d, 0xfd, 0xdf, 0x30, 0xef, 0xf5, 0x8b, 0xfe, 0xe7, 0xe5, 0xb5,
- 0xac, 0xed, 0x62, 0xfa, 0x4e, 0xdf, 0x58, 0xbf, 0xff, 0xd0, 0xf6, 0x17,
- 0xb9, 0xd7, 0x9c, 0xcd, 0x61, 0x34, 0x16, 0x2c, 0x6f, 0x54, 0x42, 0x76,
- 0x45, 0x58, 0x8e, 0xb7, 0x85, 0xf5, 0xf0, 0x3d, 0x9b, 0x2c, 0x58, 0xeb,
- 0x15, 0x26, 0xd8, 0xe4, 0x97, 0xff, 0xf8, 0x02, 0x62, 0xdc, 0x39, 0xd1,
- 0x67, 0x70, 0xf4, 0xf6, 0xb1, 0x7f, 0xf4, 0x60, 0xca, 0x45, 0xbe, 0x1a,
- 0xfa, 0x58, 0xbd, 0xa6, 0xe2, 0xc5, 0xd8, 0x1a, 0xc5, 0x49, 0xff, 0x0d,
- 0x27, 0x83, 0xb7, 0xd2, 0xda, 0xe2, 0xc5, 0xef, 0x7e, 0x56, 0x2b, 0x0f,
- 0xb7, 0xe5, 0xcc, 0x45, 0x7e, 0xfc, 0x93, 0x7d, 0x62, 0xfe, 0x29, 0x8b,
- 0x33, 0x75, 0x8b, 0xfb, 0x6f, 0xb7, 0xb5, 0x2b, 0x17, 0xd9, 0xe9, 0xfa,
- 0xc5, 0xe8, 0x67, 0x16, 0x2f, 0x4f, 0x7c, 0x58, 0xbf, 0xc3, 0xfc, 0xc4,
- 0xcd, 0xda, 0xc5, 0xe7, 0xf7, 0x16, 0x2f, 0xb8, 0x22, 0x82, 0xc5, 0xf8,
- 0x9b, 0xd0, 0x95, 0x8b, 0xfc, 0x7e, 0xe1, 0xec, 0x8b, 0x8b, 0x15, 0xba,
- 0x27, 0xbb, 0x1d, 0xe1, 0x19, 0x84, 0xf7, 0xbe, 0x0e, 0x8b, 0x15, 0xb2,
- 0x6d, 0xc3, 0x1d, 0xd0, 0xf1, 0x43, 0x4c, 0x22, 0x05, 0xee, 0xda, 0x3d,
- 0x62, 0xff, 0x7b, 0xec, 0x7d, 0x66, 0xcb, 0x15, 0xf3, 0xd6, 0x01, 0x0d,
- 0xe8, 0xe7, 0x35, 0x62, 0xfe, 0xf4, 0xf4, 0x26, 0xed, 0x62, 0x96, 0x2a,
- 0x4f, 0x77, 0xb2, 0x18, 0xe3, 0x0a, 0x82, 0xb9, 0xa1, 0x96, 0xb9, 0x3e,
- 0x8b, 0xbe, 0x5e, 0xd1, 0xc8, 0x14, 0x2a, 0x3c, 0xff, 0x7a, 0x26, 0x02,
- 0xc5, 0xf8, 0x44, 0x36, 0xd9, 0x62, 0xff, 0xfb, 0xee, 0xc0, 0xc2, 0x9e,
- 0xf9, 0x9d, 0xf9, 0x62, 0xc6, 0xe2, 0x25, 0xce, 0x3d, 0xe2, 0x9b, 0xff,
- 0xb3, 0x40, 0x3b, 0xf0, 0xce, 0x4e, 0x2c, 0x5e, 0x9e, 0xe3, 0xd6, 0x2f,
- 0xb8, 0x4e, 0x6a, 0xc5, 0x68, 0xf1, 0x3c, 0x43, 0x7d, 0x83, 0x68, 0x2c,
- 0x50, 0xcf, 0x10, 0xd2, 0x2b, 0xf9, 0xa1, 0xee, 0x49, 0xab, 0x17, 0xe9,
- 0x76, 0xf7, 0x16, 0x2f, 0xa0, 0xfd, 0xc1, 0x62, 0xe9, 0xd7, 0xcf, 0x2d,
- 0x89, 0xec, 0x6f, 0xd1, 0x4c, 0x1b, 0xd5, 0xff, 0xe2, 0xea, 0xf2, 0x3f,
- 0xe1, 0xff, 0x9c, 0x58, 0xbe, 0x39, 0x4c, 0x4b, 0x17, 0xff, 0xdf, 0x78,
- 0x3e, 0x98, 0x1e, 0x29, 0x3f, 0x16, 0x2f, 0x4e, 0x81, 0x27, 0xe5, 0xb9,
- 0x1d, 0x62, 0x3c, 0x3d, 0x0b, 0xdb, 0xa3, 0xf8, 0xb1, 0x7f, 0xdc, 0xdf,
- 0xec, 0x38, 0xdc, 0x2b, 0x1b, 0x2c, 0x51, 0xa8, 0x8c, 0x62, 0x7f, 0x0d,
- 0xd4, 0xab, 0xa3, 0x81, 0xb6, 0x43, 0x35, 0xe1, 0x92, 0xd1, 0xd3, 0xdc,
- 0x40, 0x58, 0xbf, 0xbb, 0x86, 0x1e, 0x77, 0x58, 0xbf, 0xd3, 0xf6, 0x7f,
- 0x49, 0x2c, 0x5f, 0xf9, 0xca, 0x7c, 0xfa, 0x7f, 0x09, 0x62, 0xff, 0x3f,
- 0x9f, 0x4d, 0xb4, 0xac, 0x54, 0x9f, 0x83, 0x1e, 0xde, 0x66, 0xed, 0x62,
- 0xb4, 0x8d, 0xef, 0xc2, 0x87, 0xa1, 0x05, 0x05, 0x13, 0x5c, 0x91, 0x77,
- 0x8c, 0x3a, 0xf1, 0xc5, 0xc5, 0x8b, 0xe7, 0x3e, 0x12, 0xc5, 0xa5, 0x8d,
- 0xff, 0x87, 0xaf, 0xf3, 0xf8, 0xcd, 0x4f, 0xe5, 0x62, 0xfd, 0x26, 0x13,
- 0x41, 0x62, 0xff, 0xf6, 0x98, 0xbd, 0x80, 0x8e, 0x91, 0x8e, 0x56, 0x2f,
- 0xfe, 0x29, 0x00, 0xc5, 0x3b, 0x4f, 0x70, 0x58, 0xbf, 0xa1, 0xa9, 0x83,
- 0x69, 0x62, 0xfd, 0xee, 0x05, 0x4d, 0xf2, 0xc5, 0x8e, 0xb1, 0x52, 0x78,
- 0x38, 0x5f, 0x7b, 0xd2, 0x1a, 0xc5, 0xef, 0x99, 0xa5, 0x8a, 0x81, 0xbd,
- 0xf0, 0xf5, 0xef, 0x60, 0xd6, 0x2f, 0xf8, 0x5a, 0x35, 0x9f, 0x8f, 0xd1,
- 0x62, 0xfd, 0xa0, 0x1d, 0xf8, 0xb1, 0x70, 0x3a, 0xc7, 0x1f, 0x29, 0x87,
- 0x96, 0xce, 0xd1, 0x6c, 0x50, 0x82, 0xbe, 0x6d, 0xcb, 0x16, 0x2f, 0xe7,
- 0xfb, 0xe7, 0x7e, 0x58, 0xa1, 0xa7, 0x63, 0xda, 0xe9, 0xe1, 0xae, 0x45,
- 0xbe, 0x22, 0xa5, 0x8b, 0xdd, 0x33, 0x4b, 0x17, 0xbd, 0x80, 0x58, 0xbf,
- 0xb9, 0x31, 0x40, 0x43, 0x58, 0xac, 0x3e, 0xc0, 0x0f, 0x98, 0x3b, 0x7d,
- 0xce, 0x3f, 0x45, 0x8b, 0xff, 0xf6, 0x11, 0xad, 0xcf, 0xb3, 0x80, 0xf3,
- 0xdc, 0x16, 0x2a, 0x4f, 0xef, 0x72, 0x5b, 0xf0, 0x82, 0xfa, 0x7e, 0x2c,
- 0x5f, 0xff, 0xf8, 0x46, 0xf7, 0xe1, 0x31, 0x86, 0x6b, 0x82, 0x6d, 0x0b,
- 0x69, 0x35, 0x62, 0xf3, 0xc5, 0xcc, 0x45, 0x16, 0x8b, 0x6f, 0xff, 0xb3,
- 0x51, 0x7d, 0xc8, 0x36, 0xf9, 0x85, 0xe5, 0x8b, 0x8c, 0xcf, 0xa2, 0x1b,
- 0x86, 0x97, 0xfe, 0xfb, 0xf7, 0xcc, 0x23, 0x70, 0x96, 0x2f, 0xff, 0xe7,
- 0x8b, 0x9c, 0x13, 0x68, 0x5b, 0x49, 0xa6, 0x17, 0x96, 0x2d, 0xcc, 0x46,
- 0x76, 0xe5, 0xff, 0x3f, 0xbe, 0x39, 0x14, 0xac, 0x5f, 0xf3, 0x8f, 0xf3,
- 0x0c, 0xef, 0xcb, 0x17, 0xfd, 0xbc, 0xf4, 0x9e, 0x38, 0x3b, 0x58, 0xb1,
- 0xb2, 0x89, 0x81, 0x90, 0xe1, 0xd5, 0x62, 0x60, 0x6d, 0x0c, 0xeb, 0xf7,
- 0x9b, 0xc2, 0x95, 0x8b, 0xfb, 0xf2, 0x20, 0xbf, 0x51, 0xac, 0x5f, 0xff,
- 0xdf, 0x7f, 0x7d, 0xa0, 0x60, 0xdb, 0x61, 0xfd, 0xce, 0xb1, 0x7f, 0xe7,
- 0xf4, 0x30, 0x1c, 0x2c, 0x02, 0xc5, 0x41, 0x91, 0x76, 0x33, 0x4c, 0x28,
- 0x35, 0x33, 0xb4, 0x67, 0x94, 0x41, 0x12, 0x86, 0x9e, 0x3f, 0x0a, 0xa2,
- 0x96, 0x37, 0xc2, 0x7f, 0x14, 0x08, 0xd7, 0xa2, 0xf5, 0xe0, 0x4f, 0x6b,
- 0x17, 0x4f, 0x6b, 0x14, 0xe6, 0xd8, 0x03, 0xd7, 0xa3, 0xbb, 0x95, 0x8b,
- 0xfd, 0xf2, 0x9e, 0xde, 0x7e, 0xb1, 0x7f, 0x37, 0x80, 0x61, 0x41, 0x62,
- 0xb7, 0x3e, 0x2f, 0x99, 0xd4, 0x6e, 0xea, 0x4d, 0xa6, 0x90, 0x87, 0x08,
- 0xdd, 0x46, 0x5b, 0x92, 0xf2, 0x0d, 0x60, 0xee, 0x10, 0x2f, 0x28, 0xda,
- 0x3d, 0x7b, 0x51, 0x8d, 0x1d, 0x73, 0xe4, 0x0d, 0x39, 0xd2, 0x53, 0x96,
- 0xbc, 0x8e, 0xd3, 0xcf, 0x02, 0xa4, 0x70, 0x74, 0x8c, 0x3a, 0x38, 0x80,
- 0xc8, 0x41, 0xdf, 0xf9, 0x9c, 0x62, 0xf7, 0x36, 0xc0, 0xd6, 0x2e, 0x0a,
- 0x12, 0xc5, 0xfb, 0x98, 0x6c, 0xf1, 0x62, 0xfd, 0x1d, 0x84, 0xc6, 0xac,
- 0x5f, 0xbb, 0x3b, 0x10, 0x16, 0x2d, 0xa5, 0x8b, 0x41, 0x62, 0xcd, 0xf3,
- 0x48, 0xc2, 0x57, 0xff, 0x9a, 0x3f, 0x7f, 0xb9, 0x0b, 0xd0, 0x70, 0x2c,
- 0x5f, 0xfe, 0xe7, 0x85, 0xb7, 0x51, 0x30, 0xfe, 0xd1, 0x2c, 0x57, 0x54,
- 0xce, 0xe4, 0xaf, 0x49, 0xa4, 0x4a, 0x24, 0xeb, 0xfa, 0x3f, 0x8e, 0x5d,
- 0xc1, 0x62, 0xfe, 0xc8, 0x99, 0x8b, 0x65, 0x8b, 0xe6, 0xe3, 0xe9, 0x62,
- 0xba, 0x9e, 0x87, 0xcb, 0xaf, 0xc0, 0xeb, 0x8d, 0x1e, 0xb1, 0x7f, 0xf1,
- 0x7d, 0xb8, 0x58, 0x69, 0xb9, 0x1e, 0xb1, 0x7f, 0xda, 0x8e, 0x7f, 0xe3,
- 0x76, 0x05, 0x8a, 0x94, 0x59, 0x61, 0x6b, 0x24, 0x5f, 0xe9, 0xd6, 0xa6,
- 0x0d, 0xf5, 0x8b, 0xf1, 0x85, 0xfc, 0xed, 0x62, 0xb7, 0x3d, 0xd0, 0x19,
- 0xdf, 0xff, 0x9f, 0xd2, 0x7c, 0xef, 0xd2, 0x73, 0x34, 0xc0, 0x58, 0xbe,
- 0x72, 0x61, 0xac, 0x5f, 0xef, 0xe6, 0xdf, 0x91, 0x18, 0xb1, 0x7f, 0xd2,
- 0x32, 0xcf, 0x70, 0xf2, 0xb1, 0x7f, 0xf6, 0x7b, 0xf9, 0x02, 0xc0, 0x0b,
- 0x8b, 0x17, 0xe7, 0xd3, 0xf8, 0x4b, 0x15, 0xf3, 0xec, 0xf2, 0x25, 0xff,
- 0xfb, 0x98, 0x20, 0xbe, 0x07, 0x8f, 0xd3, 0x21, 0x24, 0xb1, 0x52, 0x7f,
- 0x9e, 0x22, 0xbf, 0xee, 0x4e, 0xbd, 0x31, 0x83, 0x75, 0x8b, 0xa5, 0xd6,
- 0x2f, 0xd3, 0xad, 0xa7, 0x75, 0x8a, 0x82, 0xa6, 0xb1, 0xab, 0xe8, 0x84,
- 0xe6, 0xc5, 0x19, 0x07, 0x08, 0x7a, 0x1e, 0x47, 0x0b, 0x5e, 0xff, 0xe5,
- 0x62, 0xef, 0xca, 0xc5, 0x61, 0xb4, 0x61, 0xdb, 0xff, 0xfb, 0x3f, 0xd7,
- 0x0e, 0xff, 0x9e, 0xbc, 0xe6, 0x10, 0x16, 0x2f, 0xfe, 0x7d, 0x4c, 0x3f,
- 0x31, 0x10, 0x8d, 0x58, 0xaf, 0xa2, 0x93, 0x8b, 0xd7, 0xfe, 0xda, 0x62,
- 0x29, 0xe6, 0x4c, 0x16, 0x2e, 0x98, 0x96, 0x2d, 0x1c, 0xb1, 0x5d, 0x4d,
- 0x6e, 0xe3, 0x17, 0xf1, 0xbe, 0x9f, 0xcf, 0x16, 0x2f, 0xfb, 0x85, 0x9e,
- 0xe4, 0xeb, 0x65, 0x8b, 0xfc, 0x30, 0x9c, 0x98, 0x85, 0xa5, 0x8b, 0x1d,
- 0x62, 0xfb, 0xbf, 0x67, 0x16, 0x2f, 0xdf, 0x93, 0x0b, 0x65, 0x8a, 0x81,
- 0xe7, 0x44, 0x49, 0x7e, 0xfc, 0xee, 0x4c, 0xb1, 0x7e, 0x7e, 0xf8, 0xdd,
- 0xac, 0x5f, 0xff, 0xb3, 0xdc, 0x93, 0xf7, 0xc7, 0x1f, 0xf1, 0xcd, 0x58,
- 0xbe, 0xe3, 0xeb, 0x65, 0x8a, 0xea, 0x9a, 0x84, 0xb0, 0x39, 0x1f, 0xca,
- 0x08, 0xab, 0x8a, 0xf7, 0xfb, 0x07, 0x9a, 0x84, 0xe9, 0x62, 0xf7, 0xdf,
- 0xcb, 0x15, 0x2a, 0xca, 0x20, 0xd8, 0xe4, 0x91, 0x17, 0xb1, 0xd0, 0x23,
- 0x88, 0xe2, 0xb9, 0x86, 0x77, 0xe6, 0xfe, 0x77, 0xe5, 0x8b, 0xff, 0x66,
- 0x11, 0xa5, 0x9a, 0x33, 0xcb, 0x17, 0xfe, 0x6f, 0x72, 0x70, 0x87, 0xf9,
- 0x58, 0xbe, 0xdf, 0xf2, 0x25, 0x8a, 0xf9, 0xf0, 0xf8, 0xf6, 0xff, 0xcc,
- 0x5b, 0x07, 0x84, 0x3f, 0xca, 0xc5, 0xcf, 0xb2, 0xc5, 0x61, 0xeb, 0x91,
- 0xfd, 0xfe, 0x17, 0x70, 0xe1, 0x93, 0x1e, 0xb1, 0x7f, 0xc1, 0xb1, 0x6d,
- 0xc7, 0xef, 0xcb, 0x17, 0xb7, 0x98, 0xf5, 0x8b, 0xfd, 0x17, 0xdb, 0x5a,
- 0x71, 0xac, 0x56, 0x1e, 0xb3, 0x10, 0xdf, 0xe6, 0xec, 0xcd, 0x39, 0xf1,
- 0x62, 0xfe, 0x62, 0xd8, 0xed, 0xe5, 0x8a, 0x23, 0xe3, 0xe1, 0xad, 0xfd,
- 0x84, 0xe3, 0xc2, 0x58, 0xbd, 0xf6, 0x3a, 0xc5, 0xff, 0xec, 0xf7, 0x18,
- 0xfa, 0xc7, 0xfc, 0x8d, 0x62, 0xa0, 0x89, 0x17, 0x2b, 0x21, 0xdb, 0xf1,
- 0x9a, 0xce, 0x98, 0xb1, 0x63, 0xac, 0x58, 0x7f, 0x37, 0xa4, 0x57, 0x7f,
- 0x8b, 0x36, 0xf7, 0xa4, 0xeb, 0x15, 0x27, 0xb4, 0x44, 0xd5, 0x05, 0xc4,
- 0x81, 0x94, 0xe4, 0x28, 0x22, 0x79, 0xd1, 0x07, 0xce, 0x8a, 0x12, 0x5c,
- 0x84, 0x1f, 0xa1, 0x64, 0x64, 0x31, 0x6f, 0xe8, 0xa0, 0xfa, 0x84, 0x68,
- 0xb1, 0x74, 0x6c, 0x15, 0x58, 0xbd, 0xc7, 0x0d, 0x62, 0xff, 0x1a, 0xc6,
- 0x48, 0x0c, 0x3a, 0xc5, 0xfe, 0x83, 0xea, 0x19, 0xf6, 0x58, 0xbe, 0xc8,
- 0x9b, 0xcb, 0x17, 0xf7, 0xb9, 0x14, 0x18, 0x96, 0x2f, 0xcd, 0xde, 0x7d,
- 0x96, 0x2a, 0x4f, 0x5c, 0x45, 0xf6, 0xd7, 0x54, 0xde, 0x42, 0xd4, 0xd7,
- 0x08, 0x4d, 0x1e, 0x88, 0xdf, 0xe6, 0x64, 0xf5, 0x7f, 0xb7, 0xfb, 0xf8,
- 0xd9, 0x25, 0x8b, 0xb3, 0xb5, 0x8b, 0xd3, 0xae, 0x2c, 0x54, 0x9b, 0x53,
- 0x8c, 0x5f, 0xfe, 0x91, 0xfc, 0x46, 0x99, 0x23, 0xf8, 0xb8, 0xb1, 0x68,
- 0xfe, 0xa8, 0xd8, 0x1b, 0x51, 0x84, 0x17, 0x66, 0xcb, 0x15, 0x27, 0xa9,
- 0x87, 0x97, 0xf6, 0xdc, 0x98, 0x85, 0xa5, 0x8b, 0xfa, 0x42, 0x6f, 0xf9,
- 0xd9, 0x62, 0xf7, 0x9b, 0x8b, 0x17, 0xfc, 0x28, 0x03, 0xf2, 0xe5, 0xb2,
- 0xc5, 0x62, 0x2e, 0x8d, 0x31, 0x73, 0x22, 0x1d, 0xb8, 0x2c, 0x65, 0x8b,
- 0xff, 0xff, 0x8b, 0x7c, 0x29, 0x0f, 0xc6, 0xb7, 0x07, 0x2d, 0xaf, 0x86,
- 0xc3, 0x58, 0xb9, 0xbb, 0x58, 0xb7, 0xa5, 0x11, 0x9c, 0x74, 0xbe, 0xc3,
- 0xcc, 0x7a, 0xc5, 0xfb, 0x39, 0x25, 0x2b, 0x17, 0xfc, 0x60, 0x98, 0xc8,
- 0xba, 0x83, 0xcb, 0x17, 0xcc, 0x31, 0x1a, 0xe7, 0xcc, 0x22, 0x6a, 0x94,
- 0xe5, 0x1e, 0x15, 0x1c, 0x28, 0x14, 0x22, 0xee, 0x7d, 0x2c, 0x5f, 0x40,
- 0x41, 0xe2, 0xc5, 0xe6, 0x14, 0x4b, 0x17, 0xe9, 0x16, 0xe2, 0x3a, 0xc5,
- 0x0d, 0x10, 0x7d, 0x8b, 0x91, 0x21, 0x83, 0xd7, 0x39, 0x2c, 0x5f, 0x42,
- 0x4b, 0x75, 0x8a, 0x19, 0xb9, 0xc1, 0x6b, 0x44, 0xb1, 0x7c, 0x15, 0x69,
- 0xed, 0x62, 0xd2, 0x46, 0xeb, 0xc2, 0x75, 0xd4, 0xff, 0xdd, 0x6a, 0xfa,
- 0x41, 0x84, 0xb1, 0x7c, 0x5c, 0xf3, 0xac, 0x54, 0x1b, 0x82, 0xc1, 0xc6,
- 0xc9, 0x89, 0x66, 0xc2, 0x0b, 0x78, 0x6b, 0x77, 0x08, 0xa7, 0x95, 0x1d,
- 0x1f, 0x0b, 0x18, 0xa1, 0x87, 0xa9, 0x69, 0x67, 0x9c, 0xc0, 0x69, 0x44,
- 0x00, 0x8e, 0x80, 0xa1, 0xb5, 0xc8, 0xf3, 0xc5, 0x0c, 0x90, 0xe1, 0xed,
- 0x1c, 0x46, 0x61, 0x0d, 0xf1, 0xe3, 0x50, 0x59, 0x1a, 0x2c, 0x5d, 0xee,
- 0x2c, 0x53, 0x9e, 0x64, 0x46, 0x97, 0xc6, 0x48, 0x7c, 0x58, 0xb8, 0x1e,
- 0x58, 0xbf, 0xb4, 0x3f, 0xe6, 0xb6, 0x58, 0xb0, 0x96, 0x2e, 0x07, 0xd6,
- 0x2f, 0xb5, 0xac, 0xe2, 0xc5, 0xd9, 0x12, 0xc5, 0xa1, 0xd5, 0x1a, 0x5b,
- 0x12, 0xe0, 0xc6, 0xe6, 0x07, 0x12, 0x61, 0x83, 0x08, 0xef, 0xfb, 0x82,
- 0xd0, 0x1c, 0x7f, 0x95, 0x8b, 0xef, 0x31, 0x62, 0xc5, 0xf0, 0x49, 0x28,
- 0x2c, 0x53, 0x9e, 0x29, 0x84, 0x37, 0xc4, 0xde, 0xe2, 0xc5, 0xed, 0x37,
- 0x45, 0x8b, 0xfe, 0xc0, 0x8c, 0xe3, 0x17, 0xb8, 0xb1, 0x7e, 0xd0, 0xf3,
- 0x09, 0x62, 0xf8, 0xdd, 0x30, 0x6b, 0x17, 0xfe, 0x7c, 0xfc, 0xf4, 0xe7,
- 0xe7, 0xb5, 0x8a, 0xc3, 0xe6, 0x8f, 0x25, 0xbf, 0xbb, 0xd0, 0xbb, 0xf4,
- 0x16, 0x2f, 0xe0, 0xf0, 0x87, 0xf9, 0x58, 0xbf, 0xdc, 0x19, 0x48, 0x63,
- 0xc5, 0x8b, 0x37, 0x67, 0xc5, 0xf2, 0xeb, 0xa7, 0x65, 0x8a, 0xc5, 0x40,
- 0x31, 0x11, 0x68, 0x7d, 0x8e, 0xf9, 0x08, 0xd1, 0x12, 0x07, 0x09, 0x43,
- 0x0a, 0x2f, 0xfb, 0x7e, 0xf8, 0xf1, 0x14, 0x8d, 0x62, 0xfb, 0xde, 0xcd,
- 0x96, 0x28, 0x8f, 0x80, 0x33, 0xcb, 0xf9, 0xa4, 0x19, 0xdc, 0x16, 0x29,
- 0x62, 0xff, 0x16, 0xb3, 0x98, 0xff, 0x58, 0xa0, 0xa9, 0xbe, 0xc0, 0xcb,
- 0x04, 0x58, 0xbf, 0xfb, 0x08, 0xb3, 0xf8, 0x3f, 0x8a, 0x25, 0x8b, 0xe6,
- 0xf7, 0xe5, 0x62, 0xff, 0xe2, 0xc6, 0xf1, 0x67, 0xbd, 0x81, 0xac, 0x5a,
- 0x1b, 0x22, 0xf5, 0xc5, 0x3e, 0x89, 0xe2, 0x2b, 0xfb, 0x4f, 0xef, 0xe4,
- 0x16, 0x2f, 0x67, 0x70, 0x58, 0xa5, 0x8f, 0x97, 0xd7, 0x4f, 0x45, 0x8b,
- 0xfd, 0x3b, 0x16, 0x6e, 0xc4, 0xb1, 0x5f, 0x3c, 0xce, 0x0c, 0xd6, 0x91,
- 0xab, 0xf4, 0xcf, 0x33, 0xd8, 0x22, 0xc5, 0xbb, 0x58, 0xa6, 0x34, 0xe6,
- 0x0a, 0x5f, 0xfd, 0x23, 0xcd, 0xcb, 0x3d, 0xf7, 0xed, 0x62, 0xff, 0x7b,
- 0x35, 0xb4, 0xfb, 0x8b, 0x15, 0x04, 0x4d, 0xfc, 0x85, 0x91, 0x6f, 0xff,
- 0xb0, 0x6f, 0xec, 0x3f, 0xe6, 0x77, 0x3b, 0x2c, 0x5d, 0x9d, 0x16, 0x2f,
- 0xfb, 0x7f, 0xe0, 0xce, 0xfa, 0xc5, 0x8b, 0xf7, 0x3f, 0x24, 0x6a, 0xc5,
- 0xf7, 0xb4, 0xfb, 0x2c, 0x54, 0x9e, 0x68, 0x8a, 0x6a, 0x53, 0x10, 0xd9,
- 0x3f, 0x06, 0x75, 0x08, 0x7b, 0xff, 0xff, 0x47, 0x66, 0xb3, 0xf9, 0x25,
- 0xef, 0xe3, 0x7d, 0xbd, 0xcc, 0x58, 0xbb, 0x0d, 0x58, 0xa9, 0x44, 0x24,
- 0x73, 0x65, 0xfa, 0x75, 0xf9, 0xe8, 0xb1, 0x7d, 0xd1, 0xf9, 0xda, 0xc5,
- 0x49, 0xe8, 0x31, 0x55, 0xfb, 0xfb, 0x13, 0xca, 0xc5, 0xf8, 0xcc, 0x88,
- 0x70, 0x58, 0xb1, 0xab, 0x15, 0xb1, 0xf3, 0x44, 0x51, 0x1c, 0x57, 0x7c,
- 0xe5, 0x14, 0x7a, 0xc5, 0xf1, 0x4f, 0x70, 0x58, 0xa6, 0x3f, 0xd0, 0x1a,
- 0x78, 0x9a, 0xfb, 0xdc, 0xcf, 0x2c, 0x5f, 0xff, 0xe7, 0xee, 0x1d, 0xf9,
- 0xc3, 0xdf, 0xef, 0xbe, 0xed, 0xad, 0x96, 0x2a, 0x51, 0x19, 0xa2, 0x3b,
- 0xfa, 0x7a, 0x67, 0xff, 0x2b, 0x17, 0xde, 0xe6, 0x44, 0xb1, 0xf3, 0x5f,
- 0x7f, 0x7c, 0x6f, 0xd2, 0x46, 0xb1, 0x43, 0x45, 0xae, 0x28, 0xb1, 0xa5,
- 0xf6, 0x9d, 0xb6, 0x58, 0xbf, 0x4e, 0xa2, 0x38, 0x16, 0x2c, 0x05, 0x8b,
- 0xff, 0x0b, 0x23, 0xf8, 0xda, 0x29, 0x82, 0xc5, 0x61, 0xe9, 0x90, 0x95,
- 0x4a, 0x27, 0x5d, 0xf6, 0xb1, 0x1c, 0x3c, 0x86, 0x05, 0xff, 0xa0, 0xdd,
- 0x39, 0x27, 0x6e, 0xfc, 0xb1, 0x7f, 0x9c, 0x5a, 0xfe, 0x74, 0xe2, 0xc5,
- 0xff, 0xfd, 0xe7, 0xee, 0x05, 0x3d, 0x7c, 0xf8, 0x10, 0x7f, 0xc5, 0x8b,
- 0xff, 0xd2, 0x72, 0xce, 0x85, 0x9d, 0x33, 0x50, 0x58, 0xac, 0x45, 0x59,
- 0x2f, 0xdf, 0xef, 0x70, 0xcf, 0xfd, 0xa3, 0xd6, 0x2f, 0xb3, 0xcf, 0xc5,
- 0x8b, 0xf4, 0x45, 0x1a, 0x6c, 0x25, 0x8b, 0xff, 0xf4, 0x51, 0x48, 0x3d,
- 0xc2, 0xc8, 0x82, 0x91, 0xbc, 0x6e, 0x14, 0x58, 0xbb, 0xdf, 0x58, 0xa0,
- 0xa2, 0x2d, 0x30, 0xc1, 0x9b, 0x2f, 0xfb, 0xdf, 0xc0, 0xfd, 0x1c, 0xfc,
- 0x58, 0xae, 0xd5, 0x61, 0xc7, 0xa1, 0x45, 0x0e, 0x16, 0x21, 0xe1, 0xcf,
- 0xa1, 0xac, 0x61, 0x95, 0xff, 0x84, 0xc7, 0xe3, 0x93, 0x68, 0xd5, 0x8b,
- 0xe6, 0xf3, 0x12, 0xc5, 0x6c, 0xd8, 0x59, 0xc1, 0xfc, 0x72, 0x88, 0xf2,
- 0x1b, 0xc6, 0x91, 0x6e, 0xd9, 0xdc, 0x38, 0x5e, 0x31, 0x88, 0xa1, 0xe5,
- 0xa8, 0xcf, 0xcf, 0x0c, 0x6f, 0xba, 0x82, 0x30, 0x32, 0x8d, 0xbf, 0x91,
- 0x87, 0xfa, 0x57, 0x50, 0x6e, 0xa1, 0x0f, 0xef, 0xde, 0xfb, 0x90, 0x16,
- 0x2f, 0x33, 0xee, 0xb1, 0x7b, 0xcf, 0x05, 0x8a, 0xdc, 0xdd, 0x78, 0x76,
- 0xe8, 0xa5, 0x62, 0xf7, 0x4d, 0x41, 0x62, 0xec, 0x0c, 0x06, 0xe0, 0x86,
- 0x2f, 0xff, 0xde, 0x7e, 0x6d, 0x81, 0xf1, 0xf6, 0x26, 0xef, 0xcb, 0x17,
- 0xfd, 0x0c, 0xf6, 0x0d, 0xc8, 0x0b, 0x17, 0xd0, 0xc9, 0xed, 0x62, 0xfd,
- 0x3a, 0xc2, 0x75, 0x8b, 0xc1, 0xe7, 0xd6, 0x2f, 0xec, 0xd6, 0x84, 0x6e,
- 0x96, 0x2f, 0xe2, 0x80, 0x6d, 0xfe, 0x2c, 0x5f, 0x8d, 0xfb, 0x13, 0xac,
- 0x5b, 0x98, 0x7a, 0xee, 0x5f, 0x71, 0xb0, 0x58, 0xbe, 0xd1, 0x92, 0x1a,
- 0xc5, 0xf0, 0xc9, 0x8d, 0x58, 0xbf, 0xf9, 0xe0, 0xda, 0xce, 0x9d, 0xee,
- 0xfd, 0xac, 0x54, 0xa2, 0x47, 0x62, 0x5f, 0x11, 0xd8, 0x72, 0xac, 0x17,
- 0x65, 0xac, 0x2c, 0xed, 0x66, 0x23, 0x8f, 0x91, 0xb1, 0x31, 0x0f, 0x7a,
- 0x10, 0xf1, 0xc4, 0xc6, 0x42, 0xaa, 0xe7, 0x3a, 0xc5, 0x62, 0x31, 0x3d,
- 0x0a, 0xdb, 0xec, 0x1f, 0x03, 0x58, 0xb3, 0xf0, 0xf2, 0xc2, 0x13, 0xdf,
- 0xe0, 0x0b, 0x8e, 0x5d, 0xc1, 0x62, 0xfe, 0x03, 0xe9, 0xfb, 0x02, 0xc5,
- 0x9a, 0x3c, 0xf9, 0x22, 0x35, 0xb0, 0x16, 0x2f, 0xe9, 0xc3, 0xe6, 0x71,
- 0x62, 0xff, 0xff, 0xe6, 0x19, 0x90, 0xfc, 0x9b, 0x84, 0x28, 0x67, 0x0b,
- 0x00, 0x2e, 0x2c, 0x5f, 0xe1, 0xe1, 0x38, 0x7f, 0x12, 0xc5, 0xfb, 0xbd,
- 0xc4, 0xc4, 0xb1, 0x7f, 0xfd, 0xf7, 0x9f, 0x38, 0x26, 0x11, 0x81, 0x86,
- 0x1a, 0x45, 0xff, 0xcf, 0x3e, 0x04, 0xc2, 0x30, 0x30, 0xc3, 0x48, 0xac,
- 0x45, 0x0f, 0xd5, 0xab, 0x64, 0xc8, 0x77, 0x34, 0xf4, 0x32, 0xef, 0xf7,
- 0xc4, 0xc7, 0x1b, 0x1d, 0x62, 0xb7, 0x54, 0x58, 0x72, 0xc2, 0x8e, 0x53,
- 0xc7, 0x17, 0xb3, 0x0d, 0x48, 0xb0, 0x16, 0x2f, 0x9f, 0xf2, 0x75, 0x8b,
- 0xb9, 0x92, 0x6d, 0x0d, 0x12, 0xa1, 0x9f, 0xef, 0x94, 0x6f, 0xce, 0x45,
- 0x30, 0x58, 0xbc, 0x06, 0xf2, 0xc5, 0xf7, 0xb8, 0x28, 0xf5, 0x8b, 0xe9,
- 0xd3, 0xf4, 0x58, 0xac, 0x44, 0x73, 0x13, 0x08, 0x74, 0xc2, 0x7b, 0xfb,
- 0x3d, 0xc7, 0x2d, 0x96, 0x2f, 0xfb, 0x4d, 0xbf, 0x5f, 0xc9, 0x84, 0xb1,
- 0x78, 0x53, 0xa5, 0x8b, 0x70, 0x67, 0xb5, 0x11, 0xed, 0x6c, 0x8b, 0x1f,
- 0x42, 0x22, 0xf8, 0xd1, 0x03, 0x8b, 0x17, 0x10, 0x95, 0x10, 0xc9, 0x7f,
- 0x49, 0xe7, 0x9a, 0xc5, 0x8a, 0x81, 0xe8, 0xc4, 0x49, 0x74, 0xec, 0xb1,
- 0x7f, 0xff, 0xf6, 0x84, 0x6f, 0x7e, 0x13, 0x18, 0x66, 0xb8, 0x26, 0xd0,
- 0xb6, 0x93, 0x56, 0x2b, 0xe8, 0x93, 0xe0, 0xc5, 0xfb, 0xd3, 0x03, 0x4e,
- 0xb1, 0x7c, 0x21, 0x80, 0x35, 0x8b, 0xfc, 0x22, 0xdf, 0xf3, 0xd8, 0x45,
- 0x8b, 0xf9, 0xfa, 0x39, 0x49, 0xd6, 0x2f, 0x06, 0x18, 0x69, 0x17, 0xb0,
- 0xb7, 0x48, 0x8c, 0x34, 0x37, 0xfe, 0xcd, 0xb0, 0x6d, 0x02, 0x9d, 0x96,
- 0x2a, 0x53, 0x45, 0xd8, 0xa9, 0xc9, 0x58, 0xe0, 0x09, 0xe4, 0x61, 0x7f,
- 0xfb, 0x35, 0xef, 0x67, 0x0a, 0x73, 0x50, 0x58, 0xbf, 0x3f, 0xff, 0x9e,
- 0x58, 0xb4, 0xf5, 0x3f, 0x1e, 0x24, 0xdf, 0xbf, 0x9d, 0x88, 0x35, 0x8b,
- 0xef, 0xb1, 0x1a, 0xb1, 0x43, 0x3f, 0x7d, 0xca, 0x7c, 0x57, 0x7f, 0x77,
- 0x0e, 0x13, 0x6e, 0xb1, 0x7c, 0xd1, 0xfe, 0xe2, 0xc5, 0xe2, 0x0b, 0x58,
- 0xd9, 0x62, 0xb0, 0xff, 0xfb, 0x30, 0x62, 0x6b, 0x82, 0xd4, 0x2d, 0x56,
- 0x2f, 0xd0, 0xdf, 0x3b, 0xf2, 0xc5, 0xfb, 0x3d, 0xe1, 0x6c, 0xb1, 0x7f,
- 0x3b, 0x43, 0xcf, 0xb2, 0xc5, 0xcf, 0xb2, 0xc7, 0xcd, 0x75, 0xa0, 0x16,
- 0xa8, 0xd1, 0x81, 0x31, 0x15, 0xf9, 0x62, 0xf7, 0x46, 0x3a, 0xc5, 0xf6,
- 0x0d, 0xbe, 0xb1, 0x58, 0x78, 0x3c, 0x1f, 0xbf, 0xe3, 0x84, 0x62, 0x9f,
- 0xc8, 0xd6, 0x2f, 0x7f, 0x37, 0x58, 0xbe, 0xf4, 0xf7, 0xc5, 0x8a, 0x93,
- 0xfc, 0x19, 0xd3, 0x0f, 0x5e, 0x68, 0xf9, 0x58, 0xbf, 0x60, 0xfe, 0xd1,
- 0xeb, 0x17, 0xe2, 0xc1, 0xc9, 0xd6, 0x2f, 0xf6, 0x04, 0xdf, 0xf9, 0xd8,
- 0x45, 0x8a, 0x8d, 0x19, 0x88, 0x93, 0x28, 0xfb, 0x68, 0x61, 0x0e, 0x16,
- 0x19, 0x0e, 0xd3, 0x4a, 0x7b, 0x76, 0x8a, 0x16, 0xda, 0x8d, 0xa0, 0xf1,
- 0x9e, 0xfe, 0x15, 0xed, 0x0f, 0xf0, 0x42, 0x28, 0xa1, 0x3a, 0x22, 0xde,
- 0x83, 0xe1, 0x95, 0xc7, 0x13, 0xdf, 0xc7, 0xc7, 0xd4, 0x50, 0x58, 0xbf,
- 0xe2, 0x17, 0xbf, 0x9d, 0x07, 0x2b, 0x14, 0xb1, 0x7b, 0x4f, 0xa5, 0x8a,
- 0xc3, 0xe4, 0x0b, 0x9d, 0x98, 0x19, 0x7f, 0xf8, 0xc6, 0x2f, 0xb4, 0x39,
- 0x87, 0x98, 0xf5, 0x8a, 0xea, 0x88, 0x03, 0x4c, 0xea, 0x53, 0x39, 0x78,
- 0xc4, 0xef, 0xa7, 0xc2, 0x31, 0x62, 0xf7, 0x9e, 0x56, 0x2f, 0xcf, 0x3b,
- 0x31, 0xd6, 0x2f, 0xf7, 0xe4, 0xbc, 0x43, 0xed, 0x62, 0xc4, 0xb1, 0x73,
- 0x9d, 0x62, 0xb0, 0xd4, 0x10, 0x8d, 0x3a, 0x2f, 0xc8, 0x73, 0x85, 0x02,
- 0x5c, 0xbf, 0xf6, 0xa1, 0x03, 0xf1, 0xcb, 0xb8, 0x2c, 0x5f, 0x8a, 0x7b,
- 0x9e, 0x2c, 0x5f, 0xfb, 0x1c, 0x9b, 0xdc, 0x0e, 0x49, 0x62, 0xda, 0x93,
- 0xe5, 0xe1, 0x45, 0xbf, 0x88, 0xcd, 0x68, 0x53, 0x5f, 0x3e, 0xa7, 0xcb,
- 0x17, 0xff, 0xe2, 0x9d, 0x69, 0xe7, 0x6c, 0x00, 0x98, 0xb7, 0x58, 0xbe,
- 0xe6, 0x4c, 0x16, 0x28, 0x68, 0x99, 0xdc, 0x88, 0x95, 0x6f, 0x7f, 0x3b,
- 0x58, 0xbf, 0x0f, 0x4f, 0x27, 0x58, 0xb4, 0xc0, 0xf1, 0x88, 0x7a, 0xfa,
- 0x0f, 0x3b, 0xac, 0x5d, 0xd8, 0x16, 0x2f, 0xe3, 0xcf, 0x00, 0xfb, 0xac,
- 0x5e, 0xe4, 0x9a, 0x03, 0xc8, 0xe0, 0xcd, 0xf4, 0x27, 0x5b, 0x2c, 0x5f,
- 0xb0, 0x23, 0xcc, 0x4b, 0x15, 0x11, 0xe7, 0x11, 0x25, 0xfd, 0x9a, 0x00,
- 0x1c, 0x96, 0x29, 0x8f, 0x3c, 0x44, 0x57, 0xf1, 0x79, 0xf6, 0x29, 0x58,
- 0xb7, 0x16, 0x2e, 0x8d, 0x36, 0x58, 0xa9, 0x3d, 0xd8, 0x16, 0xb0, 0x95,
- 0xee, 0x9f, 0x75, 0x8b, 0xda, 0x98, 0x2c, 0x5f, 0xa4, 0x7f, 0x90, 0xba,
- 0xc5, 0x68, 0xf2, 0x7a, 0x0e, 0xdf, 0xe7, 0x1e, 0xb0, 0x6c, 0x75, 0x8b,
- 0xe8, 0xb9, 0x3c, 0x58, 0xbf, 0xf4, 0x76, 0x18, 0x52, 0x5b, 0x3e, 0x96,
- 0x2d, 0x87, 0x44, 0xc8, 0x0c, 0xfc, 0x49, 0x7d, 0x87, 0x30, 0x6b, 0x17,
- 0xf3, 0x9b, 0xee, 0x37, 0x6b, 0x17, 0xe3, 0x62, 0x92, 0xf2, 0xc5, 0x4a,
- 0x7b, 0x0e, 0xd1, 0xf8, 0x5e, 0x91, 0xaf, 0x09, 0x04, 0x61, 0x78, 0x29,
- 0xf7, 0x58, 0xbf, 0xff, 0xee, 0x92, 0x37, 0x26, 0xd1, 0xa4, 0xce, 0x58,
- 0x01, 0x71, 0x62, 0xff, 0xdf, 0x33, 0x99, 0xad, 0xd9, 0xb7, 0x54, 0x41,
- 0x85, 0xff, 0xdb, 0x49, 0xb9, 0xaf, 0x7a, 0x73, 0x8b, 0x14, 0x34, 0x4a,
- 0x92, 0x7d, 0x4a, 0x63, 0xaf, 0x0f, 0xbb, 0xfe, 0x13, 0x1b, 0x9e, 0xf6,
- 0x7d, 0x62, 0xee, 0x98, 0xb1, 0x5f, 0x3d, 0x36, 0x3a, 0xbf, 0xdd, 0x24,
- 0xb0, 0xcc, 0x3a, 0xc5, 0xfe, 0xfc, 0x97, 0x80, 0xde, 0x58, 0xbf, 0xfd,
- 0x0d, 0x4c, 0x37, 0xfb, 0xfc, 0x98, 0xeb, 0x15, 0xc3, 0xfe, 0x11, 0x9d,
- 0xff, 0xfa, 0x4b, 0x76, 0x20, 0x60, 0xf8, 0x42, 0x68, 0x2c, 0x5f, 0xfd,
- 0xe1, 0x4b, 0x6a, 0x4d, 0x34, 0x5b, 0x2c, 0x51, 0xd1, 0x38, 0xca, 0x97,
- 0x88, 0x46, 0xac, 0x5f, 0xf6, 0xee, 0x73, 0xbf, 0x5e, 0x09, 0x62, 0xff,
- 0x37, 0x7c, 0x33, 0x5f, 0x65, 0x8b, 0xff, 0xb0, 0x36, 0x07, 0x56, 0x32,
- 0x26, 0xf2, 0xc5, 0xb8, 0x03, 0xff, 0x23, 0x6b, 0xf9, 0xbf, 0x84, 0x7c,
- 0x58, 0xbe, 0x17, 0xf3, 0x75, 0x8b, 0xf9, 0xca, 0x7e, 0xfb, 0x2c, 0x54,
- 0x15, 0xd6, 0x0d, 0xe9, 0xc8, 0x75, 0x0b, 0x33, 0xc2, 0xfb, 0xe4, 0x44,
- 0x3d, 0xe8, 0x5e, 0x74, 0x27, 0x8e, 0x2c, 0x08, 0x49, 0x7f, 0xf7, 0xb9,
- 0xb4, 0x98, 0x53, 0xf7, 0xd9, 0x62, 0xff, 0x72, 0x75, 0x0d, 0xdf, 0x65,
- 0x8b, 0xef, 0xbb, 0x01, 0x62, 0x89, 0x13, 0xfc, 0x47, 0xf1, 0xb5, 0xfe,
+ 0xf7, 0x38, 0x26, 0x38, 0x7f, 0x6f, 0xca, 0xc5, 0x18, 0xa8, 0x3a, 0x21,
+ 0xff, 0x9a, 0x34, 0x2a, 0x08, 0xc7, 0x85, 0x5d, 0xc4, 0x57, 0xdd, 0x9b,
+ 0xee, 0xb1, 0x7f, 0xb3, 0x8c, 0xdd, 0x41, 0xd6, 0x2f, 0xd0, 0x21, 0x37,
+ 0x16, 0x2e, 0x0f, 0xeb, 0x17, 0xa2, 0x10, 0x6b, 0x15, 0x26, 0xe5, 0x86,
+ 0x6e, 0x2f, 0x2c, 0x5d, 0x31, 0x2c, 0x5c, 0x5b, 0x2c, 0x54, 0xa6, 0x3d,
+ 0xb1, 0x23, 0x99, 0xfd, 0x85, 0x87, 0xc8, 0x5f, 0xb8, 0x62, 0xfc, 0xd1,
+ 0x72, 0x7a, 0x58, 0xa3, 0x17, 0xd1, 0x87, 0x0b, 0xed, 0x42, 0xec, 0xe4,
+ 0x20, 0x53, 0x28, 0x74, 0x72, 0x52, 0xb7, 0xa3, 0x8c, 0xec, 0xcb, 0x7f,
+ 0x4c, 0x3f, 0x3d, 0x9d, 0x62, 0xf8, 0xfb, 0x34, 0x7a, 0xc5, 0xe9, 0x3c,
+ 0xac, 0x56, 0x1e, 0x1e, 0xe4, 0xf7, 0xbe, 0x1f, 0x16, 0x2f, 0xf1, 0x7b,
+ 0xc5, 0x3e, 0xe2, 0xc5, 0xe2, 0x11, 0xab, 0x15, 0x27, 0xa2, 0xe6, 0x77,
+ 0xf4, 0x24, 0x1f, 0x84, 0xac, 0x51, 0xa7, 0x9c, 0xe4, 0x17, 0xc2, 0x29,
+ 0x3a, 0xc5, 0xe6, 0x63, 0xac, 0x51, 0xcd, 0xf7, 0xc8, 0xaf, 0x78, 0x33,
+ 0xac, 0x58, 0x6b, 0x17, 0x67, 0x72, 0xc5, 0xcd, 0xc5, 0x8b, 0x6b, 0xa3,
+ 0xe2, 0x38, 0xff, 0xc4, 0x84, 0x35, 0x52, 0x8c, 0x66, 0x84, 0x1d, 0xd0,
+ 0xf2, 0xc5, 0xf4, 0x53, 0xe6, 0x58, 0xad, 0xcd, 0xd8, 0x86, 0x2f, 0x16,
+ 0x71, 0x62, 0xf0, 0x81, 0x84, 0x6f, 0xbb, 0x11, 0x5a, 0x0b, 0x15, 0xb1,
+ 0xe2, 0xfc, 0xce, 0xff, 0xdf, 0x0c, 0x7e, 0x7c, 0x8a, 0x4e, 0xb1, 0x74,
+ 0xc4, 0xb1, 0x7c, 0x3f, 0xc8, 0x16, 0x2a, 0x4f, 0xf0, 0x90, 0x43, 0x18,
+ 0xbf, 0xf1, 0x37, 0xa7, 0x02, 0x62, 0x65, 0x8b, 0xfc, 0x63, 0x38, 0xc5,
+ 0xee, 0x2c, 0x56, 0xe7, 0xe2, 0x03, 0xcb, 0xd2, 0x46, 0xac, 0x5f, 0xfb,
+ 0xce, 0x16, 0xff, 0x7e, 0xce, 0x35, 0x8b, 0xfd, 0xa8, 0x7f, 0x3b, 0x49,
+ 0xd6, 0x29, 0x62, 0xee, 0x62, 0xc5, 0x40, 0xd1, 0xf7, 0xe1, 0x97, 0x66,
+ 0xcb, 0x14, 0x23, 0x7c, 0x19, 0x35, 0xe7, 0xe8, 0x25, 0x8b, 0xc2, 0x1e,
+ 0xeb, 0x15, 0x29, 0xbd, 0x6e, 0x47, 0xd0, 0xeb, 0xa1, 0xb4, 0x25, 0xc0,
+ 0x45, 0xe1, 0xfb, 0xdd, 0x43, 0x75, 0x8b, 0xa0, 0xcb, 0x17, 0x10, 0x96,
+ 0x2f, 0x71, 0xfb, 0x2c, 0x5f, 0x79, 0x9b, 0xeb, 0x15, 0x03, 0xc1, 0x21,
+ 0xfa, 0x94, 0x48, 0x6c, 0x2e, 0xcb, 0x17, 0xd9, 0xa9, 0x1a, 0xc5, 0xf4,
+ 0x5f, 0xc8, 0x96, 0x2f, 0xf0, 0xb6, 0xf1, 0x49, 0xf8, 0xb1, 0x7b, 0x35,
+ 0x86, 0x1f, 0xe3, 0x11, 0x06, 0x4b, 0x78, 0xe2, 0xec, 0xb1, 0x7f, 0x64,
+ 0x3a, 0x86, 0x79, 0x62, 0xde, 0x82, 0x23, 0xf1, 0x03, 0xe4, 0x17, 0x3e,
+ 0xeb, 0x17, 0xa1, 0x8c, 0xb1, 0x7b, 0xba, 0x3c, 0x6b, 0x16, 0x39, 0x87,
+ 0x81, 0x1b, 0x0e, 0x50, 0x11, 0x0c, 0x25, 0x8a, 0x58, 0xbe, 0x1c, 0x74,
+ 0x84, 0xb1, 0x70, 0x8e, 0xb1, 0x44, 0x6f, 0xfc, 0x4f, 0x7d, 0xd4, 0x3e,
+ 0xeb, 0x15, 0x27, 0x88, 0xc4, 0x17, 0xf4, 0x9b, 0xee, 0x08, 0x96, 0x2f,
+ 0xef, 0x4f, 0x67, 0x20, 0x2c, 0x52, 0xa4, 0x0e, 0x2f, 0xfb, 0xd0, 0x73,
+ 0xcf, 0xc3, 0x1a, 0xc5, 0x80, 0xb1, 0x7f, 0x36, 0xc0, 0x62, 0x1a, 0x21,
+ 0x06, 0x96, 0xe6, 0x23, 0x47, 0x72, 0xf6, 0x19, 0x23, 0xb8, 0xe1, 0x2a,
+ 0xef, 0x15, 0x00, 0x1e, 0x11, 0xff, 0x20, 0xf4, 0x60, 0x16, 0x8f, 0x58,
+ 0xbf, 0xe7, 0xcf, 0x73, 0x58, 0x3c, 0x58, 0xbf, 0xbe, 0xc7, 0x29, 0xe9,
+ 0x62, 0xf8, 0xfc, 0x68, 0x7c, 0xf9, 0x83, 0x38, 0xbc, 0xcd, 0xa5, 0x8b,
+ 0xf8, 0x1f, 0x2c, 0xf7, 0x16, 0x2f, 0xe2, 0xce, 0xc5, 0x9c, 0x58, 0xb4,
+ 0xc4, 0x7f, 0x1a, 0x1c, 0xf1, 0x75, 0xfa, 0x63, 0x9f, 0xe2, 0x58, 0xa9,
+ 0x4f, 0x70, 0x69, 0xf8, 0xf7, 0xc8, 0x59, 0x78, 0xd6, 0xdc, 0x58, 0xbf,
+ 0x7e, 0x63, 0xc5, 0x05, 0x8a, 0x93, 0x7c, 0xc2, 0x57, 0xcd, 0xec, 0x09,
+ 0x62, 0xff, 0x87, 0x3d, 0x7d, 0xc7, 0xac, 0x58, 0xa8, 0x33, 0x8a, 0x46,
+ 0xe5, 0x84, 0x46, 0xc2, 0xfb, 0x78, 0xc9, 0xb5, 0x0e, 0x43, 0xc2, 0x7f,
+ 0xf2, 0x86, 0x59, 0xa4, 0x10, 0xb0, 0x28, 0xce, 0xb9, 0x0b, 0xbf, 0x4b,
+ 0xff, 0xed, 0x08, 0xc8, 0xe1, 0xfe, 0xe2, 0x3b, 0xff, 0xe3, 0x5a, 0x2f,
+ 0xce, 0xde, 0x73, 0x9c, 0x5c, 0x58, 0xbc, 0xe5, 0xba, 0xc5, 0xf6, 0x75,
+ 0xec, 0x58, 0xb4, 0x0e, 0x78, 0x04, 0x3b, 0x7a, 0x1e, 0xd9, 0x62, 0xff,
+ 0xf1, 0x67, 0xf1, 0xb7, 0xfc, 0x90, 0x86, 0xb1, 0x7f, 0xf8, 0x13, 0xd6,
+ 0x6c, 0x36, 0x6d, 0xd8, 0x6b, 0x16, 0x0f, 0x74, 0x4a, 0x81, 0x26, 0xa5,
+ 0x30, 0x61, 0x93, 0xea, 0x16, 0x97, 0xf1, 0x7a, 0x19, 0xac, 0x58, 0xbf,
+ 0x33, 0x6d, 0x84, 0xb1, 0x74, 0x73, 0x2c, 0x53, 0x1f, 0x77, 0x8b, 0x43,
+ 0x27, 0xbf, 0xda, 0xdb, 0x8d, 0xbe, 0xb1, 0x62, 0xff, 0x7e, 0x7e, 0xe6,
+ 0xe0, 0x4b, 0x17, 0xf6, 0x6e, 0xdf, 0x9f, 0xac, 0x54, 0x0f, 0x8f, 0xe6,
+ 0xb7, 0xf1, 0x6f, 0x9e, 0xfb, 0xac, 0x5f, 0xfe, 0xd3, 0x1f, 0x06, 0x59,
+ 0xee, 0x49, 0xd6, 0x2f, 0x33, 0xfa, 0x4f, 0xdd, 0xcb, 0xad, 0xc5, 0x8b,
+ 0xf3, 0x83, 0x9f, 0x75, 0x8a, 0xc3, 0x74, 0x42, 0x57, 0x68, 0x6b, 0x17,
+ 0x04, 0x12, 0xc5, 0x40, 0xd9, 0x04, 0x31, 0x7a, 0x5f, 0xb2, 0x44, 0x61,
+ 0xa2, 0xbf, 0xe7, 0x27, 0x07, 0x33, 0xec, 0xb1, 0x7f, 0x16, 0x05, 0x84,
+ 0x35, 0x8a, 0xc5, 0x41, 0x7f, 0x84, 0xcb, 0x35, 0x71, 0xcf, 0xc6, 0x21,
+ 0x9b, 0xde, 0xe7, 0x79, 0xde, 0xac, 0x5f, 0xd2, 0x5e, 0xfe, 0x41, 0x62,
+ 0xed, 0x4a, 0xc5, 0xc0, 0xe2, 0xc5, 0xfc, 0xff, 0x73, 0x4d, 0x95, 0x8a,
+ 0x19, 0xe3, 0xf8, 0x62, 0x9d, 0x10, 0x01, 0xaf, 0x56, 0x91, 0xa1, 0xc8,
+ 0x56, 0xdf, 0x10, 0x98, 0x35, 0x8a, 0x95, 0xc4, 0x47, 0x95, 0x49, 0xe5,
+ 0xd0, 0xe1, 0xf1, 0xdc, 0x51, 0x79, 0xcb, 0x16, 0x2f, 0x9c, 0xed, 0x12,
+ 0xc5, 0xdc, 0xf2, 0xc5, 0xe7, 0x26, 0x58, 0xb6, 0xcb, 0x16, 0xc8, 0x1a,
+ 0xe2, 0x1b, 0xbf, 0xe9, 0x39, 0x99, 0xad, 0x9f, 0x65, 0x8a, 0x82, 0x39,
+ 0x46, 0x37, 0xb9, 0x1c, 0x7a, 0x31, 0x12, 0xdf, 0xf8, 0x84, 0xc1, 0x99,
+ 0x98, 0x46, 0xac, 0x5e, 0x1f, 0x7a, 0x4b, 0x17, 0xe0, 0x16, 0x76, 0xc5,
+ 0x8b, 0xdf, 0x99, 0x58, 0xbf, 0xde, 0xe7, 0xc5, 0x25, 0xb2, 0xc5, 0xe7,
+ 0x26, 0x58, 0xb3, 0xe1, 0xe8, 0x6e, 0x6b, 0x7f, 0x1f, 0x07, 0x25, 0xba,
+ 0xc5, 0x18, 0x9a, 0x67, 0x7a, 0x81, 0x02, 0x23, 0x94, 0xfd, 0xb0, 0x32,
+ 0x7b, 0xc1, 0x04, 0x12, 0x45, 0x24, 0x46, 0x1a, 0x1b, 0xe7, 0x09, 0xe2,
+ 0x48, 0xad, 0xcf, 0x0d, 0xc7, 0xed, 0xd9, 0x62, 0xf4, 0xf6, 0xc5, 0x8a,
+ 0x19, 0xb2, 0xd0, 0xa5, 0xe8, 0xb3, 0xeb, 0x15, 0x86, 0xfd, 0x88, 0x6f,
+ 0x78, 0x4c, 0xb1, 0x6d, 0x96, 0x2f, 0xbd, 0xa6, 0xec, 0xb1, 0x58, 0x7a,
+ 0xba, 0x1d, 0x61, 0x3b, 0xf1, 0xdf, 0xee, 0x75, 0x8b, 0xb3, 0xbf, 0x58,
+ 0xbf, 0xbe, 0x66, 0x9e, 0x78, 0xb1, 0x51, 0xa3, 0xa6, 0x43, 0x98, 0xc7,
+ 0x76, 0x8c, 0x1e, 0x10, 0xb0, 0x19, 0xae, 0x4f, 0xb1, 0xbd, 0x3b, 0x22,
+ 0x28, 0xc7, 0x35, 0x1c, 0xd1, 0xe1, 0x47, 0xf9, 0xc7, 0x36, 0x8d, 0x00,
+ 0x11, 0xcc, 0x94, 0x30, 0xf9, 0x09, 0x3f, 0x3a, 0x76, 0x2d, 0x08, 0xa0,
+ 0x31, 0xcb, 0xf1, 0x34, 0x30, 0x6b, 0x17, 0xa0, 0x2c, 0x58, 0xbd, 0x13,
+ 0x4a, 0xc5, 0xfb, 0x3a, 0xe4, 0xc1, 0x62, 0xb4, 0x7c, 0x62, 0x1d, 0x08,
+ 0x76, 0xff, 0xbf, 0xbb, 0xc8, 0x0f, 0x30, 0x58, 0xbf, 0xfb, 0xc0, 0x72,
+ 0x87, 0x36, 0xed, 0xc7, 0x58, 0xbd, 0xfc, 0xd9, 0x62, 0xfd, 0x80, 0x06,
+ 0x01, 0x62, 0x98, 0xf1, 0x88, 0x7a, 0xfc, 0x39, 0xfc, 0xc1, 0x62, 0xfe,
+ 0xcd, 0x49, 0x4f, 0x16, 0x2f, 0xf8, 0xed, 0xcc, 0xd3, 0x74, 0x12, 0xc5,
+ 0xfd, 0x84, 0x2f, 0x4f, 0xd6, 0x2f, 0xee, 0x67, 0x62, 0x9e, 0xb0, 0xfa,
+ 0x38, 0x77, 0x52, 0x98, 0x0e, 0x14, 0x7a, 0x12, 0x97, 0xed, 0x3e, 0xcc,
+ 0x75, 0x8b, 0xf7, 0x83, 0xfb, 0x01, 0x62, 0xb6, 0x44, 0x3e, 0x1a, 0x74,
+ 0x53, 0x43, 0x54, 0xcf, 0xd4, 0x23, 0x8a, 0x3a, 0x8b, 0xc4, 0xfc, 0x58,
+ 0xbc, 0xd9, 0xba, 0xc5, 0xe7, 0xcd, 0x96, 0x2f, 0xe2, 0x07, 0x3d, 0xce,
+ 0x96, 0x2f, 0xfc, 0x13, 0x0c, 0xc0, 0xc0, 0x07, 0xee, 0x58, 0xbf, 0x0b,
+ 0xcc, 0x0e, 0x2c, 0x56, 0x22, 0x7f, 0xe6, 0x00, 0x46, 0xbf, 0xed, 0xa5,
+ 0xb7, 0x06, 0xb3, 0xa5, 0x8a, 0xd1, 0xf5, 0x91, 0x7d, 0xe6, 0x20, 0x2c,
+ 0x5f, 0xde, 0x6f, 0x81, 0xbc, 0xb1, 0x43, 0x3c, 0xac, 0x1c, 0xbf, 0xe6,
+ 0x3b, 0xff, 0xae, 0x48, 0xd6, 0x2f, 0xfc, 0x40, 0x29, 0xea, 0x29, 0x20,
+ 0x2c, 0x5f, 0xa2, 0xe7, 0xb0, 0x6b, 0x15, 0x27, 0xd2, 0x19, 0xfd, 0x18,
+ 0xbb, 0x1f, 0x92, 0xa8, 0x5c, 0xf7, 0x43, 0x9f, 0x1d, 0x68, 0xc9, 0xc0,
+ 0xd6, 0x44, 0x3c, 0x85, 0x1d, 0xf8, 0xc3, 0xce, 0x79, 0x62, 0xf0, 0x20,
+ 0x4b, 0x15, 0xb1, 0xe3, 0x40, 0xa6, 0xfd, 0x14, 0x70, 0x23, 0xb1, 0x62,
+ 0xf7, 0x9b, 0xeb, 0x17, 0xef, 0x14, 0x9f, 0x8b, 0x17, 0xee, 0x37, 0x58,
+ 0x75, 0x8a, 0x93, 0xee, 0xe8, 0x77, 0xc5, 0x17, 0xf8, 0x50, 0xd6, 0x47,
+ 0x38, 0x16, 0x2f, 0x9b, 0xb7, 0xdd, 0x62, 0xff, 0xfa, 0x7a, 0xfe, 0x70,
+ 0x4d, 0xa1, 0x6d, 0x9f, 0x58, 0xa7, 0x3f, 0x6f, 0x92, 0x5f, 0x8b, 0xdc,
+ 0x73, 0xac, 0x5f, 0xf6, 0xb9, 0xf7, 0xdc, 0x5a, 0x02, 0xc5, 0x61, 0xf2,
+ 0x31, 0x45, 0xff, 0x66, 0xc7, 0xce, 0xbd, 0x27, 0x58, 0xa9, 0x3d, 0xb1,
+ 0x90, 0x5f, 0xb5, 0x9d, 0x9b, 0xeb, 0x16, 0x75, 0x8b, 0xfe, 0x63, 0x77,
+ 0xfb, 0x8d, 0xa0, 0xb1, 0x7d, 0xb6, 0xcd, 0xd2, 0xc5, 0xb8, 0xe7, 0xe4,
+ 0x42, 0x21, 0x9d, 0xdf, 0xf0, 0xff, 0x3a, 0x90, 0x67, 0x16, 0x2f, 0xff,
+ 0xf7, 0xe4, 0xa4, 0x5b, 0xf9, 0xbf, 0x87, 0x7f, 0x00, 0x4b, 0x14, 0x6a,
+ 0x6d, 0x40, 0x84, 0xe7, 0x0d, 0x3c, 0x73, 0x7e, 0x14, 0xee, 0x01, 0x2c,
+ 0x5f, 0xee, 0x49, 0xf9, 0xb8, 0xb6, 0x58, 0xbf, 0xfc, 0x6b, 0xf8, 0xb2,
+ 0x06, 0x6e, 0x70, 0x4a, 0xc5, 0xf6, 0x6b, 0xee, 0xb1, 0x7e, 0x78, 0xbe,
+ 0xe0, 0x58, 0xbf, 0xfc, 0xd0, 0x2c, 0xec, 0xd1, 0x4e, 0x7b, 0x8b, 0x15,
+ 0x28, 0x96, 0xf9, 0x13, 0x14, 0xda, 0x39, 0x62, 0xe9, 0x35, 0x62, 0xf8,
+ 0x6c, 0xe3, 0x58, 0xa8, 0xd0, 0xf3, 0xf6, 0x15, 0xc1, 0x8b, 0xdd, 0xb0,
+ 0x96, 0x2e, 0xfb, 0xac, 0x5e, 0xf0, 0x04, 0xb1, 0x7f, 0xce, 0x14, 0x46,
+ 0x4e, 0xb5, 0x8b, 0x17, 0xfe, 0x0f, 0xa0, 0x67, 0x67, 0x2f, 0x71, 0x62,
+ 0xa5, 0x1a, 0x46, 0x8f, 0x38, 0xbc, 0x43, 0xdc, 0x3c, 0xbf, 0xd9, 0xb0,
+ 0x7f, 0xfe, 0x47, 0xac, 0x5f, 0xe7, 0xe1, 0x86, 0xeb, 0x38, 0xb1, 0x7c,
+ 0x0e, 0x79, 0xd6, 0x2f, 0xfd, 0xfc, 0xcd, 0x9f, 0x3b, 0x4f, 0x4b, 0x15,
+ 0x27, 0xc8, 0x02, 0x3a, 0x94, 0x7a, 0x6e, 0x72, 0x14, 0x26, 0xaf, 0xfe,
+ 0x93, 0xeb, 0x53, 0xb7, 0x99, 0x8d, 0x58, 0xba, 0x42, 0x58, 0xa0, 0x1e,
+ 0xf1, 0x23, 0x5f, 0xff, 0x0b, 0xbf, 0xe7, 0x37, 0xfb, 0xf5, 0xed, 0x6a,
+ 0x56, 0x2f, 0xee, 0xcf, 0xac, 0x1c, 0x68, 0xb1, 0x7c, 0xfe, 0x9d, 0x2c,
+ 0x5f, 0xf6, 0x73, 0x1f, 0x63, 0xb7, 0x72, 0xc5, 0xdf, 0xc5, 0x8a, 0x81,
+ 0xe9, 0xf0, 0xf2, 0xa5, 0x32, 0x5c, 0x59, 0xf9, 0xa8, 0x9d, 0x6f, 0x1e,
+ 0x77, 0x58, 0xbf, 0xe6, 0x87, 0x00, 0xdd, 0xb0, 0x6b, 0x17, 0x67, 0xf0,
+ 0xf6, 0x7e, 0x3d, 0x7f, 0xcc, 0xfe, 0x98, 0x08, 0x78, 0xb1, 0x7d, 0x9e,
+ 0x0f, 0x65, 0x8b, 0xe7, 0xd7, 0xc5, 0xf3, 0xdd, 0xe1, 0xc5, 0xfb, 0x4f,
+ 0xb3, 0x1d, 0x62, 0xe0, 0x82, 0x58, 0xac, 0x3c, 0x30, 0x8a, 0x6f, 0xe6,
+ 0x7e, 0xb9, 0x26, 0xac, 0x58, 0x49, 0x11, 0x87, 0xa3, 0xf2, 0x2a, 0x3a,
+ 0x60, 0x1f, 0x86, 0x6d, 0xff, 0xee, 0xdf, 0x7c, 0x2d, 0xfe, 0xe7, 0x9d,
+ 0xd6, 0x2f, 0xe6, 0x07, 0x50, 0xcf, 0x2c, 0x56, 0x1f, 0xe3, 0xa6, 0xde,
+ 0x80, 0x67, 0x58, 0xbf, 0x6b, 0xf9, 0xbe, 0xcb, 0x17, 0xba, 0x18, 0xd6,
+ 0x29, 0xcf, 0x29, 0x8a, 0xef, 0x48, 0x38, 0xb1, 0x50, 0x55, 0xe8, 0xf1,
+ 0xc4, 0xfe, 0x14, 0xac, 0x41, 0xc6, 0x91, 0x10, 0x5e, 0xc3, 0xc7, 0xac,
+ 0x5f, 0xf9, 0xbb, 0x60, 0x65, 0x3f, 0x7d, 0x96, 0x2f, 0xf6, 0x70, 0xb3,
+ 0xdf, 0x75, 0x8a, 0x1a, 0x24, 0xf4, 0x40, 0x48, 0x37, 0xfe, 0x2d, 0xc7,
+ 0xf9, 0xf9, 0x36, 0xcb, 0x17, 0xef, 0xb1, 0x39, 0xd6, 0x2a, 0x4f, 0x9d,
+ 0xd0, 0x2b, 0x66, 0x73, 0x7c, 0x21, 0x5a, 0x38, 0x70, 0x64, 0x71, 0x7b,
+ 0xa2, 0x74, 0x54, 0xe6, 0xf1, 0x43, 0x8f, 0x4f, 0xa7, 0x8c, 0x1b, 0xf1,
+ 0x9f, 0x02, 0x12, 0x85, 0x1a, 0x37, 0xa5, 0xc4, 0xf6, 0x87, 0xaf, 0x74,
+ 0x25, 0xaf, 0xf8, 0x78, 0x00, 0x39, 0x19, 0x1c, 0xb1, 0x4b, 0x17, 0xf6,
+ 0x00, 0x0e, 0x51, 0xcb, 0x17, 0xf4, 0xf1, 0xfc, 0x52, 0xb1, 0x46, 0x22,
+ 0x96, 0x4f, 0x46, 0x19, 0xf3, 0x0b, 0xf8, 0x3f, 0x75, 0xbb, 0xe2, 0xc5,
+ 0xf9, 0xcb, 0xd8, 0x75, 0x8a, 0x30, 0xf6, 0x20, 0x63, 0x7d, 0x9f, 0x70,
+ 0x96, 0x2f, 0xf7, 0xb3, 0x40, 0x3b, 0x41, 0x62, 0xfa, 0x00, 0xc0, 0x2c,
+ 0x5f, 0x36, 0x07, 0x8b, 0x17, 0xb0, 0xb7, 0x58, 0xbf, 0xbd, 0x91, 0x14,
+ 0x9d, 0x72, 0x01, 0x17, 0x77, 0x09, 0x62, 0xf0, 0xff, 0x2a, 0x90, 0x08,
+ 0x8c, 0x3d, 0x63, 0x9d, 0xde, 0x16, 0x8d, 0x58, 0xad, 0x91, 0xba, 0x4e,
+ 0x71, 0xc9, 0x77, 0xf4, 0x91, 0x9e, 0x7d, 0x96, 0x2f, 0xff, 0x77, 0xef,
+ 0xac, 0xec, 0xfe, 0x9c, 0x28, 0x2c, 0x5c, 0x52, 0xb1, 0x52, 0xa9, 0x8f,
+ 0x62, 0x3c, 0x23, 0xe8, 0xd3, 0xe4, 0x6d, 0x0f, 0xf0, 0x19, 0x88, 0xbf,
+ 0xb9, 0x3e, 0xff, 0x05, 0x86, 0x70, 0xa7, 0x4b, 0x17, 0xfd, 0x14, 0x85,
+ 0xac, 0xdd, 0xfe, 0xb1, 0x7f, 0x3e, 0xde, 0x68, 0x71, 0x62, 0xff, 0x9f,
+ 0x5f, 0x6e, 0x3e, 0xa5, 0x62, 0xd0, 0x23, 0xe7, 0xf1, 0x7d, 0xff, 0x7b,
+ 0x36, 0x9e, 0xe7, 0xd6, 0x2c, 0x5f, 0x61, 0xe6, 0x3d, 0x62, 0xfb, 0x30,
+ 0xb7, 0xe8, 0xf8, 0x78, 0x79, 0x58, 0x9b, 0x27, 0x50, 0xa3, 0xfc, 0x22,
+ 0x2f, 0xc5, 0x24, 0x29, 0x58, 0xbd, 0xa6, 0xe2, 0xc5, 0xfa, 0x4a, 0x7d,
+ 0xc5, 0x8b, 0xb8, 0x3c, 0x3e, 0xa7, 0x26, 0xf8, 0xed, 0x9c, 0xd4, 0x6f,
+ 0x75, 0x0a, 0x5b, 0xff, 0xfb, 0xf3, 0xfd, 0xdf, 0x98, 0x32, 0xc8, 0xa2,
+ 0x9d, 0x96, 0x2f, 0xc7, 0x06, 0xb3, 0xa5, 0x8a, 0x1a, 0x22, 0x31, 0x7a,
+ 0xfd, 0xa7, 0x17, 0x7f, 0x2b, 0x17, 0xfb, 0x59, 0xd7, 0x00, 0xde, 0x58,
+ 0xbf, 0xce, 0x5e, 0x90, 0x7b, 0x8b, 0x17, 0x4f, 0x4b, 0x15, 0x03, 0xcb,
+ 0x08, 0xce, 0xff, 0xe2, 0x98, 0x89, 0xe2, 0xf3, 0xf4, 0x12, 0xc5, 0x44,
+ 0x7d, 0x5e, 0x23, 0xa9, 0x4c, 0xe8, 0xd2, 0xde, 0x43, 0xaa, 0xc2, 0xd9,
+ 0x39, 0x2d, 0xe3, 0x5c, 0xbe, 0x83, 0x74, 0x12, 0xc5, 0x2c, 0x54, 0x9b,
+ 0x11, 0x92, 0xdf, 0xf1, 0x9a, 0xd6, 0x7f, 0xa8, 0x71, 0x62, 0xff, 0xff,
+ 0x67, 0x04, 0xdd, 0x66, 0x11, 0xbc, 0xe6, 0x17, 0xb8, 0xb1, 0x7f, 0xd0,
+ 0x72, 0xf7, 0xf2, 0x11, 0xcb, 0x15, 0xba, 0x36, 0xba, 0x3d, 0x3b, 0x0d,
+ 0xfa, 0x0e, 0x3c, 0x3a, 0xc5, 0xc6, 0xf6, 0x58, 0xbf, 0xfb, 0xef, 0xf2,
+ 0x16, 0xdb, 0xce, 0x8d, 0x58, 0xbf, 0xef, 0x6a, 0x73, 0xae, 0xfb, 0xef,
+ 0x91, 0xa2, 0xc5, 0xf1, 0xd9, 0x86, 0xb1, 0x7f, 0xde, 0x14, 0xe6, 0xdd,
+ 0xf7, 0xdf, 0x23, 0x45, 0x8b, 0x98, 0x23, 0x13, 0x47, 0x19, 0x46, 0xe3,
+ 0x7d, 0x24, 0x71, 0x34, 0x32, 0x2b, 0xa1, 0x05, 0x8a, 0x96, 0x40, 0xb6,
+ 0x4a, 0x77, 0x79, 0x49, 0x3a, 0x63, 0x68, 0x7d, 0x14, 0x6f, 0x3e, 0x68,
+ 0xbf, 0xfb, 0xed, 0xad, 0x49, 0xff, 0xd3, 0x47, 0xac, 0x5f, 0xbb, 0xbb,
+ 0xa7, 0xae, 0x2c, 0x56, 0x1f, 0xce, 0x92, 0x6f, 0xbd, 0xc1, 0x41, 0x62,
+ 0xff, 0xd3, 0xd0, 0x31, 0xdb, 0xb4, 0xe9, 0x62, 0xfc, 0x28, 0xec, 0xd0,
+ 0x16, 0x2f, 0xda, 0x01, 0xda, 0x0b, 0x15, 0x88, 0xda, 0x62, 0x12, 0x24,
+ 0xe2, 0x00, 0x65, 0x96, 0xd9, 0x62, 0xfc, 0x66, 0x44, 0xe7, 0x58, 0xbf,
+ 0x80, 0xd0, 0xd9, 0xb6, 0x58, 0xbe, 0x9e, 0xb0, 0x96, 0x2f, 0xd0, 0x72,
+ 0x03, 0xac, 0x5d, 0xd7, 0xb6, 0x3c, 0x9c, 0x22, 0xbf, 0x85, 0xb3, 0x90,
+ 0x8e, 0xb1, 0x52, 0x7b, 0xc4, 0x5f, 0x7c, 0x7f, 0xcf, 0x65, 0x8b, 0xff,
+ 0x74, 0x6b, 0x73, 0xc4, 0xfd, 0x71, 0x62, 0xa4, 0xf9, 0xd8, 0x96, 0xff,
+ 0xfe, 0x67, 0xf4, 0xfd, 0xfd, 0xc9, 0x28, 0x31, 0x01, 0x62, 0xff, 0x31,
+ 0x67, 0x8a, 0x60, 0xb1, 0x7f, 0xf8, 0x52, 0x67, 0x77, 0x9f, 0x9f, 0xe9,
+ 0x82, 0x58, 0xbf, 0xdd, 0x7d, 0xbd, 0xa7, 0xe9, 0x62, 0xb6, 0x55, 0x71,
+ 0x85, 0x4f, 0x0d, 0x7d, 0x42, 0x1f, 0xe4, 0x04, 0xb1, 0xc3, 0x10, 0xd4,
+ 0x6f, 0xfd, 0x83, 0xfb, 0x46, 0x4f, 0xe7, 0xa5, 0x8b, 0xfe, 0xfb, 0x71,
+ 0xc8, 0xa7, 0xa5, 0x8b, 0xdf, 0x63, 0xac, 0x52, 0xc7, 0x7a, 0xaf, 0x7b,
+ 0x52, 0xb2, 0xce, 0xf9, 0xc4, 0x2f, 0x1c, 0x5f, 0xf1, 0x1b, 0xa2, 0x7d,
+ 0xc4, 0x4b, 0x17, 0x84, 0xc1, 0xac, 0x5f, 0xbd, 0x38, 0x52, 0xb1, 0x4e,
+ 0x7f, 0xda, 0x3a, 0x21, 0xeb, 0xc1, 0x97, 0x96, 0x2e, 0x3b, 0x2c, 0x5c,
+ 0xfb, 0x2c, 0x53, 0x9a, 0xff, 0x8b, 0xdf, 0xfe, 0xfb, 0xc7, 0xbe, 0xd3,
+ 0xe9, 0x8a, 0x7a, 0x58, 0xbf, 0xd8, 0xe6, 0xb8, 0xd8, 0xeb, 0x17, 0xf6,
+ 0xba, 0xe6, 0x11, 0xab, 0x14, 0x62, 0x2c, 0x86, 0x9e, 0x19, 0x9d, 0xe9,
+ 0x03, 0xac, 0x56, 0xc9, 0xb6, 0x9a, 0x9a, 0x78, 0x69, 0x04, 0x65, 0x7f,
+ 0xe9, 0x7e, 0x4f, 0xb9, 0x3f, 0x95, 0x8b, 0xfe, 0x33, 0x93, 0xa6, 0x83,
+ 0xfd, 0x62, 0xff, 0xb7, 0x16, 0x3f, 0x5e, 0x93, 0xac, 0x59, 0xf8, 0x7e,
+ 0xa2, 0x3a, 0xbf, 0xec, 0xd8, 0xa4, 0xdc, 0xeb, 0xcb, 0x14, 0x6a, 0x62,
+ 0x87, 0x85, 0x90, 0x64, 0xf7, 0xed, 0xf1, 0xf8, 0x75, 0x8b, 0xff, 0xb9,
+ 0x25, 0xe0, 0xe2, 0xfb, 0xfb, 0x8b, 0x17, 0xd9, 0xa9, 0xec, 0xb1, 0x5d,
+ 0x1f, 0x5f, 0x91, 0xef, 0xe8, 0x4e, 0xd3, 0xc1, 0x2c, 0x5f, 0xff, 0x8f,
+ 0x30, 0xcd, 0xc6, 0xe5, 0x9a, 0xde, 0x71, 0x62, 0xdb, 0xc4, 0x88, 0x40,
+ 0x17, 0xd7, 0x48, 0xd2, 0x28, 0x53, 0xd1, 0xd3, 0x8e, 0x68, 0xd9, 0xaa,
+ 0x57, 0x70, 0x72, 0x1b, 0xcf, 0x1c, 0xd3, 0x46, 0xb4, 0x28, 0xf1, 0xaf,
+ 0x77, 0x4f, 0x4b, 0x17, 0xf8, 0xb0, 0x1c, 0x0d, 0xbc, 0xb1, 0x7b, 0xcc,
+ 0x35, 0x8b, 0xb0, 0xeb, 0x17, 0xda, 0xda, 0x60, 0xb1, 0x52, 0x6e, 0xf0,
+ 0x5e, 0xfe, 0xf1, 0x49, 0xf9, 0xde, 0xac, 0x5c, 0xf8, 0xb1, 0x7e, 0x91,
+ 0xbc, 0xf7, 0x2c, 0x5f, 0xb3, 0x5a, 0x68, 0x2c, 0x5f, 0xb5, 0xa7, 0x8b,
+ 0x8b, 0x15, 0x03, 0xd2, 0xc2, 0x8a, 0x8d, 0x91, 0xcd, 0x03, 0x3f, 0x8b,
+ 0x79, 0xf2, 0xed, 0xa5, 0x62, 0xff, 0x9f, 0x0d, 0x7d, 0x78, 0xa5, 0x62,
+ 0x8e, 0x7a, 0x1c, 0x18, 0xbf, 0xd8, 0x53, 0xd7, 0x1b, 0x75, 0x8a, 0x35,
+ 0x1d, 0x1b, 0xc2, 0x48, 0x22, 0x2b, 0xdc, 0x86, 0xeb, 0x17, 0xd3, 0x1f,
+ 0xa9, 0x58, 0xac, 0x3c, 0x4e, 0x0f, 0xde, 0x01, 0xfc, 0xb1, 0x50, 0x56,
+ 0xaa, 0xe4, 0x31, 0x1a, 0x1d, 0x61, 0xa3, 0xed, 0x03, 0xe1, 0x10, 0xde,
+ 0xde, 0x0c, 0xb1, 0x7f, 0xc7, 0x9d, 0xdf, 0xda, 0x11, 0xd6, 0x2f, 0xda,
+ 0x70, 0x06, 0x75, 0x8a, 0x31, 0x10, 0x78, 0x3d, 0xa3, 0xbb, 0xf7, 0xdb,
+ 0x61, 0xf6, 0x58, 0xbf, 0xb0, 0x7f, 0x6c, 0xd2, 0xc5, 0xfd, 0xa9, 0x78,
+ 0x37, 0x16, 0x2d, 0xdc, 0xb1, 0x76, 0x9f, 0x63, 0xc2, 0x88, 0xb6, 0xff,
+ 0xcd, 0x98, 0x46, 0x87, 0xe1, 0x0d, 0x62, 0xff, 0x33, 0x8d, 0xf3, 0xaf,
+ 0x2c, 0x5e, 0x89, 0x86, 0xb1, 0x7b, 0xb9, 0xfb, 0x2c, 0x5b, 0x6d, 0x23,
+ 0x8b, 0xe5, 0xfe, 0x40, 0x11, 0x9f, 0x70, 0xf5, 0xe7, 0xeb, 0x8b, 0x17,
+ 0xff, 0x72, 0x76, 0xcd, 0x44, 0x52, 0x0e, 0x2c, 0x5f, 0xfd, 0xdf, 0x94,
+ 0x9f, 0x58, 0xff, 0x91, 0xac, 0x5f, 0xe7, 0xfe, 0x6b, 0x59, 0xd2, 0xc5,
+ 0xfa, 0x22, 0x9d, 0x41, 0x62, 0xd3, 0x03, 0xdd, 0xc3, 0x4b, 0xff, 0x88,
+ 0x5b, 0xb9, 0xbc, 0xfc, 0x97, 0x96, 0x2f, 0x61, 0x6e, 0xb1, 0x73, 0x85,
+ 0x87, 0xc6, 0x1a, 0x35, 0x41, 0x5e, 0x0e, 0xe6, 0x1f, 0x2c, 0x68, 0xd4,
+ 0x40, 0xa9, 0xe1, 0xe1, 0x23, 0x05, 0x0a, 0x5e, 0xe8, 0x44, 0xdf, 0x69,
+ 0xa1, 0x12, 0xc5, 0xff, 0xba, 0xf6, 0x14, 0x83, 0x08, 0x0b, 0x17, 0xdc,
+ 0x90, 0x77, 0x8b, 0x15, 0x87, 0xcd, 0xc3, 0xea, 0x35, 0x15, 0x61, 0x42,
+ 0x2a, 0xfb, 0xf8, 0x06, 0x58, 0xa9, 0x4e, 0x2d, 0xa3, 0x3f, 0xe1, 0x55,
+ 0xfb, 0x82, 0x79, 0x89, 0x62, 0xfd, 0xc7, 0x2f, 0x3a, 0xc5, 0xfb, 0xcf,
+ 0xbb, 0x41, 0x62, 0xe3, 0x78, 0xb1, 0x6d, 0x4a, 0x24, 0xa2, 0x29, 0x62,
+ 0x7e, 0x14, 0xdf, 0xfa, 0x0e, 0x70, 0xb0, 0x87, 0xf9, 0x58, 0xbf, 0xf8,
+ 0xa7, 0xd9, 0x9a, 0xd6, 0x4e, 0xeb, 0x17, 0xf8, 0xdc, 0xd0, 0x0e, 0xfc,
+ 0x58, 0xae, 0x91, 0x6f, 0xf3, 0xf2, 0x43, 0xbd, 0xb0, 0xa0, 0xb1, 0x7f,
+ 0x3f, 0x40, 0xd3, 0x0d, 0x62, 0xb0, 0xf3, 0xbe, 0x3f, 0x68, 0x96, 0x2f,
+ 0xba, 0x06, 0xa5, 0x22, 0xe0, 0x82, 0x48, 0xa9, 0x37, 0xc1, 0x12, 0x59,
+ 0xd2, 0x23, 0x0d, 0x0d, 0x7d, 0x12, 0xc4, 0xe5, 0x7f, 0xe1, 0x8b, 0xcf,
+ 0xf7, 0x37, 0xee, 0xb1, 0x7f, 0xff, 0xcf, 0x1f, 0x23, 0x31, 0xa7, 0xad,
+ 0xff, 0x3d, 0x71, 0xa7, 0xb9, 0x62, 0xff, 0xff, 0x67, 0x74, 0xc4, 0xe7,
+ 0x98, 0x8c, 0x2e, 0xa1, 0xf1, 0x01, 0x62, 0xe2, 0x8c, 0x94, 0x6b, 0xe3,
+ 0x7d, 0xe2, 0x68, 0x2c, 0x5c, 0xd1, 0x2c, 0x56, 0xe6, 0xd0, 0xe3, 0x97,
+ 0x3e, 0xeb, 0x17, 0xf8, 0x02, 0xf1, 0x4f, 0xb8, 0xb1, 0x6e, 0xe5, 0x8b,
+ 0xe6, 0x30, 0x33, 0xac, 0x53, 0x1f, 0x77, 0x63, 0x40, 0x85, 0x6f, 0xe1,
+ 0xbf, 0x6f, 0xe7, 0x72, 0xc5, 0xa2, 0x58, 0xb9, 0xfb, 0x2c, 0x56, 0x1e,
+ 0xfb, 0x99, 0xf6, 0x13, 0xa5, 0x8b, 0xb6, 0x25, 0x8b, 0xdc, 0xcd, 0x2c,
+ 0x5e, 0xdd, 0xf4, 0xb1, 0x76, 0x7d, 0x62, 0xba, 0x36, 0xb1, 0xc3, 0xd7,
+ 0x6a, 0x06, 0x2e, 0x2a, 0xc2, 0x16, 0xf8, 0x45, 0xd4, 0x62, 0xee, 0xc7,
+ 0xa2, 0x2f, 0xc2, 0x19, 0xa1, 0x20, 0x02, 0xfe, 0xfc, 0x33, 0x83, 0x1e,
+ 0x52, 0xbd, 0xcf, 0xb2, 0xc5, 0x4a, 0xed, 0xeb, 0x4e, 0x69, 0xfa, 0x19,
+ 0xb7, 0xde, 0xf3, 0x1d, 0x62, 0xfc, 0x50, 0xdc, 0x5b, 0x2c, 0x5e, 0x9d,
+ 0x44, 0xb1, 0x4c, 0x79, 0x22, 0x2b, 0xbf, 0xfd, 0xaf, 0x16, 0x6c, 0xc5,
+ 0xa1, 0x48, 0x16, 0x2f, 0xff, 0xef, 0x4e, 0xe4, 0x23, 0xe4, 0x3f, 0x84,
+ 0x14, 0xe9, 0x62, 0xb4, 0x8a, 0x62, 0x4a, 0xbf, 0x1c, 0x9b, 0xdc, 0x58,
+ 0xa6, 0x3c, 0xa0, 0xc8, 0xa8, 0xc7, 0xc2, 0xd6, 0x8d, 0x21, 0x15, 0x33,
+ 0xb7, 0xfb, 0x43, 0x5a, 0x04, 0x63, 0x84, 0xf6, 0x53, 0xa7, 0xba, 0x8f,
+ 0x15, 0xe5, 0x7c, 0x6a, 0x91, 0x3a, 0x78, 0xf3, 0xff, 0x49, 0xe7, 0x69,
+ 0x76, 0xa5, 0x3c, 0x73, 0xe8, 0x63, 0x8a, 0x7a, 0xdb, 0xb1, 0xf0, 0x4d,
+ 0x81, 0xc6, 0x23, 0x77, 0xb6, 0x58, 0xbf, 0x9b, 0x79, 0x8e, 0xce, 0x96,
+ 0x2a, 0x07, 0x97, 0xf1, 0x9b, 0xf9, 0xff, 0x3b, 0x93, 0x2c, 0x5c, 0xe1,
+ 0x2c, 0x54, 0x0f, 0x17, 0xc5, 0xb6, 0x35, 0x62, 0xfd, 0x1c, 0x2f, 0xbe,
+ 0x96, 0x2f, 0xe9, 0x0b, 0x42, 0x90, 0x2c, 0x56, 0xc7, 0xb7, 0xe2, 0xcb,
+ 0xfc, 0x50, 0xe0, 0xfe, 0xe1, 0x2c, 0x5e, 0xd9, 0x8e, 0xb1, 0x7d, 0x83,
+ 0x63, 0xac, 0x5d, 0xd1, 0x2c, 0x5f, 0xba, 0x87, 0xc3, 0xe2, 0xc5, 0x61,
+ 0xe2, 0x10, 0xc5, 0xfb, 0x06, 0x42, 0x3a, 0xc5, 0x69, 0x15, 0xcc, 0xcc,
+ 0x44, 0x17, 0x38, 0xd6, 0x2f, 0xc5, 0x3f, 0x6e, 0x2c, 0x5a, 0x25, 0x8b,
+ 0x8f, 0x2b, 0x17, 0xbc, 0xe1, 0x2e, 0x50, 0x82, 0xe6, 0x0d, 0x52, 0x03,
+ 0x9d, 0x1a, 0xba, 0x31, 0x11, 0x6e, 0x26, 0x24, 0x2a, 0x82, 0x64, 0xff,
+ 0x2e, 0xef, 0xc5, 0xfd, 0x0b, 0x2a, 0x31, 0x58, 0x0c, 0xb7, 0x39, 0x1b,
+ 0x1a, 0x8a, 0x3f, 0x3b, 0xd3, 0xb4, 0xac, 0x5f, 0xfd, 0x30, 0xcf, 0xb7,
+ 0x40, 0xce, 0xbc, 0xb1, 0x70, 0x30, 0x8f, 0x8f, 0x83, 0xb7, 0xf0, 0x9b,
+ 0xbb, 0xf9, 0xb2, 0xc5, 0xfe, 0x17, 0xdf, 0x59, 0xd7, 0x96, 0x2f, 0xef,
+ 0x63, 0xc7, 0x7e, 0x56, 0x2d, 0xc3, 0x11, 0x2f, 0x1c, 0x64, 0x19, 0xad,
+ 0xda, 0xef, 0xd6, 0x2b, 0x49, 0x8d, 0x82, 0x18, 0x64, 0x77, 0x7f, 0x61,
+ 0x03, 0x30, 0x6b, 0x17, 0xf3, 0x83, 0x0f, 0x3b, 0xac, 0x5c, 0xc1, 0x2c,
+ 0x5e, 0x36, 0x11, 0xeb, 0x17, 0xdd, 0x71, 0xd9, 0x62, 0xcc, 0x61, 0xe2,
+ 0xb9, 0x15, 0xff, 0xef, 0x14, 0xe7, 0x67, 0xf4, 0xe1, 0x41, 0x62, 0x8d,
+ 0x3f, 0x07, 0x27, 0xbf, 0xfb, 0x3b, 0x6a, 0x5a, 0x05, 0x3d, 0x41, 0x62,
+ 0xff, 0xff, 0xd0, 0xdf, 0xef, 0xad, 0x8f, 0x3b, 0xfe, 0x5c, 0x73, 0xf9,
+ 0x82, 0xc5, 0xef, 0xc9, 0xab, 0x15, 0xd2, 0x23, 0x7b, 0x37, 0xdf, 0xc0,
+ 0xd6, 0x9f, 0xa0, 0x2c, 0x5f, 0xfd, 0x09, 0x20, 0x66, 0x80, 0x77, 0xe2,
+ 0xc5, 0xfe, 0xcd, 0xe7, 0x62, 0x9d, 0xd6, 0x2f, 0xdb, 0x94, 0xf5, 0x05,
+ 0x8b, 0x01, 0x62, 0xd1, 0xe6, 0x1f, 0x8e, 0x1a, 0xb9, 0x55, 0xe9, 0x3c,
+ 0xac, 0x5f, 0xb3, 0xdc, 0x6e, 0x96, 0x2f, 0xff, 0x73, 0x3e, 0xfc, 0x16,
+ 0xc6, 0x45, 0x24, 0xb1, 0x74, 0x89, 0x62, 0xfc, 0x22, 0x00, 0x70, 0x58,
+ 0xbf, 0xdf, 0x90, 0x1d, 0xa0, 0x66, 0x1e, 0x0f, 0x05, 0xe8, 0x69, 0x80,
+ 0xf0, 0xa4, 0x38, 0x47, 0x5f, 0xff, 0x8a, 0x61, 0x9f, 0x6d, 0x4f, 0x9c,
+ 0x13, 0x05, 0x8b, 0xfd, 0x20, 0x8a, 0x0e, 0x2e, 0xfd, 0x62, 0xec, 0xe1,
+ 0x88, 0xc4, 0x19, 0xb8, 0x6a, 0x74, 0x35, 0x43, 0xc5, 0x1f, 0x0d, 0x0d,
+ 0x75, 0x30, 0xd8, 0x66, 0xfc, 0x89, 0xa1, 0xa6, 0x44, 0xde, 0x30, 0x14,
+ 0x2d, 0x7b, 0x4a, 0x55, 0xbf, 0xfb, 0x4f, 0xd0, 0x7e, 0xc7, 0x83, 0x71,
+ 0x62, 0xff, 0x85, 0xb4, 0x99, 0x3e, 0x91, 0xac, 0x56, 0x91, 0x03, 0xf4,
+ 0x6b, 0xee, 0xee, 0xe9, 0x8f, 0x58, 0xbf, 0xff, 0x4f, 0xbf, 0x83, 0xf6,
+ 0x7c, 0xb3, 0xdf, 0x75, 0x8b, 0x49, 0x88, 0x80, 0xd1, 0x65, 0xf3, 0x40,
+ 0x07, 0x58, 0xbf, 0xff, 0xa4, 0x3d, 0x39, 0xe4, 0xde, 0x7d, 0xfc, 0x52,
+ 0x75, 0x8a, 0x39, 0xff, 0x80, 0x8e, 0xda, 0xd2, 0x32, 0x81, 0x0a, 0x8b,
+ 0xfe, 0x0f, 0xce, 0x42, 0x86, 0x71, 0x62, 0xf3, 0x6b, 0x65, 0x8b, 0x82,
+ 0x09, 0x62, 0xfe, 0x7c, 0xec, 0x1c, 0x23, 0x37, 0x37, 0x01, 0x0f, 0x56,
+ 0xe8, 0xbd, 0xd3, 0x95, 0xf1, 0x37, 0x40, 0x58, 0xbf, 0xb8, 0x20, 0x1e,
+ 0x60, 0xb1, 0x7f, 0x41, 0xdb, 0xb7, 0xdd, 0x62, 0xf4, 0xff, 0x8b, 0x17,
+ 0x39, 0xa6, 0x1f, 0xde, 0x17, 0x80, 0xbe, 0xf1, 0xa1, 0x01, 0x62, 0xff,
+ 0x73, 0x3c, 0xc7, 0xc2, 0x58, 0xa1, 0xab, 0xa7, 0x78, 0xdb, 0x75, 0x0e,
+ 0xb3, 0x92, 0x7e, 0x13, 0xc4, 0x77, 0xe2, 0x0b, 0xff, 0x73, 0x0b, 0x3f,
+ 0x9b, 0xe1, 0x2c, 0x5f, 0xfe, 0x7e, 0x61, 0x18, 0x1e, 0xa2, 0xcc, 0x09,
+ 0x62, 0xfb, 0x4f, 0x27, 0x58, 0xbf, 0xdc, 0xf7, 0xf0, 0xf9, 0x05, 0x8b,
+ 0xff, 0xc2, 0x91, 0xe7, 0x80, 0x19, 0x43, 0xf8, 0xb1, 0x74, 0xf1, 0x62,
+ 0xd2, 0xb1, 0x7f, 0xe8, 0xd2, 0x79, 0xcc, 0xf7, 0xda, 0x0b, 0x17, 0xff,
+ 0xde, 0xe4, 0xfb, 0xa9, 0xff, 0xe7, 0xb4, 0xf1, 0x62, 0xbb, 0xd4, 0x4b,
+ 0xe2, 0x25, 0xec, 0x04, 0x70, 0xd1, 0x9f, 0x90, 0xa8, 0xa8, 0x27, 0x40,
+ 0x33, 0x40, 0x25, 0x94, 0x39, 0xaf, 0xff, 0xed, 0x64, 0x23, 0xb3, 0x7f,
+ 0xb8, 0xca, 0x42, 0xc2, 0x58, 0xbe, 0x09, 0x83, 0x3a, 0xc5, 0xe6, 0xea,
+ 0x56, 0x2f, 0xd8, 0x6f, 0xda, 0x1f, 0x3c, 0x20, 0xc9, 0x6a, 0x0a, 0xdb,
+ 0x86, 0x7a, 0x6a, 0x6b, 0xc7, 0x85, 0xa4, 0x22, 0x85, 0x05, 0x4a, 0xe2,
+ 0x2e, 0x4b, 0xe2, 0xbf, 0xdd, 0x82, 0xc2, 0x1f, 0xe5, 0x62, 0xfc, 0x37,
+ 0xed, 0x23, 0x58, 0xbe, 0x7e, 0xd2, 0x35, 0x8b, 0xb0, 0x06, 0x1e, 0x70,
+ 0xca, 0xaf, 0xe7, 0x1e, 0xb0, 0xf8, 0xb1, 0x7f, 0xde, 0xe0, 0x7a, 0x9f,
+ 0x4c, 0x16, 0x2f, 0xb7, 0x66, 0xdd, 0x52, 0x0c, 0x17, 0xf9, 0xe7, 0x50,
+ 0x14, 0xe2, 0xc5, 0x18, 0x89, 0xed, 0x1d, 0x91, 0x8d, 0xf1, 0xb2, 0x50,
+ 0x58, 0xbe, 0x39, 0xda, 0x06, 0x26, 0x3d, 0x90, 0xcb, 0xf1, 0x85, 0xff,
+ 0x8b, 0x36, 0xd3, 0x84, 0x79, 0xe2, 0xc5, 0xff, 0xfc, 0xe3, 0xee, 0x9c,
+ 0xd6, 0xd2, 0x32, 0x63, 0x4d, 0x95, 0x8a, 0x35, 0x13, 0xfd, 0x90, 0x2f,
+ 0xf9, 0xc0, 0xc5, 0xe6, 0x6f, 0xac, 0x5f, 0x6e, 0xcd, 0xba, 0xe5, 0x11,
+ 0x2f, 0xff, 0xf6, 0x6f, 0xf9, 0xea, 0x11, 0xd9, 0xfd, 0xdf, 0x09, 0x8d,
+ 0x58, 0xad, 0x22, 0x5c, 0x8c, 0x6e, 0xdc, 0x0b, 0x17, 0x0f, 0xa5, 0x8b,
+ 0x9b, 0x90, 0x4c, 0x8b, 0x21, 0x9c, 0x72, 0x22, 0x19, 0xa9, 0x57, 0x99,
+ 0x91, 0xa6, 0x34, 0x3b, 0x05, 0x1a, 0x45, 0x2c, 0x52, 0xc5, 0xb6, 0x11,
+ 0x71, 0x1c, 0x19, 0x7f, 0xb9, 0xe6, 0xea, 0x39, 0xcd, 0x58, 0xbf, 0x64,
+ 0x52, 0x43, 0x58, 0xa9, 0x3e, 0x1d, 0x1c, 0xd4, 0xb6, 0x8b, 0xf0, 0x35,
+ 0xc2, 0xc7, 0x9d, 0x7a, 0xfd, 0x23, 0xe1, 0x8a, 0xca, 0x71, 0x43, 0xcc,
+ 0xa2, 0x84, 0x5d, 0xf8, 0xa4, 0x1d, 0x01, 0x62, 0xfd, 0x90, 0x9d, 0x01,
+ 0x62, 0xff, 0xed, 0xbf, 0x2f, 0xee, 0x4e, 0xd9, 0xc5, 0x8b, 0xa4, 0x35,
+ 0x8b, 0xf3, 0x6c, 0x53, 0x04, 0x8a, 0x88, 0xf0, 0x3e, 0x31, 0x7f, 0xe9,
+ 0xd0, 0x39, 0x91, 0xbc, 0x6f, 0xdf, 0x3b, 0xc5, 0x8b, 0xfa, 0x7c, 0x52,
+ 0x0e, 0x2c, 0x5f, 0xe6, 0x7f, 0x4e, 0xa4, 0x0b, 0x17, 0xef, 0x61, 0xdf,
+ 0xcb, 0x17, 0xfe, 0xf1, 0x48, 0x06, 0x4f, 0xd7, 0x96, 0x2d, 0xe3, 0x11,
+ 0x8d, 0xf2, 0xd6, 0x32, 0x0c, 0xa2, 0xf9, 0x88, 0x3d, 0x96, 0x2f, 0xe6,
+ 0x37, 0x06, 0xe4, 0xb1, 0x5f, 0x3d, 0x12, 0x24, 0xa8, 0x2a, 0xcb, 0x34,
+ 0xa7, 0x45, 0x07, 0x84, 0x37, 0xc8, 0xca, 0x31, 0xb0, 0xa1, 0x2b, 0x7f,
+ 0xe7, 0xde, 0x78, 0xda, 0xd3, 0x84, 0xb1, 0x7c, 0x43, 0xfc, 0xac, 0x5f,
+ 0xf6, 0xd0, 0x3c, 0xfd, 0x9c, 0xd5, 0x8b, 0xff, 0x67, 0x27, 0xed, 0xe0,
+ 0xe4, 0x6b, 0x17, 0xfc, 0xcc, 0x17, 0xd8, 0xef, 0xc5, 0x8b, 0xff, 0x79,
+ 0xcb, 0x6c, 0xeb, 0xdf, 0x65, 0x8b, 0xff, 0x9f, 0x46, 0xef, 0xf7, 0xf9,
+ 0x0b, 0x65, 0x8a, 0x94, 0xc0, 0x06, 0x7f, 0x87, 0x20, 0x40, 0xbf, 0xff,
+ 0xa4, 0x27, 0x98, 0x9f, 0x0c, 0xcf, 0xbe, 0xbe, 0xcb, 0x17, 0xfd, 0xac,
+ 0xe7, 0x38, 0xc5, 0x05, 0x8b, 0xa1, 0xb2, 0xc5, 0xb7, 0x31, 0x15, 0xba,
+ 0x5b, 0x39, 0xcd, 0xff, 0xfc, 0x3d, 0x13, 0x04, 0x63, 0xea, 0x4b, 0x3f,
+ 0x9b, 0xac, 0x53, 0x2a, 0xda, 0x22, 0x2e, 0x46, 0x76, 0x28, 0x74, 0x84,
+ 0x71, 0x7c, 0x2c, 0xe3, 0xac, 0x5d, 0xc1, 0x2c, 0x5f, 0xd0, 0xfb, 0x31,
+ 0x4a, 0xc5, 0xa7, 0x73, 0xc4, 0xe8, 0x62, 0xfc, 0x2f, 0x68, 0x50, 0x58,
+ 0xbf, 0xe9, 0xfb, 0xe1, 0xa6, 0xcc, 0x16, 0x2d, 0x84, 0x7c, 0x9e, 0x2a,
+ 0xbe, 0xdd, 0x9b, 0x75, 0x48, 0x14, 0x5b, 0x4b, 0x15, 0xa3, 0xc3, 0xf1,
+ 0x8d, 0xef, 0xc9, 0xd6, 0x2f, 0x99, 0xa1, 0xc5, 0x8b, 0xff, 0x4e, 0xcd,
+ 0xed, 0x64, 0x23, 0xb1, 0x62, 0xe7, 0xd2, 0xc5, 0xfe, 0xf4, 0x9f, 0xdc,
+ 0x60, 0x2c, 0x56, 0xc7, 0x97, 0x82, 0xf4, 0x34, 0xde, 0x71, 0xa5, 0xc8,
+ 0xb4, 0x3a, 0x44, 0x5c, 0x84, 0x6d, 0xfb, 0xf2, 0x71, 0x74, 0xb1, 0x7b,
+ 0x93, 0xd2, 0xc5, 0xf7, 0xb9, 0x20, 0x48, 0xbc, 0xda, 0xd9, 0x22, 0xf8,
+ 0x44, 0xc6, 0xa4, 0x5f, 0xe7, 0xdb, 0x3d, 0xc9, 0x02, 0x45, 0x24, 0x5f,
+ 0xd9, 0xbc, 0xfe, 0x4e, 0x91, 0x70, 0x41, 0x24, 0x5f, 0xc5, 0x25, 0xb3,
+ 0xe9, 0x22, 0xb1, 0x31, 0x9d, 0xc8, 0xce, 0x3d, 0xf2, 0x30, 0x1a, 0x10,
+ 0x60, 0x45, 0xc1, 0x8d, 0x52, 0xc5, 0xb4, 0x91, 0x18, 0x7f, 0xf2, 0xe7,
+ 0x7a, 0x0f, 0xf5, 0x8a, 0x58, 0xae, 0x95, 0x08, 0xbc, 0x76, 0xcc, 0x64,
+ 0x18, 0xed, 0x41, 0x56, 0xd4, 0x4b, 0x5f, 0x94, 0x77, 0x7f, 0xfc, 0x17,
+ 0x0b, 0x3a, 0xf3, 0x16, 0xd9, 0xd7, 0x96, 0x2f, 0xee, 0xc6, 0x34, 0x21,
+ 0x8b, 0x15, 0x28, 0x84, 0xc5, 0x3b, 0xff, 0xf1, 0x67, 0x84, 0x03, 0xb4,
+ 0x03, 0x3c, 0x73, 0x9a, 0xb1, 0x73, 0x69, 0x62, 0xfd, 0xb6, 0x0e, 0x4e,
+ 0xb1, 0x7b, 0x79, 0x38, 0x47, 0x80, 0x18, 0xbd, 0xa5, 0x62, 0xcf, 0xf3,
+ 0xc7, 0xf1, 0xb5, 0x0d, 0x30, 0x9f, 0x43, 0x8a, 0xa5, 0x96, 0x7d, 0x8e,
+ 0xef, 0x2c, 0x6b, 0x4a, 0xdf, 0x66, 0x69, 0xce, 0x02, 0x85, 0xf0, 0xa3,
+ 0x2a, 0xbf, 0x66, 0x9e, 0x76, 0x58, 0xbd, 0x84, 0x05, 0x8a, 0xc3, 0xc4,
+ 0xe1, 0x45, 0xff, 0xfc, 0xd0, 0xf1, 0x4e, 0x75, 0x9b, 0xcf, 0xbe, 0xfd,
+ 0x96, 0x2e, 0x61, 0xac, 0x51, 0xa7, 0xe8, 0x75, 0xdb, 0x1d, 0x62, 0xe1,
+ 0x1a, 0xb1, 0x44, 0x6a, 0xf8, 0x25, 0x7f, 0xff, 0xc5, 0x9e, 0xf4, 0xf5,
+ 0x03, 0x3f, 0x27, 0x17, 0x5c, 0xfc, 0xac, 0x5f, 0xdf, 0x73, 0x4d, 0x9d,
+ 0x96, 0x2f, 0xec, 0x2e, 0x39, 0x62, 0xc5, 0xfc, 0x7c, 0x1f, 0xf3, 0x65,
+ 0x8b, 0xff, 0xc4, 0xc6, 0xf0, 0x1e, 0xf7, 0x5e, 0xcd, 0xd6, 0x2f, 0xde,
+ 0x33, 0xda, 0x95, 0x8a, 0x94, 0x53, 0x9a, 0x5f, 0xd2, 0x75, 0xef, 0x88,
+ 0xeb, 0x15, 0xb2, 0xab, 0xf3, 0x61, 0x2b, 0xd2, 0x74, 0x79, 0x06, 0x9a,
+ 0xbe, 0x62, 0x50, 0xd2, 0xee, 0x31, 0xbf, 0xfa, 0x28, 0x38, 0x3f, 0x9d,
+ 0xb1, 0x8e, 0xb1, 0x7f, 0x16, 0x73, 0x53, 0xc5, 0x8b, 0xc2, 0x86, 0x2c,
+ 0x51, 0x88, 0x91, 0x64, 0x70, 0x16, 0xdf, 0xb0, 0x9b, 0xdc, 0x58, 0xbe,
+ 0xfc, 0x94, 0x16, 0x2f, 0xd9, 0xf2, 0x68, 0x96, 0x28, 0x67, 0xe3, 0x84,
+ 0xe4, 0x45, 0x50, 0x46, 0x77, 0x21, 0x43, 0x7b, 0x42, 0xfa, 0xc5, 0xd9,
+ 0xf5, 0x8b, 0xe8, 0xbe, 0x2d, 0x96, 0x2a, 0x23, 0x7a, 0x18, 0xbd, 0xe2,
+ 0x93, 0xac, 0x56, 0x91, 0x34, 0xcb, 0x62, 0x23, 0xbd, 0xf9, 0x89, 0x62,
+ 0xfa, 0x13, 0x13, 0xac, 0x50, 0xcf, 0x07, 0xa1, 0xeb, 0xfb, 0xb3, 0xe9,
+ 0x82, 0xf2, 0xc5, 0xfb, 0xef, 0xe6, 0xfa, 0xc5, 0xfc, 0xf3, 0xac, 0xeb,
+ 0xcb, 0x17, 0xf6, 0x9c, 0xf9, 0xd7, 0x96, 0x2e, 0x61, 0xac, 0x54, 0x9e,
+ 0x36, 0xe5, 0xf7, 0xf3, 0x1b, 0x9b, 0x31, 0xd6, 0x2f, 0xf3, 0x93, 0x7a,
+ 0x27, 0x09, 0x62, 0xfc, 0xf1, 0x41, 0xc6, 0xb1, 0x52, 0x7b, 0xb8, 0x69,
+ 0x7f, 0xec, 0xc0, 0xb9, 0xd4, 0x94, 0xf1, 0x62, 0xda, 0x31, 0x53, 0x6c,
+ 0xb8, 0x61, 0x1e, 0xe6, 0x27, 0x28, 0xfb, 0xa1, 0x11, 0x72, 0x11, 0x9e,
+ 0x20, 0xa9, 0x57, 0x72, 0xf2, 0xcb, 0xef, 0x71, 0xa3, 0xd6, 0x2f, 0xcc,
+ 0x3f, 0xc9, 0x2c, 0x56, 0x1e, 0x39, 0xc8, 0x2f, 0xef, 0x13, 0x1e, 0x2e,
+ 0xfd, 0x62, 0xec, 0xfa, 0xc5, 0xff, 0xf6, 0xa7, 0x3a, 0x2c, 0xec, 0xd0,
+ 0xe3, 0x8d, 0x62, 0xb4, 0x7d, 0x1e, 0x17, 0xbe, 0xf0, 0xbd, 0xc5, 0x8b,
+ 0xd0, 0xcf, 0x2c, 0x5f, 0x76, 0x78, 0x71, 0x62, 0xba, 0x3c, 0x27, 0x1d,
+ 0xac, 0x44, 0x46, 0x99, 0xaf, 0xf3, 0xb7, 0xb3, 0x79, 0x02, 0xc5, 0xe8,
+ 0x3f, 0x65, 0x8b, 0xff, 0xce, 0x0e, 0x61, 0xac, 0x7d, 0x4e, 0x12, 0xc5,
+ 0x61, 0xf4, 0x30, 0xfd, 0xff, 0xc7, 0x6e, 0x8c, 0x14, 0x53, 0xc7, 0x8f,
+ 0x58, 0xbf, 0xee, 0xbc, 0x13, 0x6b, 0x4c, 0x6a, 0xc5, 0xe9, 0xf7, 0x16,
+ 0x2a, 0x4f, 0x68, 0x8f, 0x6b, 0x11, 0x8b, 0xe8, 0x52, 0xde, 0xdc, 0x30,
+ 0x2c, 0x5f, 0x8e, 0x2c, 0x71, 0xac, 0x5f, 0xed, 0x6d, 0x3d, 0x99, 0x8e,
+ 0xb1, 0x7f, 0xfb, 0x3b, 0x98, 0x8d, 0x1e, 0x3e, 0xb5, 0x2b, 0x17, 0x7b,
+ 0x98, 0x88, 0x2f, 0x9b, 0x54, 0xa3, 0xe0, 0xd2, 0x06, 0x85, 0x55, 0xf7,
+ 0xe7, 0xae, 0x2c, 0x5f, 0x3e, 0x75, 0xe5, 0x8a, 0xc3, 0xc7, 0xf1, 0x25,
+ 0xff, 0xff, 0x7d, 0xf5, 0x83, 0x63, 0xe1, 0x78, 0xa4, 0x2c, 0xf7, 0x16,
+ 0x2d, 0x2b, 0x17, 0xd3, 0xd8, 0x73, 0xb9, 0xfb, 0x01, 0x96, 0xfe, 0x6f,
+ 0x73, 0x0a, 0x0b, 0x17, 0xfd, 0xf7, 0x60, 0x6a, 0x5a, 0x0b, 0x17, 0x34,
+ 0x3e, 0x7c, 0xbe, 0x2d, 0xaf, 0xa3, 0x37, 0xd0, 0xa0, 0xbf, 0xff, 0xdd,
+ 0xfc, 0x96, 0xdc, 0xfb, 0x3f, 0x9c, 0x79, 0xcc, 0xd2, 0xc5, 0x2c, 0x5a,
+ 0x0b, 0x15, 0x02, 0xfb, 0xe1, 0x95, 0x05, 0xed, 0x2d, 0xc8, 0x7a, 0x84,
+ 0xe6, 0xa1, 0x54, 0x72, 0x2f, 0xc2, 0x6c, 0x10, 0xe5, 0x28, 0xc7, 0xf8,
+ 0xf7, 0xe8, 0xd9, 0x04, 0x50, 0x14, 0x20, 0xef, 0xe1, 0xfd, 0x83, 0xcd,
+ 0x96, 0x2f, 0xfb, 0xda, 0xcd, 0xbd, 0x39, 0xc5, 0x8b, 0xf9, 0xbf, 0x17,
+ 0x3e, 0x35, 0x8a, 0x01, 0xf5, 0x04, 0x75, 0x46, 0x22, 0xf7, 0x50, 0x9a,
+ 0xbf, 0x07, 0x0f, 0xc9, 0xab, 0x17, 0xdc, 0xfe, 0x71, 0x62, 0xfc, 0x44,
+ 0x2d, 0x1a, 0xb1, 0x71, 0x6c, 0x61, 0xfb, 0xe1, 0x58, 0x64, 0x75, 0x88,
+ 0xdc, 0x78, 0x50, 0x52, 0xc5, 0xda, 0xec, 0xb1, 0x58, 0x69, 0x98, 0x32,
+ 0xff, 0xfa, 0x40, 0x1e, 0x7f, 0xcf, 0xd0, 0x59, 0xd7, 0x96, 0x2f, 0xff,
+ 0xcc, 0x68, 0x7d, 0x02, 0x4b, 0x76, 0xf3, 0x74, 0x05, 0x8b, 0xdb, 0xe1,
+ 0xd6, 0x2f, 0xd3, 0xd1, 0x49, 0xab, 0x17, 0xff, 0xed, 0xe4, 0x5b, 0xfe,
+ 0x75, 0xf6, 0x1f, 0xdb, 0x4b, 0x14, 0x34, 0x40, 0xe1, 0x4d, 0xfc, 0x36,
+ 0xf7, 0x05, 0x05, 0x8a, 0x94, 0x78, 0x64, 0x27, 0xc3, 0x22, 0xb4, 0x09,
+ 0x37, 0xe8, 0xe8, 0xd2, 0xad, 0x1c, 0xb1, 0x7f, 0x36, 0xa7, 0xcf, 0xd9,
+ 0x62, 0xff, 0xee, 0x4c, 0x6d, 0x90, 0x7f, 0x70, 0x51, 0xeb, 0x15, 0xd2,
+ 0x30, 0xf4, 0x64, 0x42, 0xbc, 0x2f, 0xbf, 0xff, 0xf6, 0xb5, 0x3d, 0x43,
+ 0xae, 0x3e, 0xb7, 0xfe, 0x07, 0xa7, 0x91, 0xac, 0x5f, 0x88, 0xd0, 0xf3,
+ 0xa5, 0x8b, 0xfe, 0x6d, 0x67, 0x50, 0x90, 0x4a, 0xc5, 0x4a, 0x62, 0x58,
+ 0x7a, 0xee, 0x22, 0x2b, 0xbf, 0xee, 0xa1, 0xec, 0xe7, 0xb2, 0x3d, 0x62,
+ 0xff, 0xfd, 0xb9, 0xad, 0xcc, 0xd4, 0x1f, 0xec, 0x5d, 0x41, 0x62, 0xff,
+ 0xa7, 0xdc, 0xcf, 0x3f, 0x41, 0x2c, 0x5e, 0x16, 0x8d, 0x58, 0xad, 0xcf,
+ 0x6a, 0x38, 0xee, 0xb1, 0x1b, 0x06, 0xc2, 0xca, 0xa5, 0x33, 0xe6, 0x8c,
+ 0x5a, 0xa5, 0x90, 0x36, 0x39, 0x4d, 0x1b, 0xa6, 0x38, 0xff, 0xe5, 0xd3,
+ 0x94, 0x6f, 0x37, 0xef, 0x61, 0xda, 0x0b, 0x17, 0xc4, 0x2e, 0xd0, 0x58,
+ 0xa8, 0x1e, 0x6f, 0x0a, 0x2f, 0xbe, 0x4d, 0x05, 0x8b, 0x9b, 0x8b, 0x17,
+ 0xec, 0x2f, 0xe1, 0x2c, 0x5e, 0xd8, 0x3d, 0xd6, 0x2f, 0x3c, 0x51, 0xeb,
+ 0x17, 0xde, 0xc7, 0xfa, 0xc5, 0x11, 0xe1, 0xf7, 0x10, 0xd4, 0xa6, 0x12,
+ 0xe4, 0x51, 0x11, 0x7c, 0x5d, 0x89, 0xb8, 0xc9, 0x7f, 0xa4, 0xb7, 0x68,
+ 0xe6, 0xec, 0xb1, 0x73, 0x01, 0x62, 0xa0, 0x8a, 0x50, 0x2b, 0x78, 0xe2,
+ 0xff, 0xff, 0xe1, 0x7b, 0x9c, 0xf3, 0xe4, 0x47, 0x9e, 0x44, 0x58, 0x73,
+ 0x45, 0x2b, 0x17, 0xff, 0xc5, 0x9f, 0xc3, 0x3e, 0xcf, 0xc9, 0xed, 0x8b,
+ 0x17, 0xfd, 0x0c, 0xf1, 0xe7, 0x08, 0x6b, 0x17, 0xed, 0xff, 0x9d, 0x77,
+ 0x2c, 0x5f, 0xff, 0x99, 0xa0, 0xdf, 0x33, 0x36, 0x17, 0x84, 0xc1, 0xaa,
+ 0x4f, 0xb2, 0xf7, 0x61, 0x79, 0x62, 0xe9, 0x1a, 0xc5, 0x49, 0xb7, 0x01,
+ 0x05, 0xfc, 0xde, 0xe3, 0xf1, 0xd6, 0x2f, 0xdb, 0xed, 0xa1, 0x6c, 0xb1,
+ 0x7e, 0xde, 0x4a, 0x40, 0xb1, 0x58, 0x7a, 0xac, 0x5b, 0x7f, 0xa4, 0x6f,
+ 0xbb, 0x96, 0xcb, 0x17, 0xf6, 0xff, 0x92, 0x6e, 0xcb, 0x15, 0x27, 0xc9,
+ 0x86, 0x97, 0x3f, 0x72, 0xc5, 0xff, 0x39, 0x75, 0x0d, 0x0a, 0x78, 0xb1,
+ 0x76, 0x77, 0x2c, 0x50, 0x0f, 0xbb, 0x83, 0x41, 0x1d, 0x5f, 0xb3, 0x58,
+ 0x39, 0x58, 0xbd, 0xb8, 0xb6, 0x58, 0xb8, 0x5e, 0x58, 0xbf, 0x77, 0x66,
+ 0x10, 0x16, 0x28, 0x6b, 0x86, 0x9b, 0xba, 0xf4, 0xa1, 0x1e, 0x71, 0x11,
+ 0x76, 0xa1, 0x38, 0x72, 0x0f, 0xc2, 0x08, 0xa1, 0x09, 0xe8, 0x47, 0x76,
+ 0x30, 0x08, 0x9e, 0x38, 0x83, 0xb8, 0x62, 0xff, 0xfe, 0xf6, 0xb1, 0xbd,
+ 0xcc, 0xf1, 0x33, 0x6d, 0x9b, 0xac, 0x5f, 0xbf, 0x91, 0x4c, 0x7a, 0xc5,
+ 0xef, 0x66, 0xeb, 0x17, 0xe1, 0xeb, 0x58, 0x12, 0xc5, 0xff, 0xbd, 0x9f,
+ 0x9d, 0x00, 0x98, 0xd5, 0x8b, 0xee, 0xfd, 0xb3, 0x8b, 0x15, 0xb2, 0x36,
+ 0x80, 0x58, 0x43, 0xdc, 0x2a, 0x11, 0xfd, 0xfc, 0xe5, 0x9e, 0x98, 0x96,
+ 0x2f, 0xf7, 0xe4, 0x5d, 0x41, 0xe3, 0x96, 0x2f, 0xfe, 0x87, 0x24, 0xf9,
+ 0xb9, 0x36, 0x6e, 0xb1, 0x7d, 0x24, 0x68, 0xd6, 0x2f, 0xff, 0x98, 0xb6,
+ 0x2c, 0xeb, 0x8d, 0x9e, 0xc3, 0xac, 0x5e, 0x60, 0x4a, 0xc5, 0xff, 0xe1,
+ 0xb9, 0xfa, 0x87, 0x0b, 0x34, 0x1f, 0x96, 0x2f, 0x69, 0xa2, 0x58, 0xbf,
+ 0x0f, 0x5a, 0x73, 0xac, 0x54, 0xaa, 0x16, 0x82, 0x56, 0xe5, 0xbd, 0x1c,
+ 0x7d, 0x15, 0x88, 0xf8, 0x9f, 0xe1, 0xc1, 0x26, 0x86, 0x3d, 0x74, 0x38,
+ 0xb1, 0x7f, 0x05, 0x3f, 0x7e, 0xa0, 0xb1, 0x78, 0x9c, 0xd5, 0x8b, 0xe7,
+ 0xdd, 0xb4, 0xb1, 0x7f, 0xff, 0xf9, 0x8d, 0x1f, 0xe7, 0x53, 0xf9, 0xf7,
+ 0xd8, 0xe1, 0xc5, 0xcd, 0xdf, 0x65, 0x8a, 0x82, 0x28, 0x08, 0x8e, 0xff,
+ 0xe7, 0xdd, 0xc6, 0x59, 0xee, 0x49, 0xd6, 0x2f, 0xff, 0x31, 0x67, 0xa5,
+ 0xf4, 0xe6, 0x9b, 0x2b, 0x15, 0xd2, 0x73, 0x87, 0x30, 0xe4, 0x2f, 0x7c,
+ 0x44, 0x1a, 0x25, 0xc7, 0xc5, 0x8b, 0x6e, 0xb1, 0x7f, 0xff, 0x3e, 0x8d,
+ 0xfc, 0x9e, 0x28, 0x39, 0x7e, 0x75, 0x2b, 0x16, 0x25, 0x8a, 0x01, 0xf6,
+ 0x89, 0x72, 0xb1, 0x14, 0x5c, 0x84, 0x05, 0x1d, 0x1c, 0x1e, 0x85, 0xcd,
+ 0xff, 0xd8, 0x02, 0x63, 0x79, 0x9e, 0x6f, 0xac, 0x5e, 0x7d, 0x62, 0xc5,
+ 0xe2, 0xc8, 0x2c, 0x56, 0xe6, 0xe3, 0xc3, 0x97, 0x49, 0xd6, 0x2f, 0x14,
+ 0x9d, 0x62, 0xfc, 0xc3, 0x9c, 0x25, 0x8a, 0x94, 0xc7, 0xf6, 0x28, 0x77,
+ 0xc2, 0x22, 0xe0, 0xb8, 0x87, 0x2f, 0xff, 0x16, 0x6d, 0x3e, 0xea, 0x74,
+ 0x2c, 0xd9, 0x62, 0xfc, 0xdf, 0xdd, 0xf8, 0xb1, 0x5f, 0x3f, 0x52, 0x4c,
+ 0xbf, 0xe7, 0x87, 0xbf, 0x9a, 0x7e, 0x2c, 0x5f, 0xff, 0xa1, 0x84, 0x3f,
+ 0xce, 0x14, 0x80, 0xed, 0x05, 0x8a, 0x94, 0x56, 0x91, 0x08, 0x67, 0x37,
+ 0xf7, 0x50, 0xf3, 0xfb, 0x8b, 0x17, 0xe0, 0xfe, 0xdb, 0x62, 0xc5, 0x9c,
+ 0xd3, 0xda, 0x23, 0x0b, 0xfd, 0x9f, 0xea, 0x1e, 0x93, 0xac, 0x5f, 0xa0,
+ 0x59, 0x9b, 0x2c, 0x5d, 0xad, 0x96, 0x2f, 0xfa, 0x2e, 0xf7, 0xce, 0x31,
+ 0xe1, 0x2c, 0x5f, 0xb6, 0xd6, 0x84, 0x6a, 0xc5, 0x4a, 0x2b, 0x30, 0xa1,
+ 0xc6, 0x44, 0x7f, 0x7f, 0x98, 0x72, 0x09, 0x0b, 0x8b, 0x14, 0x34, 0xdd,
+ 0xb0, 0x9f, 0xf0, 0xe1, 0x63, 0xab, 0xef, 0x43, 0xc6, 0xac, 0x5f, 0xff,
+ 0xf8, 0xd9, 0x2e, 0x7d, 0x9f, 0x5a, 0x73, 0x87, 0xee, 0xb7, 0x73, 0xac,
+ 0x5f, 0xff, 0xbd, 0xdd, 0x87, 0x6d, 0xe5, 0xe0, 0xfe, 0xcd, 0x2c, 0x5f,
+ 0xd1, 0xdd, 0xf5, 0x30, 0xcf, 0xc7, 0x2e, 0x40, 0x12, 0xff, 0x78, 0x01,
+ 0x94, 0x3f, 0x8b, 0x90, 0x04, 0xbc, 0xda, 0x82, 0xe4, 0x01, 0x2b, 0x0f,
+ 0xb0, 0x48, 0x57, 0x34, 0x17, 0x20, 0x09, 0x7c, 0xc5, 0xd4, 0x17, 0x20,
+ 0x09, 0x7f, 0x9f, 0x7f, 0xe0, 0x01, 0x2b, 0x90, 0x04, 0xbc, 0xe4, 0x35,
+ 0xc8, 0x02, 0x50, 0xd1, 0x7c, 0x72, 0x4f, 0x98, 0x76, 0x41, 0xb1, 0xab,
+ 0x90, 0x04, 0xbd, 0xa9, 0xf2, 0xe4, 0x01, 0x29, 0x72, 0x00, 0x97, 0xa3,
+ 0x9c, 0x0b, 0x90, 0x04, 0xba, 0x4e, 0xb9, 0x00, 0x60, 0xa1, 0x9f, 0x76,
+ 0x0c, 0xb9, 0x6d, 0xf3, 0x9c, 0x72, 0xb9, 0x00, 0x4b, 0xde, 0x6d, 0xd7,
+ 0x20, 0x09, 0x7f, 0xe2, 0x68, 0x46, 0x7d, 0xf7, 0x6d, 0x2e, 0x40, 0x12,
+ 0xff, 0xe6, 0xf0, 0xb6, 0x72, 0xf7, 0xda, 0x0b, 0x90, 0x04, 0xb9, 0x86,
+ 0xb9, 0x00, 0x4b, 0xfc, 0x4c, 0x17, 0x39, 0x20, 0x5c, 0x80, 0x25, 0xf9,
+ 0xcd, 0x62, 0x02, 0xe4, 0x01, 0x2e, 0x7e, 0x2e, 0x40, 0x12, 0xb4, 0x7b,
+ 0x3e, 0x35, 0xbf, 0xfd, 0xf7, 0xf7, 0xb3, 0x86, 0x69, 0xe4, 0xeb, 0x90,
+ 0x04, 0xbf, 0x78, 0xa7, 0xa8, 0x2a, 0x40, 0x12, 0xe0, 0x4a, 0xe4, 0x01,
+ 0x23, 0x0d, 0xb5, 0x2e, 0x40, 0x12, 0xfa, 0x4e, 0xc3, 0x5c, 0x80, 0x25,
+ 0x0c, 0xf2, 0x1c, 0x66, 0xf8, 0x4c, 0x5b, 0xae, 0x40, 0x12, 0xf4, 0xeb,
+ 0x75, 0xc8, 0x02, 0x5f, 0xfb, 0x3a, 0xe0, 0xe7, 0x08, 0x1c, 0x5c, 0x80,
+ 0x25, 0xf1, 0xc3, 0x90, 0x2e, 0x40, 0x12, 0xf9, 0xa1, 0x09, 0x5c, 0x80,
+ 0x25, 0x61, 0xf0, 0x08, 0xc6, 0xfc, 0xdb, 0xfe, 0x7a, 0x5c, 0x80, 0x25,
+ 0x62, 0x60, 0x9f, 0x85, 0x60, 0x88, 0x6e, 0xd0, 0x17, 0x20, 0x09, 0x50,
+ 0x57, 0x8e, 0x32, 0x4c, 0x84, 0xd6, 0xe4, 0x4f, 0x08, 0xef, 0xbf, 0x80,
+ 0x87, 0x86, 0x1e, 0x8c, 0xbc, 0x46, 0xb6, 0x3a, 0xe4, 0x01, 0x2f, 0xd9,
+ 0xee, 0x37, 0x4b, 0x90, 0x04, 0xbf, 0xc3, 0x9d, 0xe2, 0xd4, 0xf9, 0x72,
+ 0x00, 0x83, 0x36, 0xd7, 0xb5, 0x21, 0x2e, 0x40, 0x12, 0xb1, 0x1a, 0x7b,
+ 0xaa, 0xe9, 0x4e, 0xff, 0x09, 0xa1, 0x09, 0x0c, 0xeb, 0x90, 0x04, 0xbe,
+ 0x72, 0x87, 0x17, 0x20, 0x09, 0x7f, 0x34, 0x50, 0xce, 0xa0, 0xb9, 0x00,
+ 0x4a, 0xc4, 0x6f, 0x7c, 0xc0, 0x08, 0x42, 0x2f, 0xbf, 0xef, 0xcf, 0x23,
+ 0x38, 0x2d, 0x01, 0x72, 0x00, 0xc1, 0x67, 0x5c, 0x80, 0x25, 0xcd, 0xb0,
+ 0xcf, 0xb7, 0xe9, 0xf7, 0x68, 0x0b, 0x90, 0x04, 0xbf, 0x37, 0xb8, 0xfd,
+ 0x2e, 0x40, 0x12, 0xf8, 0x50, 0xce, 0x2e, 0x40, 0x12, 0xfe, 0x7f, 0x42,
+ 0x43, 0x3a, 0xe4, 0x01, 0x2c, 0xe4, 0x7d, 0x9d, 0x8c, 0x2a, 0x51, 0xde,
+ 0x44, 0xbe, 0x85, 0x15, 0x4b, 0x2f, 0x10, 0x70, 0xb9, 0xc8, 0x6f, 0xb9,
+ 0xfc, 0x44, 0x1a, 0x84, 0xc7, 0xcb, 0x58, 0xbc, 0x05, 0x64, 0x9f, 0xc9,
+ 0xc1, 0x9f, 0x4a, 0x4d, 0x8e, 0x85, 0x48, 0x71, 0x8e, 0xde, 0xf3, 0x84,
+ 0xb9, 0x42, 0x4b, 0x9b, 0x75, 0x48, 0x02, 0x46, 0x26, 0x2f, 0xd4, 0x3b,
+ 0x2a, 0x59, 0xb0, 0x2d, 0x4d, 0x33, 0xbf, 0xfc, 0xc7, 0x6f, 0x0a, 0x4c,
+ 0xe0, 0xbb, 0x4a, 0xc5, 0xe9, 0x0b, 0x8b, 0x16, 0xf2, 0xc5, 0xe2, 0xcd,
+ 0xf7, 0x36, 0x0e, 0x3d, 0x70, 0xce, 0xb1, 0x7a, 0x0f, 0xc5, 0x8b, 0xff,
+ 0x7f, 0x37, 0x93, 0xf3, 0x68, 0x6c, 0xb1, 0x7f, 0x8f, 0xac, 0x87, 0xe6,
+ 0x0b, 0x17, 0x10, 0x3c, 0x7e, 0xe1, 0xa1, 0xdf, 0xe1, 0x7b, 0x39, 0xec,
+ 0xdd, 0x62, 0xff, 0x3f, 0x5e, 0x1f, 0xf3, 0x8b, 0x15, 0xdf, 0x69, 0xa2,
+ 0x44, 0x30, 0xd0, 0x94, 0x01, 0x77, 0x0d, 0x6e, 0xed, 0x12, 0xc5, 0xfd,
+ 0xe2, 0xc0, 0x47, 0x62, 0xc5, 0xe9, 0xdb, 0xb2, 0xc5, 0x6c, 0xaa, 0xd4,
+ 0x6f, 0xa6, 0xc6, 0xed, 0xd2, 0xb9, 0xc6, 0xfb, 0x8c, 0x2f, 0xf4, 0x1f,
+ 0xc6, 0x9b, 0x91, 0xeb, 0x17, 0xd3, 0xe9, 0x1a, 0xc5, 0xb6, 0x58, 0xa8,
+ 0x1b, 0x5e, 0xc4, 0x57, 0xe9, 0xd7, 0xda, 0x3d, 0x62, 0xff, 0x14, 0xb7,
+ 0x9b, 0xa0, 0x2c, 0x56, 0xc7, 0xbd, 0xe2, 0xbb, 0xfe, 0xe1, 0x49, 0xf9,
+ 0xbc, 0xf1, 0x62, 0xdc, 0x58, 0xbf, 0xd9, 0xc2, 0x6e, 0x64, 0x7a, 0xc5,
+ 0xe9, 0x1f, 0xd6, 0x2b, 0xe7, 0xa4, 0x46, 0xb5, 0x88, 0xbf, 0xf9, 0xd7,
+ 0x66, 0x4b, 0xec, 0xed, 0x3f, 0x58, 0xa9, 0x4e, 0xe3, 0x21, 0x02, 0xf0,
+ 0xe2, 0xf9, 0x8d, 0xd0, 0x95, 0x8b, 0xff, 0x16, 0x6f, 0xf7, 0x00, 0x05,
+ 0x12, 0xc5, 0xf7, 0x99, 0xb4, 0xb1, 0x7f, 0xc3, 0xc3, 0x4b, 0x3d, 0x21,
+ 0x2c, 0x5f, 0xd9, 0xac, 0x84, 0x25, 0x62, 0xff, 0xf1, 0x67, 0x40, 0x6f,
+ 0x71, 0xcb, 0xa8, 0x2c, 0x54, 0x13, 0x15, 0xe9, 0x04, 0x04, 0x44, 0x75,
+ 0xc2, 0xdb, 0xc3, 0x6f, 0xac, 0x5f, 0xb2, 0x2e, 0x4e, 0xcb, 0x16, 0xf6,
+ 0x1e, 0x3f, 0x87, 0x6e, 0x04, 0xa4, 0x58, 0xd4, 0x8b, 0xdf, 0x9d, 0x96,
+ 0x2e, 0x08, 0x24, 0x8a, 0x73, 0xe2, 0x8f, 0x17, 0x88, 0x4c, 0x21, 0xeb,
+ 0xfe, 0x83, 0xfb, 0x0f, 0xc6, 0x82, 0xc5, 0xb8, 0x91, 0x18, 0x7f, 0x32,
+ 0x81, 0x58, 0x99, 0xa3, 0xc6, 0x05, 0x7f, 0xf6, 0x02, 0x0f, 0xe9, 0x3c,
+ 0x90, 0xd6, 0x2e, 0x72, 0x58, 0xa3, 0xa2, 0x05, 0x8a, 0x00, 0x87, 0x7f,
+ 0x60, 0xff, 0x24, 0x35, 0x8b, 0xff, 0xd9, 0xb6, 0x67, 0xc8, 0x4d, 0xef,
+ 0xe2, 0xc5, 0xfd, 0xee, 0x60, 0x5f, 0x75, 0x8b, 0x79, 0x62, 0xbc, 0x78,
+ 0x22, 0x2f, 0xbf, 0xd9, 0xb9, 0x98, 0x79, 0xdd, 0x62, 0xfd, 0x3b, 0x70,
+ 0xf0, 0x58, 0xac, 0x4c, 0x31, 0xe1, 0x15, 0xf2, 0x2f, 0x1b, 0x5f, 0xff,
+ 0x43, 0x85, 0xd4, 0x9b, 0xc9, 0xea, 0x0e, 0x75, 0x8b, 0xff, 0xb9, 0xee,
+ 0xb7, 0x7d, 0x79, 0x81, 0xc5, 0x8a, 0xe9, 0x13, 0x64, 0xa7, 0x7f, 0xc6,
+ 0xbe, 0x83, 0x00, 0x27, 0xa5, 0x8b, 0xe8, 0x7a, 0x42, 0x58, 0xbb, 0xdc,
+ 0xc3, 0xe1, 0xe8, 0xf6, 0xa3, 0x67, 0x43, 0xdf, 0x31, 0xda, 0x6d, 0x29,
+ 0x46, 0x11, 0xbc, 0x0e, 0x3f, 0xfc, 0x41, 0x34, 0x97, 0x7a, 0x6f, 0x8b,
+ 0xca, 0xe3, 0x89, 0x97, 0x52, 0x89, 0x8e, 0x8a, 0xd1, 0x96, 0x02, 0x52,
+ 0x39, 0x17, 0xfa, 0x33, 0x91, 0x43, 0x70, 0x38, 0x42, 0x5f, 0x06, 0x3c,
+ 0x3a, 0xc5, 0xf8, 0x6d, 0xbf, 0x20, 0xb1, 0x7f, 0x39, 0x03, 0x3a, 0xf2,
+ 0xc5, 0xa0, 0xe7, 0xb1, 0xf2, 0xab, 0xe9, 0xdc, 0x33, 0xac, 0x5f, 0xf9,
+ 0x9f, 0xd2, 0x5e, 0xfe, 0x41, 0x62, 0xf8, 0x67, 0x68, 0x2c, 0x59, 0xd6,
+ 0x29, 0x8d, 0xa7, 0x08, 0xeb, 0x11, 0xbb, 0xa2, 0x7f, 0x92, 0xf9, 0xc6,
+ 0xff, 0x39, 0x6e, 0xfa, 0x70, 0x2c, 0x5e, 0xcc, 0x02, 0xc5, 0xff, 0x1f,
+ 0x7f, 0xb8, 0xfe, 0xe6, 0xac, 0x51, 0xd1, 0x16, 0x46, 0x61, 0x8e, 0x5f,
+ 0xe3, 0x7e, 0xf2, 0x7e, 0x41, 0x62, 0xb7, 0x4c, 0xb3, 0xf0, 0xc7, 0x23,
+ 0x0b, 0x4a, 0xc5, 0xf7, 0xc4, 0xc4, 0xb1, 0x6f, 0x18, 0x6c, 0xc6, 0x23,
+ 0x77, 0xc9, 0x62, 0xfe, 0xce, 0xa0, 0x76, 0x82, 0xc5, 0x6e, 0x78, 0xdd,
+ 0xc2, 0xf7, 0xff, 0x7a, 0x3b, 0x22, 0x83, 0x6b, 0x61, 0xca, 0xc5, 0x74,
+ 0x8d, 0xe3, 0xb7, 0x11, 0x35, 0xff, 0xde, 0x70, 0x8f, 0xc7, 0x21, 0x37,
+ 0x96, 0x2f, 0x86, 0xc0, 0xe2, 0xc5, 0xfe, 0x31, 0xf3, 0x9f, 0xcf, 0x2c,
+ 0x56, 0x1e, 0xbf, 0x08, 0xef, 0xfe, 0x68, 0x18, 0x4f, 0x26, 0x39, 0xf1,
+ 0x62, 0xee, 0x80, 0xb1, 0x60, 0x1c, 0xf7, 0x40, 0x89, 0x7d, 0x9e, 0x0f,
+ 0x65, 0x8b, 0xd1, 0x48, 0x4b, 0x17, 0xfc, 0x69, 0xad, 0x0f, 0x3f, 0x1d,
+ 0x62, 0xf0, 0x24, 0xeb, 0x15, 0x87, 0xb1, 0xa3, 0xbb, 0xff, 0xdf, 0x7e,
+ 0xcf, 0xbe, 0xa7, 0x66, 0xd6, 0xeb, 0x17, 0xf4, 0xf5, 0x24, 0xde, 0x58,
+ 0xb8, 0x80, 0xb1, 0x74, 0xf1, 0x62, 0x9c, 0xd7, 0x76, 0x17, 0xaf, 0x9f,
+ 0xef, 0x65, 0xba, 0x31, 0x3a, 0xd9, 0x25, 0xc7, 0x7d, 0xc8, 0x43, 0x86,
+ 0x65, 0x69, 0x55, 0x21, 0x3f, 0x7a, 0x3d, 0x5b, 0xff, 0xfd, 0xf7, 0x21,
+ 0xe1, 0xfd, 0x39, 0x87, 0x1c, 0xe1, 0x2c, 0x5f, 0xec, 0xeb, 0xde, 0x68,
+ 0x71, 0x62, 0xff, 0x9b, 0xa3, 0x04, 0xc1, 0xbe, 0xcb, 0x17, 0xf8, 0x39,
+ 0x0b, 0x53, 0x84, 0xb1, 0x77, 0x7f, 0x05, 0x8b, 0xf3, 0x1a, 0x59, 0x12,
+ 0xc5, 0xfe, 0x9d, 0x03, 0x34, 0xc4, 0xb1, 0x50, 0x3f, 0x82, 0x1d, 0x0c,
+ 0xa6, 0xee, 0xa0, 0xb9, 0x40, 0x0b, 0xff, 0xd8, 0x14, 0xfb, 0x22, 0x83,
+ 0xfb, 0x8c, 0xb1, 0x50, 0x4d, 0x33, 0xa8, 0x56, 0x11, 0x7f, 0x09, 0xaf,
+ 0x84, 0xc5, 0xba, 0xc5, 0xc0, 0x82, 0xc5, 0xff, 0x89, 0xbc, 0x2f, 0x0f,
+ 0xee, 0x6a, 0xc5, 0xe9, 0xcf, 0x91, 0xec, 0x70, 0x62, 0xfc, 0xf3, 0xe9,
+ 0x1a, 0xc5, 0xff, 0x3f, 0x5c, 0xf1, 0x49, 0xf8, 0xb1, 0x7f, 0xff, 0xff,
+ 0xff, 0x0a, 0x3c, 0x9b, 0x3e, 0xc1, 0x96, 0x76, 0xc2, 0x63, 0x62, 0x80,
+ 0xb9, 0xc0, 0x98, 0x7f, 0x70, 0xb9, 0x8c, 0x35, 0x8a, 0x35, 0x1e, 0xfc,
+ 0x3a, 0xbd, 0xfc, 0xee, 0x58, 0xbf, 0x13, 0x76, 0x6f, 0xac, 0x5f, 0xfd,
+ 0xc3, 0x03, 0x1c, 0xeb, 0x4f, 0x27, 0x58, 0xac, 0x3f, 0x01, 0x14, 0xd1,
+ 0x88, 0xb1, 0xe4, 0x24, 0x2f, 0xe6, 0xfc, 0x4c, 0xfb, 0x2c, 0x5f, 0xff,
+ 0xfb, 0x6c, 0x1c, 0x9f, 0x08, 0x5e, 0x11, 0xbe, 0xeb, 0x77, 0x2d, 0x96,
+ 0x28, 0xc6, 0x69, 0xcc, 0xca, 0x85, 0xc8, 0xd1, 0xfa, 0x30, 0x79, 0x68,
+ 0x11, 0x1b, 0xe9, 0x74, 0xe6, 0xad, 0x1c, 0x48, 0x10, 0xc9, 0xef, 0x86,
+ 0x3e, 0x8c, 0x78, 0x50, 0xd5, 0x08, 0xa4, 0x32, 0xfb, 0xfc, 0x1f, 0x9f,
+ 0x53, 0x84, 0xb1, 0x7f, 0xfe, 0x22, 0x17, 0x59, 0xd7, 0x87, 0xa6, 0xeb,
+ 0x36, 0x58, 0xbf, 0x67, 0xb5, 0x3c, 0x58, 0xa7, 0x44, 0x09, 0x2c, 0xdf,
+ 0x39, 0x49, 0xd6, 0x2e, 0x98, 0x2c, 0x56, 0x1b, 0x80, 0x10, 0xdf, 0xc4,
+ 0xdd, 0x4b, 0xc4, 0xb1, 0x6d, 0x96, 0x29, 0x62, 0xe8, 0x4e, 0x8b, 0xf0,
+ 0x09, 0xde, 0x68, 0x62, 0xc5, 0x44, 0x78, 0xe7, 0x2b, 0xbe, 0x93, 0x64,
+ 0xeb, 0x17, 0xa0, 0x37, 0x58, 0xa8, 0x26, 0xe1, 0xd2, 0xcb, 0x90, 0x6a,
+ 0x12, 0x87, 0x23, 0x22, 0x3b, 0xf8, 0xb0, 0xf3, 0xa3, 0x56, 0x2f, 0xde,
+ 0x7e, 0xdf, 0x75, 0x8b, 0x70, 0xc3, 0xd8, 0xc2, 0xeb, 0xff, 0xff, 0xe2,
+ 0xdf, 0xfd, 0x34, 0x78, 0x79, 0xf2, 0x6f, 0x7a, 0x7e, 0xfe, 0xe6, 0x0d,
+ 0x62, 0xa0, 0x8a, 0xac, 0x28, 0xbf, 0xb9, 0x8c, 0x36, 0xf2, 0xc5, 0xff,
+ 0xef, 0x31, 0x00, 0xcc, 0xfc, 0xef, 0x9d, 0x96, 0x2f, 0xff, 0xdf, 0xce,
+ 0xa0, 0x53, 0x9c, 0xe8, 0x12, 0x5b, 0xac, 0x5f, 0xff, 0xc7, 0x0f, 0x3e,
+ 0xc7, 0xc3, 0xbf, 0xb0, 0xd7, 0xd2, 0xc5, 0xfe, 0x93, 0xe7, 0x77, 0x9c,
+ 0x25, 0x8a, 0x94, 0x49, 0xf1, 0x72, 0xff, 0xfb, 0x35, 0x11, 0x48, 0x39,
+ 0xbf, 0xdf, 0x5b, 0x2c, 0x54, 0x0f, 0xd7, 0x84, 0x57, 0xe3, 0x0c, 0xcf,
+ 0xb2, 0xc5, 0xee, 0x61, 0xd6, 0x2f, 0xf3, 0x91, 0x9b, 0xb6, 0xb6, 0x58,
+ 0xa8, 0x1e, 0x9f, 0x87, 0x6f, 0xf6, 0x75, 0xe3, 0x23, 0x9c, 0xd5, 0x8b,
+ 0xf7, 0x5e, 0x8e, 0x73, 0x56, 0x2f, 0x1d, 0xfc, 0x61, 0xf4, 0x61, 0xd5,
+ 0xee, 0x49, 0x2c, 0x5e, 0xd6, 0x71, 0x62, 0xdb, 0xc9, 0xb9, 0xc1, 0xcb,
+ 0xfe, 0xeb, 0x8f, 0xd4, 0x3e, 0xff, 0x58, 0xbf, 0xef, 0xb3, 0xfa, 0x1f,
+ 0x11, 0xab, 0x17, 0x9b, 0xfc, 0x58, 0xa6, 0x44, 0xa7, 0x0f, 0x02, 0x3b,
+ 0xbf, 0xa1, 0x3a, 0x00, 0x67, 0x58, 0xbf, 0xd3, 0xc6, 0x03, 0x10, 0x16,
+ 0x2f, 0xa2, 0xfb, 0xc4, 0xb1, 0x7f, 0xe3, 0x4d, 0x72, 0xdc, 0xcd, 0xbe,
+ 0x6a, 0xc5, 0x61, 0xf5, 0xb9, 0x2d, 0xff, 0xff, 0xef, 0xbf, 0xa7, 0x4c,
+ 0xe3, 0x14, 0xf2, 0x74, 0x28, 0x3e, 0xb0, 0x0b, 0x17, 0xff, 0x76, 0x2c,
+ 0xe7, 0xb0, 0xa1, 0x9c, 0x58, 0xbe, 0x3c, 0x8b, 0xcb, 0x15, 0x87, 0xd0,
+ 0xc8, 0xb7, 0xd0, 0xd3, 0x9d, 0x62, 0xf7, 0x84, 0x6a, 0xc5, 0x89, 0x8f,
+ 0x08, 0x44, 0x77, 0xf8, 0x8a, 0x7a, 0x0c, 0xf2, 0xb1, 0x7f, 0x3f, 0xdb,
+ 0xef, 0xc5, 0x8b, 0xde, 0x6d, 0x2c, 0x51, 0xcf, 0x2b, 0xc5, 0xb7, 0xec,
+ 0x8b, 0xf3, 0xb2, 0xc5, 0x62, 0x3c, 0x1c, 0x99, 0x9f, 0x88, 0x8a, 0xff,
+ 0xfe, 0xc8, 0xb9, 0x3b, 0x16, 0x04, 0xda, 0x37, 0x3a, 0xf2, 0xc5, 0xef,
+ 0x7d, 0xd6, 0x2f, 0xfc, 0x4d, 0xee, 0x3f, 0x45, 0x21, 0x2c, 0x5e, 0xf3,
+ 0x12, 0xc5, 0x98, 0xc5, 0xc5, 0xdc, 0x30, 0xd1, 0x87, 0xe1, 0x3a, 0xc4,
+ 0x05, 0x0d, 0xee, 0x46, 0xa5, 0xe3, 0x9e, 0xcb, 0xe1, 0x8e, 0xf7, 0x1f,
+ 0xdf, 0x84, 0xd9, 0xd7, 0x96, 0x28, 0xc5, 0xf6, 0x79, 0x7d, 0xc8, 0x45,
+ 0x3b, 0x67, 0xe7, 0x45, 0xfd, 0x0b, 0x4b, 0xfe, 0x98, 0xf1, 0xfe, 0x76,
+ 0x62, 0x58, 0xbf, 0x61, 0x4f, 0x5c, 0x58, 0xbf, 0xfe, 0x93, 0x86, 0x5e,
+ 0xf8, 0x9a, 0x1f, 0x17, 0x16, 0x2e, 0x7f, 0x2c, 0x5c, 0x79, 0x58, 0xbc,
+ 0x0c, 0xfc, 0x9a, 0xe7, 0x17, 0xbf, 0xb9, 0xee, 0xa1, 0x21, 0xac, 0x5f,
+ 0xed, 0xcb, 0x3b, 0x7d, 0xa0, 0xb1, 0x78, 0xe0, 0x75, 0x8b, 0xe9, 0xde,
+ 0x4e, 0x62, 0x21, 0x30, 0xc5, 0xcd, 0xaa, 0x0c, 0xba, 0xac, 0x2d, 0xdd,
+ 0x37, 0xa8, 0xd7, 0xf5, 0x3f, 0x13, 0xf6, 0xa6, 0x3c, 0x22, 0x8f, 0x42,
+ 0x03, 0xba, 0x16, 0x97, 0xf0, 0x61, 0x69, 0xf3, 0xe9, 0x17, 0xf9, 0xbd,
+ 0x30, 0x10, 0xf1, 0x62, 0xfb, 0xf3, 0x9b, 0x2c, 0x51, 0x1e, 0xb7, 0x0c,
+ 0xef, 0xb8, 0xf2, 0x05, 0x8b, 0xfe, 0xf4, 0xf5, 0xec, 0x3c, 0xfd, 0x62,
+ 0xfa, 0x2c, 0xc0, 0x96, 0x2f, 0xa0, 0xfa, 0xe2, 0xc5, 0xff, 0xc1, 0x9f,
+ 0x3d, 0x3d, 0x9f, 0xd0, 0x95, 0x8b, 0xe7, 0xf4, 0xe9, 0x62, 0xff, 0x9f,
+ 0x3a, 0xf4, 0x50, 0x6d, 0x2c, 0x58, 0x0e, 0x8a, 0x4f, 0xa3, 0x91, 0x15,
+ 0xff, 0xa0, 0x52, 0x7f, 0xce, 0xed, 0xa5, 0x8b, 0x9f, 0x16, 0x2b, 0xa3,
+ 0xd5, 0x01, 0xfd, 0xf4, 0x5f, 0x68, 0x96, 0x2f, 0xb7, 0x6d, 0x6c, 0xb1,
+ 0x7a, 0x26, 0xf2, 0xc5, 0xfb, 0x22, 0x84, 0xf4, 0xb1, 0x7f, 0xdf, 0x9e,
+ 0x7d, 0xb9, 0x31, 0xeb, 0x17, 0x3c, 0x4b, 0x17, 0x9e, 0x49, 0x62, 0xfd,
+ 0xf7, 0x8a, 0x76, 0x58, 0xbf, 0x66, 0x87, 0xfc, 0x58, 0xa1, 0x9f, 0x6e,
+ 0xe3, 0x7c, 0x2a, 0xaf, 0xa2, 0xd7, 0x90, 0x85, 0xbc, 0xc4, 0x05, 0x8b,
+ 0xfb, 0xf9, 0xee, 0x60, 0x4b, 0x17, 0x8a, 0x60, 0x91, 0x7f, 0xe2, 0x03,
+ 0xf7, 0x77, 0x0a, 0x13, 0x1e, 0xb1, 0x63, 0xac, 0x51, 0x88, 0xc1, 0x18,
+ 0xe6, 0x17, 0xb0, 0xe0, 0x69, 0x14, 0x62, 0xe6, 0x54, 0x90, 0xec, 0x44,
+ 0x33, 0xac, 0x24, 0xea, 0x18, 0xef, 0x08, 0x9d, 0x11, 0xfc, 0x95, 0x89,
+ 0x48, 0x7b, 0x85, 0x5e, 0x87, 0x8f, 0x74, 0x3a, 0x6f, 0xf4, 0xc7, 0xe6,
+ 0xb5, 0x3b, 0x2c, 0x54, 0x6e, 0xdb, 0x2a, 0xcc, 0xa2, 0x4c, 0x8d, 0x79,
+ 0xe9, 0x79, 0x9f, 0x85, 0x4b, 0x4e, 0xa8, 0x0a, 0x1a, 0xf7, 0xb4, 0xde,
+ 0x58, 0xbf, 0x73, 0x5a, 0x9f, 0x2c, 0x5f, 0xdf, 0x6c, 0x00, 0x7e, 0x58,
+ 0xbe, 0xe3, 0xeb, 0x65, 0x8a, 0xc3, 0xd3, 0xe1, 0x7d, 0xef, 0x3e, 0xcb,
+ 0x15, 0xb2, 0x36, 0x3a, 0x1d, 0x8f, 0x7c, 0x39, 0x0d, 0xec, 0xfb, 0x2c,
+ 0x5e, 0xd3, 0x6e, 0xb1, 0x7e, 0x9d, 0x67, 0x5e, 0x58, 0xb7, 0x0d, 0x3c,
+ 0x7f, 0x8f, 0x5f, 0xe8, 0x8b, 0x07, 0xf9, 0xe2, 0xc5, 0xfe, 0xcd, 0x7e,
+ 0x42, 0x2c, 0x58, 0xbf, 0xfb, 0x00, 0x06, 0xeb, 0x9c, 0x92, 0xdd, 0x62,
+ 0xd0, 0x58, 0xa2, 0x3d, 0x8e, 0x23, 0x54, 0x13, 0x09, 0xf9, 0x48, 0x0d,
+ 0x3b, 0x42, 0x2e, 0xff, 0xb0, 0xb7, 0xfb, 0xf6, 0x9e, 0x2c, 0x5d, 0xee,
+ 0x2c, 0x54, 0x0f, 0x4c, 0x8e, 0xef, 0xfe, 0xcf, 0x77, 0x91, 0xbf, 0x78,
+ 0xfd, 0x70, 0x5c, 0x58, 0xbf, 0xdb, 0xfd, 0xc7, 0x25, 0xe5, 0x8b, 0x9e,
+ 0x0b, 0x15, 0xd1, 0xe5, 0x91, 0xa5, 0xc4, 0x05, 0x8b, 0xf6, 0xbe, 0xcc,
+ 0x75, 0x8b, 0xe1, 0x10, 0xb7, 0x58, 0xa6, 0x3c, 0xce, 0x14, 0x5f, 0xde,
+ 0x8a, 0x19, 0xd4, 0x16, 0x28, 0xc5, 0x73, 0xb3, 0x1b, 0x63, 0xc2, 0x60,
+ 0xe4, 0x2d, 0x0a, 0x1f, 0x11, 0x09, 0x8c, 0x32, 0x1b, 0xff, 0x8b, 0xc3,
+ 0xce, 0xcc, 0x40, 0x04, 0xac, 0x5f, 0xec, 0xc1, 0x7f, 0x3b, 0x4a, 0xc5,
+ 0x61, 0xfc, 0x86, 0x8b, 0x7f, 0xe0, 0xa7, 0x5c, 0xc0, 0x9b, 0x46, 0xac,
+ 0x5d, 0xbb, 0x2c, 0x5e, 0xce, 0x09, 0x62, 0xff, 0xfd, 0xfc, 0xdc, 0x84,
+ 0x32, 0x90, 0xf4, 0xf2, 0x4b, 0x15, 0x88, 0xee, 0xf9, 0x13, 0x21, 0x10,
+ 0xc7, 0x87, 0x6f, 0x9f, 0x6c, 0x1a, 0xc5, 0xfe, 0x0b, 0x3a, 0xf7, 0xa4,
+ 0xeb, 0x17, 0xe2, 0xc0, 0x0b, 0x8b, 0x17, 0xfd, 0xbb, 0xe1, 0x67, 0x66,
+ 0xe2, 0xc5, 0x6c, 0x7c, 0x5f, 0x28, 0xa6, 0x45, 0xdf, 0x21, 0x31, 0x7c,
+ 0x31, 0xe1, 0xd6, 0x2e, 0x04, 0xa4, 0x5c, 0x10, 0x49, 0x14, 0xe6, 0xc4,
+ 0x21, 0x7b, 0xe1, 0x36, 0xa0, 0x91, 0x18, 0x68, 0x6f, 0xb3, 0x53, 0xc5,
+ 0x8a, 0x19, 0xec, 0x70, 0xda, 0xb1, 0x1d, 0xe6, 0xc3, 0x36, 0xff, 0xf7,
+ 0xba, 0xdd, 0xff, 0x1d, 0x3e, 0xf8, 0x7c, 0x58, 0xbe, 0xd4, 0xe1, 0x2c,
+ 0x5e, 0xd0, 0xb6, 0x58, 0xbc, 0x76, 0x81, 0x87, 0x81, 0xb1, 0x0d, 0xbb,
+ 0xe2, 0xc5, 0xfe, 0x98, 0x3f, 0xa1, 0x3e, 0x58, 0xbe, 0x71, 0x8a, 0x56,
+ 0x2e, 0xef, 0xf8, 0xb1, 0x1a, 0xcf, 0xb7, 0x43, 0x1e, 0x33, 0xbe, 0x8a,
+ 0x12, 0x05, 0x8b, 0xfe, 0xfb, 0x7b, 0x9b, 0x96, 0x6c, 0xb1, 0x78, 0xe2,
+ 0x35, 0x62, 0xf7, 0x7d, 0xc6, 0xd1, 0xb2, 0xc5, 0xff, 0xb4, 0x4c, 0x13,
+ 0xfb, 0x42, 0x3a, 0xc5, 0xdb, 0xba, 0xc5, 0xff, 0xa6, 0x3c, 0x5a, 0xcd,
+ 0x6a, 0x7a, 0x58, 0xbe, 0x27, 0xea, 0x0b, 0x17, 0xfc, 0xfd, 0x7f, 0x07,
+ 0xa6, 0xdd, 0x62, 0xa4, 0xf7, 0xb4, 0x47, 0x7d, 0x9d, 0xb0, 0x96, 0x2e,
+ 0xc1, 0xac, 0x5f, 0x98, 0xf8, 0x5e, 0x58, 0xb9, 0xe5, 0x62, 0xa0, 0x7a,
+ 0x9a, 0x17, 0xf1, 0x3d, 0xfe, 0xe6, 0x3f, 0x8d, 0x7f, 0xac, 0x5f, 0xf7,
+ 0xe7, 0x53, 0xbb, 0x96, 0xeb, 0x17, 0x8d, 0x6e, 0x77, 0xda, 0xa5, 0xd1,
+ 0x97, 0xee, 0x81, 0xd0, 0xc6, 0xa1, 0x43, 0xf2, 0x16, 0x77, 0xf1, 0x7f,
+ 0x71, 0xa5, 0xf7, 0xbd, 0x3a, 0x58, 0xa9, 0x57, 0x41, 0x84, 0x8e, 0x77,
+ 0xe9, 0x4f, 0x81, 0xc2, 0x8a, 0xa0, 0xbf, 0xb7, 0xba, 0x3f, 0x50, 0xde,
+ 0xd4, 0x62, 0xc7, 0x28, 0x04, 0x24, 0x85, 0x0a, 0x20, 0xa5, 0xf7, 0x5f,
+ 0xbe, 0xfc, 0x16, 0xcb, 0x17, 0xff, 0x38, 0xdf, 0xd3, 0xd0, 0x59, 0x9c,
+ 0x58, 0xb4, 0x6c, 0xb1, 0x4b, 0x16, 0xef, 0x0c, 0x34, 0x71, 0xb0, 0xbd,
+ 0xa3, 0x65, 0x8b, 0xe6, 0xf1, 0x4a, 0xc5, 0xff, 0xf8, 0xb3, 0xb6, 0x6f,
+ 0xf7, 0x3c, 0xe1, 0x7b, 0x8b, 0x14, 0x62, 0x30, 0x3b, 0xc3, 0x23, 0x45,
+ 0xc3, 0x21, 0xa1, 0xa6, 0xda, 0x14, 0x65, 0x17, 0xff, 0xfb, 0xf3, 0xf7,
+ 0x37, 0x05, 0xdf, 0xbf, 0xdf, 0x50, 0x9d, 0x2c, 0x5c, 0x2d, 0x2c, 0x54,
+ 0x0f, 0xf8, 0xec, 0xd7, 0xb7, 0x7e, 0x2c, 0x5f, 0x08, 0xf8, 0x35, 0x8a,
+ 0xe9, 0x30, 0xc7, 0x85, 0x4f, 0xc8, 0xbb, 0x87, 0xaf, 0xff, 0xed, 0x40,
+ 0x53, 0x9f, 0xdd, 0xf9, 0x83, 0xdb, 0x02, 0x58, 0xbf, 0xec, 0xee, 0x62,
+ 0x37, 0x3a, 0xf2, 0xc5, 0xfb, 0x43, 0xfb, 0xc4, 0xb1, 0x5f, 0x3e, 0x70,
+ 0xcf, 0x6f, 0x85, 0x24, 0x6a, 0xc5, 0xfd, 0xf7, 0x1f, 0xc4, 0x6a, 0xc5,
+ 0xf8, 0xa6, 0x27, 0xe9, 0x62, 0xd8, 0x33, 0xfc, 0xdc, 0x8d, 0xcc, 0x2f,
+ 0x7b, 0x37, 0x58, 0xa3, 0x9e, 0x97, 0x0d, 0x2e, 0x38, 0x16, 0x2f, 0xfa,
+ 0x43, 0x2f, 0x7c, 0x4d, 0x05, 0x8a, 0x81, 0xe9, 0x78, 0x62, 0xfd, 0xe2,
+ 0xcd, 0x4a, 0xc5, 0x4a, 0xa7, 0x33, 0x61, 0x8a, 0x08, 0x78, 0xf9, 0xd0,
+ 0x22, 0x2b, 0xc3, 0x6e, 0x2c, 0x5e, 0x27, 0x35, 0x62, 0xff, 0xc1, 0xf2,
+ 0x73, 0x9a, 0xd3, 0xf9, 0x62, 0xa4, 0xfe, 0xb0, 0x77, 0x83, 0xb7, 0xe9,
+ 0x39, 0x39, 0xab, 0x17, 0x0f, 0xeb, 0x17, 0x1a, 0xc6, 0x1e, 0x06, 0x14,
+ 0x5f, 0xf9, 0xb8, 0x79, 0x7d, 0x69, 0xc2, 0x58, 0xbf, 0x6d, 0x83, 0x93,
+ 0xac, 0x5b, 0x86, 0xa2, 0x5b, 0xe5, 0xc1, 0x9f, 0xdc, 0xfd, 0xcb, 0x17,
+ 0xff, 0xff, 0x7e, 0x79, 0x80, 0x9f, 0x73, 0x59, 0xb4, 0xeb, 0x9f, 0xdd,
+ 0xf8, 0xb1, 0x7d, 0xad, 0x30, 0xd6, 0x2f, 0x41, 0xb4, 0xb1, 0x43, 0x45,
+ 0xa6, 0x3a, 0x31, 0x1d, 0xfc, 0x7d, 0x69, 0xfa, 0x02, 0xc5, 0xe0, 0xdc,
+ 0xeb, 0x17, 0xe7, 0xd4, 0xf9, 0xd6, 0x2f, 0x37, 0xe2, 0x58, 0xa9, 0x3c,
+ 0x5f, 0x13, 0xdf, 0xc5, 0x3b, 0xfd, 0xfb, 0x96, 0x2f, 0x1b, 0x3c, 0x58,
+ 0xbf, 0xec, 0xf7, 0x9c, 0xdf, 0x66, 0xeb, 0x17, 0xf4, 0xf5, 0xcc, 0xeb,
+ 0xcb, 0x17, 0x6a, 0x56, 0x28, 0x67, 0x8f, 0xe3, 0x0b, 0xf0, 0x88, 0x71,
+ 0xa4, 0x68, 0xb1, 0x7f, 0xfd, 0xed, 0x4e, 0x75, 0x1c, 0x47, 0x17, 0x80,
+ 0xcb, 0x17, 0xfb, 0xcf, 0xbb, 0x8e, 0x7c, 0xb1, 0x7e, 0xe4, 0xef, 0x87,
+ 0x58, 0xa9, 0x3d, 0xde, 0x1a, 0x5f, 0x3f, 0x50, 0xc5, 0x8b, 0xfe, 0x36,
+ 0x4a, 0x19, 0xb0, 0xa0, 0xb1, 0x7f, 0xc3, 0xfc, 0xc2, 0x2d, 0x0b, 0x65,
+ 0x8a, 0x31, 0x55, 0xa4, 0x90, 0xc0, 0xc4, 0x63, 0xd9, 0x08, 0x2d, 0xc8,
+ 0xba, 0x33, 0xd4, 0x2c, 0x40, 0x43, 0xe2, 0x30, 0xce, 0xea, 0x55, 0xde,
+ 0xf2, 0x58, 0xbd, 0x41, 0x79, 0x3f, 0xa8, 0xc0, 0xf4, 0x70, 0x78, 0x67,
+ 0x31, 0x77, 0xa5, 0xf6, 0xdf, 0x37, 0x58, 0x35, 0x8b, 0xfd, 0xfc, 0x87,
+ 0x9d, 0xfa, 0x58, 0xbf, 0xef, 0x3e, 0xd3, 0xd0, 0x35, 0x2b, 0x17, 0x7f,
+ 0x65, 0x8b, 0xbc, 0x6a, 0xc5, 0xee, 0x7b, 0x16, 0x2d, 0xc3, 0x11, 0x15,
+ 0xb9, 0xd9, 0x0c, 0x86, 0x33, 0x7f, 0xdb, 0x36, 0x10, 0xa1, 0x9c, 0x58,
+ 0xac, 0x3f, 0xee, 0x22, 0xdf, 0x98, 0x11, 0xce, 0x75, 0x8b, 0xfb, 0x77,
+ 0xe0, 0xa0, 0xeb, 0x17, 0x88, 0x5c, 0x58, 0xaf, 0x9e, 0x67, 0x62, 0xfb,
+ 0xbb, 0xe4, 0x72, 0xc5, 0xfa, 0x2c, 0x21, 0x62, 0xc5, 0xfd, 0xe7, 0xea,
+ 0x05, 0x31, 0xb1, 0xe4, 0xc9, 0x0d, 0xf7, 0x5e, 0xfb, 0xac, 0x5f, 0x3e,
+ 0xdd, 0xe1, 0xab, 0x16, 0x06, 0x1e, 0x76, 0xe4, 0x95, 0x88, 0xbe, 0x78,
+ 0x4b, 0x5f, 0xf3, 0x3f, 0x9c, 0xbc, 0x2f, 0xac, 0x5e, 0xfb, 0xf6, 0x58,
+ 0xb8, 0x50, 0xf9, 0xeb, 0x86, 0x71, 0x7f, 0xf3, 0x0f, 0xef, 0xac, 0xed,
+ 0x25, 0x12, 0xc5, 0xff, 0xdc, 0x16, 0x8b, 0x07, 0xf9, 0x0a, 0x56, 0x2d,
+ 0x26, 0x22, 0x2f, 0xc8, 0xd7, 0x0f, 0x75, 0x8b, 0xb3, 0xb0, 0xcf, 0x08,
+ 0x05, 0x37, 0xf8, 0xdf, 0x75, 0xbb, 0xeb, 0x8b, 0x17, 0xec, 0xf0, 0x1b,
+ 0xcb, 0x15, 0x2a, 0xcc, 0xe1, 0x19, 0x5e, 0x9f, 0x7f, 0x0f, 0xc1, 0x17,
+ 0xc7, 0x1c, 0x5f, 0xff, 0xa7, 0xed, 0x85, 0x3a, 0x34, 0x62, 0x6d, 0x41,
+ 0x62, 0xa0, 0xb9, 0x0d, 0xc2, 0x1f, 0x4b, 0xaa, 0xee, 0x66, 0xa9, 0x6c,
+ 0xea, 0x87, 0x09, 0x3c, 0x95, 0x46, 0xf2, 0xae, 0x5a, 0x7c, 0x80, 0x0d,
+ 0x9e, 0x23, 0x14, 0xee, 0x15, 0xf8, 0x3d, 0x6a, 0x49, 0x62, 0xff, 0xfd,
+ 0xe9, 0x18, 0x1b, 0xa0, 0x3f, 0x41, 0xe9, 0xba, 0x58, 0xb9, 0xce, 0xb1,
+ 0x4b, 0x17, 0x34, 0x16, 0x2e, 0xd6, 0x2c, 0x53, 0x9a, 0xe6, 0x17, 0xb4,
+ 0x72, 0xc5, 0x18, 0x98, 0x44, 0x94, 0xc1, 0x69, 0xc5, 0xfe, 0x75, 0x1c,
+ 0x3f, 0x7f, 0x14, 0x33, 0x81, 0x9d, 0x62, 0xf0, 0x8b, 0xcb, 0x15, 0x87,
+ 0x99, 0xc2, 0xfb, 0xf1, 0xf8, 0x06, 0x65, 0x8a, 0xf1, 0xe4, 0x86, 0x43,
+ 0x7f, 0x11, 0x9f, 0xce, 0x82, 0x58, 0xbf, 0xd8, 0x7e, 0xa1, 0x39, 0xe5,
+ 0x8a, 0xc3, 0xe5, 0x01, 0x8d, 0xfd, 0x3f, 0x7e, 0xd9, 0x12, 0xc5, 0x68,
+ 0xf4, 0x40, 0x43, 0x7e, 0x89, 0x98, 0xb6, 0x58, 0xbf, 0x84, 0x03, 0x37,
+ 0x38, 0x16, 0x2d, 0x0c, 0x3d, 0xb2, 0x29, 0xbf, 0x16, 0x00, 0x5c, 0x58,
+ 0xad, 0x95, 0x49, 0xc2, 0x1d, 0xf9, 0x0d, 0x9e, 0x9f, 0x40, 0x4d, 0x7f,
+ 0xba, 0x87, 0xfb, 0xbb, 0xa6, 0x3d, 0x62, 0xff, 0x9f, 0xa8, 0x6d, 0xb0,
+ 0x3a, 0x02, 0xc5, 0x61, 0xff, 0x7c, 0xfe, 0xf8, 0x3d, 0x30, 0x16, 0x2f,
+ 0xfb, 0x8f, 0x07, 0xf4, 0xfb, 0x8b, 0x15, 0x03, 0xdd, 0xf9, 0x25, 0xff,
+ 0xe0, 0x10, 0xb9, 0xee, 0x4e, 0xb3, 0xaf, 0x2c, 0x5f, 0xfe, 0x0c, 0xa7,
+ 0x85, 0x9d, 0x9f, 0xff, 0x95, 0x8b, 0xff, 0xf1, 0x0b, 0xd3, 0xfd, 0xdf,
+ 0x9a, 0x90, 0xd8, 0x96, 0x2e, 0x28, 0x18, 0x8a, 0x1c, 0x4b, 0xbf, 0xdc,
+ 0xcd, 0x14, 0xf5, 0x05, 0x8b, 0x88, 0x0b, 0x15, 0xb1, 0xe5, 0xb1, 0xa5,
+ 0x32, 0x75, 0x44, 0x44, 0x28, 0x76, 0x84, 0xf3, 0x7f, 0xb3, 0xb6, 0x68,
+ 0x00, 0x12, 0xc5, 0xff, 0xcf, 0xa3, 0x1a, 0x61, 0x24, 0x28, 0x2c, 0x5e,
+ 0x18, 0xa5, 0x62, 0xf6, 0xb3, 0xb2, 0xc5, 0xed, 0x39, 0xab, 0x15, 0x26,
+ 0xf7, 0x07, 0xef, 0xdf, 0x78, 0xe6, 0xd9, 0x62, 0xa0, 0x8e, 0x97, 0x44,
+ 0xe2, 0xd7, 0x87, 0xef, 0xf0, 0x39, 0x85, 0x9c, 0x12, 0xc5, 0x61, 0xf7,
+ 0xb1, 0xe5, 0xfe, 0x98, 0x85, 0xcf, 0x39, 0xd6, 0x2d, 0x05, 0x8b, 0xfd,
+ 0x39, 0xd7, 0xb3, 0x52, 0xb1, 0x5b, 0x1f, 0xd6, 0x8d, 0x48, 0x4a, 0xff,
+ 0xd3, 0xf0, 0xf8, 0x59, 0xef, 0xe2, 0xc5, 0xff, 0xdf, 0x17, 0x39, 0x3a,
+ 0xdf, 0x03, 0xc5, 0x8b, 0xd8, 0x06, 0x58, 0xbf, 0x3f, 0x5e, 0x0f, 0x65,
+ 0x8b, 0x76, 0x74, 0x47, 0xfd, 0x1f, 0x83, 0x97, 0xa4, 0x18, 0xb1, 0x7f,
+ 0xf4, 0x0d, 0x60, 0xfc, 0xfa, 0x91, 0x77, 0xeb, 0x15, 0xf3, 0xe8, 0x61,
+ 0xca, 0xc4, 0x60, 0x0a, 0x13, 0xf7, 0xfd, 0x9d, 0x7d, 0xf6, 0x26, 0x82,
+ 0xc5, 0xef, 0xcf, 0x4b, 0x17, 0xff, 0xfb, 0xde, 0x72, 0x34, 0xcf, 0x1a,
+ 0x2d, 0x73, 0x8f, 0x9d, 0x2c, 0x5f, 0xec, 0xeb, 0xdf, 0xc1, 0x6e, 0xb1,
+ 0x7e, 0xd6, 0x76, 0x6f, 0xac, 0x5f, 0xb6, 0x92, 0x9e, 0x96, 0x28, 0x91,
+ 0x13, 0xc3, 0x61, 0x15, 0x5f, 0xb7, 0x79, 0x28, 0x2c, 0x57, 0x47, 0xae,
+ 0x45, 0xf5, 0x89, 0xb4, 0x34, 0x68, 0xd5, 0x2c, 0x93, 0x3c, 0x86, 0xab,
+ 0xca, 0x28, 0xd2, 0x17, 0xe3, 0x8e, 0x68, 0x4d, 0x00, 0xbc, 0xa3, 0x8e,
+ 0xe1, 0x3f, 0x8e, 0x85, 0x1c, 0x35, 0xff, 0xf8, 0xd7, 0xf1, 0x64, 0x3a,
+ 0xf1, 0x3e, 0xdc, 0x12, 0xc5, 0xfb, 0x92, 0x59, 0xb2, 0xc5, 0xc3, 0x95,
+ 0x8b, 0x76, 0x93, 0x7e, 0x32, 0x8b, 0xff, 0xb3, 0x46, 0x67, 0xd8, 0xd2,
+ 0x17, 0x16, 0x29, 0xd3, 0x05, 0x68, 0x4b, 0x88, 0xa2, 0xff, 0xc6, 0xb6,
+ 0xff, 0x78, 0xb3, 0xaf, 0x2c, 0x5f, 0x9a, 0x61, 0x30, 0x58, 0xb4, 0x7a,
+ 0xc5, 0xdd, 0x40, 0xc3, 0x79, 0x11, 0x3d, 0xd8, 0x05, 0x8b, 0x9a, 0x0c,
+ 0x78, 0xe4, 0x61, 0x73, 0xfd, 0x62, 0xff, 0xfe, 0xd4, 0x0c, 0x1f, 0xe4,
+ 0xc2, 0xce, 0xbd, 0x38, 0x12, 0xc5, 0xdc, 0xe2, 0xc5, 0xfa, 0x73, 0xdc,
+ 0x65, 0x8b, 0xf3, 0x3f, 0x04, 0x6a, 0xc5, 0xe0, 0x82, 0x09, 0x62, 0xe0,
+ 0x32, 0x44, 0x61, 0xa1, 0xbf, 0xda, 0x9e, 0xd9, 0x87, 0x1a, 0xc5, 0x18,
+ 0x9a, 0xf3, 0x8b, 0xe9, 0x7c, 0xe3, 0x1f, 0x27, 0xe2, 0x50, 0x8a, 0xaf,
+ 0xa0, 0xe4, 0x6a, 0xc5, 0xfe, 0x26, 0x36, 0x22, 0x78, 0x96, 0x2a, 0x23,
+ 0xd8, 0xe1, 0x1d, 0xf0, 0xbc, 0x26, 0x58, 0xac, 0x3c, 0x62, 0x23, 0xbf,
+ 0x81, 0x30, 0xf8, 0x7c, 0x58, 0xbd, 0xdf, 0xf7, 0xf2, 0xb1, 0x7f, 0xee,
+ 0xe3, 0x33, 0x77, 0xf7, 0x05, 0xa5, 0x8b, 0xd1, 0x48, 0xd6, 0x2f, 0xdc,
+ 0x11, 0x4c, 0x16, 0x2f, 0xf3, 0xfd, 0xb8, 0xfa, 0x95, 0x8b, 0xed, 0x4e,
+ 0x16, 0x1f, 0xc3, 0x0f, 0x70, 0xa2, 0xf0, 0x30, 0x96, 0x2b, 0x0f, 0x78,
+ 0x48, 0x54, 0xe9, 0x9e, 0x72, 0x31, 0xbb, 0xf9, 0xc8, 0x1b, 0xee, 0xeb,
+ 0x17, 0x98, 0x18, 0x91, 0x50, 0x5d, 0xad, 0xe8, 0xd3, 0x50, 0xc6, 0x3c,
+ 0x71, 0x3f, 0x8c, 0x0c, 0x04, 0x04, 0x61, 0xe8, 0xd8, 0xfb, 0x14, 0xc7,
+ 0x17, 0xdf, 0x48, 0xdc, 0x6b, 0x17, 0xee, 0xd9, 0x9d, 0x8d, 0x58, 0xbf,
+ 0xfe, 0xeb, 0xd2, 0x3c, 0x22, 0xc3, 0x70, 0x80, 0xb1, 0x52, 0x7f, 0x9a,
+ 0x2d, 0xbf, 0xb9, 0xf7, 0xdd, 0xb4, 0xb1, 0x7e, 0x1e, 0x9c, 0x5b, 0x2c,
+ 0x5f, 0x7b, 0x8d, 0xd2, 0xc5, 0xbc, 0xb1, 0x58, 0x6d, 0x8d, 0x24, 0xbf,
+ 0xfc, 0xe6, 0xfd, 0xc3, 0xd7, 0xa1, 0x31, 0xd8, 0xb1, 0x7f, 0x82, 0xc2,
+ 0xce, 0xcf, 0xa5, 0x8b, 0xff, 0x67, 0x27, 0x61, 0x89, 0xb5, 0x05, 0x8b,
+ 0xcf, 0x09, 0x58, 0xbd, 0xb8, 0x67, 0x58, 0xbc, 0x00, 0xce, 0xb1, 0x43,
+ 0x44, 0xdc, 0x48, 0x00, 0x1c, 0xf1, 0x05, 0xfc, 0x59, 0xd0, 0x03, 0x82,
+ 0xc5, 0xd9, 0xc5, 0x8b, 0xec, 0x3b, 0xf9, 0x62, 0xff, 0xec, 0xf8, 0x67,
+ 0xcd, 0xe7, 0xf2, 0x75, 0x8b, 0x73, 0x0f, 0xfc, 0x85, 0xfc, 0x45, 0x6e,
+ 0x2c, 0x56, 0x2b, 0x01, 0x88, 0xbf, 0x4c, 0x1f, 0x21, 0x24, 0xfe, 0x43,
+ 0x43, 0xc7, 0xc2, 0x85, 0x78, 0x46, 0x77, 0xef, 0xfd, 0x87, 0x2b, 0x17,
+ 0xbd, 0xfc, 0x58, 0xbf, 0xff, 0x4f, 0x60, 0xf4, 0xc0, 0xcd, 0x69, 0xcd,
+ 0x9d, 0x2c, 0x56, 0x1f, 0xb6, 0x87, 0x6f, 0xa4, 0xe6, 0x71, 0x62, 0xa5,
+ 0x1c, 0x79, 0x09, 0xe7, 0x21, 0xb9, 0x8e, 0xb1, 0x7f, 0xff, 0x61, 0x14,
+ 0xc3, 0x53, 0xc2, 0xce, 0xcf, 0xf1, 0x2c, 0x5f, 0xcc, 0xfc, 0xfc, 0x9d,
+ 0x62, 0xff, 0x73, 0xd3, 0x10, 0xba, 0xe2, 0xc5, 0x7c, 0xf9, 0x04, 0x5b,
+ 0x7c, 0xfa, 0xd4, 0xac, 0x5f, 0xec, 0xed, 0x91, 0x81, 0x04, 0x12, 0x45,
+ 0xe0, 0xb3, 0xeb, 0x17, 0xe8, 0xa7, 0x3f, 0xc5, 0x8a, 0x31, 0x18, 0xff,
+ 0x22, 0x22, 0x2f, 0x1e, 0x06, 0x3d, 0x7f, 0xbb, 0xf9, 0x16, 0xff, 0x7d,
+ 0x2c, 0x5e, 0x3b, 0x79, 0x62, 0xc0, 0x58, 0xbf, 0x4c, 0x42, 0x60, 0xd6,
+ 0x2b, 0x0d, 0xe1, 0x09, 0x54, 0x4a, 0xa6, 0x4e, 0x2f, 0xf8, 0xe1, 0x44,
+ 0x97, 0xd8, 0xe8, 0x35, 0x9b, 0xc7, 0x7e, 0x2c, 0x5f, 0xff, 0x60, 0xd9,
+ 0xc9, 0xbc, 0xe5, 0x0e, 0x62, 0xc5, 0xfd, 0xf6, 0xd3, 0xe6, 0x96, 0x2a,
+ 0x4f, 0xe5, 0x93, 0x29, 0x62, 0xfb, 0xad, 0xdf, 0x4b, 0x16, 0x04, 0x6e,
+ 0x6c, 0x7c, 0x19, 0x7f, 0xbb, 0x7d, 0xf2, 0x0d, 0xd9, 0x62, 0xfd, 0xd9,
+ 0x8e, 0xe7, 0x58, 0xa9, 0x44, 0x6e, 0x16, 0x11, 0xbd, 0xed, 0x7f, 0x16,
+ 0x2f, 0xa2, 0x84, 0xc1, 0x62, 0xa4, 0xf0, 0x70, 0x76, 0xfa, 0x43, 0x70,
+ 0x2c, 0x5c, 0x2f, 0xac, 0x5f, 0x39, 0xfb, 0xc3, 0x56, 0x2f, 0xc5, 0xad,
+ 0x0b, 0xeb, 0x17, 0xf1, 0xfc, 0x53, 0x9d, 0x2c, 0x5f, 0xff, 0xdc, 0xcf,
+ 0xbf, 0x05, 0xb7, 0xe4, 0xfe, 0xe4, 0xe2, 0xc5, 0xff, 0xfe, 0xf6, 0x39,
+ 0x6c, 0xdc, 0xce, 0xcf, 0xe7, 0xe3, 0x01, 0x62, 0xfc, 0xfe, 0xe7, 0xdc,
+ 0x68, 0xeb, 0xe1, 0x70, 0x6b, 0x95, 0xb2, 0x78, 0xb1, 0x11, 0xfc, 0x61,
+ 0x8a, 0x7d, 0x18, 0xa5, 0xf4, 0xe1, 0x0d, 0x62, 0xde, 0x58, 0xb6, 0xc3,
+ 0x36, 0x7b, 0x90, 0xd4, 0xb3, 0x5e, 0xa1, 0x0a, 0xac, 0x84, 0xf3, 0xcb,
+ 0x22, 0xfc, 0x6d, 0xad, 0x2b, 0x2c, 0x0c, 0x65, 0x09, 0x6e, 0x43, 0x7b,
+ 0xcd, 0xc2, 0x8f, 0x94, 0x38, 0x42, 0xdf, 0x8c, 0x9e, 0x4c, 0x16, 0x2f,
+ 0xfe, 0xdb, 0x3d, 0x9f, 0x9d, 0x02, 0x74, 0xb1, 0x7f, 0x77, 0xfe, 0x35,
+ 0xc2, 0xe2, 0xc5, 0x68, 0xfe, 0xc4, 0x8b, 0x7f, 0xdf, 0x6f, 0x06, 0x39,
+ 0xc2, 0x58, 0xbe, 0x72, 0x14, 0xac, 0x5f, 0xe9, 0x2d, 0xf3, 0xdf, 0x75,
+ 0x8a, 0x81, 0xea, 0x68, 0x86, 0xfb, 0x20, 0xe4, 0xb1, 0x5b, 0x1e, 0x1e,
+ 0xe4, 0x57, 0x98, 0x0e, 0xb1, 0x7f, 0xec, 0xed, 0x33, 0xf9, 0xda, 0x7a,
+ 0x58, 0xbf, 0xe1, 0x90, 0xb9, 0x9b, 0x66, 0xcb, 0x17, 0xa7, 0x44, 0xb1,
+ 0x7f, 0xf8, 0x12, 0x59, 0xd7, 0x9b, 0x9c, 0x93, 0xac, 0x5f, 0xfe, 0x26,
+ 0x1c, 0x8f, 0xf3, 0x9d, 0x9b, 0x4b, 0x17, 0xa1, 0x83, 0x58, 0xbf, 0xd8,
+ 0x32, 0x6e, 0x38, 0xd6, 0x2d, 0xf5, 0x8b, 0x6d, 0x88, 0xab, 0x64, 0xa2,
+ 0x1d, 0xe1, 0x95, 0x85, 0x89, 0x9b, 0x34, 0x3d, 0x6b, 0x49, 0xbf, 0xfa,
+ 0x35, 0x2b, 0xe3, 0xf3, 0x0e, 0xb1, 0x4e, 0x79, 0xac, 0x55, 0x7f, 0x4e,
+ 0xbd, 0xec, 0x8f, 0x58, 0xbf, 0xb8, 0xff, 0x9e, 0xa0, 0xb1, 0x76, 0xba,
+ 0x58, 0xba, 0x7b, 0x2c, 0x50, 0xd7, 0x34, 0x32, 0x14, 0x9b, 0x91, 0x6a,
+ 0x1a, 0x07, 0x24, 0xf8, 0xe3, 0x20, 0xf7, 0xf2, 0x81, 0xc8, 0x83, 0x86,
+ 0x21, 0x97, 0xf7, 0x0c, 0xdf, 0xc1, 0x8c, 0xa7, 0x36, 0x58, 0xbf, 0xdc,
+ 0x2c, 0x03, 0x10, 0x16, 0x2f, 0xfd, 0x06, 0xf0, 0xa7, 0x52, 0x28, 0xf5,
+ 0x8b, 0x12, 0xc5, 0xed, 0xa6, 0x0b, 0x14, 0xb1, 0x52, 0x6a, 0xb6, 0x1e,
+ 0xbf, 0xb3, 0xdc, 0x70, 0xbc, 0xb1, 0x7d, 0x02, 0x63, 0x56, 0x28, 0x67,
+ 0xa5, 0x85, 0xf4, 0x34, 0xdc, 0xba, 0x2f, 0xd1, 0x93, 0x21, 0x11, 0xd8,
+ 0x4e, 0x77, 0xf7, 0xdf, 0xc5, 0x27, 0x58, 0xbf, 0xf8, 0x3f, 0x47, 0x3f,
+ 0x3d, 0xf7, 0x60, 0x2c, 0x5f, 0xff, 0xd0, 0x29, 0x7d, 0x60, 0xf5, 0x3e,
+ 0x7d, 0xdc, 0x6b, 0x17, 0xff, 0xb0, 0x6c, 0x7c, 0xea, 0x18, 0x0c, 0x1a,
+ 0xc5, 0xdf, 0x65, 0x8b, 0xa2, 0xe2, 0xc5, 0xfb, 0x3b, 0x39, 0x0f, 0x0d,
+ 0x80, 0x62, 0xf7, 0xf1, 0x9e, 0xce, 0x72, 0x56, 0x2f, 0xb3, 0xaf, 0x4a,
+ 0xc5, 0xff, 0xcd, 0xac, 0x35, 0xf5, 0x9d, 0x9b, 0x4b, 0x15, 0xf3, 0xe9,
+ 0xec, 0x47, 0x7f, 0xfb, 0x3a, 0xf4, 0xe0, 0x59, 0x09, 0x07, 0x16, 0x2f,
+ 0xfc, 0x59, 0xad, 0x39, 0xf3, 0xaf, 0x2c, 0x5f, 0xfd, 0xcc, 0x17, 0x7f,
+ 0x87, 0x6f, 0xe6, 0xeb, 0x17, 0xee, 0xe6, 0xd8, 0x38, 0x2c, 0x51, 0x8a,
+ 0x9d, 0xa3, 0x1e, 0xa4, 0xfb, 0x21, 0x30, 0x44, 0x9c, 0x4b, 0xf1, 0xf8,
+ 0x92, 0xaf, 0xb3, 0xf9, 0xba, 0xc5, 0xdf, 0x65, 0x8b, 0xff, 0x7d, 0xd8,
+ 0x18, 0x53, 0xd7, 0x16, 0x2c, 0x33, 0x0f, 0xe3, 0x08, 0xfc, 0x2f, 0x7f,
+ 0xdf, 0xcf, 0x7d, 0xe4, 0xb6, 0x58, 0xbe, 0x22, 0x90, 0x96, 0x2f, 0x47,
+ 0x4f, 0x16, 0x2f, 0x14, 0x3f, 0x87, 0x84, 0xc4, 0x57, 0xff, 0xf0, 0x0e,
+ 0xe6, 0x41, 0xfd, 0xc7, 0xfb, 0x0f, 0x3a, 0x58, 0xbf, 0xfb, 0x69, 0xd6,
+ 0x9a, 0x06, 0x00, 0x78, 0xb1, 0x58, 0x8a, 0x46, 0x5d, 0xac, 0x47, 0xb1,
+ 0x43, 0x56, 0x96, 0x2e, 0xe0, 0x16, 0x2e, 0xea, 0x18, 0x69, 0x03, 0x0c,
+ 0xbd, 0x1e, 0x7c, 0x58, 0xbf, 0xde, 0x7d, 0x37, 0xd8, 0xeb, 0x17, 0xfd,
+ 0x07, 0x8b, 0xa8, 0x7c, 0x40, 0x58, 0xbe, 0xcf, 0x7d, 0xe5, 0x12, 0x1d,
+ 0x10, 0x44, 0x67, 0x4c, 0x98, 0x29, 0x42, 0xfa, 0xff, 0xb5, 0xa6, 0x81,
+ 0x9d, 0xa6, 0x3d, 0x62, 0xa4, 0xf9, 0xf0, 0x9e, 0xf1, 0xde, 0x56, 0x2a,
+ 0x53, 0xf2, 0x84, 0x76, 0xcc, 0x41, 0x46, 0xaf, 0xeb, 0xf4, 0x93, 0xa9,
+ 0x5a, 0x05, 0x0f, 0x1e, 0x1a, 0xfa, 0x5b, 0x1d, 0xfe, 0xc0, 0xbc, 0x52,
+ 0x7e, 0x2c, 0x5f, 0xb0, 0x9b, 0xdc, 0x58, 0xba, 0x1d, 0x96, 0x2f, 0xee,
+ 0x7f, 0x09, 0xf8, 0xb1, 0x7f, 0x8b, 0x70, 0xfd, 0xc1, 0x0d, 0x62, 0xfe,
+ 0xdc, 0x26, 0x22, 0x95, 0x8a, 0x82, 0x34, 0xc6, 0x4f, 0xa1, 0xa6, 0x2d,
+ 0x23, 0x7b, 0xbb, 0xfc, 0x58, 0xbe, 0x8b, 0xef, 0xa5, 0x8b, 0xe6, 0x18,
+ 0x67, 0x58, 0xbb, 0x38, 0x61, 0xf2, 0x77, 0xa3, 0x90, 0x24, 0xa9, 0x65,
+ 0x5e, 0xe2, 0xc3, 0xd2, 0x01, 0x34, 0xdc, 0xd1, 0x83, 0x94, 0x2b, 0x2e,
+ 0xee, 0xf2, 0xc5, 0xff, 0xf0, 0xb5, 0x83, 0xfc, 0xbf, 0xb8, 0xe5, 0x05,
+ 0x8b, 0xfe, 0xc1, 0xe1, 0x49, 0x0a, 0x56, 0x2f, 0x82, 0x6f, 0xf1, 0x62,
+ 0x96, 0x2b, 0xa3, 0x60, 0x11, 0x25, 0xfb, 0x06, 0x53, 0xd2, 0xc5, 0xff,
+ 0xba, 0xf4, 0xf5, 0x0f, 0x02, 0x60, 0xb1, 0x7e, 0x97, 0x83, 0x71, 0x62,
+ 0xc0, 0xc3, 0xe9, 0xd2, 0x15, 0xfe, 0xf1, 0x3f, 0x5c, 0x0c, 0xeb, 0x17,
+ 0xec, 0x8a, 0x0d, 0xc5, 0x8a, 0xfa, 0x62, 0xe5, 0x09, 0x1e, 0x13, 0xf8,
+ 0xda, 0xfc, 0xcd, 0xd4, 0x38, 0xb1, 0x7f, 0xf9, 0xc2, 0xcf, 0x75, 0x0c,
+ 0xd7, 0x50, 0xe2, 0xc5, 0x4a, 0x7e, 0x6f, 0x19, 0xd6, 0x90, 0xbc, 0x53,
+ 0x46, 0x43, 0xbc, 0xf6, 0x59, 0xf6, 0x96, 0x47, 0x0a, 0xd8, 0xb4, 0x74,
+ 0xea, 0x5c, 0x97, 0x1a, 0x6c, 0xec, 0xee, 0xf4, 0xf5, 0xee, 0xa5, 0x34,
+ 0x3c, 0xe3, 0x24, 0x7c, 0x39, 0x22, 0x96, 0x97, 0xab, 0x44, 0xfa, 0x7a,
+ 0x74, 0x27, 0xeb, 0x75, 0x76, 0x8d, 0xa8, 0x12, 0xf7, 0xca, 0xbd, 0x6e,
+ 0xe5, 0x35, 0x8f, 0xd5, 0xa7, 0x30, 0xa7, 0x6a, 0x3b, 0x53, 0x3b, 0xc2,
+ 0x6a, 0x8e, 0x1b, 0x0d, 0x3f, 0xba, 0x52, 0xcd, 0xf4, 0xf9, 0xfc, 0xb1,
+ 0x7e, 0x9f, 0x43, 0x3e, 0xb1, 0x6d, 0x7c, 0xf2, 0x88, 0x8a, 0xf7, 0x24,
+ 0x0b, 0x15, 0x87, 0x89, 0xe2, 0x7b, 0xa3, 0x6e, 0xfb, 0x58, 0xbf, 0xa7,
+ 0xb3, 0x1b, 0xf7, 0x58, 0xbd, 0x84, 0xcb, 0x17, 0x39, 0x98, 0x79, 0x66,
+ 0x98, 0x5f, 0xfb, 0xf8, 0x3f, 0xe3, 0x16, 0x47, 0xac, 0x5c, 0xfe, 0x58,
+ 0xbe, 0xf3, 0x7e, 0x56, 0x2f, 0x40, 0xb3, 0x73, 0x73, 0xd0, 0xbd, 0xff,
+ 0xc5, 0xb9, 0xad, 0xcc, 0x84, 0x96, 0xeb, 0x17, 0xd8, 0x36, 0x82, 0xc5,
+ 0xcf, 0xb2, 0xc5, 0x00, 0xdd, 0x78, 0x8a, 0xb1, 0x34, 0xde, 0x9e, 0x5c,
+ 0xcc, 0xa1, 0x01, 0x7e, 0x79, 0x3b, 0x0d, 0x62, 0xff, 0x67, 0xcb, 0x3d,
+ 0xf7, 0x58, 0xbb, 0xdc, 0xf9, 0xec, 0xf8, 0x9e, 0xdd, 0x96, 0x2f, 0xf7,
+ 0xbf, 0x9e, 0xd6, 0x04, 0xb1, 0x51, 0xe7, 0x92, 0x42, 0x97, 0xc3, 0xd3,
+ 0x41, 0x62, 0xdd, 0xcb, 0x17, 0xfe, 0x79, 0x34, 0xb3, 0xb3, 0xe9, 0x96,
+ 0x2f, 0xf4, 0x97, 0xdf, 0xb6, 0x44, 0xb1, 0x44, 0x7e, 0x9e, 0x3f, 0xa8,
+ 0xd1, 0x15, 0x50, 0x84, 0x4d, 0xed, 0xb3, 0xa5, 0x8a, 0xd1, 0xe6, 0x11,
+ 0x6d, 0xfe, 0x60, 0xbe, 0xfa, 0x68, 0x2c, 0x5d, 0x3d, 0x2c, 0x5f, 0xbf,
+ 0x31, 0xf8, 0x35, 0x8a, 0x58, 0xb4, 0x8c, 0xdb, 0x80, 0xae, 0xa3, 0x8f,
+ 0xd4, 0x34, 0xfb, 0xfa, 0x48, 0x51, 0x4f, 0x16, 0x2f, 0xbe, 0x29, 0xe2,
+ 0xc5, 0xe6, 0x60, 0x2c, 0x5d, 0x3c, 0x93, 0x7f, 0xa2, 0x3b, 0xf6, 0xfe,
+ 0x9e, 0xbc, 0xb1, 0x5f, 0x3d, 0x61, 0x15, 0xdf, 0xfb, 0xee, 0x53, 0xd7,
+ 0x1c, 0xf2, 0xb1, 0x7b, 0x93, 0xa5, 0x8b, 0xff, 0xfb, 0x3a, 0xf3, 0x0f,
+ 0xf3, 0xcc, 0x7d, 0xb6, 0x6e, 0x96, 0x2d, 0xc1, 0xa3, 0x6f, 0x72, 0x2e,
+ 0x8f, 0x88, 0x76, 0xb6, 0x4f, 0x8b, 0xd1, 0xcf, 0x54, 0xae, 0x58, 0xe3,
+ 0xb9, 0xa4, 0x8f, 0x18, 0xce, 0x88, 0x5a, 0x15, 0x22, 0x94, 0x11, 0x7a,
+ 0x1e, 0x3a, 0xc5, 0xfc, 0x59, 0x08, 0x37, 0x16, 0x2f, 0xe9, 0x0f, 0x83,
+ 0xe8, 0xeb, 0x15, 0xb9, 0xef, 0x11, 0x6d, 0xfb, 0x83, 0x90, 0xce, 0xb1,
+ 0x7b, 0x73, 0x59, 0x62, 0xf0, 0x03, 0xf2, 0xc5, 0xf6, 0x7d, 0xb4, 0xb1,
+ 0x58, 0x78, 0x24, 0x3f, 0x5b, 0xa2, 0x00, 0x26, 0x0b, 0xbf, 0xba, 0xc5,
+ 0x62, 0x3a, 0x1a, 0x15, 0x41, 0x92, 0xdc, 0x37, 0x58, 0xbe, 0xeb, 0x93,
+ 0xd2, 0xc5, 0xcd, 0x03, 0x0d, 0xe3, 0x8b, 0xde, 0x37, 0xee, 0xb1, 0x7f,
+ 0xed, 0x4f, 0x6f, 0xcb, 0xe9, 0xe2, 0x58, 0xbf, 0x66, 0x85, 0x20, 0x58,
+ 0xa8, 0x8f, 0xa4, 0x90, 0x6d, 0xb2, 0xc5, 0xe0, 0x69, 0xd6, 0x2a, 0x08,
+ 0xd9, 0xea, 0x10, 0xec, 0x44, 0x42, 0x77, 0xd1, 0xcd, 0x9f, 0x58, 0xbf,
+ 0xff, 0xd2, 0x17, 0xdb, 0xdc, 0xcd, 0x14, 0xf5, 0x0c, 0xeb, 0xcb, 0x17,
+ 0xd9, 0xee, 0x32, 0xc5, 0x87, 0xa4, 0x42, 0xfd, 0x8e, 0xff, 0x70, 0xb0,
+ 0xec, 0xdb, 0x2c, 0x54, 0x13, 0x06, 0x68, 0x55, 0x08, 0xa6, 0xfe, 0xe6,
+ 0x0d, 0xf9, 0xb2, 0xc5, 0xe8, 0x48, 0x16, 0x2f, 0xc1, 0xc5, 0x09, 0x8f,
+ 0x48, 0xa9, 0x66, 0x5e, 0xec, 0x42, 0x36, 0xfc, 0x8d, 0xec, 0xd9, 0xd4,
+ 0xbd, 0xdd, 0x9d, 0xf3, 0x51, 0x85, 0x7d, 0xc1, 0xa3, 0x05, 0x28, 0xd1,
+ 0xf8, 0x6b, 0xe2, 0xf0, 0xc7, 0x6f, 0xe1, 0xe9, 0xb7, 0x6d, 0xd6, 0x2f,
+ 0xff, 0xfb, 0xbe, 0xbb, 0x4c, 0x68, 0x79, 0xef, 0xac, 0x6d, 0x1a, 0xfd,
+ 0xb0, 0x0c, 0x33, 0xf1, 0xcb, 0x16, 0xdd, 0x62, 0xff, 0xc4, 0x26, 0x0f,
+ 0x38, 0xf2, 0x4b, 0x17, 0xe8, 0x73, 0xdd, 0x80, 0xb1, 0x46, 0x9f, 0x4f,
+ 0x47, 0xb7, 0xa3, 0x9c, 0x6b, 0x17, 0xf8, 0xdf, 0xb4, 0x35, 0x26, 0xac,
+ 0x56, 0x8f, 0xe8, 0xe4, 0x84, 0x41, 0x7e, 0x2c, 0xec, 0xda, 0x58, 0xbf,
+ 0xe8, 0x3f, 0xd9, 0xc7, 0x24, 0xb1, 0x46, 0x1f, 0x04, 0x94, 0xde, 0x96,
+ 0xd2, 0xc5, 0xf1, 0xb9, 0xc7, 0x58, 0xb8, 0xb7, 0x58, 0xbf, 0xf7, 0x73,
+ 0xed, 0xac, 0x92, 0xe3, 0xac, 0x5f, 0x83, 0xf7, 0x85, 0xf5, 0x8a, 0x31,
+ 0x14, 0xee, 0x46, 0x43, 0x1d, 0x90, 0x6f, 0xe3, 0xfb, 0xf3, 0xda, 0x56,
+ 0x2f, 0xfd, 0x1e, 0x66, 0xff, 0x7d, 0x3c, 0x9d, 0x62, 0xf1, 0x6e, 0x05,
+ 0x8a, 0xd8, 0xf8, 0xb1, 0x12, 0xfb, 0x3a, 0x01, 0x2c, 0x5f, 0xd0, 0x9f,
+ 0x7d, 0xa0, 0xb1, 0x44, 0x7a, 0x3e, 0x23, 0xbf, 0xf7, 0x84, 0x7f, 0xcb,
+ 0x93, 0x0d, 0x62, 0xff, 0xfb, 0x02, 0x30, 0x6f, 0x9d, 0x43, 0x84, 0xdb,
+ 0x2c, 0x5f, 0x42, 0x0d, 0xe5, 0x8a, 0xd9, 0x1a, 0xbd, 0x10, 0xfc, 0xf9,
+ 0x94, 0xef, 0x03, 0xe2, 0x58, 0xbe, 0x37, 0x4c, 0x12, 0xc5, 0xdb, 0x7d,
+ 0x62, 0xed, 0xfb, 0x2c, 0x58, 0x35, 0x48, 0x0a, 0x5b, 0xca, 0xc0, 0x50,
+ 0xa9, 0x3f, 0x3d, 0x0c, 0xf8, 0x6c, 0x22, 0x0a, 0xc4, 0x6a, 0x3c, 0x26,
+ 0x2f, 0xed, 0xdf, 0x6f, 0x30, 0xd6, 0x2f, 0xef, 0xcf, 0xf3, 0xaf, 0x2c,
+ 0x5e, 0x69, 0xe9, 0x62, 0xff, 0x0b, 0x81, 0x96, 0x75, 0x05, 0x8b, 0x77,
+ 0x18, 0x7a, 0x7f, 0x1d, 0xbf, 0x9f, 0xbf, 0xdf, 0xf2, 0x12, 0xc5, 0xfe,
+ 0xfb, 0x87, 0x18, 0x00, 0x4a, 0x45, 0x68, 0xfb, 0x63, 0x8d, 0x6f, 0xff,
+ 0xdc, 0x35, 0xbd, 0x07, 0x1f, 0x3f, 0x98, 0x5b, 0xac, 0x5f, 0xd9, 0xc7,
+ 0xf4, 0xf4, 0xb1, 0x7e, 0xc3, 0xb3, 0x6c, 0xb1, 0x7e, 0x9d, 0xff, 0x3a,
+ 0x58, 0xbf, 0x7d, 0xb9, 0x38, 0xb1, 0x7b, 0xe2, 0x35, 0x62, 0xf7, 0x77,
+ 0x7f, 0xc5, 0x8b, 0xcc, 0x77, 0x58, 0xa3, 0x11, 0x11, 0xf2, 0x72, 0x1f,
+ 0x11, 0x35, 0xe0, 0xe4, 0x0b, 0x15, 0xb2, 0xb2, 0x93, 0x4c, 0x3a, 0x84,
+ 0x13, 0xc2, 0x67, 0x44, 0xbf, 0x57, 0x22, 0xef, 0x14, 0x07, 0x0b, 0x1e,
+ 0xe3, 0xdb, 0xb0, 0x4b, 0x17, 0xfe, 0x87, 0xc3, 0xd4, 0x8f, 0xf8, 0x12,
+ 0xc5, 0xfb, 0xf2, 0x2e, 0x9d, 0x62, 0x8d, 0x44, 0x17, 0x42, 0xe7, 0x42,
+ 0xbf, 0x78, 0xfc, 0x8d, 0xe3, 0x5a, 0xc5, 0xff, 0x10, 0x07, 0xf6, 0x0f,
+ 0x36, 0x58, 0xbf, 0x60, 0xbb, 0xfc, 0xe2, 0xc5, 0x39, 0xf4, 0x7c, 0xee,
+ 0xfb, 0x09, 0xc2, 0x58, 0xbf, 0xf8, 0xd6, 0x62, 0x01, 0x09, 0xba, 0xef,
+ 0x16, 0x2b, 0xa3, 0xec, 0x22, 0x2b, 0xfe, 0xf7, 0x33, 0xc5, 0x27, 0xe2,
+ 0xc5, 0xfa, 0x40, 0xc4, 0x05, 0x8b, 0xf0, 0xba, 0xf3, 0x84, 0xb1, 0x6f,
+ 0x18, 0x88, 0xb8, 0x1c, 0xf0, 0x9e, 0xb1, 0x1c, 0x85, 0x0a, 0xdb, 0xfe,
+ 0x2c, 0xd0, 0xff, 0x3d, 0x41, 0x62, 0xff, 0xf4, 0x9c, 0x4c, 0x3f, 0x75,
+ 0xbb, 0x90, 0x4b, 0x16, 0xc2, 0x44, 0x38, 0x47, 0x57, 0xff, 0xfd, 0x9a,
+ 0x1f, 0xe7, 0xae, 0x16, 0x44, 0xe2, 0x2d, 0xb3, 0x75, 0x8b, 0xff, 0xe1,
+ 0x6c, 0x19, 0xf8, 0xfb, 0xbe, 0xc1, 0x37, 0x4b, 0x17, 0xf7, 0x5f, 0x7c,
+ 0xd4, 0x4b, 0x14, 0xe8, 0x87, 0x65, 0x7b, 0xff, 0x75, 0xed, 0xfe, 0xe3,
+ 0xfe, 0x6c, 0xb1, 0x7f, 0x3f, 0x5c, 0xfb, 0x84, 0xb1, 0x6e, 0xfd, 0x62,
+ 0x80, 0x78, 0xe4, 0x61, 0x58, 0x8a, 0xbd, 0x42, 0x2a, 0xfe, 0x6e, 0x66,
+ 0x11, 0xab, 0x15, 0x87, 0xa8, 0x22, 0x7b, 0xcc, 0xc1, 0x2c, 0x54, 0xab,
+ 0x23, 0x1c, 0x2b, 0x5c, 0xa3, 0x50, 0xf0, 0xfc, 0x64, 0x04, 0x43, 0x7f,
+ 0xfe, 0x66, 0x20, 0x1e, 0x7a, 0x80, 0xff, 0x25, 0xba, 0xc5, 0xf6, 0x1d,
+ 0xc6, 0xb1, 0x7f, 0x9a, 0x3c, 0xd3, 0x67, 0xdc, 0x58, 0xbb, 0xdc, 0x30,
+ 0xf6, 0xc3, 0x22, 0xbf, 0xe6, 0xd4, 0x45, 0x20, 0xe0, 0x96, 0x2a, 0x4f,
+ 0xa8, 0x66, 0x17, 0xef, 0x60, 0x8b, 0xcb, 0x17, 0xe8, 0x70, 0x39, 0x8f,
+ 0x58, 0xb4, 0xe1, 0xea, 0xb1, 0x45, 0xff, 0x8c, 0x26, 0x34, 0xce, 0x00,
+ 0x12, 0xb1, 0x7f, 0xfc, 0x09, 0x2d, 0xf7, 0xfb, 0xf5, 0xb8, 0xa7, 0x4b,
+ 0x17, 0xf8, 0x4c, 0x5b, 0xc2, 0x76, 0x58, 0xbf, 0xd0, 0x7e, 0x72, 0x75,
+ 0x05, 0x8b, 0xdb, 0x08, 0x18, 0x8b, 0xd0, 0x2a, 0x70, 0xd6, 0xce, 0x6a,
+ 0x68, 0x3a, 0x87, 0xfd, 0xc2, 0xe2, 0xc5, 0xa3, 0x65, 0x8b, 0xff, 0xe1,
+ 0xbf, 0x0b, 0x3a, 0xdd, 0xfa, 0xce, 0xbc, 0xb1, 0x68, 0x40, 0xfa, 0xb0,
+ 0x5e, 0xfd, 0xd7, 0x24, 0xbc, 0xb1, 0x5a, 0x3d, 0x0f, 0x93, 0xd1, 0xd1,
+ 0xe8, 0xd0, 0xd2, 0xa8, 0x2a, 0xb0, 0xe4, 0x6c, 0xde, 0x8c, 0x8e, 0xff,
+ 0xff, 0x0f, 0xf3, 0xbf, 0xde, 0x26, 0x68, 0x1a, 0xc1, 0xb4, 0x7a, 0xc5,
+ 0xff, 0xff, 0xbe, 0xcf, 0xc7, 0x86, 0x0f, 0xdf, 0x97, 0xd6, 0x9c, 0xb6,
+ 0x58, 0xbe, 0x2c, 0xed, 0x8b, 0x15, 0xb2, 0x3d, 0x4e, 0xce, 0x13, 0x5d,
+ 0xdb, 0x46, 0x8b, 0x17, 0xf3, 0xc5, 0x09, 0x28, 0x2c, 0x53, 0x9e, 0x67,
+ 0xc7, 0xaf, 0xff, 0xe9, 0xf7, 0x03, 0x2f, 0x7c, 0x4d, 0x0f, 0x73, 0x02,
+ 0x58, 0xbf, 0xf4, 0xed, 0x9e, 0x86, 0x13, 0x8d, 0x62, 0xff, 0xfb, 0x4c,
+ 0xdd, 0x43, 0x9e, 0xeb, 0x77, 0xd1, 0xab, 0x17, 0xf4, 0x19, 0xca, 0x60,
+ 0xb1, 0x7f, 0x8e, 0xdd, 0x3c, 0xf5, 0xe5, 0x8a, 0x93, 0xe1, 0xc2, 0xcb,
+ 0x36, 0xc8, 0xd6, 0x84, 0x2d, 0xaf, 0xfc, 0xc1, 0x7b, 0x3f, 0xe7, 0x98,
+ 0xf5, 0x8b, 0xff, 0x48, 0x5c, 0xef, 0x5b, 0x7c, 0xeb, 0xcb, 0x15, 0x2a,
+ 0xb2, 0x37, 0x7e, 0xd1, 0x0f, 0xd7, 0x9a, 0x31, 0x42, 0x2e, 0xf2, 0x15,
+ 0xff, 0xb9, 0xf1, 0x34, 0x3f, 0x99, 0xe5, 0x8b, 0xe8, 0x7f, 0x36, 0x58,
+ 0xbf, 0xe7, 0x2c, 0x3c, 0x76, 0x3f, 0x4b, 0x17, 0xff, 0xf9, 0x8e, 0x59,
+ 0xd4, 0xeb, 0x4f, 0xdb, 0x59, 0xe6, 0xe9, 0x62, 0x86, 0x89, 0xee, 0x1d,
+ 0xdf, 0xff, 0xc3, 0x87, 0x35, 0x9e, 0x6e, 0xa2, 0x60, 0xe7, 0xdc, 0x58,
+ 0xbf, 0xff, 0xb3, 0xcd, 0xd7, 0xfe, 0xf3, 0xef, 0xe7, 0x69, 0xd2, 0xc5,
+ 0xff, 0xff, 0xb3, 0x59, 0xbf, 0xe7, 0x8d, 0xac, 0x1f, 0xd9, 0xf8, 0xe7,
+ 0x58, 0xbf, 0xff, 0xd2, 0xd2, 0xe4, 0xde, 0x83, 0xf6, 0xd6, 0x79, 0xba,
+ 0x58, 0xa9, 0x4e, 0xaa, 0x04, 0x7a, 0x5f, 0xe2, 0xec, 0x73, 0x5d, 0xe6,
+ 0x6e, 0xe5, 0x8b, 0xa4, 0xe6, 0x1f, 0x61, 0xd3, 0x6f, 0x9f, 0x6d, 0xe0,
+ 0xb1, 0x7f, 0xf0, 0x0c, 0x8a, 0x02, 0x2f, 0x34, 0x31, 0x62, 0xec, 0xee,
+ 0x58, 0xa6, 0x3e, 0x12, 0x47, 0xbf, 0xe9, 0xe8, 0xed, 0xec, 0xeb, 0xcb,
+ 0x17, 0x36, 0xcb, 0x15, 0x8b, 0x87, 0xdd, 0x1f, 0xbc, 0xad, 0x8d, 0x17,
+ 0x34, 0x21, 0x88, 0x80, 0x23, 0xbb, 0xdf, 0x6e, 0x2c, 0x5b, 0xa5, 0x8b,
+ 0xfb, 0xe5, 0x9e, 0x90, 0x2c, 0x54, 0x9e, 0xe8, 0xc7, 0x58, 0x4e, 0xff,
+ 0x1d, 0xb8, 0x53, 0x86, 0xac, 0x58, 0x4b, 0x17, 0xfc, 0x21, 0x7d, 0xfd,
+ 0xf6, 0x82, 0xc5, 0xe8, 0x67, 0x96, 0x2f, 0x9b, 0xf9, 0xa5, 0x8a, 0xf9,
+ 0xbf, 0xec, 0x3b, 0x7e, 0x17, 0xf5, 0x21, 0x2c, 0x5d, 0x1c, 0xcb, 0x14,
+ 0x62, 0x6a, 0x58, 0x5a, 0x69, 0x99, 0xc4, 0x99, 0xe7, 0xc4, 0x61, 0x95,
+ 0x5f, 0xf8, 0xd1, 0xfd, 0x8e, 0x71, 0x10, 0xd6, 0x2b, 0x74, 0x53, 0x93,
+ 0x35, 0xef, 0x14, 0xac, 0x54, 0x9b, 0xf7, 0x23, 0xbb, 0xbf, 0xe2, 0xc5,
+ 0xfb, 0x98, 0x3f, 0xba, 0xc5, 0xfc, 0xec, 0x0f, 0x37, 0x4b, 0x14, 0xe7,
+ 0xad, 0xf2, 0x8a, 0x24, 0x4a, 0x79, 0xce, 0xfa, 0x1f, 0x7e, 0xcb, 0x17,
+ 0xff, 0xb3, 0x82, 0xdf, 0xef, 0xd7, 0x1f, 0xa0, 0x2c, 0x5f, 0xfe, 0x1e,
+ 0xb1, 0xcd, 0x2c, 0xf7, 0x85, 0xb2, 0xc5, 0xe9, 0x2f, 0x18, 0x8e, 0x17,
+ 0x22, 0x22, 0x5e, 0x27, 0x5d, 0xa6, 0x58, 0xbf, 0xfb, 0xb3, 0xf3, 0x98,
+ 0x5b, 0xb1, 0x01, 0x62, 0xff, 0x7d, 0xc6, 0x3c, 0x0a, 0x25, 0x8b, 0xcf,
+ 0xd7, 0x16, 0x2f, 0xd9, 0xdb, 0x21, 0xdf, 0xac, 0x51, 0xa7, 0x9b, 0xf1,
+ 0xeb, 0x03, 0x11, 0xd9, 0xba, 0x37, 0xa1, 0x07, 0x7c, 0x1f, 0xdb, 0xcb,
+ 0x15, 0xa3, 0xdf, 0x39, 0xdd, 0xff, 0xf0, 0x39, 0xef, 0xe7, 0xbe, 0xd0,
+ 0xdb, 0x02, 0x58, 0xa9, 0x3f, 0x57, 0x22, 0xbf, 0xd2, 0x17, 0xb8, 0xc4,
+ 0x6a, 0xc5, 0xfe, 0x6c, 0xfb, 0xef, 0xfc, 0x58, 0xa7, 0x55, 0x57, 0xa4,
+ 0xcf, 0xc7, 0xae, 0x44, 0x01, 0x1a, 0xdf, 0xff, 0x07, 0xaf, 0xb1, 0x9c,
+ 0x2c, 0xd8, 0xf8, 0x75, 0x8b, 0xf7, 0x9c, 0xed, 0x05, 0x8b, 0xcd, 0xd7,
+ 0x0c, 0x3f, 0xbc, 0x53, 0xb7, 0x96, 0x28, 0x07, 0x8c, 0x19, 0xa5, 0xff,
+ 0xf1, 0x36, 0x7d, 0xf5, 0xf6, 0x17, 0xf0, 0xeb, 0x17, 0xfd, 0x9c, 0x71,
+ 0xc9, 0x48, 0x16, 0x2f, 0xfd, 0xbf, 0xd8, 0xbd, 0xc3, 0x94, 0xac, 0x5c,
+ 0x6c, 0x16, 0x2f, 0xf4, 0xe8, 0x03, 0x66, 0x35, 0x62, 0xb0, 0xf3, 0x7e,
+ 0x33, 0x7e, 0xfb, 0xef, 0xfc, 0x31, 0x1c, 0x9c, 0x37, 0xf4, 0x23, 0x2f,
+ 0xef, 0x4e, 0xf0, 0xe4, 0xac, 0x50, 0xd3, 0xb4, 0xc8, 0xcc, 0xba, 0x53,
+ 0xbf, 0xcc, 0x5e, 0x8b, 0x35, 0x8b, 0x17, 0xff, 0xfd, 0xa3, 0x47, 0xf9,
+ 0xe7, 0xf3, 0xa8, 0x79, 0xe2, 0x9e, 0x09, 0x62, 0xff, 0xe7, 0xfb, 0x1c,
+ 0x39, 0x1e, 0xb5, 0x2b, 0x14, 0xc8, 0xb0, 0xf3, 0x5d, 0x62, 0x67, 0x9f,
+ 0x37, 0x68, 0x71, 0xdf, 0x17, 0xb3, 0xeb, 0x17, 0xff, 0xc5, 0x9d, 0x87,
+ 0x3a, 0x98, 0x3e, 0xed, 0xa5, 0x8a, 0x93, 0xf3, 0xf1, 0x15, 0xe9, 0xeb,
+ 0x8b, 0x14, 0xe6, 0xff, 0xe4, 0x37, 0xf8, 0xd6, 0x1e, 0x13, 0xf9, 0x62,
+ 0xf1, 0x9b, 0xc4, 0xb1, 0x58, 0x7a, 0x84, 0x67, 0x7f, 0xf4, 0xef, 0x9a,
+ 0xcf, 0xbe, 0xbe, 0xcb, 0x17, 0xf0, 0xdf, 0x35, 0x31, 0x2c, 0x5f, 0x79,
+ 0xc5, 0xba, 0xc5, 0xff, 0xcc, 0x19, 0x66, 0x7d, 0xf7, 0xfe, 0x2c, 0x54,
+ 0x9f, 0x40, 0x89, 0x2f, 0xa2, 0x29, 0x3e, 0x91, 0xf6, 0xc8, 0x85, 0x09,
+ 0x6b, 0xff, 0xda, 0x04, 0x76, 0x6a, 0x60, 0xfd, 0x7b, 0x16, 0x2f, 0xfc,
+ 0x11, 0x60, 0xfe, 0x2d, 0x88, 0x25, 0x8a, 0x64, 0x48, 0x12, 0x75, 0xfe,
+ 0xff, 0xdb, 0x6d, 0x4f, 0x65, 0x8b, 0xc3, 0xf3, 0xac, 0x56, 0x1e, 0xa7,
+ 0x0d, 0xef, 0xf1, 0x7b, 0xed, 0x09, 0xd9, 0x62, 0xff, 0xde, 0x0e, 0x1c,
+ 0x8a, 0x13, 0xad, 0x96, 0x2b, 0x0f, 0xe3, 0xa3, 0x4b, 0xfe, 0xd4, 0xfb,
+ 0x5a, 0x93, 0xf1, 0x62, 0xff, 0xfa, 0x0f, 0xe0, 0xf5, 0x3f, 0x9f, 0x71,
+ 0xba, 0x58, 0xbf, 0xfa, 0x42, 0x9d, 0x4f, 0xe5, 0xcb, 0x65, 0x8b, 0xf0,
+ 0xb9, 0xf6, 0x81, 0x89, 0xc5, 0xe4, 0x26, 0x62, 0x22, 0xe1, 0xd0, 0x6a,
+ 0x57, 0xf4, 0x24, 0xc9, 0x39, 0xd6, 0x2f, 0xd9, 0xdc, 0xf3, 0x12, 0xc5,
+ 0xa3, 0x45, 0x8b, 0xe6, 0x06, 0x14, 0x9f, 0x8f, 0xcb, 0xf8, 0x57, 0x7f,
+ 0xfb, 0xb7, 0xdc, 0x78, 0xe6, 0xb9, 0x67, 0x65, 0x8b, 0xf4, 0xe1, 0x7a,
+ 0x39, 0x62, 0xfe, 0x7e, 0x81, 0xa6, 0x1a, 0xc5, 0xff, 0xee, 0xc5, 0x9c,
+ 0x33, 0x08, 0x50, 0xce, 0x2c, 0x52, 0xc5, 0x61, 0xec, 0x1d, 0x32, 0x8e,
+ 0x8d, 0x2f, 0x95, 0x14, 0x21, 0xef, 0xdf, 0x9d, 0x71, 0xd6, 0x2d, 0x1e,
+ 0xb1, 0x76, 0x12, 0xc5, 0x68, 0xd5, 0xfc, 0x56, 0xf3, 0xcc, 0x16, 0x2f,
+ 0x40, 0x43, 0x58, 0xb7, 0x46, 0x23, 0x88, 0x66, 0x91, 0x29, 0xfc, 0x85,
+ 0x87, 0x2b, 0x15, 0x29, 0xb4, 0xa0, 0x1b, 0xfc, 0xc4, 0x1b, 0x43, 0x06,
+ 0xb1, 0x52, 0xbf, 0x91, 0x91, 0x8d, 0xbc, 0x36, 0xb5, 0x28, 0x00, 0xa1,
+ 0xc1, 0xc9, 0x52, 0xc2, 0x2a, 0xbf, 0x9f, 0x51, 0xb7, 0x3c, 0xeb, 0x17,
+ 0x42, 0x56, 0x2f, 0xee, 0xde, 0x29, 0x3f, 0x16, 0x2f, 0xc5, 0x3f, 0xc1,
+ 0xac, 0x5f, 0xfd, 0xc9, 0x06, 0x7d, 0xf4, 0xc1, 0x79, 0x62, 0xdb, 0x0c,
+ 0xfb, 0x38, 0x4f, 0x4e, 0x8c, 0x52, 0x84, 0xe5, 0x41, 0x30, 0x2c, 0x86,
+ 0xe5, 0xfc, 0x3c, 0x23, 0x75, 0x2b, 0x17, 0xff, 0xf6, 0x81, 0x9a, 0x62,
+ 0xfb, 0x31, 0xf0, 0x5a, 0xd9, 0x62, 0xdd, 0x2c, 0x54, 0x9f, 0x74, 0x72,
+ 0xdd, 0xfe, 0x7d, 0x9f, 0x7f, 0xcf, 0x96, 0x2f, 0xf9, 0xf7, 0x71, 0xfb,
+ 0x92, 0x6a, 0xc5, 0x9f, 0x47, 0xe1, 0xe3, 0x5a, 0x83, 0xa9, 0x9f, 0x1c,
+ 0xe4, 0xa1, 0xac, 0xdb, 0xc6, 0x37, 0xd4, 0xb2, 0x68, 0xa5, 0xfd, 0xea,
+ 0x72, 0xa0, 0xf2, 0xc1, 0xbf, 0x38, 0x7e, 0x08, 0xc4, 0x8a, 0x58, 0x9f,
+ 0x21, 0xcd, 0xea, 0x41, 0xe7, 0x68, 0x40, 0x85, 0x19, 0xac, 0x71, 0x40,
+ 0x70, 0x9c, 0xee, 0x84, 0xa5, 0xed, 0xff, 0x12, 0xc5, 0xfb, 0xef, 0x1c,
+ 0xfa, 0x58, 0xbd, 0xb0, 0x82, 0x58, 0xad, 0xcf, 0x2d, 0x8a, 0xef, 0xfd,
+ 0xbf, 0xe7, 0xa8, 0x6f, 0xfc, 0x1a, 0xc5, 0xfd, 0xbf, 0xe7, 0xa8, 0x7d,
+ 0x62, 0xee, 0xff, 0xb9, 0x62, 0xce, 0xb1, 0x79, 0xcf, 0x8b, 0x17, 0x49,
+ 0xab, 0x15, 0x04, 0x7d, 0x8c, 0x88, 0xd4, 0x3e, 0x8c, 0x5c, 0x83, 0x42,
+ 0x21, 0x0e, 0x5f, 0xf1, 0x60, 0x5a, 0xcd, 0xff, 0x8b, 0x17, 0xff, 0xfe,
+ 0x7d, 0xb8, 0x29, 0x30, 0xb3, 0xef, 0x25, 0xe3, 0x45, 0x3a, 0x58, 0xbf,
+ 0xff, 0x4e, 0xde, 0x11, 0xf3, 0x9b, 0xfe, 0x4a, 0x78, 0xb1, 0x5a, 0x46,
+ 0x27, 0xdb, 0x6f, 0xee, 0xa1, 0xbf, 0xdf, 0x65, 0x8b, 0x6e, 0xb1, 0x7f,
+ 0xfd, 0x07, 0x0b, 0xdf, 0xcf, 0xe7, 0x50, 0x60, 0x96, 0x2f, 0xec, 0xf7,
+ 0x36, 0xc0, 0x96, 0x2a, 0x24, 0x41, 0xe9, 0x4e, 0xf0, 0x7a, 0x95, 0x8b,
+ 0xff, 0xfb, 0x07, 0xf9, 0x08, 0xb1, 0xf6, 0x8e, 0x17, 0xdf, 0x4b, 0x15,
+ 0xb2, 0xa8, 0xa1, 0xc3, 0xfb, 0x08, 0xe3, 0xcc, 0xb5, 0x09, 0x66, 0x24,
+ 0x21, 0xea, 0x97, 0x63, 0x83, 0x91, 0x91, 0xf4, 0x64, 0xf6, 0xa8, 0xf2,
+ 0x28, 0xda, 0x5a, 0x36, 0x61, 0x4a, 0xf0, 0xb7, 0x4b, 0x17, 0xd3, 0xbb,
+ 0xee, 0xb1, 0x7b, 0x4e, 0x12, 0xc5, 0xfe, 0xd0, 0xb6, 0x78, 0x1c, 0x6b,
+ 0x17, 0xfb, 0x99, 0xa1, 0x93, 0x41, 0x62, 0x86, 0x88, 0x7d, 0x0f, 0x70,
+ 0xda, 0xe1, 0x44, 0xb1, 0x7e, 0x97, 0x3e, 0x71, 0x62, 0xfd, 0x30, 0x8e,
+ 0xd8, 0x96, 0x28, 0xe7, 0xd9, 0xf1, 0x9f, 0x13, 0xdf, 0xc4, 0x2e, 0x3e,
+ 0x69, 0x62, 0xfe, 0x30, 0xb0, 0x02, 0xe2, 0xc5, 0x61, 0xee, 0x31, 0x6d,
+ 0xef, 0xe0, 0x16, 0x2d, 0x2b, 0x17, 0xff, 0xd1, 0x33, 0x43, 0x92, 0x71,
+ 0xfe, 0x4b, 0x75, 0x8b, 0xfa, 0x0f, 0xe2, 0x9c, 0x58, 0xbf, 0xff, 0xe9,
+ 0xf7, 0x33, 0x53, 0x85, 0xf0, 0xf5, 0x13, 0x31, 0x6c, 0xb1, 0x52, 0x8f,
+ 0x57, 0x11, 0xd2, 0x8f, 0x8b, 0x2f, 0xf8, 0x5b, 0xe6, 0xb6, 0xd8, 0x5b,
+ 0x2c, 0x5f, 0xf6, 0x45, 0x09, 0xeb, 0x3a, 0xf2, 0xc5, 0xbe, 0xb1, 0x7b,
+ 0xe1, 0x9d, 0x62, 0x86, 0x6c, 0x70, 0x4a, 0x8c, 0x54, 0x73, 0x24, 0x19,
+ 0x18, 0x91, 0xce, 0xc8, 0xff, 0xcd, 0xb7, 0xb6, 0x7e, 0x96, 0x2f, 0xa7,
+ 0xe2, 0xd2, 0xc5, 0xdf, 0x1a, 0xc5, 0xcc, 0x4b, 0x15, 0x2a, 0xe4, 0x76,
+ 0x95, 0x88, 0xeb, 0xa4, 0x3f, 0xc2, 0x30, 0x86, 0x28, 0xc5, 0xd4, 0xa8,
+ 0x09, 0x8e, 0x15, 0x7a, 0x9c, 0x2d, 0xbe, 0x1f, 0xc5, 0xb2, 0xc5, 0xfc,
+ 0xd0, 0xcd, 0x84, 0x4b, 0x17, 0x60, 0xd6, 0x28, 0x67, 0x8b, 0xb9, 0x75,
+ 0xff, 0xb5, 0x91, 0xf1, 0x7d, 0x8e, 0xfc, 0x58, 0xbf, 0xb4, 0xe1, 0x7e,
+ 0x46, 0xb1, 0x7f, 0x79, 0xc2, 0x3b, 0xf9, 0x62, 0xff, 0x98, 0xb5, 0x8f,
+ 0xf9, 0x1a, 0xc5, 0xb3, 0x48, 0x95, 0xf1, 0x7f, 0x71, 0x7d, 0xb6, 0x94,
+ 0xe7, 0x71, 0xab, 0x44, 0x7f, 0x86, 0xc5, 0x9d, 0x62, 0xee, 0xff, 0x16,
+ 0x2b, 0x0f, 0xd7, 0x49, 0x0c, 0x23, 0x7f, 0xee, 0xcf, 0xe8, 0x49, 0x9e,
+ 0x91, 0x2c, 0x5a, 0x25, 0x8b, 0xdd, 0xb0, 0x6b, 0x17, 0xff, 0x84, 0xc5,
+ 0xbf, 0x5c, 0x7f, 0x39, 0x6c, 0xb1, 0x7e, 0x8e, 0x17, 0xf3, 0x75, 0x8b,
+ 0x8f, 0xc5, 0x8a, 0xc4, 0xc1, 0x62, 0x42, 0x38, 0x98, 0x07, 0xfc, 0x98,
+ 0x22, 0xdb, 0xfa, 0x7c, 0xe0, 0x98, 0x2c, 0x5d, 0x06, 0x58, 0xb9, 0xb4,
+ 0xb1, 0x5a, 0x3d, 0xb6, 0x2d, 0xe0, 0xbd, 0xfd, 0xd6, 0xcd, 0x09, 0x8f,
+ 0x58, 0xb4, 0x17, 0x28, 0xa1, 0x79, 0x8a, 0x0b, 0x94, 0x54, 0xa2, 0x3c,
+ 0x8e, 0x0f, 0xdf, 0x0c, 0xef, 0xe5, 0x8a, 0x94, 0x5f, 0xec, 0xf6, 0xc4,
+ 0x37, 0x05, 0x2b, 0x14, 0x63, 0xe3, 0x68, 0xf7, 0x86, 0x1d, 0xec, 0x24,
+ 0x66, 0x1e, 0xdb, 0x42, 0x3a, 0x04, 0x59, 0x0c, 0x33, 0x4f, 0xb7, 0x84,
+ 0x93, 0xc6, 0x91, 0x11, 0xf1, 0xe1, 0xe5, 0xfb, 0x6a, 0x20, 0xd3, 0xba,
+ 0xc5, 0x29, 0x83, 0x91, 0x99, 0x7a, 0x16, 0x62, 0x87, 0x6c, 0x71, 0x7d,
+ 0xfe, 0xfb, 0x80, 0x0f, 0xd7, 0x16, 0x2f, 0xf4, 0x9f, 0x7f, 0xb7, 0x40,
+ 0x58, 0xb7, 0x7b, 0xb9, 0xf5, 0x86, 0x6b, 0x7f, 0x45, 0x84, 0xdf, 0xc5,
+ 0x8b, 0xd9, 0x80, 0x58, 0xa8, 0x1e, 0x4f, 0x8b, 0x6f, 0x1e, 0x71, 0x62,
+ 0xd1, 0x2c, 0x5c, 0x7d, 0xcc, 0x35, 0xee, 0x39, 0x7f, 0x98, 0xb1, 0xe3,
+ 0xdf, 0xeb, 0x17, 0x1f, 0xa5, 0x8b, 0xd0, 0x93, 0xac, 0x5f, 0xd9, 0x9c,
+ 0xe6, 0x47, 0xac, 0x57, 0x47, 0x9a, 0x43, 0xb7, 0xfd, 0x25, 0xb7, 0x30,
+ 0xf3, 0x1e, 0xb1, 0x7f, 0xfd, 0xb7, 0xb3, 0x9f, 0x17, 0x27, 0x61, 0x14,
+ 0xac, 0x5f, 0xfe, 0x97, 0x18, 0x7a, 0xfb, 0xeb, 0x07, 0x2b, 0x17, 0xff,
+ 0xf6, 0x9f, 0xdc, 0xfe, 0x39, 0x16, 0x75, 0xee, 0x3a, 0xc5, 0xa0, 0x62,
+ 0x29, 0x34, 0x95, 0x74, 0xfd, 0x62, 0xfe, 0xef, 0xf7, 0xfb, 0x0a, 0x0b,
+ 0x17, 0xf3, 0x44, 0x39, 0x2d, 0x96, 0x2b, 0x64, 0xfe, 0x46, 0x45, 0x87,
+ 0x8d, 0x0f, 0x62, 0x2a, 0x10, 0xbf, 0x63, 0x5b, 0xf9, 0xbc, 0x00, 0xca,
+ 0x25, 0x8b, 0xfd, 0xf6, 0xf7, 0x02, 0xcf, 0xac, 0x5e, 0x89, 0xfe, 0xb1,
+ 0x68, 0x2c, 0x52, 0xc5, 0x31, 0x7d, 0xc1, 0x2a, 0x93, 0xdb, 0xd1, 0xe5,
+ 0xfd, 0xe2, 0xcd, 0x9f, 0x4b, 0x17, 0xec, 0xf3, 0x10, 0x16, 0x2a, 0x4f,
+ 0x54, 0x45, 0xd7, 0xbb, 0xa4, 0xeb, 0x15, 0x89, 0xa3, 0xb4, 0x24, 0x38,
+ 0xed, 0xdc, 0x43, 0x7b, 0xee, 0x1a, 0xc5, 0xf0, 0xff, 0x30, 0x58, 0xad,
+ 0xcf, 0x04, 0x87, 0xaf, 0x14, 0xee, 0xb1, 0x7e, 0xc7, 0x35, 0xcd, 0x58,
+ 0xbe, 0x98, 0x67, 0x16, 0x2f, 0xf9, 0x82, 0x0c, 0x8b, 0x3a, 0x82, 0xc5,
+ 0x62, 0x28, 0xf4, 0x3b, 0xf2, 0x96, 0x22, 0xbd, 0x13, 0x71, 0x62, 0xfc,
+ 0xde, 0x0f, 0xf2, 0xb1, 0x7a, 0x4b, 0x75, 0x8a, 0x73, 0xe4, 0xf8, 0xf7,
+ 0x71, 0x4d, 0xf9, 0xb3, 0xcf, 0xb2, 0xc5, 0xfb, 0x0d, 0x69, 0xd9, 0x62,
+ 0xf7, 0xbd, 0x2b, 0x15, 0xf3, 0xc6, 0x62, 0x9b, 0xe9, 0x8b, 0x52, 0xb1,
+ 0x69, 0x58, 0xb6, 0x2c, 0x56, 0x8d, 0x11, 0xc4, 0x6d, 0xba, 0xc5, 0x1c,
+ 0xfe, 0x7e, 0x8b, 0xdc, 0x43, 0x7d, 0x22, 0xef, 0xdd, 0x62, 0xfb, 0x85,
+ 0x21, 0x2c, 0x5f, 0x87, 0xfc, 0x28, 0x2c, 0x56, 0x1e, 0x5b, 0x11, 0xdc,
+ 0xe0, 0x58, 0xbe, 0x68, 0x9b, 0xcb, 0x15, 0x03, 0x75, 0xe1, 0x7b, 0xed,
+ 0x8e, 0x21, 0xac, 0x5e, 0xee, 0x7d, 0x96, 0x2d, 0x38, 0x78, 0xdd, 0xc4,
+ 0xb7, 0xff, 0xf6, 0x7b, 0x81, 0xf3, 0xdf, 0x62, 0x37, 0x3b, 0x48, 0x4b,
+ 0x17, 0xdc, 0xf3, 0xc4, 0xb1, 0x47, 0x44, 0x23, 0x30, 0x5f, 0xe7, 0xd4,
+ 0xec, 0xda, 0xdd, 0x62, 0xed, 0xe2, 0x58, 0xa3, 0x17, 0x69, 0x66, 0x10,
+ 0xa3, 0x86, 0x2e, 0x42, 0x7c, 0xd3, 0x1d, 0xdb, 0x9e, 0x13, 0x5a, 0x32,
+ 0xfb, 0x93, 0x2d, 0x13, 0x3f, 0x21, 0x5b, 0xe2, 0x28, 0xe3, 0x5a, 0x3a,
+ 0xff, 0xc7, 0xa7, 0xc7, 0x2f, 0xff, 0x6b, 0x72, 0xce, 0xc5, 0x93, 0xa9,
+ 0xe2, 0xc5, 0xff, 0x8e, 0xf9, 0xd6, 0x38, 0xe7, 0xb9, 0x62, 0xfb, 0x0f,
+ 0x9c, 0x58, 0xbf, 0xb2, 0x3f, 0xf3, 0x83, 0x58, 0xb9, 0xa2, 0xf9, 0xe9,
+ 0x11, 0x15, 0xff, 0xc3, 0xfc, 0xf3, 0x34, 0x36, 0x6f, 0xac, 0x56, 0x26,
+ 0x9f, 0xa4, 0xbe, 0xd0, 0x93, 0x08, 0xb6, 0x96, 0x2f, 0xf8, 0x6c, 0xc1,
+ 0x67, 0x18, 0x96, 0x2b, 0xe7, 0x88, 0x41, 0x97, 0xbb, 0x37, 0xd6, 0x2e,
+ 0x9f, 0x2c, 0x54, 0x9b, 0x68, 0xe1, 0xfb, 0xe9, 0xec, 0xfd, 0x96, 0x2e,
+ 0xc3, 0xac, 0x58, 0xd3, 0x0d, 0xeb, 0x93, 0x56, 0xc8, 0x88, 0x26, 0x0b,
+ 0xf1, 0xbe, 0xcc, 0x3a, 0xc5, 0xff, 0xa1, 0x07, 0xde, 0x4f, 0x17, 0x25,
+ 0x62, 0xff, 0xf6, 0xc1, 0xfd, 0xe4, 0xb6, 0x01, 0xe6, 0x0b, 0x15, 0x29,
+ 0xdc, 0xe4, 0x37, 0xdc, 0x8d, 0x8a, 0x44, 0x83, 0x7f, 0xf1, 0x61, 0xa6,
+ 0xb7, 0xb8, 0xe5, 0x12, 0xc5, 0xec, 0x83, 0xac, 0x5b, 0x16, 0x2a, 0x23,
+ 0xf3, 0xd2, 0x30, 0x07, 0x2f, 0x66, 0xc4, 0xb1, 0x7b, 0x05, 0xd2, 0xc5,
+ 0xfe, 0x92, 0x1f, 0xd8, 0x28, 0x96, 0x2b, 0xe7, 0xe0, 0x43, 0xbe, 0x1e,
+ 0xbf, 0x60, 0xdf, 0x5c, 0x58, 0xa5, 0x8b, 0xe8, 0x38, 0x38, 0xb1, 0x5c,
+ 0x35, 0xe1, 0x86, 0x5e, 0x13, 0x69, 0x62, 0xfb, 0x79, 0xcd, 0x96, 0x29,
+ 0xcf, 0x07, 0x43, 0xb7, 0xec, 0xff, 0xc5, 0xe5, 0x8b, 0xde, 0xf7, 0x4b,
+ 0x17, 0xff, 0x75, 0xbb, 0xfc, 0xce, 0xec, 0xfb, 0x9d, 0x62, 0x80, 0x7d,
+ 0x5e, 0x1f, 0xb8, 0x5a, 0x58, 0xbe, 0x9d, 0xe3, 0xb1, 0x62, 0xb1, 0x31,
+ 0x4d, 0x10, 0xf2, 0x12, 0x71, 0xc4, 0x41, 0x8c, 0x56, 0xca, 0x88, 0x4e,
+ 0xae, 0x14, 0x6e, 0xf7, 0xc1, 0xff, 0x37, 0x58, 0xbc, 0xcc, 0x4b, 0x14,
+ 0xb1, 0x6e, 0x78, 0xd3, 0x88, 0x6e, 0xba, 0x3f, 0x30, 0x93, 0x2a, 0x51,
+ 0xa2, 0xf0, 0xad, 0xbf, 0xff, 0x37, 0xa2, 0x29, 0x07, 0x32, 0x1f, 0x72,
+ 0x02, 0xc5, 0x18, 0xd9, 0xd7, 0x77, 0x86, 0x93, 0x29, 0x7f, 0x29, 0x0c,
+ 0x4f, 0x1b, 0xef, 0xe5, 0x21, 0x34, 0x2f, 0xf9, 0x0a, 0x0f, 0x4b, 0x20,
+ 0x11, 0x35, 0xfe, 0x9f, 0x96, 0x7b, 0xee, 0xb1, 0x7f, 0xbd, 0xfc, 0x18,
+ 0xbd, 0xc5, 0x8a, 0xd1, 0xf3, 0x91, 0x95, 0xf4, 0x73, 0x74, 0x05, 0x8b,
+ 0xfb, 0x58, 0xff, 0x91, 0xac, 0x5f, 0xdd, 0x67, 0x6e, 0xa4, 0x35, 0x8b,
+ 0x3c, 0x79, 0xf0, 0x06, 0x5b, 0x47, 0x45, 0x91, 0x42, 0x1e, 0xd0, 0x58,
+ 0xbf, 0xf6, 0x87, 0x21, 0x67, 0xe7, 0xae, 0x2c, 0x5f, 0xff, 0x70, 0xb3,
+ 0xce, 0x41, 0x7b, 0x8d, 0xd6, 0xeb, 0x15, 0x88, 0x93, 0xe9, 0x06, 0xf4,
+ 0x8b, 0xa5, 0x8a, 0x73, 0xc1, 0xf9, 0x1d, 0xfd, 0xe9, 0xd1, 0x66, 0xcb,
+ 0x17, 0xc1, 0xce, 0x80, 0xb1, 0x7f, 0xbf, 0xf9, 0xda, 0x44, 0x75, 0x8b,
+ 0xf4, 0x8b, 0xdd, 0xba, 0x58, 0xb4, 0xf4, 0x7c, 0x3f, 0x35, 0xbf, 0xd1,
+ 0x70, 0x50, 0x29, 0x3a, 0xc5, 0xa3, 0x45, 0x8b, 0x62, 0xc5, 0xf9, 0xbd,
+ 0xc9, 0x35, 0x62, 0xc5, 0xb1, 0xba, 0xdc, 0x46, 0xfe, 0xce, 0xa1, 0x39,
+ 0xe5, 0x8b, 0xff, 0xb5, 0xa6, 0x06, 0x7d, 0xf5, 0xf6, 0x58, 0xb4, 0x16,
+ 0x2b, 0xbd, 0x47, 0xec, 0xa8, 0x91, 0x47, 0x0b, 0x83, 0x44, 0xbe, 0xd8,
+ 0xf3, 0xc5, 0x8b, 0xff, 0x13, 0x1b, 0xc6, 0x1f, 0xda, 0x0b, 0x17, 0xfd,
+ 0x0e, 0x7c, 0x52, 0x5b, 0x01, 0x62, 0xf3, 0x85, 0xdf, 0xac, 0x5f, 0xe1,
+ 0x7b, 0xf8, 0x76, 0x3a, 0xc5, 0xd9, 0xc5, 0x8b, 0x69, 0x62, 0xba, 0x45,
+ 0xdc, 0x47, 0x67, 0x23, 0xf9, 0xa3, 0x0b, 0xdf, 0xff, 0x8d, 0xcf, 0x3f,
+ 0x3e, 0x2c, 0xf0, 0x18, 0x72, 0xb1, 0x7b, 0xee, 0x75, 0x8b, 0xf3, 0xec,
+ 0x79, 0xdd, 0x62, 0xb0, 0xf1, 0xfc, 0x3b, 0x52, 0xa8, 0x9e, 0x04, 0x83,
+ 0x87, 0xd6, 0x92, 0xff, 0x09, 0xdb, 0xbb, 0xff, 0xac, 0x5f, 0x9a, 0x1e,
+ 0xdf, 0x8b, 0x17, 0xbd, 0x9d, 0x96, 0x2f, 0xfc, 0x36, 0x60, 0xba, 0xf1,
+ 0x37, 0xd6, 0x28, 0x68, 0x89, 0x62, 0xae, 0x0f, 0xdf, 0x41, 0xf5, 0x05,
+ 0x8b, 0xf8, 0x11, 0x41, 0xf5, 0x05, 0x88, 0x8d, 0x1d, 0xf6, 0x6e, 0xdb,
+ 0xac, 0x5f, 0x49, 0x66, 0x96, 0x2e, 0xfe, 0x7c, 0xf1, 0x78, 0x49, 0x73,
+ 0xec, 0xb1, 0x5b, 0x9e, 0x2f, 0x8b, 0x68, 0xd4, 0xd0, 0x3a, 0x52, 0xd4,
+ 0x32, 0xef, 0x6d, 0x81, 0x2c, 0x5f, 0xed, 0xe2, 0x73, 0x89, 0xb8, 0xb1,
+ 0x7d, 0x82, 0xd6, 0xcb, 0x17, 0x4c, 0x7a, 0xc5, 0x0d, 0x12, 0x7d, 0x0f,
+ 0x9c, 0xdb, 0xe4, 0x97, 0xa4, 0x51, 0xeb, 0x17, 0xbe, 0xfe, 0x58, 0xad,
+ 0x1b, 0xd0, 0xc8, 0x2f, 0x48, 0xc6, 0xb1, 0x76, 0x77, 0x2c, 0x5f, 0x00,
+ 0x32, 0x82, 0xc5, 0x98, 0x8d, 0xf7, 0x86, 0xaf, 0xdc, 0xe6, 0x10, 0x16,
+ 0x28, 0x07, 0x9a, 0x44, 0xb5, 0x2b, 0x8d, 0x98, 0xaa, 0xf1, 0xf3, 0x34,
+ 0x32, 0xf8, 0xf7, 0xe2, 0x21, 0x42, 0xa2, 0xd1, 0x2c, 0x5f, 0xf0, 0x98,
+ 0x38, 0xa1, 0x9d, 0x41, 0x62, 0xba, 0x3d, 0x02, 0x13, 0xbe, 0x26, 0xeb,
+ 0x8b, 0x17, 0xde, 0x01, 0xf1, 0x62, 0xbc, 0x78, 0xc1, 0x91, 0xdb, 0x16,
+ 0x28, 0xe8, 0x9c, 0x03, 0x47, 0x88, 0xee, 0x9e, 0x2c, 0x5f, 0xdc, 0xf3,
+ 0xfc, 0x40, 0x58, 0xbe, 0x9f, 0xc8, 0xd6, 0x2f, 0x4f, 0x50, 0x58, 0xad,
+ 0xd1, 0x0d, 0xd0, 0xbc, 0x45, 0xe7, 0x22, 0xbf, 0xff, 0xbf, 0x85, 0xee,
+ 0x18, 0x1c, 0x3f, 0x84, 0x42, 0x82, 0xc5, 0xfd, 0xf9, 0xd1, 0x4c, 0x16,
+ 0x2f, 0xf8, 0xba, 0xf6, 0x42, 0x4b, 0x75, 0x8b, 0x1a, 0x33, 0xe7, 0x11,
+ 0x6d, 0xfb, 0xee, 0x4d, 0xb2, 0xc5, 0xff, 0x41, 0xb5, 0xe2, 0x93, 0xf1,
+ 0x62, 0xff, 0x48, 0xe7, 0x42, 0x90, 0x2c, 0x5f, 0x76, 0x9c, 0xd2, 0xc5,
+ 0xd9, 0xd2, 0xc5, 0x61, 0xbc, 0x22, 0x4b, 0x73, 0x74, 0x77, 0xc4, 0x50,
+ 0x73, 0x92, 0x6f, 0xbf, 0xfd, 0x31, 0xe1, 0xed, 0xcf, 0xee, 0xfc, 0xc1,
+ 0xac, 0x5f, 0xbd, 0xa7, 0x16, 0xcb, 0x15, 0x29, 0xeb, 0x9e, 0x31, 0x8f,
+ 0xa2, 0x04, 0xa3, 0x73, 0x77, 0xeb, 0x17, 0xfd, 0xfc, 0x78, 0x39, 0xa6,
+ 0xe2, 0xc5, 0xff, 0x30, 0x78, 0x42, 0xf0, 0x8d, 0x58, 0xa8, 0x22, 0x47,
+ 0xc3, 0x82, 0x3a, 0xbc, 0xcc, 0x6a, 0xc5, 0xff, 0x33, 0xf0, 0xb0, 0xe7,
+ 0x75, 0x8a, 0xd1, 0xea, 0x7c, 0x76, 0xe9, 0xce, 0x91, 0x4c, 0x14, 0x21,
+ 0x2f, 0x77, 0x14, 0xac, 0x5c, 0x1f, 0xd6, 0x2c, 0x52, 0x6e, 0x20, 0x3f,
+ 0x7f, 0x45, 0xcd, 0x4f, 0x5e, 0x58, 0xbf, 0xfc, 0xcd, 0xad, 0xbe, 0xde,
+ 0xfb, 0xea, 0x0b, 0x17, 0xed, 0x0f, 0xef, 0x12, 0xc5, 0xfc, 0x53, 0xd4,
+ 0x1c, 0x96, 0x2f, 0x7e, 0x74, 0xb0, 0x33, 0x5b, 0x7f, 0x63, 0x91, 0x48,
+ 0xd6, 0x2c, 0x10, 0xd1, 0xf5, 0x89, 0x7b, 0xab, 0xfc, 0xb6, 0xa5, 0x36,
+ 0xf6, 0x8c, 0xae, 0xff, 0x98, 0xb3, 0xde, 0x70, 0xbc, 0xb1, 0x7f, 0xc5,
+ 0x9f, 0xf1, 0x63, 0x44, 0xb1, 0x7f, 0xfd, 0x87, 0x10, 0xcc, 0xe4, 0xe9,
+ 0xa0, 0xff, 0x58, 0xa3, 0x11, 0x12, 0x47, 0x17, 0xff, 0xff, 0x45, 0x07,
+ 0x2f, 0x48, 0x3b, 0xbc, 0xe6, 0xeb, 0x27, 0xa8, 0x39, 0xd6, 0x2a, 0x53,
+ 0x5c, 0x3c, 0x30, 0x88, 0x8e, 0xa5, 0x91, 0x89, 0x90, 0xb6, 0xdd, 0x01,
+ 0xe5, 0x4d, 0xea, 0x37, 0xb6, 0x6c, 0x28, 0xe5, 0x05, 0x1c, 0x25, 0x46,
+ 0xce, 0xad, 0xb6, 0x5e, 0x36, 0x51, 0x85, 0x67, 0xb8, 0x38, 0xc9, 0xf2,
+ 0x1a, 0x66, 0x93, 0xef, 0x0e, 0x67, 0x21, 0x88, 0xbb, 0xf0, 0x85, 0x62,
+ 0x80, 0x46, 0x65, 0xc9, 0xee, 0x1f, 0x52, 0x88, 0xef, 0xdd, 0xf7, 0xd4,
+ 0x33, 0xcb, 0x17, 0xf7, 0x58, 0x73, 0xbc, 0x7a, 0xc5, 0xfc, 0x59, 0x14,
+ 0x27, 0xa5, 0x8b, 0xff, 0x75, 0x0c, 0xf3, 0xf6, 0x92, 0xdd, 0x62, 0xa0,
+ 0x7e, 0x3e, 0x2f, 0xbf, 0xa4, 0x5d, 0x3f, 0x5d, 0xcb, 0x17, 0xec, 0x0b,
+ 0x3a, 0xf2, 0xc5, 0x18, 0x7b, 0xae, 0x67, 0x7f, 0xfa, 0x48, 0x46, 0x67,
+ 0xb2, 0x7f, 0x31, 0x2c, 0x5f, 0xf9, 0xa5, 0xce, 0xdb, 0x3e, 0x04, 0xb1,
+ 0x7f, 0xba, 0x86, 0x0f, 0xf9, 0xb2, 0xc5, 0xff, 0x18, 0xe7, 0xc2, 0x90,
+ 0xa5, 0x62, 0xff, 0x49, 0x0e, 0x63, 0xdb, 0xb9, 0x62, 0xa0, 0xa9, 0xcf,
+ 0xa8, 0x51, 0xe9, 0xff, 0xe4, 0x40, 0x4a, 0x23, 0xef, 0x1b, 0x76, 0x39,
+ 0xbd, 0x1b, 0xc6, 0xdd, 0x2c, 0x5f, 0xba, 0x30, 0x39, 0xe2, 0xc5, 0xe9,
+ 0x87, 0x16, 0x2d, 0xc5, 0x8b, 0x7e, 0x4f, 0x6f, 0xe5, 0x81, 0x8e, 0xdf,
+ 0xa7, 0x5d, 0x43, 0x8b, 0x17, 0xfd, 0x3b, 0x18, 0xdd, 0xdd, 0xcc, 0x05,
+ 0x8b, 0xf9, 0xa0, 0x07, 0x2f, 0x2c, 0x5f, 0xff, 0xf6, 0xa2, 0x6f, 0xbf,
+ 0x26, 0x27, 0xf7, 0xb3, 0xe0, 0x7e, 0xcb, 0x15, 0x1b, 0x27, 0x77, 0x30,
+ 0x84, 0xd8, 0xd7, 0x45, 0x47, 0x41, 0x11, 0x6d, 0xff, 0xc2, 0xd6, 0x6d,
+ 0x3c, 0x98, 0x4e, 0x96, 0x2f, 0x6b, 0x38, 0xb1, 0x7e, 0x72, 0xed, 0x90,
+ 0x58, 0xbd, 0x8f, 0xb2, 0xc5, 0xff, 0x64, 0x5f, 0x9e, 0xa2, 0x6d, 0xd6,
+ 0x28, 0xd4, 0x50, 0x1c, 0x77, 0xe5, 0x3c, 0x1d, 0xbf, 0xa7, 0x6c, 0xf6,
+ 0x1d, 0x62, 0xfc, 0x19, 0x9f, 0xe6, 0x2c, 0x5f, 0xf8, 0x85, 0xbf, 0xf0,
+ 0xf1, 0x36, 0xeb, 0x17, 0x0b, 0x4b, 0x15, 0x87, 0xb5, 0x1c, 0x85, 0x50,
+ 0x4f, 0xe9, 0xe1, 0xcb, 0xa3, 0xe0, 0x17, 0x72, 0x10, 0xb7, 0x9e, 0x46,
+ 0xb1, 0x7f, 0xef, 0xb4, 0x39, 0x2f, 0xb3, 0x79, 0x62, 0x8e, 0x7b, 0x64,
+ 0x39, 0x70, 0x23, 0xd6, 0x2f, 0xf1, 0x1b, 0xf9, 0x39, 0xc9, 0x62, 0xfe,
+ 0x8f, 0x79, 0xee, 0x17, 0x96, 0x2f, 0xd3, 0x16, 0x66, 0xeb, 0x17, 0x8b,
+ 0x3b, 0x96, 0x2a, 0x51, 0xd9, 0x02, 0x1c, 0x1b, 0x73, 0x4f, 0x9a, 0x08,
+ 0xa6, 0xff, 0x9f, 0xae, 0x3c, 0xf4, 0xdb, 0x2c, 0x5f, 0xf9, 0xb7, 0x32,
+ 0x43, 0x9d, 0x9b, 0x8b, 0x17, 0xfe, 0x2c, 0xd6, 0xa5, 0xbc, 0xc6, 0xac,
+ 0x5e, 0x3b, 0x79, 0x62, 0xfd, 0x9a, 0x73, 0xf1, 0x62, 0xf3, 0x4f, 0x4b,
+ 0x15, 0x27, 0x8a, 0x72, 0x8a, 0xd9, 0x33, 0xee, 0x8e, 0xf4, 0x84, 0x47,
+ 0xc1, 0x31, 0x5f, 0xef, 0x71, 0xfb, 0x69, 0xf8, 0xb1, 0x63, 0xac, 0x52,
+ 0xc5, 0x61, 0x7c, 0xc2, 0x57, 0xde, 0xfb, 0xc4, 0xb1, 0x7f, 0x3e, 0x83,
+ 0x28, 0x4a, 0xc5, 0x49, 0xe9, 0x40, 0x92, 0x86, 0x89, 0x10, 0x9c, 0x2e,
+ 0x78, 0x2c, 0x56, 0x26, 0x40, 0xf0, 0xe5, 0x22, 0x4b, 0xff, 0xdc, 0x6c,
+ 0xec, 0xfe, 0x86, 0x1a, 0x6e, 0x2c, 0x5d, 0x3b, 0xac, 0x5f, 0xf7, 0x24,
+ 0xe5, 0x3d, 0x4f, 0x16, 0x28, 0xd3, 0xd1, 0xe0, 0xc5, 0xff, 0x64, 0x4f,
+ 0x10, 0xbb, 0x85, 0xc5, 0x8b, 0x32, 0xc5, 0x7c, 0xf4, 0x3c, 0x7f, 0x7f,
+ 0x4c, 0x58, 0x42, 0xc5, 0x8b, 0xb4, 0x6a, 0xc5, 0x49, 0xe3, 0x39, 0x6d,
+ 0xf7, 0x9e, 0x7a, 0x58, 0xbe, 0xcd, 0xa6, 0x25, 0x8a, 0x94, 0xd0, 0x9d,
+ 0xcc, 0x9a, 0x38, 0x40, 0x22, 0x3b, 0xfe, 0x98, 0xa7, 0xdf, 0xcd, 0x6e,
+ 0xb1, 0x7f, 0xfa, 0x7a, 0x30, 0x51, 0x37, 0x5c, 0xfe, 0x79, 0x62, 0xf7,
+ 0xe6, 0x25, 0x8a, 0xe9, 0x15, 0x1f, 0x3b, 0xee, 0x4f, 0xbf, 0xef, 0xb4,
+ 0x8f, 0xf2, 0x79, 0x58, 0xbf, 0xd8, 0x37, 0x92, 0x73, 0xac, 0x54, 0xa2,
+ 0x75, 0xcd, 0x3e, 0x71, 0x50, 0x4e, 0xef, 0x91, 0xc6, 0xde, 0x14, 0x4e,
+ 0xb1, 0x7f, 0x6c, 0x20, 0x7b, 0x37, 0x58, 0xb9, 0xdd, 0x62, 0xa3, 0xcf,
+ 0x97, 0x43, 0xc4, 0x63, 0x7f, 0xfe, 0x3b, 0x8f, 0x07, 0x3d, 0xc2, 0x63,
+ 0x7a, 0x93, 0xac, 0x5f, 0xbe, 0xde, 0xf8, 0x6b, 0x17, 0x36, 0xcb, 0x17,
+ 0xf3, 0x1f, 0x3b, 0x36, 0x96, 0x2b, 0x63, 0xc7, 0x38, 0xc5, 0xe2, 0x17,
+ 0x4b, 0x17, 0xfe, 0x89, 0xff, 0x3d, 0x42, 0x62, 0x95, 0x8a, 0xc4, 0xd3,
+ 0x77, 0x5a, 0x77, 0x16, 0x23, 0x10, 0xf5, 0xe9, 0xf1, 0xd6, 0x2f, 0xfd,
+ 0xe6, 0x34, 0xa7, 0xdf, 0x63, 0xac, 0x5f, 0xff, 0x06, 0xe7, 0x30, 0xd2,
+ 0x17, 0x3a, 0xdd, 0xfa, 0x58, 0xb1, 0xd6, 0x2a, 0x4f, 0xa7, 0x8a, 0xf4,
+ 0x74, 0x73, 0x30, 0xef, 0x74, 0x2a, 0x2f, 0xfb, 0x82, 0xda, 0x62, 0x30,
+ 0x1e, 0x58, 0xbf, 0x0d, 0x8a, 0x7e, 0xb1, 0x7f, 0xbd, 0x23, 0x9f, 0x61,
+ 0xd6, 0x2f, 0xf7, 0x67, 0xd6, 0x76, 0x6d, 0x2c, 0x5f, 0xd0, 0x9e, 0xbd,
+ 0x9f, 0x58, 0xbf, 0xfd, 0xee, 0x38, 0x26, 0x1c, 0xcc, 0xeb, 0xcb, 0x15,
+ 0x28, 0xe4, 0xc3, 0x38, 0x8d, 0xf8, 0x5f, 0x5d, 0x27, 0x0b, 0xf3, 0xe0,
+ 0xa3, 0x0b, 0xbf, 0xd9, 0xbe, 0x14, 0xe0, 0x4b, 0x17, 0xfc, 0x39, 0xf8,
+ 0xdf, 0xb4, 0x8d, 0x62, 0xfe, 0x98, 0x8f, 0x23, 0x95, 0x8b, 0xff, 0x9b,
+ 0xed, 0x17, 0xe7, 0xaf, 0x4f, 0xd6, 0x28, 0xe7, 0xe8, 0x02, 0xeb, 0xf4,
+ 0x58, 0xfd, 0xc3, 0x58, 0xa7, 0x3c, 0xe6, 0x22, 0xbf, 0xff, 0x34, 0x5c,
+ 0x11, 0x7b, 0x59, 0x3d, 0x41, 0xce, 0xb1, 0x52, 0x9b, 0xa7, 0xe1, 0xfa,
+ 0x11, 0x05, 0xff, 0xfc, 0x1b, 0x13, 0xf4, 0xf1, 0x4f, 0x70, 0x83, 0x17,
+ 0x3c, 0xb1, 0x7f, 0xe9, 0xf7, 0x19, 0xc6, 0x2f, 0x71, 0x62, 0xa5, 0x71,
+ 0xcd, 0xe3, 0xbc, 0xf9, 0xcf, 0x23, 0xa7, 0x11, 0xb0, 0x4c, 0x57, 0xec,
+ 0xea, 0x1f, 0x75, 0x8b, 0xff, 0x9c, 0xb3, 0xd2, 0x73, 0x3b, 0xbb, 0x79,
+ 0x62, 0xfb, 0xb8, 0x85, 0xb2, 0xc5, 0x18, 0x89, 0xa8, 0xf2, 0x93, 0xa5,
+ 0x5f, 0xbe, 0xf1, 0x3e, 0xcb, 0x17, 0x6a, 0x0b, 0x14, 0xe7, 0x84, 0xc5,
+ 0x56, 0x95, 0x8a, 0xe1, 0xb1, 0xf1, 0x05, 0xff, 0x3e, 0x9f, 0x68, 0xa0,
+ 0x23, 0x56, 0x2c, 0x05, 0x8a, 0xd8, 0xf3, 0xe3, 0xcf, 0x6f, 0xde, 0x72,
+ 0x84, 0xac, 0x5f, 0xdd, 0x43, 0x05, 0xad, 0x96, 0x2f, 0xff, 0x6b, 0x52,
+ 0x58, 0x6b, 0xff, 0xf8, 0x1a, 0xc5, 0x62, 0x28, 0xdc, 0x9c, 0x46, 0x37,
+ 0x8a, 0x60, 0xb1, 0x52, 0xa8, 0xab, 0x21, 0x4e, 0xee, 0x1a, 0x86, 0x4b,
+ 0x17, 0x5f, 0xe6, 0xf3, 0x1d, 0xcf, 0x2b, 0x17, 0xf3, 0x9a, 0xfe, 0x6f,
+ 0xac, 0x5e, 0xdf, 0xf2, 0xb1, 0x76, 0xa5, 0x62, 0x8c, 0x44, 0xac, 0x0c,
+ 0xba, 0x2e, 0x88, 0x7a, 0xfd, 0x2f, 0xee, 0xf2, 0x35, 0xac, 0x5f, 0x99,
+ 0xc7, 0x24, 0xb1, 0x74, 0x89, 0x62, 0xa5, 0x16, 0x1f, 0x40, 0x23, 0x3e,
+ 0x13, 0x5f, 0x84, 0x20, 0xde, 0x3d, 0x62, 0xee, 0xe9, 0x58, 0xb8, 0xb7,
+ 0x58, 0xa9, 0x36, 0x4e, 0x35, 0x7f, 0x84, 0xe5, 0x9c, 0xe6, 0x2c, 0x56,
+ 0xc7, 0xa2, 0x71, 0xfb, 0xb3, 0x75, 0x8b, 0xfe, 0x6f, 0x7e, 0x78, 0x21,
+ 0xe2, 0xc5, 0xfb, 0x21, 0x25, 0xba, 0xc5, 0xf7, 0xc0, 0xde, 0x58, 0xb7,
+ 0xd6, 0x29, 0x8d, 0xa8, 0x88, 0xef, 0xf1, 0x67, 0xa6, 0x02, 0xd2, 0xc5,
+ 0x1d, 0x30, 0x12, 0x18, 0xf1, 0xcf, 0x65, 0xde, 0xe2, 0x0b, 0xf0, 0x18,
+ 0xed, 0xd2, 0xc5, 0xff, 0x8e, 0xfc, 0xfc, 0xbe, 0x85, 0x1e, 0xb1, 0x5d,
+ 0x1f, 0x5b, 0x94, 0xd1, 0x8a, 0xac, 0x26, 0x16, 0x0f, 0x19, 0x23, 0x42,
+ 0xea, 0xf8, 0x45, 0x27, 0x58, 0xbf, 0xff, 0xd3, 0xd1, 0x09, 0xbd, 0x91,
+ 0x3e, 0xc4, 0xde, 0x63, 0xac, 0x5f, 0xb8, 0xfd, 0xa4, 0x6b, 0x15, 0xd2,
+ 0x2b, 0x7e, 0x44, 0x4c, 0x37, 0xfc, 0x07, 0x2f, 0x4f, 0x05, 0xf5, 0x8b,
+ 0xf4, 0x87, 0xc9, 0xe2, 0xc5, 0xfe, 0xd6, 0xcf, 0xbb, 0xeb, 0x16, 0x2f,
+ 0x13, 0x9a, 0xb1, 0x7e, 0x6d, 0x6a, 0x76, 0x58, 0xbf, 0xbc, 0xfa, 0x7f,
+ 0x09, 0x62, 0xd2, 0x62, 0x61, 0x7b, 0x1c, 0xe1, 0x49, 0xcd, 0x7c, 0x3a,
+ 0x19, 0x4d, 0xfb, 0xef, 0xac, 0xe9, 0x62, 0xfc, 0x1f, 0xf3, 0xae, 0x2c,
+ 0x5c, 0xd1, 0xeb, 0x15, 0xb9, 0xf7, 0x08, 0xa4, 0x32, 0xbb, 0xff, 0xfa,
+ 0x79, 0xbf, 0xdf, 0xf9, 0xdb, 0x1e, 0x76, 0x10, 0xd6, 0x2f, 0xff, 0xff,
+ 0xa7, 0xc4, 0xdb, 0xbf, 0x22, 0x7d, 0x6f, 0x3c, 0xf4, 0xf5, 0x21, 0xe7,
+ 0x16, 0x2f, 0xf7, 0x33, 0x53, 0xda, 0x63, 0xd6, 0x2f, 0xd8, 0x53, 0xd7,
+ 0x16, 0x2e, 0x0c, 0xeb, 0x14, 0x6a, 0x6a, 0xfa, 0x5e, 0xf4, 0x20, 0x3b,
+ 0x1c, 0x04, 0x51, 0x7f, 0xbf, 0x9d, 0x4e, 0x9c, 0xeb, 0x17, 0xfd, 0x3b,
+ 0xeb, 0x39, 0x8e, 0x35, 0x8b, 0xff, 0xcf, 0xac, 0x89, 0xf5, 0xdc, 0xe1,
+ 0xe4, 0x16, 0x2b, 0x48, 0x87, 0xe1, 0xcd, 0xe9, 0x3c, 0xac, 0x56, 0x8d,
+ 0xff, 0x88, 0xef, 0xf1, 0xc9, 0x8d, 0x7f, 0x89, 0x62, 0xfb, 0xee, 0xc0,
+ 0x58, 0xb4, 0x98, 0x7a, 0xde, 0x34, 0xbf, 0xf4, 0x9b, 0xa1, 0x77, 0x0e,
+ 0x79, 0x2b, 0x17, 0xff, 0xff, 0xfd, 0xcc, 0xf7, 0xd8, 0xfc, 0xd6, 0x9f,
+ 0xaf, 0x33, 0x1b, 0x99, 0x10, 0xbd, 0x21, 0x75, 0x2b, 0x17, 0xe1, 0x45,
+ 0x91, 0xd8, 0xb1, 0x77, 0xd9, 0x62, 0xb8, 0x8d, 0xbf, 0x42, 0x63, 0xb1,
+ 0x65, 0xff, 0x75, 0xc2, 0x73, 0xfb, 0x23, 0xd6, 0x2e, 0xcd, 0x2c, 0x54,
+ 0x9e, 0xa7, 0xcf, 0x6f, 0xef, 0x13, 0x03, 0x09, 0x62, 0xe9, 0x35, 0x62,
+ 0xf9, 0x81, 0x84, 0xb1, 0x51, 0x1b, 0x92, 0x18, 0xa3, 0x11, 0x0d, 0xe6,
+ 0x5b, 0xd2, 0x70, 0x96, 0x2a, 0x57, 0x1f, 0xc6, 0xa9, 0x90, 0xfa, 0xdd,
+ 0xdf, 0xa2, 0x86, 0x8c, 0x7b, 0xd0, 0x8b, 0x14, 0x29, 0xc2, 0x24, 0xbf,
+ 0xc2, 0xe7, 0xe7, 0xad, 0x3a, 0xc5, 0xfc, 0xdd, 0x3f, 0x73, 0x8d, 0x62,
+ 0xb6, 0x3e, 0x68, 0x1a, 0xdf, 0xc2, 0x0f, 0x7f, 0xbc, 0x7a, 0xc5, 0xf0,
+ 0x1b, 0xae, 0x2c, 0x5c, 0x10, 0x4b, 0x15, 0xc3, 0x7c, 0x11, 0x25, 0xf7,
+ 0xdb, 0x3e, 0x91, 0x18, 0x68, 0xaf, 0xff, 0xc1, 0xb9, 0xc5, 0xc9, 0x0d,
+ 0xcf, 0x31, 0x48, 0x4b, 0x17, 0x3e, 0xcb, 0x17, 0xfe, 0xdd, 0xb4, 0xdf,
+ 0xea, 0x19, 0xe5, 0x8a, 0x94, 0xe7, 0xb0, 0x8d, 0xe1, 0x28, 0xc6, 0xbd,
+ 0x96, 0x43, 0x18, 0xbd, 0x22, 0xe9, 0x62, 0xfe, 0x11, 0x3f, 0x9b, 0x75,
+ 0x8a, 0xdc, 0xf3, 0x00, 0x3d, 0x7e, 0x0f, 0x0e, 0xfa, 0x58, 0xbf, 0x3e,
+ 0xbd, 0x9b, 0xac, 0x5f, 0xb7, 0x7e, 0x7d, 0xd6, 0x2f, 0xee, 0x9f, 0x63,
+ 0xbf, 0x16, 0x2e, 0x3b, 0x2c, 0x5f, 0xef, 0x49, 0x6f, 0x1a, 0x00, 0xeb,
+ 0x15, 0x28, 0x81, 0xf9, 0x80, 0x85, 0xef, 0x7e, 0x40, 0xb1, 0x7b, 0xbb,
+ 0xba, 0x56, 0x2f, 0xf8, 0x7f, 0x7d, 0x3f, 0x51, 0x4a, 0xc5, 0x31, 0xef,
+ 0x08, 0x8e, 0xff, 0xfe, 0x71, 0x77, 0xf0, 0x93, 0x0b, 0x3c, 0x20, 0x1d,
+ 0xa0, 0xb1, 0x6e, 0xcb, 0x17, 0xff, 0xda, 0xd6, 0x00, 0x13, 0x0d, 0x31,
+ 0x4c, 0x16, 0x2a, 0x37, 0x3e, 0x3c, 0x14, 0xa9, 0x55, 0xa9, 0x84, 0x66,
+ 0x94, 0xf4, 0x52, 0xf0, 0xaa, 0x62, 0xf2, 0x7b, 0xe1, 0x0f, 0xa1, 0x89,
+ 0x7f, 0xff, 0x7f, 0x0d, 0x69, 0x78, 0xe9, 0xeb, 0xbb, 0x7f, 0xb7, 0x4b,
+ 0x17, 0xda, 0x7d, 0xe5, 0x62, 0xff, 0xff, 0xff, 0xe2, 0xef, 0xc7, 0x81,
+ 0xf7, 0xd7, 0x23, 0x51, 0x4c, 0x68, 0x13, 0xed, 0xdc, 0x68, 0x23, 0x48,
+ 0xef, 0x0e, 0x38, 0xc3, 0x3f, 0x1c, 0xb1, 0x7f, 0xff, 0xa7, 0x86, 0x73,
+ 0x0e, 0xdd, 0x7d, 0xbb, 0x9c, 0x9b, 0xa5, 0x8b, 0xfd, 0x22, 0x86, 0x79,
+ 0xf8, 0xb1, 0x43, 0x4f, 0xc3, 0x19, 0x3a, 0x23, 0x3c, 0x34, 0x7c, 0xcb,
+ 0x7b, 0xe6, 0x47, 0xac, 0x5e, 0x2d, 0xdd, 0x62, 0xf1, 0x66, 0xcb, 0x17,
+ 0xdc, 0xd3, 0x84, 0xb1, 0x6f, 0xc9, 0xe0, 0xb0, 0xed, 0x4a, 0x29, 0x9c,
+ 0x89, 0x97, 0xaf, 0xff, 0xfe, 0xf1, 0x30, 0x09, 0xe4, 0xc9, 0xed, 0x3a,
+ 0xe3, 0xfa, 0x4b, 0x65, 0x8b, 0xed, 0xfe, 0xfa, 0x58, 0xba, 0x7c, 0x62,
+ 0x25, 0x99, 0xca, 0xfc, 0xfb, 0x30, 0x89, 0x62, 0xfd, 0xa1, 0x6c, 0x2d,
+ 0x96, 0x2f, 0xe9, 0xf0, 0x8e, 0x2f, 0x2c, 0x5f, 0x1e, 0x5e, 0x39, 0x62,
+ 0xff, 0x49, 0x7d, 0x80, 0x28, 0x96, 0x2a, 0x51, 0x69, 0xf2, 0xc1, 0x17,
+ 0xf7, 0x12, 0xd7, 0x7d, 0xbb, 0x38, 0xf9, 0x95, 0x49, 0xb4, 0xa3, 0x58,
+ 0x4a, 0x5c, 0x1c, 0x73, 0x79, 0x1c, 0x91, 0xb1, 0xb6, 0xee, 0x67, 0xd4,
+ 0xb9, 0xb7, 0x84, 0x7c, 0x7c, 0x6f, 0xd1, 0x4e, 0xd1, 0x6a, 0x59, 0x49,
+ 0xe3, 0x97, 0xfc, 0xae, 0xb6, 0x87, 0xd0, 0x23, 0x3b, 0xef, 0xe1, 0x9a,
+ 0x53, 0xc0, 0xfc, 0x95, 0x35, 0xe9, 0x6f, 0x82, 0x94, 0xef, 0xda, 0x1e,
+ 0xd1, 0xd0, 0xc3, 0x0c, 0xbb, 0xba, 0x1b, 0x97, 0xff, 0xfe, 0xed, 0xb7,
+ 0x23, 0x5e, 0xd1, 0xa7, 0x79, 0xa8, 0x8b, 0xd8, 0x33, 0x0c, 0xfc, 0x72,
+ 0xc5, 0xe2, 0x8d, 0xe0, 0xb1, 0x5d, 0xf6, 0x8a, 0xcf, 0xc2, 0x2a, 0xfb,
+ 0x59, 0xec, 0x58, 0xbf, 0xdb, 0xfd, 0xfd, 0xc6, 0xe9, 0x62, 0xf6, 0x6b,
+ 0xb2, 0xc5, 0xd1, 0xb4, 0x6c, 0xb1, 0x7d, 0xc2, 0x17, 0xd6, 0x2b, 0xbc,
+ 0x3c, 0x5c, 0x22, 0xbf, 0x48, 0xff, 0x3c, 0x58, 0xbd, 0xa0, 0xe2, 0x58,
+ 0xb8, 0xff, 0x58, 0xa7, 0x37, 0x1c, 0x20, 0xbf, 0xf1, 0x00, 0xed, 0x02,
+ 0x9f, 0x71, 0x62, 0xec, 0xc5, 0x8b, 0xed, 0xfe, 0xe1, 0xac, 0x54, 0x68,
+ 0xa8, 0x2b, 0x0b, 0xcd, 0x22, 0x73, 0x68, 0xf6, 0x4d, 0x13, 0x7d, 0x81,
+ 0x88, 0x3b, 0xf3, 0xe0, 0xc5, 0xaf, 0xd1, 0x4c, 0x5f, 0x95, 0x8b, 0xff,
+ 0xc5, 0xee, 0x07, 0xe7, 0x21, 0x43, 0x38, 0xb1, 0x7f, 0xec, 0x70, 0x48,
+ 0x21, 0x9a, 0x95, 0x8b, 0xf3, 0x17, 0xb8, 0x05, 0x8b, 0x7c, 0x8f, 0x97,
+ 0xb8, 0xf6, 0xff, 0xbb, 0xb8, 0x4d, 0x11, 0x49, 0xd6, 0x2d, 0x2b, 0x14,
+ 0x23, 0xcd, 0x0c, 0xf2, 0xfb, 0x34, 0xd0, 0x58, 0xbf, 0xbf, 0x91, 0x31,
+ 0x6c, 0xb1, 0x78, 0x20, 0x82, 0x48, 0xbe, 0x87, 0xb3, 0x74, 0x88, 0xc3,
+ 0x43, 0x7e, 0xc1, 0xb8, 0x38, 0xba, 0x3f, 0x8a, 0x31, 0x17, 0x9a, 0x50,
+ 0x23, 0x7b, 0xb9, 0x05, 0x8b, 0xdc, 0x60, 0x2c, 0x54, 0x9b, 0x5e, 0x86,
+ 0x2d, 0xd9, 0x62, 0xd1, 0xcb, 0x15, 0xb9, 0xa9, 0x38, 0xa5, 0xfc, 0xfa,
+ 0x78, 0x49, 0xab, 0x15, 0x87, 0xa1, 0xe2, 0x2a, 0x95, 0x6e, 0x58, 0x54,
+ 0xf0, 0xb0, 0xd3, 0xb9, 0xc8, 0xda, 0x1b, 0xc0, 0x65, 0x28, 0x4d, 0x5f,
+ 0x1c, 0x78, 0x4b, 0x17, 0x7b, 0x8b, 0x17, 0xff, 0x87, 0x98, 0x69, 0x99,
+ 0xe7, 0xe7, 0xdd, 0x62, 0xff, 0x7b, 0xf3, 0xee, 0x7d, 0xd6, 0x2e, 0x86,
+ 0xcb, 0x17, 0xc1, 0x73, 0x03, 0x58, 0xbc, 0x68, 0xb6, 0x58, 0xb9, 0xa0,
+ 0xb1, 0x7e, 0x33, 0x22, 0x7d, 0x96, 0x28, 0xc4, 0x6a, 0x40, 0xd3, 0x06,
+ 0x4d, 0x25, 0x39, 0x07, 0x05, 0xef, 0xff, 0xdf, 0x2c, 0xea, 0x05, 0x86,
+ 0xbf, 0xff, 0x91, 0xeb, 0x17, 0xf6, 0xb0, 0x85, 0x3a, 0x58, 0xa5, 0x8a,
+ 0xd8, 0xdc, 0xf0, 0xb6, 0xe6, 0x35, 0x62, 0xfd, 0x0f, 0xc9, 0x6c, 0x91,
+ 0x74, 0xc1, 0x62, 0xf0, 0x1a, 0x0b, 0x15, 0xd1, 0xee, 0xfc, 0xa4, 0x31,
+ 0x7a, 0x64, 0x53, 0x79, 0xd6, 0xff, 0xd9, 0xd4, 0x1f, 0x08, 0xb0, 0x6b,
+ 0x17, 0xc7, 0x17, 0x5e, 0x58, 0xbd, 0xf9, 0xec, 0xb1, 0x74, 0x81, 0x62,
+ 0xb0, 0xdb, 0x06, 0x3f, 0x5b, 0x1f, 0xe7, 0x16, 0xef, 0x77, 0xf3, 0xa5,
+ 0x8a, 0x95, 0xc0, 0x9d, 0x86, 0x3a, 0x8c, 0x7d, 0xd6, 0x35, 0x09, 0x22,
+ 0x86, 0x47, 0x08, 0xbd, 0x0b, 0x91, 0x11, 0xdf, 0xdf, 0x71, 0xcb, 0x69,
+ 0x62, 0xf7, 0x70, 0xb6, 0x58, 0xad, 0xcf, 0x3f, 0xb8, 0xb6, 0xff, 0xe8,
+ 0x39, 0x03, 0x59, 0xda, 0x4b, 0xcb, 0x17, 0x9f, 0x8e, 0xb1, 0x67, 0x58,
+ 0xbe, 0x60, 0xd8, 0x6b, 0x17, 0xa7, 0x46, 0xac, 0x5a, 0x18, 0x8b, 0x3f,
+ 0xa2, 0xb0, 0xe0, 0x84, 0x42, 0x23, 0xbf, 0xff, 0xc3, 0xfe, 0x7b, 0xcc,
+ 0x5b, 0xf2, 0x74, 0xd1, 0x3f, 0xd6, 0x2f, 0xc1, 0xff, 0xf9, 0x12, 0xc5,
+ 0xf0, 0x7f, 0x7f, 0x2c, 0x51, 0x87, 0x9f, 0xc2, 0xba, 0x1a, 0x7f, 0x9d,
+ 0x43, 0x65, 0xd3, 0xc1, 0x0b, 0x1b, 0xe0, 0xe7, 0x40, 0x58, 0xbf, 0x4e,
+ 0x76, 0x91, 0xac, 0x51, 0xa7, 0x9b, 0xb9, 0x25, 0xff, 0xf7, 0x5e, 0x70,
+ 0x83, 0xf3, 0x90, 0xa1, 0x9c, 0x58, 0xbf, 0xe2, 0x90, 0xb8, 0xe5, 0xd4,
+ 0x16, 0x2f, 0xff, 0xfd, 0xc0, 0x3e, 0x87, 0x85, 0xf7, 0xdf, 0xef, 0xe3,
+ 0x64, 0xa0, 0xb1, 0x7b, 0xbf, 0x8e, 0x75, 0x8b, 0xa7, 0x75, 0x8a, 0xd2,
+ 0x6b, 0x7f, 0x24, 0x25, 0x3f, 0x1d, 0x09, 0xb7, 0xb1, 0x2d, 0xff, 0x11,
+ 0xbc, 0x7e, 0xd2, 0x5e, 0x58, 0xbf, 0xfb, 0xed, 0x16, 0x0f, 0xef, 0xdb,
+ 0x22, 0x58, 0xa9, 0x44, 0x1b, 0x9d, 0xde, 0x0e, 0x63, 0xd6, 0x2e, 0xfb,
+ 0xac, 0x58, 0x0b, 0x14, 0x69, 0xa9, 0x21, 0x7a, 0xd8, 0xfa, 0xdd, 0x2a,
+ 0xf1, 0x0b, 0xcb, 0x17, 0xfb, 0xef, 0x20, 0xdb, 0x86, 0xac, 0x54, 0x47,
+ 0xa7, 0xe1, 0xdb, 0xf1, 0x48, 0x58, 0x4b, 0x17, 0xfd, 0xfe, 0xa4, 0xd8,
+ 0xa1, 0x31, 0xeb, 0x16, 0xe0, 0xcf, 0x9f, 0x09, 0xeb, 0x49, 0x93, 0x13,
+ 0xaf, 0xa1, 0x15, 0x4b, 0x17, 0xf0, 0x7e, 0xe3, 0xe1, 0xab, 0x17, 0xe8,
+ 0x69, 0xe4, 0xeb, 0x17, 0xfb, 0x7f, 0x33, 0xeb, 0x58, 0xb1, 0x78, 0x3e,
+ 0x82, 0x58, 0xad, 0x91, 0x72, 0x30, 0xce, 0x8c, 0x34, 0x51, 0xc3, 0x4a,
+ 0x96, 0x44, 0xc6, 0x4a, 0xe0, 0x78, 0xfc, 0x3f, 0x0d, 0xc6, 0x8e, 0xc8,
+ 0x50, 0xee, 0xbd, 0xfe, 0xe1, 0xac, 0x5e, 0x70, 0x4a, 0xc5, 0xf4, 0x33,
+ 0xce, 0xb1, 0x7d, 0x9a, 0x73, 0xac, 0x5e, 0x04, 0x81, 0x62, 0x8c, 0x3f,
+ 0xde, 0x87, 0x38, 0x44, 0x19, 0x15, 0xff, 0xe8, 0x78, 0x5f, 0xd4, 0x85,
+ 0x07, 0x06, 0x2c, 0x5c, 0xc7, 0x58, 0xad, 0xd1, 0x44, 0x47, 0xfd, 0x93,
+ 0x2f, 0xff, 0xde, 0x6d, 0x63, 0x83, 0x99, 0xf7, 0xd7, 0xd9, 0x62, 0xff,
+ 0xbe, 0xfa, 0x88, 0xa6, 0x7a, 0x58, 0xbf, 0xcf, 0xc6, 0x6f, 0x0a, 0x56,
+ 0x2e, 0xdf, 0x16, 0x2f, 0x69, 0xb8, 0xb1, 0x7a, 0x48, 0x6b, 0x17, 0xee,
+ 0xb9, 0x16, 0x79, 0x62, 0xb1, 0x36, 0xee, 0x8c, 0x9d, 0x52, 0x3c, 0xeb,
+ 0x46, 0x47, 0x18, 0xf8, 0xe9, 0x0e, 0x5f, 0xbe, 0xfa, 0x91, 0xac, 0x5f,
+ 0x19, 0xc0, 0xfe, 0xb1, 0x7f, 0x3f, 0x89, 0x81, 0xc5, 0x8b, 0xf4, 0x9f,
+ 0xd9, 0xf5, 0x8b, 0xfd, 0x3d, 0xd8, 0x43, 0xfc, 0xac, 0x5d, 0x9b, 0xac,
+ 0x5f, 0x00, 0x52, 0x75, 0x8a, 0xc3, 0x76, 0xe3, 0x17, 0xa4, 0xb6, 0x58,
+ 0xbf, 0x08, 0x2f, 0xcf, 0x65, 0x8b, 0xff, 0xe2, 0xf4, 0x59, 0xac, 0x33,
+ 0xc0, 0x91, 0xca, 0xc5, 0xe9, 0x28, 0x96, 0x28, 0x69, 0xa3, 0x44, 0xe1,
+ 0xa1, 0xff, 0x8e, 0xb1, 0x60, 0x6a, 0x37, 0xdc, 0x79, 0xdd, 0x62, 0xfb,
+ 0x3a, 0xf3, 0xac, 0x5f, 0xfd, 0x16, 0x6b, 0x18, 0xf3, 0xf7, 0x1a, 0xc5,
+ 0x62, 0x22, 0xbe, 0x47, 0xe2, 0x3b, 0x62, 0xc5, 0xf3, 0x16, 0x01, 0x62,
+ 0xfc, 0x7c, 0xff, 0x4c, 0xb1, 0x51, 0x1e, 0xd9, 0xc4, 0x44, 0x43, 0x7e,
+ 0xf0, 0xa2, 0x0e, 0x56, 0x2e, 0x61, 0xac, 0x5b, 0x20, 0x78, 0x5a, 0x2b,
+ 0xa3, 0x55, 0xd0, 0xee, 0x5b, 0xf8, 0xdb, 0x8a, 0x1c, 0x7c, 0x84, 0x57,
+ 0x67, 0x2b, 0xff, 0xce, 0x32, 0x6e, 0x8b, 0x3d, 0x8e, 0x05, 0x8b, 0xed,
+ 0xb6, 0x68, 0xf5, 0x8b, 0xed, 0xc6, 0x2d, 0x96, 0x2f, 0xfa, 0x02, 0x2f,
+ 0x3f, 0xdc, 0xeb, 0x17, 0xa1, 0xc1, 0x2c, 0x5c, 0xd0, 0x58, 0xbf, 0x79,
+ 0xff, 0x02, 0x58, 0xa3, 0x9b, 0xf2, 0x17, 0xbf, 0xff, 0xff, 0x7e, 0x73,
+ 0x68, 0x3f, 0xb9, 0x3a, 0xc8, 0xc7, 0x04, 0xcf, 0x69, 0x92, 0xdd, 0x62,
+ 0xde, 0xc4, 0xd8, 0xa2, 0x26, 0xf9, 0xcb, 0x2e, 0xf0, 0x82, 0xf7, 0x69,
+ 0x8f, 0x58, 0xbc, 0x10, 0x41, 0x2c, 0x5f, 0xfd, 0xd7, 0x8b, 0x36, 0x3e,
+ 0x1f, 0x09, 0x22, 0x30, 0xd0, 0xd8, 0xf2, 0x89, 0xbc, 0x43, 0xb8, 0x20,
+ 0x2c, 0x5f, 0x75, 0xc9, 0x82, 0xc5, 0x4a, 0x69, 0xef, 0x0e, 0xb6, 0x27,
+ 0x00, 0xcd, 0xf6, 0xd9, 0xf6, 0x58, 0xbd, 0xb4, 0x0e, 0xb1, 0x68, 0x2c,
+ 0x5f, 0xf9, 0xf8, 0x03, 0x8b, 0x9c, 0x90, 0x2c, 0x5f, 0xed, 0x13, 0x05,
+ 0x9f, 0x65, 0x8b, 0xe6, 0xd7, 0xf1, 0x62, 0xff, 0x89, 0xb6, 0xe6, 0x7d,
+ 0xa3, 0xd6, 0x2f, 0xbd, 0x3e, 0xe6, 0x1e, 0xf3, 0x11, 0x5f, 0xbe, 0xda,
+ 0xcd, 0x2c, 0x5f, 0xe7, 0xee, 0x11, 0xf6, 0xef, 0x76, 0x58, 0xbf, 0xef,
+ 0x38, 0x26, 0x19, 0xd7, 0x96, 0x2f, 0xf9, 0xfa, 0x2c, 0xf7, 0xdc, 0x25,
+ 0x8a, 0x93, 0xf4, 0xd1, 0xd5, 0xff, 0xdb, 0x10, 0xb6, 0x17, 0x3d, 0xcc,
+ 0x09, 0x62, 0xfd, 0xd6, 0xee, 0x5b, 0x2c, 0x5f, 0xef, 0xcc, 0x22, 0x83,
+ 0x12, 0xc5, 0x78, 0xf7, 0xc3, 0x2b, 0xa9, 0x46, 0x5b, 0x42, 0xa2, 0xe1,
+ 0x32, 0xc5, 0x18, 0xac, 0xf7, 0x61, 0xf8, 0x09, 0x0d, 0x03, 0x21, 0x23,
+ 0xb9, 0xbc, 0x45, 0x1a, 0x85, 0x9f, 0xe1, 0xd8, 0x44, 0xd7, 0xfc, 0x02,
+ 0xcd, 0xdf, 0x3d, 0xc5, 0x8b, 0xde, 0x91, 0xac, 0x5f, 0x43, 0xc2, 0x1a,
+ 0xc5, 0xfa, 0x5e, 0x0d, 0xc5, 0x8b, 0xf9, 0x83, 0xc8, 0xa4, 0xeb, 0x15,
+ 0x28, 0x97, 0xe8, 0x77, 0x44, 0x82, 0x27, 0xbf, 0xb3, 0xdf, 0x14, 0xf4,
+ 0xb1, 0x7d, 0xe7, 0xd6, 0x2c, 0x5f, 0x75, 0xc7, 0x34, 0x67, 0xa3, 0x85,
+ 0xf5, 0xb2, 0xa3, 0x6d, 0x42, 0x78, 0xa1, 0xa1, 0xe8, 0x47, 0x5f, 0xdc,
+ 0x2c, 0xed, 0xf7, 0x58, 0xbf, 0xfd, 0x0c, 0x27, 0x1e, 0x16, 0x1b, 0x3c,
+ 0x58, 0xbd, 0xbe, 0x71, 0x62, 0xb1, 0x12, 0xbe, 0x2f, 0x12, 0x45, 0xff,
+ 0x8f, 0x3d, 0x16, 0x03, 0x93, 0x1e, 0xb1, 0x7f, 0xbf, 0x9b, 0x67, 0xdf,
+ 0xeb, 0x15, 0xa4, 0x52, 0x9c, 0xbf, 0xe8, 0x57, 0xf6, 0x81, 0x3b, 0xe1,
+ 0xd6, 0x2f, 0xf0, 0xcb, 0x3b, 0x3e, 0x99, 0x62, 0xa3, 0x65, 0xfb, 0x19,
+ 0x9d, 0x96, 0x78, 0xe2, 0x18, 0xc0, 0x45, 0xf7, 0xd1, 0xef, 0x9d, 0x2c,
+ 0x5c, 0xdb, 0xac, 0x56, 0xc6, 0xf9, 0x89, 0xaf, 0xcf, 0xc9, 0xd8, 0xeb,
+ 0x8b, 0xf4, 0xbf, 0x4b, 0x68, 0x02, 0x5c, 0x5f, 0xa5, 0xcd, 0x05, 0xc5,
+ 0xfa, 0x5f, 0x0a, 0x19, 0xc5, 0xc5, 0xfa, 0x50, 0xcf, 0x50, 0x89, 0x2f,
+ 0xd3, 0x9c, 0xc2, 0x5c, 0x5f, 0xa5, 0x2e, 0x2f, 0xd2, 0xe6, 0xf2, 0xe2,
+ 0xfd, 0x0e, 0x5c, 0xda, 0x04, 0x7f, 0xe2, 0x4c, 0xbe, 0xc8, 0xe7, 0x02,
+ 0xe2, 0xfd, 0x29, 0x71, 0x7e, 0x97, 0x02, 0x57, 0x17, 0xe9, 0x7f, 0xd8,
+ 0x06, 0xd6, 0x76, 0xc1, 0xae, 0x2f, 0xd2, 0xfe, 0xcf, 0xbf, 0x05, 0xb2,
+ 0xe2, 0xfd, 0x28, 0x08, 0xa7, 0x22, 0x4e, 0x23, 0xdf, 0x6b, 0x69, 0xf2,
+ 0xe2, 0xfd, 0x29, 0x71, 0x7e, 0x98, 0x6c, 0x6e, 0x08, 0x25, 0xc5, 0xfa,
+ 0x54, 0x15, 0x93, 0x8c, 0xdb, 0x21, 0x13, 0xd4, 0x28, 0x34, 0x4e, 0x73,
+ 0x2e, 0x43, 0x03, 0xcc, 0x01, 0x14, 0x5d, 0x26, 0xa6, 0x2f, 0xd1, 0x18,
+ 0x89, 0x0b, 0xfe, 0xda, 0x7b, 0x63, 0xeb, 0x36, 0x58, 0xbf, 0xf9, 0xbf,
+ 0xbf, 0xdc, 0x9b, 0x4d, 0x05, 0x8a, 0x82, 0x2e, 0xf4, 0x77, 0xe3, 0xcb,
+ 0xfa, 0x70, 0x39, 0x84, 0x16, 0x2f, 0xf7, 0x32, 0x10, 0x9f, 0x74, 0xb1,
+ 0x7f, 0xd3, 0xa0, 0x79, 0xd8, 0xd8, 0x2c, 0x56, 0x23, 0x34, 0x8c, 0x38,
+ 0x5c, 0x19, 0xad, 0xff, 0xb3, 0x71, 0xe6, 0x82, 0x6f, 0xc4, 0xb1, 0x74,
+ 0x86, 0xb1, 0x4b, 0x17, 0xfe, 0x2c, 0x8a, 0x76, 0x03, 0x75, 0xc5, 0x8a,
+ 0x93, 0xcd, 0xe0, 0x65, 0x24, 0x5f, 0x9e, 0x26, 0x68, 0x2c, 0x5a, 0x1b,
+ 0x1b, 0x4c, 0x0c, 0xbe, 0x89, 0x9b, 0x4b, 0x15, 0xb2, 0x70, 0x5d, 0x1e,
+ 0x69, 0x0b, 0xec, 0xa4, 0xab, 0xdc, 0x4f, 0x73, 0xec, 0xb1, 0x7f, 0x4f,
+ 0xc9, 0x9f, 0x4b, 0x15, 0xa5, 0xf8, 0x26, 0x9e, 0xe2, 0xf2, 0xe7, 0x61,
+ 0x8b, 0xe3, 0xf7, 0xdc, 0x22, 0x58, 0xbf, 0xb1, 0xf5, 0x9e, 0x95, 0x8b,
+ 0x1a, 0xb1, 0x44, 0x6f, 0xe3, 0x8b, 0x2f, 0x86, 0x36, 0x3a, 0xc5, 0xfe,
+ 0xcf, 0x1b, 0x3d, 0xb0, 0x6b, 0x15, 0x87, 0xb2, 0x44, 0x77, 0xe2, 0x9f,
+ 0x8b, 0x4b, 0x17, 0xf3, 0x85, 0x11, 0x48, 0x16, 0x2b, 0x87, 0xaf, 0xe2,
+ 0x8b, 0xfb, 0x85, 0x9e, 0xc0, 0x2c, 0x50, 0xd1, 0x8d, 0xd3, 0xb9, 0xc8,
+ 0xaf, 0xf1, 0x67, 0x6f, 0xf4, 0xd1, 0xeb, 0x17, 0xf7, 0x77, 0x85, 0xd4,
+ 0x38, 0xb1, 0x51, 0x1f, 0x68, 0x47, 0x37, 0xf7, 0xb3, 0xf3, 0xa0, 0x2c,
+ 0x5f, 0x69, 0xf3, 0xb2, 0xc5, 0xfb, 0x39, 0x9d, 0x79, 0x62, 0xf8, 0xf2,
+ 0x46, 0x98, 0x79, 0xac, 0x49, 0x7f, 0xda, 0x73, 0xf0, 0x39, 0xc8, 0x96,
+ 0x2f, 0xfb, 0x79, 0x00, 0xc4, 0xda, 0x82, 0xc5, 0xff, 0x99, 0xb6, 0xc3,
+ 0xb1, 0x75, 0x05, 0x8b, 0xcc, 0x6f, 0x30, 0xfe, 0xa2, 0x3b, 0xbb, 0x9b,
+ 0xac, 0x5f, 0xdf, 0xc3, 0x87, 0x20, 0x58, 0xa7, 0x3c, 0x8f, 0x0c, 0xdf,
+ 0xbb, 0xc3, 0x74, 0xdb, 0xac, 0x5f, 0x72, 0x73, 0xcb, 0x17, 0xfe, 0x67,
+ 0xf4, 0x05, 0x25, 0x30, 0x58, 0xbc, 0xdd, 0x4a, 0xc5, 0xbe, 0x62, 0x33,
+ 0x63, 0x51, 0x0e, 0x18, 0x7c, 0x88, 0x33, 0xdb, 0xff, 0xd3, 0xcc, 0x3c,
+ 0xee, 0xd8, 0x37, 0xec, 0xb1, 0x58, 0x8a, 0x22, 0x57, 0xbf, 0x67, 0xf3,
+ 0xaf, 0x2c, 0x58, 0x23, 0x15, 0xcf, 0x63, 0xde, 0x8e, 0x4a, 0x16, 0xbe,
+ 0x8f, 0xae, 0x38, 0x86, 0x8c, 0x5e, 0x0f, 0x98, 0xd0, 0xb2, 0x13, 0xcd,
+ 0x2f, 0x0a, 0xf9, 0xcd, 0x70, 0x96, 0x2f, 0xbd, 0xfc, 0xd9, 0x62, 0x8e,
+ 0x79, 0x04, 0x49, 0x7f, 0xda, 0xce, 0x8b, 0xa7, 0xdb, 0x4b, 0x14, 0xb1,
+ 0x61, 0x80, 0xf2, 0x02, 0x3c, 0xa5, 0x8b, 0xe6, 0x62, 0xdd, 0x62, 0xe1,
+ 0x87, 0xb1, 0xae, 0xec, 0x19, 0x52, 0x8f, 0x1c, 0x69, 0x75, 0x7b, 0xc7,
+ 0x06, 0x96, 0x2e, 0xf1, 0x2c, 0x5f, 0x86, 0xd0, 0xfe, 0x2c, 0x5e, 0x20,
+ 0x6e, 0xb1, 0x43, 0x3d, 0xdc, 0x17, 0xe1, 0x45, 0xff, 0xee, 0xbd, 0xf7,
+ 0x0c, 0x79, 0x85, 0xc7, 0x58, 0xbf, 0xff, 0x43, 0x53, 0xd9, 0xa2, 0x91,
+ 0xfe, 0x4e, 0xd1, 0x2c, 0x5f, 0xee, 0xe6, 0xe3, 0xf2, 0x2c, 0x58, 0xbf,
+ 0x89, 0x81, 0xc3, 0xca, 0xc5, 0xff, 0xe9, 0xd0, 0x33, 0xb3, 0xfa, 0x70,
+ 0xa0, 0xb1, 0x46, 0x27, 0xf7, 0x18, 0xf7, 0x85, 0xdd, 0x25, 0xe9, 0x67,
+ 0xc6, 0xe1, 0x96, 0xdb, 0xcb, 0x17, 0xec, 0xe7, 0x0f, 0xd2, 0xc5, 0xba,
+ 0x30, 0xde, 0x48, 0x95, 0xe9, 0x1c, 0xac, 0x54, 0x9e, 0x21, 0xca, 0x2f,
+ 0x39, 0x41, 0x62, 0xa5, 0xd9, 0xfd, 0x6c, 0xfb, 0x0a, 0x66, 0x18, 0xdd,
+ 0x32, 0x55, 0x76, 0xee, 0x7d, 0x14, 0x3c, 0xbc, 0x78, 0xf6, 0xc8, 0x92,
+ 0x35, 0x2b, 0x67, 0xf3, 0xfe, 0x2d, 0x48, 0x1d, 0x02, 0x49, 0x4f, 0x3d,
+ 0x72, 0x38, 0x91, 0x4a, 0x28, 0x0a, 0x1d, 0x5d, 0xc4, 0x37, 0xef, 0x9e,
+ 0x63, 0x4c, 0x58, 0xbd, 0xbe, 0xcc, 0xb1, 0x74, 0x9d, 0x62, 0xfe, 0x9f,
+ 0x7e, 0x7b, 0x62, 0xc5, 0x0c, 0xf1, 0xb7, 0x17, 0xbb, 0x6c, 0x58, 0xbf,
+ 0xb3, 0xdf, 0x13, 0x41, 0x62, 0xdb, 0x98, 0x8c, 0xec, 0x65, 0x01, 0x19,
+ 0x0c, 0x52, 0xc5, 0x9b, 0x47, 0x9e, 0x74, 0x3b, 0xfb, 0x0f, 0x13, 0x34,
+ 0x16, 0x2f, 0xe9, 0x3b, 0xee, 0xe3, 0x58, 0xbf, 0xff, 0x9b, 0xf3, 0x08,
+ 0xcc, 0x04, 0xc3, 0x83, 0xfc, 0xe9, 0x62, 0xce, 0x34, 0x5d, 0x6e, 0x5d,
+ 0xf2, 0xeb, 0xdb, 0xee, 0x25, 0x8b, 0xfe, 0x9e, 0x8a, 0x7f, 0xf1, 0x6e,
+ 0xb1, 0x58, 0x7b, 0x66, 0x90, 0x5f, 0xfa, 0x70, 0xb2, 0x0f, 0xfc, 0xec,
+ 0xb1, 0x7f, 0xf1, 0x30, 0x39, 0xac, 0xdf, 0xf9, 0xd2, 0xc5, 0x69, 0x10,
+ 0x9e, 0x3e, 0xbe, 0xcd, 0x39, 0xab, 0x17, 0xef, 0xbf, 0x26, 0x0b, 0x17,
+ 0xff, 0x98, 0xde, 0x67, 0x69, 0xeb, 0xdc, 0x11, 0xd6, 0x29, 0x8f, 0xdc,
+ 0x8a, 0x28, 0x68, 0xdd, 0x39, 0x19, 0x42, 0x6a, 0xf1, 0xe3, 0xe5, 0x62,
+ 0xff, 0x72, 0x4b, 0xdf, 0x90, 0xd6, 0x2a, 0x4f, 0x53, 0xc4, 0x17, 0xfc,
+ 0x6b, 0xe8, 0x3d, 0x3c, 0x8d, 0x62, 0xe2, 0xef, 0xd6, 0x2f, 0xa7, 0xee,
+ 0x6e, 0x1e, 0xbe, 0x8e, 0xef, 0xfd, 0x87, 0x68, 0x47, 0x08, 0x6f, 0xf5,
+ 0x8a, 0xf9, 0xfd, 0x11, 0xc5, 0xfb, 0xde, 0x68, 0x71, 0x62, 0xff, 0x14,
+ 0xfb, 0xa8, 0x98, 0xeb, 0x17, 0xef, 0x0b, 0xd8, 0x35, 0x8b, 0x62, 0xc5,
+ 0x31, 0xba, 0xec, 0x53, 0x7f, 0x9f, 0x98, 0x5b, 0x05, 0x12, 0xc5, 0xfe,
+ 0xe6, 0x19, 0xd4, 0x33, 0xcb, 0x17, 0x7f, 0x06, 0x7d, 0x9c, 0x36, 0xa8,
+ 0x26, 0xe8, 0x32, 0x13, 0x94, 0x93, 0x7f, 0xa1, 0x1d, 0x7e, 0xd0, 0x1b,
+ 0x00, 0xb1, 0x7f, 0x67, 0x73, 0xf9, 0xe0, 0xb1, 0x7d, 0xf9, 0xdb, 0x98,
+ 0x7b, 0x1f, 0x28, 0xbf, 0xf7, 0xe5, 0x9f, 0xee, 0x76, 0x1a, 0xc5, 0xef,
+ 0xb4, 0x16, 0x2f, 0xf8, 0x3d, 0x7a, 0x0e, 0x5e, 0xe2, 0xc5, 0x98, 0xd3,
+ 0xd8, 0xf8, 0xed, 0x3a, 0x2f, 0x4a, 0x12, 0xb7, 0xcf, 0xc0, 0xce, 0xb1,
+ 0x7f, 0x48, 0xb7, 0xfc, 0xe9, 0x62, 0xff, 0xef, 0x6f, 0xf7, 0x2c, 0xf7,
+ 0x24, 0xeb, 0x15, 0xb9, 0xfa, 0x74, 0x5f, 0x7d, 0x3b, 0xbc, 0x16, 0x2f,
+ 0x8e, 0x59, 0xec, 0x3c, 0x72, 0x24, 0xbf, 0xff, 0x4f, 0xcb, 0x3d, 0xf7,
+ 0x30, 0xf9, 0xe6, 0xf2, 0xc5, 0xcf, 0xd9, 0x62, 0xbc, 0x7d, 0xdd, 0xca,
+ 0xb4, 0xb1, 0x7f, 0xc5, 0x80, 0xfc, 0xb6, 0xb1, 0x62, 0x9c, 0xfa, 0x34,
+ 0x4b, 0xc0, 0xcb, 0xf7, 0xbe, 0xfa, 0x0d, 0x62, 0xff, 0x9a, 0x3f, 0x9e,
+ 0x29, 0x0c, 0xeb, 0x15, 0x87, 0xce, 0x22, 0xaa, 0xdd, 0x55, 0x0b, 0xc3,
+ 0x7d, 0xa3, 0x0c, 0x28, 0x4a, 0xdf, 0xb7, 0xc3, 0xcf, 0x16, 0x2f, 0x04,
+ 0x10, 0x49, 0x17, 0x83, 0x90, 0x24, 0x46, 0x1a, 0x1b, 0xfd, 0xd9, 0xb0,
+ 0xa1, 0x84, 0xb1, 0x7f, 0xcd, 0x00, 0xf5, 0x9d, 0x9b, 0x4b, 0x16, 0xd2,
+ 0xc5, 0xfe, 0x29, 0x81, 0xba, 0xce, 0x2c, 0x5f, 0xf9, 0xe7, 0x50, 0x35,
+ 0xf8, 0x1f, 0xd6, 0x2f, 0xfc, 0x45, 0x9b, 0x45, 0x09, 0xd6, 0xcb, 0x17,
+ 0xbf, 0x90, 0x94, 0x64, 0x60, 0x91, 0xcd, 0x03, 0x41, 0xa7, 0x4e, 0x10,
+ 0x8c, 0xfd, 0x18, 0x25, 0xff, 0xfc, 0xf2, 0x40, 0x04, 0xc1, 0xfd, 0x87,
+ 0xe3, 0x41, 0x62, 0xff, 0xf8, 0xe5, 0x31, 0x43, 0x3f, 0xf7, 0xce, 0x89,
+ 0x62, 0xff, 0xde, 0x92, 0xcd, 0x9f, 0x58, 0x35, 0x8b, 0xdf, 0x6d, 0x2c,
+ 0x5f, 0xf9, 0xce, 0xfa, 0x2c, 0xf0, 0x99, 0x62, 0xa4, 0xf6, 0xbc, 0x3b,
+ 0x73, 0x8f, 0x11, 0x73, 0xc8, 0x4c, 0x5d, 0xc0, 0x96, 0x2f, 0xfb, 0xee,
+ 0x0e, 0xa1, 0xe7, 0x02, 0xc5, 0xfe, 0x28, 0x39, 0xf3, 0xaf, 0x2c, 0x5f,
+ 0xb3, 0x41, 0xcc, 0x16, 0x2f, 0xba, 0xdd, 0xc9, 0x62, 0x86, 0x8d, 0x5c,
+ 0x19, 0x63, 0xb2, 0x34, 0xf1, 0x4d, 0x2c, 0x5a, 0x60, 0x7a, 0x7d, 0xfa,
+ 0x3d, 0x6e, 0x9c, 0x30, 0x23, 0x5a, 0xbf, 0x19, 0x3b, 0xe6, 0x96, 0x2f,
+ 0xf6, 0x6b, 0x1b, 0x7e, 0x41, 0x62, 0xff, 0xff, 0x9f, 0xdf, 0x68, 0x46,
+ 0x67, 0xdb, 0xa0, 0x78, 0xa4, 0xfc, 0x58, 0xbf, 0xf1, 0x92, 0x42, 0x3c,
+ 0x85, 0x3c, 0x58, 0xb6, 0x0d, 0x30, 0x83, 0x95, 0x7c, 0xd0, 0x9a, 0xaf,
+ 0xfb, 0xcc, 0x59, 0xcd, 0x4f, 0x16, 0x2f, 0xa1, 0x20, 0xe9, 0x62, 0xff,
+ 0xf6, 0x05, 0x9d, 0x9f, 0x85, 0x87, 0x3b, 0xac, 0x5f, 0xff, 0xfd, 0xf9,
+ 0x21, 0x73, 0xef, 0xef, 0xe1, 0x7b, 0xe5, 0x9d, 0xb3, 0x8b, 0x17, 0x0c,
+ 0x6b, 0x17, 0xe9, 0x83, 0xf8, 0xeb, 0x15, 0x04, 0x59, 0x1d, 0xc8, 0x86,
+ 0x2f, 0xff, 0xf3, 0x3f, 0xa6, 0x0f, 0xad, 0x84, 0x08, 0xe8, 0xec, 0x1b,
+ 0xac, 0x5f, 0xff, 0xf3, 0x76, 0x7e, 0xc4, 0x2e, 0x06, 0x52, 0x3f, 0xb4,
+ 0x33, 0x8b, 0x17, 0xf0, 0x24, 0xb3, 0xaf, 0x2c, 0x5c, 0xc0, 0x31, 0x52,
+ 0x7e, 0xc4, 0x99, 0x0f, 0xdf, 0x97, 0x93, 0x38, 0x6d, 0x57, 0xff, 0x83,
+ 0x28, 0x8d, 0x61, 0xff, 0x37, 0xcd, 0x2c, 0x56, 0x2f, 0xa1, 0xbc, 0xa8,
+ 0xff, 0xc6, 0x66, 0xc8, 0x45, 0x2a, 0x1f, 0x8d, 0x57, 0xbd, 0x07, 0x58,
+ 0xbf, 0xef, 0x94, 0xc3, 0xec, 0x4e, 0xb1, 0x74, 0xe9, 0x62, 0x9c, 0xf3,
+ 0xbb, 0x1b, 0xdf, 0xfb, 0xf9, 0xb7, 0x5c, 0xcd, 0xd8, 0x35, 0x8b, 0xb3,
+ 0xeb, 0x14, 0xe7, 0xb4, 0x24, 0x3a, 0xd9, 0xb5, 0xd7, 0x84, 0x38, 0x47,
+ 0x09, 0x1c, 0x8e, 0x0f, 0xa8, 0x44, 0x3c, 0xa6, 0x68, 0xa1, 0x4e, 0x78,
+ 0x7b, 0x7e, 0x56, 0x3b, 0x26, 0x81, 0x28, 0xa3, 0xb5, 0xe1, 0xaf, 0xa7,
+ 0xe7, 0x04, 0xd5, 0xd9, 0xac, 0x27, 0xdb, 0x9f, 0x65, 0x8b, 0xfc, 0x5b,
+ 0x8d, 0xfb, 0x48, 0xd6, 0x28, 0x67, 0x9c, 0x21, 0x8b, 0xfd, 0xc7, 0x3b,
+ 0x69, 0xb8, 0xb1, 0x7e, 0xf7, 0xb0, 0xb6, 0x58, 0xbf, 0xfc, 0xfa, 0xfc,
+ 0xbf, 0xb8, 0xe5, 0xd4, 0x16, 0x2f, 0xfc, 0xe1, 0x6b, 0x0e, 0x76, 0x2f,
+ 0x2c, 0x54, 0xa2, 0xcb, 0x0a, 0x49, 0x2a, 0xfe, 0xcd, 0xfd, 0x1d, 0x9f,
+ 0x58, 0xa5, 0x8a, 0xf9, 0xbe, 0x01, 0x95, 0xff, 0xd1, 0x7e, 0x76, 0x0f,
+ 0xdf, 0x13, 0x41, 0x62, 0xf1, 0xe7, 0xeb, 0x17, 0xd3, 0xbe, 0x1d, 0x62,
+ 0xb0, 0xf0, 0x3e, 0x3b, 0x4b, 0x14, 0x46, 0xb7, 0xb8, 0x86, 0xfa, 0x18,
+ 0xc7, 0x58, 0xbf, 0x1a, 0x28, 0x30, 0xd6, 0x2f, 0xf4, 0xc7, 0x99, 0xf6,
+ 0xcd, 0x2c, 0x5f, 0xfd, 0xe2, 0x9f, 0x3e, 0x11, 0x93, 0xd9, 0x62, 0xe7,
+ 0xdd, 0x62, 0xf6, 0x6a, 0x56, 0x2f, 0xbf, 0xfc, 0xe9, 0x62, 0xec, 0x3c,
+ 0x71, 0xe0, 0x06, 0x39, 0x58, 0x98, 0x2b, 0x9b, 0xfd, 0x14, 0x96, 0x2d,
+ 0x1e, 0xb1, 0x68, 0x96, 0x2c, 0x75, 0x8a, 0x73, 0x4a, 0xc2, 0x74, 0x69,
+ 0xec, 0x9c, 0xea, 0xff, 0xff, 0x8c, 0x26, 0x34, 0xcf, 0x00, 0x32, 0x87,
+ 0xf3, 0x9e, 0xcd, 0x2c, 0x5f, 0xb0, 0x1c, 0x98, 0x2c, 0x5f, 0x9c, 0xe3,
+ 0x1e, 0x2c, 0x58, 0x10, 0x45, 0xd9, 0x35, 0xc7, 0x14, 0x5f, 0xf7, 0xbf,
+ 0x9c, 0x33, 0xcf, 0xb2, 0xc5, 0xfd, 0x91, 0x66, 0x86, 0xeb, 0x15, 0x28,
+ 0xa2, 0x73, 0x82, 0x3c, 0xbf, 0xf4, 0x97, 0x50, 0xe0, 0x7b, 0x37, 0x96,
+ 0x2f, 0xf8, 0x9c, 0x5d, 0xff, 0x23, 0xa7, 0xcb, 0x17, 0xfb, 0x02, 0xea,
+ 0x1e, 0x90, 0x96, 0x2f, 0xec, 0x68, 0xbf, 0x31, 0xeb, 0x15, 0x27, 0xd0,
+ 0x03, 0x7b, 0xfc, 0x0d, 0x3e, 0x7c, 0x5c, 0x58, 0xbd, 0x9d, 0x1d, 0x62,
+ 0xfe, 0xc0, 0x77, 0x79, 0xce, 0xb1, 0x52, 0x88, 0x32, 0x34, 0xf0, 0xf5,
+ 0xf4, 0x76, 0x6a, 0x56, 0x2f, 0xff, 0xf7, 0xe4, 0x84, 0xde, 0x98, 0x3f,
+ 0xd8, 0xf3, 0xee, 0x2c, 0x5e, 0x35, 0xb4, 0xb1, 0x6f, 0x0c, 0xff, 0x7c,
+ 0xbf, 0x4b, 0x16, 0x90, 0x23, 0x58, 0xa1, 0x45, 0xd8, 0xa2, 0xff, 0xe6,
+ 0xf6, 0x84, 0x6e, 0x79, 0xc1, 0xc5, 0x8b, 0xf8, 0x19, 0xcf, 0xe7, 0x16,
+ 0x2e, 0xd0, 0x16, 0x29, 0xcf, 0x19, 0x8b, 0xaf, 0x63, 0x8d, 0x62, 0xa5,
+ 0x92, 0xe5, 0xb4, 0x39, 0x60, 0xd6, 0x32, 0x1c, 0x85, 0xb7, 0x44, 0x6e,
+ 0x45, 0x14, 0x65, 0xe7, 0x84, 0xa7, 0xe3, 0x80, 0x01, 0x69, 0x21, 0x72,
+ 0x15, 0x3e, 0x85, 0x27, 0x68, 0xc1, 0x02, 0x3b, 0x8e, 0x84, 0x67, 0x71,
+ 0x05, 0xf7, 0xf3, 0xa8, 0x2c, 0x5f, 0x67, 0x83, 0xd9, 0x62, 0xfc, 0x52,
+ 0xfd, 0x41, 0x62, 0xf0, 0x41, 0x04, 0x99, 0x04, 0x05, 0xf6, 0xec, 0xdb,
+ 0xa6, 0x41, 0x01, 0x18, 0x6b, 0xef, 0xf4, 0xed, 0xd4, 0x04, 0xde, 0x58,
+ 0xbe, 0x6d, 0x60, 0x4b, 0x15, 0xa4, 0x4f, 0x71, 0x17, 0xb1, 0xb5, 0xe0,
+ 0x82, 0x09, 0x32, 0x07, 0x8a, 0x4c, 0x81, 0xe2, 0x30, 0xd7, 0xdf, 0xde,
+ 0x63, 0x9e, 0x4e, 0xb1, 0x7e, 0x6f, 0x31, 0x01, 0x62, 0xfe, 0xcf, 0x7c,
+ 0x4d, 0x05, 0x8b, 0xc1, 0x04, 0x12, 0xc5, 0xee, 0x49, 0xa9, 0x11, 0x86,
+ 0x86, 0xfd, 0x21, 0x67, 0xd9, 0x62, 0xa5, 0x54, 0x06, 0x43, 0xd7, 0x76,
+ 0x1e, 0x8b, 0x7e, 0x5c, 0x44, 0xfe, 0x4f, 0x0c, 0xc6, 0xa3, 0xd5, 0x8e,
+ 0x9e, 0x55, 0x2d, 0xfe, 0xfc, 0xf6, 0x92, 0x9f, 0x2c, 0x5f, 0xd9, 0xd4,
+ 0x21, 0x27, 0x58, 0xbf, 0xfd, 0xcf, 0xb4, 0x33, 0xee, 0x7e, 0x4c, 0x7a,
+ 0xc5, 0xfc, 0xe6, 0xc8, 0xd8, 0xeb, 0x17, 0x82, 0x92, 0x58, 0xbf, 0xb7,
+ 0xfc, 0xeb, 0x0e, 0xb1, 0x7f, 0xff, 0x7d, 0x8e, 0x76, 0x80, 0x65, 0xdb,
+ 0x07, 0x9d, 0x79, 0x62, 0xf4, 0x96, 0xd8, 0x88, 0xee, 0x17, 0xdf, 0xfd,
+ 0xf9, 0x83, 0xfb, 0x3f, 0xbc, 0x9d, 0x62, 0xa5, 0x51, 0x84, 0x0b, 0xc6,
+ 0x69, 0x85, 0xff, 0x4d, 0x62, 0xee, 0x42, 0xaf, 0xb1, 0x9d, 0xfb, 0x79,
+ 0xfc, 0x9d, 0x62, 0xff, 0xdf, 0x78, 0x89, 0x82, 0xf6, 0x7d, 0x62, 0xe9,
+ 0xe2, 0xc5, 0x62, 0x20, 0x37, 0x29, 0xf2, 0x05, 0xf0, 0x65, 0x0e, 0x2c,
+ 0x5f, 0xfb, 0xee, 0x39, 0x2f, 0x67, 0x5e, 0x58, 0xbd, 0xc1, 0x12, 0xc5,
+ 0xf4, 0x0a, 0x46, 0xb1, 0x78, 0xa4, 0xfc, 0x37, 0xe1, 0x8e, 0xdf, 0xe1,
+ 0x37, 0x22, 0x29, 0x3a, 0xc5, 0x6e, 0x8e, 0x4e, 0x3f, 0x78, 0xca, 0xff,
+ 0xef, 0xbe, 0xbe, 0xd9, 0xc7, 0x6d, 0x96, 0x2f, 0xf0, 0x4d, 0xec, 0x3b,
+ 0x74, 0xb1, 0x7f, 0xde, 0xcd, 0x67, 0x33, 0xaf, 0x2c, 0x5f, 0xf4, 0xed,
+ 0x23, 0xc3, 0xf5, 0x2b, 0x17, 0xbe, 0x20, 0x2c, 0x5f, 0x04, 0xda, 0x34,
+ 0x67, 0xb1, 0x87, 0x55, 0x28, 0xcc, 0xc8, 0x49, 0x56, 0x26, 0xd7, 0xf4,
+ 0x42, 0x8c, 0x06, 0xff, 0x8f, 0x87, 0xc2, 0xf6, 0x6e, 0xb1, 0x7f, 0x8d,
+ 0xcd, 0xe7, 0xf2, 0x75, 0x8a, 0xd8, 0xfb, 0x98, 0xe6, 0xfa, 0x7d, 0x27,
+ 0x58, 0xbf, 0x89, 0xcd, 0x33, 0x7f, 0xac, 0x5f, 0xf1, 0x34, 0x3d, 0xec,
+ 0x2d, 0x96, 0x2f, 0xfd, 0x80, 0x03, 0x71, 0xcb, 0xa8, 0x2c, 0x5e, 0x0f,
+ 0xec, 0xb1, 0x58, 0x8c, 0x7f, 0x98, 0x91, 0xcc, 0x71, 0xfd, 0x46, 0xcb,
+ 0x98, 0x06, 0x98, 0x75, 0x18, 0x41, 0xe3, 0x9c, 0x28, 0x51, 0xf8, 0x88,
+ 0x28, 0x74, 0xdd, 0xac, 0x58, 0xbd, 0xf9, 0xee, 0x58, 0xbf, 0xd2, 0x5b,
+ 0xf5, 0xc6, 0x8f, 0x58, 0xa3, 0x0f, 0xbc, 0x62, 0xff, 0x20, 0xbf, 0xf9,
+ 0xbb, 0x67, 0xf3, 0x45, 0x3d, 0x41, 0x62, 0xe9, 0xd9, 0x62, 0xbe, 0x7b,
+ 0xdd, 0xc8, 0xd7, 0xc4, 0x2d, 0x89, 0x62, 0xfc, 0xdc, 0x1b, 0x6e, 0xb1,
+ 0x79, 0xfa, 0x82, 0xc5, 0x40, 0xfa, 0x8d, 0x23, 0x01, 0x4d, 0xf3, 0xf8,
+ 0x5f, 0x58, 0xbf, 0x87, 0xcc, 0x3c, 0xc7, 0xac, 0x5f, 0xfd, 0xc1, 0x16,
+ 0xb2, 0x7a, 0x84, 0x92, 0xc5, 0xf6, 0x0d, 0xa0, 0xb1, 0x78, 0x4c, 0x1a,
+ 0xc5, 0xfe, 0xcf, 0xb7, 0x3f, 0x3c, 0x58, 0xbb, 0x6e, 0x96, 0x28, 0x67,
+ 0xd7, 0xd0, 0xf0, 0x0c, 0xe8, 0xc4, 0x5e, 0xb4, 0x23, 0x6a, 0x0a, 0xb2,
+ 0x87, 0x08, 0xee, 0xa1, 0x1f, 0x11, 0x83, 0x11, 0xf0, 0xc4, 0x28, 0xc0,
+ 0x6f, 0xf7, 0x3f, 0x9c, 0xf6, 0x6e, 0xb1, 0x7e, 0x2f, 0x7f, 0x20, 0xb1,
+ 0x79, 0xe4, 0xd5, 0x8a, 0x73, 0xfa, 0x63, 0x52, 0x28, 0xbf, 0xec, 0x29,
+ 0xff, 0xe4, 0x27, 0x58, 0xbe, 0xdf, 0xee, 0x12, 0xc5, 0xdd, 0xda, 0x58,
+ 0xbc, 0x1c, 0x81, 0x62, 0xff, 0xb7, 0x0b, 0x3a, 0xf7, 0xa4, 0xeb, 0x17,
+ 0xd1, 0x14, 0x9d, 0x62, 0xff, 0xff, 0xff, 0x8c, 0x2c, 0x35, 0xff, 0xfc,
+ 0x8f, 0x32, 0x77, 0x60, 0xcc, 0xc2, 0xd9, 0xf4, 0xe2, 0xef, 0xf1, 0x62,
+ 0xb6, 0x4f, 0x08, 0xd2, 0xce, 0x8e, 0x22, 0x25, 0x38, 0xd9, 0x0f, 0x70,
+ 0xf4, 0x22, 0x3b, 0xdf, 0x9d, 0x2c, 0x5f, 0xff, 0xe9, 0x33, 0xd1, 0xd8,
+ 0x66, 0x7d, 0x8b, 0x22, 0x84, 0xf4, 0xb1, 0x7f, 0x10, 0xbd, 0xa1, 0x41,
+ 0x62, 0xfd, 0xbc, 0xfe, 0x4e, 0x91, 0x7e, 0x26, 0x22, 0xc4, 0x8b, 0xb3,
+ 0x74, 0x8b, 0x82, 0x09, 0x22, 0xb1, 0x10, 0x1c, 0x29, 0xf1, 0x28, 0x43,
+ 0x17, 0xe9, 0x07, 0xf3, 0xb9, 0x22, 0x30, 0xde, 0xd0, 0xd3, 0x90, 0xc6,
+ 0x60, 0xe1, 0xd9, 0x5b, 0x27, 0xc6, 0x51, 0xd6, 0xdf, 0xfc, 0x3d, 0x36,
+ 0xe5, 0x9d, 0xb4, 0xfc, 0x58, 0xbf, 0xc5, 0x9e, 0x29, 0x17, 0x7e, 0xb1,
+ 0x7b, 0x67, 0xd2, 0xc5, 0x6c, 0x89, 0xc3, 0x51, 0xfe, 0x6f, 0x52, 0xc9,
+ 0xc2, 0xc9, 0x77, 0xaf, 0x2a, 0xd1, 0xa5, 0x2c, 0x8a, 0x18, 0xd7, 0x07,
+ 0xa5, 0x8b, 0x9b, 0xeb, 0x14, 0xc6, 0xc3, 0xc3, 0x37, 0xff, 0x7e, 0x41,
+ 0xef, 0xe4, 0x3e, 0xfd, 0x96, 0x2f, 0xa7, 0xd9, 0x05, 0x8b, 0xff, 0xa4,
+ 0x1c, 0xcc, 0x1b, 0x13, 0x1a, 0xb1, 0x7f, 0xde, 0xe3, 0x74, 0xf3, 0xd7,
+ 0x96, 0x2f, 0xf8, 0x81, 0xf6, 0xf7, 0x9c, 0x0b, 0x17, 0xff, 0xef, 0xbf,
+ 0x67, 0x21, 0xf2, 0x74, 0xf9, 0xd7, 0x16, 0x2f, 0xf6, 0x76, 0x92, 0xf4,
+ 0x3b, 0xf5, 0x8b, 0xfd, 0xbb, 0xf3, 0x07, 0x0e, 0xfd, 0x62, 0xf0, 0xc5,
+ 0xc5, 0x8b, 0xfd, 0x98, 0x53, 0x08, 0x77, 0xeb, 0x17, 0xf1, 0x4e, 0x69,
+ 0x80, 0xb1, 0x7f, 0xe9, 0xd7, 0xe5, 0xff, 0x24, 0xeb, 0x17, 0x43, 0x98,
+ 0x9e, 0x0e, 0xe7, 0x3a, 0x57, 0xf9, 0xd3, 0x1d, 0x10, 0xf7, 0x8d, 0xc2,
+ 0x2c, 0xbe, 0xfb, 0x37, 0x96, 0x2f, 0xe2, 0xc3, 0xbf, 0x50, 0x58, 0xbf,
+ 0xfc, 0xcf, 0xe9, 0x2d, 0xdc, 0xfc, 0x1f, 0x4b, 0x15, 0x27, 0xf3, 0xf2,
+ 0xeb, 0xfd, 0xf9, 0xc8, 0x4e, 0x01, 0x62, 0xff, 0xf1, 0x67, 0x40, 0x6e,
+ 0x36, 0x9f, 0xa0, 0x2c, 0x50, 0xcf, 0xf7, 0x86, 0x55, 0x05, 0x7a, 0x9d,
+ 0x47, 0xf8, 0x07, 0xdf, 0x42, 0x6c, 0x28, 0x4f, 0x5f, 0x4e, 0xf8, 0x75,
+ 0x8b, 0xe3, 0x88, 0xa0, 0xb1, 0x7c, 0xd1, 0x4f, 0x72, 0xc5, 0xd2, 0x75,
+ 0x8b, 0xdf, 0x68, 0x6c, 0x7c, 0x1f, 0x23, 0x22, 0x6a, 0x1a, 0x30, 0xfd,
+ 0x08, 0x3b, 0x9c, 0x25, 0x8b, 0xf7, 0xcf, 0x39, 0xe5, 0x8b, 0x85, 0xc5,
+ 0x8a, 0xc3, 0xc0, 0xe1, 0x45, 0xe1, 0x60, 0xd6, 0x28, 0x91, 0x2d, 0xe5,
+ 0x88, 0xe2, 0x1a, 0x82, 0xf4, 0x89, 0xd1, 0xfe, 0x44, 0xd3, 0x82, 0xe5,
+ 0x19, 0x0f, 0x21, 0x7d, 0x7b, 0xb0, 0x67, 0x58, 0xbe, 0xfe, 0xd8, 0x12,
+ 0xc5, 0xf0, 0xc4, 0x50, 0x58, 0xb7, 0x18, 0xf2, 0x03, 0x25, 0xbd, 0x8c,
+ 0x05, 0x8b, 0xcc, 0x7e, 0x96, 0x2d, 0xb8, 0xcd, 0xd6, 0x0e, 0x5a, 0x35,
+ 0xac, 0x5e, 0x29, 0x82, 0xc5, 0xff, 0xb3, 0x9e, 0x86, 0x1a, 0x58, 0x05,
+ 0x8b, 0xc3, 0xc2, 0x58, 0xae, 0xf5, 0x11, 0xe3, 0x18, 0x61, 0xce, 0xe3,
+ 0xfa, 0x74, 0x7d, 0x0a, 0x16, 0xd7, 0xcf, 0xf3, 0xb2, 0xc5, 0xff, 0x82,
+ 0x1e, 0xa7, 0xec, 0x38, 0x1d, 0x62, 0xff, 0xff, 0xfe, 0xd0, 0x27, 0xdc,
+ 0x33, 0xd0, 0xc0, 0x47, 0x61, 0x83, 0xc1, 0xcb, 0x6b, 0x08, 0x08, 0x20,
+ 0xbf, 0xff, 0xff, 0xff, 0xff, 0xe7, 0x93, 0xb0, 0xf6, 0x17, 0x0c, 0xc1,
+ 0x8b, 0x50, 0xfb, 0x99, 0x9a, 0x04, 0xfb, 0x86, 0x7a, 0x18, 0x08, 0xec,
+ 0x30, 0x78, 0x39, 0x6d, 0x61, 0x01, 0x06, 0x17, 0xff, 0xdc, 0xe8, 0xc1,
+ 0xe0, 0xe5, 0xb5, 0x84, 0x05, 0x8a, 0xfa, 0x69, 0x9e, 0x87, 0xdd, 0xff,
+ 0xff, 0x8c, 0xf4, 0x30, 0x11, 0xd8, 0x60, 0xf0, 0x72, 0xda, 0xc2, 0x02,
+ 0x10, 0x5f, 0xfd, 0x9e, 0x33, 0x7f, 0xbf, 0xfe, 0xe0, 0x55, 0xa1, 0x65,
+ 0x41, 0x19, 0x1c, 0x74, 0xbd, 0x3b, 0x46, 0x62, 0xaf, 0x2e, 0x47, 0xbd,
+ 0xe8, 0x78, 0xde, 0x04, 0xf4, 0xb1, 0x73, 0x79, 0x62, 0xf1, 0x67, 0x72,
+ 0xc5, 0xf6, 0x6e, 0xdb, 0xac, 0x5f, 0x8f, 0xc0, 0x9b, 0xa5, 0x8a, 0x1a,
+ 0x3d, 0x1d, 0x44, 0xe3, 0xcc, 0x2f, 0xe1, 0xf0, 0xc9, 0x2a, 0x57, 0x27,
+ 0xfa, 0x22, 0xe4, 0xe1, 0x3d, 0xfa, 0x28, 0x3e, 0xb8, 0xb1, 0x70, 0x89,
+ 0x62, 0xb0, 0xf0, 0x7e, 0x55, 0x7e, 0xda, 0x7c, 0xf1, 0x2c, 0x5f, 0x07,
+ 0xc9, 0xc5, 0x8b, 0xf0, 0x7d, 0xd2, 0x50, 0x58, 0xad, 0xcf, 0xe7, 0xa2,
+ 0xa0, 0x11, 0xdf, 0xff, 0xef, 0xcf, 0xb8, 0xff, 0x7d, 0x16, 0x6c, 0x66,
+ 0x49, 0xd6, 0x2f, 0xb8, 0x66, 0xb1, 0x62, 0xfb, 0xfb, 0xbf, 0x16, 0x2a,
+ 0x51, 0xb5, 0xb1, 0x8b, 0x30, 0xf8, 0x92, 0xff, 0xff, 0x83, 0x1f, 0xe6,
+ 0x1e, 0xcc, 0x0b, 0x85, 0x9e, 0xf3, 0xec, 0xb1, 0x7f, 0xc3, 0x76, 0xed,
+ 0x3d, 0x9b, 0xeb, 0x17, 0x37, 0x4b, 0x16, 0xc5, 0x8b, 0x36, 0xc8, 0xce,
+ 0xe9, 0xa5, 0x8f, 0x3b, 0x0c, 0x5e, 0x72, 0xc5, 0x8b, 0xf6, 0xb4, 0xc0,
+ 0x95, 0x8a, 0x81, 0xe1, 0xb0, 0xdd, 0x77, 0xaf, 0x94, 0x45, 0x35, 0xb9,
+ 0x08, 0xe3, 0x76, 0xca, 0x4c, 0xa6, 0xf1, 0x97, 0xbc, 0xeb, 0x8e, 0xa9,
+ 0xef, 0x3f, 0x84, 0xa3, 0x4f, 0x58, 0x81, 0xaf, 0xbf, 0x69, 0x28, 0xd7,
+ 0x39, 0x39, 0x8d, 0xe7, 0xc1, 0x46, 0xe8, 0x14, 0x61, 0x41, 0xc2, 0x22,
+ 0xe8, 0xde, 0x34, 0x58, 0xbe, 0xc0, 0x6a, 0x56, 0x2f, 0x04, 0x10, 0x49,
+ 0x17, 0x98, 0x86, 0x91, 0x18, 0x68, 0x6f, 0xb3, 0x59, 0xe5, 0x8a, 0xfa,
+ 0x25, 0x00, 0x87, 0xc2, 0xfb, 0xff, 0x8d, 0x60, 0xca, 0x5c, 0x79, 0xd7,
+ 0x96, 0x2f, 0x0b, 0xbf, 0xc5, 0x8b, 0xce, 0xd0, 0x58, 0xbf, 0xfd, 0x9e,
+ 0xf3, 0x11, 0xad, 0xe2, 0x60, 0x2c, 0x54, 0xa3, 0x35, 0xd1, 0xbe, 0x44,
+ 0x43, 0x97, 0xf8, 0xb3, 0xfe, 0x29, 0x02, 0xc5, 0xff, 0xe8, 0x39, 0x67,
+ 0xa4, 0x21, 0xe9, 0xa0, 0xb1, 0x7f, 0xff, 0x3c, 0x5c, 0xe0, 0x9b, 0x42,
+ 0xda, 0x4d, 0x0c, 0xbc, 0xb1, 0x7f, 0xe2, 0xcd, 0xa7, 0xa8, 0x42, 0x4e,
+ 0xb1, 0x7f, 0xfe, 0x14, 0xe6, 0xda, 0x97, 0x84, 0x9a, 0x16, 0x7d, 0x62,
+ 0x89, 0x12, 0xfe, 0x40, 0xac, 0x4d, 0x8f, 0xe9, 0x41, 0xc3, 0xde, 0xf1,
+ 0x4c, 0x16, 0x2f, 0xb5, 0xa7, 0x3a, 0xc5, 0xb8, 0x33, 0x7e, 0xe3, 0x95,
+ 0x04, 0x4d, 0xf9, 0xd6, 0xfb, 0x86, 0xff, 0xb2, 0xc5, 0xdb, 0x0d, 0x62,
+ 0xff, 0xfd, 0xe9, 0xcd, 0x9b, 0xdb, 0xfd, 0xb4, 0x13, 0x74, 0xb1, 0x46,
+ 0x22, 0x64, 0xe4, 0xfc, 0x19, 0xad, 0x95, 0x8e, 0x94, 0xa3, 0x0f, 0x42,
+ 0xf2, 0xfd, 0xac, 0xde, 0x7e, 0xb1, 0x7f, 0xe2, 0xdf, 0xde, 0xc2, 0x29,
+ 0x8f, 0x58, 0xbf, 0xfd, 0xf7, 0xd6, 0x9f, 0x6e, 0x61, 0xe6, 0x3d, 0x62,
+ 0xa5, 0x11, 0xfb, 0xa0, 0xde, 0x30, 0xd8, 0xe5, 0x8b, 0xde, 0x61, 0xac,
+ 0x5c, 0xd1, 0xeb, 0x15, 0xa3, 0xda, 0xe1, 0x1f, 0x61, 0xdb, 0xf7, 0xe4,
+ 0xb2, 0x25, 0x8b, 0xfb, 0xd8, 0x44, 0xde, 0x58, 0xad, 0xcf, 0x53, 0xb8,
+ 0xa2, 0xf4, 0x1f, 0xb9, 0x62, 0xa4, 0xf1, 0xa2, 0x26, 0xbf, 0xc6, 0xf5,
+ 0xed, 0x4e, 0x74, 0xb1, 0x7c, 0x07, 0xd1, 0xa9, 0x17, 0xfa, 0x5b, 0x5f,
+ 0x09, 0x86, 0xb1, 0x7d, 0xad, 0x3e, 0xcb, 0x16, 0xde, 0x4f, 0xf0, 0x64,
+ 0x8c, 0x69, 0x7e, 0xd7, 0xf0, 0xe2, 0x58, 0xbf, 0x66, 0xb3, 0x22, 0x58,
+ 0xa7, 0x3d, 0x10, 0xca, 0x6f, 0xcd, 0xf3, 0x07, 0x2b, 0x15, 0x06, 0x41,
+ 0xb8, 0xe1, 0xfb, 0x92, 0xd5, 0xcd, 0x3e, 0xea, 0x17, 0x0e, 0xfb, 0xa8,
+ 0x65, 0xb1, 0x11, 0x42, 0xcf, 0x90, 0x85, 0xf1, 0x15, 0xf9, 0xb5, 0xac,
+ 0xe9, 0x62, 0xff, 0xf7, 0xbe, 0xec, 0x0c, 0xd0, 0xe4, 0xa0, 0xb1, 0x7f,
+ 0xfb, 0xa3, 0x3a, 0x04, 0x96, 0xed, 0xb1, 0x32, 0xc5, 0x4a, 0x30, 0x30,
+ 0xa4, 0x92, 0x6f, 0xd3, 0xc0, 0xca, 0x0b, 0x17, 0xb7, 0x78, 0x2c, 0x5f,
+ 0xe9, 0xf3, 0x6b, 0x59, 0xd2, 0xc5, 0x18, 0x7a, 0x5f, 0x1e, 0xbf, 0xf6,
+ 0xf9, 0xac, 0x7e, 0x7e, 0x7b, 0x2c, 0x5f, 0xf9, 0xba, 0x61, 0xb7, 0x5a,
+ 0x73, 0x56, 0x2f, 0xd3, 0xdd, 0xb6, 0x04, 0xb1, 0x7f, 0xf3, 0x67, 0x5e,
+ 0xc2, 0x14, 0x33, 0x8b, 0x17, 0xff, 0xff, 0x33, 0xf9, 0xff, 0xbb, 0x99,
+ 0x07, 0xfb, 0x17, 0xa1, 0x9a, 0xc5, 0x8b, 0xb3, 0xeb, 0x17, 0x67, 0x72,
+ 0xc5, 0x44, 0x6c, 0x7e, 0x2f, 0x5f, 0x46, 0x23, 0x42, 0x8a, 0xfc, 0xe0,
+ 0x62, 0x02, 0xc5, 0xfe, 0x9e, 0xb9, 0x3e, 0x91, 0xac, 0x50, 0x0f, 0x6c,
+ 0x89, 0xef, 0xd9, 0xcc, 0xeb, 0xcb, 0x17, 0xff, 0xdf, 0xc7, 0xd4, 0x3e,
+ 0xe2, 0xdf, 0xf8, 0x05, 0x8b, 0xdc, 0x0f, 0x86, 0x26, 0x3b, 0x90, 0x82,
+ 0x62, 0x1f, 0x14, 0xd0, 0xd5, 0xa6, 0x74, 0x46, 0x74, 0x1f, 0xa0, 0x91,
+ 0x6f, 0xa5, 0x12, 0xdd, 0xc8, 0x2c, 0x5e, 0xd8, 0x5c, 0x58, 0xba, 0x62,
+ 0x58, 0xbf, 0xce, 0x4d, 0xef, 0xe1, 0xd6, 0x29, 0x8f, 0xa4, 0x87, 0xfc,
+ 0x31, 0x7f, 0x41, 0xfc, 0xe5, 0x05, 0x8b, 0xfb, 0x8e, 0xfb, 0x3f, 0xd6,
+ 0x2d, 0xa9, 0x3d, 0xb8, 0x16, 0xdf, 0xa2, 0x29, 0xf7, 0x16, 0x2f, 0xff,
+ 0xff, 0xfa, 0x79, 0x3e, 0xdb, 0x02, 0xd6, 0x7d, 0x83, 0xe6, 0x1a, 0xc4,
+ 0x09, 0x29, 0x8b, 0xf2, 0xb1, 0x7c, 0x26, 0xcd, 0x96, 0x2f, 0x1f, 0x36,
+ 0x58, 0xbd, 0x07, 0xec, 0x47, 0x82, 0x19, 0x1d, 0xfb, 0x9f, 0x6d, 0xe5,
+ 0x62, 0xfc, 0xdb, 0x04, 0xd0, 0x58, 0xa9, 0x4e, 0xbb, 0x62, 0x72, 0x29,
+ 0xf4, 0x35, 0x82, 0x35, 0x0c, 0xa6, 0xfe, 0xeb, 0x98, 0x77, 0xfa, 0xc5,
+ 0xff, 0x73, 0xf2, 0xda, 0xd6, 0x74, 0xb1, 0x7d, 0x27, 0x6f, 0xac, 0x5f,
+ 0xff, 0xe8, 0x7b, 0x0b, 0xdc, 0x33, 0x9c, 0xcd, 0x61, 0x34, 0x16, 0x2c,
+ 0x69, 0x88, 0x83, 0xe8, 0x8a, 0xb1, 0x1d, 0x2f, 0x0b, 0xdb, 0xe0, 0x7b,
+ 0x36, 0x58, 0xb1, 0xd6, 0x2a, 0x4d, 0xb1, 0xc9, 0x2f, 0xff, 0xf0, 0x04,
+ 0xc5, 0xb8, 0x53, 0xa2, 0xce, 0xa1, 0xe9, 0xe9, 0x62, 0xff, 0xe8, 0xc1,
+ 0x94, 0x8b, 0x7c, 0x35, 0xf4, 0xb1, 0x7b, 0x4d, 0xc5, 0x8b, 0xb0, 0x25,
+ 0x8a, 0x93, 0xfe, 0x1a, 0x4f, 0x07, 0x6f, 0xa5, 0xb5, 0xc5, 0x8b, 0xde,
+ 0xfc, 0xac, 0x5f, 0x67, 0xbe, 0xeb, 0x15, 0x88, 0x8f, 0xf9, 0x73, 0x11,
+ 0x10, 0xed, 0xff, 0xf6, 0x11, 0xa6, 0x07, 0xe7, 0xfb, 0x9b, 0xf7, 0x58,
+ 0xb7, 0xd6, 0x29, 0x62, 0xe9, 0x26, 0x2f, 0xb8, 0x25, 0x58, 0x89, 0xaf,
+ 0xb8, 0xdf, 0xc5, 0x31, 0x66, 0x6e, 0xb1, 0x7f, 0x6d, 0xf6, 0xf6, 0xa5,
+ 0x62, 0xfb, 0x3d, 0x3f, 0x58, 0xbd, 0x0c, 0xe2, 0xc5, 0xe9, 0xeb, 0x8b,
+ 0x17, 0xf8, 0x7f, 0x98, 0x99, 0xba, 0x58, 0xbc, 0xfe, 0xe2, 0xc5, 0xf7,
+ 0x04, 0x50, 0x58, 0xbf, 0x13, 0x7a, 0x12, 0xb1, 0x7f, 0x8f, 0xd4, 0x3d,
+ 0x91, 0x71, 0x62, 0xb7, 0x44, 0xf7, 0x43, 0xbc, 0x23, 0x0c, 0x9e, 0xf7,
+ 0xc1, 0xd9, 0x62, 0xb6, 0x4d, 0xb8, 0x63, 0xba, 0x1e, 0x28, 0x69, 0xf7,
+ 0x20, 0x5e, 0xe9, 0xa3, 0xd6, 0x2f, 0xf7, 0xbe, 0xc7, 0xd6, 0x6c, 0xb1,
+ 0x5f, 0x3d, 0x60, 0x10, 0xde, 0x8e, 0x73, 0x56, 0x2f, 0xef, 0x4f, 0x62,
+ 0x6e, 0x96, 0x29, 0x62, 0xa4, 0xf7, 0x7a, 0x21, 0x8e, 0x30, 0xa8, 0x2e,
+ 0x1e, 0x8e, 0x1a, 0x8e, 0x45, 0xa2, 0xef, 0x97, 0xb4, 0x72, 0x05, 0x0a,
+ 0x9f, 0x3f, 0xde, 0x89, 0x80, 0xb1, 0x7e, 0x11, 0x0d, 0xb6, 0x58, 0xbf,
+ 0xfe, 0xfb, 0xb0, 0x30, 0xa7, 0xae, 0x67, 0x5e, 0x58, 0xb1, 0xb8, 0x89,
+ 0x73, 0x8f, 0x78, 0xa6, 0xff, 0xda, 0x01, 0xdf, 0x81, 0xf2, 0x71, 0x62,
+ 0xfb, 0xbb, 0xf9, 0xd9, 0x62, 0xb0, 0xfa, 0x19, 0x02, 0xf4, 0xf5, 0x1e,
+ 0xb1, 0x7d, 0xc2, 0x73, 0x56, 0x2b, 0x47, 0x89, 0xe2, 0x1b, 0xec, 0x1b,
+ 0x41, 0x62, 0x86, 0x78, 0x86, 0x91, 0x5f, 0xcd, 0x0f, 0x72, 0x4d, 0x58,
+ 0xbf, 0x4b, 0xb7, 0xb8, 0xb1, 0x7d, 0x07, 0xea, 0x0b, 0x17, 0x4e, 0xbe,
+ 0x79, 0x6c, 0x4f, 0x63, 0x7e, 0x8a, 0x60, 0x9e, 0xaf, 0xff, 0x11, 0x8f,
+ 0x23, 0xfe, 0x1f, 0xf9, 0xc5, 0x8b, 0xe3, 0x94, 0xc4, 0xb1, 0x7f, 0xfd,
+ 0xf7, 0x83, 0xe9, 0x81, 0xe2, 0x93, 0xf1, 0x62, 0xf4, 0xe8, 0x12, 0x7e,
+ 0x5b, 0x91, 0xd6, 0x23, 0xbf, 0xd0, 0xbc, 0xba, 0x3f, 0x8b, 0x17, 0xfd,
+ 0xcd, 0xfe, 0xc3, 0x8d, 0xfb, 0xd8, 0xd9, 0x62, 0x8d, 0x44, 0x6b, 0x13,
+ 0xf8, 0x6e, 0xa5, 0x5f, 0x34, 0x21, 0x3d, 0x90, 0xa8, 0x78, 0x64, 0xb4,
+ 0x74, 0xf7, 0x10, 0x16, 0x2f, 0xee, 0xa1, 0x87, 0x9d, 0xd6, 0x2f, 0xd1,
+ 0x48, 0xda, 0x25, 0x8b, 0xf9, 0xfc, 0x0c, 0x87, 0x16, 0x2f, 0xf4, 0x03,
+ 0xe0, 0x3f, 0x20, 0x58, 0xbf, 0x3f, 0x03, 0xe8, 0x0b, 0x17, 0xe2, 0xcf,
+ 0x49, 0xd6, 0x2f, 0xcc, 0xfe, 0x92, 0x58, 0xbe, 0xe7, 0xf3, 0x8b, 0x16,
+ 0x98, 0x22, 0x6d, 0xca, 0xfe, 0x4e, 0x22, 0x6b, 0xb3, 0xb2, 0xc5, 0xff,
+ 0x14, 0xf9, 0xf4, 0xfe, 0x12, 0xc5, 0x6e, 0x7a, 0x2e, 0x33, 0x7f, 0x9f,
+ 0xcf, 0xa6, 0xda, 0x56, 0x2a, 0x4f, 0x55, 0x88, 0xaf, 0x33, 0x74, 0xb1,
+ 0x46, 0x2a, 0x4d, 0x81, 0x57, 0x45, 0xda, 0x86, 0x8f, 0xe1, 0xcf, 0xd8,
+ 0x82, 0xbb, 0xc5, 0x5f, 0x72, 0x2e, 0xf2, 0x9f, 0x6f, 0x1c, 0x5c, 0x58,
+ 0xbe, 0x73, 0xe1, 0x2c, 0x5a, 0x58, 0xdf, 0xf8, 0x7a, 0xff, 0x3f, 0x83,
+ 0xd4, 0xfe, 0x56, 0x2f, 0xd2, 0x19, 0x34, 0x16, 0x2f, 0xff, 0x69, 0x8b,
+ 0xd8, 0x08, 0xe9, 0x18, 0xe5, 0x62, 0xff, 0xe2, 0x90, 0x0c, 0x53, 0xb4,
+ 0xf5, 0x05, 0x8b, 0xfa, 0x1a, 0x98, 0x36, 0x96, 0x2f, 0xde, 0xe7, 0x7a,
+ 0x6f, 0x96, 0x2c, 0x75, 0x8a, 0x93, 0xc2, 0xc3, 0x0b, 0xde, 0x90, 0x96,
+ 0x2f, 0x7c, 0x3d, 0x2c, 0x54, 0x0d, 0xef, 0x87, 0xaf, 0x7b, 0x06, 0xb1,
+ 0x7f, 0xc2, 0xd1, 0xac, 0xfc, 0x7e, 0xcb, 0x17, 0xed, 0x00, 0xef, 0xc5,
+ 0x8b, 0x80, 0x64, 0x71, 0xf2, 0x86, 0x79, 0x6c, 0xe9, 0x16, 0xa5, 0x08,
+ 0x2b, 0xe6, 0xdc, 0xb1, 0x62, 0xe9, 0xe9, 0x62, 0xf1, 0xe7, 0x75, 0x8b,
+ 0xf7, 0xdf, 0x3a, 0xf2, 0xc5, 0xff, 0xff, 0xfe, 0x6e, 0x7d, 0xa1, 0xbf,
+ 0xdf, 0xc2, 0x01, 0xda, 0x19, 0xd9, 0xfc, 0xff, 0xdd, 0xa0, 0xb1, 0x5b,
+ 0x23, 0xc7, 0x06, 0x1c, 0x78, 0x8a, 0x68, 0x6a, 0xab, 0xba, 0x5d, 0x3c,
+ 0x35, 0x88, 0xb7, 0xd1, 0x89, 0xd2, 0xc5, 0xee, 0xd9, 0xa5, 0x8b, 0xde,
+ 0xc0, 0x2c, 0x5f, 0xdc, 0x98, 0xa0, 0x21, 0xac, 0x56, 0x1f, 0x60, 0x07,
+ 0xc3, 0x1d, 0xbe, 0xe7, 0x1f, 0xb2, 0xc5, 0xff, 0xfb, 0x08, 0xd6, 0xe7,
+ 0xd9, 0xc0, 0x79, 0xea, 0x0b, 0x15, 0x27, 0xf7, 0xb9, 0x2d, 0xf8, 0x5d,
+ 0xfe, 0x9f, 0x8b, 0x17, 0xff, 0xfe, 0x11, 0xbd, 0x78, 0x4c, 0x18, 0x7a,
+ 0xe0, 0x9b, 0x42, 0xda, 0x4d, 0x58, 0xbc, 0xf1, 0x73, 0x11, 0x47, 0xa2,
+ 0xeb, 0xff, 0xec, 0xd4, 0x5f, 0x72, 0x09, 0xbe, 0x19, 0x79, 0x62, 0xe0,
+ 0xf3, 0xe8, 0x86, 0xe1, 0xa5, 0xff, 0xbe, 0xfd, 0x73, 0x08, 0xdc, 0x25,
+ 0x8b, 0xff, 0xf9, 0xe2, 0xe7, 0x04, 0xda, 0x16, 0xd2, 0x68, 0x65, 0xe5,
+ 0x8b, 0x73, 0x11, 0x9d, 0xb9, 0x7f, 0xcf, 0xef, 0x8e, 0x45, 0x2b, 0x17,
+ 0xfc, 0xe3, 0xfc, 0xc3, 0x3a, 0xf2, 0xc5, 0xfa, 0x78, 0xe0, 0xe9, 0x62,
+ 0xe6, 0xec, 0xb1, 0x76, 0xf3, 0xd8, 0xf0, 0x83, 0x29, 0xb1, 0xb2, 0x8c,
+ 0xe1, 0x90, 0xe3, 0xe5, 0x62, 0x67, 0x2d, 0x18, 0x25, 0xfb, 0xcd, 0xe1,
+ 0x4a, 0xc5, 0xfd, 0xf9, 0x17, 0x7e, 0x60, 0xd6, 0x2f, 0xff, 0xef, 0xbf,
+ 0xbe, 0xd0, 0x0c, 0x6d, 0xb0, 0xfe, 0xe7, 0x58, 0xbf, 0xf3, 0xfa, 0x18,
+ 0x0e, 0x16, 0x01, 0x62, 0xa0, 0xc9, 0xf8, 0x19, 0xa6, 0x14, 0x1a, 0x99,
+ 0xd2, 0x33, 0xcb, 0x1e, 0x89, 0x5f, 0x4f, 0x1f, 0x85, 0x51, 0x4b, 0x52,
+ 0xe1, 0x47, 0x8a, 0x04, 0x6b, 0xd9, 0x7a, 0xf0, 0x27, 0xa5, 0x8b, 0xa7,
+ 0xa5, 0x8a, 0x73, 0x6c, 0x01, 0xeb, 0xd1, 0xdd, 0x4a, 0xc5, 0xfe, 0xf9,
+ 0x4f, 0x4f, 0x3f, 0x58, 0xbf, 0x9b, 0xc0, 0x0c, 0xa0, 0xb1, 0x5b, 0x9f,
+ 0x17, 0xcc, 0xef, 0xdb, 0xfe, 0x5e, 0x3d, 0x62, 0xa3, 0x77, 0x5c, 0x01,
+ 0x34, 0x8e, 0xd8, 0x46, 0xf4, 0x32, 0xdc, 0x97, 0x8e, 0x6b, 0x07, 0x50,
+ 0x81, 0x79, 0x46, 0xd1, 0xeb, 0xda, 0x8c, 0x60, 0xeb, 0x9f, 0x20, 0x69,
+ 0xda, 0xe2, 0x9c, 0xfe, 0xe4, 0xb5, 0x8f, 0x3d, 0x8a, 0x94, 0x3b, 0xda,
+ 0x30, 0xe8, 0xe2, 0x00, 0xe1, 0x07, 0xdc, 0x47, 0x7f, 0xe6, 0x71, 0x8b,
+ 0xdc, 0xdb, 0x02, 0x58, 0xbb, 0xbc, 0x25, 0x8b, 0xf7, 0x30, 0xd9, 0xe2,
+ 0xc5, 0xfa, 0x3b, 0x09, 0x8d, 0x58, 0xbf, 0x74, 0x76, 0x20, 0x2c, 0x5b,
+ 0x4b, 0x16, 0x82, 0xc5, 0x9b, 0xe6, 0x91, 0x84, 0xaf, 0xfb, 0x86, 0x0a,
+ 0x26, 0xee, 0x11, 0xab, 0x17, 0xff, 0x9a, 0x3f, 0x7f, 0xb9, 0x0b, 0xd0,
+ 0x70, 0x2c, 0x5f, 0xfe, 0xe7, 0x85, 0xb1, 0x82, 0x61, 0xfd, 0xa2, 0x58,
+ 0xa3, 0x13, 0x7b, 0x92, 0xbd, 0x26, 0xb1, 0x29, 0x20, 0x89, 0x3a, 0xfd,
+ 0xc7, 0x2e, 0xa0, 0xb1, 0x7e, 0x97, 0xfc, 0xe9, 0x62, 0xa3, 0xcf, 0x42,
+ 0x22, 0x9b, 0xfb, 0x22, 0x66, 0x2d, 0x96, 0x2f, 0x9b, 0x8f, 0xa5, 0x8a,
+ 0x30, 0xf4, 0x3e, 0x5d, 0x7e, 0x01, 0x98, 0xd1, 0xeb, 0x17, 0xff, 0x17,
+ 0xdb, 0x85, 0x86, 0x9b, 0x91, 0xeb, 0x17, 0xfd, 0xa8, 0xe7, 0xfe, 0x37,
+ 0x40, 0x58, 0xa9, 0x45, 0x8e, 0x16, 0x32, 0x45, 0xfe, 0x9d, 0x6a, 0x60,
+ 0xdf, 0x58, 0xbf, 0x06, 0x5f, 0xce, 0x96, 0x2b, 0x73, 0xdd, 0x01, 0x9d,
+ 0xff, 0xf9, 0xfd, 0x27, 0xce, 0xbd, 0x27, 0x0f, 0x4c, 0x05, 0x8b, 0xc4,
+ 0xc3, 0x58, 0xbf, 0xfa, 0x45, 0xbe, 0x75, 0xe8, 0xc0, 0x82, 0x09, 0x62,
+ 0x9c, 0xfa, 0x88, 0x72, 0xff, 0x7e, 0x7a, 0xee, 0x97, 0x8e, 0x58, 0xbf,
+ 0xdf, 0xcd, 0xbf, 0x22, 0x0d, 0x62, 0xff, 0xa4, 0x65, 0x9e, 0xe1, 0xe5,
+ 0x62, 0xff, 0xec, 0xf7, 0xf2, 0x05, 0x80, 0x17, 0x16, 0x2f, 0xcf, 0xa7,
+ 0xf0, 0x96, 0x2b, 0xe7, 0xd9, 0xe4, 0x4b, 0xff, 0xf7, 0x30, 0x5d, 0xfe,
+ 0x05, 0x8f, 0xdb, 0x21, 0x24, 0xb1, 0x52, 0x7f, 0xbe, 0x22, 0xbf, 0xee,
+ 0x4e, 0xbd, 0x31, 0x83, 0x75, 0x8b, 0xa5, 0xd6, 0x2f, 0xd3, 0xad, 0xa7,
+ 0x75, 0x8a, 0x82, 0xb0, 0xf1, 0xc3, 0x06, 0x3c, 0x83, 0x47, 0x47, 0x36,
+ 0x28, 0xc8, 0x78, 0x43, 0xd8, 0xf2, 0x38, 0x5a, 0xf7, 0xff, 0x2b, 0x17,
+ 0x7e, 0x56, 0x2b, 0x0d, 0xa3, 0x0e, 0xdf, 0xff, 0xd9, 0xf3, 0x30, 0xef,
+ 0xf9, 0x33, 0x9c, 0xc2, 0x02, 0xc5, 0xff, 0xcf, 0xa9, 0x87, 0xe6, 0x22,
+ 0x11, 0xab, 0x15, 0xf4, 0x51, 0x71, 0x72, 0xff, 0xdb, 0x4c, 0x45, 0x3c,
+ 0xc9, 0x82, 0xc5, 0xd3, 0x12, 0xc5, 0xa3, 0x96, 0x28, 0xc3, 0x5b, 0xb8,
+ 0xc5, 0xfc, 0x6f, 0xa7, 0xf3, 0xc5, 0x8b, 0xfe, 0xe1, 0x67, 0xb9, 0x3a,
+ 0xd9, 0x62, 0xff, 0x4e, 0x7c, 0x39, 0xd6, 0xcb, 0x17, 0xf8, 0x7d, 0xdc,
+ 0x98, 0x85, 0xa5, 0x8b, 0x1d, 0x62, 0xfb, 0xaf, 0x67, 0x16, 0x2f, 0xdf,
+ 0x90, 0xcb, 0x65, 0x8a, 0x81, 0xe7, 0x44, 0x49, 0x7e, 0xfc, 0xee, 0x4c,
+ 0xb1, 0x7e, 0x7e, 0xb8, 0xdd, 0x2c, 0x5f, 0xff, 0xb3, 0xdc, 0x93, 0xf5,
+ 0xc7, 0x1f, 0xf1, 0xcd, 0x58, 0xbe, 0xe3, 0xeb, 0x65, 0x8a, 0x31, 0x35,
+ 0x09, 0x60, 0x72, 0x3f, 0x94, 0x11, 0x57, 0x15, 0xef, 0xf6, 0x0f, 0x35,
+ 0x09, 0xd2, 0xc5, 0xef, 0xbf, 0x96, 0x2a, 0x55, 0xae, 0x41, 0xb1, 0xc8,
+ 0xe2, 0x2f, 0xd1, 0xd3, 0x1a, 0x82, 0x38, 0x9e, 0x2b, 0x06, 0x67, 0x7e,
+ 0x6f, 0xe7, 0x5e, 0x58, 0xbf, 0xf6, 0x61, 0x1a, 0x59, 0xa0, 0xfc, 0xb1,
+ 0x7f, 0xe6, 0xf7, 0x27, 0x08, 0x7f, 0x95, 0x8b, 0xed, 0xff, 0x22, 0x58,
+ 0xaf, 0x9f, 0x0f, 0x8f, 0x6f, 0xfc, 0xc5, 0xb0, 0x58, 0x43, 0xfc, 0xac,
+ 0x5c, 0xfb, 0x2c, 0x56, 0x1e, 0xb9, 0x1f, 0xdf, 0xe9, 0xf7, 0x03, 0x29,
+ 0xdd, 0x62, 0xfe, 0xea, 0x1c, 0x0e, 0x63, 0xd6, 0x2b, 0x47, 0xd2, 0x23,
+ 0x5b, 0xfe, 0x09, 0x8b, 0x6e, 0x3f, 0x5e, 0x58, 0xbd, 0xbc, 0xc7, 0xac,
+ 0x5f, 0xe8, 0xbe, 0xda, 0xd3, 0x8d, 0x62, 0xb0, 0xf5, 0x98, 0x86, 0xff,
+ 0x37, 0x41, 0xe9, 0xcf, 0x8b, 0x17, 0xf3, 0x16, 0xc7, 0x6f, 0x2c, 0x51,
+ 0x1f, 0x1f, 0x0d, 0x6f, 0xec, 0x27, 0x1e, 0x12, 0xc5, 0xef, 0xb1, 0xd6,
+ 0x2f, 0xff, 0x67, 0xb8, 0xc7, 0xd6, 0x3f, 0xe4, 0x6b, 0x15, 0x04, 0x48,
+ 0xb9, 0x59, 0x0e, 0xdf, 0x83, 0xd6, 0x76, 0xc5, 0x8b, 0x1d, 0x62, 0xc3,
+ 0xf9, 0xbd, 0x22, 0xbb, 0xfc, 0x59, 0xb7, 0xbd, 0x27, 0x58, 0xa9, 0x3d,
+ 0xa2, 0x26, 0xa8, 0x2e, 0x4c, 0x8c, 0xa7, 0x21, 0x41, 0x13, 0xce, 0xa1,
+ 0x13, 0xf2, 0x22, 0x84, 0x97, 0x21, 0x07, 0xe8, 0x59, 0x07, 0x0c, 0x5b,
+ 0xfa, 0x28, 0x3e, 0xa1, 0x1a, 0x2c, 0x5d, 0x1b, 0x77, 0xab, 0x17, 0xb8,
+ 0xe1, 0x2c, 0x5f, 0xe3, 0x58, 0x39, 0x00, 0x67, 0x58, 0xbf, 0xd0, 0x7d,
+ 0x43, 0x3e, 0xcb, 0x17, 0xd9, 0x13, 0x79, 0x62, 0xfe, 0xf7, 0x22, 0x83,
+ 0x12, 0xc5, 0xf9, 0xba, 0xcf, 0xb2, 0xc5, 0x49, 0xeb, 0x88, 0xbe, 0xda,
+ 0x31, 0x37, 0xae, 0xfa, 0x9a, 0xe1, 0x11, 0xa3, 0xd1, 0x1b, 0xfc, 0xcc,
+ 0x9e, 0xaf, 0xf6, 0xff, 0x7f, 0x1b, 0x24, 0xb1, 0x76, 0x74, 0xb1, 0x7a,
+ 0x75, 0xc5, 0x8a, 0x93, 0x6a, 0x71, 0x8b, 0xfd, 0x07, 0x26, 0x37, 0xee,
+ 0xb1, 0x7f, 0xfa, 0x47, 0xf1, 0x1a, 0x1c, 0x8f, 0xe2, 0xe2, 0xc5, 0xa3,
+ 0xcc, 0x4c, 0x2c, 0x6d, 0x5d, 0x10, 0x06, 0x67, 0x76, 0x6c, 0xb1, 0x52,
+ 0x7c, 0x58, 0x95, 0x7f, 0x6d, 0xc9, 0x88, 0x5a, 0x58, 0xbf, 0xa7, 0xbb,
+ 0x7f, 0xce, 0xcb, 0x17, 0xbc, 0xdc, 0x58, 0xbf, 0xe1, 0x40, 0x1f, 0x97,
+ 0x2d, 0x96, 0x2b, 0x11, 0x76, 0x69, 0x8b, 0x99, 0x90, 0xed, 0xdd, 0xf1,
+ 0x96, 0x2f, 0xff, 0xfe, 0x2d, 0xf0, 0xa4, 0x2f, 0x1a, 0xdc, 0x1c, 0xb6,
+ 0xbe, 0x13, 0x0d, 0x62, 0xe6, 0xe9, 0x62, 0xde, 0x94, 0x46, 0x71, 0xd2,
+ 0xfb, 0x0f, 0x31, 0xeb, 0x17, 0xec, 0xe4, 0x94, 0xac, 0x5f, 0xf0, 0x62,
+ 0x60, 0xe2, 0x30, 0x1e, 0x58, 0xbe, 0x61, 0x88, 0xd7, 0x3e, 0x51, 0x13,
+ 0x54, 0xa7, 0x28, 0xf0, 0xa9, 0xe1, 0x40, 0xa1, 0x15, 0x73, 0xe9, 0x62,
+ 0xfa, 0x02, 0x0b, 0x16, 0x2f, 0x30, 0xa2, 0x58, 0xbf, 0x48, 0xb7, 0x11,
+ 0xd6, 0x28, 0x68, 0x83, 0xe8, 0x5c, 0x89, 0x03, 0x1e, 0xbb, 0x04, 0xb1,
+ 0x73, 0x92, 0xc5, 0xf4, 0x24, 0xb7, 0x58, 0xa1, 0x9b, 0x9c, 0x16, 0xbf,
+ 0xf3, 0xfc, 0x85, 0x17, 0xe7, 0xb6, 0x2c, 0x5a, 0x25, 0x8b, 0xee, 0xf5,
+ 0xa7, 0xa5, 0x8b, 0x49, 0x1b, 0xbf, 0x09, 0xd1, 0x88, 0xc1, 0x92, 0x07,
+ 0x7c, 0xbe, 0x90, 0x61, 0x2c, 0x5f, 0x17, 0x3c, 0xeb, 0x15, 0x06, 0xea,
+ 0xbc, 0x71, 0xd2, 0x64, 0x29, 0x8d, 0x76, 0xde, 0x1a, 0x9d, 0x42, 0x29,
+ 0xe5, 0x99, 0x47, 0xc3, 0x1a, 0x28, 0x60, 0xea, 0x5b, 0xf9, 0xe7, 0x47,
+ 0x9a, 0x51, 0x30, 0x23, 0xe1, 0x28, 0x6d, 0xf2, 0x3c, 0xf1, 0x43, 0x27,
+ 0xb1, 0xf0, 0x51, 0x88, 0xc7, 0x17, 0x86, 0x43, 0x7c, 0x78, 0xd5, 0xdf,
+ 0x23, 0x45, 0x8b, 0xbd, 0xc5, 0x8a, 0x73, 0xcd, 0x88, 0xd6, 0xf8, 0x39,
+ 0x0b, 0x8b, 0x17, 0x03, 0xcb, 0x17, 0xf6, 0x87, 0xfc, 0xd6, 0xcb, 0x16,
+ 0x12, 0xc5, 0xc0, 0xfa, 0xc5, 0xf6, 0xb5, 0x9c, 0x58, 0xbb, 0x22, 0x58,
+ 0xb4, 0x0c, 0x46, 0x96, 0xc4, 0xb8, 0x31, 0xb9, 0x81, 0xc4, 0x98, 0x60,
+ 0x32, 0x3b, 0xfe, 0xe0, 0xb4, 0x07, 0x1f, 0xe5, 0x62, 0xfb, 0xcc, 0x58,
+ 0xb1, 0x7d, 0xdd, 0x25, 0x05, 0x8a, 0x73, 0xc6, 0x0c, 0x86, 0xf8, 0x9b,
+ 0xdc, 0x58, 0xbd, 0xa6, 0xec, 0xb1, 0x7f, 0xd9, 0xdc, 0xce, 0x31, 0x7b,
+ 0x8b, 0x17, 0xed, 0x0f, 0x30, 0x96, 0x2f, 0x8d, 0xd3, 0x04, 0xb1, 0x7f,
+ 0xe7, 0xcf, 0xcf, 0x6e, 0x7e, 0x7a, 0x58, 0xac, 0x3e, 0x68, 0xf2, 0x5b,
+ 0xfb, 0xad, 0x0b, 0xaf, 0x41, 0x62, 0xfe, 0x0b, 0x08, 0x7f, 0x95, 0x8b,
+ 0xfd, 0xc1, 0x94, 0x84, 0x3c, 0x58, 0xb3, 0x74, 0x7c, 0x5f, 0x2e, 0xba,
+ 0x76, 0x58, 0xac, 0x54, 0x05, 0x11, 0x16, 0x87, 0xd8, 0xf3, 0x90, 0x8d,
+ 0x11, 0x20, 0x50, 0x94, 0x0c, 0xa2, 0xff, 0xb7, 0xeb, 0x8f, 0x11, 0x48,
+ 0xd6, 0x2f, 0xbd, 0xec, 0xd9, 0x62, 0x88, 0xf8, 0x02, 0x3c, 0xbf, 0x9a,
+ 0x41, 0x9d, 0x41, 0x62, 0x96, 0x2f, 0xf1, 0x6b, 0x39, 0x8f, 0xf5, 0x8b,
+ 0xf0, 0xa2, 0x3f, 0x37, 0x58, 0xbf, 0xef, 0xbc, 0x05, 0xad, 0x4f, 0x4b,
+ 0x17, 0xd1, 0xcd, 0xaf, 0x2c, 0x57, 0x7a, 0x8c, 0xbc, 0x0c, 0xf9, 0x93,
+ 0x16, 0x06, 0x77, 0x6e, 0xe5, 0x8b, 0xff, 0xb0, 0x8b, 0x3f, 0x83, 0xf8,
+ 0xa2, 0x58, 0xbe, 0x6f, 0x7e, 0x56, 0x2f, 0xfe, 0x89, 0xbe, 0xfa, 0x6f,
+ 0x7b, 0x36, 0x58, 0xbf, 0xf6, 0x37, 0x8b, 0x3d, 0xec, 0x09, 0x62, 0x9d,
+ 0x10, 0x84, 0x8d, 0x68, 0x6c, 0x99, 0x03, 0x8a, 0xfd, 0x13, 0xd0, 0xa6,
+ 0xbf, 0xff, 0xc5, 0xee, 0x0a, 0x4c, 0xfb, 0x98, 0xe6, 0x9b, 0x9e, 0xe2,
+ 0xc5, 0xf9, 0xfd, 0xfc, 0x82, 0xc5, 0x4a, 0x23, 0x74, 0xcb, 0x7b, 0x3a,
+ 0x82, 0xc5, 0x2c, 0x7c, 0xbe, 0xbf, 0xb3, 0x91, 0xbc, 0x6f, 0x1b, 0xf7,
+ 0x8b, 0x17, 0x4f, 0x65, 0x8b, 0xfd, 0x3b, 0x16, 0x6e, 0xc4, 0xb1, 0x5f,
+ 0x3c, 0xce, 0x0c, 0xd6, 0x93, 0x0c, 0xfa, 0x01, 0x0d, 0xfa, 0x11, 0xf6,
+ 0xee, 0x58, 0xb7, 0x4b, 0x14, 0xc6, 0xa0, 0x31, 0x5b, 0xff, 0xa4, 0x79,
+ 0xb9, 0x67, 0xbe, 0xfd, 0x2c, 0x5f, 0xef, 0x66, 0xb6, 0x9f, 0x71, 0x62,
+ 0xa0, 0x89, 0xbf, 0x90, 0xb2, 0x2d, 0xff, 0xf6, 0x0d, 0xfd, 0x87, 0xfc,
+ 0xce, 0xe7, 0x65, 0x8b, 0xb3, 0xb2, 0xc5, 0xff, 0x6f, 0xfc, 0x19, 0xdf,
+ 0x58, 0xb1, 0x7e, 0xe7, 0xe4, 0x8d, 0x58, 0xbe, 0xf6, 0x9f, 0x65, 0x8a,
+ 0x93, 0xcd, 0x11, 0x4d, 0x4a, 0x62, 0x1b, 0x27, 0xe0, 0xce, 0xa1, 0x0f,
+ 0x7f, 0xff, 0xe8, 0xec, 0xd6, 0x7f, 0x24, 0xbd, 0xfc, 0x6f, 0xb7, 0xb9,
+ 0x8b, 0x17, 0x61, 0xab, 0x15, 0x28, 0x84, 0x8e, 0x6c, 0xbf, 0x4e, 0xbf,
+ 0x3d, 0x96, 0x2f, 0xbb, 0x3f, 0x3a, 0x58, 0xa9, 0x3d, 0x06, 0x2a, 0xbf,
+ 0x7f, 0x62, 0x79, 0x58, 0xbf, 0x07, 0x91, 0x0e, 0x0b, 0x16, 0x35, 0x62,
+ 0xb6, 0x3e, 0x68, 0x8a, 0x23, 0x8a, 0xef, 0x9c, 0xa2, 0x8f, 0x58, 0xbe,
+ 0x29, 0xea, 0x0b, 0x14, 0xc7, 0xfa, 0x03, 0x4f, 0x13, 0x5f, 0x7b, 0x99,
+ 0xe5, 0x8b, 0xff, 0xfc, 0xfd, 0x43, 0xaf, 0x38, 0x5b, 0xfd, 0xf7, 0xdd,
+ 0xb5, 0xb2, 0xc5, 0x4a, 0x23, 0x34, 0x47, 0x7f, 0x4f, 0x6c, 0xff, 0xe5,
+ 0x62, 0xfb, 0xdc, 0xc8, 0x96, 0x3e, 0x6b, 0xef, 0xef, 0x8d, 0xfb, 0x48,
+ 0xd6, 0x28, 0x68, 0xb5, 0xc5, 0x16, 0x34, 0xbe, 0xd3, 0xb6, 0xcb, 0x17,
+ 0xff, 0x36, 0x98, 0x06, 0x34, 0x0a, 0x4e, 0xb1, 0x7f, 0xff, 0xc2, 0x9d,
+ 0x19, 0x85, 0x3f, 0x73, 0xe7, 0x0d, 0x14, 0xe9, 0x62, 0xec, 0x23, 0x11,
+ 0x56, 0x6a, 0x25, 0xfa, 0x75, 0x11, 0xc0, 0xb1, 0x60, 0x2c, 0x5f, 0xf8,
+ 0x59, 0x1f, 0xc6, 0xd1, 0x4c, 0x16, 0x2b, 0x0f, 0x4c, 0x84, 0xaa, 0x51,
+ 0x3a, 0xef, 0xb5, 0x89, 0xdd, 0xbc, 0x33, 0xb9, 0x0c, 0xcb, 0xff, 0x41,
+ 0xbb, 0x72, 0x4e, 0xdd, 0x79, 0x62, 0xff, 0x38, 0xb5, 0xfc, 0xed, 0xc5,
+ 0x8b, 0xff, 0xfb, 0xcf, 0xd4, 0x0a, 0x4c, 0xf3, 0xe7, 0x70, 0xff, 0x8b,
+ 0x17, 0xff, 0xa4, 0xe5, 0x9d, 0x8b, 0x3b, 0x66, 0xa0, 0xb1, 0x58, 0x8a,
+ 0xb2, 0x5f, 0xbf, 0xde, 0xe0, 0x7f, 0xfb, 0x47, 0xac, 0x5f, 0x67, 0x9f,
+ 0x8b, 0x17, 0xe8, 0x8a, 0x34, 0xd8, 0x4b, 0x17, 0xff, 0xe8, 0xa2, 0x90,
+ 0x7b, 0x85, 0x91, 0x77, 0x91, 0xbc, 0x6f, 0xde, 0x2c, 0x5d, 0xef, 0xac,
+ 0x57, 0x78, 0x8b, 0x6c, 0x30, 0x66, 0xeb, 0xfe, 0xf7, 0xf0, 0x2f, 0x47,
+ 0x3f, 0x16, 0x2b, 0xa5, 0x58, 0xd1, 0xe8, 0x51, 0x43, 0x85, 0x88, 0x78,
+ 0x73, 0xe8, 0x6c, 0x06, 0x67, 0x7f, 0xe1, 0x31, 0xf8, 0xe4, 0xda, 0x35,
+ 0x62, 0xf9, 0xbc, 0xc4, 0xb1, 0x5b, 0x36, 0x73, 0x70, 0x84, 0x00, 0xe5,
+ 0x12, 0x64, 0x37, 0x8d, 0x22, 0xde, 0x1f, 0x3d, 0x46, 0xdc, 0xf1, 0xf1,
+ 0x45, 0x18, 0x2e, 0xa3, 0x3f, 0x3c, 0x31, 0xbe, 0xea, 0x08, 0xc0, 0xca,
+ 0x36, 0xfe, 0x47, 0xd3, 0xe9, 0x5f, 0xe1, 0x3a, 0xf7, 0x1f, 0xdf, 0xbd,
+ 0xf7, 0x20, 0x2c, 0x5e, 0x67, 0xdd, 0x62, 0xf7, 0x9e, 0x0b, 0x15, 0xb9,
+ 0xba, 0xf0, 0xed, 0xd9, 0xb2, 0xc5, 0xd1, 0x4a, 0xc5, 0xee, 0xda, 0x82,
+ 0xc5, 0xd8, 0x11, 0x87, 0xa0, 0x01, 0x82, 0x18, 0xbf, 0xe7, 0xec, 0x59,
+ 0xc1, 0x01, 0xd6, 0x2f, 0xfd, 0xf9, 0xea, 0x05, 0x9e, 0xfb, 0xac, 0x5f,
+ 0xa7, 0x4c, 0x17, 0x96, 0x2f, 0xff, 0x9f, 0x9b, 0x60, 0x5c, 0x7d, 0x89,
+ 0xba, 0xf2, 0xc5, 0x41, 0x1e, 0xbb, 0x9d, 0x7c, 0xff, 0xc5, 0x37, 0xfd,
+ 0x0c, 0xf6, 0x0d, 0xc8, 0x0b, 0x17, 0xd0, 0xc9, 0xe9, 0x62, 0xfd, 0x3a,
+ 0xc2, 0x75, 0x8b, 0xe1, 0x02, 0x60, 0xb1, 0x76, 0x7d, 0x62, 0xbc, 0x6e,
+ 0x82, 0x23, 0xbf, 0xb3, 0x5a, 0x11, 0xba, 0x58, 0xbf, 0x8a, 0x01, 0x37,
+ 0xf8, 0xb1, 0x7e, 0x37, 0xec, 0x4e, 0xb1, 0x6e, 0x61, 0xeb, 0xb9, 0x7d,
+ 0xc6, 0xc1, 0x62, 0xfb, 0x41, 0xc8, 0x4b, 0x17, 0xc3, 0x26, 0x35, 0x62,
+ 0xff, 0xe7, 0x83, 0x6b, 0x3b, 0x75, 0xbb, 0xf4, 0xb1, 0x52, 0x89, 0x1d,
+ 0x89, 0x7c, 0x47, 0x61, 0xca, 0xe2, 0x26, 0xce, 0x59, 0x19, 0x87, 0x47,
+ 0xd1, 0x1c, 0x7c, 0x8d, 0x98, 0x08, 0x8b, 0xd0, 0x87, 0x8e, 0x26, 0x0e,
+ 0x15, 0x57, 0x39, 0xd6, 0x2b, 0x11, 0x97, 0xe8, 0x5a, 0x5f, 0x60, 0xf8,
+ 0x12, 0xc5, 0x9f, 0x87, 0x97, 0xdc, 0x4f, 0x7f, 0x80, 0x2e, 0x39, 0x75,
+ 0x05, 0x8b, 0xf8, 0x0f, 0xa7, 0xe8, 0x0b, 0x16, 0x68, 0xf3, 0xe4, 0x88,
+ 0xd6, 0xc0, 0x58, 0xbf, 0xa7, 0x0f, 0x99, 0xc5, 0x8b, 0xff, 0xff, 0x98,
+ 0x61, 0xc3, 0xf2, 0x6e, 0x10, 0xa1, 0x9c, 0x2c, 0x00, 0xb8, 0xb1, 0x7f,
+ 0x87, 0x84, 0xe1, 0x7c, 0x4b, 0x17, 0xee, 0xb7, 0x13, 0x12, 0xc5, 0xff,
+ 0xf7, 0xde, 0x7c, 0xe0, 0x98, 0x46, 0x04, 0x10, 0x49, 0x17, 0xff, 0x3c,
+ 0xf8, 0x13, 0x08, 0xc0, 0x82, 0x09, 0x22, 0xb1, 0x14, 0x3f, 0x56, 0xad,
+ 0x93, 0x21, 0xdc, 0xd3, 0xd0, 0xcb, 0xbf, 0xdf, 0x13, 0x1c, 0x6c, 0x75,
+ 0x8a, 0xdd, 0x51, 0x61, 0xcb, 0x0a, 0x39, 0x4f, 0x1c, 0x5e, 0xcc, 0x35,
+ 0x22, 0xf3, 0x37, 0x4b, 0x16, 0x02, 0xc5, 0xf3, 0xfe, 0x4e, 0xb1, 0x77,
+ 0x32, 0x4d, 0xa1, 0xa2, 0x54, 0x34, 0x4d, 0x44, 0x3b, 0xe5, 0x1b, 0xf3,
+ 0x91, 0x4c, 0x16, 0x2f, 0x01, 0xbc, 0xb1, 0x7d, 0xee, 0x0a, 0x3d, 0x62,
+ 0xfa, 0x74, 0xfd, 0x96, 0x2b, 0x11, 0x1c, 0xc4, 0xc2, 0x1d, 0x0c, 0x9e,
+ 0xfe, 0xcf, 0x71, 0xcb, 0x65, 0x8b, 0xfe, 0xd3, 0x6e, 0x67, 0xe4, 0x32,
+ 0x58, 0xbc, 0x29, 0xd2, 0xc5, 0xb8, 0x33, 0xd9, 0x88, 0xf2, 0xb6, 0x45,
+ 0x87, 0xa1, 0x0f, 0x7c, 0x68, 0x81, 0xc5, 0x8b, 0x88, 0x4a, 0x90, 0x64,
+ 0xbf, 0xa4, 0xf3, 0xcd, 0x62, 0xc5, 0x40, 0xf4, 0x62, 0x24, 0xbf, 0xfe,
+ 0x10, 0x71, 0x18, 0x4f, 0xad, 0x66, 0xc7, 0xc5, 0x8b, 0xa7, 0x65, 0x8b,
+ 0xff, 0xff, 0xb4, 0x23, 0x7a, 0xf0, 0x98, 0x30, 0xf5, 0xc1, 0x36, 0x85,
+ 0xb4, 0x9a, 0xb1, 0x5f, 0x44, 0x9f, 0x06, 0x2f, 0xde, 0x98, 0x1a, 0x75,
+ 0x8b, 0xe1, 0x0c, 0x01, 0x2c, 0x5f, 0xe1, 0x16, 0xff, 0x9e, 0xbb, 0x96,
+ 0x2f, 0xe7, 0xec, 0xe5, 0x27, 0x58, 0xbc, 0x10, 0x41, 0x24, 0x5e, 0xc2,
+ 0xdd, 0x22, 0x30, 0xd0, 0xdf, 0xfb, 0x36, 0xc1, 0xb4, 0x0a, 0x76, 0x58,
+ 0xa9, 0x4d, 0x1b, 0x62, 0xa7, 0x25, 0x63, 0x90, 0x27, 0x91, 0x85, 0xff,
+ 0xec, 0xd7, 0xbd, 0x9c, 0x29, 0xcd, 0x41, 0x62, 0xfc, 0xff, 0xfe, 0x79,
+ 0x62, 0xd2, 0x61, 0xf8, 0xf1, 0x26, 0xfd, 0xfc, 0xe8, 0x41, 0x2c, 0x5f,
+ 0x7d, 0x88, 0xd5, 0x8a, 0x19, 0xfb, 0x6e, 0x51, 0xe2, 0xbb, 0xfb, 0xa8,
+ 0x70, 0x9b, 0x75, 0x8b, 0xe6, 0x8f, 0xf7, 0x16, 0x2f, 0xb4, 0x3c, 0xfa,
+ 0xc5, 0xe2, 0xef, 0xac, 0x6c, 0xb1, 0x58, 0x8a, 0x3e, 0x8c, 0x1c, 0x99,
+ 0x88, 0xee, 0xef, 0xaf, 0x7d, 0x56, 0x2f, 0xd0, 0xdf, 0x3a, 0xf2, 0xc5,
+ 0xfb, 0x3d, 0xe1, 0x6c, 0xb1, 0x7f, 0x3b, 0x43, 0xcf, 0xb2, 0xc5, 0xcf,
+ 0xb2, 0xc7, 0xcd, 0x75, 0xa1, 0xdf, 0x54, 0x69, 0xc0, 0xa0, 0x8a, 0xfc,
+ 0xb1, 0x7b, 0xb3, 0x1d, 0x62, 0xfb, 0x06, 0xdf, 0x58, 0xac, 0x3c, 0x1e,
+ 0x0f, 0xdf, 0xf1, 0xfb, 0x98, 0xa7, 0xf2, 0x35, 0x8b, 0xdf, 0xcd, 0xd6,
+ 0x2f, 0xbd, 0x3d, 0x71, 0x62, 0xa4, 0xff, 0x46, 0x76, 0xc3, 0xd7, 0x9a,
+ 0x3e, 0x56, 0x2f, 0xd8, 0x3f, 0xb4, 0x7a, 0xc5, 0xe1, 0xc9, 0xd6, 0x2f,
+ 0xd3, 0x07, 0x2c, 0x58, 0xb1, 0x61, 0xe1, 0xb8, 0xed, 0xfe, 0xce, 0xed,
+ 0xff, 0x9d, 0x77, 0x2c, 0x54, 0x68, 0xcd, 0x3b, 0x99, 0x47, 0xdb, 0x43,
+ 0x7c, 0x70, 0xbf, 0xc8, 0x76, 0x1a, 0x53, 0xd3, 0xb4, 0x79, 0x1c, 0x50,
+ 0xe7, 0xd4, 0x6d, 0x27, 0x8c, 0xf3, 0xf0, 0xd3, 0x68, 0xc3, 0x81, 0x08,
+ 0xb2, 0x84, 0xf0, 0x8b, 0x7b, 0x0f, 0x84, 0xdd, 0x1c, 0x4b, 0x7c, 0xfa,
+ 0x8a, 0x0b, 0x17, 0xfe, 0xc0, 0x01, 0xb9, 0x31, 0x0b, 0x4b, 0x16, 0x3e,
+ 0x1f, 0x21, 0x12, 0x5f, 0xf1, 0x0b, 0xdf, 0xce, 0xc3, 0x95, 0x8a, 0x58,
+ 0xbd, 0xa7, 0xd2, 0xc5, 0x61, 0xf2, 0x77, 0xe7, 0x61, 0x86, 0x5f, 0xdf,
+ 0x26, 0xdb, 0x8c, 0xb1, 0x7f, 0xf8, 0x36, 0x2f, 0xb4, 0x39, 0x87, 0x98,
+ 0xf5, 0x8a, 0x31, 0x15, 0xf8, 0x68, 0x69, 0x75, 0xff, 0xb4, 0x6e, 0xb5,
+ 0x81, 0x47, 0x49, 0xd6, 0x2a, 0x53, 0xaf, 0x78, 0xce, 0x43, 0x31, 0xbf,
+ 0x3e, 0xb6, 0x7d, 0x96, 0x2f, 0xa7, 0xc2, 0x0d, 0x62, 0xfd, 0x9c, 0xd7,
+ 0xa5, 0x62, 0xf7, 0x9e, 0x56, 0x2f, 0xcf, 0x3b, 0x31, 0xd6, 0x2f, 0xf7,
+ 0xe4, 0xbc, 0x43, 0xe9, 0x62, 0xc4, 0xb1, 0x73, 0x9d, 0x62, 0xb0, 0xd4,
+ 0x10, 0x8d, 0x41, 0x1c, 0xee, 0x50, 0x43, 0x9c, 0x28, 0x12, 0xe5, 0xff,
+ 0xb5, 0x08, 0x1f, 0x8e, 0x5d, 0x41, 0x62, 0xfc, 0x53, 0xd4, 0xf1, 0x62,
+ 0xff, 0xd8, 0xe4, 0xde, 0xe0, 0x52, 0x4b, 0x16, 0xd4, 0x9f, 0x2f, 0x0a,
+ 0x2d, 0xfc, 0x46, 0x6b, 0x42, 0x9a, 0xf9, 0xf5, 0x3e, 0x58, 0xbf, 0xff,
+ 0x14, 0xeb, 0x4f, 0x3b, 0x60, 0x04, 0xc5, 0xba, 0xc5, 0xf7, 0x32, 0x60,
+ 0xb1, 0x43, 0x44, 0xce, 0xe4, 0x44, 0xab, 0x7b, 0xf9, 0xd2, 0xc5, 0xfe,
+ 0xfc, 0xe4, 0x52, 0x43, 0x58, 0xbc, 0xf2, 0x75, 0x8b, 0x0c, 0x67, 0x9f,
+ 0xa3, 0x3b, 0x4c, 0x11, 0x2a, 0x4d, 0xb7, 0xd0, 0x79, 0xdd, 0x62, 0xee,
+ 0x80, 0xb1, 0x7f, 0x1e, 0x78, 0x07, 0xdd, 0x62, 0xf7, 0x24, 0xd0, 0x1e,
+ 0x47, 0x06, 0x6f, 0xa1, 0x3a, 0xd9, 0x62, 0xfd, 0x9d, 0xcf, 0x31, 0x2c,
+ 0x54, 0x47, 0x9e, 0x44, 0x97, 0xf6, 0x68, 0x00, 0x72, 0x58, 0xa6, 0x3c,
+ 0xf1, 0x11, 0x5f, 0xc5, 0xe7, 0xd8, 0xa5, 0x62, 0xdc, 0x58, 0xba, 0x34,
+ 0xd9, 0x62, 0xa4, 0xf7, 0x60, 0x5a, 0xc2, 0x57, 0xbb, 0x7d, 0xd6, 0x2f,
+ 0x6a, 0x60, 0xb1, 0x7e, 0x91, 0xfe, 0x7b, 0xf5, 0x8a, 0xd1, 0xe5, 0x76,
+ 0x1d, 0xbf, 0xce, 0x3d, 0x60, 0xd8, 0xeb, 0x17, 0xd1, 0x72, 0x78, 0xb1,
+ 0x7f, 0xe8, 0xec, 0x0c, 0xa4, 0xb6, 0x7d, 0x2c, 0x5b, 0x0e, 0x89, 0x90,
+ 0x19, 0xf8, 0x92, 0xff, 0xff, 0xfb, 0x40, 0x8e, 0xc3, 0x32, 0x1f, 0xcd,
+ 0xdf, 0x5a, 0xcf, 0x7d, 0xd9, 0xf6, 0x58, 0xbe, 0xc3, 0x86, 0x35, 0x8b,
+ 0xf9, 0xcd, 0xf7, 0x1b, 0xa5, 0x8b, 0xe8, 0xa4, 0xbc, 0xb1, 0x7f, 0xff,
+ 0x43, 0xed, 0x03, 0x3d, 0xf9, 0xfe, 0xe2, 0x06, 0x12, 0xc5, 0x1a, 0x88,
+ 0x1d, 0x11, 0xd4, 0xaa, 0xd6, 0x76, 0x9f, 0xc2, 0xf5, 0x8d, 0x4a, 0x10,
+ 0x5c, 0x24, 0x14, 0x2c, 0x6f, 0x77, 0x9f, 0x75, 0x8b, 0xff, 0xfe, 0xed,
+ 0x23, 0x72, 0x6d, 0x1a, 0x4c, 0xe5, 0x80, 0x17, 0x16, 0x2f, 0xfd, 0xf0,
+ 0xf9, 0x9a, 0xdd, 0x9b, 0x75, 0x48, 0x18, 0x5f, 0xfd, 0xb4, 0x9b, 0x9a,
+ 0xf7, 0xa7, 0x38, 0xb1, 0x43, 0x44, 0xa9, 0x27, 0xd4, 0xa6, 0x3a, 0xf0,
+ 0xfb, 0xbf, 0xe1, 0x31, 0xb9, 0xef, 0x67, 0xd6, 0x2e, 0xed, 0x8b, 0x15,
+ 0xf3, 0xd3, 0x63, 0xab, 0xfd, 0xda, 0x4b, 0x03, 0xc3, 0xac, 0x5f, 0xef,
+ 0xc9, 0x78, 0x0d, 0xe5, 0x8b, 0xff, 0xd0, 0xd4, 0xc3, 0x7f, 0xbf, 0xc9,
+ 0x8e, 0xb1, 0x5c, 0x3f, 0xe1, 0x19, 0xdf, 0xff, 0xa4, 0xb7, 0x62, 0x06,
+ 0x0f, 0x84, 0x26, 0x82, 0xc5, 0xff, 0xde, 0x14, 0xb6, 0xa4, 0xd3, 0x45,
+ 0xb2, 0xc5, 0x1d, 0x13, 0x8c, 0xa9, 0x7f, 0xf1, 0xd8, 0x7f, 0x7c, 0x1b,
+ 0x90, 0x16, 0x2e, 0x11, 0xab, 0x14, 0xe7, 0xb8, 0x48, 0x77, 0xfd, 0xbb,
+ 0x9c, 0xee, 0x67, 0x04, 0xb1, 0x7f, 0x9b, 0xae, 0x07, 0xaf, 0xb2, 0xc5,
+ 0xff, 0xd8, 0x13, 0x00, 0xc6, 0x0e, 0x26, 0xf2, 0xc5, 0xb8, 0x03, 0xfe,
+ 0x23, 0x6b, 0xf9, 0xbf, 0x84, 0x7c, 0x58, 0xbe, 0x17, 0xf3, 0x75, 0x8b,
+ 0xf9, 0xca, 0x7e, 0xfb, 0x2c, 0x54, 0x17, 0x02, 0x06, 0xf4, 0xe4, 0x3a,
+ 0x85, 0x99, 0xe1, 0x7d, 0xf7, 0xe2, 0x20, 0xf4, 0x2e, 0xbb, 0x13, 0xc7,
+ 0x16, 0x77, 0x12, 0x5f, 0xfd, 0xee, 0x6d, 0x21, 0x94, 0xfd, 0xf6, 0x58,
+ 0xbf, 0xdc, 0x9d, 0x43, 0x77, 0xd9, 0x62, 0xfb, 0xee, 0xc0, 0x58, 0xa2,
+ 0x44, 0xff, 0x11, 0xfc, 0x6d, 0x7e, 0xe1, 0x9c, 0x04, 0x7a, 0xc5, 0xfe,
0xc2, 0xf3, 0xe8, 0x1c, 0x58, 0xb9, 0xfc, 0xb1, 0x7f, 0xf7, 0xf3, 0x7c,
- 0xd7, 0x3b, 0xf1, 0x87, 0x58, 0xbf, 0x67, 0x47, 0x21, 0xac, 0x50, 0xcf,
- 0xc8, 0x92, 0x6e, 0x68, 0x4a, 0x2a, 0xb9, 0x08, 0x9b, 0x68, 0xd4, 0xc3,
- 0xf5, 0x0d, 0xdb, 0xd9, 0xb0, 0x96, 0x2f, 0x98, 0x8a, 0x56, 0x2e, 0x11,
- 0xa4, 0x6f, 0x83, 0x1e, 0xa9, 0x4f, 0x6b, 0x23, 0x3e, 0xfb, 0x75, 0xdf,
- 0xdd, 0x62, 0xfb, 0x40, 0x78, 0x2c, 0x5f, 0x9b, 0xda, 0x98, 0x2c, 0x5f,
- 0xf7, 0x9c, 0x9b, 0xbf, 0x0a, 0x56, 0x2f, 0x8b, 0xc2, 0xfc, 0xa2, 0x13,
- 0xe4, 0x66, 0x14, 0x5e, 0xf8, 0xa3, 0xd6, 0x2f, 0xfc, 0xe5, 0xee, 0x38,
- 0xc1, 0xd8, 0x16, 0x2f, 0xff, 0xbe, 0xf9, 0xd3, 0x38, 0xd0, 0x72, 0x9e,
- 0x8b, 0x17, 0xfd, 0xbb, 0xe0, 0x66, 0x0d, 0xb6, 0x58, 0xb7, 0x16, 0x2b,
- 0xb3, 0xcf, 0x88, 0xf6, 0xb8, 0x8c, 0x4f, 0x42, 0x82, 0xff, 0xb0, 0xb7,
- 0xfb, 0x80, 0xcf, 0x2c, 0x59, 0xb8, 0x7c, 0x7d, 0x0a, 0x2b, 0x64, 0xe4,
- 0x35, 0x1b, 0x3d, 0x46, 0xec, 0xb0, 0x69, 0x9c, 0xea, 0x84, 0xb2, 0x7c,
- 0x35, 0x78, 0x4e, 0x85, 0xd1, 0xc5, 0x1d, 0x8d, 0xec, 0x23, 0x56, 0x2f,
- 0xf3, 0x0f, 0xf9, 0x9d, 0xf9, 0x62, 0xb0, 0xf4, 0x4d, 0x1d, 0xae, 0xd9,
- 0xf5, 0xff, 0x86, 0x89, 0x3f, 0x72, 0x50, 0x2f, 0xa9, 0x6c, 0x01, 0x21,
- 0xb3, 0x7e, 0x92, 0x84, 0x0e, 0xb1, 0x78, 0xa4, 0x35, 0x8b, 0xe7, 0xdd,
- 0xc6, 0xb1, 0x78, 0xc8, 0x1d, 0x62, 0xa0, 0x88, 0x7c, 0x28, 0xf0, 0xe8,
- 0x88, 0xef, 0xff, 0xf7, 0x37, 0xfb, 0xf7, 0xed, 0xff, 0x3b, 0x67, 0x7e,
- 0x61, 0xac, 0x5f, 0xfd, 0xe9, 0x72, 0xf6, 0xa7, 0xcd, 0xe5, 0x8a, 0x94,
- 0x55, 0x76, 0xcf, 0x7b, 0xcf, 0x12, 0xc5, 0xfc, 0x0f, 0x7a, 0x48, 0x0b,
- 0x15, 0x27, 0x98, 0xc3, 0xd7, 0x02, 0x56, 0x2f, 0xcc, 0x60, 0x98, 0xc5,
- 0x8a, 0x01, 0xe0, 0x88, 0x5e, 0xa2, 0x44, 0x1e, 0x98, 0x6f, 0x36, 0x41,
- 0x62, 0xee, 0x98, 0xb1, 0x58, 0x7b, 0x2e, 0x48, 0xc3, 0x97, 0xff, 0x34,
- 0x3a, 0xe7, 0xb3, 0xf3, 0xa0, 0x2c, 0x5c, 0x00, 0x2c, 0x5f, 0xf6, 0xff,
- 0x7d, 0x13, 0xfb, 0x8b, 0x15, 0x04, 0x4c, 0x1d, 0x18, 0x03, 0x17, 0xff,
- 0x06, 0x42, 0x6e, 0x3e, 0x74, 0x6d, 0x2c, 0x5f, 0xf6, 0xa7, 0xa3, 0xfb,
- 0x98, 0x6a, 0xc5, 0x62, 0x20, 0xa3, 0xd1, 0xaf, 0xe7, 0xff, 0xf0, 0x0c,
- 0xb1, 0x79, 0xbf, 0xc5, 0x8a, 0x93, 0xef, 0x01, 0x28, 0x8b, 0x6f, 0xfe,
- 0xe9, 0xac, 0x1c, 0xb8, 0xb7, 0x9d, 0x2c, 0x5f, 0xa7, 0xdc, 0xcf, 0x2c,
- 0x54, 0x9f, 0x78, 0xd1, 0xef, 0xee, 0x45, 0xf7, 0x0f, 0xcb, 0x17, 0xfb,
- 0x8f, 0x85, 0x9d, 0x86, 0xb1, 0x7f, 0xff, 0xb3, 0xde, 0x6d, 0x14, 0xf7,
- 0x03, 0x34, 0x03, 0xbf, 0x16, 0x2b, 0x11, 0x91, 0x1e, 0x62, 0x73, 0x4b,
- 0xf0, 0xbb, 0xdf, 0x0e, 0xb1, 0x7f, 0x9c, 0x3c, 0x21, 0xfe, 0x56, 0x2f,
- 0x9b, 0xb2, 0x1a, 0xc5, 0x1c, 0xf5, 0x80, 0x67, 0x7f, 0xfa, 0x7d, 0xc1,
- 0x6f, 0xd7, 0xec, 0x53, 0x2b, 0x16, 0x12, 0xc5, 0xf8, 0x06, 0x01, 0xa0,
- 0xb1, 0x5f, 0x37, 0x8c, 0x25, 0x7d, 0x1f, 0xd6, 0x3e, 0x0b, 0x17, 0xff,
- 0x88, 0x7f, 0xce, 0xcc, 0x62, 0xf1, 0x0d, 0x62, 0xd0, 0x93, 0xf7, 0x72,
- 0xcb, 0xff, 0xf9, 0xc3, 0xfb, 0x6f, 0x24, 0x3c, 0xef, 0xdf, 0x61, 0xac,
- 0x5f, 0xf6, 0xde, 0x86, 0x47, 0xb1, 0x01, 0x62, 0xfa, 0x2f, 0xb7, 0x96,
- 0x2b, 0x0f, 0x85, 0xcf, 0x6f, 0xd2, 0xdf, 0x68, 0xf5, 0x8b, 0xec, 0xef,
- 0x38, 0xb1, 0x76, 0x0f, 0x47, 0x9b, 0xf2, 0xab, 0xce, 0x1c, 0x7a, 0xc5,
- 0xfe, 0xce, 0x9c, 0xf7, 0xa4, 0xeb, 0x15, 0xa3, 0xd7, 0xf9, 0x0d, 0xfe,
- 0xf0, 0xca, 0x43, 0x6e, 0xd6, 0x2a, 0x57, 0x08, 0x06, 0x65, 0x90, 0x81,
- 0x34, 0x89, 0xe1, 0x11, 0x14, 0x25, 0xf4, 0x4d, 0xf8, 0x5f, 0x13, 0x6f,
- 0x21, 0x08, 0x61, 0x15, 0xff, 0xa0, 0xe5, 0x03, 0x3f, 0xf9, 0x1a, 0xc5,
- 0xc1, 0xba, 0xc5, 0xec, 0x2d, 0xd6, 0x2e, 0x93, 0xac, 0x58, 0xfb, 0x9b,
- 0x48, 0xe1, 0xda, 0x93, 0xf7, 0x74, 0xcb, 0xfe, 0xc1, 0x9a, 0xd1, 0x7e,
- 0x76, 0x58, 0xbf, 0x0b, 0xdb, 0x70, 0xd5, 0x8b, 0xff, 0x9b, 0x6e, 0x30,
- 0xe7, 0x69, 0x84, 0xac, 0x5f, 0xe7, 0x2d, 0xbf, 0x26, 0x12, 0xc5, 0xfd,
- 0x9c, 0x8e, 0xcd, 0x4a, 0xc5, 0x76, 0x9f, 0x46, 0xa1, 0x6f, 0xf2, 0x02,
- 0x3c, 0xe1, 0x67, 0x91, 0x63, 0x8d, 0x2f, 0xfa, 0x4c, 0xfb, 0x77, 0xef,
- 0xca, 0xc5, 0xf3, 0xc9, 0x44, 0xb1, 0x78, 0xc9, 0x8f, 0x58, 0xbf, 0xd2,
- 0x79, 0x8c, 0x0c, 0x30, 0xd6, 0x2b, 0x67, 0x43, 0xc1, 0x08, 0x71, 0x8e,
- 0x30, 0x8c, 0x86, 0x2e, 0xee, 0xdd, 0x93, 0x3d, 0x60, 0x35, 0x14, 0x3f,
- 0xb5, 0x0e, 0x63, 0xc6, 0x96, 0xd0, 0xc4, 0x04, 0x64, 0x25, 0x09, 0xde,
- 0x4e, 0x84, 0xfa, 0x54, 0xdf, 0x46, 0xd0, 0xce, 0xe3, 0x88, 0x82, 0x10,
- 0xdf, 0xee, 0x73, 0x08, 0x11, 0xd8, 0xb1, 0x7c, 0x4e, 0x12, 0x56, 0x2d,
- 0x1c, 0xb1, 0x70, 0x25, 0x62, 0xf1, 0x67, 0x16, 0x28, 0x8d, 0x99, 0x82,
- 0xf6, 0x89, 0x62, 0xfe, 0xe6, 0x10, 0x23, 0xb1, 0x62, 0xc6, 0xac, 0x5e,
- 0x8d, 0xa4, 0x96, 0x2b, 0xaa, 0x67, 0x38, 0x6c, 0xe4, 0x6c, 0x90, 0x02,
- 0x1e, 0x09, 0x88, 0xc0, 0x31, 0x3b, 0xef, 0x33, 0x12, 0xc5, 0x74, 0x44,
- 0x98, 0x6e, 0x57, 0x83, 0xfc, 0x16, 0x2f, 0xfd, 0xf6, 0x81, 0x67, 0xbd,
- 0x27, 0x58, 0xbf, 0xf6, 0xf9, 0xad, 0x4c, 0x39, 0x20, 0x58, 0xbf, 0xe6,
- 0xde, 0x07, 0xff, 0x6d, 0x1e, 0xb1, 0x50, 0x45, 0xe8, 0x8f, 0xba, 0x20,
- 0x5f, 0xd3, 0x0f, 0x47, 0x67, 0xd6, 0x2f, 0xf0, 0x18, 0x13, 0x1f, 0x30,
- 0x58, 0xbf, 0xfa, 0x0f, 0x9f, 0x6f, 0xfe, 0x7b, 0xe2, 0xc5, 0xfe, 0xfe,
- 0x0c, 0xa7, 0x09, 0x62, 0xa0, 0x8a, 0xce, 0xcd, 0x80, 0x8b, 0x76, 0x12,
- 0xc5, 0xed, 0x36, 0xeb, 0x14, 0x33, 0x68, 0x68, 0xb5, 0xff, 0xdb, 0x45,
- 0x09, 0xd6, 0xdf, 0xed, 0xa3, 0xd6, 0x2f, 0xc2, 0x3c, 0xe7, 0x96, 0x2f,
- 0xb0, 0x12, 0x05, 0x8a, 0x01, 0xe5, 0x11, 0x45, 0x6c, 0x8d, 0xa6, 0x22,
- 0xf4, 0x25, 0xea, 0x55, 0xaf, 0xe4, 0x37, 0x1c, 0xc9, 0xa1, 0xba, 0x28,
- 0xcf, 0xee, 0x23, 0x56, 0x2f, 0xff, 0x16, 0xdd, 0x62, 0x72, 0xc1, 0xe1,
- 0x1a, 0xb1, 0x7f, 0xc2, 0x11, 0x84, 0xfd, 0x41, 0xe5, 0x8b, 0xd1, 0x02,
- 0x56, 0x2f, 0xfb, 0xa4, 0xf7, 0x1d, 0x3a, 0xc2, 0x58, 0xbd, 0x8f, 0xf5,
- 0x8a, 0x8d, 0x8f, 0xe3, 0x07, 0xbe, 0x7d, 0x7f, 0x3f, 0x61, 0x3f, 0x3e,
- 0x58, 0xbf, 0x0b, 0x8e, 0xfd, 0xac, 0x5f, 0xe1, 0x76, 0x13, 0x7f, 0xb7,
- 0x16, 0x2f, 0xb3, 0xdf, 0x75, 0x8a, 0x63, 0xdb, 0x23, 0x9b, 0xc6, 0x64,
- 0xac, 0x5c, 0x23, 0x56, 0x2f, 0xd2, 0x44, 0x23, 0xac, 0x57, 0xcf, 0x00,
- 0xc1, 0x9b, 0xde, 0x93, 0x16, 0x2f, 0xf6, 0x0f, 0x4d, 0xbf, 0x80, 0xb1,
- 0x7e, 0xc2, 0x1f, 0xe5, 0x62, 0xb0, 0xfe, 0xbe, 0x3c, 0x19, 0xad, 0xd9,
- 0xc5, 0x8a, 0x58, 0xa5, 0x8b, 0x42, 0x22, 0xe3, 0xc1, 0x95, 0x03, 0xd6,
- 0x01, 0x7d, 0xfd, 0xbf, 0xe7, 0xc2, 0x31, 0x62, 0xa5, 0x5e, 0xe6, 0xc9,
- 0xa6, 0xc2, 0xd6, 0x3c, 0xce, 0x23, 0x1d, 0x42, 0x11, 0x88, 0x09, 0x77,
- 0x90, 0x9d, 0xf4, 0x21, 0x4c, 0x22, 0xbe, 0x1e, 0x9a, 0x0b, 0x17, 0xff,
- 0xfb, 0x09, 0xbd, 0xcc, 0xd0, 0x01, 0x39, 0xdf, 0xb8, 0xeb, 0x17, 0x42,
- 0x56, 0x2d, 0x1c, 0xb1, 0x5d, 0x4d, 0x66, 0x0b, 0xd0, 0xd1, 0x5d, 0xe8,
- 0x46, 0x54, 0xa3, 0xe5, 0xa1, 0xa3, 0x78, 0x72, 0x4b, 0x15, 0xd5, 0xfc,
- 0x16, 0xa3, 0x74, 0x19, 0xae, 0x11, 0xf6, 0x8e, 0xc0, 0x70, 0xf4, 0xca,
- 0xc4, 0x80, 0xd8, 0xcf, 0x77, 0x9c, 0x76, 0xee, 0x11, 0xaf, 0x4c, 0x6f,
- 0xfc, 0xa7, 0x66, 0xb4, 0x41, 0x00, 0x96, 0x46, 0x52, 0xe1, 0x7c, 0xb0,
- 0x29, 0x7e, 0x81, 0xc7, 0x56, 0x61, 0x35, 0xf0, 0xc6, 0x22, 0x58, 0xbb,
- 0x6e, 0x8b, 0x17, 0x67, 0xd6, 0x2b, 0xb3, 0x65, 0xe1, 0xbb, 0xf0, 0x8d,
- 0x79, 0xd9, 0x62, 0xff, 0xf4, 0xc0, 0x43, 0xc6, 0xe7, 0x32, 0x12, 0xb1,
- 0x7f, 0xb7, 0xfb, 0x14, 0x8b, 0xb5, 0x8b, 0xf0, 0x8c, 0x69, 0xed, 0x62,
- 0xfd, 0xbf, 0xe7, 0xb0, 0x8b, 0x17, 0xa5, 0xe3, 0xd6, 0x2e, 0x10, 0x5d,
- 0x62, 0xfd, 0xf6, 0xd1, 0xdd, 0x62, 0xf1, 0x93, 0x1e, 0xb1, 0x7f, 0x19,
- 0xbf, 0xe7, 0xb0, 0x8b, 0x15, 0xd5, 0x1c, 0xa1, 0x42, 0xd8, 0x0f, 0xee,
- 0x39, 0xc2, 0x81, 0x10, 0xde, 0x72, 0xc5, 0x8b, 0xfb, 0xee, 0x17, 0xfc,
- 0xec, 0xb1, 0x61, 0xc0, 0xf3, 0xb7, 0x1b, 0xbe, 0x93, 0xb7, 0x16, 0x2e,
- 0x00, 0x6b, 0x17, 0xf7, 0xe5, 0xe3, 0xce, 0xeb, 0x17, 0xfa, 0x3c, 0x5a,
- 0xfc, 0xb8, 0xd6, 0x2b, 0xaa, 0x20, 0x37, 0x19, 0x73, 0x0a, 0xd9, 0x5b,
- 0x04, 0x0a, 0x86, 0x93, 0xb9, 0xaf, 0x71, 0x87, 0xbc, 0x2b, 0x3e, 0x53,
- 0xe8, 0x51, 0x5f, 0xf0, 0x4e, 0x0f, 0xf3, 0xa6, 0x25, 0x8b, 0xfb, 0x03,
- 0xcc, 0x23, 0x56, 0x2f, 0xf3, 0x3c, 0x3f, 0x9e, 0x95, 0x8b, 0x9f, 0x65,
- 0x8f, 0x9b, 0x2b, 0xa4, 0xc5, 0x8b, 0xcd, 0x9c, 0x58, 0xbf, 0x36, 0xce,
- 0x28, 0x2c, 0x5e, 0x00, 0x25, 0x62, 0xa0, 0x7f, 0x47, 0x18, 0xf8, 0xe1,
- 0x14, 0xde, 0xc2, 0x35, 0x62, 0xa5, 0x39, 0x57, 0x3b, 0x3b, 0x03, 0x42,
- 0x88, 0x21, 0xdd, 0xff, 0xb9, 0xa9, 0xf1, 0x31, 0xce, 0xeb, 0x17, 0xff,
- 0xa7, 0x9c, 0x93, 0xe7, 0x9f, 0x9f, 0x65, 0x8b, 0xce, 0x5e, 0x58, 0xad,
- 0xcf, 0x97, 0xe9, 0x37, 0xfe, 0xfb, 0xfe, 0x73, 0x50, 0xd4, 0x16, 0x2f,
- 0xfe, 0x3c, 0xfb, 0x8d, 0x9a, 0x01, 0xf1, 0x62, 0xfe, 0x29, 0x81, 0xe5,
- 0xd6, 0x28, 0x07, 0xe0, 0x48, 0x97, 0xef, 0xce, 0xd3, 0xf5, 0x8b, 0xe9,
- 0xd9, 0xf4, 0xb1, 0x7e, 0xd3, 0x1e, 0x77, 0x58, 0xbf, 0x67, 0x42, 0xce,
- 0x2c, 0x5e, 0xe9, 0x83, 0x58, 0xbf, 0xde, 0x7e, 0x8f, 0xe8, 0x4a, 0x45,
- 0x8e, 0xb1, 0x7c, 0x6e, 0xa6, 0x31, 0xcf, 0x1c, 0xc3, 0x5b, 0x60, 0xd1,
- 0x46, 0x4c, 0xd7, 0x61, 0xab, 0x15, 0xd5, 0x58, 0xb6, 0x42, 0x8f, 0x72,
- 0x37, 0x85, 0x7c, 0x44, 0x3f, 0x29, 0x62, 0x32, 0x29, 0xe4, 0x33, 0x23,
- 0x89, 0xef, 0xff, 0x37, 0x49, 0xc1, 0xb4, 0x33, 0xee, 0x1a, 0xc5, 0xf6,
- 0xcd, 0xad, 0xd6, 0x2e, 0xee, 0x0b, 0x15, 0x26, 0xf8, 0x44, 0xb7, 0xa4,
- 0xa5, 0x62, 0xf9, 0x87, 0x31, 0xeb, 0x17, 0xb4, 0xdd, 0x16, 0x2f, 0xc3,
- 0xd6, 0xb3, 0x8b, 0x17, 0x66, 0x96, 0x2a, 0x07, 0xbe, 0xc3, 0xe0, 0x29,
- 0xa8, 0x26, 0xed, 0xa8, 0x44, 0x9c, 0x80, 0x03, 0x65, 0x08, 0x4b, 0xfc,
- 0x50, 0x2c, 0x3c, 0xee, 0xb1, 0x7a, 0x26, 0xf2, 0xc5, 0xe2, 0x93, 0xac,
- 0x54, 0x9b, 0xa8, 0x87, 0xaf, 0xcf, 0xf2, 0x98, 0x2c, 0x5f, 0xda, 0x07,
- 0xe7, 0x34, 0xb1, 0x7d, 0xa6, 0x7d, 0x96, 0x2e, 0xe3, 0xac, 0x54, 0x9f,
- 0x43, 0x97, 0x31, 0x1d, 0xb1, 0x62, 0xf6, 0x61, 0xab, 0x14, 0x33, 0x5c,
- 0x10, 0x46, 0xf1, 0x34, 0x16, 0x28, 0xe6, 0xff, 0xe4, 0x77, 0xfe, 0xe1,
- 0x9a, 0xf4, 0x1c, 0xbd, 0xc5, 0x8a, 0x95, 0x4d, 0x98, 0xa8, 0xed, 0xba,
- 0x21, 0xfc, 0x23, 0xda, 0x13, 0x22, 0x21, 0xbf, 0xe7, 0xe9, 0x9a, 0xdd,
- 0x9b, 0x75, 0x46, 0x1a, 0x5e, 0x8e, 0x17, 0x96, 0x2e, 0x7e, 0x8b, 0x17,
- 0xfe, 0xdf, 0xf2, 0x4d, 0xee, 0x66, 0xcb, 0x17, 0xda, 0x78, 0xb8, 0xb1,
- 0x7b, 0x4c, 0x62, 0xc5, 0x62, 0x20, 0xb4, 0x80, 0xc4, 0x97, 0x61, 0xab,
- 0x17, 0xff, 0x49, 0xdc, 0x78, 0x46, 0xfe, 0x4e, 0xb1, 0x5f, 0x3d, 0xcf,
- 0x0c, 0x5f, 0x61, 0xe4, 0xc5, 0x8a, 0x1a, 0x7a, 0x9b, 0xa4, 0x9c, 0x87,
- 0x90, 0x9b, 0xf4, 0x22, 0xba, 0x11, 0x5c, 0x67, 0xd6, 0x2f, 0xc4, 0xc1,
- 0x98, 0x75, 0x8b, 0xe6, 0xef, 0xd8, 0xb1, 0x67, 0x88, 0xf3, 0x78, 0x55,
- 0x46, 0xa2, 0x3b, 0xec, 0xd7, 0xff, 0xbd, 0xf9, 0xe4, 0xfe, 0x5f, 0x69,
- 0x35, 0x62, 0xe1, 0x04, 0x58, 0xbf, 0xe1, 0xb1, 0xda, 0x12, 0xfb, 0xac,
- 0x53, 0xa2, 0x78, 0x09, 0x64, 0x35, 0x7f, 0xbf, 0x31, 0x41, 0xf5, 0x05,
- 0x8b, 0x8f, 0x2b, 0x17, 0xd1, 0x14, 0x9d, 0x62, 0xb0, 0xdd, 0x10, 0xbd,
- 0xfe, 0xf3, 0x87, 0x11, 0x30, 0x6b, 0x17, 0x7d, 0xd6, 0x2f, 0xfa, 0x5a,
- 0x1f, 0x9d, 0x9b, 0x65, 0x8b, 0xd9, 0xa0, 0x2c, 0x5f, 0xf6, 0x74, 0x91,
- 0xff, 0x1f, 0xcb, 0x17, 0xb8, 0xc0, 0x58, 0xa2, 0x3d, 0x7f, 0x1d, 0x54,
- 0x7a, 0x39, 0x8e, 0x2f, 0xf3, 0xaf, 0x3a, 0x5f, 0xc2, 0x30, 0x00, 0x9e,
- 0xd6, 0x2e, 0x7d, 0x96, 0x2f, 0x8f, 0xec, 0xdd, 0x62, 0xf6, 0x9a, 0x0b,
- 0x17, 0x77, 0x2b, 0x17, 0xfc, 0xcd, 0xdf, 0xdf, 0x66, 0x25, 0x8b, 0x6d,
- 0x27, 0xa2, 0x31, 0x8a, 0x94, 0x5d, 0x61, 0x23, 0xb7, 0x5c, 0x1f, 0x96,
- 0x2f, 0xa0, 0x02, 0xc5, 0x8b, 0xff, 0xc0, 0x26, 0x3e, 0xb2, 0x7b, 0x83,
- 0x9d, 0x62, 0xa4, 0xfb, 0x04, 0x45, 0x7f, 0x78, 0x98, 0x1c, 0x12, 0xc5,
- 0xcf, 0xb2, 0xc5, 0xfe, 0xef, 0x8f, 0xc7, 0xef, 0xcb, 0x15, 0x2b, 0x8d,
- 0x43, 0x2e, 0xc6, 0xfe, 0xc7, 0xde, 0x31, 0xc8, 0x90, 0x34, 0x63, 0xf8,
- 0x69, 0x31, 0x69, 0x42, 0x17, 0x84, 0x3e, 0x2e, 0x10, 0xc5, 0xff, 0xff,
- 0xfc, 0xfe, 0xfe, 0x1f, 0xe5, 0x9d, 0x1b, 0x7f, 0xb9, 0x9e, 0x72, 0xdf,
- 0x3d, 0xf7, 0x58, 0xba, 0x7e, 0xb1, 0x7d, 0xed, 0x4f, 0x45, 0x8a, 0x1a,
- 0x31, 0xcf, 0x08, 0xb6, 0x17, 0xbe, 0xf7, 0x05, 0x1e, 0xb1, 0x7e, 0xee,
- 0x07, 0x9f, 0x2c, 0x53, 0x9e, 0x88, 0x89, 0xef, 0xa7, 0xb1, 0x47, 0xac,
- 0x5f, 0xff, 0xb7, 0x17, 0xcd, 0x72, 0x9f, 0xc8, 0x72, 0x58, 0xb1, 0x51,
- 0x1f, 0xe9, 0x13, 0xdf, 0x38, 0xc2, 0x3a, 0xc5, 0x4a, 0x6d, 0x3f, 0x84,
- 0x2b, 0x42, 0x78, 0x32, 0x2b, 0xfe, 0xfc, 0xc1, 0xcb, 0x0f, 0x2b, 0x17,
- 0xcc, 0x38, 0x6c, 0xb1, 0x7b, 0xc6, 0xec, 0xb1, 0x7f, 0xd9, 0xef, 0xe1,
- 0xc9, 0xbc, 0xb1, 0x7f, 0x74, 0x7d, 0x77, 0x31, 0xeb, 0x15, 0xb2, 0x23,
- 0x06, 0x41, 0x87, 0x15, 0xf4, 0x70, 0x14, 0x2c, 0x2f, 0xf3, 0xfa, 0x7e,
- 0xc5, 0xe5, 0x8b, 0xfb, 0xa4, 0xf5, 0xef, 0xd1, 0xb2, 0xc5, 0x40, 0xfa,
- 0xf0, 0xca, 0xe2, 0x02, 0xc5, 0xff, 0xcf, 0xc1, 0x1f, 0x93, 0xf7, 0xd4,
- 0xac, 0x5f, 0x8f, 0x3b, 0xec, 0x35, 0x8b, 0xe8, 0x49, 0xd9, 0x62, 0xfe,
- 0x1b, 0x8b, 0x59, 0xba, 0xc5, 0xfb, 0x40, 0x3b, 0xf1, 0x62, 0xef, 0x73,
- 0xaa, 0x64, 0x21, 0x52, 0x18, 0x0b, 0xe2, 0x23, 0x15, 0xf0, 0x88, 0xc2,
- 0xfa, 0x95, 0x45, 0x22, 0x8e, 0xce, 0xdc, 0x58, 0xbf, 0xa7, 0x6c, 0x27,
- 0x35, 0x71, 0x89, 0x95, 0xa3, 0xcd, 0xe0, 0x95, 0xff, 0xf9, 0xb9, 0xf6,
- 0x7f, 0x40, 0x52, 0xde, 0x14, 0xac, 0x5f, 0x3e, 0xf2, 0x75, 0x8b, 0xff,
- 0x13, 0x7e, 0x41, 0x19, 0xae, 0x71, 0x22, 0xf7, 0xf0, 0x6b, 0x15, 0x27,
- 0xbe, 0xe8, 0x57, 0xbd, 0x06, 0x58, 0xb6, 0x2c, 0x54, 0x9a, 0xe3, 0x07,
- 0x6f, 0x68, 0x5b, 0x2c, 0x5e, 0x00, 0x25, 0x62, 0xff, 0xfb, 0xd3, 0x9a,
- 0x9e, 0xac, 0x58, 0x71, 0x7d, 0x62, 0xa5, 0x11, 0x98, 0x3e, 0xc3, 0xb7,
- 0xdc, 0x11, 0x79, 0x62, 0xfc, 0x61, 0x43, 0xf8, 0xb1, 0x4e, 0x79, 0x80,
- 0x23, 0xbb, 0x6d, 0x96, 0x2c, 0x05, 0x8b, 0x4a, 0xc5, 0xb0, 0x66, 0x8f,
- 0x71, 0x2b, 0xe0, 0x8e, 0x47, 0x58, 0xad, 0x97, 0xb3, 0x07, 0x2d, 0x03,
- 0x1d, 0xfb, 0x22, 0xd2, 0xa1, 0xe1, 0x05, 0xf4, 0xe2, 0x85, 0x6f, 0x9e,
- 0x44, 0x43, 0xd0, 0xf4, 0x21, 0x3d, 0xe3, 0xce, 0xeb, 0x17, 0xfe, 0x07,
- 0x30, 0xb0, 0x1c, 0x98, 0xf5, 0x8b, 0xf3, 0x44, 0xf9, 0xc5, 0x8b, 0xee,
- 0x4e, 0xa0, 0xb1, 0x5d, 0x4f, 0x2f, 0x85, 0x17, 0x3f, 0x16, 0x2f, 0x72,
- 0x60, 0xb1, 0x52, 0x6d, 0x3b, 0x17, 0xa1, 0x9f, 0xc9, 0xd6, 0x2a, 0x53,
- 0x45, 0xc1, 0xe6, 0x8c, 0x16, 0xf3, 0x7e, 0x56, 0x2f, 0xf0, 0xff, 0x3e,
- 0xf4, 0x9d, 0x62, 0xbe, 0x7a, 0x04, 0x39, 0x79, 0xf5, 0x05, 0x8b, 0x6c,
- 0xb1, 0x5f, 0x36, 0x02, 0x1d, 0xbe, 0x93, 0x02, 0x0d, 0x62, 0xfb, 0x8f,
- 0xe9, 0x58, 0xbb, 0xb8, 0x6c, 0x79, 0x1d, 0x93, 0x5e, 0x7e, 0xf8, 0xb1,
- 0x58, 0x79, 0xee, 0x63, 0x58, 0x99, 0x4b, 0xa8, 0xfe, 0x17, 0x17, 0x82,
- 0x0a, 0x3d, 0x62, 0xd1, 0x2c, 0x5a, 0x25, 0x8a, 0xdc, 0xf2, 0x5c, 0x8c,
- 0x42, 0x77, 0xda, 0xf6, 0x7d, 0x62, 0xec, 0xdd, 0x62, 0xdc, 0x58, 0xf1,
- 0x71, 0x7d, 0x27, 0x61, 0xac, 0x5f, 0x86, 0xfd, 0x24, 0x6b, 0x14, 0x33,
- 0xcc, 0xd1, 0x15, 0x62, 0x23, 0xdd, 0xb6, 0xf4, 0x24, 0xeb, 0x17, 0xb6,
- 0x6d, 0x96, 0x2b, 0x63, 0x78, 0xc3, 0xb7, 0xbd, 0x9f, 0x58, 0xbe, 0xdb,
- 0xce, 0x6a, 0xc5, 0x4a, 0x77, 0x2e, 0x5f, 0xa8, 0x65, 0x32, 0xe8, 0x88,
- 0x4c, 0x1d, 0xbf, 0x44, 0xdf, 0x9f, 0xac, 0x5f, 0xfc, 0xcf, 0x9c, 0x9d,
- 0xb0, 0x9c, 0xd5, 0x8b, 0xfb, 0x35, 0xb6, 0xd8, 0x05, 0x8a, 0xea, 0x7e,
- 0x7c, 0x43, 0xbb, 0xa4, 0xac, 0x5f, 0xd2, 0x03, 0xb4, 0x31, 0x62, 0x86,
- 0x7d, 0x47, 0x24, 0x21, 0x9b, 0xf8, 0xf3, 0xdf, 0x9b, 0x75, 0x8b, 0x9f,
- 0x65, 0x8b, 0xf3, 0xc1, 0xfb, 0x82, 0xc5, 0x68, 0xfc, 0x7e, 0x61, 0xc1,
- 0x8b, 0xff, 0xf8, 0xb3, 0xdf, 0xc8, 0x66, 0xf3, 0xbf, 0x89, 0x8e, 0xb1,
- 0x52, 0xa8, 0xbf, 0x23, 0x06, 0x78, 0x4f, 0xf0, 0xbe, 0xff, 0xf7, 0x1b,
- 0xdf, 0x6e, 0x16, 0x7b, 0x00, 0xb1, 0x7f, 0xcf, 0x07, 0xe7, 0x70, 0x72,
- 0x58, 0xbf, 0xc0, 0x78, 0x6b, 0x4e, 0x1a, 0xc5, 0x68, 0xfb, 0x88, 0xe6,
- 0xf9, 0xcf, 0x31, 0x2c, 0x5f, 0xfd, 0xc7, 0xec, 0xb2, 0x2d, 0x4f, 0xb8,
- 0xb1, 0x7d, 0x9b, 0x0a, 0x0b, 0x17, 0xcf, 0xa9, 0xd9, 0x62, 0xa0, 0x9c,
- 0x43, 0xc2, 0xde, 0x22, 0x10, 0x11, 0x86, 0x8c, 0x61, 0x25, 0xf0, 0x4c,
- 0xc1, 0xac, 0x5f, 0x9f, 0x82, 0xc3, 0xac, 0x5f, 0xfd, 0xc6, 0xed, 0xce,
- 0x2e, 0x7a, 0x7e, 0xb1, 0x7f, 0xe9, 0x84, 0xc5, 0xcf, 0xe7, 0x4e, 0x2c,
- 0x5f, 0xe9, 0xd3, 0x11, 0x61, 0xab, 0x17, 0xd3, 0x1a, 0xa3, 0x54, 0x6a,
- 0x58, 0xae, 0xd1, 0xdf, 0xc4, 0x6f, 0x21, 0x04, 0x32, 0xbe, 0x6d, 0x37,
- 0x6b, 0x17, 0xf0, 0x36, 0x68, 0x4c, 0x7a, 0xc5, 0xf7, 0x8a, 0x40, 0xb1,
- 0x7e, 0xeb, 0x31, 0x48, 0x6b, 0x17, 0x86, 0x39, 0x58, 0xb9, 0xc9, 0x62,
- 0x8d, 0x46, 0xb7, 0x64, 0x6e, 0x64, 0x72, 0x21, 0x16, 0x18, 0x3b, 0x7b,
- 0x02, 0x41, 0x62, 0xa5, 0x59, 0x46, 0x2f, 0xee, 0x48, 0xf1, 0x8b, 0xb4,
- 0x62, 0xc4, 0xb3, 0x74, 0xec, 0xb1, 0x7d, 0xa9, 0xc3, 0xac, 0x5d, 0x81,
- 0xac, 0x52, 0x71, 0x0c, 0x17, 0xf7, 0x0c, 0x9d, 0x49, 0xd3, 0x88, 0x60,
- 0xa4, 0xe2, 0x18, 0x29, 0x38, 0x86, 0x0a, 0x4e, 0x21, 0x82, 0x93, 0x88,
- 0x60, 0xa8, 0x22, 0xfd, 0xc6, 0x80, 0x7a, 0x21, 0xa8, 0xe1, 0xa0, 0x83,
- 0x57, 0x7f, 0x13, 0x88, 0x60, 0xbf, 0x99, 0xbd, 0x14, 0x9d, 0x38, 0x86,
- 0x0e, 0xa6, 0x96, 0xc1, 0x74, 0xe2, 0x18, 0x29, 0x38, 0x86, 0x0a, 0x4e,
- 0x21, 0x82, 0xa0, 0x6d, 0x1c, 0x6a, 0x93, 0x88, 0x60, 0xa4, 0xe2, 0x18,
- 0x29, 0x38, 0x86, 0x0a, 0x4e, 0x21, 0x82, 0x93, 0x88, 0x60, 0xa4, 0xe2,
- 0x18, 0x2b, 0x64, 0x4e, 0x0c, 0x69, 0xc6, 0x80, 0x35, 0xc1, 0xae, 0x83,
- 0x54, 0x9c, 0x43, 0x05, 0x27, 0x10, 0xc1, 0x50, 0x36, 0x9c, 0x1a, 0xa4,
- 0xe2, 0x18, 0x29, 0x38, 0x86, 0x0a, 0x4e, 0x21, 0x82, 0x93, 0x88, 0x60,
- 0xa8, 0x1f, 0x40, 0x06, 0xbc, 0x34, 0x10, 0x6a, 0x93, 0x88, 0x60, 0xa4,
- 0xe2, 0x18, 0x29, 0x38, 0x86, 0x0a, 0x4e, 0x21, 0x82, 0xb6, 0x3e, 0x83,
- 0x46, 0xb4, 0x35, 0xf1, 0xab, 0x1a, 0x9c, 0x43, 0x05, 0x27, 0x10, 0xc1,
- 0x49, 0xc4, 0x30, 0x52, 0x71, 0x0c, 0x14, 0x9c, 0x43, 0x05, 0x0c, 0xfa,
- 0x3b, 0x1a, 0x00, 0xd0, 0x86, 0xa9, 0x38, 0x86, 0x0a, 0x4e, 0x21, 0x82,
- 0x93, 0x88, 0x60, 0xbf, 0x7e, 0x41, 0xcc, 0x4e, 0x21, 0x82, 0x93, 0x88,
- 0x60, 0xa8, 0x22, 0x7b, 0x71, 0xaf, 0x8d, 0x30, 0xd0, 0x0d, 0xad, 0xba,
- 0x71, 0x0c, 0x14, 0x9c, 0x43, 0x05, 0x27, 0x10, 0xc1, 0x49, 0xc4, 0x30,
- 0x52, 0x71, 0x0c, 0x15, 0x03, 0xe8, 0xec, 0x69, 0xc6, 0xba, 0x0d, 0x52,
- 0x71, 0x0c, 0x14, 0x9c, 0x43, 0x05, 0x27, 0x10, 0xc1, 0x49, 0xc4, 0x30,
- 0x54, 0x0f, 0xa0, 0x63, 0x5f, 0x1a, 0x21, 0xab, 0x7d, 0x38, 0x86, 0x0a,
- 0x4e, 0x21, 0x82, 0x93, 0x88, 0x60, 0xb4, 0x13, 0x88, 0x60, 0xa4, 0xe2,
- 0x18, 0x3b, 0x34, 0x14, 0x9c, 0x43, 0x05, 0x27, 0x10, 0xc1, 0x49, 0xc4,
- 0x30, 0x52, 0x71, 0x0c, 0x15, 0xb2, 0x39, 0xe0, 0x34, 0x69, 0xd6, 0xe5,
- 0x71, 0x0d, 0x00, 0x6b, 0xc3, 0x56, 0xc4, 0xe2, 0x18, 0x29, 0x38, 0x86,
- 0x0a, 0x4e, 0x21, 0x82, 0xd0, 0x4e, 0x21, 0x82, 0x93, 0x88, 0x60, 0xec,
- 0xd0, 0x52, 0x71, 0x0c, 0x14, 0x9c, 0x43, 0x05, 0x4a, 0x2c, 0xe0, 0x34,
- 0xe7, 0x5a, 0x2b, 0x38, 0xd5, 0x27, 0x10, 0xc1, 0x49, 0xc4, 0x30, 0x52,
- 0x71, 0x0c, 0x14, 0x9c, 0x43, 0x05, 0x27, 0x10, 0xc1, 0x52, 0x88, 0x2e,
- 0xc6, 0xb4, 0x34, 0x71, 0xa2, 0x1a, 0xa4, 0xe2, 0x18, 0x29, 0x38, 0x86,
- 0x0a, 0x4e, 0x21, 0x82, 0xb4, 0x79, 0xdc, 0x1a, 0xf0, 0xd5, 0x27, 0x10,
- 0xc1, 0x49, 0xc4, 0x30, 0x52, 0x71, 0x0c, 0x14, 0x73, 0xce, 0x21, 0xaf,
- 0x0d, 0x58, 0xe9, 0xc4, 0x30, 0x52, 0x71, 0x0c, 0x14, 0x9c, 0x43, 0x05,
- 0x00, 0xda, 0x08, 0x6a, 0x93, 0x88, 0x60, 0xa4, 0xe2, 0x18, 0x29, 0x38,
- 0x86, 0x0a, 0x4e, 0x21, 0x82, 0xa4, 0xfa, 0x22, 0x1a, 0xf8, 0xd0, 0x86,
- 0xaa, 0x59, 0x8b, 0x5b, 0x42, 0x02, 0x09, 0xc3, 0x58, 0xc8, 0x5e, 0x6f,
- 0x08, 0xde, 0xe1, 0x12, 0xf0, 0xa6, 0x8f, 0x3e, 0x8a, 0x11, 0x3a, 0x86,
- 0xd9, 0xd2, 0xbf, 0x08, 0x96, 0x85, 0x30, 0x0e, 0xca, 0x30, 0x7e, 0x34,
- 0x7a, 0x1a, 0x42, 0x86, 0x57, 0x48, 0x4b, 0x86, 0xfb, 0x1c, 0x5c, 0x62,
- 0xa0, 0x48, 0x44, 0xdf, 0xa0, 0x53, 0x9c, 0x4e, 0x21, 0x82, 0x31, 0x39,
- 0x7b, 0xcf, 0x27, 0x4e, 0x21, 0x82, 0xf9, 0xf7, 0x6d, 0x2f, 0x10, 0xc2,
- 0xf3, 0x8f, 0x17, 0x88, 0x61, 0x68, 0xce, 0xd1, 0x9d, 0xa4, 0xbf, 0x95,
- 0x78, 0xc2, 0xba, 0x33, 0xf7, 0x4c, 0xa7, 0xcb, 0x5e, 0x32, 0x43, 0x58,
- 0xa9, 0x3d, 0x26, 0x33, 0xbc, 0xe5, 0xb2, 0xc5, 0xfc, 0xe1, 0x8f, 0x53,
- 0xb2, 0xc5, 0x40, 0xf3, 0x7e, 0x3b, 0x77, 0x49, 0x58, 0xb9, 0xbb, 0x58,
- 0xbe, 0x83, 0xfc, 0x4b, 0x17, 0xd3, 0x1d, 0x3e, 0x58, 0xbc, 0xfd, 0x02,
- 0xeb, 0x17, 0xa7, 0x09, 0x62, 0xfd, 0x27, 0x6e, 0xfc, 0xb1, 0x5a, 0x3c,
- 0x4e, 0x0d, 0xdc, 0xe1, 0x16, 0x28, 0x6d, 0x90, 0x9e, 0xe3, 0x1d, 0xd6,
- 0x0a, 0x31, 0x36, 0x9c, 0x8b, 0xe3, 0x2c, 0x30, 0x44, 0x7e, 0x25, 0x0d,
- 0x9c, 0x21, 0x15, 0xc3, 0x82, 0xc5, 0xff, 0xb3, 0x76, 0xf3, 0x9e, 0x42,
- 0x71, 0x62, 0xbe, 0x7b, 0x20, 0x18, 0xbd, 0x13, 0x18, 0xb1, 0x7d, 0x90,
- 0x93, 0x56, 0x28, 0x67, 0xc9, 0x84, 0x44, 0x3f, 0x7e, 0x72, 0x13, 0x79,
- 0x62, 0xff, 0xff, 0xd9, 0x84, 0x2f, 0x3f, 0xc8, 0x46, 0x96, 0x77, 0xe9,
- 0xcd, 0x2c, 0x56, 0x22, 0xff, 0x85, 0xb1, 0xc4, 0xf7, 0xbe, 0x2d, 0xd6,
- 0x2f, 0xbf, 0x9d, 0x31, 0x62, 0xbe, 0x78, 0x7e, 0x1f, 0xbc, 0x01, 0x71,
- 0x62, 0xff, 0x31, 0x19, 0x14, 0x1c, 0x96, 0x2f, 0xfe, 0xe3, 0x10, 0x3f,
- 0x91, 0x49, 0x0d, 0x62, 0xe0, 0x4a, 0xc5, 0xfd, 0xa6, 0x23, 0x24, 0x0b,
- 0x17, 0x36, 0x96, 0x2c, 0xeb, 0x1b, 0x96, 0xf6, 0xdd, 0x62, 0xc7, 0x58,
- 0xb4, 0x63, 0xa2, 0x8b, 0x42, 0xff, 0x45, 0x62, 0x13, 0x04, 0xef, 0xee,
- 0xe1, 0xf9, 0x2d, 0x96, 0x28, 0xe9, 0xce, 0x00, 0xd2, 0x3a, 0x1c, 0xc1,
- 0x14, 0xaf, 0xf7, 0xbf, 0x2f, 0x3d, 0xf9, 0x62, 0xff, 0xff, 0xa1, 0xf9,
- 0xfb, 0x9a, 0xce, 0x53, 0xf6, 0x78, 0x38, 0xd6, 0x2f, 0xef, 0xe3, 0xfc,
- 0xec, 0xb1, 0x58, 0x89, 0x1e, 0x8c, 0x97, 0x43, 0x16, 0x2f, 0xc5, 0x3f,
- 0xda, 0x56, 0x2c, 0x75, 0x8b, 0xf9, 0xf5, 0xbb, 0x6b, 0x65, 0x8b, 0xef,
- 0xc8, 0x82, 0xeb, 0x17, 0xc1, 0x27, 0xbe, 0x2c, 0x56, 0xe7, 0x9a, 0x10,
- 0x9e, 0xfc, 0x2f, 0x7f, 0x3a, 0x2c, 0x50, 0x55, 0x1b, 0xf1, 0x09, 0x69,
- 0xf4, 0x89, 0x6d, 0xb2, 0xc5, 0xbe, 0xb1, 0x6d, 0x39, 0xa5, 0x10, 0x9d,
- 0xff, 0xcf, 0xd7, 0xec, 0xfc, 0x98, 0x41, 0x96, 0x2f, 0xe3, 0xe4, 0x52,
- 0x5b, 0x2c, 0x5f, 0xfd, 0x39, 0xa2, 0xcf, 0x71, 0x9b, 0x65, 0x8a, 0x93,
- 0xf2, 0x22, 0xfa, 0x58, 0xb8, 0x7d, 0x16, 0x2f, 0xf4, 0x50, 0x9e, 0xf6,
- 0xc0, 0xd6, 0x2f, 0xd8, 0x7d, 0x34, 0x16, 0x2f, 0xa3, 0xa6, 0x63, 0xd6,
- 0x2b, 0x15, 0x08, 0xe9, 0x98, 0xe4, 0xdf, 0x85, 0xb8, 0x08, 0x08, 0x33,
- 0x83, 0x51, 0xc7, 0x06, 0x14, 0x5f, 0x1f, 0xf2, 0x05, 0x8b, 0xff, 0xd8,
- 0x38, 0xed, 0x4f, 0x47, 0xf7, 0x30, 0xd5, 0x8b, 0xfb, 0x73, 0x00, 0x09,
- 0xed, 0x62, 0xff, 0xdb, 0x79, 0xb7, 0x29, 0x87, 0x31, 0x62, 0xa4, 0xfc,
- 0x9c, 0xca, 0xb1, 0x30, 0x5f, 0x91, 0xf2, 0x18, 0x57, 0xff, 0x75, 0x6d,
- 0xc7, 0xf9, 0x06, 0x10, 0x16, 0x2f, 0xfd, 0x9c, 0xc1, 0x05, 0xd8, 0xdf,
- 0xe2, 0xc5, 0xc0, 0x95, 0x8a, 0xc4, 0x50, 0xee, 0x8e, 0x04, 0x3a, 0x96,
- 0x46, 0x74, 0x08, 0xb2, 0x3b, 0xae, 0xd2, 0x1e, 0x18, 0xb1, 0x12, 0x7c,
- 0x5c, 0x12, 0xc6, 0x3d, 0x1c, 0x60, 0xa1, 0xad, 0x7e, 0x86, 0x0d, 0x8e,
- 0xb1, 0x7e, 0x81, 0x09, 0x8c, 0x58, 0xbe, 0x98, 0x72, 0x56, 0x2f, 0xfe,
- 0x22, 0x9d, 0x8b, 0x1f, 0xa4, 0xc7, 0x2c, 0x5e, 0x9e, 0xf8, 0xb1, 0x52,
- 0x8d, 0x87, 0x28, 0x39, 0x4b, 0x11, 0x71, 0x1e, 0xf3, 0x6a, 0x56, 0x2f,
- 0x9b, 0x4c, 0x4b, 0x17, 0xd1, 0xcc, 0x40, 0x58, 0xbe, 0xf7, 0x33, 0xcb,
- 0x14, 0xe7, 0x90, 0xc4, 0xb7, 0xe7, 0xef, 0x8d, 0xda, 0xc5, 0x41, 0x19,
- 0xe3, 0x1c, 0x3b, 0x4f, 0x08, 0x29, 0x62, 0xf1, 0xe5, 0xd6, 0x28, 0x8d,
- 0x47, 0x40, 0xcb, 0xf4, 0x4e, 0x76, 0x89, 0x62, 0xff, 0xde, 0xfb, 0x40,
- 0x9b, 0xf9, 0xc5, 0x8b, 0x8e, 0xcb, 0x17, 0xff, 0xe2, 0x6f, 0x16, 0x7b,
- 0xe2, 0xef, 0x0e, 0xdd, 0xac, 0x56, 0x22, 0xad, 0xcf, 0x98, 0x5e, 0xfc,
- 0x42, 0x6e, 0xe0, 0xb1, 0x7c, 0xc6, 0x3e, 0x2c, 0x5b, 0x8e, 0x79, 0x62,
- 0x29, 0xbf, 0x9f, 0x69, 0xef, 0x09, 0x62, 0xfc, 0xfd, 0xf3, 0xab, 0xf6,
- 0x7a, 0xba, 0x27, 0xbf, 0xef, 0xcb, 0xfd, 0xb9, 0x31, 0xeb, 0x17, 0xfc,
- 0x63, 0x0f, 0x98, 0x79, 0x8f, 0x58, 0xbd, 0x9d, 0x86, 0xb1, 0x5a, 0x3d,
- 0xc2, 0x3d, 0xbf, 0xd9, 0x85, 0x03, 0x08, 0x6b, 0x17, 0x70, 0xd5, 0x8b,
- 0x0d, 0x62, 0xfc, 0xc0, 0xe4, 0x5d, 0x16, 0x29, 0x8d, 0xf1, 0x09, 0x58,
- 0x1d, 0x53, 0x61, 0xc8, 0x4b, 0xc4, 0x42, 0x03, 0x3f, 0x2b, 0xdf, 0xfe,
- 0x78, 0xf1, 0x1a, 0xfd, 0xf3, 0x22, 0x9f, 0x2c, 0x5a, 0x3d, 0x62, 0xf8,
- 0x04, 0xf2, 0xb1, 0x5b, 0xaa, 0x81, 0xee, 0x3a, 0x33, 0xac, 0x32, 0x81,
- 0x0a, 0xd2, 0xc5, 0xdf, 0x65, 0x8b, 0xff, 0x37, 0xf0, 0xed, 0xfc, 0xec,
- 0x0b, 0x17, 0xfd, 0xfc, 0x3b, 0x7f, 0x3b, 0x02, 0xc5, 0x81, 0xd4, 0xfe,
- 0x58, 0xfe, 0xa5, 0x17, 0x2d, 0x09, 0x0b, 0x85, 0x2b, 0x17, 0xb3, 0x50,
- 0x58, 0xa1, 0x9b, 0x4e, 0x82, 0xf7, 0x86, 0xc4, 0xb1, 0x4e, 0x6f, 0xd8,
- 0x8e, 0xfb, 0x76, 0x23, 0x56, 0x2f, 0xd8, 0x43, 0xfc, 0xac, 0x5f, 0xff,
- 0xf7, 0xb0, 0xa7, 0x72, 0x93, 0xf3, 0x99, 0x0f, 0xb9, 0x01, 0x62, 0xba,
- 0xa2, 0x33, 0x44, 0xf5, 0x28, 0xd5, 0x68, 0x58, 0x5f, 0xfc, 0xda, 0xd3,
- 0x02, 0x63, 0x03, 0x0c, 0x35, 0x8b, 0xd0, 0x70, 0x2c, 0x5f, 0xf8, 0xdc,
- 0xef, 0xcf, 0xed, 0x08, 0xeb, 0x15, 0xd5, 0x15, 0x4c, 0x97, 0xe1, 0xdb,
- 0xa6, 0x0b, 0x15, 0x27, 0x90, 0x03, 0x1a, 0x96, 0x44, 0x3e, 0x32, 0xb9,
- 0x17, 0xe1, 0xaa, 0xd2, 0xd3, 0x82, 0xea, 0x45, 0x0c, 0x5e, 0x42, 0x67,
- 0xd0, 0xf4, 0x14, 0x63, 0x17, 0xf6, 0xec, 0x2d, 0xce, 0xeb, 0x17, 0xf6,
- 0x4f, 0x70, 0x73, 0xac, 0x5f, 0xb2, 0x28, 0x31, 0x2c, 0x5e, 0x28, 0x73,
- 0x47, 0xac, 0x61, 0x75, 0xf1, 0x4e, 0x69, 0x62, 0x96, 0x2e, 0x1e, 0x7c,
- 0xd6, 0xf8, 0x86, 0xf1, 0xfe, 0xcb, 0x14, 0xe8, 0xaa, 0x66, 0x11, 0x16,
- 0x5f, 0xfc, 0x58, 0xff, 0x9e, 0xc1, 0x9e, 0xe2, 0xc5, 0xff, 0xc2, 0x32,
- 0x2e, 0xb2, 0x63, 0x6f, 0x3f, 0x58, 0xb8, 0x8d, 0x58, 0xbf, 0xf8, 0x0d,
- 0x0e, 0x64, 0x3f, 0x24, 0x6a, 0xc5, 0xfc, 0x7e, 0x61, 0xe6, 0x3d, 0x62,
- 0xa4, 0xfd, 0x9d, 0x16, 0xff, 0x39, 0xbc, 0x72, 0xee, 0x0b, 0x16, 0x9d,
- 0x1e, 0xaf, 0xc8, 0x29, 0xd3, 0x0a, 0x09, 0x0e, 0x3a, 0xea, 0xfb, 0x4d,
- 0xe1, 0x55, 0x59, 0x97, 0x05, 0xb4, 0xa1, 0xa8, 0x4b, 0x65, 0x1c, 0xe4,
- 0x0e, 0x4a, 0x40, 0x36, 0x1e, 0x7b, 0xce, 0x96, 0x77, 0x2b, 0xc9, 0xe7,
- 0xc4, 0xe3, 0xe5, 0x01, 0x45, 0x1d, 0x6e, 0xa5, 0x1b, 0x1e, 0x54, 0x57,
- 0xe7, 0x3d, 0xda, 0xb2, 0x74, 0x04, 0xa2, 0x72, 0xa4, 0xa1, 0xf2, 0x38,
- 0x3f, 0x52, 0x67, 0x45, 0x0a, 0xfe, 0x91, 0x98, 0x47, 0x17, 0x18, 0x88,
- 0x12, 0x35, 0x5b, 0xfe, 0xe7, 0xbe, 0x26, 0x84, 0x25, 0x62, 0xf0, 0x36,
- 0xc5, 0x8b, 0xfd, 0xa9, 0xf3, 0x82, 0x60, 0xb1, 0x7f, 0xbb, 0xcf, 0x3f,
- 0xdc, 0xd5, 0x8b, 0xfd, 0xe8, 0x08, 0x6c, 0x40, 0x58, 0xbc, 0x7e, 0x6e,
- 0xb1, 0x78, 0xb7, 0x95, 0x8b, 0xec, 0xf3, 0x76, 0xb1, 0x5d, 0x4f, 0x7d,
- 0xc7, 0xf4, 0x3b, 0x7f, 0xf7, 0x33, 0x71, 0xe6, 0x83, 0x6f, 0xc4, 0xb1,
- 0x7f, 0xdc, 0x35, 0x8a, 0x73, 0x69, 0x58, 0xbe, 0x86, 0x6a, 0x56, 0x2f,
- 0xe0, 0xdb, 0x5a, 0x6e, 0xd6, 0x2f, 0xff, 0xdc, 0xd6, 0x9e, 0x2e, 0x6a,
- 0x7c, 0xfb, 0xb8, 0xd6, 0x2a, 0x0a, 0x95, 0xb0, 0xcf, 0x73, 0x53, 0xc2,
- 0x4f, 0xe6, 0x0c, 0x90, 0x03, 0x92, 0x22, 0x0c, 0xc2, 0xfe, 0x91, 0xb8,
- 0x72, 0x75, 0x8b, 0xc4, 0xf1, 0x2c, 0x5d, 0x0d, 0x96, 0x2f, 0xd3, 0x1d,
- 0xc1, 0x12, 0xc5, 0xef, 0x4f, 0x16, 0x2f, 0xb0, 0xf3, 0xf5, 0x8b, 0x12,
- 0xc5, 0xf8, 0x79, 0x80, 0xe2, 0xc5, 0x47, 0x1b, 0x93, 0x04, 0x6b, 0x74,
- 0x40, 0x01, 0x6e, 0xff, 0xdc, 0xea, 0xdb, 0xcc, 0x42, 0x6e, 0xd6, 0x2b,
- 0xb4, 0xd2, 0x62, 0x19, 0x39, 0x59, 0x42, 0x77, 0xc4, 0x97, 0xb6, 0x71,
- 0xac, 0x5f, 0xcc, 0xda, 0xd4, 0xec, 0xb1, 0x61, 0x2c, 0x58, 0x0e, 0x7b,
- 0xdf, 0x1e, 0x22, 0xeb, 0xc0, 0xf7, 0x16, 0x2c, 0x15, 0x58, 0xbf, 0xb9,
- 0xf8, 0xa4, 0x02, 0x58, 0xbe, 0xd3, 0x91, 0xab, 0x17, 0x7b, 0x8b, 0x17,
- 0xec, 0x2c, 0xec, 0x35, 0x8b, 0xf0, 0xb7, 0xfb, 0xe9, 0x62, 0xe7, 0x89,
- 0x62, 0xec, 0x35, 0x62, 0xde, 0x0a, 0xa2, 0x0e, 0x4a, 0x7e, 0x55, 0xc1,
- 0x8b, 0xf6, 0xff, 0x9e, 0xe0, 0xb1, 0x78, 0x7f, 0x75, 0x8a, 0xc3, 0xc8,
- 0x72, 0xbb, 0xf8, 0xfc, 0x73, 0x7c, 0x1a, 0xc5, 0xf7, 0x7f, 0x98, 0x2c,
- 0x5c, 0x5b, 0xac, 0x54, 0x9b, 0xc6, 0x24, 0xae, 0xaa, 0x97, 0x23, 0x61,
- 0xee, 0xc5, 0xb4, 0x60, 0x02, 0x32, 0x84, 0xdf, 0xa1, 0x1c, 0x61, 0x00,
- 0x46, 0xdb, 0xff, 0xf3, 0x96, 0xfb, 0xfd, 0xb7, 0xfc, 0xbe, 0x85, 0x1e,
- 0xb1, 0x7d, 0xef, 0x66, 0xcb, 0x16, 0x95, 0x8a, 0xc3, 0x6a, 0xe4, 0x97,
- 0xfd, 0x3c, 0xe6, 0x7b, 0x99, 0xb2, 0xc5, 0xbb, 0x23, 0xd9, 0x30, 0x7e,
- 0xfe, 0x9e, 0xe1, 0x81, 0x20, 0xb1, 0x58, 0x7b, 0x47, 0x29, 0xbf, 0xfc,
- 0xc7, 0xc1, 0xf7, 0xed, 0x4e, 0x76, 0x75, 0x8b, 0xbb, 0xf2, 0xc5, 0xfb,
- 0x0b, 0x67, 0xd2, 0xc5, 0xfb, 0xcc, 0x42, 0xc5, 0x8b, 0xfd, 0xcc, 0x3b,
- 0xfb, 0xec, 0xb1, 0x50, 0x47, 0x3e, 0x26, 0x68, 0x64, 0x8a, 0x3c, 0x4f,
- 0x7f, 0x48, 0xbd, 0xf6, 0x02, 0xc5, 0xef, 0xc8, 0xd6, 0x2b, 0x47, 0x97,
- 0xc2, 0xeb, 0xe8, 0x68, 0x84, 0xb1, 0x50, 0x3c, 0x5e, 0xc8, 0xaf, 0xf1,
- 0x64, 0x50, 0x11, 0x79, 0x62, 0xa5, 0x32, 0xf6, 0x86, 0xc7, 0x08, 0xef,
- 0x75, 0x3b, 0xac, 0x5f, 0x6a, 0x7d, 0xc5, 0x8b, 0xc2, 0xc2, 0x58, 0xb6,
- 0x44, 0x6f, 0xfc, 0x47, 0x7e, 0xfb, 0x94, 0x9d, 0x62, 0xc7, 0x58, 0xac,
- 0x37, 0x24, 0x4f, 0x50, 0x46, 0xe9, 0x2f, 0x71, 0x82, 0xf0, 0x4d, 0x4a,
- 0xc5, 0xff, 0x8a, 0x5b, 0x6e, 0x67, 0x49, 0x0d, 0x62, 0xff, 0xbe, 0xfa,
- 0xfb, 0x05, 0x43, 0x0d, 0x62, 0xff, 0xbd, 0xa9, 0xce, 0xc2, 0xd6, 0x36,
- 0x0a, 0xac, 0x5f, 0xfe, 0x26, 0x0f, 0x85, 0x9d, 0xc3, 0xc2, 0xd9, 0x62,
- 0xfe, 0x78, 0x8b, 0x3a, 0x32, 0xc5, 0xdc, 0x75, 0x8a, 0xd1, 0xe3, 0x70,
- 0xbe, 0xfb, 0x76, 0xdd, 0x96, 0x2f, 0xf6, 0x14, 0x33, 0x8d, 0xf5, 0x8b,
- 0xff, 0xda, 0x34, 0x36, 0xd8, 0xb3, 0xa6, 0x9f, 0x8b, 0x16, 0xe7, 0x55,
- 0x4e, 0x92, 0x5e, 0x31, 0xfc, 0x41, 0xed, 0x02, 0x24, 0xbd, 0x42, 0x4d,
- 0x88, 0xbc, 0x48, 0x61, 0x95, 0xa5, 0x62, 0xf7, 0xfe, 0xeb, 0x17, 0xec,
- 0x1f, 0xf0, 0x96, 0x2d, 0xad, 0x8f, 0x55, 0x84, 0x48, 0x76, 0xf8, 0xfa,
- 0x73, 0x56, 0x2f, 0x10, 0xb1, 0x62, 0x9c, 0xf0, 0x18, 0x92, 0xf8, 0x71,
- 0xa0, 0x54, 0x28, 0xb1, 0x7b, 0x92, 0x75, 0x8a, 0x8f, 0x3c, 0xee, 0x18,
- 0xdf, 0x4c, 0x53, 0xa5, 0x8a, 0x19, 0xe4, 0x78, 0x96, 0xff, 0xff, 0xa2,
- 0xe6, 0x0f, 0x3b, 0xf7, 0xda, 0x26, 0x6d, 0x78, 0x4c, 0xb1, 0x5d, 0xaa,
- 0xa4, 0x68, 0x77, 0x81, 0xd0, 0xa1, 0x6d, 0xe2, 0x2b, 0xe1, 0xfc, 0x41,
- 0x16, 0x2f, 0xf8, 0x46, 0xe1, 0x0b, 0xc2, 0x35, 0x62, 0xfe, 0x6d, 0xbf,
- 0x3a, 0x02, 0xc5, 0xf4, 0x38, 0xe3, 0x58, 0xa9, 0x3d, 0x26, 0x2f, 0xaf,
- 0xa2, 0xb8, 0xa1, 0x1d, 0x7f, 0x9f, 0x45, 0xef, 0x66, 0xcb, 0x17, 0xde,
- 0xdb, 0x03, 0x58, 0xbd, 0x1d, 0x80, 0x58, 0xb9, 0xba, 0x2c, 0x5f, 0xd0,
- 0x27, 0x87, 0xf1, 0x62, 0xfd, 0xb3, 0xea, 0x60, 0xb1, 0x46, 0xa3, 0xa3,
- 0xb3, 0x47, 0x25, 0x88, 0x83, 0x43, 0x24, 0x5b, 0x7f, 0xc5, 0x39, 0xcc,
- 0x23, 0x0e, 0xb1, 0x78, 0x98, 0x35, 0x8a, 0x81, 0xea, 0xf0, 0xe2, 0xf7,
- 0x9c, 0xd5, 0x8b, 0xfc, 0xcd, 0xb6, 0xa5, 0xb7, 0x58, 0xbf, 0x0b, 0xd1,
- 0xd9, 0xe5, 0x8b, 0xc3, 0x73, 0x56, 0x2a, 0x4f, 0x2b, 0x0b, 0x2f, 0xe6,
- 0xf9, 0x9a, 0x60, 0x2c, 0x5e, 0xd0, 0x0c, 0x58, 0xbf, 0xf9, 0xfd, 0x3e,
- 0xe7, 0xd9, 0xfe, 0x25, 0x8a, 0x93, 0xe3, 0x61, 0xfb, 0xe2, 0x21, 0x41,
- 0x62, 0xf7, 0x1c, 0x35, 0x8b, 0xfc, 0x42, 0xe6, 0x1e, 0x77, 0x58, 0xbf,
- 0xf7, 0xe7, 0x40, 0x2c, 0x0d, 0x80, 0xb1, 0x7b, 0x32, 0x25, 0x8b, 0xff,
- 0x79, 0x81, 0xc1, 0x89, 0xb5, 0x05, 0x8a, 0x35, 0x1a, 0x1f, 0x34, 0x01,
- 0xff, 0x87, 0x6f, 0xbc, 0x09, 0x82, 0xc5, 0x61, 0xf0, 0x88, 0xfa, 0xff,
- 0xdf, 0x17, 0x8c, 0xf7, 0xb0, 0x80, 0xb1, 0x7a, 0x7b, 0x0d, 0x62, 0xfd,
- 0xa1, 0x1d, 0x89, 0x62, 0xb1, 0x11, 0x1e, 0x41, 0x10, 0xfd, 0xf7, 0x0a,
- 0x4e, 0xb1, 0x7c, 0x79, 0xcd, 0x96, 0x2f, 0xba, 0x14, 0xf6, 0xb1, 0x70,
- 0x7e, 0x58, 0xac, 0x37, 0xce, 0x4b, 0x52, 0x8a, 0x27, 0x22, 0xe3, 0x0d,
- 0xf4, 0x97, 0xb7, 0x58, 0xbe, 0x37, 0x66, 0x8f, 0x58, 0xbe, 0x8a, 0x0c,
- 0x75, 0x8a, 0xd1, 0xe6, 0x1c, 0xa2, 0xba, 0xaf, 0xe5, 0x0e, 0x1a, 0x99,
- 0x18, 0x7f, 0x70, 0xad, 0x72, 0x28, 0x87, 0xb4, 0xfc, 0x72, 0x0f, 0xc2,
- 0x49, 0x88, 0x00, 0x44, 0x51, 0xa7, 0xf2, 0x15, 0x3e, 0x86, 0x8c, 0x71,
- 0x71, 0x8d, 0xf6, 0x0b, 0xac, 0x5f, 0xa3, 0xbf, 0x80, 0x65, 0x8b, 0xfc,
- 0x03, 0x30, 0x87, 0xf9, 0x58, 0xa9, 0x4d, 0xe9, 0xe3, 0x05, 0x38, 0xb3,
- 0x15, 0xdd, 0x02, 0x58, 0xbe, 0x3b, 0xfe, 0x56, 0x2f, 0x4e, 0x80, 0xb1,
- 0x6e, 0x61, 0xbf, 0x30, 0x8a, 0xf7, 0x70, 0xe2, 0xc5, 0xfd, 0xf6, 0xf0,
- 0x79, 0xf5, 0x8a, 0xec, 0xfd, 0x74, 0x4e, 0x18, 0xfd, 0xee, 0x00, 0x35,
- 0x8b, 0xee, 0xf9, 0x3d, 0xac, 0x5f, 0xa1, 0xee, 0x49, 0xab, 0x17, 0xff,
- 0x4e, 0xa6, 0x22, 0x60, 0xfd, 0x9f, 0x58, 0xa6, 0x3e, 0xf2, 0x2a, 0xbf,
- 0xfb, 0xf8, 0x52, 0x0e, 0x7e, 0x4b, 0xcb, 0x16, 0x83, 0xa3, 0xdc, 0xf0,
- 0x94, 0xf1, 0x05, 0x75, 0x54, 0x99, 0x30, 0xcb, 0xc3, 0x16, 0x8c, 0x5a,
- 0xff, 0x83, 0x2c, 0xd7, 0x3f, 0x9b, 0xac, 0x5f, 0xfc, 0x59, 0xcc, 0x1c,
- 0x50, 0x9d, 0x6c, 0xb1, 0x4e, 0x88, 0x1f, 0x1d, 0xdf, 0xc6, 0xf8, 0xa4,
- 0xfc, 0x58, 0xbe, 0xc1, 0xb9, 0x2c, 0x5e, 0x3c, 0xf1, 0x62, 0xfd, 0x9e,
- 0x26, 0x02, 0xc5, 0x00, 0xf1, 0x08, 0x76, 0xf8, 0x46, 0xe6, 0xcb, 0x17,
- 0x9b, 0x50, 0x58, 0xaf, 0x9e, 0x10, 0x89, 0x6f, 0xa4, 0x41, 0x7e, 0x24,
- 0x5f, 0xa1, 0x18, 0x18, 0x61, 0xac, 0x51, 0x1e, 0xb8, 0x89, 0xef, 0xa1,
- 0xe7, 0x02, 0xc5, 0xfc, 0xcf, 0xcf, 0xe7, 0x96, 0x2f, 0xd1, 0xcd, 0xb7,
- 0xdd, 0x62, 0xfc, 0x4d, 0xb4, 0xf9, 0x62, 0xff, 0x68, 0xb0, 0x64, 0xdb,
- 0x2c, 0x5f, 0x7b, 0x9d, 0x7c, 0xb1, 0x6f, 0xb9, 0xec, 0xb1, 0x9d, 0xff,
- 0xf7, 0xdc, 0xd3, 0x67, 0xdc, 0x92, 0x2c, 0xf2, 0xc5, 0xf1, 0x61, 0xe5,
- 0x62, 0xff, 0x4f, 0x98, 0x0d, 0x9a, 0x58, 0xb7, 0x96, 0x2f, 0xfc, 0xfc,
- 0x7e, 0x9a, 0x93, 0x18, 0x96, 0x2b, 0x0f, 0x49, 0x84, 0xaf, 0xf7, 0xd8,
- 0xfe, 0xe4, 0xe2, 0xc5, 0xe7, 0xec, 0x0b, 0x17, 0xf1, 0x30, 0x03, 0xcf,
- 0xac, 0x5f, 0xef, 0x16, 0x01, 0x88, 0x1a, 0x3c, 0xcf, 0x0f, 0x5c, 0x5b,
- 0xf5, 0x55, 0x5f, 0x25, 0x99, 0x08, 0x1d, 0xc9, 0x9d, 0x40, 0xe4, 0x3f,
- 0x84, 0x27, 0x88, 0x0c, 0x7f, 0xbd, 0xe3, 0xf9, 0x62, 0xfc, 0x27, 0x27,
- 0xe2, 0xc5, 0x31, 0xe2, 0xf0, 0x7a, 0xfd, 0xcd, 0x4b, 0x6e, 0xb1, 0x7e,
- 0x92, 0xde, 0x7a, 0x2c, 0x56, 0x1e, 0x9f, 0xca, 0x6b, 0xaa, 0xee, 0x94,
- 0x19, 0x46, 0xc7, 0x8f, 0x3d, 0x90, 0xfc, 0x8d, 0xa5, 0x6e, 0x02, 0x1b,
- 0x9e, 0x74, 0xbf, 0xc0, 0x2c, 0xe9, 0xa7, 0xe2, 0xc5, 0xce, 0x35, 0x8b,
- 0xf8, 0x89, 0x83, 0x6f, 0xac, 0x56, 0xe7, 0x88, 0x60, 0xbd, 0x75, 0x74,
- 0xcf, 0x21, 0x53, 0xa9, 0x94, 0xe9, 0xb4, 0x21, 0x20, 0x5d, 0x91, 0xb3,
- 0x77, 0x0a, 0xf7, 0x95, 0x1f, 0x1f, 0x09, 0x4d, 0x46, 0x86, 0x79, 0x46,
- 0xed, 0x3c, 0x52, 0x0a, 0x4c, 0xc9, 0x4a, 0x8d, 0xe4, 0x32, 0xbc, 0x44,
- 0x29, 0xe0, 0x1e, 0x90, 0x8e, 0x0d, 0xe6, 0xf8, 0x06, 0x48, 0x16, 0x2f,
- 0xfc, 0x36, 0x87, 0xd8, 0x02, 0x68, 0x2c, 0x5e, 0x8d, 0xc2, 0xc0, 0xaa,
- 0xc5, 0xe8, 0x13, 0x2c, 0x5f, 0xef, 0x49, 0xfb, 0x86, 0x79, 0x62, 0xf7,
- 0xdc, 0x0b, 0x17, 0xff, 0x6c, 0xd1, 0xfb, 0xfd, 0xf7, 0x9f, 0x71, 0x62,
- 0xa3, 0x74, 0x72, 0xc9, 0x66, 0x0e, 0x44, 0x6b, 0xc1, 0xdb, 0xf3, 0x43,
- 0xd9, 0xba, 0xc5, 0x4a, 0x77, 0xf8, 0x49, 0xdc, 0x64, 0x9a, 0x4e, 0xb9,
- 0xc2, 0x2c, 0x5f, 0x82, 0x4c, 0x35, 0x2b, 0x17, 0xfe, 0xee, 0x2f, 0x7e,
- 0x7d, 0xcf, 0xba, 0xc5, 0xef, 0xb9, 0xd6, 0x2e, 0x60, 0x2c, 0x54, 0x9f,
- 0xb3, 0x21, 0x78, 0x76, 0xfd, 0xad, 0xa7, 0x5b, 0x2c, 0x5f, 0xd9, 0xee,
- 0x08, 0xbc, 0xb1, 0x7e, 0x72, 0xf1, 0x87, 0x58, 0xbc, 0xda, 0xe2, 0xc5,
- 0x4a, 0x27, 0xf0, 0xac, 0x05, 0xde, 0x29, 0xbf, 0xf4, 0x97, 0xbe, 0x26,
- 0x84, 0x25, 0x62, 0xf6, 0x85, 0x1e, 0xb1, 0x73, 0xc4, 0xb1, 0x78, 0x81,
- 0xc5, 0x8a, 0x73, 0xd6, 0x22, 0x13, 0x06, 0x2d, 0xb2, 0xc5, 0xf1, 0xdf,
- 0xd1, 0xa2, 0xc5, 0xf4, 0xfd, 0xcd, 0x58, 0xac, 0x3c, 0xbd, 0x14, 0x5f,
- 0xe3, 0x3c, 0xe5, 0x3d, 0xc1, 0x62, 0xd8, 0xb1, 0x50, 0x3c, 0x6e, 0x86,
- 0xb7, 0xfe, 0xce, 0xfc, 0x6b, 0x70, 0xc9, 0x1a, 0xc5, 0x6c, 0x9a, 0xc9,
- 0xa5, 0xdb, 0xaf, 0x69, 0x9c, 0xc2, 0x4b, 0xff, 0x0c, 0x9f, 0x7f, 0xcf,
- 0x7c, 0x75, 0x8b, 0xe1, 0x14, 0xf4, 0x58, 0xbe, 0x67, 0x20, 0x2c, 0x7c,
- 0xd2, 0x5c, 0xdb, 0xac, 0x5c, 0x60, 0xd6, 0x2b, 0x47, 0xc5, 0xf3, 0x12,
- 0x18, 0xbf, 0xfe, 0x3b, 0xf3, 0x7f, 0xbf, 0x7e, 0xc3, 0xb7, 0x16, 0x2f,
- 0xdc, 0x2e, 0x4f, 0xd6, 0x2e, 0x2d, 0xd6, 0x2d, 0x12, 0xc5, 0x81, 0x86,
- 0xad, 0x86, 0x29, 0xd1, 0x94, 0xca, 0x42, 0x53, 0xbd, 0xa9, 0x89, 0x62,
- 0xff, 0x60, 0x7f, 0x0d, 0x8c, 0x3a, 0xc5, 0xcd, 0x12, 0xc5, 0x6c, 0x79,
- 0xe4, 0x6f, 0x7e, 0xe0, 0x6d, 0xdf, 0x16, 0x29, 0xcf, 0x35, 0x88, 0xaf,
- 0xf1, 0xf4, 0xfc, 0x92, 0xd9, 0x62, 0xff, 0xa4, 0xdf, 0xb7, 0x8c, 0xc0,
- 0x2c, 0x53, 0x1f, 0x79, 0x1a, 0x5f, 0xf7, 0x27, 0xe4, 0xe7, 0x9e, 0x2c,
- 0x5e, 0xe6, 0xb1, 0x62, 0xf1, 0x64, 0x16, 0x2f, 0xda, 0x01, 0x08, 0x0b,
- 0x15, 0x27, 0x8b, 0x83, 0x94, 0xe8, 0x82, 0xe3, 0x15, 0xa3, 0xd6, 0x2f,
- 0xec, 0x32, 0x62, 0x7e, 0x2c, 0x51, 0x1e, 0x27, 0x85, 0x6a, 0x59, 0x0f,
- 0x3b, 0x42, 0x82, 0x10, 0xcc, 0x19, 0xde, 0x47, 0xdb, 0xda, 0x7c, 0x50,
- 0xc6, 0xd4, 0x3e, 0x0e, 0x5d, 0xf8, 0x5d, 0x14, 0x23, 0xf8, 0x41, 0xe8,
- 0x5d, 0x74, 0x66, 0xbf, 0xe9, 0x7f, 0xc9, 0xf6, 0xc0, 0xd6, 0x2f, 0xfd,
- 0xc9, 0x71, 0x94, 0xc1, 0xc0, 0xb1, 0x7e, 0xfb, 0xec, 0xc4, 0xb1, 0x70,
- 0xdd, 0x62, 0xf7, 0xde, 0x25, 0x8b, 0xb5, 0xb2, 0xc5, 0xf1, 0xac, 0x40,
- 0x58, 0xac, 0x37, 0x82, 0x19, 0xbb, 0xee, 0xb1, 0x52, 0x8d, 0x0c, 0x28,
- 0x88, 0x5f, 0xeb, 0x41, 0x08, 0x2f, 0xfb, 0x62, 0xc8, 0x7f, 0x01, 0xc5,
- 0x8b, 0xf8, 0xde, 0x39, 0x77, 0x05, 0x8b, 0xe1, 0x93, 0x06, 0xb1, 0x7f,
- 0xff, 0x38, 0x88, 0xdd, 0xfe, 0xfb, 0xfe, 0x7b, 0x0d, 0xb4, 0xb1, 0x7a,
- 0x4b, 0x7e, 0xa8, 0x83, 0xf1, 0x1d, 0xff, 0x3f, 0xe7, 0xb0, 0x67, 0xb8,
- 0xb1, 0x78, 0x52, 0x05, 0x8b, 0xf6, 0x17, 0x70, 0xe6, 0x1e, 0xbe, 0x8e,
- 0xaf, 0x73, 0x0d, 0x58, 0xb9, 0x8e, 0xb1, 0x5e, 0x36, 0xbd, 0x07, 0xaf,
- 0xfd, 0xe1, 0x7a, 0x21, 0x6c, 0x77, 0xf2, 0xc5, 0x61, 0xf3, 0x39, 0x1d,
- 0xfb, 0xbd, 0x6a, 0x7b, 0x58, 0xbe, 0xdc, 0xe0, 0x95, 0x8b, 0xfa, 0x19,
- 0xce, 0x38, 0xd6, 0x2d, 0x0e, 0xa7, 0xa5, 0xe2, 0x4a, 0x95, 0x5c, 0x1b,
- 0x42, 0xcd, 0xe1, 0x1a, 0x78, 0x6c, 0x88, 0x80, 0xc7, 0xdb, 0xff, 0xfd,
- 0xf1, 0x17, 0x8b, 0x3b, 0x03, 0x7b, 0x8e, 0x5d, 0xc1, 0x62, 0xfe, 0xd8,
- 0x5e, 0x13, 0x18, 0xb1, 0x76, 0x6e, 0xb1, 0x4b, 0x1e, 0x2e, 0x2f, 0xda,
- 0xf8, 0x6c, 0x3c, 0x3e, 0x4e, 0x89, 0x37, 0xd8, 0x79, 0xdd, 0x62, 0xfa,
- 0x7d, 0x87, 0x58, 0xbc, 0xcd, 0xda, 0xc5, 0xf4, 0x1b, 0xdc, 0x58, 0xa1,
- 0x9e, 0x04, 0x43, 0xb5, 0xba, 0x21, 0x7c, 0xc5, 0x4c, 0x98, 0x68, 0x10,
- 0x4a, 0x15, 0x17, 0x87, 0x3d, 0x16, 0x2f, 0xff, 0xbc, 0x6c, 0x94, 0x38,
- 0x59, 0xef, 0x30, 0x16, 0x2f, 0xff, 0xed, 0x34, 0x3e, 0xc4, 0x39, 0xef,
- 0x5a, 0x93, 0xf1, 0x62, 0xa0, 0x8a, 0xcd, 0x28, 0x5f, 0x1b, 0x85, 0x05,
- 0x8b, 0xfc, 0x2d, 0x8e, 0x4c, 0x6b, 0xac, 0x56, 0x1e, 0xc3, 0x91, 0xdf,
- 0x6b, 0xd9, 0xb2, 0xc5, 0xff, 0xf8, 0xd6, 0xeb, 0x87, 0x7f, 0x75, 0xf7,
- 0x09, 0xcd, 0x58, 0xba, 0x62, 0x58, 0xbf, 0xf8, 0xa4, 0x31, 0x94, 0xf7,
- 0x07, 0x25, 0x8a, 0x35, 0x16, 0xfa, 0x5b, 0x21, 0x8b, 0xf1, 0xf3, 0xec,
- 0x11, 0x62, 0xa5, 0x33, 0x5c, 0x86, 0xdb, 0x98, 0x5f, 0xbb, 0xdd, 0xfd,
- 0xc5, 0x8b, 0xff, 0x45, 0x09, 0xd6, 0xdd, 0x43, 0xcf, 0xac, 0x5f, 0xef,
- 0xbf, 0xca, 0x73, 0x4b, 0x17, 0xe9, 0xe9, 0xa3, 0x38, 0xb1, 0x5d, 0x51,
- 0x47, 0xba, 0x2f, 0xcc, 0xaa, 0x53, 0x01, 0x68, 0x67, 0x54, 0xae, 0x15,
- 0x0c, 0xd1, 0xe1, 0x97, 0xa7, 0xbf, 0xc6, 0xaa, 0x51, 0x9a, 0x5f, 0xdd,
- 0x22, 0xfb, 0x90, 0xd6, 0x2f, 0xe2, 0x60, 0x02, 0x78, 0xb1, 0x52, 0x7b,
- 0xcc, 0x63, 0x7f, 0xbf, 0x9e, 0xc1, 0x6b, 0x65, 0x8b, 0xff, 0xfc, 0xfb,
- 0xff, 0x3a, 0xfe, 0x7a, 0xf1, 0xe3, 0x27, 0x76, 0x31, 0x62, 0xf8, 0x84,
- 0xde, 0x58, 0xbe, 0xef, 0x77, 0xed, 0x62, 0xb6, 0x4c, 0x1c, 0xe4, 0x1f,
- 0x35, 0x03, 0x57, 0x08, 0xaf, 0xf1, 0x4c, 0x22, 0xfc, 0xec, 0xb1, 0x76,
- 0xee, 0xb1, 0x7f, 0xce, 0x51, 0x4e, 0xfa, 0xce, 0xd6, 0x29, 0x8f, 0x4f,
- 0x83, 0x14, 0x34, 0x54, 0xfa, 0x11, 0x17, 0xe1, 0x9a, 0x68, 0xbb, 0x58,
- 0xa6, 0x3d, 0x51, 0x14, 0x5f, 0xfb, 0xb2, 0x32, 0x4f, 0x9f, 0xc2, 0x58,
- 0xa3, 0x4f, 0x81, 0x88, 0x6f, 0xfa, 0x7d, 0x9a, 0xdd, 0x9b, 0x75, 0x45,
- 0xf0, 0x5f, 0xcc, 0xe3, 0x9f, 0x71, 0x62, 0xff, 0xff, 0x79, 0xf3, 0xb1,
- 0xfc, 0x5c, 0xcd, 0xfa, 0xfd, 0xf0, 0xeb, 0x17, 0xda, 0x9e, 0xe0, 0xb1,
- 0x7f, 0xf6, 0x1c, 0x50, 0x61, 0xe6, 0xf3, 0xc5, 0x8a, 0xc3, 0xe9, 0xf9,
- 0x25, 0xd2, 0x7d, 0xd3, 0x63, 0xfa, 0x3f, 0x0b, 0x7d, 0x0c, 0xeb, 0xfe,
- 0x63, 0x78, 0xfc, 0x7e, 0xfc, 0xb1, 0x5f, 0x44, 0x51, 0x27, 0xdf, 0xff,
- 0x6f, 0xd7, 0xf2, 0xfa, 0x73, 0xbc, 0x74, 0x9d, 0x62, 0xfe, 0xe7, 0x72,
- 0x53, 0xc5, 0x8a, 0x24, 0x41, 0x86, 0xab, 0x79, 0xb5, 0xb2, 0xa2, 0xff,
- 0x2f, 0xe2, 0xdf, 0x9c, 0xc8, 0xf5, 0x8b, 0xff, 0x10, 0x03, 0xce, 0xfd,
- 0xe9, 0x3a, 0xc5, 0x49, 0xf9, 0xe1, 0x95, 0xff, 0x8b, 0xda, 0xc9, 0xee,
- 0x0e, 0x75, 0x8b, 0xd9, 0xb0, 0x45, 0x8b, 0xfb, 0x3b, 0x06, 0x7b, 0x8b,
- 0x17, 0xe9, 0x2e, 0xe1, 0xc5, 0x8f, 0x9a, 0xfa, 0x95, 0x49, 0xb9, 0x0a,
- 0x5d, 0xc8, 0xff, 0x09, 0xe6, 0x20, 0x23, 0xf1, 0x27, 0xdf, 0xfa, 0x41,
- 0xc2, 0xcd, 0xb0, 0xc3, 0xac, 0x5e, 0xf3, 0x86, 0xb1, 0x7f, 0x36, 0xc6,
- 0x0d, 0xa3, 0xd6, 0x2b, 0x11, 0x23, 0xe4, 0x01, 0x0f, 0x5f, 0xed, 0x6b,
- 0x22, 0x3c, 0xf1, 0x62, 0xff, 0x8b, 0x72, 0xcf, 0xfc, 0x44, 0xb1, 0x7f,
- 0xbd, 0xc7, 0x2e, 0xe0, 0x75, 0x8a, 0x93, 0xee, 0x63, 0x9b, 0xfe, 0x7d,
- 0x6c, 0x20, 0x02, 0x7c, 0xb1, 0x7f, 0xd3, 0x9a, 0xeb, 0x07, 0xee, 0x0b,
- 0x15, 0x04, 0xda, 0x70, 0xbc, 0x10, 0xa3, 0xe1, 0x07, 0x8e, 0xef, 0x8f,
- 0xae, 0xd9, 0x62, 0xff, 0xd3, 0xa8, 0x39, 0x61, 0xcc, 0x95, 0x8b, 0xd9,
- 0x80, 0x58, 0xbd, 0x20, 0x8f, 0x58, 0xbf, 0xfc, 0xd0, 0x9f, 0x3f, 0xe4,
- 0x51, 0xe4, 0x35, 0x8a, 0xdc, 0xfb, 0x34, 0x41, 0x7f, 0xff, 0xbe, 0xdc,
- 0x79, 0xe7, 0x5f, 0x7f, 0x0f, 0x9b, 0xb6, 0x96, 0x2f, 0x98, 0x85, 0x8b,
- 0x14, 0xb1, 0x69, 0x01, 0xad, 0x08, 0x43, 0x7f, 0x1f, 0xab, 0x9b, 0x83,
- 0x58, 0xbf, 0xe9, 0xee, 0x1f, 0x7d, 0x34, 0x16, 0x2f, 0x71, 0x8e, 0xb1,
- 0x58, 0x88, 0x82, 0x31, 0xe1, 0xd5, 0x62, 0xa7, 0xbd, 0xc9, 0x22, 0x3e,
- 0xd4, 0x22, 0x3e, 0x46, 0x08, 0x48, 0x7a, 0x16, 0x17, 0xc7, 0x29, 0x89,
- 0x62, 0xff, 0x77, 0xe3, 0x3f, 0xfc, 0x8f, 0x58, 0xbd, 0x39, 0xc5, 0x8b,
- 0xf6, 0x3e, 0xd2, 0x6a, 0xc5, 0x4a, 0x28, 0xb0, 0x8f, 0x47, 0x5f, 0x1c,
- 0xbf, 0x03, 0x91, 0xd3, 0xe5, 0x8b, 0xec, 0xd1, 0x91, 0x2c, 0x56, 0xc8,
- 0x8c, 0xc3, 0xbd, 0x16, 0x5e, 0x1b, 0xc4, 0xb1, 0x7f, 0xbd, 0x3d, 0xf0,
- 0xa7, 0xa2, 0xc5, 0x80, 0xb1, 0x7d, 0x09, 0x2f, 0x2c, 0x5f, 0x8e, 0x77,
- 0x30, 0xeb, 0x16, 0xf6, 0x1e, 0x63, 0x91, 0x56, 0xc8, 0xd8, 0xec, 0x7b,
- 0x46, 0xc4, 0xbd, 0x7d, 0xdc, 0x3c, 0xcb, 0x17, 0xff, 0xb7, 0xfb, 0x96,
- 0x74, 0x68, 0x71, 0xc6, 0xb1, 0x7f, 0xa0, 0x58, 0x73, 0xb4, 0x16, 0x2f,
- 0x9f, 0x77, 0x1a, 0xc5, 0xda, 0x97, 0x3d, 0x6f, 0x19, 0xd0, 0xd1, 0x9d,
- 0xa8, 0x51, 0x5f, 0xdc, 0xf1, 0x4e, 0x76, 0xb1, 0x52, 0x9c, 0x36, 0x1f,
- 0x34, 0x3c, 0x84, 0x51, 0x7f, 0xfb, 0x39, 0xf6, 0x7f, 0x49, 0xc9, 0x8d,
- 0x58, 0xbc, 0xc5, 0xba, 0xc5, 0xf8, 0x1c, 0xf6, 0x7d, 0x62, 0xf8, 0x7f,
- 0x9e, 0xd6, 0x2f, 0xb3, 0xf0, 0xc5, 0x8b, 0x06, 0xe7, 0x8d, 0xe2, 0x4b,
- 0x62, 0xc5, 0x4a, 0x2a, 0x19, 0xbf, 0xc5, 0x17, 0xd2, 0x64, 0x5c, 0x58,
- 0xa9, 0x5c, 0x2f, 0x84, 0xa8, 0xec, 0x40, 0x89, 0x24, 0xa1, 0x8b, 0xc2,
- 0xeb, 0xff, 0x00, 0xef, 0x9d, 0xf8, 0x72, 0x35, 0x8b, 0xfd, 0xf9, 0xee,
- 0x07, 0x36, 0x56, 0x2f, 0xff, 0xee, 0x92, 0x5e, 0xc8, 0x7e, 0x7b, 0x87,
- 0xb9, 0x3a, 0x58, 0xa5, 0x8b, 0xfb, 0xa8, 0xf3, 0x01, 0xc5, 0x8b, 0xff,
- 0xf7, 0xb3, 0x5b, 0x3f, 0x1f, 0xa7, 0xdf, 0x3b, 0xf2, 0xc5, 0x76, 0x89,
- 0x53, 0x86, 0x11, 0x85, 0xfe, 0x2f, 0x70, 0x43, 0xfb, 0xac, 0x54, 0x9f,
- 0x26, 0x18, 0x5c, 0xdd, 0xac, 0x5f, 0x75, 0x0c, 0xbc, 0xb1, 0x77, 0x30,
- 0xe6, 0xf8, 0x86, 0x2f, 0xec, 0xfb, 0xeb, 0xec, 0xb1, 0x76, 0xb6, 0x58,
- 0xad, 0x8f, 0x18, 0xe5, 0xb5, 0x88, 0x94, 0x77, 0x1b, 0xfe, 0x9e, 0x72,
- 0x5f, 0x66, 0xf2, 0xc5, 0xf9, 0x8f, 0x23, 0x95, 0x8a, 0xf1, 0xf0, 0x08,
- 0xe6, 0xfe, 0x2f, 0x86, 0xc5, 0x05, 0x8b, 0xfe, 0x7c, 0x21, 0x9a, 0xf9,
- 0xa5, 0x8a, 0x95, 0x79, 0x03, 0x40, 0xc3, 0x67, 0x8d, 0x5f, 0x50, 0xf2,
- 0xf4, 0x20, 0x44, 0x44, 0x10, 0xba, 0xfe, 0xdb, 0xab, 0x1b, 0xf7, 0x58,
- 0xbf, 0x7a, 0x47, 0x9d, 0x16, 0x2b, 0x0f, 0x72, 0x23, 0x2b, 0xfe, 0xe6,
- 0x6d, 0xc7, 0x26, 0xd9, 0x62, 0xff, 0xd9, 0xdc, 0x1c, 0x8f, 0x23, 0x95,
- 0x8b, 0xb3, 0xb5, 0x8b, 0xff, 0xff, 0x4e, 0xdd, 0xc3, 0x85, 0x91, 0x75,
- 0xdf, 0xf3, 0xb9, 0xba, 0x60, 0xd6, 0x2a, 0x53, 0x28, 0xc2, 0x27, 0x3a,
- 0xf1, 0xf0, 0x86, 0x2f, 0xe6, 0xd7, 0x70, 0xcf, 0x2c, 0x5f, 0xe6, 0xc3,
- 0x33, 0x3b, 0xf2, 0xc5, 0xff, 0x71, 0xf5, 0xe2, 0x13, 0x41, 0x62, 0x80,
- 0x7d, 0xbe, 0x34, 0xbf, 0xff, 0x3f, 0x30, 0x7f, 0xcf, 0x3e, 0x73, 0x6c,
- 0x0d, 0x62, 0xff, 0xf8, 0xbd, 0xbf, 0xdc, 0x3e, 0x16, 0x00, 0x5c, 0x58,
- 0xbf, 0x63, 0xc7, 0x38, 0xd6, 0x2f, 0xfe, 0x98, 0xec, 0x11, 0x66, 0x74,
- 0x9e, 0xd6, 0x2a, 0x51, 0x88, 0x35, 0x23, 0x95, 0x5f, 0xf4, 0xe8, 0x1e,
- 0x73, 0x70, 0x96, 0x2f, 0x73, 0x09, 0x62, 0xff, 0xff, 0x9c, 0x80, 0x3c,
- 0xef, 0x8e, 0x2d, 0xfe, 0xfe, 0xe3, 0x8d, 0x62, 0xfb, 0x83, 0xc2, 0x58,
- 0xa0, 0x22, 0x9b, 0x83, 0x9e, 0x68, 0xbf, 0xf4, 0xe6, 0xb3, 0x40, 0x3b,
- 0xf1, 0x62, 0xfb, 0xdc, 0x06, 0xeb, 0x17, 0x9b, 0xb0, 0x8b, 0x17, 0xf3,
- 0x7b, 0x93, 0x9b, 0x2c, 0x54, 0xab, 0xc7, 0xc8, 0x4e, 0x6e, 0x44, 0xf1,
- 0x8d, 0x7c, 0xbd, 0xa1, 0xbe, 0x46, 0x02, 0x3e, 0xe8, 0x4a, 0x19, 0x05,
- 0xfc, 0x5f, 0xc0, 0x49, 0x2c, 0x5f, 0x80, 0xdd, 0xc3, 0x16, 0x2f, 0xf6,
- 0x17, 0xb2, 0x29, 0x8f, 0x58, 0xbf, 0xfb, 0x59, 0xd3, 0x07, 0xa9, 0xdd,
- 0xb4, 0xb1, 0x7f, 0xa4, 0x36, 0xd6, 0x9c, 0x0b, 0x17, 0xf3, 0x6f, 0xf3,
- 0xc8, 0xd6, 0x2f, 0x60, 0x07, 0xf3, 0xe3, 0x63, 0x4a, 0x94, 0xce, 0xce,
- 0x52, 0xc6, 0xc0, 0x85, 0x55, 0xff, 0x0a, 0x4f, 0xcc, 0x3c, 0xc7, 0xac,
- 0x5f, 0xfb, 0x5b, 0x60, 0xf3, 0xff, 0xc8, 0xf5, 0x8b, 0x1a, 0xb1, 0x7f,
- 0xbd, 0xc3, 0x3a, 0x4e, 0x76, 0xb1, 0x52, 0x79, 0x64, 0x27, 0x7f, 0xed,
- 0x70, 0xe6, 0x66, 0x9e, 0x62, 0x58, 0xac, 0x3e, 0x11, 0x10, 0x58, 0x6b,
- 0x17, 0xbf, 0x84, 0xb1, 0x79, 0x8b, 0x6e, 0x1a, 0xef, 0x09, 0x56, 0x26,
- 0xe1, 0xc8, 0x77, 0x86, 0x9f, 0x7d, 0xef, 0xe1, 0x2c, 0x5f, 0xe2, 0xcf,
- 0x7b, 0x35, 0x12, 0xc5, 0xfd, 0xc6, 0x81, 0x49, 0xd6, 0x2f, 0x14, 0xc7,
- 0xac, 0x5f, 0xff, 0x42, 0x75, 0xb7, 0x9c, 0xde, 0x71, 0x8a, 0x0b, 0x17,
- 0xf6, 0xdc, 0xc3, 0xcc, 0x7a, 0xc5, 0x44, 0x88, 0x43, 0x14, 0xab, 0x13,
- 0x4b, 0x88, 0x8b, 0x46, 0x9c, 0x2d, 0x0e, 0x14, 0x77, 0xf1, 0x37, 0x70,
- 0xcf, 0x2c, 0x5d, 0xf7, 0x58, 0xbf, 0xb0, 0x12, 0x03, 0x0e, 0xb1, 0x68,
- 0x96, 0x2c, 0x19, 0x1e, 0x17, 0x0b, 0xeb, 0x64, 0x57, 0xb9, 0x71, 0x2c,
- 0xdf, 0xec, 0x3b, 0x10, 0xff, 0x2b, 0x17, 0xc3, 0xf6, 0x74, 0x58, 0xa1,
- 0x9e, 0xbf, 0xcc, 0xaf, 0xff, 0x84, 0xda, 0x84, 0x76, 0x14, 0x80, 0xed,
- 0x05, 0x8b, 0xff, 0xa1, 0xf9, 0x1f, 0xb3, 0x0b, 0xdc, 0x58, 0xb8, 0x70,
- 0x58, 0xbf, 0x67, 0xbe, 0xfe, 0x58, 0xbf, 0xd8, 0x31, 0x7b, 0x90, 0x0b,
- 0xac, 0x5d, 0x90, 0x58, 0xaf, 0x9e, 0x81, 0x1c, 0xdf, 0xff, 0xfc, 0x59,
- 0xd1, 0xa1, 0x85, 0xdc, 0x27, 0x36, 0x16, 0xcf, 0xa9, 0x3a, 0xc5, 0xa1,
- 0x29, 0xee, 0x8c, 0x8b, 0x14, 0xb4, 0x89, 0xf1, 0x8f, 0x3c, 0x18, 0x43,
- 0x7c, 0x7f, 0x3e, 0xcb, 0x15, 0x88, 0x8e, 0x76, 0xab, 0xff, 0xba, 0x78,
- 0xd9, 0x28, 0x67, 0xdc, 0xeb, 0x17, 0x6d, 0xe5, 0x8b, 0xfd, 0xd3, 0xed,
- 0x09, 0xc2, 0x58, 0xbf, 0xf8, 0x18, 0x5b, 0xfd, 0xe2, 0x66, 0x82, 0xc5,
- 0x4a, 0x24, 0xb0, 0x65, 0x8d, 0x2f, 0xa0, 0xda, 0x82, 0xc5, 0xff, 0xe9,
- 0xd3, 0x78, 0x5e, 0x7f, 0x73, 0xee, 0xb1, 0x68, 0x44, 0x7d, 0xbf, 0x23,
- 0xa5, 0x8b, 0xe3, 0x3e, 0xde, 0x58, 0xb6, 0x70, 0xd8, 0x06, 0x19, 0x7f,
- 0x40, 0xfe, 0x21, 0x44, 0xb1, 0x7f, 0xfc, 0x64, 0x27, 0xa3, 0x90, 0x34,
- 0xf2, 0x7c, 0x48, 0xad, 0x22, 0x07, 0xc6, 0x17, 0xdf, 0x33, 0xbf, 0x2c,
- 0x5f, 0x1f, 0x1f, 0xa2, 0xc5, 0xfb, 0xcd, 0xbf, 0x20, 0xb1, 0x58, 0x79,
- 0xc1, 0x92, 0x5d, 0x14, 0x7a, 0xc5, 0xf7, 0x7e, 0xcf, 0xac, 0x56, 0xc7,
- 0x80, 0x43, 0x96, 0x0d, 0x62, 0xa5, 0x51, 0x7e, 0xcb, 0x39, 0x0a, 0x8d,
- 0xc8, 0xdd, 0xd0, 0x4c, 0x51, 0xc4, 0x57, 0xed, 0x8e, 0x4c, 0x6a, 0xc5,
- 0xde, 0xc5, 0x8b, 0xfc, 0x0e, 0x61, 0x4f, 0x7c, 0x58, 0xbf, 0x69, 0xf6,
- 0x63, 0xaa, 0x61, 0x32, 0xfb, 0xc2, 0x96, 0x54, 0xc2, 0x65, 0xc0, 0x95,
- 0x50, 0x26, 0x5f, 0xe2, 0x63, 0x7d, 0x3a, 0x02, 0xa8, 0x13, 0x2f, 0xf7,
- 0x33, 0xef, 0xc1, 0x6c, 0xa9, 0x84, 0xcb, 0xb0, 0x6a, 0x98, 0x4c, 0xb8,
- 0x30, 0xd7, 0x30, 0x99, 0x58, 0x9a, 0xbf, 0x66, 0xce, 0x5e, 0x72, 0x4e,
- 0x20, 0xf4, 0x42, 0x0c, 0x92, 0xde, 0x4c, 0xc2, 0x62, 0x30, 0xf9, 0xeb,
- 0xb5, 0x47, 0xba, 0x17, 0x0e, 0x3f, 0x2b, 0xc3, 0x11, 0x2c, 0x5b, 0x75,
- 0x8b, 0xf7, 0x3c, 0x59, 0x05, 0x8a, 0xc3, 0xd8, 0xd0, 0xe8, 0x04, 0xeb,
- 0x15, 0x93, 0xbc, 0xa6, 0x76, 0x84, 0x95, 0xff, 0xf8, 0x07, 0x68, 0x73,
- 0xf3, 0xd3, 0x0c, 0x1b, 0x41, 0x62, 0xa5, 0x97, 0xb8, 0xf1, 0x80, 0x7e,
- 0x57, 0x8b, 0x10, 0x94, 0x36, 0x79, 0x2b, 0x27, 0xd2, 0xe5, 0x04, 0x77,
- 0x7f, 0xfd, 0x81, 0xfd, 0x9f, 0xd3, 0xe1, 0x03, 0x09, 0x62, 0xff, 0xd0,
- 0x26, 0x36, 0x28, 0x3e, 0xa0, 0xb1, 0x7f, 0xcc, 0x69, 0x64, 0x50, 0x9e,
- 0xd6, 0x2b, 0x47, 0xf8, 0x48, 0x37, 0xff, 0x8a, 0x43, 0xf1, 0xad, 0xcc,
- 0xc2, 0x35, 0x62, 0xfc, 0x7e, 0xe0, 0xe4, 0xb1, 0x71, 0x0f, 0x0f, 0xd3,
- 0xc9, 0x77, 0xcd, 0xd3, 0x03, 0x58, 0xb0, 0x51, 0x62, 0xff, 0xf9, 0xa1,
- 0xf9, 0x97, 0xf7, 0x1c, 0xbb, 0x82, 0xc5, 0x40, 0xf9, 0x7e, 0x2d, 0x7b,
- 0x1b, 0x8b, 0x17, 0xa2, 0x9e, 0x2c, 0x5e, 0x20, 0x1d, 0x62, 0xff, 0xd1,
- 0x38, 0x79, 0xa7, 0xd9, 0x8e, 0xb1, 0x7f, 0xd2, 0x2f, 0x13, 0xf4, 0x30,
- 0xeb, 0x17, 0xfd, 0x9e, 0x7c, 0xe6, 0xd8, 0x1a, 0xc5, 0xd2, 0x75, 0x8b,
- 0xe1, 0x8e, 0x60, 0x82, 0x2b, 0xb3, 0x9d, 0x53, 0x4d, 0x91, 0xcc, 0x1e,
- 0x71, 0xdd, 0x20, 0xfc, 0xf2, 0x38, 0xe8, 0xc1, 0x7b, 0xff, 0xcd, 0x0f,
- 0xcf, 0x43, 0x0e, 0xcd, 0xad, 0xd6, 0x2a, 0x57, 0x14, 0xf2, 0x19, 0x6f,
- 0x09, 0x5d, 0x16, 0x34, 0x22, 0x8a, 0x36, 0xf1, 0x42, 0x02, 0xfb, 0xed,
- 0xc8, 0xf5, 0x8b, 0xed, 0xca, 0x74, 0xb1, 0x73, 0xf4, 0xea, 0x79, 0x38,
- 0x4d, 0x7f, 0x78, 0x4d, 0xce, 0x79, 0x62, 0xfd, 0xc9, 0xc0, 0x4a, 0xc5,
- 0xc5, 0x9d, 0x9e, 0xb7, 0x8b, 0xee, 0x6d, 0x2c, 0x58, 0x1f, 0x3c, 0x46,
- 0x2d, 0xbf, 0xef, 0xc9, 0x87, 0xce, 0x8f, 0xba, 0xc5, 0x62, 0x65, 0xcd,
- 0x0c, 0xae, 0x13, 0xde, 0x7d, 0x1a, 0xb1, 0x76, 0x80, 0xb1, 0x58, 0x6d,
- 0x9c, 0x7a, 0xed, 0xb4, 0xb1, 0x70, 0x22, 0x58, 0xbf, 0xf8, 0xf1, 0x41,
- 0x8b, 0x61, 0xc9, 0x6c, 0xb1, 0x52, 0x7f, 0x23, 0x19, 0xc1, 0x9b, 0xe8,
- 0xbe, 0xfa, 0x58, 0xbd, 0xf7, 0xd2, 0xc5, 0xfb, 0xcf, 0xf9, 0xe7, 0x53,
- 0xc1, 0x88, 0x92, 0xf6, 0x72, 0x0b, 0x17, 0xcf, 0xf6, 0x3a, 0xc5, 0xf6,
- 0xa7, 0x9b, 0x2c, 0x53, 0xa2, 0x93, 0x48, 0x3e, 0x1d, 0x30, 0x8a, 0xa5,
- 0xf0, 0x43, 0x36, 0x96, 0x35, 0x06, 0x81, 0xce, 0xfe, 0xe4, 0x79, 0xa6,
- 0xc7, 0x55, 0xbc, 0xe2, 0xe7, 0x72, 0x99, 0xde, 0x56, 0x54, 0x53, 0xba,
- 0x7a, 0x9c, 0x2c, 0x3c, 0xa0, 0x6f, 0xce, 0x07, 0xb4, 0x27, 0x01, 0x1b,
- 0x39, 0x20, 0xf2, 0x3a, 0xcf, 0x53, 0x57, 0x7a, 0x4e, 0x72, 0x07, 0x1f,
- 0x9c, 0x73, 0x51, 0x90, 0x98, 0x09, 0x18, 0x95, 0xfb, 0xcf, 0xdb, 0x12,
- 0xc5, 0xe3, 0xfb, 0x8b, 0x17, 0xda, 0xe9, 0x83, 0x58, 0xb8, 0xc0, 0x8b,
- 0x15, 0x28, 0x86, 0xd8, 0xa1, 0x87, 0x80, 0x4b, 0x76, 0x12, 0xc5, 0xde,
- 0xe2, 0xc5, 0x49, 0xae, 0x21, 0x6b, 0xff, 0xb3, 0xf9, 0xee, 0xf7, 0x7d,
- 0x7f, 0x16, 0x2f, 0xe7, 0xd1, 0x4f, 0x70, 0x58, 0xbb, 0x38, 0xb1, 0x7f,
- 0xee, 0x66, 0xbc, 0x4c, 0x69, 0xb8, 0xb1, 0x50, 0x47, 0x50, 0xc7, 0xf1,
- 0x18, 0x05, 0xdc, 0x17, 0xbf, 0xf1, 0x60, 0x1b, 0x59, 0xd3, 0x06, 0xb1,
- 0x7e, 0x8a, 0x12, 0x5e, 0x58, 0xbf, 0xf6, 0xb3, 0x9c, 0x11, 0x18, 0x79,
- 0x58, 0xa8, 0x1f, 0x4e, 0x8a, 0x6f, 0xec, 0x81, 0x09, 0xb8, 0xb1, 0x7d,
- 0xdf, 0x1e, 0x56, 0x2f, 0xf6, 0x10, 0x4f, 0x39, 0x1a, 0xb1, 0x46, 0xa6,
- 0x9f, 0xdc, 0x2a, 0x34, 0x45, 0xf2, 0xd0, 0x11, 0xdf, 0x66, 0x9c, 0xd5,
- 0x8b, 0xc1, 0xec, 0x75, 0x8b, 0xf7, 0x34, 0x29, 0x02, 0xc5, 0xf6, 0x0c,
- 0x7b, 0x2c, 0x5f, 0xff, 0x74, 0xd6, 0x6d, 0xd4, 0x53, 0x9e, 0x9e, 0xe0,
- 0xb1, 0x7b, 0x42, 0x1a, 0xc5, 0xfe, 0x93, 0x93, 0x43, 0x3e, 0xb1, 0x5a,
- 0x3d, 0x0f, 0x8f, 0x54, 0xa7, 0x54, 0x35, 0x2c, 0x23, 0xec, 0x80, 0xe5,
- 0x2c, 0x49, 0xc8, 0x53, 0x5f, 0xa4, 0xc2, 0xec, 0x0b, 0x17, 0xfb, 0xf2,
- 0x69, 0x9f, 0x6f, 0x2c, 0x57, 0xcf, 0x83, 0xc5, 0x57, 0x60, 0x45, 0x8b,
- 0x8c, 0xe2, 0xc5, 0xfb, 0xc1, 0xe1, 0x6c, 0xb1, 0x69, 0xf9, 0xe1, 0x90,
- 0xcd, 0x46, 0x88, 0x82, 0x82, 0xe5, 0x83, 0x58, 0xa5, 0x8b, 0x66, 0x17,
- 0xfd, 0x04, 0xee, 0x73, 0x56, 0x2f, 0xe1, 0x6d, 0x3e, 0x91, 0xac, 0x56,
- 0xc7, 0xda, 0xe4, 0xde, 0x18, 0xbf, 0x9e, 0x4b, 0xdf, 0xc5, 0x8b, 0xf7,
- 0xb2, 0x27, 0x3a, 0xc5, 0xfa, 0x7b, 0x00, 0x25, 0x62, 0xa4, 0xf4, 0x88,
- 0xa6, 0xff, 0xdd, 0x33, 0xdf, 0x93, 0x73, 0x58, 0xb1, 0x7a, 0x4b, 0xcb,
- 0x14, 0xc7, 0xbb, 0xd1, 0x06, 0xfd, 0xf9, 0x7e, 0x4a, 0xc5, 0x49, 0xe5,
- 0x31, 0x1d, 0xef, 0xb9, 0x8b, 0x17, 0xe7, 0xe9, 0xe7, 0xd9, 0x62, 0xfd,
- 0xef, 0xce, 0xa0, 0xb1, 0x7f, 0xec, 0x3c, 0x94, 0x80, 0xed, 0x05, 0x8b,
- 0xfe, 0x27, 0x36, 0x7d, 0xc7, 0xd2, 0xc5, 0xff, 0xef, 0x89, 0xa1, 0xdf,
- 0xb5, 0x39, 0xde, 0x2c, 0x51, 0xd1, 0x0b, 0xc3, 0x9b, 0xfd, 0x9b, 0x6f,
- 0xf9, 0xd7, 0x16, 0x2f, 0xa1, 0xec, 0xdd, 0x62, 0xb0, 0xff, 0x74, 0x46,
- 0xc6, 0xd7, 0x14, 0xac, 0x5f, 0xf7, 0xda, 0x13, 0x11, 0x49, 0xd6, 0x2f,
- 0xe1, 0xb7, 0xbe, 0xe1, 0xac, 0x5e, 0x33, 0x22, 0x58, 0xbf, 0x8e, 0x13,
- 0xcf, 0xad, 0xd6, 0x2c, 0x58, 0x7a, 0x2e, 0x3f, 0x7f, 0xd2, 0x7e, 0x78,
- 0x98, 0x1c, 0x58, 0xbf, 0xfe, 0xcf, 0xbc, 0x97, 0xb9, 0xe2, 0x60, 0x71,
- 0x62, 0xf7, 0x41, 0xcf, 0xd1, 0x0e, 0x47, 0x37, 0xfb, 0x39, 0xd4, 0x79,
- 0x84, 0xb1, 0x4e, 0x7d, 0x3f, 0x35, 0xbf, 0xb2, 0x11, 0x33, 0x6c, 0xb1,
- 0x7f, 0xfe, 0xcd, 0xc1, 0x27, 0xcf, 0x3f, 0x33, 0x08, 0xd5, 0x8b, 0xf8,
- 0xef, 0x27, 0x62, 0x58, 0xad, 0x22, 0xc3, 0xe5, 0xe0, 0x55, 0xbf, 0xf9,
- 0xce, 0x31, 0x36, 0xa1, 0x9d, 0xf9, 0x62, 0xc5, 0x87, 0xed, 0xb9, 0x85,
- 0xff, 0x98, 0x81, 0xdf, 0xb5, 0x38, 0x1a, 0xc5, 0xff, 0xb9, 0xf7, 0xeb,
- 0xdc, 0x27, 0x36, 0x58, 0xbf, 0x33, 0x8c, 0x52, 0xb1, 0x7d, 0xa7, 0x8b,
- 0x8b, 0x17, 0x60, 0xfa, 0x9e, 0x5e, 0x89, 0xee, 0xea, 0x11, 0x62, 0xd9,
- 0x1e, 0x98, 0xc8, 0x10, 0x3d, 0x08, 0xee, 0x85, 0xf7, 0xb0, 0x71, 0xcb,
- 0x17, 0xff, 0xfe, 0xf4, 0xe1, 0x77, 0xee, 0xb9, 0xc7, 0x20, 0x16, 0x7b,
- 0xf8, 0xb1, 0x7c, 0xf3, 0xdc, 0x16, 0x2f, 0x7d, 0x8f, 0xd5, 0x11, 0xff,
- 0x6c, 0xbf, 0xd8, 0x71, 0xb8, 0x05, 0x05, 0x8b, 0xef, 0xb3, 0x1d, 0x62,
- 0xf9, 0xbf, 0xf7, 0x58, 0xa2, 0x3c, 0x4e, 0x84, 0x57, 0xe2, 0x84, 0x73,
- 0x6c, 0xb1, 0x52, 0x79, 0xe6, 0x11, 0xd4, 0xab, 0x5b, 0x84, 0x68, 0x06,
- 0xa6, 0xbc, 0x2b, 0xfe, 0x6c, 0x08, 0x63, 0xdf, 0xff, 0xe7, 0xe8, 0x42,
- 0xe7, 0x53, 0x0a, 0x47, 0xf6, 0x86, 0x71, 0x62, 0xe3, 0x5d, 0x62, 0x96,
- 0x2b, 0x66, 0x51, 0xe0, 0xe1, 0x8e, 0x69, 0x06, 0xe3, 0xdd, 0x95, 0xc7,
- 0x94, 0xea, 0x33, 0xf3, 0x96, 0xfc, 0x59, 0x8e, 0x4a, 0x10, 0x1c, 0x8c,
- 0x57, 0xd3, 0x94, 0x5d, 0x1a, 0x23, 0x99, 0x42, 0x0c, 0x5f, 0xdc, 0x6c,
- 0x1b, 0xf4, 0x58, 0xbf, 0x7f, 0x35, 0x30, 0x58, 0xbf, 0xbb, 0x87, 0x3f,
- 0x9b, 0x2c, 0x50, 0xcf, 0x67, 0xe5, 0x17, 0xfc, 0xdf, 0x89, 0xcb, 0xf9,
- 0xda, 0xc5, 0x49, 0xee, 0x61, 0x15, 0xff, 0xe7, 0xe6, 0x7c, 0x5b, 0xf9,
- 0xfc, 0xfd, 0xac, 0x5d, 0xde, 0xcb, 0x16, 0x02, 0xc5, 0x08, 0xd6, 0x06,
- 0x35, 0x7f, 0xc0, 0xe7, 0xb3, 0x0b, 0xdc, 0x58, 0xbf, 0x45, 0x09, 0xf7,
- 0x16, 0x2f, 0xa7, 0x46, 0xca, 0xc5, 0xdc, 0x02, 0xc5, 0x75, 0x4c, 0xe3,
- 0xef, 0x0c, 0x44, 0x03, 0x9f, 0x15, 0x47, 0x11, 0xdf, 0xff, 0xff, 0x7f,
- 0x08, 0x18, 0x5e, 0xfe, 0x7e, 0x72, 0x27, 0xd4, 0x5f, 0x7e, 0xfc, 0xb1,
- 0x7f, 0xb6, 0xc2, 0xce, 0xc1, 0xc5, 0x8b, 0xec, 0x04, 0xf4, 0x58, 0xbf,
- 0xb4, 0xfb, 0xff, 0x22, 0x58, 0xbf, 0xfd, 0xf6, 0xea, 0x67, 0xbc, 0xf1,
- 0x3f, 0xc4, 0xb1, 0x7a, 0x1c, 0xc5, 0x8b, 0xff, 0xd9, 0x13, 0x03, 0x3d,
- 0x3d, 0x1c, 0x80, 0xb1, 0x5d, 0x51, 0x6e, 0xc9, 0xe4, 0x3b, 0x7f, 0xbc,
- 0xfb, 0x3f, 0x71, 0xd8, 0xb1, 0x5d, 0xa6, 0xe6, 0x72, 0x4f, 0x43, 0x9c,
- 0xc3, 0x0b, 0xfe, 0xc1, 0x0f, 0xac, 0xf2, 0x60, 0xb1, 0x7c, 0x5e, 0x7f,
- 0xac, 0x57, 0x53, 0xdd, 0x63, 0xba, 0xc5, 0x5d, 0x7a, 0x7e, 0x68, 0xea,
- 0x01, 0x0a, 0x2b, 0xd3, 0x81, 0xac, 0x5f, 0xe7, 0xe1, 0x4f, 0xa6, 0x0b,
- 0x16, 0x0b, 0xac, 0x51, 0x1f, 0x2f, 0x07, 0x7c, 0x65, 0x7d, 0x3d, 0xf1,
- 0x96, 0x2a, 0x37, 0x7e, 0x79, 0x29, 0xa4, 0x49, 0x6d, 0x0e, 0xe8, 0x1d,
- 0x0e, 0x30, 0xdc, 0xbc, 0x15, 0x7d, 0xe5, 0x26, 0xf7, 0x1a, 0xa3, 0xcb,
- 0x42, 0x8f, 0x86, 0x44, 0x50, 0xa4, 0xd4, 0x2d, 0x3e, 0x5e, 0xd4, 0xab,
- 0xa0, 0xbc, 0x60, 0xe5, 0x0e, 0x4f, 0x46, 0xb0, 0x29, 0x68, 0xfd, 0x21,
- 0x5a, 0x61, 0x75, 0xfe, 0x9f, 0x8b, 0xc4, 0xc6, 0xac, 0x5e, 0xce, 0x98,
- 0xb1, 0x7b, 0x9c, 0xe2, 0xc5, 0xff, 0xc5, 0xbf, 0xf3, 0x9e, 0xcc, 0x3f,
- 0x16, 0x2f, 0xff, 0x9c, 0xb0, 0xf2, 0x61, 0x0a, 0x05, 0x87, 0x58, 0xbf,
- 0xe2, 0xf7, 0xf2, 0x61, 0x3c, 0x58, 0xbe, 0xc3, 0x70, 0x6b, 0x15, 0x27,
- 0xb7, 0xf3, 0x8b, 0xf1, 0x0a, 0x19, 0xc5, 0x8b, 0xfe, 0xc1, 0xfe, 0x7d,
- 0xf9, 0xe2, 0xc5, 0xc3, 0x7c, 0x3e, 0x12, 0x28, 0xbf, 0xfc, 0xf3, 0xef,
- 0x89, 0x8f, 0x14, 0x27, 0x65, 0x8b, 0xf8, 0xb3, 0x5a, 0xce, 0xd6, 0x2b,
- 0xe7, 0xf5, 0xc4, 0xcb, 0xff, 0x37, 0x89, 0xb9, 0xf6, 0x07, 0x16, 0x2f,
- 0x9f, 0xf8, 0x75, 0x8b, 0xfa, 0x77, 0xff, 0x6d, 0x1e, 0xb1, 0x58, 0x7a,
- 0xba, 0x22, 0xbf, 0xff, 0x9b, 0xf3, 0x08, 0x38, 0x27, 0xef, 0xf9, 0x7d,
- 0x96, 0x2b, 0x64, 0xc3, 0xb5, 0x09, 0x3e, 0x84, 0x37, 0x8a, 0x78, 0xb1,
- 0x7d, 0x85, 0x87, 0x58, 0xbf, 0xf0, 0xa6, 0x2e, 0x49, 0x1e, 0x78, 0xb1,
- 0x4b, 0x15, 0x28, 0x88, 0x80, 0xe7, 0x08, 0x44, 0x7f, 0x7e, 0x13, 0x0c,
- 0xf2, 0xb1, 0x7f, 0x8d, 0xdb, 0x03, 0xce, 0xfc, 0xb1, 0x7f, 0xf8, 0xa7,
- 0x66, 0x1f, 0xe7, 0xe5, 0x86, 0xac, 0x56, 0x22, 0x09, 0xce, 0x2f, 0xf4,
- 0x99, 0xb9, 0x67, 0xf1, 0x62, 0xb7, 0x47, 0xfe, 0xa1, 0x55, 0xe2, 0x1b,
- 0xfe, 0xfb, 0xc3, 0xed, 0x07, 0x3a, 0xc5, 0xfe, 0x67, 0xd6, 0x9c, 0x3f,
- 0x2c, 0x5f, 0xef, 0x6f, 0xef, 0x34, 0x38, 0xb1, 0x7a, 0x42, 0xd4, 0x2d,
- 0xac, 0x57, 0x67, 0xc0, 0x46, 0xd7, 0xfe, 0xe3, 0x97, 0x70, 0xf3, 0xf1,
- 0xd6, 0x2b, 0x13, 0x2e, 0xf9, 0xcb, 0x42, 0x53, 0xc4, 0x57, 0xce, 0x4f,
- 0x12, 0xc5, 0xf8, 0x07, 0x9d, 0x3a, 0xc5, 0xfb, 0xdf, 0x91, 0x05, 0xd6,
- 0x2e, 0xfb, 0x2c, 0x54, 0x9f, 0x63, 0x14, 0x78, 0xb6, 0xff, 0xfd, 0x84,
- 0x6f, 0xdb, 0x37, 0x21, 0x7b, 0x84, 0x35, 0x8b, 0xff, 0x39, 0xf0, 0x7f,
- 0x7e, 0x16, 0x2c, 0x5f, 0x1e, 0x47, 0x2b, 0x14, 0xe8, 0xb5, 0x25, 0x6e,
- 0x1e, 0xd4, 0xb2, 0x21, 0x20, 0x8a, 0x38, 0x54, 0xe4, 0x20, 0xb7, 0x85,
- 0x2b, 0xc6, 0x61, 0x14, 0x30, 0x75, 0x19, 0xd9, 0xe3, 0x64, 0xfa, 0x09,
- 0x42, 0x3b, 0xd0, 0xe2, 0xbe, 0xfe, 0x01, 0x96, 0x2e, 0x8d, 0x47, 0x58,
- 0xbe, 0x29, 0xd4, 0x16, 0x2f, 0xfb, 0xf3, 0x07, 0x22, 0x17, 0x6b, 0x17,
- 0x6e, 0xeb, 0x17, 0xf8, 0x7f, 0x98, 0x84, 0x4e, 0xb1, 0x73, 0x18, 0xb1,
- 0x51, 0xe7, 0x99, 0xe3, 0x4b, 0xfe, 0x98, 0x3f, 0xa1, 0x24, 0x05, 0x8b,
- 0xfb, 0xc6, 0x00, 0x13, 0xda, 0xc5, 0xef, 0x4e, 0x96, 0x2d, 0x38, 0x79,
- 0xdd, 0x98, 0xdf, 0x7d, 0xc4, 0x17, 0x58, 0xbd, 0x84, 0x6a, 0xc5, 0xff,
- 0xdf, 0x6e, 0x14, 0x80, 0xc8, 0x0b, 0x4b, 0x14, 0x15, 0x54, 0x73, 0x23,
- 0xd8, 0x45, 0xb9, 0xcb, 0xb2, 0x68, 0x94, 0xf0, 0x86, 0xf9, 0x38, 0x5c,
- 0x9f, 0x83, 0xb7, 0xe9, 0xeb, 0x3e, 0xdd, 0x62, 0xb4, 0x8c, 0x32, 0x84,
- 0xc5, 0xfe, 0xd6, 0x41, 0xb4, 0xc6, 0x2c, 0x5f, 0xfb, 0xef, 0xf2, 0x9c,
- 0xd7, 0x5c, 0x58, 0xb1, 0x2c, 0x5f, 0xf4, 0xc7, 0x93, 0x7a, 0x0f, 0xd1,
- 0x62, 0xf7, 0xe4, 0x6b, 0x17, 0xf1, 0x4e, 0xfa, 0x98, 0x2c, 0x5f, 0xfe,
- 0x67, 0xf4, 0x04, 0x5e, 0xe7, 0xda, 0x0b, 0x06, 0x1a, 0xeb, 0xf0, 0xdc,
- 0x5a, 0x35, 0x62, 0xe9, 0xfa, 0xc5, 0xfe, 0xdc, 0xb3, 0xf8, 0xe1, 0xac,
- 0x53, 0xa6, 0x37, 0xf4, 0xb6, 0x5b, 0xe8, 0x54, 0x60, 0xbd, 0xff, 0xb8,
- 0x67, 0x9c, 0x85, 0x0c, 0xe2, 0xc5, 0xc3, 0xe2, 0xc5, 0x41, 0x3f, 0xc8,
- 0xf8, 0xd6, 0x3e, 0x98, 0x48, 0x17, 0xff, 0xf6, 0x77, 0x9c, 0x62, 0xfb,
- 0xcf, 0xbe, 0x26, 0x3a, 0xc5, 0xfd, 0xa8, 0x73, 0xb2, 0xd2, 0xc5, 0x75,
- 0x5e, 0x95, 0x99, 0x63, 0xd8, 0x4f, 0xb9, 0xa3, 0x9f, 0xb4, 0xa0, 0xd2,
- 0x46, 0x12, 0xd5, 0xcf, 0x8b, 0x17, 0xfb, 0xdc, 0x14, 0x7f, 0x9b, 0xeb,
- 0x14, 0x73, 0xce, 0xe8, 0x2d, 0x7b, 0x8d, 0xba, 0xc5, 0xb1, 0x62, 0xfc,
- 0x23, 0xbf, 0xe5, 0x62, 0xfd, 0x9a, 0xde, 0x71, 0x62, 0xb6, 0x3e, 0x12,
- 0x11, 0x30, 0xa2, 0xff, 0xb0, 0xf9, 0xa7, 0xd9, 0x8e, 0xb1, 0x7b, 0x9b,
- 0x69, 0x62, 0xf1, 0x4f, 0xd6, 0x2e, 0x6d, 0x75, 0x37, 0x72, 0x3f, 0x7f,
- 0xd2, 0x5b, 0xf5, 0x7d, 0x66, 0xeb, 0x17, 0xff, 0x7b, 0xf8, 0x7c, 0xde,
- 0x7f, 0x27, 0x58, 0xbe, 0x21, 0x67, 0xd6, 0x2b, 0xa9, 0xf3, 0xb2, 0x2d,
- 0xe6, 0x3f, 0x16, 0x2b, 0x0f, 0x01, 0x88, 0xe8, 0x09, 0x81, 0xfa, 0x1c,
- 0x77, 0x66, 0xcb, 0x17, 0xed, 0x67, 0xbe, 0xeb, 0x17, 0xfd, 0x0c, 0xd6,
- 0xb3, 0xdf, 0x75, 0x8b, 0xe9, 0xf9, 0x83, 0xd1, 0xf0, 0xf8, 0xa2, 0xff,
- 0xb7, 0x26, 0xeb, 0xf9, 0xd6, 0x2c, 0x5f, 0xf1, 0x4f, 0x71, 0xc6, 0xfb,
- 0x3e, 0xb1, 0x7f, 0xf6, 0x6b, 0x27, 0x98, 0x3f, 0xb4, 0x16, 0x29, 0x62,
- 0xde, 0x81, 0xe7, 0xc7, 0x21, 0xd1, 0xd1, 0x70, 0x50, 0x8d, 0xa9, 0x4c,
- 0x69, 0xa1, 0xe7, 0x7a, 0x39, 0xc0, 0xb1, 0x7f, 0xfc, 0x5e, 0x66, 0xf9,
- 0x4f, 0xb8, 0x1e, 0x7d, 0x62, 0xe6, 0x8f, 0x58, 0xa7, 0x44, 0x4b, 0x10,
- 0x79, 0x3e, 0xff, 0xd8, 0x7c, 0x09, 0x98, 0x20, 0xbf, 0x16, 0x2f, 0xe3,
- 0x06, 0xda, 0xc3, 0xac, 0x5f, 0xfb, 0x06, 0xd0, 0x26, 0xd3, 0x41, 0x62,
- 0xfb, 0xa4, 0x94, 0x16, 0x2d, 0xae, 0xa8, 0x90, 0x19, 0x7e, 0x1e, 0xd7,
- 0x93, 0x0b, 0x32, 0x1a, 0x97, 0xfe, 0xe4, 0xea, 0x1f, 0x9d, 0xf0, 0x96,
- 0x2f, 0xff, 0xe3, 0x93, 0x1b, 0xf7, 0xf4, 0xc2, 0x28, 0x4e, 0xb6, 0x58,
- 0xbf, 0xf8, 0xfc, 0x68, 0x6a, 0x79, 0x25, 0xb2, 0xc5, 0xff, 0x4f, 0xbf,
- 0x87, 0xcd, 0x62, 0xc5, 0xfb, 0xdf, 0x79, 0xe2, 0xc5, 0xcc, 0x5a, 0x3e,
- 0x0e, 0x1c, 0x5f, 0xff, 0x60, 0xff, 0x3c, 0x83, 0xf3, 0x93, 0xa8, 0x2c,
- 0x56, 0xc7, 0xf9, 0x1c, 0x59, 0x7f, 0xfe, 0xf4, 0xfb, 0x85, 0x9f, 0x79,
- 0xf7, 0xda, 0x0b, 0x16, 0x75, 0x8a, 0x73, 0xe5, 0xfa, 0xa5, 0xff, 0x48,
- 0x38, 0x31, 0x36, 0xa0, 0xb1, 0x7d, 0xbb, 0x36, 0xeb, 0x88, 0x0c, 0xb6,
- 0x40, 0xfa, 0xf4, 0x75, 0x7f, 0xc7, 0x6e, 0xda, 0x1c, 0x78, 0x2c, 0x5f,
- 0xf4, 0xff, 0x77, 0xe3, 0x3e, 0xcb, 0x16, 0x9e, 0xa8, 0x9b, 0xc2, 0x7d,
- 0x1d, 0x58, 0x0b, 0x17, 0x34, 0x16, 0x2a, 0x4d, 0x49, 0xc4, 0xab, 0xe7,
- 0xfe, 0x05, 0xfb, 0x8b, 0x16, 0x2e, 0x60, 0x2c, 0x54, 0x9e, 0x79, 0x11,
- 0x78, 0x5a, 0xdb, 0xac, 0x56, 0x8f, 0x00, 0x8b, 0x6a, 0x57, 0x18, 0x31,
- 0x79, 0xa3, 0x21, 0xe4, 0x22, 0xcc, 0x94, 0x6b, 0x43, 0x65, 0x54, 0xee,
- 0xe9, 0xdc, 0x66, 0x1a, 0x29, 0x3b, 0xcf, 0xe3, 0x54, 0x04, 0x2c, 0x0a,
- 0x33, 0x9e, 0x15, 0x7a, 0x72, 0x7e, 0xf8, 0x7f, 0x98, 0xe5, 0x8b, 0xff,
- 0xc7, 0x6f, 0x70, 0x50, 0xfb, 0x39, 0x32, 0xc5, 0xff, 0xfc, 0xe3, 0x2c,
- 0xe4, 0xeb, 0xaf, 0x3e, 0xc3, 0x91, 0xac, 0x5e, 0x79, 0x82, 0xc5, 0xee,
- 0x93, 0xf5, 0x8a, 0x96, 0x69, 0x8c, 0x09, 0x31, 0xfd, 0xe9, 0x5b, 0x2d,
- 0x0a, 0xf0, 0x13, 0x71, 0x27, 0xcb, 0x86, 0x0e, 0x5f, 0x9f, 0xcd, 0x1d,
- 0x8b, 0x17, 0xec, 0xd4, 0x0c, 0x82, 0xc5, 0xfe, 0xdb, 0x92, 0x76, 0xef,
- 0xcb, 0x17, 0xfe, 0x7f, 0x43, 0xef, 0xee, 0x7d, 0xd6, 0x2b, 0x64, 0x4f,
- 0x91, 0x57, 0x43, 0x6b, 0x9b, 0xb5, 0x8b, 0xdf, 0x68, 0xf5, 0x8b, 0xe9,
- 0x04, 0x76, 0x2c, 0x5f, 0x1c, 0xed, 0xe5, 0x8a, 0x82, 0x6f, 0x79, 0x0c,
- 0x93, 0x99, 0x00, 0x63, 0xc4, 0x06, 0x12, 0xdf, 0xd8, 0x11, 0x9b, 0xfc,
- 0x58, 0xbf, 0xfb, 0x39, 0xe6, 0xec, 0xc0, 0x92, 0x50, 0x58, 0xb6, 0x2c,
- 0x5f, 0xfd, 0x84, 0xd0, 0xfb, 0x1c, 0xed, 0x05, 0x8b, 0x45, 0x1a, 0x1e,
- 0xa4, 0x6c, 0x23, 0x7f, 0xff, 0x9c, 0x5b, 0x44, 0xcd, 0xb7, 0xb2, 0x22,
- 0x93, 0xfd, 0x96, 0x2f, 0x9f, 0x53, 0xd1, 0x62, 0xff, 0xe3, 0x88, 0xd2,
- 0xc0, 0x7b, 0x99, 0xb2, 0xc5, 0xb6, 0x19, 0xf5, 0xe1, 0x25, 0xff, 0xfb,
- 0x9d, 0x70, 0x7d, 0x79, 0x9a, 0x01, 0xf2, 0x3b, 0x16, 0x28, 0x91, 0x0b,
- 0xe2, 0x8b, 0xff, 0xfd, 0x9a, 0xeb, 0xbf, 0xdc, 0x7a, 0x71, 0x6c, 0x60,
- 0xdb, 0x65, 0x8b, 0xd0, 0xd1, 0xd6, 0x2f, 0xb7, 0xfb, 0xec, 0xb1, 0x7f,
- 0xc7, 0xc0, 0x86, 0x6a, 0x7f, 0x2b, 0x17, 0x11, 0xbf, 0x3f, 0xf6, 0x1e,
- 0x30, 0x96, 0xf7, 0x80, 0x25, 0x8a, 0xdd, 0x34, 0x07, 0x87, 0x39, 0x1d,
- 0xdf, 0x8f, 0x1b, 0xc6, 0xf1, 0xb8, 0x51, 0x62, 0xff, 0xfe, 0x86, 0x71,
- 0xf5, 0xa7, 0x39, 0x9e, 0xfe, 0x07, 0xe5, 0x8a, 0x95, 0x46, 0x59, 0x1b,
- 0x13, 0x9a, 0xb1, 0xed, 0xff, 0xe3, 0xce, 0xe3, 0x96, 0xd7, 0xc3, 0x61,
- 0xac, 0x5c, 0xce, 0xb1, 0x58, 0x7c, 0x5c, 0x4c, 0xbf, 0x83, 0xfc, 0x8d,
- 0xe5, 0x62, 0x8e, 0x79, 0xec, 0x43, 0x7f, 0xb5, 0x9f, 0xfc, 0xf7, 0x05,
- 0x8b, 0xff, 0xef, 0xb3, 0xfa, 0x5e, 0x18, 0x40, 0x04, 0xac, 0x5e, 0x6f,
- 0xca, 0xc5, 0xd8, 0x05, 0x8b, 0x6d, 0xf3, 0x66, 0x18, 0xe5, 0xf8, 0xc9,
- 0xd6, 0x12, 0xc5, 0xff, 0x7e, 0x79, 0xee, 0x60, 0x82, 0xeb, 0x17, 0xfe,
- 0x97, 0xff, 0xf3, 0xdf, 0xc8, 0x2c, 0x5f, 0xec, 0x28, 0x67, 0x0c, 0x3a,
- 0xc5, 0x88, 0x68, 0xb0, 0xd1, 0xf7, 0x8f, 0xaa, 0x53, 0x0d, 0xc8, 0x6c,
- 0x5f, 0xfe, 0xcf, 0xbf, 0x49, 0xcd, 0x6c, 0x26, 0x1a, 0xc5, 0x41, 0x52,
- 0xf4, 0x46, 0xad, 0x08, 0x00, 0xe3, 0x36, 0x30, 0x9e, 0xff, 0xf4, 0x33,
- 0xb8, 0x19, 0x20, 0x8c, 0x0c, 0x30, 0xd2, 0x2f, 0xa6, 0x23, 0xe2, 0xc5,
- 0xf8, 0xe1, 0xe3, 0xf4, 0x58, 0xbb, 0x0a, 0x24, 0x51, 0x7d, 0x50, 0xc2,
- 0x3b, 0xff, 0xee, 0x73, 0xe2, 0xde, 0x60, 0xfa, 0x06, 0x12, 0xc5, 0x41,
- 0x11, 0xa1, 0x9e, 0x54, 0xa7, 0x58, 0xd1, 0xc4, 0x5f, 0xff, 0x6a, 0x03,
- 0xfc, 0xf0, 0xb0, 0x36, 0xd1, 0xab, 0x17, 0x80, 0x2e, 0x2c, 0x5f, 0xb3,
- 0x0a, 0x60, 0xb1, 0x6e, 0x49, 0xe2, 0x10, 0xf5, 0x32, 0x2f, 0x3d, 0x09,
- 0x6a, 0x96, 0x58, 0x40, 0xd7, 0x70, 0xbd, 0xe1, 0x39, 0xa3, 0x3f, 0xcb,
- 0x85, 0x68, 0x79, 0x14, 0xe1, 0x58, 0xa1, 0xc9, 0x7b, 0xee, 0x1a, 0xc5,
- 0xff, 0x39, 0x43, 0x81, 0x6a, 0x14, 0x8d, 0xc2, 0x8b, 0x17, 0xfe, 0x70,
- 0x60, 0x82, 0xee, 0x5f, 0xc5, 0x8b, 0xb4, 0x6a, 0xc5, 0x11, 0xed, 0x18,
- 0x83, 0x7d, 0x17, 0x32, 0x25, 0x8b, 0xf0, 0x27, 0xd9, 0x1e, 0xb1, 0x74,
- 0x58, 0xb1, 0x7f, 0x39, 0xa6, 0xc9, 0x79, 0x62, 0xc3, 0x63, 0xc7, 0x8e,
- 0x18, 0xbf, 0xb9, 0xad, 0x3c, 0x5c, 0x58, 0xbf, 0xb3, 0x5b, 0xb3, 0x6e,
- 0xa8, 0x82, 0x4b, 0xff, 0x4c, 0x0b, 0x3f, 0xe2, 0x90, 0x2c, 0x54, 0x9f,
- 0xc9, 0x1e, 0x5f, 0xf4, 0xfb, 0x35, 0xbb, 0x36, 0xea, 0x8b, 0xe4, 0xbf,
- 0x30, 0xff, 0x26, 0xac, 0x5f, 0xff, 0xda, 0xc1, 0xfe, 0x7b, 0x86, 0xa7,
- 0xdc, 0x30, 0xa0, 0xb1, 0x7f, 0xfe, 0x10, 0x0e, 0xd0, 0x1b, 0x30, 0x79,
- 0x14, 0xe9, 0x62, 0xd8, 0xe8, 0xb5, 0xf2, 0xf5, 0xff, 0x8b, 0x3d, 0xe7,
- 0xe7, 0xb0, 0x0b, 0x17, 0x67, 0x02, 0xaa, 0x94, 0xc7, 0x0a, 0x9d, 0xc8,
- 0x0e, 0x8e, 0x50, 0xde, 0xe1, 0x3d, 0x62, 0xae, 0xf2, 0x94, 0xfb, 0x44,
- 0xae, 0x2f, 0xa4, 0xb6, 0x1b, 0xff, 0xa7, 0xee, 0x6e, 0x6b, 0x63, 0x8b,
- 0xb5, 0x8b, 0xfe, 0x1e, 0xb0, 0xf9, 0x06, 0x1a, 0xc5, 0xff, 0xf8, 0x4d,
- 0xcc, 0x2d, 0xfe, 0xe3, 0xfe, 0x76, 0x11, 0x62, 0xa5, 0x73, 0x67, 0x08,
- 0x9e, 0x5d, 0x87, 0xcb, 0x59, 0x20, 0x8e, 0x6f, 0xfe, 0xfe, 0x00, 0x72,
- 0x3c, 0xd3, 0x71, 0x62, 0xfd, 0x3a, 0xc1, 0xca, 0xc5, 0xfa, 0x18, 0x03,
- 0x3c, 0xb1, 0x7f, 0x7e, 0x3b, 0xef, 0xbf, 0xd6, 0x2a, 0x51, 0x90, 0xe8,
- 0x8c, 0x4e, 0x22, 0xab, 0xe9, 0x87, 0x31, 0x62, 0xf7, 0x30, 0xc5, 0x8a,
- 0x01, 0xe0, 0x78, 0x8a, 0xff, 0xfb, 0x7f, 0xce, 0xb3, 0x84, 0x26, 0x81,
- 0xac, 0xb1, 0x7f, 0xfe, 0x6e, 0x9d, 0x79, 0xf6, 0x7f, 0x4f, 0xbf, 0x9e,
- 0x58, 0xa1, 0x22, 0xa8, 0xc5, 0x1b, 0xff, 0x36, 0xdf, 0x9d, 0xb3, 0xdc,
- 0xc5, 0x8a, 0x93, 0xe4, 0x22, 0x4b, 0xfe, 0xf4, 0x9f, 0xf9, 0xd3, 0x38,
- 0xb1, 0x7f, 0xd2, 0x7e, 0x4b, 0xec, 0xde, 0x58, 0xa8, 0x1f, 0xa7, 0x8e,
- 0xef, 0xfd, 0xb3, 0x77, 0x1d, 0x9e, 0x26, 0xe8, 0xb1, 0x7f, 0xc2, 0xf7,
- 0x3a, 0x83, 0x7e, 0x3a, 0xc5, 0xff, 0xef, 0x49, 0x7b, 0x99, 0x86, 0x9a,
- 0xd0, 0x58, 0xbf, 0xff, 0xed, 0x37, 0xfb, 0x86, 0x7b, 0xaf, 0x39, 0x85,
- 0xbb, 0x10, 0x16, 0x2b, 0x11, 0x6a, 0xc9, 0x77, 0xff, 0xa1, 0xfc, 0x23,
- 0x79, 0xe7, 0xf6, 0x01, 0x62, 0xfd, 0x9e, 0xf6, 0x0d, 0x62, 0xff, 0x9f,
- 0xb0, 0x75, 0xd3, 0xf6, 0x05, 0x8a, 0x34, 0xf9, 0xb4, 0x51, 0x7f, 0xec,
- 0x1c, 0xc2, 0x7f, 0x80, 0x65, 0x8b, 0xff, 0xfc, 0xdd, 0x80, 0xe6, 0x73,
- 0xa8, 0xf0, 0x85, 0xe0, 0x4c, 0x16, 0x2f, 0xe6, 0x80, 0xa0, 0xc3, 0x58,
- 0xbf, 0xff, 0xef, 0x89, 0xb6, 0xd4, 0xfd, 0x9f, 0x9c, 0xc3, 0x58, 0x80,
- 0xb1, 0x7e, 0x7d, 0xb9, 0xc6, 0x58, 0xa1, 0xa2, 0x43, 0xec, 0xf7, 0xff,
- 0xde, 0xe7, 0x27, 0x08, 0x7f, 0x9f, 0xcf, 0x16, 0x2f, 0x06, 0x18, 0x69,
- 0x17, 0xef, 0xe6, 0xed, 0xa4, 0x88, 0xc3, 0x43, 0x7f, 0xff, 0xa2, 0xd4,
- 0xf4, 0xea, 0x6b, 0x75, 0x32, 0x2e, 0x75, 0xce, 0xfc, 0xb1, 0x52, 0x99,
- 0xfb, 0x11, 0xf9, 0xc0, 0xc3, 0xcb, 0xfe, 0xfb, 0x87, 0xe8, 0xb5, 0x3e,
- 0x58, 0xbf, 0xf3, 0xf8, 0x59, 0xe6, 0x3e, 0x12, 0xc5, 0x40, 0xfe, 0x74,
- 0x79, 0x7f, 0xd2, 0x0f, 0x61, 0x43, 0x38, 0xb1, 0x71, 0xb0, 0x58, 0xbd,
- 0x2f, 0xba, 0xc5, 0xfb, 0x00, 0xc4, 0x08, 0x1b, 0x6f, 0x8c, 0xd3, 0xa3,
- 0x33, 0xe4, 0x44, 0xdd, 0x5b, 0x2f, 0x3e, 0x8d, 0x17, 0x78, 0x79, 0xf6,
- 0x43, 0xa8, 0x58, 0x9c, 0x8f, 0xe7, 0xa0, 0x66, 0x28, 0xff, 0x7d, 0x1c,
- 0x15, 0xcd, 0xe5, 0x8b, 0xdc, 0xcd, 0x96, 0x2e, 0x2d, 0x80, 0x6d, 0x7c,
- 0x2f, 0x4b, 0x15, 0x26, 0xe4, 0xe5, 0xb4, 0xb1, 0x4b, 0x16, 0xe0, 0x65,
- 0xc0, 0x40, 0xcb, 0x32, 0xc5, 0xa5, 0x62, 0xf3, 0x3e, 0xc4, 0x68, 0x84,
- 0x23, 0x7f, 0xfc, 0xfb, 0xb8, 0xf9, 0x3f, 0x62, 0x16, 0x7d, 0x62, 0xa0,
- 0x8c, 0xbe, 0x25, 0xf8, 0xc6, 0xfe, 0xe1, 0x66, 0xc6, 0x41, 0x62, 0xfc,
- 0x67, 0xb8, 0x22, 0x58, 0xb4, 0xf6, 0x7b, 0x44, 0x61, 0x7f, 0x8a, 0x79,
- 0xc7, 0x92, 0x58, 0xa3, 0x9e, 0xc3, 0x13, 0xdf, 0xff, 0xdf, 0x62, 0xee,
- 0x06, 0x42, 0x4a, 0x0c, 0x7c, 0x1a, 0xc5, 0xff, 0xa0, 0x1e, 0x3f, 0x4c,
- 0x84, 0x92, 0xc5, 0x3a, 0x27, 0x0c, 0x5c, 0xbf, 0xfd, 0x99, 0xf1, 0xfe,
- 0x79, 0x9f, 0x70, 0x2c, 0x5f, 0xa2, 0x84, 0xeb, 0x8b, 0x17, 0xe8, 0x3c,
- 0x76, 0x7d, 0x62, 0xff, 0x61, 0x0a, 0x1c, 0xd9, 0x96, 0x2f, 0xf6, 0x1c,
- 0x5c, 0xfb, 0x41, 0x62, 0xba, 0xa2, 0xf6, 0x4a, 0x86, 0x56, 0x46, 0x97,
- 0xdd, 0x46, 0x3c, 0x58, 0xa3, 0x4f, 0x88, 0xe7, 0xb7, 0xfe, 0x13, 0x43,
- 0xef, 0xc1, 0x34, 0x16, 0x2f, 0xfc, 0xfe, 0xd8, 0x5c, 0xeb, 0xad, 0x4a,
- 0xc5, 0x4a, 0xbc, 0xfd, 0xa1, 0xc5, 0x08, 0x5e, 0x8c, 0x8d, 0xe3, 0x68,
- 0x01, 0x1f, 0x8f, 0xef, 0x3f, 0xc4, 0xb1, 0x7c, 0x11, 0xc4, 0x17, 0x58,
- 0xae, 0xa7, 0x8c, 0xc3, 0xb7, 0xec, 0x87, 0xe7, 0x4b, 0x17, 0xc6, 0xf5,
- 0xfb, 0xac, 0x56, 0xe7, 0xe3, 0x1e, 0x47, 0xa2, 0x8b, 0xf4, 0x08, 0x5d,
- 0xc1, 0x62, 0xef, 0xba, 0xc5, 0xdd, 0xfb, 0xb3, 0xc1, 0x88, 0xaa, 0xfc,
- 0xff, 0x36, 0x7b, 0x58, 0xbf, 0x60, 0xca, 0x7b, 0x58, 0xb7, 0xa4, 0xf4,
- 0x88, 0xaa, 0xff, 0xff, 0xfd, 0xdf, 0x8a, 0x4f, 0xc1, 0xfe, 0x79, 0x90,
- 0x73, 0x4d, 0x6f, 0x14, 0x9f, 0x8b, 0x17, 0xf8, 0x10, 0x7f, 0x70, 0xc3,
- 0xac, 0x5f, 0xfb, 0x8d, 0x0e, 0x66, 0xf2, 0x77, 0x58, 0xad, 0x1f, 0xaf,
- 0x8d, 0xaf, 0xfb, 0x7f, 0xb8, 0x01, 0x3a, 0x82, 0xc5, 0xf6, 0xb6, 0x7d,
- 0x96, 0x2e, 0xec, 0xba, 0x9f, 0x06, 0x1d, 0xd4, 0xaa, 0xc8, 0xc7, 0x47,
- 0x84, 0x1b, 0x13, 0x0a, 0x1f, 0x46, 0x42, 0x0a, 0xff, 0xbb, 0x97, 0x3e,
- 0x16, 0x47, 0xac, 0x5e, 0xf3, 0x6e, 0xb1, 0x7f, 0xfa, 0x1c, 0xc1, 0xe7,
- 0xdd, 0xbd, 0xf9, 0x58, 0xad, 0x91, 0x45, 0xb9, 0xdf, 0x63, 0xd7, 0xed,
- 0xbf, 0x22, 0xc5, 0x8b, 0xff, 0xe8, 0x49, 0xf5, 0x2f, 0x06, 0xe3, 0x10,
- 0x16, 0x2f, 0xe7, 0xe6, 0x0c, 0xcc, 0x58, 0xbf, 0x04, 0x72, 0xce, 0x8b,
- 0x17, 0xf6, 0x0d, 0xc5, 0xbf, 0xf7, 0x3d, 0x96, 0x2e, 0xbf, 0xb9, 0x07,
- 0x3b, 0x41, 0x62, 0xff, 0xf8, 0x79, 0x01, 0x0d, 0x88, 0x1a, 0xd6, 0x06,
- 0xb1, 0x52, 0x9c, 0xa7, 0x65, 0x3a, 0x85, 0x38, 0x11, 0x43, 0x2e, 0xbf,
- 0xdc, 0x2c, 0xe9, 0xf6, 0x82, 0xc5, 0xee, 0x43, 0xa2, 0xc5, 0xf8, 0x7a,
- 0x9c, 0xf2, 0xc5, 0x39, 0xfe, 0xc7, 0x9a, 0x91, 0x05, 0xff, 0xe9, 0xd8,
- 0xcf, 0xcf, 0x7e, 0xcd, 0x88, 0x6b, 0x17, 0x9b, 0x79, 0x58, 0xac, 0x56,
- 0x60, 0xf1, 0xe3, 0xb4, 0x33, 0x88, 0xc3, 0xc9, 0xd7, 0xf8, 0x07, 0x60,
- 0x1d, 0x80, 0xb1, 0x7f, 0x9c, 0x03, 0x13, 0x6a, 0x0b, 0x17, 0xff, 0x34,
- 0x30, 0x64, 0xed, 0xf9, 0x3a, 0xc5, 0xcd, 0xf5, 0x8a, 0xf9, 0xec, 0xf9,
- 0x0a, 0xe0, 0xf7, 0x58, 0xbf, 0xe1, 0xb1, 0x9a, 0x27, 0x93, 0x56, 0x2f,
- 0xa7, 0x0b, 0xc1, 0x53, 0xd4, 0x18, 0xd5, 0xee, 0x43, 0x75, 0x8b, 0xff,
- 0x7b, 0x53, 0x9d, 0xe6, 0xb3, 0xcb, 0x17, 0xbf, 0x9d, 0x3a, 0x9e, 0xf7,
- 0x63, 0xf5, 0xc4, 0x68, 0xfa, 0x13, 0x35, 0xe4, 0xdb, 0xc5, 0x1a, 0x3d,
- 0xff, 0xe2, 0xcf, 0x3c, 0x18, 0xb3, 0xdf, 0x75, 0x8b, 0xe0, 0x19, 0xd8,
- 0x55, 0x62, 0xfe, 0x26, 0xee, 0x0f, 0x8b, 0x17, 0xf8, 0x80, 0x59, 0xef,
- 0xe7, 0x54, 0x4f, 0x62, 0x3f, 0xca, 0xaf, 0xe2, 0xea, 0x66, 0xbe, 0xcb,
- 0x17, 0xed, 0x00, 0xef, 0xc5, 0x8b, 0xfe, 0x68, 0x75, 0x97, 0x1e, 0x1d,
- 0x62, 0xb0, 0xf8, 0xc4, 0x53, 0x4e, 0x98, 0x63, 0x2b, 0x94, 0x25, 0x2f,
- 0xfe, 0x83, 0x73, 0x92, 0xfc, 0x14, 0x4c, 0xb1, 0x7f, 0xce, 0x0d, 0xbf,
- 0x3c, 0x17, 0x16, 0x29, 0xd1, 0x01, 0xa4, 0x5b, 0xf6, 0x69, 0xbb, 0x0d,
- 0x62, 0xfe, 0x7c, 0xde, 0x7d, 0xc5, 0x8b, 0x41, 0x62, 0xff, 0xf6, 0x0f,
- 0x4e, 0x2d, 0x87, 0xf9, 0x2d, 0x96, 0x2f, 0xfb, 0xed, 0xc7, 0x22, 0x9e,
- 0xd6, 0x2c, 0x19, 0x22, 0x13, 0x89, 0x96, 0xda, 0x51, 0x7f, 0x90, 0x96,
- 0xad, 0x93, 0x44, 0x22, 0xae, 0x43, 0xb6, 0xff, 0x44, 0x4c, 0x1f, 0xb3,
- 0xeb, 0x17, 0xbf, 0x9b, 0xac, 0x5e, 0x0c, 0x30, 0xd2, 0x2f, 0xe0, 0x49,
- 0x67, 0x7e, 0x48, 0x8c, 0x34, 0x35, 0xd5, 0x16, 0xb1, 0xc6, 0xa6, 0x1f,
- 0xdf, 0xff, 0xc1, 0x7e, 0xbb, 0xfd, 0xc6, 0x3c, 0x0f, 0xaf, 0xb9, 0x9b,
- 0x2c, 0x57, 0xd1, 0x3c, 0x23, 0x6b, 0xfb, 0xf3, 0xb9, 0x31, 0xd6, 0x2f,
- 0xf1, 0x74, 0xdb, 0x0d, 0xcd, 0x2c, 0x56, 0x1f, 0x2b, 0x97, 0x5e, 0xdb,
- 0xda, 0x58, 0xa9, 0x57, 0x6c, 0xf1, 0xb3, 0x34, 0x71, 0x3c, 0x84, 0x41,
- 0x84, 0x17, 0xff, 0xe6, 0xd4, 0xb8, 0xe4, 0x98, 0x1c, 0x97, 0x1a, 0xc5,
- 0xff, 0x67, 0x4c, 0x71, 0xb3, 0x1a, 0xb1, 0x7f, 0xfd, 0xef, 0xcf, 0x31,
- 0xfd, 0xc7, 0x2e, 0xe0, 0xb1, 0x7f, 0xa4, 0xef, 0xed, 0x08, 0xeb, 0x14,
- 0xe8, 0x84, 0x25, 0x0a, 0xdd, 0x33, 0x1f, 0xa9, 0x05, 0xe1, 0x7d, 0x7d,
- 0xfe, 0x4e, 0x96, 0x2f, 0xfa, 0x05, 0x3d, 0x63, 0x9b, 0x6e, 0x2c, 0x5f,
- 0xfb, 0x7f, 0xb8, 0xda, 0x04, 0x26, 0x58, 0xae, 0xcf, 0xfb, 0x47, 0xf7,
- 0xfe, 0xcf, 0xee, 0xf2, 0x03, 0xcc, 0x16, 0x2a, 0x53, 0x03, 0x78, 0x50,
- 0xe8, 0x8e, 0xff, 0xfb, 0xa9, 0x87, 0xeb, 0xf7, 0xea, 0x3d, 0x13, 0x06,
- 0xb1, 0x7f, 0xa7, 0x98, 0x19, 0x85, 0xe5, 0x8a, 0xc4, 0x47, 0x18, 0xb3,
- 0x52, 0xea, 0x88, 0x36, 0x1e, 0x84, 0xec, 0x08, 0xe3, 0x24, 0xc7, 0xad,
- 0xe3, 0x30, 0xee, 0x12, 0x8f, 0x3d, 0x3f, 0x14, 0x62, 0x9a, 0x9c, 0xd2,
- 0x3c, 0xbf, 0x4f, 0xce, 0x1b, 0xb2, 0x98, 0x0d, 0x0a, 0x3f, 0xce, 0x47,
- 0xa9, 0xe9, 0xc6, 0x91, 0x47, 0x19, 0xd2, 0x33, 0xe3, 0x21, 0x85, 0x7f,
- 0xce, 0x5b, 0x31, 0x7b, 0x0e, 0xb1, 0x7b, 0x71, 0x76, 0xb1, 0x74, 0x81,
- 0x62, 0xb0, 0xfb, 0xd8, 0xe3, 0xc4, 0x17, 0xff, 0x1a, 0x67, 0x9f, 0x85,
- 0x9d, 0x1c, 0x6b, 0x17, 0xf1, 0x60, 0xfe, 0xc1, 0xac, 0x56, 0x8f, 0xd8,
- 0xe9, 0x17, 0xff, 0xfe, 0x2c, 0x70, 0x75, 0xfb, 0x7b, 0xc2, 0xdb, 0xa9,
- 0x9a, 0xd6, 0x6c, 0xb1, 0x7c, 0xe4, 0x0e, 0x2c, 0x5e, 0x26, 0x3a, 0xc5,
- 0xf8, 0x9f, 0xed, 0x1e, 0xb1, 0x7f, 0xee, 0x3e, 0x9b, 0xef, 0xc9, 0x82,
- 0xc5, 0xfc, 0x3f, 0xe7, 0xa3, 0xb1, 0x62, 0xcf, 0x04, 0xd2, 0xf7, 0x74,
- 0xf9, 0x11, 0x0e, 0x78, 0xa8, 0x33, 0xeb, 0xfb, 0x43, 0x78, 0x0b, 0x4b,
- 0x17, 0xff, 0xf1, 0x0f, 0xec, 0xfe, 0x03, 0x94, 0x39, 0x84, 0x05, 0x8a,
- 0x95, 0x4a, 0x7f, 0x8d, 0xb5, 0x97, 0x84, 0x5f, 0x7f, 0xa1, 0xf9, 0xdb,
- 0xf3, 0xb2, 0xc5, 0xfe, 0x23, 0x78, 0xfa, 0x68, 0x2c, 0x5f, 0x13, 0x77,
- 0xe5, 0x8b, 0xfe, 0xf3, 0x77, 0x90, 0xfc, 0xe9, 0x62, 0xf6, 0x10, 0x16,
- 0x2f, 0xed, 0xe7, 0xb2, 0x90, 0xd6, 0x2f, 0xf4, 0x07, 0xf1, 0x1c, 0x78,
- 0xb1, 0x7f, 0xf7, 0x60, 0xdc, 0xb3, 0x61, 0x77, 0x0e, 0x2c, 0x5e, 0x32,
- 0x3b, 0x16, 0x2b, 0x11, 0x40, 0xe6, 0xa0, 0x4a, 0xbe, 0xcf, 0x45, 0x05,
- 0x8b, 0xff, 0x82, 0x14, 0x84, 0xe3, 0x11, 0x80, 0xe2, 0xc5, 0xa5, 0x62,
- 0xbe, 0x7f, 0xcc, 0x49, 0xe4, 0x9b, 0x9e, 0x56, 0x2f, 0xfd, 0x9e, 0x9d,
- 0x73, 0xf2, 0x5e, 0x5c, 0x41, 0x05, 0xfd, 0x9a, 0xdd, 0x9b, 0x75, 0x44,
- 0x10, 0x46, 0x1e, 0x5d, 0xe9, 0x1b, 0xac, 0x54, 0x9f, 0x67, 0x14, 0x2f,
- 0xfc, 0x45, 0x86, 0xb6, 0x1d, 0x89, 0x62, 0xee, 0x83, 0x58, 0xbd, 0xd2,
- 0x4e, 0xb1, 0x7d, 0xdf, 0x33, 0x4b, 0x17, 0xed, 0xb3, 0x53, 0x05, 0x8b,
- 0xed, 0x69, 0xc3, 0x58, 0xa3, 0x9e, 0x6f, 0xca, 0x6a, 0x51, 0x26, 0xce,
- 0x37, 0xf4, 0x78, 0xc3, 0x62, 0x82, 0xc5, 0x4a, 0x6b, 0x7b, 0x1e, 0x60,
- 0xd1, 0x42, 0xc8, 0x44, 0x37, 0xff, 0x7f, 0x71, 0xe6, 0x9f, 0x3a, 0x7c,
- 0x4b, 0x17, 0xf6, 0xa7, 0xf2, 0xe1, 0x75, 0x8a, 0x63, 0xf9, 0x31, 0x22,
- 0xff, 0xff, 0xf4, 0x96, 0xfc, 0x92, 0xf7, 0x30, 0x47, 0x33, 0x8d, 0xa9,
- 0xdf, 0x09, 0x62, 0xff, 0xf4, 0x50, 0x72, 0xf4, 0x82, 0x22, 0x78, 0x96,
- 0x2e, 0x28, 0x96, 0x28, 0x67, 0xc9, 0x89, 0x97, 0x82, 0xb1, 0xc1, 0x6a,
- 0xb1, 0x7f, 0x67, 0x99, 0xa1, 0xc5, 0x8b, 0xb3, 0x91, 0xb1, 0xec, 0x91,
- 0x65, 0x4a, 0x2a, 0xc9, 0xea, 0xff, 0xfd, 0x3e, 0xfb, 0x45, 0xc6, 0x7d,
- 0xc9, 0xb3, 0x75, 0x8b, 0xd1, 0xec, 0x75, 0x8a, 0x95, 0xfa, 0x7d, 0x8d,
- 0x30, 0x8c, 0xd3, 0xad, 0xc7, 0x35, 0x0d, 0x0f, 0xc2, 0xb1, 0x8b, 0x81,
- 0x0c, 0xd2, 0x8d, 0xf3, 0x90, 0xc7, 0xf1, 0x17, 0x48, 0xe1, 0xe3, 0x88,
- 0x42, 0x2b, 0x5f, 0xe2, 0x13, 0x44, 0xcd, 0xb2, 0xc5, 0xa0, 0xb1, 0x7a,
- 0x74, 0x05, 0x8a, 0x19, 0xaf, 0x71, 0x2b, 0xcd, 0xad, 0x96, 0x28, 0x68,
- 0xa1, 0xfb, 0x18, 0x64, 0x17, 0xa2, 0x70, 0xd6, 0x2f, 0xcf, 0xa2, 0xcd,
- 0x96, 0x29, 0xcf, 0x1f, 0xe3, 0xf7, 0x73, 0xeb, 0x17, 0xfd, 0xb4, 0x4f,
- 0xff, 0x4e, 0x6c, 0xb1, 0x5a, 0x3f, 0x50, 0x10, 0x90, 0xc5, 0xfb, 0x53,
- 0xbe, 0x12, 0xc5, 0x61, 0xeb, 0x31, 0x75, 0xfd, 0xfc, 0xf7, 0x9c, 0xeb,
- 0x17, 0xff, 0x70, 0x64, 0xfb, 0x19, 0xa2, 0x9c, 0x58, 0xbf, 0xbc, 0x66,
- 0x7d, 0xbb, 0x58, 0xbd, 0xc0, 0x32, 0xc5, 0x76, 0x8c, 0x0f, 0x97, 0x12,
- 0x2f, 0x8c, 0x2f, 0xf8, 0xb6, 0xcd, 0x00, 0x84, 0x05, 0x8b, 0xfd, 0xc0,
- 0xd8, 0x73, 0xdf, 0x16, 0x2f, 0xec, 0xef, 0xda, 0xd4, 0xac, 0x5f, 0xfd,
- 0xc2, 0x6f, 0x31, 0xcc, 0x9d, 0xb1, 0x62, 0x86, 0x7e, 0x9c, 0x2f, 0xa9,
- 0x4d, 0x0d, 0xcf, 0x58, 0xe8, 0x50, 0xaa, 0xbf, 0xe6, 0x7f, 0x31, 0xd8,
- 0x80, 0xb1, 0x7b, 0xa7, 0xf1, 0x62, 0xdb, 0xfc, 0xf5, 0x8c, 0x37, 0xbe,
- 0x17, 0xa4, 0x96, 0x2b, 0x0f, 0x33, 0x85, 0x57, 0xee, 0x83, 0xfc, 0xf1,
- 0x62, 0xc7, 0x58, 0xbf, 0xbc, 0x3f, 0x89, 0xb8, 0xb0, 0x61, 0x65, 0x6d,
- 0xd6, 0x2a, 0x4f, 0x4b, 0x73, 0xfb, 0x82, 0xbb, 0xac, 0x5f, 0xfd, 0x9b,
- 0xfe, 0x7f, 0x9a, 0xd4, 0x9a, 0xb1, 0x70, 0x25, 0x62, 0xc3, 0xd1, 0xee,
- 0x81, 0x1a, 0xb4, 0x8a, 0x22, 0x7a, 0xbe, 0x29, 0xec, 0x0b, 0x14, 0xe7,
- 0x8a, 0x61, 0x15, 0xfe, 0x13, 0x0f, 0xf3, 0xee, 0x2c, 0x5f, 0x16, 0x74,
- 0xc5, 0x8b, 0x9b, 0x6f, 0x1e, 0xb9, 0x86, 0x97, 0xe3, 0x9a, 0x6b, 0xc4,
- 0xb1, 0x63, 0x56, 0x2e, 0xec, 0x0b, 0x17, 0xcd, 0xe9, 0xc5, 0x8a, 0x93,
- 0xcd, 0x71, 0x3f, 0x8c, 0xdf, 0xec, 0xd3, 0x80, 0xed, 0x05, 0x8b, 0x9c,
- 0x96, 0x2f, 0xfa, 0x48, 0xd1, 0xbc, 0x05, 0xa5, 0x8b, 0x06, 0xb1, 0x43,
- 0x3e, 0x33, 0x8b, 0x18, 0x75, 0x7e, 0x98, 0xa1, 0x31, 0xeb, 0x17, 0xfe,
- 0xd3, 0x9a, 0x76, 0xf7, 0x05, 0x05, 0x8b, 0xc4, 0x2d, 0x96, 0x2f, 0x6c,
- 0x52, 0xb1, 0x6f, 0xac, 0x5f, 0x49, 0x1b, 0x1c, 0xb1, 0x7c, 0xd0, 0xc2,
- 0x58, 0xad, 0xcf, 0x1f, 0xe4, 0xd7, 0xf3, 0xf8, 0xb3, 0xee, 0xb1, 0x73,
- 0xc4, 0xb1, 0x7c, 0x12, 0x74, 0x6a, 0xc5, 0xbf, 0xd5, 0x11, 0xb2, 0x46,
- 0xc5, 0x81, 0x06, 0x2f, 0xfa, 0x79, 0xf7, 0xd6, 0x9a, 0x0b, 0x15, 0x87,
- 0xfc, 0x48, 0xb6, 0x0f, 0xaa, 0xb1, 0xf1, 0x96, 0xe4, 0x25, 0xb4, 0x60,
- 0x72, 0xcf, 0xa0, 0xb0, 0xf7, 0x07, 0x7d, 0x1b, 0x25, 0x4a, 0xe1, 0x53,
- 0x4b, 0x98, 0xbf, 0xa7, 0x6f, 0x73, 0x3c, 0xb1, 0x52, 0xc9, 0xea, 0x84,
- 0xa2, 0x3c, 0x87, 0x13, 0x90, 0xea, 0x11, 0xff, 0x8c, 0x25, 0x9e, 0x4a,
- 0x71, 0x64, 0x32, 0xbb, 0xe6, 0x7e, 0x92, 0xb1, 0x7e, 0x71, 0x8f, 0x09,
- 0x62, 0x86, 0x79, 0x5c, 0x23, 0xbf, 0xff, 0xfb, 0x3d, 0x27, 0x1e, 0x7a,
- 0x70, 0xa0, 0x59, 0xdc, 0x27, 0x3c, 0xb1, 0x7f, 0xfe, 0xfe, 0x73, 0x99,
- 0x82, 0xd6, 0xd8, 0x22, 0xf2, 0xc5, 0x12, 0x31, 0x7c, 0xdf, 0x7f, 0xce,
- 0x72, 0xcf, 0x75, 0xcc, 0x58, 0xbf, 0xef, 0xce, 0xbc, 0x53, 0x9d, 0xac,
- 0x5f, 0xff, 0xf3, 0xed, 0x30, 0xe6, 0xb4, 0xfd, 0xc5, 0x06, 0xd1, 0xf3,
- 0xb5, 0x8b, 0xfd, 0x2d, 0xb3, 0x69, 0x8c, 0x58, 0xbd, 0xfc, 0x21, 0xa3,
- 0x63, 0xe7, 0x3e, 0x6b, 0xac, 0x54, 0xb4, 0xf0, 0xe7, 0xf9, 0x17, 0xa3,
- 0x11, 0xbf, 0x4e, 0xa2, 0xe6, 0xcb, 0x17, 0xfd, 0xf9, 0xcd, 0x43, 0x82,
- 0x3a, 0xc5, 0xff, 0xbf, 0x23, 0xeb, 0x31, 0xff, 0x6e, 0x2c, 0x5f, 0xf9,
- 0xc1, 0x9e, 0x9f, 0xc9, 0xf1, 0x62, 0xb6, 0x47, 0x36, 0xe5, 0x6e, 0x75,
- 0x1c, 0x89, 0x73, 0xf1, 0x62, 0xf0, 0x62, 0xe2, 0xc5, 0xfe, 0xd9, 0xbc,
- 0x03, 0x0a, 0x0b, 0x17, 0xe8, 0xb8, 0x16, 0xc2, 0xc8, 0xd1, 0x62, 0xa5,
- 0x12, 0x18, 0x3e, 0x23, 0x6b, 0xfd, 0xf7, 0xd6, 0x9c, 0xb7, 0x58, 0xbf,
- 0xf4, 0x39, 0x1b, 0x73, 0x09, 0xa1, 0xc5, 0x8b, 0xd3, 0x03, 0x56, 0x2f,
- 0xd9, 0xcd, 0xb0, 0x35, 0x8b, 0xfb, 0x71, 0x4e, 0xff, 0xc5, 0x8b, 0x9f,
- 0x75, 0x8a, 0xea, 0x89, 0x08, 0x0f, 0x61, 0x54, 0x71, 0x85, 0x1a, 0x9a,
- 0x4f, 0x66, 0x9e, 0x86, 0xa5, 0xff, 0xbd, 0xf6, 0x83, 0x8f, 0xf3, 0x05,
- 0x8a, 0x63, 0xf7, 0x23, 0x8b, 0xf8, 0xc3, 0xf0, 0x36, 0xed, 0x62, 0xa5,
- 0x71, 0x5b, 0x23, 0x2e, 0x35, 0x07, 0x50, 0xa7, 0x68, 0xfb, 0xbc, 0x41,
- 0x78, 0x3c, 0xfa, 0xc5, 0xff, 0xf7, 0xb4, 0x21, 0xcf, 0x5d, 0x4e, 0xcd,
- 0xad, 0xd6, 0x2f, 0xfc, 0x59, 0xb1, 0x67, 0xbe, 0xe1, 0xac, 0x5d, 0x81,
- 0xf5, 0x44, 0xa6, 0xea, 0xb7, 0xd8, 0x0d, 0x4a, 0xc5, 0x6c, 0x7a, 0x9f,
- 0x32, 0xbf, 0xfd, 0xf7, 0xde, 0x5f, 0xdf, 0x90, 0xf3, 0xeb, 0x17, 0xfb,
- 0xcf, 0xfc, 0x2c, 0xe2, 0xc5, 0x6e, 0x7f, 0xa6, 0x25, 0xde, 0x84, 0x31,
- 0x62, 0xe9, 0x31, 0x62, 0xbb, 0x36, 0xac, 0x3b, 0x7f, 0xa6, 0x06, 0x70,
- 0x06, 0x6e, 0xb1, 0x4e, 0x7b, 0x3e, 0x21, 0xb1, 0x41, 0x1a, 0x63, 0x85,
- 0x95, 0x41, 0x3a, 0x0c, 0x8d, 0xce, 0xf6, 0xb3, 0xeb, 0x17, 0xb8, 0xe7,
- 0x58, 0xad, 0x1b, 0xaf, 0x0e, 0xdf, 0xdf, 0x6f, 0x7d, 0x8e, 0xb1, 0x7c,
- 0x6c, 0x94, 0x16, 0x2e, 0xce, 0xd6, 0x2e, 0x7d, 0x96, 0x2a, 0x51, 0x44,
- 0xe4, 0x3e, 0x2e, 0x30, 0x8c, 0x20, 0xc5, 0xfe, 0xe1, 0x61, 0xce, 0xfe,
- 0x58, 0xbe, 0xf6, 0x0a, 0x0b, 0x17, 0xff, 0x7d, 0xe4, 0xba, 0xb1, 0x41,
- 0xce, 0xb1, 0x7a, 0x27, 0x0d, 0x62, 0xfa, 0x42, 0x3e, 0x96, 0x29, 0xcf,
- 0x0c, 0x87, 0xef, 0xfc, 0xdd, 0x99, 0xe7, 0xd4, 0x88, 0x2e, 0xb1, 0x71,
- 0x9b, 0x2c, 0x51, 0xcf, 0x7f, 0xc8, 0xb7, 0xe6, 0xe1, 0x4c, 0x4b, 0x17,
- 0xef, 0x88, 0xa7, 0x65, 0x8b, 0xba, 0x69, 0x62, 0xe2, 0xd2, 0xc5, 0xff,
- 0xf8, 0x5b, 0x14, 0xe7, 0xe3, 0x27, 0xd9, 0xf1, 0x69, 0x62, 0xf7, 0x0c,
- 0xe7, 0x55, 0x40, 0x63, 0x84, 0x3e, 0x3f, 0x9a, 0x44, 0xe5, 0x04, 0x53,
- 0xc1, 0xa3, 0x05, 0xeb, 0x75, 0x5c, 0xac, 0x67, 0xe9, 0x44, 0xd7, 0x10,
- 0x6b, 0x17, 0xee, 0x1f, 0x3d, 0xc5, 0x8b, 0xf8, 0x1a, 0x9d, 0xf0, 0x96,
- 0x2f, 0xfc, 0x6e, 0x79, 0xff, 0x9e, 0x9d, 0x2c, 0x54, 0x9f, 0x6b, 0x97,
- 0x5f, 0x9a, 0x04, 0xf2, 0xb1, 0x7c, 0xde, 0x70, 0x2c, 0x5f, 0x17, 0xb0,
- 0x96, 0x2b, 0xe7, 0x86, 0xc4, 0x57, 0xf6, 0x1f, 0x30, 0x8d, 0x58, 0xa5,
- 0x8b, 0xfb, 0xdc, 0xce, 0x9f, 0x75, 0x8a, 0x34, 0xde, 0x30, 0x65, 0x8d,
- 0x1a, 0x22, 0x89, 0xa6, 0xa5, 0x1a, 0x8d, 0x0a, 0xbb, 0xfe, 0x26, 0x0e,
- 0x28, 0x36, 0xa0, 0xb1, 0x7f, 0x3e, 0xb3, 0xa4, 0xc7, 0xac, 0x54, 0x47,
- 0xdb, 0xf3, 0xbb, 0xf9, 0xf5, 0xa9, 0xc2, 0x58, 0xbf, 0xe9, 0x87, 0x33,
- 0x72, 0x9d, 0x2c, 0x51, 0xa7, 0xcb, 0xa2, 0xcb, 0x3a, 0xc5, 0xfd, 0xc7,
- 0xd6, 0xff, 0xc5, 0x8b, 0xfe, 0x26, 0xef, 0xef, 0x25, 0xe5, 0x8b, 0xfb,
- 0x00, 0x06, 0xee, 0x0b, 0x17, 0x89, 0x8d, 0xc4, 0x65, 0x6e, 0x47, 0xd8,
- 0x8f, 0xcb, 0xc8, 0xe2, 0xba, 0xb2, 0xd7, 0xe6, 0x55, 0x34, 0x23, 0x05,
- 0xc9, 0x66, 0x1b, 0x9c, 0xb8, 0xc6, 0xa1, 0x2c, 0x72, 0x02, 0x8c, 0xf7,
- 0x90, 0x93, 0x14, 0x6a, 0x57, 0xff, 0xdb, 0x66, 0xb6, 0x7f, 0x43, 0x35,
- 0xa6, 0x82, 0xc5, 0xc6, 0xf9, 0x62, 0xff, 0xf3, 0xfe, 0x7f, 0x9d, 0xf1,
- 0xff, 0x23, 0x58, 0xbd, 0xbb, 0x8d, 0x62, 0xfb, 0x62, 0x9d, 0x96, 0x2e,
- 0xcd, 0x96, 0x2c, 0x52, 0x6f, 0x30, 0x92, 0xf3, 0xe7, 0xd6, 0x2f, 0xff,
- 0xf8, 0xb3, 0x4f, 0x25, 0xec, 0xf3, 0x97, 0xb4, 0xe2, 0xd9, 0x62, 0xb4,
- 0x88, 0x00, 0x0e, 0x5f, 0xf1, 0xdb, 0xb0, 0x93, 0xb9, 0xce, 0xb1, 0x7d,
- 0x38, 0x64, 0x68, 0xb1, 0x7e, 0x91, 0xc6, 0xf1, 0xb8, 0x51, 0x62, 0xda,
- 0xc4, 0x4e, 0x91, 0xf1, 0x85, 0x17, 0xff, 0xfb, 0x8f, 0xce, 0x4f, 0x37,
- 0x26, 0xda, 0x4a, 0x62, 0xe2, 0xc5, 0x62, 0xb0, 0xa3, 0x54, 0xb7, 0x19,
- 0xed, 0x29, 0xd6, 0xb5, 0x0a, 0x46, 0x86, 0x07, 0x8d, 0x6f, 0xdf, 0x78,
- 0xe7, 0x35, 0x62, 0xfb, 0x00, 0xfd, 0x16, 0x2f, 0x80, 0x01, 0x01, 0x62,
- 0xb7, 0x3f, 0x42, 0x2c, 0x30, 0x92, 0xf8, 0x5a, 0xf3, 0xac, 0x5f, 0x8a,
- 0x1c, 0xd8, 0x0b, 0x17, 0xff, 0xe9, 0xe7, 0xf0, 0xfc, 0x91, 0xb0, 0xfe,
- 0x23, 0xac, 0x5f, 0xfc, 0x09, 0xe1, 0xe5, 0xf5, 0xa7, 0x0d, 0x62, 0xf3,
- 0x34, 0x16, 0x2f, 0xf3, 0xf9, 0xe1, 0x9d, 0xf9, 0x62, 0x86, 0x99, 0xc6,
- 0x11, 0xee, 0x54, 0xea, 0xc0, 0x45, 0x08, 0x39, 0x7f, 0xda, 0x81, 0x3c,
- 0x3b, 0xf0, 0x5a, 0xac, 0x5f, 0xdb, 0xe1, 0x81, 0x1a, 0x0b, 0x17, 0xe3,
- 0xbf, 0xbd, 0x2b, 0x17, 0x9f, 0x03, 0x58, 0xbe, 0x7e, 0x60, 0xf1, 0x17,
- 0x3b, 0xa1, 0x39, 0x91, 0x14, 0x5f, 0xf8, 0x1e, 0x9c, 0x2d, 0xf3, 0xbf,
- 0x2c, 0x5f, 0xb9, 0x87, 0x98, 0xf5, 0x8a, 0xd1, 0xf5, 0x92, 0x05, 0xff,
- 0xa6, 0x00, 0x3c, 0x87, 0xc8, 0x6c, 0xb1, 0x7f, 0xf6, 0x77, 0x0c, 0xfb,
- 0xe8, 0x9e, 0x56, 0x2f, 0xfa, 0x67, 0x9c, 0x7d, 0x61, 0xd6, 0x2a, 0x07,
- 0xf6, 0x34, 0x3b, 0xe8, 0xff, 0xe6, 0xcb, 0x17, 0xfa, 0x47, 0x9e, 0x7f,
- 0x89, 0x62, 0xa4, 0xf6, 0x86, 0x4f, 0x7f, 0xe8, 0x79, 0xf6, 0xd4, 0xc1,
- 0xb4, 0xb1, 0x7e, 0x2c, 0xd8, 0xc8, 0x2c, 0x5f, 0x1a, 0xfd, 0xf1, 0x62,
- 0xa5, 0x50, 0x56, 0xc4, 0x31, 0x42, 0xf4, 0xef, 0x8c, 0x43, 0xc4, 0x0f,
- 0x15, 0x5f, 0xfb, 0xc6, 0x02, 0x4c, 0x90, 0x48, 0x16, 0x2f, 0xf9, 0xf5,
- 0xb0, 0x81, 0xd6, 0x63, 0xd6, 0x2f, 0xff, 0x89, 0xcd, 0x36, 0x4c, 0xf3,
- 0xfd, 0xcb, 0xcb, 0x17, 0xff, 0x9b, 0xff, 0x72, 0xc0, 0x01, 0xe2, 0xe2,
- 0xc5, 0x41, 0x1b, 0x67, 0x40, 0xe8, 0xa3, 0x7f, 0xef, 0xb4, 0x3c, 0x26,
- 0x20, 0x71, 0x62, 0xff, 0xfb, 0x9f, 0x7c, 0x3b, 0x77, 0xcf, 0x7c, 0x5d,
- 0xac, 0x57, 0xd1, 0x24, 0x03, 0xfb, 0xfe, 0xfb, 0xeb, 0xdd, 0xee, 0xfe,
- 0x58, 0xbe, 0x6f, 0x7a, 0x56, 0x2f, 0xe6, 0xe3, 0x94, 0xf1, 0x62, 0xef,
- 0xb2, 0xc5, 0xf0, 0xd8, 0x81, 0x88, 0xa1, 0xdc, 0xf3, 0xe4, 0x41, 0x72,
- 0xca, 0xc4, 0xc6, 0xc5, 0x0c, 0x4b, 0xff, 0xf8, 0x78, 0x08, 0xec, 0xfb,
- 0x3f, 0x85, 0xa6, 0xe9, 0x8b, 0x17, 0xff, 0xfe, 0x3b, 0x10, 0x20, 0xfc,
- 0x11, 0xfe, 0xf3, 0xef, 0x89, 0x8e, 0xb1, 0x7f, 0xff, 0x89, 0x83, 0xf6,
- 0x7f, 0xa9, 0x67, 0xf9, 0xcc, 0x62, 0x58, 0xbd, 0x0d, 0xb1, 0x62, 0xa2,
- 0x3f, 0xfe, 0x30, 0xdf, 0xfd, 0x81, 0xea, 0x5c, 0xb0, 0x07, 0x75, 0x8b,
- 0xff, 0xf3, 0xfa, 0x12, 0x40, 0x18, 0x9b, 0x50, 0x19, 0xd6, 0x2f, 0xc4,
- 0x28, 0x67, 0x16, 0x2e, 0x29, 0x58, 0xbf, 0xfc, 0x2f, 0x41, 0xc1, 0xf6,
- 0x7f, 0x31, 0xd6, 0x2a, 0x08, 0xde, 0xc5, 0x6f, 0x94, 0x10, 0xb5, 0xdd,
- 0x63, 0xd6, 0x2f, 0xff, 0xcc, 0xfe, 0x71, 0xe0, 0xf3, 0xce, 0x77, 0xd2,
- 0xc5, 0xf4, 0x39, 0x27, 0x58, 0xbf, 0xfd, 0x3b, 0x8f, 0x0c, 0xf3, 0xea,
- 0x44, 0x17, 0x58, 0xbc, 0x2c, 0x1a, 0xc5, 0xed, 0x37, 0x3a, 0xaa, 0x7f,
- 0xd8, 0x8f, 0x23, 0x21, 0xd1, 0xdf, 0xc7, 0x59, 0x4c, 0x88, 0xe3, 0x94,
- 0x2d, 0xe9, 0x5e, 0x5d, 0x84, 0x7b, 0xee, 0x50, 0xcb, 0xe2, 0x96, 0xd5,
- 0x7f, 0xe9, 0xe6, 0xff, 0x71, 0xce, 0x69, 0x62, 0xbb, 0x64, 0x0a, 0xbc,
- 0xfb, 0xce, 0x97, 0x6e, 0x84, 0xac, 0x5f, 0xfb, 0xf3, 0xfc, 0xec, 0x19,
- 0xee, 0x2c, 0x5e, 0x89, 0xce, 0xb1, 0x43, 0x3d, 0xec, 0x40, 0xbe, 0x73,
- 0x64, 0xeb, 0x17, 0xff, 0x60, 0xc9, 0xb6, 0xe7, 0x18, 0xa0, 0xb1, 0x76,
- 0x14, 0x9f, 0x39, 0x11, 0xd6, 0xc8, 0xb2, 0xf4, 0x22, 0x29, 0x93, 0x50,
- 0x14, 0x64, 0xf7, 0xff, 0xff, 0xb7, 0xeb, 0x17, 0xe7, 0x5b, 0x75, 0xe0,
- 0x18, 0x81, 0xd7, 0x37, 0x9f, 0x71, 0x62, 0xa5, 0xb0, 0xe9, 0x1c, 0x3c,
- 0x72, 0x36, 0x8d, 0xe3, 0x12, 0x79, 0x58, 0xcd, 0x48, 0x80, 0x28, 0xe3,
- 0x04, 0x53, 0x63, 0xac, 0x5e, 0xd6, 0xa5, 0x62, 0xf7, 0xc5, 0x1e, 0xb1,
- 0x7f, 0xdb, 0x3e, 0xdc, 0xc3, 0xb7, 0xd6, 0x2f, 0xfa, 0x12, 0x37, 0x1e,
- 0x37, 0xd6, 0x2c, 0xfa, 0x3f, 0x3f, 0x1d, 0xdf, 0xda, 0x9d, 0x9c, 0xbc,
- 0xb1, 0x7f, 0xfb, 0xa7, 0x5c, 0xf3, 0xea, 0x45, 0xe8, 0x4a, 0xc5, 0x8e,
- 0xb1, 0x4e, 0x7c, 0x06, 0x27, 0x5e, 0x03, 0x71, 0x62, 0xe8, 0xdc, 0x28,
- 0xb1, 0x43, 0x3e, 0x0e, 0xc8, 0xb8, 0x3b, 0x78, 0x2d, 0x85, 0xa8, 0x51,
- 0x62, 0xfc, 0x52, 0x3c, 0x89, 0x62, 0xfe, 0x83, 0x81, 0xbc, 0x25, 0x8b,
- 0xee, 0x0b, 0x46, 0xac, 0x5f, 0xfa, 0x02, 0x1e, 0x6b, 0xc4, 0x2f, 0x2c,
- 0x5f, 0x61, 0x37, 0x16, 0x2f, 0xd3, 0xff, 0x4c, 0x16, 0x2f, 0xa1, 0x80,
- 0x8d, 0x4b, 0x17, 0x85, 0xee, 0x46, 0xe9, 0xae, 0x49, 0x7e, 0x14, 0x76,
- 0x5d, 0x11, 0x2f, 0xd0, 0x00, 0x43, 0x1c, 0x51, 0x7f, 0xfc, 0xe7, 0x61,
- 0xf3, 0x09, 0xbb, 0xd6, 0x1d, 0x62, 0x86, 0x8d, 0xbf, 0xc2, 0x32, 0xf7,
- 0xcc, 0xd2, 0xc5, 0xfe, 0x92, 0x6f, 0x88, 0xb6, 0x58, 0xbf, 0xff, 0x7d,
- 0xf5, 0xf6, 0x92, 0x35, 0xa2, 0x66, 0xd9, 0x62, 0xfb, 0x1c, 0x1c, 0x58,
- 0xbe, 0x7e, 0x4c, 0x30, 0xfe, 0x34, 0xad, 0x7b, 0x61, 0xca, 0xc5, 0xfb,
- 0xaf, 0x7c, 0x98, 0x2c, 0x5e, 0xd3, 0x6e, 0xb1, 0x78, 0xf3, 0xf5, 0x8b,
- 0xd3, 0x00, 0xaa, 0xc5, 0x80, 0x33, 0xdc, 0xc1, 0xe2, 0x1d, 0xbc, 0x31,
- 0x4a, 0xc5, 0xff, 0x4f, 0x27, 0xdc, 0xc2, 0x82, 0xc5, 0xff, 0xb4, 0xe0,
- 0xfe, 0x1e, 0x63, 0xb1, 0x62, 0xf3, 0x10, 0xd6, 0x2f, 0xfc, 0xc6, 0xc9,
- 0x6e, 0xde, 0x63, 0x56, 0x2f, 0xb0, 0x11, 0xd9, 0xf3, 0xdc, 0xe0, 0xe5,
- 0xff, 0xff, 0xec, 0xdb, 0x92, 0x6b, 0x73, 0xd0, 0xc3, 0x4d, 0xce, 0xfd,
- 0xa9, 0xce, 0xd6, 0x2f, 0x68, 0xa0, 0xb1, 0x7f, 0xf8, 0x7f, 0xc1, 0xc7,
- 0xb9, 0x1b, 0xac, 0x08, 0xb1, 0x7f, 0xc4, 0x0f, 0x38, 0xf0, 0xa0, 0xb1,
- 0x69, 0xea, 0x8a, 0x5c, 0x1d, 0x65, 0x0a, 0x75, 0x50, 0x9f, 0x1d, 0x63,
- 0x82, 0x84, 0xef, 0x0e, 0xc5, 0x19, 0x15, 0xe0, 0xbf, 0xf1, 0x62, 0xfc,
- 0x6b, 0x96, 0x74, 0x58, 0xa0, 0xab, 0x25, 0xc6, 0x36, 0x12, 0x91, 0xd8,
- 0x42, 0x50, 0x64, 0xf9, 0x0e, 0xe7, 0x94, 0xcf, 0x11, 0x41, 0xc7, 0xff,
- 0x0a, 0xb6, 0x37, 0x00, 0xf1, 0x42, 0x23, 0xd2, 0xad, 0xc4, 0xc2, 0x61,
- 0x0d, 0xf1, 0xb2, 0x5b, 0xac, 0x5c, 0x67, 0x16, 0x2f, 0xfd, 0xee, 0x64,
- 0x4c, 0x0e, 0x66, 0xcb, 0x15, 0x03, 0xfe, 0xd1, 0x21, 0x0c, 0xdf, 0xc2,
- 0x6d, 0x40, 0x67, 0x58, 0xbf, 0x60, 0x7e, 0x30, 0xeb, 0x17, 0xee, 0xbd,
- 0xc3, 0x3c, 0xb1, 0x7f, 0xff, 0x8c, 0x90, 0x0f, 0xf3, 0xac, 0x27, 0x68,
- 0x73, 0x3c, 0xb1, 0x50, 0x44, 0x67, 0x0b, 0x2e, 0xe6, 0xcb, 0x17, 0xf1,
- 0x48, 0x7a, 0x93, 0xac, 0x5f, 0xff, 0x67, 0x84, 0x03, 0xb4, 0x39, 0x9d,
- 0x24, 0x6b, 0x14, 0x34, 0x4c, 0xe0, 0xc9, 0x17, 0x56, 0x91, 0xd5, 0xe8,
- 0x5e, 0x5f, 0xfd, 0x38, 0x0e, 0x41, 0xf5, 0xb0, 0x80, 0xb1, 0x7f, 0x03,
- 0x9a, 0xd6, 0x06, 0xb1, 0x77, 0xde, 0x23, 0xf6, 0x24, 0x6b, 0xf8, 0x5a,
- 0x06, 0x7d, 0x96, 0x2b, 0x73, 0xdb, 0xe1, 0x6d, 0xf7, 0x0e, 0xce, 0xb1,
- 0x50, 0x3c, 0x5f, 0x11, 0xdf, 0xfe, 0x87, 0x5d, 0x4f, 0x1e, 0x48, 0x00,
- 0x95, 0x8a, 0x93, 0xed, 0x62, 0x2b, 0xfe, 0xe6, 0x61, 0xa6, 0xb4, 0x25,
- 0x62, 0xff, 0x4f, 0xd9, 0xfd, 0x24, 0xb1, 0x7e, 0x1e, 0x70, 0x46, 0xac,
- 0x5f, 0x31, 0xf0, 0x6b, 0x17, 0xe1, 0xb1, 0x37, 0x45, 0x8b, 0x9b, 0x8b,
- 0x15, 0x87, 0x81, 0xa2, 0x9a, 0xed, 0x31, 0x8d, 0x1d, 0x11, 0x8f, 0x8a,
- 0xba, 0x31, 0x5f, 0xf7, 0xe7, 0xbf, 0x4f, 0xda, 0x3d, 0x62, 0x96, 0x2f,
- 0xfb, 0x4e, 0x2d, 0x80, 0x09, 0x08, 0xb1, 0x7f, 0xda, 0xf7, 0x9f, 0x5e,
- 0xcd, 0xd6, 0x2f, 0xff, 0x36, 0xb4, 0x23, 0x7d, 0x91, 0x41, 0x80, 0xb1,
- 0x7f, 0xbc, 0xfa, 0x6f, 0xb1, 0xd6, 0x2e, 0x32, 0x25, 0x8b, 0x85, 0xa5,
- 0x8b, 0xfb, 0x35, 0xcf, 0xe6, 0xeb, 0x16, 0xe8, 0xb1, 0x5d, 0x53, 0xb6,
- 0x0b, 0x67, 0xa3, 0x0c, 0xc3, 0xd3, 0x4e, 0xfb, 0x4d, 0xd1, 0x9f, 0xc6,
- 0x88, 0x62, 0x38, 0xbe, 0xfa, 0x22, 0x93, 0xac, 0x5b, 0xb5, 0x8b, 0xb0,
- 0x35, 0x8b, 0xbd, 0xe7, 0x35, 0x7e, 0x13, 0xa9, 0x4c, 0x47, 0x21, 0x2e,
- 0xe9, 0xd7, 0xb6, 0x21, 0x2c, 0x5f, 0xf8, 0xfa, 0x9f, 0xbe, 0xee, 0x4c,
- 0xb1, 0x68, 0x49, 0xee, 0x30, 0xf5, 0xe0, 0xc3, 0x0d, 0x51, 0x08, 0xc1,
- 0x7f, 0xc5, 0xbe, 0x6b, 0x76, 0x6d, 0xd5, 0x10, 0x8c, 0x11, 0x86, 0xca,
- 0xa2, 0x45, 0xbb, 0x2c, 0x5b, 0x65, 0x8b, 0xe3, 0x58, 0x80, 0xb1, 0x79,
- 0x9c, 0x22, 0xc5, 0x40, 0xf5, 0x1c, 0x4f, 0xe4, 0x75, 0x2c, 0x9e, 0x01,
- 0x97, 0x61, 0x7b, 0xc7, 0x42, 0x78, 0xea, 0xda, 0x33, 0x80, 0x4b, 0x14,
- 0x14, 0x68, 0xdd, 0x1d, 0xef, 0x70, 0x0c, 0xb1, 0x7f, 0x7f, 0x77, 0xe6,
- 0x0d, 0x62, 0xb6, 0x3c, 0xcd, 0xc7, 0x6f, 0xf3, 0x0f, 0x1f, 0xa3, 0x1d,
- 0x62, 0xff, 0xfd, 0xbe, 0x11, 0x3e, 0x6a, 0x47, 0xf6, 0x27, 0x58, 0xad,
- 0x22, 0x18, 0x46, 0x97, 0xff, 0xff, 0xe7, 0x3e, 0x73, 0x08, 0x5e, 0xfe,
- 0x74, 0x1c, 0xfd, 0xe7, 0xdf, 0x13, 0x1d, 0x62, 0xff, 0xc2, 0xdf, 0x35,
- 0xb4, 0xfc, 0x43, 0x58, 0xbf, 0x36, 0xff, 0x7d, 0x96, 0x29, 0xcf, 0xb3,
- 0x88, 0x57, 0xe1, 0xcb, 0x97, 0x96, 0x2b, 0x15, 0x02, 0x6a, 0x15, 0x5f,
- 0x23, 0xf4, 0x3b, 0xc3, 0x21, 0xbf, 0x3e, 0xa1, 0x1d, 0xe5, 0x8b, 0xff,
- 0x9b, 0x9b, 0x4f, 0xf3, 0x73, 0x23, 0x99, 0x62, 0x8e, 0x7e, 0xc4, 0x59,
- 0x7f, 0xff, 0xfb, 0xf8, 0x2d, 0x1b, 0xf7, 0xee, 0x7c, 0x2f, 0x96, 0x77,
- 0xe1, 0x37, 0x16, 0x2f, 0xfe, 0xce, 0xcc, 0xf3, 0x90, 0xa1, 0x9c, 0x58,
- 0xbf, 0xff, 0xff, 0xff, 0xff, 0xff, 0x61, 0x6c, 0x4c, 0x39, 0x2d, 0xa7,
- 0x43, 0xc2, 0xcf, 0x71, 0xf7, 0xc2, 0x33, 0x6c, 0xd4, 0xf0, 0x98, 0xde,
- 0x63, 0x80, 0x02, 0x01, 0x30, 0xe4, 0xb6, 0x9d, 0x2c, 0x5f, 0xb8, 0x69,
- 0xb9, 0x1e, 0xb1, 0x7c, 0x13, 0x3b, 0xf2, 0xc5, 0x49, 0xea, 0x31, 0x75,
- 0xfd, 0x02, 0xcc, 0x10, 0x5d, 0x62, 0xff, 0x37, 0xa1, 0x9a, 0xce, 0x2c,
- 0x54, 0xaa, 0x27, 0xc4, 0x6f, 0xc6, 0xba, 0xc4, 0x04, 0x63, 0x7f, 0xe7,
- 0xdf, 0xf9, 0x1c, 0x66, 0xa6, 0x0b, 0x17, 0xe6, 0x00, 0x1f, 0xeb, 0x17,
- 0xff, 0x67, 0x4f, 0x79, 0x9c, 0x8a, 0x4e, 0xb1, 0x74, 0xc3, 0xe7, 0xd9,
- 0xe2, 0x8a, 0xfa, 0x37, 0x4a, 0x16, 0x17, 0xed, 0xfc, 0x6b, 0xee, 0xb1,
- 0x7f, 0xfb, 0xf2, 0x5e, 0xeb, 0xf6, 0x1f, 0xdb, 0x4b, 0x14, 0xc7, 0xf1,
- 0xc2, 0xcb, 0xfe, 0xce, 0x7f, 0x18, 0xb2, 0x3d, 0x62, 0xec, 0xd9, 0x62,
- 0xff, 0x18, 0x6b, 0x84, 0x92, 0x82, 0xc5, 0xff, 0x16, 0x3e, 0x8a, 0x7b,
- 0x82, 0xc5, 0x62, 0x30, 0x74, 0x75, 0xf1, 0x86, 0x37, 0xbf, 0xff, 0xef,
- 0x0b, 0x6c, 0xfb, 0xfb, 0xf8, 0x7c, 0xd4, 0x33, 0xbf, 0x2c, 0x5f, 0xdf,
- 0x7f, 0xfe, 0x4e, 0xb1, 0x7e, 0x81, 0x4e, 0x71, 0x62, 0xf3, 0x16, 0xdb,
- 0x9e, 0xaf, 0x65, 0xd5, 0x04, 0x79, 0xfa, 0x17, 0xd7, 0xf1, 0x61, 0xbc,
- 0x6f, 0xac, 0x5f, 0x39, 0xb8, 0x35, 0x8b, 0xc6, 0xe0, 0xd6, 0x2e, 0xc3,
- 0xf5, 0x3c, 0x17, 0x23, 0xa3, 0xa2, 0x77, 0xcd, 0xf7, 0xff, 0x8f, 0x86,
- 0xbe, 0x8b, 0x3d, 0xec, 0xd9, 0x62, 0xff, 0xf4, 0x50, 0x9d, 0x89, 0x8d,
- 0xe1, 0x4c, 0x16, 0x29, 0x62, 0xd2, 0x03, 0xd8, 0xe2, 0x65, 0xff, 0x8c,
- 0xcf, 0xb1, 0xe3, 0x03, 0x0c, 0x35, 0x8b, 0xff, 0xf6, 0x6f, 0xf9, 0x21,
- 0x93, 0xed, 0x84, 0xe6, 0xac, 0x56, 0xc8, 0x9c, 0x82, 0x3d, 0xff, 0xdb,
- 0x01, 0xfb, 0xe6, 0xf8, 0xe5, 0xba, 0xc5, 0x31, 0xf6, 0x11, 0x25, 0x4a,
- 0x7e, 0x50, 0x85, 0x1b, 0x46, 0x5f, 0x7f, 0xfe, 0x29, 0x07, 0x37, 0xfb,
- 0xea, 0x22, 0x90, 0x71, 0x62, 0xf1, 0xf3, 0x8b, 0x15, 0x11, 0xfa, 0x1d,
- 0x5e, 0xfe, 0x9d, 0xdb, 0x7e, 0x41, 0x62, 0xff, 0xfe, 0xf7, 0x24, 0xd8,
- 0x3f, 0xd8, 0xbd, 0x0c, 0xd6, 0x2c, 0x5f, 0xf9, 0xf9, 0x83, 0xea, 0xc0,
- 0x8e, 0xc5, 0x8b, 0x85, 0xd1, 0x62, 0xff, 0x49, 0xfb, 0xf4, 0xe7, 0x6b,
- 0x17, 0xfc, 0xfd, 0x3e, 0xd0, 0xd4, 0x9a, 0xb1, 0x7f, 0xf4, 0x83, 0x3d,
- 0x3b, 0x94, 0xfb, 0x8b, 0x15, 0xf4, 0x40, 0x11, 0xe5, 0x62, 0x71, 0xfb,
- 0xad, 0xe9, 0x0f, 0xe3, 0x5e, 0x85, 0xad, 0xf4, 0xc3, 0x91, 0xcb, 0x17,
- 0xf7, 0xba, 0x9e, 0x73, 0xcb, 0x17, 0xff, 0xdd, 0xf9, 0xc3, 0xe7, 0xdf,
- 0xb0, 0x69, 0x86, 0xb1, 0x58, 0x88, 0x4d, 0x18, 0x5f, 0xbc, 0xe2, 0x23,
- 0x56, 0x2a, 0x4f, 0x2c, 0x44, 0x57, 0xff, 0xd1, 0x14, 0x9f, 0xb8, 0x78,
- 0x43, 0xce, 0xfc, 0xb1, 0x7f, 0xff, 0xec, 0x87, 0x7e, 0xd4, 0xe7, 0x63,
- 0xfe, 0x1c, 0xb3, 0xa3, 0x92, 0xc5, 0xfb, 0x6f, 0x93, 0x76, 0xb1, 0x7f,
- 0x60, 0x78, 0x42, 0x02, 0xc5, 0xfa, 0x19, 0xe9, 0x02, 0xc5, 0xf6, 0x02,
- 0x40, 0xb1, 0x5b, 0x1f, 0xc7, 0x65, 0xc4, 0x51, 0x69, 0xd2, 0x34, 0x8f,
- 0x0a, 0x2b, 0xff, 0x9f, 0x85, 0x3e, 0xe6, 0x74, 0x73, 0x56, 0x2f, 0xff,
- 0xfe, 0x01, 0xda, 0x1f, 0x67, 0xf3, 0x8f, 0x07, 0x9e, 0x73, 0xbe, 0x96,
- 0x2b, 0x15, 0x3b, 0xfd, 0x53, 0x91, 0xa0, 0x78, 0xb4, 0x48, 0xd7, 0xed,
- 0x60, 0xfa, 0x4a, 0xc5, 0xff, 0xbe, 0xc1, 0x37, 0xfb, 0x9e, 0x77, 0x58,
- 0xa5, 0x8a, 0x58, 0xad, 0xcb, 0x82, 0x0c, 0xbf, 0xfa, 0x7e, 0xcf, 0xe0,
- 0x64, 0x23, 0xb1, 0x62, 0xf1, 0x48, 0x6b, 0x17, 0x67, 0x31, 0x1b, 0xdb,
- 0xad, 0xe8, 0x80, 0xe8, 0xd4, 0xe9, 0xa8, 0x14, 0x61, 0x17, 0xff, 0x9b,
- 0x46, 0x99, 0x21, 0xe7, 0x38, 0xc6, 0xac, 0x5f, 0x1e, 0x47, 0x2b, 0x17,
- 0xfe, 0xd9, 0x87, 0xf6, 0x86, 0x77, 0xe5, 0x8a, 0xd8, 0xf8, 0xc4, 0x45,
- 0x5b, 0x36, 0x50, 0x30, 0x21, 0x1c, 0xaa, 0x2c, 0x8c, 0xac, 0xd8, 0x4f,
- 0xef, 0x0e, 0x2e, 0xe3, 0x2e, 0x78, 0x62, 0xc5, 0x28, 0x57, 0x50, 0xae,
- 0x39, 0x1f, 0xe3, 0xbf, 0x02, 0x87, 0x21, 0xeb, 0xe9, 0x53, 0x1d, 0x23,
- 0xa1, 0x0c, 0xa0, 0xc8, 0x58, 0xdf, 0xe3, 0x64, 0xb3, 0xdf, 0x75, 0x8b,
- 0xff, 0xdc, 0x1c, 0xb1, 0x6d, 0xe7, 0xe3, 0xf4, 0x58, 0xb4, 0x9a, 0x7f,
- 0xfe, 0x33, 0xbf, 0xfe, 0xda, 0x75, 0xd4, 0x78, 0x5b, 0x60, 0x8b, 0xcb,
- 0x17, 0xee, 0x4e, 0xd8, 0x1a, 0xc5, 0xa4, 0x8f, 0xf7, 0x8a, 0x77, 0xff,
- 0xc3, 0xf0, 0x9b, 0xbf, 0x03, 0x07, 0xd7, 0xee, 0xb1, 0x7f, 0xfc, 0xfd,
- 0x07, 0x25, 0x3e, 0xe6, 0x08, 0xbc, 0xb1, 0x7f, 0xff, 0xf3, 0xfb, 0x99,
- 0xd7, 0xdc, 0x68, 0x75, 0xdf, 0xee, 0x3d, 0x38, 0xb6, 0x58, 0xbf, 0xfc,
- 0xdf, 0xfb, 0x8f, 0x3d, 0xc1, 0x17, 0x96, 0x28, 0xe8, 0xc3, 0xe8, 0xf3,
- 0x7f, 0x9f, 0xa6, 0x73, 0x99, 0x1e, 0xb1, 0x7d, 0xe2, 0x17, 0x96, 0x2e,
- 0x11, 0x2c, 0x5e, 0xc3, 0xe6, 0x8d, 0xd7, 0xc8, 0xef, 0xf8, 0xfd, 0x75,
- 0x81, 0x3f, 0x87, 0x58, 0xa9, 0x4c, 0x1a, 0x04, 0xbf, 0x72, 0x63, 0x1a,
- 0x1a, 0xac, 0xf6, 0x26, 0xe2, 0xa7, 0xa5, 0x0c, 0xdc, 0x6b, 0xac, 0x5f,
- 0xcf, 0x25, 0xe3, 0x0e, 0xb1, 0x5a, 0x3c, 0x6f, 0x0c, 0x5f, 0xfb, 0x37,
- 0xcd, 0x69, 0xa0, 0x2c, 0x58, 0xbf, 0x8c, 0xd1, 0xca, 0x43, 0x58, 0xaf,
- 0x1f, 0x79, 0x87, 0xf7, 0xe7, 0x10, 0x5f, 0x38, 0xb1, 0x58, 0x8e, 0x06,
- 0x84, 0x8f, 0x88, 0xea, 0x5b, 0xa2, 0x8c, 0xac, 0xd3, 0x5e, 0x3c, 0x96,
- 0x96, 0xe8, 0x28, 0xda, 0xef, 0x06, 0x18, 0x69, 0x17, 0xfd, 0x80, 0x6d,
- 0x67, 0x4c, 0x1a, 0x44, 0x61, 0xa1, 0xb8, 0x30, 0xd2, 0x2f, 0x06, 0x18,
- 0x69, 0x17, 0xf3, 0x6c, 0x3f, 0xcf, 0x12, 0x23, 0x0d, 0x0d, 0x12, 0x32,
- 0x83, 0x4d, 0x8e, 0x3b, 0xbf, 0x6e, 0xe3, 0x30, 0xe9, 0x11, 0x86, 0xce,
- 0xf0, 0x61, 0x86, 0x91, 0x7b, 0x93, 0xa4, 0x88, 0xc3, 0x43, 0x7c, 0xc5,
- 0xdf, 0x96, 0x2c, 0x07, 0x45, 0x97, 0x97, 0xc3, 0x30, 0xbf, 0x88, 0x1d,
- 0x43, 0xcf, 0xac, 0x58, 0x28, 0xb1, 0x4c, 0x78, 0xf1, 0xc6, 0x37, 0xfc,
- 0xe5, 0xb9, 0x60, 0x6c, 0x05, 0x8b, 0xf8, 0x4d, 0xb1, 0x0f, 0xb5, 0x8b,
- 0xe9, 0x83, 0x6e, 0xb1, 0x5f, 0x3d, 0x32, 0x30, 0xbd, 0x91, 0x3a, 0xc5,
- 0x0c, 0xdf, 0x18, 0x43, 0x7e, 0xe0, 0xb6, 0x8e, 0x25, 0x8b, 0xf0, 0xdf,
- 0xa4, 0x8d, 0x62, 0xfb, 0x0b, 0x23, 0xd6, 0x2b, 0x47, 0x9c, 0x72, 0xaa,
- 0x74, 0x4e, 0x98, 0xf7, 0x7f, 0xe6, 0x81, 0x31, 0xb1, 0x13, 0xc4, 0xb1,
- 0x70, 0x99, 0x62, 0xbe, 0x7a, 0xfe, 0x40, 0xbf, 0xa3, 0x59, 0x60, 0x6c,
- 0x05, 0x8b, 0xc1, 0x86, 0x1a, 0x45, 0xe2, 0x60, 0xd2, 0x23, 0x0d, 0x0d,
- 0xf0, 0xf0, 0x86, 0xb1, 0x7f, 0xdb, 0x4f, 0x7c, 0x72, 0xc0, 0x2c, 0x5f,
- 0x34, 0x1c, 0x0b, 0x17, 0xe7, 0x37, 0xd9, 0xba, 0xc5, 0x6e, 0x8a, 0x8d,
- 0x11, 0x7c, 0xe8, 0x88, 0xaf, 0xd9, 0xb1, 0xf0, 0xeb, 0x17, 0xf4, 0xec,
- 0x3f, 0xcf, 0x16, 0x2f, 0xf4, 0xe6, 0xf9, 0xd1, 0xc6, 0xb1, 0x7f, 0x0b,
- 0x63, 0x3c, 0xf0, 0x58, 0xb6, 0x6e, 0x89, 0x52, 0x2f, 0xe1, 0xad, 0x46,
- 0xb5, 0x4b, 0xa3, 0x55, 0xc8, 0x6c, 0x11, 0xec, 0x74, 0x2f, 0xaf, 0xef,
- 0xe7, 0x4c, 0xf7, 0x16, 0x2b, 0x75, 0x61, 0x80, 0x94, 0xff, 0xe5, 0xda,
- 0x82, 0xeb, 0x68, 0xc9, 0x35, 0x0c, 0xaf, 0xc2, 0xfc, 0xa5, 0xc3, 0x5f,
- 0xef, 0x43, 0x3f, 0xf6, 0x82, 0xc5, 0xb4, 0xb1, 0x73, 0x8d, 0x62, 0x8d,
- 0x35, 0x3f, 0x12, 0xbf, 0x45, 0xad, 0x3e, 0xcb, 0x17, 0xec, 0x2f, 0xe1,
- 0x2c, 0x5f, 0x3b, 0x10, 0xd6, 0x2e, 0x10, 0x16, 0x2f, 0xdf, 0xc7, 0xd4,
- 0x16, 0x28, 0x67, 0xc2, 0x02, 0x1f, 0x0c, 0x5f, 0xa7, 0x22, 0x7d, 0x2c,
- 0x56, 0xc7, 0xae, 0x45, 0xf7, 0x6d, 0xe5, 0x8a, 0x96, 0x40, 0x56, 0x4e,
- 0xf5, 0x1a, 0xbb, 0xba, 0xeb, 0x91, 0x7c, 0xad, 0xa1, 0xbc, 0x44, 0x57,
- 0xd1, 0xdf, 0xcd, 0xd6, 0x2f, 0x80, 0xe5, 0xe5, 0x8a, 0xd8, 0xf2, 0x78,
- 0x4f, 0x70, 0x5a, 0x85, 0x16, 0x2f, 0x09, 0x86, 0xb1, 0x7d, 0xe9, 0x0f,
- 0x8b, 0x17, 0xb9, 0x3e, 0x58, 0xb8, 0x01, 0xac, 0x5f, 0xb8, 0x22, 0x30,
- 0xeb, 0x16, 0xe4, 0x6c, 0x88, 0x48, 0x89, 0x18, 0x77, 0xc3, 0x35, 0x89,
- 0x97, 0xf6, 0x47, 0xf2, 0x3f, 0x42, 0x86, 0xff, 0xf4, 0xea, 0x5a, 0x23,
- 0xb0, 0xff, 0x24, 0xb1, 0x7f, 0xef, 0xb4, 0x33, 0x40, 0x3b, 0xf1, 0x62,
- 0x8d, 0x44, 0x47, 0x92, 0x6f, 0xd8, 0x1e, 0x6b, 0x65, 0x8b, 0xf6, 0xf3,
- 0xf9, 0x3a, 0xc5, 0xcd, 0xe5, 0x8b, 0xe8, 0xf6, 0x20, 0x6c, 0x7d, 0x58,
- 0x54, 0x45, 0x37, 0xfb, 0x0d, 0x35, 0xa1, 0x01, 0xac, 0x5f, 0xcc, 0xc3,
- 0xf0, 0x99, 0x62, 0xf8, 0x6c, 0x40, 0xc3, 0xe3, 0x23, 0x6a, 0x94, 0xdb,
- 0xb2, 0x11, 0xc2, 0x85, 0x55, 0xff, 0x0c, 0xef, 0xae, 0x31, 0x01, 0x62,
- 0xc1, 0x45, 0x8b, 0xfe, 0xfc, 0xc2, 0x0f, 0xcc, 0x1a, 0xc5, 0x80, 0x16,
- 0x1e, 0x7f, 0x85, 0xaf, 0xf1, 0xdb, 0xb9, 0xd4, 0x4c, 0xb1, 0x7f, 0xb5,
- 0x3d, 0x3c, 0x4c, 0x05, 0x8b, 0x7a, 0x4f, 0xab, 0x0d, 0x6a, 0x51, 0x7a,
- 0xf0, 0x97, 0xbf, 0xfa, 0x4f, 0x8f, 0x13, 0x34, 0x37, 0x82, 0xc5, 0x40,
- 0xfa, 0xc8, 0x9a, 0xff, 0xed, 0x0b, 0x6e, 0xb9, 0xf9, 0xe7, 0xdd, 0x62,
- 0xf8, 0x20, 0xa2, 0x3a, 0xc5, 0x3a, 0xa4, 0x08, 0xa3, 0xb0, 0xd1, 0x0f,
- 0xd2, 0x2f, 0xff, 0xdf, 0x9e, 0x78, 0xa6, 0x22, 0x91, 0xe7, 0x7e, 0x58,
- 0xbe, 0x1f, 0xe7, 0x65, 0x8b, 0xf6, 0x86, 0x31, 0x6c, 0xb1, 0x7a, 0x4a,
- 0x03, 0x45, 0x29, 0x2b, 0x18, 0x49, 0x7e, 0xcd, 0x47, 0x1c, 0x6b, 0x17,
- 0xfe, 0xef, 0xc6, 0x9a, 0xdf, 0x21, 0x79, 0x62, 0x86, 0x7d, 0xf8, 0x59,
- 0x7b, 0xef, 0x12, 0x45, 0x68, 0xdf, 0xf0, 0x86, 0xff, 0x9b, 0xbf, 0x64,
- 0x42, 0xd1, 0xab, 0x16, 0xdd, 0xcf, 0x78, 0x44, 0x37, 0xf8, 0xb3, 0xb8,
- 0x71, 0xcd, 0x58, 0xbc, 0xfb, 0xca, 0xc5, 0xf9, 0xf5, 0xb0, 0xb8, 0xb1,
- 0x5a, 0x3c, 0x73, 0x8e, 0xdc, 0x66, 0x96, 0x2f, 0x68, 0x5b, 0x2c, 0x5e,
- 0x6d, 0x1a, 0xb1, 0x63, 0xac, 0x56, 0x22, 0x28, 0xd2, 0x2d, 0x0c, 0xb0,
- 0xff, 0x41, 0xeb, 0xff, 0x0f, 0xf3, 0xcc, 0xd6, 0xd3, 0x05, 0x8b, 0xc6,
- 0x8b, 0x75, 0x8b, 0x1a, 0xb1, 0x7f, 0xf6, 0x6f, 0xf9, 0xfe, 0x6b, 0x52,
- 0x6a, 0xc5, 0xc0, 0xe4, 0x9e, 0xce, 0x84, 0xe8, 0xd4, 0x53, 0x3b, 0xcd,
- 0x75, 0x54, 0xb5, 0xb4, 0x60, 0xd1, 0x25, 0x94, 0x39, 0xaf, 0xf6, 0x6e,
- 0x09, 0xce, 0xe0, 0xb1, 0x6d, 0x2c, 0x56, 0x1e, 0x39, 0xcd, 0x6f, 0xfc,
- 0x2e, 0x61, 0x4f, 0xc6, 0x61, 0xd6, 0x2f, 0xf6, 0xa4, 0x3c, 0x27, 0x35,
- 0x62, 0xe7, 0x1a, 0xc5, 0xfe, 0xf6, 0x85, 0xcf, 0xb4, 0x34, 0x79, 0x60,
- 0x34, 0xbe, 0x96, 0x3f, 0x44, 0x8b, 0xda, 0xc8, 0xd9, 0x62, 0xff, 0x9c,
- 0xd3, 0x0a, 0x7e, 0xfb, 0x2c, 0x5f, 0xfd, 0xf7, 0x60, 0x02, 0x41, 0x3f,
- 0xe2, 0xc5, 0xfd, 0xfc, 0x39, 0xda, 0x0b, 0x17, 0x83, 0x0c, 0x34, 0x8b,
- 0xfc, 0x5e, 0xfb, 0xc9, 0x6c, 0x91, 0x18, 0x68, 0x6f, 0xa7, 0x4d, 0xf5,
- 0x8a, 0x82, 0x2d, 0xf1, 0x3f, 0xc8, 0xd7, 0xf4, 0x8c, 0x79, 0xdc, 0x16,
- 0x2f, 0xe7, 0xd4, 0x0c, 0x90, 0x2c, 0x5d, 0x20, 0xc4, 0x46, 0x91, 0x7c,
- 0x71, 0x7d, 0x62, 0xa2, 0x1d, 0xc8, 0xbc, 0x76, 0x64, 0x71, 0x17, 0xf6,
- 0xa0, 0x64, 0x1f, 0x65, 0x8b, 0xcc, 0x0e, 0x2c, 0x5d, 0x9d, 0x70, 0xf3,
- 0xbc, 0x63, 0x5b, 0xab, 0x07, 0x3c, 0xa4, 0x5e, 0x90, 0x94, 0xbf, 0xe6,
- 0x01, 0x64, 0x50, 0x9e, 0xd6, 0x2f, 0xfd, 0x3d, 0xff, 0x3b, 0x06, 0x7b,
- 0x8b, 0x15, 0x2b, 0x81, 0xd9, 0x2d, 0x49, 0xd0, 0x44, 0x75, 0x7e, 0xfb,
- 0x8d, 0xa0, 0xb1, 0x7e, 0xcd, 0x69, 0xe2, 0x58, 0xb9, 0x8b, 0x73, 0xd1,
- 0x22, 0x8b, 0xfe, 0x70, 0x46, 0xdc, 0xcd, 0x30, 0x16, 0x2f, 0x61, 0x6e,
- 0xb1, 0x7f, 0x11, 0x9a, 0x21, 0x41, 0x62, 0xfd, 0xc3, 0xbe, 0xb8, 0xb1,
- 0x5b, 0x23, 0x7f, 0x45, 0x87, 0x3e, 0x61, 0xd0, 0x17, 0xdf, 0xff, 0xd0,
- 0xfb, 0x43, 0x7f, 0xbf, 0xa1, 0x9f, 0xfb, 0x41, 0x62, 0xfd, 0x20, 0x9f,
- 0xf1, 0x62, 0xb1, 0x10, 0xa0, 0x5d, 0xbf, 0xf8, 0xc2, 0x97, 0x1f, 0xf2,
- 0x1f, 0x75, 0x8b, 0x8c, 0xc5, 0x8b, 0xfe, 0x9d, 0x03, 0xdf, 0x61, 0xba,
- 0xc5, 0x61, 0xe8, 0x98, 0x31, 0x7f, 0xd0, 0x8a, 0x0d, 0xee, 0x3c, 0xac,
- 0x5f, 0xff, 0x37, 0x85, 0x2f, 0x3d, 0xef, 0xfc, 0xef, 0x8b, 0x17, 0xed,
- 0x69, 0xfd, 0xc5, 0x8a, 0xea, 0x9b, 0x60, 0xe1, 0x2b, 0xd9, 0x10, 0x0e,
- 0x8c, 0x52, 0xbf, 0xfe, 0x04, 0x76, 0x4f, 0x3f, 0x3d, 0xf8, 0xd1, 0x69,
- 0x62, 0xff, 0xe8, 0xa0, 0x22, 0xf4, 0x33, 0x59, 0xc5, 0x8b, 0xff, 0xf1,
- 0x6f, 0xf7, 0x8a, 0x12, 0x5e, 0xd6, 0xa6, 0x0b, 0x1c, 0x3c, 0x6b, 0xff,
- 0xf9, 0xf9, 0xa7, 0x6d, 0x4b, 0xfb, 0xf9, 0xce, 0x62, 0xc5, 0xff, 0xb5,
- 0x30, 0x7f, 0x03, 0x22, 0xe2, 0xc5, 0xfe, 0xc9, 0x83, 0xf8, 0xa5, 0x62,
- 0xc0, 0xc4, 0xcc, 0x8e, 0xd1, 0xc5, 0x98, 0xe4, 0x0b, 0xf9, 0xa0, 0xd0,
- 0x7f, 0xac, 0x54, 0xaa, 0x95, 0xc5, 0x46, 0x8f, 0x38, 0x48, 0xd7, 0xff,
- 0xf3, 0x00, 0xb0, 0xe4, 0xde, 0xe1, 0x9a, 0x79, 0x1a, 0xc5, 0xd0, 0xe2,
- 0xc5, 0xa0, 0x33, 0xf2, 0x75, 0xab, 0xff, 0xc4, 0xda, 0x34, 0x27, 0xb4,
- 0x2e, 0xe1, 0xc5, 0x8a, 0x93, 0xf7, 0x72, 0x7b, 0xff, 0x30, 0xff, 0x3d,
- 0xb6, 0xfc, 0x82, 0xc5, 0x4b, 0x6d, 0x55, 0x09, 0x47, 0x39, 0x29, 0xe4,
- 0xd8, 0x75, 0x77, 0x1a, 0x63, 0xca, 0x82, 0x8a, 0x12, 0x9a, 0x21, 0xfc,
- 0xe4, 0xcb, 0x46, 0xe8, 0x08, 0x67, 0x94, 0xe1, 0x1f, 0x23, 0x2b, 0x11,
- 0x05, 0xff, 0xfd, 0xe7, 0x3e, 0x17, 0xb9, 0x26, 0xf0, 0x43, 0xfb, 0xac,
- 0x5d, 0x9d, 0xac, 0x5f, 0x9b, 0xc1, 0xe7, 0xd6, 0x2f, 0x0f, 0xf8, 0xb1,
- 0x7d, 0x8f, 0xf3, 0x56, 0x2b, 0xe7, 0xd2, 0xc5, 0x20, 0x1d, 0xbf, 0xa7,
- 0x6d, 0x0a, 0x40, 0xb1, 0x7f, 0xfd, 0x9b, 0xc9, 0x37, 0xb8, 0x31, 0x36,
- 0xa0, 0xb1, 0x5b, 0x26, 0x5d, 0xdc, 0x20, 0x62, 0x2e, 0x39, 0x7d, 0xf7,
- 0x3f, 0x9c, 0x58, 0xbe, 0x7f, 0x4f, 0x96, 0x29, 0xcf, 0x17, 0x44, 0x77,
- 0xce, 0x0c, 0x1a, 0xc5, 0xfd, 0x25, 0xbc, 0x6e, 0x16, 0x46, 0x8b, 0x16,
- 0x95, 0x8b, 0xde, 0x7d, 0x96, 0x2b, 0x63, 0x5f, 0xd8, 0x8d, 0xfa, 0x4f,
- 0xa9, 0xe8, 0xb1, 0x7f, 0xfb, 0xce, 0x1f, 0x0a, 0x7d, 0xcd, 0x6a, 0x56,
- 0x2e, 0x92, 0x58, 0xbd, 0x87, 0x8e, 0x58, 0xbe, 0xc2, 0x33, 0xcb, 0x15,
- 0x03, 0xd9, 0x18, 0xb6, 0x88, 0x2f, 0x0e, 0x4d, 0x58, 0xbf, 0xfa, 0x77,
- 0xf1, 0x48, 0x79, 0xee, 0x71, 0x62, 0xff, 0x9a, 0x4c, 0x7f, 0xfd, 0xe2,
- 0x58, 0xbf, 0xee, 0x67, 0x1c, 0xec, 0x40, 0x58, 0xbf, 0x8a, 0x61, 0xfe,
- 0x01, 0x62, 0xff, 0xcd, 0xfd, 0x4f, 0x9f, 0x77, 0x1a, 0xc5, 0xff, 0xf1,
- 0x0b, 0xdc, 0xcd, 0xfb, 0xf3, 0x31, 0xf8, 0xb1, 0x7f, 0xbf, 0x8f, 0xa8,
- 0x18, 0x75, 0x8a, 0xc4, 0x43, 0xf9, 0x4a, 0xec, 0x02, 0xc5, 0x4a, 0x6c,
- 0xa3, 0x38, 0xf9, 0x77, 0x21, 0x8d, 0xe2, 0x2a, 0x75, 0x4a, 0x5a, 0x1e,
- 0xfa, 0x30, 0x23, 0x9f, 0xbf, 0xec, 0x3e, 0x45, 0x27, 0xc0, 0xd6, 0x2f,
- 0xf3, 0xe8, 0xcf, 0x79, 0xf6, 0x58, 0xbe, 0xd4, 0xe7, 0x6b, 0x15, 0x03,
- 0xd9, 0xf1, 0xb5, 0xf4, 0xf9, 0xfc, 0xb1, 0x7f, 0xff, 0xe6, 0x3c, 0xeb,
- 0x71, 0xfe, 0x78, 0x26, 0x78, 0x73, 0xed, 0x05, 0x8a, 0x74, 0x58, 0xfc,
- 0x88, 0x88, 0xaf, 0xec, 0x78, 0xbe, 0x23, 0xac, 0x5f, 0x83, 0x6f, 0xc9,
- 0xd6, 0x2f, 0x6f, 0x3c, 0x58, 0xbf, 0xf8, 0xc8, 0x67, 0xdb, 0xef, 0xad,
- 0x4a, 0xc5, 0xff, 0xd3, 0xc6, 0xf4, 0x33, 0x5a, 0x68, 0x2c, 0x54, 0xa3,
- 0x43, 0x0a, 0x40, 0x3c, 0x24, 0x5b, 0xe8, 0x31, 0x01, 0x62, 0xff, 0xf3,
- 0xf8, 0x5a, 0x6e, 0x41, 0xf9, 0x3b, 0x2c, 0x5b, 0xf8, 0x7d, 0xac, 0x45,
- 0x7b, 0x9d, 0x31, 0x62, 0xe9, 0xd2, 0xc5, 0x78, 0xdb, 0x47, 0x0f, 0xdf,
- 0xdd, 0x24, 0xb7, 0x8e, 0xc5, 0x8b, 0xfb, 0x36, 0xe4, 0x7b, 0xee, 0xb1,
- 0x52, 0x88, 0xa7, 0x24, 0x23, 0x3b, 0xf0, 0xb4, 0x6f, 0xdd, 0x62, 0xf0,
- 0x0e, 0xeb, 0x15, 0xd5, 0x95, 0xdd, 0x31, 0xc5, 0x6d, 0x08, 0xb8, 0x10,
- 0x8c, 0x8b, 0x1b, 0x77, 0x23, 0xec, 0xa9, 0xe1, 0x49, 0xa9, 0x50, 0x3f,
- 0x44, 0x68, 0xd1, 0x00, 0x5c, 0x50, 0xff, 0xe4, 0x2a, 0x3d, 0x0e, 0x68,
- 0xe2, 0xd3, 0x0a, 0xac, 0x1a, 0xc5, 0xff, 0x10, 0x98, 0xd0, 0x1e, 0x60,
- 0xb1, 0x5a, 0x3c, 0xd0, 0x09, 0xdc, 0x20, 0x2c, 0x5f, 0xe2, 0x60, 0xf0,
- 0x98, 0xd5, 0x8b, 0xff, 0xb3, 0xdc, 0x33, 0x87, 0x29, 0xd4, 0xac, 0x58,
- 0xb6, 0x44, 0x80, 0xc6, 0x0e, 0x67, 0x7f, 0xe6, 0xf6, 0xff, 0x7e, 0xf9,
- 0x21, 0xac, 0x5b, 0xa6, 0x1f, 0xc7, 0xcd, 0xaf, 0x87, 0xa6, 0x89, 0x62,
- 0xff, 0xa7, 0xdf, 0x7e, 0x99, 0xdf, 0x96, 0x2f, 0xce, 0x10, 0x78, 0x75,
- 0x8a, 0xdc, 0xf9, 0xbe, 0x79, 0x7c, 0x39, 0x2f, 0x2c, 0x5f, 0xfe, 0xc3,
- 0x9e, 0x4b, 0x79, 0xf7, 0x3e, 0xeb, 0x17, 0xfe, 0x9d, 0x13, 0x6d, 0x3a,
- 0x98, 0x2c, 0x54, 0xa6, 0xaf, 0x90, 0x8a, 0x72, 0x32, 0x22, 0x0d, 0x2a,
- 0x9d, 0x3c, 0xdf, 0xc7, 0x01, 0x7f, 0xff, 0xbe, 0xe1, 0xe0, 0x47, 0x3b,
- 0x7b, 0x82, 0x86, 0x77, 0xe5, 0x8b, 0xff, 0xef, 0xcf, 0x3b, 0xdd, 0xfb,
- 0xce, 0x67, 0x7e, 0x58, 0xbf, 0xf3, 0x80, 0xcf, 0xc9, 0xd9, 0xbc, 0xb1,
- 0x43, 0x44, 0x9e, 0x95, 0x2f, 0xff, 0xed, 0x87, 0xf9, 0xe6, 0x77, 0xc9,
- 0xd7, 0xb9, 0x9b, 0x2c, 0x50, 0xd3, 0x7a, 0xd4, 0x3e, 0x08, 0x8e, 0xe9,
- 0x75, 0x8a, 0x95, 0xce, 0x5c, 0x95, 0xee, 0xd1, 0xd1, 0x80, 0xd6, 0xff,
- 0xa2, 0xdf, 0xee, 0x79, 0xd1, 0xab, 0x17, 0xe7, 0xec, 0x0d, 0xc5, 0x8b,
- 0xde, 0x98, 0x96, 0x2f, 0x3e, 0xa2, 0x93, 0xc7, 0xc2, 0x9b, 0xfa, 0x7f,
- 0x3e, 0x9f, 0xac, 0x5f, 0x04, 0x72, 0xdd, 0x62, 0xb0, 0xf4, 0x82, 0x16,
- 0xdf, 0xb6, 0xea, 0x29, 0x89, 0x62, 0xe6, 0x89, 0x62, 0xd0, 0x58, 0xbf,
- 0x43, 0xcf, 0xad, 0xd6, 0x2f, 0x18, 0x51, 0x2c, 0x57, 0x53, 0xf3, 0x80,
- 0xc7, 0x62, 0x40, 0x2a, 0xac, 0x54, 0x15, 0xbc, 0x21, 0x35, 0x08, 0x46,
- 0x23, 0xe4, 0x28, 0x2b, 0xac, 0x60, 0x4c, 0xb1, 0xb9, 0xa4, 0x68, 0x3d,
- 0x34, 0x8a, 0x2d, 0xa7, 0xdb, 0x21, 0x4d, 0xff, 0x1d, 0x34, 0x43, 0x2d,
- 0x55, 0xd9, 0xb1, 0xf3, 0xef, 0x2b, 0xdb, 0xb4, 0x37, 0x9f, 0xdd, 0x8f,
- 0x8e, 0x5a, 0x2a, 0x59, 0x6e, 0xa7, 0xe5, 0xcf, 0x4b, 0xc8, 0xfd, 0x69,
- 0x70, 0xd4, 0xa0, 0xa0, 0x52, 0xd8, 0xca, 0xbd, 0x17, 0xe5, 0x29, 0x0b,
- 0xd5, 0xc5, 0x08, 0xa9, 0x7e, 0xc1, 0xcf, 0x2c, 0x99, 0x29, 0x52, 0xe9,
- 0x3a, 0xc5, 0xff, 0x1d, 0x83, 0x32, 0x0e, 0x0e, 0x2c, 0x5e, 0xfe, 0x71,
- 0x62, 0xe3, 0x37, 0x58, 0xba, 0x4e, 0xb1, 0x6f, 0x00, 0xd8, 0xf8, 0x6a,
- 0xff, 0x39, 0xbe, 0xef, 0x77, 0xfa, 0xc5, 0x76, 0x7b, 0xc4, 0x4f, 0x43,
- 0x46, 0x76, 0x42, 0xb2, 0xf0, 0x47, 0xe8, 0xb1, 0x7f, 0xbe, 0xfe, 0xfb,
- 0xc8, 0x16, 0x2e, 0x6d, 0x2c, 0x5c, 0xff, 0x58, 0xbe, 0xcc, 0x2f, 0x2c,
- 0x5d, 0x24, 0xb1, 0x50, 0x3e, 0x5f, 0x8b, 0xf0, 0x5f, 0xa1, 0x0d, 0xff,
- 0xf6, 0x14, 0x67, 0x8d, 0x7e, 0xf9, 0xfc, 0x03, 0x2c, 0x5f, 0xdd, 0x62,
- 0x84, 0xeb, 0x65, 0x8b, 0xff, 0xe1, 0xcb, 0x6b, 0xe1, 0xb0, 0xe3, 0x9b,
- 0x68, 0xe5, 0x8a, 0x82, 0x63, 0xa3, 0x3e, 0x89, 0x53, 0xc6, 0x77, 0x99,
- 0x83, 0x58, 0xbf, 0x6f, 0x9e, 0xfb, 0xac, 0x50, 0xcf, 0x18, 0x87, 0x6f,
- 0xff, 0x6a, 0x29, 0x3f, 0x53, 0xe7, 0xb8, 0xfc, 0x58, 0xa6, 0x3e, 0xf1,
- 0x10, 0xdf, 0xe8, 0x79, 0xfd, 0xec, 0x02, 0xc5, 0xef, 0xb8, 0x5d, 0x62,
- 0xfe, 0x68, 0x60, 0xdb, 0xeb, 0x15, 0xb9, 0xe7, 0x1c, 0x86, 0xfb, 0xb8,
- 0x67, 0x96, 0x2f, 0xd0, 0xeb, 0x86, 0x62, 0xc5, 0xff, 0xa4, 0x41, 0x79,
- 0x1c, 0x9c, 0xa5, 0x62, 0xba, 0xa2, 0x42, 0x49, 0x06, 0x57, 0x7b, 0x76,
- 0xdd, 0x62, 0xf3, 0xea, 0x56, 0x2f, 0xd0, 0x33, 0x93, 0x8b, 0x15, 0x87,
- 0x8a, 0xc3, 0x97, 0xff, 0xe3, 0x96, 0x77, 0xe0, 0xf1, 0xfa, 0x69, 0x9a,
- 0x0b, 0x16, 0xe7, 0xcf, 0xe1, 0x88, 0x2f, 0xfe, 0xf3, 0x6c, 0xc5, 0xa9,
- 0xdf, 0x34, 0xb1, 0x7d, 0xee, 0x31, 0xd6, 0x2b, 0xa9, 0xf4, 0x06, 0x8b,
- 0x7f, 0xff, 0xd9, 0xf6, 0x33, 0x98, 0x6b, 0x10, 0x24, 0xa6, 0x2f, 0xca,
- 0xc5, 0xa5, 0x62, 0xff, 0xfd, 0x3a, 0xfc, 0x9c, 0x20, 0xa4, 0xa6, 0x2f,
- 0xca, 0xc5, 0xf9, 0xf5, 0x14, 0xff, 0x48, 0xce, 0x03, 0x31, 0x08, 0xdc,
- 0x2d, 0x2c, 0x56, 0xcc, 0x84, 0x48, 0x46, 0x15, 0x84, 0xfb, 0x90, 0xf7,
- 0x1d, 0xa9, 0xe1, 0xe8, 0xc4, 0x20, 0x84, 0x11, 0x42, 0xcf, 0x86, 0x3e,
- 0x86, 0xe0, 0xa1, 0x1e, 0x64, 0x3c, 0xc2, 0x26, 0x5f, 0xa2, 0xfc, 0xed,
- 0x8b, 0x16, 0xfa, 0xc5, 0xd8, 0x75, 0x8a, 0x81, 0xe9, 0x8c, 0xaa, 0x38,
- 0x4a, 0xc1, 0x6d, 0x62, 0xfe, 0xf7, 0xda, 0x1e, 0xd9, 0x62, 0xe8, 0xe2,
- 0x58, 0xbe, 0x88, 0xa4, 0xeb, 0x17, 0xbe, 0xd0, 0xea, 0x6f, 0x7c, 0x35,
- 0x44, 0x8a, 0x1f, 0x36, 0xde, 0x71, 0xe2, 0xc5, 0xfc, 0x6e, 0x08, 0x85,
- 0xba, 0xc5, 0xf0, 0x9b, 0x50, 0x58, 0xbf, 0xfe, 0xd0, 0x0f, 0x31, 0xd9,
- 0xd7, 0x9e, 0x66, 0x25, 0x8b, 0xe1, 0x69, 0xb8, 0xb1, 0x43, 0x44, 0xd6,
- 0x11, 0xf1, 0x52, 0xfd, 0xbf, 0xe6, 0x3c, 0x6b, 0x17, 0xd9, 0xc7, 0xe8,
- 0xb1, 0x76, 0xcc, 0xb1, 0x79, 0x88, 0x1d, 0x51, 0x30, 0xc5, 0xe4, 0x5b,
- 0xc2, 0x4b, 0xc5, 0xb4, 0xac, 0x5d, 0x84, 0xb1, 0x4e, 0x6c, 0xfa, 0x0e,
- 0xdf, 0xf7, 0xda, 0x18, 0x36, 0x83, 0xac, 0x5f, 0xee, 0xbf, 0x6d, 0xe4,
- 0x86, 0xb1, 0x7d, 0x9b, 0x19, 0x05, 0x8b, 0x72, 0x4f, 0x6c, 0x8d, 0xae,
- 0xce, 0x2c, 0x5d, 0xa9, 0x58, 0xaf, 0x9a, 0xef, 0x0b, 0xdf, 0xf1, 0x49,
- 0xdc, 0xb0, 0xf2, 0xb1, 0x74, 0xee, 0xb1, 0x7f, 0xed, 0x69, 0xe2, 0xe6,
- 0x1a, 0xfa, 0x58, 0xbd, 0xf7, 0x82, 0xc5, 0xcf, 0x2b, 0x17, 0xfc, 0xfb,
- 0x67, 0xdf, 0x5f, 0x65, 0x8b, 0x9c, 0x78, 0x98, 0xe4, 0x44, 0x20, 0x36,
- 0xe0, 0xc7, 0x90, 0x43, 0x1d, 0x08, 0x2d, 0x46, 0xae, 0x3d, 0x47, 0xc6,
- 0xc5, 0xa8, 0x40, 0x7c, 0x88, 0x10, 0x93, 0x28, 0xdc, 0x2f, 0xe1, 0x8e,
- 0x62, 0xf6, 0x2c, 0x5f, 0xfc, 0x5e, 0xe7, 0xda, 0x1d, 0x73, 0xbf, 0x2c,
- 0x50, 0x58, 0xbc, 0xb7, 0x30, 0xb9, 0x81, 0x16, 0x4e, 0x4b, 0x3b, 0x98,
- 0x8b, 0xef, 0xf4, 0x7c, 0x5c, 0x9f, 0xb4, 0x7a, 0xc5, 0xfe, 0xcd, 0xd8,
- 0xf8, 0xe3, 0x58, 0xbf, 0xd9, 0xfe, 0xf7, 0x7c, 0xd2, 0xc5, 0xfd, 0x9a,
- 0x83, 0x96, 0x2c, 0x53, 0x9f, 0x08, 0x8d, 0x6e, 0x9e, 0xf6, 0x45, 0xaf,
- 0xa1, 0x29, 0x4c, 0x99, 0x29, 0x43, 0xc2, 0xfe, 0x33, 0xff, 0xed, 0xa3,
- 0xd6, 0x2f, 0xf8, 0xc9, 0x88, 0xc9, 0xd3, 0x44, 0xb1, 0x7e, 0xe6, 0x67,
- 0xb1, 0x62, 0xf8, 0xd8, 0x3f, 0x96, 0x2f, 0x49, 0x6c, 0xb1, 0x7c, 0xff,
- 0x73, 0xac, 0x53, 0x9b, 0xf8, 0x87, 0x6b, 0xb4, 0x55, 0xe8, 0x9f, 0xec,
- 0x77, 0xb9, 0xe7, 0x58, 0xba, 0x21, 0x2c, 0x5d, 0x3b, 0xc9, 0xb6, 0x21,
- 0xdb, 0x01, 0x62, 0xff, 0xa7, 0xdf, 0x60, 0x37, 0x7c, 0x58, 0xa1, 0x9f,
- 0xbf, 0x65, 0x64, 0x25, 0x7f, 0xb1, 0xce, 0x23, 0xbf, 0x16, 0x2f, 0xff,
- 0x70, 0x4d, 0xa1, 0x6d, 0x26, 0x98, 0x5e, 0x58, 0xbf, 0x85, 0x0d, 0xdb,
- 0x5b, 0x2c, 0x5c, 0xc1, 0xac, 0x54, 0x9e, 0x4b, 0x18, 0xd0, 0xd1, 0x6f,
- 0xd2, 0x12, 0xf7, 0xff, 0xf0, 0xcc, 0x6d, 0x1b, 0x8e, 0x52, 0x7c, 0xe3,
- 0x12, 0xc5, 0xd1, 0xa3, 0x2c, 0x5a, 0x76, 0x3f, 0x60, 0xd6, 0xaf, 0xff,
- 0x84, 0xc3, 0x79, 0x39, 0x66, 0xdb, 0x08, 0x96, 0x2b, 0x47, 0xf3, 0xe2,
- 0x9b, 0xff, 0xb3, 0x66, 0x8b, 0xaf, 0xe7, 0x9c, 0x65, 0x8b, 0xff, 0x84,
- 0xcf, 0x09, 0x2d, 0xf3, 0xbf, 0x2c, 0x5f, 0x10, 0x9b, 0x7e, 0xa8, 0x8d,
- 0xe2, 0x45, 0xc7, 0x75, 0x8b, 0xfb, 0xef, 0xb8, 0xb4, 0x05, 0x8b, 0xff,
- 0xc5, 0x9d, 0x27, 0x9f, 0xcc, 0x28, 0x71, 0x62, 0xc0, 0xea, 0x7f, 0x5c,
- 0x30, 0xbf, 0xbd, 0xf7, 0xea, 0x5d, 0xac, 0x5e, 0x09, 0x31, 0xeb, 0x15,
- 0xa3, 0xfd, 0x22, 0xa0, 0x86, 0x37, 0xd8, 0x39, 0x35, 0x62, 0xf6, 0x85,
- 0xba, 0xc5, 0xcd, 0xda, 0xc5, 0xdd, 0x25, 0x62, 0xe0, 0x91, 0x2c, 0x5c,
- 0x2d, 0x2c, 0x5f, 0x7b, 0x8d, 0xd1, 0x62, 0xc0, 0x58, 0xa8, 0x8f, 0x3c,
- 0x86, 0x3c, 0x4b, 0x7f, 0x67, 0xa5, 0xb4, 0x6a, 0xc5, 0xec, 0x7f, 0x2c,
- 0x5f, 0xf3, 0xeb, 0x3b, 0x8c, 0x0c, 0x30, 0xd6, 0x2b, 0xe7, 0xba, 0xc3,
- 0x94, 0x15, 0x55, 0xed, 0x31, 0x87, 0x0c, 0xc3, 0x08, 0xfb, 0x1f, 0x71,
- 0x88, 0xf1, 0x96, 0x6a, 0x22, 0xfe, 0x42, 0x2e, 0xff, 0xf4, 0xc3, 0xa9,
- 0x9e, 0x72, 0x14, 0x33, 0x8b, 0x17, 0xa0, 0xc3, 0x58, 0xa2, 0x3e, 0xa1,
- 0x26, 0xdf, 0xe0, 0x0a, 0x21, 0x78, 0x51, 0x2c, 0x5f, 0xff, 0x0b, 0x87,
- 0x9e, 0xf7, 0xfb, 0x9c, 0x9f, 0x65, 0x8b, 0xd3, 0x9b, 0xac, 0x57, 0xcf,
- 0xc0, 0x94, 0xef, 0xff, 0xfc, 0xd1, 0xe5, 0x8e, 0x45, 0x80, 0xcf, 0x49,
- 0xdf, 0xdf, 0x75, 0x8b, 0xdb, 0xf0, 0x35, 0x8b, 0xff, 0xff, 0xfe, 0xfb,
- 0x71, 0xc8, 0x1f, 0x7f, 0xb7, 0xbe, 0xfa, 0x81, 0x85, 0x3a, 0xd3, 0xf7,
- 0xc7, 0x58, 0xad, 0x99, 0x63, 0x43, 0x34, 0xc8, 0x74, 0x6f, 0x0d, 0xee,
- 0xcb, 0xde, 0x1d, 0x5a, 0x8c, 0x64, 0xf0, 0xaf, 0xfc, 0xb3, 0x20, 0x46,
- 0x0a, 0x44, 0x3c, 0x85, 0x40, 0x88, 0x7a, 0x35, 0x18, 0x41, 0x77, 0x04,
- 0xb1, 0x7f, 0xbd, 0xe7, 0xd6, 0x77, 0xe5, 0x8b, 0xf3, 0x9f, 0x77, 0x1a,
- 0xc5, 0x68, 0xf7, 0xbe, 0x6b, 0x7b, 0x4f, 0xe5, 0x8b, 0xc0, 0x63, 0xac,
- 0x5d, 0x80, 0x58, 0xa9, 0x36, 0x98, 0x3b, 0x79, 0xb0, 0xeb, 0x15, 0xb2,
- 0x64, 0x98, 0xed, 0xa2, 0x22, 0x51, 0x08, 0x3f, 0x7f, 0xf3, 0x19, 0xf9,
- 0x87, 0x35, 0xac, 0xed, 0x62, 0xc5, 0x04, 0x49, 0xfd, 0x32, 0xfa, 0x7e,
- 0x2d, 0x2c, 0x5f, 0xdc, 0x2c, 0x19, 0x32, 0xc5, 0x11, 0xe7, 0x86, 0x47,
- 0x7f, 0x3e, 0xa7, 0xbf, 0x4a, 0xc5, 0xdb, 0xba, 0xc5, 0xf8, 0xa7, 0x69,
- 0xed, 0x62, 0xf3, 0x47, 0x4a, 0xc5, 0xfc, 0xda, 0x38, 0xb4, 0x05, 0x8b,
- 0xb4, 0x05, 0x8a, 0x81, 0xe3, 0xb9, 0x7d, 0xf3, 0xec, 0x4c, 0xb1, 0x6e,
- 0x4a, 0x63, 0x1b, 0x97, 0x38, 0xc6, 0x8a, 0x59, 0x9b, 0xc4, 0x37, 0xf6,
- 0x84, 0xc6, 0x30, 0xd6, 0x2a, 0x55, 0x1e, 0x3b, 0xbb, 0x46, 0x74, 0x62,
- 0xe5, 0xf7, 0x0a, 0x76, 0x58, 0xbf, 0xed, 0x9b, 0xec, 0x32, 0x6d, 0xd6,
- 0x2b, 0x47, 0xba, 0x44, 0x77, 0xff, 0xc1, 0xe6, 0xfc, 0xcf, 0x45, 0x86,
- 0x96, 0x01, 0x62, 0xb0, 0xfd, 0x1c, 0x86, 0xff, 0x88, 0xdf, 0xb3, 0xf9,
- 0x8e, 0xb1, 0x78, 0xef, 0xa5, 0x8b, 0xfe, 0xc0, 0xf3, 0x5b, 0xb3, 0x6e,
- 0xa8, 0xc3, 0x8b, 0xff, 0x42, 0x41, 0xc9, 0xfb, 0xf7, 0x05, 0x8b, 0xe7,
- 0xd6, 0x76, 0xb1, 0x58, 0x7c, 0x71, 0xc8, 0x17, 0xff, 0x0b, 0x83, 0xfb,
- 0x1f, 0xb8, 0x39, 0x2c, 0x5f, 0xbd, 0xf6, 0x20, 0x2c, 0x57, 0x54, 0xd6,
- 0xb6, 0x1d, 0x36, 0x15, 0x7f, 0x24, 0x64, 0x6b, 0x9c, 0xeb, 0x17, 0xfd,
- 0xec, 0x89, 0xa4, 0xa6, 0x25, 0x8a, 0x88, 0xf4, 0x18, 0x5e, 0xff, 0x61,
- 0x99, 0x10, 0x73, 0xda, 0xc5, 0xfb, 0x22, 0x29, 0x3a, 0xc5, 0xbe, 0xe7,
- 0xbf, 0xe3, 0x7b, 0x3e, 0x2a, 0xde, 0xd4, 0x72, 0x7f, 0x85, 0x1f, 0x21,
- 0x03, 0x76, 0xfb, 0xaa, 0x30, 0x42, 0xa0, 0xad, 0xe3, 0x79, 0x5f, 0xc0,
- 0x53, 0xbf, 0x8a, 0x7d, 0xc7, 0xe8, 0xb1, 0x7f, 0x70, 0x65, 0x9f, 0x0a,
- 0xac, 0x5c, 0x60, 0x45, 0x8a, 0x0a, 0x1e, 0x69, 0xcc, 0xae, 0xc2, 0x58,
- 0xbb, 0xfc, 0x58, 0xa5, 0x8b, 0xff, 0xa4, 0xb7, 0xcf, 0x7d, 0xf4, 0x0d,
- 0xd6, 0x2b, 0x0f, 0xa8, 0x86, 0x3c, 0x19, 0x7c, 0xfc, 0xfb, 0xac, 0x5e,
- 0xce, 0xfc, 0xb1, 0x43, 0x3c, 0x03, 0x91, 0x5f, 0xce, 0x59, 0xef, 0xba,
- 0xc5, 0xa7, 0x0f, 0x3b, 0x84, 0x54, 0x34, 0xd8, 0x72, 0x10, 0x02, 0x85,
- 0xdd, 0xf9, 0xa1, 0xf7, 0x02, 0xc5, 0xf0, 0xa1, 0x91, 0xcb, 0x17, 0xfb,
- 0x4d, 0xcd, 0x6b, 0x03, 0x58, 0xa1, 0xa2, 0x0c, 0x8a, 0x3a, 0x13, 0x5f,
- 0xfe, 0xfb, 0xc5, 0xf7, 0xef, 0xc5, 0x9d, 0x19, 0x62, 0xf0, 0xda, 0x25,
- 0x8b, 0xfe, 0x7e, 0x9f, 0xcd, 0x69, 0xfa, 0x2c, 0x5d, 0xc8, 0x2c, 0x54,
- 0x9f, 0x9f, 0xc7, 0xbc, 0x7b, 0x77, 0xb8, 0xb1, 0x74, 0x81, 0x62, 0xff,
- 0xb9, 0x26, 0xf0, 0x43, 0xfb, 0xac, 0x54, 0x47, 0xa5, 0xe1, 0x7a, 0xc4,
- 0x46, 0x93, 0x55, 0xff, 0xd9, 0xde, 0x7b, 0x0a, 0x1f, 0x68, 0x2c, 0x56,
- 0x1f, 0x29, 0x10, 0xdf, 0xc7, 0xe7, 0x18, 0xb6, 0x58, 0xb1, 0xd6, 0x2f,
- 0xc4, 0x59, 0xdc, 0x16, 0x28, 0xe6, 0xe8, 0xc1, 0x2a, 0x94, 0x45, 0xb3,
- 0x4d, 0xfe, 0xf6, 0x39, 0x7b, 0x98, 0xb1, 0x7e, 0x7f, 0xb3, 0xec, 0xb1,
- 0x74, 0xc7, 0xac, 0x5c, 0x0e, 0x40, 0xf0, 0x9c, 0xa2, 0xfb, 0x98, 0x5e,
- 0x58, 0xbc, 0x12, 0x74, 0xb1, 0x4e, 0x7d, 0xcc, 0x5a, 0x22, 0x2b, 0x85,
- 0xc5, 0x8b, 0x9b, 0xcb, 0x17, 0xf8, 0x18, 0x3c, 0xf4, 0x8d, 0x62, 0xa2,
- 0x3e, 0x2f, 0x8c, 0x30, 0xbd, 0xef, 0x34, 0x7a, 0xc5, 0xf8, 0xce, 0x9d,
- 0x27, 0x8b, 0x17, 0xf7, 0xde, 0x30, 0x0c, 0xeb, 0x15, 0xc3, 0xde, 0xf1,
- 0x75, 0xfe, 0x37, 0xf3, 0x01, 0x36, 0x96, 0x2c, 0x4b, 0x14, 0xe7, 0x8c,
- 0x23, 0x5a, 0x96, 0x42, 0x26, 0xcf, 0x83, 0x8e, 0x1f, 0x21, 0x7b, 0xb9,
- 0x8c, 0x50, 0xc0, 0x3c, 0x64, 0x1f, 0x85, 0x5b, 0x10, 0x94, 0x38, 0xb9,
- 0x08, 0xff, 0x17, 0x89, 0xfa, 0x39, 0xa2, 0xfb, 0x06, 0x39, 0x58, 0xbb,
- 0x23, 0xd6, 0x2b, 0x0d, 0xe4, 0x44, 0x57, 0xe3, 0x40, 0xf1, 0x71, 0x62,
- 0xfb, 0xee, 0xd0, 0x58, 0xbc, 0x36, 0x82, 0xc5, 0x49, 0xbf, 0xc2, 0x2b,
- 0xfd, 0xf6, 0x8b, 0xae, 0xf2, 0x35, 0x8b, 0x0a, 0x51, 0x82, 0x06, 0xae,
- 0x0f, 0xdf, 0xdf, 0x98, 0x7c, 0x43, 0x58, 0xbc, 0x03, 0x3b, 0x58, 0xbb,
- 0x3a, 0x2c, 0x5e, 0xf1, 0x41, 0x62, 0xc7, 0xc3, 0xd6, 0xf1, 0x07, 0x41,
- 0x9b, 0xff, 0xdd, 0x49, 0xbd, 0x3a, 0x14, 0x35, 0x30, 0x58, 0xbf, 0x4f,
- 0xbf, 0x31, 0x2c, 0x5d, 0xee, 0x2c, 0x5f, 0x98, 0xd0, 0xe7, 0x4b, 0x15,
- 0x04, 0xdc, 0xb7, 0x84, 0x2b, 0x9b, 0x7d, 0x31, 0x8a, 0x48, 0x62, 0xff,
- 0x39, 0x7a, 0x19, 0xac, 0x58, 0xbf, 0xf9, 0xf7, 0x2c, 0x3c, 0xc4, 0x39,
- 0xd9, 0x62, 0xff, 0xe8, 0x16, 0x1d, 0x8b, 0x3e, 0xc7, 0x58, 0xbf, 0xd9,
- 0xe9, 0xe8, 0xe4, 0x05, 0x8b, 0xff, 0xe0, 0x1d, 0xa1, 0x0c, 0x01, 0x9e,
- 0xdb, 0x82, 0x58, 0xad, 0xd1, 0x11, 0xa3, 0x4b, 0xff, 0x19, 0xdf, 0x59,
- 0xeb, 0x11, 0x49, 0xd6, 0x2f, 0xf6, 0xa5, 0xc6, 0x4d, 0x05, 0x8b, 0xff,
- 0x69, 0xcb, 0x72, 0xcd, 0xb0, 0x35, 0x8b, 0xfe, 0xce, 0x93, 0x9d, 0xf7,
- 0xe0, 0xb5, 0x58, 0xbf, 0x4f, 0xb9, 0x85, 0xd5, 0x16, 0xda, 0x32, 0xfa,
- 0x05, 0x0d, 0x34, 0x91, 0x43, 0xf2, 0xfd, 0xbf, 0xfb, 0x68, 0xf5, 0x8b,
- 0xfd, 0xc9, 0x81, 0xa6, 0xe4, 0x7a, 0xc5, 0xff, 0x86, 0x42, 0xf7, 0x24,
- 0xa7, 0x8b, 0x15, 0x27, 0xee, 0xe7, 0x36, 0x0b, 0xac, 0x54, 0x15, 0xd9,
- 0xee, 0x65, 0xda, 0x33, 0xc3, 0x28, 0xa3, 0x6d, 0x11, 0x4f, 0x48, 0x52,
- 0x86, 0x41, 0x7f, 0x8b, 0x01, 0xc6, 0x20, 0x2c, 0x5f, 0xa1, 0xf9, 0xd6,
- 0xcb, 0x14, 0xe7, 0xb8, 0xc6, 0x57, 0xbe, 0xe6, 0xac, 0x5e, 0x6d, 0x41,
- 0x62, 0xfa, 0x41, 0xf6, 0x58, 0xae, 0x1b, 0xff, 0x0e, 0xdf, 0xa2, 0xc2,
- 0xc1, 0xac, 0x5f, 0xfd, 0xe1, 0x94, 0xc3, 0xf9, 0x85, 0xba, 0xc5, 0xff,
- 0xfc, 0x76, 0x28, 0x77, 0xe7, 0x0f, 0x7f, 0xb9, 0xe7, 0x75, 0x8a, 0x94,
- 0x51, 0x89, 0x12, 0xff, 0xfd, 0xa0, 0x00, 0x5c, 0xd3, 0x71, 0xfc, 0x4d,
- 0x05, 0x8b, 0xff, 0xcf, 0x3e, 0x2c, 0xf7, 0xf1, 0xe1, 0xd1, 0x62, 0xff,
- 0xbb, 0xe0, 0x18, 0x87, 0x10, 0x96, 0x2e, 0x20, 0xd6, 0x2f, 0xfe, 0xcd,
- 0x8c, 0x80, 0xf3, 0xcf, 0xf1, 0x2c, 0x5f, 0xb5, 0x9d, 0x30, 0x7a, 0x3d,
- 0xf2, 0x18, 0xa7, 0x46, 0xd3, 0x42, 0x6e, 0xff, 0xfc, 0x22, 0x86, 0x17,
- 0x9e, 0x3b, 0x3c, 0x4d, 0x05, 0x8b, 0xfd, 0x20, 0x9f, 0xe7, 0x70, 0x58,
- 0xa7, 0x44, 0x51, 0x2b, 0x5f, 0xff, 0x7d, 0x8f, 0x11, 0x49, 0xfb, 0x87,
- 0xf3, 0x65, 0x8a, 0xc5, 0x53, 0xdf, 0x56, 0x04, 0x64, 0x9e, 0x85, 0x80,
- 0x88, 0x6f, 0xa2, 0x68, 0x99, 0x62, 0xf6, 0xd8, 0x1a, 0xc5, 0xa0, 0xb1,
- 0x6f, 0x75, 0x36, 0x22, 0x1f, 0xb4, 0x16, 0x29, 0x8d, 0xd8, 0x8a, 0x6e,
- 0x9e, 0x2c, 0x57, 0x54, 0x63, 0x94, 0x24, 0x3c, 0x41, 0x7f, 0xdf, 0x62,
- 0xc8, 0xa1, 0x3d, 0xac, 0x5f, 0xfd, 0xf7, 0xd6, 0x70, 0xb3, 0xa7, 0xdd,
- 0x62, 0xfc, 0x59, 0xc1, 0x75, 0xc3, 0xff, 0x88, 0xea, 0xff, 0x48, 0x07,
- 0xf9, 0x2d, 0xd6, 0x2f, 0xda, 0xdd, 0x9b, 0x75, 0x44, 0x0c, 0x5f, 0xcd,
- 0xb0, 0x18, 0x86, 0x8a, 0xc1, 0xe5, 0xec, 0xe0, 0x86, 0x8a, 0x7c, 0x34,
- 0x8e, 0x37, 0xbd, 0xf6, 0x87, 0x54, 0xca, 0x8a, 0x1c, 0xf7, 0xfd, 0xf7,
- 0xc2, 0xcd, 0xc7, 0x8b, 0x14, 0x35, 0xf9, 0x8d, 0xc8, 0x1d, 0x76, 0x22,
- 0x1d, 0x43, 0x2c, 0xf2, 0xb0, 0x0a, 0x31, 0xdf, 0x47, 0xbf, 0xd0, 0xee,
- 0xff, 0x00, 0x84, 0xdd, 0xc6, 0xc1, 0x55, 0x8b, 0xde, 0x14, 0xac, 0x5f,
- 0xfe, 0xfb, 0xfb, 0x30, 0xfc, 0x9c, 0x1b, 0xac, 0x5d, 0xce, 0x2c, 0x5f,
- 0x0f, 0xec, 0x75, 0x8b, 0xfe, 0xcd, 0x8c, 0x83, 0xcf, 0x7e, 0x58, 0xb0,
- 0x37, 0x45, 0xfe, 0x92, 0x18, 0x60, 0x88, 0xef, 0xf0, 0x3c, 0xfb, 0x1e,
- 0x77, 0x58, 0xa9, 0x4e, 0x4b, 0xb3, 0xe6, 0x86, 0xe1, 0x21, 0x5f, 0x87,
- 0x1a, 0x30, 0xe3, 0x45, 0x8b, 0xfb, 0x7e, 0xff, 0xdb, 0x47, 0xac, 0x5f,
- 0xef, 0xce, 0xb3, 0x08, 0xd5, 0x8b, 0xda, 0x32, 0x25, 0x8b, 0x64, 0x0f,
- 0x4d, 0xcc, 0xef, 0xcd, 0xaf, 0x66, 0xeb, 0x17, 0xc3, 0x79, 0xd9, 0x62,
- 0xd3, 0xa3, 0xcc, 0x11, 0x4d, 0xfe, 0xcc, 0xec, 0x0c, 0x5e, 0x58, 0xbf,
- 0x4e, 0x0d, 0xc9, 0x62, 0xf1, 0x67, 0x16, 0x2e, 0x71, 0xf5, 0x3f, 0x51,
- 0x19, 0xf4, 0x26, 0xb4, 0x20, 0x8d, 0xae, 0x42, 0x72, 0xa5, 0x50, 0x17,
- 0x70, 0x88, 0x68, 0xd3, 0x2a, 0x59, 0xab, 0x39, 0x48, 0x7a, 0x79, 0x45,
- 0xac, 0x82, 0x29, 0x46, 0xb7, 0x3c, 0x16, 0x2f, 0x69, 0xfc, 0xb1, 0x7e,
- 0xf0, 0xf3, 0x0d, 0x58, 0xa1, 0x9e, 0x37, 0x63, 0xb7, 0xf7, 0xdf, 0xdc,
- 0xcf, 0x2c, 0x5f, 0xc5, 0xa9, 0xdf, 0x34, 0xb1, 0x7d, 0x91, 0x39, 0xd6,
- 0x28, 0x68, 0xff, 0xc5, 0xdd, 0xc8, 0xd8, 0xb8, 0xc2, 0xeb, 0xff, 0xed,
- 0x4f, 0x70, 0x3b, 0xe7, 0x7f, 0xcd, 0x6c, 0xb1, 0x69, 0x58, 0xbe, 0x92,
- 0x70, 0x2c, 0x5b, 0x3e, 0x6c, 0xbc, 0x23, 0x7f, 0xb4, 0x4c, 0x19, 0x9d,
- 0x86, 0xb1, 0x70, 0x3a, 0x2c, 0x5f, 0xbd, 0xf1, 0x6c, 0x25, 0x8a, 0x19,
- 0xfe, 0xfc, 0xe0, 0x43, 0x57, 0xfd, 0xf7, 0xf9, 0x4e, 0x6b, 0x16, 0x2f,
- 0xf4, 0x0b, 0x3a, 0x39, 0x0d, 0x62, 0xe7, 0x06, 0xe7, 0xd6, 0xc6, 0xf7,
- 0xe2, 0x6f, 0x37, 0x6b, 0x17, 0xbc, 0xdd, 0x16, 0x2f, 0xf0, 0xfb, 0x86,
- 0x61, 0x6c, 0xb1, 0x61, 0xac, 0x5f, 0xfa, 0x13, 0x1f, 0x9a, 0xf7, 0x26,
- 0x0b, 0x17, 0xfd, 0xd8, 0xe7, 0x8e, 0x3f, 0xca, 0xc5, 0xfd, 0xdf, 0xa2,
- 0xfc, 0x92, 0xc5, 0xfe, 0x7f, 0x71, 0xbb, 0x00, 0x6b, 0x17, 0x6b, 0x65,
- 0x46, 0x0a, 0x57, 0xcf, 0x71, 0x8d, 0xaf, 0xfc, 0xda, 0xc2, 0x07, 0x3d,
- 0xce, 0xd6, 0x2f, 0xff, 0xb0, 0xd3, 0xce, 0x17, 0xb9, 0xc1, 0x68, 0x0b,
- 0x17, 0xff, 0xff, 0xf6, 0x7b, 0xec, 0x46, 0xf5, 0xe6, 0x99, 0xbd, 0xd3,
- 0x07, 0xd7, 0x0e, 0xc5, 0xdc, 0x17, 0x10, 0x59, 0x7f, 0xe6, 0x63, 0x77,
- 0x61, 0xf5, 0x34, 0x35, 0xc4, 0x16, 0x5f, 0xfd, 0xf7, 0xfb, 0xc9, 0x7b,
- 0xa9, 0xa1, 0xae, 0x20, 0xb2, 0xff, 0x4b, 0x97, 0xba, 0x9a, 0x1a, 0xe2,
- 0x0b, 0x2f, 0xe3, 0xe0, 0xfa, 0x9a, 0x1a, 0xe2, 0x0b, 0x2f, 0xff, 0xf9,
- 0x88, 0x9c, 0xfd, 0x79, 0xbf, 0xdf, 0x4e, 0x6e, 0xd8, 0x1a, 0xe2, 0x0b,
- 0x2e, 0xef, 0xa8, 0xd3, 0xa3, 0xdd, 0x4b, 0x4a, 0xac, 0x88, 0x48, 0x15,
- 0x2a, 0xca, 0x71, 0x03, 0xea, 0x25, 0x28, 0xfe, 0xff, 0x3c, 0x9b, 0xcf,
- 0x73, 0xb5, 0x8b, 0xfc, 0xcd, 0xb6, 0x42, 0x4d, 0x58, 0xbf, 0xe9, 0x2d,
- 0xe7, 0xdc, 0xfb, 0xac, 0x5f, 0x37, 0xa7, 0xac, 0x47, 0xda, 0x73, 0x4b,
- 0xff, 0xc7, 0xc1, 0xf5, 0x30, 0xa7, 0xf2, 0x5b, 0xac, 0x5f, 0x36, 0x80,
- 0xcb, 0x17, 0xff, 0x7d, 0xfe, 0xf2, 0x5e, 0xea, 0x68, 0x6b, 0x88, 0x2c,
- 0xbf, 0xe8, 0xb9, 0xbb, 0xed, 0xd4, 0xd0, 0xd7, 0x10, 0x59, 0x7e, 0xf7,
- 0x24, 0xfd, 0x77, 0x45, 0x21, 0x8a, 0xb7, 0xff, 0xba, 0xef, 0xf7, 0xde,
- 0x7d, 0xce, 0xa6, 0x86, 0xb8, 0x82, 0xcb, 0xff, 0xff, 0x88, 0x9c, 0xfd,
- 0x45, 0x9d, 0x79, 0xbf, 0xdf, 0x4e, 0x6e, 0xd8, 0x1a, 0xe2, 0x0b, 0x2b,
- 0x13, 0x2b, 0xed, 0x11, 0x98, 0x6f, 0xf3, 0xe9, 0xcd, 0xdb, 0x03, 0x5c,
- 0x41, 0x65, 0xff, 0xb6, 0x38, 0x9c, 0xec, 0x5d, 0xc1, 0x71, 0x05, 0x95,
- 0xf4, 0x48, 0x89, 0x0e, 0xff, 0xf9, 0x9b, 0xb8, 0x73, 0xee, 0x31, 0xce,
- 0xa5, 0x22, 0xff, 0xf3, 0x81, 0x88, 0x7d, 0x7b, 0xf0, 0xa5, 0x96, 0x2f,
- 0xfd, 0x90, 0x80, 0xb9, 0xa2, 0xda, 0x39, 0x71, 0x05, 0x95, 0xba, 0x62,
- 0x1a, 0x23, 0xfa, 0x87, 0x13, 0x2f, 0xfd, 0xbb, 0xeb, 0xcc, 0x0e, 0x75,
- 0x0d, 0x71, 0x05, 0x97, 0xf7, 0xdf, 0xff, 0x70, 0x2a, 0x00, 0xb2, 0xfd,
- 0x80, 0xea, 0x68, 0x6b, 0x88, 0x2c, 0xbb, 0x3d, 0xb9, 0xfa, 0xfc, 0xee,
- 0xbb, 0x47, 0xa7, 0x21, 0x8d, 0x7f, 0x1f, 0x07, 0xd4, 0xd0, 0xd7, 0x10,
- 0x59, 0x7f, 0xed, 0xfe, 0xfa, 0x73, 0x76, 0xc0, 0xd7, 0x10, 0x59, 0x76,
- 0x75, 0x64, 0x48, 0x71, 0x02, 0xff, 0x09, 0xce, 0xc5, 0xdc, 0x17, 0x10,
- 0x59, 0x7f, 0xec, 0x7e, 0x98, 0x58, 0x36, 0x82, 0xe2, 0x0b, 0x0e, 0x78,
- 0x34, 0x35, 0xfe, 0x8d, 0x21, 0x9e, 0x14, 0x6c, 0x76, 0x04, 0xd2, 0x8f,
- 0xc7, 0x91, 0xe8, 0xfa, 0x33, 0x31, 0x42, 0xe4, 0x37, 0x0b, 0x81, 0x2a,
- 0x88, 0x2c, 0x8c, 0x45, 0x4d, 0xcd, 0xba, 0xc5, 0x0d, 0x99, 0xe5, 0x87,
- 0x5b, 0xc2, 0x30, 0x14, 0xbd, 0xbf, 0x1c, 0xd6, 0x33, 0x75, 0xf7, 0x35,
- 0x88, 0x4b, 0x94, 0xd3, 0x4b, 0xa0, 0x11, 0x62, 0xf4, 0xc0, 0x22, 0xc5,
- 0x49, 0xb9, 0x21, 0xaa, 0xd9, 0xb0, 0xfa, 0x82, 0x50, 0xe1, 0x0b, 0xdc,
- 0x28, 0xf5, 0x09, 0xaf, 0x96, 0xb1, 0x40, 0x29, 0xbe, 0xc5, 0x08, 0x4b,
- 0xe3, 0x0b, 0x3a, 0x2c, 0x5f, 0xd2, 0x7d, 0xdf, 0xf8, 0xb1, 0x7f, 0xe8,
- 0x16, 0x7b, 0xef, 0x9d, 0xf9, 0x62, 0xfe, 0x28, 0x73, 0xdf, 0x95, 0x8b,
- 0xff, 0xff, 0x67, 0xbe, 0xd0, 0x1e, 0x69, 0xf3, 0xa1, 0x9a, 0xfb, 0xf7,
- 0xe5, 0x8b, 0x9c, 0xd5, 0x8b, 0xee, 0x85, 0x9c, 0x58, 0xbf, 0xbb, 0xe3,
- 0x7a, 0x78, 0xb1, 0x7d, 0x9b, 0x9d, 0xd6, 0x2e, 0x28, 0x61, 0xfb, 0x39,
- 0x27, 0xcb, 0xea, 0x53, 0xf6, 0x81, 0x2e, 0x17, 0x39, 0xf9, 0xcb, 0xbe,
- 0xe0, 0x64, 0x23, 0xaf, 0x00, 0xe0, 0x58, 0xbf, 0xd3, 0xf7, 0x0f, 0xb8,
- 0x71, 0x62, 0xfd, 0x3e, 0xe7, 0xdd, 0x62, 0xff, 0xda, 0xc3, 0x7f, 0x87,
- 0x16, 0xb6, 0x58, 0xbf, 0xee, 0xcb, 0x1c, 0xf8, 0x40, 0x58, 0xbf, 0xff,
- 0xff, 0x34, 0x44, 0xc1, 0xe7, 0x47, 0xe7, 0xf0, 0x11, 0xd9, 0xee, 0x31,
- 0xf3, 0xbf, 0x2c, 0x5f, 0xf9, 0x9b, 0x6c, 0x3b, 0x17, 0x70, 0x58, 0xbd,
- 0xcc, 0x25, 0x8b, 0x42, 0x23, 0xdb, 0xf1, 0xfd, 0xff, 0xe6, 0xde, 0x48,
- 0x65, 0x9d, 0x34, 0xfc, 0x58, 0xbf, 0xf7, 0x22, 0x80, 0x87, 0x14, 0x04,
- 0x35, 0x8a, 0xea, 0xaa, 0x4b, 0x61, 0xe8, 0x1b, 0x0c, 0xa3, 0x10, 0x8d,
- 0x38, 0xee, 0x1c, 0x9f, 0x29, 0xf2, 0x5d, 0xff, 0x67, 0x83, 0xc2, 0x1f,
- 0xe5, 0x62, 0xf7, 0x1c, 0x35, 0x8b, 0xff, 0xa7, 0xb8, 0x18, 0x7e, 0x7a,
- 0x7b, 0x0d, 0x62, 0xfd, 0x00, 0x81, 0x05, 0xb2, 0xc5, 0x39, 0xfc, 0xb2,
- 0x55, 0x76, 0x8b, 0x7f, 0xc2, 0x5e, 0xff, 0xd8, 0xfc, 0xd6, 0x40, 0xa4,
- 0xeb, 0x17, 0xde, 0x29, 0x3a, 0xc5, 0xfb, 0x53, 0xdc, 0x38, 0xb1, 0x7e,
- 0x8e, 0xc0, 0x98, 0x4b, 0x15, 0xb2, 0x79, 0xd0, 0x87, 0x86, 0xe5, 0x2e,
- 0x7b, 0xa2, 0x20, 0x15, 0x5f, 0xf4, 0x9b, 0xfc, 0x22, 0xce, 0xd6, 0x2f,
- 0xff, 0xee, 0xf9, 0xee, 0xbe, 0xfb, 0xb0, 0x22, 0x86, 0x77, 0x05, 0x8b,
- 0xc7, 0x6f, 0x2c, 0x5f, 0xf3, 0x43, 0x34, 0x31, 0x8a, 0x0b, 0x16, 0xe2,
- 0xc5, 0x1c, 0xf3, 0x18, 0xea, 0xee, 0x6e, 0xb1, 0x7a, 0x0f, 0xe5, 0x8b,
- 0xff, 0xde, 0x72, 0x14, 0x33, 0x80, 0xf7, 0xbb, 0x58, 0xb1, 0x44, 0x7d,
- 0x26, 0x0e, 0xdf, 0x64, 0x4d, 0x12, 0xc5, 0xff, 0x71, 0xbb, 0x8e, 0x17,
- 0xdf, 0x4b, 0x17, 0xf6, 0x68, 0x07, 0x7e, 0x2c, 0x5c, 0x2e, 0x7d, 0x12,
- 0x1e, 0x24, 0x8e, 0x3e, 0xbd, 0x2e, 0x75, 0x8b, 0x1a, 0xb1, 0x6c, 0xdc,
- 0xd7, 0xe8, 0x72, 0xff, 0xee, 0x9d, 0x27, 0x8d, 0xfe, 0xe1, 0x9e, 0x58,
- 0xac, 0x4e, 0x60, 0x10, 0xb9, 0x8e, 0x6e, 0x30, 0x9e, 0xfe, 0x14, 0x52,
- 0x5c, 0x75, 0x8b, 0xfc, 0x46, 0x66, 0x8a, 0x4e, 0xb1, 0x7f, 0x0b, 0xc5,
- 0x3e, 0xe2, 0xc5, 0x61, 0xf0, 0x80, 0xce, 0xd2, 0xb1, 0x50, 0x57, 0x56,
- 0x6b, 0x4f, 0xc8, 0x41, 0x28, 0x68, 0x91, 0xb9, 0x08, 0xf0, 0x84, 0x35,
- 0x2b, 0xed, 0xf9, 0x29, 0x5f, 0xb5, 0xe7, 0x39, 0x69, 0xc0, 0xdb, 0xc7,
- 0x7e, 0x2c, 0x5f, 0xe1, 0xb0, 0x30, 0x6f, 0xc5, 0x8b, 0xf1, 0xa3, 0x96,
- 0x25, 0x8b, 0xff, 0x73, 0x3e, 0xf0, 0x71, 0xe1, 0xd6, 0x2f, 0xd0, 0x9e,
- 0x8d, 0xf5, 0x8a, 0xd9, 0x1c, 0x10, 0x1d, 0xc3, 0x33, 0x4a, 0x18, 0xfa,
- 0xff, 0xec, 0xef, 0xdc, 0x72, 0x90, 0x31, 0xd6, 0x2f, 0xff, 0xe3, 0x7a,
- 0xff, 0x35, 0xac, 0x09, 0x9b, 0xc7, 0xb9, 0x74, 0x58, 0xbf, 0xe0, 0xcc,
- 0x26, 0xdf, 0x0b, 0x75, 0x8b, 0xe0, 0x99, 0x9b, 0x2c, 0x5f, 0xff, 0x7b,
- 0xef, 0xd4, 0xd6, 0xea, 0x58, 0x1b, 0x01, 0x62, 0xfe, 0x37, 0x53, 0x06,
- 0x35, 0x62, 0xb1, 0x10, 0xac, 0xab, 0x7c, 0x71, 0xe1, 0xd6, 0x2e, 0x0a,
- 0x85, 0x16, 0x29, 0x62, 0xff, 0x3f, 0xcb, 0x3d, 0x20, 0x58, 0xbd, 0xf1,
- 0x98, 0x73, 0x7d, 0xe0, 0xcb, 0xfe, 0xe8, 0xe4, 0x31, 0x7f, 0x0e, 0xb1,
- 0x7f, 0x37, 0xdf, 0x93, 0x05, 0x8a, 0xea, 0x98, 0xec, 0x68, 0x47, 0x2b,
- 0xd8, 0x69, 0xc3, 0xbb, 0xff, 0x05, 0xf0, 0x8b, 0x0c, 0x92, 0x02, 0xc5,
- 0xf8, 0xe7, 0x76, 0x82, 0xc5, 0xfe, 0xcf, 0xbf, 0x1c, 0x50, 0x58, 0xad,
- 0x95, 0xdd, 0x62, 0x23, 0xb3, 0x7c, 0xf0, 0xa1, 0x55, 0xe8, 0xcf, 0x84,
- 0xa1, 0xd1, 0x04, 0x21, 0x45, 0xf7, 0x7c, 0x9e, 0xd6, 0x2f, 0xff, 0xfd,
- 0xf7, 0xd3, 0xc9, 0xf0, 0x9e, 0x7e, 0xcf, 0xad, 0x3e, 0xcb, 0x17, 0xfe,
- 0x86, 0x77, 0x0d, 0x4f, 0x9b, 0xcb, 0x17, 0x8f, 0x30, 0x58, 0xbf, 0x60,
- 0xfe, 0x20, 0xd6, 0x2f, 0xff, 0xc4, 0x28, 0xff, 0xbe, 0xa7, 0xed, 0xc2,
- 0xc0, 0x2c, 0x57, 0x54, 0xdb, 0x37, 0x25, 0x89, 0xa5, 0x90, 0x08, 0x74,
- 0xc2, 0xab, 0xfe, 0xdf, 0xee, 0x3f, 0xcf, 0xb8, 0xb1, 0x7f, 0x34, 0x35,
- 0x3d, 0x81, 0x62, 0xf0, 0xdb, 0xcb, 0x17, 0xff, 0xc5, 0x9d, 0xfb, 0x53,
- 0x07, 0xe1, 0x9d, 0x81, 0x62, 0xe9, 0xed, 0x62, 0xff, 0xfd, 0xef, 0x64,
- 0x50, 0xcd, 0xba, 0xf7, 0x25, 0x3c, 0x58, 0xbf, 0xc4, 0xdd, 0xf8, 0x39,
- 0xed, 0x62, 0xff, 0xf7, 0xb2, 0x28, 0x66, 0xdd, 0xc9, 0x4f, 0x16, 0x2e,
- 0x9e, 0xfa, 0xa3, 0x73, 0xeb, 0x5e, 0x36, 0xa9, 0x4e, 0x14, 0x0a, 0x65,
- 0x0f, 0x4b, 0xf4, 0xb0, 0xf4, 0xcb, 0x17, 0xf6, 0x0f, 0xf3, 0xa6, 0x58,
- 0xbf, 0xf4, 0x87, 0xfd, 0x34, 0x3e, 0xfa, 0x58, 0xbc, 0xda, 0x36, 0x24,
- 0x4a, 0x11, 0x39, 0x85, 0xb7, 0xfe, 0xe4, 0x94, 0xc3, 0xdf, 0xc2, 0x58,
- 0xad, 0x2b, 0xaf, 0x3a, 0xdf, 0xce, 0xd8, 0xbc, 0x11, 0xd1, 0x14, 0x32,
- 0x38, 0x87, 0x79, 0xe3, 0xb1, 0x62, 0xf3, 0xf7, 0xe5, 0x8b, 0xdf, 0xd9,
- 0xd6, 0x2e, 0xc0, 0xf8, 0x6f, 0x04, 0x3d, 0x7f, 0xed, 0x13, 0x06, 0xda,
- 0xd6, 0x76, 0xb1, 0x7f, 0x9f, 0x47, 0x9c, 0x21, 0xac, 0x5c, 0xe6, 0xac,
- 0x57, 0xcf, 0x28, 0x8c, 0xaf, 0xee, 0x38, 0xf0, 0x3e, 0x2c, 0x5f, 0xcd,
- 0xa6, 0x1b, 0xe2, 0xc5, 0xa2, 0x58, 0xbb, 0x40, 0x58, 0xbb, 0x03, 0x58,
- 0xaf, 0x9e, 0x1b, 0x09, 0xf8, 0x62, 0xa5, 0x3f, 0xfd, 0x96, 0xc6, 0x5b,
- 0x90, 0x8a, 0xec, 0x87, 0xe5, 0xfe, 0x6f, 0xbf, 0xec, 0xe3, 0x8e, 0x4a,
- 0x40, 0xb1, 0x73, 0xe9, 0x62, 0xfc, 0xc5, 0xee, 0x4a, 0xc5, 0xcc, 0xeb,
- 0x17, 0xd8, 0x6c, 0xf1, 0x62, 0xb4, 0x7c, 0x07, 0x27, 0x21, 0x6a, 0xed,
- 0x34, 0x6d, 0x35, 0x7c, 0xdc, 0x0e, 0xf7, 0xc1, 0xe7, 0xd9, 0x62, 0xf8,
- 0xdd, 0x38, 0x6b, 0x17, 0xed, 0x9b, 0xf3, 0x1e, 0xb1, 0x7f, 0xc6, 0xe1,
- 0x4c, 0x3d, 0x9b, 0xac, 0x5e, 0xe4, 0x8d, 0x62, 0xf4, 0x76, 0x79, 0x62,
- 0xdb, 0x76, 0x6f, 0x7c, 0x3b, 0x41, 0x44, 0x78, 0xe1, 0x2b, 0x96, 0x09,
- 0xde, 0xfe, 0x37, 0xf3, 0xdf, 0xb1, 0x62, 0xff, 0x16, 0x0f, 0xf2, 0x19,
- 0x2c, 0x5e, 0xcd, 0x4a, 0xc5, 0xfc, 0x3f, 0xb1, 0x99, 0xb2, 0xc5, 0x40,
- 0xf3, 0x3c, 0x39, 0x52, 0x8d, 0x1d, 0x18, 0x13, 0xfd, 0xff, 0xfe, 0xd4,
- 0xfe, 0x75, 0xa9, 0xdb, 0xcc, 0xc6, 0xe7, 0x7e, 0x58, 0xa9, 0x6c, 0x15,
- 0x32, 0x70, 0x11, 0xe7, 0x6a, 0x1a, 0x5d, 0xa0, 0x0f, 0xca, 0x31, 0x41,
- 0x46, 0x20, 0x61, 0x75, 0xf1, 0x45, 0xcc, 0x58, 0xbf, 0x43, 0x36, 0xf4,
- 0xac, 0x5f, 0xff, 0xd3, 0xe3, 0x36, 0x1e, 0x7a, 0x7a, 0x3f, 0x81, 0x30,
- 0x58, 0xbf, 0xbe, 0xfa, 0xd3, 0x41, 0x62, 0xc0, 0x58, 0xb6, 0xc7, 0x3c,
- 0x0e, 0x17, 0x5f, 0xf0, 0xc6, 0x52, 0x18, 0xf2, 0x3d, 0x62, 0xa4, 0xf9,
- 0x84, 0x53, 0x5b, 0x26, 0x4c, 0x51, 0x82, 0xd2, 0xc5, 0x3a, 0x75, 0x11,
- 0x11, 0x94, 0x69, 0xf1, 0xc5, 0x57, 0xfb, 0x6d, 0xa4, 0xbb, 0xcf, 0x2c,
- 0x5f, 0xff, 0x43, 0x9c, 0x9d, 0x6e, 0x26, 0x1f, 0xe5, 0xd6, 0x2f, 0xc3,
- 0xcc, 0x2d, 0xd6, 0x2f, 0xdd, 0xf8, 0x9b, 0xeb, 0x17, 0x4c, 0x4b, 0x15,
- 0xb1, 0xf4, 0xc0, 0xa0, 0x05, 0x35, 0x89, 0xb3, 0x3a, 0x33, 0x1b, 0x0a,
- 0x17, 0x57, 0xff, 0x68, 0x85, 0xdf, 0x8b, 0x36, 0x62, 0x58, 0xbd, 0xb9,
- 0x87, 0x58, 0xbf, 0xff, 0x87, 0xf1, 0x6c, 0xf9, 0xad, 0x64, 0xf7, 0x07,
- 0x3a, 0xc5, 0xfe, 0x68, 0x88, 0x5e, 0x29, 0x58, 0xbd, 0x25, 0xe5, 0x8b,
- 0xf8, 0x66, 0x7b, 0xce, 0x1a, 0xc5, 0xc5, 0x12, 0xc5, 0x39, 0xf2, 0xb0,
- 0xe0, 0x8c, 0x6e, 0xf9, 0xab, 0x17, 0xed, 0xc6, 0xe5, 0xb2, 0xc5, 0xff,
- 0x7e, 0x7b, 0x2c, 0x1b, 0x41, 0x62, 0xf3, 0x6b, 0x65, 0x8b, 0x81, 0x2b,
- 0x17, 0xcf, 0x27, 0xc5, 0x8a, 0x58, 0xbf, 0x98, 0xdf, 0x4e, 0x80, 0xb1,
- 0x43, 0x37, 0x64, 0x19, 0x7f, 0xff, 0xa5, 0xc6, 0x52, 0x2d, 0xfd, 0x9b,
- 0x8e, 0x77, 0x30, 0xeb, 0x17, 0x02, 0x56, 0x2e, 0x93, 0x56, 0x2f, 0xfb,
- 0x3d, 0xc9, 0x39, 0x99, 0x12, 0xc5, 0xfe, 0xe6, 0x7d, 0xf8, 0x2d, 0x96,
- 0x2e, 0x0c, 0x34, 0x8b, 0xfe, 0x2c, 0xe8, 0xd0, 0xe3, 0x8d, 0x62, 0xb7,
- 0x54, 0x10, 0xe3, 0xda, 0x17, 0x3a, 0xe7, 0xc8, 0x00, 0xc8, 0x17, 0x17,
- 0x21, 0x8e, 0x1d, 0x86, 0x6a, 0x60, 0xd5, 0xe0, 0xc3, 0x0d, 0x22, 0xc7,
- 0x48, 0x8c, 0x34, 0x37, 0x36, 0x92, 0x23, 0x11, 0xca, 0x64, 0x30, 0x2f,
- 0xf9, 0x83, 0xd4, 0xbc, 0x1b, 0x8b, 0x14, 0xc7, 0xf0, 0x47, 0xf7, 0xff,
- 0xf8, 0x0d, 0xf6, 0x7f, 0x8b, 0xf3, 0xbb, 0xf7, 0x07, 0x3a, 0xc5, 0x2c,
- 0x50, 0xd7, 0x1b, 0xf0, 0x67, 0x72, 0xa8, 0xa5, 0xcf, 0x78, 0x80, 0xc6,
- 0x2a, 0xd9, 0x79, 0x64, 0x68, 0xbb, 0x90, 0x76, 0xbb, 0xf8, 0x4c, 0x34,
- 0xe4, 0xe5, 0xff, 0xfa, 0x13, 0xa0, 0x0f, 0x58, 0xe6, 0xf3, 0xf2, 0x75,
- 0x8b, 0xfb, 0xd3, 0x9f, 0xcd, 0x96, 0x2e, 0xc3, 0xac, 0x56, 0x22, 0x73,
- 0xb5, 0x7e, 0x17, 0x5f, 0xfd, 0x9f, 0xfb, 0x3f, 0xa7, 0x0a, 0x25, 0x8a,
- 0x0a, 0xc2, 0x02, 0x9a, 0x69, 0x0b, 0x7b, 0x46, 0x87, 0x09, 0xe8, 0xd1,
- 0xc7, 0x1d, 0x94, 0xb4, 0x13, 0x67, 0x3c, 0xbb, 0x9c, 0x8c, 0x7a, 0x43,
- 0xf4, 0x51, 0x93, 0x6a, 0x1c, 0x47, 0x8e, 0x9f, 0xf5, 0x8b, 0x3b, 0x56,
- 0x4b, 0x40, 0x95, 0x2c, 0x54, 0xa6, 0x9e, 0x56, 0x31, 0xbe, 0x97, 0x46,
- 0x29, 0xe9, 0x9e, 0x91, 0x82, 0xc7, 0x18, 0x5c, 0x67, 0x96, 0x2f, 0xec,
- 0x00, 0x1f, 0x50, 0x58, 0xbd, 0xf1, 0x1a, 0xb1, 0x76, 0xf8, 0xb1, 0x7e,
- 0xc8, 0xa7, 0xbe, 0x2c, 0x50, 0xd1, 0x1e, 0xe5, 0xcc, 0x3f, 0xc1, 0x8b,
- 0xff, 0x49, 0xe3, 0x9b, 0x6c, 0x1b, 0x86, 0xb1, 0x76, 0x06, 0xb1, 0x74,
- 0xf9, 0x62, 0xff, 0xf9, 0xca, 0x41, 0x82, 0x0b, 0xbf, 0xdf, 0x50, 0x58,
- 0xad, 0x91, 0x03, 0xb8, 0xc7, 0x05, 0xef, 0xb9, 0xc7, 0x02, 0xc5, 0xef,
- 0xb0, 0x16, 0x2b, 0x63, 0xc0, 0x62, 0x3b, 0x1d, 0x62, 0xa0, 0x9b, 0x56,
- 0x43, 0x13, 0x4e, 0x5e, 0x22, 0xbf, 0x9c, 0x06, 0x6d, 0x3b, 0x2c, 0x5f,
- 0xe8, 0x39, 0x61, 0xc5, 0xf5, 0x8b, 0xf7, 0xd9, 0xc9, 0x96, 0x2f, 0xfa,
- 0x5f, 0x58, 0xff, 0x91, 0xac, 0x5f, 0xfb, 0x3d, 0xcf, 0xb9, 0xdb, 0x34,
- 0xb1, 0x7f, 0xfb, 0xe2, 0xe6, 0xa4, 0xa2, 0xfb, 0x02, 0x56, 0x2e, 0xc1,
- 0xac, 0x5f, 0x4e, 0x7d, 0x96, 0x2a, 0x53, 0x51, 0x34, 0xcf, 0xe4, 0xc4,
- 0x6e, 0x23, 0xee, 0x89, 0x61, 0x05, 0xef, 0x60, 0x3c, 0xb1, 0x7b, 0xa4,
- 0x6d, 0xd1, 0x62, 0xd9, 0xd4, 0xf1, 0x30, 0x76, 0xfb, 0xaf, 0xa7, 0xa2,
- 0xc5, 0xf0, 0xca, 0x4c, 0x58, 0xbe, 0xde, 0x4e, 0xeb, 0x15, 0xd4, 0xf1,
- 0xb0, 0x8e, 0xff, 0xe2, 0x6d, 0x67, 0x8a, 0x7e, 0xf0, 0x58, 0xbf, 0xa4,
- 0xef, 0x1e, 0x7c, 0x58, 0xbc, 0x7c, 0xf2, 0xc5, 0xfb, 0x03, 0x79, 0x1a,
- 0xc5, 0xff, 0x66, 0x1c, 0xc0, 0x92, 0x50, 0x58, 0xa1, 0xa2, 0xc3, 0x0c,
- 0x1c, 0x77, 0x85, 0x17, 0xfb, 0x7f, 0xc9, 0x8f, 0x3b, 0x2c, 0x5e, 0x26,
- 0x1a, 0xc5, 0xcc, 0x6a, 0xc5, 0xfc, 0xc2, 0xdf, 0xf3, 0xc5, 0x8a, 0xd2,
- 0x26, 0x4e, 0x6d, 0xe1, 0xc8, 0xe1, 0x8b, 0xe6, 0x3b, 0x44, 0xb1, 0x7f,
- 0xf3, 0xc5, 0xd5, 0xfb, 0xe3, 0x18, 0xe7, 0x58, 0xbf, 0xf3, 0xcf, 0x98,
- 0xc2, 0x7e, 0xe0, 0xb1, 0x51, 0x22, 0x23, 0x89, 0x37, 0xdd, 0xff, 0x02,
- 0x2c, 0x5e, 0x08, 0x00, 0xd6, 0x2f, 0xa4, 0x39, 0x89, 0x62, 0xa4, 0xfa,
- 0xfb, 0x26, 0x72, 0x1b, 0xfd, 0xd7, 0xec, 0x00, 0x3f, 0xd6, 0x2d, 0xa5,
- 0x8b, 0xde, 0xef, 0x8b, 0x15, 0x86, 0xc5, 0x84, 0xaa, 0x53, 0x43, 0x78,
- 0x47, 0xb1, 0x71, 0x33, 0xdf, 0xff, 0xf9, 0xa2, 0x14, 0x05, 0xbf, 0x5f,
- 0xbf, 0xbd, 0x3d, 0xce, 0xd3, 0xc5, 0x8b, 0xf1, 0x34, 0x7e, 0xd1, 0x2c,
- 0x5f, 0x4e, 0x9f, 0xb5, 0x8b, 0xe8, 0xb9, 0x3e, 0x58, 0xad, 0xd1, 0xcf,
- 0x13, 0x9b, 0x16, 0x88, 0x8e, 0xfe, 0xe9, 0xa6, 0x97, 0x8e, 0x58, 0xb9,
- 0xfb, 0x58, 0xbf, 0xf8, 0x9b, 0xcf, 0xaf, 0xc9, 0xf8, 0xcb, 0x14, 0xb1,
- 0x5a, 0x3e, 0x71, 0x0c, 0x06, 0x87, 0x7f, 0x34, 0x42, 0x63, 0x0e, 0xb1,
- 0x78, 0x42, 0x31, 0x62, 0xff, 0xe6, 0xef, 0xae, 0x1c, 0x5c, 0x17, 0x19,
- 0x62, 0xa0, 0x89, 0x7e, 0x18, 0x08, 0x7e, 0xff, 0xe8, 0x7e, 0x75, 0xb4,
- 0xfb, 0x8d, 0x05, 0x8b, 0xe2, 0x66, 0xe8, 0xb1, 0x27, 0x8d, 0x7f, 0x4e,
- 0xfe, 0xe3, 0x76, 0xb1, 0x7d, 0xfc, 0x6d, 0x96, 0x2f, 0x1d, 0xbb, 0x58,
- 0xbf, 0xcc, 0x6c, 0x70, 0xbe, 0xfa, 0x58, 0xac, 0x3d, 0x62, 0x1e, 0xae,
- 0xd3, 0x72, 0x8f, 0x76, 0x23, 0x3e, 0x18, 0x18, 0xf3, 0x79, 0xfb, 0x89,
- 0x62, 0xf8, 0x41, 0x73, 0xba, 0xc5, 0xf6, 0x6c, 0x2e, 0x2c, 0x5f, 0xf6,
- 0x6c, 0xd1, 0x75, 0x88, 0x47, 0x58, 0xac, 0x3e, 0x3f, 0x12, 0x5f, 0x68,
- 0x9c, 0x0b, 0x17, 0xcf, 0xbb, 0x69, 0x62, 0xe9, 0x02, 0xc5, 0xa3, 0x3e,
- 0x6e, 0x8c, 0x23, 0xa5, 0x8b, 0x85, 0xb0, 0x8d, 0xb8, 0x65, 0x74, 0xe8,
- 0xc2, 0xfc, 0x24, 0xec, 0x05, 0x8b, 0xb3, 0x75, 0x8b, 0xf6, 0x6b, 0x4f,
- 0xa5, 0x8a, 0x8f, 0x3d, 0x2f, 0x89, 0x00, 0x62, 0xfd, 0xbf, 0xd8, 0x5a,
- 0x58, 0xbe, 0x9e, 0xf3, 0x75, 0x8b, 0xf1, 0x8f, 0x3c, 0x65, 0x8a, 0x63,
- 0xcc, 0x11, 0x25, 0xe3, 0x26, 0x3d, 0x62, 0xff, 0xbe, 0xdc, 0xfb, 0xec,
- 0xc4, 0xb1, 0x7c, 0xdb, 0x19, 0x05, 0x8a, 0x0a, 0xb6, 0x27, 0x71, 0xb4,
- 0x2a, 0x26, 0x3a, 0x5d, 0x90, 0xa1, 0x1c, 0x10, 0xe1, 0x59, 0x85, 0x06,
- 0xb6, 0xee, 0x47, 0xdc, 0x3c, 0x9e, 0x1a, 0x91, 0xe8, 0x11, 0x47, 0xdd,
- 0xa8, 0xc9, 0x8e, 0x7d, 0xf8, 0x4c, 0xb4, 0xa3, 0x90, 0x27, 0x85, 0xc7,
- 0xf9, 0x08, 0xaf, 0x43, 0x8c, 0x4f, 0x3d, 0x0c, 0x83, 0x76, 0x8e, 0x21,
- 0x30, 0x84, 0x21, 0xcd, 0xe2, 0x17, 0x16, 0x2f, 0xf6, 0x13, 0x83, 0x9f,
- 0x75, 0x8b, 0x88, 0x0b, 0x16, 0x8f, 0x58, 0xbe, 0x19, 0xda, 0x0b, 0x14,
- 0xe6, 0xe0, 0x42, 0xb5, 0xd5, 0x14, 0x3f, 0x32, 0x24, 0xfb, 0xcf, 0xb0,
- 0x96, 0x2f, 0xba, 0x7e, 0x60, 0xb1, 0x7f, 0xee, 0x8f, 0xa1, 0x04, 0x6d,
- 0x8c, 0x82, 0xc5, 0xa5, 0x62, 0xfc, 0x28, 0x8a, 0x4e, 0xb1, 0x52, 0x8a,
- 0x5c, 0x25, 0x64, 0x6e, 0x08, 0xdf, 0xa4, 0x0f, 0xde, 0x2c, 0x5c, 0x71,
- 0x2c, 0x5f, 0x9b, 0xdf, 0x11, 0x2c, 0x5c, 0x7e, 0x8b, 0x17, 0xfc, 0x26,
- 0x72, 0x6f, 0x37, 0xd6, 0x2b, 0xaa, 0x3c, 0xe4, 0xe9, 0xca, 0x3e, 0x30,
- 0x45, 0x1c, 0x1a, 0xbf, 0xf7, 0x1c, 0x13, 0xa7, 0xfc, 0x8d, 0x62, 0xf9,
- 0x87, 0x17, 0x6b, 0x15, 0x27, 0xc7, 0xb1, 0xf5, 0xe6, 0x10, 0x5d, 0x62,
- 0xff, 0xd9, 0xb9, 0x67, 0x23, 0xb3, 0x52, 0xb1, 0x43, 0x4c, 0xf4, 0xa1,
- 0x73, 0xe2, 0x23, 0x08, 0x6f, 0xff, 0x40, 0xa7, 0xa9, 0xca, 0x4d, 0xf3,
- 0xec, 0xb1, 0x7d, 0x82, 0xd6, 0xcb, 0x17, 0xe6, 0x3e, 0x7c, 0xeb, 0x15,
- 0xda, 0x26, 0x74, 0x9b, 0xe2, 0x4b, 0x06, 0xb1, 0x7f, 0x4f, 0x70, 0x72,
- 0xc5, 0x8b, 0xde, 0xd4, 0xac, 0x5e, 0xe3, 0x79, 0x62, 0xfb, 0x36, 0x32,
- 0x0b, 0x17, 0x8c, 0x20, 0x2c, 0x57, 0x67, 0xc0, 0x43, 0xbe, 0x25, 0xbf,
- 0xed, 0xb0, 0xb5, 0x9d, 0x24, 0x0b, 0x17, 0xf7, 0xba, 0x61, 0x60, 0xd6,
- 0x2a, 0x24, 0x4c, 0x91, 0x7f, 0x0e, 0xef, 0xdc, 0xc8, 0x3e, 0x96, 0x2f,
- 0xd1, 0x41, 0xbb, 0xe2, 0xc5, 0x61, 0xe9, 0xf0, 0xa2, 0xf0, 0xa3, 0xc2,
- 0x2c, 0x5b, 0xa2, 0xc5, 0xff, 0x6b, 0xec, 0x63, 0x7d, 0xc0, 0xb1, 0x52,
- 0x79, 0xce, 0x29, 0x7f, 0x39, 0x6d, 0xf1, 0x71, 0x62, 0xbe, 0x79, 0xfe,
- 0x20, 0xbe, 0xfe, 0x01, 0x96, 0x2e, 0x8f, 0x08, 0xb1, 0x7b, 0x90, 0xd9,
- 0x62, 0xb6, 0x4d, 0x03, 0x21, 0x80, 0x44, 0x42, 0x22, 0x30, 0x76, 0xba,
- 0xb2, 0x1e, 0x66, 0x17, 0xd0, 0x31, 0xc9, 0x5e, 0x6f, 0x0d, 0xc8, 0x8c,
- 0x74, 0x26, 0x72, 0xd6, 0x8c, 0x58, 0xa1, 0x07, 0xe8, 0xd8, 0x6f, 0x4b,
- 0xe9, 0x62, 0xee, 0xa6, 0x2c, 0x51, 0xcd, 0xbb, 0x0e, 0x5c, 0xfd, 0x16,
- 0x2f, 0x44, 0xff, 0x58, 0xbf, 0xa7, 0x4d, 0x13, 0xfd, 0x62, 0xfd, 0xc1,
- 0xc9, 0x6c, 0xc7, 0x99, 0xc1, 0xeb, 0xff, 0xde, 0xf4, 0x94, 0x9a, 0x6c,
- 0xc2, 0x3c, 0xeb, 0x17, 0xf6, 0x6d, 0x3f, 0xfc, 0xac, 0x5f, 0xb2, 0x2f,
- 0xe1, 0x2c, 0x5f, 0xb0, 0xc2, 0x10, 0x16, 0x2f, 0xc0, 0x66, 0x81, 0xd6,
- 0x2a, 0x4f, 0x47, 0x0a, 0x6f, 0x9c, 0x3c, 0xd2, 0xc5, 0xff, 0xdf, 0xc3,
- 0xe7, 0x46, 0x3e, 0x6a, 0x0b, 0x14, 0xe9, 0xbf, 0xe9, 0x3f, 0xe5, 0xc4,
- 0xf3, 0xc2, 0x0f, 0x11, 0xde, 0x3c, 0x9d, 0x62, 0xf4, 0xed, 0x8b, 0x15,
- 0x8a, 0xac, 0xbb, 0x65, 0xd4, 0x77, 0xa7, 0x56, 0xf0, 0xed, 0xf1, 0xf5,
- 0xa9, 0x58, 0xbf, 0xfe, 0xf7, 0xa4, 0xf9, 0xff, 0xcb, 0x94, 0x9d, 0x62,
- 0xfd, 0xce, 0x31, 0x41, 0x62, 0xff, 0xf1, 0x60, 0xda, 0x1e, 0x72, 0x2c,
- 0xdd, 0x62, 0xfe, 0x7d, 0x70, 0xc9, 0x02, 0xc5, 0xff, 0xd9, 0xef, 0xbf,
- 0xbf, 0x85, 0x20, 0x58, 0xb9, 0xb6, 0x58, 0xb7, 0x4e, 0xa8, 0xfa, 0xc2,
- 0x80, 0x24, 0x11, 0x7c, 0x72, 0x1d, 0xff, 0xb0, 0x6f, 0xce, 0xfc, 0x26,
- 0xe2, 0xc5, 0xfb, 0xab, 0x1b, 0xf7, 0x58, 0xb4, 0x3a, 0x9f, 0x5f, 0x10,
- 0x2f, 0xfb, 0x99, 0xe9, 0x3b, 0xea, 0x0b, 0x15, 0xda, 0xa6, 0xb7, 0x8d,
- 0x20, 0xa1, 0x81, 0xe2, 0xab, 0xf7, 0xc4, 0x53, 0xd1, 0x62, 0xfe, 0x26,
- 0xf4, 0x24, 0xd5, 0x8a, 0x93, 0xd8, 0x30, 0xaa, 0xfd, 0x1b, 0x49, 0xb2,
- 0x1a, 0xc5, 0xc7, 0xe2, 0xc5, 0xf6, 0xdd, 0x42, 0x6e, 0xb1, 0x7e, 0x70,
- 0xf3, 0xbf, 0x2c, 0x5d, 0x21, 0xac, 0x57, 0xcf, 0x08, 0x8a, 0xaf, 0xff,
- 0x72, 0x75, 0xbf, 0xb8, 0xfe, 0xfe, 0x0d, 0x62, 0xf6, 0xd1, 0xb0, 0x5b,
- 0x58, 0xbd, 0x9d, 0xc1, 0x62, 0xe6, 0x1a, 0xc5, 0x61, 0xb5, 0x61, 0xeb,
- 0xdc, 0x78, 0x96, 0x28, 0x8d, 0xef, 0x07, 0xef, 0xcf, 0xd3, 0x58, 0x75,
- 0x8a, 0xc4, 0x73, 0x1b, 0x09, 0xcf, 0x90, 0x5b, 0x8b, 0x17, 0x8d, 0x71,
- 0xac, 0x5f, 0xcc, 0xda, 0x0f, 0x3e, 0xb1, 0x7f, 0x9e, 0x7d, 0x9d, 0x18,
- 0x6b, 0x17, 0xfb, 0xf3, 0xa7, 0xdd, 0xfa, 0x2c, 0x51, 0xa8, 0xb6, 0x88,
- 0x7b, 0x45, 0xde, 0x34, 0xbe, 0x92, 0x73, 0xac, 0x5f, 0xfb, 0x62, 0x9e,
- 0xdc, 0x65, 0x3b, 0x2c, 0x5f, 0xe0, 0x73, 0xc5, 0x27, 0xe2, 0xc5, 0xfe,
- 0x3c, 0xfd, 0xb9, 0x31, 0xeb, 0x15, 0x27, 0xd4, 0xc6, 0x95, 0xba, 0x3a,
- 0xd8, 0x84, 0xa1, 0x55, 0x43, 0x57, 0x5d, 0xb9, 0x0e, 0xa3, 0x32, 0x39,
- 0xaf, 0xe1, 0x90, 0x51, 0x95, 0x5f, 0x1a, 0x18, 0xce, 0xb1, 0x7e, 0xeb,
- 0xf9, 0xd4, 0x16, 0x2b, 0xab, 0x2e, 0x46, 0x65, 0x69, 0x6c, 0xa5, 0x92,
- 0xa3, 0xb7, 0x85, 0x0f, 0x64, 0x51, 0x17, 0x9c, 0x61, 0xa7, 0x06, 0xbc,
- 0xd4, 0x19, 0x35, 0xef, 0xb8, 0x45, 0x8b, 0xb9, 0x2b, 0x17, 0xdc, 0x62,
- 0x82, 0xc5, 0x40, 0xf6, 0x0e, 0x3f, 0xc1, 0x7b, 0xfb, 0x68, 0xa1, 0x1b,
- 0x6b, 0x65, 0x8b, 0xb3, 0x75, 0x8b, 0x9f, 0x65, 0x8a, 0xf1, 0xb0, 0x08,
- 0x31, 0x4b, 0x16, 0xe2, 0xc5, 0x6e, 0x5f, 0x70, 0x32, 0xf6, 0x37, 0xd6,
- 0x28, 0x66, 0xf4, 0xe4, 0x36, 0xd9, 0x62, 0xff, 0x87, 0x87, 0x7e, 0xe0,
- 0x52, 0xb1, 0x7e, 0xf7, 0xdc, 0xfa, 0x58, 0xa8, 0x1f, 0xab, 0x89, 0xe8,
- 0xe6, 0xf7, 0xc6, 0xeb, 0x16, 0xe8, 0xb1, 0x7e, 0xfe, 0x3c, 0x38, 0xb1,
- 0x7f, 0xfd, 0xf9, 0x32, 0x33, 0xc4, 0xc0, 0xe7, 0x24, 0x09, 0x17, 0xec,
- 0xf3, 0x08, 0x2e, 0xb1, 0x68, 0xf5, 0x8b, 0xf6, 0xb7, 0x66, 0xdd, 0x71,
- 0x02, 0x17, 0xb9, 0x3d, 0xac, 0x5e, 0xe6, 0xa0, 0xb1, 0x7f, 0xff, 0x43,
- 0xae, 0x7d, 0x8b, 0x3d, 0xc6, 0xf7, 0x33, 0xcb, 0x14, 0xe7, 0xf4, 0xc3,
- 0xd6, 0x04, 0xa6, 0x09, 0x82, 0xbd, 0x9b, 0x9e, 0x13, 0x17, 0xc5, 0x81,
- 0x84, 0x58, 0xbd, 0x0f, 0x71, 0x62, 0xe7, 0xd9, 0x62, 0x9c, 0xf6, 0xd8,
- 0x97, 0xc3, 0xd7, 0x84, 0x5b, 0xac, 0x5f, 0x33, 0x31, 0x8b, 0x17, 0xdd,
- 0x81, 0xe0, 0xb1, 0x7f, 0xfd, 0x9f, 0x7d, 0x7d, 0xb8, 0xfe, 0x92, 0xdd,
- 0x62, 0xfb, 0x62, 0x63, 0xac, 0x5c, 0xc4, 0xb1, 0x52, 0x6e, 0x76, 0x23,
- 0xa0, 0xaa, 0xb9, 0xd8, 0x0a, 0x0c, 0xa3, 0xb5, 0x4d, 0x46, 0x60, 0x78,
- 0x51, 0xfc, 0xb5, 0x87, 0x88, 0x8b, 0x84, 0x9e, 0x84, 0x45, 0xf4, 0x5f,
- 0xcf, 0x2c, 0x5f, 0xcd, 0xac, 0xe9, 0x83, 0x58, 0xbf, 0x6e, 0xc6, 0xfd,
- 0xd6, 0x29, 0x8f, 0xf4, 0x04, 0x84, 0x5f, 0x7d, 0xa1, 0xb9, 0xd6, 0x2f,
- 0x0d, 0xa0, 0xb1, 0x68, 0x2c, 0x54, 0x9a, 0xf0, 0x83, 0xb7, 0x89, 0xb8,
- 0xb1, 0x7d, 0xed, 0x98, 0x96, 0x2f, 0x1e, 0x77, 0x58, 0xb9, 0x8d, 0x58,
- 0xac, 0x36, 0xc4, 0x3d, 0x73, 0x69, 0x62, 0xd0, 0x58, 0xbf, 0x6c, 0x2f,
- 0x74, 0xf2, 0xc5, 0xd2, 0x05, 0x8a, 0xc3, 0xc4, 0xf1, 0x6d, 0x49, 0xfb,
- 0x9a, 0xad, 0x70, 0x03, 0x58, 0xbf, 0xd0, 0xd4, 0xec, 0xda, 0xdd, 0x62,
- 0xff, 0xec, 0x00, 0xb8, 0xdb, 0x39, 0x4f, 0x6b, 0x15, 0xd5, 0x12, 0x8c,
- 0x32, 0x46, 0xd6, 0x75, 0x8b, 0xff, 0xf3, 0x76, 0x0d, 0xfe, 0xf1, 0x13,
- 0x07, 0xec, 0xfa, 0xc5, 0xe3, 0x5f, 0xcb, 0x17, 0xb8, 0xde, 0x58, 0xbf,
- 0x9f, 0x69, 0xf4, 0x8d, 0x62, 0xa5, 0x1a, 0x78, 0x22, 0x6a, 0xcf, 0x63,
- 0xcc, 0x3b, 0x77, 0x5f, 0xac, 0x5f, 0xbc, 0xe3, 0x14, 0xac, 0x5f, 0x34,
- 0x30, 0x6b, 0x14, 0x73, 0xca, 0x22, 0x8b, 0x12, 0xc5, 0xb7, 0x58, 0xb1,
- 0xe4, 0xd2, 0x78, 0x46, 0xde, 0x93, 0xeb, 0xc4, 0x5b, 0xfb, 0xd9, 0x14,
- 0x18, 0x0b, 0x17, 0xf4, 0x9f, 0x0d, 0x9e, 0x2c, 0x56, 0xcb, 0x93, 0x10,
- 0x22, 0xc1, 0xcd, 0xd6, 0x63, 0xc7, 0xf5, 0x08, 0xe3, 0xc2, 0xdb, 0xf1,
- 0x81, 0x81, 0x24, 0xa1, 0x9f, 0xc2, 0x6f, 0x17, 0xdf, 0xf8, 0xb3, 0x50,
- 0xc8, 0x18, 0xd1, 0xeb, 0x17, 0xe0, 0x9e, 0xc2, 0x02, 0xc5, 0xc7, 0x95,
- 0x8a, 0xc3, 0xc1, 0x72, 0xab, 0xfe, 0x87, 0x5c, 0x9d, 0xf7, 0xc2, 0x58,
- 0xbd, 0xf7, 0xd2, 0xc5, 0x0c, 0xf6, 0x7c, 0x79, 0x7e, 0xf9, 0x63, 0xf9,
- 0x62, 0xe9, 0x3a, 0xc5, 0xec, 0xd6, 0x2c, 0x56, 0xe6, 0xcc, 0xe2, 0xf7,
- 0xfc, 0x0f, 0xe7, 0x70, 0xf3, 0xc4, 0xb1, 0x52, 0x8b, 0x8c, 0x5a, 0x11,
- 0x15, 0xd9, 0xb2, 0xc5, 0x84, 0xb1, 0x43, 0x35, 0x5a, 0x18, 0xbf, 0xd3,
- 0x85, 0xee, 0x47, 0x74, 0x58, 0xbf, 0xa6, 0x3f, 0xee, 0xd0, 0x58, 0xbd,
- 0x3c, 0xea, 0x73, 0xe8, 0x23, 0x8b, 0xf9, 0x83, 0xe7, 0x24, 0x0b, 0x15,
- 0xf3, 0xe3, 0x23, 0x4b, 0x9b, 0x4b, 0x17, 0x30, 0x6b, 0x15, 0x26, 0xbc,
- 0x42, 0xf7, 0xfe, 0xfb, 0x17, 0xb8, 0x42, 0x63, 0x16, 0x2f, 0xfb, 0x5a,
- 0x7e, 0xe1, 0xe6, 0xed, 0x62, 0xf4, 0x73, 0x1a, 0xb1, 0x7f, 0xd2, 0x78,
- 0x66, 0xd8, 0x20, 0xba, 0xc5, 0xff, 0x48, 0x1e, 0x1f, 0x72, 0x02, 0xc5,
- 0xb6, 0x58, 0xb9, 0xbd, 0xa3, 0xcb, 0x0b, 0x9c, 0x56, 0x23, 0x6d, 0xc8,
- 0x5a, 0x11, 0x37, 0x36, 0xcb, 0x17, 0x49, 0x8b, 0x14, 0xc6, 0xc0, 0x31,
- 0x8b, 0xff, 0x9b, 0x86, 0x79, 0xc8, 0x50, 0xce, 0x2c, 0x5e, 0x0c, 0x30,
- 0xd7, 0x57, 0xd4, 0x71, 0xb8, 0x86, 0xba, 0xbe, 0x88, 0xc3, 0x6f, 0x52,
- 0x8b, 0x36, 0x7c, 0xb8, 0x0c, 0xb1, 0x7f, 0xf4, 0x9b, 0x9e, 0x33, 0x6f,
- 0x42, 0x4d, 0x58, 0xbe, 0x80, 0xa4, 0xd5, 0x8b, 0x01, 0x62, 0xa0, 0x7f,
- 0xf8, 0x92, 0xc4, 0x97, 0x89, 0x80, 0xb1, 0x52, 0xb9, 0xd0, 0x38, 0x76,
- 0x1a, 0xa1, 0xb9, 0x03, 0x9f, 0xea, 0x31, 0x7f, 0xb1, 0x02, 0x1a, 0x84,
- 0x43, 0xe8, 0x4b, 0x18, 0x5b, 0x7f, 0x87, 0xf6, 0x39, 0x92, 0x4b, 0x17,
- 0xf7, 0xf2, 0x1f, 0x7e, 0x8b, 0x15, 0x1e, 0x7c, 0x9e, 0x34, 0xb1, 0x2c,
- 0x5e, 0xd0, 0xb6, 0x58, 0xa8, 0x1b, 0x03, 0x88, 0xdf, 0xff, 0x13, 0x9b,
- 0x19, 0xcf, 0x7c, 0x4d, 0x08, 0x4a, 0xc5, 0x49, 0xfa, 0xe1, 0x0d, 0xfb,
- 0xf9, 0xee, 0x4a, 0xc5, 0xba, 0x2c, 0x5f, 0x8b, 0xc2, 0xcf, 0xac, 0x58,
- 0x4b, 0x14, 0xb1, 0x5d, 0x4b, 0xe1, 0x09, 0x54, 0x9f, 0x46, 0xc8, 0xd7,
- 0x04, 0x75, 0x8b, 0xba, 0x4a, 0xc5, 0xf7, 0x3d, 0x9a, 0x58, 0xad, 0x95,
- 0x8c, 0xc2, 0x31, 0x43, 0x61, 0x95, 0xb9, 0x04, 0x45, 0x1a, 0x7c, 0x62,
- 0x2e, 0x0c, 0xf8, 0x66, 0xf0, 0xda, 0x0b, 0x17, 0x3e, 0x96, 0x2b, 0x0d,
- 0xa7, 0xc7, 0x6f, 0xfb, 0xa1, 0x67, 0x0d, 0xd6, 0x71, 0x62, 0xf8, 0x89,
- 0xce, 0xb1, 0x58, 0x7b, 0xac, 0x79, 0x7b, 0x3a, 0x18, 0xb1, 0x73, 0xfd,
- 0x62, 0xe7, 0xe8, 0xb1, 0x68, 0x2c, 0x54, 0x9a, 0xb6, 0x19, 0xbf, 0xf0,
- 0x98, 0xf3, 0xae, 0x39, 0x44, 0xb1, 0x43, 0x3d, 0xe2, 0x1f, 0xbf, 0x8d,
- 0x93, 0x94, 0xc4, 0xb1, 0x7c, 0xc7, 0xc3, 0xac, 0x5f, 0xce, 0x4d, 0xe1,
- 0x79, 0x62, 0xf9, 0xcf, 0x31, 0xeb, 0x17, 0x3e, 0xba, 0x9f, 0xa4, 0x91,
- 0x61, 0x6d, 0x0d, 0x39, 0xec, 0x85, 0x06, 0x88, 0x7f, 0x0a, 0x3b, 0xfb,
- 0xd9, 0xcf, 0x8b, 0x8b, 0x17, 0xe7, 0xdc, 0x9b, 0x75, 0x8b, 0xec, 0x3b,
- 0x76, 0xb1, 0x7c, 0x76, 0x2c, 0x58, 0xbf, 0x78, 0xb3, 0x52, 0xb1, 0x70,
- 0x23, 0xd6, 0x2b, 0x63, 0xc2, 0x22, 0x7a, 0x94, 0x68, 0xe1, 0x4b, 0x91,
- 0xb3, 0x1d, 0xc5, 0x12, 0xc5, 0x2c, 0x52, 0xc5, 0x9b, 0xc5, 0xc0, 0x40,
- 0xca, 0x93, 0xd7, 0x01, 0x85, 0xe7, 0x98, 0x2c, 0x57, 0x56, 0xef, 0xd2,
- 0x37, 0x2f, 0x8d, 0x9a, 0x25, 0xfa, 0x10, 0x96, 0x19, 0x76, 0x4b, 0xba,
- 0x36, 0x32, 0xad, 0xcb, 0x5e, 0x73, 0xaa, 0x28, 0x60, 0x6a, 0x10, 0x67,
- 0x79, 0xfc, 0x36, 0x9a, 0x90, 0xb2, 0x08, 0x61, 0x13, 0xef, 0x08, 0x05,
- 0x1d, 0xf0, 0x68, 0xf1, 0xd1, 0x80, 0x19, 0x09, 0x00, 0x84, 0x37, 0xe3,
- 0x06, 0x2f, 0x71, 0x62, 0xff, 0x9f, 0xed, 0xa9, 0x37, 0x22, 0x58, 0xbf,
- 0xfe, 0xfc, 0xb6, 0xb9, 0xcc, 0xfb, 0xf0, 0x5b, 0x2c, 0x5f, 0x67, 0xd8,
- 0xeb, 0x16, 0xf4, 0xa2, 0xb7, 0x87, 0x46, 0x28, 0xdf, 0xf6, 0x0b, 0xc3,
- 0x7d, 0x37, 0x16, 0x2f, 0xc3, 0x9f, 0xc9, 0x8b, 0x16, 0x0d, 0x62, 0x99,
- 0x15, 0x7c, 0x36, 0x11, 0xc9, 0x85, 0x37, 0xfc, 0xdc, 0x2c, 0xe8, 0xff,
- 0x12, 0xc5, 0xfb, 0xf9, 0xb8, 0xb1, 0x62, 0xec, 0xe2, 0xc5, 0x61, 0xe0,
- 0x31, 0x4d, 0xff, 0x16, 0x7a, 0x7a, 0x39, 0x01, 0x62, 0xff, 0x7a, 0x7a,
- 0x3f, 0xa1, 0x2b, 0x17, 0xff, 0xf6, 0x19, 0x3a, 0x03, 0xfb, 0x42, 0x3f,
- 0x3d, 0x9a, 0x58, 0xbf, 0x1c, 0xc9, 0xd0, 0x16, 0x2b, 0x11, 0x78, 0x46,
- 0xa6, 0x2e, 0xdf, 0x31, 0x64, 0x7a, 0xc5, 0xa3, 0xd6, 0x28, 0x66, 0xe7,
- 0xc4, 0x95, 0x89, 0xbf, 0x02, 0x1e, 0xbc, 0x68, 0xa5, 0x8b, 0xf3, 0xfb,
- 0x82, 0x8f, 0x58, 0xb6, 0x8e, 0x6e, 0x3e, 0x19, 0x7c, 0xfe, 0x98, 0x2c,
- 0x5f, 0xe1, 0x33, 0xc2, 0x4b, 0x75, 0x8a, 0xc3, 0xfc, 0xf9, 0x3f, 0x08,
- 0xaf, 0xbd, 0xdf, 0x31, 0x62, 0xe6, 0xe8, 0xb1, 0x6e, 0x8b, 0x14, 0xe6,
- 0xb5, 0x86, 0x6f, 0x7f, 0x00, 0xb1, 0x7f, 0xe7, 0xd7, 0xdb, 0x86, 0xeb,
- 0xdb, 0xac, 0x5f, 0x00, 0xc9, 0xe2, 0xc5, 0xf9, 0xfd, 0x3e, 0xe2, 0x45,
- 0xf6, 0xf3, 0xee, 0x24, 0x5c, 0x18, 0x69, 0x15, 0x03, 0xe6, 0xc2, 0x80,
- 0xc9, 0x29, 0x22, 0x30, 0xd7, 0xd4, 0x13, 0x37, 0xf8, 0xe9, 0x21, 0x07,
- 0x0b, 0x9b, 0xcc, 0x40, 0x58, 0xb4, 0x6a, 0x58, 0xbc, 0xdf, 0x65, 0x8b,
- 0xf0, 0x7e, 0x32, 0x40, 0xb1, 0x7e, 0xce, 0x7b, 0x23, 0xd6, 0x2a, 0x55,
- 0x48, 0x0d, 0x47, 0x23, 0x56, 0x35, 0x0c, 0xe3, 0x9f, 0x18, 0x61, 0xcf,
- 0x15, 0xde, 0x26, 0x0d, 0x62, 0xfe, 0xe0, 0xff, 0x25, 0xb2, 0xc5, 0xfb,
- 0xef, 0x3a, 0x02, 0xc5, 0x44, 0x7e, 0x80, 0x1d, 0xf1, 0x7d, 0xdf, 0x75,
- 0x8b, 0xcf, 0xd3, 0x16, 0x2f, 0x67, 0x38, 0xb1, 0x51, 0x1e, 0x96, 0x85,
- 0xc8, 0x7a, 0xfe, 0x33, 0x35, 0xdf, 0x25, 0x62, 0xff, 0xe7, 0xf8, 0xa3,
- 0x6e, 0x7b, 0xee, 0xc0, 0x58, 0xb6, 0x1c, 0xfe, 0xbc, 0x61, 0x7f, 0xd8,
- 0x5e, 0xfb, 0xc9, 0x6c, 0xb1, 0x7f, 0xff, 0xbf, 0x87, 0x32, 0x41, 0xa9,
- 0xe1, 0x67, 0x47, 0xf8, 0x96, 0x2f, 0x7a, 0x77, 0xc4, 0x4d, 0xf8, 0xe2,
- 0xff, 0xf0, 0x6d, 0xcf, 0x3f, 0xdf, 0x0d, 0x7d, 0x2c, 0x52, 0xc5, 0x0d,
- 0x34, 0xdc, 0x86, 0x17, 0xcd, 0x38, 0x97, 0x5b, 0x32, 0xc9, 0x07, 0x1c,
- 0x1e, 0xe7, 0xb1, 0x3d, 0x6a, 0x39, 0xe3, 0xc3, 0xa4, 0x12, 0xaf, 0x8a,
- 0x1d, 0x7c, 0x84, 0x10, 0x71, 0xfb, 0x5f, 0xcf, 0x9b, 0x1d, 0xfc, 0xb1,
- 0x7e, 0x91, 0xfd, 0xa3, 0xd6, 0x2c, 0x1a, 0xc5, 0xf4, 0x51, 0xe4, 0x05,
- 0x8b, 0x10, 0x0d, 0xd7, 0x84, 0xeb, 0x48, 0xb9, 0x22, 0xe1, 0x32, 0xdf,
- 0xc5, 0x30, 0xd6, 0xa5, 0x62, 0xf4, 0xe8, 0x0b, 0x17, 0xc5, 0x3d, 0x83,
- 0x0f, 0x2b, 0xe5, 0xb7, 0xf4, 0x1b, 0xce, 0x2e, 0x2c, 0x5f, 0xfb, 0xdc,
- 0xcd, 0xfe, 0xc5, 0xee, 0x2c, 0x5e, 0x72, 0x02, 0xc7, 0x53, 0xc0, 0xa3,
- 0xa3, 0x54, 0x8e, 0x3a, 0x37, 0x5d, 0xcf, 0x2c, 0x5f, 0xf8, 0xef, 0x87,
- 0xf7, 0x04, 0x5e, 0x58, 0xbf, 0xff, 0xb4, 0x2e, 0x7d, 0xa1, 0xbf, 0xdf,
- 0xb8, 0x4b, 0x41, 0x62, 0x8d, 0x44, 0xef, 0x8f, 0xef, 0xfd, 0xe7, 0xe6,
- 0xd8, 0x1e, 0x77, 0xe5, 0x8b, 0xff, 0xfd, 0xf7, 0x21, 0x7a, 0x12, 0x68,
- 0xbf, 0x27, 0xce, 0xfc, 0xb1, 0x7f, 0xf4, 0xef, 0xf7, 0xf6, 0x44, 0x52,
- 0x7c, 0x45, 0x2e, 0xe8, 0x57, 0xff, 0xcc, 0x7f, 0x7d, 0x8f, 0x90, 0x90,
- 0x73, 0x16, 0x2b, 0x74, 0x55, 0x92, 0xe5, 0x4a, 0x72, 0xf9, 0x1b, 0xa5,
- 0x4a, 0xaa, 0x5c, 0x31, 0xfc, 0xa4, 0xcb, 0x6c, 0xb1, 0x7f, 0x72, 0x43,
- 0xf6, 0x6e, 0xb1, 0x7f, 0xd9, 0xd1, 0xb4, 0xd0, 0x68, 0x2c, 0x58, 0x7b,
- 0x9f, 0xef, 0x62, 0x7c, 0x30, 0xbf, 0xfd, 0xf7, 0x88, 0x98, 0x3f, 0x67,
- 0xcc, 0x3a, 0xc5, 0xfe, 0x84, 0xe1, 0x78, 0x4c, 0xb1, 0x6d, 0xb7, 0x3f,
- 0xfe, 0xd3, 0x6a, 0x51, 0xc2, 0x28, 0x5b, 0x5f, 0xd3, 0xf9, 0xfc, 0xec,
- 0xb1, 0x7b, 0xd2, 0x35, 0x8b, 0xff, 0x3b, 0x77, 0x0f, 0x70, 0x9c, 0xd5,
- 0x8b, 0xfb, 0x23, 0x85, 0xf7, 0xd2, 0xc5, 0x40, 0xfc, 0x4c, 0x40, 0xa9,
- 0x45, 0x8e, 0x42, 0x3a, 0xb6, 0x4c, 0x16, 0x10, 0xdf, 0xb7, 0x16, 0x29,
- 0x62, 0x98, 0xbe, 0x0c, 0x4a, 0xa4, 0xfa, 0x19, 0x22, 0xff, 0x61, 0xd8,
- 0xbd, 0xc9, 0x58, 0xb8, 0x0e, 0xb1, 0x5a, 0x3c, 0x92, 0x32, 0xa1, 0xaa,
- 0x1e, 0xfc, 0x72, 0x8c, 0xd3, 0x7d, 0x3d, 0x1c, 0x6b, 0x17, 0xe8, 0x7c,
- 0x53, 0xa5, 0x8b, 0xfd, 0x3d, 0x1f, 0xa1, 0x0b, 0x8b, 0x17, 0xf3, 0xf1,
- 0xbb, 0x86, 0x2c, 0x5c, 0xc7, 0xd1, 0xf2, 0xc7, 0x1b, 0xde, 0x7d, 0x1a,
- 0xb1, 0x7f, 0x9e, 0x7c, 0x52, 0x7e, 0x2c, 0x57, 0x69, 0x87, 0x7e, 0x11,
- 0xc0, 0x30, 0x21, 0xeb, 0xfa, 0x0e, 0x5e, 0x90, 0x2c, 0x52, 0xc5, 0xc2,
- 0x98, 0x8d, 0xc8, 0x0b, 0x6f, 0xd8, 0x23, 0xcf, 0x16, 0x29, 0x62, 0xec,
- 0x8b, 0x46, 0xd3, 0x85, 0x17, 0xfc, 0xe2, 0x0b, 0xfe, 0x4c, 0x2d, 0x96,
- 0x2f, 0xdd, 0xf8, 0xb3, 0x65, 0x8b, 0xf9, 0xfd, 0xc7, 0x28, 0x96, 0x2e,
- 0x9d, 0xa4, 0xf6, 0x3e, 0x55, 0x7f, 0xd9, 0x13, 0x67, 0xe7, 0x22, 0x58,
- 0xbf, 0xf3, 0xf7, 0xc1, 0xfe, 0x4e, 0xde, 0x58, 0xbc, 0x11, 0xc3, 0x58,
- 0xa1, 0xa7, 0xd7, 0x8c, 0x3b, 0x96, 0xbc, 0x25, 0xf4, 0x5a, 0x47, 0x21,
- 0x10, 0x2f, 0xbb, 0xfe, 0x6c, 0xb1, 0x7f, 0xf1, 0x9c, 0x7e, 0x44, 0xe3,
- 0xc2, 0x02, 0xc5, 0xe8, 0x13, 0x2c, 0x5f, 0x37, 0xb3, 0x65, 0x8b, 0xa7,
- 0xb5, 0x8b, 0x8a, 0x56, 0x2c, 0x79, 0x3e, 0xdf, 0x8e, 0x11, 0x1f, 0x86,
- 0x2f, 0xec, 0x8b, 0xf2, 0x61, 0x2c, 0x5f, 0xff, 0x34, 0x79, 0x85, 0x3f,
- 0x67, 0xf4, 0xfb, 0x8b, 0x15, 0x28, 0x81, 0x11, 0x7d, 0xfc, 0x42, 0x63,
- 0xcc, 0x7a, 0xc5, 0x4a, 0x7d, 0x63, 0x25, 0x68, 0x59, 0x94, 0x30, 0x7c,
- 0x45, 0x7f, 0x43, 0x8e, 0x5d, 0xc1, 0x62, 0xd8, 0xb1, 0x4b, 0x16, 0x7d,
- 0x17, 0xbd, 0x04, 0x6f, 0xb0, 0x07, 0xe2, 0xc5, 0x4a, 0x25, 0xb7, 0x4c,
- 0xf1, 0x3d, 0xff, 0xc5, 0x91, 0xfb, 0x0b, 0x50, 0xce, 0xfc, 0xb1, 0x7e,
- 0x7e, 0x66, 0x69, 0x62, 0xfe, 0xe0, 0x1b, 0xa6, 0x0d, 0x62, 0xff, 0xff,
- 0xff, 0xa1, 0xfc, 0x2c, 0x37, 0x08, 0x19, 0x86, 0x36, 0x80, 0x7c, 0x68,
- 0x3f, 0x01, 0x80, 0x58, 0xb8, 0x5c, 0xea, 0x8c, 0x2c, 0x30, 0xad, 0x26,
- 0x32, 0x50, 0xe9, 0xbf, 0xfc, 0xed, 0xdf, 0x5e, 0x4e, 0x9a, 0x0f, 0xf5,
- 0x8a, 0xea, 0xc8, 0xdd, 0x8a, 0x33, 0x2d, 0x4a, 0x67, 0xfc, 0xa5, 0x52,
- 0x87, 0x47, 0x0c, 0x3a, 0x46, 0xc6, 0x10, 0xa2, 0xe2, 0xd9, 0x62, 0xf7,
- 0xf3, 0x65, 0x8b, 0x47, 0x2c, 0x5f, 0xf9, 0x8c, 0xde, 0x74, 0xfe, 0xf4,
- 0xac, 0x56, 0x1f, 0x9b, 0x0f, 0x10, 0xad, 0xe8, 0x36, 0x96, 0x2e, 0x9f,
- 0x2c, 0x5f, 0x8e, 0xd0, 0xc1, 0xac, 0x53, 0x9b, 0xf0, 0x0b, 0xde, 0x17,
- 0xf1, 0x62, 0xf9, 0xbb, 0xe4, 0x16, 0x2c, 0x25, 0x8b, 0xce, 0xd0, 0x58,
- 0xbe, 0xfc, 0x97, 0x96, 0x2b, 0xa9, 0xbe, 0xe0, 0xe5, 0xb3, 0x87, 0xe7,
- 0xd1, 0x42, 0xfb, 0x3d, 0x83, 0x48, 0xbf, 0xe6, 0x23, 0x70, 0x9b, 0xdc,
- 0x58, 0xbe, 0x63, 0x40, 0x1a, 0xc5, 0x40, 0xff, 0xfe, 0x44, 0x47, 0x17,
- 0xd2, 0x45, 0x2b, 0x15, 0x12, 0xa2, 0x6d, 0x2e, 0x1c, 0x80, 0x03, 0xa5,
- 0x09, 0x7f, 0x42, 0xa0, 0xc2, 0xeb, 0xf9, 0x83, 0x6f, 0x31, 0xab, 0x17,
- 0xb8, 0x7d, 0x2c, 0x5c, 0xfb, 0xac, 0x50, 0x0d, 0xb7, 0x07, 0xab, 0x15,
- 0xea, 0x1b, 0x08, 0xb7, 0x94, 0xa5, 0xa7, 0x1f, 0x32, 0xde, 0x70, 0xf8,
- 0xb1, 0x7b, 0x8f, 0xd1, 0x62, 0xff, 0xe8, 0x19, 0xc0, 0x60, 0xb7, 0x92,
- 0x02, 0xc5, 0xff, 0xa3, 0x6c, 0x18, 0xbc, 0xfe, 0x9d, 0x2c, 0x5f, 0x3e,
- 0xba, 0xe2, 0xc5, 0xfe, 0x6d, 0x4e, 0xcd, 0xad, 0xd6, 0x28, 0xd3, 0xd9,
- 0xf9, 0x25, 0xf7, 0x70, 0xcf, 0x05, 0x51, 0x81, 0x90, 0x9d, 0xbf, 0xbc,
- 0xfa, 0x91, 0x05, 0xd6, 0x2b, 0xb4, 0xdf, 0x3f, 0x18, 0x39, 0x88, 0x76,
- 0xd4, 0xa7, 0xa8, 0xd1, 0xcd, 0xde, 0xfe, 0x6c, 0xb1, 0x7a, 0x10, 0x95,
- 0x8b, 0xd9, 0xfc, 0xea, 0x6e, 0xc4, 0x3d, 0x5b, 0xaa, 0x8e, 0x68, 0xfc,
- 0x89, 0xa6, 0xe7, 0x12, 0xc5, 0xff, 0x9f, 0x6f, 0x70, 0x51, 0xfe, 0x6f,
- 0xac, 0x54, 0x0f, 0x6f, 0xc2, 0xf7, 0xf3, 0x7b, 0xce, 0x5b, 0x2c, 0x5f,
- 0xfe, 0xcf, 0x3e, 0x17, 0xf3, 0xdf, 0x7d, 0xd6, 0x2b, 0xe7, 0xee, 0x45,
- 0xd7, 0xe9, 0xd7, 0xb2, 0x3d, 0x62, 0xff, 0xbc, 0xe7, 0xe7, 0xe4, 0xc2,
- 0x58, 0xbc, 0x59, 0xe5, 0x8b, 0xf9, 0xf9, 0xc9, 0xfc, 0xac, 0x53, 0x9e,
- 0x49, 0x0e, 0x5f, 0xfc, 0x4f, 0xbf, 0x3f, 0x2f, 0xe7, 0xf2, 0xc5, 0xff,
- 0x49, 0x6e, 0xde, 0x6e, 0xc1, 0xd5, 0x33, 0x3d, 0xc8, 0x7b, 0x2b, 0x78,
- 0x41, 0xe8, 0x82, 0xff, 0xa7, 0x3b, 0xcd, 0x83, 0x6e, 0xd6, 0x2f, 0xf9,
- 0x83, 0xd6, 0x3f, 0xe4, 0x6b, 0x15, 0xa3, 0xf5, 0x23, 0xca, 0x82, 0xae,
- 0x30, 0x47, 0x99, 0xe8, 0x7b, 0x5f, 0xc2, 0x0b, 0xbe, 0xb5, 0x8b, 0x17,
- 0xff, 0xec, 0xee, 0x1e, 0x7d, 0xb3, 0x5e, 0xf3, 0xea, 0x56, 0x2f, 0xf7,
- 0xf0, 0xd6, 0x97, 0x8e, 0x58, 0xbf, 0xd9, 0xcc, 0x8f, 0xfc, 0x8d, 0x62,
- 0xe6, 0x02, 0xc5, 0xd3, 0xb2, 0xc5, 0xef, 0xcc, 0x4b, 0x17, 0xfa, 0x5c,
- 0xb3, 0x63, 0x20, 0xb1, 0x6e, 0xc6, 0x7d, 0x58, 0x31, 0xf1, 0xeb, 0xf3,
- 0x44, 0x4f, 0x12, 0xc5, 0x6e, 0x9a, 0x5f, 0xcd, 0xbc, 0x6c, 0x28, 0x40,
- 0xf4, 0x35, 0xac, 0x4f, 0xd7, 0x91, 0xd1, 0x5f, 0x49, 0xa3, 0xc5, 0x8b,
- 0xef, 0x1b, 0x9f, 0x58, 0xbc, 0x4f, 0x2b, 0x17, 0x6a, 0x0b, 0x17, 0xfe,
- 0x2c, 0xf7, 0x85, 0xb7, 0xb3, 0x75, 0x8b, 0xff, 0xe1, 0xfb, 0x93, 0x01,
- 0xb0, 0x30, 0x6f, 0xc5, 0x8b, 0xe1, 0x36, 0xa0, 0xb1, 0x7f, 0x8b, 0x22,
- 0xfc, 0xeb, 0x65, 0x8b, 0xfe, 0x19, 0x4f, 0x7e, 0x16, 0x69, 0x62, 0xe9,
- 0x37, 0x87, 0xdf, 0xe3, 0x5a, 0x94, 0xc4, 0x06, 0xa0, 0x78, 0x49, 0x5f,
- 0xf1, 0x0b, 0xdf, 0xce, 0x83, 0x95, 0x8b, 0xf9, 0xbb, 0xe6, 0x77, 0xe5,
- 0x8b, 0xb0, 0x35, 0x8a, 0xc4, 0x41, 0x80, 0xec, 0x8c, 0x2f, 0x8f, 0xc3,
- 0x0e, 0xb1, 0x7f, 0x7b, 0x3f, 0x3d, 0xf1, 0x62, 0xa5, 0x10, 0x58, 0x5c,
- 0x22, 0x5b, 0x71, 0x62, 0xc1, 0xac, 0x5c, 0xe0, 0x58, 0xbe, 0x0d, 0x8a,
- 0x0b, 0x17, 0x0d, 0xd6, 0x2e, 0xfb, 0xac, 0x5f, 0x43, 0x9f, 0xc5, 0x8b,
- 0xe7, 0x10, 0x5f, 0x16, 0x2d, 0xce, 0xa8, 0xb1, 0x18, 0xbe, 0xe4, 0x71,
- 0x0b, 0xb0, 0xb8, 0x08, 0xe9, 0xd3, 0x24, 0x14, 0x31, 0x29, 0x93, 0x5e,
- 0x04, 0x66, 0xd7, 0xf7, 0x46, 0xd4, 0x30, 0x6b, 0x17, 0x02, 0x56, 0x2e,
- 0x04, 0xac, 0x5f, 0x43, 0x0a, 0x31, 0xcd, 0x70, 0x05, 0xeb, 0x11, 0x2e,
- 0x25, 0xeb, 0xff, 0xfe, 0xfe, 0x0b, 0x46, 0xf7, 0x0f, 0xe1, 0x1b, 0xf2,
- 0x9c, 0xd2, 0xc5, 0x46, 0x8b, 0xbb, 0x92, 0x47, 0xb1, 0x20, 0xc6, 0xcd,
- 0x18, 0x78, 0xd4, 0x75, 0x19, 0xd0, 0x23, 0x8c, 0x28, 0x60, 0x78, 0x8a,
- 0xfe, 0xd1, 0x9e, 0xe4, 0x02, 0xeb, 0x17, 0xf8, 0x59, 0x14, 0x9e, 0x01,
- 0x75, 0x8b, 0xf6, 0x0e, 0x61, 0x38, 0x7d, 0xc0, 0x35, 0xbe, 0xf0, 0xc7,
- 0x2b, 0x17, 0xff, 0x89, 0xbb, 0xe1, 0xa6, 0xb7, 0x5d, 0xce, 0x05, 0x8b,
- 0xe9, 0xd4, 0xfd, 0x62, 0xe8, 0x76, 0xb1, 0x58, 0x88, 0xc6, 0x51, 0xe1,
- 0x15, 0xff, 0xbd, 0x23, 0xdd, 0xf6, 0xce, 0xfc, 0xb1, 0x7f, 0xd8, 0xfd,
- 0xfb, 0x53, 0x9d, 0xac, 0x5f, 0xfe, 0x27, 0xef, 0x91, 0x16, 0x6d, 0x9d,
- 0xf9, 0x62, 0xff, 0xdf, 0xc3, 0x99, 0x20, 0xce, 0xfc, 0xb1, 0x58, 0x88,
- 0xef, 0x26, 0xdf, 0xee, 0xf7, 0x7d, 0x19, 0x23, 0x58, 0xbc, 0x76, 0x87,
- 0x54, 0xe4, 0x64, 0xb8, 0x90, 0xb9, 0x0c, 0x8f, 0x11, 0x53, 0x2a, 0xa1,
- 0x04, 0xa4, 0x0b, 0x85, 0xe5, 0x8b, 0xa3, 0xa5, 0x62, 0xfe, 0xc0, 0x69,
- 0xe4, 0xeb, 0x17, 0xf0, 0x0e, 0x67, 0x0c, 0xd9, 0x62, 0xff, 0xd2, 0x3f,
- 0xc9, 0x9a, 0xd6, 0x44, 0xb1, 0x7e, 0x72, 0x29, 0xed, 0x62, 0xbe, 0x7d,
- 0x1c, 0x41, 0xbb, 0x3b, 0x58, 0xae, 0xd1, 0xab, 0xe8, 0x4d, 0xc7, 0x11,
- 0x5f, 0xfe, 0x32, 0x43, 0x98, 0xa0, 0xc5, 0x9d, 0xf9, 0x62, 0xf6, 0x9f,
- 0x4b, 0x17, 0xff, 0xfe, 0xcf, 0x4b, 0xc1, 0xb9, 0xc9, 0xd4, 0xc1, 0xf7,
- 0x21, 0x71, 0x62, 0x80, 0x88, 0x8e, 0x0e, 0xd4, 0xaa, 0x90, 0x81, 0x5e,
- 0x0c, 0x7c, 0x69, 0xa3, 0x02, 0xe1, 0xc8, 0x70, 0xd5, 0xbf, 0x8b, 0x3b,
- 0x03, 0xc1, 0x62, 0xf8, 0xd9, 0xf7, 0x16, 0x2f, 0xde, 0xd4, 0xe7, 0x6b,
- 0x14, 0x69, 0xe6, 0xf6, 0x49, 0x7f, 0x73, 0x93, 0x09, 0xd2, 0xc5, 0xff,
- 0x6a, 0x4e, 0xf1, 0x4b, 0x47, 0xac, 0x56, 0x1f, 0x56, 0xe5, 0xd7, 0x85,
- 0xdf, 0x96, 0x2f, 0xd3, 0x0d, 0xb0, 0x35, 0x8a, 0x58, 0xa3, 0x9b, 0x66,
- 0x2a, 0xba, 0x2e, 0x2c, 0x56, 0xc9, 0xdc, 0xc7, 0xbd, 0x94, 0x23, 0xb8,
- 0x45, 0xe5, 0x53, 0x08, 0x2f, 0xef, 0xcb, 0x94, 0x9d, 0x62, 0xff, 0xff,
- 0xb3, 0xd2, 0x5b, 0xe7, 0xbe, 0xfd, 0xfa, 0x40, 0x1e, 0x7d, 0x62, 0xf8,
- 0xb3, 0xbf, 0x4a, 0x25, 0x06, 0x59, 0x76, 0x06, 0xb1, 0x7f, 0xc2, 0x2d,
- 0xff, 0x9b, 0x71, 0xd6, 0x2f, 0xfa, 0x7b, 0xc0, 0x4f, 0x4c, 0xd9, 0x62,
- 0xfe, 0x2c, 0xf7, 0x18, 0x0b, 0x15, 0x28, 0xf5, 0xd1, 0xc9, 0xc6, 0x00,
- 0x77, 0xc3, 0xcb, 0xff, 0xfe, 0x67, 0xf4, 0x1c, 0x79, 0x0f, 0xcb, 0xe8,
- 0x07, 0x68, 0x2c, 0x5f, 0xdb, 0x3e, 0xbb, 0xfe, 0xcb, 0x17, 0xe8, 0x66,
- 0xb3, 0x8b, 0x15, 0xf4, 0x5f, 0x93, 0x2f, 0x8c, 0xaf, 0xf7, 0xc4, 0xc6,
- 0xfa, 0x76, 0x58, 0xbf, 0xb9, 0xac, 0xde, 0x76, 0x58, 0xbf, 0xfd, 0xe7,
- 0xdb, 0x69, 0x2c, 0xf3, 0xf6, 0x1a, 0xc5, 0x6c, 0x7f, 0xb0, 0x30, 0xbe,
- 0x9e, 0xfd, 0x1e, 0xb1, 0x52, 0x79, 0x50, 0x23, 0xbf, 0xff, 0xce, 0x6e,
- 0x17, 0xbf, 0x87, 0x14, 0x18, 0x79, 0xdf, 0x96, 0x2e, 0x2e, 0xd6, 0x2f,
- 0xec, 0x3f, 0x3e, 0xf1, 0x2c, 0x5e, 0x3b, 0x76, 0x69, 0xe3, 0xfc, 0x62,
- 0xff, 0x0e, 0x49, 0xb4, 0xd0, 0x58, 0xac, 0x3e, 0x76, 0x35, 0xbf, 0xfd,
- 0xf9, 0x3f, 0xf3, 0x0b, 0x7c, 0xef, 0xcb, 0x17, 0x79, 0xb4, 0x7d, 0x60,
- 0x20, 0xbf, 0xe0, 0xbe, 0xa7, 0xcf, 0xbb, 0x8d, 0x62, 0xff, 0xfe, 0x68,
- 0x61, 0x66, 0x9c, 0xd8, 0xee, 0x34, 0x24, 0xeb, 0x17, 0xfb, 0x0b, 0x6c,
- 0x1b, 0x7d, 0x62, 0xa2, 0x55, 0x2f, 0xf2, 0x1f, 0x46, 0xf6, 0x22, 0xde,
- 0x87, 0xc1, 0xae, 0xdc, 0x0c, 0x58, 0xbf, 0xfb, 0x03, 0xc8, 0xfe, 0xad,
- 0xe9, 0xe4, 0xac, 0x5f, 0xed, 0xfe, 0xff, 0x26, 0x3a, 0xc5, 0xf8, 0xf8,
- 0x37, 0x0d, 0x62, 0xef, 0x6c, 0xb1, 0x7d, 0xde, 0xef, 0xa5, 0x8b, 0x4c,
- 0x0d, 0xf7, 0x86, 0x6b, 0x11, 0x1a, 0x4c, 0xf7, 0x1e, 0x56, 0x2f, 0xfa,
- 0x4d, 0xef, 0xda, 0x9c, 0x0d, 0x62, 0xff, 0xd9, 0xd3, 0xef, 0xdc, 0x3d,
- 0x21, 0xac, 0x5f, 0xb4, 0xc5, 0x0e, 0x2c, 0x5f, 0xfb, 0x99, 0xb7, 0x07,
- 0xa2, 0x60, 0xd6, 0x2b, 0x47, 0xd3, 0xe2, 0x8a, 0x82, 0x61, 0x5f, 0x3c,
- 0xe4, 0x2b, 0x2b, 0x4a, 0x8e, 0x4f, 0x0c, 0x16, 0x21, 0xf4, 0x64, 0x37,
- 0x7b, 0x8b, 0x17, 0xff, 0xdb, 0x4c, 0x50, 0x9f, 0x19, 0x9a, 0x66, 0x1a,
- 0xc5, 0xfe, 0x87, 0x51, 0xbf, 0x49, 0x1a, 0xc5, 0x62, 0x22, 0x99, 0x4a,
- 0xff, 0xe1, 0xce, 0xfd, 0xc3, 0x3d, 0xb6, 0x06, 0xb1, 0x7e, 0x8a, 0x0d,
- 0xad, 0x96, 0x2b, 0x73, 0xf4, 0x3a, 0x4d, 0xfb, 0x22, 0xfb, 0xf9, 0x62,
- 0xff, 0x7e, 0x5b, 0xcd, 0xd8, 0x16, 0x2f, 0xff, 0x98, 0xd8, 0xa7, 0x3d,
- 0x27, 0x9f, 0xc8, 0x16, 0x2a, 0x08, 0x84, 0x23, 0x4b, 0x98, 0xeb, 0x17,
- 0xff, 0xc5, 0x21, 0x1f, 0x59, 0xdc, 0x3d, 0x85, 0xba, 0xc5, 0x0c, 0xfa,
- 0x7c, 0x2f, 0x7f, 0xff, 0x0f, 0xef, 0x1b, 0x19, 0xe7, 0xe1, 0x67, 0x47,
- 0xf8, 0x96, 0x2b, 0x13, 0x10, 0x78, 0x45, 0x88, 0x8a, 0xb1, 0x50, 0xa1,
- 0x11, 0xf2, 0x3b, 0xdb, 0xec, 0xcf, 0xf1, 0x62, 0xa5, 0x95, 0x56, 0x32,
- 0xfc, 0x97, 0x29, 0xdb, 0x1e, 0x85, 0xda, 0x54, 0x10, 0x5d, 0x24, 0xa1,
- 0x45, 0xe9, 0x55, 0x21, 0x0d, 0xaf, 0x06, 0x18, 0x69, 0x17, 0xec, 0x34,
- 0x85, 0xc4, 0x88, 0xc3, 0x43, 0x78, 0xed, 0xe5, 0x8b, 0xe8, 0xc0, 0xc3,
- 0x0d, 0x62, 0xec, 0x02, 0xc5, 0x61, 0xe0, 0xf8, 0xaa, 0xf4, 0x83, 0x8b,
- 0x15, 0x28, 0xd8, 0x39, 0xe7, 0x97, 0x8c, 0x21, 0xbe, 0xd4, 0x9c, 0x0b,
- 0x17, 0xff, 0xde, 0xe3, 0xfd, 0x9f, 0xcf, 0xa6, 0xda, 0x56, 0x2f, 0xf1,
- 0xda, 0x0c, 0x6f, 0xdd, 0x62, 0xf9, 0xe0, 0xdc, 0xea, 0x88, 0x33, 0xa7,
- 0xdf, 0x8e, 0xde, 0x14, 0xac, 0x5f, 0xfe, 0xce, 0x8f, 0xf1, 0x7d, 0xf8,
- 0x58, 0x75, 0x8a, 0x93, 0xf3, 0x22, 0x8b, 0xfb, 0x69, 0x3e, 0xc6, 0x06,
- 0xb1, 0x7c, 0xfa, 0x07, 0x16, 0x2f, 0xfc, 0x20, 0xbe, 0x47, 0x16, 0x06,
- 0xc0, 0x58, 0xbf, 0xff, 0x3c, 0xf4, 0x93, 0x0f, 0xcf, 0x86, 0xcd, 0xd8,
- 0x6b, 0x17, 0xfa, 0x61, 0x3a, 0xd6, 0x06, 0xb1, 0x69, 0xd2, 0x23, 0xc0,
- 0xb7, 0x7f, 0xfd, 0x3c, 0x1f, 0xdc, 0x3f, 0x9c, 0x5e, 0x14, 0xac, 0x5f,
- 0xe2, 0xc3, 0x7a, 0xbf, 0x47, 0x58, 0xad, 0x91, 0x63, 0xb9, 0x47, 0x94,
- 0xaa, 0x53, 0xb8, 0x78, 0xe1, 0xaf, 0x8b, 0x3b, 0xf2, 0xc5, 0xff, 0xfd,
- 0xee, 0x39, 0x77, 0x0f, 0xcb, 0x8e, 0x7f, 0x30, 0x58, 0xbb, 0x61, 0xac,
- 0x5f, 0xd2, 0x2f, 0x13, 0xf4, 0x58, 0xae, 0xa7, 0x91, 0xa1, 0x9a, 0x74,
- 0x63, 0xf2, 0x14, 0x77, 0xfe, 0x2c, 0xe6, 0xff, 0x7d, 0xe4, 0x96, 0x2f,
- 0xff, 0xf1, 0xa1, 0xb6, 0x8d, 0x8c, 0xe6, 0x40, 0x84, 0xdc, 0xc2, 0x58,
+ 0xd7, 0x3a, 0xf0, 0x67, 0x58, 0xbf, 0x67, 0x67, 0x21, 0xac, 0x50, 0xcf,
+ 0xc8, 0x92, 0x6e, 0x68, 0x4a, 0x2a, 0xb9, 0x08, 0x9b, 0x6b, 0x13, 0x3d,
+ 0x34, 0xbb, 0x50, 0xdd, 0xbd, 0x9b, 0x09, 0x62, 0xf9, 0x88, 0xa5, 0x62,
+ 0xe1, 0x1a, 0x46, 0xf8, 0x21, 0xea, 0x95, 0x42, 0x99, 0x1b, 0x67, 0xde,
+ 0xae, 0xfe, 0xeb, 0x17, 0xda, 0x03, 0xc1, 0x62, 0xfc, 0xde, 0xd4, 0xc1,
+ 0x62, 0xff, 0xbc, 0xe4, 0xdd, 0x78, 0x52, 0xb1, 0x7c, 0x5e, 0x17, 0xe5,
+ 0x10, 0x9f, 0x23, 0x0c, 0xa2, 0xff, 0xf8, 0xff, 0x7e, 0x41, 0xfc, 0x1e,
+ 0xa7, 0xf2, 0xb1, 0x7b, 0xe2, 0x8f, 0x58, 0xbf, 0xfa, 0x76, 0xe7, 0xd8,
+ 0x38, 0x6a, 0x7a, 0x58, 0xbf, 0xf3, 0x97, 0xb8, 0xe3, 0x07, 0x40, 0x58,
+ 0xbf, 0xfe, 0xfb, 0xe7, 0x6c, 0xe3, 0x41, 0xca, 0x7b, 0x2c, 0x5f, 0xf6,
+ 0xef, 0x81, 0x06, 0x36, 0xd9, 0x62, 0xdc, 0x58, 0xae, 0x8f, 0x3e, 0x23,
+ 0xda, 0xe2, 0x31, 0x3d, 0x0a, 0x0b, 0xff, 0xec, 0xec, 0xfe, 0x80, 0x86,
+ 0xc4, 0x0c, 0x25, 0x8b, 0xf7, 0xdc, 0x01, 0xf9, 0x62, 0xec, 0x23, 0x0f,
+ 0xeb, 0x75, 0x0b, 0x37, 0x11, 0xa1, 0xda, 0x14, 0x55, 0xb2, 0xa0, 0x3d,
+ 0x47, 0xa9, 0x51, 0xbb, 0x32, 0xb6, 0x67, 0x51, 0xe1, 0x2d, 0x8f, 0x0d,
+ 0x9e, 0x13, 0xac, 0x8f, 0xdf, 0xa8, 0xf0, 0x84, 0x52, 0x92, 0xef, 0x61,
+ 0x1a, 0xb1, 0x7f, 0x98, 0x7f, 0xcc, 0xeb, 0xcb, 0x15, 0x87, 0xa2, 0x68,
+ 0xed, 0x74, 0xd9, 0x43, 0xfe, 0x1a, 0x44, 0xfd, 0xc9, 0x60, 0x7e, 0xa6,
+ 0x8f, 0x77, 0x43, 0xd2, 0xe8, 0x1d, 0x62, 0xf0, 0x59, 0xf5, 0x8b, 0xa4,
+ 0xa0, 0x6d, 0xbc, 0x31, 0x78, 0xa4, 0x25, 0x8b, 0xe7, 0xdd, 0xc6, 0xb1,
+ 0x78, 0x38, 0x1d, 0x62, 0xa0, 0x88, 0xac, 0x2b, 0xf0, 0xe8, 0x88, 0xef,
+ 0xff, 0xf7, 0x37, 0xfb, 0xf5, 0xed, 0xff, 0x3b, 0x67, 0x5e, 0x61, 0xac,
+ 0x5f, 0xfd, 0xe9, 0x72, 0xf6, 0xa7, 0xcd, 0xe5, 0x8a, 0x94, 0x55, 0x74,
+ 0xcf, 0x7b, 0xcf, 0x12, 0xc5, 0xfc, 0x0f, 0x7a, 0x48, 0x0b, 0x15, 0x27,
+ 0x98, 0xc3, 0xd7, 0x02, 0x56, 0x2f, 0xcc, 0x18, 0x98, 0x35, 0x8a, 0x01,
+ 0xe0, 0x88, 0x5e, 0xa2, 0x44, 0x1e, 0x98, 0x6f, 0x36, 0x41, 0x62, 0xe6,
+ 0x25, 0x8b, 0x62, 0xc5, 0x7c, 0xd3, 0xf6, 0x16, 0xac, 0x44, 0x53, 0x92,
+ 0x32, 0x1d, 0xff, 0xcd, 0x03, 0x33, 0xd9, 0xf9, 0xd0, 0x16, 0x2e, 0x00,
+ 0x16, 0x2f, 0xfb, 0x7f, 0xbe, 0x89, 0xfd, 0xc5, 0x8b, 0xec, 0xd8, 0x5e,
+ 0x58, 0xa8, 0x22, 0xec, 0xe8, 0xa0, 0x18, 0xf1, 0xd5, 0xff, 0xc1, 0x10,
+ 0x9b, 0x8f, 0x9d, 0x9b, 0x4b, 0x17, 0xfd, 0xa9, 0xec, 0xfe, 0xe6, 0x1a,
+ 0xb1, 0x58, 0x88, 0x28, 0xf4, 0x6b, 0xf9, 0xff, 0xfc, 0x03, 0x2c, 0x5e,
+ 0x6f, 0xf1, 0x62, 0xa4, 0xfb, 0xc0, 0x4a, 0x22, 0xdb, 0xff, 0xbb, 0x6b,
+ 0x07, 0x2e, 0x2d, 0xe7, 0x4b, 0x17, 0xe9, 0xf7, 0x33, 0xcb, 0x17, 0xff,
+ 0xf8, 0x6e, 0x5b, 0xe7, 0x5e, 0x35, 0xb3, 0x5e, 0xf4, 0xec, 0xb1, 0x52,
+ 0x8d, 0x31, 0xa3, 0xb9, 0x45, 0xfd, 0xc8, 0xbe, 0xe1, 0x79, 0x62, 0xff,
+ 0x71, 0xf0, 0xb3, 0xa0, 0x96, 0x2f, 0xff, 0xf6, 0x7b, 0xcd, 0xa2, 0x9e,
+ 0xa0, 0x1e, 0x80, 0x77, 0xe2, 0xc5, 0x62, 0x32, 0x23, 0xcc, 0x4e, 0x69,
+ 0x7e, 0x17, 0x5b, 0xe1, 0xd6, 0x2f, 0xf3, 0x85, 0x84, 0x3f, 0xca, 0xc5,
+ 0xf3, 0x74, 0x43, 0x58, 0xa3, 0x9e, 0xb0, 0x0c, 0xef, 0xff, 0x4f, 0xb8,
+ 0x2d, 0xcc, 0xfb, 0x14, 0xca, 0xc5, 0x84, 0xb1, 0x7e, 0x00, 0x60, 0x68,
+ 0x2c, 0x57, 0xcd, 0xe3, 0x09, 0x5f, 0x47, 0x99, 0x1f, 0x05, 0x8b, 0xff,
+ 0xc4, 0x3f, 0xe7, 0x41, 0xb1, 0x78, 0x86, 0xb1, 0x68, 0x49, 0xfb, 0x39,
+ 0x5d, 0xff, 0xfc, 0xe1, 0x7d, 0xb7, 0x92, 0x1e, 0x75, 0xef, 0xb0, 0xd6,
+ 0x2f, 0xfb, 0x6f, 0x43, 0x23, 0xd8, 0x80, 0xb1, 0x7d, 0x17, 0xdb, 0xcb,
+ 0x15, 0x87, 0xc2, 0xe7, 0xb7, 0xe9, 0x6f, 0xb4, 0x7a, 0xc5, 0xf6, 0x75,
+ 0x9c, 0x58, 0xbb, 0x07, 0xa3, 0xcd, 0xf9, 0x55, 0xe7, 0x0a, 0x3d, 0x62,
+ 0xff, 0x67, 0x6e, 0x7b, 0xd2, 0x75, 0x8a, 0xd1, 0xeb, 0xfc, 0x86, 0xff,
+ 0x78, 0x65, 0x21, 0x37, 0x4b, 0x15, 0x2b, 0x83, 0xc3, 0x32, 0xc8, 0x40,
+ 0x9a, 0x44, 0xf0, 0x87, 0x8a, 0x12, 0xda, 0x26, 0xfc, 0x2f, 0x89, 0xb7,
+ 0x90, 0x84, 0x0c, 0x8a, 0xff, 0xd0, 0x72, 0x80, 0x7f, 0xfc, 0x8d, 0x62,
+ 0xe0, 0x9d, 0x62, 0xf6, 0x16, 0xeb, 0x17, 0x49, 0xd6, 0x2c, 0x7d, 0xcd,
+ 0xa4, 0x70, 0xed, 0x49, 0xfb, 0xba, 0x65, 0xff, 0x60, 0xcd, 0x68, 0xbf,
+ 0x3b, 0x2c, 0x5f, 0x85, 0xed, 0xb8, 0x6a, 0xc5, 0xff, 0xcd, 0xb7, 0x18,
+ 0x73, 0xb4, 0xc2, 0x56, 0x2f, 0xf3, 0x96, 0xdf, 0x90, 0xc9, 0x62, 0xfe,
+ 0xce, 0x47, 0x66, 0xa5, 0x62, 0xba, 0x4f, 0xa3, 0x50, 0xb7, 0xf9, 0x01,
+ 0x1e, 0x70, 0xb3, 0xc8, 0xb1, 0xc6, 0x97, 0xfd, 0x21, 0xfd, 0xba, 0xf7,
+ 0xe5, 0x62, 0xf9, 0xe4, 0xa2, 0x58, 0xbc, 0x1c, 0xc7, 0xac, 0x5f, 0x3f,
+ 0x04, 0x75, 0x8b, 0x82, 0x09, 0x62, 0xfa, 0x4f, 0x31, 0x90, 0x37, 0xa1,
+ 0x11, 0xd4, 0xba, 0x6b, 0x1d, 0x8a, 0xa1, 0x18, 0x58, 0xe3, 0x15, 0xc8,
+ 0x62, 0xef, 0x0c, 0x5e, 0x89, 0xde, 0xb2, 0xf2, 0x8a, 0x33, 0x9d, 0x43,
+ 0x98, 0xf1, 0xbe, 0x34, 0x3a, 0x01, 0x19, 0x71, 0x46, 0x03, 0xc9, 0xd1,
+ 0x4f, 0x4a, 0x9b, 0xec, 0xda, 0x11, 0xdc, 0x71, 0x17, 0x72, 0xf5, 0xfe,
+ 0xe7, 0x30, 0x81, 0x1d, 0x8b, 0x17, 0xc4, 0xfd, 0xd2, 0xb1, 0x68, 0xe5,
+ 0x8b, 0x81, 0x2b, 0x17, 0x8b, 0x38, 0xb1, 0x44, 0x6c, 0xc3, 0x17, 0xb4,
+ 0x4b, 0x17, 0xf7, 0x30, 0x81, 0x1d, 0x8b, 0x16, 0x35, 0x62, 0xf4, 0x6d,
+ 0x24, 0xb1, 0x46, 0x26, 0x75, 0x86, 0xce, 0x48, 0xc9, 0x00, 0x21, 0xe0,
+ 0x98, 0x8c, 0x02, 0x13, 0xbe, 0xf3, 0x31, 0x2c, 0x57, 0x64, 0x49, 0x04,
+ 0xe3, 0x78, 0x2f, 0xc1, 0x62, 0xff, 0xdf, 0x68, 0x16, 0x7b, 0xd2, 0x75,
+ 0x8b, 0xff, 0xc3, 0xfc, 0x9d, 0x98, 0xba, 0xe0, 0x8e, 0xb1, 0x7f, 0xed,
+ 0xf3, 0x5a, 0x98, 0x72, 0x40, 0xb1, 0x7f, 0xcd, 0xbc, 0x0f, 0xfe, 0x9a,
+ 0x3d, 0x62, 0xa0, 0x98, 0x41, 0xa7, 0xc2, 0x4b, 0xec, 0x81, 0x7f, 0x4c,
+ 0x3d, 0x1d, 0x9f, 0x58, 0xbf, 0xc0, 0x60, 0x4c, 0x7c, 0xc1, 0x62, 0xfe,
+ 0xc9, 0xea, 0x0e, 0x75, 0x8b, 0xf9, 0xbf, 0xf9, 0xeb, 0x8b, 0x17, 0xa0,
+ 0xf9, 0xa3, 0xdd, 0xf9, 0x75, 0xfe, 0xfe, 0x0c, 0xa7, 0x09, 0x62, 0xa0,
+ 0x8f, 0x6e, 0xa1, 0x26, 0x03, 0x2b, 0xb0, 0x96, 0x2f, 0x69, 0xb7, 0x58,
+ 0xb3, 0x2c, 0x50, 0xcf, 0x14, 0xd1, 0x6e, 0x0f, 0x5f, 0xfd, 0xb4, 0x50,
+ 0x9d, 0x6d, 0xfe, 0x9a, 0x3d, 0x62, 0xfc, 0x23, 0xce, 0x79, 0x62, 0xfb,
+ 0x01, 0x20, 0x58, 0xa0, 0x1e, 0x51, 0x14, 0x56, 0xc8, 0xe8, 0x63, 0x0f,
+ 0x42, 0x5e, 0xa5, 0x70, 0x9f, 0x23, 0x27, 0x74, 0x16, 0x8c, 0x9c, 0x51,
+ 0xb1, 0xdc, 0x46, 0xac, 0x5f, 0xfe, 0x2d, 0x8c, 0x89, 0xcb, 0x07, 0x84,
+ 0x6a, 0xc5, 0xff, 0x08, 0x41, 0x93, 0x98, 0x0f, 0x2c, 0x5f, 0x7b, 0x8d,
+ 0xc5, 0x8b, 0x47, 0x2c, 0x5e, 0xfc, 0xc2, 0x4d, 0xc7, 0x08, 0xee, 0x04,
+ 0xac, 0x5f, 0xf0, 0x72, 0x38, 0xa1, 0x25, 0xe5, 0x8a, 0x88, 0xf4, 0xb8,
+ 0x2f, 0x7f, 0xdd, 0xa7, 0xa8, 0xe9, 0xd6, 0x12, 0xc5, 0xec, 0x7f, 0xac,
+ 0x54, 0x6c, 0x7f, 0xb8, 0x47, 0xf3, 0xeb, 0xf9, 0xfa, 0xee, 0xfc, 0xf9,
+ 0x62, 0xfc, 0x2e, 0x3b, 0xf4, 0xb1, 0x7f, 0x85, 0xd7, 0x76, 0xff, 0x6e,
+ 0x2c, 0x5f, 0x67, 0xbe, 0xeb, 0x14, 0xc7, 0xb8, 0x47, 0x57, 0x83, 0xc9,
+ 0x58, 0xb8, 0x46, 0xac, 0x5f, 0xa4, 0x88, 0x47, 0x58, 0xaf, 0x9e, 0x00,
+ 0x63, 0x37, 0xbd, 0x21, 0xac, 0x5f, 0xec, 0x1e, 0x9b, 0x7f, 0x01, 0x62,
+ 0xfd, 0x84, 0x3f, 0xca, 0xc5, 0x61, 0xfd, 0x7c, 0x78, 0x23, 0x5b, 0xb3,
+ 0x8b, 0x14, 0xb1, 0x4b, 0x16, 0x84, 0x45, 0xc7, 0x83, 0x2a, 0x07, 0xac,
+ 0x02, 0xfb, 0xfb, 0x7f, 0xcf, 0x84, 0x1a, 0xc5, 0x4a, 0xe4, 0xe6, 0xc9,
+ 0x90, 0x74, 0x36, 0x30, 0x08, 0xf3, 0x38, 0x8c, 0xb5, 0x08, 0x56, 0x20,
+ 0x25, 0xde, 0x42, 0x77, 0xd0, 0x85, 0x0c, 0x8a, 0xf8, 0x7a, 0x68, 0x2c,
+ 0x5f, 0xff, 0xc4, 0xde, 0xe6, 0x68, 0x00, 0x9c, 0xeb, 0xdc, 0x75, 0x8b,
+ 0xff, 0xff, 0xfb, 0x3d, 0xc0, 0xf9, 0xa6, 0x2f, 0x7d, 0xa0, 0x3d, 0x63,
+ 0x9b, 0x9d, 0x7b, 0x8e, 0xb1, 0x58, 0x8e, 0x63, 0xad, 0xdd, 0x09, 0x58,
+ 0xb4, 0x72, 0xc5, 0x18, 0x6b, 0x30, 0x5e, 0x86, 0x7d, 0xfe, 0x4e, 0xa9,
+ 0x4e, 0x69, 0xa3, 0x78, 0xbc, 0x39, 0x25, 0x8a, 0x32, 0x10, 0x07, 0xb1,
+ 0xba, 0x0c, 0xd7, 0x59, 0x7b, 0x47, 0x82, 0x38, 0x7a, 0x65, 0x68, 0x0e,
+ 0x6c, 0x69, 0x5b, 0xce, 0xde, 0x75, 0x08, 0xe7, 0xa6, 0xb3, 0x7e, 0x5b,
+ 0x0b, 0x5a, 0x6e, 0x70, 0x4b, 0x38, 0x29, 0xc4, 0xdf, 0x2d, 0x8a, 0x72,
+ 0xd0, 0x29, 0x4b, 0x61, 0x94, 0x5f, 0x0c, 0x62, 0x25, 0x8b, 0xb6, 0xec,
+ 0xb1, 0x76, 0x7d, 0x62, 0xba, 0x36, 0x5e, 0x1b, 0xbf, 0x08, 0xd7, 0x9d,
+ 0x96, 0x2f, 0xff, 0x4c, 0x04, 0x3c, 0x6e, 0x73, 0x21, 0x2b, 0x17, 0xfb,
+ 0x7f, 0xb1, 0x48, 0xba, 0x58, 0xbf, 0x08, 0x36, 0x9e, 0x96, 0x2f, 0xdb,
+ 0xfe, 0x7a, 0xee, 0x58, 0xbd, 0x2f, 0x1e, 0xb1, 0x70, 0xbb, 0xf5, 0x8b,
+ 0xf7, 0xdb, 0x47, 0x75, 0x8b, 0xc1, 0xcc, 0x7a, 0xc5, 0xfc, 0x1e, 0xff,
+ 0x9e, 0xbb, 0x96, 0x28, 0xc4, 0x74, 0x77, 0x85, 0xd0, 0x1f, 0xdc, 0x77,
+ 0x85, 0x02, 0x21, 0xbc, 0xe5, 0x8b, 0x17, 0xf7, 0xdf, 0xbf, 0xfc, 0xec,
+ 0xb1, 0x61, 0xc0, 0xf3, 0xf7, 0x1b, 0xbe, 0x93, 0xb7, 0x16, 0x2e, 0x00,
+ 0x4b, 0x17, 0xf7, 0xe5, 0xe3, 0xce, 0xeb, 0x17, 0xfa, 0x3c, 0x5a, 0xfc,
+ 0xb8, 0xd6, 0x28, 0xc4, 0x40, 0x6e, 0x32, 0xe6, 0x15, 0xb2, 0xb6, 0x38,
+ 0x15, 0x0d, 0x27, 0x73, 0x5e, 0xa3, 0x12, 0x78, 0x56, 0xfc, 0xa7, 0xd0,
+ 0xa2, 0xbf, 0xee, 0xee, 0x0f, 0xf3, 0xa6, 0x25, 0x8b, 0x83, 0xee, 0x58,
+ 0xbf, 0xb0, 0x2c, 0xc2, 0x35, 0x62, 0xff, 0x33, 0xc3, 0xf9, 0xe9, 0x58,
+ 0xb9, 0xf6, 0x58, 0xf9, 0xb2, 0xba, 0x43, 0x58, 0xbc, 0xd9, 0xc5, 0x8b,
+ 0xf3, 0x6c, 0xe2, 0x82, 0xc5, 0xe0, 0x02, 0x56, 0x2a, 0x07, 0xf4, 0x71,
+ 0x8f, 0x8e, 0x11, 0x4d, 0xec, 0x23, 0x56, 0x2a, 0x53, 0xb2, 0xd8, 0xf1,
+ 0xc7, 0x0e, 0xc0, 0xd0, 0xa2, 0xee, 0x3b, 0xbf, 0xf7, 0x35, 0x3e, 0x26,
+ 0x39, 0xdd, 0x62, 0xff, 0xf4, 0xf3, 0x92, 0x7c, 0xf3, 0xf3, 0xec, 0xb1,
+ 0x79, 0xcb, 0xcb, 0x15, 0xb9, 0xf2, 0xfd, 0x26, 0xff, 0xdf, 0x7f, 0xce,
+ 0x6a, 0x1a, 0x82, 0xc5, 0xff, 0xc7, 0x9f, 0x71, 0xb3, 0x40, 0x3e, 0x2c,
+ 0x5f, 0xc5, 0x30, 0x3c, 0xba, 0xc5, 0x00, 0xfc, 0x09, 0x12, 0xfd, 0xf9,
+ 0xda, 0x7e, 0xb1, 0x7d, 0x3b, 0x3e, 0x96, 0x2f, 0xda, 0x63, 0xce, 0xeb,
+ 0x17, 0xff, 0xdb, 0x6b, 0x25, 0xcb, 0x05, 0xbb, 0x10, 0xd6, 0x2f, 0xbb,
+ 0x16, 0x71, 0x62, 0xa4, 0xfc, 0xf1, 0x3e, 0xf7, 0x6c, 0x1a, 0xc5, 0xfe,
+ 0xf3, 0xf6, 0x7f, 0x42, 0x52, 0x2c, 0x75, 0x8b, 0xe3, 0x75, 0x31, 0x8e,
+ 0x78, 0xe1, 0x9a, 0xdb, 0x06, 0x8a, 0x32, 0x66, 0xbb, 0x0d, 0x58, 0xa3,
+ 0x15, 0xc0, 0x64, 0x28, 0xf7, 0x23, 0x78, 0x57, 0xc4, 0x43, 0xf2, 0x96,
+ 0x23, 0x28, 0x4e, 0x72, 0x18, 0x71, 0xc4, 0xf7, 0xff, 0x9b, 0xb4, 0xe0,
+ 0xda, 0x19, 0xf7, 0x09, 0x62, 0xfb, 0x66, 0xd6, 0xeb, 0x17, 0x75, 0x05,
+ 0x8a, 0x93, 0x7c, 0x22, 0x5b, 0xd2, 0x52, 0xb1, 0x7c, 0xc3, 0x98, 0xf5,
+ 0x8b, 0xda, 0x6e, 0xcb, 0x17, 0xe1, 0xeb, 0x59, 0xc5, 0x8b, 0xb3, 0x4b,
+ 0x15, 0x03, 0xdf, 0x61, 0xf0, 0x14, 0xd4, 0x13, 0x76, 0xd4, 0x22, 0x4e,
+ 0x40, 0x01, 0xb2, 0x84, 0x25, 0xfe, 0x28, 0x16, 0x1e, 0x77, 0x58, 0xbd,
+ 0x13, 0x79, 0x62, 0xf1, 0x49, 0xd6, 0x2a, 0x4d, 0xd4, 0x43, 0xd7, 0xe7,
+ 0xf9, 0x4c, 0x16, 0x2d, 0xde, 0x2c, 0x5f, 0x81, 0xf9, 0xcd, 0x2c, 0x54,
+ 0x46, 0xff, 0x42, 0xf7, 0xda, 0x67, 0xd9, 0x62, 0xee, 0x3a, 0xc5, 0x49,
+ 0xee, 0x39, 0x13, 0x11, 0xdb, 0x16, 0x2f, 0x66, 0x1a, 0xb1, 0x43, 0x35,
+ 0xdd, 0xc2, 0x37, 0x89, 0xa0, 0xb1, 0x47, 0x3c, 0x0f, 0x92, 0x5f, 0xf0,
+ 0x7a, 0xf4, 0x1c, 0xbd, 0xc5, 0x8b, 0xff, 0x44, 0x63, 0x75, 0x09, 0x3c,
+ 0xf4, 0xb1, 0x5c, 0x3f, 0xe0, 0xce, 0xea, 0x55, 0x80, 0xe2, 0xa3, 0xb6,
+ 0xe8, 0x87, 0xf0, 0xc2, 0x68, 0x4d, 0x0a, 0x14, 0x17, 0xed, 0x6e, 0xcd,
+ 0xba, 0xa5, 0x0d, 0x2f, 0xee, 0x66, 0x87, 0xfc, 0x58, 0xb7, 0x6c, 0x3e,
+ 0x5e, 0x1b, 0xde, 0x13, 0x71, 0x62, 0x9c, 0xf1, 0xbe, 0x53, 0x7a, 0x38,
+ 0x5e, 0x58, 0xb9, 0xfb, 0x2c, 0x5f, 0xfb, 0x7f, 0xc9, 0x37, 0xb9, 0x9b,
+ 0x2c, 0x5f, 0x69, 0xe2, 0xe2, 0xc5, 0xed, 0x30, 0x6b, 0x15, 0x88, 0x82,
+ 0xd2, 0x03, 0x12, 0x5d, 0x86, 0xac, 0x5f, 0xfd, 0x27, 0x71, 0xe1, 0x1b,
+ 0xf9, 0x3a, 0xc5, 0x7c, 0xf7, 0x3c, 0x31, 0x7d, 0x87, 0x90, 0xd6, 0x28,
+ 0x69, 0xd6, 0x6e, 0x42, 0x72, 0x1e, 0x42, 0x6f, 0xd0, 0x8a, 0xec, 0x45,
+ 0x70, 0x7f, 0x58, 0xbf, 0x13, 0x04, 0x19, 0xd6, 0x2f, 0xff, 0xf0, 0xb3,
+ 0xf8, 0x40, 0xc2, 0xf7, 0xf1, 0xbc, 0x29, 0x58, 0xbe, 0x6e, 0xbd, 0x8b,
+ 0x16, 0xe9, 0x62, 0xcf, 0x12, 0x2f, 0x88, 0xab, 0x8b, 0xc1, 0x11, 0xd1,
+ 0xa9, 0x8d, 0x7e, 0x1a, 0xf7, 0xff, 0xbd, 0xf9, 0xe4, 0xfe, 0x5f, 0x69,
+ 0x35, 0x62, 0xe1, 0x77, 0x2c, 0x5f, 0xf0, 0xd8, 0xed, 0x09, 0x7d, 0xd6,
+ 0x29, 0xd1, 0x3e, 0x04, 0xb2, 0x1b, 0xbf, 0xa6, 0x28, 0x3e, 0xa0, 0xb1,
+ 0x6d, 0xd6, 0x2b, 0xe7, 0x85, 0xe2, 0xfb, 0x8f, 0x2b, 0x17, 0xbc, 0x52,
+ 0xb1, 0x7d, 0x11, 0x49, 0xd6, 0x2b, 0x0f, 0x5b, 0x42, 0xe4, 0x39, 0x7f,
+ 0xbc, 0xe1, 0x44, 0x4c, 0x12, 0xc5, 0xdf, 0x75, 0x8b, 0xfe, 0x96, 0x87,
+ 0xe7, 0x66, 0xd9, 0x62, 0xf6, 0x68, 0x0b, 0x17, 0xfd, 0x9d, 0xa4, 0x7f,
+ 0xc7, 0xf2, 0xc5, 0xee, 0x30, 0x16, 0x28, 0x8f, 0x5f, 0xc7, 0x55, 0x1e,
+ 0x8e, 0x63, 0x8b, 0xfc, 0xeb, 0xce, 0x97, 0xf0, 0x83, 0x00, 0x27, 0xa5,
+ 0x8b, 0x9f, 0x65, 0x8b, 0xe3, 0xfb, 0x37, 0x58, 0xbd, 0xa6, 0x82, 0xc5,
+ 0xdd, 0x4a, 0xc5, 0xff, 0x33, 0x75, 0xf7, 0xd9, 0x89, 0x62, 0xdb, 0x49,
+ 0xe8, 0x8c, 0x62, 0xa5, 0x17, 0x58, 0x48, 0xed, 0xd7, 0x05, 0xe5, 0x8b,
+ 0xe8, 0x00, 0xb1, 0x62, 0xff, 0xf0, 0x09, 0x8f, 0xac, 0x9e, 0xa0, 0xe7,
+ 0x58, 0xa9, 0x3e, 0xc1, 0x11, 0x5f, 0xde, 0x26, 0x07, 0x04, 0xb1, 0x73,
+ 0xec, 0xb1, 0x7f, 0xba, 0xe3, 0xf1, 0xfa, 0xf2, 0xc5, 0x4a, 0xe6, 0x18,
+ 0xdc, 0x31, 0xe3, 0xa2, 0xd7, 0x8c, 0x72, 0x24, 0x0d, 0x18, 0xfe, 0x1a,
+ 0x4c, 0x5a, 0x50, 0x85, 0xe1, 0x0f, 0x8b, 0x84, 0x31, 0x7f, 0xff, 0xff,
+ 0x3f, 0xbf, 0x87, 0xf9, 0x67, 0x66, 0xdf, 0xee, 0x1f, 0x9c, 0xb7, 0xcf,
+ 0x7d, 0xd6, 0x2e, 0x9f, 0xac, 0x5f, 0x7b, 0x53, 0xd9, 0x62, 0x86, 0x8c,
+ 0x73, 0xc2, 0x2d, 0x85, 0xef, 0xbd, 0xc1, 0x47, 0xac, 0x5f, 0xba, 0x81,
+ 0xe7, 0xcb, 0x14, 0xe7, 0xa2, 0x22, 0x7b, 0xe9, 0xe8, 0x51, 0xeb, 0x17,
+ 0xff, 0xed, 0xc5, 0xf3, 0x5c, 0xa7, 0xf2, 0x14, 0x96, 0x2c, 0x54, 0x47,
+ 0xfa, 0x44, 0xf7, 0xce, 0x3e, 0xe7, 0x58, 0xa9, 0x4d, 0xab, 0xf0, 0x85,
+ 0x68, 0x4f, 0x04, 0x45, 0x7f, 0x41, 0xcb, 0x0f, 0x2b, 0x17, 0x9f, 0x50,
+ 0x58, 0xb7, 0xe4, 0xf2, 0x60, 0x59, 0x7e, 0xfc, 0x82, 0x3b, 0x16, 0x2f,
+ 0x98, 0x70, 0xd9, 0x62, 0xf7, 0x8d, 0xd9, 0x62, 0xff, 0xb3, 0xdf, 0xc3,
+ 0x93, 0x79, 0x62, 0xfe, 0xec, 0xfa, 0xea, 0x63, 0xd6, 0x2b, 0x64, 0x46,
+ 0x0c, 0x83, 0x0e, 0x2b, 0xe8, 0xe0, 0x28, 0x58, 0x5f, 0xe7, 0xf4, 0xfd,
+ 0x8b, 0xcb, 0x17, 0xf7, 0x69, 0x33, 0xaf, 0x46, 0xcb, 0x15, 0x03, 0xea,
+ 0xc3, 0x2b, 0x88, 0x0b, 0x17, 0xff, 0x3f, 0x04, 0x7e, 0x4f, 0xdf, 0x52,
+ 0xb1, 0x7e, 0x3c, 0xef, 0xb0, 0xd6, 0x2f, 0xa1, 0x27, 0x65, 0x8b, 0xf8,
+ 0x6e, 0x2d, 0x66, 0xeb, 0x17, 0xed, 0x00, 0xef, 0xc5, 0x8b, 0xbd, 0xc3,
+ 0x13, 0x21, 0xef, 0x48, 0x60, 0x2f, 0x88, 0x8c, 0x57, 0xc2, 0x20, 0xcb,
+ 0xea, 0x55, 0x14, 0x0a, 0x3b, 0x2b, 0x71, 0x62, 0xfe, 0x9d, 0xb0, 0x9c,
+ 0xd5, 0xca, 0x26, 0x56, 0x8f, 0x37, 0x82, 0x57, 0xff, 0xe6, 0xe7, 0xd9,
+ 0xfd, 0x01, 0x4b, 0x78, 0x52, 0xb1, 0x7c, 0xfb, 0xc9, 0xd6, 0x2f, 0xfc,
+ 0x4d, 0xf9, 0x04, 0x66, 0xb9, 0xc4, 0x8b, 0xdf, 0xc1, 0xac, 0x54, 0x9e,
+ 0xfb, 0xa1, 0x5e, 0xf4, 0x19, 0x62, 0xd8, 0xb1, 0x52, 0x6b, 0x83, 0x1d,
+ 0xb8, 0x5b, 0x2c, 0x5f, 0xd2, 0x7c, 0xe6, 0xb1, 0x62, 0xb4, 0x78, 0xdf,
+ 0x19, 0xbc, 0x00, 0x4a, 0xc5, 0xff, 0xf7, 0xa7, 0x35, 0x26, 0x31, 0x61,
+ 0xc5, 0xf5, 0x8a, 0x94, 0x47, 0x61, 0x13, 0x0e, 0xdf, 0x70, 0x45, 0xe5,
+ 0x8b, 0xf0, 0x65, 0x0f, 0xe2, 0xc5, 0x39, 0xe6, 0x00, 0x8e, 0xed, 0xb6,
+ 0x58, 0xb0, 0x16, 0x2d, 0x2b, 0x16, 0xc1, 0x9a, 0x3d, 0xc4, 0xaf, 0xbb,
+ 0x9c, 0x8e, 0xb1, 0x5b, 0x2f, 0x97, 0xc0, 0x9c, 0x72, 0xcc, 0xf1, 0xdf,
+ 0xa2, 0x2d, 0x2a, 0x1e, 0x10, 0x5f, 0x4e, 0x28, 0x7a, 0xf9, 0xe4, 0x44,
+ 0x3d, 0x8f, 0x7b, 0x89, 0xef, 0x1e, 0x77, 0x58, 0xbf, 0xf0, 0x39, 0x85,
+ 0x80, 0xe4, 0xc7, 0xac, 0x5f, 0x9a, 0x27, 0xce, 0x2c, 0x5f, 0x72, 0x75,
+ 0x05, 0x8a, 0x30, 0xf2, 0xf8, 0x51, 0x73, 0xf1, 0x62, 0xf7, 0x26, 0x0b,
+ 0x17, 0x03, 0xb2, 0xc5, 0x49, 0xe7, 0x74, 0x2f, 0xc1, 0xda, 0x1a, 0x28,
+ 0x0e, 0xe3, 0x52, 0x9b, 0x6e, 0x0f, 0x34, 0x65, 0x97, 0x9b, 0xf2, 0xb1,
+ 0x7f, 0x87, 0xf9, 0xf7, 0xa4, 0xeb, 0x15, 0xf3, 0xd0, 0x21, 0xcb, 0xcf,
+ 0xa8, 0x2c, 0x5f, 0xff, 0xa2, 0x61, 0xb7, 0xd8, 0xed, 0xe1, 0x72, 0x43,
+ 0x58, 0xb6, 0xcb, 0x15, 0xf4, 0x43, 0xb0, 0xe8, 0x95, 0xef, 0xa4, 0x3e,
+ 0xe1, 0xac, 0x5f, 0x71, 0xfd, 0x2b, 0x17, 0x75, 0x0d, 0x8f, 0x27, 0xa2,
+ 0x7b, 0xcf, 0xd7, 0x16, 0x2b, 0x0f, 0x3d, 0xcc, 0x6b, 0x13, 0x8f, 0x78,
+ 0x54, 0x7e, 0x18, 0xf7, 0xbb, 0x85, 0x1e, 0xb1, 0x68, 0x96, 0x2d, 0x12,
+ 0xc5, 0x6e, 0x79, 0x4e, 0x48, 0x21, 0x3b, 0xd2, 0x7e, 0x2c, 0x5f, 0x6b,
+ 0xd9, 0xf5, 0x8b, 0xce, 0x06, 0x58, 0xbb, 0x37, 0x58, 0xa5, 0x8f, 0x17,
+ 0x15, 0xf3, 0xcf, 0xe1, 0xa5, 0xf4, 0x9d, 0x86, 0xb1, 0x7e, 0x1b, 0xf6,
+ 0x91, 0xac, 0x50, 0xcf, 0x33, 0x44, 0x55, 0x88, 0x90, 0x76, 0xeb, 0xd0,
+ 0x93, 0xac, 0x5e, 0xd9, 0xb6, 0x58, 0xad, 0x8d, 0xe3, 0x0e, 0xde, 0xf6,
+ 0x7d, 0x62, 0xe7, 0x25, 0x8b, 0xed, 0xbc, 0xe6, 0xac, 0x54, 0xaa, 0x24,
+ 0xd8, 0xbd, 0xc7, 0x75, 0x18, 0x13, 0x2e, 0x88, 0x87, 0xb0, 0xe8, 0x62,
+ 0xd7, 0xe8, 0x9b, 0xf3, 0xf5, 0x8b, 0xff, 0x99, 0xf3, 0x93, 0xb6, 0x13,
+ 0x9a, 0xb1, 0x7f, 0x66, 0xb6, 0xdb, 0x00, 0xb1, 0x46, 0x1f, 0x9f, 0x10,
+ 0xee, 0xed, 0x2b, 0x17, 0xf4, 0x80, 0xed, 0x0c, 0x58, 0xa1, 0x9f, 0x49,
+ 0xc8, 0xc8, 0x66, 0xfe, 0x3c, 0xf5, 0xe6, 0xdd, 0x62, 0xe7, 0xd9, 0x62,
+ 0xfc, 0xf0, 0x7e, 0xa0, 0xb1, 0x5a, 0x3f, 0x1f, 0x98, 0x70, 0x62, 0xff,
+ 0xfe, 0x2c, 0xf7, 0xf2, 0x19, 0xbc, 0xef, 0xe2, 0x63, 0xac, 0x54, 0xaa,
+ 0x2e, 0xc8, 0xc1, 0x5e, 0x13, 0xfc, 0x2f, 0xbf, 0xfd, 0xc6, 0xf7, 0xdb,
+ 0x85, 0x9e, 0xc0, 0x2c, 0x5f, 0xd2, 0x07, 0xe6, 0x41, 0x62, 0xff, 0x9e,
+ 0x0f, 0xce, 0xa0, 0xe4, 0xb1, 0x7f, 0x80, 0xf0, 0xd6, 0x9c, 0x25, 0x8a,
+ 0xd1, 0xf7, 0x11, 0xcd, 0xf3, 0x9e, 0x62, 0x58, 0xbf, 0xfb, 0x8f, 0xd1,
+ 0x64, 0x5a, 0x9f, 0x71, 0x62, 0xfd, 0xee, 0x64, 0x9d, 0x62, 0xff, 0xed,
+ 0xff, 0x2f, 0xee, 0x39, 0x75, 0x05, 0x8b, 0xfe, 0x7f, 0x1d, 0xfd, 0xc9,
+ 0x3a, 0xc5, 0xb2, 0x4f, 0xff, 0x64, 0x6b, 0xec, 0xd8, 0x50, 0x58, 0xbe,
+ 0x7d, 0x4e, 0xcb, 0x15, 0x05, 0x50, 0x7b, 0xa4, 0xbc, 0x26, 0xe2, 0x21,
+ 0x01, 0x19, 0x23, 0x7a, 0x14, 0xe1, 0x13, 0x86, 0x49, 0x7d, 0xdd, 0x98,
+ 0x35, 0x8b, 0xf3, 0xf0, 0x58, 0x75, 0x8b, 0xff, 0xb8, 0xdd, 0x39, 0xc5,
+ 0xcf, 0x4f, 0xd6, 0x2f, 0xff, 0x4c, 0x5f, 0x79, 0x2f, 0xb4, 0x6f, 0x1b,
+ 0xf7, 0x8b, 0x17, 0xfe, 0x98, 0x4c, 0x5c, 0xfe, 0x76, 0xe2, 0xc5, 0xfe,
+ 0x9d, 0x31, 0x16, 0x1a, 0xb1, 0x7d, 0x31, 0xaa, 0x35, 0x46, 0xa5, 0x8a,
+ 0xe9, 0x34, 0x88, 0xf4, 0x6e, 0x2c, 0xf9, 0x0b, 0xb8, 0xca, 0xf9, 0xb4,
+ 0xdd, 0x2c, 0x5f, 0xc0, 0xd9, 0xa1, 0x31, 0xeb, 0x17, 0xde, 0x29, 0x02,
+ 0xc5, 0xf8, 0xc9, 0x8a, 0x42, 0x58, 0xb8, 0x01, 0x2c, 0x5e, 0x18, 0xe5,
+ 0x62, 0xe7, 0x25, 0x8a, 0x35, 0x1d, 0xdd, 0x11, 0xb9, 0x91, 0xc8, 0xb8,
+ 0x56, 0x21, 0x90, 0xc7, 0x6f, 0x67, 0x74, 0x16, 0x2a, 0x55, 0xf3, 0xe4,
+ 0x23, 0x37, 0x25, 0x78, 0xdc, 0x1a, 0x34, 0x02, 0x66, 0xba, 0x76, 0x58,
+ 0xbe, 0xd4, 0xe1, 0xd6, 0x2e, 0xc0, 0x96, 0x29, 0x3a, 0x86, 0x0b, 0xfb,
+ 0x81, 0xce, 0xa4, 0xe9, 0xd4, 0x30, 0x52, 0x75, 0x0c, 0x14, 0x9d, 0x43,
+ 0x05, 0x27, 0x50, 0xc1, 0x49, 0xd4, 0x30, 0x54, 0x11, 0x7e, 0xe3, 0x40,
+ 0x3d, 0x10, 0xd4, 0x70, 0xd7, 0x70, 0xd5, 0xdf, 0xc4, 0xea, 0x18, 0x2f,
+ 0xe6, 0x6f, 0x45, 0x27, 0x4e, 0xa1, 0x80, 0xc3, 0x4b, 0x6e, 0xfd, 0x3a,
+ 0x86, 0x0a, 0x4e, 0xa1, 0x82, 0x93, 0xa8, 0x60, 0xa8, 0x1b, 0x47, 0x1a,
+ 0xa4, 0xea, 0x18, 0x29, 0x3a, 0x86, 0x0a, 0x4e, 0xa1, 0x82, 0x93, 0xa8,
+ 0x60, 0xa4, 0xea, 0x18, 0x29, 0x3a, 0x86, 0x0a, 0xd9, 0x13, 0x83, 0x1a,
+ 0x71, 0xa0, 0x0d, 0x70, 0x6b, 0xb0, 0xd5, 0x27, 0x50, 0xc1, 0x49, 0xd4,
+ 0x30, 0x54, 0x0d, 0xa7, 0x06, 0xa9, 0x3a, 0x86, 0x0a, 0x4e, 0xa1, 0x82,
+ 0x93, 0xa8, 0x60, 0xa4, 0xea, 0x18, 0x2a, 0x07, 0xd0, 0x01, 0xaf, 0x0d,
+ 0x77, 0x0d, 0x52, 0x75, 0x0c, 0x14, 0x9d, 0x43, 0x05, 0x27, 0x50, 0xc1,
+ 0x49, 0xd4, 0x30, 0x56, 0xc7, 0xd0, 0x68, 0xd6, 0x86, 0xbe, 0x35, 0x63,
+ 0x53, 0xa8, 0x60, 0xa4, 0xea, 0x18, 0x29, 0x3a, 0x86, 0x0a, 0x4e, 0xa1,
+ 0x82, 0x93, 0xa8, 0x60, 0xa1, 0x9f, 0x47, 0x43, 0x40, 0x1a, 0x10, 0xd5,
+ 0x27, 0x50, 0xc1, 0x49, 0xd4, 0x30, 0x52, 0x75, 0x0c, 0x17, 0xef, 0xc8,
+ 0x39, 0x89, 0xd4, 0x30, 0x52, 0x75, 0x0c, 0x15, 0x04, 0x4f, 0x6e, 0x35,
+ 0xf1, 0xa6, 0x1a, 0x01, 0xb5, 0xb7, 0x4e, 0xa1, 0x82, 0x93, 0xa8, 0x60,
+ 0xa4, 0xea, 0x18, 0x29, 0x3a, 0x86, 0x0a, 0x4e, 0xa1, 0x82, 0xa0, 0x7d,
+ 0x1d, 0x0d, 0x38, 0xd7, 0x61, 0xaa, 0x4e, 0xa1, 0x82, 0x93, 0xa8, 0x60,
+ 0xa4, 0xea, 0x18, 0x29, 0x3a, 0x86, 0x0a, 0x81, 0xf4, 0x0c, 0x6b, 0xe3,
+ 0x44, 0x35, 0x6f, 0xa7, 0x50, 0xc1, 0x49, 0xd4, 0x30, 0x52, 0x75, 0x0c,
+ 0x16, 0x82, 0x75, 0x0c, 0x14, 0x9d, 0x43, 0x07, 0x46, 0x82, 0x93, 0xa8,
+ 0x60, 0xa4, 0xea, 0x18, 0x29, 0x3a, 0x86, 0x0a, 0x4e, 0xa1, 0x82, 0xb6,
+ 0x47, 0x3c, 0x06, 0x8d, 0x3a, 0xdc, 0xae, 0x21, 0xa0, 0x0d, 0x78, 0x6a,
+ 0xd8, 0x9d, 0x43, 0x05, 0x27, 0x50, 0xc1, 0x49, 0xd4, 0x30, 0x5a, 0x09,
+ 0xd4, 0x30, 0x52, 0x75, 0x0c, 0x1d, 0x1a, 0x0a, 0x4e, 0xa1, 0x82, 0x93,
+ 0xa8, 0x60, 0xa9, 0x45, 0x9c, 0x06, 0x9c, 0xeb, 0x45, 0x67, 0x1a, 0xa4,
+ 0xea, 0x18, 0x29, 0x3a, 0x86, 0x0a, 0x4e, 0xa1, 0x82, 0x93, 0xa8, 0x60,
+ 0xa4, 0xea, 0x18, 0x2a, 0x51, 0x05, 0xd0, 0xd6, 0x86, 0x8e, 0x34, 0x43,
+ 0x54, 0x9d, 0x43, 0x05, 0x27, 0x50, 0xc1, 0x49, 0xd4, 0x30, 0x56, 0x8f,
+ 0x3b, 0x83, 0x5e, 0x1a, 0xa4, 0xea, 0x18, 0x29, 0x3a, 0x86, 0x0a, 0x4e,
+ 0xa1, 0x82, 0x8e, 0x79, 0xc4, 0x35, 0xe1, 0xab, 0x1d, 0x3a, 0x86, 0x0a,
+ 0x4e, 0xa1, 0x82, 0x93, 0xa8, 0x60, 0xa0, 0x1b, 0x41, 0x0d, 0x52, 0x75,
+ 0x0c, 0x14, 0x9d, 0x43, 0x05, 0x27, 0x50, 0xc1, 0x49, 0xd4, 0x30, 0x54,
+ 0x9f, 0x44, 0x43, 0x5f, 0x1a, 0x10, 0xd5, 0x4b, 0x31, 0x73, 0x68, 0x40,
+ 0xc1, 0x34, 0x6b, 0x39, 0x0b, 0xcd, 0xe1, 0x1b, 0xd4, 0x22, 0x5e, 0x14,
+ 0xf1, 0xe7, 0xd1, 0x42, 0x27, 0x50, 0xdb, 0x3a, 0x57, 0xe1, 0x12, 0xd0,
+ 0xa6, 0x01, 0xd9, 0x46, 0x0f, 0xc6, 0x8f, 0x43, 0x48, 0x50, 0xca, 0xed,
+ 0x09, 0x70, 0x9f, 0x63, 0x8b, 0x83, 0x54, 0xee, 0x84, 0x4d, 0xfa, 0x05,
+ 0x39, 0xc4, 0xea, 0x18, 0x23, 0x13, 0x98, 0xbc, 0xf2, 0x74, 0xea, 0x18,
+ 0x2f, 0x9f, 0x76, 0xd2, 0xf5, 0x0c, 0x2f, 0x38, 0xf1, 0x7a, 0x86, 0x16,
+ 0x8c, 0xe9, 0x19, 0xda, 0x4b, 0xf9, 0x57, 0x8c, 0x2b, 0xb3, 0x3f, 0x80,
+ 0x3a, 0x7c, 0xcd, 0xe0, 0xe4, 0x25, 0x8a, 0x93, 0xd2, 0x63, 0x3b, 0xce,
+ 0x5b, 0x2c, 0x5f, 0xce, 0x10, 0xf5, 0x3b, 0x2c, 0x54, 0x0f, 0x37, 0xe3,
+ 0xb4, 0xb1, 0x4b, 0x16, 0xed, 0x25, 0xc6, 0x83, 0x2e, 0x6e, 0x96, 0x2f,
+ 0xa0, 0xff, 0x12, 0xc5, 0xf4, 0xc7, 0x4f, 0x96, 0x2f, 0x3f, 0x6e, 0xfd,
+ 0x62, 0xf4, 0xe1, 0x2c, 0x5f, 0xa4, 0xed, 0xd7, 0x96, 0x2b, 0x47, 0x89,
+ 0xc1, 0xbb, 0xed, 0xc3, 0xd3, 0x2c, 0x5b, 0xb9, 0x62, 0xa4, 0xdd, 0x39,
+ 0x2d, 0x0d, 0xb2, 0x7d, 0xdc, 0x63, 0xaa, 0xc1, 0x52, 0x26, 0xd3, 0x9d,
+ 0x7c, 0x9d, 0x86, 0x08, 0x8f, 0xc4, 0xa1, 0x34, 0x77, 0x2e, 0x5c, 0x38,
+ 0x2c, 0x5f, 0xfb, 0x37, 0x6f, 0x39, 0xe7, 0xbb, 0x8b, 0x15, 0xf3, 0xda,
+ 0x00, 0xc5, 0xe8, 0x98, 0x35, 0x8b, 0xec, 0x84, 0x9a, 0xb1, 0x43, 0x3e,
+ 0x4c, 0x22, 0x21, 0xfb, 0xfe, 0xc1, 0x41, 0xcb, 0xc2, 0xfa, 0xc5, 0xf9,
+ 0xc8, 0x4d, 0xe5, 0x8b, 0xff, 0xff, 0x66, 0x10, 0xbc, 0xff, 0x21, 0x1a,
+ 0x59, 0xd7, 0xa7, 0x34, 0xb1, 0x58, 0x8f, 0x82, 0x2d, 0xe1, 0xcc, 0x71,
+ 0x3d, 0xef, 0x8b, 0x75, 0x8b, 0xef, 0xe7, 0x6c, 0x58, 0xaf, 0x9e, 0x1f,
+ 0x87, 0xef, 0x00, 0x5c, 0x58, 0xbf, 0xcc, 0x41, 0xc5, 0x07, 0x25, 0x8b,
+ 0xff, 0xb8, 0xc4, 0x0f, 0xe4, 0x52, 0x43, 0x58, 0xb8, 0x12, 0xb1, 0x7f,
+ 0x69, 0x88, 0x39, 0x02, 0xc5, 0xcd, 0xa5, 0x8b, 0x3a, 0xc6, 0xe5, 0xbd,
+ 0xb7, 0x58, 0xb1, 0xd6, 0x2d, 0x18, 0xe8, 0xa2, 0xd0, 0xbf, 0xd1, 0x58,
+ 0x84, 0x31, 0x3b, 0xfb, 0xa8, 0x7e, 0x4b, 0x65, 0x8a, 0x3a, 0x73, 0x80,
+ 0x34, 0x8e, 0x87, 0x37, 0x72, 0x95, 0xfa, 0x78, 0xdd, 0x01, 0x62, 0xff,
+ 0x7b, 0xf2, 0xf3, 0xd7, 0x96, 0x2f, 0xff, 0xfa, 0x1f, 0x9f, 0xb9, 0xac,
+ 0xe5, 0x3f, 0x67, 0x83, 0x8d, 0x62, 0xfe, 0xfe, 0x3f, 0xce, 0xcb, 0x15,
+ 0x88, 0x91, 0xec, 0xc9, 0x74, 0x31, 0x62, 0xfc, 0x53, 0xfd, 0xa5, 0x62,
+ 0xf1, 0xad, 0xa5, 0x8b, 0x1d, 0x62, 0xfe, 0x7d, 0x6e, 0xda, 0xd9, 0x62,
+ 0xfb, 0xf2, 0x2e, 0xfd, 0x62, 0xfb, 0xba, 0x7a, 0xe2, 0xc5, 0x6e, 0x79,
+ 0xfd, 0xc5, 0x17, 0xe1, 0x7b, 0xf9, 0xd9, 0x62, 0xbb, 0xd4, 0x71, 0x44,
+ 0x25, 0xa7, 0xf2, 0x26, 0xb6, 0xcb, 0x16, 0xfa, 0xc5, 0xb4, 0xe6, 0x94,
+ 0x42, 0x77, 0xff, 0x39, 0x9f, 0x67, 0xe4, 0xc2, 0x0c, 0xb1, 0x7f, 0x1f,
+ 0x22, 0x92, 0xd9, 0x62, 0xff, 0xe9, 0xcd, 0x16, 0x7b, 0x8c, 0xdb, 0x2c,
+ 0x54, 0x9f, 0x91, 0x17, 0xd2, 0xc5, 0xc3, 0xec, 0xb1, 0x7f, 0xa2, 0x84,
+ 0xf5, 0xb6, 0x04, 0xb1, 0x7e, 0xc3, 0xe9, 0xa0, 0xb1, 0x7d, 0x1d, 0x33,
+ 0x1e, 0xb1, 0x58, 0xa8, 0x47, 0x4c, 0xe7, 0x26, 0xfc, 0x2d, 0x80, 0x40,
+ 0x41, 0x9c, 0x1a, 0x8e, 0x38, 0x0c, 0xa2, 0xf8, 0xff, 0x90, 0x2c, 0x5f,
+ 0xfe, 0xc1, 0xc7, 0x6a, 0x7b, 0x3f, 0xb9, 0x86, 0xac, 0x5f, 0xdb, 0x86,
+ 0x00, 0x4f, 0x4b, 0x17, 0xfe, 0xdb, 0xcd, 0xb9, 0x4c, 0x39, 0x8b, 0x15,
+ 0x27, 0xe4, 0xe6, 0x55, 0x89, 0x82, 0xfc, 0x8f, 0x90, 0xc2, 0xbf, 0xf8,
+ 0xc6, 0xdc, 0x7f, 0x90, 0x61, 0x01, 0x62, 0xff, 0xd9, 0xcc, 0x17, 0x7e,
+ 0xc6, 0xff, 0x16, 0x2e, 0x04, 0xac, 0x56, 0x22, 0x87, 0x74, 0x60, 0x22,
+ 0x54, 0xb2, 0x46, 0x60, 0x45, 0x91, 0xdd, 0x6e, 0x93, 0xd1, 0x4b, 0xc3,
+ 0x16, 0x22, 0x4f, 0x8b, 0xb1, 0x40, 0x25, 0x88, 0xfa, 0x38, 0xc1, 0x43,
+ 0x5a, 0xfd, 0x0c, 0x1b, 0x1d, 0x62, 0xfd, 0x02, 0x13, 0x06, 0xb1, 0x7d,
+ 0x30, 0xe4, 0xac, 0x5f, 0xfc, 0x45, 0x3b, 0x16, 0x3f, 0x69, 0x8e, 0x58,
+ 0xbd, 0x3d, 0x71, 0x62, 0xa5, 0x1b, 0x0e, 0x50, 0x72, 0x96, 0x22, 0xe2,
+ 0x3d, 0xe6, 0xd4, 0xac, 0x5f, 0x36, 0x98, 0x96, 0x2f, 0xa3, 0x98, 0x80,
+ 0xb1, 0x7d, 0xee, 0x67, 0x96, 0x29, 0xcf, 0x21, 0x89, 0x6f, 0xcf, 0xd7,
+ 0x1b, 0xa5, 0x8a, 0x82, 0x33, 0xc6, 0x38, 0x76, 0x9e, 0x10, 0x52, 0xc5,
+ 0xe3, 0xcb, 0xac, 0x51, 0x1a, 0x8e, 0xc1, 0x97, 0xe8, 0x9c, 0xed, 0x12,
+ 0xc5, 0xff, 0xbd, 0xf6, 0x81, 0x37, 0xf3, 0x8b, 0x17, 0x1d, 0x96, 0x2f,
+ 0xff, 0xc4, 0xde, 0x2c, 0xf7, 0xc5, 0xd6, 0x1d, 0xba, 0x58, 0xac, 0x45,
+ 0x5b, 0x9f, 0x30, 0xbd, 0xf8, 0x84, 0xdd, 0x41, 0x62, 0xf9, 0x83, 0x7c,
+ 0x58, 0xb7, 0x1c, 0xf2, 0xc4, 0x53, 0x7f, 0x3e, 0xd3, 0xd6, 0x12, 0xc5,
+ 0xf9, 0xfa, 0xe1, 0x8f, 0xd1, 0xea, 0xe8, 0x9e, 0xff, 0xbf, 0x2f, 0xf6,
+ 0xe4, 0xc7, 0xac, 0x5f, 0xf0, 0x6c, 0x3e, 0x61, 0xe6, 0x3d, 0x62, 0xf6,
+ 0x74, 0x12, 0xc5, 0x68, 0xf7, 0x08, 0xf6, 0xff, 0x66, 0x14, 0x03, 0x21,
+ 0xac, 0x5d, 0xc3, 0x56, 0x2c, 0x35, 0x8b, 0xf3, 0x03, 0x91, 0x76, 0x58,
+ 0xa6, 0x37, 0xc4, 0x25, 0x60, 0x18, 0x9b, 0x0e, 0x42, 0x5e, 0x22, 0x10,
+ 0x19, 0xf9, 0x5e, 0xff, 0xe8, 0xf1, 0x1a, 0xfd, 0x73, 0x22, 0x9f, 0x2c,
+ 0x5e, 0x89, 0xa2, 0x58, 0xa7, 0x3e, 0xa1, 0x25, 0xda, 0x3d, 0x62, 0xf8,
+ 0x04, 0xf2, 0xb1, 0x5b, 0xaa, 0xba, 0xea, 0x3a, 0x23, 0xc3, 0x05, 0x88,
+ 0x48, 0x56, 0x96, 0x2e, 0xfb, 0x2c, 0x5f, 0xf9, 0xbf, 0x87, 0x6f, 0xe7,
+ 0x40, 0x58, 0xbf, 0xef, 0xe1, 0xdb, 0xf9, 0xd0, 0x16, 0x2c, 0x03, 0x0f,
+ 0xe5, 0x8f, 0xea, 0x51, 0x70, 0xd0, 0x90, 0xb8, 0x52, 0xb1, 0x7b, 0x35,
+ 0x05, 0x8a, 0x19, 0xb4, 0xec, 0x2f, 0x78, 0x6c, 0x4b, 0x14, 0xe6, 0xfd,
+ 0x88, 0xef, 0xb7, 0x62, 0x35, 0x62, 0xfd, 0x84, 0x3f, 0xca, 0xc5, 0xff,
+ 0xff, 0x7b, 0x0a, 0x77, 0x29, 0x3f, 0x39, 0x90, 0xfb, 0x90, 0x16, 0x28,
+ 0xc4, 0x46, 0x68, 0x9e, 0xa5, 0x1a, 0x8d, 0x0b, 0x0b, 0xff, 0x9b, 0x5a,
+ 0x60, 0x4c, 0x60, 0x41, 0x04, 0xb1, 0x7a, 0x0e, 0x05, 0x8b, 0xff, 0x1b,
+ 0x9d, 0x79, 0xfd, 0xa1, 0x1d, 0x62, 0x8c, 0x45, 0x53, 0x25, 0xf8, 0x76,
+ 0xe9, 0x82, 0xc5, 0xfd, 0x31, 0x1c, 0xa4, 0xd5, 0x8a, 0x93, 0xf6, 0x01,
+ 0x87, 0x70, 0xbd, 0x4b, 0x24, 0x07, 0x19, 0x5c, 0x8b, 0xf0, 0xd5, 0x69,
+ 0x70, 0xfd, 0xfa, 0xb9, 0x43, 0x13, 0x90, 0x99, 0xf4, 0x3c, 0xc5, 0x1a,
+ 0x35, 0xff, 0xfa, 0x4b, 0x00, 0xd0, 0x72, 0xf4, 0x33, 0x58, 0xb1, 0x7e,
+ 0x61, 0x6e, 0x77, 0x58, 0xa1, 0x9f, 0xde, 0xea, 0x57, 0xd9, 0xef, 0xba,
+ 0xc5, 0xe9, 0xc3, 0xac, 0x56, 0x8d, 0xf7, 0xc8, 0xaf, 0xec, 0x9e, 0xa0,
+ 0xe7, 0x58, 0xbf, 0x64, 0x50, 0x62, 0x58, 0xbc, 0x50, 0xe6, 0x8f, 0x58,
+ 0x32, 0xeb, 0xe2, 0x9c, 0xd2, 0xc5, 0x2c, 0x5c, 0x3c, 0xf9, 0xad, 0xf1,
+ 0x0d, 0xe3, 0xfd, 0x96, 0x2b, 0x13, 0x21, 0x77, 0x76, 0x61, 0x11, 0x65,
+ 0xff, 0xc5, 0x8f, 0xf9, 0xe8, 0x19, 0xee, 0x2c, 0x5f, 0xfc, 0x20, 0xe2,
+ 0x32, 0x43, 0x6d, 0xe7, 0xeb, 0x17, 0x11, 0xab, 0x17, 0xff, 0x01, 0xa1,
+ 0xcc, 0x87, 0xe4, 0x8d, 0x58, 0xbf, 0x8f, 0xcc, 0x3c, 0xc7, 0xac, 0x54,
+ 0x9f, 0xb3, 0xa2, 0xdf, 0xe7, 0x37, 0x8e, 0x5d, 0x41, 0x62, 0xd3, 0xa3,
+ 0xd5, 0xf9, 0x05, 0x3a, 0x61, 0x5d, 0xd0, 0xe3, 0xa3, 0x1f, 0x8c, 0x5f,
+ 0xbd, 0x55, 0x99, 0x70, 0xbb, 0x4a, 0x37, 0x84, 0xbd, 0xe1, 0xce, 0x8d,
+ 0x64, 0xac, 0x83, 0x63, 0x7f, 0xde, 0x76, 0x33, 0xa9, 0x5e, 0x6f, 0x3f,
+ 0x7f, 0x1f, 0x28, 0xe2, 0x29, 0x42, 0x7a, 0x95, 0x4e, 0x79, 0x55, 0x1f,
+ 0x9e, 0xb1, 0x6a, 0xcb, 0x8c, 0x12, 0x98, 0x8a, 0x93, 0x35, 0xc8, 0xe7,
+ 0x7d, 0x4a, 0x17, 0x14, 0x65, 0x7d, 0xa3, 0x82, 0x8e, 0x3b, 0x0d, 0x13,
+ 0xba, 0x35, 0x4b, 0xfe, 0xe7, 0xbe, 0x26, 0x84, 0x25, 0x62, 0xf7, 0xb3,
+ 0x75, 0x8b, 0xb6, 0xc5, 0x8a, 0x73, 0x6c, 0x01, 0xeb, 0xfd, 0xa9, 0xf3,
+ 0x82, 0x60, 0xb1, 0x7f, 0xba, 0xcf, 0x3f, 0xdc, 0xd5, 0x8b, 0xfd, 0xe8,
+ 0x08, 0x6c, 0x40, 0x58, 0xbc, 0x7e, 0x6e, 0xb1, 0x7a, 0x0e, 0x05, 0x8b,
+ 0x4a, 0xc5, 0xdc, 0xf2, 0xc5, 0x8b, 0x73, 0x52, 0x21, 0x1b, 0xec, 0xf3,
+ 0x74, 0xb1, 0x46, 0x22, 0xbf, 0xbd, 0x1f, 0x74, 0x6d, 0x13, 0xdf, 0xfd,
+ 0xcc, 0xdc, 0x79, 0xa0, 0x9b, 0xf1, 0x2c, 0x5f, 0xf7, 0x0d, 0x62, 0x9c,
+ 0xda, 0x56, 0x2f, 0xa1, 0x9a, 0x95, 0x8b, 0xf8, 0x26, 0xd6, 0x9b, 0xa5,
+ 0x8b, 0xe1, 0x0f, 0xee, 0xb1, 0x7f, 0x02, 0x7c, 0x4f, 0xc5, 0x8b, 0xff,
+ 0xf7, 0x35, 0xa7, 0x8b, 0x9a, 0x9f, 0x3e, 0xee, 0x35, 0x8a, 0x82, 0xb0,
+ 0x8c, 0x33, 0xdc, 0xd4, 0xf0, 0xe3, 0xfa, 0x13, 0x24, 0x00, 0xe4, 0x88,
+ 0xb8, 0x61, 0xe2, 0x30, 0x8b, 0x6f, 0xe9, 0x1b, 0x85, 0x27, 0x58, 0xbc,
+ 0x4f, 0x12, 0xc5, 0xd0, 0xd9, 0x62, 0xfd, 0x31, 0xdc, 0x11, 0x2c, 0x5e,
+ 0xf4, 0xf1, 0x62, 0xfb, 0x0f, 0x3f, 0x58, 0xb1, 0x2c, 0x5f, 0x87, 0x98,
+ 0x0e, 0x2c, 0x54, 0x71, 0xb9, 0x0c, 0x46, 0xb7, 0x44, 0x00, 0x16, 0xef,
+ 0xfd, 0xc3, 0x1b, 0x79, 0x88, 0x4d, 0xd2, 0xc5, 0x74, 0x9a, 0x44, 0x43,
+ 0x27, 0x2b, 0x28, 0x4e, 0xf8, 0x92, 0xf6, 0xce, 0x35, 0x8b, 0xf9, 0x9b,
+ 0x5a, 0x9d, 0x96, 0x2c, 0x25, 0x8b, 0x01, 0xcf, 0x7b, 0xe3, 0xc4, 0x5d,
+ 0x78, 0x1e, 0xe2, 0xc5, 0xbb, 0xd5, 0x8b, 0xfb, 0x9f, 0x8a, 0x40, 0x25,
+ 0x8b, 0xe0, 0x3e, 0xa0, 0xb1, 0x79, 0xc8, 0xd5, 0x8b, 0xe6, 0x88, 0x41,
+ 0xac, 0x54, 0x0f, 0x97, 0x44, 0x7f, 0x1d, 0xbb, 0xdc, 0x58, 0xbf, 0x61,
+ 0x67, 0x41, 0x2c, 0x5f, 0x85, 0xbf, 0xdf, 0x4b, 0x17, 0x3c, 0x4b, 0x17,
+ 0x61, 0xab, 0x16, 0xf7, 0x7a, 0x88, 0x39, 0x29, 0xf9, 0x57, 0x06, 0x2f,
+ 0xdb, 0xfe, 0x7a, 0x82, 0xc5, 0xe1, 0xfd, 0xd6, 0x2b, 0x0f, 0x21, 0xca,
+ 0xef, 0xe3, 0xf1, 0xcd, 0xf0, 0x4b, 0x17, 0xdd, 0x7e, 0x60, 0xb1, 0x71,
+ 0x6e, 0xb1, 0x52, 0x6f, 0x18, 0x92, 0x8c, 0x55, 0x9f, 0x1b, 0x0f, 0x74,
+ 0x2f, 0xa8, 0x4a, 0x80, 0xbc, 0xa1, 0x37, 0xe8, 0x47, 0x86, 0x41, 0xdc,
+ 0xdb, 0x7f, 0xfe, 0x72, 0xdf, 0x7f, 0xb6, 0xff, 0x97, 0xd0, 0xa3, 0xd6,
+ 0x2f, 0xbd, 0xec, 0xd9, 0x62, 0xd2, 0xb1, 0x58, 0x6d, 0x5c, 0x92, 0xff,
+ 0xa7, 0x9c, 0xcf, 0x73, 0x36, 0x58, 0xb7, 0x44, 0x7b, 0x21, 0x8f, 0xdf,
+ 0xfe, 0xe7, 0xc2, 0x62, 0x86, 0x61, 0x75, 0xe5, 0x8b, 0xfa, 0x7a, 0x86,
+ 0x77, 0x41, 0x62, 0xb1, 0x14, 0xda, 0x29, 0x3a, 0x5d, 0xff, 0xe6, 0x3e,
+ 0x0f, 0xaf, 0x6a, 0x73, 0xa3, 0xac, 0x5d, 0xd7, 0x96, 0x2f, 0xd8, 0x5b,
+ 0x3e, 0x96, 0x2f, 0xde, 0x62, 0x16, 0x2c, 0x5f, 0xee, 0x61, 0xdf, 0xdf,
+ 0x65, 0x8a, 0x82, 0x39, 0xf1, 0x33, 0x43, 0x24, 0x51, 0xe2, 0x7b, 0xfb,
+ 0xa8, 0x45, 0x99, 0xba, 0xc5, 0xfd, 0x22, 0xf7, 0xd8, 0x0b, 0x17, 0xbf,
+ 0x23, 0x58, 0xad, 0x1e, 0x5f, 0x0b, 0xaf, 0xa1, 0xa2, 0x12, 0xc5, 0x40,
+ 0xf1, 0x7a, 0x22, 0xbf, 0xc5, 0x91, 0x40, 0x45, 0xe5, 0x8a, 0x94, 0xd8,
+ 0x1d, 0x21, 0xa1, 0x83, 0xc2, 0x3b, 0xc6, 0x1d, 0xd6, 0x2f, 0xb5, 0x3e,
+ 0xe2, 0xc5, 0xe1, 0x61, 0x2c, 0x5b, 0x22, 0x37, 0xfe, 0x23, 0xbf, 0x7d,
+ 0xca, 0x4e, 0xb1, 0x63, 0xac, 0x5f, 0xce, 0x28, 0x71, 0xf6, 0x58, 0xac,
+ 0x3e, 0x82, 0x27, 0xf0, 0x95, 0x41, 0x31, 0x92, 0x5d, 0xe4, 0x23, 0xef,
+ 0x77, 0x6a, 0x56, 0x2f, 0xfc, 0x52, 0xdb, 0x73, 0x3b, 0x48, 0x4b, 0x17,
+ 0xfd, 0xf7, 0xd7, 0xdb, 0xbd, 0x08, 0x25, 0x8b, 0xfe, 0xf6, 0xa7, 0x3a,
+ 0xef, 0xac, 0x6d, 0xde, 0xac, 0x5f, 0xfe, 0x26, 0x0b, 0x85, 0x9d, 0x43,
+ 0xc2, 0xd9, 0x62, 0xfe, 0x78, 0x8b, 0x3b, 0x32, 0xc5, 0xdc, 0x75, 0x8a,
+ 0xd1, 0xe3, 0x70, 0xbe, 0xfb, 0x76, 0xdd, 0x96, 0x2f, 0xf6, 0x14, 0x33,
+ 0x8d, 0xf5, 0x8b, 0xff, 0xda, 0x34, 0x26, 0xd8, 0xb3, 0xb6, 0x9f, 0x8b,
+ 0x16, 0xe1, 0x8a, 0x9f, 0xa4, 0xd4, 0x64, 0x18, 0x83, 0xd2, 0x0c, 0x49,
+ 0xba, 0x84, 0x9b, 0x11, 0x78, 0x90, 0x33, 0x2b, 0x9b, 0x65, 0x8b, 0x4a,
+ 0xc5, 0xef, 0xfd, 0xd6, 0x2f, 0xd8, 0x3f, 0xe1, 0x2c, 0x5b, 0x5b, 0x1e,
+ 0xab, 0x08, 0x90, 0xed, 0xf1, 0xf4, 0xe6, 0xac, 0x5e, 0x21, 0x62, 0xc5,
+ 0x39, 0xe0, 0x31, 0x25, 0xf0, 0xe3, 0x4e, 0xf7, 0xbc, 0x58, 0xbd, 0xc9,
+ 0x3a, 0xc5, 0x47, 0x9e, 0x87, 0x0c, 0xef, 0xa6, 0x29, 0xd2, 0xc5, 0x0c,
+ 0xf2, 0x3c, 0x4b, 0x7f, 0xff, 0xd1, 0x73, 0x07, 0x9d, 0x7b, 0xed, 0x13,
+ 0x36, 0xbc, 0x26, 0x58, 0xae, 0x95, 0x5e, 0xfe, 0x13, 0x2c, 0xda, 0x07,
+ 0x42, 0x85, 0xc7, 0x88, 0xaf, 0x87, 0xf1, 0x77, 0x2c, 0x5f, 0xf0, 0x8d,
+ 0xc2, 0x17, 0x84, 0x6a, 0xc5, 0xfc, 0xdb, 0x7e, 0x74, 0x05, 0x8b, 0xe8,
+ 0x71, 0xc6, 0xb1, 0x52, 0x7a, 0x4c, 0x5f, 0x5f, 0x45, 0x71, 0x42, 0x3a,
+ 0xff, 0x3e, 0x8b, 0xde, 0xcd, 0x96, 0x2f, 0xbd, 0xb6, 0x04, 0xb1, 0x7a,
+ 0x3b, 0x00, 0xb1, 0x73, 0x76, 0x58, 0xbf, 0xa0, 0x4f, 0x0f, 0xe2, 0xc5,
+ 0xfb, 0x67, 0xd4, 0xc1, 0x62, 0xff, 0x4e, 0xd9, 0x09, 0x07, 0x16, 0x28,
+ 0xd4, 0xc7, 0x3a, 0x34, 0x72, 0x58, 0x88, 0x34, 0x32, 0x45, 0xbc, 0x29,
+ 0xbf, 0xe2, 0x9c, 0xe6, 0x10, 0x67, 0x58, 0xbc, 0x4c, 0x12, 0xc5, 0x40,
+ 0xf5, 0x78, 0x71, 0x7b, 0xce, 0x6a, 0xc5, 0xff, 0x36, 0xa0, 0x3d, 0x63,
+ 0x9a, 0xb1, 0x7f, 0x36, 0xda, 0x96, 0xdd, 0x62, 0xa0, 0x7d, 0x2c, 0x75,
+ 0x7e, 0x17, 0xa3, 0xb3, 0xcb, 0x17, 0x86, 0xe6, 0xac, 0x54, 0x9e, 0x56,
+ 0x16, 0x5f, 0xcd, 0xf0, 0xf4, 0xc0, 0x58, 0xbd, 0xa0, 0x06, 0xb1, 0x7f,
+ 0xf3, 0xfa, 0x7d, 0xcf, 0xb3, 0xfc, 0x4b, 0x15, 0x27, 0xc6, 0xc3, 0xf7,
+ 0xc4, 0x42, 0x82, 0xc5, 0xee, 0x38, 0x4b, 0x17, 0xf8, 0x85, 0xcc, 0x3c,
+ 0xee, 0xb1, 0x7f, 0xef, 0xce, 0x80, 0x58, 0x13, 0x01, 0x62, 0xf6, 0x64,
+ 0x4b, 0x17, 0xfe, 0xf3, 0x03, 0x83, 0x13, 0x6a, 0x0b, 0x14, 0x6a, 0x34,
+ 0x3e, 0x68, 0x03, 0xff, 0x0e, 0xdf, 0x78, 0x13, 0x05, 0x8a, 0xc3, 0xe1,
+ 0x11, 0xf5, 0xff, 0xbe, 0x2f, 0x07, 0xef, 0x61, 0x01, 0x62, 0xf4, 0xf4,
+ 0x12, 0xc5, 0xfb, 0x42, 0x3b, 0x12, 0xc5, 0x62, 0x22, 0x3c, 0x82, 0x21,
+ 0xfb, 0xee, 0x14, 0x9d, 0x62, 0xf8, 0xf3, 0x9b, 0x2c, 0x5f, 0x76, 0x29,
+ 0xe9, 0x62, 0xe0, 0xbc, 0xb1, 0x58, 0x6f, 0x9c, 0x96, 0xa5, 0x14, 0x4e,
+ 0x45, 0xc6, 0x1b, 0xe9, 0x2f, 0x6e, 0xb1, 0x7c, 0x6e, 0xcd, 0x1e, 0xb1,
+ 0x7d, 0x14, 0x18, 0xeb, 0x15, 0xa3, 0xcc, 0x39, 0x45, 0x18, 0xc8, 0x63,
+ 0x1c, 0x35, 0x72, 0x34, 0x3e, 0xa1, 0x76, 0xe4, 0x51, 0x42, 0x1f, 0x4d,
+ 0x67, 0x20, 0xfc, 0x24, 0x98, 0x80, 0x04, 0x45, 0x1a, 0x7f, 0x21, 0x53,
+ 0xe8, 0x68, 0xc7, 0x17, 0x06, 0xdf, 0x7f, 0xf3, 0xf4, 0x02, 0xcf, 0x75,
+ 0x07, 0x25, 0x8a, 0x58, 0xad, 0x1e, 0x8f, 0x7e, 0x8b, 0x7e, 0x8e, 0xfe,
+ 0x01, 0x96, 0x2f, 0xf0, 0x03, 0xc2, 0x1f, 0xe5, 0x62, 0xa5, 0x3e, 0x17,
+ 0x8d, 0x6c, 0xe4, 0xec, 0x57, 0x74, 0x09, 0x62, 0xf8, 0xef, 0xf9, 0x58,
+ 0xbd, 0x3a, 0x02, 0xc5, 0xb9, 0x86, 0xfc, 0x32, 0x2b, 0xdd, 0x43, 0x8b,
+ 0x17, 0xe6, 0xf0, 0x59, 0xf5, 0x8b, 0xec, 0x3c, 0xc7, 0xac, 0x57, 0xcf,
+ 0x3b, 0x85, 0x35, 0xd2, 0x2d, 0xb4, 0x4e, 0x13, 0x6d, 0xee, 0x00, 0x25,
+ 0x8b, 0xe2, 0x11, 0xf8, 0xb1, 0x7f, 0x16, 0x1c, 0xf3, 0xd2, 0xc5, 0xe3,
+ 0xbf, 0x16, 0x2f, 0xba, 0xe4, 0xf4, 0xb1, 0x7e, 0x87, 0xb9, 0x26, 0xac,
+ 0x5f, 0xfd, 0x3a, 0x98, 0x89, 0x82, 0xf6, 0x7d, 0x62, 0x98, 0xfb, 0xc8,
+ 0xaa, 0xff, 0xef, 0xe1, 0x48, 0x39, 0xf9, 0x2f, 0x2c, 0x5a, 0x06, 0x26,
+ 0x85, 0x02, 0xe7, 0x1d, 0x3c, 0x25, 0x3c, 0x41, 0x46, 0x2b, 0x18, 0x98,
+ 0xc3, 0x30, 0xc8, 0xd1, 0xf6, 0x8d, 0x96, 0xff, 0x82, 0x2c, 0xd7, 0x3f,
+ 0x9b, 0xac, 0x5f, 0xfc, 0x59, 0xcc, 0x1c, 0x50, 0x9d, 0x6c, 0xb1, 0x4e,
+ 0x88, 0x1f, 0x1d, 0xdf, 0x41, 0xcb, 0x65, 0x8b, 0xe2, 0x93, 0xf1, 0x62,
+ 0xa2, 0x3c, 0x5f, 0x11, 0xdf, 0x75, 0xbb, 0xe9, 0x62, 0x8d, 0x3c, 0x8f,
+ 0x11, 0xdf, 0x60, 0xdc, 0x96, 0x2f, 0x1e, 0x78, 0xb1, 0x7e, 0xcf, 0x13,
+ 0x01, 0x62, 0x80, 0x78, 0x84, 0x3b, 0x7c, 0x23, 0x73, 0x65, 0x8b, 0xcd,
+ 0xa8, 0x2c, 0x57, 0xcf, 0x08, 0x44, 0xb7, 0xd2, 0x2e, 0xff, 0x89, 0x17,
+ 0xe8, 0x46, 0x04, 0x10, 0x4b, 0x14, 0x47, 0xb0, 0x22, 0x8b, 0xe8, 0x79,
+ 0xc0, 0xb1, 0x76, 0x74, 0xb1, 0x7f, 0x33, 0xf3, 0xf9, 0xe5, 0x8b, 0xf4,
+ 0x73, 0x6d, 0xf7, 0x58, 0xbf, 0x13, 0x6d, 0x3e, 0x58, 0xbf, 0xda, 0x2c,
+ 0x19, 0x36, 0xcb, 0x17, 0xde, 0xe1, 0x9e, 0x58, 0xb7, 0xdc, 0xf6, 0x18,
+ 0xce, 0xff, 0xfb, 0xee, 0x69, 0xb3, 0xee, 0x49, 0x16, 0x79, 0x62, 0xf8,
+ 0xb0, 0xf2, 0xb1, 0x7f, 0xa7, 0xcc, 0x06, 0xcd, 0x2c, 0x5b, 0xcb, 0x17,
+ 0xfe, 0x7e, 0x3f, 0x6d, 0x48, 0x6c, 0x4b, 0x15, 0x87, 0xa4, 0xc2, 0x57,
+ 0xfb, 0xec, 0x7f, 0x72, 0x71, 0x62, 0xff, 0xff, 0xa7, 0x5f, 0x67, 0xf4,
+ 0x24, 0xb0, 0xe2, 0xe7, 0xda, 0x0b, 0x17, 0x9f, 0xa0, 0x2c, 0x5f, 0xc4,
+ 0xc0, 0x0b, 0x3e, 0xb1, 0x7f, 0xbc, 0x58, 0x06, 0x20, 0x68, 0xf3, 0x3c,
+ 0x3d, 0x71, 0x6e, 0x62, 0xb1, 0x39, 0x2c, 0xc8, 0x40, 0x6e, 0x4c, 0xea,
+ 0x07, 0x21, 0xfc, 0x21, 0x3c, 0x40, 0x11, 0x98, 0x70, 0xb1, 0xbd, 0xe3,
+ 0xf9, 0x62, 0xfc, 0x27, 0x27, 0xe2, 0xc5, 0x31, 0xe2, 0xf0, 0x7a, 0xf7,
+ 0x27, 0xcb, 0x17, 0xee, 0x6a, 0x5b, 0x75, 0x8b, 0xf4, 0x96, 0xf3, 0xd9,
+ 0x62, 0xb0, 0xf4, 0xfe, 0x53, 0x46, 0x2f, 0x3f, 0x41, 0x94, 0x6c, 0x78,
+ 0xf5, 0xd1, 0x0e, 0x88, 0xfe, 0x30, 0xd2, 0xd0, 0x01, 0x0e, 0xee, 0x10,
+ 0xf9, 0xc2, 0xff, 0x00, 0xb3, 0xb6, 0x9f, 0x8b, 0x17, 0x38, 0xd6, 0x2f,
+ 0xe2, 0x26, 0x09, 0xbe, 0xb1, 0x5b, 0x9e, 0x20, 0x62, 0xf7, 0xde, 0x9e,
+ 0xa0, 0xb1, 0x46, 0x3a, 0xc3, 0xbe, 0xf5, 0xc2, 0x65, 0x94, 0x6d, 0x09,
+ 0xe8, 0x17, 0x64, 0x6c, 0xbd, 0x42, 0xbd, 0xe5, 0x81, 0x47, 0xc2, 0x67,
+ 0x51, 0xc7, 0x9e, 0x53, 0xb3, 0x4f, 0x4a, 0x02, 0x95, 0x4c, 0x52, 0xd6,
+ 0x79, 0x0d, 0x8f, 0x42, 0xbc, 0x53, 0xd4, 0x3d, 0xa1, 0x4e, 0x13, 0xcc,
+ 0x71, 0x25, 0xc6, 0xfd, 0x62, 0xf8, 0x01, 0xc8, 0x16, 0x2f, 0xfc, 0x36,
+ 0x87, 0xd8, 0x02, 0x68, 0x2c, 0x5e, 0x8d, 0xfb, 0xe7, 0x7a, 0xb1, 0x7a,
+ 0x04, 0xcb, 0x17, 0xfb, 0xd2, 0x7e, 0xa1, 0x9e, 0x58, 0xbd, 0xf7, 0x02,
+ 0xc5, 0xfd, 0xf7, 0xde, 0x7d, 0xc5, 0x8b, 0xdb, 0x34, 0x7a, 0xc6, 0xe6,
+ 0xbe, 0xa3, 0x74, 0x7e, 0xc9, 0x76, 0x0e, 0x44, 0x6b, 0xc4, 0xcb, 0xf3,
+ 0x43, 0xd9, 0xba, 0xc5, 0x46, 0xb4, 0xfc, 0x24, 0x67, 0x09, 0x3a, 0x8c,
+ 0xf3, 0x49, 0xd7, 0x3f, 0x72, 0xc5, 0xfb, 0xba, 0x61, 0xa9, 0x58, 0xbf,
+ 0xf7, 0x51, 0x7b, 0xf3, 0xee, 0x7d, 0xd6, 0x2f, 0x7d, 0xce, 0xb1, 0x73,
+ 0x01, 0x62, 0xa4, 0xfd, 0x99, 0x0b, 0xc3, 0xb7, 0xed, 0x6d, 0x3a, 0xd9,
+ 0x62, 0xfe, 0xcf, 0x70, 0x45, 0xe5, 0x8b, 0xcd, 0xae, 0x2c, 0x54, 0x9f,
+ 0xb6, 0x15, 0xf8, 0xba, 0xf7, 0xa0, 0xeb, 0x16, 0x75, 0x8b, 0xf0, 0x9a,
+ 0x10, 0x95, 0x8a, 0x81, 0xb9, 0xf8, 0x8d, 0xd2, 0x46, 0x1f, 0xbf, 0x95,
+ 0xaf, 0x68, 0x51, 0xeb, 0x17, 0x3c, 0x4b, 0x17, 0x88, 0x1c, 0x58, 0xa7,
+ 0x3d, 0x62, 0x21, 0x0c, 0x62, 0xdb, 0x2c, 0x5f, 0xe7, 0xe0, 0x8e, 0xdd,
+ 0x62, 0xc5, 0xff, 0xfc, 0x31, 0xc8, 0x0b, 0x07, 0xf9, 0x3c, 0xea, 0x78,
+ 0xb1, 0x79, 0xfd, 0x1a, 0x2c, 0x56, 0x8f, 0xf0, 0xeb, 0x57, 0xd3, 0xf7,
+ 0x35, 0x62, 0xa0, 0x8f, 0x5c, 0x85, 0x86, 0x88, 0xaf, 0xf0, 0x7e, 0x72,
+ 0x9e, 0xa0, 0xb1, 0x6c, 0x58, 0xa8, 0x1e, 0x37, 0x63, 0x5b, 0xff, 0x67,
+ 0x5e, 0x35, 0xb8, 0x1c, 0x8d, 0x62, 0xb6, 0x54, 0x2c, 0x69, 0x76, 0xf1,
+ 0x84, 0x69, 0xe8, 0x32, 0x4b, 0xff, 0x0c, 0x9f, 0x7f, 0xcf, 0x5c, 0x75,
+ 0x8b, 0xe1, 0x14, 0xf6, 0x58, 0xbe, 0x67, 0x20, 0x2c, 0x7c, 0xd2, 0x5c,
+ 0xdb, 0xac, 0x5c, 0x18, 0xd6, 0x2b, 0x47, 0xc5, 0xf3, 0x12, 0x18, 0xbf,
+ 0xfe, 0x3b, 0xf3, 0x7f, 0xbf, 0x5e, 0xc3, 0xb7, 0x16, 0x2f, 0xdc, 0x2e,
+ 0x4f, 0xd6, 0x2f, 0xf6, 0xb2, 0x1e, 0xe6, 0x6c, 0xb1, 0x71, 0x6e, 0xb1,
+ 0x68, 0x96, 0x2b, 0x0d, 0x5b, 0x0c, 0x56, 0x8f, 0xfc, 0x0c, 0x14, 0xe9,
+ 0x8d, 0xb2, 0x90, 0xa1, 0x4f, 0x74, 0xc4, 0xb1, 0x7e, 0xc3, 0xce, 0xb6,
+ 0x58, 0xad, 0x1e, 0x0b, 0x0c, 0x5f, 0xec, 0x0b, 0xe1, 0x30, 0x67, 0x58,
+ 0xb9, 0xa2, 0x58, 0xad, 0x8f, 0x3c, 0x8d, 0xef, 0xdc, 0x09, 0xba, 0xe2,
+ 0xc5, 0x39, 0xe6, 0xb1, 0x15, 0xfe, 0x3e, 0x9f, 0x92, 0x5b, 0x2c, 0x5f,
+ 0xf4, 0x9b, 0xf6, 0xf0, 0x78, 0x05, 0x8a, 0x63, 0xef, 0x23, 0x4b, 0xfe,
+ 0xe4, 0xfc, 0x9c, 0xf3, 0xc5, 0x8b, 0xdc, 0xd6, 0x2c, 0x5e, 0x2c, 0x82,
+ 0xc5, 0xfb, 0x40, 0x21, 0x01, 0x62, 0xa4, 0xf1, 0x70, 0x72, 0x9d, 0x10,
+ 0x5c, 0x62, 0xb4, 0x7a, 0xc5, 0xfd, 0x81, 0xcc, 0x4f, 0xc5, 0x8a, 0x23,
+ 0xc4, 0xf0, 0xad, 0x4b, 0x28, 0x23, 0x68, 0x50, 0xc2, 0x14, 0x63, 0x85,
+ 0x26, 0x4a, 0x99, 0xe9, 0x5a, 0x28, 0x63, 0x6a, 0x34, 0x93, 0xba, 0xfe,
+ 0x17, 0xa5, 0x08, 0xfe, 0x10, 0x7a, 0x17, 0x5d, 0x99, 0xaf, 0xfa, 0x5f,
+ 0xf2, 0x7d, 0xb0, 0x25, 0x8b, 0xff, 0x72, 0x5c, 0x65, 0x30, 0x70, 0x2c,
+ 0x5f, 0xbe, 0xfb, 0x31, 0x2c, 0x5c, 0x37, 0x58, 0xbd, 0xf7, 0x89, 0x62,
+ 0xed, 0x6c, 0xb1, 0x7c, 0x6b, 0x10, 0x16, 0x2b, 0x0d, 0xe0, 0x86, 0x6e,
+ 0xfb, 0xac, 0x54, 0xa3, 0x43, 0x0a, 0x22, 0x17, 0xfa, 0xd7, 0x71, 0x05,
+ 0xff, 0x6c, 0x59, 0x0f, 0xe0, 0x38, 0xb1, 0x7e, 0xe3, 0x97, 0x50, 0x58,
+ 0xbe, 0xf6, 0x66, 0x96, 0x28, 0xd3, 0xcb, 0xe1, 0x4d, 0xf0, 0xc9, 0x82,
+ 0x58, 0xbf, 0xff, 0x9c, 0x44, 0x6e, 0xff, 0x7d, 0xff, 0x3d, 0x04, 0xda,
+ 0x58, 0xbd, 0x25, 0xb9, 0x88, 0x83, 0xf1, 0x1d, 0xff, 0x3f, 0xe7, 0xa0,
+ 0x67, 0xb8, 0xb1, 0x78, 0x52, 0x05, 0x8b, 0xf6, 0x17, 0x50, 0xe6, 0x1e,
+ 0xbe, 0x8e, 0xaf, 0x73, 0x0d, 0x58, 0xb9, 0x8e, 0xb1, 0x5e, 0x36, 0xbd,
+ 0x87, 0xaf, 0xfd, 0xe1, 0x7a, 0x21, 0x6c, 0x77, 0xf2, 0xc5, 0x61, 0xf3,
+ 0x39, 0x1d, 0xfb, 0xad, 0x6a, 0x7a, 0x58, 0xbe, 0xdc, 0xe0, 0x95, 0x8b,
+ 0xfa, 0x19, 0xce, 0x38, 0xd6, 0x2d, 0x03, 0x0f, 0x4b, 0xc4, 0x95, 0x2a,
+ 0xb4, 0x76, 0x85, 0x33, 0xc2, 0x30, 0xf0, 0xd9, 0x11, 0x00, 0x6f, 0xb7,
+ 0xff, 0xfb, 0xe2, 0x2f, 0x16, 0x74, 0x06, 0xf7, 0x1c, 0xba, 0x82, 0xc5,
+ 0xfd, 0xb0, 0xbc, 0x26, 0x0d, 0x62, 0xec, 0xdd, 0x62, 0x96, 0x3c, 0x5c,
+ 0x5f, 0xb5, 0xf0, 0x98, 0x78, 0x7c, 0x9d, 0x92, 0x6f, 0xb0, 0xf3, 0xba,
+ 0xc5, 0xf4, 0xfb, 0x0e, 0xb1, 0x79, 0x9b, 0xa5, 0x8b, 0xe8, 0x37, 0xb8,
+ 0xb1, 0x43, 0x3c, 0x08, 0x87, 0x6b, 0x74, 0x42, 0xf9, 0x8a, 0x99, 0x30,
+ 0xd0, 0x20, 0x94, 0x2a, 0x2f, 0x0e, 0x7b, 0x2c, 0x5f, 0xff, 0xda, 0x7c,
+ 0x28, 0xba, 0x03, 0x7b, 0x8e, 0x5d, 0x41, 0x62, 0xff, 0xfb, 0xc6, 0xc9,
+ 0x43, 0x85, 0x9e, 0xf3, 0x01, 0x62, 0xff, 0xfe, 0xd3, 0x43, 0xec, 0x43,
+ 0x9e, 0xb5, 0xa9, 0x3f, 0x16, 0x2f, 0xfe, 0xfb, 0xf3, 0x98, 0x5e, 0xf4,
+ 0x9d, 0x62, 0xa0, 0x8f, 0x0d, 0x28, 0x71, 0x72, 0xf8, 0xdc, 0x28, 0x2c,
+ 0x5f, 0xe1, 0x6c, 0x72, 0x63, 0x5d, 0x62, 0xb0, 0xf6, 0x1c, 0x8e, 0xfb,
+ 0x5e, 0xcd, 0x96, 0x2f, 0xff, 0xc6, 0xb1, 0x98, 0x77, 0xf1, 0x9e, 0xe1,
+ 0x39, 0xab, 0x17, 0x4c, 0x4b, 0x17, 0xff, 0x14, 0x84, 0x32, 0x9e, 0xa0,
+ 0xe4, 0xb1, 0x46, 0xa2, 0xd7, 0x4b, 0x24, 0x31, 0x7e, 0x3e, 0x7d, 0xbb,
+ 0x96, 0x2a, 0x53, 0x34, 0xc8, 0x6c, 0xb9, 0x85, 0xfb, 0xad, 0xdf, 0xdc,
+ 0x58, 0xbf, 0xf4, 0x50, 0x9d, 0x6c, 0x60, 0x59, 0xf5, 0x8b, 0xfd, 0xf7,
+ 0xf9, 0x4e, 0x69, 0x62, 0xfd, 0x3d, 0xb4, 0x1f, 0x16, 0x28, 0xc4, 0x51,
+ 0x6e, 0x89, 0xf3, 0x2a, 0x94, 0x7f, 0xb4, 0x33, 0x6a, 0x57, 0x35, 0x06,
+ 0x69, 0x83, 0xef, 0x1a, 0x6e, 0xa1, 0x11, 0xf8, 0xd5, 0x0a, 0x33, 0x2b,
+ 0xfb, 0xb4, 0x5f, 0x72, 0x1a, 0xc5, 0xfc, 0x4c, 0x00, 0x4f, 0x16, 0x2a,
+ 0x4f, 0x79, 0x8c, 0x6f, 0xf7, 0xf3, 0xd8, 0x2d, 0x6c, 0xb1, 0x7f, 0xf8,
+ 0xcf, 0xc9, 0x9c, 0x78, 0xc9, 0xdd, 0x83, 0x58, 0xb4, 0x16, 0x2f, 0x3e,
+ 0xff, 0xc3, 0xe3, 0x65, 0x1b, 0xe2, 0x13, 0x79, 0x62, 0xfb, 0xad, 0xdf,
+ 0xa5, 0x8a, 0xd9, 0x33, 0x23, 0x90, 0x7e, 0x13, 0x00, 0x32, 0xe1, 0x15,
+ 0xe9, 0x8a, 0x25, 0x8b, 0xfc, 0x53, 0x08, 0xbf, 0x3b, 0x2c, 0x5d, 0xbb,
+ 0xac, 0x5f, 0xf3, 0x94, 0x53, 0xbe, 0xb3, 0xa5, 0x8a, 0x63, 0xd3, 0xe0,
+ 0xc5, 0x0d, 0x15, 0x3e, 0x84, 0x45, 0xf8, 0x66, 0x9a, 0x2e, 0x96, 0x29,
+ 0x8f, 0x54, 0x45, 0x17, 0xfe, 0xe8, 0x83, 0x93, 0xe7, 0xf0, 0x96, 0x2b,
+ 0x13, 0x7d, 0x36, 0x31, 0xd6, 0x21, 0xbf, 0xe9, 0xf6, 0x6b, 0x76, 0x6d,
+ 0xd5, 0x27, 0xc1, 0x7f, 0x33, 0x8e, 0x7d, 0xc5, 0x8b, 0xff, 0xfd, 0xe7,
+ 0xce, 0x87, 0xf1, 0x73, 0x37, 0x33, 0xef, 0x87, 0x58, 0xbe, 0xd4, 0xf5,
+ 0x05, 0x8b, 0xff, 0xb0, 0xe2, 0x83, 0x0f, 0x37, 0x9e, 0x2c, 0x56, 0x1f,
+ 0x4f, 0xc9, 0x2e, 0x93, 0xee, 0x9b, 0x17, 0xd1, 0xf8, 0x5b, 0xe8, 0x66,
+ 0xdf, 0xf3, 0x1b, 0xc7, 0xe3, 0xf5, 0xe5, 0x8a, 0xfa, 0x22, 0x89, 0x3e,
+ 0xff, 0xfb, 0x73, 0x3f, 0x2f, 0xa7, 0x3b, 0xc7, 0x49, 0xd6, 0x2f, 0xee,
+ 0x75, 0x25, 0x3c, 0x58, 0xa2, 0x44, 0x10, 0x4a, 0x97, 0x9b, 0x5b, 0x2a,
+ 0x4f, 0xf2, 0xfe, 0x2d, 0xf9, 0xcc, 0x8f, 0x58, 0xbf, 0xf1, 0x00, 0x2c,
+ 0xeb, 0xde, 0x93, 0xac, 0x5e, 0xf4, 0xec, 0xb1, 0x52, 0x89, 0x1c, 0x32,
+ 0x64, 0x1b, 0xff, 0x17, 0xb5, 0x93, 0xd4, 0x1c, 0xeb, 0x17, 0xb3, 0x6e,
+ 0xe5, 0x8b, 0xfb, 0x3a, 0x06, 0x7b, 0x8b, 0x17, 0xe9, 0x2e, 0xa1, 0xc5,
+ 0x8f, 0x9a, 0xfa, 0x95, 0x4f, 0x19, 0x0a, 0x4d, 0xc8, 0xff, 0x0b, 0xc6,
+ 0x2d, 0x23, 0xf1, 0x28, 0x5f, 0xfa, 0x41, 0xc2, 0xcd, 0xb0, 0x33, 0xac,
+ 0x5f, 0xff, 0xff, 0xff, 0x7b, 0x0f, 0xa6, 0x19, 0x9d, 0x43, 0x8f, 0xcc,
+ 0x3c, 0xff, 0xd8, 0xfd, 0x8c, 0xea, 0x1c, 0xf0, 0xb0, 0x6b, 0x17, 0xbc,
+ 0xe1, 0x2c, 0x5f, 0xcd, 0xb0, 0x63, 0x68, 0xf5, 0x8a, 0xc4, 0xd0, 0xf8,
+ 0x81, 0xe8, 0x59, 0x08, 0x7a, 0xff, 0x6b, 0x59, 0x11, 0xe7, 0x8b, 0x17,
+ 0xfc, 0x5b, 0x96, 0x7f, 0xe2, 0x25, 0x8b, 0xfd, 0xee, 0x39, 0x75, 0x03,
+ 0xac, 0x54, 0x9f, 0x73, 0x1c, 0xdf, 0xf3, 0xeb, 0x61, 0x00, 0x13, 0xe5,
+ 0x8b, 0xfd, 0x9a, 0x32, 0x0f, 0xd4, 0x16, 0x2f, 0xfe, 0x90, 0x64, 0x1f,
+ 0xd0, 0x92, 0x02, 0xc5, 0x49, 0xfc, 0xfc, 0xda, 0xa0, 0x9e, 0xd6, 0x21,
+ 0x02, 0x14, 0x7c, 0x20, 0xf4, 0x2d, 0x2f, 0x8f, 0xae, 0x99, 0x62, 0xff,
+ 0xd3, 0xa8, 0x39, 0x61, 0xc3, 0x95, 0x8b, 0xd9, 0x80, 0x58, 0xbd, 0x20,
+ 0x8f, 0x58, 0xbf, 0xfc, 0xd0, 0x9f, 0x3f, 0xe4, 0x51, 0xe4, 0x35, 0x8a,
+ 0xdc, 0xfb, 0x34, 0x41, 0x7f, 0xff, 0xbe, 0xdc, 0x79, 0xe1, 0x9e, 0xfe,
+ 0x1f, 0x37, 0x6d, 0x2c, 0x5f, 0x31, 0x0b, 0x16, 0x29, 0x62, 0xd2, 0x03,
+ 0x5b, 0xdc, 0x43, 0x7f, 0x1c, 0xc7, 0x37, 0x06, 0xb1, 0x7f, 0xd3, 0xd4,
+ 0x3e, 0xfa, 0x68, 0x2c, 0x5e, 0xe3, 0x1d, 0x62, 0xb1, 0x10, 0xe4, 0x61,
+ 0xc3, 0xaa, 0xc5, 0x4f, 0x5b, 0x92, 0x44, 0x7d, 0xa8, 0x44, 0x7c, 0x8c,
+ 0x10, 0x8f, 0xf4, 0x2c, 0x2f, 0x8e, 0x53, 0x12, 0xc5, 0xfe, 0xeb, 0xc1,
+ 0xff, 0xf9, 0x1e, 0xb1, 0x7a, 0x73, 0x8b, 0x17, 0xec, 0x7d, 0xa4, 0xd5,
+ 0x8a, 0x94, 0x51, 0x61, 0x1e, 0x8e, 0xbe, 0x39, 0x7e, 0x07, 0x23, 0xa7,
+ 0xcb, 0x17, 0xd9, 0xa0, 0xe2, 0x58, 0xad, 0x91, 0x19, 0x87, 0x7a, 0x2c,
+ 0xbc, 0x37, 0x89, 0x62, 0xff, 0x7a, 0x7a, 0xe1, 0x4f, 0x65, 0x8b, 0x01,
+ 0x62, 0xfa, 0x12, 0x5e, 0x58, 0xbf, 0x1c, 0xee, 0x19, 0xd6, 0x2d, 0xec,
+ 0x3c, 0xc7, 0x22, 0xad, 0x91, 0xb1, 0xd0, 0xf6, 0x8d, 0x89, 0x7a, 0xfb,
+ 0xa8, 0x79, 0x96, 0x2f, 0xff, 0x6f, 0xf7, 0x2c, 0xec, 0xd0, 0xe3, 0x8d,
+ 0x62, 0xff, 0x40, 0xb0, 0xe7, 0x68, 0x2c, 0x5f, 0x3e, 0xee, 0x35, 0x8b,
+ 0xb5, 0x2e, 0x7a, 0xde, 0x33, 0xa1, 0xa3, 0x3b, 0x50, 0xa2, 0xbf, 0xb9,
+ 0xe2, 0x9c, 0xe9, 0x62, 0xa5, 0x38, 0x6c, 0x3e, 0x68, 0x79, 0x08, 0xa2,
+ 0xff, 0xf6, 0x73, 0xec, 0xfe, 0x93, 0x93, 0x1a, 0xb1, 0x79, 0x8b, 0x75,
+ 0x8b, 0xf0, 0x39, 0xec, 0xfa, 0xc5, 0xf0, 0xff, 0x3d, 0x2c, 0x5f, 0x67,
+ 0xe1, 0x8b, 0x16, 0x09, 0xcf, 0x1b, 0xc4, 0x96, 0xc5, 0x8a, 0x94, 0x54,
+ 0x33, 0x7f, 0x8a, 0x2f, 0xa4, 0x38, 0xb8, 0xb1, 0x52, 0xb8, 0x5f, 0x09,
+ 0x51, 0xd8, 0x81, 0x12, 0x49, 0x43, 0x17, 0x85, 0xd7, 0xfe, 0x01, 0xdf,
+ 0x3a, 0xf0, 0xe4, 0x6b, 0x17, 0xfb, 0xf3, 0xd4, 0x0e, 0x6c, 0xac, 0x5f,
+ 0xff, 0xdd, 0xa4, 0xbd, 0x90, 0xfc, 0xf5, 0x0f, 0x72, 0x74, 0xb1, 0x7f,
+ 0xd2, 0x78, 0xf0, 0xf0, 0x9a, 0x0b, 0x14, 0xb1, 0x7f, 0x18, 0x3c, 0xc0,
+ 0x71, 0x62, 0xff, 0xfd, 0xec, 0xd6, 0xcf, 0xc7, 0xed, 0xf7, 0xce, 0xbc,
+ 0xb1, 0x5d, 0x22, 0x50, 0xe1, 0x84, 0x5f, 0x7f, 0x8b, 0xdc, 0x10, 0xfe,
+ 0xeb, 0x15, 0x27, 0xc9, 0x86, 0x17, 0x37, 0x4b, 0x17, 0xc6, 0x04, 0x5e,
+ 0x58, 0xbb, 0x98, 0x73, 0x7a, 0x43, 0x17, 0xf6, 0x7d, 0xf5, 0xf6, 0x58,
+ 0xbb, 0x5b, 0x2c, 0x56, 0xc7, 0x8c, 0x72, 0xda, 0xc4, 0x4a, 0x3b, 0x8d,
+ 0xff, 0x4f, 0x39, 0x2f, 0xb3, 0x79, 0x62, 0xfc, 0xc7, 0x91, 0xca, 0xc5,
+ 0x78, 0xf8, 0x04, 0x73, 0x7f, 0x17, 0xc2, 0x62, 0x82, 0xc5, 0xff, 0x3e,
+ 0x10, 0xcd, 0x7c, 0xd2, 0xc5, 0x4a, 0xe0, 0x10, 0xd0, 0x30, 0xdb, 0xa5,
+ 0xe7, 0x8c, 0xd3, 0x50, 0xf1, 0xf4, 0x20, 0x44, 0x45, 0xdc, 0x5d, 0x7f,
+ 0x6c, 0x63, 0x1b, 0xf7, 0x58, 0xbf, 0x7a, 0x47, 0x9d, 0x96, 0x2b, 0x0f,
+ 0x6e, 0x23, 0x1b, 0xfe, 0xe6, 0x6d, 0xc7, 0x26, 0xd9, 0x62, 0xff, 0xd9,
+ 0xd4, 0x1c, 0x8f, 0x23, 0x95, 0x8b, 0xcf, 0x1d, 0x2b, 0x17, 0x67, 0x4b,
+ 0x17, 0xff, 0xfe, 0x9d, 0xba, 0x87, 0x0b, 0x22, 0x33, 0x7f, 0xce, 0xe6,
+ 0xe9, 0x82, 0x58, 0xa9, 0x4d, 0x1b, 0x08, 0x9c, 0xe9, 0x8f, 0xbc, 0x3e,
+ 0x21, 0x8b, 0xf9, 0xb5, 0xd4, 0x33, 0xcb, 0x17, 0xf9, 0xb0, 0x3c, 0xce,
+ 0xbc, 0xb1, 0x7f, 0xdc, 0x7d, 0x78, 0x84, 0xd0, 0x58, 0xa0, 0x1f, 0x6f,
+ 0x8d, 0x2f, 0xff, 0xcf, 0xcc, 0x1f, 0xf3, 0xcf, 0x9c, 0xdb, 0x02, 0x58,
+ 0xbf, 0xfe, 0x2f, 0x6f, 0xf7, 0x0b, 0x85, 0x80, 0x17, 0x16, 0x2f, 0xd8,
+ 0xf1, 0xce, 0x35, 0x8b, 0xff, 0xa6, 0x3b, 0x04, 0x59, 0x9d, 0xa7, 0xa5,
+ 0x8a, 0x94, 0x62, 0x0d, 0x48, 0xe5, 0x57, 0xfd, 0x3a, 0x07, 0x9c, 0xdc,
+ 0x25, 0x8b, 0xdc, 0xc2, 0x58, 0xbf, 0xff, 0xe7, 0x20, 0x0f, 0x3a, 0xe3,
+ 0x8b, 0x7f, 0xbf, 0xb8, 0xe3, 0x58, 0xbe, 0xe0, 0xf0, 0x96, 0x28, 0x08,
+ 0xa6, 0xe0, 0xe7, 0x9a, 0x2f, 0xfd, 0x39, 0xac, 0xd0, 0x0e, 0xfc, 0x58,
+ 0xbe, 0xf7, 0x01, 0xba, 0xc5, 0xe6, 0xeb, 0xb9, 0x62, 0xfe, 0x6f, 0x72,
+ 0x73, 0x65, 0x8a, 0x95, 0x79, 0x19, 0x09, 0xcd, 0xc8, 0x9e, 0x31, 0xaf,
+ 0x97, 0xb4, 0x37, 0xc8, 0xc0, 0x47, 0xdd, 0x89, 0x42, 0x21, 0xbf, 0x8b,
+ 0xf8, 0x09, 0x25, 0x8b, 0xdd, 0x43, 0x16, 0x2f, 0xe1, 0xbf, 0x50, 0x26,
+ 0x58, 0xb0, 0x18, 0xf3, 0x38, 0x3d, 0x7f, 0xb0, 0xbd, 0x91, 0x4c, 0x7a,
+ 0xc5, 0xff, 0xda, 0xce, 0xd8, 0x3d, 0x4e, 0xed, 0xa5, 0x8b, 0xfd, 0x21,
+ 0x36, 0xb4, 0xe0, 0x58, 0xbf, 0x9b, 0x7f, 0x9e, 0x46, 0xb1, 0x7b, 0x00,
+ 0x3f, 0x9f, 0x1b, 0x1a, 0x5f, 0xe6, 0x87, 0xdb, 0x93, 0x1e, 0xb1, 0x52,
+ 0x9b, 0x79, 0xc9, 0xd8, 0xd8, 0x10, 0xaa, 0xe1, 0x95, 0xff, 0xf0, 0x8d,
+ 0xfb, 0xc4, 0x03, 0x88, 0x05, 0x83, 0x58, 0xbf, 0xd2, 0x7e, 0x61, 0xe6,
+ 0x3d, 0x62, 0xba, 0x44, 0x48, 0x94, 0xef, 0xfd, 0xad, 0xb0, 0x79, 0xff,
+ 0xe4, 0x7a, 0xc5, 0x8d, 0x58, 0xbc, 0xf1, 0x71, 0x62, 0xfb, 0xb4, 0xe7,
+ 0x4b, 0x17, 0x7b, 0x83, 0x3c, 0x30, 0xc7, 0xaa, 0x51, 0x0a, 0x4a, 0xd7,
+ 0xfe, 0xd7, 0x0e, 0x1e, 0x69, 0xe6, 0x25, 0x8a, 0xc3, 0xe2, 0x11, 0x0d,
+ 0xf4, 0x97, 0xb8, 0xb1, 0x61, 0xac, 0x5e, 0xfe, 0x12, 0xc5, 0xe6, 0x2d,
+ 0xb8, 0x6b, 0xbc, 0x25, 0x58, 0x9e, 0x6f, 0x23, 0x2a, 0x11, 0x08, 0x4a,
+ 0x17, 0xde, 0xfe, 0x12, 0xc5, 0xfe, 0x2c, 0xf7, 0xb3, 0x51, 0x2c, 0x5f,
+ 0xdc, 0x68, 0x14, 0x9d, 0x62, 0xf1, 0x4c, 0x7a, 0xc5, 0xff, 0xf4, 0x27,
+ 0x5b, 0x79, 0xcd, 0xe7, 0x18, 0xa0, 0xb1, 0x7f, 0x6d, 0xcc, 0x3c, 0xc7,
+ 0xac, 0x54, 0x48, 0x84, 0x0d, 0x4a, 0xb1, 0x34, 0xb8, 0x88, 0xb4, 0x69,
+ 0xc2, 0xd0, 0xa1, 0x47, 0x7f, 0x13, 0x75, 0x0c, 0xf2, 0xc5, 0xdf, 0x75,
+ 0x8b, 0xfb, 0x01, 0x20, 0x0c, 0xeb, 0x14, 0xb1, 0x7f, 0xfd, 0xd6, 0xef,
+ 0xcf, 0xbe, 0xb3, 0xb4, 0x97, 0x96, 0x2a, 0x23, 0xdf, 0xf0, 0x65, 0x82,
+ 0x24, 0x58, 0xf2, 0x11, 0xd5, 0xb2, 0x64, 0x8e, 0x5c, 0x50, 0xc8, 0xbf,
+ 0xd8, 0x76, 0x21, 0xfe, 0x56, 0x2f, 0x87, 0xec, 0xec, 0xb1, 0x43, 0x3d,
+ 0x7f, 0x99, 0x5f, 0xff, 0x09, 0xb5, 0x08, 0xec, 0x29, 0x01, 0xda, 0x0b,
+ 0x17, 0xff, 0x43, 0xf2, 0x3f, 0x66, 0x17, 0xb8, 0xb1, 0x70, 0xe0, 0xb1,
+ 0x7e, 0xcf, 0x7d, 0xfc, 0xb1, 0x7f, 0xb0, 0x62, 0xf7, 0x21, 0xdf, 0xac,
+ 0x5d, 0x90, 0x58, 0xaf, 0x9e, 0x89, 0x1d, 0x5f, 0xff, 0xfc, 0x59, 0xd9,
+ 0xa1, 0x85, 0xd4, 0x27, 0x36, 0x16, 0xcf, 0xa9, 0x3a, 0xc5, 0xa1, 0x29,
+ 0xef, 0x0c, 0x8b, 0x14, 0xb4, 0x89, 0xf1, 0x8f, 0x3c, 0x86, 0x43, 0x7c,
+ 0x7f, 0x3e, 0xcb, 0x15, 0x88, 0x8e, 0x76, 0xab, 0xff, 0xbb, 0x78, 0xd9,
+ 0x28, 0x67, 0xdc, 0xeb, 0x16, 0xf2, 0xc5, 0xff, 0xa0, 0x06, 0xf4, 0xf7,
+ 0x3e, 0xce, 0xb1, 0x5b, 0x1e, 0xa7, 0x42, 0x57, 0xfb, 0xb7, 0xda, 0x13,
+ 0x84, 0xb1, 0x7f, 0xf0, 0x30, 0xb7, 0xfb, 0xc4, 0xcd, 0x05, 0x8a, 0x94,
+ 0x4e, 0xe1, 0x23, 0x1a, 0x5f, 0x41, 0xb5, 0x05, 0x8b, 0xff, 0xd3, 0xa6,
+ 0xf0, 0xbc, 0xfe, 0xe7, 0xdd, 0x62, 0xd0, 0x88, 0xfb, 0x7e, 0x47, 0x4b,
+ 0x17, 0xc1, 0xfd, 0xbc, 0xb1, 0x6c, 0xe1, 0xb0, 0x08, 0x32, 0xfe, 0x81,
+ 0xfc, 0x42, 0x89, 0x62, 0xff, 0xf8, 0x38, 0x4f, 0x67, 0x20, 0x69, 0xe4,
+ 0xf8, 0x91, 0x5a, 0x44, 0x0f, 0x8c, 0x2f, 0xbe, 0x1f, 0x5e, 0x58, 0xbe,
+ 0x3e, 0x3f, 0x65, 0x8b, 0xf7, 0x9b, 0x7e, 0x41, 0x62, 0xb0, 0xf3, 0x82,
+ 0x24, 0xba, 0x28, 0xf5, 0x8b, 0xee, 0xbd, 0x9f, 0x58, 0xad, 0x8f, 0x00,
+ 0x87, 0x2c, 0x12, 0xc5, 0x4a, 0xa2, 0xfd, 0x96, 0x72, 0x15, 0x1b, 0x91,
+ 0xbb, 0xa0, 0x98, 0xa3, 0x88, 0xaf, 0x8e, 0x4c, 0x6a, 0xc5, 0xcd, 0xe5,
+ 0x8a, 0xd8, 0xdd, 0x6e, 0x47, 0x77, 0xb1, 0x62, 0xff, 0x03, 0x98, 0x53,
+ 0xd7, 0x16, 0x2f, 0xda, 0x7d, 0x98, 0xea, 0xc8, 0x4c, 0xbe, 0xf0, 0xa5,
+ 0x95, 0x90, 0x99, 0x70, 0x25, 0x58, 0x09, 0x97, 0xf8, 0x98, 0xdf, 0x4e,
+ 0x80, 0xac, 0x04, 0xcb, 0xfd, 0xcc, 0xfb, 0xf0, 0x5b, 0x2b, 0x21, 0x32,
+ 0xec, 0x1a, 0xb2, 0x13, 0x2e, 0x08, 0x25, 0xe4, 0x26, 0x56, 0x26, 0xaf,
+ 0xd1, 0xb3, 0x97, 0x9c, 0x93, 0x88, 0x3d, 0x90, 0x82, 0x24, 0xb7, 0x93,
+ 0x90, 0x98, 0x8c, 0x3e, 0x7a, 0xe9, 0x51, 0xee, 0x85, 0xc2, 0x8f, 0xca,
+ 0xf0, 0xc4, 0x4b, 0x16, 0xdd, 0x62, 0xfd, 0xcf, 0x16, 0x41, 0x62, 0xb0,
+ 0xf6, 0x34, 0x3a, 0x01, 0x3a, 0xc5, 0x64, 0x0f, 0x29, 0x81, 0xa1, 0x25,
+ 0x7f, 0xfe, 0x01, 0xda, 0x1c, 0xfc, 0xf6, 0xc0, 0xc6, 0xd0, 0x58, 0xa9,
+ 0x66, 0x75, 0x3c, 0x6e, 0xbf, 0x95, 0xf0, 0xc4, 0x25, 0x19, 0xc7, 0x25,
+ 0x64, 0xfa, 0x5e, 0x38, 0x8e, 0xef, 0xff, 0xb0, 0x2f, 0xb3, 0xfa, 0x7c,
+ 0x20, 0x61, 0x2c, 0x5f, 0xfa, 0x04, 0xc6, 0xc5, 0x07, 0xd4, 0x16, 0x2f,
+ 0xb3, 0xcd, 0xf5, 0x8b, 0xf6, 0x45, 0x09, 0xe9, 0x62, 0xe6, 0x37, 0xbe,
+ 0xa7, 0x98, 0x44, 0x55, 0xa4, 0x61, 0x14, 0x23, 0x6f, 0x9f, 0x4c, 0x05,
+ 0x8b, 0xff, 0xa4, 0x2f, 0x1a, 0xdc, 0xcc, 0x23, 0x56, 0x2a, 0x07, 0xd0,
+ 0x44, 0x57, 0xe3, 0xf5, 0x07, 0x25, 0x8b, 0x88, 0x78, 0x79, 0x5e, 0x21,
+ 0xbe, 0x6e, 0xd8, 0x12, 0xc5, 0xbb, 0xc5, 0x8b, 0xff, 0xe6, 0x87, 0xe6,
+ 0x5f, 0xdc, 0x72, 0xea, 0x0b, 0x15, 0x03, 0xe6, 0xf8, 0xbd, 0xec, 0x6e,
+ 0x2c, 0x5e, 0x8a, 0x78, 0xb1, 0x7f, 0x6d, 0xb3, 0x94, 0x38, 0xb1, 0x70,
+ 0x0e, 0xb1, 0x5a, 0x3c, 0x82, 0x30, 0xbf, 0xf4, 0x4e, 0x16, 0x69, 0xf6,
+ 0x63, 0xac, 0x5f, 0xf4, 0x8b, 0xc4, 0xfd, 0x83, 0x3a, 0xc5, 0xff, 0x67,
+ 0x9f, 0x39, 0xb6, 0x04, 0xb1, 0x7b, 0x8d, 0xa5, 0x8b, 0x1d, 0x62, 0xc0,
+ 0x58, 0xa9, 0x34, 0x90, 0x12, 0xbe, 0x18, 0xe6, 0x08, 0x22, 0xbb, 0x38,
+ 0x62, 0x7c, 0x72, 0x39, 0x8c, 0xce, 0x43, 0xa4, 0x1f, 0x9e, 0x78, 0xea,
+ 0x39, 0x04, 0x32, 0x0b, 0xff, 0xcd, 0x0f, 0xcf, 0x60, 0xce, 0xcd, 0xad,
+ 0xd6, 0x2a, 0x57, 0x60, 0x32, 0x31, 0x17, 0x86, 0xce, 0x8b, 0x1a, 0x11,
+ 0x65, 0x28, 0x14, 0x50, 0x8c, 0xbe, 0xfb, 0x72, 0x3d, 0x62, 0xfb, 0x72,
+ 0x9d, 0x2c, 0x5c, 0xfd, 0x8c, 0x3c, 0x9c, 0x26, 0xbf, 0xf6, 0x98, 0xdd,
+ 0x60, 0x38, 0xdb, 0xac, 0x5f, 0xde, 0x13, 0x73, 0x9e, 0x58, 0xbf, 0x72,
+ 0x70, 0x12, 0xb1, 0x71, 0x67, 0x47, 0xad, 0xe2, 0xfb, 0x9b, 0x4b, 0x15,
+ 0xf3, 0xc4, 0x62, 0xda, 0xd2, 0x3f, 0x01, 0x0d, 0xbb, 0xfe, 0xfc, 0x86,
+ 0x7c, 0xec, 0xfb, 0xac, 0x56, 0x27, 0x20, 0xd1, 0x95, 0xf0, 0xa2, 0xf3,
+ 0xe8, 0xd5, 0x8b, 0xb4, 0x05, 0x8a, 0xc3, 0x6c, 0xe3, 0xd7, 0x6d, 0xa5,
+ 0x8b, 0x81, 0x12, 0xc5, 0xff, 0xc7, 0x8a, 0x0c, 0x5b, 0x0e, 0x4b, 0x65,
+ 0x8b, 0xb6, 0xc5, 0x8a, 0x94, 0x48, 0x8c, 0x67, 0x06, 0x59, 0x1e, 0xfd,
+ 0x84, 0x68, 0xc0, 0xb1, 0x7d, 0x17, 0xdf, 0x4b, 0x17, 0xbe, 0xfa, 0x58,
+ 0xbe, 0x7f, 0xcf, 0x0c, 0x3c, 0x18, 0x89, 0x2b, 0x88, 0xa4, 0xf3, 0x55,
+ 0xdc, 0x82, 0xc5, 0xc2, 0x25, 0x8b, 0xfe, 0xe6, 0xb2, 0x7a, 0x83, 0x9d,
+ 0x62, 0xb0, 0xfa, 0x74, 0x30, 0x21, 0x7b, 0xe7, 0xfb, 0x1d, 0x62, 0xfb,
+ 0x53, 0xcd, 0x96, 0x29, 0xd3, 0x00, 0xd4, 0x23, 0x3c, 0x5c, 0x19, 0x15,
+ 0x4b, 0xe4, 0x90, 0x6d, 0x2d, 0x5a, 0x0d, 0x03, 0x9e, 0xa7, 0xc9, 0x41,
+ 0x46, 0xc7, 0x9d, 0xbc, 0xe4, 0xd7, 0x52, 0xe2, 0x9e, 0x56, 0x74, 0x53,
+ 0xba, 0x7a, 0x9c, 0x66, 0x3c, 0xa3, 0x3f, 0xce, 0x0e, 0x34, 0x27, 0x01,
+ 0x1f, 0x39, 0x43, 0x5f, 0x91, 0xf8, 0xfa, 0x9c, 0xf3, 0xda, 0x78, 0x48,
+ 0x29, 0x4a, 0xf1, 0xcd, 0x61, 0xc2, 0xc3, 0xba, 0x3d, 0xeb, 0xff, 0xf8,
+ 0xce, 0x66, 0x76, 0x72, 0x07, 0x33, 0xdf, 0xce, 0xcb, 0x17, 0xef, 0x3f,
+ 0x4c, 0x4b, 0x17, 0x8f, 0xee, 0x2c, 0x5f, 0x6b, 0xb6, 0x0d, 0x62, 0xe0,
+ 0xfb, 0x96, 0x2a, 0x51, 0x0f, 0xb1, 0x43, 0x0f, 0x00, 0x96, 0xec, 0x25,
+ 0x8b, 0xbd, 0xc5, 0x8a, 0x93, 0x5c, 0x42, 0xd7, 0xff, 0x67, 0xf3, 0xdd,
+ 0x6e, 0xfa, 0xfe, 0x2c, 0x5f, 0xcf, 0xa2, 0x9e, 0xa0, 0xb1, 0x76, 0x71,
+ 0x62, 0xff, 0xdc, 0xcd, 0x78, 0x98, 0xd3, 0x71, 0x62, 0xa0, 0x8e, 0xa1,
+ 0x8f, 0xe2, 0x30, 0x0b, 0xb8, 0x2f, 0x7f, 0xe2, 0xc0, 0x36, 0xb3, 0xb6,
+ 0x0d, 0x62, 0xfd, 0x14, 0x24, 0xbc, 0xb1, 0x7f, 0xed, 0x67, 0x38, 0x22,
+ 0x0c, 0xf2, 0xb1, 0x50, 0x3e, 0x9d, 0x14, 0xdf, 0xd9, 0x02, 0x13, 0x71,
+ 0x62, 0xfb, 0xae, 0x3c, 0xac, 0x5f, 0xec, 0x2e, 0xef, 0x39, 0x1a, 0xb1,
+ 0x46, 0xa6, 0xa1, 0xd4, 0x2a, 0x34, 0x45, 0xf2, 0xd0, 0x11, 0xdf, 0xbd,
+ 0xc6, 0xeb, 0x75, 0x8b, 0xec, 0xd3, 0x9a, 0xb1, 0x78, 0x2d, 0x8e, 0xb1,
+ 0x7e, 0xe6, 0x85, 0x20, 0x58, 0xbe, 0xc1, 0x8f, 0x65, 0x8b, 0xff, 0xee,
+ 0xda, 0xcd, 0x8c, 0x14, 0xe7, 0xa7, 0xa8, 0x2c, 0x5e, 0xd0, 0x86, 0xb1,
+ 0x7f, 0xa4, 0xe4, 0xd0, 0xcf, 0xac, 0x56, 0x8f, 0x43, 0xe3, 0xd5, 0x29,
+ 0xea, 0x41, 0x48, 0x65, 0x78, 0x47, 0xd1, 0x01, 0xca, 0x58, 0x93, 0x90,
+ 0xa5, 0xbf, 0x48, 0x65, 0xd0, 0x16, 0x2f, 0xf7, 0xe4, 0xd0, 0xfe, 0xde,
+ 0x58, 0xaf, 0x9f, 0x07, 0x8a, 0xae, 0xce, 0xe5, 0x8b, 0x83, 0xe2, 0xc5,
+ 0xfb, 0xc1, 0x61, 0x6c, 0xb1, 0x69, 0xf9, 0xe1, 0x90, 0xcd, 0x46, 0x88,
+ 0x83, 0x82, 0xed, 0x82, 0x58, 0xa5, 0x8b, 0x66, 0x17, 0xfd, 0x84, 0xee,
+ 0x73, 0x56, 0x2f, 0xe1, 0x6d, 0x3e, 0x91, 0xac, 0x56, 0xc7, 0xda, 0xe4,
+ 0xde, 0x18, 0xbf, 0x49, 0x7b, 0xf8, 0xb1, 0x7e, 0x9c, 0xd3, 0x41, 0x62,
+ 0x9c, 0xf3, 0x88, 0x9e, 0xfd, 0xec, 0x89, 0xce, 0xb1, 0x7e, 0x9e, 0x80,
+ 0x09, 0x58, 0xa9, 0x3d, 0x22, 0x29, 0xbf, 0xf7, 0x6c, 0xf7, 0xe4, 0xdc,
+ 0xd6, 0x2c, 0x5e, 0x92, 0xf2, 0xc5, 0x31, 0xee, 0xf6, 0x41, 0xbf, 0x7e,
+ 0x5f, 0x92, 0xb1, 0x52, 0x79, 0x4c, 0x47, 0x7b, 0xee, 0x1a, 0xc5, 0xf9,
+ 0xfb, 0x79, 0xf6, 0x58, 0xbf, 0x7b, 0xf3, 0xa8, 0x2c, 0x5f, 0xfb, 0x0f,
+ 0x25, 0x20, 0x3b, 0x41, 0x62, 0xff, 0x89, 0xcd, 0x9f, 0x71, 0xf4, 0xb1,
+ 0x7f, 0xfb, 0xe2, 0x68, 0x75, 0xed, 0x4e, 0x75, 0x8b, 0x14, 0x74, 0x42,
+ 0xf0, 0xe6, 0xff, 0x66, 0xdb, 0xfe, 0x75, 0xc5, 0x8b, 0xe8, 0x7b, 0x37,
+ 0x58, 0xac, 0x3f, 0xdd, 0x11, 0xb1, 0xb5, 0xa5, 0x62, 0xff, 0xf7, 0x58,
+ 0x3e, 0x4b, 0xc1, 0xfc, 0xdf, 0x58, 0xa2, 0x3d, 0xb1, 0x08, 0xdf, 0xf7,
+ 0xda, 0x13, 0x11, 0x49, 0xd6, 0x2f, 0xf9, 0x9c, 0x64, 0xd0, 0x84, 0xac,
+ 0x5f, 0x7b, 0xee, 0x12, 0xc5, 0x87, 0xf3, 0xdb, 0x63, 0x7b, 0xc1, 0xe4,
+ 0x4b, 0x17, 0xf1, 0xfb, 0xbc, 0xfa, 0xdd, 0x62, 0xff, 0xba, 0xdf, 0xef,
+ 0xd9, 0xc8, 0x6b, 0x16, 0x2c, 0x44, 0x7b, 0x8f, 0xb1, 0x9d, 0xff, 0x49,
+ 0xf9, 0xe2, 0x60, 0x71, 0x62, 0xff, 0xfb, 0x3e, 0xf2, 0x5e, 0xe7, 0x89,
+ 0x81, 0xc5, 0x8b, 0xdd, 0x87, 0x3f, 0x44, 0x39, 0x1c, 0xdf, 0xec, 0xe1,
+ 0x83, 0xcc, 0x25, 0x8a, 0x73, 0xe8, 0xf9, 0xad, 0xff, 0xf3, 0x6b, 0xa8,
+ 0x7e, 0x4b, 0x68, 0xbf, 0x3b, 0x2c, 0x5f, 0xd9, 0x08, 0x99, 0xb6, 0x58,
+ 0xbf, 0xff, 0x66, 0xe0, 0x93, 0xe7, 0x9f, 0x99, 0x84, 0x6a, 0xc5, 0xfc,
+ 0x77, 0x93, 0xb1, 0x2c, 0x56, 0x91, 0x61, 0xf2, 0xf0, 0x2a, 0xdf, 0xfc,
+ 0xe7, 0x18, 0x9b, 0x50, 0xce, 0xbc, 0xb1, 0x58, 0x7e, 0xdb, 0x98, 0x54,
+ 0x13, 0x9c, 0x28, 0xde, 0xaf, 0xf1, 0xbf, 0x62, 0x16, 0x7d, 0x62, 0xff,
+ 0xcc, 0x40, 0xeb, 0xda, 0x9c, 0x09, 0x62, 0xff, 0xbe, 0xd0, 0xfb, 0x44,
+ 0x20, 0xd6, 0x2f, 0xfd, 0xcf, 0xb9, 0x9d, 0x42, 0x73, 0x65, 0x8b, 0xf3,
+ 0x38, 0xc5, 0x2b, 0x17, 0xda, 0x78, 0xb8, 0xb1, 0x76, 0x0c, 0xc3, 0xcb,
+ 0xd1, 0x3d, 0xc6, 0x77, 0x2c, 0x54, 0x7a, 0x6a, 0x7f, 0x40, 0x01, 0xe7,
+ 0xa1, 0x1b, 0xd8, 0xba, 0xa5, 0x3d, 0xcc, 0x8e, 0x1e, 0xf6, 0x0e, 0x39,
+ 0x62, 0xff, 0xff, 0xde, 0x9c, 0x2e, 0xbc, 0x66, 0x71, 0xc8, 0x05, 0x9e,
+ 0xfe, 0x2c, 0x5f, 0x3c, 0xf5, 0x05, 0x8b, 0xdf, 0x63, 0x98, 0x88, 0xef,
+ 0xb5, 0xde, 0x2c, 0x09, 0x62, 0xff, 0x61, 0xc6, 0xe0, 0x14, 0x16, 0x2f,
+ 0xbe, 0xcc, 0x75, 0x8b, 0xe6, 0xff, 0xdd, 0x62, 0x88, 0xf1, 0x3b, 0x11,
+ 0x5f, 0x8a, 0x11, 0xcd, 0xb2, 0xc5, 0x49, 0xe7, 0x86, 0x47, 0x52, 0xb8,
+ 0x2d, 0x09, 0x40, 0xa6, 0x94, 0x3c, 0x2b, 0xa2, 0x35, 0xf8, 0xe8, 0x21,
+ 0x8f, 0x7f, 0xff, 0x9f, 0xb1, 0x0b, 0x86, 0x06, 0x52, 0x3f, 0xb4, 0x33,
+ 0x8b, 0x17, 0x1a, 0xeb, 0x17, 0xf6, 0x9c, 0x5d, 0xfe, 0x79, 0x62, 0x96,
+ 0x24, 0xd9, 0xd6, 0xcc, 0xcc, 0x11, 0xc3, 0x1c, 0xd2, 0x0d, 0xc7, 0xba,
+ 0x2b, 0x8f, 0x29, 0xd4, 0x67, 0xe7, 0x84, 0x47, 0xc8, 0x5a, 0x12, 0x85,
+ 0x0b, 0x6e, 0x46, 0x43, 0xe9, 0xdd, 0x3e, 0xcf, 0x11, 0xcc, 0x9d, 0xc9,
+ 0x77, 0xf7, 0x1b, 0x06, 0xfd, 0x96, 0x2f, 0xdf, 0xcd, 0x4c, 0x16, 0x2f,
+ 0xee, 0xa1, 0xcf, 0xe6, 0xcb, 0x14, 0x33, 0xd9, 0xf9, 0x45, 0xff, 0x37,
+ 0xe2, 0x72, 0xfe, 0x74, 0xb1, 0x52, 0x7b, 0x98, 0x45, 0x7f, 0xf9, 0xf9,
+ 0x9f, 0x16, 0xfe, 0x7f, 0x3f, 0x4b, 0x17, 0x75, 0xb2, 0xc5, 0x80, 0xb1,
+ 0x42, 0x35, 0x81, 0x0d, 0x5f, 0xf0, 0x39, 0xec, 0xc2, 0xf7, 0x16, 0x2f,
+ 0xd1, 0x42, 0x7d, 0xc5, 0x8b, 0xe9, 0xd1, 0xb2, 0xb1, 0x77, 0x00, 0xb1,
+ 0x46, 0x26, 0x71, 0xf7, 0x86, 0x22, 0x01, 0xcf, 0x8a, 0xa3, 0x88, 0xef,
+ 0xff, 0xff, 0xbf, 0x84, 0x0c, 0x2f, 0x7f, 0x3f, 0x39, 0x13, 0xea, 0x2f,
+ 0xbf, 0x5e, 0x58, 0xbf, 0xdb, 0x61, 0x67, 0x40, 0xe2, 0xc5, 0xe0, 0x4f,
+ 0x65, 0x8b, 0x41, 0x62, 0xb0, 0xd8, 0x86, 0x3f, 0x7f, 0x69, 0xf7, 0xfe,
+ 0x44, 0xb1, 0x7f, 0xfb, 0xec, 0x60, 0x7e, 0xf3, 0xc4, 0xff, 0x12, 0xc5,
+ 0xe8, 0x73, 0x16, 0x2f, 0xff, 0xf4, 0x82, 0x28, 0x4e, 0xc1, 0xce, 0xdb,
+ 0xfd, 0xb5, 0x3d, 0x2c, 0x5f, 0xf0, 0x33, 0xd3, 0xd9, 0xc8, 0x0b, 0x17,
+ 0x64, 0x50, 0x45, 0x0b, 0x33, 0xd1, 0x89, 0x9d, 0x32, 0x71, 0x42, 0xfa,
+ 0xff, 0x79, 0xf6, 0x7e, 0xa3, 0xb1, 0x62, 0xba, 0x4f, 0xe0, 0xe4, 0x3e,
+ 0x8d, 0xa8, 0x33, 0x5b, 0xfe, 0xc1, 0x0c, 0xc9, 0xe4, 0xc1, 0x62, 0xf8,
+ 0xbc, 0xff, 0x58, 0xa3, 0x0f, 0x71, 0x8e, 0xaf, 0xfd, 0xa1, 0x45, 0xf7,
+ 0x8b, 0x92, 0x75, 0x8a, 0xc5, 0x7c, 0x5a, 0x7e, 0x69, 0x4b, 0xc0, 0x85,
+ 0x17, 0x88, 0xaf, 0x4e, 0x04, 0xb1, 0x7f, 0x9f, 0x85, 0x3e, 0x98, 0x2c,
+ 0x5b, 0xbf, 0x58, 0xa2, 0x3e, 0x6e, 0x0e, 0xf8, 0xca, 0xfe, 0xc1, 0xfd,
+ 0xc7, 0x2b, 0x17, 0xd3, 0xd7, 0x19, 0x62, 0xa3, 0x77, 0xf5, 0xe3, 0x9a,
+ 0x51, 0x16, 0xd0, 0xf5, 0x81, 0xd0, 0xe3, 0x0d, 0xcb, 0xc9, 0x6c, 0x36,
+ 0x3c, 0xfd, 0xe1, 0xcd, 0xd4, 0x6a, 0x8f, 0x2d, 0xb6, 0x3e, 0x1a, 0xb1,
+ 0x42, 0x97, 0x50, 0xb4, 0xfb, 0xeb, 0x53, 0x4c, 0xfb, 0xf8, 0xc4, 0x8a,
+ 0x1c, 0x9e, 0x8d, 0x60, 0x53, 0x87, 0xbd, 0xa1, 0x79, 0x1c, 0x5c, 0x19,
+ 0x6d, 0xfe, 0x9f, 0x8b, 0xc4, 0xc6, 0xac, 0x5e, 0xce, 0xd8, 0xb1, 0x7b,
+ 0x9c, 0xe2, 0xc5, 0xdd, 0xeb, 0xac, 0x5f, 0xfc, 0x5b, 0xff, 0x39, 0xec,
+ 0xc3, 0xf1, 0x62, 0xf4, 0x22, 0x65, 0x8b, 0xff, 0xb0, 0xf2, 0x19, 0x0a,
+ 0x05, 0x87, 0x58, 0xb3, 0xf4, 0x7c, 0x44, 0x3d, 0x7f, 0xc5, 0xef, 0xe4,
+ 0xc2, 0x78, 0xb1, 0x7d, 0x86, 0xe0, 0xd6, 0x2a, 0x4f, 0x6f, 0xe7, 0x17,
+ 0xe2, 0x14, 0x33, 0x8b, 0x17, 0xfd, 0x83, 0xfc, 0xfb, 0xf3, 0xc5, 0x8b,
+ 0x86, 0xf8, 0x7c, 0x24, 0x51, 0x7f, 0xf9, 0xe7, 0xdf, 0x13, 0x1e, 0x28,
+ 0x4e, 0xcb, 0x17, 0xf1, 0x66, 0xb5, 0x9d, 0x2c, 0x57, 0xcf, 0xeb, 0x89,
+ 0x97, 0xfe, 0x6f, 0x13, 0x73, 0xec, 0x0e, 0x2c, 0x5f, 0xec, 0x39, 0x82,
+ 0xf4, 0x25, 0x62, 0xf9, 0xff, 0x87, 0x58, 0xbf, 0xa7, 0x7f, 0xf4, 0xd1,
+ 0xeb, 0x15, 0x87, 0xab, 0xa2, 0x2b, 0xff, 0xf9, 0xbf, 0x30, 0x83, 0x82,
+ 0x7e, 0xff, 0x97, 0xd9, 0x62, 0xb6, 0x4d, 0x0c, 0x67, 0xda, 0x84, 0x57,
+ 0x62, 0x1b, 0xc5, 0x3c, 0x58, 0xbe, 0xc2, 0xc3, 0xac, 0x5f, 0xf8, 0x53,
+ 0x17, 0x24, 0x8f, 0x3c, 0x58, 0xa5, 0x8a, 0x94, 0x44, 0x40, 0x73, 0x84,
+ 0x22, 0x3f, 0xbf, 0x09, 0x86, 0x79, 0x58, 0xbf, 0xc6, 0xed, 0x81, 0x67,
+ 0x5e, 0x58, 0xbf, 0xfc, 0x53, 0xb3, 0x0f, 0xf3, 0xf2, 0xc3, 0x56, 0x2b,
+ 0x11, 0x04, 0xe7, 0x17, 0xff, 0xf4, 0x1f, 0xc4, 0xdd, 0x71, 0xbc, 0x59,
+ 0x1f, 0xf7, 0x58, 0xbf, 0xd2, 0x1e, 0xe5, 0x9f, 0xc5, 0x8a, 0xdd, 0x35,
+ 0xcd, 0x42, 0xa9, 0x88, 0x7c, 0xbb, 0x7f, 0xdf, 0x78, 0x7d, 0xa0, 0xe7,
+ 0x58, 0xbf, 0xcc, 0xfa, 0xd3, 0x85, 0xe5, 0x8b, 0xfd, 0xed, 0xfd, 0xe6,
+ 0x87, 0x16, 0x2f, 0x4f, 0x7d, 0x7b, 0xed, 0x62, 0xba, 0x3e, 0x22, 0x36,
+ 0xbf, 0xf7, 0x1c, 0xba, 0x87, 0x9f, 0x8e, 0xb1, 0x58, 0x99, 0x87, 0xce,
+ 0x5a, 0x12, 0xde, 0x22, 0xbc, 0x4f, 0x12, 0xc5, 0xff, 0xec, 0xf7, 0xe4,
+ 0x39, 0x0a, 0x43, 0xd1, 0xab, 0x14, 0xe7, 0xd7, 0xf1, 0xdb, 0xf0, 0x0f,
+ 0x3a, 0x75, 0x8b, 0xf7, 0xbf, 0x22, 0xef, 0xd6, 0x2e, 0xfb, 0x2c, 0x5f,
+ 0x6c, 0x53, 0xb2, 0xc5, 0x4a, 0x24, 0x58, 0xa3, 0xc5, 0xc2, 0x17, 0xbf,
+ 0xff, 0x61, 0x1b, 0xf6, 0xcd, 0xc8, 0x5e, 0xe1, 0x0d, 0x62, 0xff, 0xce,
+ 0x7c, 0x1f, 0xdf, 0x85, 0x8b, 0x17, 0xf8, 0x01, 0x83, 0x30, 0xa0, 0xb1,
+ 0x7a, 0x47, 0x2b, 0x15, 0x27, 0xa0, 0x73, 0x4a, 0x74, 0xc1, 0x09, 0x5b,
+ 0x90, 0x8d, 0xbf, 0xff, 0xf6, 0x78, 0xd6, 0x0f, 0xda, 0x9c, 0x23, 0xb0,
+ 0xf3, 0x08, 0xd5, 0x8a, 0x96, 0x56, 0x5c, 0x21, 0x4e, 0x38, 0x41, 0x64,
+ 0x20, 0xb7, 0x85, 0x2b, 0xc6, 0xcb, 0x14, 0x33, 0xb5, 0x1c, 0xc1, 0xe3,
+ 0x73, 0xfc, 0x2b, 0x0a, 0x16, 0x5e, 0x8c, 0xfe, 0x38, 0xd2, 0xfb, 0xf8,
+ 0x06, 0x58, 0xba, 0x35, 0x1d, 0x62, 0xf8, 0xa7, 0x50, 0x58, 0xbf, 0xef,
+ 0xcc, 0x1c, 0x88, 0x5d, 0x2c, 0x5d, 0xbb, 0xac, 0x5f, 0xe1, 0xfe, 0x62,
+ 0x11, 0x3a, 0xc5, 0xcc, 0x1a, 0xc5, 0x47, 0x9e, 0x67, 0x8d, 0x2f, 0xfa,
+ 0x60, 0xfe, 0x84, 0x90, 0x16, 0x2f, 0xef, 0x06, 0x00, 0x4f, 0x4b, 0x17,
+ 0xbd, 0x3a, 0x58, 0xb4, 0xe1, 0xe7, 0x74, 0x63, 0x7d, 0xf7, 0x17, 0x7e,
+ 0xb1, 0x7b, 0x08, 0xd5, 0x8b, 0xff, 0xbe, 0xdc, 0x29, 0x00, 0x70, 0x16,
+ 0x96, 0x2f, 0xd9, 0xa6, 0x61, 0xac, 0x57, 0x7a, 0xa9, 0x86, 0x47, 0xb0,
+ 0x8b, 0x73, 0x97, 0x64, 0xd1, 0x29, 0xe1, 0x0d, 0xf2, 0x7e, 0xfc, 0xa3,
+ 0x83, 0xa1, 0xa3, 0x5f, 0xa4, 0xc9, 0xf6, 0xeb, 0x15, 0xa4, 0x69, 0x14,
+ 0x2a, 0x2f, 0x7b, 0x23, 0xd6, 0x2f, 0xf6, 0xb2, 0x0d, 0xa6, 0x0d, 0x62,
+ 0xff, 0xdf, 0x7f, 0x94, 0xe6, 0x8c, 0xc5, 0x8b, 0x12, 0xc5, 0xff, 0x4c,
+ 0x79, 0x37, 0xa0, 0xfd, 0x96, 0x2f, 0x7e, 0x46, 0xb1, 0x7f, 0x14, 0xef,
+ 0xa9, 0x82, 0xc5, 0xff, 0xe6, 0x7f, 0x40, 0x45, 0xee, 0x7d, 0xa0, 0xb0,
+ 0x19, 0xae, 0xbf, 0x0d, 0xc5, 0xa3, 0x56, 0x2e, 0x9f, 0xac, 0x5f, 0xed,
+ 0xcb, 0x3f, 0x8e, 0x12, 0xc5, 0x3a, 0x63, 0x7f, 0x4b, 0x65, 0xbe, 0xc5,
+ 0x41, 0x8b, 0xdf, 0xfb, 0x81, 0xf9, 0xc8, 0x50, 0xce, 0x2c, 0x5c, 0x3e,
+ 0x2c, 0x54, 0x13, 0xfc, 0x8f, 0x8d, 0x63, 0xe9, 0x84, 0x81, 0x7f, 0xff,
+ 0x67, 0x59, 0xc6, 0x2f, 0xbc, 0xfb, 0xe2, 0x63, 0xac, 0x5f, 0xa1, 0xce,
+ 0x8b, 0x4b, 0x17, 0xff, 0xfe, 0xeb, 0xd3, 0xb7, 0xde, 0x2d, 0x48, 0x59,
+ 0xaf, 0x7a, 0x73, 0x8b, 0x15, 0xa4, 0x4d, 0x78, 0xaa, 0x8c, 0x5f, 0x78,
+ 0x99, 0x6a, 0xbb, 0x13, 0xe1, 0x06, 0xe6, 0x8e, 0x7c, 0xd2, 0x83, 0x49,
+ 0x18, 0x50, 0xf4, 0xb9, 0xf1, 0x62, 0xff, 0x7b, 0x82, 0x8f, 0xf3, 0x7d,
+ 0x62, 0x8e, 0x79, 0xdd, 0x85, 0xaf, 0x71, 0xb7, 0x58, 0xb6, 0x2c, 0x5f,
+ 0x84, 0x77, 0xfc, 0xac, 0x5f, 0xb3, 0x5b, 0xce, 0x2c, 0x56, 0xc7, 0xc2,
+ 0x42, 0x21, 0x94, 0x5f, 0xf6, 0x1f, 0x34, 0xfb, 0x31, 0xd6, 0x2f, 0xfd,
+ 0xf9, 0x37, 0xce, 0x4e, 0x0e, 0x2c, 0x5e, 0xe6, 0xda, 0x58, 0xbc, 0x53,
+ 0xf5, 0x8b, 0x9b, 0x46, 0x1b, 0xb9, 0x1f, 0xbf, 0xe9, 0x2d, 0xcc, 0x7d,
+ 0x66, 0xeb, 0x17, 0xff, 0x7b, 0xf8, 0x7c, 0xde, 0x7f, 0x27, 0x58, 0xbe,
+ 0x21, 0x67, 0xd6, 0x28, 0xc3, 0xe7, 0x64, 0x5b, 0xcc, 0x7e, 0x2c, 0x56,
+ 0x1b, 0xf6, 0x22, 0xa0, 0x26, 0x01, 0xe8, 0x70, 0xdd, 0x9b, 0x2c, 0x5f,
+ 0xb5, 0x9e, 0xfb, 0xac, 0x5f, 0xf4, 0x33, 0x5a, 0xcf, 0x7d, 0xd6, 0x2f,
+ 0xa7, 0xe1, 0x8f, 0x47, 0xc3, 0xe2, 0x8b, 0xfe, 0xdc, 0x98, 0xcf, 0xce,
+ 0xb1, 0x62, 0xff, 0x8a, 0x7a, 0x8e, 0x37, 0xd9, 0xf5, 0x8b, 0xff, 0xb3,
+ 0x59, 0x3c, 0xc1, 0xfd, 0xa0, 0xb1, 0x4b, 0x16, 0xf4, 0x0f, 0x3e, 0x39,
+ 0x0e, 0x8e, 0x8b, 0x82, 0x84, 0x6d, 0x4a, 0x63, 0x2d, 0x0f, 0x2b, 0xb0,
+ 0xeb, 0x17, 0xa3, 0x9c, 0x0b, 0x17, 0xff, 0xc5, 0xe6, 0x6f, 0x94, 0xfb,
+ 0x81, 0x67, 0xd6, 0x2e, 0x68, 0xf5, 0x8a, 0x1a, 0x28, 0x1c, 0x5d, 0x88,
+ 0x3c, 0x9f, 0x7f, 0xec, 0x3e, 0x77, 0x66, 0x0b, 0xbf, 0xe2, 0xc5, 0xfc,
+ 0x18, 0xdb, 0x58, 0x75, 0x8b, 0xff, 0x60, 0xda, 0x04, 0xda, 0x68, 0x2c,
+ 0x5f, 0x76, 0x92, 0x82, 0xc5, 0xe6, 0x7d, 0x2c, 0x5b, 0x46, 0x22, 0xb0,
+ 0x65, 0xf8, 0x7b, 0xf2, 0x4a, 0xf2, 0x66, 0xa1, 0xc3, 0xca, 0xff, 0xdc,
+ 0x9d, 0x43, 0xf3, 0xbe, 0x12, 0xc5, 0xff, 0xfc, 0x72, 0x63, 0x7e, 0xfe,
+ 0x98, 0x45, 0x09, 0xd6, 0xcb, 0x17, 0xff, 0x1f, 0x8d, 0x0d, 0x4f, 0x24,
+ 0xb6, 0x58, 0xbf, 0xe9, 0xf7, 0xf0, 0xf9, 0xac, 0x58, 0xbf, 0x7b, 0xef,
+ 0x3c, 0x58, 0xb9, 0x8b, 0x47, 0xc1, 0xc3, 0x8b, 0xff, 0xec, 0x1f, 0xe7,
+ 0x90, 0x7e, 0x72, 0x75, 0x05, 0x8a, 0xd8, 0xff, 0x23, 0x8b, 0x2f, 0xff,
+ 0xde, 0x9f, 0x70, 0xb3, 0xef, 0x3e, 0xfb, 0x41, 0x62, 0xce, 0xb1, 0x4e,
+ 0x7c, 0xbf, 0x54, 0xbf, 0xe9, 0x07, 0x06, 0x26, 0xd4, 0x16, 0x2f, 0xb7,
+ 0x66, 0xdd, 0x72, 0x01, 0x96, 0xc8, 0x1f, 0x5e, 0x8e, 0xaf, 0xf8, 0xed,
+ 0xd3, 0x43, 0x8f, 0x05, 0x8b, 0xfe, 0x9f, 0xee, 0xfc, 0x67, 0xd9, 0x62,
+ 0xd2, 0x62, 0x26, 0xf0, 0x9f, 0x47, 0x56, 0x02, 0xc5, 0xcd, 0x05, 0x8a,
+ 0x93, 0x52, 0x71, 0x2a, 0xf9, 0xff, 0x01, 0x7a, 0xe2, 0xc5, 0x8b, 0x98,
+ 0x0b, 0x15, 0x27, 0x9e, 0x44, 0x5e, 0x16, 0xb6, 0xeb, 0x15, 0xa3, 0xc0,
+ 0x22, 0xda, 0x95, 0xc5, 0xfc, 0x5e, 0x68, 0xc8, 0x79, 0x08, 0xb0, 0xe5,
+ 0x1a, 0x50, 0xd9, 0x66, 0x06, 0x9c, 0xee, 0xf5, 0xd4, 0x65, 0x9a, 0x29,
+ 0x3b, 0xcf, 0xe3, 0x53, 0x04, 0x31, 0xca, 0x37, 0x0e, 0x15, 0x7a, 0x72,
+ 0x7a, 0xe9, 0x8e, 0x58, 0xbf, 0xa1, 0x9a, 0xd3, 0x41, 0x62, 0xc3, 0xf9,
+ 0xe4, 0x78, 0x6a, 0xc3, 0x58, 0xbf, 0xf9, 0xbd, 0xc1, 0x43, 0xec, 0xe4,
+ 0xcb, 0x15, 0xd1, 0xea, 0x9c, 0x4a, 0xff, 0xfe, 0x71, 0x96, 0x72, 0x74,
+ 0x67, 0x3e, 0xc3, 0x91, 0xac, 0x5e, 0x79, 0x82, 0xc5, 0xee, 0xd3, 0xf5,
+ 0x8a, 0x96, 0x71, 0xf4, 0x09, 0x31, 0xfd, 0xe9, 0x6c, 0x0d, 0x18, 0x28,
+ 0x1f, 0x78, 0x47, 0xe5, 0xb0, 0xc7, 0x2f, 0xcf, 0xe6, 0x8e, 0xc5, 0x8b,
+ 0xf6, 0x6a, 0x01, 0xc1, 0x62, 0xff, 0x6d, 0xc9, 0x3b, 0x75, 0xe5, 0x8b,
+ 0xff, 0x3f, 0xa1, 0xf7, 0xf7, 0x3e, 0xeb, 0x15, 0xb2, 0x27, 0xc8, 0xab,
+ 0xb1, 0xb5, 0xcd, 0xd2, 0xc5, 0xef, 0xb4, 0x7a, 0xc5, 0xf4, 0x82, 0x3b,
+ 0x16, 0x2f, 0x8e, 0x76, 0xf2, 0xc5, 0x41, 0x37, 0xbc, 0x86, 0x49, 0xcc,
+ 0x80, 0x31, 0xe2, 0x00, 0xc9, 0x6f, 0xec, 0xee, 0x66, 0xff, 0x16, 0x2f,
+ 0xfe, 0xce, 0x79, 0xba, 0x0f, 0xba, 0x4a, 0x0b, 0x16, 0xc5, 0x8b, 0xff,
+ 0xb0, 0x9a, 0x1f, 0x63, 0x9d, 0xa0, 0xb1, 0x68, 0xa3, 0x43, 0xd4, 0x8d,
+ 0x84, 0x6f, 0xff, 0xf3, 0x8b, 0x68, 0x99, 0xb6, 0xf6, 0x44, 0x52, 0x7f,
+ 0xb2, 0xc5, 0xf3, 0xea, 0x7b, 0x2c, 0x5f, 0xfc, 0x71, 0x1a, 0x58, 0x0f,
+ 0x73, 0x36, 0x58, 0xb6, 0xc3, 0x3e, 0xbc, 0x24, 0xbf, 0xff, 0x70, 0xcc,
+ 0x19, 0x9c, 0xcd, 0x00, 0xf9, 0x1d, 0x8b, 0x14, 0x48, 0x83, 0xf1, 0x45,
+ 0xff, 0xfe, 0xcd, 0x19, 0xbf, 0xdc, 0x7a, 0x71, 0x6c, 0x18, 0xdb, 0x65,
+ 0x8b, 0xd0, 0xd1, 0xd6, 0x2f, 0xb7, 0xfb, 0xec, 0xb1, 0x7f, 0xc7, 0xce,
+ 0xe0, 0xf5, 0x3f, 0x95, 0x8b, 0x88, 0xdf, 0xa2, 0x01, 0x87, 0x83, 0x25,
+ 0xbd, 0xe0, 0x09, 0x62, 0xb7, 0x4d, 0x05, 0xe1, 0xce, 0x47, 0x97, 0xe3,
+ 0xc6, 0xf1, 0xbc, 0x6f, 0xde, 0x2c, 0x5f, 0xff, 0xd0, 0xce, 0x3e, 0xb4,
+ 0xe7, 0x0f, 0xdf, 0xc0, 0xbc, 0xb1, 0x7f, 0xe6, 0x2d, 0xc9, 0xba, 0x87,
+ 0xe5, 0x62, 0xa5, 0x53, 0x9e, 0x46, 0xc6, 0xe6, 0xac, 0x7c, 0x25, 0xeb,
+ 0xff, 0xc7, 0x9d, 0xc7, 0x2d, 0xaf, 0x84, 0xc3, 0x58, 0xb9, 0x9d, 0x62,
+ 0xb0, 0xf8, 0xb8, 0x99, 0x7c, 0x36, 0x63, 0xac, 0x5f, 0xbf, 0x23, 0x79,
+ 0x58, 0xa3, 0x4f, 0x24, 0x22, 0x2a, 0x3a, 0x23, 0x99, 0xaa, 0xff, 0x6b,
+ 0x3f, 0xf9, 0xea, 0x0b, 0x17, 0xff, 0xdf, 0x67, 0xf4, 0xbc, 0x30, 0x80,
+ 0x09, 0x58, 0xbc, 0xdf, 0x95, 0x8b, 0xb0, 0x0b, 0x16, 0xdb, 0xe6, 0xcc,
+ 0x21, 0xcb, 0xf0, 0x73, 0xac, 0x25, 0x8b, 0xfe, 0xfc, 0xf3, 0xdc, 0xc1,
+ 0x77, 0xeb, 0x17, 0xfe, 0x97, 0xff, 0xf3, 0xdf, 0xc8, 0x2c, 0x5f, 0xec,
+ 0x28, 0x67, 0x03, 0x3a, 0xc5, 0x88, 0x68, 0xb1, 0xd1, 0xff, 0x8f, 0xaa,
+ 0x53, 0x0e, 0xc8, 0x6c, 0xdf, 0xfe, 0xcf, 0xbf, 0x69, 0xcd, 0x6c, 0x26,
+ 0x1a, 0xc5, 0x41, 0x52, 0xfc, 0x46, 0xad, 0x08, 0x00, 0xa3, 0x37, 0x0c,
+ 0x9e, 0xff, 0xf4, 0x33, 0xa8, 0x07, 0x20, 0x8c, 0x08, 0x20, 0x92, 0x2f,
+ 0xa6, 0x23, 0xe2, 0xc5, 0xf8, 0xe1, 0x63, 0xf6, 0x58, 0xbb, 0x0a, 0x24,
+ 0x51, 0x7d, 0x50, 0x32, 0x3b, 0xff, 0xee, 0x73, 0xe2, 0xde, 0x60, 0xfa,
+ 0x06, 0x12, 0xc5, 0x41, 0x11, 0xa1, 0x1e, 0x54, 0xa7, 0x58, 0xd1, 0xc4,
+ 0x5f, 0xff, 0x6a, 0x03, 0xfc, 0xf0, 0xb0, 0x26, 0xd1, 0xab, 0x17, 0x80,
+ 0x2e, 0x2c, 0x5f, 0xb3, 0x0a, 0x60, 0xb1, 0x6e, 0x49, 0xe2, 0x10, 0xf5,
+ 0x32, 0x2f, 0x3d, 0x09, 0x6a, 0x96, 0x5c, 0xb8, 0xd7, 0x70, 0xc1, 0xe1,
+ 0x3b, 0xa3, 0x3f, 0xcb, 0xc4, 0x68, 0xcf, 0x8a, 0x70, 0xb4, 0x50, 0xe4,
+ 0xbd, 0xf7, 0x09, 0x62, 0xff, 0x87, 0x90, 0xfc, 0xf6, 0x1c, 0xac, 0x5e,
+ 0xef, 0x23, 0x7e, 0xf1, 0x62, 0xf9, 0xca, 0x1c, 0x30, 0xfa, 0x3b, 0xea,
+ 0x77, 0x7f, 0xe7, 0x06, 0x0b, 0xbf, 0x72, 0xfe, 0x2c, 0x5d, 0xa3, 0x56,
+ 0x28, 0x8f, 0x6c, 0x34, 0x2b, 0xe8, 0xb9, 0x91, 0x2c, 0x5f, 0x81, 0x3e,
+ 0xc8, 0xf5, 0x8b, 0xa2, 0xc5, 0x8b, 0xe3, 0x5f, 0xae, 0x2c, 0x5f, 0xce,
+ 0x69, 0xb2, 0x5e, 0x58, 0xb0, 0xd8, 0xfb, 0x3c, 0x31, 0x1c, 0x4b, 0x7f,
+ 0x73, 0x5a, 0x78, 0xb8, 0xb1, 0x7f, 0x67, 0xb7, 0xfb, 0xc4, 0xb1, 0x7f,
+ 0x66, 0xb7, 0x66, 0xdd, 0x52, 0x04, 0x97, 0xfe, 0x98, 0x16, 0x7f, 0xc5,
+ 0x20, 0x58, 0xa9, 0x3f, 0x92, 0x3c, 0xbf, 0xde, 0xcd, 0x6e, 0xcd, 0xba,
+ 0xa4, 0xf9, 0x2f, 0xf6, 0x9c, 0xbd, 0xc7, 0x1a, 0xc5, 0x49, 0xfa, 0xb2,
+ 0x15, 0xf9, 0x87, 0xf9, 0x35, 0x62, 0xff, 0xfe, 0xd6, 0x0f, 0xf3, 0xd4,
+ 0x35, 0x3e, 0xe0, 0x65, 0x05, 0x8b, 0xff, 0xf0, 0x80, 0x76, 0x80, 0xd9,
+ 0x82, 0xc8, 0xa7, 0x4b, 0x16, 0xc7, 0x45, 0xaf, 0x97, 0xaf, 0xfc, 0x59,
+ 0xef, 0x3f, 0x3d, 0x80, 0x58, 0xbf, 0xfe, 0xdc, 0xb3, 0xf8, 0x4f, 0x23,
+ 0x14, 0xec, 0xb1, 0x76, 0x73, 0xbd, 0x56, 0x41, 0x03, 0x01, 0xc2, 0xa7,
+ 0x78, 0x4a, 0x9c, 0x80, 0xa1, 0xbd, 0xc2, 0x70, 0xcf, 0xab, 0x15, 0xf5,
+ 0x14, 0xb5, 0x7a, 0x25, 0xca, 0xbe, 0xd3, 0x90, 0x37, 0xff, 0x4f, 0xdc,
+ 0xdc, 0xd6, 0xc7, 0x17, 0x4b, 0x17, 0xfc, 0x3d, 0x61, 0xf2, 0x0c, 0x35,
+ 0x8b, 0xff, 0xf0, 0x9b, 0x98, 0x5b, 0xfd, 0xc7, 0xfc, 0xeb, 0xb9, 0x62,
+ 0xa5, 0x77, 0xf3, 0x08, 0x9e, 0x73, 0x43, 0xe5, 0xec, 0x90, 0x47, 0x37,
+ 0xff, 0x7f, 0x00, 0x39, 0x1e, 0x69, 0xb8, 0xb1, 0x7e, 0x9d, 0x60, 0xe5,
+ 0x62, 0xfd, 0x0c, 0x00, 0x7e, 0x58, 0xbf, 0xbf, 0x1d, 0xf7, 0xdf, 0xeb,
+ 0x15, 0x28, 0xc8, 0x74, 0x46, 0x27, 0x11, 0x55, 0xff, 0xe7, 0x92, 0xf6,
+ 0xff, 0x90, 0xb9, 0xa6, 0x58, 0xbe, 0x98, 0x73, 0x16, 0x2f, 0x73, 0x03,
+ 0x58, 0xaf, 0xa2, 0x2c, 0x09, 0x7e, 0x22, 0xbe, 0x83, 0x83, 0x16, 0x2f,
+ 0xff, 0x79, 0xa0, 0x66, 0x7e, 0x75, 0xd7, 0x25, 0x62, 0xff, 0xfb, 0x7f,
+ 0xce, 0xb3, 0x84, 0x26, 0x81, 0xac, 0xb1, 0x7f, 0xfe, 0x6e, 0xc6, 0x73,
+ 0xec, 0xfe, 0x9f, 0x7f, 0x3c, 0xb1, 0x40, 0x4c, 0x5f, 0xc4, 0x42, 0x4c,
+ 0x0d, 0x46, 0xff, 0xcd, 0xb7, 0xe7, 0x6c, 0xf7, 0x31, 0x62, 0xa4, 0xff,
+ 0xc8, 0xfe, 0xff, 0xbd, 0x27, 0xfe, 0x76, 0xce, 0x2c, 0x5e, 0x72, 0x1a,
+ 0xc5, 0xff, 0x49, 0xf9, 0x2f, 0xb3, 0x79, 0x62, 0xa0, 0x89, 0x0d, 0xce,
+ 0xfc, 0x39, 0x7f, 0xed, 0x9b, 0xa8, 0xec, 0xf1, 0x37, 0x65, 0x8b, 0xfe,
+ 0x17, 0xb8, 0x60, 0x37, 0xe3, 0xac, 0x5f, 0xfe, 0xf4, 0x97, 0xb9, 0x98,
+ 0x69, 0xad, 0x05, 0x8b, 0xff, 0xe8, 0x67, 0x8c, 0xe7, 0x30, 0xb7, 0x62,
+ 0x02, 0xc5, 0xfd, 0x9e, 0xfb, 0x90, 0x16, 0x2f, 0x69, 0xbf, 0xd1, 0xff,
+ 0x44, 0xa3, 0x58, 0x8f, 0xe6, 0x86, 0x4d, 0xff, 0xdf, 0xc2, 0x37, 0x9e,
+ 0x7f, 0x60, 0x16, 0x2f, 0xf3, 0x17, 0xb0, 0x45, 0xe5, 0x8a, 0x81, 0xfb,
+ 0x81, 0x16, 0xfd, 0x9e, 0xf6, 0x0d, 0x62, 0xff, 0x9f, 0xa0, 0x19, 0xa7,
+ 0xe8, 0x0b, 0x14, 0x69, 0xf2, 0xe8, 0xa2, 0xff, 0xd8, 0x39, 0x84, 0xff,
+ 0x00, 0xcb, 0x17, 0xff, 0xf9, 0xba, 0x01, 0xc3, 0xe1, 0x83, 0xc2, 0x17,
+ 0x81, 0x30, 0x58, 0xbf, 0x9a, 0x02, 0x83, 0x0d, 0x62, 0xff, 0xff, 0xbe,
+ 0x26, 0xdb, 0x53, 0xf6, 0x7e, 0x73, 0x0d, 0x62, 0x02, 0xc5, 0xf9, 0xf6,
+ 0xe7, 0x19, 0x62, 0x86, 0x89, 0x0f, 0xb3, 0xdf, 0xfa, 0x58, 0xb3, 0x5e,
+ 0xcc, 0xd9, 0x62, 0xff, 0xd3, 0x84, 0x3f, 0xcf, 0xe7, 0x8b, 0x17, 0x7b,
+ 0x83, 0x3f, 0xae, 0x1e, 0xde, 0x08, 0x20, 0x92, 0x2f, 0xb3, 0x76, 0xd2,
+ 0x44, 0x61, 0xa1, 0xbf, 0xf8, 0x43, 0xfb, 0x99, 0xaf, 0x4b, 0x41, 0x62,
+ 0xbe, 0x7f, 0x9c, 0x36, 0xbf, 0xff, 0xd1, 0x6a, 0x7b, 0x18, 0x6b, 0x18,
+ 0x1c, 0x5c, 0x33, 0x3a, 0xf2, 0xc5, 0x4a, 0x7e, 0xed, 0x09, 0xdf, 0x43,
+ 0x2c, 0x32, 0x2b, 0xfe, 0xfb, 0x85, 0xe8, 0xb5, 0x3e, 0x58, 0xbf, 0xf3,
+ 0xf8, 0x59, 0xe6, 0x3e, 0x12, 0xc5, 0xff, 0xff, 0xff, 0x08, 0xe7, 0x68,
+ 0x1b, 0xa6, 0xdf, 0x35, 0xa7, 0xed, 0xcc, 0xf7, 0x9b, 0x45, 0x3d, 0x41,
+ 0x62, 0xa0, 0x98, 0x96, 0x8f, 0x3e, 0x7b, 0x7f, 0xd2, 0x0f, 0x61, 0x43,
+ 0x38, 0xb1, 0x71, 0xb0, 0x58, 0xbd, 0x2f, 0xba, 0xc5, 0xfb, 0x00, 0xc4,
+ 0x08, 0x1b, 0x6f, 0x8c, 0xd3, 0xa3, 0x6f, 0xe6, 0x24, 0xdd, 0x5b, 0x32,
+ 0x20, 0x06, 0x8b, 0xbc, 0x67, 0x7d, 0x42, 0x77, 0x50, 0x87, 0x39, 0x1f,
+ 0xcf, 0x40, 0xca, 0x52, 0xad, 0x7d, 0x28, 0xd2, 0xe6, 0xf2, 0xc5, 0xee,
+ 0x66, 0xcb, 0x17, 0x16, 0xc0, 0x36, 0xbe, 0x17, 0xa5, 0x8a, 0x93, 0x72,
+ 0x72, 0xda, 0x58, 0xa5, 0x8b, 0x70, 0x22, 0xe3, 0xb8, 0x32, 0xff, 0xff,
+ 0x0b, 0xd3, 0xf3, 0x38, 0xd0, 0x7f, 0x61, 0xf8, 0xd0, 0x58, 0xb3, 0x2c,
+ 0x5a, 0x56, 0x2f, 0x33, 0xec, 0x46, 0x88, 0x42, 0x37, 0xff, 0xcf, 0xbb,
+ 0x8f, 0x93, 0xf6, 0x21, 0x67, 0xd6, 0x2a, 0x09, 0x97, 0x11, 0x57, 0x21,
+ 0x09, 0xe3, 0x1b, 0xfb, 0x85, 0x9b, 0x07, 0x05, 0x8b, 0xf0, 0x7e, 0xe0,
+ 0x89, 0x62, 0xd3, 0xd1, 0xed, 0x11, 0x85, 0xfe, 0x29, 0xe7, 0x1e, 0x49,
+ 0x62, 0x8e, 0x7b, 0x0c, 0x4f, 0x7f, 0xff, 0x7d, 0x8b, 0xa8, 0x07, 0x09,
+ 0x28, 0x31, 0xf0, 0x6b, 0x17, 0xfe, 0x80, 0x58, 0xfd, 0xb2, 0x12, 0x4b,
+ 0x14, 0xe8, 0x9c, 0x0d, 0x72, 0xff, 0xf6, 0x67, 0xc7, 0xf9, 0xe6, 0x7d,
+ 0xc0, 0xb1, 0x7f, 0xfe, 0xdf, 0xf3, 0xc6, 0xd3, 0x16, 0x77, 0x6c, 0x2e,
+ 0x2c, 0x5f, 0xfb, 0xee, 0x59, 0xef, 0xbb, 0x01, 0x62, 0xfd, 0x14, 0x27,
+ 0x5c, 0x58, 0xbf, 0x41, 0xe3, 0xb3, 0xeb, 0x17, 0xfb, 0x08, 0x50, 0xe6,
+ 0xcc, 0xb1, 0x7a, 0x48, 0x6b, 0x17, 0xfb, 0x0e, 0x2e, 0x7d, 0xa0, 0xb1,
+ 0x46, 0x23, 0x66, 0x4a, 0x86, 0x57, 0xb9, 0xa1, 0x0e, 0x5f, 0x18, 0x31,
+ 0xe2, 0xc5, 0x1a, 0x7d, 0xc7, 0x4a, 0xbf, 0xf0, 0x9a, 0x1f, 0x7e, 0x09,
+ 0xa0, 0xb1, 0x7f, 0xe7, 0xf6, 0xc2, 0xe1, 0x9a, 0xd4, 0xac, 0x54, 0xae,
+ 0x4f, 0xed, 0x0f, 0x48, 0x42, 0xf4, 0x64, 0x78, 0x93, 0xba, 0xd3, 0xc7,
+ 0x08, 0x02, 0x3f, 0x1f, 0xde, 0x7f, 0x89, 0x62, 0xfb, 0xb9, 0xc5, 0xdf,
+ 0xac, 0x5f, 0xc3, 0x91, 0xb0, 0x5e, 0x58, 0xa3, 0x0f, 0xdd, 0x87, 0x78,
+ 0x57, 0x7e, 0xc8, 0x7e, 0x74, 0xb1, 0x7c, 0x69, 0x9f, 0x75, 0x8a, 0xdc,
+ 0xff, 0x23, 0xcb, 0xf4, 0x51, 0x7e, 0x81, 0x0b, 0xa8, 0x2c, 0x5d, 0xf7,
+ 0x58, 0xbb, 0xaf, 0x74, 0x78, 0x31, 0x15, 0x5f, 0x9f, 0xe6, 0xcf, 0x4b,
+ 0x17, 0xec, 0x19, 0x4f, 0x4b, 0x16, 0xf4, 0x9e, 0x91, 0x15, 0x5f, 0xff,
+ 0xfb, 0x42, 0xde, 0x46, 0xe4, 0xda, 0x37, 0x7f, 0xbf, 0x74, 0x9e, 0x56,
+ 0x2f, 0xff, 0xff, 0x14, 0x9f, 0x83, 0xfc, 0xf3, 0x20, 0xe6, 0x9a, 0xde,
+ 0x29, 0x3f, 0x16, 0x2d, 0xd1, 0xa8, 0xe9, 0xf3, 0x8d, 0xfe, 0x04, 0x1f,
+ 0xdc, 0x0c, 0xeb, 0x17, 0xfe, 0xe3, 0x43, 0x99, 0xbc, 0x9d, 0xd6, 0x2b,
+ 0x47, 0xeb, 0xe3, 0x6b, 0xfe, 0xdf, 0xee, 0x00, 0x4e, 0xa0, 0xb1, 0x7d,
+ 0xad, 0x9f, 0x65, 0x8b, 0xba, 0x23, 0x0f, 0x83, 0x0e, 0xea, 0x55, 0xab,
+ 0x63, 0xa3, 0xc2, 0x0d, 0xa3, 0x0f, 0x14, 0x28, 0x03, 0x84, 0x15, 0xff,
+ 0x75, 0x2e, 0x7c, 0x2c, 0x8f, 0x58, 0xbd, 0xe6, 0xdd, 0x62, 0xff, 0xf4,
+ 0x39, 0x83, 0xcf, 0xbb, 0x7b, 0xf2, 0xb1, 0x5b, 0x22, 0x8b, 0x73, 0xbe,
+ 0x87, 0xaf, 0xdb, 0x7e, 0x45, 0x8b, 0x17, 0xff, 0xd0, 0x93, 0xea, 0x5e,
+ 0x0d, 0xc6, 0x20, 0x2c, 0x5f, 0xcf, 0xcc, 0x18, 0x78, 0xb1, 0x7e, 0xee,
+ 0x72, 0xce, 0xcb, 0x17, 0xf6, 0x0d, 0xc5, 0xbf, 0xf7, 0x3d, 0xa6, 0x2e,
+ 0xbf, 0xb9, 0x07, 0x3b, 0x41, 0x62, 0xff, 0xf8, 0x79, 0x01, 0x0d, 0x88,
+ 0x1a, 0xd6, 0x04, 0xb1, 0x52, 0x9c, 0xaf, 0x45, 0x3a, 0x85, 0x40, 0x11,
+ 0x42, 0x2e, 0xbf, 0xdc, 0x2c, 0xed, 0xf6, 0x82, 0xc5, 0xee, 0x43, 0xb2,
+ 0xc5, 0xf8, 0x7a, 0x9c, 0xf2, 0xc5, 0x39, 0xfe, 0xc7, 0x9a, 0x91, 0x05,
+ 0xff, 0xe9, 0xd8, 0x3f, 0xcf, 0x5e, 0xcd, 0x88, 0x6b, 0x17, 0x9b, 0x79,
+ 0x58, 0xac, 0x56, 0x62, 0xf1, 0xe4, 0x34, 0x33, 0x88, 0xc3, 0xc9, 0xd7,
+ 0xf8, 0x07, 0x60, 0x1d, 0x80, 0xb1, 0x7f, 0x9c, 0x03, 0x13, 0x6a, 0x0b,
+ 0x17, 0xb8, 0xd1, 0xeb, 0x17, 0xff, 0xef, 0x75, 0xbb, 0xff, 0x7f, 0xb9,
+ 0x33, 0x68, 0xd5, 0x8a, 0x81, 0xfc, 0x9c, 0x82, 0xff, 0xff, 0xe1, 0xe0,
+ 0xff, 0x84, 0x03, 0xe1, 0xa6, 0x6f, 0xf7, 0xd3, 0xc9, 0xd6, 0x2f, 0xfe,
+ 0x68, 0x60, 0xc9, 0xdb, 0xf2, 0x75, 0x8b, 0x9b, 0xeb, 0x15, 0xf3, 0xd9,
+ 0xf2, 0x15, 0xc1, 0x6e, 0xb1, 0x7f, 0xc3, 0x60, 0xf4, 0x4f, 0x26, 0xac,
+ 0x5f, 0x4e, 0x17, 0xbb, 0xd3, 0xd4, 0x18, 0xd5, 0xee, 0x43, 0x75, 0x8b,
+ 0xff, 0x7b, 0x53, 0x9d, 0x66, 0xb3, 0xcb, 0x17, 0xbf, 0x9d, 0x8c, 0x3d,
+ 0xee, 0x87, 0xeb, 0x88, 0xd1, 0xf4, 0x26, 0xaa, 0x55, 0x2f, 0x31, 0x17,
+ 0xa1, 0x9a, 0x28, 0xd1, 0xef, 0xff, 0x16, 0x79, 0xe0, 0xc5, 0x9e, 0xfb,
+ 0xac, 0x5f, 0x00, 0x3e, 0xbb, 0xd5, 0x8b, 0xf8, 0x9b, 0xa8, 0x3e, 0x2c,
+ 0x5f, 0xe2, 0x01, 0x67, 0xbf, 0x86, 0x22, 0x7f, 0x11, 0xfe, 0x57, 0x7f,
+ 0x11, 0x81, 0xeb, 0xec, 0xb1, 0x7e, 0xd0, 0x0e, 0xfc, 0x58, 0xbf, 0xe6,
+ 0x81, 0x92, 0xe3, 0xc3, 0xac, 0x56, 0x1f, 0x10, 0x8a, 0x69, 0xd3, 0x09,
+ 0x65, 0x62, 0x84, 0x95, 0xff, 0xd0, 0x6e, 0x72, 0x5f, 0x82, 0x89, 0x96,
+ 0x2f, 0xf9, 0xc1, 0xb7, 0xe7, 0x82, 0xe2, 0xc5, 0xe7, 0x20, 0x2c, 0x53,
+ 0xa2, 0x73, 0x48, 0xa7, 0x3b, 0xbf, 0x66, 0x9b, 0xa0, 0x96, 0x2f, 0xe7,
+ 0xcd, 0xe7, 0xdc, 0x58, 0xb4, 0x16, 0x2f, 0xff, 0x60, 0xf4, 0xe2, 0xd8,
+ 0x7f, 0x92, 0xd9, 0x62, 0xff, 0xbe, 0xdc, 0x72, 0x29, 0xe9, 0x62, 0xc1,
+ 0x12, 0x21, 0x38, 0x99, 0x52, 0x8b, 0xfc, 0x84, 0xb5, 0xff, 0xf4, 0xff,
+ 0x99, 0xb8, 0xf3, 0x41, 0x37, 0xe2, 0x58, 0xad, 0x8f, 0xe4, 0x04, 0xd5,
+ 0xb2, 0x76, 0x64, 0x55, 0xc8, 0xd9, 0xaf, 0xf4, 0x44, 0xc1, 0x7b, 0x3e,
+ 0xb1, 0x7b, 0xf9, 0xba, 0xc5, 0xe0, 0x82, 0x09, 0x22, 0xfe, 0x04, 0x96,
+ 0x75, 0xe4, 0x88, 0xc3, 0x43, 0x46, 0x22, 0xd6, 0x38, 0xd4, 0x33, 0xfb,
+ 0xe6, 0xd9, 0x89, 0x62, 0xff, 0xfe, 0xef, 0xcc, 0xdf, 0xee, 0x31, 0xe0,
+ 0x46, 0x7b, 0x99, 0xb2, 0xc5, 0x7d, 0x17, 0xde, 0x35, 0x11, 0x15, 0xfd,
+ 0xf9, 0xdc, 0x98, 0xeb, 0x17, 0xf8, 0xbb, 0x6d, 0x86, 0xe6, 0x96, 0x2b,
+ 0x0f, 0x95, 0xcb, 0xaf, 0x6d, 0xed, 0x2c, 0x54, 0xae, 0x30, 0x3c, 0x7c,
+ 0x4d, 0x1d, 0x57, 0x21, 0x2a, 0x19, 0x05, 0xff, 0xf9, 0xb5, 0x2e, 0x39,
+ 0x26, 0x07, 0x25, 0xc6, 0xb1, 0x7f, 0x43, 0x91, 0x42, 0x76, 0x58, 0xbe,
+ 0x1b, 0x31, 0xab, 0x14, 0xb1, 0x7b, 0x3b, 0x63, 0x9a, 0xf0, 0x88, 0xef,
+ 0xff, 0xbd, 0xf9, 0xe6, 0x3f, 0xb8, 0xe5, 0xd4, 0x16, 0x2f, 0xf4, 0x9d,
+ 0xfd, 0xa1, 0x1d, 0x62, 0x9d, 0x10, 0x84, 0xa1, 0x5b, 0xa7, 0x15, 0xd2,
+ 0x97, 0xd8, 0x3b, 0xf8, 0x5b, 0xdf, 0x7f, 0x93, 0xa5, 0x8b, 0xfe, 0x81,
+ 0x49, 0x91, 0xcd, 0xb7, 0x16, 0x2f, 0xfd, 0xbf, 0xdc, 0x6d, 0x02, 0x13,
+ 0x2c, 0x5f, 0xc3, 0x33, 0x3f, 0x9b, 0xac, 0x57, 0x48, 0xad, 0xd1, 0xf1,
+ 0x1f, 0xdf, 0xfb, 0x3f, 0xbb, 0xc8, 0x0f, 0x30, 0x58, 0xa9, 0x4c, 0xfd,
+ 0xe1, 0xa1, 0xa3, 0x0b, 0xff, 0xe3, 0x03, 0x39, 0x9f, 0x73, 0x07, 0xa2,
+ 0x60, 0x96, 0x2f, 0xf4, 0xf3, 0x02, 0x0c, 0xbc, 0xb1, 0x58, 0x88, 0xb0,
+ 0xd5, 0xaa, 0x5d, 0x9b, 0x56, 0xd0, 0x86, 0x84, 0xf4, 0xc0, 0xe3, 0x25,
+ 0xc8, 0x62, 0xef, 0x1e, 0x37, 0x50, 0xb0, 0x7a, 0x45, 0x8c, 0x51, 0x8e,
+ 0xea, 0x78, 0x14, 0xf3, 0x9b, 0x3f, 0x9c, 0x3e, 0x65, 0x30, 0x1a, 0x14,
+ 0xb0, 0xbe, 0x47, 0xe1, 0xe9, 0xd2, 0xf1, 0x47, 0xcd, 0xda, 0x38, 0x90,
+ 0xe1, 0x7f, 0x7f, 0xce, 0x5b, 0x31, 0x7b, 0x0e, 0xb1, 0x7b, 0x71, 0x74,
+ 0xb1, 0x74, 0x81, 0x62, 0xb0, 0xfb, 0xd8, 0xe3, 0xc4, 0x17, 0xff, 0x1a,
+ 0x1f, 0x9f, 0x85, 0x9d, 0x9c, 0x6b, 0x17, 0xf1, 0x60, 0xfe, 0xc1, 0x2c,
+ 0x56, 0x8f, 0xd8, 0xe9, 0x17, 0xff, 0xfe, 0x2c, 0x70, 0x19, 0xf6, 0xf7,
+ 0x85, 0xb1, 0x81, 0xeb, 0x59, 0xb2, 0xc5, 0xf3, 0x90, 0x38, 0xb1, 0x78,
+ 0x98, 0xeb, 0x17, 0xe2, 0x7f, 0xb4, 0x7a, 0xc5, 0xfb, 0xef, 0xc9, 0x82,
+ 0xc5, 0xff, 0xfe, 0xe6, 0x7d, 0xf8, 0x2d, 0x83, 0x9d, 0xa4, 0x07, 0x9f,
+ 0x2c, 0x5f, 0xff, 0xef, 0x16, 0x01, 0x88, 0x03, 0xfc, 0xe9, 0xe7, 0xaf,
+ 0x2c, 0x5e, 0xe3, 0xe9, 0x91, 0xd9, 0xc2, 0x80, 0xd9, 0x2f, 0xe1, 0xff,
+ 0x3d, 0x1d, 0x8b, 0x16, 0x78, 0x2a, 0x38, 0xdd, 0xcb, 0xe4, 0x44, 0x39,
+ 0xe8, 0xc5, 0x82, 0x41, 0xbf, 0xb4, 0x37, 0x80, 0xb4, 0xb1, 0x7f, 0xff,
+ 0x10, 0xfe, 0xcf, 0xe0, 0x39, 0x43, 0x98, 0x40, 0x58, 0xa9, 0x56, 0x8f,
+ 0xf9, 0x4b, 0x4c, 0xca, 0x22, 0xfb, 0xfb, 0xf3, 0xb7, 0xe7, 0x65, 0x8b,
+ 0xff, 0xff, 0x33, 0x6d, 0xef, 0xbc, 0x83, 0xc6, 0xc9, 0x0c, 0x50, 0x84,
+ 0xac, 0x54, 0x11, 0x3b, 0xe3, 0x0b, 0xfc, 0x46, 0xf1, 0xf4, 0xd0, 0x58,
+ 0xbe, 0x26, 0xeb, 0xcb, 0x17, 0xfd, 0xe6, 0xeb, 0x21, 0xf9, 0xd2, 0xc5,
+ 0xec, 0x20, 0x2c, 0x5f, 0xdb, 0xcf, 0x45, 0x21, 0x2c, 0x5f, 0xef, 0x19,
+ 0x14, 0x1b, 0x5b, 0x2c, 0x5f, 0xe8, 0x0f, 0xe2, 0x38, 0xf1, 0x62, 0xff,
+ 0xee, 0x81, 0xb9, 0x66, 0xc2, 0xea, 0x1c, 0x58, 0xbf, 0xec, 0xeb, 0x8d,
+ 0x1e, 0x79, 0x75, 0x8b, 0xc1, 0xc7, 0x62, 0xc5, 0x62, 0x37, 0x1c, 0xd7,
+ 0x49, 0x40, 0x3c, 0xbe, 0xcf, 0x45, 0x05, 0x8b, 0xff, 0xbb, 0x8a, 0x7b,
+ 0xb8, 0xc4, 0x18, 0x38, 0xb1, 0x69, 0x58, 0xaf, 0xa2, 0x01, 0x89, 0x3c,
+ 0x97, 0x73, 0xca, 0xc5, 0xff, 0xb3, 0xd3, 0xae, 0x7e, 0x4b, 0xcb, 0x90,
+ 0x20, 0xbf, 0xb3, 0x5b, 0xb3, 0x6e, 0xa9, 0x02, 0x08, 0xc3, 0xcb, 0xbd,
+ 0x23, 0x75, 0x8a, 0x93, 0xec, 0xe2, 0x85, 0xff, 0x88, 0xb0, 0xd6, 0xc3,
+ 0xb1, 0x2c, 0x5d, 0xd8, 0x6b, 0x17, 0xbb, 0x49, 0xd6, 0x2f, 0x07, 0x24,
+ 0xb1, 0x7d, 0xd7, 0x33, 0x4b, 0x17, 0xed, 0xb3, 0x53, 0x05, 0x8b, 0xed,
+ 0x69, 0xc2, 0x58, 0xa3, 0x9e, 0x6f, 0xca, 0x6a, 0x51, 0x26, 0xce, 0x37,
+ 0xf4, 0x78, 0xc2, 0x62, 0x82, 0xc5, 0x4a, 0x6f, 0x1b, 0x1e, 0x60, 0xd3,
+ 0x8f, 0x94, 0x2c, 0x04, 0x43, 0x7f, 0xf7, 0xf7, 0x1e, 0x69, 0xf3, 0xb7,
+ 0xc4, 0xb1, 0x7f, 0x6a, 0x7f, 0x2f, 0xdf, 0xac, 0x53, 0x1f, 0xd0, 0x69,
+ 0x17, 0xff, 0xff, 0xa4, 0xb7, 0xe4, 0x97, 0xb9, 0x82, 0x38, 0x7c, 0x6d,
+ 0x4e, 0xf8, 0x4b, 0x17, 0xff, 0xa2, 0x83, 0x97, 0xa4, 0x11, 0x13, 0xc4,
+ 0xb1, 0x71, 0x44, 0xb1, 0x43, 0x3e, 0x4c, 0x4c, 0xbd, 0xde, 0xc7, 0x77,
+ 0xd5, 0x62, 0xfe, 0xcf, 0x33, 0x43, 0x8b, 0x17, 0x67, 0x23, 0x63, 0xdb,
+ 0x22, 0xea, 0x94, 0x56, 0x93, 0xe5, 0xff, 0xfa, 0x7d, 0xf6, 0x8b, 0x8c,
+ 0xfb, 0x93, 0x66, 0xeb, 0x17, 0x31, 0xd6, 0x2f, 0xe3, 0xcb, 0xef, 0x20,
+ 0x58, 0xa8, 0xf3, 0xc5, 0xf0, 0xbd, 0x4b, 0x22, 0x87, 0x63, 0x4c, 0x23,
+ 0x34, 0xeb, 0x71, 0xce, 0x8c, 0x35, 0x18, 0xa7, 0xe1, 0x76, 0xc5, 0xe0,
+ 0x86, 0x69, 0x47, 0x33, 0xc8, 0x6a, 0x78, 0x8b, 0xb4, 0x71, 0x31, 0xc4,
+ 0x3d, 0xd0, 0x9b, 0xbf, 0xc4, 0x26, 0x89, 0x9b, 0x65, 0x8b, 0x41, 0x62,
+ 0xf4, 0xe8, 0x0b, 0x14, 0x33, 0x5e, 0xe2, 0x57, 0x9b, 0x5b, 0x2c, 0x50,
+ 0xd1, 0x43, 0xf6, 0x30, 0x88, 0x2f, 0x44, 0xe1, 0x2c, 0x5f, 0x9f, 0x45,
+ 0x9b, 0x2c, 0x53, 0x9e, 0x3f, 0xc7, 0xee, 0xe7, 0xd6, 0x2f, 0xfb, 0x68,
+ 0x9f, 0xfe, 0x9c, 0xd9, 0x62, 0xb4, 0x7e, 0xa0, 0x21, 0x21, 0x8b, 0xf6,
+ 0xa7, 0x7c, 0x25, 0x8a, 0xc3, 0xd6, 0x62, 0xeb, 0xfb, 0xf9, 0xef, 0x39,
+ 0xd6, 0x2f, 0xfe, 0xe0, 0xc9, 0xf6, 0x0f, 0x45, 0x38, 0xb1, 0x7f, 0x78,
+ 0x3c, 0xfb, 0x74, 0xb1, 0x7b, 0x80, 0x65, 0x8a, 0xe9, 0x18, 0x1f, 0x2e,
+ 0x24, 0x5f, 0x18, 0x5f, 0xf1, 0x6d, 0x9a, 0x01, 0x08, 0x0b, 0x17, 0xf6,
+ 0x76, 0xd6, 0x05, 0xe5, 0x8b, 0xf8, 0x26, 0x1c, 0xf5, 0xc5, 0x8a, 0x23,
+ 0xe1, 0xe1, 0x8d, 0xfd, 0x9d, 0x7b, 0x5a, 0x95, 0x8b, 0xff, 0xb8, 0x4d,
+ 0xe6, 0x38, 0x73, 0xb6, 0x2c, 0x50, 0xcf, 0xd3, 0x85, 0xf5, 0x29, 0xc7,
+ 0xb9, 0xeb, 0x42, 0x6c, 0x50, 0x95, 0xbf, 0xe6, 0x7f, 0x31, 0xd8, 0x80,
+ 0xb1, 0x7b, 0xb7, 0xf1, 0x62, 0xdb, 0xfc, 0xf5, 0x83, 0x37, 0xbe, 0x17,
+ 0xa4, 0x96, 0x2b, 0x0f, 0x33, 0x85, 0x57, 0xee, 0xc3, 0xfc, 0xf1, 0x62,
+ 0xc7, 0x58, 0xbf, 0xbc, 0x3f, 0x89, 0xb8, 0xb0, 0x19, 0x65, 0x6d, 0xd6,
+ 0x2a, 0x4f, 0x4b, 0x73, 0xfb, 0xbb, 0xdd, 0xd6, 0x2f, 0xfe, 0xcd, 0xff,
+ 0x3f, 0xcd, 0x6a, 0x4d, 0x58, 0xb8, 0x12, 0xb1, 0x61, 0xe8, 0xf7, 0x40,
+ 0x8d, 0x5a, 0x45, 0x19, 0x3d, 0xdf, 0x14, 0xf4, 0x05, 0x8a, 0x73, 0xc5,
+ 0x0c, 0x8a, 0xff, 0x09, 0x87, 0xf9, 0xf7, 0x16, 0x2f, 0x8b, 0x3b, 0x62,
+ 0xc5, 0xcd, 0xb7, 0x8f, 0x5c, 0x33, 0x4b, 0xf1, 0xcd, 0x35, 0xe2, 0x58,
+ 0xb1, 0xab, 0x17, 0x74, 0x05, 0x8b, 0xe6, 0xf4, 0xe2, 0xc5, 0x49, 0xe6,
+ 0xb8, 0x9f, 0xc6, 0x6f, 0xf6, 0x69, 0xc0, 0x76, 0x82, 0xc5, 0xce, 0x4b,
+ 0x17, 0xfd, 0x24, 0x68, 0xde, 0x02, 0xd2, 0xc5, 0x82, 0x58, 0xa1, 0x9f,
+ 0x19, 0xc5, 0x83, 0x3a, 0xbf, 0x4c, 0x50, 0x98, 0xf5, 0x8b, 0xff, 0x69,
+ 0xcd, 0x3b, 0x7b, 0x82, 0x82, 0xc5, 0xe2, 0x16, 0xcb, 0x17, 0xb6, 0x29,
+ 0x58, 0xb7, 0xd6, 0x2f, 0xa4, 0x8d, 0x8e, 0x58, 0xbe, 0x68, 0x61, 0x2c,
+ 0x56, 0xe7, 0x8f, 0xf2, 0x6b, 0xf9, 0xfc, 0x59, 0xf7, 0x58, 0xb9, 0xe2,
+ 0x58, 0xbe, 0xee, 0x9d, 0x1a, 0xb1, 0x6f, 0x98, 0x88, 0xe9, 0x23, 0x62,
+ 0xce, 0xe1, 0x8b, 0xfe, 0x9e, 0x7d, 0xf5, 0xa6, 0x82, 0xc5, 0x61, 0xff,
+ 0x12, 0x2d, 0x82, 0x31, 0x59, 0x00, 0xcb, 0x72, 0x12, 0xda, 0x30, 0x39,
+ 0x67, 0xd0, 0x58, 0x7b, 0x83, 0xbe, 0x8d, 0x96, 0xa5, 0x70, 0xa9, 0xa5,
+ 0xcc, 0xdf, 0xd3, 0xb7, 0xb9, 0x9e, 0x58, 0xa9, 0x65, 0x1e, 0x42, 0x53,
+ 0x7e, 0x43, 0x9d, 0xc8, 0x75, 0x08, 0xff, 0xc6, 0x14, 0xcf, 0x25, 0x38,
+ 0xb2, 0x11, 0x5d, 0xf3, 0x3f, 0x69, 0x58, 0xbf, 0xf0, 0x7a, 0xd4, 0xe1,
+ 0x67, 0x5c, 0x58, 0xbf, 0x38, 0xc7, 0x84, 0xb1, 0x43, 0x44, 0x57, 0x44,
+ 0x7c, 0x40, 0xbf, 0xff, 0xfb, 0x3d, 0x27, 0x1e, 0x7a, 0x70, 0xa0, 0x59,
+ 0xd4, 0x27, 0x3c, 0xb1, 0x7f, 0x16, 0x76, 0x2c, 0xe2, 0xc5, 0xfe, 0x16,
+ 0xb6, 0xc1, 0x17, 0x96, 0x2f, 0xdf, 0xce, 0x73, 0x0c, 0x3e, 0x3c, 0x2e,
+ 0xa2, 0x4c, 0x43, 0xd0, 0xd2, 0xbf, 0xe7, 0x39, 0x67, 0x8c, 0xcc, 0x58,
+ 0xbf, 0xef, 0xce, 0xbc, 0x53, 0x9d, 0x2c, 0x5f, 0xff, 0xf3, 0xed, 0x30,
+ 0xe6, 0xb4, 0xfd, 0x45, 0x06, 0xd1, 0xf3, 0xa5, 0x8b, 0xfd, 0x2d, 0xb3,
+ 0x69, 0x83, 0x58, 0xbd, 0xfc, 0x21, 0xa3, 0x63, 0xe7, 0x3e, 0x6b, 0xac,
+ 0x55, 0x72, 0xf1, 0xa0, 0xfc, 0xa3, 0xd1, 0x88, 0x5f, 0xa7, 0x51, 0x73,
+ 0x65, 0x8b, 0xfe, 0xfc, 0xe6, 0xa1, 0xc1, 0x1d, 0x62, 0xff, 0xdf, 0x91,
+ 0x99, 0x31, 0xff, 0x6e, 0x2c, 0x5f, 0xfa, 0x61, 0xd7, 0x1f, 0xe4, 0xd0,
+ 0x58, 0xbf, 0x0f, 0x20, 0xe3, 0x58, 0xbf, 0xf3, 0x83, 0x3d, 0x3f, 0x93,
+ 0xe2, 0xc5, 0x6c, 0x9a, 0x66, 0xe5, 0x6e, 0x74, 0x74, 0x31, 0x1f, 0xc7,
+ 0x14, 0x5c, 0xfc, 0x58, 0xbc, 0x10, 0xb8, 0xb1, 0x7f, 0xb6, 0x6f, 0x00,
+ 0x32, 0x82, 0xc5, 0xfa, 0x2e, 0x77, 0xdf, 0x7c, 0x8d, 0x16, 0x2a, 0x51,
+ 0x25, 0x83, 0xe2, 0x36, 0xbf, 0xdf, 0x7d, 0x69, 0xcb, 0x75, 0x8b, 0xff,
+ 0x43, 0x91, 0xb7, 0x30, 0x9a, 0x1c, 0x58, 0xbd, 0x30, 0x35, 0x62, 0xfd,
+ 0x9c, 0xdb, 0x02, 0x58, 0xbf, 0xb7, 0x14, 0xef, 0xfc, 0x58, 0xb9, 0xf7,
+ 0x58, 0xa3, 0x11, 0x21, 0x01, 0xec, 0x2a, 0x8e, 0x30, 0xa3, 0x53, 0x48,
+ 0xe8, 0xd3, 0xd0, 0xd4, 0xbf, 0xf7, 0xbe, 0xd0, 0x71, 0xfe, 0x60, 0xb1,
+ 0x4c, 0x7e, 0xe4, 0x71, 0x7f, 0x06, 0x7e, 0x04, 0xdd, 0x2c, 0x54, 0xae,
+ 0x6c, 0xe4, 0x72, 0xa6, 0xae, 0x6a, 0x15, 0x2d, 0x1f, 0x6f, 0x88, 0x2f,
+ 0x05, 0x9f, 0x58, 0xbf, 0xfe, 0xf6, 0x84, 0x39, 0x33, 0x53, 0xb3, 0x6b,
+ 0x75, 0x8b, 0xff, 0x16, 0x6c, 0x59, 0xef, 0xb8, 0x4b, 0x17, 0x60, 0x46,
+ 0x22, 0x4f, 0x75, 0x4b, 0xec, 0x06, 0xa5, 0x62, 0xb6, 0x3d, 0x3f, 0x98,
+ 0xdf, 0xfe, 0xfb, 0xef, 0x2f, 0xef, 0xc8, 0x59, 0xf5, 0x8b, 0xfd, 0xe7,
+ 0xfe, 0x16, 0x71, 0x62, 0xb7, 0x3f, 0xd0, 0xd2, 0xef, 0x42, 0x18, 0xb1,
+ 0x74, 0x86, 0xb1, 0x5d, 0x1b, 0x56, 0x1d, 0xbf, 0xd3, 0x00, 0xf8, 0x00,
+ 0xf7, 0x58, 0xa7, 0x3d, 0x9f, 0x10, 0xd8, 0xa0, 0x8d, 0x31, 0xc2, 0xca,
+ 0xff, 0xec, 0xfc, 0xe6, 0xdb, 0x39, 0x4c, 0x16, 0x2a, 0x09, 0xf2, 0x64,
+ 0x6e, 0x71, 0xc5, 0xb7, 0xb5, 0x9f, 0x58, 0xbd, 0xc7, 0x3a, 0xc5, 0x68,
+ 0xdd, 0x78, 0x76, 0xfe, 0xfb, 0x7b, 0xec, 0x75, 0x8b, 0xe3, 0x64, 0xa0,
+ 0xb1, 0x76, 0x74, 0xb1, 0x73, 0xec, 0xb1, 0x52, 0x8a, 0x27, 0x21, 0xf1,
+ 0x70, 0x64, 0x7d, 0xc3, 0x17, 0xfb, 0x85, 0x87, 0x3b, 0xf9, 0x62, 0xfb,
+ 0xd8, 0x28, 0x2c, 0x5f, 0xfd, 0xf7, 0x92, 0x31, 0x8a, 0x0e, 0x75, 0x8b,
+ 0xd1, 0x38, 0x4b, 0x17, 0xd3, 0xdc, 0xfa, 0x58, 0xa7, 0x3c, 0x42, 0x1f,
+ 0xbf, 0xf3, 0x74, 0x1f, 0x9f, 0x52, 0x2e, 0xfd, 0x62, 0xe0, 0xf6, 0x58,
+ 0xa3, 0x9f, 0x07, 0x91, 0xaf, 0xcd, 0xc2, 0x98, 0x96, 0x2f, 0xdf, 0x11,
+ 0x4e, 0xcb, 0x17, 0x76, 0xd2, 0xc5, 0xc5, 0xa5, 0x8b, 0xff, 0xf0, 0xb6,
+ 0x29, 0xcf, 0xc6, 0x4f, 0xb3, 0xe2, 0xd2, 0xc5, 0xee, 0x07, 0xc3, 0x15,
+ 0x02, 0x0e, 0x10, 0xf9, 0x08, 0x03, 0x48, 0x9c, 0xa0, 0x8a, 0x78, 0x34,
+ 0x18, 0xbd, 0x6e, 0xab, 0xa9, 0x8c, 0xfd, 0x28, 0x9e, 0xe2, 0x09, 0x62,
+ 0xfd, 0xc3, 0xe7, 0xb8, 0xb1, 0x7f, 0x03, 0x53, 0xbe, 0x12, 0xc5, 0xff,
+ 0x8d, 0xcf, 0x3f, 0xf3, 0xd3, 0xa5, 0x8a, 0x93, 0xed, 0x72, 0xeb, 0xf3,
+ 0x40, 0x9e, 0x56, 0x2f, 0x9b, 0xce, 0x05, 0x8b, 0xe2, 0xf6, 0x12, 0xc5,
+ 0x7c, 0xf0, 0xd8, 0x8a, 0xfe, 0xc3, 0xe6, 0x11, 0xab, 0x14, 0xb1, 0x7f,
+ 0x7b, 0x99, 0xdb, 0xee, 0xb1, 0x46, 0x9b, 0xc6, 0x0c, 0xb1, 0xa3, 0x44,
+ 0x51, 0x34, 0xd4, 0xa3, 0x51, 0xa1, 0x57, 0x7f, 0xc4, 0xc1, 0x45, 0x06,
+ 0xd4, 0x16, 0x2f, 0xe7, 0xd6, 0x76, 0x98, 0xf5, 0x8a, 0x88, 0xfb, 0x7e,
+ 0x77, 0x7f, 0x3e, 0xb5, 0x38, 0x4b, 0x17, 0xfd, 0x30, 0xe6, 0x6e, 0x53,
+ 0xa5, 0x8a, 0x34, 0xf9, 0x74, 0x59, 0x67, 0x58, 0xbf, 0xb8, 0xfa, 0xdf,
+ 0xf8, 0xb1, 0x7f, 0xc4, 0xdd, 0x7d, 0xe4, 0xbc, 0xb1, 0x7f, 0x60, 0x00,
+ 0xdd, 0x41, 0x62, 0xf1, 0x31, 0xb8, 0x8c, 0xad, 0xc8, 0xfa, 0x11, 0xf9,
+ 0x79, 0x1c, 0x51, 0x8c, 0xbb, 0x79, 0x95, 0xd1, 0x08, 0xc5, 0x72, 0x59,
+ 0xb6, 0xe7, 0x2e, 0x31, 0xa8, 0x4b, 0x1c, 0x80, 0xa3, 0x3d, 0xe4, 0x24,
+ 0xc5, 0x1a, 0x95, 0xff, 0xf6, 0xd9, 0xad, 0x9f, 0xd0, 0xcd, 0x69, 0xa0,
+ 0xb1, 0x71, 0xbe, 0x58, 0xbf, 0xfc, 0xff, 0x9f, 0xe7, 0x5c, 0x7f, 0xc8,
+ 0xd6, 0x2f, 0x6e, 0xe3, 0x58, 0xbe, 0xd8, 0xa7, 0x65, 0x8b, 0xb3, 0x65,
+ 0x8b, 0x14, 0x9b, 0xcc, 0x24, 0xbe, 0xd3, 0xe7, 0xd6, 0x2f, 0xf8, 0xed,
+ 0xd7, 0x74, 0xee, 0x73, 0xac, 0x5f, 0x4e, 0x07, 0x1a, 0x2c, 0x5f, 0xa4,
+ 0x71, 0xbc, 0x6f, 0xde, 0x2c, 0x5b, 0x58, 0x89, 0xf2, 0x3f, 0x0c, 0xa2,
+ 0xff, 0xff, 0x71, 0xf9, 0xc9, 0xe6, 0xe4, 0xdb, 0x49, 0x4c, 0x5c, 0x58,
+ 0xac, 0x55, 0x16, 0x6a, 0x96, 0xe3, 0x3d, 0x25, 0x3a, 0xd6, 0x89, 0x1a,
+ 0x18, 0x3e, 0x35, 0xbf, 0x7d, 0xe3, 0x9c, 0xd5, 0x8b, 0xec, 0x03, 0xf6,
+ 0x58, 0xbe, 0x00, 0x04, 0x05, 0x8a, 0xdc, 0xfd, 0x08, 0xb0, 0x32, 0x4b,
+ 0xe1, 0x6b, 0xce, 0xb1, 0x7e, 0x28, 0x73, 0x60, 0x2c, 0x5f, 0xff, 0x73,
+ 0xf8, 0x7e, 0x48, 0xd8, 0x7f, 0x11, 0xd6, 0x2f, 0xba, 0xf7, 0xf1, 0x62,
+ 0xfd, 0x09, 0xf7, 0xf1, 0x62, 0xb0, 0xf3, 0x3c, 0x49, 0x52, 0x8b, 0xe6,
+ 0x84, 0xed, 0xff, 0xc0, 0x9e, 0x1e, 0x5f, 0x5a, 0x70, 0x96, 0x2f, 0x33,
+ 0x41, 0x62, 0xff, 0x3f, 0x9e, 0x19, 0xd7, 0x96, 0x28, 0x69, 0xe3, 0x61,
+ 0x1e, 0xf0, 0xe8, 0x72, 0x60, 0x22, 0xf7, 0x0e, 0x5f, 0xf6, 0xa0, 0x4f,
+ 0x0e, 0xbd, 0xdf, 0x55, 0x8b, 0xfb, 0x7c, 0x0f, 0xb9, 0xa0, 0xb1, 0x7e,
+ 0x3b, 0xfb, 0xd2, 0xb1, 0x79, 0xf0, 0x25, 0x8b, 0xe7, 0xe6, 0x0f, 0x11,
+ 0x77, 0xba, 0x1b, 0x99, 0x91, 0x45, 0xff, 0x81, 0xe9, 0xc2, 0xdf, 0x3a,
+ 0xf2, 0xc5, 0xfb, 0x98, 0x79, 0x8f, 0x58, 0xad, 0x1f, 0x59, 0x20, 0x5f,
+ 0xfa, 0x60, 0x03, 0xc8, 0x5c, 0x86, 0xcb, 0x17, 0xff, 0x67, 0x50, 0xcf,
+ 0xbe, 0x89, 0xe5, 0x62, 0xff, 0xa6, 0x79, 0xc7, 0xd6, 0x1d, 0x62, 0xa0,
+ 0x7f, 0x63, 0x43, 0xbe, 0x8f, 0xfe, 0x6c, 0xb1, 0x7f, 0xa4, 0x79, 0xe7,
+ 0xf8, 0x96, 0x2a, 0x4f, 0x68, 0x64, 0xf7, 0xfe, 0x87, 0x9f, 0x6d, 0x4c,
+ 0x1b, 0x4b, 0x17, 0xe2, 0xcd, 0x83, 0x82, 0xc5, 0xe7, 0xeb, 0x8b, 0x17,
+ 0x67, 0x96, 0x28, 0xd3, 0x6b, 0xf1, 0xea, 0x95, 0x47, 0x9b, 0x10, 0xc5,
+ 0x0b, 0xd3, 0xbe, 0x31, 0x0f, 0x10, 0x3c, 0xbf, 0x7f, 0x19, 0xce, 0x61,
+ 0x0d, 0x62, 0xff, 0xde, 0x0c, 0x12, 0x1c, 0x82, 0x40, 0xb1, 0x7f, 0xcf,
+ 0xad, 0x84, 0x03, 0x26, 0x3d, 0x62, 0xff, 0xf8, 0x9c, 0xd3, 0x64, 0x3f,
+ 0x3f, 0xdc, 0xbc, 0xb1, 0x7f, 0xf9, 0xbf, 0xf7, 0x2c, 0x00, 0x1e, 0x2e,
+ 0x2c, 0x54, 0x11, 0xb4, 0x73, 0xfe, 0xca, 0x37, 0xfe, 0xfb, 0x43, 0xc2,
+ 0x62, 0x07, 0x16, 0x2f, 0xff, 0xb9, 0xf7, 0xc3, 0xb7, 0x5c, 0xf7, 0xc5,
+ 0xd2, 0xc5, 0x7d, 0x12, 0x40, 0x3f, 0xbf, 0xef, 0xbe, 0xbd, 0xd6, 0xef,
+ 0xe5, 0x8b, 0xe6, 0xf7, 0xa5, 0x62, 0xfe, 0x6e, 0x39, 0x4f, 0x16, 0x2e,
+ 0xfb, 0x2c, 0x5f, 0x0d, 0x88, 0x18, 0x8a, 0x1d, 0xcf, 0x3e, 0x45, 0xdf,
+ 0x96, 0x56, 0x26, 0x38, 0x28, 0x62, 0x5f, 0xff, 0xc3, 0xc0, 0x47, 0x67,
+ 0xd9, 0xfc, 0x2d, 0x37, 0x6c, 0x58, 0xbf, 0xff, 0xf1, 0xd8, 0x81, 0x07,
+ 0xe0, 0x8f, 0xf7, 0x9f, 0x7c, 0x4c, 0x75, 0x8b, 0xff, 0xfc, 0x4c, 0x17,
+ 0xb3, 0xe6, 0x16, 0x7f, 0x9c, 0xc6, 0x25, 0x8b, 0xd0, 0xdb, 0x16, 0x2a,
+ 0x23, 0xfe, 0xe3, 0x05, 0xff, 0xd8, 0x16, 0xa5, 0xcb, 0x00, 0x77, 0x58,
+ 0xbf, 0xff, 0x3f, 0xa1, 0x24, 0x01, 0x89, 0xb5, 0x01, 0x9d, 0x62, 0xfc,
+ 0x42, 0x86, 0x71, 0x62, 0xe2, 0x95, 0x8b, 0xff, 0xc2, 0xf4, 0x1c, 0x1f,
+ 0x67, 0xf3, 0x1d, 0x62, 0xa0, 0x8d, 0xec, 0x56, 0xf9, 0x41, 0x0b, 0x5c,
+ 0x64, 0x7a, 0xc5, 0xff, 0xf9, 0x9f, 0xce, 0x3c, 0x1e, 0x79, 0xce, 0xfa,
+ 0x58, 0xbd, 0xc9, 0x3a, 0xc5, 0xee, 0xdf, 0x75, 0x8a, 0x81, 0xbc, 0x71,
+ 0xdb, 0xff, 0xd3, 0xb8, 0xf0, 0x3f, 0x3e, 0xa4, 0x5d, 0xfa, 0xc5, 0xe1,
+ 0x60, 0xd6, 0x2f, 0x69, 0xb8, 0x62, 0xab, 0x8d, 0x88, 0xf2, 0x32, 0x1d,
+ 0x1d, 0xfc, 0x71, 0xa1, 0x1e, 0x44, 0x11, 0xca, 0x36, 0xf4, 0xaf, 0x4d,
+ 0x42, 0x3e, 0x07, 0x28, 0x65, 0xf1, 0x4b, 0xa2, 0xbf, 0xf4, 0xf3, 0x7f,
+ 0xb8, 0xe7, 0x34, 0xb1, 0x50, 0x64, 0x40, 0x74, 0x5e, 0xf3, 0xf6, 0xba,
+ 0x5d, 0xba, 0x12, 0xb1, 0x7f, 0xef, 0xcf, 0xf3, 0xa0, 0x67, 0xb8, 0xb1,
+ 0x7a, 0x27, 0x3a, 0xc5, 0x0c, 0xf7, 0xb1, 0x02, 0xf9, 0xcd, 0x93, 0xac,
+ 0x5f, 0xfd, 0x83, 0x26, 0xdb, 0x9c, 0x62, 0x82, 0xc5, 0xd8, 0x52, 0x7c,
+ 0xe4, 0x47, 0x5b, 0x22, 0xcb, 0xd0, 0x88, 0xa6, 0x4d, 0x40, 0x51, 0x93,
+ 0xdf, 0xff, 0xfc, 0x64, 0x5f, 0x9d, 0x6c, 0x67, 0x00, 0xc4, 0x03, 0x33,
+ 0x79, 0xf7, 0x16, 0x2f, 0xcd, 0xee, 0x61, 0x2c, 0x56, 0xe8, 0xa0, 0x27,
+ 0x9a, 0x96, 0xc9, 0x90, 0x70, 0xec, 0xc8, 0xfd, 0xb7, 0x8c, 0x69, 0xe5,
+ 0x7c, 0x35, 0x23, 0xac, 0xa3, 0x99, 0x14, 0x32, 0x6c, 0x75, 0x8b, 0xda,
+ 0xd4, 0xac, 0x5e, 0xf8, 0xa3, 0xd6, 0x2f, 0xfb, 0x67, 0xdb, 0x98, 0x76,
+ 0xfa, 0xc5, 0xff, 0x42, 0x46, 0xe3, 0xc6, 0xfa, 0xc5, 0x9f, 0x47, 0xe7,
+ 0xe3, 0xbb, 0xf4, 0xec, 0xe5, 0xe5, 0x8b, 0xfe, 0x68, 0x4f, 0xf3, 0xd3,
+ 0x05, 0x8a, 0xd1, 0xf0, 0x7c, 0xa2, 0xff, 0xf7, 0x63, 0x33, 0xcf, 0xa9,
+ 0x17, 0xa1, 0x2b, 0x16, 0x3a, 0xc5, 0x39, 0xef, 0x86, 0x9b, 0x78, 0x0d,
+ 0xc5, 0x8b, 0xa3, 0x7e, 0xf1, 0x62, 0x86, 0x7c, 0x3d, 0x11, 0x70, 0x76,
+ 0xff, 0x43, 0xd8, 0x69, 0x49, 0xab, 0x17, 0xbb, 0xef, 0xbe, 0xbd, 0xe2,
+ 0xc5, 0xf8, 0xa4, 0x79, 0x12, 0xc5, 0xfd, 0x07, 0x03, 0x78, 0x4b, 0x17,
+ 0xdc, 0x16, 0x8d, 0x58, 0xbf, 0xf4, 0x04, 0x3c, 0xd7, 0x88, 0x5e, 0x58,
+ 0xbe, 0xc2, 0x6e, 0x2c, 0x5f, 0xa7, 0xfe, 0x98, 0x2c, 0x5f, 0x43, 0x01,
+ 0x1a, 0x96, 0x2f, 0x0b, 0xdc, 0x8d, 0xd3, 0x5f, 0x93, 0x2c, 0x28, 0xe8,
+ 0xba, 0x22, 0x5f, 0xa0, 0x00, 0x86, 0x38, 0xa2, 0xff, 0xf9, 0xce, 0xc3,
+ 0xe6, 0x13, 0x75, 0xac, 0x3a, 0xc5, 0x0d, 0x1b, 0x7f, 0x84, 0x65, 0xef,
+ 0x87, 0xa5, 0x8b, 0xfd, 0x24, 0xdf, 0x11, 0x6c, 0xb1, 0x7f, 0xfe, 0xfb,
+ 0xeb, 0xed, 0x24, 0x6b, 0x44, 0xcd, 0xb2, 0xc5, 0xf6, 0x38, 0x38, 0xb1,
+ 0x7c, 0xfc, 0x98, 0x61, 0xfc, 0x69, 0x5a, 0xf6, 0xc3, 0x95, 0x8b, 0xf1,
+ 0x9d, 0x72, 0x60, 0xb1, 0x7b, 0x4d, 0xba, 0xc5, 0xe3, 0xcf, 0xd6, 0x2f,
+ 0x4c, 0x3b, 0xd5, 0x8b, 0x00, 0x67, 0xbb, 0x83, 0xc4, 0x3b, 0x78, 0x62,
+ 0x95, 0x8b, 0xfe, 0x9e, 0x4f, 0xb9, 0x85, 0x05, 0x8b, 0xff, 0x69, 0xc1,
+ 0xfc, 0x3c, 0xc7, 0x62, 0xc5, 0xe6, 0x21, 0xac, 0x5f, 0xf9, 0x8d, 0x92,
+ 0xdd, 0xbc, 0xc6, 0xac, 0x5f, 0x60, 0x23, 0xb3, 0xe7, 0xb9, 0xc1, 0xcb,
+ 0xff, 0xff, 0xd9, 0xb7, 0x24, 0xd6, 0xe7, 0xa1, 0x86, 0x9b, 0x9d, 0x7b,
+ 0x53, 0x9d, 0x2c, 0x5e, 0xd1, 0x41, 0x62, 0xff, 0xf0, 0xff, 0x83, 0x8f,
+ 0x72, 0x37, 0x59, 0xdc, 0xb1, 0x7f, 0xc4, 0x0f, 0x38, 0xf0, 0xa0, 0xb1,
+ 0x69, 0x31, 0x14, 0xd8, 0x3a, 0xca, 0x34, 0xea, 0xa1, 0x3e, 0x3a, 0xc7,
+ 0x05, 0x09, 0xde, 0x1d, 0x8a, 0x32, 0x3b, 0xdd, 0xff, 0xf1, 0x62, 0xfc,
+ 0x6b, 0x96, 0x76, 0x58, 0xae, 0xf5, 0x93, 0xfd, 0x1b, 0x09, 0x48, 0xec,
+ 0x21, 0x28, 0x38, 0x43, 0xe4, 0x38, 0xba, 0x30, 0x79, 0x4d, 0xf1, 0x14,
+ 0x1c, 0x7f, 0xf0, 0xab, 0x63, 0x70, 0x0f, 0x14, 0x22, 0x3d, 0x2a, 0xdc,
+ 0x4c, 0x21, 0x91, 0x5f, 0x1b, 0x25, 0xba, 0xc5, 0xc1, 0xf1, 0x62, 0xff,
+ 0xde, 0xe6, 0x44, 0xc0, 0xe6, 0x6c, 0xb1, 0x50, 0x3f, 0xed, 0x12, 0x10,
+ 0xcd, 0xfc, 0x26, 0xd4, 0x06, 0x75, 0x8b, 0xf6, 0x05, 0xe0, 0xce, 0xb1,
+ 0x7e, 0x33, 0xa8, 0x67, 0x96, 0x2f, 0xff, 0xf0, 0x72, 0x01, 0xfe, 0x75,
+ 0x84, 0xed, 0x0e, 0x67, 0x96, 0x2a, 0x08, 0x8b, 0xe1, 0x5d, 0xdc, 0xd9,
+ 0x62, 0xfe, 0x29, 0x0b, 0x52, 0x75, 0x8b, 0xff, 0xec, 0xf0, 0x80, 0x76,
+ 0x87, 0x33, 0xb4, 0x8d, 0x62, 0x86, 0x89, 0x9c, 0x19, 0x22, 0xea, 0xd2,
+ 0x3a, 0xbd, 0x0b, 0xcb, 0xff, 0xa7, 0x01, 0xc8, 0x3e, 0xb6, 0x10, 0x16,
+ 0x2f, 0xe0, 0x73, 0x5a, 0xc0, 0x96, 0x2e, 0xfb, 0xc4, 0x7e, 0xc4, 0x8d,
+ 0x7f, 0xd8, 0x73, 0x8b, 0x90, 0xdb, 0x75, 0x8b, 0xf8, 0x5a, 0x06, 0x7d,
+ 0x96, 0x2b, 0x74, 0x4c, 0x11, 0x6f, 0x0f, 0x6f, 0xb8, 0x76, 0x75, 0x8a,
+ 0x81, 0xe9, 0x78, 0xc2, 0xff, 0xf4, 0x0c, 0xd4, 0xf1, 0xe4, 0x80, 0x09,
+ 0x58, 0xa9, 0x3e, 0xc6, 0x22, 0xbf, 0xee, 0x66, 0x1a, 0x6b, 0x42, 0x56,
+ 0x2f, 0xef, 0xb3, 0xfa, 0x49, 0x62, 0xff, 0xf8, 0x0f, 0xa3, 0x4a, 0x70,
+ 0x2c, 0xe0, 0x8e, 0xb1, 0x52, 0x7f, 0xa6, 0x96, 0x5f, 0x87, 0x9c, 0x11,
+ 0xab, 0x17, 0xcc, 0x7c, 0x1a, 0xc5, 0xf8, 0x6c, 0x4d, 0xd9, 0x62, 0xe6,
+ 0xe2, 0xc5, 0x61, 0xe0, 0x68, 0xa6, 0xba, 0x4e, 0x1b, 0x50, 0xb7, 0x22,
+ 0x2f, 0x15, 0x76, 0x62, 0xbf, 0xef, 0xcf, 0x5e, 0x9f, 0xb4, 0x7a, 0xc5,
+ 0x2c, 0x5f, 0xf6, 0x9c, 0x5b, 0x00, 0x13, 0xdc, 0xb1, 0x7f, 0xda, 0xf7,
+ 0x9f, 0x5e, 0xcd, 0xd6, 0x2f, 0xff, 0x36, 0xb4, 0x23, 0x7d, 0x91, 0x41,
+ 0x80, 0xb1, 0x7f, 0xbc, 0xfa, 0x6f, 0xb1, 0xd6, 0x2e, 0x0e, 0x25, 0x8b,
+ 0x85, 0xa5, 0x8b, 0xfb, 0x35, 0xcf, 0xe6, 0xeb, 0x16, 0xec, 0xb1, 0x46,
+ 0x27, 0x6f, 0xdf, 0x67, 0xa3, 0x0c, 0xc3, 0xe3, 0x4e, 0xfa, 0x4d, 0xd1,
+ 0x9f, 0xc6, 0x88, 0x62, 0x38, 0xbe, 0xfa, 0x22, 0x93, 0xac, 0x5b, 0xa5,
+ 0x8b, 0xb0, 0x25, 0x8b, 0xbd, 0xe7, 0x35, 0x7e, 0x13, 0xa9, 0x4c, 0x47,
+ 0x21, 0x2e, 0xe9, 0xd7, 0xb6, 0x21, 0x2c, 0x5f, 0xf8, 0xfa, 0x9f, 0xbe,
+ 0xee, 0x4c, 0xb1, 0x68, 0x49, 0xee, 0x30, 0xf5, 0xe0, 0x82, 0x09, 0x52,
+ 0x08, 0xc1, 0x7f, 0xc5, 0xbe, 0x6b, 0x76, 0x6d, 0xd5, 0x20, 0x8c, 0x11,
+ 0x86, 0xca, 0xa2, 0x45, 0xbb, 0x2c, 0x5b, 0x65, 0x8b, 0xe3, 0x58, 0x80,
+ 0xb1, 0x79, 0x9f, 0xb9, 0x62, 0xa0, 0x7a, 0xae, 0x27, 0xf2, 0x3a, 0x96,
+ 0x54, 0xe8, 0xcb, 0xb0, 0xbd, 0xe3, 0xa0, 0x3c, 0x7e, 0x8d, 0x1d, 0x30,
+ 0x25, 0x8d, 0x0a, 0x34, 0x6e, 0xcf, 0x17, 0xff, 0xfd, 0xfc, 0xd4, 0xc3,
+ 0x9e, 0xfe, 0x76, 0xc1, 0xe8, 0x98, 0x25, 0x8b, 0xdc, 0x03, 0x2c, 0x5f,
+ 0xdf, 0xdd, 0xf9, 0x83, 0x58, 0xad, 0x8f, 0x33, 0x71, 0xdb, 0xfc, 0xc3,
+ 0xc7, 0xec, 0xc7, 0x58, 0xbf, 0xff, 0x6f, 0x84, 0x4f, 0x9a, 0x91, 0xfd,
+ 0x89, 0xd6, 0x2b, 0x48, 0x86, 0x11, 0xa5, 0xff, 0xff, 0xf9, 0xcf, 0x9c,
+ 0xc2, 0x17, 0xbf, 0x9d, 0x87, 0x3f, 0x79, 0xf7, 0xc4, 0xc7, 0x58, 0xbf,
+ 0xf0, 0xb7, 0xcd, 0x6d, 0x3f, 0x10, 0xd6, 0x2f, 0x03, 0xb1, 0xd6, 0x2f,
+ 0xb7, 0xfb, 0xec, 0xb1, 0x46, 0x1e, 0x2b, 0x10, 0x53, 0xa2, 0xa7, 0x90,
+ 0x87, 0xbf, 0x0e, 0x5c, 0xbc, 0xb1, 0x43, 0x55, 0xf9, 0x90, 0xb5, 0xd4,
+ 0x2a, 0xbe, 0x47, 0xe8, 0xcb, 0x02, 0x27, 0xbf, 0x3e, 0xa1, 0x1d, 0xe5,
+ 0x8b, 0xff, 0x9b, 0x9b, 0x4f, 0xf3, 0x70, 0xe3, 0x99, 0x62, 0x8e, 0x7e,
+ 0xc4, 0x59, 0x7f, 0xff, 0xfb, 0xf8, 0x2d, 0x1b, 0xf7, 0xea, 0x7c, 0x2f,
+ 0x96, 0x75, 0xe1, 0x37, 0x16, 0x2f, 0xfe, 0xce, 0x83, 0xf3, 0x90, 0xa1,
+ 0x9c, 0x58, 0xbf, 0xff, 0xff, 0xff, 0xff, 0xff, 0x61, 0x6c, 0x4c, 0x39,
+ 0x2d, 0xa7, 0x43, 0xc2, 0xcf, 0x71, 0xf7, 0xc2, 0x0f, 0x6c, 0xd4, 0xf0,
+ 0x98, 0xde, 0x63, 0x80, 0x02, 0x01, 0x30, 0xe4, 0xb6, 0x9d, 0x2c, 0x5f,
+ 0xb8, 0x69, 0xb9, 0x1e, 0xb1, 0x7d, 0xdd, 0x9d, 0x79, 0x62, 0xa4, 0xf5,
+ 0x58, 0xba, 0xfe, 0x81, 0x66, 0x0b, 0xbf, 0x58, 0xbf, 0xcd, 0xe8, 0x66,
+ 0xb3, 0x8b, 0x15, 0x2a, 0x8a, 0x71, 0x1b, 0xf1, 0xaf, 0x31, 0x01, 0x19,
+ 0x5f, 0xf9, 0xf7, 0xfe, 0x47, 0x07, 0xa9, 0x82, 0xc5, 0xf9, 0x80, 0x07,
+ 0xfa, 0xc5, 0xff, 0xd9, 0xdb, 0xde, 0x67, 0x22, 0x93, 0xac, 0x5d, 0x30,
+ 0xf9, 0xf6, 0x78, 0xa2, 0xbe, 0x8d, 0xd2, 0x85, 0x85, 0xfb, 0x7f, 0x1a,
+ 0xfb, 0xac, 0x5f, 0xfe, 0xfc, 0x97, 0x8c, 0xfb, 0x0f, 0xed, 0xa5, 0x8a,
+ 0x63, 0xf7, 0xe1, 0x65, 0xff, 0x67, 0x3f, 0x8c, 0x59, 0x1e, 0xb1, 0x76,
+ 0x6c, 0xb1, 0x7f, 0x83, 0x35, 0xfb, 0xa4, 0xa0, 0xb1, 0x7f, 0xc5, 0x8f,
+ 0xa2, 0x9e, 0xa0, 0xb1, 0x58, 0x8c, 0x2d, 0x1d, 0x7c, 0x61, 0x8e, 0x2f,
+ 0xff, 0xfb, 0xc2, 0xdb, 0x3e, 0xfe, 0xfe, 0x1f, 0x35, 0x0c, 0xeb, 0xcb,
+ 0x17, 0xf7, 0xdf, 0xff, 0x93, 0xac, 0x5f, 0xa0, 0x53, 0x9c, 0x58, 0xbc,
+ 0xc5, 0xb6, 0xe7, 0xab, 0xd1, 0x75, 0x41, 0x1e, 0x7e, 0x85, 0xf5, 0xfc,
+ 0x58, 0x6f, 0x1b, 0xeb, 0x17, 0xce, 0x6e, 0x0d, 0x62, 0xf1, 0xb8, 0x35,
+ 0x8b, 0xb0, 0xe6, 0x1e, 0x0b, 0x91, 0xd1, 0xd1, 0x39, 0xe6, 0xfb, 0xff,
+ 0xc7, 0xc3, 0x5f, 0x45, 0x9e, 0xf6, 0x6c, 0xb1, 0x7f, 0xfa, 0x28, 0x4e,
+ 0xc4, 0xc6, 0xf0, 0xa6, 0x0b, 0x14, 0xb1, 0x69, 0x01, 0xec, 0x71, 0x32,
+ 0xff, 0xc1, 0xe7, 0xd8, 0xf1, 0x81, 0x04, 0x12, 0xc5, 0xff, 0xfb, 0x37,
+ 0xfc, 0x90, 0xc9, 0xf6, 0xc2, 0x73, 0x56, 0x2b, 0x64, 0x4e, 0x41, 0x1e,
+ 0xff, 0xed, 0x80, 0xfd, 0x73, 0x7c, 0x72, 0xdd, 0x62, 0x98, 0xfb, 0x08,
+ 0x92, 0xa5, 0x3f, 0x28, 0x42, 0x8d, 0xa3, 0x2f, 0xbf, 0xff, 0x14, 0x83,
+ 0x9b, 0xfd, 0xf5, 0x11, 0x48, 0x38, 0xb1, 0x7f, 0xe7, 0x8b, 0x0a, 0x42,
+ 0xd4, 0x9d, 0x62, 0xf1, 0xf3, 0x8b, 0x15, 0x12, 0x2c, 0xf4, 0xae, 0x73,
+ 0xfb, 0xfa, 0x77, 0x6d, 0xf9, 0x05, 0x8b, 0xff, 0xfb, 0xdc, 0x93, 0x60,
+ 0xff, 0x62, 0xf4, 0x33, 0x58, 0xb1, 0x7f, 0xe7, 0xe6, 0x0c, 0xc6, 0x04,
+ 0x76, 0x2c, 0x5c, 0x2e, 0xcb, 0x17, 0xfa, 0x4f, 0xd7, 0xa7, 0x3a, 0x58,
+ 0xbf, 0xe7, 0xed, 0xf6, 0x86, 0xa4, 0xd5, 0x8b, 0xff, 0xa4, 0x19, 0xe9,
+ 0xdc, 0xa7, 0xdc, 0x58, 0xaf, 0xa2, 0x00, 0x8f, 0x2b, 0x13, 0x8e, 0xdd,
+ 0x6f, 0x48, 0x5f, 0x1a, 0xf4, 0x2d, 0x6f, 0xa6, 0x1c, 0x8e, 0x58, 0xbf,
+ 0xbc, 0x61, 0xe7, 0x3c, 0xb1, 0x7f, 0xfd, 0xd7, 0x9c, 0x2e, 0x7d, 0xfa,
+ 0x06, 0x98, 0x6b, 0x15, 0x88, 0x83, 0xd1, 0x7d, 0xe1, 0x11, 0xab, 0x17,
+ 0x31, 0x2c, 0x5b, 0xce, 0x6d, 0x18, 0x7a, 0xa4, 0xfe, 0xc4, 0xad, 0x7f,
+ 0xfd, 0x11, 0x49, 0xfa, 0x87, 0x84, 0x3c, 0xeb, 0xcb, 0x17, 0xff, 0xfe,
+ 0xc8, 0x75, 0xed, 0x4e, 0x74, 0x3f, 0xe1, 0xcb, 0x3b, 0x39, 0x2c, 0x5f,
+ 0xb6, 0xf9, 0x37, 0x4b, 0x17, 0xf6, 0x05, 0x84, 0x20, 0x2c, 0x5f, 0xa1,
+ 0x9e, 0x90, 0x2c, 0x5f, 0x60, 0x24, 0x0b, 0x15, 0xb1, 0xfc, 0x74, 0x5c,
+ 0x45, 0x15, 0xa4, 0x69, 0x1e, 0x14, 0x57, 0xee, 0x8d, 0xd6, 0x71, 0x62,
+ 0xa4, 0xf4, 0xd8, 0xa2, 0xff, 0xe7, 0xe1, 0x4f, 0xb9, 0x9d, 0x9c, 0xd5,
+ 0x8b, 0xff, 0xff, 0x80, 0x76, 0x87, 0xd9, 0xfc, 0xe3, 0xc1, 0xe7, 0x9c,
+ 0xef, 0xa5, 0x8a, 0xc5, 0x57, 0xbf, 0x54, 0xe4, 0x72, 0x7e, 0x20, 0x12,
+ 0x35, 0xfb, 0x58, 0x3e, 0xd2, 0xb1, 0x7f, 0xef, 0xb7, 0x76, 0xff, 0x73,
+ 0xce, 0xeb, 0x14, 0xb1, 0x4b, 0x15, 0xb9, 0x70, 0x41, 0x97, 0xff, 0x4f,
+ 0xd9, 0xfc, 0x0c, 0x84, 0x76, 0x2c, 0x5e, 0x29, 0x09, 0x62, 0xec, 0xe6,
+ 0x23, 0x7f, 0x75, 0xcd, 0x10, 0x1d, 0x1a, 0x9d, 0x35, 0x12, 0x8c, 0x26,
+ 0xff, 0xf3, 0x68, 0xd0, 0xe4, 0x2c, 0xe7, 0x18, 0xd5, 0x8b, 0xe3, 0xc8,
+ 0xe5, 0x62, 0xff, 0x0f, 0xed, 0x0c, 0xeb, 0xcb, 0x17, 0xff, 0xec, 0xd3,
+ 0xc9, 0x7b, 0x37, 0x9f, 0x7d, 0xfb, 0x2c, 0x5b, 0x66, 0x44, 0x59, 0x1a,
+ 0xd6, 0xc8, 0xd5, 0x14, 0x2b, 0x6b, 0x66, 0xce, 0xf2, 0x04, 0x23, 0x95,
+ 0x49, 0x91, 0x95, 0x9b, 0x09, 0xed, 0xe1, 0xc7, 0xd4, 0x65, 0xcf, 0x0c,
+ 0x48, 0xa5, 0x0a, 0xea, 0x1d, 0xa7, 0x31, 0xfc, 0x77, 0xc0, 0x50, 0xe4,
+ 0x64, 0x9e, 0x95, 0xbd, 0xda, 0x3a, 0x20, 0x8a, 0x03, 0x8c, 0x8e, 0xff,
+ 0x1b, 0x25, 0x9e, 0xfb, 0xac, 0x5f, 0xfe, 0xe0, 0xe5, 0x8b, 0x6f, 0x3f,
+ 0x1f, 0xb2, 0xc5, 0xa4, 0xd3, 0xff, 0xf1, 0x9d, 0xff, 0xf6, 0xd3, 0xa3,
+ 0x07, 0x85, 0xb6, 0x08, 0xbc, 0xb1, 0x7e, 0xe4, 0xed, 0x81, 0x2c, 0x5a,
+ 0x48, 0xff, 0x38, 0xa5, 0x7f, 0xfc, 0x3f, 0x09, 0xba, 0xf0, 0x30, 0x66,
+ 0x7d, 0xd6, 0x2f, 0xff, 0x9f, 0xb0, 0xe4, 0xa7, 0xdc, 0xc1, 0x17, 0x96,
+ 0x2f, 0xff, 0xfe, 0x7f, 0x73, 0x0c, 0xf7, 0x1a, 0x06, 0x6f, 0xf7, 0x1e,
+ 0x9c, 0x5b, 0x2c, 0x5f, 0xff, 0xec, 0x03, 0x19, 0xef, 0xe0, 0xff, 0x80,
+ 0xc1, 0xfd, 0xd6, 0x2f, 0xff, 0x37, 0xfe, 0xe3, 0xcf, 0x70, 0x45, 0xe5,
+ 0x8a, 0x3a, 0x64, 0x44, 0xef, 0xd9, 0x86, 0xff, 0x3f, 0x6c, 0xe7, 0x32,
+ 0x3d, 0x62, 0xfb, 0xc4, 0x2f, 0x2c, 0x5c, 0x22, 0x58, 0xbd, 0x87, 0xcd,
+ 0x1b, 0xaf, 0x91, 0xdf, 0xf1, 0xcc, 0xd6, 0x77, 0x7f, 0x0e, 0xb1, 0x52,
+ 0x98, 0x9c, 0x0c, 0xbe, 0xe4, 0xc6, 0x34, 0x35, 0x67, 0x4c, 0x4d, 0xc5,
+ 0x3f, 0x4a, 0x85, 0xb8, 0xd7, 0x58, 0xbf, 0x9e, 0x4b, 0xc1, 0x9d, 0x62,
+ 0xb4, 0x78, 0xde, 0x18, 0xbf, 0xbf, 0x3c, 0x83, 0x81, 0x62, 0xff, 0xb7,
+ 0xcd, 0x69, 0xa0, 0x2c, 0x58, 0xbf, 0xff, 0xf7, 0x40, 0x92, 0xdd, 0xbc,
+ 0xdd, 0x00, 0xf3, 0xff, 0x63, 0xf6, 0x58, 0xa1, 0xa3, 0x63, 0x0b, 0x83,
+ 0x3a, 0xbf, 0x83, 0xd1, 0xca, 0x42, 0x58, 0xaf, 0x1f, 0x00, 0x66, 0x17,
+ 0xe7, 0x17, 0x7f, 0x9c, 0x58, 0xac, 0x4e, 0xa9, 0xa3, 0x5a, 0xf1, 0x1d,
+ 0x4b, 0x79, 0x5d, 0x95, 0xa4, 0xdb, 0xc7, 0x96, 0xd2, 0xf7, 0x85, 0x28,
+ 0xd6, 0xf0, 0x41, 0x04, 0x91, 0x7f, 0xd8, 0x06, 0xd6, 0x76, 0xc1, 0xa4,
+ 0x46, 0x1a, 0x1b, 0x82, 0x09, 0x22, 0xf0, 0x41, 0x04, 0x91, 0x7f, 0x36,
+ 0xc3, 0xfc, 0xf1, 0x22, 0x30, 0xd0, 0xd1, 0x23, 0x28, 0x24, 0xd8, 0xe3,
+ 0xbb, 0xf6, 0xee, 0x30, 0xce, 0x91, 0x18, 0x6c, 0xef, 0x04, 0x10, 0x49,
+ 0x17, 0xb9, 0x3a, 0x48, 0x8c, 0x34, 0x37, 0xcc, 0x5d, 0x79, 0x62, 0xc0,
+ 0x74, 0x59, 0x79, 0x7c, 0x23, 0x0b, 0xf8, 0x80, 0x60, 0x59, 0xf5, 0x8b,
+ 0x77, 0x8b, 0x14, 0xc7, 0x8f, 0x1c, 0x61, 0x7f, 0xce, 0x5b, 0x96, 0x04,
+ 0xc0, 0x58, 0xbf, 0x84, 0xdb, 0x10, 0xfa, 0x58, 0xbe, 0x98, 0x36, 0xeb,
+ 0x15, 0xf3, 0xd3, 0x23, 0x0b, 0xff, 0xff, 0x98, 0xde, 0x78, 0xb3, 0x9f,
+ 0x7f, 0x7f, 0x0f, 0x9e, 0x9f, 0x71, 0x62, 0xfe, 0x16, 0xfc, 0x7d, 0xc4,
+ 0xb1, 0x7b, 0x22, 0x75, 0x8a, 0x1a, 0x38, 0x48, 0x87, 0xce, 0x41, 0x98,
+ 0xdf, 0xf0, 0x27, 0xa2, 0xc0, 0x0b, 0x8b, 0x17, 0xc2, 0xda, 0x38, 0x96,
+ 0x28, 0x07, 0xc3, 0xc3, 0xab, 0xfd, 0xbc, 0x90, 0xc3, 0x8b, 0x8b, 0x17,
+ 0xe1, 0xbf, 0x69, 0x1a, 0xc5, 0xf6, 0x16, 0x47, 0xac, 0x56, 0x8f, 0x38,
+ 0xe5, 0x54, 0xe8, 0xc9, 0x62, 0x20, 0xe1, 0x0b, 0x7e, 0x32, 0x7e, 0xc7,
+ 0x58, 0xbf, 0xf3, 0x40, 0x98, 0xd8, 0x89, 0xe2, 0x58, 0xb8, 0x4c, 0xb1,
+ 0x5f, 0x3d, 0x7f, 0x20, 0x5f, 0xd1, 0xac, 0xb0, 0x26, 0x02, 0xc5, 0xe0,
+ 0x82, 0x09, 0x22, 0xf1, 0x30, 0x49, 0x11, 0x86, 0x86, 0xf8, 0x78, 0x43,
+ 0x58, 0xbf, 0xed, 0xa7, 0xae, 0x39, 0x60, 0x16, 0x2f, 0x9a, 0x0e, 0x05,
+ 0x8b, 0xf3, 0x9b, 0xec, 0xdd, 0x62, 0xb7, 0x45, 0x46, 0x88, 0xbe, 0x74,
+ 0x44, 0x57, 0xec, 0xd8, 0xf8, 0x75, 0x8b, 0xfa, 0x76, 0x1f, 0xe7, 0x8b,
+ 0x17, 0xfa, 0x73, 0x7c, 0xec, 0xe3, 0x58, 0xbf, 0x85, 0xb0, 0x7e, 0x78,
+ 0x2c, 0x5b, 0x37, 0x44, 0xa9, 0x17, 0xf0, 0xd6, 0xa3, 0x5a, 0xa5, 0xd1,
+ 0xaa, 0xe4, 0x36, 0x08, 0xf6, 0x3a, 0x17, 0xd7, 0xf7, 0xf3, 0xb6, 0x7b,
+ 0x8b, 0x14, 0x35, 0x71, 0x9b, 0xc2, 0x00, 0x12, 0x9f, 0xfc, 0xbb, 0x50,
+ 0x5f, 0x04, 0x19, 0x26, 0xa3, 0x6d, 0xfc, 0x6c, 0xe5, 0x2f, 0x02, 0xff,
+ 0x7a, 0x19, 0xff, 0xb4, 0x16, 0x2d, 0xa5, 0x8b, 0x9c, 0x6b, 0x14, 0x69,
+ 0xa9, 0xf8, 0x95, 0xfa, 0x2d, 0x69, 0xf6, 0x58, 0xbe, 0x2f, 0xe1, 0x2c,
+ 0x5b, 0x4b, 0x15, 0x86, 0xcd, 0xc8, 0x6f, 0x9d, 0x88, 0x6b, 0x17, 0x08,
+ 0x0b, 0x17, 0xef, 0xe3, 0xea, 0x0b, 0x14, 0x33, 0xe1, 0x01, 0x0f, 0x86,
+ 0x2f, 0xd3, 0x91, 0x3e, 0x96, 0x2b, 0x63, 0xd7, 0x22, 0xfb, 0x79, 0x62,
+ 0xee, 0xf3, 0xbc, 0x58, 0xad, 0x8d, 0xa0, 0x84, 0xaa, 0x59, 0x41, 0x99,
+ 0x3f, 0x02, 0x6a, 0xfe, 0xeb, 0xae, 0x45, 0xf5, 0xe6, 0x86, 0xb9, 0x2b,
+ 0x5f, 0xff, 0x37, 0x69, 0xfb, 0x7f, 0x79, 0xf7, 0x26, 0x0b, 0x17, 0xd1,
+ 0xdf, 0xcd, 0xd6, 0x2f, 0x80, 0xe5, 0xe5, 0x8a, 0xd8, 0xf2, 0x78, 0x4f,
+ 0x77, 0x7d, 0x7b, 0xc5, 0x8b, 0xc2, 0x61, 0xac, 0x5f, 0x7a, 0x42, 0xe2,
+ 0xc5, 0xee, 0x4f, 0x96, 0x2e, 0x00, 0x4b, 0x17, 0xee, 0x08, 0x83, 0x3a,
+ 0xc5, 0xb9, 0x1b, 0x22, 0x12, 0x22, 0x46, 0x1d, 0xf0, 0xcd, 0x41, 0x3c,
+ 0xcc, 0x84, 0xdf, 0x44, 0x7f, 0x25, 0xf4, 0x28, 0x6f, 0xff, 0x4e, 0xa5,
+ 0xa2, 0x3b, 0x0f, 0xf2, 0x4b, 0x17, 0xfe, 0xfb, 0x43, 0x34, 0x03, 0xbf,
+ 0x16, 0x28, 0xd4, 0x44, 0x79, 0x26, 0xfd, 0x81, 0x66, 0xb6, 0x58, 0xbf,
+ 0x6f, 0x3f, 0x93, 0xac, 0x5c, 0xde, 0x58, 0xbe, 0x8f, 0x62, 0x06, 0xc7,
+ 0xd5, 0x85, 0x44, 0x53, 0x7f, 0xb0, 0xd3, 0x5a, 0x10, 0x1a, 0xc5, 0xfc,
+ 0xcc, 0x3f, 0x09, 0x96, 0x2f, 0x86, 0xc4, 0x0c, 0x3e, 0x32, 0x36, 0xa9,
+ 0x4d, 0xbb, 0x21, 0x1c, 0x28, 0x55, 0x5f, 0xf0, 0xce, 0xfa, 0xe3, 0x10,
+ 0x16, 0x2d, 0xde, 0x2c, 0x5f, 0xf7, 0xe6, 0x10, 0x7e, 0x60, 0xd6, 0x2c,
+ 0x0e, 0xf8, 0x7a, 0x1e, 0x17, 0xbf, 0xc7, 0x6e, 0xa7, 0x51, 0x32, 0xc5,
+ 0xfe, 0xd4, 0xf6, 0xf1, 0x30, 0x16, 0x2d, 0xe9, 0x3e, 0xac, 0x35, 0xa9,
+ 0x45, 0xf3, 0xc2, 0x62, 0xff, 0xe9, 0x3e, 0x3c, 0x4c, 0xd0, 0xde, 0x0b,
+ 0x15, 0x03, 0xeb, 0x22, 0x6b, 0xff, 0xb4, 0x2d, 0x8c, 0xcf, 0xcf, 0x3e,
+ 0xeb, 0x17, 0xdd, 0xc2, 0x88, 0xeb, 0x14, 0xea, 0x90, 0xa2, 0x8e, 0xcb,
+ 0x44, 0x3f, 0x47, 0xbf, 0xff, 0x7e, 0x79, 0xe2, 0x98, 0x8a, 0x47, 0x9d,
+ 0x79, 0x62, 0xf8, 0x7f, 0x9d, 0x96, 0x2f, 0xda, 0x18, 0xc5, 0xb2, 0xc5,
+ 0xe9, 0x28, 0x0d, 0x14, 0xa4, 0xac, 0x19, 0x25, 0xfb, 0x35, 0x1c, 0x71,
+ 0xac, 0x5f, 0xfb, 0xaf, 0x1a, 0x6b, 0x7c, 0x85, 0xe5, 0x8a, 0x19, 0xf7,
+ 0xe1, 0x65, 0xfe, 0x33, 0x52, 0x77, 0xfc, 0xac, 0x5e, 0xfb, 0xc4, 0x91,
+ 0x5a, 0x3f, 0x32, 0x21, 0xe1, 0xa5, 0xff, 0x37, 0x5e, 0xc8, 0x85, 0xa3,
+ 0x56, 0x2d, 0xbb, 0x9f, 0x58, 0x8b, 0xaf, 0xf1, 0x67, 0x50, 0xe3, 0x9a,
+ 0xb1, 0x79, 0xf7, 0x95, 0x8b, 0xf3, 0xeb, 0x61, 0x71, 0x62, 0xb4, 0x78,
+ 0xe7, 0x1d, 0xb8, 0x3d, 0x2c, 0x5e, 0xd0, 0xb6, 0x58, 0xbc, 0xda, 0x35,
+ 0x62, 0xc7, 0x58, 0xac, 0x44, 0x51, 0xa4, 0x5a, 0x19, 0x61, 0xfe, 0xc3,
+ 0xd7, 0xfe, 0x1f, 0xe7, 0x99, 0xad, 0xa6, 0x0b, 0x17, 0x8d, 0x16, 0xeb,
+ 0x16, 0x35, 0x62, 0xff, 0xec, 0xdf, 0xf3, 0xfc, 0xd6, 0xa4, 0xd5, 0x8b,
+ 0x81, 0xc9, 0x3d, 0x9d, 0x09, 0xd1, 0xa8, 0xa6, 0x77, 0x9a, 0x31, 0x52,
+ 0xd6, 0xd1, 0x83, 0x44, 0x96, 0x50, 0xe6, 0xbf, 0xd9, 0xb8, 0x27, 0x3a,
+ 0x82, 0xc5, 0xb4, 0xb1, 0x58, 0x78, 0xe7, 0x35, 0xbf, 0xf0, 0xb9, 0x85,
+ 0x3f, 0x18, 0x67, 0x58, 0xbf, 0xda, 0x90, 0xb0, 0x9c, 0xd5, 0x8b, 0x9c,
+ 0x6b, 0x17, 0xfb, 0xda, 0x17, 0x3e, 0xd0, 0xd1, 0xe5, 0x80, 0xd2, 0xff,
+ 0x70, 0x40, 0x6f, 0x41, 0x96, 0x2e, 0x3f, 0x64, 0x8b, 0x49, 0x87, 0x9c,
+ 0xc6, 0x97, 0xc3, 0x92, 0xdd, 0x62, 0xec, 0x8d, 0x96, 0x2f, 0xff, 0xec,
+ 0x7e, 0xa1, 0x27, 0x9c, 0xf7, 0x30, 0x45, 0xe5, 0x8a, 0xd1, 0xfb, 0x76,
+ 0x1c, 0xbf, 0xe7, 0x34, 0x32, 0x9f, 0xbe, 0xcb, 0x17, 0xff, 0x7d, 0xd8,
+ 0x00, 0x90, 0x4f, 0xf8, 0xb1, 0x7f, 0x7f, 0x0e, 0x76, 0x82, 0xc5, 0xe0,
+ 0x82, 0x09, 0x22, 0xff, 0x17, 0xbe, 0xf2, 0x5b, 0x24, 0x46, 0x1a, 0x1b,
+ 0xe9, 0xd3, 0x7d, 0x62, 0xa0, 0x8b, 0x7c, 0x4f, 0xf2, 0x35, 0xce, 0x05,
+ 0x8b, 0xfa, 0x46, 0x3c, 0xea, 0x0b, 0x17, 0xf3, 0xea, 0x01, 0xc8, 0x16,
+ 0x2e, 0x90, 0x62, 0x29, 0x3e, 0x5e, 0x42, 0xf1, 0xc5, 0xf5, 0x8a, 0x91,
+ 0xf7, 0x24, 0xf1, 0xd8, 0x71, 0xcf, 0xdf, 0xda, 0x80, 0x70, 0x7d, 0x96,
+ 0x2f, 0x30, 0x38, 0xb1, 0x76, 0x19, 0x87, 0x9d, 0xe3, 0x1a, 0xdd, 0x5e,
+ 0x43, 0x93, 0x9e, 0x57, 0x07, 0x68, 0x4a, 0x5f, 0xf3, 0x00, 0xb2, 0x28,
+ 0x4f, 0x4b, 0x17, 0xfe, 0x9e, 0xbf, 0x9d, 0x03, 0x3d, 0xc5, 0x8a, 0x95,
+ 0xd2, 0x9c, 0x9c, 0x61, 0x74, 0xd1, 0x1d, 0x5f, 0xbe, 0xe3, 0x68, 0x2c,
+ 0x5f, 0xb3, 0x5a, 0x78, 0x96, 0x2e, 0x62, 0xdc, 0xf4, 0x48, 0xa2, 0xff,
+ 0x9c, 0x11, 0xb7, 0x33, 0x4c, 0x05, 0x8b, 0xd8, 0x5b, 0xac, 0x5f, 0xee,
+ 0x37, 0xfa, 0x86, 0x79, 0x62, 0xfc, 0x1e, 0x88, 0x50, 0x58, 0xa8, 0x1e,
+ 0xf9, 0x1a, 0xdf, 0xb8, 0x77, 0xd7, 0x16, 0x2b, 0x64, 0xcc, 0x34, 0x58,
+ 0x73, 0xe6, 0x7c, 0x01, 0x0d, 0xff, 0xfd, 0x0f, 0xb4, 0x37, 0xfb, 0xfa,
+ 0x19, 0xff, 0xb4, 0x16, 0x2f, 0xd2, 0x09, 0xff, 0x16, 0x2b, 0x11, 0x0a,
+ 0x05, 0xdb, 0xff, 0x83, 0x29, 0x71, 0xff, 0x21, 0xf7, 0x58, 0xb8, 0x3c,
+ 0x58, 0xbf, 0xe9, 0xd0, 0x3d, 0xf6, 0x1b, 0xac, 0x56, 0x1e, 0x88, 0x63,
+ 0x17, 0xfd, 0x08, 0xa0, 0xde, 0xe3, 0xca, 0xc5, 0xff, 0xfb, 0xee, 0x52,
+ 0x7c, 0x26, 0xeb, 0x86, 0x9a, 0xcb, 0x17, 0xff, 0xbc, 0x29, 0x79, 0xeb,
+ 0x7f, 0xe7, 0x5c, 0x58, 0xac, 0x45, 0x1b, 0x2b, 0x5f, 0xb5, 0xa7, 0xf7,
+ 0x16, 0x28, 0xc4, 0xf7, 0x87, 0x09, 0x5e, 0x88, 0x81, 0x0d, 0xd0, 0xc8,
+ 0x6f, 0xff, 0x81, 0x1d, 0x93, 0xcf, 0xcf, 0x5e, 0x34, 0x5a, 0x58, 0xbf,
+ 0xfa, 0x28, 0x08, 0xbd, 0x0c, 0xd6, 0x71, 0x62, 0xff, 0xfc, 0x5b, 0xfd,
+ 0xe2, 0x84, 0x97, 0xb5, 0xa9, 0x82, 0xc7, 0x0f, 0x1a, 0xff, 0xfe, 0x7e,
+ 0x69, 0xdb, 0x52, 0xfe, 0xfe, 0x73, 0x98, 0xb1, 0x7f, 0xed, 0x4c, 0x1f,
+ 0xc0, 0xc8, 0xb8, 0xb1, 0x7f, 0xb2, 0x60, 0xfe, 0x29, 0x58, 0xb0, 0x31,
+ 0x33, 0x23, 0xb4, 0x71, 0x66, 0x39, 0x02, 0xfe, 0x68, 0x34, 0x1f, 0xeb,
+ 0x15, 0x2a, 0xa6, 0x71, 0x61, 0xa3, 0xce, 0x12, 0x35, 0xff, 0xfc, 0xc0,
+ 0x2c, 0x39, 0x37, 0xb8, 0x1e, 0x9e, 0x46, 0xb1, 0x74, 0x38, 0xb1, 0x68,
+ 0x0c, 0xfc, 0x9d, 0x6a, 0xff, 0xf1, 0x36, 0x8d, 0xee, 0xf6, 0x85, 0xd4,
+ 0x38, 0xb1, 0x52, 0x7f, 0x0e, 0x4f, 0x7f, 0xe6, 0x1f, 0xe7, 0xa6, 0xdf,
+ 0x90, 0x58, 0xa9, 0x6e, 0x38, 0xe1, 0x29, 0x2f, 0x25, 0x3d, 0x9b, 0x0e,
+ 0xae, 0xa3, 0x8d, 0x79, 0x50, 0x51, 0x42, 0x4f, 0x44, 0x3f, 0x9d, 0xb4,
+ 0x68, 0xf1, 0x81, 0x0d, 0x02, 0x9c, 0x99, 0xe4, 0x65, 0x82, 0x20, 0xbf,
+ 0xff, 0xbc, 0xe7, 0xc2, 0xf7, 0x24, 0xde, 0x08, 0x7f, 0x75, 0x8b, 0xb3,
+ 0xa5, 0x8b, 0xf3, 0x78, 0x2c, 0xfa, 0xc5, 0xe1, 0xff, 0x16, 0x2f, 0xb1,
+ 0xfe, 0x6a, 0xc5, 0x7c, 0xfa, 0x58, 0xa4, 0x03, 0xb7, 0xf4, 0xed, 0xa1,
+ 0x48, 0x16, 0x2f, 0xff, 0xb3, 0x79, 0x26, 0xf7, 0x06, 0x26, 0xd4, 0x16,
+ 0x2b, 0x64, 0xcb, 0xba, 0x84, 0x0c, 0x45, 0xc7, 0x2f, 0xbe, 0xe7, 0xf3,
+ 0x8b, 0x17, 0xcf, 0xe9, 0xf2, 0xc5, 0x39, 0xe2, 0xe8, 0x8e, 0xf9, 0xc1,
+ 0x83, 0x58, 0xbf, 0x16, 0xf1, 0xbf, 0x7c, 0x8d, 0x16, 0x2f, 0xfa, 0x3b,
+ 0x37, 0xfb, 0x9e, 0x77, 0x58, 0xa9, 0x3f, 0x86, 0x3a, 0xb4, 0xac, 0x5e,
+ 0xf3, 0xec, 0xb1, 0x5b, 0x1a, 0xfe, 0x84, 0x6f, 0xd2, 0x7d, 0x4f, 0x65,
+ 0x8b, 0xff, 0xde, 0x70, 0xb8, 0x53, 0xee, 0x6b, 0x52, 0xb1, 0x74, 0x92,
+ 0xc5, 0xec, 0x3c, 0x72, 0xc5, 0xf6, 0x10, 0x7e, 0x58, 0xa8, 0x1e, 0xc8,
+ 0xc5, 0xb4, 0x41, 0x78, 0x72, 0x6a, 0xc5, 0xff, 0xd3, 0xbf, 0x8a, 0x42,
+ 0xcf, 0x73, 0x8b, 0x17, 0xfc, 0xd2, 0x1b, 0xff, 0xef, 0x12, 0xc5, 0xff,
+ 0x73, 0x38, 0xe7, 0x62, 0x02, 0xc5, 0xfc, 0x53, 0x0f, 0xf0, 0x0b, 0x17,
+ 0xfe, 0x6f, 0xea, 0x7c, 0xfb, 0xb8, 0xd6, 0x2f, 0xff, 0x88, 0x5e, 0xe6,
+ 0x6f, 0xd7, 0x99, 0x8f, 0xc5, 0x8b, 0xfd, 0xfc, 0x7d, 0x40, 0x33, 0xac,
+ 0x56, 0x22, 0x1f, 0xca, 0x57, 0x60, 0x16, 0x2a, 0x53, 0x65, 0x19, 0xc7,
+ 0xcb, 0xb9, 0x0c, 0x6f, 0x11, 0x53, 0xaa, 0x52, 0xd0, 0xf7, 0xd1, 0x81,
+ 0x1c, 0xfd, 0xff, 0x9f, 0xc0, 0x61, 0x89, 0xb5, 0x05, 0x8b, 0xfc, 0x7c,
+ 0x8a, 0x4f, 0x81, 0x2c, 0x5f, 0x1e, 0x5f, 0x8b, 0x15, 0x87, 0xaf, 0xc3,
+ 0x5b, 0xff, 0xed, 0x42, 0x4b, 0x39, 0x38, 0x43, 0xfc, 0xac, 0x5f, 0xe7,
+ 0xd0, 0x7e, 0xf3, 0xec, 0xb1, 0x7d, 0xa9, 0xce, 0x96, 0x2a, 0x07, 0xb3,
+ 0xe3, 0x6b, 0xe9, 0xf3, 0xf9, 0x62, 0xff, 0xff, 0xcc, 0x79, 0xd6, 0xe3,
+ 0xfc, 0xf0, 0x4c, 0xf0, 0xe7, 0xda, 0x0b, 0x17, 0xe0, 0x09, 0x8b, 0x75,
+ 0x8b, 0xfa, 0x7f, 0x90, 0xc3, 0xac, 0x5f, 0x72, 0x60, 0x66, 0x1e, 0xb7,
+ 0x8a, 0x6b, 0x13, 0xe6, 0x78, 0x53, 0x7c, 0x88, 0x88, 0xb9, 0x0c, 0x3b,
+ 0xfb, 0x1e, 0x2f, 0x88, 0xeb, 0x17, 0xe0, 0x9b, 0xf2, 0x75, 0x8b, 0xdb,
+ 0xcf, 0x16, 0x2f, 0xfe, 0x0e, 0x19, 0xf6, 0xfb, 0xeb, 0x52, 0xb1, 0x7f,
+ 0xee, 0x37, 0xa1, 0x9a, 0xd3, 0x41, 0x62, 0xff, 0xbe, 0xcf, 0xe9, 0xf3,
+ 0xc1, 0x62, 0xa4, 0xfd, 0xf7, 0x3f, 0xa9, 0x4c, 0x97, 0x0a, 0x40, 0x3c,
+ 0x28, 0x5e, 0x5e, 0x86, 0x0d, 0x62, 0xfa, 0x0c, 0x40, 0x58, 0xbf, 0xfc,
+ 0xfe, 0x16, 0x9b, 0x90, 0x7e, 0x4e, 0xcb, 0x15, 0x87, 0xda, 0xc4, 0x55,
+ 0x88, 0xaa, 0xfc, 0x22, 0xaf, 0x73, 0xb6, 0x2c, 0x5d, 0x3a, 0x58, 0xaf,
+ 0x1b, 0x68, 0xe1, 0xfb, 0xfb, 0xb4, 0x96, 0xf1, 0xd8, 0xb1, 0x7f, 0x66,
+ 0xdc, 0x8f, 0x7d, 0xd6, 0x2a, 0x51, 0x14, 0xe4, 0x84, 0x67, 0x7e, 0x16,
+ 0x8d, 0xfb, 0xac, 0x5e, 0x01, 0xdd, 0x62, 0x8c, 0x66, 0xaf, 0x4c, 0x71,
+ 0x5b, 0x42, 0x2e, 0x04, 0x23, 0x84, 0xd6, 0x27, 0xee, 0x47, 0xd1, 0x53,
+ 0xc2, 0x93, 0x52, 0xa0, 0x4e, 0x89, 0xf8, 0x4b, 0x34, 0xa0, 0x70, 0x29,
+ 0x14, 0x6a, 0x9c, 0x87, 0x5f, 0xa1, 0xcf, 0x1c, 0x5a, 0x19, 0x55, 0x82,
+ 0x58, 0xbf, 0xe2, 0x13, 0x1a, 0x03, 0xcc, 0x16, 0x2b, 0x47, 0x9a, 0x01,
+ 0x3b, 0x84, 0x05, 0x8b, 0xfc, 0x4c, 0x16, 0x13, 0x1a, 0xb1, 0x7f, 0xf6,
+ 0x7b, 0x81, 0xf0, 0xe5, 0x3a, 0x95, 0x8b, 0xff, 0xdc, 0xcd, 0xbf, 0x27,
+ 0x0c, 0x64, 0xfb, 0x2c, 0x58, 0xb6, 0x46, 0xe8, 0xc6, 0x0e, 0x67, 0xe4,
+ 0x5b, 0xff, 0x37, 0xb7, 0xfb, 0xf5, 0xc9, 0x09, 0x62, 0xdd, 0xb1, 0x10,
+ 0xbf, 0x43, 0xbe, 0x1e, 0x9a, 0x25, 0x8b, 0xfe, 0x9f, 0x7d, 0xfb, 0x67,
+ 0x5e, 0x58, 0xbf, 0x3f, 0x70, 0xf0, 0xeb, 0x15, 0xb9, 0xf3, 0xfc, 0xf2,
+ 0xf8, 0x72, 0x5e, 0x58, 0xbf, 0x3b, 0x76, 0x0c, 0xeb, 0x17, 0xff, 0xb0,
+ 0xe7, 0x92, 0xde, 0x7d, 0xcf, 0xba, 0xc5, 0xff, 0xa7, 0x44, 0xdb, 0x4e,
+ 0xa6, 0x0b, 0x15, 0x29, 0xc1, 0xe4, 0x22, 0xdc, 0x8c, 0x04, 0x44, 0x56,
+ 0x12, 0x55, 0x3a, 0xa0, 0x7f, 0xc7, 0x5b, 0x7f, 0xff, 0xbe, 0xe1, 0x67,
+ 0x73, 0x9d, 0xbd, 0xc1, 0x43, 0x3a, 0xf2, 0xc5, 0xff, 0xf7, 0xe7, 0x9d,
+ 0x6e, 0xfd, 0x67, 0x33, 0xaf, 0x2c, 0x5f, 0xf9, 0xc0, 0x1f, 0xe4, 0xec,
+ 0xde, 0x58, 0xa1, 0xa2, 0x4f, 0x4a, 0x97, 0xff, 0xf6, 0xc3, 0xfc, 0xf3,
+ 0x3a, 0xe4, 0xeb, 0xdc, 0xcd, 0x96, 0x28, 0x69, 0xbd, 0xea, 0x1f, 0x24,
+ 0x47, 0x74, 0xba, 0xc5, 0x4a, 0xeb, 0xde, 0x4b, 0x8b, 0x68, 0xe9, 0x40,
+ 0x6b, 0x7f, 0xd1, 0x6f, 0xf7, 0x3c, 0xe8, 0xd5, 0x8b, 0xf3, 0xf4, 0x06,
+ 0xe2, 0xc5, 0xef, 0x4c, 0x4b, 0x17, 0x9f, 0x51, 0x49, 0xe3, 0xe1, 0x4d,
+ 0xfd, 0x3f, 0x9f, 0x4f, 0xd6, 0x2f, 0xbb, 0x9c, 0xb7, 0x58, 0xac, 0x3d,
+ 0x3e, 0xe2, 0xdb, 0xf6, 0xc6, 0x0a, 0x62, 0x58, 0xb9, 0xa2, 0x58, 0xb4,
+ 0x16, 0x2f, 0xd0, 0xf3, 0xeb, 0x75, 0x8b, 0xc1, 0x94, 0x4b, 0x14, 0x61,
+ 0xf9, 0xc0, 0x63, 0xa1, 0x20, 0x15, 0x56, 0x2a, 0x0a, 0xde, 0x10, 0x9a,
+ 0x84, 0x2b, 0x12, 0x72, 0x13, 0xf4, 0x64, 0x64, 0x4c, 0xd1, 0xb9, 0xa4,
+ 0x68, 0x3d, 0x1a, 0x87, 0xa6, 0x95, 0xcf, 0xb5, 0x21, 0xaa, 0x14, 0xf1,
+ 0xe1, 0xd3, 0x68, 0x32, 0xda, 0x03, 0x1b, 0x1f, 0xa6, 0xf2, 0xfa, 0xba,
+ 0x87, 0x0b, 0xd2, 0x31, 0x23, 0xe3, 0xac, 0x8a, 0x96, 0xff, 0xaa, 0x45,
+ 0xc9, 0xe9, 0x84, 0x1f, 0xad, 0x6c, 0xda, 0x95, 0x38, 0x0a, 0x61, 0xa1,
+ 0x5a, 0x04, 0x9e, 0x53, 0x11, 0x7d, 0x5d, 0x97, 0x0a, 0x9c, 0xcc, 0x14,
+ 0xf8, 0x38, 0x72, 0x95, 0x2e, 0x93, 0xac, 0x5f, 0xf1, 0xd8, 0x20, 0xe0,
+ 0xe0, 0xe2, 0xc5, 0xef, 0xe7, 0x16, 0x2e, 0x0f, 0x75, 0x8b, 0xa4, 0xeb,
+ 0x16, 0xf0, 0x0d, 0x8f, 0x86, 0xaf, 0xf3, 0x9b, 0xee, 0xb7, 0x7f, 0xac,
+ 0x57, 0x47, 0xbc, 0x44, 0xf4, 0x34, 0x67, 0x64, 0x2b, 0x2f, 0x77, 0x3f,
+ 0x65, 0x8b, 0xfd, 0xf7, 0xf7, 0xde, 0x40, 0xb1, 0x73, 0x69, 0x62, 0xe7,
+ 0xfa, 0xc5, 0xf6, 0x61, 0x79, 0x62, 0xe9, 0x25, 0x8a, 0x81, 0xf2, 0xfc,
+ 0x5f, 0x82, 0xfd, 0x88, 0x6f, 0xff, 0xb0, 0xa3, 0x3c, 0x6b, 0xf5, 0xcf,
+ 0xe0, 0x19, 0x62, 0xfe, 0x32, 0x28, 0x4e, 0xb6, 0x58, 0xbf, 0xfe, 0x1c,
+ 0xb6, 0xbe, 0x13, 0x0e, 0x39, 0xb6, 0x8e, 0x58, 0xa8, 0x26, 0x38, 0x33,
+ 0xe8, 0x95, 0x3c, 0x65, 0x79, 0x98, 0x25, 0x8b, 0xf6, 0xf9, 0xef, 0xba,
+ 0xc5, 0x0c, 0xf1, 0x88, 0x76, 0xff, 0xf6, 0xa2, 0x93, 0x98, 0x7c, 0xf7,
+ 0x1f, 0x8b, 0x14, 0xc7, 0xdc, 0x22, 0x1b, 0xfd, 0x0f, 0x3f, 0xbd, 0x80,
+ 0x58, 0xbd, 0xf7, 0xef, 0xd6, 0x2f, 0xe6, 0x86, 0x0d, 0xbe, 0xb1, 0x5b,
+ 0x9e, 0x79, 0xc8, 0xaf, 0xba, 0x86, 0x79, 0x62, 0xfd, 0x03, 0x30, 0x3c,
+ 0x58, 0xbf, 0xf4, 0x8b, 0xbf, 0x91, 0xc9, 0xca, 0x56, 0x28, 0xc4, 0x48,
+ 0x49, 0x20, 0xca, 0xaf, 0x6e, 0xdb, 0xac, 0x5e, 0x7d, 0x4a, 0xc5, 0xfa,
+ 0x01, 0xf2, 0x71, 0x62, 0xb0, 0xf1, 0x58, 0x72, 0xff, 0xfc, 0x72, 0xce,
+ 0xbc, 0x16, 0x3f, 0x6d, 0x33, 0x41, 0x62, 0xdc, 0xf9, 0xfc, 0x31, 0x05,
+ 0xff, 0xde, 0x6d, 0x98, 0xb5, 0x3b, 0xe6, 0x96, 0x2f, 0xbd, 0xc6, 0x3a,
+ 0xc5, 0x18, 0x7d, 0x01, 0x22, 0xdf, 0xff, 0xf6, 0x7d, 0x83, 0xe6, 0x1a,
+ 0xc4, 0x09, 0x29, 0x8b, 0xf2, 0xb1, 0x69, 0x58, 0xbf, 0xff, 0x4e, 0xbf,
+ 0x27, 0xee, 0x14, 0x94, 0xc5, 0xf9, 0x58, 0xbf, 0x3e, 0xa2, 0x9f, 0xe9,
+ 0x19, 0xe0, 0x66, 0x21, 0x1b, 0x85, 0xa5, 0x8a, 0xd9, 0x90, 0x87, 0x08,
+ 0xc2, 0xb0, 0x9f, 0x72, 0x2e, 0xa3, 0xb4, 0x3c, 0x3c, 0xd8, 0x84, 0x10,
+ 0x83, 0x28, 0x59, 0xf0, 0xc3, 0xd0, 0xdc, 0x14, 0x23, 0xc3, 0x87, 0x9f,
+ 0x72, 0x65, 0xfa, 0x2f, 0xce, 0xd8, 0xb1, 0x6f, 0xac, 0x5d, 0x87, 0x58,
+ 0xa8, 0x1e, 0x98, 0xca, 0xa3, 0x84, 0xad, 0xdf, 0x6b, 0x17, 0xf7, 0xbe,
+ 0xd0, 0xf6, 0xcb, 0x17, 0x47, 0x12, 0xc5, 0xf4, 0x45, 0x27, 0x58, 0xbd,
+ 0xf6, 0x81, 0x86, 0xf7, 0xc3, 0x54, 0x48, 0xa0, 0xf3, 0x6d, 0xe7, 0x1e,
+ 0x2c, 0x5f, 0xc6, 0xe0, 0x88, 0x5b, 0xac, 0x5f, 0x09, 0xb5, 0x05, 0x8b,
+ 0xff, 0xed, 0x00, 0xf3, 0x1d, 0x86, 0x73, 0xcc, 0xc4, 0xb1, 0x7c, 0x2d,
+ 0x37, 0x16, 0x28, 0x68, 0x99, 0xc2, 0x3e, 0x29, 0xdf, 0xb7, 0xfc, 0xc7,
+ 0x8d, 0x62, 0xfb, 0x38, 0xfd, 0x96, 0x2e, 0xd9, 0x96, 0x2f, 0x31, 0x00,
+ 0xc4, 0x4c, 0x31, 0x79, 0x16, 0xf0, 0x92, 0xf1, 0x6d, 0x2b, 0x17, 0x61,
+ 0x2c, 0x53, 0x9b, 0x3e, 0xc3, 0xb7, 0xfd, 0xf6, 0x86, 0x0d, 0xa0, 0xeb,
+ 0x17, 0xf8, 0xcf, 0xb6, 0xf2, 0x43, 0x58, 0xbe, 0xcd, 0x83, 0x82, 0xc5,
+ 0xb9, 0x27, 0xb4, 0x46, 0xb7, 0x67, 0x16, 0x2e, 0xd4, 0xac, 0x57, 0xcd,
+ 0x77, 0x85, 0xef, 0xf8, 0xa4, 0xee, 0x58, 0x79, 0x58, 0xba, 0x77, 0x58,
+ 0xbf, 0xcf, 0xe6, 0x21, 0xfe, 0x56, 0x2f, 0xfb, 0x4f, 0x17, 0x30, 0xd7,
+ 0xd2, 0xc5, 0x40, 0xfb, 0x74, 0x65, 0x7b, 0xef, 0x05, 0x8b, 0x9e, 0x56,
+ 0x2f, 0xf9, 0xf6, 0xcf, 0xbe, 0xbe, 0xcb, 0x16, 0x1e, 0x26, 0xd5, 0x11,
+ 0x08, 0x0d, 0xb9, 0x08, 0x5f, 0x11, 0x04, 0x3b, 0xdc, 0x2d, 0x7f, 0xff,
+ 0x9a, 0x01, 0xeb, 0x3d, 0x9a, 0x01, 0xda, 0x1e, 0x6f, 0xac, 0x53, 0xa3,
+ 0x58, 0x9d, 0x28, 0xd5, 0xd4, 0x98, 0xf8, 0xd8, 0x74, 0xff, 0xf2, 0x20,
+ 0x42, 0x48, 0xa5, 0x4a, 0x5f, 0x87, 0x31, 0x7b, 0x16, 0x2f, 0x7a, 0x4e,
+ 0xb1, 0x43, 0x3c, 0x62, 0x29, 0xbf, 0xf8, 0xbd, 0xcf, 0xb4, 0x0c, 0xce,
+ 0xbc, 0xb1, 0x5d, 0xf1, 0x7d, 0x76, 0x61, 0x73, 0x02, 0x2c, 0x9d, 0x65,
+ 0x78, 0x5a, 0x88, 0x86, 0xff, 0xb0, 0xd2, 0xcf, 0x71, 0xf6, 0x58, 0xbf,
+ 0xd1, 0xf1, 0x72, 0x7e, 0xd1, 0xeb, 0x17, 0xfb, 0x37, 0x63, 0xe3, 0x8d,
+ 0x62, 0xff, 0x67, 0xfa, 0xdd, 0xf3, 0x4b, 0x17, 0xf6, 0x6a, 0x0e, 0x58,
+ 0xb1, 0x4e, 0x7c, 0x22, 0x35, 0xba, 0x7a, 0xd9, 0x16, 0xbe, 0x84, 0xa5,
+ 0x69, 0x35, 0xf6, 0x3a, 0x28, 0x78, 0x5f, 0xc1, 0xff, 0xfd, 0x34, 0x7a,
+ 0xc5, 0xff, 0x07, 0x31, 0x07, 0x3a, 0x68, 0x96, 0x2f, 0xdc, 0xcc, 0xf6,
+ 0x2c, 0x5c, 0xfe, 0x58, 0xbe, 0x66, 0x87, 0x16, 0x2c, 0x6c, 0x0d, 0xcf,
+ 0x85, 0xef, 0x49, 0x6c, 0xb1, 0x7c, 0xff, 0x73, 0xac, 0x53, 0x9b, 0xf8,
+ 0x87, 0x6b, 0xa4, 0x74, 0x69, 0x83, 0xec, 0xf7, 0xb9, 0xe7, 0x58, 0xba,
+ 0x21, 0x2c, 0x5b, 0x79, 0x36, 0xc4, 0x3b, 0x7f, 0xf6, 0xd3, 0xd7, 0x9c,
+ 0x28, 0xb3, 0x37, 0x58, 0xa9, 0x3e, 0xf1, 0x13, 0x58, 0x0b, 0x17, 0xfd,
+ 0x3e, 0xfb, 0x01, 0xba, 0xe2, 0xc5, 0x0c, 0xfb, 0x7a, 0x21, 0x21, 0x2b,
+ 0xfd, 0x8e, 0x71, 0x1d, 0xf8, 0xb1, 0x7f, 0xfb, 0x82, 0x6d, 0x0b, 0x69,
+ 0x34, 0x32, 0xf2, 0xc5, 0xfc, 0x28, 0x6e, 0xda, 0xd9, 0x62, 0xe6, 0x09,
+ 0x62, 0xa4, 0xf2, 0x58, 0xc6, 0x86, 0x8b, 0x7e, 0xd0, 0x97, 0xbf, 0xff,
+ 0x86, 0x1b, 0x68, 0xdc, 0x72, 0x93, 0xe7, 0x18, 0x96, 0x2d, 0x12, 0xc5,
+ 0x99, 0x62, 0x8c, 0x34, 0x91, 0xa0, 0x9d, 0xa7, 0x64, 0x52, 0x84, 0xfd,
+ 0x7f, 0xfc, 0x26, 0x1b, 0xc9, 0xcb, 0x36, 0xd8, 0x44, 0xb1, 0x5a, 0x3f,
+ 0xaf, 0x15, 0x5f, 0xfd, 0x9b, 0x34, 0x46, 0x7e, 0x79, 0xc6, 0x58, 0xbf,
+ 0xf8, 0x4c, 0xf0, 0x92, 0xdf, 0x3a, 0xf2, 0xc5, 0xf1, 0x09, 0xb7, 0x31,
+ 0x11, 0x9c, 0x47, 0xb8, 0xee, 0xb1, 0x7f, 0x7d, 0xf7, 0x16, 0x80, 0xb1,
+ 0x7f, 0xf8, 0xb3, 0xb4, 0xf3, 0xf9, 0x85, 0x0e, 0x2c, 0x58, 0x06, 0x1f,
+ 0xd7, 0x0c, 0x2f, 0xef, 0x7d, 0xcc, 0x2e, 0x96, 0x2f, 0x77, 0x4c, 0x7a,
+ 0xc5, 0x68, 0xff, 0x08, 0xa7, 0xb8, 0xc2, 0xfb, 0x07, 0x26, 0xac, 0x5e,
+ 0xd0, 0xb7, 0x58, 0xb9, 0xba, 0x58, 0xbb, 0xb4, 0xac, 0x5d, 0xdd, 0x12,
+ 0xc5, 0xc2, 0xd2, 0xc5, 0xf7, 0xb8, 0xdd, 0x96, 0x2c, 0x05, 0x8a, 0x88,
+ 0xf3, 0xc8, 0x63, 0xc4, 0xb7, 0xf6, 0x7a, 0x5b, 0x46, 0xac, 0x5e, 0xc7,
+ 0xf2, 0xc5, 0xff, 0x3e, 0xb3, 0xa8, 0xc0, 0x82, 0x09, 0x62, 0xbe, 0x7b,
+ 0xac, 0x39, 0x5d, 0xea, 0xaf, 0x79, 0x8c, 0x34, 0x66, 0x38, 0x47, 0xd0,
+ 0xfb, 0x8c, 0x47, 0x8c, 0xb3, 0x59, 0x17, 0xf2, 0x11, 0x77, 0xff, 0xa6,
+ 0x06, 0x07, 0xe7, 0x21, 0x43, 0x38, 0xb1, 0x7a, 0x0c, 0x35, 0x8a, 0x23,
+ 0xe9, 0x12, 0x65, 0xfc, 0x28, 0x85, 0xe1, 0x44, 0xb1, 0x7e, 0xc2, 0x35,
+ 0xf8, 0xb1, 0x40, 0x3d, 0xa1, 0x19, 0x5f, 0xff, 0x0b, 0x87, 0x9e, 0xb7,
+ 0xfb, 0x9c, 0x9f, 0x65, 0x8b, 0xd3, 0x9b, 0xac, 0x57, 0xcf, 0xc0, 0x94,
+ 0xef, 0xff, 0xfc, 0xd1, 0xe5, 0x8e, 0x45, 0x80, 0xcf, 0x49, 0xdf, 0xdf,
+ 0x75, 0x8b, 0xb8, 0x12, 0xc5, 0xfa, 0x78, 0x52, 0x75, 0x8a, 0xdc, 0xf0,
+ 0x3e, 0x33, 0x7f, 0xff, 0xff, 0x9b, 0x8e, 0x40, 0xfb, 0xfd, 0xbd, 0xf7,
+ 0xd4, 0x03, 0x29, 0xd6, 0x9f, 0xae, 0x3a, 0xc5, 0xff, 0xec, 0xf7, 0x36,
+ 0x10, 0xf0, 0x2c, 0x29, 0x58, 0xaf, 0xa3, 0x64, 0x10, 0x8e, 0xad, 0x99,
+ 0x9b, 0xe3, 0x34, 0xc8, 0xc9, 0x77, 0x8d, 0x0f, 0xa2, 0xf7, 0x87, 0x56,
+ 0xa3, 0x49, 0x3c, 0x2b, 0xbf, 0x2c, 0xc8, 0x11, 0x82, 0x93, 0xdf, 0x21,
+ 0x24, 0x22, 0x1e, 0xd0, 0xaa, 0x0e, 0x1f, 0x97, 0x70, 0x4b, 0x17, 0xfb,
+ 0xde, 0x7d, 0x67, 0x5e, 0x58, 0xbf, 0x39, 0xf7, 0x71, 0xac, 0x56, 0x8f,
+ 0x7b, 0xe6, 0xb7, 0xb4, 0xfe, 0x58, 0xbc, 0x06, 0x3a, 0xc5, 0xd8, 0x05,
+ 0x8a, 0x93, 0x69, 0x83, 0xb7, 0x9b, 0x0e, 0xb1, 0x5b, 0x26, 0x49, 0x8e,
+ 0xda, 0x22, 0x25, 0x1e, 0xe1, 0xfb, 0xf0, 0xe4, 0x5d, 0xff, 0x16, 0x2f,
+ 0xfe, 0x60, 0xff, 0x30, 0xe6, 0xb5, 0x9d, 0x2c, 0x58, 0xa0, 0x8c, 0x21,
+ 0xa6, 0xfc, 0xba, 0xfa, 0x7e, 0x2d, 0x2c, 0x5f, 0xdc, 0x2c, 0x19, 0x32,
+ 0xc5, 0x11, 0xe7, 0x84, 0x47, 0x7f, 0x3e, 0xa7, 0xaf, 0x4a, 0xc5, 0xdb,
+ 0xba, 0xc5, 0xf8, 0xa7, 0x69, 0xe9, 0x62, 0xf3, 0x47, 0x4a, 0xc5, 0xfc,
+ 0xda, 0x38, 0xb4, 0x05, 0x8b, 0xb4, 0x05, 0x8a, 0x81, 0xe3, 0xb9, 0x7d,
+ 0xf3, 0xec, 0x4c, 0xb1, 0x7d, 0xc3, 0x3c, 0xeb, 0x16, 0xe4, 0xa6, 0x79,
+ 0xb9, 0x73, 0x8c, 0x68, 0xa5, 0x99, 0xbc, 0x42, 0x19, 0x15, 0xfd, 0xa1,
+ 0x30, 0x6c, 0x35, 0x8a, 0x95, 0x4f, 0x6f, 0x08, 0x46, 0x8d, 0x78, 0x36,
+ 0xab, 0xee, 0x14, 0xec, 0xb1, 0x7f, 0xdb, 0x37, 0xd8, 0x64, 0xdb, 0xac,
+ 0x56, 0x8f, 0x74, 0x88, 0xef, 0xff, 0x82, 0xcd, 0xf9, 0x9e, 0x8b, 0x0d,
+ 0x2c, 0x02, 0xc5, 0x61, 0xfa, 0x39, 0x0d, 0xff, 0x11, 0xbf, 0x67, 0xf3,
+ 0x1d, 0x62, 0xf1, 0xdf, 0x4b, 0x17, 0xfd, 0x81, 0x66, 0xb7, 0x66, 0xdd,
+ 0x52, 0x87, 0x17, 0xfe, 0x84, 0x83, 0x93, 0xf7, 0xea, 0x0b, 0x17, 0xcf,
+ 0xac, 0xe9, 0x62, 0xb0, 0xf8, 0xe3, 0x90, 0x2f, 0xfe, 0x17, 0x07, 0xf6,
+ 0x3f, 0x50, 0x72, 0x58, 0xbf, 0x7b, 0xec, 0x40, 0x58, 0xa3, 0x13, 0x5a,
+ 0xd8, 0x74, 0xd8, 0x55, 0xfc, 0x91, 0x91, 0xae, 0x73, 0xac, 0x5f, 0xf7,
+ 0xb2, 0x26, 0x92, 0x98, 0x96, 0x2a, 0x23, 0xd0, 0x61, 0x7b, 0xec, 0xfb,
+ 0xf6, 0x58, 0xbf, 0xd8, 0x1e, 0x44, 0x14, 0xf4, 0xb1, 0x7e, 0xc8, 0x8a,
+ 0x4e, 0xb1, 0x6f, 0xb9, 0xef, 0xf8, 0xde, 0xcf, 0x8a, 0xc0, 0x75, 0x1c,
+ 0x9f, 0xe1, 0x44, 0x44, 0x5c, 0x84, 0x1d, 0xdb, 0xee, 0xa9, 0x41, 0x0a,
+ 0x82, 0xba, 0x7d, 0xe5, 0x90, 0x81, 0x7e, 0xfb, 0xdc, 0x7e, 0xcb, 0x16,
+ 0x95, 0x8b, 0x14, 0x9b, 0x6d, 0x12, 0xdf, 0xdc, 0x19, 0x67, 0xfb, 0xd5,
+ 0x8b, 0x83, 0xee, 0x58, 0xae, 0xf0, 0xf3, 0xce, 0x67, 0x76, 0x12, 0xc5,
+ 0xdf, 0xe2, 0xc5, 0x2c, 0x5f, 0xfd, 0x25, 0xbe, 0x7b, 0xef, 0xa0, 0x6e,
+ 0xb1, 0x58, 0x7d, 0x44, 0x31, 0xe0, 0xcb, 0xe7, 0xe7, 0xdd, 0x62, 0xf6,
+ 0x75, 0xe5, 0x8a, 0x19, 0xe0, 0x1c, 0x8a, 0xfe, 0x72, 0xcf, 0x7d, 0xd6,
+ 0x2d, 0x38, 0x79, 0xdc, 0x22, 0xa1, 0xa6, 0xc3, 0x90, 0x80, 0x14, 0x2e,
+ 0xef, 0xcd, 0x0f, 0xb8, 0x16, 0x2f, 0x85, 0x0c, 0x8e, 0x58, 0xbf, 0xda,
+ 0x6e, 0x6b, 0x58, 0x12, 0xc5, 0x0d, 0x10, 0x64, 0x51, 0xd8, 0x9a, 0xff,
+ 0xf7, 0xde, 0x2f, 0xbf, 0x5e, 0x2c, 0xec, 0xcb, 0x17, 0x86, 0xd1, 0x2c,
+ 0x5f, 0xf3, 0xf6, 0xfe, 0x6b, 0x4f, 0xd9, 0x62, 0xee, 0x41, 0x62, 0xa4,
+ 0xfc, 0xfe, 0x3d, 0xe3, 0xdb, 0xbd, 0xc5, 0x8b, 0xa4, 0x0b, 0x17, 0xfd,
+ 0xc9, 0x37, 0x82, 0x1f, 0xdd, 0x62, 0xa2, 0x3d, 0x2f, 0x0b, 0xd6, 0x22,
+ 0x34, 0x9a, 0xaf, 0xfe, 0xce, 0xb3, 0xd8, 0x50, 0xfb, 0x41, 0x62, 0xb0,
+ 0xf9, 0x48, 0x86, 0xfe, 0x3f, 0x38, 0xc5, 0xb2, 0xc5, 0x8e, 0xb1, 0x7e,
+ 0x22, 0xce, 0xa0, 0xb1, 0x47, 0x37, 0x41, 0x89, 0x54, 0xa2, 0x2d, 0x9a,
+ 0x6f, 0xf7, 0xb1, 0xcb, 0xdc, 0xc5, 0x8b, 0xfb, 0x3e, 0xfb, 0xff, 0x16,
+ 0x2f, 0xcf, 0xf6, 0x7d, 0x96, 0x2e, 0x98, 0xf5, 0x8b, 0x81, 0xc8, 0x1e,
+ 0x13, 0x94, 0x5f, 0x73, 0x0b, 0xcb, 0x17, 0xbb, 0xa7, 0x4b, 0x14, 0xe7,
+ 0xde, 0xc5, 0xa2, 0x22, 0xb8, 0x5c, 0x58, 0xb9, 0xbc, 0xb1, 0x7f, 0x81,
+ 0x83, 0xcf, 0x48, 0xd6, 0x2a, 0x23, 0xe2, 0xf8, 0xc3, 0x0b, 0xde, 0xf3,
+ 0x47, 0xac, 0x5f, 0x40, 0x4c, 0x1a, 0xc5, 0xfb, 0x3b, 0x16, 0x71, 0x62,
+ 0xfb, 0xb7, 0x69, 0xe2, 0xc5, 0x11, 0xe8, 0x06, 0x53, 0x7f, 0x7d, 0xe3,
+ 0x00, 0xce, 0xb1, 0x44, 0x8c, 0x6e, 0x3a, 0x78, 0x8a, 0xff, 0x1b, 0xf9,
+ 0x80, 0x9b, 0x4b, 0x16, 0x25, 0x8a, 0x73, 0xc6, 0x11, 0xad, 0x4b, 0x23,
+ 0x87, 0x67, 0x41, 0xc7, 0x11, 0x90, 0xbd, 0xdc, 0xc6, 0x28, 0x60, 0x1e,
+ 0x32, 0x0f, 0xc2, 0xad, 0x88, 0x40, 0x64, 0x50, 0xdf, 0xe4, 0x23, 0xfc,
+ 0x5e, 0x28, 0x73, 0x47, 0x3a, 0xdf, 0x60, 0xc7, 0x2b, 0x17, 0x64, 0x7a,
+ 0xc5, 0x61, 0xbc, 0x88, 0x8a, 0xff, 0xfb, 0xae, 0x0a, 0x7a, 0x2c, 0xdc,
+ 0xb0, 0x5b, 0x2c, 0x5f, 0x8d, 0x03, 0xc5, 0xc5, 0x8b, 0xef, 0xbb, 0x41,
+ 0x62, 0xf0, 0xda, 0x0b, 0x15, 0x26, 0xff, 0x08, 0xaf, 0xf7, 0xda, 0x23,
+ 0x37, 0x91, 0xac, 0x54, 0xa3, 0x00, 0x0d, 0x5c, 0x1f, 0xa9, 0x4d, 0x08,
+ 0x51, 0x89, 0xdf, 0xdf, 0x98, 0x7c, 0x43, 0x58, 0xbc, 0x00, 0xfa, 0x58,
+ 0xbb, 0x3b, 0x2c, 0x5e, 0xf1, 0x41, 0x62, 0xc7, 0xc3, 0xd6, 0xf1, 0x07,
+ 0x61, 0x9b, 0xff, 0xc6, 0x13, 0x7a, 0x74, 0x28, 0x6a, 0x60, 0xb1, 0x7e,
+ 0x9f, 0x7e, 0x62, 0x58, 0xbb, 0xdc, 0x58, 0xbf, 0x31, 0xa1, 0x4e, 0x96,
+ 0x2a, 0x09, 0xb8, 0xef, 0x08, 0x57, 0x36, 0xfa, 0x5b, 0x14, 0x90, 0xc5,
+ 0xfe, 0x72, 0xf4, 0x33, 0x58, 0xb1, 0x7f, 0xf3, 0xee, 0x58, 0x79, 0x88,
+ 0x73, 0xb2, 0xc5, 0xff, 0xd0, 0x2c, 0x3b, 0x16, 0x7d, 0x8e, 0xb1, 0x7f,
+ 0xb3, 0xd3, 0xd9, 0xc8, 0x0b, 0x17, 0xff, 0xc0, 0x3b, 0x42, 0x18, 0x00,
+ 0xfd, 0xb7, 0x04, 0xb1, 0x5b, 0xa2, 0x23, 0x46, 0x97, 0xfe, 0xcf, 0x7b,
+ 0xf8, 0x31, 0x7b, 0x8b, 0x17, 0xfe, 0x0f, 0xa3, 0x24, 0xc8, 0x8a, 0x4e,
+ 0xb1, 0x7f, 0xb5, 0x2e, 0x32, 0x68, 0x2c, 0x5f, 0xfb, 0x4e, 0x5b, 0x96,
+ 0x6d, 0x81, 0x2c, 0x5f, 0xf6, 0x76, 0x9c, 0xeb, 0xaf, 0x77, 0xd5, 0x62,
+ 0xfd, 0x3e, 0xe6, 0x11, 0x88, 0xb7, 0xd1, 0x97, 0xd0, 0x28, 0x69, 0xa3,
+ 0x8a, 0x1f, 0x77, 0xed, 0xff, 0xd3, 0x47, 0xac, 0x5f, 0xee, 0x4c, 0x0d,
+ 0x37, 0x23, 0xd6, 0x2f, 0xfc, 0x32, 0x17, 0xb9, 0x25, 0x3c, 0x58, 0xa9,
+ 0x3f, 0x77, 0x39, 0xb7, 0x7e, 0xb1, 0x50, 0x57, 0xe5, 0xb9, 0x97, 0x48,
+ 0xcf, 0x0c, 0xaf, 0x92, 0x14, 0x70, 0xe2, 0x29, 0xed, 0x0a, 0x50, 0x88,
+ 0x2f, 0xf1, 0x60, 0x38, 0xc4, 0x05, 0x8b, 0xf4, 0x3f, 0x3a, 0xd9, 0x62,
+ 0x9c, 0xf7, 0x18, 0xca, 0xf7, 0xdc, 0xd5, 0x8b, 0xcd, 0xa8, 0x2c, 0x5f,
+ 0x48, 0x3e, 0xcb, 0x15, 0xc3, 0x7f, 0xe1, 0xdb, 0xf4, 0x58, 0x58, 0x35,
+ 0x8b, 0xff, 0xbc, 0x32, 0x98, 0x7f, 0x30, 0xb7, 0x58, 0xbf, 0xff, 0x8e,
+ 0xc5, 0x0e, 0xbc, 0xe1, 0x6f, 0xf7, 0x3c, 0xee, 0xb1, 0x52, 0x8a, 0x31,
+ 0x22, 0x5f, 0xff, 0xb4, 0x00, 0x0b, 0x9a, 0x6e, 0x3f, 0x89, 0xa0, 0xb1,
+ 0x7f, 0xf9, 0xe7, 0xc5, 0x9e, 0xfe, 0x3c, 0x3b, 0x2c, 0x5f, 0xf7, 0x5c,
+ 0x03, 0x10, 0xe2, 0x12, 0xc5, 0xc4, 0x12, 0xc5, 0xff, 0xd9, 0xb0, 0x70,
+ 0x1e, 0x79, 0xfe, 0x25, 0x8b, 0xf6, 0xb3, 0xb6, 0x0f, 0x47, 0xbe, 0x43,
+ 0x14, 0xe8, 0xda, 0x68, 0x4d, 0xdf, 0xff, 0x84, 0x50, 0xc2, 0xf3, 0xc7,
+ 0x67, 0x89, 0xa0, 0xb1, 0x7f, 0xa4, 0x13, 0xfc, 0xea, 0x0b, 0x14, 0xe8,
+ 0x8a, 0x25, 0x6b, 0xff, 0xef, 0xb1, 0xe2, 0x29, 0x3f, 0x50, 0xfe, 0x6c,
+ 0xb1, 0x58, 0xaa, 0x7b, 0xea, 0xc0, 0x8c, 0x93, 0xd0, 0xb0, 0x11, 0x0d,
+ 0xf4, 0x4d, 0x13, 0x2c, 0x5e, 0xdb, 0x02, 0x58, 0xb4, 0x16, 0x2d, 0xe3,
+ 0x0d, 0x88, 0x87, 0xed, 0x05, 0x8a, 0x63, 0x74, 0x22, 0x8b, 0xa7, 0x8b,
+ 0x14, 0x62, 0x31, 0x8a, 0x11, 0xfe, 0x20, 0xbf, 0xef, 0xb1, 0x64, 0x50,
+ 0x9e, 0x96, 0x2f, 0xfe, 0xfb, 0xeb, 0x38, 0x59, 0xdb, 0xee, 0xb1, 0x7e,
+ 0x2c, 0xe0, 0x8c, 0xc3, 0xff, 0x88, 0xea, 0xff, 0x48, 0x07, 0xf9, 0x2d,
+ 0xd6, 0x2f, 0xda, 0xdd, 0x9b, 0x75, 0x48, 0x0c, 0x5f, 0xcd, 0xb0, 0x18,
+ 0x86, 0x88, 0x41, 0xe5, 0xec, 0xe0, 0x86, 0x8a, 0x7c, 0x34, 0x8e, 0x37,
+ 0xbd, 0xf6, 0x81, 0x89, 0x94, 0x94, 0x39, 0xaf, 0xfb, 0xef, 0x85, 0x9b,
+ 0x8f, 0x16, 0x28, 0x6b, 0xf2, 0x9b, 0x90, 0x3a, 0xec, 0x44, 0x3a, 0x86,
+ 0x59, 0xe5, 0x60, 0x14, 0x63, 0x9e, 0x8f, 0x77, 0xb1, 0xd5, 0xfe, 0x01,
+ 0x09, 0xba, 0x8d, 0xbb, 0xd5, 0x8b, 0xde, 0x14, 0xac, 0x5f, 0xfe, 0xfb,
+ 0xfb, 0x30, 0xfc, 0x9c, 0x1b, 0xac, 0x5d, 0xce, 0x2c, 0x5f, 0x0f, 0xec,
+ 0x75, 0x8b, 0xfe, 0xcd, 0x83, 0x83, 0xcf, 0x5e, 0x58, 0xb0, 0x37, 0x45,
+ 0xfe, 0x92, 0x18, 0x60, 0x88, 0xef, 0xf0, 0x3c, 0xfb, 0x1e, 0x77, 0x58,
+ 0xbe, 0xd6, 0x84, 0x6a, 0xc5, 0x4a, 0x77, 0x1d, 0x1f, 0xb4, 0x37, 0x09,
+ 0x08, 0x33, 0x6b, 0xf0, 0xe3, 0x46, 0x1c, 0x68, 0xb1, 0x7f, 0x6f, 0xd7,
+ 0xfa, 0x68, 0xf5, 0x8b, 0xfd, 0xf9, 0xd6, 0x61, 0x1a, 0xb1, 0x7b, 0x41,
+ 0xc4, 0xb1, 0x6c, 0x81, 0xe9, 0xb9, 0x9d, 0xf9, 0xb5, 0xec, 0xdd, 0x62,
+ 0xf8, 0x6f, 0x3b, 0x2c, 0x5a, 0x74, 0x79, 0x82, 0x29, 0xbf, 0xd9, 0x9d,
+ 0x01, 0x8b, 0xcb, 0x17, 0xf0, 0xff, 0x27, 0x29, 0x58, 0xbf, 0x4e, 0x0d,
+ 0xc9, 0x62, 0xf1, 0x67, 0x16, 0x2e, 0x71, 0x98, 0x8a, 0x2e, 0x19, 0x88,
+ 0xb7, 0xb1, 0x35, 0xa1, 0x04, 0xc5, 0x39, 0x0c, 0x9a, 0x95, 0x47, 0xbd,
+ 0x42, 0x21, 0xa3, 0x86, 0xa9, 0x66, 0xe8, 0xe5, 0x22, 0x0d, 0xe5, 0x29,
+ 0xb2, 0x78, 0xa5, 0x38, 0x5c, 0xf0, 0x58, 0xbd, 0xa7, 0xf2, 0xc5, 0xfb,
+ 0xc3, 0xcc, 0x35, 0x62, 0x86, 0x78, 0xdd, 0x0e, 0xdf, 0xdf, 0x7f, 0x73,
+ 0x3c, 0xb1, 0x7f, 0x16, 0xa7, 0x7c, 0xd2, 0xc5, 0xf6, 0x44, 0xe7, 0x58,
+ 0xa1, 0xa3, 0xff, 0x17, 0x77, 0x23, 0x62, 0xe0, 0xcb, 0xaf, 0xff, 0xb5,
+ 0x3d, 0x40, 0xef, 0x9d, 0x7f, 0x35, 0xb2, 0xc5, 0xa5, 0x62, 0xfa, 0x49,
+ 0xc0, 0xb1, 0x6c, 0xf9, 0xb2, 0xf0, 0x8d, 0xfe, 0xd1, 0x30, 0x41, 0xf4,
+ 0x12, 0xc5, 0xc0, 0xec, 0xb1, 0x7e, 0xf7, 0xc5, 0xb0, 0x96, 0x28, 0x67,
+ 0xfb, 0xf3, 0x81, 0x0d, 0x5f, 0xf7, 0xdf, 0xe5, 0x39, 0xac, 0x58, 0xbf,
+ 0xd0, 0x2c, 0xec, 0xe4, 0x35, 0x8b, 0x9c, 0x1b, 0x9f, 0x5b, 0x1b, 0xdf,
+ 0x89, 0xbc, 0xdd, 0x2c, 0x5e, 0xf3, 0x76, 0x58, 0xbf, 0xc3, 0xea, 0x19,
+ 0x85, 0xb2, 0xc5, 0x86, 0xb1, 0x7f, 0xe8, 0x4c, 0x7e, 0x6b, 0xdc, 0x98,
+ 0x2c, 0x5f, 0xf7, 0x43, 0x9e, 0x38, 0xff, 0x2b, 0x17, 0xf7, 0x5e, 0x8b,
+ 0xf2, 0x4b, 0x17, 0xf9, 0xfd, 0xc6, 0xe8, 0x01, 0x2c, 0x5d, 0xad, 0x95,
+ 0x28, 0x29, 0x5f, 0x3d, 0xc6, 0x36, 0xbf, 0xf3, 0x6b, 0x08, 0x1c, 0xf7,
+ 0x3a, 0x58, 0xbf, 0xfe, 0xc3, 0x4f, 0x38, 0x5e, 0xe7, 0x05, 0xa0, 0x2c,
+ 0x5f, 0xff, 0xff, 0xd9, 0xef, 0xb1, 0x1a, 0x67, 0x34, 0xcd, 0xee, 0xd8,
+ 0x33, 0x30, 0xec, 0x5d, 0x41, 0x72, 0x05, 0x97, 0xfe, 0x66, 0x37, 0x76,
+ 0x19, 0x86, 0x84, 0xb9, 0x02, 0xcb, 0xff, 0xbe, 0xff, 0x79, 0x2f, 0x18,
+ 0x68, 0x4b, 0x90, 0x2c, 0xbf, 0xd2, 0xe5, 0xe3, 0x0d, 0x09, 0x72, 0x05,
+ 0x97, 0xf1, 0xf0, 0x66, 0x1a, 0x12, 0xe4, 0x0b, 0x2f, 0xff, 0xf9, 0x88,
+ 0x9c, 0xe6, 0x73, 0x7f, 0xbe, 0x9c, 0xdd, 0xb0, 0x25, 0xc8, 0x16, 0x5d,
+ 0xd1, 0x83, 0x4e, 0x7b, 0x75, 0x1d, 0x2a, 0x32, 0x19, 0x1f, 0xd4, 0xab,
+ 0x21, 0xc4, 0x0f, 0xa8, 0x94, 0xa3, 0x8b, 0xfc, 0xf2, 0x6f, 0x3d, 0xce,
+ 0x96, 0x2f, 0xf3, 0x36, 0xd9, 0x09, 0x35, 0x62, 0xff, 0xa4, 0xb7, 0x9f,
+ 0x73, 0xee, 0xb1, 0x7c, 0xde, 0x93, 0x22, 0x3e, 0xd3, 0x9a, 0x5f, 0xfe,
+ 0x3e, 0x0c, 0xc0, 0xca, 0x7f, 0x25, 0xba, 0xc5, 0xf3, 0x68, 0x0c, 0xb1,
+ 0x7f, 0xf7, 0xdf, 0xef, 0x25, 0xe3, 0x0d, 0x09, 0x72, 0x05, 0x97, 0xfd,
+ 0x17, 0x37, 0x7d, 0x8c, 0x34, 0x25, 0xc8, 0x16, 0x5f, 0xbd, 0xc9, 0x39,
+ 0x9b, 0xa2, 0x88, 0x35, 0x4b, 0xff, 0xc6, 0x6f, 0xf7, 0xde, 0x7d, 0xc3,
+ 0x0d, 0x09, 0x72, 0x05, 0x97, 0xff, 0xff, 0x11, 0x39, 0xcc, 0x16, 0x19,
+ 0xcd, 0xfe, 0xfa, 0x73, 0x76, 0xc0, 0x97, 0x20, 0x59, 0x58, 0x99, 0x37,
+ 0x48, 0x6c, 0xbf, 0x7f, 0x9f, 0x4e, 0x6e, 0xd8, 0x12, 0xe4, 0x0b, 0x2f,
+ 0xfd, 0xb1, 0xc4, 0xe7, 0x62, 0xea, 0x0b, 0x90, 0x2c, 0xaf, 0xa2, 0x44,
+ 0x48, 0x77, 0xff, 0xcc, 0xdd, 0x43, 0x9f, 0x71, 0x8e, 0x75, 0x29, 0x17,
+ 0xff, 0x9c, 0x0c, 0x43, 0x33, 0xaf, 0x0a, 0x59, 0x62, 0xff, 0xd9, 0x08,
+ 0x0b, 0x9a, 0x2d, 0xa3, 0x97, 0x20, 0x59, 0x5b, 0xa6, 0x1f, 0xa2, 0x3f,
+ 0xa8, 0x71, 0x2e, 0xff, 0xdb, 0xbe, 0xbc, 0xc0, 0xe1, 0x81, 0x2e, 0x40,
+ 0xb2, 0xfe, 0xfb, 0xff, 0xee, 0x05, 0x58, 0x16, 0x5f, 0xb0, 0x06, 0x1a,
+ 0x12, 0xe4, 0x0b, 0x2e, 0xcf, 0x6e, 0x7e, 0x9f, 0x3b, 0xae, 0x91, 0xe5,
+ 0xc8, 0x62, 0x5f, 0xc7, 0xc1, 0x98, 0x68, 0x4b, 0x90, 0x2c, 0xbf, 0xf6,
+ 0xff, 0x7d, 0x39, 0xbb, 0x60, 0x4b, 0x90, 0x2c, 0xbb, 0x0c, 0x64, 0x47,
+ 0xf0, 0xfe, 0xff, 0x09, 0xce, 0xc5, 0xd4, 0x17, 0x20, 0x59, 0x7f, 0xec,
+ 0x7e, 0xd8, 0x58, 0x36, 0x82, 0xe4, 0x0b, 0x0e, 0x78, 0x34, 0x35, 0xfd,
+ 0xad, 0x21, 0x9e, 0x14, 0x6c, 0x74, 0x04, 0xc2, 0x8f, 0xab, 0x91, 0xe8,
+ 0x7a, 0x33, 0x11, 0x42, 0xe0, 0x26, 0xfb, 0x81, 0x2a, 0x90, 0x2c, 0x8c,
+ 0x45, 0x4d, 0xcd, 0xba, 0xc5, 0x0d, 0x99, 0xb9, 0x87, 0x5b, 0xc2, 0x30,
+ 0x14, 0xbc, 0x5f, 0x1c, 0xd6, 0x33, 0x70, 0x77, 0x35, 0x88, 0x4b, 0x94,
+ 0xd1, 0xeb, 0xa1, 0xdc, 0xb1, 0x7a, 0x61, 0xdc, 0xb1, 0x52, 0x6e, 0xc8,
+ 0x6e, 0xb6, 0x6c, 0x39, 0xa0, 0x94, 0x38, 0x42, 0xf5, 0x0a, 0x3d, 0x42,
+ 0x6b, 0xe5, 0xac, 0x50, 0x0a, 0x6f, 0x01, 0x42, 0x1a, 0xf8, 0x32, 0xce,
+ 0xcb, 0x17, 0xf4, 0x9f, 0x77, 0xfe, 0x2c, 0x5f, 0xfa, 0x05, 0x9e, 0xfb,
+ 0xe7, 0x5e, 0x58, 0xbf, 0x8a, 0x1c, 0xf7, 0xe5, 0x62, 0xff, 0xff, 0xd9,
+ 0xef, 0xb4, 0x07, 0x9a, 0x7c, 0xec, 0x1e, 0xbe, 0xfd, 0x79, 0x62, 0xe7,
+ 0x35, 0x62, 0xfb, 0xb1, 0x67, 0x16, 0x2f, 0xee, 0xb8, 0xde, 0x9e, 0x2c,
+ 0x5f, 0x66, 0xe7, 0x75, 0x8b, 0x8a, 0x18, 0x7e, 0xce, 0x49, 0xf2, 0xfa,
+ 0x94, 0xfd, 0xa0, 0x4b, 0x85, 0xce, 0x7e, 0x72, 0xef, 0xb8, 0x07, 0x08,
+ 0xeb, 0xc0, 0x38, 0x16, 0x2f, 0xf4, 0xfd, 0xc2, 0xea, 0x1c, 0x58, 0xbf,
+ 0x4f, 0xb9, 0xf7, 0x58, 0xbf, 0xf6, 0xb0, 0xdf, 0xe1, 0xc5, 0xad, 0x96,
+ 0x2f, 0xfb, 0xa2, 0xc7, 0x3e, 0x10, 0x16, 0x2f, 0xff, 0xff, 0xcd, 0x11,
+ 0x30, 0x59, 0xd9, 0xf9, 0xfc, 0x04, 0x76, 0x7b, 0x8c, 0x7c, 0xeb, 0xcb,
+ 0x17, 0xfb, 0xec, 0x43, 0xce, 0xbc, 0xb1, 0x7f, 0xe6, 0x6d, 0xb0, 0xec,
+ 0x5d, 0x41, 0x62, 0xf7, 0x30, 0x96, 0x2d, 0x0c, 0x44, 0x7c, 0x46, 0x9e,
+ 0x3f, 0xbf, 0xb7, 0x9e, 0xed, 0xdf, 0xb9, 0x62, 0xff, 0xf3, 0x6f, 0x24,
+ 0x32, 0xce, 0xda, 0x7e, 0x2c, 0x5f, 0xfb, 0x91, 0x40, 0x43, 0x8a, 0x02,
+ 0x1a, 0xc5, 0x18, 0xac, 0x27, 0x61, 0xe8, 0x1b, 0x0c, 0xa3, 0x10, 0x8d,
+ 0x38, 0xea, 0x31, 0x83, 0x9b, 0x7c, 0xdb, 0xc9, 0x77, 0xfd, 0x9e, 0x0b,
+ 0x08, 0x7f, 0x95, 0x8b, 0xdc, 0x70, 0x96, 0x2f, 0xfe, 0x9e, 0xa0, 0x19,
+ 0xf9, 0xe9, 0xe8, 0x25, 0x8b, 0xf4, 0x3b, 0xbb, 0x85, 0xb2, 0xc5, 0x39,
+ 0xfd, 0xb2, 0x55, 0x74, 0x8b, 0x9f, 0xc2, 0x66, 0xff, 0xe7, 0xce, 0x19,
+ 0xac, 0x7f, 0xc8, 0xd6, 0x2f, 0xfd, 0x8f, 0xcd, 0x64, 0x0a, 0x4e, 0xb1,
+ 0x7d, 0xe2, 0x93, 0xac, 0x5f, 0xb5, 0x3d, 0x43, 0x8b, 0x17, 0xe8, 0xec,
+ 0xee, 0xc2, 0x58, 0xad, 0x95, 0x0a, 0xc2, 0x1e, 0x46, 0x94, 0xee, 0x88,
+ 0xe7, 0xba, 0x22, 0x01, 0x55, 0xff, 0x49, 0xbf, 0xc2, 0x2c, 0xe9, 0x62,
+ 0xff, 0xfe, 0xeb, 0x9e, 0x33, 0xdf, 0x76, 0x04, 0x50, 0xce, 0xa0, 0xb1,
+ 0x78, 0xed, 0xe5, 0x8b, 0xfe, 0x68, 0x66, 0x86, 0x31, 0x41, 0x62, 0xdc,
+ 0x58, 0xa3, 0x9e, 0x63, 0x1d, 0x5d, 0xcd, 0xd6, 0x2f, 0x41, 0xfc, 0xb1,
+ 0x7f, 0xfb, 0xce, 0x42, 0x86, 0x70, 0x1e, 0xf7, 0x4b, 0x16, 0x28, 0x8f,
+ 0xa4, 0x31, 0xdb, 0xec, 0x89, 0xa2, 0x58, 0xbf, 0xee, 0x37, 0x51, 0xc2,
+ 0xfb, 0xe9, 0x62, 0xfe, 0xcd, 0x00, 0xef, 0xc5, 0x8b, 0x85, 0xcf, 0xa2,
+ 0x43, 0xc4, 0x91, 0xc7, 0xd7, 0xfe, 0xce, 0xbd, 0x9e, 0x9d, 0x61, 0x2c,
+ 0x5e, 0x97, 0x3a, 0xc5, 0x8d, 0x58, 0xb6, 0x6e, 0x6b, 0xf4, 0x39, 0x7f,
+ 0xf7, 0x6e, 0xd3, 0xc6, 0xff, 0x50, 0xcf, 0x2c, 0x56, 0x27, 0xac, 0x08,
+ 0x5c, 0xf0, 0xfe, 0x39, 0xb4, 0x32, 0x7b, 0xf8, 0x51, 0x49, 0x71, 0xd6,
+ 0x2f, 0xf1, 0x07, 0x9a, 0x29, 0x3a, 0xc5, 0xfc, 0x2f, 0x14, 0xfb, 0x8b,
+ 0x15, 0x87, 0xc2, 0x03, 0x3b, 0x4a, 0xc5, 0x41, 0x5f, 0xb1, 0xad, 0x3f,
+ 0x21, 0x04, 0xa5, 0x82, 0x53, 0xe4, 0x23, 0xfb, 0x88, 0x6a, 0x59, 0x03,
+ 0xb9, 0x2a, 0xaf, 0xa6, 0xd7, 0x39, 0x69, 0xc5, 0x7b, 0xc7, 0x7e, 0x2c,
+ 0x5f, 0xe1, 0xb0, 0x30, 0x6f, 0xc5, 0x8b, 0xf1, 0xa3, 0x96, 0x25, 0x8b,
+ 0xff, 0x73, 0x3e, 0xf0, 0x71, 0xe1, 0xd6, 0x2f, 0xd0, 0x9e, 0xcd, 0xf5,
+ 0x8a, 0xd9, 0x1c, 0x10, 0x1d, 0xc3, 0x33, 0x4a, 0x18, 0xfa, 0xff, 0xec,
+ 0xeb, 0xdc, 0x72, 0x90, 0x31, 0xd6, 0x2f, 0xff, 0xe3, 0x4c, 0xfe, 0x6b,
+ 0x59, 0xdd, 0x9b, 0xc7, 0xb9, 0x76, 0x58, 0xbf, 0xe0, 0x83, 0x26, 0xdf,
+ 0x0b, 0x75, 0x8b, 0xee, 0xec, 0xcd, 0x96, 0x2f, 0xff, 0xbd, 0xf7, 0x30,
+ 0xd6, 0x30, 0xb0, 0x26, 0x02, 0xc5, 0xfc, 0x6e, 0xa6, 0x0c, 0x6a, 0xc5,
+ 0x62, 0x20, 0xd9, 0x4e, 0xf8, 0xe3, 0xc3, 0xac, 0x5d, 0xde, 0xf7, 0x8b,
+ 0x14, 0xb1, 0x7f, 0x9f, 0xe5, 0x9e, 0x90, 0x2c, 0x5e, 0xf8, 0xc3, 0x39,
+ 0xbe, 0xf0, 0x65, 0xff, 0x76, 0x72, 0x18, 0xbf, 0x87, 0x58, 0xbf, 0x9b,
+ 0xef, 0xc9, 0x82, 0xc5, 0x18, 0x98, 0xfc, 0x68, 0x47, 0x2c, 0x18, 0x69,
+ 0xc3, 0xbb, 0xff, 0x77, 0xf8, 0x45, 0x81, 0xc9, 0x01, 0x62, 0xf8, 0xee,
+ 0xd0, 0x58, 0xbf, 0x3e, 0xc5, 0x27, 0x58, 0xa3, 0x9e, 0x57, 0xc8, 0xaf,
+ 0xf6, 0x7d, 0xf8, 0xe2, 0x82, 0xc5, 0x6c, 0xaf, 0xff, 0x11, 0x1d, 0x9b,
+ 0xe7, 0x85, 0x0a, 0x9f, 0x46, 0x80, 0x24, 0xfe, 0xd0, 0x8c, 0xee, 0x22,
+ 0xbd, 0xc9, 0xe9, 0x62, 0xff, 0xff, 0xfe, 0xce, 0xc5, 0x9c, 0x33, 0xc6,
+ 0xc9, 0x43, 0x3e, 0xe7, 0x30, 0x78, 0x31, 0xb1, 0xd6, 0x2b, 0xa4, 0x55,
+ 0x10, 0xf5, 0xfd, 0x07, 0xe0, 0x7d, 0x01, 0x62, 0xff, 0xff, 0xdf, 0x7d,
+ 0x3c, 0x9f, 0x09, 0xe7, 0xec, 0xfa, 0xd3, 0xec, 0xb1, 0x7f, 0xe8, 0x67,
+ 0x50, 0xd4, 0xf9, 0xbc, 0xb1, 0x78, 0xf3, 0x05, 0x8b, 0xdf, 0x10, 0x4b,
+ 0x17, 0x8f, 0x30, 0x58, 0xb6, 0x0c, 0xde, 0x00, 0x7e, 0xff, 0xfc, 0x42,
+ 0x8f, 0xfb, 0xea, 0x7e, 0xdc, 0x2c, 0x02, 0xc5, 0x18, 0x9e, 0x9c, 0x91,
+ 0xee, 0x63, 0x13, 0x4b, 0x20, 0x12, 0xc8, 0x64, 0xd7, 0xfd, 0xbf, 0xdc,
+ 0x7f, 0x9f, 0x71, 0x62, 0xfb, 0x53, 0xd0, 0x16, 0x2f, 0xef, 0x3e, 0x9b,
+ 0x69, 0x58, 0xb3, 0x40, 0xf4, 0x9c, 0x92, 0xf0, 0xdb, 0xcb, 0x17, 0xff,
+ 0xc5, 0x9d, 0x7b, 0x53, 0x07, 0xe0, 0x7d, 0x01, 0x62, 0xe9, 0xe9, 0x62,
+ 0xff, 0xfd, 0xef, 0x64, 0x50, 0xcd, 0x8c, 0xea, 0x4a, 0x78, 0xb1, 0x7f,
+ 0x89, 0xba, 0xf0, 0x53, 0xd2, 0xc5, 0xff, 0xef, 0x64, 0x50, 0xcd, 0xba,
+ 0x92, 0x9e, 0x2c, 0x5d, 0x3d, 0x18, 0x8d, 0xbf, 0xac, 0xf8, 0xda, 0xa5,
+ 0x38, 0x30, 0x29, 0x94, 0x3c, 0xef, 0xd2, 0xc3, 0xd3, 0x2c, 0x5f, 0xd8,
+ 0x3f, 0xce, 0x99, 0x62, 0xff, 0xd2, 0x17, 0xf4, 0xd0, 0xfb, 0xe9, 0x62,
+ 0xf3, 0x68, 0xd8, 0x91, 0x28, 0x44, 0xe1, 0x96, 0xdf, 0xf1, 0x18, 0xf1,
+ 0xed, 0xc7, 0x3a, 0xc5, 0xff, 0x49, 0x4c, 0x3d, 0xfc, 0x25, 0x8a, 0xc3,
+ 0xf3, 0xe1, 0xe5, 0x69, 0x71, 0x60, 0xec, 0xdf, 0x84, 0x6b, 0x13, 0x02,
+ 0x3a, 0x02, 0x86, 0x47, 0x21, 0x6d, 0x79, 0xe3, 0xb1, 0x62, 0xf3, 0xf5,
+ 0xe5, 0x8b, 0xdf, 0xd9, 0xd6, 0x2e, 0xc0, 0xb8, 0x6f, 0x04, 0x3d, 0x7f,
+ 0xed, 0x13, 0x04, 0xda, 0xd6, 0x74, 0xb1, 0x7f, 0x9f, 0x47, 0x9c, 0x21,
+ 0xac, 0x5c, 0xe6, 0xac, 0x57, 0xcf, 0x28, 0x8c, 0xaf, 0xee, 0x38, 0xf0,
+ 0x2e, 0x2c, 0x5f, 0xcd, 0xa6, 0x1b, 0xe2, 0xc5, 0xdd, 0x3a, 0xc5, 0xa2,
+ 0x58, 0xbb, 0x40, 0x58, 0xbb, 0x02, 0x58, 0xaf, 0x9e, 0x1b, 0x09, 0xf8,
+ 0x62, 0xa5, 0x50, 0xbe, 0xcb, 0x63, 0x2d, 0xc8, 0x45, 0x74, 0x43, 0xf2,
+ 0xf2, 0x2c, 0xf2, 0xdd, 0xff, 0x67, 0x1c, 0x72, 0x52, 0x05, 0x8b, 0x9f,
+ 0x4b, 0x17, 0xe6, 0x2f, 0x72, 0x56, 0x2f, 0xed, 0x70, 0x47, 0xcd, 0x2c,
+ 0x59, 0xd6, 0x29, 0xcf, 0x01, 0x8b, 0xef, 0xb0, 0xd9, 0xe2, 0xc5, 0x69,
+ 0x15, 0x47, 0x67, 0x22, 0x0a, 0xe9, 0x39, 0xed, 0x3b, 0xfc, 0xdc, 0x10,
+ 0xc1, 0xbe, 0x0b, 0x3e, 0xcb, 0x17, 0xc6, 0xe9, 0xc2, 0x58, 0xbf, 0x6c,
+ 0xdf, 0x98, 0xf5, 0x8b, 0x8f, 0x2b, 0x17, 0xf1, 0x4c, 0x3d, 0x9b, 0xac,
+ 0x58, 0xd8, 0x1e, 0x2e, 0x0b, 0xde, 0xe4, 0x8d, 0x62, 0xf4, 0x76, 0x79,
+ 0x62, 0xdb, 0x74, 0x6f, 0x7c, 0x3b, 0x5d, 0xe2, 0x64, 0x98, 0x4a, 0xee,
+ 0x22, 0x65, 0xbf, 0x8d, 0xfc, 0xf5, 0xec, 0x58, 0xbf, 0xc5, 0x83, 0xfc,
+ 0x84, 0x4b, 0x17, 0xb3, 0x52, 0xb1, 0x7f, 0x0f, 0xec, 0x1e, 0x6c, 0xb1,
+ 0x50, 0x3c, 0xcf, 0x0e, 0x54, 0xa3, 0x47, 0x46, 0x04, 0xff, 0x7f, 0xff,
+ 0xb5, 0x3f, 0x9d, 0x6a, 0x76, 0xf3, 0x31, 0xb9, 0xd7, 0x96, 0x2a, 0x5b,
+ 0x30, 0xec, 0x9c, 0x49, 0x79, 0xf6, 0x86, 0x9c, 0x2f, 0x02, 0x21, 0x46,
+ 0x8e, 0x28, 0xc4, 0x83, 0x2e, 0xbe, 0xf9, 0xdb, 0xcb, 0x17, 0xc5, 0x17,
+ 0x31, 0x62, 0xfd, 0x0c, 0xdb, 0xd2, 0xb1, 0x7f, 0xff, 0x4f, 0x83, 0xd8,
+ 0x79, 0xe9, 0xec, 0xfe, 0x04, 0xc1, 0x62, 0xfe, 0xfb, 0xeb, 0x4d, 0x05,
+ 0x8b, 0x01, 0x62, 0xdb, 0x1c, 0xf0, 0x38, 0x5d, 0x7f, 0xc3, 0x19, 0x48,
+ 0x43, 0xc8, 0xf5, 0x8a, 0x93, 0xe6, 0x11, 0x4d, 0x6c, 0x99, 0x31, 0x46,
+ 0x0b, 0x4b, 0x14, 0xe9, 0xd4, 0x44, 0x46, 0x51, 0xa7, 0xc7, 0x15, 0x5f,
+ 0xed, 0xb6, 0x92, 0xeb, 0x3c, 0xb1, 0x7f, 0xfd, 0x0e, 0x72, 0x75, 0xb8,
+ 0x98, 0x7f, 0x97, 0x58, 0xbf, 0x0f, 0x30, 0xb7, 0x58, 0xbf, 0x75, 0xe2,
+ 0x6f, 0xac, 0x5d, 0x31, 0x2c, 0x56, 0xc7, 0xd3, 0x02, 0x80, 0x14, 0xd4,
+ 0xab, 0x31, 0xc8, 0xf2, 0xdd, 0x19, 0x8d, 0x85, 0x0b, 0xab, 0xff, 0xb4,
+ 0x42, 0xeb, 0xc5, 0x9b, 0x31, 0x2c, 0x5e, 0xdc, 0x33, 0xac, 0x5f, 0xff,
+ 0xc3, 0xf8, 0xb6, 0x7c, 0xd6, 0xb2, 0x7a, 0x83, 0x9d, 0x62, 0xff, 0x34,
+ 0x44, 0x2f, 0x14, 0xac, 0x5e, 0x92, 0xf2, 0xc5, 0xfc, 0x30, 0xfd, 0xe7,
+ 0x09, 0x62, 0xe2, 0x89, 0x62, 0x9c, 0xf9, 0x58, 0x70, 0x46, 0x37, 0x7c,
+ 0xd5, 0x8b, 0xf6, 0xe3, 0x72, 0xd9, 0x62, 0xff, 0xbf, 0x3d, 0x16, 0x0d,
+ 0xa0, 0xb1, 0x79, 0xb5, 0xb2, 0xc5, 0xc0, 0x95, 0x8b, 0xe7, 0x93, 0xe2,
+ 0xc5, 0x2c, 0x5f, 0xcc, 0x6f, 0xa7, 0x40, 0x58, 0xa1, 0x9b, 0xb2, 0x0c,
+ 0xbf, 0xff, 0xd2, 0xe3, 0x29, 0x16, 0xfe, 0xcd, 0xc7, 0x3b, 0x86, 0x75,
+ 0x8b, 0x81, 0x2b, 0x17, 0x49, 0xab, 0x17, 0xfd, 0x9e, 0xe4, 0x9c, 0x3c,
+ 0x89, 0x62, 0xff, 0x73, 0x3e, 0xfc, 0x16, 0xcb, 0x17, 0x04, 0x12, 0x45,
+ 0xff, 0x16, 0x76, 0x68, 0x71, 0xc6, 0xb1, 0x5b, 0xaa, 0x08, 0x71, 0xed,
+ 0x0b, 0x9d, 0x73, 0xe4, 0x00, 0x64, 0xef, 0xc5, 0xc8, 0x63, 0x87, 0x61,
+ 0x1a, 0x86, 0x35, 0x78, 0x20, 0x82, 0x48, 0xb1, 0xd2, 0x23, 0x0d, 0x0d,
+ 0xcd, 0xa4, 0x88, 0xc4, 0x73, 0x07, 0x0c, 0x1b, 0xfe, 0x60, 0xb5, 0x2f,
+ 0x06, 0xe2, 0xc5, 0x31, 0xfc, 0x11, 0xfd, 0xff, 0xfe, 0x03, 0x7d, 0x9f,
+ 0xe2, 0xfc, 0xee, 0xfd, 0x41, 0xce, 0xb1, 0x4b, 0x14, 0x35, 0xc7, 0x0c,
+ 0x19, 0xdc, 0xaa, 0x29, 0x73, 0xfe, 0x20, 0x0d, 0x8a, 0xb6, 0x5e, 0x5a,
+ 0x1a, 0x2e, 0xe4, 0x1d, 0x2e, 0xfe, 0x13, 0x0d, 0x39, 0x3b, 0x7f, 0xfe,
+ 0x84, 0xe8, 0x03, 0xd6, 0x39, 0xbc, 0xfc, 0x9d, 0x62, 0xfe, 0xf4, 0xe7,
+ 0xf3, 0x65, 0x8b, 0xb0, 0xeb, 0x15, 0x88, 0x9c, 0xe9, 0x5f, 0x85, 0xd7,
+ 0xff, 0x67, 0xfe, 0xcf, 0xe9, 0xc2, 0x89, 0x62, 0xbb, 0xd8, 0x45, 0x3e,
+ 0x4d, 0x21, 0x6b, 0x68, 0xd1, 0x21, 0x3f, 0x1e, 0x38, 0xf3, 0xb2, 0x9a,
+ 0x26, 0x6c, 0xeb, 0x67, 0x53, 0x98, 0x0f, 0x49, 0x51, 0x8a, 0x33, 0x8d,
+ 0x46, 0xc6, 0x78, 0xe6, 0xbf, 0x59, 0x0f, 0x35, 0x64, 0x8c, 0x09, 0x52,
+ 0xc5, 0x4b, 0x8e, 0xe5, 0x68, 0x91, 0xe9, 0x78, 0xe2, 0x9e, 0xad, 0xed,
+ 0x18, 0x2c, 0x71, 0x85, 0xc1, 0xf9, 0x62, 0xfe, 0xc0, 0x01, 0xf5, 0x05,
+ 0x8b, 0xdf, 0x11, 0xab, 0x17, 0x6f, 0x8b, 0x17, 0xec, 0x8a, 0x7a, 0xe2,
+ 0xc5, 0x0d, 0x11, 0xee, 0x5c, 0xc3, 0xfc, 0x18, 0xbf, 0xf4, 0x9e, 0x39,
+ 0xb6, 0xc1, 0xb8, 0x4b, 0x17, 0x60, 0x4b, 0x17, 0x4f, 0x96, 0x2f, 0xff,
+ 0x9c, 0xa4, 0x18, 0x2e, 0xfd, 0xfe, 0xfa, 0x82, 0xc5, 0x6c, 0x88, 0x2d,
+ 0xc6, 0x38, 0x2f, 0x7d, 0xce, 0x38, 0x16, 0x2f, 0x7d, 0x80, 0xb1, 0x5b,
+ 0x1e, 0x03, 0x11, 0xdf, 0xc5, 0x86, 0x99, 0xe7, 0x58, 0xb1, 0xd6, 0x2a,
+ 0x09, 0xcd, 0x64, 0x31, 0x74, 0xe5, 0xf2, 0x2f, 0x17, 0xdf, 0xce, 0x00,
+ 0xf6, 0x9d, 0x96, 0x2f, 0xf4, 0x1c, 0xb0, 0xe2, 0xfa, 0xc5, 0xfb, 0xec,
+ 0xe4, 0xcb, 0x17, 0xfd, 0x2f, 0xac, 0x7f, 0xc8, 0xd6, 0x2f, 0xfd, 0x9e,
+ 0xe7, 0xdc, 0xed, 0x9a, 0x58, 0xbf, 0xfd, 0xf1, 0x73, 0x52, 0x51, 0x7d,
+ 0x81, 0x2b, 0x17, 0x60, 0xd6, 0x2f, 0xa7, 0x3e, 0xcb, 0x15, 0x29, 0xa8,
+ 0x9a, 0x67, 0xf2, 0x62, 0x37, 0x11, 0xf7, 0x64, 0xbe, 0xe1, 0x7b, 0xd8,
+ 0x0f, 0x2c, 0x5e, 0xed, 0x1b, 0x76, 0x58, 0xa3, 0x0f, 0x13, 0x07, 0x6f,
+ 0x4b, 0xc7, 0xac, 0x5f, 0xdc, 0x8a, 0x0f, 0xa8, 0x96, 0x2b, 0x0f, 0xc9,
+ 0xc8, 0xbc, 0x3f, 0x7f, 0xff, 0xf3, 0x3f, 0xa4, 0xb7, 0x73, 0x9d, 0xf9,
+ 0xcc, 0xfb, 0xf0, 0x5b, 0x2c, 0x5d, 0x3d, 0x96, 0x2c, 0x67, 0xd1, 0x17,
+ 0xe7, 0x2b, 0xe1, 0x94, 0x86, 0xb1, 0x7d, 0xbc, 0x9d, 0xd6, 0x28, 0xc3,
+ 0xc6, 0xc2, 0x3b, 0xff, 0x89, 0xb5, 0x9e, 0x29, 0xfb, 0xc1, 0x62, 0xfb,
+ 0xf9, 0xb3, 0xac, 0x5f, 0xd2, 0x77, 0x8f, 0x3e, 0x2c, 0x5e, 0x3e, 0x79,
+ 0x62, 0xf8, 0x27, 0x91, 0xac, 0x5b, 0xbd, 0x58, 0xb4, 0x68, 0xb1, 0x68,
+ 0xd1, 0x62, 0xa3, 0x63, 0xc5, 0x8d, 0x42, 0xf1, 0xac, 0x5e, 0xb1, 0x15,
+ 0x1c, 0x68, 0xbf, 0xec, 0xc3, 0x87, 0xdd, 0x25, 0x05, 0x8b, 0x9c, 0x35,
+ 0x8a, 0x82, 0x71, 0xc3, 0x23, 0xc3, 0x07, 0x86, 0x2f, 0x08, 0xbb, 0x8f,
+ 0x2f, 0xf6, 0xff, 0x90, 0xde, 0x76, 0x58, 0xbc, 0x4c, 0x35, 0x8b, 0x98,
+ 0xd5, 0x8b, 0xf9, 0x85, 0xbf, 0xe7, 0x8b, 0x15, 0xa4, 0x4c, 0x9c, 0xdb,
+ 0xc3, 0x91, 0xc3, 0x17, 0xcc, 0x76, 0x89, 0x62, 0xff, 0xe7, 0x88, 0xc7,
+ 0xeb, 0x8c, 0x1b, 0x9d, 0x62, 0xff, 0xcf, 0x3e, 0x60, 0xc9, 0xfa, 0x82,
+ 0xc5, 0x44, 0x88, 0x7e, 0x24, 0x5f, 0x75, 0xfc, 0xee, 0x58, 0xbd, 0xdc,
+ 0x00, 0x96, 0x2f, 0xa4, 0x29, 0x89, 0x62, 0xa4, 0xfb, 0x7a, 0x27, 0x72,
+ 0x2b, 0xfc, 0x67, 0xd8, 0x00, 0x7f, 0xac, 0x5b, 0x4b, 0x17, 0xbd, 0xd7,
+ 0x16, 0x2b, 0x0d, 0x8b, 0x09, 0x54, 0xa6, 0x88, 0xf0, 0x91, 0x62, 0xe2,
+ 0x66, 0xbf, 0xff, 0xf3, 0x44, 0x28, 0x0b, 0x73, 0x3e, 0xfe, 0xf4, 0xf5,
+ 0x3b, 0x4f, 0x16, 0x2f, 0xfe, 0xe7, 0xf3, 0xa8, 0x67, 0x3f, 0x3a, 0x58,
+ 0xbf, 0x13, 0x47, 0xed, 0x12, 0xc5, 0xf4, 0xe9, 0xfa, 0x58, 0xbe, 0x8b,
+ 0x93, 0xe5, 0x8a, 0xdd, 0x32, 0xc7, 0x72, 0x89, 0x19, 0x8b, 0x44, 0x47,
+ 0x78, 0xf9, 0xf5, 0x8b, 0xf6, 0x9a, 0x5e, 0x39, 0x62, 0x84, 0x78, 0xfd,
+ 0x87, 0x6e, 0x7e, 0x96, 0x2f, 0xfe, 0x26, 0xf3, 0xeb, 0xf2, 0x7e, 0x32,
+ 0xc5, 0x2c, 0x56, 0x8f, 0x9c, 0x43, 0x01, 0x21, 0xdf, 0xcd, 0x10, 0x98,
+ 0x33, 0xac, 0x5e, 0x10, 0x83, 0x58, 0xbf, 0xf9, 0xba, 0x33, 0x0e, 0x2e,
+ 0x0b, 0x8c, 0xb1, 0x50, 0x44, 0xb7, 0x0c, 0x04, 0x3f, 0x7f, 0xf4, 0x3f,
+ 0x3a, 0xda, 0x7d, 0xc6, 0x82, 0xc5, 0xf1, 0x33, 0x76, 0x58, 0x93, 0xc6,
+ 0xbf, 0xa7, 0x7f, 0x71, 0xba, 0x58, 0xbe, 0xfe, 0x36, 0xcb, 0x17, 0xfe,
+ 0xe7, 0x8d, 0x7d, 0xfd, 0xcc, 0xd9, 0x62, 0xf1, 0xdb, 0xa5, 0x8b, 0xfc,
+ 0xc6, 0xc7, 0x0b, 0xef, 0xa5, 0x8a, 0x8d, 0x91, 0x33, 0x88, 0x64, 0x3d,
+ 0x5d, 0x27, 0x91, 0x1e, 0xec, 0x46, 0x7c, 0x30, 0x0e, 0x17, 0x97, 0x9f,
+ 0xa8, 0x96, 0x2f, 0x85, 0xdf, 0x9d, 0xd6, 0x2f, 0xdc, 0x13, 0x75, 0xdc,
+ 0xb1, 0x7f, 0xc4, 0x66, 0x41, 0xcd, 0x35, 0x96, 0x29, 0xcf, 0xa0, 0x45,
+ 0xb7, 0xd9, 0xb0, 0xb8, 0xb1, 0x7f, 0xd9, 0xb3, 0x44, 0x64, 0x42, 0x3a,
+ 0xc5, 0x61, 0xf1, 0x78, 0x92, 0xfb, 0x44, 0xe0, 0x58, 0xbe, 0x7d, 0xdb,
+ 0x4b, 0x17, 0x48, 0x16, 0x2d, 0x19, 0xf3, 0x74, 0x19, 0x1d, 0x2c, 0x5c,
+ 0x2d, 0x84, 0x6d, 0xc2, 0x2b, 0xa7, 0x46, 0x17, 0xe1, 0x27, 0x60, 0x2c,
+ 0x5d, 0x9b, 0xac, 0x5f, 0xb3, 0x5a, 0x7d, 0x2c, 0x54, 0x79, 0xe9, 0x7c,
+ 0x48, 0x03, 0x17, 0xed, 0xfe, 0xc2, 0xd2, 0xc5, 0xf4, 0xf5, 0x9b, 0xac,
+ 0x5f, 0x83, 0x79, 0xe3, 0x2c, 0x53, 0x1e, 0x60, 0x89, 0x2f, 0x07, 0x31,
+ 0xeb, 0x17, 0xf8, 0x6c, 0x2d, 0x30, 0x86, 0xb1, 0x7f, 0x9b, 0x9f, 0x7d,
+ 0x98, 0x96, 0x2b, 0x0f, 0x9f, 0xe6, 0x97, 0xcd, 0xb0, 0x70, 0x58, 0xae,
+ 0xf5, 0xb5, 0x3b, 0x8d, 0xa1, 0x51, 0x31, 0xea, 0xec, 0x9f, 0x08, 0xe0,
+ 0x87, 0x18, 0xfe, 0x42, 0xe0, 0xd7, 0x0d, 0xc8, 0xba, 0x8f, 0x41, 0xe1,
+ 0xef, 0x1e, 0x81, 0x14, 0x7d, 0xda, 0x8d, 0xac, 0xf0, 0x92, 0xfc, 0x22,
+ 0xda, 0x54, 0x70, 0x15, 0x3b, 0xf1, 0xf2, 0x84, 0x87, 0x21, 0x07, 0xe8,
+ 0x71, 0x89, 0xe7, 0xb1, 0x90, 0x4e, 0xd1, 0xc4, 0x21, 0xc2, 0x23, 0xb8,
+ 0x86, 0xf1, 0x0b, 0x8b, 0x17, 0xfb, 0x09, 0xc1, 0xcf, 0xba, 0xc5, 0xc4,
+ 0x05, 0x8b, 0x47, 0xac, 0x5f, 0x0c, 0xed, 0x05, 0x8a, 0x73, 0x70, 0x21,
+ 0x5b, 0xfe, 0xc2, 0x73, 0x7c, 0xe0, 0xe2, 0xc5, 0x18, 0x8d, 0xaf, 0x99,
+ 0x12, 0x78, 0x88, 0x2f, 0x3e, 0xc2, 0x58, 0xbe, 0xed, 0xf9, 0x82, 0xc5,
+ 0xff, 0xbb, 0x3e, 0x85, 0xdc, 0xdb, 0x07, 0x05, 0x8b, 0x4a, 0xc5, 0xf8,
+ 0x51, 0x14, 0x9d, 0x62, 0xa5, 0x14, 0xd8, 0x4a, 0xc8, 0xfc, 0x11, 0xbd,
+ 0x1b, 0xf7, 0x91, 0xba, 0xc5, 0xf0, 0x1f, 0xac, 0x58, 0xb9, 0x8e, 0xb1,
+ 0x52, 0x6e, 0xa2, 0x23, 0xb8, 0xe2, 0x58, 0xbf, 0x37, 0xbe, 0x22, 0x58,
+ 0xbf, 0x7a, 0x12, 0x40, 0x58, 0xb8, 0xfd, 0x96, 0x2e, 0x9e, 0x2c, 0x5f,
+ 0xe6, 0x72, 0x6f, 0x37, 0xd6, 0x2b, 0xe7, 0x90, 0x21, 0x7a, 0x31, 0x3a,
+ 0xe8, 0xdc, 0xea, 0x59, 0xdc, 0x87, 0xe3, 0x0c, 0x50, 0x45, 0x1c, 0x62,
+ 0xbf, 0xf6, 0xe4, 0xd9, 0xbc, 0xf6, 0x9e, 0x2c, 0x5f, 0xfb, 0x8e, 0x09,
+ 0xd3, 0xfe, 0x46, 0xb1, 0x7c, 0xc3, 0x8b, 0xa5, 0x8b, 0x41, 0x72, 0x8b,
+ 0x15, 0x28, 0x82, 0xd8, 0xf8, 0x89, 0x6f, 0x30, 0xbb, 0xf5, 0x8b, 0xff,
+ 0x66, 0xe5, 0x9c, 0x8e, 0xcd, 0x4a, 0xc5, 0x0d, 0x3c, 0x97, 0x74, 0x28,
+ 0x61, 0xf8, 0xbc, 0x32, 0x2b, 0xff, 0xd0, 0x29, 0x30, 0xe5, 0x26, 0xf9,
+ 0xf6, 0x58, 0xbe, 0xc1, 0x6b, 0x65, 0x8b, 0xe3, 0xe7, 0xce, 0xb1, 0x74,
+ 0xec, 0xb1, 0x4c, 0x6e, 0xf8, 0x47, 0x5d, 0x23, 0x2f, 0x49, 0x9e, 0x5f,
+ 0xb0, 0x4b, 0x17, 0xf4, 0xf5, 0x07, 0x2c, 0x58, 0xbd, 0xed, 0x4a, 0xc5,
+ 0xee, 0x37, 0x96, 0x2f, 0xb3, 0x60, 0xe0, 0xb1, 0x78, 0x32, 0x02, 0xc5,
+ 0x74, 0x7c, 0x04, 0x3b, 0xe2, 0x5b, 0x9f, 0x4b, 0x17, 0x85, 0xb4, 0xac,
+ 0x5a, 0x4d, 0x36, 0xba, 0x17, 0xbf, 0xed, 0xb0, 0xb5, 0x9d, 0xa4, 0x0b,
+ 0x17, 0xf7, 0xbb, 0x61, 0x60, 0xd6, 0x2a, 0x24, 0x7a, 0xfd, 0x90, 0x89,
+ 0xf8, 0x77, 0x7e, 0xe6, 0x41, 0xf4, 0xb1, 0x7e, 0x8a, 0x0d, 0xd7, 0x16,
+ 0x2b, 0x0f, 0x4f, 0x85, 0x17, 0x85, 0x1f, 0xdc, 0xb1, 0x6e, 0xcb, 0x17,
+ 0xfd, 0xaf, 0xb0, 0x6d, 0xf7, 0x02, 0xc5, 0x49, 0xe7, 0x38, 0xa5, 0xfc,
+ 0xe5, 0xb7, 0xc5, 0xc5, 0x8a, 0xf9, 0xe7, 0xf8, 0x82, 0xfb, 0xf8, 0x06,
+ 0x58, 0xba, 0x3f, 0xb9, 0x62, 0xf7, 0x21, 0xb2, 0xc5, 0x6c, 0x9a, 0x16,
+ 0x43, 0x04, 0x88, 0x84, 0x44, 0x18, 0xf5, 0x18, 0xca, 0xaf, 0x98, 0x7b,
+ 0xc0, 0xf7, 0x27, 0x0e, 0xde, 0x31, 0xa8, 0x8c, 0x74, 0x26, 0x72, 0xd6,
+ 0x8d, 0xc8, 0xa1, 0x21, 0xe8, 0xd8, 0xef, 0x4b, 0xe9, 0x62, 0xe3, 0x03,
+ 0x58, 0xa3, 0x9b, 0x66, 0x1c, 0xb9, 0xfb, 0x2c, 0x5e, 0x89, 0xfe, 0xb1,
+ 0x7f, 0x4e, 0x9a, 0x27, 0xfa, 0xc5, 0xfb, 0x83, 0x92, 0xd9, 0x8f, 0x33,
+ 0x83, 0xd7, 0xf8, 0xd6, 0x89, 0xc6, 0xf2, 0xb1, 0x7f, 0xfb, 0xde, 0x92,
+ 0x93, 0x4d, 0x98, 0x47, 0x9d, 0x62, 0xfe, 0xcd, 0xa7, 0xff, 0x95, 0x8b,
+ 0xf6, 0x45, 0xfc, 0x25, 0x8b, 0xf6, 0x06, 0x42, 0x02, 0xc5, 0xf8, 0x0c,
+ 0xd0, 0x3a, 0xc5, 0x49, 0xe8, 0xe1, 0x4d, 0xf3, 0x85, 0x9a, 0x58, 0xbf,
+ 0xfb, 0xf8, 0x7c, 0xec, 0xc7, 0xcd, 0x41, 0x62, 0x8d, 0x4e, 0xcd, 0xcd,
+ 0x34, 0x9f, 0xf2, 0xe2, 0x79, 0xe1, 0x07, 0x88, 0xef, 0x1e, 0x4e, 0xb1,
+ 0x7a, 0x76, 0xc5, 0x8a, 0xc5, 0x5e, 0x9d, 0x32, 0xea, 0x3f, 0x13, 0xb2,
+ 0x78, 0x76, 0xf8, 0xfa, 0xd4, 0xac, 0x5f, 0xff, 0x7b, 0xd2, 0x7c, 0xff,
+ 0xe5, 0xca, 0x4e, 0xb1, 0x7e, 0xe7, 0x18, 0xa0, 0xb1, 0x7f, 0xf8, 0xb0,
+ 0x6d, 0x0f, 0x39, 0x16, 0x6e, 0xb1, 0x7f, 0x3e, 0xb8, 0x1c, 0x81, 0x62,
+ 0xff, 0xec, 0xf7, 0xdf, 0xdf, 0xc2, 0x90, 0x2c, 0x5c, 0xdb, 0x2c, 0x5b,
+ 0xb1, 0x88, 0xfa, 0xc2, 0x80, 0x24, 0x11, 0x7c, 0x72, 0x1d, 0xff, 0xb0,
+ 0x6f, 0xce, 0xbc, 0x26, 0xe2, 0xc5, 0xf8, 0xc6, 0x37, 0xee, 0xb1, 0x68,
+ 0x18, 0x7d, 0x5c, 0x40, 0xbf, 0xee, 0x67, 0xa4, 0xef, 0xa8, 0x2c, 0x57,
+ 0x4a, 0x9a, 0x1e, 0x34, 0x82, 0x85, 0xf7, 0x8a, 0x6f, 0x6f, 0x90, 0x58,
+ 0xbf, 0x7c, 0x45, 0x3d, 0x96, 0x2f, 0xdc, 0x62, 0x84, 0xac, 0x5f, 0xc4,
+ 0xde, 0x84, 0x9a, 0xb1, 0x52, 0x7f, 0xfc, 0x2a, 0x0c, 0x9e, 0xfd, 0x1b,
+ 0x49, 0xb2, 0x12, 0xc5, 0xc7, 0xe2, 0xc5, 0xf6, 0xc6, 0x77, 0x6e, 0xb1,
+ 0x7e, 0x70, 0xb3, 0xaf, 0x2c, 0x5d, 0x21, 0x2c, 0x57, 0xcf, 0x08, 0x8a,
+ 0xaf, 0xff, 0x72, 0x75, 0xbf, 0xb8, 0xfe, 0xfe, 0x0d, 0x62, 0xff, 0xff,
+ 0xdc, 0xc3, 0xce, 0xf8, 0x4e, 0x68, 0x7a, 0x1f, 0xf1, 0xc8, 0xd5, 0x8b,
+ 0xdb, 0x46, 0xdd, 0xf6, 0xb1, 0x7b, 0x3a, 0x82, 0xc5, 0xcc, 0x35, 0x8a,
+ 0xc3, 0x6a, 0xc3, 0xd7, 0xb8, 0xf1, 0x2c, 0x51, 0x1b, 0xde, 0x0f, 0xdf,
+ 0x9f, 0xb6, 0xb0, 0xeb, 0x15, 0x88, 0xe7, 0x36, 0x13, 0xbf, 0x20, 0xb7,
+ 0x16, 0x2f, 0x1a, 0xe3, 0x58, 0xbf, 0x99, 0xb4, 0x16, 0x7d, 0x62, 0xff,
+ 0x3c, 0xfb, 0x3b, 0x30, 0xd6, 0x2f, 0xfe, 0xc0, 0xe7, 0x40, 0x7f, 0x68,
+ 0x47, 0x58, 0xbf, 0xdf, 0x9d, 0x3e, 0xef, 0xd9, 0x62, 0x8d, 0x47, 0xe4,
+ 0x43, 0xda, 0x2e, 0x23, 0x4f, 0x23, 0x5f, 0x49, 0x39, 0xd6, 0x2f, 0xfd,
+ 0xb1, 0x4f, 0x4e, 0x32, 0x9d, 0x96, 0x2f, 0xf0, 0x39, 0xe2, 0x93, 0xf1,
+ 0x62, 0xff, 0x1e, 0x7e, 0xdc, 0x98, 0xf5, 0x8a, 0x93, 0xea, 0x63, 0x4a,
+ 0xdd, 0x1d, 0x6c, 0x42, 0x50, 0xaa, 0xa1, 0xae, 0x37, 0xee, 0x43, 0xd2,
+ 0x66, 0xa3, 0x55, 0x39, 0xaf, 0xe3, 0x0e, 0x28, 0xcd, 0xaf, 0x79, 0xcd,
+ 0x58, 0xbe, 0x34, 0x21, 0x9d, 0x62, 0xf6, 0xce, 0x12, 0xc5, 0xf8, 0xcf,
+ 0xce, 0xa0, 0xb1, 0x46, 0x33, 0x4b, 0xe6, 0x58, 0xa6, 0xca, 0x59, 0x2a,
+ 0x2c, 0xd4, 0x9d, 0xe1, 0x3b, 0xd1, 0x7c, 0x45, 0xe7, 0x18, 0x69, 0xcd,
+ 0xbe, 0x3d, 0x78, 0x78, 0x44, 0xc1, 0x0f, 0xde, 0xfb, 0xf7, 0x2c, 0x5d,
+ 0xc9, 0x58, 0xbe, 0xe3, 0x14, 0x16, 0x2a, 0x07, 0xb2, 0x72, 0x0e, 0x0b,
+ 0xdf, 0xdb, 0x45, 0x08, 0xdb, 0x5b, 0x2c, 0x5d, 0x9b, 0xac, 0x5c, 0xfb,
+ 0x2c, 0x57, 0x8d, 0x87, 0x70, 0xc5, 0x2c, 0x5b, 0x8b, 0x15, 0xb9, 0x7d,
+ 0xc0, 0xcb, 0xbe, 0x25, 0x8b, 0xd8, 0xdf, 0x58, 0xbe, 0xf0, 0x30, 0x96,
+ 0x28, 0x67, 0xef, 0xa2, 0x13, 0x8c, 0x10, 0xe5, 0xf0, 0x09, 0xe5, 0x62,
+ 0xdb, 0x2c, 0x5f, 0xf0, 0xf0, 0xef, 0xd4, 0x0a, 0x56, 0x2f, 0xde, 0xfb,
+ 0x9f, 0x4b, 0x15, 0x03, 0xf5, 0x71, 0x3d, 0x1c, 0xde, 0xf8, 0xdd, 0x62,
+ 0xdd, 0x96, 0x2f, 0xdf, 0xc7, 0x87, 0x16, 0x2f, 0xff, 0xbf, 0x21, 0xc6,
+ 0x78, 0x98, 0x1c, 0xe4, 0x81, 0x22, 0xf1, 0xb3, 0xc5, 0x8b, 0xf6, 0x79,
+ 0x85, 0xdf, 0xac, 0x5a, 0x3d, 0x62, 0xfd, 0xad, 0xd9, 0xb7, 0x5c, 0x80,
+ 0x85, 0xee, 0x4f, 0x4b, 0x17, 0xb9, 0xa8, 0x2c, 0x5f, 0xff, 0xd0, 0x33,
+ 0x3e, 0xc5, 0x9e, 0xe3, 0x7b, 0x99, 0xe5, 0x8a, 0x73, 0xf9, 0x61, 0xeb,
+ 0x98, 0x6b, 0x16, 0x04, 0xa6, 0x35, 0x82, 0xbd, 0x1b, 0x9e, 0x12, 0xfe,
+ 0x20, 0xbe, 0x2c, 0x0b, 0xb9, 0x62, 0xef, 0x71, 0x62, 0xe7, 0x02, 0xc5,
+ 0x40, 0xd7, 0x8c, 0x62, 0xe7, 0xd9, 0x62, 0x9d, 0x11, 0xcc, 0xab, 0xe2,
+ 0x1b, 0xc2, 0x2d, 0xd6, 0x2f, 0x99, 0x98, 0x35, 0x8b, 0xee, 0x80, 0xf0,
+ 0x58, 0xbf, 0xfe, 0xcf, 0xbe, 0xbe, 0xdc, 0x7f, 0x49, 0x6e, 0xb1, 0x7d,
+ 0xb1, 0x31, 0xd6, 0x2e, 0x62, 0x58, 0xbf, 0x49, 0xbd, 0xc2, 0xd2, 0xc5,
+ 0x49, 0xf3, 0x6c, 0x47, 0xa1, 0x6a, 0xef, 0x57, 0x13, 0xa0, 0x28, 0x32,
+ 0x8c, 0x54, 0xe8, 0x7b, 0x51, 0xa3, 0x9e, 0x1c, 0x7f, 0x2e, 0x61, 0xe2,
+ 0x22, 0xe1, 0x27, 0xa1, 0x6b, 0x7d, 0x17, 0xf3, 0xcb, 0x17, 0xf3, 0x6b,
+ 0x3b, 0x60, 0xd6, 0x2f, 0xdb, 0xb1, 0xbf, 0x75, 0x8a, 0x63, 0xfd, 0x01,
+ 0x21, 0x17, 0xdf, 0x68, 0x6e, 0x75, 0x8b, 0xc3, 0x68, 0x2c, 0x5a, 0x0b,
+ 0x15, 0x26, 0xbf, 0xb8, 0x76, 0xf1, 0x37, 0x16, 0x2f, 0xbd, 0xb3, 0x12,
+ 0xc5, 0xe3, 0xce, 0xeb, 0x17, 0x31, 0xab, 0x15, 0x86, 0xd8, 0x87, 0xae,
+ 0x6d, 0x2c, 0x5a, 0x0b, 0x17, 0xed, 0x85, 0xee, 0xde, 0x58, 0xba, 0x40,
+ 0xb1, 0x58, 0x78, 0x9e, 0x2d, 0xa9, 0x3f, 0x73, 0x55, 0xae, 0x00, 0x4b,
+ 0x16, 0xd2, 0xc5, 0xfe, 0x86, 0xa7, 0x66, 0xd6, 0xeb, 0x17, 0xff, 0x60,
+ 0x05, 0xc6, 0xd9, 0xca, 0x7a, 0x58, 0xa3, 0x11, 0x4c, 0xe3, 0x2c, 0x24,
+ 0x46, 0xd6, 0x75, 0x8b, 0xff, 0xf3, 0x74, 0x0d, 0xfe, 0xf1, 0x13, 0x05,
+ 0xec, 0xfa, 0xc5, 0xe3, 0x5f, 0xcb, 0x17, 0xb8, 0xde, 0x58, 0xbf, 0x9f,
+ 0x69, 0xf4, 0x8d, 0x62, 0xa5, 0x1a, 0x78, 0x22, 0x6a, 0xcf, 0x43, 0xcc,
+ 0x3b, 0x71, 0x9f, 0x58, 0xbf, 0x79, 0xc6, 0x29, 0x58, 0xbe, 0x68, 0x60,
+ 0xd6, 0x28, 0xe7, 0x94, 0x45, 0x16, 0x25, 0x8b, 0x6e, 0xb1, 0x63, 0xc9,
+ 0xa4, 0xf0, 0x8d, 0xbd, 0x27, 0xd7, 0x88, 0xb7, 0xf7, 0xb2, 0x28, 0x30,
+ 0x16, 0x2f, 0xe9, 0x3e, 0x1b, 0x3c, 0x58, 0xad, 0x97, 0x2d, 0x60, 0x47,
+ 0x83, 0x9b, 0xac, 0xc7, 0x8f, 0xea, 0x11, 0xc7, 0x86, 0x47, 0xe3, 0x0e,
+ 0x02, 0x49, 0x43, 0x3b, 0x84, 0xde, 0x2f, 0xbf, 0xf1, 0x66, 0xa1, 0x90,
+ 0x0d, 0xa3, 0xd6, 0x2f, 0xdd, 0xde, 0xc2, 0x02, 0xc5, 0xc7, 0x95, 0x8a,
+ 0xc3, 0xc2, 0x72, 0xbb, 0xfe, 0x81, 0x99, 0x3b, 0xef, 0x84, 0xb1, 0x7b,
+ 0xef, 0xa5, 0x8a, 0x19, 0xec, 0x78, 0xee, 0xfd, 0xf2, 0xc7, 0xf2, 0xc5,
+ 0xd2, 0x75, 0x8b, 0xd9, 0xac, 0x58, 0xad, 0xcd, 0x99, 0xc5, 0xef, 0xfb,
+ 0xee, 0x2e, 0xfc, 0x3d, 0x84, 0x4b, 0x17, 0xfb, 0xf9, 0xd4, 0x3c, 0xf1,
+ 0x2c, 0x54, 0x0f, 0xdc, 0x08, 0x35, 0x29, 0x8a, 0xe2, 0xd0, 0xa1, 0x33,
+ 0x76, 0x6c, 0xb1, 0x61, 0x2c, 0x50, 0xcd, 0x56, 0x86, 0x2f, 0xf4, 0xe1,
+ 0x7b, 0x91, 0xdd, 0x96, 0x2f, 0xe9, 0x8f, 0xfb, 0xb4, 0x16, 0x2f, 0x4f,
+ 0x0c, 0x39, 0xf4, 0x11, 0xc5, 0xfc, 0xc1, 0x73, 0x92, 0x05, 0x8a, 0xf9,
+ 0xf1, 0x11, 0x9d, 0xcd, 0xa5, 0x8b, 0x98, 0x25, 0x8a, 0x93, 0x5e, 0x21,
+ 0x7b, 0xff, 0x7d, 0x8b, 0xdc, 0x21, 0x30, 0x6b, 0x17, 0xfd, 0xad, 0x3f,
+ 0x50, 0xf3, 0x74, 0xb1, 0x7a, 0x39, 0x8d, 0x58, 0xbf, 0xe9, 0x3c, 0x33,
+ 0x6c, 0x17, 0x7e, 0xb1, 0x7f, 0xd2, 0x07, 0x87, 0xdc, 0x80, 0xb1, 0x6d,
+ 0x96, 0x2e, 0x6f, 0x68, 0xf2, 0xfb, 0xf3, 0x8a, 0xc4, 0x6e, 0xb9, 0x0b,
+ 0x42, 0x2a, 0xe6, 0xd9, 0x62, 0xe9, 0x0d, 0x62, 0x98, 0xd8, 0x04, 0x31,
+ 0x7f, 0xf3, 0x70, 0x3f, 0x39, 0x0a, 0x19, 0xc5, 0x8b, 0xc1, 0x04, 0x12,
+ 0xe0, 0xfa, 0x8e, 0x37, 0x10, 0xd7, 0x07, 0xd1, 0x18, 0x6d, 0xea, 0x51,
+ 0x66, 0xcf, 0x97, 0x01, 0x96, 0x2f, 0xfe, 0x93, 0x73, 0xc1, 0xed, 0xe8,
+ 0x49, 0xab, 0x17, 0xd0, 0x14, 0x9a, 0xb1, 0x7f, 0xdb, 0x6a, 0x7c, 0xfb,
+ 0xb8, 0xd6, 0x2c, 0x05, 0x8a, 0x82, 0x2e, 0xb1, 0x25, 0xc9, 0x18, 0xee,
+ 0xf1, 0x30, 0x16, 0x2a, 0x57, 0x4c, 0x47, 0x0e, 0xb3, 0x54, 0x37, 0x20,
+ 0x73, 0xfd, 0x46, 0x33, 0xf6, 0x20, 0x43, 0x50, 0x88, 0x7d, 0x0d, 0x10,
+ 0xce, 0xaf, 0xf0, 0xfe, 0xc7, 0x0e, 0x49, 0x62, 0xfe, 0xfe, 0x43, 0xef,
+ 0xd9, 0x62, 0xa3, 0xcf, 0x93, 0xc6, 0x96, 0x25, 0x8b, 0xda, 0x16, 0xcb,
+ 0x15, 0x03, 0x60, 0x71, 0x1b, 0xff, 0xe2, 0x73, 0x63, 0x39, 0xef, 0x89,
+ 0xa1, 0x09, 0x58, 0xa9, 0x3f, 0x5c, 0x21, 0xbf, 0x7f, 0x3d, 0xc9, 0x58,
+ 0xb7, 0x65, 0x8b, 0xf1, 0x78, 0x59, 0xf5, 0x8b, 0x09, 0x62, 0x96, 0x28,
+ 0xc2, 0xf8, 0x42, 0x55, 0x27, 0xcf, 0xb2, 0x35, 0xdd, 0xce, 0xb1, 0x77,
+ 0x69, 0x58, 0xbe, 0xe7, 0xb3, 0x4b, 0x15, 0xb2, 0xb1, 0x98, 0x46, 0x28,
+ 0x6c, 0x32, 0xb7, 0x20, 0x88, 0xa3, 0x4f, 0x6c, 0x45, 0xc1, 0xaf, 0x0c,
+ 0xde, 0x1b, 0x41, 0x62, 0xe7, 0xd2, 0xc5, 0x61, 0xb4, 0xf8, 0xed, 0xfe,
+ 0x2c, 0xe1, 0xba, 0xce, 0x2c, 0x5f, 0xee, 0xa7, 0xd9, 0x9d, 0x41, 0x62,
+ 0xbb, 0x1f, 0x48, 0x46, 0x97, 0x89, 0xce, 0xb1, 0x7f, 0x0d, 0xcb, 0x60,
+ 0xfa, 0x58, 0xa2, 0x3c, 0xd0, 0x87, 0x2b, 0x11, 0x28, 0xce, 0x57, 0xb3,
+ 0xb0, 0x6b, 0x17, 0x3f, 0xd6, 0x2e, 0x7e, 0xcb, 0x16, 0x82, 0xc5, 0x49,
+ 0xab, 0x61, 0x9b, 0xff, 0x09, 0x8f, 0x3a, 0xe3, 0x94, 0x4b, 0x14, 0x33,
+ 0xde, 0x21, 0xfb, 0xdd, 0xb0, 0x6b, 0x17, 0xe9, 0x39, 0x4c, 0x4b, 0x15,
+ 0x87, 0x8e, 0x68, 0xfd, 0xf3, 0x1f, 0x0e, 0xb1, 0x7f, 0x39, 0x37, 0x85,
+ 0xe5, 0x8b, 0xe7, 0x3c, 0xc7, 0xac, 0x5c, 0xfa, 0x30, 0xfd, 0x24, 0x8b,
+ 0x0b, 0x68, 0x69, 0xeb, 0xe4, 0x28, 0x34, 0xd1, 0xf8, 0x4b, 0x5f, 0xde,
+ 0xce, 0x7c, 0x5c, 0x58, 0xbf, 0x3e, 0xe4, 0xdb, 0xac, 0x5f, 0x61, 0xdb,
+ 0xa5, 0x8b, 0xe3, 0xb1, 0x62, 0xc5, 0xfb, 0xc5, 0x9a, 0x95, 0x8b, 0x81,
+ 0x1e, 0xb1, 0x5b, 0x1e, 0x11, 0x13, 0xd4, 0xa3, 0x47, 0x0a, 0x5c, 0x8d,
+ 0x98, 0xee, 0x28, 0x96, 0x29, 0x62, 0x96, 0x2c, 0xde, 0x2e, 0x3b, 0x83,
+ 0x2a, 0x4f, 0x60, 0x06, 0x17, 0x9e, 0x60, 0xb1, 0x46, 0x37, 0xd9, 0xb1,
+ 0xb9, 0x7c, 0x6c, 0xd1, 0x30, 0xb9, 0xd8, 0xee, 0x10, 0x96, 0x19, 0x76,
+ 0x4e, 0x35, 0x9b, 0x19, 0xc6, 0xe5, 0xaf, 0x3a, 0x0f, 0x14, 0x30, 0x35,
+ 0x08, 0x43, 0xbc, 0x7e, 0x33, 0x76, 0xa4, 0x54, 0x02, 0x18, 0x45, 0x18,
+ 0xef, 0x08, 0x45, 0x1f, 0xb8, 0x48, 0xf1, 0xd1, 0x80, 0x07, 0x09, 0x1e,
+ 0xe2, 0x1b, 0xf0, 0x63, 0x17, 0xb8, 0xb1, 0x7f, 0xcf, 0xf6, 0xd4, 0x9b,
+ 0x91, 0x2c, 0x5f, 0xff, 0x7e, 0x5b, 0x5c, 0xe6, 0x7d, 0xf8, 0x2d, 0x96,
+ 0x2f, 0xb3, 0xec, 0x75, 0x8b, 0x7a, 0x51, 0x5b, 0xc3, 0xa0, 0xd4, 0x6f,
+ 0xfb, 0x05, 0xe1, 0xbe, 0x9b, 0x8b, 0x17, 0xe1, 0xcf, 0xe4, 0x35, 0x8b,
+ 0x04, 0xb1, 0x4c, 0x8a, 0xbe, 0x1b, 0x08, 0xe4, 0x32, 0x9b, 0xfe, 0x6e,
+ 0x16, 0x76, 0x7f, 0x89, 0x62, 0xfd, 0xfc, 0xdc, 0x58, 0xb1, 0x76, 0x71,
+ 0x62, 0xb0, 0xf0, 0x18, 0xa6, 0xff, 0x8b, 0x3d, 0x3d, 0x9c, 0x80, 0xb1,
+ 0x7f, 0xbd, 0x3d, 0x9f, 0xd0, 0x95, 0x8b, 0xff, 0xfb, 0x03, 0x9d, 0x01,
+ 0xfd, 0xa1, 0x1f, 0x9e, 0xcd, 0x2c, 0x5f, 0x8e, 0x1c, 0xe8, 0x0b, 0x15,
+ 0x88, 0xbc, 0x23, 0x50, 0xd7, 0x6f, 0x98, 0xb2, 0x3d, 0x62, 0xd1, 0xeb,
+ 0x14, 0x33, 0x73, 0xe2, 0x4a, 0xc4, 0xdf, 0x81, 0x0f, 0x5e, 0x34, 0x52,
+ 0xc5, 0xf9, 0xfd, 0xc1, 0x47, 0xac, 0x5b, 0x47, 0x37, 0x1f, 0x0c, 0xbe,
+ 0x7f, 0x4c, 0x16, 0x2f, 0xf0, 0x99, 0xe1, 0x25, 0xba, 0xc5, 0x61, 0xfe,
+ 0x7c, 0x9f, 0x84, 0x57, 0xde, 0xeb, 0x98, 0xb1, 0x73, 0x76, 0x58, 0xb7,
+ 0x65, 0x8a, 0x73, 0x5a, 0xc3, 0x37, 0xbf, 0x80, 0x58, 0xbf, 0xf3, 0xeb,
+ 0xed, 0xc3, 0x75, 0xed, 0xd6, 0x2f, 0x80, 0x1c, 0xf1, 0x62, 0xfc, 0xfe,
+ 0x9f, 0x71, 0x22, 0xfb, 0x79, 0xf7, 0x12, 0x2e, 0x08, 0x24, 0x8a, 0x81,
+ 0xf3, 0x61, 0x40, 0x44, 0x94, 0x91, 0x18, 0x6b, 0xea, 0x09, 0x9b, 0xfc,
+ 0x74, 0x90, 0x82, 0x85, 0xcd, 0xe6, 0x20, 0x2c, 0x5a, 0x35, 0x2c, 0x5e,
+ 0x6f, 0xb2, 0xc5, 0xf8, 0x2f, 0x07, 0x20, 0x58, 0xbf, 0x67, 0x3d, 0x91,
+ 0xeb, 0x15, 0x2a, 0xa4, 0x06, 0xa3, 0x91, 0xab, 0x1a, 0x86, 0x71, 0xcf,
+ 0x8c, 0x30, 0xe7, 0x8a, 0xef, 0x13, 0x04, 0xb1, 0x7f, 0x70, 0x7f, 0x92,
+ 0xd9, 0x62, 0xfd, 0xf7, 0x9d, 0x01, 0x62, 0xa2, 0x3f, 0x40, 0x0e, 0xf8,
+ 0xbe, 0xef, 0xba, 0xc5, 0xe7, 0xed, 0x8b, 0x15, 0x11, 0xb5, 0xd0, 0xbd,
+ 0xf8, 0xa7, 0xb7, 0xe5, 0x62, 0xff, 0x6a, 0x7f, 0x2e, 0x5b, 0x2c, 0x5f,
+ 0xc1, 0xe6, 0xba, 0xe4, 0xac, 0x5f, 0xfc, 0xff, 0x14, 0x6d, 0xcf, 0x7d,
+ 0xd8, 0x0b, 0x14, 0x73, 0xfa, 0xf1, 0x85, 0xd9, 0xc5, 0x8a, 0xc3, 0x73,
+ 0xf2, 0x2b, 0xfe, 0xc2, 0xf7, 0xde, 0x4b, 0x65, 0x8b, 0xff, 0xfd, 0xfc,
+ 0x38, 0x72, 0x0d, 0x4f, 0x0b, 0x3b, 0x3f, 0xc4, 0xb1, 0x7b, 0xd3, 0xbe,
+ 0x22, 0x6f, 0xc7, 0x17, 0xff, 0x82, 0x6e, 0x79, 0xfe, 0xf8, 0x6b, 0xe9,
+ 0x62, 0x96, 0x2a, 0x55, 0x16, 0x0e, 0x1c, 0xd9, 0x0b, 0xbf, 0x9a, 0x71,
+ 0x2e, 0xb6, 0x65, 0xcd, 0x0e, 0x38, 0x3d, 0xcf, 0x62, 0x7a, 0xd4, 0x73,
+ 0xc7, 0x87, 0x48, 0x25, 0x5f, 0x14, 0x3a, 0xf8, 0xcb, 0xe2, 0x20, 0xa5,
+ 0x2a, 0xdf, 0xcf, 0x9b, 0x1d, 0xfc, 0xb1, 0x7f, 0xa1, 0x31, 0xee, 0x59,
+ 0x12, 0xc5, 0xf0, 0xfe, 0xd1, 0xeb, 0x17, 0xd0, 0xfe, 0x6c, 0xb1, 0x52,
+ 0x79, 0x4c, 0x4d, 0x60, 0x96, 0x2f, 0xa2, 0x8f, 0x20, 0x2c, 0x58, 0x80,
+ 0x6e, 0xbc, 0x27, 0x76, 0x79, 0x62, 0xb4, 0x9a, 0x2b, 0x17, 0x14, 0x20,
+ 0x04, 0xb5, 0x1c, 0x4d, 0x7f, 0x14, 0xc3, 0x5a, 0x95, 0x8b, 0xfe, 0x1c,
+ 0xfe, 0x61, 0x00, 0xa5, 0x62, 0xc0, 0x58, 0xb4, 0xb9, 0xe6, 0x68, 0xea,
+ 0xf8, 0xa7, 0xa0, 0x62, 0x27, 0xfe, 0xf3, 0x7f, 0x41, 0xbc, 0xe2, 0xe2,
+ 0xc5, 0xff, 0xbd, 0xcc, 0xdf, 0xec, 0x5e, 0xe2, 0xc5, 0xe7, 0x20, 0x2c,
+ 0x18, 0x78, 0x14, 0x74, 0x6a, 0x91, 0xcf, 0x66, 0xeb, 0xb9, 0xe5, 0x8b,
+ 0xff, 0x1d, 0xf0, 0xfe, 0xe0, 0x8b, 0xcb, 0x17, 0xff, 0xf6, 0x85, 0xcf,
+ 0xb4, 0x37, 0xfb, 0xf5, 0x09, 0x68, 0x2c, 0x51, 0xa8, 0x9d, 0xf1, 0xfd,
+ 0xff, 0xbc, 0xfc, 0xdb, 0x02, 0xce, 0xbc, 0xb1, 0x7f, 0xff, 0xbe, 0xe4,
+ 0x2f, 0x42, 0x4d, 0x17, 0xe4, 0xf9, 0xd7, 0x96, 0x2f, 0xfe, 0x9d, 0xfe,
+ 0xfe, 0xc8, 0x8a, 0x4f, 0x88, 0xa5, 0xdd, 0x0a, 0xff, 0xf9, 0x8f, 0xef,
+ 0xb1, 0xf2, 0x12, 0x0e, 0x62, 0xc5, 0x6e, 0x8a, 0xb2, 0x5c, 0xa9, 0x4e,
+ 0x5f, 0x23, 0x74, 0xbf, 0xec, 0xd0, 0x1f, 0xda, 0x11, 0xd6, 0x2a, 0x55,
+ 0x6f, 0xe1, 0x8f, 0xe5, 0x26, 0x47, 0x14, 0x5b, 0x65, 0x8b, 0xfb, 0x92,
+ 0x17, 0xb3, 0x75, 0x8b, 0xfe, 0xce, 0xcd, 0xa6, 0x83, 0x41, 0x62, 0xc3,
+ 0xdc, 0xff, 0x7a, 0x13, 0xe1, 0x85, 0xff, 0xef, 0xbc, 0x44, 0xc1, 0x7b,
+ 0x3e, 0x19, 0xd6, 0x2f, 0xf4, 0x27, 0x0b, 0xc2, 0x65, 0x8b, 0x6d, 0xb9,
+ 0xff, 0xf4, 0x9b, 0x52, 0x8e, 0x11, 0x42, 0xda, 0xfe, 0x9f, 0xcf, 0xe7,
+ 0x65, 0x8b, 0xde, 0x91, 0xac, 0x5f, 0xf9, 0xdb, 0xa8, 0x7b, 0x84, 0xe6,
+ 0xac, 0x5f, 0xd9, 0x1c, 0x2f, 0xbe, 0x96, 0x2a, 0x07, 0xe2, 0x1a, 0x05,
+ 0x4a, 0x2c, 0x72, 0x11, 0xd5, 0xb2, 0x60, 0xb0, 0x86, 0xfd, 0xb8, 0xb1,
+ 0x4b, 0x14, 0xc5, 0xf0, 0x42, 0x55, 0x27, 0xd0, 0xc9, 0x17, 0xfb, 0x0e,
+ 0xc5, 0xee, 0x4a, 0xc5, 0xc0, 0x75, 0x8a, 0xd1, 0xe4, 0x91, 0x95, 0x0d,
+ 0x50, 0xf7, 0xe3, 0x94, 0x66, 0x9b, 0xe9, 0xec, 0xe3, 0x58, 0xbf, 0x43,
+ 0xe2, 0x9d, 0x2c, 0x5f, 0x7d, 0xc2, 0xe2, 0xc5, 0xfe, 0x9e, 0xcf, 0xd8,
+ 0x85, 0xc5, 0x8b, 0xf9, 0xf8, 0xdd, 0x43, 0x16, 0x2e, 0x63, 0xee, 0x88,
+ 0x9d, 0x12, 0x47, 0x1b, 0xde, 0x7d, 0x1a, 0xb1, 0x7f, 0x9e, 0x7c, 0x52,
+ 0x7e, 0x2c, 0x57, 0x49, 0xa0, 0xfe, 0x16, 0x40, 0x3f, 0x21, 0xeb, 0xfa,
+ 0x0e, 0x5e, 0x90, 0x2c, 0x52, 0xc5, 0xc2, 0x98, 0x8d, 0xc8, 0x0b, 0x6f,
+ 0xd8, 0x23, 0xcf, 0x16, 0x29, 0x62, 0xec, 0x8b, 0x46, 0xd3, 0x85, 0x17,
+ 0xfc, 0xe2, 0xef, 0xff, 0x21, 0x96, 0xcb, 0x17, 0xee, 0xbc, 0x59, 0xb2,
+ 0xc5, 0xfc, 0xfe, 0xe3, 0x94, 0x4b, 0x15, 0x27, 0xb1, 0xf2, 0xab, 0xfe,
+ 0x1f, 0xe4, 0x6f, 0xda, 0x46, 0xb1, 0x69, 0xd8, 0xf7, 0x22, 0x21, 0xbf,
+ 0xec, 0x89, 0xb3, 0xf3, 0x91, 0x2c, 0x5f, 0xf9, 0xfa, 0xe0, 0xff, 0x27,
+ 0x6f, 0x2c, 0x5e, 0xee, 0x70, 0x96, 0x28, 0x6a, 0x91, 0x71, 0x87, 0x72,
+ 0xd7, 0x87, 0xa6, 0x8a, 0x48, 0xe7, 0xb9, 0x02, 0xfb, 0xaf, 0xe6, 0xcb,
+ 0x17, 0xff, 0x07, 0xc7, 0xe4, 0x4e, 0x3c, 0x20, 0x2c, 0x5e, 0x81, 0x32,
+ 0xc5, 0xf3, 0x7b, 0x36, 0x58, 0xba, 0x7a, 0x58, 0xb8, 0xa5, 0x62, 0xc7,
+ 0x93, 0xed, 0xf8, 0xe1, 0x11, 0xf8, 0x62, 0xfc, 0xfa, 0xe6, 0x69, 0x62,
+ 0xf4, 0x86, 0x4b, 0x17, 0x64, 0x58, 0x78, 0xbf, 0x28, 0xbf, 0xfe, 0x68,
+ 0xf0, 0xca, 0x7e, 0xcf, 0xe9, 0xf7, 0x16, 0x2a, 0x4f, 0xfc, 0x45, 0xb7,
+ 0xf1, 0x09, 0x8f, 0x31, 0xeb, 0x15, 0x2a, 0x8b, 0x46, 0x4a, 0xd0, 0xb3,
+ 0x28, 0xc1, 0x3c, 0x43, 0x7f, 0x43, 0x8e, 0x5d, 0x41, 0x62, 0xff, 0xdf,
+ 0x70, 0xbf, 0x30, 0xf8, 0x86, 0xb1, 0x6c, 0x58, 0xa5, 0x8b, 0x3e, 0x8b,
+ 0xde, 0xc2, 0x37, 0xd8, 0x03, 0xf1, 0x62, 0xa5, 0x1a, 0xe6, 0x97, 0xee,
+ 0xbd, 0xe2, 0x7b, 0x9f, 0xb2, 0xc5, 0xff, 0xb2, 0x3f, 0x61, 0x6a, 0x19,
+ 0xd7, 0x96, 0x29, 0x8f, 0x78, 0x86, 0x6f, 0xcf, 0xcc, 0xcd, 0x2c, 0x5f,
+ 0xdc, 0x03, 0x76, 0xc1, 0xac, 0x5f, 0xff, 0xff, 0xf4, 0x3f, 0x85, 0x86,
+ 0xe1, 0x03, 0x30, 0x36, 0xd0, 0x0f, 0x8d, 0x07, 0xe0, 0x30, 0x0b, 0x17,
+ 0x0b, 0x86, 0x23, 0x0b, 0x0c, 0x2b, 0x49, 0x8c, 0x14, 0x3a, 0x6f, 0xff,
+ 0x3b, 0x74, 0x67, 0x27, 0x4d, 0x07, 0xfa, 0xc5, 0x18, 0xca, 0x31, 0x8a,
+ 0x36, 0x5d, 0x4a, 0xc1, 0xfc, 0xa9, 0x92, 0x8c, 0xaf, 0x90, 0x9c, 0xed,
+ 0x19, 0xc7, 0x71, 0x45, 0xc5, 0xb2, 0xc5, 0xef, 0xe6, 0xcb, 0x16, 0x8e,
+ 0x58, 0xbf, 0xf3, 0x07, 0xbc, 0xe9, 0xfd, 0xe9, 0x58, 0xac, 0x3f, 0x36,
+ 0x1e, 0x21, 0x5b, 0xd0, 0x6d, 0x2c, 0x5d, 0x3e, 0x58, 0xbf, 0x1d, 0xa1,
+ 0x83, 0x58, 0xa7, 0x37, 0xe0, 0x17, 0xbc, 0x2f, 0xe2, 0xc5, 0xf3, 0x75,
+ 0xc8, 0x2c, 0x58, 0x4b, 0x17, 0x9d, 0xa0, 0xb1, 0x7d, 0xf9, 0x2f, 0x2c,
+ 0x51, 0x86, 0xfb, 0x83, 0x96, 0xce, 0x1f, 0x97, 0x65, 0x0b, 0xec, 0xf6,
+ 0x0d, 0x22, 0xff, 0x98, 0x8d, 0xc2, 0x6f, 0x71, 0x62, 0xf9, 0x8d, 0x00,
+ 0x4b, 0x17, 0xec, 0x37, 0xd9, 0xba, 0xc5, 0x41, 0x15, 0x3f, 0x22, 0x23,
+ 0x8e, 0x12, 0xdf, 0x49, 0x14, 0xac, 0x54, 0x4a, 0x97, 0x74, 0xb8, 0x72,
+ 0x00, 0x0e, 0x94, 0x25, 0xbd, 0x0d, 0x20, 0xcf, 0x2f, 0xe6, 0x09, 0xbc,
+ 0xc6, 0xac, 0x5e, 0xe1, 0xf4, 0xb1, 0x73, 0xee, 0xb1, 0x40, 0x36, 0xdc,
+ 0x1e, 0xac, 0x5c, 0x0b, 0x36, 0x11, 0x6f, 0x2a, 0x27, 0x4e, 0x3e, 0x65,
+ 0xbc, 0xe1, 0x71, 0x62, 0xf7, 0x1f, 0xb2, 0xc5, 0xff, 0xe9, 0x39, 0x4f,
+ 0x40, 0x62, 0x16, 0x7d, 0x62, 0xff, 0xe8, 0x07, 0xc0, 0x60, 0xb7, 0x92,
+ 0x02, 0xc5, 0xfd, 0xb3, 0x10, 0xb3, 0xeb, 0x17, 0xfe, 0x8d, 0xb0, 0x62,
+ 0xf3, 0xfa, 0x74, 0xb1, 0x7c, 0xfa, 0x33, 0x16, 0x2f, 0xf3, 0x6a, 0x76,
+ 0x6d, 0x6e, 0xb1, 0x7f, 0x48, 0xbb, 0xfc, 0x1c, 0xac, 0x51, 0xa8, 0x8a,
+ 0xf9, 0x1f, 0x8d, 0x6f, 0xba, 0x86, 0x7b, 0xbd, 0x47, 0xfe, 0x43, 0x3a,
+ 0xfe, 0xf3, 0xea, 0x45, 0xdf, 0xac, 0x54, 0x15, 0x1a, 0x74, 0x92, 0xe8,
+ 0xff, 0x8c, 0xb4, 0x34, 0x4b, 0x6a, 0x55, 0x53, 0x34, 0xa5, 0x3b, 0xdf,
+ 0xcd, 0x96, 0x2f, 0x42, 0x12, 0xb1, 0x7b, 0x3f, 0x86, 0x1b, 0xb1, 0x0f,
+ 0x56, 0xea, 0xd8, 0x5a, 0x56, 0x21, 0x35, 0xdc, 0xe2, 0x58, 0xbf, 0xf3,
+ 0xed, 0xee, 0x0a, 0x3f, 0xcd, 0xf5, 0x8a, 0x81, 0xed, 0xf8, 0x5e, 0xff,
+ 0x6c, 0x67, 0x89, 0xba, 0xe2, 0xc5, 0xfc, 0xde, 0xf3, 0x96, 0xcb, 0x17,
+ 0xff, 0xb3, 0xcf, 0x85, 0xfc, 0xf7, 0xdf, 0x75, 0x8a, 0xf9, 0xfb, 0x91,
+ 0x75, 0xee, 0xda, 0x3a, 0xc5, 0xfa, 0x75, 0xec, 0x8f, 0x58, 0xbf, 0xef,
+ 0x39, 0xf9, 0xf9, 0x0c, 0x96, 0x2f, 0x16, 0x79, 0x62, 0xfe, 0x7e, 0x72,
+ 0x7f, 0x2b, 0x14, 0xe7, 0x92, 0x43, 0x97, 0xff, 0x13, 0xef, 0xcf, 0xcb,
+ 0xf9, 0xfc, 0xb1, 0x79, 0xba, 0x01, 0x89, 0xa9, 0xec, 0x43, 0xb9, 0x07,
+ 0x45, 0x6f, 0x08, 0x3d, 0x10, 0x5f, 0x49, 0x6e, 0xce, 0xa9, 0xcf, 0xd2,
+ 0x80, 0x6f, 0xff, 0x45, 0x83, 0x2c, 0x7d, 0x67, 0xa7, 0x4b, 0x17, 0xfd,
+ 0x39, 0xd6, 0x6c, 0x13, 0x74, 0xb1, 0x7f, 0xcc, 0x16, 0xb1, 0xff, 0x23,
+ 0x58, 0xa9, 0x45, 0xf6, 0x92, 0x48, 0xf2, 0xa0, 0xaf, 0x08, 0x12, 0xa5,
+ 0x7d, 0x0f, 0xfb, 0xf8, 0x5d, 0xfb, 0xeb, 0x58, 0xb1, 0x7f, 0xfe, 0xce,
+ 0xa1, 0xe7, 0xdb, 0x35, 0xef, 0x3e, 0xa5, 0x62, 0xf6, 0x75, 0x05, 0x8b,
+ 0xcd, 0xe7, 0x58, 0xbf, 0xee, 0xbc, 0xde, 0x29, 0xcf, 0xac, 0x5f, 0xef,
+ 0xe1, 0xad, 0x2f, 0x1c, 0xb1, 0x7f, 0xb3, 0x99, 0x1f, 0xf9, 0x1a, 0xc5,
+ 0xcc, 0x05, 0x8b, 0xa7, 0x65, 0x8b, 0xdf, 0x98, 0x96, 0x2f, 0xf4, 0xb9,
+ 0x66, 0xc1, 0xc1, 0x62, 0xdd, 0x0c, 0xfa, 0xb0, 0x63, 0xe3, 0xd7, 0xe6,
+ 0x88, 0x9e, 0x25, 0x8a, 0xc4, 0xe1, 0x37, 0x39, 0xf9, 0xb7, 0x8d, 0x85,
+ 0x08, 0x1e, 0xc6, 0xb5, 0x8a, 0x9d, 0x3e, 0xae, 0xc3, 0xdc, 0x8e, 0x82,
+ 0xfa, 0x4d, 0x1e, 0x2c, 0x5f, 0x78, 0xdc, 0xfa, 0xc5, 0xe2, 0x79, 0x58,
+ 0xbb, 0x50, 0x58, 0xbf, 0xf1, 0x67, 0xbc, 0x2d, 0xbd, 0x9b, 0xac, 0x5f,
+ 0xff, 0x0f, 0xdc, 0x98, 0x0d, 0x81, 0x83, 0x7e, 0x2c, 0x5f, 0x09, 0xb5,
+ 0x05, 0x8b, 0xfc, 0x59, 0x17, 0xe7, 0x5b, 0x2c, 0x5f, 0xf0, 0xca, 0x7a,
+ 0xf0, 0xb3, 0x4b, 0x17, 0x49, 0xbc, 0x3e, 0xff, 0x1a, 0xd4, 0xa6, 0x20,
+ 0x35, 0x03, 0xc2, 0x4a, 0xff, 0x88, 0x5e, 0xfe, 0x76, 0x1c, 0xac, 0x5f,
+ 0xcd, 0xd7, 0x33, 0xaf, 0x2c, 0x5d, 0x81, 0x2c, 0x56, 0x22, 0x0c, 0x07,
+ 0x64, 0x61, 0x7c, 0x7e, 0x06, 0x75, 0x8b, 0xfb, 0xd9, 0xf9, 0xeb, 0x8b,
+ 0x15, 0x28, 0x82, 0xc2, 0xe1, 0x12, 0xdb, 0x8b, 0x16, 0x09, 0x62, 0xc3,
+ 0x58, 0xb9, 0xc0, 0xb1, 0x7c, 0x13, 0x14, 0x16, 0x2e, 0x1b, 0xac, 0x5d,
+ 0xf7, 0x58, 0xbe, 0x87, 0x3f, 0x8b, 0x17, 0x85, 0xdf, 0xe2, 0xc5, 0xfd,
+ 0xd7, 0x30, 0x13, 0xd9, 0x62, 0x9c, 0xf4, 0xd8, 0x8a, 0xdc, 0x31, 0x1f,
+ 0xc3, 0x17, 0xdc, 0x8e, 0x21, 0x76, 0x17, 0x03, 0xb5, 0x3a, 0x70, 0x4c,
+ 0x26, 0x28, 0xc4, 0x29, 0x93, 0xc9, 0x04, 0x72, 0x97, 0xf7, 0x66, 0xd4,
+ 0x30, 0x6b, 0x17, 0x02, 0x56, 0x2e, 0x04, 0xac, 0x53, 0x9a, 0xe0, 0x0b,
+ 0xde, 0x86, 0x12, 0xc4, 0x61, 0xa0, 0xac, 0x45, 0x68, 0x9f, 0xaf, 0xff,
+ 0xfb, 0xf8, 0x2d, 0x1b, 0xd4, 0x3f, 0x84, 0x6f, 0xca, 0x73, 0x4b, 0x17,
+ 0x89, 0xb8, 0xb1, 0x51, 0xa2, 0xf3, 0xcc, 0x91, 0xec, 0x48, 0x31, 0xb3,
+ 0x46, 0x1e, 0x35, 0x1d, 0x46, 0x74, 0x08, 0xfd, 0xca, 0x1a, 0xde, 0x22,
+ 0x13, 0x4d, 0xfd, 0x3f, 0x62, 0x68, 0x2c, 0x5f, 0xda, 0x0f, 0xdc, 0x87,
+ 0x7e, 0xb1, 0x7f, 0xe6, 0xd6, 0xc1, 0xeb, 0x3b, 0x36, 0x96, 0x2f, 0xf0,
+ 0xb2, 0x29, 0x3c, 0x3b, 0xf5, 0x8b, 0xa1, 0x26, 0x23, 0x7f, 0x0b, 0x37,
+ 0x36, 0x02, 0x1d, 0xe8, 0x34, 0x16, 0x2e, 0xc1, 0xc9, 0xf3, 0x32, 0x4d,
+ 0xf7, 0x86, 0x39, 0x58, 0xbf, 0xfc, 0x4d, 0xd7, 0x0d, 0x35, 0x8c, 0xdc,
+ 0xe0, 0x58, 0xbe, 0x9d, 0x4f, 0xd6, 0x2e, 0x87, 0x4b, 0x15, 0x88, 0x8b,
+ 0x65, 0x0e, 0x11, 0x5f, 0xfb, 0xd2, 0x3d, 0xdf, 0x6c, 0xeb, 0xcb, 0x17,
+ 0xfd, 0x8f, 0xd7, 0xb5, 0x39, 0xd2, 0xc5, 0xff, 0xe2, 0x7e, 0xb9, 0x11,
+ 0x66, 0xd9, 0xd7, 0x96, 0x2f, 0xfd, 0xfc, 0x38, 0x72, 0x0c, 0xeb, 0xcb,
+ 0x15, 0x88, 0x8e, 0xf2, 0x6d, 0xfe, 0xeb, 0x77, 0xd0, 0x72, 0x35, 0x8b,
+ 0xc7, 0x68, 0x18, 0x9c, 0x8c, 0x97, 0x12, 0x17, 0x21, 0x91, 0xe2, 0x2a,
+ 0x65, 0x53, 0xe0, 0x94, 0x7f, 0x70, 0xbc, 0xb1, 0x74, 0x74, 0xac, 0x5f,
+ 0xd8, 0x0d, 0x3c, 0x9d, 0x62, 0xfe, 0x01, 0xc3, 0xe0, 0x7b, 0x2c, 0x5f,
+ 0xfa, 0x47, 0xf9, 0x0f, 0x5a, 0xc8, 0x96, 0x2f, 0xce, 0x45, 0x3d, 0x2c,
+ 0x57, 0xcf, 0xa3, 0x88, 0x37, 0x67, 0x4b, 0x15, 0xd2, 0x35, 0x7d, 0x09,
+ 0xb8, 0xe2, 0x2b, 0xff, 0x9a, 0x26, 0x01, 0x9f, 0x63, 0xbf, 0x16, 0x2f,
+ 0xff, 0x07, 0x21, 0x4c, 0x50, 0x62, 0xce, 0xbc, 0xb1, 0x7b, 0x4f, 0xa5,
+ 0x8b, 0xff, 0xff, 0x67, 0xa5, 0xe0, 0xdc, 0xe4, 0xea, 0x60, 0xfb, 0x90,
+ 0xb8, 0xb1, 0x40, 0x44, 0x47, 0x07, 0x6a, 0x55, 0x6b, 0x40, 0xaf, 0x06,
+ 0x3e, 0x34, 0xd1, 0x81, 0x11, 0xcf, 0x11, 0x82, 0x86, 0xad, 0xfc, 0x59,
+ 0xd0, 0x1e, 0x0b, 0x17, 0xc6, 0xcf, 0xb8, 0xb1, 0x7e, 0xf6, 0xa7, 0x3a,
+ 0x58, 0xa3, 0x4f, 0x37, 0xa2, 0x4b, 0xfb, 0x9c, 0x98, 0x4e, 0x96, 0x2f,
+ 0xfb, 0x52, 0x77, 0x8a, 0x5a, 0x3d, 0x62, 0xb0, 0xfa, 0xb7, 0x2e, 0xbc,
+ 0x2e, 0xbc, 0xb1, 0x7e, 0x98, 0x6d, 0x81, 0x2c, 0x52, 0xc5, 0x1c, 0xdb,
+ 0x31, 0x55, 0xd1, 0x71, 0x62, 0xb6, 0x4e, 0xe6, 0x3d, 0xec, 0xa1, 0x1d,
+ 0xc2, 0x2f, 0x2a, 0x86, 0x41, 0x7f, 0x7e, 0x5c, 0xa4, 0xeb, 0x17, 0xff,
+ 0xfd, 0x9e, 0x92, 0xdf, 0x3d, 0xf7, 0xeb, 0xd2, 0x00, 0xb3, 0xeb, 0x17,
+ 0xc5, 0x9d, 0x7a, 0x51, 0x28, 0x32, 0xcb, 0xb0, 0x25, 0x8b, 0xfe, 0x11,
+ 0x6f, 0xfc, 0xdb, 0x8e, 0xb1, 0x7f, 0xd3, 0xd6, 0x02, 0x7b, 0x66, 0xcb,
+ 0x17, 0xf1, 0x67, 0xb8, 0xc0, 0x58, 0xa9, 0x47, 0xae, 0x8e, 0x4e, 0x30,
+ 0x03, 0xbe, 0x1e, 0x5f, 0xff, 0xf3, 0x3f, 0xa0, 0xe3, 0xc8, 0x7e, 0x5f,
+ 0x40, 0x3b, 0x41, 0x62, 0xfe, 0xd9, 0xf5, 0xd7, 0xf6, 0x58, 0xbf, 0x43,
+ 0x35, 0x9c, 0x58, 0xaf, 0xa2, 0xfc, 0x99, 0x7c, 0x65, 0x7f, 0xbe, 0x26,
+ 0x37, 0xd3, 0xb2, 0xc5, 0xfd, 0xcd, 0x66, 0xf3, 0xb2, 0xc5, 0xff, 0xef,
+ 0x3e, 0xdb, 0x49, 0x67, 0x9f, 0xa0, 0x96, 0x2b, 0x63, 0xfd, 0x81, 0x85,
+ 0xf4, 0xf5, 0xe8, 0xf5, 0x8a, 0x93, 0xca, 0x81, 0x1d, 0xff, 0xfe, 0x73,
+ 0x70, 0xbd, 0xfc, 0x38, 0xa0, 0xc3, 0xce, 0xbc, 0xb1, 0x76, 0x77, 0xeb,
+ 0x17, 0x17, 0x4b, 0x17, 0xf6, 0x1f, 0x9f, 0x78, 0x96, 0x2f, 0x1d, 0xba,
+ 0xef, 0x4f, 0x8c, 0xd1, 0xcf, 0x8c, 0x5f, 0xe1, 0xc9, 0x36, 0x9a, 0x0b,
+ 0x15, 0x87, 0xf2, 0xc8, 0xf7, 0xff, 0xbf, 0x27, 0xfe, 0x61, 0x6f, 0x9d,
+ 0x79, 0x62, 0xef, 0x36, 0x8f, 0xac, 0x04, 0x17, 0xfd, 0xdf, 0xea, 0x7c,
+ 0xfb, 0xb8, 0xd6, 0x2f, 0xff, 0xe6, 0x86, 0x16, 0x69, 0xcd, 0x8e, 0xe3,
+ 0x42, 0x4e, 0xb1, 0x7f, 0xb0, 0xb6, 0xc1, 0xb7, 0xd6, 0x2a, 0x25, 0x58,
+ 0xdf, 0x21, 0xf4, 0x75, 0x22, 0x2d, 0xec, 0x7e, 0x12, 0xed, 0xc0, 0xc5,
+ 0x8b, 0xff, 0xb0, 0x2c, 0x8f, 0x31, 0xbd, 0x3c, 0x95, 0x8b, 0xfd, 0xbf,
+ 0xdf, 0xe4, 0xc7, 0x58, 0xbf, 0x1f, 0x06, 0xe1, 0x2c, 0x5d, 0xed, 0x96,
+ 0x2f, 0xba, 0xdd, 0xf4, 0xb1, 0x69, 0x81, 0xbe, 0xf0, 0xcd, 0x62, 0x23,
+ 0x49, 0x9e, 0xe3, 0xca, 0xc5, 0xff, 0xed, 0xdb, 0x5b, 0x70, 0xb3, 0xde,
+ 0xcd, 0x2c, 0x5c, 0xc7, 0x58, 0xbf, 0x7b, 0x53, 0x81, 0x2c, 0x5d, 0x26,
+ 0xe1, 0xe0, 0x74, 0x2f, 0x7f, 0xec, 0xed, 0xf7, 0xea, 0x1e, 0x90, 0x96,
+ 0x2f, 0xda, 0x62, 0x87, 0x16, 0x2f, 0xf3, 0x9c, 0x73, 0xc0, 0xf8, 0xb1,
+ 0x7c, 0x4f, 0xd4, 0x16, 0x2f, 0xfd, 0xcc, 0xdb, 0x83, 0xd1, 0x30, 0x4b,
+ 0x15, 0xa4, 0x60, 0xfc, 0xa0, 0x06, 0xbe, 0x23, 0xa9, 0x4f, 0xee, 0x10,
+ 0x8c, 0xf9, 0x77, 0x23, 0x04, 0xad, 0x2b, 0x3c, 0x3c, 0x30, 0x58, 0x87,
+ 0xd2, 0x84, 0xae, 0xf7, 0x16, 0x2f, 0xff, 0xb6, 0x98, 0xa1, 0x3e, 0x0f,
+ 0x34, 0xcc, 0x35, 0x8b, 0xfd, 0x03, 0x06, 0xfd, 0xa4, 0x6b, 0x15, 0x88,
+ 0x89, 0x65, 0x2b, 0xff, 0x3f, 0x50, 0x0f, 0x80, 0x67, 0xd9, 0x62, 0xff,
+ 0xe1, 0xce, 0xfd, 0x43, 0x3d, 0xb6, 0x04, 0xb1, 0x7e, 0x8a, 0x0d, 0xad,
+ 0x96, 0x2b, 0x73, 0xf4, 0x3a, 0x4d, 0xfb, 0x22, 0xfb, 0xf9, 0x62, 0xff,
+ 0x7e, 0x5b, 0xcd, 0xd0, 0x16, 0x2f, 0xff, 0x98, 0xd8, 0xa7, 0x3d, 0x27,
+ 0x9f, 0xc8, 0x16, 0x2a, 0x08, 0x84, 0x23, 0x4b, 0x98, 0xeb, 0x17, 0xff,
+ 0xc5, 0x3d, 0xcf, 0xac, 0xea, 0x1e, 0xc2, 0xdd, 0x62, 0x86, 0x7d, 0x5e,
+ 0x17, 0xbf, 0xff, 0x87, 0xf7, 0x8d, 0x83, 0xf3, 0xf0, 0xb3, 0xb3, 0xfc,
+ 0x4b, 0x15, 0x89, 0x88, 0xbc, 0x23, 0x04, 0x45, 0x52, 0xab, 0x2f, 0x21,
+ 0x6c, 0x44, 0x7c, 0x8e, 0xfa, 0xfb, 0x33, 0xfc, 0x58, 0xa9, 0x66, 0x18,
+ 0x0c, 0xbf, 0x25, 0xe1, 0xf4, 0xc7, 0xa1, 0x76, 0x97, 0x09, 0xdf, 0xa5,
+ 0x14, 0x28, 0x7d, 0x2b, 0xb3, 0xb9, 0x1e, 0xf0, 0x41, 0x04, 0x91, 0x7e,
+ 0xc3, 0x48, 0x5c, 0x48, 0x8c, 0x34, 0x37, 0x8e, 0xde, 0x58, 0xbe, 0x8c,
+ 0x08, 0x20, 0x96, 0x2e, 0xc0, 0x2c, 0x56, 0x1e, 0x0f, 0x8a, 0xaf, 0x48,
+ 0x38, 0xb1, 0x52, 0x8d, 0x83, 0x9e, 0x79, 0x78, 0x32, 0x1b, 0xed, 0x49,
+ 0xc0, 0xb1, 0x7f, 0xfd, 0xee, 0x3f, 0xd9, 0xfc, 0xfa, 0x6d, 0xa5, 0x62,
+ 0xff, 0x1d, 0xa0, 0xc6, 0xfd, 0xd6, 0x2f, 0xff, 0x71, 0xfe, 0xcf, 0xe7,
+ 0xd3, 0x6d, 0x2b, 0x17, 0xcf, 0x06, 0xe1, 0x88, 0xcc, 0x3a, 0x7f, 0x8d,
+ 0x2f, 0xc7, 0x6f, 0x0a, 0x56, 0x2f, 0xff, 0x67, 0x67, 0xf8, 0xbe, 0xfc,
+ 0x2c, 0x3a, 0xc5, 0x49, 0xf9, 0x91, 0x45, 0xfd, 0xb4, 0x9f, 0x60, 0xc2,
+ 0x58, 0xbe, 0x7d, 0x03, 0x8b, 0x17, 0xfe, 0x17, 0x7f, 0x91, 0xc5, 0x81,
+ 0x30, 0x16, 0x2f, 0xff, 0xcf, 0x3d, 0xa4, 0x33, 0xf3, 0xe1, 0x33, 0x74,
+ 0x12, 0xc5, 0xfe, 0x98, 0x4e, 0xb5, 0x81, 0x2c, 0x5a, 0x74, 0x88, 0xf0,
+ 0x2d, 0xdf, 0xff, 0x4f, 0x07, 0xf7, 0x0b, 0xe7, 0x17, 0x85, 0x2b, 0x17,
+ 0xf8, 0xb0, 0xd3, 0x1f, 0xb3, 0xac, 0x56, 0xc8, 0xb0, 0xdc, 0xa3, 0xca,
+ 0x55, 0x29, 0xdc, 0x3c, 0x70, 0xd7, 0xc5, 0x9d, 0x79, 0x62, 0xff, 0xfe,
+ 0xf7, 0x1c, 0xba, 0x87, 0xe5, 0xc7, 0x3f, 0x98, 0x2c, 0x5d, 0xb0, 0xd6,
+ 0x2f, 0xe9, 0x17, 0x89, 0xfb, 0x2c, 0x51, 0x87, 0x91, 0xa1, 0x9a, 0x74,
+ 0x63, 0x72, 0x14, 0x77, 0xfe, 0x2c, 0xe6, 0xff, 0x7d, 0xe4, 0x96, 0x2f,
+ 0xff, 0xf1, 0xa1, 0x36, 0x8d, 0x8c, 0xe6, 0x40, 0x84, 0xdc, 0xc2, 0x58,
0xbf, 0xfd, 0xef, 0xbb, 0x03, 0x0b, 0xdf, 0xc8, 0x2c, 0x5f, 0xfd, 0xf7,
0xd7, 0xdb, 0x59, 0xbb, 0x79, 0x62, 0xff, 0xfe, 0xfb, 0x9e, 0x70, 0xbd,
0xc9, 0x3c, 0xc5, 0x3f, 0x58, 0xbf, 0xfd, 0xf7, 0xe4, 0xc2, 0x0e, 0x32,
- 0x6f, 0xac, 0x5f, 0x1c, 0xed, 0x0e, 0xa9, 0x98, 0xe2, 0x4e, 0xe8, 0xac,
- 0xb5, 0x52, 0xa9, 0x4f, 0x09, 0xdc, 0xfc, 0x51, 0xcb, 0xdf, 0xda, 0x16,
- 0xff, 0x7e, 0x2c, 0x5f, 0x06, 0xc5, 0x05, 0x8b, 0xfe, 0xf4, 0xf6, 0x06,
- 0xff, 0xdd, 0x62, 0xdf, 0x58, 0xbd, 0xfc, 0x08, 0xb1, 0x58, 0x7d, 0x7b,
- 0x9d, 0x44, 0x25, 0x7b, 0x4d, 0xba, 0xc5, 0xf9, 0xf7, 0xfc, 0xf9, 0x62,
- 0xe9, 0xc5, 0x8a, 0xd8, 0xdf, 0xee, 0x53, 0x7d, 0x3b, 0x10, 0x96, 0x2b,
- 0x47, 0x8d, 0xf2, 0x3b, 0xee, 0x39, 0xe5, 0x62, 0xff, 0xd3, 0x85, 0xb6,
- 0x13, 0x77, 0xc5, 0x8b, 0xf1, 0x67, 0xa7, 0x4b, 0x17, 0x83, 0x0c, 0x34,
- 0x8b, 0xf3, 0x1b, 0xf7, 0xf2, 0x44, 0x61, 0xa1, 0xa9, 0x44, 0x23, 0xa4,
- 0x5f, 0x1f, 0x93, 0xe5, 0x8b, 0xdd, 0x24, 0xeb, 0x17, 0xbc, 0xe1, 0xac,
- 0x5e, 0xe3, 0x69, 0x62, 0xbb, 0x37, 0x7e, 0x1e, 0xba, 0x46, 0xb1, 0x7f,
- 0xb5, 0xa9, 0xd8, 0x78, 0x4b, 0x15, 0xf3, 0xcb, 0x61, 0x7a, 0x94, 0xc2,
- 0xf0, 0x8d, 0xd6, 0x99, 0xb6, 0xff, 0xf1, 0x90, 0xea, 0x3c, 0xfe, 0xef,
- 0xcc, 0x1a, 0xc5, 0xec, 0xc8, 0x96, 0x2b, 0x63, 0xec, 0x02, 0x7d, 0xf7,
- 0x30, 0xbc, 0xb1, 0x58, 0x78, 0xac, 0x47, 0x7e, 0x33, 0x8f, 0xf1, 0x2c,
- 0x5e, 0x1c, 0x9d, 0x62, 0xef, 0x9a, 0xb1, 0x6e, 0x75, 0x5c, 0x70, 0x19,
- 0x86, 0x42, 0x8f, 0xb2, 0x28, 0x88, 0xb5, 0x0c, 0x2f, 0xc6, 0x58, 0x50,
- 0xeb, 0xe1, 0x00, 0x8a, 0xba, 0x0e, 0xde, 0x8e, 0xce, 0xd6, 0x2d, 0x01,
- 0xae, 0xec, 0xe4, 0xe7, 0xf3, 0xc2, 0xea, 0xa3, 0x65, 0xe4, 0xd1, 0x4f,
- 0x04, 0xdf, 0xd2, 0x79, 0xfc, 0x81, 0x62, 0xf4, 0xec, 0x25, 0x8b, 0x05,
- 0xf0, 0xf2, 0xfe, 0x5b, 0x7f, 0xf3, 0xfa, 0x75, 0x85, 0xe6, 0x62, 0x58,
- 0xa8, 0x33, 0x43, 0x1c, 0x82, 0x23, 0x3d, 0x47, 0xb6, 0x72, 0x8f, 0xcb,
- 0x3d, 0x29, 0xe8, 0xf1, 0x3f, 0x74, 0x2b, 0xbf, 0x86, 0xd0, 0x29, 0xd9,
- 0x62, 0xfb, 0xef, 0xdf, 0x96, 0x2f, 0x4e, 0x16, 0x1e, 0x94, 0x45, 0xd7,
- 0xdb, 0xea, 0x60, 0xb1, 0x79, 0xcf, 0xc5, 0x8b, 0xf7, 0xe7, 0x7c, 0x25,
- 0x8b, 0x4a, 0xc5, 0x00, 0xdc, 0xf4, 0x28, 0xbf, 0xf3, 0xeb, 0x7f, 0xbe,
- 0xff, 0x72, 0x58, 0xbf, 0xff, 0xfc, 0xc4, 0x0f, 0x7f, 0x0f, 0xee, 0x67,
- 0x4f, 0xbe, 0xff, 0x73, 0x05, 0xb2, 0xc5, 0x6c, 0x8b, 0xd0, 0x20, 0x54,
- 0xa6, 0x09, 0x90, 0xe0, 0xbf, 0xec, 0x8f, 0x93, 0xf7, 0x0c, 0xf2, 0xc5,
- 0x4b, 0x62, 0xbb, 0x90, 0xa6, 0x7a, 0x6d, 0xd6, 0xa1, 0xd4, 0xc6, 0x20,
- 0x24, 0x28, 0xd6, 0xb8, 0x4f, 0x7d, 0x9c, 0xf3, 0xac, 0x5f, 0xd9, 0xce,
- 0x66, 0xb6, 0x58, 0xb6, 0xf0, 0x3d, 0x11, 0x91, 0x5e, 0x29, 0xe8, 0xb1,
- 0x7f, 0xf6, 0xa7, 0x7f, 0x93, 0x78, 0xa4, 0x35, 0x8b, 0x82, 0xee, 0xb1,
- 0x4b, 0x16, 0xfa, 0xc5, 0x40, 0xbe, 0x70, 0xcb, 0xfd, 0x14, 0x1c, 0x41,
- 0x78, 0xe7, 0x58, 0xbe, 0xd3, 0xc5, 0xc5, 0x8b, 0x03, 0xa9, 0xf0, 0x68,
- 0xf2, 0xb6, 0x47, 0x16, 0x8e, 0x49, 0xfe, 0xa5, 0x35, 0x76, 0x8c, 0x9e,
- 0xf4, 0x4d, 0xb2, 0xc5, 0xee, 0x0a, 0x3d, 0x62, 0xb0, 0xf0, 0x3c, 0x3f,
- 0x7c, 0x2d, 0x85, 0xb2, 0xc5, 0xfa, 0x04, 0xf3, 0xda, 0xc5, 0xa7, 0x47,
- 0x9c, 0x44, 0xd5, 0x2f, 0xa4, 0xb9, 0xb4, 0x6e, 0x70, 0x97, 0xe6, 0x39,
- 0x76, 0x79, 0x49, 0x14, 0x36, 0x71, 0xbb, 0x79, 0x5c, 0xbd, 0xcb, 0x75,
- 0x73, 0xd8, 0xa5, 0x13, 0xea, 0x78, 0x14, 0xf1, 0x8b, 0xfe, 0x75, 0xb5,
- 0xa5, 0x14, 0x02, 0x3e, 0xa2, 0xa5, 0xd9, 0xf2, 0x3a, 0x5f, 0x56, 0x33,
- 0x42, 0x86, 0xdf, 0x42, 0x98, 0xe8, 0xdd, 0x4c, 0x68, 0x08, 0xdf, 0x7e,
- 0x78, 0xa0, 0xe4, 0xb1, 0x70, 0x51, 0xd6, 0x2f, 0xe3, 0x88, 0xd2, 0xc0,
- 0x2c, 0x5e, 0xd3, 0xee, 0xb1, 0x7f, 0xf1, 0xad, 0xd7, 0x83, 0xfe, 0x39,
- 0x1a, 0xb1, 0x78, 0x6c, 0x1a, 0xc5, 0x75, 0x3e, 0x67, 0x48, 0xac, 0x46,
- 0xb6, 0xe5, 0xff, 0x84, 0x25, 0xff, 0x45, 0xe0, 0x9c, 0x98, 0x85, 0xa5,
- 0x8b, 0xfc, 0x39, 0x23, 0xc8, 0xe5, 0x62, 0xa4, 0xfc, 0x58, 0xfe, 0xff,
- 0xbf, 0x3b, 0x6a, 0x60, 0xda, 0x58, 0xbf, 0xfd, 0xf9, 0xf9, 0x61, 0xa3,
- 0xc2, 0x98, 0xf5, 0x8b, 0xf1, 0x1a, 0x64, 0x81, 0x62, 0xff, 0x81, 0xa9,
- 0x17, 0x89, 0xfa, 0x2c, 0x5f, 0xf3, 0x77, 0xef, 0xce, 0xf9, 0x12, 0xc5,
- 0x61, 0xfb, 0x91, 0xdd, 0xf9, 0xc7, 0xf7, 0x35, 0x62, 0xf1, 0x8c, 0x4b,
- 0x14, 0x34, 0xd4, 0xf1, 0x30, 0xa1, 0x43, 0xe2, 0x00, 0x85, 0x37, 0xe2,
- 0xd8, 0x7f, 0x95, 0x8b, 0xf4, 0x93, 0x9f, 0x16, 0x2f, 0x83, 0xf6, 0x47,
- 0xac, 0x5f, 0xcc, 0x73, 0x06, 0xd0, 0x58, 0xa9, 0x45, 0x2e, 0xc5, 0x3d,
- 0x93, 0x7c, 0x9e, 0xff, 0xfc, 0x4c, 0x1e, 0x9e, 0x7e, 0x67, 0x9f, 0xf3,
- 0xd1, 0x62, 0xff, 0xcf, 0xf9, 0x1f, 0xc5, 0x3d, 0xf1, 0x62, 0xff, 0xef,
- 0x86, 0xc5, 0xb1, 0x61, 0x92, 0x75, 0x8b, 0xc4, 0x58, 0xb1, 0x58, 0x8a,
- 0x1d, 0x20, 0x32, 0x35, 0xe1, 0x9a, 0x05, 0x8b, 0xed, 0x69, 0xbc, 0xb1,
- 0x7c, 0xe6, 0x9c, 0x35, 0x8b, 0xf4, 0x73, 0xeb, 0x0d, 0x58, 0xa3, 0x9f,
- 0xa7, 0xc8, 0xf8, 0x4b, 0x7b, 0xa8, 0x4d, 0xd6, 0x2e, 0xcf, 0x2c, 0x56,
- 0xc6, 0xeb, 0xe4, 0x77, 0xfe, 0x38, 0xe4, 0xb3, 0xa1, 0x67, 0x16, 0x2f,
- 0x7c, 0x8e, 0xb1, 0x7f, 0x80, 0x6b, 0x61, 0xe7, 0x75, 0x8a, 0xea, 0x9d,
- 0x7c, 0xc2, 0x4f, 0x1a, 0x5c, 0x89, 0x8f, 0xc3, 0x1d, 0xbf, 0xfa, 0x26,
- 0xdf, 0xf3, 0x0f, 0x16, 0x1d, 0x62, 0xfe, 0xd6, 0x11, 0x36, 0xcb, 0x17,
- 0xfe, 0x32, 0x4f, 0x9a, 0x3b, 0x11, 0xab, 0x15, 0xba, 0x2c, 0xdd, 0x1b,
- 0xc5, 0xb7, 0xfe, 0x0f, 0xb8, 0x73, 0xae, 0x7f, 0x09, 0x62, 0xff, 0xa7,
- 0xbe, 0x69, 0xfa, 0x60, 0xd6, 0x2f, 0xff, 0x8b, 0x39, 0xe3, 0x64, 0xa1,
- 0x9f, 0x73, 0xac, 0x54, 0x48, 0x8b, 0xe8, 0x79, 0x52, 0x8f, 0x4c, 0x86,
- 0x75, 0xf9, 0xf5, 0x27, 0x3a, 0xc5, 0xbc, 0xb1, 0x7f, 0x66, 0xc6, 0x9a,
- 0x22, 0x58, 0xbf, 0xfc, 0x7e, 0xe1, 0xce, 0xb8, 0x45, 0x8e, 0x05, 0x8b,
- 0xff, 0x0b, 0xbe, 0x44, 0x59, 0xec, 0x02, 0xc5, 0xfc, 0xda, 0x14, 0xf7,
- 0x05, 0x8a, 0xea, 0x8f, 0xf9, 0x12, 0x73, 0x1d, 0x26, 0x32, 0x0d, 0xff,
- 0xd2, 0x33, 0xe6, 0xf3, 0xcf, 0xe1, 0xd6, 0x2f, 0xcd, 0x83, 0x7e, 0x8b,
- 0x17, 0xbd, 0x27, 0x58, 0xbc, 0x4f, 0x2b, 0x17, 0x9f, 0x03, 0x58, 0xad,
- 0x23, 0x0c, 0xe8, 0xbc, 0x29, 0xe8, 0x3a, 0x60, 0xdd, 0xe7, 0xf8, 0x96,
- 0x2f, 0xc4, 0xde, 0x63, 0xac, 0x5f, 0x79, 0xfe, 0x25, 0x8b, 0xfb, 0x35,
- 0xdc, 0x3d, 0x2b, 0x16, 0x8f, 0x0b, 0x53, 0xd2, 0x30, 0x8e, 0xfc, 0x1e,
- 0x6f, 0x20, 0x58, 0xbd, 0x98, 0x35, 0x8b, 0xed, 0xff, 0x9a, 0x58, 0xa9,
- 0x44, 0xeb, 0x99, 0x80, 0xa8, 0x20, 0xe5, 0x75, 0x66, 0xdf, 0x46, 0xe5,
- 0x13, 0x0f, 0x18, 0x42, 0x98, 0x64, 0x19, 0x1c, 0x6b, 0xc3, 0xd6, 0x23,
- 0xed, 0x43, 0xe7, 0xf1, 0xee, 0xb4, 0x61, 0xe5, 0x19, 0x27, 0x09, 0xbd,
- 0x19, 0x38, 0xa3, 0x0c, 0xe8, 0x9a, 0x60, 0xe8, 0x48, 0xc5, 0xad, 0x19,
- 0x1b, 0xcf, 0x4f, 0xa3, 0x85, 0x27, 0x01, 0xc2, 0xb2, 0xf8, 0x63, 0x49,
- 0x73, 0x51, 0xb4, 0xab, 0x30, 0xb7, 0x2b, 0x64, 0x2c, 0x95, 0x94, 0x16,
- 0xb1, 0xde, 0xc6, 0xa9, 0x4e, 0x31, 0xae, 0x36, 0x69, 0xbd, 0x42, 0xfd,
- 0xab, 0x3f, 0x48, 0x5a, 0x2b, 0xf1, 0xdb, 0xe3, 0x4c, 0xc6, 0xab, 0xf1,
- 0xb4, 0xde, 0xad, 0xed, 0xec, 0xc7, 0x76, 0xa4, 0x15, 0xed, 0x71, 0x84,
- 0x7c, 0xe3, 0x9c, 0x56, 0xce, 0x33, 0x57, 0x87, 0x38, 0x7b, 0x55, 0x09,
- 0xfb, 0xf1, 0xca, 0x6b, 0xdb, 0xd9, 0x05, 0xa8, 0x89, 0x0b, 0xcb, 0x28,
- 0x2b, 0xe7, 0xd5, 0xe6, 0x60, 0x7e, 0x1e, 0xc4, 0x16, 0x10, 0xab, 0x2f,
- 0x8e, 0x94, 0xa4, 0x20, 0xe9, 0x90, 0x91, 0xd5, 0xe8, 0x39, 0x97, 0xbe,
- 0x24, 0x12, 0x9f, 0x05, 0x51, 0x93, 0xd4, 0xab, 0x90, 0xde, 0xa1, 0xcf,
- 0xbe, 0x9e, 0xfd, 0x8b, 0x17, 0x76, 0x1a, 0xc5, 0xe3, 0xe7, 0x96, 0x2f,
- 0xf3, 0x1e, 0x7c, 0xfc, 0x75, 0x8b, 0xf6, 0x68, 0xcf, 0x71, 0x62, 0xef,
- 0xca, 0xc5, 0xa3, 0x3e, 0x8c, 0xd6, 0x23, 0x00, 0xd1, 0x0e, 0xf0, 0xc8,
- 0xc2, 0xab, 0xed, 0xca, 0x71, 0x62, 0xfd, 0xad, 0xd9, 0xb7, 0x54, 0x5c,
- 0x65, 0xfd, 0x06, 0x28, 0x39, 0xd6, 0x2d, 0x19, 0x28, 0x86, 0xc2, 0x26,
- 0x37, 0xbf, 0xd1, 0x99, 0xad, 0xd9, 0xb7, 0x54, 0x5d, 0x65, 0xff, 0xd1,
- 0x8d, 0x08, 0xcc, 0xd6, 0xec, 0xdb, 0xaa, 0x25, 0x12, 0xa6, 0x7a, 0xcf,
- 0x4f, 0x63, 0x98, 0x43, 0xd8, 0x67, 0x06, 0xc6, 0x31, 0xb9, 0xcb, 0xcf,
- 0x9f, 0xc7, 0xc6, 0xb4, 0xdb, 0xd4, 0xb7, 0x60, 0x8c, 0x3b, 0x90, 0xe5,
- 0xf1, 0xb0, 0x44, 0x5b, 0xff, 0xd1, 0x87, 0x68, 0x46, 0x66, 0xb7, 0x66,
- 0xdd, 0x51, 0x2d, 0x17, 0xfe, 0x0a, 0x85, 0x75, 0xa6, 0x98, 0x78, 0x22,
- 0xc5, 0xff, 0x46, 0xbf, 0xbc, 0x7b, 0x4f, 0x61, 0x16, 0x2f, 0xff, 0x83,
- 0xdc, 0x28, 0x15, 0x00, 0x5f, 0x51, 0xa7, 0x5e, 0xbf, 0x8e, 0x58, 0xbf,
- 0xff, 0xf0, 0x4f, 0x46, 0xc3, 0x3c, 0x6c, 0x4e, 0x16, 0xbe, 0x0b, 0xea,
- 0x34, 0xeb, 0xd7, 0xf1, 0xcb, 0x15, 0xf4, 0xc0, 0x43, 0x6e, 0xbf, 0x47,
- 0xe9, 0xe4, 0x96, 0x2f, 0xa1, 0x1b, 0x19, 0xb2, 0xc5, 0x31, 0xea, 0x85,
- 0xca, 0xaf, 0x47, 0x9d, 0xd6, 0x2f, 0xfb, 0x08, 0x7f, 0x9d, 0x31, 0x2c,
- 0x54, 0x9e, 0xbe, 0x10, 0x5f, 0x86, 0x23, 0x7e, 0x25, 0x8b, 0xcc, 0xdb,
- 0xaa, 0x23, 0x72, 0xfd, 0xdc, 0x45, 0x23, 0x58, 0xa1, 0x9f, 0xfe, 0xe5,
- 0x6c, 0x55, 0x7e, 0x1f, 0xe7, 0x34, 0xb1, 0x7f, 0xa7, 0x68, 0x8a, 0x41,
- 0xc5, 0x8a, 0xd2, 0x23, 0x08, 0xbf, 0x85, 0x17, 0xfb, 0x4e, 0x17, 0xdf,
- 0xf2, 0x1a, 0xc5, 0xe1, 0x47, 0x06, 0xb1, 0x7d, 0xa1, 0x48, 0x16, 0x29,
- 0xcf, 0xfe, 0x23, 0xa3, 0x08, 0xaf, 0xff, 0xff, 0xba, 0x16, 0x73, 0x83,
- 0x9c, 0xd6, 0xec, 0xdb, 0xc6, 0x41, 0xfd, 0x3e, 0xe2, 0xa3, 0x0f, 0x2a,
- 0x51, 0x80, 0xe6, 0x17, 0xf3, 0x46, 0x47, 0xb1, 0x01, 0x62, 0xfd, 0xb1,
- 0x9f, 0x90, 0xd6, 0x2b, 0xe8, 0x80, 0x22, 0x11, 0x19, 0xdf, 0xdc, 0x8c,
- 0x0f, 0x91, 0xe6, 0x2c, 0x5f, 0x9f, 0x6f, 0xbc, 0x72, 0xc5, 0xfb, 0x38,
- 0xda, 0x82, 0xc5, 0x47, 0x9e, 0xa6, 0x8b, 0x2f, 0xc1, 0x23, 0x34, 0x17,
- 0x0d, 0x62, 0xfd, 0xa9, 0xf4, 0x71, 0xab, 0x17, 0xc3, 0x2c, 0x02, 0xc5,
- 0xf4, 0x86, 0x71, 0xac, 0x5f, 0x6f, 0xf9, 0x0d, 0x62, 0xf7, 0xe4, 0xd5,
- 0x8a, 0xc4, 0x44, 0xe8, 0x88, 0x2e, 0x48, 0x61, 0x2d, 0xfb, 0x5b, 0xb3,
- 0x6e, 0xa8, 0x97, 0xcb, 0xf8, 0x5b, 0xe9, 0xe4, 0x96, 0x2f, 0x34, 0x23,
- 0x30, 0xf9, 0x7e, 0x6f, 0x6c, 0x58, 0xbd, 0xf6, 0xf2, 0xc5, 0x70, 0xd7,
- 0x18, 0x23, 0x7f, 0x8c, 0xdf, 0xee, 0x31, 0x76, 0xb1, 0x5e, 0x3d, 0xa1,
- 0x11, 0x5f, 0x08, 0x2f, 0xd2, 0x56, 0x2f, 0xcf, 0x21, 0x8a, 0x3d, 0x62,
- 0xb0, 0xf5, 0x48, 0xa6, 0xfe, 0x2f, 0x67, 0xa7, 0x4b, 0x17, 0xe7, 0xec,
- 0x26, 0x83, 0x58, 0xa9, 0x3d, 0xa3, 0x0b, 0x6f, 0xf6, 0xb4, 0xfe, 0x06,
- 0x71, 0x62, 0xff, 0x49, 0xe6, 0x30, 0x30, 0xc3, 0x58, 0xa7, 0x3e, 0xe0,
- 0x86, 0x95, 0x29, 0xd2, 0x63, 0xbb, 0xbd, 0x34, 0x24, 0x2f, 0xdc, 0x93,
- 0x22, 0xe2, 0xc5, 0xfd, 0x2f, 0x1f, 0x9d, 0xc1, 0x62, 0xfd, 0xa3, 0x7e,
- 0x2e, 0x2c, 0x54, 0x48, 0x87, 0xf9, 0x59, 0x86, 0x37, 0xa7, 0x52, 0xb1,
- 0x58, 0x79, 0xce, 0x65, 0x73, 0x7d, 0x62, 0xe8, 0xdc, 0x2a, 0xb1, 0x7c,
- 0xe0, 0x9e, 0xd6, 0x2f, 0x80, 0x3e, 0x4a, 0xc5, 0xf3, 0x6b, 0x6d, 0x96,
- 0x2d, 0x84, 0x79, 0x1d, 0x08, 0xea, 0x08, 0xcb, 0xec, 0x5e, 0x3c, 0x87,
- 0x8d, 0x77, 0xfb, 0xf1, 0x9b, 0xfd, 0xfe, 0x11, 0x62, 0xf0, 0x24, 0x35,
- 0x8b, 0xfd, 0x8f, 0xa8, 0x7d, 0xc3, 0x58, 0xbd, 0xb4, 0x98, 0xb1, 0x58,
- 0x8a, 0xc8, 0xf3, 0xbf, 0x8f, 0x11, 0xa5, 0xce, 0x62, 0xc5, 0xed, 0x8c,
- 0x82, 0xc5, 0x82, 0x44, 0x6e, 0x18, 0x62, 0xee, 0x90, 0x58, 0xbe, 0x17,
- 0xdf, 0x4b, 0x17, 0xdc, 0xfc, 0xfd, 0x62, 0xff, 0x4e, 0xd2, 0x5b, 0x60,
- 0x45, 0x8b, 0x9b, 0xeb, 0x14, 0xb1, 0x4b, 0x16, 0xe3, 0x9a, 0xfd, 0x0b,
- 0xf0, 0x32, 0xf8, 0x0e, 0x7e, 0x2c, 0x54, 0xa3, 0x7b, 0x62, 0x38, 0x99,
- 0x7c, 0x67, 0x68, 0xc0, 0xab, 0x3d, 0x50, 0x2d, 0x52, 0xa6, 0x34, 0x6d,
- 0x9e, 0x86, 0xf9, 0x91, 0x95, 0xef, 0x1f, 0x77, 0x65, 0xef, 0x08, 0xc8,
- 0xf2, 0x58, 0x8d, 0x35, 0x0b, 0x63, 0xc2, 0x9b, 0xf2, 0x98, 0x4a, 0x31,
- 0x4e, 0x43, 0xaf, 0xd0, 0xed, 0x13, 0xb7, 0x42, 0x98, 0xe1, 0xa3, 0x23,
- 0x01, 0xbf, 0xdb, 0xc6, 0x46, 0xc1, 0x48, 0xd0, 0x28, 0xeb, 0x17, 0xff,
- 0xe2, 0x9d, 0xe3, 0x3d, 0xde, 0xef, 0xc2, 0xce, 0x8c, 0xb1, 0x7f, 0xf4,
- 0x3c, 0xf1, 0x46, 0x0d, 0xfa, 0x48, 0xd6, 0x2e, 0x37, 0x65, 0x8b, 0xff,
- 0x63, 0xf4, 0xf6, 0x61, 0x7b, 0x8b, 0x17, 0x07, 0x18, 0xe7, 0xb2, 0x18,
- 0xd5, 0xff, 0xd1, 0x9c, 0xc8, 0x9f, 0x53, 0x13, 0x9d, 0x62, 0x86, 0x9b,
- 0xdf, 0x6b, 0x8f, 0x0a, 0x43, 0x99, 0x5f, 0x6b, 0x26, 0x25, 0x8b, 0xfe,
- 0x1e, 0xa7, 0xec, 0x38, 0x1d, 0x62, 0xfc, 0xfc, 0xc1, 0xc6, 0x49, 0xee,
- 0xf0, 0x8e, 0xfd, 0xad, 0xd9, 0xb7, 0x54, 0x55, 0x65, 0xfb, 0x39, 0xf9,
- 0xed, 0x62, 0xd1, 0x98, 0x7c, 0x1f, 0x37, 0xbf, 0x05, 0x47, 0xa6, 0xdd,
- 0x62, 0xf8, 0x41, 0x07, 0x2b, 0x17, 0xee, 0x79, 0xfb, 0xe2, 0xc5, 0xa3,
- 0x75, 0x8a, 0xf9, 0xf3, 0x78, 0x96, 0x38, 0xaa, 0xff, 0x7b, 0x92, 0x0c,
- 0xef, 0xcb, 0x17, 0x38, 0x45, 0x8b, 0xb3, 0x4b, 0x17, 0xb3, 0xbf, 0x2c,
- 0x5f, 0x39, 0xdb, 0xa2, 0xc5, 0x62, 0x29, 0xcd, 0x35, 0x61, 0x90, 0x0b,
- 0xf8, 0x7a, 0xf4, 0x05, 0xc5, 0x8b, 0xfe, 0x78, 0xce, 0x9d, 0x70, 0xed,
- 0xda, 0xc5, 0xc1, 0x03, 0x58, 0xaf, 0x9e, 0xe1, 0x20, 0xdf, 0xdf, 0x9e,
- 0x82, 0x1e, 0x2c, 0x5f, 0xbf, 0x11, 0x48, 0xd6, 0x2f, 0x36, 0xa0, 0xb1,
- 0x4c, 0x78, 0xc1, 0x94, 0xdf, 0xbd, 0x11, 0x48, 0xd6, 0x2f, 0xff, 0x00,
- 0xe2, 0x1e, 0x67, 0x80, 0x71, 0x76, 0xb1, 0x44, 0x7e, 0xde, 0x29, 0xbf,
- 0xfb, 0xdf, 0x9e, 0x13, 0x08, 0x2e, 0xfa, 0x58, 0xbd, 0x30, 0xc5, 0x8b,
- 0xfa, 0x79, 0x1b, 0x63, 0x1d, 0x62, 0xfe, 0x71, 0x6e, 0x53, 0x12, 0xc5,
- 0xff, 0xc2, 0xe7, 0xdf, 0xd0, 0xc2, 0x71, 0xac, 0x5e, 0xe1, 0x8c, 0xb1,
- 0x50, 0x54, 0xac, 0x37, 0x6c, 0x84, 0xc7, 0x64, 0x31, 0x24, 0x68, 0x73,
- 0xe6, 0x44, 0x5f, 0xe4, 0x4b, 0xfe, 0x37, 0x0b, 0x3b, 0xf3, 0x1d, 0x62,
- 0xff, 0xfd, 0xf9, 0xee, 0x02, 0x78, 0xec, 0x33, 0xf2, 0xfa, 0x58, 0xb0,
- 0x45, 0x8b, 0x06, 0xb1, 0x5d, 0x9a, 0x7f, 0x0a, 0x5e, 0x09, 0x3e, 0x58,
- 0xbf, 0x8b, 0xc5, 0x3e, 0xe2, 0xc5, 0xfd, 0x27, 0x32, 0x4b, 0x75, 0x8b,
- 0xa7, 0x4b, 0x15, 0x87, 0xe7, 0xa2, 0xde, 0x17, 0xdf, 0x1c, 0xef, 0x12,
- 0xc5, 0xf7, 0xe4, 0x8d, 0x58, 0xac, 0x3c, 0x78, 0x89, 0x2e, 0x6e, 0xd6,
- 0x2f, 0x77, 0xc8, 0x96, 0x2e, 0x7f, 0x2c, 0x5e, 0x32, 0x40, 0xb1, 0x68,
- 0xf5, 0x8a, 0xed, 0x10, 0x5a, 0x18, 0xe1, 0x07, 0x85, 0xe3, 0x87, 0xaf,
- 0xa2, 0x21, 0x6e, 0xb1, 0x7f, 0x61, 0xe2, 0x66, 0xd9, 0x62, 0xdc, 0x58,
- 0xbe, 0x7f, 0xb9, 0xab, 0x14, 0x03, 0x6b, 0xc1, 0x2b, 0x9b, 0xb5, 0x8a,
- 0x23, 0x73, 0xe2, 0x1b, 0xff, 0xe8, 0x7d, 0xa0, 0x6b, 0x73, 0x05, 0xce,
- 0x3a, 0xc5, 0x2c, 0x56, 0x1e, 0xe8, 0x45, 0x1a, 0x94, 0xd8, 0x9c, 0x95,
- 0xa1, 0x3a, 0x4f, 0xb7, 0x0d, 0xd6, 0x2f, 0xf8, 0xa6, 0x1e, 0x73, 0x8e,
- 0x56, 0x2f, 0xf1, 0x3c, 0x22, 0xfc, 0xec, 0xb1, 0x79, 0x9b, 0x75, 0x44,
- 0x80, 0x5b, 0x50, 0x3d, 0xfd, 0xcd, 0x6f, 0xb5, 0x85, 0xe5, 0x8b, 0xe1,
- 0xc6, 0xe1, 0x64, 0x68, 0xb1, 0x7f, 0xfe, 0xfe, 0x1f, 0xce, 0x22, 0x86,
- 0x13, 0xed, 0xc5, 0x8a, 0x1a, 0x6d, 0x59, 0x09, 0x7d, 0x14, 0xf0, 0x8b,
- 0xc6, 0x77, 0xba, 0x37, 0xd6, 0x2b, 0xaa, 0x7d, 0xf1, 0x91, 0xc0, 0xca,
- 0x7d, 0xef, 0xc8, 0xd6, 0x2f, 0xdc, 0x62, 0x6e, 0xd6, 0x2f, 0xfb, 0xcf,
- 0xc7, 0x10, 0x5c, 0x72, 0xb1, 0x76, 0x12, 0xc5, 0xc2, 0x89, 0x62, 0xd2,
- 0xb1, 0x52, 0x6a, 0x84, 0x33, 0x7b, 0x06, 0xeb, 0x15, 0x04, 0xce, 0x77,
- 0x3b, 0xec, 0x75, 0xca, 0x23, 0xcf, 0x74, 0x80, 0x72, 0x0b, 0xfa, 0x75,
- 0xb4, 0xeb, 0x65, 0x8b, 0xe7, 0x3c, 0xf1, 0x62, 0xa0, 0x7a, 0x46, 0x98,
- 0x5f, 0xed, 0x6c, 0x79, 0x28, 0x71, 0x62, 0xa4, 0xf6, 0x30, 0x8e, 0xfb,
- 0xd3, 0xd3, 0x75, 0x8b, 0xff, 0x89, 0xf6, 0xcc, 0x23, 0x73, 0xbf, 0x2c,
- 0x5f, 0xff, 0x1d, 0xc8, 0x06, 0x79, 0xc8, 0x50, 0xce, 0x2c, 0x5f, 0xfc,
- 0xf2, 0x76, 0x19, 0x81, 0x24, 0xa0, 0xb1, 0x7f, 0xff, 0xcf, 0xe2, 0xce,
- 0x85, 0x9c, 0xdb, 0x03, 0x8e, 0x17, 0xdf, 0x4b, 0x15, 0x29, 0xb6, 0x8c,
- 0x9b, 0x11, 0x7e, 0xa0, 0x04, 0x6b, 0xf0, 0x18, 0x04, 0x75, 0x8b, 0x98,
- 0x6b, 0x17, 0xfd, 0x07, 0xf0, 0x27, 0x3b, 0x82, 0xc5, 0xff, 0x46, 0x73,
- 0x35, 0xb6, 0xd8, 0x05, 0x8a, 0xd9, 0x12, 0x11, 0x0b, 0xfc, 0xea, 0xff,
- 0xf7, 0x6c, 0x42, 0x06, 0xa7, 0xee, 0x47, 0x58, 0xbf, 0x9f, 0xa3, 0xfa,
- 0x29, 0x58, 0xa9, 0x4d, 0x93, 0x21, 0x70, 0xe6, 0x5c, 0x4a, 0xbf, 0x8c,
- 0x8d, 0xb4, 0xf2, 0x75, 0x8b, 0xb9, 0x05, 0x8a, 0x63, 0xcc, 0xe1, 0xa5,
- 0xff, 0xfd, 0x3b, 0xf9, 0xf5, 0xac, 0x07, 0x3c, 0xdf, 0x61, 0xac, 0x5c,
- 0x15, 0xfa, 0xc5, 0xff, 0xec, 0x8b, 0xec, 0x7f, 0x7e, 0x7c, 0x23, 0xac,
- 0x5f, 0xfd, 0xf7, 0x38, 0xf3, 0xcf, 0xfd, 0xdd, 0x62, 0xe9, 0xf2, 0xc5,
- 0x0c, 0xf7, 0x02, 0x22, 0xd4, 0x6c, 0xd9, 0x84, 0xcc, 0x25, 0x36, 0x86,
- 0xcc, 0x12, 0x46, 0xf5, 0x92, 0x9d, 0xcd, 0x84, 0x2e, 0xe7, 0x5d, 0xc2,
- 0x06, 0x3c, 0x8a, 0x28, 0x49, 0x69, 0xd4, 0xf0, 0xa4, 0xfc, 0x76, 0x0d,
- 0x2d, 0x9c, 0xa3, 0x13, 0xe4, 0x71, 0xbe, 0x8e, 0xb4, 0x50, 0x8c, 0xe8,
- 0x43, 0x1c, 0xb8, 0x60, 0xe0, 0x48, 0x54, 0x5f, 0xfa, 0x13, 0x80, 0xfe,
- 0x61, 0x6e, 0xb1, 0x7e, 0x92, 0x2c, 0xf2, 0xc5, 0xf6, 0xb4, 0xfb, 0xac,
- 0x5f, 0x16, 0x6d, 0x19, 0x88, 0x88, 0x8e, 0x3e, 0x30, 0x9a, 0xff, 0x05,
- 0x42, 0x91, 0xbf, 0x66, 0x0a, 0x39, 0x62, 0xfb, 0x7f, 0xb6, 0xeb, 0x17,
- 0xf8, 0xce, 0x66, 0xb7, 0xfc, 0xac, 0x5f, 0xf6, 0x45, 0x06, 0xd6, 0xdf,
- 0x12, 0xc5, 0xfe, 0x35, 0x8b, 0x03, 0x60, 0x2c, 0x5f, 0xe7, 0xee, 0x13,
- 0xd2, 0x63, 0xd6, 0x2f, 0x8d, 0x87, 0xf1, 0x62, 0xf0, 0xa4, 0xc5, 0x8b,
- 0xfe, 0x78, 0x3f, 0xc4, 0x73, 0xba, 0xc5, 0x40, 0xf5, 0xfc, 0x3d, 0x68,
- 0xc8, 0xdd, 0x3e, 0x98, 0xd4, 0x91, 0x24, 0xa3, 0x36, 0x34, 0xf0, 0x06,
- 0x9c, 0x39, 0x31, 0xee, 0xff, 0x46, 0x7d, 0x8f, 0x92, 0x35, 0x8a, 0x8c,
- 0x5d, 0x13, 0xd4, 0xa2, 0x00, 0xe5, 0x1b, 0x47, 0x42, 0x1e, 0xfd, 0xad,
- 0xd9, 0xb7, 0x54, 0x59, 0x05, 0xc6, 0x8d, 0x62, 0xd1, 0x98, 0x7a, 0x1a,
- 0x37, 0xbf, 0xff, 0xdf, 0x6d, 0x46, 0x7d, 0xbc, 0x42, 0xdb, 0x98, 0x79,
- 0x8f, 0x58, 0xbf, 0x9f, 0xa4, 0x67, 0x27, 0xb5, 0x8b, 0xff, 0xfc, 0x21,
- 0xe4, 0x61, 0x99, 0xf2, 0x13, 0x47, 0xe1, 0xb3, 0xc5, 0x8b, 0xff, 0xf6,
- 0xef, 0xcc, 0x1e, 0x14, 0x87, 0xe3, 0x5b, 0x8b, 0x17, 0xfd, 0xf7, 0x60,
- 0x60, 0xb5, 0xb2, 0xc5, 0xfb, 0xe2, 0x63, 0x63, 0x3e, 0x89, 0x1f, 0x2b,
- 0xda, 0x60, 0x99, 0xe8, 0xe1, 0xf3, 0x5c, 0x4e, 0x7f, 0xd1, 0xb8, 0xd0,
- 0xd5, 0x18, 0xbc, 0xa0, 0x7b, 0xfd, 0x19, 0x9a, 0xdd, 0x9b, 0x75, 0x45,
- 0xae, 0x5f, 0xa2, 0xf0, 0xe4, 0x96, 0x2f, 0xf1, 0x66, 0xda, 0xd3, 0x86,
- 0xb1, 0x7d, 0xf7, 0x98, 0x96, 0x2f, 0xd8, 0x64, 0xed, 0x19, 0x88, 0x81,
- 0xdc, 0xa4, 0x21, 0xad, 0xfe, 0x8c, 0xcd, 0x6e, 0xcd, 0xba, 0xa2, 0xe4,
- 0x2f, 0xda, 0xdd, 0x9b, 0x75, 0x45, 0xd8, 0x5f, 0x47, 0x4f, 0xb1, 0x62,
- 0xff, 0xcd, 0x08, 0xcc, 0xd6, 0xec, 0xdb, 0xaa, 0x28, 0xe2, 0xd1, 0x98,
- 0x8a, 0xc7, 0x37, 0x39, 0x2d, 0xff, 0x33, 0xf3, 0xf9, 0x0e, 0x4a, 0xc5,
- 0xe3, 0xe7, 0xd6, 0x2f, 0xfb, 0x37, 0x14, 0x97, 0x70, 0xe2, 0xc5, 0xfd,
- 0xad, 0x4e, 0xff, 0x75, 0x8b, 0x8a, 0x33, 0xe8, 0xbf, 0x63, 0x82, 0x1d,
- 0xe1, 0xdd, 0xff, 0xbd, 0xc7, 0x38, 0x8d, 0x2c, 0x02, 0xc5, 0xf1, 0x4c,
- 0x0e, 0xb1, 0x7c, 0xe4, 0x07, 0x58, 0xb9, 0xcd, 0x58, 0xa8, 0x1b, 0x9e,
- 0x84, 0x37, 0xfe, 0x8d, 0x82, 0xa7, 0x9d, 0x43, 0x1f, 0xa2, 0xc5, 0xa0,
- 0xb1, 0x7e, 0xd6, 0xec, 0xdb, 0xaa, 0x29, 0x52, 0xff, 0xb7, 0xfb, 0xc5,
- 0xf9, 0xdb, 0x16, 0x2f, 0xff, 0x7e, 0x76, 0x9f, 0xbf, 0x46, 0x1f, 0xdd,
- 0x62, 0x30, 0xde, 0x5d, 0x08, 0xcc, 0x46, 0x94, 0x4e, 0x75, 0xda, 0x62,
- 0xcd, 0x0e, 0x4b, 0xff, 0x33, 0xfa, 0x02, 0x1b, 0x10, 0x16, 0x2e, 0xf8,
- 0x96, 0x2f, 0xfe, 0xe3, 0x76, 0x79, 0xff, 0xb1, 0xfa, 0x2c, 0x5a, 0x32,
- 0x55, 0x72, 0x0d, 0x03, 0x16, 0xfb, 0x23, 0x3c, 0x6c, 0x1f, 0x29, 0xe1,
- 0xf7, 0x86, 0x2f, 0xff, 0xfe, 0x6f, 0x60, 0x26, 0x11, 0x86, 0x1f, 0x07,
- 0x30, 0x91, 0xb3, 0x1a, 0xb1, 0x5b, 0x3b, 0x6c, 0xb8, 0x53, 0xec, 0xc7,
- 0x1b, 0xce, 0x47, 0x8d, 0xbc, 0x28, 0x3b, 0x85, 0x03, 0xd7, 0x08, 0xc7,
- 0x85, 0x53, 0x4a, 0x5b, 0x01, 0x59, 0x43, 0x1b, 0x8a, 0x7e, 0x87, 0x88,
- 0xa1, 0xed, 0xd2, 0x59, 0x68, 0x70, 0x81, 0xbf, 0xe8, 0x46, 0x66, 0xb7,
- 0x66, 0xdd, 0x51, 0x1c, 0x17, 0xfc, 0xf1, 0x99, 0xad, 0xd9, 0xb7, 0x54,
- 0x56, 0xa5, 0xa3, 0x19, 0x12, 0xbe, 0x4b, 0xbf, 0xfd, 0x18, 0x76, 0x84,
- 0x66, 0x6b, 0x76, 0x6d, 0xd5, 0x12, 0xd9, 0x74, 0x6c, 0x16, 0xd6, 0x2f,
- 0x05, 0x77, 0xd2, 0xc5, 0xe8, 0xde, 0x37, 0xe2, 0xc5, 0xb7, 0x58, 0xbc,
- 0x22, 0x75, 0x8b, 0xc2, 0xd0, 0x16, 0x2e, 0xce, 0xd6, 0x2f, 0xc7, 0x3c,
- 0xbf, 0x16, 0x2f, 0xe9, 0xd0, 0x1b, 0xbe, 0x2c, 0x58, 0x78, 0x7a, 0xff,
- 0x28, 0xbf, 0x7a, 0x7e, 0x67, 0x16, 0x2f, 0x74, 0x14, 0x16, 0x28, 0x2a,
- 0x99, 0x6c, 0x04, 0xf7, 0x1c, 0xec, 0x79, 0xdb, 0xc8, 0x9f, 0xa1, 0x55,
- 0xff, 0x07, 0x14, 0x1b, 0x5b, 0x7c, 0x4b, 0x17, 0x0e, 0x0b, 0x17, 0xff,
- 0xd8, 0x1e, 0x6d, 0xef, 0x60, 0x6d, 0xe6, 0x35, 0x62, 0xff, 0xb5, 0x09,
- 0x3e, 0x7d, 0xe0, 0xb1, 0x58, 0x8e, 0x2f, 0x9f, 0x10, 0xc0, 0x94, 0xed,
- 0x2b, 0x17, 0xc1, 0x07, 0x3d, 0xac, 0x54, 0x6b, 0x36, 0xee, 0x23, 0x7f,
- 0xd9, 0xd9, 0x60, 0x00, 0xd0, 0x58, 0xb8, 0xfb, 0xac, 0x5f, 0xcf, 0xdf,
- 0x07, 0x84, 0xb1, 0x7f, 0x77, 0x90, 0x9d, 0x01, 0x62, 0xb0, 0xf7, 0x58,
- 0xba, 0xff, 0xfa, 0x4b, 0x6e, 0x09, 0x9e, 0x1c, 0xfb, 0x41, 0x62, 0xa5,
- 0x31, 0xf8, 0x1c, 0xe9, 0xdb, 0xe4, 0x17, 0xef, 0xbc, 0x96, 0xcb, 0x17,
- 0xff, 0x8b, 0x0e, 0x76, 0x81, 0x83, 0xfc, 0xf6, 0xb1, 0x77, 0xcc, 0x58,
- 0xb8, 0x7e, 0x58, 0xa6, 0x36, 0x22, 0x19, 0xbe, 0x29, 0xee, 0x0b, 0x17,
- 0x19, 0xb2, 0xc5, 0xfe, 0xf7, 0x06, 0x26, 0xd4, 0x16, 0x28, 0xe7, 0x9e,
- 0x43, 0x57, 0xb4, 0xd1, 0x2c, 0x53, 0x9b, 0xf1, 0x10, 0xdf, 0x6e, 0xda,
- 0x02, 0xc5, 0xfa, 0x4f, 0x9d, 0xf9, 0x62, 0xdb, 0x49, 0xe6, 0x91, 0x25,
- 0xff, 0xb5, 0xf6, 0xc2, 0x14, 0x33, 0x8b, 0x17, 0xff, 0xdd, 0x80, 0x7f,
- 0x68, 0x67, 0x08, 0x4c, 0x62, 0xc5, 0x3a, 0x24, 0x18, 0xfa, 0xf8, 0x19,
- 0xa8, 0x96, 0x2f, 0xf3, 0x7b, 0x86, 0x72, 0x71, 0x62, 0xfc, 0xff, 0x93,
- 0x22, 0x58, 0xbd, 0xe9, 0x3a, 0xc5, 0x75, 0x56, 0xb5, 0x02, 0x81, 0xbe,
- 0xee, 0x41, 0x14, 0x2c, 0x74, 0xdb, 0xf8, 0x5b, 0x80, 0x84, 0x89, 0x3c,
- 0x68, 0x10, 0xaa, 0xff, 0xe3, 0x64, 0xbd, 0x9a, 0x7d, 0x98, 0xeb, 0x17,
- 0xcd, 0x03, 0x5d, 0x62, 0x96, 0x3e, 0x68, 0xef, 0xf7, 0x59, 0xcf, 0xb8,
- 0xb7, 0x58, 0xa3, 0x4f, 0x48, 0x03, 0x97, 0xc4, 0xfe, 0xe2, 0xc5, 0xe7,
- 0xcd, 0x2c, 0x5d, 0xee, 0x2c, 0x5c, 0xdd, 0xac, 0x56, 0x1b, 0x02, 0x18,
- 0xb3, 0xe9, 0x11, 0xa7, 0x22, 0xfa, 0x65, 0xfb, 0x4c, 0x59, 0x2b, 0x14,
- 0xa8, 0x86, 0xc7, 0x4c, 0x2f, 0xf0, 0xb0, 0x63, 0x5b, 0xa4, 0x96, 0x2f,
- 0x63, 0x8d, 0x62, 0xf0, 0xf0, 0xeb, 0x16, 0x21, 0x9b, 0x97, 0x1c, 0xbf,
- 0x49, 0x7b, 0x3c, 0xb1, 0x4e, 0x79, 0x84, 0x4b, 0x7f, 0xe2, 0x9c, 0xdf,
- 0xef, 0xd1, 0xb4, 0xb1, 0x52, 0x8f, 0xb8, 0x42, 0x6f, 0xc4, 0x17, 0x18,
- 0x75, 0x8b, 0x85, 0x05, 0x8b, 0xd3, 0xee, 0x2c, 0x5e, 0x14, 0x9d, 0x62,
- 0xfe, 0x81, 0x4f, 0xbf, 0x2b, 0x17, 0x3e, 0x96, 0x2a, 0x24, 0x57, 0x80,
- 0x64, 0x86, 0x38, 0x3b, 0xe1, 0xde, 0x85, 0xb7, 0xef, 0xbe, 0xa4, 0x6b,
- 0x17, 0xf8, 0x51, 0xf1, 0x7c, 0x45, 0xe5, 0x8b, 0xff, 0x36, 0xc6, 0x16,
- 0x70, 0x85, 0xf5, 0x8b, 0xe9, 0x39, 0x9b, 0x2c, 0x56, 0xe8, 0xc6, 0xf9,
- 0x43, 0x1c, 0x92, 0x05, 0xff, 0x3c, 0x1b, 0x87, 0x9c, 0xf2, 0xc5, 0xd0,
- 0xc5, 0x8b, 0xfc, 0xcf, 0xe8, 0xbe, 0x23, 0x56, 0x2a, 0x23, 0xcd, 0xf8,
- 0xbd, 0xfd, 0xb4, 0x1f, 0x79, 0x3a, 0xc5, 0xff, 0xe3, 0x96, 0x02, 0x41,
- 0x85, 0x38, 0x1a, 0xc5, 0x49, 0xfc, 0x39, 0x85, 0x4a, 0x68, 0x19, 0x08,
- 0x5d, 0x42, 0x6e, 0xe6, 0x82, 0xc5, 0xff, 0x42, 0x33, 0x35, 0xbb, 0x36,
- 0xea, 0x89, 0x80, 0xa9, 0x3e, 0x26, 0x17, 0xbd, 0xf7, 0xfa, 0xc5, 0xf3,
- 0x79, 0xfc, 0xb1, 0x51, 0xe6, 0xfc, 0x43, 0xb7, 0x03, 0xb5, 0x8b, 0x82,
- 0xee, 0xb1, 0x7a, 0x1a, 0x3a, 0xc5, 0xcf, 0xf5, 0x8b, 0xa1, 0x05, 0x8b,
- 0xfd, 0xb3, 0x78, 0x06, 0x14, 0x16, 0x2d, 0x2b, 0x17, 0xfb, 0xd0, 0x9d,
- 0x6a, 0x60, 0xb1, 0x76, 0xce, 0xb1, 0x7f, 0xd3, 0x9c, 0x8b, 0xee, 0x1f,
- 0x96, 0x2b, 0x11, 0x30, 0xe2, 0x24, 0x69, 0xc1, 0x8b, 0xb9, 0x2b, 0x15,
- 0x29, 0xe2, 0x6c, 0x49, 0x01, 0x91, 0x8d, 0xe0, 0xf6, 0xe2, 0xee, 0x30,
- 0xd0, 0xce, 0x11, 0xd5, 0xe1, 0x7b, 0x8b, 0x17, 0xf7, 0xb2, 0x22, 0x93,
- 0xac, 0x5e, 0x0d, 0xc0, 0xb1, 0x7f, 0x1f, 0xed, 0xa9, 0xd9, 0x62, 0xd8,
- 0xb1, 0x52, 0x78, 0x11, 0xc5, 0xf7, 0xdc, 0x62, 0x02, 0xc5, 0xe2, 0x9d,
- 0x96, 0x2f, 0xfd, 0x9d, 0xc3, 0xf3, 0xc3, 0x7f, 0x2b, 0x15, 0x04, 0xd3,
- 0x9c, 0x7a, 0x22, 0xef, 0xaf, 0x00, 0x90, 0x2e, 0x44, 0x10, 0x76, 0xfe,
- 0xef, 0x52, 0x63, 0x12, 0xc5, 0xfe, 0x9c, 0xd7, 0xbd, 0x9c, 0x58, 0xa6,
- 0x3e, 0x20, 0x17, 0xdf, 0xe8, 0x36, 0xa2, 0xfb, 0xe9, 0x62, 0xff, 0x0b,
- 0xbd, 0x3c, 0x9f, 0x16, 0x2f, 0xdf, 0x79, 0x2d, 0x96, 0x2f, 0xfa, 0x76,
- 0xf1, 0x48, 0xbd, 0xc5, 0x8a, 0xfa, 0x25, 0xb8, 0x69, 0x1c, 0x51, 0x7c,
- 0x59, 0xc9, 0x58, 0xa8, 0x93, 0x1f, 0xf4, 0x32, 0xfa, 0x19, 0xde, 0x83,
- 0x81, 0x62, 0xf8, 0xb3, 0xce, 0xb1, 0x7e, 0x92, 0xdd, 0xce, 0xb1, 0x44,
- 0x79, 0x3e, 0x21, 0xb8, 0xa5, 0x62, 0xfb, 0xbd, 0xdc, 0xd5, 0x8b, 0xf3,
- 0x1b, 0x9f, 0x65, 0x8a, 0xc4, 0xc9, 0x22, 0x39, 0x66, 0x60, 0x10, 0xf8,
- 0x58, 0x44, 0xd7, 0xff, 0x69, 0xbe, 0x66, 0x16, 0x45, 0x31, 0xeb, 0x17,
- 0xff, 0xa1, 0xfc, 0x20, 0xcc, 0xd7, 0xde, 0x4e, 0xb1, 0x7f, 0x3f, 0xb0,
- 0xf3, 0xf5, 0x8b, 0xfe, 0x70, 0x6d, 0xf9, 0xe0, 0xb8, 0xb1, 0x7f, 0xa0,
- 0xde, 0xe3, 0x94, 0xac, 0x5a, 0x74, 0x7d, 0xa4, 0x77, 0x5d, 0xa6, 0x19,
- 0xa4, 0xcf, 0x42, 0x6a, 0xff, 0xf1, 0x30, 0x79, 0xbf, 0xe7, 0xb8, 0x47,
- 0x62, 0xc5, 0xd1, 0xec, 0xb1, 0x7e, 0x8b, 0x9e, 0x7d, 0x96, 0x2f, 0xe8,
- 0x3c, 0x4c, 0xd0, 0x58, 0xa7, 0x3d, 0x96, 0x2b, 0xbf, 0xf6, 0x1f, 0x35,
- 0x9d, 0xc3, 0x3c, 0xb1, 0x7f, 0x3f, 0xdc, 0xf8, 0x6a, 0xc5, 0x7c, 0xfb,
- 0x78, 0x7f, 0x7f, 0xcd, 0xfd, 0x4b, 0xc1, 0xb8, 0xb1, 0x7f, 0xf9, 0xb6,
- 0xfb, 0xc9, 0x64, 0x4f, 0xa7, 0x58, 0xa1, 0xab, 0x7d, 0xc8, 0xd5, 0x22,
- 0x37, 0xd2, 0x7f, 0xdc, 0xfd, 0x08, 0xd1, 0x11, 0x06, 0x71, 0x62, 0x58,
- 0xb4, 0x72, 0xc5, 0xfe, 0x92, 0xf0, 0x0c, 0x28, 0x2c, 0x5f, 0x6e, 0xf8,
- 0x35, 0x8a, 0x58, 0xb6, 0xeb, 0x18, 0x4c, 0xb8, 0x40, 0x48, 0xba, 0x03,
- 0x58, 0xa8, 0xdd, 0x1b, 0x3b, 0x08, 0xc0, 0x57, 0xb3, 0x47, 0x2f, 0xd1,
- 0x01, 0xc6, 0x2f, 0xc6, 0xcc, 0x30, 0x6b, 0x17, 0xd9, 0xef, 0xe2, 0xc5,
- 0xcc, 0x6a, 0xc5, 0xd8, 0x32, 0x37, 0x51, 0xc4, 0x57, 0x46, 0xdb, 0xae,
- 0x30, 0xa2, 0xef, 0x01, 0x62, 0xf8, 0x7f, 0xcd, 0x96, 0x2e, 0x09, 0x05,
- 0x8b, 0xf3, 0x67, 0xb0, 0xeb, 0x17, 0xb3, 0xbf, 0x2c, 0x56, 0xc7, 0x8a,
- 0x69, 0x3d, 0x6c, 0x8b, 0xf7, 0x18, 0xd1, 0x23, 0x2f, 0xdf, 0x8c, 0x8e,
- 0x62, 0x02, 0xc5, 0xfd, 0x9f, 0x63, 0x0b, 0xcb, 0x15, 0xb1, 0xed, 0x0c,
- 0xb2, 0xf3, 0x36, 0xeb, 0x17, 0xfa, 0x2c, 0xd3, 0xec, 0xc7, 0x58, 0xbf,
- 0x46, 0x92, 0x68, 0xf1, 0x62, 0xfe, 0xcf, 0x7a, 0x75, 0xc5, 0x8b, 0xf9,
- 0x88, 0x1b, 0x03, 0xcb, 0x17, 0xe3, 0x3d, 0xc9, 0xf2, 0xc5, 0x4a, 0x65,
- 0x5b, 0x11, 0xe0, 0xee, 0x8d, 0x48, 0xba, 0x38, 0xb8, 0xc2, 0xfb, 0x46,
- 0x46, 0xee, 0x81, 0x74, 0x28, 0x46, 0x16, 0xa4, 0x73, 0x1a, 0xae, 0xd1,
- 0xa6, 0xc1, 0xc8, 0x71, 0xa2, 0xe4, 0xb9, 0x73, 0x61, 0x53, 0xbc, 0x78,
- 0xbd, 0xc6, 0x88, 0xf0, 0xe3, 0x8a, 0x31, 0xfd, 0x46, 0xf8, 0x78, 0x4d,
- 0xfe, 0x51, 0x1b, 0x47, 0xa0, 0x08, 0x66, 0x94, 0xa6, 0x4e, 0x4b, 0xd4,
- 0xf4, 0x6b, 0x02, 0x6a, 0xe8, 0xc6, 0x19, 0x74, 0x74, 0x3a, 0x8c, 0x8f,
- 0x02, 0xf1, 0xc5, 0xa4, 0x8b, 0xff, 0x34, 0x23, 0x33, 0x5b, 0xb3, 0x6e,
- 0xa8, 0x98, 0xcb, 0xa4, 0x22, 0xc5, 0xda, 0xc5, 0x8b, 0x4e, 0x8d, 0x87,
- 0xc6, 0x6f, 0xf6, 0x1b, 0xcf, 0xc9, 0x79, 0x62, 0xfb, 0xd0, 0x93, 0x56,
- 0x28, 0x8f, 0x60, 0xc3, 0x4b, 0x46, 0x3a, 0x67, 0xc7, 0x1e, 0xfc, 0x20,
- 0x38, 0xfd, 0x7f, 0xc3, 0x7e, 0x91, 0x9d, 0x80, 0xc8, 0x2c, 0x5f, 0xf4,
- 0x6f, 0x1b, 0xfd, 0xe4, 0xec, 0x35, 0x8b, 0x05, 0x56, 0x2e, 0x0c, 0x35,
- 0x8a, 0x0b, 0x0d, 0x80, 0x62, 0xd7, 0xe8, 0xde, 0x36, 0x8d, 0xa3, 0x78,
- 0xd9, 0x62, 0xfe, 0x0a, 0xc6, 0xe1, 0x64, 0x21, 0xf5, 0x8b, 0xc1, 0x6e,
- 0x03, 0x58, 0xa8, 0xdc, 0xf8, 0xa3, 0x51, 0xf5, 0xfd, 0xad, 0x08, 0xb3,
- 0xeb, 0x17, 0xd2, 0x4f, 0xf5, 0x8b, 0xe9, 0xda, 0x74, 0xb1, 0x7f, 0xb9,
- 0x20, 0x6f, 0x31, 0xab, 0x17, 0xbd, 0x31, 0x2c, 0x5f, 0x4c, 0x4e, 0x75,
- 0x8b, 0xff, 0x16, 0x0b, 0x72, 0xcd, 0x8c, 0x82, 0xc5, 0xc3, 0xc5, 0x8b,
- 0x39, 0x1e, 0xc0, 0x44, 0x1a, 0xc4, 0x51, 0xe9, 0xee, 0xef, 0xca, 0xc5,
- 0xf7, 0x27, 0x52, 0xb1, 0x7d, 0xb0, 0x87, 0x1e, 0xb1, 0x7f, 0xc1, 0x1c,
- 0x1d, 0x72, 0x29, 0x3a, 0xc5, 0x0d, 0x3f, 0xa7, 0x21, 0x8f, 0x23, 0x88,
- 0xd3, 0x50, 0xc1, 0xf9, 0x17, 0x85, 0xcc, 0x22, 0x08, 0x51, 0x68, 0x2c,
- 0x5f, 0x8f, 0x39, 0xee, 0x2c, 0x5f, 0xb8, 0xe5, 0xdc, 0x16, 0x2e, 0xc8,
- 0x96, 0x2c, 0x1f, 0x53, 0xc1, 0xc2, 0x9a, 0x8d, 0x11, 0x4a, 0x31, 0x2c,
- 0x69, 0xbf, 0xdf, 0x9d, 0x6c, 0x60, 0x80, 0xb1, 0x7f, 0x43, 0xf3, 0xd0,
- 0x72, 0xb1, 0x7b, 0xa1, 0xf8, 0xb1, 0x7b, 0x66, 0x25, 0x8a, 0xc3, 0xed,
- 0x34, 0xc0, 0x44, 0x17, 0xfc, 0xfd, 0x07, 0x39, 0x07, 0x25, 0x8b, 0xff,
- 0xfe, 0x16, 0xfa, 0xce, 0x92, 0x5e, 0xd0, 0xb6, 0xfc, 0xfb, 0x8e, 0xb1,
- 0x7f, 0xed, 0xbf, 0x91, 0x7e, 0x47, 0x9b, 0xac, 0x53, 0xa2, 0xb4, 0x4d,
- 0x77, 0x37, 0x16, 0x2f, 0xba, 0xfb, 0x3e, 0xb1, 0x5f, 0x37, 0x9c, 0x17,
- 0xbf, 0xff, 0x9f, 0xbf, 0x73, 0x6d, 0x67, 0x3a, 0xe6, 0xff, 0x14, 0x7a,
- 0xc5, 0x4a, 0x21, 0xb4, 0x43, 0x7e, 0xf1, 0x4f, 0xb8, 0xb1, 0x6d, 0x96,
- 0x2d, 0x20, 0x37, 0x64, 0x51, 0x7f, 0xff, 0xfd, 0x0e, 0x7f, 0x04, 0x1f,
- 0x3f, 0x9b, 0xe7, 0x3a, 0xe7, 0x70, 0xe3, 0x93, 0xac, 0x5e, 0x66, 0xdd,
- 0x51, 0x58, 0x97, 0xcc, 0x64, 0x9a, 0xb1, 0x7c, 0x79, 0xe6, 0x2c, 0x56,
- 0xe7, 0xe1, 0xa2, 0xa0, 0x12, 0x5f, 0xbe, 0xe7, 0x9d, 0x2c, 0x5f, 0xfe,
- 0x13, 0x6d, 0xac, 0x3f, 0xe7, 0x62, 0x12, 0xc5, 0x39, 0xfa, 0x11, 0x45,
- 0xfe, 0x14, 0x33, 0x80, 0xec, 0x0b, 0x17, 0xf8, 0x13, 0xfc, 0xfb, 0x84,
- 0x58, 0xbf, 0xd9, 0xe6, 0x20, 0x64, 0x7a, 0xc5, 0xff, 0x67, 0x8b, 0x05,
- 0x25, 0xe5, 0x8a, 0xe1, 0xf6, 0x47, 0x1a, 0xdf, 0xda, 0xdb, 0xdc, 0x60,
- 0x2c, 0x5f, 0xf3, 0x16, 0xec, 0x42, 0xcf, 0xac, 0x5f, 0xd9, 0xc0, 0x66,
- 0x0d, 0x62, 0x98, 0xf9, 0x48, 0xe2, 0xa0, 0xbb, 0x66, 0x38, 0x73, 0x1b,
- 0x0e, 0x4d, 0xd7, 0x7b, 0x25, 0xd4, 0x3c, 0xbf, 0x0a, 0x42, 0x20, 0xe1,
- 0xb7, 0xa1, 0x42, 0x22, 0x5e, 0x90, 0x95, 0xbf, 0xb4, 0x13, 0xd8, 0x40,
- 0x58, 0xbf, 0xef, 0x70, 0xb3, 0xa1, 0x67, 0x16, 0x2a, 0x4f, 0xa8, 0x46,
- 0x17, 0xde, 0x2c, 0x08, 0xb1, 0x79, 0xc4, 0x35, 0x8b, 0xff, 0xa7, 0xbf,
- 0xe6, 0xf3, 0xae, 0xe1, 0xc5, 0x8a, 0x35, 0x15, 0x4e, 0x43, 0x1e, 0x48,
- 0x21, 0xdb, 0xff, 0x8b, 0xc6, 0x8a, 0x4b, 0x37, 0x9d, 0x2c, 0x5f, 0x9c,
- 0x2e, 0xc2, 0xdd, 0x62, 0xf6, 0x6c, 0x17, 0x58, 0xa9, 0x3c, 0xf7, 0x2d,
- 0xbf, 0xda, 0xdb, 0xdc, 0x6e, 0xf7, 0x58, 0xbf, 0xfe, 0x3f, 0x4c, 0xd6,
- 0x9f, 0xa7, 0x1c, 0x4d, 0xa5, 0x8a, 0x94, 0xd0, 0x3f, 0x09, 0x46, 0x20,
- 0x11, 0xc5, 0xfd, 0xec, 0x29, 0x0e, 0x39, 0x62, 0xff, 0xfa, 0x73, 0x98,
- 0x5d, 0x78, 0xf1, 0xd2, 0x40, 0x58, 0xac, 0x44, 0x19, 0x18, 0xdf, 0xf8,
- 0x98, 0xe1, 0xb0, 0xe7, 0xbe, 0x2c, 0x5f, 0x3c, 0x4e, 0x1a, 0xc5, 0xfb,
- 0xc4, 0xc0, 0xe2, 0xc5, 0xd3, 0xa8, 0x1e, 0x61, 0xa4, 0x97, 0xff, 0x39,
- 0xf9, 0xd7, 0xef, 0xe2, 0x93, 0xac, 0x54, 0x13, 0x21, 0x01, 0x0f, 0x21,
- 0x19, 0xe2, 0xeb, 0xfb, 0xa6, 0x04, 0x72, 0x89, 0x62, 0xff, 0x73, 0xef,
- 0x1e, 0x26, 0x1a, 0xc5, 0xf3, 0x79, 0xb7, 0x58, 0xbf, 0xe9, 0xe8, 0xda,
- 0xdf, 0xec, 0x11, 0x62, 0xd2, 0xb1, 0x7c, 0xc7, 0xc2, 0x58, 0xa9, 0x36,
- 0x5f, 0x11, 0xbf, 0xcf, 0x3b, 0x96, 0x3e, 0xcb, 0x15, 0x04, 0xd3, 0xfb,
- 0x32, 0x39, 0xbf, 0xc8, 0xfc, 0xe0, 0x10, 0x82, 0xfe, 0x2f, 0x7f, 0x00,
- 0xcb, 0x17, 0xc2, 0x0b, 0xc7, 0x3a, 0xc5, 0x49, 0xeb, 0xb9, 0x6d, 0xff,
- 0x04, 0x11, 0xfd, 0xdc, 0x27, 0xeb, 0x17, 0xec, 0xd8, 0xed, 0xe5, 0x8a,
- 0x73, 0xe7, 0x23, 0xeb, 0xe9, 0x3b, 0x79, 0x62, 0xf8, 0xe2, 0x04, 0x4b,
- 0x15, 0x04, 0x77, 0x64, 0x21, 0xf8, 0x40, 0x22, 0x2b, 0xf8, 0x8b, 0x00,
- 0x67, 0x6b, 0x17, 0xde, 0xce, 0xe2, 0x58, 0xac, 0x3d, 0x40, 0x85, 0xf7,
- 0x6a, 0x56, 0x2f, 0x44, 0xe6, 0xac, 0x54, 0x46, 0xdb, 0x82, 0xf7, 0x47,
- 0x0d, 0x62, 0xfd, 0x27, 0xdb, 0x03, 0x58, 0xbf, 0x60, 0xf9, 0xf9, 0x58,
- 0xbc, 0x79, 0xd2, 0xc5, 0xc3, 0x0d, 0x62, 0xff, 0xff, 0xff, 0x37, 0xbd,
- 0x9f, 0xe3, 0x41, 0xcb, 0xd0, 0xcd, 0x67, 0x33, 0xed, 0xb1, 0x4c, 0x16,
- 0x2f, 0x7a, 0x62, 0x58, 0xa9, 0x4f, 0x23, 0x16, 0x77, 0x22, 0x71, 0xbd,
- 0x15, 0x00, 0xa0, 0x87, 0x78, 0x32, 0x64, 0x23, 0x2f, 0xfd, 0x17, 0x7e,
- 0x71, 0xe1, 0x61, 0xd6, 0x2f, 0xe1, 0x47, 0x6f, 0xf7, 0x0b, 0xac, 0x5f,
- 0x77, 0x09, 0xfa, 0xc5, 0xfe, 0xe0, 0xff, 0x9b, 0x8a, 0x3d, 0x62, 0xd9,
- 0xc3, 0xdd, 0x11, 0x25, 0xd3, 0xd1, 0x62, 0xbe, 0x78, 0x04, 0x4f, 0x7e,
- 0x71, 0x96, 0x09, 0x62, 0xff, 0xfa, 0x7a, 0xe0, 0xff, 0x9a, 0xee, 0x4b,
- 0xdc, 0x58, 0xaf, 0x9f, 0xc8, 0x89, 0xef, 0xf4, 0x4d, 0x8f, 0x03, 0x0e,
- 0xb1, 0x43, 0x47, 0x8e, 0xf0, 0x9a, 0x72, 0x2b, 0xfd, 0xdc, 0x22, 0x83,
- 0x6b, 0x65, 0x8b, 0x98, 0x96, 0x2f, 0xed, 0x38, 0xdf, 0x3b, 0x58, 0xbe,
- 0x87, 0x9f, 0x65, 0x8a, 0x94, 0x50, 0x6c, 0x71, 0x82, 0xcc, 0x5d, 0x7f,
- 0xff, 0xa4, 0xe6, 0x9a, 0xdd, 0xfe, 0x5f, 0xdc, 0x72, 0xee, 0x0b, 0x17,
- 0xff, 0xde, 0x9d, 0xdf, 0xce, 0x7e, 0xbc, 0x61, 0x8d, 0x62, 0xff, 0xf0,
- 0x0e, 0xdd, 0xfb, 0x58, 0xff, 0x91, 0xac, 0x53, 0xa2, 0x7b, 0x8a, 0x75,
- 0x2a, 0xfe, 0x72, 0x3c, 0x57, 0x86, 0xaf, 0xce, 0xda, 0x30, 0x2b, 0xa1,
- 0xe5, 0x8b, 0xe7, 0x3b, 0x41, 0x62, 0xfe, 0x90, 0x1e, 0x78, 0x4b, 0x17,
- 0xf6, 0x6d, 0x85, 0x90, 0x58, 0xba, 0x62, 0x58, 0xbf, 0xff, 0xa4, 0x27,
- 0x27, 0x4e, 0x67, 0xfa, 0xc5, 0x3a, 0xda, 0x56, 0x2a, 0x53, 0x0e, 0x80,
- 0xc3, 0x91, 0x68, 0xb4, 0x05, 0xa4, 0x31, 0x7f, 0xff, 0x37, 0xe3, 0x3e,
- 0xf2, 0x76, 0x1f, 0x1b, 0x66, 0xd2, 0xc5, 0xff, 0xdc, 0xfe, 0x04, 0x7f,
- 0x3c, 0x38, 0x25, 0x8b, 0xf8, 0xfe, 0x13, 0x6d, 0x2b, 0x16, 0x7e, 0xa8,
- 0xd4, 0xed, 0x78, 0xc4, 0x7b, 0xf9, 0xfd, 0x09, 0xf3, 0xac, 0x5a, 0x0b,
- 0x17, 0x85, 0xde, 0x2c, 0x5f, 0xed, 0x38, 0xb6, 0x07, 0x20, 0xb1, 0x7f,
- 0x67, 0x60, 0xcf, 0x71, 0x62, 0xfe, 0x14, 0x97, 0x70, 0xe2, 0xc7, 0xcd,
- 0x7d, 0xfc, 0x71, 0x77, 0x0e, 0x47, 0xac, 0x5f, 0x4f, 0xda, 0x3d, 0x62,
- 0xd0, 0x93, 0xd9, 0x23, 0x4b, 0xef, 0xff, 0x34, 0xb1, 0x7f, 0xf3, 0x6b,
- 0x6f, 0xbe, 0xb0, 0xbb, 0xdd, 0x62, 0xe9, 0xd9, 0x62, 0xa0, 0x7b, 0xee,
- 0x8f, 0x7f, 0xf0, 0xe7, 0x92, 0xfd, 0xfb, 0xd2, 0x75, 0x8b, 0xfa, 0x43,
- 0x88, 0xa4, 0x6b, 0x17, 0xff, 0x16, 0x71, 0xc1, 0xd6, 0x76, 0x9e, 0x2c,
- 0x56, 0xca, 0xa7, 0x86, 0x3d, 0xbb, 0x2f, 0x70, 0x98, 0x72, 0x68, 0xa1,
- 0x05, 0xa2, 0x1f, 0x22, 0xf4, 0x2f, 0xbf, 0x6f, 0xf9, 0x23, 0x56, 0x2f,
- 0xf9, 0xbd, 0xf9, 0x0d, 0xe7, 0xcb, 0x15, 0x2a, 0xe8, 0xb2, 0x55, 0x83,
- 0x42, 0x3c, 0x45, 0x57, 0xc7, 0x6e, 0xfc, 0xb1, 0x7f, 0xf6, 0xd3, 0xee,
- 0xa6, 0x6e, 0x60, 0x43, 0x38, 0xb1, 0x7f, 0xf3, 0x47, 0xe1, 0x30, 0xdb,
- 0x3b, 0xf2, 0xc5, 0xff, 0x6a, 0x78, 0xda, 0x29, 0x82, 0xc5, 0xd3, 0x05,
- 0x8a, 0xd2, 0x39, 0x7e, 0xa1, 0xd1, 0x18, 0x21, 0xc5, 0xe8, 0x36, 0xcb,
- 0x17, 0xba, 0xec, 0x75, 0x8b, 0xfe, 0x6e, 0xe0, 0xff, 0xfb, 0x47, 0xac,
- 0x5f, 0xcc, 0xfa, 0x29, 0x0d, 0x62, 0xfb, 0x06, 0xc0, 0x58, 0xbf, 0x4e,
- 0xc5, 0x3b, 0x2c, 0x51, 0xcf, 0x2c, 0x88, 0xad, 0xe5, 0x8b, 0xfc, 0xdb,
- 0x16, 0x7b, 0x00, 0xb1, 0x7f, 0xe3, 0x79, 0xcc, 0xfb, 0xf0, 0x5b, 0x2c,
- 0x50, 0xd1, 0x0f, 0x82, 0x42, 0x33, 0xbf, 0xdf, 0x6d, 0xbd, 0xec, 0x0d,
- 0x62, 0xa3, 0x65, 0x69, 0x79, 0x18, 0x4f, 0x68, 0x2e, 0x3d, 0xa2, 0x1f,
- 0x9e, 0xb3, 0xc1, 0x42, 0xa0, 0x45, 0xf7, 0xd3, 0x14, 0xec, 0xb1, 0x7c,
- 0x36, 0x20, 0x2c, 0x5f, 0xf8, 0x98, 0x7f, 0x9e, 0x9f, 0x62, 0x58, 0xbe,
- 0x6e, 0x75, 0xfa, 0xc5, 0xff, 0xe8, 0x61, 0x78, 0x5f, 0x70, 0x81, 0x26,
- 0x3d, 0x62, 0xff, 0xff, 0xf6, 0x1f, 0x34, 0x00, 0x0b, 0x9f, 0x7f, 0x43,
- 0x3e, 0xc0, 0x71, 0xca, 0xc5, 0xa3, 0xd6, 0x2f, 0xbe, 0xec, 0x05, 0x8a,
- 0x93, 0x6f, 0xc1, 0x5b, 0xbe, 0x25, 0x8b, 0xff, 0xfd, 0x9b, 0xf5, 0x21,
- 0x04, 0xeb, 0x9d, 0xc3, 0x04, 0x40, 0xe2, 0xc5, 0xd0, 0xe2, 0xc5, 0x6c,
- 0x88, 0x16, 0x69, 0xa9, 0x45, 0xe0, 0xa1, 0x33, 0x7f, 0xfb, 0x6c, 0xef,
- 0xdc, 0x72, 0x90, 0x31, 0xd6, 0x2f, 0xf7, 0x65, 0x83, 0xfb, 0x06, 0xb1,
- 0x58, 0x88, 0x06, 0x4b, 0xad, 0x95, 0xa6, 0xc0, 0x90, 0x64, 0x46, 0x9f,
- 0xf6, 0x4b, 0xf5, 0x16, 0x85, 0x71, 0x43, 0x73, 0x90, 0xa7, 0xbe, 0xf4,
- 0x25, 0xd6, 0x2f, 0xf0, 0xf6, 0xc0, 0xf3, 0xec, 0xb1, 0x78, 0x52, 0x05,
- 0x8b, 0xf8, 0xb3, 0xb8, 0x47, 0xc4, 0xb1, 0x5a, 0x3d, 0x0f, 0x8e, 0xd6,
- 0x22, 0x9d, 0xa1, 0x0b, 0x7f, 0x6d, 0x14, 0x23, 0x6d, 0x6c, 0xb1, 0x7c,
- 0x45, 0x9e, 0x58, 0xbc, 0x2d, 0x6c, 0xb1, 0x7e, 0x78, 0xfd, 0x69, 0xd6,
- 0x2f, 0x7d, 0xce, 0xb1, 0x51, 0xba, 0x30, 0x24, 0xe3, 0x08, 0x7e, 0x3e,
- 0x22, 0xbb, 0xfe, 0xc8, 0xa0, 0xda, 0xdb, 0xe2, 0x58, 0xbe, 0x8e, 0x62,
- 0x02, 0xc5, 0xb6, 0x19, 0xf0, 0x98, 0x79, 0x79, 0x85, 0xa5, 0x8b, 0xe8,
- 0xf9, 0xe1, 0x2c, 0x5f, 0xfb, 0xec, 0x7f, 0x7e, 0x7c, 0x23, 0xac, 0x56,
- 0x1f, 0x2c, 0x44, 0xb7, 0xff, 0x66, 0x1a, 0x79, 0x7d, 0x69, 0xc3, 0x58,
- 0xbc, 0xcd, 0xa5, 0x8b, 0xfe, 0xf7, 0xc4, 0xd0, 0x0a, 0x81, 0xd6, 0x2f,
- 0xf9, 0xe0, 0xff, 0x11, 0xce, 0xeb, 0x17, 0x67, 0x96, 0x2a, 0x53, 0xbd,
- 0x19, 0x56, 0x42, 0x0b, 0x44, 0x5f, 0x45, 0x21, 0xcf, 0x1f, 0x47, 0x1c,
- 0xdc, 0xc1, 0x16, 0x2f, 0x7f, 0x0e, 0xb1, 0x7f, 0xfa, 0x63, 0xcf, 0x23,
- 0x2c, 0xf7, 0x98, 0x96, 0x28, 0x91, 0x03, 0xe1, 0x90, 0x83, 0xb7, 0xbe,
- 0xf1, 0x81, 0x47, 0x5d, 0xc5, 0x1a, 0x39, 0xc6, 0xc4, 0xe1, 0x6e, 0x14,
- 0xa1, 0x6a, 0x5b, 0x32, 0x8a, 0x36, 0x8c, 0xbe, 0x06, 0x83, 0x85, 0x26,
- 0x4e, 0xf1, 0x1b, 0x1e, 0xf6, 0xf1, 0xc0, 0x77, 0x1f, 0x2b, 0xc7, 0x25,
- 0x14, 0x74, 0x1a, 0x94, 0xba, 0x78, 0x41, 0x7e, 0x70, 0xe5, 0xa3, 0x67,
- 0x04, 0x65, 0x21, 0x73, 0x92, 0x97, 0x9f, 0xc9, 0x72, 0x7e, 0x97, 0xb4,
- 0x28, 0x48, 0x74, 0x86, 0x4c, 0x74, 0x39, 0x8c, 0x94, 0xd6, 0x12, 0x1f,
- 0x17, 0xa3, 0x5c, 0x74, 0x6e, 0xb1, 0x70, 0x53, 0xb5, 0x8b, 0xef, 0x47,
- 0x67, 0xd6, 0x2c, 0x4b, 0x14, 0x15, 0x36, 0xf0, 0x26, 0xb0, 0x58, 0xb1,
- 0x74, 0x6e, 0x14, 0x58, 0xa8, 0xd8, 0xdc, 0x05, 0x82, 0xf7, 0x05, 0xb8,
- 0xe5, 0x8b, 0xec, 0x1b, 0x1d, 0x62, 0xa3, 0x73, 0xc3, 0xd1, 0x0d, 0xef,
+ 0x6f, 0xac, 0x5f, 0xec, 0xd4, 0xf0, 0xe5, 0xb2, 0xc5, 0xcd, 0x03, 0x13,
+ 0x65, 0xc4, 0x9d, 0xd1, 0x59, 0x6b, 0x89, 0x37, 0x3c, 0x4b, 0x16, 0x39,
+ 0xcf, 0xbb, 0xea, 0xd5, 0x2a, 0xb1, 0xf0, 0x9d, 0xcf, 0xc5, 0x28, 0xe6,
+ 0xfe, 0xd0, 0xb7, 0xfb, 0xf1, 0x62, 0xf8, 0x26, 0x28, 0x2c, 0x5f, 0xf7,
+ 0xa7, 0xa0, 0x37, 0xfe, 0xeb, 0x16, 0xfa, 0xc5, 0xef, 0xe7, 0x72, 0xc5,
+ 0x61, 0xf6, 0x6e, 0x75, 0x10, 0x95, 0xed, 0x36, 0xeb, 0x17, 0xe7, 0xdf,
+ 0xf3, 0xe5, 0x8b, 0xa7, 0x16, 0x2b, 0x63, 0x7f, 0xb9, 0x4d, 0xf4, 0xec,
+ 0x42, 0x58, 0xad, 0x1e, 0x37, 0xc8, 0xef, 0xb8, 0xe7, 0x95, 0x8b, 0xff,
+ 0x4e, 0x16, 0xd8, 0x4d, 0xd7, 0x16, 0x2f, 0xc5, 0x9e, 0x9d, 0x2c, 0x5e,
+ 0x08, 0x20, 0x92, 0x2f, 0xcc, 0x6f, 0xdf, 0xc9, 0x11, 0x86, 0x86, 0xa5,
+ 0x10, 0x8e, 0x91, 0x7c, 0x7e, 0x4f, 0x96, 0x2f, 0x76, 0x93, 0xac, 0x5e,
+ 0xf3, 0x84, 0xb1, 0x7b, 0x8d, 0xa5, 0x8a, 0xe8, 0xdd, 0xf8, 0x7a, 0xff,
+ 0xff, 0xef, 0x4c, 0x1f, 0xe2, 0x39, 0xda, 0x1a, 0x9f, 0xb7, 0x0b, 0x00,
+ 0xb1, 0x74, 0x8d, 0x62, 0xff, 0x6b, 0x53, 0xb0, 0xf0, 0x96, 0x29, 0xd1,
+ 0x79, 0xf7, 0x16, 0x17, 0xa9, 0x4e, 0x27, 0x08, 0xdd, 0x69, 0xa1, 0xbd,
+ 0x7f, 0xf8, 0x38, 0x18, 0x3c, 0xfe, 0xef, 0xcc, 0x1a, 0xc5, 0xec, 0xc8,
+ 0x96, 0x2b, 0x63, 0xeb, 0x02, 0x75, 0xf7, 0x30, 0xbc, 0xb1, 0x58, 0x78,
+ 0xac, 0x47, 0x7e, 0x0f, 0x8f, 0xf1, 0x2c, 0x5e, 0x1c, 0x9d, 0x62, 0xef,
+ 0x9a, 0xb1, 0x6e, 0x18, 0xb9, 0xe4, 0x33, 0x0c, 0x85, 0x1f, 0x44, 0x51,
+ 0x11, 0x6a, 0x18, 0x5f, 0x8e, 0xa8, 0xa1, 0xdf, 0xc2, 0x01, 0x15, 0x76,
+ 0x1d, 0xbd, 0x1d, 0x9d, 0x2c, 0x5a, 0x03, 0x5e, 0x5b, 0xc9, 0xd8, 0x17,
+ 0x85, 0xcd, 0x46, 0xcb, 0xd9, 0xe2, 0x9e, 0x8b, 0xbf, 0xa4, 0xf3, 0xf9,
+ 0x02, 0xc5, 0xe9, 0xd8, 0x4b, 0x16, 0xef, 0xf0, 0xf2, 0xfe, 0x5b, 0x7f,
+ 0xf3, 0xfa, 0x75, 0x85, 0xe6, 0x62, 0x58, 0xa8, 0x33, 0x80, 0xdc, 0x82,
+ 0x23, 0x3d, 0x47, 0xb6, 0x72, 0x8f, 0xcb, 0xb0, 0x29, 0xf1, 0x21, 0x3f,
+ 0x76, 0x2c, 0xbf, 0x86, 0xd0, 0x29, 0xd9, 0x62, 0xfb, 0xef, 0xd7, 0x96,
+ 0x2f, 0xff, 0xe7, 0x9f, 0x7c, 0x4c, 0x72, 0xcf, 0x7d, 0xf6, 0x82, 0xc5,
+ 0xe9, 0xc2, 0xc4, 0x56, 0xc4, 0x5d, 0xf2, 0x4b, 0xfc, 0x26, 0xdb, 0x09,
+ 0xcd, 0x58, 0xbe, 0xdf, 0x53, 0x05, 0x8b, 0xce, 0x7e, 0x2c, 0x5f, 0xbf,
+ 0x3b, 0xe1, 0x2c, 0x5a, 0x56, 0x28, 0x06, 0xe7, 0xb1, 0x45, 0xff, 0x9f,
+ 0x5b, 0xfd, 0xf7, 0xfb, 0x92, 0xc5, 0xff, 0xff, 0xe6, 0x20, 0x7b, 0xf8,
+ 0x7f, 0x73, 0x3b, 0x7d, 0xf7, 0xfb, 0x86, 0x2d, 0x96, 0x2b, 0x64, 0x5e,
+ 0x81, 0x02, 0xa5, 0x30, 0x4c, 0x87, 0x05, 0xff, 0x64, 0x7c, 0x9f, 0xa8,
+ 0x67, 0x96, 0x2a, 0x5b, 0x34, 0x6c, 0x87, 0x7b, 0xd3, 0xaf, 0x75, 0x1a,
+ 0x2f, 0xcf, 0xd8, 0xd0, 0x04, 0x85, 0x1a, 0xd7, 0x09, 0xef, 0xb3, 0x9e,
+ 0x75, 0x8b, 0xfb, 0x39, 0xcc, 0xd6, 0xcb, 0x16, 0xde, 0x07, 0xa2, 0x32,
+ 0x2b, 0xc5, 0x3d, 0x96, 0x2f, 0xfe, 0xd4, 0xef, 0xf2, 0x6f, 0x14, 0x84,
+ 0xb1, 0x77, 0x7e, 0xeb, 0x14, 0xb1, 0x6f, 0xac, 0x54, 0x0b, 0xe7, 0x0c,
+ 0xbf, 0xd1, 0x41, 0xc5, 0xdf, 0xc7, 0x3a, 0xc5, 0xf6, 0x9e, 0x2e, 0x2c,
+ 0x58, 0x06, 0x1f, 0x0e, 0x8f, 0x6b, 0x64, 0x71, 0xe8, 0xe8, 0xa1, 0x01,
+ 0x52, 0x9a, 0xeb, 0x46, 0x51, 0x7a, 0x26, 0xd9, 0x62, 0xf7, 0x05, 0x1e,
+ 0xb1, 0x58, 0x78, 0x1e, 0x1f, 0xbe, 0x16, 0xc2, 0xd9, 0x62, 0xfd, 0x02,
+ 0x79, 0xe9, 0x62, 0xd3, 0xa3, 0xce, 0x22, 0x6a, 0x97, 0xdc, 0xd6, 0xda,
+ 0x50, 0x44, 0x27, 0x29, 0x07, 0x2f, 0x0f, 0x29, 0x4d, 0x06, 0xce, 0x55,
+ 0xef, 0x2e, 0xe7, 0xa9, 0xc5, 0x57, 0x3e, 0x8a, 0x55, 0x3e, 0xa7, 0xaf,
+ 0x0f, 0x1f, 0xdf, 0xe7, 0x68, 0x1a, 0x51, 0xa0, 0x23, 0xea, 0x2a, 0x69,
+ 0xc7, 0x23, 0xa7, 0xf5, 0x67, 0x06, 0x28, 0x74, 0xf6, 0x29, 0x8e, 0x8d,
+ 0xec, 0x36, 0x8e, 0xe6, 0xfb, 0xf3, 0xc5, 0x07, 0x25, 0x8b, 0xbb, 0xc7,
+ 0x58, 0xbf, 0x8e, 0x23, 0x4b, 0x00, 0xb1, 0x7b, 0x4f, 0xba, 0xc5, 0xff,
+ 0xc6, 0xb1, 0x9c, 0x1f, 0xf1, 0xc8, 0xd5, 0x8b, 0xc3, 0x60, 0x96, 0x28,
+ 0xc3, 0xe5, 0x74, 0x7a, 0xc4, 0x6a, 0x6e, 0x5f, 0xf8, 0x41, 0xdf, 0xf4,
+ 0x5e, 0xee, 0xe4, 0xc4, 0x2d, 0x2c, 0x5f, 0xe1, 0xc9, 0x1e, 0x47, 0x2b,
+ 0x15, 0x27, 0xe4, 0xc8, 0x17, 0xfd, 0xf9, 0xdb, 0x53, 0x06, 0xd2, 0xc5,
+ 0xff, 0xef, 0xcf, 0xcb, 0x0d, 0x1e, 0x14, 0xc7, 0xac, 0x5f, 0x88, 0xd0,
+ 0xe4, 0x0b, 0x17, 0xfc, 0x0d, 0x48, 0xbc, 0x4f, 0xd9, 0x62, 0xff, 0x9b,
+ 0xaf, 0x7e, 0x77, 0xc8, 0x96, 0x2b, 0x0f, 0xdc, 0x8e, 0xef, 0xce, 0x3f,
+ 0xb9, 0xab, 0x17, 0x83, 0x62, 0x58, 0xa1, 0xa6, 0xa7, 0x89, 0x85, 0x0a,
+ 0x1f, 0x10, 0x77, 0x14, 0xdf, 0x8b, 0x61, 0xfe, 0x56, 0x2f, 0xd2, 0x4e,
+ 0x7c, 0x58, 0xbe, 0x0b, 0xd9, 0x1e, 0xb1, 0x7f, 0x31, 0xc3, 0x1b, 0x41,
+ 0x62, 0xa5, 0x14, 0xbb, 0x14, 0xf4, 0x4d, 0xf2, 0x7b, 0xff, 0xf1, 0x30,
+ 0x5a, 0x79, 0xf8, 0x7e, 0x7f, 0xcf, 0x65, 0x8b, 0xff, 0x3f, 0xe4, 0x7f,
+ 0x14, 0xf5, 0xc5, 0x8b, 0xff, 0xbe, 0x13, 0x16, 0xc5, 0x81, 0xc9, 0xd6,
+ 0x2f, 0x11, 0x62, 0xc5, 0x62, 0x28, 0x74, 0x80, 0xc8, 0xd7, 0x86, 0x68,
+ 0x16, 0x2f, 0xb5, 0xa6, 0xf2, 0xc5, 0xf3, 0x9a, 0x70, 0x96, 0x2f, 0xd1,
+ 0xcf, 0xac, 0x35, 0x62, 0x8e, 0x7e, 0x9f, 0x23, 0xe1, 0x2d, 0xe3, 0x3b,
+ 0xb7, 0x58, 0xbb, 0x3c, 0xb1, 0x5b, 0x1b, 0xaf, 0x91, 0xdf, 0xf8, 0xe3,
+ 0x92, 0xce, 0xc5, 0x9c, 0x58, 0xbd, 0xf2, 0x3a, 0xc5, 0xfe, 0x01, 0xad,
+ 0x87, 0x9d, 0xd6, 0x28, 0xc4, 0xeb, 0xe6, 0x12, 0x78, 0xd2, 0xe4, 0x4c,
+ 0x7e, 0x10, 0xed, 0xff, 0xd1, 0x36, 0xff, 0x98, 0x78, 0xb0, 0xeb, 0x17,
+ 0xf6, 0xb0, 0x89, 0xb6, 0x58, 0xbf, 0xf0, 0x72, 0x7c, 0xd1, 0xd8, 0x8d,
+ 0x58, 0xad, 0xd1, 0x66, 0xe8, 0xde, 0x2d, 0xbf, 0xf0, 0x5d, 0x43, 0x86,
+ 0x67, 0xf0, 0x96, 0x2f, 0xfa, 0x7a, 0xe6, 0x9f, 0xb6, 0x0d, 0x62, 0xff,
+ 0xf8, 0xb3, 0x9e, 0x36, 0x4a, 0x19, 0xf7, 0x3a, 0xc5, 0x44, 0x88, 0xbe,
+ 0xc7, 0x95, 0x28, 0xf3, 0xc8, 0x66, 0xdf, 0x9f, 0x52, 0x73, 0xac, 0x5b,
+ 0xcb, 0x17, 0xf6, 0x6c, 0x69, 0xa2, 0x25, 0x8b, 0xfc, 0x2e, 0x8b, 0x3d,
+ 0x80, 0x58, 0xbf, 0xfb, 0xa8, 0x70, 0xcc, 0x22, 0xc7, 0x02, 0xc5, 0xff,
+ 0xe2, 0x17, 0x5d, 0x78, 0x45, 0xec, 0xeb, 0xcb, 0x14, 0x74, 0x49, 0xf6,
+ 0x45, 0xbf, 0xf0, 0xba, 0xe4, 0x45, 0x9e, 0xc0, 0x2c, 0x5f, 0xcd, 0xa1,
+ 0x4f, 0x50, 0x58, 0xa3, 0x13, 0x9f, 0x91, 0x2c, 0x31, 0x78, 0x63, 0xe8,
+ 0x95, 0x90, 0x6f, 0xfe, 0x91, 0x9f, 0x37, 0x9e, 0x7f, 0x0e, 0xb1, 0x7e,
+ 0x6c, 0x1b, 0xf6, 0x58, 0xbd, 0xe9, 0x3a, 0xc5, 0xe2, 0x79, 0x58, 0xbc,
+ 0xf8, 0x12, 0xc5, 0x69, 0x18, 0x67, 0x45, 0xe1, 0x4f, 0x61, 0xd0, 0xc6,
+ 0xef, 0x3f, 0xc4, 0xb1, 0x7e, 0x26, 0xf3, 0x1d, 0x62, 0xfb, 0xcf, 0xf1,
+ 0x2c, 0x5f, 0xd9, 0xae, 0xa1, 0xe9, 0x58, 0xb4, 0x7f, 0x7d, 0x4f, 0x48,
+ 0x32, 0x3b, 0xf0, 0x59, 0xbc, 0x81, 0x62, 0xf6, 0x60, 0xd6, 0x2f, 0xb7,
+ 0xfe, 0x69, 0x62, 0xa5, 0x13, 0xce, 0x68, 0x02, 0xae, 0xe1, 0xca, 0x31,
+ 0x9c, 0xe1, 0x1b, 0x94, 0x4c, 0x3c, 0x21, 0x0a, 0x71, 0x90, 0x64, 0x71,
+ 0xaf, 0x0f, 0x68, 0x8f, 0xb5, 0x0f, 0x9f, 0xc7, 0xba, 0xd1, 0x87, 0x14,
+ 0x64, 0x7c, 0x26, 0xf4, 0x78, 0xe2, 0x8c, 0x77, 0xb2, 0x68, 0x63, 0xbd,
+ 0xd1, 0x8b, 0xda, 0x32, 0x37, 0x9f, 0x70, 0x7b, 0xef, 0x27, 0x36, 0xfb,
+ 0xd9, 0xc6, 0x58, 0xd2, 0x5d, 0xd4, 0x6d, 0x2d, 0x1b, 0xbe, 0xe5, 0xc6,
+ 0xf7, 0xc9, 0x5d, 0xbd, 0xf5, 0x94, 0xf3, 0x1a, 0xa5, 0x75, 0xc6, 0xb9,
+ 0x45, 0x93, 0x7c, 0x2e, 0x3b, 0x56, 0xe6, 0x10, 0xb4, 0xf1, 0xc3, 0xbc,
+ 0x43, 0x3c, 0xc7, 0x87, 0xe9, 0xb4, 0xf6, 0x9d, 0xef, 0x1e, 0xcf, 0xab,
+ 0x5a, 0x74, 0xf6, 0xd2, 0x72, 0x3e, 0x73, 0x02, 0x2b, 0x70, 0x0b, 0xab,
+ 0xcb, 0x77, 0x3d, 0xaf, 0x51, 0xfe, 0x20, 0x6f, 0x9a, 0xf9, 0x21, 0x01,
+ 0x6b, 0x93, 0xfb, 0xf9, 0x6d, 0xc5, 0x7e, 0xc7, 0x3c, 0xcc, 0x90, 0x57,
+ 0xd8, 0x8c, 0xb3, 0x15, 0x6d, 0xf5, 0xda, 0x99, 0x3a, 0x15, 0x38, 0x8a,
+ 0x3a, 0xd0, 0x04, 0x07, 0x7d, 0x43, 0xbd, 0xd5, 0x81, 0xc5, 0x46, 0x4f,
+ 0xbb, 0xad, 0xc3, 0x7d, 0xce, 0xfe, 0xf7, 0x5e, 0xc5, 0x8b, 0xf8, 0xe3,
+ 0x9e, 0x07, 0xc5, 0x8a, 0x93, 0xce, 0x71, 0xeb, 0xba, 0x09, 0x62, 0xf1,
+ 0xf3, 0xcb, 0x17, 0xf9, 0x8f, 0x3e, 0x7e, 0x3a, 0xc5, 0xfb, 0x34, 0x1f,
+ 0xb8, 0xb1, 0x77, 0xe5, 0x62, 0xd1, 0x9f, 0x46, 0x53, 0x10, 0x00, 0x68,
+ 0x87, 0x78, 0x64, 0x19, 0x55, 0xf6, 0xe5, 0x38, 0xb1, 0x7e, 0xd6, 0xec,
+ 0xdb, 0xaa, 0x4e, 0x32, 0xfe, 0x83, 0x14, 0x1c, 0xeb, 0x16, 0x8c, 0x94,
+ 0x43, 0x61, 0x13, 0x1b, 0xdf, 0xe8, 0xcc, 0xd6, 0xec, 0xdb, 0xaa, 0x4e,
+ 0xb2, 0xff, 0xe8, 0xc6, 0x84, 0x66, 0x6b, 0x76, 0x6d, 0xd5, 0x22, 0x89,
+ 0x53, 0x3f, 0x0e, 0xad, 0xb1, 0xcc, 0x21, 0xee, 0x33, 0x83, 0x63, 0x49,
+ 0xdc, 0xe5, 0xe9, 0x08, 0x91, 0xf1, 0xae, 0x36, 0xfb, 0xbd, 0xd0, 0x23,
+ 0x59, 0xe4, 0x39, 0x7c, 0x6d, 0xdc, 0x8b, 0x7f, 0xfa, 0x30, 0xed, 0x08,
+ 0xcc, 0xd6, 0xec, 0xdb, 0xaa, 0x45, 0xa2, 0xff, 0xdd, 0xef, 0x7b, 0xad,
+ 0x34, 0xc3, 0xdd, 0xcb, 0x17, 0xfd, 0x1a, 0xfe, 0xf1, 0xed, 0x3d, 0x77,
+ 0x2c, 0x5f, 0xff, 0x05, 0xbf, 0x79, 0xde, 0x83, 0xbf, 0xd4, 0x68, 0x61,
+ 0x9f, 0x8e, 0x58, 0xbf, 0xff, 0xf7, 0x77, 0xa3, 0x61, 0x9e, 0x36, 0x27,
+ 0xef, 0xaf, 0xbb, 0xfd, 0x46, 0x86, 0x19, 0xf8, 0xe5, 0x8a, 0xfa, 0x60,
+ 0x61, 0x37, 0xdf, 0xa3, 0xf4, 0xf2, 0x4b, 0x17, 0xd0, 0x8d, 0x83, 0xd9,
+ 0x62, 0xfc, 0x0f, 0x67, 0xdd, 0x62, 0x98, 0xff, 0x7b, 0xf2, 0xa1, 0x15,
+ 0xde, 0x8f, 0x3b, 0xac, 0x5f, 0xf6, 0x10, 0xff, 0x3a, 0x62, 0x58, 0xbc,
+ 0xf1, 0xd1, 0x2c, 0x54, 0x9f, 0xc6, 0x10, 0x7c, 0xde, 0xfd, 0xbf, 0xf0,
+ 0xd7, 0x58, 0xbf, 0x0c, 0x46, 0xfc, 0x4b, 0x17, 0x99, 0xb7, 0x54, 0x86,
+ 0xe5, 0xfb, 0xa8, 0x8a, 0x46, 0xb1, 0x43, 0x3f, 0xfd, 0xca, 0xd8, 0xaa,
+ 0xfc, 0x3f, 0xce, 0x69, 0x62, 0xff, 0x4e, 0xd1, 0x14, 0x83, 0x8b, 0x15,
+ 0xba, 0x66, 0xba, 0x85, 0x49, 0x17, 0xf0, 0xa2, 0xff, 0x69, 0xfb, 0xfd,
+ 0xff, 0x21, 0x2c, 0x5e, 0x14, 0x70, 0x4b, 0x17, 0xda, 0x14, 0x81, 0x62,
+ 0x9d, 0x10, 0x11, 0x1d, 0x86, 0x45, 0x7d, 0xf9, 0xeb, 0x8b, 0x17, 0xff,
+ 0xff, 0x8b, 0x39, 0xc1, 0xce, 0x6b, 0x76, 0x6d, 0xe3, 0x20, 0xfe, 0x9f,
+ 0x71, 0x52, 0x87, 0x95, 0xc4, 0x56, 0x76, 0x24, 0xa9, 0x4c, 0x09, 0xe1,
+ 0xbb, 0x7f, 0x34, 0x64, 0x7b, 0x10, 0x16, 0x2f, 0xdb, 0x07, 0xf9, 0x09,
+ 0x62, 0xbe, 0x88, 0x62, 0x27, 0x11, 0x9d, 0xfd, 0xc8, 0xc0, 0xb9, 0x1e,
+ 0x1a, 0xc5, 0xf9, 0xf6, 0xfb, 0xc7, 0x2c, 0x5f, 0xb3, 0x8d, 0xa8, 0x2c,
+ 0x54, 0x79, 0xea, 0x68, 0xb2, 0xfd, 0xdd, 0x19, 0xae, 0xfc, 0x25, 0x8b,
+ 0xf6, 0x6f, 0xc0, 0xf8, 0xb1, 0x7d, 0x3e, 0x8e, 0x35, 0x62, 0xb0, 0xf4,
+ 0xb4, 0x57, 0x7c, 0x32, 0xc0, 0x2c, 0x5f, 0x48, 0x47, 0x1a, 0xc5, 0xf6,
+ 0xff, 0x90, 0x96, 0x2f, 0x7e, 0x4d, 0x58, 0xac, 0x44, 0x4e, 0x88, 0xbb,
+ 0xf2, 0x40, 0xc9, 0x6f, 0x34, 0x78, 0x96, 0x2f, 0xda, 0xdd, 0x9b, 0x75,
+ 0x48, 0xbe, 0x5f, 0xc2, 0xdf, 0x4f, 0x24, 0xb1, 0x79, 0xa1, 0x19, 0xb2,
+ 0x21, 0x70, 0x83, 0xe6, 0xf6, 0xc5, 0x8b, 0xdf, 0x6f, 0x2c, 0x57, 0x0d,
+ 0x70, 0x62, 0x37, 0xf8, 0x3d, 0xfe, 0xe3, 0x17, 0x4b, 0x15, 0xe3, 0xda,
+ 0x11, 0x15, 0xf0, 0xbb, 0xfe, 0xd2, 0xb1, 0x7e, 0x79, 0x08, 0x51, 0xeb,
+ 0x15, 0x87, 0xac, 0x45, 0x57, 0xf1, 0x7b, 0x3d, 0x3a, 0x58, 0xbf, 0x3f,
+ 0x5d, 0xda, 0x09, 0x62, 0xa4, 0xf6, 0xc3, 0x2d, 0xbf, 0xda, 0xd3, 0xf8,
+ 0x19, 0xc5, 0x8b, 0xfd, 0x27, 0x98, 0xc0, 0x82, 0x09, 0x62, 0x9c, 0xfb,
+ 0xbb, 0x8d, 0x2a, 0x53, 0xa7, 0xc7, 0x87, 0x7b, 0x68, 0x48, 0x5f, 0xb9,
+ 0x21, 0xc5, 0xc5, 0x8b, 0xfa, 0x5e, 0x3f, 0x3a, 0x82, 0xc5, 0xfb, 0x46,
+ 0xfc, 0x5c, 0x58, 0xa8, 0x91, 0x0f, 0xf2, 0xb0, 0xcc, 0x6f, 0x4e, 0xa5,
+ 0x62, 0xb0, 0xf3, 0x9c, 0xca, 0xe6, 0xfa, 0xc5, 0xe0, 0xf9, 0x1c, 0xb1,
+ 0x74, 0x6f, 0xde, 0xac, 0x5f, 0x38, 0x27, 0xa5, 0x8b, 0xe0, 0x0f, 0x92,
+ 0xb1, 0x7c, 0xda, 0xdb, 0x65, 0x8b, 0x61, 0x1e, 0x47, 0x62, 0x3a, 0x82,
+ 0x3b, 0x86, 0x2f, 0xd1, 0x14, 0x79, 0x17, 0x1a, 0xef, 0xf7, 0xe3, 0x37,
+ 0xfb, 0xff, 0xb9, 0x62, 0xf0, 0x24, 0x25, 0x8b, 0xfd, 0x8f, 0xa8, 0x7d,
+ 0xc2, 0x58, 0xbd, 0xb4, 0x86, 0xb1, 0x58, 0x8a, 0xd8, 0xf3, 0xcf, 0x8f,
+ 0x11, 0xa5, 0xfc, 0x66, 0xff, 0x9e, 0xb8, 0xb1, 0x73, 0x86, 0xb1, 0x7b,
+ 0x60, 0xe0, 0xb1, 0x51, 0x1b, 0x86, 0x18, 0xa0, 0xd1, 0x17, 0xdc, 0xd5,
+ 0x77, 0x68, 0x2c, 0x5f, 0xc6, 0x87, 0xc7, 0x6f, 0xac, 0x5e, 0xfb, 0xe9,
+ 0x62, 0x98, 0xf3, 0x44, 0x61, 0x7d, 0xcf, 0xcf, 0xd6, 0x2f, 0xf4, 0xed,
+ 0x25, 0xb6, 0x77, 0x2c, 0x5c, 0xdf, 0x58, 0xa5, 0x8a, 0x58, 0xb7, 0x1c,
+ 0xd7, 0xe8, 0x5f, 0x81, 0x97, 0xc0, 0x73, 0xf1, 0x62, 0xa5, 0x1b, 0xfb,
+ 0x11, 0xc4, 0xcd, 0xe3, 0x3b, 0x46, 0x77, 0xad, 0x8c, 0x77, 0x7d, 0x53,
+ 0x66, 0x34, 0x9d, 0xa1, 0x44, 0x38, 0x55, 0xe4, 0x6c, 0x5b, 0xca, 0x4b,
+ 0xe8, 0xbd, 0xe1, 0x19, 0x1e, 0x4b, 0x14, 0x22, 0x35, 0x0a, 0xa3, 0xc3,
+ 0x1f, 0xf2, 0x9c, 0xca, 0x31, 0x4e, 0x46, 0x1d, 0xe8, 0x7d, 0x8a, 0x19,
+ 0x3d, 0x89, 0xe3, 0x99, 0xc3, 0x8c, 0x02, 0xfb, 0xbc, 0x8d, 0x3b, 0xc7,
+ 0x58, 0xbd, 0x14, 0x8d, 0x62, 0xed, 0xe3, 0x23, 0x63, 0xd0, 0x11, 0x95,
+ 0xff, 0xf8, 0xa7, 0x78, 0xcf, 0x75, 0xbb, 0xf0, 0xb3, 0xb3, 0x2c, 0x5f,
+ 0xfd, 0x0f, 0x3c, 0x51, 0x83, 0x7e, 0xd2, 0x35, 0x8b, 0x8d, 0xd9, 0x62,
+ 0xff, 0xd8, 0xfd, 0xbd, 0x98, 0x5e, 0xe2, 0xc5, 0xc1, 0x46, 0x39, 0xec,
+ 0x84, 0x35, 0x7f, 0xf4, 0x67, 0x32, 0x27, 0xd4, 0xc4, 0xe7, 0x58, 0xa1,
+ 0xa6, 0xf7, 0xd2, 0xe3, 0xc2, 0x90, 0xe6, 0x57, 0xb4, 0xd1, 0x2c, 0x5e,
+ 0xc9, 0x89, 0x62, 0xb6, 0x37, 0x7a, 0x1e, 0xbf, 0xe1, 0xea, 0x7e, 0xc3,
+ 0x81, 0xd6, 0x2f, 0xcf, 0xcc, 0x1c, 0x64, 0x9e, 0xe7, 0x08, 0xaf, 0xda,
+ 0xdd, 0x9b, 0x75, 0x49, 0x56, 0x5f, 0xb3, 0x9f, 0x9e, 0x96, 0x2d, 0x19,
+ 0x87, 0xc1, 0xf3, 0x7b, 0xf7, 0x7a, 0x3d, 0x36, 0xeb, 0x17, 0x30, 0xd6,
+ 0x2f, 0x85, 0xdc, 0x39, 0x58, 0xbf, 0x73, 0xcf, 0xd7, 0x16, 0x2d, 0x1b,
+ 0xac, 0x51, 0xcf, 0xfb, 0xe2, 0xfe, 0x26, 0x8e, 0x2a, 0xbf, 0xde, 0xe4,
+ 0x83, 0x3a, 0xf2, 0xc5, 0xcf, 0xdc, 0xb1, 0x76, 0x69, 0x62, 0xf6, 0x75,
+ 0xe5, 0x8b, 0xe7, 0x3b, 0x76, 0x58, 0xac, 0x45, 0x41, 0xa6, 0xac, 0x34,
+ 0x01, 0x7f, 0x0f, 0x5e, 0x80, 0xb8, 0xb1, 0x7f, 0xcf, 0x19, 0xd8, 0xcc,
+ 0x3b, 0x74, 0xb1, 0x77, 0x70, 0x4b, 0x15, 0xf3, 0xdc, 0x24, 0x0b, 0xfb,
+ 0xf3, 0xd8, 0x43, 0xc5, 0x8b, 0xf7, 0xe2, 0x29, 0x1a, 0xc5, 0xe6, 0xd4,
+ 0x16, 0x29, 0x8f, 0x18, 0x22, 0x9b, 0xf7, 0xa2, 0x29, 0x1a, 0xc5, 0xff,
+ 0xe0, 0x1c, 0x43, 0xcc, 0xf0, 0x0e, 0x2e, 0x96, 0x28, 0x8f, 0xdb, 0xc5,
+ 0x37, 0xfe, 0x7d, 0x1a, 0xdd, 0x40, 0x4d, 0xe5, 0x8b, 0xff, 0xbd, 0xf9,
+ 0xe1, 0x30, 0xbb, 0xf7, 0xd2, 0xc5, 0xe9, 0x86, 0x2c, 0x5f, 0xd3, 0xc8,
+ 0xdb, 0x18, 0xeb, 0x17, 0xf3, 0x8b, 0x72, 0x98, 0x96, 0x2f, 0xfe, 0x17,
+ 0x3e, 0xfe, 0x86, 0x13, 0x8d, 0x62, 0xf7, 0x03, 0x65, 0x8b, 0xef, 0xcb,
+ 0xe9, 0x62, 0xa0, 0xaa, 0xe8, 0x6e, 0xd9, 0x09, 0x83, 0x48, 0x7a, 0x41,
+ 0x89, 0x27, 0x43, 0x9f, 0x32, 0x22, 0xff, 0x22, 0x06, 0x3d, 0x7f, 0xb0,
+ 0xb3, 0xaf, 0x31, 0xd6, 0x2f, 0x4f, 0xf8, 0xb1, 0x46, 0x9e, 0x81, 0x19,
+ 0xdf, 0xff, 0xbf, 0x3d, 0x40, 0x4f, 0x1d, 0x81, 0xfe, 0x5f, 0x4b, 0x16,
+ 0xee, 0x58, 0xb0, 0x4b, 0x15, 0xd1, 0xa8, 0xf0, 0xad, 0xee, 0xe9, 0xf2,
+ 0xc5, 0xfc, 0x5e, 0x29, 0xf7, 0x16, 0x2f, 0xe9, 0x38, 0x72, 0x5b, 0xac,
+ 0x5d, 0x3a, 0x58, 0xac, 0x3f, 0x3d, 0x16, 0xf0, 0xbe, 0xf8, 0xe7, 0x78,
+ 0x96, 0x2f, 0xbf, 0x24, 0x6a, 0xc5, 0x61, 0xe3, 0xc4, 0x49, 0x73, 0x74,
+ 0xb1, 0x7b, 0xae, 0x44, 0xb1, 0x73, 0xf9, 0x62, 0xf0, 0x72, 0x05, 0x8b,
+ 0x47, 0xac, 0x57, 0x48, 0x82, 0xd0, 0xc7, 0x08, 0x3c, 0x2f, 0x1c, 0x3d,
+ 0x7d, 0x11, 0x0b, 0x75, 0x8b, 0xfb, 0x0f, 0x13, 0x36, 0xcb, 0x16, 0xe2,
+ 0xc5, 0xf3, 0xfd, 0xcd, 0x58, 0xa0, 0x1b, 0x5e, 0x09, 0x5c, 0xdd, 0x2c,
+ 0x51, 0x1b, 0x9f, 0x10, 0xdf, 0xff, 0x43, 0xed, 0x03, 0x5b, 0x98, 0x2e,
+ 0x71, 0xd6, 0x29, 0x62, 0xb0, 0xf7, 0x7b, 0x94, 0x6a, 0x53, 0x63, 0x72,
+ 0x56, 0x84, 0xe9, 0x3e, 0xdc, 0x37, 0x58, 0xbf, 0xe2, 0x98, 0x79, 0xce,
+ 0x39, 0x58, 0xbf, 0xc4, 0xf0, 0x8b, 0xf3, 0xb2, 0xc5, 0xe6, 0x6d, 0xd5,
+ 0x22, 0x01, 0x6d, 0x40, 0xf7, 0xf7, 0x35, 0xbe, 0xd6, 0x17, 0x96, 0x2f,
+ 0x87, 0x1b, 0xf7, 0xc8, 0xd1, 0x62, 0xff, 0xfd, 0xfc, 0x3f, 0x9c, 0x45,
+ 0x0c, 0x27, 0xdb, 0x8b, 0x14, 0x34, 0xda, 0xf2, 0x12, 0xfa, 0x29, 0xe1,
+ 0x17, 0x8d, 0x2f, 0x76, 0x6f, 0xac, 0x51, 0x89, 0xf8, 0x46, 0x47, 0x05,
+ 0x29, 0xf7, 0xbf, 0x23, 0x58, 0xbf, 0x71, 0x89, 0xba, 0x58, 0xbf, 0xef,
+ 0x3f, 0x1c, 0x5d, 0xf8, 0xe5, 0x62, 0xec, 0x25, 0x8b, 0x85, 0x12, 0xc5,
+ 0xa5, 0x62, 0xa4, 0xd5, 0x08, 0x66, 0xf6, 0x0d, 0xd6, 0x2a, 0x09, 0x9c,
+ 0xee, 0x75, 0xd0, 0xeb, 0x94, 0x47, 0x9f, 0x69, 0x00, 0xe4, 0x17, 0xf4,
+ 0xeb, 0x69, 0xd6, 0xcb, 0x17, 0xce, 0x79, 0xe2, 0xc5, 0x40, 0xf4, 0x8d,
+ 0x30, 0xbf, 0xda, 0xd8, 0xf2, 0x50, 0xe2, 0xc5, 0x49, 0xec, 0x61, 0x1d,
+ 0xf7, 0xa7, 0xb6, 0xeb, 0x17, 0xff, 0x13, 0xed, 0x98, 0x46, 0xe7, 0x5e,
+ 0x58, 0xbf, 0xfe, 0x3b, 0x90, 0x03, 0xf3, 0x90, 0xa1, 0x9c, 0x58, 0xbf,
+ 0xf9, 0xe4, 0xec, 0x30, 0xfb, 0xa4, 0xa0, 0xb1, 0x7f, 0xff, 0xcf, 0xe2,
+ 0xce, 0xc5, 0x9c, 0xdb, 0x02, 0x8e, 0x17, 0xdf, 0x4b, 0x15, 0x29, 0xb7,
+ 0x0c, 0x9b, 0x11, 0x7e, 0xa0, 0x04, 0x7b, 0xf0, 0x18, 0x04, 0x75, 0x8b,
+ 0x98, 0x6b, 0x17, 0xfd, 0x07, 0xf0, 0x27, 0x3a, 0x82, 0xc5, 0xff, 0x46,
+ 0x73, 0x35, 0xb6, 0xd8, 0x05, 0x8a, 0xd9, 0x12, 0x11, 0x0b, 0xfc, 0xea,
+ 0xff, 0xf7, 0x4c, 0x42, 0x06, 0xa7, 0xee, 0x47, 0x58, 0xbf, 0x9f, 0xb3,
+ 0xfa, 0x29, 0x58, 0xa9, 0x4d, 0x93, 0x21, 0x70, 0xe6, 0x5c, 0x4a, 0xbf,
+ 0x83, 0x8d, 0xb4, 0xf2, 0x75, 0x8b, 0xb9, 0x05, 0x8a, 0x63, 0xcc, 0xe1,
+ 0xa5, 0xff, 0xfd, 0x3b, 0xf9, 0xf5, 0xac, 0x07, 0x3c, 0xdf, 0x61, 0xac,
+ 0x5d, 0xde, 0xfd, 0x62, 0xfd, 0x91, 0x41, 0xa0, 0xb1, 0x7f, 0xef, 0xb1,
+ 0xfd, 0xf9, 0xf0, 0x8e, 0xb1, 0x6c, 0x19, 0xf4, 0xc4, 0x53, 0x7f, 0xf7,
+ 0xdc, 0xe3, 0xcf, 0x3f, 0xf7, 0x75, 0x8b, 0xa7, 0xcb, 0x14, 0x33, 0xdc,
+ 0xee, 0x45, 0xa8, 0xd9, 0xb4, 0x34, 0x98, 0x56, 0xed, 0x0e, 0x78, 0x24,
+ 0x8d, 0xeb, 0x25, 0x6d, 0x9b, 0x0f, 0x1d, 0xc8, 0xba, 0x84, 0x14, 0x79,
+ 0x14, 0x50, 0x93, 0xd3, 0xa9, 0xe1, 0x49, 0xf8, 0xec, 0x5a, 0x5b, 0x41,
+ 0x46, 0x27, 0xc8, 0xe3, 0xbd, 0x1d, 0x68, 0xa1, 0x19, 0xd8, 0x86, 0x39,
+ 0x70, 0x38, 0x43, 0x77, 0x42, 0x12, 0xff, 0xd0, 0x9c, 0x07, 0xf3, 0x0b,
+ 0x75, 0x8b, 0xf4, 0x91, 0x67, 0x96, 0x2f, 0xb5, 0xa7, 0xdd, 0x62, 0xf8,
+ 0xb3, 0x68, 0xcc, 0x44, 0x44, 0x71, 0xf0, 0x64, 0xd7, 0xfb, 0xbd, 0xef,
+ 0x23, 0x7e, 0x83, 0x14, 0x72, 0xc5, 0xf6, 0xff, 0x6d, 0xd6, 0x2f, 0xf0,
+ 0x7c, 0xcd, 0x6f, 0xf9, 0x58, 0xbf, 0xec, 0x8a, 0x0d, 0xad, 0xbe, 0x25,
+ 0x8b, 0xee, 0x85, 0xc9, 0x58, 0xbf, 0xc6, 0xb1, 0x60, 0x4c, 0x05, 0x8b,
+ 0xfc, 0xfd, 0x42, 0x7b, 0x4c, 0x7a, 0xc5, 0xf1, 0xb0, 0xfe, 0x2c, 0x5e,
+ 0xdb, 0xbd, 0xec, 0xb1, 0x78, 0x52, 0x1a, 0xc5, 0xff, 0x3c, 0x1f, 0xe2,
+ 0x39, 0xdd, 0x62, 0xa0, 0x7a, 0xfe, 0x1e, 0xb4, 0x64, 0x6e, 0xa8, 0xd6,
+ 0x35, 0x25, 0x49, 0x28, 0xcd, 0xb0, 0xf0, 0xd2, 0x40, 0x1a, 0x70, 0xe7,
+ 0xb1, 0x20, 0x6f, 0xb7, 0xfa, 0x33, 0xec, 0x7c, 0x91, 0xac, 0x54, 0x62,
+ 0xec, 0x0e, 0xa5, 0x13, 0x05, 0x2a, 0x0a, 0x3a, 0x14, 0x77, 0xed, 0x6e,
+ 0xcd, 0xba, 0xa4, 0xc8, 0x2e, 0x34, 0x6b, 0x16, 0x8c, 0xc3, 0xd0, 0xd1,
+ 0xbd, 0xfe, 0x21, 0x78, 0xb3, 0xb3, 0x2c, 0x5f, 0xfc, 0xde, 0x21, 0x6d,
+ 0xcc, 0x3c, 0xc7, 0xac, 0x5f, 0x7d, 0xb5, 0x19, 0x87, 0xf9, 0xf3, 0x4b,
+ 0xf9, 0xfb, 0x46, 0x72, 0x7a, 0x58, 0xbf, 0xff, 0xc2, 0x1e, 0x46, 0x07,
+ 0x9f, 0x21, 0x34, 0x7e, 0x1b, 0x3c, 0x58, 0xbf, 0xff, 0x6e, 0xfc, 0xc1,
+ 0xe1, 0x48, 0x5e, 0x35, 0xb8, 0xb1, 0x7f, 0xdf, 0x76, 0x06, 0x0b, 0x5b,
+ 0x2c, 0x5f, 0xbe, 0x26, 0x36, 0x33, 0xe8, 0x91, 0xf2, 0xbd, 0xa6, 0x09,
+ 0x9e, 0x8e, 0x1f, 0x35, 0xc4, 0xe7, 0xfd, 0x1b, 0x8d, 0x0d, 0x50, 0x23,
+ 0xc7, 0xb5, 0x7f, 0xa3, 0x33, 0x5b, 0xb3, 0x6e, 0xa9, 0x35, 0xcb, 0xf4,
+ 0x5e, 0x1c, 0x92, 0xc5, 0xfe, 0x2c, 0xdb, 0x5a, 0x70, 0x96, 0x2f, 0xbe,
+ 0xf3, 0x12, 0xc5, 0xfb, 0x03, 0x9d, 0xa3, 0x31, 0x10, 0x3b, 0x94, 0xf7,
+ 0x1a, 0xdf, 0xe8, 0xcc, 0xd6, 0xec, 0xdb, 0xaa, 0x4e, 0x42, 0xfd, 0xad,
+ 0xd9, 0xb7, 0x54, 0x9d, 0x85, 0xf4, 0x74, 0xfb, 0x16, 0x2f, 0xfc, 0xd0,
+ 0x8c, 0xcd, 0x6e, 0xcd, 0xba, 0xa4, 0x8e, 0x2d, 0x19, 0x88, 0xac, 0x73,
+ 0x73, 0x92, 0xdf, 0xf3, 0x3f, 0x3f, 0x90, 0xe4, 0xac, 0x5e, 0x3e, 0x7d,
+ 0x62, 0xff, 0xb3, 0x71, 0x49, 0x75, 0x0e, 0x2c, 0x5f, 0xda, 0xd4, 0xef,
+ 0xf7, 0x58, 0xb8, 0xa3, 0x3e, 0x8b, 0xf6, 0x38, 0x21, 0xde, 0x1d, 0xdf,
+ 0xbb, 0xe4, 0x68, 0x0c, 0xd9, 0x62, 0xff, 0xde, 0xe3, 0x9c, 0x46, 0x96,
+ 0x01, 0x62, 0xf8, 0xa6, 0x07, 0x58, 0xbe, 0x72, 0x03, 0xac, 0x5c, 0xe6,
+ 0xac, 0x54, 0x0d, 0xcf, 0x62, 0x1b, 0xff, 0x46, 0xdd, 0xe9, 0xe7, 0x50,
+ 0xc7, 0xec, 0xb1, 0x68, 0x2c, 0x5f, 0xb5, 0xbb, 0x36, 0xea, 0x92, 0x54,
+ 0xbf, 0xed, 0xfe, 0xf1, 0x7e, 0x76, 0xc5, 0x8b, 0xff, 0xdf, 0x9d, 0xa7,
+ 0xef, 0xd9, 0x87, 0xf7, 0x58, 0x8c, 0x37, 0x97, 0xfe, 0x73, 0x96, 0x02,
+ 0x22, 0x60, 0x96, 0x2e, 0x84, 0x66, 0x26, 0x23, 0x13, 0x9f, 0x97, 0xeb,
+ 0xa4, 0xd8, 0xda, 0x32, 0x3b, 0xff, 0x33, 0xfa, 0x02, 0x1b, 0x10, 0x16,
+ 0x2e, 0xf8, 0x96, 0x2f, 0xfe, 0xe3, 0x74, 0x79, 0xff, 0xb1, 0xfb, 0x2c,
+ 0x5f, 0xfe, 0x98, 0x7e, 0x5b, 0xc2, 0x2f, 0x38, 0xd6, 0x2d, 0x19, 0xde,
+ 0xab, 0xb1, 0x93, 0x51, 0xa0, 0x62, 0xdf, 0x44, 0x67, 0x8e, 0xbb, 0xe5,
+ 0x5c, 0x3e, 0xf0, 0xc0, 0x91, 0xef, 0xff, 0xfe, 0x6f, 0x60, 0x26, 0x11,
+ 0x81, 0x9f, 0x07, 0x30, 0x91, 0xb3, 0x1a, 0xb1, 0x5b, 0x3b, 0xc6, 0x88,
+ 0x56, 0x3d, 0xa3, 0x8f, 0x8b, 0x23, 0xb2, 0xde, 0x1b, 0x5d, 0x42, 0x81,
+ 0xeb, 0x9d, 0xf3, 0xc2, 0xa9, 0xa5, 0x55, 0x00, 0xa8, 0xa1, 0x8d, 0xc5,
+ 0x4f, 0x43, 0xc4, 0x50, 0xf6, 0xed, 0x2f, 0xe8, 0x28, 0x50, 0x5f, 0xf4,
+ 0x23, 0x33, 0x5b, 0xb3, 0x6e, 0xa9, 0x0e, 0x0b, 0xfe, 0x78, 0xcc, 0xd6,
+ 0xec, 0xdb, 0xaa, 0x4b, 0x52, 0xd1, 0x8c, 0x89, 0x5f, 0x25, 0xdf, 0xfe,
+ 0x8c, 0x3b, 0x42, 0x33, 0x35, 0xbb, 0x36, 0xea, 0x91, 0x6c, 0xba, 0x36,
+ 0xef, 0xb5, 0x8b, 0xdd, 0xee, 0xfa, 0x58, 0xbd, 0x1b, 0xc6, 0xfc, 0x58,
+ 0xb6, 0xeb, 0x17, 0x84, 0x4e, 0xb1, 0x78, 0x5a, 0x02, 0xc5, 0xd9, 0xd2,
+ 0xc5, 0xf8, 0xe7, 0x97, 0xe2, 0xc5, 0xfd, 0x3a, 0x03, 0x75, 0xc5, 0x8b,
+ 0x0f, 0x0f, 0x5f, 0xe5, 0x17, 0xef, 0x4f, 0xc3, 0xe2, 0xc5, 0xee, 0xc2,
+ 0x82, 0xc5, 0x77, 0xa9, 0x96, 0xc0, 0x4f, 0x71, 0xce, 0x87, 0x9d, 0xbc,
+ 0x89, 0xfb, 0x15, 0x5f, 0xf0, 0x51, 0x41, 0xb5, 0xb7, 0xc4, 0xb1, 0x70,
+ 0xe0, 0xb1, 0x7f, 0xfd, 0x81, 0x66, 0xde, 0xf6, 0x04, 0xde, 0x63, 0x56,
+ 0x2f, 0xfb, 0x50, 0x93, 0xe7, 0xde, 0x0b, 0x15, 0x88, 0xe2, 0xf9, 0xf1,
+ 0x0c, 0x09, 0x4e, 0xd2, 0xb1, 0x7d, 0xdc, 0x39, 0xe9, 0x62, 0xa3, 0x59,
+ 0xb8, 0x71, 0x1b, 0xfe, 0xce, 0x8b, 0x00, 0x06, 0x82, 0xc5, 0xc7, 0xdd,
+ 0x62, 0xfd, 0xb0, 0xa1, 0x9b, 0x2c, 0x5f, 0xcf, 0xd7, 0x07, 0x84, 0xb1,
+ 0x7f, 0x75, 0x90, 0x9d, 0x01, 0x62, 0xb0, 0xf7, 0x58, 0xba, 0xfb, 0x93,
+ 0xae, 0x2c, 0x5f, 0xfd, 0xb7, 0x04, 0xcf, 0x0e, 0x7d, 0xa0, 0xb1, 0x69,
+ 0xe8, 0xfa, 0x48, 0x8e, 0xa5, 0x38, 0xa8, 0x1c, 0xe0, 0xce, 0xa1, 0x11,
+ 0xf8, 0x44, 0xdf, 0xbe, 0xf2, 0x5b, 0x2c, 0x5f, 0xfe, 0x2c, 0x39, 0xda,
+ 0x01, 0x8f, 0xf3, 0xd2, 0xc5, 0xdf, 0x0d, 0x62, 0xff, 0xda, 0x38, 0xa1,
+ 0x3f, 0xde, 0x4e, 0xb1, 0x6f, 0x2c, 0x54, 0x9e, 0x98, 0xd0, 0x69, 0x91,
+ 0x1a, 0x26, 0xcb, 0xc0, 0x10, 0xd6, 0x2f, 0x9c, 0x5d, 0xfe, 0x2c, 0x51,
+ 0x1e, 0x2f, 0x87, 0xaf, 0x8a, 0x7a, 0x82, 0xc5, 0xc1, 0xec, 0xb1, 0x7f,
+ 0xbd, 0xc1, 0x89, 0xb5, 0x05, 0x8a, 0x39, 0xe7, 0x90, 0xd5, 0xed, 0x34,
+ 0x4b, 0x14, 0xe6, 0xfc, 0x44, 0x37, 0xdb, 0xb6, 0x80, 0xb1, 0x7e, 0x93,
+ 0xe7, 0x5e, 0x58, 0xb6, 0xd2, 0x79, 0xa4, 0x49, 0x60, 0x96, 0x2f, 0xfd,
+ 0xaf, 0xb6, 0x10, 0xa1, 0x9c, 0x58, 0xbf, 0xfe, 0xe8, 0x03, 0xfb, 0x43,
+ 0x38, 0x42, 0x60, 0xd6, 0x2a, 0x51, 0x46, 0xe2, 0x6c, 0x7d, 0x7c, 0x0c,
+ 0xd4, 0x4b, 0x17, 0xf9, 0xbd, 0xc0, 0xf9, 0x38, 0xb1, 0x7e, 0x7f, 0xc8,
+ 0x71, 0x2c, 0x5e, 0xf4, 0x9d, 0x62, 0x8c, 0x5c, 0x3d, 0x81, 0x40, 0xe1,
+ 0xb3, 0x8c, 0xfb, 0x90, 0xc5, 0x0b, 0x1d, 0x36, 0xfe, 0x19, 0x40, 0x2d,
+ 0x22, 0x4f, 0x1a, 0x77, 0x15, 0x5f, 0xfc, 0x6c, 0x97, 0xb3, 0x4f, 0xb3,
+ 0x1d, 0x62, 0xf9, 0xa0, 0x6b, 0xac, 0x52, 0xc7, 0xcd, 0x1d, 0xfe, 0x32,
+ 0x73, 0xee, 0x2d, 0xd6, 0x28, 0xd3, 0xd1, 0x00, 0xe5, 0xdd, 0xe7, 0x7a,
+ 0xb1, 0x7c, 0x4f, 0xee, 0x2c, 0x5e, 0x7c, 0xd2, 0xc5, 0xde, 0xe2, 0xc5,
+ 0xcd, 0xd2, 0xc5, 0x61, 0xb0, 0x21, 0x8b, 0x3e, 0x91, 0x1a, 0x72, 0x2f,
+ 0xa6, 0x5f, 0xb4, 0xc5, 0x92, 0xb1, 0x4a, 0x90, 0x6c, 0x74, 0xcb, 0x74,
+ 0x47, 0xf8, 0x57, 0xb1, 0xad, 0xd2, 0x4b, 0x17, 0xb1, 0xc6, 0xb1, 0x78,
+ 0x78, 0x75, 0x8b, 0x10, 0xcd, 0xcb, 0x8e, 0x5f, 0xa4, 0xbd, 0x9e, 0x58,
+ 0xbf, 0xff, 0x9b, 0xc3, 0xce, 0xe7, 0xd4, 0xfd, 0xb8, 0x58, 0x05, 0x8a,
+ 0x74, 0x54, 0x11, 0x28, 0x89, 0xef, 0xfc, 0x53, 0x9b, 0xfd, 0xfb, 0x36,
+ 0x96, 0x2a, 0x53, 0x65, 0x84, 0x3d, 0xfc, 0x5d, 0x70, 0x67, 0x58, 0xb8,
+ 0x50, 0x58, 0xbb, 0xdc, 0x58, 0xb6, 0xeb, 0x15, 0x26, 0xad, 0xc6, 0x2f,
+ 0x0a, 0x4e, 0xb1, 0x7f, 0x40, 0xa7, 0xdf, 0x95, 0x8b, 0x9f, 0x4b, 0x15,
+ 0x12, 0x37, 0x00, 0x32, 0x48, 0x7c, 0x1f, 0xf0, 0xef, 0x62, 0xdb, 0xf7,
+ 0xdf, 0x52, 0x35, 0x8b, 0xe3, 0xf7, 0x34, 0x4b, 0x17, 0xf8, 0x51, 0xf1,
+ 0x7c, 0x45, 0xe5, 0x8b, 0xff, 0x36, 0xc1, 0x96, 0x70, 0x85, 0xf5, 0x8b,
+ 0xe9, 0x38, 0x7b, 0x2c, 0x56, 0xe8, 0xed, 0x72, 0x8f, 0x93, 0xb1, 0xc9,
+ 0x20, 0x5f, 0xf3, 0xc1, 0xb8, 0x79, 0xcf, 0x2c, 0x5d, 0x0c, 0x58, 0xbf,
+ 0xcc, 0xfe, 0x8b, 0xe2, 0x35, 0x62, 0xa2, 0x3c, 0xdf, 0x8b, 0xdf, 0xfc,
+ 0x78, 0xce, 0x3f, 0x06, 0x2d, 0x4f, 0x16, 0x2f, 0xed, 0xa0, 0xfb, 0xc9,
+ 0xd6, 0x2f, 0xff, 0x1c, 0xb0, 0x12, 0x0c, 0x29, 0xc0, 0x96, 0x2a, 0x4f,
+ 0xe1, 0xcc, 0x2f, 0xdc, 0x8e, 0x16, 0x0d, 0x62, 0xa5, 0x3b, 0x5c, 0x84,
+ 0x2b, 0x91, 0xea, 0x18, 0x2c, 0x41, 0x73, 0x41, 0x62, 0xfc, 0xe6, 0xcf,
+ 0x25, 0x62, 0xff, 0xa1, 0x19, 0x9a, 0xdd, 0x9b, 0x75, 0x48, 0xc0, 0x54,
+ 0xa2, 0x2b, 0x42, 0xec, 0x51, 0x7b, 0xef, 0xf5, 0x8b, 0xe6, 0xf3, 0xf9,
+ 0x62, 0xf0, 0xdc, 0x96, 0x2a, 0x3c, 0xf6, 0xc4, 0x3a, 0x11, 0x15, 0xc0,
+ 0xe9, 0x62, 0xee, 0xfd, 0xd6, 0x2f, 0x43, 0x47, 0x58, 0xb9, 0xfe, 0xb1,
+ 0x74, 0x20, 0xb1, 0x7f, 0xb6, 0x6f, 0x00, 0x32, 0x82, 0xc5, 0xa5, 0x62,
+ 0xff, 0x7a, 0x13, 0xad, 0x4c, 0x16, 0x2e, 0xd9, 0xd6, 0x2f, 0xfa, 0x73,
+ 0x91, 0x7d, 0xc2, 0xf2, 0xc5, 0x62, 0x26, 0x1c, 0x44, 0x8d, 0x38, 0x31,
+ 0x77, 0x25, 0x62, 0xa5, 0x3d, 0x4d, 0x8c, 0xe0, 0x32, 0x31, 0xcc, 0x1e,
+ 0xdc, 0x5d, 0xc6, 0x1a, 0x19, 0xc2, 0x3a, 0xbc, 0x2f, 0x71, 0x62, 0xfe,
+ 0xf6, 0x44, 0x52, 0x75, 0x8b, 0xc1, 0x38, 0x16, 0x2f, 0xe3, 0xfd, 0xb5,
+ 0x3b, 0x2c, 0x5b, 0x16, 0x2a, 0x4f, 0x02, 0x38, 0xbe, 0xfb, 0x8c, 0x40,
+ 0x58, 0xbc, 0x53, 0xb2, 0xc5, 0xf6, 0x47, 0xbe, 0x96, 0x2f, 0xfd, 0x9d,
+ 0x43, 0xf3, 0xc3, 0x7f, 0x2b, 0x15, 0x04, 0xdc, 0xdc, 0x7a, 0x22, 0xef,
+ 0xaf, 0x00, 0x93, 0xbf, 0x22, 0x21, 0xde, 0xe2, 0x5b, 0xfb, 0xad, 0x48,
+ 0x6c, 0x4b, 0x17, 0xfa, 0x73, 0x5e, 0xf6, 0x71, 0x62, 0x98, 0xf8, 0x80,
+ 0x5f, 0x7e, 0x38, 0x7a, 0x6e, 0x2c, 0x5f, 0xe8, 0x36, 0xa2, 0xfb, 0xe9,
+ 0x62, 0xfc, 0xff, 0xe4, 0x0e, 0xb1, 0x7f, 0x85, 0xd6, 0x9e, 0x4f, 0x8b,
+ 0x17, 0xef, 0xbc, 0x96, 0xcb, 0x17, 0xfd, 0x3b, 0x78, 0xa4, 0x5e, 0xe2,
+ 0xc5, 0x7d, 0x12, 0xdc, 0x34, 0x8e, 0x28, 0xbe, 0x2c, 0xe4, 0xac, 0x54,
+ 0x49, 0xa4, 0x00, 0xd7, 0xd0, 0xbf, 0xec, 0x67, 0x7a, 0x0e, 0x05, 0x8b,
+ 0xe2, 0xcf, 0x3a, 0xc5, 0xfa, 0x4b, 0x77, 0x3a, 0xc5, 0x11, 0xe4, 0xf8,
+ 0x86, 0xe2, 0x95, 0x8b, 0xee, 0xb7, 0x73, 0x56, 0x2f, 0xcc, 0x6e, 0x7d,
+ 0x96, 0x2a, 0x55, 0x51, 0xe4, 0x6e, 0x51, 0x23, 0x33, 0x30, 0x08, 0x7c,
+ 0x2c, 0x22, 0x6b, 0xff, 0xb4, 0xdf, 0x0f, 0x0b, 0x22, 0x98, 0xf5, 0x8b,
+ 0xff, 0xd0, 0xfe, 0x10, 0x41, 0xeb, 0xef, 0x27, 0x58, 0xbf, 0x9f, 0xd8,
+ 0x79, 0xfa, 0xc5, 0xff, 0x38, 0x36, 0xfc, 0xf0, 0x5c, 0x58, 0xbf, 0xd0,
+ 0x6f, 0x71, 0xca, 0x56, 0x2d, 0x3a, 0x3e, 0xd2, 0x3b, 0xae, 0x93, 0x0c,
+ 0xd2, 0x67, 0xa1, 0x35, 0x7f, 0xf8, 0x98, 0x2c, 0xdf, 0xf3, 0xd4, 0x23,
+ 0xb1, 0x62, 0xe8, 0xf6, 0x58, 0xbf, 0xfc, 0x22, 0x63, 0x79, 0x9e, 0x92,
+ 0x70, 0x2c, 0x5f, 0xa2, 0xe7, 0x9f, 0x65, 0x8b, 0xfa, 0x0f, 0x13, 0x34,
+ 0x16, 0x29, 0xcf, 0x65, 0x8a, 0xef, 0xfd, 0x87, 0xcd, 0x67, 0x50, 0xcf,
+ 0x2c, 0x5f, 0xcf, 0xf7, 0x3e, 0x1a, 0xb1, 0x5f, 0x3e, 0xde, 0x1f, 0xdf,
+ 0xf3, 0x7f, 0x52, 0xf0, 0x6e, 0x2c, 0x5f, 0xfe, 0x6d, 0xbe, 0xf2, 0x59,
+ 0x13, 0xe9, 0xd6, 0x28, 0x6a, 0xf1, 0xb2, 0x35, 0x48, 0x8d, 0xf4, 0x9e,
+ 0x71, 0xaf, 0xc2, 0x8b, 0xd0, 0x8d, 0x11, 0x10, 0x47, 0x16, 0x25, 0x8b,
+ 0x47, 0x2c, 0x5f, 0xe9, 0x2f, 0x00, 0x32, 0x82, 0xc5, 0xf6, 0xef, 0x83,
+ 0x58, 0xa5, 0x8b, 0x6e, 0xb1, 0x84, 0xcb, 0x84, 0x04, 0x8b, 0xa0, 0x35,
+ 0x8b, 0xfe, 0x6e, 0x86, 0xe2, 0xef, 0xdf, 0x4b, 0x15, 0x1b, 0xa6, 0x31,
+ 0xb0, 0x8c, 0x05, 0x7a, 0x34, 0x72, 0xfd, 0x10, 0x1c, 0x63, 0x83, 0x17,
+ 0xe3, 0x66, 0x18, 0x35, 0x8b, 0xec, 0xf7, 0xf1, 0x62, 0xe6, 0x35, 0x62,
+ 0xec, 0x19, 0x1b, 0xa8, 0xe2, 0x2b, 0xa3, 0x6d, 0xd7, 0x28, 0x51, 0x77,
+ 0x80, 0xb1, 0x7c, 0x3f, 0xe6, 0xcb, 0x17, 0x77, 0x41, 0x62, 0xfc, 0xd9,
+ 0xec, 0x3a, 0xc5, 0xec, 0xeb, 0xcb, 0x15, 0xb1, 0xe2, 0x9a, 0x4f, 0x5b,
+ 0x23, 0x01, 0xc6, 0x34, 0x48, 0xcc, 0x17, 0xe0, 0xe3, 0x98, 0x80, 0xb1,
+ 0x7f, 0x67, 0xd8, 0x32, 0xf2, 0xc5, 0x6c, 0x7b, 0x43, 0x2c, 0xbf, 0xd1,
+ 0x66, 0x9f, 0x66, 0x3a, 0xc5, 0xfa, 0x34, 0x93, 0x47, 0x8b, 0x17, 0xf6,
+ 0x7b, 0xd3, 0xae, 0x2c, 0x5f, 0xfe, 0x72, 0x14, 0x33, 0x86, 0x37, 0x50,
+ 0xc5, 0x8b, 0xf9, 0x88, 0x1b, 0x03, 0xcb, 0x17, 0xe0, 0xfd, 0xc9, 0xf2,
+ 0xc5, 0x4a, 0x6b, 0x18, 0x47, 0xa3, 0x52, 0x2e, 0xf1, 0x74, 0x72, 0x58,
+ 0x65, 0xf6, 0x8c, 0x8d, 0xdd, 0x29, 0xdf, 0x78, 0x49, 0xdf, 0x52, 0x49,
+ 0x8d, 0x57, 0x68, 0xd3, 0xa0, 0xe6, 0x38, 0xec, 0x32, 0x72, 0x40, 0xd8,
+ 0x5d, 0xef, 0x1f, 0x37, 0x51, 0xdd, 0xbc, 0x62, 0x31, 0x46, 0x8d, 0xa8,
+ 0xff, 0x4f, 0x0d, 0xbf, 0xca, 0x5d, 0x68, 0xfd, 0x41, 0x0d, 0xb2, 0x95,
+ 0x89, 0xc9, 0xc3, 0x0f, 0x47, 0x52, 0x27, 0x8e, 0xcc, 0x61, 0x17, 0x47,
+ 0x43, 0xac, 0x38, 0xfb, 0xaf, 0x1c, 0x5a, 0x48, 0xbb, 0x9c, 0x58, 0xbf,
+ 0xf3, 0x42, 0x33, 0x35, 0xbb, 0x36, 0xea, 0x91, 0x8c, 0xba, 0x7b, 0x96,
+ 0x2e, 0xd6, 0x2c, 0x5a, 0x74, 0x6c, 0x7e, 0x35, 0x7f, 0xb0, 0xde, 0x7e,
+ 0x4b, 0xcb, 0x17, 0xde, 0x84, 0x9a, 0xb1, 0x44, 0x7b, 0x01, 0x9a, 0x5a,
+ 0x31, 0xd3, 0x57, 0xd0, 0xf1, 0xc6, 0x3f, 0x08, 0x1e, 0x3f, 0x5e, 0x00,
+ 0x70, 0x58, 0xbe, 0xdb, 0x71, 0x12, 0xc5, 0xf0, 0xdf, 0xb4, 0x67, 0x47,
+ 0x88, 0x18, 0xfd, 0xe6, 0x63, 0x56, 0x2f, 0xfa, 0x37, 0x8d, 0xfe, 0xf2,
+ 0x76, 0x1a, 0xc5, 0xbb, 0xd5, 0x8b, 0x82, 0x09, 0x62, 0xbb, 0xe1, 0xb1,
+ 0x08, 0x5e, 0xfd, 0x1b, 0xc6, 0xd1, 0xb4, 0x6f, 0x1b, 0x2c, 0x5f, 0xdd,
+ 0xec, 0x6f, 0xdf, 0x21, 0x0f, 0xac, 0x5e, 0xef, 0xb8, 0x0d, 0x62, 0xa3,
+ 0x73, 0xe5, 0x8d, 0x48, 0x17, 0xf6, 0xb4, 0x22, 0xcf, 0xac, 0x5d, 0x1a,
+ 0xe3, 0x45, 0x8b, 0xe9, 0x27, 0xfa, 0xc5, 0xf4, 0xed, 0x3a, 0x58, 0xbf,
+ 0xdc, 0x90, 0x37, 0x98, 0xd5, 0x8b, 0xde, 0x98, 0x96, 0x2f, 0xa6, 0x27,
+ 0x3a, 0xc5, 0xff, 0x8b, 0x05, 0xb9, 0x66, 0xc1, 0xc1, 0x62, 0xe1, 0xe2,
+ 0xc5, 0x9c, 0x8f, 0x63, 0xb9, 0x06, 0xb1, 0x14, 0x9a, 0x7b, 0xbb, 0xf2,
+ 0xb1, 0x7e, 0x93, 0xcf, 0x5c, 0x58, 0xbe, 0xe4, 0xea, 0x56, 0x2f, 0xb6,
+ 0x10, 0xe3, 0xd6, 0x2f, 0x82, 0x92, 0x95, 0x8b, 0xfc, 0xe0, 0x33, 0x22,
+ 0x93, 0xac, 0x54, 0x9e, 0xbf, 0x71, 0x15, 0x0d, 0x53, 0x0b, 0x90, 0xc7,
+ 0x91, 0xc4, 0x69, 0xa8, 0x61, 0x7c, 0x88, 0x85, 0xfc, 0x52, 0x19, 0x17,
+ 0x73, 0xfd, 0xa0, 0xb1, 0x7e, 0x3c, 0xe7, 0xb8, 0xb1, 0x7e, 0xe3, 0x97,
+ 0x50, 0x58, 0xbb, 0x22, 0x58, 0xb0, 0x46, 0x1e, 0x0e, 0x14, 0xd4, 0x68,
+ 0x8a, 0x41, 0x89, 0x63, 0x4d, 0xfe, 0xfc, 0xeb, 0x60, 0xc4, 0x05, 0x8b,
+ 0xfa, 0x1f, 0x9e, 0xc3, 0x95, 0x8b, 0xdd, 0x8f, 0xc5, 0x8b, 0xe7, 0x0b,
+ 0x3e, 0xb1, 0x7b, 0x66, 0x25, 0x8a, 0xc4, 0x48, 0x1a, 0x61, 0xf2, 0x01,
+ 0x11, 0xdf, 0xee, 0xc3, 0x9c, 0x83, 0x92, 0xc5, 0xfd, 0x3c, 0xcf, 0xbf,
+ 0x65, 0x8a, 0x73, 0xe3, 0x11, 0xa5, 0xff, 0xff, 0x0b, 0x7d, 0x67, 0x69,
+ 0x2f, 0x68, 0x5b, 0x7e, 0x7d, 0xc7, 0x58, 0xbf, 0xf6, 0xdf, 0xc8, 0xbf,
+ 0x23, 0xcd, 0xd6, 0x29, 0xd1, 0x5a, 0x26, 0xbb, 0x9b, 0x8b, 0x17, 0xc6,
+ 0x7b, 0x3e, 0xb1, 0x5f, 0x37, 0x7c, 0x17, 0xbf, 0xff, 0x9f, 0xaf, 0x73,
+ 0x6d, 0x67, 0x0c, 0xcd, 0xfe, 0x28, 0xf5, 0x8a, 0x94, 0x42, 0xe8, 0x86,
+ 0xfd, 0xe2, 0x9f, 0x71, 0x62, 0xdb, 0x2c, 0x5a, 0x40, 0x6e, 0xc8, 0xa2,
+ 0xff, 0xff, 0xfa, 0x1c, 0xfe, 0x08, 0x2e, 0x7f, 0x37, 0xce, 0x19, 0x9d,
+ 0x43, 0x8e, 0x4e, 0xb1, 0x7d, 0xe3, 0x5f, 0x4b, 0x17, 0x99, 0xb7, 0x54,
+ 0x96, 0x25, 0xf3, 0x07, 0x26, 0xac, 0x5f, 0x1e, 0x79, 0x8b, 0x15, 0xb9,
+ 0xf8, 0x68, 0xa8, 0x04, 0x97, 0xef, 0xb9, 0xe7, 0x4b, 0x17, 0xff, 0x84,
+ 0xdb, 0x6b, 0x0f, 0xf9, 0xd8, 0x84, 0xb1, 0x4e, 0x7e, 0x84, 0x51, 0x7f,
+ 0x31, 0xc3, 0x1f, 0xe5, 0x62, 0xfe, 0x86, 0x70, 0x1d, 0x01, 0x62, 0x98,
+ 0xf7, 0xc4, 0x5f, 0x7e, 0xdb, 0xe4, 0xc0, 0x58, 0xbf, 0xa7, 0xf9, 0xf7,
+ 0xee, 0x58, 0xa9, 0x3d, 0x90, 0x14, 0xdf, 0xec, 0xf3, 0x10, 0x32, 0x3d,
+ 0x62, 0xff, 0xb3, 0xc5, 0x82, 0x92, 0xf2, 0xc5, 0x70, 0xfb, 0x23, 0x8d,
+ 0x6f, 0xed, 0x6d, 0xee, 0x30, 0x16, 0x2f, 0xf9, 0x8b, 0x76, 0x21, 0x67,
+ 0xd6, 0x2f, 0xec, 0xe0, 0x33, 0x06, 0xb1, 0x4c, 0x7c, 0xa4, 0x71, 0x50,
+ 0x5e, 0x4b, 0x1c, 0x33, 0x8d, 0x87, 0x16, 0xeb, 0xbd, 0x12, 0xbc, 0x20,
+ 0x75, 0x09, 0x4f, 0xc2, 0x90, 0x9f, 0xf8, 0xf5, 0xe8, 0x46, 0x88, 0x97,
+ 0xb4, 0x25, 0x6f, 0xed, 0x77, 0x7b, 0x08, 0x0b, 0x17, 0xfd, 0xee, 0x16,
+ 0x76, 0x2c, 0xe2, 0xc5, 0x49, 0xf5, 0x88, 0xc6, 0xfb, 0xc5, 0x9d, 0xcb,
+ 0x17, 0x9c, 0x43, 0x58, 0xbf, 0xfa, 0x7a, 0xfe, 0x6f, 0x3a, 0xea, 0x1c,
+ 0x58, 0xa3, 0x51, 0x56, 0xe4, 0x31, 0xe4, 0xa2, 0x1d, 0xbf, 0xf8, 0xbc,
+ 0x68, 0xa4, 0xb3, 0x79, 0xd2, 0xc5, 0xf9, 0xfb, 0xf6, 0x16, 0xeb, 0x17,
+ 0x6d, 0xdf, 0xac, 0x5f, 0xff, 0xfd, 0x9b, 0x8c, 0x5b, 0x06, 0x4d, 0xe9,
+ 0x03, 0xc1, 0xfc, 0x52, 0x05, 0x8a, 0xc4, 0x48, 0xf8, 0x7a, 0xa5, 0x1c,
+ 0x2f, 0x0b, 0xfb, 0xfd, 0xad, 0xbd, 0xc6, 0xeb, 0x75, 0x8b, 0xff, 0xe3,
+ 0xf6, 0xcd, 0x69, 0xfb, 0x71, 0xc4, 0xda, 0x58, 0xa9, 0x4f, 0x63, 0xf1,
+ 0x93, 0x31, 0x30, 0x8e, 0x2f, 0xef, 0x61, 0x48, 0x51, 0xcb, 0x17, 0xff,
+ 0xd3, 0x9c, 0xc2, 0x33, 0x8f, 0x1d, 0x24, 0x05, 0x8a, 0xc4, 0x41, 0x11,
+ 0x8d, 0xff, 0x89, 0x8e, 0x13, 0x0e, 0x7a, 0xe2, 0xc5, 0xf3, 0xc4, 0xe1,
+ 0x2c, 0x5f, 0xbc, 0x4c, 0x0e, 0x2c, 0x5d, 0x3a, 0x81, 0xe6, 0x1a, 0x49,
+ 0x7f, 0xf3, 0x9f, 0x86, 0x7d, 0xfc, 0x52, 0x75, 0x8a, 0x82, 0x64, 0x00,
+ 0x21, 0xe4, 0x23, 0x3c, 0x5d, 0x7f, 0x76, 0xce, 0xe7, 0x28, 0x96, 0x2f,
+ 0xf7, 0x3e, 0xf1, 0xe2, 0x61, 0xac, 0x5f, 0x37, 0x9b, 0x75, 0x8b, 0xfe,
+ 0x9e, 0xcd, 0xad, 0xfe, 0xdd, 0xcb, 0x16, 0x95, 0x8b, 0xe6, 0x3e, 0x12,
+ 0xc5, 0x49, 0xb2, 0xf8, 0x8d, 0xff, 0xff, 0xff, 0xdd, 0x0c, 0x84, 0xd1,
+ 0xe2, 0x91, 0xb1, 0x03, 0xf9, 0xec, 0x3f, 0xd8, 0x5d, 0xfe, 0x43, 0xdc,
+ 0xc5, 0x8b, 0xfc, 0xf3, 0xb9, 0x63, 0xec, 0xb1, 0x50, 0x4f, 0xe3, 0xa3,
+ 0x33, 0x9b, 0xfc, 0x8f, 0xce, 0x22, 0x20, 0xee, 0x85, 0x3d, 0xfc, 0x5e,
+ 0xfe, 0x01, 0x96, 0x2f, 0x85, 0xdf, 0xc7, 0x3a, 0xc5, 0x49, 0xec, 0x39,
+ 0x6d, 0xff, 0x77, 0x08, 0xfe, 0xea, 0x13, 0xf5, 0x8b, 0xf6, 0x6c, 0x76,
+ 0xf2, 0xc5, 0x39, 0xf4, 0x11, 0xfd, 0xf3, 0x7c, 0x33, 0xac, 0x5f, 0x49,
+ 0xdb, 0xcb, 0x17, 0xc7, 0x10, 0x22, 0x58, 0xa8, 0x26, 0x27, 0x90, 0x88,
+ 0x62, 0x0e, 0x12, 0x08, 0x8a, 0xfe, 0x22, 0xc0, 0x07, 0xd2, 0xc5, 0xf7,
+ 0xb3, 0xa8, 0x96, 0x2b, 0x0f, 0x53, 0xb8, 0xbe, 0xed, 0x4a, 0xc5, 0xe8,
+ 0x9c, 0xd5, 0x8a, 0x88, 0xdb, 0x70, 0x5e, 0xe8, 0xe1, 0xac, 0x5f, 0xa4,
+ 0xfb, 0x60, 0x4b, 0x17, 0xec, 0x1f, 0x3f, 0x2b, 0x17, 0x8f, 0x3a, 0x58,
+ 0xb8, 0x61, 0x2c, 0x5f, 0xff, 0xff, 0xe6, 0xf7, 0xb3, 0xfc, 0x68, 0x39,
+ 0x7a, 0x19, 0xac, 0xe6, 0x7d, 0xb6, 0x29, 0x82, 0xc5, 0xef, 0x4c, 0x4b,
+ 0x15, 0x29, 0xe4, 0xe2, 0xd6, 0xe4, 0x4e, 0x37, 0xa2, 0xa0, 0x14, 0x10,
+ 0xef, 0x06, 0x43, 0x84, 0x65, 0xff, 0xa2, 0xeb, 0xce, 0x3c, 0x2c, 0x3a,
+ 0xc5, 0xfc, 0x28, 0xed, 0xfe, 0xfd, 0xfa, 0xc5, 0xf7, 0x50, 0x9f, 0xac,
+ 0x5f, 0xee, 0x0f, 0xf9, 0xb8, 0xa3, 0xd6, 0x2d, 0x9c, 0x3d, 0xd1, 0x12,
+ 0x5d, 0x3d, 0x96, 0x2b, 0xe7, 0x80, 0x44, 0xf7, 0xe7, 0x19, 0x60, 0x96,
+ 0x2f, 0xff, 0xa4, 0xcc, 0x1f, 0xf3, 0x5d, 0x49, 0x7b, 0x8b, 0x15, 0xf3,
+ 0xf8, 0x11, 0x3d, 0xfe, 0x89, 0xb1, 0xe0, 0x19, 0xd6, 0x28, 0x68, 0xf0,
+ 0xde, 0x13, 0x2e, 0x45, 0x7f, 0xba, 0x84, 0x50, 0x6d, 0x6c, 0xb1, 0x73,
+ 0x12, 0xc5, 0xfd, 0xa7, 0x1b, 0xe7, 0x4b, 0x17, 0xd0, 0xf3, 0xec, 0xb1,
+ 0x52, 0x8a, 0x0d, 0x8e, 0x30, 0x59, 0x8b, 0xaf, 0xff, 0xf4, 0x9c, 0xd3,
+ 0x5b, 0xaf, 0xcb, 0xfb, 0x8e, 0x5d, 0x41, 0x62, 0xff, 0xfb, 0xd3, 0xbb,
+ 0xf9, 0xce, 0x67, 0x18, 0x63, 0x58, 0xbf, 0xfc, 0x03, 0xb7, 0x5e, 0xd6,
+ 0x3f, 0xe4, 0x6b, 0x14, 0xe8, 0x9d, 0xe2, 0x95, 0x4a, 0xbf, 0x8c, 0x8f,
+ 0x15, 0xe1, 0xab, 0xf3, 0xb6, 0x8c, 0x06, 0xe8, 0x79, 0x62, 0xf9, 0xce,
+ 0xd0, 0x58, 0xbf, 0xa4, 0x07, 0x9e, 0x12, 0xc5, 0xfd, 0x9b, 0x61, 0x64,
+ 0x16, 0x2e, 0x98, 0x96, 0x2f, 0xff, 0xe9, 0xee, 0xe4, 0xe9, 0xc3, 0xf9,
+ 0x91, 0x4e, 0xb6, 0x95, 0x8a, 0x94, 0xc3, 0xa0, 0x30, 0xe4, 0x5a, 0x2d,
+ 0x01, 0x69, 0x0c, 0x5f, 0xff, 0xcd, 0xf8, 0xcf, 0xbc, 0x9d, 0x87, 0xc6,
+ 0xd9, 0xb4, 0xb1, 0x7f, 0xf7, 0x3f, 0x9d, 0xcf, 0xe7, 0x87, 0x04, 0xb1,
+ 0x7f, 0x1f, 0xc2, 0x6d, 0xa5, 0x62, 0xce, 0x62, 0x35, 0x7a, 0x5e, 0x0d,
+ 0x22, 0xfe, 0x7f, 0x42, 0x7c, 0xeb, 0x16, 0x82, 0xc5, 0xe1, 0x75, 0x8b,
+ 0x17, 0xfb, 0x4e, 0x2d, 0x81, 0xc8, 0x2c, 0x5f, 0xd9, 0xd0, 0x33, 0xdc,
+ 0x58, 0xbf, 0x85, 0x25, 0xd4, 0x38, 0xb1, 0xf3, 0x5f, 0x7f, 0x1c, 0x5d,
+ 0x43, 0x91, 0xeb, 0x17, 0xd3, 0xf6, 0x8f, 0x58, 0xb4, 0x24, 0xf6, 0x48,
+ 0xd2, 0xfb, 0xff, 0xcd, 0x2c, 0x5f, 0xfc, 0xda, 0xdb, 0xef, 0xac, 0x2e,
+ 0xb7, 0x58, 0xba, 0x76, 0x58, 0xa8, 0x1e, 0xfb, 0xa3, 0xdf, 0xfa, 0x79,
+ 0x2f, 0xd7, 0xbd, 0x27, 0x58, 0xb9, 0xa2, 0x58, 0xa1, 0x9e, 0xb9, 0xa7,
+ 0xf7, 0xf4, 0x85, 0x11, 0x48, 0xd6, 0x2f, 0xfe, 0x2c, 0xe3, 0x80, 0xc9,
+ 0xda, 0x78, 0xb1, 0x5b, 0x2a, 0xd2, 0x18, 0xf6, 0xec, 0xbd, 0x42, 0x61,
+ 0xc9, 0xa2, 0x84, 0x16, 0x9e, 0x3c, 0x47, 0xd8, 0xbe, 0xfd, 0xbf, 0xe4,
+ 0x8d, 0x58, 0xbf, 0xe6, 0xf7, 0xe4, 0x27, 0x9f, 0x2c, 0x54, 0xab, 0xd6,
+ 0xc9, 0x5c, 0x8d, 0x08, 0xf1, 0x15, 0x5f, 0x1d, 0xba, 0xf2, 0xc5, 0xff,
+ 0xdb, 0x4f, 0x8c, 0x0f, 0x70, 0xfb, 0x83, 0xe2, 0xc5, 0xff, 0xcd, 0x1f,
+ 0x84, 0xc3, 0x6c, 0xeb, 0xcb, 0x17, 0xfd, 0xa9, 0xe3, 0x68, 0xa6, 0x0b,
+ 0x17, 0x4c, 0x16, 0x2b, 0x48, 0xe5, 0xfa, 0x87, 0x64, 0x6e, 0xe3, 0x8b,
+ 0xd0, 0x6d, 0x96, 0x2f, 0x19, 0xb1, 0xd6, 0x2f, 0xcc, 0xc5, 0xb1, 0xd6,
+ 0x2f, 0xf9, 0xba, 0x83, 0xff, 0xed, 0x1e, 0xb1, 0x7f, 0xdf, 0x0c, 0x71,
+ 0x93, 0xbe, 0x76, 0x58, 0xbf, 0x3e, 0x8a, 0x42, 0x58, 0xa1, 0x9f, 0x4b,
+ 0x20, 0xdf, 0x60, 0xd8, 0x0b, 0x17, 0xe9, 0xd8, 0xa7, 0x65, 0x8a, 0x39,
+ 0xe5, 0x91, 0x15, 0xbc, 0xb1, 0x7f, 0x9b, 0x62, 0xcf, 0x60, 0x16, 0x2f,
+ 0xfc, 0x6f, 0x39, 0x9f, 0x7e, 0x0b, 0x65, 0x8a, 0x1a, 0x21, 0xf0, 0x48,
+ 0x46, 0x77, 0xfb, 0xed, 0xb7, 0xbd, 0x81, 0x2c, 0x54, 0x6c, 0xaf, 0x43,
+ 0x23, 0x09, 0xe9, 0x09, 0xc7, 0xa2, 0x20, 0xd1, 0x47, 0xe1, 0x4c, 0xcd,
+ 0x85, 0x0a, 0x81, 0x17, 0xdf, 0x4c, 0x53, 0xb2, 0xc5, 0xf0, 0xd8, 0x80,
+ 0xb1, 0x7f, 0xe2, 0x61, 0xfe, 0x7b, 0x7d, 0x89, 0x62, 0xf9, 0xb8, 0x67,
+ 0xd6, 0x2f, 0xff, 0x43, 0x0b, 0xc2, 0xfb, 0xf7, 0x77, 0x4c, 0x7a, 0xc5,
+ 0xff, 0xff, 0xec, 0x3e, 0x68, 0x00, 0x17, 0x3e, 0xfe, 0x86, 0x7d, 0x80,
+ 0xe3, 0x95, 0x8b, 0x47, 0xac, 0x5f, 0x7d, 0xd8, 0x0b, 0x15, 0x26, 0xdf,
+ 0x82, 0xb7, 0x7c, 0x4b, 0x17, 0xff, 0xfb, 0x37, 0x30, 0x85, 0xdc, 0x66,
+ 0x75, 0x0c, 0x11, 0x03, 0x8b, 0x17, 0x43, 0x8b, 0x15, 0xb2, 0x20, 0x19,
+ 0xa2, 0xa5, 0x17, 0x62, 0x84, 0xc5, 0xff, 0xed, 0xb3, 0xaf, 0x71, 0xca,
+ 0x40, 0xc7, 0x58, 0xbf, 0xdd, 0x16, 0x0f, 0xec, 0x12, 0xc5, 0x62, 0x20,
+ 0x19, 0x2e, 0xb6, 0x56, 0x9b, 0x02, 0x41, 0x91, 0x1a, 0x7f, 0xd1, 0x27,
+ 0xd4, 0xda, 0x15, 0xc5, 0x0d, 0xbe, 0x42, 0x9e, 0xfb, 0xd0, 0x97, 0x58,
+ 0xbf, 0xc3, 0xdb, 0x02, 0xcf, 0xb2, 0xc5, 0xe1, 0x48, 0x16, 0x2f, 0xe2,
+ 0xce, 0xa1, 0x1f, 0x12, 0xc5, 0x68, 0xf4, 0x3e, 0x3b, 0x58, 0x8a, 0x76,
+ 0x84, 0x2d, 0xfd, 0xb4, 0x50, 0x8d, 0xb5, 0xb2, 0xc5, 0xf1, 0x16, 0x79,
+ 0x62, 0xf0, 0xb5, 0xb2, 0xc5, 0xf9, 0xe3, 0xf5, 0xa7, 0x58, 0xbd, 0xf7,
+ 0x3a, 0xc5, 0x46, 0xe8, 0xc0, 0x93, 0x8c, 0x21, 0xf8, 0xf8, 0x8a, 0xef,
+ 0xfb, 0x22, 0x83, 0x6b, 0x6f, 0x89, 0x62, 0xff, 0xb0, 0x63, 0x7e, 0xb3,
+ 0xaf, 0x2c, 0x5f, 0x47, 0x31, 0x01, 0x62, 0xdb, 0x0d, 0x13, 0x9f, 0x3c,
+ 0x0c, 0xee, 0xf3, 0x0b, 0x4b, 0x17, 0xd1, 0xf3, 0xc2, 0x58, 0xbf, 0xf7,
+ 0xd8, 0xfe, 0xfc, 0xf8, 0x47, 0x58, 0xac, 0x3e, 0x58, 0x89, 0x6f, 0xfe,
+ 0xcc, 0x34, 0xf2, 0xfa, 0xd3, 0x84, 0xb1, 0x79, 0x9b, 0x4b, 0x17, 0xfd,
+ 0xef, 0x89, 0xa1, 0xde, 0x81, 0xd6, 0x2f, 0x81, 0xdb, 0x06, 0xb1, 0x7f,
+ 0xcf, 0x07, 0xf8, 0x8e, 0x77, 0x58, 0xbb, 0x3c, 0xb1, 0x52, 0x9f, 0x88,
+ 0xce, 0x32, 0x10, 0x5a, 0x22, 0xfa, 0x29, 0x0e, 0x70, 0xff, 0xc4, 0xb1,
+ 0xc7, 0x37, 0x37, 0x72, 0xc5, 0xef, 0xe1, 0xd6, 0x2f, 0xff, 0x4c, 0x79,
+ 0xe4, 0x65, 0x9e, 0xf3, 0x12, 0xc5, 0x12, 0x20, 0xbc, 0x35, 0xdc, 0x3b,
+ 0x73, 0xc6, 0x77, 0x8e, 0xce, 0x36, 0x34, 0x74, 0x8d, 0x8a, 0x3b, 0xee,
+ 0x15, 0x1d, 0xf5, 0x2d, 0x8d, 0x45, 0xd3, 0x2a, 0x13, 0x68, 0xcf, 0x20,
+ 0x68, 0x38, 0x63, 0xe4, 0xf7, 0x59, 0xb1, 0xf8, 0xef, 0x28, 0x63, 0xa8,
+ 0xf9, 0x1e, 0x51, 0xdc, 0x51, 0xec, 0xea, 0x53, 0x59, 0xe1, 0x05, 0xf9,
+ 0xc3, 0x86, 0x8d, 0x9c, 0x11, 0x95, 0x77, 0xe7, 0x05, 0x38, 0x07, 0xc9,
+ 0xc1, 0x8f, 0x4b, 0xed, 0x14, 0x24, 0x3b, 0x43, 0x26, 0x3a, 0x1c, 0xc1,
+ 0xca, 0xda, 0xee, 0x8c, 0x1a, 0xa3, 0x1d, 0xb0, 0x8f, 0xed, 0x9d, 0x55,
+ 0xe8, 0xd7, 0x1d, 0x1b, 0xac, 0x5d, 0xde, 0x74, 0xb1, 0x7d, 0xe8, 0xec,
+ 0xfa, 0xc5, 0x89, 0x62, 0xbb, 0xd3, 0x6f, 0x02, 0x6b, 0x77, 0xc5, 0x8b,
+ 0xa3, 0x7e, 0xf1, 0x62, 0xa3, 0x63, 0x75, 0xdf, 0x06, 0x2e, 0xef, 0xb8,
+ 0xe5, 0x8b, 0xec, 0x1b, 0x1d, 0x62, 0xa3, 0x73, 0xc4, 0xd1, 0x15, 0xef,
0x4f, 0xd6, 0x2f, 0xa4, 0x78, 0x75, 0x8b, 0x6a, 0x4d, 0xfe, 0x87, 0x6d,
- 0x1e, 0xb1, 0x73, 0x84, 0x58, 0xbd, 0xa9, 0xdd, 0x62, 0xda, 0x58, 0xac,
- 0x36, 0x0c, 0x3d, 0x7d, 0xb6, 0xa7, 0x65, 0x8b, 0x8c, 0x02, 0xc5, 0xd9,
- 0xf5, 0x8b, 0xdf, 0xc8, 0x96, 0x2f, 0x7d, 0xce, 0xb1, 0x68, 0x96, 0x2b,
- 0x63, 0xe5, 0x18, 0xbb, 0x0f, 0x08, 0x76, 0xd1, 0x2c, 0x5f, 0x16, 0xc2,
- 0xe2, 0xc5, 0x39, 0xb7, 0x61, 0x3b, 0xf6, 0x0f, 0x4d, 0xba, 0xc5, 0xf3,
- 0x6d, 0x3a, 0x58, 0xbd, 0xa6, 0xd9, 0x62, 0xc3, 0xf9, 0xf5, 0x11, 0x4f,
- 0x88, 0xef, 0x61, 0x79, 0x62, 0xa4, 0xf4, 0x3e, 0x69, 0x78, 0x6d, 0x05,
- 0x8b, 0xfb, 0xf1, 0x42, 0x75, 0xb2, 0xc5, 0xc2, 0x82, 0xc5, 0x39, 0xf3,
- 0x30, 0xef, 0x43, 0x1b, 0x0d, 0x62, 0x9d, 0x5a, 0xd4, 0x44, 0xc7, 0x15,
- 0xfa, 0x4b, 0x0f, 0x80, 0x94, 0x9f, 0xb8, 0xe7, 0xe8, 0x6c, 0xf4, 0x84,
- 0x3c, 0x71, 0x7d, 0xed, 0x70, 0x4b, 0x16, 0xfa, 0xc5, 0xfc, 0x1c, 0xf7,
- 0xc6, 0xdd, 0x62, 0xe3, 0x38, 0xb1, 0x51, 0x1e, 0x57, 0x0c, 0x6e, 0x28,
- 0x96, 0x2c, 0x62, 0xc5, 0xd2, 0x6a, 0xc5, 0xed, 0x4c, 0x16, 0x2f, 0x8b,
- 0x01, 0xc5, 0x8b, 0x77, 0xb1, 0xeb, 0xe8, 0x61, 0x87, 0x6a, 0x53, 0x55,
- 0xd8, 0x78, 0x6b, 0x98, 0x47, 0xd8, 0xc0, 0x9a, 0xaf, 0xb5, 0xb6, 0x69,
- 0x62, 0xf9, 0xf4, 0x28, 0xf5, 0x8a, 0x93, 0xca, 0xc2, 0x4b, 0xf7, 0x70,
- 0xf3, 0x76, 0xb1, 0x77, 0x37, 0x58, 0xb9, 0xa5, 0x62, 0xd2, 0xb1, 0x5f,
- 0x44, 0x5b, 0x10, 0x11, 0x5f, 0x06, 0x7c, 0x2d, 0x6c, 0x58, 0xbf, 0xdd,
- 0xea, 0x5e, 0x0d, 0xc5, 0x8b, 0xec, 0x29, 0x82, 0xc5, 0x61, 0xea, 0x9c,
- 0xd2, 0xd1, 0xcb, 0x17, 0xee, 0x67, 0x9f, 0x4b, 0x17, 0xb3, 0xbf, 0x2c,
- 0x50, 0x0f, 0x1b, 0x85, 0x17, 0xbe, 0xe1, 0xac, 0x5f, 0xfc, 0x2d, 0xdc,
- 0xdf, 0xb4, 0x38, 0xe7, 0x58, 0xac, 0x44, 0x3e, 0xe4, 0x44, 0x3d, 0x74,
- 0x38, 0xb1, 0x73, 0x0d, 0x62, 0xf7, 0xb3, 0x8b, 0x17, 0x14, 0xac, 0x54,
- 0x0f, 0x28, 0x42, 0xfd, 0x07, 0x6f, 0xf9, 0xc5, 0xb4, 0xf6, 0x0d, 0x4a,
- 0xc5, 0xe8, 0x4f, 0x6b, 0x16, 0x8f, 0x58, 0xa8, 0x8d, 0x99, 0x0f, 0x5d,
- 0x9d, 0xac, 0x58, 0x96, 0x2d, 0xa7, 0x35, 0x2c, 0x31, 0x68, 0xe5, 0x8b,
- 0xf8, 0xb3, 0xa6, 0x9f, 0x8b, 0x15, 0xb1, 0xe2, 0x06, 0x2b, 0x6e, 0xd6,
- 0x2a, 0x51, 0x40, 0xed, 0x22, 0x24, 0xbe, 0xd4, 0x24, 0xeb, 0x17, 0xee,
- 0xcf, 0x39, 0xe5, 0x8a, 0xc3, 0xcc, 0x62, 0x3b, 0xef, 0xb6, 0x69, 0x62,
- 0xfd, 0xb6, 0x13, 0x9a, 0xb1, 0x52, 0x79, 0x6e, 0x45, 0x7f, 0x6a, 0x00,
- 0x7e, 0xf8, 0xb1, 0x7f, 0xb8, 0x61, 0x4f, 0xdf, 0x65, 0x8a, 0x63, 0xe5,
- 0xf1, 0x85, 0xf7, 0x39, 0x20, 0x58, 0xa0, 0xb5, 0x5d, 0x31, 0x96, 0x61,
- 0x90, 0xe4, 0x38, 0xbb, 0x2f, 0x76, 0x2d, 0x18, 0x9d, 0xbb, 0xf0, 0xea,
- 0x67, 0xa2, 0x6b, 0x14, 0x21, 0x43, 0x21, 0xbf, 0xf6, 0x16, 0x1a, 0x59,
- 0xef, 0xba, 0xc5, 0xfc, 0xc6, 0xe0, 0xda, 0x0b, 0x15, 0xf3, 0xeb, 0x23,
- 0xdb, 0xf9, 0xc8, 0xb3, 0xa3, 0x2c, 0x5c, 0x67, 0x96, 0x2f, 0xef, 0xbe,
- 0x44, 0xc0, 0x58, 0xa8, 0x1e, 0x3f, 0x86, 0x6f, 0x6b, 0x4c, 0xb1, 0x7d,
- 0x00, 0x0a, 0x0b, 0x17, 0xda, 0x32, 0x40, 0xb1, 0x7a, 0x7f, 0x2b, 0x15,
- 0x27, 0xc8, 0xe4, 0x9f, 0x24, 0xbd, 0x0e, 0x74, 0x58, 0xbf, 0x1e, 0x4a,
- 0x1c, 0x58, 0xbe, 0x9f, 0x46, 0xe1, 0x45, 0x8b, 0xf3, 0x1c, 0x00, 0x95,
- 0x8b, 0xf4, 0x50, 0x9f, 0x71, 0x62, 0xb6, 0x3d, 0x2f, 0x14, 0x5f, 0x42,
- 0x4a, 0x0b, 0x15, 0x29, 0x85, 0xec, 0x41, 0x02, 0x87, 0x7e, 0x88, 0x8e,
- 0xf1, 0x1b, 0xf5, 0x8b, 0x0d, 0x62, 0xa4, 0xd8, 0x38, 0xf5, 0xcd, 0xda,
- 0xc5, 0xfd, 0xfc, 0x88, 0xa4, 0x6b, 0x17, 0xfd, 0x09, 0x3f, 0x33, 0x53,
- 0xc5, 0x8a, 0xdc, 0xf9, 0xfb, 0x2e, 0xbe, 0x88, 0x98, 0x35, 0x8b, 0xfe,
- 0x92, 0xce, 0x98, 0x4c, 0x6a, 0xc5, 0x1a, 0x7b, 0xba, 0x24, 0xb0, 0xd6,
- 0x28, 0x69, 0x9a, 0xbb, 0xfb, 0x42, 0x04, 0x44, 0x77, 0xbc, 0xe0, 0x58,
- 0xbe, 0x04, 0x96, 0xeb, 0x16, 0x0b, 0xac, 0x51, 0xa7, 0xad, 0xd8, 0xe8,
- 0x88, 0xef, 0xa1, 0xec, 0x31, 0x62, 0xfd, 0xe7, 0xfb, 0x1d, 0x62, 0xe9,
- 0x02, 0xc5, 0x49, 0xbf, 0xdc, 0xa2, 0xf6, 0xa4, 0xeb, 0x14, 0xe8, 0xd2,
- 0x63, 0x11, 0x31, 0x86, 0x43, 0x7e, 0xce, 0xfc, 0xc7, 0x58, 0xbb, 0x22,
- 0x58, 0xb6, 0xc4, 0x78, 0x26, 0x14, 0xde, 0x9d, 0x6c, 0xb1, 0x76, 0xd2,
- 0xb1, 0x52, 0x7b, 0xee, 0x52, 0x21, 0xea, 0x58, 0xbd, 0xbc, 0x81, 0x62,
- 0xc5, 0x03, 0x55, 0x81, 0x97, 0xfc, 0xc6, 0xf1, 0xfa, 0x49, 0x79, 0x62,
- 0xfe, 0xfb, 0x9f, 0x3e, 0xcb, 0x15, 0x28, 0x8d, 0x22, 0x51, 0x1d, 0xdf,
- 0x78, 0x9c, 0x22, 0xc5, 0xc2, 0xe2, 0xc5, 0xf6, 0x76, 0xd0, 0x58, 0xbf,
- 0xcf, 0xc7, 0x10, 0x5f, 0xee, 0xb1, 0x5c, 0x3d, 0xaf, 0x11, 0xdf, 0x85,
- 0x0e, 0x7c, 0x6b, 0x15, 0x28, 0xbe, 0x77, 0x22, 0x22, 0xbf, 0x64, 0x50,
- 0x6e, 0x2c, 0x54, 0x19, 0x19, 0xc3, 0x21, 0xed, 0xd1, 0xc8, 0xa2, 0x84,
- 0x0e, 0xa3, 0x38, 0x3b, 0xdf, 0xe3, 0x54, 0x28, 0xda, 0x79, 0x0d, 0xcf,
- 0x43, 0x90, 0x45, 0xdd, 0x21, 0xc4, 0x61, 0x6d, 0x99, 0x62, 0xc4, 0xb1,
- 0x7f, 0x34, 0x02, 0x04, 0x16, 0xcb, 0x17, 0xf7, 0x0c, 0x91, 0x85, 0xb0,
- 0xaa, 0xc5, 0xd9, 0xc5, 0x8b, 0x12, 0xc5, 0xd0, 0x8f, 0x58, 0xa8, 0x23,
- 0x4c, 0xe2, 0x3f, 0x11, 0x63, 0x42, 0x3a, 0xe0, 0xbf, 0x84, 0x6e, 0x04,
- 0x7a, 0xc5, 0xde, 0xe2, 0xc5, 0xb8, 0xb1, 0x7b, 0x46, 0x44, 0xb1, 0x7f,
- 0x71, 0xbb, 0xf3, 0xec, 0xb1, 0x51, 0x1f, 0x16, 0x84, 0xbc, 0x41, 0x4b,
- 0x14, 0xe6, 0xf2, 0x38, 0xc2, 0xfe, 0xcd, 0x87, 0xf7, 0xd2, 0xc5, 0x62,
- 0x64, 0x6e, 0x37, 0xf8, 0x5b, 0x11, 0x1d, 0xfc, 0xc5, 0xfe, 0xda, 0x3d,
- 0x62, 0xff, 0x84, 0x50, 0x2c, 0x04, 0x81, 0x62, 0xff, 0xd3, 0x9c, 0xeb,
- 0x2e, 0x33, 0x20, 0xb1, 0x7c, 0x19, 0x93, 0xb2, 0xc5, 0xf8, 0x3e, 0x6d,
- 0x81, 0xac, 0x54, 0x9e, 0x93, 0x93, 0x54, 0xa6, 0x39, 0xf3, 0x12, 0x38,
- 0xf4, 0x24, 0xee, 0x29, 0x58, 0xbc, 0x00, 0x4a, 0xc5, 0xd9, 0xba, 0xc5,
- 0xd2, 0x3e, 0x1b, 0x5f, 0x0e, 0xde, 0x92, 0xdd, 0x62, 0xff, 0xfe, 0x60,
- 0xc6, 0xcd, 0xad, 0xbe, 0xde, 0xfb, 0xea, 0x0b, 0x17, 0xed, 0xf7, 0xfc,
- 0xe9, 0x62, 0xbe, 0x8a, 0x52, 0x1d, 0x12, 0xed, 0x41, 0x38, 0xcd, 0xd0,
- 0x78, 0x97, 0xe8, 0x68, 0xdf, 0x31, 0x34, 0x4b, 0x17, 0xec, 0xd1, 0x9e,
- 0xe2, 0xc5, 0xf9, 0xfc, 0x59, 0x05, 0x8b, 0xd0, 0x78, 0xf5, 0x8b, 0xe9,
- 0x0e, 0x62, 0x58, 0xbf, 0xf7, 0x3a, 0x37, 0xe4, 0xdc, 0xf7, 0x16, 0x2e,
- 0x30, 0xeb, 0x17, 0xd9, 0xa1, 0x62, 0xc5, 0x80, 0xb1, 0x44, 0x6d, 0x0c,
- 0x22, 0xbe, 0xdb, 0x69, 0x8f, 0x58, 0xbc, 0xdd, 0x92, 0xc5, 0xfd, 0xe2,
- 0x60, 0x61, 0x2c, 0x5f, 0x89, 0x81, 0x84, 0xb1, 0x5d, 0x4f, 0x4b, 0xc5,
- 0x95, 0x28, 0xbb, 0x19, 0x40, 0x9b, 0xef, 0x45, 0x31, 0xeb, 0x15, 0xb2,
- 0xa7, 0x28, 0x11, 0x1a, 0x55, 0xd9, 0x3b, 0x90, 0x44, 0x49, 0xf4, 0x20,
- 0x26, 0x94, 0x37, 0x38, 0x5f, 0x61, 0xac, 0x5e, 0xc2, 0xdd, 0x62, 0x98,
- 0xd7, 0xf0, 0x4a, 0xfd, 0xc8, 0xa1, 0x3d, 0xac, 0x5f, 0x7b, 0x71, 0x6c,
- 0xb1, 0x69, 0xf9, 0xe8, 0x91, 0x5d, 0xfb, 0x37, 0xf6, 0x6e, 0xb1, 0x6e,
- 0x2c, 0x5f, 0xc1, 0x8c, 0x4d, 0xa8, 0x2c, 0x52, 0xc5, 0x49, 0xbc, 0x30,
- 0xc2, 0xf7, 0x26, 0x0b, 0x17, 0xef, 0xe6, 0x9f, 0x8b, 0x17, 0x3e, 0xbb,
- 0x3c, 0x5f, 0x0e, 0xdf, 0xcf, 0xa7, 0xe4, 0xec, 0xb1, 0x6e, 0x8b, 0x15,
- 0x29, 0xf2, 0xc1, 0xc7, 0x09, 0xa2, 0x2a, 0xd2, 0x77, 0xd9, 0xb8, 0x5c,
- 0x10, 0xba, 0xfe, 0xfc, 0x94, 0x1f, 0x65, 0x8b, 0x87, 0x2b, 0x17, 0xfe,
- 0xfe, 0x43, 0xd3, 0x85, 0xdf, 0x96, 0x2b, 0x0f, 0x5b, 0xc2, 0xf7, 0xf9,
- 0xf6, 0x26, 0xd8, 0x5c, 0x58, 0xb1, 0x8b, 0x14, 0xe8, 0xed, 0x28, 0x42,
- 0x78, 0x84, 0x21, 0xad, 0xf1, 0xfd, 0x9b, 0xac, 0x5e, 0x27, 0x35, 0x62,
- 0xfb, 0x06, 0xfd, 0x16, 0x2e, 0x93, 0xe1, 0xe0, 0xb0, 0xed, 0xfa, 0x1e,
- 0x73, 0xf9, 0x62, 0xfe, 0x6e, 0xff, 0x26, 0x12, 0xc5, 0xb3, 0xb3, 0xd8,
- 0x0c, 0xa6, 0xf1, 0x9d, 0x92, 0xc5, 0xfc, 0xd0, 0x62, 0xc0, 0x8b, 0x17,
- 0x38, 0xd6, 0x2f, 0xb9, 0xf6, 0x82, 0xc5, 0xbc, 0xb1, 0x52, 0x9f, 0x60,
- 0xd0, 0x9d, 0x97, 0x50, 0x83, 0xf9, 0x4b, 0x0f, 0x80, 0xb8, 0x42, 0xe6,
- 0x11, 0xdc, 0x51, 0x2c, 0x58, 0xd5, 0x8a, 0xc3, 0x57, 0xa1, 0x8b, 0x76,
- 0xb1, 0x61, 0x2c, 0x5c, 0x09, 0x48, 0xb8, 0x30, 0xd2, 0x29, 0xcd, 0x88,
- 0x62, 0xf7, 0xe2, 0xcf, 0x7d, 0xd2, 0x23, 0x0d, 0x0d, 0xe2, 0xce, 0x2c,
- 0x5d, 0x83, 0x58, 0xa3, 0x4d, 0x9f, 0x41, 0xca, 0x82, 0x24, 0x46, 0xdb,
- 0x76, 0xe0, 0x58, 0xbf, 0xcc, 0x6c, 0x91, 0x67, 0x96, 0x2f, 0xce, 0x39,
- 0xc2, 0x58, 0xbe, 0x2f, 0x3e, 0xcb, 0x17, 0x01, 0x96, 0x2f, 0x9f, 0x4f,
- 0xe5, 0x8a, 0x93, 0xdc, 0x72, 0x38, 0x85, 0xea, 0x55, 0x23, 0x0c, 0x83,
- 0xb1, 0x36, 0x87, 0xa8, 0x08, 0xc8, 0x67, 0x86, 0x42, 0x84, 0x15, 0xef,
- 0xc8, 0x6b, 0x17, 0x9b, 0xbe, 0x2c, 0x52, 0xc5, 0xd3, 0xf5, 0x8a, 0xe1,
- 0xa3, 0xf0, 0x65, 0xf1, 0x0e, 0x46, 0xb1, 0x7c, 0x67, 0xdb, 0xcb, 0x17,
- 0xe3, 0x3c, 0x52, 0x05, 0x8a, 0xd9, 0x1d, 0xe3, 0x1e, 0xed, 0x05, 0xc8,
- 0x7c, 0x45, 0xd0, 0x92, 0xfb, 0xf2, 0x23, 0x16, 0x2d, 0xa5, 0x8b, 0xd2,
- 0x51, 0x2c, 0x5b, 0xa2, 0xc5, 0x2c, 0x5a, 0x56, 0x2b, 0x0d, 0x88, 0x05,
- 0x08, 0x32, 0x96, 0x29, 0x62, 0xa2, 0x2e, 0x0e, 0x19, 0x77, 0xe2, 0x58,
- 0xb9, 0xc0, 0xb1, 0x52, 0x6c, 0x00, 0x33, 0x5b, 0x26, 0x73, 0x84, 0x91,
- 0x09, 0x69, 0x39, 0x91, 0x00, 0xa3, 0x7d, 0x0d, 0x37, 0x45, 0x8b, 0x05,
- 0xd6, 0x2f, 0xfe, 0x35, 0xcb, 0x7e, 0x49, 0xdb, 0xbf, 0x2c, 0x5e, 0x06,
- 0x04, 0x58, 0xbf, 0xfe, 0x2c, 0x06, 0x1c, 0x53, 0xad, 0x38, 0xb7, 0x58,
- 0xbe, 0x29, 0x3c, 0x4b, 0x15, 0x29, 0x8a, 0x6c, 0x4a, 0x68, 0xb6, 0x91,
- 0xc8, 0x7f, 0xca, 0x17, 0xc7, 0xe0, 0x8e, 0xb1, 0x63, 0x56, 0x2d, 0x1c,
- 0xb1, 0x76, 0x8d, 0x58, 0xa9, 0x3e, 0x57, 0x24, 0x10, 0x99, 0x82, 0xb7,
- 0xd3, 0x1d, 0x9d, 0xac, 0x5f, 0xfe, 0xc8, 0x72, 0x7d, 0x0c, 0x8f, 0x62,
- 0x02, 0xc5, 0xf1, 0xac, 0x40, 0x58, 0xaf, 0x9f, 0x78, 0x93, 0x2f, 0xf9,
- 0xfd, 0xfc, 0xef, 0xc2, 0x95, 0x8b, 0xe3, 0x27, 0x40, 0x58, 0xa8, 0x1e,
- 0xf7, 0xce, 0xae, 0xce, 0x2c, 0x5f, 0xfe, 0xc8, 0x47, 0x61, 0xad, 0x9e,
- 0x9f, 0x71, 0x62, 0xa5, 0x10, 0xd0, 0x22, 0x00, 0xbd, 0x71, 0x33, 0x5f,
- 0x46, 0x0d, 0x74, 0xf1, 0x62, 0xc0, 0x58, 0xbe, 0x93, 0xc9, 0xd6, 0x2f,
- 0xce, 0x19, 0xdb, 0xcb, 0x14, 0xe7, 0x97, 0xa2, 0x2b, 0xed, 0xff, 0x3c,
- 0x58, 0xb6, 0x2c, 0x54, 0x15, 0x5f, 0x3c, 0x79, 0x5a, 0x2a, 0x61, 0x7e,
- 0x2e, 0x86, 0x43, 0x1c, 0x49, 0x73, 0x6c, 0xb1, 0x6f, 0x2c, 0x57, 0x0d,
- 0x50, 0x63, 0x17, 0xfc, 0x3c, 0x1c, 0x64, 0x5b, 0x88, 0x96, 0x2c, 0x6a,
- 0xc5, 0x4a, 0xfe, 0x0e, 0x47, 0x26, 0xf1, 0xb6, 0x7e, 0x17, 0xad, 0x2b,
- 0xe4, 0x50, 0x98, 0x30, 0x88, 0x21, 0xfd, 0x80, 0xb1, 0x7d, 0x21, 0x8a,
- 0x25, 0x8b, 0xdc, 0x98, 0x96, 0x2f, 0xb3, 0xa3, 0xe9, 0x62, 0xe7, 0x3a,
- 0xc5, 0xb0, 0x66, 0xec, 0xe4, 0x97, 0xd1, 0x44, 0xff, 0x58, 0xa5, 0x8b,
- 0x69, 0x62, 0xc7, 0x58, 0xae, 0x1e, 0xaf, 0x89, 0x44, 0x19, 0xd0, 0x4a,
- 0xf8, 0x6c, 0xdd, 0xac, 0x5f, 0x80, 0xfa, 0x73, 0x56, 0x2e, 0xe7, 0x96,
- 0x2c, 0x6a, 0xc5, 0x49, 0xab, 0x61, 0x8b, 0xb3, 0xb5, 0x8a, 0x35, 0x3f,
- 0x7d, 0xc4, 0xa2, 0x25, 0x3a, 0xcf, 0xde, 0xd8, 0xf8, 0x04, 0x64, 0xa9,
- 0x1c, 0x3f, 0x6f, 0xac, 0x5f, 0x0f, 0xf3, 0xb2, 0xc5, 0x61, 0xb6, 0xdc,
- 0x4a, 0xf6, 0x68, 0xd5, 0x8b, 0xf8, 0xbd, 0x84, 0xe1, 0xac, 0x5f, 0xde,
- 0xe6, 0x1d, 0xfc, 0xb1, 0x6d, 0x2c, 0x54, 0x9e, 0x06, 0x17, 0x52, 0xc5,
- 0x2c, 0x5a, 0x56, 0x28, 0x2e, 0x6a, 0x48, 0x33, 0xc1, 0x97, 0xb3, 0xa3,
- 0x2c, 0x5f, 0x7f, 0xf8, 0x05, 0x8b, 0x4f, 0xcf, 0x04, 0xc1, 0xeb, 0x6c,
- 0xb1, 0x52, 0x9d, 0x16, 0x10, 0xb8, 0xf1, 0xdb, 0x59, 0x24, 0x0e, 0x41,
- 0x72, 0x8b, 0xfb, 0xd9, 0xdc, 0x26, 0x0b, 0x17, 0xef, 0x67, 0xd8, 0xd5,
- 0x8a, 0xec, 0xf6, 0x1c, 0xbe, 0xfd, 0xd8, 0x02, 0x82, 0xe2, 0xc5, 0xef,
- 0xb1, 0xd6, 0x2e, 0x9e, 0x2c, 0x5f, 0xcd, 0xe0, 0x18, 0x50, 0x58, 0xbf,
- 0x73, 0x34, 0xe6, 0xac, 0x50, 0xd1, 0x19, 0xd8, 0xec, 0x78, 0xbf, 0x8b,
- 0xee, 0x8f, 0x89, 0x62, 0xfe, 0xf0, 0xdc, 0x12, 0x4b, 0x17, 0xb6, 0xfb,
- 0xac, 0x5d, 0xf1, 0x76, 0x79, 0x6c, 0x5b, 0x6f, 0xac, 0x5e, 0x0c, 0x30,
- 0xd2, 0x2f, 0xf4, 0xec, 0x66, 0x7d, 0xbb, 0x48, 0x8c, 0x34, 0x37, 0xf9,
- 0xc6, 0xc5, 0xdc, 0x38, 0xb1, 0x43, 0x3f, 0xdf, 0xa4, 0xdf, 0xbf, 0x3f,
- 0x73, 0x56, 0x2d, 0xb2, 0xc5, 0x40, 0xde, 0x61, 0x4d, 0xf8, 0xe6, 0x4e,
- 0x80, 0xb1, 0x4b, 0x14, 0xb1, 0x69, 0x39, 0x70, 0x00, 0xca, 0x93, 0xe7,
- 0x82, 0x15, 0xe7, 0xcd, 0xd6, 0x2e, 0x17, 0x6b, 0x17, 0xfa, 0x1f, 0xcc,
- 0x28, 0x71, 0x62, 0xe6, 0x35, 0x62, 0xf6, 0xa1, 0x12, 0xc5, 0x49, 0xf5,
- 0x31, 0x98, 0x86, 0x2b, 0xe8, 0xb0, 0xe4, 0x20, 0xef, 0xe6, 0xf6, 0xb5,
- 0x9b, 0x2c, 0x54, 0xab, 0x6f, 0x1b, 0x3e, 0x17, 0x6f, 0x0b, 0x07, 0x5e,
- 0x8a, 0x10, 0xfc, 0x21, 0xf4, 0x33, 0x43, 0x28, 0xbd, 0x27, 0x75, 0x8b,
- 0xd0, 0xcd, 0xd6, 0x29, 0x62, 0xe7, 0x3a, 0xc5, 0xa7, 0x63, 0x46, 0x30,
- 0xcb, 0x4a, 0xc5, 0xfe, 0xe7, 0xf3, 0x9e, 0x7d, 0x96, 0x2e, 0xe3, 0x2c,
- 0x54, 0x68, 0xbb, 0xb7, 0x30, 0xbb, 0xc9, 0x76, 0x1b, 0xc2, 0x3f, 0xb1,
- 0xc7, 0x41, 0x88, 0x9d, 0x84, 0x7c, 0x6b, 0x7d, 0x09, 0x07, 0x16, 0x2f,
- 0xe8, 0x4f, 0x47, 0x20, 0x2c, 0x5b, 0x58, 0x7a, 0x46, 0x11, 0xde, 0xd0,
- 0x41, 0xac, 0x5b, 0xeb, 0x15, 0x27, 0xb4, 0xe5, 0x01, 0x08, 0x2f, 0xfa,
- 0x7b, 0xfe, 0x44, 0xc5, 0xb2, 0xc5, 0xfc, 0xc1, 0xf7, 0x0c, 0xf2, 0xc5,
- 0x7c, 0xfa, 0xc8, 0xee, 0xff, 0xe7, 0xe8, 0x59, 0xce, 0xe1, 0x9e, 0x25,
- 0x8b, 0xff, 0xda, 0x35, 0xb5, 0xa1, 0x1b, 0x9b, 0xc8, 0x16, 0x2f, 0xe6,
- 0x87, 0xbd, 0x27, 0x58, 0xbf, 0x7e, 0x7b, 0x68, 0xf5, 0x8b, 0xff, 0xe9,
- 0xf7, 0x07, 0x9e, 0x7f, 0x8b, 0x3b, 0xf2, 0xc5, 0x41, 0x33, 0xf7, 0x46,
- 0xd2, 0x77, 0xcb, 0xbc, 0x59, 0x78, 0xb3, 0xeb, 0x16, 0xd2, 0xc5, 0xff,
- 0x38, 0xcc, 0xf7, 0x7b, 0xb9, 0xd6, 0x2f, 0xec, 0xdc, 0xce, 0x9f, 0xc5,
- 0x8a, 0x81, 0xf7, 0xe1, 0xed, 0xff, 0x49, 0x78, 0xb3, 0xd2, 0x1a, 0xc5,
- 0x83, 0x58, 0xbf, 0x83, 0xe3, 0x97, 0x70, 0x58, 0xbe, 0xdb, 0xd9, 0xf5,
- 0x8a, 0x93, 0xe7, 0xc1, 0x31, 0x18, 0x52, 0xc5, 0x3a, 0x36, 0x35, 0x09,
- 0xf6, 0x2d, 0xbe, 0xe7, 0x99, 0xd6, 0x2f, 0xd1, 0x00, 0xf9, 0x12, 0xc5,
- 0xff, 0xa4, 0x87, 0x9b, 0x61, 0x67, 0x6b, 0x17, 0x7e, 0x56, 0x2b, 0x73,
- 0xd5, 0xf1, 0xf5, 0x62, 0x28, 0xda, 0x10, 0x17, 0x0a, 0x0b, 0x17, 0xde,
- 0xe4, 0x81, 0x62, 0xed, 0x09, 0x62, 0xb0, 0xdd, 0xf8, 0x8e, 0xdc, 0x58,
- 0xad, 0x91, 0x0a, 0x4a, 0x62, 0x20, 0xbf, 0xcd, 0xd3, 0x07, 0xb6, 0x06,
- 0xb1, 0x7f, 0xfa, 0x73, 0xb3, 0x3c, 0xe4, 0x28, 0x67, 0x16, 0x2f, 0x10,
- 0xb6, 0x58, 0xbf, 0xdc, 0x93, 0xf7, 0x0c, 0xf2, 0xc5, 0xe9, 0xcd, 0x96,
- 0x2d, 0x83, 0x45, 0xde, 0xe9, 0x7e, 0x1e, 0xe8, 0x6b, 0x7d, 0x9f, 0x33,
- 0x4b, 0x17, 0x76, 0x1a, 0xc5, 0xd2, 0x1a, 0xc5, 0xc7, 0x02, 0xc5, 0xcc,
- 0x4b, 0x15, 0x27, 0xc0, 0xe3, 0x5f, 0x18, 0x61, 0x8b, 0x9c, 0xd5, 0x8b,
- 0xe1, 0x41, 0x86, 0xb1, 0x7c, 0xfe, 0x03, 0x2c, 0x5f, 0xa7, 0xb8, 0x61,
- 0xd6, 0x2a, 0x08, 0x86, 0xd0, 0xc1, 0xc8, 0xfe, 0x45, 0x7b, 0xe2, 0x25,
- 0x8b, 0xee, 0x49, 0x1a, 0xb1, 0x5b, 0x32, 0x29, 0x07, 0x09, 0xac, 0x8d,
- 0x81, 0xd2, 0xa3, 0xc7, 0x22, 0x84, 0x0e, 0xa1, 0xf2, 0x73, 0x3f, 0xc3,
- 0x15, 0xa1, 0x56, 0x03, 0x02, 0x87, 0x97, 0x11, 0x7d, 0x08, 0x41, 0x42,
- 0xff, 0xa1, 0xe9, 0x83, 0xb7, 0x68, 0xd5, 0x8b, 0xe9, 0x3b, 0x7d, 0x62,
- 0xf7, 0xbc, 0xcb, 0x17, 0xda, 0x14, 0xf4, 0x58, 0xbc, 0xc4, 0x01, 0x9f,
- 0x23, 0x11, 0x78, 0x76, 0xfe, 0xe1, 0x66, 0xc6, 0x41, 0x62, 0xd9, 0x1e,
- 0x7d, 0xc0, 0x3e, 0xbf, 0x8f, 0x14, 0x24, 0xbc, 0xb1, 0x74, 0x81, 0x62,
- 0xf7, 0x9f, 0x65, 0x8a, 0xc3, 0xe4, 0x88, 0xbf, 0xe2, 0xf7, 0xfb, 0x77,
- 0xe1, 0x67, 0x46, 0x58, 0xbe, 0x9d, 0x9a, 0x0b, 0x17, 0x00, 0xeb, 0x17,
- 0xb9, 0xf7, 0x58, 0xad, 0x1b, 0x5f, 0x0c, 0x5f, 0xc4, 0xde, 0xdb, 0x03,
- 0x58, 0xa5, 0x8a, 0x23, 0x77, 0xe2, 0xfa, 0x93, 0xfc, 0xc5, 0xcb, 0xed,
- 0x8b, 0x3b, 0x58, 0xbf, 0x81, 0xcc, 0x1b, 0x41, 0x62, 0xb0, 0xf4, 0x98,
- 0x92, 0xff, 0xa0, 0x36, 0x07, 0xa7, 0xbf, 0x2c, 0x5f, 0xd9, 0xef, 0xb9,
- 0x01, 0x62, 0xf3, 0x97, 0x16, 0x2f, 0x79, 0xf6, 0x58, 0xa2, 0x3e, 0x7f,
- 0x16, 0xf4, 0x1c, 0xbe, 0xeb, 0x9d, 0xf9, 0x62, 0xfe, 0xe4, 0xf7, 0x0c,
- 0xf2, 0xc5, 0x6e, 0x7a, 0xbc, 0x26, 0xbe, 0xcf, 0x3f, 0x16, 0x29, 0x62,
- 0xbb, 0x35, 0xcc, 0x45, 0x52, 0x9c, 0xce, 0x42, 0x89, 0xe1, 0x0a, 0xca,
- 0x37, 0x4f, 0x96, 0x2e, 0xf8, 0x16, 0x2a, 0x57, 0x53, 0xe1, 0x0e, 0xbc,
- 0x84, 0x77, 0x65, 0xfa, 0x35, 0xfc, 0x35, 0x09, 0xcb, 0x91, 0xdc, 0xf9,
- 0x10, 0x42, 0xf4, 0xb1, 0x7c, 0xc5, 0x20, 0x58, 0xb8, 0x46, 0x2c, 0x54,
- 0x47, 0x8d, 0xa0, 0xc3, 0x08, 0x6e, 0x78, 0xf5, 0x8b, 0x71, 0x62, 0x88,
- 0xd6, 0x78, 0x6a, 0xfe, 0xfc, 0xfb, 0x9f, 0x75, 0x8b, 0x98, 0xd5, 0x8b,
- 0x0f, 0xc7, 0x8d, 0x1c, 0x5d, 0x7b, 0xbe, 0x0d, 0x62, 0xa5, 0x16, 0x18,
- 0xcc, 0xe5, 0x76, 0x8e, 0x58, 0xba, 0x46, 0xb1, 0x41, 0x53, 0x59, 0xf1,
- 0x5b, 0x98, 0xeb, 0x16, 0x35, 0x62, 0xdc, 0x58, 0xb1, 0xd6, 0x2d, 0xa5,
- 0x8a, 0x63, 0x48, 0x21, 0x2a, 0x73, 0xe9, 0xd0, 0x9f, 0xcd, 0xaf, 0x19,
- 0xdf, 0x96, 0x2f, 0xc3, 0xd3, 0x8b, 0x65, 0x8b, 0x1a, 0xb1, 0x5b, 0x1b,
- 0xdd, 0x15, 0x5f, 0xe6, 0x0f, 0xdd, 0xee, 0xfa, 0x58, 0xb1, 0x8b, 0x16,
- 0x02, 0xc5, 0x2c, 0x0d, 0x38, 0x97, 0x84, 0x07, 0xcb, 0x99, 0x74, 0x88,
- 0x84, 0x6f, 0x1c, 0x27, 0x7f, 0x14, 0x18, 0xf8, 0x35, 0x8b, 0xb0, 0x0b,
- 0x15, 0x27, 0x88, 0x45, 0xb7, 0xde, 0x39, 0xf4, 0xb1, 0x7f, 0xf0, 0x24,
- 0xb7, 0x6f, 0x00, 0xc2, 0x82, 0xc5, 0xe8, 0x3f, 0xd6, 0x2f, 0x3e, 0x12,
- 0xc5, 0xe2, 0xc8, 0x2c, 0x56, 0x8d, 0xbf, 0x86, 0xef, 0xdb, 0x68, 0x4d,
- 0xc5, 0x8b, 0xe1, 0x05, 0xf8, 0xcb, 0x17, 0xff, 0x7a, 0x12, 0x69, 0x9e,
- 0xf8, 0x9b, 0x65, 0x8b, 0xdf, 0xce, 0x2c, 0x5e, 0x66, 0x0d, 0x62, 0xfb,
- 0x4e, 0x0e, 0x2c, 0x5b, 0x61, 0x9e, 0x07, 0x07, 0x6b, 0x11, 0xec, 0xc4,
- 0xfe, 0x49, 0x12, 0xed, 0xff, 0xdc, 0xfe, 0x0c, 0xb3, 0xa1, 0x67, 0x16,
- 0x2f, 0xa6, 0x10, 0x3a, 0xc5, 0xe6, 0x8b, 0x8b, 0x14, 0xe8, 0x86, 0x24,
- 0x5f, 0x11, 0xd4, 0x15, 0x87, 0x1a, 0x41, 0xd9, 0x24, 0x48, 0xda, 0x54,
- 0x62, 0x12, 0x8c, 0x83, 0xd0, 0xc1, 0xb0, 0x6b, 0x16, 0xdd, 0x62, 0xa2,
- 0x34, 0xc6, 0x09, 0xd4, 0x6e, 0xfa, 0xe2, 0xc1, 0x42, 0xc8, 0xd9, 0x50,
- 0x2c, 0x5d, 0x8d, 0x6d, 0xd3, 0x2f, 0x03, 0x68, 0xff, 0x21, 0x19, 0x68,
- 0xe7, 0x5e, 0x72, 0x94, 0x02, 0x6c, 0x77, 0xfb, 0xc7, 0x0b, 0xdc, 0xae,
- 0x87, 0x95, 0x6d, 0x14, 0xaa, 0x8d, 0x4b, 0x4c, 0x3c, 0xaf, 0x3f, 0xd2,
- 0x4a, 0xda, 0x54, 0x38, 0x25, 0x2d, 0x85, 0xe1, 0x7a, 0x53, 0xbf, 0xbc,
- 0xa4, 0xf3, 0x7a, 0x79, 0xac, 0x50, 0xe7, 0xe9, 0x18, 0x68, 0x6b, 0x31,
- 0xd1, 0xd7, 0x19, 0x2f, 0x10, 0x24, 0x29, 0x6f, 0xf7, 0xe4, 0xbc, 0x59,
- 0xb2, 0xc5, 0xfc, 0xf8, 0x13, 0x82, 0x95, 0x8b, 0xec, 0x29, 0x82, 0xc5,
- 0xa3, 0x06, 0x88, 0x3f, 0x19, 0x98, 0x5f, 0x78, 0x06, 0x41, 0x62, 0xff,
- 0xfb, 0x8f, 0xf6, 0x7f, 0x66, 0x80, 0x76, 0x82, 0xc5, 0xa3, 0x3b, 0x3e,
- 0xef, 0x0f, 0xdf, 0x74, 0x91, 0x6e, 0xb1, 0x7f, 0xd2, 0x20, 0xbf, 0x36,
- 0x3b, 0x6c, 0xb1, 0x7f, 0x80, 0x61, 0x42, 0x78, 0xcb, 0x17, 0x72, 0x32,
- 0x51, 0x34, 0x32, 0x6f, 0x20, 0x58, 0x52, 0x98, 0x27, 0xa1, 0x8d, 0x51,
- 0x8b, 0x97, 0xdb, 0x4a, 0xe4, 0x1c, 0x75, 0x97, 0xed, 0x6e, 0xcd, 0xba,
- 0xa2, 0xb7, 0x2f, 0xfc, 0xd0, 0x8c, 0xcd, 0x6e, 0xcd, 0xba, 0xa2, 0x70,
- 0x2d, 0x19, 0x88, 0x87, 0x39, 0xbd, 0x2c, 0x5c, 0xc3, 0x58, 0xb4, 0x6c,
- 0x33, 0x47, 0xe0, 0xcb, 0x7d, 0x62, 0xdc, 0x58, 0xa1, 0x1a, 0x48, 0xe1,
- 0x2b, 0xf6, 0x07, 0xc7, 0x0d, 0x62, 0xee, 0x71, 0x62, 0xfd, 0xd0, 0x78,
- 0x5b, 0x2c, 0x54, 0x0f, 0x0d, 0xc6, 0x2e, 0x0a, 0x71, 0x62, 0xff, 0x9c,
- 0xd3, 0x5b, 0xee, 0x36, 0x58, 0xbe, 0xdd, 0x9b, 0x75, 0x45, 0xa2, 0x5f,
- 0x7c, 0x9a, 0x3d, 0x62, 0xff, 0xe1, 0xfd, 0x8d, 0x8a, 0x27, 0xe0, 0x8e,
- 0xb1, 0x52, 0x7d, 0xd8, 0x4b, 0x7e, 0xcf, 0xee, 0xfc, 0x58, 0xbf, 0xb6,
- 0xfe, 0x68, 0x5b, 0xac, 0x5f, 0xff, 0xf1, 0x00, 0xb3, 0xdf, 0xce, 0xa0,
- 0x26, 0xf7, 0xda, 0x2e, 0x2c, 0x54, 0xa2, 0x65, 0xcc, 0x6f, 0xe6, 0xee,
- 0x7d, 0x23, 0x58, 0xa0, 0xb1, 0x51, 0x34, 0x07, 0x34, 0x75, 0xf8, 0x4f,
- 0x91, 0x07, 0x21, 0x85, 0xd0, 0x86, 0xff, 0xff, 0xe1, 0xf3, 0xec, 0x59,
- 0xb9, 0x0b, 0x63, 0xcf, 0x7e, 0xc1, 0x96, 0x2c, 0x5e, 0x72, 0xdd, 0x62,
- 0xf3, 0x10, 0x16, 0x2a, 0x51, 0x59, 0x8e, 0x7b, 0x8e, 0xdf, 0x02, 0x4b,
- 0x75, 0x8b, 0xf6, 0x6f, 0xec, 0xdd, 0x62, 0xf7, 0x49, 0x89, 0x62, 0xff,
- 0x64, 0x7f, 0x35, 0xa6, 0xf2, 0xc5, 0xfd, 0x3b, 0x37, 0xd8, 0xeb, 0x17,
- 0xe9, 0x00, 0x98, 0xc5, 0x8a, 0xc4, 0x6c, 0x39, 0x54, 0x44, 0x1f, 0x37,
- 0x22, 0xeb, 0xfa, 0x7d, 0x85, 0xbe, 0x2c, 0x5b, 0x8b, 0x14, 0xe6, 0xff,
- 0xe5, 0xb7, 0xe6, 0x21, 0x0f, 0x16, 0x2f, 0xd9, 0xed, 0xdf, 0x8b, 0x15,
- 0x27, 0xa0, 0x44, 0xf7, 0x85, 0xee, 0x2c, 0x5f, 0x87, 0xf6, 0x2f, 0x2c,
- 0x5f, 0x45, 0x86, 0x8d, 0x62, 0x86, 0x7d, 0x78, 0x3d, 0xe2, 0x8b, 0xff,
- 0x4c, 0xf7, 0xec, 0xff, 0xf2, 0x25, 0x8a, 0xd1, 0xf7, 0x70, 0xba, 0xff,
- 0xa7, 0x6f, 0xe7, 0x3f, 0x91, 0xeb, 0x17, 0xed, 0xf1, 0xcb, 0x75, 0x8b,
- 0xfd, 0x9b, 0x94, 0x83, 0x92, 0xb1, 0x74, 0xef, 0xd4, 0xf7, 0x38, 0x53,
- 0x7f, 0xdd, 0x39, 0x9f, 0xc2, 0x30, 0x6b, 0x15, 0x27, 0xd9, 0x86, 0x15,
- 0xf4, 0xc9, 0x4a, 0x30, 0x5b, 0xfd, 0x9a, 0x06, 0x44, 0x67, 0x16, 0x2c,
- 0x6a, 0xc5, 0xff, 0x64, 0xed, 0x91, 0x69, 0xf8, 0xb1, 0x4e, 0x79, 0xb1,
- 0x09, 0xdf, 0xff, 0xb6, 0x9f, 0x48, 0xf5, 0x3f, 0x6e, 0x16, 0x01, 0x62,
- 0xff, 0xd3, 0xdb, 0x47, 0xfc, 0x9a, 0x3f, 0x65, 0x8b, 0xff, 0x4e, 0x81,
- 0x8f, 0x9a, 0xf0, 0x96, 0x2a, 0x51, 0xb3, 0xf5, 0x5e, 0x23, 0x50, 0xd3,
- 0xd6, 0x72, 0x98, 0xa1, 0x07, 0xc8, 0x7d, 0xdf, 0xd3, 0xd0, 0x9b, 0xdc,
- 0x58, 0xbf, 0xfe, 0xf4, 0x8f, 0xe2, 0x63, 0x77, 0xc7, 0x2d, 0xd6, 0x2f,
- 0xfd, 0xcf, 0xe0, 0x22, 0xe1, 0x37, 0xd6, 0x2f, 0x8e, 0xe5, 0x05, 0x8a,
- 0x74, 0x5a, 0x47, 0xa9, 0x71, 0x02, 0xa5, 0x71, 0xeb, 0x25, 0x8e, 0xfd,
- 0x21, 0xa1, 0xc7, 0x6e, 0x8b, 0x17, 0x4f, 0xd6, 0x2e, 0xe1, 0xd6, 0x29,
- 0xcf, 0x0e, 0x21, 0x4f, 0x8b, 0xd2, 0xc5, 0x8d, 0x58, 0xbd, 0xa9, 0x35,
- 0x62, 0xfc, 0xfe, 0x29, 0x3a, 0xc5, 0x46, 0xe7, 0xc9, 0x21, 0x91, 0x09,
- 0xfc, 0x7a, 0xff, 0x0e, 0x48, 0xb3, 0x36, 0x58, 0xbf, 0x8f, 0xad, 0x38,
- 0x38, 0xb1, 0x7f, 0xd2, 0x5e, 0xc8, 0x49, 0x79, 0x62, 0xa4, 0xf9, 0xa0,
- 0x5f, 0x7b, 0x7c, 0x0d, 0x62, 0xa2, 0x3c, 0x0f, 0x90, 0xd4, 0xa3, 0xef,
- 0x21, 0xb1, 0x7f, 0xfc, 0xfe, 0xe3, 0xee, 0xda, 0xdf, 0x1c, 0xb7, 0x58,
- 0xb0, 0x6b, 0x17, 0xfb, 0x53, 0xee, 0xe1, 0x9e, 0x58, 0xbf, 0xff, 0xb2,
- 0x26, 0x2d, 0x80, 0xfd, 0xf3, 0x7c, 0x72, 0xdd, 0x62, 0xec, 0x1a, 0xc5,
- 0xed, 0x98, 0xeb, 0x17, 0x03, 0x52, 0x6d, 0x5c, 0x5e, 0xfd, 0xa3, 0xce,
- 0x71, 0x62, 0xa4, 0xf4, 0xf0, 0xae, 0xff, 0xee, 0xf9, 0xe2, 0xce, 0x9e,
- 0xf3, 0x8d, 0x62, 0xfb, 0x9b, 0x0b, 0x8b, 0x15, 0x05, 0x41, 0x8e, 0xa3,
- 0x10, 0x99, 0x1a, 0xf2, 0x1c, 0xc2, 0x20, 0x31, 0x22, 0xd0, 0x58, 0xb4,
- 0x16, 0x2f, 0x11, 0x86, 0xac, 0x56, 0xe7, 0x86, 0xe2, 0x51, 0x09, 0x5f,
- 0xd9, 0xd3, 0xc2, 0x9d, 0xd6, 0x2f, 0xf7, 0xfe, 0x23, 0x4f, 0x3c, 0x58,
- 0xbe, 0x87, 0xcc, 0xe2, 0xc5, 0xf4, 0xf4, 0x9d, 0x2c, 0x57, 0x53, 0xc9,
- 0xd8, 0x96, 0xe3, 0x46, 0xb1, 0x7f, 0xfd, 0xc2, 0xce, 0x8d, 0xe2, 0xce,
- 0x7d, 0xa2, 0x58, 0xac, 0x3e, 0xa7, 0x19, 0xbb, 0xe7, 0x58, 0xbf, 0x4f,
- 0xb8, 0x67, 0xd6, 0x2a, 0x53, 0xd1, 0x19, 0x86, 0x18, 0xbb, 0xfc, 0x50,
- 0x8f, 0x39, 0x01, 0x0c, 0x5f, 0xff, 0xde, 0xff, 0x5c, 0x84, 0x83, 0x85,
- 0x91, 0x42, 0x7b, 0x58, 0xbc, 0xfd, 0xc1, 0x62, 0xbe, 0x7f, 0xa4, 0xbf,
- 0x63, 0xac, 0x5e, 0x03, 0x7d, 0x62, 0xff, 0x6d, 0x8e, 0x36, 0x63, 0x56,
- 0x28, 0x67, 0xc7, 0x82, 0x4c, 0x3b, 0x7f, 0x6a, 0x47, 0x25, 0x12, 0xc5,
- 0xb8, 0xb1, 0x5b, 0x1e, 0x07, 0xcb, 0xa8, 0x2a, 0xda, 0x71, 0x46, 0x8a,
- 0x1b, 0x12, 0x0d, 0xb7, 0x25, 0x23, 0xef, 0x19, 0x17, 0x65, 0xf1, 0x43,
- 0xef, 0x50, 0x87, 0x3b, 0x87, 0xe7, 0x5c, 0xda, 0x11, 0x80, 0x84, 0x99,
- 0x46, 0x79, 0xc9, 0x46, 0x5e, 0x94, 0xfe, 0x28, 0x72, 0x47, 0x42, 0x10,
- 0xc6, 0xdb, 0xfe, 0xc8, 0xa0, 0xda, 0xdb, 0xe2, 0x58, 0xbd, 0xb4, 0xee,
- 0xb1, 0x68, 0xc1, 0x9e, 0xdb, 0x9e, 0x54, 0x62, 0x7b, 0xe2, 0x8e, 0xd6,
- 0xf7, 0x0f, 0xc5, 0x8b, 0xfc, 0x15, 0x97, 0xf4, 0x33, 0x8b, 0x17, 0xff,
- 0xcf, 0xe7, 0xd3, 0x02, 0x7e, 0xfb, 0xc8, 0x16, 0x2f, 0xff, 0xf4, 0x9d,
- 0x89, 0xca, 0x4b, 0x63, 0xe1, 0xc2, 0x60, 0xd6, 0x2f, 0xec, 0xd4, 0xf4,
- 0x98, 0x2c, 0x57, 0xd1, 0x1e, 0x4c, 0x17, 0x42, 0x0b, 0x17, 0xff, 0x61,
- 0x4e, 0x1b, 0x30, 0xf6, 0x6c, 0xb1, 0x7e, 0xe0, 0x87, 0x9c, 0x58, 0xbd,
- 0xc9, 0xf2, 0xc5, 0xff, 0x9b, 0xfd, 0x67, 0x3d, 0xf7, 0x3a, 0xc5, 0xff,
- 0xfe, 0x7f, 0x4f, 0xcb, 0x3d, 0xa9, 0xf9, 0x67, 0x41, 0x6e, 0xb1, 0x7f,
- 0xfd, 0x39, 0xef, 0xb4, 0x34, 0x21, 0xc9, 0x4a, 0xc5, 0x41, 0x54, 0x93,
- 0xc3, 0x7a, 0x3c, 0x8b, 0xe3, 0x1c, 0x44, 0xf1, 0x48, 0x87, 0x7a, 0x20,
- 0x04, 0x62, 0xbf, 0xfe, 0xe7, 0xe4, 0xde, 0xaf, 0xb3, 0x7d, 0xfb, 0xe2,
- 0xc5, 0xe6, 0xd7, 0x16, 0x28, 0x47, 0xe4, 0x1a, 0xad, 0xff, 0xe7, 0xfb,
- 0x3e, 0xde, 0x72, 0x70, 0x71, 0x62, 0xff, 0x8a, 0x61, 0x9c, 0xc7, 0x95,
- 0x8b, 0x6c, 0xb1, 0x52, 0x79, 0x24, 0x6d, 0x7f, 0xff, 0xd2, 0x03, 0xb4,
- 0x3a, 0xfb, 0xf8, 0x7c, 0xde, 0x7f, 0x27, 0x58, 0xbf, 0xfe, 0x72, 0xf0,
- 0xbe, 0xfc, 0x8e, 0x6f, 0x60, 0xd6, 0x2b, 0xe8, 0xbb, 0xf3, 0x4d, 0xfc,
- 0xfb, 0x75, 0x62, 0x02, 0xc5, 0xff, 0xff, 0x7d, 0x9f, 0x98, 0x6b, 0x10,
- 0x3a, 0xe4, 0x7c, 0x93, 0x1a, 0xb1, 0x79, 0x9b, 0x75, 0x45, 0xb4, 0x54,
- 0xa2, 0x53, 0x76, 0xab, 0xfe, 0x27, 0x37, 0x59, 0xb4, 0xf9, 0x62, 0xff,
- 0xff, 0x9b, 0xdc, 0x8c, 0xcf, 0x6b, 0x3e, 0x27, 0xfb, 0xf2, 0x4e, 0xb1,
- 0x7f, 0xff, 0x4b, 0x7a, 0x7f, 0x3c, 0x77, 0x83, 0xeb, 0x06, 0xb1, 0x7f,
- 0x7e, 0x4f, 0x2e, 0x35, 0x8a, 0x75, 0x46, 0x51, 0x11, 0xea, 0x18, 0x87,
- 0x23, 0x23, 0xae, 0x34, 0xf9, 0x62, 0xff, 0xe8, 0xd2, 0x4d, 0x0f, 0xaf,
- 0x4e, 0xbd, 0x7f, 0x1c, 0xb1, 0x7f, 0x34, 0x07, 0xf7, 0x3a, 0xc5, 0xfe,
- 0xc8, 0x8a, 0x4f, 0xd7, 0x75, 0x8b, 0x38, 0xcf, 0x97, 0xc5, 0xd4, 0x16,
- 0xd1, 0xcb, 0xf8, 0x5f, 0x5f, 0xfe, 0xfe, 0x41, 0x8b, 0xcd, 0x07, 0x36,
- 0x56, 0x2f, 0xfb, 0x33, 0x78, 0xe1, 0x7d, 0xf4, 0xb1, 0x7f, 0xf7, 0xf3,
- 0x6e, 0x3e, 0xa4, 0x23, 0x12, 0xc5, 0xd8, 0xeb, 0x15, 0xb9, 0xee, 0x74,
- 0x46, 0xbd, 0xe0, 0x3a, 0xc5, 0xfd, 0x31, 0xb7, 0x36, 0xc0, 0xd6, 0x2a,
- 0x4f, 0xdf, 0x09, 0x74, 0x3b, 0x60, 0xa2, 0xc5, 0xfc, 0x6b, 0xf8, 0x9b,
- 0xb5, 0x8b, 0xff, 0x7a, 0x4e, 0x4c, 0x69, 0x60, 0x16, 0x2a, 0x4f, 0xb7,
- 0x0b, 0xec, 0x05, 0x8a, 0x89, 0x16, 0xa5, 0x08, 0x3f, 0x10, 0x5f, 0xf1,
- 0x0e, 0x64, 0xe1, 0x1a, 0x0b, 0x17, 0xe7, 0x2d, 0x98, 0x6b, 0x14, 0xe7,
- 0xc5, 0xc3, 0xab, 0xfe, 0x90, 0x7e, 0x76, 0x2c, 0xe2, 0xc5, 0x49, 0xed,
- 0x08, 0x86, 0xfb, 0x39, 0x24, 0xb1, 0x7f, 0xf9, 0xf5, 0x39, 0xf1, 0x3f,
- 0x3f, 0x80, 0x58, 0xbf, 0xfe, 0x18, 0xbd, 0xc1, 0xe4, 0x3f, 0x3d, 0x07,
- 0x2b, 0x15, 0xb2, 0x2f, 0x46, 0x42, 0xe9, 0x36, 0x0a, 0x2c, 0x5f, 0xe8,
- 0x4e, 0xb6, 0x9d, 0x6c, 0xb1, 0x7f, 0x9b, 0xdd, 0x74, 0x37, 0xd2, 0xc5,
- 0x49, 0xf6, 0x08, 0xda, 0xff, 0xf4, 0xc3, 0xf2, 0x46, 0x96, 0x6c, 0x64,
- 0x16, 0x2f, 0xff, 0xf4, 0xb9, 0x37, 0x85, 0xec, 0x1c, 0x9c, 0x7f, 0x9e,
- 0xd6, 0x2f, 0xf3, 0x9c, 0x73, 0xc3, 0x38, 0xb1, 0x7b, 0xd9, 0xba, 0xc5,
- 0xff, 0xf1, 0x3f, 0x47, 0xf7, 0xe7, 0xdc, 0x9e, 0x92, 0xb1, 0x4e, 0x9a,
- 0x8e, 0x93, 0x3e, 0xc1, 0xe3, 0x51, 0x0f, 0x5f, 0xe1, 0xe1, 0x41, 0xfe,
- 0x25, 0x8b, 0xff, 0xf9, 0xf5, 0x22, 0x83, 0xb9, 0x67, 0x85, 0x1e, 0xfb,
- 0x2c, 0x58, 0x6b, 0x17, 0xfd, 0x31, 0xd9, 0xa0, 0x1d, 0xa0, 0xb1, 0x7f,
- 0x0b, 0x7f, 0xce, 0xb1, 0x62, 0xf7, 0x7c, 0xfa, 0xc5, 0x61, 0xe7, 0x31,
- 0x7d, 0x3a, 0x69, 0x9f, 0x33, 0x65, 0xd2, 0x12, 0xe4, 0x22, 0xaf, 0xfe,
- 0xf3, 0x3e, 0x4e, 0x9a, 0x0f, 0xf5, 0x8b, 0xf3, 0x0f, 0x08, 0x0b, 0x17,
- 0x08, 0x22, 0xc5, 0x41, 0x10, 0x6e, 0x85, 0xa2, 0x7b, 0xfe, 0x9d, 0x75,
- 0xe4, 0xfd, 0x9d, 0x62, 0xfe, 0x76, 0x87, 0x9f, 0x65, 0x8b, 0xed, 0xa7,
- 0xee, 0xb1, 0x5f, 0x3d, 0x16, 0x2e, 0xbe, 0x9c, 0x27, 0x58, 0xbe, 0xf4,
- 0xe0, 0xd6, 0x28, 0x67, 0x85, 0xd9, 0x05, 0xef, 0x66, 0xcb, 0x14, 0x14,
- 0x6c, 0xc5, 0x42, 0xa3, 0xd3, 0x2b, 0x27, 0x68, 0x7e, 0xc0, 0x8c, 0x70,
- 0x92, 0xc9, 0x61, 0xbb, 0xc6, 0x9e, 0xe5, 0xd1, 0x24, 0xea, 0x31, 0x03,
- 0xc3, 0x8b, 0xf0, 0xf1, 0x68, 0x6f, 0x00, 0xc0, 0xa1, 0x05, 0xc8, 0xdc,
- 0xbd, 0x1c, 0xb0, 0xa1, 0xa0, 0x19, 0x7c, 0x74, 0x22, 0xcc, 0x63, 0x08,
- 0x47, 0x7b, 0x30, 0xd5, 0x8b, 0xfa, 0x61, 0xc6, 0xcd, 0xd6, 0x2e, 0x98,
- 0xcd, 0x1e, 0x5f, 0xc7, 0x6f, 0xf0, 0x57, 0x3c, 0xfd, 0x3e, 0xeb, 0x17,
- 0xfb, 0x4d, 0xe0, 0x18, 0x50, 0x58, 0xbf, 0xfe, 0xef, 0x99, 0xd1, 0xfd,
- 0x3d, 0x1c, 0xb0, 0x6b, 0x15, 0x28, 0x88, 0x11, 0xad, 0xfc, 0x26, 0x22,
- 0xc0, 0x2c, 0x5f, 0xff, 0xda, 0x9f, 0x3e, 0xee, 0x39, 0x7d, 0x3c, 0x1f,
- 0x8b, 0x17, 0x87, 0x3d, 0xac, 0x5f, 0x9b, 0x43, 0x11, 0x2c, 0x54, 0x9e,
- 0x31, 0xa3, 0xd7, 0xff, 0xb8, 0xde, 0xfb, 0xc0, 0xff, 0xed, 0xa3, 0xd6,
- 0x2f, 0xce, 0x76, 0xf4, 0xac, 0x5f, 0xef, 0x3e, 0xee, 0x3e, 0xc9, 0x62,
- 0xff, 0xed, 0xb0, 0xb2, 0x2e, 0xba, 0x14, 0x81, 0x62, 0xfe, 0x93, 0xe0,
- 0xb0, 0xeb, 0x15, 0x28, 0xaa, 0xc3, 0x57, 0x48, 0xbf, 0xff, 0xff, 0xf0,
- 0xca, 0x77, 0xef, 0x77, 0xec, 0xec, 0x46, 0xe1, 0x37, 0x61, 0xef, 0xf7,
- 0x88, 0x9c, 0xfc, 0x58, 0xbe, 0xf1, 0x98, 0x11, 0x62, 0xff, 0xcf, 0xe9,
- 0xf3, 0xf4, 0x92, 0xdd, 0x62, 0xee, 0xe0, 0xb1, 0x58, 0x98, 0xfb, 0xc2,
- 0x81, 0x89, 0x84, 0x81, 0x7d, 0xae, 0xc5, 0xb2, 0xc5, 0xfa, 0x39, 0xf5,
- 0x86, 0xac, 0x56, 0x1e, 0x91, 0x13, 0x5d, 0xef, 0xac, 0x5f, 0xf6, 0x7b,
- 0x86, 0x73, 0xd9, 0xf5, 0x8a, 0xd8, 0xf4, 0xce, 0x31, 0x78, 0xf3, 0xba,
- 0xc5, 0xf1, 0x49, 0xf8, 0xb1, 0x67, 0xd8, 0xf0, 0x3c, 0x3d, 0x7f, 0xcd,
- 0xdf, 0x1e, 0x3f, 0xe2, 0x31, 0x62, 0xfc, 0xdd, 0xc0, 0xce, 0x2c, 0x5e,
- 0x17, 0x7c, 0x58, 0xbf, 0xe8, 0xb9, 0xd1, 0x8b, 0x61, 0x0d, 0x62, 0xff,
- 0x73, 0xa3, 0x17, 0xb0, 0x0b, 0x17, 0x8f, 0x3e, 0x58, 0xa7, 0x44, 0x84,
- 0x47, 0xc7, 0x35, 0xba, 0x4d, 0x58, 0xbf, 0xf1, 0x0f, 0xf3, 0xce, 0x66,
- 0xa5, 0x62, 0xbe, 0x7a, 0xcc, 0x31, 0x68, 0xc8, 0xd9, 0x7e, 0x37, 0x68,
- 0x60, 0x8c, 0x8b, 0x0b, 0x0d, 0x85, 0x07, 0x64, 0x51, 0x27, 0xea, 0x1a,
- 0x3f, 0x8d, 0x30, 0xa1, 0x25, 0xc7, 0x3f, 0x31, 0x88, 0xa3, 0xa1, 0xfc,
- 0x71, 0x59, 0x90, 0xaf, 0x09, 0x08, 0x6a, 0x8c, 0x65, 0x60, 0xe4, 0x7b,
- 0xe0, 0x9f, 0xbd, 0xbf, 0x9e, 0x2e, 0x6c, 0xfa, 0x58, 0xb8, 0xff, 0x58,
- 0xbe, 0xdd, 0x9b, 0x75, 0x45, 0xca, 0x5f, 0x31, 0xf0, 0x96, 0x2b, 0x47,
- 0xa5, 0xe3, 0x1b, 0xf9, 0x87, 0xf9, 0x2d, 0x96, 0x2e, 0x37, 0xeb, 0x17,
- 0x31, 0xd6, 0x2d, 0xc5, 0x8a, 0x93, 0x52, 0xc2, 0xf6, 0x8c, 0x94, 0xd2,
- 0xc6, 0x61, 0x8d, 0x5f, 0x22, 0x62, 0xe2, 0x42, 0xb4, 0x6a, 0x58, 0xb9,
- 0xce, 0xb1, 0x73, 0x9a, 0xb1, 0x7e, 0xd6, 0xec, 0xdb, 0xaa, 0x2e, 0xd2,
- 0xfd, 0x3b, 0xb9, 0x32, 0xc5, 0x2c, 0x51, 0xcd, 0x9f, 0x09, 0xef, 0x6d,
- 0x81, 0xac, 0x5e, 0x07, 0x46, 0x58, 0xbf, 0xe7, 0x84, 0x1c, 0x81, 0x30,
- 0x58, 0xb8, 0xf1, 0xcb, 0x17, 0xfd, 0xe9, 0x27, 0x04, 0x73, 0x6c, 0xb1,
- 0x7b, 0x4c, 0x05, 0x8a, 0xc3, 0xd9, 0x73, 0xcb, 0x69, 0x62, 0xed, 0xa5,
- 0x62, 0xb0, 0xd5, 0x30, 0x95, 0x46, 0xa5, 0x44, 0xb2, 0x30, 0x31, 0x7c,
- 0x18, 0x76, 0xa3, 0x90, 0xfc, 0x7d, 0x87, 0xc8, 0xe3, 0x8e, 0x82, 0x4a,
- 0xbd, 0x8e, 0x35, 0x8b, 0xfb, 0x3f, 0xc9, 0xd6, 0xeb, 0x17, 0xf7, 0x05,
- 0x14, 0x52, 0x75, 0x8b, 0xdd, 0x82, 0x33, 0x63, 0xfc, 0x21, 0xc1, 0x17,
- 0xd4, 0x62, 0x6b, 0x8d, 0x18, 0xbd, 0xd1, 0x79, 0x62, 0xff, 0xa4, 0xfd,
- 0x45, 0x13, 0xb7, 0x6b, 0x17, 0xd1, 0x37, 0xa3, 0x3e, 0x7a, 0xc0, 0x19,
- 0xa9, 0x87, 0x6d, 0x9e, 0xc5, 0x70, 0xb4, 0x17, 0x83, 0x96, 0x61, 0x89,
- 0x66, 0xda, 0xf2, 0x47, 0xbd, 0xe2, 0x48, 0xf8, 0x65, 0xfe, 0xb7, 0x0f,
- 0x2a, 0xf8, 0x0f, 0x91, 0xc7, 0xfa, 0x5e, 0xf1, 0x90, 0x82, 0xbf, 0xd1,
- 0x99, 0xad, 0xd9, 0xb7, 0x54, 0x54, 0xe5, 0xfd, 0x9c, 0x63, 0x7e, 0xeb,
- 0x17, 0xfb, 0x5e, 0x7f, 0x6c, 0x2e, 0x2c, 0x5d, 0xce, 0x2c, 0x5f, 0xf8,
- 0xb3, 0x53, 0xe7, 0xdd, 0xc6, 0xb1, 0x7e, 0xc0, 0x4e, 0x12, 0xc5, 0xa3,
- 0x20, 0x8e, 0x0c, 0x2e, 0xd1, 0xb3, 0x0c, 0x11, 0xf5, 0xff, 0xfc, 0xfa,
- 0x11, 0xbf, 0xc2, 0xdf, 0xef, 0x1c, 0xf2, 0x1a, 0xc5, 0xff, 0x64, 0x50,
- 0x6d, 0x6d, 0xf1, 0x2c, 0x5f, 0xfb, 0x0b, 0x7f, 0xbc, 0x73, 0xc8, 0x6b,
- 0x17, 0xe9, 0x3b, 0x49, 0xd6, 0x2f, 0x68, 0x46, 0xfc, 0xfa, 0x59, 0x0a,
- 0xfc, 0x3c, 0xc0, 0x71, 0x62, 0xff, 0xe8, 0xe6, 0x20, 0x67, 0xa4, 0x9c,
- 0x0b, 0x16, 0x8c, 0x0b, 0x54, 0xe9, 0x86, 0xc0, 0xf0, 0xa5, 0xe1, 0xa1,
- 0x85, 0x14, 0x4a, 0x95, 0xba, 0x47, 0xed, 0x7f, 0xf3, 0xf4, 0x9f, 0xbc,
- 0xc5, 0x14, 0xee, 0xb1, 0x7e, 0x0b, 0x23, 0x4f, 0x39, 0xab, 0x17, 0x6d,
- 0x8b, 0x17, 0xdc, 0x2f, 0xf9, 0x62, 0xff, 0x7e, 0x79, 0x27, 0x14, 0x4b,
- 0x17, 0xed, 0xca, 0x7f, 0x8b, 0x17, 0x0b, 0x65, 0x8b, 0xe1, 0x42, 0x76,
- 0x58, 0xbf, 0xee, 0xe1, 0xce, 0xb9, 0xd1, 0xb4, 0xb1, 0x7f, 0xe1, 0x45,
- 0xd5, 0xfe, 0x71, 0x6a, 0x56, 0x2a, 0x09, 0x9f, 0x8c, 0x8d, 0xcd, 0x62,
- 0x28, 0xd0, 0xcf, 0xc9, 0x38, 0x7f, 0x7f, 0x0b, 0xb3, 0xb3, 0x12, 0xc5,
- 0xbc, 0xb1, 0x7f, 0x77, 0xd6, 0x72, 0x07, 0x58, 0xbe, 0xef, 0x92, 0x35,
- 0x8b, 0x09, 0x62, 0xf4, 0xb6, 0xdd, 0x4d, 0xb0, 0x09, 0x29, 0xd1, 0x5b,
- 0xa1, 0x22, 0x67, 0xbf, 0x4f, 0x70, 0xcf, 0x2c, 0x5f, 0x1f, 0x1c, 0xeb,
- 0x17, 0xdb, 0xb3, 0x6e, 0xa8, 0xae, 0x4b, 0x8f, 0x2b, 0x17, 0xed, 0x6e,
- 0xcd, 0xba, 0xa2, 0xce, 0x2f, 0xfc, 0x6b, 0xf7, 0xc2, 0xc0, 0xd8, 0x0b,
- 0x15, 0x28, 0x8f, 0xc1, 0x7f, 0x1b, 0xdf, 0xf8, 0x24, 0xef, 0x27, 0x92,
- 0xce, 0x8b, 0x15, 0x18, 0x7e, 0x0e, 0x5d, 0x78, 0x23, 0x7d, 0x62, 0xe6,
- 0x82, 0xc5, 0xfd, 0x0f, 0x77, 0xbb, 0xf1, 0x62, 0x98, 0xf2, 0x04, 0x2f,
- 0x7f, 0x3f, 0x30, 0x98, 0x35, 0x8b, 0xfe, 0xdd, 0xb5, 0x9d, 0x24, 0xbc,
- 0xb1, 0x78, 0x50, 0x95, 0x8b, 0xff, 0x4c, 0x4c, 0xfd, 0xf3, 0xae, 0xdb,
- 0x2c, 0x54, 0x15, 0x78, 0xb9, 0x4e, 0x88, 0xbf, 0x19, 0x83, 0x12, 0x13,
- 0x3f, 0x88, 0x44, 0x5b, 0xd0, 0xec, 0x20, 0xed, 0xc2, 0x25, 0x8b, 0xff,
- 0x3c, 0x5f, 0x92, 0x19, 0x4c, 0x16, 0x29, 0xcf, 0x57, 0xe2, 0xf7, 0xff,
- 0x7c, 0x5a, 0xc1, 0xc8, 0x4f, 0xbe, 0xeb, 0x17, 0xfc, 0xfa, 0xdf, 0xf9,
- 0xd5, 0xe5, 0x62, 0xa0, 0x88, 0x3e, 0x24, 0x5f, 0xf7, 0x04, 0xc6, 0x45,
- 0xd7, 0x00, 0xb1, 0x7f, 0xfb, 0xd3, 0xce, 0xa2, 0xe7, 0xa6, 0x28, 0x9d,
- 0x62, 0xff, 0xfc, 0xdf, 0xc3, 0xc9, 0xfa, 0xe6, 0x1a, 0x6b, 0x41, 0x62,
- 0xfe, 0x73, 0xec, 0x2d, 0x41, 0x62, 0xfc, 0x7c, 0x89, 0x80, 0xb1, 0x7d,
- 0xb7, 0xdb, 0xcb, 0x14, 0xc7, 0x9a, 0x22, 0x9b, 0xe3, 0xc6, 0x81, 0x5f,
- 0x2c, 0x5f, 0xa6, 0x28, 0xa7, 0x75, 0x8b, 0xa7, 0xfd, 0x4f, 0x61, 0xcb,
- 0x6a, 0x55, 0x04, 0xe1, 0xf4, 0x49, 0xff, 0x58, 0x27, 0xde, 0x8f, 0x37,
- 0xfc, 0x52, 0x7e, 0x0a, 0x0c, 0x6a, 0xc5, 0xff, 0x33, 0x77, 0x0e, 0x67,
- 0x7e, 0x58, 0xb8, 0xfd, 0x16, 0x2f, 0x14, 0x8d, 0x62, 0xff, 0xef, 0xbf,
- 0xa7, 0x40, 0x29, 0xf7, 0x16, 0x2b, 0x0f, 0xe9, 0x86, 0x84, 0x39, 0x77,
- 0xf1, 0x62, 0xfd, 0x91, 0x44, 0x2d, 0x96, 0x2b, 0x0f, 0x0f, 0xe2, 0xf7,
- 0xd0, 0x6f, 0x3a, 0xc5, 0xf6, 0x80, 0x09, 0x58, 0xbf, 0xe7, 0xdf, 0xaf,
- 0x22, 0x26, 0x0d, 0x62, 0x8d, 0x45, 0x27, 0x64, 0x2e, 0x45, 0xf2, 0x3b,
- 0xf4, 0x52, 0x79, 0x31, 0x62, 0xfd, 0xd4, 0x79, 0xc1, 0x2c, 0x5f, 0xff,
- 0xf6, 0x9f, 0x80, 0xce, 0xaf, 0xd2, 0x7e, 0xf3, 0x14, 0x53, 0xba, 0xc5,
- 0xd0, 0x3a, 0xc5, 0xff, 0xa2, 0xea, 0xc3, 0x79, 0x89, 0xbc, 0xb1, 0x52,
- 0x9a, 0xce, 0x1f, 0x39, 0x53, 0x15, 0x93, 0x60, 0x86, 0x2f, 0xb5, 0xd4,
- 0x2e, 0x4b, 0x17, 0xd2, 0x7c, 0x25, 0x8a, 0x93, 0xca, 0x39, 0x4d, 0xe1,
- 0x37, 0x16, 0x2f, 0xf1, 0x8f, 0x14, 0xf1, 0xce, 0xb1, 0x7f, 0xfb, 0xef,
- 0xd7, 0xec, 0xfe, 0x9c, 0x1b, 0xac, 0x5e, 0xf7, 0xdd, 0x62, 0xff, 0xb5,
- 0xd6, 0x4e, 0xf1, 0xed, 0x12, 0xc5, 0x49, 0xee, 0x38, 0xed, 0xee, 0xaf,
- 0xa5, 0x8b, 0xed, 0xd9, 0xb7, 0x54, 0x48, 0x45, 0xfd, 0x0d, 0x60, 0xd8,
- 0xeb, 0x17, 0xe2, 0x87, 0xcc, 0xe2, 0xc5, 0x49, 0xec, 0x39, 0x75, 0x1a,
- 0x8e, 0x88, 0x88, 0x34, 0x3f, 0xc8, 0x44, 0xdf, 0xef, 0x70, 0x50, 0x9d,
- 0xa5, 0x62, 0xff, 0xce, 0x1f, 0x33, 0x5e, 0xf3, 0xe9, 0x62, 0xb0, 0xfd,
- 0x7c, 0x6b, 0x7f, 0xfe, 0x7d, 0x6f, 0xfc, 0xeb, 0xad, 0x60, 0x71, 0xd2,
- 0x75, 0x8a, 0x81, 0xff, 0x70, 0x86, 0xff, 0x45, 0xf9, 0xe7, 0x57, 0x35,
- 0x62, 0xfe, 0xfc, 0xed, 0xd7, 0x00, 0xb1, 0x7f, 0x33, 0x77, 0x0e, 0x3a,
- 0xc5, 0xfe, 0x04, 0xc7, 0xcf, 0xa4, 0x6b, 0x17, 0xfc, 0x7c, 0x6d, 0x6d,
- 0xd7, 0xb3, 0xac, 0x5f, 0xf0, 0x49, 0x3c, 0xc6, 0x06, 0x18, 0x6b, 0x17,
- 0xb8, 0xf1, 0x2c, 0x54, 0xa3, 0x53, 0x0d, 0x98, 0xf8, 0x48, 0x57, 0xfe,
- 0x1e, 0x72, 0x43, 0x97, 0xef, 0x8b, 0x17, 0xfb, 0xbe, 0x78, 0xa4, 0xfc,
- 0x58, 0xbf, 0xfc, 0xc5, 0xbf, 0x51, 0x93, 0x43, 0xed, 0x05, 0x8a, 0x74,
- 0x40, 0x88, 0xd6, 0xff, 0xec, 0x1b, 0xf4, 0x62, 0x07, 0x5e, 0x01, 0x62,
- 0xfe, 0xc2, 0x70, 0x72, 0x56, 0x2f, 0xfb, 0xbd, 0xdf, 0x59, 0x08, 0x4a,
- 0xc5, 0xff, 0xfa, 0x29, 0x89, 0xe2, 0xea, 0xfd, 0xf1, 0x8c, 0x73, 0xac,
- 0x54, 0xaf, 0x57, 0xc0, 0xd7, 0x23, 0x8e, 0xee, 0x33, 0x77, 0x22, 0x88,
- 0xe3, 0x46, 0x3f, 0x8c, 0x09, 0x8e, 0x81, 0x0c, 0x12, 0x22, 0xe2, 0x47,
- 0x8b, 0x04, 0x77, 0x71, 0x62, 0xc5, 0x75, 0x5f, 0xb8, 0x8c, 0x9e, 0xcc,
- 0x78, 0x6b, 0x5f, 0xa2, 0xfb, 0xf7, 0xe5, 0x8b, 0x9f, 0xeb, 0x17, 0xfe,
- 0x63, 0x22, 0x27, 0xf1, 0x48, 0x16, 0x2b, 0x66, 0x44, 0xf4, 0x27, 0xf6,
- 0x46, 0x89, 0xd9, 0x5f, 0x85, 0xef, 0xfc, 0xe7, 0xce, 0x75, 0xee, 0x19,
- 0xe5, 0x8b, 0xee, 0x0c, 0x72, 0xb1, 0x5f, 0x3e, 0x5f, 0x21, 0x5e, 0xf9,
- 0x9c, 0x58, 0xbf, 0xdc, 0x66, 0xdb, 0xaf, 0xf1, 0x62, 0xa0, 0x7a, 0xbe,
- 0x1f, 0xbf, 0xff, 0x80, 0x08, 0xd0, 0x51, 0x05, 0xa8, 0x4e, 0x84, 0x16,
- 0xbd, 0x7a, 0xfe, 0x39, 0x62, 0xe0, 0xb2, 0x34, 0x58, 0xb8, 0xd0, 0x2c,
- 0x5f, 0xff, 0xbe, 0xf1, 0x7d, 0xfb, 0xf7, 0xf7, 0x7e, 0x60, 0xd6, 0x2f,
- 0xa5, 0xc5, 0xc5, 0x8b, 0x46, 0x05, 0xb4, 0x5b, 0x49, 0x16, 0xe3, 0x3f,
- 0x59, 0xa9, 0x54, 0x33, 0x8e, 0xff, 0x22, 0x68, 0xcd, 0x2f, 0x7e, 0x4e,
- 0xb1, 0x7f, 0xfe, 0xc0, 0x48, 0x35, 0xa9, 0x0f, 0xae, 0x99, 0xa0, 0xb1,
- 0x60, 0xaa, 0xc5, 0xfb, 0x3f, 0xbc, 0x9d, 0x62, 0xff, 0xe9, 0xda, 0x7a,
- 0xcc, 0x53, 0xc1, 0x44, 0xb1, 0x79, 0xe3, 0xb1, 0x62, 0xa0, 0x7d, 0x1e,
- 0x49, 0xa8, 0xd1, 0x33, 0xe2, 0x1d, 0xe2, 0xc7, 0x85, 0x85, 0x09, 0x1b,
- 0xb9, 0xf5, 0x8b, 0xee, 0x66, 0xb6, 0x58, 0xa8, 0x1b, 0xce, 0x0c, 0x5e,
- 0xe4, 0x9a, 0xb1, 0x5f, 0x37, 0xfc, 0x21, 0xbf, 0xdb, 0xbe, 0xb2, 0x10,
- 0x95, 0x8b, 0xa4, 0x35, 0x8b, 0xe2, 0xf1, 0x4a, 0xc5, 0xfe, 0xc1, 0x93,
- 0x02, 0x7a, 0x2c, 0x53, 0x1e, 0xa8, 0x08, 0x6f, 0xfb, 0x36, 0xe3, 0xe1,
- 0xe7, 0x75, 0x8a, 0xc4, 0xc7, 0x7b, 0x21, 0x73, 0x46, 0x6d, 0xe1, 0x0d,
- 0xf8, 0xba, 0x88, 0xcd, 0xd6, 0x2f, 0xf9, 0xbd, 0xf1, 0x6f, 0xfc, 0x89,
- 0x62, 0xa4, 0xfa, 0x62, 0x2d, 0xbb, 0xa4, 0x16, 0x2a, 0x23, 0x78, 0x72,
- 0x2b, 0xf4, 0xeb, 0xa8, 0x3c, 0xb1, 0x7f, 0x02, 0x34, 0xeb, 0xd7, 0xf1,
- 0xcb, 0x16, 0x31, 0x62, 0xf0, 0x33, 0xeb, 0x17, 0xff, 0x48, 0x0e, 0xd0,
- 0xe7, 0xb3, 0x0e, 0xb1, 0x7f, 0xc5, 0x9b, 0x7d, 0x8b, 0x0e, 0xb1, 0x43,
- 0x45, 0x67, 0x62, 0x7f, 0x1d, 0x24, 0x4b, 0xd1, 0x1e, 0x25, 0x8b, 0x46,
- 0x46, 0xcd, 0xfc, 0xe8, 0x5b, 0x48, 0x0b, 0x53, 0x49, 0x8d, 0x5f, 0x66,
- 0x51, 0xc3, 0x6f, 0x25, 0x8f, 0xef, 0x0e, 0x9e, 0xe1, 0x48, 0xf2, 0x8b,
- 0x22, 0x59, 0xd1, 0xd1, 0xe1, 0x6b, 0xf9, 0x4d, 0xad, 0x49, 0x3b, 0x29,
- 0x5a, 0xdc, 0x8e, 0x03, 0xd1, 0xf6, 0x0a, 0x1d, 0xc1, 0x91, 0x47, 0x15,
- 0x99, 0x0e, 0x80, 0x87, 0xb7, 0xf8, 0x4d, 0xa8, 0x7c, 0x36, 0x58, 0xbf,
- 0x7c, 0x6f, 0xec, 0x58, 0xbf, 0xff, 0xff, 0xa7, 0xc4, 0xc0, 0x26, 0xe8,
- 0xfd, 0x08, 0x5c, 0x30, 0xa4, 0x7f, 0x68, 0x67, 0x16, 0x2f, 0xfc, 0x61,
- 0x48, 0xfe, 0xd0, 0xce, 0x2c, 0x5f, 0xf1, 0x48, 0xfe, 0xd0, 0xce, 0x2c,
- 0x5f, 0xe6, 0xe8, 0xfd, 0x08, 0x5c, 0xea, 0x7e, 0xe6, 0x1f, 0xde, 0xce,
- 0xe3, 0x06, 0x9d, 0x73, 0x9a, 0xe8, 0xa0, 0xa3, 0x01, 0xbf, 0xfa, 0x33,
- 0xed, 0xc2, 0xcf, 0x7a, 0x40, 0xb1, 0x7f, 0xfa, 0x30, 0xed, 0x08, 0xcc,
- 0xd6, 0xec, 0xdb, 0xaa, 0x27, 0xc2, 0xff, 0xf4, 0x23, 0x33, 0xa3, 0x9b,
- 0xce, 0x49, 0xc4, 0xb1, 0x7f, 0xd8, 0x1e, 0x74, 0x7f, 0x42, 0x56, 0x2f,
- 0xf9, 0x88, 0x7f, 0x93, 0x84, 0x12, 0xc5, 0xed, 0x4f, 0x16, 0x29, 0xcf,
- 0x60, 0x47, 0x77, 0xfe, 0xef, 0xd1, 0x41, 0xb5, 0xb7, 0xc4, 0xb1, 0x7f,
- 0x08, 0xbc, 0x42, 0xd9, 0x62, 0xf8, 0xf9, 0x9b, 0xac, 0x5f, 0xd0, 0x9f,
- 0x73, 0x3a, 0x2c, 0x5e, 0xe8, 0x39, 0x58, 0xbf, 0x88, 0x9c, 0xfe, 0xc5,
- 0x8b, 0xd0, 0xe6, 0x2c, 0x5e, 0x8e, 0x8d, 0x83, 0x58, 0xac, 0x44, 0x7b,
- 0x0f, 0x98, 0x58, 0x10, 0x76, 0xfc, 0x6b, 0x7b, 0x03, 0x58, 0xbf, 0xb6,
- 0x32, 0x39, 0x88, 0x0b, 0x17, 0xfc, 0xf0, 0x7f, 0x88, 0xe7, 0x75, 0x8b,
- 0xfe, 0xc8, 0xa0, 0xda, 0xdb, 0xe2, 0x58, 0xba, 0x62, 0x58, 0xbc, 0xc4,
- 0x02, 0x3d, 0x4f, 0x1e, 0x54, 0xa3, 0xc7, 0xc6, 0x71, 0xd0, 0x8d, 0xb4,
- 0x66, 0xca, 0xe6, 0x47, 0x09, 0x3c, 0x21, 0x3a, 0x23, 0x17, 0x80, 0x8c,
- 0xa1, 0x7e, 0x23, 0xe3, 0x23, 0x1b, 0xa6, 0x5c, 0x82, 0xf4, 0xbe, 0xaa,
- 0xdd, 0xd6, 0x26, 0x3c, 0xb7, 0xb8, 0xfa, 0xff, 0x27, 0x52, 0xd7, 0x4e,
- 0xaf, 0xf4, 0x76, 0x9c, 0xe1, 0xbf, 0xfd, 0x1a, 0x8d, 0x0e, 0x3f, 0x61,
- 0xc6, 0xdd, 0x7a, 0xfe, 0x39, 0x62, 0xfe, 0x6f, 0x70, 0xb9, 0xe5, 0x8b,
- 0xf3, 0x08, 0x2e, 0x76, 0x58, 0xa2, 0x3d, 0xaf, 0x17, 0x5f, 0xff, 0xc2,
- 0x26, 0x37, 0xaf, 0x8d, 0x92, 0x86, 0x7d, 0xce, 0xb1, 0x73, 0xf6, 0xb1,
- 0x7f, 0xfd, 0x0d, 0xa3, 0x54, 0xc6, 0x9b, 0x6f, 0xae, 0xbd, 0x7f, 0x1c,
- 0xb1, 0x50, 0x44, 0x00, 0x06, 0x2e, 0x33, 0x8b, 0x17, 0xff, 0x6d, 0xf9,
- 0x7f, 0x71, 0xcb, 0xb8, 0x2c, 0x57, 0xcf, 0x7c, 0x86, 0x6f, 0xfe, 0xcf,
- 0x3e, 0x17, 0xf3, 0xd2, 0x35, 0x8b, 0xff, 0x78, 0xd9, 0x28, 0x67, 0xdc,
- 0xeb, 0x17, 0xfc, 0x6c, 0x94, 0x33, 0xee, 0x75, 0x8b, 0xe1, 0x13, 0x1b,
- 0xd4, 0xfe, 0x3c, 0x7f, 0x7e, 0xd0, 0x1f, 0xf2, 0xb1, 0x47, 0x3e, 0x31,
- 0x1d, 0xdf, 0xb3, 0x59, 0x91, 0x2c, 0x5a, 0x32, 0x0a, 0xf2, 0x72, 0x18,
- 0x07, 0x21, 0xfc, 0x37, 0x9a, 0x10, 0x44, 0x43, 0xc8, 0xc7, 0x4c, 0x22,
- 0xbf, 0x6b, 0x76, 0x6d, 0xd5, 0x15, 0x91, 0x7f, 0xe6, 0x84, 0x66, 0x6b,
- 0x76, 0x6d, 0xd5, 0x13, 0x71, 0x68, 0xcc, 0x44, 0x39, 0xcd, 0xeb, 0x74,
- 0xd0, 0x5e, 0x31, 0x6b, 0xff, 0xe6, 0xde, 0x33, 0x6c, 0x0f, 0x93, 0xef,
- 0xe1, 0x2c, 0x5f, 0xf1, 0x34, 0x67, 0x24, 0x13, 0x2b, 0x17, 0x82, 0x9d,
- 0xee, 0xb1, 0x7f, 0xfb, 0x8d, 0x07, 0x35, 0xe1, 0x80, 0xe6, 0x2c, 0x5f,
- 0xfe, 0x7f, 0xb1, 0x7a, 0x19, 0xac, 0x0a, 0x46, 0xeb, 0x15, 0xb2, 0x27,
- 0x20, 0x95, 0x7f, 0xe1, 0xb9, 0x0b, 0x7c, 0xe0, 0x52, 0x37, 0x58, 0xbf,
- 0xfd, 0xe7, 0xf8, 0xbe, 0xcf, 0xdf, 0x24, 0xd5, 0x8a, 0x94, 0x4a, 0xe2,
- 0x4d, 0xf6, 0xec, 0xdb, 0xaa, 0x25, 0x62, 0xff, 0xfb, 0x5b, 0x14, 0xe9,
- 0x86, 0x4d, 0xa9, 0xe8, 0xb1, 0x5a, 0x44, 0x10, 0x8c, 0x6f, 0xf9, 0x9e,
- 0x0e, 0x42, 0x93, 0xac, 0x5f, 0x48, 0xdb, 0xeb, 0x16, 0x75, 0x8a, 0x58,
- 0xbf, 0xcf, 0x07, 0x21, 0x49, 0xd6, 0x2f, 0xc4, 0xcf, 0xde, 0xe7, 0x37,
- 0xcc, 0x19, 0x44, 0x8a, 0xee, 0x84, 0x41, 0x13, 0xef, 0xd9, 0xa3, 0x26,
- 0x3d, 0x62, 0xfe, 0x72, 0x98, 0x48, 0x45, 0x8b, 0xcf, 0x3e, 0x58, 0xbc,
- 0x47, 0xd9, 0x62, 0xa4, 0xfa, 0x34, 0x5c, 0xc3, 0x97, 0xc2, 0x1e, 0x1a,
- 0xb1, 0x79, 0xa1, 0x18, 0x16, 0x2e, 0x1e, 0x4c, 0x30, 0x07, 0x0b, 0x9c,
- 0x85, 0x1e, 0xe4, 0x6f, 0x0e, 0x5f, 0x99, 0xf2, 0x12, 0x91, 0xc5, 0xb5,
- 0xb2, 0xeb, 0xfe, 0xea, 0xa7, 0x9c, 0x76, 0xbf, 0x46, 0x34, 0x5c, 0xc5,
- 0x8b, 0xf4, 0x66, 0x42, 0x40, 0xb1, 0x51, 0x88, 0x94, 0xd8, 0xf6, 0x05,
- 0x96, 0xf2, 0xc5, 0xff, 0xfd, 0xde, 0xa7, 0xa1, 0x4c, 0x1b, 0x77, 0x21,
- 0xb1, 0x2c, 0x5f, 0x36, 0xb6, 0x8c, 0x73, 0xee, 0x61, 0x2b, 0xff, 0x7b,
- 0x23, 0x33, 0x4f, 0xb3, 0x1d, 0x62, 0xfe, 0x0a, 0xb1, 0xf5, 0x3c, 0x58,
- 0xbf, 0xfc, 0x14, 0x8d, 0xc2, 0xbc, 0xc6, 0x83, 0xe6, 0xb1, 0x62, 0xff,
- 0xcf, 0xc1, 0x1c, 0x9f, 0xa0, 0x99, 0x62, 0xff, 0x98, 0xf3, 0xf9, 0x83,
- 0x1a, 0xb1, 0x7f, 0xfd, 0xf9, 0x83, 0x83, 0x59, 0xf6, 0x26, 0x82, 0xc5,
- 0xff, 0xf3, 0x69, 0xbf, 0x0c, 0xf7, 0x1b, 0x61, 0x41, 0x62, 0xfe, 0x78,
- 0x38, 0xf0, 0xeb, 0x17, 0xfd, 0x9e, 0x93, 0xc8, 0xdb, 0xcb, 0x15, 0xba,
- 0x2d, 0xbe, 0xa2, 0x45, 0xb7, 0xc0, 0xe0, 0x8e, 0xb1, 0x7f, 0x49, 0x36,
- 0xed, 0x1e, 0xb1, 0x7c, 0x20, 0x83, 0x95, 0x8b, 0xff, 0xfc, 0xdd, 0xff,
- 0x39, 0x3c, 0xe3, 0x7e, 0x7b, 0xfb, 0x9d, 0x62, 0xff, 0xa7, 0x79, 0xd3,
- 0xfa, 0x77, 0x58, 0xa8, 0x2a, 0xc2, 0x1a, 0x07, 0x67, 0x2f, 0x18, 0x26,
- 0x8c, 0x0e, 0x49, 0xf3, 0x02, 0x25, 0xf3, 0x15, 0xff, 0x60, 0x73, 0xf7,
- 0xc2, 0xf2, 0xc5, 0xb4, 0xb1, 0x7f, 0xe0, 0x7b, 0x3f, 0x25, 0xe8, 0xec,
- 0x58, 0xa1, 0x9e, 0x98, 0x84, 0xaf, 0xe9, 0x06, 0x1e, 0x77, 0x58, 0xbf,
- 0xfe, 0x93, 0x64, 0xa4, 0x1c, 0xce, 0x49, 0x1a, 0xb1, 0x7f, 0xfd, 0xf6,
- 0x07, 0x30, 0x9a, 0x0e, 0x3c, 0x3a, 0xc5, 0xc7, 0x25, 0x8b, 0xf8, 0xb3,
- 0x7f, 0xbe, 0x96, 0x06, 0x5b, 0xdf, 0x6e, 0xcd, 0xba, 0xa2, 0x5c, 0x2f,
- 0xfe, 0x7d, 0x7d, 0xb9, 0x30, 0xc1, 0x41, 0x62, 0xfc, 0xd0, 0xdd, 0xc2,
- 0x2c, 0x5f, 0xff, 0x7f, 0x07, 0x3f, 0x98, 0x14, 0xe9, 0x86, 0xb1, 0x50,
- 0x4f, 0x7c, 0x69, 0xee, 0xcb, 0xa3, 0xdf, 0x98, 0x92, 0x27, 0x0a, 0xef,
- 0x13, 0x1d, 0x62, 0xdb, 0x2c, 0x5e, 0x86, 0x79, 0x8d, 0x78, 0x41, 0xcb,
- 0xfe, 0xfb, 0xe9, 0x82, 0x04, 0x92, 0x58, 0xbf, 0xff, 0xdf, 0x92, 0xcd,
- 0xe4, 0x05, 0x3a, 0x14, 0x35, 0x30, 0x58, 0xbc, 0x6c, 0x1d, 0x62, 0xff,
- 0xff, 0x7d, 0xf6, 0x3b, 0x43, 0x04, 0x17, 0xe3, 0x7f, 0x77, 0xe2, 0xc5,
- 0xff, 0xff, 0x6f, 0x22, 0xdf, 0xef, 0xac, 0x1f, 0x24, 0x85, 0xbb, 0x9a,
- 0xb1, 0x52, 0x8d, 0x1c, 0x67, 0xbe, 0x03, 0x47, 0x1a, 0xb1, 0x7f, 0x01,
- 0x80, 0x22, 0xdd, 0x62, 0xff, 0xb6, 0x61, 0xcc, 0x0b, 0x0e, 0xb1, 0x7a,
- 0x4f, 0xc5, 0x8b, 0xcd, 0x0f, 0x39, 0xeb, 0x11, 0xcd, 0xff, 0xb8, 0x23,
- 0x79, 0x87, 0x7f, 0xca, 0xc5, 0xed, 0x4f, 0xd6, 0x2f, 0xf4, 0x9e, 0x63,
- 0x03, 0x0c, 0x35, 0x8a, 0x74, 0x4b, 0xe9, 0x00, 0x20, 0xed, 0x62, 0x74,
- 0xbb, 0x93, 0xbc, 0x21, 0x5a, 0x19, 0x17, 0xf6, 0xe2, 0x8f, 0xfb, 0x41,
- 0x62, 0xff, 0xff, 0xf6, 0x43, 0xed, 0x09, 0x1c, 0x93, 0x77, 0xfc, 0xe4,
- 0xf3, 0x8d, 0xf5, 0x8b, 0x42, 0x51, 0x52, 0xe6, 0x77, 0xf9, 0xc6, 0xc1,
- 0x3a, 0x4c, 0x16, 0x2f, 0xa3, 0x9f, 0xec, 0xb1, 0x52, 0x7b, 0x90, 0x37,
- 0xbf, 0xcc, 0x5a, 0x92, 0x68, 0x2c, 0x5a, 0x56, 0x2b, 0x87, 0x85, 0x1c,
- 0x63, 0x7f, 0xf1, 0x41, 0x86, 0xd3, 0x09, 0x26, 0x58, 0xa9, 0x3e, 0x6c,
- 0x25, 0xb9, 0xb4, 0xb1, 0x7f, 0xff, 0x16, 0x74, 0x7f, 0xc9, 0xf3, 0x79,
- 0xe7, 0xf0, 0xeb, 0x17, 0x14, 0xee, 0x7e, 0x7c, 0x17, 0xbf, 0xff, 0xb0,
- 0x5b, 0xfe, 0x4a, 0x60, 0xc3, 0x9e, 0xf4, 0xeb, 0x17, 0xfe, 0xe3, 0x90,
- 0xbd, 0x1c, 0xfd, 0x0e, 0xb1, 0x7f, 0xf6, 0x7b, 0x3e, 0x4d, 0x01, 0x37,
- 0x16, 0x2f, 0xff, 0xff, 0x67, 0xb9, 0x83, 0x61, 0xc9, 0x37, 0x7f, 0xce,
- 0x4f, 0x38, 0xdf, 0x58, 0xa7, 0x45, 0xc9, 0x21, 0xdf, 0xff, 0x49, 0x4e,
- 0xd8, 0x5e, 0xfb, 0x43, 0xf8, 0xb1, 0x79, 0xca, 0x56, 0x2f, 0xf8, 0x46,
- 0xb1, 0xb9, 0xb6, 0x6c, 0xb1, 0x52, 0xb8, 0x57, 0x08, 0x41, 0x8e, 0x19,
- 0x2f, 0x09, 0x38, 0xf2, 0xd3, 0xad, 0x94, 0x3f, 0x7c, 0x43, 0xd1, 0x3a,
- 0x38, 0x6e, 0xff, 0xf1, 0x63, 0xc1, 0x9f, 0x7c, 0xd3, 0x41, 0x62, 0xff,
- 0xb0, 0xee, 0x40, 0x7f, 0x89, 0x62, 0xfd, 0xf7, 0xd3, 0x71, 0x62, 0xfe,
- 0x1c, 0xbf, 0xe4, 0xeb, 0x17, 0xe1, 0xcc, 0x7b, 0x69, 0x62, 0xf4, 0x90,
- 0x30, 0xf6, 0x18, 0xb6, 0xbc, 0x8b, 0x00, 0x90, 0x80, 0xad, 0x93, 0x12,
- 0xc8, 0x74, 0x5f, 0xe9, 0x2d, 0xd9, 0xf6, 0xc5, 0x8b, 0xb7, 0x95, 0x8a,
- 0x34, 0xf2, 0xc8, 0xce, 0xfe, 0xe9, 0x25, 0xbb, 0x71, 0x62, 0xff, 0xe2,
- 0x98, 0x60, 0xf2, 0x18, 0x40, 0x58, 0xbf, 0x30, 0x39, 0x84, 0xb1, 0x52,
- 0x89, 0x97, 0x30, 0xe2, 0x15, 0xff, 0xfe, 0x7f, 0x49, 0x31, 0xf0, 0xed,
- 0x0e, 0x4f, 0xa4, 0x6b, 0x14, 0xe9, 0xa3, 0xfa, 0x17, 0x7d, 0x0b, 0xaf,
- 0x80, 0x07, 0xed, 0x62, 0xfc, 0x23, 0x4b, 0x00, 0xb1, 0x7f, 0xcd, 0xa3,
- 0x4b, 0x3d, 0xf7, 0x58, 0xa7, 0x44, 0x31, 0xc9, 0x08, 0xa6, 0xff, 0x7d,
- 0xfb, 0xf6, 0xd8, 0x1a, 0xc5, 0xff, 0xb3, 0xcd, 0xde, 0x43, 0xf3, 0xa5,
- 0x8b, 0xfc, 0xe6, 0xbf, 0xf7, 0x7e, 0x2c, 0x5f, 0xcc, 0xf0, 0x73, 0x65,
- 0x62, 0xd3, 0x03, 0xe2, 0xf9, 0xad, 0xff, 0xff, 0xfc, 0x40, 0x62, 0x07,
- 0x30, 0xed, 0xfc, 0x1b, 0x39, 0x4f, 0xd9, 0xe0, 0xe3, 0x58, 0xbd, 0xdc,
- 0x25, 0x62, 0xe8, 0x01, 0x62, 0xfe, 0x21, 0x43, 0xed, 0x0c, 0x36, 0xce,
- 0x3d, 0x7f, 0xf0, 0xa0, 0x4f, 0x09, 0xf1, 0x0a, 0x0b, 0x17, 0xe9, 0xe0,
- 0x0f, 0xe5, 0x8a, 0x73, 0xed, 0xfa, 0x25, 0x0d, 0x3a, 0xf7, 0x27, 0xe4,
- 0x2e, 0x7d, 0x0a, 0xeb, 0x6e, 0xb1, 0x77, 0x3b, 0x58, 0xbf, 0xb4, 0x01,
- 0xe0, 0x38, 0xb1, 0x52, 0xb8, 0x29, 0x90, 0xbd, 0xdc, 0xb9, 0xcd, 0xda,
- 0x52, 0x80, 0x11, 0xfc, 0x26, 0x21, 0x9b, 0xf7, 0xf0, 0xb3, 0x75, 0x8b,
- 0x8b, 0xcb, 0x15, 0x03, 0x7e, 0xc5, 0x17, 0xa1, 0xff, 0x2c, 0x53, 0x9b,
- 0xef, 0x90, 0x5f, 0x77, 0xf9, 0xdd, 0x62, 0xdf, 0x93, 0xc5, 0x62, 0x0b,
- 0xff, 0x89, 0xc1, 0xcd, 0x4b, 0xc1, 0xb8, 0xb1, 0x7f, 0xf8, 0x36, 0xd4,
- 0xb9, 0xf0, 0x73, 0x09, 0x58, 0xbe, 0x03, 0x36, 0x96, 0x2c, 0xd0, 0x3e,
- 0xbe, 0xd2, 0x6b, 0x11, 0xf8, 0xe4, 0xdc, 0x85, 0x75, 0xf1, 0xc9, 0x86,
- 0xb1, 0x79, 0xf6, 0x0b, 0xac, 0x5f, 0x9c, 0xe4, 0xd0, 0x58, 0xbf, 0xfb,
- 0xdf, 0xce, 0x9f, 0x73, 0xe0, 0x82, 0xeb, 0x14, 0xe8, 0xb6, 0x8f, 0x22,
- 0xd1, 0x13, 0x13, 0xdf, 0xe6, 0xef, 0x9e, 0xfc, 0x86, 0xb1, 0x7f, 0xf0,
- 0x9a, 0x3d, 0xf6, 0xcf, 0xbf, 0x7c, 0x58, 0xbf, 0xd3, 0x13, 0x7b, 0xec,
- 0x05, 0x8b, 0xff, 0x77, 0x0c, 0xf6, 0x6b, 0x79, 0xc5, 0x8b, 0xcd, 0x08,
- 0xc8, 0xd1, 0xbb, 0xde, 0x0b, 0x0c, 0xa6, 0x58, 0xc6, 0xd0, 0x85, 0x84,
- 0x22, 0xc6, 0x45, 0x92, 0x83, 0x7b, 0x84, 0x93, 0x99, 0xc4, 0x79, 0xa6,
- 0x03, 0xc3, 0xbf, 0xf1, 0xe3, 0x34, 0xe8, 0xd0, 0x21, 0x4e, 0x51, 0xad,
- 0x72, 0x77, 0x3f, 0xd2, 0x8e, 0xc5, 0x0e, 0x90, 0xcf, 0xa3, 0x8d, 0x8c,
- 0x49, 0x08, 0x69, 0x7f, 0xe1, 0x1e, 0x33, 0x92, 0x5e, 0xcd, 0x2c, 0x5d,
- 0xd1, 0xd6, 0x2f, 0xfe, 0x9e, 0x3f, 0x4e, 0x4c, 0x1f, 0xcc, 0xb1, 0x7f,
- 0xe9, 0xf4, 0xf4, 0x92, 0xdd, 0xb8, 0xb1, 0x7b, 0x3f, 0x18, 0xe8, 0x9e,
- 0x61, 0x9e, 0x22, 0xdf, 0xf0, 0xf2, 0x32, 0x74, 0xff, 0x12, 0xc5, 0xff,
- 0xc3, 0x98, 0xc0, 0x99, 0xdc, 0x3f, 0x3c, 0x58, 0xb4, 0x66, 0xed, 0xfd,
- 0x7b, 0x9d, 0x9e, 0xbc, 0x20, 0xe4, 0x75, 0x7e, 0x87, 0x00, 0x90, 0xba,
- 0x1e, 0x5e, 0x92, 0x35, 0x62, 0xff, 0xa1, 0x19, 0x9a, 0xdd, 0x9b, 0x75,
- 0x44, 0x76, 0x5a, 0x33, 0xe7, 0xd0, 0xc3, 0xb7, 0xff, 0xc2, 0x9e, 0xe0,
- 0xe7, 0x0f, 0x08, 0x7f, 0x95, 0x8b, 0xff, 0xff, 0x8f, 0x3b, 0xef, 0xf7,
- 0x8b, 0xee, 0x43, 0x6d, 0x49, 0xa6, 0x8b, 0x65, 0x8b, 0x84, 0x62, 0xc5,
- 0xf1, 0x33, 0x76, 0xb1, 0x7d, 0xdf, 0x9c, 0x35, 0x8a, 0x93, 0xc7, 0x39,
- 0x15, 0xdb, 0x46, 0x0d, 0x34, 0xac, 0x51, 0x3b, 0xc1, 0x8c, 0x17, 0xff,
- 0xf9, 0x81, 0x18, 0x64, 0xed, 0x9e, 0x92, 0x70, 0x67, 0x7e, 0x58, 0xbf,
- 0x71, 0xfa, 0x7f, 0xa2, 0xc5, 0xc5, 0xc5, 0x8b, 0xef, 0xe4, 0x23, 0x24,
- 0xf1, 0x18, 0xb6, 0xb1, 0x33, 0x18, 0x93, 0xbd, 0x0a, 0x9b, 0x1a, 0xb1,
- 0x77, 0x51, 0xac, 0x54, 0x6e, 0x6b, 0x42, 0xa2, 0x77, 0xfc, 0x15, 0x8e,
- 0xc3, 0x5f, 0xc5, 0x2b, 0x17, 0xf4, 0x6c, 0x53, 0xbe, 0x12, 0xc5, 0x84,
- 0xb1, 0x6f, 0xac, 0x54, 0x6e, 0x69, 0x04, 0x25, 0x7f, 0x05, 0x4b, 0x3e,
- 0xde, 0x58, 0xb0, 0x6b, 0x17, 0xcf, 0xec, 0xfa, 0xc5, 0xfe, 0xe6, 0x16,
- 0x69, 0xbc, 0xb1, 0x79, 0xc8, 0x0b, 0x15, 0xc3, 0xce, 0xe8, 0x65, 0x77,
- 0xf1, 0x62, 0xfd, 0x84, 0xe0, 0x31, 0x62, 0xa4, 0xdf, 0xf0, 0x5e, 0xf6,
- 0x6a, 0x56, 0x2f, 0xf7, 0xe7, 0x6d, 0x4e, 0x0d, 0x62, 0xec, 0xd9, 0x62,
- 0xf0, 0x41, 0xca, 0xc5, 0x49, 0xf5, 0x91, 0xa0, 0x86, 0x2f, 0xfd, 0xae,
- 0xb9, 0xec, 0xfc, 0xe8, 0x0b, 0x17, 0xff, 0xfe, 0x67, 0xdf, 0x0b, 0xac,
- 0x33, 0x9e, 0xcf, 0xc9, 0x7b, 0xee, 0xb1, 0x67, 0x58, 0xa7, 0x45, 0xf7,
- 0xd0, 0x59, 0xb2, 0xfa, 0x61, 0x3a, 0x58, 0xbf, 0xff, 0x41, 0xc7, 0xf7,
- 0xe9, 0xd7, 0x07, 0xa7, 0x16, 0xeb, 0x17, 0xd3, 0xa9, 0xd2, 0xc5, 0x46,
- 0xca, 0xd1, 0x60, 0x27, 0x8e, 0x0e, 0xc7, 0xa2, 0x0f, 0xc2, 0x1c, 0xa1,
- 0xd7, 0xc2, 0xef, 0x11, 0x18, 0xb7, 0x7a, 0x29, 0xd9, 0x62, 0xfa, 0x4b,
- 0xdc, 0x58, 0xbb, 0x03, 0x93, 0xc1, 0xe0, 0xfd, 0xff, 0xb9, 0xec, 0xfc,
- 0x97, 0xbe, 0xeb, 0x17, 0xfb, 0xdc, 0x98, 0x99, 0xb4, 0xb1, 0x7f, 0xd3,
- 0x9e, 0x76, 0xda, 0x74, 0xb1, 0x63, 0xac, 0x58, 0xeb, 0x14, 0x15, 0x34,
- 0x86, 0x09, 0x5f, 0xff, 0x87, 0x9a, 0xeb, 0x87, 0x14, 0xeb, 0x4e, 0x2d,
- 0xd6, 0x2b, 0x13, 0x4d, 0x73, 0xe0, 0x1a, 0x79, 0x70, 0x44, 0xd7, 0x05,
- 0x38, 0xb1, 0x7f, 0x00, 0xb3, 0xbf, 0x62, 0xc5, 0xdb, 0x47, 0xac, 0x5f,
- 0xfd, 0xd2, 0x47, 0xec, 0x97, 0xf4, 0xc4, 0xb1, 0x7c, 0x6f, 0xf0, 0x0b,
- 0x17, 0xf3, 0x07, 0x9e, 0x9d, 0xd6, 0x29, 0x8f, 0x4c, 0x89, 0x2f, 0xff,
- 0xfe, 0x63, 0x67, 0x40, 0x14, 0xe6, 0x7f, 0x77, 0x92, 0x9c, 0xf8, 0x96,
- 0x2f, 0xe2, 0x03, 0x69, 0x8c, 0x58, 0xbf, 0xfe, 0x9f, 0x4f, 0xba, 0xfb,
- 0xf8, 0x4d, 0xa3, 0x56, 0x2a, 0x34, 0x54, 0x1f, 0x23, 0x9b, 0x17, 0x38,
- 0xe6, 0xa1, 0x33, 0xf2, 0x06, 0x70, 0x22, 0xeb, 0xff, 0x03, 0x99, 0xec,
- 0x88, 0xa4, 0xeb, 0x17, 0xff, 0xdf, 0xea, 0x58, 0xfa, 0x7d, 0x98, 0xe7,
- 0x75, 0x8b, 0xff, 0xff, 0xbe, 0xc3, 0x26, 0xeb, 0xcf, 0xcf, 0x3a, 0x89,
- 0xba, 0xc3, 0x3a, 0x4a, 0xc5, 0xff, 0x1b, 0xd7, 0x1c, 0xdd, 0x67, 0x16,
- 0x2b, 0xe8, 0xb6, 0x27, 0x9b, 0xff, 0xc5, 0x86, 0xfd, 0xa1, 0xf0, 0xd8,
- 0xc3, 0xac, 0x54, 0x9f, 0x7e, 0x11, 0x54, 0xa7, 0xaa, 0xe7, 0xff, 0x8d,
- 0xda, 0xff, 0xcf, 0xae, 0xbc, 0x2c, 0x3c, 0xee, 0xb1, 0x7f, 0x85, 0xe7,
- 0x6e, 0x8d, 0x05, 0x8b, 0xfc, 0x52, 0x0e, 0xbf, 0x63, 0xac, 0x5f, 0xcd,
- 0xd0, 0x78, 0x46, 0xac, 0x5a, 0x49, 0x13, 0x5e, 0x35, 0x30, 0xd6, 0xff,
- 0xff, 0xff, 0xbf, 0x3a, 0xdb, 0x06, 0xfe, 0xe4, 0xed, 0x3a, 0xc1, 0xe3,
- 0xc9, 0x67, 0x47, 0xd3, 0x2c, 0x5f, 0xff, 0xfa, 0x4b, 0x76, 0xf3, 0x76,
- 0x0e, 0xb8, 0x4f, 0x22, 0xff, 0xe5, 0x62, 0xa0, 0x98, 0x00, 0x21, 0x27,
- 0x7f, 0xe2, 0x14, 0x3a, 0xe3, 0x94, 0x9d, 0x62, 0xfe, 0xe4, 0x1f, 0x76,
- 0xd2, 0xc5, 0xe6, 0x6d, 0xd5, 0x15, 0x09, 0x7f, 0x1b, 0xcf, 0xc9, 0x79,
- 0x62, 0xff, 0xf3, 0xf4, 0xc7, 0x2c, 0xd4, 0xef, 0x3a, 0x58, 0xb1, 0xd6,
- 0x2f, 0x60, 0xbc, 0x47, 0xb8, 0x24, 0xab, 0xfc, 0xc0, 0x98, 0xbe, 0x20,
- 0x2c, 0x54, 0xa6, 0x97, 0xb9, 0x7b, 0x95, 0x6a, 0x11, 0x62, 0x32, 0xbf,
- 0xa6, 0x28, 0x0b, 0xb8, 0x2c, 0x5f, 0xbe, 0xf2, 0x5e, 0x58, 0xbf, 0xdc,
- 0xeb, 0xc0, 0x36, 0x44, 0xb1, 0x5a, 0x3d, 0xe0, 0x13, 0xdf, 0xc1, 0x18,
- 0x86, 0x67, 0x6b, 0x14, 0xe7, 0xa8, 0xc4, 0x57, 0xf8, 0xfc, 0x7c, 0xe8,
- 0xda, 0x58, 0xbf, 0xff, 0x67, 0xf0, 0xde, 0xb8, 0x3e, 0xae, 0x20, 0x02,
- 0x56, 0x2f, 0x9c, 0xd6, 0xdd, 0x62, 0xff, 0xfb, 0x0f, 0xd4, 0x85, 0xce,
- 0xbc, 0xcd, 0x37, 0x96, 0x2f, 0xfe, 0x11, 0xba, 0x79, 0xf4, 0x50, 0x68,
- 0x2c, 0x56, 0xe8, 0xbf, 0xe1, 0x27, 0x95, 0x29, 0x93, 0x7f, 0xf1, 0xa8,
- 0xa3, 0x19, 0xbe, 0xd6, 0xe2, 0x02, 0xc5, 0xfd, 0x84, 0xda, 0xd3, 0xac,
- 0x53, 0x9e, 0x8f, 0xc9, 0x6f, 0xd2, 0x42, 0x6d, 0x96, 0x2f, 0xff, 0x37,
- 0x65, 0x9e, 0xef, 0x71, 0x4e, 0xb8, 0xb1, 0x58, 0x89, 0x6e, 0x10, 0x88,
- 0xa2, 0xfb, 0x62, 0x9d, 0x96, 0x2f, 0xfe, 0xd3, 0xf8, 0xb0, 0xde, 0xaf,
- 0xd1, 0xd6, 0x2f, 0xfd, 0x82, 0xdf, 0xee, 0x2d, 0xe7, 0x4b, 0x15, 0x28,
- 0xad, 0x72, 0x4f, 0x24, 0x5f, 0xfe, 0x90, 0xfa, 0xe7, 0x47, 0xf4, 0xe1,
- 0x41, 0x62, 0xfd, 0x9b, 0xb1, 0x1a, 0xb1, 0x50, 0x64, 0xb3, 0x1a, 0x6b,
- 0xbc, 0x36, 0xfb, 0x8c, 0xd5, 0xca, 0x75, 0x1c, 0x51, 0xd3, 0xff, 0x0e,
- 0x32, 0x8e, 0x7f, 0x91, 0x8e, 0xfa, 0x1b, 0x9d, 0x0b, 0x8c, 0x4d, 0xbd,
- 0x1e, 0xd2, 0xb1, 0x6c, 0x58, 0xbf, 0xfe, 0x73, 0xce, 0xfd, 0x77, 0xfb,
- 0x84, 0x93, 0xca, 0xc5, 0xff, 0xc2, 0x6d, 0xb9, 0x8f, 0xbe, 0xf9, 0xd1,
- 0x62, 0xa0, 0x8a, 0xff, 0x88, 0x92, 0xad, 0xef, 0x7c, 0xeb, 0x17, 0xf0,
- 0x33, 0xae, 0x0f, 0x65, 0x8b, 0x7b, 0xa9, 0xe7, 0xb8, 0xf5, 0xfc, 0xfa,
- 0x6d, 0xdc, 0x96, 0x2b, 0x0f, 0x5b, 0xc5, 0x37, 0xff, 0xfa, 0x74, 0x6f,
- 0x5e, 0x10, 0xb3, 0xd3, 0x07, 0x1f, 0xdd, 0x62, 0xa0, 0x88, 0x4e, 0x10,
- 0xde, 0x07, 0x31, 0x62, 0xff, 0x70, 0x51, 0x30, 0xda, 0x25, 0x8b, 0xf7,
- 0x80, 0x61, 0x41, 0x62, 0xff, 0xfc, 0x1b, 0x04, 0xe3, 0xea, 0x2e, 0x49,
- 0xdb, 0xbf, 0x2c, 0x53, 0x22, 0x17, 0x85, 0x57, 0xf4, 0xee, 0xe5, 0x30,
- 0x58, 0xb4, 0x72, 0xc5, 0xfd, 0xec, 0xd8, 0xf3, 0xba, 0xc5, 0x41, 0x36,
- 0xce, 0xc7, 0x62, 0x85, 0xd9, 0xc8, 0x80, 0x5b, 0xe1, 0x5b, 0xf1, 0x6c,
- 0x09, 0x31, 0x62, 0xfe, 0x84, 0x7c, 0xfa, 0x49, 0x62, 0xb0, 0xf6, 0x82,
- 0x15, 0x5f, 0xa3, 0xcf, 0x2f, 0xa5, 0x8b, 0xec, 0x39, 0x92, 0xb1, 0x78,
- 0x2f, 0x1c, 0xeb, 0x14, 0x47, 0x8e, 0x22, 0x3a, 0x94, 0x49, 0xbb, 0x95,
- 0xd3, 0xc5, 0x8a, 0x94, 0x77, 0x42, 0x16, 0xc0, 0x21, 0xbf, 0x40, 0xa4,
- 0xe6, 0xac, 0x5f, 0xfc, 0x7c, 0xd1, 0x63, 0xf4, 0x7d, 0x32, 0xc5, 0xfc,
- 0xfb, 0xb8, 0xf7, 0x3a, 0xc5, 0x76, 0x89, 0xd6, 0x29, 0xf2, 0x25, 0xff,
- 0xf9, 0xf5, 0xd7, 0x3c, 0x29, 0xcd, 0xbf, 0x8f, 0x05, 0x8b, 0xe9, 0xf1,
- 0x90, 0x58, 0xbf, 0xf1, 0x64, 0x5e, 0xfe, 0x69, 0xf8, 0xb1, 0x7f, 0xe3,
- 0xf5, 0x3b, 0x7b, 0xaf, 0xfd, 0xa5, 0x8b, 0xfd, 0x27, 0xc7, 0xd0, 0xa3,
- 0xd6, 0x29, 0x8f, 0xec, 0x48, 0xb4, 0x34, 0x7f, 0xfc, 0x90, 0xa1, 0x75,
- 0x7f, 0x1c, 0x4d, 0xb3, 0xec, 0xb1, 0x7f, 0xf0, 0xa1, 0x09, 0xea, 0x77,
- 0x1e, 0x7d, 0x62, 0xf8, 0x9c, 0xee, 0xb1, 0x52, 0x89, 0x8c, 0x30, 0xed,
- 0x1e, 0xf6, 0xd8, 0x1a, 0xc5, 0xec, 0xd7, 0xd6, 0x2d, 0x31, 0xb1, 0xbc,
- 0xdc, 0x7e, 0xfa, 0x38, 0x41, 0x25, 0x62, 0xa5, 0x58, 0x88, 0xcc, 0x32,
- 0x35, 0x67, 0x86, 0x66, 0x9a, 0xc4, 0x59, 0x7e, 0xcc, 0x36, 0x74, 0xb1,
- 0x7e, 0x6f, 0xf5, 0x1c, 0xac, 0x5f, 0xf6, 0x7d, 0x8f, 0xe1, 0x37, 0x96,
- 0x28, 0xe8, 0x8b, 0xf1, 0x44, 0x71, 0x55, 0xff, 0x7b, 0x86, 0x71, 0xbb,
- 0x86, 0x2c, 0x5f, 0xe6, 0x87, 0x5e, 0x08, 0x0c, 0xb1, 0x7d, 0x3f, 0x9d,
- 0x96, 0x2c, 0xe3, 0x3d, 0x9f, 0x9b, 0x54, 0xa3, 0xbf, 0x0c, 0xc5, 0x09,
- 0x5b, 0xf7, 0x1f, 0xf8, 0x35, 0x8b, 0xf4, 0x27, 0xd9, 0xb2, 0xc5, 0x47,
- 0x9e, 0x8e, 0x8a, 0x2f, 0x4f, 0x36, 0x58, 0xbb, 0xbf, 0x2c, 0x5d, 0xec,
- 0x58, 0xa9, 0x36, 0x1d, 0x8c, 0xdf, 0xdc, 0x72, 0xdf, 0xf2, 0xb1, 0x58,
- 0x8c, 0x2d, 0xc9, 0x74, 0x9d, 0xe2, 0x1b, 0xf4, 0x38, 0x4c, 0x05, 0x8b,
- 0xd1, 0xcf, 0xf5, 0x8a, 0xec, 0xf2, 0x1c, 0xa2, 0xff, 0xbd, 0xcd, 0x64,
- 0x5f, 0x73, 0x56, 0x2f, 0x82, 0x13, 0x41, 0x62, 0xe1, 0x69, 0x62, 0xbe,
- 0x6f, 0x38, 0x49, 0x58, 0x89, 0x9f, 0x3c, 0x5c, 0x5f, 0x58, 0xbe, 0x83,
- 0x19, 0x12, 0xc5, 0xff, 0xfe, 0xe3, 0x88, 0x2f, 0xf7, 0xeb, 0x9d, 0xfb,
- 0xe6, 0x73, 0x69, 0x58, 0xbf, 0x42, 0x41, 0xcc, 0x58, 0xbf, 0xf6, 0x75,
- 0xe7, 0x8b, 0x01, 0x1d, 0x8b, 0x17, 0xb3, 0x7e, 0xb8, 0x7d, 0x7f, 0x28,
- 0xb7, 0x9d, 0x30, 0xbe, 0x43, 0x5a, 0xff, 0xfe, 0x7e, 0x03, 0x20, 0x52,
- 0x06, 0xff, 0x70, 0xcf, 0x2c, 0x5f, 0xfd, 0xbb, 0xeb, 0x4d, 0x06, 0xdc,
- 0x5d, 0xac, 0x5e, 0x03, 0xfd, 0x62, 0xff, 0xb0, 0xdc, 0x3b, 0xc7, 0x49,
- 0xd6, 0x2f, 0xf4, 0x9e, 0x63, 0x03, 0x0c, 0x35, 0x8a, 0xed, 0x54, 0xa3,
- 0xc6, 0x61, 0xa2, 0xef, 0xad, 0x81, 0x20, 0x87, 0x42, 0x1e, 0x5f, 0xf7,
- 0x56, 0x2c, 0x09, 0xd7, 0xe2, 0x58, 0xbf, 0x06, 0xfa, 0xc3, 0x56, 0x2a,
- 0x57, 0x38, 0xf2, 0x10, 0xaf, 0x0b, 0xb8, 0x88, 0x9a, 0x55, 0x58, 0x9b,
- 0x4c, 0x3f, 0xbf, 0xfe, 0x6f, 0xf5, 0x9e, 0xb9, 0xd2, 0x61, 0xd6, 0x74,
- 0xb1, 0x7e, 0x1b, 0xff, 0x09, 0x62, 0xff, 0xbc, 0xfc, 0x71, 0x05, 0xc7,
- 0x2b, 0x17, 0x4f, 0x6b, 0x17, 0xff, 0xde, 0xf4, 0xfb, 0xb8, 0x7f, 0x08,
- 0xd3, 0x0e, 0xb1, 0x7f, 0x4f, 0xb0, 0x9a, 0x3d, 0x62, 0xfd, 0x00, 0x7d,
- 0x8e, 0xb1, 0x7b, 0x6c, 0x0d, 0x62, 0xc0, 0xea, 0x79, 0x11, 0xb1, 0x4d,
- 0x0d, 0x3c, 0xdc, 0x57, 0x72, 0x7d, 0x1e, 0xb0, 0xc0, 0x15, 0x09, 0xde,
- 0xe8, 0xd8, 0x2a, 0xb1, 0x7f, 0xe6, 0x2d, 0xfd, 0x9f, 0xf7, 0x84, 0xb1,
- 0x4e, 0x7c, 0x22, 0x21, 0xbd, 0x3d, 0x25, 0x62, 0xfe, 0x9d, 0x6d, 0x3a,
- 0xd9, 0x62, 0xf8, 0x5b, 0x4c, 0x16, 0x2a, 0x07, 0xa9, 0xc3, 0x0b, 0xfc,
- 0x6f, 0x5d, 0x3f, 0x7e, 0xc5, 0x8b, 0xff, 0xef, 0xc8, 0xfa, 0xff, 0x3a,
- 0xe6, 0x9a, 0x18, 0xb1, 0x7c, 0xe6, 0xe0, 0xd6, 0x2f, 0x1b, 0x83, 0x58,
- 0xbd, 0xec, 0x3f, 0x53, 0xc1, 0x72, 0x3b, 0xfe, 0x90, 0x1d, 0xa1, 0x1a,
- 0x05, 0x42, 0x8b, 0x17, 0x06, 0x17, 0x58, 0xbf, 0x07, 0xf1, 0x16, 0xeb,
- 0x17, 0xf8, 0xbd, 0xcc, 0x83, 0xfd, 0x62, 0xa4, 0xf7, 0xb0, 0xae, 0xa5,
- 0x13, 0x7c, 0x7b, 0xbf, 0xfd, 0x90, 0xc8, 0x9f, 0x58, 0x2d, 0xd8, 0x96,
- 0x2f, 0xd9, 0xd0, 0xa7, 0xb5, 0x8a, 0xf9, 0xfa, 0x71, 0x2a, 0xe1, 0x7d,
- 0x62, 0xa5, 0x55, 0x96, 0xe7, 0x0f, 0x09, 0x42, 0x34, 0xe4, 0x38, 0xbd,
- 0x09, 0x68, 0xe2, 0x2b, 0xff, 0xe9, 0x06, 0x17, 0x56, 0xf7, 0x5f, 0xe0,
- 0x19, 0x62, 0xe2, 0xd9, 0x62, 0xe9, 0xe8, 0xb1, 0x52, 0xaf, 0x37, 0x25,
- 0x6a, 0x3b, 0xb1, 0x29, 0x08, 0x62, 0xff, 0xff, 0xbb, 0xdc, 0xb3, 0xa6,
- 0x0f, 0x30, 0x88, 0x4d, 0xb4, 0xe9, 0x62, 0xff, 0x0f, 0x0f, 0xd7, 0x8d,
- 0xf5, 0x8b, 0xc2, 0x9e, 0x2c, 0x56, 0x22, 0xed, 0xda, 0x3e, 0x6d, 0x77,
- 0x20, 0xb1, 0x7f, 0xfb, 0xf2, 0x72, 0x63, 0x4b, 0x01, 0xd8, 0x16, 0x2f,
- 0xee, 0x8c, 0x7f, 0x86, 0xcb, 0x17, 0xff, 0xef, 0x37, 0xe3, 0x39, 0xfc,
- 0x2f, 0x75, 0x04, 0x38, 0xb1, 0x7f, 0xff, 0xf7, 0xf9, 0x87, 0x3c, 0xe8,
- 0xde, 0x60, 0xcb, 0x1f, 0x59, 0xe9, 0x58, 0xb3, 0xca, 0x33, 0x59, 0x72,
- 0xff, 0x13, 0xe6, 0xf3, 0xee, 0x2c, 0x5f, 0xf3, 0x97, 0x4d, 0xb0, 0xdc,
- 0xd2, 0xc5, 0x39, 0xf7, 0xf0, 0xce, 0xa0, 0x9f, 0xfb, 0xa5, 0x94, 0x3f,
- 0xbd, 0x09, 0x5b, 0xfa, 0x4e, 0xff, 0x9e, 0xd6, 0x2e, 0x16, 0x96, 0x2b,
- 0x47, 0x8d, 0xc2, 0xeb, 0xfc, 0x26, 0xe6, 0x7d, 0xce, 0xb1, 0x7f, 0xf3,
- 0x3f, 0x85, 0xa6, 0xe4, 0x01, 0xba, 0xc5, 0xdf, 0x75, 0x8b, 0xfe, 0x87,
- 0x5f, 0x66, 0xb4, 0xfb, 0xac, 0x53, 0x9e, 0xa1, 0x0b, 0xdf, 0x8e, 0x15,
- 0x8d, 0xb3, 0x4b, 0x17, 0xfc, 0xfe, 0xc3, 0xb9, 0xb8, 0x35, 0x8a, 0x93,
- 0xeb, 0xc3, 0x2b, 0xff, 0x7d, 0xc8, 0x06, 0x7f, 0xed, 0xb2, 0xc5, 0xe3,
- 0xbf, 0x16, 0x2f, 0xf6, 0x7d, 0xc7, 0x25, 0xe5, 0x8b, 0xfb, 0x4c, 0x40,
- 0x04, 0xac, 0x54, 0xae, 0x94, 0x6c, 0x5d, 0x92, 0x85, 0xde, 0x11, 0x9a,
- 0x22, 0xf9, 0x9b, 0x42, 0x68, 0xa1, 0x17, 0xe2, 0x01, 0x20, 0x86, 0x3a,
- 0x61, 0x95, 0xfe, 0x2c, 0xf7, 0x00, 0xfd, 0xac, 0x5f, 0x8b, 0x06, 0x4c,
- 0xb1, 0x7f, 0x69, 0xfd, 0xf7, 0x1a, 0xc5, 0x41, 0x11, 0x18, 0x69, 0xa2,
- 0x6b, 0xe1, 0x4f, 0x09, 0x62, 0xff, 0xfd, 0x9d, 0xc2, 0x76, 0xeb, 0xf9,
- 0x72, 0x6d, 0x1a, 0xb1, 0x76, 0x74, 0x58, 0xbf, 0x49, 0xdb, 0xbf, 0x2c,
- 0x5d, 0x9b, 0x2c, 0x5f, 0xfc, 0x3e, 0x66, 0x8b, 0x01, 0xcc, 0xd2, 0xc5,
- 0x7d, 0x13, 0xdc, 0x19, 0xf1, 0x48, 0x86, 0x2f, 0xd9, 0xb8, 0x9b, 0x65,
- 0x8a, 0xdd, 0x38, 0x0d, 0x11, 0x7e, 0x1e, 0xe4, 0x7b, 0x7f, 0xff, 0xff,
- 0xf0, 0xa6, 0x02, 0x63, 0x7a, 0xf3, 0x0b, 0x02, 0x4c, 0x3a, 0xe1, 0x3c,
- 0xfd, 0xcb, 0x3d, 0x9d, 0x16, 0x2f, 0xff, 0x10, 0xbb, 0x2c, 0x7d, 0x6f,
- 0xf9, 0xe2, 0xc5, 0x82, 0xeb, 0x15, 0xa3, 0xe1, 0x0d, 0x2e, 0xff, 0xfe,
- 0xdd, 0xbf, 0x90, 0x9d, 0x48, 0x35, 0x26, 0x31, 0x2c, 0x5f, 0xfa, 0x49,
- 0xcf, 0x8e, 0x52, 0x75, 0x8b, 0xec, 0xfb, 0x8d, 0x62, 0x8e, 0x7b, 0xa0,
- 0x3b, 0xbf, 0xfe, 0x68, 0x71, 0xc7, 0xd6, 0x0e, 0x3f, 0x99, 0xc5, 0x8a,
- 0x94, 0xd4, 0x70, 0x8d, 0xa1, 0x70, 0x22, 0x2b, 0xff, 0xc3, 0x79, 0xdc,
- 0xcf, 0xb7, 0x7e, 0xfc, 0xac, 0x5f, 0x6c, 0xc5, 0xd1, 0x62, 0xfe, 0x06,
- 0x17, 0xc4, 0x4b, 0x15, 0x87, 0xa4, 0xc4, 0xb7, 0xff, 0xff, 0xee, 0xbe,
- 0xfb, 0xcf, 0x3a, 0xe0, 0xb7, 0x9e, 0x9d, 0x73, 0x5a, 0xce, 0x82, 0x6f,
- 0xac, 0x5e, 0x86, 0x6c, 0xb1, 0x50, 0x45, 0x63, 0x42, 0x3a, 0xfb, 0xd1,
- 0xa0, 0x54, 0x28, 0xb1, 0x52, 0x7b, 0x18, 0x4f, 0x7d, 0xf2, 0x60, 0x8b,
- 0x17, 0xc7, 0x70, 0x92, 0xb1, 0x52, 0xbd, 0x65, 0x91, 0xd7, 0xe9, 0x0f,
- 0xf2, 0x95, 0x59, 0x00, 0xa1, 0x3f, 0xc8, 0xc9, 0x3c, 0x40, 0x22, 0x4b,
- 0xff, 0xe1, 0x73, 0xf3, 0x91, 0xf8, 0x45, 0x8e, 0x05, 0x8b, 0xfb, 0xbe,
- 0x39, 0xe7, 0x75, 0x8b, 0xe6, 0x18, 0xb8, 0xb1, 0x7f, 0xcf, 0x1e, 0xdf,
- 0xc0, 0x93, 0x12, 0xc5, 0x4a, 0x38, 0x59, 0x43, 0x86, 0x06, 0x11, 0xdf,
- 0x60, 0xcf, 0xc5, 0x8b, 0xfc, 0xdf, 0xe3, 0xf4, 0xc1, 0xac, 0x5e, 0xcc,
- 0xe2, 0xc5, 0xb4, 0xb1, 0x7b, 0xd8, 0x75, 0x8a, 0x93, 0x5f, 0x82, 0x56,
- 0xd8, 0x67, 0xd4, 0xc9, 0x77, 0x8c, 0x8e, 0x65, 0x8b, 0xff, 0xf3, 0xed,
- 0xf6, 0x7f, 0x4f, 0xdf, 0xdc, 0xc1, 0xac, 0x5f, 0xf7, 0x5c, 0xfb, 0xb7,
- 0xbf, 0x2b, 0x15, 0x1e, 0x88, 0xf2, 0x55, 0xa5, 0x8a, 0xfa, 0x38, 0x5a,
- 0x16, 0x06, 0x12, 0xd3, 0x26, 0x7c, 0x28, 0xc2, 0x6f, 0x7e, 0x74, 0xb1,
- 0x7f, 0xfe, 0x71, 0x61, 0x03, 0xae, 0x7c, 0x47, 0x3b, 0x41, 0x62, 0xb7,
- 0x3f, 0x4d, 0x0e, 0xdf, 0xfb, 0xa3, 0x43, 0x08, 0x65, 0x30, 0x58, 0xbf,
- 0xf7, 0x04, 0x3f, 0xbf, 0x5d, 0xb0, 0x35, 0x8b, 0xb6, 0x95, 0x8a, 0xc4,
- 0x4d, 0xf8, 0xfc, 0x48, 0x97, 0xd9, 0xf3, 0xca, 0xc5, 0xf7, 0xc3, 0x6d,
- 0x96, 0x2b, 0x49, 0x9a, 0x14, 0x2f, 0xb8, 0x5f, 0xe2, 0x2b, 0xce, 0x1c,
- 0x4b, 0x17, 0xff, 0xf7, 0xf7, 0x16, 0x03, 0xae, 0x7b, 0x8f, 0xe0, 0x4e,
- 0xcb, 0x17, 0xfc, 0xdf, 0x7e, 0x70, 0x4c, 0x05, 0x8a, 0x1a, 0x2e, 0x30,
- 0x7d, 0x98, 0x2d, 0x19, 0x1b, 0xbe, 0x18, 0xc8, 0x50, 0xa8, 0x2a, 0x81,
- 0x1a, 0x2b, 0x46, 0xc4, 0xd3, 0x2d, 0xdb, 0x68, 0x6d, 0xc2, 0x37, 0xa1,
- 0xca, 0x58, 0xca, 0x5d, 0xa9, 0xb0, 0xe1, 0xde, 0x19, 0xdd, 0xc6, 0xb0,
- 0xf1, 0xc7, 0xc5, 0x1d, 0x3e, 0xa5, 0xf1, 0x1e, 0x3d, 0xbf, 0xcf, 0x14,
- 0xb4, 0xa4, 0x30, 0x43, 0x08, 0x2e, 0x42, 0x53, 0x87, 0xfc, 0x9e, 0x32,
- 0xf4, 0xff, 0xb0, 0xa3, 0x76, 0xe8, 0x78, 0x19, 0x1c, 0x74, 0x7b, 0xa6,
- 0x47, 0xa2, 0x12, 0x1f, 0x57, 0x89, 0xc3, 0x58, 0xbf, 0xdc, 0x7f, 0x4f,
- 0xf7, 0x75, 0x8b, 0xed, 0xd9, 0xb7, 0x54, 0x55, 0x05, 0xfe, 0xd4, 0xf4,
- 0xee, 0x19, 0xe5, 0x8a, 0xd1, 0xf4, 0x08, 0xc6, 0xdd, 0xac, 0x5f, 0xd3,
- 0xee, 0x74, 0xc1, 0xac, 0x54, 0x9e, 0x19, 0xa2, 0x77, 0xf0, 0xb4, 0x0f,
- 0x37, 0x6b, 0x17, 0xfd, 0x9e, 0x6e, 0xfa, 0xed, 0x81, 0xac, 0x5f, 0xf9,
- 0xa1, 0x19, 0x9a, 0xdd, 0x9b, 0x75, 0x44, 0xd6, 0x5f, 0xf7, 0xe4, 0xfc,
- 0xe3, 0x16, 0xeb, 0x17, 0xd3, 0xa9, 0xf2, 0xc5, 0xcd, 0xe5, 0x8a, 0x19,
- 0xb9, 0x39, 0x15, 0xfc, 0x21, 0xe1, 0x34, 0x16, 0x2f, 0xf7, 0x7c, 0x27,
- 0x93, 0x0e, 0xb1, 0x47, 0x3e, 0x26, 0x2d, 0xbf, 0x83, 0xcf, 0xc3, 0x38,
- 0xb1, 0x7f, 0x89, 0xbd, 0xc8, 0xbe, 0xeb, 0x16, 0x8c, 0x82, 0xb7, 0x81,
- 0x8e, 0xe4, 0x27, 0x0d, 0x65, 0xdc, 0x8b, 0x46, 0x07, 0x3e, 0xfa, 0x83,
- 0x39, 0x82, 0x10, 0x7c, 0x21, 0x30, 0xbe, 0xff, 0xf3, 0x8f, 0x0f, 0xd7,
- 0xd9, 0x1e, 0xfd, 0x38, 0xb1, 0x7f, 0x9a, 0x2e, 0x37, 0x85, 0x2b, 0x15,
- 0x1e, 0x88, 0x5d, 0x28, 0xde, 0x66, 0xdd, 0x51, 0x56, 0x17, 0xf4, 0x5c,
- 0x6f, 0x0a, 0x56, 0x2d, 0xad, 0xcf, 0x65, 0x8a, 0xaf, 0x6a, 0x4e, 0xb1,
- 0x7f, 0xd3, 0x09, 0xd6, 0xd3, 0xad, 0x96, 0x2f, 0xfc, 0x43, 0x9e, 0x91,
- 0x3f, 0x42, 0x02, 0xc5, 0xff, 0xce, 0xc0, 0xeb, 0x3b, 0x88, 0x86, 0x25,
- 0x8a, 0x94, 0x45, 0x7d, 0x0e, 0xd1, 0x92, 0x9d, 0x5e, 0x3f, 0xe8, 0xa0,
- 0x87, 0x7d, 0x0c, 0x5b, 0xe2, 0xc1, 0x05, 0xd6, 0x2f, 0xee, 0xfd, 0x3f,
- 0x68, 0xf5, 0x8b, 0xf3, 0x7f, 0x35, 0x8b, 0x15, 0x27, 0xb2, 0xc6, 0x57,
- 0xf7, 0x7c, 0xcf, 0xc9, 0xd6, 0x2f, 0xed, 0x0a, 0x2e, 0x4f, 0x96, 0x2a,
- 0x51, 0xfd, 0xf7, 0xff, 0x10, 0x08, 0xbe, 0xff, 0xe0, 0x61, 0x46, 0x40,
- 0x1c, 0xd9, 0x89, 0x62, 0xa3, 0x11, 0x09, 0x27, 0x97, 0xf0, 0xdc, 0x5e,
- 0xce, 0x2c, 0x5f, 0xce, 0x77, 0xf7, 0xe5, 0x62, 0xfa, 0x62, 0x9e, 0xd6,
- 0x2b, 0xe7, 0xa3, 0xc2, 0xdb, 0xff, 0xf6, 0x85, 0xb0, 0xf4, 0xdb, 0x96,
- 0x74, 0xd3, 0xf1, 0x62, 0xff, 0x3f, 0xe4, 0xe7, 0x68, 0x2c, 0x5f, 0xb5,
- 0xbb, 0x36, 0xea, 0x89, 0x10, 0xbe, 0x63, 0x0d, 0x95, 0x8b, 0xff, 0x60,
- 0x47, 0xdb, 0xbc, 0xd6, 0x99, 0x62, 0xfe, 0x73, 0xec, 0x2d, 0x41, 0x62,
- 0xe8, 0x46, 0x4a, 0x60, 0x18, 0x66, 0x23, 0x7e, 0x84, 0x91, 0xc8, 0x57,
- 0xf6, 0xd3, 0xaf, 0xb3, 0xac, 0x5a, 0x32, 0x37, 0x55, 0x0d, 0x8f, 0xfa,
- 0x22, 0x68, 0xd6, 0xb8, 0xbb, 0x7e, 0xd6, 0xec, 0xdb, 0xaa, 0x2d, 0x22,
- 0xff, 0xcd, 0x08, 0xcc, 0xd6, 0xec, 0xdb, 0xaa, 0x27, 0xd2, 0xd1, 0x98,
- 0x88, 0x73, 0x9b, 0xdf, 0xf9, 0xa1, 0x19, 0x9a, 0xdd, 0x9b, 0x75, 0x45,
- 0x08, 0x5f, 0x89, 0xb9, 0x9e, 0x58, 0xb4, 0x61, 0xcf, 0xdd, 0x94, 0x2f,
- 0xfe, 0xc0, 0xe3, 0x3c, 0x6b, 0x71, 0xfd, 0x2b, 0x17, 0xef, 0x0b, 0x76,
- 0xe2, 0xc5, 0xd3, 0xa5, 0x8b, 0xff, 0xa4, 0xe2, 0xd6, 0xec, 0xe3, 0x98,
- 0x96, 0x2c, 0xfb, 0x1e, 0xec, 0x42, 0xf4, 0x74, 0x58, 0x7e, 0x10, 0xf7,
- 0xed, 0x6e, 0xcd, 0xba, 0xa2, 0x8f, 0x2d, 0x8b, 0x17, 0xf0, 0xbc, 0x77,
- 0x0f, 0x8b, 0x14, 0x33, 0xc1, 0x21, 0x1b, 0xe7, 0xc0, 0x71, 0x62, 0xe6,
- 0xdd, 0x62, 0xd8, 0x33, 0x74, 0x10, 0x8a, 0xfd, 0x3c, 0x88, 0xa5, 0x62,
- 0xff, 0xa6, 0x13, 0xad, 0xa7, 0x5b, 0x2c, 0x5f, 0xff, 0xff, 0xe3, 0x1f,
- 0x51, 0x4f, 0xf5, 0x9f, 0x63, 0x39, 0x86, 0xb1, 0x02, 0x4a, 0x62, 0xfc,
- 0xac, 0x5f, 0x9b, 0x8f, 0xe9, 0x58, 0xbf, 0xe9, 0x8a, 0x4a, 0x62, 0xfc,
- 0xac, 0x54, 0xa3, 0xc0, 0xd8, 0x48, 0x11, 0x3d, 0xf1, 0xf6, 0xc0, 0xd6,
- 0x2f, 0xff, 0xc3, 0xfc, 0x99, 0x19, 0xe2, 0x60, 0x73, 0x92, 0x04, 0x8a,
- 0x93, 0xff, 0xc2, 0x5b, 0xcd, 0x08, 0xc9, 0x56, 0x93, 0x85, 0x11, 0x3c,
- 0x69, 0x6f, 0xe5, 0x04, 0x51, 0xe8, 0xca, 0xe3, 0xa1, 0x67, 0x7f, 0xf6,
- 0x7e, 0x33, 0xc6, 0xb7, 0x1f, 0xd2, 0xb1, 0x7f, 0xff, 0xf3, 0xed, 0x18,
- 0xfe, 0xc8, 0x89, 0xf9, 0xe9, 0x31, 0xf5, 0x14, 0xfd, 0x62, 0xd1, 0x9b,
- 0x2e, 0xca, 0x1e, 0x71, 0x0b, 0xd0, 0x93, 0x08, 0x91, 0x52, 0xff, 0x87,
- 0x1b, 0x5a, 0x05, 0x18, 0x43, 0xc7, 0x25, 0x52, 0x9b, 0x78, 0x6f, 0x9b,
- 0xce, 0xe4, 0xf7, 0x2b, 0xad, 0xe3, 0xd8, 0x8a, 0x55, 0x5f, 0xe1, 0xca,
- 0x08, 0x51, 0x7a, 0x76, 0xfa, 0xff, 0xf8, 0x3d, 0xc2, 0x81, 0x50, 0x05,
- 0xf5, 0x1a, 0x75, 0xeb, 0xf8, 0xe5, 0x8b, 0xff, 0xff, 0x04, 0xf4, 0x6c,
- 0x33, 0xc6, 0xc4, 0xe1, 0x6b, 0xe0, 0xbe, 0xa3, 0x4e, 0xbd, 0x7f, 0x1c,
- 0xb1, 0x5f, 0x4c, 0x04, 0x36, 0xeb, 0xff, 0xbf, 0x2f, 0xa7, 0x0b, 0xef,
- 0xf9, 0x0d, 0x62, 0xff, 0xfc, 0x16, 0x1b, 0xd8, 0x58, 0x16, 0x05, 0x08,
- 0xf1, 0xab, 0xaf, 0x5f, 0xc7, 0x2c, 0x5f, 0xfb, 0x81, 0x77, 0x37, 0xaf,
- 0x5f, 0xc7, 0x46, 0x4a, 0x3a, 0xb7, 0x25, 0xe2, 0x55, 0xff, 0xff, 0xfe,
- 0x08, 0x17, 0x73, 0x7a, 0xf5, 0xfc, 0x74, 0x64, 0xfc, 0x3d, 0xc2, 0x81,
- 0x50, 0x05, 0xf5, 0x1a, 0x75, 0xeb, 0xf8, 0xe5, 0x8b, 0xf6, 0xb7, 0x66,
- 0xdd, 0x51, 0x11, 0x17, 0xe7, 0xf4, 0x46, 0x0d, 0x62, 0xff, 0x70, 0x53,
- 0x17, 0x9f, 0xa2, 0xc5, 0xa3, 0x31, 0x13, 0x3b, 0x9b, 0xc4, 0x57, 0x7f,
- 0x66, 0xb7, 0x66, 0xdd, 0x51, 0x15, 0x97, 0xed, 0x6e, 0xcd, 0xba, 0xa2,
- 0xb8, 0x2e, 0x9f, 0xac, 0x5d, 0x1f, 0x19, 0x87, 0x9d, 0xd0, 0xde, 0xa3,
- 0x11, 0x7e, 0xd0, 0x8a, 0xbe, 0xfb, 0x69, 0xd6, 0x2f, 0xde, 0x01, 0x85,
- 0x05, 0x8b, 0xf0, 0x24, 0xb7, 0x8c, 0x93, 0xcc, 0x62, 0x2b, 0xa2, 0x8f,
- 0x58, 0xbf, 0x89, 0xf7, 0xf4, 0xc1, 0x62, 0xd1, 0x9b, 0x1e, 0x56, 0x87,
- 0x2c, 0xfd, 0xa2, 0xd8, 0x10, 0x8a, 0xbf, 0xc1, 0x50, 0xa1, 0x4e, 0xed,
- 0xda, 0xc5, 0xf6, 0x7d, 0xbc, 0xb1, 0x7f, 0xb1, 0xf4, 0x00, 0x0b, 0x8b,
- 0x16, 0x0a, 0x91, 0xeb, 0x70, 0x8a, 0xff, 0xff, 0xff, 0x05, 0x23, 0x70,
- 0xac, 0xf3, 0xf8, 0x6e, 0x0c, 0xb3, 0x67, 0x87, 0x24, 0x73, 0xf2, 0x68,
- 0xf5, 0x8b, 0xff, 0xfd, 0xfc, 0x14, 0x3f, 0x9d, 0x1a, 0x3d, 0x8b, 0xdf,
- 0xc8, 0x2c, 0x5f, 0xf4, 0x96, 0xed, 0xf6, 0x21, 0xac, 0x5f, 0xa7, 0xcc,
- 0x58, 0xb1, 0x46, 0x9e, 0xf6, 0x8e, 0x2f, 0xff, 0xed, 0x4e, 0xc7, 0x78,
- 0x60, 0xb7, 0x2c, 0xdb, 0x52, 0xb1, 0x7e, 0x26, 0xf4, 0xee, 0xb1, 0x7f,
- 0xfe, 0xe3, 0xfd, 0x9e, 0x0e, 0x5e, 0x17, 0xf5, 0x8b, 0x17, 0xfe, 0x29,
- 0x09, 0x3f, 0x72, 0x93, 0xac, 0x54, 0x13, 0xfd, 0x78, 0x61, 0xe8, 0x8f,
- 0x8b, 0xbe, 0x28, 0x08, 0xa9, 0x7e, 0xc0, 0xc1, 0xc7, 0x58, 0xbf, 0x03,
- 0x9e, 0x29, 0x58, 0xbf, 0xde, 0xe4, 0xc4, 0xcd, 0xa5, 0x8a, 0x93, 0xdc,
- 0x72, 0x8b, 0xec, 0x3b, 0x79, 0x62, 0xfe, 0x63, 0x43, 0x6d, 0x71, 0x62,
- 0xbe, 0x7a, 0x4c, 0x45, 0x7f, 0xfe, 0xfe, 0x16, 0x1b, 0xf6, 0x87, 0xc3,
- 0x63, 0x0e, 0xb1, 0x7f, 0xf0, 0xe4, 0x03, 0x66, 0x0c, 0x78, 0x4b, 0x17,
- 0x99, 0xb7, 0x54, 0x53, 0xc5, 0x0c, 0xfb, 0xb7, 0x44, 0xbd, 0x25, 0xe5,
- 0x8b, 0xff, 0x4f, 0x42, 0xce, 0x61, 0x39, 0xd6, 0x2f, 0x3e, 0xbe, 0xe7,
- 0xb4, 0xc3, 0x97, 0xfc, 0xc7, 0xe3, 0xe7, 0x46, 0xd2, 0xc5, 0xff, 0x8a,
- 0x7a, 0x3f, 0xa1, 0x38, 0x4b, 0x15, 0x04, 0xfb, 0x35, 0x0c, 0x6f, 0xbe,
- 0x91, 0x8f, 0x8e, 0xaf, 0xf0, 0xc1, 0xd6, 0x63, 0xe6, 0x0b, 0x17, 0xf8,
- 0xee, 0x31, 0x36, 0xa0, 0xb1, 0x71, 0xdd, 0x62, 0xa4, 0xf2, 0xf7, 0x34,
- 0xbf, 0xff, 0xa7, 0xdc, 0x11, 0xf7, 0x70, 0x4e, 0x7d, 0xc5, 0xba, 0xc5,
- 0xcf, 0xc5, 0x8b, 0xfa, 0x4f, 0xc9, 0x7d, 0x96, 0x2a, 0x08, 0xa2, 0xc5,
- 0xdf, 0x0b, 0xdf, 0xff, 0xcd, 0xa6, 0xff, 0x70, 0xcf, 0x61, 0x0b, 0xc2,
- 0x35, 0x62, 0xfa, 0x13, 0x9b, 0x2c, 0x5f, 0xff, 0xb4, 0x2d, 0x6a, 0x4b,
- 0x0d, 0x7f, 0xff, 0x0c, 0x58, 0xb0, 0xd6, 0x2e, 0x7e, 0x8b, 0x16, 0x75,
- 0x8a, 0xdd, 0x31, 0x3e, 0xd7, 0x74, 0x46, 0x75, 0x70, 0x09, 0x74, 0x19,
- 0xbc, 0xe5, 0xe5, 0x8b, 0xf3, 0x9c, 0x63, 0xc5, 0x8b, 0xdb, 0x4e, 0xeb,
- 0x17, 0xf0, 0xf2, 0x1f, 0x9d, 0xd6, 0x2f, 0xfc, 0xc3, 0x9c, 0x2f, 0x72,
- 0x49, 0x62, 0xf3, 0x42, 0x31, 0xd1, 0x14, 0xc3, 0xe4, 0x5f, 0x7e, 0x30,
- 0x8c, 0xef, 0x8b, 0x17, 0x89, 0xc0, 0xb1, 0x43, 0x3c, 0x83, 0x96, 0x5f,
- 0xf6, 0x9b, 0x61, 0x89, 0xb5, 0x05, 0x8b, 0xff, 0x70, 0x5a, 0x76, 0x71,
- 0xc9, 0x2c, 0x5f, 0xe9, 0x3c, 0xc6, 0x06, 0x18, 0x6b, 0x14, 0xe7, 0xee,
- 0x10, 0xf6, 0xa5, 0x1e, 0xee, 0x44, 0xd0, 0xb2, 0xbf, 0x9c, 0x78, 0x71,
- 0x79, 0x62, 0xff, 0xb0, 0x81, 0x27, 0x7d, 0x41, 0x62, 0xff, 0x3f, 0x1c,
- 0x41, 0x71, 0xca, 0xc5, 0x40, 0xfb, 0xfc, 0x71, 0x7e, 0xd4, 0xc1, 0xc0,
- 0xb1, 0x7f, 0xfc, 0x7c, 0x7f, 0x0b, 0xd3, 0x07, 0x1e, 0x0d, 0x62, 0xa0,
- 0x99, 0xb3, 0xc2, 0x77, 0x44, 0x40, 0x28, 0xbf, 0x6b, 0x69, 0xd6, 0xcb,
- 0x17, 0xe7, 0x2f, 0x18, 0x75, 0x8a, 0x93, 0xd4, 0x01, 0x5d, 0xfe, 0xd4,
- 0xcf, 0xb8, 0xfd, 0x16, 0x2f, 0xe9, 0xd9, 0x86, 0xde, 0x58, 0xa8, 0x22,
- 0x10, 0xe4, 0x21, 0x0d, 0x6f, 0xd2, 0x7d, 0xc0, 0x4b, 0x17, 0xdd, 0x49,
- 0xa0, 0xb1, 0x7e, 0x6c, 0xfb, 0x9d, 0x62, 0xa2, 0x3f, 0x4e, 0x14, 0xf4,
- 0x24, 0xba, 0x42, 0x2c, 0x54, 0xa3, 0xc7, 0x21, 0x4d, 0x11, 0x95, 0xfc,
- 0xfe, 0x63, 0x7e, 0xeb, 0x17, 0xfd, 0x3b, 0xfd, 0x9e, 0x3a, 0x74, 0xb1,
- 0x7f, 0x98, 0xfd, 0x47, 0xf7, 0x3a, 0xc5, 0x1c, 0xfc, 0xba, 0x1e, 0x5f,
- 0xf1, 0x49, 0xe6, 0x05, 0x87, 0x58, 0xbf, 0xf1, 0x30, 0x7e, 0xcf, 0xb3,
- 0xc4, 0xb1, 0x7f, 0xf8, 0xf3, 0xad, 0xa7, 0xbc, 0x10, 0x5f, 0x06, 0xb1,
- 0x7f, 0xfb, 0x3c, 0x20, 0x1d, 0xa1, 0xd7, 0x4d, 0xc5, 0x8b, 0xef, 0x42,
- 0x4d, 0x58, 0xa8, 0x27, 0xf7, 0x90, 0xa0, 0x72, 0x48, 0x8d, 0xd8, 0xfc,
- 0x94, 0x0c, 0x4d, 0xbe, 0xc7, 0x28, 0x96, 0x2f, 0xbd, 0x1a, 0x05, 0x42,
- 0x8b, 0x17, 0xb5, 0x3b, 0x2c, 0x56, 0x1e, 0x7b, 0x98, 0xd6, 0xe8, 0x91,
- 0xe3, 0x8d, 0xfe, 0x2d, 0xf3, 0xa6, 0x7b, 0x8b, 0x17, 0xe1, 0x8a, 0x75,
- 0xb2, 0xc5, 0xff, 0xf7, 0x81, 0x30, 0xce, 0x8f, 0xe9, 0xc2, 0x82, 0xc5,
- 0xcc, 0x6a, 0xc5, 0x4a, 0x32, 0x30, 0xd9, 0xca, 0xb4, 0xa1, 0x7b, 0xdf,
- 0x75, 0x8b, 0xb4, 0x25, 0x8b, 0xec, 0xf6, 0x1d, 0x62, 0xdb, 0x49, 0xba,
- 0x61, 0x8a, 0xc3, 0xfd, 0x65, 0x7b, 0xf7, 0xbe, 0x1b, 0x6c, 0xb1, 0x7e,
- 0x71, 0x14, 0x79, 0xab, 0x15, 0x1a, 0x36, 0x9e, 0x71, 0xb4, 0x24, 0xc2,
- 0xc2, 0xb9, 0x95, 0x37, 0xb2, 0xf4, 0x21, 0x0a, 0x37, 0x2c, 0x94, 0x1a,
- 0x6a, 0x7e, 0xf0, 0x84, 0xee, 0x18, 0x8f, 0x1a, 0x14, 0x4b, 0x9a, 0x1c,
- 0x3c, 0x2c, 0xbf, 0x1c, 0x03, 0x46, 0xd0, 0x52, 0x82, 0xf9, 0x28, 0xbf,
- 0xd0, 0xf9, 0xe9, 0x0e, 0xc8, 0xe8, 0x5b, 0x98, 0x40, 0x10, 0xae, 0xfe,
- 0xcf, 0x73, 0x1a, 0x3d, 0x62, 0xfe, 0x60, 0xf9, 0xc9, 0x02, 0xc5, 0x49,
- 0xef, 0x91, 0x85, 0xfb, 0xc6, 0x6c, 0x20, 0xba, 0xc5, 0xfa, 0x3a, 0x40,
- 0xde, 0x58, 0xb6, 0xcb, 0x17, 0x9a, 0x11, 0x83, 0x44, 0x76, 0x10, 0x39,
- 0x80, 0x65, 0x77, 0xff, 0x80, 0x01, 0x72, 0x30, 0xc2, 0x63, 0x94, 0xac,
- 0x5f, 0xff, 0xfb, 0xdc, 0x10, 0xfe, 0xf1, 0x9e, 0x13, 0x10, 0x38, 0x64,
- 0xe8, 0x0b, 0x17, 0xff, 0x16, 0x01, 0x88, 0x11, 0x87, 0x73, 0xac, 0x56,
- 0x93, 0x06, 0x24, 0xef, 0x39, 0x5f, 0xf0, 0x71, 0x85, 0x91, 0x40, 0x5e,
- 0x58, 0xbf, 0xfb, 0xef, 0xc8, 0xc3, 0xbe, 0xb8, 0x23, 0xac, 0x54, 0xa2,
- 0x23, 0x73, 0xfb, 0xff, 0xff, 0xcf, 0x0c, 0x28, 0xc2, 0xcd, 0xcb, 0x36,
- 0xe1, 0x67, 0xbc, 0xe0, 0xe2, 0xc5, 0xff, 0xc2, 0xf4, 0x1c, 0x11, 0x9e,
- 0x35, 0xc9, 0x62, 0xfc, 0xdf, 0xfb, 0xc4, 0xb1, 0x7f, 0xf6, 0x71, 0xc8,
- 0x05, 0x9e, 0xfe, 0x2c, 0x5f, 0xf9, 0xc8, 0x05, 0x9e, 0xfe, 0x46, 0x7c,
- 0xfa, 0xcc, 0x29, 0xa8, 0xc5, 0xe5, 0x51, 0xca, 0xa0, 0x78, 0xd5, 0xb5,
- 0x0b, 0x80, 0x11, 0x93, 0xcf, 0x21, 0x69, 0x78, 0xbb, 0x02, 0xc5, 0xb1,
- 0x62, 0xfc, 0x52, 0x20, 0xbf, 0x16, 0x2e, 0x7f, 0xac, 0x5f, 0xff, 0x30,
- 0xcd, 0x6f, 0x67, 0xcb, 0x3d, 0xf7, 0x58, 0xbf, 0x8d, 0xd3, 0x0d, 0x89,
- 0x62, 0xa5, 0x1d, 0xe3, 0x1e, 0xc1, 0x1d, 0x16, 0x7c, 0x5d, 0x93, 0xef,
- 0xfe, 0x71, 0xe9, 0xbb, 0x8c, 0xd6, 0xa7, 0x65, 0x8a, 0x8c, 0x44, 0xf7,
- 0xd5, 0x2d, 0x2b, 0x17, 0xf7, 0x27, 0x72, 0x91, 0xac, 0x50, 0xcd, 0xfb,
- 0x88, 0xdf, 0x37, 0x63, 0x95, 0x8b, 0xff, 0xe9, 0xd6, 0x41, 0xdb, 0xd8,
- 0x37, 0x16, 0xe9, 0x17, 0x0b, 0xb5, 0x8a, 0xf9, 0xf4, 0x12, 0x7d, 0xe7,
- 0x07, 0x16, 0x2d, 0xba, 0xc5, 0xfa, 0x60, 0x01, 0x41, 0x62, 0xfb, 0x76,
- 0x6d, 0xd5, 0x15, 0x99, 0x74, 0x86, 0xb1, 0x5b, 0x22, 0x8b, 0x07, 0x62,
- 0x13, 0xd1, 0x4f, 0x43, 0x1b, 0xef, 0x39, 0xf8, 0xb1, 0x6d, 0x2c, 0x58,
- 0xd5, 0x8a, 0x73, 0x4b, 0xc1, 0x2b, 0xdc, 0x16, 0xeb, 0x14, 0x69, 0xbf,
- 0xe1, 0x05, 0x8c, 0x58, 0xbf, 0xe9, 0xd8, 0xb3, 0xa6, 0x9f, 0x8b, 0x17,
- 0xb5, 0x3d, 0x16, 0x2a, 0x4f, 0xb6, 0x02, 0x7c, 0x3b, 0xbf, 0xba, 0x11,
- 0x4c, 0x7c, 0x4b, 0x17, 0xe3, 0xc9, 0x43, 0x8b, 0x17, 0x4c, 0x4b, 0x15,
- 0x27, 0xe7, 0xb1, 0x9e, 0x8a, 0x2f, 0xbd, 0xc3, 0x38, 0xb1, 0x7d, 0xce,
- 0x48, 0x6b, 0x17, 0xff, 0x9b, 0xdc, 0xf3, 0xf7, 0xce, 0x9e, 0xd8, 0x96,
- 0x2c, 0xcb, 0x15, 0x88, 0xa9, 0x72, 0x52, 0x24, 0xe2, 0x7d, 0xdb, 0x3a,
- 0xc5, 0xee, 0x7c, 0x4b, 0x17, 0xf4, 0x4e, 0x5f, 0xce, 0xd6, 0x2b, 0x0f,
- 0x37, 0x83, 0xd5, 0x28, 0x86, 0xc6, 0x5b, 0x9b, 0xcb, 0x17, 0xc0, 0x30,
- 0xa0, 0xb4, 0x14, 0x33, 0x7f, 0xe1, 0x7b, 0xff, 0xe9, 0x3f, 0xb3, 0x0b,
- 0xdc, 0xfe, 0x01, 0x96, 0x2f, 0xf1, 0xe7, 0xbe, 0x6a, 0x7a, 0x2c, 0x5c,
- 0xdc, 0x58, 0xa9, 0x3c, 0xe1, 0x1b, 0xdf, 0xce, 0x28, 0xf8, 0xd0, 0x07,
- 0x58, 0xbe, 0xf3, 0x02, 0x56, 0x2a, 0x07, 0xb3, 0xd9, 0xbd, 0xf8, 0xa7,
- 0xef, 0x8b, 0x17, 0x4c, 0x16, 0x2b, 0x0f, 0x81, 0x88, 0xc0, 0x4d, 0x77,
- 0x7e, 0x58, 0xbd, 0xa0, 0x71, 0x63, 0x0b, 0x9b, 0xe9, 0x04, 0xc1, 0x62,
- 0xce, 0xb1, 0x78, 0x9b, 0xcb, 0x1c, 0x2c, 0x6d, 0x90, 0x3d, 0xe2, 0x33,
- 0xbc, 0x28, 0x0d, 0x62, 0x9d, 0x19, 0xdf, 0x84, 0x51, 0x13, 0x5f, 0xa2,
- 0xfb, 0x96, 0xcb, 0x17, 0xde, 0xfc, 0xf4, 0x58, 0xae, 0xcf, 0x3c, 0x8a,
- 0xaf, 0x33, 0x1d, 0x62, 0xff, 0x66, 0xbf, 0x3d, 0xfb, 0x16, 0x2f, 0xcd,
- 0xb0, 0x1f, 0xcb, 0x17, 0xec, 0x8b, 0x61, 0x01, 0x62, 0xfe, 0xf4, 0xe8,
- 0x13, 0x12, 0xc5, 0xa3, 0x25, 0x93, 0x19, 0x02, 0x01, 0xc2, 0x2f, 0x21,
- 0x87, 0xda, 0x6b, 0xc2, 0x1e, 0x28, 0x47, 0xea, 0x14, 0x27, 0x86, 0xc7,
- 0xe1, 0x80, 0xcc, 0x00, 0x21, 0x28, 0x4e, 0x72, 0x1b, 0x5e, 0x8c, 0x50,
- 0x50, 0x82, 0xe8, 0x44, 0x18, 0xe4, 0x71, 0xa1, 0x85, 0x21, 0x0a, 0xef,
- 0xd8, 0x73, 0x26, 0x3d, 0x62, 0xfe, 0xe7, 0x24, 0x06, 0x6c, 0xb1, 0x50,
- 0x3d, 0xdc, 0x2c, 0xbf, 0xde, 0x6d, 0x6d, 0x2e, 0x35, 0x8b, 0xfb, 0xdc,
- 0x1b, 0xc9, 0x2c, 0x53, 0x9f, 0x0b, 0x1a, 0x5f, 0xd2, 0x7d, 0x85, 0xa8,
- 0x2c, 0x5f, 0x6b, 0x03, 0xf2, 0xc5, 0x7c, 0xfd, 0x3c, 0x41, 0xd0, 0xc2,
- 0xff, 0x6d, 0xfc, 0xdf, 0xf3, 0xa5, 0x8b, 0xfe, 0x92, 0x87, 0x0e, 0xc4,
- 0x6a, 0xc5, 0x49, 0xf7, 0xf8, 0xda, 0xe9, 0x1a, 0xc5, 0xff, 0x08, 0xf9,
- 0xbe, 0xbb, 0x60, 0xd6, 0x2a, 0x07, 0xeb, 0xc2, 0x1f, 0x0b, 0xdf, 0xed,
- 0x49, 0xb8, 0x4e, 0x6a, 0xc5, 0xff, 0xf3, 0x36, 0xdf, 0x79, 0x28, 0x3f,
- 0xdb, 0x8b, 0x17, 0xf4, 0x35, 0xa9, 0x3f, 0x16, 0x2f, 0xf3, 0xe8, 0xc1,
- 0xfe, 0x60, 0xb1, 0x71, 0xe5, 0x62, 0x86, 0x7f, 0x6c, 0x5e, 0x10, 0xd6,
- 0xff, 0xf8, 0x7f, 0x9e, 0x75, 0xc7, 0xd3, 0x9e, 0x4d, 0x58, 0xb4, 0xac,
- 0x5a, 0x56, 0x2b, 0x0f, 0xd3, 0x8a, 0x42, 0x11, 0xbc, 0x4d, 0xe5, 0x8b,
- 0xf6, 0x76, 0x09, 0xfa, 0xc5, 0xff, 0xc1, 0x98, 0x72, 0xce, 0xfd, 0x38,
- 0x1a, 0xc5, 0xff, 0x3c, 0x1f, 0xe2, 0x39, 0xdd, 0x62, 0xa5, 0x10, 0x3e,
- 0x48, 0xbf, 0x79, 0xcb, 0x0e, 0xb1, 0x79, 0x8a, 0x30, 0x6b, 0xa3, 0x19,
- 0x0f, 0x6e, 0xe3, 0x15, 0xd1, 0x79, 0xcd, 0x3f, 0x0c, 0x92, 0x85, 0x27,
- 0x42, 0xe8, 0xe1, 0xc3, 0x21, 0x54, 0x10, 0x8a, 0xfa, 0x4f, 0xdc, 0xac,
- 0x5f, 0xf1, 0x7b, 0xf9, 0x07, 0x06, 0x2c, 0x5f, 0xf8, 0x45, 0xef, 0xe0,
- 0x47, 0x06, 0x2c, 0x5f, 0xf6, 0x7b, 0xf9, 0x07, 0x06, 0x2c, 0x5f, 0xcf,
- 0x80, 0x6e, 0xdd, 0x62, 0xf3, 0x07, 0x18, 0x34, 0xc0, 0x30, 0x8c, 0xe7,
- 0x04, 0x81, 0xe3, 0x8a, 0x82, 0xa2, 0xd2, 0x8f, 0x3e, 0xff, 0xcd, 0x08,
- 0xcc, 0xd6, 0xec, 0xdb, 0xaa, 0x24, 0x52, 0xff, 0xfd, 0xef, 0xe1, 0x46,
- 0x79, 0x9b, 0xbe, 0x1a, 0x6b, 0x2c, 0x5f, 0xf9, 0xbd, 0x19, 0x2f, 0xa7,
- 0xf0, 0x96, 0x2a, 0x31, 0x1d, 0x92, 0xa0, 0xcb, 0x77, 0xfd, 0xad, 0x38,
- 0x79, 0x13, 0x9d, 0x62, 0xfb, 0x79, 0xfc, 0xac, 0x53, 0x9e, 0xf1, 0x1d,
- 0xdf, 0xb5, 0xbb, 0x36, 0xea, 0x8b, 0x24, 0xb7, 0x16, 0x2a, 0x4f, 0xa7,
- 0x08, 0x0e, 0x6f, 0x7f, 0x40, 0xa7, 0xec, 0x75, 0x8b, 0xe7, 0x28, 0x71,
- 0x62, 0xfd, 0x3c, 0xf3, 0xec, 0xb1, 0x5b, 0x1e, 0x59, 0xa4, 0x57, 0xf8,
- 0x5b, 0x7e, 0x7d, 0xc7, 0x58, 0xbf, 0x84, 0x37, 0xd3, 0x71, 0x62, 0xe6,
- 0xe2, 0xc5, 0x2c, 0x56, 0x8d, 0x1f, 0x85, 0xef, 0xb3, 0x61, 0x76, 0xb1,
- 0x4e, 0x78, 0xc4, 0x43, 0x7d, 0x99, 0xdc, 0x16, 0x2f, 0xde, 0xe1, 0x9c,
- 0x8c, 0x94, 0xea, 0xf1, 0xe3, 0x44, 0x9c, 0x35, 0xf4, 0x25, 0xc2, 0x10,
- 0x54, 0x62, 0xa5, 0x7c, 0x8f, 0x62, 0xff, 0xd0, 0xe3, 0xf8, 0xe7, 0x9f,
- 0x71, 0x62, 0xfe, 0x9e, 0xe1, 0xb6, 0x06, 0xb1, 0x7e, 0x93, 0xb0, 0xe3,
- 0x3b, 0x3f, 0x1f, 0x20, 0x5f, 0x60, 0x7c, 0xfa, 0xc5, 0xf4, 0x9d, 0xc3,
- 0x58, 0xbf, 0x9c, 0xf3, 0xf3, 0x06, 0xb1, 0x51, 0x1e, 0x90, 0x42, 0x3b,
- 0xd3, 0x0e, 0x2c, 0x5f, 0x4e, 0x10, 0xd6, 0x2e, 0xfb, 0xe8, 0xdf, 0x1c,
- 0x76, 0xf9, 0xe4, 0x41, 0x75, 0x8b, 0xcd, 0xe9, 0x58, 0xbf, 0x8f, 0xe7,
- 0xfb, 0x1d, 0x62, 0xff, 0xf3, 0xfb, 0xf9, 0xec, 0x29, 0xf4, 0x8d, 0x62,
- 0xa4, 0xfd, 0x98, 0xba, 0xf9, 0xe3, 0x66, 0xdd, 0x62, 0xf0, 0xb0, 0x6b,
- 0x17, 0xf9, 0xfc, 0x2d, 0x37, 0x23, 0x36, 0x54, 0x45, 0x8e, 0xdb, 0xb1,
- 0xe8, 0xb0, 0xe4, 0xdf, 0x84, 0x97, 0x88, 0x23, 0x8a, 0x29, 0xd5, 0x85,
- 0xb4, 0xa6, 0x4b, 0xff, 0x14, 0xf7, 0x0f, 0x39, 0x03, 0x8b, 0x17, 0xb4,
- 0xe6, 0xac, 0x5f, 0xbc, 0xdd, 0x82, 0x30, 0x67, 0xba, 0x73, 0xfb, 0xfb,
- 0x35, 0xbb, 0x36, 0xea, 0x8b, 0x60, 0xbf, 0xff, 0x7f, 0xa9, 0x66, 0xbd,
- 0xcf, 0xc5, 0xd7, 0xaf, 0xe3, 0x96, 0x2f, 0xdf, 0x6d, 0x39, 0xd6, 0x28,
- 0x2a, 0x88, 0xad, 0xd8, 0xaf, 0xd9, 0xd3, 0x4d, 0xc5, 0x8b, 0xff, 0x6b,
- 0x69, 0xf3, 0xbc, 0x39, 0x2b, 0x17, 0xb4, 0x2f, 0xac, 0x5f, 0xfd, 0x23,
- 0xce, 0xfc, 0x6b, 0x01, 0xfc, 0xb1, 0x77, 0xa3, 0x25, 0x1e, 0xa3, 0x28,
- 0xc2, 0xad, 0x1f, 0x98, 0x3d, 0x51, 0x8a, 0x84, 0xde, 0x3b, 0xbb, 0xd9,
- 0xcc, 0x58, 0xbe, 0xdd, 0x9b, 0x75, 0x45, 0xb6, 0x5c, 0xda, 0x58, 0xb4,
- 0x16, 0x2d, 0xcd, 0x8d, 0x48, 0x85, 0xeb, 0x48, 0x82, 0xf2, 0xd5, 0xfb,
- 0xfe, 0x70, 0x09, 0x62, 0xff, 0xf4, 0xed, 0xe7, 0x1e, 0x14, 0x1f, 0xe2,
- 0x58, 0xa7, 0x3f, 0x3f, 0x94, 0xdf, 0x9a, 0x22, 0x93, 0xac, 0x5f, 0xa1,
- 0x19, 0xc3, 0xca, 0xc5, 0xfe, 0x84, 0xeb, 0x69, 0xd6, 0xcb, 0x17, 0xb4,
- 0x67, 0x96, 0x2a, 0x4f, 0x57, 0x0d, 0xaf, 0xa6, 0x2e, 0x3a, 0xc5, 0x41,
- 0x52, 0x0e, 0x42, 0x7a, 0x28, 0x4b, 0x1c, 0x85, 0x8a, 0x0a, 0x10, 0x21,
- 0x08, 0x2f, 0xfc, 0x3d, 0x38, 0xb6, 0x8c, 0xe6, 0xbc, 0xb1, 0x51, 0x88,
- 0xba, 0xc7, 0x5b, 0xff, 0xfe, 0xf3, 0x9b, 0x19, 0xe1, 0x34, 0x44, 0xc1,
- 0xea, 0x7c, 0xde, 0x58, 0xbf, 0xd9, 0xce, 0x48, 0x0c, 0xd9, 0x62, 0xf7,
- 0xf3, 0x65, 0x8b, 0xf9, 0x87, 0x98, 0x46, 0xac, 0x5f, 0xdf, 0x7d, 0x69,
- 0xa0, 0xb1, 0x7f, 0xef, 0x3c, 0x1f, 0xe2, 0x39, 0xdd, 0x62, 0x86, 0x8e,
- 0xe8, 0x8d, 0x8e, 0x3d, 0xc2, 0xd3, 0x0b, 0xaf, 0xf6, 0x46, 0x6b, 0x23,
- 0x9c, 0xd5, 0x8b, 0x02, 0x31, 0x10, 0xd1, 0xc9, 0x96, 0xcf, 0xaa, 0x0f,
- 0x28, 0xf8, 0x2f, 0xfe, 0x29, 0x04, 0x61, 0x64, 0x50, 0x9e, 0xd6, 0x2c,
- 0x4b, 0x16, 0x82, 0xc5, 0x46, 0xc6, 0x8c, 0x62, 0x37, 0xa3, 0x6f, 0x8d,
- 0x62, 0xf6, 0xdf, 0x75, 0x8b, 0xff, 0x46, 0xd1, 0xb0, 0x5b, 0xf7, 0xf0,
- 0xa4, 0x0b, 0x17, 0x82, 0xc8, 0xd6, 0x16, 0x2c, 0x5f, 0x4f, 0xda, 0x25,
- 0x8b, 0xdd, 0x05, 0x05, 0x8a, 0xf1, 0xe1, 0xf4, 0x23, 0xbf, 0x14, 0x06,
- 0x23, 0xac, 0x5f, 0xc1, 0x99, 0x1c, 0xc4, 0x05, 0x8a, 0x93, 0xdc, 0xc2,
- 0x9b, 0xf9, 0xcc, 0x8b, 0x82, 0xed, 0x62, 0xfb, 0x7f, 0x8b, 0x4b, 0x16,
- 0x8d, 0x96, 0x28, 0x66, 0xf3, 0x44, 0xb5, 0xf4, 0x47, 0xb3, 0x75, 0xff,
- 0x66, 0xb5, 0x30, 0x6e, 0xc3, 0x58, 0xbf, 0xff, 0x68, 0x1f, 0xce, 0x7f,
- 0x3d, 0xc7, 0x2e, 0xe0, 0xb1, 0x7f, 0xf8, 0xd3, 0x58, 0x39, 0xd7, 0xc3,
- 0x62, 0xd9, 0x62, 0xa5, 0x14, 0xce, 0xaf, 0x7f, 0x84, 0x33, 0x36, 0x66,
- 0x1a, 0xc5, 0xff, 0xd1, 0x7c, 0x51, 0xfe, 0x03, 0x94, 0x38, 0xb1, 0x7d,
- 0xbb, 0x36, 0xea, 0x8b, 0xc0, 0xbf, 0x7b, 0xbd, 0xdf, 0x4b, 0x17, 0xfc,
- 0x0e, 0x75, 0xe0, 0x1b, 0x22, 0x58, 0xbf, 0xda, 0xd6, 0x7b, 0x92, 0x75,
- 0x8a, 0x73, 0xf1, 0x63, 0xdb, 0xc3, 0x7f, 0x2c, 0x5f, 0xe9, 0xe9, 0xad,
- 0x67, 0x7c, 0x58, 0xb3, 0x1c, 0xf5, 0x3c, 0x3b, 0x7e, 0xd6, 0x74, 0x6d,
- 0x2c, 0x5f, 0xfb, 0x46, 0x79, 0xfe, 0x59, 0xec, 0x58, 0xa7, 0x3e, 0x96,
- 0x2a, 0xa8, 0x2a, 0x92, 0x19, 0x0b, 0x9b, 0x69, 0x28, 0xe6, 0x3f, 0x84,
- 0xe1, 0x3a, 0x74, 0x84, 0x85, 0xf7, 0x82, 0xd7, 0x22, 0x58, 0xba, 0x65,
- 0x62, 0xb4, 0x78, 0x3e, 0x2b, 0xbf, 0x6c, 0x52, 0xe3, 0x58, 0xbf, 0xfc,
- 0xfe, 0xfb, 0xb0, 0x3b, 0x80, 0x9b, 0xcb, 0x17, 0xff, 0xce, 0x79, 0xdf,
- 0xae, 0x1f, 0x0b, 0xd1, 0xd8, 0xb1, 0x52, 0x8c, 0x71, 0x94, 0x7d, 0x2e,
- 0xe6, 0xe2, 0xc5, 0xe8, 0xec, 0xfa, 0xc5, 0x00, 0xdb, 0xf8, 0x5e, 0xff,
- 0x87, 0xa9, 0xf3, 0xee, 0xe3, 0x58, 0xbd, 0xe9, 0x3a, 0xc5, 0x61, 0xeb,
- 0xf8, 0xea, 0xfa, 0x4a, 0x0c, 0xb1, 0x5a, 0x3c, 0x23, 0x90, 0xdd, 0xb8,
- 0x6b, 0x17, 0xf4, 0x97, 0xba, 0x36, 0xeb, 0x17, 0xf4, 0x27, 0xa4, 0xeb,
- 0xb5, 0x8b, 0xff, 0xf9, 0xb6, 0x8a, 0x13, 0xad, 0xbd, 0x0c, 0x8f, 0x62,
- 0x02, 0xc5, 0x46, 0x88, 0xdc, 0x80, 0xd6, 0x18, 0x31, 0x8d, 0xf7, 0x7c,
- 0x9e, 0x8b, 0x17, 0x19, 0xc5, 0x8b, 0xef, 0x7f, 0x8e, 0xb1, 0x7f, 0xbb,
- 0xfe, 0x0c, 0xc9, 0xed, 0x62, 0xa4, 0xf6, 0x9c, 0x8e, 0xf1, 0x64, 0x4b,
- 0x15, 0x88, 0xd6, 0x88, 0x9b, 0x4e, 0x7f, 0x20, 0xbf, 0xbc, 0xdf, 0xea,
- 0x39, 0x58, 0xbf, 0xe6, 0xf7, 0x25, 0xc7, 0x87, 0x58, 0xa9, 0x3e, 0x82,
- 0x30, 0xbf, 0x41, 0xdf, 0xec, 0xb1, 0x7c, 0x58, 0xe6, 0xac, 0x5f, 0xd0,
- 0xf6, 0x17, 0xb8, 0xb1, 0x7a, 0x02, 0xe2, 0xc5, 0x8f, 0xd9, 0xe6, 0x44,
- 0x5d, 0x5d, 0xa2, 0xfc, 0xe4, 0xe6, 0x37, 0x5d, 0x86, 0xac, 0x58, 0xeb,
- 0x17, 0xd0, 0xf3, 0xec, 0xb1, 0x47, 0x36, 0xcc, 0x25, 0x7f, 0xf7, 0xa4,
- 0xb7, 0x73, 0x9d, 0xf8, 0x25, 0x8b, 0xff, 0x8c, 0x9d, 0x43, 0xaf, 0x30,
- 0xf3, 0x8b, 0x14, 0xe8, 0x8c, 0xf2, 0x2d, 0xf3, 0x16, 0xdf, 0x58, 0xa9,
- 0x4d, 0xc7, 0x0c, 0x9d, 0x39, 0xa1, 0x58, 0x19, 0x15, 0xd8, 0x75, 0x8b,
- 0xf3, 0xfc, 0x6f, 0xc5, 0x8b, 0x3e, 0xc6, 0xfe, 0x02, 0xf7, 0xec, 0x20,
- 0x04, 0x95, 0x8b, 0x9b, 0x8b, 0x17, 0x84, 0xdc, 0x58, 0xaf, 0x1b, 0x43,
- 0x05, 0xed, 0xc5, 0x8b, 0x8b, 0xcb, 0x17, 0x9f, 0x63, 0xac, 0x56, 0x1b,
- 0x5d, 0x0b, 0xd6, 0xc7, 0xcf, 0x12, 0x3d, 0x4a, 0x2b, 0x72, 0x11, 0x37,
- 0x44, 0x35, 0x8b, 0xff, 0xff, 0xe2, 0x13, 0x73, 0x0b, 0x9c, 0xcf, 0xbf,
- 0x05, 0xb7, 0x3f, 0x9d, 0xfa, 0x56, 0x2f, 0xcf, 0xa6, 0xec, 0x35, 0x8b,
- 0xff, 0x4e, 0xfd, 0x70, 0x85, 0x0c, 0xe2, 0xc5, 0x41, 0x1d, 0x31, 0x3f,
- 0x1c, 0xaa, 0xff, 0x7d, 0xc3, 0x37, 0x4c, 0x1a, 0xc5, 0xfb, 0xa4, 0x8c,
- 0xfc, 0x58, 0xbf, 0xb3, 0x82, 0xf4, 0x92, 0xc5, 0xfd, 0x85, 0xbe, 0x77,
- 0xe5, 0x8b, 0xff, 0xfe, 0x7f, 0x31, 0xd8, 0x81, 0xbf, 0xdf, 0x50, 0x32,
- 0x18, 0x4b, 0x15, 0x88, 0x96, 0x62, 0xfb, 0xf7, 0x4c, 0xc2, 0x35, 0x62,
- 0xfe, 0xc1, 0xfe, 0x79, 0x1e, 0xb1, 0x7a, 0x0d, 0xda, 0xc5, 0xe1, 0xff,
- 0x16, 0x2e, 0x9e, 0xfb, 0x37, 0x6c, 0x3d, 0x43, 0x56, 0x79, 0x91, 0x81,
- 0x6e, 0x62, 0xe6, 0xf1, 0x15, 0xfe, 0x18, 0x60, 0x21, 0x22, 0xa1, 0x36,
- 0x5f, 0xc5, 0x9e, 0x06, 0x76, 0xb1, 0x7f, 0x98, 0x81, 0xe8, 0xec, 0xfa,
- 0xc5, 0xb8, 0xb1, 0x7c, 0xf3, 0xa8, 0x2c, 0x5e, 0xfb, 0x41, 0xcd, 0xa1,
- 0xc4, 0xaa, 0x3d, 0x13, 0x7f, 0x6a, 0xa9, 0x47, 0x7e, 0x43, 0x26, 0xe3,
- 0xf1, 0x62, 0xfa, 0x4a, 0x11, 0xeb, 0x17, 0xff, 0x01, 0x88, 0x05, 0x9d,
- 0x3f, 0x83, 0x58, 0xbf, 0xf9, 0x81, 0x83, 0xcf, 0xbe, 0xbe, 0xcb, 0x15,
- 0xda, 0x22, 0x38, 0x8b, 0x7f, 0xe6, 0x07, 0x9f, 0x9f, 0x92, 0xf2, 0xc5,
- 0xfd, 0xdf, 0x30, 0xf3, 0x1e, 0xb1, 0x4e, 0x7e, 0x02, 0x3e, 0xbf, 0xc6,
- 0x14, 0x0c, 0xd3, 0x01, 0x62, 0xfb, 0x3c, 0x1e, 0xeb, 0x16, 0x02, 0xc5,
- 0xfe, 0xd6, 0x9c, 0xff, 0xcd, 0x96, 0x2a, 0x4f, 0x1f, 0x04, 0xaa, 0x0a,
- 0x98, 0xb0, 0x98, 0xd1, 0x87, 0x85, 0x6f, 0xe1, 0x28, 0x02, 0x1e, 0x1b,
- 0x79, 0xb2, 0xff, 0x37, 0xd8, 0xc3, 0xe7, 0x16, 0x2e, 0x0a, 0xf4, 0x58,
- 0xb6, 0xeb, 0x17, 0x6f, 0x05, 0x8a, 0xc3, 0xca, 0xdc, 0x7b, 0xc2, 0x77,
- 0xfc, 0x45, 0x9b, 0x03, 0x92, 0x4b, 0x15, 0x1b, 0xb7, 0x02, 0xc1, 0x52,
- 0x68, 0xd8, 0x8c, 0x2c, 0x1e, 0x8d, 0x69, 0xf2, 0xe3, 0xb4, 0x20, 0x21,
- 0x0a, 0xf1, 0x91, 0x64, 0xb7, 0x33, 0x61, 0x7d, 0xbc, 0x3a, 0x7b, 0x66,
- 0x78, 0x5d, 0x45, 0x0f, 0xed, 0x46, 0x2c, 0x78, 0x52, 0xfe, 0x52, 0x83,
- 0x42, 0x30, 0x04, 0xe5, 0x18, 0x57, 0x25, 0xb1, 0x7a, 0x5e, 0xdf, 0x47,
- 0xc8, 0xe7, 0xe3, 0x0b, 0xef, 0x7a, 0x46, 0xb1, 0x7c, 0x06, 0xd7, 0x16,
- 0x2e, 0xee, 0x32, 0x4f, 0x03, 0x07, 0x6f, 0xf0, 0x23, 0x22, 0x84, 0x97,
- 0x96, 0x2a, 0x31, 0x53, 0xbc, 0xca, 0x0f, 0xd1, 0x85, 0x89, 0x62, 0xdd,
- 0xac, 0x5c, 0x43, 0xc3, 0x48, 0x60, 0x8d, 0xd9, 0xda, 0xc5, 0xf8, 0x32,
- 0xcd, 0x84, 0xb1, 0x7b, 0x82, 0xd9, 0x62, 0xa4, 0xf2, 0x58, 0xaa, 0x9d,
- 0x10, 0x3a, 0x61, 0xbe, 0xdd, 0x9b, 0x75, 0x45, 0xe8, 0x5f, 0x80, 0xfa,
- 0x86, 0x2c, 0x56, 0x8f, 0x67, 0x86, 0x37, 0xc0, 0x33, 0x5b, 0xac, 0x5f,
- 0xb3, 0xc5, 0x3b, 0x2c, 0x5f, 0xf9, 0x9f, 0xc2, 0xd3, 0x74, 0xc1, 0xac,
- 0x5c, 0x2e, 0x2c, 0x5f, 0x73, 0xed, 0x1e, 0xb1, 0x43, 0x37, 0xdf, 0x18,
- 0xbf, 0x49, 0xdb, 0xf2, 0xb1, 0x78, 0xef, 0xe5, 0x8b, 0xfe, 0x6f, 0x42,
- 0x4d, 0xf3, 0xec, 0xb1, 0x5a, 0x3f, 0xf3, 0x93, 0x90, 0xed, 0xfb, 0x0f,
- 0xf6, 0x1a, 0xc5, 0x4a, 0xb0, 0xc1, 0xc2, 0xb7, 0x1e, 0xfb, 0x22, 0xd1,
- 0x37, 0xca, 0x19, 0xf8, 0xc8, 0x50, 0x04, 0x2e, 0xbf, 0xfb, 0x07, 0xfc,
- 0x39, 0xda, 0x18, 0x4b, 0x17, 0x85, 0x20, 0x58, 0xbe, 0xe9, 0x85, 0x18,
- 0x33, 0xe0, 0xd2, 0x1d, 0xfb, 0x22, 0x83, 0x0d, 0x62, 0xf8, 0x23, 0xeb,
- 0x65, 0x8b, 0x46, 0x78, 0xf3, 0xc2, 0x14, 0xd3, 0xa2, 0xe7, 0xf0, 0x8c,
- 0xa8, 0xc4, 0xf2, 0xf2, 0x3a, 0x4a, 0x8d, 0x4f, 0xca, 0x77, 0x1a, 0xdd,
- 0x26, 0x35, 0x8d, 0xa1, 0xf3, 0x08, 0xcb, 0x32, 0xbb, 0x76, 0xde, 0x50,
- 0x63, 0xd2, 0x7c, 0x62, 0xa4, 0x83, 0xea, 0x31, 0x63, 0xcb, 0x4f, 0xfc,
- 0xba, 0x96, 0x84, 0x38, 0x25, 0x2b, 0x14, 0xb2, 0x8e, 0x4a, 0x34, 0xf1,
- 0x78, 0xab, 0xaf, 0x80, 0xe7, 0x4d, 0xaf, 0x02, 0x3b, 0x65, 0x8b, 0xbd,
- 0xc5, 0x8a, 0x8d, 0x8d, 0xd1, 0x11, 0x5c, 0x73, 0xac, 0x5b, 0xeb, 0x14,
- 0x14, 0x35, 0x42, 0x18, 0xbf, 0xf8, 0x53, 0x11, 0x67, 0x46, 0x39, 0xdd,
- 0x62, 0xfb, 0x3e, 0xde, 0x58, 0xbf, 0xd8, 0xfa, 0x00, 0x05, 0xc5, 0x8b,
- 0x05, 0x4d, 0x44, 0xe1, 0x23, 0x70, 0x8a, 0xf3, 0xe7, 0x16, 0x2f, 0xff,
- 0x7b, 0x82, 0x9e, 0x67, 0x9c, 0xed, 0x05, 0x8b, 0xd3, 0xde, 0xcb, 0x14,
- 0x47, 0xd3, 0xe4, 0xab, 0xe7, 0x8e, 0x93, 0xac, 0x5f, 0xef, 0xce, 0xda,
- 0x9c, 0x1a, 0xc5, 0xff, 0xf4, 0x59, 0x81, 0xf5, 0x32, 0x13, 0xd1, 0xc8,
- 0x0b, 0x17, 0xff, 0x66, 0x06, 0x64, 0x27, 0xa3, 0x90, 0x16, 0x2f, 0x63,
- 0xf4, 0xea, 0x89, 0xd8, 0x95, 0xaa, 0x53, 0x09, 0xfc, 0x34, 0x6f, 0xfb,
- 0xdc, 0xce, 0xe1, 0xf1, 0x1a, 0xb1, 0x7b, 0x93, 0x12, 0xc5, 0xda, 0x95,
- 0x8a, 0x1a, 0xa6, 0xe7, 0x84, 0x29, 0xc8, 0x7f, 0x19, 0x71, 0x14, 0x70,
- 0xf4, 0x20, 0xf5, 0xe2, 0x6f, 0xac, 0x5e, 0xef, 0x19, 0x62, 0xe9, 0x82,
- 0xc5, 0x46, 0x1b, 0x4e, 0x83, 0xb7, 0xbf, 0x9c, 0x58, 0xbf, 0xe2, 0x73,
- 0x7d, 0xde, 0xef, 0xf5, 0x8b, 0xdc, 0x9d, 0x96, 0x2f, 0xc1, 0x3f, 0x1f,
- 0x3d, 0xac, 0x54, 0xa3, 0x30, 0x64, 0xd8, 0x3b, 0xd9, 0xe3, 0x8f, 0x5f,
- 0xef, 0x7d, 0xd8, 0x00, 0x95, 0x8b, 0xee, 0xe0, 0x2d, 0x96, 0x2f, 0xe3,
- 0x78, 0xd3, 0xdc, 0x16, 0x2d, 0x9d, 0x9e, 0xb3, 0x93, 0x5e, 0x2c, 0xf2,
- 0xc5, 0xc2, 0x65, 0x8b, 0xcd, 0xa8, 0x49, 0xb3, 0x21, 0xcb, 0x9c, 0xeb,
- 0x15, 0x89, 0x95, 0x6a, 0x11, 0x22, 0x5a, 0x08, 0x61, 0x7c, 0x71, 0x10,
- 0xd6, 0x2f, 0xff, 0xe9, 0xd4, 0x5c, 0xdf, 0xe2, 0xe7, 0x24, 0xd2, 0xce,
- 0x8b, 0x17, 0x8d, 0x90, 0xd6, 0x2f, 0x33, 0x6e, 0xa8, 0x88, 0xcb, 0xe3,
- 0x77, 0x6d, 0x2c, 0x51, 0xa7, 0xdd, 0xb8, 0xfb, 0x95, 0x5f, 0x7b, 0x8c,
- 0x05, 0x8b, 0xef, 0xb9, 0xa2, 0x58, 0xbb, 0xb1, 0xac, 0x54, 0x6c, 0x7c,
- 0x03, 0x23, 0x62, 0x4b, 0xf3, 0xb1, 0xf3, 0x4b, 0x17, 0xfc, 0x26, 0xec,
- 0xb3, 0x63, 0x20, 0xb1, 0x7b, 0x73, 0x0e, 0xb1, 0x7f, 0xff, 0xd3, 0x17,
- 0xa7, 0x9a, 0x9f, 0x3e, 0xee, 0x3e, 0xa6, 0x93, 0x2c, 0x54, 0xa2, 0x28,
- 0x88, 0x2f, 0xfe, 0x7e, 0x7f, 0x0d, 0x35, 0xba, 0x8f, 0xb5, 0x8a, 0xd9,
- 0x58, 0x6e, 0xe4, 0x7a, 0x86, 0x79, 0xe1, 0x21, 0xf3, 0x3e, 0x13, 0xfa,
- 0x18, 0xdd, 0x08, 0x6f, 0xbe, 0xfc, 0x35, 0x62, 0xfe, 0x6e, 0xff, 0x8e,
- 0x1a, 0xc5, 0xd0, 0xfa, 0xc5, 0x68, 0xf1, 0xd8, 0xbe, 0xff, 0x67, 0xb0,
- 0xfb, 0x60, 0x6b, 0x14, 0x33, 0xd6, 0x22, 0x1b, 0xff, 0xb9, 0xcc, 0x39,
- 0x67, 0x4e, 0xb2, 0x14, 0x58, 0xa7, 0x3e, 0xd1, 0x10, 0xdf, 0xec, 0xdb,
- 0xe5, 0x82, 0x1a, 0xc5, 0x7c, 0xf5, 0x48, 0x86, 0xff, 0x6d, 0xac, 0xf7,
- 0x9f, 0xcb, 0x14, 0xb1, 0x7f, 0xf7, 0xf3, 0xc5, 0x31, 0x75, 0x34, 0x99,
- 0x62, 0xe1, 0x4c, 0x47, 0xa7, 0xe0, 0xca, 0x94, 0x5b, 0x72, 0x11, 0x17,
- 0x8a, 0x7b, 0x58, 0xb9, 0xce, 0xb1, 0x7f, 0x13, 0x07, 0xec, 0xfa, 0xc5,
- 0x41, 0x11, 0x23, 0x27, 0xf8, 0xef, 0x85, 0xee, 0x6f, 0xac, 0x5f, 0xed,
- 0x67, 0x31, 0x8b, 0x65, 0x8b, 0xc7, 0x17, 0x6b, 0x14, 0x33, 0xe9, 0xc1,
- 0x70, 0x19, 0xdf, 0xe1, 0x0c, 0xcf, 0xfd, 0xa0, 0xb1, 0x63, 0xac, 0x5f,
- 0xe3, 0x21, 0x3d, 0x1c, 0x80, 0xb1, 0x7f, 0x42, 0x7a, 0x39, 0x01, 0x62,
- 0xc1, 0xf5, 0x3e, 0x53, 0x0d, 0xa8, 0x68, 0xa3, 0xc7, 0x7b, 0xff, 0xa7,
- 0x6e, 0xa5, 0x9e, 0xe7, 0xf0, 0xd5, 0x8b, 0xf3, 0x6c, 0x63, 0x8d, 0x62,
- 0xff, 0xec, 0x0c, 0x53, 0xb7, 0x87, 0x3e, 0xe2, 0xc5, 0xcf, 0x12, 0xc5,
- 0x41, 0x3c, 0xcc, 0x86, 0xcf, 0xc8, 0x99, 0x20, 0x8a, 0xbc, 0x8f, 0x7f,
- 0xfa, 0x0e, 0x69, 0xad, 0xc9, 0x7d, 0x9b, 0xcb, 0x17, 0xff, 0xf3, 0x3f,
- 0xa7, 0xe5, 0x9e, 0xfb, 0xff, 0x1c, 0x35, 0x8a, 0x74, 0x52, 0xfd, 0x32,
- 0xc4, 0xb1, 0x7f, 0x7f, 0xaf, 0xf0, 0x78, 0xb1, 0x7f, 0xff, 0xf7, 0x9c,
- 0xfa, 0x7c, 0xec, 0x85, 0xe9, 0xff, 0x5e, 0x8f, 0xe8, 0xa5, 0x62, 0x99,
- 0x14, 0xfe, 0x30, 0xbe, 0x0f, 0xa8, 0x36, 0x58, 0xbf, 0x9c, 0x9f, 0x5a,
- 0xc5, 0x8a, 0x93, 0xd4, 0xc2, 0x8b, 0xfe, 0xc6, 0x20, 0x68, 0x52, 0x05,
- 0x8a, 0x94, 0xea, 0x06, 0x45, 0x90, 0xb8, 0xed, 0xdb, 0x44, 0x17, 0xfe,
- 0x14, 0x1f, 0xc6, 0x6a, 0x7f, 0x2b, 0x17, 0xff, 0xe3, 0xc7, 0xbb, 0x34,
- 0x5e, 0xfe, 0x43, 0xef, 0xd1, 0x62, 0xff, 0xee, 0x7a, 0x7d, 0x9e, 0x8a,
- 0x13, 0xf5, 0x8b, 0xc2, 0x90, 0x2c, 0x5d, 0xdc, 0x24, 0xf8, 0xf4, 0x8d,
- 0x7f, 0xcf, 0xcc, 0x1e, 0x74, 0x7d, 0x2c, 0x5f, 0xff, 0xf3, 0x73, 0xf9,
- 0xdf, 0x89, 0xc3, 0xeb, 0x38, 0x43, 0xfc, 0xac, 0x5f, 0xed, 0x45, 0x1c,
- 0xfa, 0xc3, 0x56, 0x2f, 0xa7, 0x52, 0x05, 0x8a, 0xc3, 0xdb, 0xf1, 0xcd,
- 0xcd, 0x12, 0xc5, 0xf0, 0x1a, 0x23, 0xac, 0x5f, 0xff, 0xb0, 0xe7, 0x70,
- 0x9d, 0x71, 0xf4, 0xe7, 0x93, 0x56, 0x2e, 0x93, 0xe9, 0x12, 0xa0, 0x18,
- 0x22, 0x4b, 0x8c, 0x3a, 0xc5, 0xff, 0xef, 0x43, 0x35, 0x9c, 0xeb, 0xa1,
- 0xbe, 0x96, 0x2f, 0xd9, 0xa8, 0x49, 0xd6, 0x2b, 0x64, 0x47, 0x38, 0xc9,
- 0xd3, 0x6a, 0x55, 0xcb, 0xe4, 0x2f, 0xb7, 0x2e, 0xec, 0xe9, 0xe1, 0x87,
- 0xf8, 0x5b, 0x34, 0x32, 0x2e, 0xd8, 0xe9, 0x17, 0x06, 0x1a, 0x45, 0xfe,
- 0xfb, 0xc5, 0xf9, 0xda, 0x30, 0x06, 0xcc, 0x31, 0x9b, 0xec, 0x1f, 0xf1,
- 0x62, 0xd1, 0x9b, 0x9f, 0x89, 0x27, 0xdf, 0xee, 0x16, 0x7a, 0x3b, 0x3c,
- 0xb1, 0x7d, 0xd2, 0x7d, 0x2b, 0x17, 0xba, 0x36, 0x96, 0x2f, 0xb3, 0xe5,
- 0x8b, 0x15, 0x87, 0x81, 0xc1, 0xfa, 0x82, 0x39, 0xb0, 0xad, 0xcd, 0xbc,
- 0xc9, 0x60, 0x8b, 0x17, 0xe6, 0x3e, 0x77, 0xe5, 0x8b, 0xdc, 0x68, 0xf5,
- 0x8b, 0xfc, 0xc5, 0xbf, 0x50, 0xfd, 0xc5, 0x8a, 0xd9, 0x12, 0xb8, 0x28,
- 0xe5, 0x22, 0x20, 0xbd, 0xb4, 0xc7, 0xac, 0x52, 0xc5, 0xff, 0xd8, 0x59,
- 0xce, 0x36, 0xbb, 0x87, 0x16, 0x2f, 0xf6, 0x77, 0xef, 0xe0, 0xb7, 0x58,
- 0xad, 0xd1, 0x0e, 0xe1, 0x84, 0x8b, 0x7f, 0xf9, 0xcd, 0xe3, 0xe1, 0x00,
- 0x7a, 0x6d, 0xd6, 0x2b, 0x0f, 0xeb, 0xe5, 0xf7, 0xff, 0xd8, 0xe0, 0xe7,
- 0x5c, 0x39, 0x9f, 0x6f, 0xca, 0xc5, 0xff, 0xff, 0xc2, 0x9d, 0xbb, 0x87,
- 0x0b, 0x22, 0xeb, 0xbf, 0xe7, 0x73, 0x74, 0xc1, 0xac, 0x5f, 0xf0, 0x1e,
- 0x2e, 0x3f, 0xdc, 0xeb, 0x17, 0xf1, 0xcb, 0x03, 0x60, 0x2c, 0x5e, 0x83,
- 0x81, 0x62, 0xb0, 0xf2, 0xf8, 0x5d, 0x7f, 0xa7, 0xf9, 0x14, 0x1b, 0x65,
- 0x8b, 0xff, 0xc5, 0x9c, 0x2c, 0x37, 0x9f, 0x92, 0xf2, 0xc5, 0xff, 0xc5,
- 0x9d, 0xc3, 0x83, 0x7e, 0x92, 0x35, 0x8a, 0xd9, 0x5b, 0xe0, 0xe3, 0x22,
- 0xd1, 0x09, 0xd4, 0x80, 0xf9, 0xe8, 0x42, 0x88, 0x87, 0xa1, 0xa8, 0x44,
- 0x9b, 0xf3, 0xfa, 0x7d, 0xc5, 0x8b, 0xfc, 0xdd, 0xf1, 0x88, 0x58, 0xb1,
- 0x7c, 0xfa, 0x60, 0x2c, 0x54, 0x0f, 0xf4, 0x05, 0x1c, 0x33, 0xbf, 0x61,
- 0x7b, 0xae, 0x2c, 0x5f, 0xe0, 0x4f, 0x46, 0xff, 0xdd, 0x62, 0xa3, 0x11,
- 0x1b, 0xc2, 0xff, 0x14, 0xdf, 0xf7, 0x05, 0xad, 0x3c, 0xbe, 0x96, 0x2f,
- 0xfb, 0xda, 0x14, 0x59, 0xb9, 0x4a, 0xc5, 0x62, 0xa4, 0x16, 0x8e, 0x6b,
- 0xc6, 0x62, 0x39, 0xb4, 0x7a, 0xc5, 0xf1, 0x77, 0x14, 0xac, 0x5c, 0xd1,
- 0xeb, 0x17, 0xf9, 0xfb, 0xf3, 0x31, 0xf8, 0xb1, 0x7f, 0xd3, 0x9d, 0xcb,
- 0x41, 0xa0, 0xb1, 0x7f, 0x60, 0x3a, 0x96, 0x01, 0x62, 0xe3, 0xee, 0xb1,
- 0x43, 0x3c, 0x86, 0x2f, 0xbf, 0xf6, 0x07, 0xd5, 0x86, 0xf1, 0x3c, 0xac,
- 0x5f, 0xa4, 0xbd, 0x20, 0x58, 0xbd, 0xe0, 0x32, 0xc5, 0xd3, 0xb2, 0xc5,
- 0x68, 0xf7, 0x0e, 0x4e, 0x10, 0x76, 0xff, 0xf6, 0x8e, 0x53, 0xd9, 0x9a,
- 0xf7, 0x18, 0xeb, 0x17, 0xb1, 0xa3, 0xd6, 0x2b, 0x0f, 0xb0, 0x93, 0x6f,
- 0xfd, 0xf7, 0x20, 0x19, 0xff, 0xb6, 0xcb, 0x17, 0xe9, 0x0c, 0xcf, 0xca,
- 0xc5, 0x46, 0xea, 0xbb, 0x64, 0x57, 0x62, 0x48, 0x0d, 0x0c, 0xd3, 0x21,
- 0x01, 0xa2, 0x16, 0x84, 0xef, 0x21, 0x3b, 0xe2, 0x03, 0x10, 0x6f, 0xe2,
- 0x26, 0xe9, 0x14, 0xac, 0x5f, 0xf6, 0x7f, 0xed, 0x0f, 0x67, 0xd6, 0x2f,
- 0xc5, 0x9f, 0x6f, 0x2c, 0x5e, 0xeb, 0xcd, 0xd6, 0x2a, 0x3c, 0xf2, 0x3e,
- 0x4f, 0x7d, 0xdc, 0x05, 0x1e, 0xb1, 0x7f, 0x9d, 0x81, 0xad, 0x0b, 0xeb,
- 0x17, 0xf4, 0x9b, 0x84, 0xe6, 0xac, 0x5f, 0xd9, 0xe0, 0x9e, 0xcf, 0xac,
- 0x54, 0xa7, 0x1f, 0x02, 0xfc, 0x84, 0x0b, 0x92, 0xfc, 0xa0, 0x8d, 0x38,
- 0x5d, 0x7f, 0x6d, 0x14, 0xf0, 0x5d, 0xac, 0x5c, 0x2f, 0xac, 0x5f, 0xe3,
- 0x09, 0x8d, 0xd6, 0xa5, 0x62, 0xa4, 0xff, 0xf6, 0x32, 0x61, 0x8b, 0xff,
- 0xfb, 0x78, 0xcd, 0x31, 0x3f, 0xa3, 0x35, 0x3e, 0x26, 0x02, 0xc5, 0xd1,
- 0xa4, 0x16, 0x2f, 0x36, 0x12, 0xc5, 0xdd, 0xc1, 0x62, 0xff, 0xc5, 0x20,
- 0x6f, 0x00, 0xc2, 0x82, 0xc5, 0x76, 0x7b, 0x1e, 0x19, 0xbe, 0x78, 0x9e,
- 0x56, 0x2d, 0xc5, 0x8a, 0x19, 0xb4, 0xc2, 0x2b, 0xf6, 0x7a, 0x3b, 0x3c,
- 0xb1, 0x79, 0xf5, 0xd5, 0x8f, 0x2c, 0x88, 0x2f, 0xff, 0xf7, 0x33, 0x70,
- 0x9e, 0x17, 0x70, 0xe7, 0x3d, 0x33, 0xee, 0x2c, 0x5f, 0xbd, 0x33, 0xee,
- 0x2c, 0x5f, 0x4c, 0xfb, 0x8b, 0x17, 0xbb, 0x87, 0x38, 0x79, 0x5e, 0x28,
- 0xac, 0x47, 0x30, 0xa1, 0x63, 0x5f, 0x4d, 0x03, 0xd1, 0x8c, 0xd4, 0x6e,
- 0xea, 0x49, 0x63, 0x44, 0xf8, 0xda, 0x18, 0x33, 0x2a, 0xa3, 0x67, 0x18,
- 0x46, 0x38, 0x38, 0xdc, 0xb2, 0x5a, 0x89, 0xb0, 0x86, 0xde, 0x38, 0x3e,
- 0xe3, 0x60, 0x78, 0x53, 0x45, 0x1f, 0xd6, 0xa5, 0x53, 0x9d, 0x3f, 0xf2,
- 0xf5, 0xda, 0x50, 0x10, 0x21, 0xa0, 0x53, 0xbf, 0x3c, 0x96, 0x61, 0xe9,
- 0x47, 0x82, 0x87, 0x2f, 0x42, 0xe0, 0xd8, 0x63, 0x87, 0x4c, 0x73, 0x09,
- 0x1f, 0x15, 0xe3, 0x3f, 0xf5, 0x8b, 0x82, 0x7d, 0x62, 0xfd, 0xad, 0xd9,
- 0xb7, 0x54, 0x45, 0xc5, 0xed, 0x0b, 0xeb, 0x17, 0xff, 0x0b, 0x5a, 0xc1,
- 0xc1, 0xe3, 0xbe, 0x25, 0x8b, 0xf7, 0x80, 0x61, 0x41, 0x22, 0xfd, 0xcf,
+ 0x1e, 0xb1, 0x73, 0xf7, 0x2c, 0x5e, 0xd4, 0xee, 0xb1, 0x6d, 0x2c, 0x56,
+ 0x1b, 0x06, 0x1e, 0xbe, 0xdb, 0x53, 0xb2, 0xc5, 0xc1, 0x81, 0x62, 0xec,
+ 0xfa, 0xc5, 0xef, 0xe4, 0x4b, 0x17, 0xbe, 0xe7, 0x58, 0xb4, 0x4b, 0x15,
+ 0xb1, 0xf2, 0x8c, 0x5d, 0x87, 0x84, 0x3b, 0x68, 0x96, 0x2f, 0x8b, 0x61,
+ 0x71, 0x62, 0x9c, 0xdb, 0xb0, 0x9d, 0xfb, 0x07, 0xa6, 0xdd, 0x62, 0xf9,
+ 0xb6, 0x9d, 0x2c, 0x5e, 0xd3, 0x6c, 0xb1, 0x61, 0xfc, 0xfa, 0x88, 0xa7,
+ 0xc4, 0x77, 0xb0, 0xbc, 0xb1, 0x52, 0x7a, 0x1f, 0x34, 0xbc, 0x36, 0x82,
+ 0xc5, 0xfd, 0xf8, 0xa1, 0x3a, 0xd9, 0x62, 0xe1, 0x41, 0x62, 0x9c, 0xf9,
+ 0x98, 0x77, 0xb1, 0x8d, 0x86, 0xb1, 0x7b, 0x0f, 0x2b, 0x14, 0xea, 0xdd,
+ 0xe2, 0x26, 0x38, 0xaf, 0xd2, 0x98, 0x7c, 0x04, 0xa4, 0xfd, 0xc7, 0x3f,
+ 0x43, 0x67, 0xb4, 0x21, 0xe3, 0x8b, 0xfb, 0x84, 0xaf, 0x6b, 0x82, 0x58,
+ 0xb7, 0xd6, 0x2f, 0xe0, 0xa7, 0xae, 0x36, 0xeb, 0x17, 0x07, 0xc5, 0x8a,
+ 0x88, 0xf2, 0xb8, 0x63, 0x71, 0x44, 0xb1, 0x60, 0xd6, 0x2e, 0x93, 0x56,
+ 0x2f, 0x6a, 0x60, 0xb1, 0x7c, 0x58, 0x0e, 0x2c, 0x5b, 0xad, 0x8f, 0x5f,
+ 0x43, 0x0c, 0x3b, 0x52, 0x9a, 0xae, 0xc3, 0xc3, 0x5c, 0xc2, 0x3e, 0x86,
+ 0x04, 0xd5, 0x7d, 0xad, 0xb3, 0x4b, 0x17, 0xcf, 0xa1, 0x47, 0xac, 0x54,
+ 0x9e, 0x56, 0x12, 0x5f, 0xba, 0x87, 0x9b, 0xa5, 0x8b, 0xb9, 0xba, 0xc5,
+ 0xcd, 0x2b, 0x16, 0x95, 0x8a, 0xfa, 0x22, 0xd8, 0x80, 0x8a, 0xf8, 0x33,
+ 0xe1, 0x6b, 0x62, 0xc5, 0xf3, 0x1d, 0xce, 0xb1, 0x7f, 0xba, 0xd4, 0xbc,
+ 0x1b, 0x8b, 0x17, 0xd8, 0x53, 0x05, 0x8a, 0x81, 0xfb, 0xe1, 0x11, 0xcd,
+ 0x2d, 0x1c, 0xb1, 0x7e, 0xe6, 0x79, 0xf4, 0xb1, 0x7b, 0x3a, 0xf2, 0xc5,
+ 0x00, 0xf1, 0xb8, 0x51, 0x7b, 0xee, 0x12, 0xc5, 0xcc, 0x35, 0x8b, 0xff,
+ 0x85, 0xbb, 0x9b, 0xf6, 0x87, 0x1c, 0xeb, 0x15, 0x88, 0x9e, 0xdc, 0x8a,
+ 0x21, 0xe2, 0x17, 0xba, 0x1c, 0x58, 0xb9, 0x86, 0xb1, 0x7b, 0xd9, 0xc5,
+ 0x8b, 0x8a, 0x56, 0x2a, 0x07, 0x94, 0x21, 0x7e, 0xc3, 0xb7, 0xfc, 0xe2,
+ 0xda, 0x7a, 0x06, 0xa5, 0x62, 0xf4, 0x27, 0xa5, 0x8b, 0x47, 0xac, 0x54,
+ 0x46, 0xcc, 0x87, 0xae, 0xce, 0x96, 0x2c, 0x4b, 0x16, 0xd3, 0x9a, 0x96,
+ 0x18, 0xb4, 0x72, 0xc5, 0xfc, 0x59, 0xdb, 0x4f, 0xc5, 0x8a, 0xd8, 0xf1,
+ 0x02, 0x15, 0xb7, 0x4b, 0x15, 0x28, 0xa0, 0x76, 0x91, 0x12, 0x5f, 0x6a,
+ 0x12, 0x75, 0x8b, 0xf7, 0x47, 0x9c, 0xf2, 0xc5, 0x61, 0xe6, 0x31, 0x1d,
+ 0xf7, 0xdb, 0x34, 0xb1, 0x7e, 0xdb, 0x09, 0xcd, 0x58, 0xa9, 0x3c, 0xb7,
+ 0x22, 0xbf, 0xb5, 0x00, 0x3f, 0x5c, 0x58, 0xbf, 0xdc, 0x0c, 0xa7, 0xef,
+ 0xb2, 0xc5, 0x31, 0xf2, 0xf8, 0xc2, 0xfb, 0x9c, 0x90, 0x2c, 0x57, 0x7d,
+ 0x57, 0x61, 0x66, 0x11, 0x03, 0x2e, 0xc8, 0x7c, 0xf4, 0x7a, 0xec, 0x5a,
+ 0x31, 0x3b, 0x77, 0xe1, 0xd4, 0xcf, 0x44, 0xd6, 0x28, 0x42, 0x84, 0x43,
+ 0x7f, 0xc5, 0x86, 0x96, 0x7b, 0xee, 0xb1, 0x7c, 0x3f, 0xe7, 0x16, 0x2b,
+ 0x0f, 0x6d, 0x8e, 0x2f, 0xe6, 0x37, 0x06, 0xd0, 0x58, 0xaf, 0x9e, 0x71,
+ 0x10, 0x5f, 0x88, 0xb3, 0xb3, 0x2c, 0x5f, 0xbf, 0x83, 0x68, 0x2c, 0x53,
+ 0x9e, 0x83, 0x14, 0x5a, 0x0b, 0x17, 0x07, 0xe5, 0x8b, 0xfb, 0xef, 0x91,
+ 0x30, 0x16, 0x2a, 0x07, 0x8f, 0xe1, 0x9b, 0xda, 0xd3, 0x2c, 0x5f, 0x40,
+ 0x02, 0x82, 0xc5, 0xf6, 0x83, 0x90, 0x2c, 0x5e, 0x9f, 0xca, 0xc5, 0x49,
+ 0xf2, 0x39, 0x27, 0xc9, 0x2f, 0x43, 0x9d, 0x96, 0x2f, 0xc7, 0x92, 0x87,
+ 0x16, 0x2f, 0xa7, 0xd1, 0xbf, 0x78, 0xb1, 0x7e, 0x63, 0x80, 0x12, 0xb1,
+ 0x7e, 0x8a, 0x13, 0xee, 0x2c, 0x56, 0xc7, 0xa5, 0xe2, 0x8b, 0xe8, 0x49,
+ 0x41, 0x62, 0xa5, 0x30, 0xcd, 0x88, 0x20, 0x50, 0xef, 0xf1, 0x11, 0xde,
+ 0x23, 0x7e, 0xb1, 0x61, 0xac, 0x54, 0x9b, 0x07, 0x1e, 0xbf, 0xff, 0x41,
+ 0xc8, 0x85, 0xd6, 0xa7, 0xcf, 0xbb, 0x8d, 0x62, 0xe6, 0xe9, 0x62, 0xfe,
+ 0xfe, 0x44, 0x52, 0x35, 0x8b, 0xfe, 0x84, 0x9f, 0x99, 0xa9, 0xe2, 0xc5,
+ 0x6e, 0x7c, 0xfd, 0x17, 0x5f, 0x44, 0x4c, 0x12, 0xc5, 0xff, 0x49, 0x67,
+ 0x6c, 0x26, 0x35, 0x62, 0x8d, 0x3d, 0xdd, 0x12, 0x58, 0x6b, 0x15, 0x29,
+ 0xc5, 0x8d, 0x59, 0xdf, 0xda, 0x10, 0x22, 0x23, 0xbd, 0xe7, 0x02, 0xc5,
+ 0xf0, 0x24, 0xb7, 0x58, 0xb7, 0x7e, 0xb1, 0x46, 0x9e, 0xbf, 0x43, 0xa2,
+ 0x23, 0xbe, 0x87, 0xb0, 0x35, 0x8b, 0xf7, 0x9f, 0xec, 0x75, 0x8b, 0xa4,
+ 0x0b, 0x15, 0x26, 0xff, 0x72, 0x8b, 0xda, 0x93, 0xac, 0x53, 0xa3, 0x49,
+ 0x8c, 0x44, 0xc6, 0x11, 0x0d, 0xfb, 0x3a, 0xf3, 0x1d, 0x62, 0xec, 0x89,
+ 0x62, 0xdb, 0x11, 0xe0, 0x86, 0x53, 0x7a, 0x75, 0xb2, 0xc5, 0xdb, 0x4a,
+ 0xc5, 0x49, 0xef, 0xb9, 0x48, 0x87, 0xa9, 0x62, 0xf6, 0xf2, 0x05, 0x8b,
+ 0x14, 0x0d, 0x56, 0x06, 0x5f, 0xf3, 0x1b, 0xc7, 0xed, 0x25, 0xe5, 0x8b,
+ 0xfb, 0xee, 0x7c, 0xfb, 0x2c, 0x54, 0xa2, 0x34, 0x89, 0x44, 0x77, 0x7d,
+ 0xe2, 0x7e, 0xe5, 0x8b, 0x85, 0xc5, 0x8b, 0xec, 0xe9, 0xa0, 0xb1, 0x7f,
+ 0x9f, 0x8e, 0x2e, 0xff, 0xee, 0xb1, 0x5c, 0x3d, 0xbf, 0x11, 0xdf, 0x85,
+ 0x0e, 0x7c, 0x6b, 0x15, 0x28, 0xbf, 0x77, 0x32, 0x22, 0xbf, 0x64, 0x50,
+ 0x6e, 0x2c, 0x54, 0x19, 0x31, 0x23, 0x71, 0xc2, 0x0e, 0x96, 0x5c, 0x8a,
+ 0x28, 0x40, 0xea, 0x33, 0x93, 0xbd, 0xfe, 0x3a, 0xa2, 0x8d, 0xdb, 0x90,
+ 0xdc, 0xf4, 0x39, 0x04, 0x5d, 0xda, 0x1c, 0x81, 0x96, 0xd9, 0x96, 0x2c,
+ 0x4b, 0x17, 0xf3, 0x43, 0xbb, 0xb8, 0x5b, 0x2c, 0x5e, 0xc6, 0x25, 0x8b,
+ 0xf0, 0x72, 0x3e, 0xfb, 0xef, 0x56, 0x2b, 0x47, 0xa3, 0xc1, 0xbb, 0xb3,
+ 0x8b, 0x16, 0x25, 0x8b, 0xa1, 0x1e, 0xb1, 0x50, 0x4c, 0x38, 0xe2, 0x3f,
+ 0x11, 0x68, 0x43, 0x91, 0x17, 0x05, 0xfc, 0x23, 0x70, 0x23, 0xd6, 0x2e,
+ 0xf7, 0x16, 0x2d, 0xc5, 0x8b, 0xda, 0x0e, 0x25, 0x8b, 0xfb, 0x8d, 0xd7,
+ 0x9f, 0x65, 0x8a, 0x88, 0xf8, 0xb4, 0x25, 0xe2, 0x0a, 0x58, 0xa7, 0x37,
+ 0x91, 0xc6, 0x17, 0xf6, 0x6c, 0x3f, 0xbe, 0x96, 0x2d, 0x2b, 0x15, 0x89,
+ 0x9a, 0x38, 0xdf, 0xe1, 0x6c, 0x44, 0x71, 0xc5, 0xf7, 0xf3, 0x17, 0xfa,
+ 0x68, 0xf5, 0x8b, 0xfe, 0x11, 0x40, 0xb0, 0x12, 0x05, 0x8b, 0xff, 0x4e,
+ 0x70, 0xc9, 0x71, 0x87, 0x05, 0x8b, 0xe0, 0x83, 0x9d, 0x96, 0x2f, 0xc1,
+ 0x73, 0x6c, 0x09, 0x62, 0xa4, 0xf4, 0x9c, 0x9a, 0xa5, 0x31, 0xbf, 0x98,
+ 0x91, 0xc7, 0xa1, 0x25, 0x71, 0x4a, 0xc5, 0xe0, 0x02, 0x56, 0x2e, 0xcd,
+ 0xd6, 0x2e, 0x91, 0xf0, 0xda, 0xf8, 0x76, 0xf4, 0x96, 0xeb, 0x17, 0xff,
+ 0xf3, 0x04, 0x36, 0x6d, 0x6d, 0xf6, 0xf7, 0xdf, 0x50, 0x58, 0xbf, 0x6f,
+ 0xbf, 0xe7, 0x4b, 0x15, 0xf4, 0x52, 0x90, 0xe8, 0x97, 0x6a, 0x09, 0xc6,
+ 0x6e, 0x83, 0xc4, 0xbf, 0x43, 0x46, 0xf9, 0x89, 0xa2, 0x58, 0xbf, 0x66,
+ 0x83, 0xf7, 0x16, 0x2f, 0xcf, 0xe2, 0xc8, 0x2c, 0x5c, 0xf1, 0xeb, 0x17,
+ 0x3e, 0x96, 0x2a, 0x06, 0xc7, 0xb8, 0x6a, 0xfa, 0x42, 0x98, 0x96, 0x2f,
+ 0xfd, 0xce, 0xcd, 0xf9, 0x37, 0x3d, 0xc5, 0x8b, 0x83, 0x3a, 0xc5, 0xf6,
+ 0x68, 0x58, 0xb1, 0x60, 0x2c, 0x51, 0x1b, 0x40, 0xc8, 0xaf, 0xb6, 0xda,
+ 0x63, 0xd6, 0x2f, 0x37, 0x44, 0xb1, 0x7f, 0x78, 0x98, 0x18, 0x4b, 0x17,
+ 0xe2, 0x60, 0x61, 0x2c, 0x51, 0x87, 0xa5, 0xe2, 0xca, 0x94, 0x5d, 0x0c,
+ 0xa0, 0x4d, 0xf6, 0x8f, 0x58, 0xb4, 0x4b, 0x16, 0x8a, 0x4d, 0x46, 0x0a,
+ 0xdf, 0x49, 0xdf, 0x4b, 0x15, 0xb2, 0xaf, 0x58, 0x11, 0x1a, 0x55, 0xd2,
+ 0xc3, 0x92, 0x44, 0x49, 0xf4, 0x20, 0x26, 0x94, 0x36, 0xf8, 0xae, 0x11,
+ 0x35, 0x86, 0xb1, 0x7b, 0x0b, 0x75, 0x8a, 0x63, 0x5f, 0xc1, 0x2b, 0xf7,
+ 0x22, 0x84, 0xf4, 0xb1, 0x7d, 0xed, 0xc5, 0xb2, 0xc5, 0xa7, 0xe7, 0xa2,
+ 0x45, 0x77, 0xec, 0xdf, 0xd9, 0xba, 0xc5, 0xf6, 0xa4, 0xa2, 0x58, 0xb7,
+ 0x16, 0x2f, 0xe0, 0x86, 0x26, 0xd4, 0x16, 0x29, 0x62, 0xa4, 0xde, 0x06,
+ 0x61, 0x7b, 0x93, 0x05, 0x8b, 0xf7, 0xf3, 0x4f, 0xc5, 0x8b, 0x9f, 0x5d,
+ 0x1e, 0x2f, 0x87, 0x6f, 0xe7, 0xd3, 0xf2, 0x76, 0x58, 0xb7, 0x65, 0x8a,
+ 0x95, 0x41, 0x10, 0x71, 0xc2, 0x67, 0x2a, 0x88, 0x8f, 0x49, 0xdf, 0x66,
+ 0xe1, 0x77, 0x71, 0x75, 0xfd, 0xf9, 0x28, 0x3e, 0xcb, 0x17, 0x0e, 0x56,
+ 0x2f, 0xfd, 0xfc, 0x87, 0xa7, 0x0b, 0xaf, 0x2c, 0x56, 0x1e, 0xb7, 0x85,
+ 0xef, 0xf3, 0xec, 0x4d, 0xb0, 0xb8, 0xb1, 0x60, 0xd6, 0x29, 0xd1, 0xda,
+ 0x50, 0x84, 0xf1, 0x0f, 0x71, 0xad, 0xf1, 0xfd, 0x9b, 0xac, 0x5e, 0xc7,
+ 0x1a, 0xc5, 0xe2, 0x73, 0x56, 0x2f, 0xb0, 0x6f, 0xd9, 0x62, 0xe9, 0x3e,
+ 0x1e, 0x0b, 0x0e, 0xdf, 0xa1, 0xe7, 0x3f, 0x96, 0x2f, 0xe6, 0xeb, 0xf2,
+ 0x19, 0x2c, 0x5b, 0x3a, 0x3d, 0x80, 0x8a, 0x6f, 0x07, 0xd1, 0x2c, 0x5f,
+ 0xcd, 0x06, 0x2c, 0xee, 0x58, 0xb9, 0xc6, 0xb1, 0x78, 0x5d, 0x01, 0x62,
+ 0xfb, 0x9f, 0x68, 0x2c, 0x5b, 0xcb, 0x15, 0x2a, 0x8a, 0x46, 0x87, 0xd1,
+ 0x23, 0xae, 0xea, 0x10, 0x7f, 0x29, 0x61, 0xf0, 0x17, 0x90, 0xb8, 0x87,
+ 0xc3, 0x23, 0xb8, 0xa2, 0x58, 0xb1, 0xab, 0x16, 0x09, 0x62, 0xb0, 0xdf,
+ 0x68, 0x60, 0x31, 0x3b, 0x74, 0xb1, 0x61, 0x2c, 0x5c, 0x09, 0x48, 0xb8,
+ 0x20, 0x92, 0x29, 0xcd, 0x88, 0x42, 0xf7, 0xe2, 0xcf, 0x7d, 0xd2, 0x23,
+ 0x0d, 0x0d, 0xe2, 0xce, 0x2c, 0x5d, 0x83, 0x58, 0xa3, 0x4d, 0x9f, 0x61,
+ 0xca, 0x82, 0x24, 0x46, 0xdb, 0x76, 0xe0, 0x58, 0xbf, 0xcc, 0x6c, 0x91,
+ 0x67, 0x96, 0x2f, 0xce, 0x39, 0xc2, 0x58, 0xbe, 0x2f, 0x3e, 0xcb, 0x17,
+ 0x01, 0x96, 0x2f, 0x9f, 0x4f, 0xe5, 0x8a, 0x93, 0xdc, 0x72, 0x38, 0x85,
+ 0xea, 0x55, 0x2a, 0x0c, 0xbb, 0xa1, 0x36, 0x87, 0xa8, 0x08, 0xc8, 0x67,
+ 0x86, 0x42, 0x84, 0x15, 0xef, 0xc8, 0x4b, 0x17, 0x9b, 0xae, 0x2c, 0x52,
+ 0xc5, 0xd3, 0xf5, 0x8a, 0xe1, 0xa3, 0xf0, 0x65, 0xf1, 0x0e, 0x46, 0xb1,
+ 0x7c, 0x1f, 0xdb, 0xcb, 0x17, 0xe0, 0xfc, 0x52, 0x05, 0x8a, 0xd9, 0x1d,
+ 0xe3, 0x1e, 0xe9, 0x05, 0xc8, 0x7c, 0x45, 0xd8, 0x92, 0xfb, 0xf2, 0x20,
+ 0xd6, 0x2d, 0xa5, 0x8b, 0xd2, 0x51, 0x2c, 0x5b, 0xb2, 0xc5, 0x2c, 0x5a,
+ 0x56, 0x2b, 0x0d, 0x88, 0x05, 0x08, 0x32, 0x96, 0x29, 0x62, 0xa2, 0x2e,
+ 0x0e, 0x19, 0x77, 0xe2, 0x58, 0xb9, 0xc0, 0xb1, 0x52, 0x6c, 0x00, 0x33,
+ 0x5b, 0x26, 0x73, 0x84, 0x91, 0x09, 0x69, 0x39, 0x91, 0x00, 0xa3, 0x7d,
+ 0x0d, 0x37, 0x65, 0x8b, 0x77, 0xeb, 0x17, 0xff, 0x1a, 0xe5, 0xbf, 0x24,
+ 0xed, 0xd7, 0x96, 0x2f, 0x03, 0x3b, 0x96, 0x2f, 0xff, 0x8b, 0x01, 0x87,
+ 0x14, 0xeb, 0x4e, 0x2d, 0xd6, 0x2f, 0x8a, 0x4f, 0x12, 0xc5, 0xd8, 0x35,
+ 0x8a, 0x94, 0xcb, 0x76, 0x25, 0x34, 0x5f, 0x48, 0xe4, 0x41, 0xe5, 0x00,
+ 0x88, 0xef, 0x8f, 0xc1, 0x1d, 0x62, 0xc6, 0xac, 0x5a, 0x39, 0x62, 0xed,
+ 0x1a, 0xb1, 0x52, 0x7c, 0xae, 0x48, 0x21, 0x30, 0xc5, 0x6f, 0xa6, 0x3b,
+ 0x3a, 0x58, 0xbf, 0xfd, 0x90, 0xe4, 0xfa, 0x19, 0x1e, 0xc4, 0x05, 0x8b,
+ 0xe3, 0x58, 0x80, 0xb1, 0x5f, 0x3e, 0xf1, 0x26, 0x5f, 0xf3, 0xfb, 0xf9,
+ 0xd7, 0x85, 0x2b, 0x17, 0xc1, 0xce, 0x80, 0xb1, 0x50, 0x3d, 0xef, 0x9d,
+ 0x5d, 0x9c, 0x58, 0xbf, 0xfd, 0x90, 0x8e, 0xc3, 0x5b, 0x3d, 0x3e, 0xe2,
+ 0xc5, 0x4a, 0x21, 0xa0, 0x44, 0x01, 0x7a, 0xe2, 0x66, 0xbe, 0x8c, 0x1a,
+ 0xe9, 0xe2, 0xc5, 0x80, 0xb1, 0x7d, 0x27, 0x93, 0xac, 0x5f, 0x9c, 0x23,
+ 0xb7, 0x96, 0x29, 0xcf, 0x2f, 0x44, 0x57, 0xdb, 0xfe, 0x78, 0xb1, 0x6c,
+ 0x58, 0xa8, 0x2a, 0xbe, 0x78, 0xf2, 0xb4, 0x54, 0xc2, 0xfc, 0x5d, 0x08,
+ 0x86, 0x38, 0x92, 0xe6, 0xd9, 0x62, 0xde, 0x58, 0xae, 0x1a, 0xa0, 0x86,
+ 0x2f, 0xfe, 0xc7, 0xf7, 0x0b, 0x3d, 0xd4, 0x25, 0x62, 0xf6, 0xe2, 0x25,
+ 0x8b, 0xe1, 0xe0, 0xe3, 0x37, 0x3e, 0x28, 0x91, 0x2c, 0x6a, 0xc5, 0x4b,
+ 0x21, 0x27, 0x23, 0x93, 0x78, 0xe1, 0x7f, 0x0c, 0xb6, 0x95, 0xf2, 0x28,
+ 0x4c, 0x07, 0x08, 0x4e, 0xe3, 0xeb, 0x01, 0x62, 0xfa, 0x42, 0x14, 0x4b,
+ 0x17, 0xb9, 0x31, 0x2c, 0x5f, 0x67, 0x67, 0xd2, 0xc5, 0xce, 0x75, 0x8b,
+ 0x60, 0xcd, 0xd9, 0xc9, 0x2f, 0xa2, 0x89, 0xfe, 0xb1, 0x4b, 0x16, 0xd2,
+ 0xc5, 0x8e, 0xb1, 0x5c, 0x3d, 0x5f, 0x12, 0x88, 0x33, 0xb0, 0x95, 0xf0,
+ 0xd9, 0xba, 0x58, 0xbf, 0x01, 0xf4, 0xe6, 0xac, 0x5d, 0xcf, 0x2c, 0x5d,
+ 0x83, 0x58, 0xbd, 0xdb, 0x06, 0xb1, 0x46, 0x9b, 0x6e, 0xe1, 0x7b, 0x1a,
+ 0xb1, 0x52, 0x88, 0x6c, 0x4e, 0x62, 0x5b, 0xda, 0x6e, 0xcb, 0x17, 0x67,
+ 0x4b, 0x14, 0x6a, 0xa7, 0xfd, 0xc4, 0xa2, 0x25, 0x3a, 0xcf, 0xde, 0xd8,
+ 0xf8, 0x04, 0x65, 0x0a, 0xff, 0x16, 0xc7, 0x0f, 0xdb, 0xeb, 0x17, 0xc3,
+ 0xfc, 0xec, 0xb1, 0x58, 0x6d, 0xb7, 0x12, 0xbd, 0x9a, 0x35, 0x62, 0xfe,
+ 0x2f, 0x61, 0x38, 0x4b, 0x17, 0xf7, 0xb9, 0x87, 0x7f, 0x2c, 0x5b, 0x4b,
+ 0x15, 0x27, 0x81, 0x85, 0xd4, 0xb1, 0x4b, 0x16, 0x95, 0x8a, 0xef, 0xcd,
+ 0x49, 0x06, 0x78, 0x32, 0xf6, 0x76, 0x65, 0x8b, 0xe7, 0xd3, 0x1a, 0xb1,
+ 0x7d, 0xff, 0xe0, 0x16, 0x2d, 0x3f, 0x3e, 0x46, 0x1e, 0x0c, 0x8e, 0xdb,
+ 0x2c, 0x54, 0xa7, 0xa5, 0x84, 0x2e, 0x3c, 0x76, 0xd6, 0x49, 0x04, 0x25,
+ 0xbb, 0xf3, 0x4b, 0xfb, 0xd9, 0xd4, 0x26, 0x0b, 0x17, 0xef, 0x67, 0xd8,
+ 0xd5, 0x8a, 0xe8, 0xf6, 0x1c, 0xbe, 0xfd, 0xd0, 0x3b, 0xc1, 0x71, 0x62,
+ 0xf7, 0xd8, 0xeb, 0x17, 0x4f, 0x16, 0x2f, 0xe6, 0xf0, 0x03, 0x28, 0x2c,
+ 0x5f, 0x73, 0x1e, 0x0b, 0x17, 0xee, 0x66, 0x9c, 0xd5, 0x8a, 0x1a, 0x2b,
+ 0xba, 0x1d, 0x8f, 0x17, 0xd1, 0x7f, 0x88, 0xae, 0x8f, 0x89, 0x62, 0xfe,
+ 0xf0, 0xdc, 0x12, 0x4b, 0x17, 0xb6, 0xfb, 0xac, 0x5d, 0xf1, 0x74, 0x79,
+ 0x6c, 0x5b, 0x6f, 0xac, 0x5e, 0x08, 0x20, 0x92, 0x2f, 0xf4, 0xec, 0x1e,
+ 0x7d, 0xba, 0x48, 0x8c, 0x34, 0x37, 0xf9, 0xc6, 0xc5, 0xd4, 0x38, 0xb1,
+ 0x43, 0x3f, 0xdf, 0xa4, 0xdf, 0xd0, 0x9d, 0x85, 0x3a, 0x58, 0xbf, 0x7e,
+ 0x7e, 0xe6, 0xac, 0x5b, 0x65, 0x8a, 0x81, 0xbc, 0xc2, 0x9b, 0xf1, 0xc3,
+ 0x9d, 0x01, 0x62, 0x96, 0x29, 0x62, 0xd2, 0x72, 0xe0, 0x01, 0x95, 0x27,
+ 0xcf, 0x04, 0x2b, 0xcf, 0x9b, 0xac, 0x5f, 0xcf, 0xd7, 0x3d, 0x9b, 0xac,
+ 0x5c, 0x2e, 0x96, 0x2f, 0xf4, 0x3f, 0x98, 0x50, 0xe2, 0xc5, 0xcc, 0x6a,
+ 0xc5, 0xed, 0x42, 0x25, 0x8a, 0x93, 0xea, 0x63, 0x31, 0x0c, 0x51, 0xa8,
+ 0xe0, 0xf9, 0x87, 0x21, 0x07, 0x7f, 0x37, 0xb5, 0xac, 0xd9, 0x62, 0xa5,
+ 0x5e, 0xe0, 0xd9, 0xf0, 0xbb, 0x78, 0x58, 0x74, 0x44, 0xed, 0x71, 0x42,
+ 0x1f, 0x84, 0x3e, 0x87, 0xe8, 0x46, 0xd7, 0xa4, 0xee, 0xb1, 0x7a, 0x19,
+ 0xba, 0xc5, 0x2c, 0x5c, 0xe7, 0x58, 0xb4, 0xec, 0x68, 0xc6, 0x19, 0x69,
+ 0x58, 0xbf, 0xbf, 0x9c, 0xf3, 0xec, 0xb1, 0x7f, 0xa2, 0x11, 0x7b, 0x9f,
+ 0x75, 0x8a, 0xe1, 0xf2, 0x78, 0xbe, 0xee, 0x32, 0xc5, 0x46, 0x8b, 0xda,
+ 0xf3, 0x0d, 0xec, 0x9c, 0x2a, 0xde, 0x13, 0xbd, 0x0e, 0x3a, 0x0c, 0x44,
+ 0xec, 0xeb, 0xe2, 0x2b, 0xe8, 0x48, 0x38, 0xb1, 0x7f, 0x42, 0x7b, 0x39,
+ 0x01, 0x62, 0xda, 0xc3, 0xd2, 0x0c, 0x8e, 0xf6, 0xbb, 0x86, 0xb1, 0x6f,
+ 0xac, 0x54, 0x9e, 0xdb, 0x94, 0x77, 0x10, 0xdf, 0xf4, 0xf5, 0xfc, 0x89,
+ 0x8b, 0x65, 0x8b, 0xf9, 0x82, 0xea, 0x19, 0xe5, 0x8a, 0xf9, 0xf5, 0x91,
+ 0xdd, 0xff, 0xcf, 0xd8, 0xb3, 0x9d, 0x43, 0x3c, 0x4b, 0x17, 0xfe, 0xfc,
+ 0xf5, 0x02, 0xcf, 0x7d, 0xd6, 0x2f, 0xfe, 0x35, 0xb5, 0xa1, 0x1b, 0x9b,
+ 0xc8, 0x16, 0x2f, 0xf3, 0x1c, 0x7d, 0x05, 0x9f, 0x58, 0xad, 0x1f, 0xf7,
+ 0x64, 0x8b, 0xf9, 0xa1, 0xef, 0x49, 0xd6, 0x2f, 0xdf, 0x9e, 0x9a, 0x3d,
+ 0x62, 0xff, 0xfa, 0x7d, 0xc1, 0xe7, 0x9f, 0xe2, 0xce, 0xbc, 0xb1, 0x50,
+ 0x4f, 0x4b, 0x74, 0x67, 0x85, 0xee, 0x89, 0x3e, 0x5d, 0xe2, 0xcb, 0xc5,
+ 0x9f, 0x58, 0xb6, 0x96, 0x2f, 0xf9, 0xc6, 0x1f, 0xba, 0xdd, 0xce, 0xb1,
+ 0x7f, 0x66, 0xe1, 0xf6, 0xfe, 0x2c, 0x54, 0x0f, 0xbf, 0x0f, 0x6f, 0xfa,
+ 0x4b, 0xc5, 0x9e, 0x90, 0x96, 0x2c, 0x12, 0xc5, 0xfc, 0x17, 0x1c, 0xba,
+ 0x82, 0xc5, 0xf6, 0xde, 0xcf, 0xac, 0x54, 0x9f, 0x3e, 0x09, 0x88, 0xc2,
+ 0x96, 0x29, 0xd1, 0xb1, 0xa8, 0x4f, 0xb1, 0x6d, 0xf7, 0x3c, 0xce, 0xb1,
+ 0x7e, 0x88, 0x07, 0xc8, 0x96, 0x2f, 0xfd, 0x24, 0x3c, 0xdb, 0x0b, 0x3a,
+ 0x58, 0xbb, 0xf2, 0xb1, 0x5b, 0x9e, 0xaf, 0x8f, 0xab, 0x11, 0x46, 0xd0,
+ 0x80, 0xb8, 0x50, 0x58, 0xbe, 0xf7, 0x24, 0x0b, 0x17, 0x68, 0x4b, 0x15,
+ 0x86, 0xef, 0xc4, 0x76, 0xe2, 0xc5, 0x6c, 0x88, 0x52, 0x53, 0x11, 0x05,
+ 0xfe, 0x6e, 0xd8, 0x3d, 0xb0, 0x25, 0x8b, 0xff, 0xd3, 0x9d, 0x07, 0xe7,
+ 0x21, 0x43, 0x38, 0xb1, 0x78, 0x85, 0xb2, 0xc5, 0xfe, 0xe4, 0x9f, 0xa8,
+ 0x67, 0x96, 0x2f, 0x4e, 0x6c, 0xb1, 0x6c, 0x1a, 0x2e, 0xf7, 0x4b, 0xf0,
+ 0xf7, 0x63, 0x5b, 0xec, 0xf8, 0x7a, 0x58, 0xbb, 0xa0, 0x96, 0x2e, 0x90,
+ 0x96, 0x2e, 0x38, 0x16, 0x2e, 0x62, 0x58, 0xa9, 0x3e, 0x07, 0x1a, 0xf8,
+ 0xc3, 0x0c, 0x5c, 0xe6, 0xac, 0x5f, 0x0a, 0x0c, 0x35, 0x8b, 0xe7, 0xf0,
+ 0x19, 0x62, 0xfd, 0x3d, 0x43, 0x0e, 0xb1, 0x50, 0x44, 0x36, 0x86, 0x0e,
+ 0x47, 0xf2, 0x2b, 0xdf, 0x11, 0x2c, 0x5f, 0x72, 0x48, 0xd5, 0x8a, 0xd9,
+ 0x92, 0x96, 0x38, 0x4d, 0xe4, 0x7e, 0x6e, 0xbb, 0x1e, 0x39, 0x14, 0x20,
+ 0x75, 0x0f, 0x93, 0x99, 0xfe, 0x18, 0xad, 0x0a, 0xb0, 0x18, 0x14, 0x3c,
+ 0xb8, 0x8b, 0xe8, 0x42, 0x0a, 0x17, 0xfd, 0x8f, 0x43, 0x1d, 0xbb, 0x46,
+ 0xac, 0x5f, 0x49, 0xdb, 0xeb, 0x17, 0xbd, 0xe6, 0x58, 0xbe, 0xd0, 0xa7,
+ 0xb2, 0xc5, 0xe6, 0x20, 0x0c, 0xf9, 0x18, 0x8b, 0xc3, 0xb7, 0xf7, 0x0b,
+ 0x36, 0x0e, 0x0b, 0x16, 0xc8, 0xf3, 0xee, 0x01, 0xf5, 0xfc, 0x78, 0xa1,
+ 0x25, 0xe5, 0x8b, 0xa4, 0x0b, 0x17, 0x8b, 0x3b, 0x96, 0x2e, 0x7d, 0x96,
+ 0x29, 0x8d, 0xbf, 0x87, 0xef, 0x41, 0x86, 0xb1, 0x58, 0x8b, 0xa8, 0x8b,
+ 0xfe, 0x9d, 0xc2, 0x0b, 0xfd, 0xbb, 0xf0, 0xb3, 0xb3, 0x2c, 0x5f, 0x4e,
+ 0xcd, 0x05, 0x8b, 0x80, 0x75, 0x8b, 0xdc, 0xfb, 0xac, 0x56, 0x8d, 0xaf,
+ 0x86, 0x2f, 0xe2, 0x6f, 0x6d, 0x81, 0x2c, 0x52, 0xc5, 0x11, 0xbb, 0xf1,
+ 0x7d, 0x49, 0xfe, 0x62, 0xe5, 0xf6, 0xc5, 0x9d, 0x2c, 0x5f, 0xc0, 0xe6,
+ 0x0d, 0xa0, 0xb1, 0x58, 0x7a, 0x4c, 0x49, 0x7f, 0xd0, 0x1b, 0x03, 0xd3,
+ 0xd7, 0x96, 0x2f, 0xec, 0xf7, 0xdc, 0x80, 0xb1, 0x79, 0xcb, 0x8b, 0x17,
+ 0xbc, 0xfb, 0x2c, 0x51, 0x1f, 0x3f, 0x8b, 0x7b, 0x0e, 0x5f, 0x19, 0x9d,
+ 0x79, 0x62, 0xfe, 0xe4, 0xf5, 0x0c, 0xf2, 0xc5, 0x6e, 0x7a, 0x9c, 0x25,
+ 0xbe, 0xcf, 0x3f, 0x16, 0x29, 0x62, 0xba, 0x35, 0xcc, 0x45, 0x52, 0x9c,
+ 0xc6, 0x42, 0x89, 0xe1, 0x08, 0xca, 0x36, 0xf2, 0xc5, 0xfa, 0x28, 0x31,
+ 0x41, 0x62, 0xa4, 0xdd, 0xe0, 0x95, 0xdf, 0x02, 0xc5, 0xf6, 0x7c, 0x02,
+ 0x58, 0xa9, 0x5e, 0x18, 0x84, 0x3a, 0xf2, 0x1c, 0x9d, 0x1e, 0xe8, 0xd7,
+ 0xf0, 0xd4, 0x27, 0x2e, 0x47, 0x71, 0xe7, 0xf1, 0x0f, 0xc7, 0x0c, 0x58,
+ 0x35, 0x8a, 0x58, 0xbe, 0x62, 0x90, 0x2c, 0x5c, 0x20, 0xd6, 0x2b, 0x0f,
+ 0x66, 0x21, 0x3d, 0x06, 0x06, 0x43, 0x73, 0xc7, 0xac, 0x5b, 0x8b, 0x14,
+ 0x46, 0xb3, 0xc3, 0x57, 0xf7, 0xe7, 0xdc, 0xfb, 0xac, 0x5c, 0xc6, 0xac,
+ 0x58, 0x7e, 0x3c, 0x68, 0xe2, 0xeb, 0xdd, 0x70, 0x6b, 0x16, 0x95, 0x8a,
+ 0x94, 0x60, 0xe3, 0x33, 0x95, 0xb0, 0xfd, 0xa3, 0x96, 0x2e, 0x91, 0xac,
+ 0x57, 0x7a, 0x6b, 0x3e, 0x2b, 0x73, 0x1d, 0x62, 0xf1, 0x34, 0x16, 0x2c,
+ 0x6a, 0xc5, 0xb8, 0xb1, 0x63, 0xac, 0x5b, 0x4b, 0x14, 0xc6, 0x90, 0x42,
+ 0x54, 0xe7, 0xd3, 0xa1, 0x3f, 0x9b, 0x5e, 0x0f, 0xaf, 0x2c, 0x5f, 0x69,
+ 0xc5, 0xb2, 0xc5, 0xf4, 0xeb, 0x09, 0x62, 0x86, 0x78, 0xa1, 0x92, 0x58,
+ 0xd5, 0x8a, 0xd8, 0xdb, 0x68, 0x8e, 0xff, 0x30, 0x5e, 0xeb, 0x77, 0xd2,
+ 0xc5, 0x83, 0x58, 0xb0, 0x16, 0x29, 0x60, 0x69, 0xf1, 0xe0, 0xbb, 0xc2,
+ 0x17, 0xe5, 0xcd, 0x09, 0xb2, 0x22, 0x11, 0xbc, 0x70, 0x9d, 0xfc, 0x50,
+ 0x63, 0xe0, 0xd6, 0x2e, 0xc0, 0x2c, 0x54, 0x9e, 0x21, 0x16, 0xdf, 0x78,
+ 0xe7, 0xd2, 0xc5, 0xff, 0xc0, 0x92, 0xdd, 0xbc, 0x00, 0xca, 0x0b, 0x17,
+ 0x3f, 0xd6, 0x2e, 0x6e, 0xe5, 0x8a, 0x81, 0xb1, 0xf8, 0xbd, 0xe7, 0xc2,
+ 0x58, 0xbc, 0x59, 0x05, 0x8a, 0xd1, 0xb7, 0xf0, 0xdd, 0xfb, 0x6d, 0x09,
+ 0xb8, 0xb1, 0x7c, 0x2e, 0xff, 0x8c, 0xb1, 0x7f, 0xf7, 0xa1, 0x26, 0x87,
+ 0xef, 0x89, 0xb6, 0x58, 0xbd, 0xfc, 0xe2, 0xc5, 0xe6, 0x60, 0x96, 0x2f,
+ 0xb4, 0xe0, 0xe2, 0xc5, 0xb6, 0x19, 0xe0, 0x70, 0x76, 0xb1, 0x1e, 0xec,
+ 0x51, 0xe4, 0x91, 0x2e, 0xdf, 0xfd, 0xcf, 0xe0, 0xcb, 0x3b, 0x16, 0x71,
+ 0x62, 0xfa, 0x61, 0x03, 0xac, 0x5e, 0x68, 0xb8, 0xb1, 0x4e, 0x88, 0x62,
+ 0x45, 0xf1, 0x1d, 0x41, 0x5a, 0x21, 0xa4, 0x1d, 0x12, 0x44, 0xef, 0xa5,
+ 0x86, 0x21, 0x28, 0xc8, 0x7d, 0x0c, 0x1b, 0xdf, 0x2e, 0x96, 0x2c, 0x12,
+ 0xc5, 0xb7, 0x58, 0xa1, 0x9e, 0x24, 0x43, 0xc1, 0x89, 0xd4, 0x6e, 0xfb,
+ 0xe5, 0x9d, 0xe1, 0x64, 0x6c, 0xab, 0xdf, 0x18, 0x23, 0x5b, 0x84, 0xcb,
+ 0xdd, 0xda, 0x50, 0x64, 0x23, 0x2d, 0x1c, 0xee, 0x6e, 0x52, 0xc0, 0x0d,
+ 0x94, 0x0d, 0xbc, 0x73, 0x9d, 0x4a, 0xf7, 0x79, 0x67, 0x31, 0x4a, 0xd9,
+ 0xd4, 0xb9, 0x73, 0xcb, 0x2f, 0xfd, 0x26, 0xcd, 0xa5, 0x8b, 0x02, 0x54,
+ 0xf7, 0x7f, 0x0c, 0x32, 0x9e, 0xf9, 0xe5, 0x2a, 0x3f, 0xd3, 0xe6, 0x82,
+ 0x8c, 0x2b, 0xb4, 0x65, 0x41, 0x32, 0xc7, 0x4a, 0x09, 0x0e, 0x70, 0x2f,
+ 0xba, 0x18, 0x77, 0xfb, 0xf2, 0x5e, 0x2c, 0xd9, 0x62, 0xfa, 0x0f, 0xa8,
+ 0x2c, 0x5f, 0xcf, 0x9d, 0xdc, 0x14, 0xac, 0x5f, 0x61, 0x4c, 0x16, 0x2d,
+ 0x18, 0x34, 0x53, 0xfc, 0xcf, 0xc4, 0x61, 0x98, 0x5e, 0x00, 0x70, 0x58,
+ 0xbf, 0xfe, 0xe3, 0xfd, 0x9f, 0xd9, 0xa0, 0x1d, 0xa0, 0xb1, 0x7f, 0x7b,
+ 0xad, 0xc5, 0x3f, 0x58, 0xb4, 0x67, 0x48, 0x9f, 0xf0, 0xf8, 0x69, 0xf7,
+ 0xdd, 0xa4, 0x5b, 0xac, 0x5f, 0xf4, 0x8b, 0xbf, 0xe6, 0xc7, 0x6d, 0x96,
+ 0x2f, 0xf3, 0x3f, 0x61, 0x6b, 0x52, 0xb1, 0x7f, 0xd2, 0x50, 0xc3, 0xe7,
+ 0x5e, 0x58, 0xbf, 0x83, 0x28, 0x4f, 0x19, 0x62, 0x8d, 0x3e, 0x70, 0x1c,
+ 0xdd, 0xc8, 0xc9, 0x4c, 0x98, 0x64, 0xdf, 0x41, 0xf4, 0x27, 0x2c, 0x29,
+ 0x4e, 0xcb, 0xd1, 0xb0, 0xd4, 0x62, 0xee, 0xc6, 0xd2, 0xc4, 0x47, 0x2a,
+ 0x62, 0xfd, 0xad, 0xd9, 0xb7, 0x54, 0x96, 0xe5, 0xff, 0x9a, 0x11, 0x99,
+ 0xad, 0xd9, 0xb7, 0x54, 0x8e, 0x05, 0xa3, 0x31, 0x10, 0xe7, 0x37, 0xa5,
+ 0x8b, 0x98, 0x6b, 0x16, 0x8d, 0x86, 0x68, 0xfc, 0x19, 0x6f, 0xac, 0x5b,
+ 0x8b, 0x14, 0x23, 0x49, 0x1c, 0x25, 0x7e, 0xc0, 0xb8, 0xe1, 0x2c, 0x5d,
+ 0xce, 0x2c, 0x5f, 0xbb, 0x0f, 0x0b, 0x65, 0x8a, 0x81, 0xe1, 0xb8, 0xc5,
+ 0xdd, 0xe7, 0x16, 0x2f, 0xf9, 0xcd, 0x35, 0xbe, 0xe3, 0x65, 0x8b, 0xed,
+ 0xd9, 0xb7, 0x54, 0x9a, 0x25, 0xf7, 0xc9, 0xa3, 0xd6, 0x2f, 0xfe, 0x1f,
+ 0xd8, 0xd8, 0xa2, 0x7e, 0x08, 0xeb, 0x15, 0x27, 0xdd, 0x84, 0xb7, 0xec,
+ 0xfe, 0xef, 0xc5, 0x8b, 0xfb, 0x6f, 0xe6, 0x85, 0xba, 0xc5, 0xff, 0xff,
+ 0x10, 0x0b, 0x3d, 0xfc, 0x30, 0x04, 0xde, 0xfb, 0x45, 0xc5, 0x8b, 0xfe,
+ 0xce, 0xb0, 0xb3, 0xf8, 0x4b, 0x15, 0x28, 0xcf, 0x73, 0x1d, 0x33, 0xdf,
+ 0xcd, 0xd4, 0xfa, 0x46, 0xb1, 0x5d, 0xf1, 0x53, 0x54, 0x07, 0x74, 0x75,
+ 0xf8, 0x4f, 0x91, 0x07, 0x21, 0xf1, 0xd8, 0xba, 0xff, 0xff, 0xe1, 0xf3,
+ 0xec, 0x59, 0xb9, 0x0b, 0x63, 0xcf, 0x5e, 0xc1, 0x96, 0x2c, 0x5e, 0x72,
+ 0xdd, 0x62, 0xf3, 0x10, 0x16, 0x2a, 0x51, 0x59, 0x8e, 0x7b, 0x8e, 0xde,
+ 0x92, 0xdd, 0x62, 0xdd, 0x2c, 0x50, 0x0d, 0x87, 0x61, 0xdb, 0xf6, 0x6f,
+ 0xec, 0xdd, 0x62, 0xf7, 0x69, 0x89, 0x62, 0xff, 0x64, 0x7f, 0x35, 0xa6,
+ 0xf2, 0xc5, 0xfd, 0x3b, 0x37, 0xd8, 0xeb, 0x17, 0xe9, 0x00, 0x98, 0x35,
+ 0x8a, 0xc4, 0x6c, 0x39, 0x54, 0x44, 0x1f, 0x37, 0x22, 0xeb, 0xfa, 0x7d,
+ 0x85, 0xbe, 0x2c, 0x5b, 0x8b, 0x14, 0xe6, 0xff, 0xe5, 0xb7, 0xe6, 0x21,
+ 0x0f, 0x16, 0x2f, 0xd9, 0xed, 0xdf, 0x8b, 0x15, 0x27, 0xa0, 0x44, 0xf7,
+ 0x85, 0xee, 0x2c, 0x5f, 0x87, 0xf6, 0x2f, 0x2c, 0x5f, 0x45, 0x86, 0x8d,
+ 0x62, 0x86, 0x7d, 0x78, 0x3d, 0xe2, 0x8b, 0xff, 0x4c, 0xf5, 0xec, 0xff,
+ 0xf2, 0x25, 0x8a, 0xd1, 0xf7, 0x70, 0xba, 0xff, 0xa7, 0x6f, 0xe7, 0x3f,
+ 0x91, 0xeb, 0x17, 0xed, 0xf1, 0xcb, 0x75, 0x8b, 0xfd, 0x9b, 0x94, 0x83,
+ 0x92, 0xb1, 0x74, 0xee, 0x61, 0xee, 0x70, 0xa6, 0xff, 0xbb, 0x73, 0x3f,
+ 0x84, 0x18, 0xd6, 0x2a, 0x4f, 0xaf, 0x0b, 0xeb, 0xe9, 0x92, 0x14, 0x60,
+ 0x97, 0xfb, 0x34, 0x0c, 0x88, 0x3e, 0x2c, 0x58, 0xd5, 0x8b, 0xfe, 0xc9,
+ 0xdb, 0x22, 0xd3, 0xf1, 0x62, 0x9c, 0xf3, 0x62, 0x13, 0xbf, 0xff, 0x6d,
+ 0x3e, 0x91, 0xea, 0x7e, 0xdc, 0x2c, 0x02, 0xc5, 0xff, 0xa7, 0xa6, 0x8f,
+ 0xf9, 0x34, 0x7e, 0xcb, 0x17, 0xfe, 0x9d, 0x03, 0x1f, 0x35, 0xe1, 0x2c,
+ 0x54, 0xa3, 0x67, 0xea, 0xbc, 0x46, 0xbf, 0xfb, 0xf3, 0xbb, 0xef, 0x80,
+ 0x3c, 0xe9, 0x62, 0x86, 0xa8, 0x71, 0xca, 0x62, 0x84, 0x1f, 0x21, 0xf7,
+ 0xe2, 0xfb, 0x88, 0x6b, 0x17, 0xf4, 0xf6, 0x26, 0xf7, 0x16, 0x2f, 0xff,
+ 0xbd, 0x23, 0xf8, 0x98, 0xdd, 0xf1, 0xcb, 0x75, 0x8b, 0xff, 0x73, 0xf8,
+ 0x08, 0xb8, 0x4d, 0xf5, 0x8b, 0xe3, 0xb9, 0x41, 0x62, 0x9d, 0x16, 0x91,
+ 0xea, 0x5c, 0x40, 0xa9, 0x5c, 0xe4, 0xc9, 0x6c, 0x5b, 0xab, 0x7c, 0x5d,
+ 0xa1, 0xc7, 0x6e, 0xcb, 0x17, 0x4f, 0xd6, 0x2e, 0xe1, 0xd6, 0x29, 0xcf,
+ 0x0e, 0x21, 0x4f, 0x8b, 0xd2, 0xc5, 0x8d, 0x58, 0xbd, 0xa9, 0x35, 0x62,
+ 0xfc, 0xfe, 0x29, 0x3a, 0xc5, 0x46, 0xe7, 0xc9, 0x21, 0x91, 0x09, 0xfc,
+ 0x7a, 0xff, 0x0e, 0x48, 0xb3, 0x36, 0x58, 0xbf, 0x8f, 0xad, 0x38, 0x38,
+ 0xb1, 0x7f, 0xd2, 0x5e, 0xc8, 0x49, 0x79, 0x62, 0xa4, 0xf9, 0xa0, 0x5f,
+ 0x7b, 0x7c, 0x09, 0x62, 0xa2, 0x3c, 0x0f, 0x90, 0xd4, 0xa3, 0xef, 0x21,
+ 0xb1, 0x7f, 0xfc, 0xfe, 0xe3, 0xee, 0xda, 0xdf, 0x1c, 0xb7, 0x58, 0xb0,
+ 0x4b, 0x17, 0xfb, 0x53, 0xee, 0xa1, 0x9e, 0x58, 0xbf, 0xff, 0xb2, 0x26,
+ 0x2d, 0x80, 0xfd, 0x73, 0x7c, 0x72, 0xdd, 0x62, 0xec, 0x1a, 0xc5, 0xed,
+ 0x98, 0xeb, 0x17, 0x03, 0x52, 0x6d, 0x5c, 0x5e, 0xfd, 0xa3, 0xce, 0x71,
+ 0x62, 0xa4, 0xf4, 0xf0, 0xae, 0xff, 0xee, 0xb9, 0xe2, 0xce, 0xde, 0xf3,
+ 0x8d, 0x62, 0xfb, 0x9b, 0x0b, 0x8b, 0x15, 0x05, 0x41, 0x8e, 0xa3, 0x10,
+ 0x99, 0x1a, 0xf2, 0x1c, 0xc2, 0x20, 0x0d, 0x22, 0xd0, 0x58, 0xbc, 0x41,
+ 0x9a, 0xb1, 0x4e, 0x6c, 0x62, 0x12, 0xbf, 0xb3, 0xb7, 0x85, 0x3b, 0xac,
+ 0x5f, 0xf8, 0x53, 0xa2, 0xce, 0xc5, 0x9c, 0x58, 0xbf, 0xbe, 0x23, 0x4f,
+ 0x3c, 0x58, 0xad, 0xcf, 0xbf, 0xe7, 0xf7, 0xd0, 0xf8, 0x7c, 0x58, 0xbe,
+ 0x9e, 0xd3, 0xa5, 0x8a, 0x30, 0xf2, 0x76, 0x25, 0xb8, 0xd1, 0xac, 0x5f,
+ 0xff, 0x70, 0xb3, 0xb3, 0x78, 0xb3, 0x9f, 0x68, 0x96, 0x2b, 0x0f, 0xa9,
+ 0xc6, 0x6e, 0xf9, 0xd6, 0x2f, 0xd3, 0xee, 0x07, 0xf5, 0x8a, 0x95, 0x43,
+ 0xa3, 0x21, 0xc8, 0x50, 0x3b, 0x64, 0x50, 0x8e, 0x39, 0x01, 0x0c, 0x5f,
+ 0xff, 0xde, 0xf9, 0x99, 0x09, 0x07, 0x0b, 0x22, 0x84, 0xf4, 0xb1, 0x79,
+ 0xfa, 0x82, 0xc5, 0x7c, 0xff, 0x09, 0x7a, 0xc7, 0x58, 0xbc, 0x06, 0xfa,
+ 0xc5, 0xfe, 0xdb, 0x1c, 0x6c, 0xc6, 0xac, 0x50, 0xcf, 0x8f, 0x04, 0x98,
+ 0x76, 0xfe, 0xd4, 0x8e, 0x4a, 0x25, 0x8b, 0x71, 0x62, 0xb6, 0x3c, 0x0f,
+ 0x97, 0x57, 0x7a, 0xdb, 0x07, 0x46, 0x8a, 0x1b, 0x12, 0x0d, 0xb7, 0x25,
+ 0x45, 0xef, 0x19, 0x1f, 0x4b, 0xf1, 0x43, 0xef, 0x50, 0x87, 0x3b, 0x87,
+ 0xe7, 0x77, 0x5a, 0x13, 0x40, 0x84, 0x99, 0x46, 0x79, 0xc9, 0x46, 0x5e,
+ 0x95, 0x72, 0x28, 0x74, 0xc7, 0x42, 0x10, 0x36, 0xdb, 0xfe, 0xc8, 0xa0,
+ 0xda, 0xdb, 0xe2, 0x58, 0xbd, 0xb4, 0xee, 0xb1, 0x68, 0xc1, 0x9e, 0xdb,
+ 0x9e, 0x54, 0x62, 0x7c, 0x02, 0x8e, 0xda, 0xfc, 0xd1, 0x91, 0xbb, 0x46,
+ 0xeb, 0x17, 0xb8, 0x7e, 0x2c, 0x5f, 0xee, 0xf6, 0x5f, 0xd0, 0xce, 0x2c,
+ 0x5f, 0xff, 0x3f, 0x9f, 0x4c, 0x09, 0xfb, 0xef, 0x20, 0x58, 0xbf, 0xfd,
+ 0x24, 0xd0, 0x68, 0x7d, 0xc9, 0xb8, 0xb1, 0x7f, 0xff, 0xa4, 0xec, 0x4e,
+ 0x52, 0x5b, 0x1f, 0x0f, 0xdd, 0x83, 0x58, 0xbf, 0xb3, 0x53, 0xda, 0x60,
+ 0xb1, 0x5f, 0x44, 0x81, 0x30, 0xdd, 0x08, 0x2c, 0x5f, 0xfd, 0x85, 0x38,
+ 0x6c, 0xc3, 0xd9, 0xb2, 0xc5, 0xfb, 0x82, 0x1e, 0x71, 0x62, 0xfe, 0xfe,
+ 0x1c, 0x5b, 0xe2, 0xc5, 0xd3, 0xe5, 0x8a, 0x73, 0xc6, 0xe1, 0x7d, 0xff,
+ 0x9b, 0xe6, 0x4e, 0x7b, 0xee, 0x75, 0x8b, 0xff, 0xfc, 0xfe, 0x9f, 0x96,
+ 0x7b, 0x53, 0xf2, 0xce, 0xc2, 0xdd, 0x62, 0xff, 0xfa, 0x73, 0xdf, 0x68,
+ 0x68, 0x43, 0x92, 0x95, 0x8a, 0x82, 0xb2, 0x31, 0xa7, 0xbc, 0x35, 0xe3,
+ 0xc8, 0xbe, 0x31, 0xc4, 0x4f, 0x37, 0x88, 0x87, 0xb1, 0xff, 0x73, 0x15,
+ 0xff, 0xf7, 0x3f, 0x26, 0x98, 0xfb, 0x37, 0xdf, 0xae, 0x2c, 0x5e, 0x6d,
+ 0x71, 0x62, 0x84, 0x7e, 0x21, 0x2a, 0x5f, 0xfd, 0xf6, 0x7d, 0xbc, 0xe4,
+ 0xe0, 0xe2, 0xc5, 0xfb, 0x1b, 0xc2, 0x95, 0x8a, 0x73, 0xeb, 0x02, 0x25,
+ 0xff, 0x14, 0xc3, 0x39, 0x8f, 0x2b, 0x16, 0xd9, 0x62, 0xa4, 0xf2, 0x48,
+ 0xda, 0xff, 0xff, 0xa4, 0x07, 0x68, 0x19, 0xef, 0xe1, 0xf3, 0x79, 0xfc,
+ 0x9d, 0x62, 0xff, 0xf9, 0xcb, 0xc2, 0xfb, 0xf2, 0x39, 0xbd, 0x83, 0x58,
+ 0xaf, 0xa2, 0xeb, 0xcd, 0x17, 0xf3, 0xec, 0x63, 0x10, 0x16, 0x2f, 0xff,
+ 0xfb, 0xec, 0xfc, 0xc3, 0x58, 0x80, 0x66, 0x47, 0xc9, 0x31, 0xab, 0x17,
+ 0x99, 0xb7, 0x54, 0x9b, 0x45, 0x4a, 0x24, 0xf7, 0x69, 0xbf, 0xe2, 0x73,
+ 0x75, 0x9b, 0x4f, 0x96, 0x2f, 0xff, 0xcf, 0xb6, 0x42, 0x4d, 0xd0, 0xb8,
+ 0xe5, 0x0e, 0x2c, 0x5f, 0xd2, 0x5b, 0xe7, 0x5e, 0x58, 0xbf, 0xff, 0xe6,
+ 0xf7, 0x23, 0x33, 0xda, 0xcf, 0x89, 0xfe, 0xfc, 0x93, 0xac, 0x5f, 0xff,
+ 0xd2, 0xde, 0x9f, 0xcf, 0x1d, 0xe0, 0xfa, 0xc1, 0xac, 0x5f, 0xdf, 0x93,
+ 0xcb, 0x8d, 0x62, 0x9d, 0x55, 0xb4, 0x44, 0x7a, 0x86, 0x11, 0xc8, 0xfe,
+ 0x74, 0x05, 0x72, 0x2f, 0xe3, 0x4f, 0x96, 0x2f, 0xfe, 0x8d, 0x24, 0xd0,
+ 0x8c, 0xec, 0x61, 0x9f, 0x8e, 0x58, 0xbf, 0x9a, 0x03, 0xfb, 0x9d, 0x62,
+ 0xff, 0x64, 0x45, 0x27, 0x33, 0x75, 0x8b, 0x38, 0xcf, 0x93, 0xc5, 0xd5,
+ 0xdf, 0x68, 0xe1, 0xfc, 0x2e, 0xaf, 0xff, 0x7f, 0x20, 0xc5, 0xe6, 0x83,
+ 0x9b, 0x2b, 0x17, 0xfd, 0x99, 0xbc, 0x70, 0xbe, 0xfa, 0x58, 0xbf, 0xfb,
+ 0xf9, 0xb7, 0x1f, 0x53, 0xdc, 0xc4, 0xb1, 0x7f, 0xff, 0x85, 0xed, 0x0a,
+ 0x1a, 0x17, 0x85, 0xe7, 0xf7, 0x3e, 0xeb, 0x17, 0x63, 0xac, 0x56, 0xe8,
+ 0xc1, 0x24, 0x7e, 0xcc, 0x97, 0xbc, 0x07, 0x58, 0xbf, 0xa6, 0x36, 0xe6,
+ 0xd8, 0x12, 0xc5, 0x4a, 0x21, 0x30, 0xcb, 0x43, 0xb6, 0xef, 0x16, 0x2e,
+ 0x2f, 0x2c, 0x5f, 0x78, 0x9b, 0xa5, 0x8b, 0x1b, 0x26, 0xe9, 0xc5, 0xef,
+ 0xfd, 0xe9, 0x39, 0x31, 0xa5, 0x80, 0x58, 0xa9, 0x3e, 0x4c, 0x26, 0xb0,
+ 0x16, 0x2a, 0x24, 0x73, 0x94, 0x2d, 0x7c, 0x41, 0x7f, 0xc4, 0x39, 0x93,
+ 0xf7, 0x34, 0x16, 0x2f, 0xce, 0x5b, 0x30, 0xd6, 0x29, 0xcf, 0x8f, 0x87,
+ 0x77, 0xfd, 0x20, 0xfc, 0xec, 0x59, 0xc5, 0x8a, 0x93, 0xda, 0x11, 0x0d,
+ 0xf6, 0x72, 0x49, 0x62, 0xff, 0xf3, 0xea, 0x73, 0xe2, 0x7e, 0x7f, 0x00,
+ 0xb1, 0x7f, 0xb9, 0xf9, 0x72, 0x1c, 0xac, 0x5f, 0xff, 0x0c, 0x5e, 0xe0,
+ 0xf2, 0x1f, 0x9e, 0xc3, 0x95, 0x8b, 0x89, 0x96, 0x2b, 0x64, 0xc1, 0x46,
+ 0x43, 0x89, 0x2e, 0x64, 0x4a, 0x76, 0xef, 0x16, 0x2f, 0xf4, 0x27, 0x5b,
+ 0x4e, 0xb6, 0x58, 0xbf, 0xcd, 0xe3, 0x34, 0x37, 0xd2, 0xc5, 0x49, 0xf5,
+ 0x88, 0xda, 0xff, 0xf4, 0xc3, 0xf2, 0x46, 0x96, 0x6c, 0x1c, 0x16, 0x2f,
+ 0xff, 0xf4, 0xb9, 0x37, 0x85, 0xec, 0x1c, 0x9c, 0x7f, 0x9e, 0x96, 0x2f,
+ 0xf3, 0x9c, 0x73, 0xc0, 0xf8, 0xb1, 0x7b, 0xd9, 0xba, 0xc5, 0xff, 0xf1,
+ 0x3f, 0x67, 0xf7, 0xe7, 0xdc, 0x9e, 0xd2, 0xb1, 0x4e, 0x9a, 0x8e, 0x93,
+ 0x3e, 0xc1, 0xe3, 0x51, 0x0f, 0x5f, 0xe1, 0xe1, 0x41, 0xfe, 0x25, 0x8b,
+ 0xff, 0x85, 0xcf, 0xb4, 0x27, 0xb8, 0x9f, 0xa5, 0x8b, 0xff, 0xf9, 0xf5,
+ 0x22, 0x83, 0xb9, 0x67, 0x85, 0x1e, 0xfb, 0x2c, 0x58, 0x6b, 0x17, 0xfd,
+ 0x31, 0xd9, 0xa0, 0x1d, 0xa0, 0xb1, 0x7f, 0x0b, 0x7f, 0xce, 0xb1, 0x62,
+ 0xf7, 0x5c, 0xfa, 0xc5, 0x61, 0xe7, 0x31, 0x7d, 0x3a, 0x72, 0x9a, 0x33,
+ 0xfa, 0x43, 0x2e, 0x90, 0x97, 0x21, 0x15, 0x7f, 0xfe, 0x92, 0xf3, 0x9c,
+ 0x43, 0x9f, 0xe1, 0x36, 0x96, 0x2f, 0xfc, 0xcf, 0x93, 0xa6, 0x83, 0xfd,
+ 0x62, 0xb8, 0x88, 0xff, 0x29, 0xdf, 0x98, 0x78, 0x40, 0x58, 0xb8, 0x5d,
+ 0xcb, 0x17, 0xfe, 0x1c, 0xc0, 0x4f, 0x01, 0x3c, 0x16, 0x2a, 0x08, 0xa4,
+ 0x72, 0x3d, 0x13, 0xb0, 0xdd, 0xff, 0x4e, 0x8c, 0xe4, 0xfd, 0x9d, 0x62,
+ 0xfe, 0x76, 0x87, 0x9f, 0x65, 0x8b, 0xed, 0xa7, 0xee, 0xb1, 0x5f, 0x3d,
+ 0x16, 0x2e, 0xbe, 0x9c, 0x27, 0x58, 0xbe, 0xf4, 0xe0, 0xd6, 0x28, 0x67,
+ 0x85, 0xd1, 0x05, 0xef, 0x66, 0xcb, 0x15, 0xde, 0x36, 0xd5, 0x1d, 0xe8,
+ 0xf4, 0xcb, 0x5b, 0xda, 0x30, 0xa8, 0x42, 0x38, 0x6d, 0x59, 0x2e, 0x43,
+ 0x78, 0xd9, 0x5c, 0xbe, 0x24, 0x9d, 0x47, 0x04, 0x78, 0xc5, 0x7f, 0x0f,
+ 0x26, 0x8c, 0x98, 0x09, 0x25, 0x08, 0x2e, 0x46, 0xe5, 0xe8, 0xf7, 0x85,
+ 0x1c, 0x68, 0x47, 0x71, 0xd0, 0x8a, 0x0d, 0x8f, 0xb8, 0x8e, 0xf6, 0x61,
+ 0xab, 0x17, 0xf4, 0xc3, 0x8d, 0x9b, 0xac, 0x5f, 0xff, 0xed, 0xf3, 0xd2,
+ 0x5e, 0xe7, 0xd9, 0xfd, 0x2f, 0xda, 0x56, 0x2e, 0x98, 0xcd, 0x22, 0xb3,
+ 0xe3, 0xa1, 0x97, 0x5f, 0x03, 0xde, 0xe9, 0x62, 0xf1, 0xba, 0x95, 0x8b,
+ 0xf7, 0x9f, 0xb7, 0xdd, 0x62, 0xdd, 0xec, 0x9e, 0x46, 0x0f, 0x5f, 0xed,
+ 0x37, 0x80, 0x19, 0x41, 0x62, 0xff, 0xfb, 0xae, 0x67, 0x67, 0xf4, 0xf6,
+ 0x72, 0xc1, 0xac, 0x54, 0xa2, 0x20, 0x46, 0xb7, 0xf0, 0x98, 0x8b, 0x00,
+ 0xb1, 0x7f, 0xff, 0x6a, 0x7c, 0xfb, 0xb8, 0xe5, 0xf4, 0xf0, 0x7e, 0x2c,
+ 0x5e, 0x1c, 0xf4, 0xb1, 0x7e, 0x6d, 0x0c, 0x44, 0xb1, 0x52, 0x78, 0xc6,
+ 0x8f, 0x5f, 0xfe, 0xe3, 0x7b, 0xef, 0x03, 0xff, 0xa6, 0x8f, 0x58, 0xbf,
+ 0x39, 0xdb, 0xd2, 0xb1, 0x7f, 0xbc, 0xfb, 0xb8, 0xfa, 0x25, 0x8b, 0xff,
+ 0xb6, 0xc2, 0xc8, 0x8c, 0xd0, 0xa4, 0x0b, 0x17, 0xf4, 0x9f, 0x05, 0x87,
+ 0x58, 0xb8, 0xbb, 0x2c, 0x54, 0xa3, 0x0b, 0x0d, 0x5d, 0x1f, 0xb8, 0xb6,
+ 0xff, 0xff, 0xff, 0xc3, 0x29, 0xdf, 0xad, 0xdf, 0xa3, 0xb1, 0x1b, 0x84,
+ 0xdd, 0x05, 0xbf, 0xde, 0x22, 0x73, 0xf1, 0x62, 0xfb, 0xc1, 0xe7, 0x72,
+ 0xc5, 0xff, 0x9f, 0xd3, 0xe7, 0xed, 0x25, 0xba, 0xc5, 0xdd, 0x41, 0x62,
+ 0xb1, 0x32, 0x07, 0x85, 0x03, 0x13, 0x89, 0x02, 0xf7, 0x42, 0xd9, 0x62,
+ 0xfa, 0x60, 0x00, 0x96, 0x2b, 0x47, 0x88, 0x44, 0x17, 0xe8, 0xe7, 0xd6,
+ 0x1a, 0xb1, 0x58, 0x79, 0xa4, 0x43, 0x77, 0xbe, 0xb1, 0x7f, 0xd9, 0xee,
+ 0x07, 0xcf, 0x67, 0xd6, 0x2b, 0x63, 0xd3, 0x38, 0xc5, 0xe3, 0xce, 0xeb,
+ 0x17, 0xc5, 0x27, 0xe2, 0xc5, 0x9f, 0x63, 0xc0, 0xf0, 0xf5, 0xff, 0x37,
+ 0x5c, 0x78, 0xff, 0x88, 0x35, 0x8b, 0xf3, 0x75, 0x00, 0xf8, 0xb1, 0x78,
+ 0x5d, 0x71, 0x62, 0xff, 0xa2, 0xe7, 0x66, 0x2d, 0x84, 0x35, 0x8b, 0xfd,
+ 0xce, 0xcc, 0x5e, 0xc0, 0x2c, 0x5e, 0x3c, 0xf9, 0x62, 0x9d, 0x12, 0x11,
+ 0x1f, 0x1c, 0xd6, 0xe9, 0x35, 0x62, 0xff, 0xc4, 0x3f, 0xcf, 0x39, 0x9a,
+ 0x95, 0x8a, 0xf9, 0xeb, 0x30, 0xc5, 0xa3, 0x3b, 0xd6, 0x42, 0xa4, 0x6c,
+ 0xdb, 0xb4, 0x2c, 0xc6, 0x45, 0x85, 0x86, 0xc2, 0x83, 0xa2, 0x28, 0x93,
+ 0xf5, 0x0e, 0x9f, 0xc6, 0xba, 0x50, 0xd1, 0xe3, 0x9f, 0x98, 0xc4, 0x51,
+ 0xd8, 0xfe, 0x38, 0xac, 0x38, 0x57, 0xf7, 0x42, 0x1a, 0xa3, 0x19, 0x82,
+ 0x79, 0x29, 0x1c, 0x14, 0x89, 0x3b, 0xf9, 0xe2, 0xe6, 0xcf, 0xa5, 0x8b,
+ 0x8f, 0xf5, 0x8b, 0xed, 0xd9, 0xb7, 0x54, 0x9c, 0xa5, 0xf3, 0x1f, 0x09,
+ 0x62, 0xb4, 0x7a, 0x5e, 0x31, 0xbd, 0xf7, 0xfa, 0xc5, 0xfc, 0xc3, 0xfc,
+ 0x96, 0xcb, 0x17, 0x1b, 0xf5, 0x8b, 0x98, 0xeb, 0x17, 0xe1, 0x4f, 0x50,
+ 0xe2, 0xc5, 0xb8, 0xb1, 0x52, 0x7a, 0x78, 0x2e, 0xc5, 0x56, 0x8c, 0x94,
+ 0xe7, 0xc6, 0x61, 0x8d, 0x5b, 0x91, 0x7c, 0x75, 0x8b, 0x89, 0xb2, 0xd1,
+ 0xa9, 0x62, 0xe7, 0x3a, 0xc5, 0xcc, 0x35, 0x8b, 0x9c, 0xd5, 0x8b, 0xf6,
+ 0xb7, 0x66, 0xdd, 0x52, 0x76, 0x97, 0xe9, 0xdd, 0xc9, 0x96, 0x29, 0x62,
+ 0x8e, 0x6c, 0xf8, 0x4f, 0x7b, 0x6c, 0x09, 0x62, 0xf0, 0x3b, 0x32, 0xc5,
+ 0xff, 0x3c, 0x20, 0xe4, 0x09, 0x82, 0xc5, 0xc7, 0x8e, 0x58, 0xbf, 0xef,
+ 0x49, 0x38, 0x23, 0x9b, 0x65, 0x8b, 0xda, 0x60, 0x2c, 0x56, 0x1e, 0xcb,
+ 0x9e, 0x5b, 0x4b, 0x17, 0x6d, 0x2b, 0x15, 0x86, 0xa9, 0x84, 0xaa, 0x35,
+ 0x2a, 0x3c, 0x91, 0x88, 0x0b, 0x8c, 0x5f, 0x06, 0x1d, 0xa8, 0xe4, 0x3f,
+ 0x1f, 0x61, 0xf2, 0x38, 0xe3, 0xa0, 0x92, 0xaf, 0x63, 0x8d, 0x62, 0xfe,
+ 0xcf, 0xf2, 0x75, 0xba, 0xc5, 0xff, 0xfd, 0xc9, 0xd6, 0xf9, 0xd7, 0xba,
+ 0xdc, 0x4c, 0x5d, 0x79, 0x62, 0xfe, 0xe0, 0xa2, 0x8a, 0x4e, 0xb1, 0x7b,
+ 0xa0, 0x46, 0x6c, 0x8d, 0xd2, 0x1c, 0xe1, 0x78, 0x98, 0x6a, 0x31, 0x3d,
+ 0x86, 0x8e, 0x16, 0xde, 0x58, 0xbc, 0x26, 0x0d, 0x62, 0xa2, 0x36, 0x0c,
+ 0x25, 0x7f, 0xd2, 0x73, 0x05, 0x13, 0xb7, 0x4b, 0x17, 0xd1, 0x37, 0xa3,
+ 0x3e, 0x7b, 0xa0, 0x21, 0xa9, 0x8c, 0x22, 0xeb, 0x62, 0xb8, 0x5a, 0x59,
+ 0xa1, 0xcb, 0x4e, 0xc8, 0x4e, 0x1b, 0x6d, 0x94, 0x5e, 0xf9, 0x4e, 0xe3,
+ 0xe1, 0x99, 0xfa, 0xe0, 0xf1, 0x8b, 0x4a, 0xd1, 0x78, 0x72, 0x3e, 0x5f,
+ 0x4e, 0x3f, 0x87, 0x0b, 0x9b, 0xfd, 0x19, 0x9a, 0xdd, 0x9b, 0x75, 0x49,
+ 0x4e, 0x5f, 0xd9, 0xc6, 0x37, 0xee, 0xb1, 0x7f, 0xb5, 0xe7, 0xf6, 0xc2,
+ 0xe2, 0xc5, 0xdc, 0xe2, 0xc5, 0xff, 0x8b, 0x35, 0x3e, 0x7d, 0xdc, 0x6b,
+ 0x17, 0xec, 0x04, 0xe1, 0x2c, 0x5a, 0x32, 0x08, 0xe0, 0xc2, 0xed, 0x1b,
+ 0x30, 0xc1, 0x1f, 0x5f, 0xff, 0xcf, 0xa1, 0x1b, 0xfc, 0x2d, 0xfe, 0xf1,
+ 0xcf, 0x21, 0x2c, 0x5f, 0xf6, 0x45, 0x06, 0xd6, 0xdf, 0x12, 0xc5, 0xff,
+ 0xb0, 0xb7, 0xfb, 0xc7, 0x3c, 0x84, 0xb1, 0x7e, 0x93, 0xb4, 0x9d, 0x62,
+ 0xf6, 0x84, 0x6f, 0xcf, 0xa5, 0x90, 0xaf, 0xc3, 0xcc, 0x07, 0x16, 0x2f,
+ 0xfe, 0x8e, 0x62, 0x06, 0x7a, 0x49, 0xc0, 0xb1, 0x68, 0xce, 0xfa, 0xa7,
+ 0x4c, 0x36, 0x07, 0x85, 0x2f, 0x0d, 0x03, 0x28, 0xa2, 0x54, 0xaf, 0xda,
+ 0x3f, 0x6b, 0xff, 0x9f, 0xb4, 0xfd, 0xe6, 0x28, 0xa7, 0x75, 0x8b, 0xf7,
+ 0x7c, 0x8d, 0x3c, 0xe6, 0xac, 0x5d, 0xb6, 0x2c, 0x5f, 0x70, 0xbf, 0xe5,
+ 0x8b, 0xfd, 0xf9, 0xe4, 0x9c, 0x51, 0x2c, 0x5f, 0xb7, 0x29, 0xfe, 0x2c,
+ 0x5f, 0xde, 0x30, 0x65, 0x30, 0x58, 0xb6, 0xcb, 0x14, 0xc7, 0x84, 0x22,
+ 0xfb, 0xff, 0x3f, 0xe7, 0xb7, 0xb3, 0x02, 0xe2, 0xc5, 0xe8, 0x4e, 0xcb,
+ 0x15, 0xa3, 0xdf, 0x12, 0x0d, 0xff, 0x75, 0x0e, 0x19, 0x9d, 0x9b, 0x4b,
+ 0x17, 0xfe, 0x14, 0x46, 0x3f, 0xce, 0x2d, 0x4a, 0xc5, 0xb7, 0x58, 0xa8,
+ 0x27, 0xee, 0x32, 0x37, 0x35, 0x89, 0xab, 0x50, 0x80, 0xf9, 0x17, 0x0f,
+ 0xbb, 0x90, 0xaf, 0xe1, 0x74, 0x76, 0x62, 0x58, 0xbf, 0xff, 0x61, 0x00,
+ 0x4c, 0x5b, 0x98, 0xf3, 0xb3, 0x06, 0xb1, 0x6f, 0x2c, 0x5f, 0xdd, 0x19,
+ 0x39, 0x03, 0xac, 0x5f, 0x75, 0xc9, 0x1a, 0xc5, 0x84, 0xb1, 0x7a, 0x5b,
+ 0x63, 0x0d, 0xb0, 0x09, 0x29, 0xd1, 0x57, 0xa1, 0x22, 0x66, 0xbe, 0x9f,
+ 0x7f, 0x16, 0x2f, 0xd3, 0xd4, 0x33, 0xcb, 0x17, 0xc7, 0xc7, 0x3a, 0xc5,
+ 0xf6, 0xec, 0xdb, 0xaa, 0x4b, 0x92, 0xfe, 0x9f, 0x61, 0x37, 0x96, 0x2e,
+ 0x3c, 0xac, 0x5f, 0xb5, 0xbb, 0x36, 0xea, 0x93, 0x38, 0xbf, 0xf1, 0xaf,
+ 0xd7, 0x0b, 0x02, 0x60, 0x2c, 0x5e, 0xe6, 0x0d, 0x62, 0xa5, 0x15, 0x98,
+ 0x2f, 0xe3, 0x71, 0x20, 0xdf, 0xfe, 0xeb, 0x86, 0x66, 0xf2, 0xe4, 0x52,
+ 0x75, 0x8b, 0xfe, 0x9d, 0xe4, 0xf2, 0x59, 0xd9, 0x62, 0x89, 0x10, 0xbd,
+ 0xc9, 0x75, 0x18, 0x8e, 0x57, 0x86, 0x05, 0xee, 0xe6, 0xfa, 0xc5, 0xcd,
+ 0x05, 0x8b, 0xfa, 0x1e, 0xeb, 0x77, 0xe2, 0xc5, 0x31, 0xe4, 0x08, 0x5e,
+ 0xfe, 0x7e, 0x61, 0x30, 0x4b, 0x17, 0xf9, 0xb5, 0x9d, 0xa4, 0xbc, 0xb1,
+ 0x7e, 0x86, 0x1e, 0x77, 0x58, 0xad, 0xcf, 0x77, 0x46, 0x97, 0x85, 0x09,
+ 0x58, 0xbf, 0xf4, 0xc4, 0xcf, 0xd7, 0x0c, 0xdb, 0x65, 0x8a, 0xd9, 0x70,
+ 0x72, 0x04, 0x4e, 0x53, 0xa2, 0x23, 0x98, 0xfe, 0x3b, 0xd6, 0x2a, 0x26,
+ 0x8f, 0x10, 0x8a, 0x11, 0x5d, 0x88, 0xfb, 0x87, 0x6e, 0x11, 0x2c, 0x5f,
+ 0xf9, 0xe2, 0xfc, 0x90, 0xca, 0x60, 0xb1, 0x4e, 0x7a, 0xbf, 0x17, 0xbd,
+ 0xbb, 0x79, 0x62, 0xff, 0xc2, 0xd6, 0x0e, 0x7b, 0xbe, 0xfb, 0xac, 0x56,
+ 0x1f, 0x0f, 0xc7, 0xaf, 0xf9, 0xf5, 0xbf, 0xf0, 0xc7, 0x95, 0x8a, 0x81,
+ 0xed, 0xf0, 0x86, 0xff, 0xb8, 0x26, 0x0e, 0x23, 0x30, 0x0b, 0x17, 0xff,
+ 0xbd, 0x3c, 0x30, 0x5c, 0xf4, 0xc5, 0x13, 0xac, 0x5f, 0x40, 0x5f, 0xc5,
+ 0x8b, 0xff, 0xf3, 0x7f, 0x0f, 0x27, 0x33, 0x30, 0xd3, 0x5a, 0x0b, 0x17,
+ 0xf3, 0x9f, 0x61, 0x6a, 0x0b, 0x17, 0xd9, 0x13, 0x01, 0x62, 0xef, 0xe2,
+ 0xc5, 0x1c, 0xdd, 0x7c, 0x8e, 0xfb, 0x6f, 0xb7, 0x96, 0x29, 0x8f, 0x14,
+ 0x44, 0x37, 0xc7, 0x8d, 0x3b, 0xdf, 0x2c, 0x5f, 0xa6, 0x28, 0xa7, 0x75,
+ 0x8b, 0xa7, 0xe6, 0x1e, 0xcb, 0x97, 0x54, 0xaa, 0x5b, 0xc3, 0xde, 0x93,
+ 0xa2, 0x23, 0xfa, 0xb9, 0x42, 0xbf, 0xb3, 0xd5, 0xff, 0x14, 0x9f, 0x82,
+ 0x83, 0x1a, 0xb1, 0x7f, 0xcc, 0xdd, 0x43, 0x99, 0xd7, 0x96, 0x2e, 0x3f,
+ 0x65, 0x8b, 0xfe, 0xf6, 0x7c, 0xb3, 0xdf, 0x75, 0x8b, 0xa4, 0x6b, 0x15,
+ 0x03, 0xcf, 0x23, 0x8b, 0xff, 0xbe, 0xfe, 0x9d, 0x00, 0xa7, 0xdc, 0x58,
+ 0xac, 0x46, 0x73, 0x34, 0x88, 0x86, 0xef, 0xe2, 0xc5, 0xfb, 0x22, 0x88,
+ 0x5b, 0x2c, 0x56, 0x1e, 0x1f, 0xc5, 0xef, 0xa0, 0xde, 0x75, 0x8b, 0xed,
+ 0x00, 0x12, 0xb1, 0x7f, 0xcf, 0xb9, 0x9c, 0x88, 0x98, 0x25, 0x8a, 0x35,
+ 0x14, 0x7d, 0x10, 0xb9, 0x17, 0xc8, 0xef, 0xd1, 0x49, 0xe4, 0x35, 0x8b,
+ 0xf1, 0x83, 0xce, 0x09, 0x62, 0xfc, 0x2e, 0xef, 0xcf, 0x4b, 0x17, 0xff,
+ 0xf9, 0xf8, 0x0c, 0x31, 0xfb, 0x4f, 0xde, 0x62, 0x8a, 0x77, 0x58, 0xbd,
+ 0xcc, 0x25, 0x8a, 0xd9, 0x15, 0xda, 0x2d, 0x03, 0x2d, 0xd0, 0x3a, 0xc5,
+ 0xff, 0xa2, 0x31, 0x86, 0xf3, 0x13, 0x79, 0x62, 0xa5, 0x3c, 0xac, 0x3e,
+ 0x72, 0xa6, 0x86, 0xc1, 0x18, 0x88, 0x62, 0xfb, 0x46, 0x77, 0xe4, 0xb1,
+ 0x7d, 0x27, 0xc2, 0x58, 0xa9, 0x3c, 0xa3, 0x94, 0xde, 0x13, 0x71, 0x62,
+ 0xff, 0x06, 0xf1, 0x4f, 0x1c, 0xeb, 0x17, 0xff, 0xbe, 0xe6, 0x7d, 0x9f,
+ 0xd3, 0x83, 0x75, 0x8b, 0xde, 0xfb, 0xac, 0x5f, 0xf6, 0x8c, 0x93, 0xbc,
+ 0x7b, 0x44, 0xb1, 0x52, 0x7b, 0x6e, 0x3b, 0x78, 0xc7, 0xd2, 0xc5, 0xf6,
+ 0xec, 0xdb, 0xaa, 0x44, 0x22, 0xfe, 0x86, 0xb0, 0x6c, 0x75, 0x8b, 0xf1,
+ 0x43, 0xe1, 0xf1, 0x62, 0xa4, 0xf6, 0x1c, 0xba, 0x8d, 0x47, 0x3c, 0x44,
+ 0x1a, 0x1e, 0xe4, 0x22, 0x6f, 0xf7, 0xb8, 0x28, 0x4e, 0xd2, 0xb1, 0x7f,
+ 0xe7, 0x0b, 0x99, 0xaf, 0x79, 0xf4, 0xb1, 0x58, 0x7e, 0xbe, 0x35, 0xb8,
+ 0x8d, 0x58, 0xbf, 0xff, 0x3e, 0xb7, 0xfe, 0x19, 0xad, 0x60, 0x51, 0xd2,
+ 0x75, 0x8a, 0x82, 0x25, 0x58, 0x87, 0x83, 0x17, 0xfa, 0x2f, 0xcf, 0x0c,
+ 0x73, 0x56, 0x2f, 0xef, 0xce, 0xc6, 0x60, 0x16, 0x2f, 0xe6, 0x6e, 0xa1,
+ 0xc7, 0x58, 0xbf, 0xe6, 0x62, 0x33, 0xae, 0x08, 0xeb, 0x17, 0xf8, 0x13,
+ 0x1f, 0x3e, 0x91, 0xac, 0x5f, 0xf1, 0xf1, 0xb5, 0xb1, 0x9d, 0x1d, 0x62,
+ 0xff, 0xbb, 0xa4, 0xf3, 0x18, 0x10, 0x41, 0x2c, 0x5e, 0xe3, 0xc4, 0xb1,
+ 0x52, 0x8d, 0x4c, 0x36, 0x63, 0xd1, 0x21, 0xde, 0x66, 0x3a, 0xc5, 0xff,
+ 0x67, 0x24, 0x29, 0x7e, 0xb8, 0xb1, 0x5b, 0x1e, 0xb0, 0xc7, 0x2f, 0xf7,
+ 0x5c, 0xf1, 0x49, 0xf8, 0xb1, 0x7f, 0xf9, 0x8b, 0x73, 0x06, 0x4d, 0x0f,
+ 0xb4, 0x16, 0x29, 0xd1, 0x00, 0x23, 0x5b, 0xff, 0xb0, 0x6f, 0xd9, 0x88,
+ 0x06, 0x70, 0x0b, 0x17, 0xf6, 0x13, 0x83, 0x92, 0xb1, 0x7f, 0xdd, 0x6e,
+ 0xfa, 0xc8, 0x42, 0x56, 0x2f, 0xff, 0xd1, 0x4c, 0x4f, 0x11, 0x8f, 0xd7,
+ 0x18, 0x37, 0x3a, 0xc5, 0x4a, 0xf9, 0xfc, 0x0d, 0x72, 0x38, 0xbe, 0xa3,
+ 0x4e, 0x72, 0xf8, 0x8d, 0xf4, 0x60, 0x72, 0xef, 0xc6, 0x1e, 0xd0, 0x90,
+ 0x04, 0x28, 0xc8, 0x8b, 0x88, 0xfe, 0x2c, 0x11, 0xdd, 0xc5, 0x8b, 0x14,
+ 0x63, 0x21, 0x6a, 0x32, 0x7d, 0x71, 0xe1, 0xd1, 0x7e, 0x8b, 0xef, 0xd7,
+ 0x96, 0x2e, 0x7f, 0xac, 0x5f, 0xf9, 0x83, 0x88, 0x9f, 0xc5, 0x20, 0x58,
+ 0xad, 0x99, 0x28, 0x10, 0xa4, 0x3d, 0x8d, 0x13, 0xa2, 0xbf, 0x0b, 0xdf,
+ 0x1f, 0x76, 0x1a, 0xc5, 0xfc, 0x67, 0x8a, 0x4f, 0xc5, 0x8a, 0x93, 0xd3,
+ 0x81, 0x25, 0xff, 0x9c, 0xf9, 0xc3, 0x3a, 0x86, 0x79, 0x62, 0xfb, 0x83,
+ 0x1c, 0xac, 0x57, 0xcf, 0x93, 0xc8, 0x37, 0xbe, 0x1f, 0x16, 0x2f, 0xf6,
+ 0x43, 0x9c, 0xc2, 0x02, 0xc5, 0xfc, 0xcd, 0xb1, 0x9f, 0xc5, 0x8a, 0xf9,
+ 0xf1, 0x70, 0xce, 0xa0, 0x8a, 0x3f, 0x42, 0x06, 0xff, 0xd1, 0x9e, 0xfe,
+ 0x43, 0x98, 0x50, 0x58, 0xbf, 0xa7, 0xae, 0x1e, 0x49, 0x62, 0xff, 0xfe,
+ 0x00, 0x23, 0x41, 0x45, 0xdf, 0x5e, 0xee, 0xc5, 0xdf, 0x53, 0x0c, 0xfc,
+ 0x72, 0xc5, 0xdd, 0xf2, 0x34, 0x58, 0xb8, 0xd0, 0x2c, 0x5f, 0xff, 0xbe,
+ 0xf1, 0x7d, 0xfa, 0xf7, 0xf7, 0x7e, 0x60, 0xd6, 0x2f, 0xa5, 0xc5, 0xc5,
+ 0x8b, 0x46, 0x77, 0xda, 0x2d, 0xe4, 0x8f, 0x71, 0x9f, 0xac, 0xd4, 0xaa,
+ 0xe0, 0xc8, 0x62, 0xee, 0x50, 0xe8, 0x5f, 0x2e, 0x68, 0xcd, 0xaf, 0x7e,
+ 0x4e, 0xb1, 0x7f, 0xbb, 0x3f, 0x50, 0x29, 0x0d, 0x62, 0xff, 0x66, 0xbd,
+ 0x98, 0x17, 0x16, 0x2f, 0xff, 0xd8, 0x09, 0x06, 0xb5, 0x21, 0x19, 0xa6,
+ 0x68, 0x2c, 0x5b, 0xbd, 0x58, 0xbf, 0x67, 0xf7, 0x93, 0xac, 0x5f, 0xfd,
+ 0x3b, 0x49, 0x93, 0x14, 0xf0, 0x51, 0x2c, 0x5e, 0x78, 0xec, 0x58, 0xa8,
+ 0x1f, 0x3f, 0x92, 0x2a, 0x34, 0x4e, 0xa3, 0x07, 0x77, 0x37, 0x23, 0x4e,
+ 0x2b, 0xf8, 0x5c, 0x50, 0x90, 0xbb, 0x9f, 0x58, 0xbe, 0xe6, 0x6b, 0x65,
+ 0x8a, 0x81, 0xbc, 0xe0, 0xc5, 0xee, 0x49, 0xab, 0x15, 0xf3, 0x7f, 0xc2,
+ 0x1b, 0xfd, 0xbb, 0xeb, 0x21, 0x09, 0x58, 0xba, 0x42, 0x58, 0xbe, 0x2f,
+ 0x14, 0xac, 0x5f, 0xec, 0x19, 0x30, 0x27, 0xb2, 0xc5, 0x31, 0xea, 0x80,
+ 0x86, 0xff, 0xb3, 0x6e, 0x3e, 0x1e, 0x77, 0x58, 0xac, 0x4c, 0x77, 0xa2,
+ 0x17, 0x34, 0x66, 0xde, 0x10, 0xdf, 0x88, 0xc1, 0x07, 0xba, 0xc5, 0xff,
+ 0x37, 0xbe, 0x2d, 0xff, 0x91, 0x2c, 0x54, 0x9f, 0x44, 0x45, 0x97, 0x76,
+ 0x82, 0xc5, 0x44, 0x6f, 0x0e, 0x45, 0x7e, 0x9d, 0x18, 0x0f, 0x2c, 0x5f,
+ 0xc0, 0x8d, 0x0c, 0x33, 0xf1, 0xcb, 0x16, 0x0d, 0x62, 0xf0, 0x33, 0xeb,
+ 0x17, 0xff, 0x48, 0x0e, 0xd0, 0xe7, 0xb3, 0x0e, 0xb1, 0x7f, 0xc5, 0x9b,
+ 0x7d, 0x8b, 0x0e, 0xb1, 0x43, 0x45, 0x67, 0x42, 0x7f, 0x1d, 0x24, 0x4b,
+ 0x8f, 0x12, 0xc5, 0xa3, 0x96, 0x2a, 0x23, 0x5d, 0xc1, 0x9b, 0x46, 0x46,
+ 0xce, 0x98, 0x83, 0xbe, 0xd2, 0x3b, 0xea, 0x6b, 0x32, 0x83, 0xf6, 0x7a,
+ 0x81, 0x70, 0xe3, 0x02, 0xc9, 0xc4, 0xad, 0xe3, 0x0b, 0xea, 0x1b, 0xaf,
+ 0x29, 0xf6, 0x26, 0xcd, 0x1d, 0x1e, 0x30, 0x9f, 0xca, 0xde, 0x6a, 0x4f,
+ 0x10, 0x21, 0x58, 0x52, 0xd9, 0x79, 0x28, 0x27, 0xd2, 0x81, 0x85, 0x0e,
+ 0xd0, 0x88, 0xa3, 0x8a, 0x83, 0x87, 0x37, 0x73, 0x5d, 0xfe, 0x13, 0x6a,
+ 0x1f, 0x09, 0x96, 0x2f, 0xdf, 0x1b, 0xfb, 0x16, 0x2f, 0xff, 0xff, 0xe9,
+ 0xf1, 0x30, 0x09, 0xbb, 0x3f, 0x62, 0x17, 0x03, 0x29, 0x1f, 0xda, 0x19,
+ 0xc5, 0x8b, 0xdb, 0xf2, 0x0b, 0x17, 0xfe, 0x0c, 0xa4, 0x7f, 0x68, 0x67,
+ 0x16, 0x2f, 0xf8, 0xa4, 0x7f, 0x68, 0x67, 0x16, 0x2f, 0xf3, 0x76, 0x7e,
+ 0xc4, 0x2e, 0x18, 0x7e, 0xe1, 0x9f, 0xde, 0xce, 0xa3, 0x06, 0x9e, 0x63,
+ 0x9a, 0xe8, 0xa1, 0xa1, 0x14, 0x50, 0x96, 0xbf, 0xfa, 0x33, 0xed, 0xc2,
+ 0xcf, 0x7a, 0x40, 0xb1, 0x7f, 0xfa, 0x30, 0xed, 0x08, 0xcc, 0xd6, 0xec,
+ 0xdb, 0xaa, 0x47, 0xc2, 0xff, 0xf4, 0x23, 0x33, 0xb3, 0x9b, 0xce, 0x49,
+ 0xc4, 0xb1, 0x7f, 0xd8, 0x16, 0x76, 0x7f, 0x42, 0x56, 0x2f, 0xf9, 0x88,
+ 0x7f, 0x93, 0xf7, 0x09, 0x62, 0xf6, 0xa7, 0x8b, 0x14, 0xe7, 0xb2, 0x23,
+ 0xcb, 0xff, 0x75, 0xe8, 0xa0, 0xda, 0xdb, 0xe2, 0x58, 0xbf, 0x84, 0x5e,
+ 0x21, 0x6c, 0xb1, 0x7c, 0x7c, 0xcd, 0xd6, 0x2f, 0xe8, 0x4f, 0xb9, 0x9d,
+ 0x96, 0x2f, 0x76, 0x1c, 0xac, 0x5f, 0xc4, 0x4e, 0x7f, 0x62, 0xc5, 0xe8,
+ 0x73, 0x16, 0x2f, 0x47, 0x46, 0xc1, 0x2c, 0x56, 0x22, 0x3d, 0x87, 0xc3,
+ 0x2c, 0xee, 0x1d, 0xbf, 0x1a, 0xde, 0xc0, 0x96, 0x2f, 0xed, 0x83, 0x8e,
+ 0x62, 0x02, 0xc5, 0xff, 0x3c, 0x1f, 0xe2, 0x39, 0xdd, 0x62, 0xff, 0xb2,
+ 0x28, 0x36, 0xb6, 0xf8, 0x96, 0x2e, 0x98, 0x96, 0x2f, 0x31, 0x00, 0x8f,
+ 0x53, 0xc7, 0x95, 0x28, 0xf1, 0xf1, 0x9c, 0x74, 0x23, 0x6d, 0x19, 0xb2,
+ 0xb9, 0xb1, 0xc2, 0x53, 0x08, 0x4e, 0x88, 0xc5, 0xe0, 0x23, 0x28, 0x5f,
+ 0x88, 0xfc, 0x38, 0xc6, 0xe9, 0x97, 0x21, 0x3d, 0x2f, 0xb2, 0xb7, 0x76,
+ 0x65, 0x4f, 0x2d, 0xf2, 0x3e, 0xd3, 0x26, 0x6a, 0x5d, 0x29, 0xd9, 0xfe,
+ 0x8e, 0xd3, 0x9c, 0x77, 0xff, 0xa3, 0x51, 0xa1, 0x47, 0xec, 0x38, 0xd8,
+ 0xc3, 0x3f, 0x1c, 0xb1, 0x7f, 0x37, 0xb8, 0x5c, 0xf2, 0xc5, 0xf9, 0x85,
+ 0xdf, 0x9d, 0x96, 0x28, 0x8f, 0x6f, 0xc5, 0xd7, 0xe2, 0xcd, 0x8f, 0xe5,
+ 0x8b, 0xff, 0xf8, 0x44, 0xc6, 0x99, 0xe3, 0x64, 0xa1, 0x9f, 0x73, 0xac,
+ 0x5c, 0xfd, 0x2c, 0x5f, 0xff, 0x43, 0x68, 0xd5, 0x31, 0xa6, 0xdb, 0xe8,
+ 0xc3, 0x3f, 0x1c, 0xb1, 0x50, 0x3f, 0xe0, 0x0c, 0x5c, 0x1f, 0x16, 0x2f,
+ 0xfe, 0xdb, 0xf2, 0xfe, 0xe3, 0x97, 0x50, 0x58, 0xb8, 0x5b, 0xac, 0x57,
+ 0xcf, 0xe0, 0x86, 0x78, 0x8d, 0x7f, 0xf6, 0x79, 0xf0, 0xbf, 0x9e, 0x91,
+ 0xac, 0x5f, 0xfb, 0xc6, 0xc9, 0x43, 0x3e, 0xe7, 0x58, 0xbf, 0xe3, 0x64,
+ 0xa1, 0x9f, 0x73, 0xac, 0x5f, 0x08, 0x98, 0xd3, 0x0f, 0xe3, 0xc7, 0xf7,
+ 0xed, 0x01, 0xff, 0x2b, 0x14, 0x73, 0xe2, 0x11, 0xd5, 0xfb, 0x35, 0x99,
+ 0x12, 0xc5, 0xa3, 0x20, 0xb8, 0x25, 0x90, 0xbf, 0xdc, 0x84, 0xe5, 0x3f,
+ 0x86, 0xdb, 0x42, 0x68, 0x8b, 0xb9, 0x18, 0xe0, 0x64, 0x57, 0xed, 0x6e,
+ 0xcd, 0xba, 0xa4, 0xb2, 0x2f, 0xfc, 0xd0, 0x8c, 0xcd, 0x6e, 0xcd, 0xba,
+ 0xa4, 0x6e, 0x2d, 0x19, 0x88, 0x87, 0x39, 0xbd, 0x6e, 0x9a, 0x83, 0xc6,
+ 0x4b, 0x7f, 0xfc, 0xdb, 0xc6, 0x6d, 0x81, 0x72, 0x7d, 0xfc, 0x25, 0x8b,
+ 0xfe, 0x26, 0x8c, 0xe4, 0x82, 0x65, 0x62, 0xf7, 0x79, 0xd6, 0xeb, 0x17,
+ 0xff, 0xb8, 0xd0, 0x73, 0x5e, 0x18, 0x0e, 0x62, 0xc5, 0xff, 0x98, 0xbd,
+ 0x0c, 0xd6, 0x77, 0x91, 0xba, 0xc5, 0xff, 0xfe, 0xcf, 0x73, 0x39, 0x84,
+ 0xf3, 0xc6, 0xfe, 0x0b, 0x65, 0x8b, 0x3f, 0xd1, 0x4f, 0xe4, 0x8a, 0xd9,
+ 0x31, 0x98, 0x43, 0xc6, 0xff, 0xc3, 0x72, 0x16, 0xf9, 0xce, 0xf2, 0x37,
+ 0x58, 0xbf, 0xfd, 0xe7, 0xf8, 0xbe, 0xcf, 0xd7, 0x24, 0xd5, 0x8a, 0x94,
+ 0x4b, 0x62, 0x55, 0xf6, 0xec, 0xdb, 0xaa, 0x45, 0x62, 0xff, 0xfb, 0x5b,
+ 0x14, 0xe9, 0x86, 0x4d, 0xa9, 0xec, 0xb1, 0x5a, 0x44, 0x10, 0x8c, 0x6f,
+ 0xf9, 0x9e, 0x0e, 0x42, 0x93, 0xac, 0x5f, 0x48, 0xdb, 0xeb, 0x16, 0x75,
+ 0x8a, 0x58, 0xbf, 0xcf, 0x07, 0x21, 0x49, 0xd6, 0x2f, 0xc4, 0xcf, 0xd6,
+ 0xe7, 0x37, 0xcc, 0x19, 0x44, 0x8a, 0xee, 0xc4, 0x5d, 0xc9, 0xf7, 0xec,
+ 0xd0, 0x73, 0x1e, 0xb1, 0x7f, 0x39, 0x4c, 0x27, 0xb9, 0x62, 0xf3, 0xcf,
+ 0x96, 0x2f, 0x11, 0xf6, 0x58, 0xa9, 0x3e, 0x9d, 0x17, 0xb0, 0xe5, 0xf0,
+ 0x87, 0x86, 0xac, 0x5e, 0x68, 0x46, 0x77, 0xc5, 0xcc, 0x39, 0x8c, 0xf8,
+ 0x70, 0xc0, 0xc8, 0x51, 0xee, 0x46, 0xf0, 0xe5, 0xf9, 0xa7, 0x21, 0x2b,
+ 0x1c, 0x5b, 0x5b, 0x2f, 0x04, 0x6e, 0xaa, 0x79, 0xcf, 0xdb, 0xf4, 0x63,
+ 0x45, 0xcc, 0x58, 0xbf, 0x46, 0x64, 0x24, 0x0b, 0x17, 0xf3, 0x72, 0x30,
+ 0xb9, 0x2b, 0x15, 0x18, 0x8c, 0x4d, 0x8f, 0x60, 0x59, 0xa2, 0xbb, 0x79,
+ 0x62, 0xff, 0xfd, 0xa9, 0xec, 0x53, 0x06, 0xdd, 0xc8, 0x6c, 0x4b, 0x17,
+ 0xcf, 0x85, 0xe5, 0x8a, 0xe8, 0xfd, 0xbe, 0xab, 0x7c, 0xda, 0xda, 0x31,
+ 0xd1, 0x56, 0xd0, 0x88, 0xbf, 0xf7, 0xb2, 0x33, 0x34, 0xfb, 0x31, 0xd6,
+ 0x2f, 0xf0, 0x7e, 0x7d, 0x48, 0xbb, 0xf5, 0x8b, 0xfb, 0xbd, 0x63, 0xea,
+ 0x78, 0xb1, 0x7f, 0xfb, 0xbc, 0x8d, 0xfb, 0xde, 0x63, 0x41, 0xf3, 0x58,
+ 0xb1, 0x7f, 0xdc, 0x11, 0xc9, 0xfb, 0x09, 0x96, 0x2f, 0xff, 0xd3, 0xa9,
+ 0x61, 0xe7, 0x84, 0x79, 0xd4, 0x9d, 0x62, 0x9d, 0x11, 0xfc, 0x3b, 0xbf,
+ 0xe6, 0x3c, 0xfe, 0x60, 0xc6, 0xac, 0x5f, 0xff, 0x7e, 0x60, 0xe0, 0xd6,
+ 0x7d, 0x89, 0xa0, 0xb1, 0x7f, 0xfc, 0xda, 0x6f, 0xc3, 0x3d, 0xc6, 0xd8,
+ 0x50, 0x58, 0xbf, 0x9e, 0x0e, 0x3c, 0x3a, 0xc5, 0xff, 0xf7, 0x5f, 0xcd,
+ 0xff, 0x93, 0xa6, 0x87, 0x31, 0x62, 0xff, 0x7a, 0x4f, 0x23, 0x6f, 0x2c,
+ 0x54, 0xa2, 0x13, 0x14, 0x6f, 0xfe, 0xc1, 0xb1, 0x48, 0xda, 0x73, 0x4b,
+ 0x15, 0xba, 0x6c, 0x9f, 0x51, 0x28, 0x58, 0xf0, 0x86, 0xf8, 0x1c, 0x11,
+ 0xd6, 0x2f, 0xe9, 0x26, 0xdd, 0xa3, 0xd6, 0x2f, 0x85, 0xdc, 0x39, 0x58,
+ 0xbf, 0xff, 0xcd, 0xd7, 0xf3, 0x93, 0xce, 0x37, 0xe7, 0xaf, 0xb9, 0xd6,
+ 0x2f, 0xf8, 0xb0, 0x0d, 0xbe, 0xa7, 0x75, 0x8b, 0xfd, 0xbc, 0xe9, 0xfd,
+ 0x3b, 0xac, 0x5f, 0xe1, 0x42, 0x4e, 0x4d, 0xf5, 0x8a, 0x93, 0xe8, 0xd1,
+ 0xad, 0x41, 0x5f, 0x78, 0xc8, 0xba, 0x39, 0x78, 0xec, 0xb4, 0x86, 0x72,
+ 0x4f, 0x98, 0x11, 0x37, 0x18, 0xbd, 0x0a, 0x2b, 0xfe, 0xc0, 0xa7, 0xef,
+ 0x85, 0xe5, 0x8b, 0x69, 0x62, 0xff, 0xc0, 0xf6, 0x7e, 0x4b, 0xd1, 0xd8,
+ 0xb1, 0x43, 0x3d, 0x31, 0x09, 0x5f, 0x81, 0x87, 0x9d, 0xd6, 0x2f, 0xf8,
+ 0x7c, 0x6d, 0xdc, 0x6d, 0x05, 0x8b, 0xf8, 0x4d, 0xd4, 0x73, 0x1a, 0xb1,
+ 0x52, 0x89, 0x61, 0x94, 0xfc, 0xea, 0xff, 0xfa, 0x4d, 0x92, 0x90, 0x73,
+ 0x39, 0x24, 0x6a, 0xc5, 0xff, 0xf7, 0xd8, 0x1c, 0xc2, 0x68, 0x38, 0xf0,
+ 0xeb, 0x17, 0xfc, 0xfe, 0xe4, 0x9f, 0x42, 0xd9, 0x62, 0xe3, 0x92, 0xc5,
+ 0xfc, 0x59, 0xbf, 0xdf, 0x4b, 0x03, 0x2d, 0xef, 0xb7, 0x66, 0xdd, 0x52,
+ 0x2e, 0x17, 0xf9, 0x87, 0x3f, 0x73, 0x65, 0x62, 0xfa, 0x18, 0x28, 0x2c,
+ 0x5f, 0xe3, 0xbf, 0xdb, 0xef, 0xc5, 0x8a, 0x93, 0xd6, 0x62, 0x3b, 0xe7,
+ 0xd7, 0xd8, 0x91, 0x53, 0xc8, 0x44, 0xdf, 0x9a, 0x1b, 0xbf, 0x72, 0xc5,
+ 0xed, 0x30, 0xd6, 0x2f, 0xbd, 0xc9, 0x02, 0xc5, 0xff, 0x7f, 0x07, 0x3f,
+ 0x98, 0x14, 0x9e, 0x03, 0x0e, 0xd4, 0x15, 0x7d, 0x8d, 0x3c, 0xd4, 0xe7,
+ 0x52, 0xd1, 0xef, 0xe1, 0xb4, 0x47, 0xbc, 0x6c, 0xbf, 0xff, 0xf3, 0x0c,
+ 0x19, 0x9d, 0x73, 0xae, 0x3e, 0xb7, 0xfe, 0x0f, 0x4c, 0xb1, 0x79, 0x9b,
+ 0x75, 0x8b, 0xc4, 0xc7, 0x58, 0xb6, 0xcb, 0x17, 0x67, 0x86, 0x79, 0x8c,
+ 0x3b, 0xdc, 0x39, 0x7b, 0x58, 0x12, 0xc5, 0x40, 0xf6, 0xb8, 0x79, 0x70,
+ 0x80, 0xb1, 0x7f, 0x9f, 0x4d, 0xdd, 0xdd, 0x24, 0xb1, 0x7d, 0xdc, 0x4d,
+ 0xb2, 0xc5, 0xfa, 0x4f, 0x25, 0xba, 0xc5, 0x69, 0x13, 0xdf, 0x18, 0x63,
+ 0x8f, 0x13, 0x5f, 0xff, 0xf4, 0xed, 0x9b, 0x8d, 0xcb, 0xf2, 0xfc, 0xc1,
+ 0xb7, 0x44, 0xb1, 0x7f, 0xff, 0x49, 0x66, 0xf2, 0x02, 0x9d, 0x0a, 0x1a,
+ 0x98, 0x2c, 0x54, 0x11, 0x81, 0xf6, 0x6b, 0xff, 0xc7, 0x7f, 0xcb, 0x3f,
+ 0xdc, 0xec, 0x35, 0x8b, 0xff, 0xff, 0xc3, 0xfe, 0x7f, 0x18, 0xb7, 0x9d,
+ 0xf5, 0x9b, 0x13, 0x7b, 0x92, 0x05, 0x8b, 0xff, 0xff, 0xfd, 0xf9, 0x07,
+ 0x39, 0x9a, 0x29, 0xea, 0x1b, 0xfd, 0xe2, 0x2c, 0x7d, 0x4f, 0x69, 0x82,
+ 0xc5, 0x4a, 0x61, 0x2e, 0xf1, 0x74, 0x1d, 0x62, 0xa5, 0x38, 0xac, 0x8d,
+ 0x44, 0xd2, 0x2b, 0xff, 0xfd, 0xf7, 0xd8, 0xed, 0x0c, 0x17, 0x7f, 0xc6,
+ 0xfe, 0xef, 0xc5, 0x8b, 0xff, 0xfe, 0xde, 0x45, 0xbf, 0xdf, 0x58, 0x3e,
+ 0x49, 0x0b, 0x77, 0x35, 0x62, 0xa5, 0x1a, 0x58, 0xd1, 0x7c, 0x06, 0x8e,
+ 0x35, 0x62, 0xfe, 0x03, 0x00, 0x45, 0xba, 0xc5, 0xff, 0x6c, 0xc3, 0x98,
+ 0x16, 0x1d, 0x62, 0xf4, 0x9f, 0x8b, 0x17, 0x9a, 0x1e, 0x73, 0xd6, 0x23,
+ 0x9b, 0xff, 0x70, 0x46, 0xf3, 0x0e, 0xff, 0x95, 0x8b, 0xda, 0x9f, 0xac,
+ 0x5f, 0xe9, 0x3c, 0xc6, 0x04, 0x10, 0x4b, 0x14, 0xe8, 0x97, 0xd2, 0x07,
+ 0x70, 0xed, 0x62, 0x74, 0xdb, 0x93, 0xbc, 0x21, 0x5a, 0x19, 0x17, 0xf6,
+ 0xe2, 0x8f, 0xfb, 0x41, 0x62, 0xff, 0xff, 0xf6, 0x43, 0xed, 0x09, 0x1c,
+ 0x93, 0x75, 0xfc, 0xe4, 0xf3, 0x8d, 0xf5, 0x8a, 0x94, 0x54, 0xb9, 0x9d,
+ 0xff, 0x61, 0xb2, 0xdb, 0xea, 0x77, 0x58, 0xa8, 0x1e, 0xe6, 0xe4, 0x37,
+ 0xf9, 0xc6, 0xdd, 0xdd, 0xa6, 0x0b, 0x17, 0xd1, 0xcf, 0xf6, 0x58, 0xa9,
+ 0x3d, 0xd8, 0x1c, 0x5f, 0xe6, 0x2d, 0x49, 0x34, 0x16, 0x2d, 0x2b, 0x15,
+ 0xc3, 0xc2, 0x8e, 0x31, 0xbf, 0xf8, 0xa0, 0xc3, 0x69, 0x84, 0x93, 0x2c,
+ 0x54, 0x9f, 0x36, 0x12, 0xdc, 0xda, 0x58, 0xbf, 0xff, 0x8b, 0x3b, 0x3f,
+ 0xe4, 0xf9, 0xbc, 0xf3, 0xf8, 0x75, 0x8b, 0x8a, 0x77, 0x3f, 0x3e, 0x0b,
+ 0xdf, 0xff, 0xd8, 0x2d, 0xff, 0x25, 0x30, 0x61, 0xcf, 0x5a, 0x75, 0x8b,
+ 0xff, 0x71, 0xc8, 0x5e, 0x8e, 0x7e, 0xc7, 0x58, 0xbf, 0xff, 0xf9, 0xcb,
+ 0x0f, 0x3a, 0xc7, 0xfc, 0x83, 0x85, 0x91, 0x41, 0xa0, 0xb1, 0x7f, 0xed,
+ 0x4f, 0x9d, 0xa1, 0x25, 0xb2, 0xc5, 0xa6, 0x08, 0xad, 0x76, 0xfb, 0xff,
+ 0xb3, 0xd9, 0xf2, 0x68, 0x09, 0xb8, 0xb1, 0x7f, 0xff, 0xfb, 0x3d, 0xcc,
+ 0x1b, 0x0e, 0x49, 0xba, 0xfe, 0x72, 0x79, 0xc6, 0xfa, 0xc5, 0x3a, 0x2e,
+ 0x49, 0x0e, 0xff, 0xfa, 0x02, 0x98, 0x30, 0xc9, 0xbd, 0xc9, 0x02, 0xc5,
+ 0xfd, 0x33, 0xc9, 0xeb, 0x4b, 0x15, 0x27, 0xfa, 0x04, 0xfb, 0xff, 0xc5,
+ 0x3b, 0x61, 0x7b, 0xed, 0x0f, 0xe2, 0xc5, 0xff, 0xfe, 0xcd, 0x8e, 0x2e,
+ 0x9b, 0xdf, 0x9e, 0x60, 0xda, 0x60, 0xb1, 0x7f, 0xf0, 0xd8, 0x80, 0x4d,
+ 0xd6, 0xb0, 0xeb, 0x15, 0x28, 0xef, 0x24, 0x91, 0x31, 0x5e, 0x72, 0x95,
+ 0x8b, 0xfe, 0x11, 0xac, 0x6e, 0x6d, 0x9b, 0x2c, 0x54, 0xaf, 0x34, 0xc2,
+ 0x10, 0x03, 0x86, 0x4b, 0xc2, 0x4e, 0x3c, 0xb4, 0xeb, 0x7f, 0x87, 0x89,
+ 0x43, 0x83, 0x90, 0x9e, 0xf4, 0x62, 0x1d, 0x8b, 0xa3, 0x86, 0xef, 0xff,
+ 0x16, 0x3c, 0x19, 0xf7, 0xcd, 0x34, 0x16, 0x2f, 0xfb, 0x0e, 0xe4, 0x07,
+ 0xf8, 0x96, 0x2f, 0xd0, 0xe7, 0xdc, 0x0b, 0x17, 0xf4, 0x8f, 0x09, 0xe5,
+ 0x62, 0xff, 0x3f, 0x5c, 0x88, 0x98, 0x35, 0x8b, 0xff, 0xfc, 0xfd, 0x04,
+ 0x3f, 0xce, 0xba, 0xdd, 0xfa, 0xf7, 0x30, 0x25, 0x8a, 0xd2, 0x32, 0x48,
+ 0xaf, 0xc6, 0xd7, 0xfe, 0xce, 0x70, 0x45, 0x14, 0x26, 0x3d, 0x62, 0xff,
+ 0xbd, 0xbf, 0xdf, 0x43, 0xcd, 0x96, 0x2f, 0x3c, 0xc1, 0x62, 0x98, 0xf6,
+ 0x08, 0xf2, 0xe6, 0x35, 0x62, 0xf8, 0x8b, 0x3d, 0x89, 0x81, 0x68, 0xbf,
+ 0xf0, 0x9b, 0x8e, 0x20, 0xbf, 0xb3, 0x3a, 0x1e, 0x12, 0xc5, 0xfe, 0x92,
+ 0x93, 0xbe, 0x04, 0xb1, 0x7e, 0xfb, 0xe9, 0xb8, 0xb1, 0x7f, 0x0e, 0x5f,
+ 0xf2, 0x75, 0x8b, 0xf0, 0xe6, 0x3d, 0xb4, 0xb1, 0x7a, 0x48, 0x18, 0x7b,
+ 0x0c, 0x5b, 0x5d, 0x2b, 0x5d, 0x78, 0xfd, 0x34, 0xb5, 0xf2, 0xdf, 0x19,
+ 0x77, 0x42, 0x02, 0xb6, 0x57, 0xf9, 0x92, 0xe5, 0x6f, 0xf4, 0x96, 0xec,
+ 0xfb, 0x62, 0xc5, 0xdb, 0xca, 0xc5, 0x1a, 0x79, 0x64, 0x67, 0x7f, 0x76,
+ 0x92, 0xdd, 0xb8, 0xb1, 0x7f, 0xf1, 0x4c, 0x30, 0x79, 0x0c, 0x20, 0x2c,
+ 0x5f, 0x98, 0x1c, 0xc2, 0x58, 0xa9, 0x44, 0xcb, 0x98, 0x71, 0x0a, 0xff,
+ 0xff, 0x3f, 0xa4, 0x98, 0xf8, 0x76, 0x87, 0x27, 0xd2, 0x35, 0x8a, 0x74,
+ 0xd1, 0xfd, 0x0b, 0xbe, 0xc5, 0xd7, 0xff, 0xbf, 0x3a, 0x27, 0x2c, 0xf7,
+ 0xb3, 0x8b, 0x17, 0xc0, 0x03, 0xf4, 0xb1, 0x7f, 0x85, 0xbb, 0x0f, 0x42,
+ 0xd9, 0x62, 0xfe, 0x35, 0xfd, 0xc9, 0x3a, 0xc5, 0xff, 0xf6, 0x3f, 0xe4,
+ 0x1c, 0x2c, 0x8a, 0x0d, 0x05, 0x8b, 0xed, 0xf5, 0x3b, 0xac, 0x5e, 0xdf,
+ 0xef, 0x88, 0xda, 0x34, 0xdf, 0x45, 0xec, 0x9f, 0x7e, 0x11, 0xa5, 0x80,
+ 0x58, 0xbf, 0xff, 0x9f, 0xa8, 0x4f, 0xb8, 0xe5, 0x0c, 0x1b, 0x4c, 0x16,
+ 0x2f, 0xf9, 0xb4, 0x69, 0x67, 0xbe, 0xeb, 0x17, 0xfe, 0xd4, 0x9f, 0xed,
+ 0xd4, 0x1f, 0x65, 0x8b, 0xff, 0xff, 0x84, 0x5b, 0x4b, 0x7e, 0x4f, 0x85,
+ 0x27, 0x26, 0xf7, 0x24, 0x0b, 0x14, 0x35, 0x60, 0x0e, 0x91, 0xa8, 0x7f,
+ 0x1d, 0x3b, 0xe5, 0x24, 0xb5, 0xe3, 0x9e, 0xe4, 0x1b, 0xfd, 0xf7, 0xeb,
+ 0xdb, 0x60, 0x4b, 0x17, 0xfe, 0xcf, 0x37, 0x59, 0x0f, 0xce, 0x96, 0x2f,
+ 0xf3, 0x9a, 0xff, 0xdd, 0xf8, 0xb1, 0x7f, 0x33, 0xc1, 0xcd, 0x95, 0x8b,
+ 0x4c, 0x0f, 0x8b, 0xe6, 0xb7, 0xff, 0xff, 0xf1, 0x01, 0x88, 0x1c, 0xc3,
+ 0xb7, 0xf0, 0x6c, 0xe5, 0x3f, 0x67, 0x83, 0x8d, 0x62, 0xff, 0xff, 0xcd,
+ 0xb1, 0xdf, 0x98, 0x36, 0x72, 0x9f, 0xb3, 0xc1, 0xc6, 0xb1, 0x7f, 0x3f,
+ 0xdb, 0xef, 0xc5, 0x8b, 0xdd, 0x42, 0x56, 0x2e, 0x80, 0x16, 0x2f, 0xe2,
+ 0x14, 0x3e, 0xd0, 0xc3, 0x6c, 0xe3, 0xd7, 0xff, 0x0a, 0x04, 0xf0, 0x9f,
+ 0x10, 0xa0, 0xb1, 0x7e, 0x9e, 0x00, 0xfe, 0x58, 0xa7, 0x3e, 0xdf, 0xa2,
+ 0x50, 0xd5, 0x22, 0xb9, 0x3e, 0xa1, 0x06, 0x76, 0x9e, 0x31, 0xfa, 0x15,
+ 0xd6, 0xdd, 0x62, 0xee, 0x74, 0xb1, 0x7f, 0x68, 0x03, 0xc0, 0x71, 0x62,
+ 0xa5, 0x7e, 0x2b, 0x25, 0x9b, 0xee, 0xf2, 0xe6, 0xed, 0x2b, 0x98, 0x0c,
+ 0x5e, 0x13, 0x10, 0xcd, 0xfb, 0xf8, 0x59, 0xba, 0xc5, 0xc5, 0xe5, 0x8a,
+ 0x81, 0xbf, 0x62, 0x8b, 0xd0, 0xff, 0x96, 0x29, 0xcd, 0xf7, 0xc8, 0x2f,
+ 0xba, 0xfc, 0xee, 0xb1, 0x6f, 0xc9, 0xe2, 0xb1, 0x05, 0xff, 0xc4, 0xe0,
+ 0xe6, 0xa5, 0xe0, 0xdc, 0x58, 0xbf, 0xfc, 0x13, 0x6a, 0x5c, 0xf8, 0x39,
+ 0x84, 0xac, 0x5f, 0x01, 0x9b, 0x4b, 0x16, 0x68, 0x1f, 0x5f, 0x49, 0x35,
+ 0x88, 0xfc, 0x72, 0x6e, 0x42, 0xba, 0xf8, 0xe4, 0xc3, 0x58, 0xbc, 0xfb,
+ 0x77, 0xeb, 0x17, 0xe7, 0x39, 0x34, 0x16, 0x2f, 0x3f, 0x5c, 0x58, 0xb9,
+ 0xbc, 0xb1, 0x73, 0xce, 0xc6, 0xd7, 0x83, 0xd7, 0xff, 0x7b, 0xf9, 0xdb,
+ 0xee, 0x7c, 0x17, 0x7e, 0xb1, 0x4e, 0x98, 0xcc, 0x79, 0x16, 0x88, 0xfe,
+ 0xb8, 0xc5, 0x97, 0xee, 0x7b, 0xf2, 0x12, 0xc5, 0xfc, 0x6e, 0xb3, 0xcd,
+ 0xd2, 0xc5, 0x9b, 0xa3, 0xda, 0xd1, 0x55, 0xff, 0xc2, 0x68, 0xf7, 0xdb,
+ 0x3e, 0xfd, 0x71, 0x62, 0xff, 0x4c, 0x4d, 0xef, 0xb0, 0x16, 0x2f, 0xfd,
+ 0xd4, 0x33, 0xd9, 0xad, 0xe7, 0x16, 0x2d, 0x19, 0xde, 0x3a, 0xd3, 0x08,
+ 0xd0, 0xeb, 0xbe, 0x19, 0xcc, 0xe6, 0xb6, 0xd0, 0x97, 0x84, 0x22, 0xc7,
+ 0x0b, 0x8c, 0x96, 0x55, 0xbb, 0xbf, 0x51, 0x8a, 0xbc, 0x30, 0x22, 0x87,
+ 0xe6, 0xa3, 0xad, 0x3c, 0x61, 0x1f, 0x8f, 0x1d, 0xa7, 0xed, 0x01, 0x0d,
+ 0x12, 0x9c, 0x44, 0xe5, 0x25, 0x23, 0xd2, 0x8f, 0x45, 0x1a, 0x60, 0x50,
+ 0xa6, 0x8e, 0x28, 0x0d, 0x27, 0xb8, 0xd2, 0xff, 0xfa, 0x33, 0x4e, 0x79,
+ 0x8f, 0x8c, 0x67, 0xd0, 0xa3, 0xd6, 0x2c, 0xd0, 0x54, 0x81, 0xf8, 0xf9,
+ 0x2f, 0xfc, 0x23, 0xc6, 0x72, 0x4b, 0xd9, 0xa5, 0x8b, 0xbb, 0x3a, 0xc5,
+ 0xff, 0xd3, 0xc7, 0xed, 0xc9, 0x83, 0xf9, 0x96, 0x2f, 0xfd, 0x3e, 0x9e,
+ 0xd2, 0x5b, 0xb7, 0x16, 0x2f, 0x67, 0xe3, 0x1d, 0x13, 0xcc, 0x33, 0xc4,
+ 0x5b, 0xfe, 0x1e, 0x46, 0x4e, 0x9f, 0xe2, 0x58, 0xbf, 0xf4, 0xc6, 0x77,
+ 0x67, 0x50, 0xfc, 0xf1, 0x62, 0xff, 0xfe, 0xe4, 0x61, 0xf3, 0x79, 0x7e,
+ 0xcc, 0x42, 0xdf, 0x38, 0xb1, 0x43, 0x45, 0x39, 0x23, 0x5a, 0x33, 0x77,
+ 0x64, 0x94, 0xe8, 0x27, 0xb5, 0xf6, 0x5c, 0x30, 0xf4, 0x38, 0x04, 0x85,
+ 0xda, 0x1c, 0x77, 0xa4, 0x8d, 0x58, 0xbf, 0xe8, 0x46, 0x66, 0xb7, 0x66,
+ 0xdd, 0x52, 0x1d, 0x96, 0x8c, 0xf9, 0xf4, 0x30, 0xed, 0xff, 0xf0, 0xa7,
+ 0xa8, 0x39, 0xc2, 0xc2, 0x1f, 0xe5, 0x62, 0xff, 0xff, 0xe3, 0xce, 0xfb,
+ 0xfd, 0xe2, 0xfb, 0x90, 0xdb, 0x52, 0x69, 0xa2, 0xd9, 0x62, 0xe1, 0x06,
+ 0xb1, 0x7c, 0x4c, 0xdd, 0x2c, 0x5f, 0x75, 0xe7, 0x09, 0x62, 0xa4, 0xf1,
+ 0xce, 0x45, 0x76, 0xd1, 0x83, 0x4d, 0x2b, 0x14, 0x4e, 0xf0, 0x1b, 0x05,
+ 0xff, 0xfe, 0x60, 0x46, 0x07, 0x3b, 0x67, 0xa4, 0x9c, 0x19, 0xd7, 0x96,
+ 0x2f, 0xdc, 0x7e, 0xdf, 0xec, 0xb1, 0x71, 0x71, 0x62, 0xfb, 0xf9, 0x08,
+ 0xc9, 0x3c, 0x46, 0x2d, 0xac, 0x4c, 0xc6, 0x24, 0xef, 0x42, 0xa6, 0xc6,
+ 0xac, 0x5c, 0x60, 0xd6, 0x2a, 0x37, 0x35, 0x9d, 0xe8, 0x9d, 0xff, 0x77,
+ 0xb1, 0xd8, 0x6b, 0xf8, 0xa5, 0x62, 0xfe, 0x8d, 0x8a, 0x77, 0xc2, 0x58,
+ 0xb0, 0x96, 0x2f, 0xf6, 0x42, 0x4d, 0x6e, 0x3a, 0xc5, 0xbe, 0xb1, 0x51,
+ 0xb9, 0xeb, 0xc6, 0x82, 0x42, 0x33, 0xbf, 0xbb, 0xd2, 0xcf, 0xb7, 0x96,
+ 0x2f, 0xfd, 0xdf, 0x3b, 0xe7, 0xf3, 0x6c, 0xc2, 0x35, 0x62, 0xc1, 0x2c,
+ 0x5f, 0x6f, 0xf1, 0x47, 0xac, 0x5f, 0x61, 0xf0, 0x96, 0x2e, 0xcf, 0xac,
+ 0x50, 0xcd, 0xc7, 0x88, 0x69, 0x62, 0x9c, 0xd6, 0x91, 0x0d, 0xfe, 0xe6,
+ 0x16, 0x69, 0xbc, 0xb1, 0x79, 0xc8, 0x0b, 0x15, 0xc3, 0xce, 0xec, 0x65,
+ 0x77, 0xf1, 0x62, 0xfd, 0x84, 0xe0, 0x0d, 0x62, 0xa4, 0xdf, 0xf0, 0x5e,
+ 0xf6, 0x6a, 0x56, 0x2f, 0xfa, 0x4a, 0x38, 0x53, 0x06, 0xd2, 0xc5, 0xfe,
+ 0xfc, 0xed, 0xa9, 0xc1, 0xac, 0x5d, 0x9b, 0x2c, 0x5e, 0xee, 0x1c, 0xac,
+ 0x54, 0x9f, 0x61, 0x1a, 0x08, 0x62, 0xff, 0xda, 0x33, 0x3d, 0x9f, 0x9d,
+ 0x01, 0x62, 0xff, 0xff, 0xcc, 0xfb, 0xe1, 0x19, 0x0c, 0xe7, 0xb3, 0xf2,
+ 0x5e, 0xfb, 0xac, 0x59, 0xd6, 0x29, 0xd1, 0x79, 0xf4, 0x06, 0x6b, 0xbe,
+ 0x98, 0x4e, 0x96, 0x2f, 0xff, 0xd0, 0x71, 0xfd, 0xfb, 0x19, 0x83, 0xd3,
+ 0x8b, 0x75, 0x8b, 0xe9, 0xd4, 0xe9, 0x62, 0xa3, 0x65, 0xc0, 0x89, 0x13,
+ 0x84, 0x23, 0x71, 0xb5, 0xd8, 0xf4, 0x40, 0x71, 0xcf, 0xc2, 0x9c, 0xa1,
+ 0xd3, 0xc2, 0xef, 0x11, 0x06, 0xb5, 0x7a, 0x29, 0xd9, 0x62, 0xfa, 0x4b,
+ 0xdc, 0x58, 0xbb, 0x02, 0x93, 0xc1, 0xe0, 0xfd, 0xc5, 0xc5, 0x8b, 0xff,
+ 0x73, 0xd9, 0xf9, 0x2f, 0x7d, 0xd6, 0x2f, 0xf7, 0xb9, 0x31, 0x33, 0x69,
+ 0x62, 0xff, 0xa7, 0x3c, 0xed, 0xb4, 0xe9, 0x62, 0xc7, 0x58, 0xb1, 0xd6,
+ 0x2b, 0xbd, 0x34, 0x81, 0x89, 0x5f, 0xff, 0x87, 0x9a, 0x33, 0x0e, 0x29,
+ 0xd6, 0x9c, 0x5b, 0xac, 0x54, 0x13, 0x64, 0xc1, 0x77, 0x3e, 0x01, 0xa7,
+ 0x97, 0x04, 0x4f, 0x77, 0x79, 0xc5, 0x8b, 0xf8, 0x05, 0x9d, 0x7b, 0x16,
+ 0x2e, 0xda, 0x3d, 0x62, 0xfd, 0x9c, 0x6d, 0x1a, 0xb1, 0x7f, 0xf7, 0x69,
+ 0x1f, 0xb2, 0x5f, 0xd3, 0x12, 0xc5, 0xf1, 0xbf, 0xc0, 0x2c, 0x5f, 0xcc,
+ 0x16, 0x7a, 0x77, 0x58, 0xa6, 0x3d, 0x32, 0x24, 0xbf, 0xff, 0xf9, 0x8d,
+ 0x9d, 0x00, 0x53, 0x99, 0xfd, 0xde, 0x4a, 0x73, 0xe2, 0x58, 0xbf, 0x88,
+ 0x0d, 0xa6, 0x0d, 0x62, 0xff, 0xfa, 0x7d, 0x3e, 0x33, 0xdf, 0xc2, 0x6d,
+ 0x1a, 0xb1, 0x51, 0xa2, 0xa3, 0x89, 0x1d, 0xd8, 0xbb, 0x07, 0x1c, 0xa7,
+ 0x50, 0x99, 0xf9, 0x03, 0x38, 0x11, 0x75, 0xff, 0x81, 0xcc, 0xf6, 0x44,
+ 0x52, 0x75, 0x8b, 0xff, 0xc6, 0x16, 0x3e, 0x9f, 0x66, 0x39, 0xdd, 0x62,
+ 0xff, 0xfc, 0x59, 0xcf, 0xb3, 0xfa, 0x7d, 0xcd, 0xb0, 0x25, 0x8a, 0xfa,
+ 0x28, 0x3b, 0x25, 0x5f, 0xff, 0xfd, 0xf6, 0x19, 0x31, 0x9c, 0xfc, 0xf0,
+ 0xc1, 0x31, 0x90, 0xce, 0xd2, 0xb1, 0x7f, 0xc6, 0x99, 0x8e, 0x6e, 0xb3,
+ 0x8b, 0x15, 0xf4, 0x59, 0x13, 0xb5, 0xff, 0xe2, 0xc3, 0x7e, 0xd0, 0xf8,
+ 0x4c, 0x19, 0xd6, 0x2a, 0x4f, 0xbf, 0x08, 0xaa, 0x55, 0x22, 0xbc, 0x37,
+ 0xff, 0x1a, 0x35, 0xff, 0xbf, 0x9b, 0xe6, 0xbc, 0xcc, 0x6a, 0xc5, 0xff,
+ 0x9f, 0x46, 0x70, 0xb0, 0xf3, 0xba, 0xc5, 0xfe, 0x17, 0x9d, 0xbb, 0x34,
+ 0x16, 0x2f, 0xf1, 0x48, 0x0c, 0xfb, 0x1d, 0x62, 0xfe, 0x6e, 0xc3, 0xc2,
+ 0x35, 0x62, 0xd2, 0x48, 0x99, 0xf1, 0xa8, 0x66, 0x97, 0xff, 0xff, 0xfd,
+ 0xf9, 0xd6, 0xd8, 0x37, 0xf7, 0x27, 0x69, 0xd6, 0x0f, 0x1e, 0x4b, 0x3b,
+ 0x3e, 0x99, 0x62, 0xff, 0xff, 0xd2, 0x5b, 0xb7, 0x9b, 0xa0, 0x19, 0x84,
+ 0xf2, 0x2f, 0xfe, 0x56, 0x2a, 0x08, 0xff, 0x04, 0x24, 0xef, 0xd8, 0x3f,
+ 0xb1, 0xd6, 0x2f, 0xff, 0xc0, 0x6e, 0x36, 0x75, 0xec, 0x84, 0x83, 0x98,
+ 0xb1, 0x7f, 0xc2, 0x81, 0x98, 0xe5, 0x27, 0x58, 0xbf, 0xfe, 0x2c, 0xd9,
+ 0xf7, 0x33, 0x92, 0x76, 0xeb, 0xcb, 0x14, 0x34, 0xc2, 0x7a, 0x28, 0x25,
+ 0x5f, 0x1c, 0xdf, 0xdc, 0x83, 0xee, 0xda, 0x58, 0xbc, 0xcd, 0xba, 0xa4,
+ 0xa1, 0x2f, 0xe3, 0x79, 0xf9, 0x2f, 0x2c, 0x5f, 0xfe, 0xf7, 0xf0, 0x6f,
+ 0xcc, 0x20, 0x49, 0xd6, 0x2f, 0xff, 0x3f, 0x6c, 0x72, 0xcd, 0x4e, 0xf3,
+ 0xa5, 0x8b, 0x1d, 0x62, 0xde, 0x23, 0xdc, 0x12, 0x55, 0xb1, 0xd1, 0x98,
+ 0x28, 0x52, 0xdf, 0xe6, 0x04, 0xc5, 0xf1, 0x01, 0x62, 0xa5, 0x3b, 0x5d,
+ 0xcb, 0xdc, 0xab, 0x50, 0xfb, 0x11, 0x65, 0xfa, 0x28, 0x0b, 0xa8, 0x2c,
+ 0x5f, 0xff, 0xff, 0x8c, 0xc2, 0x76, 0xf4, 0xee, 0xfa, 0xd9, 0x8c, 0xcd,
+ 0x6b, 0x05, 0xe1, 0x1d, 0x62, 0xa5, 0x16, 0x20, 0x2c, 0xbf, 0x7d, 0xe4,
+ 0xbc, 0xb1, 0x7f, 0xb8, 0x67, 0x00, 0xd9, 0x12, 0xc5, 0x68, 0xf7, 0x40,
+ 0x4f, 0x7f, 0xfb, 0x1e, 0x02, 0xd6, 0x7f, 0xf3, 0x91, 0xeb, 0x17, 0xf7,
+ 0x73, 0x10, 0xc3, 0xe9, 0x62, 0x9d, 0x14, 0x3f, 0x22, 0x64, 0xcb, 0xfc,
+ 0x7e, 0x3e, 0x76, 0x6d, 0x2c, 0x5d, 0x83, 0x58, 0xbf, 0xff, 0x67, 0xf0,
+ 0xd3, 0x30, 0x66, 0x38, 0x80, 0x09, 0x58, 0xbe, 0x73, 0x5b, 0x75, 0x8b,
+ 0xff, 0xec, 0x39, 0x84, 0x2e, 0x19, 0xcc, 0xd3, 0x79, 0x62, 0xff, 0xe1,
+ 0x1b, 0xa7, 0x9f, 0x45, 0x06, 0x82, 0xc5, 0x6e, 0x8b, 0xde, 0x12, 0x79,
+ 0x4a, 0x99, 0x39, 0x22, 0x35, 0xf0, 0xb8, 0xa3, 0x15, 0xbe, 0xd6, 0xe2,
+ 0x02, 0xc5, 0xfd, 0x84, 0xda, 0xd3, 0xac, 0x53, 0x9e, 0x8f, 0xc9, 0x6f,
+ 0xd2, 0x42, 0x6d, 0x96, 0x2f, 0xf8, 0xa0, 0xe0, 0x3c, 0xf5, 0x05, 0x8b,
+ 0xff, 0xba, 0x2c, 0xf7, 0x5b, 0x8a, 0x75, 0xc5, 0x8a, 0xc4, 0x41, 0x31,
+ 0xd5, 0x62, 0x3b, 0x38, 0x42, 0x28, 0x55, 0x5f, 0x6c, 0x53, 0xb2, 0xc5,
+ 0xff, 0xda, 0x7f, 0x16, 0x1a, 0x63, 0xf6, 0x75, 0x8b, 0xff, 0x60, 0xb7,
+ 0xfb, 0x8b, 0x79, 0xd2, 0xc5, 0xff, 0xf3, 0xea, 0x60, 0x60, 0xdc, 0x8d,
+ 0xd3, 0x84, 0xb1, 0x52, 0x8f, 0xe7, 0x24, 0xf2, 0x3c, 0x72, 0x0d, 0xff,
+ 0xfd, 0xb8, 0xa6, 0x3c, 0xcc, 0x1f, 0xe4, 0xb7, 0x32, 0x74, 0xb1, 0x7f,
+ 0xf0, 0x46, 0x67, 0x67, 0xf4, 0xe1, 0x41, 0x62, 0xff, 0xd9, 0xf6, 0xf0,
+ 0xa7, 0xec, 0x75, 0x8a, 0x94, 0x42, 0x89, 0x1e, 0xfd, 0x9b, 0xb1, 0x1a,
+ 0xb1, 0x50, 0x66, 0xd6, 0x8c, 0xec, 0xd4, 0x0d, 0xe1, 0xb3, 0xd4, 0x66,
+ 0x8f, 0x19, 0x8e, 0xa3, 0xf3, 0x3c, 0x60, 0x1f, 0x8c, 0x80, 0xa3, 0xc0,
+ 0xe4, 0x6f, 0xfe, 0x8c, 0xc8, 0x47, 0xdd, 0xa1, 0xce, 0x19, 0x15, 0xff,
+ 0x9c, 0xc6, 0x7d, 0x64, 0x4c, 0x35, 0x8b, 0x9a, 0x56, 0x28, 0x67, 0xab,
+ 0x1e, 0x7f, 0x6c, 0x58, 0xbc, 0x63, 0x81, 0x62, 0xff, 0xf1, 0xe7, 0x73,
+ 0x37, 0xfb, 0xf7, 0x49, 0xe5, 0x62, 0xb0, 0xfb, 0x9c, 0x7a, 0xff, 0xe1,
+ 0x36, 0xdc, 0xc7, 0xdf, 0x7c, 0xec, 0xb1, 0x50, 0x47, 0x47, 0xdf, 0xc8,
+ 0x82, 0xf7, 0xbe, 0x75, 0x8b, 0xf8, 0x18, 0x66, 0x0f, 0x65, 0x8b, 0x78,
+ 0xc3, 0xce, 0x71, 0xeb, 0xf9, 0xf4, 0xdb, 0xb9, 0x2c, 0x56, 0x1e, 0xaf,
+ 0x8a, 0x2f, 0xff, 0xf4, 0xe8, 0xd3, 0x38, 0x42, 0xcf, 0x4c, 0x1c, 0x7f,
+ 0x75, 0x8a, 0x82, 0x20, 0xf8, 0x43, 0x7c, 0x76, 0x6d, 0xd6, 0x2f, 0x03,
+ 0x98, 0xb1, 0x7f, 0xb8, 0x28, 0x98, 0x6d, 0x12, 0xc5, 0xfb, 0xc0, 0x0c,
+ 0xa0, 0xb1, 0x7f, 0xfe, 0x09, 0xbb, 0xb8, 0xfa, 0x8b, 0x92, 0x76, 0xeb,
+ 0xcb, 0x14, 0xc8, 0x86, 0xe1, 0x55, 0xfd, 0x3b, 0xb9, 0x4c, 0x16, 0x2d,
+ 0x1c, 0xb1, 0x7f, 0x7b, 0x36, 0x3c, 0xee, 0xb1, 0x5b, 0x27, 0x21, 0x02,
+ 0x3e, 0x87, 0x62, 0x85, 0xe1, 0xc8, 0x80, 0x5b, 0xe1, 0x5b, 0xf1, 0x6c,
+ 0x09, 0x0d, 0x62, 0xfe, 0x84, 0x7c, 0xfa, 0x49, 0x62, 0xb0, 0xf6, 0xbb,
+ 0x8a, 0xaf, 0xd1, 0xe7, 0x97, 0xd2, 0xc5, 0xf6, 0x1c, 0x39, 0x58, 0xbd,
+ 0xdf, 0xc7, 0x3a, 0xc5, 0x11, 0xe4, 0x08, 0x8e, 0xa5, 0x12, 0x8e, 0xe7,
+ 0x74, 0xf1, 0x62, 0xa5, 0x1e, 0x10, 0x85, 0xc0, 0x08, 0x6f, 0xd0, 0x29,
+ 0x39, 0xab, 0x17, 0xff, 0x1f, 0x34, 0x58, 0xfd, 0x9f, 0x4c, 0xb1, 0x7f,
+ 0x3e, 0xee, 0x3d, 0xce, 0xb1, 0x5d, 0x22, 0x75, 0x8a, 0x7c, 0x89, 0x7f,
+ 0xfe, 0x7d, 0x19, 0x9e, 0x14, 0xe6, 0xdf, 0xc7, 0x82, 0xc5, 0xff, 0xf7,
+ 0x40, 0x92, 0xf6, 0x67, 0x5e, 0x9d, 0xe5, 0x62, 0xfa, 0x7c, 0x1c, 0x16,
+ 0x2f, 0xfc, 0x59, 0x17, 0xbf, 0x9a, 0x7e, 0x2c, 0x5f, 0xf8, 0xe6, 0x1d,
+ 0xbc, 0x67, 0xfd, 0xa5, 0x8b, 0xfd, 0x27, 0xc7, 0xd0, 0xa3, 0xd6, 0x29,
+ 0x8f, 0xe4, 0x48, 0x75, 0x29, 0xa7, 0x0d, 0x47, 0xe4, 0x85, 0x0b, 0x8b,
+ 0xf8, 0xe2, 0x6d, 0x9f, 0x65, 0x8b, 0xff, 0x85, 0x08, 0x49, 0x87, 0x71,
+ 0xe7, 0xd6, 0x2f, 0x89, 0xce, 0xeb, 0x15, 0x28, 0x97, 0xc3, 0x0e, 0x91,
+ 0xaf, 0x6d, 0x81, 0x2c, 0x5e, 0xcd, 0x7d, 0x62, 0xd3, 0x1b, 0x1b, 0xcd,
+ 0xc7, 0xef, 0xdc, 0xcd, 0xfe, 0xeb, 0x17, 0xd1, 0xc2, 0xee, 0x95, 0x8a,
+ 0x95, 0x72, 0xa3, 0x30, 0xc8, 0xe9, 0x1e, 0x1b, 0x1a, 0x6b, 0x62, 0xc1,
+ 0x14, 0xdf, 0xb3, 0x0d, 0x9d, 0x2c, 0x5f, 0x9b, 0xe6, 0x0e, 0x56, 0x2f,
+ 0xfb, 0x3e, 0xc7, 0xf0, 0x9b, 0xcb, 0x14, 0x74, 0x45, 0x78, 0xa2, 0x38,
+ 0xa6, 0xff, 0xbd, 0xc0, 0xf8, 0xdd, 0x43, 0x16, 0x2e, 0x17, 0xd6, 0x2f,
+ 0xe8, 0x38, 0x03, 0xf4, 0xac, 0x5f, 0xe6, 0x81, 0x9c, 0x10, 0x19, 0x62,
+ 0xfa, 0x7f, 0x3b, 0x2c, 0x59, 0xc6, 0x7b, 0x1f, 0x35, 0xa9, 0x4c, 0xd7,
+ 0x0c, 0xce, 0x78, 0xc3, 0x02, 0x84, 0x3d, 0xfb, 0x8f, 0xfc, 0x1a, 0xc5,
+ 0xfa, 0x13, 0xec, 0xd9, 0x62, 0xa3, 0xcf, 0x47, 0x45, 0x17, 0xa7, 0x9b,
+ 0x2c, 0x5f, 0xc4, 0xdd, 0x7a, 0x49, 0x62, 0xee, 0xbc, 0xb1, 0x77, 0xb1,
+ 0x62, 0xa4, 0xd8, 0x74, 0x33, 0x7f, 0x71, 0xcb, 0x7f, 0xca, 0xc5, 0x62,
+ 0x3b, 0xf7, 0x25, 0x71, 0xed, 0x2e, 0xf8, 0x86, 0xfd, 0x0e, 0x13, 0x01,
+ 0x62, 0xf4, 0x73, 0xfd, 0x62, 0xba, 0x3c, 0x87, 0x28, 0xbf, 0xef, 0x73,
+ 0x59, 0x17, 0xdc, 0xd5, 0x8b, 0xee, 0xe2, 0x68, 0x2c, 0x5c, 0x2d, 0x2c,
+ 0x57, 0xcd, 0xef, 0x09, 0x6b, 0x11, 0x35, 0xe7, 0x9b, 0x8b, 0xeb, 0x17,
+ 0xd0, 0x60, 0xe2, 0x58, 0xbf, 0xff, 0xdc, 0x71, 0x77, 0xff, 0x73, 0x33,
+ 0xaf, 0x7c, 0x3e, 0x6d, 0x2b, 0x17, 0xe8, 0x48, 0x39, 0x8b, 0x17, 0xfe,
+ 0xc3, 0x39, 0xe2, 0xc0, 0x47, 0x62, 0xc5, 0xec, 0xdc, 0xcc, 0x3e, 0xaf,
+ 0x94, 0x5b, 0xce, 0x98, 0x4f, 0x21, 0xab, 0x7f, 0xff, 0x3f, 0x01, 0x90,
+ 0x29, 0x03, 0x7f, 0xa8, 0x67, 0x96, 0x2f, 0xfc, 0xfa, 0xd3, 0x41, 0xb7,
+ 0x17, 0x4b, 0x17, 0xff, 0x98, 0x79, 0xda, 0x7f, 0x9a, 0xd3, 0xf6, 0x58,
+ 0xad, 0xd1, 0x1c, 0x48, 0x37, 0x80, 0xff, 0x58, 0xbf, 0xec, 0x37, 0x0e,
+ 0xf1, 0xd2, 0x75, 0x8b, 0xfd, 0x27, 0x98, 0xc0, 0x82, 0x09, 0x62, 0xba,
+ 0x55, 0xf6, 0xf1, 0x97, 0x68, 0xbb, 0xf0, 0xe9, 0x01, 0x19, 0x0e, 0xf7,
+ 0x1e, 0x5f, 0xf1, 0x8c, 0x59, 0xdc, 0x67, 0xc4, 0xb1, 0x7e, 0x09, 0xf5,
+ 0x86, 0xac, 0x54, 0xae, 0xae, 0x64, 0x24, 0x5e, 0x17, 0x91, 0x11, 0x34,
+ 0xb1, 0x21, 0x39, 0x86, 0x7d, 0x7f, 0xfc, 0xdf, 0x32, 0x4c, 0xce, 0xd3,
+ 0x03, 0x27, 0x4b, 0x17, 0xe1, 0xbf, 0xf0, 0x96, 0x2f, 0xfb, 0xcf, 0xc7,
+ 0x17, 0x7e, 0x39, 0x58, 0xba, 0x7a, 0x58, 0xbf, 0xc1, 0xf0, 0xc6, 0xd6,
+ 0xa5, 0x62, 0xff, 0xfb, 0xde, 0x9f, 0x75, 0x0f, 0xe1, 0x1a, 0x19, 0xd6,
+ 0x2f, 0xe9, 0xf6, 0x13, 0x47, 0xac, 0x5f, 0xa0, 0x0f, 0xb1, 0xd6, 0x2f,
+ 0x6d, 0x81, 0x2c, 0x58, 0x06, 0x1e, 0x44, 0x6c, 0x53, 0x7f, 0xdc, 0x93,
+ 0x1f, 0x68, 0x4f, 0x7a, 0xb1, 0x43, 0x54, 0x81, 0x8a, 0x8e, 0x4f, 0xa3,
+ 0xe3, 0x8c, 0x31, 0xb0, 0x15, 0x09, 0xdf, 0x85, 0xd7, 0x46, 0xdd, 0xea,
+ 0xc5, 0xff, 0x98, 0xb7, 0xf6, 0x7f, 0xde, 0x12, 0xc5, 0x39, 0xf1, 0x08,
+ 0x8a, 0xf4, 0xf6, 0x95, 0x8b, 0xfa, 0x75, 0xb4, 0xeb, 0x65, 0x8b, 0xe1,
+ 0x6d, 0x30, 0x58, 0xa8, 0x1e, 0xa7, 0x0c, 0x2f, 0xf1, 0xa6, 0x69, 0xfa,
+ 0xf6, 0x2c, 0x5f, 0xed, 0x34, 0x86, 0x39, 0xfa, 0xc5, 0xff, 0xf7, 0xe4,
+ 0x66, 0x7f, 0x0c, 0xcd, 0x34, 0x31, 0x62, 0xf9, 0xcd, 0xc1, 0xac, 0x5e,
+ 0x37, 0x06, 0xb1, 0x63, 0x98, 0x78, 0x2e, 0x47, 0x7e, 0x13, 0x43, 0x34,
+ 0xb1, 0x6f, 0x61, 0xe8, 0x11, 0x45, 0xff, 0x48, 0x0e, 0xd0, 0x8d, 0x3b,
+ 0xde, 0xf1, 0x62, 0xe0, 0xbb, 0xf5, 0x8b, 0xf0, 0x5f, 0x11, 0x6e, 0xb1,
+ 0x7f, 0x8b, 0xdc, 0xc8, 0x3f, 0xd6, 0x2a, 0x4f, 0x7b, 0x0a, 0xea, 0x51,
+ 0x39, 0xc7, 0xcb, 0xff, 0xd9, 0x0c, 0x89, 0xf5, 0x82, 0xdd, 0x89, 0x62,
+ 0xfe, 0x68, 0x68, 0xd6, 0x25, 0x8b, 0xf6, 0x76, 0x29, 0xe9, 0x62, 0xbe,
+ 0x8a, 0x20, 0x25, 0x70, 0xba, 0xe1, 0x7d, 0x62, 0xa5, 0x5b, 0x24, 0x0d,
+ 0xf7, 0x34, 0x78, 0x71, 0x11, 0x37, 0x21, 0xcb, 0xe8, 0x62, 0x47, 0x18,
+ 0x5f, 0xff, 0x48, 0x30, 0x8c, 0x6f, 0x19, 0xfc, 0x03, 0x2c, 0x5c, 0x5b,
+ 0x2c, 0x5d, 0x3d, 0x96, 0x2a, 0x57, 0x22, 0xb2, 0x5c, 0x33, 0xc2, 0x0c,
+ 0x94, 0x04, 0x31, 0x7f, 0xff, 0xdd, 0x6e, 0x59, 0xdb, 0x07, 0x98, 0x44,
+ 0x26, 0xda, 0x74, 0xb1, 0x7f, 0x87, 0x87, 0x33, 0x8d, 0xf5, 0x8b, 0xc2,
+ 0x9e, 0x2c, 0x56, 0x22, 0xe9, 0xda, 0x3e, 0x6b, 0x77, 0x20, 0xb1, 0x7f,
+ 0xff, 0xfe, 0xec, 0x59, 0xc7, 0xf6, 0x84, 0x73, 0x35, 0x3f, 0x73, 0x96,
+ 0x78, 0xc9, 0x82, 0xc5, 0xff, 0xd2, 0x72, 0x63, 0x4b, 0x01, 0xd0, 0x16,
+ 0x29, 0xd1, 0x97, 0xf8, 0x43, 0x5f, 0xdd, 0x98, 0xff, 0x09, 0x96, 0x2f,
+ 0xff, 0xa7, 0xdc, 0x9d, 0x8c, 0xc1, 0x98, 0xe7, 0x95, 0x8b, 0xff, 0xb5,
+ 0x3c, 0xc1, 0xfd, 0xfb, 0x66, 0x96, 0x2f, 0xff, 0xde, 0x6f, 0xc6, 0x73,
+ 0xf8, 0x5e, 0x30, 0x10, 0xe2, 0xc5, 0xff, 0xff, 0xdf, 0xe6, 0x1c, 0xf3,
+ 0xa3, 0x79, 0x83, 0x2c, 0x7d, 0x67, 0xa5, 0x62, 0xcf, 0x28, 0xcc, 0x65,
+ 0xbb, 0xfc, 0x4f, 0x9b, 0xcf, 0xb8, 0xb1, 0x7f, 0xce, 0x5d, 0xb6, 0xc3,
+ 0x73, 0x4b, 0x14, 0xe7, 0xdf, 0xc3, 0x3a, 0x82, 0xa7, 0x27, 0x27, 0xf9,
+ 0x88, 0x14, 0x8a, 0x31, 0x2f, 0x42, 0x56, 0xfe, 0x93, 0xbf, 0xe7, 0xa5,
+ 0x8b, 0x85, 0xa5, 0x8a, 0xd1, 0xe3, 0x70, 0xba, 0xff, 0x09, 0xb9, 0x9f,
+ 0x73, 0xac, 0x5e, 0xed, 0x9a, 0x58, 0xbc, 0x1e, 0x8d, 0x58, 0xbf, 0xf3,
+ 0xf8, 0x5a, 0x6e, 0x40, 0x1b, 0xac, 0x54, 0xa2, 0x00, 0xe3, 0xec, 0x41,
+ 0x77, 0xdd, 0x62, 0xff, 0xa0, 0x67, 0xb3, 0x5a, 0x7d, 0xd6, 0x29, 0xcf,
+ 0x4c, 0x85, 0xef, 0xc7, 0xef, 0x63, 0x6c, 0xd2, 0xc5, 0xff, 0x3f, 0xb0,
+ 0xee, 0x6e, 0x0d, 0x62, 0xa4, 0xfb, 0x30, 0xce, 0xfd, 0x9a, 0xe3, 0x69,
+ 0x62, 0xff, 0xdf, 0x72, 0x00, 0x7f, 0xfb, 0x6c, 0xb1, 0x7e, 0x70, 0x1d,
+ 0xa0, 0xb1, 0x73, 0xf1, 0x62, 0xb6, 0x37, 0xe7, 0x28, 0xbf, 0xd9, 0xf7,
+ 0x1c, 0x97, 0x96, 0x2f, 0xed, 0x31, 0x00, 0x12, 0xb1, 0x52, 0xbe, 0xad,
+ 0xb1, 0x76, 0x4b, 0x55, 0x78, 0x54, 0x68, 0x8b, 0xf0, 0xb3, 0x68, 0x40,
+ 0x94, 0x23, 0x38, 0x41, 0xe2, 0x81, 0x42, 0x00, 0x22, 0x20, 0xcc, 0xaf,
+ 0xf1, 0x67, 0xb8, 0x07, 0xe9, 0x62, 0xfc, 0x58, 0x32, 0x65, 0x8b, 0xfb,
+ 0x4f, 0xef, 0xb8, 0xd6, 0x2a, 0x08, 0x88, 0xc3, 0x4d, 0x13, 0x5f, 0x0a,
+ 0x78, 0x4b, 0x17, 0xff, 0xec, 0xea, 0x13, 0xb1, 0x9f, 0x97, 0x26, 0xd1,
+ 0xab, 0x17, 0x67, 0x65, 0x8b, 0xf4, 0x9d, 0xba, 0xf2, 0xc5, 0xd9, 0xb2,
+ 0xc5, 0xff, 0xc3, 0xe6, 0x68, 0xb0, 0x1c, 0xcd, 0x2c, 0x57, 0xd1, 0x3d,
+ 0xc1, 0x9f, 0x14, 0x88, 0x62, 0xfd, 0x9b, 0x89, 0xb6, 0x58, 0xad, 0xd3,
+ 0x7f, 0xd1, 0x17, 0xe1, 0xec, 0x47, 0xb7, 0xff, 0xff, 0xff, 0x0a, 0x60,
+ 0x26, 0x34, 0xce, 0x61, 0x67, 0x74, 0xc0, 0xcc, 0x27, 0x9f, 0xb9, 0x67,
+ 0xb3, 0xb2, 0xc5, 0xff, 0xe2, 0x17, 0x45, 0x8f, 0xad, 0xff, 0x3c, 0x58,
+ 0xb7, 0x7e, 0xb1, 0x5a, 0x3e, 0x20, 0x92, 0xef, 0xff, 0xed, 0xdb, 0xf9,
+ 0x09, 0xd4, 0x83, 0x52, 0x1b, 0x12, 0xc5, 0xff, 0xa4, 0x9c, 0xf8, 0xe5,
+ 0x27, 0x58, 0xbe, 0xcf, 0xb8, 0xd6, 0x28, 0xe7, 0xba, 0x03, 0xbb, 0xff,
+ 0xe6, 0x87, 0x1c, 0x66, 0x41, 0xc7, 0xf0, 0xf8, 0xb1, 0x52, 0x9a, 0x86,
+ 0x11, 0xb4, 0x2e, 0x04, 0x45, 0x7f, 0xf8, 0x6f, 0x3b, 0x87, 0xf6, 0xeb,
+ 0xdf, 0x95, 0x8b, 0xff, 0xf6, 0x43, 0xed, 0x03, 0x33, 0xd1, 0xcf, 0xa9,
+ 0x82, 0xc5, 0xf6, 0xcc, 0x5d, 0x96, 0x2e, 0xc0, 0x96, 0x2e, 0x11, 0x2c,
+ 0x5e, 0x06, 0x16, 0xc6, 0xbf, 0xe3, 0x15, 0x88, 0x86, 0x65, 0x4b, 0xff,
+ 0xff, 0xf1, 0x9e, 0xfb, 0xcf, 0x0c, 0xc1, 0x6f, 0x3d, 0x8c, 0xcd, 0x6b,
+ 0x3b, 0x09, 0xbe, 0xb1, 0x7a, 0x19, 0xb2, 0xc5, 0x41, 0x15, 0x2d, 0x08,
+ 0xbb, 0xef, 0x46, 0x9d, 0xef, 0x78, 0xb1, 0x52, 0x7b, 0x58, 0x4f, 0x7d,
+ 0xf2, 0x6e, 0xe5, 0x8b, 0x8c, 0x25, 0x8b, 0xcf, 0xdd, 0x2b, 0x15, 0x03,
+ 0x6e, 0x71, 0x8a, 0x95, 0xf7, 0x2c, 0x8e, 0xbb, 0x48, 0x7f, 0x94, 0xa8,
+ 0xc8, 0x00, 0x4d, 0x28, 0x6f, 0xf2, 0x32, 0x4f, 0x10, 0x09, 0x72, 0xff,
+ 0xf8, 0x5c, 0xfc, 0xe4, 0x7e, 0x11, 0x63, 0x81, 0x62, 0xfe, 0xeb, 0x8e,
+ 0x79, 0xdd, 0x62, 0xf9, 0x86, 0x2e, 0x2c, 0x5f, 0xf3, 0xc7, 0xb7, 0xf3,
+ 0xba, 0x62, 0x58, 0xa9, 0x47, 0x13, 0x28, 0x70, 0xc0, 0x32, 0x3b, 0xec,
+ 0x19, 0xf8, 0xb1, 0x7f, 0x9b, 0xfc, 0x7e, 0xd8, 0x35, 0x8b, 0xd9, 0x9c,
+ 0x58, 0xb6, 0x96, 0x2f, 0x7b, 0x0e, 0xb1, 0x52, 0x6b, 0xf0, 0x4a, 0xdb,
+ 0x0c, 0xfa, 0x99, 0x2e, 0xf0, 0x71, 0xcc, 0xb1, 0x7f, 0xfe, 0x7d, 0xbe,
+ 0xcf, 0xe9, 0xfb, 0xfb, 0x98, 0x35, 0x8b, 0xfe, 0x33, 0x3e, 0xed, 0xef,
+ 0xca, 0xc5, 0x47, 0xa2, 0x38, 0x95, 0x69, 0x62, 0xbe, 0x8e, 0x06, 0x85,
+ 0x78, 0x64, 0xb4, 0xc9, 0x9e, 0x8a, 0x30, 0x8b, 0x81, 0xde, 0xac, 0x5f,
+ 0xbf, 0x3f, 0x78, 0xf5, 0x8b, 0xdf, 0x9d, 0x2c, 0x5f, 0xff, 0x9c, 0x58,
+ 0x40, 0x33, 0x3e, 0x23, 0x9d, 0xa0, 0xb1, 0x5b, 0x9f, 0x9e, 0x87, 0x6f,
+ 0x8e, 0x22, 0xdd, 0x62, 0xff, 0xdd, 0x9a, 0x18, 0x43, 0x29, 0x82, 0xc5,
+ 0xff, 0xb8, 0x21, 0xfd, 0xcc, 0xdb, 0x02, 0x58, 0xbb, 0x69, 0x58, 0xac,
+ 0x44, 0xd7, 0x8f, 0xc4, 0x87, 0x7d, 0x9f, 0x3c, 0xac, 0x5f, 0x7c, 0x26,
+ 0xd9, 0x62, 0xa5, 0x50, 0x94, 0x07, 0x75, 0x09, 0xe0, 0x11, 0x94, 0x2f,
+ 0xb8, 0x5f, 0xe2, 0x2b, 0xce, 0x14, 0x4b, 0x17, 0xff, 0xf7, 0xf7, 0x16,
+ 0x00, 0xcc, 0xf7, 0x1f, 0xc0, 0x9d, 0x96, 0x2f, 0xf9, 0xbe, 0xfc, 0xe0,
+ 0x98, 0x0b, 0x14, 0x34, 0x5b, 0xe0, 0xfb, 0x2f, 0xda, 0x32, 0x37, 0x7d,
+ 0x11, 0xfe, 0xf0, 0xaf, 0xbd, 0x41, 0x8d, 0x21, 0x13, 0x1b, 0x1c, 0xf7,
+ 0xc3, 0x29, 0x9c, 0x54, 0xda, 0x1f, 0x50, 0x8e, 0x44, 0x72, 0xa3, 0xb2,
+ 0xb0, 0x78, 0x36, 0x36, 0x3d, 0xe3, 0x0d, 0xea, 0x35, 0x57, 0x8e, 0xce,
+ 0x28, 0xed, 0xf5, 0x38, 0xcc, 0x79, 0x45, 0x9f, 0x9e, 0xe9, 0x69, 0x56,
+ 0xc0, 0x86, 0xf7, 0x7e, 0x42, 0x53, 0x9f, 0x9c, 0xa4, 0x32, 0xfa, 0x91,
+ 0x9a, 0x28, 0xe1, 0x3b, 0x1e, 0x04, 0x47, 0x1d, 0x1e, 0xe0, 0x72, 0x8e,
+ 0xfb, 0xa3, 0x25, 0xbd, 0xd8, 0x0e, 0xb1, 0x7b, 0xb0, 0x1d, 0x62, 0xf1,
+ 0x38, 0x4b, 0x17, 0xfb, 0x8f, 0xe9, 0xfe, 0xee, 0xb1, 0x7d, 0xbb, 0x36,
+ 0xea, 0x92, 0xa0, 0xbf, 0xda, 0x9e, 0xdd, 0x43, 0x3c, 0xb1, 0x5a, 0x3e,
+ 0x81, 0x18, 0xdb, 0xa5, 0x8b, 0xfa, 0x7d, 0xce, 0xd8, 0x35, 0x8a, 0x93,
+ 0xc3, 0x34, 0x4e, 0xfe, 0x16, 0x81, 0xe6, 0xe9, 0x62, 0xff, 0xb3, 0xcd,
+ 0xd1, 0x9b, 0x60, 0x4b, 0x17, 0xfe, 0x68, 0x46, 0x66, 0xb7, 0x66, 0xdd,
+ 0x52, 0x35, 0x97, 0xfd, 0xf9, 0x3f, 0x38, 0xc5, 0xba, 0xc5, 0xf4, 0xea,
+ 0x7c, 0xb1, 0x73, 0x79, 0x62, 0x86, 0x6e, 0x4e, 0x45, 0x7f, 0x08, 0x78,
+ 0x4d, 0x05, 0x8b, 0xfd, 0xd7, 0x09, 0xe4, 0x33, 0xac, 0x51, 0xcf, 0x89,
+ 0x8b, 0x6f, 0xe0, 0xb3, 0xf0, 0xce, 0x2c, 0x5f, 0xe2, 0x6f, 0x72, 0x2f,
+ 0xba, 0xc5, 0xa3, 0x23, 0x65, 0x76, 0xbd, 0xf0, 0x7e, 0x03, 0xe3, 0x1d,
+ 0xc8, 0x4e, 0x1a, 0xcb, 0xb9, 0x16, 0x8c, 0x0e, 0x7b, 0xf5, 0x06, 0x73,
+ 0x04, 0x20, 0xf8, 0x42, 0x19, 0x7d, 0xff, 0xb0, 0xe6, 0x7b, 0x23, 0xdf,
+ 0xb7, 0x16, 0x2f, 0xff, 0xf4, 0x8e, 0x3e, 0x41, 0x31, 0x42, 0x7b, 0x67,
+ 0x73, 0x94, 0x4b, 0x16, 0x71, 0xa2, 0xbb, 0x88, 0xb7, 0xf9, 0xa2, 0xe3,
+ 0x78, 0x52, 0xb1, 0x51, 0xe7, 0xb9, 0xa2, 0x8b, 0x85, 0x12, 0xc5, 0xe6,
+ 0x6d, 0xd5, 0x25, 0x61, 0x7f, 0x45, 0xc6, 0xf0, 0xa5, 0x62, 0xda, 0xdc,
+ 0xf6, 0x58, 0xaa, 0xff, 0xff, 0x76, 0xce, 0xe7, 0x28, 0x8c, 0x29, 0xf7,
+ 0x32, 0x22, 0x65, 0x8b, 0xf9, 0xf3, 0xb8, 0xb0, 0x0b, 0x15, 0x04, 0x4a,
+ 0x8d, 0x9a, 0xfb, 0xef, 0xae, 0x2c, 0x5e, 0xd4, 0x9d, 0x62, 0xff, 0xfc,
+ 0xc4, 0x6c, 0x64, 0x3f, 0x9d, 0x37, 0xc4, 0x5b, 0x2c, 0x5f, 0xe8, 0x4e,
+ 0xb6, 0x9d, 0x6c, 0xb1, 0x7f, 0xce, 0x09, 0x03, 0x10, 0xb1, 0x62, 0xa4,
+ 0xfb, 0x70, 0xda, 0xff, 0xc4, 0x39, 0xed, 0x13, 0xf6, 0x20, 0x2c, 0x5f,
+ 0xfc, 0xec, 0x03, 0x27, 0x71, 0x10, 0xc4, 0xb1, 0x52, 0x88, 0x9f, 0xa1,
+ 0xda, 0x32, 0x55, 0xa5, 0x6c, 0x4b, 0x8e, 0x4f, 0x0b, 0xd8, 0x88, 0xf4,
+ 0x46, 0x71, 0xd2, 0x86, 0x47, 0xa1, 0x53, 0x7c, 0x58, 0x2e, 0xfd, 0x62,
+ 0xfe, 0xeb, 0xd3, 0xf6, 0x8f, 0x58, 0xbf, 0x37, 0xf3, 0x58, 0xb1, 0x52,
+ 0x7b, 0x2c, 0x65, 0x7f, 0x75, 0xcc, 0xfc, 0x9d, 0x62, 0xfe, 0xd0, 0xa2,
+ 0xe4, 0xf9, 0x62, 0xa5, 0x1f, 0xff, 0x84, 0x07, 0x88, 0x04, 0x5f, 0x7f,
+ 0xf0, 0x30, 0xa3, 0x20, 0x0e, 0x6c, 0xc4, 0xb1, 0x51, 0x88, 0x89, 0x94,
+ 0x1b, 0xf8, 0x6e, 0x2f, 0x67, 0x16, 0x2f, 0xe7, 0x3b, 0xfb, 0xf2, 0xb1,
+ 0x7d, 0x31, 0x4f, 0x4b, 0x15, 0xf3, 0xd1, 0xe1, 0x6d, 0xff, 0xfb, 0x42,
+ 0xd8, 0x7a, 0x6d, 0xcb, 0x3b, 0x69, 0xf8, 0xb1, 0x7f, 0x9f, 0xf2, 0x73,
+ 0xb4, 0x16, 0x2f, 0xda, 0xdd, 0x9b, 0x75, 0x48, 0x88, 0x5f, 0x30, 0x66,
+ 0xca, 0xc5, 0xff, 0xb3, 0xb9, 0xf6, 0xeb, 0x35, 0xa6, 0x58, 0xbf, 0x9c,
+ 0xfb, 0x0b, 0x50, 0x58, 0xb4, 0x64, 0xa6, 0x03, 0x86, 0x62, 0x37, 0xec,
+ 0x49, 0x1c, 0x87, 0x73, 0x1d, 0x62, 0xa0, 0x7d, 0xdd, 0x2b, 0xdf, 0xdb,
+ 0x4e, 0xbe, 0xce, 0xb1, 0x7f, 0x70, 0xb0, 0x02, 0xe2, 0xc5, 0xa3, 0x23,
+ 0x75, 0x5d, 0x38, 0xff, 0xa2, 0x26, 0x8f, 0x27, 0x84, 0x62, 0x2e, 0xbf,
+ 0x6b, 0x76, 0x6d, 0xd5, 0x26, 0x91, 0x7f, 0xe6, 0x84, 0x66, 0x6b, 0x76,
+ 0x6d, 0xd5, 0x23, 0xe9, 0x68, 0xcc, 0x44, 0x39, 0xcd, 0xef, 0xfc, 0xd0,
+ 0x8c, 0xcd, 0x6e, 0xcd, 0xba, 0xa4, 0x84, 0x2f, 0xc4, 0xdc, 0xcf, 0x2c,
+ 0x5a, 0x30, 0xe7, 0xee, 0xca, 0x17, 0xff, 0x60, 0x51, 0x9e, 0x35, 0xb8,
+ 0xfe, 0x95, 0x8b, 0xf7, 0x85, 0xbb, 0x71, 0x62, 0xe9, 0xd2, 0xc5, 0xff,
+ 0xd2, 0x71, 0x6b, 0x76, 0x71, 0xcc, 0x4b, 0x16, 0x7d, 0x8f, 0x76, 0x21,
+ 0x7a, 0x3a, 0x2c, 0x3f, 0x08, 0x7b, 0xed, 0xd9, 0xb7, 0x54, 0x91, 0xe5,
+ 0xfa, 0x4f, 0xfc, 0xee, 0x58, 0xad, 0x1e, 0xe7, 0x8c, 0x6d, 0x8b, 0x17,
+ 0xf0, 0xbc, 0x77, 0x0b, 0x8b, 0x14, 0x33, 0xc1, 0x21, 0x1b, 0xe7, 0xc0,
+ 0x71, 0x62, 0xe6, 0xdd, 0x62, 0xd8, 0x33, 0x75, 0xdc, 0x45, 0x7e, 0x9e,
+ 0x44, 0x52, 0xb1, 0x7f, 0xd3, 0x09, 0xd6, 0xd3, 0xad, 0x96, 0x2f, 0xff,
+ 0xff, 0xf0, 0x6f, 0xa8, 0xa7, 0xfa, 0xcf, 0xb0, 0x7c, 0xc3, 0x58, 0x81,
+ 0x25, 0x31, 0x7e, 0x56, 0x2f, 0xcd, 0xc7, 0xf4, 0xac, 0x5f, 0xf4, 0xc5,
+ 0x25, 0x31, 0x7e, 0x56, 0x2a, 0x51, 0xe0, 0x6c, 0x24, 0x08, 0x9e, 0xf8,
+ 0xfb, 0x60, 0x4b, 0x17, 0xff, 0xe1, 0xfe, 0x43, 0x8c, 0xf1, 0x30, 0x39,
+ 0xc9, 0x02, 0x45, 0x49, 0xff, 0xe1, 0x2d, 0xe6, 0x84, 0x64, 0xab, 0x91,
+ 0xc8, 0x42, 0x44, 0xc7, 0xa5, 0xbf, 0x94, 0x91, 0x47, 0xa3, 0x2b, 0x8e,
+ 0x85, 0x9d, 0xff, 0xd9, 0xf8, 0xcf, 0x1a, 0xdc, 0x7f, 0x4a, 0xc5, 0xff,
+ 0xff, 0xcf, 0xb4, 0x63, 0xfb, 0x22, 0x27, 0xe7, 0xa4, 0x37, 0xd4, 0x53,
+ 0xf5, 0x8b, 0x46, 0x6c, 0xbb, 0xc2, 0x79, 0xc8, 0xaf, 0x42, 0x63, 0xb9,
+ 0x22, 0xa6, 0x14, 0x1a, 0x7b, 0x5b, 0x33, 0x68, 0x43, 0xcb, 0x25, 0x52,
+ 0x9b, 0x7a, 0x30, 0x3b, 0xcf, 0x16, 0x75, 0x3a, 0x68, 0xf2, 0x87, 0xa2,
+ 0x96, 0x1d, 0xf8, 0x79, 0x02, 0x14, 0x5e, 0x9e, 0x0b, 0xbf, 0xfe, 0x0b,
+ 0x7e, 0xf3, 0xbd, 0x07, 0x7f, 0xa8, 0xd0, 0xc3, 0x3f, 0x1c, 0xb1, 0x7f,
+ 0xff, 0xee, 0xef, 0x46, 0xc3, 0x3c, 0x6c, 0x4f, 0xdf, 0x5f, 0x77, 0xfa,
+ 0x8d, 0x0c, 0x33, 0xf1, 0xcb, 0x15, 0xf4, 0xc0, 0xc2, 0x6f, 0xbf, 0xfb,
+ 0xf2, 0xfa, 0x7e, 0xff, 0x7f, 0xc8, 0x4b, 0x17, 0xff, 0xee, 0xf8, 0x6f,
+ 0x5d, 0xf3, 0xbe, 0x77, 0x84, 0x78, 0xd4, 0x61, 0x9f, 0x8e, 0x58, 0xbf,
+ 0xf7, 0x3b, 0xf7, 0x34, 0xc3, 0x3f, 0x1d, 0x19, 0x28, 0xed, 0xdc, 0x97,
+ 0x89, 0x77, 0xff, 0xff, 0xfb, 0xbb, 0xbf, 0x73, 0x4c, 0x33, 0xf1, 0xd1,
+ 0x93, 0xf0, 0xb7, 0xef, 0x3b, 0xd0, 0x77, 0xfa, 0x8d, 0x0c, 0x33, 0xf1,
+ 0xcb, 0x17, 0xed, 0x6e, 0xcd, 0xba, 0xa4, 0x22, 0x2f, 0xcf, 0xe8, 0x83,
+ 0x1a, 0xc5, 0xfe, 0xe0, 0xa6, 0x2f, 0x3f, 0x65, 0x8b, 0x46, 0x62, 0x26,
+ 0x77, 0x37, 0x88, 0xae, 0xfe, 0xcd, 0x6e, 0xcd, 0xba, 0xa4, 0x2b, 0x2f,
+ 0xda, 0xdd, 0x9b, 0x75, 0x49, 0x70, 0x5d, 0x3f, 0x58, 0xba, 0x3e, 0x33,
+ 0x0f, 0x3b, 0xb1, 0xbd, 0x46, 0x22, 0xfd, 0xa1, 0x15, 0x7d, 0xf6, 0xd3,
+ 0xac, 0x5f, 0xbc, 0x00, 0xca, 0x0b, 0x17, 0xe0, 0x49, 0x6f, 0x19, 0x27,
+ 0x98, 0xc4, 0x57, 0x45, 0x1e, 0xb1, 0x7f, 0x13, 0xef, 0xe9, 0x82, 0xc5,
+ 0xa3, 0x36, 0x3c, 0xad, 0x0e, 0x59, 0xfa, 0x45, 0xb0, 0x21, 0x15, 0x7f,
+ 0xbb, 0xde, 0xf0, 0xa7, 0x76, 0xe9, 0x62, 0xfb, 0x3e, 0xde, 0x58, 0xbf,
+ 0xd8, 0xfa, 0x00, 0x05, 0xc5, 0x8b, 0x77, 0xa4, 0x7a, 0xdc, 0x22, 0xbf,
+ 0xff, 0xff, 0xdd, 0xe4, 0x6f, 0xde, 0xcf, 0x3f, 0x86, 0xe0, 0xcb, 0x36,
+ 0x78, 0x72, 0x47, 0x3f, 0x26, 0x8f, 0x58, 0xbf, 0xff, 0xdf, 0xc1, 0x43,
+ 0xf9, 0xd9, 0xa3, 0xd8, 0xbd, 0xfc, 0x82, 0xc5, 0xff, 0x49, 0x6e, 0xdf,
+ 0x62, 0x1a, 0xc5, 0xfa, 0x7c, 0xc5, 0x8b, 0x14, 0x69, 0xef, 0x68, 0xe2,
+ 0xff, 0xfe, 0xd4, 0xec, 0x77, 0x86, 0x0b, 0x72, 0xcd, 0xb5, 0x2b, 0x17,
+ 0xe2, 0x6f, 0x4e, 0xeb, 0x17, 0xff, 0xee, 0x3f, 0xd9, 0xe0, 0xe5, 0xe1,
+ 0x7f, 0x58, 0xb1, 0x7f, 0x8f, 0xc7, 0x8e, 0xcd, 0x4a, 0xc5, 0xff, 0x4f,
+ 0x74, 0xfd, 0xca, 0x4e, 0xb1, 0x58, 0x7e, 0x04, 0x6d, 0x50, 0x54, 0x9e,
+ 0xf0, 0xc3, 0xd1, 0x1f, 0x17, 0x7c, 0x51, 0xdd, 0x0c, 0x4b, 0xb8, 0xeb,
+ 0x17, 0xd8, 0x79, 0x82, 0xc5, 0xd8, 0x10, 0x0d, 0xc9, 0x0b, 0xdf, 0x81,
+ 0xcf, 0x14, 0xac, 0x5f, 0xef, 0x72, 0x62, 0x66, 0xd2, 0xc5, 0x49, 0xee,
+ 0x39, 0x45, 0xf6, 0x1d, 0xbc, 0xb1, 0x7f, 0x31, 0xa1, 0x36, 0xb8, 0xb1,
+ 0x5f, 0x3d, 0x26, 0x22, 0xbf, 0xff, 0x7f, 0x0b, 0x0d, 0xfb, 0x43, 0xe1,
+ 0x30, 0x67, 0x58, 0xbf, 0xd2, 0x7f, 0x7f, 0x3b, 0x62, 0xc5, 0xf3, 0xef,
+ 0x9a, 0x58, 0xbf, 0xf8, 0x72, 0x01, 0xb3, 0x04, 0x3c, 0x25, 0x8b, 0xcc,
+ 0xdb, 0xaa, 0x49, 0xe2, 0xb6, 0x44, 0x88, 0xc8, 0xf7, 0x44, 0xbd, 0x25,
+ 0xe5, 0x8b, 0xff, 0x4f, 0x62, 0xce, 0x61, 0x39, 0xd6, 0x2f, 0x3e, 0xbe,
+ 0xe7, 0xb4, 0xc3, 0x97, 0xfc, 0xc7, 0xe3, 0xe7, 0x66, 0xd2, 0xc5, 0xff,
+ 0x8a, 0x7b, 0x3f, 0xa1, 0x38, 0x4b, 0x15, 0x05, 0x4a, 0x71, 0x2c, 0x6a,
+ 0x18, 0xdf, 0x84, 0x61, 0x18, 0xf8, 0xea, 0xff, 0x0c, 0x06, 0x4c, 0x7c,
+ 0xc1, 0x62, 0xff, 0x1d, 0xc6, 0x26, 0xd4, 0x16, 0x2e, 0x3b, 0xac, 0x54,
+ 0x9e, 0x5e, 0xe6, 0x97, 0xff, 0xf4, 0xfb, 0x82, 0x3e, 0xee, 0x09, 0xcf,
+ 0xb8, 0xb7, 0x58, 0xb9, 0xf8, 0xb1, 0x7f, 0x49, 0xf9, 0x2f, 0xb2, 0xc5,
+ 0x41, 0x14, 0x58, 0xbb, 0xe1, 0x7b, 0xff, 0xf9, 0xb4, 0xdf, 0xea, 0x19,
+ 0xec, 0x21, 0x78, 0x46, 0xac, 0x5f, 0x42, 0x73, 0x65, 0x8b, 0xff, 0xf6,
+ 0x85, 0xad, 0x49, 0x61, 0xaf, 0xff, 0xe0, 0x6b, 0x16, 0x1a, 0xc5, 0xcf,
+ 0xd9, 0x62, 0xce, 0xb1, 0x5b, 0xa6, 0x27, 0xd2, 0xee, 0x88, 0xce, 0xae,
+ 0x01, 0x2e, 0xc3, 0x37, 0x8f, 0x3b, 0xac, 0x5c, 0x5e, 0x58, 0xac, 0x36,
+ 0xae, 0x3d, 0x7e, 0x73, 0x8c, 0x78, 0xb1, 0x7b, 0x69, 0xdd, 0x62, 0xfe,
+ 0x1e, 0x43, 0xf3, 0xba, 0xc5, 0xff, 0x98, 0x73, 0x85, 0xee, 0x49, 0x2c,
+ 0x53, 0xa2, 0x29, 0x87, 0xc8, 0xbe, 0xf0, 0x60, 0x09, 0x62, 0xf8, 0x01,
+ 0xfa, 0x56, 0x2d, 0x08, 0xc3, 0xf1, 0xc2, 0xd7, 0x20, 0xba, 0x7a, 0x58,
+ 0xbc, 0x79, 0xdd, 0x62, 0xe7, 0xf6, 0xc6, 0xdb, 0x06, 0x29, 0x91, 0x30,
+ 0x26, 0xcb, 0xf0, 0x64, 0x1f, 0x5c, 0x58, 0xbc, 0x4e, 0x05, 0x8a, 0x19,
+ 0xe4, 0x1c, 0xb2, 0xff, 0xb4, 0xdb, 0x0c, 0x4d, 0xa8, 0x2c, 0x5f, 0xfb,
+ 0x82, 0xd3, 0xb3, 0x8e, 0x49, 0x62, 0xff, 0x49, 0xe6, 0x30, 0x20, 0x82,
+ 0x58, 0xa7, 0x3f, 0x7e, 0xe3, 0xda, 0x94, 0x7c, 0x39, 0x13, 0x42, 0xca,
+ 0xfe, 0x71, 0xe1, 0xc5, 0xe5, 0x8b, 0xfe, 0xc2, 0x04, 0x9d, 0xf5, 0x05,
+ 0x8b, 0xfc, 0xfc, 0x71, 0x77, 0xe3, 0x95, 0x8a, 0x81, 0xf8, 0x78, 0xe2,
+ 0xfd, 0xa9, 0x83, 0x81, 0x62, 0xff, 0xf8, 0xf8, 0xfe, 0x17, 0xa6, 0x0e,
+ 0x3c, 0x1a, 0xc5, 0x41, 0x33, 0x77, 0x84, 0xf6, 0x88, 0x80, 0x51, 0x7e,
+ 0xd6, 0xd3, 0xad, 0x96, 0x2f, 0xce, 0x5e, 0x0c, 0xeb, 0x15, 0x27, 0xa8,
+ 0x02, 0xbb, 0xfd, 0xa9, 0x9f, 0x71, 0xfb, 0x2c, 0x5f, 0xd3, 0xb3, 0x0d,
+ 0xbc, 0xb1, 0x50, 0x44, 0x21, 0xc8, 0x7b, 0x8d, 0x6f, 0xd2, 0x7d, 0xc0,
+ 0x4b, 0x17, 0xcc, 0xf1, 0xd2, 0xb1, 0x7c, 0x61, 0x34, 0x16, 0x2f, 0xcd,
+ 0x9f, 0x73, 0xac, 0x54, 0x48, 0x97, 0x39, 0x4f, 0x09, 0x3b, 0x11, 0xdd,
+ 0x3d, 0xcb, 0x15, 0x29, 0x92, 0x64, 0x32, 0xa2, 0x40, 0xbf, 0xfd, 0x02,
+ 0xc1, 0x7a, 0x7d, 0x84, 0x09, 0x58, 0xbf, 0x9f, 0xcc, 0x6f, 0xdd, 0x62,
+ 0xff, 0xf8, 0x4d, 0xa8, 0x6f, 0xf7, 0x1e, 0x9c, 0x5b, 0x2c, 0x5f, 0xf4,
+ 0xef, 0xf6, 0x78, 0xe9, 0xd2, 0xc5, 0xfe, 0x63, 0x98, 0x3f, 0xb9, 0xd6,
+ 0x28, 0xe7, 0xe3, 0xd8, 0xf2, 0xff, 0x8a, 0x4f, 0x30, 0x2c, 0x3a, 0xc5,
+ 0xff, 0x89, 0x82, 0xf6, 0x7d, 0x9e, 0x25, 0x8b, 0xdb, 0x4f, 0x4b, 0x17,
+ 0xff, 0x4e, 0xb6, 0x9e, 0xb0, 0x5d, 0xfe, 0x0d, 0x62, 0xb6, 0x3e, 0xa3,
+ 0x8f, 0xdf, 0xfe, 0xcf, 0x08, 0x07, 0x68, 0x19, 0xa6, 0xe2, 0xc5, 0xff,
+ 0xbe, 0xe4, 0x00, 0xff, 0xf6, 0xd9, 0x62, 0xfb, 0xd0, 0x93, 0x56, 0x2a,
+ 0x55, 0x89, 0x41, 0x20, 0x65, 0xd9, 0x0c, 0x47, 0x24, 0x88, 0xdd, 0xa1,
+ 0x52, 0x44, 0x7e, 0x4c, 0x0d, 0x06, 0xfb, 0x1c, 0xa2, 0x58, 0xbe, 0xf4,
+ 0x69, 0xde, 0xf7, 0x8b, 0x17, 0xb5, 0x3b, 0x2c, 0x56, 0x1e, 0x8b, 0x99,
+ 0xd6, 0xe8, 0x93, 0xe3, 0x9d, 0xfe, 0x2d, 0xf3, 0xb6, 0x7b, 0x8b, 0x17,
+ 0xe1, 0x8a, 0x75, 0xb2, 0xc5, 0xff, 0xf7, 0x81, 0x30, 0xce, 0xcf, 0xe9,
+ 0xc2, 0x82, 0xc5, 0xcc, 0x6a, 0xc5, 0x4a, 0x32, 0x30, 0xd9, 0xca, 0xb4,
+ 0xa1, 0x7b, 0xdf, 0x75, 0x8b, 0xb4, 0x25, 0x8b, 0xa7, 0x8b, 0x17, 0xd9,
+ 0xec, 0x3a, 0xc5, 0xb6, 0x93, 0xd1, 0x18, 0xc3, 0x0b, 0xd6, 0x22, 0x89,
+ 0x9b, 0xaf, 0xed, 0x03, 0x8e, 0x37, 0x58, 0xbe, 0xf8, 0x4d, 0xb2, 0xc5,
+ 0x49, 0xe9, 0xf8, 0xba, 0xf8, 0x45, 0x1e, 0x6a, 0xc5, 0xf8, 0xa1, 0x3f,
+ 0x95, 0x8a, 0x73, 0xce, 0x11, 0x3d, 0x46, 0x8d, 0xca, 0xb4, 0x6d, 0x09,
+ 0x5e, 0xf8, 0x59, 0x32, 0xbb, 0xf6, 0x84, 0xf4, 0x21, 0x10, 0x37, 0x2c,
+ 0x94, 0xe8, 0x6b, 0x1e, 0xf0, 0x83, 0xea, 0x18, 0x8f, 0x1a, 0x14, 0x50,
+ 0x91, 0xd0, 0xf9, 0xe3, 0xbb, 0xfc, 0x6c, 0x4d, 0x1b, 0x49, 0x4a, 0x3e,
+ 0xe4, 0xb4, 0x7f, 0x46, 0x4f, 0xda, 0x1d, 0x91, 0xd0, 0xdc, 0x0d, 0xd3,
+ 0xb9, 0xbe, 0xff, 0xff, 0x9f, 0xb1, 0x67, 0x23, 0x37, 0xfb, 0xfe, 0x73,
+ 0x50, 0x3c, 0x7a, 0xc5, 0xfd, 0x9e, 0xe6, 0x34, 0x7a, 0xc5, 0xfc, 0xc1,
+ 0x73, 0x92, 0x05, 0x8a, 0x93, 0xdf, 0x23, 0x0b, 0xf7, 0x83, 0xd8, 0x5d,
+ 0xfa, 0xc5, 0xfa, 0x3a, 0x40, 0xde, 0x58, 0xb6, 0xcb, 0x17, 0x9a, 0x11,
+ 0x83, 0x44, 0x7e, 0x10, 0x39, 0x88, 0x45, 0x77, 0xff, 0x80, 0x01, 0x72,
+ 0x30, 0x32, 0x63, 0x94, 0xac, 0x5f, 0xff, 0xfb, 0xdc, 0x10, 0xfe, 0xf1,
+ 0x9e, 0x13, 0x10, 0x38, 0x1c, 0xe8, 0x0b, 0x17, 0xff, 0x16, 0x01, 0x88,
+ 0x11, 0x87, 0x73, 0xac, 0x56, 0x93, 0x06, 0x24, 0xef, 0x39, 0x5f, 0xf0,
+ 0x51, 0x85, 0x91, 0x40, 0x5e, 0x58, 0xbf, 0x3e, 0xb8, 0x23, 0xac, 0x5f,
+ 0xc4, 0xcf, 0xfc, 0xe2, 0xc5, 0xf7, 0xdf, 0x91, 0x87, 0x3d, 0x5e, 0x14,
+ 0xd4, 0xa3, 0x43, 0x78, 0x4a, 0x5f, 0xff, 0xd3, 0xbc, 0x67, 0xdb, 0x79,
+ 0x03, 0x69, 0xbd, 0x06, 0x58, 0xbf, 0xfd, 0xd7, 0x23, 0x38, 0x59, 0xda,
+ 0x4b, 0xdc, 0x58, 0xbf, 0xff, 0xfc, 0xf0, 0xc2, 0x8c, 0x2c, 0xdc, 0xb3,
+ 0x6e, 0x16, 0x7b, 0xce, 0x0e, 0x2c, 0x5f, 0xfc, 0x2f, 0x41, 0xc1, 0x19,
+ 0xe3, 0x5c, 0x96, 0x2f, 0xf4, 0xfd, 0xce, 0xe5, 0x05, 0x8b, 0xf3, 0x7f,
+ 0xef, 0x12, 0xc5, 0xff, 0xd9, 0xc7, 0x20, 0x16, 0x7b, 0xf8, 0xb1, 0x7f,
+ 0xe7, 0x20, 0x16, 0x7b, 0xf9, 0x19, 0xa4, 0x4e, 0xfc, 0xc8, 0x32, 0x9a,
+ 0x8c, 0x64, 0x07, 0xc2, 0x3c, 0x11, 0xc6, 0xba, 0xf1, 0xab, 0x6a, 0x30,
+ 0x03, 0x94, 0x32, 0xf8, 0x14, 0x09, 0xe7, 0x90, 0xe6, 0xbc, 0x5d, 0x01,
+ 0x62, 0xd8, 0xb1, 0x7e, 0x29, 0x17, 0x7f, 0xc5, 0x8b, 0x9f, 0xeb, 0x17,
+ 0xff, 0xcc, 0x33, 0x5b, 0xd9, 0xf2, 0xcf, 0x7d, 0xd6, 0x2f, 0xe3, 0x74,
+ 0xc3, 0x62, 0x58, 0xa9, 0x47, 0x80, 0xc7, 0xb0, 0x47, 0x45, 0xbf, 0x17,
+ 0x64, 0xfb, 0xff, 0x9c, 0x7a, 0x6e, 0xa3, 0x35, 0xa9, 0xd9, 0x62, 0xa3,
+ 0x11, 0x3d, 0xf5, 0x4b, 0x4a, 0xc5, 0xfd, 0xc9, 0xdc, 0xa4, 0x6b, 0x14,
+ 0x33, 0x7e, 0xe2, 0x37, 0xcd, 0xd0, 0xe5, 0x62, 0xff, 0xfa, 0x75, 0x90,
+ 0x76, 0xf6, 0x0d, 0xc5, 0xba, 0x45, 0xc2, 0xe9, 0x62, 0xbe, 0x7d, 0x04,
+ 0x9f, 0x79, 0xc1, 0xc5, 0x8b, 0x6e, 0xb1, 0x7e, 0x98, 0x00, 0x50, 0x58,
+ 0xbe, 0xdd, 0x9b, 0x75, 0x49, 0x66, 0x5d, 0x21, 0x2c, 0x56, 0xc8, 0xa2,
+ 0xc1, 0xd8, 0x84, 0xf4, 0x53, 0xd8, 0xc6, 0xfb, 0xce, 0x7e, 0x2c, 0x5b,
+ 0x4b, 0x16, 0x35, 0x62, 0x9c, 0xd2, 0xf0, 0x4a, 0xf7, 0x05, 0xba, 0xc5,
+ 0x1a, 0x6f, 0xf8, 0x41, 0x7e, 0xf1, 0xaf, 0xd7, 0x16, 0x2c, 0x1a, 0xc5,
+ 0xff, 0x4e, 0xc5, 0x9d, 0xb4, 0xfc, 0x58, 0xbd, 0xa9, 0xec, 0xb1, 0x52,
+ 0x7d, 0xb0, 0x13, 0xe1, 0xdd, 0xfd, 0xd8, 0x8a, 0x63, 0xe2, 0x58, 0xbf,
+ 0x1e, 0x4a, 0x1c, 0x58, 0xba, 0x62, 0x58, 0xa9, 0x3f, 0x3d, 0x8c, 0xf4,
+ 0x51, 0x7d, 0xee, 0x07, 0xc5, 0x8b, 0xee, 0x72, 0x42, 0x58, 0xbf, 0xfc,
+ 0xde, 0xe7, 0x9f, 0xae, 0x76, 0xf6, 0xc4, 0xb1, 0x66, 0x58, 0xac, 0x45,
+ 0x4b, 0x92, 0x91, 0x27, 0x13, 0xee, 0xd9, 0xd6, 0x2f, 0x73, 0xe2, 0x58,
+ 0xbe, 0x60, 0xbe, 0x25, 0x8b, 0xfa, 0x27, 0x2f, 0xe7, 0x4b, 0x15, 0x87,
+ 0xe2, 0x71, 0xee, 0x12, 0x54, 0xa2, 0xdf, 0x21, 0x13, 0x73, 0x79, 0x62,
+ 0xf8, 0x01, 0x94, 0x16, 0x82, 0x86, 0x6f, 0xfc, 0x2f, 0x7f, 0xfd, 0x27,
+ 0xf6, 0x61, 0x7b, 0x9f, 0xc0, 0x32, 0xc5, 0xfe, 0x3c, 0xf5, 0xcd, 0x4f,
+ 0x65, 0x8b, 0x85, 0xb2, 0xc5, 0xb8, 0xb1, 0x7b, 0xcd, 0x12, 0xc5, 0x31,
+ 0xb0, 0xf0, 0x95, 0x4a, 0x28, 0x08, 0xdc, 0x49, 0x37, 0xf3, 0x8a, 0x3e,
+ 0x34, 0x01, 0xd6, 0x2f, 0xbc, 0xc0, 0x95, 0x8a, 0x81, 0xec, 0xf4, 0x6f,
+ 0x7e, 0x29, 0xfb, 0xe2, 0xc5, 0xd3, 0x05, 0x8a, 0xc3, 0xe0, 0x62, 0x30,
+ 0x13, 0x5d, 0xd7, 0x96, 0x2f, 0x68, 0x1c, 0x58, 0xc2, 0xe6, 0xfa, 0x41,
+ 0x30, 0x58, 0xb3, 0xac, 0x5e, 0x26, 0xf2, 0xc7, 0x0b, 0x1b, 0x64, 0x0f,
+ 0x78, 0x8c, 0xef, 0x0a, 0x03, 0x58, 0xa7, 0x46, 0x77, 0xe1, 0x14, 0x44,
+ 0xd7, 0xe8, 0xbe, 0xe5, 0xb2, 0xc5, 0xf7, 0xbf, 0x3d, 0x96, 0x2b, 0xa3,
+ 0xcf, 0x22, 0xab, 0xcc, 0xc7, 0x58, 0xbf, 0xd9, 0xaf, 0xcf, 0x5e, 0xc5,
+ 0x8b, 0xf3, 0x6c, 0x07, 0xf2, 0xc5, 0xf4, 0x5b, 0x08, 0x0b, 0x17, 0xfe,
+ 0x72, 0x14, 0x33, 0x9b, 0x60, 0x4b, 0x15, 0x87, 0xcd, 0xe2, 0x6b, 0xfb,
+ 0xd3, 0xa0, 0x4c, 0x4b, 0x15, 0x2c, 0xaa, 0x88, 0x10, 0x0e, 0x11, 0x79,
+ 0x0c, 0x3e, 0x93, 0x5e, 0x10, 0xf1, 0xe4, 0x51, 0x42, 0x63, 0x50, 0xa1,
+ 0x3c, 0x36, 0x3f, 0x0f, 0x16, 0x65, 0x01, 0x09, 0x43, 0xbb, 0x90, 0xe7,
+ 0xf4, 0x62, 0x82, 0x84, 0x17, 0x62, 0x20, 0x87, 0x23, 0x8d, 0x03, 0x84,
+ 0x7f, 0x71, 0x0d, 0xff, 0xff, 0xd2, 0x08, 0xc1, 0x94, 0xf5, 0x0f, 0xce,
+ 0xb6, 0xe6, 0x0b, 0x71, 0x74, 0xb1, 0x51, 0x89, 0xf6, 0x14, 0x6e, 0x57,
+ 0xec, 0x38, 0x73, 0x1e, 0xb1, 0x7f, 0x73, 0x92, 0x00, 0xf6, 0x58, 0xa8,
+ 0x1e, 0xee, 0x16, 0x5f, 0xef, 0x36, 0xb6, 0x97, 0x1a, 0xc5, 0xfd, 0xee,
+ 0x0d, 0xe4, 0x96, 0x29, 0xcf, 0x85, 0x8d, 0x2f, 0xe9, 0x0b, 0xc6, 0xb7,
+ 0x16, 0x2f, 0xe9, 0x3e, 0xc2, 0xd4, 0x16, 0x2f, 0xb5, 0x81, 0x79, 0x62,
+ 0xbe, 0x8a, 0x42, 0x20, 0xf1, 0x87, 0x63, 0x0b, 0xfd, 0xb7, 0xf3, 0x7f,
+ 0xce, 0x96, 0x2f, 0xfa, 0x4a, 0x1c, 0x3b, 0x11, 0xab, 0x15, 0x27, 0xdf,
+ 0xe3, 0x6b, 0xa4, 0x6b, 0x17, 0xfc, 0x23, 0xe6, 0xfa, 0xe9, 0x82, 0x58,
+ 0xa8, 0x1f, 0xaf, 0x08, 0x7c, 0x2f, 0x7f, 0xb5, 0x26, 0xe1, 0x39, 0xab,
+ 0x17, 0xff, 0xcc, 0xdb, 0x7d, 0xe4, 0xa0, 0xff, 0x6e, 0x2c, 0x5f, 0xd0,
+ 0xd6, 0xa4, 0xfc, 0x58, 0xbf, 0xcf, 0xa0, 0xc7, 0xf9, 0x82, 0xc5, 0xc7,
+ 0x95, 0x8a, 0x19, 0xfd, 0xb1, 0x7f, 0x71, 0xad, 0xff, 0xf0, 0xff, 0x3c,
+ 0x33, 0x1f, 0x4e, 0x79, 0x35, 0x62, 0xd2, 0xb1, 0x69, 0x58, 0xac, 0x3f,
+ 0x3e, 0x28, 0x88, 0x46, 0xff, 0xd0, 0xc8, 0xf6, 0x20, 0x6d, 0x81, 0x2c,
+ 0x5e, 0x26, 0xf2, 0xc5, 0xfb, 0x3a, 0x04, 0xfd, 0x62, 0xff, 0xe0, 0x83,
+ 0x39, 0x67, 0x5e, 0x9c, 0x09, 0x62, 0xf0, 0xe4, 0x0b, 0x17, 0xfc, 0xf0,
+ 0x7f, 0x88, 0xe7, 0x75, 0x8a, 0x94, 0x4f, 0x0d, 0x23, 0xc3, 0xb7, 0xef,
+ 0x39, 0x61, 0xd6, 0x2f, 0x31, 0x46, 0x0d, 0x77, 0x0b, 0x23, 0x26, 0xea,
+ 0x32, 0x2d, 0x17, 0x9c, 0xd3, 0xf0, 0xc9, 0x28, 0x52, 0x78, 0xbb, 0xb2,
+ 0x1c, 0x70, 0xe0, 0x70, 0xc7, 0xee, 0x2f, 0xbc, 0x7e, 0xa5, 0x62, 0xfe,
+ 0x83, 0x6b, 0x6f, 0x89, 0x62, 0xfd, 0xc9, 0x00, 0x7b, 0x2c, 0x54, 0x47,
+ 0xb7, 0xc3, 0x0a, 0x94, 0x4e, 0x63, 0xcd, 0xff, 0x17, 0xbf, 0x90, 0x70,
+ 0x62, 0xc5, 0xff, 0x84, 0x5e, 0xfe, 0x77, 0x38, 0x31, 0x62, 0xff, 0xb3,
+ 0xdf, 0xc8, 0x38, 0x31, 0x62, 0xfe, 0x7c, 0x03, 0x74, 0xeb, 0x17, 0xfe,
+ 0xf3, 0xc1, 0xfe, 0x23, 0x9d, 0xd6, 0x2f, 0x30, 0x51, 0x83, 0x4c, 0xfb,
+ 0x08, 0x4e, 0x70, 0x48, 0x3e, 0x38, 0x0c, 0xb6, 0xa0, 0xac, 0x90, 0xa5,
+ 0x5c, 0x5f, 0xf9, 0xa1, 0x19, 0x9a, 0xdd, 0x9b, 0x75, 0x48, 0x8a, 0x5f,
+ 0xf8, 0x71, 0x9d, 0xbc, 0x6e, 0x0d, 0xfa, 0x58, 0xbf, 0xfe, 0xfe, 0x14,
+ 0x67, 0x99, 0xba, 0xe1, 0xa6, 0xb2, 0xc5, 0x62, 0x27, 0x3c, 0x8f, 0x7f,
+ 0xe6, 0xf4, 0x64, 0xbe, 0x9f, 0xc2, 0x58, 0xa8, 0xc4, 0xd3, 0xe6, 0x1d,
+ 0x8c, 0x45, 0x7f, 0xda, 0xd3, 0x85, 0x91, 0x39, 0xd6, 0x2f, 0xb7, 0x9f,
+ 0xca, 0xc5, 0x39, 0xef, 0x11, 0xdd, 0xfb, 0x5b, 0xb3, 0x6e, 0xa9, 0x32,
+ 0x4b, 0x71, 0x62, 0xa4, 0xfa, 0x70, 0x80, 0xe6, 0xf7, 0xf4, 0x0a, 0x7e,
+ 0xc7, 0x58, 0xbe, 0x72, 0x87, 0x16, 0x2f, 0xd3, 0xcf, 0x3e, 0xcb, 0x15,
+ 0xb1, 0xe5, 0x9a, 0x45, 0x7f, 0x85, 0xb7, 0xe7, 0xdc, 0x75, 0x8b, 0xf8,
+ 0x43, 0x7d, 0x37, 0x16, 0x2e, 0x6e, 0x2c, 0x52, 0xc5, 0x68, 0xd1, 0xf8,
+ 0x5e, 0xfb, 0x36, 0x17, 0x4b, 0x14, 0xe7, 0x8c, 0x44, 0x37, 0xd9, 0x9d,
+ 0x41, 0x62, 0xfd, 0xee, 0x07, 0xc8, 0xc9, 0x4e, 0xaf, 0x1e, 0x34, 0x49,
+ 0xc3, 0x5f, 0x42, 0x5f, 0xb8, 0x82, 0xa3, 0x15, 0x2c, 0x64, 0x7b, 0x17,
+ 0xfe, 0x87, 0x1f, 0xc7, 0x3c, 0xfb, 0x8b, 0x17, 0xf4, 0xf5, 0x0d, 0xb0,
+ 0x25, 0x8b, 0xf4, 0x9d, 0x87, 0x19, 0xd1, 0xf8, 0xf9, 0x02, 0xfb, 0x02,
+ 0xe7, 0xd6, 0x2f, 0xce, 0x2e, 0xfd, 0xf4, 0xb1, 0x7d, 0x27, 0x70, 0x96,
+ 0x2f, 0xe7, 0x3c, 0xfc, 0x31, 0xac, 0x54, 0x47, 0xa5, 0xdc, 0x47, 0x7a,
+ 0x61, 0xc5, 0x8b, 0xe9, 0xc2, 0x1a, 0xc5, 0xdf, 0x7d, 0x1b, 0xe3, 0x8e,
+ 0xdf, 0xe9, 0xc0, 0x71, 0x9f, 0x65, 0x8b, 0xe7, 0x91, 0x77, 0xeb, 0x17,
+ 0x9b, 0xd2, 0xb1, 0x7f, 0x1f, 0xcf, 0xf6, 0x3a, 0xc5, 0xff, 0xe7, 0xf7,
+ 0xf3, 0xd8, 0x53, 0xe9, 0x1a, 0xc5, 0x49, 0xfb, 0x31, 0x75, 0xf3, 0xc6,
+ 0xcd, 0xba, 0xc5, 0xe1, 0x60, 0xd6, 0x2f, 0xf3, 0xf8, 0x5a, 0x6e, 0x46,
+ 0x6c, 0xaa, 0x10, 0x64, 0x98, 0xff, 0xbb, 0x24, 0x45, 0x9a, 0x33, 0x39,
+ 0x3f, 0xe1, 0x25, 0xe2, 0x08, 0xe2, 0x8a, 0x75, 0x71, 0x0d, 0x2b, 0x1a,
+ 0xff, 0xfd, 0xf6, 0x84, 0x66, 0x6a, 0x77, 0xeb, 0xc2, 0x6e, 0x2c, 0x5f,
+ 0xf3, 0x74, 0x08, 0xc3, 0xe9, 0xcd, 0x58, 0xa1, 0xa2, 0x6b, 0xcb, 0x77,
+ 0xf6, 0x6b, 0x76, 0x6d, 0xd5, 0x26, 0xc1, 0x7f, 0xfe, 0xf9, 0x85, 0x9a,
+ 0xf7, 0x3f, 0x11, 0x86, 0x7e, 0x39, 0x62, 0xfd, 0xf6, 0xd3, 0x9d, 0x62,
+ 0xbb, 0xd4, 0x43, 0xee, 0xbf, 0x7e, 0xce, 0xda, 0x6e, 0x2c, 0x5f, 0xfb,
+ 0x5b, 0x4f, 0x9d, 0xe1, 0xc9, 0x58, 0xbd, 0xa1, 0x7d, 0x62, 0xff, 0xe9,
+ 0x1e, 0x75, 0xe3, 0x58, 0x0f, 0xe5, 0x8b, 0xbd, 0x19, 0x28, 0xf6, 0x19,
+ 0x4e, 0x15, 0x68, 0xfc, 0x31, 0xea, 0x8c, 0x54, 0x22, 0xf1, 0xdc, 0xde,
+ 0xce, 0x62, 0xc5, 0xed, 0x66, 0xcb, 0x17, 0xdb, 0xb3, 0x6e, 0xa9, 0x36,
+ 0xcb, 0xf1, 0xc1, 0x85, 0xba, 0xc5, 0xcd, 0xa5, 0x8b, 0x41, 0x62, 0xdc,
+ 0x93, 0xd2, 0xd8, 0xa4, 0x42, 0xf5, 0xba, 0x35, 0xb4, 0x3d, 0xe8, 0x41,
+ 0xdf, 0xbf, 0xe7, 0x00, 0x96, 0x2f, 0xff, 0x4e, 0xde, 0x71, 0xe1, 0x41,
+ 0xfe, 0x25, 0x8a, 0x73, 0xf3, 0xf9, 0x4d, 0xf9, 0xa2, 0x29, 0x3a, 0xc5,
+ 0xf4, 0x67, 0x0f, 0x2b, 0x16, 0x25, 0x8a, 0x81, 0xb7, 0x22, 0x6b, 0xfd,
+ 0x09, 0xd6, 0xd3, 0xad, 0x96, 0x2f, 0xf0, 0x24, 0x0c, 0x42, 0xc5, 0x8b,
+ 0x83, 0xf2, 0xc5, 0x39, 0xe5, 0xe8, 0xca, 0xa5, 0x14, 0x59, 0x08, 0x1b,
+ 0xe9, 0x8b, 0x8e, 0xb1, 0x50, 0x56, 0x4d, 0x90, 0xf2, 0x8a, 0x15, 0x27,
+ 0x21, 0x65, 0xf2, 0x86, 0x17, 0x71, 0x35, 0xff, 0x87, 0xa7, 0x16, 0xd1,
+ 0x9c, 0xd7, 0x96, 0x2a, 0x31, 0x17, 0x78, 0xed, 0x7f, 0xff, 0xde, 0x73,
+ 0x63, 0x3c, 0x26, 0x88, 0x98, 0x2d, 0x4f, 0x9b, 0xcb, 0x17, 0xfb, 0x39,
+ 0xc9, 0x00, 0x7b, 0x2c, 0x5e, 0xfe, 0x6c, 0xb1, 0x7f, 0x30, 0xf3, 0x08,
+ 0xd5, 0x8b, 0xfb, 0xef, 0xad, 0x34, 0x16, 0x2f, 0xfd, 0xe7, 0x83, 0xfc,
+ 0x47, 0x3b, 0xac, 0x50, 0xd1, 0xdd, 0x11, 0xb1, 0xc7, 0xb8, 0x5a, 0x19,
+ 0x75, 0xfe, 0xc8, 0xcd, 0x64, 0x73, 0x9a, 0xb1, 0x60, 0x46, 0x22, 0x1a,
+ 0x39, 0x32, 0xd9, 0xf5, 0x41, 0xe5, 0x1f, 0x05, 0xff, 0xc5, 0x20, 0x8c,
+ 0x2c, 0x8a, 0x13, 0xd2, 0xc5, 0x89, 0x62, 0xd0, 0x58, 0xa8, 0xd8, 0xd1,
+ 0x8c, 0x46, 0xf4, 0x6d, 0xf1, 0xac, 0x5e, 0xdb, 0xee, 0xb1, 0x7f, 0xe8,
+ 0xda, 0x36, 0xef, 0xbf, 0x7f, 0x0a, 0x40, 0xb1, 0x7b, 0xbe, 0x46, 0xbe,
+ 0xf8, 0xb1, 0x7d, 0x3f, 0x68, 0x96, 0x2f, 0x76, 0x14, 0x16, 0x2b, 0xc7,
+ 0x87, 0xd8, 0x8e, 0xfc, 0x50, 0x18, 0x8e, 0xb1, 0x76, 0x79, 0x62, 0xfe,
+ 0x08, 0x38, 0xe6, 0x20, 0x2c, 0x54, 0x9f, 0x98, 0xca, 0x70, 0x5e, 0xff,
+ 0xdc, 0x11, 0xf7, 0xfb, 0x44, 0x20, 0x96, 0x2f, 0xe7, 0x0e, 0x2e, 0x0b,
+ 0xa5, 0x8b, 0xed, 0xfe, 0x2d, 0x2c, 0x5a, 0x36, 0x58, 0xa1, 0x9b, 0xcd,
+ 0x12, 0xd3, 0xa3, 0x4f, 0xe8, 0x8c, 0xdd, 0x7f, 0xb5, 0xa9, 0x83, 0x74,
+ 0x12, 0xc5, 0xfc, 0xfb, 0x0c, 0xa4, 0x35, 0x8a, 0xc3, 0xe5, 0x23, 0x6b,
+ 0xff, 0xf6, 0x81, 0xfc, 0xe7, 0xf3, 0xdc, 0x72, 0xea, 0x0b, 0x17, 0xff,
+ 0x8d, 0x35, 0x82, 0x9d, 0x7c, 0x26, 0x2d, 0x96, 0x2a, 0x51, 0x4c, 0xea,
+ 0xf7, 0xf8, 0x43, 0x0f, 0x66, 0x61, 0xac, 0x5f, 0xfd, 0x17, 0xc5, 0x1f,
+ 0xe0, 0x39, 0x43, 0x8b, 0x17, 0xdb, 0xb3, 0x6e, 0xa9, 0x3c, 0x0b, 0xf7,
+ 0xba, 0xdd, 0xf4, 0xb1, 0x7f, 0xc0, 0xe1, 0x9c, 0x03, 0x64, 0x4b, 0x17,
+ 0xfb, 0x5a, 0xcf, 0x72, 0x4e, 0xb1, 0x4e, 0x7e, 0x0c, 0x79, 0x78, 0x6f,
+ 0xe5, 0x8b, 0xfd, 0x3d, 0xb5, 0xac, 0xeb, 0x8b, 0x14, 0x73, 0xd4, 0xf0,
+ 0xed, 0xdc, 0xfa, 0xc5, 0x31, 0xba, 0x11, 0x15, 0xfb, 0x59, 0xd9, 0xb4,
+ 0xb1, 0x7f, 0xed, 0x07, 0xe7, 0xf9, 0x67, 0xb1, 0x62, 0x9c, 0xfa, 0x58,
+ 0xaa, 0xa0, 0xab, 0x10, 0x64, 0x2e, 0x6d, 0xa4, 0xa3, 0x98, 0xfe, 0x13,
+ 0x65, 0x0a, 0xee, 0xd0, 0x89, 0xbe, 0xf7, 0x7d, 0x72, 0x25, 0x8b, 0xa6,
+ 0x56, 0x2b, 0x47, 0x85, 0xe2, 0xcb, 0xf6, 0xc5, 0x2e, 0x35, 0x8b, 0x79,
+ 0x62, 0xff, 0xdf, 0x76, 0x07, 0x50, 0x13, 0x79, 0x62, 0xce, 0x03, 0xd2,
+ 0xf0, 0x95, 0xff, 0xf3, 0x9e, 0x77, 0x33, 0x0f, 0x85, 0xe8, 0xec, 0x58,
+ 0xa9, 0x47, 0xa0, 0xde, 0xbe, 0x4f, 0x73, 0x71, 0x62, 0xf4, 0x76, 0x7d,
+ 0x62, 0x80, 0x6d, 0xfc, 0x2f, 0x7e, 0x70, 0x99, 0xbb, 0x96, 0x2f, 0xf8,
+ 0x7a, 0x9f, 0x3e, 0xee, 0x35, 0x8b, 0xde, 0x93, 0xac, 0x56, 0x1e, 0xbf,
+ 0x8e, 0xaf, 0xa4, 0xa0, 0xcb, 0x17, 0x3c, 0x72, 0xc5, 0x44, 0x8d, 0xed,
+ 0x42, 0x08, 0xe4, 0x3d, 0xf9, 0x0d, 0xdb, 0x84, 0xb1, 0x7f, 0x49, 0x7b,
+ 0xb3, 0x6e, 0xb1, 0x7f, 0x42, 0x7b, 0x4e, 0xba, 0x58, 0xbf, 0xff, 0x9b,
+ 0x68, 0xa1, 0x3a, 0xdb, 0xd0, 0xc8, 0xf6, 0x20, 0x2c, 0x54, 0x68, 0x8d,
+ 0xc8, 0x0d, 0x61, 0x83, 0x18, 0xdf, 0x75, 0xc9, 0xec, 0xb1, 0x70, 0x7c,
+ 0x58, 0xbe, 0xf7, 0xf8, 0xeb, 0x17, 0xfb, 0xaf, 0xe0, 0xc3, 0x9e, 0x96,
+ 0x2a, 0x4f, 0x69, 0xc8, 0xef, 0x16, 0x44, 0xb1, 0x58, 0x8d, 0x68, 0x89,
+ 0xb4, 0xe7, 0xf2, 0x0b, 0xfb, 0xcd, 0xf3, 0x07, 0x2b, 0x17, 0xfc, 0xde,
+ 0xe4, 0xb8, 0xf0, 0xeb, 0x15, 0x27, 0xce, 0x45, 0xf7, 0xe8, 0x3b, 0xfd,
+ 0x96, 0x2f, 0x8b, 0x1c, 0xd5, 0x8b, 0xfa, 0x1e, 0xc2, 0xf7, 0x16, 0x2f,
+ 0x40, 0x5c, 0x58, 0xb1, 0xfa, 0x3c, 0xc8, 0x8b, 0xab, 0xa4, 0x5f, 0x9c,
+ 0x9c, 0x36, 0xeb, 0xbf, 0x05, 0x8b, 0xb0, 0xd5, 0x8b, 0xdb, 0xe1, 0x2c,
+ 0x5f, 0xba, 0xe3, 0xf5, 0xc5, 0x8b, 0x1d, 0x62, 0xfa, 0x1e, 0x7d, 0x96,
+ 0x2a, 0x4f, 0xfa, 0x21, 0xd3, 0x95, 0xb0, 0x95, 0xff, 0xde, 0x92, 0xdd,
+ 0xce, 0x77, 0xe0, 0x96, 0x2f, 0xfe, 0x0e, 0x75, 0x03, 0x39, 0x87, 0x9c,
+ 0x58, 0xa7, 0x44, 0x5f, 0x91, 0x6f, 0x98, 0xb6, 0xfa, 0xc5, 0x4a, 0x7d,
+ 0x70, 0x32, 0xc1, 0x87, 0x84, 0xb3, 0x43, 0x18, 0x22, 0x2b, 0xb0, 0xeb,
+ 0x17, 0xe7, 0xf8, 0xdf, 0x8b, 0x16, 0x7d, 0x8d, 0xfc, 0x05, 0xef, 0xd8,
+ 0x40, 0xee, 0x95, 0x8b, 0x9b, 0x8b, 0x17, 0x84, 0xdc, 0x58, 0xaf, 0x1b,
+ 0x40, 0xc5, 0xed, 0xc5, 0x8b, 0x8b, 0xcb, 0x17, 0x9f, 0x63, 0xac, 0x56,
+ 0x1b, 0x5d, 0x0b, 0xd6, 0xc7, 0xcf, 0x12, 0x3d, 0x4a, 0x2b, 0x72, 0x11,
+ 0x37, 0x44, 0x35, 0x8b, 0xff, 0xff, 0xe2, 0x13, 0x73, 0x0b, 0x9c, 0xcf,
+ 0xbf, 0x05, 0xb7, 0x3f, 0x9d, 0x7a, 0x56, 0x2f, 0xcf, 0xa6, 0xe8, 0x25,
+ 0x8b, 0xff, 0x4e, 0xe6, 0x61, 0x0a, 0x19, 0xc5, 0x8a, 0x82, 0x3a, 0x22,
+ 0x7e, 0x39, 0x55, 0xfe, 0xfb, 0x84, 0x6e, 0x98, 0x25, 0x8b, 0xf7, 0x69,
+ 0x19, 0xf8, 0xb1, 0x7f, 0x67, 0x05, 0xe9, 0x25, 0x8b, 0xfb, 0x0b, 0x7c,
+ 0xeb, 0xcb, 0x17, 0xff, 0xfc, 0xfe, 0x63, 0xb1, 0x03, 0x7f, 0xbe, 0xa0,
+ 0x1c, 0x30, 0x96, 0x2b, 0x11, 0x2c, 0xc5, 0xf7, 0xee, 0xd9, 0x84, 0x6a,
+ 0xc5, 0xfd, 0x83, 0xfc, 0xf2, 0x3d, 0x62, 0xf4, 0x1b, 0xa5, 0x8b, 0xc3,
+ 0xfe, 0x2c, 0x5d, 0x3d, 0x74, 0x6e, 0xd8, 0x7a, 0x86, 0xac, 0xef, 0x23,
+ 0x01, 0xdc, 0xc5, 0xcd, 0xe2, 0x2b, 0xfc, 0x30, 0xc0, 0x42, 0x45, 0x42,
+ 0x6c, 0xbf, 0x8b, 0x3c, 0x0c, 0xe9, 0x62, 0xff, 0x31, 0x03, 0xd1, 0xd9,
+ 0xf5, 0x8b, 0x71, 0x62, 0xf9, 0xe7, 0x50, 0x58, 0xbd, 0xf6, 0x83, 0x9b,
+ 0x43, 0x89, 0x54, 0x7a, 0x26, 0xfe, 0xd5, 0x52, 0x8e, 0xfc, 0x86, 0x4d,
+ 0xc7, 0xe2, 0xc5, 0xf4, 0x94, 0x23, 0xd6, 0x2f, 0xfe, 0x03, 0x10, 0x0b,
+ 0x3b, 0x7f, 0x06, 0xb1, 0x7f, 0xf3, 0x03, 0x07, 0x9f, 0x7d, 0x7d, 0x96,
+ 0x2b, 0xa4, 0x44, 0x71, 0x16, 0xff, 0xcc, 0x0f, 0x3f, 0x3f, 0x25, 0xe5,
+ 0x8b, 0xfb, 0xae, 0x61, 0xe6, 0x3d, 0x62, 0x9c, 0xfc, 0x04, 0x7d, 0x7f,
+ 0x83, 0x28, 0x07, 0xa6, 0x02, 0xc5, 0xef, 0x05, 0xba, 0xc5, 0xff, 0x8f,
+ 0xf2, 0xce, 0xbc, 0x26, 0xe2, 0xc5, 0x61, 0xf0, 0x31, 0x05, 0x80, 0xb1,
+ 0x7f, 0xb5, 0xa7, 0x3f, 0xf3, 0x65, 0x8a, 0x93, 0xc7, 0xc1, 0x2a, 0x82,
+ 0xab, 0xdc, 0x26, 0x34, 0x61, 0xe1, 0x5b, 0xf8, 0x4a, 0x00, 0x87, 0x90,
+ 0x96, 0xf3, 0x3d, 0xfe, 0x6f, 0xb0, 0x67, 0xce, 0x2c, 0x5d, 0xde, 0xf6,
+ 0x58, 0xb6, 0xeb, 0x17, 0x6f, 0x05, 0x8a, 0xc3, 0xcb, 0xdc, 0x7f, 0xc2,
+ 0x77, 0x45, 0xc5, 0x8b, 0xfb, 0x36, 0x07, 0x24, 0x96, 0x29, 0x8f, 0x1c,
+ 0x86, 0x6f, 0xff, 0xf9, 0xc8, 0x50, 0xce, 0x75, 0xed, 0x4e, 0x75, 0x03,
+ 0x80, 0x4b, 0x14, 0x48, 0x89, 0xf1, 0x05, 0x46, 0xed, 0xda, 0x6f, 0x7a,
+ 0x4d, 0x1b, 0x11, 0xf7, 0xc1, 0xe8, 0xd6, 0xa1, 0x2e, 0x7b, 0x42, 0x5e,
+ 0x11, 0x80, 0x0e, 0x12, 0x79, 0x2e, 0x28, 0xd8, 0x62, 0x6f, 0x18, 0xb7,
+ 0x4c, 0xcf, 0x0f, 0xf8, 0xa3, 0x24, 0xd4, 0x62, 0xc7, 0x85, 0x27, 0xe5,
+ 0x65, 0x34, 0x27, 0x80, 0x4e, 0x51, 0x85, 0xf2, 0x5b, 0x0f, 0xa7, 0x0d,
+ 0xbb, 0x42, 0x06, 0x39, 0xfc, 0x38, 0x7f, 0xde, 0xf4, 0x8d, 0x62, 0xf8,
+ 0x0d, 0xae, 0x2c, 0x5d, 0xd4, 0x64, 0x9e, 0x06, 0x0e, 0xdf, 0xe0, 0x46,
+ 0x45, 0x09, 0x2f, 0x2c, 0x54, 0x62, 0xa8, 0xc9, 0x94, 0x49, 0xa3, 0x0b,
+ 0x12, 0xc5, 0xba, 0x58, 0xb8, 0x87, 0x86, 0x90, 0x31, 0x1b, 0xb3, 0xa5,
+ 0x8b, 0xf0, 0x45, 0x9b, 0x09, 0x62, 0xf7, 0x05, 0xb2, 0xc5, 0x49, 0xe4,
+ 0xb1, 0x55, 0x3a, 0x20, 0x74, 0xc3, 0x7d, 0xbb, 0x36, 0xea, 0x93, 0xd0,
+ 0xbf, 0x01, 0xf5, 0x0c, 0x58, 0xad, 0x1e, 0xcf, 0x0c, 0x6f, 0x80, 0x1e,
+ 0xb7, 0x58, 0xbe, 0x92, 0x13, 0x2c, 0x5f, 0xb3, 0xc5, 0x3b, 0x2c, 0x5f,
+ 0xf9, 0x9f, 0xc2, 0xd3, 0x76, 0xc1, 0xac, 0x5c, 0x2e, 0x2c, 0x5f, 0x73,
+ 0xed, 0x1e, 0xb1, 0x43, 0x37, 0xdf, 0x18, 0xbf, 0x49, 0xdb, 0xf2, 0xb1,
+ 0x78, 0xef, 0xe5, 0x8b, 0xfe, 0x6f, 0x42, 0x4d, 0xf3, 0xec, 0xb1, 0x5a,
+ 0x3f, 0xf3, 0x93, 0x90, 0xed, 0xfb, 0x0f, 0xf6, 0x1a, 0xc5, 0x4a, 0xb2,
+ 0xd1, 0xc2, 0xb7, 0x1e, 0xfa, 0x22, 0x72, 0x6d, 0x10, 0xfc, 0xa1, 0x9f,
+ 0x83, 0x85, 0x07, 0x71, 0x75, 0xff, 0xd8, 0x3f, 0xe1, 0xce, 0xd0, 0xc2,
+ 0x58, 0xbc, 0x29, 0x02, 0xc5, 0xf7, 0x6c, 0x28, 0xc1, 0x9f, 0x06, 0x90,
+ 0xef, 0xfb, 0xaf, 0x61, 0x0a, 0x19, 0xc5, 0x8b, 0xe8, 0xa0, 0xc3, 0x58,
+ 0xbf, 0xcf, 0xc0, 0xc9, 0xbd, 0xc5, 0x8a, 0xc3, 0xd8, 0x34, 0x92, 0xfb,
+ 0xb9, 0xf5, 0xb2, 0xc5, 0xa3, 0x31, 0x1b, 0x7e, 0x84, 0x97, 0x71, 0x15,
+ 0x3a, 0x6b, 0x1f, 0x8c, 0x62, 0xa3, 0x15, 0x3c, 0xe4, 0xa5, 0x0a, 0x8d,
+ 0x4f, 0xe9, 0xf9, 0x1a, 0xdc, 0xe6, 0x35, 0x9d, 0xa1, 0xf3, 0x08, 0xcb,
+ 0x32, 0xd0, 0xc9, 0xef, 0x28, 0xe9, 0xe9, 0x9f, 0x31, 0x52, 0x5b, 0xf5,
+ 0x1b, 0xd1, 0xe5, 0xab, 0x7e, 0x70, 0x99, 0xa1, 0x88, 0x09, 0x46, 0x85,
+ 0x38, 0x1d, 0xc9, 0x46, 0x9e, 0x2f, 0x15, 0x7c, 0x88, 0x14, 0xf0, 0x2d,
+ 0xe0, 0x47, 0x6c, 0xb1, 0x7f, 0xd1, 0xbc, 0x68, 0x2e, 0x39, 0x75, 0x05,
+ 0x8b, 0xbd, 0xc5, 0x8a, 0x8d, 0x8f, 0xff, 0xbe, 0xc8, 0x89, 0x16, 0xe3,
+ 0x9d, 0x62, 0xdf, 0x58, 0xae, 0xf0, 0xd5, 0x08, 0x62, 0xff, 0xe1, 0x4c,
+ 0x45, 0x9d, 0x98, 0xe7, 0x75, 0x8b, 0xec, 0xfb, 0x79, 0x62, 0xff, 0x63,
+ 0xe8, 0x00, 0x17, 0x16, 0x2d, 0xde, 0x9a, 0x89, 0xc2, 0x46, 0xe1, 0x15,
+ 0xe7, 0xce, 0x2c, 0x5f, 0xfe, 0xf7, 0x05, 0x3c, 0xcf, 0x39, 0xda, 0x0b,
+ 0x17, 0xa7, 0xad, 0x96, 0x28, 0x8f, 0xa7, 0xc9, 0x57, 0xcf, 0x1d, 0x27,
+ 0x58, 0xbf, 0xdf, 0x9d, 0xb5, 0x38, 0x35, 0x8b, 0xff, 0xe8, 0xb3, 0x02,
+ 0x30, 0x38, 0x4f, 0x67, 0x20, 0x2c, 0x5f, 0xfd, 0x98, 0x10, 0x70, 0x9e,
+ 0xce, 0x40, 0x58, 0xbd, 0x8f, 0xd8, 0xc4, 0x4e, 0x44, 0xab, 0x52, 0x98,
+ 0x3f, 0xe1, 0xa1, 0x7f, 0xde, 0xe6, 0x75, 0x0f, 0x88, 0xd5, 0x8b, 0xdc,
+ 0x98, 0x96, 0x2e, 0xd4, 0xac, 0x50, 0xd5, 0x36, 0x3c, 0x21, 0x4e, 0x43,
+ 0xf8, 0xcb, 0x08, 0xa3, 0x87, 0xbd, 0xc3, 0xd6, 0xc5, 0x8b, 0x9b, 0xeb,
+ 0x15, 0xb9, 0xa8, 0x21, 0x1b, 0xdd, 0x63, 0x2c, 0x5d, 0x30, 0x58, 0xa8,
+ 0xc3, 0x69, 0xd8, 0x76, 0xf7, 0xf3, 0x8b, 0x17, 0xfc, 0x4e, 0x6f, 0xba,
+ 0xdd, 0xfe, 0xb1, 0x7b, 0x93, 0xb2, 0xc5, 0xfb, 0xbb, 0xf1, 0xf3, 0xd2,
+ 0xc5, 0x4a, 0x33, 0x46, 0x4d, 0x83, 0xbd, 0x1e, 0x38, 0xf5, 0xfe, 0xf7,
+ 0xdd, 0x80, 0x09, 0x58, 0xbe, 0xea, 0x02, 0xd9, 0x62, 0xfe, 0x37, 0x8d,
+ 0x3d, 0x41, 0x62, 0xd9, 0xd1, 0xeb, 0x39, 0x35, 0xe2, 0xcf, 0x2c, 0x5e,
+ 0xc2, 0x35, 0x62, 0xe1, 0x32, 0xc5, 0xe6, 0xd4, 0x24, 0xf4, 0x30, 0x70,
+ 0x87, 0x6e, 0x73, 0xac, 0x56, 0x26, 0xa9, 0xa8, 0x44, 0x89, 0xdf, 0xb8,
+ 0xf6, 0xff, 0xfc, 0x46, 0x16, 0x3e, 0x1c, 0xb3, 0xdf, 0x7e, 0x96, 0x2f,
+ 0x8e, 0x22, 0x1a, 0xc5, 0xff, 0xfd, 0x3a, 0x8b, 0x9b, 0xfc, 0x5c, 0xe4,
+ 0x9a, 0x59, 0xd9, 0x62, 0xf1, 0xb2, 0x12, 0xc5, 0xe6, 0x6d, 0xd5, 0x21,
+ 0x19, 0x7b, 0x76, 0xd2, 0xc5, 0xfe, 0x83, 0x30, 0xd9, 0xbb, 0x2c, 0x51,
+ 0xa7, 0xa5, 0xd0, 0xf5, 0x1a, 0x8b, 0xfd, 0xc7, 0xdd, 0xf2, 0xfb, 0xdc,
+ 0x60, 0x2c, 0x5f, 0x7d, 0xcd, 0x12, 0xc5, 0xdd, 0x0d, 0x62, 0xa3, 0x63,
+ 0xe0, 0x19, 0x1b, 0x12, 0x5f, 0x9d, 0x8f, 0x9a, 0x58, 0xbf, 0xe1, 0x37,
+ 0x45, 0x9b, 0x07, 0x05, 0x8b, 0xdb, 0x86, 0x75, 0x8b, 0xff, 0xfc, 0x21,
+ 0xb1, 0x03, 0x0d, 0xd3, 0xf5, 0x9e, 0xe1, 0x62, 0xc5, 0xff, 0xff, 0x4c,
+ 0x5e, 0x9e, 0x6a, 0x7c, 0xfb, 0xb8, 0xcc, 0x34, 0x99, 0x62, 0xa5, 0x1d,
+ 0x51, 0x10, 0x13, 0x0d, 0xff, 0xcf, 0xcf, 0xe1, 0xa6, 0xb1, 0x83, 0xe9,
+ 0x62, 0xa5, 0x70, 0x83, 0x65, 0x4d, 0xc8, 0xf5, 0x19, 0x01, 0xe1, 0x23,
+ 0xf3, 0x3e, 0x13, 0xfa, 0x32, 0x6e, 0xc5, 0xf7, 0xdf, 0x7e, 0x1a, 0xb1,
+ 0x7f, 0x37, 0x5f, 0xc7, 0x09, 0x62, 0xe8, 0x7d, 0x62, 0xb4, 0x78, 0xec,
+ 0x5f, 0x7f, 0xb3, 0xd8, 0x7d, 0xb0, 0x25, 0x8a, 0x19, 0xeb, 0x11, 0x0d,
+ 0xff, 0xdc, 0xe6, 0x1c, 0xb3, 0xb1, 0x93, 0xde, 0x2c, 0x53, 0x9f, 0x68,
+ 0x88, 0x6f, 0xf6, 0x6d, 0xf2, 0xc1, 0x0d, 0x62, 0xbe, 0x7a, 0xa4, 0x43,
+ 0x7f, 0xb6, 0xd6, 0x7b, 0xcf, 0xe5, 0x8a, 0x58, 0xbf, 0xfb, 0xf9, 0xe2,
+ 0x98, 0x8c, 0x34, 0x99, 0x62, 0xe1, 0x4c, 0x47, 0xa5, 0xe0, 0xca, 0x94,
+ 0x5a, 0xf2, 0x10, 0xf7, 0x8a, 0x7a, 0x58, 0xb9, 0xce, 0xb1, 0x76, 0x8d,
+ 0x58, 0xbf, 0x30, 0x5e, 0xcf, 0xac, 0x53, 0x1e, 0x11, 0x0c, 0xd4, 0x11,
+ 0x7a, 0x32, 0x7f, 0x8e, 0xf9, 0x66, 0xe6, 0xfa, 0xc5, 0xfe, 0xd6, 0x73,
+ 0x18, 0xb6, 0x58, 0xbc, 0x71, 0x74, 0xb1, 0x43, 0x3e, 0x9c, 0x17, 0x01,
+ 0x9d, 0xfe, 0x10, 0xc3, 0xff, 0xda, 0x0b, 0x16, 0x3a, 0xc5, 0xfe, 0x0e,
+ 0x13, 0xd9, 0xc8, 0x0b, 0x17, 0xf4, 0x27, 0xb3, 0x90, 0x16, 0x2c, 0x11,
+ 0x87, 0xca, 0x19, 0xb5, 0x0d, 0x14, 0x58, 0xef, 0x7f, 0xed, 0x8c, 0x2c,
+ 0xf7, 0x3f, 0x86, 0xac, 0x5f, 0xee, 0xa1, 0xc1, 0xfc, 0x47, 0x58, 0xa9,
+ 0x3f, 0x9c, 0x42, 0xbf, 0x36, 0xc1, 0xb8, 0xd6, 0x2f, 0xfe, 0xc0, 0x85,
+ 0x3b, 0x78, 0x73, 0xee, 0x2c, 0x5c, 0xf1, 0x2c, 0x54, 0x15, 0x0e, 0x64,
+ 0x36, 0x3f, 0x09, 0xb6, 0x20, 0x22, 0xaf, 0x23, 0xdf, 0xfe, 0x83, 0x9a,
+ 0x6b, 0x72, 0x5f, 0x66, 0xf2, 0xc5, 0xff, 0xfc, 0xcf, 0xe9, 0xf9, 0x67,
+ 0xbe, 0xff, 0xc7, 0x09, 0x62, 0xff, 0xff, 0xfe, 0x2c, 0xd6, 0x9f, 0xb8,
+ 0xc9, 0x83, 0xfb, 0xf2, 0x76, 0x23, 0x27, 0x5a, 0x7e, 0xcb, 0x14, 0xe9,
+ 0x99, 0x7d, 0x33, 0xcb, 0x36, 0x25, 0x8b, 0xfb, 0xe6, 0x7f, 0x07, 0x8b,
+ 0x17, 0xff, 0xff, 0x79, 0xcf, 0xa7, 0xce, 0x88, 0x5e, 0x9f, 0x99, 0xd9,
+ 0xfd, 0x14, 0xac, 0x53, 0x22, 0x97, 0xc5, 0xf7, 0xc1, 0x18, 0x0d, 0x96,
+ 0x2f, 0xe7, 0x27, 0xd6, 0xb1, 0x62, 0xa4, 0xf4, 0xf0, 0x9e, 0xff, 0xb1,
+ 0x88, 0x1a, 0x14, 0x81, 0x62, 0xff, 0xba, 0x86, 0x37, 0x51, 0xd2, 0x75,
+ 0x8a, 0x94, 0xfc, 0x46, 0x61, 0x90, 0xb6, 0xe9, 0xd7, 0x44, 0x1e, 0x38,
+ 0xbf, 0x79, 0xe1, 0x9c, 0x58, 0xbf, 0xe8, 0x3f, 0x83, 0xd4, 0xfe, 0x56,
+ 0x2b, 0x0f, 0x88, 0x45, 0x17, 0xff, 0xe3, 0xc7, 0xbb, 0x34, 0x5e, 0xfe,
+ 0x43, 0xef, 0xd9, 0x62, 0xff, 0xee, 0x7a, 0x7d, 0x9e, 0x8a, 0x13, 0xf5,
+ 0x8b, 0xc2, 0x90, 0x2c, 0x5f, 0xdc, 0x38, 0x8a, 0x42, 0x58, 0xbb, 0xa8,
+ 0x4a, 0x24, 0xb4, 0x8c, 0x21, 0xdb, 0xfe, 0x7e, 0x60, 0xf3, 0xb3, 0xe9,
+ 0x62, 0xff, 0xff, 0x9b, 0x9f, 0xce, 0xbc, 0x4e, 0x11, 0x93, 0x84, 0x3f,
+ 0xca, 0xc5, 0xfe, 0xd4, 0x51, 0xcf, 0xac, 0x35, 0x62, 0xfa, 0x75, 0x20,
+ 0x58, 0xac, 0x3d, 0xbf, 0x1c, 0xdc, 0xd1, 0x2c, 0x5f, 0x01, 0xa2, 0x3a,
+ 0xc5, 0xff, 0xfb, 0x0e, 0x77, 0xee, 0x33, 0x1f, 0x4e, 0x79, 0x35, 0x62,
+ 0xe9, 0x3e, 0x91, 0x2a, 0x01, 0x82, 0x24, 0xb8, 0x33, 0xac, 0x5f, 0xfe,
+ 0xf4, 0x33, 0x59, 0xc3, 0x34, 0x37, 0xd2, 0xc5, 0xfb, 0x35, 0x09, 0x3a,
+ 0xc5, 0x6c, 0x88, 0xd7, 0x19, 0x3a, 0x65, 0x4a, 0xbd, 0x2c, 0x87, 0x6e,
+ 0xe7, 0x9d, 0x1d, 0x3c, 0x30, 0xbf, 0x0b, 0x66, 0x86, 0x3d, 0xdb, 0x1d,
+ 0x22, 0xe0, 0x82, 0x48, 0xbf, 0xdf, 0x78, 0xbf, 0x3b, 0x46, 0x00, 0xd9,
+ 0x84, 0x33, 0x7d, 0x83, 0xfe, 0x2c, 0x5a, 0x33, 0x73, 0xf1, 0x24, 0xfb,
+ 0xfd, 0xc2, 0xcf, 0x47, 0x67, 0x96, 0x2f, 0xbb, 0x4f, 0xa5, 0x62, 0xf7,
+ 0x66, 0xd2, 0xc5, 0xf6, 0x7c, 0xb1, 0x62, 0xb0, 0xf0, 0x38, 0x3f, 0x50,
+ 0x47, 0x36, 0x15, 0xb9, 0xb7, 0x99, 0x2d, 0xdc, 0xb1, 0x7e, 0x63, 0xe7,
+ 0x5e, 0x58, 0xbf, 0xcc, 0x5b, 0x98, 0x17, 0xb8, 0xb1, 0x5b, 0x1f, 0xae,
+ 0x0a, 0x88, 0xa6, 0xff, 0x7b, 0x52, 0x5b, 0x3e, 0xeb, 0x17, 0xb6, 0x98,
+ 0xf5, 0x8a, 0x58, 0xbf, 0xfb, 0x0b, 0x39, 0xc6, 0xd7, 0x50, 0xe2, 0xc5,
+ 0xfe, 0xce, 0xbd, 0xfc, 0x16, 0xeb, 0x15, 0xba, 0x21, 0xdc, 0x30, 0x91,
+ 0x6f, 0xff, 0x39, 0xbc, 0x7c, 0x20, 0x0f, 0x4d, 0xba, 0xc5, 0x61, 0xfd,
+ 0x7c, 0xbe, 0xff, 0xbe, 0xe5, 0xb1, 0x63, 0xec, 0xb1, 0x7f, 0xfd, 0x8e,
+ 0x0e, 0x19, 0x87, 0x0f, 0xed, 0xf9, 0x58, 0xbf, 0xff, 0xf8, 0x53, 0xb7,
+ 0x50, 0xe1, 0x64, 0x46, 0x6f, 0xf9, 0xdc, 0xdd, 0x30, 0x4b, 0x17, 0xfc,
+ 0x07, 0x8b, 0x8f, 0xf7, 0x3a, 0xc5, 0xff, 0xfe, 0xcf, 0x73, 0xf8, 0x23,
+ 0xf0, 0xf8, 0x51, 0x7b, 0x52, 0xb1, 0x7f, 0x1c, 0xb0, 0x26, 0x02, 0xc5,
+ 0xe8, 0x38, 0x16, 0x2e, 0xcf, 0x2c, 0x56, 0x1f, 0x17, 0x0b, 0xa3, 0x87,
+ 0x6f, 0xf4, 0xff, 0x22, 0x83, 0x6c, 0xb1, 0x7f, 0xf8, 0xb3, 0x85, 0x86,
+ 0xf3, 0xf2, 0x5e, 0x58, 0xbf, 0xf8, 0xb3, 0xa8, 0x70, 0x6f, 0xda, 0x46,
+ 0xb1, 0x5b, 0x2e, 0x1e, 0x0e, 0x32, 0x2d, 0xc8, 0x74, 0x72, 0x75, 0x10,
+ 0x3d, 0x91, 0xd7, 0xa1, 0x88, 0x23, 0x1e, 0xc6, 0xbd, 0xc9, 0x37, 0xe7,
+ 0xf4, 0xfb, 0x8b, 0x14, 0xb1, 0x7f, 0x75, 0xc6, 0x21, 0x62, 0xc5, 0x39,
+ 0xba, 0x60, 0xcb, 0xe7, 0xd3, 0x01, 0x62, 0xa0, 0x8a, 0x30, 0x31, 0x70,
+ 0x7e, 0xfd, 0x85, 0xe3, 0x31, 0x62, 0xff, 0x02, 0x7b, 0x37, 0xfe, 0xeb,
+ 0x15, 0x18, 0x88, 0xde, 0x18, 0x78, 0xa2, 0xff, 0x19, 0x9f, 0x7d, 0x7d,
+ 0x96, 0x2f, 0xfb, 0x82, 0xd6, 0x9e, 0x5f, 0x4b, 0x17, 0xfd, 0xed, 0x0a,
+ 0x2c, 0xdc, 0xa5, 0x62, 0xa5, 0x7c, 0xa3, 0x27, 0x1c, 0x5a, 0x3d, 0xc0,
+ 0x19, 0xf8, 0xd0, 0x47, 0x36, 0x8f, 0x58, 0xbe, 0x2e, 0xa2, 0x95, 0x8b,
+ 0x9a, 0x3d, 0x62, 0xff, 0x3f, 0x5e, 0x66, 0x3f, 0x16, 0x2f, 0xfa, 0x73,
+ 0xa9, 0x68, 0x34, 0x16, 0x2f, 0xec, 0x01, 0x85, 0x80, 0x58, 0xb8, 0xfb,
+ 0xac, 0x50, 0xcf, 0x1d, 0x8b, 0xaf, 0xfd, 0x81, 0x18, 0xc3, 0x78, 0x9e,
+ 0x56, 0x2f, 0xd2, 0x5e, 0x90, 0x2c, 0x5e, 0xf0, 0x19, 0x62, 0xe9, 0xd9,
+ 0x62, 0xb4, 0x7b, 0x87, 0x27, 0xee, 0x1d, 0xbf, 0xfd, 0xa3, 0x94, 0xf4,
+ 0x1e, 0xbd, 0xc6, 0x3a, 0xc5, 0xec, 0x68, 0xf5, 0x8a, 0xc3, 0xec, 0x24,
+ 0xdb, 0xff, 0x7d, 0xc8, 0x01, 0xff, 0xed, 0xb2, 0xc5, 0xfa, 0x42, 0x0f,
+ 0xf2, 0xb1, 0x51, 0xba, 0xae, 0xc9, 0x15, 0xd8, 0x92, 0x03, 0x43, 0x34,
+ 0xc7, 0xfd, 0x10, 0xb4, 0x27, 0x39, 0x09, 0xef, 0x10, 0x06, 0x83, 0x7f,
+ 0x11, 0x37, 0x68, 0xa5, 0x62, 0xff, 0xb3, 0xff, 0x68, 0x7b, 0x3e, 0xb1,
+ 0x7e, 0x2c, 0xfb, 0x79, 0x62, 0xf1, 0x9c, 0xdd, 0x62, 0xa3, 0xcf, 0x1f,
+ 0xe4, 0xf7, 0xdd, 0x40, 0x51, 0xeb, 0x17, 0xfd, 0x81, 0x7f, 0x00, 0x79,
+ 0xd2, 0xc5, 0xfe, 0x76, 0x06, 0xb4, 0x2f, 0xac, 0x5f, 0xd2, 0x6e, 0x13,
+ 0x9a, 0xb1, 0x7f, 0x67, 0xbb, 0xbd, 0x9f, 0x58, 0xa9, 0x4f, 0x26, 0x05,
+ 0xf9, 0x08, 0x07, 0x25, 0xd1, 0x47, 0xce, 0x88, 0xd3, 0x85, 0xd7, 0xf6,
+ 0xd1, 0x4f, 0x05, 0xd2, 0xc5, 0xc2, 0xfa, 0xc5, 0xfe, 0x0c, 0x98, 0xdd,
+ 0x6a, 0x56, 0x2a, 0x4f, 0xff, 0x63, 0x26, 0x18, 0xbf, 0xff, 0x46, 0x69,
+ 0x89, 0xfd, 0x19, 0xa9, 0xf1, 0x30, 0x16, 0x2f, 0x9b, 0xee, 0x35, 0x8a,
+ 0xdc, 0xff, 0x3c, 0xb5, 0x68, 0x2c, 0x5f, 0xdf, 0x2c, 0x19, 0x32, 0xc5,
+ 0x46, 0x86, 0xf9, 0x84, 0xaf, 0x36, 0x12, 0xc5, 0xdd, 0x41, 0x62, 0xff,
+ 0xc5, 0x20, 0x6f, 0x00, 0x32, 0x82, 0xc5, 0x74, 0x7b, 0x1e, 0x19, 0xb0,
+ 0x4b, 0x17, 0xcf, 0x13, 0xca, 0xc5, 0xb8, 0xb1, 0x43, 0x36, 0x98, 0x45,
+ 0x7e, 0xcf, 0x47, 0x67, 0x96, 0x2c, 0x63, 0x1e, 0x59, 0x10, 0x5f, 0x14,
+ 0x9e, 0x56, 0x2c, 0xfa, 0x3c, 0x8f, 0x13, 0xdf, 0xff, 0xd9, 0xbf, 0x77,
+ 0x85, 0xd4, 0x39, 0xcf, 0x4c, 0xfb, 0x8b, 0x17, 0xf7, 0x45, 0x9e, 0xc0,
+ 0x2c, 0x57, 0x11, 0x20, 0x26, 0x2b, 0xf7, 0xa6, 0x7d, 0xc5, 0x8b, 0xe9,
+ 0x9f, 0x71, 0x62, 0xf7, 0x50, 0xe7, 0x0f, 0x2b, 0xc5, 0x15, 0x88, 0xa2,
+ 0x13, 0x6d, 0x3a, 0xa5, 0x5f, 0xc3, 0x6b, 0xd1, 0xac, 0xd4, 0x6e, 0xeb,
+ 0xdb, 0x63, 0x46, 0x48, 0xda, 0x18, 0x53, 0x2a, 0x9f, 0x68, 0x4d, 0x42,
+ 0x32, 0x21, 0xc7, 0x39, 0x93, 0x8c, 0xa6, 0xc2, 0x57, 0x78, 0xe0, 0xfa,
+ 0x8e, 0x4d, 0xe1, 0x4d, 0x14, 0xa4, 0xad, 0x4b, 0x83, 0x3c, 0x2f, 0xbf,
+ 0x2f, 0xcd, 0xa5, 0x01, 0x02, 0x16, 0x05, 0x3e, 0xaf, 0xc9, 0x6a, 0x3e,
+ 0x94, 0xe2, 0x28, 0x79, 0x76, 0x85, 0x50, 0x4c, 0x31, 0xc4, 0xa1, 0xb9,
+ 0xf7, 0x4a, 0x78, 0xbf, 0xc5, 0x82, 0xef, 0xf9, 0x9a, 0x58, 0xbb, 0xff,
+ 0x58, 0xa1, 0x9e, 0x80, 0x67, 0x17, 0x77, 0x7d, 0x62, 0xfd, 0xad, 0xd9,
+ 0xb7, 0x54, 0x85, 0xc5, 0xed, 0x0b, 0xeb, 0x17, 0xff, 0x0b, 0x5a, 0xc1,
+ 0xc1, 0xe3, 0xbe, 0x25, 0x8b, 0xf7, 0x80, 0x19, 0x41, 0x22, 0xfd, 0xcf,
0x7e, 0x40, 0xb1, 0x7e, 0x6d, 0xa7, 0x42, 0x58, 0xb9, 0x8e, 0xb1, 0x68,
- 0xc9, 0x4d, 0xab, 0x61, 0xfc, 0x1a, 0xd1, 0xb9, 0xc7, 0x99, 0x24, 0x45,
- 0x51, 0xc5, 0x26, 0x14, 0xdf, 0x88, 0x50, 0xce, 0x2c, 0x5e, 0x26, 0xdd,
- 0x62, 0xf4, 0x73, 0x81, 0x62, 0xf6, 0x3f, 0xd6, 0x2f, 0x11, 0x0d, 0x62,
- 0xfb, 0x30, 0xbc, 0xb1, 0x7a, 0x5b, 0x75, 0x8b, 0xa1, 0x19, 0x88, 0xdb,
- 0x34, 0xa1, 0xc7, 0x7e, 0x40, 0x43, 0x9c, 0x1c, 0xf1, 0x0d, 0x46, 0x2e,
- 0x9e, 0x42, 0x5b, 0x37, 0x71, 0xb2, 0xdf, 0xff, 0x61, 0x38, 0xe3, 0x38,
- 0x58, 0x3f, 0xe6, 0x96, 0x2f, 0xfe, 0x3b, 0x42, 0x33, 0x35, 0xbb, 0x36,
- 0xea, 0x89, 0x98, 0xbe, 0x8c, 0x8d, 0x58, 0xcb, 0x17, 0xff, 0x0e, 0x30,
- 0x84, 0xc6, 0x0f, 0xee, 0x6a, 0xc5, 0xff, 0xe0, 0xa0, 0x1b, 0xde, 0xfe,
- 0x11, 0x37, 0x96, 0x2f, 0x7d, 0xf8, 0xb1, 0x7c, 0x15, 0xe4, 0xf9, 0x62,
- 0xfe, 0x9e, 0x14, 0xfb, 0x8b, 0x14, 0x16, 0xcf, 0x50, 0xe4, 0xf5, 0x1b,
- 0xa3, 0x9a, 0x34, 0x4d, 0x8d, 0x4e, 0x37, 0xef, 0x68, 0x53, 0xd1, 0x62,
- 0xff, 0xc6, 0xce, 0x6b, 0xae, 0x0b, 0x5b, 0x2c, 0x5d, 0x27, 0x58, 0xbf,
- 0x61, 0x77, 0xe0, 0xa2, 0xc5, 0xc1, 0xec, 0xb1, 0x41, 0x54, 0x66, 0x46,
- 0xa2, 0xb8, 0x21, 0xe0, 0xbf, 0x65, 0xb6, 0xe8, 0xb1, 0x76, 0xb6, 0x58,
- 0xbf, 0x3f, 0x79, 0x9b, 0x2c, 0x50, 0x8f, 0x0b, 0xa0, 0xcd, 0x0c, 0xfe,
- 0xb1, 0x5a, 0xe8, 0xe8, 0xdd, 0x62, 0xe0, 0xfc, 0xb1, 0x51, 0xb1, 0xed,
- 0x05, 0xb2, 0x11, 0x90, 0x5f, 0x46, 0xe1, 0x5e, 0x4a, 0xc5, 0xe8, 0xde,
- 0x35, 0xc6, 0xb5, 0x8b, 0x05, 0xac, 0x6e, 0x7b, 0x61, 0x61, 0x65, 0xa2,
- 0x58, 0xba, 0x78, 0xb1, 0x74, 0x6d, 0x05, 0x8b, 0x8c, 0xe2, 0xc5, 0x05,
- 0xb4, 0x4c, 0xec, 0x73, 0xd8, 0x9c, 0x42, 0xfe, 0x1d, 0xb9, 0xb8, 0xb1,
- 0x7f, 0x9b, 0xbe, 0x31, 0x0b, 0x16, 0x2f, 0xfd, 0x0c, 0xff, 0xda, 0x0e,
- 0xe4, 0xb1, 0x5a, 0x44, 0x38, 0x05, 0xfc, 0x67, 0x74, 0x74, 0x6e, 0xb1,
- 0x7e, 0xe3, 0x93, 0x6c, 0xb1, 0x7f, 0xef, 0xbf, 0xb8, 0xdd, 0xed, 0x81,
- 0xac, 0x5f, 0xfb, 0xa4, 0xfd, 0xe6, 0x28, 0xa7, 0x75, 0x8a, 0x0a, 0xa3,
- 0xf6, 0x36, 0x30, 0x0b, 0x08, 0x37, 0x28, 0x74, 0x2b, 0xa3, 0xa3, 0x75,
- 0x8b, 0x9c, 0xeb, 0x17, 0xef, 0x13, 0xf7, 0xe5, 0x8a, 0x0b, 0x0f, 0x83,
- 0x72, 0x03, 0x05, 0xef, 0xfa, 0x37, 0x01, 0xcc, 0xd3, 0xed, 0x2b, 0x16,
- 0x89, 0x62, 0xfd, 0x23, 0x30, 0x1c, 0x58, 0xb4, 0x6f, 0xf3, 0x7a, 0x42,
- 0x77, 0xf7, 0x3f, 0x27, 0x71, 0xac, 0x5c, 0xc4, 0xb1, 0x5c, 0x3c, 0x4f,
- 0x17, 0x5c, 0xc3, 0x58, 0xa8, 0xdd, 0x15, 0x11, 0xb3, 0x78, 0x58, 0x45,
- 0x7c, 0x14, 0x8d, 0x7c, 0x95, 0x8b, 0x09, 0x62, 0x82, 0xd4, 0xdf, 0xb9,
- 0x6d, 0xe0, 0xb7, 0x1a, 0xe3, 0x5a, 0xc5, 0xde, 0xc5, 0x8a, 0x8d, 0x67,
- 0x8f, 0xd9, 0x85, 0xd1, 0xd1, 0xba, 0xc5, 0xff, 0xff, 0xfc, 0x17, 0xee,
- 0x42, 0xc0, 0xb6, 0x3d, 0xfa, 0x6a, 0x11, 0x74, 0x10, 0x5a, 0xc6, 0xa0,
- 0xbc, 0x6b, 0x0b, 0x5e, 0xbd, 0x7f, 0x1c, 0xb1, 0x7f, 0xd3, 0xb6, 0x9b,
- 0xf2, 0x77, 0x58, 0xbb, 0x3e, 0xb1, 0x44, 0x7a, 0x1e, 0x39, 0xbf, 0xff,
- 0xe7, 0xf1, 0x9a, 0x9f, 0xce, 0x6e, 0x37, 0x2d, 0x8f, 0x30, 0x58, 0xbc,
- 0x09, 0x02, 0xc5, 0xff, 0x60, 0x65, 0x86, 0xfd, 0xa3, 0xd6, 0x2b, 0x0f,
- 0x68, 0x87, 0x6f, 0x76, 0xe7, 0x58, 0xbf, 0x9a, 0x2c, 0xe9, 0x3c, 0x58,
- 0xaf, 0x9e, 0x71, 0x0f, 0x5f, 0xdc, 0xd4, 0xe7, 0xb8, 0xb1, 0x61, 0x2c,
- 0x54, 0x9e, 0x06, 0x17, 0x5f, 0xf7, 0x24, 0xcf, 0xbc, 0x24, 0xeb, 0x17,
- 0xe0, 0x38, 0xf2, 0x3d, 0x62, 0xfe, 0x1b, 0x1f, 0x53, 0xc5, 0x8a, 0xc3,
- 0xd9, 0x62, 0xbb, 0xff, 0x74, 0x13, 0x6e, 0x37, 0xe9, 0x23, 0x58, 0xbf,
- 0xa4, 0xed, 0x09, 0xf2, 0xc5, 0xff, 0xd2, 0x76, 0xf6, 0x76, 0x03, 0x99,
- 0xf5, 0x8b, 0xff, 0xdb, 0xe8, 0x5b, 0x77, 0xc7, 0xd6, 0xff, 0xc5, 0x8b,
- 0xc0, 0x33, 0xcb, 0x17, 0xcf, 0xd1, 0x80, 0xb1, 0x52, 0x89, 0x3c, 0x50,
- 0xf0, 0xfd, 0xff, 0xd9, 0xf6, 0x1f, 0xdf, 0xa9, 0xf3, 0x75, 0x8a, 0x1a,
- 0x7c, 0x18, 0x40, 0x6a, 0x27, 0xcb, 0x4a, 0x1b, 0x5c, 0x2e, 0xbe, 0x7d,
- 0x84, 0x4b, 0x17, 0xec, 0xdb, 0x01, 0x12, 0xc5, 0x75, 0x3c, 0xdf, 0x11,
- 0xdf, 0x9c, 0x21, 0xaf, 0xba, 0xc5, 0xff, 0x0a, 0x1c, 0x63, 0xb1, 0x01,
- 0x62, 0xe7, 0xf2, 0xc5, 0xb7, 0x58, 0xae, 0xa6, 0xa8, 0x2a, 0x2f, 0x5a,
- 0x45, 0xb3, 0x16, 0x01, 0x8e, 0xfc, 0x09, 0xe6, 0x76, 0xb1, 0x7d, 0xd5,
- 0xda, 0x25, 0x8a, 0xd1, 0xe7, 0x70, 0xa6, 0xc7, 0x58, 0xa9, 0x36, 0x83,
- 0x22, 0xbf, 0xdd, 0x70, 0x9b, 0x40, 0x8e, 0x58, 0xb8, 0xa0, 0xb1, 0x7b,
- 0x52, 0x6a, 0xc5, 0xff, 0xf3, 0x7f, 0x3b, 0x07, 0xc3, 0x6f, 0xc5, 0xf1,
- 0x2c, 0x53, 0xa2, 0x26, 0x21, 0x73, 0x8f, 0x5f, 0xe1, 0xe9, 0x80, 0xd9,
- 0xa5, 0x8b, 0xfb, 0x39, 0x26, 0x14, 0xac, 0x5d, 0xc3, 0xac, 0x50, 0xd3,
- 0x69, 0xc8, 0x60, 0xb9, 0x87, 0xcc, 0xc4, 0x5b, 0x6c, 0x58, 0xb9, 0x8e,
- 0xb1, 0x5c, 0x35, 0x01, 0x04, 0x6e, 0x09, 0xe5, 0x8b, 0x05, 0xd6, 0x2c,
- 0x09, 0x36, 0x02, 0x1a, 0xbc, 0x76, 0xf2, 0xc5, 0x82, 0xeb, 0x17, 0xf4,
- 0xf4, 0x9f, 0x37, 0x16, 0x2b, 0x0f, 0x88, 0x87, 0x78, 0x2d, 0x7f, 0xee,
- 0xff, 0x9c, 0x9e, 0x71, 0xbe, 0xb1, 0x7e, 0x8e, 0x19, 0x30, 0x6b, 0x17,
- 0xff, 0x8f, 0xd7, 0x59, 0xe6, 0xef, 0xaf, 0xb0, 0x0b, 0x15, 0x28, 0xe9,
- 0x62, 0xdf, 0x20, 0x08, 0xb2, 0xff, 0x13, 0x6d, 0x25, 0x20, 0x58, 0xbf,
- 0xff, 0xb7, 0x29, 0x3f, 0x59, 0xd6, 0x9f, 0xa6, 0x99, 0x80, 0xb1, 0x7e,
- 0x83, 0x79, 0x8d, 0x58, 0xa9, 0x44, 0x46, 0x2f, 0xdf, 0x16, 0x02, 0x56,
- 0x28, 0x8f, 0x0b, 0xa1, 0x0d, 0xe1, 0xe0, 0xd6, 0x29, 0x62, 0xfb, 0x3d,
- 0x80, 0x58, 0xb1, 0xa0, 0x35, 0xc4, 0x19, 0x58, 0x7e, 0x4c, 0x97, 0x7f,
- 0x38, 0x6f, 0xcc, 0xdd, 0x62, 0x9d, 0x1c, 0x9a, 0x84, 0xaf, 0x08, 0x2f,
- 0x7a, 0x60, 0xb1, 0x7f, 0xed, 0x84, 0xd1, 0x63, 0xe8, 0x51, 0xeb, 0x17,
- 0x0a, 0x0b, 0x14, 0xe7, 0xf2, 0xc3, 0xbd, 0x11, 0x2f, 0x1e, 0x60, 0xb1,
- 0x7c, 0xfd, 0x27, 0x4b, 0x17, 0xb8, 0xd1, 0x2c, 0x54, 0x9e, 0xff, 0xc7,
- 0x7c, 0x49, 0x7f, 0x46, 0x44, 0x15, 0xfb, 0x12, 0xc5, 0x46, 0xec, 0xf3,
- 0x00, 0xb6, 0x41, 0xb4, 0x63, 0x50, 0x21, 0x1c, 0x30, 0xb1, 0xbb, 0x76,
- 0x1e, 0xc8, 0x1e, 0x53, 0x9c, 0x50, 0xa9, 0xd4, 0x36, 0x8f, 0x0b, 0x1f,
- 0xc7, 0x12, 0xce, 0xc0, 0x53, 0x28, 0xdc, 0x78, 0x77, 0xe8, 0xf8, 0x3a,
- 0x42, 0xb4, 0xc8, 0x47, 0x04, 0x2e, 0xbe, 0x68, 0x18, 0x75, 0x8b, 0xdb,
- 0x90, 0x16, 0x2d, 0xad, 0x1e, 0x17, 0x09, 0x2f, 0x31, 0x6e, 0xb1, 0x7b,
- 0xc5, 0x2b, 0x17, 0xc4, 0x59, 0xe5, 0x8b, 0xc5, 0x9d, 0xac, 0x5b, 0xb5,
- 0x8b, 0xe6, 0x33, 0x36, 0x58, 0xac, 0x36, 0xff, 0x13, 0xa0, 0xaa, 0x2c,
- 0x64, 0x73, 0x62, 0x11, 0xaa, 0x57, 0x13, 0x0f, 0x0e, 0x19, 0xd7, 0xcd,
- 0xf7, 0x89, 0x62, 0xf8, 0xa2, 0x91, 0xac, 0x5d, 0xdf, 0x96, 0x2f, 0xbf,
- 0x14, 0x8d, 0x62, 0xf0, 0x54, 0x52, 0xb1, 0x7b, 0x5b, 0x0d, 0x62, 0xfb,
- 0x00, 0x67, 0x96, 0x2f, 0xda, 0x93, 0x18, 0x96, 0x28, 0x67, 0xd7, 0xd8,
- 0xf8, 0x09, 0x2a, 0x55, 0x50, 0x64, 0x66, 0xfb, 0x95, 0x39, 0x1c, 0x44,
- 0x6c, 0x32, 0x02, 0x41, 0x42, 0x32, 0xfc, 0x43, 0xf9, 0x91, 0xcb, 0x17,
- 0xfe, 0x6c, 0x08, 0xfa, 0x34, 0x59, 0xf5, 0x8b, 0xdf, 0x9e, 0xd6, 0x2f,
- 0xd2, 0x72, 0xc8, 0x96, 0x2f, 0xe7, 0xc2, 0x1f, 0xe5, 0x62, 0xc7, 0x58,
- 0xb1, 0xd6, 0x2e, 0x92, 0x58, 0xad, 0x8d, 0x40, 0x62, 0x57, 0xbf, 0x91,
- 0x2c, 0x50, 0xd1, 0x9f, 0xb9, 0x44, 0x79, 0x67, 0x0e, 0xbc, 0x47, 0x4b,
- 0x17, 0xde, 0xfb, 0x8d, 0x62, 0x96, 0x2d, 0x24, 0x6b, 0xf8, 0x47, 0x7f,
- 0x6a, 0x48, 0x59, 0xf5, 0x8b, 0xfe, 0x6e, 0xf1, 0xf7, 0xdd, 0x86, 0xb1,
- 0x7d, 0xa9, 0xc2, 0x58, 0xbe, 0x6f, 0x40, 0x0b, 0x17, 0xbd, 0xcc, 0x58,
- 0xa5, 0x8b, 0xf1, 0x64, 0x4f, 0xb2, 0xc5, 0x85, 0xd9, 0xb5, 0x38, 0x65,
- 0x84, 0xb1, 0x7f, 0x9f, 0x76, 0xcd, 0x67, 0x96, 0x28, 0x07, 0x8b, 0xc1,
- 0x2b, 0xc2, 0x8d, 0xc9, 0x62, 0x8d, 0x4f, 0x53, 0x72, 0x5d, 0x16, 0x9c,
- 0xef, 0xe4, 0x2c, 0x47, 0xc5, 0x2f, 0x36, 0x84, 0x22, 0xbf, 0xed, 0x4e,
- 0x42, 0x7f, 0x20, 0x58, 0xbf, 0xfd, 0xd7, 0xec, 0xfe, 0x00, 0x88, 0x9a,
- 0x0b, 0x17, 0xff, 0x9f, 0x82, 0x3e, 0x6f, 0xf9, 0x2f, 0x71, 0x62, 0xf4,
- 0x04, 0x35, 0x8b, 0x3c, 0x0f, 0xa6, 0x24, 0xbb, 0xfe, 0x30, 0xf9, 0xc6,
- 0x6e, 0xe0, 0xb1, 0x74, 0x6e, 0x15, 0x58, 0xbf, 0xef, 0xcb, 0x8d, 0xf9,
- 0xb3, 0x2c, 0x50, 0x58, 0x7b, 0x4e, 0x43, 0x52, 0xbc, 0x13, 0xb1, 0x6c,
- 0x10, 0x72, 0x1d, 0xbb, 0xa7, 0x3c, 0xa0, 0xfd, 0x42, 0x08, 0xe7, 0x1f,
- 0x85, 0xa0, 0x0a, 0x0a, 0x12, 0xb7, 0xff, 0xff, 0xff, 0xff, 0x82, 0xc0,
- 0xae, 0x05, 0x91, 0xb0, 0x5b, 0x0b, 0x7b, 0x85, 0xe6, 0x35, 0xc6, 0xda,
- 0xd8, 0x26, 0x08, 0x61, 0x6b, 0x31, 0xdd, 0x99, 0xf8, 0xda, 0x66, 0x36,
- 0x8f, 0x8d, 0x5e, 0xeb, 0xd7, 0xf1, 0xcb, 0x17, 0xfc, 0x43, 0x89, 0xcb,
- 0xb8, 0x71, 0x62, 0xff, 0xfb, 0x5f, 0x0d, 0x87, 0x9b, 0x0b, 0xda, 0xd4,
- 0xac, 0x5f, 0xfe, 0x87, 0xc5, 0x3a, 0x8c, 0xfb, 0xee, 0xda, 0x58, 0xbf,
- 0x19, 0xae, 0x31, 0x2c, 0x57, 0x67, 0xf1, 0xf4, 0xfa, 0x94, 0xca, 0x58,
- 0xec, 0x10, 0xcb, 0xbf, 0xc6, 0x45, 0xc9, 0xf4, 0x8d, 0x62, 0xdc, 0x58,
- 0xbc, 0x2d, 0x01, 0x62, 0xe1, 0x43, 0xa9, 0xb0, 0xdc, 0x4a, 0xff, 0xdf,
- 0xc2, 0xc3, 0x70, 0xb0, 0x6b, 0x17, 0xfe, 0x0e, 0x7c, 0x37, 0x8f, 0xe4,
- 0x9d, 0x62, 0xfe, 0xfb, 0xf8, 0xa4, 0xeb, 0x15, 0xd9, 0xf8, 0x12, 0x1d,
- 0xf7, 0x33, 0xbf, 0x2c, 0x5e, 0x8a, 0x43, 0x58, 0xbe, 0x6e, 0x38, 0xd6,
- 0x2b, 0x0f, 0x04, 0x31, 0xfb, 0xf0, 0xff, 0x25, 0xb2, 0xc5, 0xf3, 0x97,
- 0xb8, 0xb1, 0x7f, 0xff, 0xc7, 0x7d, 0x7c, 0x5c, 0x84, 0xf4, 0xd4, 0x97,
- 0xbf, 0x90, 0x58, 0xa8, 0x22, 0x2d, 0xc8, 0xaf, 0xfc, 0xfe, 0x7d, 0xdc,
- 0x7e, 0xcd, 0xd6, 0x2b, 0x65, 0x53, 0x90, 0x30, 0xc8, 0x56, 0xe8, 0x8b,
- 0xec, 0xa4, 0x45, 0xe8, 0x5a, 0x04, 0x22, 0xb8, 0xe3, 0x58, 0xbf, 0x13,
- 0x69, 0xa0, 0xb1, 0x73, 0xf4, 0x58, 0xbf, 0xc4, 0x3f, 0xc9, 0xc2, 0x09,
- 0x62, 0xa4, 0xfd, 0x86, 0x4e, 0xc3, 0x37, 0xa4, 0x72, 0xb1, 0x7e, 0xcf,
- 0xff, 0x00, 0xb1, 0x6d, 0xce, 0x78, 0x84, 0x39, 0x7c, 0xc1, 0xb4, 0x7a,
- 0xc5, 0x31, 0xe7, 0x11, 0x45, 0xf8, 0x5b, 0xfd, 0xc3, 0x58, 0xbe, 0xf4,
- 0x76, 0x7d, 0x62, 0xfe, 0x0f, 0xaf, 0xb9, 0x81, 0xac, 0x5f, 0xb6, 0x83,
- 0x96, 0x2c, 0x5f, 0xff, 0xe6, 0x2d, 0xcb, 0x07, 0xf1, 0x75, 0xfc, 0xc3,
- 0x53, 0xb2, 0xc5, 0x62, 0x39, 0x5c, 0x99, 0x8c, 0xc4, 0x51, 0x74, 0xfd,
- 0x62, 0xfe, 0x30, 0xa7, 0xf3, 0x05, 0x8b, 0xff, 0xf8, 0xd2, 0xc0, 0x0b,
- 0x9d, 0x60, 0xff, 0x9d, 0xc9, 0x96, 0x2f, 0xdc, 0x98, 0xfd, 0x4a, 0xc5,
- 0x1a, 0x8c, 0xe3, 0x8b, 0xb1, 0x70, 0x17, 0xaf, 0xf9, 0xf7, 0x8a, 0x1f,
- 0x92, 0x35, 0x62, 0xfe, 0xdf, 0xaf, 0xd8, 0x9d, 0x62, 0xf4, 0x9f, 0xcb,
- 0x14, 0x48, 0x89, 0x11, 0xe0, 0x66, 0x17, 0xfb, 0x03, 0x9f, 0x13, 0x71,
- 0x62, 0xfc, 0x58, 0x76, 0x82, 0xc5, 0xff, 0xff, 0xb9, 0xc9, 0x01, 0x87,
- 0xe3, 0xe1, 0x0a, 0x19, 0xc0, 0xdb, 0xb5, 0x8a, 0x35, 0x12, 0xc1, 0x93,
- 0xde, 0x7f, 0xba, 0xc5, 0x4a, 0x67, 0x4e, 0x60, 0xd0, 0xc9, 0xf1, 0x2d,
- 0xd2, 0x4b, 0x17, 0xd9, 0xb8, 0xf1, 0x62, 0xe9, 0xd2, 0xc5, 0x2c, 0x40,
- 0xb7, 0xbf, 0x30, 0xff, 0x24, 0xb1, 0x7c, 0x43, 0x33, 0xb5, 0x8b, 0xf3,
- 0xec, 0x79, 0xdd, 0x62, 0xe1, 0x79, 0x62, 0xf3, 0x6a, 0x1d, 0x51, 0xc6,
- 0xe7, 0x47, 0x1b, 0x62, 0x7f, 0x12, 0xc7, 0x15, 0x54, 0x6c, 0xcd, 0x36,
- 0x99, 0x4b, 0x23, 0x34, 0xc9, 0x60, 0x46, 0xbf, 0x3c, 0x23, 0xb5, 0x0b,
- 0xf3, 0x90, 0x7e, 0x31, 0x06, 0x8c, 0x20, 0xa5, 0x00, 0x79, 0x00, 0x50,
- 0xf9, 0xbf, 0xc6, 0xb7, 0x4d, 0xf3, 0xbf, 0x2c, 0x5c, 0xc3, 0x58, 0xbb,
- 0xa4, 0x7a, 0xc5, 0xff, 0x02, 0x60, 0x31, 0x36, 0xa0, 0xb1, 0x46, 0xa2,
- 0x9f, 0x47, 0x2c, 0x2e, 0x43, 0xb7, 0xff, 0xed, 0x69, 0xf3, 0xa1, 0x0b,
- 0x9d, 0x78, 0x26, 0xe2, 0xc5, 0x2c, 0x5f, 0xff, 0x71, 0xe3, 0xb3, 0x7f,
- 0xb9, 0x10, 0xb5, 0xb2, 0xc5, 0x68, 0xf8, 0x3c, 0x19, 0x7f, 0x7b, 0x0f,
- 0xde, 0x1d, 0x62, 0xa5, 0x30, 0xbc, 0x85, 0xd3, 0x91, 0x5f, 0xe3, 0x9d,
- 0xa1, 0xc7, 0x82, 0xc5, 0xfe, 0x37, 0xac, 0xf6, 0x0d, 0x4a, 0xc5, 0x61,
- 0xf6, 0x31, 0xa5, 0x3a, 0xa0, 0x6f, 0xc6, 0x8e, 0x50, 0x9f, 0xbf, 0xe0,
- 0xc9, 0x8d, 0xc1, 0xb9, 0x2c, 0x5f, 0xfe, 0xe9, 0x83, 0xfc, 0xf4, 0x3c,
- 0x93, 0x18, 0xb1, 0x68, 0x96, 0x2b, 0x0f, 0x84, 0x49, 0xd7, 0x0d, 0xd6,
- 0x2f, 0xef, 0xb8, 0x72, 0x43, 0x58, 0xb4, 0x30, 0xf1, 0x77, 0x17, 0xbf,
- 0x86, 0xd0, 0xe3, 0xc1, 0x62, 0xa5, 0x35, 0x6d, 0x42, 0x69, 0x99, 0x84,
- 0x51, 0x7c, 0x22, 0xf7, 0x16, 0x2f, 0xee, 0x09, 0xc9, 0xf8, 0xb1, 0x7a,
- 0x75, 0x2b, 0x15, 0xd4, 0xf2, 0x7e, 0x5b, 0x74, 0xee, 0xb1, 0x5b, 0xa2,
- 0xa3, 0x4d, 0x81, 0x09, 0x2f, 0x42, 0x38, 0x35, 0x8b, 0x80, 0xeb, 0x17,
- 0xe3, 0xc3, 0xe6, 0x71, 0x62, 0xda, 0xea, 0x78, 0x46, 0x0b, 0xdf, 0x98,
- 0x32, 0xc1, 0xac, 0x54, 0xa2, 0xdd, 0xd9, 0x34, 0x57, 0x7f, 0xe2, 0x9d,
- 0xcd, 0x6c, 0xd3, 0x81, 0x62, 0xfe, 0xe6, 0x3e, 0xb4, 0xcb, 0x17, 0xee,
- 0x75, 0x03, 0x79, 0x62, 0xb6, 0x44, 0xb8, 0x0f, 0xfc, 0x5b, 0x74, 0xe9,
- 0x62, 0xff, 0xed, 0xb3, 0x8e, 0xdf, 0x8c, 0x0c, 0x30, 0xd2, 0x2c, 0xe0,
- 0x3e, 0x32, 0x17, 0xbf, 0xbb, 0x84, 0x4e, 0x20, 0xba, 0xc5, 0xfe, 0x6d,
- 0x47, 0x0b, 0xef, 0xa5, 0x8a, 0x93, 0xec, 0x11, 0xad, 0x4a, 0x68, 0xe3,
- 0x84, 0xa7, 0xe1, 0x25, 0x7d, 0xf1, 0x77, 0x05, 0x8b, 0xfb, 0xbc, 0xf8,
- 0xbb, 0x02, 0xc5, 0xbe, 0xb1, 0x7f, 0x1f, 0x9f, 0x92, 0xf2, 0xc5, 0xf6,
- 0xa7, 0xdc, 0x58, 0xbd, 0xb7, 0xc4, 0xb1, 0x7f, 0xef, 0xb7, 0x3f, 0x9d,
- 0x33, 0xdc, 0x58, 0xa9, 0x3e, 0x06, 0x1f, 0xa7, 0x46, 0x8c, 0x45, 0xdf,
- 0x84, 0x1d, 0xf9, 0xc5, 0xbb, 0xec, 0xb1, 0x50, 0x4e, 0x63, 0x09, 0x77,
- 0x31, 0xf4, 0x38, 0xe3, 0x8d, 0x6f, 0xff, 0x37, 0x85, 0xd7, 0x9f, 0x71,
- 0x94, 0xc7, 0xac, 0x5f, 0xec, 0x93, 0x5b, 0xcc, 0x6a, 0xc5, 0x01, 0x10,
- 0x64, 0x9f, 0x7e, 0x33, 0xdc, 0x9f, 0x2c, 0x5e, 0xdb, 0x84, 0xb1, 0x50,
- 0x3c, 0x8d, 0x15, 0x5f, 0xe3, 0xe6, 0xe4, 0xd9, 0xba, 0xc5, 0xc2, 0x89,
- 0x62, 0xe8, 0x72, 0x4f, 0x34, 0x06, 0x97, 0xc7, 0xe1, 0x9c, 0x58, 0xbf,
- 0x16, 0xc3, 0x9d, 0x2c, 0x5f, 0xfc, 0x28, 0xff, 0xb9, 0xe6, 0x3f, 0xf9,
- 0xb2, 0xc5, 0xed, 0xc5, 0xba, 0xc5, 0x4a, 0x6a, 0xdd, 0xb7, 0xb9, 0x6b,
- 0x12, 0x91, 0x48, 0x93, 0x2f, 0xfb, 0xde, 0x93, 0xe6, 0x11, 0xab, 0x17,
- 0xff, 0xde, 0xfe, 0x04, 0xf6, 0x7c, 0xb3, 0xdf, 0x75, 0x8a, 0xed, 0x11,
- 0x44, 0x73, 0x7f, 0x13, 0x7a, 0x12, 0x6a, 0xc5, 0xfe, 0xc0, 0x0c, 0x4d,
- 0xa8, 0x2c, 0x54, 0x9f, 0x16, 0xc5, 0xd7, 0xf3, 0x30, 0xfa, 0x60, 0xd6,
- 0x2c, 0x1a, 0xc5, 0xf3, 0xc7, 0xb7, 0x16, 0x2e, 0x6d, 0xd5, 0x16, 0x79,
- 0x7b, 0x08, 0x6b, 0x14, 0xe7, 0xf3, 0xf1, 0x36, 0x25, 0x0c, 0x96, 0xff,
- 0x49, 0x1b, 0xa1, 0x49, 0x2c, 0x5f, 0xc0, 0x62, 0x83, 0x9d, 0x62, 0xed,
- 0xdd, 0x62, 0xa5, 0x50, 0x16, 0xd0, 0x85, 0x19, 0x16, 0xf0, 0xa8, 0x73,
- 0xb0, 0x19, 0x88, 0xb6, 0xfc, 0x0c, 0xc0, 0xf8, 0xb1, 0x7f, 0xbf, 0xee,
- 0x37, 0x66, 0x1d, 0x62, 0xff, 0xf1, 0x7a, 0x3b, 0x22, 0x83, 0x6b, 0x61,
- 0xca, 0xc5, 0xfe, 0x98, 0x3f, 0xa7, 0xdc, 0x58, 0xbf, 0xdc, 0x11, 0xdf,
- 0xc0, 0x65, 0x8b, 0xc6, 0x7e, 0x56, 0x2a, 0x07, 0xa4, 0x03, 0x4b, 0xc3,
- 0x1b, 0x2c, 0x57, 0xd1, 0x88, 0x50, 0x85, 0xf1, 0x15, 0xfd, 0x03, 0x33,
- 0xed, 0xda, 0xc5, 0xff, 0xfe, 0x72, 0x13, 0x7b, 0xae, 0x0f, 0xae, 0x41,
- 0xcd, 0x35, 0x96, 0x2f, 0xde, 0x29, 0xce, 0xd6, 0x2b, 0xaa, 0xa6, 0x49,
- 0x29, 0xc3, 0x77, 0x8c, 0x4d, 0x8d, 0x38, 0x60, 0x63, 0x2d, 0xbc, 0xb1,
- 0x7f, 0xc6, 0xb1, 0x67, 0x42, 0xce, 0x2c, 0x5f, 0xdd, 0x0b, 0x39, 0x84,
- 0xb1, 0x7e, 0xee, 0x0f, 0x84, 0xb1, 0x68, 0xf5, 0x8a, 0xc3, 0xeb, 0xd1,
- 0x77, 0x0a, 0x2f, 0x3c, 0x25, 0x62, 0xcd, 0xd4, 0xf2, 0xb8, 0x5d, 0x6d,
- 0x1a, 0x98, 0xc7, 0xe1, 0xdf, 0x7f, 0x9c, 0x78, 0x70, 0xf3, 0xeb, 0x16,
- 0xd9, 0x62, 0xff, 0xff, 0xb3, 0xdc, 0xcd, 0xd8, 0x81, 0xd7, 0x52, 0x42,
- 0xf4, 0xfd, 0x62, 0xfd, 0xc1, 0xbc, 0x92, 0xc5, 0x4a, 0x35, 0x8e, 0x68,
- 0x42, 0x7e, 0x68, 0xbf, 0x16, 0x74, 0x7e, 0xd6, 0x2d, 0xa5, 0x8b, 0xff,
- 0x79, 0xe2, 0x0d, 0x87, 0x3d, 0xf1, 0x62, 0xb4, 0x7f, 0xcc, 0x55, 0xc1,
- 0x2a, 0x8d, 0xd5, 0x8b, 0xbc, 0x65, 0x4d, 0x18, 0x30, 0xa1, 0x73, 0x7d,
- 0x0e, 0x39, 0x2c, 0x5f, 0xff, 0x7e, 0x75, 0xd7, 0xf3, 0xb1, 0x0b, 0x61,
- 0x71, 0x62, 0xfa, 0x40, 0xc7, 0x58, 0xba, 0x1c, 0x94, 0x4c, 0x8c, 0x88,
- 0x95, 0x6e, 0x00, 0x16, 0x2f, 0x06, 0x18, 0x69, 0x17, 0xfd, 0x0e, 0x16,
- 0x6e, 0x3c, 0xd2, 0x44, 0x61, 0xa1, 0xb4, 0x16, 0x2f, 0xfb, 0xd9, 0xad,
- 0xa7, 0xa3, 0x1d, 0x62, 0xa5, 0x30, 0xe7, 0x3a, 0x63, 0x9f, 0x26, 0x98,
- 0x25, 0x7f, 0x87, 0xf9, 0x29, 0xc0, 0xd6, 0x2f, 0xfb, 0xec, 0x7f, 0xc8,
- 0xde, 0x56, 0x2a, 0x07, 0xd7, 0xe3, 0x3b, 0xf7, 0x5c, 0xfc, 0x8d, 0x62,
- 0xfc, 0x10, 0x47, 0xc1, 0xac, 0x5f, 0xfe, 0x37, 0xf3, 0x9d, 0xfb, 0x0e,
- 0xc4, 0x05, 0x8b, 0xff, 0xde, 0xe7, 0x8d, 0x92, 0x86, 0x6c, 0x28, 0x2c,
- 0x5f, 0xff, 0x74, 0x21, 0x43, 0x3a, 0x3f, 0xa7, 0x7c, 0xfa, 0xc5, 0xff,
- 0xfc, 0x22, 0xf7, 0x24, 0x8d, 0xfb, 0xf5, 0xfe, 0x01, 0x96, 0x2f, 0xd9,
- 0xd3, 0xac, 0x0e, 0xb1, 0x6f, 0x4a, 0x37, 0xa0, 0xa9, 0xf5, 0xda, 0x95,
- 0x44, 0x5b, 0x11, 0x61, 0x53, 0x95, 0xb2, 0x58, 0xa3, 0x2b, 0xbf, 0xf7,
- 0x70, 0x21, 0x03, 0xae, 0xe7, 0x02, 0xc5, 0xd2, 0x6a, 0xc5, 0xe2, 0x98,
- 0x2c, 0x5f, 0xf0, 0xe4, 0xa4, 0x10, 0xfb, 0xac, 0x5f, 0xd3, 0x13, 0x9e,
- 0x62, 0x58, 0xbd, 0xe7, 0xd9, 0x62, 0xf3, 0x83, 0x16, 0x2f, 0xfd, 0x02,
- 0x13, 0x73, 0xf8, 0x06, 0x58, 0xb7, 0x70, 0x3d, 0xac, 0x1c, 0xa3, 0x51,
- 0x40, 0xcf, 0x15, 0x29, 0xd1, 0xec, 0x8a, 0x31, 0x87, 0x1c, 0xf1, 0xc0,
- 0xa1, 0x9f, 0x7f, 0xbe, 0xe3, 0x26, 0x68, 0x96, 0x2f, 0xf0, 0xfe, 0x26,
- 0x04, 0x76, 0x2c, 0x5d, 0xff, 0xac, 0x5f, 0x30, 0x27, 0x4b, 0x17, 0xff,
- 0xfb, 0x35, 0xa7, 0x90, 0x75, 0xdf, 0xef, 0x20, 0x29, 0x02, 0xc5, 0x4a,
- 0x60, 0xce, 0x66, 0xc6, 0xfc, 0x18, 0xf1, 0x15, 0xf4, 0xfb, 0x36, 0x58,
- 0xbe, 0x80, 0x01, 0x2b, 0x17, 0xfa, 0x7a, 0xfb, 0x39, 0xc9, 0x58, 0xbd,
- 0x38, 0x4b, 0x17, 0xc3, 0x17, 0xb8, 0xb1, 0x61, 0x80, 0xdf, 0x98, 0x37,
- 0x68, 0xe5, 0x8b, 0xfd, 0x3e, 0x7e, 0x92, 0x5b, 0xac, 0x5f, 0x4e, 0x14,
- 0x1c, 0xf2, 0xb8, 0x2b, 0x46, 0xa6, 0xc5, 0xd9, 0x1e, 0x88, 0xc9, 0xd3,
- 0xce, 0x57, 0xbe, 0x67, 0x16, 0x2f, 0xba, 0xfc, 0xc1, 0xac, 0x5d, 0x9c,
- 0x81, 0xe3, 0x7c, 0x7e, 0x9d, 0x17, 0xe5, 0x09, 0x2b, 0xb3, 0xb5, 0x8b,
- 0xd2, 0x46, 0xac, 0x5f, 0xf1, 0xcb, 0x3d, 0xc1, 0x6a, 0x0b, 0x17, 0xdf,
- 0xf3, 0x7d, 0x62, 0xa4, 0xf7, 0x5c, 0xea, 0xa0, 0xdf, 0x40, 0x8e, 0x39,
- 0x1c, 0x87, 0x49, 0xb0, 0xea, 0xde, 0x50, 0x67, 0x71, 0xe9, 0x3c, 0x35,
- 0xa2, 0x8f, 0x03, 0x52, 0xb8, 0x4f, 0x2b, 0x53, 0xf2, 0xe0, 0x81, 0x1f,
- 0xd1, 0x4a, 0xd6, 0xe4, 0x7f, 0xfe, 0x8d, 0x8b, 0xa4, 0xa6, 0x98, 0xe2,
- 0x63, 0x06, 0x02, 0x3d, 0x5d, 0xa9, 0x58, 0xb4, 0x6e, 0xb1, 0x7f, 0xd9,
- 0xa2, 0xce, 0x8d, 0xa8, 0x2c, 0x5d, 0x9e, 0x58, 0xb8, 0x99, 0x62, 0xf0,
- 0x1f, 0x75, 0x8b, 0xc5, 0x30, 0x58, 0xea, 0x5f, 0x56, 0x1f, 0x0b, 0x9a,
- 0x5b, 0xae, 0x22, 0x60, 0xd7, 0x8b, 0x71, 0x62, 0xee, 0xe0, 0xb1, 0x4e,
- 0x7a, 0xc0, 0x2b, 0x8e, 0x12, 0xbd, 0xa8, 0xd0, 0x22, 0xc5, 0xcd, 0x05,
- 0x8b, 0xf1, 0x7b, 0x00, 0x75, 0x8b, 0xed, 0x3c, 0xf9, 0x62, 0xfe, 0xe1,
- 0x64, 0x52, 0x75, 0x8a, 0x01, 0xe8, 0x78, 0x8a, 0x9d, 0x1a, 0xc7, 0x25,
- 0x61, 0x71, 0x3c, 0x5d, 0x3e, 0x58, 0xbe, 0x03, 0x07, 0xe5, 0x8b, 0xfc,
- 0xc1, 0xfd, 0xe7, 0x52, 0xb1, 0x7f, 0x08, 0xfc, 0x16, 0xb6, 0x58, 0xbf,
- 0x3f, 0x49, 0x2f, 0x2c, 0x57, 0x55, 0x6c, 0x11, 0xb8, 0xbc, 0x8b, 0x8e,
- 0x32, 0x83, 0x63, 0x07, 0xec, 0xed, 0xc5, 0xf4, 0x48, 0x46, 0x7c, 0x31,
- 0xbf, 0xfe, 0xfe, 0x0f, 0xa8, 0xfe, 0xe6, 0xf5, 0xee, 0x0e, 0xb1, 0x7f,
- 0xff, 0xc1, 0x7e, 0xa5, 0x9b, 0xc7, 0xff, 0x3e, 0xc7, 0x1f, 0x5e, 0xbf,
- 0x8e, 0x58, 0xbf, 0xf6, 0x9f, 0x90, 0x33, 0xf2, 0x52, 0xb1, 0x79, 0xe4,
- 0xeb, 0x17, 0x3f, 0xd6, 0x2b, 0x46, 0xce, 0x38, 0x72, 0xff, 0xfd, 0xe3,
- 0x45, 0x38, 0x3f, 0xe7, 0x3b, 0x84, 0xfd, 0x62, 0x82, 0xda, 0x6c, 0xfa,
- 0x79, 0x3b, 0x91, 0x12, 0x5f, 0xee, 0xa5, 0x9d, 0x0b, 0x38, 0xb1, 0x7f,
- 0x9c, 0xa2, 0xe7, 0x9f, 0x65, 0x8b, 0xe0, 0x0b, 0x5b, 0x2c, 0x5f, 0xec,
- 0xe9, 0xcc, 0x92, 0xed, 0x62, 0xfe, 0xe7, 0xa3, 0xb3, 0x52, 0xb1, 0x7a,
- 0x21, 0x69, 0x62, 0xe6, 0x82, 0xc5, 0xfb, 0x77, 0x28, 0x84, 0xb1, 0x7f,
- 0x72, 0x7b, 0x0b, 0x63, 0x3a, 0xc5, 0xfc, 0x7c, 0x2f, 0x47, 0x62, 0xc5,
- 0xff, 0xfe, 0xcf, 0x08, 0x07, 0x68, 0x30, 0xe4, 0x9b, 0x4d, 0x05, 0x8b,
- 0xf8, 0x98, 0x3f, 0x67, 0xf1, 0x11, 0xe4, 0x61, 0x7f, 0xb3, 0xff, 0x17,
- 0x98, 0x96, 0x2e, 0x71, 0xac, 0x5f, 0xdf, 0xdd, 0xb4, 0xd0, 0x58, 0xb6,
- 0xf0, 0x3c, 0x6c, 0x17, 0xbc, 0xf1, 0x71, 0x62, 0xa4, 0xf1, 0x8e, 0x51,
- 0x7f, 0xff, 0xa7, 0x35, 0x02, 0x6f, 0xb7, 0x66, 0xb0, 0xde, 0x4e, 0xb1,
- 0x7f, 0xf7, 0x9f, 0xec, 0x78, 0xe1, 0x7d, 0xf4, 0xb1, 0x7f, 0x37, 0x8f,
- 0x39, 0xe5, 0x8a, 0x63, 0xf5, 0x12, 0x45, 0xfd, 0x9a, 0xfc, 0xc3, 0x8b,
- 0x17, 0xa7, 0xbe, 0x2c, 0x54, 0x9e, 0x67, 0xcb, 0xaf, 0xe9, 0x28, 0x33,
- 0xec, 0xb1, 0x6e, 0x2c, 0x5f, 0xd2, 0x07, 0xfb, 0x9d, 0x62, 0xa4, 0xdf,
- 0xb8, 0x95, 0xe2, 0xcd, 0xd6, 0x28, 0xd4, 0x54, 0x7d, 0xb3, 0x83, 0xf4,
- 0x35, 0xc6, 0x5d, 0xc5, 0xfb, 0x2a, 0x8a, 0x18, 0xba, 0x43, 0x3c, 0x2f,
- 0xfe, 0x42, 0x50, 0xd5, 0xe3, 0x6f, 0xa1, 0x93, 0x7d, 0xfe, 0xda, 0x3d,
- 0x62, 0xfd, 0xf6, 0x3b, 0xf1, 0x62, 0x86, 0x79, 0xfb, 0x93, 0xd4, 0xae,
- 0xe5, 0xe1, 0x8b, 0xce, 0x42, 0x34, 0x3c, 0xef, 0xcf, 0xf6, 0x3b, 0xac,
- 0x5a, 0x56, 0x2e, 0x33, 0xcb, 0x15, 0x26, 0xa8, 0x02, 0x37, 0x98, 0x80,
- 0xb1, 0x5d, 0x51, 0x1b, 0x8a, 0x3b, 0x90, 0x5e, 0xe9, 0x83, 0x58, 0xb6,
- 0xb6, 0x3d, 0x18, 0x8c, 0xae, 0x6f, 0xac, 0x5f, 0xb3, 0xa6, 0x7b, 0x8b,
- 0x17, 0xd1, 0x41, 0x89, 0x62, 0xb4, 0x7c, 0x9f, 0x17, 0xe1, 0x55, 0xfe,
- 0x09, 0xac, 0x08, 0x42, 0x0d, 0x62, 0xb6, 0x3e, 0x80, 0xcb, 0xef, 0x04,
- 0x71, 0xac, 0x56, 0x1e, 0x1b, 0x12, 0x57, 0x56, 0x58, 0x8c, 0xc7, 0x7d,
- 0xb2, 0x1e, 0x1b, 0x39, 0xae, 0x89, 0x7f, 0x3c, 0x00, 0xd1, 0x93, 0x94,
- 0x67, 0x37, 0xf1, 0xf7, 0xeb, 0x87, 0xe2, 0xc5, 0xfb, 0x6e, 0xe1, 0x27,
- 0x58, 0xbf, 0xff, 0xfe, 0x07, 0x33, 0x08, 0xd3, 0x34, 0x53, 0x9f, 0x8c,
- 0xe1, 0x66, 0xc7, 0xc3, 0xac, 0x5d, 0xac, 0x58, 0xbb, 0x8e, 0xb1, 0x5b,
- 0x1a, 0xed, 0x0b, 0xdc, 0x64, 0x16, 0x2f, 0xa4, 0x8c, 0x3a, 0xc5, 0x61,
- 0xef, 0x1c, 0x88, 0xc1, 0x9a, 0xc4, 0xcf, 0x3d, 0x18, 0x6d, 0xc0, 0xe2,
- 0xc5, 0xf7, 0x52, 0x9d, 0xd6, 0x2f, 0x9b, 0xf2, 0x62, 0xc5, 0x61, 0xf0,
- 0x7c, 0x63, 0xa1, 0x2d, 0xf4, 0x87, 0x83, 0x58, 0xbf, 0xfe, 0x17, 0x70,
- 0xe0, 0xff, 0x3a, 0x1b, 0x30, 0x6b, 0x17, 0x46, 0xe1, 0x62, 0xc5, 0x4a,
- 0xab, 0x8c, 0x8d, 0x9d, 0xe1, 0x13, 0xa3, 0x02, 0x23, 0x31, 0x4e, 0xec,
- 0xf2, 0xc5, 0xc7, 0x75, 0x8a, 0x19, 0xae, 0x21, 0x7b, 0xe0, 0xe7, 0xbe,
- 0x2c, 0x5f, 0xe1, 0xb7, 0x80, 0x61, 0x41, 0x62, 0xf7, 0x8c, 0xc5, 0x8b,
- 0xa7, 0x65, 0x8a, 0x93, 0xeb, 0x63, 0x5e, 0x0f, 0x5f, 0x17, 0xb9, 0x2b,
- 0x17, 0x87, 0x30, 0x58, 0xbf, 0x45, 0x09, 0xef, 0xcb, 0x17, 0xf6, 0xff,
- 0x7e, 0x8d, 0xa5, 0x8b, 0x4e, 0xc7, 0xb9, 0x85, 0x77, 0xdb, 0x39, 0x79,
- 0x62, 0xec, 0xfa, 0xc5, 0x4a, 0x3f, 0x18, 0x88, 0x9e, 0x44, 0x4f, 0x1c,
- 0x47, 0x61, 0xac, 0x52, 0xc6, 0x16, 0x57, 0x78, 0x2e, 0xb1, 0x5b, 0x2e,
- 0xf2, 0x42, 0x57, 0x56, 0x42, 0x3f, 0xe4, 0x1c, 0x84, 0x87, 0xa3, 0x29,
- 0xe8, 0xb9, 0x1c, 0x35, 0x68, 0xd4, 0xb1, 0x7e, 0xd0, 0x0e, 0xfc, 0x58,
- 0xba, 0x7a, 0x2c, 0x56, 0x1e, 0x17, 0x42, 0x9b, 0xdf, 0x10, 0x6b, 0x17,
- 0xbe, 0xdb, 0x2c, 0x5c, 0x20, 0x2c, 0x5e, 0x13, 0xee, 0xb1, 0x7d, 0xe7,
- 0x9e, 0xd6, 0x2a, 0x07, 0xb3, 0xf1, 0x8e, 0x0f, 0x5c, 0x2d, 0xd6, 0x2f,
- 0xfa, 0x76, 0x3b, 0x00, 0x0f, 0xf5, 0x8a, 0x82, 0x20, 0x80, 0x5f, 0xc1,
- 0x9b, 0xde, 0xc3, 0x16, 0x2f, 0xf3, 0x44, 0xfd, 0xcf, 0x25, 0x62, 0xfe,
- 0x38, 0xb9, 0xec, 0xf2, 0xc5, 0xfe, 0x0d, 0xb7, 0xc2, 0xc1, 0xac, 0x5f,
- 0x9b, 0xfd, 0xc3, 0x8b, 0x15, 0x28, 0x8d, 0xe1, 0x78, 0x8d, 0x2f, 0xd9,
- 0xc0, 0x4c, 0x4b, 0x17, 0xdc, 0xeb, 0xa9, 0x58, 0xbe, 0x61, 0xc9, 0xd6,
- 0x2f, 0xe7, 0x3b, 0xc4, 0x23, 0x16, 0x2b, 0xb3, 0xf7, 0x88, 0x97, 0xe4,
- 0x57, 0xf6, 0xf8, 0x71, 0x73, 0xcb, 0x15, 0x27, 0xc2, 0x23, 0x1b, 0xf0,
- 0x84, 0x63, 0xc7, 0xac, 0x5e, 0x84, 0xf1, 0x62, 0xe2, 0x3a, 0xc5, 0x84,
- 0xb1, 0x50, 0x3c, 0x61, 0x8e, 0x80, 0x5e, 0xf0, 0xc5, 0xba, 0xc5, 0xf0,
- 0xca, 0x60, 0xb1, 0x5d, 0x51, 0xc7, 0x2e, 0x6e, 0x5e, 0xc3, 0xf7, 0xd1,
- 0x69, 0xe3, 0x96, 0x2e, 0x71, 0xac, 0x5f, 0x72, 0x0c, 0x4b, 0x15, 0x86,
- 0xe7, 0x82, 0xf7, 0xff, 0x8c, 0xeb, 0xdf, 0x8a, 0x73, 0xae, 0x77, 0xe5,
- 0x8b, 0xfe, 0x9f, 0xbc, 0xc5, 0x14, 0xee, 0xb1, 0x51, 0xa2, 0xf1, 0x04,
- 0xad, 0x0c, 0x8c, 0xd1, 0xfe, 0xe1, 0xf2, 0xe6, 0x11, 0xe3, 0xd1, 0x43,
- 0x07, 0x45, 0xe7, 0x8c, 0x07, 0xf1, 0x82, 0x31, 0xe7, 0x98, 0x04, 0x41,
- 0xd1, 0x46, 0xfe, 0x26, 0xf4, 0x33, 0xb5, 0x8b, 0xfc, 0xf1, 0x31, 0x3f,
- 0x7c, 0x58, 0xbb, 0x37, 0x58, 0xbf, 0xc5, 0xee, 0x14, 0xfb, 0x8b, 0x17,
- 0xfb, 0xe5, 0x8e, 0x09, 0x02, 0xc5, 0xf9, 0xfa, 0x61, 0x71, 0x62, 0xfa,
- 0x3b, 0x35, 0x2b, 0x17, 0xff, 0xf4, 0xfc, 0x5d, 0xcf, 0xb7, 0xfc, 0xe8,
- 0x58, 0x28, 0x96, 0x2b, 0x13, 0x12, 0x73, 0x3d, 0x19, 0x1c, 0xa7, 0xe4,
- 0xb7, 0xef, 0x67, 0xc5, 0x1e, 0xb1, 0x7f, 0xed, 0xbe, 0xe7, 0x98, 0xff,
- 0xe6, 0xcb, 0x15, 0xd9, 0xf8, 0x68, 0xb2, 0xfe, 0xd6, 0x7f, 0xe2, 0xf2,
- 0xc5, 0xfd, 0x19, 0xcf, 0x4f, 0xb8, 0xb8, 0x83, 0x4b, 0xe2, 0x9c, 0xd2,
- 0x85, 0x6e, 0x7c, 0x1f, 0x3f, 0xbf, 0xb3, 0x5b, 0x09, 0x86, 0xa8, 0x83,
- 0x48, 0xc3, 0x47, 0x5b, 0x26, 0x03, 0x08, 0x59, 0x5f, 0xf7, 0xb8, 0xda,
- 0x1e, 0x9a, 0x0b, 0x15, 0xa3, 0xe4, 0xe1, 0x55, 0xf1, 0x7f, 0x3b, 0x58,
- 0xa9, 0x4f, 0x35, 0xe3, 0x88, 0x62, 0x2b, 0xfd, 0xd3, 0x8e, 0x4d, 0xa3,
- 0x56, 0x2f, 0xcd, 0xbb, 0x9e, 0x56, 0x2f, 0xe8, 0x7c, 0x9b, 0xbf, 0x2c,
- 0x56, 0xe7, 0xae, 0x45, 0x17, 0xc6, 0x13, 0x6c, 0xb1, 0x7e, 0xe3, 0xe9,
- 0xc0, 0xb1, 0x58, 0x7d, 0xdc, 0x22, 0x08, 0x49, 0x7e, 0xf7, 0xe7, 0x5b,
- 0x2c, 0x5d, 0xdb, 0xac, 0x5f, 0xa7, 0xdd, 0x4e, 0x1a, 0xc5, 0xff, 0xb6,
- 0xf7, 0xe7, 0xf9, 0xd1, 0xa0, 0xb1, 0x78, 0xf3, 0xba, 0xc5, 0xf1, 0x00,
- 0x5c, 0x58, 0xac, 0x3c, 0x1d, 0x0f, 0x5f, 0xbb, 0x8b, 0xed, 0xda, 0xc5,
- 0xf4, 0x33, 0xbf, 0x2c, 0x5c, 0x0e, 0x2c, 0x57, 0x66, 0xf3, 0x44, 0x95,
- 0x29, 0x97, 0x3c, 0x20, 0xd8, 0x84, 0x4d, 0x17, 0xcc, 0xc0, 0xe2, 0xc5,
- 0xcc, 0x6a, 0xc5, 0xcd, 0xb4, 0x46, 0xe8, 0x88, 0xaf, 0xf8, 0x7c, 0xe6,
- 0x68, 0x7f, 0xc5, 0x8b, 0xdf, 0x9d, 0x2c, 0x5f, 0xf7, 0x18, 0xa6, 0x27,
- 0x1e, 0xcb, 0x16, 0x02, 0xc5, 0xfe, 0x83, 0x9e, 0x7e, 0x60, 0xd6, 0x2f,
- 0xff, 0x4e, 0x17, 0x7e, 0xcd, 0x3e, 0xcc, 0x75, 0x8b, 0x83, 0xfa, 0xc5,
- 0xd9, 0xfe, 0xa8, 0xe4, 0xdc, 0xeb, 0x82, 0x5e, 0x35, 0x0d, 0x2a, 0xec,
- 0xe2, 0xc5, 0x78, 0xfc, 0x23, 0x96, 0x6a, 0x09, 0xcb, 0x07, 0x1b, 0x8d,
- 0x4a, 0x7f, 0x6d, 0x1e, 0x85, 0xf8, 0x67, 0x26, 0x0d, 0x62, 0xf7, 0x46,
- 0x89, 0x62, 0x9c, 0xf2, 0x7e, 0x53, 0x7f, 0xd9, 0x0f, 0xe1, 0x36, 0x8d,
- 0x58, 0xb8, 0xe1, 0xac, 0x54, 0x61, 0xe9, 0x40, 0xe6, 0xfd, 0x27, 0xf6,
- 0x7d, 0x62, 0xba, 0xb2, 0xac, 0xa3, 0x43, 0x49, 0x8c, 0xaa, 0x12, 0xa1,
- 0x86, 0x69, 0x90, 0xfb, 0x73, 0x08, 0x8a, 0xb4, 0x31, 0xf8, 0xd6, 0x99,
- 0xe8, 0xa5, 0x14, 0x71, 0xc4, 0x4e, 0x61, 0x09, 0x6f, 0xcf, 0xbc, 0x9e,
- 0x56, 0x2f, 0xb2, 0x7b, 0xf2, 0xc5, 0xfe, 0xef, 0x58, 0xff, 0x91, 0xac,
- 0x5f, 0xf6, 0xef, 0xcc, 0x16, 0xec, 0x4b, 0x17, 0x0e, 0x56, 0x2f, 0xd1,
- 0x7d, 0x81, 0x2b, 0x17, 0x64, 0x16, 0x2f, 0xff, 0xbf, 0x27, 0xeb, 0xf9,
- 0x6d, 0x0c, 0xa6, 0x0b, 0x15, 0x04, 0xd8, 0x46, 0x51, 0x84, 0x7f, 0x34,
- 0x63, 0xa2, 0x17, 0xe1, 0x48, 0x85, 0xee, 0xc3, 0x16, 0x2f, 0xdf, 0x62,
- 0x98, 0xf5, 0x8b, 0xfc, 0x6b, 0x7b, 0x87, 0x7f, 0x2c, 0x5f, 0xe6, 0xf3,
- 0x60, 0xdf, 0xa2, 0xc5, 0xf0, 0x3f, 0x23, 0x58, 0xbf, 0xbe, 0xe1, 0x94,
- 0x8d, 0x62, 0xff, 0xa4, 0x07, 0x9c, 0x2f, 0x71, 0x62, 0xff, 0xb9, 0x81,
- 0xfd, 0x8e, 0xfc, 0x58, 0xbf, 0x66, 0xb6, 0x17, 0x16, 0x28, 0xd4, 0xd5,
- 0xb7, 0x35, 0x73, 0x48, 0x88, 0xfe, 0x5d, 0xc3, 0x8e, 0x87, 0x57, 0xf6,
- 0xef, 0xb6, 0x77, 0xe5, 0x8b, 0xf3, 0xf7, 0x07, 0x25, 0x8b, 0xcf, 0xfc,
- 0x58, 0xbf, 0xbc, 0xc7, 0x3c, 0x9d, 0x62, 0xb0, 0xfc, 0xb7, 0x28, 0xec,
- 0x72, 0x96, 0x28, 0xd4, 0x6f, 0x9e, 0x14, 0x61, 0x98, 0x5f, 0xf0, 0xb6,
- 0xeb, 0x9e, 0xfc, 0xf9, 0x62, 0xfd, 0xc1, 0x03, 0x3e, 0xb1, 0x73, 0xc4,
- 0xb1, 0x52, 0x8b, 0x5d, 0xcd, 0xfc, 0x7a, 0x10, 0xa6, 0xff, 0xe2, 0x11,
- 0xa7, 0x17, 0xbf, 0x22, 0x0b, 0xac, 0x5f, 0x1e, 0x74, 0x6a, 0xc5, 0xf6,
- 0x00, 0x0c, 0xb1, 0x78, 0xcf, 0xb2, 0xc5, 0x61, 0xf2, 0x11, 0x24, 0x71,
- 0x15, 0x6c, 0x8d, 0xf0, 0xe1, 0x5f, 0x7c, 0x64, 0x96, 0xeb, 0x17, 0xb9,
- 0xf9, 0x58, 0xbf, 0x43, 0x3e, 0xe7, 0x58, 0xa8, 0x1f, 0x48, 0xc9, 0x08,
- 0x76, 0xfd, 0xb6, 0x0b, 0x5b, 0x2c, 0x5f, 0x8b, 0x41, 0xb6, 0xcb, 0x17,
- 0xfb, 0xfd, 0x30, 0x7c, 0xc3, 0x16, 0x2a, 0x53, 0x4d, 0xc8, 0x49, 0xb9,
- 0x73, 0x15, 0x88, 0xaa, 0xfc, 0xcf, 0xe2, 0x95, 0x8b, 0xed, 0xff, 0x21,
- 0xac, 0x5f, 0xb3, 0xdc, 0x73, 0xac, 0x5c, 0x22, 0x58, 0xb8, 0x5e, 0x58,
- 0xb0, 0xd6, 0x2f, 0xdc, 0x1c, 0xe0, 0xd6, 0x2b, 0x63, 0xd2, 0x8f, 0x18,
- 0x61, 0x2b, 0xc5, 0x9b, 0x2c, 0x54, 0xaf, 0xf3, 0x41, 0xbc, 0x63, 0x19,
- 0x1c, 0x03, 0xc7, 0xfb, 0xa9, 0x4d, 0x67, 0x4c, 0x0b, 0x93, 0x11, 0x2f,
- 0x0a, 0x04, 0xd2, 0x61, 0x95, 0xff, 0x49, 0xe7, 0xce, 0x59, 0x05, 0x8b,
- 0x41, 0x62, 0xfb, 0x82, 0x90, 0x2c, 0x5e, 0xfb, 0x9d, 0x62, 0xc1, 0x16,
- 0x2b, 0x73, 0x62, 0x21, 0xda, 0xd2, 0x2f, 0xfe, 0x6e, 0x01, 0x22, 0x54,
- 0xbb, 0x09, 0x62, 0xfd, 0xc3, 0x39, 0xf1, 0x2c, 0x57, 0xcf, 0x07, 0xc2,
- 0xd7, 0xff, 0xb4, 0xf2, 0x7c, 0xeb, 0x9f, 0x7c, 0x3a, 0xc5, 0xfb, 0xb9,
- 0xf6, 0xa5, 0x62, 0xf9, 0xf9, 0x2c, 0xb1, 0x5d, 0x51, 0x28, 0x49, 0x5c,
- 0x29, 0xbf, 0xd8, 0x59, 0xdf, 0xa0, 0x75, 0x8b, 0xbd, 0x2b, 0x15, 0x27,
- 0x96, 0xc6, 0x97, 0xfc, 0xd0, 0x1b, 0x88, 0x2e, 0xfa, 0x58, 0xbf, 0x61,
- 0x14, 0x8d, 0x62, 0xfb, 0xed, 0xf9, 0x58, 0xbf, 0xa7, 0x63, 0xb4, 0x52,
- 0xb1, 0x6e, 0x2c, 0x5f, 0x18, 0x12, 0x7b, 0x58, 0xb6, 0x96, 0x2a, 0x08,
- 0x9c, 0x88, 0x88, 0x05, 0xe4, 0x24, 0x22, 0x7b, 0xff, 0xe6, 0x37, 0xd3,
- 0xa0, 0x6a, 0x7c, 0x4c, 0x05, 0x8b, 0xfb, 0x71, 0xfc, 0x4d, 0xc5, 0x8b,
- 0xff, 0xdf, 0x97, 0x29, 0xf3, 0xe9, 0xfc, 0x25, 0x8a, 0x93, 0xf8, 0x73,
- 0x0b, 0x98, 0xd5, 0x8b, 0xfb, 0x62, 0xcf, 0x6a, 0x56, 0x2f, 0xf3, 0xf8,
- 0xcd, 0x4f, 0xe5, 0x62, 0xfb, 0x73, 0x3d, 0xc5, 0x8b, 0xf8, 0xb0, 0x18,
- 0x50, 0x58, 0xbf, 0xf8, 0xc2, 0x6f, 0x71, 0xfb, 0xfb, 0x86, 0xb1, 0x7f,
- 0x8f, 0x3b, 0xc9, 0x3c, 0x4b, 0x16, 0x37, 0xa9, 0xfd, 0xe2, 0x3d, 0x62,
- 0x34, 0x5a, 0x14, 0xf7, 0xb5, 0x26, 0xac, 0x54, 0xa7, 0x3b, 0x02, 0xe7,
- 0x34, 0x28, 0x7b, 0xf0, 0x9a, 0xa5, 0x78, 0x0b, 0x1f, 0x5e, 0x16, 0xda,
- 0x7c, 0x39, 0x07, 0xcf, 0x5a, 0x18, 0x44, 0x95, 0xc8, 0x64, 0x78, 0x80,
- 0x51, 0xda, 0xdf, 0xfe, 0x2c, 0x1e, 0xa4, 0x7f, 0x63, 0x33, 0x65, 0x8b,
- 0xcd, 0xd8, 0x16, 0x2d, 0xd1, 0x62, 0xa0, 0x6c, 0xb8, 0x3d, 0x73, 0xf9,
- 0x62, 0xff, 0xe2, 0xfb, 0x70, 0xb0, 0xd3, 0x72, 0x3d, 0x62, 0xfe, 0x10,
- 0xf3, 0xd3, 0x12, 0xc5, 0x61, 0xfb, 0xee, 0x91, 0x7f, 0x43, 0x0b, 0x67,
- 0xd2, 0xc5, 0xe2, 0x61, 0xac, 0x5f, 0xe9, 0x16, 0xf8, 0x79, 0xdd, 0x62,
- 0x9c, 0xf4, 0x48, 0x72, 0xe3, 0x3c, 0xb1, 0x7e, 0xe4, 0xeb, 0xd2, 0xb1,
- 0x43, 0x3e, 0x1d, 0x10, 0x70, 0x66, 0xe7, 0x0b, 0xac, 0x5d, 0x03, 0x16,
- 0x2f, 0x83, 0xc8, 0x3a, 0xc5, 0xec, 0x73, 0x56, 0x2f, 0x66, 0x6c, 0xb1,
- 0x61, 0xac, 0x5e, 0x66, 0xd2, 0xc5, 0x49, 0xae, 0x88, 0x4a, 0x99, 0x15,
- 0x84, 0x47, 0xe1, 0xd3, 0x12, 0xef, 0x63, 0xf4, 0x58, 0xbd, 0x03, 0x0e,
- 0xb1, 0x5f, 0x37, 0xac, 0x3d, 0x7f, 0x71, 0xf5, 0x82, 0xd2, 0xc5, 0xe1,
- 0xbe, 0x96, 0x2f, 0xff, 0xe8, 0xba, 0xbe, 0xe2, 0xd7, 0x05, 0xd4, 0xef,
- 0xef, 0xba, 0xc5, 0xd2, 0x6a, 0xc5, 0x49, 0xfd, 0xbb, 0x1d, 0x4a, 0xe5,
- 0xe6, 0x3e, 0x9a, 0x43, 0xbc, 0x23, 0xbb, 0x22, 0x78, 0x70, 0x44, 0x5f,
- 0xa1, 0xb3, 0xc3, 0x17, 0xef, 0x3e, 0x20, 0x11, 0x70, 0x48, 0x4c, 0x5e,
- 0x19, 0xf8, 0xb1, 0x7f, 0x19, 0xef, 0x86, 0xdb, 0x2c, 0x58, 0x2a, 0xa8,
- 0xbf, 0x0a, 0x81, 0xea, 0x9c, 0xca, 0xfd, 0xb7, 0x70, 0x91, 0xac, 0x5f,
- 0x13, 0xf7, 0x05, 0x8b, 0xfa, 0x27, 0xe0, 0x84, 0x75, 0x8a, 0xc3, 0xd3,
- 0x62, 0x3b, 0xda, 0xcc, 0x58, 0xa8, 0xdd, 0x17, 0x4e, 0xfd, 0xc2, 0x0b,
- 0xc6, 0x4c, 0x4b, 0x17, 0x8a, 0x40, 0xb1, 0x79, 0xf3, 0xeb, 0x16, 0xde,
- 0x4d, 0xc6, 0x87, 0x2f, 0xff, 0x16, 0x0f, 0xf3, 0xd3, 0x91, 0xef, 0xdf,
- 0x96, 0x2b, 0x48, 0xce, 0x25, 0x7e, 0x84, 0xf7, 0x86, 0x18, 0x16, 0x2f,
- 0xff, 0x7f, 0x24, 0xfa, 0xc0, 0x9f, 0x79, 0x3a, 0xc5, 0xff, 0x0a, 0x10,
- 0x3f, 0xbd, 0x27, 0x58, 0xb4, 0x3e, 0x88, 0x6f, 0x25, 0xdf, 0xa7, 0xee,
- 0x0e, 0x2c, 0x5f, 0xdc, 0x9d, 0xb3, 0x83, 0x58, 0xad, 0x1e, 0xbf, 0x8a,
- 0x2e, 0xfe, 0x2c, 0x5f, 0xff, 0x7e, 0x47, 0x9b, 0xf5, 0xc2, 0xc1, 0xfe,
- 0x56, 0x2f, 0xfb, 0x53, 0xf7, 0xe9, 0xa9, 0x82, 0xc5, 0xff, 0xfe, 0x04,
- 0xf7, 0x0e, 0x0f, 0x30, 0xb3, 0x7f, 0xb8, 0xbc, 0xb1, 0x7f, 0xec, 0x2c,
- 0xce, 0x75, 0x87, 0x0e, 0xb1, 0x7f, 0xf4, 0xf7, 0x25, 0xb4, 0xc1, 0xcb,
- 0x16, 0x2f, 0xfd, 0x9e, 0xc0, 0x75, 0xcf, 0x94, 0xac, 0x53, 0xa3, 0x08,
- 0xe8, 0x04, 0x87, 0x7f, 0xe6, 0x9e, 0xe1, 0xd7, 0x9d, 0x8e, 0x56, 0x2f,
- 0xd8, 0x3f, 0xbf, 0x96, 0x2f, 0xe6, 0xd8, 0xb3, 0x61, 0x2c, 0x50, 0xd7,
- 0x42, 0x72, 0x30, 0x2d, 0xcc, 0x7b, 0x85, 0x2b, 0xc2, 0x02, 0x3c, 0x8a,
- 0x21, 0x7d, 0x28, 0x80, 0xef, 0x91, 0x92, 0x78, 0xb8, 0x34, 0x38, 0xe2,
- 0x8b, 0xdc, 0x29, 0x58, 0xbe, 0xc0, 0xfa, 0xc1, 0x62, 0xf9, 0xf9, 0x83,
- 0xea, 0x78, 0x5b, 0x0e, 0x5e, 0x36, 0x74, 0xb1, 0x7c, 0x76, 0x18, 0x96,
- 0x2f, 0x45, 0x27, 0x58, 0xbe, 0xfc, 0x9d, 0xd6, 0x2f, 0xe9, 0xfb, 0xf2,
- 0x4c, 0x58, 0xac, 0x3e, 0xe1, 0x0f, 0x18, 0x45, 0x7c, 0x02, 0x68, 0x2c,
- 0x5f, 0xdf, 0x73, 0xb3, 0x04, 0x58, 0xbf, 0x40, 0x84, 0xc6, 0xac, 0x5e,
- 0x17, 0x7c, 0x58, 0xbf, 0xc2, 0x2f, 0x3f, 0xdc, 0xeb, 0x17, 0x8b, 0x02,
- 0x2c, 0x5e, 0x3e, 0x74, 0x58, 0xae, 0xa8, 0x8f, 0x80, 0xfe, 0x19, 0xb0,
- 0xf5, 0xcf, 0xb2, 0xc5, 0x89, 0x62, 0xb4, 0x6a, 0x4c, 0x18, 0xb1, 0xd6,
- 0x2f, 0x6b, 0x3b, 0x58, 0xbe, 0x38, 0x3b, 0x02, 0xc5, 0xc3, 0x98, 0x1e,
- 0xa8, 0x04, 0x8c, 0x1e, 0xbf, 0xfd, 0x0f, 0x3e, 0xcc, 0x39, 0x81, 0x61,
- 0xd6, 0x2d, 0x1c, 0xb1, 0x7e, 0x6f, 0x31, 0x01, 0x62, 0xa3, 0x15, 0xc2,
- 0xc8, 0xf0, 0xe1, 0x22, 0x69, 0x7e, 0xe4, 0x5d, 0x97, 0xc5, 0x0b, 0x8d,
- 0x33, 0x1d, 0xdd, 0x8e, 0xc2, 0xe9, 0x51, 0xc2, 0xb7, 0xfc, 0xe6, 0xce,
- 0x8b, 0x1c, 0xd5, 0x8b, 0xb7, 0xd9, 0x62, 0xfd, 0x8f, 0xa8, 0xa0, 0xb1,
- 0x7c, 0x4d, 0xee, 0x2c, 0x51, 0xcf, 0x2f, 0xa1, 0x4d, 0xf3, 0x44, 0x64,
- 0x4b, 0x15, 0x27, 0x94, 0xc4, 0x97, 0x3c, 0x4b, 0x17, 0xfe, 0xcd, 0xba,
- 0xfe, 0x62, 0x7e, 0xe0, 0xb1, 0x7f, 0x49, 0xa3, 0x29, 0xed, 0x62, 0xe7,
- 0x3a, 0xc5, 0x4a, 0x22, 0xb4, 0x89, 0xd0, 0xbe, 0xfa, 0x4a, 0x77, 0x58,
- 0xbd, 0x3a, 0x35, 0x62, 0xb7, 0x3c, 0x02, 0x22, 0xbe, 0x92, 0xc3, 0x56,
- 0x2f, 0x72, 0x4d, 0x58, 0xbd, 0xf6, 0xed, 0x62, 0xff, 0x36, 0x77, 0xef,
- 0x37, 0xd6, 0x2f, 0xfe, 0x10, 0xf3, 0x53, 0x07, 0x1c, 0x92, 0xc5, 0xff,
- 0x13, 0x6d, 0x3a, 0xd3, 0x41, 0x62, 0xfe, 0xe4, 0x50, 0x92, 0x82, 0xc5,
- 0xff, 0x9f, 0xda, 0x14, 0x3b, 0x86, 0x79, 0x62, 0xa0, 0x8e, 0xcf, 0xa1,
- 0xf8, 0xe7, 0xa1, 0x7d, 0xfe, 0xe7, 0x30, 0x81, 0x1d, 0x8b, 0x17, 0xff,
- 0x3f, 0x20, 0xfe, 0x33, 0x53, 0xf9, 0x58, 0xb1, 0xf0, 0xfe, 0xfe, 0x6d,
- 0x7f, 0xfd, 0xa6, 0xe1, 0x66, 0xc6, 0x40, 0x52, 0xe4, 0xb1, 0x52, 0x99,
- 0x8b, 0x42, 0xe8, 0x44, 0xf5, 0xda, 0xac, 0x18, 0x87, 0xbe, 0x3d, 0xe9,
- 0x4a, 0x37, 0xff, 0xf9, 0xf8, 0x0c, 0xea, 0xfd, 0x27, 0xef, 0x31, 0x45,
- 0x3b, 0xac, 0x5e, 0xf3, 0xec, 0xb1, 0x7f, 0xbe, 0xfa, 0x27, 0xf7, 0x16,
- 0x2f, 0x77, 0x31, 0x2c, 0x58, 0x1b, 0x9e, 0x93, 0x19, 0xde, 0x29, 0xdd,
- 0x62, 0xff, 0x67, 0x22, 0xfb, 0x87, 0xe5, 0x8b, 0xf3, 0x42, 0x63, 0xce,
- 0xb1, 0x7f, 0xe7, 0x8b, 0xf3, 0xae, 0xe1, 0x3a, 0x58, 0xbf, 0xa1, 0x31,
- 0xe7, 0x98, 0x2c, 0x5f, 0xfe, 0xf7, 0xe7, 0xa7, 0x09, 0xbd, 0x13, 0xf4,
- 0x58, 0xbf, 0xf3, 0x9f, 0x35, 0x93, 0x13, 0x9d, 0x62, 0xb1, 0x11, 0xba,
- 0x4f, 0xa9, 0x4e, 0x0b, 0x63, 0x61, 0x95, 0xc4, 0x83, 0xc8, 0x5f, 0x5f,
- 0x67, 0xa4, 0x6b, 0x17, 0xd1, 0x6a, 0x7b, 0x58, 0xbf, 0xf8, 0x9b, 0xbe,
- 0x73, 0x34, 0x3f, 0xe2, 0xc5, 0xff, 0xe9, 0xdf, 0xae, 0xb1, 0xc4, 0x17,
- 0xc0, 0x98, 0xb1, 0x4e, 0x89, 0x72, 0x45, 0xae, 0xac, 0x84, 0xd8, 0x42,
- 0x8b, 0x1c, 0x77, 0x22, 0x79, 0x5c, 0x7a, 0x48, 0x3b, 0x33, 0x38, 0x11,
- 0x47, 0x23, 0x9f, 0x0d, 0x44, 0xc2, 0x20, 0x90, 0xbc, 0xb0, 0x51, 0x62,
- 0xf7, 0x40, 0x3a, 0xc5, 0x2c, 0x5f, 0xcd, 0xd9, 0xc9, 0x83, 0x58, 0xa9,
- 0x37, 0x7a, 0x0c, 0xa5, 0x8b, 0xd9, 0x80, 0x58, 0xbd, 0xf7, 0xf2, 0xc5,
- 0xba, 0x05, 0x51, 0xaa, 0x16, 0x0b, 0x62, 0xd3, 0x90, 0x10, 0x61, 0x83,
- 0x96, 0x02, 0xc5, 0xfb, 0x5b, 0x09, 0x86, 0xb1, 0x68, 0xe5, 0x8a, 0x81,
- 0xe8, 0xe0, 0x91, 0x85, 0x57, 0xa4, 0x27, 0x16, 0x2e, 0x63, 0xac, 0x51,
- 0xa7, 0xcb, 0xb9, 0x7e, 0x87, 0xef, 0xda, 0xd6, 0x47, 0xc4, 0xb1, 0x70,
- 0x7c, 0x58, 0xa9, 0x6e, 0x50, 0xe1, 0x0c, 0xc1, 0xb9, 0xe4, 0xef, 0x2e,
- 0xf1, 0x8a, 0xbc, 0xbc, 0x08, 0xf8, 0x5e, 0x9c, 0xe7, 0xf0, 0xaf, 0x6a,
- 0x43, 0x68, 0x23, 0xa5, 0x14, 0x63, 0x9d, 0x0c, 0x4c, 0x2d, 0xbd, 0xec,
- 0xfa, 0xc5, 0xfe, 0x09, 0xce, 0x49, 0xe7, 0xcb, 0x17, 0x31, 0x8b, 0x15,
- 0x27, 0x9c, 0x73, 0x6b, 0xf1, 0xc5, 0xbe, 0x1d, 0x62, 0xfd, 0xa3, 0xc8,
- 0x38, 0xb1, 0x4e, 0x7a, 0x6c, 0x55, 0x7f, 0x8a, 0x05, 0x87, 0x9d, 0xd6,
- 0x2e, 0xc8, 0xe5, 0x8a, 0xc3, 0xcd, 0xf9, 0x9d, 0xfb, 0xef, 0xd3, 0x06,
- 0xb1, 0x77, 0x9d, 0x62, 0xf6, 0x1e, 0x56, 0x2b, 0xa9, 0xb3, 0xc1, 0x7b,
- 0x98, 0xeb, 0x17, 0xcf, 0xbb, 0x69, 0x62, 0xff, 0x16, 0x10, 0xa1, 0x9c,
- 0x58, 0xbf, 0x72, 0x77, 0xc0, 0x2c, 0x5f, 0x9c, 0x62, 0xf7, 0x16, 0x2e,
- 0xf7, 0x3a, 0x9e, 0x93, 0x14, 0xd4, 0xa2, 0xcc, 0x50, 0x84, 0xad, 0x93,
- 0x14, 0x80, 0xb8, 0xe1, 0xad, 0x77, 0x5e, 0xd6, 0x2f, 0xcc, 0x77, 0x09,
- 0x8b, 0x17, 0xf6, 0x7d, 0xbc, 0xd1, 0x2c, 0x5d, 0x3d, 0xac, 0x57, 0x67,
- 0x8d, 0xe2, 0xea, 0xc4, 0x49, 0x33, 0x7d, 0xfe, 0x11, 0x67, 0x89, 0x8e,
- 0xb1, 0x7f, 0xff, 0xd9, 0xf6, 0x09, 0xa6, 0xd8, 0xb0, 0x23, 0xe0, 0x7d,
- 0xc3, 0x8b, 0x15, 0x88, 0x9e, 0xd1, 0x95, 0xa2, 0x58, 0xbd, 0xfc, 0x02,
- 0xc5, 0x39, 0xb0, 0xf0, 0x9d, 0xfe, 0xe4, 0xc2, 0x76, 0x9d, 0x96, 0x2e,
- 0xc3, 0x56, 0x2f, 0xff, 0x61, 0xbf, 0x7e, 0x7f, 0x3a, 0x4e, 0x76, 0xb1,
- 0x52, 0x8b, 0xa7, 0x20, 0xf9, 0xa9, 0x0c, 0x5a, 0x56, 0x2f, 0x98, 0xc9,
- 0x0d, 0x62, 0xa4, 0xda, 0xf6, 0x23, 0x76, 0xb1, 0x62, 0xfc, 0x10, 0xcd,
- 0x7d, 0x96, 0x2f, 0xfc, 0x3c, 0x3e, 0xa5, 0xcb, 0x25, 0x62, 0xe9, 0xdd,
- 0x62, 0x9c, 0xf5, 0x3c, 0x79, 0x7c, 0x67, 0x27, 0x65, 0x8a, 0x93, 0xc6,
- 0xe1, 0x0d, 0xd1, 0xb8, 0x45, 0x8a, 0xc4, 0xc1, 0x81, 0x0c, 0x62, 0x21,
- 0xbe, 0x7d, 0x4c, 0x16, 0x2f, 0xb6, 0x3c, 0xf1, 0x62, 0xb6, 0x3c, 0x6c,
- 0x22, 0xbf, 0xf4, 0xf9, 0x85, 0xe6, 0xef, 0x3c, 0xb1, 0x7f, 0xda, 0xeb,
- 0x23, 0xfe, 0x6f, 0x2b, 0x17, 0xff, 0x4e, 0x0d, 0xf8, 0x59, 0xd1, 0xc9,
- 0x62, 0xbe, 0x8b, 0xe6, 0x3f, 0x11, 0xe5, 0xf3, 0x4b, 0xc7, 0x2c, 0x5f,
- 0xb8, 0x2d, 0x8e, 0xeb, 0x15, 0xb9, 0xe7, 0x76, 0x49, 0x7e, 0x6f, 0x9d,
- 0xf8, 0xb1, 0x78, 0xb3, 0x8b, 0x17, 0xff, 0xfe, 0x9f, 0xb9, 0xe3, 0x22,
- 0x83, 0x68, 0xcf, 0xbf, 0x7c, 0xdd, 0xf6, 0x58, 0xa0, 0xab, 0x28, 0x43,
- 0x66, 0xb8, 0x3a, 0x0d, 0xb4, 0xd2, 0x1d, 0xd7, 0x5e, 0x33, 0x68, 0xf3,
- 0x78, 0xa1, 0x5b, 0xa8, 0x5f, 0xfe, 0x30, 0xc6, 0x6f, 0x01, 0x09, 0x46,
- 0x3b, 0xc7, 0xaf, 0x43, 0x80, 0x4f, 0xbd, 0x09, 0x0c, 0x28, 0x08, 0x39,
- 0x7f, 0xbd, 0x0c, 0x8f, 0x62, 0x02, 0xc5, 0xed, 0x70, 0x4b, 0x16, 0xe2,
- 0xc5, 0xfe, 0xdc, 0x0c, 0x07, 0x2d, 0xd6, 0x2b, 0xe7, 0x8e, 0x42, 0x55,
- 0x88, 0x86, 0x76, 0x5b, 0xfd, 0xb0, 0xf3, 0xdc, 0x6e, 0xd6, 0x2f, 0x03,
- 0xdc, 0x58, 0xbf, 0xf8, 0xed, 0xdc, 0x61, 0x30, 0xc9, 0xbe, 0xb1, 0x6e,
- 0x2c, 0x52, 0xc5, 0x78, 0xbe, 0xe8, 0x25, 0x5d, 0x51, 0x4b, 0x83, 0xc0,
- 0x65, 0xa5, 0x8b, 0xa0, 0x14, 0x58, 0xb7, 0x57, 0x35, 0x0c, 0x19, 0x7d,
- 0x82, 0xd6, 0xcb, 0x17, 0xd0, 0xe0, 0xce, 0xb1, 0x4e, 0x79, 0x0c, 0x49,
- 0x7f, 0xf6, 0x74, 0xc1, 0xe1, 0x0a, 0x19, 0xc5, 0x8b, 0xf6, 0xa7, 0xe6,
- 0x0d, 0x62, 0xb4, 0x7d, 0xec, 0x8b, 0x60, 0x2c, 0x5d, 0xb4, 0xac, 0x5f,
- 0xb0, 0x7f, 0x7d, 0x96, 0x2d, 0x3b, 0x1e, 0x9b, 0x89, 0x10, 0xc5, 0xf0,
- 0x6d, 0x9c, 0x58, 0xbf, 0x87, 0x20, 0x2c, 0xed, 0x62, 0xff, 0xa0, 0x76,
- 0x87, 0xb9, 0x26, 0xac, 0x5d, 0xf7, 0x58, 0xa9, 0x45, 0x1e, 0x11, 0xb1,
- 0x77, 0x8e, 0xef, 0xa6, 0x4b, 0x75, 0x8b, 0xdc, 0x72, 0x58, 0xb0, 0x16,
- 0x2f, 0xb7, 0xeb, 0xce, 0xd6, 0x2b, 0x46, 0xe8, 0x84, 0xaf, 0xf1, 0x90,
- 0x9e, 0x8e, 0x40, 0x58, 0xbe, 0x60, 0x98, 0x4b, 0x17, 0xdc, 0x6e, 0xdd,
- 0x62, 0xb1, 0x1e, 0x4c, 0xac, 0x44, 0x1c, 0x36, 0xf1, 0x1d, 0xff, 0xe0,
- 0x19, 0xe7, 0x83, 0xe8, 0x07, 0x7e, 0x2c, 0x50, 0xd7, 0x8e, 0xb2, 0x17,
- 0x9b, 0x90, 0xbc, 0x36, 0xe3, 0xd6, 0x4e, 0xde, 0xd0, 0x8f, 0x03, 0xa1,
- 0x43, 0x5b, 0x87, 0x42, 0x8c, 0x53, 0xa2, 0x3d, 0xd0, 0xfa, 0xc5, 0xf7,
- 0x36, 0x17, 0x16, 0x2e, 0xda, 0x0b, 0x17, 0x9f, 0xee, 0xb1, 0x71, 0xe5,
- 0x62, 0xe8, 0xdc, 0x6b, 0x15, 0x28, 0xa6, 0xc1, 0x8e, 0xc9, 0x7c, 0x32,
- 0x21, 0xc8, 0xe1, 0x7b, 0xff, 0xb6, 0xdf, 0xee, 0x66, 0x8d, 0xce, 0xfc,
- 0xb1, 0x7d, 0x9d, 0xc2, 0x56, 0x2f, 0x09, 0xb8, 0xb1, 0x58, 0x88, 0xbf,
- 0xa5, 0x98, 0x47, 0x7b, 0xcf, 0xb2, 0xc5, 0xff, 0x39, 0xb2, 0x39, 0xe9,
- 0x9f, 0x58, 0xbf, 0x61, 0x47, 0x49, 0xab, 0x17, 0xe9, 0x20, 0x1f, 0xcb,
- 0x17, 0xf9, 0xc3, 0xee, 0x1c, 0xcd, 0xd6, 0x2f, 0xe8, 0x18, 0x00, 0x4f,
- 0x6b, 0x17, 0xb0, 0x3d, 0xd6, 0x2a, 0x51, 0xb4, 0xe5, 0x7f, 0x28, 0x63,
- 0x72, 0x31, 0xbf, 0xf1, 0x0b, 0x9d, 0x46, 0x26, 0xd4, 0x16, 0x2f, 0xe1,
- 0x72, 0x62, 0x16, 0x96, 0x2f, 0x0b, 0x3b, 0x58, 0xbf, 0xb3, 0xb0, 0x67,
- 0xb8, 0xb1, 0x7e, 0x92, 0xee, 0x1c, 0x58, 0xf9, 0xaf, 0xaf, 0xa2, 0xdb,
- 0xc6, 0x02, 0x4d, 0xbd, 0xec, 0x3a, 0xc5, 0xf3, 0x9b, 0xf7, 0x58, 0xbb,
- 0xd9, 0x27, 0x81, 0xf1, 0xdb, 0xfb, 0x0f, 0xad, 0x48, 0xd6, 0x2f, 0xdd,
- 0xf3, 0xcf, 0xb2, 0xc5, 0xfc, 0x22, 0xdb, 0x8f, 0xda, 0xc5, 0xff, 0xd3,
- 0xb0, 0x6d, 0xdf, 0x30, 0x6f, 0xc5, 0x8a, 0x94, 0x51, 0x40, 0xac, 0x8c,
- 0x2d, 0xe5, 0x8b, 0xd2, 0x5b, 0x2c, 0x5f, 0xb0, 0xdf, 0x3e, 0xcb, 0x17,
- 0x40, 0x6b, 0x17, 0x67, 0x6b, 0x15, 0x86, 0xc0, 0x03, 0x17, 0xa4, 0xbc,
- 0xb1, 0x52, 0x8c, 0x51, 0x89, 0x76, 0x3a, 0x05, 0xae, 0x84, 0x17, 0xfb,
- 0xdc, 0x14, 0x3a, 0xe1, 0x2c, 0x5f, 0xff, 0xd0, 0xe1, 0x64, 0x5d, 0x77,
- 0xfc, 0xee, 0x6e, 0x98, 0x35, 0x8b, 0xd8, 0xfb, 0x2c, 0x5d, 0x3b, 0x76,
- 0x88, 0x02, 0x63, 0xa6, 0x47, 0x28, 0xa1, 0x6d, 0x7f, 0xfe, 0x9d, 0x03,
- 0x38, 0x42, 0x68, 0x7c, 0x4d, 0xb2, 0xc5, 0xe2, 0xce, 0x8b, 0x17, 0xef,
- 0x63, 0x16, 0xeb, 0x15, 0xf4, 0x4e, 0x79, 0x58, 0x20, 0xf5, 0xff, 0xe9,
- 0x06, 0xb5, 0x21, 0xf5, 0xf7, 0x33, 0x65, 0x8b, 0xdd, 0xc9, 0xd6, 0x2f,
- 0xff, 0x0f, 0xf3, 0xdc, 0x0b, 0x0f, 0x9d, 0xf9, 0x62, 0xfc, 0x7c, 0xfe,
- 0x12, 0xc5, 0x39, 0xf9, 0xb2, 0x65, 0xfe, 0x83, 0x90, 0xa4, 0x8d, 0x58,
- 0xbf, 0xdf, 0x7e, 0x08, 0xf2, 0xeb, 0x17, 0xcd, 0x1c, 0xc6, 0xac, 0x5e,
- 0xce, 0xfd, 0xb9, 0xec, 0xfc, 0xce, 0xff, 0x34, 0x07, 0x98, 0x0e, 0x2c,
- 0x53, 0x9f, 0x40, 0x8d, 0x6f, 0xfd, 0xd3, 0xed, 0x0e, 0xbe, 0xfb, 0x1a,
- 0xb1, 0x7f, 0x81, 0x85, 0x14, 0xe6, 0x96, 0x2b, 0x0f, 0xe1, 0x91, 0x6e,
- 0x62, 0x58, 0xb9, 0x82, 0x2c, 0x5c, 0x7c, 0xd1, 0xaf, 0xf8, 0xb5, 0xff,
- 0xbb, 0x87, 0xe4, 0xed, 0xdc, 0x31, 0x62, 0xfe, 0x7e, 0xfb, 0x86, 0x79,
- 0x62, 0xa5, 0x13, 0xb8, 0x58, 0x04, 0x1a, 0xed, 0x55, 0x3f, 0xe1, 0xe8,
- 0x50, 0x99, 0xe4, 0x3b, 0x2f, 0xdd, 0xf0, 0xef, 0x1e, 0xb1, 0x73, 0x3a,
- 0xc5, 0xff, 0xdf, 0x67, 0xf0, 0x04, 0x44, 0xd0, 0x58, 0xbf, 0xe6, 0x27,
- 0x3f, 0x7c, 0x98, 0x96, 0x2f, 0xa4, 0x84, 0x17, 0x58, 0xbe, 0x3c, 0xf7,
- 0x05, 0x8b, 0xb3, 0x9d, 0x51, 0x8f, 0xb2, 0x1f, 0xce, 0x80, 0x4d, 0x52,
- 0x9a, 0xab, 0x16, 0x94, 0x37, 0x6f, 0x98, 0x1e, 0x0b, 0xac, 0x5f, 0xcd,
- 0xb0, 0x18, 0x86, 0xb1, 0x7d, 0xef, 0xb1, 0xd6, 0x2f, 0xff, 0x60, 0x7d,
- 0xc3, 0x9c, 0x93, 0xb7, 0x7e, 0x58, 0xa9, 0x3f, 0x17, 0x23, 0xad, 0x99,
- 0xa7, 0x63, 0x8c, 0x54, 0xd4, 0x6d, 0xe1, 0xf1, 0xdb, 0x83, 0x96, 0x45,
- 0x0d, 0x0d, 0x43, 0xcc, 0xf1, 0x98, 0xfe, 0x18, 0x60, 0x32, 0x24, 0xfe,
- 0x42, 0x47, 0xd2, 0xb1, 0xfa, 0x47, 0x46, 0x19, 0x9c, 0x71, 0x38, 0x48,
- 0x4f, 0xdf, 0x45, 0x99, 0xba, 0xc5, 0xf6, 0x44, 0xe7, 0x58, 0xad, 0x1e,
- 0x38, 0x09, 0x2f, 0xfb, 0xff, 0xc7, 0xee, 0x19, 0xa5, 0x8b, 0xef, 0xe7,
- 0x70, 0x58, 0xa9, 0x44, 0x03, 0x11, 0x70, 0xea, 0xff, 0x78, 0x5b, 0x4f,
- 0xa4, 0x6b, 0x17, 0xbd, 0x84, 0xb1, 0x7b, 0xed, 0x1e, 0xb1, 0x71, 0x79,
- 0x62, 0xfc, 0x28, 0x60, 0x38, 0xb1, 0x7f, 0x8c, 0x9d, 0xe3, 0xb3, 0x52,
- 0xb1, 0x7f, 0xc3, 0xc1, 0x6b, 0x6d, 0xdf, 0x65, 0x8b, 0xc5, 0x1a, 0x79,
- 0x62, 0xff, 0xf7, 0x4c, 0x21, 0x93, 0x07, 0xce, 0x48, 0x16, 0x2f, 0xff,
- 0xfe, 0x3b, 0xf3, 0xac, 0x50, 0x11, 0x7b, 0xaf, 0xe6, 0x0e, 0x58, 0x79,
- 0x58, 0xac, 0x46, 0x10, 0x93, 0x2f, 0x9f, 0x52, 0x75, 0x8a, 0xd1, 0xe2,
- 0x7c, 0x8a, 0xf1, 0x60, 0x6b, 0x17, 0xff, 0xdb, 0xfc, 0x45, 0x9d, 0xc1,
- 0xf8, 0x59, 0xd1, 0x62, 0xfd, 0xf9, 0xfb, 0x9a, 0xb1, 0x73, 0x45, 0xc3,
- 0xfc, 0x08, 0xa7, 0x79, 0xf4, 0x6a, 0xc5, 0x4a, 0x61, 0x31, 0x11, 0x7e,
- 0x13, 0x31, 0xc6, 0x17, 0xff, 0xf9, 0xfa, 0x10, 0xb9, 0xd4, 0xc2, 0x91,
- 0xfd, 0xa1, 0x9c, 0x58, 0xa8, 0x2b, 0xcd, 0x34, 0x71, 0xc8, 0x34, 0x2f,
- 0xf2, 0x96, 0x38, 0x23, 0xdf, 0x4a, 0x31, 0xe8, 0x8d, 0x7e, 0xc8, 0xa0,
- 0xc4, 0xb1, 0x7e, 0xcd, 0x14, 0x81, 0x62, 0xee, 0x81, 0x16, 0x2e, 0x3e,
- 0x2c, 0x54, 0xb6, 0x98, 0x5b, 0x18, 0x65, 0x35, 0x65, 0xe5, 0x00, 0x68,
- 0xb9, 0xa7, 0x00, 0xbd, 0x08, 0x71, 0x14, 0x47, 0x13, 0x98, 0x39, 0x7f,
- 0x39, 0xc5, 0x14, 0xf9, 0x62, 0xfb, 0xff, 0x73, 0x56, 0x2e, 0x88, 0x4b,
- 0x17, 0xfe, 0x36, 0x4b, 0x76, 0x7d, 0xba, 0xe2, 0xc5, 0x8e, 0xb1, 0x58,
- 0x89, 0x1e, 0xc9, 0x1c, 0x64, 0x2e, 0x85, 0x7f, 0xbc, 0x01, 0x17, 0x1c,
- 0x6b, 0x17, 0xe8, 0x03, 0x30, 0x6b, 0x16, 0xe8, 0xe7, 0xb8, 0xc6, 0x97,
- 0xef, 0xbe, 0x80, 0x25, 0x8b, 0xa6, 0x0b, 0x17, 0xe9, 0xef, 0xd3, 0xa5,
- 0x8b, 0xcf, 0xf1, 0x2c, 0x5b, 0x58, 0x8a, 0xe8, 0x8a, 0x34, 0x52, 0x71,
- 0x7f, 0x14, 0xdf, 0xc1, 0xf1, 0xa7, 0xb8, 0x2c, 0x54, 0xa2, 0x03, 0x14,
- 0x2f, 0xf3, 0x83, 0xdd, 0xee, 0xfa, 0x58, 0xbf, 0xec, 0xed, 0xbd, 0x3e,
- 0x60, 0x2c, 0x5f, 0xfe, 0xc2, 0xdb, 0x76, 0x1e, 0xb5, 0x27, 0xe2, 0xc5,
- 0xff, 0xc5, 0x3e, 0xe7, 0xbb, 0xdd, 0xcb, 0x65, 0x8b, 0xf0, 0x47, 0xee,
- 0x1c, 0x58, 0xa8, 0x8f, 0xcd, 0x91, 0xef, 0xf3, 0x91, 0xac, 0x28, 0x0d,
- 0x62, 0xf8, 0xe6, 0x45, 0xc5, 0x8a, 0xc3, 0xda, 0x73, 0x4b, 0xf8, 0xb3,
- 0xc2, 0x92, 0x58, 0xbf, 0x77, 0x02, 0x91, 0xac, 0x51, 0xcf, 0x55, 0x8b,
- 0x2f, 0xe8, 0x39, 0x1d, 0xbc, 0xb1, 0x7f, 0xc3, 0xce, 0xbc, 0x72, 0xee,
- 0x0b, 0x16, 0x9e, 0xcf, 0xa4, 0x32, 0xda, 0x95, 0x53, 0x98, 0x72, 0xf0,
- 0xbf, 0xfb, 0xe3, 0x3a, 0x94, 0x22, 0xaf, 0x66, 0xd2, 0xb1, 0x7b, 0xd9,
- 0xf5, 0x8b, 0x34, 0x0d, 0xd7, 0xc7, 0x6f, 0xec, 0x10, 0x5c, 0x5e, 0x31,
- 0x62, 0xff, 0xf6, 0x11, 0x80, 0xeb, 0x9b, 0xe3, 0x94, 0xac, 0x56, 0x8f,
- 0xff, 0xe6, 0x97, 0xff, 0x4f, 0x39, 0x87, 0xf1, 0x49, 0xf8, 0xb1, 0x7f,
- 0xd3, 0xa3, 0x7e, 0x53, 0x9a, 0x58, 0xbf, 0x8d, 0xeb, 0x87, 0x9d, 0xd6,
- 0x2f, 0xfe, 0x9e, 0xe1, 0xe1, 0x4e, 0xcf, 0xdf, 0x96, 0x2f, 0xf3, 0xfd,
- 0xb7, 0x92, 0x1a, 0xc5, 0x3a, 0x2b, 0x48, 0xcb, 0x89, 0x17, 0xf4, 0xee,
- 0x03, 0x88, 0x0b, 0x17, 0xdd, 0x1c, 0x86, 0xb1, 0x7f, 0xe2, 0x91, 0xfe,
- 0x4e, 0x59, 0xba, 0xc5, 0xe7, 0x2f, 0x2c, 0x56, 0x1f, 0xf4, 0x44, 0x9f,
- 0x3e, 0xbf, 0xc3, 0xe3, 0xff, 0xf8, 0x35, 0x8b, 0xff, 0x4f, 0x09, 0xa1,
- 0xd7, 0x99, 0xa5, 0x8b, 0xf4, 0x22, 0x29, 0x1a, 0xc5, 0x39, 0xf4, 0xb2,
- 0x05, 0xf8, 0x78, 0x53, 0x1e, 0xb1, 0x7f, 0x16, 0x43, 0xf2, 0x35, 0x8a,
- 0xd8, 0xf5, 0xc6, 0x55, 0x78, 0x9b, 0x4b, 0x17, 0xcc, 0xcc, 0x11, 0x62,
- 0xff, 0xff, 0xff, 0x7f, 0x1f, 0x50, 0xea, 0x59, 0x14, 0x24, 0xbd, 0xd4,
- 0x1c, 0xeb, 0xc3, 0xb4, 0x0d, 0xf2, 0xc5, 0xff, 0xfd, 0x83, 0xea, 0xe0,
- 0x9e, 0xbe, 0xfe, 0x7b, 0xed, 0x05, 0x8b, 0xff, 0xb9, 0xb6, 0x07, 0x84,
- 0x20, 0x93, 0x19, 0x89, 0x9a, 0x9c, 0x73, 0xc4, 0x7d, 0x21, 0x2f, 0x7e,
- 0xf7, 0x18, 0x8d, 0x58, 0xbf, 0xf4, 0x66, 0xee, 0x6f, 0xda, 0x19, 0xc5,
- 0x8a, 0xd8, 0xfb, 0x78, 0x53, 0x52, 0xa9, 0xad, 0xe3, 0x58, 0x32, 0x1e,
- 0x17, 0xfb, 0xb8, 0x72, 0x28, 0x4e, 0xcb, 0x17, 0xfd, 0xac, 0x35, 0x87,
- 0xf9, 0xd2, 0xc5, 0x0d, 0x7c, 0xa7, 0x21, 0x4b, 0xb9, 0x14, 0x48, 0x9a,
- 0x87, 0x31, 0xcb, 0xbf, 0x0a, 0xe6, 0x2f, 0x28, 0x4e, 0xfa, 0x57, 0x10,
- 0x8f, 0x3a, 0x1c, 0x5f, 0xff, 0xde, 0xce, 0xfd, 0xad, 0x4f, 0x80, 0x61,
- 0x43, 0xf8, 0xb1, 0x73, 0xf4, 0x58, 0xbe, 0x92, 0x87, 0x16, 0x2c, 0xfd,
- 0xa2, 0x66, 0x25, 0xe0, 0x0c, 0xdf, 0xed, 0x6c, 0x53, 0xbb, 0xc1, 0x62,
- 0xbe, 0x7d, 0x8c, 0x6f, 0x7e, 0xfc, 0xf4, 0x1c, 0xac, 0x5e, 0x1b, 0x12,
- 0xc5, 0xba, 0x2c, 0x5f, 0xbb, 0xf1, 0x4f, 0xd6, 0x2d, 0xa9, 0x37, 0xac,
- 0x29, 0x7d, 0xdc, 0x53, 0xa5, 0x8b, 0x69, 0x62, 0xb0, 0xdb, 0x88, 0x96,
- 0xef, 0xba, 0xc5, 0xff, 0xfa, 0x7d, 0xf6, 0x8b, 0x8c, 0xfb, 0x93, 0x66,
- 0xeb, 0x15, 0x04, 0xdb, 0x06, 0x55, 0xa5, 0x9e, 0x2e, 0x74, 0x20, 0x8e,
- 0x17, 0xbe, 0x7e, 0x98, 0x35, 0x8b, 0xe2, 0xf6, 0x12, 0xc5, 0xc5, 0xed,
- 0x1e, 0x2b, 0x12, 0x5f, 0xf7, 0x70, 0xe0, 0xbd, 0x3e, 0xe2, 0xc5, 0xfb,
- 0x50, 0x6e, 0xc3, 0x58, 0xbf, 0xdc, 0x0d, 0x87, 0x3d, 0xf1, 0x62, 0xa5,
- 0x19, 0x38, 0x58, 0xe7, 0x8c, 0x57, 0x7e, 0xe0, 0xbd, 0x24, 0xb1, 0x7f,
- 0x85, 0xdc, 0x3d, 0xc1, 0x47, 0xac, 0x5f, 0x83, 0x1f, 0xdc, 0xeb, 0x17,
- 0xb9, 0x3d, 0xac, 0x5e, 0x9f, 0xf1, 0x62, 0xfd, 0x9f, 0x87, 0x60, 0x58,
- 0xb0, 0x7d, 0x9f, 0x28, 0x07, 0xbc, 0x3b, 0x58, 0x8c, 0x66, 0x84, 0x7d,
- 0xff, 0xf4, 0x91, 0x99, 0x17, 0xd8, 0xf8, 0x36, 0x82, 0xc5, 0x41, 0x3d,
- 0x7c, 0x39, 0xf9, 0x41, 0x46, 0x00, 0x19, 0x35, 0xfe, 0xce, 0xfa, 0xe7,
- 0xdf, 0xeb, 0x17, 0x7c, 0x6b, 0x17, 0x3e, 0xeb, 0x17, 0x37, 0x86, 0x6c,
- 0x23, 0x86, 0x2b, 0x48, 0x95, 0x66, 0x6b, 0x4a, 0xc5, 0xfd, 0xa9, 0x78,
- 0x37, 0x16, 0x28, 0x66, 0xfb, 0xb1, 0x1b, 0xfc, 0xc0, 0xc8, 0xa4, 0xee,
- 0xb1, 0x7f, 0xde, 0xe0, 0xa0, 0x60, 0xdf, 0xcb, 0x17, 0xa7, 0x34, 0xb1,
- 0x7e, 0x11, 0xbf, 0x7e, 0x2c, 0x5e, 0x26, 0x36, 0x23, 0xc6, 0xd0, 0xe5,
- 0x4a, 0x61, 0x78, 0x44, 0xc6, 0x62, 0x84, 0x15, 0xff, 0xfe, 0x8c, 0xcd,
- 0x08, 0xb9, 0xee, 0xf7, 0x7d, 0x79, 0x81, 0xc5, 0x8b, 0xe9, 0xc8, 0x32,
- 0xc5, 0x0d, 0x11, 0x1f, 0x67, 0xbd, 0x8f, 0xc5, 0x8b, 0xf7, 0xbd, 0x82,
- 0xd9, 0x62, 0xff, 0xfb, 0x66, 0xfe, 0x0f, 0xae, 0x11, 0x63, 0x81, 0x62,
- 0xb6, 0x44, 0xb6, 0xe3, 0x9a, 0x2a, 0xbf, 0xed, 0x03, 0x34, 0x02, 0x10,
- 0x16, 0x2f, 0xc0, 0x6e, 0xe0, 0x75, 0x8b, 0xfd, 0x0f, 0x16, 0x73, 0xee,
- 0xb1, 0x52, 0x89, 0x78, 0x8e, 0x98, 0xaa, 0xfe, 0x26, 0x37, 0x99, 0xa5,
- 0x8b, 0xff, 0xe6, 0xff, 0xdf, 0xac, 0x1c, 0xf3, 0xf3, 0x06, 0xb1, 0x47,
- 0x44, 0x0f, 0x42, 0xeb, 0xff, 0xd9, 0xad, 0x34, 0x3a, 0xfe, 0x7d, 0xc6,
- 0x58, 0xbd, 0xed, 0x83, 0x58, 0xbf, 0x9c, 0x7a, 0x71, 0x6c, 0xb1, 0x7b,
- 0x4d, 0xce, 0xa7, 0x9f, 0xe2, 0x0b, 0x7a, 0x51, 0xeb, 0x02, 0x51, 0x42,
- 0x6e, 0xff, 0x6e, 0xed, 0xd7, 0x8d, 0xf5, 0x8a, 0x73, 0xf0, 0xf9, 0xd5,
- 0x0d, 0x5d, 0xc6, 0x42, 0xe5, 0xe1, 0x92, 0xd2, 0x85, 0x6f, 0x70, 0x46,
- 0xac, 0x5e, 0xfb, 0x86, 0xb1, 0x7f, 0xfe, 0xfb, 0x9d, 0x87, 0xcc, 0x26,
- 0xef, 0x58, 0x75, 0x8b, 0xe2, 0x98, 0x3a, 0xc5, 0xe6, 0x28, 0x96, 0x2f,
- 0x77, 0x07, 0x58, 0xb3, 0x1c, 0xdd, 0x90, 0xed, 0xe1, 0x49, 0x2c, 0x5f,
- 0xd0, 0x9e, 0x91, 0xc2, 0xd2, 0xc5, 0xff, 0xfe, 0x7f, 0x49, 0x34, 0x30,
- 0x7c, 0x6d, 0x3f, 0xdf, 0xa2, 0xc5, 0xf4, 0x94, 0x38, 0xb1, 0x58, 0x9f,
- 0x2e, 0xe3, 0xee, 0x3d, 0xa5, 0x5f, 0xae, 0x11, 0x28, 0x87, 0x3a, 0x1a,
- 0x18, 0xc1, 0x7f, 0xfe, 0xe1, 0x75, 0xfb, 0x3f, 0x80, 0x22, 0x26, 0x82,
- 0xc5, 0xff, 0xff, 0xd3, 0xac, 0x8a, 0x4f, 0x9b, 0xb8, 0xff, 0x3e, 0xe1,
- 0xba, 0xc0, 0x8b, 0x17, 0xe2, 0x98, 0x01, 0xd6, 0x2f, 0xe7, 0x36, 0x38,
- 0x5a, 0x35, 0x62, 0xff, 0x14, 0x8b, 0xbe, 0x34, 0x7a, 0xc5, 0x7c, 0xfa,
- 0xd8, 0xd2, 0xfa, 0x70, 0x3f, 0x2c, 0x5f, 0xdb, 0xcf, 0x60, 0xd4, 0xac,
- 0x5f, 0xe9, 0x2d, 0xd8, 0x80, 0x15, 0x58, 0xa9, 0x3e, 0x73, 0x98, 0x5c,
- 0x5b, 0xac, 0x52, 0xc5, 0xf6, 0x47, 0x38, 0x16, 0x2a, 0x36, 0x36, 0x3a,
- 0x0c, 0xb3, 0xe1, 0xf7, 0x9d, 0x26, 0xff, 0xa4, 0x1a, 0xd4, 0x86, 0x3e,
- 0xd6, 0x2f, 0xf0, 0x67, 0xfc, 0xb9, 0x6c, 0xb1, 0x7f, 0xf9, 0xa0, 0xfa,
- 0xce, 0xe2, 0x84, 0xeb, 0x65, 0x8b, 0xff, 0xfc, 0x03, 0xb4, 0x33, 0xa3,
- 0xf3, 0xf8, 0x08, 0xec, 0xfb, 0xac, 0x54, 0xa3, 0x9c, 0x06, 0xa2, 0x4d,
- 0xb8, 0x3e, 0x2c, 0x5f, 0xf1, 0xe7, 0x7c, 0xf3, 0xeb, 0x16, 0x2e, 0x6f,
- 0x2c, 0x5e, 0x2c, 0xe7, 0x53, 0xe9, 0xc1, 0x92, 0x39, 0xbf, 0x9b, 0x61,
- 0xe6, 0x71, 0x62, 0xb1, 0x70, 0x6f, 0x78, 0x49, 0x44, 0x42, 0x78, 0x45,
- 0x7e, 0x12, 0x00, 0x26, 0xf4, 0x64, 0x7d, 0x21, 0x31, 0x1c, 0x7f, 0x7f,
- 0xdc, 0xf0, 0xbb, 0xc1, 0xb1, 0x2c, 0x5f, 0xff, 0xfd, 0x09, 0xea, 0x3c,
- 0x26, 0xe7, 0xd8, 0x1c, 0xeb, 0x9e, 0x9f, 0x71, 0x62, 0xa2, 0x45, 0x7f,
- 0x8e, 0xae, 0x17, 0x6b, 0x17, 0xf4, 0x9e, 0x73, 0xbf, 0x2c, 0x5b, 0x0e,
- 0x78, 0xfe, 0x19, 0xa9, 0x5e, 0x73, 0xc9, 0xc9, 0x16, 0x8d, 0x40, 0x4d,
- 0x77, 0xfb, 0x69, 0x2f, 0x7d, 0xa0, 0xb1, 0x7d, 0xf6, 0x63, 0xac, 0x5f,
- 0xd8, 0x59, 0xc9, 0xd2, 0xc5, 0x68, 0xf3, 0x8c, 0x22, 0xbf, 0x82, 0xba,
- 0x79, 0x3e, 0x2c, 0x5d, 0xa3, 0x56, 0x2a, 0x51, 0xdf, 0x90, 0x82, 0x22,
- 0x33, 0x0c, 0x6f, 0xfb, 0xb8, 0x47, 0x39, 0x7a, 0x4e, 0xb1, 0x7b, 0x9d,
- 0x5d, 0x62, 0xb0, 0xf7, 0x3c, 0x7b, 0x7f, 0x6d, 0x9a, 0x7d, 0xe5, 0x62,
- 0xf8, 0x87, 0x27, 0x58, 0xbf, 0xfe, 0x11, 0x7b, 0x9f, 0x78, 0x8a, 0x4e,
- 0xd0, 0x58, 0xbf, 0xb5, 0x2f, 0x06, 0xe2, 0xc5, 0xc2, 0x65, 0x8b, 0x67,
- 0x53, 0xc4, 0x22, 0xda, 0x3a, 0x2f, 0x3a, 0x42, 0x52, 0xfe, 0x60, 0x60,
- 0xda, 0x0b, 0x15, 0x29, 0x9a, 0xe4, 0x37, 0x9c, 0xaa, 0xf8, 0x1c, 0x8d,
- 0x41, 0x55, 0x8b, 0xed, 0xdb, 0x5b, 0x2c, 0x5f, 0x81, 0xce, 0xb3, 0xe5,
- 0x8a, 0x93, 0xd0, 0x62, 0x5a, 0x95, 0x4a, 0xce, 0x43, 0xf8, 0xd9, 0x18,
- 0xcc, 0x9f, 0xaf, 0xdf, 0x03, 0xe8, 0xd5, 0x8b, 0xdb, 0x99, 0x05, 0x8b,
- 0xe9, 0xd0, 0x5f, 0x8b, 0x15, 0xf3, 0xc7, 0x01, 0x05, 0xfb, 0xb0, 0x36,
- 0x7d, 0x62, 0xfe, 0x0d, 0x87, 0x3d, 0xf1, 0x62, 0x9c, 0xf6, 0x40, 0x53,
- 0x7f, 0x87, 0xfc, 0x00, 0xbd, 0xc5, 0x8b, 0xec, 0x09, 0x3a, 0x58, 0xbf,
- 0xff, 0xff, 0xb2, 0x3f, 0x07, 0xc9, 0x1c, 0xfb, 0xf8, 0x2d, 0xff, 0x3c,
- 0xfe, 0x71, 0xa4, 0xeb, 0x17, 0xef, 0xe4, 0x20, 0xcb, 0x17, 0xff, 0xd9,
- 0xfd, 0xfe, 0xf1, 0x13, 0x07, 0xec, 0xfa, 0xc5, 0x62, 0xa6, 0xb7, 0x71,
- 0xd3, 0xdb, 0x10, 0x91, 0xaf, 0x09, 0x3d, 0x08, 0xb8, 0xe2, 0x8b, 0xef,
- 0xf2, 0x77, 0x58, 0xbe, 0xf3, 0xe4, 0x4b, 0x16, 0x35, 0x62, 0xb0, 0xf6,
- 0xbb, 0x24, 0x72, 0x3b, 0xe8, 0x14, 0xec, 0xb1, 0x71, 0x80, 0x58, 0xad,
- 0x1b, 0xce, 0x11, 0xde, 0xc7, 0x89, 0x62, 0xf4, 0x91, 0xab, 0x15, 0x27,
- 0xb6, 0x32, 0x1e, 0x0e, 0xd7, 0x57, 0x59, 0x95, 0x30, 0xc0, 0xda, 0x3c,
- 0xa8, 0x10, 0x8e, 0x56, 0x96, 0x4f, 0xe0, 0xef, 0x1e, 0x4b, 0xc7, 0x1b,
- 0x14, 0xb4, 0x2d, 0x43, 0x94, 0xf1, 0xb5, 0xfe, 0x72, 0x01, 0xa5, 0x19,
- 0x02, 0x10, 0x05, 0x3d, 0x93, 0xc8, 0xce, 0xbd, 0x2b, 0xc8, 0x52, 0xae,
- 0x43, 0x86, 0x89, 0x90, 0xc5, 0xbf, 0xfb, 0xdc, 0xfe, 0x44, 0x42, 0xee,
- 0x1c, 0x58, 0xa5, 0x8b, 0xff, 0xb0, 0x81, 0x99, 0xae, 0x7a, 0x71, 0x62,
- 0xff, 0xbb, 0xf6, 0x69, 0xf6, 0x63, 0xac, 0x5e, 0xce, 0x98, 0xb1, 0x40,
- 0x44, 0xd9, 0x21, 0x70, 0xee, 0xfe, 0x84, 0xf6, 0x0d, 0x4a, 0xc5, 0x4a,
- 0x69, 0xb0, 0x48, 0xc8, 0x53, 0xf6, 0x5f, 0x78, 0x2f, 0x07, 0x58, 0xbe,
- 0x92, 0x68, 0x2c, 0x5f, 0x70, 0xcd, 0xa5, 0x62, 0xf3, 0x10, 0x3a, 0x9f,
- 0x3e, 0x88, 0x78, 0x43, 0x7f, 0xbe, 0xd0, 0xeb, 0xad, 0x4a, 0xc5, 0x47,
- 0x9f, 0xbf, 0xd0, 0x6f, 0xf0, 0xc7, 0x30, 0xf9, 0x9c, 0x58, 0xac, 0x3d,
- 0xb7, 0x25, 0xbc, 0x76, 0x89, 0x62, 0xff, 0xd0, 0x62, 0x0d, 0x87, 0x3d,
- 0xf1, 0x62, 0xfe, 0x73, 0xcf, 0xcc, 0x1a, 0xc5, 0xff, 0x19, 0xe7, 0x21,
- 0x43, 0x38, 0xb1, 0x50, 0x3e, 0x97, 0x2f, 0xbd, 0xc6, 0x25, 0x8b, 0xf7,
- 0xde, 0x75, 0xc5, 0x8a, 0xdd, 0x32, 0xc8, 0x87, 0xbf, 0x0a, 0x9e, 0x10,
- 0xf4, 0x1c, 0xbf, 0xff, 0x43, 0x85, 0x9e, 0xe3, 0xe1, 0xfd, 0xac, 0x0d,
- 0x62, 0xff, 0xdf, 0x73, 0x8f, 0x22, 0x9c, 0xd2, 0xc5, 0xe8, 0x4f, 0x6b,
- 0x17, 0xe1, 0x10, 0xa7, 0xb5, 0x8b, 0xc7, 0xcf, 0x2c, 0x5f, 0x48, 0x18,
- 0xeb, 0x16, 0x86, 0x23, 0x16, 0x23, 0xf3, 0x8f, 0x00, 0xa4, 0x87, 0x6b,
- 0xb4, 0xda, 0x8a, 0x31, 0xbb, 0xf8, 0x8a, 0x7e, 0x2d, 0x2c, 0x5b, 0x75,
- 0x8b, 0xbd, 0x2b, 0x16, 0xe0, 0x54, 0xd5, 0x38, 0x9d, 0xf4, 0x33, 0x68,
- 0x2c, 0x54, 0xa3, 0x3d, 0xca, 0x99, 0x5c, 0x8a, 0xaf, 0xc5, 0x80, 0x17,
- 0x16, 0x2f, 0xf7, 0x52, 0x6d, 0x8a, 0x7b, 0x58, 0xbf, 0xf7, 0xdf, 0xdf,
- 0xc7, 0xf4, 0x81, 0x62, 0xed, 0xdf, 0x11, 0x39, 0xa2, 0x8e, 0x1b, 0x5d,
- 0xcf, 0x2c, 0x5f, 0x86, 0xc5, 0x20, 0x58, 0xad, 0xcd, 0xf9, 0x83, 0x17,
- 0xf7, 0x06, 0xe0, 0x92, 0x58, 0xbf, 0x9b, 0xc0, 0x30, 0xa0, 0xb1, 0x5b,
- 0x1f, 0xff, 0x64, 0x7f, 0x2d, 0xbf, 0xc2, 0x9e, 0x99, 0xe7, 0xd2, 0xc5,
- 0xef, 0xbc, 0x4b, 0x17, 0xfd, 0x3b, 0xe0, 0xe7, 0xb8, 0x71, 0x62, 0xb7,
- 0x3d, 0x92, 0x1e, 0xbf, 0xff, 0xed, 0x00, 0x02, 0xe7, 0xdf, 0xd0, 0xcf,
- 0xb0, 0x1c, 0x72, 0xb1, 0x7f, 0xcd, 0xac, 0xe9, 0x9d, 0x24, 0x6b, 0x15,
- 0x88, 0xa3, 0x03, 0x3d, 0xff, 0xf6, 0x1a, 0x6b, 0x8f, 0xef, 0x17, 0xdf,
- 0xbf, 0x2c, 0x51, 0xcf, 0xd8, 0x88, 0xaf, 0xf7, 0x5f, 0xb4, 0x09, 0xc3,
- 0x58, 0xa9, 0x4e, 0x4b, 0x23, 0x3b, 0x72, 0x1b, 0x85, 0xa5, 0x8b, 0xdb,
- 0xb6, 0x96, 0x2f, 0xfd, 0xb6, 0x11, 0xf3, 0xdc, 0x33, 0x8b, 0x17, 0xee,
- 0x6f, 0x3a, 0x35, 0x62, 0xfb, 0x37, 0x93, 0xac, 0x5f, 0xdc, 0x7c, 0x0c,
- 0x86, 0xb1, 0x6d, 0xbe, 0x7a, 0x3c, 0x23, 0xbf, 0x9c, 0x1d, 0xc3, 0x3c,
- 0xb1, 0x5b, 0x26, 0x97, 0xf1, 0x86, 0x1e, 0x02, 0x09, 0x3e, 0x74, 0x29,
- 0xbf, 0xe3, 0x0a, 0x19, 0xd0, 0xb3, 0x8b, 0x17, 0xd0, 0xf6, 0x01, 0x62,
- 0xf7, 0x1e, 0x25, 0x8a, 0xec, 0xf0, 0x78, 0x47, 0x7e, 0xe3, 0x97, 0x70,
- 0x58, 0xbd, 0xf1, 0x6e, 0xb1, 0x58, 0x79, 0x1e, 0x29, 0xbf, 0x63, 0x8f,
- 0xee, 0xb1, 0x5b, 0x1e, 0x44, 0x08, 0x6f, 0xee, 0x71, 0xcb, 0xb8, 0x2c,
- 0x5d, 0xa3, 0x56, 0x2b, 0xb3, 0xc8, 0x62, 0xfb, 0xff, 0x9a, 0x1d, 0x78,
- 0x59, 0xee, 0x64, 0x7a, 0xc5, 0x4a, 0x71, 0x39, 0x0b, 0x36, 0x6b, 0x11,
- 0x15, 0xff, 0xbb, 0xf7, 0x1c, 0xa4, 0x0c, 0x75, 0x8a, 0x58, 0xac, 0x3c,
- 0xbe, 0x87, 0xf7, 0xa0, 0x7f, 0xac, 0x56, 0xc7, 0x83, 0xe2, 0x3b, 0xff,
- 0xff, 0x47, 0x67, 0xbe, 0xc3, 0x8c, 0x2c, 0xe8, 0x59, 0xce, 0x3f, 0x7e,
- 0x58, 0xb7, 0x6b, 0x17, 0xd8, 0x79, 0x8f, 0x58, 0xb7, 0x61, 0x73, 0x71,
- 0xc1, 0x3b, 0xc6, 0xb8, 0x6b, 0x17, 0xe0, 0xdf, 0x08, 0xd5, 0x8a, 0x73,
- 0xc8, 0x10, 0xfd, 0xfe, 0x19, 0x99, 0x17, 0xd8, 0xeb, 0x15, 0x89, 0xcd,
- 0x39, 0x1b, 0x42, 0xb0, 0x9d, 0x04, 0x43, 0x7d, 0xf6, 0x09, 0xc5, 0x8b,
- 0xff, 0x67, 0x7e, 0x0f, 0x08, 0x7f, 0x95, 0x8b, 0x36, 0xe7, 0xcb, 0xa2,
- 0x5b, 0x62, 0xc5, 0xf6, 0xb6, 0x7d, 0x96, 0x2f, 0x7d, 0xf4, 0xb1, 0x66,
- 0x73, 0xc2, 0x88, 0x96, 0xba, 0x9f, 0xd7, 0xd4, 0xee, 0xcf, 0x2c, 0x5e,
- 0x29, 0x3a, 0xc5, 0x49, 0xb3, 0xe0, 0xbd, 0xfe, 0x9e, 0x63, 0xf4, 0x63,
- 0xac, 0x5f, 0xf8, 0x98, 0x3d, 0x4b, 0xc1, 0xb8, 0xb1, 0x5b, 0x1f, 0x94,
- 0x46, 0x97, 0x82, 0xf8, 0x4b, 0x17, 0xba, 0x61, 0x2c, 0x54, 0xa6, 0x97,
- 0xda, 0xbb, 0x42, 0x48, 0x89, 0x3c, 0x41, 0x7b, 0xf0, 0x3a, 0xc5, 0xdf,
- 0x75, 0x8a, 0xc3, 0x6b, 0xe1, 0xea, 0x96, 0xcb, 0xde, 0x11, 0xbd, 0xe4,
- 0x69, 0x86, 0xca, 0x8d, 0xee, 0x1a, 0xaf, 0x0f, 0x9d, 0x18, 0xfe, 0x51,
- 0x03, 0x46, 0xfe, 0x05, 0x92, 0x94, 0x0b, 0xc9, 0x4c, 0xde, 0x85, 0x88,
- 0xa3, 0xed, 0x8e, 0x84, 0x1d, 0xf6, 0x9e, 0x7b, 0x58, 0xbd, 0xfc, 0xdd,
- 0x62, 0xf1, 0xdf, 0x8b, 0x15, 0x86, 0xef, 0x43, 0xd7, 0xdd, 0xf0, 0x47,
- 0x58, 0xb8, 0x0e, 0xb1, 0x74, 0xc4, 0xe6, 0xf1, 0x89, 0x6f, 0x74, 0xc1,
- 0xac, 0x5c, 0xe1, 0xac, 0x5b, 0x75, 0x8a, 0xc3, 0x56, 0x71, 0x8b, 0xf1,
- 0xa6, 0xbe, 0xa0, 0xb1, 0x68, 0x2c, 0x5f, 0xe9, 0xfb, 0x78, 0x42, 0xed,
- 0x62, 0xb8, 0x78, 0xe2, 0x12, 0xbc, 0xdd, 0xc1, 0x62, 0xfc, 0x67, 0xdf,
- 0xbe, 0x2c, 0x50, 0x55, 0x51, 0x64, 0xaf, 0x6c, 0xb9, 0x02, 0xb1, 0xa5,
- 0x68, 0x80, 0x9c, 0xbc, 0x44, 0x21, 0xeb, 0xfb, 0xce, 0x4e, 0x0e, 0x2c,
- 0x5f, 0x0c, 0xb3, 0xeb, 0x16, 0x1f, 0x53, 0xcf, 0x30, 0xb6, 0xfb, 0x52,
- 0x5b, 0xac, 0x5f, 0xb3, 0x82, 0xd6, 0xcb, 0x17, 0xff, 0xff, 0xfd, 0xd8,
- 0x35, 0xbf, 0x23, 0xfa, 0x3c, 0x68, 0x69, 0x81, 0x4e, 0x40, 0x2d, 0xe8,
- 0x2c, 0xea, 0x08, 0xfe, 0xbd, 0x7f, 0x1c, 0xb1, 0x58, 0x99, 0xe3, 0x95,
- 0x91, 0x19, 0x85, 0x57, 0x8e, 0xde, 0x58, 0xba, 0x1e, 0x58, 0xbe, 0xf3,
- 0x77, 0xc5, 0x8b, 0xf0, 0xdf, 0xa4, 0x8d, 0x62, 0xb6, 0x3c, 0xed, 0xc9,
- 0x2d, 0xf5, 0x8b, 0x01, 0x62, 0xe6, 0x0b, 0xac, 0x5d, 0xc8, 0x2c, 0x54,
- 0xa3, 0xf8, 0x63, 0xac, 0xcc, 0x02, 0x4e, 0x09, 0x78, 0x48, 0x43, 0x77,
- 0xf6, 0xd1, 0x42, 0x36, 0xd6, 0xcb, 0x17, 0x40, 0x0b, 0x17, 0x9b, 0x34,
- 0xb1, 0x78, 0xb3, 0xcb, 0x17, 0xbf, 0x87, 0x58, 0xae, 0xcf, 0xb7, 0xe3,
- 0x04, 0x39, 0xe1, 0xcb, 0xbc, 0x4b, 0x17, 0xa7, 0xbe, 0x2c, 0x5f, 0x39,
- 0x43, 0x16, 0x2e, 0x33, 0xeb, 0x17, 0xb6, 0x62, 0x58, 0xbb, 0x5b, 0x2c,
- 0x50, 0xd1, 0x1c, 0x71, 0xef, 0x90, 0xf8, 0x64, 0x43, 0xb7, 0x6b, 0xeb,
- 0x17, 0xd2, 0x36, 0x82, 0xc5, 0xfb, 0x3d, 0xf7, 0xf2, 0xc5, 0xf9, 0xbb,
- 0xce, 0xfc, 0xb1, 0x5f, 0x3d, 0x2f, 0x14, 0x5e, 0x6d, 0x41, 0x62, 0xf7,
- 0xf0, 0xeb, 0x15, 0x03, 0x75, 0xe1, 0xdb, 0xfe, 0x36, 0x2c, 0xcd, 0xfd,
- 0x26, 0xac, 0x5f, 0xcd, 0xac, 0xfc, 0x81, 0x62, 0xe7, 0xe2, 0xc5, 0xc5,
- 0xb2, 0xc5, 0x6e, 0x6b, 0xc4, 0x2f, 0x78, 0xcf, 0xb2, 0xc5, 0x75, 0x4f,
- 0x8b, 0x61, 0x83, 0x5d, 0x3b, 0x5c, 0xd1, 0x09, 0xcf, 0x7e, 0xb9, 0xc2,
- 0x2b, 0xe3, 0xc7, 0x47, 0x8d, 0x62, 0xdb, 0x2c, 0x5b, 0x4b, 0x15, 0xb1,
- 0xa5, 0x71, 0x3b, 0xed, 0x99, 0xbe, 0xb1, 0x7e, 0x16, 0xcc, 0xdf, 0x58,
- 0xbd, 0xb3, 0x6c, 0xb1, 0x7e, 0xc1, 0x81, 0xbc, 0xb1, 0x5d, 0x51, 0x27,
- 0xf2, 0x36, 0x29, 0xe8, 0x3f, 0x7e, 0x32, 0x02, 0x9e, 0x2c, 0x5e, 0xf3,
- 0x0d, 0x62, 0xb6, 0x44, 0x39, 0xa8, 0x04, 0x55, 0x7e, 0x1b, 0xf4, 0x91,
- 0xac, 0x5b, 0xcb, 0x17, 0x47, 0x6e, 0xb1, 0x7f, 0x07, 0x85, 0x3d, 0xf1,
- 0x62, 0xa0, 0x88, 0x7e, 0xca, 0xb4, 0x24, 0xc3, 0x97, 0xd9, 0xd3, 0x06,
- 0xb1, 0x7f, 0x09, 0xb5, 0x06, 0x02, 0xc5, 0xff, 0x16, 0x6b, 0x53, 0xb9,
- 0x87, 0x58, 0xbe, 0x3b, 0x77, 0x18, 0x33, 0xe9, 0x30, 0xba, 0xcc, 0xb1,
- 0x73, 0xeb, 0x0f, 0x3f, 0x87, 0xd7, 0xe8, 0xbe, 0xfd, 0xf9, 0x62, 0xb4,
- 0x99, 0x9f, 0xe1, 0xb9, 0xe2, 0xcb, 0xf6, 0x10, 0xff, 0x2b, 0x15, 0x1b,
- 0xb2, 0x0e, 0x26, 0x14, 0xb0, 0x3c, 0xc8, 0x52, 0xbc, 0xa2, 0xc3, 0xbb,
- 0xfd, 0x3d, 0xa3, 0x3b, 0x28, 0x5c, 0x0a, 0x37, 0x00, 0xcd, 0xaf, 0x82,
- 0x9f, 0x9e, 0x8b, 0x17, 0xfd, 0x83, 0x1b, 0xf7, 0x9d, 0xf9, 0x62, 0xfb,
- 0x72, 0x98, 0x2c, 0x57, 0xcf, 0x79, 0x8e, 0xef, 0xf4, 0xe7, 0xa7, 0xec,
- 0x35, 0x8b, 0xb9, 0x1e, 0xb1, 0x7b, 0xee, 0x75, 0x8b, 0xb3, 0x8b, 0x15,
- 0x86, 0xd2, 0x38, 0x76, 0xff, 0xb3, 0xd3, 0xb9, 0x92, 0x0c, 0x58, 0xbd,
- 0x3d, 0xc1, 0x62, 0xb6, 0x4c, 0x74, 0x64, 0x3a, 0x32, 0x02, 0x78, 0x64,
- 0x61, 0x0e, 0xaf, 0xb3, 0x0b, 0xcb, 0x17, 0xff, 0xba, 0x39, 0x03, 0xee,
- 0xd0, 0xf3, 0xec, 0xb1, 0x7c, 0x26, 0xd4, 0x16, 0x2f, 0xfb, 0x37, 0x9d,
- 0xdb, 0x5b, 0x4a, 0xc5, 0x4a, 0x2a, 0x86, 0x99, 0xf2, 0x3b, 0xff, 0x48,
- 0xf5, 0x3e, 0x7d, 0xdc, 0x6b, 0x17, 0xde, 0xe3, 0x6e, 0xb1, 0x43, 0x3e,
- 0x31, 0x1f, 0xdf, 0x09, 0xb5, 0x05, 0x8b, 0xd2, 0x12, 0x0b, 0x17, 0xa3,
- 0x85, 0xda, 0xc5, 0xf4, 0xe7, 0x70, 0x58, 0xa1, 0xa2, 0x1e, 0x22, 0x3d,
- 0x0f, 0x84, 0x22, 0xbf, 0xbd, 0xb8, 0xc6, 0x7d, 0x2c, 0x5f, 0xff, 0x37,
- 0x1b, 0x4f, 0xd8, 0x3d, 0x09, 0x8e, 0xc5, 0x8b, 0xe7, 0x29, 0x02, 0xc5,
- 0x00, 0xfd, 0x3c, 0xa7, 0x7f, 0xd1, 0x73, 0xa3, 0x16, 0xc2, 0x1a, 0xc5,
- 0xfc, 0xc1, 0x80, 0x07, 0x8e, 0x58, 0xbe, 0xcf, 0x61, 0xd6, 0x2e, 0x23,
- 0x56, 0x29, 0x8d, 0xd0, 0x88, 0xaa, 0x08, 0x8d, 0xe3, 0x6d, 0xfa, 0x04,
- 0x26, 0xe2, 0xc5, 0xff, 0xa4, 0x85, 0xe8, 0x08, 0xbd, 0xc5, 0x8a, 0xc3,
- 0xe7, 0xd1, 0x45, 0xff, 0xf8, 0x73, 0x09, 0xc8, 0x7e, 0x46, 0x53, 0xee,
- 0x2c, 0x5f, 0xf4, 0xfa, 0x19, 0x1e, 0xc4, 0x05, 0x8a, 0xc4, 0x47, 0x92,
- 0xa5, 0xe0, 0x38, 0x16, 0x2f, 0xb6, 0x8b, 0xee, 0xb1, 0x6f, 0xe1, 0xe1,
- 0x08, 0x76, 0xff, 0xe8, 0x13, 0x71, 0xbf, 0xdc, 0x33, 0xcb, 0x17, 0x31,
- 0xd6, 0x2f, 0xfa, 0x3f, 0xef, 0xd4, 0xdd, 0x67, 0x16, 0x2b, 0x11, 0x39,
- 0xba, 0x28, 0x85, 0xef, 0xfc, 0x4c, 0x6f, 0xda, 0x1c, 0x71, 0xac, 0x5f,
- 0xbe, 0xe4, 0xdb, 0x2c, 0x5b, 0x75, 0x8b, 0xe1, 0x43, 0x39, 0xb9, 0xbb,
- 0x22, 0x8a, 0x3a, 0x2c, 0x89, 0xea, 0xee, 0x92, 0xb1, 0x7f, 0xff, 0x6c,
- 0xfa, 0x26, 0x37, 0x9f, 0x96, 0xee, 0x46, 0xeb, 0x17, 0x67, 0x96, 0x2a,
- 0x51, 0x19, 0x83, 0x24, 0xb9, 0x71, 0x87, 0x58, 0xa7, 0x47, 0xa1, 0x42,
- 0xbb, 0xc5, 0xb7, 0xf8, 0x79, 0xce, 0x66, 0xb6, 0x58, 0xb0, 0xd6, 0x2b,
- 0x73, 0xc7, 0xec, 0xd6, 0xee, 0x8c, 0xb1, 0x7f, 0x6a, 0x77, 0xce, 0x98,
- 0xb1, 0x7f, 0x88, 0x1a, 0xd3, 0xc5, 0xc5, 0x8a, 0x93, 0xe5, 0x63, 0x0b,
- 0xd2, 0x12, 0x56, 0x28, 0x28, 0xcb, 0x68, 0x98, 0xe9, 0x36, 0x5c, 0x84,
- 0x32, 0xc7, 0x09, 0x2c, 0x85, 0x49, 0xa8, 0x1d, 0xc2, 0x95, 0xc8, 0xa2,
- 0x86, 0x5e, 0xa1, 0x14, 0x78, 0x58, 0x7d, 0x8c, 0xa1, 0x87, 0xe8, 0xf5,
- 0x84, 0xf5, 0xd0, 0x92, 0x39, 0xf8, 0x21, 0x05, 0xfa, 0x29, 0xf1, 0x74,
- 0x58, 0xbe, 0x8b, 0x1c, 0x0b, 0x15, 0xd4, 0xf3, 0xa4, 0xae, 0xff, 0xe9,
- 0xe9, 0xa9, 0xd6, 0x3f, 0xe4, 0x6b, 0x17, 0x4e, 0x2c, 0x51, 0x1e, 0xdf,
- 0x11, 0x6f, 0x8e, 0x14, 0x8d, 0x71, 0xb2, 0xc5, 0xcc, 0x75, 0x8b, 0xa2,
- 0x8e, 0x58, 0xa2, 0x36, 0x7d, 0x05, 0xef, 0xe9, 0xf3, 0x44, 0xde, 0x58,
- 0xb0, 0xd6, 0x2f, 0xff, 0x77, 0x0e, 0x75, 0xfe, 0x7b, 0x84, 0xde, 0x58,
- 0xb3, 0xe8, 0xf8, 0x0e, 0x25, 0x70, 0xbc, 0xb1, 0x7e, 0x11, 0x7b, 0x00,
- 0xb1, 0x50, 0x54, 0x39, 0x8f, 0xdd, 0x90, 0xbb, 0x31, 0xc8, 0xbd, 0x08,
- 0xe8, 0xe2, 0x70, 0x83, 0x16, 0x8c, 0x8d, 0xe3, 0x38, 0x90, 0x0a, 0x46,
- 0x18, 0x15, 0x8c, 0xa2, 0x34, 0x8c, 0xba, 0x36, 0x8f, 0x5c, 0x2d, 0xc2,
- 0xe0, 0x2c, 0x36, 0x0b, 0x58, 0xc9, 0xa3, 0x53, 0xf4, 0x6b, 0x6e, 0x9a,
- 0x7a, 0xce, 0xd3, 0x89, 0xb0, 0x9e, 0x85, 0x1d, 0x37, 0xab, 0x2d, 0x10,
- 0xa9, 0xb3, 0x99, 0x7b, 0xd2, 0xec, 0x3b, 0x9e, 0x7e, 0x79, 0xeb, 0x08,
- 0xf8, 0x77, 0xc5, 0x4a, 0xe0, 0xd5, 0x28, 0xec, 0xf3, 0xef, 0xbf, 0xaf,
- 0xaa, 0x9a, 0x96, 0x20, 0x09, 0xf7, 0x90, 0xbc, 0x6d, 0x45, 0x5a, 0xd3,
- 0x72, 0xd6, 0xbc, 0x7a, 0xb5, 0xcb, 0x14, 0xb4, 0x5e, 0x92, 0x83, 0x83,
- 0x8c, 0xea, 0x3a, 0x91, 0x34, 0x65, 0x30, 0x9c, 0x24, 0xba, 0xdb, 0xf4,
- 0x63, 0xe9, 0xb4, 0xb1, 0x51, 0x91, 0x9e, 0xce, 0xec, 0xac, 0xe5, 0x7f,
- 0xcc, 0xe7, 0x00, 0x12, 0xcc, 0x6f, 0xff, 0x46, 0x1d, 0xa1, 0x19, 0x9a,
- 0xdd, 0x9b, 0x75, 0x44, 0xd8, 0x5f, 0xb5, 0xbb, 0x36, 0xea, 0x8a, 0xb4,
- 0xb8, 0x1d, 0x16, 0x2e, 0xe4, 0x72, 0xc5, 0xa3, 0x30, 0xfb, 0x3e, 0x6f,
- 0xc1, 0xab, 0xba, 0x69, 0x62, 0xe6, 0x95, 0x8b, 0xfd, 0x08, 0x0b, 0xc5,
- 0x30, 0x58, 0xbe, 0xcf, 0xb7, 0x96, 0x2b, 0x0f, 0x58, 0x8d, 0x2f, 0xfc,
- 0x0f, 0xb4, 0x1e, 0x1f, 0x7e, 0x8b, 0x14, 0x15, 0x3e, 0x1e, 0x10, 0x5f,
- 0xff, 0xee, 0x92, 0xfa, 0xdd, 0xce, 0xd0, 0x72, 0xc1, 0xe1, 0xab, 0x17,
- 0xfe, 0x26, 0x70, 0x8e, 0x5b, 0x49, 0xab, 0x16, 0x84, 0xa2, 0x89, 0x98,
- 0xaf, 0xf1, 0x4b, 0x7b, 0x8e, 0x4b, 0x17, 0xfe, 0x70, 0x63, 0x3e, 0xb7,
- 0x9f, 0x2c, 0x5f, 0x0f, 0xf3, 0xb2, 0xc5, 0x61, 0xf1, 0x39, 0xf5, 0xee,
- 0x63, 0xac, 0x59, 0xd6, 0x2e, 0xf3, 0xf5, 0x35, 0xbd, 0x07, 0x2f, 0xfd,
- 0x0c, 0x86, 0x34, 0x0a, 0x4e, 0xb1, 0x52, 0x7d, 0xae, 0x61, 0x7f, 0xcd,
- 0xf6, 0x86, 0x6d, 0x81, 0xac, 0x56, 0x8f, 0x68, 0xe4, 0x17, 0xfb, 0x59,
- 0xbc, 0x80, 0xc3, 0xac, 0x5f, 0xee, 0x37, 0xa3, 0x38, 0x52, 0xb1, 0x7f,
- 0x4e, 0xda, 0x9c, 0x1a, 0xc5, 0x40, 0xf9, 0x3e, 0x6d, 0x7f, 0xfe, 0x9d,
- 0xa7, 0x52, 0x79, 0x9f, 0x7d, 0xc0, 0x75, 0x8a, 0x93, 0xf7, 0xf9, 0x15,
- 0xfe, 0xc3, 0xbe, 0xb6, 0x10, 0x16, 0x2f, 0xff, 0x9c, 0xb6, 0xcf, 0x88,
- 0xdc, 0x01, 0xd8, 0x0b, 0x17, 0xe6, 0x17, 0xe7, 0x4b, 0x17, 0xe7, 0xe8,
- 0xe5, 0x3a, 0x3f, 0x9e, 0x8a, 0x37, 0xff, 0xff, 0xd8, 0x2d, 0xf0, 0x7f,
- 0x92, 0xde, 0x75, 0x99, 0xdc, 0x0a, 0x4f, 0x9a, 0x58, 0xac, 0x45, 0xe9,
- 0x20, 0x5c, 0xf1, 0xcb, 0x17, 0xa4, 0x71, 0x2c, 0x5e, 0xe8, 0x28, 0x2c,
- 0x54, 0x17, 0x41, 0xb0, 0x9f, 0x78, 0x49, 0xbc, 0x62, 0x9a, 0x22, 0xfc,
- 0x62, 0x20, 0x21, 0x28, 0xda, 0xf8, 0x43, 0xe1, 0xae, 0x83, 0xd7, 0xda,
- 0x3f, 0xc6, 0xb1, 0x7f, 0xf6, 0xa0, 0x59, 0xee, 0x49, 0xfd, 0xba, 0xc5,
- 0x49, 0xf5, 0x08, 0x92, 0xec, 0x25, 0x8b, 0xbf, 0xc5, 0x8b, 0x76, 0xb1,
- 0x7f, 0x1b, 0x1c, 0x2f, 0xbe, 0x96, 0x2b, 0x0f, 0x19, 0xc4, 0xeb, 0x0f,
- 0xfa, 0x39, 0x7a, 0x86, 0x8b, 0x8c, 0x84, 0xa5, 0xff, 0xb9, 0x3e, 0xfb,
- 0x1c, 0xfb, 0xee, 0xb1, 0x7f, 0xe6, 0x70, 0x93, 0xff, 0x16, 0x41, 0x62,
- 0xfd, 0x07, 0xdd, 0xb4, 0xb1, 0x50, 0x45, 0x57, 0xd0, 0xb8, 0x7f, 0x79,
- 0x9b, 0x75, 0x45, 0x68, 0x5f, 0x8d, 0xef, 0x82, 0xed, 0x62, 0xa5, 0x10,
- 0xfb, 0x98, 0x39, 0x55, 0xfc, 0x27, 0x37, 0x52, 0x35, 0x8b, 0xfb, 0x40,
- 0x33, 0x93, 0x8b, 0x17, 0xa4, 0xbc, 0xb1, 0x7f, 0xfe, 0xe7, 0x33, 0xef,
- 0xc1, 0x6c, 0xce, 0x7d, 0x3a, 0xc5, 0xda, 0xfb, 0x9f, 0x93, 0x0e, 0x54,
- 0xa3, 0x35, 0xe1, 0x43, 0x7f, 0xfe, 0xe7, 0x33, 0xf9, 0xb6, 0x69, 0xa1,
- 0x06, 0x82, 0xc5, 0xfe, 0x3f, 0x1f, 0x3a, 0x36, 0x96, 0x2b, 0x11, 0x16,
- 0xca, 0xd7, 0xed, 0x08, 0x0e, 0x35, 0x8b, 0xf8, 0x63, 0xcc, 0x07, 0x16,
- 0x2f, 0xe9, 0x07, 0xb8, 0x28, 0xf5, 0x8a, 0x93, 0xe0, 0xe1, 0x75, 0xff,
- 0xe7, 0xf4, 0x27, 0x7f, 0xbf, 0xb8, 0xdd, 0xac, 0x56, 0x95, 0x79, 0x9c,
- 0xbf, 0xf0, 0xfc, 0x28, 0x58, 0xf0, 0x87, 0xd0, 0x89, 0xe8, 0x43, 0x7f,
- 0x03, 0xae, 0x69, 0xcd, 0x58, 0xbf, 0xec, 0x1b, 0xf2, 0x22, 0x91, 0xac,
- 0x50, 0xcf, 0xa9, 0x8c, 0x6f, 0xfa, 0x77, 0xc3, 0xe1, 0x7a, 0x39, 0x62,
- 0xff, 0x7e, 0x74, 0x0f, 0x66, 0xcb, 0x17, 0xf8, 0xb2, 0x1d, 0x5f, 0xf0,
- 0x58, 0xbb, 0xee, 0x74, 0x53, 0x7c, 0xf3, 0xc6, 0xb7, 0xff, 0x34, 0x3a,
- 0xea, 0x7c, 0xfb, 0xb8, 0xd6, 0x2f, 0xd2, 0x5b, 0x11, 0xab, 0x16, 0x82,
- 0xc5, 0xa1, 0x28, 0x82, 0x82, 0x3f, 0x65, 0x37, 0xb0, 0xee, 0xb1, 0x78,
- 0x5c, 0xf2, 0xc5, 0xff, 0xfa, 0x0c, 0x4f, 0xe9, 0xfe, 0xf8, 0x32, 0x9e,
- 0x2c, 0x5f, 0xff, 0x9c, 0x24, 0x90, 0xa0, 0xfc, 0xe4, 0xf5, 0x3e, 0xeb,
- 0x14, 0xe8, 0xae, 0x65, 0x4b, 0xff, 0xed, 0xe7, 0x58, 0x06, 0x3b, 0x42,
- 0x5f, 0x75, 0x8b, 0xf3, 0x84, 0xfe, 0x1d, 0x62, 0xff, 0xfa, 0x1c, 0xc2,
- 0x93, 0xb6, 0x7b, 0xd2, 0x75, 0x8b, 0x7a, 0x51, 0x91, 0x8a, 0x0c, 0x55,
- 0x43, 0x54, 0x08, 0x71, 0xcf, 0xc3, 0x33, 0xd0, 0xe9, 0xbf, 0xef, 0xbe,
- 0xbc, 0xdf, 0x61, 0xac, 0x5f, 0xff, 0xfd, 0xd1, 0xfd, 0xcc, 0x37, 0x7f,
- 0xbf, 0xb2, 0x22, 0x93, 0xed, 0x81, 0xac, 0x5e, 0xd8, 0x41, 0x16, 0x2f,
- 0xff, 0xbc, 0xd9, 0xc1, 0xe4, 0x3f, 0x3d, 0x07, 0x2b, 0x17, 0xff, 0xff,
- 0xf3, 0xf8, 0x78, 0x2e, 0x75, 0xfe, 0x6f, 0xf1, 0x6c, 0xf8, 0x5d, 0xc3,
- 0x9c, 0x14, 0xac, 0x53, 0x23, 0x7c, 0x94, 0x6a, 0x53, 0x99, 0xc7, 0x86,
- 0x8c, 0x02, 0xfe, 0xf3, 0x7f, 0xa8, 0xe5, 0x62, 0xf4, 0x05, 0x12, 0xc5,
- 0x49, 0xe7, 0xb1, 0x85, 0xf4, 0x3c, 0xfb, 0x2c, 0x5f, 0xb9, 0xc6, 0x2d,
- 0x96, 0x2f, 0xc6, 0x78, 0xa4, 0x0b, 0x16, 0xfa, 0xc5, 0x76, 0x88, 0x83,
- 0x92, 0x74, 0x29, 0x30, 0xa6, 0xff, 0xf8, 0x0d, 0x9f, 0x67, 0x09, 0x27,
- 0x26, 0x35, 0x62, 0xff, 0xcf, 0xcc, 0x1f, 0x7c, 0x9d, 0x71, 0x62, 0xff,
- 0x34, 0x3c, 0xfb, 0x7d, 0xd6, 0x2f, 0x14, 0x81, 0x62, 0xff, 0x49, 0xe6,
- 0x30, 0x30, 0xc3, 0x58, 0xa8, 0x1e, 0xb0, 0x41, 0xcb, 0xff, 0xa3, 0x24,
- 0x0f, 0x0c, 0xf1, 0x48, 0x16, 0x2a, 0x53, 0xc5, 0xc4, 0x1d, 0xd4, 0x1d,
- 0x01, 0xa1, 0x15, 0xe2, 0x4b, 0xf6, 0x7d, 0xf0, 0xeb, 0x17, 0x10, 0x16,
- 0x2f, 0x80, 0x77, 0xd2, 0xc5, 0x49, 0xba, 0x71, 0x7b, 0xff, 0x0d, 0xfa,
- 0x38, 0xf0, 0x3c, 0xfa, 0xc5, 0xff, 0x88, 0x6c, 0x76, 0x84, 0xbe, 0xeb,
- 0x17, 0xb0, 0xf2, 0xb1, 0x52, 0x7b, 0x58, 0x7d, 0x7f, 0xc2, 0xf7, 0x32,
- 0x0f, 0xa9, 0x58, 0xbf, 0xff, 0xe6, 0xf4, 0x93, 0x6d, 0x3a, 0x97, 0x84,
- 0x9c, 0xa4, 0xd5, 0x8b, 0xfc, 0xfc, 0x71, 0x05, 0xc7, 0x2b, 0x14, 0x34,
- 0x6a, 0x11, 0xcf, 0x99, 0x2f, 0xef, 0xce, 0xe4, 0xc7, 0x58, 0xbf, 0xff,
- 0xc6, 0xe6, 0xb3, 0xdd, 0x5c, 0x7d, 0x58, 0xb0, 0xe2, 0xfa, 0xc5, 0xff,
- 0x99, 0xf7, 0xfb, 0x0b, 0x6d, 0x3a, 0xc5, 0x3a, 0x34, 0xd8, 0xb8, 0x99,
- 0x6f, 0x6e, 0x29, 0x58, 0xbf, 0xdb, 0x4e, 0x10, 0xff, 0x2b, 0x16, 0xc7,
- 0x3d, 0x16, 0x1e, 0xad, 0x95, 0xda, 0x0d, 0x87, 0x07, 0xf7, 0x84, 0xdb,
- 0xc3, 0xd3, 0xf1, 0x81, 0x13, 0xf5, 0xfb, 0x3b, 0x0d, 0x83, 0x58, 0xbf,
- 0xfb, 0xbe, 0x7e, 0x79, 0x9e, 0x26, 0x35, 0x62, 0xb4, 0x7e, 0x2c, 0x57,
- 0x7f, 0xa1, 0x3a, 0xda, 0x75, 0xb2, 0xc5, 0xf4, 0x35, 0x87, 0x58, 0xbd,
- 0x9a, 0x02, 0xc5, 0xfa, 0x2c, 0x19, 0xe3, 0xd6, 0x2f, 0xf1, 0xe7, 0xbd,
- 0x4f, 0x7e, 0x58, 0xbf, 0x71, 0xf0, 0x80, 0xb1, 0x7a, 0x75, 0x12, 0xc5,
- 0xfc, 0x52, 0x1f, 0x70, 0xe2, 0xc5, 0x76, 0x98, 0xc3, 0x91, 0xc4, 0x3a,
- 0x72, 0xde, 0x1b, 0x74, 0x27, 0x08, 0x3d, 0x78, 0xd1, 0x6e, 0xb1, 0x76,
- 0x71, 0x62, 0xa5, 0x3e, 0xfc, 0x8d, 0x38, 0xd6, 0xa3, 0x08, 0x2f, 0xff,
- 0xff, 0xcf, 0xbe, 0x7a, 0x4b, 0xdc, 0xeb, 0x2e, 0x3c, 0x3f, 0x5d, 0x4b,
- 0xc1, 0xb8, 0xb1, 0x7f, 0xf9, 0x9f, 0xc2, 0xd3, 0x70, 0xcc, 0x2d, 0xd6,
- 0x2f, 0xd3, 0x0f, 0xce, 0xcb, 0x17, 0xff, 0xf1, 0xbc, 0xfc, 0x97, 0x87,
- 0xf9, 0xe1, 0x09, 0xbc, 0xb1, 0x50, 0x44, 0x2e, 0x14, 0xdf, 0xfd, 0x84,
- 0x31, 0xcf, 0xf3, 0x0b, 0x75, 0x8b, 0xff, 0xed, 0x03, 0x80, 0xfb, 0x41,
- 0xfc, 0x52, 0x05, 0x8a, 0xc5, 0x41, 0x5f, 0x84, 0x29, 0x43, 0x43, 0x84,
- 0x42, 0x43, 0xbf, 0xb3, 0xcc, 0x40, 0x12, 0xc5, 0xfd, 0xfe, 0xaf, 0xb3,
- 0x12, 0xc5, 0xfc, 0x7e, 0x0c, 0x98, 0x35, 0x8b, 0xf0, 0x39, 0x1a, 0xa3,
+ 0xc9, 0x4d, 0xbf, 0x62, 0x3c, 0x1b, 0xd1, 0xb9, 0xc7, 0x99, 0x24, 0x45,
+ 0x51, 0xc5, 0x21, 0x94, 0xdf, 0x0a, 0x19, 0xc5, 0x8b, 0x83, 0xd9, 0x62,
+ 0x88, 0xde, 0xf8, 0x8e, 0xf1, 0x36, 0xeb, 0x17, 0xa3, 0x9c, 0x0b, 0x17,
+ 0xb1, 0xfe, 0xb1, 0x78, 0x88, 0x6b, 0x17, 0xd9, 0x85, 0xe5, 0x8b, 0xd2,
+ 0xdb, 0xac, 0x5d, 0x08, 0xcc, 0x46, 0x99, 0xa4, 0x0e, 0x3b, 0xf2, 0x02,
+ 0x1c, 0xe0, 0xe7, 0x88, 0x6a, 0x31, 0x77, 0x66, 0x12, 0xf3, 0xba, 0x8e,
+ 0x6a, 0xff, 0xfb, 0x09, 0xc7, 0x19, 0xc2, 0xc1, 0xff, 0x34, 0xb1, 0x7f,
+ 0xf1, 0xda, 0x11, 0x99, 0xad, 0xd9, 0xb7, 0x54, 0x8c, 0xc5, 0xf4, 0x64,
+ 0x6a, 0xc6, 0x58, 0xbf, 0xf8, 0x71, 0x84, 0x26, 0x0c, 0x7f, 0x73, 0x56,
+ 0x2f, 0xfc, 0x52, 0x78, 0xce, 0x4f, 0x85, 0xc5, 0x8b, 0xff, 0xdd, 0xe0,
+ 0x1b, 0xde, 0xfe, 0x11, 0x37, 0x96, 0x2f, 0x7d, 0xf8, 0xb1, 0x7d, 0xde,
+ 0xf2, 0x7c, 0xb1, 0x7f, 0x4f, 0x0a, 0x7d, 0xc5, 0x8a, 0xef, 0xb3, 0xd5,
+ 0x39, 0x45, 0x46, 0xe8, 0xe9, 0x8d, 0x13, 0xa3, 0x53, 0x95, 0xfb, 0xda,
+ 0x14, 0xf6, 0x58, 0xbf, 0xf1, 0xb3, 0x9a, 0x33, 0x05, 0xad, 0x96, 0x2e,
+ 0x93, 0xac, 0x5f, 0xb0, 0xba, 0xf7, 0x78, 0xb1, 0x70, 0x5b, 0x2c, 0x57,
+ 0x7a, 0x8c, 0xc8, 0xd4, 0x57, 0x04, 0x2c, 0x17, 0xe8, 0xba, 0xdd, 0x96,
+ 0x2e, 0xd6, 0xcb, 0x17, 0xe7, 0xeb, 0x33, 0x65, 0x8a, 0x11, 0xe1, 0x76,
+ 0x19, 0xa1, 0x9f, 0xd6, 0x2b, 0x5d, 0x1d, 0x1b, 0xac, 0x5c, 0x17, 0x96,
+ 0x2a, 0x36, 0x3d, 0xae, 0xfb, 0x21, 0x19, 0x05, 0xf4, 0x6f, 0xde, 0xf2,
+ 0x56, 0x2f, 0x46, 0xf1, 0xae, 0x35, 0xac, 0x5b, 0xbe, 0xb1, 0xb9, 0xee,
+ 0x77, 0xc2, 0xdb, 0x44, 0xb1, 0x74, 0xf1, 0x62, 0xe8, 0xda, 0x0b, 0x17,
+ 0x07, 0xc5, 0x8a, 0xef, 0xb4, 0x4d, 0xec, 0x77, 0xd0, 0x9c, 0x42, 0xfe,
+ 0x1d, 0xb9, 0xb8, 0xb1, 0x7f, 0x9b, 0xae, 0x31, 0x0b, 0x16, 0x2f, 0xfd,
+ 0x0c, 0xff, 0xda, 0x0e, 0xe4, 0xb1, 0x5a, 0x44, 0x38, 0x05, 0xfc, 0x67,
+ 0x74, 0x74, 0x6e, 0xb1, 0x7e, 0xe3, 0x93, 0x6c, 0xb1, 0x7f, 0xef, 0xbf,
+ 0xb8, 0xdd, 0x6d, 0x81, 0x2c, 0x5f, 0xfb, 0xb4, 0xfd, 0xe6, 0x28, 0xa7,
+ 0x75, 0x8a, 0xef, 0x51, 0xfb, 0x1b, 0x18, 0x77, 0xc2, 0x0d, 0xca, 0x1d,
+ 0x0a, 0xe8, 0xe8, 0xdd, 0x62, 0xe7, 0x3a, 0xc5, 0xfb, 0xc4, 0xfd, 0x79,
+ 0x62, 0xbb, 0xe1, 0xf0, 0x6e, 0x40, 0x18, 0xbd, 0xfe, 0x01, 0xc3, 0xd3,
+ 0xed, 0x2b, 0x17, 0xc7, 0x6f, 0x4a, 0xc5, 0xff, 0xff, 0xdf, 0x0c, 0x71,
+ 0x9f, 0xcf, 0x64, 0x97, 0xb8, 0x58, 0x3f, 0xcf, 0x65, 0x8a, 0x8d, 0xd1,
+ 0x9f, 0x1a, 0x8d, 0xbb, 0x11, 0x5a, 0x25, 0x8b, 0xf4, 0x8c, 0x30, 0x71,
+ 0x62, 0xd1, 0xbf, 0xcd, 0xe9, 0x09, 0xdf, 0xdc, 0xfc, 0x9d, 0xc6, 0xb1,
+ 0x73, 0x12, 0xc5, 0x70, 0xf1, 0x3c, 0x5d, 0x73, 0x0d, 0x62, 0xfd, 0x91,
+ 0x42, 0x4e, 0xb1, 0x51, 0xba, 0x34, 0x63, 0x66, 0xfe, 0xf8, 0x44, 0x18,
+ 0xbd, 0xf7, 0x79, 0x1a, 0xf9, 0x2b, 0x16, 0x12, 0xc5, 0x77, 0xd4, 0xf0,
+ 0x1c, 0xba, 0xf7, 0x7d, 0xc6, 0xb8, 0xd6, 0xb1, 0x77, 0xb1, 0x62, 0xa3,
+ 0x59, 0xe4, 0x74, 0x63, 0x74, 0x74, 0x6e, 0xb1, 0x7f, 0xff, 0xff, 0x77,
+ 0xfd, 0x4f, 0x7c, 0xef, 0xb1, 0xef, 0xdb, 0x50, 0x8b, 0xb0, 0xbb, 0xeb,
+ 0x1a, 0xbb, 0xf8, 0xd7, 0xdf, 0x53, 0x0c, 0xfc, 0x72, 0xc5, 0xbe, 0xb1,
+ 0x7f, 0xd3, 0xb6, 0x9b, 0xf2, 0x77, 0x58, 0xbb, 0x3e, 0xb1, 0x44, 0x7a,
+ 0x1e, 0x39, 0xbf, 0xff, 0xe7, 0xf0, 0x7a, 0x9f, 0xce, 0x6e, 0x37, 0x2d,
+ 0x8f, 0x30, 0x58, 0xbc, 0x09, 0x02, 0xc5, 0xff, 0x60, 0x45, 0x86, 0xfd,
+ 0xa3, 0xd6, 0x2b, 0x0f, 0x68, 0x87, 0x6f, 0x18, 0x78, 0xf5, 0x8b, 0xdd,
+ 0x39, 0xd6, 0x2f, 0xd2, 0xe3, 0xc3, 0xac, 0x5f, 0xa2, 0xce, 0xd3, 0xc5,
+ 0x8a, 0x93, 0xd2, 0x62, 0x7a, 0xd9, 0x16, 0x5f, 0x22, 0x27, 0x0b, 0xfb,
+ 0x9a, 0x9c, 0xf7, 0x16, 0x2c, 0x25, 0x8a, 0x93, 0xc0, 0xc2, 0xeb, 0x9f,
+ 0x65, 0x8b, 0xfd, 0x21, 0xfd, 0xe1, 0x27, 0x58, 0xa8, 0x1e, 0x67, 0x06,
+ 0x2f, 0xe8, 0xa5, 0x87, 0x84, 0xb1, 0x7c, 0xe3, 0xc8, 0xf5, 0x8a, 0x39,
+ 0xe9, 0x00, 0xb6, 0xfa, 0x74, 0x66, 0xcb, 0x17, 0xf0, 0xd8, 0xfa, 0x9e,
+ 0x2c, 0x56, 0x1f, 0xaf, 0xc8, 0x98, 0x96, 0xff, 0xdd, 0x84, 0xdb, 0x8d,
+ 0xfb, 0x48, 0xd6, 0x2f, 0xe9, 0x3b, 0x42, 0x7c, 0xb1, 0x7f, 0xf4, 0x9d,
+ 0xbd, 0x9d, 0x00, 0xe1, 0xfd, 0x62, 0xff, 0xf6, 0xfa, 0x16, 0xdd, 0x71,
+ 0xf5, 0xbf, 0xf1, 0x62, 0xf0, 0x03, 0xf2, 0xc5, 0xf3, 0xf6, 0x60, 0x2c,
+ 0x54, 0xa2, 0x4f, 0x14, 0x3c, 0x3f, 0x7f, 0xf6, 0x7d, 0x87, 0xf7, 0x30,
+ 0xf9, 0xba, 0xc5, 0x0d, 0x3e, 0xcc, 0x2d, 0x35, 0x13, 0xe5, 0xa5, 0x0d,
+ 0xae, 0x17, 0x5f, 0x3e, 0xc2, 0x25, 0x8b, 0xf6, 0x6d, 0x80, 0x89, 0x62,
+ 0x8c, 0x3c, 0xdf, 0x11, 0xdf, 0x9f, 0xb8, 0xd7, 0xdd, 0x62, 0xff, 0x85,
+ 0x0e, 0x31, 0xd8, 0x80, 0xb1, 0x73, 0xf9, 0x62, 0xdb, 0xac, 0x51, 0x86,
+ 0xab, 0xbd, 0x17, 0xad, 0x22, 0xdd, 0x8b, 0x40, 0xc7, 0x7e, 0x04, 0xf3,
+ 0x3a, 0x58, 0xbe, 0x31, 0xda, 0x25, 0x8a, 0xd1, 0xe6, 0xf0, 0xa6, 0xc7,
+ 0x58, 0xa9, 0x36, 0x83, 0x22, 0xbf, 0xc6, 0x61, 0x36, 0x81, 0x1c, 0xb1,
+ 0x71, 0x41, 0x62, 0xf6, 0xa4, 0xd5, 0x8b, 0xff, 0xe6, 0xfe, 0x74, 0x0f,
+ 0x84, 0xdf, 0x8b, 0xe2, 0x58, 0xa7, 0x44, 0x4c, 0x42, 0xe7, 0x1e, 0xbf,
+ 0xc3, 0xd3, 0x01, 0xb3, 0x4b, 0x17, 0xf6, 0x72, 0x43, 0x29, 0x58, 0xbf,
+ 0xf7, 0x99, 0xe7, 0x61, 0x79, 0x83, 0x58, 0xbb, 0x87, 0x58, 0xa1, 0xa7,
+ 0x51, 0x90, 0xc0, 0x73, 0x0f, 0x99, 0xb1, 0x68, 0x90, 0x2d, 0x8b, 0x17,
+ 0x31, 0xd6, 0x2b, 0x86, 0xa3, 0xb8, 0x46, 0xee, 0xef, 0x2c, 0x5b, 0xbf,
+ 0x58, 0xb0, 0x24, 0xd9, 0x08, 0x6e, 0xf1, 0xdb, 0xcb, 0x16, 0xef, 0xd6,
+ 0x2f, 0xe9, 0xed, 0x3e, 0x6e, 0x2c, 0x56, 0x1f, 0x19, 0x0e, 0xf0, 0x5e,
+ 0xff, 0xe3, 0x00, 0x01, 0x73, 0x46, 0x19, 0xf8, 0xe5, 0x8b, 0xff, 0x75,
+ 0xfc, 0xe4, 0xf3, 0x8d, 0xf5, 0x8b, 0xf4, 0x70, 0xc9, 0x82, 0x58, 0xbf,
+ 0xfc, 0x73, 0x35, 0x9e, 0x6e, 0x8c, 0xf6, 0x01, 0x62, 0xa5, 0x33, 0x53,
+ 0x96, 0xb2, 0x77, 0x90, 0x04, 0x59, 0x7f, 0x36, 0xd2, 0x52, 0x05, 0x8a,
+ 0x58, 0x23, 0x5b, 0x7f, 0xf4, 0x4e, 0x42, 0x31, 0xfa, 0x83, 0x79, 0x62,
+ 0xff, 0xfe, 0xdc, 0xa4, 0xe6, 0x4e, 0xb4, 0xfd, 0xb4, 0xcc, 0x05, 0x8b,
+ 0xf4, 0x1b, 0xcc, 0x6a, 0xc5, 0x4a, 0x21, 0xf1, 0x7a, 0xf8, 0xb0, 0x12,
+ 0xb1, 0x44, 0x78, 0x5d, 0x88, 0x6f, 0x0f, 0x06, 0xb1, 0x4b, 0x17, 0xd9,
+ 0xec, 0x02, 0xc5, 0x8d, 0x01, 0xae, 0x20, 0xca, 0xc3, 0xf2, 0x64, 0xbb,
+ 0xe6, 0x3b, 0xc4, 0xb1, 0x7f, 0x38, 0x4f, 0xcc, 0xdd, 0x62, 0xa5, 0x50,
+ 0xbb, 0xc6, 0x21, 0xa8, 0x4a, 0xb1, 0x07, 0x08, 0xed, 0x2b, 0x17, 0xbd,
+ 0x30, 0x58, 0xbf, 0xf6, 0xc2, 0x68, 0xb1, 0xf4, 0x28, 0xf5, 0x8b, 0x85,
+ 0x05, 0x8a, 0x35, 0x11, 0x4e, 0x22, 0xc3, 0xbd, 0x91, 0x2f, 0x1e, 0x60,
+ 0xb1, 0x7b, 0x8d, 0x12, 0xc5, 0x49, 0xbb, 0xf0, 0xed, 0xfd, 0x19, 0x17,
+ 0x7b, 0xf6, 0x25, 0x8a, 0x8d, 0xdb, 0x19, 0xde, 0xfb, 0x20, 0xef, 0x90,
+ 0xce, 0xd9, 0x8a, 0x04, 0x23, 0x86, 0x16, 0x43, 0x4b, 0x77, 0x0e, 0x9b,
+ 0x1e, 0x56, 0xac, 0x50, 0xa9, 0xd4, 0x36, 0x8f, 0x0b, 0x0f, 0xc7, 0x90,
+ 0xd0, 0x82, 0x02, 0xb1, 0x47, 0x7d, 0xc7, 0x6f, 0x4a, 0x32, 0xed, 0x0d,
+ 0xe0, 0xde, 0x7b, 0x88, 0x2f, 0x9a, 0x01, 0x9d, 0x62, 0xf6, 0xe4, 0x05,
+ 0x8b, 0x6b, 0x47, 0x85, 0xc2, 0x4b, 0xf0, 0xa7, 0xe5, 0x2b, 0x17, 0x98,
+ 0xb7, 0x58, 0xbd, 0xe2, 0x95, 0x8b, 0xe2, 0x2c, 0xf2, 0xc5, 0xe2, 0xce,
+ 0x96, 0x2d, 0xd2, 0xc5, 0xf3, 0x07, 0x9b, 0x2c, 0x56, 0x1b, 0x7f, 0x89,
+ 0xde, 0x8b, 0xf2, 0xb1, 0x5d, 0xea, 0x33, 0xe4, 0x73, 0x62, 0x11, 0xaa,
+ 0x39, 0x05, 0x71, 0x33, 0xa0, 0xa1, 0xd9, 0x7c, 0x51, 0x48, 0xd6, 0x2e,
+ 0xeb, 0xcb, 0x17, 0xdf, 0x8a, 0x46, 0xb1, 0x7b, 0xbd, 0x14, 0xac, 0x5e,
+ 0xd6, 0xc3, 0x58, 0xbe, 0xc0, 0x07, 0xe5, 0x8b, 0xf6, 0xa4, 0x36, 0x25,
+ 0x8a, 0x19, 0xf5, 0xf4, 0x3e, 0x02, 0x4a, 0x95, 0x5a, 0x03, 0x28, 0xc8,
+ 0xd8, 0x5c, 0xaa, 0x22, 0x36, 0x19, 0x01, 0x20, 0xa1, 0x1b, 0x7e, 0x21,
+ 0xfc, 0x38, 0xe5, 0x8b, 0xff, 0x36, 0x77, 0x3e, 0x8d, 0x16, 0x7d, 0x62,
+ 0xf7, 0xe7, 0xa5, 0x8b, 0xf4, 0x9c, 0xb2, 0x25, 0x8b, 0xf9, 0xf0, 0x87,
+ 0xf9, 0x58, 0xb1, 0xd6, 0x2c, 0x75, 0x8b, 0xa4, 0x96, 0x2b, 0x63, 0x50,
+ 0x10, 0x95, 0xef, 0xe4, 0x4b, 0x14, 0x34, 0x67, 0xee, 0x51, 0x1e, 0x59,
+ 0xc3, 0xaf, 0x11, 0xd2, 0xc5, 0xff, 0x89, 0xbf, 0x24, 0xdf, 0x90, 0x2c,
+ 0x5f, 0xd2, 0x5e, 0xfb, 0x8d, 0x62, 0xfe, 0xd4, 0x90, 0xb3, 0xeb, 0x17,
+ 0xfc, 0xdd, 0x63, 0xef, 0xbb, 0x0d, 0x62, 0xfb, 0x53, 0x84, 0xb1, 0x7c,
+ 0xde, 0x80, 0x16, 0x2f, 0x7b, 0x98, 0xb1, 0x4b, 0x17, 0xe2, 0xc8, 0x9f,
+ 0x65, 0x8b, 0x0b, 0xa3, 0x6a, 0x70, 0xcb, 0xda, 0xc2, 0x58, 0xb0, 0x96,
+ 0x2f, 0xf3, 0xee, 0xd9, 0xac, 0xf2, 0xc5, 0x49, 0xf0, 0x80, 0x73, 0x82,
+ 0x57, 0x85, 0x1b, 0x92, 0xc5, 0x0d, 0x52, 0x01, 0xa7, 0x9b, 0x96, 0xe8,
+ 0xb4, 0xe7, 0x7f, 0x21, 0x62, 0x3e, 0x29, 0x7a, 0x11, 0x3d, 0xc5, 0xd7,
+ 0xfd, 0xa9, 0xc8, 0x4f, 0xe4, 0x0b, 0x17, 0xff, 0x8c, 0xfb, 0x3f, 0x80,
+ 0x22, 0x26, 0x82, 0xc5, 0xff, 0xe7, 0xe0, 0x8f, 0x9b, 0xfe, 0x4b, 0xdc,
+ 0x58, 0xbd, 0x01, 0x0d, 0x62, 0xcf, 0x03, 0xe9, 0x89, 0x2e, 0xfb, 0x39,
+ 0x3a, 0x58, 0xbf, 0xc7, 0xce, 0x33, 0x75, 0x05, 0x8a, 0x23, 0xd6, 0x0c,
+ 0x8a, 0xe8, 0xdf, 0xbd, 0x58, 0xbe, 0x7d, 0xdc, 0x6b, 0x17, 0xfd, 0xf9,
+ 0x71, 0xbf, 0x36, 0x65, 0x8a, 0xef, 0x87, 0xfd, 0x24, 0x4e, 0x47, 0x52,
+ 0xbd, 0x91, 0xb1, 0x6c, 0x10, 0xb2, 0x1d, 0xbb, 0xa7, 0x3c, 0xa4, 0xcd,
+ 0x42, 0x58, 0xe7, 0x1f, 0x85, 0x98, 0x1f, 0x8a, 0x14, 0x17, 0xff, 0xff,
+ 0xff, 0xff, 0xbb, 0xe7, 0x7b, 0x9d, 0xf2, 0x36, 0xef, 0xbe, 0xfb, 0xdf,
+ 0xbf, 0x98, 0xd7, 0x1b, 0x6b, 0x6e, 0xec, 0x10, 0xfb, 0xeb, 0x31, 0xdd,
+ 0x07, 0xf8, 0xda, 0x66, 0x36, 0x8f, 0x8d, 0x5e, 0x30, 0xcf, 0xc7, 0x2c,
+ 0x5f, 0xf1, 0x0e, 0x27, 0x2e, 0xa1, 0xc5, 0x8b, 0xfe, 0xd6, 0xa4, 0xbd,
+ 0xfc, 0x82, 0xc5, 0xff, 0xf6, 0xbe, 0x13, 0x0f, 0x36, 0x17, 0xb5, 0xa9,
+ 0x58, 0xbf, 0xfd, 0x0f, 0x8a, 0x75, 0x19, 0xf7, 0xdd, 0xb4, 0xb1, 0x7e,
+ 0x0f, 0x5c, 0x62, 0x58, 0xae, 0x8f, 0xe3, 0xe9, 0xf5, 0x29, 0xb1, 0x61,
+ 0xdb, 0x1c, 0x82, 0x19, 0x77, 0xf8, 0x38, 0xb9, 0x3e, 0x91, 0xac, 0x5b,
+ 0x8b, 0x17, 0x85, 0xa0, 0x2c, 0x5c, 0x28, 0x18, 0x6c, 0x37, 0x12, 0xbf,
+ 0xf7, 0xf0, 0xb0, 0xdc, 0x2c, 0x1a, 0xc5, 0xff, 0x82, 0x9f, 0x0d, 0xe3,
+ 0xf9, 0x27, 0x58, 0xbf, 0xbe, 0xfe, 0x29, 0x3a, 0xc5, 0x74, 0x7e, 0x04,
+ 0x87, 0x7c, 0xde, 0xe6, 0xcb, 0x17, 0xdc, 0xce, 0xbc, 0xb1, 0x7a, 0x29,
+ 0x09, 0x62, 0xf9, 0xb8, 0xe3, 0x58, 0xac, 0x3c, 0x10, 0x87, 0xef, 0xc3,
+ 0xfc, 0x96, 0xcb, 0x17, 0xce, 0x5e, 0xe2, 0xc5, 0xff, 0xff, 0x1d, 0xf5,
+ 0xf1, 0x72, 0x13, 0xdb, 0x52, 0x5e, 0xfe, 0x41, 0x62, 0xa0, 0x88, 0xb7,
+ 0x22, 0xbf, 0xf3, 0xf9, 0xf7, 0x71, 0xfb, 0x37, 0x58, 0xad, 0x95, 0x5f,
+ 0xc0, 0xbf, 0x21, 0x5b, 0x11, 0x16, 0x89, 0x3e, 0xca, 0x44, 0x5e, 0x85,
+ 0xa7, 0x71, 0x15, 0xc7, 0x1a, 0xc5, 0xf8, 0x9b, 0x4d, 0x05, 0x8b, 0x9f,
+ 0xb2, 0xc5, 0xfe, 0x21, 0xfe, 0x4f, 0xdc, 0x25, 0x8a, 0x93, 0xf7, 0x19,
+ 0x3b, 0x0c, 0xde, 0x91, 0xca, 0xc5, 0xfb, 0x3f, 0xfc, 0x02, 0xc5, 0xb7,
+ 0x39, 0xe2, 0x10, 0xe5, 0xf3, 0x04, 0xd1, 0xeb, 0x14, 0xc7, 0x9c, 0x45,
+ 0x17, 0xe1, 0x6f, 0xf7, 0x09, 0x62, 0xfb, 0xd1, 0xd9, 0xf5, 0x8b, 0xf8,
+ 0x23, 0x3d, 0xcc, 0x09, 0x62, 0xfd, 0xb4, 0x1c, 0xb1, 0x62, 0xff, 0xff,
+ 0x31, 0x6e, 0x58, 0x3f, 0x88, 0xcf, 0xcc, 0x35, 0x3b, 0x2c, 0x56, 0x23,
+ 0x8d, 0xc9, 0x98, 0xc8, 0x45, 0x17, 0x4f, 0xd6, 0x2f, 0xe0, 0xca, 0x7f,
+ 0x30, 0x58, 0xbf, 0xff, 0x8d, 0x2c, 0x00, 0xb8, 0x64, 0x1f, 0xf3, 0xb9,
+ 0x32, 0xc5, 0xfb, 0x93, 0x1f, 0xa9, 0x58, 0xa3, 0x51, 0x9a, 0x71, 0x76,
+ 0x2e, 0x02, 0xed, 0xff, 0x3e, 0xf1, 0x43, 0xf2, 0x46, 0xac, 0x5f, 0xdb,
+ 0x99, 0xf6, 0x27, 0x58, 0xbd, 0x27, 0xf2, 0xc5, 0x12, 0x22, 0x04, 0x78,
+ 0x11, 0x7d, 0xfe, 0xc0, 0xa7, 0xc4, 0xdc, 0x58, 0xbf, 0x16, 0x1d, 0xa0,
+ 0xb1, 0x7f, 0xff, 0xee, 0x72, 0x40, 0x19, 0xf8, 0xf8, 0x42, 0x86, 0x70,
+ 0x26, 0xe9, 0x62, 0x8d, 0x44, 0xb0, 0x44, 0xf7, 0x9f, 0xee, 0xb1, 0x52,
+ 0x99, 0xd3, 0x98, 0x34, 0x32, 0x7c, 0x4b, 0x74, 0x92, 0xc5, 0xf6, 0x6e,
+ 0x3c, 0x58, 0xba, 0x74, 0xb1, 0x4b, 0x10, 0x2d, 0xef, 0xcc, 0x3f, 0xc9,
+ 0x2c, 0x5f, 0x10, 0xc3, 0xe9, 0x62, 0xfc, 0xfb, 0x1e, 0x77, 0x58, 0xb8,
+ 0x5e, 0x58, 0xbc, 0xda, 0x81, 0x88, 0xe3, 0x73, 0xa3, 0x8d, 0xb1, 0x3f,
+ 0x89, 0x63, 0x8a, 0xaf, 0xf3, 0x14, 0x59, 0xb0, 0xa0, 0xb1, 0x51, 0xb3,
+ 0x37, 0x92, 0x65, 0x4c, 0x0d, 0x03, 0x25, 0x92, 0x9b, 0x08, 0xd7, 0x84,
+ 0x7e, 0xa1, 0x7e, 0x72, 0x0f, 0xc6, 0x1c, 0xd1, 0x83, 0x94, 0x7f, 0xfe,
+ 0x40, 0x14, 0x3e, 0x42, 0x6a, 0xbf, 0xf6, 0x81, 0x9b, 0xfe, 0x4b, 0xdc,
+ 0x58, 0xbf, 0xbe, 0xf1, 0xe2, 0x0e, 0x25, 0x8b, 0xed, 0xf3, 0xaf, 0x2c,
+ 0x5c, 0x6b, 0x18, 0x7b, 0x3d, 0x8d, 0x2e, 0x61, 0xac, 0x5d, 0xda, 0x3d,
+ 0x62, 0xff, 0x81, 0x30, 0x18, 0x9b, 0x50, 0x58, 0xa3, 0x51, 0x3f, 0xa3,
+ 0x16, 0x17, 0x21, 0xdb, 0xff, 0xf6, 0xb4, 0xf9, 0xd8, 0x85, 0xc3, 0x38,
+ 0x26, 0xe2, 0xc5, 0x2c, 0x5f, 0xff, 0x71, 0xe3, 0xb3, 0x7f, 0xb9, 0x10,
+ 0xb5, 0xb2, 0xc5, 0x68, 0xf8, 0x3c, 0x19, 0x7f, 0x7b, 0x0f, 0xd6, 0x1d,
+ 0x62, 0xa5, 0x30, 0xac, 0x85, 0xcb, 0x91, 0x5f, 0xe3, 0x9d, 0xa1, 0xc7,
+ 0x82, 0xc5, 0xfe, 0x34, 0xc9, 0xe8, 0x1a, 0x95, 0x8a, 0xc3, 0xeb, 0x63,
+ 0x4a, 0x95, 0x67, 0x8f, 0x19, 0xc7, 0xe3, 0x46, 0x28, 0x4f, 0x5f, 0xf0,
+ 0x44, 0xc6, 0xe0, 0xdc, 0x96, 0x2f, 0xff, 0x76, 0xc1, 0xfe, 0x7b, 0x1e,
+ 0x49, 0x83, 0x58, 0xb4, 0x4b, 0x15, 0x87, 0xc2, 0x24, 0xeb, 0x86, 0xeb,
+ 0x17, 0xf7, 0xdc, 0x29, 0x21, 0xac, 0x5a, 0x18, 0x78, 0xbb, 0x8b, 0xde,
+ 0xd4, 0xf9, 0x62, 0xfa, 0x1c, 0x78, 0x2c, 0x58, 0x7a, 0x3c, 0x06, 0x1d,
+ 0xa9, 0x4e, 0x3f, 0x50, 0x9a, 0x66, 0x61, 0x34, 0x5f, 0x08, 0xbd, 0xc5,
+ 0x8b, 0xfb, 0x82, 0x72, 0x7e, 0x2c, 0x5e, 0x9d, 0x4a, 0xc5, 0x18, 0x79,
+ 0x3f, 0x2d, 0xba, 0x77, 0x58, 0xad, 0xd1, 0x4f, 0xa6, 0xce, 0xe2, 0x3b,
+ 0xd0, 0x8e, 0x09, 0x62, 0xe0, 0x3a, 0xc5, 0xc2, 0xf2, 0xc5, 0xf8, 0xf0,
+ 0xf8, 0x7c, 0x58, 0xb6, 0x8c, 0x3d, 0xa8, 0xe1, 0x70, 0xc6, 0x2f, 0xcc,
+ 0x11, 0x60, 0xd6, 0x2a, 0x51, 0xbc, 0xef, 0x9a, 0x3a, 0xbf, 0xf1, 0x4e,
+ 0xe6, 0xb6, 0x69, 0xc0, 0xb1, 0x7f, 0x73, 0x1f, 0x5a, 0x65, 0x8b, 0xe3,
+ 0x00, 0xde, 0x58, 0xbf, 0xfe, 0x68, 0x7b, 0x3a, 0x83, 0x14, 0x33, 0xaf,
+ 0x2c, 0x57, 0x0f, 0xd7, 0xc4, 0x95, 0xb2, 0x60, 0x60, 0x3f, 0xf4, 0x28,
+ 0xae, 0x9d, 0x2c, 0x5f, 0xcd, 0xf8, 0xc0, 0x82, 0x09, 0x22, 0xec, 0xe2,
+ 0xc5, 0xed, 0xb3, 0x8e, 0x79, 0x9f, 0x35, 0xb3, 0x81, 0x12, 0xc4, 0xc7,
+ 0x7d, 0xf9, 0xeb, 0xb9, 0x62, 0xfe, 0xea, 0x11, 0x38, 0xbb, 0xf5, 0x8b,
+ 0xfc, 0xda, 0x8e, 0x17, 0xdf, 0x4b, 0x15, 0x27, 0xda, 0x23, 0x6a, 0x94,
+ 0xea, 0x47, 0x0c, 0xdd, 0xc9, 0xff, 0x09, 0x4b, 0xef, 0x8b, 0xa8, 0x2c,
+ 0x5f, 0xdd, 0x67, 0xc5, 0xd0, 0x16, 0x2d, 0xf5, 0x8b, 0xf8, 0xfc, 0xfc,
+ 0x97, 0x96, 0x2f, 0xb5, 0x3e, 0xe2, 0xc5, 0xed, 0xbe, 0x25, 0x8b, 0xff,
+ 0x7d, 0xb9, 0xfc, 0xed, 0x9e, 0xe2, 0xc5, 0x49, 0xf0, 0x30, 0xfd, 0x3a,
+ 0x34, 0x62, 0x2e, 0xfc, 0x20, 0xef, 0xce, 0x2d, 0xdf, 0x65, 0x8a, 0x82,
+ 0x73, 0x18, 0x4b, 0xb9, 0x8f, 0xa1, 0xc7, 0x1c, 0x6b, 0x7f, 0xf4, 0x96,
+ 0xed, 0xe6, 0x34, 0xc3, 0x65, 0x62, 0xff, 0xf3, 0x78, 0x46, 0x73, 0xee,
+ 0x32, 0x98, 0xf5, 0x8b, 0xfa, 0x4d, 0x6f, 0x31, 0xab, 0x17, 0xbd, 0x21,
+ 0xac, 0x56, 0x1e, 0x6b, 0x17, 0xd1, 0xa9, 0x81, 0x01, 0x1c, 0xa1, 0x37,
+ 0x77, 0xe2, 0x58, 0xbf, 0x07, 0xee, 0x4f, 0x96, 0x2f, 0x6d, 0xc2, 0x58,
+ 0xa9, 0x3e, 0x18, 0x0c, 0xe8, 0xaa, 0xff, 0x1f, 0x37, 0x26, 0xcd, 0xd6,
+ 0x2e, 0x14, 0x4b, 0x17, 0x43, 0x92, 0x79, 0xa0, 0x34, 0xbe, 0x3f, 0x03,
+ 0xe2, 0xc5, 0xf8, 0xb6, 0x1c, 0xe9, 0x62, 0xff, 0xe1, 0x47, 0xfd, 0xcf,
+ 0x31, 0xff, 0xcd, 0x96, 0x2f, 0x6e, 0x2d, 0xd6, 0x2a, 0x53, 0x62, 0xe9,
+ 0xed, 0xcb, 0x58, 0x94, 0x8a, 0x44, 0x99, 0x7f, 0xde, 0xf4, 0x9f, 0x30,
+ 0x8d, 0x58, 0xbf, 0xfe, 0xf7, 0xf3, 0xbb, 0xd9, 0xf2, 0xcf, 0x7d, 0xd6,
+ 0x2b, 0xa4, 0x45, 0x91, 0xcd, 0xde, 0xe2, 0xc5, 0xf9, 0xbd, 0x09, 0x35,
+ 0x62, 0xa0, 0x78, 0x24, 0x31, 0x7f, 0xb0, 0x03, 0x13, 0x6a, 0x0b, 0x15,
+ 0x27, 0xab, 0xb1, 0x0d, 0xfc, 0xcc, 0x3e, 0xd8, 0x35, 0x8b, 0x04, 0xb1,
+ 0x7c, 0xf1, 0xed, 0xc5, 0x8b, 0x9b, 0x75, 0x49, 0x9e, 0x5e, 0xc2, 0x1a,
+ 0xc5, 0x39, 0xfc, 0xfc, 0x4d, 0x89, 0x42, 0x25, 0xbf, 0xd2, 0x46, 0xe8,
+ 0x52, 0x4b, 0x17, 0xf0, 0x18, 0xa0, 0xe7, 0x58, 0xbb, 0x77, 0x58, 0xa9,
+ 0x54, 0x6d, 0xb4, 0x2e, 0x46, 0x45, 0xbc, 0x2a, 0x1c, 0xec, 0x06, 0x62,
+ 0x2d, 0xbf, 0x03, 0x30, 0x2e, 0x2c, 0x5f, 0xef, 0xfb, 0x8d, 0xd0, 0x67,
+ 0x58, 0xbf, 0xfc, 0x5e, 0x8e, 0xc8, 0xa0, 0xda, 0xd8, 0x72, 0xb1, 0x7f,
+ 0xa6, 0x0f, 0xe9, 0xf7, 0x16, 0x2f, 0xf7, 0x04, 0x77, 0xf0, 0x19, 0x62,
+ 0xf0, 0x7f, 0x95, 0x8a, 0x81, 0xe9, 0x00, 0xd2, 0xf0, 0xc6, 0xcb, 0x15,
+ 0xf4, 0x62, 0x14, 0x21, 0x7c, 0x45, 0x7f, 0x40, 0x3c, 0xfb, 0x74, 0xb1,
+ 0x7f, 0xff, 0x9c, 0x84, 0xde, 0x33, 0x06, 0x66, 0x41, 0xcd, 0x35, 0x96,
+ 0x2f, 0xe7, 0xf7, 0xf0, 0x6e, 0xb1, 0x7c, 0x53, 0x9d, 0x2c, 0x51, 0xa7,
+ 0x9f, 0xe2, 0xda, 0x31, 0x55, 0x64, 0x94, 0xe1, 0xbb, 0xc6, 0x26, 0xc6,
+ 0x9c, 0x30, 0x0e, 0x16, 0x56, 0xf2, 0xc5, 0xfd, 0xa0, 0x04, 0xdf, 0xe2,
+ 0xc5, 0xff, 0x1a, 0xc5, 0x9d, 0x8b, 0x38, 0xb1, 0x7f, 0x76, 0x2c, 0xe6,
+ 0x12, 0xc5, 0xfb, 0xa8, 0x3e, 0x12, 0xc5, 0xa3, 0xd6, 0x2b, 0x0f, 0xaf,
+ 0x45, 0xdc, 0x28, 0xbc, 0xf0, 0x95, 0x8b, 0x31, 0x87, 0x95, 0xc2, 0xeb,
+ 0x68, 0xd4, 0xc5, 0xff, 0x0e, 0xfb, 0xfc, 0xe3, 0xc3, 0x85, 0x9f, 0x58,
+ 0xb6, 0xcb, 0x17, 0xa1, 0x3d, 0x2c, 0x5f, 0xff, 0xdc, 0xcd, 0xd8, 0x80,
+ 0x66, 0xa4, 0x85, 0xe9, 0xfa, 0xc5, 0xb2, 0x23, 0xfa, 0xf0, 0xf5, 0xfb,
+ 0x83, 0x79, 0x25, 0x8a, 0x94, 0xc4, 0x0e, 0x68, 0x50, 0x8d, 0xf1, 0x45,
+ 0xf8, 0xb3, 0xb3, 0xf4, 0xb1, 0x6d, 0x2c, 0x5f, 0xfb, 0xcf, 0x10, 0x4c,
+ 0x39, 0xeb, 0x8b, 0x15, 0xa3, 0xfe, 0x62, 0xae, 0x09, 0x54, 0x6e, 0xae,
+ 0x1a, 0x44, 0x9e, 0x34, 0x76, 0x8d, 0x00, 0x50, 0xbf, 0xbe, 0x87, 0x1c,
+ 0x96, 0x2f, 0xff, 0xbf, 0x3a, 0x33, 0xf3, 0xb1, 0x0b, 0x61, 0x71, 0x62,
+ 0xfa, 0x40, 0xc7, 0x58, 0xba, 0x1c, 0x94, 0x4c, 0x0c, 0x88, 0x95, 0x2e,
+ 0x00, 0x16, 0x2f, 0xc2, 0x07, 0x9f, 0x65, 0x8b, 0xc1, 0x04, 0x12, 0x45,
+ 0xff, 0x43, 0x85, 0x9b, 0x8f, 0x34, 0x91, 0x18, 0x68, 0x6d, 0x05, 0x8b,
+ 0xfe, 0xf6, 0x6b, 0x69, 0xec, 0xc7, 0x58, 0xa9, 0x4c, 0xe1, 0xce, 0x8e,
+ 0x30, 0xc9, 0x7e, 0x4d, 0x0c, 0x4a, 0xff, 0x0f, 0xf2, 0x53, 0x81, 0x2c,
+ 0x5f, 0xf7, 0xd8, 0xff, 0x91, 0xbc, 0xac, 0x5f, 0xff, 0xbc, 0x6b, 0x73,
+ 0x53, 0xef, 0xe1, 0xf3, 0x58, 0xb1, 0x50, 0x46, 0x0f, 0x8c, 0xc2, 0x38,
+ 0xbf, 0x19, 0x9f, 0x91, 0xac, 0x5f, 0xbb, 0x84, 0x7c, 0x1a, 0xc5, 0xff,
+ 0xe3, 0x7f, 0x39, 0xd7, 0xb0, 0xec, 0x40, 0x58, 0xbf, 0xfd, 0xee, 0x78,
+ 0xd9, 0x28, 0x66, 0xc2, 0x82, 0xc5, 0xff, 0xf7, 0x62, 0x14, 0x33, 0xb3,
+ 0xfa, 0x77, 0xcf, 0xac, 0x5f, 0xff, 0xc2, 0x2f, 0x72, 0x48, 0xdf, 0xb9,
+ 0x9f, 0xc0, 0x32, 0xc5, 0xfb, 0x3b, 0x19, 0x03, 0xac, 0x5b, 0xd2, 0x8d,
+ 0xc8, 0x2a, 0x7d, 0x72, 0xa5, 0x51, 0x7e, 0xc6, 0x38, 0x52, 0xe5, 0x8c,
+ 0x96, 0x28, 0xca, 0x6f, 0xfd, 0xd4, 0x08, 0x40, 0x33, 0x73, 0x81, 0x62,
+ 0xe9, 0x35, 0x62, 0xf1, 0x4c, 0x16, 0x2f, 0xf8, 0x72, 0x52, 0x08, 0x7d,
+ 0xd6, 0x2f, 0xe9, 0x89, 0xcf, 0x31, 0x2c, 0x5e, 0xf3, 0xec, 0xb1, 0x79,
+ 0xc1, 0x8b, 0x17, 0xfe, 0x81, 0x09, 0xb9, 0xfc, 0x03, 0x2c, 0x5b, 0xa8,
+ 0x1e, 0xd6, 0x0e, 0x51, 0xa8, 0xa0, 0x67, 0x8a, 0x94, 0xe8, 0xb6, 0x44,
+ 0x18, 0xc3, 0x8e, 0x78, 0xe0, 0x50, 0xcf, 0xbc, 0x7c, 0x25, 0x8b, 0xfd,
+ 0xf7, 0x19, 0x33, 0x44, 0xb1, 0x7f, 0x7c, 0x4c, 0x08, 0xec, 0x58, 0xbf,
+ 0xfe, 0xc0, 0xbd, 0x38, 0x5b, 0xcf, 0xa7, 0xa0, 0x96, 0x2d, 0x8b, 0x15,
+ 0xb1, 0xf1, 0xf1, 0x4a, 0x86, 0x8b, 0x7e, 0x42, 0x52, 0xef, 0xfd, 0x62,
+ 0xff, 0xf8, 0x1d, 0x79, 0x9b, 0xc1, 0xfb, 0x82, 0x28, 0x2c, 0x5e, 0x04,
+ 0xe9, 0x62, 0xa4, 0xfc, 0x19, 0x4e, 0xff, 0xff, 0x66, 0xb4, 0xf2, 0x03,
+ 0x37, 0xfb, 0xc8, 0x0a, 0x40, 0xb1, 0x51, 0xba, 0xa3, 0x79, 0x1c, 0x78,
+ 0x75, 0x31, 0x47, 0x21, 0x11, 0xe2, 0x0b, 0xc7, 0xf7, 0x4b, 0x17, 0xd3,
+ 0xec, 0xd9, 0x62, 0xfa, 0x00, 0x04, 0xac, 0x5f, 0xe9, 0x33, 0xd9, 0xce,
+ 0x4a, 0xc5, 0xe9, 0xc2, 0x58, 0xbe, 0x18, 0xbd, 0xc5, 0x8b, 0x0c, 0x06,
+ 0xfc, 0x31, 0xbb, 0x47, 0x2c, 0x5f, 0xe9, 0xf3, 0xf6, 0x92, 0xdd, 0x62,
+ 0xfa, 0x70, 0xa0, 0xe7, 0x95, 0xc1, 0x5a, 0x35, 0x36, 0x1e, 0x88, 0xf4,
+ 0x46, 0x4e, 0x7e, 0x72, 0xbd, 0xf0, 0xf8, 0xb1, 0x7c, 0x67, 0xc3, 0x1a,
+ 0xc5, 0xd9, 0xc8, 0x1e, 0x2f, 0xc7, 0xe9, 0xd1, 0x7c, 0x50, 0x91, 0xbb,
+ 0x3a, 0x58, 0xbd, 0x24, 0x6a, 0xc5, 0xff, 0x1c, 0xb3, 0xdc, 0x16, 0xa0,
+ 0xb1, 0x7d, 0xff, 0x37, 0xd6, 0x2a, 0x4f, 0x75, 0xce, 0xaa, 0x0e, 0x8e,
+ 0x18, 0x71, 0xee, 0x64, 0x3a, 0x0d, 0x8c, 0x4b, 0x79, 0x5b, 0x5d, 0x47,
+ 0xc0, 0xf1, 0xaa, 0xc5, 0x1f, 0xce, 0xa5, 0x8b, 0x1e, 0x58, 0xe7, 0xe5,
+ 0xfa, 0x82, 0x51, 0x79, 0x4b, 0x46, 0xe4, 0x7f, 0xde, 0x95, 0x26, 0x26,
+ 0x5e, 0xd2, 0x8f, 0xa3, 0x89, 0x83, 0x18, 0xee, 0x7a, 0xbb, 0x52, 0xb1,
+ 0x68, 0xdd, 0x62, 0xff, 0xb3, 0x45, 0x9d, 0x9b, 0x50, 0x58, 0xbb, 0x3c,
+ 0xb1, 0x71, 0x32, 0xc5, 0xe0, 0x3e, 0xeb, 0x17, 0x8a, 0x60, 0xb0, 0x61,
+ 0x7d, 0x58, 0x7c, 0x0e, 0x69, 0x63, 0x31, 0x12, 0xe6, 0xbb, 0xdb, 0x8b,
+ 0x17, 0x75, 0x05, 0x8a, 0x73, 0xd5, 0x01, 0x54, 0x70, 0x95, 0xed, 0x46,
+ 0x9d, 0xcb, 0x17, 0x34, 0x16, 0x2f, 0xc5, 0xec, 0x01, 0xd6, 0x2f, 0xb4,
+ 0xf3, 0xe5, 0x8b, 0xfb, 0x85, 0x91, 0x49, 0xd6, 0x28, 0x07, 0xa1, 0xe2,
+ 0x2a, 0x74, 0x6b, 0x9c, 0x99, 0x85, 0xc4, 0xf1, 0x74, 0xf9, 0x62, 0xf8,
+ 0x0c, 0x17, 0x96, 0x2f, 0xf3, 0x05, 0xf7, 0x9d, 0x4a, 0xc5, 0xfc, 0x23,
+ 0xf0, 0x5a, 0xd9, 0x62, 0xfc, 0xfd, 0xa4, 0xbc, 0xb1, 0x46, 0x2b, 0x5f,
+ 0x8d, 0xc5, 0xe4, 0x5c, 0x71, 0x93, 0x1b, 0x18, 0x47, 0x47, 0x6e, 0x2f,
+ 0xa2, 0x42, 0x33, 0xe1, 0x8d, 0xff, 0xf7, 0xf0, 0x66, 0x0f, 0xee, 0x69,
+ 0x9d, 0x41, 0xd6, 0x2f, 0xff, 0xfb, 0xbf, 0x30, 0xb3, 0x78, 0xff, 0xe7,
+ 0xd8, 0xe3, 0x30, 0xcf, 0xc7, 0x2c, 0x5f, 0xfb, 0x4f, 0xc8, 0x07, 0xf9,
+ 0x29, 0x58, 0xbc, 0xf2, 0x75, 0x8b, 0x9f, 0xeb, 0x15, 0xa3, 0x67, 0x1c,
+ 0x39, 0x7f, 0xfe, 0xf1, 0xa2, 0x9c, 0x1f, 0xf3, 0x9d, 0x42, 0x7e, 0xb1,
+ 0x5d, 0xf6, 0x9b, 0x2e, 0x9d, 0xce, 0xe4, 0x44, 0x97, 0xf8, 0xc2, 0xce,
+ 0xc5, 0x9c, 0x58, 0xa5, 0x8b, 0xee, 0x79, 0xf6, 0x58, 0xb9, 0xcb, 0x73,
+ 0x61, 0x10, 0x65, 0xfd, 0x0e, 0x0a, 0x74, 0x6a, 0xc5, 0xe1, 0x6b, 0x65,
+ 0x8a, 0xe8, 0xf3, 0xc0, 0x61, 0x7f, 0xb3, 0xb7, 0x32, 0x4b, 0xa5, 0x8b,
+ 0xfb, 0x9e, 0x8e, 0xcd, 0x4a, 0xc5, 0xe8, 0x85, 0xa5, 0x8b, 0x9a, 0x0b,
+ 0x17, 0xed, 0xdc, 0xa2, 0x12, 0xc5, 0xfd, 0xc9, 0xeb, 0xbe, 0xc6, 0x75,
+ 0x8b, 0xf8, 0xf8, 0x5e, 0x8e, 0xc5, 0x8b, 0xff, 0xfd, 0x9e, 0x10, 0x0e,
+ 0xd0, 0x61, 0xc9, 0x36, 0x9a, 0x0b, 0x17, 0xf1, 0x30, 0x5e, 0xcf, 0xe2,
+ 0x23, 0xc8, 0xc2, 0xff, 0x67, 0xfe, 0x2f, 0x31, 0x2c, 0x5c, 0xe3, 0x58,
+ 0xbf, 0xbf, 0xbb, 0x69, 0xa0, 0xb1, 0x6d, 0xe0, 0x78, 0xd8, 0x2f, 0x79,
+ 0xe2, 0xe2, 0xc5, 0x49, 0xe3, 0x1c, 0xa2, 0xff, 0xff, 0x4e, 0x6a, 0x04,
+ 0xdf, 0x6e, 0x8d, 0x61, 0xbc, 0x9d, 0x62, 0xff, 0xef, 0x3f, 0xd8, 0xf1,
+ 0xc2, 0xfb, 0xe9, 0x62, 0xfe, 0x6f, 0x1e, 0x73, 0xcb, 0x14, 0xc7, 0xea,
+ 0x24, 0x8b, 0xfb, 0x35, 0xf9, 0x87, 0x16, 0x2f, 0x4f, 0x5c, 0x58, 0xa9,
+ 0x3c, 0xcf, 0x97, 0x5f, 0xd2, 0x50, 0x67, 0xd9, 0x62, 0xdc, 0x58, 0xbf,
+ 0xa4, 0x0f, 0xf7, 0x3a, 0xc5, 0x49, 0xbf, 0x71, 0x2b, 0xc5, 0x9b, 0xac,
+ 0x51, 0xa8, 0xa8, 0xfb, 0x67, 0x07, 0xe8, 0x6b, 0x8c, 0xdb, 0x8b, 0xf4,
+ 0x55, 0x14, 0x31, 0xb4, 0x86, 0x78, 0x5f, 0xfc, 0x84, 0xa1, 0xab, 0xc6,
+ 0xdf, 0x43, 0x26, 0xfe, 0xdf, 0xec, 0x77, 0xe2, 0xc5, 0x4a, 0xec, 0x4e,
+ 0x18, 0xbc, 0xe4, 0x2b, 0x42, 0x92, 0xfc, 0xff, 0x63, 0xba, 0xc5, 0xa5,
+ 0x62, 0xe0, 0xfc, 0xb1, 0x52, 0x6a, 0x80, 0x23, 0x79, 0x88, 0x0b, 0x14,
+ 0x62, 0x23, 0x71, 0x47, 0x72, 0x0b, 0xdd, 0xb0, 0x6b, 0x15, 0xb1, 0xe8,
+ 0x44, 0x63, 0x70, 0x22, 0x58, 0xad, 0x1b, 0xd2, 0x24, 0xb9, 0xbe, 0xb1,
+ 0x7e, 0xce, 0xd9, 0xee, 0x2c, 0x5f, 0x45, 0x06, 0x25, 0x8a, 0xd1, 0xf2,
+ 0x7c, 0x5f, 0x85, 0x57, 0xfb, 0xbb, 0x59, 0xdc, 0x42, 0x09, 0x62, 0xb6,
+ 0x3e, 0xa0, 0x8b, 0xef, 0x77, 0x38, 0xd6, 0x2b, 0x0f, 0x11, 0x89, 0x28,
+ 0xc6, 0x5b, 0xac, 0xc7, 0x75, 0xb2, 0x26, 0x32, 0xbb, 0xe6, 0x88, 0xff,
+ 0x3b, 0x7c, 0xd1, 0xb1, 0x94, 0x66, 0x57, 0x82, 0xea, 0x56, 0x2f, 0xe3,
+ 0xee, 0x66, 0x1f, 0x8b, 0x16, 0xfa, 0xc5, 0xfb, 0x6e, 0xa1, 0x27, 0x58,
+ 0xbf, 0xff, 0xfe, 0x07, 0x33, 0x08, 0xd0, 0xf4, 0x53, 0x9f, 0x8c, 0xe1,
+ 0x66, 0xc7, 0xc3, 0xac, 0x5e, 0x29, 0x1a, 0xc5, 0xda, 0xc5, 0x8b, 0xb8,
+ 0xeb, 0x15, 0xb1, 0xae, 0xd0, 0xbd, 0xc1, 0xc1, 0x62, 0xfa, 0x48, 0x33,
+ 0xac, 0x56, 0xc8, 0xa8, 0xc4, 0xa3, 0x91, 0x06, 0x33, 0x58, 0x9b, 0x3f,
+ 0xa3, 0x29, 0xb8, 0x1c, 0x58, 0xbe, 0x30, 0xa7, 0x75, 0x8b, 0xe6, 0xfc,
+ 0x86, 0xb1, 0x58, 0x7b, 0xff, 0x18, 0xec, 0x49, 0x7d, 0x21, 0x60, 0xd6,
+ 0x2f, 0xff, 0x85, 0xd4, 0x38, 0x3f, 0xce, 0x86, 0xcc, 0x12, 0xc5, 0xd1,
+ 0xbf, 0x7c, 0x58, 0xa8, 0xd4, 0xab, 0xd6, 0x44, 0xb2, 0x39, 0x27, 0x84,
+ 0x46, 0x8c, 0x08, 0x8c, 0x35, 0x3b, 0xb3, 0xcb, 0x17, 0x1d, 0xd6, 0x28,
+ 0x66, 0xb8, 0x85, 0xef, 0x82, 0x9e, 0xb8, 0xb1, 0x7f, 0x8b, 0x3a, 0x84,
+ 0xe7, 0x96, 0x2f, 0xf0, 0xdb, 0xc0, 0x0c, 0xa0, 0xb1, 0x7b, 0xc1, 0xe2,
+ 0xc5, 0xd3, 0xb2, 0xc5, 0x49, 0xf5, 0xb1, 0xaf, 0x07, 0xaf, 0x8b, 0xdc,
+ 0x95, 0x8b, 0xc3, 0x98, 0x2c, 0x5f, 0xa2, 0x84, 0xf5, 0xe5, 0x8b, 0xfb,
+ 0x7f, 0xbf, 0x66, 0xd2, 0xc5, 0xa7, 0x63, 0xdc, 0xc2, 0xbb, 0xed, 0x9c,
+ 0xbc, 0xb1, 0x76, 0x7d, 0x62, 0xa5, 0x1f, 0x8c, 0x44, 0x4f, 0x22, 0x27,
+ 0x8e, 0x23, 0xb0, 0xd6, 0x29, 0x63, 0x0b, 0x2b, 0xbd, 0xdf, 0xac, 0x54,
+ 0xaf, 0x43, 0x6c, 0x3f, 0x09, 0x64, 0xd9, 0x0a, 0x2f, 0x90, 0x00, 0x97,
+ 0x90, 0x9e, 0xf4, 0x65, 0x3d, 0x97, 0x23, 0x86, 0xad, 0x1a, 0x96, 0x2f,
+ 0xda, 0x01, 0xdf, 0x8b, 0x17, 0x4f, 0x65, 0x8b, 0xf3, 0xe1, 0x37, 0x4b,
+ 0x15, 0x87, 0xd3, 0xd8, 0xa7, 0xb8, 0x66, 0xf7, 0xc4, 0x12, 0xc5, 0xf3,
+ 0x19, 0x02, 0x58, 0xb9, 0xb6, 0x58, 0xa3, 0x4d, 0xdf, 0xc8, 0xee, 0x10,
+ 0x16, 0x2f, 0x09, 0xf7, 0x58, 0xbe, 0xf3, 0xcf, 0x4b, 0x15, 0x03, 0xd9,
+ 0xf8, 0xc7, 0x07, 0xae, 0x16, 0xeb, 0x17, 0xfd, 0x3b, 0x1d, 0x80, 0x07,
+ 0xfa, 0xc5, 0x41, 0x10, 0x40, 0x2f, 0xe0, 0xcd, 0xef, 0x60, 0x6b, 0x17,
+ 0xf9, 0xa2, 0x7e, 0xa7, 0x92, 0xb1, 0x7f, 0x1c, 0x5c, 0xf6, 0x79, 0x62,
+ 0xff, 0x04, 0xdb, 0xe1, 0x60, 0xd6, 0x2f, 0xcd, 0xfe, 0xa1, 0xc5, 0x8a,
+ 0x94, 0x46, 0xf0, 0xbc, 0x46, 0x97, 0xdc, 0x04, 0xc4, 0xb1, 0x7f, 0x3c,
+ 0x3f, 0x24, 0x6a, 0xc5, 0x61, 0xe9, 0x70, 0x92, 0xfb, 0x86, 0x6a, 0x56,
+ 0x2f, 0x98, 0x72, 0x75, 0x8b, 0xf9, 0xce, 0xf1, 0x08, 0x35, 0x8a, 0xe8,
+ 0xfd, 0xa2, 0x24, 0xf9, 0x15, 0xfd, 0xbe, 0x1c, 0x5c, 0xf2, 0xc5, 0x49,
+ 0xf0, 0x88, 0xc6, 0xfc, 0x21, 0x06, 0xf1, 0xeb, 0x17, 0xa1, 0x3c, 0x58,
+ 0xb8, 0x8e, 0xb1, 0x61, 0x2c, 0x54, 0x0f, 0x18, 0x63, 0xa0, 0x17, 0xbc,
+ 0x31, 0x6e, 0xb1, 0x7c, 0x32, 0x98, 0x2c, 0x51, 0x88, 0xe3, 0x97, 0x37,
+ 0x2f, 0x61, 0xfb, 0xe8, 0xb4, 0xf1, 0xcb, 0x17, 0xf3, 0xef, 0x27, 0x17,
+ 0x96, 0x2f, 0xff, 0xa7, 0xdf, 0x93, 0x47, 0x3a, 0x89, 0xba, 0x82, 0xc5,
+ 0xce, 0x35, 0x8b, 0xee, 0x41, 0x89, 0x62, 0xf3, 0xe0, 0xd6, 0x2b, 0x0f,
+ 0x57, 0x82, 0xfe, 0x22, 0xbf, 0x3f, 0x5e, 0x93, 0xac, 0x5f, 0xfc, 0x67,
+ 0x5e, 0x29, 0xc3, 0x33, 0xaf, 0x2c, 0x56, 0x1f, 0x88, 0x65, 0x37, 0xfd,
+ 0x3f, 0x79, 0x8a, 0x29, 0xdd, 0x62, 0xf9, 0x8e, 0xfe, 0x58, 0xa8, 0xd1,
+ 0x7f, 0xba, 0x61, 0x02, 0x33, 0x33, 0x56, 0xba, 0x87, 0xeb, 0x98, 0x47,
+ 0x8f, 0x45, 0x0c, 0x1d, 0x42, 0x04, 0xf0, 0xf8, 0xfc, 0x60, 0x8c, 0x76,
+ 0x44, 0xfc, 0x2f, 0xf4, 0x2a, 0x05, 0x09, 0xfe, 0xc4, 0x41, 0x1d, 0xdb,
+ 0xbf, 0x58, 0xbf, 0x37, 0xa1, 0x9d, 0x2c, 0x57, 0x7e, 0x78, 0x04, 0x2f,
+ 0x7f, 0x9e, 0x26, 0x27, 0xeb, 0x8b, 0x17, 0x66, 0xeb, 0x17, 0xf8, 0xbd,
+ 0xc2, 0x9f, 0x71, 0x62, 0xff, 0x7c, 0xb1, 0xc1, 0x20, 0x58, 0xbf, 0x3f,
+ 0x6c, 0x2e, 0x2c, 0x5f, 0x47, 0x66, 0xa5, 0x62, 0xff, 0xfe, 0x9f, 0x8b,
+ 0xa9, 0xf6, 0xff, 0x9d, 0x0b, 0x05, 0x12, 0xc5, 0x62, 0x62, 0x4e, 0x67,
+ 0xa3, 0x23, 0x94, 0xfc, 0x96, 0xe8, 0xec, 0x58, 0xbe, 0xcf, 0x8a, 0x3d,
+ 0x62, 0xb0, 0xf0, 0x3c, 0x35, 0x7f, 0xed, 0xbe, 0xe7, 0x98, 0xff, 0xe6,
+ 0xcb, 0x15, 0xd1, 0xf2, 0xe8, 0x86, 0xfe, 0xd6, 0x7f, 0xe2, 0xf2, 0xc5,
+ 0xfd, 0x19, 0xcf, 0x4f, 0xb8, 0xb9, 0x03, 0x4b, 0xe2, 0x9c, 0xd2, 0x85,
+ 0x6e, 0x7c, 0x1f, 0x3f, 0xbf, 0xb3, 0x5b, 0x09, 0x86, 0xa9, 0x03, 0x48,
+ 0xc3, 0x47, 0x5b, 0x26, 0x03, 0x08, 0x59, 0x5f, 0xf7, 0xb8, 0xda, 0x1e,
+ 0x9a, 0x0b, 0x15, 0xa3, 0xe4, 0xe1, 0x55, 0xf1, 0x7f, 0x3a, 0x58, 0xa9,
+ 0x4f, 0x35, 0xe3, 0x88, 0x62, 0x2b, 0xbb, 0x86, 0xb1, 0x7f, 0x71, 0xc9,
+ 0xb4, 0x6a, 0xc5, 0x7c, 0xf2, 0x7b, 0x0d, 0xdf, 0x6e, 0xe7, 0x95, 0x8b,
+ 0xff, 0x49, 0xa5, 0x9d, 0x79, 0xbf, 0x2b, 0x14, 0xc7, 0xc5, 0xe2, 0x3b,
+ 0xfa, 0x1f, 0x26, 0xeb, 0xcb, 0x15, 0xb9, 0xe8, 0x11, 0x0d, 0xf0, 0x64,
+ 0xdb, 0x2c, 0x5f, 0xb8, 0xfa, 0x70, 0x2c, 0x56, 0x1f, 0x77, 0x08, 0xbb,
+ 0x89, 0x2f, 0xde, 0xfc, 0xeb, 0x65, 0x8b, 0xba, 0x75, 0x8b, 0xf4, 0xf8,
+ 0xc3, 0x84, 0xb1, 0x7f, 0xed, 0xbd, 0xf9, 0xfe, 0x76, 0x68, 0x2c, 0x5e,
+ 0x3c, 0xee, 0xb1, 0x7c, 0x40, 0x17, 0x16, 0x2e, 0x68, 0x2c, 0x56, 0x1e,
+ 0xc6, 0x87, 0x98, 0x8e, 0xfd, 0xd4, 0x5f, 0x6e, 0x96, 0x2f, 0xa1, 0x9d,
+ 0x79, 0x62, 0xe0, 0x71, 0x62, 0xba, 0x37, 0x9a, 0x24, 0xa9, 0x4d, 0x45,
+ 0xe1, 0x34, 0xc5, 0xa2, 0x68, 0xbe, 0x66, 0x07, 0x16, 0x2e, 0x63, 0x56,
+ 0x2e, 0x6d, 0xa2, 0x37, 0x44, 0x45, 0x7f, 0xc3, 0xe7, 0x33, 0x43, 0xfe,
+ 0x2c, 0x5f, 0xe0, 0xbf, 0x9d, 0x43, 0x09, 0x62, 0xf7, 0xe7, 0x4b, 0x17,
+ 0x03, 0xa5, 0x8b, 0xfe, 0xe3, 0x14, 0xc4, 0xe3, 0xd9, 0x62, 0xc0, 0x58,
+ 0xbf, 0xd0, 0x73, 0xcf, 0xc3, 0x1a, 0xc5, 0xff, 0xe9, 0xc2, 0xeb, 0xd9,
+ 0xa7, 0xd9, 0x8e, 0xb1, 0x70, 0x5f, 0x58, 0xbb, 0x3e, 0x62, 0x39, 0x37,
+ 0x3a, 0xe0, 0x97, 0x8d, 0x42, 0x4a, 0xbb, 0x38, 0xb1, 0x46, 0x26, 0xd9,
+ 0xe8, 0x7e, 0xc7, 0x2c, 0x54, 0x13, 0xc3, 0x0a, 0x38, 0x9a, 0x95, 0x4b,
+ 0xb8, 0x74, 0xd1, 0xfc, 0x5f, 0x0c, 0x0d, 0xe5, 0x8b, 0xe3, 0x93, 0x04,
+ 0xb1, 0x7f, 0x07, 0xec, 0x36, 0x78, 0xb1, 0x43, 0x3d, 0x32, 0x23, 0xbd,
+ 0xd9, 0xa2, 0x58, 0xac, 0x45, 0xbb, 0xbb, 0x7c, 0x86, 0xff, 0xb2, 0x1f,
+ 0xc2, 0x6d, 0x1a, 0xb1, 0x71, 0xc2, 0x58, 0xa8, 0xc3, 0xd2, 0x81, 0xcd,
+ 0xf1, 0xfd, 0x9f, 0x58, 0xbd, 0xb4, 0xf7, 0x2c, 0x54, 0x9e, 0x27, 0x08,
+ 0xe8, 0xc6, 0x66, 0x1c, 0x68, 0x69, 0x31, 0x95, 0x42, 0x55, 0xd8, 0xdf,
+ 0x72, 0x34, 0x47, 0x31, 0x88, 0xab, 0x43, 0x1f, 0x8d, 0xf1, 0x9e, 0x8a,
+ 0x54, 0x57, 0x21, 0xd8, 0x28, 0x40, 0x77, 0x34, 0xdf, 0x9f, 0x79, 0x3c,
+ 0xac, 0x5f, 0x64, 0xf5, 0xe5, 0x8b, 0xfd, 0xd6, 0xb1, 0xff, 0x23, 0x58,
+ 0xbf, 0xed, 0xdf, 0x98, 0x2d, 0xd8, 0x96, 0x2e, 0x1c, 0xac, 0x5f, 0xa2,
+ 0xfb, 0x02, 0x56, 0x2e, 0xc8, 0x2c, 0x5f, 0xe7, 0xdd, 0xc7, 0x1c, 0xe0,
+ 0x58, 0xbf, 0xfe, 0xfc, 0x9c, 0xcf, 0xcb, 0x68, 0x65, 0x30, 0x58, 0xa8,
+ 0x27, 0x2e, 0x32, 0x8c, 0x23, 0xf9, 0xa3, 0x1d, 0x10, 0xbf, 0x0a, 0x7c,
+ 0x2e, 0x23, 0x7b, 0xb0, 0x35, 0x8b, 0xf7, 0xd8, 0xa6, 0x3d, 0x62, 0xff,
+ 0x1a, 0xde, 0xe1, 0xdf, 0xcb, 0x17, 0xf9, 0xbc, 0xd8, 0x37, 0xec, 0xb1,
+ 0x7c, 0x0f, 0xc8, 0xd6, 0x2f, 0xef, 0xb8, 0x45, 0x23, 0x58, 0xbf, 0xe9,
+ 0x01, 0xe7, 0x0b, 0xdc, 0x58, 0xbf, 0xee, 0x60, 0x5f, 0x63, 0xbf, 0x16,
+ 0x2f, 0xd9, 0xad, 0x85, 0xc5, 0x8a, 0x35, 0x35, 0x6d, 0xcd, 0x5c, 0xd2,
+ 0x22, 0x3f, 0x97, 0x70, 0xe3, 0xb1, 0xd5, 0xfd, 0xbb, 0xed, 0x9d, 0x79,
+ 0x62, 0xfc, 0xfd, 0x41, 0xc9, 0x62, 0xf3, 0xff, 0x16, 0x2f, 0xef, 0x31,
+ 0xcf, 0x27, 0x58, 0xac, 0x3f, 0x2d, 0xca, 0x3a, 0x1c, 0xa5, 0x8a, 0x35,
+ 0x1b, 0xe7, 0x85, 0x18, 0x46, 0x17, 0xfc, 0x2d, 0x8c, 0xcf, 0x7e, 0x7c,
+ 0xb1, 0x7e, 0xe0, 0x81, 0x9f, 0x58, 0xb9, 0xe2, 0x58, 0xa9, 0x45, 0xa6,
+ 0xe6, 0xfe, 0x3c, 0xee, 0x29, 0xbf, 0xf8, 0x84, 0x69, 0xc5, 0xef, 0xc8,
+ 0xbb, 0xf5, 0x8b, 0xe3, 0xce, 0x8d, 0x58, 0xbe, 0xc0, 0x01, 0x96, 0x2f,
+ 0x07, 0xf6, 0x58, 0xac, 0x3e, 0x42, 0x24, 0x8e, 0x22, 0xad, 0x91, 0xc0,
+ 0x14, 0x2c, 0x2f, 0x83, 0x92, 0xdd, 0x62, 0x96, 0x2f, 0x73, 0xf2, 0xb0,
+ 0x72, 0x65, 0xfa, 0x19, 0xf7, 0x3a, 0xc5, 0x41, 0x10, 0x63, 0x30, 0x22,
+ 0xbb, 0xf6, 0xd8, 0x2d, 0x6c, 0xb1, 0x7e, 0x2d, 0x04, 0xdb, 0x2c, 0x5f,
+ 0xef, 0xf6, 0xc1, 0xf3, 0x03, 0x58, 0xa9, 0x4d, 0xa3, 0x21, 0x5a, 0xe5,
+ 0xec, 0x56, 0x22, 0xab, 0xf3, 0x3f, 0x8a, 0x56, 0x2f, 0xb7, 0xfc, 0x84,
+ 0xb1, 0x7e, 0xcf, 0x71, 0xce, 0xb1, 0x70, 0x89, 0x62, 0xe1, 0x79, 0x62,
+ 0xc3, 0x58, 0xbf, 0x70, 0x73, 0x83, 0x58, 0xad, 0x8f, 0x4a, 0x3c, 0x61,
+ 0x84, 0xaf, 0x16, 0x6c, 0xb1, 0x52, 0xc8, 0x0f, 0x83, 0xe0, 0xc6, 0x32,
+ 0x38, 0x07, 0x8f, 0xf3, 0x52, 0xa2, 0x0e, 0x99, 0xdf, 0x93, 0x11, 0x2f,
+ 0x0a, 0x04, 0xd2, 0x19, 0x95, 0xff, 0x49, 0xe7, 0xce, 0x59, 0x05, 0x8b,
+ 0x41, 0x62, 0xfb, 0x82, 0x90, 0x2c, 0x5e, 0xfb, 0x9d, 0x62, 0xdd, 0xcb,
+ 0x15, 0xb9, 0xb2, 0x10, 0xed, 0x69, 0x18, 0x1f, 0x37, 0x00, 0x91, 0x2a,
+ 0xdd, 0x84, 0xb1, 0x7e, 0xe0, 0x7c, 0xf8, 0x96, 0x2b, 0xe7, 0x83, 0xe1,
+ 0x6b, 0xff, 0xda, 0x79, 0x3e, 0x19, 0x9f, 0x7c, 0x3a, 0xc5, 0xfb, 0xa9,
+ 0xf6, 0xa5, 0x62, 0xf9, 0xf9, 0x2c, 0xb1, 0x46, 0x22, 0x4c, 0x92, 0x78,
+ 0x53, 0x7f, 0xb0, 0xb3, 0xaf, 0x40, 0xeb, 0x17, 0x7a, 0x56, 0x2a, 0x4f,
+ 0x2d, 0x8d, 0x2f, 0xf9, 0xa0, 0x37, 0x17, 0x7e, 0xfa, 0x58, 0xbf, 0x61,
+ 0x14, 0x8d, 0x62, 0xf3, 0x7e, 0x56, 0x2f, 0xe2, 0x68, 0x3f, 0x50, 0x58,
+ 0xaf, 0x9e, 0x50, 0x63, 0x97, 0xf4, 0xec, 0x76, 0x8a, 0x56, 0x2d, 0xc5,
+ 0x8b, 0xe0, 0xfb, 0xa7, 0xa5, 0x8b, 0x69, 0x62, 0xa0, 0x89, 0xe8, 0x88,
+ 0xc0, 0x5e, 0x42, 0x42, 0x28, 0xbf, 0xfe, 0x63, 0x7d, 0x3a, 0x06, 0xa7,
+ 0xc4, 0xc0, 0x58, 0xbf, 0xb7, 0x1f, 0xc4, 0xdc, 0x58, 0xbf, 0xfd, 0xf9,
+ 0x72, 0x9f, 0x3e, 0x9f, 0xc2, 0x58, 0xa9, 0x3f, 0x87, 0x30, 0xb9, 0x8d,
+ 0x58, 0xbf, 0xb6, 0x2c, 0xf6, 0xa5, 0x62, 0xff, 0x3f, 0x83, 0xd4, 0xfe,
+ 0x56, 0x2f, 0xb7, 0x0f, 0xdc, 0x58, 0xbf, 0x8b, 0x01, 0x85, 0x05, 0x8b,
+ 0xff, 0x83, 0x26, 0xf7, 0x1f, 0xaf, 0xb8, 0x4b, 0x17, 0xf8, 0xf3, 0xbc,
+ 0x93, 0xc4, 0xb1, 0x63, 0x4c, 0x3f, 0xbc, 0x47, 0xac, 0x46, 0x83, 0x42,
+ 0x9e, 0xf6, 0xa4, 0xd5, 0x8a, 0x94, 0xe7, 0x20, 0x5c, 0xe6, 0x85, 0x0f,
+ 0x6e, 0x13, 0x54, 0xaf, 0x26, 0x63, 0xeb, 0xc2, 0xd7, 0x4f, 0x67, 0x20,
+ 0xf9, 0xf3, 0x46, 0x1c, 0x49, 0x5c, 0x86, 0x47, 0x88, 0x05, 0x1d, 0xa5,
+ 0xff, 0xe2, 0xc1, 0xea, 0x47, 0xf6, 0x0f, 0x36, 0x58, 0xbf, 0x72, 0x7b,
+ 0x37, 0xd6, 0x2f, 0x37, 0x40, 0x58, 0xb7, 0x65, 0x8a, 0x81, 0xb2, 0xe0,
+ 0xf5, 0xcf, 0xe5, 0x8b, 0xff, 0x8b, 0xed, 0xc2, 0xc3, 0x4d, 0xc8, 0xf5,
+ 0x8b, 0xf8, 0x43, 0xcf, 0x4c, 0x4b, 0x15, 0x87, 0xef, 0xba, 0x45, 0xfd,
+ 0x0c, 0x2d, 0x9f, 0x4b, 0x17, 0x89, 0x86, 0xb1, 0x7f, 0xa4, 0x5b, 0xe1,
+ 0xe7, 0x75, 0x8a, 0x73, 0xd1, 0x21, 0xcb, 0x83, 0xf2, 0xc5, 0xfb, 0x93,
+ 0xaf, 0x4a, 0xc5, 0x0c, 0xf8, 0x74, 0x41, 0xc1, 0x9b, 0x9f, 0xbf, 0x58,
+ 0xba, 0x01, 0xac, 0x5f, 0x05, 0x90, 0x75, 0x8b, 0xd8, 0xe6, 0xac, 0x5e,
+ 0xcc, 0xd9, 0x62, 0xc3, 0x58, 0xbc, 0xcd, 0xa5, 0x8a, 0x93, 0x5d, 0x10,
+ 0x95, 0x32, 0x2b, 0x08, 0x8f, 0xc3, 0xa1, 0xa5, 0xde, 0xc7, 0xec, 0xb1,
+ 0x7a, 0x01, 0x9d, 0x62, 0xbe, 0x6f, 0x58, 0x7a, 0xf8, 0x38, 0x0b, 0x4b,
+ 0x17, 0xf7, 0x1f, 0x58, 0x2d, 0x2c, 0x5e, 0x1b, 0xe9, 0x62, 0xff, 0xfe,
+ 0x88, 0xc7, 0xdc, 0x5a, 0xe0, 0x8c, 0x3b, 0xfb, 0xee, 0xb1, 0x74, 0x9a,
+ 0xb1, 0x52, 0x7f, 0x2e, 0xc3, 0x52, 0xba, 0x15, 0x04, 0xbc, 0x5c, 0x34,
+ 0x87, 0x78, 0x47, 0x74, 0x44, 0xf0, 0xe0, 0x88, 0xbf, 0x43, 0x87, 0x86,
+ 0x2f, 0xde, 0x78, 0x41, 0xe2, 0x51, 0x17, 0x77, 0x42, 0x5a, 0xf0, 0xcf,
+ 0xc5, 0x8b, 0xf8, 0x3f, 0x7c, 0x26, 0xd9, 0x62, 0xdd, 0xea, 0xa4, 0xfc,
+ 0x2a, 0x07, 0xac, 0x73, 0x2b, 0xf6, 0xdd, 0x42, 0x46, 0xb1, 0x7c, 0x4f,
+ 0xd4, 0x16, 0x2f, 0xe8, 0x9f, 0x82, 0x11, 0xd6, 0x2b, 0x0f, 0x4d, 0x88,
+ 0xef, 0xfa, 0x77, 0xfc, 0xf6, 0xd0, 0x7c, 0x58, 0xbd, 0xac, 0xc5, 0x8a,
+ 0x8d, 0xd1, 0xf0, 0xef, 0xc4, 0x41, 0xc3, 0xeb, 0xc1, 0xcc, 0x4b, 0x17,
+ 0x8a, 0x40, 0xb1, 0x79, 0xf3, 0xeb, 0x16, 0xde, 0x4d, 0xc6, 0x87, 0x2f,
+ 0xff, 0x16, 0x0f, 0xf3, 0xdb, 0x91, 0xef, 0xd7, 0x96, 0x2b, 0x48, 0xce,
+ 0x25, 0x7e, 0xc4, 0xf7, 0x86, 0x10, 0x16, 0x2f, 0xff, 0x7f, 0x24, 0xfa,
+ 0xce, 0xef, 0xbc, 0x9d, 0x62, 0xff, 0x85, 0x08, 0x1f, 0xde, 0x93, 0xac,
+ 0x5a, 0x1f, 0x44, 0x3f, 0x93, 0x2f, 0xd3, 0xf7, 0x07, 0x16, 0x2f, 0xee,
+ 0x4e, 0xd9, 0xc1, 0xac, 0x56, 0x8f, 0x5f, 0xc5, 0x17, 0x7f, 0x16, 0x2f,
+ 0xff, 0xbf, 0x23, 0xcd, 0xcc, 0xc2, 0xc1, 0xfe, 0x56, 0x2f, 0xfb, 0x53,
+ 0xf7, 0xed, 0xa9, 0x82, 0xc5, 0xff, 0xfe, 0x04, 0xf5, 0x0e, 0x0f, 0x30,
+ 0xb3, 0x7f, 0xb8, 0xbc, 0xb1, 0x7f, 0xec, 0x2c, 0xce, 0x19, 0x0e, 0x1d,
+ 0x62, 0xff, 0xe9, 0xea, 0x4b, 0x69, 0x83, 0x96, 0x2c, 0x5f, 0xfb, 0x3d,
+ 0x80, 0x33, 0x3e, 0x52, 0xb1, 0x4e, 0x8c, 0x03, 0x9f, 0x92, 0x1d, 0xff,
+ 0x9a, 0x7a, 0x81, 0x9c, 0xe8, 0x72, 0xb1, 0x7e, 0xc1, 0xfd, 0xfc, 0xb1,
+ 0x7f, 0x36, 0xc5, 0x9b, 0x09, 0x62, 0x86, 0xba, 0x25, 0x91, 0x87, 0x6e,
+ 0x63, 0xd4, 0x29, 0x9e, 0x10, 0x11, 0xe4, 0x51, 0x0b, 0xe9, 0x40, 0x07,
+ 0x7c, 0x8c, 0x8b, 0xc5, 0xc1, 0x21, 0x47, 0x14, 0x5e, 0xe1, 0x4a, 0xc5,
+ 0xf6, 0x04, 0x64, 0x16, 0x2f, 0x9f, 0x98, 0x33, 0x0f, 0x07, 0x61, 0xcb,
+ 0xc6, 0xce, 0x96, 0x2f, 0x8e, 0xc3, 0x12, 0xc5, 0xe8, 0xa4, 0xeb, 0x17,
+ 0xdf, 0x93, 0xba, 0xc5, 0xfd, 0x3f, 0x7e, 0x48, 0x6b, 0x15, 0x87, 0xdc,
+ 0x21, 0xe0, 0xc8, 0xaf, 0x80, 0x4d, 0x05, 0x8b, 0xfb, 0xee, 0x76, 0x6e,
+ 0xe5, 0x8b, 0xf4, 0x08, 0x4c, 0x6a, 0xc5, 0xe1, 0x75, 0xc5, 0x8b, 0xfc,
+ 0x22, 0xf3, 0xfd, 0xce, 0xb1, 0x78, 0xb3, 0xb9, 0x62, 0xf1, 0xf3, 0xb2,
+ 0xc5, 0x18, 0x89, 0x08, 0x0f, 0xe1, 0x9b, 0x0f, 0xdc, 0xfb, 0x2c, 0x58,
+ 0x96, 0x2b, 0x46, 0xa4, 0x31, 0x8b, 0x1d, 0x62, 0xf6, 0xb3, 0xa5, 0x8b,
+ 0xe3, 0x83, 0xa0, 0x2c, 0x5c, 0x39, 0x81, 0xea, 0x80, 0x48, 0x31, 0xeb,
+ 0xff, 0xd0, 0xf3, 0xec, 0xc3, 0x98, 0x16, 0x1d, 0x62, 0xd1, 0xcb, 0x17,
+ 0xe6, 0xf3, 0x10, 0x16, 0x2a, 0x31, 0x5c, 0x34, 0x8f, 0x0e, 0x12, 0x26,
+ 0x97, 0xee, 0x45, 0xd1, 0x84, 0x50, 0xb9, 0xd3, 0x29, 0xdd, 0xd8, 0xef,
+ 0xbf, 0x4a, 0x8e, 0x15, 0xbf, 0xe7, 0x36, 0x74, 0x58, 0xe6, 0xac, 0x5e,
+ 0x1e, 0xbb, 0x2c, 0x5d, 0xbe, 0xcb, 0x17, 0xb5, 0x14, 0x16, 0x2f, 0xba,
+ 0xc1, 0x1d, 0x62, 0x9c, 0xf0, 0xf4, 0x3f, 0x7f, 0xf8, 0xd6, 0xe8, 0xce,
+ 0x4e, 0x9a, 0x0f, 0xf5, 0x8a, 0xc3, 0xee, 0x34, 0x86, 0xf8, 0x9b, 0xdc,
+ 0x58, 0xa3, 0x9e, 0x27, 0x62, 0x2b, 0xe6, 0x88, 0x38, 0x96, 0x2a, 0x4f,
+ 0x29, 0x89, 0x2e, 0x78, 0x96, 0x2f, 0xfd, 0x9b, 0x19, 0xf9, 0x89, 0xfa,
+ 0x82, 0xc5, 0xfd, 0x26, 0x8c, 0xa7, 0xa5, 0x8b, 0x9c, 0xeb, 0x15, 0x28,
+ 0x89, 0xd2, 0x1f, 0x62, 0xfb, 0xe9, 0x29, 0xdd, 0x62, 0xf4, 0xe8, 0xd5,
+ 0x8a, 0xdc, 0xf0, 0x08, 0x8a, 0xfa, 0x4b, 0x0d, 0x58, 0xbd, 0xc9, 0x35,
+ 0x62, 0xf7, 0xdb, 0xa5, 0x8b, 0xfc, 0xd9, 0xd7, 0xbc, 0xdf, 0x58, 0xbf,
+ 0xf8, 0x43, 0xcd, 0x4c, 0x1c, 0x72, 0x4b, 0x17, 0xfc, 0x4d, 0xb4, 0xeb,
+ 0x4d, 0x05, 0x8b, 0xfb, 0x91, 0x42, 0x4a, 0x0b, 0x17, 0xfe, 0x7f, 0x68,
+ 0x50, 0xea, 0x19, 0xe5, 0x8a, 0x82, 0x3b, 0x3e, 0x87, 0xe3, 0x9e, 0xc5,
+ 0xf7, 0xfa, 0x4d, 0xf6, 0x13, 0x79, 0x62, 0xff, 0x73, 0x98, 0x40, 0x8e,
+ 0xc5, 0x8b, 0xff, 0x9f, 0x90, 0x7f, 0x07, 0xa9, 0xfc, 0xac, 0x58, 0xf8,
+ 0x7f, 0x7f, 0x36, 0xbf, 0xfe, 0xd3, 0x70, 0xb3, 0x60, 0xe0, 0x29, 0x72,
+ 0x58, 0xa9, 0x4d, 0x92, 0x07, 0xed, 0x0a, 0xe1, 0x13, 0xd7, 0x4a, 0xc0,
+ 0x62, 0x1e, 0xf8, 0xf7, 0xa5, 0x42, 0x5f, 0xff, 0xe7, 0xe0, 0x30, 0xc7,
+ 0xed, 0x3f, 0x79, 0x8a, 0x29, 0xdd, 0x62, 0xf7, 0x9f, 0x65, 0x8b, 0xfd,
+ 0xf7, 0xd1, 0x3f, 0xb8, 0xb1, 0x7b, 0xa9, 0x89, 0x62, 0xc0, 0xdc, 0xf4,
+ 0x98, 0xce, 0xf1, 0x4e, 0xeb, 0x17, 0xfb, 0x39, 0x17, 0xdc, 0x2f, 0x2c,
+ 0x5f, 0x9a, 0x13, 0x1e, 0x75, 0x8b, 0xff, 0x3c, 0x5f, 0x9d, 0x75, 0x09,
+ 0xd2, 0xc5, 0xfd, 0x09, 0x8f, 0x3c, 0xc1, 0x62, 0xff, 0xba, 0x68, 0xf3,
+ 0xe8, 0xa6, 0x0b, 0x17, 0xff, 0xbd, 0xf9, 0xed, 0xc2, 0x6f, 0x44, 0xfd,
+ 0x96, 0x2f, 0xfc, 0xe7, 0xcd, 0x64, 0xc4, 0xe7, 0x58, 0xac, 0x44, 0x6e,
+ 0x93, 0xea, 0x53, 0xbf, 0xd8, 0xd8, 0x65, 0x71, 0x20, 0xfc, 0xc7, 0x90,
+ 0xca, 0xbe, 0xcf, 0x48, 0xd6, 0x2f, 0xa2, 0xd4, 0xf4, 0xb1, 0x7f, 0xf1,
+ 0x37, 0x5c, 0xe6, 0x68, 0x7f, 0xc5, 0x8b, 0xff, 0xd3, 0xb9, 0x9a, 0xc7,
+ 0x17, 0x7f, 0x9d, 0xd8, 0xb1, 0x4e, 0x89, 0x82, 0x45, 0xa3, 0x19, 0x1a,
+ 0xd0, 0x85, 0x0e, 0x38, 0xee, 0x44, 0xf2, 0xc8, 0xf4, 0x90, 0x76, 0x56,
+ 0x70, 0x22, 0x8e, 0x47, 0xb8, 0x12, 0xf0, 0x64, 0x5d, 0xd0, 0xbd, 0xb7,
+ 0x78, 0xb1, 0x7b, 0xb0, 0x1d, 0x62, 0x96, 0x2f, 0xe6, 0xe8, 0xe4, 0xc1,
+ 0x2c, 0x54, 0x9b, 0xbd, 0x06, 0x52, 0xc5, 0xec, 0xc0, 0x2c, 0x5e, 0xfb,
+ 0xf9, 0x62, 0xdd, 0xbb, 0xd4, 0x6b, 0x77, 0xc1, 0x7c, 0x5a, 0x72, 0x02,
+ 0x0c, 0x0c, 0x72, 0xc0, 0x58, 0xbf, 0x6b, 0x61, 0x30, 0xd6, 0x2d, 0x1c,
+ 0xb1, 0x50, 0x3d, 0x1c, 0x12, 0x0c, 0xaa, 0xf4, 0xf7, 0x71, 0x62, 0xe6,
+ 0x3a, 0xc5, 0x1a, 0x7c, 0xdb, 0x97, 0xe8, 0x82, 0xfd, 0xad, 0x64, 0x7c,
+ 0x4b, 0x17, 0x98, 0x84, 0xb1, 0x70, 0xf1, 0x62, 0xdc, 0x58, 0xa1, 0x9a,
+ 0x90, 0x85, 0xea, 0x5b, 0xb4, 0xb8, 0x43, 0x9c, 0x6e, 0x99, 0x3c, 0x59,
+ 0xbc, 0x62, 0x8f, 0x2f, 0x02, 0x3e, 0x17, 0xd1, 0x1c, 0x9c, 0x83, 0xf1,
+ 0xac, 0xb5, 0x23, 0xd8, 0x11, 0xd3, 0x0a, 0x31, 0xfe, 0xc6, 0x21, 0x16,
+ 0x86, 0x8b, 0x7b, 0xd9, 0xf5, 0x8b, 0xfe, 0x33, 0x7f, 0xb6, 0x85, 0x30,
+ 0x58, 0xbf, 0xdd, 0xdc, 0xe4, 0x9e, 0x7c, 0xb1, 0x68, 0xe5, 0x8b, 0x06,
+ 0xb1, 0x4e, 0x6a, 0x18, 0x56, 0xa4, 0xff, 0x8e, 0xbf, 0x7a, 0x1d, 0xec,
+ 0xac, 0x5f, 0x9c, 0xbd, 0x20, 0x58, 0xbf, 0x1c, 0x5b, 0xe1, 0xd6, 0x2f,
+ 0xda, 0x3c, 0x83, 0x8b, 0x14, 0x62, 0x27, 0x24, 0x89, 0xc9, 0xd8, 0xaa,
+ 0xff, 0x14, 0x0b, 0x0f, 0x3b, 0xac, 0x5d, 0x91, 0xcb, 0x15, 0x87, 0x9b,
+ 0xf3, 0x3b, 0xf0, 0xfe, 0x26, 0xe2, 0xc5, 0xfb, 0xef, 0xdb, 0x06, 0xb1,
+ 0x77, 0x9d, 0x62, 0xf6, 0x1e, 0x56, 0x28, 0xc3, 0x67, 0x82, 0xf7, 0x31,
+ 0xd6, 0x2f, 0x9f, 0x76, 0xd2, 0xc5, 0xfe, 0x2c, 0x21, 0x43, 0x38, 0xb1,
+ 0x7e, 0xe4, 0xef, 0x80, 0x58, 0xbf, 0x38, 0xc5, 0xee, 0x2c, 0x5d, 0xee,
+ 0x18, 0x7a, 0x4c, 0x53, 0x52, 0x8b, 0x21, 0x42, 0x12, 0xb6, 0x4c, 0x4e,
+ 0x02, 0xe3, 0x86, 0xad, 0xc6, 0x74, 0xb1, 0x7e, 0x63, 0xbf, 0x76, 0x2c,
+ 0x5f, 0xd9, 0xf6, 0xf3, 0x44, 0xb1, 0x74, 0xf4, 0xb1, 0x5d, 0x1e, 0x37,
+ 0x8b, 0xaf, 0x36, 0xa2, 0x58, 0xac, 0x45, 0x8b, 0x38, 0x70, 0x8e, 0xff,
+ 0x08, 0xb3, 0xc4, 0xc7, 0x58, 0xbf, 0xff, 0xec, 0xfb, 0x77, 0x69, 0xb6,
+ 0x2c, 0xee, 0x7c, 0x0b, 0xa8, 0x71, 0x62, 0xb1, 0x14, 0x1a, 0x32, 0xb4,
+ 0x4b, 0x17, 0xa4, 0xbc, 0xb1, 0x7b, 0xf8, 0x05, 0x8a, 0x73, 0xcc, 0x8f,
+ 0x13, 0xf0, 0xe5, 0xfe, 0xe4, 0xc2, 0x76, 0x9d, 0x96, 0x2e, 0xc3, 0x56,
+ 0x2f, 0xff, 0x61, 0xbf, 0x7e, 0x7f, 0x3b, 0x4e, 0x74, 0xb1, 0x52, 0x8c,
+ 0xb7, 0x31, 0xf9, 0xa9, 0x0c, 0x5a, 0x56, 0x2f, 0x98, 0x39, 0x09, 0x62,
+ 0xff, 0xef, 0xe6, 0xfa, 0xd4, 0xfb, 0x9f, 0x75, 0x8b, 0x98, 0xeb, 0x15,
+ 0x28, 0x92, 0xe8, 0x47, 0xc4, 0x81, 0xa3, 0x5d, 0xac, 0x58, 0xbf, 0x77,
+ 0x07, 0xaf, 0xb2, 0xc5, 0xff, 0x87, 0x87, 0xd4, 0xb9, 0x64, 0xac, 0x5d,
+ 0x3b, 0xac, 0x53, 0x9e, 0xa7, 0x8f, 0x2f, 0x83, 0xe4, 0xec, 0xb1, 0x52,
+ 0x78, 0xdc, 0x21, 0xba, 0x37, 0xee, 0x58, 0xbd, 0x17, 0x19, 0x62, 0xb1,
+ 0x32, 0x60, 0x43, 0x1c, 0x88, 0x44, 0x41, 0x7c, 0xfa, 0x98, 0x2c, 0x5f,
+ 0x6c, 0x79, 0xe2, 0xc5, 0x6c, 0x78, 0xd8, 0x45, 0x7f, 0xe9, 0xf3, 0x0b,
+ 0xcd, 0xd6, 0x79, 0x62, 0xff, 0xb4, 0x64, 0x8f, 0xf9, 0xbc, 0xac, 0x5f,
+ 0xfd, 0x38, 0x37, 0xe1, 0x67, 0x67, 0x25, 0x8a, 0xfa, 0x2f, 0x58, 0xfc,
+ 0x47, 0x77, 0xcd, 0x2f, 0x1c, 0xb1, 0x7e, 0xe0, 0xb6, 0x3b, 0xac, 0x56,
+ 0xe7, 0x9d, 0xd1, 0x25, 0xf9, 0xbe, 0x77, 0xe2, 0xc5, 0xe2, 0xce, 0x2c,
+ 0x5f, 0xff, 0xfa, 0x7e, 0xe7, 0x8c, 0x8a, 0x0d, 0xa0, 0xfe, 0xfd, 0x73,
+ 0x77, 0xd9, 0x62, 0xbb, 0xd6, 0x60, 0x3c, 0x8e, 0xed, 0x0b, 0xa8, 0x42,
+ 0xf4, 0x70, 0x88, 0xc2, 0x13, 0x4a, 0x77, 0x5d, 0x78, 0xcd, 0x23, 0xcd,
+ 0xe2, 0x86, 0x5e, 0xa1, 0x9d, 0xf8, 0xce, 0x5a, 0x19, 0x80, 0x3e, 0x28,
+ 0xcf, 0x79, 0x08, 0x7f, 0x43, 0x7c, 0x4f, 0xbd, 0x89, 0x03, 0x28, 0xee,
+ 0x1c, 0xbf, 0xde, 0x86, 0x47, 0xb1, 0x01, 0x62, 0xf6, 0xb8, 0x25, 0x8b,
+ 0x71, 0x62, 0xff, 0x6e, 0x06, 0x03, 0x96, 0xeb, 0x15, 0xf3, 0xc7, 0x21,
+ 0x2a, 0xc4, 0x43, 0x3b, 0x2d, 0xfe, 0xd8, 0x79, 0xee, 0x37, 0x4b, 0x17,
+ 0x81, 0xee, 0x2c, 0x5f, 0xfc, 0x76, 0xea, 0x30, 0x98, 0x64, 0xdf, 0x58,
+ 0xb7, 0x16, 0x29, 0x62, 0xbc, 0x5f, 0x76, 0x12, 0xa3, 0x11, 0x4b, 0x83,
+ 0xc0, 0x65, 0xa5, 0x8b, 0xa1, 0xde, 0x2c, 0x58, 0xc7, 0x35, 0x2c, 0x19,
+ 0x7d, 0x82, 0xd6, 0xcb, 0x17, 0xd0, 0xe0, 0xce, 0xb1, 0x7e, 0x1e, 0x0d,
+ 0xa0, 0xb1, 0x4e, 0x7e, 0x0c, 0x48, 0x22, 0x4b, 0xff, 0xb3, 0xb6, 0x0f,
+ 0x08, 0x50, 0xce, 0x2c, 0x5f, 0xb5, 0x3f, 0x0c, 0x6b, 0x15, 0xa3, 0xef,
+ 0x64, 0x5b, 0x01, 0x62, 0xed, 0xa5, 0x62, 0xfd, 0x83, 0xfb, 0xec, 0xb1,
+ 0x69, 0xd8, 0xf4, 0xdc, 0x48, 0x86, 0x2f, 0x82, 0x6c, 0xe2, 0xc5, 0xfc,
+ 0x39, 0x01, 0x67, 0x4b, 0x17, 0xfd, 0x03, 0xb4, 0x3d, 0xc9, 0x35, 0x62,
+ 0xef, 0xba, 0xc5, 0x4a, 0x28, 0xf0, 0x8d, 0x8b, 0xbc, 0x77, 0x7a, 0x4b,
+ 0x75, 0x8b, 0x9f, 0x65, 0x8a, 0x93, 0x6b, 0xf1, 0xdb, 0xdc, 0x72, 0x58,
+ 0xb0, 0x16, 0x2f, 0xe8, 0x4e, 0xb5, 0x21, 0x2c, 0x5b, 0xa5, 0x8b, 0xb7,
+ 0x33, 0x0f, 0x0b, 0x85, 0xf5, 0xa4, 0x41, 0x92, 0xa5, 0xfe, 0x0e, 0x13,
+ 0xd9, 0xc8, 0x0b, 0x17, 0xcd, 0xdd, 0x84, 0xb1, 0x7d, 0xc6, 0xe9, 0xd6,
+ 0x2b, 0x13, 0x3e, 0x68, 0x4f, 0x91, 0x17, 0x0d, 0xbc, 0x49, 0x7f, 0xf8,
+ 0x01, 0xf9, 0xe0, 0xfa, 0x01, 0xdf, 0x8b, 0x14, 0x35, 0xef, 0x3c, 0x85,
+ 0xe6, 0xe4, 0x2f, 0x0d, 0xb8, 0xf5, 0x93, 0xc2, 0x59, 0xa1, 0x38, 0x07,
+ 0x42, 0x86, 0xb7, 0x1b, 0xc5, 0x1a, 0xf7, 0x64, 0xdb, 0xa1, 0xf5, 0x8b,
+ 0xee, 0x6c, 0x2e, 0x2c, 0x5d, 0xb4, 0x16, 0x2f, 0x3f, 0xdd, 0x62, 0xe3,
+ 0xca, 0xc5, 0xd1, 0xb8, 0xd6, 0x2a, 0x51, 0x4d, 0x83, 0x1d, 0x12, 0xf8,
+ 0x64, 0x43, 0x91, 0xc2, 0xf7, 0xff, 0x6d, 0xbf, 0xdc, 0x3d, 0x1b, 0x9d,
+ 0x79, 0x62, 0xfb, 0x3a, 0x84, 0xac, 0x5e, 0x7f, 0xca, 0xc5, 0xe1, 0x37,
+ 0x16, 0x2b, 0x11, 0x4f, 0xf4, 0xbe, 0xc4, 0x61, 0x8e, 0x5e, 0xf3, 0xec,
+ 0xb1, 0x7f, 0xce, 0x6c, 0x8e, 0x7b, 0x67, 0xd6, 0x2f, 0xd8, 0x51, 0xd2,
+ 0x6a, 0xc5, 0xf1, 0x00, 0xfe, 0x58, 0xbf, 0xbe, 0xe6, 0x6d, 0x81, 0x2c,
+ 0x54, 0x9e, 0xa7, 0x08, 0xef, 0xf3, 0x85, 0xd4, 0x39, 0x9b, 0xac, 0x5f,
+ 0xd0, 0x0c, 0x00, 0x9e, 0x96, 0x2f, 0x60, 0x5b, 0xac, 0x54, 0xa6, 0x4e,
+ 0xef, 0xff, 0x21, 0x63, 0x72, 0x31, 0xbf, 0x4f, 0x50, 0xe4, 0xac, 0x5f,
+ 0xf0, 0xb8, 0x60, 0xc4, 0xda, 0x82, 0xc5, 0x61, 0xf2, 0x91, 0x4d, 0xfc,
+ 0x2e, 0x4c, 0x42, 0xd2, 0xc5, 0xe1, 0x67, 0x4b, 0x17, 0xf6, 0x74, 0x0c,
+ 0xf7, 0x16, 0x2f, 0xd2, 0x5d, 0x43, 0x8b, 0x1f, 0x35, 0xf5, 0xf4, 0x5b,
+ 0x78, 0xc0, 0x49, 0xb7, 0xbe, 0xfb, 0xac, 0x5e, 0xf6, 0x1d, 0x62, 0xf9,
+ 0xcd, 0xfb, 0xac, 0x5b, 0x24, 0xf0, 0x3e, 0x3b, 0x50, 0x44, 0x27, 0x97,
+ 0xaf, 0xec, 0x3e, 0xb5, 0x23, 0x58, 0xbf, 0x75, 0xcf, 0x3e, 0xcb, 0x17,
+ 0xf0, 0x8b, 0x6e, 0x3f, 0x4b, 0x17, 0xff, 0x4e, 0xc1, 0x37, 0x5c, 0xc1,
+ 0xbf, 0x16, 0x2a, 0x51, 0x45, 0x02, 0xb2, 0x30, 0xb7, 0x96, 0x2f, 0x49,
+ 0x6c, 0xb1, 0x7e, 0xc3, 0x7c, 0xfb, 0x2c, 0x5f, 0xe7, 0x88, 0xc2, 0x9f,
+ 0x71, 0x62, 0xe8, 0x0d, 0x62, 0xec, 0xe9, 0x62, 0xb0, 0xd8, 0x00, 0x62,
+ 0xf4, 0x97, 0x96, 0x2a, 0x51, 0xf4, 0x31, 0x2e, 0x87, 0x74, 0x54, 0x06,
+ 0x5e, 0xc4, 0x17, 0x47, 0x4a, 0xc5, 0xfd, 0xc1, 0x40, 0xcc, 0x25, 0x8a,
+ 0x73, 0xc9, 0xf0, 0xd5, 0xff, 0xfd, 0x0e, 0x16, 0x44, 0x66, 0xff, 0x9d,
+ 0xcd, 0xd3, 0x04, 0xb1, 0x7b, 0x1f, 0x65, 0x8b, 0xa7, 0x6e, 0x8f, 0xfc,
+ 0x98, 0xa9, 0x91, 0x9c, 0x28, 0x50, 0x5f, 0xff, 0xa7, 0x40, 0xce, 0x10,
+ 0x9a, 0x1f, 0x13, 0x6c, 0xb1, 0x7c, 0xd0, 0xe8, 0x0b, 0x17, 0xf0, 0x24,
+ 0xef, 0xa8, 0x96, 0x2d, 0xd9, 0x62, 0xc5, 0x27, 0x87, 0x85, 0xf7, 0xef,
+ 0x63, 0x16, 0xeb, 0x15, 0xf4, 0xc2, 0x89, 0x5b, 0xcc, 0xfd, 0xc4, 0xb7,
+ 0xff, 0xa4, 0x1a, 0xd4, 0x84, 0x67, 0xb9, 0x9b, 0x2c, 0x5e, 0xea, 0x4e,
+ 0xb1, 0x7f, 0xf8, 0x7f, 0x9e, 0xa0, 0x58, 0x7c, 0xeb, 0xcb, 0x17, 0xe3,
+ 0xe7, 0xf0, 0x96, 0x29, 0xcf, 0xcd, 0x93, 0x2f, 0xf4, 0x1c, 0x85, 0x24,
+ 0x6a, 0xc5, 0xfe, 0xfb, 0xf0, 0x47, 0x97, 0x58, 0xbe, 0x68, 0xe6, 0x35,
+ 0x62, 0xee, 0xbd, 0xb9, 0xec, 0xfc, 0xce, 0xfe, 0xc3, 0x67, 0x80, 0x65,
+ 0x8a, 0xc3, 0xde, 0x08, 0xc2, 0xff, 0x34, 0x07, 0x98, 0x0e, 0x2c, 0x53,
+ 0x9e, 0xa8, 0x88, 0xaf, 0xfd, 0xdb, 0xed, 0x03, 0x3d, 0xf6, 0x35, 0x62,
+ 0xff, 0x03, 0x0a, 0x29, 0xcd, 0x2c, 0x56, 0x1f, 0xbb, 0x22, 0x5c, 0xc4,
+ 0xb1, 0x73, 0x77, 0x2c, 0x5c, 0x7c, 0xd1, 0xb0, 0xf8, 0xb5, 0xff, 0xba,
+ 0x87, 0xe4, 0xed, 0xd4, 0x31, 0x62, 0xfe, 0x7e, 0xba, 0x86, 0x79, 0x62,
+ 0xa5, 0x13, 0xb8, 0x58, 0x04, 0x1b, 0xff, 0xcc, 0x0e, 0x0f, 0xf8, 0x5e,
+ 0xce, 0xbc, 0xb1, 0x5d, 0x2b, 0x3d, 0xfc, 0x67, 0xe5, 0x09, 0x8e, 0x43,
+ 0xb7, 0xc5, 0xd7, 0xee, 0xb8, 0x77, 0x8f, 0x58, 0xb9, 0x9d, 0x62, 0xff,
+ 0xef, 0xb3, 0xf8, 0x02, 0x22, 0x68, 0x2c, 0x5f, 0xf3, 0x13, 0x9f, 0xae,
+ 0x4c, 0x4b, 0x17, 0xd2, 0x42, 0xef, 0xd6, 0x2f, 0x8f, 0x3d, 0x41, 0x62,
+ 0xec, 0xe1, 0x88, 0xc8, 0xd9, 0x0f, 0xe7, 0x40, 0x27, 0xa9, 0x4d, 0x55,
+ 0x8b, 0x4a, 0x1b, 0xd7, 0x7b, 0xbf, 0x58, 0xbf, 0xdc, 0xfb, 0x6f, 0x24,
+ 0x35, 0x8b, 0x30, 0x0f, 0x47, 0xc3, 0xb7, 0xf3, 0x6c, 0x06, 0x21, 0xac,
+ 0x5f, 0xec, 0x3c, 0x50, 0x62, 0xd9, 0x62, 0xfb, 0xdf, 0x63, 0xac, 0x5f,
+ 0xfe, 0xc0, 0xba, 0x87, 0x39, 0x27, 0x6e, 0xbc, 0xb1, 0x52, 0x7e, 0x2e,
+ 0x47, 0x5b, 0x36, 0x04, 0x03, 0x8d, 0x88, 0xd8, 0x56, 0x6f, 0x0d, 0x6e,
+ 0xa1, 0x68, 0xe4, 0x71, 0x43, 0x43, 0x51, 0x94, 0x1e, 0x37, 0x0f, 0xc6,
+ 0x62, 0x04, 0x02, 0x4e, 0xe4, 0x24, 0x7d, 0x2d, 0x77, 0xb4, 0x76, 0x21,
+ 0x42, 0x12, 0x38, 0x9c, 0x32, 0xee, 0xe8, 0x53, 0x5f, 0x45, 0x99, 0xba,
+ 0xc5, 0xf6, 0x44, 0xe7, 0x58, 0xad, 0x1e, 0x38, 0x09, 0x2f, 0xfb, 0xff,
+ 0xc7, 0xea, 0x19, 0xa5, 0x8b, 0xef, 0xe7, 0x50, 0x58, 0xa9, 0x44, 0x03,
+ 0x11, 0x70, 0xea, 0xff, 0x78, 0x5b, 0x4f, 0xa4, 0x6b, 0x17, 0xbd, 0x84,
+ 0xb1, 0x7b, 0xed, 0x1e, 0xb1, 0x71, 0x79, 0x62, 0xfc, 0x28, 0x60, 0x38,
+ 0xb1, 0x7f, 0x83, 0x9d, 0xe3, 0xb3, 0x52, 0xb1, 0x7f, 0xc3, 0xc1, 0x6b,
+ 0x6d, 0xdf, 0x65, 0x8b, 0xc5, 0x1a, 0x79, 0x62, 0xff, 0xf7, 0x6c, 0x21,
+ 0x93, 0x05, 0xce, 0x48, 0x16, 0x2f, 0xff, 0xfe, 0x3b, 0xf0, 0xc8, 0xa0,
+ 0x22, 0xf1, 0x9f, 0x98, 0x39, 0x61, 0xe5, 0x62, 0xb1, 0x18, 0x02, 0x4c,
+ 0xbe, 0x7d, 0x49, 0xd6, 0x2b, 0x47, 0x89, 0xf2, 0x2b, 0xc5, 0x81, 0x2c,
+ 0x5f, 0xff, 0x6f, 0xf1, 0x16, 0x75, 0x07, 0xe1, 0x67, 0x65, 0x8b, 0xf7,
+ 0xe7, 0xee, 0x6a, 0xc5, 0xcd, 0x17, 0x0f, 0xf3, 0xb9, 0x4e, 0xf3, 0xe8,
+ 0xd5, 0x8a, 0x94, 0xc2, 0xa2, 0x22, 0xfc, 0x26, 0x63, 0x8c, 0x6f, 0xff,
+ 0xf3, 0xf6, 0x21, 0x70, 0xc0, 0xca, 0x47, 0xf6, 0x86, 0x71, 0x62, 0xa0,
+ 0xaf, 0x2c, 0xd1, 0xc7, 0x20, 0xd0, 0xbf, 0xca, 0x58, 0xe0, 0x8f, 0x7d,
+ 0x28, 0xc3, 0xb2, 0x35, 0xfb, 0x22, 0x83, 0x12, 0xc5, 0xfb, 0x34, 0x52,
+ 0x05, 0x8b, 0xbb, 0x77, 0x2c, 0x5c, 0x7c, 0x58, 0xa9, 0x6d, 0xf5, 0xb6,
+ 0x3f, 0xca, 0xc0, 0xf9, 0xe5, 0x10, 0xe8, 0xb9, 0xa7, 0x00, 0x3d, 0x08,
+ 0x71, 0x14, 0x47, 0x13, 0x86, 0x3b, 0x7f, 0x39, 0xc5, 0x14, 0xf9, 0x62,
+ 0xfb, 0xff, 0x73, 0x56, 0x2e, 0x88, 0x4b, 0x17, 0xfe, 0x36, 0x4b, 0x76,
+ 0x7d, 0x8c, 0xc5, 0x8b, 0x1d, 0x62, 0xb1, 0x12, 0x1d, 0x12, 0x38, 0xcf,
+ 0x7e, 0x83, 0x7f, 0xbc, 0x01, 0x17, 0x1c, 0x6b, 0x17, 0xe8, 0x03, 0x30,
+ 0x6b, 0x16, 0xec, 0xe7, 0xb8, 0xc6, 0x97, 0xef, 0xbe, 0x80, 0x25, 0x8b,
+ 0xa6, 0x0b, 0x17, 0xe9, 0xeb, 0xd3, 0xa5, 0x8b, 0xcf, 0xf1, 0x2c, 0x5b,
+ 0x58, 0x8a, 0xe8, 0x8a, 0x34, 0x52, 0x71, 0x7f, 0x14, 0xdf, 0xc1, 0x71,
+ 0xa7, 0xa8, 0x2c, 0x54, 0xa2, 0x03, 0x14, 0x2f, 0xf3, 0x83, 0xdd, 0x6e,
+ 0xfa, 0x58, 0xbf, 0xec, 0xe9, 0xbd, 0x3e, 0x60, 0x2c, 0x5f, 0xfe, 0xc2,
+ 0xdb, 0x76, 0x1e, 0xb5, 0x27, 0xe2, 0xc5, 0xff, 0xc5, 0x3e, 0xe7, 0xba,
+ 0xdd, 0xcb, 0x65, 0x8b, 0xf7, 0x73, 0xf5, 0x0e, 0x2c, 0x54, 0x47, 0xe8,
+ 0xc8, 0xf7, 0x43, 0xeb, 0x17, 0xf9, 0xc8, 0xd6, 0x14, 0x06, 0xb1, 0x7c,
+ 0x70, 0xe2, 0xe2, 0xc5, 0x49, 0xf9, 0x60, 0xc3, 0x9a, 0x5f, 0xc5, 0x9e,
+ 0x14, 0x92, 0xc5, 0xfb, 0xa8, 0x14, 0x8d, 0x62, 0x8e, 0x7a, 0xac, 0x59,
+ 0x7f, 0x41, 0xc8, 0xed, 0xe5, 0x8b, 0xfe, 0x1e, 0x19, 0xc7, 0x2e, 0xa0,
+ 0xb1, 0x69, 0xe8, 0xfa, 0x02, 0x2d, 0xa9, 0x55, 0x81, 0x87, 0x2f, 0x0c,
+ 0x0f, 0xc2, 0x51, 0xa1, 0x02, 0x50, 0x89, 0xbd, 0x9b, 0x4a, 0xc5, 0xef,
+ 0x67, 0xd6, 0x2c, 0xd0, 0x37, 0x5f, 0x1d, 0xbf, 0xb0, 0x5d, 0xf8, 0xbc,
+ 0x1a, 0xc5, 0xff, 0xec, 0x20, 0xc0, 0x66, 0x6f, 0x8e, 0x52, 0xb1, 0x5a,
+ 0x3f, 0xff, 0x9a, 0xdf, 0xfd, 0x3c, 0xe6, 0x1f, 0xc5, 0x27, 0xe2, 0xc5,
+ 0xff, 0x4e, 0x8d, 0xf9, 0x4e, 0x69, 0x62, 0xfe, 0x34, 0xcc, 0x3c, 0xee,
+ 0xb1, 0x7f, 0xf4, 0xf5, 0x0f, 0x0a, 0x76, 0x7e, 0xbc, 0xb1, 0x7f, 0x9f,
+ 0xed, 0xbc, 0x90, 0xd6, 0x29, 0xd1, 0x58, 0x46, 0x3c, 0x48, 0xbf, 0xa7,
+ 0x70, 0x1c, 0x40, 0x58, 0xbe, 0xec, 0xe4, 0x35, 0x8b, 0xff, 0x14, 0x8f,
+ 0xf2, 0x72, 0xcd, 0xd6, 0x2f, 0x39, 0x79, 0x62, 0xb0, 0xff, 0xa2, 0x24,
+ 0xf9, 0xf5, 0xfe, 0x1f, 0x1f, 0xff, 0xc1, 0xac, 0x5f, 0xfa, 0x78, 0x4d,
+ 0x03, 0x39, 0x9a, 0x58, 0xbf, 0x42, 0x22, 0x91, 0xac, 0x53, 0x9f, 0x43,
+ 0x1f, 0xdf, 0x87, 0x85, 0x31, 0xeb, 0x17, 0xf1, 0x64, 0x3f, 0x23, 0x58,
+ 0xad, 0x8f, 0x5c, 0x65, 0x57, 0x89, 0xb4, 0xb1, 0x7c, 0xcc, 0xdd, 0xcb,
+ 0x17, 0xff, 0xff, 0xfb, 0xf8, 0xfa, 0x81, 0x85, 0x91, 0x42, 0x4b, 0xc6,
+ 0x03, 0x86, 0x70, 0xed, 0x03, 0x7c, 0xb1, 0x7f, 0xf0, 0x24, 0xcf, 0x7f,
+ 0x3d, 0xf6, 0x82, 0xc5, 0xff, 0xff, 0xfa, 0x7e, 0x59, 0xe8, 0xec, 0x33,
+ 0x7f, 0xb8, 0xca, 0x5b, 0x6f, 0xb1, 0x87, 0x02, 0xc5, 0xff, 0xff, 0xfb,
+ 0xf8, 0x7c, 0xde, 0x7f, 0x27, 0x33, 0x85, 0x9f, 0xf1, 0x48, 0x0c, 0x38,
+ 0x16, 0x2f, 0x60, 0xcc, 0x74, 0xd4, 0xf4, 0x8d, 0xe8, 0x44, 0x5f, 0xfd,
+ 0xcd, 0xb0, 0x2c, 0x21, 0x77, 0x4c, 0x66, 0x2a, 0x6e, 0x38, 0xe7, 0x89,
+ 0x3b, 0x47, 0xcf, 0x7e, 0xf7, 0x18, 0x8d, 0x58, 0xbf, 0xf4, 0x66, 0xee,
+ 0x6f, 0xda, 0x19, 0xc5, 0x8a, 0xd8, 0xfb, 0x78, 0x53, 0x52, 0xae, 0x9d,
+ 0xe5, 0x48, 0x87, 0x0f, 0x3b, 0xfd, 0xd4, 0x39, 0x14, 0x27, 0x65, 0x8b,
+ 0xfe, 0xd6, 0x1a, 0xc3, 0xfc, 0xe9, 0x62, 0x86, 0xc8, 0x64, 0xc8, 0x52,
+ 0xee, 0x45, 0x12, 0x26, 0xa1, 0xca, 0x72, 0xef, 0xc2, 0xb9, 0x8b, 0xca,
+ 0x13, 0x9e, 0x9c, 0x1e, 0x11, 0xef, 0x63, 0x8b, 0xff, 0xee, 0xbd, 0xad,
+ 0x4f, 0x80, 0x19, 0x43, 0xf8, 0xb1, 0x6f, 0x2c, 0x5b, 0xd8, 0x7c, 0xba,
+ 0x53, 0xb9, 0xfb, 0x2c, 0x5f, 0x49, 0x43, 0x8b, 0x16, 0x7e, 0x8f, 0x8a,
+ 0x22, 0x70, 0x0c, 0xdf, 0xed, 0x6c, 0x53, 0xbb, 0xc1, 0x62, 0xbe, 0x7d,
+ 0x6c, 0x6d, 0x7e, 0xfc, 0xf6, 0x1c, 0xac, 0x5c, 0xc4, 0xb1, 0x7d, 0xa6,
+ 0xed, 0x8b, 0x14, 0x33, 0x74, 0x21, 0x6b, 0xe7, 0xfc, 0xc1, 0x62, 0xdd,
+ 0x96, 0x2f, 0xdd, 0x78, 0xa7, 0xeb, 0x16, 0xd4, 0x9b, 0xd6, 0x14, 0xbe,
+ 0xea, 0x29, 0xd2, 0xc5, 0xb4, 0xb1, 0x58, 0x6d, 0xc4, 0x4b, 0x7c, 0xda,
+ 0xea, 0x0b, 0x17, 0x7d, 0xd6, 0x2f, 0xff, 0xd3, 0xef, 0xb4, 0x5c, 0x67,
+ 0xdc, 0x9b, 0x37, 0x58, 0xa8, 0x27, 0xe2, 0x36, 0x43, 0x48, 0x74, 0xbf,
+ 0xc5, 0xc1, 0x10, 0x76, 0x24, 0x8e, 0x17, 0xbe, 0x7e, 0xd8, 0x35, 0x8b,
+ 0xe2, 0xf6, 0x12, 0xc5, 0xc5, 0xed, 0x1e, 0x2b, 0x12, 0x5f, 0xf7, 0x50,
+ 0xe0, 0xbd, 0x3e, 0xe2, 0xc5, 0xfb, 0x50, 0x6e, 0x82, 0x58, 0xbf, 0xdc,
+ 0x09, 0x87, 0x3d, 0x71, 0x62, 0xa5, 0x19, 0x38, 0x58, 0xe7, 0x8c, 0x57,
+ 0x7e, 0xe0, 0xbd, 0x24, 0xb1, 0x7f, 0x85, 0xd4, 0x3d, 0xc1, 0x47, 0xac,
+ 0x5e, 0xe4, 0xf4, 0xb1, 0x7a, 0x7f, 0xc5, 0x8b, 0xf6, 0x7e, 0x1d, 0x01,
+ 0x62, 0xe6, 0x0b, 0xa3, 0xe5, 0x00, 0xf7, 0x87, 0x6f, 0xff, 0xa4, 0x83,
+ 0xc8, 0xbe, 0xc7, 0xc1, 0xb4, 0x16, 0x2a, 0x09, 0xc6, 0x61, 0xcf, 0xca,
+ 0x0a, 0x13, 0xe1, 0x1e, 0x5f, 0xec, 0xe8, 0xcc, 0xfb, 0xfd, 0x62, 0xef,
+ 0x8d, 0x62, 0xe7, 0xdd, 0x62, 0xe6, 0xf0, 0xcd, 0x84, 0x70, 0xc5, 0x69,
+ 0x12, 0x8c, 0xcb, 0x69, 0x58, 0xbf, 0xb5, 0x2f, 0x06, 0xe2, 0xc5, 0x0c,
+ 0xdf, 0x74, 0x23, 0x7f, 0x03, 0x22, 0x93, 0xba, 0xc5, 0xff, 0xb8, 0x1f,
+ 0x39, 0xb3, 0x45, 0x31, 0xeb, 0x14, 0xc7, 0xe9, 0xe2, 0xeb, 0xfe, 0xf7,
+ 0x05, 0x00, 0xc6, 0xfe, 0x58, 0xbd, 0x39, 0xa5, 0x8b, 0xf0, 0x8d, 0xfb,
+ 0xf1, 0x62, 0xf1, 0x31, 0xb1, 0x1e, 0x36, 0x87, 0x2a, 0x53, 0x6d, 0xc8,
+ 0x4b, 0x31, 0x08, 0xa1, 0x05, 0x7f, 0xfe, 0xd0, 0x8b, 0x9e, 0xeb, 0x77,
+ 0xd7, 0x98, 0x1c, 0x58, 0xbf, 0xfb, 0x87, 0x14, 0x20, 0xcf, 0xbb, 0x8d,
+ 0x62, 0xd1, 0x98, 0x89, 0xfe, 0x2c, 0xdf, 0x4e, 0x41, 0x96, 0x28, 0x67,
+ 0x99, 0xf2, 0xbb, 0xd8, 0xfc, 0x58, 0xbf, 0x7b, 0xd8, 0x2d, 0x96, 0x2f,
+ 0xff, 0xb6, 0x6f, 0xe0, 0xcc, 0xc2, 0x2c, 0x70, 0x2c, 0x5e, 0x3b, 0xe9,
+ 0x62, 0xb6, 0x45, 0x96, 0xe3, 0x9a, 0x2a, 0x02, 0x7d, 0xff, 0x68, 0x19,
+ 0xa0, 0x10, 0x80, 0xb1, 0x7e, 0x03, 0x75, 0x03, 0xac, 0x5f, 0xe8, 0x78,
+ 0xb3, 0x9f, 0x75, 0x8a, 0x94, 0x4b, 0xc4, 0x74, 0xc5, 0x57, 0x79, 0x96,
+ 0x2f, 0xe2, 0x84, 0xb9, 0x4a, 0xc5, 0xfc, 0x4c, 0x6f, 0x33, 0x4b, 0x17,
+ 0xff, 0xcd, 0xff, 0xb9, 0x90, 0x73, 0xcf, 0xc3, 0x1a, 0xc5, 0x62, 0x2a,
+ 0xce, 0x57, 0xd8, 0xba, 0xff, 0xf6, 0x6b, 0x4d, 0x03, 0x3f, 0x3e, 0xe3,
+ 0x2c, 0x5e, 0xf6, 0xc1, 0x2c, 0x5c, 0x7c, 0x58, 0xbf, 0x9c, 0x7a, 0x71,
+ 0x6c, 0xb1, 0x7b, 0x4d, 0xc3, 0x0f, 0x9b, 0x08, 0x3c, 0x2f, 0x6f, 0x4a,
+ 0x64, 0x50, 0x31, 0x14, 0x2c, 0x6f, 0xf6, 0xee, 0xc6, 0x71, 0xbe, 0xb1,
+ 0x4e, 0x7e, 0x1f, 0x3b, 0xbf, 0xff, 0x19, 0xe2, 0xc7, 0xe7, 0x30, 0xb3,
+ 0xdf, 0x75, 0x8a, 0x1a, 0xe5, 0x16, 0x43, 0x51, 0xe1, 0xac, 0x72, 0xf6,
+ 0x94, 0xa8, 0x22, 0x1b, 0xdc, 0x11, 0xab, 0x17, 0xbe, 0xe1, 0x2c, 0x5f,
+ 0xff, 0xbe, 0xe7, 0x61, 0xf3, 0x09, 0xba, 0xd6, 0x1d, 0x62, 0xf8, 0xa6,
+ 0x0e, 0xb1, 0x79, 0x8a, 0x25, 0x8b, 0xdd, 0x41, 0xd6, 0x2c, 0xc7, 0x37,
+ 0x64, 0x3b, 0x78, 0x52, 0x4b, 0x17, 0xf4, 0x27, 0xb4, 0x70, 0xb4, 0xb1,
+ 0x7f, 0xff, 0x9f, 0xd2, 0x4d, 0x0c, 0x1f, 0x1b, 0x4f, 0xf7, 0xec, 0xb1,
+ 0x7d, 0x25, 0x0e, 0x2c, 0x56, 0x27, 0xcb, 0xb8, 0xfb, 0x8f, 0x69, 0x57,
+ 0xeb, 0x84, 0x4a, 0x21, 0xce, 0xc6, 0x81, 0xb0, 0x5f, 0xff, 0xb8, 0x46,
+ 0x7d, 0x9f, 0xc0, 0x11, 0x13, 0x41, 0x62, 0xff, 0xff, 0xe9, 0xd6, 0x45,
+ 0x27, 0xcd, 0xdc, 0x7f, 0x9f, 0x70, 0xdd, 0x67, 0x72, 0xc5, 0xf8, 0xa6,
+ 0x00, 0x75, 0x8b, 0xf9, 0xcd, 0x8e, 0x16, 0x8d, 0x58, 0xbf, 0xc5, 0x22,
+ 0xeb, 0x8d, 0x1e, 0xb1, 0x5f, 0x3e, 0xb6, 0x34, 0xbe, 0x9c, 0x0b, 0xcb,
+ 0x17, 0xf6, 0xf3, 0xd0, 0x35, 0x2b, 0x17, 0xfa, 0x4b, 0x76, 0x20, 0x77,
+ 0xab, 0x15, 0x27, 0xd0, 0x73, 0x0b, 0x8b, 0x75, 0x8a, 0x58, 0xbe, 0xc8,
+ 0xe7, 0x02, 0xc5, 0x46, 0xc6, 0xc7, 0x41, 0x96, 0x7c, 0x3e, 0xf3, 0xa4,
+ 0xdf, 0xf4, 0x83, 0x5a, 0x90, 0x87, 0xd2, 0xc5, 0xfe, 0x08, 0xff, 0x97,
+ 0x2d, 0x96, 0x2f, 0xff, 0x34, 0x1f, 0x59, 0xd4, 0x50, 0x9d, 0x6c, 0xb1,
+ 0x7f, 0xff, 0x80, 0x76, 0x86, 0x76, 0x7e, 0x7f, 0x01, 0x1d, 0x9f, 0x75,
+ 0x8a, 0x94, 0x73, 0x80, 0xd4, 0x49, 0xb7, 0x05, 0xc5, 0x8b, 0xfe, 0x3c,
+ 0xef, 0x9e, 0x7d, 0x62, 0xc5, 0xcd, 0xe5, 0x8b, 0xc5, 0x9c, 0x30, 0xfa,
+ 0x70, 0x64, 0x8e, 0x6f, 0xe6, 0xd8, 0x79, 0x9c, 0x58, 0xbf, 0xe9, 0xd4,
+ 0x6c, 0x01, 0x31, 0x6e, 0xb1, 0x58, 0xb8, 0xb5, 0xbc, 0x24, 0xa2, 0x21,
+ 0x3c, 0x22, 0xff, 0x09, 0x00, 0x13, 0x7a, 0x32, 0x3e, 0xd0, 0x98, 0x8e,
+ 0x3e, 0x0c, 0xba, 0xff, 0xb9, 0xe1, 0x75, 0x83, 0x62, 0x58, 0xbf, 0xff,
+ 0xfa, 0x12, 0x60, 0xf0, 0x9b, 0x9f, 0x60, 0x70, 0xcc, 0xf4, 0xfb, 0x8b,
+ 0x15, 0x12, 0x2b, 0x7c, 0x75, 0x70, 0xba, 0x58, 0xbf, 0xa4, 0xf3, 0x9d,
+ 0x79, 0x62, 0xd8, 0x73, 0xc7, 0xf0, 0xcd, 0x4a, 0xf5, 0xfe, 0x4e, 0x68,
+ 0xb4, 0x6b, 0x82, 0x6b, 0xbf, 0xdb, 0x49, 0x7b, 0xed, 0x05, 0x8a, 0x58,
+ 0xbe, 0xfb, 0x31, 0xd6, 0x2f, 0xec, 0x2c, 0xe4, 0xe9, 0x62, 0xb4, 0x79,
+ 0xc1, 0x91, 0x5f, 0xdd, 0xee, 0x9e, 0x4f, 0x8b, 0x17, 0x68, 0xd5, 0x8a,
+ 0x94, 0x7e, 0x40, 0xd3, 0x16, 0x88, 0x8c, 0x33, 0x2b, 0xfe, 0xea, 0x11,
+ 0xce, 0x5e, 0x93, 0xac, 0x5e, 0xe1, 0x8e, 0xb1, 0x58, 0x7b, 0x7e, 0x3d,
+ 0xbf, 0xb6, 0xcd, 0x3e, 0xf2, 0xb1, 0x7c, 0x43, 0x93, 0xac, 0x5f, 0xff,
+ 0x08, 0xbd, 0xcf, 0xbc, 0x45, 0x27, 0x68, 0x2c, 0x5f, 0xda, 0x97, 0x83,
+ 0x71, 0x62, 0xe1, 0x32, 0xc5, 0xb0, 0xc3, 0xc4, 0x22, 0xda, 0x3a, 0x2e,
+ 0xfb, 0x42, 0x52, 0xfe, 0x60, 0x60, 0xda, 0x0b, 0x15, 0x29, 0x9a, 0x64,
+ 0x37, 0x5c, 0xaa, 0xf8, 0x1c, 0x8d, 0x5d, 0xea, 0xc5, 0xe6, 0xd6, 0xcb,
+ 0x17, 0xff, 0xcd, 0xe1, 0x4b, 0xcf, 0x5b, 0xff, 0x3a, 0xe2, 0xc5, 0x6e,
+ 0x7e, 0x00, 0x1e, 0xbf, 0x03, 0x86, 0x4f, 0x96, 0x2a, 0x4f, 0x35, 0x88,
+ 0xea, 0x55, 0x61, 0xb9, 0x0f, 0xe3, 0x63, 0x63, 0x32, 0x87, 0x65, 0xfb,
+ 0xe0, 0x7d, 0x1a, 0xb1, 0x7b, 0x70, 0xe0, 0xb1, 0x7d, 0x3a, 0xef, 0xf8,
+ 0xb1, 0x5f, 0x3c, 0x80, 0x10, 0x5f, 0xba, 0x03, 0x67, 0xd6, 0x2f, 0xe0,
+ 0x98, 0x73, 0xd7, 0x16, 0x29, 0xcf, 0x64, 0x05, 0x37, 0xf7, 0xf0, 0x02,
+ 0xf7, 0x16, 0x2f, 0x4e, 0x7d, 0x62, 0x86, 0x79, 0x7e, 0x2f, 0xbe, 0xce,
+ 0xe9, 0xd2, 0xc5, 0xff, 0xff, 0xfd, 0x91, 0xf8, 0x3e, 0x48, 0xe7, 0xdf,
+ 0xc1, 0x6f, 0xf9, 0xe7, 0xf3, 0x8d, 0x27, 0x58, 0xbf, 0x7f, 0x21, 0x06,
+ 0x58, 0xbf, 0xfe, 0xcf, 0xef, 0xf7, 0x88, 0x98, 0x2f, 0x67, 0xd6, 0x2b,
+ 0x15, 0x52, 0xbb, 0x96, 0x9e, 0xd9, 0xb0, 0x88, 0xb8, 0x4b, 0xe8, 0x45,
+ 0xc7, 0x14, 0x5f, 0x7f, 0x93, 0xba, 0xc5, 0xf7, 0x9f, 0x22, 0x58, 0xb1,
+ 0xab, 0x15, 0x87, 0xb5, 0xd1, 0x23, 0x91, 0xdf, 0x40, 0xa7, 0x65, 0x8b,
+ 0x83, 0x02, 0xc5, 0x68, 0xde, 0x70, 0x8e, 0xf6, 0x3c, 0x4b, 0x17, 0xa4,
+ 0x8d, 0x58, 0xa9, 0x3d, 0xb1, 0x90, 0xf0, 0x76, 0x8c, 0x76, 0x31, 0xf3,
+ 0x0b, 0xfd, 0xa3, 0xcb, 0x81, 0x08, 0xe5, 0x7b, 0x65, 0x24, 0x1b, 0x78,
+ 0xfe, 0x1e, 0x50, 0x94, 0x52, 0xc4, 0xb5, 0x0e, 0x33, 0xc7, 0x9b, 0xf9,
+ 0xdd, 0x26, 0x94, 0x9a, 0x08, 0x40, 0x14, 0xf8, 0xa7, 0x23, 0x47, 0xf4,
+ 0xb6, 0x61, 0x4a, 0xf8, 0x0a, 0x1a, 0x21, 0xc3, 0x16, 0xff, 0xef, 0x73,
+ 0xf9, 0x11, 0x0b, 0xa8, 0x71, 0x62, 0x96, 0x2f, 0xfe, 0xc2, 0x06, 0x66,
+ 0xb9, 0xe9, 0xc5, 0x8b, 0xfe, 0xeb, 0xd9, 0xa7, 0xd9, 0x8e, 0xb1, 0x7b,
+ 0x3b, 0x62, 0xc5, 0x01, 0x13, 0x64, 0x85, 0xc3, 0xbb, 0xfa, 0x13, 0xd0,
+ 0x35, 0x2b, 0x15, 0x29, 0xa6, 0xc1, 0x23, 0x21, 0x4f, 0xd1, 0x7d, 0xee,
+ 0xfe, 0x0e, 0xb1, 0x7d, 0x24, 0xd0, 0x58, 0xbe, 0xe0, 0x7b, 0x4a, 0xc5,
+ 0xe6, 0x20, 0x18, 0x7d, 0x1a, 0x22, 0xe1, 0x0d, 0xfe, 0xfb, 0x40, 0xcd,
+ 0x6a, 0x56, 0x2a, 0x3c, 0xfd, 0x7e, 0x81, 0x7f, 0x86, 0x39, 0x87, 0xc3,
+ 0xe2, 0xc5, 0xff, 0x8b, 0xdc, 0xc1, 0x9b, 0xac, 0xe2, 0xc5, 0x62, 0x26,
+ 0xdc, 0x94, 0x46, 0xd7, 0x8e, 0xd1, 0x2c, 0x5f, 0xfa, 0x0c, 0x41, 0x30,
+ 0xe7, 0xae, 0x2c, 0x5f, 0xff, 0x98, 0xbb, 0x67, 0x50, 0x3c, 0xff, 0xd8,
+ 0xfd, 0x96, 0x2f, 0xe7, 0x3c, 0xfc, 0x31, 0xac, 0x5f, 0xf0, 0x7e, 0x72,
+ 0x14, 0x33, 0x8b, 0x15, 0x03, 0xe9, 0x72, 0xfb, 0xdc, 0x62, 0x58, 0xbf,
+ 0x7d, 0xe7, 0x5c, 0x58, 0xad, 0xd3, 0x85, 0x88, 0x7b, 0x48, 0x1f, 0x86,
+ 0x17, 0x08, 0x7b, 0x0e, 0x5f, 0xff, 0xa1, 0xc2, 0xcf, 0x71, 0xf0, 0xfe,
+ 0xd6, 0x04, 0xb1, 0x70, 0xa0, 0xb1, 0x7f, 0xce, 0x71, 0xe4, 0x53, 0x9a,
+ 0x58, 0xad, 0x8f, 0x47, 0xe3, 0x17, 0xa1, 0x3d, 0x2c, 0x5f, 0x84, 0x42,
+ 0x9e, 0x96, 0x2f, 0x1f, 0x3c, 0xb1, 0x7d, 0x20, 0x63, 0xac, 0x5a, 0x18,
+ 0x8a, 0x98, 0x88, 0xce, 0x3c, 0x02, 0x92, 0x1d, 0xae, 0x93, 0x9f, 0x28,
+ 0xd4, 0x2f, 0xe2, 0x29, 0xf8, 0xb4, 0xb1, 0x6d, 0xd6, 0x2e, 0xf4, 0xac,
+ 0x5f, 0x4f, 0xc5, 0xa5, 0x8b, 0x73, 0xbd, 0x3c, 0xd7, 0x13, 0x21, 0x7b,
+ 0xe8, 0x66, 0xd0, 0x58, 0xa9, 0x4c, 0x01, 0xca, 0x99, 0xe8, 0x8e, 0x2f,
+ 0xc5, 0x80, 0x17, 0x16, 0x2f, 0xf1, 0x84, 0xdb, 0x14, 0xf4, 0xb1, 0x7f,
+ 0xef, 0xbf, 0xbf, 0x8f, 0xe9, 0x02, 0xc5, 0xdb, 0xbe, 0x22, 0x6f, 0x45,
+ 0x1c, 0x35, 0xbb, 0x9e, 0x58, 0xbf, 0x0d, 0x8a, 0x40, 0xb1, 0x5b, 0x9b,
+ 0xf0, 0xc6, 0x2f, 0xee, 0x0d, 0xc1, 0x24, 0xb1, 0x7f, 0x37, 0x80, 0x19,
+ 0x41, 0x62, 0xb6, 0x3f, 0xfe, 0x88, 0xfe, 0x5b, 0x7f, 0xfe, 0x29, 0x3f,
+ 0x89, 0x81, 0xc2, 0xcf, 0x48, 0x4b, 0x17, 0xf8, 0x53, 0xdb, 0x3c, 0xfa,
+ 0x58, 0xbd, 0xf7, 0x89, 0x62, 0xff, 0xa7, 0x7c, 0x1c, 0xf5, 0x0e, 0x2c,
+ 0x5f, 0x8b, 0x39, 0x27, 0x58, 0xad, 0xd1, 0x00, 0x43, 0xdd, 0x8e, 0xef,
+ 0xff, 0xfb, 0x40, 0x00, 0xb9, 0xf7, 0xf4, 0x33, 0xec, 0x07, 0x1c, 0xac,
+ 0x5f, 0xf3, 0x6b, 0x3b, 0x67, 0x69, 0x1a, 0xc5, 0x62, 0x28, 0xc0, 0xcf,
+ 0x7f, 0xfd, 0x86, 0x9a, 0xe3, 0xfb, 0xc5, 0xf7, 0xeb, 0xcb, 0x14, 0x73,
+ 0xf6, 0x22, 0x2b, 0xfc, 0x67, 0xda, 0x04, 0xe1, 0x2c, 0x5f, 0xd2, 0x18,
+ 0xc6, 0xfb, 0xac, 0x54, 0xa7, 0xa3, 0x91, 0xa5, 0xb9, 0x08, 0x8d, 0x6e,
+ 0x16, 0x96, 0x2f, 0x6e, 0xda, 0x58, 0xbf, 0xf6, 0xd8, 0x47, 0xcf, 0x70,
+ 0x3e, 0x2c, 0x5f, 0x6f, 0x3a, 0x35, 0x62, 0xfb, 0x3e, 0xdd, 0x2c, 0x57,
+ 0x0f, 0x20, 0x32, 0x5b, 0xec, 0xde, 0x4e, 0xb1, 0x7f, 0x71, 0xf0, 0x22,
+ 0x1a, 0xc5, 0xb6, 0xf9, 0xe8, 0xf0, 0x8e, 0xfe, 0x70, 0x75, 0x0c, 0xf2,
+ 0xc5, 0x6c, 0x9c, 0x5f, 0xc6, 0x18, 0x78, 0x10, 0x89, 0x27, 0x4e, 0xc5,
+ 0x37, 0xfc, 0x19, 0x43, 0x3b, 0x16, 0x71, 0x62, 0xfb, 0x36, 0x14, 0x16,
+ 0x2f, 0xa1, 0xec, 0x02, 0xc5, 0xee, 0x3c, 0x4b, 0x15, 0x03, 0xe5, 0xe8,
+ 0x93, 0x84, 0x77, 0xee, 0x39, 0x75, 0x05, 0x8b, 0x62, 0xc5, 0xef, 0x8b,
+ 0x75, 0x8a, 0xc3, 0xd9, 0xdc, 0xa7, 0xc2, 0x37, 0xec, 0x71, 0xfd, 0xd6,
+ 0x2b, 0x63, 0xd6, 0x81, 0x7d, 0xfd, 0xce, 0x39, 0x75, 0x05, 0x8b, 0xb4,
+ 0x6a, 0xc5, 0x74, 0x79, 0x0c, 0x5f, 0x7f, 0xf3, 0x40, 0xce, 0x16, 0x7b,
+ 0x99, 0x1e, 0xb1, 0x52, 0x9d, 0xa6, 0x43, 0x7d, 0x9a, 0xc4, 0x45, 0x7f,
+ 0xee, 0xbd, 0xc7, 0x29, 0x03, 0x1d, 0x62, 0x96, 0x2b, 0x0f, 0x2f, 0xb1,
+ 0xfd, 0xc7, 0xfa, 0xc5, 0xef, 0x7b, 0xa5, 0x8a, 0x81, 0xb7, 0x00, 0xc5,
+ 0x6c, 0x7f, 0x7e, 0x5a, 0xbf, 0xd8, 0x77, 0xfc, 0x86, 0x75, 0x8b, 0xff,
+ 0xfe, 0xcf, 0x7d, 0x87, 0x18, 0x59, 0xd8, 0xb3, 0x9c, 0x7e, 0xbc, 0xb1,
+ 0x5a, 0x44, 0xfc, 0x71, 0xa5, 0xba, 0x58, 0xbe, 0xc3, 0xcc, 0x7a, 0xc5,
+ 0xba, 0xef, 0xcd, 0xc7, 0x04, 0xef, 0x1a, 0xe1, 0x2c, 0x5f, 0x82, 0x7c,
+ 0x23, 0x56, 0x29, 0xcf, 0x20, 0x43, 0xf7, 0xf8, 0x61, 0xe4, 0x5f, 0x63,
+ 0xac, 0x56, 0x27, 0xd8, 0xf0, 0xc2, 0x65, 0xe2, 0x75, 0x11, 0x0d, 0xf3,
+ 0x83, 0xa1, 0xac, 0x5e, 0x6e, 0xee, 0x2c, 0x56, 0xe7, 0x89, 0xf2, 0x4b,
+ 0xff, 0x67, 0x5e, 0x0b, 0x08, 0x7f, 0x95, 0x8b, 0x36, 0xe7, 0xc7, 0xa2,
+ 0x3b, 0x62, 0xc5, 0xf6, 0xb6, 0x7d, 0x96, 0x2f, 0x7d, 0xf4, 0xb1, 0x66,
+ 0x73, 0xc2, 0x88, 0x96, 0x8c, 0x3f, 0xaf, 0xa9, 0xdd, 0x9e, 0x58, 0xbc,
+ 0x52, 0x75, 0x8a, 0x93, 0x67, 0xc1, 0x7b, 0xfd, 0x3c, 0xc7, 0xec, 0xc7,
+ 0x58, 0xbf, 0xf1, 0x30, 0x5a, 0x97, 0x83, 0x71, 0x62, 0xb6, 0x3f, 0x28,
+ 0x8d, 0x2f, 0x77, 0xf8, 0x4b, 0x17, 0xbb, 0x61, 0x2c, 0x54, 0xa6, 0x97,
+ 0xd2, 0xb3, 0x42, 0x48, 0x89, 0x3c, 0x43, 0x7b, 0xf0, 0x3a, 0xc5, 0xdf,
+ 0x75, 0x8a, 0xc3, 0x6b, 0xe1, 0xea, 0x96, 0xd8, 0xe6, 0x11, 0xdd, 0x64,
+ 0x76, 0x66, 0xcb, 0x00, 0xea, 0x1a, 0xaf, 0x0f, 0x98, 0x8c, 0x74, 0xa9,
+ 0xf9, 0x50, 0xcd, 0x1e, 0x60, 0x17, 0x8a, 0x52, 0xa7, 0x25, 0x79, 0x7a,
+ 0x1e, 0x62, 0x8f, 0xb6, 0x3a, 0x10, 0x77, 0xda, 0x79, 0xe9, 0x62, 0xf7,
+ 0xf3, 0x75, 0x8b, 0xc7, 0x7e, 0x2c, 0x56, 0x1b, 0xbd, 0x0f, 0x5f, 0x75,
+ 0xc1, 0x1d, 0x62, 0xe0, 0x3a, 0xc5, 0xd3, 0x13, 0x9b, 0xc6, 0x25, 0xbd,
+ 0xdb, 0x06, 0xb1, 0x73, 0x84, 0xb1, 0x6d, 0xd6, 0x2b, 0x0d, 0x59, 0xc6,
+ 0x2f, 0xe1, 0x75, 0xcf, 0xbc, 0x7a, 0xc5, 0xf8, 0xd3, 0x5f, 0x50, 0x58,
+ 0xb8, 0xd9, 0x58, 0xb4, 0x16, 0x2f, 0xf4, 0xfd, 0xbc, 0x21, 0x74, 0xb1,
+ 0x4e, 0x7b, 0xfc, 0x18, 0x10, 0x95, 0xe6, 0xea, 0x0b, 0x17, 0xe0, 0xfe,
+ 0xfd, 0x71, 0x62, 0xff, 0x14, 0x9d, 0x8b, 0xa8, 0x2c, 0x57, 0x7a, 0xaa,
+ 0xda, 0x57, 0xb6, 0x5c, 0x81, 0x58, 0xd2, 0xa3, 0xc8, 0x34, 0x66, 0x50,
+ 0x8a, 0xf1, 0x70, 0x87, 0x83, 0x2b, 0xbf, 0xbc, 0xe4, 0xe0, 0xe2, 0xc5,
+ 0xfd, 0xcc, 0x18, 0x1b, 0xcb, 0x17, 0x73, 0x8b, 0x17, 0xc3, 0x2c, 0xfa,
+ 0xc5, 0x86, 0x62, 0x25, 0x62, 0x2d, 0xd1, 0x70, 0x63, 0x17, 0xda, 0x92,
+ 0xdd, 0x62, 0xfb, 0x09, 0xc6, 0xb1, 0x7d, 0xa6, 0x23, 0x56, 0x2f, 0x3b,
+ 0x76, 0x58, 0xbb, 0x5b, 0x2c, 0x5d, 0x9c, 0x19, 0xb7, 0x10, 0xf5, 0xff,
+ 0xff, 0xff, 0x74, 0x0d, 0x6f, 0xc8, 0xfe, 0xcf, 0x1a, 0x1a, 0x1f, 0x79,
+ 0xc8, 0x77, 0xde, 0xbb, 0xe1, 0x80, 0x8f, 0x30, 0xcf, 0xc7, 0x2c, 0x56,
+ 0x27, 0xa8, 0xe8, 0xdf, 0x23, 0x62, 0x12, 0x5a, 0x0c, 0xb2, 0xfc, 0x71,
+ 0x7c, 0x3d, 0x96, 0x2e, 0x6f, 0x2c, 0x56, 0x8f, 0x0c, 0xe5, 0x97, 0x43,
+ 0xcb, 0x17, 0xde, 0x6e, 0xb8, 0xb1, 0x7e, 0x1b, 0xf6, 0x91, 0xac, 0x56,
+ 0xc7, 0x9d, 0xb9, 0x25, 0xbe, 0xb1, 0x60, 0x2c, 0x5c, 0xdd, 0xfa, 0xc5,
+ 0xdc, 0x82, 0xc5, 0x4a, 0x60, 0x83, 0x22, 0x66, 0x60, 0x12, 0x70, 0x4b,
+ 0xc2, 0x42, 0x1c, 0xbf, 0xb6, 0x8a, 0x11, 0xb6, 0xb6, 0x58, 0xba, 0x00,
+ 0x58, 0xbc, 0xd9, 0xa5, 0x8b, 0xc5, 0x9e, 0x58, 0xbd, 0xfc, 0x3a, 0xc5,
+ 0x74, 0x7d, 0xbf, 0x18, 0x21, 0xcf, 0x0e, 0x5d, 0xe2, 0x58, 0xbd, 0x3d,
+ 0x71, 0x62, 0xf9, 0xca, 0x18, 0xb1, 0x70, 0x7f, 0x58, 0xbd, 0xb3, 0x12,
+ 0xc5, 0xda, 0xd9, 0x62, 0x86, 0x88, 0xe3, 0x8f, 0x7c, 0x87, 0xc3, 0x22,
+ 0x1d, 0xbb, 0x5f, 0x58, 0xbe, 0x91, 0xb4, 0x16, 0x2f, 0xd9, 0xef, 0xbf,
+ 0x96, 0x2f, 0xcd, 0xd6, 0x75, 0xe5, 0x8a, 0xf9, 0xe9, 0x78, 0xa2, 0xf3,
+ 0x6a, 0x0b, 0x17, 0xbf, 0x87, 0x58, 0xa8, 0x1b, 0xaf, 0x0e, 0xdf, 0xf1,
+ 0xb1, 0x66, 0x6f, 0xe9, 0x35, 0x62, 0xfe, 0x6d, 0x67, 0xe4, 0x0b, 0x17,
+ 0x3f, 0x16, 0x2e, 0x2d, 0x96, 0x2b, 0x73, 0x5e, 0x21, 0x7b, 0xc1, 0xfd,
+ 0x96, 0x28, 0xc4, 0xf8, 0xb6, 0x18, 0x35, 0xd3, 0xa5, 0xcd, 0x10, 0x9c,
+ 0xf7, 0xeb, 0x9c, 0x22, 0xbe, 0x3c, 0x74, 0x78, 0xd6, 0x2d, 0xb2, 0xc5,
+ 0xdf, 0xc5, 0x8a, 0x58, 0xad, 0xcd, 0x1e, 0x85, 0xeb, 0x63, 0xd8, 0x73,
+ 0x6b, 0xed, 0x99, 0xbe, 0xb1, 0x7e, 0x16, 0xcc, 0xdf, 0x58, 0xbd, 0xb3,
+ 0x6c, 0xb1, 0x7e, 0xc1, 0x81, 0xbc, 0xb1, 0x46, 0x22, 0x4f, 0xe4, 0x6c,
+ 0x53, 0xd8, 0x7e, 0xfc, 0x1c, 0x05, 0x3c, 0x58, 0xbc, 0x00, 0xfe, 0xb1,
+ 0x7b, 0xcc, 0x35, 0x8a, 0xd9, 0x14, 0xa6, 0x9f, 0xf4, 0x54, 0x43, 0xf7,
+ 0xe1, 0xbf, 0x69, 0x1a, 0xc5, 0xbc, 0xb1, 0x74, 0x76, 0xeb, 0x17, 0xe7,
+ 0x2d, 0x83, 0xe9, 0x62, 0xf8, 0xa7, 0xae, 0x2c, 0x58, 0x21, 0x9e, 0x76,
+ 0x15, 0xd4, 0x11, 0x9d, 0xd1, 0x56, 0x84, 0x99, 0xaa, 0xfb, 0x3b, 0x60,
+ 0xd6, 0x2f, 0xe1, 0x36, 0xa0, 0xc0, 0x58, 0xbf, 0xe2, 0xcd, 0x6a, 0x77,
+ 0x0c, 0xeb, 0x17, 0xc7, 0x6e, 0xa3, 0x06, 0x7d, 0x21, 0x97, 0x59, 0x96,
+ 0x2e, 0x7d, 0x61, 0xe7, 0xf0, 0xfa, 0xfd, 0x17, 0xdf, 0xaf, 0x2c, 0x56,
+ 0x93, 0x33, 0xfc, 0x37, 0x3c, 0x59, 0x7e, 0xc2, 0x1f, 0xe5, 0x62, 0xa3,
+ 0x76, 0x46, 0xf4, 0xc2, 0x96, 0x07, 0x99, 0x0a, 0x57, 0x94, 0x58, 0x77,
+ 0x6f, 0xc2, 0x09, 0xa3, 0x5a, 0x28, 0xc3, 0x45, 0x1b, 0x80, 0x46, 0xd7,
+ 0xdd, 0xe7, 0xe7, 0xb2, 0xc5, 0xff, 0x60, 0xc6, 0xfd, 0x67, 0x5e, 0x58,
+ 0xbe, 0xdc, 0xa6, 0x0b, 0x15, 0xf3, 0xde, 0x63, 0xbb, 0xfd, 0x39, 0xe9,
+ 0xfb, 0x0d, 0x62, 0xee, 0x47, 0xac, 0x5c, 0xdd, 0x96, 0x2d, 0xd9, 0x62,
+ 0x9c, 0xd6, 0xb0, 0xcd, 0xef, 0xb9, 0xd6, 0x2e, 0xce, 0x2c, 0x50, 0xcf,
+ 0x4f, 0x07, 0xe3, 0x87, 0x6f, 0xfb, 0x3d, 0x3b, 0x87, 0x20, 0xc5, 0x8b,
+ 0xd3, 0xd4, 0x16, 0x2b, 0x64, 0xdd, 0xc6, 0x43, 0xa3, 0x20, 0x42, 0x6c,
+ 0x23, 0x1e, 0xe3, 0xab, 0xec, 0xc2, 0xf2, 0xc5, 0xff, 0xee, 0xce, 0x40,
+ 0xfb, 0xb4, 0x3c, 0xfb, 0x2c, 0x5f, 0x09, 0xb5, 0x05, 0x8b, 0xfe, 0xcd,
+ 0xe7, 0x76, 0xd6, 0xd2, 0xb1, 0x52, 0x8a, 0xa1, 0xa6, 0x7c, 0x8e, 0xff,
+ 0xd2, 0x3d, 0x4f, 0x9f, 0x77, 0x1a, 0xc5, 0xf7, 0xb8, 0xdb, 0xac, 0x50,
+ 0xcf, 0x8c, 0x47, 0xf7, 0xc2, 0x6d, 0x41, 0x62, 0xf4, 0xf7, 0x41, 0x62,
+ 0xf4, 0x70, 0xba, 0x58, 0xbe, 0x9c, 0xea, 0x0b, 0x14, 0x34, 0x44, 0x44,
+ 0x47, 0xa2, 0x0e, 0xe2, 0x2b, 0xfb, 0xdb, 0x8c, 0x67, 0xd2, 0xc5, 0xff,
+ 0xf3, 0x71, 0xb4, 0xfd, 0x03, 0xd0, 0x98, 0xec, 0x58, 0xbe, 0x72, 0x90,
+ 0x2c, 0x50, 0x0f, 0xd3, 0xca, 0x77, 0xfd, 0x17, 0x3b, 0x31, 0x6c, 0x21,
+ 0xac, 0x5f, 0xcc, 0x10, 0x00, 0x78, 0xe5, 0x8b, 0xec, 0xf6, 0x1d, 0x62,
+ 0xe2, 0x35, 0x62, 0x98, 0xdd, 0x08, 0x8a, 0xa0, 0x88, 0xde, 0x36, 0xdf,
+ 0xa0, 0x42, 0x6e, 0x2c, 0x5f, 0xfa, 0x48, 0x5e, 0x80, 0x8b, 0xdc, 0x58,
+ 0xac, 0x3e, 0x7d, 0x14, 0x5f, 0xff, 0x87, 0x30, 0x9c, 0x87, 0xe4, 0x65,
+ 0x3e, 0xe2, 0xc5, 0xff, 0x4f, 0xa1, 0x91, 0xec, 0x40, 0x58, 0xbf, 0x73,
+ 0x21, 0x09, 0x58, 0xac, 0x45, 0xb9, 0x2a, 0x70, 0xee, 0xf0, 0x1c, 0x0b,
+ 0x17, 0xdb, 0x45, 0xf7, 0x58, 0xb7, 0xf0, 0xf0, 0x84, 0x3b, 0x7f, 0xf4,
+ 0x09, 0xb8, 0xdf, 0xea, 0x19, 0xe5, 0x8b, 0x98, 0xeb, 0x15, 0x87, 0xb9,
+ 0xba, 0x2d, 0xff, 0x89, 0x8d, 0xfb, 0x43, 0x8e, 0x35, 0x8b, 0xf7, 0xdc,
+ 0x9b, 0x65, 0x8b, 0x6e, 0xb1, 0x7c, 0x28, 0x67, 0x37, 0x37, 0x64, 0x51,
+ 0x47, 0x45, 0x91, 0x3d, 0x5d, 0xda, 0x56, 0x2f, 0xff, 0xed, 0x9f, 0x44,
+ 0xc6, 0xf3, 0xf2, 0xdd, 0x48, 0xdd, 0x62, 0xec, 0xf2, 0xc5, 0x4a, 0x23,
+ 0x30, 0x64, 0x97, 0x2e, 0x0c, 0xeb, 0x14, 0xe8, 0xf4, 0x28, 0x57, 0x78,
+ 0xb6, 0xff, 0x0f, 0x39, 0xcc, 0xd6, 0xcb, 0x16, 0x1a, 0xc5, 0x6e, 0x78,
+ 0xfd, 0x1a, 0xdd, 0xd9, 0x96, 0x2f, 0xed, 0x4e, 0xf9, 0xdb, 0x16, 0x2f,
+ 0xf1, 0x03, 0x5a, 0x78, 0xb8, 0xb1, 0x52, 0x7c, 0xac, 0x61, 0x7a, 0x7b,
+ 0xa5, 0x62, 0xbb, 0xc6, 0x5d, 0x9c, 0xc7, 0xff, 0xb3, 0x14, 0x21, 0x96,
+ 0x38, 0x49, 0x64, 0x2a, 0x8d, 0x41, 0xea, 0x14, 0xae, 0x45, 0x14, 0x32,
+ 0xf5, 0x08, 0xa3, 0xc3, 0x63, 0xee, 0x05, 0x08, 0x3f, 0x47, 0x90, 0x27,
+ 0xae, 0xc4, 0x91, 0xcf, 0xdd, 0xc4, 0x17, 0xe8, 0xa7, 0xc5, 0xd9, 0x62,
+ 0xfa, 0x2c, 0x70, 0x2c, 0x51, 0x87, 0x9d, 0x25, 0x77, 0xff, 0x4f, 0x6d,
+ 0x4e, 0xb1, 0xff, 0x23, 0x58, 0xba, 0x71, 0x62, 0x88, 0xf6, 0xf8, 0x8b,
+ 0x7c, 0x7e, 0xf2, 0x35, 0xc6, 0xcb, 0x17, 0x31, 0xd6, 0x2e, 0x8a, 0x39,
+ 0x62, 0x88, 0xd9, 0xf6, 0x17, 0xbf, 0xf7, 0xdf, 0x45, 0x9d, 0xb4, 0xfc,
+ 0x58, 0xbf, 0xa7, 0xcd, 0x13, 0x79, 0x62, 0xc3, 0x58, 0xbf, 0xfd, 0xd4,
+ 0x38, 0x67, 0xf3, 0xdc, 0x26, 0xf2, 0xc5, 0x68, 0xf7, 0xce, 0x25, 0x7f,
+ 0xa4, 0x2e, 0x68, 0x52, 0x05, 0x8a, 0x73, 0xd7, 0x22, 0x2b, 0x85, 0xe5,
+ 0x8b, 0x0d, 0x62, 0xf8, 0xbd, 0x80, 0x58, 0xad, 0x1b, 0x41, 0x09, 0x54,
+ 0x15, 0x6c, 0x63, 0xef, 0x44, 0x2e, 0xcf, 0x11, 0x11, 0xd0, 0x3d, 0x0e,
+ 0x48, 0xe2, 0x0e, 0xe4, 0xcb, 0x46, 0x46, 0xf1, 0xae, 0xfb, 0xf7, 0x91,
+ 0x86, 0x77, 0xb1, 0x94, 0xc6, 0x91, 0x99, 0x46, 0xd1, 0xec, 0x77, 0xdc,
+ 0x2e, 0xbb, 0xe4, 0x60, 0xdd, 0xf5, 0x8d, 0x2e, 0x35, 0x42, 0x3a, 0x35,
+ 0xb8, 0xcd, 0x63, 0x8d, 0xb4, 0xe4, 0xc4, 0x27, 0xd0, 0xc7, 0x4e, 0x98,
+ 0xcb, 0x4f, 0x76, 0x6c, 0xe6, 0xee, 0xf4, 0xc1, 0x3e, 0xa7, 0xc7, 0xde,
+ 0x91, 0x2f, 0x1f, 0x1b, 0x4c, 0x54, 0xce, 0x9d, 0x52, 0xa9, 0x4f, 0x3f,
+ 0x95, 0xfb, 0x42, 0x02, 0xd4, 0xd2, 0x40, 0x52, 0x19, 0x7b, 0xf8, 0xdb,
+ 0xca, 0xb8, 0xd6, 0xe5, 0xb2, 0x3e, 0xf5, 0x72, 0x1c, 0x29, 0x7b, 0xbd,
+ 0xa5, 0x88, 0x05, 0x1c, 0xe4, 0x75, 0x25, 0x04, 0x3a, 0x63, 0xc7, 0x74,
+ 0xe3, 0x5d, 0xfa, 0x31, 0xf4, 0xda, 0x58, 0xa8, 0xc8, 0xd8, 0xd8, 0x76,
+ 0x56, 0x72, 0xb8, 0x92, 0xbf, 0x9a, 0xf9, 0x10, 0x25, 0xa4, 0xdf, 0xfe,
+ 0x8c, 0x3b, 0x42, 0x33, 0x35, 0xbb, 0x36, 0xea, 0x91, 0xb0, 0xbf, 0x6b,
+ 0x76, 0x6d, 0xd5, 0x25, 0x69, 0x70, 0x3b, 0x2c, 0x5d, 0xc8, 0xe5, 0x8b,
+ 0x46, 0x61, 0xf6, 0x7c, 0xdf, 0x83, 0x57, 0x76, 0xd2, 0xc5, 0xcd, 0x2b,
+ 0x17, 0xfa, 0x10, 0x17, 0x8a, 0x60, 0xb1, 0x7d, 0x9f, 0x6f, 0x2c, 0x56,
+ 0x1e, 0xb1, 0x1a, 0x5f, 0xf8, 0x1f, 0x68, 0x3c, 0x3e, 0xfd, 0x96, 0x2b,
+ 0xbd, 0x3e, 0x1e, 0x10, 0x5f, 0xff, 0xee, 0xd2, 0xfa, 0xdd, 0xce, 0xd0,
+ 0x72, 0xc1, 0xe1, 0xab, 0x17, 0xfe, 0x26, 0x7e, 0xe7, 0x2d, 0xa4, 0xd5,
+ 0x8b, 0x42, 0x51, 0x46, 0xcc, 0x57, 0xf8, 0xa5, 0xbd, 0xc7, 0x25, 0x8b,
+ 0xff, 0x38, 0x31, 0x9f, 0x5b, 0xcf, 0x96, 0x2f, 0x87, 0xf9, 0xd9, 0x62,
+ 0xb0, 0xf8, 0x9c, 0xfa, 0xf7, 0x31, 0xd6, 0x2f, 0xfb, 0x22, 0xcc, 0xe6,
+ 0xcd, 0x1e, 0xb1, 0x67, 0x58, 0xbb, 0xce, 0x61, 0xf5, 0x10, 0xe7, 0x63,
+ 0xdb, 0xff, 0x43, 0x21, 0x8d, 0x02, 0x93, 0xac, 0x54, 0x9f, 0xcb, 0x9e,
+ 0x5f, 0xf3, 0x7d, 0xa1, 0x9b, 0x60, 0x4b, 0x15, 0xa3, 0xda, 0x39, 0x05,
+ 0xfd, 0x9b, 0xc8, 0x03, 0x3a, 0xc5, 0xf6, 0xd9, 0xf7, 0x58, 0xad, 0x1e,
+ 0x98, 0x8c, 0x2f, 0xc5, 0x26, 0xfd, 0x96, 0x2f, 0xf7, 0x1b, 0xd1, 0x9c,
+ 0x29, 0x58, 0xbf, 0xa7, 0x6d, 0x4e, 0x0d, 0x62, 0xa0, 0x7c, 0x9f, 0x36,
+ 0xbf, 0xff, 0x4e, 0xd3, 0xa9, 0x3c, 0xcf, 0xbe, 0xe0, 0x3a, 0xc5, 0x49,
+ 0xfb, 0xfc, 0x8a, 0xff, 0x61, 0xdf, 0x5b, 0x08, 0x0b, 0x17, 0xff, 0xce,
+ 0x5b, 0x67, 0xc4, 0x6e, 0x00, 0xec, 0x05, 0x8b, 0xf3, 0x0b, 0xf3, 0xa5,
+ 0x8b, 0xf3, 0xf6, 0x72, 0x9d, 0x1f, 0xcf, 0x65, 0x1b, 0xff, 0xff, 0xec,
+ 0x16, 0xf8, 0x3f, 0xc9, 0x6f, 0x3a, 0xcc, 0xea, 0x05, 0x27, 0xcd, 0x2c,
+ 0x56, 0x22, 0xf4, 0x90, 0x2e, 0x78, 0xe5, 0x8b, 0xd2, 0x38, 0x96, 0x2f,
+ 0x76, 0x14, 0x16, 0x2a, 0x0b, 0xb6, 0xd8, 0x4f, 0xbc, 0x24, 0xde, 0x35,
+ 0xdd, 0x3a, 0x9c, 0x8b, 0xf1, 0x81, 0x80, 0x84, 0xa3, 0x6b, 0xe1, 0x0f,
+ 0x86, 0xbb, 0x0f, 0x5f, 0x8a, 0x45, 0xdf, 0xf1, 0x62, 0xef, 0x8d, 0x62,
+ 0xda, 0xc3, 0xc5, 0x39, 0x6d, 0xff, 0xda, 0x81, 0x67, 0xb9, 0x27, 0xf6,
+ 0xeb, 0x15, 0x27, 0xda, 0x22, 0x7b, 0xb0, 0x96, 0x2e, 0xff, 0x16, 0x2d,
+ 0xd2, 0xc5, 0xfc, 0x6c, 0x70, 0xbe, 0xfa, 0x58, 0xac, 0x3c, 0x67, 0x13,
+ 0xac, 0x3f, 0xe8, 0xe5, 0xea, 0x1a, 0x2e, 0x32, 0x12, 0x97, 0xfe, 0xe4,
+ 0xfb, 0xec, 0x73, 0xef, 0xba, 0xc5, 0xff, 0x99, 0xfb, 0xa7, 0xfe, 0x2c,
+ 0x82, 0xc5, 0xfa, 0x0f, 0xbb, 0x69, 0x62, 0xa0, 0x8a, 0xbf, 0xa1, 0x71,
+ 0x02, 0xf6, 0xee, 0x12, 0xc5, 0xcd, 0xba, 0xa4, 0xb4, 0x2b, 0x73, 0xc4,
+ 0x61, 0xfb, 0xf1, 0xbd, 0x70, 0x5d, 0x2c, 0x54, 0xa3, 0x0f, 0x77, 0x47,
+ 0x22, 0xbf, 0x84, 0xe6, 0xea, 0x46, 0xb1, 0x7f, 0x68, 0x01, 0xf2, 0x71,
+ 0x62, 0xf4, 0x97, 0x96, 0x2f, 0xff, 0xdc, 0xe6, 0x7d, 0xf8, 0x2d, 0x99,
+ 0xcf, 0xa7, 0x58, 0xbb, 0x5f, 0x73, 0xf2, 0x61, 0xca, 0x94, 0x66, 0xbc,
+ 0x28, 0x6f, 0xff, 0xdc, 0xe6, 0x7f, 0x36, 0xcd, 0x34, 0x20, 0xd0, 0x58,
+ 0xbf, 0xc7, 0xe3, 0xe7, 0x66, 0xd2, 0xc5, 0x62, 0x22, 0xd9, 0x5a, 0xfd,
+ 0xa1, 0x01, 0xc6, 0xb1, 0x7f, 0x0c, 0x79, 0x80, 0xe2, 0xc5, 0xfd, 0x20,
+ 0xf7, 0x05, 0x1e, 0xb1, 0x52, 0x7c, 0x1c, 0x2e, 0xbf, 0xfc, 0xfe, 0x84,
+ 0xef, 0xf7, 0xf7, 0x1b, 0xa5, 0x8a, 0xd2, 0xaf, 0x33, 0x97, 0xfe, 0x1f,
+ 0x85, 0x0b, 0x1e, 0x10, 0xfa, 0x11, 0x3d, 0x88, 0x6f, 0xe0, 0x19, 0x9a,
+ 0x73, 0x56, 0x2f, 0xfb, 0x06, 0xfc, 0x88, 0xa4, 0x6b, 0x14, 0x33, 0xe9,
+ 0x63, 0x0b, 0xfb, 0x69, 0xd6, 0xa4, 0x25, 0x8b, 0xfe, 0x9d, 0xf0, 0xf8,
+ 0x5e, 0x8e, 0x58, 0xbf, 0xdf, 0x9d, 0x03, 0xd9, 0xb2, 0xc5, 0xfe, 0x2c,
+ 0x81, 0x8f, 0xf8, 0x2c, 0x59, 0xce, 0x8a, 0x5f, 0x9e, 0x78, 0xd6, 0xa5,
+ 0x30, 0xaf, 0xc3, 0x56, 0xff, 0xe6, 0x81, 0x9a, 0x9f, 0x3e, 0xee, 0x35,
+ 0x8b, 0xf4, 0x96, 0xc4, 0x6a, 0xc5, 0xa0, 0xb1, 0x68, 0x4a, 0x20, 0x60,
+ 0x8d, 0xd1, 0x4d, 0xec, 0x3b, 0xac, 0x5f, 0xff, 0x37, 0x77, 0xf3, 0x45,
+ 0x30, 0x72, 0x10, 0x6b, 0x17, 0x85, 0xcf, 0x2c, 0x5f, 0xff, 0xa0, 0xc4,
+ 0xfe, 0x9f, 0xef, 0x83, 0x29, 0xe2, 0xc5, 0xff, 0xf9, 0xfb, 0xa4, 0x85,
+ 0x07, 0xe7, 0x24, 0xc3, 0xee, 0xb1, 0x4e, 0x8a, 0xe6, 0x54, 0xbf, 0xfe,
+ 0xde, 0x75, 0x80, 0x63, 0xb4, 0x25, 0xf7, 0x58, 0xbf, 0x3f, 0x77, 0xf0,
+ 0xeb, 0x17, 0xff, 0xd0, 0xe6, 0x14, 0x9d, 0xb3, 0xde, 0x93, 0xac, 0x5b,
+ 0xd2, 0x8c, 0x9c, 0x50, 0x62, 0xba, 0x1a, 0xa5, 0x7d, 0x0e, 0x1d, 0x4b,
+ 0xf0, 0xcc, 0xf4, 0x3a, 0xaf, 0xfb, 0xef, 0xaf, 0x37, 0xd8, 0x6b, 0x17,
+ 0xfd, 0x06, 0xe7, 0xb9, 0x82, 0xef, 0xd6, 0x2f, 0xff, 0xfc, 0xfe, 0xe6,
+ 0x1b, 0xbf, 0xdf, 0xd9, 0x11, 0x49, 0xf6, 0xc0, 0x96, 0x29, 0xd1, 0x5f,
+ 0xd8, 0xfe, 0xf6, 0xc2, 0xee, 0x58, 0xbe, 0x81, 0x37, 0x96, 0x2f, 0xff,
+ 0xbc, 0xd9, 0xc1, 0xe4, 0x3f, 0x3d, 0x87, 0x2b, 0x17, 0xff, 0xff, 0xf3,
+ 0xf8, 0x78, 0x2e, 0x19, 0xfc, 0xdf, 0xe2, 0xd9, 0xf0, 0xba, 0x87, 0x38,
+ 0x29, 0x58, 0xa6, 0x46, 0xf1, 0x28, 0xd4, 0xa6, 0xcf, 0x84, 0x9d, 0x11,
+ 0x34, 0x60, 0x17, 0xf7, 0x9b, 0xe6, 0x0e, 0x56, 0x2f, 0x80, 0x1f, 0xa5,
+ 0x62, 0xd1, 0x2c, 0x5a, 0x0e, 0x6d, 0xc4, 0x49, 0x52, 0x88, 0xc6, 0x66,
+ 0xbe, 0x87, 0x9f, 0x65, 0x8b, 0xf7, 0x38, 0xc5, 0xb2, 0xc5, 0xf8, 0x3f,
+ 0x14, 0x81, 0x62, 0xdf, 0x58, 0xae, 0x91, 0x10, 0x72, 0x4e, 0xc5, 0x21,
+ 0x94, 0xdf, 0xff, 0x01, 0xb3, 0xec, 0xfd, 0xd2, 0x72, 0x63, 0x56, 0x2f,
+ 0xfc, 0xfc, 0xc1, 0xf5, 0xc9, 0xd7, 0x16, 0x2f, 0xf3, 0x43, 0xcf, 0xb7,
+ 0xdd, 0x62, 0xf1, 0x48, 0x16, 0x2f, 0xf4, 0x9e, 0x63, 0x02, 0x08, 0x25,
+ 0x8a, 0x81, 0xeb, 0x77, 0x0e, 0x5f, 0xfd, 0x19, 0x20, 0x78, 0x67, 0x8a,
+ 0x40, 0xb1, 0x52, 0x9e, 0x3e, 0x20, 0xee, 0xa2, 0xe8, 0x0d, 0x08, 0xaf,
+ 0x12, 0xdf, 0xb3, 0xef, 0x87, 0x58, 0xb8, 0x80, 0xb1, 0x7c, 0x03, 0xbe,
+ 0x96, 0x2a, 0x4d, 0xd3, 0x8b, 0xdf, 0xf8, 0x6f, 0xd9, 0xc7, 0x81, 0x67,
+ 0xd6, 0x2f, 0xfc, 0x43, 0x63, 0xb4, 0x25, 0xf7, 0x58, 0xbd, 0x87, 0x95,
+ 0x8a, 0x93, 0xda, 0xc3, 0xeb, 0xfe, 0x17, 0xb9, 0x90, 0x7d, 0x4a, 0xc5,
+ 0xff, 0xff, 0x37, 0xa4, 0x9b, 0x69, 0xd4, 0xbc, 0x24, 0xe5, 0x26, 0xac,
+ 0x5f, 0xe7, 0xe3, 0x8b, 0xbf, 0x1c, 0xac, 0x50, 0xd1, 0xaa, 0x47, 0x3e,
+ 0x64, 0xbf, 0xbf, 0x3b, 0x93, 0x1d, 0x62, 0xff, 0xff, 0x1b, 0x9a, 0xcf,
+ 0x18, 0xe3, 0x31, 0x8b, 0x0e, 0x2f, 0xac, 0x5f, 0xf9, 0x9f, 0x7f, 0xb0,
+ 0xb6, 0xd3, 0xac, 0x53, 0xa3, 0x45, 0x8b, 0x89, 0x8e, 0xf6, 0xe2, 0x95,
+ 0x8b, 0xfd, 0xb4, 0xe1, 0x0f, 0xf2, 0xb1, 0x6c, 0x73, 0xd1, 0x61, 0xea,
+ 0xd9, 0x5d, 0x98, 0xd8, 0x70, 0x7f, 0x78, 0x4d, 0xbc, 0x3d, 0x7f, 0x18,
+ 0x01, 0x3f, 0x5f, 0xb3, 0xa0, 0x98, 0x25, 0x8b, 0xff, 0xba, 0xe7, 0xe7,
+ 0x99, 0xe2, 0x63, 0x56, 0x2e, 0x7c, 0x58, 0xad, 0x22, 0x1d, 0x8a, 0xf8,
+ 0x8d, 0x7f, 0xa1, 0x3a, 0xda, 0x75, 0xb2, 0xc5, 0xf4, 0x35, 0x87, 0x58,
+ 0xbd, 0x9a, 0x02, 0xc5, 0xfa, 0x2c, 0x19, 0xe3, 0xd6, 0x2f, 0xf1, 0xe7,
+ 0xad, 0x4f, 0x5e, 0x58, 0xbf, 0x71, 0xf0, 0x80, 0xb1, 0x7f, 0xf9, 0xc8,
+ 0x20, 0xc0, 0xd0, 0x21, 0x30, 0x6b, 0x17, 0xa7, 0x51, 0x2c, 0x5f, 0xc5,
+ 0x21, 0x75, 0x0e, 0x2c, 0x57, 0x49, 0xb2, 0x39, 0x1c, 0x43, 0xa7, 0x2d,
+ 0xe1, 0xb7, 0x89, 0xfb, 0x26, 0x77, 0x0f, 0x5e, 0x34, 0x5b, 0xac, 0x5d,
+ 0x9c, 0x58, 0xa9, 0x54, 0x93, 0x91, 0xcd, 0x1a, 0xf0, 0x19, 0x05, 0xff,
+ 0xff, 0xf9, 0xf7, 0xcf, 0x49, 0x7b, 0x86, 0x4b, 0x8f, 0x0e, 0x66, 0xa5,
+ 0xe0, 0xdc, 0x58, 0xbf, 0xfc, 0xcf, 0xe1, 0x69, 0xb8, 0x1e, 0x16, 0xeb,
+ 0x17, 0xe9, 0x87, 0xe7, 0x65, 0x8b, 0xff, 0xf8, 0xde, 0x7e, 0x4b, 0xc3,
+ 0xfc, 0xf0, 0x84, 0xde, 0x58, 0xa8, 0x22, 0x17, 0x0a, 0x6f, 0xfe, 0xc2,
+ 0x18, 0xe7, 0xf9, 0x85, 0xba, 0xc5, 0xff, 0xf6, 0x81, 0xc0, 0x7d, 0xa0,
+ 0xfe, 0x29, 0x02, 0xc5, 0x62, 0xa0, 0x8f, 0xc2, 0x0c, 0xa1, 0xa1, 0xc2,
+ 0x21, 0x21, 0xdf, 0xd9, 0xe6, 0x20, 0x09, 0x62, 0xfe, 0xf9, 0x8f, 0xb3,
+ 0x12, 0xc5, 0xfc, 0x7e, 0x0c, 0x98, 0x25, 0x8b, 0xf0, 0x39, 0x1a, 0xa3,
0x54, 0x6a, 0x58, 0xa9, 0x3e, 0xb6, 0x2f, 0xbe, 0x71, 0xe1, 0x2c, 0x5f,
- 0xc5, 0x9e, 0xf6, 0x6c, 0xb1, 0x5b, 0x9e, 0x7f, 0x88, 0x6f, 0xb4, 0xf2,
- 0x75, 0x8b, 0x98, 0x6b, 0x15, 0xd9, 0xb9, 0x01, 0x15, 0x61, 0xff, 0x32,
- 0xe5, 0xfe, 0x6f, 0x3f, 0x9c, 0x1c, 0x58, 0xa8, 0x2a, 0x08, 0xc2, 0xd2,
- 0x84, 0xdf, 0x21, 0xda, 0x22, 0x0b, 0x71, 0x62, 0xfb, 0xdc, 0xc8, 0x2c,
- 0x57, 0x66, 0xd7, 0x42, 0x57, 0xfd, 0xff, 0xbe, 0x9f, 0x66, 0x3a, 0xc5,
- 0x49, 0xee, 0x31, 0x15, 0xff, 0x6a, 0x22, 0xc1, 0xfe, 0x7a, 0x2c, 0x5f,
- 0xf6, 0x81, 0x83, 0x6f, 0x0a, 0x56, 0x2f, 0xfc, 0x3f, 0x89, 0x8d, 0xc1,
- 0xb4, 0x16, 0x2f, 0xbe, 0x1b, 0x6c, 0xb1, 0x58, 0x8d, 0xa6, 0x3c, 0x23,
- 0x9f, 0x20, 0x54, 0x6e, 0xe9, 0x19, 0x42, 0xa3, 0x51, 0xb4, 0x33, 0x66,
- 0x77, 0x3b, 0x68, 0xc7, 0x07, 0x0d, 0x9c, 0x9c, 0x4b, 0x36, 0x1c, 0x1b,
- 0xc3, 0x1f, 0xb8, 0x5e, 0xbc, 0xa3, 0xa8, 0x92, 0x75, 0x1e, 0x91, 0xe1,
- 0x07, 0xf9, 0x4d, 0xad, 0x38, 0x1c, 0x08, 0x73, 0x14, 0xa1, 0x0e, 0x4a,
- 0x4e, 0xf4, 0xa5, 0xce, 0x90, 0xe5, 0x32, 0x1f, 0x57, 0xd1, 0x87, 0x32,
- 0x3d, 0x62, 0xa3, 0x13, 0xdd, 0x36, 0x3b, 0x2b, 0xf9, 0xc0, 0xdd, 0x27,
- 0xcb, 0x17, 0xd3, 0xbb, 0xee, 0xb1, 0x50, 0x3d, 0x30, 0xcb, 0xef, 0xf0,
- 0xbb, 0x62, 0xc0, 0x71, 0x62, 0xff, 0xfd, 0xfc, 0x2c, 0x37, 0xed, 0x0f,
- 0x86, 0xc6, 0x1d, 0x62, 0xfb, 0x76, 0x6d, 0xd5, 0x16, 0x01, 0x50, 0x44,
- 0x4e, 0x96, 0x2f, 0xf1, 0xdf, 0x82, 0x9d, 0x44, 0xb1, 0x7e, 0x8b, 0x9a,
- 0x9e, 0x8b, 0x17, 0xdb, 0x99, 0xf8, 0x96, 0x2f, 0xfe, 0x78, 0x3f, 0x49,
- 0xfc, 0x9d, 0xf1, 0x62, 0xa5, 0x19, 0x8e, 0x6a, 0xc5, 0x82, 0x27, 0xbf,
- 0x16, 0x00, 0x5c, 0x58, 0xb8, 0xc0, 0x2c, 0x57, 0xcf, 0x04, 0x05, 0x17,
- 0xf4, 0xf4, 0xe7, 0x24, 0x0b, 0x17, 0xe1, 0xe6, 0x03, 0x8b, 0x15, 0x2a,
- 0xb1, 0x36, 0x23, 0xc8, 0x5e, 0xf2, 0x1d, 0xfe, 0x7b, 0x11, 0x11, 0x86,
- 0x17, 0xf8, 0x73, 0x19, 0xdf, 0x85, 0x2b, 0x15, 0x18, 0x8a, 0x81, 0x38,
- 0x5f, 0xb5, 0xbb, 0x36, 0xea, 0x89, 0xd4, 0xbf, 0xff, 0xdf, 0x9d, 0x87,
- 0x87, 0x8c, 0xe7, 0x33, 0xef, 0xc1, 0x6c, 0xb1, 0x7f, 0xd3, 0xee, 0x03,
- 0x33, 0x5c, 0x58, 0xbf, 0x46, 0x1d, 0xa1, 0x19, 0x88, 0xd7, 0x88, 0xdc,
- 0x99, 0xef, 0xff, 0xe2, 0x14, 0xfb, 0x98, 0x51, 0x80, 0x04, 0xfd, 0xb6,
- 0x58, 0xbc, 0xd1, 0x32, 0xc5, 0xd3, 0xc5, 0x8b, 0x8a, 0x32, 0x23, 0x69,
- 0xe1, 0xda, 0x94, 0x61, 0x64, 0x24, 0xaf, 0x1b, 0x27, 0x58, 0xbd, 0xb4,
- 0xee, 0xb1, 0x7f, 0xdf, 0x17, 0x63, 0x7e, 0x92, 0x35, 0x8b, 0x66, 0xc7,
- 0xb9, 0xe1, 0xfb, 0xe6, 0xdc, 0xc3, 0xac, 0x5e, 0x87, 0x23, 0x0d, 0x46,
- 0x39, 0x3d, 0x74, 0x28, 0xbd, 0x87, 0x75, 0x8b, 0xed, 0xd9, 0xb7, 0x54,
- 0x5b, 0x25, 0xfe, 0x7d, 0x7d, 0xba, 0x38, 0x5d, 0x62, 0xb4, 0x7d, 0x5f,
- 0x31, 0xbf, 0xfb, 0xef, 0xef, 0x8b, 0xbc, 0x3b, 0x76, 0xb1, 0x77, 0x47,
- 0x58, 0xbf, 0xbc, 0xdf, 0xea, 0x39, 0x58, 0xbf, 0xff, 0xa1, 0x19, 0xc9,
- 0x7c, 0x1b, 0xe7, 0x33, 0xc5, 0x2b, 0x15, 0x28, 0x8b, 0x63, 0x0b, 0xf4,
- 0x25, 0xfa, 0x4a, 0xc5, 0xfb, 0x08, 0x07, 0xc5, 0x8b, 0xfe, 0x9e, 0x46,
- 0x7d, 0xf7, 0x6d, 0x2c, 0x5f, 0xff, 0x7b, 0xf9, 0x07, 0x28, 0x73, 0xf2,
- 0x5e, 0x58, 0xbf, 0xe7, 0xc2, 0x36, 0x7a, 0x37, 0xd6, 0x2a, 0x53, 0x16,
- 0xdc, 0xa4, 0x04, 0xe4, 0x7b, 0x1c, 0x9f, 0x7f, 0xa1, 0x3a, 0xda, 0x75,
- 0xb2, 0xc5, 0xfe, 0xf7, 0xde, 0x2f, 0xce, 0xcb, 0x15, 0x27, 0xd9, 0x86,
- 0xd7, 0xdf, 0x70, 0xe3, 0x65, 0x8b, 0xff, 0xfb, 0xef, 0xc6, 0xf4, 0x9c,
- 0xd9, 0xe3, 0xc7, 0x4f, 0x96, 0x2f, 0xdf, 0xcd, 0x4f, 0x96, 0x2b, 0xb4,
- 0x43, 0x79, 0x7a, 0x86, 0x8d, 0x36, 0x85, 0x7d, 0xfe, 0xf4, 0x1a, 0x1f,
- 0x9d, 0x96, 0x2e, 0x90, 0x2c, 0x5f, 0xbd, 0xf0, 0xdb, 0x65, 0x8b, 0x46,
- 0x0d, 0x74, 0x53, 0x21, 0x0d, 0xb9, 0x13, 0xa3, 0x9e, 0x14, 0x8d, 0x19,
- 0xb9, 0x42, 0xe7, 0x90, 0xf3, 0xf1, 0x38, 0x66, 0xa6, 0x0b, 0xdf, 0xf4,
- 0xbf, 0xb9, 0x3b, 0x67, 0x16, 0x2e, 0x87, 0x96, 0x2f, 0x81, 0x1d, 0x91,
- 0x9f, 0x3d, 0x10, 0x1c, 0xdf, 0xf8, 0xa3, 0x0e, 0x27, 0xf1, 0x30, 0x45,
- 0x8b, 0xf3, 0x73, 0xed, 0x05, 0x8b, 0xfc, 0x2f, 0x03, 0x42, 0x87, 0x16,
- 0x2b, 0x47, 0xbc, 0x45, 0x17, 0xf3, 0x6a, 0x39, 0x88, 0xd5, 0x8b, 0xc2,
- 0xe4, 0x66, 0x1e, 0x91, 0x10, 0xd8, 0x18, 0x99, 0x40, 0x21, 0xe7, 0x58,
- 0x9c, 0xab, 0x46, 0xcf, 0x77, 0x7b, 0xac, 0x5f, 0x6e, 0xcd, 0xba, 0xa2,
- 0xe6, 0x2c, 0x75, 0x8a, 0xd1, 0xe1, 0x86, 0x63, 0x7f, 0x16, 0x76, 0x07,
- 0x82, 0xc5, 0xfe, 0x29, 0x30, 0xb3, 0xa6, 0x2c, 0x58, 0x2e, 0xb1, 0x5a,
- 0x3f, 0x8f, 0x17, 0x74, 0x34, 0xbc, 0xc7, 0xe2, 0xc5, 0xd9, 0xf5, 0x8b,
- 0xf6, 0x85, 0xdc, 0x38, 0xb1, 0x52, 0x78, 0x58, 0x2f, 0x74, 0x47, 0x58,
- 0xb1, 0x2c, 0x52, 0xc6, 0x16, 0x35, 0x29, 0xf6, 0x62, 0xeb, 0xc2, 0x6d,
- 0x8c, 0x49, 0x7c, 0x32, 0x08, 0xe2, 0xab, 0xf4, 0x60, 0x52, 0x37, 0x8d,
- 0xc2, 0x8b, 0x17, 0xfd, 0x19, 0x9a, 0x6e, 0x7d, 0xa0, 0xb1, 0x5b, 0x1f,
- 0xd9, 0x1f, 0xdf, 0xd0, 0x6d, 0x6d, 0xf1, 0x2c, 0x5f, 0xb9, 0x20, 0x33,
- 0x65, 0x8b, 0x64, 0x47, 0xb7, 0xc3, 0x0b, 0xcf, 0xfe, 0x2c, 0x5c, 0x2d,
- 0xd6, 0x2f, 0x71, 0xb4, 0xb1, 0x76, 0x12, 0xc5, 0xff, 0x3c, 0x1f, 0xe2,
- 0x39, 0xdd, 0x62, 0x86, 0x79, 0xfe, 0x16, 0xbb, 0xb8, 0xc1, 0xa3, 0xb0,
- 0x05, 0x1c, 0x1d, 0xf0, 0xc9, 0x8d, 0x95, 0x18, 0xaa, 0xa3, 0x21, 0xc8,
- 0xd1, 0xb4, 0xdf, 0xb5, 0xbb, 0x36, 0xea, 0x8b, 0xbc, 0xbf, 0xd0, 0x8c,
- 0xe6, 0xb4, 0xe1, 0xac, 0x5d, 0xef, 0x2c, 0x5a, 0x33, 0x11, 0x10, 0xc6,
- 0xfe, 0x39, 0xbf, 0xe2, 0x96, 0xdb, 0xbe, 0x48, 0xd6, 0x2c, 0xeb, 0x17,
+ 0xc5, 0x9e, 0xf6, 0x6c, 0xb1, 0x5b, 0x9e, 0x7f, 0x88, 0x6f, 0x6a, 0x07,
+ 0x58, 0xbe, 0xd3, 0xc9, 0xd6, 0x2e, 0x61, 0xac, 0x57, 0x46, 0xe4, 0x04,
+ 0x55, 0x88, 0x9c, 0x72, 0x36, 0x57, 0xbf, 0xcd, 0xe7, 0xf3, 0x83, 0x8b,
+ 0x15, 0x05, 0x46, 0x58, 0x5a, 0x50, 0x9a, 0xe4, 0x61, 0x62, 0x2d, 0xb7,
+ 0x16, 0x2f, 0xbd, 0xcc, 0x82, 0xc5, 0x74, 0x6d, 0x74, 0x25, 0x7f, 0xdf,
+ 0xfb, 0xe9, 0xf6, 0x63, 0xac, 0x54, 0x9e, 0xe3, 0x11, 0x5f, 0xf6, 0xa2,
+ 0x2c, 0x1f, 0xe7, 0xb2, 0xc5, 0xff, 0x68, 0x18, 0x36, 0xf0, 0xa5, 0x62,
+ 0xff, 0xc3, 0xf8, 0x98, 0xdc, 0x1b, 0x41, 0x62, 0xfb, 0xe1, 0x36, 0xcb,
+ 0x15, 0x88, 0xda, 0x63, 0xc2, 0x39, 0xf2, 0x05, 0x46, 0xee, 0x9f, 0x2b,
+ 0xbd, 0x1a, 0x8d, 0xa1, 0x9b, 0x33, 0xd0, 0x1b, 0x46, 0xe2, 0x38, 0x6c,
+ 0xe4, 0xe4, 0x41, 0xb0, 0xdf, 0xde, 0x32, 0xbe, 0xa1, 0x52, 0xf2, 0xa3,
+ 0x62, 0x56, 0xd4, 0xa4, 0xf3, 0xc3, 0x3b, 0xf2, 0x9c, 0x1a, 0x70, 0x34,
+ 0x10, 0xfc, 0x29, 0x4f, 0x1c, 0x94, 0x9b, 0xe9, 0x50, 0xdd, 0xa1, 0xcc,
+ 0x1c, 0x3e, 0xaf, 0xa3, 0x0e, 0x1c, 0x7a, 0xc5, 0x46, 0x27, 0xc0, 0x6c,
+ 0x76, 0xb7, 0xf3, 0x81, 0xbb, 0x4f, 0x96, 0x2f, 0xa7, 0x77, 0xdd, 0x62,
+ 0xa0, 0x7a, 0x61, 0x17, 0xdf, 0xe1, 0x74, 0xc5, 0x80, 0xe2, 0xc5, 0xff,
+ 0xfb, 0xf8, 0x58, 0x6f, 0xda, 0x1f, 0x09, 0x83, 0x3a, 0xc5, 0xf6, 0xec,
+ 0xdb, 0xaa, 0x4c, 0x02, 0xa0, 0x88, 0x9d, 0x2c, 0x5f, 0xfe, 0xc1, 0x94,
+ 0xee, 0x67, 0xe7, 0x62, 0x12, 0xc5, 0xe9, 0xce, 0x96, 0x2f, 0x31, 0x6e,
+ 0xb1, 0x7c, 0xdd, 0x70, 0xc1, 0x9b, 0xa0, 0x87, 0x6f, 0xfd, 0x3e, 0xe7,
+ 0x9c, 0x78, 0x50, 0x58, 0xbf, 0xc7, 0x7e, 0x0a, 0x75, 0x12, 0xc5, 0xfa,
+ 0x2e, 0x6a, 0x7b, 0x2c, 0x5f, 0x6e, 0x1f, 0xe2, 0x58, 0xbf, 0xf9, 0xe0,
+ 0xfd, 0xa7, 0xf2, 0x77, 0xc5, 0x8a, 0x94, 0x66, 0x39, 0xab, 0x16, 0x08,
+ 0x9e, 0xfc, 0x58, 0x01, 0x71, 0x62, 0xe0, 0xc0, 0xb1, 0x5f, 0x3c, 0x10,
+ 0x14, 0x5f, 0xd3, 0xdb, 0x9c, 0x90, 0x2c, 0x5f, 0x66, 0x03, 0x8b, 0x17,
+ 0xf9, 0x86, 0xdd, 0x78, 0x99, 0x62, 0x86, 0x7a, 0xb1, 0xc4, 0x55, 0x2b,
+ 0x82, 0xbb, 0x11, 0xe4, 0x2f, 0x7e, 0x46, 0x08, 0x43, 0x11, 0xdf, 0x23,
+ 0x0a, 0xf3, 0xd8, 0x88, 0x83, 0x84, 0x2d, 0xfe, 0x1c, 0xc6, 0x75, 0xe1,
+ 0x4a, 0xc5, 0x46, 0x23, 0x68, 0x50, 0xa2, 0xbf, 0x6b, 0x76, 0x6d, 0xd5,
+ 0x23, 0xa9, 0x7f, 0xff, 0xbf, 0x3b, 0x0f, 0x0f, 0x19, 0xce, 0x67, 0xdf,
+ 0x82, 0xd9, 0x62, 0xff, 0xa7, 0xdc, 0x06, 0x66, 0xb8, 0xb1, 0x7e, 0x8c,
+ 0x3b, 0x42, 0x33, 0x11, 0xaf, 0x11, 0xb9, 0x33, 0xdf, 0xff, 0xc4, 0x29,
+ 0xf7, 0x30, 0xa3, 0x00, 0x09, 0xfb, 0x6c, 0xb1, 0x79, 0xa2, 0x65, 0x8b,
+ 0xa7, 0x8b, 0x17, 0x14, 0x64, 0x46, 0xd3, 0xc3, 0xb5, 0x28, 0xc2, 0xc8,
+ 0x49, 0x5e, 0x36, 0x4e, 0xb1, 0x7b, 0x69, 0xdd, 0x62, 0xff, 0xbe, 0x2e,
+ 0x86, 0xfd, 0xa4, 0x6b, 0x16, 0xcd, 0x8f, 0x73, 0xc3, 0xf7, 0xcd, 0xb8,
+ 0x67, 0x58, 0xbd, 0x0e, 0x46, 0x1a, 0x8c, 0x72, 0x7a, 0xec, 0x51, 0x7f,
+ 0xfe, 0x92, 0x19, 0x8d, 0x2f, 0xda, 0x4c, 0x33, 0xf1, 0xcb, 0x17, 0xe9,
+ 0x39, 0x49, 0xab, 0x17, 0x4f, 0xd6, 0x2a, 0x06, 0xfc, 0x65, 0x15, 0xde,
+ 0x22, 0xf1, 0xe1, 0x37, 0x7b, 0x0e, 0xeb, 0x17, 0xdb, 0xb3, 0x6e, 0xa9,
+ 0x36, 0x4b, 0xfc, 0xfa, 0xfb, 0x76, 0x7e, 0xfd, 0x62, 0xb4, 0x7d, 0x7f,
+ 0x31, 0xbf, 0xfb, 0xef, 0xef, 0x8b, 0xac, 0x3b, 0x74, 0xb1, 0x77, 0x67,
+ 0x58, 0xbf, 0xbc, 0xdf, 0x30, 0x72, 0xb1, 0x7f, 0xfd, 0xc9, 0x7c, 0x1b,
+ 0xe7, 0x33, 0xc5, 0x2b, 0x17, 0xc0, 0x0f, 0xd2, 0xb1, 0x68, 0x46, 0x1f,
+ 0x83, 0xa6, 0x54, 0xa3, 0x25, 0xa1, 0x3f, 0x7e, 0x84, 0xbf, 0x69, 0x58,
+ 0xbe, 0x78, 0xec, 0xd2, 0xc5, 0xfb, 0x08, 0x07, 0xc5, 0x8b, 0xfe, 0x9e,
+ 0x46, 0x7d, 0xf7, 0x6d, 0x2c, 0x5f, 0xff, 0x7b, 0xf9, 0x07, 0x28, 0x73,
+ 0xf2, 0x5e, 0x58, 0xbf, 0xe7, 0xc2, 0x36, 0x7b, 0x37, 0xd6, 0x2a, 0x53,
+ 0x3b, 0x81, 0x4e, 0xe4, 0xa0, 0x27, 0x23, 0xd8, 0xe4, 0xfb, 0xfd, 0x09,
+ 0xd6, 0xd3, 0xad, 0x96, 0x2f, 0xf7, 0xbe, 0xf1, 0x7e, 0x76, 0x58, 0xa9,
+ 0x3e, 0xcc, 0x36, 0xbf, 0xfb, 0xbb, 0x00, 0x77, 0xd1, 0x9d, 0xb8, 0x75,
+ 0x8b, 0xef, 0xb8, 0x51, 0xb2, 0xc5, 0xff, 0xfd, 0xf7, 0xe3, 0x7a, 0x4e,
+ 0x6c, 0xf1, 0xe3, 0xa7, 0xcb, 0x17, 0xff, 0xff, 0xdc, 0x7f, 0x49, 0xdb,
+ 0xc2, 0x93, 0x20, 0xfe, 0x93, 0x94, 0xef, 0xa9, 0x58, 0xbf, 0x7f, 0x35,
+ 0x3e, 0x58, 0xae, 0x93, 0x03, 0x3a, 0xf7, 0x9f, 0x6a, 0x53, 0xaa, 0x1a,
+ 0x63, 0x46, 0x59, 0x7f, 0xbd, 0x06, 0x87, 0xe7, 0x65, 0x8b, 0xa4, 0x0b,
+ 0x17, 0xef, 0x7c, 0x26, 0xd9, 0x62, 0xd1, 0x92, 0xbd, 0x36, 0x32, 0xcc,
+ 0x84, 0x3e, 0xe4, 0x4e, 0x8e, 0x78, 0x71, 0x34, 0x6c, 0x25, 0x0c, 0x6e,
+ 0x47, 0x95, 0xe3, 0x50, 0x8d, 0x43, 0x17, 0xbf, 0xe9, 0x7f, 0x72, 0x76,
+ 0xce, 0x2c, 0x5d, 0x0f, 0x2c, 0x5f, 0xfe, 0xcf, 0x08, 0x07, 0x68, 0x10,
+ 0x98, 0x35, 0x8b, 0xe0, 0x47, 0x64, 0x67, 0xd1, 0x38, 0x03, 0x92, 0x18,
+ 0xbf, 0xf1, 0x46, 0x1c, 0x4f, 0xe2, 0x6e, 0xe5, 0x8b, 0xf3, 0x73, 0xed,
+ 0x05, 0x8b, 0xfc, 0x2f, 0x03, 0x42, 0x87, 0x16, 0x2b, 0x47, 0xbc, 0x45,
+ 0x17, 0xf3, 0x6a, 0x39, 0x88, 0xd5, 0x8b, 0xc2, 0xe4, 0x66, 0x1e, 0x91,
+ 0x10, 0xd8, 0x18, 0x99, 0x48, 0x21, 0xe9, 0x58, 0x9d, 0x1b, 0x46, 0xeb,
+ 0x6d, 0xd6, 0x2f, 0x8a, 0x7d, 0xc5, 0x8a, 0xe8, 0xda, 0xc4, 0x27, 0x7d,
+ 0xbb, 0x36, 0xea, 0x93, 0x98, 0xb1, 0xd6, 0x2b, 0x47, 0x86, 0x11, 0x8d,
+ 0xfc, 0x59, 0xd0, 0x1e, 0x0b, 0x17, 0xf8, 0xa4, 0x32, 0xce, 0xd8, 0xb1,
+ 0x6e, 0xfd, 0x62, 0xb4, 0x7f, 0x3e, 0x2e, 0xec, 0x69, 0x79, 0x8f, 0xc5,
+ 0x8b, 0xb3, 0xeb, 0x17, 0xed, 0x0b, 0xa8, 0x71, 0x62, 0xa4, 0xf0, 0xb0,
+ 0x5e, 0xe8, 0x8e, 0xb1, 0x62, 0x58, 0xa5, 0x8c, 0x2c, 0x6a, 0x53, 0xf6,
+ 0xc6, 0x67, 0x84, 0xe3, 0x18, 0x92, 0xf8, 0x44, 0x11, 0xc5, 0x57, 0xe8,
+ 0xce, 0xf2, 0x37, 0x8d, 0xfb, 0xc5, 0x8b, 0xfe, 0x8c, 0xcd, 0x37, 0x3e,
+ 0xd0, 0x58, 0xad, 0x8f, 0xf4, 0x90, 0x6e, 0x8f, 0xf2, 0xc5, 0xfd, 0x06,
+ 0xd6, 0xdf, 0x12, 0xc5, 0xfb, 0x92, 0x00, 0xf6, 0x58, 0xb6, 0x44, 0x7b,
+ 0x7c, 0x30, 0xbe, 0x68, 0x7f, 0x16, 0x2f, 0xfe, 0xda, 0x7e, 0xcf, 0xee,
+ 0x60, 0xbb, 0xf5, 0x8a, 0x19, 0xf6, 0x68, 0x8a, 0xf3, 0xff, 0x8b, 0x17,
+ 0x0b, 0x75, 0x8b, 0xdc, 0x6d, 0x2c, 0x5f, 0x0c, 0x2c, 0xfa, 0xc5, 0xd8,
+ 0x4b, 0x17, 0xfc, 0xf0, 0x7f, 0x88, 0xe7, 0x75, 0x8a, 0x93, 0xf3, 0x19,
+ 0x27, 0x85, 0xae, 0xea, 0x32, 0x0a, 0x88, 0x06, 0xed, 0x90, 0x94, 0x01,
+ 0x17, 0x07, 0x7c, 0x32, 0x1c, 0x24, 0x2a, 0x31, 0x5d, 0x46, 0x43, 0x99,
+ 0xa5, 0x21, 0x5f, 0xb5, 0xbb, 0x36, 0xea, 0x93, 0xbc, 0xbf, 0xd0, 0x8c,
+ 0xe6, 0xb4, 0xe1, 0x2c, 0x5d, 0xef, 0x2c, 0x5a, 0x33, 0x11, 0x10, 0xc6,
+ 0xfe, 0x39, 0xbf, 0xe2, 0x96, 0xdb, 0xae, 0x48, 0xd6, 0x2c, 0xeb, 0x17,
0x4e, 0xeb, 0x15, 0x03, 0x52, 0x71, 0x1b, 0x86, 0x05, 0x8b, 0xc7, 0x6f,
- 0x2c, 0x5d, 0x21, 0x16, 0x2f, 0x16, 0x6c, 0xb1, 0x7d, 0x9b, 0x0b, 0xa2,
- 0xc5, 0xa3, 0x06, 0x98, 0xae, 0x31, 0x9a, 0x42, 0x71, 0x80, 0x0e, 0x90,
- 0xc9, 0x83, 0xb5, 0x31, 0xbe, 0x03, 0x41, 0x13, 0x33, 0x3d, 0xee, 0xdd,
- 0xaf, 0xb8, 0x65, 0xbd, 0xa6, 0x79, 0xd4, 0xbe, 0xd3, 0xc3, 0xf7, 0xf1,
- 0x8a, 0x34, 0x3b, 0x41, 0x3a, 0xb6, 0x52, 0xa8, 0xf9, 0x39, 0x79, 0xe8,
- 0x63, 0x19, 0x1a, 0x65, 0xfc, 0xdd, 0xef, 0xf6, 0xd2, 0xc5, 0xff, 0x31,
- 0x6d, 0xc7, 0x2e, 0xe0, 0xb1, 0x44, 0x7d, 0x41, 0x98, 0x5f, 0xfb, 0x6c,
- 0x0f, 0xf9, 0xcc, 0x72, 0x58, 0xb7, 0x16, 0x2b, 0x0f, 0x44, 0x07, 0xf7,
- 0xfe, 0x72, 0x2c, 0x37, 0x71, 0x30, 0xd6, 0x2f, 0xbe, 0xfa, 0x82, 0xc5,
- 0xfb, 0x3e, 0x36, 0x25, 0x8b, 0x9e, 0x33, 0xe9, 0x8e, 0x93, 0x9f, 0x08,
- 0x7c, 0x7e, 0x61, 0x1d, 0xfb, 0x9c, 0x3b, 0x41, 0x62, 0xf8, 0x2f, 0x08,
- 0x05, 0xd6, 0x2f, 0xff, 0xa4, 0xb6, 0xe0, 0x99, 0xe1, 0xcf, 0xb4, 0x16,
- 0x2b, 0x47, 0xf9, 0xf2, 0xcb, 0xff, 0xf7, 0xe4, 0xb6, 0xe0, 0x99, 0xe1,
- 0xcf, 0xb4, 0x16, 0x2f, 0xff, 0xff, 0xe7, 0x92, 0xf1, 0x31, 0xb9, 0xe1,
- 0x79, 0xfd, 0xcf, 0xbe, 0xa7, 0x66, 0xd6, 0xeb, 0x17, 0x7d, 0xc6, 0x8d,
- 0xff, 0xab, 0x5f, 0xff, 0xcc, 0xfe, 0x9e, 0x85, 0x9c, 0xfb, 0x40, 0x7a,
- 0x0b, 0xac, 0x5d, 0xc9, 0x58, 0xbf, 0xfb, 0xbd, 0xc4, 0xdd, 0xfb, 0x30,
- 0x8d, 0x58, 0xbf, 0x82, 0x04, 0x78, 0xb9, 0x2b, 0x17, 0x89, 0xa3, 0x25,
- 0x56, 0x30, 0xe1, 0x4b, 0xbc, 0x60, 0x3f, 0x2e, 0xe3, 0x07, 0x85, 0xcc,
- 0x48, 0xbf, 0xa3, 0x78, 0xd2, 0x7b, 0xd6, 0xcb, 0x17, 0x8e, 0x28, 0xf5,
- 0x8b, 0xfc, 0x6c, 0x9c, 0x6c, 0xc1, 0xac, 0x5f, 0x66, 0xc2, 0xfa, 0xc5,
- 0xcc, 0x75, 0x8a, 0xd1, 0xbb, 0x11, 0x25, 0xf0, 0x82, 0x0e, 0x56, 0x2f,
- 0xff, 0xdc, 0x32, 0x47, 0x93, 0xe7, 0xe9, 0x22, 0x0b, 0xca, 0xc5, 0xfb,
- 0x02, 0x7a, 0x4d, 0x58, 0xb0, 0x45, 0x8a, 0xd8, 0xdf, 0xe1, 0x5d, 0xf7,
- 0x1f, 0x7d, 0x2c, 0x56, 0xc9, 0xdb, 0x39, 0x0e, 0x9c, 0x3e, 0x42, 0x02,
- 0x52, 0x84, 0xd0, 0x64, 0x37, 0xfe, 0xe3, 0x1b, 0xf7, 0x92, 0x14, 0xac,
- 0x5f, 0xf3, 0x79, 0xbf, 0xdc, 0x33, 0xcb, 0x17, 0xe0, 0x37, 0x05, 0x2b,
- 0x15, 0xf3, 0xe2, 0xf1, 0xd5, 0x62, 0x30, 0x9e, 0x14, 0x17, 0x30, 0x16,
- 0x2f, 0xfa, 0x21, 0xb3, 0x07, 0x9d, 0xf9, 0x62, 0xff, 0xff, 0xf1, 0x30,
- 0x65, 0x9e, 0xf6, 0x6d, 0x24, 0xc6, 0xf0, 0xf3, 0x84, 0x35, 0x8b, 0xd8,
- 0x67, 0x16, 0x2b, 0x11, 0xce, 0xe2, 0xfa, 0x3c, 0x08, 0xed, 0x79, 0xe2,
- 0xe2, 0xc5, 0xfc, 0x52, 0x03, 0xb4, 0x16, 0x2f, 0xe2, 0x90, 0x1d, 0xa0,
- 0xb1, 0x7f, 0xa3, 0x78, 0xd0, 0xb0, 0x7f, 0x12, 0xc5, 0xfb, 0x3a, 0x49,
- 0x7b, 0x0f, 0xaf, 0x85, 0xb7, 0xe2, 0x17, 0x3e, 0xfd, 0x51, 0xe9, 0x83,
- 0xda, 0x84, 0xc5, 0xf8, 0x6f, 0xd3, 0x58, 0xb1, 0x6f, 0xc9, 0xfe, 0x62,
- 0x95, 0xfe, 0x68, 0x6b, 0x23, 0x9c, 0x0b, 0x17, 0xfa, 0x4a, 0x77, 0xe0,
- 0x0e, 0xb1, 0x7d, 0x31, 0x7d, 0xd6, 0x2f, 0x33, 0x6e, 0xa8, 0x95, 0xcb,
- 0xfc, 0x6b, 0x10, 0x3d, 0x9f, 0x58, 0xad, 0x91, 0x03, 0xb9, 0x1b, 0x95,
- 0x5e, 0xfe, 0x6e, 0xb1, 0x7d, 0x80, 0x17, 0x16, 0x2e, 0x6e, 0xf0, 0xf0,
- 0x48, 0x7a, 0xf9, 0xa0, 0xe0, 0x58, 0xbf, 0xff, 0xf8, 0x3f, 0x1a, 0xdc,
- 0xfe, 0xef, 0xcc, 0x1f, 0xa0, 0x21, 0xb1, 0x01, 0x62, 0xff, 0xa2, 0x26,
- 0x33, 0x01, 0x30, 0x58, 0xbf, 0x31, 0xad, 0xe8, 0x2c, 0x5f, 0xff, 0x71,
- 0xdb, 0xbf, 0xb3, 0xf8, 0x5a, 0x6e, 0x2c, 0x51, 0x1f, 0xcf, 0x8a, 0x68,
- 0xd4, 0x6a, 0x77, 0x0b, 0x3b, 0xff, 0xbf, 0x90, 0xdf, 0xee, 0x39, 0x2f,
- 0x2c, 0x54, 0xa7, 0x72, 0xf1, 0xa5, 0x78, 0xaa, 0xff, 0xfe, 0x93, 0xe7,
- 0xa7, 0xdc, 0xcd, 0x4e, 0x11, 0x87, 0x58, 0xa8, 0x2e, 0x0c, 0x8c, 0x9b,
- 0x73, 0x6d, 0x42, 0xd4, 0xee, 0x5f, 0x2c, 0x28, 0xf6, 0xfc, 0x6b, 0x7f,
- 0xe8, 0x19, 0x0c, 0x2f, 0x6d, 0x83, 0x58, 0xbf, 0xf6, 0xef, 0xac, 0xfb,
- 0xeb, 0xec, 0xb1, 0x7f, 0xf0, 0xb9, 0xf6, 0x87, 0x9d, 0x88, 0x0b, 0x15,
- 0xda, 0x20, 0xf4, 0x7f, 0x77, 0xdf, 0x48, 0xe8, 0xf4, 0x31, 0x2f, 0x69,
- 0xfc, 0xb1, 0x7e, 0x68, 0x37, 0x70, 0x58, 0xa8, 0x8f, 0x1b, 0x43, 0xb7,
- 0xe2, 0x60, 0xcc, 0x3a, 0xc5, 0x49, 0xe6, 0xf8, 0x8e, 0xfe, 0x84, 0xb8,
- 0x1c, 0xeb, 0x17, 0xff, 0xfd, 0x9d, 0xc3, 0x0e, 0xe5, 0x0d, 0x4f, 0xd9,
- 0xfd, 0x3f, 0x58, 0xbe, 0xdb, 0xd9, 0xf5, 0x8b, 0xff, 0x68, 0xb0, 0x6f,
- 0x0c, 0xef, 0xcb, 0x15, 0x27, 0xc6, 0xe4, 0x97, 0xf4, 0x9c, 0x7a, 0x6d,
- 0xd6, 0x2a, 0x09, 0x8b, 0xfe, 0x19, 0x04, 0x41, 0x7f, 0xf8, 0xbd, 0xfc,
- 0x87, 0x7e, 0xd4, 0xe0, 0x6b, 0x17, 0xff, 0xff, 0x98, 0x8c, 0x90, 0x64,
- 0x3f, 0x3d, 0x07, 0x31, 0x98, 0x42, 0x86, 0x71, 0x62, 0xa5, 0x18, 0xfa,
- 0x4c, 0xba, 0x1b, 0x2c, 0x5e, 0x68, 0x62, 0xc5, 0xe6, 0x8e, 0x35, 0x62,
- 0xb7, 0x37, 0xa0, 0x1c, 0xbf, 0xff, 0xff, 0xff, 0x0d, 0x8e, 0x76, 0x84,
- 0x24, 0xc9, 0x1b, 0xe9, 0xbb, 0x1f, 0xe7, 0x5c, 0x76, 0x62, 0x9d, 0xff,
- 0x31, 0x2c, 0x5f, 0xc5, 0xe1, 0x7c, 0x2b, 0x2b, 0x16, 0xf4, 0xa3, 0x8d,
- 0xe1, 0x63, 0x7f, 0xff, 0x1f, 0x3b, 0xf7, 0xdb, 0x76, 0x1f, 0xb8, 0x4e,
- 0x6a, 0xc5, 0xfe, 0x93, 0xcc, 0x60, 0x61, 0x86, 0xb1, 0x4e, 0x8c, 0x46,
- 0x2c, 0x08, 0xbd, 0x58, 0x9f, 0xcb, 0x47, 0x93, 0x7f, 0xff, 0xfe, 0x09,
- 0x9a, 0x7d, 0x98, 0xfb, 0xfd, 0xfe, 0xf2, 0x5e, 0xfb, 0x6f, 0x24, 0x35,
- 0x8b, 0xfd, 0xd3, 0xf8, 0xff, 0x3b, 0x2c, 0x5f, 0x6b, 0x4f, 0xb2, 0xc5,
- 0x39, 0xec, 0x80, 0xd6, 0x99, 0x1f, 0xe5, 0x0d, 0xeb, 0xfd, 0x9a, 0xe3,
- 0x6e, 0x2e, 0xd6, 0x2f, 0xff, 0x6b, 0xde, 0x6d, 0x8c, 0x38, 0xfe, 0xe6,
- 0xac, 0x5f, 0xfb, 0x69, 0xd8, 0xb3, 0xde, 0xcd, 0x96, 0x2e, 0xef, 0x98,
- 0x89, 0x03, 0x13, 0xeb, 0x11, 0xec, 0xd0, 0xc6, 0xbf, 0xdd, 0xe3, 0xf3,
- 0x82, 0x95, 0x8b, 0xff, 0x66, 0xa1, 0xe7, 0x1e, 0x14, 0x16, 0x2c, 0x25,
- 0x8b, 0x9f, 0xa2, 0xc5, 0xe7, 0xcd, 0x2c, 0x57, 0xcd, 0xaf, 0x86, 0x6f,
- 0xff, 0xd2, 0x03, 0x24, 0x64, 0x2f, 0x4f, 0x33, 0xbf, 0x2c, 0x5e, 0x68,
- 0x05, 0x16, 0x2b, 0x64, 0x70, 0x7d, 0x1c, 0x04, 0x3d, 0x15, 0xef, 0xfb,
- 0x1f, 0xa1, 0x4e, 0x6a, 0x0b, 0x17, 0xff, 0xef, 0x43, 0x23, 0xd8, 0x81,
- 0xdf, 0xb5, 0x38, 0x1a, 0xc0, 0x66, 0xe6, 0xfb, 0xdf, 0x90, 0x2c, 0x58,
- 0x0b, 0x15, 0xd9, 0xb5, 0xd1, 0x1d, 0x4a, 0xa5, 0x9c, 0x8c, 0x79, 0x9e,
- 0x45, 0x0a, 0x0b, 0xff, 0xf8, 0x6f, 0xbf, 0xdc, 0x63, 0xc0, 0xcc, 0x8b,
- 0xe2, 0x35, 0x62, 0xff, 0xf6, 0x9f, 0xa4, 0x1f, 0xdf, 0x93, 0xb1, 0x2c,
- 0x56, 0x22, 0xb7, 0x4c, 0x57, 0xf7, 0xdb, 0xdc, 0xfc, 0xac, 0x5f, 0xfe,
- 0x88, 0xa7, 0xdc, 0xf7, 0x7b, 0xb9, 0x6c, 0xb1, 0x7f, 0xff, 0xfe, 0x63,
- 0x73, 0x4d, 0xd8, 0x70, 0x7f, 0xce, 0xe4, 0xdd, 0xf1, 0xc8, 0x4d, 0xf5,
- 0x8b, 0xfe, 0x60, 0xc7, 0xf9, 0xdb, 0x03, 0x58, 0xa7, 0x4c, 0x3d, 0x93,
- 0x8a, 0x10, 0xb7, 0xff, 0xce, 0x0c, 0x3b, 0xfb, 0x92, 0x76, 0xef, 0xcb,
- 0x17, 0xff, 0xf7, 0x4c, 0x1e, 0xa4, 0x5c, 0x7e, 0x8c, 0xe3, 0x14, 0xac,
- 0x56, 0x22, 0xb9, 0xd4, 0x2f, 0xff, 0xf6, 0xed, 0xa6, 0xff, 0x70, 0xcf,
- 0x67, 0xa4, 0x41, 0x7c, 0x58, 0xbf, 0xf9, 0xbb, 0x83, 0xfb, 0xf3, 0xaf,
- 0x4a, 0xc5, 0xff, 0x49, 0xfd, 0x91, 0x41, 0xfc, 0xb1, 0x50, 0x4c, 0x19,
- 0xc8, 0x4e, 0xcd, 0xe4, 0x5b, 0xff, 0xfd, 0xf7, 0x18, 0xf0, 0x3e, 0xfc,
- 0x26, 0xe7, 0xc3, 0x61, 0xac, 0x5f, 0x09, 0xb5, 0x05, 0x8b, 0xf8, 0xa7,
- 0x60, 0x37, 0x96, 0x2f, 0xf3, 0x0c, 0xc0, 0x92, 0x50, 0x58, 0xb4, 0xee,
- 0x7c, 0x87, 0x2e, 0xbf, 0xfe, 0x3b, 0x10, 0x3e, 0x1b, 0x16, 0xdb, 0xbe,
- 0xcb, 0x17, 0xff, 0xfc, 0xe5, 0x0e, 0x6c, 0x2e, 0x67, 0xa4, 0x98, 0x04,
- 0xd0, 0x58, 0xbf, 0xff, 0xb4, 0xdc, 0xc2, 0x9c, 0x07, 0x32, 0x29, 0xef,
- 0x8b, 0x17, 0x3f, 0x99, 0x31, 0x30, 0x29, 0x89, 0x96, 0x86, 0x9f, 0xeb,
- 0xc2, 0x1d, 0xa3, 0x3b, 0xbf, 0xe1, 0x00, 0xed, 0x0e, 0x68, 0x6b, 0x17,
- 0xff, 0xfb, 0x1c, 0xbd, 0x85, 0xd4, 0x98, 0x72, 0x5b, 0x4e, 0x96, 0x2b,
- 0xc8, 0x9a, 0xe8, 0x77, 0x6d, 0x2c, 0x5f, 0xff, 0xbb, 0xf1, 0x4f, 0xdb,
- 0x99, 0xb9, 0x36, 0x6e, 0xb1, 0x58, 0x88, 0xdd, 0xc9, 0x44, 0x25, 0x7f,
- 0xff, 0xfb, 0xf8, 0x70, 0x36, 0xb3, 0xa6, 0x0f, 0x38, 0x26, 0xef, 0xe1,
- 0xb7, 0x96, 0x2f, 0xf4, 0xfd, 0xfd, 0xc6, 0xed, 0x62, 0xff, 0xd9, 0xdf,
- 0xbd, 0x27, 0xfe, 0x6c, 0xb1, 0x7f, 0xd1, 0x6f, 0xf7, 0x3c, 0xe8, 0xd5,
- 0x8b, 0xfc, 0x0c, 0xd6, 0x67, 0xb8, 0xb1, 0x7d, 0xb7, 0xb3, 0x75, 0x8a,
- 0xc4, 0x4a, 0xf6, 0x7b, 0xa3, 0x3a, 0x96, 0x49, 0x5c, 0x08, 0x87, 0x19,
- 0xee, 0x47, 0xcf, 0xb9, 0xef, 0xe5, 0x31, 0x14, 0x6c, 0x3e, 0x30, 0x13,
- 0xd8, 0x66, 0x86, 0x43, 0x5a, 0xf6, 0x01, 0x96, 0x2f, 0x6b, 0x3b, 0x58,
- 0xbd, 0xf6, 0x87, 0xcd, 0xd0, 0x07, 0x2f, 0xfe, 0x67, 0xf4, 0x96, 0xee,
- 0x73, 0xba, 0xc5, 0xf7, 0xe4, 0xbc, 0xb1, 0x73, 0x8f, 0xe7, 0xcb, 0xc4,
- 0x3b, 0x67, 0xd1, 0x88, 0x50, 0x97, 0xbf, 0xec, 0xef, 0x83, 0x96, 0x2d,
- 0x96, 0x2f, 0xf3, 0x72, 0x4b, 0xdf, 0x75, 0x8b, 0xf1, 0xe2, 0xe3, 0x92,
- 0xc5, 0xff, 0xdb, 0xbe, 0xbf, 0x91, 0x7d, 0xf5, 0xb2, 0xc5, 0xff, 0xcc,
- 0x0c, 0x2e, 0xfd, 0xa9, 0xc0, 0xd6, 0x2f, 0xf4, 0x9b, 0x9a, 0x33, 0xdc,
- 0x58, 0xbf, 0xc4, 0x53, 0xb7, 0xe4, 0x6b, 0x17, 0xfa, 0x1c, 0xfc, 0xe8,
- 0xc1, 0xac, 0x56, 0x1f, 0x4b, 0x19, 0xd4, 0x15, 0x06, 0xe1, 0x61, 0xa7,
- 0x5b, 0x99, 0x76, 0x52, 0x49, 0x1c, 0x45, 0xf4, 0x27, 0xef, 0xc0, 0x89,
- 0xc4, 0x17, 0x58, 0xbf, 0xff, 0xdf, 0xcd, 0xcb, 0x0f, 0x85, 0x9e, 0x10,
- 0x0e, 0xd0, 0x58, 0xbf, 0xbe, 0xc7, 0x29, 0xed, 0x62, 0xff, 0xc5, 0x9f,
- 0xc8, 0xa0, 0xfa, 0x82, 0xc5, 0xff, 0xff, 0xf0, 0x24, 0xb7, 0x6f, 0x37,
- 0x60, 0xce, 0x8f, 0xe8, 0x7d, 0xfd, 0xc7, 0x1a, 0xc5, 0xff, 0x77, 0xef,
- 0xb1, 0xf3, 0xbf, 0x2c, 0x5f, 0xff, 0xfe, 0x21, 0x7f, 0xdf, 0x9d, 0x03,
- 0x35, 0x02, 0x78, 0x7f, 0x30, 0xb7, 0x58, 0xbf, 0x05, 0xff, 0x80, 0x65,
- 0x8b, 0x67, 0x11, 0x46, 0x27, 0x7b, 0xfe, 0x9c, 0xf1, 0x60, 0x23, 0xb1,
- 0x62, 0xff, 0xcf, 0xd1, 0xfd, 0x14, 0x24, 0xbc, 0xb1, 0x52, 0xab, 0xf6,
- 0x05, 0xd8, 0xc1, 0xb9, 0x77, 0x67, 0xfa, 0x84, 0x01, 0x43, 0x7f, 0x85,
- 0x1e, 0x3a, 0xbf, 0xfc, 0xd9, 0x0f, 0xe3, 0x96, 0x02, 0x3b, 0x16, 0x2f,
- 0x34, 0x23, 0x23, 0x47, 0x50, 0x25, 0x31, 0xf8, 0xc2, 0x32, 0xc1, 0xc6,
- 0x1b, 0x93, 0xb8, 0xdb, 0xc6, 0xcf, 0xdc, 0x31, 0x9c, 0x86, 0x28, 0xd1,
- 0x35, 0x0f, 0xc3, 0x91, 0x7e, 0x52, 0x7b, 0x46, 0x4e, 0x08, 0xc7, 0x02,
- 0xe4, 0xc5, 0x2a, 0x37, 0x94, 0xa1, 0xff, 0x4b, 0xc5, 0x32, 0x5b, 0xb0,
- 0x48, 0x44, 0xdc, 0x17, 0xc5, 0x8b, 0xfe, 0xcf, 0x4e, 0xb0, 0xbe, 0x25,
- 0x8b, 0xff, 0x9f, 0x44, 0xc6, 0x96, 0x7a, 0x43, 0x58, 0xbe, 0x91, 0x05,
- 0xf1, 0x62, 0x8d, 0x3e, 0xaf, 0x22, 0x5f, 0xf4, 0x33, 0xdf, 0x79, 0xd0,
- 0x16, 0x2f, 0xb7, 0x68, 0x62, 0xc5, 0x80, 0xb1, 0x58, 0x6d, 0x5c, 0x8e,
- 0xff, 0x60, 0xdc, 0xbd, 0x9f, 0x58, 0xbf, 0xff, 0x87, 0xf9, 0x2d, 0xb8,
- 0x26, 0x78, 0x73, 0xed, 0x05, 0x8b, 0xff, 0xff, 0xf8, 0xb3, 0x84, 0x2f,
- 0xfb, 0xf3, 0xa0, 0x66, 0xa0, 0x4f, 0x0f, 0xe6, 0x16, 0xeb, 0x17, 0xb3,
- 0xf1, 0x91, 0xa9, 0x54, 0x10, 0xc6, 0xf2, 0x14, 0x5d, 0x91, 0xfd, 0xb8,
- 0x87, 0xf8, 0x64, 0x62, 0xe5, 0xff, 0xff, 0xf0, 0xf2, 0x33, 0x90, 0x7f,
- 0xcf, 0x70, 0xc3, 0xe7, 0x47, 0xf0, 0x24, 0x72, 0xb1, 0x79, 0xe5, 0x96,
- 0x2f, 0x7a, 0x46, 0x91, 0x7f, 0xfb, 0xec, 0xfe, 0x98, 0x3e, 0xb6, 0x10,
- 0x12, 0x2f, 0x68, 0x2f, 0x19, 0x27, 0xd1, 0xc1, 0xdb, 0xcd, 0xbc, 0x64,
- 0x11, 0x7a, 0x38, 0x41, 0xda, 0x30, 0x6e, 0xc7, 0x77, 0x79, 0x63, 0xe7,
- 0xb5, 0x12, 0xfe, 0x9c, 0x19, 0x14, 0x24, 0xba, 0x46, 0x7f, 0x7f, 0xfa,
- 0x30, 0xed, 0x08, 0xcc, 0xd6, 0xec, 0xdb, 0xaa, 0x26, 0x12, 0xfa, 0x5c,
- 0xcf, 0xac, 0x5f, 0xef, 0xc9, 0x31, 0xe4, 0x22, 0xc5, 0xe7, 0x33, 0xeb,
- 0x17, 0xff, 0xf6, 0x74, 0x61, 0xfe, 0x63, 0x3d, 0xfc, 0x18, 0xbd, 0xc5,
- 0x8b, 0xff, 0xda, 0x60, 0x46, 0x1b, 0xe8, 0x07, 0x3c, 0x82, 0xc5, 0xd9,
- 0x18, 0x34, 0xc9, 0xd8, 0x8c, 0x06, 0x84, 0x3c, 0x63, 0x0d, 0xc1, 0x40,
- 0xb1, 0x62, 0xdd, 0x16, 0x28, 0x2a, 0x6d, 0x4e, 0x43, 0x7e, 0x7f, 0xff,
- 0x36, 0x58, 0xbf, 0xba, 0x3f, 0x79, 0x9b, 0x2c, 0x58, 0x6b, 0x15, 0x87,
- 0x87, 0xf3, 0x1b, 0xfb, 0x21, 0x3f, 0xdd, 0xd6, 0x2a, 0x36, 0x3c, 0xf0,
- 0xb5, 0x21, 0xbf, 0x40, 0xc8, 0x4e, 0x96, 0x2f, 0xfe, 0x0a, 0xe7, 0x70,
- 0x13, 0x78, 0xa6, 0x0b, 0x17, 0xc1, 0x6f, 0x20, 0x75, 0x8b, 0xf4, 0x69,
- 0x1a, 0x05, 0x23, 0xa3, 0x75, 0x8b, 0xbd, 0x1a, 0x96, 0x2f, 0xfe, 0xc7,
- 0x06, 0x33, 0xeb, 0x79, 0xf2, 0xc5, 0xdd, 0xc7, 0xac, 0x5f, 0xbe, 0xe7,
- 0x9d, 0xd6, 0x2e, 0xc3, 0xf5, 0x3c, 0x5d, 0xc7, 0x2f, 0xe9, 0x3e, 0x02,
- 0x7a, 0x2c, 0x5f, 0xfe, 0xf7, 0x05, 0x3d, 0x77, 0xfb, 0xc7, 0x36, 0xcb,
- 0x14, 0x34, 0x58, 0xfc, 0xc0, 0x8b, 0xef, 0xfa, 0x1d, 0x7c, 0x5d, 0x7a,
- 0xfe, 0x39, 0x62, 0xfa, 0x40, 0x61, 0xd6, 0x2f, 0xa7, 0x92, 0x05, 0x8b,
- 0xb5, 0x9b, 0x9e, 0x31, 0x12, 0x5f, 0xbc, 0xdb, 0x37, 0x16, 0x2f, 0xa4,
- 0xef, 0xa5, 0x8b, 0xb0, 0x96, 0x2d, 0x31, 0x1f, 0x0e, 0x8a, 0x78, 0x45,
- 0x7c, 0x23, 0x33, 0x65, 0x8b, 0xff, 0xcc, 0x42, 0xcf, 0x13, 0x7c, 0xb3,
- 0x4b, 0x17, 0xd2, 0x4f, 0x12, 0xc5, 0xff, 0xfb, 0x36, 0xeb, 0x98, 0x5e,
- 0xfb, 0x3f, 0x1f, 0xa2, 0xc5, 0xee, 0x82, 0x82, 0xc5, 0xfb, 0xf2, 0x37,
- 0x35, 0x62, 0xb7, 0x57, 0xc8, 0xf1, 0x9c, 0xc7, 0x97, 0xea, 0x11, 0x47,
- 0x84, 0x77, 0xcd, 0x40, 0x4a, 0x48, 0xfe, 0x22, 0xe8, 0xb0, 0x10, 0x82,
- 0xff, 0xd3, 0xad, 0x67, 0xdb, 0xdf, 0x95, 0x8b, 0xfc, 0x1f, 0xdf, 0xdc,
- 0x6d, 0x2c, 0x5e, 0x2e, 0x4a, 0xc5, 0x6c, 0x88, 0xfc, 0x3e, 0x63, 0x5b,
- 0xe1, 0xef, 0x27, 0x58, 0xbc, 0x67, 0x09, 0x62, 0xff, 0x30, 0x3a, 0xfa,
- 0x7b, 0x82, 0xc5, 0x39, 0xfc, 0xfc, 0x90, 0x87, 0xaf, 0xf3, 0x6b, 0x08,
- 0x2a, 0x1e, 0xeb, 0x17, 0x46, 0xfe, 0x58, 0xbe, 0x89, 0xc3, 0x89, 0x62,
- 0xff, 0x49, 0xdf, 0xf3, 0x84, 0xb1, 0x73, 0x71, 0x62, 0x8e, 0x7d, 0xde,
- 0x26, 0xe8, 0x63, 0x7f, 0x7a, 0x7a, 0x13, 0x76, 0xb1, 0x7e, 0x2d, 0xdc,
- 0xb1, 0x62, 0xff, 0xc5, 0x83, 0xcf, 0xfa, 0x7b, 0x82, 0xc5, 0xfb, 0x6f,
- 0x63, 0x8d, 0x62, 0xb4, 0x7d, 0x04, 0x7f, 0x7f, 0xee, 0x0f, 0x44, 0xc1,
- 0xe7, 0x7e, 0x58, 0xbf, 0xc1, 0x96, 0x77, 0xec, 0xfa, 0xc5, 0x4a, 0x25,
- 0xf0, 0x85, 0xd0, 0x6f, 0xf4, 0xb6, 0xde, 0x35, 0xb4, 0xb1, 0x7e, 0x6d,
- 0x41, 0x8e, 0xb1, 0x52, 0xab, 0x54, 0x67, 0x39, 0x08, 0xbe, 0xcc, 0x5c,
- 0xc3, 0xf1, 0x93, 0x11, 0x68, 0x8d, 0x6c, 0x75, 0x8b, 0xfd, 0xef, 0xb3,
- 0xf1, 0xfa, 0x2c, 0x5a, 0x37, 0x58, 0xa2, 0x3c, 0xc8, 0xe3, 0x5b, 0xfd,
- 0xc9, 0xc2, 0x1f, 0xe5, 0x62, 0xfe, 0x9c, 0x21, 0xfe, 0x56, 0x2f, 0x0b,
- 0x51, 0x75, 0x3d, 0xee, 0x19, 0x5f, 0xfa, 0x1b, 0x31, 0x60, 0xca, 0x77,
- 0x58, 0xbb, 0xf1, 0xeb, 0x17, 0xfe, 0x35, 0xa2, 0x1e, 0xb0, 0xb0, 0x35,
- 0x8b, 0xfd, 0xac, 0xdb, 0xd3, 0xdc, 0x16, 0x2f, 0xff, 0xdc, 0x9c, 0xdb,
- 0x9c, 0xcd, 0x03, 0x33, 0x5c, 0x58, 0xa8, 0x23, 0xa0, 0xd1, 0xbd, 0xd0,
- 0x7c, 0x6d, 0x7f, 0xf4, 0xc3, 0xf2, 0x0e, 0xa7, 0x9c, 0xf2, 0xc5, 0xf6,
- 0xe5, 0x3f, 0x58, 0xbf, 0xc1, 0xf5, 0xc1, 0xfe, 0x7a, 0x2c, 0x5f, 0xf8,
- 0x58, 0x6e, 0x78, 0x53, 0xd8, 0xd6, 0x2a, 0x4f, 0xe9, 0xce, 0x6f, 0xf1,
- 0x0b, 0xd9, 0xe3, 0x36, 0x58, 0xac, 0x47, 0x9e, 0xa1, 0x3b, 0xe2, 0x0b,
- 0xb0, 0x35, 0x8b, 0xd2, 0x5e, 0x58, 0xbf, 0xe1, 0xe4, 0x3f, 0x3d, 0x07,
- 0x2b, 0x17, 0x74, 0xd9, 0x62, 0xba, 0x9e, 0xb3, 0x9d, 0xdd, 0xaf, 0xba,
- 0x25, 0x59, 0xca, 0xff, 0xc3, 0x6f, 0xcb, 0x3e, 0xb3, 0xb5, 0x8a, 0x73,
- 0xeb, 0x30, 0xb6, 0xff, 0x83, 0x33, 0xf3, 0xbf, 0xde, 0x25, 0x8b, 0xe1,
- 0x1f, 0x06, 0xb1, 0x5d, 0x9f, 0x08, 0x43, 0xeb, 0xfc, 0x7e, 0x3e, 0x74,
- 0x6d, 0x2c, 0x5f, 0xff, 0xf7, 0xf2, 0x19, 0x0f, 0xe1, 0x61, 0xbf, 0x68,
- 0x64, 0x0e, 0xb1, 0x58, 0x8c, 0x06, 0x25, 0xf1, 0xad, 0xf7, 0x0c, 0x9d,
- 0x96, 0x2f, 0xda, 0x98, 0x73, 0x16, 0x2f, 0x9f, 0xd9, 0xd1, 0x62, 0x96,
- 0x2f, 0xf6, 0x07, 0xe2, 0x60, 0x71, 0x62, 0xa5, 0x11, 0x9f, 0x28, 0x22,
- 0x4f, 0x06, 0x5f, 0xff, 0xf6, 0xed, 0xa9, 0xf4, 0xc3, 0xa9, 0x9e, 0x2c,
- 0x03, 0x10, 0x16, 0x2f, 0x7d, 0xa0, 0xb1, 0x50, 0x5f, 0xe5, 0xc5, 0xed,
- 0xe1, 0x05, 0xd9, 0xbb, 0xc6, 0x4f, 0x11, 0xfe, 0xa3, 0x39, 0x39, 0xa7,
- 0xe3, 0x18, 0x28, 0xd0, 0xf8, 0x5d, 0xe8, 0x58, 0x88, 0xef, 0xa3, 0x4d,
- 0xfe, 0x68, 0x3f, 0x7c, 0x9e, 0xd6, 0x2f, 0xfd, 0xcf, 0xc9, 0xfd, 0xc2,
- 0x6e, 0xd6, 0x2f, 0x88, 0x5a, 0x95, 0x8a, 0xec, 0xf8, 0x99, 0x02, 0xbe,
- 0x8b, 0x96, 0x84, 0xbd, 0xff, 0xf4, 0x97, 0xb5, 0x2f, 0x02, 0xc3, 0xb4,
- 0x16, 0x2f, 0xf8, 0x85, 0xc2, 0xc3, 0x67, 0x8b, 0x17, 0xe3, 0x9f, 0x05,
- 0x12, 0xc5, 0xff, 0xe9, 0xdf, 0x82, 0xf3, 0xfd, 0xcd, 0xfb, 0xac, 0x5f,
- 0xc7, 0x9c, 0x2f, 0x47, 0x2c, 0x5f, 0x69, 0xfb, 0x82, 0xc5, 0xb8, 0xb1,
- 0x7e, 0x9c, 0x2f, 0x47, 0x2c, 0x5e, 0xe3, 0x77, 0xd5, 0x12, 0x0e, 0x61,
- 0x11, 0x21, 0xc4, 0xa8, 0x69, 0xee, 0x9a, 0x9b, 0xa3, 0x93, 0x95, 0x7a,
- 0x1b, 0x97, 0xfd, 0x1f, 0x83, 0xfc, 0xc7, 0x94, 0xac, 0x53, 0xa2, 0x3d,
- 0x94, 0x6f, 0xfb, 0x5b, 0x6f, 0xf7, 0xf8, 0xbc, 0xb1, 0x5f, 0x3d, 0xe6,
- 0x21, 0xbe, 0xf0, 0x7c, 0xdd, 0x62, 0xff, 0x39, 0xba, 0xcd, 0xa7, 0x65,
- 0x8b, 0xf4, 0x9f, 0xa0, 0x20, 0xb1, 0x58, 0x88, 0x7e, 0x13, 0x78, 0xda,
- 0xef, 0x3a, 0xc5, 0xc2, 0xc5, 0x8b, 0xb5, 0xc5, 0x8a, 0x81, 0xfa, 0x9a,
- 0x5e, 0x01, 0x78, 0xe1, 0x7b, 0xff, 0xe1, 0x6a, 0x77, 0x0f, 0x1f, 0xfb,
- 0xbe, 0xc1, 0x16, 0x2f, 0x4b, 0xee, 0xb1, 0x50, 0x3f, 0x38, 0x95, 0xaf,
- 0xa7, 0x59, 0xb2, 0xc5, 0xed, 0x4f, 0x45, 0x8b, 0xa7, 0xcb, 0x15, 0x26,
- 0xdb, 0x43, 0xf7, 0xed, 0xdf, 0x9f, 0x75, 0x8b, 0xfb, 0x1c, 0xbc, 0x2f,
- 0xac, 0x57, 0x67, 0xad, 0xf2, 0x9b, 0xf6, 0xe4, 0xfd, 0xc1, 0x62, 0xe3,
- 0x3e, 0xb1, 0x51, 0x26, 0xb1, 0xf2, 0x3e, 0x2c, 0xf9, 0xd8, 0x44, 0x71,
- 0xc5, 0x57, 0x8f, 0xd7, 0x16, 0x2f, 0xce, 0x20, 0xbc, 0x73, 0xac, 0x5f,
- 0xda, 0xc7, 0xfc, 0x8d, 0x62, 0xfb, 0x7f, 0x66, 0xeb, 0x17, 0x0b, 0x8b,
- 0x15, 0x86, 0xf7, 0x44, 0xb7, 0xd2, 0x51, 0x6e, 0xb1, 0x7f, 0xfa, 0x4b,
- 0x3d, 0xfc, 0xf7, 0xe4, 0x41, 0x75, 0x8b, 0xf4, 0xc4, 0xcd, 0xa5, 0x8a,
- 0xd2, 0x26, 0x7e, 0x49, 0xc4, 0xdb, 0xf9, 0xf5, 0xd5, 0x88, 0x0b, 0x17,
- 0xbf, 0x9d, 0xac, 0x5f, 0xff, 0xe0, 0xc2, 0x7b, 0x3f, 0xd4, 0xb3, 0x67,
- 0xc2, 0xee, 0x1c, 0x58, 0xbf, 0x73, 0x3c, 0x66, 0xcb, 0x17, 0x7f, 0x75,
- 0x8b, 0x83, 0xf4, 0x9e, 0x26, 0x15, 0xd6, 0x23, 0x61, 0xa1, 0x57, 0x52,
- 0xab, 0xb2, 0x03, 0xe3, 0x2f, 0xc6, 0xa7, 0x85, 0xcf, 0xcc, 0x18, 0xbc,
- 0xa1, 0xed, 0x7f, 0xbd, 0xfc, 0x1e, 0x14, 0x16, 0x2f, 0xfb, 0x77, 0x1f,
- 0xb3, 0xe5, 0x2b, 0x17, 0xfe, 0x60, 0x7f, 0x1c, 0x62, 0xf7, 0x16, 0x29,
- 0xcf, 0xe0, 0x8e, 0x69, 0xd1, 0x97, 0xe8, 0x55, 0xdf, 0x61, 0xf3, 0xeb,
- 0x17, 0xdd, 0x30, 0x72, 0xb1, 0x7e, 0x68, 0xb8, 0x67, 0x45, 0x8b, 0xe1,
- 0x0f, 0xf2, 0xb1, 0x50, 0x3d, 0x02, 0x2d, 0xbe, 0x86, 0x4f, 0x6b, 0x17,
- 0xfd, 0x3b, 0x19, 0x0f, 0x89, 0xb6, 0x58, 0xbf, 0xf1, 0x7b, 0xed, 0x0e,
- 0xbc, 0xf8, 0xd6, 0x2f, 0x4f, 0x70, 0x58, 0xa9, 0x4e, 0x7a, 0x04, 0xf8,
- 0x44, 0xee, 0x91, 0x10, 0xe8, 0x8d, 0x8f, 0x49, 0x0a, 0xff, 0x45, 0xc6,
- 0x28, 0x9c, 0xeb, 0x17, 0xfd, 0x0e, 0xbf, 0x6d, 0xe4, 0x86, 0xb1, 0x58,
- 0x7e, 0x3d, 0x9a, 0xdf, 0x41, 0xb8, 0xeb, 0x17, 0xf1, 0x38, 0x0f, 0x3d,
- 0x16, 0x2f, 0x68, 0x07, 0x58, 0xa7, 0x3c, 0xd1, 0x17, 0xdf, 0xe7, 0xf1,
- 0x9a, 0x9f, 0xca, 0xc5, 0xf8, 0x9b, 0x72, 0xc5, 0x8b, 0xfa, 0x19, 0xff,
- 0xb4, 0x16, 0x2a, 0x08, 0x89, 0x73, 0x4f, 0x13, 0xd6, 0x26, 0xd4, 0xc4,
- 0x5c, 0x6f, 0x14, 0x2a, 0xaf, 0x3c, 0x84, 0x58, 0xbe, 0x2c, 0x73, 0x56,
- 0x2f, 0x9e, 0x7b, 0xe2, 0xc5, 0xf8, 0xcf, 0x14, 0x81, 0x62, 0x86, 0x88,
- 0xc3, 0x8f, 0x78, 0x8b, 0xa1, 0x1d, 0xff, 0x86, 0xfa, 0xdc, 0x6f, 0xd2,
- 0x46, 0xb1, 0x7f, 0xed, 0x49, 0x9d, 0xf0, 0x2a, 0xd9, 0xf5, 0x8b, 0xd0,
- 0x7e, 0x2c, 0x5e, 0x31, 0x8e, 0xb1, 0x7f, 0xf0, 0xf4, 0xfd, 0xc0, 0xb0,
- 0xd9, 0xe2, 0xc5, 0xef, 0x60, 0x6b, 0x14, 0x34, 0xc9, 0x9d, 0x0a, 0x24,
- 0x5d, 0x0e, 0x90, 0xf7, 0x91, 0xaf, 0xfe, 0x7e, 0x60, 0xff, 0x27, 0xdb,
- 0x03, 0x58, 0xbf, 0xb0, 0x27, 0xbb, 0x84, 0xac, 0x5f, 0xb3, 0xed, 0xee,
- 0x2c, 0x5f, 0xf8, 0x13, 0x0c, 0xef, 0xdb, 0x08, 0x35, 0x8a, 0x39, 0xf5,
- 0xf8, 0xa2, 0xff, 0x16, 0x1c, 0xf8, 0x28, 0x96, 0x2f, 0x82, 0xff, 0x7e,
- 0x2c, 0x54, 0x9f, 0xee, 0x88, 0x84, 0x69, 0x7d, 0x07, 0xd6, 0xcb, 0x17,
- 0x34, 0x4b, 0x17, 0x49, 0xfb, 0x37, 0x9a, 0x24, 0xbe, 0x7d, 0x36, 0x96,
- 0x2f, 0xff, 0x7a, 0x19, 0xac, 0xe4, 0xb8, 0xf0, 0xeb, 0x17, 0xf9, 0xfe,
- 0xe2, 0x67, 0xfa, 0xc5, 0x41, 0x13, 0xae, 0x45, 0xf4, 0x9b, 0xdc, 0x60,
- 0x2c, 0x54, 0xae, 0x4d, 0xe4, 0x6c, 0xbb, 0xab, 0xf6, 0x8c, 0xf1, 0x8c,
- 0xfd, 0xa9, 0xa1, 0x95, 0xe2, 0xfa, 0x58, 0xbe, 0x93, 0xbc, 0x16, 0x2e,
- 0xfc, 0xc0, 0xd7, 0x68, 0x32, 0xf4, 0x91, 0xab, 0x17, 0x34, 0x16, 0x2f,
- 0xfa, 0x7e, 0x11, 0xb6, 0x13, 0xe9, 0x62, 0xee, 0x62, 0xc5, 0x39, 0xe9,
- 0xb1, 0xe5, 0xff, 0xff, 0x8f, 0x2d, 0xef, 0x49, 0xb9, 0xef, 0xc9, 0x37,
- 0xb8, 0xe4, 0xb1, 0x7e, 0x9d, 0xc9, 0x8e, 0xb1, 0x7f, 0xe9, 0x87, 0x5c,
- 0xfb, 0xeb, 0xec, 0xb1, 0x5f, 0x3e, 0x8e, 0x14, 0x54, 0xa3, 0xd1, 0xe1,
- 0xa5, 0x7b, 0xf3, 0xf5, 0x8a, 0x1a, 0xa0, 0xae, 0xcb, 0x23, 0xc7, 0x62,
- 0x6a, 0xfc, 0x62, 0x9e, 0x26, 0xb8, 0x5b, 0x2c, 0x5f, 0x66, 0xa7, 0x75,
- 0x8b, 0xa2, 0xe0, 0xcd, 0xe7, 0xc6, 0x6f, 0xef, 0x6a, 0x77, 0xcd, 0x2c,
- 0x5f, 0xff, 0xfe, 0x9f, 0xfd, 0xb9, 0xd7, 0xec, 0xfc, 0xfe, 0x03, 0xae,
- 0xb3, 0xcd, 0xda, 0xc5, 0xfd, 0xf7, 0x1b, 0xeb, 0x75, 0x8b, 0xe7, 0xe4,
- 0xc1, 0x62, 0xee, 0xf9, 0xb9, 0xe8, 0xb1, 0x7d, 0xfc, 0xc0, 0xd6, 0x9f,
- 0x4b, 0x17, 0xbd, 0xd7, 0x16, 0x2a, 0x53, 0xa6, 0x72, 0xed, 0x17, 0xb4,
- 0x33, 0x40, 0x5e, 0x61, 0x75, 0x80, 0xb1, 0x7c, 0xfd, 0x27, 0xeb, 0x16,
- 0xc7, 0x36, 0xde, 0x12, 0xbf, 0xc6, 0x0d, 0x9b, 0x76, 0xdd, 0x62, 0xff,
- 0xf7, 0x35, 0x9d, 0x24, 0xbc, 0xc4, 0x2c, 0x58, 0xac, 0x44, 0x07, 0x8d,
- 0xaf, 0xbe, 0x2e, 0xfc, 0xb1, 0x7f, 0xf7, 0xf2, 0x74, 0x58, 0x73, 0x8a,
- 0x25, 0x8b, 0xfb, 0xc6, 0x00, 0x13, 0xda, 0xc5, 0xff, 0x3f, 0x9f, 0x0e,
- 0x59, 0xb2, 0xc5, 0x39, 0xf4, 0xfc, 0xc6, 0xfe, 0xe3, 0x9a, 0x76, 0xf2,
- 0xc5, 0xff, 0xba, 0x49, 0xb0, 0x72, 0x9d, 0x4a, 0xc5, 0xff, 0xff, 0xb5,
- 0x9d, 0x24, 0xbd, 0xd4, 0xc2, 0x9f, 0xb3, 0xfa, 0x7d, 0xc5, 0x8b, 0xff,
- 0x7d, 0xd8, 0x1d, 0x75, 0xa1, 0x7d, 0x62, 0xed, 0xe3, 0x65, 0x8b, 0xe2,
- 0x6f, 0x9a, 0xb1, 0x7b, 0x61, 0x41, 0x62, 0xf1, 0x67, 0x3a, 0x9f, 0x00,
- 0xc7, 0xb0, 0x8e, 0xf9, 0x81, 0x01, 0xac, 0x5f, 0xe9, 0x3e, 0xe4, 0xd9,
- 0xba, 0xc5, 0x0d, 0x57, 0x36, 0xf0, 0xae, 0xec, 0x85, 0xcb, 0xf4, 0x81,
- 0xe6, 0xfe, 0x90, 0xa2, 0x0d, 0x00, 0xc2, 0x3b, 0xee, 0xbd, 0x02, 0x6c,
- 0xb1, 0x7f, 0xb9, 0xfc, 0x08, 0xf8, 0x1a, 0xc5, 0x4a, 0xe0, 0xe8, 0xc8,
- 0xb2, 0x58, 0x59, 0xb0, 0x8f, 0x01, 0x5d, 0xa3, 0xd6, 0x2f, 0xdc, 0x8d,
- 0x34, 0x2d, 0x96, 0x2d, 0x1e, 0xb1, 0x7b, 0x07, 0xe5, 0x8a, 0x73, 0x65,
- 0xa1, 0x5b, 0xf3, 0x44, 0xfe, 0xe2, 0xc5, 0x62, 0x2a, 0xce, 0xc5, 0xf2,
- 0x0b, 0xee, 0x8d, 0x14, 0x4b, 0x17, 0xf7, 0x7e, 0x66, 0x3f, 0x16, 0x2a,
- 0x4f, 0x59, 0xc9, 0xef, 0x16, 0x76, 0xb1, 0x77, 0xb1, 0x62, 0xff, 0xcf,
- 0xd3, 0x07, 0xfc, 0xdf, 0x09, 0x62, 0xff, 0xa1, 0xe9, 0x0c, 0xa7, 0xdc,
- 0x58, 0xbf, 0xd2, 0x52, 0x06, 0x60, 0x8b, 0x17, 0xb4, 0xd0, 0x58, 0xbf,
- 0xc3, 0xfe, 0x6f, 0xf9, 0xd2, 0xc5, 0x0d, 0x10, 0xba, 0x33, 0x21, 0xdb,
- 0xf7, 0x33, 0xda, 0x95, 0x8b, 0x79, 0x62, 0xff, 0xe2, 0x93, 0xb3, 0xfd,
- 0xbd, 0xf9, 0x58, 0xae, 0xcf, 0x50, 0x2e, 0x25, 0x52, 0x9f, 0x44, 0x05,
- 0xfb, 0x40, 0x78, 0x5f, 0xf0, 0xbc, 0x4f, 0x97, 0x36, 0xeb, 0x17, 0xf3,
- 0xc4, 0xdb, 0xf2, 0x0b, 0x17, 0xff, 0xfc, 0x31, 0xe4, 0x74, 0xeb, 0x08,
- 0x7f, 0x93, 0x00, 0x09, 0xed, 0x62, 0xb7, 0x45, 0x9f, 0xc6, 0x18, 0xc2,
- 0xff, 0xe9, 0x72, 0xcf, 0x72, 0x7e, 0xc7, 0x58, 0xbf, 0xe2, 0xce, 0x71,
- 0xff, 0x9e, 0x58, 0xad, 0x1f, 0xd7, 0x44, 0x2b, 0xff, 0xf9, 0xc8, 0x7a,
- 0xcd, 0xff, 0x3f, 0xcd, 0x6a, 0x4d, 0x58, 0xbf, 0xfd, 0x20, 0xe7, 0x5f,
- 0x43, 0x23, 0xd8, 0x80, 0xb1, 0x5f, 0x45, 0x59, 0x2e, 0x5c, 0x61, 0xd6,
- 0x2f, 0xc2, 0x08, 0xf8, 0x75, 0x8b, 0xf6, 0x7b, 0xd3, 0x12, 0xc5, 0xfb,
- 0xcc, 0x77, 0xf2, 0xc5, 0x1a, 0x7f, 0x7a, 0x2a, 0x22, 0x9a, 0x58, 0xbe,
- 0x9c, 0x83, 0x2c, 0x51, 0xcd, 0x6f, 0xc3, 0x2e, 0x3f, 0x96, 0x2f, 0xe8,
- 0x7f, 0x1e, 0x1c, 0x58, 0xbf, 0x9f, 0xc2, 0xd3, 0x73, 0xa9, 0xe3, 0x60,
- 0xc5, 0x4a, 0x61, 0x03, 0x5c, 0x66, 0x7b, 0xfc, 0xf8, 0x72, 0xcd, 0x99,
- 0x62, 0xff, 0x71, 0xfa, 0x0e, 0x41, 0xb2, 0xc5, 0x61, 0xf4, 0xb1, 0x95,
- 0xff, 0xb2, 0x0c, 0x40, 0xea, 0x1e, 0x7d, 0x62, 0xfb, 0xdc, 0x00, 0x96,
- 0x2f, 0x39, 0xfc, 0xb1, 0x78, 0x8c, 0xf2, 0xc5, 0xf8, 0x43, 0x62, 0x07,
- 0x53, 0x76, 0xc3, 0xb7, 0xf0, 0x35, 0x22, 0x0b, 0xe2, 0xc5, 0xfd, 0xa9,
- 0x0d, 0xbf, 0xc5, 0x8b, 0xf8, 0x1c, 0x78, 0x9c, 0x35, 0x8a, 0x94, 0x48,
- 0xe1, 0x93, 0x17, 0xdb, 0xb5, 0x8a, 0x94, 0xdb, 0xa0, 0xbe, 0x50, 0xcf,
- 0xe1, 0x6d, 0xfb, 0xb6, 0x1f, 0xf1, 0x62, 0xf8, 0x78, 0x78, 0xe5, 0x8b,
- 0xfb, 0xef, 0xe2, 0x93, 0xac, 0x5f, 0x4f, 0x42, 0x95, 0x8b, 0xcd, 0x0c,
- 0x58, 0xa9, 0x45, 0xdb, 0x94, 0xc4, 0x4c, 0x72, 0xd2, 0x23, 0xa8, 0xdd,
- 0x96, 0xb7, 0x30, 0xc0, 0x84, 0x21, 0x46, 0x41, 0x92, 0x81, 0x77, 0x8c,
- 0x3d, 0xe1, 0x55, 0x14, 0x33, 0xce, 0x45, 0xf8, 0xe7, 0x0a, 0x13, 0x1c,
- 0x20, 0xf4, 0x75, 0xe2, 0x87, 0xe5, 0xfe, 0xd4, 0xf0, 0xd0, 0x34, 0x4b,
- 0x17, 0xff, 0x71, 0xbd, 0xfc, 0xe9, 0xf6, 0x16, 0xcb, 0x17, 0xff, 0xf6,
- 0x47, 0xb1, 0x03, 0xae, 0x84, 0x6e, 0x42, 0x4b, 0x75, 0x8b, 0xff, 0xe6,
- 0x38, 0xff, 0x3f, 0x93, 0x8b, 0xb8, 0x71, 0x62, 0xff, 0xf6, 0x7b, 0xef,
- 0x9d, 0xfb, 0x3a, 0x4f, 0x16, 0x2d, 0xff, 0xa2, 0x78, 0x94, 0xaf, 0x9b,
- 0x9e, 0xd9, 0x62, 0xfc, 0xec, 0x0e, 0xbe, 0x58, 0xbf, 0xf9, 0x8b, 0xf2,
- 0xe3, 0x7e, 0x64, 0x16, 0x2e, 0x67, 0x58, 0xb1, 0x8b, 0x14, 0xe6, 0xa4,
- 0x02, 0xd7, 0xf0, 0x39, 0xf9, 0x2f, 0x2c, 0x54, 0x9e, 0x73, 0x10, 0x5f,
- 0xd9, 0xd3, 0xee, 0x08, 0x96, 0x2a, 0x55, 0x7e, 0xec, 0x6d, 0x04, 0x8c,
- 0x87, 0xf9, 0xa5, 0x1f, 0x24, 0x62, 0xa2, 0x85, 0xcf, 0x08, 0x2e, 0x29,
- 0x58, 0xbe, 0xfc, 0xf2, 0x56, 0x2f, 0x18, 0x3c, 0x58, 0xbc, 0x17, 0xe4,
- 0x6c, 0xb1, 0x5b, 0x1f, 0xe8, 0xc5, 0x98, 0x8b, 0x83, 0xd7, 0xb8, 0xfc,
- 0x58, 0xbc, 0x7e, 0xbb, 0xac, 0x5f, 0xff, 0x44, 0x60, 0x48, 0x16, 0x0f,
- 0x03, 0xd6, 0x6c, 0xb1, 0x5d, 0x4f, 0xdd, 0x88, 0x6f, 0xed, 0xa2, 0x84,
- 0x6d, 0xad, 0x96, 0x2f, 0x66, 0xe3, 0x58, 0xbe, 0xf6, 0x10, 0x16, 0x2f,
- 0xe6, 0x0e, 0x7d, 0x9b, 0x2c, 0x5f, 0xd9, 0xad, 0x4c, 0x8d, 0x62, 0xa3,
- 0x74, 0x6a, 0x61, 0xc3, 0x8f, 0x11, 0x14, 0x71, 0x7d, 0xff, 0xdb, 0x7f,
- 0x06, 0x37, 0xef, 0x3b, 0xf2, 0xc5, 0xf6, 0xc6, 0x0b, 0x65, 0x8b, 0xe8,
- 0xa1, 0x3b, 0x2c, 0x54, 0x9e, 0x66, 0x13, 0xde, 0xfb, 0x1a, 0xb1, 0x7f,
- 0x8b, 0x62, 0xc1, 0x4f, 0x16, 0x29, 0x62, 0xf8, 0x06, 0x14, 0x16, 0x2c,
- 0xf2, 0x6c, 0x3c, 0x19, 0x7c, 0x59, 0xfc, 0x58, 0xbe, 0x0e, 0x2e, 0x4a,
- 0xc5, 0xe9, 0x3e, 0x2c, 0x5c, 0x09, 0x58, 0xa7, 0x36, 0x60, 0x1c, 0xbe,
- 0x29, 0x6d, 0xd6, 0x2f, 0xd2, 0x6e, 0x7b, 0x8b, 0x17, 0xff, 0xf6, 0x13,
- 0x8f, 0x99, 0xce, 0x67, 0xdf, 0x82, 0xd9, 0x62, 0xfe, 0x1e, 0x9b, 0xdf,
- 0x12, 0xc5, 0xcd, 0xe8, 0x22, 0x2b, 0x8b, 0x77, 0xf3, 0xfc, 0x47, 0x3b,
- 0xac, 0x5f, 0xfc, 0x28, 0x67, 0x3a, 0xf9, 0xe3, 0xb3, 0x65, 0x8a, 0x81,
- 0xfc, 0x91, 0x75, 0xf6, 0x43, 0x09, 0x62, 0x9c, 0xf0, 0x80, 0x43, 0x52,
- 0xaf, 0x4b, 0x68, 0x4a, 0x0c, 0x83, 0x07, 0x8d, 0x63, 0xdc, 0x97, 0xb2,
- 0x1d, 0x2c, 0x1c, 0x83, 0xe4, 0x45, 0x0b, 0x3f, 0x43, 0xa6, 0xf8, 0xbd,
- 0x20, 0x58, 0xb4, 0x64, 0x6e, 0xf9, 0x51, 0xc1, 0x42, 0x50, 0xac, 0x2e,
- 0xe3, 0x42, 0xe8, 0xd8, 0xa8, 0x2d, 0xa4, 0x85, 0xa9, 0x4c, 0x6a, 0x40,
- 0x99, 0xc0, 0x2d, 0xa3, 0x3f, 0x84, 0x2a, 0x07, 0x2c, 0x0b, 0x29, 0x0c,
- 0x06, 0xc7, 0x3f, 0xbc, 0xaf, 0x1e, 0xe3, 0x1d, 0x79, 0x41, 0x71, 0x4b,
- 0x48, 0xd4, 0xae, 0x13, 0xca, 0x49, 0xfc, 0xeb, 0x43, 0x4a, 0xbb, 0x04,
- 0xa4, 0x60, 0xbc, 0x24, 0x4a, 0x73, 0x0b, 0x94, 0xbb, 0x3f, 0x4b, 0xfa,
- 0x14, 0x60, 0xbd, 0x0f, 0x03, 0x84, 0xa4, 0x74, 0x3d, 0xcc, 0x9c, 0x21,
- 0x09, 0x0b, 0x7b, 0xff, 0xe0, 0xac, 0x6e, 0x15, 0x73, 0x3f, 0x9d, 0xc3,
- 0x02, 0x71, 0x62, 0xe1, 0x79, 0x62, 0xfe, 0x7f, 0x66, 0xbd, 0x2b, 0x17,
- 0x6a, 0x56, 0x2a, 0x3c, 0xf7, 0x22, 0x18, 0x08, 0x5b, 0x7e, 0xc0, 0xf3,
- 0xec, 0xb1, 0x7f, 0x3e, 0xc6, 0x6d, 0x3b, 0x2c, 0x5f, 0xfe, 0xf3, 0xfc,
- 0x5f, 0x67, 0xef, 0x92, 0x6a, 0xc5, 0xff, 0xe7, 0xee, 0x1c, 0x7f, 0x7e,
- 0x75, 0xe9, 0x58, 0xbf, 0x81, 0xc9, 0x8f, 0xd4, 0xac, 0x56, 0x23, 0x23,
- 0x49, 0x8c, 0x97, 0x7f, 0xa7, 0x4d, 0x13, 0x72, 0x0b, 0x17, 0x99, 0xb7,
- 0x54, 0x55, 0xc5, 0xfc, 0xc6, 0x7f, 0xec, 0x75, 0x8a, 0xdc, 0xf6, 0x7e,
- 0x55, 0x7f, 0x3e, 0xbe, 0xc6, 0x1d, 0x62, 0xf9, 0xfd, 0x09, 0x58, 0xa1,
- 0xa6, 0x03, 0xa8, 0x46, 0xfc, 0x8f, 0xa1, 0x7d, 0xff, 0xcd, 0xec, 0xd8,
- 0xb0, 0x7f, 0xc8, 0x96, 0x2f, 0xfa, 0x7b, 0x2c, 0x1f, 0xf2, 0x25, 0x8a,
- 0xf9, 0xff, 0x84, 0x45, 0xbf, 0xf9, 0xbd, 0x9b, 0x16, 0x0f, 0xf9, 0x12,
- 0xc5, 0xff, 0x4f, 0x65, 0x83, 0xfe, 0x44, 0xb1, 0x7f, 0xfa, 0x42, 0x70,
- 0x98, 0xa4, 0xcd, 0xe4, 0xfd, 0x51, 0x47, 0xf2, 0x40, 0x88, 0xb7, 0xc4,
- 0x13, 0x8c, 0xb1, 0x7c, 0x59, 0x14, 0xac, 0x5f, 0xff, 0xbe, 0xc5, 0xe8,
- 0xb3, 0x59, 0xd7, 0x37, 0xcf, 0x2c, 0x5a, 0x3d, 0x62, 0xff, 0xf4, 0xed,
- 0xe7, 0x1e, 0x14, 0x1f, 0xe2, 0x58, 0xbe, 0xee, 0x28, 0x89, 0x62, 0xb1,
- 0x1f, 0xee, 0x44, 0x75, 0x8f, 0x8a, 0xb2, 0x55, 0xd2, 0x75, 0x8b, 0xb8,
- 0x35, 0x8a, 0xd1, 0xaf, 0x61, 0x7b, 0xf9, 0xa0, 0xfd, 0x35, 0x2b, 0x17,
- 0xef, 0x49, 0x48, 0x16, 0x2f, 0xfe, 0xf1, 0x48, 0x25, 0x87, 0x2f, 0x12,
- 0xc5, 0xa7, 0x47, 0xd4, 0x72, 0x7b, 0xed, 0xd9, 0xb7, 0x54, 0x47, 0x85,
- 0xf0, 0xa1, 0x9c, 0x58, 0xba, 0x33, 0x34, 0x7a, 0x84, 0x63, 0x7e, 0xfb,
- 0xeb, 0xec, 0xb1, 0x78, 0xbc, 0xcb, 0x17, 0x60, 0xf0, 0xf1, 0x38, 0x51,
- 0x50, 0x44, 0xf9, 0xdc, 0xef, 0xe9, 0xd6, 0xd3, 0xad, 0x96, 0x2f, 0xfb,
- 0xa1, 0x9f, 0x68, 0x81, 0x91, 0x2c, 0x54, 0x0f, 0xbf, 0xc6, 0x17, 0xff,
- 0xf1, 0x60, 0x4e, 0x75, 0xe0, 0x3a, 0x75, 0x6e, 0x43, 0x4c, 0xb1, 0x7f,
- 0x37, 0xe4, 0xa4, 0x0b, 0x15, 0xd1, 0x12, 0x11, 0xcc, 0x97, 0xff, 0x6d,
- 0x3a, 0xdf, 0x39, 0xcc, 0x1e, 0x2c, 0x54, 0xa6, 0x41, 0x90, 0xb2, 0x62,
- 0x8b, 0xf4, 0x8f, 0x81, 0x22, 0x58, 0xbf, 0xce, 0x20, 0xbe, 0x43, 0x68,
- 0x96, 0x2b, 0x63, 0xe6, 0xf1, 0x65, 0xff, 0xff, 0x68, 0xb3, 0x6e, 0xa5,
- 0x9d, 0x0b, 0x02, 0x73, 0xaf, 0x01, 0xd1, 0x62, 0xff, 0xb3, 0xdc, 0x33,
- 0x9d, 0x77, 0x82, 0xc5, 0xfc, 0x59, 0xee, 0x60, 0x6b, 0x17, 0xff, 0xfc,
- 0xc5, 0xb0, 0xff, 0x3c, 0xce, 0xf9, 0x3a, 0xf7, 0x33, 0x65, 0x8a, 0x94,
- 0xda, 0xb0, 0x8c, 0xee, 0x2c, 0x7e, 0x19, 0x75, 0xfe, 0xdd, 0xf9, 0xf7,
- 0xf3, 0xac, 0x5f, 0x87, 0x3e, 0x91, 0xac, 0x5f, 0xb3, 0x66, 0x2e, 0xd6,
- 0x2b, 0xb4, 0x42, 0xb9, 0xa1, 0x14, 0x5e, 0xf0, 0x5b, 0xc5, 0x8b, 0xfc,
- 0x36, 0xe0, 0x27, 0xb2, 0x58, 0xbe, 0xf6, 0x10, 0x16, 0x2b, 0xb3, 0xd6,
- 0xf1, 0xa5, 0xfe, 0x08, 0xc3, 0x9c, 0x1b, 0xac, 0x5a, 0x32, 0x37, 0x67,
- 0x06, 0xcc, 0x2f, 0xb6, 0x35, 0x81, 0x40, 0xe1, 0xf5, 0x91, 0x97, 0xef,
- 0x1b, 0x3b, 0xba, 0x45, 0x19, 0x1e, 0x9d, 0x8e, 0x41, 0xf8, 0x4c, 0xb4,
- 0x63, 0x45, 0x1d, 0x97, 0x25, 0x01, 0xfa, 0x19, 0xdd, 0x0b, 0xcc, 0x79,
- 0x08, 0x47, 0x7b, 0xec, 0x75, 0x8b, 0xed, 0xd9, 0xb7, 0x54, 0x58, 0x25,
- 0x86, 0xb1, 0x5a, 0x3c, 0x3f, 0x98, 0xde, 0x36, 0x76, 0x58, 0xbd, 0x9d,
- 0x31, 0x62, 0xc7, 0x58, 0xb9, 0xf4, 0x46, 0xc0, 0x43, 0xd7, 0xff, 0xe1,
- 0x36, 0xc7, 0xc8, 0xe1, 0x6b, 0x35, 0x03, 0x20, 0xb1, 0x5f, 0x44, 0x39,
- 0x15, 0xdc, 0x6f, 0x96, 0x2f, 0xd8, 0x59, 0xee, 0x2c, 0x5f, 0xb3, 0x82,
- 0x6e, 0xd6, 0x2f, 0x0b, 0xb0, 0x2c, 0x5e, 0xf0, 0xd9, 0x62, 0xf1, 0xcc,
- 0x3a, 0xc5, 0xfc, 0xc7, 0x33, 0x4d, 0xda, 0xc5, 0xff, 0xff, 0xf9, 0xe1,
- 0xb9, 0x09, 0xb6, 0x3e, 0x47, 0x0b, 0x51, 0x42, 0x7b, 0xcd, 0x40, 0xc8,
- 0x2c, 0x56, 0x91, 0x79, 0xe3, 0x0b, 0x46, 0x4a, 0xb1, 0xdc, 0x60, 0x34,
- 0x8b, 0x78, 0x6b, 0x68, 0x89, 0x86, 0x48, 0x9f, 0x85, 0x22, 0x1f, 0x8e,
- 0x1d, 0x32, 0x1b, 0x77, 0xfa, 0x33, 0x35, 0xbb, 0x36, 0xea, 0x8b, 0x28,
- 0xbf, 0xf6, 0x7a, 0x18, 0x08, 0xec, 0xf8, 0x96, 0x2f, 0x1a, 0xc4, 0xb1,
- 0x7f, 0xfb, 0x18, 0x7f, 0xcd, 0x6a, 0x7a, 0x1b, 0x2b, 0x17, 0xdb, 0xb3,
- 0x6e, 0xa8, 0xb4, 0xca, 0x35, 0x13, 0x51, 0xe3, 0xba, 0x4c, 0xbd, 0x22,
- 0xed, 0x62, 0xfb, 0x36, 0x70, 0xd6, 0x2b, 0xe7, 0x84, 0x43, 0xd7, 0xfc,
- 0xda, 0xf8, 0x8c, 0xfb, 0x71, 0x62, 0xfd, 0x9b, 0xfb, 0x37, 0x58, 0xa8,
- 0x1f, 0x2e, 0x1d, 0xdf, 0xe1, 0xfd, 0xa2, 0xfb, 0x9d, 0x62, 0x96, 0x18,
- 0xda, 0xdf, 0xe9, 0x3e, 0x0c, 0xa7, 0xb5, 0x8b, 0xf0, 0xdc, 0x12, 0x4b,
- 0x17, 0xdc, 0x29, 0x02, 0xc5, 0xfe, 0xf4, 0x8d, 0xf5, 0x3d, 0x16, 0x2b,
- 0x0f, 0x5d, 0x88, 0xaf, 0xef, 0xb7, 0x27, 0x38, 0xb1, 0x43, 0x56, 0x8f,
- 0x90, 0xdc, 0xdd, 0xda, 0x28, 0x43, 0x1d, 0x5b, 0xe3, 0x6c, 0x66, 0x4f,
- 0xdc, 0x20, 0xbf, 0xff, 0x8f, 0x18, 0xdc, 0xe3, 0x13, 0x16, 0x6c, 0x79,
- 0xdd, 0x62, 0xa3, 0x11, 0xcf, 0x90, 0x89, 0xbf, 0xc1, 0x64, 0x6e, 0x15,
- 0xc3, 0xbf, 0x96, 0x2f, 0xc1, 0x48, 0xdc, 0x2c, 0x0b, 0x02, 0xc5, 0x8b,
- 0xe0, 0xb2, 0x37, 0x8d, 0xe3, 0x45, 0x8a, 0x0a, 0x1f, 0xd0, 0x5b, 0x42,
- 0xbf, 0x46, 0x9e, 0x6f, 0xe2, 0xc5, 0xe0, 0x67, 0x16, 0x2f, 0xf7, 0xdc,
- 0x31, 0xb3, 0x6e, 0xb1, 0x41, 0x53, 0xd2, 0x8d, 0x87, 0x6f, 0x69, 0xb7,
- 0x58, 0xbd, 0xf7, 0x89, 0x62, 0xfc, 0xdd, 0xf8, 0x52, 0xb1, 0x43, 0x3e,
- 0x57, 0x1e, 0x21, 0xeb, 0xf0, 0xd8, 0x9b, 0x75, 0x8a, 0x0a, 0x9e, 0xa8,
- 0x5a, 0x96, 0xdf, 0xd2, 0x7c, 0xfb, 0xc1, 0x62, 0xfc, 0x16, 0xc2, 0xbc,
- 0xc9, 0x58, 0xbf, 0xdd, 0x62, 0x7f, 0x90, 0xbc, 0xb1, 0x4b, 0x17, 0xf0,
- 0x5a, 0xb7, 0xdc, 0x24, 0xac, 0x46, 0xc4, 0xca, 0x0b, 0x11, 0x18, 0x16,
- 0xa8, 0x77, 0xf8, 0xc3, 0xe7, 0xb8, 0xfc, 0x58, 0xb3, 0xac, 0x54, 0x6c,
- 0x78, 0xd1, 0xc6, 0xb7, 0xf0, 0x55, 0xf7, 0x9e, 0xf8, 0xb1, 0x7f, 0xa7,
- 0x6d, 0x30, 0xf6, 0x65, 0x8b, 0xff, 0xf7, 0xd8, 0xbd, 0x0c, 0xd6, 0x49,
- 0x16, 0x79, 0x62, 0xa0, 0x88, 0x77, 0x35, 0xbf, 0xfe, 0x6d, 0x9b, 0xa7,
- 0x3a, 0xb7, 0x4d, 0xfe, 0xfa, 0x58, 0xbf, 0x74, 0x61, 0xe1, 0xd6, 0x2f,
- 0xee, 0x36, 0xc5, 0x3b, 0x2c, 0x5f, 0x30, 0x23, 0xb1, 0x62, 0xff, 0xb9,
- 0x3f, 0x91, 0xfd, 0x8d, 0x58, 0xae, 0xa7, 0xbf, 0xe2, 0x5b, 0xb3, 0xa2,
- 0xc5, 0xb9, 0x26, 0xf4, 0x89, 0x2f, 0xec, 0xf4, 0x94, 0xc4, 0xb1, 0x7c,
- 0xe1, 0x27, 0x8b, 0x17, 0xe7, 0x09, 0x24, 0xeb, 0x17, 0xa7, 0xdc, 0x58,
- 0xa3, 0x9e, 0x29, 0x14, 0x5e, 0x08, 0x39, 0x58, 0xa7, 0x3c, 0x01, 0x10,
- 0xdf, 0xa4, 0xb7, 0xfc, 0xac, 0x5f, 0xff, 0xc7, 0x9e, 0xf9, 0xd6, 0x5f,
- 0x93, 0xee, 0x4f, 0xe5, 0x62, 0xff, 0xec, 0xf7, 0xdc, 0xf9, 0xee, 0x19,
- 0xc5, 0x8b, 0xff, 0x63, 0x02, 0x61, 0xa9, 0xc2, 0x58, 0xa9, 0x46, 0xfe,
- 0xeb, 0xae, 0x8d, 0x7c, 0xfd, 0x3f, 0xd1, 0x62, 0xfb, 0x92, 0x51, 0x2c,
- 0x5f, 0x48, 0x48, 0xb1, 0x62, 0x98, 0xf2, 0x08, 0x8e, 0xff, 0xf0, 0xe4,
- 0xde, 0xb2, 0xfa, 0x9f, 0x4f, 0xd6, 0x2f, 0xdb, 0xb1, 0x49, 0x8b, 0x15,
- 0x87, 0xeb, 0xf4, 0xcb, 0xff, 0xa2, 0x32, 0x76, 0xeb, 0x3f, 0xcd, 0x62,
- 0xc5, 0x61, 0xf5, 0x31, 0x0d, 0xfe, 0x08, 0xe0, 0xea, 0xdf, 0x12, 0xc5,
- 0x41, 0x76, 0x1c, 0x64, 0x58, 0xb1, 0xd9, 0x53, 0xc3, 0x2e, 0x22, 0x53,
- 0x96, 0xfe, 0x15, 0x20, 0x21, 0x28, 0xc1, 0xf8, 0x5f, 0xe6, 0xfe, 0x90,
- 0xff, 0x08, 0x41, 0x7f, 0xfb, 0x3a, 0xcf, 0x46, 0xd7, 0x27, 0x4f, 0xc5,
- 0x8b, 0xbb, 0x89, 0x62, 0xff, 0x8b, 0x06, 0x53, 0xbc, 0xe9, 0x62, 0xff,
- 0xff, 0xb9, 0x18, 0xf1, 0x3f, 0xca, 0x74, 0xc0, 0x67, 0x1c, 0x92, 0xc5,
- 0x44, 0x98, 0x31, 0xd3, 0x58, 0x68, 0x07, 0x17, 0xf8, 0xe6, 0x1c, 0x07,
- 0x70, 0x2c, 0x5f, 0xba, 0xeb, 0x42, 0xfa, 0xc5, 0xf9, 0xcd, 0x92, 0xdd,
- 0x62, 0xb8, 0x7a, 0xbe, 0x2c, 0xbf, 0xde, 0xe4, 0xc4, 0xcd, 0xa5, 0x8a,
- 0x94, 0x70, 0xe4, 0x22, 0xdc, 0x8a, 0xf3, 0xe6, 0xcb, 0x17, 0xff, 0xb7,
- 0xfb, 0xfd, 0xf5, 0x31, 0x07, 0x9f, 0x58, 0xaf, 0x9f, 0x51, 0x0e, 0xdf,
- 0x9b, 0xb8, 0x67, 0x96, 0x2f, 0x00, 0xb1, 0x62, 0xe2, 0xc5, 0x8a, 0xea,
- 0x6c, 0x80, 0x39, 0x78, 0xf3, 0xa5, 0x8b, 0xfe, 0x7e, 0xbf, 0x6d, 0x4f,
- 0x49, 0x58, 0xa9, 0x3d, 0x9e, 0x0e, 0xdf, 0xf1, 0xda, 0x11, 0xc2, 0xfb,
- 0xe9, 0x62, 0xb6, 0x46, 0xd6, 0x9f, 0x0e, 0x43, 0x7e, 0x6e, 0x7a, 0x46,
- 0xb1, 0x52, 0x7b, 0x22, 0x31, 0xbf, 0xcc, 0x19, 0x83, 0x1e, 0x06, 0xb1,
- 0x7f, 0x9b, 0x50, 0x6f, 0x36, 0xeb, 0x17, 0xff, 0xb3, 0x0b, 0x00, 0x59,
- 0xef, 0xe4, 0x16, 0x2a, 0x55, 0x41, 0x68, 0x87, 0xf1, 0xc7, 0x31, 0x08,
- 0x8d, 0xc2, 0x1a, 0x5e, 0x36, 0x60, 0xb1, 0x76, 0xff, 0x58, 0xbf, 0x74,
- 0x2c, 0xe7, 0x5c, 0x36, 0xfe, 0x1e, 0xbf, 0xf8, 0xe4, 0xc6, 0x96, 0x03,
- 0x6c, 0x0d, 0x62, 0xff, 0xf1, 0x61, 0xbf, 0x68, 0x7c, 0x36, 0x30, 0xeb,
- 0x15, 0x28, 0x93, 0xc4, 0x6a, 0x74, 0x7a, 0x7e, 0x1a, 0x77, 0xf4, 0x97,
- 0x86, 0x52, 0xb1, 0x7d, 0x0e, 0x1e, 0x0b, 0x17, 0xf6, 0xb3, 0x40, 0x04,
- 0xac, 0x54, 0x9e, 0x93, 0x92, 0x5f, 0x49, 0x93, 0xf5, 0x8b, 0x9f, 0x65,
- 0x8b, 0xcc, 0xdb, 0xaa, 0x2d, 0xc2, 0xe8, 0xb8, 0xb1, 0x73, 0xc4, 0xb1,
- 0x7c, 0xde, 0x68, 0x96, 0x2e, 0xf7, 0x38, 0x6e, 0xfa, 0x0c, 0x56, 0xc8,
- 0xc5, 0xdc, 0x61, 0xca, 0x8c, 0x54, 0xbf, 0x9f, 0xd1, 0x14, 0x8d, 0x62,
- 0xff, 0xb5, 0xf6, 0xcd, 0x6c, 0xfb, 0x2c, 0x5f, 0x7b, 0x99, 0xf5, 0x8a,
- 0x73, 0xde, 0x63, 0xbb, 0xe8, 0xa4, 0x78, 0xb1, 0x7f, 0x00, 0xf9, 0xc1,
- 0x12, 0xc5, 0xdd, 0x49, 0x62, 0xfe, 0xe3, 0xe7, 0x46, 0xd2, 0xc5, 0xfd,
- 0xc9, 0xd6, 0xb0, 0x35, 0x8a, 0x81, 0xfb, 0x9c, 0x67, 0xc5, 0xf4, 0xe8,
- 0xd4, 0x68, 0x52, 0xdf, 0xfb, 0x35, 0x85, 0xd7, 0xf9, 0xd8, 0x6b, 0x17,
- 0xe2, 0x03, 0x77, 0xc5, 0x8b, 0xfb, 0x3a, 0x3f, 0xce, 0xcb, 0x15, 0x28,
- 0x9a, 0x64, 0x22, 0x29, 0xbe, 0x98, 0xe7, 0x35, 0x62, 0xa0, 0xb9, 0x44,
- 0x32, 0x73, 0x5f, 0xbb, 0x20, 0xd4, 0x3a, 0x0e, 0x7f, 0xf8, 0x46, 0x31,
- 0x01, 0x43, 0xdf, 0x90, 0xc0, 0xf1, 0x6d, 0xff, 0x98, 0x64, 0xdd, 0x3f,
- 0x31, 0x71, 0x62, 0xff, 0x6f, 0xd5, 0xbe, 0x4c, 0x05, 0x8a, 0x58, 0xbd,
- 0x3b, 0x92, 0xc5, 0x78, 0xd4, 0xf4, 0x0c, 0xbf, 0x88, 0x11, 0x14, 0x9d,
- 0x62, 0x8d, 0x47, 0x8b, 0xa0, 0x9d, 0x7d, 0x88, 0xef, 0x1c, 0x9d, 0x62,
- 0xc4, 0xb1, 0x6d, 0xd6, 0x2f, 0xfb, 0xe2, 0x6e, 0x66, 0x11, 0xab, 0x17,
- 0xff, 0xe9, 0xdf, 0xae, 0x7d, 0xf5, 0x3f, 0xc2, 0x1c, 0xac, 0x5f, 0xb8,
- 0xdd, 0xb0, 0xd6, 0x2c, 0xe3, 0x45, 0xc1, 0xce, 0x7c, 0xad, 0x7f, 0x9a,
- 0x30, 0xb3, 0x69, 0x35, 0x62, 0xf6, 0x04, 0x75, 0x8a, 0x94, 0xe0, 0xb0,
- 0x71, 0xc4, 0x7f, 0x0c, 0xb2, 0x35, 0xe8, 0x6f, 0x7f, 0xd2, 0xc5, 0xfc,
- 0xc2, 0xdd, 0x62, 0xe8, 0x05, 0x56, 0x2f, 0xf1, 0x6c, 0x4d, 0xa6, 0x82,
- 0xc5, 0x49, 0xe7, 0x88, 0x72, 0xa0, 0x8a, 0x7e, 0x42, 0x1a, 0xff, 0x10,
- 0x8f, 0x3c, 0xf3, 0xac, 0x5f, 0xe7, 0x29, 0x3c, 0xf7, 0xc5, 0x8b, 0xf4,
- 0xeb, 0x58, 0x11, 0x62, 0xa5, 0x12, 0x11, 0x19, 0x91, 0x9d, 0xfe, 0x10,
- 0xcb, 0x3a, 0x34, 0x16, 0x2f, 0xff, 0xdf, 0x8b, 0xa9, 0xc5, 0xe7, 0xdb,
- 0x3c, 0x6e, 0x7d, 0x62, 0xfe, 0x29, 0x8a, 0x2c, 0x02, 0xc5, 0xff, 0xe9,
- 0xdb, 0xce, 0x3c, 0x28, 0x3f, 0xc4, 0xb1, 0x7f, 0x9f, 0xa6, 0x7d, 0x8b,
- 0x65, 0x8b, 0xb0, 0xeb, 0x15, 0x03, 0xcc, 0xe1, 0xad, 0x83, 0x58, 0xbd,
- 0x39, 0xa5, 0x8b, 0xfd, 0xf9, 0x83, 0xc7, 0x61, 0xd6, 0x2a, 0x07, 0xca,
- 0x31, 0x3e, 0x0e, 0x5f, 0xba, 0xf7, 0xc7, 0x35, 0x62, 0xb6, 0x3d, 0xce,
- 0xcb, 0xeb, 0xb4, 0xc1, 0xda, 0x1c, 0x77, 0xfe, 0xcf, 0xbe, 0x87, 0xf9,
- 0x2d, 0xd6, 0x2f, 0x87, 0x9c, 0x12, 0xc5, 0xff, 0x8b, 0x3d, 0xc9, 0xeb,
- 0xec, 0xdd, 0x62, 0xfb, 0xaf, 0xb0, 0x0b, 0x17, 0xff, 0x60, 0x1f, 0x51,
- 0x9f, 0xce, 0x92, 0x4b, 0x15, 0x04, 0xc4, 0x30, 0xfd, 0xc8, 0xfe, 0x83,
- 0xe2, 0x5b, 0xfd, 0xdc, 0x24, 0xbd, 0x80, 0x58, 0xbe, 0xe0, 0x1f, 0xcb,
- 0x15, 0x05, 0xc3, 0x6d, 0xcd, 0x5d, 0x73, 0xe5, 0xed, 0x1c, 0xef, 0x23,
- 0x39, 0x12, 0x49, 0x86, 0x97, 0xe6, 0xd7, 0xb3, 0xeb, 0x17, 0xd9, 0xc2,
- 0x95, 0x8b, 0xff, 0x38, 0x26, 0x03, 0xfc, 0x96, 0xeb, 0x15, 0x04, 0x44,
- 0x7c, 0xa3, 0xc4, 0x37, 0x88, 0x5b, 0xac, 0x5f, 0xa1, 0x9a, 0xce, 0x2c,
- 0x51, 0xcf, 0x1b, 0xc3, 0xd4, 0xb1, 0x78, 0x4d, 0xe5, 0x8b, 0x85, 0x2b,
- 0x15, 0x03, 0x69, 0xe1, 0xda, 0x58, 0xbe, 0xef, 0x77, 0xd2, 0xc5, 0xa3,
- 0x31, 0x12, 0x5d, 0xa0, 0x1c, 0x87, 0xc1, 0x97, 0xfe, 0xc2, 0xef, 0xd9,
- 0x98, 0x5b, 0x2c, 0x51, 0xd1, 0x09, 0xe4, 0x6b, 0xec, 0x19, 0x0d, 0x62,
- 0xa4, 0xf1, 0x7a, 0x11, 0xdf, 0xd9, 0xce, 0x31, 0x6e, 0xb1, 0x7f, 0xc5,
- 0xef, 0xb4, 0x04, 0xc6, 0x2c, 0x54, 0xaa, 0x7e, 0xc7, 0x67, 0x8d, 0xf7,
- 0x44, 0x6c, 0x5d, 0x62, 0x58, 0xbd, 0xa0, 0x92, 0xb1, 0x77, 0xba, 0x85,
- 0x86, 0xc2, 0x21, 0x1b, 0xcc, 0xfb, 0x2c, 0x56, 0x1e, 0x91, 0xa6, 0xb7,
- 0xe0, 0x8f, 0xd1, 0xb4, 0xb1, 0x71, 0x0d, 0x62, 0xce, 0xb1, 0x68, 0xe5,
- 0x8a, 0x01, 0xa6, 0xf0, 0x8d, 0x4a, 0x22, 0x86, 0x58, 0x47, 0xb7, 0xba,
- 0xc6, 0x91, 0xa2, 0xc5, 0xfd, 0x9a, 0xdd, 0x9b, 0x75, 0x45, 0x0e, 0x58,
- 0x6b, 0x17, 0xfd, 0xac, 0xf7, 0x58, 0x6d, 0xc7, 0x58, 0xba, 0x4c, 0x58,
- 0xb4, 0x23, 0x11, 0x47, 0xb1, 0xe6, 0x09, 0x11, 0xed, 0xfa, 0x1d, 0x7a,
- 0x1e, 0x56, 0x2d, 0x05, 0x8b, 0xf8, 0x5e, 0x29, 0xf7, 0x16, 0x29, 0xcf,
- 0x00, 0x02, 0x55, 0x2a, 0x9e, 0x9e, 0x15, 0x91, 0x17, 0x34, 0x33, 0x49,
- 0x14, 0x4d, 0xb7, 0xb4, 0x6e, 0xeb, 0x17, 0x61, 0xd6, 0x2f, 0x7b, 0x02,
- 0x2c, 0x5a, 0x77, 0x36, 0xde, 0x17, 0xa8, 0x1f, 0xe8, 0x15, 0xaf, 0xe2,
- 0xcf, 0x73, 0x06, 0xb1, 0x7d, 0x31, 0xe2, 0x95, 0x8b, 0xd1, 0x60, 0xd6,
- 0x2f, 0x45, 0x3e, 0x58, 0xa9, 0x37, 0x82, 0x1e, 0xad, 0x23, 0x40, 0xe4,
- 0x40, 0x2d, 0xe3, 0x0d, 0xc2, 0x31, 0x62, 0xf3, 0x47, 0x1a, 0xb1, 0x7e,
- 0xe3, 0x7f, 0x37, 0x58, 0xae, 0xcf, 0x8c, 0x03, 0x3c, 0x21, 0xbf, 0x44,
- 0xfd, 0x84, 0xc5, 0x8b, 0x1d, 0x62, 0xba, 0x9b, 0xe9, 0x2c, 0xbf, 0x61,
- 0x0f, 0xf2, 0xb1, 0x43, 0x3c, 0x90, 0xc8, 0xaf, 0x66, 0x99, 0x62, 0xff,
- 0xb2, 0x47, 0xf9, 0x09, 0x31, 0x2c, 0x5f, 0xe0, 0x3f, 0xff, 0x80, 0x65,
- 0x8a, 0xdd, 0x11, 0x47, 0x1c, 0x01, 0xdd, 0xff, 0xb3, 0xdc, 0xfe, 0x6b,
- 0x58, 0x1a, 0xc5, 0xff, 0x88, 0x23, 0x13, 0x1c, 0x78, 0x35, 0x8a, 0x95,
- 0x56, 0x99, 0x0a, 0x07, 0x85, 0xbb, 0x42, 0xb4, 0xc3, 0x10, 0x88, 0x17,
- 0xff, 0xc3, 0x7e, 0x9d, 0x79, 0xe6, 0xef, 0x87, 0x14, 0x16, 0x2f, 0xfb,
- 0xee, 0x71, 0xcf, 0x5f, 0x3a, 0xc5, 0xff, 0xfb, 0xf9, 0xa6, 0x89, 0xfe,
- 0x32, 0x91, 0x0f, 0x16, 0x2f, 0xf8, 0x40, 0x61, 0xfe, 0x4b, 0xa2, 0xc5,
- 0xff, 0x98, 0x72, 0x3f, 0xb9, 0x39, 0xd6, 0x2f, 0xfd, 0x06, 0xe7, 0x57,
- 0xee, 0x0d, 0xc5, 0x8b, 0xfe, 0x60, 0x75, 0xcf, 0x3e, 0xb1, 0x62, 0xff,
- 0x9b, 0x5c, 0x6f, 0xf2, 0x76, 0x58, 0xae, 0xd1, 0x6c, 0x48, 0x5d, 0x0e,
- 0xaf, 0xd3, 0xc6, 0xec, 0x0b, 0x17, 0xdf, 0x08, 0xfb, 0x2c, 0x5f, 0x61,
- 0xc2, 0xc8, 0xd4, 0xb1, 0x5b, 0x9f, 0xe8, 0x0a, 0x7c, 0x4d, 0x7f, 0x0b,
- 0x7c, 0xf1, 0x4a, 0xc5, 0xff, 0xe9, 0xe7, 0xe4, 0xbd, 0xd6, 0x2d, 0xff,
- 0x12, 0xc5, 0x70, 0xff, 0xba, 0x17, 0x56, 0x2b, 0x96, 0x75, 0x78, 0x8e,
- 0xf4, 0xaa, 0x73, 0xbf, 0xc3, 0xcc, 0xa1, 0x5f, 0xe8, 0x57, 0x5f, 0xfb,
- 0xbe, 0x75, 0xe9, 0x92, 0x31, 0x6c, 0xb1, 0x7b, 0xd9, 0xba, 0xc5, 0xd9,
- 0xba, 0xc5, 0xb3, 0xa9, 0xb6, 0xf0, 0xf5, 0xff, 0x7d, 0xb5, 0xdf, 0xa5,
- 0xf6, 0x58, 0xbf, 0x4b, 0x94, 0xf4, 0x58, 0xbd, 0xbf, 0xe2, 0x58, 0xbc,
- 0x5b, 0xf5, 0xdc, 0xf2, 0x22, 0x28, 0xa8, 0x22, 0xed, 0xa1, 0x07, 0x4c,
- 0x9c, 0x31, 0x3e, 0x0a, 0x1c, 0x77, 0xfa, 0x13, 0xad, 0xa7, 0x5b, 0x2c,
- 0x5f, 0x4b, 0x68, 0x0b, 0x17, 0xe7, 0xf9, 0x0b, 0xcb, 0x17, 0xfb, 0x77,
- 0xe6, 0x0d, 0xb7, 0x58, 0xbf, 0xbf, 0x84, 0xff, 0x12, 0xc5, 0x0d, 0x15,
- 0x91, 0x11, 0x7c, 0xa3, 0xc6, 0xb7, 0xed, 0xa7, 0xed, 0xe5, 0x8b, 0xf3,
- 0x73, 0xa6, 0x71, 0x62, 0xfc, 0xde, 0xeb, 0x32, 0xb1, 0x52, 0x9c, 0xe6,
- 0x43, 0x89, 0x8f, 0x80, 0x52, 0x22, 0xab, 0xf7, 0x5f, 0xe0, 0x19, 0x62,
- 0xff, 0x6a, 0x7e, 0xc3, 0x81, 0xd6, 0x2f, 0xf8, 0xef, 0xe8, 0xec, 0x26,
- 0x35, 0x62, 0xfd, 0xd7, 0x61, 0x6a, 0x0b, 0x17, 0xb3, 0x38, 0xb1, 0x7f,
- 0x41, 0xb5, 0x9d, 0xf9, 0x62, 0xfe, 0x1b, 0x1f, 0xee, 0x1a, 0xc5, 0x49,
- 0xef, 0x61, 0x7d, 0xff, 0x67, 0xb8, 0x67, 0x34, 0xdc, 0x58, 0xbf, 0xe9,
- 0xfb, 0x9a, 0xfb, 0x31, 0xd6, 0x2e, 0xdb, 0x65, 0x8b, 0xee, 0xa6, 0xe0,
- 0xd6, 0x28, 0x67, 0x80, 0x01, 0xab, 0xf3, 0xfb, 0x8c, 0xeb, 0x17, 0xfe,
- 0xc0, 0xdb, 0x46, 0xce, 0xf8, 0x75, 0x8b, 0xff, 0xef, 0xbf, 0x05, 0xb6,
- 0xff, 0x7f, 0x7b, 0x36, 0x58, 0xbf, 0x45, 0x86, 0xbe, 0x96, 0x2b, 0x0f,
- 0xf9, 0xd5, 0x2f, 0xfb, 0x40, 0xd3, 0x17, 0xb0, 0x0b, 0x17, 0xf4, 0xf5,
- 0x8b, 0x7f, 0xc4, 0xb1, 0x5b, 0x2b, 0xab, 0x19, 0x56, 0x1a, 0x39, 0xe4,
- 0x45, 0xba, 0x7a, 0x39, 0x07, 0xce, 0xd9, 0xe8, 0x04, 0x44, 0x4f, 0xc8,
- 0x5f, 0x88, 0x80, 0x21, 0xcd, 0xe3, 0x35, 0x05, 0x8b, 0xf8, 0xcf, 0x0a,
- 0x73, 0x65, 0x8b, 0xf8, 0x1f, 0x67, 0xf8, 0x96, 0x2f, 0x70, 0xa0, 0xb1,
- 0x50, 0x44, 0xd4, 0x43, 0xfa, 0x30, 0xf1, 0x75, 0xfb, 0x3a, 0x66, 0xa0,
- 0xb1, 0x4b, 0x17, 0xdb, 0x94, 0xf8, 0x8d, 0xb4, 0x71, 0x55, 0xf9, 0xb9,
- 0xcd, 0xb8, 0xb1, 0x7f, 0x31, 0x00, 0xc0, 0x71, 0x62, 0xfd, 0xe2, 0x60,
- 0x71, 0x62, 0xf7, 0x0e, 0xcb, 0x17, 0xf8, 0x8d, 0x33, 0xff, 0x17, 0x16,
- 0x28, 0xd4, 0x55, 0xf6, 0x5f, 0x11, 0x40, 0x87, 0x6f, 0xfe, 0x17, 0x3e,
- 0xd0, 0x92, 0x1e, 0x7d, 0x62, 0xff, 0x8c, 0x90, 0x45, 0x09, 0xd6, 0xcb,
- 0x17, 0xf1, 0x37, 0x8c, 0x9d, 0xd6, 0x28, 0xe7, 0xd8, 0x47, 0xb7, 0xc4,
- 0x0d, 0x80, 0xb1, 0x7f, 0xff, 0xa2, 0xe3, 0x8f, 0xac, 0x4e, 0x5d, 0x1a,
- 0x26, 0xf0, 0xa5, 0x62, 0xb1, 0x15, 0x8e, 0x42, 0xc4, 0x97, 0xff, 0x8b,
- 0xd2, 0x0f, 0xb1, 0x74, 0xce, 0xf8, 0xb1, 0x7b, 0x4d, 0xa5, 0x8a, 0x73,
- 0xe9, 0x89, 0x32, 0xff, 0x8c, 0x28, 0x67, 0x42, 0xce, 0x2c, 0x5f, 0xf1,
- 0xf9, 0xd7, 0x07, 0x25, 0xe5, 0x8b, 0xf4, 0x3a, 0xf3, 0x98, 0xb1, 0x7f,
- 0xb9, 0xd7, 0xdd, 0x47, 0x84, 0xb1, 0x60, 0x2c, 0x57, 0x67, 0x95, 0xa3,
- 0x8a, 0x94, 0x69, 0xe1, 0xdb, 0xba, 0xdf, 0xc2, 0xdf, 0xf3, 0xac, 0x58,
- 0xbe, 0xef, 0x9e, 0x75, 0x8a, 0xc3, 0xd3, 0x62, 0xfa, 0x95, 0xd8, 0x5c,
- 0x74, 0x34, 0xe9, 0xe1, 0xab, 0xa4, 0x0f, 0xc6, 0xb8, 0xd0, 0x96, 0x01,
- 0x11, 0x46, 0x1d, 0xc8, 0x40, 0x5f, 0xfd, 0x0c, 0x09, 0x0c, 0xf4, 0xfb,
- 0x98, 0xb1, 0x7f, 0xff, 0xf3, 0x3f, 0xa4, 0xb7, 0x73, 0x9d, 0xf9, 0xcc,
- 0xfb, 0xf0, 0x5b, 0x2c, 0x5b, 0xaf, 0x68, 0xb8, 0xfa, 0x35, 0xf9, 0x84,
- 0x6c, 0x98, 0xb1, 0x7d, 0x9a, 0x9e, 0x2c, 0x5e, 0xdc, 0x2b, 0xa5, 0x8a,
- 0x8d, 0x8f, 0x14, 0x44, 0x55, 0x88, 0xc2, 0x88, 0xb0, 0x9b, 0xef, 0xa2,
- 0x80, 0x8d, 0x58, 0xbf, 0xb3, 0xce, 0x3c, 0x3a, 0xc5, 0xf1, 0x41, 0xce,
- 0xb1, 0x6e, 0xb1, 0x1e, 0x7b, 0x16, 0xdf, 0xce, 0x5d, 0x1a, 0x20, 0xb5,
- 0x58, 0xbf, 0xa6, 0x2e, 0xe1, 0x9d, 0x16, 0x2a, 0x23, 0xe9, 0xe1, 0xbd,
- 0xc1, 0x48, 0xd1, 0x62, 0xa5, 0x34, 0xc1, 0xba, 0xb4, 0x24, 0xfc, 0x47,
- 0x77, 0x00, 0xb1, 0x7f, 0x43, 0x8c, 0x71, 0xf1, 0x62, 0xba, 0x9e, 0x3b,
- 0x0c, 0x52, 0xc5, 0x2c, 0x5b, 0x80, 0x2e, 0x38, 0x19, 0x7f, 0xfd, 0xf9,
- 0x32, 0x33, 0xc4, 0xc0, 0xe7, 0x24, 0x09, 0x17, 0x1b, 0x8b, 0x14, 0x33,
- 0xec, 0x35, 0x52, 0xe1, 0xe2, 0xc5, 0xfb, 0x69, 0xd9, 0xb8, 0xb1, 0x5d,
- 0x51, 0xed, 0x90, 0x92, 0x72, 0x36, 0x17, 0xbf, 0x82, 0x30, 0x0f, 0x3c,
- 0x58, 0xbf, 0x73, 0x3a, 0x7d, 0xd6, 0x2e, 0x90, 0x2c, 0x52, 0xc1, 0x85,
- 0xbd, 0x78, 0xf7, 0x44, 0x83, 0x5f, 0x45, 0x78, 0x21, 0x1b, 0x7f, 0x84,
- 0x5e, 0xea, 0x40, 0x02, 0xc5, 0xf7, 0x3a, 0x67, 0x16, 0x2f, 0xfd, 0xce,
- 0x8d, 0x16, 0xcc, 0x4d, 0x12, 0xc5, 0xff, 0xa4, 0x24, 0x4d, 0xd1, 0xbd,
- 0xd2, 0x56, 0x2f, 0xfd, 0x83, 0x98, 0x4e, 0x8f, 0xee, 0xd6, 0x2f, 0xe6,
- 0x04, 0x45, 0x23, 0x58, 0xbf, 0xe2, 0xcd, 0x87, 0xfc, 0x2f, 0x2c, 0x5e,
- 0xf3, 0xf1, 0x62, 0xfe, 0xd4, 0xf4, 0x92, 0xf2, 0xc5, 0xff, 0xd9, 0x0c,
- 0x2e, 0xbf, 0x98, 0x84, 0x35, 0x8a, 0x73, 0xf6, 0x01, 0x7d, 0x4a, 0xa6,
- 0x6d, 0x8a, 0x30, 0xda, 0x22, 0x5d, 0x21, 0x9d, 0x17, 0xe8, 0x04, 0x5d,
- 0xc3, 0x9f, 0x42, 0x4e, 0xa3, 0x77, 0xc7, 0x26, 0x0a, 0x42, 0xf0, 0x2a,
- 0x59, 0x1a, 0x3f, 0xc6, 0xd0, 0xe5, 0x0b, 0x65, 0xa1, 0x61, 0x68, 0x5a,
- 0xc2, 0xfa, 0x35, 0x3a, 0xc6, 0xb2, 0xa9, 0x9e, 0x42, 0xda, 0x3e, 0x08,
- 0x46, 0x3e, 0x39, 0x63, 0xd9, 0x3c, 0x58, 0x6c, 0x74, 0x1b, 0xc7, 0x7d,
- 0xdc, 0x60, 0x4f, 0x0b, 0x88, 0xa7, 0x19, 0x75, 0x2e, 0x18, 0xf2, 0xd2,
- 0xbf, 0x38, 0xc2, 0xd2, 0xff, 0x41, 0x28, 0x18, 0xa3, 0xd0, 0xe4, 0xbf,
- 0x8f, 0x4f, 0x72, 0x8a, 0x50, 0xff, 0x48, 0xde, 0xc3, 0x84, 0x44, 0x74,
- 0x66, 0x26, 0x4b, 0x56, 0xbf, 0xef, 0xb3, 0xc2, 0x7d, 0xcc, 0x58, 0xbe,
- 0x98, 0x37, 0x45, 0x8b, 0xfb, 0xdd, 0xf1, 0xc8, 0x6b, 0x17, 0xff, 0x6b,
- 0x3b, 0xdf, 0xef, 0xee, 0x37, 0x6b, 0x17, 0xe9, 0xe6, 0x84, 0x05, 0x8b,
- 0xff, 0xf8, 0xf9, 0xee, 0x19, 0xc2, 0xcf, 0x08, 0x07, 0x68, 0x2c, 0x5f,
- 0x60, 0xda, 0x0b, 0x17, 0x8c, 0x28, 0x2c, 0x53, 0x9e, 0x00, 0x08, 0xae,
- 0xde, 0x32, 0x53, 0xba, 0xd8, 0xe1, 0xc9, 0x00, 0x5e, 0x49, 0x1c, 0x29,
- 0xf4, 0x27, 0x6a, 0x31, 0x73, 0x50, 0x53, 0x8b, 0x97, 0xf9, 0xe3, 0x8c,
- 0xec, 0x1c, 0x95, 0x8b, 0xe9, 0xd4, 0x0e, 0xb1, 0x7f, 0xd1, 0x34, 0x94,
- 0xc4, 0x29, 0x58, 0xbd, 0xf7, 0x8f, 0x58, 0xbe, 0x8e, 0xcd, 0x4a, 0xc5,
- 0xee, 0x34, 0x7a, 0xc5, 0xbc, 0xb1, 0x58, 0x7a, 0xfd, 0x92, 0xc7, 0x10,
- 0x5f, 0xb0, 0x62, 0xf7, 0x16, 0x2f, 0xff, 0xc5, 0x90, 0xfc, 0xeb, 0x30,
- 0x8d, 0xd6, 0xa5, 0x62, 0xff, 0x37, 0xd8, 0xc3, 0xe7, 0x16, 0x2f, 0x36,
- 0x8d, 0x58, 0xb4, 0x64, 0xaa, 0x0d, 0xd8, 0xe7, 0x08, 0xf7, 0x39, 0x77,
- 0x72, 0x32, 0xe1, 0x4f, 0x45, 0x40, 0xcd, 0x2f, 0xf4, 0x66, 0x6b, 0x76,
- 0x6d, 0xd5, 0x17, 0x99, 0x53, 0x0b, 0x69, 0xe8, 0x42, 0x38, 0x71, 0xc3,
- 0x65, 0xe5, 0x8d, 0xf7, 0x58, 0x58, 0xea, 0x71, 0xac, 0xf0, 0xaf, 0xfc,
- 0xe3, 0x99, 0x5e, 0x61, 0x27, 0x25, 0x1f, 0x74, 0x84, 0x55, 0xfe, 0x8c,
- 0xcd, 0x6e, 0xcd, 0xba, 0xa2, 0x96, 0x2e, 0x8d, 0xe3, 0x52, 0xc5, 0xde,
- 0xd9, 0x62, 0xfc, 0xf1, 0x9c, 0xc7, 0x58, 0xbf, 0xff, 0x7f, 0x0b, 0x0d,
- 0xfb, 0x43, 0xe1, 0xb1, 0x87, 0x58, 0xbe, 0xdd, 0x9b, 0x75, 0x45, 0x84,
- 0x54, 0x11, 0x13, 0xa5, 0x8b, 0xef, 0x48, 0xf1, 0x62, 0xff, 0xfb, 0x08,
- 0x73, 0xf9, 0xef, 0xd8, 0x4c, 0x75, 0x8b, 0xc4, 0x2d, 0xd6, 0x2a, 0x4f,
- 0xb1, 0x93, 0xaf, 0xff, 0xef, 0x63, 0xeb, 0x9e, 0x27, 0x07, 0x27, 0xdc,
- 0x75, 0x8b, 0xd9, 0xe7, 0x58, 0xa5, 0x8a, 0x94, 0x41, 0x1d, 0x6b, 0x83,
- 0x97, 0xf0, 0xb4, 0xfb, 0x31, 0xd6, 0x2d, 0x19, 0x1a, 0x95, 0x50, 0x49,
- 0x18, 0xc6, 0x72, 0x16, 0x6e, 0x46, 0x78, 0x47, 0x72, 0x14, 0x51, 0xc5,
- 0xf7, 0xfa, 0x33, 0x35, 0xbb, 0x36, 0xea, 0x8b, 0x2c, 0xbf, 0xf0, 0x59,
- 0x1a, 0x64, 0x3f, 0x8f, 0x0e, 0x2c, 0x5d, 0x07, 0x58, 0xa5, 0x8b, 0x32,
- 0xc5, 0x49, 0x7a, 0x68, 0x65, 0xa0, 0xb1, 0x73, 0x1a, 0xb1, 0x63, 0x56,
- 0x2c, 0x6a, 0xc5, 0x49, 0xa6, 0xd0, 0x9d, 0xf4, 0x61, 0xb1, 0xa8, 0x28,
- 0xb1, 0x49, 0x17, 0xa3, 0x0c, 0x3a, 0xc5, 0x6e, 0x7c, 0x1c, 0x32, 0x10,
- 0x65, 0xf6, 0x69, 0x86, 0xb1, 0x43, 0x4d, 0x08, 0xd2, 0x07, 0x12, 0x23,
- 0xee, 0x42, 0x03, 0xc6, 0x17, 0x4f, 0xd6, 0x2c, 0x05, 0x8b, 0x8d, 0xd9,
- 0x62, 0xda, 0x81, 0xac, 0xc1, 0x2b, 0x79, 0x62, 0xb7, 0x3f, 0xb6, 0x43,
- 0xf1, 0x35, 0x2c, 0x52, 0xc3, 0x13, 0x2f, 0x40, 0xa5, 0x62, 0x80, 0x6d,
- 0x7c, 0x33, 0x6f, 0xac, 0x52, 0xc5, 0x40, 0xbe, 0x34, 0x4a, 0xc6, 0xac,
- 0x53, 0x9f, 0x98, 0x0f, 0xfc, 0x43, 0x7f, 0xfe, 0x1b, 0xfb, 0xf8, 0x37,
- 0xc1, 0xb6, 0xcc, 0x4b, 0x17, 0xfc, 0xdd, 0x96, 0x77, 0xe9, 0x35, 0x62,
- 0xff, 0x6d, 0xdf, 0x24, 0x7e, 0x75, 0x8b, 0xf4, 0xe7, 0x49, 0xe2, 0xc5,
- 0xa5, 0x8f, 0x7c, 0x33, 0x6b, 0xf8, 0x8d, 0x03, 0x7b, 0x8b, 0x17, 0x6a,
+ 0x2c, 0x5d, 0x3d, 0xcb, 0x17, 0x8b, 0x36, 0x58, 0xbe, 0xcd, 0x85, 0xd9,
+ 0x62, 0xd1, 0x83, 0x4c, 0x5b, 0x18, 0xcd, 0x21, 0x38, 0xc0, 0x07, 0x48,
+ 0x68, 0x31, 0xdb, 0xff, 0x7b, 0x23, 0xe3, 0x38, 0x0f, 0x7b, 0xa5, 0x8a,
+ 0x98, 0xea, 0xbe, 0xa0, 0x89, 0x99, 0xb1, 0xd9, 0x6e, 0xf3, 0xd4, 0x32,
+ 0xde, 0xd4, 0xf0, 0xea, 0x75, 0xc0, 0xf1, 0x81, 0x7e, 0x31, 0x46, 0x87,
+ 0x68, 0x27, 0xe7, 0x8a, 0x58, 0x4f, 0x27, 0x7e, 0xfd, 0x0c, 0x70, 0xe3,
+ 0x4d, 0xee, 0x6e, 0xb7, 0x96, 0x2f, 0xe6, 0xeb, 0x7f, 0xb6, 0x96, 0x2f,
+ 0xf9, 0x8b, 0x6e, 0x39, 0x75, 0x05, 0x8a, 0x23, 0xea, 0x08, 0xc2, 0xff,
+ 0xdb, 0x60, 0x5f, 0xce, 0x63, 0x92, 0xc5, 0xb8, 0xb1, 0x58, 0x7a, 0x20,
+ 0x3f, 0xbf, 0xf3, 0x91, 0x61, 0xbb, 0x89, 0x86, 0xb1, 0x7d, 0xf7, 0xd4,
+ 0x16, 0x2f, 0xd9, 0xf1, 0xb1, 0x2c, 0x5c, 0xf1, 0x87, 0x4e, 0x67, 0xef,
+ 0x84, 0xe7, 0xc2, 0x1f, 0x1f, 0x86, 0x47, 0x7e, 0xe7, 0x0e, 0xd0, 0x58,
+ 0xbe, 0xef, 0xe1, 0x0e, 0xfd, 0x62, 0xff, 0xfa, 0x4b, 0x6e, 0x09, 0x9e,
+ 0x1c, 0xfb, 0x41, 0x62, 0xb4, 0x7f, 0xdf, 0x2e, 0xba, 0x3e, 0x3d, 0x62,
+ 0xff, 0xfd, 0xf9, 0x2d, 0xb8, 0x26, 0x78, 0x73, 0xed, 0x05, 0x8b, 0xff,
+ 0xff, 0xf9, 0xe4, 0xbc, 0x4c, 0x6e, 0x78, 0x5e, 0x7f, 0x73, 0xef, 0xa9,
+ 0xd9, 0xb5, 0xba, 0xc5, 0xdf, 0x71, 0xa3, 0x7f, 0xea, 0xd7, 0xff, 0xf3,
+ 0x3f, 0xa7, 0xb1, 0x67, 0x3e, 0xd0, 0x1e, 0xbb, 0xf5, 0x8b, 0xff, 0xff,
+ 0x61, 0x36, 0x81, 0x1d, 0x81, 0x97, 0xbe, 0x26, 0x84, 0x83, 0x8b, 0x17,
+ 0x72, 0x56, 0x2f, 0xfe, 0xeb, 0x71, 0x37, 0x5e, 0xcc, 0x23, 0x56, 0x2f,
+ 0xee, 0xee, 0xe7, 0x8b, 0x92, 0xb1, 0x78, 0x9a, 0x32, 0x55, 0xac, 0x0e,
+ 0x14, 0xe6, 0x91, 0x6f, 0x0f, 0xdf, 0x97, 0x13, 0x0f, 0x1b, 0xfc, 0x2e,
+ 0x1a, 0x45, 0xfd, 0x1b, 0xc6, 0x93, 0xd6, 0xb6, 0x58, 0xbc, 0x71, 0x47,
+ 0xac, 0x5f, 0xe3, 0x64, 0xe3, 0x66, 0x09, 0x62, 0xfb, 0x36, 0x17, 0xd6,
+ 0x2e, 0x63, 0xac, 0x56, 0x8d, 0xd8, 0x89, 0x2f, 0x85, 0xdc, 0x39, 0x58,
+ 0xbf, 0xff, 0x70, 0x39, 0x1e, 0x4f, 0x9f, 0xb4, 0x8b, 0xbf, 0x95, 0x8b,
+ 0xf6, 0x77, 0x7a, 0x4d, 0x58, 0xb7, 0x72, 0xc5, 0x6c, 0x78, 0x38, 0x59,
+ 0x7d, 0xc7, 0xdf, 0x4b, 0x15, 0xb2, 0x77, 0x6e, 0x43, 0xa7, 0x0f, 0x90,
+ 0x80, 0x98, 0xa1, 0x3a, 0x11, 0x15, 0xff, 0xb8, 0xc6, 0xfd, 0xe4, 0x85,
+ 0x2b, 0x17, 0xfc, 0xde, 0x6f, 0xf5, 0x0c, 0xf2, 0xc5, 0xf8, 0x0d, 0xc1,
+ 0x4a, 0xc5, 0x7c, 0xf8, 0xbc, 0x75, 0x58, 0x8c, 0x27, 0x85, 0x05, 0xd0,
+ 0x65, 0x8b, 0x98, 0x0b, 0x17, 0xfd, 0x10, 0xd9, 0x82, 0xce, 0xbc, 0xb1,
+ 0x7f, 0xff, 0xf8, 0x98, 0x22, 0xcf, 0x7b, 0x36, 0x92, 0x63, 0x78, 0x79,
+ 0xc2, 0x1a, 0xc5, 0xff, 0x98, 0xa0, 0x60, 0xc4, 0xda, 0x82, 0xc5, 0xec,
+ 0x0f, 0x8b, 0x15, 0x29, 0x9f, 0x60, 0xbb, 0x8b, 0xe8, 0xf0, 0x27, 0x6e,
+ 0xe4, 0x0b, 0xcf, 0x17, 0x16, 0x2f, 0xe2, 0x90, 0x1d, 0xa0, 0xb1, 0x7f,
+ 0x14, 0x80, 0xed, 0x05, 0x8b, 0xfd, 0x1b, 0xc6, 0x85, 0x83, 0xf8, 0x96,
+ 0x2f, 0xd9, 0xda, 0x4b, 0xd8, 0x7d, 0x7c, 0x2d, 0xbf, 0x10, 0xb9, 0xf7,
+ 0x31, 0x1e, 0x98, 0x3d, 0xa8, 0x4c, 0x5f, 0x86, 0xfd, 0xb5, 0x8b, 0x16,
+ 0xfc, 0x9f, 0xde, 0x28, 0xdf, 0xe6, 0x86, 0xb2, 0x39, 0xc0, 0xb1, 0x7f,
+ 0xa4, 0xa7, 0x7e, 0x00, 0xeb, 0x17, 0xd3, 0x17, 0xdd, 0x62, 0xf3, 0x36,
+ 0xea, 0x91, 0x5c, 0xbf, 0xc6, 0xb1, 0x03, 0xd9, 0xf5, 0x8a, 0xd9, 0x10,
+ 0x3b, 0x91, 0xb9, 0x55, 0xef, 0xe6, 0xeb, 0x17, 0xd8, 0x01, 0x71, 0x62,
+ 0xe6, 0xeb, 0x0f, 0x04, 0x87, 0xaf, 0x9a, 0x0e, 0x05, 0x8b, 0xff, 0xff,
+ 0x82, 0xf1, 0xad, 0xcf, 0xee, 0xfc, 0xc1, 0xfa, 0x02, 0x1b, 0x10, 0x16,
+ 0x2f, 0xfa, 0x22, 0x60, 0xf0, 0x13, 0x05, 0x8b, 0xf3, 0x1a, 0xde, 0x82,
+ 0xc5, 0xff, 0xf7, 0x1d, 0xba, 0xfb, 0x3f, 0x85, 0xa6, 0xe2, 0xc5, 0x11,
+ 0xfc, 0xf8, 0xa6, 0x8d, 0x46, 0xa7, 0x50, 0xb3, 0xbf, 0xfb, 0xf9, 0x0d,
+ 0xfe, 0xe3, 0x92, 0xf2, 0xc5, 0x4a, 0x77, 0x2f, 0x1a, 0x57, 0x8a, 0xaf,
+ 0xff, 0xc7, 0xcf, 0x4f, 0xb9, 0x9a, 0x9c, 0x20, 0xce, 0xb1, 0x7f, 0xff,
+ 0xde, 0x7f, 0x73, 0xef, 0xf6, 0xe4, 0x50, 0x98, 0xfc, 0xeb, 0xcb, 0x15,
+ 0x28, 0xc1, 0x12, 0xad, 0x41, 0x72, 0x88, 0x64, 0xdb, 0x9b, 0x6a, 0x16,
+ 0xa7, 0x72, 0xf9, 0x61, 0x47, 0xb7, 0xe8, 0x7b, 0x5f, 0xfe, 0x66, 0x2c,
+ 0xf4, 0xeb, 0x85, 0xa3, 0xac, 0x5f, 0xfa, 0x01, 0xc3, 0x0b, 0xdb, 0x60,
+ 0xd6, 0x2f, 0xfd, 0xbb, 0xeb, 0x3e, 0xfa, 0xfb, 0x2c, 0x5f, 0xfc, 0x2e,
+ 0x7d, 0xa1, 0xe7, 0x62, 0x02, 0xc5, 0x74, 0x88, 0x3d, 0x1f, 0xdd, 0xf7,
+ 0x35, 0x33, 0x0d, 0x24, 0x7a, 0x18, 0x97, 0xb4, 0xfe, 0x58, 0xbf, 0x34,
+ 0x1b, 0xa8, 0x2c, 0x54, 0x47, 0x8d, 0xa1, 0xdb, 0xf1, 0x30, 0x41, 0x9d,
+ 0x62, 0xa4, 0xf3, 0x7c, 0x47, 0x7f, 0x42, 0x5c, 0x0e, 0x75, 0x8b, 0xff,
+ 0xfe, 0xce, 0xa1, 0x87, 0x72, 0x86, 0xa7, 0xec, 0xfe, 0x9f, 0xac, 0x5f,
+ 0x6d, 0xec, 0xfa, 0xc5, 0xff, 0xb4, 0x58, 0x37, 0x86, 0x75, 0xe5, 0x8a,
+ 0x93, 0xe3, 0x72, 0x4b, 0xfa, 0x4e, 0x3d, 0x36, 0xeb, 0x15, 0x04, 0xc5,
+ 0xff, 0x0c, 0x82, 0x20, 0xbf, 0xfb, 0xdf, 0xc8, 0x75, 0xed, 0x4e, 0x04,
+ 0xb1, 0x7f, 0xff, 0xe7, 0x07, 0x1b, 0xac, 0xfb, 0x8b, 0xbf, 0xcd, 0x67,
+ 0xf3, 0xb4, 0xac, 0x51, 0x22, 0xe7, 0xc8, 0xf7, 0xff, 0xff, 0x98, 0x83,
+ 0x90, 0x64, 0x3f, 0x3d, 0x87, 0x31, 0x98, 0x42, 0x86, 0x71, 0x62, 0xa5,
+ 0x13, 0xba, 0x22, 0xba, 0x1b, 0x2c, 0x5e, 0x68, 0x62, 0xc5, 0xe6, 0x8e,
+ 0x35, 0x62, 0xb7, 0x37, 0xa0, 0x1c, 0xbf, 0xff, 0xff, 0xff, 0x0d, 0x8e,
+ 0x76, 0x84, 0x24, 0x39, 0x1b, 0xe9, 0xba, 0x1f, 0xe7, 0x5c, 0x76, 0x62,
+ 0x9d, 0xff, 0x31, 0x2c, 0x5f, 0xc5, 0xe1, 0x7f, 0xbd, 0x95, 0x8b, 0x7a,
+ 0x51, 0xc8, 0xf0, 0xb1, 0xbf, 0xff, 0x8f, 0x9d, 0x7b, 0xed, 0xbb, 0x0f,
+ 0xdc, 0x27, 0x35, 0x62, 0xff, 0xe1, 0x6e, 0x58, 0x6f, 0xbc, 0xd0, 0xe2,
+ 0xc5, 0xfe, 0x93, 0xcc, 0x60, 0x41, 0x04, 0xb1, 0x4e, 0x98, 0x5b, 0x16,
+ 0x71, 0x7b, 0xb9, 0x1e, 0xb1, 0x52, 0x83, 0x4a, 0x11, 0xbf, 0xff, 0xff,
+ 0x77, 0x66, 0x9f, 0x66, 0x3e, 0xff, 0x7f, 0xbc, 0x97, 0xbe, 0xdb, 0xc9,
+ 0x0d, 0x62, 0xff, 0x76, 0xfe, 0x3f, 0xce, 0xcb, 0x17, 0xda, 0xd3, 0xec,
+ 0xb1, 0x4e, 0x7b, 0x20, 0x35, 0xa6, 0x4c, 0x00, 0xa1, 0xbf, 0x7f, 0xb3,
+ 0x5c, 0x6d, 0xc5, 0xd2, 0xc5, 0xff, 0xed, 0x7b, 0xcd, 0xb0, 0x67, 0x1f,
+ 0xdc, 0xd5, 0x8b, 0xff, 0x6d, 0x3b, 0x16, 0x7b, 0xd9, 0xb2, 0xc5, 0xdd,
+ 0x73, 0x11, 0x20, 0x1a, 0x7d, 0x62, 0x3d, 0x9a, 0x18, 0xd7, 0xfb, 0xac,
+ 0x7e, 0x70, 0x52, 0xb1, 0x7f, 0xec, 0xd4, 0x3c, 0xe3, 0xc2, 0x82, 0xc5,
+ 0x84, 0xb1, 0x73, 0xf6, 0x58, 0xbc, 0xf9, 0xa5, 0x8a, 0xf9, 0xb5, 0xf0,
+ 0xcd, 0xff, 0xfa, 0x40, 0x1c, 0x8c, 0x85, 0xe9, 0xe6, 0x75, 0xe5, 0x8b,
+ 0xcd, 0x0e, 0xf1, 0x62, 0xb6, 0x47, 0x0f, 0xd1, 0xc0, 0x43, 0xd9, 0x5e,
+ 0xff, 0xb1, 0xfb, 0x14, 0xe6, 0xa0, 0xb1, 0x7f, 0xfe, 0xf4, 0x32, 0x3d,
+ 0x88, 0x1d, 0x7b, 0x53, 0x81, 0x2c, 0x04, 0x6e, 0x6f, 0xbd, 0xf9, 0x02,
+ 0xc5, 0x80, 0xb1, 0x5d, 0x1b, 0x5d, 0x11, 0xd4, 0xaa, 0x5a, 0xc8, 0xc7,
+ 0xd9, 0xe4, 0x50, 0xa0, 0xbf, 0xff, 0x86, 0xfb, 0xfd, 0xc6, 0x3c, 0x08,
+ 0x38, 0xbe, 0x23, 0x56, 0x2f, 0xff, 0x69, 0xfb, 0x41, 0xfd, 0xf9, 0x3b,
+ 0x12, 0xc5, 0x62, 0x2b, 0x74, 0xc5, 0x7f, 0x7d, 0xbd, 0xcf, 0xca, 0xc5,
+ 0xff, 0xe8, 0x8a, 0x7d, 0xcf, 0x75, 0xbb, 0x96, 0xcb, 0x17, 0xff, 0xff,
+ 0xe6, 0x37, 0x34, 0xdd, 0x05, 0x07, 0xfc, 0xee, 0x4d, 0xd7, 0x1c, 0x84,
+ 0xdf, 0x58, 0xbf, 0xe6, 0x08, 0x7f, 0x9d, 0xb0, 0x25, 0x8a, 0x74, 0xc3,
+ 0xd9, 0x38, 0xa1, 0x0b, 0x7f, 0xfc, 0xe0, 0xc3, 0xbf, 0xb9, 0x27, 0x6e,
+ 0xbc, 0xb1, 0x7f, 0xff, 0x76, 0xc1, 0xea, 0x45, 0xc7, 0xec, 0xce, 0x31,
+ 0x4a, 0xc5, 0x62, 0x2b, 0x9d, 0x42, 0xff, 0xff, 0x6e, 0xda, 0x6f, 0xf5,
+ 0x0c, 0xf6, 0x7a, 0x45, 0xdf, 0xe2, 0xc5, 0xff, 0xcd, 0xd4, 0x1f, 0xdf,
+ 0x9d, 0x7a, 0x56, 0x2f, 0xfd, 0x06, 0xe7, 0x27, 0xf3, 0xbe, 0x2c, 0x5f,
+ 0xde, 0xc8, 0xa0, 0xfe, 0x58, 0xb4, 0xb9, 0xf7, 0x1c, 0xfe, 0xff, 0xfc,
+ 0xfa, 0xfe, 0x60, 0x5e, 0xcd, 0xb0, 0xd7, 0xd2, 0xc5, 0x41, 0x3b, 0x87,
+ 0x21, 0x3b, 0x3f, 0xa1, 0x67, 0xd8, 0x9a, 0xff, 0xff, 0x7d, 0xc6, 0x3c,
+ 0x0b, 0xaf, 0x09, 0xb9, 0xf0, 0x98, 0x6b, 0x17, 0xc2, 0x6d, 0x41, 0x62,
+ 0xfe, 0x29, 0xd8, 0x0d, 0xe5, 0x8b, 0xfc, 0xc3, 0x0f, 0xba, 0x4a, 0x0b,
+ 0x16, 0x9d, 0xcf, 0x94, 0xe5, 0xd7, 0xff, 0xc7, 0x62, 0x07, 0xc2, 0x62,
+ 0xdb, 0x77, 0xd9, 0x62, 0xff, 0xff, 0x9c, 0xa1, 0xcd, 0x85, 0xcc, 0xf4,
+ 0x93, 0x00, 0x9a, 0x0b, 0x17, 0xff, 0xf6, 0x9b, 0x98, 0x53, 0x80, 0xe6,
+ 0x45, 0x3d, 0x71, 0x62, 0xe7, 0xf3, 0x26, 0x26, 0x05, 0x31, 0x32, 0xd0,
+ 0xd3, 0xfe, 0x78, 0x44, 0x34, 0x67, 0x77, 0xfc, 0x20, 0x1d, 0xa1, 0xcd,
+ 0x0d, 0x62, 0xff, 0xff, 0x63, 0x97, 0xb0, 0x8c, 0x26, 0x1c, 0x96, 0xd3,
+ 0xa5, 0x8a, 0xf2, 0x26, 0x7b, 0x1d, 0xdb, 0x4b, 0x17, 0xff, 0xee, 0xbc,
+ 0x53, 0xf6, 0xe6, 0x6e, 0x4d, 0x9b, 0xac, 0x56, 0x22, 0x37, 0x72, 0x51,
+ 0x09, 0x5f, 0xf8, 0x5c, 0xc2, 0x6f, 0x80, 0x3e, 0x96, 0x2f, 0xff, 0xfe,
+ 0xc3, 0x81, 0xb5, 0x9d, 0xb0, 0x79, 0xc1, 0x37, 0x5f, 0x09, 0xbc, 0xb1,
+ 0x5a, 0x45, 0xb7, 0xd0, 0x6f, 0xf4, 0xfd, 0xfd, 0xc6, 0xe9, 0x62, 0xff,
+ 0xd9, 0xd7, 0xbd, 0x27, 0xfe, 0x6c, 0xb1, 0x7f, 0xd1, 0x6f, 0xf7, 0x3c,
+ 0xe8, 0xd5, 0x8b, 0xfc, 0x0c, 0xd6, 0x67, 0xb8, 0xb1, 0x7d, 0xb7, 0xb3,
+ 0x75, 0x8a, 0xc4, 0x4a, 0xf4, 0x7b, 0xa3, 0x3a, 0x96, 0x52, 0x7c, 0x08,
+ 0x87, 0x19, 0xee, 0x4a, 0x99, 0xdd, 0x47, 0xf2, 0x98, 0xca, 0x36, 0x0f,
+ 0x43, 0x98, 0x44, 0x61, 0x1a, 0x07, 0x0d, 0x6b, 0xd8, 0x06, 0x58, 0xbd,
+ 0xac, 0xe9, 0x62, 0xf7, 0xda, 0x1f, 0x37, 0x40, 0x1c, 0xbf, 0xf9, 0x9f,
+ 0xd2, 0x5b, 0xb9, 0xce, 0xeb, 0x17, 0xdf, 0x92, 0xf2, 0xc5, 0xce, 0x3f,
+ 0x9f, 0x2f, 0x10, 0xed, 0x9f, 0x46, 0x21, 0x42, 0x5e, 0xff, 0xb3, 0xae,
+ 0x0e, 0x58, 0xb6, 0x58, 0xbf, 0xcd, 0xc9, 0x2f, 0x7d, 0xd6, 0x2f, 0xc7,
+ 0x8b, 0x8e, 0x4b, 0x17, 0xff, 0x6e, 0xfa, 0xfe, 0x45, 0xf7, 0xd6, 0xcb,
+ 0x17, 0xdb, 0x36, 0x71, 0x62, 0xff, 0xe6, 0x06, 0x17, 0x5e, 0xd4, 0xe0,
+ 0x4b, 0x17, 0xfa, 0x4d, 0xcd, 0x07, 0xee, 0x2c, 0x5f, 0xe2, 0x29, 0xdb,
+ 0xf2, 0x35, 0x8b, 0xfd, 0x0e, 0x7e, 0x74, 0x18, 0xd6, 0x2b, 0x0f, 0xa5,
+ 0x8c, 0xea, 0x0a, 0x8c, 0x30, 0xb0, 0xd3, 0xad, 0xcc, 0xba, 0x29, 0x64,
+ 0x82, 0x23, 0xe2, 0x2f, 0xa1, 0x3f, 0x7e, 0x04, 0x4e, 0x2e, 0xfd, 0x62,
+ 0xff, 0xff, 0x7f, 0x37, 0x2c, 0x3e, 0x16, 0x78, 0x40, 0x3b, 0x41, 0x62,
+ 0xfe, 0xfb, 0x1c, 0xa7, 0xa5, 0x8b, 0xff, 0x16, 0x7f, 0x22, 0x83, 0xea,
+ 0x0b, 0x17, 0xff, 0xff, 0xc0, 0x92, 0xdd, 0xbc, 0xdd, 0x03, 0x3b, 0x3f,
+ 0xa1, 0xf7, 0xf7, 0x1c, 0x6b, 0x17, 0xfd, 0xd7, 0xbe, 0xc7, 0xce, 0xbc,
+ 0xb1, 0x7f, 0xff, 0xf8, 0x85, 0xff, 0x7e, 0x74, 0x0c, 0xd4, 0x09, 0xe1,
+ 0xfc, 0xc2, 0xdd, 0x62, 0xfd, 0xdf, 0xff, 0x00, 0xcb, 0x16, 0xce, 0x22,
+ 0x90, 0x4e, 0xf7, 0xfd, 0x39, 0xe2, 0xc0, 0x47, 0x62, 0xc5, 0xff, 0x9f,
+ 0xb3, 0xfa, 0x28, 0x49, 0x79, 0x62, 0xa5, 0x57, 0xfc, 0x0b, 0xf1, 0x83,
+ 0x72, 0xee, 0x8f, 0xf5, 0x08, 0x02, 0x87, 0x07, 0x0a, 0x3c, 0x75, 0x7f,
+ 0xf9, 0xb2, 0x1f, 0xc7, 0x2c, 0x04, 0x76, 0x2c, 0x5e, 0x68, 0x46, 0x46,
+ 0x8e, 0xae, 0xd2, 0x63, 0xf6, 0x84, 0x65, 0x83, 0x8d, 0x93, 0x27, 0x9a,
+ 0xb7, 0x8e, 0xd3, 0xa8, 0x6a, 0xb9, 0x0c, 0x51, 0xa2, 0x6a, 0x38, 0xb3,
+ 0x91, 0x7e, 0x55, 0x33, 0x46, 0x54, 0x08, 0xc7, 0x7b, 0xf2, 0x62, 0x95,
+ 0x1d, 0xca, 0x5a, 0x1f, 0xa5, 0xf7, 0x07, 0x2e, 0x13, 0xba, 0x11, 0x37,
+ 0x77, 0xf8, 0xb1, 0x78, 0x01, 0xf4, 0xb1, 0x7f, 0xd9, 0xe9, 0xd6, 0x17,
+ 0xc4, 0xb1, 0x7f, 0xf3, 0xe8, 0x98, 0xd2, 0xcf, 0x48, 0x4b, 0x17, 0xd2,
+ 0x2e, 0xff, 0x16, 0x28, 0xd3, 0xeb, 0xf2, 0x25, 0xff, 0x43, 0x3d, 0xf7,
+ 0x9d, 0x01, 0x62, 0xfb, 0x76, 0x86, 0x2c, 0x58, 0x0b, 0x15, 0x86, 0xd5,
+ 0xc8, 0xef, 0xf6, 0x0d, 0xcb, 0xd9, 0xf5, 0x8b, 0xff, 0xf8, 0x7f, 0x92,
+ 0xdb, 0x82, 0x67, 0x87, 0x3e, 0xd0, 0x58, 0xbf, 0xff, 0xff, 0x8b, 0x38,
+ 0x42, 0xff, 0xbf, 0x3a, 0x06, 0x6a, 0x04, 0xf0, 0xfe, 0x61, 0x6e, 0xb1,
+ 0x7b, 0x3f, 0x19, 0x1a, 0x95, 0x52, 0x48, 0xe0, 0xc8, 0x32, 0x14, 0x7d,
+ 0x11, 0xfd, 0xb8, 0x87, 0xf8, 0x64, 0x1a, 0xe5, 0xff, 0xff, 0xf0, 0xf2,
+ 0x33, 0x90, 0x7f, 0xcf, 0x50, 0xc3, 0xe7, 0x67, 0xf0, 0x24, 0x72, 0xb1,
+ 0x79, 0xe5, 0x96, 0x2f, 0x7a, 0x46, 0x91, 0x7f, 0xfb, 0xec, 0xfe, 0x98,
+ 0x3e, 0xb6, 0x10, 0x12, 0x2f, 0x6b, 0xbf, 0x8c, 0x93, 0xe8, 0xe0, 0xed,
+ 0xe6, 0xde, 0x32, 0x08, 0xbe, 0x1c, 0x20, 0xed, 0x18, 0x37, 0x6c, 0xd3,
+ 0xbc, 0xbb, 0xe3, 0xda, 0xc5, 0x2f, 0x4e, 0x1f, 0x0a, 0x13, 0xdd, 0xa3,
+ 0x40, 0xbf, 0xfd, 0x18, 0x76, 0x84, 0x66, 0x6b, 0x76, 0x6d, 0xd5, 0x23,
+ 0x09, 0x7d, 0x2e, 0x1f, 0xd6, 0x2f, 0xff, 0xff, 0xfa, 0x7c, 0x28, 0xc0,
+ 0xf7, 0x6d, 0x33, 0xed, 0x19, 0xbf, 0xde, 0x28, 0x66, 0xc6, 0x72, 0x67,
+ 0x65, 0x8b, 0xfd, 0xf9, 0x26, 0x3c, 0xf7, 0x2c, 0x5e, 0x70, 0xfe, 0xb1,
+ 0x7f, 0xff, 0x67, 0x66, 0x1f, 0xe6, 0x33, 0xdf, 0xc1, 0x8b, 0xdc, 0x58,
+ 0xbf, 0xfd, 0xa6, 0x04, 0x61, 0xbe, 0x80, 0x53, 0xc8, 0x2c, 0x5d, 0x91,
+ 0x83, 0x4f, 0x2b, 0xa2, 0x36, 0x85, 0x10, 0x0d, 0x48, 0x78, 0x36, 0x1b,
+ 0xbb, 0xce, 0xf8, 0xb1, 0x6e, 0xcb, 0x15, 0xde, 0x9b, 0x73, 0x91, 0xdf,
+ 0x9f, 0xff, 0xcd, 0x96, 0x2e, 0xef, 0x0e, 0xb1, 0x7f, 0x76, 0x7e, 0xb3,
+ 0x36, 0x58, 0xb0, 0xd6, 0x2b, 0x0f, 0x0f, 0xe6, 0x37, 0xf6, 0x42, 0x7f,
+ 0xbb, 0xac, 0x5f, 0xef, 0x7f, 0x08, 0x9b, 0xcb, 0x15, 0x1a, 0x23, 0x86,
+ 0x36, 0x60, 0xef, 0xa9, 0x0f, 0x71, 0x75, 0xfa, 0x01, 0xc2, 0x74, 0xb1,
+ 0x7f, 0xf7, 0x7b, 0x9d, 0x40, 0x4d, 0xe2, 0x98, 0x2c, 0x5f, 0x77, 0xde,
+ 0x40, 0xeb, 0x17, 0xe8, 0xd2, 0x34, 0xef, 0x23, 0xa3, 0x75, 0x8b, 0xbd,
+ 0x1a, 0x96, 0x2f, 0xb8, 0xe6, 0x62, 0xc5, 0xff, 0xd8, 0xe0, 0xc6, 0x7d,
+ 0x6f, 0x3e, 0x58, 0xbb, 0xa8, 0xf5, 0x8b, 0xf7, 0xdc, 0xf3, 0xba, 0xc5,
+ 0xd8, 0x73, 0x0f, 0x17, 0x71, 0xcb, 0xfa, 0x4f, 0x80, 0x9e, 0xcb, 0x17,
+ 0xff, 0xbd, 0xc1, 0x49, 0x9b, 0xfd, 0xe3, 0x9b, 0x65, 0x8a, 0x1a, 0x2b,
+ 0xfe, 0x5e, 0x45, 0xf7, 0xfd, 0x03, 0x3c, 0x46, 0x19, 0xf8, 0xe5, 0x8b,
+ 0xe9, 0x00, 0x67, 0x58, 0xbe, 0x9e, 0x48, 0x16, 0x2e, 0xd6, 0x6e, 0x78,
+ 0xc4, 0x49, 0x7e, 0xf3, 0x6c, 0xdc, 0x58, 0xbe, 0x93, 0xbe, 0x96, 0x2e,
+ 0xc2, 0x58, 0xa8, 0x8f, 0x87, 0x45, 0x3c, 0x22, 0xb8, 0x5c, 0x58, 0xa9,
+ 0x3c, 0x83, 0x98, 0x5f, 0x37, 0xc3, 0xe2, 0xc5, 0xe0, 0xf3, 0x65, 0x8a,
+ 0xf1, 0xe1, 0x88, 0x92, 0xff, 0xf3, 0x10, 0xb3, 0xc4, 0xdf, 0x2c, 0xd2,
+ 0xc5, 0xf4, 0x93, 0xc4, 0xb1, 0x7f, 0xfe, 0xcd, 0x8c, 0xcc, 0x2f, 0x7d,
+ 0x9f, 0x8f, 0xd9, 0x62, 0xf7, 0x61, 0x41, 0x62, 0xfd, 0xf9, 0x1b, 0x9a,
+ 0xb1, 0x46, 0xae, 0x3a, 0xee, 0x46, 0xf1, 0x9b, 0xc7, 0x97, 0xea, 0x10,
+ 0xe7, 0x86, 0xb7, 0xd9, 0x00, 0x44, 0x48, 0xfe, 0x22, 0xec, 0xaf, 0xdc,
+ 0x41, 0x7c, 0x76, 0x62, 0x58, 0xbf, 0xf4, 0xeb, 0x59, 0xf6, 0xf7, 0xe5,
+ 0x62, 0xff, 0x05, 0xf7, 0xf7, 0x1b, 0x4b, 0x17, 0x8b, 0x92, 0xb1, 0x51,
+ 0xa2, 0x2c, 0x36, 0x21, 0xc3, 0xe6, 0x35, 0xbe, 0x1e, 0xf2, 0x75, 0x8b,
+ 0xc1, 0xf0, 0x96, 0x2f, 0x82, 0xf6, 0x7d, 0x62, 0xfe, 0x01, 0x9e, 0x9e,
+ 0xa0, 0xb1, 0x52, 0x7a, 0xac, 0x49, 0x4e, 0x8b, 0x7f, 0x92, 0x13, 0x9d,
+ 0x99, 0x62, 0xfe, 0xd6, 0x17, 0x7a, 0x16, 0xeb, 0x15, 0x11, 0xe3, 0x30,
+ 0x8d, 0xd1, 0xbf, 0x96, 0x2f, 0xa2, 0x70, 0xa2, 0x58, 0xbf, 0xd2, 0x77,
+ 0xfc, 0xe1, 0x2c, 0x5c, 0xdc, 0x58, 0xa3, 0x9f, 0x77, 0x89, 0xbb, 0x18,
+ 0xdf, 0xde, 0x9e, 0xc4, 0xdd, 0x2c, 0x5f, 0x8b, 0x77, 0x2c, 0x58, 0xbf,
+ 0xf1, 0x60, 0xf3, 0xfe, 0x9e, 0xa0, 0xb1, 0x7e, 0xdb, 0xd8, 0xe3, 0x58,
+ 0xad, 0x1f, 0x41, 0x1f, 0xdf, 0xfb, 0x83, 0xd1, 0x30, 0x59, 0xd7, 0x96,
+ 0x2f, 0xf0, 0x45, 0x9d, 0x7b, 0x3e, 0xb1, 0x52, 0x89, 0x7c, 0x21, 0x74,
+ 0x1b, 0xfc, 0x6f, 0xe4, 0x6f, 0x3d, 0xcb, 0x17, 0xf7, 0xb3, 0xad, 0xdc,
+ 0x96, 0x29, 0x8f, 0x9b, 0xc6, 0xf7, 0xef, 0xe0, 0xe7, 0x65, 0x8b, 0xf6,
+ 0xde, 0x35, 0xb4, 0xb1, 0x69, 0xe8, 0xf5, 0x18, 0xa6, 0xfc, 0xda, 0x83,
+ 0x1d, 0x62, 0xa5, 0x5c, 0x58, 0xc8, 0xb2, 0x11, 0x7d, 0x18, 0xb9, 0x87,
+ 0xe3, 0x26, 0x68, 0x49, 0x93, 0xa8, 0x89, 0xec, 0x75, 0x8b, 0xfd, 0xef,
+ 0xb3, 0xf1, 0xfb, 0x2c, 0x5a, 0x37, 0x58, 0xa2, 0x3c, 0xc8, 0xe3, 0x5b,
+ 0xfd, 0xc9, 0xc2, 0x1f, 0xe5, 0x62, 0xfe, 0x9c, 0x21, 0xfe, 0x56, 0x2f,
+ 0x0b, 0x51, 0x18, 0x7b, 0xdc, 0x32, 0xbf, 0xf4, 0x36, 0x62, 0xc1, 0x94,
+ 0xee, 0xb1, 0x77, 0xe3, 0xd6, 0x2f, 0xfc, 0x6b, 0x44, 0x3d, 0x61, 0x60,
+ 0x4b, 0x17, 0xfb, 0x59, 0xb7, 0xa7, 0xa8, 0x2c, 0x5f, 0xff, 0xb9, 0x39,
+ 0xb7, 0x39, 0x9a, 0x06, 0x66, 0xb8, 0xb1, 0x50, 0x47, 0x41, 0xa3, 0x7b,
+ 0xa0, 0xf8, 0xda, 0xff, 0xe9, 0x87, 0xe4, 0x06, 0x1e, 0x73, 0xcb, 0x17,
+ 0xb6, 0x7d, 0x2c, 0x5f, 0x6e, 0x53, 0xf5, 0x8b, 0xfc, 0x11, 0x98, 0x3f,
+ 0xcf, 0x65, 0x8b, 0xff, 0x0b, 0x0d, 0xcf, 0x0a, 0x7a, 0x1a, 0xc5, 0x49,
+ 0xfc, 0xb9, 0xc5, 0xfe, 0x21, 0x7b, 0x3c, 0x1e, 0xcb, 0x15, 0xb2, 0x62,
+ 0x18, 0x3d, 0xa8, 0x4e, 0x78, 0x82, 0xec, 0x09, 0x62, 0xf4, 0x97, 0x96,
+ 0x2f, 0xf8, 0x79, 0x0f, 0xcf, 0x61, 0xca, 0xc5, 0xdd, 0xb6, 0x58, 0xa3,
+ 0x0f, 0x59, 0xce, 0xee, 0xd7, 0xdd, 0x12, 0x8c, 0xe5, 0x7f, 0xe1, 0xb7,
+ 0xe5, 0x9f, 0x59, 0xd2, 0xc5, 0x39, 0xf5, 0x86, 0x5b, 0x7f, 0xc1, 0x07,
+ 0xf9, 0xdf, 0xef, 0x12, 0xc5, 0xf0, 0x8f, 0x83, 0x58, 0xae, 0x8f, 0x87,
+ 0xb8, 0xfa, 0xff, 0x1f, 0x8f, 0x9d, 0x9b, 0x4b, 0x17, 0xff, 0xfd, 0xfc,
+ 0x86, 0x43, 0xf8, 0x58, 0x6f, 0xda, 0x19, 0x03, 0xac, 0x5f, 0xd0, 0xe3,
+ 0x67, 0x5e, 0x58, 0xac, 0x47, 0x83, 0x13, 0x78, 0xd4, 0x4c, 0xd7, 0xdc,
+ 0x0e, 0x76, 0x58, 0xbf, 0x6a, 0x61, 0xcc, 0x58, 0xbe, 0x7f, 0x67, 0x65,
+ 0x8a, 0x58, 0xbf, 0xd8, 0x17, 0x89, 0x81, 0xc5, 0x8a, 0x94, 0x46, 0x7c,
+ 0xa0, 0x89, 0x3c, 0x19, 0x7f, 0xff, 0xdb, 0xb6, 0xa7, 0xd3, 0x03, 0x03,
+ 0xf1, 0x60, 0x18, 0x80, 0xb1, 0x7b, 0xed, 0x05, 0x8a, 0x83, 0x21, 0x2b,
+ 0x17, 0xb7, 0x84, 0x17, 0x46, 0xcf, 0x19, 0x3c, 0x47, 0xfa, 0x8d, 0x54,
+ 0xe8, 0x7f, 0x8c, 0x5c, 0xa3, 0x73, 0xe1, 0xdf, 0xa1, 0x62, 0x23, 0xbe,
+ 0xcd, 0x17, 0xf9, 0xa0, 0xfd, 0x72, 0x7a, 0x58, 0xbf, 0xf7, 0x3f, 0x27,
+ 0xf7, 0x09, 0xba, 0x58, 0xbe, 0x21, 0x6a, 0x56, 0x2b, 0xa3, 0xe2, 0x64,
+ 0x0b, 0x8e, 0x05, 0x8a, 0xfa, 0x34, 0x5a, 0x12, 0xfc, 0x22, 0xbf, 0xf1,
+ 0x7e, 0x63, 0xfd, 0xc7, 0x28, 0x96, 0x2f, 0xff, 0xa4, 0xbd, 0xa9, 0x78,
+ 0x16, 0x1d, 0xa0, 0xb1, 0x7f, 0xc4, 0x2e, 0x16, 0x1b, 0x3c, 0x58, 0xbf,
+ 0x1c, 0xf8, 0x28, 0x96, 0x2f, 0xff, 0x4e, 0xfc, 0x17, 0x9f, 0xee, 0x6f,
+ 0xdd, 0x62, 0xfe, 0x3c, 0xe1, 0x7a, 0x39, 0x62, 0xfb, 0x4f, 0xd4, 0x16,
+ 0x2d, 0xc5, 0x8b, 0xf4, 0xe1, 0x7a, 0x39, 0x62, 0xf7, 0x1b, 0xa3, 0x11,
+ 0x20, 0xe6, 0x11, 0x12, 0x1c, 0x4a, 0x86, 0x9e, 0xe1, 0xa9, 0xba, 0x39,
+ 0x39, 0x57, 0xa1, 0xb9, 0x7f, 0xd1, 0xf8, 0x3f, 0xcc, 0x79, 0x4a, 0xc5,
+ 0x4a, 0xaa, 0xd7, 0x94, 0x3c, 0xca, 0x37, 0xfd, 0xad, 0xb7, 0xfb, 0xfc,
+ 0x5e, 0x58, 0xaf, 0x9f, 0x9b, 0x1b, 0x5f, 0x78, 0x2e, 0x6e, 0xb1, 0x7f,
+ 0x9c, 0xdd, 0x66, 0xd3, 0xb2, 0xc5, 0xfa, 0x4f, 0xd8, 0x10, 0x58, 0xac,
+ 0x44, 0x3f, 0x09, 0xbc, 0x6d, 0x77, 0x9d, 0x62, 0xe1, 0x62, 0xc5, 0xda,
+ 0xe2, 0xc5, 0x40, 0xfd, 0x4d, 0x2f, 0x00, 0xbc, 0x70, 0xbd, 0xff, 0xf0,
+ 0xb5, 0x3b, 0x85, 0x8f, 0xfd, 0xdf, 0x6e, 0xe5, 0x8b, 0xd2, 0xfb, 0xac,
+ 0x54, 0x0f, 0xd2, 0x25, 0x7b, 0xd9, 0xe7, 0x58, 0xbe, 0x9d, 0x66, 0xcb,
+ 0x17, 0xb5, 0x3d, 0x96, 0x2e, 0x9f, 0x2c, 0x54, 0x9b, 0x6d, 0x0f, 0xdf,
+ 0xb7, 0x7e, 0x7d, 0xd6, 0x2f, 0xec, 0x72, 0xf0, 0xbe, 0xb1, 0x5d, 0x1e,
+ 0xb7, 0xca, 0x6f, 0xdb, 0x93, 0xf5, 0x05, 0x8b, 0x83, 0xfa, 0xc5, 0x44,
+ 0x9b, 0xa6, 0x88, 0xfe, 0x39, 0xc5, 0x9f, 0x3b, 0x08, 0x8e, 0x38, 0xaa,
+ 0xf1, 0xcc, 0xc5, 0x8b, 0xf3, 0x8b, 0xbf, 0x8e, 0x75, 0x8b, 0xfb, 0x58,
+ 0xff, 0x91, 0xac, 0x5f, 0x6f, 0xec, 0xdd, 0x62, 0xe1, 0x71, 0x62, 0xb0,
+ 0xde, 0xe8, 0x96, 0xfa, 0x4a, 0x2d, 0xd6, 0x2f, 0xff, 0x49, 0x67, 0xbf,
+ 0x9e, 0xfc, 0x8b, 0xbf, 0x58, 0xbf, 0x4c, 0x4c, 0xda, 0x58, 0xad, 0x22,
+ 0x6b, 0xe4, 0x9c, 0x4e, 0xbf, 0x9f, 0x46, 0x31, 0x01, 0x62, 0xec, 0xe9,
+ 0x62, 0xf4, 0x9f, 0x16, 0x2b, 0xe6, 0xd3, 0xb0, 0xc5, 0xff, 0xfe, 0x0b,
+ 0xbb, 0xd9, 0xf3, 0x0b, 0x36, 0x7c, 0x2e, 0xa1, 0xc5, 0x8b, 0xf7, 0x33,
+ 0xc1, 0xec, 0xb1, 0x77, 0xf7, 0x58, 0xb8, 0x2f, 0x49, 0xe2, 0x61, 0x5d,
+ 0x62, 0x36, 0x1a, 0x15, 0x75, 0x2a, 0xc9, 0x60, 0x3c, 0x33, 0x0c, 0x6a,
+ 0x78, 0x5d, 0x7c, 0xc1, 0x98, 0x8a, 0x1f, 0x77, 0xfb, 0xdf, 0xc1, 0xe1,
+ 0x41, 0x62, 0xff, 0xff, 0xfe, 0x67, 0xf4, 0xfc, 0xb3, 0xdf, 0x7f, 0x43,
+ 0x3f, 0xf6, 0x87, 0x05, 0x1d, 0x9f, 0x58, 0xbf, 0xed, 0xdc, 0x7e, 0xcf,
+ 0x94, 0xac, 0x5f, 0xf9, 0x81, 0xfc, 0x71, 0x8b, 0xdc, 0x58, 0xa7, 0x3f,
+ 0x82, 0x39, 0xa7, 0x4d, 0x57, 0xe6, 0x7e, 0x8c, 0x0a, 0xfb, 0x0f, 0x9f,
+ 0x58, 0xbf, 0xe2, 0xf6, 0x6f, 0xf9, 0x26, 0x58, 0xb8, 0x72, 0xb1, 0x6e,
+ 0xd2, 0x79, 0xf8, 0x71, 0x7e, 0x68, 0xb8, 0x1f, 0x65, 0x8b, 0xe1, 0x0f,
+ 0xf2, 0xb1, 0x50, 0x3d, 0x02, 0x2d, 0xbe, 0x86, 0x4f, 0x4b, 0x17, 0xfd,
+ 0x3b, 0x07, 0x0f, 0x89, 0xb6, 0x58, 0xbd, 0x9d, 0xa5, 0x62, 0xff, 0xbd,
+ 0xf6, 0x81, 0x9c, 0xf8, 0xd6, 0x28, 0x07, 0xb4, 0x43, 0xd7, 0xa7, 0xa8,
+ 0x2c, 0x54, 0xaa, 0x39, 0x81, 0xb6, 0x38, 0xbb, 0xc4, 0x44, 0x3a, 0x23,
+ 0x68, 0x4b, 0x91, 0x0d, 0xfe, 0x8b, 0x8c, 0x51, 0x39, 0xd6, 0x2f, 0xfa,
+ 0x06, 0x7d, 0xb7, 0x92, 0x1a, 0xc5, 0x61, 0xf8, 0x74, 0x6b, 0x73, 0x7d,
+ 0x62, 0xf3, 0xc9, 0x2c, 0x5f, 0x41, 0xb8, 0xeb, 0x17, 0xf1, 0x38, 0x0f,
+ 0x3d, 0x96, 0x2f, 0x68, 0x07, 0x58, 0xa7, 0x3c, 0xd1, 0x17, 0xdc, 0x7d,
+ 0x2c, 0x5f, 0xf1, 0x7b, 0xf9, 0xd4, 0x05, 0x12, 0xc5, 0xfe, 0x7f, 0x07,
+ 0xa9, 0xfc, 0xac, 0x5f, 0x89, 0xb7, 0x2c, 0x58, 0xbf, 0xa1, 0x9f, 0xfb,
+ 0x41, 0x62, 0xa5, 0x18, 0xb0, 0x3c, 0x73, 0x4f, 0x13, 0xd6, 0x27, 0xf9,
+ 0xd1, 0x17, 0xc5, 0xd8, 0x6f, 0x8d, 0xfe, 0x21, 0x14, 0x37, 0x6f, 0x3c,
+ 0xf7, 0x2c, 0x5f, 0x16, 0x39, 0xab, 0x17, 0xcf, 0x3d, 0x71, 0x62, 0xfc,
+ 0x1f, 0x8a, 0x40, 0xb1, 0x43, 0x44, 0x69, 0xc7, 0xfc, 0x45, 0xd8, 0x8e,
+ 0xff, 0xc3, 0x7d, 0x6e, 0x37, 0xed, 0x23, 0x58, 0xbf, 0xf6, 0xa4, 0x3e,
+ 0xb9, 0xde, 0xb6, 0x7d, 0x62, 0xf4, 0x1f, 0x8b, 0x17, 0x83, 0x63, 0xac,
+ 0x5f, 0xfc, 0x3d, 0x3f, 0x50, 0x2c, 0x36, 0x78, 0xb1, 0x7b, 0xd8, 0x12,
+ 0xc5, 0x0d, 0x32, 0x77, 0x42, 0x89, 0x1b, 0x43, 0xa4, 0x3d, 0xe4, 0x6b,
+ 0xff, 0x9f, 0x98, 0x3f, 0xc9, 0xf6, 0xc0, 0x96, 0x2f, 0xec, 0xee, 0xf7,
+ 0x50, 0x95, 0x8b, 0xf6, 0x7d, 0xbd, 0xc5, 0x8b, 0xff, 0x02, 0x61, 0x9d,
+ 0x7b, 0x61, 0x04, 0xb1, 0x47, 0x3e, 0xbf, 0x14, 0x5f, 0xe2, 0xc3, 0x9f,
+ 0x05, 0x12, 0xc5, 0xf7, 0x7f, 0xf7, 0xe2, 0xc5, 0x49, 0xff, 0x68, 0x88,
+ 0x46, 0x97, 0xd0, 0x7d, 0x6c, 0xb1, 0x73, 0x44, 0xb1, 0x74, 0x9f, 0xa3,
+ 0x79, 0xa2, 0x4b, 0xe7, 0xd3, 0x69, 0x62, 0xf7, 0x01, 0x1e, 0xb1, 0x7c,
+ 0xe3, 0xc3, 0xac, 0x5f, 0xde, 0x86, 0x6b, 0x38, 0x61, 0xe1, 0xc9, 0x0d,
+ 0xfe, 0x7f, 0xb8, 0x99, 0xfe, 0xb1, 0x50, 0x46, 0xdb, 0xb2, 0xfd, 0x12,
+ 0xf7, 0x18, 0x0b, 0x15, 0x2b, 0x9b, 0x99, 0x1b, 0x36, 0xea, 0xfd, 0x23,
+ 0x3c, 0x63, 0x7f, 0x6a, 0x68, 0xc2, 0x3c, 0x5f, 0x4b, 0x17, 0xd2, 0x77,
+ 0x82, 0xc5, 0xdf, 0x98, 0x1a, 0xed, 0x06, 0x5e, 0x92, 0x35, 0x62, 0xe6,
+ 0x82, 0xc5, 0xff, 0x4f, 0xfb, 0x9b, 0x61, 0x3e, 0x96, 0x2e, 0xe6, 0x2c,
+ 0x53, 0x9e, 0xa3, 0x1e, 0xdf, 0xff, 0xf8, 0xf2, 0xde, 0xf4, 0x9b, 0x9e,
+ 0xfc, 0x93, 0x7b, 0x8e, 0x4b, 0x17, 0xe9, 0xdc, 0x98, 0xeb, 0x17, 0xfe,
+ 0x98, 0x19, 0x9f, 0x7d, 0x7d, 0x96, 0x2b, 0xe7, 0xcf, 0xc2, 0x8a, 0x94,
+ 0x79, 0xbc, 0x34, 0x6f, 0x7e, 0x7e, 0xb1, 0x43, 0x54, 0x15, 0xd1, 0x64,
+ 0x78, 0xec, 0x4d, 0x7f, 0x8c, 0x4f, 0xc4, 0xd7, 0x0b, 0x65, 0x8b, 0xec,
+ 0xd4, 0xee, 0xb1, 0x74, 0x5c, 0x19, 0xbc, 0xf8, 0xcd, 0xfd, 0xed, 0x4e,
+ 0xf9, 0xa5, 0x8b, 0xff, 0xff, 0xd3, 0xff, 0xb7, 0x0c, 0xfb, 0x3f, 0x3f,
+ 0x80, 0x33, 0x59, 0xe6, 0xe9, 0x62, 0xfe, 0xfb, 0x8d, 0xf5, 0xba, 0xc5,
+ 0xf3, 0xf2, 0x60, 0xb1, 0x7f, 0xb3, 0xe0, 0x3e, 0x6a, 0x25, 0x8b, 0xba,
+ 0xe6, 0xe8, 0x86, 0x62, 0xf2, 0x22, 0xbf, 0x98, 0x1a, 0xd3, 0xe9, 0x62,
+ 0xf7, 0x8c, 0xc5, 0x8a, 0x94, 0xf9, 0x5c, 0xbb, 0x45, 0xed, 0x18, 0x00,
+ 0x0f, 0x03, 0x2e, 0xb0, 0x16, 0x2f, 0x9f, 0xb4, 0xfd, 0x62, 0xd8, 0xe6,
+ 0xdb, 0xc2, 0x57, 0xf8, 0x31, 0xb3, 0x6e, 0xdb, 0xac, 0x5f, 0xfe, 0xe6,
+ 0xb3, 0xb4, 0x97, 0x98, 0x85, 0x8b, 0x15, 0x88, 0x80, 0xf1, 0xb5, 0xf7,
+ 0xc5, 0xd7, 0x96, 0x2f, 0xfe, 0xfe, 0x4e, 0x8b, 0x0e, 0x71, 0x44, 0xb1,
+ 0x7f, 0x78, 0x30, 0x02, 0x7a, 0x58, 0xbf, 0xe7, 0xf3, 0xe1, 0xcb, 0x36,
+ 0x58, 0xa7, 0x3e, 0x9f, 0x98, 0xdf, 0xdc, 0x73, 0x4e, 0xde, 0x58, 0xbf,
+ 0xf7, 0x69, 0x36, 0x0e, 0x53, 0xa9, 0x58, 0xbf, 0xff, 0xf6, 0xb3, 0xb4,
+ 0x97, 0x8c, 0x0c, 0xa7, 0xec, 0xfe, 0x9f, 0x71, 0x62, 0xff, 0xdf, 0x76,
+ 0x01, 0x9a, 0xd0, 0xbe, 0xb1, 0x76, 0xf1, 0xb2, 0xc5, 0xf1, 0x37, 0xcd,
+ 0x58, 0xbd, 0xb0, 0xa0, 0xb1, 0x78, 0xb3, 0x86, 0x1f, 0x00, 0xc7, 0xb0,
+ 0x8e, 0xf9, 0x81, 0x01, 0xac, 0x5f, 0xe9, 0x3e, 0xe4, 0xd9, 0xba, 0xc5,
+ 0x0d, 0x57, 0x1e, 0xf0, 0xae, 0xe8, 0x85, 0xcb, 0xf4, 0x81, 0xe6, 0xee,
+ 0xd0, 0xa1, 0x08, 0xfc, 0x32, 0x3b, 0xe3, 0x3b, 0x77, 0x6c, 0xb1, 0x7f,
+ 0xb9, 0xfc, 0xee, 0x7c, 0x09, 0x62, 0xa5, 0x70, 0x6c, 0x64, 0x59, 0x2c,
+ 0x20, 0xd8, 0x47, 0x80, 0xae, 0xd1, 0xeb, 0x17, 0xb6, 0x98, 0xf5, 0x8b,
+ 0xf7, 0x23, 0x4d, 0x0b, 0x65, 0x8b, 0x47, 0xac, 0x5e, 0xc1, 0xf9, 0x62,
+ 0x9c, 0xd9, 0x68, 0x56, 0xfc, 0xd1, 0x3f, 0xb8, 0xb1, 0x7f, 0xff, 0x9f,
+ 0x8d, 0xee, 0xe7, 0xd9, 0xbb, 0xb3, 0x59, 0xe6, 0x89, 0x62, 0xb6, 0x4c,
+ 0xcf, 0x08, 0x4e, 0xc5, 0xf2, 0x0f, 0x14, 0xdf, 0x76, 0x68, 0xa2, 0x58,
+ 0xbf, 0xba, 0xf3, 0x31, 0xf8, 0xb1, 0x52, 0x7a, 0xce, 0x4f, 0x78, 0xb3,
+ 0xa5, 0x8b, 0xbd, 0x8b, 0x17, 0xfe, 0x7e, 0xd8, 0x3f, 0xe6, 0xf8, 0x4b,
+ 0x17, 0xfd, 0x0f, 0x48, 0x45, 0x3e, 0xe2, 0xc5, 0xfe, 0x92, 0x90, 0x33,
+ 0x77, 0x2c, 0x5e, 0xd3, 0x41, 0x62, 0xff, 0x0f, 0xf9, 0xbf, 0xe7, 0x4b,
+ 0x14, 0x34, 0x43, 0x68, 0xd0, 0x87, 0x6f, 0xdc, 0xcf, 0x6a, 0x56, 0x2d,
+ 0xe5, 0x8b, 0xff, 0x8a, 0x4e, 0xcf, 0xf6, 0xf7, 0xe5, 0x62, 0xba, 0x3d,
+ 0x4e, 0xfc, 0x4a, 0xa5, 0x3e, 0xa8, 0x0b, 0xf4, 0x80, 0xf0, 0xc0, 0xe1,
+ 0x78, 0x9f, 0x2e, 0x6d, 0xd6, 0x2f, 0xe7, 0x89, 0xb7, 0xe4, 0x16, 0x2f,
+ 0xff, 0xf8, 0x63, 0xc8, 0xe9, 0xd6, 0x10, 0xff, 0x21, 0x80, 0x13, 0xd2,
+ 0xc5, 0x6e, 0x8b, 0x3f, 0x8c, 0x31, 0x85, 0xff, 0xd2, 0xe5, 0x9e, 0xe4,
+ 0xfd, 0x8e, 0xb1, 0x7f, 0xc5, 0x9c, 0xe3, 0xff, 0x3c, 0xb1, 0x5a, 0x3f,
+ 0xae, 0xc8, 0x57, 0xff, 0xf3, 0x90, 0xf5, 0x9b, 0xfe, 0x7f, 0x9a, 0xd4,
+ 0x9a, 0xb1, 0x7f, 0xfa, 0x41, 0xc3, 0x3d, 0x0c, 0x8f, 0x62, 0x02, 0xc5,
+ 0x7d, 0x15, 0x44, 0xb9, 0x70, 0x67, 0x58, 0xbf, 0x0b, 0xb9, 0xf0, 0xeb,
+ 0x17, 0xec, 0xf7, 0xa6, 0x25, 0x8b, 0xfa, 0x7a, 0xe1, 0x9e, 0x75, 0x8b,
+ 0xf7, 0x98, 0xef, 0xe5, 0x8a, 0x35, 0x15, 0x9a, 0x2b, 0x39, 0x49, 0x18,
+ 0x52, 0xc5, 0xf4, 0xe4, 0x19, 0x62, 0x8e, 0x6b, 0x7e, 0x19, 0x71, 0xfc,
+ 0xb1, 0x7f, 0x43, 0xf8, 0xf0, 0xe2, 0xc5, 0xfc, 0xfe, 0x16, 0x9b, 0x86,
+ 0x1e, 0x36, 0x0c, 0x54, 0xa6, 0x2a, 0x36, 0xa6, 0x67, 0xbf, 0xfb, 0xf8,
+ 0xd1, 0x16, 0x0f, 0xf3, 0xc5, 0x8b, 0xfb, 0x0e, 0x59, 0xb3, 0x2c, 0x50,
+ 0xcf, 0xc5, 0xd1, 0x2f, 0xf7, 0x1f, 0xb0, 0xe4, 0x1b, 0x2c, 0x56, 0x1e,
+ 0xc3, 0x10, 0xdf, 0xfb, 0x20, 0xc4, 0x03, 0x02, 0xcf, 0xac, 0x5f, 0x7b,
+ 0x80, 0x12, 0xc5, 0xe7, 0x3f, 0x96, 0x2f, 0x10, 0x7e, 0x58, 0xbf, 0x08,
+ 0x6c, 0x40, 0x30, 0xdd, 0xb0, 0xed, 0xfc, 0x0d, 0x48, 0xbb, 0xfc, 0x58,
+ 0xbf, 0xb5, 0x21, 0x37, 0xf8, 0xb1, 0x7f, 0x03, 0x8f, 0x13, 0x84, 0xb1,
+ 0x52, 0x89, 0x2c, 0x33, 0x62, 0xfb, 0x74, 0xb1, 0x52, 0x9b, 0x74, 0x17,
+ 0xca, 0x19, 0xfc, 0x2d, 0xbf, 0x74, 0xc3, 0xfe, 0x2c, 0x5f, 0x0f, 0x0f,
+ 0x1c, 0xb1, 0x7f, 0x7d, 0xfc, 0x52, 0x75, 0x8b, 0xe9, 0xec, 0x52, 0xb1,
+ 0x79, 0xa1, 0x8b, 0x15, 0x28, 0xbb, 0x72, 0x98, 0x89, 0x8e, 0x5a, 0x44,
+ 0x75, 0x1b, 0xb3, 0x27, 0x66, 0x34, 0x88, 0x42, 0x84, 0x64, 0x19, 0x28,
+ 0x1f, 0x78, 0xc3, 0xde, 0x15, 0x51, 0x43, 0x38, 0xe4, 0x5f, 0x8f, 0x68,
+ 0xa1, 0xf1, 0xc2, 0x0f, 0x47, 0x5c, 0x28, 0x7e, 0x5f, 0xed, 0x4f, 0x0d,
+ 0x03, 0x44, 0xb1, 0x7f, 0xf7, 0x1b, 0xdf, 0xce, 0xdf, 0x61, 0x6c, 0xb1,
+ 0x7c, 0xfc, 0x11, 0xd6, 0x2f, 0xf0, 0x8d, 0xc8, 0x49, 0x6e, 0xb1, 0x7f,
+ 0x64, 0x7b, 0x10, 0x0c, 0x81, 0xec, 0x68, 0x8e, 0xff, 0x68, 0x11, 0x7d,
+ 0xc8, 0x6b, 0x17, 0xff, 0xcc, 0x71, 0xfe, 0x7f, 0x27, 0x17, 0x50, 0xe2,
+ 0xc5, 0xff, 0xec, 0xf7, 0xdf, 0x3a, 0xf6, 0x76, 0x9e, 0x2c, 0x5b, 0xf2,
+ 0x8d, 0x3f, 0x9a, 0x92, 0x95, 0xf3, 0x73, 0xdb, 0x2c, 0x5f, 0x9d, 0x80,
+ 0x67, 0x96, 0x2f, 0xfc, 0x5f, 0x97, 0x1b, 0xf3, 0x20, 0xb1, 0x7b, 0x07,
+ 0x05, 0x8b, 0xdc, 0x93, 0xac, 0x53, 0x1f, 0xb8, 0x0f, 0x78, 0x3b, 0x73,
+ 0x3a, 0xc5, 0x83, 0x58, 0xa7, 0x35, 0x20, 0x16, 0xbf, 0x81, 0xcf, 0xc9,
+ 0x79, 0x62, 0xa4, 0xf3, 0x98, 0x82, 0xfd, 0xdb, 0xee, 0x08, 0x96, 0x2f,
+ 0xda, 0xc3, 0x67, 0x8b, 0x15, 0x87, 0xaa, 0xe5, 0x97, 0xff, 0x36, 0xd3,
+ 0xbf, 0xde, 0x28, 0x08, 0xeb, 0x15, 0x2b, 0x8d, 0x5b, 0x1b, 0x42, 0x14,
+ 0x19, 0x18, 0xd1, 0xa6, 0x9f, 0x24, 0x68, 0x50, 0x14, 0x29, 0x78, 0xea,
+ 0x22, 0x0b, 0x8a, 0x56, 0x2f, 0xbf, 0x3c, 0x95, 0x8b, 0xc1, 0x8f, 0x16,
+ 0x2f, 0x77, 0xfc, 0x8d, 0x96, 0x2b, 0x63, 0xfe, 0x18, 0xb3, 0x11, 0x70,
+ 0x7a, 0xf7, 0x1f, 0x8b, 0x17, 0x8e, 0x66, 0xeb, 0x17, 0x3e, 0x96, 0x2f,
+ 0xff, 0x07, 0xdd, 0x02, 0xc1, 0xe0, 0x5a, 0xcd, 0x96, 0x28, 0x67, 0xcf,
+ 0x10, 0xbd, 0x18, 0x8a, 0xa6, 0x84, 0x3d, 0xfd, 0xb4, 0x50, 0x8d, 0xb5,
+ 0xb2, 0xc5, 0xfc, 0x79, 0x2f, 0x67, 0x96, 0x2f, 0x66, 0xe3, 0x58, 0xbe,
+ 0xf6, 0x10, 0x16, 0x2f, 0x7b, 0x36, 0x58, 0xbf, 0x39, 0x6c, 0x1f, 0x4b,
+ 0x17, 0x30, 0x52, 0x79, 0x23, 0x1e, 0xbf, 0xb3, 0x5a, 0x99, 0x1a, 0xc5,
+ 0x46, 0xe9, 0xa4, 0x49, 0xc6, 0x16, 0xb8, 0xf1, 0x35, 0xc7, 0x16, 0xdf,
+ 0xfd, 0xb7, 0xf0, 0x63, 0x7e, 0xb3, 0xaf, 0x2c, 0x5f, 0x6c, 0x18, 0xb6,
+ 0x58, 0xbe, 0x8a, 0x13, 0xb2, 0xc5, 0x49, 0xe6, 0x61, 0x3d, 0xef, 0xb1,
+ 0xab, 0x17, 0xf8, 0xb6, 0x2c, 0x14, 0xf1, 0x62, 0x96, 0x2f, 0x80, 0x19,
+ 0x41, 0x62, 0xcf, 0x26, 0xc3, 0xc1, 0x97, 0xc5, 0x9f, 0xc5, 0x8b, 0xe0,
+ 0xa2, 0xe4, 0xac, 0x5e, 0x93, 0xe2, 0xc5, 0xc0, 0x95, 0x8a, 0x73, 0x66,
+ 0x01, 0xcb, 0xe2, 0x96, 0xdd, 0x62, 0xfd, 0x26, 0xe7, 0xb8, 0xb1, 0x7f,
+ 0xff, 0x61, 0x38, 0xf9, 0x9c, 0xe6, 0x7d, 0xf8, 0x2d, 0x96, 0x2f, 0xe1,
+ 0xe9, 0xbd, 0xf1, 0x2c, 0x5c, 0xde, 0x82, 0x22, 0xb8, 0xb7, 0x7f, 0x3f,
+ 0xc4, 0x73, 0xba, 0xc5, 0xff, 0xc2, 0x86, 0x70, 0xcf, 0x3c, 0x76, 0x6c,
+ 0xb1, 0x50, 0x3f, 0x82, 0x2e, 0xbe, 0xc8, 0x61, 0x2c, 0x53, 0x9e, 0x10,
+ 0x08, 0x6a, 0x55, 0xe8, 0xed, 0x09, 0x41, 0x90, 0x60, 0xf1, 0xac, 0x7b,
+ 0x92, 0xf4, 0x43, 0xa5, 0x83, 0x90, 0x7c, 0x88, 0xa1, 0x67, 0xe8, 0x74,
+ 0x5f, 0xff, 0x9b, 0xa8, 0x73, 0xf2, 0xfe, 0xe3, 0x97, 0x50, 0x58, 0xbd,
+ 0xe9, 0x02, 0xc5, 0x68, 0xfd, 0x09, 0x5e, 0xd1, 0x91, 0xbb, 0xea, 0x61,
+ 0xf7, 0x84, 0xdd, 0xec, 0x61, 0x51, 0xa2, 0x94, 0x6c, 0x55, 0xdf, 0x69,
+ 0x5d, 0xf5, 0x2a, 0x8d, 0x48, 0x33, 0x39, 0x27, 0xb4, 0x6e, 0x10, 0x87,
+ 0xc0, 0xe5, 0xff, 0xe5, 0x23, 0x58, 0xd8, 0xee, 0x37, 0x96, 0xa9, 0xd4,
+ 0x63, 0xaf, 0x28, 0xa2, 0x29, 0x71, 0xda, 0x9c, 0x06, 0x3c, 0xae, 0x0f,
+ 0xce, 0xe9, 0x34, 0xab, 0xc0, 0x4a, 0x85, 0xef, 0xe1, 0x24, 0x53, 0x98,
+ 0x1c, 0xa6, 0x7a, 0xfa, 0x75, 0xa0, 0x51, 0x8f, 0xf6, 0x3c, 0x0a, 0x18,
+ 0xf1, 0xd1, 0xb8, 0x07, 0x38, 0x5b, 0xdd, 0x19, 0x5d, 0xff, 0xf7, 0x7b,
+ 0x1b, 0xf7, 0xae, 0x1f, 0xf3, 0xa8, 0x67, 0x77, 0x16, 0x2e, 0x17, 0x96,
+ 0x2f, 0xe7, 0xf6, 0x6b, 0xd2, 0xb1, 0x76, 0xa5, 0x62, 0xa3, 0xcf, 0x72,
+ 0x21, 0x8e, 0xe2, 0xdb, 0xf6, 0x05, 0x9f, 0x65, 0x8b, 0xf9, 0xf6, 0x0f,
+ 0x69, 0xd9, 0x62, 0xff, 0xf7, 0x9f, 0xe2, 0xfb, 0x3f, 0x5c, 0x93, 0x56,
+ 0x2f, 0xff, 0x3f, 0x50, 0xe3, 0xfb, 0xf3, 0xaf, 0x4a, 0xc5, 0xfc, 0x0e,
+ 0x4c, 0x7e, 0xa5, 0x62, 0xb1, 0x19, 0x1a, 0x4c, 0x64, 0xbb, 0xfd, 0x3a,
+ 0x68, 0x9b, 0x90, 0x58, 0xbc, 0xcd, 0xba, 0xa4, 0xae, 0x2f, 0xe6, 0x0f,
+ 0xff, 0x63, 0xac, 0x56, 0xe7, 0xb3, 0xf2, 0xab, 0xf9, 0xf5, 0xf6, 0x0c,
+ 0xeb, 0x17, 0xcf, 0xe8, 0x4a, 0xc5, 0x0d, 0x30, 0x1d, 0x42, 0x37, 0xe4,
+ 0x7d, 0x8b, 0xef, 0xfe, 0x6f, 0x66, 0xc5, 0x83, 0xfe, 0x44, 0xb1, 0x7f,
+ 0xd3, 0xd1, 0x60, 0xff, 0x91, 0x2c, 0x57, 0xcf, 0xff, 0xb9, 0x16, 0xff,
+ 0xe6, 0xf6, 0x6c, 0x58, 0x3f, 0xe4, 0x4b, 0x17, 0xfd, 0x3d, 0x16, 0x0f,
+ 0xf9, 0x12, 0xc5, 0xff, 0xe9, 0xee, 0xe1, 0x31, 0x48, 0x7b, 0xc9, 0xcc,
+ 0x45, 0x27, 0xc9, 0x7b, 0x91, 0x6f, 0x8b, 0xbb, 0x8c, 0xb1, 0x7c, 0x59,
+ 0x14, 0xac, 0x5f, 0xff, 0xbe, 0xc5, 0xe8, 0xb3, 0x58, 0x66, 0x6f, 0x9e,
+ 0x58, 0xb4, 0x7a, 0xc5, 0xff, 0xe9, 0xdb, 0xce, 0x3c, 0x28, 0x3f, 0xc4,
+ 0xb1, 0x7d, 0xd4, 0x51, 0x12, 0xc5, 0x62, 0x3f, 0x9c, 0x88, 0xea, 0xff,
+ 0x15, 0x64, 0xab, 0xa4, 0xeb, 0x17, 0x70, 0x6b, 0x15, 0xa3, 0x5e, 0xc2,
+ 0xf7, 0xe6, 0x0f, 0x93, 0x8b, 0x17, 0xcf, 0xdb, 0x52, 0xb1, 0x7f, 0xf3,
+ 0x44, 0x23, 0x99, 0x3e, 0x7f, 0xca, 0xc5, 0x40, 0xfa, 0x88, 0x92, 0xa0,
+ 0x8b, 0x36, 0x84, 0x95, 0xfb, 0xd2, 0x52, 0x05, 0x8b, 0xff, 0x14, 0x82,
+ 0x58, 0x72, 0xf1, 0x2c, 0x5f, 0xf7, 0x5e, 0x8a, 0x7d, 0xf6, 0x89, 0x62,
+ 0xbc, 0x7f, 0x42, 0x3d, 0xb4, 0xe9, 0x18, 0x67, 0x85, 0x0d, 0xf6, 0xec,
+ 0xdb, 0xaa, 0x43, 0xc2, 0xf8, 0x50, 0xce, 0x2c, 0x5d, 0x19, 0x9a, 0x3d,
+ 0x42, 0x31, 0xbf, 0x7d, 0xf5, 0xf6, 0x58, 0xbc, 0x5e, 0x65, 0x8b, 0xb0,
+ 0x78, 0x78, 0x9c, 0x28, 0xa8, 0x22, 0x7c, 0xee, 0x77, 0xf4, 0xeb, 0x69,
+ 0xd6, 0xcb, 0x17, 0xfd, 0xd8, 0x3f, 0xb4, 0x40, 0xc8, 0x96, 0x2a, 0x07,
+ 0xdf, 0xe3, 0x0b, 0xfc, 0x09, 0x03, 0x10, 0xb1, 0x62, 0xff, 0xfe, 0x2c,
+ 0xee, 0xe1, 0x9c, 0x07, 0x63, 0x1b, 0x90, 0xd3, 0x2c, 0x5f, 0xcd, 0xf9,
+ 0x29, 0x02, 0xc5, 0x3a, 0x30, 0x7b, 0x19, 0x47, 0x31, 0xdf, 0xfd, 0xb4,
+ 0xeb, 0x7c, 0xe7, 0x30, 0x78, 0xb1, 0x52, 0x9a, 0xee, 0x43, 0x8d, 0x8d,
+ 0x2f, 0xd2, 0x3e, 0x77, 0x44, 0xb1, 0x7f, 0xee, 0xe9, 0xeb, 0x93, 0xc2,
+ 0x9f, 0x2c, 0x5f, 0xa2, 0x7f, 0x48, 0x16, 0x2f, 0xcd, 0xee, 0xe7, 0xd8,
+ 0xc3, 0xeb, 0x94, 0x2b, 0xf7, 0x7f, 0x90, 0xda, 0x25, 0x8b, 0x3f, 0x0f,
+ 0xc8, 0x48, 0x55, 0xb2, 0x66, 0x3e, 0x8c, 0x2a, 0xff, 0xa7, 0xb3, 0x44,
+ 0x3c, 0xc3, 0x56, 0x2f, 0xff, 0xfb, 0x45, 0x9b, 0x18, 0x59, 0xd8, 0xb3,
+ 0xbb, 0x86, 0x70, 0x1d, 0x96, 0x2f, 0xfc, 0x5b, 0x3e, 0xb8, 0x2e, 0x10,
+ 0x96, 0x2f, 0xfb, 0x3d, 0xc0, 0xf8, 0x66, 0xf0, 0x58, 0xbf, 0x8b, 0x3d,
+ 0xcc, 0x09, 0x62, 0xff, 0xff, 0x98, 0xb6, 0x1f, 0xe7, 0x99, 0xd7, 0x27,
+ 0x5e, 0xe6, 0x6c, 0xb1, 0x52, 0x9f, 0x64, 0x0a, 0xf0, 0xf1, 0xdc, 0x0e,
+ 0x80, 0xc7, 0xc1, 0x17, 0x5f, 0xed, 0xdf, 0x9f, 0x7f, 0x3a, 0xc5, 0xf8,
+ 0x73, 0xe9, 0x1a, 0xc5, 0xff, 0x39, 0x03, 0x53, 0xe6, 0xf2, 0xc5, 0xfb,
+ 0x36, 0x62, 0xe9, 0x62, 0xba, 0x45, 0xeb, 0x9a, 0x7c, 0xa0, 0x8e, 0x2f,
+ 0x7b, 0xbe, 0xf1, 0x62, 0xff, 0x0d, 0xb8, 0x09, 0xe8, 0x96, 0x2f, 0xfe,
+ 0x9e, 0x9c, 0xff, 0x6f, 0x14, 0x9d, 0x62, 0xfb, 0xd8, 0x40, 0x58, 0xae,
+ 0x91, 0x35, 0xa3, 0x4f, 0x22, 0x5f, 0xee, 0xe6, 0x1c, 0xe0, 0xdd, 0x62,
+ 0xd1, 0x91, 0xbb, 0x62, 0xb3, 0x30, 0xc1, 0xd8, 0xda, 0x05, 0x03, 0x87,
+ 0xd6, 0x46, 0x5f, 0xbc, 0x6d, 0x0e, 0xeb, 0x14, 0x64, 0x7a, 0x76, 0x3c,
+ 0x34, 0xff, 0x0e, 0xa6, 0x8c, 0x80, 0xa3, 0xef, 0xe4, 0xb5, 0x0f, 0x46,
+ 0x3f, 0xd8, 0xf0, 0x38, 0x5f, 0x77, 0x18, 0xde, 0xfb, 0x1d, 0x62, 0xfb,
+ 0x76, 0x6d, 0xd5, 0x26, 0x09, 0x61, 0xac, 0x56, 0x8f, 0x0f, 0xe6, 0x37,
+ 0x8d, 0x9d, 0x96, 0x2f, 0x67, 0x6c, 0x58, 0xb1, 0xd6, 0x2e, 0x7d, 0x11,
+ 0xb0, 0x10, 0xf5, 0xff, 0xf8, 0x4d, 0xb1, 0xf2, 0x38, 0x5a, 0xcd, 0x40,
+ 0x38, 0x2c, 0x57, 0xd1, 0x0e, 0x45, 0x77, 0x1b, 0xe5, 0x8b, 0x85, 0x05,
+ 0x8b, 0xf6, 0x16, 0x7b, 0x8b, 0x17, 0xec, 0xe0, 0x9b, 0xa5, 0x8b, 0xc2,
+ 0xe8, 0x0b, 0x17, 0xbc, 0x36, 0x58, 0xbc, 0x70, 0xce, 0xb1, 0x7f, 0x31,
+ 0xc3, 0xd3, 0x74, 0xb1, 0x7f, 0xff, 0xfe, 0x78, 0x6e, 0x42, 0x6d, 0x8f,
+ 0x91, 0xc2, 0xd4, 0x50, 0x9e, 0xb3, 0x50, 0x0e, 0x0b, 0x15, 0xa4, 0x5e,
+ 0x78, 0xc2, 0xd1, 0x92, 0xac, 0xd7, 0x18, 0x0d, 0x22, 0xde, 0x1a, 0xda,
+ 0x22, 0xf8, 0xcb, 0x0c, 0x11, 0x3f, 0x0a, 0x44, 0x3f, 0x1c, 0x3a, 0x1c,
+ 0x36, 0xef, 0xf4, 0x66, 0x6b, 0x76, 0x6d, 0xd5, 0x26, 0x51, 0x7f, 0xec,
+ 0xf4, 0x30, 0x11, 0xd9, 0xf1, 0x2c, 0x5e, 0x35, 0x89, 0x62, 0xff, 0xf6,
+ 0x30, 0xff, 0x9a, 0xd4, 0xf6, 0x36, 0x56, 0x2f, 0xb7, 0x66, 0xdd, 0x52,
+ 0x69, 0x97, 0xde, 0x29, 0x3a, 0xc5, 0xfb, 0x36, 0x2c, 0xec, 0xb1, 0x4e,
+ 0x79, 0x84, 0x45, 0x46, 0xa6, 0x0d, 0x1e, 0x3b, 0xa4, 0xcf, 0xbe, 0xd8,
+ 0x0b, 0x17, 0xa4, 0x5d, 0x2c, 0x5f, 0x66, 0xce, 0x12, 0xc5, 0x61, 0xea,
+ 0x7c, 0x48, 0x87, 0xaf, 0xdf, 0x6e, 0x80, 0xeb, 0x17, 0xbe, 0xdc, 0x58,
+ 0xbe, 0x6d, 0x7c, 0x58, 0x78, 0xc1, 0x94, 0xdf, 0xb3, 0x7f, 0x66, 0xeb,
+ 0x15, 0x03, 0xe3, 0xc3, 0x9b, 0xfc, 0x3f, 0xb4, 0x5f, 0x73, 0xac, 0x52,
+ 0xc3, 0x1b, 0x5b, 0xfd, 0x27, 0xc1, 0x94, 0xf4, 0xb1, 0x7e, 0x1b, 0x82,
+ 0x49, 0x62, 0xfb, 0x85, 0x20, 0x58, 0xbf, 0xde, 0x91, 0xbe, 0xa7, 0xb2,
+ 0xc5, 0x61, 0xeb, 0xb1, 0x15, 0xfd, 0xf6, 0xe4, 0xe7, 0x16, 0x2f, 0xe1,
+ 0x37, 0xdf, 0x09, 0x62, 0x86, 0xb8, 0x9f, 0x91, 0xa4, 0x6f, 0x09, 0x68,
+ 0xa1, 0xac, 0x75, 0x6f, 0x8d, 0xb1, 0x99, 0x3f, 0x70, 0x83, 0xc5, 0xb7,
+ 0xff, 0xf1, 0xe3, 0x1b, 0x9c, 0x62, 0x62, 0xcd, 0x8f, 0x3b, 0xac, 0x54,
+ 0x62, 0x3e, 0xf2, 0x13, 0xb7, 0xd8, 0x77, 0xf2, 0xc5, 0xd1, 0xb7, 0x7a,
+ 0xb1, 0x77, 0x7c, 0x8d, 0xfb, 0xd3, 0xc4, 0xef, 0x84, 0x57, 0xee, 0xf2,
+ 0x37, 0xef, 0x9d, 0xf3, 0xbe, 0x2c, 0x5f, 0x77, 0xc8, 0xde, 0x37, 0x8d,
+ 0x16, 0x2b, 0xbc, 0x3f, 0xfe, 0xfb, 0x46, 0xbe, 0xf3, 0x7f, 0x16, 0x2f,
+ 0xf4, 0xc5, 0xd9, 0xb7, 0x10, 0x16, 0x2a, 0x34, 0x3d, 0xae, 0xfa, 0x91,
+ 0x5e, 0x06, 0x71, 0x62, 0xff, 0x7d, 0xc2, 0x1b, 0x36, 0xeb, 0x15, 0xde,
+ 0x9e, 0x94, 0x6c, 0x3b, 0x7b, 0x4d, 0xba, 0xc5, 0xef, 0xbc, 0x4b, 0x17,
+ 0xe6, 0xeb, 0xc2, 0x95, 0x8a, 0x19, 0xf2, 0xb8, 0xf1, 0x0f, 0x5f, 0x86,
+ 0xc4, 0xdb, 0xac, 0x57, 0x7a, 0x7a, 0xbd, 0xf5, 0x2d, 0xbf, 0xa4, 0xf9,
+ 0xf7, 0x82, 0xc5, 0xfb, 0xbe, 0xfb, 0xde, 0x64, 0xac, 0x5f, 0xe3, 0x22,
+ 0x7f, 0x90, 0xbc, 0xb1, 0x4b, 0x17, 0xf7, 0x7d, 0x5b, 0xef, 0xdd, 0x2b,
+ 0x11, 0xb1, 0x32, 0xbb, 0xe2, 0x23, 0x7b, 0xea, 0x85, 0x7f, 0x83, 0x3e,
+ 0x7b, 0x8f, 0xc5, 0x8b, 0x3a, 0xc5, 0x46, 0xc7, 0x8d, 0x1c, 0x6b, 0x7f,
+ 0x77, 0xaf, 0xbc, 0xf5, 0xc5, 0x8b, 0xfd, 0x3b, 0x69, 0x87, 0xb3, 0x2c,
+ 0x5f, 0xff, 0xbe, 0xc5, 0xe8, 0x66, 0xb2, 0x48, 0xb3, 0xcb, 0x15, 0x04,
+ 0x43, 0xb9, 0xad, 0xff, 0xf3, 0x6c, 0xdd, 0xb8, 0x63, 0x76, 0xdf, 0xef,
+ 0xa5, 0x8b, 0xf7, 0x66, 0x1e, 0x1d, 0x62, 0xfe, 0xe3, 0x6c, 0x53, 0xb2,
+ 0xc5, 0xf3, 0x02, 0x3b, 0x16, 0x2f, 0xfb, 0x93, 0xf9, 0x1f, 0xd8, 0xd5,
+ 0x8a, 0x30, 0xf7, 0xfc, 0x4b, 0x76, 0x76, 0x58, 0xb7, 0x24, 0xde, 0x11,
+ 0x1d, 0xfb, 0xd2, 0x53, 0x12, 0xc5, 0xff, 0x43, 0x98, 0x53, 0xd9, 0x80,
+ 0xb1, 0x58, 0x7c, 0x5d, 0x14, 0x5f, 0x3f, 0x74, 0xf1, 0x62, 0xff, 0x9c,
+ 0x78, 0x73, 0x0e, 0xc3, 0x58, 0xbf, 0x3f, 0x74, 0x93, 0xac, 0x5e, 0x9f,
+ 0x71, 0x62, 0xa0, 0x88, 0x03, 0x9d, 0x11, 0x4d, 0xee, 0xe1, 0xca, 0xc5,
+ 0x39, 0xe7, 0x88, 0xbe, 0xfd, 0x25, 0xbf, 0xe5, 0x62, 0xff, 0x9f, 0x93,
+ 0xee, 0x4f, 0xe5, 0x62, 0xfd, 0x91, 0xd9, 0xa9, 0x58, 0xbf, 0x1e, 0x7a,
+ 0xe1, 0x92, 0x7c, 0x41, 0x9c, 0x5f, 0xfd, 0x9e, 0xfb, 0x9f, 0x3d, 0xc0,
+ 0xf8, 0xb1, 0x7f, 0xec, 0x60, 0x4c, 0x35, 0x38, 0x4b, 0x15, 0x28, 0xc3,
+ 0xdd, 0x05, 0xd1, 0xaf, 0x9f, 0xb7, 0xfb, 0x2c, 0x5f, 0x72, 0x4a, 0x25,
+ 0x8b, 0xe9, 0xee, 0x8b, 0x16, 0x2f, 0x9e, 0x4b, 0xcb, 0x14, 0xc7, 0xd4,
+ 0x44, 0x7c, 0x26, 0xbf, 0xfc, 0x39, 0x34, 0xc9, 0x7d, 0x4f, 0xa7, 0xeb,
+ 0x17, 0xed, 0xd8, 0xa4, 0x35, 0x8a, 0xc3, 0xf4, 0xfa, 0x5d, 0xff, 0xd1,
+ 0x07, 0x3b, 0x19, 0x3f, 0xcd, 0x62, 0xc5, 0x61, 0xf4, 0xb1, 0x0d, 0xfe,
+ 0xee, 0x70, 0x18, 0xdf, 0x12, 0xc5, 0x41, 0x7a, 0x68, 0x64, 0x58, 0xaf,
+ 0xd1, 0x53, 0xc3, 0x2a, 0x28, 0x43, 0x9c, 0x8b, 0xf0, 0xf4, 0x01, 0x09,
+ 0x46, 0x9b, 0xc2, 0xff, 0x42, 0x47, 0xb4, 0x61, 0x5d, 0xc4, 0x17, 0xc1,
+ 0x39, 0x91, 0xcb, 0x17, 0xff, 0xb0, 0xc9, 0xec, 0xda, 0xe4, 0xe9, 0xf8,
+ 0xb1, 0x77, 0x51, 0x2c, 0x5f, 0xf1, 0x60, 0xca, 0x77, 0x9d, 0x2c, 0x5f,
+ 0xff, 0xf7, 0x23, 0x1e, 0x27, 0xf9, 0x4e, 0x98, 0x0c, 0xe3, 0x92, 0x58,
+ 0xac, 0x4c, 0xb6, 0x22, 0x83, 0xa6, 0x30, 0xd0, 0x0e, 0x2f, 0xf1, 0xc3,
+ 0x38, 0x0e, 0xe0, 0x58, 0xbf, 0x19, 0xad, 0x0b, 0xeb, 0x17, 0xe7, 0x36,
+ 0x4b, 0x75, 0x8a, 0xe1, 0xea, 0x78, 0xae, 0xfc, 0x79, 0xf4, 0x8d, 0x62,
+ 0xfd, 0x31, 0x33, 0x69, 0x62, 0xde, 0x93, 0xd0, 0xe1, 0x45, 0x4a, 0x64,
+ 0x79, 0x08, 0xa7, 0x72, 0xbc, 0xf9, 0xb2, 0xc5, 0xff, 0xed, 0xfe, 0xff,
+ 0x7d, 0x4c, 0x41, 0x67, 0xd6, 0x2b, 0xe7, 0xd4, 0x43, 0xb7, 0xe6, 0xea,
+ 0x19, 0xe5, 0x8b, 0xc0, 0x2c, 0x58, 0xb8, 0xb1, 0x62, 0x8c, 0x36, 0x40,
+ 0x1c, 0xbc, 0x79, 0xd2, 0xc5, 0xff, 0x39, 0x9f, 0x6d, 0x4f, 0x69, 0x58,
+ 0xa9, 0x3d, 0x8e, 0x0e, 0xdf, 0xf1, 0xda, 0x11, 0xc2, 0xfb, 0xe9, 0x62,
+ 0xb6, 0x46, 0xc6, 0x9e, 0x8e, 0x43, 0x7e, 0x6e, 0x7a, 0x46, 0xb1, 0x52,
+ 0x7b, 0x22, 0x31, 0xbf, 0xcc, 0x10, 0x63, 0x1e, 0x04, 0xb1, 0x7f, 0x9b,
+ 0x50, 0x6f, 0x36, 0xeb, 0x17, 0xff, 0xb3, 0x0b, 0x00, 0x59, 0xef, 0xe4,
+ 0x16, 0x2a, 0x55, 0x40, 0x68, 0x87, 0xf1, 0xc6, 0x31, 0x08, 0x8d, 0xfb,
+ 0x8d, 0x2f, 0x1b, 0x30, 0x58, 0xbb, 0x7f, 0xac, 0x5f, 0xbb, 0x16, 0x70,
+ 0xcc, 0x36, 0xfe, 0x1e, 0xbf, 0xf1, 0x31, 0xa5, 0x80, 0xdb, 0x02, 0x58,
+ 0xbf, 0xf7, 0x3e, 0xe6, 0x4b, 0x8f, 0x0e, 0xb1, 0x47, 0x3f, 0xff, 0x20,
+ 0x5f, 0xfe, 0x2c, 0x37, 0xed, 0x0f, 0x84, 0xc1, 0x9d, 0x62, 0xa4, 0xfb,
+ 0xf0, 0x8a, 0x9d, 0x34, 0xdf, 0xc6, 0x5b, 0x7f, 0x49, 0x78, 0x65, 0x2b,
+ 0x17, 0xd0, 0xe1, 0xe0, 0xb1, 0x7f, 0xd2, 0x4f, 0xbb, 0x79, 0x8d, 0x58,
+ 0xbf, 0xb5, 0x9a, 0x00, 0x25, 0x62, 0xa5, 0x11, 0x66, 0x92, 0x39, 0xcd,
+ 0xf4, 0x87, 0x3f, 0x58, 0xb9, 0xf6, 0x58, 0xbc, 0xcd, 0xba, 0xa4, 0xdc,
+ 0x2e, 0x8b, 0x8b, 0x17, 0x3c, 0x4b, 0x17, 0xcd, 0xe6, 0x89, 0x62, 0xef,
+ 0x73, 0x86, 0xef, 0xb0, 0xc5, 0x6c, 0x8c, 0x5d, 0xc6, 0x1c, 0xa8, 0x35,
+ 0x4b, 0xff, 0x6e, 0x67, 0x07, 0xfc, 0xdf, 0x34, 0xb1, 0x7e, 0xf4, 0x45,
+ 0x23, 0x58, 0xa9, 0x3e, 0xc7, 0x43, 0xbf, 0xed, 0x7d, 0xb3, 0x5b, 0x3e,
+ 0xcb, 0x17, 0xde, 0xe6, 0x7d, 0x62, 0x9c, 0xf7, 0x98, 0xee, 0xfa, 0x29,
+ 0x1e, 0x2c, 0x5f, 0xc0, 0x3e, 0x70, 0x44, 0xb1, 0x71, 0x84, 0xb1, 0x7f,
+ 0x71, 0xf3, 0xb3, 0x69, 0x62, 0xfe, 0xe4, 0xeb, 0x58, 0x12, 0xc5, 0x40,
+ 0xfd, 0x8e, 0x31, 0xe2, 0xfa, 0x74, 0x69, 0xb4, 0x29, 0x2f, 0xe2, 0x33,
+ 0xf9, 0xd0, 0x4b, 0x17, 0xfb, 0x0f, 0xd4, 0x27, 0x3c, 0xb1, 0x76, 0x6b,
+ 0x0f, 0x94, 0x06, 0x37, 0xe2, 0x03, 0x75, 0xc5, 0x8b, 0xfb, 0x3b, 0x3f,
+ 0xce, 0xcb, 0x15, 0x28, 0x84, 0x62, 0xc2, 0x29, 0xbd, 0x31, 0x3a, 0xc5,
+ 0xce, 0x6a, 0xc5, 0xa4, 0x8d, 0xac, 0x70, 0xed, 0x41, 0x77, 0x3c, 0x65,
+ 0x26, 0xc2, 0xdf, 0xa2, 0xfd, 0x43, 0xa0, 0xf0, 0xab, 0xfb, 0xf3, 0x10,
+ 0x14, 0x3d, 0xb9, 0x18, 0x7f, 0x98, 0xaf, 0xfc, 0xc3, 0x26, 0xed, 0xf9,
+ 0x8b, 0x8b, 0x17, 0xfb, 0x73, 0x1b, 0xe4, 0xc0, 0x58, 0xa5, 0x8b, 0xd3,
+ 0xb9, 0x2c, 0x57, 0x8d, 0x4f, 0x60, 0xcb, 0xe2, 0x6d, 0xf1, 0x62, 0xfc,
+ 0x08, 0x8a, 0x4e, 0xb1, 0x4c, 0x79, 0x64, 0x45, 0x46, 0xa6, 0x5a, 0xe8,
+ 0x27, 0x5e, 0x66, 0xeb, 0xc7, 0x27, 0x58, 0xb1, 0x2c, 0x5f, 0xf7, 0xc4,
+ 0xdc, 0xcc, 0x23, 0x56, 0x2f, 0xff, 0xd3, 0xb9, 0x99, 0xf7, 0xd4, 0xff,
+ 0x08, 0x72, 0xb1, 0x7e, 0x79, 0x2f, 0x4a, 0xc5, 0xff, 0xff, 0x7a, 0x4e,
+ 0xfe, 0x7d, 0xf3, 0x41, 0xeb, 0x53, 0xe6, 0xf2, 0xc5, 0x86, 0xb1, 0x7b,
+ 0x8d, 0xd6, 0x1f, 0xd3, 0x34, 0x59, 0xc6, 0x9b, 0x01, 0xce, 0x7e, 0xab,
+ 0xe8, 0x50, 0x5f, 0xe6, 0x8c, 0x2c, 0xda, 0x4d, 0x58, 0xbd, 0x9d, 0xce,
+ 0xb1, 0x52, 0xa8, 0xaf, 0x07, 0x3f, 0x1b, 0x89, 0x24, 0x76, 0x37, 0xbf,
+ 0xe9, 0x62, 0xfe, 0x61, 0x6e, 0xb1, 0x74, 0x3b, 0xd5, 0x8b, 0xfc, 0x5b,
+ 0x13, 0x69, 0xa0, 0xb1, 0x52, 0x7a, 0x02, 0x1d, 0xbf, 0xfe, 0x9f, 0x7d,
+ 0x8e, 0x66, 0xf2, 0xe5, 0x3d, 0x96, 0x2a, 0x08, 0xfa, 0xe4, 0x21, 0xfb,
+ 0x88, 0x6f, 0xf1, 0x08, 0xf3, 0xcf, 0x3a, 0xc5, 0xfe, 0x72, 0x93, 0xcf,
+ 0x5c, 0x58, 0xbf, 0x4e, 0xb5, 0x9d, 0xcb, 0x15, 0x28, 0x91, 0x88, 0xcc,
+ 0x8c, 0xef, 0x86, 0x60, 0x67, 0x58, 0xbf, 0x86, 0x59, 0xd9, 0xa0, 0xb1,
+ 0x4e, 0x7a, 0xa2, 0x26, 0xbf, 0xff, 0x7e, 0x23, 0x0e, 0x2f, 0x3e, 0xd9,
+ 0xe3, 0x73, 0xeb, 0x17, 0xf1, 0x4c, 0x51, 0x60, 0x16, 0x2f, 0x6d, 0xce,
+ 0x2c, 0x5f, 0xfd, 0xb7, 0x9c, 0x78, 0x50, 0x7f, 0x89, 0x62, 0xd1, 0x2c,
+ 0x54, 0x9e, 0xc6, 0xe8, 0xb7, 0xf9, 0xfb, 0x67, 0xd8, 0xb6, 0x58, 0xbb,
+ 0x0e, 0xb1, 0x50, 0x3c, 0xce, 0x1a, 0xd8, 0x25, 0x8b, 0xd3, 0x9a, 0x58,
+ 0xbf, 0xdf, 0x98, 0x3c, 0x76, 0x1d, 0x62, 0xa0, 0x7c, 0xa3, 0x13, 0xe0,
+ 0xe5, 0xf8, 0xce, 0xb8, 0xe6, 0xac, 0x56, 0xc7, 0xb7, 0xd1, 0x7d, 0x74,
+ 0x98, 0x33, 0x43, 0x8a, 0xff, 0xd9, 0xf7, 0xd0, 0xff, 0x25, 0xba, 0xc5,
+ 0xf0, 0xf3, 0x82, 0x58, 0xbf, 0xf1, 0x67, 0xb9, 0x26, 0x7b, 0x37, 0x58,
+ 0xbe, 0x33, 0xd8, 0x05, 0x8b, 0xff, 0xb0, 0x0f, 0xa8, 0xcf, 0xe7, 0x69,
+ 0x25, 0x8a, 0x82, 0x61, 0xd8, 0x7e, 0xe4, 0x7f, 0x40, 0xf1, 0x25, 0xfe,
+ 0xea, 0x12, 0x5e, 0xc0, 0x2c, 0x5f, 0x70, 0x0f, 0xe5, 0x8a, 0x82, 0xe3,
+ 0x6e, 0xe4, 0x2e, 0xb7, 0x11, 0x7f, 0xdd, 0xda, 0x37, 0x4e, 0x46, 0x6e,
+ 0x24, 0x90, 0xcd, 0x2f, 0xcd, 0xaf, 0x67, 0xd6, 0x2f, 0xb3, 0x85, 0x2b,
+ 0x17, 0xfe, 0x70, 0x4c, 0x07, 0xf9, 0x2d, 0xd6, 0x2a, 0x08, 0x88, 0xf9,
+ 0x47, 0x88, 0x6f, 0x10, 0xb7, 0x58, 0xbf, 0x43, 0x35, 0x9c, 0x58, 0xa3,
+ 0x9e, 0x37, 0x87, 0xa9, 0x62, 0xf0, 0x9b, 0xcb, 0x17, 0x0a, 0x56, 0x2a,
+ 0x06, 0xd3, 0xc3, 0xb4, 0xb1, 0x7d, 0xd6, 0xef, 0xa5, 0x8b, 0x46, 0x62,
+ 0x24, 0xba, 0x40, 0x39, 0x0f, 0x83, 0x2f, 0xfd, 0x85, 0xd7, 0xb3, 0x30,
+ 0xb6, 0x58, 0xa3, 0xa2, 0x13, 0xc8, 0xd7, 0xd8, 0x32, 0x1a, 0xc5, 0x49,
+ 0xe2, 0xf6, 0x23, 0xbf, 0xb3, 0x9c, 0x62, 0xdd, 0x62, 0xff, 0x8b, 0xdf,
+ 0x68, 0x09, 0x83, 0x58, 0xa9, 0x54, 0xfd, 0x8e, 0xcf, 0x1b, 0xee, 0x88,
+ 0xd8, 0xba, 0xc4, 0xb1, 0x7b, 0x5d, 0xd2, 0xb1, 0x77, 0x8c, 0xef, 0x86,
+ 0xc6, 0x21, 0x1b, 0xcc, 0xfb, 0x2c, 0x56, 0x1e, 0x91, 0xa6, 0xb7, 0xee,
+ 0xe7, 0xec, 0xda, 0x58, 0xb8, 0x86, 0xb1, 0x67, 0x58, 0xb4, 0x72, 0xc5,
+ 0x00, 0xd3, 0x78, 0x46, 0xa5, 0x11, 0x63, 0x2d, 0x23, 0xdb, 0xc6, 0x46,
+ 0x91, 0xa2, 0xc5, 0xfd, 0x9a, 0xdd, 0x9b, 0x75, 0x49, 0x0e, 0x58, 0x6b,
+ 0x17, 0xfd, 0xac, 0xf1, 0x90, 0xdb, 0x8e, 0xb1, 0x74, 0x86, 0xb1, 0x68,
+ 0x46, 0x22, 0x8b, 0x63, 0xcc, 0x12, 0x23, 0xcb, 0xf4, 0x0c, 0xec, 0x79,
+ 0x58, 0xb4, 0x16, 0x2f, 0xe1, 0x78, 0xa7, 0xdc, 0x58, 0xa7, 0x3c, 0x00,
+ 0x09, 0x54, 0xaa, 0x78, 0x78, 0x56, 0xc4, 0x5c, 0xd0, 0xcb, 0x24, 0x51,
+ 0x36, 0x5e, 0xd1, 0xbb, 0xac, 0x5d, 0x87, 0x58, 0xbd, 0xec, 0xee, 0x58,
+ 0xb4, 0xee, 0x6d, 0xfc, 0x2f, 0x50, 0x3f, 0xe0, 0x2b, 0xdf, 0xc5, 0x9e,
+ 0xe6, 0x0d, 0x62, 0xfa, 0x63, 0xc5, 0x2b, 0x17, 0xa2, 0xc1, 0xac, 0x5e,
+ 0x8a, 0x7c, 0xb1, 0x52, 0x6f, 0x04, 0x3d, 0x5a, 0x46, 0x81, 0xc8, 0x80,
+ 0x5b, 0xc6, 0x1b, 0x84, 0x1a, 0xc5, 0xe6, 0x8e, 0x35, 0x62, 0xfd, 0xc6,
+ 0xfe, 0x6e, 0xb1, 0x5d, 0x1f, 0x18, 0x06, 0x78, 0x43, 0x7e, 0x89, 0xfa,
+ 0xee, 0xc5, 0x8b, 0x1d, 0x62, 0x8c, 0x37, 0xf2, 0x5b, 0x7e, 0xc2, 0x1f,
+ 0xe5, 0x62, 0x86, 0x79, 0x01, 0x10, 0xde, 0xcd, 0x32, 0xc5, 0xff, 0xff,
+ 0x79, 0xcb, 0xc2, 0xf9, 0x9e, 0x06, 0x77, 0x7d, 0xa2, 0x33, 0xb9, 0x62,
+ 0xff, 0xb2, 0x47, 0xf9, 0xee, 0x98, 0x96, 0x2f, 0xf0, 0x1f, 0xff, 0xc0,
+ 0x32, 0xc5, 0x6e, 0x8f, 0xc7, 0x1c, 0x3b, 0x88, 0x0f, 0x2f, 0xfd, 0x9e,
+ 0xe7, 0xf3, 0x5a, 0xc0, 0x96, 0x2f, 0xfc, 0x5d, 0xcc, 0x4c, 0x71, 0xe0,
+ 0xd6, 0x2a, 0x55, 0x99, 0xe4, 0x28, 0x1e, 0x16, 0xed, 0x18, 0xf8, 0x67,
+ 0xbd, 0xc8, 0x17, 0xff, 0xc3, 0x7e, 0xc6, 0x73, 0xcd, 0xd7, 0x0e, 0x28,
+ 0x2c, 0x5d, 0x30, 0x58, 0xbf, 0xce, 0x71, 0xc9, 0x9e, 0x75, 0x8a, 0x8f,
+ 0x3c, 0xbf, 0x8b, 0xdf, 0xff, 0xbf, 0x9a, 0x68, 0x9f, 0xe3, 0x29, 0x10,
+ 0xf1, 0x62, 0xff, 0x84, 0x06, 0x1f, 0xe4, 0xbb, 0x2c, 0x5f, 0xf9, 0x87,
+ 0x23, 0xfb, 0x93, 0x9d, 0x62, 0xff, 0xd0, 0x6e, 0x18, 0xfd, 0x41, 0xb8,
+ 0xb1, 0x7f, 0xcc, 0x03, 0x33, 0xcf, 0xac, 0x58, 0xbf, 0xe6, 0xd7, 0x1b,
+ 0xfc, 0x9d, 0x96, 0x2b, 0xa4, 0x5a, 0x12, 0x0f, 0x63, 0x9b, 0xf4, 0xf1,
+ 0xba, 0x02, 0xc5, 0xf7, 0xfb, 0x9f, 0x65, 0x8b, 0xec, 0x3f, 0x7c, 0x8d,
+ 0x4b, 0x15, 0xb9, 0xff, 0x80, 0xa7, 0xc4, 0xf7, 0xf0, 0xb7, 0xcf, 0x14,
+ 0xac, 0x5f, 0xfe, 0x9e, 0x7e, 0x4b, 0xc6, 0x45, 0xbf, 0xe2, 0x58, 0xae,
+ 0x1f, 0xef, 0x62, 0xea, 0xc5, 0x79, 0x2f, 0x0a, 0x18, 0x89, 0x74, 0xaa,
+ 0x73, 0xbf, 0xc3, 0xc4, 0xa1, 0x63, 0xe8, 0x56, 0xdf, 0xc5, 0xe3, 0x38,
+ 0x22, 0x58, 0xbf, 0x34, 0x21, 0x9c, 0x58, 0xbf, 0xf7, 0x5c, 0x33, 0xb6,
+ 0x48, 0xc5, 0xb2, 0xc5, 0xef, 0x66, 0xeb, 0x17, 0x66, 0xeb, 0x16, 0xc3,
+ 0x0d, 0xb7, 0x87, 0xaf, 0xfb, 0xed, 0xae, 0xbd, 0x2f, 0xb2, 0xc5, 0xfa,
+ 0x5c, 0xa7, 0xb2, 0xc5, 0xed, 0xff, 0x12, 0xc5, 0xe2, 0xdc, 0xcd, 0xcf,
+ 0x22, 0x22, 0x8a, 0x82, 0x2e, 0x9a, 0x10, 0x74, 0xe9, 0xed, 0x1c, 0xbd,
+ 0x8a, 0x09, 0xec, 0x50, 0xe1, 0xbf, 0xd0, 0x9d, 0x6d, 0x3a, 0xd9, 0x62,
+ 0xfa, 0x5b, 0x40, 0x58, 0xbf, 0x3f, 0xc8, 0x5e, 0x58, 0xbf, 0xdb, 0xbf,
+ 0x30, 0x6d, 0xba, 0xc5, 0xfd, 0xfc, 0x27, 0xf8, 0x96, 0x28, 0x68, 0xac,
+ 0x88, 0x8b, 0xe5, 0x1e, 0x35, 0xbf, 0x6d, 0x3f, 0x6f, 0x2c, 0x5f, 0x9b,
+ 0x9d, 0xb3, 0x8b, 0x17, 0xe6, 0xf1, 0x93, 0x2b, 0x15, 0x29, 0xcd, 0xe4,
+ 0x38, 0x98, 0xf8, 0x05, 0x22, 0x2a, 0xbf, 0x19, 0xfc, 0x03, 0x2c, 0x5f,
+ 0xed, 0x4f, 0xd8, 0x70, 0x3a, 0xc5, 0xfe, 0x7e, 0xd3, 0xbe, 0x9b, 0xb2,
+ 0xc5, 0xfe, 0x7f, 0x47, 0x61, 0x31, 0xab, 0x15, 0xb1, 0xf7, 0x1c, 0xe2,
+ 0xfc, 0x66, 0xc2, 0xd4, 0x16, 0x2f, 0x66, 0x71, 0x62, 0xfe, 0x83, 0x6b,
+ 0x3a, 0xf2, 0xc5, 0xfc, 0x36, 0x3f, 0xdc, 0x25, 0x8a, 0x93, 0xde, 0xc2,
+ 0xfb, 0xfe, 0xcf, 0x70, 0x3e, 0x69, 0xb8, 0xb1, 0x7f, 0xd3, 0xf7, 0x35,
+ 0xf6, 0x63, 0xac, 0x5d, 0xb6, 0xcb, 0x17, 0xc6, 0x1b, 0x83, 0x58, 0xbc,
+ 0x0f, 0x3a, 0xc5, 0x0c, 0xf7, 0x00, 0x34, 0x44, 0xb7, 0xe7, 0xf7, 0x19,
+ 0xd6, 0x2f, 0xfd, 0x81, 0x36, 0x8d, 0x9d, 0xf0, 0xeb, 0x17, 0xff, 0xdf,
+ 0x7e, 0x0b, 0x6d, 0xfe, 0xfe, 0xf6, 0x6c, 0xb1, 0x7e, 0x8b, 0x0d, 0x7d,
+ 0x2c, 0x56, 0x1f, 0xf3, 0xaa, 0x5f, 0xe0, 0x69, 0x8b, 0xd8, 0x05, 0x8b,
+ 0xff, 0x9b, 0xd0, 0x63, 0x22, 0x84, 0xeb, 0x65, 0x8a, 0xd1, 0xfd, 0x80,
+ 0xce, 0xfe, 0x93, 0x22, 0xdf, 0xf1, 0x2c, 0x56, 0xcb, 0x91, 0x23, 0x29,
+ 0xc8, 0x51, 0x39, 0x1c, 0x45, 0x9a, 0x7a, 0x39, 0x07, 0xce, 0xda, 0x12,
+ 0xc0, 0x2e, 0x22, 0x7e, 0x42, 0xfc, 0x50, 0x9b, 0xee, 0x22, 0xbc, 0x1e,
+ 0xa0, 0xb1, 0x7f, 0xc5, 0x3d, 0xa2, 0x7f, 0x7e, 0x56, 0x2f, 0xe0, 0xfc,
+ 0x29, 0xcd, 0x96, 0x2f, 0xe0, 0x7d, 0x9f, 0xe2, 0x58, 0xbd, 0xc2, 0x82,
+ 0xc5, 0x41, 0x1a, 0xae, 0x3f, 0x11, 0xde, 0x8c, 0x3c, 0x5d, 0x7e, 0xce,
+ 0xd9, 0xa8, 0x2c, 0x52, 0xc5, 0xf6, 0xe5, 0x3e, 0x23, 0x6d, 0x1c, 0x55,
+ 0x7e, 0x6e, 0x73, 0x6e, 0x2c, 0x5f, 0xcc, 0x40, 0x0c, 0x1c, 0x58, 0xbf,
+ 0x78, 0x98, 0x1c, 0x58, 0xbd, 0xc3, 0xb2, 0xc5, 0xfe, 0x23, 0x43, 0xff,
+ 0xc5, 0xc5, 0x8a, 0x35, 0x15, 0x7d, 0x17, 0xc4, 0x50, 0x21, 0xdb, 0xff,
+ 0x85, 0xcf, 0xb4, 0x24, 0x87, 0x9f, 0x58, 0xbf, 0xe0, 0xe4, 0x11, 0x42,
+ 0x75, 0xb2, 0xc5, 0xfc, 0x4d, 0xe0, 0xe7, 0x75, 0x8a, 0x39, 0xf6, 0x11,
+ 0xed, 0xf1, 0x03, 0x60, 0x2c, 0x5f, 0xff, 0xe8, 0xb8, 0xe3, 0x32, 0x27,
+ 0x2e, 0xcd, 0x13, 0x78, 0x52, 0xb1, 0x58, 0x8a, 0xb7, 0x21, 0x62, 0x4b,
+ 0xff, 0xc5, 0xe9, 0x07, 0xd8, 0xbb, 0x67, 0x5c, 0x58, 0xbd, 0xa6, 0xd2,
+ 0xc5, 0x39, 0xf4, 0xc4, 0x99, 0x7f, 0xc1, 0x94, 0x33, 0xb1, 0x67, 0x16,
+ 0x2f, 0xf8, 0xfc, 0x33, 0x07, 0x25, 0xe5, 0x8b, 0xf4, 0x0c, 0xe7, 0x31,
+ 0x62, 0xff, 0x70, 0xcf, 0x18, 0x3c, 0x25, 0x8b, 0x01, 0x62, 0xba, 0x3c,
+ 0x8d, 0x1b, 0x54, 0xa3, 0x3f, 0x0e, 0x9d, 0xca, 0xfe, 0x16, 0xff, 0x9d,
+ 0x62, 0xc5, 0xf7, 0x5c, 0xf3, 0xac, 0x56, 0x1e, 0x9b, 0x17, 0xd4, 0xae,
+ 0xc6, 0x64, 0x20, 0x0d, 0x3a, 0x78, 0x6a, 0xe9, 0x03, 0xf1, 0xad, 0xb4,
+ 0x25, 0x80, 0x44, 0x51, 0x85, 0x72, 0x10, 0x17, 0xff, 0x43, 0x3b, 0xa1,
+ 0x9e, 0x9f, 0x73, 0x16, 0x2f, 0xff, 0xfe, 0x67, 0xf4, 0x96, 0xee, 0x73,
+ 0xbf, 0x39, 0x9f, 0x7e, 0x0b, 0x65, 0x8b, 0x19, 0xd2, 0x2e, 0x7e, 0x8f,
+ 0x7e, 0x61, 0x1b, 0x21, 0xac, 0x5f, 0x66, 0xa7, 0x8b, 0x17, 0xb7, 0xef,
+ 0x74, 0xb1, 0x51, 0xb1, 0xe3, 0x08, 0x8a, 0xb1, 0x18, 0x51, 0x15, 0x93,
+ 0x85, 0xf4, 0x6f, 0x1b, 0xc6, 0xfd, 0xe2, 0xc5, 0xf4, 0x50, 0x11, 0xab,
+ 0x17, 0xf6, 0x79, 0xc7, 0x87, 0x58, 0xbe, 0x28, 0x39, 0xd6, 0x2c, 0x64,
+ 0x47, 0x9e, 0xc5, 0xb7, 0xf3, 0x97, 0x66, 0x8b, 0xbe, 0xab, 0x17, 0xf4,
+ 0xc5, 0xd4, 0x33, 0xb2, 0xc5, 0xff, 0xa4, 0xa7, 0x86, 0x04, 0xdd, 0x71,
+ 0x62, 0xa2, 0x45, 0x5f, 0x0e, 0x3c, 0x65, 0x77, 0x79, 0x1a, 0x2c, 0x5e,
+ 0x1e, 0x1d, 0x62, 0xfc, 0xcd, 0xd4, 0x38, 0xb1, 0x7b, 0xbb, 0xcc, 0x61,
+ 0xe3, 0x68, 0x76, 0xa3, 0x75, 0x4a, 0x32, 0x70, 0x37, 0x56, 0x86, 0xa7,
+ 0x8c, 0x43, 0x68, 0xbb, 0x80, 0x58, 0xbf, 0xa1, 0xc6, 0x38, 0xf8, 0xb1,
+ 0x46, 0x1e, 0x3b, 0x0c, 0x52, 0xc5, 0x2c, 0x5b, 0x80, 0x2e, 0x38, 0x19,
+ 0x7f, 0xfd, 0xf9, 0x0e, 0x33, 0xc4, 0xc0, 0xe7, 0x24, 0x09, 0x17, 0x1b,
+ 0x8b, 0x14, 0x33, 0xec, 0x35, 0x52, 0xe1, 0xe2, 0xc5, 0x2c, 0x5f, 0x4e,
+ 0xcd, 0xc5, 0x8a, 0x8d, 0x46, 0xbf, 0x60, 0xca, 0x31, 0x32, 0x3c, 0x84,
+ 0x93, 0x91, 0xb2, 0x35, 0xfd, 0xdc, 0xc0, 0x3c, 0xf1, 0x62, 0xfd, 0xcc,
+ 0xed, 0xf7, 0x58, 0xba, 0x40, 0xb1, 0x4b, 0x01, 0x96, 0xf5, 0xe3, 0xdd,
+ 0x12, 0x0d, 0x7d, 0x16, 0x00, 0x84, 0x75, 0xfe, 0x11, 0x78, 0xc2, 0x00,
+ 0x16, 0x2f, 0xb9, 0xdb, 0x38, 0xb1, 0x7f, 0xee, 0x76, 0x68, 0xb6, 0x62,
+ 0x68, 0x96, 0x2f, 0xfd, 0x3d, 0xd1, 0x37, 0x66, 0xf7, 0x69, 0x58, 0xbf,
+ 0xf6, 0x0e, 0x61, 0x3a, 0x3f, 0xba, 0x58, 0xbf, 0x98, 0x11, 0x14, 0x8d,
+ 0x62, 0xff, 0x8b, 0x36, 0x1f, 0xf0, 0xbc, 0xb1, 0x7b, 0xcf, 0xc5, 0x8b,
+ 0xfb, 0x53, 0xda, 0x4b, 0xcb, 0x17, 0xff, 0x64, 0x30, 0x8c, 0xfc, 0xc4,
+ 0x21, 0xac, 0x53, 0x9f, 0xa8, 0x0b, 0xea, 0x55, 0x32, 0xec, 0x51, 0x86,
+ 0xb1, 0x12, 0xe9, 0x0c, 0xe8, 0xdf, 0x40, 0x22, 0xee, 0x1c, 0xfa, 0x12,
+ 0x57, 0xc6, 0x08, 0xce, 0xcb, 0x15, 0x1b, 0xbe, 0x83, 0x27, 0x79, 0x0c,
+ 0x3e, 0xf6, 0x11, 0x11, 0xa4, 0x20, 0x63, 0x68, 0x73, 0x77, 0xd9, 0x7f,
+ 0x7c, 0x2d, 0xef, 0xac, 0x30, 0x63, 0x53, 0xbc, 0x6b, 0x2a, 0x99, 0xf5,
+ 0x6d, 0xa5, 0x09, 0xc2, 0x36, 0xd1, 0xcb, 0x1d, 0xc9, 0xfb, 0x33, 0x63,
+ 0xe2, 0xde, 0x53, 0x47, 0x51, 0xa5, 0xbc, 0x32, 0x62, 0x9c, 0xf1, 0xd4,
+ 0xb9, 0x43, 0xcb, 0x49, 0xfc, 0xe7, 0x0b, 0x4e, 0x19, 0x02, 0x52, 0xf9,
+ 0x47, 0xd1, 0xc9, 0xcd, 0x6f, 0x4f, 0x9c, 0x0a, 0x51, 0x2f, 0x69, 0x50,
+ 0x01, 0x42, 0xa6, 0x3a, 0x35, 0xd0, 0xe5, 0xab, 0x77, 0x42, 0x46, 0xff,
+ 0xbe, 0xcf, 0x09, 0xf7, 0x31, 0x62, 0xfa, 0x60, 0xdd, 0x96, 0x2f, 0xef,
+ 0x75, 0xc7, 0x21, 0xac, 0x5f, 0xfd, 0xac, 0xeb, 0x7f, 0xbf, 0xb8, 0xdd,
+ 0x2c, 0x5f, 0xa7, 0x9a, 0x10, 0x16, 0x2f, 0xff, 0xe3, 0xe7, 0xb8, 0x1f,
+ 0x0b, 0x3c, 0x20, 0x1d, 0xa0, 0xb1, 0x7d, 0x83, 0x68, 0x2c, 0x5e, 0x0c,
+ 0xa0, 0xb1, 0x4e, 0x78, 0x00, 0x22, 0xbb, 0x78, 0xc9, 0x4e, 0xeb, 0x63,
+ 0x87, 0x24, 0x01, 0x79, 0x24, 0x70, 0xa7, 0xd0, 0x9d, 0xa8, 0xc5, 0xcf,
+ 0xd1, 0x4e, 0x42, 0xdf, 0xe7, 0x8e, 0x0f, 0xa0, 0x72, 0x56, 0x2f, 0xa7,
+ 0x50, 0x3a, 0xc5, 0xff, 0x44, 0xd2, 0x53, 0x10, 0xa5, 0x62, 0xf7, 0xde,
+ 0x3d, 0x62, 0xff, 0xa1, 0x9e, 0x32, 0x4d, 0xd4, 0xac, 0x5f, 0x47, 0x66,
+ 0xa5, 0x62, 0xf7, 0x1a, 0x3d, 0x62, 0xde, 0x58, 0xac, 0x3d, 0x7e, 0x89,
+ 0x63, 0x88, 0x2f, 0xfe, 0x8b, 0xf9, 0xd4, 0x3b, 0x49, 0x44, 0x35, 0x8b,
+ 0xe1, 0x8b, 0xdc, 0x58, 0xa5, 0x8a, 0xc3, 0x60, 0x11, 0x25, 0xff, 0xf8,
+ 0xb2, 0x1f, 0x9d, 0x66, 0x11, 0xba, 0xd4, 0xac, 0x5f, 0xe6, 0xfb, 0x06,
+ 0x7c, 0xe2, 0xc5, 0xe6, 0xd1, 0xab, 0x17, 0xa4, 0x71, 0xba, 0xc5, 0xa3,
+ 0x25, 0x56, 0xe6, 0xc7, 0x38, 0x47, 0xb9, 0xcf, 0x44, 0x0f, 0x09, 0x26,
+ 0x32, 0x27, 0xae, 0x10, 0xf6, 0x54, 0x08, 0xd0, 0x31, 0xeb, 0xfd, 0x19,
+ 0x9a, 0xdd, 0x9b, 0x75, 0x49, 0xe6, 0x54, 0xc3, 0x43, 0x5e, 0x10, 0x8e,
+ 0x1c, 0xa2, 0x9c, 0xbd, 0x56, 0x5e, 0xab, 0x40, 0x8d, 0x4e, 0x48, 0x1e,
+ 0x17, 0x9f, 0x9d, 0x8f, 0x2b, 0xd5, 0xcf, 0xe4, 0xb0, 0xde, 0xd0, 0xb7,
+ 0xbf, 0xd1, 0x99, 0xad, 0xd9, 0xb7, 0x54, 0x92, 0xc5, 0xd1, 0xbc, 0x6a,
+ 0x58, 0xbb, 0xdb, 0x2c, 0x59, 0xd6, 0x2f, 0xff, 0xa1, 0x3d, 0xa6, 0x23,
+ 0x38, 0xfa, 0x29, 0x89, 0x62, 0xf3, 0xc6, 0x73, 0x0f, 0x95, 0xc4, 0x6f,
+ 0xff, 0xdf, 0xc2, 0xc3, 0x7e, 0xd0, 0xf8, 0x4c, 0x19, 0xd6, 0x2f, 0xc5,
+ 0x9c, 0x23, 0xac, 0x5f, 0x6e, 0xcd, 0xba, 0xa4, 0xc2, 0x2a, 0x08, 0xb0,
+ 0xdd, 0x63, 0x44, 0xf7, 0xde, 0x91, 0xe2, 0xc5, 0xff, 0xf6, 0x10, 0xe7,
+ 0xf3, 0xd7, 0xb0, 0x98, 0xeb, 0x17, 0x88, 0x5b, 0xac, 0x54, 0x9f, 0x63,
+ 0x27, 0x5f, 0xfe, 0xc1, 0x94, 0xee, 0x67, 0xe7, 0x62, 0x12, 0xc5, 0xff,
+ 0x37, 0x5c, 0x30, 0x73, 0x9d, 0x2c, 0x5f, 0xff, 0xde, 0xc7, 0xd7, 0x3c,
+ 0x4e, 0x0e, 0x4f, 0xb8, 0xeb, 0x17, 0xb3, 0xce, 0xb1, 0x4b, 0x16, 0xc5,
+ 0x8a, 0x94, 0x49, 0x9d, 0x6b, 0x83, 0x91, 0xc1, 0x97, 0xf0, 0xb4, 0xfb,
+ 0x31, 0xd6, 0x2d, 0x19, 0x1a, 0x95, 0xf6, 0xc9, 0x18, 0xdf, 0xb2, 0x1c,
+ 0x8e, 0x62, 0x78, 0x47, 0x7c, 0x80, 0x09, 0x9c, 0x86, 0x7c, 0x71, 0xfd,
+ 0xfe, 0x8c, 0xcd, 0x6e, 0xcd, 0xba, 0xa4, 0xcb, 0x2f, 0xfd, 0xdf, 0x23,
+ 0x4c, 0x87, 0xf1, 0xe1, 0xc5, 0x8b, 0xa0, 0xeb, 0x17, 0xfe, 0x8d, 0xfb,
+ 0xef, 0xec, 0xfe, 0x86, 0x71, 0x62, 0x96, 0x2c, 0xcb, 0x15, 0x25, 0xe9,
+ 0xa1, 0x97, 0xff, 0xbe, 0xfa, 0xfe, 0x4f, 0x8b, 0x35, 0x2b, 0x16, 0x82,
+ 0xc5, 0xcc, 0x6a, 0xc5, 0x8d, 0x58, 0xb1, 0xab, 0x15, 0x26, 0x9b, 0x42,
+ 0x77, 0xd1, 0x86, 0xc6, 0xae, 0xf1, 0x62, 0x92, 0x2f, 0x46, 0x06, 0x75,
+ 0x8a, 0xdc, 0xf8, 0x78, 0x66, 0x20, 0xcb, 0xec, 0xd3, 0x0d, 0x62, 0x86,
+ 0x9c, 0x5e, 0x10, 0x1a, 0x90, 0xe2, 0x44, 0x7d, 0xc8, 0x40, 0xf8, 0xc2,
+ 0xe9, 0xfa, 0xc5, 0x80, 0xb1, 0x71, 0xbb, 0x2c, 0x5b, 0x50, 0x35, 0x98,
+ 0x25, 0x6f, 0x2c, 0x56, 0xe7, 0xf6, 0xc8, 0x7e, 0x26, 0xba, 0x10, 0x58,
+ 0xa5, 0x8a, 0x58, 0x62, 0x65, 0xe8, 0x14, 0xac, 0x50, 0x0d, 0xaf, 0x86,
+ 0x6d, 0xf5, 0x8a, 0x58, 0xa8, 0x17, 0xc6, 0x89, 0x58, 0xd5, 0x8a, 0x94,
+ 0x66, 0x3a, 0xc8, 0x0f, 0xfc, 0x43, 0x7f, 0xfe, 0x1b, 0xfb, 0xf8, 0x37,
+ 0xc1, 0xb6, 0xcc, 0x4b, 0x17, 0xfc, 0xdd, 0x16, 0x75, 0xe9, 0x35, 0x62,
+ 0xff, 0x6d, 0xd7, 0x24, 0x7e, 0x75, 0x8b, 0xf4, 0xe7, 0x69, 0xe2, 0xc5,
+ 0xa5, 0x8f, 0x7c, 0x23, 0x6b, 0xf8, 0x8d, 0x03, 0x7b, 0x8b, 0x17, 0x6a,
0x0b, 0x15, 0x27, 0x8e, 0xc5, 0xf5, 0x29, 0xbe, 0x32, 0xa1, 0x42, 0x68,
- 0x4d, 0xd7, 0xff, 0xdf, 0xc7, 0x87, 0x3f, 0x81, 0x1f, 0xcf, 0x05, 0x8b,
- 0xe6, 0x84, 0x06, 0xb1, 0x77, 0xbc, 0xb1, 0x7f, 0x14, 0x8b, 0x7f, 0xb2,
- 0xc5, 0xed, 0x7d, 0xb6, 0x3c, 0x61, 0x8c, 0x5f, 0xb5, 0x3e, 0x6f, 0xac,
- 0x53, 0x9e, 0xe3, 0x1a, 0x5e, 0x0c, 0x30, 0xd2, 0x2f, 0xf4, 0x3b, 0xf6,
- 0xa7, 0x3b, 0x48, 0x8c, 0x34, 0x37, 0xff, 0x78, 0x46, 0xe7, 0x7e, 0x1e,
- 0x61, 0xab, 0x15, 0x28, 0x91, 0x12, 0x4d, 0xff, 0x09, 0xbb, 0xcf, 0x3f,
- 0x61, 0xac, 0x5d, 0x3c, 0x58, 0xa8, 0x2a, 0x5d, 0x1a, 0x8f, 0xe1, 0x8a,
- 0x50, 0xd2, 0xe1, 0x17, 0x43, 0xcb, 0x05, 0x16, 0x2d, 0xd1, 0x62, 0xa3,
- 0x51, 0xaa, 0x80, 0xb5, 0xfc, 0xed, 0xc0, 0x70, 0x4b, 0x17, 0xff, 0x3c,
- 0x1b, 0x8c, 0x42, 0xdf, 0x38, 0x91, 0x7f, 0xff, 0x7d, 0xfd, 0xfc, 0xe1,
- 0x61, 0xc5, 0xcf, 0xb4, 0x16, 0x2f, 0xf4, 0xc3, 0xcd, 0xf6, 0x1a, 0xc5,
- 0xf3, 0x78, 0xde, 0x2c, 0x54, 0xa3, 0xdb, 0x11, 0x34, 0xb6, 0xc6, 0x77,
- 0xb9, 0xc1, 0x2c, 0x5e, 0xdd, 0xb4, 0xb1, 0x7f, 0xff, 0xcf, 0xe9, 0x26,
- 0xf7, 0x30, 0xbb, 0xf4, 0x9e, 0x75, 0x12, 0xc5, 0x3a, 0x21, 0x18, 0x7a,
- 0xd0, 0x58, 0xb4, 0x16, 0x2d, 0x05, 0x8b, 0xc1, 0x86, 0x1a, 0xc5, 0xb7,
- 0x48, 0x8c, 0x34, 0x35, 0x27, 0xfa, 0x68, 0x93, 0x89, 0x00, 0xce, 0xee,
- 0x09, 0x62, 0xda, 0x58, 0xbf, 0x49, 0x0f, 0x0d, 0x58, 0xa9, 0x3d, 0x2c,
- 0x18, 0x38, 0x95, 0xa5, 0x62, 0x96, 0x2f, 0xc2, 0xe7, 0xda, 0x0b, 0x18,
- 0x4c, 0xbf, 0xfe, 0xe3, 0xef, 0x85, 0xa9, 0x2c, 0x1e, 0x1a, 0xb1, 0x47,
- 0x44, 0x2f, 0x8d, 0xaf, 0xff, 0xb0, 0x7f, 0x67, 0x84, 0x33, 0xcc, 0x40,
- 0x58, 0xbf, 0xce, 0x71, 0x73, 0xed, 0x05, 0x8d, 0x1e, 0x75, 0xfb, 0x99,
- 0xd3, 0xee, 0xb1, 0x43, 0x3e, 0xff, 0x22, 0xdb, 0xb5, 0x8b, 0x1a, 0xb1,
- 0x61, 0x2c, 0x51, 0x1a, 0x5e, 0x09, 0xd0, 0xd3, 0xfc, 0xc8, 0x51, 0x34,
- 0x38, 0x38, 0x45, 0xe3, 0x8b, 0xb8, 0x6a, 0xc5, 0xb1, 0x62, 0xe1, 0x02,
- 0x4d, 0x50, 0xc6, 0x6d, 0x2b, 0x17, 0xf4, 0x8f, 0xf3, 0xee, 0x2c, 0x53,
- 0x9b, 0xf2, 0x11, 0xbf, 0xff, 0xa7, 0x38, 0xe3, 0x1e, 0x7a, 0x19, 0xad,
- 0xf3, 0xeb, 0x17, 0xff, 0xff, 0xa4, 0x6e, 0x3f, 0xcc, 0x34, 0xcd, 0xdc,
- 0x39, 0xee, 0xf7, 0x7d, 0x1a, 0xb1, 0x5c, 0x46, 0xbf, 0x96, 0xef, 0xe2,
- 0x93, 0x94, 0xe2, 0xc5, 0xff, 0xd2, 0xda, 0xf7, 0xf0, 0x62, 0xf7, 0x16,
- 0x2e, 0xce, 0x8b, 0x17, 0x42, 0x56, 0x2f, 0x70, 0x66, 0xac, 0x56, 0xca,
- 0x90, 0xc6, 0xd7, 0x90, 0xf6, 0x88, 0x8f, 0xe5, 0x7e, 0x45, 0x10, 0xc9,
- 0x82, 0xf7, 0xff, 0xb3, 0xbf, 0x19, 0xe7, 0xf7, 0xf0, 0x6e, 0xb1, 0x7f,
- 0xff, 0xfa, 0x7d, 0xc7, 0xe7, 0x27, 0xdf, 0x79, 0xd0, 0x0e, 0xd0, 0x87,
- 0x8d, 0x58, 0xa3, 0x51, 0x8b, 0xf4, 0xcb, 0x9f, 0xb5, 0x8b, 0xef, 0x93,
- 0xca, 0xc5, 0xd0, 0xfa, 0xc5, 0x31, 0xb9, 0x01, 0x0d, 0xd2, 0x75, 0x8b,
- 0xff, 0xe2, 0x14, 0x21, 0x3e, 0xfe, 0x1c, 0xc9, 0x02, 0xc5, 0xfe, 0xc2,
- 0x21, 0x43, 0x82, 0x58, 0xa9, 0x44, 0x27, 0xd4, 0x6f, 0xfe, 0x7d, 0xa7,
- 0xef, 0x3e, 0xe0, 0xb8, 0xb1, 0x7f, 0xf0, 0xa1, 0x9c, 0xd4, 0xbc, 0x1b,
- 0x89, 0x17, 0xff, 0xf8, 0xb3, 0xa0, 0xe7, 0xef, 0xfc, 0x21, 0xe9, 0xfb,
- 0x82, 0xc5, 0x9f, 0x48, 0xeb, 0x24, 0x5e, 0x22, 0x54, 0x13, 0x41, 0xf4,
- 0x61, 0xb7, 0x6f, 0x19, 0x1b, 0xb6, 0x8c, 0x71, 0xa2, 0x4c, 0xc6, 0xed,
- 0xb4, 0x35, 0xe1, 0x0e, 0x31, 0xc7, 0x55, 0x92, 0xa7, 0x4d, 0x84, 0x76,
- 0xe4, 0xfa, 0x8c, 0x90, 0xe7, 0x5f, 0x85, 0x13, 0x42, 0x78, 0x10, 0x8d,
- 0x29, 0x45, 0x3c, 0x95, 0x81, 0xe8, 0xcf, 0xfa, 0x12, 0x06, 0xa3, 0x1c,
- 0x40, 0x64, 0x7b, 0x97, 0xff, 0xa3, 0x0e, 0xd0, 0x8c, 0xcd, 0x6e, 0xcd,
- 0xba, 0xa2, 0x8c, 0x2f, 0xef, 0xb0, 0x53, 0xec, 0x14, 0x58, 0xbe, 0x7f,
- 0x34, 0x72, 0xc5, 0xfc, 0xda, 0x01, 0xe4, 0x0b, 0x17, 0xd3, 0xa9, 0x02,
- 0xc5, 0xf8, 0x72, 0x79, 0x31, 0x62, 0xf4, 0xbf, 0x96, 0x2a, 0x4f, 0x17,
- 0xe5, 0x35, 0x12, 0x36, 0xfe, 0x4b, 0xd0, 0xb8, 0xc6, 0x7b, 0xff, 0xcd,
+ 0x4d, 0xd7, 0xff, 0xdf, 0xc7, 0x87, 0x3f, 0x9d, 0xcf, 0xe7, 0x82, 0xc5,
+ 0xf3, 0x42, 0x03, 0x58, 0xbf, 0xfc, 0x46, 0xb4, 0x21, 0x3b, 0x37, 0xb3,
+ 0x65, 0x8b, 0xfd, 0xc1, 0xb3, 0x1b, 0x9b, 0x2c, 0x5f, 0xfb, 0x59, 0x84,
+ 0x6f, 0x1f, 0xaf, 0x2c, 0x54, 0x9f, 0xab, 0x9a, 0xdf, 0xfe, 0xd9, 0xf9,
+ 0xcc, 0x84, 0x24, 0x31, 0x6c, 0xb1, 0x77, 0xbc, 0xb1, 0x7f, 0x14, 0x8b,
+ 0x7f, 0xb2, 0xc5, 0xdf, 0x6d, 0x8f, 0x18, 0x63, 0x17, 0x49, 0xd6, 0x2b,
+ 0x47, 0x8a, 0x45, 0xd7, 0xed, 0x4f, 0x9b, 0xeb, 0x14, 0xe7, 0x92, 0xc4,
+ 0x37, 0x82, 0x08, 0x24, 0x8b, 0xfd, 0x0e, 0xbd, 0xa9, 0xce, 0x92, 0x23,
+ 0x0d, 0x0d, 0xff, 0x00, 0xf9, 0xd7, 0x30, 0x8d, 0x58, 0xbf, 0xfb, 0xc2,
+ 0x37, 0x3a, 0xf0, 0xf3, 0x0d, 0x58, 0xa9, 0x46, 0x63, 0xa4, 0x88, 0xee,
+ 0xff, 0x84, 0xdd, 0x67, 0x9f, 0xa0, 0x96, 0x2e, 0x9e, 0x2c, 0x54, 0x17,
+ 0x01, 0x86, 0xa5, 0x84, 0x66, 0xc3, 0x07, 0x44, 0x1f, 0x8c, 0x88, 0xa3,
+ 0x0d, 0xe1, 0x77, 0x63, 0xcb, 0x77, 0x8b, 0x16, 0xec, 0xb1, 0x51, 0xa8,
+ 0xd5, 0xc0, 0x5e, 0xf1, 0xbd, 0x1a, 0xb1, 0x78, 0x1c, 0x12, 0xc5, 0x9a,
+ 0x4d, 0xff, 0x08, 0x6d, 0x2b, 0x17, 0xfe, 0x17, 0xa1, 0x26, 0x8b, 0xf2,
+ 0x75, 0x8b, 0xfe, 0xd6, 0x85, 0xb0, 0x1b, 0xdc, 0x58, 0xb3, 0xee, 0x88,
+ 0xe2, 0x11, 0x0d, 0x06, 0x9d, 0x1d, 0x3f, 0x85, 0x9d, 0xe6, 0xd6, 0xeb,
+ 0x17, 0xbf, 0x87, 0x58, 0xbf, 0xde, 0xd4, 0xe7, 0x5a, 0x9d, 0x8d, 0xdf,
+ 0x87, 0xaf, 0xfd, 0x0c, 0xea, 0x1e, 0x29, 0x3f, 0x16, 0x2f, 0xfd, 0x06,
+ 0xe3, 0x10, 0xb7, 0xce, 0x24, 0x5f, 0xfe, 0xcf, 0xe6, 0xff, 0x6c, 0xdc,
+ 0x85, 0xc5, 0x8a, 0x74, 0x45, 0x11, 0xfd, 0xff, 0xfd, 0xf7, 0xf7, 0xf3,
+ 0x85, 0x87, 0x17, 0x3e, 0xd0, 0x58, 0xbf, 0xd3, 0x0f, 0x37, 0xd8, 0x6b,
+ 0x17, 0xcd, 0xe3, 0x78, 0xb1, 0x52, 0x8d, 0x3c, 0x21, 0xd2, 0xdb, 0x19,
+ 0xde, 0xe7, 0x04, 0xb1, 0x7f, 0x14, 0xc5, 0x17, 0x25, 0x62, 0xf6, 0xed,
+ 0xa5, 0x8b, 0xff, 0xff, 0xfd, 0xf1, 0x31, 0xbc, 0x16, 0xc7, 0x16, 0x9a,
+ 0x05, 0x9d, 0x01, 0xbd, 0xc7, 0x2e, 0xa0, 0xb1, 0x7f, 0xfc, 0xde, 0xe6,
+ 0x17, 0x5e, 0x93, 0xce, 0xa2, 0x58, 0xbc, 0xfe, 0x91, 0xa3, 0x90, 0xa1,
+ 0x27, 0x58, 0x9b, 0x43, 0x97, 0xb4, 0x60, 0x56, 0x82, 0xc5, 0xfa, 0x13,
+ 0xb3, 0x79, 0x62, 0xd0, 0x58, 0xb4, 0x16, 0x2f, 0x04, 0x10, 0x4b, 0x16,
+ 0xdd, 0x22, 0x30, 0xd0, 0xdf, 0x80, 0x3f, 0xb6, 0xcb, 0x15, 0x28, 0xd0,
+ 0x80, 0x91, 0xa5, 0x2e, 0x24, 0x03, 0x32, 0x26, 0xb6, 0x96, 0x2f, 0xd2,
+ 0x43, 0xc3, 0x56, 0x2c, 0x12, 0xc5, 0x61, 0xe6, 0x9c, 0x48, 0x8a, 0x2d,
+ 0x2b, 0x14, 0xb1, 0x7e, 0x17, 0x3e, 0xd0, 0x58, 0xc2, 0x65, 0xff, 0xf7,
+ 0x1f, 0x7c, 0x2d, 0x49, 0x60, 0xf0, 0xd5, 0x8b, 0xff, 0x9b, 0x5b, 0x66,
+ 0xbd, 0xc7, 0xe8, 0x25, 0x8a, 0x3a, 0x33, 0x7c, 0x6c, 0x12, 0x7d, 0xff,
+ 0xf6, 0x0f, 0xec, 0xf0, 0x86, 0x79, 0x88, 0x0b, 0x17, 0xf9, 0xce, 0x2e,
+ 0x7d, 0xa0, 0xb1, 0xa3, 0xce, 0xbf, 0x73, 0x3b, 0x7d, 0xd6, 0x28, 0x67,
+ 0xdf, 0xe4, 0x5b, 0xbe, 0xcb, 0x16, 0xe9, 0x62, 0xc6, 0xac, 0x58, 0x4b,
+ 0x14, 0x46, 0x97, 0x82, 0x74, 0x35, 0x4d, 0x39, 0x0e, 0xa6, 0x87, 0x71,
+ 0x11, 0x70, 0x5f, 0xc7, 0x17, 0x70, 0x4b, 0x17, 0x61, 0xab, 0x17, 0x6c,
+ 0x6a, 0xc5, 0xfd, 0x25, 0x83, 0xc3, 0x56, 0x2f, 0xfd, 0xfc, 0x3f, 0xcb,
+ 0x3b, 0x36, 0xeb, 0x16, 0x8f, 0x94, 0x5c, 0x0c, 0x61, 0xc6, 0x34, 0x35,
+ 0xe2, 0xdb, 0xb8, 0x6a, 0xc5, 0xb1, 0x62, 0xc0, 0x93, 0x54, 0x31, 0x9a,
+ 0x64, 0x50, 0x89, 0xee, 0xd2, 0xb1, 0x7f, 0x48, 0xff, 0x3e, 0xe2, 0xc5,
+ 0x39, 0xbf, 0x21, 0x1b, 0xf3, 0xc2, 0x13, 0xd9, 0x62, 0xff, 0xfe, 0x9c,
+ 0xe3, 0x8c, 0x79, 0xe8, 0x66, 0xb7, 0xcf, 0xac, 0x5f, 0xff, 0xfe, 0x91,
+ 0xb8, 0xff, 0x30, 0xd3, 0x37, 0x50, 0xe7, 0xba, 0xdd, 0xf4, 0x6a, 0xc5,
+ 0x7d, 0x30, 0x1e, 0x15, 0x79, 0x6e, 0x96, 0x2d, 0xd2, 0xc0, 0xc9, 0x97,
+ 0xf1, 0x49, 0xca, 0x71, 0x62, 0xff, 0xfa, 0x5c, 0xbd, 0xa9, 0x83, 0xfd,
+ 0xf5, 0x05, 0x8b, 0xff, 0xa5, 0xb5, 0xef, 0xe0, 0xc5, 0xee, 0x2c, 0x5f,
+ 0xb3, 0xfe, 0x73, 0x56, 0x2e, 0xce, 0xcb, 0x17, 0x42, 0x56, 0x2c, 0x6a,
+ 0xc5, 0xee, 0x0c, 0xd5, 0x8a, 0xd9, 0x59, 0x40, 0xd8, 0x72, 0x32, 0x0e,
+ 0x8f, 0x62, 0x21, 0xd1, 0x5f, 0xd3, 0xb8, 0x8b, 0xe2, 0x91, 0x0c, 0x84,
+ 0x2e, 0x18, 0x9d, 0xff, 0x83, 0xcf, 0xb0, 0xfc, 0xfc, 0x75, 0x8b, 0xff,
+ 0xd9, 0xd7, 0x83, 0xf3, 0xfb, 0xf8, 0x37, 0x58, 0xbf, 0xff, 0xfb, 0xdc,
+ 0x7e, 0x72, 0x7d, 0xf7, 0x9d, 0x00, 0xed, 0x08, 0x78, 0xd5, 0x8b, 0xc7,
+ 0xe0, 0x96, 0x2a, 0x51, 0x24, 0xee, 0x97, 0xfe, 0x68, 0x6a, 0x70, 0xb3,
+ 0xaf, 0x2c, 0x56, 0x26, 0xf8, 0x69, 0xff, 0xe1, 0xbd, 0xc2, 0x1b, 0x9f,
+ 0xa5, 0x8b, 0xef, 0x93, 0xca, 0xc5, 0xd0, 0xfa, 0xc5, 0x31, 0xb9, 0x01,
+ 0x0d, 0xd2, 0x75, 0x8b, 0xff, 0xe2, 0x14, 0x21, 0x3e, 0xfe, 0x1c, 0x39,
+ 0x02, 0xc5, 0xfe, 0xc2, 0x21, 0x43, 0x82, 0x58, 0xa9, 0x44, 0x27, 0xd4,
+ 0x6f, 0xff, 0x49, 0x6c, 0xfa, 0xfc, 0xef, 0x38, 0x4b, 0x17, 0xf8, 0xd9,
+ 0xe0, 0xd9, 0x8d, 0x58, 0xbf, 0x9e, 0x7d, 0xc1, 0x71, 0x62, 0xc3, 0x58,
+ 0xa5, 0x8a, 0x72, 0xf8, 0x42, 0x57, 0x9f, 0x69, 0xf9, 0xf5, 0xf1, 0x32,
+ 0xff, 0xe1, 0x43, 0x39, 0xa9, 0x78, 0x37, 0x12, 0x2f, 0xff, 0xf1, 0x67,
+ 0x61, 0xcf, 0xdf, 0xf8, 0x43, 0xd3, 0xf5, 0x05, 0x8a, 0xd2, 0x36, 0x48,
+ 0xcf, 0x88, 0x95, 0x89, 0xd4, 0x3c, 0x6f, 0x35, 0x05, 0x47, 0x64, 0x45,
+ 0xe8, 0xfc, 0x6e, 0xde, 0x32, 0x37, 0x6f, 0xd4, 0x23, 0x44, 0xa8, 0xd4,
+ 0x2f, 0x31, 0xf9, 0xed, 0x0e, 0x38, 0x43, 0xec, 0x71, 0xdb, 0xe4, 0xe2,
+ 0x31, 0xb0, 0xbe, 0xde, 0x34, 0xfe, 0x98, 0xa2, 0x4a, 0xd4, 0x73, 0xa7,
+ 0x3a, 0xfc, 0x70, 0xcd, 0x18, 0x20, 0x21, 0x44, 0x52, 0xa5, 0xb9, 0x39,
+ 0xc3, 0xe9, 0x45, 0xbd, 0x90, 0xc2, 0x51, 0x8e, 0x20, 0x0e, 0x56, 0xb5,
+ 0xff, 0xe8, 0xc3, 0xb4, 0x23, 0x33, 0x5b, 0xb3, 0x6e, 0xa9, 0x23, 0x0b,
+ 0xfb, 0xed, 0xde, 0x7d, 0xbb, 0xc5, 0x8b, 0xf8, 0x78, 0x7d, 0x85, 0xc5,
+ 0x8b, 0xde, 0x68, 0xe5, 0x8b, 0xe6, 0x89, 0xb8, 0xb1, 0x4e, 0x78, 0x7a,
+ 0x20, 0xbf, 0x9b, 0x40, 0x3c, 0x81, 0x62, 0xfa, 0x75, 0x20, 0x58, 0xbf,
+ 0x0e, 0x4f, 0x21, 0xac, 0x5e, 0x97, 0xf2, 0xc5, 0x49, 0xe2, 0xfc, 0xa6,
+ 0x9d, 0x34, 0xa8, 0x9c, 0xfe, 0x43, 0xd8, 0xb8, 0x36, 0x7b, 0xff, 0xcd,
0xf6, 0xcf, 0xb7, 0xdb, 0x3e, 0xcb, 0x17, 0xf9, 0xa1, 0xc7, 0x2c, 0x02,
0xc5, 0xf9, 0xbd, 0xf7, 0x89, 0x62, 0xbe, 0x8a, 0x20, 0x23, 0x91, 0x95,
0xf6, 0x61, 0x3a, 0xc5, 0xff, 0xda, 0xc1, 0xea, 0x7c, 0xfb, 0xb8, 0xd6,
- 0x2f, 0xa7, 0x6c, 0x1a, 0xc5, 0xc1, 0xc4, 0xb1, 0x5f, 0x37, 0xac, 0x47,
+ 0x2f, 0xa7, 0x6c, 0x1a, 0xc5, 0xc1, 0x44, 0xb1, 0x5f, 0x37, 0xac, 0x47,
0x7f, 0xfd, 0xa7, 0x37, 0x3c, 0x2f, 0xb9, 0xf3, 0xec, 0xb1, 0x7e, 0x26,
- 0x04, 0x98, 0xb1, 0x7f, 0x86, 0x2e, 0xf9, 0xfc, 0xe2, 0xc5, 0xfe, 0xcf,
- 0x70, 0xcd, 0xa7, 0x65, 0x8b, 0xfd, 0x99, 0x10, 0x6d, 0xdf, 0x16, 0x2f,
- 0xee, 0x67, 0xf2, 0x1c, 0x58, 0xb6, 0x00, 0xf9, 0x3c, 0x6d, 0x7f, 0xec,
- 0x72, 0xce, 0x7b, 0x99, 0xb2, 0xc5, 0xff, 0x9f, 0xb8, 0x70, 0xb3, 0xdf,
- 0x12, 0xc5, 0xff, 0x3e, 0xbf, 0x98, 0x50, 0xe2, 0xc5, 0x40, 0xfe, 0x37,
- 0x40, 0xbe, 0x6e, 0x98, 0x4b, 0x17, 0xff, 0xfd, 0x87, 0xfb, 0xcf, 0x8b,
- 0x3d, 0xfc, 0x2c, 0x0d, 0x80, 0xb1, 0x7d, 0x9c, 0x33, 0x8b, 0x17, 0xff,
- 0x9a, 0x22, 0x60, 0xf5, 0x2f, 0x06, 0xe2, 0xc5, 0x76, 0x98, 0xc6, 0x88,
- 0xfe, 0x46, 0x4c, 0x82, 0x24, 0xba, 0x3c, 0x22, 0xc5, 0xfe, 0xdf, 0xee,
- 0x79, 0xd1, 0xab, 0x17, 0xe3, 0x73, 0x08, 0xd5, 0x8b, 0x34, 0x0f, 0x7f,
- 0x46, 0xd7, 0x00, 0x28, 0xb1, 0x7f, 0x6c, 0x64, 0x73, 0x10, 0x16, 0x2f,
- 0xee, 0xb9, 0xa6, 0xf7, 0x16, 0x2f, 0xfc, 0xc4, 0x0c, 0xf4, 0x93, 0x81,
- 0x62, 0xa5, 0x13, 0xe7, 0x33, 0x8e, 0x30, 0xb4, 0x60, 0x51, 0x7f, 0xfa,
- 0x63, 0x11, 0xc8, 0x71, 0x9a, 0x5e, 0xe4, 0x11, 0x42, 0x08, 0xe4, 0x1f,
- 0x50, 0x62, 0x80, 0x1b, 0x14, 0x26, 0xf8, 0x4f, 0xe8, 0xf3, 0x84, 0x96,
- 0x1b, 0xe4, 0x71, 0x39, 0x90, 0xbb, 0xa8, 0x3a, 0x32, 0x3d, 0x4a, 0xe5,
- 0x3c, 0x24, 0x5a, 0xb4, 0xa8, 0xe4, 0x72, 0x1e, 0xa4, 0x2e, 0xdf, 0xfd,
- 0x18, 0xd0, 0x8c, 0xcd, 0x6e, 0xcd, 0xba, 0xa2, 0x39, 0x2f, 0xff, 0x46,
- 0x1d, 0xa1, 0x19, 0x9a, 0xdd, 0x9b, 0x75, 0x44, 0xe4, 0x5f, 0xe8, 0xcc,
- 0xd6, 0xec, 0xdb, 0xaa, 0x2c, 0xc2, 0xff, 0xf0, 0xd8, 0xfd, 0x73, 0xb8,
- 0x60, 0x30, 0x6b, 0x17, 0x78, 0x0b, 0x17, 0xec, 0xf9, 0x66, 0x96, 0x2f,
- 0x6d, 0x3a, 0x58, 0xbe, 0xe3, 0x1e, 0x33, 0x11, 0x55, 0xf4, 0xd2, 0x18,
- 0xe1, 0x3d, 0xd1, 0x9c, 0x58, 0xa8, 0x1f, 0x87, 0x6a, 0xb7, 0xd1, 0xac,
- 0x28, 0x14, 0x8d, 0x6b, 0x17, 0xf8, 0x78, 0x79, 0xee, 0x4e, 0xb1, 0x41,
- 0x43, 0xec, 0x8d, 0x67, 0x16, 0xe8, 0xb1, 0x7f, 0x46, 0x91, 0xa6, 0xff,
- 0x9e, 0xd6, 0x2f, 0xa3, 0x40, 0xb7, 0x1d, 0x1b, 0xac, 0x5f, 0xed, 0x4f,
- 0xbe, 0xdd, 0xc1, 0x62, 0xff, 0xff, 0xfa, 0x62, 0xfc, 0xfa, 0x4c, 0x7d,
- 0x45, 0x3f, 0xce, 0x99, 0xfc, 0x1f, 0x4c, 0x58, 0xa0, 0x22, 0xdc, 0x8d,
- 0x6f, 0xfb, 0x38, 0xde, 0x01, 0x85, 0x05, 0x8b, 0x01, 0x62, 0xfe, 0xe6,
- 0xb5, 0x9d, 0xf1, 0x62, 0xe9, 0x82, 0xc5, 0x05, 0x0f, 0x67, 0x04, 0xb4,
- 0x61, 0x7e, 0xe4, 0x80, 0xcd, 0x96, 0x2f, 0x6b, 0x0e, 0xb1, 0x7c, 0xe5,
- 0x9c, 0x58, 0xb6, 0x70, 0xfa, 0x7c, 0x56, 0x10, 0x76, 0xff, 0xff, 0xdf,
- 0x92, 0x17, 0x39, 0x26, 0x79, 0xc8, 0x50, 0xce, 0x79, 0xd6, 0x2e, 0xdb,
- 0x16, 0x2f, 0xc5, 0x9d, 0x30, 0x96, 0x2f, 0xbd, 0xe7, 0xd2, 0xc5, 0xdc,
- 0x02, 0xc5, 0x41, 0x1c, 0xe6, 0xb6, 0x38, 0xc6, 0x8a, 0x3c, 0x47, 0x6f,
- 0x2c, 0x58, 0x22, 0xc5, 0x47, 0x1a, 0x63, 0x04, 0xae, 0xfc, 0x4b, 0x17,
- 0x16, 0xeb, 0x15, 0x03, 0x62, 0xc3, 0x37, 0xb9, 0x3c, 0x58, 0xbf, 0xd1,
- 0x70, 0x36, 0x26, 0xd9, 0x62, 0xe8, 0xee, 0x2c, 0x5c, 0x40, 0x58, 0xbf,
- 0x30, 0x7b, 0x60, 0x6b, 0x15, 0xb1, 0xee, 0xb0, 0xd9, 0x0b, 0xdb, 0xeb,
- 0x17, 0xc6, 0xfd, 0xf8, 0xb1, 0x51, 0xb1, 0xb6, 0x10, 0x95, 0x9d, 0x62,
- 0xff, 0x4f, 0x27, 0xdb, 0x60, 0x6b, 0x16, 0x73, 0x9e, 0x31, 0x08, 0xdd,
- 0xbc, 0x16, 0x2f, 0xde, 0xe1, 0x4c, 0x16, 0x2f, 0x83, 0xf4, 0x9a, 0xb1,
- 0x52, 0x7c, 0xd8, 0x32, 0xe5, 0x17, 0xd8, 0x36, 0x82, 0xc5, 0xf8, 0x19,
- 0xc3, 0x3e, 0xb1, 0x77, 0xb6, 0x58, 0xbb, 0xa4, 0xac, 0x5f, 0xf0, 0xff,
- 0x3c, 0xe6, 0x6a, 0x56, 0x2e, 0xe9, 0x2b, 0x17, 0x74, 0x95, 0x8a, 0x82,
- 0x3a, 0x7b, 0x22, 0x72, 0xa3, 0x8c, 0x90, 0xcf, 0x0e, 0x63, 0x86, 0x6f,
- 0x0e, 0x44, 0xb1, 0x70, 0x19, 0x62, 0xec, 0x25, 0x8b, 0x80, 0x25, 0x8a,
- 0x93, 0x5d, 0xa1, 0x6b, 0xe6, 0x87, 0xf1, 0x62, 0xf7, 0xb2, 0x56, 0x28,
- 0x66, 0xfb, 0xb2, 0x2b, 0xb7, 0x95, 0x8a, 0x1a, 0x26, 0x31, 0x7b, 0x72,
- 0x2b, 0x18, 0xb1, 0x7f, 0xfb, 0x79, 0xe7, 0x30, 0xfd, 0xf8, 0x45, 0xe5,
- 0x8b, 0xde, 0xc3, 0xac, 0x5f, 0xe9, 0x06, 0x14, 0xf7, 0xc5, 0x8b, 0xc0,
- 0xce, 0x2c, 0x5f, 0x61, 0x0a, 0x56, 0x2b, 0xaa, 0x3b, 0xb0, 0x4d, 0xd3,
- 0x78, 0x3b, 0xe3, 0x31, 0x0e, 0xdf, 0x4f, 0xf0, 0x6b, 0x17, 0xde, 0x8e,
- 0x63, 0x56, 0x2c, 0xdb, 0x1e, 0x49, 0x11, 0x5f, 0xb7, 0xfb, 0x38, 0x5d,
- 0x62, 0xfc, 0x2e, 0x4f, 0x25, 0x62, 0xb4, 0x7a, 0xac, 0x5b, 0x7f, 0x10,
- 0x3f, 0x80, 0x65, 0x8b, 0xe2, 0x9e, 0x82, 0x58, 0xa7, 0x3d, 0x16, 0x2d,
- 0xb1, 0xd6, 0x2e, 0x36, 0x39, 0x62, 0xbb, 0x35, 0xce, 0x25, 0x7f, 0x0f,
- 0xac, 0x6e, 0x58, 0x11, 0x62, 0xf6, 0xd1, 0x4a, 0xc5, 0x2c, 0x5f, 0xf1,
- 0x03, 0x3d, 0x24, 0xe0, 0x58, 0xac, 0x3c, 0x36, 0x0c, 0xa9, 0x45, 0xcb,
- 0x1b, 0xc7, 0x31, 0x5e, 0x21, 0x44, 0xb1, 0x68, 0xc0, 0xa3, 0x35, 0x80,
- 0x2a, 0x59, 0x1a, 0x0a, 0x46, 0xb3, 0xb9, 0x87, 0x76, 0xc4, 0x50, 0x84,
- 0x98, 0xe1, 0x37, 0x91, 0x8e, 0x9a, 0xe1, 0xba, 0xb7, 0x64, 0x0e, 0x3b,
- 0x14, 0x24, 0xf4, 0xc8, 0x76, 0xcf, 0xc2, 0x31, 0xa3, 0x15, 0x03, 0x30,
- 0x5c, 0x74, 0xa1, 0xbb, 0xc8, 0xc7, 0xbd, 0x0a, 0x01, 0x3e, 0x74, 0x72,
- 0x8e, 0x4e, 0x32, 0x1b, 0x41, 0x0c, 0x6f, 0xda, 0xdd, 0x9b, 0x75, 0x45,
- 0xba, 0x5c, 0x42, 0x58, 0xb7, 0x16, 0x2b, 0x0f, 0x83, 0x46, 0xe0, 0x17,
- 0xbf, 0xd3, 0xa9, 0x71, 0xe1, 0xd6, 0x2f, 0x7e, 0x74, 0xb1, 0x7e, 0x88,
- 0xbb, 0xcd, 0xd6, 0x2f, 0xfc, 0x21, 0x93, 0x1b, 0x83, 0x68, 0x2c, 0x5a,
- 0x33, 0x64, 0x5c, 0x8c, 0xcb, 0x07, 0x78, 0x57, 0x51, 0x89, 0x96, 0xfe,
- 0x1c, 0xf7, 0xe7, 0x07, 0x30, 0x22, 0xc5, 0xfe, 0x7d, 0x8b, 0x00, 0x2e,
- 0x2c, 0x5f, 0x9f, 0x46, 0x45, 0xc5, 0x8a, 0x88, 0xf7, 0xfe, 0x69, 0x7f,
- 0x13, 0x46, 0x6b, 0x6f, 0xac, 0x5d, 0x9b, 0xac, 0x5a, 0x56, 0x2b, 0x0d,
- 0x48, 0x63, 0x17, 0x9f, 0xb0, 0x2c, 0x5f, 0xbb, 0x87, 0xdc, 0x0b, 0x17,
- 0xff, 0x69, 0xb7, 0x00, 0xb9, 0xe9, 0xec, 0x35, 0x8b, 0x88, 0xd5, 0x8b,
- 0x32, 0xc5, 0xf6, 0xec, 0xdb, 0xaa, 0x29, 0x02, 0xb0, 0xf6, 0xa2, 0x18,
- 0xd0, 0x8d, 0xfe, 0x87, 0x9c, 0x3e, 0x01, 0xd6, 0x2f, 0xe8, 0xfd, 0xff,
- 0x2f, 0xa5, 0x8b, 0xd9, 0x9b, 0xac, 0x5e, 0xc7, 0xfa, 0xc5, 0xff, 0x9a,
- 0x3a, 0x4b, 0x7c, 0xf7, 0xdd, 0x62, 0xff, 0xd9, 0xf7, 0xe9, 0xfc, 0xc2,
- 0xdd, 0x62, 0xfe, 0xcf, 0xe7, 0xdc, 0xd5, 0x8b, 0xf7, 0xa7, 0xa3, 0xf4,
- 0x58, 0xbc, 0xd0, 0x8c, 0x95, 0x4e, 0xe3, 0x2a, 0xc8, 0x51, 0xf6, 0x5e,
- 0xe6, 0xb1, 0x19, 0x7c, 0x74, 0x87, 0x38, 0x83, 0xe4, 0x0e, 0x85, 0xd7,
- 0xb9, 0xf1, 0x2c, 0x5d, 0x26, 0x2c, 0x56, 0x1b, 0x60, 0xc7, 0xaf, 0xe9,
- 0x2e, 0x71, 0xce, 0xb1, 0x58, 0x79, 0xce, 0x43, 0x7f, 0x9c, 0x62, 0xf7,
- 0x0e, 0x4b, 0x17, 0xc1, 0x9e, 0x78, 0xb1, 0x7f, 0xfe, 0x1b, 0xc6, 0x0b,
- 0xdb, 0xff, 0x3d, 0xfc, 0xef, 0x8b, 0x17, 0x98, 0xa0, 0xb1, 0x7f, 0x0b,
- 0x46, 0xfd, 0xa0, 0xb1, 0x68, 0xc9, 0x5e, 0x14, 0xc8, 0x44, 0xee, 0x47,
- 0x12, 0xde, 0x88, 0x4f, 0x2a, 0x57, 0xf1, 0x9b, 0xb1, 0x00, 0x8d, 0x3a,
- 0x12, 0x06, 0xb9, 0x1c, 0x39, 0x7f, 0xf4, 0x63, 0x42, 0x33, 0x35, 0xbb,
- 0x36, 0xea, 0x89, 0x48, 0xad, 0x9b, 0xac, 0xf8, 0x96, 0x4e, 0xbe, 0xd1,
- 0xaf, 0x82, 0x9b, 0xde, 0x52, 0xda, 0x3d, 0x3c, 0x80, 0x12, 0x19, 0x16,
- 0xdd, 0x62, 0xe6, 0xdd, 0x62, 0xd1, 0x8c, 0x6a, 0xfa, 0x09, 0xdf, 0xce,
- 0x59, 0xfc, 0xdd, 0x62, 0xfe, 0x72, 0xf6, 0x38, 0xd6, 0x2e, 0x87, 0x96,
- 0x2f, 0x14, 0x86, 0xb1, 0x74, 0xc6, 0x68, 0xda, 0x90, 0xc5, 0x41, 0x11,
- 0xfe, 0x61, 0xbd, 0xc1, 0x1d, 0x62, 0xd0, 0x58, 0xb8, 0xfe, 0x58, 0xbb,
- 0x8c, 0xb1, 0x7e, 0xcd, 0x79, 0xf1, 0x62, 0xef, 0x62, 0xc5, 0xa3, 0x75,
- 0x8b, 0x46, 0x41, 0x39, 0x3e, 0xe1, 0x78, 0xe4, 0x71, 0x0f, 0x1c, 0x48,
- 0x03, 0x04, 0x2f, 0xd0, 0x9e, 0x38, 0x5e, 0xfe, 0x2f, 0x47, 0x64, 0xe9,
- 0x62, 0xff, 0xf6, 0xa6, 0x11, 0xd9, 0xee, 0x3f, 0xb6, 0x82, 0xc5, 0xfe,
- 0xf7, 0x26, 0x26, 0x6d, 0x2c, 0x54, 0xa2, 0x0d, 0xd3, 0xef, 0xff, 0xb3,
- 0xcf, 0xf1, 0x7d, 0x9f, 0xbe, 0x49, 0xab, 0x17, 0x89, 0xa0, 0xb1, 0x77,
- 0x47, 0x58, 0xbf, 0xe9, 0x7f, 0x7e, 0x7f, 0x27, 0x58, 0xbf, 0x46, 0xc1,
- 0x5d, 0x73, 0x8b, 0x17, 0xff, 0x76, 0x0d, 0x60, 0xe7, 0x4f, 0xd8, 0x16,
- 0x2f, 0xfb, 0x0f, 0xc7, 0x8e, 0xcd, 0x4a, 0xc5, 0x3a, 0x20, 0x82, 0x23,
- 0xdf, 0xf8, 0x5a, 0x86, 0x41, 0xcd, 0x35, 0x96, 0x2f, 0xda, 0xdd, 0x9b,
- 0x75, 0x44, 0xec, 0x5f, 0xfe, 0xda, 0x77, 0xe4, 0xfb, 0x35, 0xa9, 0xdd,
- 0x62, 0xfd, 0x90, 0x29, 0xd9, 0x62, 0xf8, 0x0d, 0x1c, 0x6a, 0xc5, 0xff,
- 0x04, 0x93, 0xcc, 0x60, 0x61, 0x86, 0xb1, 0x58, 0x7d, 0x2c, 0x4f, 0x7e,
- 0x6d, 0x6f, 0xac, 0x58, 0xbf, 0xfb, 0xe2, 0x38, 0xbd, 0x9d, 0x30, 0x47,
- 0x58, 0xbf, 0xcf, 0xce, 0x3f, 0xe7, 0x8b, 0x15, 0xb2, 0x29, 0x06, 0x52,
- 0x74, 0x8b, 0xdf, 0x60, 0xd6, 0x2f, 0xf8, 0x9a, 0x02, 0x01, 0xda, 0x0b,
- 0x16, 0xc1, 0x9e, 0xbf, 0xc7, 0xaf, 0xff, 0xfe, 0xe4, 0x96, 0xf3, 0xd1,
- 0xbe, 0x39, 0x1b, 0xc1, 0xf5, 0xb0, 0x80, 0xb1, 0x7f, 0xc6, 0xbf, 0xb8,
- 0xfb, 0xb6, 0x96, 0x2f, 0x34, 0x23, 0x02, 0xd5, 0x71, 0x4a, 0x61, 0x6b,
- 0xb1, 0x26, 0x20, 0xb9, 0xbe, 0x93, 0x7f, 0x09, 0x16, 0x86, 0x21, 0x42,
- 0x23, 0x84, 0xe6, 0x3a, 0xda, 0x3d, 0x62, 0xff, 0xfe, 0xc2, 0x26, 0xf7,
- 0xf3, 0x8d, 0x9a, 0x01, 0xf1, 0x62, 0xb6, 0x3e, 0xd6, 0x15, 0xbf, 0xff,
- 0x38, 0xc4, 0x79, 0x08, 0xc3, 0x29, 0x2c, 0xdd, 0x62, 0xf3, 0xea, 0x0b,
- 0x17, 0xfa, 0x13, 0xad, 0xa7, 0x5b, 0x2c, 0x5f, 0xfb, 0xe4, 0xd0, 0x10,
- 0x0e, 0xd0, 0x58, 0xa9, 0x3f, 0x5c, 0x36, 0xb8, 0x37, 0x58, 0xbf, 0xcd,
- 0xb3, 0x67, 0xb0, 0xeb, 0x17, 0xf6, 0x81, 0x84, 0xdf, 0x58, 0xbf, 0xff,
- 0x67, 0x70, 0xfc, 0xf1, 0xb5, 0x21, 0x3e, 0xdb, 0xac, 0x5a, 0x32, 0x59,
- 0x22, 0x70, 0x85, 0x98, 0xc8, 0x71, 0x45, 0xc7, 0x34, 0x32, 0x79, 0xc8,
- 0xaf, 0xc6, 0x68, 0xc4, 0x40, 0x56, 0x28, 0x49, 0x06, 0x41, 0x1c, 0x30,
- 0x61, 0x98, 0x42, 0xdb, 0x81, 0x1c, 0xb1, 0x7d, 0x23, 0x92, 0x58, 0xbe,
- 0x7d, 0x4f, 0x45, 0x8b, 0xb3, 0xeb, 0x17, 0xff, 0x47, 0x31, 0x03, 0x3d,
- 0x24, 0xe0, 0x58, 0xb4, 0x64, 0x7a, 0x2f, 0x08, 0x6f, 0x84, 0x31, 0xc4,
- 0x86, 0x0b, 0xdf, 0xfc, 0xc7, 0xfe, 0x6e, 0xdf, 0x93, 0x20, 0xb1, 0x7e,
- 0xf6, 0xb2, 0x43, 0x58, 0xbc, 0xe3, 0x65, 0x8b, 0xff, 0xdf, 0x26, 0x03,
- 0xfa, 0x4f, 0xa7, 0x35, 0x62, 0xff, 0xe2, 0xcf, 0xb6, 0xd9, 0xc2, 0x6e,
- 0xd6, 0x2e, 0x8e, 0x8c, 0x1a, 0x63, 0x2e, 0x8d, 0xf2, 0x96, 0x1c, 0xe2,
- 0x55, 0x4b, 0x3b, 0x7e, 0x11, 0xdf, 0x1e, 0x93, 0x4b, 0xc8, 0xeb, 0xe3,
- 0xa3, 0x72, 0xbf, 0xfb, 0x4d, 0xdc, 0x60, 0xf2, 0x26, 0x6d, 0x96, 0x2f,
- 0xfd, 0x1a, 0xa3, 0x58, 0x53, 0x5a, 0xc0, 0xc9, 0x96, 0x2f, 0xfc, 0xfa,
- 0xfb, 0x73, 0xf2, 0xda, 0x58, 0xbf, 0xe9, 0x2e, 0xc1, 0xce, 0x48, 0x16,
- 0x2f, 0xb5, 0x81, 0xf9, 0x62, 0xbe, 0x89, 0xce, 0x1f, 0x74, 0x3a, 0xbf,
- 0xda, 0xce, 0x10, 0x98, 0xc5, 0x8b, 0xff, 0xff, 0xfe, 0xfb, 0xf9, 0x9b,
- 0xbe, 0x73, 0x92, 0x79, 0xfe, 0x66, 0xd8, 0x59, 0xdf, 0xb9, 0x3d, 0xac,
- 0x5f, 0xe8, 0x37, 0xa2, 0x83, 0xf9, 0x62, 0xff, 0x4c, 0x1f, 0xce, 0x50,
- 0x58, 0xbf, 0xfc, 0x3f, 0xcc, 0x36, 0xc0, 0xfd, 0x3d, 0x86, 0xb1, 0x7f,
- 0xff, 0xed, 0xc5, 0xb6, 0x74, 0x9e, 0xf0, 0x6d, 0x03, 0x0f, 0xcc, 0x61,
- 0xac, 0x5f, 0xef, 0xce, 0x81, 0xbe, 0xf8, 0xb1, 0x77, 0xa3, 0x23, 0x65,
- 0x68, 0xb9, 0x0e, 0xc3, 0x4c, 0xb7, 0x34, 0x8a, 0x12, 0xba, 0x35, 0x63,
- 0x2e, 0x27, 0xf9, 0xca, 0xc3, 0x75, 0xc2, 0xe6, 0x97, 0x1f, 0x7f, 0xee,
- 0xf8, 0xe7, 0xea, 0x66, 0xb3, 0x65, 0x8b, 0xc5, 0x9e, 0x58, 0xa8, 0x8f,
- 0x84, 0x91, 0x6f, 0xec, 0xd3, 0xfb, 0xf2, 0xb1, 0x7d, 0xbb, 0x36, 0xea,
- 0x88, 0xb0, 0xbf, 0x9f, 0x4c, 0x5b, 0xca, 0xc5, 0xf3, 0x91, 0x4a, 0xc5,
- 0x68, 0xff, 0xbe, 0x63, 0xd0, 0xb6, 0xfd, 0x10, 0xb6, 0x09, 0x2b, 0x17,
- 0xd9, 0xe0, 0x3a, 0xc5, 0xff, 0x9a, 0x11, 0x99, 0xad, 0xd9, 0xb7, 0x54,
- 0x4b, 0xa5, 0xfe, 0x61, 0xc9, 0x7e, 0x78, 0xb1, 0x7e, 0x6e, 0x79, 0xfa,
- 0x2c, 0x5e, 0x71, 0x6c, 0xb1, 0x46, 0x9e, 0x46, 0x8a, 0xaf, 0xff, 0xec,
- 0x1f, 0xe4, 0xc8, 0xcf, 0x13, 0x03, 0x9c, 0x90, 0x24, 0x5a, 0x32, 0x55,
- 0x4c, 0x8c, 0x8b, 0x21, 0x56, 0xe6, 0x3a, 0x2d, 0x39, 0x17, 0xd4, 0x3c,
- 0xf5, 0x1c, 0x47, 0x7f, 0xf1, 0xda, 0x11, 0x99, 0xad, 0xd9, 0xb7, 0x54,
- 0x4c, 0x45, 0xfd, 0xf9, 0x2e, 0xe2, 0x65, 0x8b, 0xfe, 0x66, 0x2c, 0xf3,
- 0xf6, 0x1a, 0xc5, 0xfc, 0x7e, 0x71, 0xf0, 0x35, 0x8b, 0xf9, 0xe3, 0x9c,
- 0x18, 0x35, 0x8a, 0x93, 0xdf, 0x62, 0xfb, 0xff, 0xf1, 0x30, 0x0e, 0xfd,
- 0x73, 0xef, 0x30, 0x68, 0x2c, 0x5f, 0x66, 0xf3, 0x19, 0x29, 0x9e, 0x1c,
- 0xbf, 0xf0, 0x98, 0xf1, 0x05, 0x46, 0x27, 0xdd, 0xf8, 0xe4, 0xaf, 0xf7,
- 0xd8, 0xf1, 0x8c, 0x21, 0xac, 0x58, 0x6b, 0x17, 0x9c, 0xb6, 0x58, 0xbf,
- 0x6b, 0x76, 0x6d, 0xd5, 0x15, 0x49, 0x6c, 0x58, 0xad, 0x8f, 0xdc, 0x62,
- 0x58, 0x3a, 0x69, 0xbd, 0xff, 0x6b, 0x4e, 0x45, 0x82, 0xdd, 0x62, 0xff,
- 0xc2, 0x6d, 0x40, 0xb0, 0x36, 0x02, 0xc5, 0xff, 0xcd, 0xcd, 0x38, 0x7e,
- 0xfb, 0xea, 0x0b, 0x17, 0xfd, 0xa6, 0xff, 0x70, 0xcf, 0x46, 0x4a, 0x2f,
- 0x86, 0x73, 0xf3, 0xfa, 0x8c, 0x4d, 0x71, 0xa1, 0xf7, 0x7f, 0xe8, 0xcf,
- 0xc9, 0xf0, 0x72, 0x5e, 0x58, 0xbd, 0xe7, 0xd9, 0x62, 0xff, 0xcd, 0x08,
- 0xcc, 0xd6, 0xec, 0xdb, 0xaa, 0x27, 0x42, 0xf8, 0x5c, 0x70, 0x2c, 0x5e,
- 0x7e, 0xc3, 0x58, 0xa0, 0x1e, 0x17, 0x08, 0xef, 0xdc, 0xcf, 0x96, 0x2c,
- 0x5f, 0x79, 0xe0, 0xeb, 0x14, 0x6a, 0x63, 0x67, 0x1e, 0x04, 0x24, 0xbc,
- 0x44, 0x61, 0x3d, 0xf3, 0xe6, 0xba, 0x2c, 0x5e, 0x2f, 0x71, 0x62, 0xfc,
- 0x5e, 0x21, 0x6c, 0xb1, 0x4c, 0x78, 0xc2, 0x1d, 0xbe, 0xd8, 0xa7, 0x65,
- 0x8b, 0xf6, 0x16, 0xcc, 0x35, 0x8b, 0xe3, 0xc9, 0xb1, 0x91, 0xe8, 0xd7,
- 0x3b, 0x50, 0x88, 0x7a, 0x12, 0x5f, 0xf8, 0x02, 0xe4, 0x60, 0xc3, 0x62,
- 0x82, 0xc5, 0x46, 0x27, 0x94, 0xf1, 0x94, 0x81, 0x76, 0xff, 0xf3, 0xe9,
- 0xbb, 0xfb, 0x3f, 0x7c, 0x93, 0x56, 0x2f, 0xf3, 0xb6, 0xa6, 0x0d, 0xd1,
- 0x62, 0xf9, 0xc8, 0x0e, 0xb1, 0x7e, 0x8a, 0x62, 0x9e, 0x2c, 0x5f, 0xc1,
- 0xe3, 0xf4, 0xc2, 0x58, 0xa7, 0x3d, 0x9e, 0x15, 0x5e, 0x7f, 0xca, 0xc4,
- 0x61, 0xa1, 0xbf, 0xf8, 0x5c, 0xf4, 0xf7, 0x18, 0x28, 0x9c, 0xeb, 0x15,
- 0x04, 0xc5, 0x4f, 0x09, 0xbf, 0x97, 0xdf, 0xed, 0x40, 0xc8, 0x67, 0xd9,
- 0x62, 0x96, 0x29, 0xcf, 0x07, 0x86, 0xb6, 0xd2, 0xc5, 0x7c, 0xd9, 0xb1,
- 0x0d, 0xfb, 0x5b, 0xb3, 0x6e, 0xa8, 0x9d, 0xcb, 0xff, 0xfa, 0x4e, 0x2d,
- 0x45, 0x27, 0xea, 0x7c, 0xf7, 0x1f, 0x8b, 0x17, 0x9a, 0x11, 0x98, 0x89,
- 0x6f, 0x1b, 0xdf, 0x9f, 0xa6, 0xa6, 0x0b, 0x17, 0xef, 0x09, 0x8e, 0xe9,
- 0x17, 0x1e, 0x39, 0x62, 0xfe, 0xc7, 0x1b, 0x31, 0xab, 0x17, 0xfe, 0x29,
- 0xf6, 0x73, 0x33, 0xb8, 0x2c, 0x5f, 0xff, 0x8b, 0x58, 0x1e, 0x47, 0xcf,
- 0xe5, 0xc8, 0x72, 0xb1, 0x50, 0x5c, 0x59, 0x1a, 0x66, 0x46, 0x93, 0xbc,
- 0x2a, 0x8f, 0x0b, 0x6f, 0x9b, 0x31, 0x51, 0x14, 0x70, 0x6f, 0xc5, 0xa6,
- 0x1f, 0x5f, 0xf0, 0xe6, 0x13, 0x18, 0x1f, 0x00, 0xb1, 0x7e, 0xe1, 0x48,
- 0x38, 0xb1, 0x78, 0xb0, 0x6b, 0x17, 0xc2, 0xfb, 0xe9, 0x62, 0xe9, 0x8c,
- 0x93, 0xe7, 0x01, 0x44, 0x70, 0xe5, 0x46, 0x27, 0x1d, 0x90, 0xaa, 0x28,
- 0x52, 0xdf, 0xfe, 0x90, 0x1d, 0xa1, 0x19, 0xc1, 0x96, 0x7d, 0x62, 0xff,
- 0xbd, 0xc7, 0x3b, 0xf8, 0x0c, 0xb1, 0x77, 0xa5, 0x62, 0xee, 0x46, 0x49,
- 0xe8, 0x6e, 0x73, 0x7f, 0xfa, 0x30, 0xed, 0x08, 0xcc, 0xd6, 0xec, 0xdb,
- 0xaa, 0x28, 0x52, 0xe9, 0xd2, 0xc5, 0xe9, 0xcd, 0x2c, 0x5f, 0x81, 0x3b,
- 0x60, 0x6b, 0x17, 0xfe, 0x6f, 0x43, 0x09, 0xc7, 0x19, 0xcd, 0x8f, 0x76,
- 0x21, 0x70, 0x0e, 0x5f, 0x13, 0x6b, 0xa2, 0xc5, 0xcc, 0x1a, 0xc5, 0xb6,
- 0x58, 0xa3, 0x9a, 0xb2, 0x18, 0xbf, 0xf7, 0xdc, 0xed, 0x0c, 0x3b, 0x76,
- 0xb1, 0x68, 0xc9, 0x45, 0x76, 0xc9, 0xfb, 0x90, 0x5d, 0xb3, 0xac, 0x5f,
- 0xfe, 0xf8, 0xbd, 0x25, 0x9b, 0x1a, 0x29, 0x89, 0x62, 0xfe, 0x11, 0xce,
- 0xd0, 0x8c, 0x93, 0xe5, 0xdc, 0x62, 0xff, 0xff, 0xc5, 0x9d, 0x1f, 0xe2,
- 0x8c, 0xdf, 0xef, 0xf2, 0x9c, 0xd6, 0x1d, 0x62, 0xa0, 0x9a, 0xbf, 0xe1,
- 0x3f, 0xc4, 0x8b, 0xf0, 0xbb, 0xf3, 0xee, 0xb1, 0x7c, 0x58, 0x1f, 0xd6,
- 0x2f, 0xe8, 0x36, 0xb6, 0xf8, 0x96, 0x2f, 0xdc, 0x90, 0x19, 0xb2, 0xc5,
- 0xb2, 0x23, 0xdb, 0xe1, 0x85, 0xf6, 0xe4, 0xd0, 0x58, 0xb9, 0xa3, 0x96,
- 0x2f, 0xf0, 0xe4, 0x8b, 0x33, 0x65, 0x8b, 0xe0, 0x63, 0x12, 0xc5, 0xfe,
- 0xf1, 0x48, 0x0e, 0xd0, 0x58, 0xa9, 0x44, 0x36, 0x19, 0x39, 0x0d, 0xfe,
- 0xc2, 0x9c, 0xd4, 0xec, 0xb1, 0x7f, 0xf7, 0x47, 0xf4, 0xfc, 0xb3, 0xda,
- 0x95, 0x8b, 0xf3, 0x68, 0x11, 0xd8, 0xb1, 0x79, 0xc3, 0xf2, 0xc5, 0x62,
- 0x23, 0x9d, 0x17, 0x85, 0x77, 0xfc, 0x78, 0xa0, 0xda, 0xdb, 0xe2, 0x58,
- 0xbd, 0x20, 0x8c, 0xd9, 0x57, 0x64, 0x0a, 0xc6, 0xfc, 0xe5, 0x07, 0x23,
- 0x28, 0x50, 0x70, 0xb7, 0xd0, 0xc0, 0x30, 0xba, 0x9d, 0x5e, 0x01, 0x4b,
- 0x22, 0xbf, 0xff, 0x0b, 0x78, 0xc6, 0xf7, 0xf0, 0xf3, 0xa2, 0x90, 0x2c,
- 0x5f, 0xf1, 0xdb, 0x98, 0x1c, 0x90, 0xd6, 0x2f, 0xfc, 0xd0, 0x8c, 0xcd,
- 0x6e, 0xcd, 0xba, 0xa2, 0x92, 0x2f, 0xef, 0x96, 0x0f, 0xe2, 0x58, 0xbb,
- 0x06, 0xb1, 0x58, 0x78, 0xbf, 0x2e, 0xbd, 0x24, 0x35, 0x8b, 0x46, 0x6c,
- 0x9b, 0x26, 0x2c, 0x9c, 0xe7, 0xd0, 0x95, 0x0c, 0x86, 0xff, 0xff, 0xb0,
- 0x85, 0xc9, 0xc2, 0xf1, 0x31, 0xb9, 0x14, 0x90, 0xd6, 0x2e, 0x39, 0x2c,
- 0x5f, 0xfd, 0x17, 0xd8, 0xfe, 0xfc, 0xf8, 0x47, 0x58, 0xbe, 0xc2, 0x9d,
- 0x96, 0x2b, 0x0f, 0xa7, 0x48, 0xf7, 0xb3, 0x91, 0x84, 0x98, 0x2f, 0x19,
- 0x0c, 0x84, 0x05, 0x4b, 0x78, 0xef, 0xb4, 0xb2, 0xb8, 0x4a, 0x7c, 0xc2,
- 0xdd, 0xe5, 0x05, 0x44, 0x57, 0xa9, 0x64, 0xc7, 0x9e, 0x20, 0xf9, 0xe3,
- 0x42, 0x74, 0x06, 0x25, 0x0b, 0xcf, 0x4f, 0x15, 0x8a, 0x38, 0xe8, 0xe8,
- 0xd7, 0xee, 0x8d, 0xc2, 0xd5, 0x62, 0xfb, 0x76, 0x6d, 0xd5, 0x11, 0x21,
- 0x7f, 0xfe, 0x7d, 0x7d, 0xba, 0xc5, 0xf9, 0xd8, 0x2f, 0xa9, 0x8e, 0x58,
- 0xad, 0x22, 0x4b, 0xe6, 0x37, 0xff, 0xfb, 0xf3, 0xb0, 0x5f, 0x53, 0x1d,
- 0x19, 0xa7, 0x93, 0xed, 0x81, 0xac, 0x5f, 0x9f, 0xdf, 0xc3, 0xac, 0x5a,
- 0x32, 0x37, 0x4d, 0xbf, 0x21, 0x6d, 0x11, 0x18, 0x5d, 0xba, 0xf6, 0x9b,
- 0x4b, 0x17, 0xfe, 0x68, 0x46, 0x66, 0xb7, 0x66, 0xdd, 0x51, 0x2f, 0x17,
- 0x74, 0xfa, 0xc5, 0xf3, 0x79, 0xb6, 0x58, 0xb4, 0x63, 0xa2, 0xa8, 0xe3,
- 0xa4, 0xa1, 0x1c, 0x35, 0x7f, 0xf4, 0xf4, 0x68, 0x9f, 0x5d, 0xc2, 0x62,
- 0x58, 0xbc, 0x14, 0x38, 0x16, 0x2f, 0xe1, 0xff, 0x1c, 0x8d, 0x58, 0xbc,
- 0x72, 0x95, 0x8a, 0xe1, 0xe5, 0x18, 0x5d, 0x7b, 0xcc, 0x6a, 0xc5, 0x05,
- 0x4f, 0x05, 0x88, 0xee, 0x88, 0x96, 0x2f, 0xfc, 0x16, 0x33, 0x8c, 0x52,
- 0x53, 0x05, 0x8b, 0xfe, 0xeb, 0x3e, 0x7d, 0x4f, 0x48, 0x96, 0x2f, 0xff,
- 0x7e, 0x78, 0x60, 0xe7, 0x51, 0x61, 0x01, 0x62, 0xfb, 0x42, 0xf7, 0x16,
- 0x2f, 0xe1, 0xb9, 0xac, 0x40, 0x58, 0xbc, 0x66, 0xc1, 0x16, 0x2f, 0xd2,
- 0x40, 0x19, 0xd6, 0x2f, 0xda, 0x01, 0xdf, 0x8b, 0x17, 0x00, 0xeb, 0x17,
- 0xa4, 0xbb, 0x58, 0xbf, 0x78, 0xc3, 0x94, 0xac, 0x59, 0xf4, 0x7b, 0xdf,
- 0x18, 0x21, 0xdb, 0xff, 0xdf, 0xe9, 0x24, 0x08, 0xfc, 0x1e, 0x6b, 0xb5,
- 0x8b, 0xfc, 0xfa, 0x61, 0xb9, 0x1a, 0xb1, 0x74, 0xf9, 0x62, 0xff, 0x9b,
- 0x6d, 0x4f, 0x70, 0x73, 0xac, 0x5f, 0xfe, 0x10, 0xdf, 0x46, 0x44, 0x10,
- 0x4c, 0x51, 0x2c, 0x5e, 0x11, 0x44, 0xb1, 0x50, 0x4d, 0xd9, 0xcc, 0xfe,
- 0xa0, 0x03, 0x32, 0x17, 0xe1, 0xdf, 0x94, 0x2f, 0xe0, 0x7e, 0x74, 0xe7,
- 0x58, 0xbf, 0x38, 0x40, 0x8c, 0x75, 0x8b, 0x69, 0x62, 0xff, 0xb9, 0x3d,
- 0x1b, 0xf3, 0xdc, 0x4b, 0x15, 0x87, 0x9f, 0x10, 0x95, 0x4a, 0x32, 0xf4,
- 0x5c, 0xcf, 0x77, 0xd9, 0xe3, 0x36, 0x58, 0xbf, 0xf3, 0x70, 0xce, 0x85,
- 0x3e, 0x6f, 0xac, 0x5f, 0xf1, 0x4c, 0x5a, 0x68, 0x9b, 0x8b, 0x17, 0x18,
- 0x75, 0x8a, 0x82, 0x25, 0x3a, 0x20, 0x84, 0x3a, 0xbb, 0xe0, 0x58, 0xa7,
- 0x3c, 0xc6, 0x34, 0xbf, 0x66, 0xd9, 0xc3, 0xac, 0x5f, 0xb5, 0x3e, 0x7e,
- 0x8b, 0x17, 0xed, 0x9b, 0x8c, 0x05, 0x8a, 0x73, 0xd3, 0x62, 0xab, 0xff,
- 0xa2, 0xea, 0x61, 0x4f, 0x46, 0xe9, 0x31, 0x2c, 0x52, 0xc5, 0xff, 0xbd,
- 0xcc, 0xe4, 0x97, 0xb0, 0x0b, 0x17, 0xde, 0xcd, 0x44, 0xb1, 0x7b, 0xcd,
- 0xd1, 0x62, 0xb0, 0xf0, 0xd8, 0x92, 0xa5, 0x14, 0x30, 0x84, 0x0d, 0xe3,
- 0xe0, 0x45, 0x8b, 0xf3, 0x72, 0x7a, 0x62, 0xc5, 0x44, 0x7d, 0xfa, 0x27,
- 0xe8, 0x3f, 0x52, 0x9c, 0xde, 0x26, 0xb4, 0x63, 0x97, 0x6a, 0x56, 0x28,
- 0x28, 0xc8, 0x26, 0x81, 0xf0, 0xd3, 0x30, 0x93, 0x72, 0xee, 0xc8, 0x9c,
- 0xa2, 0x28, 0xff, 0x75, 0x19, 0x71, 0xcb, 0xbf, 0x18, 0x29, 0x10, 0x79,
- 0xf3, 0xa4, 0x77, 0x61, 0x0d, 0x2e, 0xc2, 0x58, 0xbf, 0x07, 0x31, 0xf2,
- 0x75, 0x8b, 0xfb, 0xaf, 0x3f, 0x8f, 0xe5, 0x8a, 0x19, 0xf9, 0x60, 0xb3,
- 0x96, 0x5b, 0xb5, 0x8b, 0xfc, 0xde, 0xd8, 0x51, 0x4c, 0x7a, 0xc5, 0xff,
- 0xd8, 0x73, 0x3a, 0x37, 0xb0, 0xf3, 0xc5, 0x8a, 0x02, 0x20, 0x38, 0x73,
- 0x43, 0x45, 0xb3, 0xc2, 0x4e, 0xfe, 0x21, 0x7a, 0x29, 0x35, 0x62, 0xf0,
- 0x5d, 0xf4, 0xb1, 0x4c, 0x7a, 0x22, 0x30, 0xbf, 0xfb, 0x1f, 0xbe, 0x7a,
- 0x76, 0x3b, 0x41, 0x62, 0x9c, 0xf9, 0xf4, 0x43, 0x7f, 0x85, 0xef, 0x94,
- 0xe6, 0x96, 0x2f, 0xc5, 0x9b, 0x19, 0xd1, 0x62, 0xfb, 0x36, 0x33, 0xa2,
- 0xc5, 0xf4, 0xf6, 0x36, 0xea, 0x7a, 0x64, 0x59, 0x7f, 0xff, 0x43, 0xe6,
- 0x77, 0xef, 0xbb, 0x02, 0x3a, 0x75, 0x84, 0xb1, 0x43, 0x44, 0xd3, 0x9d,
- 0x5c, 0x15, 0x8f, 0x58, 0xbf, 0xfe, 0x7d, 0x75, 0xfc, 0xbf, 0xb8, 0x2d,
- 0xc5, 0x2b, 0x17, 0xcf, 0xb0, 0x23, 0xd6, 0x2d, 0xda, 0xc5, 0xe6, 0x6d,
- 0xd5, 0x14, 0xb9, 0x4b, 0x17, 0xfc, 0xfd, 0x3f, 0xbb, 0xf3, 0x06, 0xb1,
- 0x58, 0x88, 0x5d, 0xc4, 0xe2, 0x2a, 0xd0, 0x65, 0xfb, 0xc6, 0xc9, 0x41,
- 0x62, 0xf7, 0xa7, 0x4b, 0x14, 0x73, 0xc6, 0x22, 0x9b, 0xfe, 0xcd, 0x47,
- 0xe0, 0xf3, 0x5d, 0xac, 0x53, 0x9e, 0xf7, 0x42, 0x1b, 0xff, 0x4c, 0x3e,
- 0xcf, 0xdf, 0x24, 0xd5, 0x8a, 0xd9, 0x5d, 0x2c, 0x23, 0x20, 0xc2, 0x23,
- 0x47, 0xe2, 0x53, 0xd4, 0x2b, 0x3f, 0x0e, 0x22, 0x23, 0xbf, 0xf8, 0x5c,
- 0xfb, 0x43, 0xaf, 0x07, 0xe7, 0x58, 0xbf, 0x37, 0x7a, 0xe7, 0x16, 0x2e,
- 0x7f, 0x68, 0xfc, 0xb8, 0x91, 0x7f, 0xfb, 0x5b, 0x75, 0xe8, 0x2f, 0xcb,
- 0x9e, 0x46, 0xb1, 0x5f, 0x3f, 0xd6, 0x2d, 0xbd, 0x3a, 0xf2, 0xc5, 0xfc,
- 0x3e, 0xe7, 0x4f, 0xda, 0xc5, 0xf7, 0xb6, 0xc0, 0xd6, 0x2a, 0x07, 0xe4,
- 0xe3, 0xa4, 0x61, 0x7f, 0xfe, 0x89, 0xb5, 0xb7, 0x9e, 0x3f, 0x36, 0x68,
- 0xa6, 0x3d, 0x62, 0xf8, 0xdd, 0x67, 0x16, 0x2a, 0x51, 0x06, 0xeb, 0xf7,
- 0xfe, 0x92, 0x9f, 0xf5, 0x11, 0x0b, 0x75, 0x8b, 0xd1, 0x1f, 0x16, 0x2e,
- 0x10, 0x6b, 0x17, 0x84, 0xdc, 0x58, 0xbc, 0x72, 0x89, 0x62, 0xf0, 0x9a,
- 0x25, 0x8a, 0xc3, 0x79, 0x10, 0xf5, 0xfa, 0x40, 0xdd, 0xf1, 0x62, 0xf1,
- 0x38, 0x16, 0x2f, 0xf8, 0x6c, 0x40, 0x61, 0x8a, 0x3d, 0x62, 0xf6, 0x7b,
- 0x8b, 0x15, 0x27, 0xeb, 0x83, 0x9c, 0x3c, 0xbf, 0xf8, 0x86, 0x12, 0x2c,
- 0x83, 0xea, 0x76, 0x58, 0xbf, 0xfe, 0xf7, 0xe4, 0x8d, 0xeb, 0x3b, 0x7a,
- 0x7a, 0x71, 0x62, 0xa5, 0x13, 0xcc, 0x91, 0x50, 0x55, 0x3a, 0x32, 0x1c,
- 0x41, 0x8f, 0x1e, 0x88, 0x67, 0xeb, 0x20, 0x21, 0xf4, 0x27, 0xba, 0x43,
- 0x2e, 0xfb, 0x61, 0x0d, 0xd6, 0x2f, 0xf8, 0x6c, 0x40, 0x30, 0xe5, 0x2b,
- 0x15, 0x27, 0xbb, 0x84, 0x97, 0xcc, 0x43, 0x08, 0xb1, 0x7f, 0x8b, 0x21,
- 0xd7, 0xf3, 0x1e, 0xb1, 0x51, 0xe7, 0xb8, 0x72, 0x4a, 0x58, 0xbf, 0x73,
- 0xda, 0x9e, 0x2c, 0x5a, 0x7b, 0x36, 0xbe, 0x0c, 0xbf, 0xe0, 0x73, 0x53,
- 0xdc, 0x1c, 0xeb, 0x17, 0xbc, 0xdd, 0x16, 0x2f, 0xdb, 0x0a, 0x29, 0x8f,
- 0x58, 0xbe, 0x14, 0x53, 0x1e, 0xb1, 0x73, 0x6d, 0xd4, 0xf5, 0x76, 0x2e,
- 0xa9, 0x47, 0x03, 0x1d, 0x89, 0xd2, 0xff, 0xa5, 0xc1, 0xc9, 0x3b, 0x79,
- 0x62, 0xff, 0x9f, 0x91, 0x39, 0x7a, 0x40, 0xb1, 0x7e, 0x07, 0x18, 0x80,
- 0xb1, 0x7f, 0xf0, 0xdb, 0xb3, 0x88, 0xbd, 0xfc, 0x82, 0xc5, 0x49, 0xf7,
- 0x39, 0x45, 0xff, 0xc5, 0xee, 0x93, 0xae, 0x31, 0x4c, 0x7a, 0xc5, 0xfc,
- 0xcf, 0xb7, 0x53, 0xe2, 0xc5, 0x41, 0x3a, 0x5d, 0x17, 0x1c, 0xe3, 0xf0,
- 0xa7, 0xe1, 0x07, 0x92, 0x2f, 0xf4, 0xc7, 0xf2, 0x4e, 0xde, 0x58, 0xb9,
- 0x89, 0x62, 0xff, 0xa4, 0x1d, 0x7f, 0x27, 0x62, 0x58, 0xae, 0xcf, 0x43,
- 0xa0, 0xb5, 0xff, 0xf6, 0x0c, 0xc8, 0xb9, 0xef, 0xe0, 0xc5, 0xee, 0x2c,
- 0x5f, 0xd1, 0x64, 0x7b, 0x10, 0x16, 0x2a, 0x09, 0x98, 0x6a, 0x10, 0xdf,
- 0x25, 0xf2, 0xa5, 0xfd, 0x21, 0xbf, 0xc5, 0x1e, 0xb1, 0x7f, 0x77, 0x0e,
- 0x31, 0x76, 0xb1, 0x52, 0xba, 0x71, 0x05, 0xac, 0x95, 0x58, 0xf1, 0xc6,
- 0xe9, 0x0c, 0xc3, 0x2b, 0x85, 0x12, 0xc5, 0xff, 0x45, 0xd7, 0x53, 0xdc,
- 0x1c, 0xeb, 0x15, 0x11, 0xeb, 0x90, 0xcd, 0xff, 0xee, 0x92, 0x5e, 0xf7,
- 0xf0, 0x62, 0xf7, 0x16, 0x2f, 0x63, 0x9d, 0x62, 0xff, 0xff, 0xde, 0x8e,
- 0xcf, 0x19, 0xd1, 0xbc, 0x66, 0xcf, 0xf2, 0xc1, 0xb1, 0xd6, 0x2e, 0x93,
- 0xac, 0x54, 0xa6, 0x2d, 0x84, 0x5b, 0xa6, 0xb8, 0xe6, 0x9d, 0x2f, 0xc5,
- 0x17, 0x9c, 0xd5, 0x8b, 0xa6, 0x0b, 0x17, 0xc5, 0x13, 0x9d, 0x62, 0xfc,
- 0xe3, 0x11, 0x62, 0xc5, 0xfa, 0x47, 0xf6, 0xed, 0x62, 0xff, 0xbf, 0x0c,
- 0xf3, 0x00, 0xce, 0xd6, 0x2f, 0xbd, 0xfc, 0x87, 0x53, 0xe5, 0x72, 0x9a,
- 0x89, 0x18, 0xc5, 0x08, 0xca, 0x94, 0xd4, 0x9c, 0xa9, 0x85, 0xc5, 0x0e,
- 0x9b, 0xfb, 0x51, 0x61, 0x49, 0xd6, 0x2d, 0xd1, 0x62, 0xb0, 0xf0, 0x9c,
- 0xba, 0xe9, 0x89, 0x62, 0xff, 0xf0, 0xb6, 0xd3, 0x9d, 0xfd, 0xc9, 0xd7,
- 0x45, 0x8a, 0x82, 0x21, 0xb4, 0x40, 0x43, 0x17, 0xe0, 0x4e, 0xf8, 0x75,
- 0x8b, 0xfd, 0x9b, 0x72, 0x62, 0x16, 0x96, 0x2f, 0xb1, 0x9f, 0x65, 0x8b,
- 0xa7, 0xcb, 0x14, 0x73, 0x72, 0x44, 0x54, 0xe8, 0xe7, 0xd1, 0x79, 0x14,
- 0xf1, 0xbe, 0xe8, 0x62, 0xc5, 0xfb, 0x86, 0xe9, 0x83, 0x58, 0xbb, 0x3b,
- 0x58, 0xbc, 0x52, 0x75, 0x8a, 0x19, 0xef, 0xee, 0x57, 0xa1, 0x8b, 0xd1,
- 0xf9, 0x05, 0x8b, 0xfe, 0xe3, 0xf4, 0xeb, 0x11, 0x48, 0xd6, 0x2b, 0xb3,
- 0xde, 0x72, 0x0b, 0xfc, 0xda, 0x8b, 0x3c, 0x13, 0xa2, 0xc5, 0xc0, 0xe2,
- 0xc5, 0xe1, 0xf1, 0xd6, 0x2a, 0x4d, 0xab, 0x0c, 0x54, 0xa7, 0xdc, 0x33,
- 0xbc, 0x76, 0x68, 0x47, 0x08, 0x88, 0x36, 0xeb, 0xe6, 0xfb, 0x6c, 0xb1,
- 0x7e, 0xf8, 0x8d, 0xc2, 0x58, 0xbc, 0x1b, 0x41, 0x62, 0xfd, 0x13, 0x01,
- 0xb7, 0x58, 0xbe, 0xd7, 0x8a, 0x56, 0x2b, 0x0f, 0x31, 0x8a, 0xaf, 0xf0,
- 0x64, 0xde, 0x83, 0x0d, 0x62, 0xe8, 0xe7, 0x58, 0xb8, 0xcd, 0x96, 0x2f,
- 0x8c, 0xda, 0x7e, 0xb1, 0x44, 0x6f, 0xfc, 0x35, 0x7e, 0xcf, 0x79, 0xcd,
- 0x58, 0xbf, 0xe9, 0xff, 0x1b, 0xd3, 0xa0, 0x8b, 0x17, 0xfe, 0x3b, 0x0c,
- 0xc8, 0xa1, 0x25, 0xda, 0xc5, 0x0c, 0xff, 0x5c, 0xee, 0xfe, 0x17, 0xe7,
- 0x58, 0x05, 0x8b, 0xdd, 0x27, 0x4b, 0x17, 0xda, 0x01, 0x9d, 0x16, 0x2f,
- 0x38, 0x7e, 0x58, 0xa8, 0x22, 0x49, 0xcb, 0xbe, 0x3f, 0xc2, 0x7a, 0xd9,
- 0x58, 0xc0, 0xc8, 0xf0, 0xa7, 0x76, 0xae, 0xc8, 0x1c, 0xd2, 0x25, 0x9d,
- 0x10, 0x7e, 0x14, 0xde, 0x85, 0x9d, 0xfe, 0x2f, 0x67, 0x1d, 0xbe, 0xb1,
- 0x7d, 0xc8, 0x71, 0x96, 0x2f, 0xf8, 0x0f, 0xfc, 0xd3, 0x45, 0xc5, 0x8b,
- 0xff, 0xe8, 0x14, 0xec, 0x64, 0x5c, 0xfe, 0x04, 0xd0, 0x16, 0x2f, 0x40,
- 0x7d, 0x16, 0x2a, 0x4f, 0xd9, 0x95, 0xaf, 0xee, 0xa7, 0xcf, 0x37, 0x96,
- 0x2f, 0xef, 0xb8, 0xdf, 0x5b, 0xac, 0x52, 0xc5, 0xf3, 0x17, 0x70, 0x58,
- 0xad, 0xcd, 0x7f, 0xc3, 0x2d, 0xcc, 0x45, 0x86, 0xe6, 0x0c, 0xbd, 0x7b,
- 0xb8, 0xb8, 0xb1, 0x5d, 0x9e, 0xab, 0x1a, 0xde, 0x97, 0x1a, 0xc5, 0xfd,
- 0xf7, 0xf1, 0x49, 0xd6, 0x2f, 0xf8, 0xb7, 0x6f, 0xf7, 0x0c, 0xf2, 0xc5,
- 0x44, 0x7d, 0x0c, 0x5b, 0x52, 0xab, 0xc8, 0x66, 0x5d, 0x91, 0x9e, 0x16,
- 0x0d, 0x19, 0x2f, 0x08, 0x85, 0x08, 0x4b, 0xfd, 0x81, 0xc1, 0xf8, 0x23,
- 0xac, 0x5d, 0xd3, 0x8b, 0x17, 0xf0, 0xb9, 0x31, 0x0b, 0x4b, 0x17, 0xec,
- 0xdb, 0x3f, 0xc5, 0x8a, 0x93, 0xf3, 0xf8, 0xd1, 0x18, 0x5f, 0xfe, 0x80,
- 0x9b, 0xa3, 0xff, 0x82, 0x8e, 0x16, 0x96, 0x2f, 0x87, 0xf9, 0x35, 0x62,
- 0xf8, 0xe2, 0x8b, 0x4b, 0x17, 0x6b, 0x8b, 0x17, 0xfe, 0xce, 0x75, 0xfc,
- 0xb9, 0x0b, 0x65, 0x8a, 0xc3, 0xd9, 0x21, 0x8a, 0xdd, 0x34, 0x0e, 0xcb,
- 0x74, 0xa2, 0x72, 0x4e, 0x8f, 0xd7, 0xfc, 0x09, 0x01, 0x9d, 0x24, 0x82,
- 0x2c, 0x5f, 0xff, 0xb6, 0x9f, 0x4f, 0xdf, 0xd0, 0x7d, 0x6f, 0xf9, 0x58,
- 0xba, 0x4e, 0xb1, 0x52, 0xab, 0x8f, 0x23, 0xe8, 0x74, 0xf6, 0x3e, 0x12,
- 0xbd, 0xff, 0x4c, 0x5e, 0x71, 0xe1, 0x44, 0xb1, 0x7f, 0xff, 0xda, 0xef,
- 0x77, 0xef, 0xa9, 0xad, 0xd7, 0x9f, 0x6d, 0xe4, 0x86, 0xb1, 0x7f, 0xcd,
- 0xc3, 0x3d, 0xde, 0xee, 0x75, 0x8b, 0x7e, 0x51, 0x5a, 0x27, 0x0b, 0xe7,
- 0x36, 0x3b, 0x16, 0x2f, 0xe3, 0x3d, 0x3b, 0x17, 0x6b, 0x17, 0xff, 0xdb,
- 0xfd, 0xa2, 0x32, 0x28, 0x39, 0x61, 0xe5, 0x62, 0xf1, 0x39, 0xd6, 0x2b,
- 0x48, 0xc6, 0x01, 0x31, 0x18, 0xf9, 0x4e, 0xff, 0x3f, 0x8b, 0x0d, 0xcf,
- 0xac, 0x5e, 0x8f, 0x63, 0xac, 0x57, 0x8f, 0x4c, 0x21, 0x9d, 0xff, 0xde,
- 0xe1, 0x9c, 0xc2, 0x17, 0xa7, 0xeb, 0x17, 0xf4, 0xb1, 0x7b, 0x09, 0x62,
- 0xb0, 0xfc, 0x49, 0x1a, 0xfe, 0xeb, 0xe9, 0xda, 0x62, 0x58, 0xbf, 0x72,
- 0x3e, 0x74, 0x6a, 0xc5, 0xa4, 0xd3, 0xdf, 0xec, 0xca, 0xfe, 0x68, 0x9f,
- 0x53, 0xb2, 0xc5, 0xd3, 0xb2, 0xc5, 0x7c, 0xf1, 0xc2, 0x17, 0xdf, 0x82,
- 0x1e, 0x73, 0xcb, 0x17, 0xff, 0x19, 0xe8, 0x48, 0xd8, 0xb3, 0xc0, 0x58,
- 0xbf, 0xcf, 0xd3, 0xb8, 0x60, 0x48, 0x2c, 0x56, 0x22, 0xa3, 0x45, 0x44,
- 0x8b, 0x76, 0x1d, 0x62, 0xa0, 0xb9, 0xf2, 0x38, 0x73, 0xe4, 0x3b, 0x9e,
- 0x11, 0xe7, 0x84, 0xaf, 0xdf, 0xd9, 0xc0, 0x50, 0xcc, 0xe8, 0x5d, 0x7e,
- 0x08, 0xe7, 0x9e, 0x2c, 0x5f, 0x9b, 0xa6, 0x6b, 0x8b, 0x17, 0xed, 0x8c,
- 0xe8, 0xd0, 0x58, 0xa1, 0xa2, 0x04, 0xe5, 0x44, 0x55, 0x7b, 0xa6, 0x0d,
- 0x62, 0xc1, 0xac, 0x5e, 0x27, 0x3a, 0xc5, 0xb6, 0x58, 0xb7, 0xd8, 0xd7,
- 0x98, 0x39, 0x7a, 0x2e, 0x4a, 0xc5, 0xf6, 0x81, 0x1d, 0x8b, 0x14, 0x69,
- 0xe2, 0x30, 0xf5, 0xd1, 0x62, 0xc5, 0x2c, 0x5f, 0xa7, 0xdf, 0x68, 0x98,
- 0xd2, 0x70, 0x62, 0xfe, 0x07, 0x60, 0xcd, 0x62, 0xc5, 0xfa, 0x5f, 0xcf,
- 0x05, 0x8b, 0xf6, 0x1a, 0x6b, 0x8d, 0x62, 0xb7, 0x3d, 0x12, 0x27, 0xbd,
- 0x39, 0xe5, 0x8b, 0xee, 0x4e, 0xa0, 0xb1, 0x7e, 0xcd, 0x68, 0x5b, 0x2c,
- 0x5c, 0xc0, 0x39, 0xf4, 0xf0, 0x73, 0xc4, 0x75, 0x29, 0xa2, 0xe4, 0x20,
- 0x1e, 0x11, 0x77, 0xc3, 0xfb, 0x76, 0xb1, 0x7e, 0xfb, 0xeb, 0xee, 0xb1,
- 0x73, 0x92, 0xc5, 0x61, 0xbe, 0x01, 0x45, 0xef, 0xcf, 0x16, 0x2e, 0x07,
- 0x3a, 0x9b, 0xd9, 0x20, 0xa9, 0x46, 0x6b, 0x42, 0x7e, 0xfb, 0xdc, 0xcd,
- 0x96, 0x2f, 0xff, 0xf7, 0xdf, 0xa3, 0x01, 0xe1, 0x3d, 0x18, 0xf3, 0xf0,
- 0x8c, 0xb1, 0x5d, 0xa2, 0x27, 0xe4, 0x97, 0x66, 0xcb, 0x14, 0xc6, 0xf0,
- 0x89, 0x2a, 0x57, 0x34, 0xa0, 0x5e, 0x31, 0xfc, 0x42, 0x76, 0xb8, 0x91,
- 0xbf, 0x1c, 0x11, 0x46, 0x0b, 0xc8, 0x75, 0xdf, 0xff, 0xb4, 0xc3, 0xeb,
- 0x3f, 0xeb, 0xf7, 0xd6, 0x43, 0xa2, 0xc5, 0xcc, 0x35, 0x8a, 0x73, 0xf3,
- 0x65, 0xcb, 0xff, 0xfb, 0x77, 0xe6, 0x0f, 0x7f, 0xbf, 0xb2, 0x22, 0x93,
- 0xac, 0x54, 0x47, 0xfb, 0xf2, 0x0b, 0x81, 0xba, 0xc5, 0x9d, 0x62, 0xdc,
- 0x58, 0xb1, 0xbc, 0x37, 0x9e, 0x19, 0x10, 0x8d, 0xfd, 0xb3, 0x67, 0xb0,
- 0xeb, 0x14, 0xe7, 0xc6, 0xc6, 0xb7, 0x80, 0xdb, 0xac, 0x5f, 0xfb, 0xcc,
- 0x0e, 0xbe, 0x26, 0x07, 0x16, 0x2f, 0x78, 0xa5, 0x62, 0x88, 0xf7, 0x43,
- 0x41, 0xbf, 0xc5, 0x8f, 0xac, 0xf4, 0xac, 0x5f, 0xd8, 0xfa, 0xcf, 0x4a,
- 0xc5, 0xe2, 0x9f, 0xf5, 0x3d, 0xd2, 0x31, 0xbf, 0xd3, 0xee, 0x75, 0x1b,
- 0x06, 0xb1, 0x58, 0x8e, 0x91, 0x3f, 0xf4, 0x33, 0xbf, 0xff, 0x9b, 0x4d,
- 0xdc, 0x0c, 0xe0, 0x30, 0x5b, 0xc9, 0x01, 0x62, 0xf8, 0x38, 0xb9, 0x2b,
- 0x17, 0xff, 0xdf, 0x3b, 0x02, 0x7e, 0x67, 0x1c, 0x13, 0xf5, 0x8b, 0xff,
- 0xda, 0x03, 0x0f, 0xae, 0x7e, 0x4b, 0x60, 0x8b, 0x17, 0xe2, 0x6d, 0xa7,
- 0xcb, 0x14, 0xe8, 0xc8, 0xfa, 0x8f, 0x13, 0xef, 0xdb, 0x37, 0x32, 0x0b,
- 0x17, 0xff, 0xc3, 0xce, 0x8d, 0xa8, 0x8c, 0x83, 0x79, 0x8e, 0xb1, 0x76,
- 0x47, 0xac, 0x54, 0xa2, 0x5d, 0xca, 0x74, 0xa9, 0x7f, 0x37, 0x60, 0x3b,
- 0xf1, 0x62, 0xc6, 0xac, 0x5f, 0xb5, 0x9d, 0x07, 0x2b, 0x15, 0x2b, 0x88,
- 0x1b, 0x46, 0xc9, 0xb9, 0x8f, 0x6b, 0xd1, 0x43, 0xb7, 0x50, 0xc6, 0xf9,
- 0x70, 0x0b, 0xfc, 0x27, 0x7f, 0xfa, 0x75, 0xbb, 0x87, 0xa9, 0xee, 0x0e,
- 0x75, 0x8b, 0xf9, 0xc3, 0x68, 0xa4, 0xeb, 0x17, 0x82, 0x4f, 0x16, 0x2b,
- 0x88, 0x9b, 0xf2, 0x68, 0x8b, 0xed, 0x18, 0x15, 0x7c, 0x14, 0xb8, 0xd1,
- 0x26, 0x36, 0x85, 0x68, 0x58, 0x4b, 0x1a, 0xc6, 0x26, 0x90, 0xd1, 0xb4,
- 0x6c, 0x50, 0x87, 0x18, 0xe1, 0xbf, 0x92, 0xf1, 0xb7, 0x8d, 0xcf, 0xb8,
- 0x49, 0xbc, 0xb4, 0xd8, 0xf8, 0x76, 0x45, 0x3b, 0x69, 0xa8, 0xf4, 0x8f,
- 0x1c, 0xdf, 0xe5, 0xee, 0xb4, 0xb7, 0x30, 0x4b, 0x8b, 0x29, 0x6b, 0x1c,
- 0x9d, 0x47, 0xf4, 0xef, 0x60, 0xa3, 0x7f, 0x8e, 0x86, 0x11, 0x93, 0x8c,
- 0x01, 0x23, 0x2f, 0xbf, 0x6b, 0x76, 0x6d, 0xd5, 0x14, 0xe1, 0x7f, 0x7d,
- 0xce, 0x4c, 0x6a, 0xc5, 0xa3, 0x30, 0xf9, 0x5c, 0xde, 0xf4, 0x6a, 0xf4,
- 0x6a, 0x58, 0xbf, 0xa4, 0xf8, 0x12, 0x7c, 0xb1, 0x7d, 0xf9, 0x23, 0x56,
- 0x2f, 0xa7, 0x79, 0xfa, 0xc5, 0x1c, 0xfd, 0x7c, 0x5e, 0x61, 0x1d, 0xee,
- 0x19, 0x05, 0x8b, 0xfe, 0xfb, 0x17, 0x9a, 0x0e, 0x05, 0x8a, 0xc3, 0xd7,
- 0x71, 0xfb, 0xfe, 0xd3, 0x73, 0xf9, 0x85, 0xba, 0xc5, 0xfc, 0x2e, 0x67,
- 0x8c, 0xd9, 0x62, 0x9c, 0xfa, 0xbe, 0x73, 0x7e, 0x3e, 0xb5, 0x9c, 0x58,
- 0xbf, 0xff, 0x7c, 0x5e, 0xd4, 0xfb, 0x99, 0xbf, 0x27, 0x5b, 0xac, 0x5f,
- 0x08, 0x23, 0x44, 0xb1, 0x7f, 0x9c, 0xdc, 0x84, 0x83, 0x8b, 0x15, 0x03,
- 0xda, 0xe1, 0x35, 0xe1, 0xc9, 0xd6, 0x2f, 0xf4, 0xf9, 0xf7, 0x71, 0xca,
- 0xc5, 0xb4, 0xb1, 0x7f, 0xfd, 0x11, 0x3f, 0x3d, 0x26, 0x3e, 0xa2, 0x9f,
- 0xac, 0x5c, 0xde, 0x58, 0xa8, 0x1f, 0xde, 0x09, 0x32, 0x95, 0x0d, 0x1f,
- 0x1a, 0x1d, 0xf4, 0x2b, 0xaf, 0x67, 0x1d, 0x62, 0xff, 0x4f, 0xa5, 0xc8,
- 0xce, 0x2c, 0x56, 0x1e, 0x7e, 0x87, 0x2f, 0xff, 0xbd, 0xc3, 0x39, 0xe7,
- 0x92, 0xf1, 0x30, 0x16, 0x2e, 0x37, 0x65, 0x8a, 0xc3, 0xea, 0x35, 0x42,
- 0xfe, 0xee, 0x12, 0x71, 0x44, 0xb1, 0x7f, 0x1c, 0x73, 0xc1, 0x12, 0xc5,
- 0xe8, 0x49, 0xd6, 0x2f, 0xf7, 0xa1, 0x86, 0xb1, 0x01, 0x62, 0xef, 0xba,
- 0xc5, 0x76, 0x7d, 0x0e, 0x3b, 0xe3, 0x4a, 0x94, 0x7b, 0x39, 0x8b, 0x42,
- 0x5a, 0xfc, 0xda, 0xf1, 0x4a, 0xc5, 0xf0, 0xa2, 0x11, 0xab, 0x17, 0xf6,
- 0xf3, 0xc6, 0xec, 0x0b, 0x15, 0xb9, 0xfe, 0xc4, 0x4e, 0x44, 0xd7, 0xdc,
- 0xeb, 0xc3, 0x16, 0x2f, 0xfe, 0xce, 0x98, 0x3d, 0x4b, 0xc1, 0xb8, 0xb1,
- 0x66, 0xec, 0xfb, 0x34, 0x4f, 0x7e, 0xf7, 0x70, 0x90, 0xd6, 0x2f, 0xe6,
- 0x33, 0x3a, 0x4f, 0x16, 0x2b, 0x0f, 0x6c, 0x45, 0x77, 0xff, 0x7d, 0xcc,
- 0xf3, 0x90, 0xa1, 0x9c, 0x58, 0xbf, 0xee, 0xf8, 0x58, 0x3f, 0xb0, 0x6b,
- 0x17, 0xdc, 0x7f, 0x4a, 0xc5, 0x39, 0xee, 0xb1, 0xdd, 0xff, 0xf6, 0x6d,
- 0x9d, 0xfb, 0x8e, 0x52, 0x06, 0x3a, 0xc5, 0x62, 0x62, 0x46, 0xc2, 0x8b,
- 0x84, 0x17, 0xfe, 0xcf, 0xce, 0xb2, 0x30, 0x30, 0xc3, 0x48, 0xb9, 0xc3,
- 0x58, 0xbb, 0x68, 0xc8, 0xd4, 0xc9, 0x82, 0x98, 0x4f, 0xc2, 0x10, 0xe3,
- 0x84, 0x56, 0x10, 0xee, 0x53, 0xdc, 0x2c, 0xde, 0x31, 0xa8, 0xa1, 0x08,
- 0x78, 0x45, 0xfe, 0x31, 0x86, 0x85, 0x78, 0x21, 0x38, 0x50, 0x83, 0xf4,
- 0x66, 0x71, 0xc6, 0xc1, 0x11, 0x6f, 0xda, 0xdd, 0x9b, 0x75, 0x45, 0x78,
- 0x5f, 0xfd, 0xf9, 0xdb, 0x53, 0xe7, 0xdd, 0xc6, 0xb1, 0x7f, 0xf8, 0x6d,
- 0xae, 0x92, 0x0f, 0xc9, 0xd8, 0x96, 0x2f, 0xfd, 0xe9, 0x27, 0xd8, 0xed,
- 0xa0, 0x2c, 0x54, 0xa2, 0x29, 0x92, 0xef, 0xff, 0xec, 0x1f, 0xe4, 0xc8,
- 0xcf, 0x13, 0x03, 0x9c, 0x90, 0x24, 0x5a, 0x33, 0x13, 0x87, 0x88, 0xdc,
- 0xa1, 0xa1, 0x1c, 0x43, 0x7f, 0xf4, 0x63, 0x42, 0x33, 0x35, 0xbb, 0x36,
- 0xea, 0x89, 0x1c, 0xbb, 0x0e, 0xb1, 0x77, 0xb1, 0x62, 0xfb, 0xbf, 0x18,
- 0x05, 0x8a, 0xdc, 0xf5, 0x3b, 0x17, 0x71, 0x7b, 0xff, 0xec, 0xf3, 0xfc,
- 0x5f, 0x67, 0xef, 0x92, 0x6a, 0xc5, 0xff, 0xe3, 0x5f, 0x59, 0xa8, 0x4f,
- 0xfe, 0xe0, 0x58, 0xbb, 0xe3, 0x58, 0xba, 0x46, 0xb1, 0x7f, 0xfe, 0xf4,
- 0x8e, 0x44, 0x17, 0xd4, 0xf9, 0xc1, 0x30, 0x58, 0xbf, 0xde, 0x78, 0x6b,
- 0x4f, 0xda, 0xc5, 0xe2, 0x68, 0xc8, 0x22, 0xf7, 0xe3, 0x1d, 0x05, 0xcc,
- 0x59, 0xbf, 0xe1, 0x37, 0xf0, 0x6c, 0xdb, 0xac, 0x5f, 0xfc, 0xe1, 0xf5,
- 0xe6, 0x3c, 0x73, 0x97, 0x96, 0x2f, 0xff, 0x6a, 0x73, 0xb8, 0xcf, 0x42,
- 0x40, 0x77, 0x58, 0xad, 0xd1, 0xa1, 0xc3, 0x9f, 0x24, 0xdf, 0xfe, 0x0d,
- 0xe2, 0x8c, 0x2c, 0xd6, 0x67, 0x61, 0xac, 0x5e, 0x70, 0x4a, 0xc5, 0xed,
- 0xf0, 0xe9, 0x11, 0x85, 0xe5, 0xe0, 0x9f, 0x35, 0x62, 0xfb, 0x1b, 0xb0,
- 0x2c, 0x5f, 0xf8, 0x1c, 0xeb, 0xbf, 0xdf, 0xa3, 0xe9, 0x62, 0xff, 0xfa,
- 0x48, 0x5c, 0xfb, 0xeb, 0x3a, 0x49, 0x79, 0x62, 0xa5, 0x12, 0xbf, 0x45,
- 0xbf, 0xf9, 0xf5, 0x9a, 0x84, 0xff, 0xee, 0x05, 0x8b, 0xed, 0xd9, 0xb7,
- 0x54, 0x49, 0x05, 0xfc, 0xda, 0xce, 0x9f, 0xc5, 0x8a, 0xd9, 0x37, 0xe8,
- 0x42, 0xe0, 0xd2, 0x2d, 0x22, 0x00, 0xc6, 0xfa, 0x2f, 0x66, 0xeb, 0x17,
- 0xe9, 0x70, 0x39, 0xd6, 0x2a, 0x4f, 0x32, 0x04, 0xb7, 0xf1, 0x78, 0xa4,
- 0xfc, 0x58, 0xbd, 0xa9, 0x1a, 0xc5, 0x49, 0xe5, 0x61, 0x6d, 0xff, 0xf9,
- 0xf4, 0xe1, 0x24, 0xb6, 0x9f, 0x3f, 0xdb, 0x65, 0x8b, 0xf3, 0x43, 0xcf,
- 0xb2, 0xc5, 0x4a, 0x20, 0x1d, 0x5e, 0xfb, 0x63, 0x88, 0x35, 0x8b, 0xff,
- 0xcd, 0xe8, 0xb9, 0x83, 0x18, 0x9b, 0x50, 0x58, 0xbf, 0xfe, 0x6e, 0xf9,
- 0x9f, 0x62, 0xcd, 0x8e, 0x2f, 0xac, 0x5f, 0xfd, 0xf7, 0xef, 0xd9, 0xdf,
- 0xb5, 0xa9, 0x58, 0xbf, 0xf9, 0xe4, 0xec, 0x33, 0x02, 0x49, 0x41, 0x62,
- 0xfe, 0x9f, 0xf2, 0x3a, 0x7c, 0xb1, 0x6f, 0x2c, 0x56, 0x26, 0x43, 0xba,
- 0x8f, 0xd1, 0xc0, 0x8d, 0xe3, 0x1b, 0xff, 0xb0, 0x11, 0xd9, 0xa9, 0xd9,
- 0xb5, 0xba, 0xc5, 0xf9, 0x81, 0xec, 0x02, 0xc5, 0x11, 0xf8, 0xf1, 0x26,
- 0xff, 0x67, 0xd8, 0xe5, 0x3d, 0xac, 0x5d, 0x08, 0xc9, 0x5e, 0x3c, 0x81,
- 0x86, 0x47, 0x3e, 0xf0, 0x9e, 0x89, 0xaf, 0xf0, 0xa0, 0x62, 0x10, 0x13,
- 0x72, 0x36, 0xdf, 0x42, 0xf0, 0xc2, 0x1b, 0xf0, 0xbb, 0xdd, 0xf8, 0xb1,
- 0x7f, 0xd9, 0xe7, 0xe6, 0xb5, 0x90, 0x58, 0xb8, 0x2d, 0x42, 0x8b, 0x17,
- 0x30, 0x16, 0x29, 0x62, 0xb4, 0x68, 0xce, 0x2f, 0x7f, 0x7d, 0xfb, 0xf3,
- 0x7d, 0x62, 0xf6, 0x7e, 0x32, 0x36, 0x44, 0xb6, 0x23, 0x6e, 0x43, 0x6e,
- 0xd6, 0x2f, 0x10, 0x8e, 0xb1, 0x7f, 0xf9, 0xc8, 0x50, 0xce, 0x16, 0x6c,
- 0x64, 0x16, 0x28, 0x67, 0xf6, 0x68, 0x9f, 0x87, 0x6d, 0x19, 0x2c, 0xc3,
- 0x61, 0x98, 0x62, 0x8e, 0xf1, 0x84, 0x77, 0x19, 0x1b, 0x98, 0xb4, 0xf5,
- 0x40, 0x21, 0x87, 0xc2, 0xbf, 0x43, 0x3c, 0xc8, 0x62, 0x5f, 0xfd, 0x18,
- 0xd0, 0x8c, 0xcd, 0x6e, 0xcd, 0xba, 0xa2, 0x4a, 0x2f, 0xb7, 0x66, 0xdd,
- 0x51, 0x78, 0x97, 0x8c, 0x90, 0x2c, 0x56, 0x8f, 0x3c, 0xe6, 0x37, 0xfd,
- 0x08, 0xcc, 0xd6, 0xec, 0xdb, 0xaa, 0x24, 0xd2, 0xd1, 0x98, 0x7d, 0xac,
- 0x45, 0x7c, 0x14, 0x97, 0x8e, 0x58, 0xbd, 0xf7, 0x25, 0x8a, 0x8d, 0xcf,
- 0x17, 0x72, 0x9b, 0xd1, 0xa8, 0x3d, 0x96, 0x2e, 0x1c, 0x6c, 0xb1, 0x7f,
- 0xa3, 0x48, 0xd3, 0xf8, 0x7c, 0xe2, 0xc5, 0xf1, 0x9b, 0x43, 0xcb, 0x14,
- 0x15, 0x3e, 0x48, 0xd8, 0xfa, 0xff, 0xfc, 0x36, 0x87, 0x05, 0xe9, 0xf7,
- 0x01, 0xef, 0x76, 0xb1, 0x7b, 0xde, 0xed, 0x62, 0xe0, 0xa4, 0x6d, 0x87,
- 0xf0, 0x05, 0x9b, 0xf7, 0x39, 0x85, 0x8b, 0x17, 0xfd, 0xad, 0xe7, 0x6c,
- 0xc2, 0xf2, 0xc5, 0xfc, 0x46, 0x45, 0xa9, 0xe8, 0xb1, 0x7c, 0xcf, 0xdf,
- 0x16, 0x2f, 0xf7, 0x39, 0x80, 0x37, 0xc4, 0xb1, 0x7f, 0xfe, 0xf7, 0x00,
- 0x59, 0xef, 0xe7, 0x8a, 0x64, 0xeb, 0x16, 0xfa, 0xc5, 0x62, 0x6a, 0x2e,
- 0x4f, 0x1e, 0x75, 0xf3, 0x26, 0x23, 0x23, 0x50, 0xd5, 0x2f, 0x87, 0xf9,
- 0xd9, 0x62, 0xff, 0x4f, 0xe4, 0x46, 0x38, 0x45, 0x8b, 0xf6, 0x14, 0xf7,
- 0xc5, 0x8b, 0xff, 0xa1, 0x3e, 0xf9, 0x9c, 0x9f, 0x61, 0xd6, 0x28, 0x07,
- 0xdd, 0xe2, 0x8a, 0xd9, 0x18, 0xcf, 0x0a, 0x4b, 0xf1, 0x3e, 0xee, 0x35,
- 0x8b, 0xdd, 0x26, 0x0b, 0x17, 0xe9, 0xf7, 0x33, 0xcb, 0x17, 0x98, 0x87,
- 0x87, 0x8f, 0xf1, 0xfb, 0xfc, 0xe6, 0xf7, 0xcc, 0x23, 0x56, 0x2f, 0xf1,
- 0xc5, 0xef, 0xc8, 0x82, 0xeb, 0x17, 0xd8, 0x2d, 0x6c, 0xb1, 0x79, 0xb5,
- 0x0e, 0xa7, 0xbb, 0xc3, 0x9a, 0xc4, 0xda, 0x1d, 0xbf, 0xe6, 0x22, 0x84,
- 0x9d, 0xfb, 0x05, 0xbb, 0x12, 0xc5, 0xe9, 0x9f, 0x2c, 0x5f, 0xf6, 0x00,
- 0x7f, 0x92, 0x90, 0xd6, 0x2f, 0x81, 0xcc, 0x25, 0x8a, 0x93, 0xdb, 0x73,
+ 0x04, 0x86, 0xb1, 0x7f, 0x86, 0x2e, 0xb9, 0xfc, 0xe2, 0xc5, 0xfe, 0xcf,
+ 0x70, 0x3d, 0xa7, 0x65, 0x8b, 0xfd, 0x99, 0x10, 0x4d, 0xd7, 0x16, 0x2f,
+ 0xee, 0x67, 0xf2, 0x1c, 0x58, 0xb6, 0x00, 0xf9, 0x3c, 0x6d, 0x7f, 0xce,
+ 0x59, 0xcf, 0x73, 0x36, 0x58, 0xbf, 0xe9, 0x18, 0x58, 0x43, 0xfc, 0xac,
+ 0x56, 0x1f, 0x90, 0x47, 0x37, 0xfe, 0x7e, 0xa1, 0xc2, 0xcf, 0x7c, 0x4b,
+ 0x17, 0xfc, 0xfa, 0xfe, 0x61, 0x43, 0x8b, 0x15, 0x03, 0xf8, 0xdd, 0x02,
+ 0xf9, 0xbb, 0x61, 0x2c, 0x5f, 0xff, 0xf6, 0x1f, 0xef, 0x3e, 0x2c, 0xf7,
+ 0xf0, 0xb0, 0x26, 0x02, 0xc5, 0xf6, 0x70, 0x3e, 0x2c, 0x5f, 0xfe, 0x68,
+ 0x89, 0x82, 0xd4, 0xbc, 0x1b, 0x8b, 0x15, 0xd2, 0x63, 0x1a, 0x23, 0xf9,
+ 0x19, 0x32, 0x08, 0x92, 0xe8, 0xfe, 0xe5, 0x8b, 0xfd, 0xbf, 0xdc, 0xf3,
+ 0xa3, 0x56, 0x2f, 0xc6, 0xe6, 0x11, 0xab, 0x16, 0x68, 0x1e, 0xfe, 0x8d,
+ 0xae, 0x07, 0x78, 0xb1, 0x7f, 0x6c, 0x1c, 0x73, 0x10, 0x16, 0x2f, 0xe3,
+ 0x33, 0x4d, 0xee, 0x2c, 0x5f, 0xf9, 0x88, 0x19, 0xe9, 0x27, 0x02, 0xc5,
+ 0x4a, 0x27, 0x8e, 0x67, 0x1c, 0x5f, 0x68, 0xce, 0xf1, 0x91, 0xa7, 0x31,
+ 0xc1, 0x64, 0x3c, 0x0d, 0x2f, 0x72, 0x08, 0xa1, 0x04, 0x72, 0x0f, 0xa8,
+ 0x31, 0x40, 0x0d, 0x8a, 0x13, 0x7c, 0x84, 0xcf, 0xa3, 0xb2, 0x12, 0x58,
+ 0x4f, 0xb1, 0xc4, 0xe1, 0xc2, 0xee, 0xa0, 0xec, 0x23, 0xb5, 0x38, 0x64,
+ 0x78, 0x55, 0xb5, 0x7f, 0x2b, 0xc8, 0xf2, 0xfd, 0x49, 0x32, 0xbf, 0xfa,
+ 0x31, 0xa1, 0x19, 0x9a, 0xdd, 0x9b, 0x75, 0x48, 0x72, 0x5f, 0xfe, 0x8c,
+ 0x3b, 0x42, 0x33, 0x35, 0xbb, 0x36, 0xea, 0x91, 0xc8, 0xbf, 0xd1, 0x99,
+ 0xad, 0xd9, 0xb7, 0x54, 0x99, 0x85, 0xff, 0xe1, 0xb1, 0xcc, 0xce, 0xa1,
+ 0x80, 0xc1, 0xac, 0x5d, 0xe0, 0x2c, 0x5f, 0xb3, 0xe5, 0x9a, 0x58, 0xbd,
+ 0xb4, 0xe9, 0x62, 0xfb, 0x8c, 0x78, 0xcc, 0x45, 0x4f, 0xd3, 0x08, 0x63,
+ 0x84, 0xf7, 0x46, 0x71, 0x62, 0xa0, 0x7e, 0x1d, 0x2a, 0xdf, 0x46, 0xbe,
+ 0xf3, 0xbc, 0x8d, 0x6b, 0x17, 0xf8, 0x78, 0x79, 0xea, 0x4e, 0xb1, 0x5d,
+ 0xe1, 0xf7, 0x46, 0xb3, 0xab, 0x76, 0x58, 0xbf, 0xa3, 0x48, 0xd3, 0x7f,
+ 0xcf, 0x4b, 0x17, 0x77, 0xdc, 0x72, 0xc5, 0xee, 0xfb, 0x8e, 0x8d, 0xd6,
+ 0x2a, 0x37, 0x3c, 0xf8, 0xd0, 0x8a, 0xff, 0xed, 0x69, 0x8a, 0x28, 0x39,
+ 0x19, 0x1e, 0xb1, 0x7f, 0xb5, 0x3e, 0xfb, 0x75, 0x05, 0x8b, 0xff, 0xff,
+ 0xe9, 0x8b, 0xf3, 0xe9, 0x0d, 0xf5, 0x14, 0xff, 0x3b, 0x67, 0xf0, 0x7d,
+ 0xb1, 0x62, 0x8c, 0x4c, 0x00, 0x09, 0x24, 0x6b, 0x7f, 0xd9, 0xc6, 0xf0,
+ 0x03, 0x28, 0x2c, 0x58, 0x0b, 0x17, 0xf7, 0x35, 0xac, 0xeb, 0x8b, 0x17,
+ 0x4c, 0x16, 0x2b, 0xbc, 0x3d, 0x9c, 0x12, 0xd1, 0x85, 0xfb, 0x92, 0x00,
+ 0xf6, 0x58, 0xbd, 0xac, 0x3a, 0xc5, 0xf3, 0x96, 0x71, 0x62, 0xd9, 0xc3,
+ 0xe9, 0xf1, 0x5f, 0x70, 0xed, 0x2c, 0x52, 0xc5, 0xff, 0xb5, 0xa6, 0x28,
+ 0xa0, 0xe4, 0x66, 0xc5, 0xc0, 0xc3, 0x2f, 0xff, 0xfd, 0xf9, 0x21, 0x73,
+ 0x92, 0x1f, 0x9c, 0x85, 0x0c, 0xe7, 0x9d, 0x62, 0xfc, 0x59, 0xdb, 0x09,
+ 0x62, 0xfb, 0xde, 0x7d, 0x2c, 0x5d, 0xc0, 0x2c, 0x51, 0x89, 0x92, 0x41,
+ 0x55, 0xdb, 0x34, 0x51, 0xe2, 0x3b, 0x79, 0x62, 0xdd, 0xcb, 0x15, 0x1c,
+ 0x69, 0xc3, 0x12, 0xa5, 0x8a, 0x58, 0xbf, 0xf6, 0xb4, 0xc5, 0x14, 0x1c,
+ 0x8c, 0x34, 0xb8, 0x88, 0x32, 0xef, 0xc4, 0xb1, 0x71, 0x6e, 0xb1, 0x46,
+ 0x22, 0x1e, 0x0a, 0xcc, 0x33, 0x7b, 0x93, 0xc5, 0x8b, 0xff, 0xb5, 0xa6,
+ 0x28, 0xa0, 0xe4, 0x66, 0x96, 0x2f, 0xee, 0x04, 0xc4, 0xdb, 0x2c, 0x51,
+ 0x87, 0xeb, 0x12, 0x35, 0xd1, 0xdc, 0x58, 0xbf, 0x61, 0xc3, 0xeb, 0x8b,
+ 0x17, 0x10, 0x16, 0x2f, 0xcc, 0x16, 0xd8, 0x12, 0xc5, 0x6c, 0x88, 0x88,
+ 0x0d, 0xb1, 0x59, 0x0b, 0xdb, 0xeb, 0x17, 0xc6, 0xfd, 0xf8, 0xb1, 0x7f,
+ 0x30, 0x71, 0xcc, 0x40, 0x58, 0xa8, 0xd8, 0xf9, 0xc4, 0x24, 0x11, 0x25,
+ 0x9d, 0x62, 0xff, 0x4f, 0x27, 0xdb, 0x60, 0x4b, 0x16, 0x73, 0x9e, 0x31,
+ 0x08, 0xd2, 0xc5, 0x2c, 0x52, 0xc5, 0xff, 0xb5, 0xa6, 0x28, 0xa0, 0xe4,
+ 0x64, 0x9a, 0x4e, 0x83, 0x1c, 0x32, 0xd0, 0x58, 0xbc, 0xc4, 0x05, 0x8a,
+ 0xdc, 0xd7, 0x68, 0x4a, 0xfd, 0xee, 0x14, 0xc1, 0x62, 0xf8, 0x2f, 0x49,
+ 0xab, 0x14, 0x62, 0x3f, 0xa6, 0x11, 0xf8, 0x44, 0xe5, 0x14, 0xb1, 0x4b,
+ 0x17, 0xfe, 0xd6, 0x98, 0xa2, 0x83, 0x91, 0x9b, 0x97, 0x00, 0x0c, 0xbe,
+ 0xc1, 0xb4, 0x16, 0x2f, 0xc0, 0xce, 0x07, 0xf5, 0x8b, 0xbd, 0xb2, 0xc5,
+ 0xdd, 0xa5, 0x62, 0xff, 0x87, 0xf9, 0xe7, 0x33, 0x52, 0xb1, 0x77, 0x69,
+ 0x58, 0xbb, 0xb4, 0xac, 0x51, 0x89, 0x9f, 0x41, 0x57, 0xa2, 0x27, 0x2a,
+ 0x38, 0xc9, 0x0c, 0xf0, 0xe6, 0x38, 0x66, 0xff, 0xed, 0x69, 0x8a, 0x28,
+ 0x39, 0x19, 0xc5, 0x8b, 0xa4, 0x4b, 0x17, 0xe2, 0x1e, 0x75, 0xe5, 0x8b,
+ 0x7d, 0x62, 0x8c, 0x44, 0xc0, 0xd1, 0x98, 0x5c, 0x45, 0x37, 0x01, 0x96,
+ 0x2f, 0xfe, 0xd6, 0x98, 0xa2, 0x83, 0x91, 0x98, 0xb1, 0x76, 0x12, 0xc5,
+ 0xc0, 0x12, 0xc5, 0x49, 0xae, 0xd0, 0xb5, 0xf3, 0x43, 0xf8, 0xb1, 0x7e,
+ 0xe7, 0xe4, 0xbc, 0xb1, 0x7b, 0xd9, 0x2b, 0x14, 0x33, 0xe6, 0x34, 0x8b,
+ 0xa2, 0x8b, 0xb7, 0x95, 0x8a, 0x31, 0x34, 0x21, 0xb9, 0xe4, 0x21, 0xb7,
+ 0x31, 0xb0, 0x6b, 0x17, 0xda, 0x89, 0xfe, 0xb1, 0x7f, 0xfb, 0x79, 0xe7,
+ 0x30, 0xfd, 0x78, 0x45, 0xe5, 0x8b, 0xde, 0xc3, 0xac, 0x5f, 0xe9, 0x06,
+ 0x14, 0xf5, 0xc5, 0x8b, 0xc0, 0xce, 0x2c, 0x5f, 0x61, 0x0a, 0x56, 0x28,
+ 0xc4, 0xc4, 0xa4, 0x4f, 0x09, 0x1d, 0x37, 0x83, 0xbe, 0x33, 0x10, 0xed,
+ 0xee, 0x49, 0xd6, 0x2f, 0xa7, 0xf8, 0x35, 0x8b, 0xfd, 0xc6, 0xf0, 0x03,
+ 0x28, 0x2c, 0x5f, 0x7a, 0x39, 0x8d, 0x58, 0xad, 0x8f, 0xfb, 0xa2, 0x22,
+ 0x35, 0xa8, 0x91, 0x96, 0xd0, 0x9b, 0xa5, 0x8a, 0x58, 0xbf, 0xf6, 0xb4,
+ 0xc5, 0x14, 0x1c, 0x8c, 0xef, 0xcb, 0x82, 0x0c, 0xbf, 0x6f, 0xf6, 0x7e,
+ 0xfd, 0x62, 0xfc, 0x2e, 0x4f, 0x25, 0x62, 0x8c, 0x45, 0x76, 0x96, 0x18,
+ 0xba, 0x96, 0x29, 0x62, 0xff, 0xda, 0xd3, 0x14, 0x50, 0x72, 0x32, 0x05,
+ 0xc1, 0xc3, 0x2f, 0xe2, 0x07, 0xf0, 0x0c, 0xb1, 0x7c, 0x53, 0xd8, 0x4b,
+ 0x14, 0x62, 0x29, 0x5d, 0x51, 0x8b, 0x6c, 0x75, 0x8b, 0x8d, 0x8e, 0x58,
+ 0xae, 0x8d, 0x73, 0x89, 0x5f, 0xfd, 0xad, 0x31, 0x45, 0x07, 0x23, 0x19,
+ 0x62, 0xfe, 0x19, 0x91, 0xb9, 0x67, 0x72, 0xc5, 0xed, 0xa2, 0x95, 0x8a,
+ 0x58, 0xbf, 0xe2, 0x06, 0x7a, 0x49, 0xc0, 0xb1, 0x58, 0x78, 0x6c, 0x19,
+ 0x46, 0x23, 0xfa, 0x51, 0x58, 0xde, 0x39, 0x8a, 0xf1, 0x0a, 0x25, 0x8b,
+ 0x46, 0x77, 0x8d, 0xa2, 0x2f, 0x7a, 0x5b, 0x1a, 0x0a, 0x46, 0xb8, 0x45,
+ 0x4c, 0x65, 0x9b, 0x18, 0xc2, 0x12, 0x63, 0x84, 0xe6, 0x46, 0xe6, 0x6b,
+ 0x96, 0xf0, 0xc4, 0xe8, 0xc1, 0xe1, 0x25, 0x14, 0x2b, 0x35, 0x0a, 0x33,
+ 0xbd, 0xfe, 0x34, 0x86, 0x8e, 0x58, 0x11, 0x86, 0xf7, 0xe7, 0xa5, 0x1a,
+ 0xcf, 0x23, 0x56, 0xf4, 0x65, 0xc2, 0x87, 0x77, 0x68, 0x76, 0xc7, 0x2e,
+ 0x87, 0x18, 0xff, 0x71, 0xfd, 0xfb, 0x5b, 0xb3, 0x6e, 0xa9, 0x37, 0x4b,
+ 0x88, 0x4b, 0x16, 0xe2, 0xc5, 0x61, 0xf0, 0x68, 0xdc, 0x02, 0xf7, 0xfa,
+ 0x75, 0x2e, 0x3c, 0x3a, 0xc5, 0xef, 0xce, 0x96, 0x2f, 0xd1, 0x17, 0x59,
+ 0xba, 0xc5, 0xff, 0x84, 0x32, 0x63, 0x70, 0x6d, 0x05, 0x8b, 0x46, 0x6c,
+ 0x8b, 0x91, 0x99, 0x60, 0xef, 0x0a, 0xea, 0x31, 0x32, 0xdf, 0xc3, 0x9e,
+ 0xfc, 0xe0, 0xe6, 0x77, 0x2c, 0x5f, 0xe7, 0xd8, 0xb0, 0x02, 0xe2, 0xc5,
+ 0xf9, 0xf4, 0x1c, 0x5c, 0x58, 0xa8, 0x8f, 0x7f, 0xe6, 0x97, 0xf1, 0x34,
+ 0x66, 0xb6, 0xfa, 0xc5, 0xd9, 0xba, 0xc5, 0xa5, 0x62, 0xb0, 0xd4, 0x84,
+ 0x31, 0x79, 0xfa, 0x02, 0xc5, 0xfb, 0xa8, 0x7d, 0xc0, 0xb1, 0x7f, 0xf6,
+ 0x9b, 0x70, 0x0b, 0x9e, 0x9e, 0x82, 0x58, 0xb8, 0x8d, 0x58, 0xb3, 0x2c,
+ 0x5f, 0x6e, 0xcd, 0xba, 0xa4, 0x90, 0x2b, 0x0f, 0x6a, 0x21, 0x8d, 0x08,
+ 0xdf, 0xe8, 0x79, 0xc2, 0xe0, 0x1d, 0x62, 0xfe, 0x8f, 0xdf, 0xf2, 0xfa,
+ 0x58, 0xbd, 0x99, 0xba, 0xc5, 0xcf, 0xf5, 0x8b, 0xff, 0x9f, 0x8f, 0xdb,
+ 0xec, 0x7d, 0x4f, 0x16, 0x2b, 0x0f, 0x75, 0x85, 0xef, 0xfc, 0xd1, 0xd2,
+ 0x5b, 0xe7, 0xbe, 0xeb, 0x17, 0xfe, 0xcf, 0xbf, 0x6f, 0xe6, 0x16, 0xeb,
+ 0x17, 0xf6, 0x7f, 0x3e, 0xe6, 0xac, 0x5f, 0xbd, 0x3d, 0x9f, 0xb2, 0xc5,
+ 0xe6, 0x84, 0x64, 0xaa, 0xd8, 0x19, 0x56, 0x42, 0x8f, 0xa2, 0xf7, 0x35,
+ 0x88, 0xcb, 0xef, 0x44, 0x41, 0xc4, 0x1f, 0x20, 0x76, 0x2e, 0xbd, 0xcf,
+ 0x89, 0x62, 0xe9, 0x0d, 0x62, 0xb0, 0xdb, 0x04, 0x3d, 0x7f, 0x49, 0x73,
+ 0x8e, 0x75, 0x8a, 0xc3, 0xce, 0x72, 0x1b, 0xfc, 0xe3, 0x17, 0xb8, 0x72,
+ 0x58, 0xbe, 0x08, 0xf3, 0xc5, 0x8b, 0xff, 0xf0, 0xde, 0x30, 0x5e, 0xdf,
+ 0xf9, 0xef, 0xe7, 0x5c, 0x58, 0xbc, 0xc5, 0x05, 0x8b, 0xf8, 0x5a, 0x37,
+ 0xed, 0x05, 0x8b, 0xf7, 0x8a, 0x73, 0xa5, 0x8b, 0x46, 0x4a, 0xf4, 0xf6,
+ 0x42, 0x2b, 0x72, 0x38, 0x96, 0xf4, 0x42, 0x79, 0x5e, 0xdf, 0x8c, 0xdd,
+ 0x88, 0x04, 0x69, 0xd8, 0x90, 0x25, 0xc8, 0xe1, 0xc0, 0xcc, 0x2f, 0xfe,
+ 0x8c, 0x68, 0x46, 0x66, 0xb7, 0x66, 0xdd, 0x52, 0x29, 0x15, 0xb3, 0xa2,
+ 0x7b, 0x89, 0x64, 0xeb, 0xed, 0x1a, 0xf0, 0x2b, 0x4d, 0x62, 0x97, 0x2d,
+ 0xe9, 0xec, 0xae, 0xe8, 0x6b, 0x5e, 0x66, 0xdd, 0x62, 0xe0, 0x4a, 0xc5,
+ 0xb5, 0xb9, 0xb4, 0x00, 0xed, 0xfe, 0x66, 0xdb, 0x21, 0x26, 0xac, 0x52,
+ 0xc5, 0xee, 0xa4, 0x35, 0x8a, 0xdc, 0xd5, 0xb0, 0x65, 0xfd, 0x9e, 0xf3,
+ 0x85, 0xe5, 0x8b, 0x9b, 0x75, 0x8b, 0x46, 0x62, 0x3b, 0xe2, 0x28, 0x65,
+ 0xf2, 0x21, 0xec, 0x5f, 0x7f, 0x39, 0x67, 0xf3, 0x75, 0x8b, 0xf9, 0xcb,
+ 0xd8, 0xe3, 0x58, 0xba, 0x1e, 0x58, 0xbc, 0x52, 0x12, 0xc5, 0xd3, 0x19,
+ 0xa3, 0x6a, 0x43, 0x15, 0x04, 0x47, 0xf9, 0x86, 0xf7, 0x04, 0x75, 0x8b,
+ 0x41, 0x62, 0xe3, 0xf9, 0x62, 0xee, 0x32, 0xc5, 0xfb, 0x35, 0xe7, 0xc5,
+ 0x8b, 0xbd, 0x8b, 0x16, 0x8d, 0xd6, 0x2d, 0x19, 0x04, 0xe4, 0xfa, 0x85,
+ 0xe3, 0x91, 0xc4, 0x3c, 0x71, 0x20, 0x0c, 0x10, 0xbf, 0x62, 0x78, 0xe1,
+ 0x7b, 0xf7, 0x23, 0x03, 0x1f, 0xd6, 0x2f, 0xe2, 0xf4, 0x76, 0x4e, 0x96,
+ 0x2f, 0xff, 0x6a, 0x61, 0x1d, 0x9e, 0xe3, 0xfb, 0x68, 0x2c, 0x5f, 0xef,
+ 0x72, 0x62, 0x66, 0xd2, 0xc5, 0x4a, 0x20, 0xdd, 0x3e, 0xff, 0xfb, 0x3c,
+ 0xff, 0x17, 0xd9, 0xfa, 0xe4, 0x9a, 0xb1, 0x78, 0x9a, 0x0b, 0x17, 0x76,
+ 0x75, 0x8b, 0xfe, 0x97, 0xf7, 0xe7, 0xf2, 0x75, 0x8b, 0xf4, 0x6d, 0xde,
+ 0xeb, 0x9c, 0x58, 0xbf, 0xfd, 0xc6, 0x83, 0x9a, 0xf0, 0xc0, 0x73, 0x16,
+ 0x2f, 0xfe, 0xe8, 0x1a, 0xc1, 0xce, 0x9f, 0xa0, 0x2c, 0x5f, 0xd9, 0xf7,
+ 0x29, 0x3a, 0xc5, 0x2c, 0x5f, 0x9e, 0x3b, 0x35, 0x2b, 0x17, 0x61, 0xe4,
+ 0xdb, 0x70, 0x32, 0xb6, 0x4c, 0x79, 0xd2, 0xb4, 0x8f, 0xdc, 0xc5, 0x7f,
+ 0xe1, 0x6a, 0x19, 0x07, 0x34, 0xd6, 0x58, 0xbf, 0x6b, 0x76, 0x6d, 0xd5,
+ 0x23, 0xb1, 0x7f, 0xfb, 0x69, 0xdf, 0x93, 0xec, 0xd6, 0xa7, 0x75, 0x8b,
+ 0xf6, 0x40, 0xa7, 0x65, 0x8b, 0xe0, 0x34, 0x71, 0xab, 0x17, 0xfd, 0xdd,
+ 0x27, 0x98, 0xc0, 0x82, 0x09, 0x62, 0xb0, 0xfa, 0x98, 0x9e, 0xfc, 0xda,
+ 0xdf, 0x58, 0xb1, 0x7f, 0xf7, 0xc4, 0x71, 0x7b, 0x3b, 0x60, 0x8e, 0xb1,
+ 0x7f, 0x9f, 0x9c, 0x7f, 0xcf, 0x16, 0x2b, 0x64, 0x52, 0x0c, 0xa4, 0xe9,
+ 0x17, 0xbe, 0xc1, 0x2c, 0x5f, 0xf1, 0x34, 0x04, 0x03, 0xb4, 0x16, 0x2d,
+ 0x83, 0x3d, 0x7f, 0x8f, 0x5f, 0xff, 0xfd, 0xc9, 0x2d, 0xe7, 0xb3, 0x7c,
+ 0x72, 0x37, 0x83, 0xeb, 0x61, 0x01, 0x62, 0xff, 0x8d, 0x7f, 0x71, 0xf7,
+ 0x6d, 0x2c, 0x5e, 0x68, 0x46, 0x77, 0xd5, 0x74, 0x36, 0x63, 0x52, 0xd9,
+ 0x07, 0x10, 0x5c, 0xdf, 0x49, 0xbf, 0x84, 0x93, 0x43, 0x10, 0xa1, 0x11,
+ 0xc2, 0x70, 0xdd, 0x6d, 0x1e, 0xb1, 0x7f, 0xff, 0x61, 0x13, 0x7b, 0xf9,
+ 0xc6, 0xcd, 0x00, 0xf8, 0xb1, 0x5b, 0x1f, 0x6b, 0x0a, 0xdf, 0xcf, 0xd8,
+ 0xb3, 0x8e, 0xb1, 0x7f, 0xf8, 0x47, 0x9e, 0xe6, 0x19, 0x49, 0x66, 0xeb,
+ 0x15, 0x03, 0xfa, 0x19, 0x75, 0xe2, 0x98, 0x2c, 0x53, 0x9b, 0xed, 0x11,
+ 0x5e, 0x7d, 0x41, 0x62, 0xff, 0x42, 0x75, 0xb4, 0xeb, 0x65, 0x8b, 0xff,
+ 0x7c, 0x9a, 0x02, 0x01, 0xda, 0x0b, 0x15, 0x27, 0xeb, 0x86, 0xd7, 0x04,
+ 0xeb, 0x17, 0xf9, 0xb6, 0x6c, 0xf6, 0x1d, 0x62, 0xfe, 0xd0, 0x30, 0x9b,
+ 0xeb, 0x17, 0xff, 0xec, 0xea, 0x1f, 0x9e, 0x36, 0xa7, 0xbb, 0xed, 0xba,
+ 0xc5, 0xa3, 0x25, 0x94, 0xa7, 0x08, 0x59, 0x8c, 0x87, 0x14, 0x5c, 0x73,
+ 0x43, 0x27, 0x9d, 0x45, 0xfc, 0x66, 0xcd, 0x0d, 0xa0, 0x10, 0x14, 0x24,
+ 0x82, 0x20, 0x8e, 0x18, 0x0c, 0xcf, 0xb8, 0xb6, 0xe0, 0x47, 0x2c, 0x5f,
+ 0x48, 0xe4, 0x96, 0x2f, 0x9f, 0x53, 0xd9, 0x62, 0xec, 0xfa, 0xc5, 0xff,
+ 0xd1, 0xcc, 0x40, 0xcf, 0x49, 0x38, 0x16, 0x2d, 0x19, 0x1e, 0x8b, 0xc2,
+ 0x1b, 0xe1, 0x0c, 0x71, 0x20, 0x62, 0xf7, 0xff, 0x31, 0xff, 0x9b, 0xb7,
+ 0xe4, 0x38, 0x2c, 0x5f, 0xbd, 0xac, 0x90, 0x96, 0x2f, 0x38, 0xd9, 0x62,
+ 0xff, 0xf7, 0xc9, 0x80, 0xfe, 0x93, 0xe9, 0xcd, 0x58, 0xbf, 0xf8, 0xb3,
+ 0xed, 0xb6, 0x70, 0x9b, 0xa5, 0x8b, 0xa3, 0xa3, 0x06, 0x98, 0xcb, 0xa3,
+ 0x7c, 0xa5, 0x87, 0x38, 0x95, 0x52, 0xd8, 0x3d, 0xc2, 0x3e, 0x6c, 0x84,
+ 0x91, 0xe9, 0x50, 0x3c, 0x8e, 0xd6, 0x3a, 0x37, 0x2b, 0xff, 0xb4, 0xdd,
+ 0x46, 0x0f, 0x22, 0x66, 0xd9, 0x62, 0xff, 0xd1, 0xaa, 0x35, 0xf7, 0x9a,
+ 0xd6, 0x04, 0x4c, 0xb1, 0x7f, 0x41, 0xb5, 0xb7, 0xc4, 0xb1, 0x7e, 0xe4,
+ 0x80, 0x3d, 0x96, 0x2d, 0x91, 0x1e, 0xdf, 0x0c, 0x2f, 0xfc, 0xfa, 0xfb,
+ 0x73, 0xf2, 0xda, 0x58, 0xbf, 0xe9, 0x2e, 0x81, 0xce, 0x48, 0x16, 0x2f,
+ 0xb5, 0x81, 0x79, 0x62, 0xbe, 0x89, 0xce, 0x1f, 0x76, 0x3a, 0xbf, 0xda,
+ 0xce, 0x10, 0x98, 0x35, 0x8b, 0xff, 0xff, 0xfe, 0xfb, 0xf9, 0x9b, 0xae,
+ 0x73, 0x92, 0x79, 0xfe, 0x66, 0xd8, 0x59, 0xd7, 0xb9, 0x3d, 0x2c, 0x5f,
+ 0xe8, 0x37, 0xa2, 0x83, 0xf9, 0x62, 0xff, 0x4c, 0x1f, 0xce, 0x50, 0x58,
+ 0xbf, 0xfc, 0x3f, 0xcc, 0x36, 0xc0, 0xbd, 0x3d, 0x04, 0xb1, 0x7f, 0xff,
+ 0xed, 0xc5, 0xb6, 0x76, 0x9e, 0xb0, 0x6d, 0x00, 0xcf, 0xcc, 0x61, 0xac,
+ 0x5f, 0xd3, 0xa0, 0x6f, 0xbe, 0x2c, 0x5f, 0x9c, 0x3d, 0x84, 0x4b, 0x15,
+ 0xf3, 0xda, 0xe1, 0x85, 0xff, 0xbc, 0xf0, 0x7f, 0x88, 0xe7, 0x75, 0x8b,
+ 0xbd, 0x19, 0x1b, 0x2e, 0x27, 0x0e, 0x15, 0x99, 0x0c, 0x43, 0x4c, 0xb7,
+ 0x34, 0x8a, 0x12, 0xba, 0x35, 0x63, 0x2e, 0x27, 0xfa, 0x19, 0x81, 0x91,
+ 0x58, 0x6e, 0xba, 0xba, 0xd3, 0x93, 0x17, 0xfe, 0xeb, 0x8e, 0x73, 0x03,
+ 0xd6, 0x6c, 0xb1, 0x78, 0xb3, 0xcb, 0x15, 0x11, 0xf0, 0x12, 0x25, 0xfd,
+ 0x9a, 0x7f, 0x7e, 0x56, 0x2f, 0xe7, 0x20, 0x0f, 0x09, 0x62, 0xfb, 0x76,
+ 0x6d, 0xd5, 0x21, 0x61, 0x7f, 0x3e, 0x98, 0xb7, 0x95, 0x8b, 0xe7, 0x22,
+ 0x95, 0x8a, 0x82, 0x2a, 0xb4, 0x59, 0xf3, 0x1e, 0xc5, 0xb7, 0xe8, 0x85,
+ 0xb7, 0x74, 0xac, 0x5f, 0x67, 0x80, 0xeb, 0x17, 0xfe, 0x68, 0x46, 0x66,
+ 0xb7, 0x66, 0xdd, 0x52, 0x2e, 0x97, 0xf9, 0x87, 0x25, 0xf9, 0xe2, 0xc5,
+ 0xd3, 0x1e, 0xb1, 0x73, 0x1a, 0xb1, 0x50, 0x36, 0x5e, 0x1a, 0xbf, 0x3c,
+ 0x83, 0x09, 0x62, 0xf7, 0xf7, 0x75, 0x8b, 0xf3, 0x73, 0xcf, 0xd9, 0x62,
+ 0xf3, 0x8b, 0x65, 0x8a, 0x93, 0xe6, 0x34, 0x7b, 0x45, 0x57, 0xff, 0xf6,
+ 0x0f, 0xf2, 0x1c, 0x67, 0x89, 0x81, 0xce, 0x48, 0x12, 0x2d, 0x19, 0x2a,
+ 0xdd, 0xc6, 0x45, 0x90, 0xd7, 0x73, 0xfd, 0x17, 0x1c, 0x8b, 0xea, 0x0c,
+ 0xc8, 0x44, 0x3e, 0x84, 0x64, 0x71, 0x7d, 0xff, 0xc7, 0x68, 0x46, 0x66,
+ 0xb7, 0x66, 0xdd, 0x52, 0x31, 0x17, 0xf7, 0xe4, 0xba, 0x89, 0x96, 0x2f,
+ 0xf9, 0x98, 0xb3, 0xcf, 0xd0, 0x4b, 0x17, 0xf1, 0xf9, 0xc7, 0xc0, 0x96,
+ 0x2f, 0xe7, 0x8e, 0x70, 0x60, 0xd6, 0x2a, 0x4f, 0x7d, 0x8b, 0xef, 0xff,
+ 0xc4, 0xc0, 0x3b, 0x99, 0x9f, 0x79, 0x83, 0x41, 0x62, 0xfb, 0x37, 0x98,
+ 0xc9, 0x4c, 0xec, 0xe5, 0xff, 0x84, 0xc7, 0x88, 0x2a, 0x31, 0x3e, 0xdf,
+ 0xc7, 0x23, 0x7f, 0xbe, 0xc7, 0x8c, 0x61, 0x0d, 0x62, 0xc3, 0x58, 0xbc,
+ 0xe5, 0xb2, 0xc5, 0xfb, 0x5b, 0xb3, 0x6e, 0xa9, 0x2a, 0x4b, 0x62, 0xc5,
+ 0x6c, 0x7e, 0xe3, 0x12, 0xc1, 0xd3, 0x4d, 0xef, 0xfb, 0x5a, 0x72, 0x2c,
+ 0x16, 0xeb, 0x17, 0xfe, 0x13, 0x6a, 0x05, 0x81, 0x30, 0x16, 0x2f, 0xf7,
+ 0xc3, 0x1c, 0xfa, 0x46, 0xb1, 0x7f, 0xf3, 0x73, 0x4e, 0x17, 0xbe, 0xfa,
+ 0x82, 0xc5, 0xff, 0x69, 0xbf, 0xd4, 0x33, 0xd1, 0x92, 0x8f, 0x31, 0x9c,
+ 0xe1, 0xff, 0xcd, 0x6a, 0x31, 0x39, 0xd6, 0x8c, 0xc2, 0xff, 0xd1, 0x9f,
+ 0x93, 0xe0, 0xe4, 0xbc, 0xb1, 0x7b, 0xcf, 0xb2, 0xc5, 0xff, 0x9a, 0x11,
+ 0x99, 0xad, 0xd9, 0xb7, 0x54, 0x8e, 0x85, 0xf9, 0xfa, 0x01, 0xe5, 0x62,
+ 0xe2, 0xf2, 0xc5, 0x6c, 0x78, 0x0c, 0x53, 0x7c, 0x2e, 0x38, 0x16, 0x2f,
+ 0x3f, 0x41, 0x2c, 0x50, 0x0f, 0x0b, 0x84, 0x77, 0xee, 0x67, 0xcb, 0x16,
+ 0x2f, 0xbc, 0xf0, 0x75, 0x8a, 0x35, 0x37, 0xd3, 0x8f, 0x34, 0x24, 0x00,
+ 0xc9, 0xe2, 0x20, 0xc9, 0xef, 0x0b, 0xa8, 0x2c, 0x5f, 0x3e, 0x6b, 0xb2,
+ 0xc5, 0xe2, 0xf7, 0x16, 0x2f, 0xc5, 0xe2, 0x16, 0xcb, 0x14, 0xc7, 0x8c,
+ 0x21, 0xdb, 0xed, 0x8a, 0x76, 0x58, 0xbf, 0x61, 0x6c, 0xc3, 0x58, 0xbe,
+ 0x3c, 0x9b, 0x19, 0x28, 0xf6, 0x8f, 0x1f, 0x3b, 0x50, 0x88, 0x7b, 0x12,
+ 0x5f, 0xf8, 0x02, 0xe4, 0x60, 0xc2, 0x62, 0x82, 0xc5, 0x46, 0x2a, 0x01,
+ 0x78, 0xd5, 0x00, 0xd3, 0x7f, 0xf9, 0xf4, 0xdd, 0x7d, 0x9f, 0xae, 0x49,
+ 0xab, 0x17, 0xf9, 0xdb, 0x53, 0x06, 0xec, 0xb1, 0x7c, 0xe4, 0x07, 0x58,
+ 0xbf, 0x45, 0x31, 0x4f, 0x16, 0x2f, 0xe0, 0xb1, 0xfb, 0x61, 0x2c, 0x53,
+ 0x9e, 0xcf, 0x0a, 0xaf, 0x3f, 0xe5, 0x62, 0x30, 0xd0, 0xdf, 0xfc, 0x2e,
+ 0x7a, 0x7a, 0x8c, 0x14, 0x4e, 0x75, 0x8a, 0x82, 0x62, 0xa7, 0x84, 0xdf,
+ 0xcb, 0xef, 0xf6, 0xa0, 0x1c, 0x33, 0xec, 0xb1, 0x4b, 0x14, 0xe7, 0x83,
+ 0xc3, 0x5b, 0x69, 0x62, 0xbe, 0x6c, 0xd8, 0x86, 0xfd, 0xad, 0xd9, 0xb7,
+ 0x54, 0x8e, 0xe5, 0xff, 0xfd, 0x27, 0x16, 0xa2, 0x93, 0x98, 0x7c, 0xf7,
+ 0x1f, 0x8b, 0x17, 0x9a, 0x11, 0x98, 0x89, 0x5f, 0x1b, 0xdf, 0x9f, 0xb6,
+ 0xa6, 0x0b, 0x17, 0xef, 0x09, 0x8e, 0xe9, 0x17, 0x1e, 0x39, 0x62, 0xfe,
+ 0xc7, 0x1b, 0x31, 0xab, 0x17, 0xfe, 0x29, 0xf6, 0x73, 0x33, 0xa8, 0x2c,
+ 0x5f, 0xff, 0x8b, 0x58, 0x16, 0x47, 0xcf, 0xe5, 0xc8, 0x72, 0xb1, 0x50,
+ 0x5c, 0x58, 0x1a, 0x66, 0x46, 0x93, 0xbc, 0x2a, 0x8f, 0x0b, 0x5f, 0x9b,
+ 0x31, 0x51, 0x14, 0x70, 0x6f, 0xc5, 0xa1, 0x9f, 0x5f, 0xf0, 0xe6, 0x13,
+ 0x18, 0x17, 0x00, 0xb1, 0x7e, 0xe1, 0x48, 0x38, 0xb1, 0x78, 0xb0, 0x6b,
+ 0x17, 0xc2, 0xfb, 0xe9, 0x62, 0xe9, 0x8c, 0x93, 0xe7, 0x01, 0x44, 0x70,
+ 0xe5, 0x46, 0x27, 0x1d, 0x90, 0xaa, 0x28, 0x52, 0xdf, 0xfe, 0x90, 0x1d,
+ 0xa1, 0x19, 0xc1, 0x96, 0x7d, 0x62, 0xff, 0xbd, 0xc7, 0x3b, 0xf8, 0x0c,
+ 0xb1, 0x77, 0xa5, 0x62, 0xf6, 0xd3, 0xba, 0xc5, 0xdc, 0x8c, 0x93, 0xef,
+ 0xdc, 0xe5, 0xc5, 0xef, 0xff, 0x46, 0x1d, 0xa1, 0x19, 0x9a, 0xdd, 0x9b,
+ 0x75, 0x49, 0x0a, 0x5d, 0x3a, 0x58, 0xbd, 0x39, 0xa5, 0x8b, 0xf0, 0x27,
+ 0x6c, 0x09, 0x62, 0xff, 0xcd, 0xe8, 0x61, 0x38, 0xe3, 0x39, 0xb1, 0xee,
+ 0xc4, 0x2e, 0x01, 0xcb, 0xe2, 0x6d, 0x76, 0x58, 0xb9, 0x82, 0x58, 0xb6,
+ 0xcb, 0x14, 0x73, 0x56, 0x43, 0x17, 0xfe, 0xfb, 0x9d, 0xa1, 0x87, 0x6e,
+ 0x96, 0x2d, 0x19, 0x28, 0xae, 0xd9, 0x3f, 0x72, 0x0b, 0xb6, 0x75, 0x8b,
+ 0xff, 0xdf, 0x17, 0xa4, 0xb3, 0x63, 0x45, 0x31, 0x2c, 0x5f, 0xc2, 0x39,
+ 0xda, 0x11, 0x92, 0x7c, 0xbb, 0x8c, 0x5f, 0xff, 0xf8, 0xb3, 0xb3, 0xfc,
+ 0x51, 0x9b, 0xfd, 0xfe, 0x53, 0x9a, 0xc3, 0xac, 0x54, 0x13, 0x57, 0xfc,
+ 0x27, 0xf8, 0x91, 0x7d, 0xe6, 0xeb, 0x8b, 0x17, 0xe1, 0x75, 0xe7, 0xdd,
+ 0x62, 0xf8, 0xb0, 0x2f, 0xac, 0x5f, 0xd0, 0x6d, 0x6d, 0xf1, 0x2c, 0x5f,
+ 0xb9, 0x20, 0x0f, 0x65, 0x8b, 0x64, 0x47, 0xb7, 0xc3, 0x0b, 0xed, 0xc9,
+ 0xa0, 0xb1, 0x73, 0x47, 0x2c, 0x5f, 0x39, 0x49, 0xd6, 0x2f, 0xf0, 0xe4,
+ 0x8b, 0x33, 0x65, 0x8b, 0xe0, 0x63, 0x12, 0xc5, 0xfe, 0xf1, 0x48, 0x0e,
+ 0xd0, 0x58, 0xa9, 0x44, 0x36, 0x19, 0x39, 0x0d, 0xfe, 0xc2, 0x9c, 0xd4,
+ 0xec, 0xb1, 0x7f, 0xf7, 0x67, 0xf4, 0xfc, 0xb3, 0xda, 0x95, 0x8b, 0xf3,
+ 0x68, 0x11, 0xd8, 0xb1, 0x79, 0xc2, 0xf2, 0xc5, 0x62, 0x23, 0x9d, 0x17,
+ 0x85, 0x77, 0xfc, 0x78, 0xa0, 0xda, 0xdb, 0xe2, 0x58, 0xbd, 0x20, 0x8c,
+ 0x95, 0x66, 0x3b, 0x12, 0x40, 0xac, 0x6f, 0xce, 0x50, 0x72, 0x36, 0x1a,
+ 0x28, 0x53, 0xf0, 0xb7, 0xd0, 0xc0, 0x0c, 0xba, 0x9d, 0x70, 0x74, 0xa5,
+ 0xb3, 0xdf, 0xff, 0x85, 0xbc, 0x63, 0x7b, 0xf8, 0x79, 0xd1, 0x48, 0x16,
+ 0x2f, 0xf8, 0xed, 0xcc, 0x0a, 0x48, 0x6b, 0x17, 0xfe, 0x68, 0x46, 0x66,
+ 0xb7, 0x66, 0xdd, 0x52, 0x49, 0x17, 0xf7, 0xcb, 0x07, 0xf1, 0x2c, 0x5d,
+ 0x83, 0x58, 0xac, 0x3c, 0x5f, 0x97, 0x5e, 0x92, 0x1a, 0xc5, 0xa3, 0x36,
+ 0x4d, 0x93, 0x16, 0x4e, 0x73, 0xe8, 0x4a, 0x84, 0x43, 0x7f, 0xff, 0x0b,
+ 0x93, 0x85, 0xe2, 0x63, 0x72, 0x29, 0x21, 0xac, 0x5f, 0xc5, 0x9c, 0x0f,
+ 0x22, 0x58, 0xb6, 0x12, 0x22, 0x7b, 0x2d, 0x5c, 0x72, 0x58, 0xbf, 0xfa,
+ 0x2f, 0xb1, 0xfd, 0xf9, 0xf0, 0x8e, 0xb1, 0x7d, 0x85, 0x3b, 0x2c, 0x56,
+ 0x1f, 0x4e, 0x91, 0xef, 0x67, 0x23, 0x09, 0x19, 0x5c, 0x29, 0x0e, 0x10,
+ 0x15, 0x2d, 0xf9, 0x16, 0xd3, 0x81, 0x30, 0x95, 0x31, 0x85, 0xbb, 0xca,
+ 0x4b, 0x88, 0xb3, 0x52, 0xef, 0xcf, 0x3c, 0x41, 0xf3, 0xc6, 0x85, 0xe0,
+ 0x0f, 0x4a, 0x17, 0x9e, 0x9e, 0x88, 0x14, 0x71, 0xf1, 0xd1, 0xd6, 0xdd,
+ 0x1b, 0xf7, 0xd5, 0x62, 0xfb, 0x76, 0x6d, 0xd5, 0x21, 0x21, 0x7f, 0xfe,
+ 0x7d, 0x7d, 0x8c, 0x8b, 0xf3, 0xb7, 0x7f, 0xa9, 0x8e, 0x58, 0xad, 0x22,
+ 0x4b, 0xe6, 0x37, 0xff, 0xfb, 0xf3, 0xb7, 0x7f, 0xa9, 0x8e, 0x8c, 0xd3,
+ 0xc9, 0xf6, 0xc0, 0x96, 0x2f, 0xcf, 0xef, 0xe1, 0xd6, 0x2d, 0x19, 0x1b,
+ 0xa6, 0xe3, 0x90, 0xb7, 0x88, 0x8f, 0xbf, 0x6f, 0xbd, 0xa6, 0xd2, 0xc5,
+ 0xff, 0x9a, 0x11, 0x99, 0xad, 0xd9, 0xb7, 0x54, 0x8b, 0xc5, 0xdd, 0xbe,
+ 0xb1, 0x7c, 0xde, 0x6d, 0x96, 0x2d, 0x18, 0xe8, 0xaa, 0x38, 0xe9, 0x28,
+ 0x47, 0x0d, 0x5f, 0xdd, 0xf5, 0xcd, 0x01, 0x8e, 0xb1, 0x7f, 0xf4, 0xf6,
+ 0x68, 0x9f, 0x5d, 0x42, 0x62, 0x58, 0xbd, 0xde, 0x1c, 0x0b, 0x17, 0xf0,
+ 0xff, 0x8e, 0x46, 0xac, 0x5e, 0x39, 0x4a, 0xc5, 0x70, 0xf2, 0x83, 0x2e,
+ 0xbd, 0xe6, 0x35, 0x62, 0xbb, 0xd3, 0xc1, 0x62, 0x3b, 0xa2, 0x25, 0x8b,
+ 0xff, 0x77, 0xc6, 0x71, 0x8a, 0x4a, 0x60, 0xb1, 0x7f, 0xc6, 0x4f, 0x9f,
+ 0x53, 0xda, 0x25, 0x8b, 0xff, 0xdf, 0x9e, 0x06, 0x39, 0xd4, 0x58, 0x40,
+ 0x58, 0xbe, 0xd0, 0xbd, 0xc5, 0x8b, 0xf8, 0x6e, 0x6b, 0x10, 0x16, 0x2f,
+ 0xed, 0x30, 0x52, 0x39, 0x58, 0xbc, 0x1e, 0xdd, 0xcb, 0x17, 0xe9, 0x20,
+ 0x0c, 0xeb, 0x17, 0xfb, 0x0e, 0x64, 0x69, 0xde, 0x1c, 0x0b, 0x17, 0xc0,
+ 0x3b, 0xf1, 0x62, 0x86, 0x7c, 0x7a, 0x40, 0xb8, 0x07, 0x58, 0xbd, 0x25,
+ 0xd2, 0xc5, 0xfb, 0xc1, 0x9c, 0xa5, 0x62, 0xcf, 0xa3, 0xde, 0xf8, 0xc1,
+ 0x0e, 0xdf, 0xfe, 0xff, 0x69, 0x20, 0x47, 0xe0, 0xf3, 0x5d, 0x2c, 0x5f,
+ 0xe7, 0xd3, 0x0d, 0xc8, 0xd5, 0x8b, 0xa7, 0xcb, 0x17, 0xfc, 0xdb, 0x6a,
+ 0x7a, 0x83, 0x9d, 0x62, 0xff, 0xf0, 0x86, 0xfa, 0x0e, 0x2e, 0xe1, 0x31,
+ 0x44, 0xb1, 0x7b, 0x53, 0x05, 0x8b, 0x8a, 0x25, 0x8a, 0xc3, 0x6a, 0x21,
+ 0xda, 0x82, 0x75, 0xce, 0x67, 0xf5, 0x00, 0x19, 0x90, 0xbf, 0x0e, 0xfd,
+ 0x08, 0x6b, 0xf8, 0x1f, 0x9d, 0x39, 0xd6, 0x2f, 0xcf, 0xdd, 0xdc, 0xc7,
+ 0x58, 0xb6, 0x96, 0x2f, 0xfb, 0x93, 0xd9, 0xbf, 0x3d, 0x44, 0xb1, 0x58,
+ 0x79, 0xf1, 0x09, 0x54, 0xa3, 0x37, 0x45, 0xcc, 0xfb, 0x7e, 0x8a, 0x7a,
+ 0xf3, 0xac, 0x5e, 0xf0, 0x7b, 0x2c, 0x54, 0x9e, 0x56, 0x15, 0x5f, 0xf9,
+ 0xb8, 0x1f, 0x62, 0x9f, 0x37, 0xd6, 0x2f, 0xf8, 0xa6, 0x2d, 0x34, 0x4d,
+ 0xc5, 0x8b, 0x83, 0x3a, 0xc5, 0x41, 0x12, 0x9d, 0x90, 0x7b, 0x8e, 0xae,
+ 0xf8, 0x16, 0x29, 0xcf, 0x35, 0x8d, 0x6f, 0xd3, 0x17, 0x04, 0x4b, 0x17,
+ 0xd1, 0x70, 0x44, 0xb1, 0x73, 0x1c, 0xc3, 0xcd, 0x92, 0x9b, 0xed, 0xb3,
+ 0x87, 0x58, 0xbe, 0xeb, 0x93, 0xf5, 0x8a, 0x19, 0xfa, 0xe1, 0x6b, 0x92,
+ 0x5f, 0xb5, 0x3e, 0x7e, 0xcb, 0x17, 0xed, 0x9b, 0x8c, 0x05, 0x8a, 0x73,
+ 0xd3, 0x62, 0xab, 0xff, 0xa2, 0x30, 0x32, 0x9e, 0xcd, 0xda, 0x62, 0x58,
+ 0xa5, 0x8b, 0x44, 0xb1, 0x7f, 0xe6, 0xd9, 0xbb, 0x72, 0x49, 0xbb, 0x96,
+ 0x2f, 0xfd, 0xee, 0x67, 0x24, 0xbd, 0x80, 0x58, 0xbe, 0xf6, 0x6a, 0x25,
+ 0x8b, 0xde, 0x6e, 0xcb, 0x15, 0x87, 0x86, 0xc4, 0x95, 0x28, 0xa1, 0x84,
+ 0x20, 0x6f, 0x1f, 0x3b, 0x96, 0x2e, 0xed, 0x8b, 0x17, 0xa3, 0xd8, 0xd5,
+ 0x89, 0x2e, 0x6f, 0xcd, 0xc9, 0xed, 0x8b, 0x14, 0x34, 0xe7, 0x22, 0x87,
+ 0x26, 0x89, 0xfc, 0x73, 0xd8, 0xbe, 0xa5, 0x52, 0xd6, 0x26, 0x68, 0x31,
+ 0xa3, 0xaf, 0xbb, 0x52, 0xb1, 0x5d, 0xe3, 0x2b, 0x22, 0x07, 0xa3, 0x4c,
+ 0xc2, 0x43, 0x4b, 0xb7, 0x2e, 0xe8, 0x8d, 0xe1, 0x17, 0x14, 0xa2, 0xed,
+ 0x46, 0x6a, 0x77, 0x8f, 0xc6, 0x02, 0x50, 0xe2, 0xf4, 0x20, 0x3b, 0x4a,
+ 0x7a, 0xee, 0x42, 0xbb, 0x09, 0x62, 0xfc, 0x14, 0xc7, 0xc9, 0xd6, 0x2f,
+ 0xe3, 0x39, 0xfc, 0x7f, 0x2c, 0x5f, 0xfb, 0xae, 0x73, 0x3e, 0xfc, 0x16,
+ 0xcb, 0x14, 0x34, 0x59, 0xe0, 0xb3, 0x96, 0x08, 0xbe, 0xdd, 0x2c, 0x5f,
+ 0x07, 0xd9, 0xfb, 0x96, 0x2f, 0x76, 0x7e, 0xe5, 0x8b, 0xf7, 0xf3, 0xb8,
+ 0x44, 0x61, 0xe5, 0x86, 0x53, 0x7f, 0x9b, 0xdb, 0x0a, 0x29, 0x8f, 0x58,
+ 0xbf, 0xfb, 0x0e, 0x1f, 0x66, 0xf6, 0x1e, 0x78, 0xb1, 0x40, 0x44, 0x07,
+ 0x0e, 0x6f, 0xe9, 0x38, 0xff, 0x3c, 0x58, 0xba, 0x60, 0xb1, 0x43, 0x4e,
+ 0x27, 0x17, 0x9e, 0x18, 0x64, 0x47, 0xc2, 0xeb, 0xfd, 0xe7, 0x6d, 0x02,
+ 0x3b, 0x16, 0x2f, 0xe2, 0x17, 0xa2, 0x93, 0x56, 0x2f, 0x77, 0xef, 0xa5,
+ 0x8a, 0x63, 0xd2, 0x11, 0x85, 0xff, 0xd8, 0xfd, 0x73, 0xd3, 0xb1, 0xda,
+ 0x0b, 0x17, 0xe9, 0x03, 0xf5, 0xc5, 0x8a, 0xc4, 0xc6, 0x1e, 0x11, 0x1a,
+ 0x21, 0x24, 0x6b, 0xfc, 0x2f, 0x7c, 0xa7, 0x34, 0xb1, 0x7e, 0x2c, 0xd8,
+ 0x3e, 0xcb, 0x17, 0xd9, 0xb0, 0x7d, 0x96, 0x2f, 0xa7, 0xa1, 0xb1, 0x87,
+ 0xa6, 0x45, 0x97, 0xff, 0xf4, 0x3e, 0x1f, 0x5e, 0xfb, 0xb0, 0x23, 0xa7,
+ 0x58, 0x4b, 0x14, 0x34, 0x4c, 0xb9, 0xcd, 0xff, 0xd2, 0x5e, 0xee, 0x29,
+ 0x0b, 0xa8, 0x71, 0x62, 0xee, 0xf6, 0x3d, 0x62, 0xff, 0xf9, 0xf4, 0x67,
+ 0xe5, 0xfd, 0xc1, 0x6e, 0x29, 0x58, 0xbe, 0x7d, 0x81, 0x1e, 0xb1, 0x6e,
+ 0x96, 0x2f, 0x33, 0x6e, 0xa9, 0x25, 0xca, 0x58, 0xbf, 0xe7, 0xed, 0xfd,
+ 0xdf, 0x98, 0x35, 0x8a, 0xc4, 0x42, 0xee, 0x27, 0x11, 0x56, 0x83, 0x2f,
+ 0xef, 0x14, 0xf7, 0x31, 0xd6, 0x2f, 0xc5, 0x3d, 0xcc, 0x75, 0x8b, 0xa7,
+ 0x73, 0x0f, 0x6b, 0xc6, 0x17, 0xef, 0x1b, 0x25, 0x05, 0x8b, 0xde, 0x9d,
+ 0x2c, 0x51, 0xcf, 0x18, 0x8a, 0x6f, 0xfb, 0x35, 0x1f, 0x83, 0xcd, 0x74,
+ 0xb1, 0x4e, 0x7b, 0xdd, 0x88, 0x6f, 0xfd, 0x30, 0xfb, 0x3f, 0x5c, 0x93,
+ 0x56, 0x2f, 0xfa, 0x79, 0x27, 0x0f, 0x69, 0xd9, 0x62, 0xb6, 0x5c, 0xb2,
+ 0x84, 0x63, 0xe3, 0x22, 0xc4, 0x93, 0x48, 0x22, 0x52, 0xd4, 0x2b, 0x0f,
+ 0x09, 0x8f, 0xc3, 0x4c, 0x88, 0xfb, 0x90, 0x2f, 0xff, 0xcf, 0xed, 0x0b,
+ 0x9f, 0x68, 0x19, 0xc1, 0xf9, 0xd6, 0x2f, 0xff, 0x6b, 0x63, 0x3b, 0x0b,
+ 0xf2, 0xe7, 0x91, 0xac, 0x57, 0xd1, 0x4e, 0xcb, 0x17, 0x6b, 0xcb, 0x17,
+ 0xc3, 0xf8, 0x8e, 0xb1, 0x52, 0x6f, 0x04, 0x31, 0x7f, 0x0f, 0xa9, 0xd3,
+ 0xf4, 0xb1, 0x7d, 0xed, 0xb0, 0x25, 0x8a, 0x81, 0xfa, 0xb9, 0x01, 0x18,
+ 0x5f, 0xff, 0xa2, 0x6d, 0x6d, 0xe7, 0x8f, 0xcd, 0x9a, 0x29, 0x8f, 0x58,
+ 0xbe, 0x37, 0x59, 0xc5, 0x8a, 0x94, 0x41, 0xba, 0xfd, 0xff, 0xa4, 0xa7,
+ 0xe6, 0x08, 0x85, 0xba, 0xc5, 0xe8, 0x8f, 0x8b, 0x17, 0x08, 0x25, 0x8b,
+ 0xc2, 0x6e, 0x2c, 0x5f, 0xff, 0x68, 0x73, 0xf6, 0x8a, 0x63, 0xfd, 0x9d,
+ 0xb8, 0xb1, 0x78, 0xe5, 0x12, 0xc5, 0xe1, 0x34, 0x4b, 0x17, 0x10, 0xd6,
+ 0x2a, 0x51, 0x53, 0x8a, 0xd1, 0x0f, 0x30, 0xf5, 0xfa, 0x40, 0xdd, 0x71,
+ 0x62, 0xf7, 0x58, 0x05, 0x8b, 0x01, 0x62, 0xe8, 0x81, 0x26, 0xc3, 0xa1,
+ 0xeb, 0xd1, 0xcc, 0x4b, 0x15, 0x27, 0x9b, 0xe2, 0xeb, 0xc4, 0xe0, 0x58,
+ 0xbf, 0xe1, 0xb1, 0x01, 0x86, 0x28, 0xf5, 0x8b, 0xd9, 0xee, 0x2c, 0x54,
+ 0x9f, 0xae, 0x0e, 0x70, 0xf2, 0xff, 0xe2, 0x1f, 0x74, 0x59, 0x07, 0xd4,
+ 0xec, 0xb1, 0x7e, 0x97, 0x83, 0xf6, 0x58, 0xb9, 0x8d, 0x58, 0xbf, 0xfa,
+ 0x48, 0xd3, 0x27, 0x6f, 0x4f, 0x6e, 0x2c, 0x54, 0x79, 0xf0, 0xfc, 0x62,
+ 0xbe, 0x8a, 0xff, 0x42, 0x2a, 0xa5, 0x32, 0x06, 0x87, 0xc5, 0x41, 0x71,
+ 0x24, 0x64, 0x38, 0x81, 0x1e, 0x3d, 0x10, 0xcf, 0xe1, 0x8c, 0x03, 0xb2,
+ 0x85, 0x37, 0xa1, 0x2d, 0xda, 0x34, 0xdb, 0xed, 0x84, 0x37, 0x58, 0xbf,
+ 0xe1, 0xb1, 0x00, 0x33, 0x94, 0xac, 0x54, 0x9e, 0xee, 0x12, 0x5f, 0x31,
+ 0x0f, 0xb9, 0x62, 0xff, 0x16, 0x40, 0xcf, 0xcc, 0x7a, 0xc5, 0x47, 0x9e,
+ 0xe1, 0xc9, 0x69, 0x62, 0xfd, 0xcf, 0x6a, 0x78, 0xb1, 0x69, 0xe8, 0xda,
+ 0xf8, 0x32, 0xff, 0x81, 0xcd, 0x4f, 0x50, 0x73, 0xac, 0x5e, 0xf3, 0x76,
+ 0x58, 0xbf, 0x6c, 0x28, 0xa6, 0x3d, 0x62, 0xf8, 0x51, 0x4c, 0x7a, 0xc5,
+ 0xcd, 0xb1, 0x87, 0xab, 0xb1, 0x75, 0x4a, 0x37, 0xd8, 0xec, 0x4e, 0x97,
+ 0xf0, 0x39, 0x27, 0x6f, 0x2c, 0x5f, 0xe9, 0x8b, 0x92, 0x76, 0xf2, 0xc5,
+ 0xa5, 0xcf, 0x8b, 0xb1, 0x75, 0xff, 0x3f, 0x22, 0x72, 0xf4, 0x81, 0x62,
+ 0xfc, 0x0e, 0x31, 0x01, 0x62, 0xff, 0xe1, 0xb7, 0x47, 0x11, 0x7b, 0xf9,
+ 0x05, 0x8a, 0x93, 0xee, 0x72, 0x8b, 0xff, 0x8b, 0xdd, 0xa7, 0x5c, 0x62,
+ 0x98, 0xf5, 0x8b, 0xf9, 0x9f, 0x63, 0x0f, 0x8b, 0x15, 0x04, 0xfd, 0xb5,
+ 0x09, 0x03, 0x94, 0x7e, 0x14, 0xfc, 0x20, 0xf2, 0x45, 0xfe, 0x98, 0xfe,
+ 0x49, 0xdb, 0xcb, 0x17, 0x31, 0x2c, 0x5f, 0xf4, 0x80, 0xcf, 0xc9, 0xd8,
+ 0x96, 0x2b, 0xa3, 0xcf, 0xec, 0x2d, 0x7f, 0xfd, 0x83, 0x0e, 0x2e, 0x7b,
+ 0xf8, 0x31, 0x7b, 0x8b, 0x17, 0xf4, 0x59, 0x1e, 0xc4, 0x05, 0x8a, 0x82,
+ 0x65, 0xfa, 0x84, 0x2f, 0xc9, 0x7c, 0xa9, 0x7f, 0x48, 0x4f, 0xf1, 0x47,
+ 0xac, 0x5d, 0xdd, 0xf5, 0x8b, 0xfb, 0xa8, 0x71, 0x8b, 0xa5, 0x8a, 0x95,
+ 0xda, 0x78, 0x2d, 0x64, 0xaf, 0xc7, 0x8e, 0x47, 0x48, 0x67, 0x32, 0x0c,
+ 0x6e, 0xe1, 0x44, 0xb1, 0x7f, 0xd1, 0x19, 0xa9, 0xea, 0x0e, 0x75, 0x8a,
+ 0x88, 0xf5, 0x88, 0x66, 0xff, 0xf7, 0x69, 0x2f, 0x7b, 0xf8, 0x31, 0x7b,
+ 0x8b, 0x17, 0xb1, 0xce, 0xb1, 0x7f, 0x08, 0x0e, 0x4f, 0x1e, 0xb1, 0x7f,
+ 0xff, 0xd1, 0xd9, 0xe0, 0xfb, 0x37, 0x83, 0xd9, 0xfe, 0x58, 0x36, 0x3a,
+ 0xc5, 0x0d, 0x13, 0xde, 0x30, 0xba, 0x4e, 0xb1, 0x7c, 0x0c, 0xed, 0x2b,
+ 0x15, 0x29, 0xc3, 0xe1, 0x16, 0xe9, 0xaf, 0x0b, 0xad, 0x11, 0xb0, 0xbd,
+ 0xf8, 0xa2, 0xf3, 0x9a, 0xb1, 0x74, 0xc1, 0x62, 0xf8, 0xa2, 0x73, 0xac,
+ 0x5f, 0x9c, 0x62, 0x2c, 0x58, 0xbf, 0x48, 0xfe, 0xdd, 0x2c, 0x5f, 0xf7,
+ 0xe1, 0x9e, 0x60, 0x07, 0xd2, 0xc5, 0xf7, 0xbf, 0x90, 0x30, 0xf9, 0x5c,
+ 0xa6, 0xa2, 0x46, 0x29, 0x42, 0x32, 0xa5, 0x35, 0x17, 0x2a, 0x61, 0x71,
+ 0x43, 0xa2, 0xfe, 0xd4, 0x58, 0x52, 0x75, 0x8b, 0x76, 0x58, 0xac, 0x3c,
+ 0x27, 0x2e, 0xba, 0x62, 0x58, 0xbf, 0xfc, 0x2d, 0xb4, 0xe7, 0x7f, 0x72,
+ 0x75, 0xd9, 0x62, 0xa0, 0x88, 0x6d, 0x10, 0x10, 0xc5, 0xf8, 0x13, 0xbe,
+ 0x1d, 0x62, 0xff, 0x66, 0xdc, 0x98, 0x85, 0xa5, 0x8b, 0xec, 0x67, 0xd9,
+ 0x62, 0xe9, 0xf2, 0xc5, 0x1c, 0xdc, 0x91, 0x15, 0x3a, 0x39, 0xf4, 0x5e,
+ 0x45, 0x3c, 0x6f, 0xba, 0x18, 0xb1, 0x7e, 0xe1, 0xba, 0x60, 0x96, 0x2e,
+ 0xce, 0x96, 0x2f, 0x14, 0x9d, 0x62, 0x86, 0x7b, 0xfb, 0x95, 0xe8, 0x62,
+ 0x96, 0x2f, 0x47, 0xe4, 0x16, 0x2f, 0xf4, 0x80, 0xed, 0x00, 0xce, 0xb1,
+ 0x7f, 0x9f, 0xb1, 0x91, 0x14, 0x8d, 0x62, 0xbe, 0x7d, 0x9c, 0x35, 0xae,
+ 0x91, 0x5c, 0xf0, 0x8c, 0xbf, 0xcd, 0xa8, 0xb3, 0xdd, 0xdd, 0x96, 0x2e,
+ 0x07, 0x16, 0x2f, 0x0f, 0x8e, 0xb1, 0x52, 0x6d, 0x58, 0x62, 0xa5, 0x52,
+ 0x88, 0xce, 0xf1, 0xdb, 0xe6, 0x0d, 0x0b, 0xa1, 0x14, 0x04, 0xdf, 0x7c,
+ 0xdf, 0x6d, 0x96, 0x2f, 0xdf, 0x11, 0xb8, 0x4b, 0x17, 0x82, 0x68, 0x2c,
+ 0x5f, 0xa2, 0x60, 0x36, 0xeb, 0x17, 0xda, 0xf1, 0x4a, 0xc5, 0x61, 0xe6,
+ 0x31, 0x55, 0xfe, 0x08, 0x9b, 0xd0, 0x61, 0xac, 0x5d, 0x1c, 0xeb, 0x16,
+ 0x8f, 0x58, 0xb6, 0xcb, 0x14, 0x23, 0x50, 0x18, 0xad, 0xf0, 0x7b, 0x4f,
+ 0xd6, 0x28, 0x8f, 0x1f, 0xc4, 0x57, 0xec, 0xf7, 0x9c, 0xd5, 0x8b, 0xfe,
+ 0x9f, 0xf1, 0xbd, 0x3a, 0xee, 0x58, 0xbf, 0xf1, 0xd8, 0x61, 0xc5, 0x09,
+ 0x2e, 0x96, 0x28, 0x67, 0xfc, 0xe7, 0x97, 0xf0, 0xbf, 0x3a, 0xc0, 0x2c,
+ 0x5e, 0xed, 0x3a, 0x58, 0xbe, 0xd0, 0x03, 0xec, 0xb1, 0x79, 0xc2, 0xf2,
+ 0xc5, 0x41, 0x12, 0x4e, 0x5d, 0xf1, 0xfe, 0x13, 0xd6, 0xca, 0xd2, 0x86,
+ 0x47, 0x85, 0x3b, 0xb5, 0x74, 0x40, 0xe6, 0x91, 0x42, 0x27, 0x44, 0x3f,
+ 0x85, 0x3f, 0xa1, 0x67, 0x7f, 0x8b, 0xd9, 0xc7, 0x6f, 0xac, 0x5f, 0x72,
+ 0x1c, 0x65, 0x8b, 0xfe, 0x03, 0xff, 0x34, 0xd1, 0x71, 0x62, 0xf1, 0x8d,
+ 0xf5, 0x8b, 0xff, 0xe8, 0x14, 0xec, 0x1c, 0x5c, 0xfe, 0x77, 0x68, 0x0b,
+ 0x17, 0xa0, 0x3e, 0xcb, 0x15, 0x27, 0xee, 0xca, 0xf7, 0xf1, 0x87, 0xcf,
+ 0x37, 0x96, 0x2f, 0xef, 0xb8, 0xdf, 0x5b, 0xac, 0x52, 0xc5, 0xf3, 0x17,
+ 0x50, 0x58, 0xad, 0xcd, 0x7f, 0xc3, 0x2d, 0xcc, 0x45, 0x7e, 0xe5, 0xec,
+ 0xbd, 0x7b, 0xa8, 0xb8, 0xb1, 0x5d, 0x1e, 0xab, 0x1a, 0xde, 0x97, 0x1a,
+ 0xc5, 0xfd, 0xf7, 0xf1, 0x49, 0xd6, 0x2f, 0xf8, 0xb7, 0x6f, 0xf5, 0x0c,
+ 0xf2, 0xc5, 0x44, 0x7d, 0x0c, 0x5b, 0x52, 0xac, 0x40, 0x66, 0x5d, 0x11,
+ 0xb9, 0xd1, 0xe1, 0x2a, 0xd1, 0x92, 0x70, 0x88, 0x50, 0x84, 0xbf, 0xd8,
+ 0x14, 0x1f, 0x82, 0x3a, 0xc5, 0xdd, 0xb8, 0xb1, 0x7f, 0x0b, 0x93, 0x10,
+ 0xb4, 0xb1, 0x7e, 0xcd, 0xb3, 0xfc, 0x58, 0xa9, 0x3f, 0x3f, 0x8d, 0x11,
+ 0x85, 0xff, 0xe8, 0x09, 0xbb, 0x3f, 0xf8, 0x28, 0xe1, 0x69, 0x62, 0xff,
+ 0x02, 0x40, 0xc4, 0x2c, 0x58, 0xbe, 0x1f, 0xe4, 0xd5, 0x8b, 0xe3, 0x8a,
+ 0x2d, 0x2c, 0x5d, 0xae, 0x2c, 0x5f, 0xfb, 0x38, 0x67, 0xe5, 0xc8, 0x5b,
+ 0x2c, 0x56, 0x1e, 0xc1, 0x0c, 0x56, 0xe9, 0xb8, 0xf4, 0x5a, 0xea, 0x3a,
+ 0x32, 0x39, 0x27, 0x67, 0xdb, 0xfe, 0x04, 0x80, 0x3e, 0xd2, 0x5d, 0xcb,
+ 0x17, 0xff, 0xed, 0xa7, 0xd3, 0xf7, 0xf4, 0x1f, 0x5b, 0xfe, 0x56, 0x2e,
+ 0x93, 0xac, 0x54, 0xab, 0x21, 0xc9, 0x43, 0x2e, 0xb6, 0xc7, 0xe2, 0x57,
+ 0xbb, 0x61, 0xac, 0x5f, 0xf4, 0xc5, 0xe7, 0x1e, 0x14, 0x4b, 0x17, 0xff,
+ 0xfd, 0xae, 0xb7, 0x7e, 0x8c, 0x35, 0x8c, 0xe7, 0xdb, 0x79, 0x21, 0xac,
+ 0x5f, 0xf3, 0x70, 0x3f, 0x75, 0xbb, 0x9d, 0x62, 0xdf, 0x94, 0x55, 0x89,
+ 0xba, 0xf9, 0xcd, 0x8e, 0xc5, 0x8b, 0xf8, 0x3f, 0x4e, 0xc5, 0xd2, 0xc5,
+ 0xff, 0xf6, 0xff, 0x68, 0x83, 0x8a, 0x0e, 0x58, 0x79, 0x58, 0xbc, 0x4e,
+ 0x75, 0x8a, 0xd2, 0x31, 0x80, 0x4c, 0x46, 0x3e, 0x53, 0xbf, 0xcf, 0xe2,
+ 0xc3, 0x73, 0xeb, 0x17, 0xa3, 0xd8, 0xeb, 0x15, 0xe3, 0xd3, 0xee, 0x33,
+ 0xbb, 0x9c, 0x58, 0xbf, 0xfb, 0xdc, 0x0f, 0x98, 0x42, 0xf4, 0xfd, 0x62,
+ 0xfe, 0x96, 0x2f, 0x61, 0x2c, 0x56, 0x1f, 0x89, 0x23, 0x5f, 0xc6, 0x7a,
+ 0x76, 0x98, 0x96, 0x2f, 0xdc, 0x8f, 0x9d, 0x1a, 0xb1, 0x69, 0x34, 0xf7,
+ 0xba, 0x31, 0xbf, 0x9a, 0x27, 0xd4, 0xec, 0xb1, 0x74, 0xec, 0xb1, 0x5f,
+ 0x3c, 0x7e, 0xe2, 0xfb, 0xf7, 0x71, 0xe7, 0x3c, 0xb1, 0x7f, 0xf0, 0x7e,
+ 0x84, 0x8d, 0x8b, 0x3c, 0x05, 0x8b, 0xef, 0x4e, 0x7d, 0x62, 0xff, 0x3f,
+ 0x6e, 0xa1, 0x9d, 0xd0, 0x58, 0xac, 0x46, 0x66, 0x8a, 0xd9, 0x14, 0x88,
+ 0xae, 0xc3, 0xac, 0x54, 0xae, 0xac, 0xc0, 0x64, 0x70, 0xe5, 0xc8, 0x77,
+ 0x3c, 0x23, 0xf4, 0x4a, 0x78, 0x44, 0xfd, 0xf9, 0x9c, 0x05, 0x0f, 0x1e,
+ 0xc7, 0x57, 0xee, 0xe7, 0x3c, 0xf1, 0x62, 0xfa, 0x7a, 0x9f, 0x2c, 0x5e,
+ 0xcd, 0x71, 0x62, 0xcd, 0x11, 0xe0, 0x76, 0x23, 0xbf, 0x6c, 0x1f, 0x66,
+ 0x82, 0xc5, 0x0d, 0x18, 0x47, 0x6b, 0x22, 0xab, 0xdd, 0xb0, 0x6b, 0x16,
+ 0x09, 0x62, 0xf7, 0x18, 0xeb, 0x17, 0x89, 0xce, 0xb1, 0x6d, 0x96, 0x29,
+ 0x8d, 0x78, 0x63, 0x94, 0x69, 0xf6, 0xfd, 0x32, 0xf4, 0x5c, 0x95, 0x8b,
+ 0xed, 0x02, 0x3b, 0x16, 0x2f, 0xff, 0xa4, 0xa4, 0x06, 0x3f, 0xe1, 0x3e,
+ 0x61, 0xac, 0x51, 0xa8, 0x93, 0x61, 0xee, 0xe2, 0x6b, 0xfc, 0xc6, 0xeb,
+ 0x3b, 0x48, 0x16, 0x2e, 0x8b, 0x16, 0x29, 0x62, 0xfb, 0xdf, 0x68, 0x98,
+ 0xd2, 0x70, 0x62, 0xff, 0xa3, 0xd8, 0x80, 0xe6, 0xb7, 0x4b, 0x15, 0x27,
+ 0xeb, 0x87, 0x17, 0xfe, 0x73, 0x87, 0xf7, 0xf6, 0x76, 0x89, 0x62, 0xfe,
+ 0x07, 0x40, 0xcd, 0x62, 0xc5, 0xfa, 0x5f, 0xcf, 0x05, 0x8b, 0xf6, 0x1a,
+ 0x6b, 0x8d, 0x62, 0xb7, 0x3d, 0x12, 0x27, 0xbf, 0x47, 0x0b, 0xef, 0xa5,
+ 0x8b, 0xe1, 0x7d, 0xf4, 0xb1, 0x46, 0x1e, 0x7c, 0x71, 0x65, 0xe9, 0xcf,
+ 0x2c, 0x5f, 0x72, 0x75, 0x05, 0x8b, 0xf6, 0x6b, 0x42, 0xd9, 0x62, 0xc0,
+ 0x39, 0xf4, 0xf0, 0x73, 0xc4, 0x74, 0x74, 0x62, 0x34, 0x23, 0xea, 0x53,
+ 0xdc, 0xc8, 0x40, 0x3c, 0x66, 0xb7, 0xc3, 0xfb, 0x74, 0xb1, 0x7e, 0xfb,
+ 0xeb, 0xee, 0xb1, 0x73, 0x92, 0xc5, 0x61, 0xbe, 0x01, 0x45, 0xef, 0xcf,
+ 0x16, 0x2e, 0x07, 0x0c, 0x37, 0xb2, 0x41, 0x52, 0x8c, 0xc6, 0x84, 0xfd,
+ 0xf7, 0xb9, 0x9b, 0x2c, 0x5f, 0xff, 0xef, 0xbf, 0x66, 0x03, 0xc2, 0x7b,
+ 0x31, 0xe7, 0xfd, 0xcc, 0xb1, 0x5d, 0x22, 0x2b, 0xe4, 0x97, 0x66, 0xcb,
+ 0x14, 0xc6, 0xf0, 0x89, 0x2a, 0x57, 0xb5, 0x60, 0x5e, 0x31, 0xfc, 0x84,
+ 0x03, 0xc2, 0xda, 0x3c, 0xce, 0x28, 0x67, 0xe8, 0x83, 0xf2, 0x87, 0xca,
+ 0x30, 0x5e, 0x43, 0xb2, 0xff, 0xfd, 0xa6, 0x19, 0x93, 0xf3, 0x3e, 0xfa,
+ 0xc8, 0x76, 0x58, 0xb9, 0x86, 0xb1, 0x4e, 0x7e, 0x2c, 0xb5, 0x7f, 0xff,
+ 0x6e, 0xfc, 0xc1, 0xef, 0xf7, 0xf6, 0x44, 0x52, 0x75, 0x8b, 0xff, 0xce,
+ 0x73, 0x27, 0xe6, 0x61, 0x4b, 0x8d, 0x62, 0xa2, 0x46, 0x3f, 0xc8, 0x09,
+ 0x76, 0xd1, 0xcb, 0x17, 0xd3, 0x10, 0xb6, 0x58, 0xa3, 0x9b, 0xaf, 0x0a,
+ 0xdc, 0x0d, 0xd6, 0x2c, 0xeb, 0x16, 0xe2, 0xc5, 0x8d, 0xe1, 0xbc, 0xf0,
+ 0xc8, 0x84, 0x6f, 0xed, 0x9b, 0x3d, 0x87, 0x58, 0xbf, 0x7d, 0xf5, 0x3f,
+ 0x58, 0xa7, 0x44, 0x5b, 0x1a, 0x88, 0xba, 0xf0, 0x1b, 0x75, 0x8b, 0xff,
+ 0x79, 0x80, 0x67, 0x89, 0x81, 0xc5, 0x8b, 0xde, 0x29, 0x58, 0xa2, 0x3d,
+ 0xc0, 0x90, 0x2f, 0xf1, 0x63, 0xeb, 0x3d, 0x2b, 0x17, 0xf6, 0x3e, 0xb3,
+ 0xd2, 0xb1, 0x78, 0xa7, 0xe6, 0x1e, 0xe9, 0x18, 0xdf, 0xe9, 0xf7, 0x0c,
+ 0x1b, 0x04, 0xb1, 0x58, 0x8e, 0x71, 0x3f, 0xf6, 0x32, 0xbf, 0xfe, 0x6e,
+ 0xa0, 0x1f, 0x01, 0x82, 0xde, 0x48, 0x0b, 0x17, 0xe1, 0xe1, 0xe4, 0x6b,
+ 0x16, 0x6d, 0x1f, 0xd9, 0x29, 0xdf, 0xf7, 0xe2, 0x6f, 0xb9, 0xd8, 0x6b,
+ 0x17, 0xa2, 0xe4, 0xac, 0x53, 0x9e, 0xc0, 0x47, 0x57, 0xff, 0xdf, 0x3b,
+ 0x02, 0x7e, 0x1f, 0x1c, 0x13, 0xf5, 0x8b, 0xff, 0xda, 0x03, 0x0c, 0xcc,
+ 0xfc, 0x96, 0xdd, 0xcb, 0x17, 0xe2, 0x6d, 0xa7, 0xcb, 0x14, 0xe8, 0xc8,
+ 0xfa, 0x8f, 0x13, 0xef, 0xdb, 0x37, 0x32, 0x0b, 0x17, 0xff, 0xc3, 0xce,
+ 0xcd, 0xa8, 0x83, 0x83, 0x79, 0x8e, 0xb1, 0x76, 0x47, 0xac, 0x54, 0xa2,
+ 0x5d, 0xca, 0x74, 0xa9, 0x7f, 0xc1, 0x97, 0x21, 0x85, 0x9d, 0x2c, 0x5f,
+ 0xcd, 0xd0, 0x0e, 0xfc, 0x58, 0xb1, 0xab, 0x17, 0xff, 0xff, 0xdd, 0x3f,
+ 0xc6, 0x53, 0xdd, 0x3d, 0x67, 0x66, 0xf6, 0x7c, 0xb3, 0xdf, 0x75, 0x8b,
+ 0xf6, 0xb3, 0xb0, 0xe5, 0x62, 0xfe, 0x7f, 0x4c, 0x4d, 0xd9, 0x62, 0xa5,
+ 0x77, 0x03, 0x68, 0xd8, 0x77, 0x85, 0x67, 0x4f, 0xd1, 0x43, 0xab, 0x50,
+ 0xc6, 0x39, 0x77, 0xce, 0x80, 0x5e, 0x42, 0x7e, 0x84, 0x0f, 0x62, 0xab,
+ 0xff, 0xd3, 0xad, 0xdc, 0x2d, 0x4f, 0x50, 0x73, 0xac, 0x5f, 0xce, 0x13,
+ 0x45, 0x27, 0x58, 0xbd, 0xdd, 0x3c, 0x58, 0xae, 0x22, 0x73, 0xc9, 0xa2,
+ 0x2f, 0xb4, 0x67, 0x78, 0xfa, 0x12, 0xfd, 0xe9, 0xb4, 0x68, 0x93, 0x1b,
+ 0x42, 0xbb, 0xbe, 0x13, 0x46, 0xb1, 0x89, 0xa5, 0x85, 0xed, 0x1e, 0x24,
+ 0x23, 0xc4, 0x1c, 0x6c, 0xb9, 0x39, 0xe5, 0xbc, 0x6b, 0x7d, 0x43, 0x4d,
+ 0xe7, 0x3e, 0x63, 0xe3, 0x04, 0x8a, 0x78, 0x8f, 0x52, 0x93, 0xcf, 0x1d,
+ 0x5f, 0xe7, 0x10, 0x1a, 0x5d, 0x98, 0x25, 0xd7, 0x14, 0xba, 0x2e, 0x4e,
+ 0xd4, 0x7a, 0x90, 0x92, 0x28, 0xfd, 0x3b, 0x35, 0x47, 0x43, 0xa0, 0x39,
+ 0xde, 0xee, 0xe8, 0xd8, 0xaf, 0xda, 0xdd, 0x9b, 0x75, 0x49, 0x38, 0x5f,
+ 0xdf, 0x73, 0x93, 0x1a, 0xb1, 0x68, 0xcc, 0x3e, 0x57, 0x37, 0xbd, 0x1a,
+ 0xbd, 0x1a, 0x96, 0x2f, 0xe9, 0x3e, 0x77, 0x4f, 0x96, 0x2f, 0xbf, 0x24,
+ 0x6a, 0xc5, 0xf4, 0xef, 0x3f, 0x58, 0xbf, 0x48, 0x52, 0x52, 0xb1, 0x47,
+ 0x44, 0xef, 0x8c, 0x03, 0x23, 0xee, 0x23, 0xbc, 0x33, 0xf9, 0x62, 0xf7,
+ 0x03, 0x82, 0xc5, 0xff, 0x7d, 0x8b, 0xcd, 0x07, 0x02, 0xc5, 0x61, 0xeb,
+ 0xb8, 0xfd, 0xff, 0x69, 0xb9, 0xfc, 0xc2, 0xdd, 0x62, 0xfe, 0x17, 0x33,
+ 0xc1, 0xec, 0xb1, 0x4e, 0x7d, 0x5f, 0x39, 0xbe, 0xd6, 0xb3, 0x8b, 0x17,
+ 0xe6, 0xeb, 0xf3, 0xd9, 0x62, 0x8e, 0x79, 0xdd, 0x88, 0xef, 0xff, 0xdf,
+ 0x17, 0xb5, 0x3e, 0xe6, 0x6f, 0xc9, 0xd6, 0xeb, 0x17, 0xc2, 0xee, 0x68,
+ 0x96, 0x2f, 0xf3, 0x9b, 0x90, 0x90, 0x71, 0x62, 0xa0, 0x7b, 0x7c, 0x27,
+ 0xbc, 0x39, 0x3a, 0xc5, 0xf8, 0x5c, 0xfb, 0x84, 0xb1, 0x7f, 0xa7, 0xcf,
+ 0xbb, 0x8e, 0x56, 0x2d, 0xa5, 0x8b, 0xff, 0xe8, 0x89, 0xf9, 0xe9, 0x0d,
+ 0xf5, 0x14, 0xfd, 0x62, 0xe6, 0xf2, 0xc5, 0x40, 0xfe, 0xf0, 0x49, 0x94,
+ 0xa8, 0x69, 0x91, 0x1a, 0x3b, 0xa2, 0xaf, 0x42, 0xba, 0xf6, 0x71, 0xd6,
+ 0x2f, 0xf4, 0xfa, 0x5c, 0x83, 0xe2, 0xc5, 0x61, 0xe7, 0xe8, 0x72, 0xff,
+ 0x16, 0xf1, 0x41, 0xf5, 0x05, 0x8b, 0xff, 0xef, 0x70, 0x3e, 0x79, 0xe4,
+ 0xbc, 0x4c, 0x05, 0x8b, 0x8d, 0xd9, 0x62, 0xa5, 0x14, 0x18, 0x6c, 0x6a,
+ 0x85, 0xfd, 0xd4, 0x24, 0xe2, 0x89, 0x62, 0xfe, 0x38, 0xe7, 0x82, 0x25,
+ 0x8b, 0xd0, 0x93, 0xac, 0x5f, 0xef, 0x43, 0x0d, 0x62, 0x02, 0xc5, 0xdf,
+ 0x75, 0x8a, 0xe8, 0xfa, 0x1c, 0x77, 0xc6, 0x95, 0x28, 0xf6, 0x73, 0x16,
+ 0x84, 0xb5, 0xf9, 0xb5, 0xe2, 0x95, 0x8b, 0xe1, 0x44, 0x23, 0x56, 0x2f,
+ 0xed, 0xe7, 0x8d, 0xd0, 0x16, 0x2f, 0x9a, 0x26, 0xf2, 0xc5, 0x6e, 0x8a,
+ 0x08, 0x89, 0xc8, 0x98, 0x33, 0x0b, 0xff, 0xff, 0x8c, 0x6f, 0xc6, 0x16,
+ 0x6b, 0x00, 0x0c, 0x8b, 0x82, 0x88, 0xa4, 0xeb, 0x17, 0xdc, 0x33, 0x81,
+ 0xac, 0x5f, 0xfd, 0x9d, 0xb0, 0x7a, 0x97, 0x83, 0x71, 0x62, 0xba, 0x3e,
+ 0xbd, 0x13, 0x53, 0xa6, 0x0a, 0xd0, 0xe2, 0xbf, 0x7b, 0xa8, 0x48, 0x4b,
+ 0x17, 0xf3, 0x07, 0x9d, 0xa7, 0x8b, 0x15, 0x87, 0xb6, 0x22, 0xbb, 0xff,
+ 0xbe, 0xe1, 0xf9, 0xc8, 0x50, 0xce, 0x2c, 0x5f, 0xf7, 0x5c, 0x2c, 0x1f,
+ 0xd8, 0x25, 0x8b, 0xee, 0x3f, 0xa5, 0x62, 0x9c, 0xf7, 0x58, 0xee, 0xff,
+ 0xfb, 0x36, 0xce, 0xbd, 0xc7, 0x29, 0x03, 0x1d, 0x62, 0xb1, 0x31, 0x23,
+ 0x61, 0x45, 0xc2, 0x0b, 0xf3, 0xec, 0xc4, 0x05, 0x8b, 0xff, 0x67, 0xe7,
+ 0x59, 0x18, 0x10, 0x41, 0x24, 0x5c, 0xe1, 0x2c, 0x5d, 0xb4, 0x64, 0x6a,
+ 0x65, 0xc8, 0xcc, 0x31, 0xf6, 0x41, 0x83, 0xa8, 0xe1, 0x15, 0x8d, 0xfb,
+ 0x92, 0x75, 0x0b, 0x47, 0x8d, 0x12, 0x28, 0x49, 0x9e, 0x18, 0x3f, 0x8c,
+ 0x95, 0xa1, 0xa4, 0x08, 0xd1, 0x0a, 0x10, 0x5e, 0x8c, 0xcf, 0xb1, 0xb4,
+ 0x71, 0x47, 0x72, 0x2d, 0xfb, 0x5b, 0xb3, 0x6e, 0xa9, 0x2f, 0x0b, 0xff,
+ 0xbf, 0x3b, 0x6a, 0x7c, 0xfb, 0xb8, 0xd6, 0x2f, 0xff, 0x0d, 0xb5, 0xda,
+ 0x41, 0xf9, 0x3b, 0x12, 0xc5, 0xff, 0xbd, 0x24, 0xfb, 0x1d, 0xb4, 0x05,
+ 0x8a, 0x94, 0x45, 0x32, 0x5d, 0xff, 0xfd, 0x83, 0xfc, 0x87, 0x19, 0xe2,
+ 0x60, 0x73, 0x92, 0x04, 0x8b, 0x46, 0x62, 0x70, 0xf1, 0x1b, 0x94, 0x34,
+ 0x23, 0x88, 0x6f, 0xfe, 0x8c, 0x68, 0x46, 0x66, 0xb7, 0x66, 0xdd, 0x52,
+ 0x23, 0x97, 0x61, 0xd6, 0x2e, 0xf6, 0x2c, 0x5f, 0x75, 0xe0, 0xc0, 0xb1,
+ 0x5b, 0x9e, 0xa7, 0x42, 0xee, 0x2f, 0x7f, 0xfd, 0x9e, 0x7f, 0x8b, 0xec,
+ 0xfd, 0x72, 0x4d, 0x58, 0xbf, 0xfc, 0x6b, 0xeb, 0x35, 0x09, 0xff, 0xdc,
+ 0x0b, 0x17, 0x7c, 0x6b, 0x17, 0x48, 0xd6, 0x2f, 0xff, 0xde, 0x91, 0xc8,
+ 0xbb, 0xfd, 0x4f, 0x9c, 0x13, 0x05, 0x8b, 0xfd, 0xe7, 0x86, 0xb4, 0xfd,
+ 0x2c, 0x5e, 0x26, 0x8c, 0x82, 0x2f, 0xbe, 0x31, 0xd8, 0x5c, 0x35, 0xab,
+ 0xfe, 0x13, 0x7f, 0x06, 0xcd, 0xba, 0xc5, 0xff, 0xce, 0x11, 0x9c, 0xc7,
+ 0x8e, 0x72, 0xf2, 0xc5, 0xff, 0xed, 0x4e, 0x75, 0x19, 0xe8, 0x48, 0x0e,
+ 0xeb, 0x15, 0xba, 0x33, 0xf8, 0x73, 0xe4, 0x8b, 0xff, 0xe6, 0x93, 0xc6,
+ 0x73, 0x22, 0x91, 0x77, 0xfd, 0xdf, 0x58, 0xbf, 0xf9, 0xe2, 0x8c, 0x2c,
+ 0xd6, 0x67, 0x41, 0x2c, 0x51, 0x22, 0x94, 0x25, 0xcb, 0xff, 0xc4, 0xc1,
+ 0x7b, 0x3f, 0xa9, 0x83, 0x69, 0x62, 0xf3, 0x82, 0x56, 0x2f, 0x6f, 0x87,
+ 0x48, 0x8c, 0x2f, 0x2f, 0x77, 0x7c, 0xd5, 0x8b, 0xec, 0x6e, 0x80, 0xb1,
+ 0x7f, 0xe0, 0x70, 0xcd, 0xfe, 0xfd, 0x9f, 0x4b, 0x17, 0xff, 0xd2, 0x42,
+ 0xe7, 0xdf, 0x59, 0xda, 0x4b, 0xcb, 0x15, 0x28, 0x94, 0xfa, 0x25, 0xff,
+ 0xcf, 0xac, 0xd4, 0x27, 0xff, 0x70, 0x2c, 0x5f, 0x6e, 0xcd, 0xba, 0xa4,
+ 0x48, 0x2f, 0xe6, 0xd6, 0x76, 0xfe, 0x2c, 0x56, 0xc9, 0xbe, 0xc2, 0x16,
+ 0xe6, 0x91, 0x69, 0x10, 0x06, 0x37, 0xd1, 0x7b, 0x37, 0x58, 0xbf, 0x4b,
+ 0x81, 0xce, 0xb1, 0x52, 0x79, 0x90, 0x25, 0xbf, 0x8b, 0xc5, 0x27, 0xe2,
+ 0xc5, 0xed, 0x48, 0xd6, 0x2a, 0x4f, 0x2b, 0x0b, 0x6f, 0xff, 0xcf, 0xa7,
+ 0xee, 0x92, 0xda, 0x7c, 0xff, 0x6d, 0x96, 0x2f, 0xcd, 0x0f, 0x3e, 0xcb,
+ 0x15, 0x28, 0x81, 0x75, 0x8b, 0xed, 0x8e, 0x20, 0x96, 0x2f, 0xff, 0x37,
+ 0xa2, 0xe6, 0x0c, 0x62, 0x6d, 0x41, 0x62, 0xff, 0xf9, 0xba, 0xe6, 0x7d,
+ 0x8b, 0x36, 0x38, 0xbe, 0xb1, 0x7f, 0xf7, 0xdf, 0xaf, 0x67, 0x5e, 0xd6,
+ 0xa5, 0x62, 0xff, 0xe7, 0x93, 0xb0, 0xc3, 0xee, 0x92, 0x82, 0xc5, 0xfd,
+ 0x3f, 0xe4, 0x74, 0xf9, 0x62, 0xde, 0x58, 0xac, 0x4c, 0x8b, 0x75, 0x1f,
+ 0xa3, 0x81, 0x1f, 0xc6, 0x37, 0xff, 0x60, 0x23, 0xb3, 0x53, 0xb3, 0x6b,
+ 0x75, 0x8b, 0xf3, 0x03, 0xd8, 0x05, 0x8a, 0x23, 0xf1, 0xe2, 0x4d, 0xfe,
+ 0xcf, 0xb1, 0xca, 0x7a, 0x58, 0xba, 0x11, 0x92, 0xbc, 0x7d, 0x03, 0x0c,
+ 0x8e, 0x7d, 0xe1, 0x3d, 0x13, 0x5f, 0xe1, 0x42, 0xc4, 0x20, 0x26, 0xe4,
+ 0x6d, 0xde, 0x85, 0xe0, 0x64, 0x37, 0xe1, 0x75, 0xbb, 0xf1, 0x62, 0xff,
+ 0xb3, 0xcf, 0xcd, 0x6b, 0x20, 0xb1, 0x77, 0x7d, 0x7b, 0xc5, 0x8b, 0x98,
+ 0x0b, 0x14, 0xb1, 0x5a, 0x34, 0x67, 0x17, 0xbf, 0xbe, 0xfd, 0x79, 0xbe,
+ 0xb1, 0x77, 0xe3, 0x23, 0x64, 0x4c, 0x62, 0x46, 0xe4, 0x37, 0x8a, 0x62,
+ 0x58, 0xac, 0x3e, 0x17, 0x44, 0xb7, 0x4b, 0x17, 0x88, 0x47, 0x58, 0xbf,
+ 0xfc, 0xe4, 0x28, 0x67, 0x0b, 0x36, 0x0e, 0x0b, 0x14, 0x33, 0xfb, 0x34,
+ 0x4f, 0xc3, 0xb6, 0x8c, 0x96, 0x69, 0xa0, 0xcc, 0x31, 0x47, 0x78, 0xc2,
+ 0x7a, 0x8c, 0x89, 0xe1, 0xad, 0x11, 0x1b, 0x4f, 0x52, 0x02, 0x18, 0x7c,
+ 0x2b, 0xf4, 0x66, 0x41, 0xc2, 0x6e, 0xff, 0xe8, 0xc6, 0x84, 0x66, 0x6b,
+ 0x76, 0x6d, 0xd5, 0x22, 0x51, 0x7d, 0xbb, 0x36, 0xea, 0x93, 0xc4, 0xbc,
+ 0x1c, 0x81, 0x62, 0xb4, 0x79, 0xe7, 0x31, 0xbf, 0xe8, 0x46, 0x66, 0xb7,
+ 0x66, 0xdd, 0x52, 0x26, 0x96, 0x8c, 0xc3, 0xed, 0x62, 0x2b, 0xee, 0xf2,
+ 0x5e, 0x39, 0x62, 0xf7, 0xdc, 0x96, 0x2a, 0x37, 0x3c, 0x6d, 0xca, 0xaf,
+ 0x46, 0xa0, 0xb6, 0x58, 0xb8, 0x71, 0xb2, 0xc5, 0xfe, 0x87, 0xe3, 0x62,
+ 0x36, 0x74, 0xb1, 0x7f, 0xa3, 0x48, 0xd3, 0xf8, 0x7c, 0xe2, 0xc5, 0xf0,
+ 0x7b, 0x43, 0xcb, 0x15, 0xde, 0x9f, 0x24, 0x6c, 0x7d, 0x7f, 0xfe, 0x1b,
+ 0x43, 0x82, 0xf4, 0xfb, 0x80, 0xf7, 0xba, 0x58, 0xbd, 0xef, 0x74, 0xb1,
+ 0x77, 0x79, 0x1b, 0x61, 0xfc, 0x01, 0x66, 0xfd, 0xce, 0x61, 0x62, 0xc5,
+ 0xff, 0x6b, 0x79, 0xdb, 0x30, 0xbc, 0xb1, 0x7f, 0x10, 0x71, 0x6a, 0x7b,
+ 0x2c, 0x5f, 0x33, 0xf5, 0xc5, 0x8b, 0xfd, 0xce, 0x60, 0x0d, 0xf1, 0x2c,
+ 0x5f, 0xff, 0xbd, 0xc0, 0x16, 0x7b, 0xf9, 0xe2, 0x99, 0x3a, 0xc5, 0xbe,
+ 0xb1, 0x58, 0x9a, 0x8b, 0x93, 0xc7, 0x9d, 0x7c, 0xc9, 0x88, 0xc8, 0xd4,
+ 0x25, 0x4b, 0xe1, 0xfe, 0x76, 0x58, 0xbf, 0xd3, 0xf9, 0x10, 0x6f, 0xdc,
+ 0xb1, 0x7e, 0xc2, 0x9e, 0xb8, 0xb1, 0x7f, 0xf4, 0x27, 0xdf, 0x0f, 0x93,
+ 0xec, 0x3a, 0xc5, 0x00, 0xfb, 0xbc, 0x51, 0x7f, 0x3c, 0xf7, 0x7e, 0x74,
+ 0xb1, 0x5b, 0x23, 0xdd, 0xe1, 0x4b, 0xf2, 0x2b, 0xf1, 0x3e, 0xee, 0x35,
+ 0x8b, 0xdd, 0xa6, 0x0b, 0x17, 0xe9, 0xf7, 0x33, 0xcb, 0x17, 0x98, 0x87,
+ 0x87, 0x8f, 0xf1, 0xfb, 0xfc, 0xe6, 0xf5, 0xcc, 0x23, 0x56, 0x2f, 0xf1,
+ 0xc5, 0xef, 0xc8, 0xbb, 0xf5, 0x8b, 0xec, 0x16, 0xb6, 0x58, 0xbc, 0xda,
+ 0x81, 0x87, 0xbd, 0xc3, 0xaa, 0xc4, 0xda, 0x1d, 0xbf, 0xe6, 0x22, 0x84,
+ 0xa5, 0xfb, 0x05, 0xbb, 0x12, 0xc5, 0xe9, 0x9f, 0x2c, 0x5f, 0xf6, 0x00,
+ 0x7f, 0x92, 0x90, 0x96, 0x2f, 0x81, 0xcc, 0x25, 0x8a, 0x93, 0xdb, 0x73,
0x9b, 0xff, 0x0b, 0x7e, 0x71, 0xb5, 0xe9, 0x35, 0x62, 0xfd, 0xff, 0x73,
0x3c, 0xb1, 0x7f, 0xbc, 0xff, 0x73, 0x7e, 0xeb, 0x14, 0xe8, 0x9f, 0x64,
0x21, 0x14, 0xdf, 0xff, 0xbe, 0xce, 0x0e, 0x61, 0xac, 0x7d, 0x4e, 0x12,
0xc5, 0xfd, 0x9e, 0x36, 0x4a, 0x0b, 0x17, 0x38, 0xd6, 0x2a, 0x51, 0x32,
- 0x35, 0x4f, 0x97, 0x5f, 0xee, 0x03, 0x32, 0x23, 0x0e, 0xb1, 0x78, 0x53,
- 0xda, 0xc5, 0x49, 0xea, 0x40, 0xda, 0xff, 0xb6, 0x7e, 0x71, 0x81, 0xf1,
- 0x2c, 0x5f, 0xc3, 0xc2, 0xe4, 0xfd, 0x62, 0xf8, 0x65, 0x3d, 0xac, 0x5b,
- 0x4b, 0x16, 0x71, 0x9f, 0x16, 0x8b, 0x44, 0x47, 0x6f, 0xac, 0x5f, 0xf6,
- 0x1a, 0x6b, 0x43, 0x3b, 0xf2, 0xc5, 0xed, 0xa7, 0x65, 0x8b, 0x9b, 0xbc,
- 0x3d, 0xb3, 0x0f, 0x2b, 0xc8, 0x9b, 0x13, 0x6d, 0xfb, 0x82, 0x37, 0x66,
- 0x58, 0xbf, 0xd8, 0x36, 0x3e, 0x77, 0xe5, 0x8a, 0x81, 0xef, 0x91, 0x5d,
- 0xfb, 0x33, 0xdf, 0xc5, 0x8a, 0x93, 0xc8, 0xf9, 0x0d, 0xfe, 0x87, 0x35,
- 0xa6, 0x2f, 0x2c, 0x5f, 0xff, 0xb5, 0xef, 0xe1, 0x13, 0x7a, 0x4b, 0xd1,
- 0xd8, 0xb1, 0x52, 0x88, 0xa7, 0x34, 0xae, 0xab, 0xb9, 0x7b, 0x14, 0x41,
- 0xdc, 0x70, 0xbf, 0xde, 0x18, 0xf1, 0x42, 0x0f, 0x44, 0x3f, 0x84, 0xef,
- 0x21, 0x9f, 0xe8, 0x65, 0x74, 0x85, 0x5d, 0xfe, 0x6e, 0xbc, 0xf7, 0xe4,
- 0x0b, 0x17, 0xe7, 0x18, 0xbd, 0xc5, 0x8b, 0xec, 0x3c, 0xc7, 0xac, 0x51,
- 0xa8, 0x84, 0xf9, 0xb7, 0x0a, 0x6f, 0xe7, 0xc2, 0x9e, 0xf8, 0xb1, 0x7b,
- 0x4e, 0x75, 0x8b, 0xf0, 0xc9, 0x83, 0xe2, 0xc5, 0xf7, 0xa4, 0xb6, 0x58,
- 0xa3, 0x4f, 0x33, 0xc5, 0x37, 0xb5, 0x9e, 0x58, 0xbf, 0xf4, 0xef, 0xd4,
- 0xcf, 0x71, 0x88, 0xd5, 0x8a, 0xd1, 0xf0, 0x9c, 0x76, 0xa5, 0x30, 0xfc,
- 0x69, 0x78, 0x42, 0x5f, 0xb0, 0x61, 0x6c, 0xa3, 0xd6, 0x2f, 0xe6, 0x20,
- 0x05, 0xb2, 0x8f, 0x58, 0xb9, 0x87, 0xd0, 0xf9, 0xe3, 0x8c, 0x68, 0xea,
- 0x82, 0x3f, 0x19, 0xe0, 0xa1, 0x35, 0x70, 0x4e, 0xd6, 0x2f, 0x31, 0x6e,
- 0xb1, 0x7b, 0xf2, 0x62, 0xc5, 0x70, 0xf5, 0xbc, 0x36, 0x18, 0xed, 0xfd,
- 0xd7, 0xdc, 0x62, 0x35, 0x62, 0xfe, 0x0e, 0x2f, 0xc9, 0x1a, 0xb1, 0x7b,
- 0x18, 0xeb, 0x17, 0x08, 0xc5, 0x8b, 0xd3, 0xd4, 0xeb, 0x17, 0xd3, 0xf7,
- 0x3a, 0xc5, 0xd9, 0xe5, 0x8b, 0xfd, 0x07, 0xfb, 0x41, 0xfe, 0xb1, 0x5f,
- 0x3c, 0xa6, 0x17, 0xbc, 0xdd, 0x98, 0xb1, 0x50, 0x4d, 0x8b, 0x0c, 0x4d,
- 0x31, 0x88, 0x73, 0x43, 0x27, 0x1f, 0xfb, 0x61, 0x10, 0xdf, 0xfe, 0x16,
- 0xa0, 0x53, 0x09, 0xf7, 0xf0, 0x96, 0x2f, 0x46, 0xe1, 0x59, 0x58, 0xbb,
- 0xbf, 0x2c, 0x5d, 0xf9, 0x58, 0xbd, 0x3e, 0xe6, 0x1b, 0x03, 0x06, 0x6f,
- 0x49, 0x44, 0xb1, 0x74, 0xc7, 0xac, 0x56, 0x8d, 0xbf, 0xc7, 0x6f, 0xcc,
- 0x02, 0x63, 0xac, 0x54, 0x6e, 0x98, 0x3c, 0x15, 0x9d, 0xa4, 0x88, 0x6f,
- 0xc3, 0xfc, 0x7b, 0x92, 0xc5, 0xfe, 0x2c, 0x3c, 0x76, 0x6a, 0x56, 0x2a,
- 0x4f, 0x82, 0x22, 0xbb, 0xd3, 0xee, 0x2c, 0x5f, 0xe3, 0xff, 0x06, 0x37,
- 0xed, 0x62, 0xfe, 0x1f, 0xc5, 0x3a, 0x95, 0x8a, 0x93, 0xe3, 0xc3, 0x5b,
- 0xfe, 0xfc, 0x96, 0x45, 0x3a, 0xd9, 0x62, 0xfe, 0x2c, 0x1f, 0xd8, 0x35,
- 0x8b, 0xfa, 0x0d, 0xad, 0xbe, 0x25, 0x8b, 0x48, 0xd1, 0x30, 0x69, 0xd4,
- 0x45, 0xd7, 0xfb, 0xdd, 0x85, 0x4d, 0x35, 0xc6, 0xb1, 0x7f, 0xe6, 0xee,
- 0x1c, 0xeb, 0x3b, 0xb1, 0x8b, 0x17, 0xbb, 0xf4, 0xac, 0x56, 0x2a, 0x2f,
- 0xec, 0x89, 0xe1, 0x01, 0xa8, 0x5c, 0x1c, 0xdd, 0x8f, 0x04, 0x89, 0x7c,
- 0x11, 0xe4, 0xd5, 0x8b, 0xd0, 0xec, 0xd5, 0x8b, 0x0d, 0x62, 0xfd, 0x9a,
- 0x87, 0xc4, 0xb1, 0x7e, 0x83, 0x4f, 0x61, 0x16, 0x2f, 0xde, 0xf8, 0xbd,
- 0xc5, 0x8a, 0x1a, 0x24, 0x37, 0x12, 0xec, 0xa4, 0xe5, 0x77, 0xe1, 0xcf,
- 0x0c, 0xe2, 0xc5, 0xc3, 0xed, 0x62, 0x8e, 0x78, 0x62, 0x2a, 0xbf, 0xf8,
- 0x5a, 0x68, 0x1c, 0x43, 0xf8, 0x89, 0x62, 0xf0, 0xa7, 0x8b, 0x17, 0xfe,
- 0x06, 0xff, 0x7d, 0x13, 0xfb, 0x8b, 0x17, 0xfd, 0x39, 0xc8, 0xbe, 0xe1,
- 0xf9, 0x62, 0x8e, 0x89, 0x86, 0x1d, 0xe2, 0x05, 0xfa, 0x1f, 0x92, 0x35,
- 0x62, 0xfc, 0xed, 0xa9, 0xdd, 0x62, 0xdd, 0x30, 0xf4, 0x78, 0x53, 0x71,
- 0x6c, 0xb1, 0x52, 0xac, 0x60, 0x64, 0xb9, 0x0b, 0x07, 0x84, 0x11, 0xc8,
- 0x9a, 0x1b, 0xc0, 0x84, 0x01, 0x85, 0x37, 0xc2, 0x88, 0x46, 0xac, 0x52,
- 0xc5, 0xfd, 0x23, 0x3c, 0xe7, 0x96, 0x2b, 0xc6, 0xe4, 0xc0, 0xcb, 0xfe,
- 0x9d, 0x01, 0xbd, 0x1d, 0x9e, 0x58, 0xbb, 0x58, 0xb1, 0x7d, 0xdb, 0xf7,
- 0x05, 0x8b, 0x8c, 0xd9, 0x62, 0x9c, 0xdf, 0x80, 0x96, 0xa2, 0x4c, 0xcf,
- 0x4b, 0xff, 0x22, 0x01, 0xe1, 0x2b, 0x5d, 0x1b, 0x85, 0xb5, 0x8b, 0xb0,
- 0xeb, 0x17, 0xb5, 0xd3, 0xeb, 0x17, 0xec, 0xd3, 0x48, 0xd6, 0x2a, 0x37,
- 0x44, 0x0c, 0x91, 0xb0, 0xb9, 0x10, 0x5e, 0x1e, 0x12, 0xc5, 0xf0, 0xa1,
- 0xe3, 0x16, 0x2f, 0x6f, 0x3a, 0x58, 0xbf, 0xf6, 0x84, 0x7f, 0xbc, 0x9d,
- 0x89, 0x62, 0xff, 0x0b, 0xb1, 0xfc, 0x4d, 0xc5, 0x8b, 0xfd, 0x27, 0x2c,
- 0x84, 0x92, 0xc5, 0x7c, 0xf9, 0xf8, 0x6d, 0x7f, 0x9c, 0xba, 0xe1, 0xdf,
- 0xcb, 0x15, 0xb2, 0x67, 0xce, 0x4b, 0xa1, 0xef, 0x42, 0x97, 0xa1, 0x15,
- 0xfc, 0x59, 0x11, 0x4e, 0xcb, 0x17, 0xf1, 0x13, 0x9f, 0xd8, 0xb1, 0x7a,
- 0x7b, 0x82, 0xc5, 0xc5, 0x05, 0x8b, 0xa3, 0x60, 0xd6, 0x28, 0x46, 0xd6,
- 0x38, 0x5e, 0xa5, 0x53, 0xee, 0x46, 0xb5, 0x1e, 0xa4, 0xc5, 0xc4, 0x58,
- 0x11, 0x4e, 0xff, 0xed, 0xc4, 0xc3, 0xe9, 0x83, 0x0b, 0x65, 0x1e, 0xb1,
- 0x7c, 0xff, 0x9e, 0x8b, 0x15, 0xa3, 0xf5, 0xf2, 0x8d, 0xfe, 0x9d, 0x4f,
- 0x60, 0xd4, 0xac, 0x5f, 0xdd, 0xc2, 0x70, 0x11, 0xeb, 0x17, 0xfd, 0xac,
- 0xfe, 0x11, 0x48, 0xd6, 0x2f, 0xff, 0xe9, 0xf8, 0x86, 0xf3, 0x14, 0xbf,
- 0x04, 0xd1, 0xd8, 0xb1, 0x5a, 0x44, 0xa1, 0xcd, 0xef, 0x38, 0x4d, 0x96,
- 0x2d, 0xb2, 0xc5, 0x49, 0xb3, 0x22, 0x0b, 0xdf, 0x14, 0x7a, 0xc5, 0xfc,
- 0x53, 0xef, 0xb4, 0x16, 0x2a, 0x4f, 0x3a, 0x22, 0x1b, 0xde, 0x9d, 0x2c,
- 0x54, 0xaa, 0x1e, 0xd8, 0x8b, 0x0d, 0x1e, 0x18, 0xd1, 0x2b, 0x33, 0x68,
- 0x88, 0xae, 0x6d, 0xd6, 0x2f, 0xff, 0xff, 0x61, 0x13, 0x43, 0xef, 0xd4,
- 0xcd, 0x6a, 0x60, 0xfe, 0x7d, 0x30, 0x16, 0x2f, 0xc3, 0x16, 0xc6, 0x1d,
- 0x62, 0xff, 0xfc, 0x52, 0x3e, 0x09, 0x9e, 0x0e, 0x0e, 0x0b, 0x8b, 0x17,
- 0xf6, 0x7b, 0xef, 0xdc, 0x16, 0x2a, 0x24, 0x42, 0x12, 0xad, 0x6e, 0x8d,
- 0x3f, 0xc2, 0xc2, 0xfe, 0xef, 0x98, 0x76, 0xe2, 0xc5, 0xf0, 0xf3, 0xf2,
- 0xb1, 0x6d, 0x2c, 0x5f, 0xb6, 0xd4, 0xf7, 0xa5, 0x8a, 0xd8, 0xde, 0xe0,
- 0x95, 0xff, 0xfd, 0xee, 0xa3, 0x96, 0xd6, 0x10, 0x3a, 0xf3, 0xdc, 0xed,
- 0x62, 0xfb, 0x5b, 0x03, 0xcb, 0x17, 0xf0, 0xf2, 0x12, 0x0e, 0x2c, 0x56,
- 0x22, 0xd1, 0xd8, 0x44, 0x4b, 0x52, 0xac, 0x76, 0x03, 0x19, 0x1a, 0x5b,
- 0x94, 0xb1, 0x79, 0x2f, 0xf2, 0x1a, 0xb7, 0xff, 0xf4, 0x6a, 0x14, 0x69,
- 0x27, 0xf7, 0x5d, 0xb3, 0xfd, 0x7a, 0xfe, 0x39, 0x62, 0xfe, 0xfb, 0xfa,
- 0x48, 0x0b, 0x17, 0xdf, 0xe8, 0xfa, 0x58, 0xa9, 0x3d, 0x2c, 0x2d, 0xbf,
- 0xfd, 0x9f, 0xdf, 0xef, 0xdf, 0xb0, 0xed, 0xc5, 0x8b, 0xf4, 0x6d, 0x1a,
- 0xe3, 0x5c, 0x6b, 0x08, 0xb1, 0x74, 0xf9, 0x62, 0xf1, 0x46, 0xfd, 0x16,
- 0x28, 0xe6, 0xef, 0xc2, 0xf7, 0xf6, 0x67, 0x33, 0xbf, 0x2c, 0x5c, 0x28,
- 0xf5, 0x8b, 0x6c, 0x33, 0xc9, 0x39, 0x75, 0xfb, 0xc7, 0x88, 0x86, 0xb1,
- 0x7d, 0xf3, 0x23, 0x99, 0x62, 0xa3, 0x64, 0xd8, 0xb1, 0xf9, 0x9a, 0x88,
- 0xa4, 0x45, 0x57, 0xdc, 0xe3, 0x9d, 0x62, 0xff, 0xef, 0xbf, 0x61, 0xc9,
- 0xff, 0x2f, 0x05, 0x8a, 0x88, 0xfa, 0x7e, 0x47, 0x7b, 0x82, 0xed, 0x62,
- 0xff, 0x45, 0x06, 0xd6, 0xdf, 0x12, 0xc5, 0xff, 0xf6, 0xc1, 0xb4, 0x39,
- 0xcc, 0xd0, 0x73, 0xa3, 0x56, 0x2c, 0x4b, 0x17, 0xf3, 0x7b, 0x9b, 0x60,
- 0x6b, 0x17, 0xff, 0xf3, 0xf1, 0xa1, 0xc7, 0xe9, 0xc1, 0x33, 0xc1, 0xfa,
- 0x2c, 0x5c, 0x61, 0x8b, 0x15, 0x89, 0xc3, 0xc4, 0x46, 0x71, 0xf6, 0x37,
- 0x02, 0xa9, 0x08, 0xf8, 0xc0, 0xc5, 0xeb, 0xf6, 0x68, 0x00, 0x95, 0x8b,
- 0xa3, 0xa3, 0x23, 0x77, 0x56, 0x60, 0x14, 0x28, 0x0a, 0x93, 0x05, 0xb8,
- 0x40, 0xc6, 0xa8, 0x51, 0xcc, 0x70, 0xfb, 0x32, 0xc2, 0x1d, 0x43, 0x8e,
- 0x43, 0x27, 0x83, 0x0d, 0x8d, 0x27, 0x79, 0x47, 0x3d, 0xc2, 0x4d, 0xe3,
- 0x92, 0x8f, 0x72, 0x8a, 0x35, 0x0d, 0x4a, 0xd0, 0xfc, 0xb8, 0x66, 0x8e,
- 0xdc, 0x10, 0xcc, 0x29, 0x57, 0x9c, 0x95, 0xe7, 0xe9, 0x70, 0xc2, 0x6c,
- 0xe9, 0x0c, 0x50, 0xc8, 0x23, 0xa3, 0xae, 0x32, 0x51, 0xe8, 0x47, 0x1b,
- 0xfc, 0x2d, 0xa3, 0x02, 0x04, 0x73, 0x56, 0x2a, 0x61, 0x1d, 0x83, 0xb4,
- 0x3f, 0xe1, 0x78, 0x32, 0x43, 0x95, 0x26, 0xf4, 0x9a, 0xb8, 0xa5, 0x64,
- 0x9d, 0x3b, 0xf4, 0xce, 0x3f, 0x43, 0x1c, 0x51, 0x8a, 0x99, 0x6a, 0xe7,
- 0x82, 0x4a, 0x40, 0xa9, 0xac, 0xe8, 0xb2, 0x76, 0xa5, 0xc2, 0xc2, 0xb8,
- 0xf9, 0x1d, 0x73, 0x2d, 0x9a, 0xb7, 0x05, 0x8d, 0xac, 0x78, 0xf7, 0xcd,
- 0x82, 0x3b, 0xbb, 0xd9, 0x4a, 0x7b, 0x4f, 0xf1, 0x1f, 0x2a, 0x8a, 0x2c,
- 0x7b, 0x1c, 0xeb, 0x30, 0x57, 0xf3, 0xef, 0x5c, 0x10, 0x7e, 0xdb, 0xe0,
- 0xb6, 0x3b, 0xde, 0x41, 0x6b, 0x57, 0x02, 0xf3, 0xb2, 0xc5, 0x88, 0x27,
- 0x5e, 0x5f, 0x41, 0x2f, 0xb3, 0xac, 0x27, 0x16, 0x3a, 0xcb, 0x3a, 0x5a,
- 0x41, 0x10, 0xeb, 0xb5, 0x08, 0xea, 0x7d, 0x29, 0x96, 0x84, 0x40, 0x26,
- 0x24, 0x51, 0x68,
+ 0x35, 0x4f, 0x97, 0x5e, 0x17, 0x25, 0x62, 0xff, 0x70, 0x19, 0x91, 0x06,
+ 0x75, 0x8b, 0xc2, 0x9e, 0x96, 0x2a, 0x4f, 0x52, 0x06, 0xd7, 0xfd, 0xb3,
+ 0xf3, 0x8c, 0x0f, 0x89, 0x62, 0xfe, 0x1e, 0x17, 0x27, 0xeb, 0x17, 0xc3,
+ 0x29, 0xe9, 0x62, 0xda, 0x58, 0xb3, 0x8c, 0xf8, 0xb4, 0x5a, 0x22, 0x3b,
+ 0x7d, 0x62, 0xff, 0xb0, 0xd3, 0x5a, 0x19, 0xd7, 0x96, 0x2f, 0x6d, 0x3b,
+ 0x2c, 0x5c, 0xdd, 0x61, 0xed, 0x86, 0x79, 0x5e, 0x44, 0xd8, 0x9b, 0x6f,
+ 0xdc, 0x11, 0xbb, 0x32, 0xc5, 0xfe, 0xc1, 0xb1, 0xf3, 0xaf, 0x2c, 0x54,
+ 0x0f, 0x7c, 0x8a, 0xef, 0xd9, 0x9e, 0xfe, 0x2c, 0x54, 0x9e, 0x47, 0xc8,
+ 0x6f, 0xf4, 0x39, 0xad, 0x31, 0x79, 0x62, 0xff, 0xfd, 0xaf, 0x7f, 0x08,
+ 0x9b, 0xd2, 0x5e, 0x8e, 0xc5, 0x8a, 0x94, 0x45, 0x39, 0xa5, 0x18, 0xbb,
+ 0xd1, 0xb1, 0x44, 0x1d, 0xc7, 0x0b, 0xfd, 0xe1, 0x8f, 0xd1, 0x7c, 0x4e,
+ 0x3a, 0x21, 0xfc, 0x27, 0x79, 0x0c, 0xff, 0x43, 0x2b, 0xb4, 0x2a, 0xef,
+ 0xf3, 0x19, 0xcf, 0x7e, 0x40, 0xb1, 0x7e, 0x71, 0x8b, 0xdc, 0x58, 0xbe,
+ 0xc3, 0xcc, 0x7a, 0xc5, 0x1a, 0x88, 0x3f, 0x9a, 0xf0, 0xa6, 0xfe, 0x7c,
+ 0x29, 0xeb, 0x8b, 0x17, 0xb4, 0xe7, 0x58, 0xbf, 0x0c, 0x98, 0x2e, 0x2c,
+ 0x5f, 0x7a, 0x4b, 0x65, 0x8a, 0x34, 0xf3, 0x3c, 0x53, 0x7b, 0x59, 0xe5,
+ 0x8b, 0xff, 0x4e, 0xe6, 0x07, 0xee, 0x31, 0x1a, 0xb1, 0x5a, 0x3e, 0x03,
+ 0x8e, 0xd4, 0xa6, 0x1d, 0x8d, 0x2f, 0x08, 0x3b, 0xf6, 0xff, 0x66, 0xd2,
+ 0xc5, 0xfb, 0x07, 0xdf, 0x65, 0x1e, 0xb1, 0x7f, 0x31, 0x03, 0xbe, 0xca,
+ 0x3d, 0x62, 0xe6, 0x1f, 0x63, 0xe9, 0x8e, 0x32, 0xa3, 0xaa, 0x32, 0xfc,
+ 0x67, 0x7c, 0x33, 0x14, 0x24, 0xaf, 0xc5, 0xce, 0xa1, 0xc5, 0x8b, 0xcc,
+ 0x5b, 0xac, 0x5e, 0xfc, 0x86, 0xb1, 0x50, 0x3e, 0x5f, 0x15, 0x04, 0x3b,
+ 0x7f, 0x19, 0xee, 0x31, 0x1a, 0xb1, 0x7f, 0x05, 0x17, 0xe4, 0x8d, 0x58,
+ 0xbd, 0x8c, 0x75, 0x8b, 0x84, 0x1a, 0xc5, 0xc6, 0x1d, 0x62, 0xc2, 0x58,
+ 0xa9, 0x35, 0x7f, 0x19, 0xbe, 0x9f, 0xb9, 0xd6, 0x2e, 0xcf, 0x2c, 0x5f,
+ 0xe8, 0x3f, 0xda, 0x0f, 0xf5, 0x8a, 0xf9, 0xe5, 0x30, 0xbd, 0xe6, 0xe8,
+ 0x35, 0x8a, 0x82, 0x71, 0xb8, 0x60, 0x69, 0x8c, 0x43, 0x9a, 0x44, 0x39,
+ 0x07, 0xdb, 0x08, 0x86, 0xff, 0xf0, 0xb5, 0x02, 0x98, 0x4f, 0xbf, 0x84,
+ 0xb1, 0x7a, 0x37, 0xef, 0x65, 0x62, 0xfd, 0xc9, 0x21, 0x71, 0x62, 0xee,
+ 0xbc, 0xb1, 0x77, 0xe5, 0x62, 0xf4, 0xfb, 0x98, 0x6c, 0x03, 0x19, 0xbd,
+ 0x25, 0x12, 0xc5, 0xd3, 0x1e, 0xb1, 0x5a, 0x36, 0xff, 0x1d, 0xbf, 0x30,
+ 0x09, 0x8e, 0xb1, 0x51, 0xba, 0x66, 0x12, 0x4f, 0x05, 0x87, 0x69, 0x22,
+ 0x1b, 0xf0, 0xff, 0x1e, 0xe4, 0xb1, 0x7f, 0x8b, 0x0f, 0x1d, 0x9a, 0x95,
+ 0x8a, 0x93, 0xe0, 0x88, 0xae, 0xf4, 0xfb, 0x8b, 0x17, 0xf8, 0xff, 0xc1,
+ 0x8d, 0xfa, 0x58, 0xbf, 0x87, 0xf1, 0x4e, 0xa5, 0x62, 0xa4, 0xf8, 0xf0,
+ 0xd6, 0xff, 0xbf, 0x25, 0x91, 0x4e, 0xb6, 0x58, 0xbf, 0x8b, 0x07, 0xf6,
+ 0x09, 0x62, 0xfe, 0x83, 0x6b, 0x6f, 0x89, 0x62, 0xd2, 0x34, 0x4c, 0x1a,
+ 0x75, 0x11, 0x75, 0xfe, 0xf7, 0x5d, 0xe9, 0xa6, 0xb8, 0xd6, 0x2f, 0xfc,
+ 0xdd, 0x43, 0x86, 0x4e, 0xec, 0x1a, 0xc5, 0xee, 0xbd, 0x2b, 0x15, 0x8a,
+ 0x8b, 0xfa, 0x22, 0x78, 0x40, 0x6a, 0x17, 0x07, 0x37, 0x63, 0xd1, 0x21,
+ 0xdf, 0x61, 0x64, 0x4b, 0x17, 0x9e, 0x38, 0xeb, 0x17, 0x9e, 0x4d, 0x58,
+ 0xae, 0x8d, 0xef, 0x71, 0x05, 0xe8, 0x74, 0x6a, 0xc5, 0x86, 0xb1, 0x7e,
+ 0xcd, 0x43, 0xe2, 0x58, 0xbf, 0x41, 0xa7, 0xae, 0xe5, 0x8b, 0x8c, 0xf2,
+ 0xc5, 0xfb, 0xdf, 0x17, 0xb8, 0xb1, 0x43, 0x45, 0x56, 0xe2, 0x5d, 0x14,
+ 0xc4, 0x58, 0x71, 0x9b, 0xf0, 0xe7, 0x81, 0xf1, 0x62, 0xe1, 0xf4, 0xb1,
+ 0x47, 0x3c, 0x31, 0x15, 0x5f, 0xfc, 0x2d, 0x34, 0x0e, 0x21, 0xfc, 0x44,
+ 0xb1, 0x78, 0x53, 0xc5, 0x8b, 0xff, 0x03, 0x7f, 0xbe, 0x89, 0xfd, 0xc5,
+ 0x8b, 0xfe, 0x9c, 0xe4, 0x5f, 0x70, 0xbc, 0xb1, 0x47, 0x44, 0xc3, 0x0e,
+ 0xf1, 0x02, 0xfd, 0x0f, 0xc9, 0x1a, 0xb1, 0x7e, 0x76, 0xd4, 0xee, 0xb1,
+ 0x6e, 0xd8, 0x7a, 0x3c, 0x29, 0xb8, 0xb6, 0x58, 0xa9, 0x56, 0x80, 0x32,
+ 0x5c, 0x86, 0x53, 0xc2, 0x40, 0xe4, 0x4d, 0x0d, 0xe0, 0x42, 0x00, 0x32,
+ 0x9b, 0xcc, 0xc7, 0x58, 0xbe, 0x14, 0x42, 0x35, 0x62, 0x96, 0x2f, 0xe9,
+ 0x19, 0xe7, 0x3c, 0xb1, 0x5e, 0x37, 0x21, 0x86, 0x5f, 0xf4, 0xe8, 0x0d,
+ 0xe8, 0xec, 0xf2, 0xc5, 0xda, 0xc5, 0x8b, 0xf7, 0xdf, 0x4c, 0x75, 0x8b,
+ 0xee, 0x9f, 0xa8, 0x2c, 0x5c, 0x1e, 0xcb, 0x15, 0x87, 0xce, 0xe5, 0x00,
+ 0x25, 0xad, 0x93, 0x84, 0x88, 0x73, 0x4b, 0xff, 0x22, 0x01, 0xe1, 0x3f,
+ 0x5d, 0x1b, 0xf7, 0xda, 0xc5, 0xd8, 0x75, 0x8b, 0xda, 0xed, 0xf5, 0x8b,
+ 0xf6, 0x69, 0xa4, 0x6b, 0x15, 0x1b, 0xa2, 0x0a, 0x49, 0x18, 0x5c, 0x88,
+ 0x2f, 0x0f, 0x09, 0x62, 0xf8, 0x50, 0xf0, 0x6b, 0x17, 0xb7, 0x9d, 0x2c,
+ 0x5f, 0xfb, 0x42, 0x3f, 0xde, 0x4e, 0xc4, 0xb1, 0x7b, 0xa9, 0x8f, 0x58,
+ 0xbf, 0xc2, 0xe8, 0x7f, 0x13, 0x71, 0x62, 0xff, 0x49, 0xcb, 0x21, 0x24,
+ 0xb1, 0x5f, 0x3e, 0x7e, 0x1b, 0x5f, 0xe7, 0x23, 0x30, 0xef, 0xe5, 0x8a,
+ 0xd9, 0x35, 0xe7, 0x25, 0xd0, 0xf7, 0xcf, 0xbd, 0x08, 0x8e, 0xc4, 0x57,
+ 0xf1, 0x64, 0x45, 0x3b, 0x2c, 0x5f, 0xc4, 0x4e, 0x7f, 0x62, 0xc5, 0xe9,
+ 0xea, 0x0b, 0x17, 0x14, 0x16, 0x2e, 0x8d, 0x82, 0x58, 0xa1, 0x1b, 0x58,
+ 0xe1, 0x7a, 0x95, 0x55, 0x59, 0x1b, 0xd4, 0x7a, 0xfb, 0x17, 0x11, 0x67,
+ 0x72, 0x9d, 0xff, 0xdb, 0x89, 0x87, 0xdb, 0x07, 0xdf, 0x65, 0x1e, 0xb1,
+ 0x7c, 0xff, 0x9e, 0xcb, 0x15, 0xa3, 0xf6, 0xf2, 0x95, 0xfe, 0x9d, 0x4f,
+ 0x40, 0xd4, 0xac, 0x5f, 0xa1, 0x38, 0x08, 0xf5, 0x8b, 0xff, 0xfe, 0x9d,
+ 0x0b, 0xdc, 0x60, 0x7e, 0x70, 0x6f, 0xa8, 0x0b, 0x16, 0x2b, 0xa4, 0x48,
+ 0xf8, 0xae, 0xff, 0xb5, 0x9f, 0xc2, 0x29, 0x1a, 0xc5, 0xff, 0xfd, 0x3f,
+ 0x10, 0xde, 0x62, 0x97, 0xe0, 0x9a, 0x3b, 0x16, 0x2b, 0x48, 0x94, 0x39,
+ 0xbd, 0xe7, 0xee, 0xd9, 0x62, 0xdb, 0x2c, 0x54, 0x9b, 0x42, 0x21, 0xbd,
+ 0xf1, 0x47, 0xac, 0x5e, 0x06, 0x7d, 0x62, 0xfe, 0x29, 0xf7, 0xda, 0x0b,
+ 0x15, 0x27, 0xd7, 0xd1, 0x0c, 0x43, 0xb7, 0xbd, 0x3a, 0x58, 0xa9, 0x55,
+ 0x9b, 0xb1, 0x16, 0x43, 0x15, 0xe1, 0x71, 0x12, 0xbb, 0x42, 0x28, 0x46,
+ 0x17, 0x36, 0xeb, 0x17, 0xff, 0xff, 0xb0, 0x89, 0xa1, 0xf7, 0x30, 0x3d,
+ 0x6a, 0x60, 0xfe, 0x7d, 0x30, 0x16, 0x2f, 0xc3, 0x16, 0xc1, 0x9d, 0x62,
+ 0xff, 0xfc, 0x52, 0x3e, 0x09, 0x9e, 0x0e, 0x0e, 0x0b, 0x8b, 0x17, 0xf6,
+ 0x7b, 0xef, 0xd4, 0x16, 0x2a, 0x24, 0x42, 0x12, 0xad, 0x6e, 0x8d, 0x3f,
+ 0xc2, 0xc2, 0xfe, 0xeb, 0x98, 0x76, 0xe2, 0xc5, 0xfd, 0x84, 0x4d, 0xed,
+ 0x96, 0x2f, 0x87, 0x9f, 0x95, 0x8b, 0x69, 0x62, 0xfd, 0xb6, 0xa7, 0xad,
+ 0x2c, 0x56, 0xc6, 0xf7, 0x04, 0xaf, 0xff, 0xef, 0x18, 0x39, 0x6d, 0x61,
+ 0x00, 0xce, 0x7b, 0x9d, 0x2c, 0x5f, 0x6b, 0x60, 0x79, 0x62, 0xff, 0x37,
+ 0x5a, 0x98, 0x36, 0x96, 0x2f, 0xe1, 0xe4, 0x24, 0x1c, 0x58, 0xac, 0x47,
+ 0x33, 0xaf, 0x91, 0x28, 0x8d, 0x2a, 0x55, 0xc3, 0xc0, 0x63, 0x23, 0x4a,
+ 0x72, 0x9f, 0x97, 0xb1, 0x69, 0x2f, 0xf2, 0x30, 0x7b, 0xff, 0xfa, 0x35,
+ 0x0a, 0x34, 0x93, 0xf8, 0xcd, 0xb3, 0xe6, 0x19, 0xf8, 0xe5, 0x8b, 0xfb,
+ 0xef, 0xe9, 0x20, 0x2c, 0x5f, 0x7f, 0xb3, 0xe9, 0x62, 0xa4, 0xf4, 0xb0,
+ 0xb6, 0xff, 0xef, 0xef, 0xf7, 0xeb, 0xd8, 0x76, 0xe2, 0xc5, 0xe9, 0x2d,
+ 0x96, 0x2f, 0x7d, 0xbc, 0xb1, 0x58, 0x88, 0x1f, 0xa3, 0x86, 0x3b, 0x7e,
+ 0x8d, 0xa3, 0x5c, 0x6b, 0x8d, 0x7d, 0xcb, 0x17, 0x4f, 0x96, 0x2f, 0x14,
+ 0x6f, 0xd9, 0x62, 0x8e, 0x6e, 0xfc, 0x2f, 0x7f, 0x66, 0x73, 0x3a, 0xf2,
+ 0xc5, 0xc2, 0x8f, 0x58, 0xb6, 0xc3, 0x3c, 0x93, 0x97, 0x5f, 0xbc, 0x78,
+ 0x88, 0x6b, 0x17, 0xdf, 0x0e, 0x39, 0x96, 0x2a, 0x36, 0x4d, 0x8f, 0x1f,
+ 0xd9, 0xa8, 0x8a, 0x44, 0x55, 0x7d, 0xce, 0x39, 0xd6, 0x2f, 0xfe, 0xfb,
+ 0xf4, 0x14, 0x9f, 0xf2, 0xf0, 0x58, 0xa8, 0x8f, 0xa7, 0xe4, 0x77, 0x85,
+ 0xa3, 0x56, 0x2e, 0x17, 0x4b, 0x15, 0x03, 0x71, 0xc1, 0xfb, 0xfd, 0x14,
+ 0x1b, 0x5b, 0x7c, 0x4b, 0x17, 0xff, 0xdb, 0x04, 0xd0, 0xe7, 0x33, 0x41,
+ 0x4e, 0x8d, 0x58, 0xb1, 0x2c, 0x5f, 0xcd, 0xee, 0x6d, 0x81, 0x2c, 0x5f,
+ 0xff, 0xcf, 0xc6, 0x87, 0x1f, 0xb7, 0x04, 0xcf, 0x07, 0xec, 0xb1, 0x70,
+ 0x61, 0xac, 0x56, 0x27, 0x83, 0x12, 0xd9, 0xc8, 0x58, 0xdc, 0x0a, 0xa4,
+ 0x23, 0xe3, 0x00, 0xd7, 0xaf, 0xb4, 0x00, 0x4a, 0xc5, 0xf8, 0x2c, 0x1b,
+ 0x41, 0x62, 0xb0, 0xf3, 0x1c, 0x8e, 0xe8, 0xe8, 0xc8, 0xdd, 0xd7, 0xce,
+ 0x77, 0x85, 0x1d, 0xe9, 0x34, 0x68, 0x3b, 0xdf, 0x70, 0x9e, 0x8d, 0x50,
+ 0xa4, 0x98, 0xe2, 0x36, 0x65, 0x84, 0x63, 0x63, 0x8e, 0x77, 0x27, 0x8a,
+ 0x4d, 0x8d, 0x43, 0x79, 0x4c, 0x7d, 0x42, 0xbd, 0xe3, 0xbd, 0x8f, 0x72,
+ 0x8a, 0x37, 0x9d, 0x4a, 0xdc, 0x3b, 0x77, 0xe5, 0xcf, 0xb4, 0xa0, 0x80,
+ 0x43, 0x6c, 0xa5, 0x74, 0xf2, 0x5d, 0x27, 0xa5, 0xfd, 0x09, 0xeb, 0xb4,
+ 0x30, 0x82, 0x85, 0x0c, 0x74, 0x72, 0x61, 0xca, 0x77, 0xee, 0x85, 0xed,
+ 0xfe, 0x16, 0xd1, 0x9d, 0xdd, 0xce, 0x6a, 0xc5, 0x4c, 0x29, 0x84, 0xf6,
+ 0x8c, 0x02, 0x17, 0xa1, 0xbc, 0x39, 0x57, 0xef, 0x4b, 0xba, 0x8a, 0x57,
+ 0x19, 0xd3, 0xbf, 0x4d, 0xe1, 0xf4, 0x36, 0xc5, 0x18, 0xa8, 0x76, 0xc0,
+ 0x2f, 0xba, 0x53, 0x7d, 0x4d, 0x6c, 0x8c, 0xbf, 0xb5, 0x34, 0x3e, 0x15,
+ 0xd5, 0x38, 0xeb, 0xe1, 0x4c, 0xd6, 0x82, 0x90, 0x6d, 0x66, 0x13, 0xbe,
+ 0x70, 0xc4, 0xbd, 0x5e, 0xff, 0x93, 0xda, 0xc7, 0xa8, 0xf9, 0x54, 0x91,
+ 0x66, 0x1d, 0x87, 0xac, 0xce, 0x3e, 0x0f, 0xbf, 0x17, 0xad, 0xfb, 0x7a,
+ 0xc0, 0xd9, 0x85, 0x40, 0x82, 0xda, 0x27, 0x77, 0xf3, 0xbd, 0xe5, 0x8a,
+ 0x7c, 0x9e, 0x5f, 0xbf, 0x77, 0xb3, 0xe2, 0x48, 0x16, 0x61, 0x42, 0xbd,
+ 0xad, 0x8b, 0xe8, 0x56, 0x8b, 0xf6, 0x3a, 0xb2, 0x3c, 0x0e, 0xd2, 0x7e,
+ 0x77, 0x62, 0xa2, 0x6a, 0x80,
};
-static const unsigned kPreloadedHSTSBits = 1312341;
-
-static const unsigned kHSTSRootPosition = 1311675;
+static const unsigned kPreloadedHSTSBits = 1489857;
+static const unsigned kHSTSRootPosition = 1489184;
#endif // NET_HTTP_TRANSPORT_SECURITY_STATE_STATIC_H_
diff --git a/chromium/net/http/transport_security_state_static.json b/chromium/net/http/transport_security_state_static.json
index 367ef13924c..2deebb28f5f 100644
--- a/chromium/net/http/transport_security_state_static.json
+++ b/chromium/net/http/transport_security_state_static.json
@@ -283,6 +283,7 @@
{ "name": "mail-settings.google.com", "include_subdomains": true, "mode": "force-https", "pins": "google" },
{ "name": "meet.google.com", "include_subdomains": true, "mode": "force-https", "pins": "google" },
{ "name": "myaccount.google.com", "include_subdomains": true, "mode": "force-https", "pins": "google" },
+ { "name": "myactivity.google.com", "include_subdomains": true, "mode": "force-https", "pins": "google" },
{ "name": "passwords.google.com", "include_subdomains": true, "mode": "force-https", "pins": "google" },
{ "name": "pixel.google.com", "include_subdomains": true, "mode": "force-https", "pins": "google" },
{ "name": "play.google.com", "include_subdomains": true, "mode": "force-https", "pins": "google" },
@@ -309,11 +310,15 @@
{ "name": "code.google.com", "include_subdomains": true, "mode": "force-https", "pins": "google" },
{ "name": "codereview.appspot.com", "include_subdomains": true, "mode": "force-https", "pins": "google" },
{ "name": "codereview.chromium.org", "include_subdomains": true, "mode": "force-https", "pins": "google" },
+ { "name": "crbug.com", "include_subdomains": true, "mode": "force-https", "pins": "google" },
+ { "name": "crosbug.com", "include_subdomains": true, "mode": "force-https", "pins": "google" },
+ { "name": "crrev.com", "include_subdomains": true, "mode": "force-https", "pins": "google" },
{ "name": "dl.google.com", "include_subdomains": true, "mode": "force-https", "pins": "google" },
{ "name": "drive.google.com", "include_subdomains": true, "mode": "force-https", "pins": "google" },
{ "name": "firebaseio.com", "include_subdomains": true, "mode": "force-https", "pins": "google" },
{ "name": "g4w.co", "include_subdomains": true, "mode": "force-https", "pins": "google" },
{ "name": "gmail.com", "mode": "force-https", "pins": "google" },
+ { "name": "goo.gl", "include_subdomains": true, "mode": "force-https", "pins": "google" },
{ "name": "googlecode.com", "include_subdomains": true, "pins": "google" },
{ "name": "googlemail.com", "mode": "force-https", "pins": "google" },
{ "name": "googleplex.com", "include_subdomains": true, "mode": "force-https", "pins": "google" },
@@ -589,7 +594,6 @@
{ "name": "google.vu", "include_subdomains": true, "pins": "google" },
{ "name": "googleweblight.com", "include_subdomains": true, "pins": "google" },
{ "name": "google.ws", "include_subdomains": true, "pins": "google" },
- { "name": "goo.gl", "include_subdomains": true, "pins": "google" },
{ "name": "gstatic.com", "include_subdomains": true, "pins": "google" },
{ "name": "static.googleadsserving.cn", "include_subdomains": true, "pins": "google" },
{ "name": "urchin.com", "include_subdomains": true, "pins": "google" },
@@ -906,7 +910,6 @@
{ "name": "mobile.usaa.com", "mode": "force-https" },
{ "name": "subrosa.io", "include_subdomains": true, "mode": "force-https" },
{ "name": "detectify.com", "mode": "force-https" },
- { "name": "crbug.com", "include_subdomains": true, "mode": "force-https" },
{ "name": "manageprojects.com", "include_subdomains": true, "mode": "force-https" },
{ "name": "tinfoilsecurity.com", "mode": "force-https" },
{ "name": "www.tinfoilsecurity.com", "mode": "force-https" },
@@ -1454,7 +1457,6 @@
{ "name": "fundingempire.com", "include_subdomains": true, "mode": "force-https" },
{ "name": "heid.ws", "include_subdomains": true, "mode": "force-https" },
{ "name": "ironfistdesign.com", "include_subdomains": true, "mode": "force-https" },
- { "name": "kinogb.net", "include_subdomains": true, "mode": "force-https" },
{ "name": "ljs.io", "include_subdomains": true, "mode": "force-https" },
{ "name": "lovelycorral.com", "include_subdomains": true, "mode": "force-https" },
{ "name": "megashur.se", "include_subdomains": true, "mode": "force-https" },
@@ -3200,7 +3202,6 @@
{ "name": "smiatek.name", "include_subdomains": true, "mode": "force-https" },
{ "name": "korni22.org", "include_subdomains": true, "mode": "force-https" },
{ "name": "student.andover.edu", "include_subdomains": true, "mode": "force-https" },
- { "name": "0.me.uk", "include_subdomains": true, "mode": "force-https" },
{ "name": "agilebits.net", "include_subdomains": true, "mode": "force-https" },
{ "name": "alenan.org", "include_subdomains": true, "mode": "force-https" },
{ "name": "amisharingstuff.com", "include_subdomains": true, "mode": "force-https" },
@@ -4897,7 +4898,6 @@
{ "name": "chic-leather.com", "include_subdomains": true, "mode": "force-https" },
{ "name": "chijiokeindustries.co.uk", "include_subdomains": true, "mode": "force-https" },
{ "name": "chun.pro", "include_subdomains": true, "mode": "force-https" },
- { "name": "cip.md", "include_subdomains": true, "mode": "force-https" },
{ "name": "citiagent.cz", "include_subdomains": true, "mode": "force-https" },
{ "name": "cmdline.org", "include_subdomains": true, "mode": "force-https" },
{ "name": "cojo.eu", "include_subdomains": true, "mode": "force-https" },
@@ -5284,7 +5284,6 @@
{ "name": "mcpart.land", "include_subdomains": true, "mode": "force-https" },
{ "name": "medirich.co", "include_subdomains": true, "mode": "force-https" },
{ "name": "medo64.com", "include_subdomains": true, "mode": "force-https" },
- { "name": "medwayindia.com", "include_subdomains": true, "mode": "force-https" },
{ "name": "meizufans.eu", "include_subdomains": true, "mode": "force-https" },
{ "name": "metebalci.com", "include_subdomains": true, "mode": "force-https" },
{ "name": "michaelcullen.name", "include_subdomains": true, "mode": "force-https" },
@@ -6378,7 +6377,6 @@
{ "name": "jeffcasavant.com", "include_subdomains": true, "mode": "force-https" },
{ "name": "jeremiahbenes.com", "include_subdomains": true, "mode": "force-https" },
{ "name": "jeugdkans.nl", "include_subdomains": true, "mode": "force-https" },
- { "name": "jf.duckdns.org", "include_subdomains": true, "mode": "force-https" },
{ "name": "jhejderup.me", "include_subdomains": true, "mode": "force-https" },
{ "name": "jimas.eu", "include_subdomains": true, "mode": "force-https" },
{ "name": "jka.io", "include_subdomains": true, "mode": "force-https" },
@@ -7223,7 +7221,6 @@
{ "name": "goben.ch", "include_subdomains": true, "mode": "force-https" },
{ "name": "gogenenglish.com", "include_subdomains": true, "mode": "force-https" },
{ "name": "goldpreisfinder.at", "include_subdomains": true, "mode": "force-https" },
- { "name": "gooby.co", "include_subdomains": true, "mode": "force-https" },
{ "name": "gordonobrecht.com", "include_subdomains": true, "mode": "force-https" },
{ "name": "grafmurr.de", "include_subdomains": true, "mode": "force-https" },
{ "name": "gritte.ch", "include_subdomains": true, "mode": "force-https" },
@@ -7651,7 +7648,6 @@
{ "name": "webstore.be", "include_subdomains": true, "mode": "force-https" },
{ "name": "weddingenvelopes.co.uk", "include_subdomains": true, "mode": "force-https" },
{ "name": "wer-kommt-her.de", "include_subdomains": true, "mode": "force-https" },
- { "name": "whiskeyriver.co.uk", "include_subdomains": true, "mode": "force-https" },
{ "name": "whisp.ly", "include_subdomains": true, "mode": "force-https" },
{ "name": "whoshotya.de", "include_subdomains": true, "mode": "force-https" },
{ "name": "wikimilk.org", "include_subdomains": true, "mode": "force-https" },
@@ -8783,7 +8779,9 @@
{ "name": "winebid.com", "include_subdomains": true, "mode": "force-https" },
// Entries submitted through hstspreload.appspot.com in Chrome 51 or later.
- // START OF BULK ADDITIONS
+ // These entries are subject to the continued requirements documented at
+ // https://hstspreload.org/#continued-requirements
+ // START OF BULK ENTRIES
{ "name": "050media.nl", "include_subdomains": true, "mode": "force-https" },
{ "name": "0x.sk", "include_subdomains": true, "mode": "force-https" },
{ "name": "0x44.net", "include_subdomains": true, "mode": "force-https" },
@@ -10006,8 +10004,6 @@
{ "name": "jirav.com", "include_subdomains": true, "mode": "force-https" },
{ "name": "jobflyapp.com", "include_subdomains": true, "mode": "force-https" },
{ "name": "jobmedic.com", "include_subdomains": true, "mode": "force-https" },
- { "name": "johndong.net", "include_subdomains": true, "mode": "force-https" },
- { "name": "johners.tech", "include_subdomains": true, "mode": "force-https" },
{ "name": "jokewignand.nl", "include_subdomains": true, "mode": "force-https" },
{ "name": "jonnichols.info", "include_subdomains": true, "mode": "force-https" },
{ "name": "jooto.com", "include_subdomains": true, "mode": "force-https" },
@@ -10102,7 +10098,6 @@
{ "name": "komiksbaza.pl", "include_subdomains": true, "mode": "force-https" },
{ "name": "kompetenzwerft.de", "include_subdomains": true, "mode": "force-https" },
{ "name": "kon-sil.de", "include_subdomains": true, "mode": "force-https" },
- { "name": "koophetlokaal.nl", "include_subdomains": true, "mode": "force-https" },
{ "name": "koretech.nl", "include_subdomains": true, "mode": "force-https" },
{ "name": "kozuch.biz", "include_subdomains": true, "mode": "force-https" },
{ "name": "kraynik.com", "include_subdomains": true, "mode": "force-https" },
@@ -10393,7 +10388,6 @@
{ "name": "mytc.fr", "include_subdomains": true, "mode": "force-https" },
{ "name": "mythslegendscollection.com", "include_subdomains": true, "mode": "force-https" },
{ "name": "mytripcar.co.uk", "include_subdomains": true, "mode": "force-https" },
- { "name": "mytripcar.com", "include_subdomains": true, "mode": "force-https" },
{ "name": "mytripcar.de", "include_subdomains": true, "mode": "force-https" },
{ "name": "mytripcar.es", "include_subdomains": true, "mode": "force-https" },
{ "name": "myworth.com.au", "include_subdomains": true, "mode": "force-https" },
@@ -10825,7 +10819,6 @@
{ "name": "ryankearney.com", "include_subdomains": true, "mode": "force-https" },
{ "name": "s-cubed.net", "include_subdomains": true, "mode": "force-https" },
{ "name": "saccani.net", "include_subdomains": true, "mode": "force-https" },
- { "name": "safic.net", "include_subdomains": true, "mode": "force-https" },
{ "name": "salmo23.com.br", "include_subdomains": true, "mode": "force-https" },
{ "name": "salmododia.net", "include_subdomains": true, "mode": "force-https" },
{ "name": "salmos91.com", "include_subdomains": true, "mode": "force-https" },
@@ -12549,7 +12542,6 @@
{ "name": "state-sponsored-actors.net", "include_subdomains": true, "mode": "force-https" },
{ "name": "stargatepartners.com", "include_subdomains": true, "mode": "force-https" },
{ "name": "stayokhotelscdc-mailing.com", "include_subdomains": true, "mode": "force-https" },
- { "name": "ssersay.com", "include_subdomains": true, "mode": "force-https" },
{ "name": "stevenhumphrey.uk", "include_subdomains": true, "mode": "force-https" },
{ "name": "stig.io", "include_subdomains": true, "mode": "force-https" },
{ "name": "stillblackhat.id", "include_subdomains": true, "mode": "force-https" },
@@ -13145,7 +13137,6 @@
{ "name": "kircp.com", "include_subdomains": true, "mode": "force-https" },
{ "name": "kitk.at", "include_subdomains": true, "mode": "force-https" },
{ "name": "kjarni.cc", "include_subdomains": true, "mode": "force-https" },
- { "name": "kkaufmann.de", "include_subdomains": true, "mode": "force-https" },
{ "name": "kkovacs.eu", "include_subdomains": true, "mode": "force-https" },
{ "name": "kkzxak47.com", "include_subdomains": true, "mode": "force-https" },
{ "name": "kngkng.com", "include_subdomains": true, "mode": "force-https" },
@@ -13275,7 +13266,6 @@
{ "name": "online.marketing", "include_subdomains": true, "mode": "force-https" },
{ "name": "onlinemarketingtraining.co.uk", "include_subdomains": true, "mode": "force-https" },
{ "name": "onviga.de", "include_subdomains": true, "mode": "force-https" },
- { "name": "open-coding.org", "include_subdomains": true, "mode": "force-https" },
{ "name": "open-infrastructure.net", "include_subdomains": true, "mode": "force-https" },
{ "name": "openrtv.com", "include_subdomains": true, "mode": "force-https" },
{ "name": "oses.mobi", "include_subdomains": true, "mode": "force-https" },
@@ -14181,7 +14171,6 @@
{ "name": "ginkel.com", "include_subdomains": true, "mode": "force-https" },
{ "name": "gis3m.org", "include_subdomains": true, "mode": "force-https" },
{ "name": "globalonetechnology.com", "include_subdomains": true, "mode": "force-https" },
- { "name": "glopoi.com", "include_subdomains": true, "mode": "force-https" },
{ "name": "gmbh-kiekin.de", "include_subdomains": true, "mode": "force-https" },
{ "name": "gnetion.com", "include_subdomains": true, "mode": "force-https" },
{ "name": "gnunet.org", "include_subdomains": true, "mode": "force-https" },
@@ -14577,7 +14566,6 @@
{ "name": "meikan.moe", "include_subdomains": true, "mode": "force-https" },
{ "name": "melted.me", "include_subdomains": true, "mode": "force-https" },
{ "name": "memeblast.ninja", "include_subdomains": true, "mode": "force-https" },
- { "name": "mencap.org.uk", "include_subdomains": true, "mode": "force-https" },
{ "name": "mensmaximus.de", "include_subdomains": true, "mode": "force-https" },
{ "name": "meshok.ru", "include_subdomains": true, "mode": "force-https" },
{ "name": "metagrader.com", "include_subdomains": true, "mode": "force-https" },
@@ -15161,7 +15149,6 @@
{ "name": "todamateria.com.br", "include_subdomains": true, "mode": "force-https" },
{ "name": "tokenloan.com", "include_subdomains": true, "mode": "force-https" },
{ "name": "tokotamz.net", "include_subdomains": true, "mode": "force-https" },
- { "name": "tokyopopline.com", "include_subdomains": true, "mode": "force-https" },
{ "name": "toleressea.fr", "include_subdomains": true, "mode": "force-https" },
{ "name": "toles-sur-mesure.fr", "include_subdomains": true, "mode": "force-https" },
{ "name": "tomlankhorst.nl", "include_subdomains": true, "mode": "force-https" },
@@ -15717,7 +15704,6 @@
{ "name": "cuvva.us", "include_subdomains": true, "mode": "force-https" },
{ "name": "convert.im", "include_subdomains": true, "mode": "force-https" },
{ "name": "cuvva.it", "include_subdomains": true, "mode": "force-https" },
- { "name": "builtritetrailerplans.com", "include_subdomains": true, "mode": "force-https" },
{ "name": "curtis-smith.me.uk", "include_subdomains": true, "mode": "force-https" },
{ "name": "crvv.me", "include_subdomains": true, "mode": "force-https" },
{ "name": "demuzere.org", "include_subdomains": true, "mode": "force-https" },
@@ -16084,7 +16070,6 @@
{ "name": "idcrane.com", "include_subdomains": true, "mode": "force-https" },
{ "name": "fuckav.ru", "include_subdomains": true, "mode": "force-https" },
{ "name": "hrfhomelottery.com", "include_subdomains": true, "mode": "force-https" },
- { "name": "hzsh.xyz", "include_subdomains": true, "mode": "force-https" },
{ "name": "hintergrundbewegung.de", "include_subdomains": true, "mode": "force-https" },
{ "name": "hiverlune.net", "include_subdomains": true, "mode": "force-https" },
{ "name": "httpswatch.ca", "include_subdomains": true, "mode": "force-https" },
@@ -16461,7 +16446,6 @@
{ "name": "multimarques.com", "include_subdomains": true, "mode": "force-https" },
{ "name": "mainframeserver.space", "include_subdomains": true, "mode": "force-https" },
{ "name": "miyoshi-kikaku.co.jp", "include_subdomains": true, "mode": "force-https" },
- { "name": "mindwerks.net", "include_subdomains": true, "mode": "force-https" },
{ "name": "mikek.work", "include_subdomains": true, "mode": "force-https" },
{ "name": "myartsjournal.com", "include_subdomains": true, "mode": "force-https" },
{ "name": "miyatore.com", "include_subdomains": true, "mode": "force-https" },
@@ -17467,7 +17451,6 @@
{ "name": "bruckner.li", "include_subdomains": true, "mode": "force-https" },
{ "name": "bxp40.at", "include_subdomains": true, "mode": "force-https" },
{ "name": "charr.xyz", "include_subdomains": true, "mode": "force-https" },
- { "name": "cgat.no", "include_subdomains": true, "mode": "force-https" },
{ "name": "chopperforums.com", "include_subdomains": true, "mode": "force-https" },
{ "name": "caringladies.org", "include_subdomains": true, "mode": "force-https" },
{ "name": "chrisebert.net", "include_subdomains": true, "mode": "force-https" },
@@ -17954,7 +17937,6 @@
{ "name": "kevinratcliff.com", "include_subdomains": true, "mode": "force-https" },
{ "name": "iora.fr", "include_subdomains": true, "mode": "force-https" },
{ "name": "karhm.com", "include_subdomains": true, "mode": "force-https" },
- { "name": "jf-projects.de", "include_subdomains": true, "mode": "force-https" },
{ "name": "jasonian-photo.com", "include_subdomains": true, "mode": "force-https" },
{ "name": "kaffeekrone.de", "include_subdomains": true, "mode": "force-https" },
{ "name": "kenny-peck.com", "include_subdomains": true, "mode": "force-https" },
@@ -18615,7 +18597,6 @@
{ "name": "velen.io", "include_subdomains": true, "mode": "force-https" },
{ "name": "ureka.org", "include_subdomains": true, "mode": "force-https" },
{ "name": "ukk.dk", "include_subdomains": true, "mode": "force-https" },
- { "name": "usap.gov", "include_subdomains": true, "mode": "force-https" },
{ "name": "vd42.net", "include_subdomains": true, "mode": "force-https" },
{ "name": "thefreebirds.in", "include_subdomains": true, "mode": "force-https" },
{ "name": "tokototech.com", "include_subdomains": true, "mode": "force-https" },
@@ -18698,7 +18679,6 @@
{ "name": "veg-leiden.nl", "include_subdomains": true, "mode": "force-https" },
{ "name": "xn--ruanmller-u9a.com", "include_subdomains": true, "mode": "force-https" },
{ "name": "vodpay.com", "include_subdomains": true, "mode": "force-https" },
- { "name": "x-case.de", "include_subdomains": true, "mode": "force-https" },
{ "name": "yhrd.org", "include_subdomains": true, "mode": "force-https" },
{ "name": "yesiammaisey.me", "include_subdomains": true, "mode": "force-https" },
{ "name": "zenhaiku.com", "include_subdomains": true, "mode": "force-https" },
@@ -18746,11 +18726,2519 @@
{ "name": "rijk-catering.nl", "include_subdomains": true, "mode": "force-https" },
{ "name": "rvsbevestigingen.nl", "include_subdomains": true, "mode": "force-https" },
{ "name": "yhb.io", "include_subdomains": true, "mode": "force-https" },
- // END OF BULK ADDITIONS
+ { "name": "accudraftpaintbooths.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "afinadoronline.com.br", "include_subdomains": true, "mode": "force-https" },
+ { "name": "441jj.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "acrossgw.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "advanced-scribes.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "21lg.co", "include_subdomains": true, "mode": "force-https" },
+ { "name": "439191.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "adequatetechnology.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "abe.cloud", "include_subdomains": true, "mode": "force-https" },
+ { "name": "afva.net", "include_subdomains": true, "mode": "force-https" },
+ { "name": "accelerateyourworld.org", "include_subdomains": true, "mode": "force-https" },
+ { "name": "21stnc.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "1600esplanade.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "airpbx.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "9yw.me", "include_subdomains": true, "mode": "force-https" },
+ { "name": "a-rickroll-n.pw", "include_subdomains": true, "mode": "force-https" },
+ { "name": "airedaleterrier.com.br", "include_subdomains": true, "mode": "force-https" },
+ { "name": "aging.gov", "include_subdomains": true, "mode": "force-https" },
+ { "name": "0100dev.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "0100dev.nl", "include_subdomains": true, "mode": "force-https" },
+ { "name": "abolitionist.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "10000v.ru", "include_subdomains": true, "mode": "force-https" },
+ { "name": "abolitionistsociety.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "a2c-co.net", "include_subdomains": true, "mode": "force-https" },
+ { "name": "accordiondoor.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "adelinlydia-coach.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "agfmedia.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "abulanov.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "398.info", "include_subdomains": true, "mode": "force-https" },
+ { "name": "alertaenlinea.gov", "include_subdomains": true, "mode": "force-https" },
+ { "name": "39sihu.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "2600edinburgh.org", "include_subdomains": true, "mode": "force-https" },
+ { "name": "1kando.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "2pay.fr", "include_subdomains": true, "mode": "force-https" },
+ { "name": "0ik.de", "include_subdomains": true, "mode": "force-https" },
+ { "name": "0xda.de", "include_subdomains": true, "mode": "force-https" },
+ { "name": "adhesivelaundry.co.uk", "include_subdomains": true, "mode": "force-https" },
+ { "name": "abbruch-star.de", "include_subdomains": true, "mode": "force-https" },
+ { "name": "040fit.nl", "include_subdomains": true, "mode": "force-https" },
+ { "name": "aduedu.de", "include_subdomains": true, "mode": "force-https" },
+ { "name": "8ox.ru", "include_subdomains": true, "mode": "force-https" },
+ { "name": "adindexr.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "a-allard.be", "include_subdomains": true, "mode": "force-https" },
+ { "name": "acwcerts.co.uk", "include_subdomains": true, "mode": "force-https" },
+ { "name": "aidikofflaw.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "abenteuer-ahnenforschung.de", "include_subdomains": true, "mode": "force-https" },
+ { "name": "abt.de", "include_subdomains": true, "mode": "force-https" },
+ { "name": "11urss.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "246060.ru", "include_subdomains": true, "mode": "force-https" },
+ { "name": "2acbi-asso.fr", "include_subdomains": true, "mode": "force-https" },
+ { "name": "accessmy.net", "include_subdomains": true, "mode": "force-https" },
+ { "name": "aamwa.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "aitosoftware.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "agenda21senden.de", "include_subdomains": true, "mode": "force-https" },
+ { "name": "alboweb.nl", "include_subdomains": true, "mode": "force-https" },
+ { "name": "adrinet.tk", "include_subdomains": true, "mode": "force-https" },
+ { "name": "1000serien.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "aimotive.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "adhosting.nl", "include_subdomains": true, "mode": "force-https" },
+ { "name": "algarmatic-automatismos.pt", "include_subdomains": true, "mode": "force-https" },
+ { "name": "15-10.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "abborsjo.fi", "include_subdomains": true, "mode": "force-https" },
+ { "name": "actu-medias.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "amcfirst.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "amimoto-ami.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "amphetamines.org", "include_subdomains": true, "mode": "force-https" },
+ { "name": "amartinz.at", "include_subdomains": true, "mode": "force-https" },
+ { "name": "andrewdaws.tv", "include_subdomains": true, "mode": "force-https" },
+ { "name": "2intermediate.co.uk", "include_subdomains": true, "mode": "force-https" },
+ { "name": "amazingfloridagulfhomes.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "alternative.bike", "include_subdomains": true, "mode": "force-https" },
+ { "name": "analyticsinmotion.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "androticsdirect.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "alfa-tech.su", "include_subdomains": true, "mode": "force-https" },
+ { "name": "adrianseo.ro", "include_subdomains": true, "mode": "force-https" },
+ { "name": "alfa24.pro", "include_subdomains": true, "mode": "force-https" },
+ { "name": "anotherfatgeek.net", "include_subdomains": true, "mode": "force-https" },
+ { "name": "alisonisrealestate.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "animal-rights.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "alexdaniel.org", "include_subdomains": true, "mode": "force-https" },
+ { "name": "ankiweb.net", "include_subdomains": true, "mode": "force-https" },
+ { "name": "alluvion.studio", "include_subdomains": true, "mode": "force-https" },
+ { "name": "apple.ax", "include_subdomains": true, "mode": "force-https" },
+ { "name": "af-fotografie.net", "include_subdomains": true, "mode": "force-https" },
+ { "name": "alt33c3.org", "include_subdomains": true, "mode": "force-https" },
+ { "name": "100onrainkajino.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "andymoore.info", "include_subdomains": true, "mode": "force-https" },
+ { "name": "anivar.net", "include_subdomains": true, "mode": "force-https" },
+ { "name": "amphibo.ly", "include_subdomains": true, "mode": "force-https" },
+ { "name": "amsportuk.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "armandsdiscount.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "alrait.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "agatheetraphael.fr", "include_subdomains": true, "mode": "force-https" },
+ { "name": "arawaza.info", "include_subdomains": true, "mode": "force-https" },
+ { "name": "arigato-java.download", "include_subdomains": true, "mode": "force-https" },
+ { "name": "abstraction21.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "als-hardware.co.za", "include_subdomains": true, "mode": "force-https" },
+ { "name": "andrezadnik.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "allo-symo.fr", "include_subdomains": true, "mode": "force-https" },
+ { "name": "anotherchef.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "altkremsmuensterer.at", "include_subdomains": true, "mode": "force-https" },
+ { "name": "0o0.ooo", "include_subdomains": true, "mode": "force-https" },
+ { "name": "anacruz.es", "include_subdomains": true, "mode": "force-https" },
+ { "name": "agentseeker.ca", "include_subdomains": true, "mode": "force-https" },
+ { "name": "artiming.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "asuhe.win", "include_subdomains": true, "mode": "force-https" },
+ { "name": "ami-de-bastanes.fr", "include_subdomains": true, "mode": "force-https" },
+ { "name": "apbox.de", "include_subdomains": true, "mode": "force-https" },
+ { "name": "anecuni-rec.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "anti-radar.org", "include_subdomains": true, "mode": "force-https" },
+ { "name": "approvedtreecare.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "amandaonishi.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "aranel.me", "include_subdomains": true, "mode": "force-https" },
+ { "name": "andreasfritz-fotografie.de", "include_subdomains": true, "mode": "force-https" },
+ { "name": "arawaza.biz", "include_subdomains": true, "mode": "force-https" },
+ { "name": "allrealty.co.za", "include_subdomains": true, "mode": "force-https" },
+ { "name": "alexey-shamara.ru", "include_subdomains": true, "mode": "force-https" },
+ { "name": "arbeitslosenverwaltung.de", "include_subdomains": true, "mode": "force-https" },
+ { "name": "alupferd.de", "include_subdomains": true, "mode": "force-https" },
+ { "name": "amyharrisonline.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "anecuni-club.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "anvartay.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "ans-delft.nl", "include_subdomains": true, "mode": "force-https" },
+ { "name": "aov.io", "include_subdomains": true, "mode": "force-https" },
+ { "name": "anita-mukorom.hu", "include_subdomains": true, "mode": "force-https" },
+ { "name": "arewedubstepyet.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "antikvariat.ru", "include_subdomains": true, "mode": "force-https" },
+ { "name": "5h0r7.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "arados.de", "include_subdomains": true, "mode": "force-https" },
+ { "name": "artlifeisgood.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "aschaefer.net", "include_subdomains": true, "mode": "force-https" },
+ { "name": "aluminium-scaffolding.co.uk", "include_subdomains": true, "mode": "force-https" },
+ { "name": "asafilm.co", "include_subdomains": true, "mode": "force-https" },
+ { "name": "andreaseracleous.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "aparaatti.org", "include_subdomains": true, "mode": "force-https" },
+ { "name": "ariacreations.net", "include_subdomains": true, "mode": "force-https" },
+ { "name": "assurancesmons.be", "include_subdomains": true, "mode": "force-https" },
+ { "name": "askkaren.gov", "include_subdomains": true, "mode": "force-https" },
+ { "name": "asuhe.xyz", "include_subdomains": true, "mode": "force-https" },
+ { "name": "0day.su", "include_subdomains": true, "mode": "force-https" },
+ { "name": "arab.dating", "include_subdomains": true, "mode": "force-https" },
+ { "name": "atom86.net", "include_subdomains": true, "mode": "force-https" },
+ { "name": "anchorgrounds.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "arnaudb.net", "include_subdomains": true, "mode": "force-https" },
+ { "name": "atlseccon.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "autoparts.sh", "include_subdomains": true, "mode": "force-https" },
+ { "name": "aucubin.de", "include_subdomains": true, "mode": "force-https" },
+ { "name": "artisense.de", "include_subdomains": true, "mode": "force-https" },
+ { "name": "ascgathering.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "artlego.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "24sihu.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "axg.io", "include_subdomains": true, "mode": "force-https" },
+ { "name": "38sihu.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "architectdirect.nl", "include_subdomains": true, "mode": "force-https" },
+ { "name": "arkaic.dyndns.org", "include_subdomains": true, "mode": "force-https" },
+ { "name": "astrea-voetbal-groningen.nl", "include_subdomains": true, "mode": "force-https" },
+ { "name": "artofeyes.nl", "include_subdomains": true, "mode": "force-https" },
+ { "name": "afiru.net", "include_subdomains": true, "mode": "force-https" },
+ { "name": "avepol.cz", "include_subdomains": true, "mode": "force-https" },
+ { "name": "asadzulfahri.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "asia.dating", "include_subdomains": true, "mode": "force-https" },
+ { "name": "architecte-interieur.be", "include_subdomains": true, "mode": "force-https" },
+ { "name": "aubio.org", "include_subdomains": true, "mode": "force-https" },
+ { "name": "autoparts.im", "include_subdomains": true, "mode": "force-https" },
+ { "name": "awccanadianpharmacy.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "auricblue.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "athi.pl", "include_subdomains": true, "mode": "force-https" },
+ { "name": "autoparts.wf", "include_subdomains": true, "mode": "force-https" },
+ { "name": "bdd.fi", "include_subdomains": true, "mode": "force-https" },
+ { "name": "baileebee.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "bedlingtonterrier.com.br", "include_subdomains": true, "mode": "force-https" },
+ { "name": "ashlane-cottages.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "atraining.ru", "include_subdomains": true, "mode": "force-https" },
+ { "name": "becubed.co", "include_subdomains": true, "mode": "force-https" },
+ { "name": "atelier-rk.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "autoentrepreneurinfo.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "bankbranchlocator.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "auditsquare.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "axiomer.es", "include_subdomains": true, "mode": "force-https" },
+ { "name": "battleofthegridiron.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "apretatuercas.es", "include_subdomains": true, "mode": "force-https" },
+ { "name": "avepol.eu", "include_subdomains": true, "mode": "force-https" },
+ { "name": "auriko-games.de", "include_subdomains": true, "mode": "force-https" },
+ { "name": "babymasaze.cz", "include_subdomains": true, "mode": "force-https" },
+ { "name": "axiomer.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "audiblox.co.za", "include_subdomains": true, "mode": "force-https" },
+ { "name": "b-rickroll-e.pw", "include_subdomains": true, "mode": "force-https" },
+ { "name": "benary.org", "include_subdomains": true, "mode": "force-https" },
+ { "name": "australian.dating", "include_subdomains": true, "mode": "force-https" },
+ { "name": "axiomer.me", "include_subdomains": true, "mode": "force-https" },
+ { "name": "atypicom.fr", "include_subdomains": true, "mode": "force-https" },
+ { "name": "atypicom.it", "include_subdomains": true, "mode": "force-https" },
+ { "name": "beetleroadstories.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "axiomer.net", "include_subdomains": true, "mode": "force-https" },
+ { "name": "bigskymontanalandforsale.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "bingcheung.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "atypicom.pt", "include_subdomains": true, "mode": "force-https" },
+ { "name": "aromaclub.nl", "include_subdomains": true, "mode": "force-https" },
+ { "name": "avotoma.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "autosiero.nl", "include_subdomains": true, "mode": "force-https" },
+ { "name": "barans2239.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "aviationstrategy.aero", "include_subdomains": true, "mode": "force-https" },
+ { "name": "bichonmaltes.com.br", "include_subdomains": true, "mode": "force-https" },
+ { "name": "bestgifts4you.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "befoodsafe.gov", "include_subdomains": true, "mode": "force-https" },
+ { "name": "avenelequinehospital.com.au", "include_subdomains": true, "mode": "force-https" },
+ { "name": "bicha.net", "include_subdomains": true, "mode": "force-https" },
+ { "name": "axiomer.org", "include_subdomains": true, "mode": "force-https" },
+ { "name": "be-webdesign.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "bacgrouppublishing.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "barburas.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "bbwcs.co.uk", "include_subdomains": true, "mode": "force-https" },
+ { "name": "b-landia.net", "include_subdomains": true, "mode": "force-https" },
+ { "name": "babettelandmesser.de", "include_subdomains": true, "mode": "force-https" },
+ { "name": "asr.solar", "include_subdomains": true, "mode": "force-https" },
+ { "name": "bibliaon.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "atypicom.es", "include_subdomains": true, "mode": "force-https" },
+ { "name": "betobaccofree.gov", "include_subdomains": true, "mode": "force-https" },
+ { "name": "azun.pl", "include_subdomains": true, "mode": "force-https" },
+ { "name": "bastiv.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "bettolinokitchen.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "autoosijek.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "bgenlisted.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "autodalmacija.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "boiadeirodeberna.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "blameomar.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "bestcellular.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "belge.rs", "include_subdomains": true, "mode": "force-https" },
+ { "name": "beauty24.de", "include_subdomains": true, "mode": "force-https" },
+ { "name": "belanglos.de", "include_subdomains": true, "mode": "force-https" },
+ { "name": "blayneallan.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "alexismeza.nl", "include_subdomains": true, "mode": "force-https" },
+ { "name": "alexismeza.es", "include_subdomains": true, "mode": "force-https" },
+ { "name": "biointelligence-explosion.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "ameza.me", "include_subdomains": true, "mode": "force-https" },
+ { "name": "bluemoonroleplaying.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "ameza.io", "include_subdomains": true, "mode": "force-https" },
+ { "name": "biopsychiatry.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "ameza.com.mx", "include_subdomains": true, "mode": "force-https" },
+ { "name": "baudairenergyservices.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "be2cloud.de", "include_subdomains": true, "mode": "force-https" },
+ { "name": "block-this.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "borzoi.com.br", "include_subdomains": true, "mode": "force-https" },
+ { "name": "brandongomez.me", "include_subdomains": true, "mode": "force-https" },
+ { "name": "bracoitaliano.com.br", "include_subdomains": true, "mode": "force-https" },
+ { "name": "bltc.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "badenhard.eu", "include_subdomains": true, "mode": "force-https" },
+ { "name": "bltc.org", "include_subdomains": true, "mode": "force-https" },
+ { "name": "b2bmuzikbank.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "brooklynrealestateblog.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "benjamin-suess.de", "include_subdomains": true, "mode": "force-https" },
+ { "name": "btorrent.xyz", "include_subdomains": true, "mode": "force-https" },
+ { "name": "branw.xyz", "include_subdomains": true, "mode": "force-https" },
+ { "name": "berlin.dating", "include_subdomains": true, "mode": "force-https" },
+ { "name": "black-octopus.ru", "include_subdomains": true, "mode": "force-https" },
+ { "name": "bonqoeur.ca", "include_subdomains": true, "mode": "force-https" },
+ { "name": "brettcornwall.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "blackphantom.de", "include_subdomains": true, "mode": "force-https" },
+ { "name": "bencorby.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "brandons.site", "include_subdomains": true, "mode": "force-https" },
+ { "name": "brianalaway.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "bohaishibei.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "backschues.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "brockmeyer.net", "include_subdomains": true, "mode": "force-https" },
+ { "name": "brickftp.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "blackdown.de", "include_subdomains": true, "mode": "force-https" },
+ { "name": "bondpro.gov", "include_subdomains": true, "mode": "force-https" },
+ { "name": "blvdmb.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "bcmguide.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "bitpumpe.net", "include_subdomains": true, "mode": "force-https" },
+ { "name": "bk-bund-berlin.de", "include_subdomains": true, "mode": "force-https" },
+ { "name": "bugsmashed.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "brandtrapselfie.nl", "include_subdomains": true, "mode": "force-https" },
+ { "name": "brianalawayconsulting.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "brunohenc.from.hr", "include_subdomains": true, "mode": "force-https" },
+ { "name": "bornandgrazed.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "blackpapermoon.de", "include_subdomains": true, "mode": "force-https" },
+ { "name": "biker.dating", "include_subdomains": true, "mode": "force-https" },
+ { "name": "bullterrier.me", "include_subdomains": true, "mode": "force-https" },
+ { "name": "brmsalescommunity.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "braunsteinpc.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "bep362.vn", "include_subdomains": true, "mode": "force-https" },
+ { "name": "bonop.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "buldogueingles.com.br", "include_subdomains": true, "mode": "force-https" },
+ { "name": "bgkoleda.bg", "include_subdomains": true, "mode": "force-https" },
+ { "name": "black.dating", "include_subdomains": true, "mode": "force-https" },
+ { "name": "bulmastife.com.br", "include_subdomains": true, "mode": "force-https" },
+ { "name": "birdymanbestreviews.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "bubblespetspa.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "bonnyprints.es", "include_subdomains": true, "mode": "force-https" },
+ { "name": "buenosairesestetica.com.ar", "include_subdomains": true, "mode": "force-https" },
+ { "name": "burr.is", "include_subdomains": true, "mode": "force-https" },
+ { "name": "brztec.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "autoepc.ro", "include_subdomains": true, "mode": "force-https" },
+ { "name": "birgit-rydlewski.de", "include_subdomains": true, "mode": "force-https" },
+ { "name": "bool.be", "include_subdomains": true, "mode": "force-https" },
+ { "name": "boudah.pl", "include_subdomains": true, "mode": "force-https" },
+ { "name": "ca-key.de", "include_subdomains": true, "mode": "force-https" },
+ { "name": "binsp.net", "include_subdomains": true, "mode": "force-https" },
+ { "name": "biscuits-rec.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "biscuits-shop.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "braintensive.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "brightfuturemadebyme.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "brege.org", "include_subdomains": true, "mode": "force-https" },
+ { "name": "byte.chat", "include_subdomains": true, "mode": "force-https" },
+ { "name": "brie.tech", "include_subdomains": true, "mode": "force-https" },
+ { "name": "booth.in.th", "include_subdomains": true, "mode": "force-https" },
+ { "name": "brauingenieur.de", "include_subdomains": true, "mode": "force-https" },
+ { "name": "camp.co.uk", "include_subdomains": true, "mode": "force-https" },
+ { "name": "cairnterrier.com.br", "include_subdomains": true, "mode": "force-https" },
+ { "name": "bypassed.today", "include_subdomains": true, "mode": "force-https" },
+ { "name": "caodesantohumberto.com.br", "include_subdomains": true, "mode": "force-https" },
+ { "name": "bynumlaw.net", "include_subdomains": true, "mode": "force-https" },
+ { "name": "caodecristachines.com.br", "include_subdomains": true, "mode": "force-https" },
+ { "name": "canterberry.cc", "include_subdomains": true, "mode": "force-https" },
+ { "name": "brazilian.dating", "include_subdomains": true, "mode": "force-https" },
+ { "name": "bugwie.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "carbon12.software", "include_subdomains": true, "mode": "force-https" },
+ { "name": "cacao-chocolate.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "burpsuite.site", "include_subdomains": true, "mode": "force-https" },
+ { "name": "batonger.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "carolcappelletti.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "bukatv.cz", "include_subdomains": true, "mode": "force-https" },
+ { "name": "bsuess.de", "include_subdomains": true, "mode": "force-https" },
+ { "name": "caribbeanexams.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "buergerhaushalt.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "c-rickroll-v.pw", "include_subdomains": true, "mode": "force-https" },
+ { "name": "brunner.ninja", "include_subdomains": true, "mode": "force-https" },
+ { "name": "caylercapital.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "carlmjohnson.net", "include_subdomains": true, "mode": "force-https" },
+ { "name": "bn1digital.co.uk", "include_subdomains": true, "mode": "force-https" },
+ { "name": "cannabis-marijuana.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "bypassed.world", "include_subdomains": true, "mode": "force-https" },
+ { "name": "bypassed.works", "include_subdomains": true, "mode": "force-https" },
+ { "name": "bvexplained.co.uk", "include_subdomains": true, "mode": "force-https" },
+ { "name": "cavalierkingcharlesspaniel.com.br", "include_subdomains": true, "mode": "force-https" },
+ { "name": "bunbomenu.de", "include_subdomains": true, "mode": "force-https" },
+ { "name": "c-path.org", "include_subdomains": true, "mode": "force-https" },
+ { "name": "aoku3d.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "biospeak.solutions", "include_subdomains": true, "mode": "force-https" },
+ { "name": "camperlist.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "cctld.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "bundespolizei-forum.de", "include_subdomains": true, "mode": "force-https" },
+ { "name": "carbon12.org", "include_subdomains": true, "mode": "force-https" },
+ { "name": "cesipagano.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "businesshub.cz", "include_subdomains": true, "mode": "force-https" },
+ { "name": "c3vo.de", "include_subdomains": true, "mode": "force-https" },
+ { "name": "card-toka.jp", "include_subdomains": true, "mode": "force-https" },
+ { "name": "achterstieg.dedyn.io", "include_subdomains": true, "mode": "force-https" },
+ { "name": "cee.io", "include_subdomains": true, "mode": "force-https" },
+ { "name": "cetamol.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "carroarmato0.be", "include_subdomains": true, "mode": "force-https" },
+ { "name": "charcoalvenice.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "buben.tech", "include_subdomains": true, "mode": "force-https" },
+ { "name": "charlottesvillegolfcommunities.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "businessimmigration-eu.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "bogner.sh", "include_subdomains": true, "mode": "force-https" },
+ { "name": "bisterfeldt.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "canfly.org", "include_subdomains": true, "mode": "force-https" },
+ { "name": "ca-terminal-multiservices.fr", "include_subdomains": true, "mode": "force-https" },
+ { "name": "chenzhekl.me", "include_subdomains": true, "mode": "force-https" },
+ { "name": "c4539.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "caputodesign.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "camerweb.es", "include_subdomains": true, "mode": "force-https" },
+ { "name": "c4.hk", "include_subdomains": true, "mode": "force-https" },
+ { "name": "campfire.co.il", "include_subdomains": true, "mode": "force-https" },
+ { "name": "cesdb.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "chatxp.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "centrationgame.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "canifis.net", "include_subdomains": true, "mode": "force-https" },
+ { "name": "cambodian.dating", "include_subdomains": true, "mode": "force-https" },
+ { "name": "carusorealestate.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "calixte-concept.fr", "include_subdomains": true, "mode": "force-https" },
+ { "name": "ceciliacolombara.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "car24portal.de", "include_subdomains": true, "mode": "force-https" },
+ { "name": "casc.cz", "include_subdomains": true, "mode": "force-https" },
+ { "name": "chonghe.org", "include_subdomains": true, "mode": "force-https" },
+ { "name": "christiangaetano.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "caletka.cz", "include_subdomains": true, "mode": "force-https" },
+ { "name": "ciderclub.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "cbintermountainrealty.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "citrusui.me", "include_subdomains": true, "mode": "force-https" },
+ { "name": "cfan.space", "include_subdomains": true, "mode": "force-https" },
+ { "name": "chrisopperwall.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "carlo.mx", "include_subdomains": true, "mode": "force-https" },
+ { "name": "carterorland.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "ccac.gov", "include_subdomains": true, "mode": "force-https" },
+ { "name": "chesterbrass.uk", "include_subdomains": true, "mode": "force-https" },
+ { "name": "champicreuse.fr", "include_subdomains": true, "mode": "force-https" },
+ { "name": "catholics.dating", "include_subdomains": true, "mode": "force-https" },
+ { "name": "cgan.de", "include_subdomains": true, "mode": "force-https" },
+ { "name": "cegfw.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "buytheway.co.za", "include_subdomains": true, "mode": "force-https" },
+ { "name": "chlouis.net", "include_subdomains": true, "mode": "force-https" },
+ { "name": "adawolfa.cz", "include_subdomains": true, "mode": "force-https" },
+ { "name": "cerstvekorenie.sk", "include_subdomains": true, "mode": "force-https" },
+ { "name": "cerstve-korenie.sk", "include_subdomains": true, "mode": "force-https" },
+ { "name": "chromaryu.net", "include_subdomains": true, "mode": "force-https" },
+ { "name": "cloudoptimus.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "cdepot.eu", "include_subdomains": true, "mode": "force-https" },
+ { "name": "caulong-ao.net", "include_subdomains": true, "mode": "force-https" },
+ { "name": "centrallead.net", "include_subdomains": true, "mode": "force-https" },
+ { "name": "chua.family", "include_subdomains": true, "mode": "force-https" },
+ { "name": "cockerspanielingles.com.br", "include_subdomains": true, "mode": "force-https" },
+ { "name": "christianscholz.eu", "include_subdomains": true, "mode": "force-https" },
+ { "name": "chanissue.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "cloudbasedsite.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "christophkreileder.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "cockerspanielamericano.com.br", "include_subdomains": true, "mode": "force-https" },
+ { "name": "citationgurus.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "castagnonavocats.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "chorkley.co.uk", "include_subdomains": true, "mode": "force-https" },
+ { "name": "bastelzauberwelt.de", "include_subdomains": true, "mode": "force-https" },
+ { "name": "clinicaltrials.gov", "include_subdomains": true, "mode": "force-https" },
+ { "name": "codewiz.xyz", "include_subdomains": true, "mode": "force-https" },
+ { "name": "ahwah.net", "include_subdomains": true, "mode": "force-https" },
+ { "name": "chirpstory.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "ciuciucadou.ro", "include_subdomains": true, "mode": "force-https" },
+ { "name": "cncn.us", "include_subdomains": true, "mode": "force-https" },
+ { "name": "chewey.org", "include_subdomains": true, "mode": "force-https" },
+ { "name": "chicorycom.net", "include_subdomains": true, "mode": "force-https" },
+ { "name": "codenode.io", "include_subdomains": true, "mode": "force-https" },
+ { "name": "clipclip.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "christianpusch.de", "include_subdomains": true, "mode": "force-https" },
+ { "name": "chewey.de", "include_subdomains": true, "mode": "force-https" },
+ { "name": "chokladfantasi.net", "include_subdomains": true, "mode": "force-https" },
+ { "name": "chrisu3050.at", "include_subdomains": true, "mode": "force-https" },
+ { "name": "celina-reads.de", "include_subdomains": true, "mode": "force-https" },
+ { "name": "chenky.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "clickgram.biz", "include_subdomains": true, "mode": "force-https" },
+ { "name": "computer-acquisti.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "christophercolumbusfoundation.gov", "include_subdomains": true, "mode": "force-https" },
+ { "name": "claimit.ml", "include_subdomains": true, "mode": "force-https" },
+ { "name": "cleanexperts.co.uk", "include_subdomains": true, "mode": "force-https" },
+ { "name": "corecodec.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "catenacondos.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "codigosddd.com.br", "include_subdomains": true, "mode": "force-https" },
+ { "name": "cieslar.io", "include_subdomains": true, "mode": "force-https" },
+ { "name": "coreyjmahler.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "clicn.bio", "include_subdomains": true, "mode": "force-https" },
+ { "name": "cluster.id", "include_subdomains": true, "mode": "force-https" },
+ { "name": "compibus.fr", "include_subdomains": true, "mode": "force-https" },
+ { "name": "cockedey.in", "include_subdomains": true, "mode": "force-https" },
+ { "name": "cda-aigle.ch", "include_subdomains": true, "mode": "force-https" },
+ { "name": "colearnr.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "corecdn.org", "include_subdomains": true, "mode": "force-https" },
+ { "name": "corex.io", "include_subdomains": true, "mode": "force-https" },
+ { "name": "classifiedssa.co.za", "include_subdomains": true, "mode": "force-https" },
+ { "name": "congineer.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "cloudia.org", "include_subdomains": true, "mode": "force-https" },
+ { "name": "cheetahwerx.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "clicnbio.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "cobrasystems.nl", "include_subdomains": true, "mode": "force-https" },
+ { "name": "computerbase.de", "include_subdomains": true, "mode": "force-https" },
+ { "name": "coatl-industries.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "cookie4.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "cognitivecomputingconsortium.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "creepypastas.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "csmainframe.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "cryptoshot.pw", "include_subdomains": true, "mode": "force-https" },
+ { "name": "creativeliquid.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "courageousparentsnetwork.org", "include_subdomains": true, "mode": "force-https" },
+ { "name": "codedump.net", "include_subdomains": true, "mode": "force-https" },
+ { "name": "countryoutlaws.ca", "include_subdomains": true, "mode": "force-https" },
+ { "name": "codebrahma.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "chorkley.uk", "include_subdomains": true, "mode": "force-https" },
+ { "name": "coresolutions.ca", "include_subdomains": true, "mode": "force-https" },
+ { "name": "crockett.io", "include_subdomains": true, "mode": "force-https" },
+ { "name": "ahmedabadflowermall.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "cine-music.de", "include_subdomains": true, "mode": "force-https" },
+ { "name": "cosmeticappraisal.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "crustytoothpaste.net", "include_subdomains": true, "mode": "force-https" },
+ { "name": "consumeractionlawgroup.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "computerslotopschool.nl", "include_subdomains": true, "mode": "force-https" },
+ { "name": "criminal.enterprises", "include_subdomains": true, "mode": "force-https" },
+ { "name": "collectdocs.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "bierbringer.at", "include_subdomains": true, "mode": "force-https" },
+ { "name": "colombian.dating", "include_subdomains": true, "mode": "force-https" },
+ { "name": "cooink.net", "include_subdomains": true, "mode": "force-https" },
+ { "name": "comchezmeme.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "combron.nl", "include_subdomains": true, "mode": "force-https" },
+ { "name": "corona-academy.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "crisp.im", "include_subdomains": true, "mode": "force-https" },
+ { "name": "cocodemy.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "content-design.de", "include_subdomains": true, "mode": "force-https" },
+ { "name": "countryattire.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "creditstar.lt", "include_subdomains": true, "mode": "force-https" },
+ { "name": "cubekrowd.net", "include_subdomains": true, "mode": "force-https" },
+ { "name": "dalingk.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "crescent.gr.jp", "include_subdomains": true, "mode": "force-https" },
+ { "name": "cuntflaps.me", "include_subdomains": true, "mode": "force-https" },
+ { "name": "cubecraft.net", "include_subdomains": true, "mode": "force-https" },
+ { "name": "css.net", "include_subdomains": true, "mode": "force-https" },
+ { "name": "cun.lu", "include_subdomains": true, "mode": "force-https" },
+ { "name": "davidandkailey.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "csgo.help", "include_subdomains": true, "mode": "force-https" },
+ { "name": "daveaglick.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "codecontrollers.de", "include_subdomains": true, "mode": "force-https" },
+ { "name": "datadyne.technology", "include_subdomains": true, "mode": "force-https" },
+ { "name": "d-rickroll-e.pw", "include_subdomains": true, "mode": "force-https" },
+ { "name": "braemer-it-consulting.de", "include_subdomains": true, "mode": "force-https" },
+ { "name": "crimewatch.net.za", "include_subdomains": true, "mode": "force-https" },
+ { "name": "croome.no-ip.org", "include_subdomains": true, "mode": "force-https" },
+ { "name": "cosmeticos-naturales.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "cunha.be", "include_subdomains": true, "mode": "force-https" },
+ { "name": "dakerealestate.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "cranems.com.ua", "include_subdomains": true, "mode": "force-https" },
+ { "name": "david-pearce.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "cube-cloud.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "danwillenberg.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "cornishcamels.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "cubecart-demo.co.uk", "include_subdomains": true, "mode": "force-https" },
+ { "name": "cuni-cuni-club.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "defero.io", "include_subdomains": true, "mode": "force-https" },
+ { "name": "cajio.ru", "include_subdomains": true, "mode": "force-https" },
+ { "name": "decesus.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "cuni-rec.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "dakl-shop.de", "include_subdomains": true, "mode": "force-https" },
+ { "name": "cubecart-hosting.co.uk", "include_subdomains": true, "mode": "force-https" },
+ { "name": "debigare.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "daniel-seifert.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "datenlast.de", "include_subdomains": true, "mode": "force-https" },
+ { "name": "cybertorsk.org", "include_subdomains": true, "mode": "force-https" },
+ { "name": "das-sommercamp.de", "include_subdomains": true, "mode": "force-https" },
+ { "name": "cyber-konzept.de", "include_subdomains": true, "mode": "force-https" },
+ { "name": "dansk-skole.de", "include_subdomains": true, "mode": "force-https" },
+ { "name": "cuppycakes.fi", "include_subdomains": true, "mode": "force-https" },
+ { "name": "de-rwa.de", "include_subdomains": true, "mode": "force-https" },
+ { "name": "derpumpkinfuhrer.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "darisni.me", "include_subdomains": true, "mode": "force-https" },
+ { "name": "deltava.org", "include_subdomains": true, "mode": "force-https" },
+ { "name": "diceduels.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "dbas.cz", "include_subdomains": true, "mode": "force-https" },
+ { "name": "dede.ml", "include_subdomains": true, "mode": "force-https" },
+ { "name": "ddfreedish.site", "include_subdomains": true, "mode": "force-https" },
+ { "name": "bstoked.net", "include_subdomains": true, "mode": "force-https" },
+ { "name": "damedrogy.cz", "include_subdomains": true, "mode": "force-https" },
+ { "name": "dehydrated.de", "include_subdomains": true, "mode": "force-https" },
+ { "name": "dcl.re", "include_subdomains": true, "mode": "force-https" },
+ { "name": "dejure.org", "include_subdomains": true, "mode": "force-https" },
+ { "name": "davepage.me.uk", "include_subdomains": true, "mode": "force-https" },
+ { "name": "daku.gdn", "include_subdomains": true, "mode": "force-https" },
+ { "name": "datenschutztag.org", "include_subdomains": true, "mode": "force-https" },
+ { "name": "de-servers.de", "include_subdomains": true, "mode": "force-https" },
+ { "name": "dengyong.org", "include_subdomains": true, "mode": "force-https" },
+ { "name": "db-works.nl", "include_subdomains": true, "mode": "force-https" },
+ { "name": "direnv.net", "include_subdomains": true, "mode": "force-https" },
+ { "name": "cyberxpert.nl", "include_subdomains": true, "mode": "force-https" },
+ { "name": "dhhs.gov", "include_subdomains": true, "mode": "force-https" },
+ { "name": "diferenca.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "develux.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "darkstance.org", "include_subdomains": true, "mode": "force-https" },
+ { "name": "dicionariodesimbolos.com.br", "include_subdomains": true, "mode": "force-https" },
+ { "name": "dgby.org", "include_subdomains": true, "mode": "force-https" },
+ { "name": "detskysad.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "cubecart.net", "include_subdomains": true, "mode": "force-https" },
+ { "name": "devzero.io", "include_subdomains": true, "mode": "force-https" },
+ { "name": "deitti.net", "include_subdomains": true, "mode": "force-https" },
+ { "name": "dewin.io", "include_subdomains": true, "mode": "force-https" },
+ { "name": "discotek.club", "include_subdomains": true, "mode": "force-https" },
+ { "name": "der-bank-blog.de", "include_subdomains": true, "mode": "force-https" },
+ { "name": "diewebstube.de", "include_subdomains": true, "mode": "force-https" },
+ { "name": "dhpiggott.net", "include_subdomains": true, "mode": "force-https" },
+ { "name": "deutsch-vietnamesisch-dolmetscher.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "dhpcs.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "delta-smart.ch", "include_subdomains": true, "mode": "force-https" },
+ { "name": "deltasmart.ch", "include_subdomains": true, "mode": "force-https" },
+ { "name": "cyhour.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "derre.fr", "include_subdomains": true, "mode": "force-https" },
+ { "name": "dicionario.org", "include_subdomains": true, "mode": "force-https" },
+ { "name": "cloud-crowd.com.au", "include_subdomains": true, "mode": "force-https" },
+ { "name": "disability.gov", "include_subdomains": true, "mode": "force-https" },
+ { "name": "destinattorneyjohngreene.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "adajwells.me", "include_subdomains": true, "mode": "force-https" },
+ { "name": "digioccumss.ddns.net", "include_subdomains": true, "mode": "force-https" },
+ { "name": "danieljireh.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "decoboutique.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "desu.ne.jp", "include_subdomains": true, "mode": "force-https" },
+ { "name": "digitalhurricane.io", "include_subdomains": true, "mode": "force-https" },
+ { "name": "dotacni-parazit.cz", "include_subdomains": true, "mode": "force-https" },
+ { "name": "dimonb.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "drivinghorror.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "dominioanimal.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "dnsknowledge.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "dbox.ga", "include_subdomains": true, "mode": "force-https" },
+ { "name": "dominioanimal.com.br", "include_subdomains": true, "mode": "force-https" },
+ { "name": "digiarc.net", "include_subdomains": true, "mode": "force-https" },
+ { "name": "dooleylabs.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "dietrich-spielwaren.de", "include_subdomains": true, "mode": "force-https" },
+ { "name": "drakeanddragon.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "directlinkfunding.co.uk", "include_subdomains": true, "mode": "force-https" },
+ { "name": "debron-ot.nl", "include_subdomains": true, "mode": "force-https" },
+ { "name": "dlzz.net", "include_subdomains": true, "mode": "force-https" },
+ { "name": "discoverhealthage.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "docset.io", "include_subdomains": true, "mode": "force-https" },
+ { "name": "deurenfabriek.nl", "include_subdomains": true, "mode": "force-https" },
+ { "name": "dogmap.jp", "include_subdomains": true, "mode": "force-https" },
+ { "name": "ditrutoancau.vn", "include_subdomains": true, "mode": "force-https" },
+ { "name": "dognlife.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "digitalrights.fund", "include_subdomains": true, "mode": "force-https" },
+ { "name": "distrilogservices.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "dress-cons.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "directnews.be", "include_subdomains": true, "mode": "force-https" },
+ { "name": "digitalbitbox.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "drummondframing.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "diehl.io", "include_subdomains": true, "mode": "force-https" },
+ { "name": "dulei.si", "include_subdomains": true, "mode": "force-https" },
+ { "name": "dontbubble.me", "include_subdomains": true, "mode": "force-https" },
+ { "name": "deuxsol.co", "include_subdomains": true, "mode": "force-https" },
+ { "name": "diare-na-miru.cz", "include_subdomains": true, "mode": "force-https" },
+ { "name": "deuxvia.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "darbtech.net", "include_subdomains": true, "mode": "force-https" },
+ { "name": "dokelio-idf.fr", "include_subdomains": true, "mode": "force-https" },
+ { "name": "doked.io", "include_subdomains": true, "mode": "force-https" },
+ { "name": "dopply.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "doma.in", "include_subdomains": true, "mode": "force-https" },
+ { "name": "drighes.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "dotplex.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "dinotv.at", "include_subdomains": true, "mode": "force-https" },
+ { "name": "drinkplanet.eu", "include_subdomains": true, "mode": "force-https" },
+ { "name": "educourse.ga", "include_subdomains": true, "mode": "force-https" },
+ { "name": "dragonstower.net", "include_subdomains": true, "mode": "force-https" },
+ { "name": "dominoknihy.cz", "include_subdomains": true, "mode": "force-https" },
+ { "name": "dzndk.net", "include_subdomains": true, "mode": "force-https" },
+ { "name": "dungi.org", "include_subdomains": true, "mode": "force-https" },
+ { "name": "dzndk.org", "include_subdomains": true, "mode": "force-https" },
+ { "name": "buildingclouds.ch", "include_subdomains": true, "mode": "force-https" },
+ { "name": "dynamictostatic.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "davidgreig.uk", "include_subdomains": true, "mode": "force-https" },
+ { "name": "dopfer-fenstertechnik.de", "include_subdomains": true, "mode": "force-https" },
+ { "name": "egoroof.ru", "include_subdomains": true, "mode": "force-https" },
+ { "name": "e-rickroll-r.pw", "include_subdomains": true, "mode": "force-https" },
+ { "name": "doc.to", "include_subdomains": true, "mode": "force-https" },
+ { "name": "ebraph.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "dragfiles.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "e-standardstore.org", "include_subdomains": true, "mode": "force-https" },
+ { "name": "dkravchenko.su", "include_subdomains": true, "mode": "force-https" },
+ { "name": "dotplex.de", "include_subdomains": true, "mode": "force-https" },
+ { "name": "ecomlane.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "duncanwinfrey.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "droni.cz", "include_subdomains": true, "mode": "force-https" },
+ { "name": "eddyn.net", "include_subdomains": true, "mode": "force-https" },
+ { "name": "egbert.net", "include_subdomains": true, "mode": "force-https" },
+ { "name": "droomhuis-in-de-friese-meren-kopen.nl", "include_subdomains": true, "mode": "force-https" },
+ { "name": "droomhuisophetplattelandverkopen.nl", "include_subdomains": true, "mode": "force-https" },
+ { "name": "e-isfa.eu", "include_subdomains": true, "mode": "force-https" },
+ { "name": "droomhuis-in-brielle-kopen.nl", "include_subdomains": true, "mode": "force-https" },
+ { "name": "dragonfly.co.uk", "include_subdomains": true, "mode": "force-https" },
+ { "name": "elsemanario.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "drgn.no", "include_subdomains": true, "mode": "force-https" },
+ { "name": "droomhuis-in-rijnwaarden-kopen.nl", "include_subdomains": true, "mode": "force-https" },
+ { "name": "elementalsoftware.org", "include_subdomains": true, "mode": "force-https" },
+ { "name": "droomhuis-in-zuid-holland-kopen.nl", "include_subdomains": true, "mode": "force-https" },
+ { "name": "eboyer.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "droomhuis-in-zeeland-kopen.nl", "include_subdomains": true, "mode": "force-https" },
+ { "name": "droomhuisindestadverkopen.nl", "include_subdomains": true, "mode": "force-https" },
+ { "name": "echo-security.co", "include_subdomains": true, "mode": "force-https" },
+ { "name": "earth-people.org", "include_subdomains": true, "mode": "force-https" },
+ { "name": "eeb98.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "elementalsoftware.net", "include_subdomains": true, "mode": "force-https" },
+ { "name": "epicpages.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "duoluodeyu.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "emesolutions.net", "include_subdomains": true, "mode": "force-https" },
+ { "name": "dreamcatcherblog.de", "include_subdomains": true, "mode": "force-https" },
+ { "name": "ecc-kaufbeuren.de", "include_subdomains": true, "mode": "force-https" },
+ { "name": "ecotruck-pooling.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "buildingclouds.es", "include_subdomains": true, "mode": "force-https" },
+ { "name": "drogueriaelbarco.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "eisp.it", "include_subdomains": true, "mode": "force-https" },
+ { "name": "eqim.me", "include_subdomains": true, "mode": "force-https" },
+ { "name": "electricoperaduo.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "devpsy.info", "include_subdomains": true, "mode": "force-https" },
+ { "name": "diversity-spielzeug.de", "include_subdomains": true, "mode": "force-https" },
+ { "name": "dom-medicina.ru", "include_subdomains": true, "mode": "force-https" },
+ { "name": "egumenita.ro", "include_subdomains": true, "mode": "force-https" },
+ { "name": "egb.at", "include_subdomains": true, "mode": "force-https" },
+ { "name": "entabe.jp", "include_subdomains": true, "mode": "force-https" },
+ { "name": "eengezinswoning-in-sudwest-fryslan-kopen.nl", "include_subdomains": true, "mode": "force-https" },
+ { "name": "eengezinswoning-in-alphen-aan-den-rijn-kopen.nl", "include_subdomains": true, "mode": "force-https" },
+ { "name": "eengezinswoning-in-de-friese-meren-kopen.nl", "include_subdomains": true, "mode": "force-https" },
+ { "name": "eagle-yard.de", "include_subdomains": true, "mode": "force-https" },
+ { "name": "energyaupair.se", "include_subdomains": true, "mode": "force-https" },
+ { "name": "eengezinswoning-in-zuid-holland-kopen.nl", "include_subdomains": true, "mode": "force-https" },
+ { "name": "enuchi.jp", "include_subdomains": true, "mode": "force-https" },
+ { "name": "eengezinswoning-in-friesland-kopen.nl", "include_subdomains": true, "mode": "force-https" },
+ { "name": "embellir-kyujin.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "eengezinswoning-in-rijnwaarden-kopen.nl", "include_subdomains": true, "mode": "force-https" },
+ { "name": "eengezinswoning-in-leeuwarden-kopen.nl", "include_subdomains": true, "mode": "force-https" },
+ { "name": "einfachmaldiefressehalten.de", "include_subdomains": true, "mode": "force-https" },
+ { "name": "eengezinswoning-in-zeeland-kopen.nl", "include_subdomains": true, "mode": "force-https" },
+ { "name": "etaoinwu.tk", "include_subdomains": true, "mode": "force-https" },
+ { "name": "ennori.jp", "include_subdomains": true, "mode": "force-https" },
+ { "name": "egw-ceramica.de", "include_subdomains": true, "mode": "force-https" },
+ { "name": "eengezinswoning-in-zuidplas-kopen.nl", "include_subdomains": true, "mode": "force-https" },
+ { "name": "eengezinswoning-in-zwartewaterland-kopen.nl", "include_subdomains": true, "mode": "force-https" },
+ { "name": "emavok.eu", "include_subdomains": true, "mode": "force-https" },
+ { "name": "et180.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "especificosba.com.mx", "include_subdomains": true, "mode": "force-https" },
+ { "name": "eengezinswoningverkopen.nl", "include_subdomains": true, "mode": "force-https" },
+ { "name": "eastmanbusinessinstitute.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "enginepit.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "buildingclouds.de", "include_subdomains": true, "mode": "force-https" },
+ { "name": "erick.blog", "include_subdomains": true, "mode": "force-https" },
+ { "name": "epsilon.dk", "include_subdomains": true, "mode": "force-https" },
+ { "name": "dupree.co", "include_subdomains": true, "mode": "force-https" },
+ { "name": "entheogens.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "entactogens.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "encode.host", "include_subdomains": true, "mode": "force-https" },
+ { "name": "elektro-koehl.de", "include_subdomains": true, "mode": "force-https" },
+ { "name": "euclideanpostulates.xyz", "include_subdomains": true, "mode": "force-https" },
+ { "name": "exploit-db.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "extensiblewebmanifesto.org", "include_subdomains": true, "mode": "force-https" },
+ { "name": "expancio.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "engineowning.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "events12.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "extensiblewebreportcard.org", "include_subdomains": true, "mode": "force-https" },
+ { "name": "espacetheosophie.fr", "include_subdomains": true, "mode": "force-https" },
+ { "name": "ericairwin.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "extensiblewebsummit.org", "include_subdomains": true, "mode": "force-https" },
+ { "name": "erythroxylum-coca.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "essite.net", "include_subdomains": true, "mode": "force-https" },
+ { "name": "exhalespa.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "estcequonmetenprodaujourdhui.info", "include_subdomains": true, "mode": "force-https" },
+ { "name": "facebook.ax", "include_subdomains": true, "mode": "force-https" },
+ { "name": "ecolesrec.ch", "include_subdomains": true, "mode": "force-https" },
+ { "name": "eganassociates.com.au", "include_subdomains": true, "mode": "force-https" },
+ { "name": "escapeplaza.de", "include_subdomains": true, "mode": "force-https" },
+ { "name": "evafojtova.cz", "include_subdomains": true, "mode": "force-https" },
+ { "name": "escolaengenharia.com.br", "include_subdomains": true, "mode": "force-https" },
+ { "name": "ekedc.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "evankurniawan.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "endlessvideo.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "f-rickroll-g.pw", "include_subdomains": true, "mode": "force-https" },
+ { "name": "factureenlinea.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "enginx.net", "include_subdomains": true, "mode": "force-https" },
+ { "name": "ficlab.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "exs.lv", "include_subdomains": true, "mode": "force-https" },
+ { "name": "feaden.me", "include_subdomains": true, "mode": "force-https" },
+ { "name": "fieldclockapp.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "evion.nl", "include_subdomains": true, "mode": "force-https" },
+ { "name": "exploited.cz", "include_subdomains": true, "mode": "force-https" },
+ { "name": "equitee.co", "include_subdomains": true, "mode": "force-https" },
+ { "name": "filesense.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "eventmake.es", "include_subdomains": true, "mode": "force-https" },
+ { "name": "fedjobs.gov", "include_subdomains": true, "mode": "force-https" },
+ { "name": "europastudien.de", "include_subdomains": true, "mode": "force-https" },
+ { "name": "fabled.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "farmacia.pt", "include_subdomains": true, "mode": "force-https" },
+ { "name": "federaljobs.gov", "include_subdomains": true, "mode": "force-https" },
+ { "name": "farfetchos.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "fantopia.club", "include_subdomains": true, "mode": "force-https" },
+ { "name": "flooringnightmares.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "fishlinemedia.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "earticleblog.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "buyaccessible.gov", "include_subdomains": true, "mode": "force-https" },
+ { "name": "eupho.me", "include_subdomains": true, "mode": "force-https" },
+ { "name": "fixthetimeline.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "erstehilfeprodukte.at", "include_subdomains": true, "mode": "force-https" },
+ { "name": "fix-the-timeline.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "fix-the-timeline.org", "include_subdomains": true, "mode": "force-https" },
+ { "name": "fixthetimeline.org", "include_subdomains": true, "mode": "force-https" },
+ { "name": "everything.place", "include_subdomains": true, "mode": "force-https" },
+ { "name": "fbijobs.gov", "include_subdomains": true, "mode": "force-https" },
+ { "name": "europapier.cz", "include_subdomains": true, "mode": "force-https" },
+ { "name": "easyocm.hu", "include_subdomains": true, "mode": "force-https" },
+ { "name": "florida-prep.org", "include_subdomains": true, "mode": "force-https" },
+ { "name": "europapier.hr", "include_subdomains": true, "mode": "force-https" },
+ { "name": "fitness.gov", "include_subdomains": true, "mode": "force-https" },
+ { "name": "famdouma.nl", "include_subdomains": true, "mode": "force-https" },
+ { "name": "firesofheaven.org", "include_subdomains": true, "mode": "force-https" },
+ { "name": "etath.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "fancy-bridge.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "evoludis.net", "include_subdomains": true, "mode": "force-https" },
+ { "name": "ffis.me", "include_subdomains": true, "mode": "force-https" },
+ { "name": "feyermedia.de", "include_subdomains": true, "mode": "force-https" },
+ { "name": "flyawayantennas.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "europapier.ua", "include_subdomains": true, "mode": "force-https" },
+ { "name": "foxhound.com.br", "include_subdomains": true, "mode": "force-https" },
+ { "name": "europapier.si", "include_subdomains": true, "mode": "force-https" },
+ { "name": "foodsafety.gov", "include_subdomains": true, "mode": "force-https" },
+ { "name": "europapier.rs", "include_subdomains": true, "mode": "force-https" },
+ { "name": "europapier.ba", "include_subdomains": true, "mode": "force-https" },
+ { "name": "europapier.hu", "include_subdomains": true, "mode": "force-https" },
+ { "name": "francisli.net", "include_subdomains": true, "mode": "force-https" },
+ { "name": "foxterrier.com.br", "include_subdomains": true, "mode": "force-https" },
+ { "name": "feld.saarland", "include_subdomains": true, "mode": "force-https" },
+ { "name": "foo.fo", "include_subdomains": true, "mode": "force-https" },
+ { "name": "fachschaftslisten.org", "include_subdomains": true, "mode": "force-https" },
+ { "name": "fotella.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "fojtova.cz", "include_subdomains": true, "mode": "force-https" },
+ { "name": "flauschig.net", "include_subdomains": true, "mode": "force-https" },
+ { "name": "felixhefner.de", "include_subdomains": true, "mode": "force-https" },
+ { "name": "famvsomeren.nl", "include_subdomains": true, "mode": "force-https" },
+ { "name": "ehomusicgear.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "fojtovi.cz", "include_subdomains": true, "mode": "force-https" },
+ { "name": "central4.me", "include_subdomains": true, "mode": "force-https" },
+ { "name": "frostwarning.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "fullyint.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "foolip.org", "include_subdomains": true, "mode": "force-https" },
+ { "name": "fitsw.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "feedkovacs.hu", "include_subdomains": true, "mode": "force-https" },
+ { "name": "floseed.fr", "include_subdomains": true, "mode": "force-https" },
+ { "name": "exehack.net", "include_subdomains": true, "mode": "force-https" },
+ { "name": "frolova.org", "include_subdomains": true, "mode": "force-https" },
+ { "name": "firebounty.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "flucky.xyz", "include_subdomains": true, "mode": "force-https" },
+ { "name": "fistu.la", "include_subdomains": true, "mode": "force-https" },
+ { "name": "foo.hamburg", "include_subdomains": true, "mode": "force-https" },
+ { "name": "frolov.net", "include_subdomains": true, "mode": "force-https" },
+ { "name": "fushee.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "folioapp.io", "include_subdomains": true, "mode": "force-https" },
+ { "name": "gaireg.de", "include_subdomains": true, "mode": "force-https" },
+ { "name": "fotogiraffe.ru", "include_subdomains": true, "mode": "force-https" },
+ { "name": "freeben666.fr", "include_subdomains": true, "mode": "force-https" },
+ { "name": "fleurette.me", "include_subdomains": true, "mode": "force-https" },
+ { "name": "freecloud.at", "include_subdomains": true, "mode": "force-https" },
+ { "name": "forstbetrieb-hennecke.de", "include_subdomains": true, "mode": "force-https" },
+ { "name": "fastdigitizing.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "galgoingles.com.br", "include_subdomains": true, "mode": "force-https" },
+ { "name": "fzslm.me", "include_subdomains": true, "mode": "force-https" },
+ { "name": "galgopersa.com.br", "include_subdomains": true, "mode": "force-https" },
+ { "name": "floth.at", "include_subdomains": true, "mode": "force-https" },
+ { "name": "froh.co.jp", "include_subdomains": true, "mode": "force-https" },
+ { "name": "fhfaoig.gov", "include_subdomains": true, "mode": "force-https" },
+ { "name": "gaite.me", "include_subdomains": true, "mode": "force-https" },
+ { "name": "gabi.soy", "include_subdomains": true, "mode": "force-https" },
+ { "name": "galgoafegao.com.br", "include_subdomains": true, "mode": "force-https" },
+ { "name": "gamingexodus.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "foej-aktiv.de", "include_subdomains": true, "mode": "force-https" },
+ { "name": "fullbundle.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "geekwhack.org", "include_subdomains": true, "mode": "force-https" },
+ { "name": "flymns.fr", "include_subdomains": true, "mode": "force-https" },
+ { "name": "forafifty.co.za", "include_subdomains": true, "mode": "force-https" },
+ { "name": "friedhelm-wolf.de", "include_subdomains": true, "mode": "force-https" },
+ { "name": "friendlyfiregameshow.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "fresh.co.il", "include_subdomains": true, "mode": "force-https" },
+ { "name": "freshempire.gov", "include_subdomains": true, "mode": "force-https" },
+ { "name": "freelanced.co.za", "include_subdomains": true, "mode": "force-https" },
+ { "name": "gbcsummercamps.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "g3rv4.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "footlegende.fr", "include_subdomains": true, "mode": "force-https" },
+ { "name": "gametium.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "gebn.co.uk", "include_subdomains": true, "mode": "force-https" },
+ { "name": "gameclue.jp", "include_subdomains": true, "mode": "force-https" },
+ { "name": "foto.by", "include_subdomains": true, "mode": "force-https" },
+ { "name": "gagstempel.de", "include_subdomains": true, "mode": "force-https" },
+ { "name": "gametium.es", "include_subdomains": true, "mode": "force-https" },
+ { "name": "fortuna-loessnitz.de", "include_subdomains": true, "mode": "force-https" },
+ { "name": "gamek.es", "include_subdomains": true, "mode": "force-https" },
+ { "name": "gene-drives.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "general-anaesthesia.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "fun-stamps.de", "include_subdomains": true, "mode": "force-https" },
+ { "name": "funnystamps.de", "include_subdomains": true, "mode": "force-https" },
+ { "name": "getshifter.io", "include_subdomains": true, "mode": "force-https" },
+ { "name": "garagemhermetica.org", "include_subdomains": true, "mode": "force-https" },
+ { "name": "giri.co", "include_subdomains": true, "mode": "force-https" },
+ { "name": "geekchimp.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "funstamps.de", "include_subdomains": true, "mode": "force-https" },
+ { "name": "geti2p.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "farmkazuto.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "funstempel.de", "include_subdomains": true, "mode": "force-https" },
+ { "name": "gebruikershandleiding.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "ghostcir.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "garystallman.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "graphene.software", "include_subdomains": true, "mode": "force-https" },
+ { "name": "getpake.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "datamatic.ru", "include_subdomains": true, "mode": "force-https" },
+ { "name": "getfestify.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "globalhealth.gov", "include_subdomains": true, "mode": "force-https" },
+ { "name": "g-rickroll-o.pw", "include_subdomains": true, "mode": "force-https" },
+ { "name": "graphsearchengine.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "geschmacksache.online", "include_subdomains": true, "mode": "force-https" },
+ { "name": "grepmaste.rs", "include_subdomains": true, "mode": "force-https" },
+ { "name": "gradients.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "giantmicrobes.de", "include_subdomains": true, "mode": "force-https" },
+ { "name": "gramati.com.br", "include_subdomains": true, "mode": "force-https" },
+ { "name": "gchoic.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "gracetini.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "fun-stempel.de", "include_subdomains": true, "mode": "force-https" },
+ { "name": "goverage.org", "include_subdomains": true, "mode": "force-https" },
+ { "name": "gincher.net", "include_subdomains": true, "mode": "force-https" },
+ { "name": "hackerone.net", "include_subdomains": true, "mode": "force-https" },
+ { "name": "geboortestoeltje.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "furnitureconcept.co.uk", "include_subdomains": true, "mode": "force-https" },
+ { "name": "gibraltar.at", "include_subdomains": true, "mode": "force-https" },
+ { "name": "glamguru.world", "include_subdomains": true, "mode": "force-https" },
+ { "name": "global-lights.ma", "include_subdomains": true, "mode": "force-https" },
+ { "name": "grow-shop.lt", "include_subdomains": true, "mode": "force-https" },
+ { "name": "fuzoku-sodan.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "gamefund.me", "include_subdomains": true, "mode": "force-https" },
+ { "name": "gus.moe", "include_subdomains": true, "mode": "force-https" },
+ { "name": "google.ax", "include_subdomains": true, "mode": "force-https" },
+ { "name": "geoport.al", "include_subdomains": true, "mode": "force-https" },
+ { "name": "gospelfollower.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "gj-bochum.de", "include_subdomains": true, "mode": "force-https" },
+ { "name": "gesunde-smoothies.de", "include_subdomains": true, "mode": "force-https" },
+ { "name": "hallucinogen.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "gratis-lovecheck.de", "include_subdomains": true, "mode": "force-https" },
+ { "name": "h-rickroll-n.pw", "include_subdomains": true, "mode": "force-https" },
+ { "name": "groupe-cassous.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "geekwithabudget.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "hearty.blog", "include_subdomains": true, "mode": "force-https" },
+ { "name": "ginnegappen.nl", "include_subdomains": true, "mode": "force-https" },
+ { "name": "hammer-corp.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "giddyaunt.net", "include_subdomains": true, "mode": "force-https" },
+ { "name": "git-stuff.tk", "include_subdomains": true, "mode": "force-https" },
+ { "name": "golfhausmallorca.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "hearty.tw", "include_subdomains": true, "mode": "force-https" },
+ { "name": "guso.ml", "include_subdomains": true, "mode": "force-https" },
+ { "name": "gza.jp", "include_subdomains": true, "mode": "force-https" },
+ { "name": "guso.tech", "include_subdomains": true, "mode": "force-https" },
+ { "name": "henry.gg", "include_subdomains": true, "mode": "force-https" },
+ { "name": "gruenes-wp.de", "include_subdomains": true, "mode": "force-https" },
+ { "name": "hannah.link", "include_subdomains": true, "mode": "force-https" },
+ { "name": "hac30.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "hakugin.me", "include_subdomains": true, "mode": "force-https" },
+ { "name": "guideo.ch", "include_subdomains": true, "mode": "force-https" },
+ { "name": "getpublii.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "hiltonhyland.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "habtium.es", "include_subdomains": true, "mode": "force-https" },
+ { "name": "gruene-wattenscheid.de", "include_subdomains": true, "mode": "force-https" },
+ { "name": "group4layers.net", "include_subdomains": true, "mode": "force-https" },
+ { "name": "governmentjobs.gov", "include_subdomains": true, "mode": "force-https" },
+ { "name": "grumpy.fr", "include_subdomains": true, "mode": "force-https" },
+ { "name": "green-care.nl", "include_subdomains": true, "mode": "force-https" },
+ { "name": "helencrump.co.uk", "include_subdomains": true, "mode": "force-https" },
+ { "name": "goanalyse.co.uk", "include_subdomains": true, "mode": "force-https" },
+ { "name": "hedonistic-imperative.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "hamacho-kyudo.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "gmod.de", "include_subdomains": true, "mode": "force-https" },
+ { "name": "habtium.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "handysex.live", "include_subdomains": true, "mode": "force-https" },
+ { "name": "habbos.es", "include_subdomains": true, "mode": "force-https" },
+ { "name": "hhs.gov", "include_subdomains": true, "mode": "force-https" },
+ { "name": "guso.gq", "include_subdomains": true, "mode": "force-https" },
+ { "name": "halongbaybackpackertour.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "heimprofis.de", "include_subdomains": true, "mode": "force-https" },
+ { "name": "honeypot.net", "include_subdomains": true, "mode": "force-https" },
+ { "name": "gsi-network.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "goombi.fr", "include_subdomains": true, "mode": "force-https" },
+ { "name": "hipercultura.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "gsmkungen.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "goodtech.com.br", "include_subdomains": true, "mode": "force-https" },
+ { "name": "haraj.com.sa", "include_subdomains": true, "mode": "force-https" },
+ { "name": "gnylf.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "hstspreload.org", "include_subdomains": true, "mode": "force-https" },
+ { "name": "halcyonsbastion.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "head-shop.lv", "include_subdomains": true, "mode": "force-https" },
+ { "name": "hrndz.io", "include_subdomains": true, "mode": "force-https" },
+ { "name": "grieg.net", "include_subdomains": true, "mode": "force-https" },
+ { "name": "feuerwerksmanufaktur.de", "include_subdomains": true, "mode": "force-https" },
+ { "name": "hardtfrieden.de", "include_subdomains": true, "mode": "force-https" },
+ { "name": "howsyourhealth.org", "include_subdomains": true, "mode": "force-https" },
+ { "name": "herecsrymy.cz", "include_subdomains": true, "mode": "force-https" },
+ { "name": "head-shop.lt", "include_subdomains": true, "mode": "force-https" },
+ { "name": "https.jetzt", "include_subdomains": true, "mode": "force-https" },
+ { "name": "helup.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "headshotharp.de", "include_subdomains": true, "mode": "force-https" },
+ { "name": "guenthernoack.de", "include_subdomains": true, "mode": "force-https" },
+ { "name": "http2.pro", "include_subdomains": true, "mode": "force-https" },
+ { "name": "hirzaconsult.ro", "include_subdomains": true, "mode": "force-https" },
+ { "name": "hr98.tk", "include_subdomains": true, "mode": "force-https" },
+ { "name": "hidbo.de", "include_subdomains": true, "mode": "force-https" },
+ { "name": "hilchenba.ch", "include_subdomains": true, "mode": "force-https" },
+ { "name": "fxpig-ib.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "hookbin.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "hydronium.me", "include_subdomains": true, "mode": "force-https" },
+ { "name": "hydronium.ga", "include_subdomains": true, "mode": "force-https" },
+ { "name": "hydronium.tk", "include_subdomains": true, "mode": "force-https" },
+ { "name": "hydronium.cf", "include_subdomains": true, "mode": "force-https" },
+ { "name": "hofiprojekt.cz", "include_subdomains": true, "mode": "force-https" },
+ { "name": "hintermeier-rae.at", "include_subdomains": true, "mode": "force-https" },
+ { "name": "herculex.fi", "include_subdomains": true, "mode": "force-https" },
+ { "name": "heartgames.pl", "include_subdomains": true, "mode": "force-https" },
+ { "name": "hump.dk", "include_subdomains": true, "mode": "force-https" },
+ { "name": "hms-waldmann.de", "include_subdomains": true, "mode": "force-https" },
+ { "name": "hunger.im", "include_subdomains": true, "mode": "force-https" },
+ { "name": "icodesign.me", "include_subdomains": true, "mode": "force-https" },
+ { "name": "harlentimberproducts.co.uk", "include_subdomains": true, "mode": "force-https" },
+ { "name": "gabriele-kluge.de", "include_subdomains": true, "mode": "force-https" },
+ { "name": "hwinfo.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "huwcbjones.co.uk", "include_subdomains": true, "mode": "force-https" },
+ { "name": "helingqi.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "hydronium.ml", "include_subdomains": true, "mode": "force-https" },
+ { "name": "huwjones.me", "include_subdomains": true, "mode": "force-https" },
+ { "name": "hiyacar.co.uk", "include_subdomains": true, "mode": "force-https" },
+ { "name": "htmue.net", "include_subdomains": true, "mode": "force-https" },
+ { "name": "hideftv.deals", "include_subdomains": true, "mode": "force-https" },
+ { "name": "i-rickroll-n.pw", "include_subdomains": true, "mode": "force-https" },
+ { "name": "httptest.net", "include_subdomains": true, "mode": "force-https" },
+ { "name": "hybridworx.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "gotirupati.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "hybridworx.net", "include_subdomains": true, "mode": "force-https" },
+ { "name": "huguesblanchard.paris", "include_subdomains": true, "mode": "force-https" },
+ { "name": "ibase.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "iamjoshellis.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "huangh.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "hoekwoningverkopen.nl", "include_subdomains": true, "mode": "force-https" },
+ { "name": "hotpoint-training.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "hybridworx.de", "include_subdomains": true, "mode": "force-https" },
+ { "name": "hp-work.net", "include_subdomains": true, "mode": "force-https" },
+ { "name": "heptner24.de", "include_subdomains": true, "mode": "force-https" },
+ { "name": "hybridworx.org", "include_subdomains": true, "mode": "force-https" },
+ { "name": "huchet.me", "include_subdomains": true, "mode": "force-https" },
+ { "name": "fws.gov", "include_subdomains": true, "mode": "force-https" },
+ { "name": "ilgi.work", "include_subdomains": true, "mode": "force-https" },
+ { "name": "huodongweb.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "honovere.de", "include_subdomains": true, "mode": "force-https" },
+ { "name": "hudhaifahgoga.co.za", "include_subdomains": true, "mode": "force-https" },
+ { "name": "immunicity.today", "include_subdomains": true, "mode": "force-https" },
+ { "name": "hszemi.de", "include_subdomains": true, "mode": "force-https" },
+ { "name": "grabi.ga", "include_subdomains": true, "mode": "force-https" },
+ { "name": "home-coaching.be", "include_subdomains": true, "mode": "force-https" },
+ { "name": "hanzubon.jp", "include_subdomains": true, "mode": "force-https" },
+ { "name": "ifengge.me", "include_subdomains": true, "mode": "force-https" },
+ { "name": "guso.site", "include_subdomains": true, "mode": "force-https" },
+ { "name": "hybridworx.eu", "include_subdomains": true, "mode": "force-https" },
+ { "name": "identifyme.net", "include_subdomains": true, "mode": "force-https" },
+ { "name": "i28s.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "hotelflow.com.br", "include_subdomains": true, "mode": "force-https" },
+ { "name": "immersionwealth.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "immunicity.world", "include_subdomains": true, "mode": "force-https" },
+ { "name": "hypnoresults.com.au", "include_subdomains": true, "mode": "force-https" },
+ { "name": "gtdgo.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "hvh.no", "include_subdomains": true, "mode": "force-https" },
+ { "name": "hostma.ma", "include_subdomains": true, "mode": "force-https" },
+ { "name": "immunicity.works", "include_subdomains": true, "mode": "force-https" },
+ { "name": "ibenchu.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "iamreubin.co.uk", "include_subdomains": true, "mode": "force-https" },
+ { "name": "ifx.ee", "include_subdomains": true, "mode": "force-https" },
+ { "name": "ilhansubasi.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "inforichjapan.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "ict-radar.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "interchangedesign.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "ict-radar.nl", "include_subdomains": true, "mode": "force-https" },
+ { "name": "ictradar.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "inviosolutions.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "iiong.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "ignat.by", "include_subdomains": true, "mode": "force-https" },
+ { "name": "internetovehazardnihry.cz", "include_subdomains": true, "mode": "force-https" },
+ { "name": "intercom.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "informatik-handwerk.de", "include_subdomains": true, "mode": "force-https" },
+ { "name": "inetpub.cn", "include_subdomains": true, "mode": "force-https" },
+ { "name": "instruktor.io", "include_subdomains": true, "mode": "force-https" },
+ { "name": "interchanges.io", "include_subdomains": true, "mode": "force-https" },
+ { "name": "intvonline.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "hypa.net.au", "include_subdomains": true, "mode": "force-https" },
+ { "name": "huendeleskopfhuette.de", "include_subdomains": true, "mode": "force-https" },
+ { "name": "info-screen.me", "include_subdomains": true, "mode": "force-https" },
+ { "name": "inima.org", "include_subdomains": true, "mode": "force-https" },
+ { "name": "indusap.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "infinity-freedom.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "hydra.zone", "include_subdomains": true, "mode": "force-https" },
+ { "name": "infopier.sg", "include_subdomains": true, "mode": "force-https" },
+ { "name": "ihrhost.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "inme.ga", "include_subdomains": true, "mode": "force-https" },
+ { "name": "independent-operators.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "interhosts.co.za", "include_subdomains": true, "mode": "force-https" },
+ { "name": "huberulrich.de", "include_subdomains": true, "mode": "force-https" },
+ { "name": "interessiert-uns.net", "include_subdomains": true, "mode": "force-https" },
+ { "name": "intelevo.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "itsgoingdown.org", "include_subdomains": true, "mode": "force-https" },
+ { "name": "ikzoekeengoedkopeauto.nl", "include_subdomains": true, "mode": "force-https" },
+ { "name": "ikarate.ru", "include_subdomains": true, "mode": "force-https" },
+ { "name": "ipfs.ink", "include_subdomains": true, "mode": "force-https" },
+ { "name": "ipuservicedesign.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "internetcom.jp", "include_subdomains": true, "mode": "force-https" },
+ { "name": "isthefieldcontrolsystemdown.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "integralblue.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "jackrusselterrier.com.br", "include_subdomains": true, "mode": "force-https" },
+ { "name": "intux.be", "include_subdomains": true, "mode": "force-https" },
+ { "name": "irmtrudjurke.de", "include_subdomains": true, "mode": "force-https" },
+ { "name": "internaldh.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "ikulist.me", "include_subdomains": true, "mode": "force-https" },
+ { "name": "it-fernau.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "ipv6.gr", "include_subdomains": true, "mode": "force-https" },
+ { "name": "installgentoo.net", "include_subdomains": true, "mode": "force-https" },
+ { "name": "inuyasha-petition.tk", "include_subdomains": true, "mode": "force-https" },
+ { "name": "ixec2.tk", "include_subdomains": true, "mode": "force-https" },
+ { "name": "jamhost.org", "include_subdomains": true, "mode": "force-https" },
+ { "name": "internaut.co.za", "include_subdomains": true, "mode": "force-https" },
+ { "name": "interracial.dating", "include_subdomains": true, "mode": "force-https" },
+ { "name": "ingesol.fr", "include_subdomains": true, "mode": "force-https" },
+ { "name": "isitdoneyet.gov", "include_subdomains": true, "mode": "force-https" },
+ { "name": "infinity-freedom.de", "include_subdomains": true, "mode": "force-https" },
+ { "name": "jaco.by", "include_subdomains": true, "mode": "force-https" },
+ { "name": "ithakama.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "jahner.xyz", "include_subdomains": true, "mode": "force-https" },
+ { "name": "ipv4.gr", "include_subdomains": true, "mode": "force-https" },
+ { "name": "infinity-lifestyle.de", "include_subdomains": true, "mode": "force-https" },
+ { "name": "ibizatopcharter.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "huroji.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "ipfp.pl", "include_subdomains": true, "mode": "force-https" },
+ { "name": "invisionita.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "ifengge.cn", "include_subdomains": true, "mode": "force-https" },
+ { "name": "ip.or.at", "include_subdomains": true, "mode": "force-https" },
+ { "name": "iservicio.mx", "include_subdomains": true, "mode": "force-https" },
+ { "name": "j-rickroll-a.pw", "include_subdomains": true, "mode": "force-https" },
+ { "name": "itooky.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "jabbas.eu", "include_subdomains": true, "mode": "force-https" },
+ { "name": "ijoda.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "istschonsolangeinrente.de", "include_subdomains": true, "mode": "force-https" },
+ { "name": "itfaq.nl", "include_subdomains": true, "mode": "force-https" },
+ { "name": "ja.md", "include_subdomains": true, "mode": "force-https" },
+ { "name": "inebula.it", "include_subdomains": true, "mode": "force-https" },
+ { "name": "ithakama.cz", "include_subdomains": true, "mode": "force-https" },
+ { "name": "irish.dating", "include_subdomains": true, "mode": "force-https" },
+ { "name": "edition-sonblom.de", "include_subdomains": true, "mode": "force-https" },
+ { "name": "jangho.me", "include_subdomains": true, "mode": "force-https" },
+ { "name": "injertoshorticolas.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "horeizai.net", "include_subdomains": true, "mode": "force-https" },
+ { "name": "indesit-training.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "idisplay.es", "include_subdomains": true, "mode": "force-https" },
+ { "name": "ivaoru.org", "include_subdomains": true, "mode": "force-https" },
+ { "name": "ishome.org", "include_subdomains": true, "mode": "force-https" },
+ { "name": "josecage.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "jasoncosper.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "hundeformel.de", "include_subdomains": true, "mode": "force-https" },
+ { "name": "javamilk.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "jamesknd.uk", "include_subdomains": true, "mode": "force-https" },
+ { "name": "julio.jamil.nom.br", "include_subdomains": true, "mode": "force-https" },
+ { "name": "isoface33.fr", "include_subdomains": true, "mode": "force-https" },
+ { "name": "jdtic.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "iphoneunlock.nu", "include_subdomains": true, "mode": "force-https" },
+ { "name": "jps-selection.eu", "include_subdomains": true, "mode": "force-https" },
+ { "name": "justinharrison.ca", "include_subdomains": true, "mode": "force-https" },
+ { "name": "jcf-office.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "jjj.blog", "include_subdomains": true, "mode": "force-https" },
+ { "name": "jetbbs.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "irmgard-woelfle.de", "include_subdomains": true, "mode": "force-https" },
+ { "name": "kaohub.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "jd-group.co.uk", "include_subdomains": true, "mode": "force-https" },
+ { "name": "jetzt-elektromobil.de", "include_subdomains": true, "mode": "force-https" },
+ { "name": "jdcdirectsales.com.ph", "include_subdomains": true, "mode": "force-https" },
+ { "name": "jobshq.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "itpro.ua", "include_subdomains": true, "mode": "force-https" },
+ { "name": "jps-selection.co.uk", "include_subdomains": true, "mode": "force-https" },
+ { "name": "jps-selection.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "johnsegovia.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "jabberzac.org", "include_subdomains": true, "mode": "force-https" },
+ { "name": "jimmehcai.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "jordans.co.uk", "include_subdomains": true, "mode": "force-https" },
+ { "name": "keksi.io", "include_subdomains": true, "mode": "force-https" },
+ { "name": "kerijacoby.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "karmic.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "jiripudil.cz", "include_subdomains": true, "mode": "force-https" },
+ { "name": "jinancy.fr", "include_subdomains": true, "mode": "force-https" },
+ { "name": "iteli.eu", "include_subdomains": true, "mode": "force-https" },
+ { "name": "keyserver.sexy", "include_subdomains": true, "mode": "force-https" },
+ { "name": "k-wallet.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "jungaa.fr", "include_subdomains": true, "mode": "force-https" },
+ { "name": "jcwodan.nl", "include_subdomains": true, "mode": "force-https" },
+ { "name": "jiaidu.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "jinshuju.net", "include_subdomains": true, "mode": "force-https" },
+ { "name": "joscares.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "jiangzm.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "jakobssystems.net", "include_subdomains": true, "mode": "force-https" },
+ { "name": "klickstdu.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "jm-bea.net", "include_subdomains": true, "mode": "force-https" },
+ { "name": "k-rickroll-g.pw", "include_subdomains": true, "mode": "force-https" },
+ { "name": "just-a-clanpage.de", "include_subdomains": true, "mode": "force-https" },
+ { "name": "k-scr.me", "include_subdomains": true, "mode": "force-https" },
+ { "name": "jvwdev.nl", "include_subdomains": true, "mode": "force-https" },
+ { "name": "jameswarp.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "jingyuesi.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "kaleidomarketing.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "joviam.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "karlis-kavacis.id.lv", "include_subdomains": true, "mode": "force-https" },
+ { "name": "jd1.de", "include_subdomains": true, "mode": "force-https" },
+ { "name": "jurko.cz", "include_subdomains": true, "mode": "force-https" },
+ { "name": "jmcleaning.services", "include_subdomains": true, "mode": "force-https" },
+ { "name": "karit.nz", "include_subdomains": true, "mode": "force-https" },
+ { "name": "kavinvin.me", "include_subdomains": true, "mode": "force-https" },
+ { "name": "kerem.xyz", "include_subdomains": true, "mode": "force-https" },
+ { "name": "kingtecservices.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "jeannelucienne.fr", "include_subdomains": true, "mode": "force-https" },
+ { "name": "jessicah.org", "include_subdomains": true, "mode": "force-https" },
+ { "name": "kkaefer.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "kafoom.de", "include_subdomains": true, "mode": "force-https" },
+ { "name": "kimoota.net", "include_subdomains": true, "mode": "force-https" },
+ { "name": "keinefilterblase.de", "include_subdomains": true, "mode": "force-https" },
+ { "name": "kirillpokrovsky.de", "include_subdomains": true, "mode": "force-https" },
+ { "name": "kourpe.online", "include_subdomains": true, "mode": "force-https" },
+ { "name": "itpros.ru", "include_subdomains": true, "mode": "force-https" },
+ { "name": "katja-nikolic-design.de", "include_subdomains": true, "mode": "force-https" },
+ { "name": "kalterersee.ch", "include_subdomains": true, "mode": "force-https" },
+ { "name": "karlstabo.se", "include_subdomains": true, "mode": "force-https" },
+ { "name": "kokumoto.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "kottur.is", "include_subdomains": true, "mode": "force-https" },
+ { "name": "kls-agency.com.ua", "include_subdomains": true, "mode": "force-https" },
+ { "name": "kiss-register.org", "include_subdomains": true, "mode": "force-https" },
+ { "name": "klimapartner.net", "include_subdomains": true, "mode": "force-https" },
+ { "name": "kozmik.co", "include_subdomains": true, "mode": "force-https" },
+ { "name": "kirchengemeinde-markt-erlbach.de", "include_subdomains": true, "mode": "force-https" },
+ { "name": "janssenwigman.nl", "include_subdomains": true, "mode": "force-https" },
+ { "name": "knowledgesnapsites.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "kappit.dk", "include_subdomains": true, "mode": "force-https" },
+ { "name": "labrat.mobi", "include_subdomains": true, "mode": "force-https" },
+ { "name": "klosko.net", "include_subdomains": true, "mode": "force-https" },
+ { "name": "kledingrekken.nl", "include_subdomains": true, "mode": "force-https" },
+ { "name": "institutulcultural.ro", "include_subdomains": true, "mode": "force-https" },
+ { "name": "kostuumstore.nl", "include_subdomains": true, "mode": "force-https" },
+ { "name": "it-sysoft.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "jobseekeritalia.it", "include_subdomains": true, "mode": "force-https" },
+ { "name": "freedomrealtyoftexas.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "kralik.io", "include_subdomains": true, "mode": "force-https" },
+ { "name": "kolba.design", "include_subdomains": true, "mode": "force-https" },
+ { "name": "krc.link", "include_subdomains": true, "mode": "force-https" },
+ { "name": "knaake.net", "include_subdomains": true, "mode": "force-https" },
+ { "name": "kgnk.ru", "include_subdomains": true, "mode": "force-https" },
+ { "name": "knapp.noip.me", "include_subdomains": true, "mode": "force-https" },
+ { "name": "kristjanrang.eu", "include_subdomains": true, "mode": "force-https" },
+ { "name": "kohlistkool.tk", "include_subdomains": true, "mode": "force-https" },
+ { "name": "klempnershop.eu", "include_subdomains": true, "mode": "force-https" },
+ { "name": "kprog.net", "include_subdomains": true, "mode": "force-https" },
+ { "name": "kraftfleisch.de", "include_subdomains": true, "mode": "force-https" },
+ { "name": "lanzainc.xyz", "include_subdomains": true, "mode": "force-https" },
+ { "name": "l-rickroll-i.pw", "include_subdomains": true, "mode": "force-https" },
+ { "name": "kuchentraum.eu", "include_subdomains": true, "mode": "force-https" },
+ { "name": "kotelezobiztositas.eu", "include_subdomains": true, "mode": "force-https" },
+ { "name": "kuketz-security.de", "include_subdomains": true, "mode": "force-https" },
+ { "name": "kuketz-blog.de", "include_subdomains": true, "mode": "force-https" },
+ { "name": "klimapartner.de", "include_subdomains": true, "mode": "force-https" },
+ { "name": "kub.hr", "include_subdomains": true, "mode": "force-https" },
+ { "name": "kotitesti.fi", "include_subdomains": true, "mode": "force-https" },
+ { "name": "kap-genial.de", "include_subdomains": true, "mode": "force-https" },
+ { "name": "lafr4nc3.xyz", "include_subdomains": true, "mode": "force-https" },
+ { "name": "jaksel.id", "include_subdomains": true, "mode": "force-https" },
+ { "name": "laniakean.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "lanyang.tk", "include_subdomains": true, "mode": "force-https" },
+ { "name": "lansechensilu.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "leaodarodesia.com.br", "include_subdomains": true, "mode": "force-https" },
+ { "name": "kotilinkki.fi", "include_subdomains": true, "mode": "force-https" },
+ { "name": "kyujin-office.net", "include_subdomains": true, "mode": "force-https" },
+ { "name": "laureltv.org", "include_subdomains": true, "mode": "force-https" },
+ { "name": "lampegiganten.dk", "include_subdomains": true, "mode": "force-https" },
+ { "name": "lapolla.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "late.am", "include_subdomains": true, "mode": "force-https" },
+ { "name": "gorf.club", "include_subdomains": true, "mode": "force-https" },
+ { "name": "krizevackapajdasija.hr", "include_subdomains": true, "mode": "force-https" },
+ { "name": "kontakthuman.hu", "include_subdomains": true, "mode": "force-https" },
+ { "name": "laughinggrapepublishing.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "laserpc.net", "include_subdomains": true, "mode": "force-https" },
+ { "name": "lanboll.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "legible.es", "include_subdomains": true, "mode": "force-https" },
+ { "name": "kitchenchaos.de", "include_subdomains": true, "mode": "force-https" },
+ { "name": "laquack.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "lazowik.pl", "include_subdomains": true, "mode": "force-https" },
+ { "name": "lhasaapso.com.br", "include_subdomains": true, "mode": "force-https" },
+ { "name": "jan-roenspies.de", "include_subdomains": true, "mode": "force-https" },
+ { "name": "lampenwelt.at", "include_subdomains": true, "mode": "force-https" },
+ { "name": "jjf.org.au", "include_subdomains": true, "mode": "force-https" },
+ { "name": "laubacher.io", "include_subdomains": true, "mode": "force-https" },
+ { "name": "lampenwelt.ch", "include_subdomains": true, "mode": "force-https" },
+ { "name": "lampen24.be", "include_subdomains": true, "mode": "force-https" },
+ { "name": "la-flora-negra.de", "include_subdomains": true, "mode": "force-https" },
+ { "name": "lampegiganten.no", "include_subdomains": true, "mode": "force-https" },
+ { "name": "leetsaber.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "kodak-ism.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "kuschelmonstershop.de", "include_subdomains": true, "mode": "force-https" },
+ { "name": "lets.ninja", "include_subdomains": true, "mode": "force-https" },
+ { "name": "kxind.cn", "include_subdomains": true, "mode": "force-https" },
+ { "name": "lifanov.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "lemuslimpost.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "lettersblogatory.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "lel.ovh", "include_subdomains": true, "mode": "force-https" },
+ { "name": "kids-at-home.ch", "include_subdomains": true, "mode": "force-https" },
+ { "name": "kuaza.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "leonhooijer.nl", "include_subdomains": true, "mode": "force-https" },
+ { "name": "lijero.co", "include_subdomains": true, "mode": "force-https" },
+ { "name": "lexicography.online", "include_subdomains": true, "mode": "force-https" },
+ { "name": "languageterminal.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "laplanetebleue.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "leftclick.cloud", "include_subdomains": true, "mode": "force-https" },
+ { "name": "lafosseobservatoire.be", "include_subdomains": true, "mode": "force-https" },
+ { "name": "latelierdekathy.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "lars-mense.de", "include_subdomains": true, "mode": "force-https" },
+ { "name": "lexico.pt", "include_subdomains": true, "mode": "force-https" },
+ { "name": "landgoedverkopen.nl", "include_subdomains": true, "mode": "force-https" },
+ { "name": "legends-game.ru", "include_subdomains": true, "mode": "force-https" },
+ { "name": "la-grande-jaugue.fr", "include_subdomains": true, "mode": "force-https" },
+ { "name": "letsencrypt-for-cpanel.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "liukang.tech", "include_subdomains": true, "mode": "force-https" },
+ { "name": "leticiagomeztagle.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "levans.fr", "include_subdomains": true, "mode": "force-https" },
+ { "name": "kvetinymilt.cz", "include_subdomains": true, "mode": "force-https" },
+ { "name": "liquidhost.co", "include_subdomains": true, "mode": "force-https" },
+ { "name": "lichttraeumer.de", "include_subdomains": true, "mode": "force-https" },
+ { "name": "linuxmint.cz", "include_subdomains": true, "mode": "force-https" },
+ { "name": "lajijonencadebarbera.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "linux-florida.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "lidl-shop.be", "include_subdomains": true, "mode": "force-https" },
+ { "name": "libble.eu", "include_subdomains": true, "mode": "force-https" },
+ { "name": "liftie.info", "include_subdomains": true, "mode": "force-https" },
+ { "name": "limix.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "lidl-shop.nl", "include_subdomains": true, "mode": "force-https" },
+ { "name": "lighttp.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "lianye.in", "include_subdomains": true, "mode": "force-https" },
+ { "name": "kuschelmonster.de", "include_subdomains": true, "mode": "force-https" },
+ { "name": "linss.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "localnetwork.nz", "include_subdomains": true, "mode": "force-https" },
+ { "name": "lecourtier.fr", "include_subdomains": true, "mode": "force-https" },
+ { "name": "livejasmin.dk", "include_subdomains": true, "mode": "force-https" },
+ { "name": "luludapomerania.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "grandchamproofing.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "loforo.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "lionlyrics.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "looktothestars.org", "include_subdomains": true, "mode": "force-https" },
+ { "name": "linux-mint.cz", "include_subdomains": true, "mode": "force-https" },
+ { "name": "librervac.org", "include_subdomains": true, "mode": "force-https" },
+ { "name": "lidow.eu", "include_subdomains": true, "mode": "force-https" },
+ { "name": "linguamilla.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "lights.co.uk", "include_subdomains": true, "mode": "force-https" },
+ { "name": "liquid.solutions", "include_subdomains": true, "mode": "force-https" },
+ { "name": "klugemedia.de", "include_subdomains": true, "mode": "force-https" },
+ { "name": "lifebetweenlives.com.au", "include_subdomains": true, "mode": "force-https" },
+ { "name": "lukasoppermann.de", "include_subdomains": true, "mode": "force-https" },
+ { "name": "lunarsoft.net", "include_subdomains": true, "mode": "force-https" },
+ { "name": "malamutedoalasca.com.br", "include_subdomains": true, "mode": "force-https" },
+ { "name": "kofler.info", "include_subdomains": true, "mode": "force-https" },
+ { "name": "linden.me", "include_subdomains": true, "mode": "force-https" },
+ { "name": "losless.fr", "include_subdomains": true, "mode": "force-https" },
+ { "name": "loongsg.xyz", "include_subdomains": true, "mode": "force-https" },
+ { "name": "majemedia.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "lebal.se", "include_subdomains": true, "mode": "force-https" },
+ { "name": "limawi.io", "include_subdomains": true, "mode": "force-https" },
+ { "name": "lidlovajogurteka.si", "include_subdomains": true, "mode": "force-https" },
+ { "name": "lostserver.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "lukas-schauer.de", "include_subdomains": true, "mode": "force-https" },
+ { "name": "lsc-dillingen.de", "include_subdomains": true, "mode": "force-https" },
+ { "name": "lukas-oppermann.de", "include_subdomains": true, "mode": "force-https" },
+ { "name": "lukas2511.de", "include_subdomains": true, "mode": "force-https" },
+ { "name": "lolpatrol.wtf", "include_subdomains": true, "mode": "force-https" },
+ { "name": "marksill.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "lukasoppermann.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "marsanvet.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "magnacumlaude.co", "include_subdomains": true, "mode": "force-https" },
+ { "name": "loveph.one", "include_subdomains": true, "mode": "force-https" },
+ { "name": "m-rickroll-v.pw", "include_subdomains": true, "mode": "force-https" },
+ { "name": "lmtm.eu", "include_subdomains": true, "mode": "force-https" },
+ { "name": "mastimtibetano.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "mapletime.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "luzfaltex.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "localhorst.xyz", "include_subdomains": true, "mode": "force-https" },
+ { "name": "lizhi.io", "include_subdomains": true, "mode": "force-https" },
+ { "name": "mastiffingles.com.br", "include_subdomains": true, "mode": "force-https" },
+ { "name": "lesquerda.cat", "include_subdomains": true, "mode": "force-https" },
+ { "name": "maskt.pw", "include_subdomains": true, "mode": "force-https" },
+ { "name": "ltecode.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "lucysan.net", "include_subdomains": true, "mode": "force-https" },
+ { "name": "lvmoo.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "maldiverna.guide", "include_subdomains": true, "mode": "force-https" },
+ { "name": "mammooc.org", "include_subdomains": true, "mode": "force-https" },
+ { "name": "mansdell.net", "include_subdomains": true, "mode": "force-https" },
+ { "name": "maillady-susume.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "matthi.coffee", "include_subdomains": true, "mode": "force-https" },
+ { "name": "m132.eu", "include_subdomains": true, "mode": "force-https" },
+ { "name": "lolmegafroi.de", "include_subdomains": true, "mode": "force-https" },
+ { "name": "lesliekearney.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "masterdemolitioninc.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "macoun.de", "include_subdomains": true, "mode": "force-https" },
+ { "name": "matrict.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "mbrooks.info", "include_subdomains": true, "mode": "force-https" },
+ { "name": "laufseminare-laufreisen.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "mailing-femprendedores.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "marco-polo-reisen.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "lila.pink", "include_subdomains": true, "mode": "force-https" },
+ { "name": "mapresidentielle.fr", "include_subdomains": true, "mode": "force-https" },
+ { "name": "mcsniper.co", "include_subdomains": true, "mode": "force-https" },
+ { "name": "materialism.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "mcjackk77.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "megaplonk.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "maxwellflynn.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "magicbroccoli.de", "include_subdomains": true, "mode": "force-https" },
+ { "name": "levindesalpes.fr", "include_subdomains": true, "mode": "force-https" },
+ { "name": "marine.gov", "include_subdomains": true, "mode": "force-https" },
+ { "name": "marriage-shrine.jp", "include_subdomains": true, "mode": "force-https" },
+ { "name": "mario.party", "include_subdomains": true, "mode": "force-https" },
+ { "name": "mediaarea.net", "include_subdomains": true, "mode": "force-https" },
+ { "name": "maservant.net", "include_subdomains": true, "mode": "force-https" },
+ { "name": "marinela.com.mx", "include_subdomains": true, "mode": "force-https" },
+ { "name": "margagriesser.de", "include_subdomains": true, "mode": "force-https" },
+ { "name": "matthias-muenzner.de", "include_subdomains": true, "mode": "force-https" },
+ { "name": "lorenadumitrascu.ro", "include_subdomains": true, "mode": "force-https" },
+ { "name": "lovelyblogacademy.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "manufacturing.gov", "include_subdomains": true, "mode": "force-https" },
+ { "name": "mentalhealth.gov", "include_subdomains": true, "mode": "force-https" },
+ { "name": "laurelblack.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "melhorproduto.com.br", "include_subdomains": true, "mode": "force-https" },
+ { "name": "metsasta.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "mackey7.net", "include_subdomains": true, "mode": "force-https" },
+ { "name": "matanz.de", "include_subdomains": true, "mode": "force-https" },
+ { "name": "mescaline.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "martine.nu", "include_subdomains": true, "mode": "force-https" },
+ { "name": "mega-feeling.de", "include_subdomains": true, "mode": "force-https" },
+ { "name": "locauxrama.fr", "include_subdomains": true, "mode": "force-https" },
+ { "name": "med-otzyv.ru", "include_subdomains": true, "mode": "force-https" },
+ { "name": "mhjuma.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "martiestrimsalon.nl", "include_subdomains": true, "mode": "force-https" },
+ { "name": "marbinvest.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "maestrano.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "mcga.media", "include_subdomains": true, "mode": "force-https" },
+ { "name": "metalsculpture.co.uk", "include_subdomains": true, "mode": "force-https" },
+ { "name": "markuskeppeler.no-ip.biz", "include_subdomains": true, "mode": "force-https" },
+ { "name": "mclist.it", "include_subdomains": true, "mode": "force-https" },
+ { "name": "maxhoechtl.at", "include_subdomains": true, "mode": "force-https" },
+ { "name": "menchez.me", "include_subdomains": true, "mode": "force-https" },
+ { "name": "martonmihaly.hu", "include_subdomains": true, "mode": "force-https" },
+ { "name": "maskinkultur.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "michaeleichorn.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "mecenat-cassous.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "medy-me.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "mathieui.net", "include_subdomains": true, "mode": "force-https" },
+ { "name": "medpics.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "mimocad.io", "include_subdomains": true, "mode": "force-https" },
+ { "name": "meldcode-assistent.nl", "include_subdomains": true, "mode": "force-https" },
+ { "name": "mine.world", "include_subdomains": true, "mode": "force-https" },
+ { "name": "massot.eu", "include_subdomains": true, "mode": "force-https" },
+ { "name": "medienservice-fritz.de", "include_subdomains": true, "mode": "force-https" },
+ { "name": "miraheze.org", "include_subdomains": true, "mode": "force-https" },
+ { "name": "massoni.pl", "include_subdomains": true, "mode": "force-https" },
+ { "name": "metadatawiki.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "media-instance.ru", "include_subdomains": true, "mode": "force-https" },
+ { "name": "modded-minecraft-server-list.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "meteenonline.nl", "include_subdomains": true, "mode": "force-https" },
+ { "name": "mattressinsider.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "melbourne.dating", "include_subdomains": true, "mode": "force-https" },
+ { "name": "mexior.nl", "include_subdomains": true, "mode": "force-https" },
+ { "name": "mika.moe", "include_subdomains": true, "mode": "force-https" },
+ { "name": "moho.kr", "include_subdomains": true, "mode": "force-https" },
+ { "name": "milldyke.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "mobileread.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "michaelpfrommer.de", "include_subdomains": true, "mode": "force-https" },
+ { "name": "molinero.xyz", "include_subdomains": true, "mode": "force-https" },
+ { "name": "modafinil.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "meanevo.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "minitrucktalk.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "mexican.dating", "include_subdomains": true, "mode": "force-https" },
+ { "name": "mgrossklaus.de", "include_subdomains": true, "mode": "force-https" },
+ { "name": "michaelsulzer.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "minenash.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "mikori.sk", "include_subdomains": true, "mode": "force-https" },
+ { "name": "modelcube.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "limpens.net", "include_subdomains": true, "mode": "force-https" },
+ { "name": "mahfouzadedimeji.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "malwarekillers.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "luxe-it.co.uk", "include_subdomains": true, "mode": "force-https" },
+ { "name": "mailon.ga", "include_subdomains": true, "mode": "force-https" },
+ { "name": "moodfoods.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "multiplexcy.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "montarfotoaki.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "mushroomandfern.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "klva.cz", "include_subdomains": true, "mode": "force-https" },
+ { "name": "it-schamans.de", "include_subdomains": true, "mode": "force-https" },
+ { "name": "it-shamans.eu", "include_subdomains": true, "mode": "force-https" },
+ { "name": "moobo.co.jp", "include_subdomains": true, "mode": "force-https" },
+ { "name": "moovablestorage.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "musewearflipflops.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "michelledonelan.co.uk", "include_subdomains": true, "mode": "force-https" },
+ { "name": "mokadev.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "mhermans.nl", "include_subdomains": true, "mode": "force-https" },
+ { "name": "mondedie.fr", "include_subdomains": true, "mode": "force-https" },
+ { "name": "mticareportal.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "mxihan.xyz", "include_subdomains": true, "mode": "force-https" },
+ { "name": "millstep.de", "include_subdomains": true, "mode": "force-https" },
+ { "name": "moefactory.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "moobo.xyz", "include_subdomains": true, "mode": "force-https" },
+ { "name": "mooselook.de", "include_subdomains": true, "mode": "force-https" },
+ { "name": "monautoneuve.fr", "include_subdomains": true, "mode": "force-https" },
+ { "name": "mybicc.org", "include_subdomains": true, "mode": "force-https" },
+ { "name": "mode-individuell.de", "include_subdomains": true, "mode": "force-https" },
+ { "name": "mikes.tk", "include_subdomains": true, "mode": "force-https" },
+ { "name": "mona-dress.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "mobisaar-cloud.de", "include_subdomains": true, "mode": "force-https" },
+ { "name": "mundschenk.at", "include_subdomains": true, "mode": "force-https" },
+ { "name": "murdercube.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "moechel.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "mt2414.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "mist.ink", "include_subdomains": true, "mode": "force-https" },
+ { "name": "mozart-game.cz", "include_subdomains": true, "mode": "force-https" },
+ { "name": "mrhee.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "moehrke.cc", "include_subdomains": true, "mode": "force-https" },
+ { "name": "nadia.pt", "include_subdomains": true, "mode": "force-https" },
+ { "name": "mozartgame.cz", "include_subdomains": true, "mode": "force-https" },
+ { "name": "msv-limpezas.pt", "include_subdomains": true, "mode": "force-https" },
+ { "name": "multiplayernow.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "mobix5.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "mysterysear.ch", "include_subdomains": true, "mode": "force-https" },
+ { "name": "misoji-resist.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "mobilesector.de", "include_subdomains": true, "mode": "force-https" },
+ { "name": "music-project.eu", "include_subdomains": true, "mode": "force-https" },
+ { "name": "mople71.cz", "include_subdomains": true, "mode": "force-https" },
+ { "name": "mlrslateroofing.com.au", "include_subdomains": true, "mode": "force-https" },
+ { "name": "munduch.cz", "include_subdomains": true, "mode": "force-https" },
+ { "name": "monstrus.de", "include_subdomains": true, "mode": "force-https" },
+ { "name": "mybboard.pl", "include_subdomains": true, "mode": "force-https" },
+ { "name": "myanimelist.net", "include_subdomains": true, "mode": "force-https" },
+ { "name": "martinec.co.uk", "include_subdomains": true, "mode": "force-https" },
+ { "name": "nbaimg.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "mvp-stars.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "mygalgame.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "mydreamlifelab.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "moscow.dating", "include_subdomains": true, "mode": "force-https" },
+ { "name": "myvoipnews.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "naughty.audio", "include_subdomains": true, "mode": "force-https" },
+ { "name": "kinmunity.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "newday.host", "include_subdomains": true, "mode": "force-https" },
+ { "name": "johnmalloneemd.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "mynook.info", "include_subdomains": true, "mode": "force-https" },
+ { "name": "my-dick.ru", "include_subdomains": true, "mode": "force-https" },
+ { "name": "mlvbphotography.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "ncands.net", "include_subdomains": true, "mode": "force-https" },
+ { "name": "n8ch.net", "include_subdomains": true, "mode": "force-https" },
+ { "name": "mosfet.cz", "include_subdomains": true, "mode": "force-https" },
+ { "name": "my-cdn.de", "include_subdomains": true, "mode": "force-https" },
+ { "name": "nedzad.me", "include_subdomains": true, "mode": "force-https" },
+ { "name": "mycard.moe", "include_subdomains": true, "mode": "force-https" },
+ { "name": "mrmoregame.de", "include_subdomains": true, "mode": "force-https" },
+ { "name": "newtrackon.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "neurobiology.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "nalinux.cz", "include_subdomains": true, "mode": "force-https" },
+ { "name": "nashira.cz", "include_subdomains": true, "mode": "force-https" },
+ { "name": "nedlinin.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "moyoo.net", "include_subdomains": true, "mode": "force-https" },
+ { "name": "mush-room.co.jp", "include_subdomains": true, "mode": "force-https" },
+ { "name": "neuropharmacology.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "nf9q.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "mycompanion.cz", "include_subdomains": true, "mode": "force-https" },
+ { "name": "nemumu.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "n6a.net", "include_subdomains": true, "mode": "force-https" },
+ { "name": "mrserge.lv", "include_subdomains": true, "mode": "force-https" },
+ { "name": "mysqldump-secure.org", "include_subdomains": true, "mode": "force-https" },
+ { "name": "nadyaolcer.fr", "include_subdomains": true, "mode": "force-https" },
+ { "name": "namereel.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "n-un.de", "include_subdomains": true, "mode": "force-https" },
+ { "name": "myepass.de", "include_subdomains": true, "mode": "force-https" },
+ { "name": "neatous.net", "include_subdomains": true, "mode": "force-https" },
+ { "name": "mydebian.in.ua", "include_subdomains": true, "mode": "force-https" },
+ { "name": "neatous.cz", "include_subdomains": true, "mode": "force-https" },
+ { "name": "muslimbanter.co.za", "include_subdomains": true, "mode": "force-https" },
+ { "name": "nqesh.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "ndy.sex", "include_subdomains": true, "mode": "force-https" },
+ { "name": "niklas.pw", "include_subdomains": true, "mode": "force-https" },
+ { "name": "mywari.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "nakuro.de", "include_subdomains": true, "mode": "force-https" },
+ { "name": "no-ip.cz", "include_subdomains": true, "mode": "force-https" },
+ { "name": "nll.fi", "include_subdomains": true, "mode": "force-https" },
+ { "name": "nietzsche.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "novascan.net", "include_subdomains": true, "mode": "force-https" },
+ { "name": "newind.info", "include_subdomains": true, "mode": "force-https" },
+ { "name": "note7forever.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "megablogging.org", "include_subdomains": true, "mode": "force-https" },
+ { "name": "numberzero.org", "include_subdomains": true, "mode": "force-https" },
+ { "name": "nohttps.org", "include_subdomains": true, "mode": "force-https" },
+ { "name": "nephos.xyz", "include_subdomains": true, "mode": "force-https" },
+ { "name": "neuronfactor.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "noticiasdehumor.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "nextpages.de", "include_subdomains": true, "mode": "force-https" },
+ { "name": "netwarc.eu", "include_subdomains": true, "mode": "force-https" },
+ { "name": "notinglife.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "nifpnet.nl", "include_subdomains": true, "mode": "force-https" },
+ { "name": "muehlemann.net", "include_subdomains": true, "mode": "force-https" },
+ { "name": "nootropic.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "neartothesky.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "normaculta.com.br", "include_subdomains": true, "mode": "force-https" },
+ { "name": "nicolas-hoffmann.net", "include_subdomains": true, "mode": "force-https" },
+ { "name": "mystown.org", "include_subdomains": true, "mode": "force-https" },
+ { "name": "mutuelle-obligatoire-pme.fr", "include_subdomains": true, "mode": "force-https" },
+ { "name": "nexusconnectinternational.eu", "include_subdomains": true, "mode": "force-https" },
+ { "name": "nsure.us", "include_subdomains": true, "mode": "force-https" },
+ { "name": "noisyfox.cn", "include_subdomains": true, "mode": "force-https" },
+ { "name": "oheila.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "octolopagon.games", "include_subdomains": true, "mode": "force-https" },
+ { "name": "nup.pw", "include_subdomains": true, "mode": "force-https" },
+ { "name": "numista.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "motorbiketourhanoi.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "oldenglishsheepdog.com.br", "include_subdomains": true, "mode": "force-https" },
+ { "name": "okchicas.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "nickdekruijk.nl", "include_subdomains": true, "mode": "force-https" },
+ { "name": "nyphox.net", "include_subdomains": true, "mode": "force-https" },
+ { "name": "next47.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "nys-hk.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "ofggolf.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "o-rickroll-y.pw", "include_subdomains": true, "mode": "force-https" },
+ { "name": "nkp-media.de", "include_subdomains": true, "mode": "force-https" },
+ { "name": "nzmk.cz", "include_subdomains": true, "mode": "force-https" },
+ { "name": "not-a.link", "include_subdomains": true, "mode": "force-https" },
+ { "name": "olygazoo.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "nohm.eu", "include_subdomains": true, "mode": "force-https" },
+ { "name": "notesforpebble.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "njpjanssen.nl", "include_subdomains": true, "mode": "force-https" },
+ { "name": "ocapic.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "oflow.me", "include_subdomains": true, "mode": "force-https" },
+ { "name": "noodplan.co.za", "include_subdomains": true, "mode": "force-https" },
+ { "name": "nordwaldzendo.de", "include_subdomains": true, "mode": "force-https" },
+ { "name": "neofelhz.space", "include_subdomains": true, "mode": "force-https" },
+ { "name": "nurses.dating", "include_subdomains": true, "mode": "force-https" },
+ { "name": "oktoberfeststore.nl", "include_subdomains": true, "mode": "force-https" },
+ { "name": "osburn.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "olswangtrainees.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "msuess.me", "include_subdomains": true, "mode": "force-https" },
+ { "name": "new.travel.pl", "include_subdomains": true, "mode": "force-https" },
+ { "name": "pagiamtzis.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "octopus-agents.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "orchidspaper.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "offenedialoge.de", "include_subdomains": true, "mode": "force-https" },
+ { "name": "office-ruru.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "otmns.net", "include_subdomains": true, "mode": "force-https" },
+ { "name": "parkwithark.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "olivierpieters.be", "include_subdomains": true, "mode": "force-https" },
+ { "name": "oxytocin.org", "include_subdomains": true, "mode": "force-https" },
+ { "name": "oeko-bundesfreiwilligendienst-sh.de", "include_subdomains": true, "mode": "force-https" },
+ { "name": "newhdmovies.io", "include_subdomains": true, "mode": "force-https" },
+ { "name": "numm.fr", "include_subdomains": true, "mode": "force-https" },
+ { "name": "ocad.com.au", "include_subdomains": true, "mode": "force-https" },
+ { "name": "orangetravel.eu", "include_subdomains": true, "mode": "force-https" },
+ { "name": "paedlink.ca", "include_subdomains": true, "mode": "force-https" },
+ { "name": "pastordocaucaso.com.br", "include_subdomains": true, "mode": "force-https" },
+ { "name": "pastorbelgagroenendael.com.br", "include_subdomains": true, "mode": "force-https" },
+ { "name": "pastorcanadense.com.br", "include_subdomains": true, "mode": "force-https" },
+ { "name": "oeko-jahr.de", "include_subdomains": true, "mode": "force-https" },
+ { "name": "onioncloud.org", "include_subdomains": true, "mode": "force-https" },
+ { "name": "ning.so", "include_subdomains": true, "mode": "force-https" },
+ { "name": "paino.cloud", "include_subdomains": true, "mode": "force-https" },
+ { "name": "p-rickroll-o.pw", "include_subdomains": true, "mode": "force-https" },
+ { "name": "onrr.gov", "include_subdomains": true, "mode": "force-https" },
+ { "name": "opinello.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "pastormaremanoabruzes.com.br", "include_subdomains": true, "mode": "force-https" },
+ { "name": "oeko-bundesfreiwilligendienst.de", "include_subdomains": true, "mode": "force-https" },
+ { "name": "panpsychism.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "outerlimitsdigital.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "notcompletelycorrect.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "paradise-engineering.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "onfarma.it", "include_subdomains": true, "mode": "force-https" },
+ { "name": "overture.london", "include_subdomains": true, "mode": "force-https" },
+ { "name": "offshoremarineparts.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "ordernow.at", "include_subdomains": true, "mode": "force-https" },
+ { "name": "nutikell.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "passthepopcorn.me", "include_subdomains": true, "mode": "force-https" },
+ { "name": "oskuro.net", "include_subdomains": true, "mode": "force-https" },
+ { "name": "nn.cz", "include_subdomains": true, "mode": "force-https" },
+ { "name": "palmer.im", "include_subdomains": true, "mode": "force-https" },
+ { "name": "panoranordic.net", "include_subdomains": true, "mode": "force-https" },
+ { "name": "oec-music.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "ownspec.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "okaz.de", "include_subdomains": true, "mode": "force-https" },
+ { "name": "oppejoud.ee", "include_subdomains": true, "mode": "force-https" },
+ { "name": "okad.eu", "include_subdomains": true, "mode": "force-https" },
+ { "name": "orkestar-krizevci.hr", "include_subdomains": true, "mode": "force-https" },
+ { "name": "online-eikaiwa-guide.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "orthodoxy.lt", "include_subdomains": true, "mode": "force-https" },
+ { "name": "partridge.tech", "include_subdomains": true, "mode": "force-https" },
+ { "name": "nutricuerpo.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "participatorybudgeting.de", "include_subdomains": true, "mode": "force-https" },
+ { "name": "pinscher.com.br", "include_subdomains": true, "mode": "force-https" },
+ { "name": "pentest.blog", "include_subdomains": true, "mode": "force-https" },
+ { "name": "pixelcubed.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "phurl.io", "include_subdomains": true, "mode": "force-https" },
+ { "name": "phpkari.cz", "include_subdomains": true, "mode": "force-https" },
+ { "name": "peyote.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "peromsik.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "paddy.rocks", "include_subdomains": true, "mode": "force-https" },
+ { "name": "phcorner.net", "include_subdomains": true, "mode": "force-https" },
+ { "name": "osborneinn.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "pidomex.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "osxentwicklerforum.de", "include_subdomains": true, "mode": "force-https" },
+ { "name": "pic2map.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "personalcommunicationsecurity.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "paio2-rec.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "participatorybudgeting.info", "include_subdomains": true, "mode": "force-https" },
+ { "name": "paio2.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "piratesforums.co", "include_subdomains": true, "mode": "force-https" },
+ { "name": "pitchpinecapital.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "paulswartz.net", "include_subdomains": true, "mode": "force-https" },
+ { "name": "paypod.org", "include_subdomains": true, "mode": "force-https" },
+ { "name": "orro.ro", "include_subdomains": true, "mode": "force-https" },
+ { "name": "pavelfojt.cz", "include_subdomains": true, "mode": "force-https" },
+ { "name": "pdfresizer.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "peirong.me", "include_subdomains": true, "mode": "force-https" },
+ { "name": "opsafewinter.net", "include_subdomains": true, "mode": "force-https" },
+ { "name": "pointeringles.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "perzeidi.hr", "include_subdomains": true, "mode": "force-https" },
+ { "name": "paterno-gaming.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "pcxserver.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "phoxmeh.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "patikabiztositas.hu", "include_subdomains": true, "mode": "force-https" },
+ { "name": "pehapkari.cz", "include_subdomains": true, "mode": "force-https" },
+ { "name": "patriaco.net", "include_subdomains": true, "mode": "force-https" },
+ { "name": "peg.nu", "include_subdomains": true, "mode": "force-https" },
+ { "name": "ourai.ws", "include_subdomains": true, "mode": "force-https" },
+ { "name": "parabhairavayoga.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "pc-rescue.me", "include_subdomains": true, "mode": "force-https" },
+ { "name": "paulrotter.de", "include_subdomains": true, "mode": "force-https" },
+ { "name": "physicalism.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "pamaniqu.nl", "include_subdomains": true, "mode": "force-https" },
+ { "name": "pinpayments.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "paulrobertlloyd.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "pi-eng.fr", "include_subdomains": true, "mode": "force-https" },
+ { "name": "piem.org", "include_subdomains": true, "mode": "force-https" },
+ { "name": "physicalist.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "phototag.org", "include_subdomains": true, "mode": "force-https" },
+ { "name": "peterhuetz.at", "include_subdomains": true, "mode": "force-https" },
+ { "name": "procrastinationland.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "phillippi.me", "include_subdomains": true, "mode": "force-https" },
+ { "name": "piggott.me.uk", "include_subdomains": true, "mode": "force-https" },
+ { "name": "paulerhof.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "oldchaphome.nl", "include_subdomains": true, "mode": "force-https" },
+ { "name": "proxyowl.pw", "include_subdomains": true, "mode": "force-https" },
+ { "name": "practodev.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "prideindomination.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "pstudio.me", "include_subdomains": true, "mode": "force-https" },
+ { "name": "primates.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "phosagro.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "puli.com.br", "include_subdomains": true, "mode": "force-https" },
+ { "name": "power-coonies.de", "include_subdomains": true, "mode": "force-https" },
+ { "name": "peterhuetz.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "poollicht.be", "include_subdomains": true, "mode": "force-https" },
+ { "name": "pm-partners-management-dev.azurewebsites.net", "include_subdomains": true, "mode": "force-https" },
+ { "name": "povareschka.ru", "include_subdomains": true, "mode": "force-https" },
+ { "name": "politik-bei-uns.de", "include_subdomains": true, "mode": "force-https" },
+ { "name": "pm13-media.cz", "include_subdomains": true, "mode": "force-https" },
+ { "name": "principia-journal.de", "include_subdomains": true, "mode": "force-https" },
+ { "name": "pornbase.info", "include_subdomains": true, "mode": "force-https" },
+ { "name": "practicepanther.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "pozytywnyplan.pl", "include_subdomains": true, "mode": "force-https" },
+ { "name": "personalizedtouch.co", "include_subdomains": true, "mode": "force-https" },
+ { "name": "picsandtours.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "pm-onboarding-external-dev.azurewebsites.net", "include_subdomains": true, "mode": "force-https" },
+ { "name": "q-rickroll-u.pw", "include_subdomains": true, "mode": "force-https" },
+ { "name": "ravage.fm", "include_subdomains": true, "mode": "force-https" },
+ { "name": "posaunenchor-senden.de", "include_subdomains": true, "mode": "force-https" },
+ { "name": "pmsf.eu", "include_subdomains": true, "mode": "force-https" },
+ { "name": "psychedelics.org", "include_subdomains": true, "mode": "force-https" },
+ { "name": "online-pr.at", "include_subdomains": true, "mode": "force-https" },
+ { "name": "rainbowbay.org", "include_subdomains": true, "mode": "force-https" },
+ { "name": "principia-magazin.de", "include_subdomains": true, "mode": "force-https" },
+ { "name": "presscenter.jp", "include_subdomains": true, "mode": "force-https" },
+ { "name": "psychedelia.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "qe2homelottery.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "psychoactive.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "r-rickroll-u.pw", "include_subdomains": true, "mode": "force-https" },
+ { "name": "rainm.eu", "include_subdomains": true, "mode": "force-https" },
+ { "name": "rally-base.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "novurania.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "nandex.org", "include_subdomains": true, "mode": "force-https" },
+ { "name": "qqj.net", "include_subdomains": true, "mode": "force-https" },
+ { "name": "rasagiline.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "primewho.org", "include_subdomains": true, "mode": "force-https" },
+ { "name": "questsocial.it", "include_subdomains": true, "mode": "force-https" },
+ { "name": "rathorian.fr", "include_subdomains": true, "mode": "force-https" },
+ { "name": "r-cut.fr", "include_subdomains": true, "mode": "force-https" },
+ { "name": "quarterfull.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "qkmortgage.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "peplog.nl", "include_subdomains": true, "mode": "force-https" },
+ { "name": "pyrotechnologie.de", "include_subdomains": true, "mode": "force-https" },
+ { "name": "randomhero.cloud", "include_subdomains": true, "mode": "force-https" },
+ { "name": "redheeler.com.br", "include_subdomains": true, "mode": "force-https" },
+ { "name": "regolithmedia.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "pixdigital.net", "include_subdomains": true, "mode": "force-https" },
+ { "name": "proggersession.de", "include_subdomains": true, "mode": "force-https" },
+ { "name": "mijnetickets.nl", "include_subdomains": true, "mode": "force-https" },
+ { "name": "puneflowermall.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "ramshair.jp", "include_subdomains": true, "mode": "force-https" },
+ { "name": "regain.us", "include_subdomains": true, "mode": "force-https" },
+ { "name": "progarm.org", "include_subdomains": true, "mode": "force-https" },
+ { "name": "prolan.pw", "include_subdomains": true, "mode": "force-https" },
+ { "name": "raymondelooff.nl", "include_subdomains": true, "mode": "force-https" },
+ { "name": "probiv.biz", "include_subdomains": true, "mode": "force-https" },
+ { "name": "relaybox.io", "include_subdomains": true, "mode": "force-https" },
+ { "name": "recurly.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "plueschmikroben.de", "include_subdomains": true, "mode": "force-https" },
+ { "name": "rhodesianridgeback.com.br", "include_subdomains": true, "mode": "force-https" },
+ { "name": "policedriver.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "pwfrance.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "qweepi.de", "include_subdomains": true, "mode": "force-https" },
+ { "name": "rei.ki", "include_subdomains": true, "mode": "force-https" },
+ { "name": "pugovka72.ru", "include_subdomains": true, "mode": "force-https" },
+ { "name": "plus-5.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "reptrax.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "purplepr.bg", "include_subdomains": true, "mode": "force-https" },
+ { "name": "repugnant-conclusion.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "reproductive-revolution.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "reaganlibrary.gov", "include_subdomains": true, "mode": "force-https" },
+ { "name": "rc-offi.net", "include_subdomains": true, "mode": "force-https" },
+ { "name": "plueschmikrobe.de", "include_subdomains": true, "mode": "force-https" },
+ { "name": "remedica.fr", "include_subdomains": true, "mode": "force-https" },
+ { "name": "professors.ee", "include_subdomains": true, "mode": "force-https" },
+ { "name": "puurwonengeldrop.nl", "include_subdomains": true, "mode": "force-https" },
+ { "name": "pruikshop.nl", "include_subdomains": true, "mode": "force-https" },
+ { "name": "robototes.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "questionable.host", "include_subdomains": true, "mode": "force-https" },
+ { "name": "printeknologies.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "reinout.nu", "include_subdomains": true, "mode": "force-https" },
+ { "name": "rechenwerk.net", "include_subdomains": true, "mode": "force-https" },
+ { "name": "ripple.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "renearends.nl", "include_subdomains": true, "mode": "force-https" },
+ { "name": "plueschvirus.de", "include_subdomains": true, "mode": "force-https" },
+ { "name": "relatethesport.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "richterphilipp.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "respon.jp", "include_subdomains": true, "mode": "force-https" },
+ { "name": "rencaijia.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "ridwan.co", "include_subdomains": true, "mode": "force-https" },
+ { "name": "reinouthoornweg.nl", "include_subdomains": true, "mode": "force-https" },
+ { "name": "reality0ne.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "rca.fr", "include_subdomains": true, "mode": "force-https" },
+ { "name": "rehabthailand.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "rtejr.ie", "include_subdomains": true, "mode": "force-https" },
+ { "name": "real-compare.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "rogerriendeau.ca", "include_subdomains": true, "mode": "force-https" },
+ { "name": "quality1.com.br", "include_subdomains": true, "mode": "force-https" },
+ { "name": "roelof.io", "include_subdomains": true, "mode": "force-https" },
+ { "name": "renerehelse.no", "include_subdomains": true, "mode": "force-https" },
+ { "name": "rivlo.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "redprice.by", "include_subdomains": true, "mode": "force-https" },
+ { "name": "robust.ga", "include_subdomains": true, "mode": "force-https" },
+ { "name": "rro.rs", "include_subdomains": true, "mode": "force-https" },
+ { "name": "rootusers.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "rimo.site", "include_subdomains": true, "mode": "force-https" },
+ { "name": "sa.net", "include_subdomains": true, "mode": "force-https" },
+ { "name": "proteapower.co.za", "include_subdomains": true, "mode": "force-https" },
+ { "name": "rememberthis.co.za", "include_subdomains": true, "mode": "force-https" },
+ { "name": "sadbox.org", "include_subdomains": true, "mode": "force-https" },
+ { "name": "sadbox.es", "include_subdomains": true, "mode": "force-https" },
+ { "name": "rickrongen.nl", "include_subdomains": true, "mode": "force-https" },
+ { "name": "rubyist.today", "include_subdomains": true, "mode": "force-https" },
+ { "name": "relatic.net", "include_subdomains": true, "mode": "force-https" },
+ { "name": "rayiris.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "rhees.nl", "include_subdomains": true, "mode": "force-https" },
+ { "name": "roo.ie", "include_subdomains": true, "mode": "force-https" },
+ { "name": "rem0te.net", "include_subdomains": true, "mode": "force-https" },
+ { "name": "roerstaafjes.nl", "include_subdomains": true, "mode": "force-https" },
+ { "name": "openkim.org", "include_subdomains": true, "mode": "force-https" },
+ { "name": "righettod.eu", "include_subdomains": true, "mode": "force-https" },
+ { "name": "redoakmedia.net", "include_subdomains": true, "mode": "force-https" },
+ { "name": "runtl.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "roflcopter.fr", "include_subdomains": true, "mode": "force-https" },
+ { "name": "riverbanktearooms.co.uk", "include_subdomains": true, "mode": "force-https" },
+ { "name": "safetyrisk.net", "include_subdomains": true, "mode": "force-https" },
+ { "name": "roketix.co.uk", "include_subdomains": true, "mode": "force-https" },
+ { "name": "restoruns.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "ruska-modra.cz", "include_subdomains": true, "mode": "force-https" },
+ { "name": "roleplayhome.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "ruskamodra.cz", "include_subdomains": true, "mode": "force-https" },
+ { "name": "room3b.eu", "include_subdomains": true, "mode": "force-https" },
+ { "name": "plueschviren.de", "include_subdomains": true, "mode": "force-https" },
+ { "name": "s-rickroll-p.pw", "include_subdomains": true, "mode": "force-https" },
+ { "name": "rjnutrition.consulting", "include_subdomains": true, "mode": "force-https" },
+ { "name": "plushmania.de", "include_subdomains": true, "mode": "force-https" },
+ { "name": "reinaldudras.ee", "include_subdomains": true, "mode": "force-https" },
+ { "name": "repair.by", "include_subdomains": true, "mode": "force-https" },
+ { "name": "nzquakes.maori.nz", "include_subdomains": true, "mode": "force-https" },
+ { "name": "riesenmikroben.de", "include_subdomains": true, "mode": "force-https" },
+ { "name": "riesenmikrobe.de", "include_subdomains": true, "mode": "force-https" },
+ { "name": "rus-trip.ru", "include_subdomains": true, "mode": "force-https" },
+ { "name": "salamanderpaddlegear.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "securethe.news", "include_subdomains": true, "mode": "force-https" },
+ { "name": "muckingabout.eu", "include_subdomains": true, "mode": "force-https" },
+ { "name": "safetext.me", "include_subdomains": true, "mode": "force-https" },
+ { "name": "ruhrnalist.de", "include_subdomains": true, "mode": "force-https" },
+ { "name": "rullzer.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "rrom.me", "include_subdomains": true, "mode": "force-https" },
+ { "name": "roxtri.cz", "include_subdomains": true, "mode": "force-https" },
+ { "name": "schsrch.xyz", "include_subdomains": true, "mode": "force-https" },
+ { "name": "saotn.org", "include_subdomains": true, "mode": "force-https" },
+ { "name": "scryfall.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "seattlewalkinbathtubs.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "saxoncreative.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "rugby.video", "include_subdomains": true, "mode": "force-https" },
+ { "name": "scepticism.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "saludsis.mil.co", "include_subdomains": true, "mode": "force-https" },
+ { "name": "savageorgiev.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "selegiline.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "semianalog.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "safelist.eu", "include_subdomains": true, "mode": "force-https" },
+ { "name": "sensebridge.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "schauer.so", "include_subdomains": true, "mode": "force-https" },
+ { "name": "sendthisfile.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "safeex.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "sandrolittke.de", "include_subdomains": true, "mode": "force-https" },
+ { "name": "rw-solutions.tech", "include_subdomains": true, "mode": "force-https" },
+ { "name": "science-questions.org", "include_subdomains": true, "mode": "force-https" },
+ { "name": "sandmarc.cz", "include_subdomains": true, "mode": "force-https" },
+ { "name": "psicologoforensebarcelona.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "sensualism.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "sensebridge.net", "include_subdomains": true, "mode": "force-https" },
+ { "name": "securejabber.me", "include_subdomains": true, "mode": "force-https" },
+ { "name": "setterirlandes.com.br", "include_subdomains": true, "mode": "force-https" },
+ { "name": "safewings-nh.nl", "include_subdomains": true, "mode": "force-https" },
+ { "name": "rubyquincunx.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "self-evident.org", "include_subdomains": true, "mode": "force-https" },
+ { "name": "securitystrata.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "secitem.at", "include_subdomains": true, "mode": "force-https" },
+ { "name": "ronomon.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "sanderkoenders.nl", "include_subdomains": true, "mode": "force-https" },
+ { "name": "secitem.de", "include_subdomains": true, "mode": "force-https" },
+ { "name": "scootfleet.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "selfhosters.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "sendonce.io", "include_subdomains": true, "mode": "force-https" },
+ { "name": "shiftj.is", "include_subdomains": true, "mode": "force-https" },
+ { "name": "scottferguson.com.au", "include_subdomains": true, "mode": "force-https" },
+ { "name": "shibainu.com.br", "include_subdomains": true, "mode": "force-https" },
+ { "name": "securitywithnick.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "shenghaiautoparts.net", "include_subdomains": true, "mode": "force-https" },
+ { "name": "schoolotzyv.ru", "include_subdomains": true, "mode": "force-https" },
+ { "name": "sensepixel.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "sambaash.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "royalsignaturecruise.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "serversuit.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "senseofnumber.co.uk", "include_subdomains": true, "mode": "force-https" },
+ { "name": "sanderkoenders.eu", "include_subdomains": true, "mode": "force-https" },
+ { "name": "shinonome-lab.eu.org", "include_subdomains": true, "mode": "force-https" },
+ { "name": "satai.dk", "include_subdomains": true, "mode": "force-https" },
+ { "name": "sansdev.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "rprimas.duckdns.org", "include_subdomains": true, "mode": "force-https" },
+ { "name": "senarius.de", "include_subdomains": true, "mode": "force-https" },
+ { "name": "schwarztrade.cz", "include_subdomains": true, "mode": "force-https" },
+ { "name": "scoolcode.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "sciencemonster.co.uk", "include_subdomains": true, "mode": "force-https" },
+ { "name": "seccom.ch", "include_subdomains": true, "mode": "force-https" },
+ { "name": "pchospital.cc", "include_subdomains": true, "mode": "force-https" },
+ { "name": "serverlauget.no", "include_subdomains": true, "mode": "force-https" },
+ { "name": "security-thoughts.org", "include_subdomains": true, "mode": "force-https" },
+ { "name": "sendway.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "sellservs.co.za", "include_subdomains": true, "mode": "force-https" },
+ { "name": "seniors.singles", "include_subdomains": true, "mode": "force-https" },
+ { "name": "sgroup-rec.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "server-essentials.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "seguroviagem.srv.br", "include_subdomains": true, "mode": "force-https" },
+ { "name": "simeonoff.ninja", "include_subdomains": true, "mode": "force-https" },
+ { "name": "riesenviren.de", "include_subdomains": true, "mode": "force-https" },
+ { "name": "selfdestruct.net", "include_subdomains": true, "mode": "force-https" },
+ { "name": "shota.party", "include_subdomains": true, "mode": "force-https" },
+ { "name": "sgroup-hitoduma.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "silverlinkz.net", "include_subdomains": true, "mode": "force-https" },
+ { "name": "sims4hub.ga", "include_subdomains": true, "mode": "force-https" },
+ { "name": "sidepodcastextra.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "sit.ec", "include_subdomains": true, "mode": "force-https" },
+ { "name": "ravkr.duckdns.org", "include_subdomains": true, "mode": "force-https" },
+ { "name": "simonsmh.cc", "include_subdomains": true, "mode": "force-https" },
+ { "name": "sirtaptap.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "servermonkey.nl", "include_subdomains": true, "mode": "force-https" },
+ { "name": "slovoice.org", "include_subdomains": true, "mode": "force-https" },
+ { "name": "shymeck.pw", "include_subdomains": true, "mode": "force-https" },
+ { "name": "short-biography.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "shipard.cz", "include_subdomains": true, "mode": "force-https" },
+ { "name": "sinonimosonline.com.br", "include_subdomains": true, "mode": "force-https" },
+ { "name": "schutznetze24.de", "include_subdomains": true, "mode": "force-https" },
+ { "name": "shm-forum.org.uk", "include_subdomains": true, "mode": "force-https" },
+ { "name": "shansing.cn", "include_subdomains": true, "mode": "force-https" },
+ { "name": "sinonimos.com.br", "include_subdomains": true, "mode": "force-https" },
+ { "name": "skory.us", "include_subdomains": true, "mode": "force-https" },
+ { "name": "shang-yu.cn", "include_subdomains": true, "mode": "force-https" },
+ { "name": "shiftdevices.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "snekchat.moe", "include_subdomains": true, "mode": "force-https" },
+ { "name": "smartwelve.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "seobot.com.au", "include_subdomains": true, "mode": "force-https" },
+ { "name": "smartcheck.gov", "include_subdomains": true, "mode": "force-https" },
+ { "name": "salmonvision.com.tw", "include_subdomains": true, "mode": "force-https" },
+ { "name": "shaken110.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "shadowguardian507.tk", "include_subdomains": true, "mode": "force-https" },
+ { "name": "smurfrp.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "skidstresser.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "simsnieuws.nl", "include_subdomains": true, "mode": "force-https" },
+ { "name": "seccomp.ru", "include_subdomains": true, "mode": "force-https" },
+ { "name": "solymar.co", "include_subdomains": true, "mode": "force-https" },
+ { "name": "smart-cp.jp", "include_subdomains": true, "mode": "force-https" },
+ { "name": "slo-tech.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "snarf.in", "include_subdomains": true, "mode": "force-https" },
+ { "name": "socialprize.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "sikevux.se", "include_subdomains": true, "mode": "force-https" },
+ { "name": "sh-heppelmann.de", "include_subdomains": true, "mode": "force-https" },
+ { "name": "shishkin.link", "include_subdomains": true, "mode": "force-https" },
+ { "name": "sifreuret.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "snowplane.net", "include_subdomains": true, "mode": "force-https" },
+ { "name": "seogeek.nl", "include_subdomains": true, "mode": "force-https" },
+ { "name": "sijmenschoon.nl", "include_subdomains": true, "mode": "force-https" },
+ { "name": "sokietech.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "skynetz.tk", "include_subdomains": true, "mode": "force-https" },
+ { "name": "smartviewing.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "sinnovate.de", "include_subdomains": true, "mode": "force-https" },
+ { "name": "silentexplosion.de", "include_subdomains": true, "mode": "force-https" },
+ { "name": "shopherbal.co.za", "include_subdomains": true, "mode": "force-https" },
+ { "name": "slashand.co", "include_subdomains": true, "mode": "force-https" },
+ { "name": "sitecuatui.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "soruly.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "spacebaseapp.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "sozon.ca", "include_subdomains": true, "mode": "force-https" },
+ { "name": "sostacancun.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "southernmost.us", "include_subdomains": true, "mode": "force-https" },
+ { "name": "shamara.info", "include_subdomains": true, "mode": "force-https" },
+ { "name": "shishkin.us", "include_subdomains": true, "mode": "force-https" },
+ { "name": "sodacore.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "skolem.de", "include_subdomains": true, "mode": "force-https" },
+ { "name": "sinktank.de", "include_subdomains": true, "mode": "force-https" },
+ { "name": "spitfireuav.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "spacedirectory.org", "include_subdomains": true, "mode": "force-https" },
+ { "name": "slink.hr", "include_subdomains": true, "mode": "force-https" },
+ { "name": "statementinsertsforless.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "squaddraft.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "scrisulfacebine.ro", "include_subdomains": true, "mode": "force-https" },
+ { "name": "smablo.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "soul-source.co.uk", "include_subdomains": true, "mode": "force-https" },
+ { "name": "shiftnrg.org", "include_subdomains": true, "mode": "force-https" },
+ { "name": "software.rocks", "include_subdomains": true, "mode": "force-https" },
+ { "name": "soundeo.net", "include_subdomains": true, "mode": "force-https" },
+ { "name": "simon-pokorny.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "show-saratov.ru", "include_subdomains": true, "mode": "force-https" },
+ { "name": "spiritfanfics.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "soundeo.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "solidshield.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "spaceweatherlive.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "strauser.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "storysift.news", "include_subdomains": true, "mode": "force-https" },
+ { "name": "ssl.do", "include_subdomains": true, "mode": "force-https" },
+ { "name": "sparta-trade.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "srandom.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "skydragoness.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "submedia.tv", "include_subdomains": true, "mode": "force-https" },
+ { "name": "spassstempel.de", "include_subdomains": true, "mode": "force-https" },
+ { "name": "spaceweather.live", "include_subdomains": true, "mode": "force-https" },
+ { "name": "scribbleserver.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "smoothics.mobi", "include_subdomains": true, "mode": "force-https" },
+ { "name": "sokolka.tv", "include_subdomains": true, "mode": "force-https" },
+ { "name": "shapesedinburgh.co.uk", "include_subdomains": true, "mode": "force-https" },
+ { "name": "spacepage.be", "include_subdomains": true, "mode": "force-https" },
+ { "name": "streamingeverywhere.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "squids.space", "include_subdomains": true, "mode": "force-https" },
+ { "name": "srcc.fr", "include_subdomains": true, "mode": "force-https" },
+ { "name": "southafrican.dating", "include_subdomains": true, "mode": "force-https" },
+ { "name": "stadt-apotheke-muensingen.de", "include_subdomains": true, "mode": "force-https" },
+ { "name": "stopbullying.gov", "include_subdomains": true, "mode": "force-https" },
+ { "name": "spresso.me", "include_subdomains": true, "mode": "force-https" },
+ { "name": "spornkuller.de", "include_subdomains": true, "mode": "force-https" },
+ { "name": "surasak.xyz", "include_subdomains": true, "mode": "force-https" },
+ { "name": "starka.st", "include_subdomains": true, "mode": "force-https" },
+ { "name": "statgram.me", "include_subdomains": true, "mode": "force-https" },
+ { "name": "summa.eu", "include_subdomains": true, "mode": "force-https" },
+ { "name": "ssldev.net", "include_subdomains": true, "mode": "force-https" },
+ { "name": "ssls.cz", "include_subdomains": true, "mode": "force-https" },
+ { "name": "sonic.network", "include_subdomains": true, "mode": "force-https" },
+ { "name": "spiritual.dating", "include_subdomains": true, "mode": "force-https" },
+ { "name": "solutive.fi", "include_subdomains": true, "mode": "force-https" },
+ { "name": "stewonet.nl", "include_subdomains": true, "mode": "force-https" },
+ { "name": "st-kilian-markt-erlbach.de", "include_subdomains": true, "mode": "force-https" },
+ { "name": "sumthing.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "spatzenwerkstatt.de", "include_subdomains": true, "mode": "force-https" },
+ { "name": "stamboommuller.nl", "include_subdomains": true, "mode": "force-https" },
+ { "name": "srrdb.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "sports.dating", "include_subdomains": true, "mode": "force-https" },
+ { "name": "sport-in-sundern.de", "include_subdomains": true, "mode": "force-https" },
+ { "name": "siamsnus.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "swineson.me", "include_subdomains": true, "mode": "force-https" },
+ { "name": "spacountryexplorer.org.au", "include_subdomains": true, "mode": "force-https" },
+ { "name": "surasak.org", "include_subdomains": true, "mode": "force-https" },
+ { "name": "sysrq.tech", "include_subdomains": true, "mode": "force-https" },
+ { "name": "syy.im", "include_subdomains": true, "mode": "force-https" },
+ { "name": "synotna.eu", "include_subdomains": true, "mode": "force-https" },
+ { "name": "stelleninserate.de", "include_subdomains": true, "mode": "force-https" },
+ { "name": "squarelab.it", "include_subdomains": true, "mode": "force-https" },
+ { "name": "superhappiness.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "studentrdh.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "stamboomvanderwal.nl", "include_subdomains": true, "mode": "force-https" },
+ { "name": "subdev.org", "include_subdomains": true, "mode": "force-https" },
+ { "name": "surgeongeneral.gov", "include_subdomains": true, "mode": "force-https" },
+ { "name": "sternen-sitzberg.ch", "include_subdomains": true, "mode": "force-https" },
+ { "name": "sorincocorada.ro", "include_subdomains": true, "mode": "force-https" },
+ { "name": "technologysi.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "st-news.de", "include_subdomains": true, "mode": "force-https" },
+ { "name": "star-killer.net", "include_subdomains": true, "mode": "force-https" },
+ { "name": "stravers.shoes", "include_subdomains": true, "mode": "force-https" },
+ { "name": "swingmonkey.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "ta-65.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "talldude.net", "include_subdomains": true, "mode": "force-https" },
+ { "name": "t-ken.xyz", "include_subdomains": true, "mode": "force-https" },
+ { "name": "ta65.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "teachmeplease.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "teachmeplease.ru", "include_subdomains": true, "mode": "force-https" },
+ { "name": "stevens.se", "include_subdomains": true, "mode": "force-https" },
+ { "name": "strangeplace.net", "include_subdomains": true, "mode": "force-https" },
+ { "name": "sysadmin.pm", "include_subdomains": true, "mode": "force-https" },
+ { "name": "teacherph.net", "include_subdomains": true, "mode": "force-https" },
+ { "name": "teacherph.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "suempresa.cloud", "include_subdomains": true, "mode": "force-https" },
+ { "name": "sysadminstory.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "shereallyheals.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "teencounseling.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "texus.me", "include_subdomains": true, "mode": "force-https" },
+ { "name": "ssbkk.ru", "include_subdomains": true, "mode": "force-https" },
+ { "name": "tahakomat.cz", "include_subdomains": true, "mode": "force-https" },
+ { "name": "tassup.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "supersu.kr", "include_subdomains": true, "mode": "force-https" },
+ { "name": "studenttenant.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "tedb.us", "include_subdomains": true, "mode": "force-https" },
+ { "name": "steffi-in-australien.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "texby.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "stephan-matthiesen.de", "include_subdomains": true, "mode": "force-https" },
+ { "name": "superschnappchen.de", "include_subdomains": true, "mode": "force-https" },
+ { "name": "thedronechart.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "stellmacher.name", "include_subdomains": true, "mode": "force-https" },
+ { "name": "sysgeek.cn", "include_subdomains": true, "mode": "force-https" },
+ { "name": "sweetvanilla.jp", "include_subdomains": true, "mode": "force-https" },
+ { "name": "stcable.net", "include_subdomains": true, "mode": "force-https" },
+ { "name": "teedb.de", "include_subdomains": true, "mode": "force-https" },
+ { "name": "telepass.me", "include_subdomains": true, "mode": "force-https" },
+ { "name": "swiftqueue.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "tadata.me", "include_subdomains": true, "mode": "force-https" },
+ { "name": "southgale.condos", "include_subdomains": true, "mode": "force-https" },
+ { "name": "stmsolutions.pl", "include_subdomains": true, "mode": "force-https" },
+ { "name": "tequilazor.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "thetruthhurvitz.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "technoscoots.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "therealcost.gov", "include_subdomains": true, "mode": "force-https" },
+ { "name": "sutas.market", "include_subdomains": true, "mode": "force-https" },
+ { "name": "tcacademy.co.uk", "include_subdomains": true, "mode": "force-https" },
+ { "name": "swisslinux.org", "include_subdomains": true, "mode": "force-https" },
+ { "name": "svetjakonadlani.cz", "include_subdomains": true, "mode": "force-https" },
+ { "name": "tarantul.org.ua", "include_subdomains": true, "mode": "force-https" },
+ { "name": "theoutline.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "theoscure.eu", "include_subdomains": true, "mode": "force-https" },
+ { "name": "subzerolosangeles.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "ticketsourcebeta.co.uk", "include_subdomains": true, "mode": "force-https" },
+ { "name": "stamonicatourandtravel.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "teeworlds-friends.de", "include_subdomains": true, "mode": "force-https" },
+ { "name": "susann-kerk.de", "include_subdomains": true, "mode": "force-https" },
+ { "name": "theprincegame.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "thalskarth.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "timdoug.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "sylvangarden.net", "include_subdomains": true, "mode": "force-https" },
+ { "name": "sweetlegs.jp", "include_subdomains": true, "mode": "force-https" },
+ { "name": "tobacco.gov", "include_subdomains": true, "mode": "force-https" },
+ { "name": "taqun.club", "include_subdomains": true, "mode": "force-https" },
+ { "name": "thailandpropertylistings.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "todapolitica.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "techreview.link", "include_subdomains": true, "mode": "force-https" },
+ { "name": "thisfreelife.gov", "include_subdomains": true, "mode": "force-https" },
+ { "name": "thecrochetcottage.net", "include_subdomains": true, "mode": "force-https" },
+ { "name": "tetramax.eu", "include_subdomains": true, "mode": "force-https" },
+ { "name": "thehighersideclothing.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "tampabaybusinesslistings.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "thebrightons.co.uk", "include_subdomains": true, "mode": "force-https" },
+ { "name": "thephp.cc", "include_subdomains": true, "mode": "force-https" },
+ { "name": "threecrownsllp.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "thetrendspotter.net", "include_subdomains": true, "mode": "force-https" },
+ { "name": "tofilmhub.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "tarsashaz-biztositas.hu", "include_subdomains": true, "mode": "force-https" },
+ { "name": "tobyschrapel.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "tloxygen.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "thriveta.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "tosainu.com.br", "include_subdomains": true, "mode": "force-https" },
+ { "name": "throughtheglass.photo", "include_subdomains": true, "mode": "force-https" },
+ { "name": "tokoyo.biz", "include_subdomains": true, "mode": "force-https" },
+ { "name": "ti-planet.org", "include_subdomains": true, "mode": "force-https" },
+ { "name": "tjc.host", "include_subdomains": true, "mode": "force-https" },
+ { "name": "thomas-gibertie.fr", "include_subdomains": true, "mode": "force-https" },
+ { "name": "thagki9.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "tlthings.net", "include_subdomains": true, "mode": "force-https" },
+ { "name": "tokio.fi", "include_subdomains": true, "mode": "force-https" },
+ { "name": "traininglist.org", "include_subdomains": true, "mode": "force-https" },
+ { "name": "tmberg.cf", "include_subdomains": true, "mode": "force-https" },
+ { "name": "thehiddenbay.info", "include_subdomains": true, "mode": "force-https" },
+ { "name": "tmberg.ga", "include_subdomains": true, "mode": "force-https" },
+ { "name": "torchl.it", "include_subdomains": true, "mode": "force-https" },
+ { "name": "themilanlife.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "torrentz2.eu", "include_subdomains": true, "mode": "force-https" },
+ { "name": "torretzalam.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "tomli.blog", "include_subdomains": true, "mode": "force-https" },
+ { "name": "theocharis.org", "include_subdomains": true, "mode": "force-https" },
+ { "name": "tourismwithme.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "toretame.jp", "include_subdomains": true, "mode": "force-https" },
+ { "name": "tjc.wiki", "include_subdomains": true, "mode": "force-https" },
+ { "name": "tmberg.ml", "include_subdomains": true, "mode": "force-https" },
+ { "name": "tmberg.gq", "include_subdomains": true, "mode": "force-https" },
+ { "name": "trafarm.ro", "include_subdomains": true, "mode": "force-https" },
+ { "name": "themecraft.studio", "include_subdomains": true, "mode": "force-https" },
+ { "name": "tmberg.tk", "include_subdomains": true, "mode": "force-https" },
+ { "name": "togetter.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "tmdb.biz", "include_subdomains": true, "mode": "force-https" },
+ { "name": "theworkingeye.nl", "include_subdomains": true, "mode": "force-https" },
+ { "name": "tomnatt.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "troo.ly", "include_subdomains": true, "mode": "force-https" },
+ { "name": "tobias-haenel.de", "include_subdomains": true, "mode": "force-https" },
+ { "name": "timowi.de", "include_subdomains": true, "mode": "force-https" },
+ { "name": "ttchan.org", "include_subdomains": true, "mode": "force-https" },
+ { "name": "tubex.ga", "include_subdomains": true, "mode": "force-https" },
+ { "name": "tnb-plattform.de", "include_subdomains": true, "mode": "force-https" },
+ { "name": "totallylegitimatehosting.ru", "include_subdomains": true, "mode": "force-https" },
+ { "name": "toretfaction.net", "include_subdomains": true, "mode": "force-https" },
+ { "name": "traista.ru", "include_subdomains": true, "mode": "force-https" },
+ { "name": "tink.network", "include_subdomains": true, "mode": "force-https" },
+ { "name": "trajano.net", "include_subdomains": true, "mode": "force-https" },
+ { "name": "tom-kunze.de", "include_subdomains": true, "mode": "force-https" },
+ { "name": "toonpool.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "timowi.net", "include_subdomains": true, "mode": "force-https" },
+ { "name": "thrivewellnesshub.co.za", "include_subdomains": true, "mode": "force-https" },
+ { "name": "tomabrafix.de", "include_subdomains": true, "mode": "force-https" },
+ { "name": "toool.org", "include_subdomains": true, "mode": "force-https" },
+ { "name": "the-hemingway-code.de", "include_subdomains": true, "mode": "force-https" },
+ { "name": "tomaskavalek.cz", "include_subdomains": true, "mode": "force-https" },
+ { "name": "tuxlife.net", "include_subdomains": true, "mode": "force-https" },
+ { "name": "treino.blog.br", "include_subdomains": true, "mode": "force-https" },
+ { "name": "topdesk.net", "include_subdomains": true, "mode": "force-https" },
+ { "name": "topdeskdev.net", "include_subdomains": true, "mode": "force-https" },
+ { "name": "techtoy.store", "include_subdomains": true, "mode": "force-https" },
+ { "name": "twitter.ax", "include_subdomains": true, "mode": "force-https" },
+ { "name": "thejacksoninstitute.com.au", "include_subdomains": true, "mode": "force-https" },
+ { "name": "truetrophies.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "tomjonsson.se", "include_subdomains": true, "mode": "force-https" },
+ { "name": "simccorp.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "togech.jp", "include_subdomains": true, "mode": "force-https" },
+ { "name": "torproject.org.uk", "include_subdomains": true, "mode": "force-https" },
+ { "name": "udp.sh", "include_subdomains": true, "mode": "force-https" },
+ { "name": "trackdays4fun.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "tsurimap.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "tochi-urikata.net", "include_subdomains": true, "mode": "force-https" },
+ { "name": "twolanedesign.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "truesteamachievements.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "tm.id.au", "include_subdomains": true, "mode": "force-https" },
+ { "name": "ttsoft.pl", "include_subdomains": true, "mode": "force-https" },
+ { "name": "transfer.pw", "include_subdomains": true, "mode": "force-https" },
+ { "name": "unli.xyz", "include_subdomains": true, "mode": "force-https" },
+ { "name": "unblocked.ink", "include_subdomains": true, "mode": "force-https" },
+ { "name": "ugisgutless.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "unblocked.today", "include_subdomains": true, "mode": "force-https" },
+ { "name": "turkrock.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "topnotepad.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "totalprint.hu", "include_subdomains": true, "mode": "force-https" },
+ { "name": "uefeng.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "touchoflife.in", "include_subdomains": true, "mode": "force-https" },
+ { "name": "v2bv.win", "include_subdomains": true, "mode": "force-https" },
+ { "name": "transmisjeonline.pl", "include_subdomains": true, "mode": "force-https" },
+ { "name": "twelverocks.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "tubetoon.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "twodadsgames.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "usajobs.gov", "include_subdomains": true, "mode": "force-https" },
+ { "name": "ttuwiki.org", "include_subdomains": true, "mode": "force-https" },
+ { "name": "tonyw.xyz", "include_subdomains": true, "mode": "force-https" },
+ { "name": "ttuwiki.ee", "include_subdomains": true, "mode": "force-https" },
+ { "name": "vavel.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "traderjoe-cloud.de", "include_subdomains": true, "mode": "force-https" },
+ { "name": "tyil.work", "include_subdomains": true, "mode": "force-https" },
+ { "name": "tyil.nl", "include_subdomains": true, "mode": "force-https" },
+ { "name": "unblocked.works", "include_subdomains": true, "mode": "force-https" },
+ { "name": "upmchealthsecurity.us", "include_subdomains": true, "mode": "force-https" },
+ { "name": "tumagiri.net", "include_subdomains": true, "mode": "force-https" },
+ { "name": "usability.gov", "include_subdomains": true, "mode": "force-https" },
+ { "name": "uctarna.online", "include_subdomains": true, "mode": "force-https" },
+ { "name": "utilitarianism.org", "include_subdomains": true, "mode": "force-https" },
+ { "name": "twee-onder-een-kap-woning-in-leeuwarden-kopen.nl", "include_subdomains": true, "mode": "force-https" },
+ { "name": "uggedal.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "twee-onder-een-kap-woning-in-zwartewaterland-kopen.nl", "include_subdomains": true, "mode": "force-https" },
+ { "name": "twee-onder-een-kap-woning-in-sudwest-fryslan-kopen.nl", "include_subdomains": true, "mode": "force-https" },
+ { "name": "trixexpressweb.nl", "include_subdomains": true, "mode": "force-https" },
+ { "name": "twee-onder-een-kap-woning-in-zuidplas-kopen.nl", "include_subdomains": true, "mode": "force-https" },
+ { "name": "twee-onder-een-kap-woning-in-veendam-kopen.nl", "include_subdomains": true, "mode": "force-https" },
+ { "name": "tweeondereenkapwoningverkopen.nl", "include_subdomains": true, "mode": "force-https" },
+ { "name": "tussengelegenwoningverkopen.nl", "include_subdomains": true, "mode": "force-https" },
+ { "name": "unblocked.world", "include_subdomains": true, "mode": "force-https" },
+ { "name": "usmint.gov", "include_subdomains": true, "mode": "force-https" },
+ { "name": "twee-onder-een-kap-woning-in-alphen-aan-den-rijn-kopen.nl", "include_subdomains": true, "mode": "force-https" },
+ { "name": "twee-onder-een-kap-woning-in-de-friese-meren-kopen.nl", "include_subdomains": true, "mode": "force-https" },
+ { "name": "twotube.ie", "include_subdomains": true, "mode": "force-https" },
+ { "name": "tkappertjedemetamorfose.nl", "include_subdomains": true, "mode": "force-https" },
+ { "name": "tweeondereenkapverkopen.nl", "include_subdomains": true, "mode": "force-https" },
+ { "name": "twee-onder-een-kap-woning-in-pekela-kopen.nl", "include_subdomains": true, "mode": "force-https" },
+ { "name": "twee-onder-een-kap-woning-in-rijnwaarden-kopen.nl", "include_subdomains": true, "mode": "force-https" },
+ { "name": "travelinsightswriter.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "twojfaktum.pl", "include_subdomains": true, "mode": "force-https" },
+ { "name": "section508.gov", "include_subdomains": true, "mode": "force-https" },
+ { "name": "uevan.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "texter.at", "include_subdomains": true, "mode": "force-https" },
+ { "name": "thedrop.pw", "include_subdomains": true, "mode": "force-https" },
+ { "name": "tentins.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "tpidg.us", "include_subdomains": true, "mode": "force-https" },
+ { "name": "unitrade-425.co.za", "include_subdomains": true, "mode": "force-https" },
+ { "name": "unmonito.red", "include_subdomains": true, "mode": "force-https" },
+ { "name": "urown.net", "include_subdomains": true, "mode": "force-https" },
+ { "name": "uk.dating", "include_subdomains": true, "mode": "force-https" },
+ { "name": "unixforum.org", "include_subdomains": true, "mode": "force-https" },
+ { "name": "vinesauce.info", "include_subdomains": true, "mode": "force-https" },
+ { "name": "vid.me", "include_subdomains": true, "mode": "force-https" },
+ { "name": "tanto259.name", "include_subdomains": true, "mode": "force-https" },
+ { "name": "vega.dyndns.info", "include_subdomains": true, "mode": "force-https" },
+ { "name": "vea.re", "include_subdomains": true, "mode": "force-https" },
+ { "name": "vintagetrailerbuyers.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "v-u-z.ru", "include_subdomains": true, "mode": "force-https" },
+ { "name": "vaccines.gov", "include_subdomains": true, "mode": "force-https" },
+ { "name": "victordiaz.me", "include_subdomains": true, "mode": "force-https" },
+ { "name": "vnfs-team.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "voidpay.net", "include_subdomains": true, "mode": "force-https" },
+ { "name": "vicianovi.cz", "include_subdomains": true, "mode": "force-https" },
+ { "name": "vineright.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "unlax.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "urban-garden.lv", "include_subdomains": true, "mode": "force-https" },
+ { "name": "urban-garden.lt", "include_subdomains": true, "mode": "force-https" },
+ { "name": "vdesc.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "vegane-proteine.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "vrzl.pro", "include_subdomains": true, "mode": "force-https" },
+ { "name": "upr-info.org", "include_subdomains": true, "mode": "force-https" },
+ { "name": "vanhove.biz", "include_subdomains": true, "mode": "force-https" },
+ { "name": "voidpay.org", "include_subdomains": true, "mode": "force-https" },
+ { "name": "unwomen.is", "include_subdomains": true, "mode": "force-https" },
+ { "name": "valeriansaliou.name", "include_subdomains": true, "mode": "force-https" },
+ { "name": "viosey.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "vorangerie.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "vldkn.net", "include_subdomains": true, "mode": "force-https" },
+ { "name": "visikom.de", "include_subdomains": true, "mode": "force-https" },
+ { "name": "vicenage.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "vodpay.org", "include_subdomains": true, "mode": "force-https" },
+ { "name": "volkswurst.de", "include_subdomains": true, "mode": "force-https" },
+ { "name": "vmug.pl", "include_subdomains": true, "mode": "force-https" },
+ { "name": "villenavedornon.fr", "include_subdomains": true, "mode": "force-https" },
+ { "name": "wallace-group.net", "include_subdomains": true, "mode": "force-https" },
+ { "name": "vapeshopsupply.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "upnext.io", "include_subdomains": true, "mode": "force-https" },
+ { "name": "waxdramatic.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "ventesprivees-fr.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "teehaus-shila.de", "include_subdomains": true, "mode": "force-https" },
+ { "name": "venzocrm.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "volto.io", "include_subdomains": true, "mode": "force-https" },
+ { "name": "vokativy.cz", "include_subdomains": true, "mode": "force-https" },
+ { "name": "ursuslibris.hu", "include_subdomains": true, "mode": "force-https" },
+ { "name": "vante.me", "include_subdomains": true, "mode": "force-https" },
+ { "name": "ve3oat.ca", "include_subdomains": true, "mode": "force-https" },
+ { "name": "vpsmojo.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "violenceinterrupted.org", "include_subdomains": true, "mode": "force-https" },
+ { "name": "voyageforum.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "vijverbenodigdheden.nl", "include_subdomains": true, "mode": "force-https" },
+ { "name": "vietnamwomenveterans.org", "include_subdomains": true, "mode": "force-https" },
+ { "name": "verberne.nu", "include_subdomains": true, "mode": "force-https" },
+ { "name": "virtualstrongbox.ca", "include_subdomains": true, "mode": "force-https" },
+ { "name": "vonavy-cukor.sk", "include_subdomains": true, "mode": "force-https" },
+ { "name": "voodoo-laden.de", "include_subdomains": true, "mode": "force-https" },
+ { "name": "villa-romantica-zillertal.at", "include_subdomains": true, "mode": "force-https" },
+ { "name": "voidserv.net", "include_subdomains": true, "mode": "force-https" },
+ { "name": "vinagro.sk", "include_subdomains": true, "mode": "force-https" },
+ { "name": "vanderrijt.nl", "include_subdomains": true, "mode": "force-https" },
+ { "name": "watersportmarkt.net", "include_subdomains": true, "mode": "force-https" },
+ { "name": "websecurity.is", "include_subdomains": true, "mode": "force-https" },
+ { "name": "webproject.rocks", "include_subdomains": true, "mode": "force-https" },
+ { "name": "willfarrell.ca", "include_subdomains": true, "mode": "force-https" },
+ { "name": "whitkirkchurch.org.uk", "include_subdomains": true, "mode": "force-https" },
+ { "name": "weiji.ga", "include_subdomains": true, "mode": "force-https" },
+ { "name": "winsufi.biz", "include_subdomains": true, "mode": "force-https" },
+ { "name": "webstationservice.fr", "include_subdomains": true, "mode": "force-https" },
+ { "name": "willstamper.name", "include_subdomains": true, "mode": "force-https" },
+ { "name": "welsh.com.br", "include_subdomains": true, "mode": "force-https" },
+ { "name": "vodpay.net", "include_subdomains": true, "mode": "force-https" },
+ { "name": "wahlman.org", "include_subdomains": true, "mode": "force-https" },
+ { "name": "vivocloud.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "whatagreatwebsite.net", "include_subdomains": true, "mode": "force-https" },
+ { "name": "w3ctag.org", "include_subdomains": true, "mode": "force-https" },
+ { "name": "weimaraner.com.br", "include_subdomains": true, "mode": "force-https" },
+ { "name": "westhighlandwhiteterrier.com.br", "include_subdomains": true, "mode": "force-https" },
+ { "name": "visualideas.org", "include_subdomains": true, "mode": "force-https" },
+ { "name": "ujob.com.cn", "include_subdomains": true, "mode": "force-https" },
+ { "name": "whistleblower.gov", "include_subdomains": true, "mode": "force-https" },
+ { "name": "vjeff.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "unquote.li", "include_subdomains": true, "mode": "force-https" },
+ { "name": "voodoochile.at", "include_subdomains": true, "mode": "force-https" },
+ { "name": "webcontentspinning.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "vbazile.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "wecanfindit.co.za", "include_subdomains": true, "mode": "force-https" },
+ { "name": "whmcs.hosting", "include_subdomains": true, "mode": "force-https" },
+ { "name": "vrijstaandhuis-in-leeuwarden-kopen.nl", "include_subdomains": true, "mode": "force-https" },
+ { "name": "vrijstaandhuisverkopen.nl", "include_subdomains": true, "mode": "force-https" },
+ { "name": "vrijstaandhuis-in-zuidplas-kopen.nl", "include_subdomains": true, "mode": "force-https" },
+ { "name": "wane.co", "include_subdomains": true, "mode": "force-https" },
+ { "name": "thegrape.ro", "include_subdomains": true, "mode": "force-https" },
+ { "name": "variag-montazh.ru", "include_subdomains": true, "mode": "force-https" },
+ { "name": "vulnscan.org", "include_subdomains": true, "mode": "force-https" },
+ { "name": "wireheading.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "vereinlandwege.de", "include_subdomains": true, "mode": "force-https" },
+ { "name": "wangjun.me", "include_subdomains": true, "mode": "force-https" },
+ { "name": "wendigo.pl", "include_subdomains": true, "mode": "force-https" },
+ { "name": "x509.pw", "include_subdomains": true, "mode": "force-https" },
+ { "name": "veganism.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "x509.pub", "include_subdomains": true, "mode": "force-https" },
+ { "name": "whatsyouroffer.co.uk", "include_subdomains": true, "mode": "force-https" },
+ { "name": "wusx.club", "include_subdomains": true, "mode": "force-https" },
+ { "name": "xiqi.us", "include_subdomains": true, "mode": "force-https" },
+ { "name": "wolfeyesusa.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "wyam.io", "include_subdomains": true, "mode": "force-https" },
+ { "name": "w3n.org", "include_subdomains": true, "mode": "force-https" },
+ { "name": "vooreenveiligthuis.nl", "include_subdomains": true, "mode": "force-https" },
+ { "name": "wahrnehmungswelten.de", "include_subdomains": true, "mode": "force-https" },
+ { "name": "wilfrid-calixte.fr", "include_subdomains": true, "mode": "force-https" },
+ { "name": "wrp.gov", "include_subdomains": true, "mode": "force-https" },
+ { "name": "wallabag.it", "include_subdomains": true, "mode": "force-https" },
+ { "name": "vrijstaandhuis-in-brielle-kopen.nl", "include_subdomains": true, "mode": "force-https" },
+ { "name": "widsl.de", "include_subdomains": true, "mode": "force-https" },
+ { "name": "wiegedaten.de", "include_subdomains": true, "mode": "force-https" },
+ { "name": "wigggle.it", "include_subdomains": true, "mode": "force-https" },
+ { "name": "vrijstaandhuis-in-veendam-kopen.nl", "include_subdomains": true, "mode": "force-https" },
+ { "name": "wiedmeyer.de", "include_subdomains": true, "mode": "force-https" },
+ { "name": "web-insider.net", "include_subdomains": true, "mode": "force-https" },
+ { "name": "werktor.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "vrijstaandhuis-in-delfzijl-kopen.nl", "include_subdomains": true, "mode": "force-https" },
+ { "name": "weltentreff.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "w-w-auto.de", "include_subdomains": true, "mode": "force-https" },
+ { "name": "vrijstaandhuis-in-laren-kopen.nl", "include_subdomains": true, "mode": "force-https" },
+ { "name": "vrijstaandhuis-in-zuid-holland-kopen.nl", "include_subdomains": true, "mode": "force-https" },
+ { "name": "vuljespaarpot.nl", "include_subdomains": true, "mode": "force-https" },
+ { "name": "warumsuchen.at", "include_subdomains": true, "mode": "force-https" },
+ { "name": "wbvb.nl", "include_subdomains": true, "mode": "force-https" },
+ { "name": "volgavibes.ru", "include_subdomains": true, "mode": "force-https" },
+ { "name": "xbtmusic.org", "include_subdomains": true, "mode": "force-https" },
+ { "name": "xtom.email", "include_subdomains": true, "mode": "force-https" },
+ { "name": "wnmm.nl", "include_subdomains": true, "mode": "force-https" },
+ { "name": "xsyds.cn", "include_subdomains": true, "mode": "force-https" },
+ { "name": "xing.ml", "include_subdomains": true, "mode": "force-https" },
+ { "name": "vietnamchevrolet.net", "include_subdomains": true, "mode": "force-https" },
+ { "name": "wesell.asia", "include_subdomains": true, "mode": "force-https" },
+ { "name": "wp-fastsearch.de", "include_subdomains": true, "mode": "force-https" },
+ { "name": "yardbird.us", "include_subdomains": true, "mode": "force-https" },
+ { "name": "yahoo.ax", "include_subdomains": true, "mode": "force-https" },
+ { "name": "xn--thorme-6uaf.ca", "include_subdomains": true, "mode": "force-https" },
+ { "name": "wild-emotion-events.de", "include_subdomains": true, "mode": "force-https" },
+ { "name": "webreport.fr", "include_subdomains": true, "mode": "force-https" },
+ { "name": "workpermit.com.vn", "include_subdomains": true, "mode": "force-https" },
+ { "name": "yorkshireterrier.com.br", "include_subdomains": true, "mode": "force-https" },
+ { "name": "vietnamphotographytours.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "xn--aviao-dra1a.pt", "include_subdomains": true, "mode": "force-https" },
+ { "name": "wewlad.me", "include_subdomains": true, "mode": "force-https" },
+ { "name": "wereldplanner.nl", "include_subdomains": true, "mode": "force-https" },
+ { "name": "worldeventscalendars.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "wukongmusic.us", "include_subdomains": true, "mode": "force-https" },
+ { "name": "wmawri.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "yukonlip.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "yukonconnector.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "wiz.at", "include_subdomains": true, "mode": "force-https" },
+ { "name": "zao.fi", "include_subdomains": true, "mode": "force-https" },
+ { "name": "xn--rdiger-kuhlmann-zvb.de", "include_subdomains": true, "mode": "force-https" },
+ { "name": "wt-server3.de", "include_subdomains": true, "mode": "force-https" },
+ { "name": "zeronet.io", "include_subdomains": true, "mode": "force-https" },
+ { "name": "wevenues.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "zenmate.com.tr", "include_subdomains": true, "mode": "force-https" },
+ { "name": "xlange.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "x-iweb.ru", "include_subdomains": true, "mode": "force-https" },
+ { "name": "ximbo.net", "include_subdomains": true, "mode": "force-https" },
+ { "name": "xsz.jp", "include_subdomains": true, "mode": "force-https" },
+ { "name": "xmv.cz", "include_subdomains": true, "mode": "force-https" },
+ { "name": "xn--allgu-biker-o8a.de", "include_subdomains": true, "mode": "force-https" },
+ { "name": "wr.su", "include_subdomains": true, "mode": "force-https" },
+ { "name": "yizhu.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "yuwei.org", "include_subdomains": true, "mode": "force-https" },
+ { "name": "yingatech.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "ywei.org", "include_subdomains": true, "mode": "force-https" },
+ { "name": "vanacht.co.za", "include_subdomains": true, "mode": "force-https" },
+ { "name": "xiazhanjian.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "zohar.link", "include_subdomains": true, "mode": "force-https" },
+ { "name": "zh1.li", "include_subdomains": true, "mode": "force-https" },
+ { "name": "zabszk.net", "include_subdomains": true, "mode": "force-https" },
+ { "name": "xn--spenijmazania-yhc.pl", "include_subdomains": true, "mode": "force-https" },
+ { "name": "xn--fischereiverein-mnsterhausen-i7c.de", "include_subdomains": true, "mode": "force-https" },
+ { "name": "xn--lsupp-mra.net", "include_subdomains": true, "mode": "force-https" },
+ { "name": "yourcopywriter.it", "include_subdomains": true, "mode": "force-https" },
+ { "name": "yame2.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "youcruit.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "youon.tokyo", "include_subdomains": true, "mode": "force-https" },
+ { "name": "zer0.de", "include_subdomains": true, "mode": "force-https" },
+ { "name": "ziptie.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "wpcarer.pro", "include_subdomains": true, "mode": "force-https" },
+ { "name": "uygindir.ml", "include_subdomains": true, "mode": "force-https" },
+ { "name": "zen-ume.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "yobai28.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "wpsono.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "yourcomputer.expert", "include_subdomains": true, "mode": "force-https" },
+ { "name": "yatorie.net", "include_subdomains": true, "mode": "force-https" },
+ { "name": "youngdogs.org", "include_subdomains": true, "mode": "force-https" },
+ { "name": "zigzagmart.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "woontegelwinkel.nl", "include_subdomains": true, "mode": "force-https" },
+ { "name": "yii2.cc", "include_subdomains": true, "mode": "force-https" },
+ { "name": "zupago.pe", "include_subdomains": true, "mode": "force-https" },
+ { "name": "zivy-ruzenec.cz", "include_subdomains": true, "mode": "force-https" },
+ { "name": "zivyruzenec.cz", "include_subdomains": true, "mode": "force-https" },
+ { "name": "yobai-grouprec.jp", "include_subdomains": true, "mode": "force-https" },
+ { "name": "zwollemag.nl", "include_subdomains": true, "mode": "force-https" },
+ { "name": "zonky.io", "include_subdomains": true, "mode": "force-https" },
+ { "name": "yotubaiotona.net", "include_subdomains": true, "mode": "force-https" },
+ { "name": "xn5.de", "include_subdomains": true, "mode": "force-https" },
+ { "name": "wypemagazine.se", "include_subdomains": true, "mode": "force-https" },
+ { "name": "zwollemagazine.nl", "include_subdomains": true, "mode": "force-https" },
+ { "name": "zingjerijk.nl", "include_subdomains": true, "mode": "force-https" },
+ { "name": "yasutomonodokoiko.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "zojadravai.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "zonecb.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "z-konzept-nutrition.ru", "include_subdomains": true, "mode": "force-https" },
+ { "name": "yuricarlenzoli.it", "include_subdomains": true, "mode": "force-https" },
+ { "name": "wibuw.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "zybbo.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "yarchives.jp", "include_subdomains": true, "mode": "force-https" },
+ { "name": "zunftmarke.de", "include_subdomains": true, "mode": "force-https" },
+ { "name": "zhangge.net", "include_subdomains": true, "mode": "force-https" },
+ { "name": "zaidanfood.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "yeu.io", "include_subdomains": true, "mode": "force-https" },
+ { "name": "zoowiki.us", "include_subdomains": true, "mode": "force-https" },
+ { "name": "zoigl.club", "include_subdomains": true, "mode": "force-https" },
+ { "name": "wpyecom.es", "include_subdomains": true, "mode": "force-https" },
+ { "name": "zmsastro.co.za", "include_subdomains": true, "mode": "force-https" },
+ { "name": "xn--lsaupp-iua.se", "include_subdomains": true, "mode": "force-https" },
+ { "name": "zeebrieshoekvanholland.nl", "include_subdomains": true, "mode": "force-https" },
+ { "name": "vanderstraeten.dynv6.net", "include_subdomains": true, "mode": "force-https" },
+ { "name": "zaidanfood.eu", "include_subdomains": true, "mode": "force-https" },
+ { "name": "zaidanlebensmittelhandel.de", "include_subdomains": true, "mode": "force-https" },
+ { "name": "zhousiru.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "xscancun.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "zolotoy-standart.com.ua", "include_subdomains": true, "mode": "force-https" },
+ { "name": "zorasvobodova.cz", "include_subdomains": true, "mode": "force-https" },
+ // END OF BULK ENTRIES
- // Manual additions in Chrome 51 or later that do not belong in a
+ // Manual additions and changes in Chrome 51 or later that do not belong in a
// special section above.
- // START OF MANUAL ADDITIONS
+ // START OF MANUAL ENTRIES
{ "name": "bodhi.fedoraproject.org", "include_subdomains": true, "mode": "force-https" },
{ "name": "communityblog.fedoraproject.org", "include_subdomains": true, "mode": "force-https" },
{ "name": "keys.fedoraproject.org", "include_subdomains": true, "mode": "force-https" },
@@ -18777,7 +21265,6 @@
{ "name": "sogravatas.com.br", "include_subdomains": true, "mode": "force-https" },
{ "name": "xn--neb-tma3u8u.xyz", "include_subdomains": true, "mode": "force-https" },
{ "name": "swehack.org", "include_subdomains": true, "mode": "force-https", "pins": "swehackCom" },
- { "name": "nightx.uk", "include_subdomains": true, "mode": "force-https", "pins": "nightx" },
{ "name": "relaxpointhyncice.cz", "include_subdomains": true, "mode": "force-https" },
{ "name": "crt.sh", "include_subdomains": true, "mode": "force-https", "expect_ct": true, "expect_ct_report_uri": "https://clients3.google.com/ct_upload" },
{ "name": "caddyserver.com", "expect_staple": true, "expect_staple_report_uri": "https://reporting.caddyserver.com/expect-staple" },
@@ -18797,9 +21284,16 @@
{ "name": "www.amazon.fr", "include_subdomains": true, "mode": "force-https" },
{ "name": "www.amazon.it", "include_subdomains": true, "mode": "force-https" },
{ "name": "www.amazon.nl", "include_subdomains": true, "mode": "force-https" },
+ { "name": "music.amazon.com", "include_subdomains": true, "mode": "force-https" },
{ "name": "crypto.is", "include_subdomains": true, "mode": "force-https", "expect_ct": true, "expect_ct_report_uri": "https://clients3.google.com/ct_upload" },
{ "name": "ritter.vg", "expect_ct": true, "expect_ct_report_uri": "https://clients3.google.com/ct_upload", "expect_staple": true, "expect_staple_report_uri": "https://asac.casa/expectstaple.jsp" },
- // END OF MANUAL ADDITIONS
+ { "name": "tails.boum.org", "include_subdomains": true, "mode": "force-https" },
+ { "name": "0.me.uk", "include_subdomains": true, "mode": "force-https", "pins": "nightx" },
+ { "name": "nightx.uk", "include_subdomains": true, "mode": "force-https", "pins": "nightx" },
+ { "name": "themathematician.uk", "include_subdomains": true, "mode": "force-https", "pins": "nightx" },
+ { "name": "baas-becking.biology.utah.edu", "include_subdomains": true, "mode": "force-https" },
+ { "name": "www.theguardian.com", "include_subdomains": true, "mode": "force-https" },
+ // END OF MANUAL ENTRIES
// To avoid trailing comma changes from showing up in diffs, we place a
// single entry at the end.
@@ -19087,6 +21581,11 @@
"SWEHACK_ORG",
"GOOGLESOURCE_COM",
"NIGHTX_UK",
- "FIREBASEIO_COM"
+ "FIREBASEIO_COM",
+ "CRBUG_COM",
+ "CROSBUG_COM",
+ "CRREV_COM",
+ "ME_UK",
+ "THEMATHEMATICIAN_UK"
]
}
diff --git a/chromium/net/http/transport_security_state_static_fuzzer.cc b/chromium/net/http/transport_security_state_static_fuzzer.cc
new file mode 100644
index 00000000000..b7b9b5f7ddc
--- /dev/null
+++ b/chromium/net/http/transport_security_state_static_fuzzer.cc
@@ -0,0 +1,49 @@
+// Copyright 2016 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.
+
+#include <string>
+
+#include "net/http/transport_security_state.h"
+
+namespace net {
+
+class TransportSecurityStateStaticFuzzer {
+ public:
+ bool FuzzStaticDomainState(TransportSecurityState* state,
+ const std::string& input) {
+ state->enable_static_pins_ = true;
+ TransportSecurityState::STSState sts_result;
+ TransportSecurityState::PKPState pkp_result;
+ return state->GetStaticDomainState(input, &sts_result, &pkp_result);
+ }
+
+ bool FuzzStaticExpectCTState(TransportSecurityState* state,
+ const std::string& input) {
+ state->enable_static_expect_ct_ = true;
+ TransportSecurityState::ExpectCTState result;
+ return state->GetStaticExpectCTState(input, &result);
+ }
+
+ bool FuzzStaticExpectStapleState(TransportSecurityState* state,
+ const std::string& input) {
+ state->enable_static_expect_staple_ = true;
+ TransportSecurityState::ExpectStapleState result;
+ return state->GetStaticExpectStapleState(input, &result);
+ }
+};
+
+} // namespace net
+
+extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
+ std::string input(reinterpret_cast<const char*>(data), size);
+
+ net::TransportSecurityStateStaticFuzzer helper;
+ net::TransportSecurityState state;
+
+ helper.FuzzStaticDomainState(&state, input);
+ helper.FuzzStaticExpectCTState(&state, input);
+ helper.FuzzStaticExpectStapleState(&state, input);
+
+ return 0;
+}
diff --git a/chromium/net/http/transport_security_state_unittest.cc b/chromium/net/http/transport_security_state_unittest.cc
index fcd2a16aac1..7fb0b491049 100644
--- a/chromium/net/http/transport_security_state_unittest.cc
+++ b/chromium/net/http/transport_security_state_unittest.cc
@@ -199,7 +199,7 @@ void CheckHPKPReport(
const HashValueVector& known_pins) {
std::unique_ptr<base::Value> value(base::JSONReader::Read(report));
ASSERT_TRUE(value);
- ASSERT_TRUE(value->IsType(base::Value::TYPE_DICTIONARY));
+ ASSERT_TRUE(value->IsType(base::Value::Type::DICTIONARY));
base::DictionaryValue* report_dict;
ASSERT_TRUE(value->GetAsDictionary(&report_dict));
@@ -264,7 +264,7 @@ void CheckSerializedExpectStapleReport(const std::string& report,
const std::string& cert_status) {
std::unique_ptr<base::Value> value(base::JSONReader::Read(report));
ASSERT_TRUE(value);
- ASSERT_TRUE(value->IsType(base::Value::TYPE_DICTIONARY));
+ ASSERT_TRUE(value->IsType(base::Value::Type::DICTIONARY));
base::DictionaryValue* report_dict;
ASSERT_TRUE(value->GetAsDictionary(&report_dict));
@@ -486,29 +486,6 @@ TEST_F(TransportSecurityStateTest, MatchesCase1) {
EXPECT_TRUE(state.ShouldUpgradeToSSL("example.com"));
}
-TEST_F(TransportSecurityStateTest, Fuzz) {
- TransportSecurityState state;
- TransportSecurityState::STSState sts_state;
- TransportSecurityState::PKPState pkp_state;
-
- EnableStaticPins(&state);
-
- for (size_t i = 0; i < 128; i++) {
- std::string hostname;
-
- for (;;) {
- if (base::RandInt(0, 16) == 7) {
- break;
- }
- if (i > 0 && base::RandInt(0, 7) == 7) {
- hostname.append(1, '.');
- }
- hostname.append(1, 'a' + base::RandInt(0, 25));
- }
- state.GetStaticDomainState(hostname, &sts_state, &pkp_state);
- }
-}
-
TEST_F(TransportSecurityStateTest, MatchesCase2) {
TransportSecurityState state;
const base::Time current_time(base::Time::Now());
diff --git a/chromium/net/http2/decoder/decode_buffer.cc b/chromium/net/http2/decoder/decode_buffer.cc
new file mode 100644
index 00000000000..15235bae4b5
--- /dev/null
+++ b/chromium/net/http2/decoder/decode_buffer.cc
@@ -0,0 +1,90 @@
+// Copyright 2016 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.
+
+#include "net/http2/decoder/decode_buffer.h"
+
+namespace net {
+
+bool DecodeBuffer::SlowDecodeUnsignedInt(uint32_t field_size,
+ uint32_t field_offset,
+ uint32_t* decode_offset,
+ uint32_t* value) {
+ DCHECK_LT(0u, field_size);
+ DCHECK_LE(field_size, 4u);
+ DCHECK(decode_offset != nullptr);
+ DCHECK_LE(field_offset, *decode_offset);
+ const uint32_t next_field_offset = field_offset + field_size;
+ if (*decode_offset == field_offset) {
+ // Starting to decode field. It is possible we will reach this point
+ // twice, once when we've just exhausted the input, and once when
+ // resuming decoding with a new input buffer.
+ // Clear the field; we do NOT assume that the caller has done so
+ // previously.
+ *value = 0;
+ } else if (*decode_offset >= next_field_offset) {
+ // We already decoded this field.
+ return true;
+ }
+ do {
+ if (Empty()) {
+ return false; // Not done decoding.
+ }
+ *value = *value << 8 | DecodeUInt8();
+ (*decode_offset)++;
+ } while (*decode_offset < next_field_offset);
+ return true;
+}
+
+bool DecodeBuffer::SlowDecodeUInt8(uint32_t field_offset,
+ uint32_t* decode_offset,
+ uint8_t* value) {
+ uint32_t tmp = *value;
+ const bool done = SlowDecodeUnsignedInt(1 /* field_size */, field_offset,
+ decode_offset, &tmp);
+ *value = tmp & 0xff;
+ DCHECK_EQ(tmp, *value);
+ return done;
+}
+
+bool DecodeBuffer::SlowDecodeUInt16(uint32_t field_offset,
+ uint32_t* decode_offset,
+ uint16_t* value) {
+ uint32_t tmp = *value;
+ const bool done = SlowDecodeUnsignedInt(2 /* field_size */, field_offset,
+ decode_offset, &tmp);
+ *value = tmp & 0xffff;
+ DCHECK_EQ(tmp, *value);
+ return done;
+}
+
+bool DecodeBuffer::SlowDecodeUInt24(uint32_t field_offset,
+ uint32_t* decode_offset,
+ uint32_t* value) {
+ uint32_t tmp = *value;
+ const bool done = SlowDecodeUnsignedInt(3 /* field_size */, field_offset,
+ decode_offset, &tmp);
+ *value = tmp & 0xffffff;
+ DCHECK_EQ(tmp, *value);
+ return done;
+}
+
+bool DecodeBuffer::SlowDecodeUInt31(uint32_t field_offset,
+ uint32_t* decode_offset,
+ uint32_t* value) {
+ uint32_t tmp = *value;
+ const bool done = SlowDecodeUnsignedInt(4 /* field_size */, field_offset,
+ decode_offset, &tmp);
+ *value = tmp & 0x7fffffff;
+ DCHECK_EQ(tmp & 0x7fffffff, *value);
+ return done;
+}
+
+bool DecodeBuffer::SlowDecodeUInt32(uint32_t field_offset,
+ uint32_t* decode_offset,
+ uint32_t* value) {
+ return SlowDecodeUnsignedInt(4 /* field_size */, field_offset, decode_offset,
+ value);
+}
+
+} // namespace net
diff --git a/chromium/net/http2/decoder/decode_buffer.h b/chromium/net/http2/decoder/decode_buffer.h
new file mode 100644
index 00000000000..828e4bf522e
--- /dev/null
+++ b/chromium/net/http2/decoder/decode_buffer.h
@@ -0,0 +1,289 @@
+// Copyright 2016 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.
+
+#ifndef NET_HTTP2_DECODER_DECODE_BUFFER_H_
+#define NET_HTTP2_DECODER_DECODE_BUFFER_H_
+
+// DecodeBuffer provides primitives for decoding various integer types found
+// in HTTP/2 frames.
+// DecodeBuffer wraps a byte array from which we can read and decode serialized
+// HTTP/2 frames, or parts thereof. DecodeBuffer is intended only for stack
+// allocation, where the caller is typically going to use the DecodeBuffer
+// instance as part of decoding the entire buffer before returning to its own
+// caller. Only the concrete Slow* methods are defined in the cc file,
+// all other methods are defined in this header file to enable inlining.
+
+#include <stddef.h>
+#include <stdint.h>
+
+#include <algorithm>
+
+#include "base/logging.h"
+#include "base/macros.h"
+#include "base/strings/string_piece.h"
+#include "net/base/net_export.h"
+
+namespace net {
+class DecodeBufferSubset;
+
+class NET_EXPORT_PRIVATE DecodeBuffer {
+ public:
+ DecodeBuffer(const char* buffer, size_t len)
+ : buffer_(buffer), cursor_(buffer), beyond_(buffer + len) {
+ DCHECK(buffer != nullptr);
+ DCHECK_LE(len, MaxDecodeBufferLength());
+ }
+ explicit DecodeBuffer(base::StringPiece s)
+ : DecodeBuffer(s.data(), s.size()) {}
+ // Constructor for character arrays, typically in tests. For example:
+ // const char input[] = { 0x11 };
+ // DecodeBuffer b(input);
+ template <size_t N>
+ explicit DecodeBuffer(const char (&buf)[N]) : DecodeBuffer(buf, N) {}
+
+ bool Empty() const { return cursor_ >= beyond_; }
+ bool HasData() const { return cursor_ < beyond_; }
+ size_t Remaining() const {
+ DCHECK_LE(cursor_, beyond_);
+ return beyond_ - cursor_;
+ }
+ size_t Offset() const { return cursor_ - buffer_; }
+ size_t FullSize() const { return beyond_ - buffer_; }
+
+ // Returns the minimum of the number of bytes remaining in this DecodeBuffer
+ // and |length|, in support of determining how much of some structure/payload
+ // is in this DecodeBuffer.
+ size_t MinLengthRemaining(size_t length) const {
+ return std::min(length, Remaining());
+ }
+
+ // For string decoding, returns a pointer to the next byte/char to be decoded.
+ const char* cursor() const { return cursor_; }
+ // Advances the cursor (pointer to the next byte/char to be decoded).
+ void AdvanceCursor(size_t amount) {
+ DCHECK_LE(amount, Remaining()); // Need at least that much remaining.
+ DCHECK_EQ(subset_, nullptr) << "Access via subset only when present.";
+ cursor_ += amount;
+ }
+
+ // Only call methods starting "Decode" when there is enough input remaining.
+ char DecodeChar() {
+ DCHECK_LE(1u, Remaining()); // Need at least one byte remaining.
+ DCHECK_EQ(subset_, nullptr) << "Access via subset only when present.";
+ return *cursor_++;
+ }
+
+ uint8_t DecodeUInt8() { return static_cast<uint8_t>(DecodeChar()); }
+
+ uint16_t DecodeUInt16() {
+ DCHECK_LE(2u, Remaining());
+ const uint8_t b1 = DecodeUInt8();
+ const uint8_t b2 = DecodeUInt8();
+ // Note that chars are automatically promoted to ints during arithmetic,
+ // so the b1 << 8 doesn't end up as zero before being or-ed with b2.
+ // And the left-shift operator has higher precedence than the or operator.
+ return b1 << 8 | b2;
+ }
+
+ uint32_t DecodeUInt24() {
+ DCHECK_LE(3u, Remaining());
+ const uint8_t b1 = DecodeUInt8();
+ const uint8_t b2 = DecodeUInt8();
+ const uint8_t b3 = DecodeUInt8();
+ return b1 << 16 | b2 << 8 | b3;
+ }
+
+ // For 31-bit unsigned integers, where the 32nd bit is reserved for future
+ // use (i.e. the high-bit of the first byte of the encoding); examples:
+ // the Stream Id in a frame header or the Window Size Increment in a
+ // WINDOW_UPDATE frame.
+ uint32_t DecodeUInt31() {
+ DCHECK_LE(4u, Remaining());
+ const uint8_t b1 = DecodeUInt8() & 0x7f; // Mask out the high order bit.
+ const uint8_t b2 = DecodeUInt8();
+ const uint8_t b3 = DecodeUInt8();
+ const uint8_t b4 = DecodeUInt8();
+ return b1 << 24 | b2 << 16 | b3 << 8 | b4;
+ }
+
+ uint32_t DecodeUInt32() {
+ DCHECK_LE(4u, Remaining());
+ const uint8_t b1 = DecodeUInt8();
+ const uint8_t b2 = DecodeUInt8();
+ const uint8_t b3 = DecodeUInt8();
+ const uint8_t b4 = DecodeUInt8();
+ return b1 << 24 | b2 << 16 | b3 << 8 | b4;
+ }
+
+ // SlowDecode* routines are used for decoding a multi-field structure when
+ // there may not be enough bytes in the buffer to decode the entirety of the
+ // structure.
+
+ // Read as much of an unsigned int field of an encoded structure as possible,
+ // keeping track via decode_offset of our position in the encoded structure.
+ // Returns true if the field has been fully decoded.
+ // |field_size| is the number of bytes of the encoding of the field (usually
+ // a compile time fixed value).
+ // |field_offset| is the offset of the first byte of the encoding of the field
+ // within the encoding of that structure (usually a compile time fixed value).
+ // |*decode_offset| is the offset of the byte to be decoded next.
+ // |*value| is the storage for the decoded value, and is used for storing
+ // partially decoded values; if some, but not all, bytes of the encoding are
+ // available then this method will return having stored the decoded bytes into
+ // *value.
+ bool SlowDecodeUnsignedInt(uint32_t field_size,
+ uint32_t field_offset,
+ uint32_t* decode_offset,
+ uint32_t* value);
+
+ // Like SlowDecodeUnsignedInt, but specifically for 8-bit unsigned integers.
+ // Obviously a byte can't be split (on our byte addressable machines), but
+ // a larger structure containing such a field might be.
+ bool SlowDecodeUInt8(uint32_t field_offset,
+ uint32_t* decode_offset,
+ uint8_t* value);
+
+ // Like SlowDecodeUnsignedInt, but specifically for 16-bit unsigned integers.
+ bool SlowDecodeUInt16(uint32_t field_offset,
+ uint32_t* decode_offset,
+ uint16_t* value);
+
+ // Like SlowDecodeUnsignedInt, but specifically for 24-bit unsigned integers.
+ bool SlowDecodeUInt24(uint32_t field_offset,
+ uint32_t* decode_offset,
+ uint32_t* value);
+
+ // Like SlowDecodeUnsignedInt, but specifically for 31-bit unsigned integers.
+ // (same definition as for DecodeUInt31).
+ bool SlowDecodeUInt31(uint32_t field_offset,
+ uint32_t* decode_offset,
+ uint32_t* value);
+
+ // Like SlowDecodeUnsignedInt, but specifically for 31-bit unsigned integers.
+ bool SlowDecodeUInt32(uint32_t field_offset,
+ uint32_t* decode_offset,
+ uint32_t* value);
+
+ // Decodes an enum value, where the size (in bytes) of the encoding must be
+ // stated explicitly. It is assumed that under the covers enums are really
+ // just integers, and that we can static_cast them to and from uint32.
+ template <typename E>
+ bool SlowDecodeEnum(uint32_t field_size,
+ uint32_t field_offset,
+ uint32_t* decode_offset,
+ E* value) {
+ uint32_t tmp = static_cast<uint32_t>(*value);
+ const bool done =
+ SlowDecodeUnsignedInt(field_size, field_offset, decode_offset, &tmp);
+ *value = static_cast<E>(tmp);
+ DCHECK_EQ(tmp, static_cast<uint32_t>(*value));
+ return done;
+ }
+
+ // We assume the decode buffers will typically be modest in size (i.e. a few
+ // K).
+ // Let's make sure during testing that we don't go very high, with 32MB
+ // selected rather arbitrarily.
+ static constexpr size_t MaxDecodeBufferLength() { return 1 << 25; }
+
+ protected:
+#ifndef NDEBUG
+ // These are part of validating during tests that there is at most one
+ // DecodeBufferSubset instance at a time for any DecodeBuffer instance.
+ void set_subset_of_base(DecodeBuffer* base,
+ const DecodeBufferSubset* subset) {
+ DCHECK_EQ(this, subset);
+ base->set_subset(subset);
+ }
+ void clear_subset_of_base(DecodeBuffer* base,
+ const DecodeBufferSubset* subset) {
+ DCHECK_EQ(this, subset);
+ base->clear_subset(subset);
+ }
+#endif
+
+ private:
+#ifndef NDEBUG
+ void set_subset(const DecodeBufferSubset* subset) {
+ DCHECK(subset != nullptr);
+ DCHECK_EQ(subset_, nullptr) << "There is already a subset";
+ subset_ = subset;
+ }
+ void clear_subset(const DecodeBufferSubset* subset) {
+ DCHECK(subset != nullptr);
+ DCHECK_EQ(subset_, subset);
+ subset_ = nullptr;
+ }
+#endif
+
+ // Prevent heap allocation of DecodeBuffer.
+ static void* operator new(size_t s);
+ static void* operator new[](size_t s);
+ static void operator delete(void* p);
+ static void operator delete[](void* p);
+
+ const char* const buffer_;
+ const char* cursor_;
+ const char* const beyond_;
+ const DecodeBufferSubset* subset_ = nullptr; // Used for DCHECKs.
+
+ DISALLOW_COPY_AND_ASSIGN(DecodeBuffer);
+};
+
+// DecodeBufferSubset is used when decoding a known sized chunk of data, which
+// starts at base->cursor(), and continues for subset_len, which may be
+// entirely in |base|, or may extend beyond it (hence the MinLengthRemaining
+// in the constructor).
+// There are two benefits to using DecodeBufferSubset: it ensures that the
+// cursor of |base| is advanced when the subset's destructor runs, and it
+// ensures that the consumer of the subset can't go beyond the subset which
+// it is intended to decode.
+// There must be only a single DecodeBufferSubset at a time for a base
+// DecodeBuffer, though they can be nested (i.e. a DecodeBufferSubset's
+// base may itself be a DecodeBufferSubset). This avoids the AdvanceCursor
+// being called erroneously.
+class DecodeBufferSubset : public DecodeBuffer {
+ public:
+ DecodeBufferSubset(DecodeBuffer* base, size_t subset_len)
+ : DecodeBuffer(base->cursor(), base->MinLengthRemaining(subset_len)),
+#ifndef NDEBUG
+ start_base_offset_(base->Offset()),
+ max_base_offset_(start_base_offset_ + FullSize()),
+#endif
+ base_buffer_(base) {
+#ifndef NDEBUG
+ DCHECK_LE(max_base_offset_, base->FullSize());
+ set_subset_of_base(base_buffer_, this);
+#endif
+ }
+
+ ~DecodeBufferSubset() {
+ size_t offset = Offset();
+#ifndef NDEBUG
+ clear_subset_of_base(base_buffer_, this);
+ DCHECK_LE(Offset(), FullSize());
+ DCHECK_EQ(start_base_offset_, base_buffer_->Offset())
+ << "The base buffer was modified";
+ DCHECK_LE(offset, FullSize());
+ DCHECK_LE(start_base_offset_ + offset, base_buffer_->FullSize());
+#endif
+ base_buffer_->AdvanceCursor(offset);
+#ifndef NDEBUG
+ DCHECK_GE(max_base_offset_, base_buffer_->Offset());
+#endif
+ }
+
+ private:
+#ifndef NDEBUG
+ const size_t start_base_offset_; // Used for DCHECKs.
+ const size_t max_base_offset_; // Used for DCHECKs.
+#endif
+ DecodeBuffer* const base_buffer_;
+
+ DISALLOW_COPY_AND_ASSIGN(DecodeBufferSubset);
+};
+
+} // namespace net
+
+#endif // NET_HTTP2_DECODER_DECODE_BUFFER_H_
diff --git a/chromium/net/http2/decoder/decode_buffer_test.cc b/chromium/net/http2/decoder/decode_buffer_test.cc
new file mode 100644
index 00000000000..a4d10d7cb28
--- /dev/null
+++ b/chromium/net/http2/decoder/decode_buffer_test.cc
@@ -0,0 +1,378 @@
+// Copyright 2016 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.
+
+#include "net/http2/decoder/decode_buffer.h"
+
+#include <string>
+
+#include "base/logging.h"
+#include "base/strings/string_piece.h"
+#include "net/http2/tools/http2_random.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+using base::StringPiece;
+using std::string;
+
+namespace net {
+namespace test {
+
+enum class TestEnumClass32 {
+ kValue1 = 1,
+ kValue99 = 99,
+ kValue1M = 1000000,
+};
+
+enum class TestEnumClass8 {
+ kValue1 = 1,
+ kValue2 = 1,
+ kValue99 = 99,
+ kValue255 = 255,
+};
+
+enum TestEnum8 {
+ kMaskLo = 0x01,
+ kMaskHi = 0x80,
+};
+
+struct TestStruct {
+ uint8_t f1;
+ uint16_t f2;
+ uint32_t f3; // Decoded as a uint24
+ uint32_t f4;
+ uint32_t f5; // Decoded as if uint31
+ TestEnumClass32 f6;
+ TestEnumClass8 f7;
+ TestEnum8 f8;
+};
+
+const size_t kF1Offset = 0;
+const size_t kF2Offset = 1;
+const size_t kF3Offset = 3;
+const size_t kF4Offset = 6;
+const size_t kF5Offset = 10;
+const size_t kF6Offset = 14;
+const size_t kF7Offset = 18;
+const size_t kF8Offset = 19;
+
+class DecodeBufferTest : public ::testing::Test {
+ public:
+ DecodeBufferTest() {}
+
+ protected:
+ // Double checks the call fn(f).
+ template <typename T>
+ bool SlowDecodeField(DecodeBuffer* b,
+ size_t field_size,
+ size_t field_offset,
+ std::function<bool(DecodeBuffer*)> fn,
+ T* f) {
+ VLOG(2) << "Remaining: " << b->Remaining();
+ VLOG(2) << "field_size: " << field_size;
+ VLOG(2) << "field_offset: " << field_offset;
+ VLOG(2) << "decode_offset_: " << decode_offset_;
+ EXPECT_GE(decode_offset_, field_offset);
+ bool had_data = b->HasData();
+ VLOG(2) << "had_data: " << had_data;
+ uint32_t old = static_cast<uint32_t>(*f);
+ VLOG(2) << "old: " << old;
+ size_t old_decode_offset = decode_offset_;
+ bool done = fn(b);
+ VLOG(2) << "done: " << done;
+ if (old_decode_offset == decode_offset_) {
+ // Didn't do any decoding (may have no input, or may have already
+ // decoded this field).
+ if (done) {
+ EXPECT_LE(field_offset + field_size, decode_offset_);
+ // Shouldn't have modified already decoded field.
+ EXPECT_EQ(old, static_cast<uint32_t>(*f));
+ } else {
+ EXPECT_TRUE(!had_data);
+ }
+ } else {
+ // Did some decoding.
+ EXPECT_TRUE(had_data);
+ EXPECT_LT(old_decode_offset, decode_offset_);
+ if (done) {
+ EXPECT_EQ(field_offset + field_size, decode_offset_);
+ } else {
+ EXPECT_GT(field_offset + field_size, decode_offset_);
+ }
+ }
+ VLOG(2) << "---------------------------------------";
+ return done;
+ }
+
+
+ void SlowDecodeTestStruct(StringPiece input, TestStruct* p) {
+ VLOG(2) << "############################################################";
+ EXPECT_LE(10u, input.size());
+ decode_offset_ = 0;
+ auto decode_f1 = [this, p](DecodeBuffer* db) {
+ return db->SlowDecodeUInt8(kF1Offset, &decode_offset_, &p->f1);
+ };
+ auto decode_f2 = [this, p](DecodeBuffer* db) {
+ return db->SlowDecodeUInt16(kF2Offset, &decode_offset_, &p->f2);
+ };
+ auto decode_f3 = [this, p](DecodeBuffer* db) {
+ return db->SlowDecodeUInt24(kF3Offset, &decode_offset_, &p->f3);
+ };
+ auto decode_f4 = [this, p](DecodeBuffer* db) {
+ return db->SlowDecodeUInt32(kF4Offset, &decode_offset_, &p->f4);
+ };
+ auto decode_f5 = [this, p](DecodeBuffer* db) {
+ return db->SlowDecodeUInt31(kF5Offset, &decode_offset_, &p->f5);
+ };
+ auto decode_f6 = [this, p](DecodeBuffer* db) {
+ return db->SlowDecodeEnum(4, kF6Offset, &decode_offset_, &p->f6);
+ };
+ auto decode_f7 = [this, p](DecodeBuffer* db) {
+ return db->SlowDecodeEnum(1, kF7Offset, &decode_offset_, &p->f7);
+ };
+ auto decode_f8 = [this, p](DecodeBuffer* db) {
+ return db->SlowDecodeEnum(1, kF8Offset, &decode_offset_, &p->f8);
+ };
+ while (input.size() > 0) {
+ size_t size = input.size();
+ // Sometimes check that zero length input is OK.
+ auto r = random_.Next();
+ if (r % 100 == 0) {
+ size = 0;
+ } else if (size > 1) {
+ auto r = random_.Next();
+ size = (r % size) + 1;
+ }
+ VLOG(2) << "================= input size " << size;
+ DecodeBuffer b(input.data(), size);
+ size_t old_decode_offset = decode_offset_;
+ if (SlowDecodeField(&b, 1, kF1Offset, decode_f1, &p->f1) &&
+ SlowDecodeField(&b, 2, kF2Offset, decode_f2, &p->f2) &&
+ SlowDecodeField(&b, 3, kF3Offset, decode_f3, &p->f3) &&
+ SlowDecodeField(&b, 4, kF4Offset, decode_f4, &p->f4) &&
+ SlowDecodeField(&b, 4, kF5Offset, decode_f5, &p->f5) &&
+ SlowDecodeField(&b, 4, kF6Offset, decode_f6, &p->f6) &&
+ SlowDecodeField(&b, 1, kF7Offset, decode_f7, &p->f7) &&
+ SlowDecodeField(&b, 1, kF8Offset, decode_f8, &p->f8)) {
+ EXPECT_TRUE(b.Empty());
+ EXPECT_EQ(size, input.size());
+ EXPECT_EQ(input.size(), b.Offset()); // All input consumed.
+ return;
+ }
+ EXPECT_EQ(old_decode_offset + size, decode_offset_);
+ EXPECT_TRUE(b.Empty());
+ EXPECT_EQ(size, b.Offset()); // All input consumed.
+ EXPECT_LT(size, input.size()); // More remains.
+ input = StringPiece(input.data() + size, input.size() - size);
+ }
+ ADD_FAILURE() << "Ran out of input! decode_offset_ = " << decode_offset_;
+ }
+
+ Http2Random random_;
+ uint32_t decode_offset_;
+};
+
+TEST_F(DecodeBufferTest, DecodesFixedInts) {
+ const char data[] = "\x01\x12\x23\x34\x45\x56\x67\x78\x89\x9a";
+ DecodeBuffer b1(data, strlen(data));
+ EXPECT_EQ(1, b1.DecodeUInt8());
+ EXPECT_EQ(0x1223u, b1.DecodeUInt16());
+ EXPECT_EQ(0x344556u, b1.DecodeUInt24());
+ EXPECT_EQ(0x6778899Au, b1.DecodeUInt32());
+
+ DecodeBuffer b2(data, strlen(data));
+ uint8_t b;
+ decode_offset_ = 0;
+ EXPECT_TRUE(b2.SlowDecodeUInt8(0, &decode_offset_, &b));
+ EXPECT_EQ(1, b);
+ uint16_t s;
+ decode_offset_ = 0;
+ EXPECT_TRUE(b2.SlowDecodeUInt16(0, &decode_offset_, &s));
+ EXPECT_EQ(0x1223, s);
+ uint32_t i;
+ decode_offset_ = 0;
+ EXPECT_TRUE(b2.SlowDecodeUInt24(0, &decode_offset_, &i));
+ // EXPECT_EQ(0x344556, b1.DecodeUInt24());
+ // EXPECT_EQ(0x6778899a, b1.DecodeUInt32());
+}
+
+// Decode the structure many times, where we'll pass different partitions
+// into DecodeSlowly.
+TEST_F(DecodeBufferTest, SlowDecodeTestStruct) {
+ // clang-format off
+ const char data[] = {
+ 0x12u, // f1
+ 0x23u, 0x34u, // f2
+ 0x45u, 0x56u, 0x67u, // f3
+ 0x78u, 0x89u, 0x9au, 0xabu, // f4
+ 0xfeu, 0xedu, 0xdcu, 0xcbu, // f5 (high-bit will be cleared.)
+ 0x00u, 0x0fu, 0x42u, 0x40u, // f6 (kValue1M)
+ 0x63u, // f7 (kValue99)
+ 0x81u, // f8 (kMaskLo | kMaskHi)
+ };
+ // clang-format on
+ StringPiece input(data, sizeof data);
+ for (int i = 0; i < 200; ++i) {
+ TestStruct ts;
+ // Init the struct to random garbage.
+ ts.f1 = random_.Rand8();
+ ts.f2 = random_.Rand16();
+ ts.f3 = random_.Rand32();
+ ts.f4 = random_.Rand32();
+ ts.f5 = 0x80000000 | random_.Rand32(); // Ensure high-bit is set.
+ ts.f6 = static_cast<TestEnumClass32>(random_.Rand32());
+ ts.f7 = static_cast<TestEnumClass8>(random_.Rand8());
+ ts.f8 = static_cast<TestEnum8>(random_.Rand8());
+ SlowDecodeTestStruct(input, &ts);
+ ASSERT_EQ(0x12u, ts.f1);
+ ASSERT_EQ(0x2334u, ts.f2);
+ ASSERT_EQ(0x455667u, ts.f3);
+ ASSERT_EQ(0x78899AABu, ts.f4);
+ ASSERT_EQ(0x7EEDDCCBu, ts.f5);
+ ASSERT_EQ(TestEnumClass32::kValue1M, ts.f6);
+ ASSERT_EQ(TestEnumClass8::kValue99, ts.f7);
+ ASSERT_EQ(kMaskLo | kMaskHi, ts.f8);
+ }
+}
+
+// Make sure that DecodeBuffer is not copying input, just pointing into
+// provided input buffer.
+TEST_F(DecodeBufferTest, HasNotCopiedInput) {
+ const char data[] = "ab";
+ DecodeBuffer b1(data, 2);
+
+ EXPECT_EQ(2u, b1.Remaining());
+ EXPECT_EQ(0u, b1.Offset());
+ EXPECT_FALSE(b1.Empty());
+ EXPECT_EQ(data, b1.cursor()); // cursor points to input buffer
+ EXPECT_TRUE(b1.HasData());
+
+ b1.AdvanceCursor(1);
+
+ EXPECT_EQ(1u, b1.Remaining());
+ EXPECT_EQ(1u, b1.Offset());
+ EXPECT_FALSE(b1.Empty());
+ EXPECT_EQ(&data[1], b1.cursor());
+ EXPECT_TRUE(b1.HasData());
+
+ b1.AdvanceCursor(1);
+
+ EXPECT_EQ(0u, b1.Remaining());
+ EXPECT_EQ(2u, b1.Offset());
+ EXPECT_TRUE(b1.Empty());
+ EXPECT_EQ(&data[2], b1.cursor());
+ EXPECT_FALSE(b1.HasData());
+
+ DecodeBuffer b2(data, 0);
+
+ EXPECT_EQ(0u, b2.Remaining());
+ EXPECT_EQ(0u, b2.Offset());
+ EXPECT_TRUE(b2.Empty());
+ EXPECT_EQ(data, b2.cursor());
+ EXPECT_FALSE(b2.HasData());
+}
+
+// DecodeBufferSubset can't go beyond the end of the base buffer.
+TEST_F(DecodeBufferTest, DecodeBufferSubsetLimited) {
+ const char data[] = "abc";
+ DecodeBuffer base(data, 3);
+ base.AdvanceCursor(1);
+ DecodeBufferSubset subset(&base, 100);
+ EXPECT_EQ(2u, subset.FullSize());
+}
+
+// DecodeBufferSubset advances the cursor of its base upon destruction.
+TEST_F(DecodeBufferTest, DecodeBufferSubsetAdvancesCursor) {
+ const char data[] = "abc";
+ const size_t size = sizeof(data) - 1;
+ EXPECT_EQ(3u, size);
+ DecodeBuffer base(data, size);
+ {
+ // First no change to the cursor.
+ DecodeBufferSubset subset(&base, size + 100);
+ EXPECT_EQ(size, subset.FullSize());
+ EXPECT_EQ(base.FullSize(), subset.FullSize());
+ EXPECT_EQ(0u, subset.Offset());
+ }
+ EXPECT_EQ(0u, base.Offset());
+ EXPECT_EQ(size, base.Remaining());
+}
+
+// Make sure that DecodeBuffer ctor complains about bad args.
+#if GTEST_HAS_DEATH_TEST && !defined(NDEBUG)
+TEST(DecodeBufferDeathTest, NonNullBufferRequired) {
+ EXPECT_DEBUG_DEATH({ DecodeBuffer b(nullptr, 3); }, "nullptr");
+}
+
+// Make sure that DecodeBuffer ctor complains about bad args.
+TEST(DecodeBufferDeathTest, ModestBufferSizeRequired) {
+ EXPECT_DEBUG_DEATH(
+ {
+ const char data[] = "abc";
+ size_t len = 0;
+ DecodeBuffer b(data, ~len);
+ },
+ "Max.*Length");
+}
+
+// Make sure that DecodeBuffer detects advance beyond end, in debug mode.
+TEST(DecodeBufferDeathTest, LimitedAdvance) {
+ {
+ // Advance right up to end is OK.
+ const char data[] = "abc";
+ DecodeBuffer b(data, 3);
+ b.AdvanceCursor(3); // OK
+ EXPECT_TRUE(b.Empty());
+ }
+ EXPECT_DEBUG_DEATH(
+ {
+ // Going beyond is not OK.
+ const char data[] = "abc";
+ DecodeBuffer b(data, 3);
+ b.AdvanceCursor(4);
+ },
+ "4 vs. 3");
+}
+
+// Make sure that DecodeBuffer detects decode beyond end, in debug mode.
+TEST(DecodeBufferDeathTest, DecodeUInt8PastEnd) {
+ const char data[] = {0x12, 0x23};
+ DecodeBuffer b(data, sizeof data);
+ EXPECT_EQ(2u, b.FullSize());
+ EXPECT_EQ(0x1223, b.DecodeUInt16());
+ EXPECT_DEBUG_DEATH({ b.DecodeUInt8(); }, "1 vs. 0");
+}
+
+// Make sure that DecodeBuffer detects decode beyond end, in debug mode.
+TEST(DecodeBufferDeathTest, DecodeUInt16OverEnd) {
+ const char data[] = {0x12, 0x23, 0x34};
+ DecodeBuffer b(data, sizeof data);
+ EXPECT_EQ(3u, b.FullSize());
+ EXPECT_EQ(0x1223, b.DecodeUInt16());
+ EXPECT_DEBUG_DEATH({ b.DecodeUInt16(); }, "2 vs. 1");
+}
+
+// Make sure that DecodeBuffer doesn't agree with having two subsets.
+TEST(DecodeBufferSubsetDeathTest, TwoSubsets) {
+ const char data[] = "abc";
+ DecodeBuffer base(data, 3);
+ DecodeBufferSubset subset1(&base, 1);
+ EXPECT_DEBUG_DEATH({ DecodeBufferSubset subset2(&base, 1); },
+ "There is already a subset");
+}
+
+// Make sure that DecodeBufferSubset notices when the base's cursor has moved.
+TEST(DecodeBufferSubsetDeathTest, BaseCursorAdvanced) {
+ const char data[] = "abc";
+ DecodeBuffer base(data, 3);
+ base.AdvanceCursor(1);
+ EXPECT_DEBUG_DEATH(
+ {
+ DecodeBufferSubset subset1(&base, 2);
+ base.AdvanceCursor(1);
+ },
+ "Access via subset only when present");
+}
+#endif // GTEST_HAS_DEATH_TEST && !defined(NDEBUG)
+
+} // namespace test
+} // namespace net
diff --git a/chromium/net/http2/decoder/decode_http2_structures.cc b/chromium/net/http2/decoder/decode_http2_structures.cc
new file mode 100644
index 00000000000..cd419e38bfb
--- /dev/null
+++ b/chromium/net/http2/decoder/decode_http2_structures.cc
@@ -0,0 +1,355 @@
+// Copyright 2016 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.
+
+#include "net/http2/decoder/decode_http2_structures.h"
+
+#include <string.h>
+
+#include "base/logging.h"
+#include "net/http2/decoder/decode_buffer.h"
+#include "net/http2/http2_constants.h"
+
+namespace net {
+
+// Http2FrameHeader decoding:
+
+void DoDecode(Http2FrameHeader* out, DecodeBuffer* b) {
+ DCHECK_NE(nullptr, out);
+ DCHECK_NE(nullptr, b);
+ DCHECK_LE(Http2FrameHeader::EncodedSize(), b->Remaining());
+ out->payload_length = b->DecodeUInt24();
+ out->type = static_cast<Http2FrameType>(b->DecodeUInt8());
+ out->flags = static_cast<Http2FrameFlag>(b->DecodeUInt8());
+ out->stream_id = b->DecodeUInt31();
+}
+
+bool MaybeDecode(Http2FrameHeader* out, DecodeBuffer* b) {
+ DCHECK_NE(nullptr, out);
+ DCHECK_NE(nullptr, b);
+ if (b->Remaining() >= Http2FrameHeader::EncodedSize()) {
+ DoDecode(out, b);
+ return true;
+ }
+ return false;
+}
+
+bool SlowDecode(Http2FrameHeader* out, DecodeBuffer* b, uint32_t* offset) {
+ DCHECK_NE(nullptr, out);
+ DCHECK_NE(nullptr, b);
+ DCHECK_NE(nullptr, offset);
+ DCHECK_GT(Http2FrameHeader::EncodedSize(), *offset);
+ if (b->SlowDecodeUInt24(0 /* field_offset */, offset, &out->payload_length) &&
+ b->SlowDecodeEnum(1 /* field_size */, 3 /* field_offset */, offset,
+ &out->type) &&
+ b->SlowDecodeEnum(1 /* field_size */, 4 /* field_offset */, offset,
+ &out->flags) &&
+ b->SlowDecodeUInt31(5 /* field_offset */, offset, &out->stream_id)) {
+ DCHECK_EQ(Http2FrameHeader::EncodedSize(), *offset);
+ return true;
+ }
+ DCHECK_GT(Http2FrameHeader::EncodedSize(), *offset);
+ return false;
+}
+
+// Http2PriorityFields decoding:
+
+void DoDecode(Http2PriorityFields* out, DecodeBuffer* b) {
+ DCHECK_NE(nullptr, out);
+ DCHECK_NE(nullptr, b);
+ DCHECK_LE(Http2PriorityFields::EncodedSize(), b->Remaining());
+ uint32_t stream_id_and_flag = b->DecodeUInt32();
+ out->stream_dependency = stream_id_and_flag & StreamIdMask();
+ if (out->stream_dependency == stream_id_and_flag) {
+ out->is_exclusive = false;
+ } else {
+ out->is_exclusive = true;
+ }
+ // Note that chars are automatically promoted to ints during arithmetic,
+ // so 255 + 1 doesn't end up as zero.
+ out->weight = b->DecodeUInt8() + 1;
+}
+
+bool MaybeDecode(Http2PriorityFields* out, DecodeBuffer* b) {
+ DCHECK_NE(nullptr, out);
+ DCHECK_NE(nullptr, b);
+ if (b->Remaining() >= Http2PriorityFields::EncodedSize()) {
+ DoDecode(out, b);
+ return true;
+ }
+ return false;
+}
+
+bool SlowDecode(Http2PriorityFields* out, DecodeBuffer* b, uint32_t* offset) {
+ DCHECK_NE(nullptr, out);
+ DCHECK_NE(nullptr, b);
+ DCHECK_NE(nullptr, offset);
+ DCHECK_GT(Http2PriorityFields::EncodedSize(), *offset);
+ const uint32_t start_offset = *offset;
+ if (b->SlowDecodeUInt32(0 /* field_offset */, offset,
+ &out->stream_dependency) &&
+ b->SlowDecodeUnsignedInt(1, // field_size
+ 4, // field_offset
+ offset, &out->weight)) {
+ DCHECK_EQ(Http2PriorityFields::EncodedSize(), *offset);
+ if (start_offset < *offset) {
+ // First time here. Extract is_exclusive from stream_dependency.
+ const uint32_t stream_id_only = out->stream_dependency & StreamIdMask();
+ if (out->stream_dependency != stream_id_only) {
+ out->stream_dependency = stream_id_only;
+ out->is_exclusive = true;
+ } else {
+ out->is_exclusive = false;
+ }
+ // Need to add one to the weight field because the encoding is 0-255, but
+ // interpreted as 1-256.
+ ++(out->weight);
+ }
+ return true;
+ }
+ DCHECK_GT(Http2PriorityFields::EncodedSize(), *offset);
+ return false;
+}
+
+// Http2RstStreamFields decoding:
+
+void DoDecode(Http2RstStreamFields* out, DecodeBuffer* b) {
+ DCHECK_NE(nullptr, out);
+ DCHECK_NE(nullptr, b);
+ DCHECK_LE(Http2RstStreamFields::EncodedSize(), b->Remaining());
+ out->error_code = static_cast<Http2ErrorCode>(b->DecodeUInt32());
+}
+
+bool MaybeDecode(Http2RstStreamFields* out, DecodeBuffer* b) {
+ DCHECK_NE(nullptr, out);
+ DCHECK_NE(nullptr, b);
+ if (b->Remaining() >= Http2RstStreamFields::EncodedSize()) {
+ DoDecode(out, b);
+ return true;
+ }
+ return false;
+}
+
+bool SlowDecode(Http2RstStreamFields* out, DecodeBuffer* b, uint32_t* offset) {
+ DCHECK_NE(nullptr, out);
+ DCHECK_NE(nullptr, b);
+ DCHECK_NE(nullptr, offset);
+ DCHECK_GT(Http2RstStreamFields::EncodedSize(), *offset);
+
+ if (b->SlowDecodeEnum(4 /* field_size */, 0 /* field_offset */, offset,
+ &out->error_code)) {
+ DCHECK_EQ(Http2RstStreamFields::EncodedSize(), *offset);
+ return true;
+ }
+ DCHECK_GT(Http2RstStreamFields::EncodedSize(), *offset);
+ return false;
+}
+
+// Http2SettingFields decoding:
+
+void DoDecode(Http2SettingFields* out, DecodeBuffer* b) {
+ DCHECK_NE(nullptr, out);
+ DCHECK_NE(nullptr, b);
+ DCHECK_LE(Http2SettingFields::EncodedSize(), b->Remaining());
+ out->parameter = static_cast<Http2SettingsParameter>(b->DecodeUInt16());
+ out->value = b->DecodeUInt32();
+}
+
+bool MaybeDecode(Http2SettingFields* out, DecodeBuffer* b) {
+ DCHECK_NE(nullptr, out);
+ DCHECK_NE(nullptr, b);
+ if (b->Remaining() >= Http2SettingFields::EncodedSize()) {
+ DoDecode(out, b);
+ return true;
+ }
+ return false;
+}
+
+bool SlowDecode(Http2SettingFields* out, DecodeBuffer* b, uint32_t* offset) {
+ DCHECK_NE(nullptr, out);
+ DCHECK_NE(nullptr, b);
+ DCHECK_NE(nullptr, offset);
+ DCHECK_LT(*offset, Http2SettingFields::EncodedSize());
+
+ if (b->SlowDecodeEnum(2 /* field_size */, 0 /* field_offset */, offset,
+ &out->parameter) &&
+ b->SlowDecodeUInt32(2 /* field_offset */, offset, &out->value)) {
+ DCHECK_EQ(Http2SettingFields::EncodedSize(), *offset);
+ return true;
+ }
+ DCHECK_LT(*offset, Http2SettingFields::EncodedSize());
+ return false;
+}
+
+// Http2PushPromiseFields decoding:
+
+void DoDecode(Http2PushPromiseFields* out, DecodeBuffer* b) {
+ DCHECK_NE(nullptr, out);
+ DCHECK_NE(nullptr, b);
+ DCHECK_LE(Http2PushPromiseFields::EncodedSize(), b->Remaining());
+ out->promised_stream_id = b->DecodeUInt31();
+}
+
+bool MaybeDecode(Http2PushPromiseFields* out, DecodeBuffer* b) {
+ DCHECK_NE(nullptr, out);
+ DCHECK_NE(nullptr, b);
+ if (b->Remaining() >= Http2PushPromiseFields::EncodedSize()) {
+ DoDecode(out, b);
+ return true;
+ }
+ return false;
+}
+
+bool SlowDecode(Http2PushPromiseFields* out,
+ DecodeBuffer* b,
+ uint32_t* offset) {
+ DCHECK_NE(nullptr, out);
+ DCHECK_NE(nullptr, b);
+ DCHECK_NE(nullptr, offset);
+ DCHECK_LT(*offset, Http2PushPromiseFields::EncodedSize());
+ if (b->SlowDecodeUInt31(0 /* field_offset */, offset,
+ &out->promised_stream_id)) {
+ DCHECK_EQ(Http2PushPromiseFields::EncodedSize(), *offset);
+ return true;
+ }
+ DCHECK_LT(*offset, Http2PushPromiseFields::EncodedSize());
+ return false;
+}
+
+// Http2PingFields decoding:
+
+void DoDecode(Http2PingFields* out, DecodeBuffer* b) {
+ DCHECK_NE(nullptr, out);
+ DCHECK_NE(nullptr, b);
+ DCHECK_LE(Http2PingFields::EncodedSize(), b->Remaining());
+ memcpy(out->opaque_data, b->cursor(), Http2PingFields::EncodedSize());
+ b->AdvanceCursor(Http2PingFields::EncodedSize());
+}
+
+bool MaybeDecode(Http2PingFields* out, DecodeBuffer* b) {
+ DCHECK_NE(nullptr, out);
+ DCHECK_NE(nullptr, b);
+ if (b->Remaining() >= Http2PingFields::EncodedSize()) {
+ DoDecode(out, b);
+ return true;
+ }
+ return false;
+}
+
+bool SlowDecode(Http2PingFields* out, DecodeBuffer* b, uint32_t* offset) {
+ DCHECK_NE(nullptr, out);
+ DCHECK_NE(nullptr, b);
+ DCHECK_NE(nullptr, offset);
+ DCHECK_LT(*offset, Http2PingFields::EncodedSize());
+ while (*offset < Http2PingFields::EncodedSize()) {
+ if (b->Empty()) {
+ return false;
+ }
+ out->opaque_data[(*offset)++] = b->DecodeUInt8();
+ }
+ return true;
+}
+
+// Http2GoAwayFields decoding:
+
+void DoDecode(Http2GoAwayFields* out, DecodeBuffer* b) {
+ DCHECK_NE(nullptr, out);
+ DCHECK_NE(nullptr, b);
+ DCHECK_LE(Http2GoAwayFields::EncodedSize(), b->Remaining());
+ out->last_stream_id = b->DecodeUInt31();
+ out->error_code = static_cast<Http2ErrorCode>(b->DecodeUInt32());
+}
+
+bool MaybeDecode(Http2GoAwayFields* out, DecodeBuffer* b) {
+ DCHECK_NE(nullptr, out);
+ DCHECK_NE(nullptr, b);
+ if (b->Remaining() >= Http2GoAwayFields::EncodedSize()) {
+ DoDecode(out, b);
+ return true;
+ }
+ return false;
+}
+
+bool SlowDecode(Http2GoAwayFields* out, DecodeBuffer* b, uint32_t* offset) {
+ DCHECK_NE(nullptr, out);
+ DCHECK_NE(nullptr, b);
+ DCHECK_NE(nullptr, offset);
+ DCHECK_LT(*offset, Http2GoAwayFields::EncodedSize());
+ if (b->SlowDecodeUInt31(0 /* field_offset */, offset, &out->last_stream_id) &&
+ b->SlowDecodeEnum(4 /* field_size */, 4 /* field_offset */, offset,
+ &out->error_code)) {
+ DCHECK_EQ(Http2GoAwayFields::EncodedSize(), *offset);
+ return true;
+ }
+ DCHECK_LT(*offset, Http2GoAwayFields::EncodedSize());
+ return false;
+}
+
+// Http2WindowUpdateFields decoding:
+
+void DoDecode(Http2WindowUpdateFields* out, DecodeBuffer* b) {
+ DCHECK_NE(nullptr, out);
+ DCHECK_NE(nullptr, b);
+ DCHECK_LE(Http2WindowUpdateFields::EncodedSize(), b->Remaining());
+ out->window_size_increment = b->DecodeUInt31();
+}
+
+bool MaybeDecode(Http2WindowUpdateFields* out, DecodeBuffer* b) {
+ DCHECK_NE(nullptr, out);
+ DCHECK_NE(nullptr, b);
+ if (b->Remaining() >= Http2WindowUpdateFields::EncodedSize()) {
+ DoDecode(out, b);
+ return true;
+ }
+ return false;
+}
+
+bool SlowDecode(Http2WindowUpdateFields* out,
+ DecodeBuffer* b,
+ uint32_t* offset) {
+ DCHECK_NE(nullptr, out);
+ DCHECK_NE(nullptr, b);
+ DCHECK_NE(nullptr, offset);
+ DCHECK_LT(*offset, Http2WindowUpdateFields::EncodedSize());
+ if (b->SlowDecodeUInt31(0 /* field_offset */, offset,
+ &out->window_size_increment)) {
+ DCHECK_EQ(Http2WindowUpdateFields::EncodedSize(), *offset);
+ return true;
+ }
+ DCHECK_LT(*offset, Http2WindowUpdateFields::EncodedSize());
+ return false;
+}
+
+// Http2AltSvcFields decoding:
+
+void DoDecode(Http2AltSvcFields* out, DecodeBuffer* b) {
+ DCHECK_NE(nullptr, out);
+ DCHECK_NE(nullptr, b);
+ DCHECK_LE(Http2AltSvcFields::EncodedSize(), b->Remaining());
+ out->origin_length = b->DecodeUInt16();
+}
+
+bool MaybeDecode(Http2AltSvcFields* out, DecodeBuffer* b) {
+ DCHECK_NE(nullptr, out);
+ DCHECK_NE(nullptr, b);
+ if (b->Remaining() >= Http2AltSvcFields::EncodedSize()) {
+ DoDecode(out, b);
+ return true;
+ }
+ return false;
+}
+
+bool SlowDecode(Http2AltSvcFields* out, DecodeBuffer* b, uint32_t* offset) {
+ DCHECK_NE(nullptr, out);
+ DCHECK_NE(nullptr, b);
+ DCHECK_NE(nullptr, offset);
+ DCHECK_LT(*offset, Http2AltSvcFields::EncodedSize());
+ if (b->SlowDecodeUInt16(0 /* field_offset */, offset, &out->origin_length)) {
+ DCHECK_EQ(Http2AltSvcFields::EncodedSize(), *offset);
+ return true;
+ }
+ DCHECK_LT(*offset, Http2AltSvcFields::EncodedSize());
+ return false;
+}
+
+} // namespace net
diff --git a/chromium/net/http2/decoder/decode_http2_structures.h b/chromium/net/http2/decoder/decode_http2_structures.h
new file mode 100644
index 00000000000..7cee46f26a6
--- /dev/null
+++ b/chromium/net/http2/decoder/decode_http2_structures.h
@@ -0,0 +1,94 @@
+// Copyright 2016 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.
+
+#ifndef NET_HTTP2_DECODER_DECODE_HTTP2_STRUCTURES_H_
+#define NET_HTTP2_DECODER_DECODE_HTTP2_STRUCTURES_H_
+
+// Provides functions for decoding the fixed size structures in the HTTP/2 spec.
+
+// TODO(jamessynge): Consider whether the value of the SlowDecode methods is
+// worth their complexity; in particular, dropping back to buffering at most
+// 9 bytes (the largest fixed size structure) may actually be more efficient
+// than using the SlowDecode methods, or at least worth the complexity
+// reduction.
+// See http2_structure_decoder.h et al for an experiment in removing all except
+// DoDecode.
+
+#include "net/base/net_export.h"
+#include "net/http2/decoder/decode_buffer.h"
+#include "net/http2/http2_structures.h"
+
+namespace net {
+
+// DoDecode(STRUCTURE* out, DecodeBuffer* b) decodes the structure from start
+// to end, advancing the cursor by STRUCTURE::EncodedSize(). The decoder buffer
+// must be large enough (i.e. b->Remaining() >= STRUCTURE::EncodedSize()).
+
+NET_EXPORT_PRIVATE void DoDecode(Http2FrameHeader* out, DecodeBuffer* b);
+NET_EXPORT_PRIVATE void DoDecode(Http2PriorityFields* out, DecodeBuffer* b);
+NET_EXPORT_PRIVATE void DoDecode(Http2RstStreamFields* out, DecodeBuffer* b);
+NET_EXPORT_PRIVATE void DoDecode(Http2SettingFields* out, DecodeBuffer* b);
+NET_EXPORT_PRIVATE void DoDecode(Http2PushPromiseFields* out, DecodeBuffer* b);
+NET_EXPORT_PRIVATE void DoDecode(Http2PingFields* out, DecodeBuffer* b);
+NET_EXPORT_PRIVATE void DoDecode(Http2GoAwayFields* out, DecodeBuffer* b);
+NET_EXPORT_PRIVATE void DoDecode(Http2WindowUpdateFields* out, DecodeBuffer* b);
+NET_EXPORT_PRIVATE void DoDecode(Http2AltSvcFields* out, DecodeBuffer* b);
+
+// MaybeDecode(STRUCTURE* out, DecodeBuffer* b) decodes the structure from
+// start to end if the decoder buffer is large enough, advancing the cursor
+// by STRUCTURE::EncodedSize(), then returns true.
+// If the decode buffer isn't large enough, does nothing and returns false.
+// The buffer is large enough if b->Remaining() >= STRUCTURE::EncodedSize().
+
+NET_EXPORT_PRIVATE bool MaybeDecode(Http2FrameHeader* out, DecodeBuffer* b);
+NET_EXPORT_PRIVATE bool MaybeDecode(Http2PriorityFields* out, DecodeBuffer* b);
+NET_EXPORT_PRIVATE bool MaybeDecode(Http2RstStreamFields* out, DecodeBuffer* b);
+NET_EXPORT_PRIVATE bool MaybeDecode(Http2SettingFields* out, DecodeBuffer* b);
+NET_EXPORT_PRIVATE bool MaybeDecode(Http2PushPromiseFields* out,
+ DecodeBuffer* b);
+NET_EXPORT_PRIVATE bool MaybeDecode(Http2PingFields* out, DecodeBuffer* b);
+NET_EXPORT_PRIVATE bool MaybeDecode(Http2GoAwayFields* out, DecodeBuffer* b);
+NET_EXPORT_PRIVATE bool MaybeDecode(Http2WindowUpdateFields* out,
+ DecodeBuffer* b);
+NET_EXPORT_PRIVATE bool MaybeDecode(Http2AltSvcFields* out, DecodeBuffer* b);
+
+// SlowDecode(STRUCTURE* out, DecodeBuffer* b, uint32_t* offset) provides
+// incremental decoding of a structure, supporting cases where the structure
+// is split across multiple input buffers. *offset represents the offset within
+// the encoding of the structure, in the range [0, STRUCTURE::EncodedSize()].
+// Returns true when it is able to completely decode the structure, false
+// before that. Updates *offset to record the progress decoding the structure;
+// if false is returned, then b->Remaining() == 0 when SlowDecode returns.
+
+NET_EXPORT_PRIVATE bool SlowDecode(Http2FrameHeader* out,
+ DecodeBuffer* b,
+ uint32_t* offset);
+NET_EXPORT_PRIVATE bool SlowDecode(Http2PriorityFields* out,
+ DecodeBuffer* b,
+ uint32_t* offset);
+NET_EXPORT_PRIVATE bool SlowDecode(Http2RstStreamFields* out,
+ DecodeBuffer* b,
+ uint32_t* offset);
+NET_EXPORT_PRIVATE bool SlowDecode(Http2SettingFields* out,
+ DecodeBuffer* b,
+ uint32_t* offset);
+NET_EXPORT_PRIVATE bool SlowDecode(Http2PushPromiseFields* out,
+ DecodeBuffer* b,
+ uint32_t* offset);
+NET_EXPORT_PRIVATE bool SlowDecode(Http2PingFields* out,
+ DecodeBuffer* b,
+ uint32_t* offset);
+NET_EXPORT_PRIVATE bool SlowDecode(Http2GoAwayFields* out,
+ DecodeBuffer* b,
+ uint32_t* offset);
+NET_EXPORT_PRIVATE bool SlowDecode(Http2WindowUpdateFields* out,
+ DecodeBuffer* b,
+ uint32_t* offset);
+NET_EXPORT_PRIVATE bool SlowDecode(Http2AltSvcFields* out,
+ DecodeBuffer* b,
+ uint32_t* offset);
+
+} // namespace net
+
+#endif // NET_HTTP2_DECODER_DECODE_HTTP2_STRUCTURES_H_
diff --git a/chromium/net/http2/decoder/decode_http2_structures_test.cc b/chromium/net/http2/decoder/decode_http2_structures_test.cc
new file mode 100644
index 00000000000..0a76bdccc9c
--- /dev/null
+++ b/chromium/net/http2/decoder/decode_http2_structures_test.cc
@@ -0,0 +1,534 @@
+// Copyright 2016 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.
+
+#include "net/http2/decoder/decode_http2_structures.h"
+
+// Tests decoding all of the fixed size HTTP/2 structures (i.e. those defined
+// in net/http2/http2_structures.h).
+
+// TODO(jamessynge): Combine tests of DoDecode, MaybeDecode, SlowDecode and
+// Http2StructureDecoder test using gUnit's support for tests parameterized
+// by type.
+
+#include <stddef.h>
+#include <string>
+
+#include "base/logging.h"
+#include "base/strings/string_piece.h"
+#include "net/http2/decoder/decode_buffer.h"
+#include "net/http2/decoder/decode_status.h"
+#include "net/http2/http2_constants.h"
+#include "net/http2/http2_structures_test_util.h"
+#include "net/http2/tools/http2_frame_builder.h"
+#include "net/http2/tools/random_decoder_test.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+using ::testing::AssertionFailure;
+using ::testing::AssertionResult;
+using ::testing::AssertionSuccess;
+using base::StringPiece;
+using std::string;
+
+namespace net {
+namespace test {
+namespace {
+
+template <class S>
+string SerializeStructure(const S& s) {
+ Http2FrameBuilder fb;
+ fb.Append(s);
+ EXPECT_EQ(S::EncodedSize(), fb.size());
+ return fb.buffer();
+}
+
+template <class S>
+class StructureDecoderTest : public RandomDecoderTest {
+ protected:
+ typedef S Structure;
+
+ StructureDecoderTest() {
+ // IF the test adds more data after the encoded structure, stop as
+ // soon as the structure is decoded.
+ stop_decode_on_done_ = true;
+ }
+
+ // Reset the decoding to the start of the structure, and overwrite the
+ // current contents of |structure_|, in to which we'll decode the buffer.
+ DecodeStatus StartDecoding(DecodeBuffer* b) override {
+ decode_offset_ = 0;
+ Randomize(&structure_);
+ return ResumeDecoding(b);
+ }
+
+ DecodeStatus ResumeDecoding(DecodeBuffer* b) override {
+ // If we're at the start...
+ if (decode_offset_ == 0) {
+ const uint32_t start_offset = b->Offset();
+ const char* const start_cursor = b->cursor();
+ // ... attempt to decode the entire structure.
+ if (MaybeDecode(&structure_, b)) {
+ ++fast_decode_count_;
+ EXPECT_EQ(S::EncodedSize(), b->Offset() - start_offset);
+
+ if (!HasFailure()) {
+ // Success. Confirm that SlowDecode produces the same result.
+ DecodeBuffer b2(start_cursor, b->Offset() - start_offset);
+ S second;
+ Randomize(&second);
+ uint32_t second_offset = 0;
+ EXPECT_TRUE(SlowDecode(&second, &b2, &second_offset));
+ EXPECT_EQ(S::EncodedSize(), second_offset);
+ EXPECT_EQ(structure_, second);
+ }
+
+ // Test can't easily tell if MaybeDecode or SlowDecode is used, so
+ // update decode_offset_ as if SlowDecode had been used to completely
+ // decode.
+ decode_offset_ = S::EncodedSize();
+ return DecodeStatus::kDecodeDone;
+ }
+ }
+
+ // We didn't have enough in the first buffer to decode everything, so we'll
+ // reach here multiple times until we've completely decoded the structure.
+ if (SlowDecode(&structure_, b, &decode_offset_)) {
+ ++slow_decode_count_;
+ EXPECT_EQ(S::EncodedSize(), decode_offset_);
+ return DecodeStatus::kDecodeDone;
+ }
+
+ // Drained the input buffer, but not yet done.
+ EXPECT_TRUE(b->Empty());
+ EXPECT_GT(S::EncodedSize(), decode_offset_);
+
+ return DecodeStatus::kDecodeInProgress;
+ }
+
+ // Set the fields of |*p| to random values.
+ void Randomize(S* p) { ::net::test::Randomize(p, RandomPtr()); }
+
+ // Fully decodes the Structure at the start of data, and confirms it matches
+ // *expected (if provided).
+ void DecodeLeadingStructure(const S* expected, StringPiece data) {
+ ASSERT_LE(S::EncodedSize(), data.size());
+ DecodeBuffer original(data);
+
+ // The validator is called after each of the several times that the input
+ // DecodeBuffer is decoded, each with a different segmentation of the input.
+ // Validate that structure_ matches the expected value, if provided.
+ Validator validator = [expected, this](
+ const DecodeBuffer& db, DecodeStatus status) -> AssertionResult {
+ if (expected != nullptr && *expected != structure_) {
+ return AssertionFailure()
+ << "Expected structs to be equal\nExpected: " << *expected
+ << "\n Actual: " << structure_;
+ }
+ return AssertionSuccess();
+ };
+
+ // First validate that decoding is done and that we've advanced the cursor
+ // the expected amount.
+ validator = ValidateDoneAndOffset(S::EncodedSize(), validator);
+
+ // Decode several times, with several segmentations of the input buffer.
+ fast_decode_count_ = 0;
+ slow_decode_count_ = 0;
+ EXPECT_TRUE(DecodeAndValidateSeveralWays(
+ &original, false /*return_non_zero_on_first*/, validator));
+
+ if (!HasFailure()) {
+ EXPECT_EQ(S::EncodedSize(), decode_offset_);
+ EXPECT_EQ(S::EncodedSize(), original.Offset());
+ EXPECT_LT(0u, fast_decode_count_);
+ EXPECT_LT(0u, slow_decode_count_);
+ if (expected != nullptr) {
+ DVLOG(1) << "DecodeLeadingStructure expected: " << *expected;
+ DVLOG(1) << "DecodeLeadingStructure actual: " << structure_;
+ EXPECT_EQ(*expected, structure_);
+ }
+ }
+ }
+
+ template <size_t N>
+ void DecodeLeadingStructure(const char (&data)[N]) {
+ DecodeLeadingStructure(nullptr, StringPiece(data, N));
+ }
+
+ // Encode the structure |in_s| into bytes, then decode the bytes
+ // and validate that the decoder produced the same field values.
+ void EncodeThenDecode(const S& in_s) {
+ string bytes = SerializeStructure(in_s);
+ EXPECT_EQ(S::EncodedSize(), bytes.size());
+ DecodeLeadingStructure(&in_s, bytes);
+ }
+
+ // Generate
+ void TestDecodingRandomizedStructures(size_t count) {
+ for (size_t i = 0; i < count && !HasFailure(); ++i) {
+ Structure input;
+ Randomize(&input);
+ EncodeThenDecode(input);
+ }
+ }
+
+ uint32_t decode_offset_ = 0;
+ S structure_;
+ size_t fast_decode_count_ = 0;
+ size_t slow_decode_count_ = 0;
+};
+
+class FrameHeaderDecoderTest : public StructureDecoderTest<Http2FrameHeader> {};
+
+TEST_F(FrameHeaderDecoderTest, DecodesLiteral) {
+ {
+ // Realistic input.
+ const char kData[] = {
+ 0x00, 0x00, 0x05, // Payload length: 5
+ 0x01, // Frame type: HEADERS
+ 0x08, // Flags: PADDED
+ 0x00, 0x00, 0x00, 0x01, // Stream ID: 1
+ 0x04, // Padding length: 4
+ 0x00, 0x00, 0x00, 0x00, // Padding bytes
+ };
+ DecodeLeadingStructure(kData);
+ if (!HasFailure()) {
+ EXPECT_EQ(5u, structure_.payload_length);
+ EXPECT_EQ(Http2FrameType::HEADERS, structure_.type);
+ EXPECT_EQ(Http2FrameFlag::FLAG_PADDED, structure_.flags);
+ EXPECT_EQ(1u, structure_.stream_id);
+ }
+ }
+ {
+ // Unlikely input.
+ const char kData[] = {
+ 0xffu, 0xffu, 0xffu, // Payload length: uint24 max
+ 0xffu, // Frame type: Unknown
+ 0xffu, // Flags: Unknown/All
+ 0xffu, 0xffu, 0xffu, 0xffu, // Stream ID: uint31 max, plus R-bit
+ };
+ DecodeLeadingStructure(kData);
+ if (!HasFailure()) {
+ EXPECT_EQ((1u << 24) - 1, structure_.payload_length);
+ EXPECT_EQ(static_cast<Http2FrameType>(255), structure_.type);
+ EXPECT_EQ(255, structure_.flags);
+ EXPECT_EQ(0x7FFFFFFFu, structure_.stream_id);
+ }
+ }
+}
+
+TEST_F(FrameHeaderDecoderTest, DecodesRandomized) {
+ TestDecodingRandomizedStructures(100);
+}
+
+//------------------------------------------------------------------------------
+
+class PriorityFieldsDecoderTest
+ : public StructureDecoderTest<Http2PriorityFields> {};
+
+TEST_F(PriorityFieldsDecoderTest, DecodesLiteral) {
+ {
+ const char kData[] = {
+ 0x80u, 0x00, 0x00, 0x05, // Exclusive (yes) and Dependency (5)
+ 0xffu, // Weight: 256 (after adding 1)
+ };
+ DecodeLeadingStructure(kData);
+ if (!HasFailure()) {
+ EXPECT_EQ(5u, structure_.stream_dependency);
+ EXPECT_EQ(256u, structure_.weight);
+ EXPECT_EQ(true, structure_.is_exclusive);
+ }
+ }
+ {
+ const char kData[] = {
+ 0x7f, 0xffu,
+ 0xffu, 0xffu, // Exclusive (no) and Dependency (0x7fffffff)
+ 0x00, // Weight: 1 (after adding 1)
+ };
+ DecodeLeadingStructure(kData);
+ if (!HasFailure()) {
+ EXPECT_EQ(StreamIdMask(), structure_.stream_dependency);
+ EXPECT_EQ(1u, structure_.weight);
+ EXPECT_FALSE(structure_.is_exclusive);
+ }
+ }
+}
+
+TEST_F(PriorityFieldsDecoderTest, DecodesRandomized) {
+ TestDecodingRandomizedStructures(100);
+}
+
+//------------------------------------------------------------------------------
+
+class RstStreamFieldsDecoderTest
+ : public StructureDecoderTest<Http2RstStreamFields> {};
+
+TEST_F(RstStreamFieldsDecoderTest, DecodesLiteral) {
+ {
+ const char kData[] = {
+ 0x00, 0x00, 0x00, 0x01, // Error: PROTOCOL_ERROR
+ };
+ DecodeLeadingStructure(kData);
+ if (!HasFailure()) {
+ EXPECT_TRUE(structure_.IsSupportedErrorCode());
+ EXPECT_EQ(Http2ErrorCode::PROTOCOL_ERROR, structure_.error_code);
+ }
+ }
+ {
+ const char kData[] = {
+ 0xffu, 0xffu, 0xffu, 0xffu, // Error: max uint32 (Unknown error code)
+ };
+ DecodeLeadingStructure(kData);
+ if (!HasFailure()) {
+ EXPECT_FALSE(structure_.IsSupportedErrorCode());
+ EXPECT_EQ(static_cast<Http2ErrorCode>(0xffffffff), structure_.error_code);
+ }
+ }
+}
+
+TEST_F(RstStreamFieldsDecoderTest, DecodesRandomized) {
+ TestDecodingRandomizedStructures(100);
+}
+
+//------------------------------------------------------------------------------
+
+class SettingFieldsDecoderTest
+ : public StructureDecoderTest<Http2SettingFields> {};
+
+TEST_F(SettingFieldsDecoderTest, DecodesLiteral) {
+ {
+ const char kData[] = {
+ 0x00, 0x01, // Setting: HEADER_TABLE_SIZE
+ 0x00, 0x00, 0x40, 0x00, // Value: 16K
+ };
+ DecodeLeadingStructure(kData);
+ if (!HasFailure()) {
+ EXPECT_TRUE(structure_.IsSupportedParameter());
+ EXPECT_EQ(Http2SettingsParameter::HEADER_TABLE_SIZE,
+ structure_.parameter);
+ EXPECT_EQ(1u << 14, structure_.value);
+ }
+ }
+ {
+ const char kData[] = {
+ 0x00, 0x00, // Setting: Unknown (0)
+ 0xffu, 0xffu, 0xffu, 0xffu, // Value: max uint32
+ };
+ DecodeLeadingStructure(kData);
+ if (!HasFailure()) {
+ EXPECT_FALSE(structure_.IsSupportedParameter());
+ EXPECT_EQ(static_cast<Http2SettingsParameter>(0), structure_.parameter);
+ }
+ }
+}
+
+TEST_F(SettingFieldsDecoderTest, DecodesRandomized) {
+ TestDecodingRandomizedStructures(100);
+}
+
+//------------------------------------------------------------------------------
+
+class PushPromiseFieldsDecoderTest
+ : public StructureDecoderTest<Http2PushPromiseFields> {};
+
+TEST_F(PushPromiseFieldsDecoderTest, DecodesLiteral) {
+ {
+ const char kData[] = {
+ 0x00, 0x01, 0x8au, 0x92u, // Promised Stream ID: 101010
+ };
+ DecodeLeadingStructure(kData);
+ if (!HasFailure()) {
+ EXPECT_EQ(101010u, structure_.promised_stream_id);
+ }
+ }
+ {
+ // Promised stream id has R-bit (reserved for future use) set, which
+ // should be cleared by the decoder.
+ const char kData[] = {
+ 0xffu, 0xffu, 0xffu, 0xffu, // Promised Stream ID: max uint31 and R-bit
+ };
+ DecodeLeadingStructure(kData);
+ if (!HasFailure()) {
+ EXPECT_EQ(StreamIdMask(), structure_.promised_stream_id);
+ }
+ }
+}
+
+TEST_F(PushPromiseFieldsDecoderTest, DecodesRandomized) {
+ TestDecodingRandomizedStructures(100);
+}
+
+//------------------------------------------------------------------------------
+
+class PingFieldsDecoderTest : public StructureDecoderTest<Http2PingFields> {};
+
+TEST_F(PingFieldsDecoderTest, DecodesLiteral) {
+ {
+ // Each byte is different, so can detect if order changed.
+ const char kData[] = {
+ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+ };
+ DecodeLeadingStructure(kData);
+ if (!HasFailure()) {
+ EXPECT_EQ(StringPiece(kData, 8), ToStringPiece(structure_.opaque_data));
+ }
+ }
+ {
+ // All zeros, detect problems handling NULs.
+ const char kData[] = {
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ };
+ DecodeLeadingStructure(kData);
+ if (!HasFailure()) {
+ EXPECT_EQ(StringPiece(kData, 8), ToStringPiece(structure_.opaque_data));
+ }
+ }
+ {
+ const char kData[] = {
+ 0xffu, 0xffu, 0xffu, 0xffu, 0xffu, 0xffu, 0xffu, 0xffu,
+ };
+ DecodeLeadingStructure(kData);
+ if (!HasFailure()) {
+ EXPECT_EQ(StringPiece(kData, 8), ToStringPiece(structure_.opaque_data));
+ }
+ }
+}
+
+TEST_F(PingFieldsDecoderTest, DecodesRandomized) {
+ TestDecodingRandomizedStructures(100);
+}
+
+//------------------------------------------------------------------------------
+
+class GoAwayFieldsDecoderTest : public StructureDecoderTest<Http2GoAwayFields> {
+};
+
+TEST_F(GoAwayFieldsDecoderTest, DecodesLiteral) {
+ {
+ const char kData[] = {
+ 0x00, 0x00, 0x00, 0x00, // Last Stream ID: 0
+ 0x00, 0x00, 0x00, 0x00, // Error: NO_ERROR (0)
+ };
+ DecodeLeadingStructure(kData);
+ if (!HasFailure()) {
+ EXPECT_EQ(0u, structure_.last_stream_id);
+ EXPECT_TRUE(structure_.IsSupportedErrorCode());
+ EXPECT_EQ(Http2ErrorCode::HTTP2_NO_ERROR, structure_.error_code);
+ }
+ }
+ {
+ const char kData[] = {
+ 0x00, 0x00, 0x00, 0x01, // Last Stream ID: 1
+ 0x00, 0x00, 0x00, 0x0d, // Error: HTTP_1_1_REQUIRED
+ };
+ DecodeLeadingStructure(kData);
+ if (!HasFailure()) {
+ EXPECT_EQ(1u, structure_.last_stream_id);
+ EXPECT_TRUE(structure_.IsSupportedErrorCode());
+ EXPECT_EQ(Http2ErrorCode::HTTP_1_1_REQUIRED, structure_.error_code);
+ }
+ }
+ {
+ const char kData[] = {
+ 0xffu, 0xffu, 0xffu, 0xffu, // Last Stream ID: max uint31 and R-bit
+ 0xffu, 0xffu, 0xffu, 0xffu, // Error: max uint32 (Unknown error code)
+ };
+ DecodeLeadingStructure(kData);
+ if (!HasFailure()) {
+ EXPECT_EQ(StreamIdMask(), structure_.last_stream_id); // No high-bit.
+ EXPECT_FALSE(structure_.IsSupportedErrorCode());
+ EXPECT_EQ(static_cast<Http2ErrorCode>(0xffffffff), structure_.error_code);
+ }
+ }
+}
+
+TEST_F(GoAwayFieldsDecoderTest, DecodesRandomized) {
+ TestDecodingRandomizedStructures(100);
+}
+
+//------------------------------------------------------------------------------
+
+class WindowUpdateFieldsDecoderTest
+ : public StructureDecoderTest<Http2WindowUpdateFields> {};
+
+TEST_F(WindowUpdateFieldsDecoderTest, DecodesLiteral) {
+ {
+ const char kData[] = {
+ 0x00, 0x01, 0x00, 0x00, // Window Size Increment: 2 ^ 16
+ };
+ DecodeLeadingStructure(kData);
+ if (!HasFailure()) {
+ EXPECT_EQ(1u << 16, structure_.window_size_increment);
+ }
+ }
+ {
+ // Increment must be non-zero, but we need to be able to decode the invalid
+ // zero to detect it.
+ const char kData[] = {
+ 0x00, 0x00, 0x00, 0x00, // Window Size Increment: 0
+ };
+ DecodeLeadingStructure(kData);
+ if (!HasFailure()) {
+ EXPECT_EQ(0u, structure_.window_size_increment);
+ }
+ }
+ {
+ // Increment has R-bit (reserved for future use) set, which
+ // should be cleared by the decoder.
+ const char kData[] = {
+ 0xffu, 0xffu, 0xffu,
+ 0xffu, // Window Size Increment: max uint31 and R-bit
+ };
+ DecodeLeadingStructure(kData);
+ if (!HasFailure()) {
+ EXPECT_EQ(StreamIdMask(), structure_.window_size_increment);
+ }
+ }
+}
+
+TEST_F(WindowUpdateFieldsDecoderTest, DecodesRandomized) {
+ TestDecodingRandomizedStructures(100);
+}
+
+//------------------------------------------------------------------------------
+
+class AltSvcFieldsDecoderTest : public StructureDecoderTest<Http2AltSvcFields> {
+};
+
+TEST_F(AltSvcFieldsDecoderTest, DecodesLiteral) {
+ {
+ const char kData[] = {
+ 0x00, 0x00, // Origin Length: 0
+ };
+ DecodeLeadingStructure(kData);
+ if (!HasFailure()) {
+ EXPECT_EQ(0, structure_.origin_length);
+ }
+ }
+ {
+ const char kData[] = {
+ 0x00, 0x14, // Origin Length: 20
+ };
+ DecodeLeadingStructure(kData);
+ if (!HasFailure()) {
+ EXPECT_EQ(20, structure_.origin_length);
+ }
+ }
+ {
+ const char kData[] = {
+ 0xffu, 0xffu, // Origin Length: uint16 max
+ };
+ DecodeLeadingStructure(kData);
+ if (!HasFailure()) {
+ EXPECT_EQ(65535, structure_.origin_length);
+ }
+ }
+}
+
+TEST_F(AltSvcFieldsDecoderTest, DecodesRandomized) {
+ TestDecodingRandomizedStructures(100);
+}
+
+} // namespace
+} // namespace test
+} // namespace net
diff --git a/chromium/net/http2/decoder/decode_status.cc b/chromium/net/http2/decoder/decode_status.cc
new file mode 100644
index 00000000000..99a1de0b505
--- /dev/null
+++ b/chromium/net/http2/decoder/decode_status.cc
@@ -0,0 +1,27 @@
+// Copyright 2016 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.
+
+#include "net/http2/decoder/decode_status.h"
+
+#include "base/logging.h"
+
+namespace net {
+
+std::ostream& operator<<(std::ostream& out, DecodeStatus v) {
+ switch (v) {
+ case DecodeStatus::kDecodeDone:
+ return out << "DecodeDone";
+ case DecodeStatus::kDecodeInProgress:
+ return out << "DecodeInProgress";
+ case DecodeStatus::kDecodeError:
+ return out << "DecodeError";
+ }
+ // Since the value doesn't come over the wire, only a programming bug should
+ // result in reaching this point.
+ int unknown = static_cast<int>(v);
+ LOG(DFATAL) << "Unknown DecodeStatus " << unknown << std::hex << unknown;
+ return out << "UnknownDecodeStatus(" << unknown << ")";
+}
+
+} // namespace net
diff --git a/chromium/net/http2/decoder/decode_status.h b/chromium/net/http2/decoder/decode_status.h
new file mode 100644
index 00000000000..e5fbeebc57c
--- /dev/null
+++ b/chromium/net/http2/decoder/decode_status.h
@@ -0,0 +1,32 @@
+// Copyright 2016 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.
+
+#ifndef NET_HTTP2_DECODER_DECODE_STATUS_H_
+#define NET_HTTP2_DECODER_DECODE_STATUS_H_
+
+// Enum DecodeStatus is used to report the status of decoding of many
+// types of HTTP/2 and HPACK objects.
+
+#include <ostream>
+
+#include "net/base/net_export.h"
+
+namespace net {
+
+enum class DecodeStatus {
+ // Decoding is done.
+ kDecodeDone,
+
+ // Decoder needs more input to be able to make progress.
+ kDecodeInProgress,
+
+ // Decoding failed (e.g. HPACK variable length integer is too large, or
+ // an HTTP/2 frame has padding declared to be larger than the payload).
+ kDecodeError,
+};
+NET_EXPORT_PRIVATE std::ostream& operator<<(std::ostream& out, DecodeStatus v);
+
+} // namespace net
+
+#endif // NET_HTTP2_DECODER_DECODE_STATUS_H_
diff --git a/chromium/net/http2/decoder/frame_decoder_state.cc b/chromium/net/http2/decoder/frame_decoder_state.cc
new file mode 100644
index 00000000000..e2b44066056
--- /dev/null
+++ b/chromium/net/http2/decoder/frame_decoder_state.cc
@@ -0,0 +1,81 @@
+// Copyright 2016 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.
+
+#include "net/http2/decoder/frame_decoder_state.h"
+
+namespace net {
+
+DecodeStatus FrameDecoderState::ReadPadLength(DecodeBuffer* db,
+ bool report_pad_length) {
+ DVLOG(2) << "ReadPadLength db->Remaining=" << db->Remaining()
+ << "; payload_length=" << frame_header().payload_length;
+ DCHECK(IsPaddable());
+ DCHECK(frame_header().IsPadded());
+
+ // Pad Length is always at the start of the frame, so remaining_payload_
+ // should equal payload_length at this point.
+ const uint32_t total_payload = frame_header().payload_length;
+ DCHECK_EQ(total_payload, remaining_payload_);
+ DCHECK_EQ(0u, remaining_padding_);
+
+ if (db->HasData()) {
+ const uint32_t pad_length = db->DecodeUInt8();
+ const uint32_t total_padding = pad_length + 1;
+ if (total_padding <= total_payload) {
+ remaining_padding_ = pad_length;
+ remaining_payload_ = total_payload - total_padding;
+ if (report_pad_length) {
+ listener()->OnPadLength(pad_length);
+ }
+ return DecodeStatus::kDecodeDone;
+ }
+ const uint32_t missing_length = total_padding - total_payload;
+ // To allow for the possibility of recovery, record the number of
+ // remaining bytes of the frame's payload (invalid though it is)
+ // in remaining_payload_.
+ remaining_payload_ = total_payload - 1; // 1 for sizeof(Pad Length).
+ remaining_padding_ = 0;
+ listener()->OnPaddingTooLong(frame_header(), missing_length);
+ return DecodeStatus::kDecodeError;
+ }
+
+ if (total_payload == 0) {
+ remaining_payload_ = 0;
+ remaining_padding_ = 0;
+ listener()->OnPaddingTooLong(frame_header(), 1);
+ return DecodeStatus::kDecodeError;
+ }
+ // Need to wait for another buffer.
+ return DecodeStatus::kDecodeInProgress;
+}
+
+bool FrameDecoderState::SkipPadding(DecodeBuffer* db) {
+ DVLOG(2) << "SkipPadding remaining_padding_=" << remaining_padding_
+ << ", db->Remaining=" << db->Remaining()
+ << ", header: " << frame_header();
+ DCHECK_EQ(remaining_payload_, 0u);
+ DCHECK(IsPaddable()) << "header: " << frame_header();
+ DCHECK_GE(remaining_padding_, 0u);
+ DCHECK(remaining_padding_ == 0 || frame_header().IsPadded())
+ << "remaining_padding_=" << remaining_padding_
+ << ", header: " << frame_header();
+ const size_t avail = AvailablePadding(db);
+ if (avail > 0) {
+ listener()->OnPadding(db->cursor(), avail);
+ db->AdvanceCursor(avail);
+ remaining_padding_ -= avail;
+ }
+ return remaining_padding_ == 0;
+}
+
+DecodeStatus FrameDecoderState::ReportFrameSizeError() {
+ DVLOG(2) << "FrameDecoderState::ReportFrameSizeError: "
+ << " remaining_payload_=" << remaining_payload_
+ << "; remaining_padding_=" << remaining_padding_
+ << ", header: " << frame_header();
+ listener()->OnFrameSizeError(frame_header());
+ return DecodeStatus::kDecodeError;
+}
+
+} // namespace net
diff --git a/chromium/net/http2/decoder/frame_decoder_state.h b/chromium/net/http2/decoder/frame_decoder_state.h
new file mode 100644
index 00000000000..ddf64d1f3a1
--- /dev/null
+++ b/chromium/net/http2/decoder/frame_decoder_state.h
@@ -0,0 +1,252 @@
+// Copyright 2016 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.
+
+#ifndef NET_HTTP2_DECODER_FRAME_DECODER_STATE_H_
+#define NET_HTTP2_DECODER_FRAME_DECODER_STATE_H_
+
+// FrameDecoderState provides state and behaviors in support of decoding
+// the common frame header and the payload of all frame types.
+// It is an input to all of the payload decoders.
+
+// TODO(jamessynge): Since FrameDecoderState has far more than state in it,
+// rename to FrameDecoderHelper, or similar.
+
+#include <stddef.h>
+
+#include "base/logging.h"
+#include "net/base/net_export.h"
+#include "net/http2/decoder/decode_buffer.h"
+#include "net/http2/decoder/decode_status.h"
+#include "net/http2/decoder/http2_frame_decoder_listener.h"
+#include "net/http2/decoder/http2_structure_decoder.h"
+#include "net/http2/http2_constants.h"
+#include "net/http2/http2_structures.h"
+
+namespace net {
+namespace test {
+class FrameDecoderStatePeer;
+} // namespace test
+
+class NET_EXPORT_PRIVATE FrameDecoderState {
+ public:
+ FrameDecoderState() {}
+
+ // Sets the listener which the decoders should call as they decode HTTP/2
+ // frames. The listener can be changed at any time, which allows for replacing
+ // it with a no-op listener when an error is detected, either by the payload
+ // decoder (OnPaddingTooLong or OnFrameSizeError) or by the "real" listener.
+ // That in turn allows us to define Http2FrameDecoderListener such that all
+ // methods have return type void, with no direct way to indicate whether the
+ // decoder should stop, and to eliminate from the decoder all checks of the
+ // return value. Instead the listener/caller can simply replace the current
+ // listener with a no-op listener implementation.
+ // TODO(jamessynge): Make set_listener private as only Http2FrameDecoder
+ // and tests need to set it, so it doesn't need to be public.
+ void set_listener(Http2FrameDecoderListener* listener) {
+ listener_ = listener;
+ }
+ Http2FrameDecoderListener* listener() const { return listener_; }
+
+ // The most recently decoded frame header.
+ const Http2FrameHeader& frame_header() const { return frame_header_; }
+
+ // Decode a structure in the payload, adjusting remaining_payload_ to account
+ // for the consumed portion of the payload. Returns kDecodeDone when fully
+ // decoded, kDecodeError if it ran out of payload before decoding completed,
+ // and kDecodeInProgress if the decode buffer didn't have enough of the
+ // remaining payload.
+ template <class S>
+ DecodeStatus StartDecodingStructureInPayload(S* out, DecodeBuffer* db) {
+ DVLOG(2) << __func__ << "\n\tdb->Remaining=" << db->Remaining()
+ << "\n\tremaining_payload_=" << remaining_payload_
+ << "\n\tneed=" << S::EncodedSize();
+ DecodeStatus status =
+ structure_decoder_.Start(out, db, &remaining_payload_);
+ if (status != DecodeStatus::kDecodeError) {
+ return status;
+ }
+ DVLOG(2) << "StartDecodingStructureInPayload: detected frame size error";
+ return ReportFrameSizeError();
+ }
+
+ // Resume decoding of a structure that has been split across buffers,
+ // adjusting remaining_payload_ to account for the consumed portion of
+ // the payload. Returns values are as for StartDecodingStructureInPayload.
+ template <class S>
+ DecodeStatus ResumeDecodingStructureInPayload(S* out, DecodeBuffer* db) {
+ DVLOG(2) << __func__ << "\n\tdb->Remaining=" << db->Remaining()
+ << "\n\tremaining_payload_=" << remaining_payload_;
+ if (structure_decoder_.Resume(out, db, &remaining_payload_)) {
+ return DecodeStatus::kDecodeDone;
+ } else if (remaining_payload_ > 0) {
+ return DecodeStatus::kDecodeInProgress;
+ } else {
+ DVLOG(2) << "ResumeDecodingStructureInPayload: detected frame size error";
+ return ReportFrameSizeError();
+ }
+ }
+
+ // Initializes the two remaining* fields, which is needed if the frame's
+ // payload is split across buffers, or the decoder calls ReadPadLength or
+ // StartDecodingStructureInPayload, and of course the methods below which
+ // read those fields, as their names imply.
+ void InitializeRemainders() {
+ remaining_payload_ = frame_header().payload_length;
+ // Note that remaining_total_payload() relies on remaining_padding_ being
+ // zero for frames that have no padding.
+ remaining_padding_ = 0;
+ }
+
+ // Returns the number of bytes of the frame's payload that remain to be
+ // decoded, including any trailing padding. This method must only be called
+ // after the variables have been initialized, which in practice means once a
+ // payload decoder has called InitializeRemainders and/or ReadPadLength.
+ size_t remaining_total_payload() const {
+ DCHECK(IsPaddable() || remaining_padding_ == 0) << frame_header();
+ return remaining_payload_ + remaining_padding_;
+ }
+
+ // Returns the number of bytes of the frame's payload that remain to be
+ // decoded, excluding any trailing padding. This method must only be called
+ // after the variable has been initialized, which in practice means once a
+ // payload decoder has called InitializeRemainders; ReadPadLength will deduct
+ // the total number of padding bytes from remaining_payload_, including the
+ // size of the Pad Length field itself (1 byte).
+ size_t remaining_payload() const { return remaining_payload_; }
+
+ // Returns the number of bytes of the frame's payload that remain to be
+ // decoded, including any trailing padding. This method must only be called if
+ // the frame type allows padding, and after the variable has been initialized,
+ // which in practice means once a payload decoder has called
+ // InitializeRemainders and/or ReadPadLength.
+ size_t remaining_payload_and_padding() const {
+ DCHECK(IsPaddable()) << frame_header();
+ return remaining_payload_ + remaining_padding_;
+ }
+
+ // Returns the number of bytes of trailing padding after the payload that
+ // remain to be decoded. This method must only be called if the frame type
+ // allows padding, and after the variable has been initialized, which in
+ // practice means once a payload decoder has called InitializeRemainders,
+ // and isn't set to a non-zero value until ReadPadLength has been called.
+ uint32_t remaining_padding() const {
+ DCHECK(IsPaddable()) << frame_header();
+ return remaining_padding_;
+ }
+
+ // Returns the amount of trailing padding after the payload that remains to be
+ // decoded.
+ uint32_t remaining_padding_for_test() const { return remaining_padding_; }
+
+ // How many bytes of the remaining payload are in db?
+ size_t AvailablePayload(DecodeBuffer* db) const {
+ return db->MinLengthRemaining(remaining_payload_);
+ }
+
+ // How many bytes of the remaining payload and padding are in db?
+ // Call only for frames whose type is paddable.
+ size_t AvailablePayloadAndPadding(DecodeBuffer* db) const {
+ DCHECK(IsPaddable()) << frame_header();
+ return db->MinLengthRemaining(remaining_payload_ + remaining_padding_);
+ }
+
+ // How many bytes of the padding that have not yet been skipped are in db?
+ // Call only after remaining_padding_ has been set (for padded frames), or
+ // been cleared (for unpadded frames); and after all of the non-padding
+ // payload has been decoded.
+ size_t AvailablePadding(DecodeBuffer* db) const {
+ DCHECK(IsPaddable()) << frame_header();
+ DCHECK_EQ(remaining_payload_, 0u);
+ return db->MinLengthRemaining(remaining_padding_);
+ }
+
+ // Reduces remaining_payload_ by amount. To be called by a payload decoder
+ // after it has passed a variable length portion of the payload to the
+ // listener; remaining_payload_ will be automatically reduced when fixed
+ // size structures and padding, including the Pad Length field, are decoded.
+ void ConsumePayload(size_t amount) {
+ DCHECK_LE(amount, remaining_payload_);
+ remaining_payload_ -= amount;
+ }
+
+ // Reads the Pad Length field into remaining_padding_, and appropriately sets
+ // remaining_payload_. When present, the Pad Length field is always the first
+ // field in the payload, which this method relies on so that the caller need
+ // not set remaining_payload_ before calling this method.
+ // If report_pad_length is true, calls the listener's OnPadLength method when
+ // it decodes the Pad Length field.
+ // Returns kDecodeDone if the decode buffer was not empty (i.e. because the
+ // field is only a single byte long, it can always be decoded if the buffer is
+ // not empty).
+ // Returns kDecodeError if the buffer is empty because the frame has no
+ // payload (i.e. payload_length() == 0).
+ // Returns kDecodeInProgress if the buffer is empty but the frame has a
+ // payload.
+ DecodeStatus ReadPadLength(DecodeBuffer* db, bool report_pad_length);
+
+ // Skip the trailing padding bytes; only call once remaining_payload_==0.
+ // Returns true when the padding has been skipped.
+ // Does NOT check that the padding is all zeroes.
+ bool SkipPadding(DecodeBuffer* db);
+
+ // Calls the listener's OnFrameSizeError method and returns kDecodeError.
+ DecodeStatus ReportFrameSizeError();
+
+ private:
+ friend class Http2FrameDecoder;
+ friend class test::FrameDecoderStatePeer;
+
+ // Starts the decoding of a common frame header. Returns true if completed the
+ // decoding, false if the decode buffer didn't have enough data in it, in
+ // which case the decode buffer will have been drained and the caller should
+ // call ResumeDecodingFrameHeader when more data is available. This is called
+ // from Http2FrameDecoder, a friend class.
+ bool StartDecodingFrameHeader(DecodeBuffer* db) {
+ return structure_decoder_.Start(&frame_header_, db);
+ }
+
+ // Resumes decoding the common frame header after the preceding call to
+ // StartDecodingFrameHeader returned false, as did any subsequent calls to
+ // ResumeDecodingFrameHeader. This is called from Http2FrameDecoder,
+ // a friend class.
+ bool ResumeDecodingFrameHeader(DecodeBuffer* db) {
+ return structure_decoder_.Resume(&frame_header_, db);
+ }
+
+ // Clear any of the flags in the frame header that aren't set in valid_flags.
+ void RetainFlags(uint8_t valid_flags) {
+ frame_header_.RetainFlags(valid_flags);
+ }
+
+ // Clear all of the flags in the frame header; for use with frame types that
+ // don't define any flags, such as WINDOW_UPDATE.
+ void ClearFlags() { frame_header_.flags = Http2FrameFlag(); }
+
+ // Returns true if the type of frame being decoded can have padding.
+ bool IsPaddable() const {
+ return frame_header().type == Http2FrameType::DATA ||
+ frame_header().type == Http2FrameType::HEADERS ||
+ frame_header().type == Http2FrameType::PUSH_PROMISE;
+ }
+
+ Http2FrameDecoderListener* listener_ = nullptr;
+ Http2FrameHeader frame_header_;
+
+ // Number of bytes remaining to be decoded, if set; does not include the
+ // trailing padding once the length of padding has been determined.
+ // See ReadPadLength.
+ uint32_t remaining_payload_;
+
+ // The amount of trailing padding after the payload that remains to be
+ // decoded. See ReadPadLength.
+ uint32_t remaining_padding_;
+
+ // Generic decoder of structures, which takes care of buffering the needed
+ // bytes if the encoded structure is split across decode buffers.
+ Http2StructureDecoder structure_decoder_;
+};
+
+} // namespace net
+
+#endif // NET_HTTP2_DECODER_FRAME_DECODER_STATE_H_
diff --git a/chromium/net/http2/decoder/frame_decoder_state_test_util.cc b/chromium/net/http2/decoder/frame_decoder_state_test_util.cc
new file mode 100644
index 00000000000..5988b8c2c9b
--- /dev/null
+++ b/chromium/net/http2/decoder/frame_decoder_state_test_util.cc
@@ -0,0 +1,34 @@
+// Copyright 2016 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.
+
+#include "net/http2/decoder/frame_decoder_state_test_util.h"
+
+#include "base/logging.h"
+#include "net/http2/decoder/http2_structure_decoder_test_util.h"
+#include "net/http2/http2_structures.h"
+#include "net/http2/http2_structures_test_util.h"
+#include "net/http2/tools/http2_random.h"
+#include "net/http2/tools/random_decoder_test.h"
+
+namespace net {
+namespace test {
+
+// static
+void FrameDecoderStatePeer::Randomize(FrameDecoderState* p, RandomBase* rng) {
+ VLOG(1) << "FrameDecoderStatePeer::Randomize";
+ ::net::test::Randomize(&p->frame_header_, rng);
+ p->remaining_payload_ = rng->Rand32();
+ p->remaining_padding_ = rng->Rand32();
+ Http2StructureDecoderPeer::Randomize(&p->structure_decoder_, rng);
+}
+
+// static
+void FrameDecoderStatePeer::set_frame_header(const Http2FrameHeader& header,
+ FrameDecoderState* p) {
+ VLOG(1) << "FrameDecoderStatePeer::set_frame_header " << header;
+ p->frame_header_ = header;
+}
+
+} // namespace test
+} // namespace net
diff --git a/chromium/net/http2/decoder/frame_decoder_state_test_util.h b/chromium/net/http2/decoder/frame_decoder_state_test_util.h
new file mode 100644
index 00000000000..e32a401101c
--- /dev/null
+++ b/chromium/net/http2/decoder/frame_decoder_state_test_util.h
@@ -0,0 +1,36 @@
+// Copyright 2016 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.
+
+#ifndef NET_HTTP2_DECODER_FRAME_DECODER_STATE_TEST_UTIL_H_
+#define NET_HTTP2_DECODER_FRAME_DECODER_STATE_TEST_UTIL_H_
+
+#include "net/http2/decoder/frame_decoder_state.h"
+#include "net/http2/http2_structures.h"
+#include "net/http2/tools/random_decoder_test.h"
+
+namespace net {
+namespace test {
+
+class FrameDecoderStatePeer {
+ public:
+ // Randomizes (i.e. corrupts) the fields of the FrameDecoderState.
+ // PayloadDecoderBaseTest::StartDecoding calls this before passing the first
+ // decode buffer to the payload decoder, which increases the likelihood of
+ // detecting any use of prior states of the decoder on the decoding of
+ // future payloads.
+ static void Randomize(FrameDecoderState* p, RandomBase* rng);
+
+ // Inject a frame header into the FrameDecoderState.
+ // PayloadDecoderBaseTest::StartDecoding calls this just after calling
+ // Randomize (above), to simulate a full frame decoder having just finished
+ // decoding the common frame header and then calling the appropriate payload
+ // decoder based on the frame type in that frame header.
+ static void set_frame_header(const Http2FrameHeader& header,
+ FrameDecoderState* p);
+};
+
+} // namespace test
+} // namespace net
+
+#endif // NET_HTTP2_DECODER_FRAME_DECODER_STATE_TEST_UTIL_H_
diff --git a/chromium/net/http2/decoder/frame_parts.cc b/chromium/net/http2/decoder/frame_parts.cc
new file mode 100644
index 00000000000..33cd7bfd788
--- /dev/null
+++ b/chromium/net/http2/decoder/frame_parts.cc
@@ -0,0 +1,527 @@
+// Copyright 2016 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.
+
+#include "net/http2/decoder/frame_parts.h"
+
+#include <type_traits>
+
+#include "base/logging.h"
+#include "net/base/escape.h"
+#include "net/http2/http2_structures_test_util.h"
+#include "net/http2/tools/failure.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+using base::StringPiece;
+using std::string;
+using ::testing::AssertionFailure;
+using ::testing::AssertionResult;
+using ::testing::AssertionSuccess;
+using ::testing::ContainerEq;
+
+namespace net {
+namespace test {
+namespace {
+
+static_assert(std::is_base_of<Http2FrameDecoderListener, FrameParts>::value &&
+ !std::is_abstract<FrameParts>::value,
+ "FrameParts needs to implement all of the methods of "
+ "Http2FrameDecoderListener");
+
+// Compare two optional variables of the same type.
+// TODO(jamessynge): Maybe create a ::testing::Matcher for this.
+template <class T>
+AssertionResult VerifyOptionalEq(const T& opt_a, const T& opt_b) {
+ if (opt_a) {
+ if (opt_b) {
+ VERIFY_EQ(opt_a.value(), opt_b.value());
+ } else {
+ return AssertionFailure() << "opt_b is not set; opt_a.value()="
+ << opt_a.value();
+ }
+ } else if (opt_b) {
+ return AssertionFailure() << "opt_a is not set; opt_b.value()="
+ << opt_b.value();
+ }
+ return AssertionSuccess();
+}
+
+} // namespace
+
+FrameParts::FrameParts(const Http2FrameHeader& header) : frame_header(header) {
+ VLOG(1) << "FrameParts, header: " << frame_header;
+}
+
+FrameParts::FrameParts(const Http2FrameHeader& header, StringPiece payload)
+ : FrameParts(header) {
+ VLOG(1) << "FrameParts with payload.size() = " << payload.size();
+ payload.AppendToString(&this->payload);
+ opt_payload_length = payload.size();
+}
+FrameParts::FrameParts(const Http2FrameHeader& header,
+ StringPiece payload,
+ size_t total_pad_length)
+ : FrameParts(header, payload) {
+ VLOG(1) << "FrameParts with total_pad_length=" << total_pad_length;
+ SetTotalPadLength(total_pad_length);
+}
+
+FrameParts::FrameParts(const FrameParts& other) = default;
+
+FrameParts::~FrameParts() {}
+
+AssertionResult FrameParts::VerifyEquals(const FrameParts& that) const {
+#define COMMON_MESSAGE "\n this: " << *this << "\n that: " << that
+
+ VERIFY_EQ(frame_header, that.frame_header) << COMMON_MESSAGE;
+ VERIFY_EQ(payload, that.payload) << COMMON_MESSAGE;
+ VERIFY_EQ(padding, that.padding) << COMMON_MESSAGE;
+ VERIFY_EQ(altsvc_origin, that.altsvc_origin) << COMMON_MESSAGE;
+ VERIFY_EQ(altsvc_value, that.altsvc_value) << COMMON_MESSAGE;
+ VERIFY_EQ(settings, that.settings) << COMMON_MESSAGE;
+
+#define VERIFY_OPTIONAL_FIELD(field_name) \
+ VERIFY_SUCCESS(VerifyOptionalEq(field_name, that.field_name))
+
+ VERIFY_OPTIONAL_FIELD(opt_altsvc_origin_length) << COMMON_MESSAGE;
+ VERIFY_OPTIONAL_FIELD(opt_altsvc_value_length) << COMMON_MESSAGE;
+ VERIFY_OPTIONAL_FIELD(opt_goaway) << COMMON_MESSAGE;
+ VERIFY_OPTIONAL_FIELD(opt_missing_length) << COMMON_MESSAGE;
+ VERIFY_OPTIONAL_FIELD(opt_pad_length) << COMMON_MESSAGE;
+ VERIFY_OPTIONAL_FIELD(opt_ping) << COMMON_MESSAGE;
+ VERIFY_OPTIONAL_FIELD(opt_priority) << COMMON_MESSAGE;
+ VERIFY_OPTIONAL_FIELD(opt_push_promise) << COMMON_MESSAGE;
+ VERIFY_OPTIONAL_FIELD(opt_rst_stream_error_code) << COMMON_MESSAGE;
+ VERIFY_OPTIONAL_FIELD(opt_window_update_increment) << COMMON_MESSAGE;
+
+#undef VERIFY_OPTIONAL_FIELD
+
+ return AssertionSuccess();
+}
+
+void FrameParts::SetTotalPadLength(size_t total_pad_length) {
+ opt_pad_length.reset();
+ padding.clear();
+ if (total_pad_length > 0) {
+ ASSERT_LE(total_pad_length, 256u);
+ ASSERT_TRUE(frame_header.IsPadded());
+ opt_pad_length = total_pad_length - 1;
+ char zero = 0;
+ padding.append(opt_pad_length.value(), zero);
+ }
+
+ if (opt_pad_length) {
+ VLOG(1) << "SetTotalPadLength: pad_length=" << opt_pad_length.value();
+ } else {
+ VLOG(1) << "SetTotalPadLength: has no pad length";
+ }
+}
+
+void FrameParts::SetAltSvcExpected(StringPiece origin, StringPiece value) {
+ origin.AppendToString(&altsvc_origin);
+ value.AppendToString(&altsvc_value);
+ opt_altsvc_origin_length = origin.size();
+ opt_altsvc_value_length = value.size();
+}
+
+bool FrameParts::OnFrameHeader(const Http2FrameHeader& header) {
+ ADD_FAILURE() << "OnFrameHeader: " << *this;
+ return true;
+}
+
+void FrameParts::OnDataStart(const Http2FrameHeader& header) {
+ VLOG(1) << "OnDataStart: " << header;
+ ASSERT_TRUE(StartFrameOfType(header, Http2FrameType::DATA)) << *this;
+ opt_payload_length = header.payload_length;
+}
+
+void FrameParts::OnDataPayload(const char* data, size_t len) {
+ VLOG(1) << "OnDataPayload: len=" << len << "; frame_header: " << frame_header;
+ ASSERT_TRUE(InFrameOfType(Http2FrameType::DATA)) << *this;
+ ASSERT_TRUE(
+ AppendString(StringPiece(data, len), &payload, &opt_payload_length));
+}
+
+void FrameParts::OnDataEnd() {
+ VLOG(1) << "OnDataEnd; frame_header: " << frame_header;
+ ASSERT_TRUE(EndFrameOfType(Http2FrameType::DATA)) << *this;
+}
+
+void FrameParts::OnHeadersStart(const Http2FrameHeader& header) {
+ VLOG(1) << "OnHeadersStart: " << header;
+ ASSERT_TRUE(StartFrameOfType(header, Http2FrameType::HEADERS)) << *this;
+ opt_payload_length = header.payload_length;
+}
+
+void FrameParts::OnHeadersPriority(const Http2PriorityFields& priority) {
+ VLOG(1) << "OnHeadersPriority: priority: " << priority
+ << "; frame_header: " << frame_header;
+ ASSERT_TRUE(InFrameOfType(Http2FrameType::HEADERS)) << *this;
+ ASSERT_FALSE(opt_priority);
+ opt_priority = priority;
+ ASSERT_TRUE(opt_payload_length);
+ opt_payload_length =
+ opt_payload_length.value() - Http2PriorityFields::EncodedSize();
+}
+
+void FrameParts::OnHpackFragment(const char* data, size_t len) {
+ VLOG(1) << "OnHpackFragment: len=" << len
+ << "; frame_header: " << frame_header;
+ ASSERT_TRUE(got_start_callback);
+ ASSERT_FALSE(got_end_callback);
+ ASSERT_TRUE(FrameCanHaveHpackPayload(frame_header)) << *this;
+ ASSERT_TRUE(
+ AppendString(StringPiece(data, len), &payload, &opt_payload_length));
+}
+
+void FrameParts::OnHeadersEnd() {
+ VLOG(1) << "OnHeadersEnd; frame_header: " << frame_header;
+ ASSERT_TRUE(EndFrameOfType(Http2FrameType::HEADERS)) << *this;
+}
+
+void FrameParts::OnPriorityFrame(const Http2FrameHeader& header,
+ const Http2PriorityFields& priority) {
+ VLOG(1) << "OnPriorityFrame: " << header << "; priority: " << priority;
+ ASSERT_TRUE(StartFrameOfType(header, Http2FrameType::PRIORITY)) << *this;
+ ASSERT_FALSE(opt_priority);
+ opt_priority = priority;
+ ASSERT_TRUE(EndFrameOfType(Http2FrameType::PRIORITY)) << *this;
+}
+
+void FrameParts::OnContinuationStart(const Http2FrameHeader& header) {
+ VLOG(1) << "OnContinuationStart: " << header;
+ ASSERT_TRUE(StartFrameOfType(header, Http2FrameType::CONTINUATION)) << *this;
+ opt_payload_length = header.payload_length;
+}
+
+void FrameParts::OnContinuationEnd() {
+ VLOG(1) << "OnContinuationEnd; frame_header: " << frame_header;
+ ASSERT_TRUE(EndFrameOfType(Http2FrameType::CONTINUATION)) << *this;
+}
+
+void FrameParts::OnPadLength(size_t trailing_length) {
+ VLOG(1) << "OnPadLength: trailing_length=" << trailing_length;
+ ASSERT_TRUE(InPaddedFrame()) << *this;
+ ASSERT_FALSE(opt_pad_length);
+ ASSERT_TRUE(opt_payload_length);
+ size_t total_padding_length = trailing_length + 1;
+ ASSERT_GE(opt_payload_length.value(), static_cast<int>(total_padding_length));
+ opt_payload_length = opt_payload_length.value() - total_padding_length;
+ opt_pad_length = trailing_length;
+}
+
+void FrameParts::OnPadding(const char* pad, size_t skipped_length) {
+ VLOG(1) << "OnPadding: skipped_length=" << skipped_length;
+ ASSERT_TRUE(InPaddedFrame()) << *this;
+ ASSERT_TRUE(opt_pad_length);
+ ASSERT_TRUE(AppendString(StringPiece(pad, skipped_length), &padding,
+ &opt_pad_length));
+}
+
+void FrameParts::OnRstStream(const Http2FrameHeader& header,
+ Http2ErrorCode error_code) {
+ VLOG(1) << "OnRstStream: " << header << "; code=" << error_code;
+ ASSERT_TRUE(StartFrameOfType(header, Http2FrameType::RST_STREAM)) << *this;
+ ASSERT_FALSE(opt_rst_stream_error_code);
+ opt_rst_stream_error_code = error_code;
+ ASSERT_TRUE(EndFrameOfType(Http2FrameType::RST_STREAM)) << *this;
+}
+
+void FrameParts::OnSettingsStart(const Http2FrameHeader& header) {
+ VLOG(1) << "OnSettingsStart: " << header;
+ ASSERT_TRUE(StartFrameOfType(header, Http2FrameType::SETTINGS)) << *this;
+ ASSERT_EQ(0u, settings.size());
+ ASSERT_FALSE(header.IsAck()) << header;
+}
+
+void FrameParts::OnSetting(const Http2SettingFields& setting_fields) {
+ VLOG(1) << "OnSetting: " << setting_fields;
+ ASSERT_TRUE(InFrameOfType(Http2FrameType::SETTINGS)) << *this;
+ settings.push_back(setting_fields);
+}
+
+void FrameParts::OnSettingsEnd() {
+ VLOG(1) << "OnSettingsEnd; frame_header: " << frame_header;
+ ASSERT_TRUE(EndFrameOfType(Http2FrameType::SETTINGS)) << *this;
+}
+
+void FrameParts::OnSettingsAck(const Http2FrameHeader& header) {
+ VLOG(1) << "OnSettingsAck: " << header;
+ ASSERT_TRUE(StartFrameOfType(header, Http2FrameType::SETTINGS)) << *this;
+ ASSERT_EQ(0u, settings.size());
+ ASSERT_TRUE(header.IsAck());
+ ASSERT_TRUE(EndFrameOfType(Http2FrameType::SETTINGS)) << *this;
+}
+
+void FrameParts::OnPushPromiseStart(const Http2FrameHeader& header,
+ const Http2PushPromiseFields& promise,
+ size_t total_padding_length) {
+ VLOG(1) << "OnPushPromiseStart header: " << header << "; promise: " << promise
+ << "; total_padding_length: " << total_padding_length;
+ ASSERT_TRUE(StartFrameOfType(header, Http2FrameType::PUSH_PROMISE)) << *this;
+ ASSERT_GE(header.payload_length, Http2PushPromiseFields::EncodedSize());
+ opt_payload_length =
+ header.payload_length - Http2PushPromiseFields::EncodedSize();
+ ASSERT_FALSE(opt_push_promise);
+ opt_push_promise = promise;
+ if (total_padding_length > 0) {
+ ASSERT_GE(opt_payload_length.value(),
+ static_cast<int>(total_padding_length));
+ OnPadLength(total_padding_length - 1);
+ } else {
+ ASSERT_FALSE(header.IsPadded());
+ }
+}
+
+void FrameParts::OnPushPromiseEnd() {
+ VLOG(1) << "OnPushPromiseEnd; frame_header: " << frame_header;
+ ASSERT_TRUE(EndFrameOfType(Http2FrameType::PUSH_PROMISE)) << *this;
+}
+
+void FrameParts::OnPing(const Http2FrameHeader& header,
+ const Http2PingFields& ping) {
+ VLOG(1) << "OnPing header: " << header << " ping: " << ping;
+ ASSERT_TRUE(StartFrameOfType(header, Http2FrameType::PING)) << *this;
+ ASSERT_FALSE(header.IsAck());
+ ASSERT_FALSE(opt_ping);
+ opt_ping = ping;
+ ASSERT_TRUE(EndFrameOfType(Http2FrameType::PING)) << *this;
+}
+
+void FrameParts::OnPingAck(const Http2FrameHeader& header,
+ const Http2PingFields& ping) {
+ VLOG(1) << "OnPingAck header: " << header << " ping: " << ping;
+ ASSERT_TRUE(StartFrameOfType(header, Http2FrameType::PING)) << *this;
+ ASSERT_TRUE(header.IsAck());
+ ASSERT_FALSE(opt_ping);
+ opt_ping = ping;
+ ASSERT_TRUE(EndFrameOfType(Http2FrameType::PING)) << *this;
+}
+
+void FrameParts::OnGoAwayStart(const Http2FrameHeader& header,
+ const Http2GoAwayFields& goaway) {
+ VLOG(1) << "OnGoAwayStart: " << goaway;
+ ASSERT_TRUE(StartFrameOfType(header, Http2FrameType::GOAWAY)) << *this;
+ ASSERT_FALSE(opt_goaway);
+ opt_goaway = goaway;
+ opt_payload_length = header.payload_length - Http2GoAwayFields::EncodedSize();
+}
+
+void FrameParts::OnGoAwayOpaqueData(const char* data, size_t len) {
+ VLOG(1) << "OnGoAwayOpaqueData: len=" << len;
+ ASSERT_TRUE(InFrameOfType(Http2FrameType::GOAWAY)) << *this;
+ ASSERT_TRUE(
+ AppendString(StringPiece(data, len), &payload, &opt_payload_length));
+}
+
+void FrameParts::OnGoAwayEnd() {
+ VLOG(1) << "OnGoAwayEnd; frame_header: " << frame_header;
+ ASSERT_TRUE(EndFrameOfType(Http2FrameType::GOAWAY)) << *this;
+}
+
+void FrameParts::OnWindowUpdate(const Http2FrameHeader& header,
+ uint32_t increment) {
+ VLOG(1) << "OnWindowUpdate header: " << header
+ << " increment=" << increment;
+ ASSERT_TRUE(StartFrameOfType(header, Http2FrameType::WINDOW_UPDATE)) << *this;
+ ASSERT_FALSE(opt_window_update_increment);
+ opt_window_update_increment = increment;
+ ASSERT_TRUE(EndFrameOfType(Http2FrameType::WINDOW_UPDATE)) << *this;
+}
+
+void FrameParts::OnAltSvcStart(const Http2FrameHeader& header,
+ size_t origin_length,
+ size_t value_length) {
+ VLOG(1) << "OnAltSvcStart: " << header
+ << " origin_length: " << origin_length
+ << " value_length: " << value_length;
+ ASSERT_TRUE(StartFrameOfType(header, Http2FrameType::ALTSVC)) << *this;
+ ASSERT_FALSE(opt_altsvc_origin_length);
+ opt_altsvc_origin_length = origin_length;
+ ASSERT_FALSE(opt_altsvc_value_length);
+ opt_altsvc_value_length = value_length;
+}
+
+void FrameParts::OnAltSvcOriginData(const char* data, size_t len) {
+ VLOG(1) << "OnAltSvcOriginData: len=" << len;
+ ASSERT_TRUE(InFrameOfType(Http2FrameType::ALTSVC)) << *this;
+ ASSERT_TRUE(AppendString(StringPiece(data, len), &altsvc_origin,
+ &opt_altsvc_origin_length));
+}
+
+void FrameParts::OnAltSvcValueData(const char* data, size_t len) {
+ VLOG(1) << "OnAltSvcValueData: len=" << len;
+ ASSERT_TRUE(InFrameOfType(Http2FrameType::ALTSVC)) << *this;
+ ASSERT_TRUE(AppendString(StringPiece(data, len), &altsvc_value,
+ &opt_altsvc_value_length));
+}
+
+void FrameParts::OnAltSvcEnd() {
+ VLOG(1) << "OnAltSvcEnd; frame_header: " << frame_header;
+ ASSERT_TRUE(EndFrameOfType(Http2FrameType::ALTSVC)) << *this;
+}
+
+void FrameParts::OnUnknownStart(const Http2FrameHeader& header) {
+ VLOG(1) << "OnUnknownStart: " << header;
+ ASSERT_FALSE(IsSupportedHttp2FrameType(header.type)) << header;
+ ASSERT_FALSE(got_start_callback);
+ ASSERT_EQ(frame_header, header);
+ got_start_callback = true;
+ opt_payload_length = header.payload_length;
+}
+
+void FrameParts::OnUnknownPayload(const char* data, size_t len) {
+ VLOG(1) << "OnUnknownPayload: len=" << len;
+ ASSERT_FALSE(IsSupportedHttp2FrameType(frame_header.type)) << *this;
+ ASSERT_TRUE(got_start_callback);
+ ASSERT_FALSE(got_end_callback);
+ ASSERT_TRUE(
+ AppendString(StringPiece(data, len), &payload, &opt_payload_length));
+}
+
+void FrameParts::OnUnknownEnd() {
+ VLOG(1) << "OnUnknownEnd; frame_header: " << frame_header;
+ ASSERT_FALSE(IsSupportedHttp2FrameType(frame_header.type)) << *this;
+ ASSERT_TRUE(got_start_callback);
+ ASSERT_FALSE(got_end_callback);
+ got_end_callback = true;
+}
+
+void FrameParts::OnPaddingTooLong(const Http2FrameHeader& header,
+ size_t missing_length) {
+ VLOG(1) << "OnPaddingTooLong: " << header
+ << "; missing_length: " << missing_length;
+ ASSERT_EQ(frame_header, header);
+ ASSERT_FALSE(got_end_callback);
+ ASSERT_TRUE(FrameIsPadded(header));
+ ASSERT_FALSE(opt_pad_length);
+ ASSERT_FALSE(opt_missing_length);
+ opt_missing_length = missing_length;
+ got_start_callback = true;
+ got_end_callback = true;
+}
+
+void FrameParts::OnFrameSizeError(const Http2FrameHeader& header) {
+ VLOG(1) << "OnFrameSizeError: " << header;
+ ASSERT_EQ(frame_header, header);
+ ASSERT_FALSE(got_end_callback);
+ ASSERT_FALSE(has_frame_size_error);
+ has_frame_size_error = true;
+ got_end_callback = true;
+}
+
+void FrameParts::OutputTo(std::ostream& out) const {
+ out << "FrameParts{\n frame_header: " << frame_header << "\n";
+ if (!payload.empty()) {
+ out << " payload=\"" << EscapeQueryParamValue(payload, false) << "\"\n";
+ }
+ if (!padding.empty()) {
+ out << " padding=\"" << EscapeQueryParamValue(padding, false) << "\"\n";
+ }
+ if (!altsvc_origin.empty()) {
+ out << " altsvc_origin=\"" << EscapeQueryParamValue(altsvc_origin, false)
+ << "\"\n";
+ }
+ if (!altsvc_value.empty()) {
+ out << " altsvc_value=\"" << EscapeQueryParamValue(altsvc_value, false)
+ << "\"\n";
+ }
+ if (opt_priority) {
+ out << " priority=" << opt_priority.value() << "\n";
+ }
+ if (opt_rst_stream_error_code) {
+ out << " rst_stream=" << opt_rst_stream_error_code.value() << "\n";
+ }
+ if (opt_push_promise) {
+ out << " push_promise=" << opt_push_promise.value() << "\n";
+ }
+ if (opt_ping) {
+ out << " ping=" << opt_ping.value() << "\n";
+ }
+ if (opt_goaway) {
+ out << " goaway=" << opt_goaway.value() << "\n";
+ }
+ if (opt_window_update_increment) {
+ out << " window_update=" << opt_window_update_increment.value() << "\n";
+ }
+ if (opt_payload_length) {
+ out << " payload_length=" << opt_payload_length.value() << "\n";
+ }
+ if (opt_pad_length) {
+ out << " pad_length=" << opt_pad_length.value() << "\n";
+ }
+ if (opt_missing_length) {
+ out << " missing_length=" << opt_missing_length.value() << "\n";
+ }
+ if (opt_altsvc_origin_length) {
+ out << " origin_length=" << opt_altsvc_origin_length.value() << "\n";
+ }
+ if (opt_altsvc_value_length) {
+ out << " value_length=" << opt_altsvc_value_length.value() << "\n";
+ }
+ if (has_frame_size_error) {
+ out << " has_frame_size_error\n";
+ }
+ if (got_start_callback) {
+ out << " got_start_callback\n";
+ }
+ if (got_end_callback) {
+ out << " got_end_callback\n";
+ }
+ for (size_t ndx = 0; ndx < settings.size(); ++ndx) {
+ out << " setting[" << ndx << "]=" << settings[ndx];
+ }
+ out << "}";
+}
+
+AssertionResult FrameParts::StartFrameOfType(
+ const Http2FrameHeader& header,
+ Http2FrameType expected_frame_type) {
+ VERIFY_EQ(header.type, expected_frame_type);
+ VERIFY_FALSE(got_start_callback);
+ VERIFY_FALSE(got_end_callback);
+ VERIFY_EQ(frame_header, header);
+ got_start_callback = true;
+ return AssertionSuccess();
+}
+
+AssertionResult FrameParts::InFrameOfType(Http2FrameType expected_frame_type) {
+ VERIFY_TRUE(got_start_callback);
+ VERIFY_FALSE(got_end_callback);
+ VERIFY_EQ(frame_header.type, expected_frame_type);
+ return AssertionSuccess();
+}
+
+AssertionResult FrameParts::EndFrameOfType(Http2FrameType expected_frame_type) {
+ VERIFY_SUCCESS(InFrameOfType(expected_frame_type));
+ got_end_callback = true;
+ return AssertionSuccess();
+}
+
+AssertionResult FrameParts::InPaddedFrame() {
+ VERIFY_TRUE(got_start_callback);
+ VERIFY_FALSE(got_end_callback);
+ VERIFY_TRUE(FrameIsPadded(frame_header));
+ return AssertionSuccess();
+}
+
+AssertionResult FrameParts::AppendString(StringPiece source,
+ string* target,
+ base::Optional<int>* opt_length) {
+ source.AppendToString(target);
+ if (opt_length != nullptr) {
+ VERIFY_TRUE(*opt_length) << "Length is not set yet\n" << *this;
+ VERIFY_LE(target->size(), static_cast<size_t>(opt_length->value()))
+ << "String too large; source.size() = " << source.size() << "\n"
+ << *this;
+ }
+ return ::testing::AssertionSuccess();
+}
+
+std::ostream& operator<<(std::ostream& out, const FrameParts& v) {
+ v.OutputTo(out);
+ return out;
+}
+
+} // namespace test
+} // namespace net
diff --git a/chromium/net/http2/decoder/frame_parts.h b/chromium/net/http2/decoder/frame_parts.h
new file mode 100644
index 00000000000..c64dea69766
--- /dev/null
+++ b/chromium/net/http2/decoder/frame_parts.h
@@ -0,0 +1,176 @@
+// Copyright 2016 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.
+
+#ifndef NET_HTTP2_DECODER_FRAME_PARTS_H_
+#define NET_HTTP2_DECODER_FRAME_PARTS_H_
+
+// FrameParts implements Http2FrameDecoderListener, recording the callbacks
+// during the decoding of a single frame. It is also used for comparing the
+// info that a test expects to be recorded during the decoding of a frame
+// with the actual recorded value (i.e. by providing a comparator).
+
+// TODO(jamessynge): Convert FrameParts to a class, hide the members, add
+// getters/setters.
+
+#include <stddef.h>
+
+#include <string>
+#include <vector>
+
+#include "base/logging.h"
+#include "base/optional.h"
+#include "base/strings/string_piece.h"
+#include "net/http2/decoder/http2_frame_decoder_listener.h"
+#include "net/http2/http2_constants.h"
+#include "net/http2/http2_structures.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace net {
+namespace test {
+
+struct FrameParts;
+
+std::ostream& operator<<(std::ostream& out, const FrameParts& v);
+
+struct FrameParts : public Http2FrameDecoderListener {
+ // The first callback for every type of frame includes the frame header; this
+ // is the only constructor used during decoding of a frame.
+ explicit FrameParts(const Http2FrameHeader& header);
+
+ // For use in tests where the expected frame has a variable size payload.
+ FrameParts(const Http2FrameHeader& header, base::StringPiece payload);
+
+ // For use in tests where the expected frame has a variable size payload
+ // and may be padded.
+ FrameParts(const Http2FrameHeader& header,
+ base::StringPiece payload,
+ size_t total_pad_length);
+
+ FrameParts(const FrameParts& other);
+
+ ~FrameParts() override;
+
+ // Returns AssertionSuccess() if they're equal, else AssertionFailure()
+ // with info about the difference.
+ ::testing::AssertionResult VerifyEquals(const FrameParts& other) const;
+
+ // Format this FrameParts object.
+ void OutputTo(std::ostream& out) const;
+
+ // Set the total padding length (0 to 256).
+ void SetTotalPadLength(size_t total_pad_length);
+
+ // Set the origin and value expected in an ALTSVC frame.
+ void SetAltSvcExpected(base::StringPiece origin, base::StringPiece value);
+
+ // Http2FrameDecoderListener methods:
+ bool OnFrameHeader(const Http2FrameHeader& header) override;
+ void OnDataStart(const Http2FrameHeader& header) override;
+ void OnDataPayload(const char* data, size_t len) override;
+ void OnDataEnd() override;
+ void OnHeadersStart(const Http2FrameHeader& header) override;
+ void OnHeadersPriority(const Http2PriorityFields& priority) override;
+ void OnHpackFragment(const char* data, size_t len) override;
+ void OnHeadersEnd() override;
+ void OnPriorityFrame(const Http2FrameHeader& header,
+ const Http2PriorityFields& priority) override;
+ void OnContinuationStart(const Http2FrameHeader& header) override;
+ void OnContinuationEnd() override;
+ void OnPadLength(size_t trailing_length) override;
+ void OnPadding(const char* pad, size_t skipped_length) override;
+ void OnRstStream(const Http2FrameHeader& header,
+ Http2ErrorCode error_code) override;
+ void OnSettingsStart(const Http2FrameHeader& header) override;
+ void OnSetting(const Http2SettingFields& setting_fields) override;
+ void OnSettingsEnd() override;
+ void OnSettingsAck(const Http2FrameHeader& header) override;
+ void OnPushPromiseStart(const Http2FrameHeader& header,
+ const Http2PushPromiseFields& promise,
+ size_t total_padding_length) override;
+ void OnPushPromiseEnd() override;
+ void OnPing(const Http2FrameHeader& header,
+ const Http2PingFields& ping) override;
+ void OnPingAck(const Http2FrameHeader& header,
+ const Http2PingFields& ping) override;
+ void OnGoAwayStart(const Http2FrameHeader& header,
+ const Http2GoAwayFields& goaway) override;
+ void OnGoAwayOpaqueData(const char* data, size_t len) override;
+ void OnGoAwayEnd() override;
+ void OnWindowUpdate(const Http2FrameHeader& header,
+ uint32_t increment) override;
+ void OnAltSvcStart(const Http2FrameHeader& header,
+ size_t origin_length,
+ size_t value_length) override;
+ void OnAltSvcOriginData(const char* data, size_t len) override;
+ void OnAltSvcValueData(const char* data, size_t len) override;
+ void OnAltSvcEnd() override;
+ void OnUnknownStart(const Http2FrameHeader& header) override;
+ void OnUnknownPayload(const char* data, size_t len) override;
+ void OnUnknownEnd() override;
+ void OnPaddingTooLong(const Http2FrameHeader& header,
+ size_t missing_length) override;
+ void OnFrameSizeError(const Http2FrameHeader& header) override;
+
+ // The fields are public for access by tests.
+
+ const Http2FrameHeader frame_header;
+
+ std::string payload;
+ std::string padding;
+ std::string altsvc_origin;
+ std::string altsvc_value;
+
+ base::Optional<Http2PriorityFields> opt_priority;
+ base::Optional<Http2ErrorCode> opt_rst_stream_error_code;
+ base::Optional<Http2PushPromiseFields> opt_push_promise;
+ base::Optional<Http2PingFields> opt_ping;
+ base::Optional<Http2GoAwayFields> opt_goaway;
+
+ base::Optional<int> opt_pad_length;
+ base::Optional<int> opt_payload_length;
+ base::Optional<int> opt_missing_length;
+ base::Optional<int> opt_altsvc_origin_length;
+ base::Optional<int> opt_altsvc_value_length;
+
+ base::Optional<size_t> opt_window_update_increment;
+
+ bool has_frame_size_error = false;
+
+ std::vector<Http2SettingFields> settings;
+
+ // These booleans are not checked by CompareCollectedFrames.
+ bool got_start_callback = false;
+ bool got_end_callback = false;
+
+ private:
+ // ASSERT during an On* method that we're handling a frame of type
+ // expected_frame_type, and have not already received other On* methods
+ // (i.e. got_start_callback is false).
+ ::testing::AssertionResult StartFrameOfType(
+ const Http2FrameHeader& header,
+ Http2FrameType expected_frame_type);
+
+ // ASSERT that StartFrameOfType has already been called with
+ // expected_frame_type (i.e. got_start_callback has been called), and that
+ // EndFrameOfType has not yet been called (i.e. got_end_callback is false).
+ ::testing::AssertionResult InFrameOfType(Http2FrameType expected_frame_type);
+
+ // ASSERT that we're InFrameOfType, and then sets got_end_callback=true.
+ ::testing::AssertionResult EndFrameOfType(Http2FrameType expected_frame_type);
+
+ // ASSERT that we're in the middle of processing a frame that is padded.
+ ::testing::AssertionResult InPaddedFrame();
+
+ // Append source to target. If opt_length is not nullptr, then verifies that
+ // the optional has a value (i.e. that the necessary On*Start method has been
+ // called), and that target is not longer than opt_length->value().
+ ::testing::AssertionResult AppendString(base::StringPiece source,
+ std::string* target,
+ base::Optional<int>* opt_length);
+};
+
+} // namespace test
+} // namespace net
+
+#endif // NET_HTTP2_DECODER_FRAME_PARTS_H_
diff --git a/chromium/net/http2/decoder/frame_parts_collector.cc b/chromium/net/http2/decoder/frame_parts_collector.cc
new file mode 100644
index 00000000000..05c54880105
--- /dev/null
+++ b/chromium/net/http2/decoder/frame_parts_collector.cc
@@ -0,0 +1,112 @@
+// Copyright 2016 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.
+
+#include "net/http2/decoder/frame_parts_collector.h"
+
+#include <utility>
+
+#include "base/logging.h"
+#include "net/http2/http2_structures_test_util.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace net {
+namespace test {
+
+FramePartsCollector::FramePartsCollector() {}
+FramePartsCollector::~FramePartsCollector() {}
+
+void FramePartsCollector::Reset() {
+ current_frame_.reset();
+ collected_frames_.clear();
+ expected_header_set_ = false;
+}
+
+const FrameParts* FramePartsCollector::frame(size_t n) const {
+ if (n < size()) {
+ return collected_frames_.at(n).get();
+ }
+ CHECK(n == size());
+ return current_frame();
+}
+
+void FramePartsCollector::ExpectFrameHeader(const Http2FrameHeader& header) {
+ EXPECT_FALSE(IsInProgress());
+ EXPECT_FALSE(expected_header_set_) << "expected_header_: "
+ << expected_header_;
+ expected_header_ = header;
+ expected_header_set_ = true;
+ // OnFrameHeader is called before the flags are scrubbed, but the other
+ // methods are called after, so scrub the invalid flags from expected_header_.
+ ScrubFlagsOfHeader(&expected_header_);
+}
+
+void FramePartsCollector::TestExpectedHeader(const Http2FrameHeader& header) {
+ if (expected_header_set_) {
+ EXPECT_EQ(header, expected_header_);
+ expected_header_set_ = false;
+ }
+}
+
+Http2FrameDecoderListener* FramePartsCollector::StartFrame(
+ const Http2FrameHeader& header) {
+ TestExpectedHeader(header);
+ EXPECT_FALSE(IsInProgress());
+ if (current_frame_ == nullptr) {
+ current_frame_.reset(new FrameParts(header));
+ }
+ return current_frame();
+}
+
+Http2FrameDecoderListener* FramePartsCollector::StartAndEndFrame(
+ const Http2FrameHeader& header) {
+ TestExpectedHeader(header);
+ EXPECT_FALSE(IsInProgress());
+ if (current_frame_ == nullptr) {
+ current_frame_.reset(new FrameParts(header));
+ }
+ Http2FrameDecoderListener* result = current_frame();
+ collected_frames_.push_back(std::move(current_frame_));
+ return result;
+}
+
+Http2FrameDecoderListener* FramePartsCollector::CurrentFrame() {
+ EXPECT_TRUE(IsInProgress());
+ if (current_frame_ == nullptr) {
+ return &failing_listener_;
+ }
+ return current_frame();
+}
+
+Http2FrameDecoderListener* FramePartsCollector::EndFrame() {
+ EXPECT_TRUE(IsInProgress());
+ if (current_frame_ == nullptr) {
+ return &failing_listener_;
+ }
+ Http2FrameDecoderListener* result = current_frame();
+ collected_frames_.push_back(std::move(current_frame_));
+ return result;
+}
+
+Http2FrameDecoderListener* FramePartsCollector::FrameError(
+ const Http2FrameHeader& header) {
+ TestExpectedHeader(header);
+ if (current_frame_ == nullptr) {
+ // The decoder may detect an error before making any calls to the listener
+ // regarding the frame, in which case current_frame_==nullptr and we need
+ // to create a FrameParts instance.
+ current_frame_.reset(new FrameParts(header));
+ } else {
+ // Similarly, the decoder may have made calls to the listener regarding the
+ // frame before detecting the error; for example, the DATA payload decoder
+ // calls OnDataStart before it can detect padding errors, hence before it
+ // can call OnPaddingTooLong.
+ EXPECT_EQ(header, current_frame_->frame_header);
+ }
+ Http2FrameDecoderListener* result = current_frame();
+ collected_frames_.push_back(std::move(current_frame_));
+ return result;
+}
+
+} // namespace test
+} // namespace net
diff --git a/chromium/net/http2/decoder/frame_parts_collector.h b/chromium/net/http2/decoder/frame_parts_collector.h
new file mode 100644
index 00000000000..c411e48eabd
--- /dev/null
+++ b/chromium/net/http2/decoder/frame_parts_collector.h
@@ -0,0 +1,116 @@
+// Copyright 2016 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.
+
+#ifndef NET_HTTP2_DECODER_FRAME_PARTS_COLLECTOR_H_
+#define NET_HTTP2_DECODER_FRAME_PARTS_COLLECTOR_H_
+
+// FramePartsCollector is a base class for Http2FrameDecoderListener
+// implementations that create one FrameParts instance for each decoded frame.
+
+#include <stddef.h>
+
+#include <memory>
+#include <vector>
+
+#include "net/http2/decoder/frame_parts.h"
+#include "net/http2/decoder/http2_frame_decoder_listener.h"
+#include "net/http2/decoder/http2_frame_decoder_listener_test_util.h"
+#include "net/http2/http2_structures.h"
+
+namespace net {
+namespace test {
+
+class FramePartsCollector : public FailingHttp2FrameDecoderListener {
+ public:
+ FramePartsCollector();
+ ~FramePartsCollector() override;
+
+ // Toss out the collected data.
+ void Reset();
+
+ // Returns true if has started recording the info for a frame and has not yet
+ // finished doing so.
+ bool IsInProgress() const { return current_frame_ != nullptr; }
+
+ // Returns the FrameParts instance into which we're currently recording
+ // callback info if IsInProgress, else nullptr.
+ const FrameParts* current_frame() const { return current_frame_.get(); }
+
+ // Returns the completely collected FrameParts instances.
+ const std::vector<std::unique_ptr<FrameParts>>& collected_frames() const {
+ return collected_frames_;
+ }
+
+ // Returns the number of completely collected FrameParts instances.
+ size_t size() const { return collected_frames_.size(); }
+
+ // Returns the n'th frame, where 0 is the oldest of the collected frames,
+ // and n==size() is the frame currently being collected, if there is one.
+ // Returns nullptr if the requested index is not valid.
+ const FrameParts* frame(size_t n) const;
+
+ protected:
+ // In support of OnFrameHeader, set the header that we expect to be used in
+ // the next call.
+ // TODO(jamessynge): Remove ExpectFrameHeader et al. once done with supporting
+ // SpdyFramer's exact states.
+ void ExpectFrameHeader(const Http2FrameHeader& header);
+
+ // For use in implementing On*Start methods of Http2FrameDecoderListener,
+ // returns a FrameParts instance, which will be newly created if
+ // IsInProgress==false (which the caller should ensure), else will be the
+ // current_frame(); never returns nullptr.
+ // If called when IsInProgress==true, a test failure will be recorded.
+ Http2FrameDecoderListener* StartFrame(const Http2FrameHeader& header);
+
+ // For use in implementing On* callbacks, such as OnPingAck, that are the only
+ // call expected for the frame being decoded; not for On*Start methods.
+ // Returns a FrameParts instance, which will be newly created if
+ // IsInProgress==false (which the caller should ensure), else will be the
+ // current_frame(); never returns nullptr.
+ // If called when IsInProgress==true, a test failure will be recorded.
+ Http2FrameDecoderListener* StartAndEndFrame(const Http2FrameHeader& header);
+
+ // If IsInProgress==true, returns the FrameParts into which the current
+ // frame is being recorded; else records a test failure and returns
+ // failing_listener_, which will record a test failure when any of its
+ // On* methods is called.
+ Http2FrameDecoderListener* CurrentFrame();
+
+ // For use in implementing On*End methods, pushes the current frame onto
+ // the vector of completed frames, and returns a pointer to it for recording
+ // the info in the final call. If IsInProgress==false, records a test failure
+ // and returns failing_listener_, which will record a test failure when any
+ // of its On* methods is called.
+ Http2FrameDecoderListener* EndFrame();
+
+ // For use in implementing OnPaddingTooLong and OnFrameSizeError, is
+ // equivalent to EndFrame() if IsInProgress==true, else equivalent to
+ // StartAndEndFrame().
+ Http2FrameDecoderListener* FrameError(const Http2FrameHeader& header);
+
+ private:
+ // Returns the mutable FrameParts instance into which we're currently
+ // recording callback info if IsInProgress, else nullptr.
+ FrameParts* current_frame() { return current_frame_.get(); }
+
+ // If expected header is set, verify that it matches the header param.
+ // TODO(jamessynge): Remove TestExpectedHeader et al. once done
+ // with supporting SpdyFramer's exact states.
+ void TestExpectedHeader(const Http2FrameHeader& header);
+
+ std::unique_ptr<FrameParts> current_frame_;
+ std::vector<std::unique_ptr<FrameParts>> collected_frames_;
+ FailingHttp2FrameDecoderListener failing_listener_;
+
+ // TODO(jamessynge): Remove expected_header_ et al. once done with supporting
+ // SpdyFramer's exact states.
+ Http2FrameHeader expected_header_;
+ bool expected_header_set_ = false;
+};
+
+} // namespace test
+} // namespace net
+
+#endif // NET_HTTP2_DECODER_FRAME_PARTS_COLLECTOR_H_
diff --git a/chromium/net/http2/decoder/frame_parts_collector_listener.cc b/chromium/net/http2/decoder/frame_parts_collector_listener.cc
new file mode 100644
index 00000000000..83a1ea34fca
--- /dev/null
+++ b/chromium/net/http2/decoder/frame_parts_collector_listener.cc
@@ -0,0 +1,230 @@
+// Copyright 2016 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.
+
+#include "net/http2/decoder/frame_parts_collector_listener.h"
+
+#include "base/logging.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace net {
+namespace test {
+
+bool FramePartsCollectorListener::OnFrameHeader(
+ const Http2FrameHeader& header) {
+ VLOG(1) << "OnFrameHeader: " << header;
+ ExpectFrameHeader(header);
+ return true;
+}
+
+void FramePartsCollectorListener::OnDataStart(const Http2FrameHeader& header) {
+ VLOG(1) << "OnDataStart: " << header;
+ StartFrame(header)->OnDataStart(header);
+}
+
+void FramePartsCollectorListener::OnDataPayload(const char* data, size_t len) {
+ VLOG(1) << "OnDataPayload: len=" << len;
+ CurrentFrame()->OnDataPayload(data, len);
+}
+
+void FramePartsCollectorListener::OnDataEnd() {
+ VLOG(1) << "OnDataEnd";
+ EndFrame()->OnDataEnd();
+}
+
+void FramePartsCollectorListener::OnHeadersStart(
+ const Http2FrameHeader& header) {
+ VLOG(1) << "OnHeadersStart: " << header;
+ StartFrame(header)->OnHeadersStart(header);
+}
+
+void FramePartsCollectorListener::OnHeadersPriority(
+ const Http2PriorityFields& priority) {
+ VLOG(1) << "OnHeadersPriority: " << priority;
+ CurrentFrame()->OnHeadersPriority(priority);
+}
+
+void FramePartsCollectorListener::OnHpackFragment(const char* data,
+ size_t len) {
+ VLOG(1) << "OnHpackFragment: len=" << len;
+ CurrentFrame()->OnHpackFragment(data, len);
+}
+
+void FramePartsCollectorListener::OnHeadersEnd() {
+ VLOG(1) << "OnHeadersEnd";
+ EndFrame()->OnHeadersEnd();
+}
+
+void FramePartsCollectorListener::OnPriorityFrame(
+ const Http2FrameHeader& header,
+ const Http2PriorityFields& priority_fields) {
+ VLOG(1) << "OnPriority: " << header << "; " << priority_fields;
+ StartAndEndFrame(header)->OnPriorityFrame(header, priority_fields);
+}
+
+void FramePartsCollectorListener::OnContinuationStart(
+ const Http2FrameHeader& header) {
+ VLOG(1) << "OnContinuationStart: " << header;
+ StartFrame(header)->OnContinuationStart(header);
+}
+
+void FramePartsCollectorListener::OnContinuationEnd() {
+ VLOG(1) << "OnContinuationEnd";
+ EndFrame()->OnContinuationEnd();
+}
+
+void FramePartsCollectorListener::OnPadLength(size_t pad_length) {
+ VLOG(1) << "OnPadLength: " << pad_length;
+ CurrentFrame()->OnPadLength(pad_length);
+}
+
+void FramePartsCollectorListener::OnPadding(const char* padding,
+ size_t skipped_length) {
+ VLOG(1) << "OnPadding: " << skipped_length;
+ CurrentFrame()->OnPadding(padding, skipped_length);
+}
+
+void FramePartsCollectorListener::OnRstStream(const Http2FrameHeader& header,
+ Http2ErrorCode error_code) {
+ VLOG(1) << "OnRstStream: " << header << "; error_code=" << error_code;
+ StartAndEndFrame(header)->OnRstStream(header, error_code);
+}
+
+void FramePartsCollectorListener::OnSettingsStart(
+ const Http2FrameHeader& header) {
+ VLOG(1) << "OnSettingsStart: " << header;
+ EXPECT_EQ(Http2FrameType::SETTINGS, header.type) << header;
+ EXPECT_EQ(Http2FrameFlag(), header.flags) << header;
+ StartFrame(header)->OnSettingsStart(header);
+}
+
+void FramePartsCollectorListener::OnSetting(
+ const Http2SettingFields& setting_fields) {
+ VLOG(1) << "Http2SettingFields: setting_fields=" << setting_fields;
+ CurrentFrame()->OnSetting(setting_fields);
+}
+
+void FramePartsCollectorListener::OnSettingsEnd() {
+ VLOG(1) << "OnSettingsEnd";
+ EndFrame()->OnSettingsEnd();
+}
+
+void FramePartsCollectorListener::OnSettingsAck(
+ const Http2FrameHeader& header) {
+ VLOG(1) << "OnSettingsAck: " << header;
+ StartAndEndFrame(header)->OnSettingsAck(header);
+}
+
+void FramePartsCollectorListener::OnPushPromiseStart(
+ const Http2FrameHeader& header,
+ const Http2PushPromiseFields& promise,
+ size_t total_padding_length) {
+ VLOG(1) << "OnPushPromiseStart header: " << header << " promise: " << promise
+ << " total_padding_length: " << total_padding_length;
+ EXPECT_EQ(Http2FrameType::PUSH_PROMISE, header.type);
+ StartFrame(header)->OnPushPromiseStart(header, promise, total_padding_length);
+}
+
+void FramePartsCollectorListener::OnPushPromiseEnd() {
+ VLOG(1) << "OnPushPromiseEnd";
+ EndFrame()->OnPushPromiseEnd();
+}
+
+void FramePartsCollectorListener::OnPing(const Http2FrameHeader& header,
+ const Http2PingFields& ping) {
+ VLOG(1) << "OnPing: " << header << "; " << ping;
+ StartAndEndFrame(header)->OnPing(header, ping);
+}
+
+void FramePartsCollectorListener::OnPingAck(const Http2FrameHeader& header,
+ const Http2PingFields& ping) {
+ VLOG(1) << "OnPingAck: " << header << "; " << ping;
+ StartAndEndFrame(header)->OnPingAck(header, ping);
+}
+
+void FramePartsCollectorListener::OnGoAwayStart(
+ const Http2FrameHeader& header,
+ const Http2GoAwayFields& goaway) {
+ VLOG(1) << "OnGoAwayStart header: " << header << "; goaway: " << goaway;
+ StartFrame(header)->OnGoAwayStart(header, goaway);
+}
+
+void FramePartsCollectorListener::OnGoAwayOpaqueData(const char* data,
+ size_t len) {
+ VLOG(1) << "OnGoAwayOpaqueData: len=" << len;
+ CurrentFrame()->OnGoAwayOpaqueData(data, len);
+}
+
+void FramePartsCollectorListener::OnGoAwayEnd() {
+ VLOG(1) << "OnGoAwayEnd";
+ EndFrame()->OnGoAwayEnd();
+}
+
+void FramePartsCollectorListener::OnWindowUpdate(
+ const Http2FrameHeader& header,
+ uint32_t window_size_increment) {
+ VLOG(1) << "OnWindowUpdate: " << header
+ << "; window_size_increment=" << window_size_increment;
+ EXPECT_EQ(Http2FrameType::WINDOW_UPDATE, header.type);
+ StartAndEndFrame(header)->OnWindowUpdate(header, window_size_increment);
+}
+
+void FramePartsCollectorListener::OnAltSvcStart(const Http2FrameHeader& header,
+ size_t origin_length,
+ size_t value_length) {
+ VLOG(1) << "OnAltSvcStart header: " << header
+ << "; origin_length=" << origin_length
+ << "; value_length=" << value_length;
+ StartFrame(header)->OnAltSvcStart(header, origin_length, value_length);
+}
+
+void FramePartsCollectorListener::OnAltSvcOriginData(const char* data,
+ size_t len) {
+ VLOG(1) << "OnAltSvcOriginData: len=" << len;
+ CurrentFrame()->OnAltSvcOriginData(data, len);
+}
+
+void FramePartsCollectorListener::OnAltSvcValueData(const char* data,
+ size_t len) {
+ VLOG(1) << "OnAltSvcValueData: len=" << len;
+ CurrentFrame()->OnAltSvcValueData(data, len);
+}
+
+void FramePartsCollectorListener::OnAltSvcEnd() {
+ VLOG(1) << "OnAltSvcEnd";
+ EndFrame()->OnAltSvcEnd();
+}
+
+void FramePartsCollectorListener::OnUnknownStart(
+ const Http2FrameHeader& header) {
+ VLOG(1) << "OnUnknownStart: " << header;
+ StartFrame(header)->OnUnknownStart(header);
+}
+
+void FramePartsCollectorListener::OnUnknownPayload(const char* data,
+ size_t len) {
+ VLOG(1) << "OnUnknownPayload: len=" << len;
+ CurrentFrame()->OnUnknownPayload(data, len);
+}
+
+void FramePartsCollectorListener::OnUnknownEnd() {
+ VLOG(1) << "OnUnknownEnd";
+ EndFrame()->OnUnknownEnd();
+}
+
+void FramePartsCollectorListener::OnPaddingTooLong(
+ const Http2FrameHeader& header,
+ size_t missing_length) {
+ VLOG(1) << "OnPaddingTooLong: " << header
+ << " missing_length: " << missing_length;
+ EndFrame()->OnPaddingTooLong(header, missing_length);
+}
+
+void FramePartsCollectorListener::OnFrameSizeError(
+ const Http2FrameHeader& header) {
+ VLOG(1) << "OnFrameSizeError: " << header;
+ FrameError(header)->OnFrameSizeError(header);
+}
+
+} // namespace test
+} // namespace net
diff --git a/chromium/net/http2/decoder/frame_parts_collector_listener.h b/chromium/net/http2/decoder/frame_parts_collector_listener.h
new file mode 100644
index 00000000000..89b7fed1027
--- /dev/null
+++ b/chromium/net/http2/decoder/frame_parts_collector_listener.h
@@ -0,0 +1,83 @@
+// Copyright 2016 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.
+
+#ifndef NET_HTTP2_DECODER_FRAME_PARTS_COLLECTOR_LISTENER_H_
+#define NET_HTTP2_DECODER_FRAME_PARTS_COLLECTOR_LISTENER_H_
+
+// FramePartsCollectorListener extends FramePartsCollector with an
+// implementation of every method of Http2FrameDecoderListener; it is
+// essentially the union of all the Listener classes in the tests of the
+// payload decoders (i.e. in ./payload_decoders/*_test.cc files), with the
+// addition of the OnFrameHeader method.
+// FramePartsCollectorListener supports tests of Http2FrameDecoder.
+
+#include <stddef.h>
+
+#include "net/http2/decoder/frame_parts_collector.h"
+#include "net/http2/decoder/http2_frame_decoder_listener.h"
+#include "net/http2/http2_constants.h"
+#include "net/http2/http2_structures.h"
+
+namespace net {
+namespace test {
+
+class FramePartsCollectorListener : public FramePartsCollector {
+ public:
+ FramePartsCollectorListener() {}
+ ~FramePartsCollectorListener() override {}
+
+ // TODO(jamessynge): Remove OnFrameHeader once done with supporting
+ // SpdyFramer's exact states.
+ bool OnFrameHeader(const Http2FrameHeader& header) override;
+ void OnDataStart(const Http2FrameHeader& header) override;
+ void OnDataPayload(const char* data, size_t len) override;
+ void OnDataEnd() override;
+ void OnHeadersStart(const Http2FrameHeader& header) override;
+ void OnHeadersPriority(const Http2PriorityFields& priority) override;
+ void OnHpackFragment(const char* data, size_t len) override;
+ void OnHeadersEnd() override;
+ void OnPriorityFrame(const Http2FrameHeader& header,
+ const Http2PriorityFields& priority_fields) override;
+ void OnContinuationStart(const Http2FrameHeader& header) override;
+ void OnContinuationEnd() override;
+ void OnPadLength(size_t pad_length) override;
+ void OnPadding(const char* padding, size_t skipped_length) override;
+ void OnRstStream(const Http2FrameHeader& header,
+ Http2ErrorCode error_code) override;
+ void OnSettingsStart(const Http2FrameHeader& header) override;
+ void OnSetting(const Http2SettingFields& setting_fields) override;
+ void OnSettingsEnd() override;
+ void OnSettingsAck(const Http2FrameHeader& header) override;
+ void OnPushPromiseStart(const Http2FrameHeader& header,
+ const Http2PushPromiseFields& promise,
+ size_t total_padding_length) override;
+ void OnPushPromiseEnd() override;
+ void OnPing(const Http2FrameHeader& header,
+ const Http2PingFields& ping) override;
+ void OnPingAck(const Http2FrameHeader& header,
+ const Http2PingFields& ping) override;
+ void OnGoAwayStart(const Http2FrameHeader& header,
+ const Http2GoAwayFields& goaway) override;
+ void OnGoAwayOpaqueData(const char* data, size_t len) override;
+ void OnGoAwayEnd() override;
+ void OnWindowUpdate(const Http2FrameHeader& header,
+ uint32_t window_size_increment) override;
+ void OnAltSvcStart(const Http2FrameHeader& header,
+ size_t origin_length,
+ size_t value_length) override;
+ void OnAltSvcOriginData(const char* data, size_t len) override;
+ void OnAltSvcValueData(const char* data, size_t len) override;
+ void OnAltSvcEnd() override;
+ void OnUnknownStart(const Http2FrameHeader& header) override;
+ void OnUnknownPayload(const char* data, size_t len) override;
+ void OnUnknownEnd() override;
+ void OnPaddingTooLong(const Http2FrameHeader& header,
+ size_t missing_length) override;
+ void OnFrameSizeError(const Http2FrameHeader& header) override;
+};
+
+} // namespace test
+} // namespace net
+
+#endif // NET_HTTP2_DECODER_FRAME_PARTS_COLLECTOR_LISTENER_H_
diff --git a/chromium/net/http2/decoder/http2_frame_decoder.cc b/chromium/net/http2/decoder/http2_frame_decoder.cc
new file mode 100644
index 00000000000..fe24f91644c
--- /dev/null
+++ b/chromium/net/http2/decoder/http2_frame_decoder.cc
@@ -0,0 +1,426 @@
+// Copyright 2016 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.
+
+#include "net/http2/decoder/http2_frame_decoder.h"
+
+#include "net/http2/http2_constants.h"
+
+namespace net {
+
+std::ostream& operator<<(std::ostream& out, Http2FrameDecoder::State v) {
+ switch (v) {
+ case Http2FrameDecoder::State::kStartDecodingHeader:
+ return out << "kStartDecodingHeader";
+ case Http2FrameDecoder::State::kResumeDecodingHeader:
+ return out << "kResumeDecodingHeader";
+ case Http2FrameDecoder::State::kResumeDecodingPayload:
+ return out << "kResumeDecodingPayload";
+ case Http2FrameDecoder::State::kDiscardPayload:
+ return out << "kDiscardPayload";
+ }
+ return out << static_cast<int>(v);
+}
+
+Http2FrameDecoder::Http2FrameDecoder(Http2FrameDecoderListener* listener)
+ : state_(State::kStartDecodingHeader),
+ maximum_payload_size_(Http2SettingsInfo::DefaultMaxFrameSize()) {
+ set_listener(listener);
+}
+
+void Http2FrameDecoder::set_listener(Http2FrameDecoderListener* listener) {
+ if (listener == nullptr) {
+ listener = &no_op_listener_;
+ }
+ frame_decoder_state_.set_listener(listener);
+}
+
+Http2FrameDecoderListener* Http2FrameDecoder::listener() const {
+ return frame_decoder_state_.listener();
+}
+
+DecodeStatus Http2FrameDecoder::DecodeFrame(DecodeBuffer* db) {
+ DVLOG(2) << "Http2FrameDecoder::DecodeFrame state=" << state_;
+ switch (state_) {
+ case State::kStartDecodingHeader:
+ if (frame_decoder_state_.StartDecodingFrameHeader(db)) {
+ return StartDecodingPayload(db);
+ }
+ state_ = State::kResumeDecodingHeader;
+ return DecodeStatus::kDecodeInProgress;
+
+ case State::kResumeDecodingHeader:
+ if (frame_decoder_state_.ResumeDecodingFrameHeader(db)) {
+ return StartDecodingPayload(db);
+ }
+ return DecodeStatus::kDecodeInProgress;
+
+ case State::kResumeDecodingPayload:
+ return ResumeDecodingPayload(db);
+
+ case State::kDiscardPayload:
+ return DiscardPayload(db);
+ }
+
+ NOTREACHED();
+ return DecodeStatus::kDecodeError;
+}
+
+size_t Http2FrameDecoder::remaining_payload() const {
+ return frame_decoder_state_.remaining_payload();
+}
+
+uint32_t Http2FrameDecoder::remaining_padding() const {
+ return frame_decoder_state_.remaining_padding();
+}
+
+DecodeStatus Http2FrameDecoder::StartDecodingPayload(DecodeBuffer* db) {
+ const Http2FrameHeader& header = frame_header();
+
+ // TODO(jamessynge): Remove OnFrameHeader once done with supporting
+ // SpdyFramer's exact states.
+ if (!listener()->OnFrameHeader(header)) {
+ DVLOG(2) << "OnFrameHeader rejected the frame, will discard; header: "
+ << header;
+ state_ = State::kDiscardPayload;
+ frame_decoder_state_.InitializeRemainders();
+ return DecodeStatus::kDecodeError;
+ }
+
+ if (header.payload_length > maximum_payload_size_) {
+ DVLOG(2) << "Payload length is greater than allowed: "
+ << header.payload_length << " > " << maximum_payload_size_
+ << "\n header: " << header;
+ state_ = State::kDiscardPayload;
+ frame_decoder_state_.InitializeRemainders();
+ listener()->OnFrameSizeError(header);
+ return DecodeStatus::kDecodeError;
+ }
+
+ // The decode buffer can extend across many frames. Make sure that the
+ // buffer we pass to the start method that is specific to the frame type
+ // does not exend beyond this frame.
+ DecodeBufferSubset subset(db, header.payload_length);
+ DecodeStatus status;
+ switch (header.type) {
+ case Http2FrameType::DATA:
+ status = StartDecodingDataPayload(&subset);
+ break;
+
+ case Http2FrameType::HEADERS:
+ status = StartDecodingHeadersPayload(&subset);
+ break;
+
+ case Http2FrameType::PRIORITY:
+ status = StartDecodingPriorityPayload(&subset);
+ break;
+
+ case Http2FrameType::RST_STREAM:
+ status = StartDecodingRstStreamPayload(&subset);
+ break;
+
+ case Http2FrameType::SETTINGS:
+ status = StartDecodingSettingsPayload(&subset);
+ break;
+
+ case Http2FrameType::PUSH_PROMISE:
+ status = StartDecodingPushPromisePayload(&subset);
+ break;
+
+ case Http2FrameType::PING:
+ status = StartDecodingPingPayload(&subset);
+ break;
+
+ case Http2FrameType::GOAWAY:
+ status = StartDecodingGoAwayPayload(&subset);
+ break;
+
+ case Http2FrameType::WINDOW_UPDATE:
+ status = StartDecodingWindowUpdatePayload(&subset);
+ break;
+
+ case Http2FrameType::CONTINUATION:
+ status = StartDecodingContinuationPayload(&subset);
+ break;
+
+ case Http2FrameType::ALTSVC:
+ status = StartDecodingAltSvcPayload(&subset);
+ break;
+
+ default:
+ status = StartDecodingUnknownPayload(&subset);
+ break;
+ }
+
+ if (status == DecodeStatus::kDecodeDone) {
+ state_ = State::kStartDecodingHeader;
+ return status;
+ } else if (status == DecodeStatus::kDecodeInProgress) {
+ state_ = State::kResumeDecodingPayload;
+ return status;
+ } else {
+ state_ = State::kDiscardPayload;
+ return status;
+ }
+}
+
+DecodeStatus Http2FrameDecoder::ResumeDecodingPayload(DecodeBuffer* db) {
+ // The decode buffer can extend across many frames. Make sure that the
+ // buffer we pass to the start method that is specific to the frame type
+ // does not exend beyond this frame.
+ size_t remaining = frame_decoder_state_.remaining_total_payload();
+ DCHECK_LE(remaining, frame_header().payload_length);
+ DecodeBufferSubset subset(db, remaining);
+ DecodeStatus status;
+ switch (frame_header().type) {
+ case Http2FrameType::DATA:
+ status = ResumeDecodingDataPayload(&subset);
+ break;
+
+ case Http2FrameType::HEADERS:
+ status = ResumeDecodingHeadersPayload(&subset);
+ break;
+
+ case Http2FrameType::PRIORITY:
+ status = ResumeDecodingPriorityPayload(&subset);
+ break;
+
+ case Http2FrameType::RST_STREAM:
+ status = ResumeDecodingRstStreamPayload(&subset);
+ break;
+
+ case Http2FrameType::SETTINGS:
+ status = ResumeDecodingSettingsPayload(&subset);
+ break;
+
+ case Http2FrameType::PUSH_PROMISE:
+ status = ResumeDecodingPushPromisePayload(&subset);
+ break;
+
+ case Http2FrameType::PING:
+ status = ResumeDecodingPingPayload(&subset);
+ break;
+
+ case Http2FrameType::GOAWAY:
+ status = ResumeDecodingGoAwayPayload(&subset);
+ break;
+
+ case Http2FrameType::WINDOW_UPDATE:
+ status = ResumeDecodingWindowUpdatePayload(&subset);
+ break;
+
+ case Http2FrameType::CONTINUATION:
+ status = ResumeDecodingContinuationPayload(&subset);
+ break;
+
+ case Http2FrameType::ALTSVC:
+ status = ResumeDecodingAltSvcPayload(&subset);
+ break;
+
+ default:
+ status = ResumeDecodingUnknownPayload(&subset);
+ break;
+ }
+
+ if (status == DecodeStatus::kDecodeDone) {
+ state_ = State::kStartDecodingHeader;
+ return status;
+ } else if (status == DecodeStatus::kDecodeInProgress) {
+ return status;
+ } else {
+ state_ = State::kDiscardPayload;
+ return status;
+ }
+}
+
+// Clear any of the flags in the frame header that aren't set in valid_flags.
+void Http2FrameDecoder::RetainFlags(uint8_t valid_flags) {
+ frame_decoder_state_.RetainFlags(valid_flags);
+}
+
+// Clear all of the flags in the frame header; for use with frame types that
+// don't define any flags, such as WINDOW_UPDATE.
+void Http2FrameDecoder::ClearFlags() {
+ frame_decoder_state_.ClearFlags();
+}
+
+DecodeStatus Http2FrameDecoder::StartDecodingAltSvcPayload(DecodeBuffer* db) {
+ ClearFlags();
+ return altsvc_payload_decoder_.StartDecodingPayload(&frame_decoder_state_,
+ db);
+}
+DecodeStatus Http2FrameDecoder::ResumeDecodingAltSvcPayload(DecodeBuffer* db) {
+ // The frame is not paddable.
+ DCHECK_EQ(frame_decoder_state_.remaining_total_payload(),
+ frame_decoder_state_.remaining_payload());
+ return altsvc_payload_decoder_.ResumeDecodingPayload(&frame_decoder_state_,
+ db);
+}
+
+DecodeStatus Http2FrameDecoder::StartDecodingContinuationPayload(
+ DecodeBuffer* db) {
+ RetainFlags(Http2FrameFlag::FLAG_END_HEADERS);
+ return continuation_payload_decoder_.StartDecodingPayload(
+ &frame_decoder_state_, db);
+}
+DecodeStatus Http2FrameDecoder::ResumeDecodingContinuationPayload(
+ DecodeBuffer* db) {
+ // The frame is not paddable.
+ DCHECK_EQ(frame_decoder_state_.remaining_total_payload(),
+ frame_decoder_state_.remaining_payload());
+ return continuation_payload_decoder_.ResumeDecodingPayload(
+ &frame_decoder_state_, db);
+}
+
+DecodeStatus Http2FrameDecoder::StartDecodingDataPayload(DecodeBuffer* db) {
+ RetainFlags(Http2FrameFlag::FLAG_END_STREAM | Http2FrameFlag::FLAG_PADDED);
+ return data_payload_decoder_.StartDecodingPayload(&frame_decoder_state_, db);
+}
+DecodeStatus Http2FrameDecoder::ResumeDecodingDataPayload(DecodeBuffer* db) {
+ return data_payload_decoder_.ResumeDecodingPayload(&frame_decoder_state_, db);
+}
+
+DecodeStatus Http2FrameDecoder::StartDecodingGoAwayPayload(DecodeBuffer* db) {
+ ClearFlags();
+ return goaway_payload_decoder_.StartDecodingPayload(&frame_decoder_state_,
+ db);
+}
+DecodeStatus Http2FrameDecoder::ResumeDecodingGoAwayPayload(DecodeBuffer* db) {
+ // The frame is not paddable.
+ DCHECK_EQ(frame_decoder_state_.remaining_total_payload(),
+ frame_decoder_state_.remaining_payload());
+ return goaway_payload_decoder_.ResumeDecodingPayload(&frame_decoder_state_,
+ db);
+}
+
+DecodeStatus Http2FrameDecoder::StartDecodingHeadersPayload(DecodeBuffer* db) {
+ RetainFlags(Http2FrameFlag::FLAG_END_STREAM |
+ Http2FrameFlag::FLAG_END_HEADERS | Http2FrameFlag::FLAG_PADDED |
+ Http2FrameFlag::FLAG_PRIORITY);
+ return headers_payload_decoder_.StartDecodingPayload(&frame_decoder_state_,
+ db);
+}
+DecodeStatus Http2FrameDecoder::ResumeDecodingHeadersPayload(DecodeBuffer* db) {
+ DCHECK_LE(frame_decoder_state_.remaining_payload_and_padding(),
+ frame_header().payload_length);
+ return headers_payload_decoder_.ResumeDecodingPayload(&frame_decoder_state_,
+ db);
+}
+
+DecodeStatus Http2FrameDecoder::StartDecodingPingPayload(DecodeBuffer* db) {
+ RetainFlags(Http2FrameFlag::FLAG_ACK);
+ return ping_payload_decoder_.StartDecodingPayload(&frame_decoder_state_, db);
+}
+DecodeStatus Http2FrameDecoder::ResumeDecodingPingPayload(DecodeBuffer* db) {
+ // The frame is not paddable.
+ DCHECK_EQ(frame_decoder_state_.remaining_total_payload(),
+ frame_decoder_state_.remaining_payload());
+ return ping_payload_decoder_.ResumeDecodingPayload(&frame_decoder_state_, db);
+}
+
+DecodeStatus Http2FrameDecoder::StartDecodingPriorityPayload(DecodeBuffer* db) {
+ ClearFlags();
+ return priority_payload_decoder_.StartDecodingPayload(&frame_decoder_state_,
+ db);
+}
+DecodeStatus Http2FrameDecoder::ResumeDecodingPriorityPayload(
+ DecodeBuffer* db) {
+ // The frame is not paddable.
+ DCHECK_EQ(frame_decoder_state_.remaining_total_payload(),
+ frame_decoder_state_.remaining_payload());
+ return priority_payload_decoder_.ResumeDecodingPayload(&frame_decoder_state_,
+ db);
+}
+
+DecodeStatus Http2FrameDecoder::StartDecodingPushPromisePayload(
+ DecodeBuffer* db) {
+ RetainFlags(Http2FrameFlag::FLAG_END_HEADERS | Http2FrameFlag::FLAG_PADDED);
+ return push_promise_payload_decoder_.StartDecodingPayload(
+ &frame_decoder_state_, db);
+}
+DecodeStatus Http2FrameDecoder::ResumeDecodingPushPromisePayload(
+ DecodeBuffer* db) {
+ DCHECK_LE(frame_decoder_state_.remaining_payload_and_padding(),
+ frame_header().payload_length);
+ return push_promise_payload_decoder_.ResumeDecodingPayload(
+ &frame_decoder_state_, db);
+}
+
+DecodeStatus Http2FrameDecoder::StartDecodingRstStreamPayload(
+ DecodeBuffer* db) {
+ ClearFlags();
+ return rst_stream_payload_decoder_.StartDecodingPayload(&frame_decoder_state_,
+ db);
+}
+DecodeStatus Http2FrameDecoder::ResumeDecodingRstStreamPayload(
+ DecodeBuffer* db) {
+ // The frame is not paddable.
+ DCHECK_EQ(frame_decoder_state_.remaining_total_payload(),
+ frame_decoder_state_.remaining_payload());
+ return rst_stream_payload_decoder_.ResumeDecodingPayload(
+ &frame_decoder_state_, db);
+}
+
+DecodeStatus Http2FrameDecoder::StartDecodingSettingsPayload(DecodeBuffer* db) {
+ RetainFlags(Http2FrameFlag::FLAG_ACK);
+ return settings_payload_decoder_.StartDecodingPayload(&frame_decoder_state_,
+ db);
+}
+DecodeStatus Http2FrameDecoder::ResumeDecodingSettingsPayload(
+ DecodeBuffer* db) {
+ // The frame is not paddable.
+ DCHECK_EQ(frame_decoder_state_.remaining_total_payload(),
+ frame_decoder_state_.remaining_payload());
+ return settings_payload_decoder_.ResumeDecodingPayload(&frame_decoder_state_,
+ db);
+}
+
+DecodeStatus Http2FrameDecoder::StartDecodingUnknownPayload(DecodeBuffer* db) {
+ // We don't known what type of frame this is, so we don't know which flags
+ // are valid, so we don't touch them.
+ return unknown_payload_decoder_.StartDecodingPayload(&frame_decoder_state_,
+ db);
+}
+DecodeStatus Http2FrameDecoder::ResumeDecodingUnknownPayload(DecodeBuffer* db) {
+ // We don't known what type of frame this is, so we treat it as not paddable.
+ DCHECK_EQ(frame_decoder_state_.remaining_total_payload(),
+ frame_decoder_state_.remaining_payload());
+ return unknown_payload_decoder_.ResumeDecodingPayload(&frame_decoder_state_,
+ db);
+}
+
+DecodeStatus Http2FrameDecoder::StartDecodingWindowUpdatePayload(
+ DecodeBuffer* db) {
+ ClearFlags();
+ return window_update_payload_decoder_.StartDecodingPayload(
+ &frame_decoder_state_, db);
+}
+DecodeStatus Http2FrameDecoder::ResumeDecodingWindowUpdatePayload(
+ DecodeBuffer* db) {
+ // The frame is not paddable.
+ DCHECK_EQ(frame_decoder_state_.remaining_total_payload(),
+ frame_decoder_state_.remaining_payload());
+ return window_update_payload_decoder_.ResumeDecodingPayload(
+ &frame_decoder_state_, db);
+}
+
+DecodeStatus Http2FrameDecoder::DiscardPayload(DecodeBuffer* db) {
+ DVLOG(2) << "remaining_payload=" << frame_decoder_state_.remaining_payload_
+ << "; remaining_padding=" << frame_decoder_state_.remaining_padding_;
+ frame_decoder_state_.remaining_payload_ +=
+ frame_decoder_state_.remaining_padding_;
+ frame_decoder_state_.remaining_padding_ = 0;
+ const size_t avail = frame_decoder_state_.AvailablePayload(db);
+ DVLOG(2) << "avail=" << avail;
+ if (avail > 0) {
+ frame_decoder_state_.ConsumePayload(avail);
+ db->AdvanceCursor(avail);
+ }
+ if (frame_decoder_state_.remaining_payload_ == 0) {
+ state_ = State::kStartDecodingHeader;
+ return DecodeStatus::kDecodeDone;
+ }
+ return DecodeStatus::kDecodeInProgress;
+}
+
+} // namespace net
diff --git a/chromium/net/http2/decoder/http2_frame_decoder.h b/chromium/net/http2/decoder/http2_frame_decoder.h
new file mode 100644
index 00000000000..f440993a3b6
--- /dev/null
+++ b/chromium/net/http2/decoder/http2_frame_decoder.h
@@ -0,0 +1,203 @@
+// Copyright 2016 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.
+
+#ifndef NET_HTTP2_DECODER_HTTP2_FRAME_DECODER_H_
+#define NET_HTTP2_DECODER_HTTP2_FRAME_DECODER_H_
+
+// Http2FrameDecoder decodes the available input until it reaches the end of
+// the input or it reaches the end of the first frame in the input.
+// Note that Http2FrameDecoder does only minimal validation; for example,
+// stream ids are not checked, nor is the sequence of frames such as
+// CONTINUATION frame placement.
+//
+// Http2FrameDecoder enters state kError once it has called the listener's
+// OnFrameSizeError or OnPaddingTooLong methods, and at this time has no
+// provision for leaving that state. While the HTTP/2 spec (RFC7540) allows
+// for some such errors to be considered as just stream errors in some cases,
+// this implementation treats them all as connection errors.
+
+#include <stddef.h>
+
+#include "base/logging.h"
+#include "base/macros.h"
+#include "net/base/net_export.h"
+#include "net/http2/decoder/decode_buffer.h"
+#include "net/http2/decoder/decode_status.h"
+#include "net/http2/decoder/frame_decoder_state.h"
+#include "net/http2/decoder/http2_frame_decoder_listener.h"
+#include "net/http2/decoder/payload_decoders/altsvc_payload_decoder.h"
+#include "net/http2/decoder/payload_decoders/continuation_payload_decoder.h"
+#include "net/http2/decoder/payload_decoders/data_payload_decoder.h"
+#include "net/http2/decoder/payload_decoders/goaway_payload_decoder.h"
+#include "net/http2/decoder/payload_decoders/headers_payload_decoder.h"
+#include "net/http2/decoder/payload_decoders/ping_payload_decoder.h"
+#include "net/http2/decoder/payload_decoders/priority_payload_decoder.h"
+#include "net/http2/decoder/payload_decoders/push_promise_payload_decoder.h"
+#include "net/http2/decoder/payload_decoders/rst_stream_payload_decoder.h"
+#include "net/http2/decoder/payload_decoders/settings_payload_decoder.h"
+#include "net/http2/decoder/payload_decoders/unknown_payload_decoder.h"
+#include "net/http2/decoder/payload_decoders/window_update_payload_decoder.h"
+#include "net/http2/http2_structures.h"
+
+namespace net {
+namespace test {
+class Http2FrameDecoderPeer;
+} // namespace test
+
+class NET_EXPORT_PRIVATE Http2FrameDecoder {
+ public:
+ explicit Http2FrameDecoder(Http2FrameDecoderListener* listener);
+ Http2FrameDecoder() : Http2FrameDecoder(nullptr) {}
+
+ // The decoder will call the listener's methods as it decodes a frame.
+ void set_listener(Http2FrameDecoderListener* listener);
+ Http2FrameDecoderListener* listener() const;
+
+ // The decoder will reject frame's whose payload
+ // length field exceeds the maximum payload size.
+ void set_maximum_payload_size(size_t v) { maximum_payload_size_ = v; }
+ size_t maximum_payload_size() const { return maximum_payload_size_; }
+
+ // Decodes the input up to the next frame boundary (i.e. at most one frame).
+ //
+ // Returns kDecodeDone if it decodes the final byte of a frame, OR if there
+ // is no input and it is awaiting the start of a new frame (e.g. if this
+ // is the first call to DecodeFrame, or if the previous call returned
+ // kDecodeDone).
+ //
+ // Returns kDecodeInProgress if it decodes all of the decode buffer, but has
+ // not reached the end of the frame.
+ //
+ // Returns kDecodeError if the frame's padding or length wasn't valid (i.e. if
+ // the decoder called either the listener's OnPaddingTooLong or
+ // OnFrameSizeError method).
+ DecodeStatus DecodeFrame(DecodeBuffer* db);
+
+ //////////////////////////////////////////////////////////////////////////////
+ // Methods that support Http2FrameDecoderAdapter.
+
+ // Is the remainder of the frame's payload being discarded?
+ bool IsDiscardingPayload() const { return state_ == State::kDiscardPayload; }
+
+ // Returns the number of bytes of the frame's payload that remain to be
+ // decoded, excluding any trailing padding. This method must only be called
+ // after the frame header has been decoded AND DecodeFrame has returned
+ // kDecodeInProgress.
+ size_t remaining_payload() const;
+
+ // Returns the number of bytes of trailing padding after the payload that
+ // remain to be decoded. This method must only be called if the frame type
+ // allows padding, and after the frame header has been decoded AND
+ // DecodeFrame has returned. Will return 0 if the Pad Length field has not
+ // yet been decoded.
+ uint32_t remaining_padding() const;
+
+ private:
+ enum class State {
+ // Ready to start decoding a new frame's header.
+ kStartDecodingHeader,
+ // Was in state kStartDecodingHeader, but unable to read the entire frame
+ // header, so needs more input to complete decoding the header.
+ kResumeDecodingHeader,
+
+ // Have decoded the frame header, and started decoding the available bytes
+ // of the frame's payload, but need more bytes to finish the job.
+ kResumeDecodingPayload,
+
+ // Decoding of the most recently started frame resulted in an error:
+ // OnPaddingTooLong or OnFrameSizeError was called to indicate that the
+ // decoder detected a problem, or OnFrameHeader returned false, indicating
+ // that the listener detected a problem. Regardless of which, the decoder
+ // will stay in state kDiscardPayload until it has been passed the rest
+ // of the bytes of the frame's payload that it hasn't yet seen, after
+ // which it will be ready to decode another frame.
+ kDiscardPayload,
+ };
+
+ friend class test::Http2FrameDecoderPeer;
+ friend std::ostream& operator<<(std::ostream& out, State v);
+
+ DecodeStatus StartDecodingPayload(DecodeBuffer* db);
+ DecodeStatus ResumeDecodingPayload(DecodeBuffer* db);
+ DecodeStatus DiscardPayload(DecodeBuffer* db);
+
+ const Http2FrameHeader& frame_header() const {
+ return frame_decoder_state_.frame_header();
+ }
+
+ // Clear any of the flags in the frame header that aren't set in valid_flags.
+ void RetainFlags(uint8_t valid_flags);
+
+ // Clear all of the flags in the frame header; for use with frame types that
+ // don't define any flags, such as WINDOW_UPDATE.
+ void ClearFlags();
+
+ // These methods call the StartDecodingPayload() method of the frame type's
+ // payload decoder, after first clearing invalid flags in the header. The
+ // caller must ensure that the decode buffer does not extend beyond the
+ // end of the payload (handled by Http2FrameDecoder::StartDecodingPayload).
+ DecodeStatus StartDecodingAltSvcPayload(DecodeBuffer* db);
+ DecodeStatus StartDecodingContinuationPayload(DecodeBuffer* db);
+ DecodeStatus StartDecodingDataPayload(DecodeBuffer* db);
+ DecodeStatus StartDecodingGoAwayPayload(DecodeBuffer* db);
+ DecodeStatus StartDecodingHeadersPayload(DecodeBuffer* db);
+ DecodeStatus StartDecodingPingPayload(DecodeBuffer* db);
+ DecodeStatus StartDecodingPriorityPayload(DecodeBuffer* db);
+ DecodeStatus StartDecodingPushPromisePayload(DecodeBuffer* db);
+ DecodeStatus StartDecodingRstStreamPayload(DecodeBuffer* db);
+ DecodeStatus StartDecodingSettingsPayload(DecodeBuffer* db);
+ DecodeStatus StartDecodingUnknownPayload(DecodeBuffer* db);
+ DecodeStatus StartDecodingWindowUpdatePayload(DecodeBuffer* db);
+
+ // These methods call the ResumeDecodingPayload() method of the frame type's
+ // payload decoder; they are called only if the preceding call to the
+ // corresponding Start method (above) returned kDecodeInProgress, as did any
+ // subsequent calls to the resume method.
+ // Unlike the Start methods, the decode buffer may extend beyond the
+ // end of the payload, so the method will create a DecodeBufferSubset
+ // before calling the ResumeDecodingPayload method of the frame type's
+ // payload decoder.
+ DecodeStatus ResumeDecodingAltSvcPayload(DecodeBuffer* db);
+ DecodeStatus ResumeDecodingContinuationPayload(DecodeBuffer* db);
+ DecodeStatus ResumeDecodingDataPayload(DecodeBuffer* db);
+ DecodeStatus ResumeDecodingGoAwayPayload(DecodeBuffer* db);
+ DecodeStatus ResumeDecodingHeadersPayload(DecodeBuffer* db);
+ DecodeStatus ResumeDecodingPingPayload(DecodeBuffer* db);
+ DecodeStatus ResumeDecodingPriorityPayload(DecodeBuffer* db);
+ DecodeStatus ResumeDecodingPushPromisePayload(DecodeBuffer* db);
+ DecodeStatus ResumeDecodingRstStreamPayload(DecodeBuffer* db);
+ DecodeStatus ResumeDecodingSettingsPayload(DecodeBuffer* db);
+ DecodeStatus ResumeDecodingUnknownPayload(DecodeBuffer* db);
+ DecodeStatus ResumeDecodingWindowUpdatePayload(DecodeBuffer* db);
+
+ FrameDecoderState frame_decoder_state_;
+
+ // We only need one payload decoder at a time, so they share the same storage.
+ union {
+ AltSvcPayloadDecoder altsvc_payload_decoder_;
+ ContinuationPayloadDecoder continuation_payload_decoder_;
+ DataPayloadDecoder data_payload_decoder_;
+ GoAwayPayloadDecoder goaway_payload_decoder_;
+ HeadersPayloadDecoder headers_payload_decoder_;
+ PingPayloadDecoder ping_payload_decoder_;
+ PriorityPayloadDecoder priority_payload_decoder_;
+ PushPromisePayloadDecoder push_promise_payload_decoder_;
+ RstStreamPayloadDecoder rst_stream_payload_decoder_;
+ SettingsPayloadDecoder settings_payload_decoder_;
+ UnknownPayloadDecoder unknown_payload_decoder_;
+ WindowUpdatePayloadDecoder window_update_payload_decoder_;
+ };
+
+ State state_;
+ size_t maximum_payload_size_;
+
+ // Listener used whenever caller passes nullptr to set_listener.
+ Http2FrameDecoderNoOpListener no_op_listener_;
+
+ DISALLOW_COPY_AND_ASSIGN(Http2FrameDecoder);
+};
+
+} // namespace net
+
+#endif // NET_HTTP2_DECODER_HTTP2_FRAME_DECODER_H_
diff --git a/chromium/net/http2/decoder/http2_frame_decoder_listener.cc b/chromium/net/http2/decoder/http2_frame_decoder_listener.cc
new file mode 100644
index 00000000000..bf62ae4fe25
--- /dev/null
+++ b/chromium/net/http2/decoder/http2_frame_decoder_listener.cc
@@ -0,0 +1,14 @@
+// Copyright 2016 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.
+
+#include "net/http2/decoder/http2_frame_decoder_listener.h"
+
+namespace net {
+
+bool Http2FrameDecoderNoOpListener::OnFrameHeader(
+ const Http2FrameHeader& header) {
+ return true;
+}
+
+} // namespace net
diff --git a/chromium/net/http2/decoder/http2_frame_decoder_listener.h b/chromium/net/http2/decoder/http2_frame_decoder_listener.h
new file mode 100644
index 00000000000..3345ab6f3c2
--- /dev/null
+++ b/chromium/net/http2/decoder/http2_frame_decoder_listener.h
@@ -0,0 +1,356 @@
+// Copyright 2016 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.
+
+#ifndef NET_HTTP2_DECODER_HTTP2_FRAME_DECODER_LISTENER_H_
+#define NET_HTTP2_DECODER_HTTP2_FRAME_DECODER_LISTENER_H_
+
+// Http2FrameDecoderListener is the interface which the HTTP/2 decoder uses
+// to report the decoded frames to a listener.
+//
+// The general design is to assume that the listener will copy the data it needs
+// (e.g. frame headers) and will keep track of the implicit state of the
+// decoding process (i.e. the decoder maintains just the information it needs in
+// order to perform the decoding). Therefore, the parameters are just those with
+// (potentially) new data, not previously provided info about the current frame.
+//
+// The calls are described as if they are made in quick succession, i.e. one
+// after another, but of course the decoder needs input to decode, and the
+// decoder will only call the listener once the necessary input has been
+// provided. For example: OnDataStart can only be called once the 9 bytes of
+// of an HTTP/2 common frame header have been received. The decoder will call
+// the listener methods as soon as possible to avoid almost all buffering.
+//
+// The listener interface is designed so that it is possible to exactly
+// reconstruct the serialized frames, with the exception of reserved bits,
+// including in the frame header's flags and stream_id fields, which will have
+// been cleared before the methods below are called.
+
+#include <stddef.h>
+
+#include <type_traits>
+
+#include "net/http2/http2_constants.h"
+#include "net/http2/http2_structures.h"
+
+namespace net {
+
+// TODO(jamessynge): Consider sorting the methods by frequency of call, if that
+// helps at all.
+class Http2FrameDecoderListener {
+ public:
+ Http2FrameDecoderListener() {}
+ virtual ~Http2FrameDecoderListener() {}
+
+ // Called once the common frame header has been decoded for any frame, and
+ // before any of the methods below, which will also be called. This method is
+ // included in this interface only for the purpose of supporting SpdyFramer
+ // semantics via an adapter. This is the only method that has a non-void
+ // return type, and this is just so that Http2FrameDecoderAdapter (called
+ // from SpdyFramer) can more readily pass existing tests that expect decoding
+ // to stop if the headers alone indicate an error. Return false to stop
+ // decoding just after decoding the header, else return true to continue
+ // decoding.
+ // TODO(jamessynge): Remove OnFrameHeader once done with supporting
+ // SpdyFramer's exact states.
+ virtual bool OnFrameHeader(const Http2FrameHeader& header) = 0;
+
+ //////////////////////////////////////////////////////////////////////////////
+
+ // Called once the common frame header has been decoded for a DATA frame,
+ // before examining the frame's payload, after which:
+ // OnPadLength will be called if header.IsPadded() is true, i.e. if the
+ // PADDED flag is set;
+ // OnDataPayload will be called as the non-padding portion of the payload
+ // is available until all of it has been provided;
+ // OnPadding will be called if the frame is padded AND the Pad Length field
+ // is greater than zero;
+ // OnDataEnd will be called last. If the frame is unpadded and has no
+ // payload, then this will be called immediately after OnDataStart.
+ virtual void OnDataStart(const Http2FrameHeader& header) = 0;
+
+ // Called when the next non-padding portion of a DATA frame's payload is
+ // received.
+ // |data| The start of |len| bytes of data.
+ // |len| The length of the data buffer. Maybe zero in some cases, which does
+ // not mean anything special.
+ virtual void OnDataPayload(const char* data, size_t len) = 0;
+
+ // Called after an entire DATA frame has been received.
+ // If header.IsEndStream() == true, this is the last data for the stream.
+ virtual void OnDataEnd() = 0;
+
+ // Called once the common frame header has been decoded for a HEADERS frame,
+ // before examining the frame's payload, after which:
+ // OnPadLength will be called if header.IsPadded() is true, i.e. if the
+ // PADDED flag is set;
+ // OnHeadersPriority will be called if header.HasPriority() is true, i.e. if
+ // the frame has the PRIORITY flag;
+ // OnHpackFragment as the remainder of the non-padding payload is available
+ // until all if has been provided;
+ // OnPadding will be called if the frame is padded AND the Pad Length field
+ // is greater than zero;
+ // OnHeadersEnd will be called last; If the frame is unpadded and has no
+ // payload, then this will be called immediately after OnHeadersStart;
+ // OnHeadersEnd indicates the end of the HPACK block only if the frame
+ // header had the END_HEADERS flag set, else the END_HEADERS should be
+ // looked for on a subsequent CONTINUATION frame.
+ virtual void OnHeadersStart(const Http2FrameHeader& header) = 0;
+
+ // Called when a HEADERS frame is received with the PRIORITY flag set and
+ // the priority fields have been decoded.
+ virtual void OnHeadersPriority(
+ const Http2PriorityFields& priority_fields) = 0;
+
+ // Called when a fragment (i.e. some or all of an HPACK Block) is received;
+ // this may be part of a HEADERS, PUSH_PROMISE or CONTINUATION frame.
+ // |data| The start of |len| bytes of data.
+ // |len| The length of the data buffer. Maybe zero in some cases, which does
+ // not mean anything special, except that it simplified the decoder.
+ virtual void OnHpackFragment(const char* data, size_t len) = 0;
+
+ // Called after an entire HEADERS frame has been received. The frame is the
+ // end of the HEADERS if the END_HEADERS flag is set; else there should be
+ // CONTINUATION frames after this frame.
+ virtual void OnHeadersEnd() = 0;
+
+ // Called when an entire PRIORITY frame has been decoded.
+ virtual void OnPriorityFrame(const Http2FrameHeader& header,
+ const Http2PriorityFields& priority_fields) = 0;
+
+ // Called once the common frame header has been decoded for a CONTINUATION
+ // frame, before examining the frame's payload, after which:
+ // OnHpackFragment as the frame's payload is available until all of it
+ // has been provided;
+ // OnContinuationEnd will be called last; If the frame has no payload,
+ // then this will be called immediately after OnContinuationStart;
+ // the HPACK block is at an end if and only if the frame header passed
+ // to OnContinuationStart had the END_HEADERS flag set.
+ virtual void OnContinuationStart(const Http2FrameHeader& header) = 0;
+
+ // Called after an entire CONTINUATION frame has been received. The frame is
+ // the end of the HEADERS if the END_HEADERS flag is set.
+ virtual void OnContinuationEnd() = 0;
+
+ // Called when Pad Length field has been read. Applies to DATA and HEADERS
+ // frames. For PUSH_PROMISE frames, the Pad Length + 1 is provided in the
+ // OnPushPromiseStart call as total_padding_length.
+ virtual void OnPadLength(size_t pad_length) = 0;
+
+ // Called when padding is skipped over.
+ virtual void OnPadding(const char* padding, size_t skipped_length) = 0;
+
+ // Called when an entire RST_STREAM frame has been decoded.
+ // This is the only callback for RST_STREAM frames.
+ virtual void OnRstStream(const Http2FrameHeader& header,
+ Http2ErrorCode error_code) = 0;
+
+ // Called once the common frame header has been decoded for a SETTINGS frame
+ // without the ACK flag, before examining the frame's payload, after which:
+ // OnSetting will be called in turn for each pair of settings parameter and
+ // value found in the payload;
+ // OnSettingsEnd will be called last; If the frame has no payload,
+ // then this will be called immediately after OnSettingsStart.
+ // The frame header is passed so that the caller can check the stream_id,
+ // which should be zero, but that hasn't been checked by the decoder.
+ virtual void OnSettingsStart(const Http2FrameHeader& header) = 0;
+
+ // Called for each setting parameter and value within a SETTINGS frame.
+ virtual void OnSetting(const Http2SettingFields& setting_fields) = 0;
+
+ // Called after parsing the complete payload of SETTINGS frame (non-ACK).
+ virtual void OnSettingsEnd() = 0;
+
+ // Called when an entire SETTINGS frame, with the ACK flag, has been decoded.
+ virtual void OnSettingsAck(const Http2FrameHeader& header) = 0;
+
+ // Called just before starting to process the HPACK block of a PUSH_PROMISE
+ // frame. The Pad Length field has already been decoded at this point, so
+ // OnPadLength will not be called; note that total_padding_length is Pad
+ // Length + 1. After OnPushPromiseStart:
+ // OnHpackFragment as the remainder of the non-padding payload is available
+ // until all if has been provided;
+ // OnPadding will be called if the frame is padded AND the Pad Length field
+ // is greater than zero (i.e. total_padding_length > 1);
+ // OnPushPromiseEnd will be called last; If the frame is unpadded and has no
+ // payload, then this will be called immediately after OnPushPromiseStart.
+ virtual void OnPushPromiseStart(const Http2FrameHeader& header,
+ const Http2PushPromiseFields& promise,
+ size_t total_padding_length) = 0;
+
+ // Called after all of the HPACK block fragment and padding of a PUSH_PROMISE
+ // has been decoded and delivered to the listener. This call indicates the end
+ // of the HPACK block if and only if the frame header had the END_HEADERS flag
+ // set (i.e. header.IsEndHeaders() is true); otherwise the next block must be
+ // a CONTINUATION frame with the same stream id (not the same promised stream
+ // id).
+ virtual void OnPushPromiseEnd() = 0;
+
+ // Called when an entire PING frame, without the ACK flag, has been decoded.
+ virtual void OnPing(const Http2FrameHeader& header,
+ const Http2PingFields& ping) = 0;
+
+ // Called when an entire PING frame, with the ACK flag, has been decoded.
+ virtual void OnPingAck(const Http2FrameHeader& header,
+ const Http2PingFields& ping) = 0;
+
+ // Called after parsing a GOAWAY frame's header and fixed size fields, after
+ // which:
+ // OnGoAwayOpaqueData will be called as opaque data of the payload becomes
+ // available to the decoder, until all of it has been provided to the
+ // listener;
+ // OnGoAwayEnd will be called last, after all the opaque data has been
+ // provided to the listener; if there is no opaque data, then OnGoAwayEnd
+ // will be called immediately after OnGoAwayStart.
+ virtual void OnGoAwayStart(const Http2FrameHeader& header,
+ const Http2GoAwayFields& goaway) = 0;
+
+ // Called when the next portion of a GOAWAY frame's payload is received.
+ // |data| The start of |len| bytes of opaque data.
+ // |len| The length of the opaque data buffer. Maybe zero in some cases,
+ // which does not mean anything special.
+ virtual void OnGoAwayOpaqueData(const char* data, size_t len) = 0;
+
+ // Called after finishing decoding all of a GOAWAY frame.
+ virtual void OnGoAwayEnd() = 0;
+
+ // Called when an entire WINDOW_UPDATE frame has been decoded. The
+ // window_size_increment is required to be non-zero, but that has not been
+ // checked. If header.stream_id==0, the connection's flow control window is
+ // being increased, else the specified stream's flow control is being
+ // increased.
+ virtual void OnWindowUpdate(const Http2FrameHeader& header,
+ uint32_t window_size_increment) = 0;
+
+ // Called when an ALTSVC frame header and origin length have been parsed.
+ // Either or both lengths may be zero. After OnAltSvcStart:
+ // OnAltSvcOriginData will be called until all of the (optional) Origin
+ // has been provided;
+ // OnAltSvcValueData will be called until all of the Alt-Svc-Field-Value
+ // has been provided;
+ // OnAltSvcEnd will called last, after all of the origin and
+ // Alt-Svc-Field-Value have been delivered to the listener.
+ virtual void OnAltSvcStart(const Http2FrameHeader& header,
+ size_t origin_length,
+ size_t value_length) = 0;
+
+ // Called when decoding the (optional) origin of an ALTSVC;
+ // the field is uninterpreted.
+ virtual void OnAltSvcOriginData(const char* data, size_t len) = 0;
+
+ // Called when decoding the Alt-Svc-Field-Value of an ALTSVC;
+ // the field is uninterpreted.
+ virtual void OnAltSvcValueData(const char* data, size_t len) = 0;
+
+ // Called after decoding all of a ALTSVC frame and providing to the listener
+ // via the above methods.
+ virtual void OnAltSvcEnd() = 0;
+
+ // Called when the common frame header has been decoded, but the frame type
+ // is unknown, after which:
+ // OnUnknownPayload is called as the payload of the frame is provided to the
+ // decoder, until all of the payload has been decoded;
+ // OnUnknownEnd will called last, after the entire frame of the unknown type
+ // has been decoded and provided to the listener.
+ virtual void OnUnknownStart(const Http2FrameHeader& header) = 0;
+
+ // Called when the payload of an unknown frame type is received.
+ // |data| A buffer containing the data received.
+ // |len| The length of the data buffer.
+ virtual void OnUnknownPayload(const char* data, size_t len) = 0;
+
+ // Called after decoding all of the payload of an unknown frame type.
+ virtual void OnUnknownEnd() = 0;
+
+ //////////////////////////////////////////////////////////////////////////////
+ // Below here are events indicating a problem has been detected during
+ // decoding (i.e. the received frames are malformed in some way).
+
+ // Padding field (uint8) has a value that is too large (i.e. the amount of
+ // padding is greater than the remainder of the payload that isn't required).
+ // From RFC Section 6.1, DATA:
+ // If the length of the padding is the length of the frame payload or
+ // greater, the recipient MUST treat this as a connection error
+ // (Section 5.4.1) of type PROTOCOL_ERROR.
+ // The same is true for HEADERS and PUSH_PROMISE.
+ virtual void OnPaddingTooLong(const Http2FrameHeader& header,
+ size_t missing_length) = 0;
+
+ // Frame size error. Depending upon the effected frame, this may or may not
+ // require terminating the connection, though that is probably the best thing
+ // to do.
+ // From RFC Section 4.2, Frame Size:
+ // An endpoint MUST send an error code of FRAME_SIZE_ERROR if a frame
+ // exceeds the size defined in SETTINGS_MAX_FRAME_SIZE, exceeds any limit
+ // defined for the frame type, or is too small to contain mandatory frame
+ // data. A frame size error in a frame that could alter the state of the
+ // the entire connection MUST be treated as a connection error
+ // (Section 5.4.1); this includes any frame carrying a header block
+ // (Section 4.3) (that is, HEADERS, PUSH_PROMISE, and CONTINUATION),
+ // SETTINGS, and any frame with a stream identifier of 0.
+ virtual void OnFrameSizeError(const Http2FrameHeader& header) = 0;
+};
+
+// Do nothing for each call. Useful for ignoring a frame that is invalid.
+class Http2FrameDecoderNoOpListener : public Http2FrameDecoderListener {
+ public:
+ Http2FrameDecoderNoOpListener() {}
+ ~Http2FrameDecoderNoOpListener() override {}
+
+ // TODO(jamessynge): Remove OnFrameHeader once done with supporting
+ // SpdyFramer's exact states.
+ bool OnFrameHeader(const Http2FrameHeader& header) override;
+
+ void OnDataStart(const Http2FrameHeader& header) override {}
+ void OnDataPayload(const char* data, size_t len) override {}
+ void OnDataEnd() override {}
+ void OnHeadersStart(const Http2FrameHeader& header) override {}
+ void OnHeadersPriority(const Http2PriorityFields& priority) override {}
+ void OnHpackFragment(const char* data, size_t len) override {}
+ void OnHeadersEnd() override {}
+ void OnPriorityFrame(const Http2FrameHeader& header,
+ const Http2PriorityFields& priority) override {}
+ void OnContinuationStart(const Http2FrameHeader& header) override {}
+ void OnContinuationEnd() override {}
+ void OnPadLength(size_t trailing_length) override {}
+ void OnPadding(const char* padding, size_t skipped_length) override {}
+ void OnRstStream(const Http2FrameHeader& header,
+ Http2ErrorCode error_code) override {}
+ void OnSettingsStart(const Http2FrameHeader& header) override {}
+ void OnSetting(const Http2SettingFields& setting_fields) override {}
+ void OnSettingsEnd() override {}
+ void OnSettingsAck(const Http2FrameHeader& header) override {}
+ void OnPushPromiseStart(const Http2FrameHeader& header,
+ const Http2PushPromiseFields& promise,
+ size_t total_padding_length) override {}
+ void OnPushPromiseEnd() override {}
+ void OnPing(const Http2FrameHeader& header,
+ const Http2PingFields& ping) override {}
+ void OnPingAck(const Http2FrameHeader& header,
+ const Http2PingFields& ping) override {}
+ void OnGoAwayStart(const Http2FrameHeader& header,
+ const Http2GoAwayFields& goaway) override {}
+ void OnGoAwayOpaqueData(const char* data, size_t len) override {}
+ void OnGoAwayEnd() override {}
+ void OnWindowUpdate(const Http2FrameHeader& header,
+ uint32_t increment) override {}
+ void OnAltSvcStart(const Http2FrameHeader& header,
+ size_t origin_length,
+ size_t value_length) override {}
+ void OnAltSvcOriginData(const char* data, size_t len) override {}
+ void OnAltSvcValueData(const char* data, size_t len) override {}
+ void OnAltSvcEnd() override {}
+ void OnUnknownStart(const Http2FrameHeader& header) override {}
+ void OnUnknownPayload(const char* data, size_t len) override {}
+ void OnUnknownEnd() override {}
+ void OnPaddingTooLong(const Http2FrameHeader& header,
+ size_t missing_length) override {}
+ void OnFrameSizeError(const Http2FrameHeader& header) override {}
+};
+
+static_assert(!std::is_abstract<Http2FrameDecoderNoOpListener>(),
+ "Http2FrameDecoderNoOpListener ought to be concrete.");
+
+} // namespace net
+
+#endif // NET_HTTP2_DECODER_HTTP2_FRAME_DECODER_LISTENER_H_
diff --git a/chromium/net/http2/decoder/http2_frame_decoder_listener_test_util.cc b/chromium/net/http2/decoder/http2_frame_decoder_listener_test_util.cc
new file mode 100644
index 00000000000..9159b6cdc5b
--- /dev/null
+++ b/chromium/net/http2/decoder/http2_frame_decoder_listener_test_util.cc
@@ -0,0 +1,485 @@
+// Copyright 2016 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.
+
+#include "net/http2/decoder/http2_frame_decoder_listener_test_util.h"
+
+#include "base/logging.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace net {
+
+FailingHttp2FrameDecoderListener::FailingHttp2FrameDecoderListener() {}
+FailingHttp2FrameDecoderListener::~FailingHttp2FrameDecoderListener() {}
+
+bool FailingHttp2FrameDecoderListener::OnFrameHeader(
+ const Http2FrameHeader& header) {
+ ADD_FAILURE() << "OnFrameHeader: " << header;
+ return false;
+}
+
+void FailingHttp2FrameDecoderListener::OnDataStart(
+ const Http2FrameHeader& header) {
+ FAIL() << "OnDataStart: " << header;
+}
+
+void FailingHttp2FrameDecoderListener::OnDataPayload(const char* data,
+ size_t len) {
+ FAIL() << "OnDataPayload: len=" << len;
+}
+
+void FailingHttp2FrameDecoderListener::OnDataEnd() {
+ FAIL() << "OnDataEnd";
+}
+
+void FailingHttp2FrameDecoderListener::OnHeadersStart(
+ const Http2FrameHeader& header) {
+ FAIL() << "OnHeadersStart: " << header;
+}
+
+void FailingHttp2FrameDecoderListener::OnHeadersPriority(
+ const Http2PriorityFields& priority) {
+ FAIL() << "OnHeadersPriority: " << priority;
+}
+
+void FailingHttp2FrameDecoderListener::OnHpackFragment(const char* data,
+ size_t len) {
+ FAIL() << "OnHpackFragment: len=" << len;
+}
+
+void FailingHttp2FrameDecoderListener::OnHeadersEnd() {
+ FAIL() << "OnHeadersEnd";
+}
+
+void FailingHttp2FrameDecoderListener::OnPriorityFrame(
+ const Http2FrameHeader& header,
+ const Http2PriorityFields& priority) {
+ FAIL() << "OnPriorityFrame: " << header << "; priority: " << priority;
+}
+
+void FailingHttp2FrameDecoderListener::OnContinuationStart(
+ const Http2FrameHeader& header) {
+ FAIL() << "OnContinuationStart: " << header;
+}
+
+void FailingHttp2FrameDecoderListener::OnContinuationEnd() {
+ FAIL() << "OnContinuationEnd";
+}
+
+void FailingHttp2FrameDecoderListener::OnPadLength(size_t trailing_length) {
+ FAIL() << "OnPadLength: trailing_length=" << trailing_length;
+}
+
+void FailingHttp2FrameDecoderListener::OnPadding(const char* padding,
+ size_t skipped_length) {
+ FAIL() << "OnPadding: skipped_length=" << skipped_length;
+}
+
+void FailingHttp2FrameDecoderListener::OnRstStream(
+ const Http2FrameHeader& header,
+ Http2ErrorCode error_code) {
+ FAIL() << "OnRstStream: " << header << "; code=" << error_code;
+}
+
+void FailingHttp2FrameDecoderListener::OnSettingsStart(
+ const Http2FrameHeader& header) {
+ FAIL() << "OnSettingsStart: " << header;
+}
+
+void FailingHttp2FrameDecoderListener::OnSetting(
+ const Http2SettingFields& setting_fields) {
+ FAIL() << "OnSetting: " << setting_fields;
+}
+
+void FailingHttp2FrameDecoderListener::OnSettingsEnd() {
+ FAIL() << "OnSettingsEnd";
+}
+
+void FailingHttp2FrameDecoderListener::OnSettingsAck(
+ const Http2FrameHeader& header) {
+ FAIL() << "OnSettingsAck: " << header;
+}
+
+void FailingHttp2FrameDecoderListener::OnPushPromiseStart(
+ const Http2FrameHeader& header,
+ const Http2PushPromiseFields& promise,
+ size_t total_padding_length) {
+ FAIL() << "OnPushPromiseStart: " << header << "; promise: " << promise
+ << "; total_padding_length: " << total_padding_length;
+}
+
+void FailingHttp2FrameDecoderListener::OnPushPromiseEnd() {
+ FAIL() << "OnPushPromiseEnd";
+}
+
+void FailingHttp2FrameDecoderListener::OnPing(const Http2FrameHeader& header,
+ const Http2PingFields& ping) {
+ FAIL() << "OnPing: " << header << "; ping: " << ping;
+}
+
+void FailingHttp2FrameDecoderListener::OnPingAck(const Http2FrameHeader& header,
+ const Http2PingFields& ping) {
+ FAIL() << "OnPingAck: " << header << "; ping: " << ping;
+}
+
+void FailingHttp2FrameDecoderListener::OnGoAwayStart(
+ const Http2FrameHeader& header,
+ const Http2GoAwayFields& goaway) {
+ FAIL() << "OnGoAwayStart: " << header << "; goaway: " << goaway;
+}
+
+void FailingHttp2FrameDecoderListener::OnGoAwayOpaqueData(const char* data,
+ size_t len) {
+ FAIL() << "OnGoAwayOpaqueData: len=" << len;
+}
+
+void FailingHttp2FrameDecoderListener::OnGoAwayEnd() {
+ FAIL() << "OnGoAwayEnd";
+}
+
+void FailingHttp2FrameDecoderListener::OnWindowUpdate(
+ const Http2FrameHeader& header,
+ uint32_t increment) {
+ FAIL() << "OnWindowUpdate: " << header << "; increment=" << increment;
+}
+
+void FailingHttp2FrameDecoderListener::OnAltSvcStart(
+ const Http2FrameHeader& header,
+ size_t origin_length,
+ size_t value_length) {
+ FAIL() << "OnAltSvcStart: " << header << "; origin_length: " << origin_length
+ << "; value_length: " << value_length;
+}
+
+void FailingHttp2FrameDecoderListener::OnAltSvcOriginData(const char* data,
+ size_t len) {
+ FAIL() << "OnAltSvcOriginData: len=" << len;
+}
+
+void FailingHttp2FrameDecoderListener::OnAltSvcValueData(const char* data,
+ size_t len) {
+ FAIL() << "OnAltSvcValueData: len=" << len;
+}
+
+void FailingHttp2FrameDecoderListener::OnAltSvcEnd() {
+ FAIL() << "OnAltSvcEnd";
+}
+
+void FailingHttp2FrameDecoderListener::OnUnknownStart(
+ const Http2FrameHeader& header) {
+ FAIL() << "OnUnknownStart: " << header;
+}
+
+void FailingHttp2FrameDecoderListener::OnUnknownPayload(const char* data,
+ size_t len) {
+ FAIL() << "OnUnknownPayload: len=" << len;
+}
+
+void FailingHttp2FrameDecoderListener::OnUnknownEnd() {
+ FAIL() << "OnUnknownEnd";
+}
+
+void FailingHttp2FrameDecoderListener::OnPaddingTooLong(
+ const Http2FrameHeader& header,
+ size_t missing_length) {
+ FAIL() << "OnPaddingTooLong: " << header
+ << "; missing_length: " << missing_length;
+}
+
+void FailingHttp2FrameDecoderListener::OnFrameSizeError(
+ const Http2FrameHeader& header) {
+ FAIL() << "OnFrameSizeError: " << header;
+}
+
+LoggingHttp2FrameDecoderListener::LoggingHttp2FrameDecoderListener()
+ : wrapped_(nullptr) {}
+LoggingHttp2FrameDecoderListener::LoggingHttp2FrameDecoderListener(
+ Http2FrameDecoderListener* wrapped)
+ : wrapped_(wrapped) {}
+LoggingHttp2FrameDecoderListener::~LoggingHttp2FrameDecoderListener() {}
+
+bool LoggingHttp2FrameDecoderListener::OnFrameHeader(
+ const Http2FrameHeader& header) {
+ VLOG(1) << "OnFrameHeader: " << header;
+ if (wrapped_ != nullptr) {
+ return wrapped_->OnFrameHeader(header);
+ }
+ return true;
+}
+
+void LoggingHttp2FrameDecoderListener::OnDataStart(
+ const Http2FrameHeader& header) {
+ VLOG(1) << "OnDataStart: " << header;
+ if (wrapped_ != nullptr) {
+ wrapped_->OnDataStart(header);
+ }
+}
+
+void LoggingHttp2FrameDecoderListener::OnDataPayload(const char* data,
+ size_t len) {
+ VLOG(1) << "OnDataPayload: len=" << len;
+ if (wrapped_ != nullptr) {
+ wrapped_->OnDataPayload(data, len);
+ }
+}
+
+void LoggingHttp2FrameDecoderListener::OnDataEnd() {
+ VLOG(1) << "OnDataEnd";
+ if (wrapped_ != nullptr) {
+ wrapped_->OnDataEnd();
+ }
+}
+
+void LoggingHttp2FrameDecoderListener::OnHeadersStart(
+ const Http2FrameHeader& header) {
+ VLOG(1) << "OnHeadersStart: " << header;
+ if (wrapped_ != nullptr) {
+ wrapped_->OnHeadersStart(header);
+ }
+}
+
+void LoggingHttp2FrameDecoderListener::OnHeadersPriority(
+ const Http2PriorityFields& priority) {
+ VLOG(1) << "OnHeadersPriority: " << priority;
+ if (wrapped_ != nullptr) {
+ wrapped_->OnHeadersPriority(priority);
+ }
+}
+
+void LoggingHttp2FrameDecoderListener::OnHpackFragment(const char* data,
+ size_t len) {
+ VLOG(1) << "OnHpackFragment: len=" << len;
+ if (wrapped_ != nullptr) {
+ wrapped_->OnHpackFragment(data, len);
+ }
+}
+
+void LoggingHttp2FrameDecoderListener::OnHeadersEnd() {
+ VLOG(1) << "OnHeadersEnd";
+ if (wrapped_ != nullptr) {
+ wrapped_->OnHeadersEnd();
+ }
+}
+
+void LoggingHttp2FrameDecoderListener::OnPriorityFrame(
+ const Http2FrameHeader& header,
+ const Http2PriorityFields& priority) {
+ VLOG(1) << "OnPriorityFrame: " << header << "; priority: " << priority;
+ if (wrapped_ != nullptr) {
+ wrapped_->OnPriorityFrame(header, priority);
+ }
+}
+
+void LoggingHttp2FrameDecoderListener::OnContinuationStart(
+ const Http2FrameHeader& header) {
+ VLOG(1) << "OnContinuationStart: " << header;
+ if (wrapped_ != nullptr) {
+ wrapped_->OnContinuationStart(header);
+ }
+}
+
+void LoggingHttp2FrameDecoderListener::OnContinuationEnd() {
+ VLOG(1) << "OnContinuationEnd";
+ if (wrapped_ != nullptr) {
+ wrapped_->OnContinuationEnd();
+ }
+}
+
+void LoggingHttp2FrameDecoderListener::OnPadLength(size_t trailing_length) {
+ VLOG(1) << "OnPadLength: trailing_length=" << trailing_length;
+ if (wrapped_ != nullptr) {
+ wrapped_->OnPadLength(trailing_length);
+ }
+}
+
+void LoggingHttp2FrameDecoderListener::OnPadding(const char* padding,
+ size_t skipped_length) {
+ VLOG(1) << "OnPadding: skipped_length=" << skipped_length;
+ if (wrapped_ != nullptr) {
+ wrapped_->OnPadding(padding, skipped_length);
+ }
+}
+
+void LoggingHttp2FrameDecoderListener::OnRstStream(
+ const Http2FrameHeader& header,
+ Http2ErrorCode error_code) {
+ VLOG(1) << "OnRstStream: " << header << "; code=" << error_code;
+ if (wrapped_ != nullptr) {
+ wrapped_->OnRstStream(header, error_code);
+ }
+}
+
+void LoggingHttp2FrameDecoderListener::OnSettingsStart(
+ const Http2FrameHeader& header) {
+ VLOG(1) << "OnSettingsStart: " << header;
+ if (wrapped_ != nullptr) {
+ wrapped_->OnSettingsStart(header);
+ }
+}
+
+void LoggingHttp2FrameDecoderListener::OnSetting(
+ const Http2SettingFields& setting_fields) {
+ VLOG(1) << "OnSetting: " << setting_fields;
+ if (wrapped_ != nullptr) {
+ wrapped_->OnSetting(setting_fields);
+ }
+}
+
+void LoggingHttp2FrameDecoderListener::OnSettingsEnd() {
+ VLOG(1) << "OnSettingsEnd";
+ if (wrapped_ != nullptr) {
+ wrapped_->OnSettingsEnd();
+ }
+}
+
+void LoggingHttp2FrameDecoderListener::OnSettingsAck(
+ const Http2FrameHeader& header) {
+ VLOG(1) << "OnSettingsAck: " << header;
+ if (wrapped_ != nullptr) {
+ wrapped_->OnSettingsAck(header);
+ }
+}
+
+void LoggingHttp2FrameDecoderListener::OnPushPromiseStart(
+ const Http2FrameHeader& header,
+ const Http2PushPromiseFields& promise,
+ size_t total_padding_length) {
+ VLOG(1) << "OnPushPromiseStart: " << header << "; promise: " << promise
+ << "; total_padding_length: " << total_padding_length;
+ if (wrapped_ != nullptr) {
+ wrapped_->OnPushPromiseStart(header, promise, total_padding_length);
+ }
+}
+
+void LoggingHttp2FrameDecoderListener::OnPushPromiseEnd() {
+ VLOG(1) << "OnPushPromiseEnd";
+ if (wrapped_ != nullptr) {
+ wrapped_->OnPushPromiseEnd();
+ }
+}
+
+void LoggingHttp2FrameDecoderListener::OnPing(const Http2FrameHeader& header,
+ const Http2PingFields& ping) {
+ VLOG(1) << "OnPing: " << header << "; ping: " << ping;
+ if (wrapped_ != nullptr) {
+ wrapped_->OnPing(header, ping);
+ }
+}
+
+void LoggingHttp2FrameDecoderListener::OnPingAck(const Http2FrameHeader& header,
+ const Http2PingFields& ping) {
+ VLOG(1) << "OnPingAck: " << header << "; ping: " << ping;
+ if (wrapped_ != nullptr) {
+ wrapped_->OnPingAck(header, ping);
+ }
+}
+
+void LoggingHttp2FrameDecoderListener::OnGoAwayStart(
+ const Http2FrameHeader& header,
+ const Http2GoAwayFields& goaway) {
+ VLOG(1) << "OnGoAwayStart: " << header << "; goaway: " << goaway;
+ if (wrapped_ != nullptr) {
+ wrapped_->OnGoAwayStart(header, goaway);
+ }
+}
+
+void LoggingHttp2FrameDecoderListener::OnGoAwayOpaqueData(const char* data,
+ size_t len) {
+ VLOG(1) << "OnGoAwayOpaqueData: len=" << len;
+ if (wrapped_ != nullptr) {
+ wrapped_->OnGoAwayOpaqueData(data, len);
+ }
+}
+
+void LoggingHttp2FrameDecoderListener::OnGoAwayEnd() {
+ VLOG(1) << "OnGoAwayEnd";
+ if (wrapped_ != nullptr) {
+ wrapped_->OnGoAwayEnd();
+ }
+}
+
+void LoggingHttp2FrameDecoderListener::OnWindowUpdate(
+ const Http2FrameHeader& header,
+ uint32_t increment) {
+ VLOG(1) << "OnWindowUpdate: " << header << "; increment=" << increment;
+ if (wrapped_ != nullptr) {
+ wrapped_->OnWindowUpdate(header, increment);
+ }
+}
+
+void LoggingHttp2FrameDecoderListener::OnAltSvcStart(
+ const Http2FrameHeader& header,
+ size_t origin_length,
+ size_t value_length) {
+ VLOG(1) << "OnAltSvcStart: " << header << "; origin_length: " << origin_length
+ << "; value_length: " << value_length;
+ if (wrapped_ != nullptr) {
+ wrapped_->OnAltSvcStart(header, origin_length, value_length);
+ }
+}
+
+void LoggingHttp2FrameDecoderListener::OnAltSvcOriginData(const char* data,
+ size_t len) {
+ VLOG(1) << "OnAltSvcOriginData: len=" << len;
+ if (wrapped_ != nullptr) {
+ wrapped_->OnAltSvcOriginData(data, len);
+ }
+}
+
+void LoggingHttp2FrameDecoderListener::OnAltSvcValueData(const char* data,
+ size_t len) {
+ VLOG(1) << "OnAltSvcValueData: len=" << len;
+ if (wrapped_ != nullptr) {
+ wrapped_->OnAltSvcValueData(data, len);
+ }
+}
+
+void LoggingHttp2FrameDecoderListener::OnAltSvcEnd() {
+ VLOG(1) << "OnAltSvcEnd";
+ if (wrapped_ != nullptr) {
+ wrapped_->OnAltSvcEnd();
+ }
+}
+
+void LoggingHttp2FrameDecoderListener::OnUnknownStart(
+ const Http2FrameHeader& header) {
+ VLOG(1) << "OnUnknownStart: " << header;
+ if (wrapped_ != nullptr) {
+ wrapped_->OnUnknownStart(header);
+ }
+}
+
+void LoggingHttp2FrameDecoderListener::OnUnknownPayload(const char* data,
+ size_t len) {
+ VLOG(1) << "OnUnknownPayload: len=" << len;
+ if (wrapped_ != nullptr) {
+ wrapped_->OnUnknownPayload(data, len);
+ }
+}
+
+void LoggingHttp2FrameDecoderListener::OnUnknownEnd() {
+ VLOG(1) << "OnUnknownEnd";
+ if (wrapped_ != nullptr) {
+ wrapped_->OnUnknownEnd();
+ }
+}
+
+void LoggingHttp2FrameDecoderListener::OnPaddingTooLong(
+ const Http2FrameHeader& header,
+ size_t missing_length) {
+ VLOG(1) << "OnPaddingTooLong: " << header
+ << "; missing_length: " << missing_length;
+ if (wrapped_ != nullptr) {
+ wrapped_->OnPaddingTooLong(header, missing_length);
+ }
+}
+
+void LoggingHttp2FrameDecoderListener::OnFrameSizeError(
+ const Http2FrameHeader& header) {
+ VLOG(1) << "OnFrameSizeError: " << header;
+ if (wrapped_ != nullptr) {
+ wrapped_->OnFrameSizeError(header);
+ }
+}
+
+} // namespace net
diff --git a/chromium/net/http2/decoder/http2_frame_decoder_listener_test_util.h b/chromium/net/http2/decoder/http2_frame_decoder_listener_test_util.h
new file mode 100644
index 00000000000..ead1b93a664
--- /dev/null
+++ b/chromium/net/http2/decoder/http2_frame_decoder_listener_test_util.h
@@ -0,0 +1,141 @@
+// Copyright 2016 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.
+
+#ifndef NET_HTTP2_DECODER_HTTP2_FRAME_DECODER_LISTENER_TEST_UTIL_H_
+#define NET_HTTP2_DECODER_HTTP2_FRAME_DECODER_LISTENER_TEST_UTIL_H_
+
+#include <stddef.h>
+
+#include "net/http2/decoder/http2_frame_decoder_listener.h"
+#include "net/http2/http2_constants.h"
+#include "net/http2/http2_structures.h"
+
+namespace net {
+
+// Fail if any of the methods are called. Allows a test to override only the
+// expected calls.
+class FailingHttp2FrameDecoderListener : public Http2FrameDecoderListener {
+ public:
+ FailingHttp2FrameDecoderListener();
+ ~FailingHttp2FrameDecoderListener() override;
+
+ // TODO(jamessynge): Remove OnFrameHeader once done with supporting
+ // SpdyFramer's exact states.
+ bool OnFrameHeader(const Http2FrameHeader& header) override;
+ void OnDataStart(const Http2FrameHeader& header) override;
+ void OnDataPayload(const char* data, size_t len) override;
+ void OnDataEnd() override;
+ void OnHeadersStart(const Http2FrameHeader& header) override;
+ void OnHeadersPriority(const Http2PriorityFields& priority) override;
+ void OnHpackFragment(const char* data, size_t len) override;
+ void OnHeadersEnd() override;
+ void OnPriorityFrame(const Http2FrameHeader& header,
+ const Http2PriorityFields& priority) override;
+ void OnContinuationStart(const Http2FrameHeader& header) override;
+ void OnContinuationEnd() override;
+ void OnPadLength(size_t trailing_length) override;
+ void OnPadding(const char* padding, size_t skipped_length) override;
+ void OnRstStream(const Http2FrameHeader& header,
+ Http2ErrorCode error_code) override;
+ void OnSettingsStart(const Http2FrameHeader& header) override;
+ void OnSetting(const Http2SettingFields& setting_fields) override;
+ void OnSettingsEnd() override;
+ void OnSettingsAck(const Http2FrameHeader& header) override;
+ void OnPushPromiseStart(const Http2FrameHeader& header,
+ const Http2PushPromiseFields& promise,
+ size_t total_padding_length) override;
+ void OnPushPromiseEnd() override;
+ void OnPing(const Http2FrameHeader& header,
+ const Http2PingFields& ping) override;
+ void OnPingAck(const Http2FrameHeader& header,
+ const Http2PingFields& ping) override;
+ void OnGoAwayStart(const Http2FrameHeader& header,
+ const Http2GoAwayFields& goaway) override;
+ void OnGoAwayOpaqueData(const char* data, size_t len) override;
+ void OnGoAwayEnd() override;
+ void OnWindowUpdate(const Http2FrameHeader& header,
+ uint32_t increment) override;
+ void OnAltSvcStart(const Http2FrameHeader& header,
+ size_t origin_length,
+ size_t value_length) override;
+ void OnAltSvcOriginData(const char* data, size_t len) override;
+ void OnAltSvcValueData(const char* data, size_t len) override;
+ void OnAltSvcEnd() override;
+ void OnUnknownStart(const Http2FrameHeader& header) override;
+ void OnUnknownPayload(const char* data, size_t len) override;
+ void OnUnknownEnd() override;
+ void OnPaddingTooLong(const Http2FrameHeader& header,
+ size_t missing_length) override;
+ void OnFrameSizeError(const Http2FrameHeader& header) override;
+
+ private:
+ void EnsureNotAbstract() { FailingHttp2FrameDecoderListener instance; }
+};
+
+// VLOG's all the calls it receives, and forwards those calls to an optional
+// listener.
+class LoggingHttp2FrameDecoderListener : public Http2FrameDecoderListener {
+ public:
+ LoggingHttp2FrameDecoderListener();
+ explicit LoggingHttp2FrameDecoderListener(Http2FrameDecoderListener* wrapped);
+ ~LoggingHttp2FrameDecoderListener() override;
+
+ // TODO(jamessynge): Remove OnFrameHeader once done with supporting
+ // SpdyFramer's exact states.
+ bool OnFrameHeader(const Http2FrameHeader& header) override;
+ void OnDataStart(const Http2FrameHeader& header) override;
+ void OnDataPayload(const char* data, size_t len) override;
+ void OnDataEnd() override;
+ void OnHeadersStart(const Http2FrameHeader& header) override;
+ void OnHeadersPriority(const Http2PriorityFields& priority) override;
+ void OnHpackFragment(const char* data, size_t len) override;
+ void OnHeadersEnd() override;
+ void OnPriorityFrame(const Http2FrameHeader& header,
+ const Http2PriorityFields& priority) override;
+ void OnContinuationStart(const Http2FrameHeader& header) override;
+ void OnContinuationEnd() override;
+ void OnPadLength(size_t trailing_length) override;
+ void OnPadding(const char* padding, size_t skipped_length) override;
+ void OnRstStream(const Http2FrameHeader& header,
+ Http2ErrorCode error_code) override;
+ void OnSettingsStart(const Http2FrameHeader& header) override;
+ void OnSetting(const Http2SettingFields& setting_fields) override;
+ void OnSettingsEnd() override;
+ void OnSettingsAck(const Http2FrameHeader& header) override;
+ void OnPushPromiseStart(const Http2FrameHeader& header,
+ const Http2PushPromiseFields& promise,
+ size_t total_padding_length) override;
+ void OnPushPromiseEnd() override;
+ void OnPing(const Http2FrameHeader& header,
+ const Http2PingFields& ping) override;
+ void OnPingAck(const Http2FrameHeader& header,
+ const Http2PingFields& ping) override;
+ void OnGoAwayStart(const Http2FrameHeader& header,
+ const Http2GoAwayFields& goaway) override;
+ void OnGoAwayOpaqueData(const char* data, size_t len) override;
+ void OnGoAwayEnd() override;
+ void OnWindowUpdate(const Http2FrameHeader& header,
+ uint32_t increment) override;
+ void OnAltSvcStart(const Http2FrameHeader& header,
+ size_t origin_length,
+ size_t value_length) override;
+ void OnAltSvcOriginData(const char* data, size_t len) override;
+ void OnAltSvcValueData(const char* data, size_t len) override;
+ void OnAltSvcEnd() override;
+ void OnUnknownStart(const Http2FrameHeader& header) override;
+ void OnUnknownPayload(const char* data, size_t len) override;
+ void OnUnknownEnd() override;
+ void OnPaddingTooLong(const Http2FrameHeader& header,
+ size_t missing_length) override;
+ void OnFrameSizeError(const Http2FrameHeader& header) override;
+
+ private:
+ void EnsureNotAbstract() { LoggingHttp2FrameDecoderListener instance; }
+
+ Http2FrameDecoderListener* wrapped_;
+};
+
+} // namespace net
+
+#endif // NET_HTTP2_DECODER_HTTP2_FRAME_DECODER_LISTENER_TEST_UTIL_H_
diff --git a/chromium/net/http2/decoder/http2_frame_decoder_test.cc b/chromium/net/http2/decoder/http2_frame_decoder_test.cc
new file mode 100644
index 00000000000..0d1d2783220
--- /dev/null
+++ b/chromium/net/http2/decoder/http2_frame_decoder_test.cc
@@ -0,0 +1,930 @@
+// Copyright 2016 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.
+
+#include "net/http2/decoder/http2_frame_decoder.h"
+
+// Tests of Http2FrameDecoder.
+
+#include <memory>
+#include <string>
+#include <vector>
+
+#include "base/logging.h"
+#include "net/http2/decoder/frame_parts.h"
+#include "net/http2/decoder/frame_parts_collector_listener.h"
+#include "net/http2/http2_constants.h"
+#include "net/http2/tools/failure.h"
+#include "net/http2/tools/http2_random.h"
+#include "net/http2/tools/random_decoder_test.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+using base::StringPiece;
+using std::string;
+using ::testing::AssertionResult;
+using ::testing::AssertionSuccess;
+
+namespace net {
+namespace test {
+class Http2FrameDecoderPeer {
+ public:
+ static size_t remaining_total_payload(Http2FrameDecoder* decoder) {
+ return decoder->frame_decoder_state_.remaining_total_payload();
+ }
+};
+
+namespace {
+
+class Http2FrameDecoderTest : public RandomDecoderTest {
+
+ protected:
+ void SetUp() override {
+ // On any one run of this suite, we'll always choose the same value for
+ // use_default_reconstruct_ because the random seed is the same for each
+ // test case, but across runs the random seed changes.
+ use_default_reconstruct_ = Random().OneIn(2);
+ }
+
+ DecodeStatus StartDecoding(DecodeBuffer* db) override {
+ DVLOG(2) << "StartDecoding, db->Remaining=" << db->Remaining();
+ collector_.Reset();
+ PrepareDecoder();
+
+ DecodeStatus status = decoder_.DecodeFrame(db);
+ if (status != DecodeStatus::kDecodeInProgress) {
+ // Keep track of this so that a concrete test can verify that both fast
+ // and slow decoding paths have been tested.
+ ++fast_decode_count_;
+ if (status == DecodeStatus::kDecodeError) {
+ ConfirmDiscardsRemainingPayload();
+ }
+ }
+ return status;
+ }
+
+ DecodeStatus ResumeDecoding(DecodeBuffer* db) override {
+ DVLOG(2) << "ResumeDecoding, db->Remaining=" << db->Remaining();
+ DecodeStatus status = decoder_.DecodeFrame(db);
+ if (status != DecodeStatus::kDecodeInProgress) {
+ // Keep track of this so that a concrete test can verify that both fast
+ // and slow decoding paths have been tested.
+ ++slow_decode_count_;
+ if (status == DecodeStatus::kDecodeError) {
+ ConfirmDiscardsRemainingPayload();
+ }
+ }
+ return status;
+ }
+
+ // When an error is returned, the decoder is in state kDiscardPayload, and
+ // stays there until the remaining bytes of the frame's payload have been
+ // skipped over. There are no callbacks for this situation.
+ void ConfirmDiscardsRemainingPayload() {
+ ASSERT_TRUE(decoder_.IsDiscardingPayload());
+ size_t remaining =
+ Http2FrameDecoderPeer::remaining_total_payload(&decoder_);
+ // The decoder will discard the remaining bytes, but not go beyond that,
+ // which these conditions verify.
+ size_t extra = 10;
+ string junk(remaining + extra, '0');
+ DecodeBuffer tmp(junk);
+ EXPECT_EQ(DecodeStatus::kDecodeDone, decoder_.DecodeFrame(&tmp));
+ EXPECT_EQ(remaining, tmp.Offset());
+ EXPECT_EQ(extra, tmp.Remaining());
+ EXPECT_FALSE(decoder_.IsDiscardingPayload());
+ }
+
+ void PrepareDecoder() {
+ // Save and restore the maximum_payload_size when reconstructing
+ // the decoder.
+ size_t maximum_payload_size = decoder_.maximum_payload_size();
+
+ // Alternate which constructor is used.
+ if (use_default_reconstruct_) {
+ decoder_.~Http2FrameDecoder();
+ new (&decoder_) Http2FrameDecoder;
+ decoder_.set_listener(&collector_);
+ } else {
+ decoder_.~Http2FrameDecoder();
+ new (&decoder_) Http2FrameDecoder(&collector_);
+ }
+ decoder_.set_maximum_payload_size(maximum_payload_size);
+
+ use_default_reconstruct_ = !use_default_reconstruct_;
+ }
+
+ void ResetDecodeSpeedCounters() {
+ fast_decode_count_ = 0;
+ slow_decode_count_ = 0;
+ }
+
+ AssertionResult VerifyCollected(const FrameParts& expected) {
+ VERIFY_FALSE(collector_.IsInProgress());
+ VERIFY_EQ(1u, collector_.size());
+ VERIFY_AND_RETURN_SUCCESS(expected.VerifyEquals(*collector_.frame(0)));
+ }
+
+ AssertionResult DecodePayloadAndValidateSeveralWays(StringPiece payload,
+ Validator validator) {
+ DecodeBuffer db(payload);
+ bool start_decoding_requires_non_empty = false;
+ return DecodeAndValidateSeveralWays(&db, start_decoding_requires_non_empty,
+ validator);
+ }
+
+
+ // Decode one frame's payload and confirm that the listener recorded the
+ // expected FrameParts instance, and only one FrameParts instance. The
+ // payload will be decoded several times with different partitionings
+ // of the payload, and after each the validator will be called.
+ AssertionResult DecodePayloadAndValidateSeveralWays(
+ StringPiece payload,
+ const FrameParts& expected) {
+ Validator validator = [&expected, this](
+ const DecodeBuffer& input, DecodeStatus status) -> AssertionResult {
+ VERIFY_EQ(status, DecodeStatus::kDecodeDone);
+ VERIFY_AND_RETURN_SUCCESS(VerifyCollected(expected));
+ };
+ ResetDecodeSpeedCounters();
+ VERIFY_SUCCESS(DecodePayloadAndValidateSeveralWays(
+ payload, ValidateDoneAndEmpty(validator)));
+ VERIFY_GT(fast_decode_count_, 0u);
+ VERIFY_GT(slow_decode_count_, 0u);
+
+ // Repeat with more input; it should stop without reading that input.
+ string next_frame = Random().RandString(10);
+ string input;
+ payload.AppendToString(&input);
+ input += next_frame;
+
+ ResetDecodeSpeedCounters();
+ VERIFY_SUCCESS(DecodePayloadAndValidateSeveralWays(
+ payload, ValidateDoneAndOffset(payload.size(), validator)));
+ VERIFY_GT(fast_decode_count_, 0u);
+ VERIFY_GT(slow_decode_count_, 0u);
+
+ return AssertionSuccess();
+ }
+
+ template <size_t N>
+ AssertionResult DecodePayloadAndValidateSeveralWays(
+ const char (&buf)[N],
+ const FrameParts& expected) {
+ return DecodePayloadAndValidateSeveralWays(StringPiece(buf, N), expected);
+ }
+
+ template <size_t N>
+ AssertionResult DecodePayloadAndValidateSeveralWays(
+ const char (&buf)[N],
+ const Http2FrameHeader& header) {
+ return DecodePayloadAndValidateSeveralWays(StringPiece(buf, N),
+ FrameParts(header));
+ }
+
+ template <size_t N>
+ AssertionResult DecodePayloadExpectingError(const char (&buf)[N],
+ const FrameParts& expected) {
+ auto validator = [&expected, this](const DecodeBuffer& input,
+ DecodeStatus status) -> AssertionResult {
+ VERIFY_EQ(status, DecodeStatus::kDecodeError);
+ VERIFY_AND_RETURN_SUCCESS(VerifyCollected(expected));
+ };
+ ResetDecodeSpeedCounters();
+ EXPECT_TRUE(
+ DecodePayloadAndValidateSeveralWays(ToStringPiece(buf), validator));
+ EXPECT_GT(fast_decode_count_, 0u);
+ EXPECT_GT(slow_decode_count_, 0u);
+ return AssertionSuccess();
+ }
+
+ template <size_t N>
+ AssertionResult DecodePayloadExpectingFrameSizeError(const char (&buf)[N],
+ FrameParts expected) {
+ expected.has_frame_size_error = true;
+ VERIFY_AND_RETURN_SUCCESS(DecodePayloadExpectingError(buf, expected));
+ }
+
+ template <size_t N>
+ AssertionResult DecodePayloadExpectingFrameSizeError(
+ const char (&buf)[N],
+ const Http2FrameHeader& header) {
+ return DecodePayloadExpectingFrameSizeError(buf, FrameParts(header));
+ }
+
+ // Count of payloads that are fully decoded by StartDecodingPayload or for
+ // which an error was detected by StartDecodingPayload.
+ size_t fast_decode_count_ = 0;
+
+ // Count of payloads that required calling ResumeDecodingPayload in order to
+ // decode completely, or for which an error was detected by
+ // ResumeDecodingPayload.
+ size_t slow_decode_count_ = 0;
+
+ FramePartsCollectorListener collector_;
+ Http2FrameDecoder decoder_;
+ bool use_default_reconstruct_;
+};
+
+////////////////////////////////////////////////////////////////////////////////
+// Tests that pass the minimum allowed size for the frame type, which is often
+// empty. The tests are in order by frame type value (i.e. 0 for DATA frames).
+
+TEST_F(Http2FrameDecoderTest, DataEmpty) {
+ const char kFrameData[] = {
+ 0x00, 0x00, 0x00, // Payload length: 0
+ 0x00, // DATA
+ 0x00, // Flags: none
+ 0x00, 0x00, 0x00, 0x00, // Stream ID: 0 (invalid but unchecked here)
+ };
+ Http2FrameHeader header(0, Http2FrameType::DATA, 0, 0);
+ FrameParts expected(header, "");
+ EXPECT_TRUE(DecodePayloadAndValidateSeveralWays(kFrameData, expected));
+}
+
+TEST_F(Http2FrameDecoderTest, HeadersEmpty) {
+ const char kFrameData[] = {
+ 0x00, 0x00, 0x00, // Payload length: 0
+ 0x01, // HEADERS
+ 0x00, // Flags: none
+ 0x00, 0x00, 0x00, 0x01, // Stream ID: 0 (REQUIRES ID)
+ };
+ Http2FrameHeader header(0, Http2FrameType::HEADERS, 0, 1);
+ FrameParts expected(header, "");
+ EXPECT_TRUE(DecodePayloadAndValidateSeveralWays(kFrameData, expected));
+}
+
+TEST_F(Http2FrameDecoderTest, Priority) {
+ const char kFrameData[] = {
+ 0x00, 0x00, 0x05, // Length: 5
+ 0x02, // Type: PRIORITY
+ 0x00, // Flags: none
+ 0x00, 0x00, 0x00, 0x02, // Stream: 2
+ 0x80u, 0x00, 0x00, 0x01, // Parent: 1 (Exclusive)
+ 0x10, // Weight: 17
+ };
+ Http2FrameHeader header(5, Http2FrameType::PRIORITY, 0, 2);
+ FrameParts expected(header);
+ expected.opt_priority = Http2PriorityFields(1, 17, true);
+ EXPECT_TRUE(DecodePayloadAndValidateSeveralWays(kFrameData, expected));
+}
+
+TEST_F(Http2FrameDecoderTest, RstStream) {
+ const char kFrameData[] = {
+ 0x00, 0x00, 0x04, // Length: 4
+ 0x03, // Type: RST_STREAM
+ 0x00, // Flags: none
+ 0x00, 0x00, 0x00, 0x01, // Stream: 1
+ 0x00, 0x00, 0x00, 0x01, // Error: PROTOCOL_ERROR
+ };
+ Http2FrameHeader header(4, Http2FrameType::RST_STREAM, 0, 1);
+ FrameParts expected(header);
+ expected.opt_rst_stream_error_code = Http2ErrorCode::PROTOCOL_ERROR;
+ EXPECT_TRUE(DecodePayloadAndValidateSeveralWays(kFrameData, expected));
+}
+
+TEST_F(Http2FrameDecoderTest, SettingsEmpty) {
+ const char kFrameData[] = {
+ 0x00, 0x00, 0x00, // Length: 0
+ 0x04, // Type: SETTINGS
+ 0x00, // Flags: none
+ 0x00, 0x00, 0x00, 0x01, // Stream: 1 (invalid but unchecked here)
+ };
+ Http2FrameHeader header(0, Http2FrameType::SETTINGS, 0, 1);
+ EXPECT_TRUE(DecodePayloadAndValidateSeveralWays(kFrameData, header));
+}
+
+TEST_F(Http2FrameDecoderTest, SettingsAck) {
+ const char kFrameData[] = {
+ 0x00, 0x00, 0x00, // Length: 6
+ 0x04, // Type: SETTINGS
+ 0x01, // Flags: ACK
+ 0x00, 0x00, 0x00, 0x00, // Stream: 0
+ };
+ Http2FrameHeader header(0, Http2FrameType::SETTINGS, Http2FrameFlag::FLAG_ACK,
+ 0);
+ FrameParts expected(header);
+ EXPECT_TRUE(DecodePayloadAndValidateSeveralWays(kFrameData, expected));
+}
+
+TEST_F(Http2FrameDecoderTest, PushPromiseMinimal) {
+ const char kFrameData[] = {
+ 0x00, 0x00, 0x04, // Payload length: 4
+ 0x05, // PUSH_PROMISE
+ 0x04, // Flags: END_HEADERS
+ 0x00, 0x00, 0x00, 0x02, // Stream: 2 (invalid but unchecked here)
+ 0x00, 0x00, 0x00, 0x01, // Promised: 1 (invalid but unchecked here)
+ };
+ Http2FrameHeader header(4, Http2FrameType::PUSH_PROMISE,
+ Http2FrameFlag::FLAG_END_HEADERS, 2);
+ FrameParts expected(header, "");
+ expected.opt_push_promise = Http2PushPromiseFields{1};
+ EXPECT_TRUE(DecodePayloadAndValidateSeveralWays(kFrameData, expected));
+}
+
+TEST_F(Http2FrameDecoderTest, Ping) {
+ const char kFrameData[] = {
+ 0x00, 0x00, 0x08, // Length: 8
+ 0x06, // Type: PING
+ 0xfeu, // Flags: no valid flags
+ 0x00, 0x00, 0x00, 0x00, // Stream: 0
+ 's', 'o', 'm', 'e', // "some"
+ 'd', 'a', 't', 'a', // "data"
+ };
+ Http2FrameHeader header(8, Http2FrameType::PING, 0, 0);
+ FrameParts expected(header);
+ expected.opt_ping = Http2PingFields{{'s', 'o', 'm', 'e', 'd', 'a', 't', 'a'}};
+ EXPECT_TRUE(DecodePayloadAndValidateSeveralWays(kFrameData, expected));
+}
+
+TEST_F(Http2FrameDecoderTest, PingAck) {
+ const char kFrameData[] = {
+ 0x00, 0x00, 0x08, // Length: 8
+ 0x06, // Type: PING
+ 0xffu, // Flags: ACK (plus all invalid flags)
+ 0x00, 0x00, 0x00, 0x00, // Stream: 0
+ 's', 'o', 'm', 'e', // "some"
+ 'd', 'a', 't', 'a', // "data"
+ };
+ Http2FrameHeader header(8, Http2FrameType::PING, Http2FrameFlag::FLAG_ACK, 0);
+ FrameParts expected(header);
+ expected.opt_ping = Http2PingFields{{'s', 'o', 'm', 'e', 'd', 'a', 't', 'a'}};
+ EXPECT_TRUE(DecodePayloadAndValidateSeveralWays(kFrameData, expected));
+}
+
+TEST_F(Http2FrameDecoderTest, GoAwayMinimal) {
+ const char kFrameData[] = {
+ 0x00, 0x00, 0x08, // Length: 8 (no opaque data)
+ 0x07, // Type: GOAWAY
+ 0xffu, // Flags: 0xff (no valid flags)
+ 0x00, 0x00, 0x00, 0x01, // Stream: 1 (invalid but unchecked here)
+ 0x80u, 0x00, 0x00, 0xffu, // Last: 255 (plus R bit)
+ 0x00, 0x00, 0x00, 0x09, // Error: COMPRESSION_ERROR
+ };
+ Http2FrameHeader header(8, Http2FrameType::GOAWAY, 0, 1);
+ FrameParts expected(header);
+ expected.opt_goaway =
+ Http2GoAwayFields(255, Http2ErrorCode::COMPRESSION_ERROR);
+ EXPECT_TRUE(DecodePayloadAndValidateSeveralWays(kFrameData, expected));
+}
+
+TEST_F(Http2FrameDecoderTest, WindowUpdate) {
+ const char kFrameData[] = {
+ 0x00, 0x00, 0x04, // Length: 4
+ 0x08, // Type: WINDOW_UPDATE
+ 0x0f, // Flags: 0xff (no valid flags)
+ 0x00, 0x00, 0x00, 0x01, // Stream: 1
+ 0x80u, 0x00, 0x04, 0x00, // Incr: 1024 (plus R bit)
+ };
+ Http2FrameHeader header(4, Http2FrameType::WINDOW_UPDATE, 0, 1);
+ FrameParts expected(header);
+ expected.opt_window_update_increment = 1024;
+ EXPECT_TRUE(DecodePayloadAndValidateSeveralWays(kFrameData, expected));
+}
+
+TEST_F(Http2FrameDecoderTest, ContinuationEmpty) {
+ const char kFrameData[] = {
+ 0x00, 0x00, 0x00, // Payload length: 0
+ 0x09, // CONTINUATION
+ 0x00, // Flags: none
+ 0x00, 0x00, 0x00, 0x00, // Stream ID: 0 (invalid but unchecked here)
+ };
+ Http2FrameHeader header(0, Http2FrameType::CONTINUATION, 0, 0);
+ FrameParts expected(header);
+ EXPECT_TRUE(DecodePayloadAndValidateSeveralWays(kFrameData, expected));
+}
+
+TEST_F(Http2FrameDecoderTest, AltSvcMinimal) {
+ const char kFrameData[] = {
+ 0x00, 0x00, 0x02, // Payload length: 2
+ 0x0a, // ALTSVC
+ 0xffu, // Flags: none (plus 0xff)
+ 0x00, 0x00, 0x00, 0x00, // Stream ID: 0 (invalid but unchecked here)
+ 0x00, 0x00, // Origin Length: 0
+ };
+ Http2FrameHeader header(2, Http2FrameType::ALTSVC, 0, 0);
+ FrameParts expected(header);
+ expected.opt_altsvc_origin_length = 0;
+ expected.opt_altsvc_value_length = 0;
+ EXPECT_TRUE(DecodePayloadAndValidateSeveralWays(kFrameData, expected));
+}
+
+TEST_F(Http2FrameDecoderTest, UnknownEmpty) {
+ const char kFrameData[] = {
+ 0x00, 0x00, 0x00, // Payload length: 0
+ 0x20, // 32 (unknown)
+ 0xffu, // Flags: all
+ 0x00, 0x00, 0x00, 0x00, // Stream ID: 0
+ };
+ Http2FrameHeader header(0, static_cast<Http2FrameType>(32), 0xff, 0);
+ FrameParts expected(header);
+ EXPECT_TRUE(DecodePayloadAndValidateSeveralWays(kFrameData, expected));
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// Tests of longer payloads, for those frame types that allow longer payloads.
+
+TEST_F(Http2FrameDecoderTest, DataPayload) {
+ const char kFrameData[] = {
+ 0x00, 0x00, 0x03, // Payload length: 7
+ 0x00, // DATA
+ 0x80u, // Flags: 0x80
+ 0x00, 0x00, 0x02, 0x02, // Stream ID: 514
+ 'a', 'b', 'c', // Data
+ };
+ Http2FrameHeader header(3, Http2FrameType::DATA, 0, 514);
+ FrameParts expected(header, "abc");
+ EXPECT_TRUE(DecodePayloadAndValidateSeveralWays(kFrameData, expected));
+}
+
+TEST_F(Http2FrameDecoderTest, HeadersPayload) {
+ const char kFrameData[] = {
+ 0x00, 0x00, 0x03, // Payload length: 3
+ 0x01, // HEADERS
+ 0x05, // Flags: END_STREAM | END_HEADERS
+ 0x00, 0x00, 0x00, 0x02, // Stream ID: 0 (REQUIRES ID)
+ 'a', 'b', 'c', // HPACK fragment (doesn't have to be valid)
+ };
+ Http2FrameHeader header(
+ 3, Http2FrameType::HEADERS,
+ Http2FrameFlag::FLAG_END_STREAM | Http2FrameFlag::FLAG_END_HEADERS, 2);
+ FrameParts expected(header, "abc");
+ EXPECT_TRUE(DecodePayloadAndValidateSeveralWays(kFrameData, expected));
+}
+
+TEST_F(Http2FrameDecoderTest, HeadersPriority) {
+ const char kFrameData[] = {
+ 0x00, 0x00, 0x05, // Payload length: 5
+ 0x01, // HEADERS
+ 0x20, // Flags: PRIORITY
+ 0x00, 0x00, 0x00, 0x02, // Stream ID: 0 (REQUIRES ID)
+ 0x00, 0x00, 0x00, 0x01, // Parent: 1 (Not Exclusive)
+ 0xffu, // Weight: 256
+ };
+ Http2FrameHeader header(5, Http2FrameType::HEADERS,
+ Http2FrameFlag::FLAG_PRIORITY, 2);
+ FrameParts expected(header);
+ expected.opt_priority = Http2PriorityFields(1, 256, false);
+ EXPECT_TRUE(DecodePayloadAndValidateSeveralWays(kFrameData, expected));
+}
+
+TEST_F(Http2FrameDecoderTest, Settings) {
+ const char kFrameData[] = {
+ 0x00, 0x00, 0x0c, // Length: 12
+ 0x04, // Type: SETTINGS
+ 0x00, // Flags: none
+ 0x00, 0x00, 0x00, 0x00, // Stream: 0
+ 0x00, 0x04, // Param: INITIAL_WINDOW_SIZE
+ 0x0a, 0x0b, 0x0c, 0x0d, // Value: 168496141
+ 0x00, 0x02, // Param: ENABLE_PUSH
+ 0x00, 0x00, 0x00, 0x03, // Value: 3 (invalid but unchecked here)
+ };
+ Http2FrameHeader header(12, Http2FrameType::SETTINGS, 0, 0);
+ FrameParts expected(header);
+ expected.settings.push_back(Http2SettingFields(
+ Http2SettingsParameter::INITIAL_WINDOW_SIZE, 168496141));
+ expected.settings.push_back(
+ Http2SettingFields(Http2SettingsParameter::ENABLE_PUSH, 3));
+ EXPECT_TRUE(DecodePayloadAndValidateSeveralWays(kFrameData, expected));
+}
+
+TEST_F(Http2FrameDecoderTest, PushPromisePayload) {
+ const char kFrameData[] = {
+ 0x00, 0x00, 7, // Payload length: 7
+ 0x05, // PUSH_PROMISE
+ 0x04, // Flags: END_HEADERS
+ 0x00, 0x00, 0x00, 0xffu, // Stream ID: 255
+ 0x00, 0x00, 0x01, 0x00, // Promised: 256
+ 'a', 'b', 'c', // HPACK fragment (doesn't have to be valid)
+ };
+ Http2FrameHeader header(7, Http2FrameType::PUSH_PROMISE,
+ Http2FrameFlag::FLAG_END_HEADERS, 255);
+ FrameParts expected(header, "abc");
+ expected.opt_push_promise = Http2PushPromiseFields{256};
+ EXPECT_TRUE(DecodePayloadAndValidateSeveralWays(kFrameData, expected));
+}
+
+TEST_F(Http2FrameDecoderTest, GoAwayOpaqueData) {
+ const char kFrameData[] = {
+ 0x00, 0x00, 0x0e, // Length: 14
+ 0x07, // Type: GOAWAY
+ 0xffu, // Flags: 0xff (no valid flags)
+ 0x80u, 0x00, 0x00, 0x00, // Stream: 0 (plus R bit)
+ 0x00, 0x00, 0x01, 0x00, // Last: 256
+ 0x00, 0x00, 0x00, 0x03, // Error: FLOW_CONTROL_ERROR
+ 'o', 'p', 'a', 'q', 'u', 'e',
+ };
+ Http2FrameHeader header(14, Http2FrameType::GOAWAY, 0, 0);
+ FrameParts expected(header, "opaque");
+ expected.opt_goaway =
+ Http2GoAwayFields(256, Http2ErrorCode::FLOW_CONTROL_ERROR);
+ EXPECT_TRUE(DecodePayloadAndValidateSeveralWays(kFrameData, expected));
+}
+
+TEST_F(Http2FrameDecoderTest, ContinuationPayload) {
+ const char kFrameData[] = {
+ 0x00, 0x00, 0x03, // Payload length: 3
+ 0x09, // CONTINUATION
+ 0xffu, // Flags: END_HEADERS | 0xfb
+ 0x00, 0x00, 0x00, 0x02, // Stream ID: 2
+ 'a', 'b', 'c', // Data
+ };
+ Http2FrameHeader header(3, Http2FrameType::CONTINUATION,
+ Http2FrameFlag::FLAG_END_HEADERS, 2);
+ FrameParts expected(header, "abc");
+ EXPECT_TRUE(DecodePayloadAndValidateSeveralWays(kFrameData, expected));
+}
+
+TEST_F(Http2FrameDecoderTest, AltSvcPayload) {
+ const char kFrameData[] = {
+ 0x00, 0x00, 0x08, // Payload length: 3
+ 0x0a, // ALTSVC
+ 0x00, // Flags: none
+ 0x00, 0x00, 0x00, 0x02, // Stream ID: 2
+ 0x00, 0x03, // Origin Length: 0
+ 'a', 'b', 'c', // Origin
+ 'd', 'e', 'f', // Value
+ };
+ Http2FrameHeader header(8, Http2FrameType::ALTSVC, 0, 2);
+ FrameParts expected(header);
+ expected.SetAltSvcExpected("abc", "def");
+ EXPECT_TRUE(DecodePayloadAndValidateSeveralWays(kFrameData, expected));
+}
+
+TEST_F(Http2FrameDecoderTest, UnknownPayload) {
+ const char kFrameData[] = {
+ 0x00, 0x00, 0x03, // Payload length: 3
+ 0x30, // 48 (unknown)
+ 0x00, // Flags: none
+ 0x00, 0x00, 0x00, 0x02, // Stream ID: 2
+ 'a', 'b', 'c', // Payload
+ };
+ Http2FrameHeader header(3, static_cast<Http2FrameType>(48), 0, 2);
+ FrameParts expected(header, "abc");
+ EXPECT_TRUE(DecodePayloadAndValidateSeveralWays(kFrameData, expected));
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// Tests of padded payloads, for those frame types that allow padding.
+
+TEST_F(Http2FrameDecoderTest, DataPayloadAndPadding) {
+ const char kFrameData[] = {
+ 0x00, 0x00, 0x07, // Payload length: 7
+ 0x00, // DATA
+ 0x09, // Flags: END_STREAM | PADDED
+ 0x00, 0x00, 0x00, 0x02, // Stream ID: 0 (REQUIRES ID)
+ 0x03, // Pad Len
+ 'a', 'b', 'c', // Data
+ 0x00, 0x00, 0x00, // Padding
+ };
+ Http2FrameHeader header(
+ 7, Http2FrameType::DATA,
+ Http2FrameFlag::FLAG_END_STREAM | Http2FrameFlag::FLAG_PADDED, 2);
+ size_t total_pad_length = 4; // Including the Pad Length field.
+ FrameParts expected(header, "abc", total_pad_length);
+ EXPECT_TRUE(DecodePayloadAndValidateSeveralWays(kFrameData, expected));
+}
+
+TEST_F(Http2FrameDecoderTest, HeadersPayloadAndPadding) {
+ const char kFrameData[] = {
+ 0x00, 0x00, 0x07, // Payload length: 7
+ 0x01, // HEADERS
+ 0x08, // Flags: PADDED
+ 0x00, 0x00, 0x00, 0x02, // Stream ID: 0 (REQUIRES ID)
+ 0x03, // Pad Len
+ 'a', 'b', 'c', // HPACK fragment (doesn't have to be valid)
+ 0x00, 0x00, 0x00, // Padding
+ };
+ Http2FrameHeader header(7, Http2FrameType::HEADERS,
+ Http2FrameFlag::FLAG_PADDED, 2);
+ size_t total_pad_length = 4; // Including the Pad Length field.
+ FrameParts expected(header, "abc", total_pad_length);
+ EXPECT_TRUE(DecodePayloadAndValidateSeveralWays(kFrameData, expected));
+}
+
+TEST_F(Http2FrameDecoderTest, HeadersPayloadPriorityAndPadding) {
+ const char kFrameData[] = {
+ 0x00, 0x00, 0x0c, // Payload length: 12
+ 0x01, // HEADERS
+ 0xffu, // Flags: all, including undefined
+ 0x00, 0x00, 0x00, 0x02, // Stream ID: 0 (REQUIRES ID)
+ 0x03, // Pad Len
+ 0x80u, 0x00, 0x00, 0x01, // Parent: 1 (Exclusive)
+ 0x10, // Weight: 17
+ 'a', 'b', 'c', // HPACK fragment (doesn't have to be valid)
+ 0x00, 0x00, 0x00, // Padding
+ };
+ Http2FrameHeader header(
+ 12, Http2FrameType::HEADERS,
+ Http2FrameFlag::FLAG_END_STREAM | Http2FrameFlag::FLAG_END_HEADERS |
+ Http2FrameFlag::FLAG_PADDED | Http2FrameFlag::FLAG_PRIORITY,
+ 2);
+ size_t total_pad_length = 4; // Including the Pad Length field.
+ FrameParts expected(header, "abc", total_pad_length);
+ expected.opt_priority = Http2PriorityFields(1, 17, true);
+ EXPECT_TRUE(DecodePayloadAndValidateSeveralWays(kFrameData, expected));
+}
+
+TEST_F(Http2FrameDecoderTest, PushPromisePayloadAndPadding) {
+ const char kFrameData[] = {
+ 0x00, 0x00, 11, // Payload length: 11
+ 0x05, // PUSH_PROMISE
+ 0xffu, // Flags: END_HEADERS | PADDED | 0xf3
+ 0x00, 0x00, 0x00, 0x01, // Stream ID: 1
+ 0x03, // Pad Len
+ 0x00, 0x00, 0x00, 0x02, // Promised: 2
+ 'a', 'b', 'c', // HPACK fragment (doesn't have to be valid)
+ 0x00, 0x00, 0x00, // Padding
+ };
+ Http2FrameHeader header(
+ 11, Http2FrameType::PUSH_PROMISE,
+ Http2FrameFlag::FLAG_END_HEADERS | Http2FrameFlag::FLAG_PADDED, 1);
+ size_t total_pad_length = 4; // Including the Pad Length field.
+ FrameParts expected(header, "abc", total_pad_length);
+ expected.opt_push_promise = Http2PushPromiseFields{2};
+ EXPECT_TRUE(DecodePayloadAndValidateSeveralWays(kFrameData, expected));
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// Payload too short errors.
+
+TEST_F(Http2FrameDecoderTest, DataMissingPadLengthField) {
+ const char kFrameData[] = {
+ 0x00, 0x00, 0x00, // Payload length: 0
+ 0x00, // DATA
+ 0x08, // Flags: PADDED
+ 0x00, 0x00, 0x00, 0x01, // Stream ID: 1
+ };
+ Http2FrameHeader header(0, Http2FrameType::DATA, Http2FrameFlag::FLAG_PADDED,
+ 1);
+ FrameParts expected(header);
+ expected.opt_missing_length = 1;
+ EXPECT_TRUE(DecodePayloadExpectingError(kFrameData, expected));
+}
+
+TEST_F(Http2FrameDecoderTest, HeaderPaddingTooLong) {
+ const char kFrameData[] = {
+ 0x00, 0x00, 0x02, // Payload length: 0
+ 0x01, // HEADERS
+ 0x08, // Flags: PADDED
+ 0x00, 0x01, 0x00, 0x00, // Stream ID: 65536
+ 0xffu, // Pad Len: 255
+ 0x00, // Only one byte of padding
+ };
+ Http2FrameHeader header(2, Http2FrameType::HEADERS,
+ Http2FrameFlag::FLAG_PADDED, 65536);
+ FrameParts expected(header);
+ expected.opt_missing_length = 254;
+ EXPECT_TRUE(DecodePayloadExpectingError(kFrameData, expected));
+}
+
+TEST_F(Http2FrameDecoderTest, HeaderMissingPriority) {
+ const char kFrameData[] = {
+ 0x00, 0x00, 0x04, // Payload length: 0
+ 0x01, // HEADERS
+ 0x20, // Flags: PRIORITY
+ 0x00, 0x01, 0x00, 0x00, // Stream ID: 65536
+ 0x00, 0x00, 0x00, 0x00, // Priority (truncated)
+ };
+ Http2FrameHeader header(4, Http2FrameType::HEADERS,
+ Http2FrameFlag::FLAG_PRIORITY, 65536);
+ EXPECT_TRUE(DecodePayloadExpectingFrameSizeError(kFrameData, header));
+}
+
+TEST_F(Http2FrameDecoderTest, PriorityTooShort) {
+ const char kFrameData[] = {
+ 0x00, 0x00, 0x04, // Length: 5
+ 0x02, // Type: PRIORITY
+ 0x00, // Flags: none
+ 0x00, 0x00, 0x00, 0x02, // Stream: 2
+ 0x80u, 0x00, 0x00, 0x01, // Parent: 1 (Exclusive)
+ };
+ Http2FrameHeader header(4, Http2FrameType::PRIORITY, 0, 2);
+ EXPECT_TRUE(DecodePayloadExpectingFrameSizeError(kFrameData, header));
+}
+
+TEST_F(Http2FrameDecoderTest, RstStreamTooShort) {
+ const char kFrameData[] = {
+ 0x00, 0x00, 0x03, // Length: 4
+ 0x03, // Type: RST_STREAM
+ 0x00, // Flags: none
+ 0x00, 0x00, 0x00, 0x01, // Stream: 1
+ 0x00, 0x00, 0x00, // Truncated
+ };
+ Http2FrameHeader header(3, Http2FrameType::RST_STREAM, 0, 1);
+ EXPECT_TRUE(DecodePayloadExpectingFrameSizeError(kFrameData, header));
+}
+
+// SETTINGS frames must a multiple of 6 bytes long, so an 9 byte payload is
+// invalid.
+TEST_F(Http2FrameDecoderTest, SettingsWrongSize) {
+ const char kFrameData[] = {
+ 0x00, 0x00, 0x09, // Length: 2
+ 0x04, // Type: SETTINGS
+ 0x00, // Flags: none
+ 0x00, 0x00, 0x00, 0x00, // Stream: 0
+ 0x00, 0x02, // Param: ENABLE_PUSH
+ 0x00, 0x00, 0x00, 0x03, // Value: 1
+ 0x00, 0x04, // Param: INITIAL_WINDOW_SIZE
+ 0x00, // Value: Truncated
+ };
+ Http2FrameHeader header(9, Http2FrameType::SETTINGS, 0, 0);
+ FrameParts expected(header);
+ expected.settings.push_back(
+ Http2SettingFields(Http2SettingsParameter::ENABLE_PUSH, 3));
+ EXPECT_TRUE(DecodePayloadExpectingFrameSizeError(kFrameData, expected));
+}
+
+TEST_F(Http2FrameDecoderTest, PushPromiseTooShort) {
+ const char kFrameData[] = {
+ 0x00, 0x00, 3, // Payload length: 3
+ 0x05, // PUSH_PROMISE
+ 0x00, // Flags: none
+ 0x00, 0x00, 0x00, 0x01, // Stream ID: 1
+ 0x00, 0x00, 0x00, // Truncated promise id
+ };
+ Http2FrameHeader header(3, Http2FrameType::PUSH_PROMISE, 0, 1);
+ EXPECT_TRUE(DecodePayloadExpectingFrameSizeError(kFrameData, header));
+}
+
+TEST_F(Http2FrameDecoderTest, PushPromisePaddedTruncatedPromise) {
+ const char kFrameData[] = {
+ 0x00, 0x00, 4, // Payload length: 4
+ 0x05, // PUSH_PROMISE
+ 0x08, // Flags: PADDED
+ 0x00, 0x00, 0x00, 0x01, // Stream ID: 1
+ 0x00, // Pad Len
+ 0x00, 0x00, 0x00, // Truncated promise id
+ };
+ Http2FrameHeader header(4, Http2FrameType::PUSH_PROMISE,
+ Http2FrameFlag::FLAG_PADDED, 1);
+ EXPECT_TRUE(DecodePayloadExpectingFrameSizeError(kFrameData, header));
+}
+
+TEST_F(Http2FrameDecoderTest, PingTooShort) {
+ const char kFrameData[] = {
+ 0x00, 0x00, 0x07, // Length: 8
+ 0x06, // Type: PING
+ 0xfeu, // Flags: no valid flags
+ 0x00, 0x00, 0x00, 0x00, // Stream: 0
+ 's', 'o', 'm', 'e', // "some"
+ 'd', 'a', 't', // Too little
+ };
+ Http2FrameHeader header(7, Http2FrameType::PING, 0, 0);
+ EXPECT_TRUE(DecodePayloadExpectingFrameSizeError(kFrameData, header));
+}
+
+TEST_F(Http2FrameDecoderTest, GoAwayTooShort) {
+ const char kFrameData[] = {
+ 0x00, 0x00, 0x00, // Length: 0
+ 0x07, // Type: GOAWAY
+ 0xffu, // Flags: 0xff (no valid flags)
+ 0x00, 0x00, 0x00, 0x00, // Stream: 0
+ };
+ Http2FrameHeader header(0, Http2FrameType::GOAWAY, 0, 0);
+ EXPECT_TRUE(DecodePayloadExpectingFrameSizeError(kFrameData, header));
+}
+
+TEST_F(Http2FrameDecoderTest, WindowUpdateTooShort) {
+ const char kFrameData[] = {
+ 0x00, 0x00, 0x03, // Length: 3
+ 0x08, // Type: WINDOW_UPDATE
+ 0x0f, // Flags: 0xff (no valid flags)
+ 0x00, 0x00, 0x00, 0x01, // Stream: 1
+ 0x80u, 0x00, 0x04, // Truncated
+ };
+ Http2FrameHeader header(3, Http2FrameType::WINDOW_UPDATE, 0, 1);
+ EXPECT_TRUE(DecodePayloadExpectingFrameSizeError(kFrameData, header));
+}
+
+TEST_F(Http2FrameDecoderTest, AltSvcTruncatedOriginLength) {
+ const char kFrameData[] = {
+ 0x00, 0x00, 0x01, // Payload length: 3
+ 0x0a, // ALTSVC
+ 0x00, // Flags: none
+ 0x00, 0x00, 0x00, 0x02, // Stream ID: 2
+ 0x00, // Origin Length: truncated
+ };
+ Http2FrameHeader header(1, Http2FrameType::ALTSVC, 0, 2);
+ EXPECT_TRUE(DecodePayloadExpectingFrameSizeError(kFrameData, header));
+}
+
+TEST_F(Http2FrameDecoderTest, AltSvcTruncatedOrigin) {
+ const char kFrameData[] = {
+ 0x00, 0x00, 0x05, // Payload length: 3
+ 0x0a, // ALTSVC
+ 0x00, // Flags: none
+ 0x00, 0x00, 0x00, 0x02, // Stream ID: 2
+ 0x00, 0x04, // Origin Length: 4 (too long)
+ 'a', 'b', 'c', // Origin
+ };
+ Http2FrameHeader header(5, Http2FrameType::ALTSVC, 0, 2);
+ EXPECT_TRUE(DecodePayloadExpectingFrameSizeError(kFrameData, header));
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// Payload too long errors.
+
+// The decoder calls the listener's OnFrameSizeError method if the frame's
+// payload is longer than the currently configured maximum payload size.
+TEST_F(Http2FrameDecoderTest, BeyondMaximum) {
+ decoder_.set_maximum_payload_size(2);
+ const char kFrameData[] = {
+ 0x00, 0x00, 0x07, // Payload length: 7
+ 0x00, // DATA
+ 0x09, // Flags: END_STREAM | PADDED
+ 0x00, 0x00, 0x00, 0x02, // Stream ID: 0 (REQUIRES ID)
+ 0x03, // Pad Len
+ 'a', 'b', 'c', // Data
+ 0x00, 0x00, 0x00, // Padding
+ };
+ Http2FrameHeader header(
+ 7, Http2FrameType::DATA,
+ Http2FrameFlag::FLAG_END_STREAM | Http2FrameFlag::FLAG_PADDED, 2);
+ FrameParts expected(header);
+ expected.has_frame_size_error = true;
+ auto validator = [&expected, this](const DecodeBuffer& input,
+ DecodeStatus status) -> AssertionResult {
+ VERIFY_EQ(status, DecodeStatus::kDecodeError);
+ // The decoder detects this error after decoding the header, and without
+ // trying to decode the payload.
+ VERIFY_EQ(input.Offset(), Http2FrameHeader::EncodedSize());
+ VERIFY_AND_RETURN_SUCCESS(VerifyCollected(expected));
+ };
+ ResetDecodeSpeedCounters();
+ EXPECT_TRUE(DecodePayloadAndValidateSeveralWays(ToStringPiece(kFrameData),
+ validator));
+ EXPECT_GT(fast_decode_count_, 0u);
+ EXPECT_GT(slow_decode_count_, 0u);
+}
+
+TEST_F(Http2FrameDecoderTest, PriorityTooLong) {
+ const char kFrameData[] = {
+ 0x00, 0x00, 0x06, // Length: 5
+ 0x02, // Type: PRIORITY
+ 0x00, // Flags: none
+ 0x00, 0x00, 0x00, 0x02, // Stream: 2
+ 0x80u, 0x00, 0x00, 0x01, // Parent: 1 (Exclusive)
+ 0x10, // Weight: 17
+ 0x00, // Too much
+ };
+ Http2FrameHeader header(6, Http2FrameType::PRIORITY, 0, 2);
+ EXPECT_TRUE(DecodePayloadExpectingFrameSizeError(kFrameData, header));
+}
+
+TEST_F(Http2FrameDecoderTest, RstStreamTooLong) {
+ const char kFrameData[] = {
+ 0x00, 0x00, 0x05, // Length: 4
+ 0x03, // Type: RST_STREAM
+ 0x00, // Flags: none
+ 0x00, 0x00, 0x00, 0x01, // Stream: 1
+ 0x00, 0x00, 0x00, 0x01, // Error: PROTOCOL_ERROR
+ 0x00, // Too much
+ };
+ Http2FrameHeader header(5, Http2FrameType::RST_STREAM, 0, 1);
+ EXPECT_TRUE(DecodePayloadExpectingFrameSizeError(kFrameData, header));
+}
+
+TEST_F(Http2FrameDecoderTest, SettingsAckTooLong) {
+ const char kFrameData[] = {
+ 0x00, 0x00, 0x06, // Length: 6
+ 0x04, // Type: SETTINGS
+ 0x01, // Flags: ACK
+ 0x00, 0x00, 0x00, 0x00, // Stream: 0
+ 0x00, 0x00, // Extra
+ 0x00, 0x00, 0x00, 0x00, // Extra
+ };
+ Http2FrameHeader header(6, Http2FrameType::SETTINGS, Http2FrameFlag::FLAG_ACK,
+ 0);
+ EXPECT_TRUE(DecodePayloadExpectingFrameSizeError(kFrameData, header));
+}
+
+TEST_F(Http2FrameDecoderTest, PingAckTooLong) {
+ const char kFrameData[] = {
+ 0x00, 0x00, 0x09, // Length: 8
+ 0x06, // Type: PING
+ 0xffu, // Flags: ACK | 0xfe
+ 0x00, 0x00, 0x00, 0x00, // Stream: 0
+ 's', 'o', 'm', 'e', // "some"
+ 'd', 'a', 't', 'a', // "data"
+ 0x00, // Too much
+ };
+ Http2FrameHeader header(9, Http2FrameType::PING, Http2FrameFlag::FLAG_ACK, 0);
+ EXPECT_TRUE(DecodePayloadExpectingFrameSizeError(kFrameData, header));
+}
+
+TEST_F(Http2FrameDecoderTest, WindowUpdateTooLong) {
+ const char kFrameData[] = {
+ 0x00, 0x00, 0x05, // Length: 5
+ 0x08, // Type: WINDOW_UPDATE
+ 0x0f, // Flags: 0xff (no valid flags)
+ 0x00, 0x00, 0x00, 0x01, // Stream: 1
+ 0x80u, 0x00, 0x04, 0x00, // Incr: 1024 (plus R bit)
+ 0x00, // Too much
+ };
+ Http2FrameHeader header(5, Http2FrameType::WINDOW_UPDATE, 0, 1);
+ EXPECT_TRUE(DecodePayloadExpectingFrameSizeError(kFrameData, header));
+}
+
+} // namespace
+} // namespace test
+} // namespace net
diff --git a/chromium/net/http2/decoder/http2_structure_decoder.cc b/chromium/net/http2/decoder/http2_structure_decoder.cc
new file mode 100644
index 00000000000..a7b1dca47a3
--- /dev/null
+++ b/chromium/net/http2/decoder/http2_structure_decoder.cc
@@ -0,0 +1,90 @@
+// Copyright 2016 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.
+
+#include "net/http2/decoder/http2_structure_decoder.h"
+
+#include <algorithm>
+
+#include "net/http2/tools/http2_bug_tracker.h"
+
+namespace net {
+
+// Below we have some defensive coding: if we somehow run off the end, don't
+// overwrite lots of memory. Note that most of this decoder is not defensive
+// against bugs in the decoder, only against malicious encoders, but since
+// we're copying memory into a buffer here, let's make sure we don't allow a
+// small mistake to grow larger. The decoder will get stuck if we hit the
+// HTTP2_BUG conditions, but shouldn't corrupt memory.
+
+uint32_t Http2StructureDecoder::IncompleteStart(DecodeBuffer* db,
+ uint32_t target_size) {
+ if (target_size > sizeof buffer_) {
+ HTTP2_BUG << "target_size too large for buffer: " << target_size;
+ return 0;
+ }
+ const uint32_t num_to_copy = db->MinLengthRemaining(target_size);
+ memcpy(buffer_, db->cursor(), num_to_copy);
+ offset_ = num_to_copy;
+ db->AdvanceCursor(num_to_copy);
+ return num_to_copy;
+}
+
+DecodeStatus Http2StructureDecoder::IncompleteStart(DecodeBuffer* db,
+ uint32_t* remaining_payload,
+ uint32_t target_size) {
+ DVLOG(1) << "IncompleteStart@" << this
+ << ": *remaining_payload=" << *remaining_payload
+ << "; target_size=" << target_size
+ << "; db->Remaining=" << db->Remaining();
+ *remaining_payload -=
+ IncompleteStart(db, std::min(target_size, *remaining_payload));
+ if (*remaining_payload > 0 && db->Empty()) {
+ return DecodeStatus::kDecodeInProgress;
+ }
+ DVLOG(1) << "IncompleteStart: kDecodeError";
+ return DecodeStatus::kDecodeError;
+}
+
+bool Http2StructureDecoder::ResumeFillingBuffer(DecodeBuffer* db,
+ uint32_t target_size) {
+ DVLOG(2) << "ResumeFillingBuffer@" << this << ": target_size=" << target_size
+ << "; offset_=" << offset_ << "; db->Remaining=" << db->Remaining();
+ if (target_size < offset_) {
+ HTTP2_BUG << "Already filled buffer_! target_size=" << target_size
+ << " offset_=" << offset_;
+ return false;
+ }
+ const uint32_t needed = target_size - offset_;
+ const uint32_t num_to_copy = db->MinLengthRemaining(needed);
+ DVLOG(2) << "ResumeFillingBuffer num_to_copy=" << num_to_copy;
+ memcpy(&buffer_[offset_], db->cursor(), num_to_copy);
+ db->AdvanceCursor(num_to_copy);
+ offset_ += num_to_copy;
+ return needed == num_to_copy;
+}
+
+bool Http2StructureDecoder::ResumeFillingBuffer(DecodeBuffer* db,
+ uint32_t* remaining_payload,
+ uint32_t target_size) {
+ DVLOG(2) << "ResumeFillingBuffer@" << this << ": target_size=" << target_size
+ << "; offset_=" << offset_
+ << "; *remaining_payload=" << *remaining_payload
+ << "; db->Remaining=" << db->Remaining();
+ if (target_size < offset_) {
+ HTTP2_BUG << "Already filled buffer_! target_size=" << target_size
+ << " offset_=" << offset_;
+ return false;
+ }
+ const uint32_t needed = target_size - offset_;
+ const uint32_t num_to_copy =
+ db->MinLengthRemaining(std::min(needed, *remaining_payload));
+ DVLOG(2) << "ResumeFillingBuffer num_to_copy=" << num_to_copy;
+ memcpy(&buffer_[offset_], db->cursor(), num_to_copy);
+ db->AdvanceCursor(num_to_copy);
+ offset_ += num_to_copy;
+ *remaining_payload -= num_to_copy;
+ return needed == num_to_copy;
+}
+
+} // namespace net
diff --git a/chromium/net/http2/decoder/http2_structure_decoder.h b/chromium/net/http2/decoder/http2_structure_decoder.h
new file mode 100644
index 00000000000..8665e96cb21
--- /dev/null
+++ b/chromium/net/http2/decoder/http2_structure_decoder.h
@@ -0,0 +1,129 @@
+// Copyright 2016 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.
+
+#ifndef NET_HTTP2_DECODER_HTTP2_STRUCTURE_DECODER_H_
+#define NET_HTTP2_DECODER_HTTP2_STRUCTURE_DECODER_H_
+
+// Http2StructureDecoder is a class for decoding the fixed size structures in
+// the HTTP/2 spec, defined in net/http2/http2_structures.h. This class
+// is in aid of deciding whether to keep the SlowDecode methods which I
+// (jamessynge) now think may not be worth their complexity. In particular,
+// if most transport buffers are large, so it is rare that a structure is
+// split across buffer boundaries, than the cost of buffering upon
+// those rare occurrences is small, which then simplifies the callers.
+
+#include "base/logging.h"
+#include "net/base/net_export.h"
+#include "net/http2/decoder/decode_buffer.h"
+#include "net/http2/decoder/decode_http2_structures.h"
+#include "net/http2/decoder/decode_status.h"
+#include "net/http2/http2_structures.h"
+
+namespace net {
+namespace test {
+class Http2StructureDecoderPeer;
+} // namespace test
+
+class NET_EXPORT_PRIVATE Http2StructureDecoder {
+ public:
+ // The caller needs to keep track of whether to call Start or Resume.
+ //
+ // Start has an optimization for the case where the DecodeBuffer holds the
+ // entire encoded structure; in that case it decodes into *out and returns
+ // true, and does NOT touch the data members of the Http2StructureDecoder
+ // instance because the caller won't be calling Resume later.
+ //
+ // However, if the DecodeBuffer is too small to hold the entire encoded
+ // structure, Start copies the available bytes into the Http2StructureDecoder
+ // instance, and returns false to indicate that it has not been able to
+ // complete the decoding.
+ //
+ template <class S>
+ bool Start(S* out, DecodeBuffer* db) {
+ static_assert(S::EncodedSize() <= sizeof buffer_, "buffer_ is too small");
+ DVLOG(2) << __func__ << "@" << this << ": db->Remaining=" << db->Remaining()
+ << "; EncodedSize=" << S::EncodedSize();
+ if (db->Remaining() >= S::EncodedSize()) {
+ DoDecode(out, db);
+ return true;
+ }
+ IncompleteStart(db, S::EncodedSize());
+ return false;
+ }
+
+ template <class S>
+ bool Resume(S* out, DecodeBuffer* db) {
+ DVLOG(2) << __func__ << "@" << this << ": offset_=" << offset_
+ << "; db->Remaining=" << db->Remaining();
+ if (ResumeFillingBuffer(db, S::EncodedSize())) {
+ // We have the whole thing now.
+ DVLOG(2) << __func__ << "@" << this << " offset_=" << offset_
+ << " Ready to decode from buffer_.";
+ DecodeBuffer buffer_db(buffer_, S::EncodedSize());
+ DoDecode(out, &buffer_db);
+ return true;
+ }
+ DCHECK_LT(offset_, S::EncodedSize());
+ return false;
+ }
+
+ // A second pair of Start and Resume, where the caller has a variable,
+ // |remaining_payload| that is both tested for sufficiency and updated
+ // during decoding. Note that the decode buffer may extend beyond the
+ // remaining payload because the buffer may include padding.
+ template <class S>
+ DecodeStatus Start(S* out, DecodeBuffer* db, uint32_t* remaining_payload) {
+ static_assert(S::EncodedSize() <= sizeof buffer_, "buffer_ is too small");
+ DVLOG(2) << __func__ << "@" << this
+ << ": *remaining_payload=" << *remaining_payload
+ << "; db->Remaining=" << db->Remaining()
+ << "; EncodedSize=" << S::EncodedSize();
+ if (db->MinLengthRemaining(*remaining_payload) >= S::EncodedSize()) {
+ DoDecode(out, db);
+ *remaining_payload -= S::EncodedSize();
+ return DecodeStatus::kDecodeDone;
+ }
+ return IncompleteStart(db, remaining_payload, S::EncodedSize());
+ }
+
+ template <class S>
+ bool Resume(S* out, DecodeBuffer* db, uint32_t* remaining_payload) {
+ DVLOG(3) << __func__ << "@" << this << ": offset_=" << offset_
+ << "; *remaining_payload=" << *remaining_payload
+ << "; db->Remaining=" << db->Remaining()
+ << "; EncodedSize=" << S::EncodedSize();
+ if (ResumeFillingBuffer(db, remaining_payload, S::EncodedSize())) {
+ // We have the whole thing now.
+ DVLOG(2) << __func__ << "@" << this << ": offset_=" << offset_
+ << "; Ready to decode from buffer_.";
+ DecodeBuffer buffer_db(buffer_, S::EncodedSize());
+ DoDecode(out, &buffer_db);
+ return true;
+ }
+ DCHECK_LT(offset_, S::EncodedSize());
+ return false;
+ }
+
+ uint32_t offset() const { return offset_; }
+
+ private:
+ friend class test::Http2StructureDecoderPeer;
+
+ uint32_t IncompleteStart(DecodeBuffer* db, uint32_t target_size);
+ DecodeStatus IncompleteStart(DecodeBuffer* db,
+ uint32_t* remaining_payload,
+ uint32_t target_size);
+
+ bool ResumeFillingBuffer(DecodeBuffer* db, uint32_t target_size);
+ bool ResumeFillingBuffer(DecodeBuffer* db,
+ uint32_t* remaining_payload,
+ uint32_t target_size);
+
+ uint32_t offset_;
+ char buffer_[Http2FrameHeader::EncodedSize()];
+};
+
+} // namespace net
+
+#endif // NET_HTTP2_DECODER_HTTP2_STRUCTURE_DECODER_H_
diff --git a/chromium/net/http2/decoder/http2_structure_decoder_test.cc b/chromium/net/http2/decoder/http2_structure_decoder_test.cc
new file mode 100644
index 00000000000..3ff2f98f143
--- /dev/null
+++ b/chromium/net/http2/decoder/http2_structure_decoder_test.cc
@@ -0,0 +1,505 @@
+// Copyright 2016 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.
+
+#include "net/http2/decoder/http2_structure_decoder.h"
+
+// Tests decoding all of the fixed size HTTP/2 structures (i.e. those defined in
+// net/http2/http2_structures.h) using Http2StructureDecoder, which handles
+// buffering of structures split across input buffer boundaries, and in turn
+// uses DoDecode when it has all of a structure in a contiguous buffer.
+
+// NOTE: This tests the first pair of Start and Resume, which don't take
+// a remaining_payload parameter. The other pair are well tested via the
+// payload decoder tests, though...
+// TODO(jamessynge): Create type parameterized tests for Http2StructureDecoder
+// where the type is the type of structure, and with testing of both pairs of
+// Start and Resume methods; note that it appears that the first pair will be
+// used only for Http2FrameHeader, and the other pair only for structures in the
+// frame payload.
+
+#include <stddef.h>
+#include <string>
+
+#include "base/logging.h"
+#include "base/strings/string_piece.h"
+#include "net/http2/decoder/decode_buffer.h"
+#include "net/http2/decoder/decode_status.h"
+#include "net/http2/http2_constants.h"
+#include "net/http2/http2_structures_test_util.h"
+#include "net/http2/tools/failure.h"
+#include "net/http2/tools/http2_frame_builder.h"
+#include "net/http2/tools/random_decoder_test.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+using ::testing::AssertionFailure;
+using ::testing::AssertionResult;
+using ::testing::AssertionSuccess;
+using base::StringPiece;
+using std::string;
+
+namespace net {
+namespace test {
+namespace {
+const bool kMayReturnZeroOnFirst = false;
+
+template <class S>
+string SerializeStructure(const S& s) {
+ Http2FrameBuilder fb;
+ fb.Append(s);
+ EXPECT_EQ(S::EncodedSize(), fb.size());
+ return fb.buffer();
+}
+
+template <class S>
+class Http2StructureDecoderTest : public RandomDecoderTest {
+ protected:
+ typedef S Structure;
+
+ Http2StructureDecoderTest() {
+ // IF the test adds more data after the encoded structure, stop as
+ // soon as the structure is decoded.
+ stop_decode_on_done_ = true;
+ }
+
+ DecodeStatus StartDecoding(DecodeBuffer* b) override {
+ // Overwrite the current contents of |structure_|, in to which we'll
+ // decode the buffer, so that we can be confident that we really decoded
+ // the structure every time.
+ structure_.~S();
+ new (&structure_) S;
+ uint32_t old_remaining = b->Remaining();
+ if (structure_decoder_.Start(&structure_, b)) {
+ EXPECT_EQ(old_remaining - S::EncodedSize(), b->Remaining());
+ ++fast_decode_count_;
+ return DecodeStatus::kDecodeDone;
+ } else {
+ EXPECT_LT(structure_decoder_.offset(), S::EncodedSize());
+ EXPECT_EQ(0u, b->Remaining());
+ EXPECT_EQ(old_remaining - structure_decoder_.offset(), b->Remaining());
+ ++incomplete_start_count_;
+ return DecodeStatus::kDecodeInProgress;
+ }
+ }
+
+ DecodeStatus ResumeDecoding(DecodeBuffer* b) override {
+ uint32_t old_offset = structure_decoder_.offset();
+ EXPECT_LT(old_offset, S::EncodedSize());
+ uint32_t avail = b->Remaining();
+ if (structure_decoder_.Resume(&structure_, b)) {
+ EXPECT_LE(S::EncodedSize(), old_offset + avail);
+ EXPECT_EQ(b->Remaining(), avail - (S::EncodedSize() - old_offset));
+ ++slow_decode_count_;
+ return DecodeStatus::kDecodeDone;
+ } else {
+ EXPECT_LT(structure_decoder_.offset(), S::EncodedSize());
+ EXPECT_EQ(0u, b->Remaining());
+ EXPECT_GT(S::EncodedSize(), old_offset + avail);
+ ++incomplete_resume_count_;
+ return DecodeStatus::kDecodeInProgress;
+ }
+ }
+
+
+ // Fully decodes the Structure at the start of data, and confirms it matches
+ // *expected (if provided).
+ AssertionResult DecodeLeadingStructure(const S* expected, StringPiece data) {
+ VERIFY_LE(S::EncodedSize(), data.size());
+ DecodeBuffer original(data);
+
+ // The validator is called after each of the several times that the input
+ // DecodeBuffer is decoded, each with a different segmentation of the input.
+ // Validate that structure_ matches the expected value, if provided.
+ Validator validator;
+ if (expected != nullptr) {
+ validator = [expected, this](const DecodeBuffer& db,
+ DecodeStatus status) -> AssertionResult {
+ VERIFY_EQ(*expected, structure_);
+ return AssertionSuccess();
+ };
+ }
+
+ // Before that, validate that decoding is done and that we've advanced
+ // the cursor the expected amount.
+ validator = ValidateDoneAndOffset(S::EncodedSize(), validator);
+
+ // Decode several times, with several segmentations of the input buffer.
+ fast_decode_count_ = 0;
+ slow_decode_count_ = 0;
+ incomplete_start_count_ = 0;
+ incomplete_resume_count_ = 0;
+ VERIFY_SUCCESS(DecodeAndValidateSeveralWays(
+ &original, kMayReturnZeroOnFirst, validator));
+ VERIFY_FALSE(HasFailure());
+ VERIFY_EQ(S::EncodedSize(), structure_decoder_.offset());
+ VERIFY_EQ(S::EncodedSize(), original.Offset());
+ VERIFY_LT(0u, fast_decode_count_);
+ VERIFY_LT(0u, slow_decode_count_);
+ VERIFY_LT(0u, incomplete_start_count_);
+
+ // If the structure is large enough so that SelectZeroOrOne will have
+ // caused Resume to return false, check that occurred.
+ if (S::EncodedSize() >= 2) {
+ VERIFY_LE(0u, incomplete_resume_count_);
+ } else {
+ VERIFY_EQ(0u, incomplete_resume_count_);
+ }
+ if (expected != nullptr) {
+ DVLOG(1) << "DecodeLeadingStructure expected: " << *expected;
+ DVLOG(1) << "DecodeLeadingStructure actual: " << structure_;
+ VERIFY_EQ(*expected, structure_);
+ }
+ return AssertionSuccess();
+ }
+
+ template <size_t N>
+ AssertionResult DecodeLeadingStructure(const char (&data)[N]) {
+ VERIFY_AND_RETURN_SUCCESS(
+ DecodeLeadingStructure(nullptr, StringPiece(data, N)));
+ }
+
+ // Encode the structure |in_s| into bytes, then decode the bytes
+ // and validate that the decoder produced the same field values.
+ AssertionResult EncodeThenDecode(const S& in_s) {
+ string bytes = SerializeStructure(in_s);
+ VERIFY_EQ(S::EncodedSize(), bytes.size());
+ VERIFY_AND_RETURN_SUCCESS(DecodeLeadingStructure(&in_s, bytes));
+ }
+
+ // Repeatedly fill a structure with random but valid contents, encode it, then
+ // decode it, and finally validate that the decoded structure matches the
+ // random input. Lather-rinse-and-repeat.
+ AssertionResult TestDecodingRandomizedStructures(size_t count) {
+ for (size_t i = 0; i < count; ++i) {
+ Structure input;
+ Randomize(&input, RandomPtr());
+ VERIFY_SUCCESS(EncodeThenDecode(input));
+ }
+ return AssertionSuccess();
+ }
+
+ AssertionResult TestDecodingRandomizedStructures() {
+ VERIFY_SUCCESS(TestDecodingRandomizedStructures(100));
+ return AssertionSuccess();
+ }
+
+ uint32_t decode_offset_ = 0;
+ S structure_;
+ Http2StructureDecoder structure_decoder_;
+ size_t fast_decode_count_ = 0;
+ size_t slow_decode_count_ = 0;
+ size_t incomplete_start_count_ = 0;
+ size_t incomplete_resume_count_ = 0;
+};
+
+class Http2FrameHeaderDecoderTest
+ : public Http2StructureDecoderTest<Http2FrameHeader> {};
+
+TEST_F(Http2FrameHeaderDecoderTest, DecodesLiteral) {
+ {
+ // Realistic input.
+ const char kData[] = {
+ 0x00, 0x00, 0x05, // Payload length: 5
+ 0x01, // Frame type: HEADERS
+ 0x08, // Flags: PADDED
+ 0x00, 0x00, 0x00, 0x01, // Stream ID: 1
+ 0x04, // Padding length: 4
+ 0x00, 0x00, 0x00, 0x00, // Padding bytes
+ };
+ ASSERT_TRUE(DecodeLeadingStructure(kData));
+ EXPECT_EQ(5u, structure_.payload_length);
+ EXPECT_EQ(Http2FrameType::HEADERS, structure_.type);
+ EXPECT_EQ(Http2FrameFlag::FLAG_PADDED, structure_.flags);
+ EXPECT_EQ(1u, structure_.stream_id);
+ }
+ {
+ // Unlikely input.
+ const char kData[] = {
+ 0xffu, 0xffu, 0xffu, // Payload length: uint24 max
+ 0xffu, // Frame type: Unknown
+ 0xffu, // Flags: Unknown/All
+ 0xffu, 0xffu, 0xffu, 0xffu, // Stream ID: uint31 max, plus R-bit
+ };
+ ASSERT_TRUE(DecodeLeadingStructure(kData));
+ EXPECT_EQ((1u << 24) - 1u, structure_.payload_length);
+ EXPECT_EQ(static_cast<Http2FrameType>(255), structure_.type);
+ EXPECT_EQ(255, structure_.flags);
+ EXPECT_EQ(0x7FFFFFFFu, structure_.stream_id);
+ }
+}
+
+TEST_F(Http2FrameHeaderDecoderTest, DecodesRandomized) {
+ TestDecodingRandomizedStructures();
+}
+
+//------------------------------------------------------------------------------
+
+class Http2PriorityFieldsDecoderTest
+ : public Http2StructureDecoderTest<Http2PriorityFields> {};
+
+TEST_F(Http2PriorityFieldsDecoderTest, DecodesLiteral) {
+ {
+ const char kData[] = {
+ 0x80u, 0x00, 0x00, 0x05, // Exclusive (yes) and Dependency (5)
+ 0xffu, // Weight: 256 (after adding 1)
+ };
+ ASSERT_TRUE(DecodeLeadingStructure(kData));
+ EXPECT_EQ(5u, structure_.stream_dependency);
+ EXPECT_EQ(256u, structure_.weight);
+ EXPECT_EQ(true, structure_.is_exclusive);
+ }
+ {
+ const char kData[] = {
+ 0x7fu, 0xffu,
+ 0xffu, 0xffu, // Exclusive (no) and Dependency (0x7fffffff)
+ 0x00u, // Weight: 1 (after adding 1)
+ };
+ ASSERT_TRUE(DecodeLeadingStructure(kData));
+ EXPECT_EQ(StreamIdMask(), structure_.stream_dependency);
+ EXPECT_EQ(1u, structure_.weight);
+ EXPECT_FALSE(structure_.is_exclusive);
+ }
+}
+
+TEST_F(Http2PriorityFieldsDecoderTest, DecodesRandomized) {
+ TestDecodingRandomizedStructures();
+}
+
+//------------------------------------------------------------------------------
+
+class Http2RstStreamFieldsDecoderTest
+ : public Http2StructureDecoderTest<Http2RstStreamFields> {};
+
+TEST_F(Http2RstStreamFieldsDecoderTest, DecodesLiteral) {
+ {
+ const char kData[] = {
+ 0x00, 0x00, 0x00, 0x01, // Error: PROTOCOL_ERROR
+ };
+ ASSERT_TRUE(DecodeLeadingStructure(kData));
+ EXPECT_TRUE(structure_.IsSupportedErrorCode());
+ EXPECT_EQ(Http2ErrorCode::PROTOCOL_ERROR, structure_.error_code);
+ }
+ {
+ const char kData[] = {
+ 0xffu, 0xffu, 0xffu, 0xffu, // Error: max uint32 (Unknown error code)
+ };
+ ASSERT_TRUE(DecodeLeadingStructure(kData));
+ EXPECT_FALSE(structure_.IsSupportedErrorCode());
+ EXPECT_EQ(static_cast<Http2ErrorCode>(0xffffffff), structure_.error_code);
+ }
+}
+
+TEST_F(Http2RstStreamFieldsDecoderTest, DecodesRandomized) {
+ TestDecodingRandomizedStructures();
+}
+
+//------------------------------------------------------------------------------
+
+class Http2SettingFieldsDecoderTest
+ : public Http2StructureDecoderTest<Http2SettingFields> {};
+
+TEST_F(Http2SettingFieldsDecoderTest, DecodesLiteral) {
+ {
+ const char kData[] = {
+ 0x00, 0x01, // Setting: HEADER_TABLE_SIZE
+ 0x00, 0x00, 0x40, 0x00, // Value: 16K
+ };
+ ASSERT_TRUE(DecodeLeadingStructure(kData));
+ EXPECT_TRUE(structure_.IsSupportedParameter());
+ EXPECT_EQ(Http2SettingsParameter::HEADER_TABLE_SIZE, structure_.parameter);
+ EXPECT_EQ(1u << 14, structure_.value);
+ }
+ {
+ const char kData[] = {
+ 0x00, 0x00, // Setting: Unknown (0)
+ 0xffu, 0xffu, 0xffu, 0xffu, // Value: max uint32
+ };
+ ASSERT_TRUE(DecodeLeadingStructure(kData));
+ EXPECT_FALSE(structure_.IsSupportedParameter());
+ EXPECT_EQ(static_cast<Http2SettingsParameter>(0), structure_.parameter);
+ }
+}
+
+TEST_F(Http2SettingFieldsDecoderTest, DecodesRandomized) {
+ TestDecodingRandomizedStructures();
+}
+
+//------------------------------------------------------------------------------
+
+class Http2PushPromiseFieldsDecoderTest
+ : public Http2StructureDecoderTest<Http2PushPromiseFields> {};
+
+TEST_F(Http2PushPromiseFieldsDecoderTest, DecodesLiteral) {
+ {
+ const char kData[] = {
+ 0x00, 0x01, 0x8au, 0x92u, // Promised Stream ID: 101010
+ };
+ ASSERT_TRUE(DecodeLeadingStructure(kData));
+ EXPECT_EQ(101010u, structure_.promised_stream_id);
+ }
+ {
+ // Promised stream id has R-bit (reserved for future use) set, which
+ // should be cleared by the decoder.
+ const char kData[] = {
+ 0xffu, 0xffu, 0xffu, 0xffu, // Promised Stream ID: max uint31 and R-bit
+ };
+ ASSERT_TRUE(DecodeLeadingStructure(kData));
+ EXPECT_EQ(StreamIdMask(), structure_.promised_stream_id);
+ }
+}
+
+TEST_F(Http2PushPromiseFieldsDecoderTest, DecodesRandomized) {
+ TestDecodingRandomizedStructures();
+}
+
+//------------------------------------------------------------------------------
+
+class Http2PingFieldsDecoderTest
+ : public Http2StructureDecoderTest<Http2PingFields> {};
+
+TEST_F(Http2PingFieldsDecoderTest, DecodesLiteral) {
+ {
+ // Each byte is different, so can detect if order changed.
+ const char kData[] = {
+ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+ };
+ ASSERT_TRUE(DecodeLeadingStructure(kData));
+ EXPECT_EQ(StringPiece(kData, 8), ToStringPiece(structure_.opaque_data));
+ }
+ {
+ // All zeros, detect problems handling NULs.
+ const char kData[] = {
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ };
+ ASSERT_TRUE(DecodeLeadingStructure(kData));
+ EXPECT_EQ(StringPiece(kData, 8), ToStringPiece(structure_.opaque_data));
+ }
+ {
+ const char kData[] = {
+ 0xffu, 0xffu, 0xffu, 0xffu, 0xffu, 0xffu, 0xffu, 0xffu,
+ };
+ ASSERT_TRUE(DecodeLeadingStructure(kData));
+ EXPECT_EQ(StringPiece(kData, 8), ToStringPiece(structure_.opaque_data));
+ }
+}
+
+TEST_F(Http2PingFieldsDecoderTest, DecodesRandomized) {
+ TestDecodingRandomizedStructures();
+}
+
+//------------------------------------------------------------------------------
+
+class Http2GoAwayFieldsDecoderTest
+ : public Http2StructureDecoderTest<Http2GoAwayFields> {};
+
+TEST_F(Http2GoAwayFieldsDecoderTest, DecodesLiteral) {
+ {
+ const char kData[] = {
+ 0x00, 0x00, 0x00, 0x00, // Last Stream ID: 0
+ 0x00, 0x00, 0x00, 0x00, // Error: NO_ERROR (0)
+ };
+ ASSERT_TRUE(DecodeLeadingStructure(kData));
+ EXPECT_EQ(0u, structure_.last_stream_id);
+ EXPECT_TRUE(structure_.IsSupportedErrorCode());
+ EXPECT_EQ(Http2ErrorCode::HTTP2_NO_ERROR, structure_.error_code);
+ }
+ {
+ const char kData[] = {
+ 0x00, 0x00, 0x00, 0x01, // Last Stream ID: 1
+ 0x00, 0x00, 0x00, 0x0d, // Error: HTTP_1_1_REQUIRED
+ };
+ ASSERT_TRUE(DecodeLeadingStructure(kData));
+ EXPECT_EQ(1u, structure_.last_stream_id);
+ EXPECT_TRUE(structure_.IsSupportedErrorCode());
+ EXPECT_EQ(Http2ErrorCode::HTTP_1_1_REQUIRED, structure_.error_code);
+ }
+ {
+ const char kData[] = {
+ 0xffu, 0xffu, 0xffu, 0xffu, // Last Stream ID: max uint31 and R-bit
+ 0xffu, 0xffu, 0xffu, 0xffu, // Error: max uint32 (Unknown error code)
+ };
+ ASSERT_TRUE(DecodeLeadingStructure(kData));
+ EXPECT_EQ(StreamIdMask(), structure_.last_stream_id); // No high-bit.
+ EXPECT_FALSE(structure_.IsSupportedErrorCode());
+ EXPECT_EQ(static_cast<Http2ErrorCode>(0xffffffff), structure_.error_code);
+ }
+}
+
+TEST_F(Http2GoAwayFieldsDecoderTest, DecodesRandomized) {
+ TestDecodingRandomizedStructures();
+}
+
+//------------------------------------------------------------------------------
+
+class Http2WindowUpdateFieldsDecoderTest
+ : public Http2StructureDecoderTest<Http2WindowUpdateFields> {};
+
+TEST_F(Http2WindowUpdateFieldsDecoderTest, DecodesLiteral) {
+ {
+ const char kData[] = {
+ 0x00, 0x01, 0x00, 0x00, // Window Size Increment: 2 ^ 16
+ };
+ ASSERT_TRUE(DecodeLeadingStructure(kData));
+ EXPECT_EQ(1u << 16, structure_.window_size_increment);
+ }
+ {
+ // Increment must be non-zero, but we need to be able to decode the invalid
+ // zero to detect it.
+ const char kData[] = {
+ 0x00, 0x00, 0x00, 0x00, // Window Size Increment: 0
+ };
+ ASSERT_TRUE(DecodeLeadingStructure(kData));
+ EXPECT_EQ(0u, structure_.window_size_increment);
+ }
+ {
+ // Increment has R-bit (reserved for future use) set, which
+ // should be cleared by the decoder.
+ const char kData[] = {
+ 0xffu, 0xffu, 0xffu,
+ 0xffu, // Window Size Increment: max uint31 and R-bit
+ };
+ ASSERT_TRUE(DecodeLeadingStructure(kData));
+ EXPECT_EQ(StreamIdMask(), structure_.window_size_increment);
+ }
+}
+
+TEST_F(Http2WindowUpdateFieldsDecoderTest, DecodesRandomized) {
+ TestDecodingRandomizedStructures();
+}
+
+//------------------------------------------------------------------------------
+
+class Http2AltSvcFieldsDecoderTest
+ : public Http2StructureDecoderTest<Http2AltSvcFields> {};
+
+TEST_F(Http2AltSvcFieldsDecoderTest, DecodesLiteral) {
+ {
+ const char kData[] = {
+ 0x00, 0x00, // Origin Length: 0
+ };
+ ASSERT_TRUE(DecodeLeadingStructure(kData));
+ EXPECT_EQ(0, structure_.origin_length);
+ }
+ {
+ const char kData[] = {
+ 0x00, 0x14, // Origin Length: 20
+ };
+ ASSERT_TRUE(DecodeLeadingStructure(kData));
+ EXPECT_EQ(20, structure_.origin_length);
+ }
+ {
+ const char kData[] = {
+ 0xffu, 0xffu, // Origin Length: uint16 max
+ };
+ ASSERT_TRUE(DecodeLeadingStructure(kData));
+ EXPECT_EQ(65535, structure_.origin_length);
+ }
+}
+
+TEST_F(Http2AltSvcFieldsDecoderTest, DecodesRandomized) {
+ TestDecodingRandomizedStructures();
+}
+
+} // namespace
+} // namespace test
+} // namespace net
diff --git a/chromium/net/http2/decoder/http2_structure_decoder_test_util.h b/chromium/net/http2/decoder/http2_structure_decoder_test_util.h
new file mode 100644
index 00000000000..b45211f76f0
--- /dev/null
+++ b/chromium/net/http2/decoder/http2_structure_decoder_test_util.h
@@ -0,0 +1,30 @@
+// Copyright 2016 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.
+
+#ifndef NET_HTTP2_DECODER_HTTP2_STRUCTURE_DECODER_TEST_UTIL_H_
+#define NET_HTTP2_DECODER_HTTP2_STRUCTURE_DECODER_TEST_UTIL_H_
+
+#include "net/http2/decoder/http2_structure_decoder.h"
+
+#include <cstddef>
+
+#include "net/http2/tools/http2_random.h"
+
+namespace net {
+namespace test {
+
+class Http2StructureDecoderPeer {
+ public:
+ static void Randomize(Http2StructureDecoder* p, RandomBase* rng) {
+ p->offset_ = rng->Rand32();
+ for (size_t i = 0; i < sizeof p->buffer_; ++i) {
+ p->buffer_[i] = rng->Rand8();
+ }
+ }
+};
+
+} // namespace test
+} // namespace net
+
+#endif // NET_HTTP2_DECODER_HTTP2_STRUCTURE_DECODER_TEST_UTIL_H_
diff --git a/chromium/net/http2/decoder/payload_decoders/altsvc_payload_decoder.cc b/chromium/net/http2/decoder/payload_decoders/altsvc_payload_decoder.cc
new file mode 100644
index 00000000000..fe0e8c274aa
--- /dev/null
+++ b/chromium/net/http2/decoder/payload_decoders/altsvc_payload_decoder.cc
@@ -0,0 +1,143 @@
+// Copyright 2016 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.
+
+#include "net/http2/decoder/payload_decoders/altsvc_payload_decoder.h"
+
+#include <stddef.h>
+
+#include "base/logging.h"
+#include "base/macros.h"
+#include "net/http2/decoder/decode_buffer.h"
+#include "net/http2/decoder/http2_frame_decoder_listener.h"
+#include "net/http2/http2_constants.h"
+#include "net/http2/http2_structures.h"
+#include "net/http2/tools/http2_bug_tracker.h"
+
+namespace net {
+
+std::ostream& operator<<(std::ostream& out,
+ AltSvcPayloadDecoder::PayloadState v) {
+ switch (v) {
+ case AltSvcPayloadDecoder::PayloadState::kStartDecodingStruct:
+ return out << "kStartDecodingStruct";
+ case AltSvcPayloadDecoder::PayloadState::kMaybeDecodedStruct:
+ return out << "kMaybeDecodedStruct";
+ case AltSvcPayloadDecoder::PayloadState::kDecodingStrings:
+ return out << "kDecodingStrings";
+ case AltSvcPayloadDecoder::PayloadState::kResumeDecodingStruct:
+ return out << "kResumeDecodingStruct";
+ }
+ return out << static_cast<int>(v);
+}
+
+DecodeStatus AltSvcPayloadDecoder::StartDecodingPayload(
+ FrameDecoderState* state,
+ DecodeBuffer* db) {
+ DVLOG(2) << "AltSvcPayloadDecoder::StartDecodingPayload: "
+ << state->frame_header();
+ DCHECK_EQ(Http2FrameType::ALTSVC, state->frame_header().type);
+ DCHECK_LE(db->Remaining(), state->frame_header().payload_length);
+ DCHECK_EQ(0, state->frame_header().flags);
+
+ state->InitializeRemainders();
+ payload_state_ = PayloadState::kStartDecodingStruct;
+
+ return ResumeDecodingPayload(state, db);
+}
+
+DecodeStatus AltSvcPayloadDecoder::ResumeDecodingPayload(
+ FrameDecoderState* state,
+ DecodeBuffer* db) {
+ const Http2FrameHeader& frame_header = state->frame_header();
+ DVLOG(2) << "AltSvcPayloadDecoder::ResumeDecodingPayload: " << frame_header;
+ DCHECK_EQ(Http2FrameType::ALTSVC, frame_header.type);
+ DCHECK_LE(state->remaining_payload(), frame_header.payload_length);
+ DCHECK_LE(db->Remaining(), state->remaining_payload());
+ DCHECK_NE(PayloadState::kMaybeDecodedStruct, payload_state_);
+ // |status| has to be initialized to some value to avoid compiler error in
+ // case PayloadState::kMaybeDecodedStruct below, but value does not matter,
+ // see DCHECK_NE above.
+ DecodeStatus status = DecodeStatus::kDecodeError;
+ while (true) {
+ DVLOG(2) << "AltSvcPayloadDecoder::ResumeDecodingPayload payload_state_="
+ << payload_state_;
+ switch (payload_state_) {
+ case PayloadState::kStartDecodingStruct:
+ status = state->StartDecodingStructureInPayload(&altsvc_fields_, db);
+ // FALLTHROUGH_INTENDED
+
+ case PayloadState::kMaybeDecodedStruct:
+ if (status == DecodeStatus::kDecodeDone &&
+ altsvc_fields_.origin_length <= state->remaining_payload()) {
+ size_t origin_length = altsvc_fields_.origin_length;
+ size_t value_length = state->remaining_payload() - origin_length;
+ state->listener()->OnAltSvcStart(frame_header, origin_length,
+ value_length);
+ } else if (status != DecodeStatus::kDecodeDone) {
+ DCHECK(state->remaining_payload() > 0 ||
+ status == DecodeStatus::kDecodeError)
+ << "\nremaining_payload: " << state->remaining_payload()
+ << "\nstatus: " << status << "\nheader: " << frame_header;
+ // Assume in progress.
+ payload_state_ = PayloadState::kResumeDecodingStruct;
+ return status;
+ } else {
+ // The origin's length is longer than the remaining payload.
+ DCHECK_GT(altsvc_fields_.origin_length, state->remaining_payload());
+ return state->ReportFrameSizeError();
+ }
+ // FALLTHROUGH_INTENDED
+
+ case PayloadState::kDecodingStrings:
+ return DecodeStrings(state, db);
+
+ case PayloadState::kResumeDecodingStruct:
+ status = state->ResumeDecodingStructureInPayload(&altsvc_fields_, db);
+ payload_state_ = PayloadState::kMaybeDecodedStruct;
+ continue;
+ }
+ HTTP2_BUG << "PayloadState: " << payload_state_;
+ }
+}
+
+DecodeStatus AltSvcPayloadDecoder::DecodeStrings(FrameDecoderState* state,
+ DecodeBuffer* db) {
+ DVLOG(2) << "AltSvcPayloadDecoder::DecodeStrings remaining_payload="
+ << state->remaining_payload()
+ << ", db->Remaining=" << db->Remaining();
+ // Note that we don't explicitly keep track of exactly how far through the
+ // origin; instead we compute it from how much is left of the original
+ // payload length and the decoded total length of the origin.
+ size_t origin_length = altsvc_fields_.origin_length;
+ size_t value_length = state->frame_header().payload_length - origin_length -
+ Http2AltSvcFields::EncodedSize();
+ if (state->remaining_payload() > value_length) {
+ size_t remaining_origin_length = state->remaining_payload() - value_length;
+ size_t avail = db->MinLengthRemaining(remaining_origin_length);
+ state->listener()->OnAltSvcOriginData(db->cursor(), avail);
+ db->AdvanceCursor(avail);
+ state->ConsumePayload(avail);
+ if (remaining_origin_length > avail) {
+ payload_state_ = PayloadState::kDecodingStrings;
+ return DecodeStatus::kDecodeInProgress;
+ }
+ }
+ // All that is left is the value string.
+ DCHECK_LE(state->remaining_payload(), value_length);
+ DCHECK_LE(db->Remaining(), state->remaining_payload());
+ if (db->HasData()) {
+ size_t avail = db->Remaining();
+ state->listener()->OnAltSvcValueData(db->cursor(), avail);
+ db->AdvanceCursor(avail);
+ state->ConsumePayload(avail);
+ }
+ if (state->remaining_payload() == 0) {
+ state->listener()->OnAltSvcEnd();
+ return DecodeStatus::kDecodeDone;
+ }
+ payload_state_ = PayloadState::kDecodingStrings;
+ return DecodeStatus::kDecodeInProgress;
+}
+
+} // namespace net
diff --git a/chromium/net/http2/decoder/payload_decoders/altsvc_payload_decoder.h b/chromium/net/http2/decoder/payload_decoders/altsvc_payload_decoder.h
new file mode 100644
index 00000000000..f92fa7f9db7
--- /dev/null
+++ b/chromium/net/http2/decoder/payload_decoders/altsvc_payload_decoder.h
@@ -0,0 +1,64 @@
+// Copyright 2016 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.
+
+#ifndef NET_HTTP2_DECODER_PAYLOAD_DECODERS_ALTSVC_PAYLOAD_DECODER_H_
+#define NET_HTTP2_DECODER_PAYLOAD_DECODERS_ALTSVC_PAYLOAD_DECODER_H_
+
+// Decodes the payload of a ALTSVC frame.
+
+#include "net/base/net_export.h"
+#include "net/http2/decoder/decode_buffer.h"
+#include "net/http2/decoder/decode_status.h"
+#include "net/http2/decoder/frame_decoder_state.h"
+#include "net/http2/http2_structures.h"
+
+namespace net {
+namespace test {
+class AltSvcPayloadDecoderPeer;
+} // namespace test
+
+class NET_EXPORT_PRIVATE AltSvcPayloadDecoder {
+ public:
+ // States during decoding of a ALTSVC frame.
+ enum class PayloadState {
+ // Start decoding the fixed size structure at the start of an ALTSVC
+ // frame (Http2AltSvcFields).
+ kStartDecodingStruct,
+
+ // Handle the DecodeStatus returned from starting or resuming the
+ // decoding of Http2AltSvcFields. If complete, calls OnAltSvcStart.
+ kMaybeDecodedStruct,
+
+ // Reports the value of the strings (origin and value) of an ALTSVC frame
+ // to the listener.
+ kDecodingStrings,
+
+ // The initial decode buffer wasn't large enough for the Http2AltSvcFields,
+ // so this state resumes the decoding when ResumeDecodingPayload is called
+ // later with a new DecodeBuffer.
+ kResumeDecodingStruct,
+ };
+
+ // Starts the decoding of a ALTSVC frame's payload, and completes it if the
+ // entire payload is in the provided decode buffer.
+ DecodeStatus StartDecodingPayload(FrameDecoderState* state, DecodeBuffer* db);
+
+ // Resumes decoding a ALTSVC frame's payload that has been split across
+ // decode buffers.
+ DecodeStatus ResumeDecodingPayload(FrameDecoderState* state,
+ DecodeBuffer* db);
+
+ private:
+ friend class test::AltSvcPayloadDecoderPeer;
+
+ // Implements state kDecodingStrings.
+ DecodeStatus DecodeStrings(FrameDecoderState* state, DecodeBuffer* db);
+
+ Http2AltSvcFields altsvc_fields_;
+ PayloadState payload_state_;
+};
+
+} // namespace net
+
+#endif // NET_HTTP2_DECODER_PAYLOAD_DECODERS_ALTSVC_PAYLOAD_DECODER_H_
diff --git a/chromium/net/http2/decoder/payload_decoders/altsvc_payload_decoder_test.cc b/chromium/net/http2/decoder/payload_decoders/altsvc_payload_decoder_test.cc
new file mode 100644
index 00000000000..5fa62d61fa3
--- /dev/null
+++ b/chromium/net/http2/decoder/payload_decoders/altsvc_payload_decoder_test.cc
@@ -0,0 +1,131 @@
+// Copyright 2016 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.
+
+#include "net/http2/decoder/payload_decoders/altsvc_payload_decoder.h"
+
+#include <stddef.h>
+
+#include <string>
+
+#include "base/logging.h"
+#include "net/http2/decoder/frame_parts.h"
+#include "net/http2/decoder/frame_parts_collector.h"
+#include "net/http2/decoder/http2_frame_decoder_listener.h"
+#include "net/http2/decoder/payload_decoders/payload_decoder_base_test_util.h"
+#include "net/http2/http2_constants.h"
+#include "net/http2/http2_structures_test_util.h"
+#include "net/http2/tools/http2_frame_builder.h"
+#include "net/http2/tools/http2_random.h"
+#include "net/http2/tools/random_decoder_test.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+using std::string;
+
+namespace net {
+namespace test {
+
+// Provides friend access to an instance of the payload decoder, and also
+// provides info to aid in testing.
+class AltSvcPayloadDecoderPeer {
+ public:
+ static constexpr Http2FrameType FrameType() { return Http2FrameType::ALTSVC; }
+
+ // Returns the mask of flags that affect the decoding of the payload (i.e.
+ // flags that that indicate the presence of certain fields or padding).
+ static constexpr uint8_t FlagsAffectingPayloadDecoding() { return 0; }
+
+ static void Randomize(AltSvcPayloadDecoder* p, RandomBase* rng) {
+ CorruptEnum(&p->payload_state_, rng);
+ test::Randomize(&p->altsvc_fields_, rng);
+ VLOG(1) << "AltSvcPayloadDecoderPeer::Randomize altsvc_fields_="
+ << p->altsvc_fields_;
+ }
+};
+
+namespace {
+
+struct Listener : public FramePartsCollector {
+ void OnAltSvcStart(const Http2FrameHeader& header,
+ size_t origin_length,
+ size_t value_length) override {
+ VLOG(1) << "OnAltSvcStart header: " << header
+ << "; origin_length=" << origin_length
+ << "; value_length=" << value_length;
+ StartFrame(header)->OnAltSvcStart(header, origin_length, value_length);
+ }
+
+ void OnAltSvcOriginData(const char* data, size_t len) override {
+ VLOG(1) << "OnAltSvcOriginData: len=" << len;
+ CurrentFrame()->OnAltSvcOriginData(data, len);
+ }
+
+ void OnAltSvcValueData(const char* data, size_t len) override {
+ VLOG(1) << "OnAltSvcValueData: len=" << len;
+ CurrentFrame()->OnAltSvcValueData(data, len);
+ }
+
+ void OnAltSvcEnd() override {
+ VLOG(1) << "OnAltSvcEnd";
+ EndFrame()->OnAltSvcEnd();
+ }
+
+ void OnFrameSizeError(const Http2FrameHeader& header) override {
+ VLOG(1) << "OnFrameSizeError: " << header;
+ FrameError(header)->OnFrameSizeError(header);
+ }
+};
+
+class AltSvcPayloadDecoderTest
+ : public AbstractPayloadDecoderTest<AltSvcPayloadDecoder,
+ AltSvcPayloadDecoderPeer,
+ Listener> {};
+
+// Confirm we get an error if the payload is not long enough to hold
+// Http2AltSvcFields and the indicated length of origin.
+TEST_F(AltSvcPayloadDecoderTest, Truncated) {
+ Http2FrameBuilder fb;
+ fb.Append(Http2AltSvcFields{0xffff}); // The longest possible origin length.
+ fb.Append("Too little origin!");
+ EXPECT_TRUE(
+ VerifyDetectsFrameSizeError(0, fb.buffer(), /*approve_size*/ nullptr));
+}
+
+class AltSvcPayloadLengthTests : public AltSvcPayloadDecoderTest,
+ public ::testing::WithParamInterface<
+ ::testing::tuple<uint16_t, uint32_t>> {
+ protected:
+ AltSvcPayloadLengthTests()
+ : origin_length_(::testing::get<0>(GetParam())),
+ value_length_(::testing::get<1>(GetParam())) {
+ VLOG(1) << "################ origin_length_=" << origin_length_
+ << " value_length_=" << value_length_ << " ################";
+ }
+
+ const uint16_t origin_length_;
+ const uint32_t value_length_;
+};
+
+INSTANTIATE_TEST_CASE_P(VariousOriginAndValueLengths,
+ AltSvcPayloadLengthTests,
+ ::testing::Combine(::testing::Values(0, 1, 3, 65535),
+ ::testing::Values(0, 1, 3, 65537)));
+
+TEST_P(AltSvcPayloadLengthTests, ValidOriginAndValueLength) {
+ string origin = Random().RandString(origin_length_);
+ string value = Random().RandString(value_length_);
+ Http2FrameBuilder fb;
+ fb.Append(Http2AltSvcFields{origin_length_});
+ fb.Append(origin);
+ fb.Append(value);
+ Http2FrameHeader header(fb.size(), Http2FrameType::ALTSVC, RandFlags(),
+ RandStreamId());
+ set_frame_header(header);
+ FrameParts expected(header);
+ expected.SetAltSvcExpected(origin, value);
+ ASSERT_TRUE(DecodePayloadAndValidateSeveralWays(fb.buffer(), expected));
+}
+
+} // namespace
+} // namespace test
+} // namespace net
diff --git a/chromium/net/http2/decoder/payload_decoders/continuation_payload_decoder.cc b/chromium/net/http2/decoder/payload_decoders/continuation_payload_decoder.cc
new file mode 100644
index 00000000000..ac5371c056f
--- /dev/null
+++ b/chromium/net/http2/decoder/payload_decoders/continuation_payload_decoder.cc
@@ -0,0 +1,58 @@
+// Copyright 2016 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.
+
+#include "net/http2/decoder/payload_decoders/continuation_payload_decoder.h"
+
+#include <stddef.h>
+
+#include "base/logging.h"
+#include "net/http2/decoder/decode_buffer.h"
+#include "net/http2/decoder/http2_frame_decoder_listener.h"
+#include "net/http2/http2_constants.h"
+#include "net/http2/http2_structures.h"
+
+namespace net {
+
+DecodeStatus ContinuationPayloadDecoder::StartDecodingPayload(
+ FrameDecoderState* state,
+ DecodeBuffer* db) {
+ const Http2FrameHeader& frame_header = state->frame_header();
+ const uint32_t total_length = frame_header.payload_length;
+
+ DVLOG(2) << "ContinuationPayloadDecoder::StartDecodingPayload: "
+ << frame_header;
+ DCHECK_EQ(Http2FrameType::CONTINUATION, frame_header.type);
+ DCHECK_LE(db->Remaining(), total_length);
+ DCHECK_EQ(0, frame_header.flags & ~(Http2FrameFlag::FLAG_END_HEADERS));
+
+ state->InitializeRemainders();
+ state->listener()->OnContinuationStart(frame_header);
+ return ResumeDecodingPayload(state, db);
+}
+
+DecodeStatus ContinuationPayloadDecoder::ResumeDecodingPayload(
+ FrameDecoderState* state,
+ DecodeBuffer* db) {
+ DVLOG(2) << "ContinuationPayloadDecoder::ResumeDecodingPayload"
+ << " remaining_payload=" << state->remaining_payload()
+ << " db->Remaining=" << db->Remaining();
+ DCHECK_EQ(Http2FrameType::CONTINUATION, state->frame_header().type);
+ DCHECK_LE(state->remaining_payload(), state->frame_header().payload_length);
+ DCHECK_LE(db->Remaining(), state->remaining_payload());
+
+ size_t avail = db->Remaining();
+ DCHECK_LE(avail, state->remaining_payload());
+ if (avail > 0) {
+ state->listener()->OnHpackFragment(db->cursor(), avail);
+ db->AdvanceCursor(avail);
+ state->ConsumePayload(avail);
+ }
+ if (state->remaining_payload() == 0) {
+ state->listener()->OnContinuationEnd();
+ return DecodeStatus::kDecodeDone;
+ }
+ return DecodeStatus::kDecodeInProgress;
+}
+
+} // namespace net
diff --git a/chromium/net/http2/decoder/payload_decoders/continuation_payload_decoder.h b/chromium/net/http2/decoder/payload_decoders/continuation_payload_decoder.h
new file mode 100644
index 00000000000..4ab58aaa5ed
--- /dev/null
+++ b/chromium/net/http2/decoder/payload_decoders/continuation_payload_decoder.h
@@ -0,0 +1,31 @@
+// Copyright 2016 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.
+
+#ifndef NET_HTTP2_DECODER_PAYLOAD_DECODERS_CONTINUATION_PAYLOAD_DECODER_H_
+#define NET_HTTP2_DECODER_PAYLOAD_DECODERS_CONTINUATION_PAYLOAD_DECODER_H_
+
+// Decodes the payload of a CONTINUATION frame.
+
+#include "net/base/net_export.h"
+#include "net/http2/decoder/decode_buffer.h"
+#include "net/http2/decoder/decode_status.h"
+#include "net/http2/decoder/frame_decoder_state.h"
+
+namespace net {
+
+class NET_EXPORT_PRIVATE ContinuationPayloadDecoder {
+ public:
+ // Starts the decoding of a CONTINUATION frame's payload, and completes
+ // it if the entire payload is in the provided decode buffer.
+ DecodeStatus StartDecodingPayload(FrameDecoderState* state, DecodeBuffer* db);
+
+ // Resumes decoding a CONTINUATION frame's payload that has been split across
+ // decode buffers.
+ DecodeStatus ResumeDecodingPayload(FrameDecoderState* state,
+ DecodeBuffer* db);
+};
+
+} // namespace net
+
+#endif // NET_HTTP2_DECODER_PAYLOAD_DECODERS_CONTINUATION_PAYLOAD_DECODER_H_
diff --git a/chromium/net/http2/decoder/payload_decoders/continuation_payload_decoder_test.cc b/chromium/net/http2/decoder/payload_decoders/continuation_payload_decoder_test.cc
new file mode 100644
index 00000000000..32440396a39
--- /dev/null
+++ b/chromium/net/http2/decoder/payload_decoders/continuation_payload_decoder_test.cc
@@ -0,0 +1,94 @@
+// Copyright 2016 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.
+
+#include "net/http2/decoder/payload_decoders/continuation_payload_decoder.h"
+
+#include <stddef.h>
+
+#include <string>
+#include <type_traits>
+
+#include "base/logging.h"
+#include "net/http2/decoder/frame_parts.h"
+#include "net/http2/decoder/frame_parts_collector.h"
+#include "net/http2/decoder/http2_frame_decoder_listener.h"
+#include "net/http2/decoder/payload_decoders/payload_decoder_base_test_util.h"
+#include "net/http2/http2_constants.h"
+#include "net/http2/http2_structures.h"
+#include "net/http2/tools/random_decoder_test.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+using std::string;
+
+namespace net {
+namespace test {
+
+// Provides friend access to an instance of the payload decoder, and also
+// provides info to aid in testing.
+class ContinuationPayloadDecoderPeer {
+ public:
+ static constexpr Http2FrameType FrameType() {
+ return Http2FrameType::CONTINUATION;
+ }
+
+ // Returns the mask of flags that affect the decoding of the payload (i.e.
+ // flags that that indicate the presence of certain fields or padding).
+ static constexpr uint8_t FlagsAffectingPayloadDecoding() { return 0; }
+
+ static void Randomize(ContinuationPayloadDecoder* p, RandomBase* rng) {
+ // ContinuationPayloadDecoder has no fields,
+ // so there is nothing to randomize.
+ static_assert(std::is_empty<ContinuationPayloadDecoder>::value,
+ "Need to randomize fields of ContinuationPayloadDecoder");
+ }
+};
+
+namespace {
+
+struct Listener : public FramePartsCollector {
+ void OnContinuationStart(const Http2FrameHeader& header) override {
+ VLOG(1) << "OnContinuationStart: " << header;
+ StartFrame(header)->OnContinuationStart(header);
+ }
+
+ void OnHpackFragment(const char* data, size_t len) override {
+ VLOG(1) << "OnHpackFragment: len=" << len;
+ CurrentFrame()->OnHpackFragment(data, len);
+ }
+
+ void OnContinuationEnd() override {
+ VLOG(1) << "OnContinuationEnd";
+ EndFrame()->OnContinuationEnd();
+ }
+};
+
+class ContinuationPayloadDecoderTest
+ : public AbstractPayloadDecoderTest<ContinuationPayloadDecoder,
+ ContinuationPayloadDecoderPeer,
+ Listener>,
+ public ::testing::WithParamInterface<uint32_t> {
+ protected:
+ ContinuationPayloadDecoderTest() : length_(GetParam()) {
+ VLOG(1) << "################ length_=" << length_ << " ################";
+ }
+
+ const uint32_t length_;
+};
+
+INSTANTIATE_TEST_CASE_P(VariousLengths,
+ ContinuationPayloadDecoderTest,
+ ::testing::Values(0, 1, 2, 3, 4, 5, 6));
+
+TEST_P(ContinuationPayloadDecoderTest, ValidLength) {
+ string hpack_payload = Random().RandString(length_);
+ Http2FrameHeader frame_header(length_, Http2FrameType::CONTINUATION,
+ RandFlags(), RandStreamId());
+ set_frame_header(frame_header);
+ FrameParts expected(frame_header, hpack_payload);
+ EXPECT_TRUE(DecodePayloadAndValidateSeveralWays(hpack_payload, expected));
+}
+
+} // namespace
+} // namespace test
+} // namespace net
diff --git a/chromium/net/http2/decoder/payload_decoders/data_payload_decoder.cc b/chromium/net/http2/decoder/payload_decoders/data_payload_decoder.cc
new file mode 100644
index 00000000000..60b8a714f19
--- /dev/null
+++ b/chromium/net/http2/decoder/payload_decoders/data_payload_decoder.cc
@@ -0,0 +1,123 @@
+// Copyright 2016 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.
+
+#include "net/http2/decoder/payload_decoders/data_payload_decoder.h"
+
+#include <stddef.h>
+
+#include "base/logging.h"
+#include "base/macros.h"
+#include "net/http2/decoder/decode_buffer.h"
+#include "net/http2/decoder/http2_frame_decoder_listener.h"
+#include "net/http2/http2_constants.h"
+#include "net/http2/http2_structures.h"
+#include "net/http2/tools/http2_bug_tracker.h"
+
+namespace net {
+
+std::ostream& operator<<(std::ostream& out,
+ DataPayloadDecoder::PayloadState v) {
+ switch (v) {
+ case DataPayloadDecoder::PayloadState::kReadPadLength:
+ return out << "kReadPadLength";
+ case DataPayloadDecoder::PayloadState::kReadPayload:
+ return out << "kReadPayload";
+ case DataPayloadDecoder::PayloadState::kSkipPadding:
+ return out << "kSkipPadding";
+ }
+ return out << static_cast<int>(v);
+}
+
+DecodeStatus DataPayloadDecoder::StartDecodingPayload(FrameDecoderState* state,
+ DecodeBuffer* db) {
+ const Http2FrameHeader& frame_header = state->frame_header();
+ const uint32_t total_length = frame_header.payload_length;
+
+ DVLOG(2) << "DataPayloadDecoder::StartDecodingPayload: " << frame_header;
+ DCHECK_EQ(Http2FrameType::DATA, frame_header.type);
+ DCHECK_LE(db->Remaining(), total_length);
+ DCHECK_EQ(
+ 0, frame_header.flags &
+ ~(Http2FrameFlag::FLAG_END_STREAM | Http2FrameFlag::FLAG_PADDED));
+
+ // Special case for the hoped for common case: unpadded and fits fully into
+ // the decode buffer. TO BE SEEN if that is true. It certainly requires that
+ // the transport buffers be large (e.g. >> 16KB typically).
+ // TODO(jamessynge) Add counters.
+ DVLOG(2) << "StartDecodingPayload total_length=" << total_length;
+ if (!frame_header.IsPadded()) {
+ DVLOG(2) << "StartDecodingPayload !IsPadded";
+ if (db->Remaining() == total_length) {
+ DVLOG(2) << "StartDecodingPayload all present";
+ // Note that we don't cache the listener field so that the callee can
+ // replace it if the frame is bad.
+ // If this case is common enough, consider combining the 3 callbacks
+ // into one.
+ state->listener()->OnDataStart(frame_header);
+ if (total_length > 0) {
+ state->listener()->OnDataPayload(db->cursor(), total_length);
+ db->AdvanceCursor(total_length);
+ }
+ state->listener()->OnDataEnd();
+ return DecodeStatus::kDecodeDone;
+ }
+ payload_state_ = PayloadState::kReadPayload;
+ } else {
+ payload_state_ = PayloadState::kReadPadLength;
+ }
+ state->InitializeRemainders();
+ state->listener()->OnDataStart(frame_header);
+ return ResumeDecodingPayload(state, db);
+}
+
+DecodeStatus DataPayloadDecoder::ResumeDecodingPayload(FrameDecoderState* state,
+ DecodeBuffer* db) {
+ DVLOG(2) << "DataPayloadDecoder::ResumeDecodingPayload payload_state_="
+ << payload_state_;
+ const Http2FrameHeader& frame_header = state->frame_header();
+ DCHECK_EQ(Http2FrameType::DATA, frame_header.type);
+ DCHECK_LE(state->remaining_payload_and_padding(),
+ frame_header.payload_length);
+ DCHECK_LE(db->Remaining(), state->remaining_payload_and_padding());
+ DecodeStatus status;
+ size_t avail;
+ switch (payload_state_) {
+ case PayloadState::kReadPadLength:
+ // ReadPadLength handles the OnPadLength callback, and updating the
+ // remaining_payload and remaining_padding fields. If the amount of
+ // padding is too large to fit in the frame's payload, ReadPadLength
+ // instead calls OnPaddingTooLong and returns kDecodeError.
+ status = state->ReadPadLength(db, /*report_pad_length*/ true);
+ if (status != DecodeStatus::kDecodeDone) {
+ return status;
+ }
+ // FALLTHROUGH_INTENDED
+
+ case PayloadState::kReadPayload:
+ avail = state->AvailablePayload(db);
+ if (avail > 0) {
+ state->listener()->OnDataPayload(db->cursor(), avail);
+ db->AdvanceCursor(avail);
+ state->ConsumePayload(avail);
+ }
+ if (state->remaining_payload() > 0) {
+ payload_state_ = PayloadState::kReadPayload;
+ return DecodeStatus::kDecodeInProgress;
+ }
+ // FALLTHROUGH_INTENDED
+
+ case PayloadState::kSkipPadding:
+ // SkipPadding handles the OnPadding callback.
+ if (state->SkipPadding(db)) {
+ state->listener()->OnDataEnd();
+ return DecodeStatus::kDecodeDone;
+ }
+ payload_state_ = PayloadState::kSkipPadding;
+ return DecodeStatus::kDecodeInProgress;
+ }
+ HTTP2_BUG << "PayloadState: " << payload_state_;
+ return DecodeStatus::kDecodeError;
+}
+
+} // namespace net
diff --git a/chromium/net/http2/decoder/payload_decoders/data_payload_decoder.h b/chromium/net/http2/decoder/payload_decoders/data_payload_decoder.h
new file mode 100644
index 00000000000..2fe09596a67
--- /dev/null
+++ b/chromium/net/http2/decoder/payload_decoders/data_payload_decoder.h
@@ -0,0 +1,54 @@
+// Copyright 2016 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.
+
+#ifndef NET_HTTP2_DECODER_PAYLOAD_DECODERS_DATA_PAYLOAD_DECODER_H_
+#define NET_HTTP2_DECODER_PAYLOAD_DECODERS_DATA_PAYLOAD_DECODER_H_
+
+// Decodes the payload of a DATA frame.
+
+#include "net/base/net_export.h"
+#include "net/http2/decoder/decode_buffer.h"
+#include "net/http2/decoder/decode_status.h"
+#include "net/http2/decoder/frame_decoder_state.h"
+
+namespace net {
+namespace test {
+class DataPayloadDecoderPeer;
+} // namespace test
+
+class NET_EXPORT_PRIVATE DataPayloadDecoder {
+ public:
+ // States during decoding of a DATA frame.
+ enum class PayloadState {
+ // The frame is padded and we need to read the PAD_LENGTH field (1 byte),
+ // and then call OnPadLength
+ kReadPadLength,
+
+ // Report the non-padding portion of the payload to the listener's
+ // OnDataPayload method.
+ kReadPayload,
+
+ // The decoder has finished with the non-padding portion of the payload,
+ // and is now ready to skip the trailing padding, if the frame has any.
+ kSkipPadding,
+ };
+
+ // Starts decoding a DATA frame's payload, and completes it if
+ // the entire payload is in the provided decode buffer.
+ DecodeStatus StartDecodingPayload(FrameDecoderState* state, DecodeBuffer* db);
+
+ // Resumes decoding a DATA frame's payload that has been split across
+ // decode buffers.
+ DecodeStatus ResumeDecodingPayload(FrameDecoderState* state,
+ DecodeBuffer* db);
+
+ private:
+ friend class test::DataPayloadDecoderPeer;
+
+ PayloadState payload_state_;
+};
+
+} // namespace net
+
+#endif // NET_HTTP2_DECODER_PAYLOAD_DECODERS_DATA_PAYLOAD_DECODER_H_
diff --git a/chromium/net/http2/decoder/payload_decoders/data_payload_decoder_test.cc b/chromium/net/http2/decoder/payload_decoders/data_payload_decoder_test.cc
new file mode 100644
index 00000000000..bedb32f35b7
--- /dev/null
+++ b/chromium/net/http2/decoder/payload_decoders/data_payload_decoder_test.cc
@@ -0,0 +1,120 @@
+// Copyright 2016 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.
+
+#include "net/http2/decoder/payload_decoders/data_payload_decoder.h"
+
+#include <stddef.h>
+
+#include <string>
+
+#include "base/logging.h"
+#include "net/http2/decoder/frame_parts.h"
+#include "net/http2/decoder/frame_parts_collector.h"
+#include "net/http2/decoder/http2_frame_decoder_listener.h"
+#include "net/http2/decoder/payload_decoders/payload_decoder_base_test_util.h"
+#include "net/http2/http2_constants.h"
+#include "net/http2/http2_structures.h"
+#include "net/http2/http2_structures_test_util.h"
+#include "net/http2/tools/failure.h"
+#include "net/http2/tools/http2_frame_builder.h"
+#include "net/http2/tools/http2_random.h"
+#include "net/http2/tools/random_decoder_test.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+using ::testing::AssertionResult;
+using std::string;
+
+namespace net {
+namespace test {
+
+// Provides friend access to an instance of the payload decoder, and also
+// provides info to aid in testing.
+class DataPayloadDecoderPeer {
+ public:
+ static constexpr Http2FrameType FrameType() { return Http2FrameType::DATA; }
+
+ // Returns the mask of flags that affect the decoding of the payload (i.e.
+ // flags that that indicate the presence of certain fields or padding).
+ static constexpr uint8_t FlagsAffectingPayloadDecoding() {
+ return Http2FrameFlag::FLAG_PADDED;
+ }
+
+ static void Randomize(DataPayloadDecoder* p, RandomBase* rng) {
+ VLOG(1) << "DataPayloadDecoderPeer::Randomize";
+ CorruptEnum(&p->payload_state_, rng);
+ }
+};
+
+namespace {
+
+struct Listener : public FramePartsCollector {
+ void OnDataStart(const Http2FrameHeader& header) override {
+ VLOG(1) << "OnDataStart: " << header;
+ StartFrame(header)->OnDataStart(header);
+ }
+
+ void OnDataPayload(const char* data, size_t len) override {
+ VLOG(1) << "OnDataPayload: len=" << len;
+ CurrentFrame()->OnDataPayload(data, len);
+ }
+
+ void OnDataEnd() override {
+ VLOG(1) << "OnDataEnd";
+ EndFrame()->OnDataEnd();
+ }
+
+ void OnPadLength(size_t pad_length) override {
+ VLOG(1) << "OnPadLength: " << pad_length;
+ CurrentFrame()->OnPadLength(pad_length);
+ }
+
+ void OnPadding(const char* padding, size_t skipped_length) override {
+ VLOG(1) << "OnPadding: " << skipped_length;
+ CurrentFrame()->OnPadding(padding, skipped_length);
+ }
+
+ void OnPaddingTooLong(const Http2FrameHeader& header,
+ size_t missing_length) override {
+ VLOG(1) << "OnPaddingTooLong: " << header
+ << " missing_length: " << missing_length;
+ EndFrame()->OnPaddingTooLong(header, missing_length);
+ }
+};
+
+class DataPayloadDecoderTest
+ : public AbstractPaddablePayloadDecoderTest<DataPayloadDecoder,
+ DataPayloadDecoderPeer,
+ Listener> {
+ protected:
+ AssertionResult CreateAndDecodeDataOfSize(size_t data_size) {
+ Reset();
+ uint8_t flags = RandFlags();
+
+ string data_payload = Random().RandString(data_size);
+ frame_builder_.Append(data_payload);
+ MaybeAppendTrailingPadding();
+
+ Http2FrameHeader frame_header(frame_builder_.size(), Http2FrameType::DATA,
+ flags, RandStreamId());
+ set_frame_header(frame_header);
+ ScrubFlagsOfHeader(&frame_header);
+ FrameParts expected(frame_header, data_payload, total_pad_length_);
+ VERIFY_AND_RETURN_SUCCESS(
+ DecodePayloadAndValidateSeveralWays(frame_builder_.buffer(), expected));
+ }
+};
+
+INSTANTIATE_TEST_CASE_P(VariousPadLengths,
+ DataPayloadDecoderTest,
+ ::testing::Values(0, 1, 2, 3, 4, 254, 255, 256));
+
+TEST_P(DataPayloadDecoderTest, VariousDataPayloadSizes) {
+ for (size_t data_size : {0, 1, 2, 3, 255, 256, 1024}) {
+ EXPECT_TRUE(CreateAndDecodeDataOfSize(data_size));
+ }
+}
+
+} // namespace
+} // namespace test
+} // namespace net
diff --git a/chromium/net/http2/decoder/payload_decoders/goaway_payload_decoder.cc b/chromium/net/http2/decoder/payload_decoders/goaway_payload_decoder.cc
new file mode 100644
index 00000000000..f5b597f0e5a
--- /dev/null
+++ b/chromium/net/http2/decoder/payload_decoders/goaway_payload_decoder.cc
@@ -0,0 +1,118 @@
+// Copyright 2016 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.
+
+#include "net/http2/decoder/payload_decoders/goaway_payload_decoder.h"
+
+#include <stddef.h>
+
+#include "base/logging.h"
+#include "base/macros.h"
+#include "net/http2/decoder/decode_buffer.h"
+#include "net/http2/decoder/http2_frame_decoder_listener.h"
+#include "net/http2/http2_constants.h"
+#include "net/http2/http2_structures.h"
+#include "net/http2/tools/http2_bug_tracker.h"
+
+namespace net {
+
+std::ostream& operator<<(std::ostream& out,
+ GoAwayPayloadDecoder::PayloadState v) {
+ switch (v) {
+ case GoAwayPayloadDecoder::PayloadState::kStartDecodingFixedFields:
+ return out << "kStartDecodingFixedFields";
+ case GoAwayPayloadDecoder::PayloadState::kHandleFixedFieldsStatus:
+ return out << "kHandleFixedFieldsStatus";
+ case GoAwayPayloadDecoder::PayloadState::kReadOpaqueData:
+ return out << "kReadOpaqueData";
+ case GoAwayPayloadDecoder::PayloadState::kResumeDecodingFixedFields:
+ return out << "kResumeDecodingFixedFields";
+ }
+
+ NOTREACHED();
+ return out;
+}
+
+DecodeStatus GoAwayPayloadDecoder::StartDecodingPayload(
+ FrameDecoderState* state,
+ DecodeBuffer* db) {
+ DVLOG(2) << "GoAwayPayloadDecoder::StartDecodingPayload: "
+ << state->frame_header();
+ DCHECK_EQ(Http2FrameType::GOAWAY, state->frame_header().type);
+ DCHECK_LE(db->Remaining(), state->frame_header().payload_length);
+ DCHECK_EQ(0, state->frame_header().flags);
+
+ state->InitializeRemainders();
+ payload_state_ = PayloadState::kStartDecodingFixedFields;
+ return ResumeDecodingPayload(state, db);
+}
+
+DecodeStatus GoAwayPayloadDecoder::ResumeDecodingPayload(
+ FrameDecoderState* state,
+ DecodeBuffer* db) {
+ DVLOG(2) << "GoAwayPayloadDecoder::ResumeDecodingPayload: remaining_payload="
+ << state->remaining_payload()
+ << ", db->Remaining=" << db->Remaining();
+
+ const Http2FrameHeader& frame_header = state->frame_header();
+ DCHECK_EQ(Http2FrameType::GOAWAY, frame_header.type);
+ DCHECK_LE(db->Remaining(), frame_header.payload_length);
+ DCHECK_NE(PayloadState::kHandleFixedFieldsStatus, payload_state_);
+
+ // |status| has to be initialized to some value to avoid compiler error in
+ // case PayloadState::kHandleFixedFieldsStatus below, but value does not
+ // matter, see DCHECK_NE above.
+ DecodeStatus status = DecodeStatus::kDecodeError;
+ size_t avail;
+ while (true) {
+ DVLOG(2) << "GoAwayPayloadDecoder::ResumeDecodingPayload payload_state_="
+ << payload_state_;
+ switch (payload_state_) {
+ case PayloadState::kStartDecodingFixedFields:
+ status = state->StartDecodingStructureInPayload(&goaway_fields_, db);
+ // FALLTHROUGH_INTENDED
+
+ case PayloadState::kHandleFixedFieldsStatus:
+ if (status == DecodeStatus::kDecodeDone) {
+ state->listener()->OnGoAwayStart(frame_header, goaway_fields_);
+ } else {
+ // Not done decoding the structure. Either we've got more payload
+ // to decode, or we've run out because the payload is too short,
+ // in which case OnFrameSizeError will have already been called.
+ DCHECK((status == DecodeStatus::kDecodeInProgress &&
+ state->remaining_payload() > 0) ||
+ (status == DecodeStatus::kDecodeError &&
+ state->remaining_payload() == 0))
+ << "\n status=" << status
+ << "; remaining_payload=" << state->remaining_payload();
+ payload_state_ = PayloadState::kResumeDecodingFixedFields;
+ return status;
+ }
+ // FALLTHROUGH_INTENDED
+
+ case PayloadState::kReadOpaqueData:
+ // The opaque data is all the remains to be decoded, so anything left
+ // in the decode buffer is opaque data.
+ avail = db->Remaining();
+ if (avail > 0) {
+ state->listener()->OnGoAwayOpaqueData(db->cursor(), avail);
+ db->AdvanceCursor(avail);
+ state->ConsumePayload(avail);
+ }
+ if (state->remaining_payload() > 0) {
+ payload_state_ = PayloadState::kReadOpaqueData;
+ return DecodeStatus::kDecodeInProgress;
+ }
+ state->listener()->OnGoAwayEnd();
+ return DecodeStatus::kDecodeDone;
+
+ case PayloadState::kResumeDecodingFixedFields:
+ status = state->ResumeDecodingStructureInPayload(&goaway_fields_, db);
+ payload_state_ = PayloadState::kHandleFixedFieldsStatus;
+ continue;
+ }
+ HTTP2_BUG << "PayloadState: " << payload_state_;
+ }
+}
+
+} // namespace net
diff --git a/chromium/net/http2/decoder/payload_decoders/goaway_payload_decoder.h b/chromium/net/http2/decoder/payload_decoders/goaway_payload_decoder.h
new file mode 100644
index 00000000000..5aefc6ce6e7
--- /dev/null
+++ b/chromium/net/http2/decoder/payload_decoders/goaway_payload_decoder.h
@@ -0,0 +1,66 @@
+// Copyright 2016 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.
+
+#ifndef NET_HTTP2_DECODER_PAYLOAD_DECODERS_GOAWAY_PAYLOAD_DECODER_H_
+#define NET_HTTP2_DECODER_PAYLOAD_DECODERS_GOAWAY_PAYLOAD_DECODER_H_
+
+// Decodes the payload of a GOAWAY frame.
+
+// TODO(jamessynge): Sweep through all payload decoders, changing the names of
+// the PayloadState enums so that they are really states, and not actions.
+
+#include "net/base/net_export.h"
+#include "net/http2/decoder/decode_buffer.h"
+#include "net/http2/decoder/decode_status.h"
+#include "net/http2/decoder/frame_decoder_state.h"
+#include "net/http2/http2_structures.h"
+
+namespace net {
+namespace test {
+class GoAwayPayloadDecoderPeer;
+} // namespace test
+
+class NET_EXPORT_PRIVATE GoAwayPayloadDecoder {
+ public:
+ // States during decoding of a GOAWAY frame.
+ enum class PayloadState {
+ // At the start of the GOAWAY frame payload, ready to start decoding the
+ // fixed size fields into goaway_fields_.
+ kStartDecodingFixedFields,
+
+ // Handle the DecodeStatus returned from starting or resuming the
+ // decoding of Http2GoAwayFields into goaway_fields_. If complete,
+ // calls OnGoAwayStart.
+ kHandleFixedFieldsStatus,
+
+ // Report the Opaque Data portion of the payload to the listener's
+ // OnGoAwayOpaqueData method, and call OnGoAwayEnd when the end of the
+ // payload is reached.
+ kReadOpaqueData,
+
+ // The fixed size fields weren't all available when the decoder first
+ // tried to decode them (state kStartDecodingFixedFields); this state
+ // resumes the decoding when ResumeDecodingPayload is called later.
+ kResumeDecodingFixedFields,
+ };
+
+ // Starts the decoding of a GOAWAY frame's payload, and completes it if
+ // the entire payload is in the provided decode buffer.
+ DecodeStatus StartDecodingPayload(FrameDecoderState* state, DecodeBuffer* db);
+
+ // Resumes decoding a GOAWAY frame's payload that has been split across
+ // decode buffers.
+ DecodeStatus ResumeDecodingPayload(FrameDecoderState* state,
+ DecodeBuffer* db);
+
+ private:
+ friend class test::GoAwayPayloadDecoderPeer;
+
+ Http2GoAwayFields goaway_fields_;
+ PayloadState payload_state_;
+};
+
+} // namespace net
+
+#endif // NET_HTTP2_DECODER_PAYLOAD_DECODERS_GOAWAY_PAYLOAD_DECODER_H_
diff --git a/chromium/net/http2/decoder/payload_decoders/goaway_payload_decoder_test.cc b/chromium/net/http2/decoder/payload_decoders/goaway_payload_decoder_test.cc
new file mode 100644
index 00000000000..cddda79c78e
--- /dev/null
+++ b/chromium/net/http2/decoder/payload_decoders/goaway_payload_decoder_test.cc
@@ -0,0 +1,117 @@
+// Copyright 2016 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.
+
+#include "net/http2/decoder/payload_decoders/goaway_payload_decoder.h"
+
+#include <stddef.h>
+
+#include <string>
+
+#include "base/logging.h"
+#include "net/http2/decoder/frame_parts.h"
+#include "net/http2/decoder/frame_parts_collector.h"
+#include "net/http2/decoder/http2_frame_decoder_listener.h"
+#include "net/http2/decoder/payload_decoders/payload_decoder_base_test_util.h"
+#include "net/http2/http2_constants.h"
+#include "net/http2/http2_structures_test_util.h"
+#include "net/http2/tools/http2_frame_builder.h"
+#include "net/http2/tools/http2_random.h"
+#include "net/http2/tools/random_decoder_test.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+using std::string;
+
+namespace net {
+namespace test {
+
+class GoAwayPayloadDecoderPeer {
+ public:
+ static constexpr Http2FrameType FrameType() { return Http2FrameType::GOAWAY; }
+
+ // Returns the mask of flags that affect the decoding of the payload (i.e.
+ // flags that that indicate the presence of certain fields or padding).
+ static constexpr uint8_t FlagsAffectingPayloadDecoding() { return 0; }
+
+ static void Randomize(GoAwayPayloadDecoder* p, RandomBase* rng) {
+ CorruptEnum(&p->payload_state_, rng);
+ test::Randomize(&p->goaway_fields_, rng);
+ VLOG(1) << "GoAwayPayloadDecoderPeer::Randomize goaway_fields: "
+ << p->goaway_fields_;
+ }
+};
+
+namespace {
+
+struct Listener : public FramePartsCollector {
+ void OnGoAwayStart(const Http2FrameHeader& header,
+ const Http2GoAwayFields& goaway) override {
+ VLOG(1) << "OnGoAwayStart header: " << header << "; goaway: " << goaway;
+ StartFrame(header)->OnGoAwayStart(header, goaway);
+ }
+
+ void OnGoAwayOpaqueData(const char* data, size_t len) override {
+ VLOG(1) << "OnGoAwayOpaqueData: len=" << len;
+ CurrentFrame()->OnGoAwayOpaqueData(data, len);
+ }
+
+ void OnGoAwayEnd() override {
+ VLOG(1) << "OnGoAwayEnd";
+ EndFrame()->OnGoAwayEnd();
+ }
+
+ void OnFrameSizeError(const Http2FrameHeader& header) override {
+ VLOG(1) << "OnFrameSizeError: " << header;
+ FrameError(header)->OnFrameSizeError(header);
+ }
+};
+
+class GoAwayPayloadDecoderTest
+ : public AbstractPayloadDecoderTest<GoAwayPayloadDecoder,
+ GoAwayPayloadDecoderPeer,
+ Listener> {};
+
+// Confirm we get an error if the payload is not long enough to hold
+// Http2GoAwayFields.
+TEST_F(GoAwayPayloadDecoderTest, Truncated) {
+ auto approve_size = [](size_t size) {
+ return size != Http2GoAwayFields::EncodedSize();
+ };
+ Http2FrameBuilder fb;
+ fb.Append(Http2GoAwayFields(123, Http2ErrorCode::ENHANCE_YOUR_CALM));
+ EXPECT_TRUE(VerifyDetectsFrameSizeError(0, fb.buffer(), approve_size));
+}
+
+class GoAwayOpaqueDataLengthTests
+ : public GoAwayPayloadDecoderTest,
+ public ::testing::WithParamInterface<uint32_t> {
+ protected:
+ GoAwayOpaqueDataLengthTests() : length_(GetParam()) {
+ VLOG(1) << "################ length_=" << length_ << " ################";
+ }
+
+ const uint32_t length_;
+};
+
+INSTANTIATE_TEST_CASE_P(VariousLengths,
+ GoAwayOpaqueDataLengthTests,
+ ::testing::Values(0, 1, 2, 3, 4, 5, 6));
+
+TEST_P(GoAwayOpaqueDataLengthTests, ValidLength) {
+ Http2GoAwayFields goaway;
+ Randomize(&goaway, RandomPtr());
+ string opaque_data = Random().RandString(length_);
+ Http2FrameBuilder fb;
+ fb.Append(goaway);
+ fb.Append(opaque_data);
+ Http2FrameHeader header(fb.size(), Http2FrameType::GOAWAY, RandFlags(),
+ RandStreamId());
+ set_frame_header(header);
+ FrameParts expected(header, opaque_data);
+ expected.opt_goaway = goaway;
+ ASSERT_TRUE(DecodePayloadAndValidateSeveralWays(fb.buffer(), expected));
+}
+
+} // namespace
+} // namespace test
+} // namespace net
diff --git a/chromium/net/http2/decoder/payload_decoders/headers_payload_decoder.cc b/chromium/net/http2/decoder/payload_decoders/headers_payload_decoder.cc
new file mode 100644
index 00000000000..eff1d3be351
--- /dev/null
+++ b/chromium/net/http2/decoder/payload_decoders/headers_payload_decoder.cc
@@ -0,0 +1,173 @@
+// Copyright 2016 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.
+
+#include "net/http2/decoder/payload_decoders/headers_payload_decoder.h"
+
+#include <stddef.h>
+
+#include "base/logging.h"
+#include "base/macros.h"
+#include "net/http2/decoder/decode_buffer.h"
+#include "net/http2/decoder/http2_frame_decoder_listener.h"
+#include "net/http2/http2_constants.h"
+#include "net/http2/http2_structures.h"
+#include "net/http2/tools/http2_bug_tracker.h"
+
+namespace net {
+
+std::ostream& operator<<(std::ostream& out,
+ HeadersPayloadDecoder::PayloadState v) {
+ switch (v) {
+ case HeadersPayloadDecoder::PayloadState::kReadPadLength:
+ return out << "kReadPadLength";
+ case HeadersPayloadDecoder::PayloadState::kStartDecodingPriorityFields:
+ return out << "kStartDecodingPriorityFields";
+ case HeadersPayloadDecoder::PayloadState::kResumeDecodingPriorityFields:
+ return out << "kResumeDecodingPriorityFields";
+ case HeadersPayloadDecoder::PayloadState::kReadPayload:
+ return out << "kReadPayload";
+ case HeadersPayloadDecoder::PayloadState::kSkipPadding:
+ return out << "kSkipPadding";
+ }
+ return out << static_cast<int>(v);
+}
+
+DecodeStatus HeadersPayloadDecoder::StartDecodingPayload(
+ FrameDecoderState* state,
+ DecodeBuffer* db) {
+ const Http2FrameHeader& frame_header = state->frame_header();
+ const uint32_t total_length = frame_header.payload_length;
+
+ DVLOG(2) << "HeadersPayloadDecoder::StartDecodingPayload: " << frame_header;
+
+ DCHECK_EQ(Http2FrameType::HEADERS, frame_header.type);
+ DCHECK_LE(db->Remaining(), total_length);
+ DCHECK_EQ(
+ 0,
+ frame_header.flags &
+ ~(Http2FrameFlag::FLAG_END_STREAM | Http2FrameFlag::FLAG_END_HEADERS |
+ Http2FrameFlag::FLAG_PADDED | Http2FrameFlag::FLAG_PRIORITY));
+
+ // Special case for HEADERS frames that contain only the HPACK block
+ // (fragment or whole) and that fit fully into the decode buffer.
+ // Why? Unencoded browser GET requests are typically under 1K and HPACK
+ // commonly shrinks request headers by 80%, so we can expect this to
+ // be common.
+ // TODO(jamessynge) Add counters here and to Spdy for determining how
+ // common this situation is. A possible approach is to create a
+ // Http2FrameDecoderListener that counts the callbacks and then forwards
+ // them on to another listener, which makes it easy to add and remove
+ // counting on a connection or even frame basis.
+
+ // PADDED and PRIORITY both extra steps to decode, but if neither flag is
+ // set then we can decode faster.
+ const auto payload_flags =
+ Http2FrameFlag::FLAG_PADDED | Http2FrameFlag::FLAG_PRIORITY;
+ if (!frame_header.HasAnyFlags(payload_flags)) {
+ DVLOG(2) << "StartDecodingPayload !IsPadded && !HasPriority";
+ if (db->Remaining() == total_length) {
+ DVLOG(2) << "StartDecodingPayload all present";
+ // Note that we don't cache the listener field so that the callee can
+ // replace it if the frame is bad.
+ // If this case is common enough, consider combining the 3 callbacks
+ // into one, especially if END_HEADERS is also set.
+ state->listener()->OnHeadersStart(frame_header);
+ if (total_length > 0) {
+ state->listener()->OnHpackFragment(db->cursor(), total_length);
+ db->AdvanceCursor(total_length);
+ }
+ state->listener()->OnHeadersEnd();
+ return DecodeStatus::kDecodeDone;
+ }
+ payload_state_ = PayloadState::kReadPayload;
+ } else if (frame_header.IsPadded()) {
+ payload_state_ = PayloadState::kReadPadLength;
+ } else {
+ DCHECK(frame_header.HasPriority()) << frame_header;
+ payload_state_ = PayloadState::kStartDecodingPriorityFields;
+ }
+ state->InitializeRemainders();
+ state->listener()->OnHeadersStart(frame_header);
+ return ResumeDecodingPayload(state, db);
+}
+
+DecodeStatus HeadersPayloadDecoder::ResumeDecodingPayload(
+ FrameDecoderState* state,
+ DecodeBuffer* db) {
+ DVLOG(2) << "HeadersPayloadDecoder::ResumeDecodingPayload "
+ << "remaining_payload=" << state->remaining_payload()
+ << "; db->Remaining=" << db->Remaining();
+
+ const Http2FrameHeader& frame_header = state->frame_header();
+
+ DCHECK_EQ(Http2FrameType::HEADERS, frame_header.type);
+ DCHECK_LE(state->remaining_payload_and_padding(),
+ frame_header.payload_length);
+ DCHECK_LE(db->Remaining(), state->remaining_payload_and_padding());
+ DecodeStatus status;
+ size_t avail;
+ while (true) {
+ DVLOG(2) << "HeadersPayloadDecoder::ResumeDecodingPayload payload_state_="
+ << payload_state_;
+ switch (payload_state_) {
+ case PayloadState::kReadPadLength:
+ // ReadPadLength handles the OnPadLength callback, and updating the
+ // remaining_payload and remaining_padding fields. If the amount of
+ // padding is too large to fit in the frame's payload, ReadPadLength
+ // instead calls OnPaddingTooLong and returns kDecodeError.
+ status = state->ReadPadLength(db, /*report_pad_length*/ true);
+ if (status != DecodeStatus::kDecodeDone) {
+ return status;
+ }
+ if (!frame_header.HasPriority()) {
+ payload_state_ = PayloadState::kReadPayload;
+ continue;
+ }
+ // FALLTHROUGH_INTENDED
+
+ case PayloadState::kStartDecodingPriorityFields:
+ status = state->StartDecodingStructureInPayload(&priority_fields_, db);
+ if (status != DecodeStatus::kDecodeDone) {
+ payload_state_ = PayloadState::kResumeDecodingPriorityFields;
+ return status;
+ }
+ state->listener()->OnHeadersPriority(priority_fields_);
+ // FALLTHROUGH_INTENDED
+
+ case PayloadState::kReadPayload:
+ avail = state->AvailablePayload(db);
+ if (avail > 0) {
+ state->listener()->OnHpackFragment(db->cursor(), avail);
+ db->AdvanceCursor(avail);
+ state->ConsumePayload(avail);
+ }
+ if (state->remaining_payload() > 0) {
+ payload_state_ = PayloadState::kReadPayload;
+ return DecodeStatus::kDecodeInProgress;
+ }
+ // FALLTHROUGH_INTENDED
+
+ case PayloadState::kSkipPadding:
+ // SkipPadding handles the OnPadding callback.
+ if (state->SkipPadding(db)) {
+ state->listener()->OnHeadersEnd();
+ return DecodeStatus::kDecodeDone;
+ }
+ payload_state_ = PayloadState::kSkipPadding;
+ return DecodeStatus::kDecodeInProgress;
+
+ case PayloadState::kResumeDecodingPriorityFields:
+ status = state->ResumeDecodingStructureInPayload(&priority_fields_, db);
+ if (status != DecodeStatus::kDecodeDone) {
+ return status;
+ }
+ state->listener()->OnHeadersPriority(priority_fields_);
+ payload_state_ = PayloadState::kReadPayload;
+ continue;
+ }
+ HTTP2_BUG << "PayloadState: " << payload_state_;
+ }
+}
+
+} // namespace net
diff --git a/chromium/net/http2/decoder/payload_decoders/headers_payload_decoder.h b/chromium/net/http2/decoder/payload_decoders/headers_payload_decoder.h
new file mode 100644
index 00000000000..76e6a082c37
--- /dev/null
+++ b/chromium/net/http2/decoder/payload_decoders/headers_payload_decoder.h
@@ -0,0 +1,67 @@
+// Copyright 2016 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.
+
+#ifndef NET_HTTP2_DECODER_PAYLOAD_DECODERS_HEADERS_PAYLOAD_DECODER_H_
+#define NET_HTTP2_DECODER_PAYLOAD_DECODERS_HEADERS_PAYLOAD_DECODER_H_
+
+// Decodes the payload of a HEADERS frame.
+
+#include "net/base/net_export.h"
+#include "net/http2/decoder/decode_buffer.h"
+#include "net/http2/decoder/decode_status.h"
+#include "net/http2/decoder/frame_decoder_state.h"
+#include "net/http2/http2_structures.h"
+
+namespace net {
+namespace test {
+class HeadersPayloadDecoderPeer;
+} // namespace test
+
+class NET_EXPORT_PRIVATE HeadersPayloadDecoder {
+ public:
+ // States during decoding of a HEADERS frame, unless the fast path kicks
+ // in, in which case the state machine will be bypassed.
+ enum class PayloadState {
+ // The PADDED flag is set, and we now need to read the Pad Length field
+ // (the first byte of the payload, after the common frame header).
+ kReadPadLength,
+
+ // The PRIORITY flag is set, and we now need to read the fixed size priority
+ // fields (E, Stream Dependency, Weight) into priority_fields_. Calls on
+ // OnHeadersPriority if completely decodes those fields.
+ kStartDecodingPriorityFields,
+
+ // The decoder passes the non-padding portion of the remaining payload
+ // (i.e. the HPACK block fragment) to the listener's OnHpackFragment method.
+ kReadPayload,
+
+ // The decoder has finished with the HPACK block fragment, and is now
+ // ready to skip the trailing padding, if the frame has any.
+ kSkipPadding,
+
+ // The fixed size fields weren't all available when the decoder first tried
+ // to decode them (state kStartDecodingPriorityFields); this state resumes
+ // the decoding when ResumeDecodingPayload is called later.
+ kResumeDecodingPriorityFields,
+ };
+
+ // Starts the decoding of a HEADERS frame's payload, and completes it if
+ // the entire payload is in the provided decode buffer.
+ DecodeStatus StartDecodingPayload(FrameDecoderState* state, DecodeBuffer* db);
+
+ // Resumes decoding a HEADERS frame's payload that has been split across
+ // decode buffers.
+ DecodeStatus ResumeDecodingPayload(FrameDecoderState* state,
+ DecodeBuffer* db);
+
+ private:
+ friend class test::HeadersPayloadDecoderPeer;
+
+ PayloadState payload_state_;
+ Http2PriorityFields priority_fields_;
+};
+
+} // namespace net
+
+#endif // NET_HTTP2_DECODER_PAYLOAD_DECODERS_HEADERS_PAYLOAD_DECODER_H_
diff --git a/chromium/net/http2/decoder/payload_decoders/headers_payload_decoder_test.cc b/chromium/net/http2/decoder/payload_decoders/headers_payload_decoder_test.cc
new file mode 100644
index 00000000000..69bf56ffdc5
--- /dev/null
+++ b/chromium/net/http2/decoder/payload_decoders/headers_payload_decoder_test.cc
@@ -0,0 +1,169 @@
+// Copyright 2016 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.
+
+#include "net/http2/decoder/payload_decoders/headers_payload_decoder.h"
+
+#include <stddef.h>
+
+#include <string>
+
+#include "base/logging.h"
+#include "net/http2/decoder/frame_parts.h"
+#include "net/http2/decoder/frame_parts_collector.h"
+#include "net/http2/decoder/http2_frame_decoder_listener.h"
+#include "net/http2/decoder/payload_decoders/payload_decoder_base_test_util.h"
+#include "net/http2/http2_constants.h"
+#include "net/http2/http2_structures_test_util.h"
+#include "net/http2/tools/http2_frame_builder.h"
+#include "net/http2/tools/http2_random.h"
+#include "net/http2/tools/random_decoder_test.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+using std::string;
+
+namespace net {
+namespace test {
+
+class HeadersPayloadDecoderPeer {
+ public:
+ static constexpr Http2FrameType FrameType() {
+ return Http2FrameType::HEADERS;
+ }
+
+ // Returns the mask of flags that affect the decoding of the payload (i.e.
+ // flags that that indicate the presence of certain fields or padding).
+ static constexpr uint8_t FlagsAffectingPayloadDecoding() {
+ return Http2FrameFlag::FLAG_PADDED | Http2FrameFlag::FLAG_PRIORITY;
+ }
+
+ static void Randomize(HeadersPayloadDecoder* p, RandomBase* rng) {
+ CorruptEnum(&p->payload_state_, rng);
+ test::Randomize(&p->priority_fields_, rng);
+ VLOG(1) << "HeadersPayloadDecoderPeer::Randomize priority_fields_: "
+ << p->priority_fields_;
+ }
+};
+
+namespace {
+
+// Listener handles all On* methods that are expected to be called. If any other
+// On* methods of Http2FrameDecoderListener is called then the test fails; this
+// is achieved by way of FailingHttp2FrameDecoderListener, the base class of
+// FramePartsCollector.
+// These On* methods make use of StartFrame, EndFrame, etc. of the base class
+// to create and access to FrameParts instance(s) that will record the details.
+// After decoding, the test validation code can access the FramePart instance(s)
+// via the public methods of FramePartsCollector.
+struct Listener : public FramePartsCollector {
+ void OnHeadersStart(const Http2FrameHeader& header) override {
+ VLOG(1) << "OnHeadersStart: " << header;
+ StartFrame(header)->OnHeadersStart(header);
+ }
+
+ void OnHeadersPriority(const Http2PriorityFields& priority) override {
+ VLOG(1) << "OnHeadersPriority: " << priority;
+ CurrentFrame()->OnHeadersPriority(priority);
+ }
+
+ void OnHpackFragment(const char* data, size_t len) override {
+ VLOG(1) << "OnHpackFragment: len=" << len;
+ CurrentFrame()->OnHpackFragment(data, len);
+ }
+
+ void OnHeadersEnd() override {
+ VLOG(1) << "OnHeadersEnd";
+ EndFrame()->OnHeadersEnd();
+ }
+
+ void OnPadLength(size_t pad_length) override {
+ VLOG(1) << "OnPadLength: " << pad_length;
+ CurrentFrame()->OnPadLength(pad_length);
+ }
+
+ void OnPadding(const char* padding, size_t skipped_length) override {
+ VLOG(1) << "OnPadding: " << skipped_length;
+ CurrentFrame()->OnPadding(padding, skipped_length);
+ }
+
+ void OnPaddingTooLong(const Http2FrameHeader& header,
+ size_t missing_length) override {
+ VLOG(1) << "OnPaddingTooLong: " << header
+ << "; missing_length: " << missing_length;
+ FrameError(header)->OnPaddingTooLong(header, missing_length);
+ }
+
+ void OnFrameSizeError(const Http2FrameHeader& header) override {
+ VLOG(1) << "OnFrameSizeError: " << header;
+ FrameError(header)->OnFrameSizeError(header);
+ }
+};
+
+class HeadersPayloadDecoderTest
+ : public AbstractPaddablePayloadDecoderTest<HeadersPayloadDecoder,
+ HeadersPayloadDecoderPeer,
+ Listener> {};
+
+INSTANTIATE_TEST_CASE_P(VariousPadLengths,
+ HeadersPayloadDecoderTest,
+ ::testing::Values(0, 1, 2, 3, 4, 254, 255, 256));
+
+// Decode various sizes of (fake) HPACK payload, both with and without the
+// PRIORITY flag set.
+TEST_P(HeadersPayloadDecoderTest, VariousHpackPayloadSizes) {
+ for (size_t hpack_size : {0, 1, 2, 3, 255, 256, 1024}) {
+ LOG(INFO) << "########### hpack_size = " << hpack_size << " ###########";
+ Http2PriorityFields priority(RandStreamId(), 1 + Random().Rand8(),
+ Random().OneIn(2));
+
+ for (bool has_priority : {false, true}) {
+ Reset();
+ ASSERT_EQ(IsPadded() ? 1u : 0u, frame_builder_.size());
+ uint8_t flags = RandFlags();
+ if (has_priority) {
+ flags |= Http2FrameFlag::FLAG_PRIORITY;
+ frame_builder_.Append(priority);
+ }
+
+ string hpack_payload = Random().RandString(hpack_size);
+ frame_builder_.Append(hpack_payload);
+
+ MaybeAppendTrailingPadding();
+ Http2FrameHeader frame_header(frame_builder_.size(),
+ Http2FrameType::HEADERS, flags,
+ RandStreamId());
+ set_frame_header(frame_header);
+ ScrubFlagsOfHeader(&frame_header);
+ FrameParts expected(frame_header, hpack_payload, total_pad_length_);
+ if (has_priority) {
+ expected.opt_priority = priority;
+ }
+ EXPECT_TRUE(DecodePayloadAndValidateSeveralWays(frame_builder_.buffer(),
+ expected));
+ }
+ }
+}
+
+// Confirm we get an error if the PRIORITY flag is set but the payload is
+// not long enough, regardless of the amount of (valid) padding.
+TEST_P(HeadersPayloadDecoderTest, Truncated) {
+ auto approve_size = [](size_t size) {
+ return size != Http2PriorityFields::EncodedSize();
+ };
+ Http2FrameBuilder fb;
+ fb.Append(Http2PriorityFields(RandStreamId(), 1 + Random().Rand8(),
+ Random().OneIn(2)));
+ EXPECT_TRUE(VerifyDetectsMultipleFrameSizeErrors(
+ Http2FrameFlag::FLAG_PRIORITY, fb.buffer(), approve_size,
+ total_pad_length_));
+}
+
+// Confirm we get an error if the PADDED flag is set but the payload is not
+// long enough to hold even the Pad Length amount of padding.
+TEST_P(HeadersPayloadDecoderTest, PaddingTooLong) {
+ EXPECT_TRUE(VerifyDetectsPaddingTooLong());
+}
+
+} // namespace
+} // namespace test
+} // namespace net
diff --git a/chromium/net/http2/decoder/payload_decoders/payload_decoder_base_test_util.cc b/chromium/net/http2/decoder/payload_decoders/payload_decoder_base_test_util.cc
new file mode 100644
index 00000000000..d96d481b63e
--- /dev/null
+++ b/chromium/net/http2/decoder/payload_decoders/payload_decoder_base_test_util.cc
@@ -0,0 +1,98 @@
+// Copyright 2016 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.
+
+#include "net/http2/decoder/payload_decoders/payload_decoder_base_test_util.h"
+
+#include "net/http2/decoder/frame_decoder_state_test_util.h"
+#include "net/http2/http2_structures_test_util.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace net {
+namespace test {
+PayloadDecoderBaseTest::PayloadDecoderBaseTest() {
+ // If the test adds more data after the frame payload,
+ // stop as soon as the payload is decoded.
+ stop_decode_on_done_ = true;
+ frame_header_is_set_ = false;
+ Randomize(&frame_header_, RandomPtr());
+}
+
+DecodeStatus PayloadDecoderBaseTest::StartDecoding(DecodeBuffer* db) {
+ DVLOG(2) << "StartDecoding, db->Remaining=" << db->Remaining();
+ // Make sure sub-class has set frame_header_ so that we can inject it
+ // into the payload decoder below.
+ if (!frame_header_is_set_) {
+ ADD_FAILURE() << "frame_header_ is not set";
+ return DecodeStatus::kDecodeError;
+ }
+ // The contract with the payload decoders is that they won't receive a
+ // decode buffer that extends beyond the end of the frame.
+ if (db->Remaining() > frame_header_.payload_length) {
+ ADD_FAILURE() << "DecodeBuffer has too much data: " << db->Remaining()
+ << " > " << frame_header_.payload_length;
+ return DecodeStatus::kDecodeError;
+ }
+
+ // Prepare the payload decoder.
+ PreparePayloadDecoder();
+
+ // Reconstruct the FrameDecoderState, prepare the listener, and add it to
+ // the FrameDecoderState.
+ frame_decoder_state_.~FrameDecoderState();
+ new (&frame_decoder_state_) FrameDecoderState;
+ frame_decoder_state_.set_listener(PrepareListener());
+
+ // Make sure that a listener was provided.
+ if (frame_decoder_state_.listener() == nullptr) {
+ ADD_FAILURE() << "PrepareListener must return a listener.";
+ return DecodeStatus::kDecodeError;
+ }
+
+ // Now that nothing in the payload decoder should be valid, inject the
+ // Http2FrameHeader whose payload we're about to decode. That header is the
+ // only state that a payload decoder should expect is valid when its Start
+ // method is called.
+ FrameDecoderStatePeer::set_frame_header(frame_header_, &frame_decoder_state_);
+ DecodeStatus status = StartDecodingPayload(db);
+ if (status != DecodeStatus::kDecodeInProgress) {
+ // Keep track of this so that a concrete test can verify that both fast
+ // and slow decoding paths have been tested.
+ ++fast_decode_count_;
+ }
+ return status;
+}
+
+DecodeStatus PayloadDecoderBaseTest::ResumeDecoding(DecodeBuffer* db) {
+ DVLOG(2) << "ResumeDecoding, db->Remaining=" << db->Remaining();
+ DecodeStatus status = ResumeDecodingPayload(db);
+ if (status != DecodeStatus::kDecodeInProgress) {
+ // Keep track of this so that a concrete test can verify that both fast
+ // and slow decoding paths have been tested.
+ ++slow_decode_count_;
+ }
+ return status;
+}
+
+::testing::AssertionResult
+PayloadDecoderBaseTest::DecodePayloadAndValidateSeveralWays(
+ base::StringPiece payload,
+ Validator validator) {
+ VERIFY_TRUE(frame_header_is_set_);
+ // Cap the payload to be decoded at the declared payload length. This is
+ // required by the decoders' preconditions; they are designed on the
+ // assumption that they're never passed more than they're permitted to
+ // consume.
+ // Note that it is OK if the payload is too short; the validator may be
+ // designed to check for that.
+ if (payload.size() > frame_header_.payload_length) {
+ payload = base::StringPiece(payload.data(), frame_header_.payload_length);
+ }
+ DecodeBuffer db(payload);
+ ResetDecodeSpeedCounters();
+ const bool kMayReturnZeroOnFirst = false;
+ return DecodeAndValidateSeveralWays(&db, kMayReturnZeroOnFirst, validator);
+}
+
+} // namespace test
+} // namespace net
diff --git a/chromium/net/http2/decoder/payload_decoders/payload_decoder_base_test_util.h b/chromium/net/http2/decoder/payload_decoders/payload_decoder_base_test_util.h
new file mode 100644
index 00000000000..5f998e42d08
--- /dev/null
+++ b/chromium/net/http2/decoder/payload_decoders/payload_decoder_base_test_util.h
@@ -0,0 +1,462 @@
+// Copyright 2016 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.
+
+#ifndef NET_HTTP2_DECODER_PAYLOAD_DECODERS_PAYLOAD_DECODER_BASE_TEST_UTIL_H_
+#define NET_HTTP2_DECODER_PAYLOAD_DECODERS_PAYLOAD_DECODER_BASE_TEST_UTIL_H_
+
+// Base class for testing concrete payload decoder classes.
+
+#include <stddef.h>
+
+#include <string>
+
+#include "base/logging.h"
+#include "base/strings/string_piece.h"
+#include "net/http2/decoder/decode_buffer.h"
+#include "net/http2/decoder/decode_status.h"
+#include "net/http2/decoder/frame_decoder_state.h"
+#include "net/http2/decoder/frame_parts.h"
+#include "net/http2/decoder/http2_frame_decoder_listener.h"
+#include "net/http2/http2_constants.h"
+#include "net/http2/http2_constants_test_util.h"
+#include "net/http2/http2_structures.h"
+#include "net/http2/tools/http2_frame_builder.h"
+#include "net/http2/tools/random_decoder_test.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace net {
+namespace test {
+
+// Base class for tests of payload decoders. Below this there is a templated
+// sub-class that adds a bunch of type specific features.
+class PayloadDecoderBaseTest : public RandomDecoderTest {
+ protected:
+ PayloadDecoderBaseTest();
+
+ // Virtual functions to be implemented by the test classes for the individual
+ // payload decoders...
+
+ // Start decoding the payload.
+ virtual DecodeStatus StartDecodingPayload(DecodeBuffer* db) = 0;
+
+ // Resume decoding the payload.
+ virtual DecodeStatus ResumeDecodingPayload(DecodeBuffer* db) = 0;
+
+ // In support of ensuring that we're really accessing and updating the
+ // decoder, prepare the decoder by, for example, overwriting the decoder.
+ virtual void PreparePayloadDecoder() = 0;
+
+ // Get the listener to be inserted into the FrameDecoderState, ready for
+ // listening (e.g. reset if it is a FramePartsCollector).
+ virtual Http2FrameDecoderListener* PrepareListener() = 0;
+
+ // Record a frame header for use on each call to StartDecoding.
+ void set_frame_header(const Http2FrameHeader& header) {
+ EXPECT_EQ(0, InvalidFlagMaskForFrameType(header.type) & header.flags);
+ if (!frame_header_is_set_ || frame_header_ != header) {
+ VLOG(2) << "set_frame_header: " << frame_header_;
+ }
+ frame_header_ = header;
+ frame_header_is_set_ = true;
+ }
+
+ const Http2FrameHeader& frame_header() const {
+ CHECK(frame_header_is_set_);
+ return frame_header_;
+ }
+
+ FrameDecoderState* mutable_state() { return &frame_decoder_state_; }
+
+ // Randomize the payload decoder, sets the payload decoder's frame_header_,
+ // then start decoding the payload. Called by RandomDecoderTest. This method
+ // is final so that we can always perform certain actions when
+ // RandomDecoderTest starts the decoding of a payload, such as randomizing the
+ // the payload decoder, injecting the frame header and counting fast decoding
+ // cases. Sub-classes must implement StartDecodingPayload to perform their
+ // initial decoding of a frame's payload.
+ DecodeStatus StartDecoding(DecodeBuffer* db) final;
+
+ // Called by RandomDecoderTest. This method is final so that we can always
+ // perform certain actions when RandomDecoderTest calls it, such as counting
+ // slow decode cases. Sub-classes must implement ResumeDecodingPayload to
+ // continue decoding the frame's payload, which must not all be in one buffer.
+ DecodeStatus ResumeDecoding(DecodeBuffer* db) final;
+
+ // Given the specified payload (without the common frame header), decode
+ // it with several partitionings of the payload.
+ ::testing::AssertionResult DecodePayloadAndValidateSeveralWays(
+ base::StringPiece payload,
+ Validator validator);
+
+ // TODO(jamessynge): Add helper method for verifying these are both non-zero,
+ // and call the new method from tests that expect successful decoding.
+ void ResetDecodeSpeedCounters() {
+ fast_decode_count_ = 0;
+ slow_decode_count_ = 0;
+ }
+
+ // Count of payloads that are full decoded by StartDecodingPayload, or that
+ // an error was detected by StartDecodingPayload.
+ size_t fast_decode_count_ = 0;
+
+ // Count of payloads that require calling ResumeDecodingPayload in order to
+ // decode them completely (or to detect an error during decoding).
+ size_t slow_decode_count_ = 0;
+
+ private:
+ bool frame_header_is_set_ = false;
+ Http2FrameHeader frame_header_;
+ FrameDecoderState frame_decoder_state_;
+};
+
+// Base class for payload decoders of type Decoder, with corresponding test
+// peer of type DecoderPeer, and using class Listener as the implementation
+// of Http2FrameDecoderListenerInterface to be used during decoding.
+// Typically Listener is a sub-class of FramePartsCollector.
+// SupportedFrameType is set to false only for UnknownPayloadDecoder.
+template <class Decoder,
+ class DecoderPeer,
+ class Listener,
+ bool SupportedFrameType = true>
+class AbstractPayloadDecoderTest : public PayloadDecoderBaseTest {
+
+ protected:
+ // An ApproveSize function returns true to approve decoding the specified
+ // size of payload, else false to skip that size. Typically used for negative
+ // tests; for example, decoding a SETTINGS frame at all sizes except for
+ // multiples of 6.
+ typedef std::function<bool(size_t size)> ApproveSize;
+
+ AbstractPayloadDecoderTest() {}
+
+ // These tests are in setup rather than the constructor for two reasons:
+ // 1) Constructors are not allowed to fail, so gUnit documents that EXPECT_*
+ // and ASSERT_* are not allowed in constructors, and should instead be in
+ // SetUp if they are needed before the body of the test is executed.
+ // 2) To allow the sub-class constructor to make any desired modifications to
+ // the DecoderPeer before these tests are executed; in particular,
+ // UnknownPayloadDecoderPeer has not got a fixed frame type, but it is
+ // instead set during the test's constructor.
+ void SetUp() override {
+ PayloadDecoderBaseTest::SetUp();
+
+ // Confirm that DecoderPeer et al returns sensible values. Using auto as the
+ // variable type so that no (narrowing) conversions take place that hide
+ // problems; i.e. if someone changes KnownFlagsMaskForFrameType so that it
+ // doesn't return a uint8, and has bits above the low-order 8 bits set, this
+ // bit of paranoia should detect the problem before we get too far.
+ auto frame_type = DecoderPeer::FrameType();
+ if (SupportedFrameType) {
+ EXPECT_TRUE(IsSupportedHttp2FrameType(frame_type)) << frame_type;
+ } else {
+ EXPECT_FALSE(IsSupportedHttp2FrameType(frame_type)) << frame_type;
+ }
+
+ auto known_flags = KnownFlagsMaskForFrameType(frame_type);
+ EXPECT_EQ(known_flags, known_flags & 0xff);
+
+ auto flags_to_avoid = DecoderPeer::FlagsAffectingPayloadDecoding();
+ EXPECT_EQ(flags_to_avoid, flags_to_avoid & known_flags);
+ }
+
+ void PreparePayloadDecoder() override {
+ payload_decoder_.~Decoder();
+ new (&payload_decoder_) Decoder;
+ }
+
+ Http2FrameDecoderListener* PrepareListener() override {
+ listener_.Reset();
+ return &listener_;
+ }
+
+ // Returns random flags, but only those valid for the frame type, yet not
+ // those that the DecoderPeer says will affect the decoding of the payload
+ // (e.g. the PRIORTY flag on a HEADERS frame or PADDED on DATA frames).
+ uint8_t RandFlags() {
+ return Random().Rand8() &
+ KnownFlagsMaskForFrameType(DecoderPeer::FrameType()) &
+ ~DecoderPeer::FlagsAffectingPayloadDecoding();
+ }
+
+ // Start decoding the payload.
+ DecodeStatus StartDecodingPayload(DecodeBuffer* db) override {
+ DVLOG(2) << "StartDecodingPayload, db->Remaining=" << db->Remaining();
+ return payload_decoder_.StartDecodingPayload(mutable_state(), db);
+ }
+
+ // Resume decoding the payload.
+ DecodeStatus ResumeDecodingPayload(DecodeBuffer* db) override {
+ DVLOG(2) << "ResumeDecodingPayload, db->Remaining=" << db->Remaining();
+ return payload_decoder_.ResumeDecodingPayload(mutable_state(), db);
+ }
+
+
+ // Decode one frame's payload and confirm that the listener recorded the
+ // expected FrameParts instance, and only FrameParts instance. The payload
+ // will be decoded several times with different partitionings of the payload,
+ // and after each the validator will be called.
+ AssertionResult DecodePayloadAndValidateSeveralWays(
+ base::StringPiece payload,
+ const FrameParts& expected) {
+ NoArgValidator validator = [&expected, this]() -> AssertionResult {
+ VERIFY_FALSE(listener_.IsInProgress());
+ VERIFY_EQ(1u, listener_.size());
+ VERIFY_AND_RETURN_SUCCESS(expected.VerifyEquals(*listener_.frame(0)));
+ };
+ return PayloadDecoderBaseTest::DecodePayloadAndValidateSeveralWays(
+ payload, ValidateDoneAndEmpty(validator));
+ }
+
+ // Decode one frame's payload, expecting that the final status will be
+ // kDecodeError, and that OnFrameSizeError will have been called on the
+ // listener. The payload will be decoded several times with different
+ // partitionings of the payload. The type WrappedValidator is either
+ // RandomDecoderTest::Validator, RandomDecoderTest::NoArgValidator or
+ // std::nullptr_t (not extra validation).
+ template <typename WrappedValidator>
+ ::testing::AssertionResult VerifyDetectsFrameSizeError(
+ base::StringPiece payload,
+ const Http2FrameHeader& header,
+ WrappedValidator wrapped_validator) {
+ set_frame_header(header);
+ // If wrapped_validator is not a RandomDecoderTest::Validator, make it so.
+ Validator validator = ToValidator(wrapped_validator);
+ // And wrap that validator in another which will check that we've reached
+ // the expected state of kDecodeError with OnFrameSizeError having been
+ // called by the payload decoder.
+ validator = [header, validator, this](
+ const DecodeBuffer& input,
+ DecodeStatus status) -> ::testing::AssertionResult {
+ DVLOG(2) << "VerifyDetectsFrameSizeError validator; status=" << status
+ << "; input.Remaining=" << input.Remaining();
+ VERIFY_EQ(DecodeStatus::kDecodeError, status);
+ VERIFY_FALSE(listener_.IsInProgress());
+ VERIFY_EQ(1u, listener_.size());
+ const FrameParts* frame = listener_.frame(0);
+ VERIFY_EQ(header, frame->frame_header);
+ VERIFY_TRUE(frame->has_frame_size_error);
+ // Verify did not get OnPaddingTooLong, as we should only ever produce
+ // one of these two errors for a single frame.
+ VERIFY_FALSE(frame->opt_missing_length);
+ return validator(input, status);
+ };
+ VERIFY_AND_RETURN_SUCCESS(
+ PayloadDecoderBaseTest::DecodePayloadAndValidateSeveralWays(payload,
+ validator));
+ }
+
+ // Confirm that we get OnFrameSizeError when trying to decode unpadded_payload
+ // at all sizes from zero to unpadded_payload.size(), except those sizes not
+ // approved by approve_size.
+ // If total_pad_length is greater than zero, then that amount of padding
+ // is added to the payload (including the Pad Length field).
+ // The flags will be required_flags, PADDED if total_pad_length > 0, and some
+ // randomly selected flag bits not excluded by FlagsAffectingPayloadDecoding.
+ ::testing::AssertionResult VerifyDetectsMultipleFrameSizeErrors(
+ uint8_t required_flags,
+ base::StringPiece unpadded_payload,
+ ApproveSize approve_size,
+ int total_pad_length) {
+ // required_flags should come from those that are defined for the frame
+ // type AND are those that affect the decoding of the payload (otherwise,
+ // the flag shouldn't be required).
+ Http2FrameType frame_type = DecoderPeer::FrameType();
+ VERIFY_EQ(required_flags,
+ required_flags & KnownFlagsMaskForFrameType(frame_type));
+ VERIFY_EQ(required_flags,
+ required_flags & DecoderPeer::FlagsAffectingPayloadDecoding());
+
+ if (0 != (Http2FrameFlag::FLAG_PADDED &
+ KnownFlagsMaskForFrameType(frame_type))) {
+ // Frame type supports padding.
+ if (total_pad_length == 0) {
+ required_flags &= ~Http2FrameFlag::FLAG_PADDED;
+ } else {
+ required_flags |= Http2FrameFlag::FLAG_PADDED;
+ }
+ } else {
+ VERIFY_EQ(0, total_pad_length);
+ }
+
+ bool validated = false;
+ for (size_t real_payload_size = 0;
+ real_payload_size <= unpadded_payload.size(); ++real_payload_size) {
+ if (approve_size != nullptr && !approve_size(real_payload_size)) {
+ continue;
+ }
+ VLOG(1) << "real_payload_size=" << real_payload_size;
+ uint8_t flags = required_flags | RandFlags();
+ Http2FrameBuilder fb;
+ if (total_pad_length > 0) {
+ // total_pad_length_ includes the size of the Pad Length field, and thus
+ // ranges from 0 (no PADDED flag) to 256 (Pad Length == 255).
+ fb.AppendUInt8(total_pad_length - 1);
+ }
+ // Append a subset of the unpadded_payload, which the decoder should
+ // determine is not a valid amount.
+ fb.Append(unpadded_payload.substr(0, real_payload_size));
+ if (total_pad_length > 0) {
+ fb.AppendZeroes(total_pad_length - 1);
+ }
+ // We choose a random stream id because the payload decoders aren't
+ // checking stream ids.
+ uint32_t stream_id = RandStreamId();
+ Http2FrameHeader header(fb.size(), frame_type, flags, stream_id);
+ VERIFY_SUCCESS(VerifyDetectsFrameSizeError(fb.buffer(), header, nullptr));
+ validated = true;
+ }
+ VERIFY_TRUE(validated);
+ return ::testing::AssertionSuccess();
+ }
+
+ // As above, but for frames without padding.
+ ::testing::AssertionResult VerifyDetectsFrameSizeError(
+ uint8_t required_flags,
+ base::StringPiece unpadded_payload,
+ ApproveSize approve_size) {
+ Http2FrameType frame_type = DecoderPeer::FrameType();
+ uint8_t known_flags = KnownFlagsMaskForFrameType(frame_type);
+ VERIFY_EQ(0, known_flags & Http2FrameFlag::FLAG_PADDED);
+ VERIFY_EQ(0, required_flags & Http2FrameFlag::FLAG_PADDED);
+ VERIFY_AND_RETURN_SUCCESS(VerifyDetectsMultipleFrameSizeErrors(
+ required_flags, unpadded_payload, approve_size, 0));
+ }
+
+ Listener listener_;
+ union {
+ // Confirm at compile time that Decoder can be in an anonymous union,
+ // i.e. complain loudly if Decoder has members that prevent this, as it
+ // becomes annoying and possibly difficult to deal with non-anonymous
+ // unions and such union members.
+ Decoder payload_decoder_;
+ };
+};
+
+// A base class for tests parameterized by the total number of bytes of
+// padding, including the Pad Length field (i.e. a total_pad_length of 0
+// means unpadded as there is then no room for the Pad Length field).
+// The frame type must support padding.
+template <class Decoder, class DecoderPeer, class Listener>
+class AbstractPaddablePayloadDecoderTest
+ : public AbstractPayloadDecoderTest<Decoder, DecoderPeer, Listener>,
+ public ::testing::WithParamInterface<int> {
+ typedef AbstractPayloadDecoderTest<Decoder, DecoderPeer, Listener> Base;
+
+ protected:
+ using Base::Random;
+ using Base::RandStreamId;
+ using Base::set_frame_header;
+ using Base::listener_;
+ typedef typename Base::Validator Validator;
+
+ AbstractPaddablePayloadDecoderTest() : total_pad_length_(GetParam()) {
+ LOG(INFO) << "total_pad_length_ = " << total_pad_length_;
+ }
+
+ // Note that total_pad_length_ includes the size of the Pad Length field,
+ // and thus ranges from 0 (no PADDED flag) to 256 (Pad Length == 255).
+ bool IsPadded() const { return total_pad_length_ > 0; }
+
+ // Value of the Pad Length field. Only call if IsPadded.
+ size_t pad_length() const {
+ EXPECT_TRUE(IsPadded());
+ return total_pad_length_ - 1;
+ }
+
+ // Clear the frame builder and add the Pad Length field if appropriate.
+ void Reset() {
+ frame_builder_ = Http2FrameBuilder();
+ if (IsPadded()) {
+ frame_builder_.AppendUInt8(pad_length());
+ }
+ }
+
+ void MaybeAppendTrailingPadding() {
+ if (IsPadded()) {
+ frame_builder_.AppendZeroes(pad_length());
+ }
+ }
+
+ uint8_t RandFlags() {
+ uint8_t flags = Base::RandFlags();
+ if (IsPadded()) {
+ flags |= Http2FrameFlag::FLAG_PADDED;
+ } else {
+ flags &= ~Http2FrameFlag::FLAG_PADDED;
+ }
+ return flags;
+ }
+
+
+ // Verify that we get OnPaddingTooLong when decoding payload, and that the
+ // amount of missing padding is as specified. header.IsPadded must be true,
+ // and the payload must be empty or the PadLength field must be too large.
+ ::testing::AssertionResult VerifyDetectsPaddingTooLong(
+ base::StringPiece payload,
+ const Http2FrameHeader& header,
+ int expected_missing_length) {
+ set_frame_header(header);
+ auto& listener = listener_;
+ Validator validator = [header, expected_missing_length, &listener](
+ const DecodeBuffer& input,
+ DecodeStatus status) -> ::testing::AssertionResult {
+ VERIFY_EQ(DecodeStatus::kDecodeError, status);
+ VERIFY_FALSE(listener.IsInProgress());
+ VERIFY_EQ(1u, listener.size());
+ const FrameParts* frame = listener.frame(0);
+ VERIFY_EQ(header, frame->frame_header);
+ VERIFY_TRUE(frame->opt_missing_length);
+ VERIFY_EQ(expected_missing_length, frame->opt_missing_length.value());
+ // Verify did not get OnFrameSizeError.
+ VERIFY_FALSE(frame->has_frame_size_error);
+ return ::testing::AssertionSuccess();
+ };
+ VERIFY_AND_RETURN_SUCCESS(
+ PayloadDecoderBaseTest::DecodePayloadAndValidateSeveralWays(payload,
+ validator));
+ }
+
+ // Verifies that we get OnPaddingTooLong for a padded frame payload whose
+ // (randomly selected) payload length is less than total_pad_length_.
+ // Flags will be selected at random, except PADDED will be set and
+ // flags_to_avoid will not be set. The stream id is selected at random.
+ ::testing::AssertionResult VerifyDetectsPaddingTooLong() {
+ uint8_t flags = RandFlags() | Http2FrameFlag::FLAG_PADDED;
+
+ // Create an all padding payload for total_pad_length_.
+ int payload_length = 0;
+ Http2FrameBuilder fb;
+ if (IsPadded()) {
+ fb.AppendUInt8(pad_length());
+ fb.AppendZeroes(pad_length());
+ VLOG(1) << "fb.size=" << fb.size();
+ // Pick a random length for the payload that is shorter than neccesary.
+ payload_length = Random().Rand32() % fb.size();
+ }
+
+ VLOG(1) << "payload_length=" << payload_length;
+ std::string payload = fb.buffer().substr(0, payload_length);
+
+ // The missing length is the amount we cut off the end, unless
+ // payload_length is zero, in which case the decoder knows only that 1
+ // byte, the Pad Length field, is missing.
+ int missing_length = payload_length == 0 ? 1 : fb.size() - payload_length;
+ VLOG(1) << "missing_length=" << missing_length;
+
+ const Http2FrameHeader header(payload_length, DecoderPeer::FrameType(),
+ flags, RandStreamId());
+ VERIFY_AND_RETURN_SUCCESS(
+ VerifyDetectsPaddingTooLong(payload, header, missing_length));
+ }
+
+ // total_pad_length_ includes the size of the Pad Length field, and thus
+ // ranges from 0 (no PADDED flag) to 256 (Pad Length == 255).
+ const size_t total_pad_length_;
+ Http2FrameBuilder frame_builder_;
+};
+
+} // namespace test
+} // namespace net
+
+#endif // NET_HTTP2_DECODER_PAYLOAD_DECODERS_PAYLOAD_DECODER_BASE_TEST_UTIL_H_
diff --git a/chromium/net/http2/decoder/payload_decoders/ping_payload_decoder.cc b/chromium/net/http2/decoder/payload_decoders/ping_payload_decoder.cc
new file mode 100644
index 00000000000..abe43d0a6a2
--- /dev/null
+++ b/chromium/net/http2/decoder/payload_decoders/ping_payload_decoder.cc
@@ -0,0 +1,89 @@
+// Copyright 2016 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.
+
+#include "net/http2/decoder/payload_decoders/ping_payload_decoder.h"
+
+#include "base/logging.h"
+#include "net/http2/decoder/http2_frame_decoder_listener.h"
+#include "net/http2/http2_constants.h"
+
+namespace net {
+namespace {
+constexpr auto kOpaqueSize = Http2PingFields::EncodedSize();
+}
+
+DecodeStatus PingPayloadDecoder::StartDecodingPayload(FrameDecoderState* state,
+ DecodeBuffer* db) {
+ const Http2FrameHeader& frame_header = state->frame_header();
+ const uint32_t total_length = frame_header.payload_length;
+
+ DVLOG(2) << "PingPayloadDecoder::StartDecodingPayload: " << frame_header;
+ DCHECK_EQ(Http2FrameType::PING, frame_header.type);
+ DCHECK_LE(db->Remaining(), total_length);
+ DCHECK_EQ(0, frame_header.flags & ~(Http2FrameFlag::FLAG_ACK));
+
+ // Is the payload entirely in the decode buffer and is it the correct size?
+ // Given the size of the header and payload (17 bytes total), this is most
+ // likely the case the vast majority of the time.
+ if (db->Remaining() == kOpaqueSize && total_length == kOpaqueSize) {
+ // Special case this situation as it allows us to avoid any copying;
+ // the other path makes two copies, first into the buffer in
+ // Http2StructureDecoder as it accumulates the 8 bytes of opaque data,
+ // and a second copy into the Http2PingFields member of in this class.
+ // This supports the claim that this decoder is (mostly) non-buffering.
+ static_assert(sizeof(Http2PingFields) == kOpaqueSize,
+ "If not, then can't enter this block!");
+ auto ping = reinterpret_cast<const Http2PingFields*>(db->cursor());
+ if (frame_header.IsAck()) {
+ state->listener()->OnPingAck(frame_header, *ping);
+ } else {
+ state->listener()->OnPing(frame_header, *ping);
+ }
+ db->AdvanceCursor(kOpaqueSize);
+ return DecodeStatus::kDecodeDone;
+ }
+ state->InitializeRemainders();
+ return HandleStatus(
+ state, state->StartDecodingStructureInPayload(&ping_fields_, db));
+}
+
+DecodeStatus PingPayloadDecoder::ResumeDecodingPayload(FrameDecoderState* state,
+ DecodeBuffer* db) {
+ DVLOG(2) << "ResumeDecodingPayload: remaining_payload="
+ << state->remaining_payload();
+ DCHECK_EQ(Http2FrameType::PING, state->frame_header().type);
+ DCHECK_LE(db->Remaining(), state->frame_header().payload_length);
+ return HandleStatus(
+ state, state->ResumeDecodingStructureInPayload(&ping_fields_, db));
+}
+
+DecodeStatus PingPayloadDecoder::HandleStatus(FrameDecoderState* state,
+ DecodeStatus status) {
+ DVLOG(2) << "HandleStatus: status=" << status
+ << "; remaining_payload=" << state->remaining_payload();
+ if (status == DecodeStatus::kDecodeDone) {
+ if (state->remaining_payload() == 0) {
+ const Http2FrameHeader& frame_header = state->frame_header();
+ if (frame_header.IsAck()) {
+ state->listener()->OnPingAck(frame_header, ping_fields_);
+ } else {
+ state->listener()->OnPing(frame_header, ping_fields_);
+ }
+ return DecodeStatus::kDecodeDone;
+ }
+ // Payload is too long.
+ return state->ReportFrameSizeError();
+ }
+ // Not done decoding the structure. Either we've got more payload to decode,
+ // or we've run out because the payload is too short.
+ DCHECK(
+ (status == DecodeStatus::kDecodeInProgress &&
+ state->remaining_payload() > 0) ||
+ (status == DecodeStatus::kDecodeError && state->remaining_payload() == 0))
+ << "\n status=" << status
+ << "; remaining_payload=" << state->remaining_payload();
+ return status;
+}
+
+} // namespace net
diff --git a/chromium/net/http2/decoder/payload_decoders/ping_payload_decoder.h b/chromium/net/http2/decoder/payload_decoders/ping_payload_decoder.h
new file mode 100644
index 00000000000..0eb10a2e5cc
--- /dev/null
+++ b/chromium/net/http2/decoder/payload_decoders/ping_payload_decoder.h
@@ -0,0 +1,43 @@
+// Copyright 2016 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.
+
+#ifndef NET_HTTP2_DECODER_PAYLOAD_DECODERS_PING_PAYLOAD_DECODER_H_
+#define NET_HTTP2_DECODER_PAYLOAD_DECODERS_PING_PAYLOAD_DECODER_H_
+
+// Decodes the payload of a PING frame; for the RFC, see:
+// http://httpwg.org/specs/rfc7540.html#PING
+
+#include "net/base/net_export.h"
+#include "net/http2/decoder/decode_buffer.h"
+#include "net/http2/decoder/decode_status.h"
+#include "net/http2/decoder/frame_decoder_state.h"
+#include "net/http2/http2_structures.h"
+
+namespace net {
+namespace test {
+class PingPayloadDecoderPeer;
+} // namespace test
+
+class NET_EXPORT_PRIVATE PingPayloadDecoder {
+ public:
+ // Starts the decoding of a PING frame's payload, and completes it if the
+ // entire payload is in the provided decode buffer.
+ DecodeStatus StartDecodingPayload(FrameDecoderState* state, DecodeBuffer* db);
+
+ // Resumes decoding a PING frame's payload that has been split across
+ // decode buffers.
+ DecodeStatus ResumeDecodingPayload(FrameDecoderState* state,
+ DecodeBuffer* db);
+
+ private:
+ friend class test::PingPayloadDecoderPeer;
+
+ DecodeStatus HandleStatus(FrameDecoderState* state, DecodeStatus status);
+
+ Http2PingFields ping_fields_;
+};
+
+} // namespace net
+
+#endif // NET_HTTP2_DECODER_PAYLOAD_DECODERS_PING_PAYLOAD_DECODER_H_
diff --git a/chromium/net/http2/decoder/payload_decoders/ping_payload_decoder_test.cc b/chromium/net/http2/decoder/payload_decoders/ping_payload_decoder_test.cc
new file mode 100644
index 00000000000..573341177c9
--- /dev/null
+++ b/chromium/net/http2/decoder/payload_decoders/ping_payload_decoder_test.cc
@@ -0,0 +1,117 @@
+// Copyright 2016 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.
+
+#include "net/http2/decoder/payload_decoders/ping_payload_decoder.h"
+
+#include <stddef.h>
+
+#include "base/logging.h"
+#include "net/http2/decoder/frame_parts.h"
+#include "net/http2/decoder/frame_parts_collector.h"
+#include "net/http2/decoder/http2_frame_decoder_listener.h"
+#include "net/http2/decoder/payload_decoders/payload_decoder_base_test_util.h"
+#include "net/http2/http2_constants.h"
+#include "net/http2/http2_structures_test_util.h"
+#include "net/http2/tools/http2_frame_builder.h"
+#include "net/http2/tools/http2_random.h"
+#include "net/http2/tools/random_decoder_test.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace net {
+namespace test {
+
+class PingPayloadDecoderPeer {
+ public:
+ static constexpr Http2FrameType FrameType() { return Http2FrameType::PING; }
+
+ // Returns the mask of flags that affect the decoding of the payload (i.e.
+ // flags that that indicate the presence of certain fields or padding).
+ static constexpr uint8_t FlagsAffectingPayloadDecoding() { return 0; }
+
+ static void Randomize(PingPayloadDecoder* p, RandomBase* rng) {
+ VLOG(1) << "PingPayloadDecoderPeer::Randomize";
+ test::Randomize(&p->ping_fields_, rng);
+ }
+};
+
+namespace {
+
+struct Listener : public FramePartsCollector {
+ void OnPing(const Http2FrameHeader& header,
+ const Http2PingFields& ping) override {
+ VLOG(1) << "OnPing: " << header << "; " << ping;
+ StartAndEndFrame(header)->OnPing(header, ping);
+ }
+
+ void OnPingAck(const Http2FrameHeader& header,
+ const Http2PingFields& ping) override {
+ VLOG(1) << "OnPingAck: " << header << "; " << ping;
+ StartAndEndFrame(header)->OnPingAck(header, ping);
+ }
+
+ void OnFrameSizeError(const Http2FrameHeader& header) override {
+ VLOG(1) << "OnFrameSizeError: " << header;
+ FrameError(header)->OnFrameSizeError(header);
+ }
+};
+
+class PingPayloadDecoderTest
+ : public AbstractPayloadDecoderTest<PingPayloadDecoder,
+ PingPayloadDecoderPeer,
+ Listener> {
+ protected:
+ Http2PingFields RandPingFields() {
+ Http2PingFields fields;
+ test::Randomize(&fields, RandomPtr());
+ return fields;
+ }
+};
+
+// Confirm we get an error if the payload is not the correct size to hold
+// exactly one Http2PingFields.
+TEST_F(PingPayloadDecoderTest, WrongSize) {
+ auto approve_size = [](size_t size) {
+ return size != Http2PingFields::EncodedSize();
+ };
+ Http2FrameBuilder fb;
+ fb.Append(RandPingFields());
+ fb.Append(RandPingFields());
+ fb.Append(RandPingFields());
+ EXPECT_TRUE(VerifyDetectsFrameSizeError(0, fb.buffer(), approve_size));
+}
+
+TEST_F(PingPayloadDecoderTest, Ping) {
+ for (int n = 0; n < 100; ++n) {
+ Http2PingFields fields = RandPingFields();
+ Http2FrameBuilder fb;
+ fb.Append(fields);
+ Http2FrameHeader header(fb.size(), Http2FrameType::PING,
+ RandFlags() & ~Http2FrameFlag::FLAG_ACK,
+ RandStreamId());
+ set_frame_header(header);
+ FrameParts expected(header);
+ expected.opt_ping = fields;
+ EXPECT_TRUE(DecodePayloadAndValidateSeveralWays(fb.buffer(), expected));
+ }
+}
+
+TEST_F(PingPayloadDecoderTest, PingAck) {
+ for (int n = 0; n < 100; ++n) {
+ Http2PingFields fields;
+ Randomize(&fields, RandomPtr());
+ Http2FrameBuilder fb;
+ fb.Append(fields);
+ Http2FrameHeader header(fb.size(), Http2FrameType::PING,
+ RandFlags() | Http2FrameFlag::FLAG_ACK,
+ RandStreamId());
+ set_frame_header(header);
+ FrameParts expected(header);
+ expected.opt_ping = fields;
+ EXPECT_TRUE(DecodePayloadAndValidateSeveralWays(fb.buffer(), expected));
+ }
+}
+
+} // namespace
+} // namespace test
+} // namespace net
diff --git a/chromium/net/http2/decoder/payload_decoders/priority_payload_decoder.cc b/chromium/net/http2/decoder/payload_decoders/priority_payload_decoder.cc
new file mode 100644
index 00000000000..51ae80b9808
--- /dev/null
+++ b/chromium/net/http2/decoder/payload_decoders/priority_payload_decoder.cc
@@ -0,0 +1,64 @@
+// Copyright 2016 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.
+
+#include "net/http2/decoder/payload_decoders/priority_payload_decoder.h"
+
+#include "base/logging.h"
+#include "net/http2/decoder/decode_buffer.h"
+#include "net/http2/decoder/http2_frame_decoder_listener.h"
+#include "net/http2/http2_constants.h"
+#include "net/http2/http2_structures.h"
+
+namespace net {
+
+DecodeStatus PriorityPayloadDecoder::StartDecodingPayload(
+ FrameDecoderState* state,
+ DecodeBuffer* db) {
+ DVLOG(2) << "PriorityPayloadDecoder::StartDecodingPayload: "
+ << state->frame_header();
+ DCHECK_EQ(Http2FrameType::PRIORITY, state->frame_header().type);
+ DCHECK_LE(db->Remaining(), state->frame_header().payload_length);
+ // PRIORITY frames have no flags.
+ DCHECK_EQ(0, state->frame_header().flags);
+ state->InitializeRemainders();
+ return HandleStatus(
+ state, state->StartDecodingStructureInPayload(&priority_fields_, db));
+}
+
+DecodeStatus PriorityPayloadDecoder::ResumeDecodingPayload(
+ FrameDecoderState* state,
+ DecodeBuffer* db) {
+ DVLOG(2) << "PriorityPayloadDecoder::ResumeDecodingPayload"
+ << " remaining_payload=" << state->remaining_payload()
+ << " db->Remaining=" << db->Remaining();
+ DCHECK_EQ(Http2FrameType::PRIORITY, state->frame_header().type);
+ DCHECK_LE(db->Remaining(), state->frame_header().payload_length);
+ return HandleStatus(
+ state, state->ResumeDecodingStructureInPayload(&priority_fields_, db));
+}
+
+DecodeStatus PriorityPayloadDecoder::HandleStatus(FrameDecoderState* state,
+ DecodeStatus status) {
+ if (status == DecodeStatus::kDecodeDone) {
+ if (state->remaining_payload() == 0) {
+ state->listener()->OnPriorityFrame(state->frame_header(),
+ priority_fields_);
+ return DecodeStatus::kDecodeDone;
+ }
+ // Payload is too long.
+ return state->ReportFrameSizeError();
+ }
+ // Not done decoding the structure. Either we've got more payload to decode,
+ // or we've run out because the payload is too short, in which case
+ // OnFrameSizeError will have already been called.
+ DCHECK(
+ (status == DecodeStatus::kDecodeInProgress &&
+ state->remaining_payload() > 0) ||
+ (status == DecodeStatus::kDecodeError && state->remaining_payload() == 0))
+ << "\n status=" << status
+ << "; remaining_payload=" << state->remaining_payload();
+ return status;
+}
+
+} // namespace net
diff --git a/chromium/net/http2/decoder/payload_decoders/priority_payload_decoder.h b/chromium/net/http2/decoder/payload_decoders/priority_payload_decoder.h
new file mode 100644
index 00000000000..d41a404b8df
--- /dev/null
+++ b/chromium/net/http2/decoder/payload_decoders/priority_payload_decoder.h
@@ -0,0 +1,44 @@
+// Copyright 2016 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.
+
+#ifndef NET_HTTP2_DECODER_PAYLOAD_DECODERS_PRIORITY_PAYLOAD_DECODER_H_
+#define NET_HTTP2_DECODER_PAYLOAD_DECODERS_PRIORITY_PAYLOAD_DECODER_H_
+
+// Decodes the payload of a PRIORITY frame.
+
+#include "net/base/net_export.h"
+#include "net/http2/decoder/decode_buffer.h"
+#include "net/http2/decoder/decode_status.h"
+#include "net/http2/decoder/frame_decoder_state.h"
+#include "net/http2/http2_structures.h"
+
+namespace net {
+namespace test {
+class PriorityPayloadDecoderPeer;
+} // namespace test
+
+class NET_EXPORT_PRIVATE PriorityPayloadDecoder {
+ public:
+ // Starts the decoding of a PRIORITY frame's payload, and completes it if
+ // the entire payload is in the provided decode buffer.
+ DecodeStatus StartDecodingPayload(FrameDecoderState* state, DecodeBuffer* db);
+
+ // Resumes decoding a PRIORITY frame that has been split across decode
+ // buffers.
+ DecodeStatus ResumeDecodingPayload(FrameDecoderState* state,
+ DecodeBuffer* db);
+
+ private:
+ friend class test::PriorityPayloadDecoderPeer;
+
+ // Determines whether to report the PRIORITY to the listener, wait for more
+ // input, or to report a Frame Size Error.
+ DecodeStatus HandleStatus(FrameDecoderState* state, DecodeStatus status);
+
+ Http2PriorityFields priority_fields_;
+};
+
+} // namespace net
+
+#endif // NET_HTTP2_DECODER_PAYLOAD_DECODERS_PRIORITY_PAYLOAD_DECODER_H_
diff --git a/chromium/net/http2/decoder/payload_decoders/priority_payload_decoder_test.cc b/chromium/net/http2/decoder/payload_decoders/priority_payload_decoder_test.cc
new file mode 100644
index 00000000000..d40b07c8dd3
--- /dev/null
+++ b/chromium/net/http2/decoder/payload_decoders/priority_payload_decoder_test.cc
@@ -0,0 +1,95 @@
+// Copyright 2016 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.
+
+#include "net/http2/decoder/payload_decoders/priority_payload_decoder.h"
+
+#include <stddef.h>
+
+#include "base/logging.h"
+#include "net/http2/decoder/frame_parts.h"
+#include "net/http2/decoder/frame_parts_collector.h"
+#include "net/http2/decoder/http2_frame_decoder_listener.h"
+#include "net/http2/decoder/payload_decoders/payload_decoder_base_test_util.h"
+#include "net/http2/http2_constants.h"
+#include "net/http2/http2_structures_test_util.h"
+#include "net/http2/tools/http2_frame_builder.h"
+#include "net/http2/tools/http2_random.h"
+#include "net/http2/tools/random_decoder_test.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace net {
+namespace test {
+
+class PriorityPayloadDecoderPeer {
+ public:
+ static constexpr Http2FrameType FrameType() {
+ return Http2FrameType::PRIORITY;
+ }
+
+ // Returns the mask of flags that affect the decoding of the payload (i.e.
+ // flags that that indicate the presence of certain fields or padding).
+ static constexpr uint8_t FlagsAffectingPayloadDecoding() { return 0; }
+
+ static void Randomize(PriorityPayloadDecoder* p, RandomBase* rng) {
+ VLOG(1) << "PriorityPayloadDecoderPeer::Randomize";
+ test::Randomize(&p->priority_fields_, rng);
+ }
+};
+
+namespace {
+
+struct Listener : public FramePartsCollector {
+ void OnPriorityFrame(const Http2FrameHeader& header,
+ const Http2PriorityFields& priority_fields) override {
+ VLOG(1) << "OnPriority: " << header << "; " << priority_fields;
+ StartAndEndFrame(header)->OnPriorityFrame(header, priority_fields);
+ }
+
+ void OnFrameSizeError(const Http2FrameHeader& header) override {
+ VLOG(1) << "OnFrameSizeError: " << header;
+ FrameError(header)->OnFrameSizeError(header);
+ }
+};
+
+class PriorityPayloadDecoderTest
+ : public AbstractPayloadDecoderTest<PriorityPayloadDecoder,
+ PriorityPayloadDecoderPeer,
+ Listener> {
+ protected:
+ Http2PriorityFields RandPriorityFields() {
+ Http2PriorityFields fields;
+ test::Randomize(&fields, RandomPtr());
+ return fields;
+ }
+};
+
+// Confirm we get an error if the payload is not the correct size to hold
+// exactly one Http2PriorityFields.
+TEST_F(PriorityPayloadDecoderTest, WrongSize) {
+ auto approve_size = [](size_t size) {
+ return size != Http2PriorityFields::EncodedSize();
+ };
+ Http2FrameBuilder fb;
+ fb.Append(RandPriorityFields());
+ fb.Append(RandPriorityFields());
+ EXPECT_TRUE(VerifyDetectsFrameSizeError(0, fb.buffer(), approve_size));
+}
+
+TEST_F(PriorityPayloadDecoderTest, VariousPayloads) {
+ for (int n = 0; n < 100; ++n) {
+ Http2PriorityFields fields = RandPriorityFields();
+ Http2FrameBuilder fb;
+ fb.Append(fields);
+ Http2FrameHeader header(fb.size(), Http2FrameType::PRIORITY, RandFlags(),
+ RandStreamId());
+ set_frame_header(header);
+ FrameParts expected(header);
+ expected.opt_priority = fields;
+ EXPECT_TRUE(DecodePayloadAndValidateSeveralWays(fb.buffer(), expected));
+ }
+}
+
+} // namespace
+} // namespace test
+} // namespace net
diff --git a/chromium/net/http2/decoder/payload_decoders/push_promise_payload_decoder.cc b/chromium/net/http2/decoder/payload_decoders/push_promise_payload_decoder.cc
new file mode 100644
index 00000000000..f160d1eee20
--- /dev/null
+++ b/chromium/net/http2/decoder/payload_decoders/push_promise_payload_decoder.cc
@@ -0,0 +1,172 @@
+// Copyright 2016 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.
+
+#include "net/http2/decoder/payload_decoders/push_promise_payload_decoder.h"
+
+#include <stddef.h>
+
+#include "base/logging.h"
+#include "base/macros.h"
+#include "net/http2/decoder/decode_buffer.h"
+#include "net/http2/decoder/http2_frame_decoder_listener.h"
+#include "net/http2/http2_constants.h"
+#include "net/http2/http2_structures.h"
+#include "net/http2/tools/http2_bug_tracker.h"
+
+namespace net {
+
+std::ostream& operator<<(std::ostream& out,
+ PushPromisePayloadDecoder::PayloadState v) {
+ switch (v) {
+ case PushPromisePayloadDecoder::PayloadState::kReadPadLength:
+ return out << "kReadPadLength";
+ case PushPromisePayloadDecoder::PayloadState::
+ kStartDecodingPushPromiseFields:
+ return out << "kStartDecodingPushPromiseFields";
+ case PushPromisePayloadDecoder::PayloadState::kReadPayload:
+ return out << "kReadPayload";
+ case PushPromisePayloadDecoder::PayloadState::kSkipPadding:
+ return out << "kSkipPadding";
+ case PushPromisePayloadDecoder::PayloadState::
+ kResumeDecodingPushPromiseFields:
+ return out << "kResumeDecodingPushPromiseFields";
+ }
+ return out << static_cast<int>(v);
+}
+
+DecodeStatus PushPromisePayloadDecoder::StartDecodingPayload(
+ FrameDecoderState* state,
+ DecodeBuffer* db) {
+ const Http2FrameHeader& frame_header = state->frame_header();
+ const uint32_t total_length = frame_header.payload_length;
+
+ DVLOG(2) << "PushPromisePayloadDecoder::StartDecodingPayload: "
+ << frame_header;
+
+ DCHECK_EQ(Http2FrameType::PUSH_PROMISE, frame_header.type);
+ DCHECK_LE(db->Remaining(), total_length);
+ DCHECK_EQ(
+ 0, frame_header.flags &
+ ~(Http2FrameFlag::FLAG_END_HEADERS | Http2FrameFlag::FLAG_PADDED));
+
+ if (!frame_header.IsPadded()) {
+ // If it turns out that PUSH_PROMISE frames without padding are sufficiently
+ // common, and that they are usually short enough that they fit entirely
+ // into one DecodeBuffer, we can detect that here and implement a special
+ // case, avoiding the state machine in ResumeDecodingPayload.
+ payload_state_ = PayloadState::kStartDecodingPushPromiseFields;
+ } else {
+ payload_state_ = PayloadState::kReadPadLength;
+ }
+ state->InitializeRemainders();
+ return ResumeDecodingPayload(state, db);
+}
+
+DecodeStatus PushPromisePayloadDecoder::ResumeDecodingPayload(
+ FrameDecoderState* state,
+ DecodeBuffer* db) {
+ DVLOG(2) << "UnknownPayloadDecoder::ResumeDecodingPayload"
+ << " remaining_payload=" << state->remaining_payload()
+ << " db->Remaining=" << db->Remaining();
+
+ const Http2FrameHeader& frame_header = state->frame_header();
+ DCHECK_EQ(Http2FrameType::PUSH_PROMISE, frame_header.type);
+ DCHECK_LE(state->remaining_payload(), frame_header.payload_length);
+ DCHECK_LE(db->Remaining(), frame_header.payload_length);
+
+ DecodeStatus status;
+ while (true) {
+ DVLOG(2)
+ << "PushPromisePayloadDecoder::ResumeDecodingPayload payload_state_="
+ << payload_state_;
+ switch (payload_state_) {
+ case PayloadState::kReadPadLength:
+ DCHECK_EQ(state->remaining_payload(), frame_header.payload_length);
+ // ReadPadLength handles the OnPadLength callback, and updating the
+ // remaining_payload and remaining_padding fields. If the amount of
+ // padding is too large to fit in the frame's payload, ReadPadLength
+ // instead calls OnPaddingTooLong and returns kDecodeError.
+ // Suppress the call to OnPadLength because we haven't yet called
+ // OnPushPromiseStart, which needs to wait until we've decoded the
+ // Promised Stream ID.
+ status = state->ReadPadLength(db, /*report_pad_length*/ false);
+ if (status != DecodeStatus::kDecodeDone) {
+ payload_state_ = PayloadState::kReadPadLength;
+ return status;
+ }
+ // FALLTHROUGH_INTENDED
+
+ case PayloadState::kStartDecodingPushPromiseFields:
+ status =
+ state->StartDecodingStructureInPayload(&push_promise_fields_, db);
+ if (status != DecodeStatus::kDecodeDone) {
+ payload_state_ = PayloadState::kResumeDecodingPushPromiseFields;
+ return status;
+ }
+ // Finished decoding the Promised Stream ID. Can now tell the listener
+ // that we're starting to decode a PUSH_PROMISE frame.
+ ReportPushPromise(state);
+ // FALLTHROUGH_INTENDED
+
+ case PayloadState::kReadPayload:
+ DCHECK_LT(state->remaining_payload(), frame_header.payload_length);
+ DCHECK_LE(state->remaining_payload(),
+ frame_header.payload_length -
+ Http2PushPromiseFields::EncodedSize());
+ DCHECK_LE(
+ state->remaining_payload(),
+ frame_header.payload_length -
+ Http2PushPromiseFields::EncodedSize() -
+ (frame_header.IsPadded() ? (1 + state->remaining_padding())
+ : 0));
+ {
+ size_t avail = state->AvailablePayload(db);
+ state->listener()->OnHpackFragment(db->cursor(), avail);
+ db->AdvanceCursor(avail);
+ state->ConsumePayload(avail);
+ }
+ if (state->remaining_payload() > 0) {
+ payload_state_ = PayloadState::kReadPayload;
+ return DecodeStatus::kDecodeInProgress;
+ }
+ // FALLTHROUGH_INTENDED
+
+ case PayloadState::kSkipPadding:
+ // SkipPadding handles the OnPadding callback.
+ if (state->SkipPadding(db)) {
+ state->listener()->OnPushPromiseEnd();
+ return DecodeStatus::kDecodeDone;
+ }
+ payload_state_ = PayloadState::kSkipPadding;
+ return DecodeStatus::kDecodeInProgress;
+
+ case PayloadState::kResumeDecodingPushPromiseFields:
+ status =
+ state->ResumeDecodingStructureInPayload(&push_promise_fields_, db);
+ if (status == DecodeStatus::kDecodeDone) {
+ // Finished decoding the Promised Stream ID. Can now tell the listener
+ // that we're starting to decode a PUSH_PROMISE frame.
+ ReportPushPromise(state);
+ payload_state_ = PayloadState::kReadPayload;
+ continue;
+ }
+ payload_state_ = PayloadState::kResumeDecodingPushPromiseFields;
+ return status;
+ }
+ HTTP2_BUG << "PayloadState: " << payload_state_;
+ }
+}
+
+void PushPromisePayloadDecoder::ReportPushPromise(FrameDecoderState* state) {
+ const Http2FrameHeader& frame_header = state->frame_header();
+ if (frame_header.IsPadded()) {
+ state->listener()->OnPushPromiseStart(frame_header, push_promise_fields_,
+ 1 + state->remaining_padding());
+ } else {
+ state->listener()->OnPushPromiseStart(frame_header, push_promise_fields_,
+ 0);
+ }
+}
+
+} // namespace net
diff --git a/chromium/net/http2/decoder/payload_decoders/push_promise_payload_decoder.h b/chromium/net/http2/decoder/payload_decoders/push_promise_payload_decoder.h
new file mode 100644
index 00000000000..fe6c52327dd
--- /dev/null
+++ b/chromium/net/http2/decoder/payload_decoders/push_promise_payload_decoder.h
@@ -0,0 +1,66 @@
+// Copyright 2016 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.
+
+#ifndef NET_HTTP2_DECODER_PAYLOAD_DECODERS_PUSH_PROMISE_PAYLOAD_DECODER_H_
+#define NET_HTTP2_DECODER_PAYLOAD_DECODERS_PUSH_PROMISE_PAYLOAD_DECODER_H_
+
+// Decodes the payload of a PUSH_PROMISE frame.
+
+#include "net/base/net_export.h"
+#include "net/http2/decoder/decode_buffer.h"
+#include "net/http2/decoder/decode_status.h"
+#include "net/http2/decoder/frame_decoder_state.h"
+#include "net/http2/http2_structures.h"
+
+namespace net {
+namespace test {
+class PushPromisePayloadDecoderPeer;
+} // namespace test
+
+class NET_EXPORT_PRIVATE PushPromisePayloadDecoder {
+ public:
+ // States during decoding of a PUSH_PROMISE frame.
+ enum class PayloadState {
+ // The frame is padded and we need to read the PAD_LENGTH field (1 byte).
+ kReadPadLength,
+
+ // Ready to start decoding the fixed size fields of the PUSH_PROMISE
+ // frame into push_promise_fields_.
+ kStartDecodingPushPromiseFields,
+
+ // The decoder has already called OnPushPromiseStart, and is now reporting
+ // the HPACK block fragment to the listener's OnHpackFragment method.
+ kReadPayload,
+
+ // The decoder has finished with the HPACK block fragment, and is now
+ // ready to skip the trailing padding, if the frame has any.
+ kSkipPadding,
+
+ // The fixed size fields weren't all available when the decoder first tried
+ // to decode them (state kStartDecodingPushPromiseFields); this state
+ // resumes the decoding when ResumeDecodingPayload is called later.
+ kResumeDecodingPushPromiseFields,
+ };
+
+ // Starts the decoding of a PUSH_PROMISE frame's payload, and completes it if
+ // the entire payload is in the provided decode buffer.
+ DecodeStatus StartDecodingPayload(FrameDecoderState* state, DecodeBuffer* db);
+
+ // Resumes decoding a PUSH_PROMISE frame's payload that has been split across
+ // decode buffers.
+ DecodeStatus ResumeDecodingPayload(FrameDecoderState* state,
+ DecodeBuffer* db);
+
+ private:
+ friend class test::PushPromisePayloadDecoderPeer;
+
+ void ReportPushPromise(FrameDecoderState* state);
+
+ PayloadState payload_state_;
+ Http2PushPromiseFields push_promise_fields_;
+};
+
+} // namespace net
+
+#endif // NET_HTTP2_DECODER_PAYLOAD_DECODERS_PUSH_PROMISE_PAYLOAD_DECODER_H_
diff --git a/chromium/net/http2/decoder/payload_decoders/push_promise_payload_decoder_test.cc b/chromium/net/http2/decoder/payload_decoders/push_promise_payload_decoder_test.cc
new file mode 100644
index 00000000000..f7d8383650b
--- /dev/null
+++ b/chromium/net/http2/decoder/payload_decoders/push_promise_payload_decoder_test.cc
@@ -0,0 +1,147 @@
+// Copyright 2016 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.
+
+#include "net/http2/decoder/payload_decoders/push_promise_payload_decoder.h"
+
+#include <stddef.h>
+
+#include <string>
+
+#include "base/logging.h"
+#include "net/http2/decoder/frame_parts.h"
+#include "net/http2/decoder/frame_parts_collector.h"
+#include "net/http2/decoder/http2_frame_decoder_listener.h"
+#include "net/http2/decoder/payload_decoders/payload_decoder_base_test_util.h"
+#include "net/http2/http2_constants.h"
+#include "net/http2/http2_structures_test_util.h"
+#include "net/http2/tools/http2_frame_builder.h"
+#include "net/http2/tools/http2_random.h"
+#include "net/http2/tools/random_decoder_test.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+using std::string;
+
+namespace net {
+namespace test {
+
+// Provides friend access to an instance of the payload decoder, and also
+// provides info to aid in testing.
+class PushPromisePayloadDecoderPeer {
+ public:
+ static constexpr Http2FrameType FrameType() {
+ return Http2FrameType::PUSH_PROMISE;
+ }
+
+ // Returns the mask of flags that affect the decoding of the payload (i.e.
+ // flags that that indicate the presence of certain fields or padding).
+ static constexpr uint8_t FlagsAffectingPayloadDecoding() {
+ return Http2FrameFlag::FLAG_PADDED;
+ }
+
+ static void Randomize(PushPromisePayloadDecoder* p, RandomBase* rng) {
+ VLOG(1) << "PushPromisePayloadDecoderPeer::Randomize";
+ CorruptEnum(&p->payload_state_, rng);
+ test::Randomize(&p->push_promise_fields_, rng);
+ }
+};
+
+namespace {
+
+// Listener listens for only those methods expected by the payload decoder
+// under test, and forwards them onto the FrameParts instance for the current
+// frame.
+struct Listener : public FramePartsCollector {
+ void OnPushPromiseStart(const Http2FrameHeader& header,
+ const Http2PushPromiseFields& promise,
+ size_t total_padding_length) override {
+ VLOG(1) << "OnPushPromiseStart header: " << header
+ << " promise: " << promise
+ << " total_padding_length: " << total_padding_length;
+ EXPECT_EQ(Http2FrameType::PUSH_PROMISE, header.type);
+ StartFrame(header)->OnPushPromiseStart(header, promise,
+ total_padding_length);
+ }
+
+ void OnHpackFragment(const char* data, size_t len) override {
+ VLOG(1) << "OnHpackFragment: len=" << len;
+ CurrentFrame()->OnHpackFragment(data, len);
+ }
+
+ void OnPushPromiseEnd() override {
+ VLOG(1) << "OnPushPromiseEnd";
+ EndFrame()->OnPushPromiseEnd();
+ }
+
+ void OnPadding(const char* padding, size_t skipped_length) override {
+ VLOG(1) << "OnPadding: " << skipped_length;
+ CurrentFrame()->OnPadding(padding, skipped_length);
+ }
+
+ void OnPaddingTooLong(const Http2FrameHeader& header,
+ size_t missing_length) override {
+ VLOG(1) << "OnPaddingTooLong: " << header
+ << "; missing_length: " << missing_length;
+ FrameError(header)->OnPaddingTooLong(header, missing_length);
+ }
+
+ void OnFrameSizeError(const Http2FrameHeader& header) override {
+ VLOG(1) << "OnFrameSizeError: " << header;
+ FrameError(header)->OnFrameSizeError(header);
+ }
+};
+
+class PushPromisePayloadDecoderTest
+ : public AbstractPaddablePayloadDecoderTest<PushPromisePayloadDecoder,
+ PushPromisePayloadDecoderPeer,
+ Listener> {
+};
+
+INSTANTIATE_TEST_CASE_P(VariousPadLengths,
+ PushPromisePayloadDecoderTest,
+ ::testing::Values(0, 1, 2, 3, 4, 254, 255, 256));
+
+// Payload contains the required Http2PushPromiseFields, followed by some
+// (fake) HPACK payload.
+TEST_P(PushPromisePayloadDecoderTest, VariousHpackPayloadSizes) {
+ for (size_t hpack_size : {0, 1, 2, 3, 255, 256, 1024}) {
+ LOG(INFO) << "########### hpack_size = " << hpack_size << " ###########";
+ Reset();
+ string hpack_payload = Random().RandString(hpack_size);
+ Http2PushPromiseFields push_promise{RandStreamId()};
+ frame_builder_.Append(push_promise);
+ frame_builder_.Append(hpack_payload);
+ MaybeAppendTrailingPadding();
+ Http2FrameHeader frame_header(frame_builder_.size(),
+ Http2FrameType::PUSH_PROMISE, RandFlags(),
+ RandStreamId());
+ set_frame_header(frame_header);
+ FrameParts expected(frame_header, hpack_payload, total_pad_length_);
+ expected.opt_push_promise = push_promise;
+ EXPECT_TRUE(
+ DecodePayloadAndValidateSeveralWays(frame_builder_.buffer(), expected));
+ }
+}
+
+// Confirm we get an error if the payload is not long enough for the required
+// portion of the payload, regardless of the amount of (valid) padding.
+TEST_P(PushPromisePayloadDecoderTest, Truncated) {
+ auto approve_size = [](size_t size) {
+ return size != Http2PushPromiseFields::EncodedSize();
+ };
+ Http2PushPromiseFields push_promise{RandStreamId()};
+ Http2FrameBuilder fb;
+ fb.Append(push_promise);
+ EXPECT_TRUE(VerifyDetectsMultipleFrameSizeErrors(0, fb.buffer(), approve_size,
+ total_pad_length_));
+}
+
+// Confirm we get an error if the PADDED flag is set but the payload is not
+// long enough to hold even the Pad Length amount of padding.
+TEST_P(PushPromisePayloadDecoderTest, PaddingTooLong) {
+ EXPECT_TRUE(VerifyDetectsPaddingTooLong());
+}
+
+} // namespace
+} // namespace test
+} // namespace net
diff --git a/chromium/net/http2/decoder/payload_decoders/rst_stream_payload_decoder.cc b/chromium/net/http2/decoder/payload_decoders/rst_stream_payload_decoder.cc
new file mode 100644
index 00000000000..e9d86fb7385
--- /dev/null
+++ b/chromium/net/http2/decoder/payload_decoders/rst_stream_payload_decoder.cc
@@ -0,0 +1,66 @@
+// Copyright 2016 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.
+
+#include "net/http2/decoder/payload_decoders/rst_stream_payload_decoder.h"
+
+#include "base/logging.h"
+#include "net/http2/decoder/decode_buffer.h"
+#include "net/http2/decoder/http2_frame_decoder_listener.h"
+#include "net/http2/http2_constants.h"
+#include "net/http2/http2_structures.h"
+
+namespace net {
+
+DecodeStatus RstStreamPayloadDecoder::StartDecodingPayload(
+ FrameDecoderState* state,
+ DecodeBuffer* db) {
+ DVLOG(2) << "RstStreamPayloadDecoder::StartDecodingPayload: "
+ << state->frame_header();
+ DCHECK_EQ(Http2FrameType::RST_STREAM, state->frame_header().type);
+ DCHECK_LE(db->Remaining(), state->frame_header().payload_length);
+ // RST_STREAM has no flags.
+ DCHECK_EQ(0, state->frame_header().flags);
+ state->InitializeRemainders();
+ return HandleStatus(
+ state, state->StartDecodingStructureInPayload(&rst_stream_fields_, db));
+}
+
+DecodeStatus RstStreamPayloadDecoder::ResumeDecodingPayload(
+ FrameDecoderState* state,
+ DecodeBuffer* db) {
+ DVLOG(2) << "RstStreamPayloadDecoder::ResumeDecodingPayload"
+ << " remaining_payload=" << state->remaining_payload()
+ << " db->Remaining=" << db->Remaining();
+ DCHECK_EQ(Http2FrameType::RST_STREAM, state->frame_header().type);
+ DCHECK_LE(db->Remaining(), state->frame_header().payload_length);
+ return HandleStatus(
+ state, state->ResumeDecodingStructureInPayload(&rst_stream_fields_, db));
+}
+
+DecodeStatus RstStreamPayloadDecoder::HandleStatus(FrameDecoderState* state,
+ DecodeStatus status) {
+ DVLOG(2) << "HandleStatus: status=" << status
+ << "; remaining_payload=" << state->remaining_payload();
+ if (status == DecodeStatus::kDecodeDone) {
+ if (state->remaining_payload() == 0) {
+ state->listener()->OnRstStream(state->frame_header(),
+ rst_stream_fields_.error_code);
+ return DecodeStatus::kDecodeDone;
+ }
+ // Payload is too long.
+ return state->ReportFrameSizeError();
+ }
+ // Not done decoding the structure. Either we've got more payload to decode,
+ // or we've run out because the payload is too short, in which case
+ // OnFrameSizeError will have already been called by the FrameDecoderState.
+ DCHECK(
+ (status == DecodeStatus::kDecodeInProgress &&
+ state->remaining_payload() > 0) ||
+ (status == DecodeStatus::kDecodeError && state->remaining_payload() == 0))
+ << "\n status=" << status
+ << "; remaining_payload=" << state->remaining_payload();
+ return status;
+}
+
+} // namespace net
diff --git a/chromium/net/http2/decoder/payload_decoders/rst_stream_payload_decoder.h b/chromium/net/http2/decoder/payload_decoders/rst_stream_payload_decoder.h
new file mode 100644
index 00000000000..cdfd65875d3
--- /dev/null
+++ b/chromium/net/http2/decoder/payload_decoders/rst_stream_payload_decoder.h
@@ -0,0 +1,42 @@
+// Copyright 2016 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.
+
+#ifndef NET_HTTP2_DECODER_PAYLOAD_DECODERS_RST_STREAM_PAYLOAD_DECODER_H_
+#define NET_HTTP2_DECODER_PAYLOAD_DECODERS_RST_STREAM_PAYLOAD_DECODER_H_
+
+// Decodes the payload of a RST_STREAM frame.
+
+#include "net/base/net_export.h"
+#include "net/http2/decoder/decode_buffer.h"
+#include "net/http2/decoder/decode_status.h"
+#include "net/http2/decoder/frame_decoder_state.h"
+#include "net/http2/http2_structures.h"
+
+namespace net {
+namespace test {
+class RstStreamPayloadDecoderPeer;
+} // namespace test
+
+class NET_EXPORT_PRIVATE RstStreamPayloadDecoder {
+ public:
+ // Starts the decoding of a RST_STREAM frame's payload, and completes it if
+ // the entire payload is in the provided decode buffer.
+ DecodeStatus StartDecodingPayload(FrameDecoderState* state, DecodeBuffer* db);
+
+ // Resumes decoding a RST_STREAM frame's payload that has been split across
+ // decode buffers.
+ DecodeStatus ResumeDecodingPayload(FrameDecoderState* state,
+ DecodeBuffer* db);
+
+ private:
+ friend class test::RstStreamPayloadDecoderPeer;
+
+ DecodeStatus HandleStatus(FrameDecoderState* state, DecodeStatus status);
+
+ Http2RstStreamFields rst_stream_fields_;
+};
+
+} // namespace net
+
+#endif // NET_HTTP2_DECODER_PAYLOAD_DECODERS_RST_STREAM_PAYLOAD_DECODER_H_
diff --git a/chromium/net/http2/decoder/payload_decoders/rst_stream_payload_decoder_test.cc b/chromium/net/http2/decoder/payload_decoders/rst_stream_payload_decoder_test.cc
new file mode 100644
index 00000000000..88bd80366dc
--- /dev/null
+++ b/chromium/net/http2/decoder/payload_decoders/rst_stream_payload_decoder_test.cc
@@ -0,0 +1,97 @@
+// Copyright 2016 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.
+
+#include "net/http2/decoder/payload_decoders/rst_stream_payload_decoder.h"
+
+#include <stddef.h>
+
+#include "base/logging.h"
+#include "net/http2/decoder/frame_parts.h"
+#include "net/http2/decoder/frame_parts_collector.h"
+#include "net/http2/decoder/http2_frame_decoder_listener.h"
+#include "net/http2/decoder/payload_decoders/payload_decoder_base_test_util.h"
+#include "net/http2/http2_constants.h"
+#include "net/http2/http2_constants_test_util.h"
+#include "net/http2/http2_structures_test_util.h"
+#include "net/http2/tools/http2_frame_builder.h"
+#include "net/http2/tools/http2_random.h"
+#include "net/http2/tools/random_decoder_test.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace net {
+namespace test {
+
+class RstStreamPayloadDecoderPeer {
+ public:
+ static constexpr Http2FrameType FrameType() {
+ return Http2FrameType::RST_STREAM;
+ }
+
+ // Returns the mask of flags that affect the decoding of the payload (i.e.
+ // flags that that indicate the presence of certain fields or padding).
+ static constexpr uint8_t FlagsAffectingPayloadDecoding() { return 0; }
+
+ static void Randomize(RstStreamPayloadDecoder* p, RandomBase* rng) {
+ VLOG(1) << "RstStreamPayloadDecoderPeer::Randomize";
+ test::Randomize(&p->rst_stream_fields_, rng);
+ }
+};
+
+namespace {
+
+struct Listener : public FramePartsCollector {
+ void OnRstStream(const Http2FrameHeader& header,
+ Http2ErrorCode error_code) override {
+ VLOG(1) << "OnRstStream: " << header << "; error_code=" << error_code;
+ StartAndEndFrame(header)->OnRstStream(header, error_code);
+ }
+
+ void OnFrameSizeError(const Http2FrameHeader& header) override {
+ VLOG(1) << "OnFrameSizeError: " << header;
+ FrameError(header)->OnFrameSizeError(header);
+ }
+};
+
+class RstStreamPayloadDecoderTest
+ : public AbstractPayloadDecoderTest<RstStreamPayloadDecoder,
+ RstStreamPayloadDecoderPeer,
+ Listener> {
+ protected:
+ Http2RstStreamFields RandRstStreamFields() {
+ Http2RstStreamFields fields;
+ test::Randomize(&fields, RandomPtr());
+ return fields;
+ }
+};
+
+// Confirm we get an error if the payload is not the correct size to hold
+// exactly one Http2RstStreamFields.
+TEST_F(RstStreamPayloadDecoderTest, WrongSize) {
+ auto approve_size = [](size_t size) {
+ return size != Http2RstStreamFields::EncodedSize();
+ };
+ Http2FrameBuilder fb;
+ fb.Append(RandRstStreamFields());
+ fb.Append(RandRstStreamFields());
+ fb.Append(RandRstStreamFields());
+ EXPECT_TRUE(VerifyDetectsFrameSizeError(0, fb.buffer(), approve_size));
+}
+
+TEST_F(RstStreamPayloadDecoderTest, AllErrors) {
+ for (auto error_code : AllHttp2ErrorCodes()) {
+ Http2RstStreamFields fields{error_code};
+ Http2FrameBuilder fb;
+ fb.Append(fields);
+ Http2FrameHeader header(fb.size(), Http2FrameType::RST_STREAM, RandFlags(),
+ RandStreamId());
+ set_frame_header(header);
+ FrameParts expected(header);
+ expected.opt_rst_stream_error_code = error_code;
+ EXPECT_TRUE(DecodePayloadAndValidateSeveralWays(fb.buffer(), expected));
+ }
+}
+
+} // namespace
+} // namespace test
+} // namespace net
diff --git a/chromium/net/http2/decoder/payload_decoders/settings_payload_decoder.cc b/chromium/net/http2/decoder/payload_decoders/settings_payload_decoder.cc
new file mode 100644
index 00000000000..f8cc52cb486
--- /dev/null
+++ b/chromium/net/http2/decoder/payload_decoders/settings_payload_decoder.cc
@@ -0,0 +1,97 @@
+// Copyright 2016 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.
+
+#include "net/http2/decoder/payload_decoders/settings_payload_decoder.h"
+
+#include "base/logging.h"
+#include "net/http2/decoder/decode_buffer.h"
+#include "net/http2/decoder/http2_frame_decoder_listener.h"
+#include "net/http2/http2_constants.h"
+#include "net/http2/http2_structures.h"
+
+namespace net {
+
+DecodeStatus SettingsPayloadDecoder::StartDecodingPayload(
+ FrameDecoderState* state,
+ DecodeBuffer* db) {
+ const Http2FrameHeader& frame_header = state->frame_header();
+ const uint32_t total_length = frame_header.payload_length;
+
+ DVLOG(2) << "SettingsPayloadDecoder::StartDecodingPayload: " << frame_header;
+ DCHECK_EQ(Http2FrameType::SETTINGS, frame_header.type);
+ DCHECK_LE(db->Remaining(), total_length);
+ DCHECK_EQ(0, frame_header.flags & ~(Http2FrameFlag::FLAG_ACK));
+
+ if (frame_header.IsAck()) {
+ if (total_length == 0) {
+ state->listener()->OnSettingsAck(frame_header);
+ return DecodeStatus::kDecodeDone;
+ } else {
+ state->InitializeRemainders();
+ return state->ReportFrameSizeError();
+ }
+ } else {
+ state->InitializeRemainders();
+ state->listener()->OnSettingsStart(frame_header);
+ return StartDecodingSettings(state, db);
+ }
+}
+
+DecodeStatus SettingsPayloadDecoder::ResumeDecodingPayload(
+ FrameDecoderState* state,
+ DecodeBuffer* db) {
+ DVLOG(2) << "SettingsPayloadDecoder::ResumeDecodingPayload"
+ << " remaining_payload=" << state->remaining_payload()
+ << " db->Remaining=" << db->Remaining();
+ DCHECK_EQ(Http2FrameType::SETTINGS, state->frame_header().type);
+ DCHECK_LE(db->Remaining(), state->frame_header().payload_length);
+
+ DecodeStatus status =
+ state->ResumeDecodingStructureInPayload(&setting_fields_, db);
+ if (status == DecodeStatus::kDecodeDone) {
+ state->listener()->OnSetting(setting_fields_);
+ return StartDecodingSettings(state, db);
+ }
+ return HandleNotDone(state, db, status);
+}
+
+DecodeStatus SettingsPayloadDecoder::StartDecodingSettings(
+ FrameDecoderState* state,
+ DecodeBuffer* db) {
+ DVLOG(2) << "SettingsPayloadDecoder::StartDecodingSettings"
+ << " remaining_payload=" << state->remaining_payload()
+ << " db->Remaining=" << db->Remaining();
+ while (state->remaining_payload() > 0) {
+ DecodeStatus status =
+ state->StartDecodingStructureInPayload(&setting_fields_, db);
+ if (status == DecodeStatus::kDecodeDone) {
+ state->listener()->OnSetting(setting_fields_);
+ continue;
+ }
+ return HandleNotDone(state, db, status);
+ }
+ DVLOG(2) << "LEAVING SettingsPayloadDecoder::StartDecodingSettings"
+ << "\n\tdb->Remaining=" << db->Remaining()
+ << "\n\t remaining_payload=" << state->remaining_payload();
+ state->listener()->OnSettingsEnd();
+ return DecodeStatus::kDecodeDone;
+}
+
+DecodeStatus SettingsPayloadDecoder::HandleNotDone(FrameDecoderState* state,
+ DecodeBuffer* db,
+ DecodeStatus status) {
+ // Not done decoding the structure. Either we've got more payload to decode,
+ // or we've run out because the payload is too short, in which case
+ // OnFrameSizeError will have already been called.
+ DCHECK(
+ (status == DecodeStatus::kDecodeInProgress &&
+ state->remaining_payload() > 0) ||
+ (status == DecodeStatus::kDecodeError && state->remaining_payload() == 0))
+ << "\n status=" << status
+ << "; remaining_payload=" << state->remaining_payload()
+ << "; db->Remaining=" << db->Remaining();
+ return status;
+}
+
+} // namespace net
diff --git a/chromium/net/http2/decoder/payload_decoders/settings_payload_decoder.h b/chromium/net/http2/decoder/payload_decoders/settings_payload_decoder.h
new file mode 100644
index 00000000000..40d3c367aba
--- /dev/null
+++ b/chromium/net/http2/decoder/payload_decoders/settings_payload_decoder.h
@@ -0,0 +1,54 @@
+// Copyright 2016 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.
+
+#ifndef NET_HTTP2_DECODER_PAYLOAD_DECODERS_SETTINGS_PAYLOAD_DECODER_H_
+#define NET_HTTP2_DECODER_PAYLOAD_DECODERS_SETTINGS_PAYLOAD_DECODER_H_
+
+// Decodes the payload of a SETTINGS frame; for the RFC, see:
+// http://httpwg.org/specs/rfc7540.html#SETTINGS
+
+#include "net/base/net_export.h"
+#include "net/http2/decoder/decode_buffer.h"
+#include "net/http2/decoder/decode_status.h"
+#include "net/http2/decoder/frame_decoder_state.h"
+#include "net/http2/http2_structures.h"
+
+namespace net {
+namespace test {
+class SettingsPayloadDecoderPeer;
+} // namespace test
+
+class NET_EXPORT_PRIVATE SettingsPayloadDecoder {
+ public:
+ // Starts the decoding of a SETTINGS frame's payload, and completes it if
+ // the entire payload is in the provided decode buffer.
+ DecodeStatus StartDecodingPayload(FrameDecoderState* state, DecodeBuffer* db);
+
+ // Resumes decoding a SETTINGS frame that has been split across decode
+ // buffers.
+ DecodeStatus ResumeDecodingPayload(FrameDecoderState* state,
+ DecodeBuffer* db);
+
+ private:
+ friend class test::SettingsPayloadDecoderPeer;
+
+ // Decodes as many settings as are available in the decode buffer, starting at
+ // the first byte of one setting; if a single setting is split across buffers,
+ // ResumeDecodingPayload will handle starting from where the previous call
+ // left off, and then will call StartDecodingSettings.
+ DecodeStatus StartDecodingSettings(FrameDecoderState* state,
+ DecodeBuffer* db);
+
+ // Decoding a single SETTING returned a status other than kDecodeDone; this
+ // method just brings together the DCHECKs to reduce duplication.
+ DecodeStatus HandleNotDone(FrameDecoderState* state,
+ DecodeBuffer* db,
+ DecodeStatus status);
+
+ Http2SettingFields setting_fields_;
+};
+
+} // namespace net
+
+#endif // NET_HTTP2_DECODER_PAYLOAD_DECODERS_SETTINGS_PAYLOAD_DECODER_H_
diff --git a/chromium/net/http2/decoder/payload_decoders/settings_payload_decoder_test.cc b/chromium/net/http2/decoder/payload_decoders/settings_payload_decoder_test.cc
new file mode 100644
index 00000000000..4d26e1bf656
--- /dev/null
+++ b/chromium/net/http2/decoder/payload_decoders/settings_payload_decoder_test.cc
@@ -0,0 +1,165 @@
+// Copyright 2016 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.
+
+#include "net/http2/decoder/payload_decoders/settings_payload_decoder.h"
+
+#include <stddef.h>
+
+#include <vector>
+
+#include "base/logging.h"
+#include "net/http2/decoder/frame_parts.h"
+#include "net/http2/decoder/frame_parts_collector.h"
+#include "net/http2/decoder/http2_frame_decoder_listener.h"
+#include "net/http2/decoder/payload_decoders/payload_decoder_base_test_util.h"
+#include "net/http2/http2_constants.h"
+#include "net/http2/http2_constants_test_util.h"
+#include "net/http2/http2_structures_test_util.h"
+#include "net/http2/tools/http2_frame_builder.h"
+#include "net/http2/tools/http2_random.h"
+#include "net/http2/tools/random_decoder_test.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace net {
+namespace test {
+
+class SettingsPayloadDecoderPeer {
+ public:
+ static constexpr Http2FrameType FrameType() {
+ return Http2FrameType::SETTINGS;
+ }
+
+ // Returns the mask of flags that affect the decoding of the payload (i.e.
+ // flags that that indicate the presence of certain fields or padding).
+ static constexpr uint8_t FlagsAffectingPayloadDecoding() {
+ return Http2FrameFlag::FLAG_ACK;
+ }
+
+ static void Randomize(SettingsPayloadDecoder* p, RandomBase* rng) {
+ VLOG(1) << "SettingsPayloadDecoderPeer::Randomize";
+ test::Randomize(&p->setting_fields_, rng);
+ }
+};
+
+namespace {
+
+struct Listener : public FramePartsCollector {
+ void OnSettingsStart(const Http2FrameHeader& header) override {
+ VLOG(1) << "OnSettingsStart: " << header;
+ EXPECT_EQ(Http2FrameType::SETTINGS, header.type) << header;
+ EXPECT_EQ(Http2FrameFlag(), header.flags) << header;
+ StartFrame(header)->OnSettingsStart(header);
+ }
+
+ void OnSetting(const Http2SettingFields& setting_fields) override {
+ VLOG(1) << "Http2SettingFields: setting_fields=" << setting_fields;
+ CurrentFrame()->OnSetting(setting_fields);
+ }
+
+ void OnSettingsEnd() override {
+ VLOG(1) << "OnSettingsEnd";
+ EndFrame()->OnSettingsEnd();
+ }
+
+ void OnSettingsAck(const Http2FrameHeader& header) override {
+ VLOG(1) << "OnSettingsAck: " << header;
+ StartAndEndFrame(header)->OnSettingsAck(header);
+ }
+
+ void OnFrameSizeError(const Http2FrameHeader& header) override {
+ VLOG(1) << "OnFrameSizeError: " << header;
+ FrameError(header)->OnFrameSizeError(header);
+ }
+};
+
+class SettingsPayloadDecoderTest
+ : public AbstractPayloadDecoderTest<SettingsPayloadDecoder,
+ SettingsPayloadDecoderPeer,
+ Listener> {
+ protected:
+ Http2SettingFields RandSettingsFields() {
+ Http2SettingFields fields;
+ test::Randomize(&fields, RandomPtr());
+ return fields;
+ }
+};
+
+// Confirm we get an error if the SETTINGS payload is not the correct size
+// to hold exactly zero or more whole Http2SettingFields.
+TEST_F(SettingsPayloadDecoderTest, SettingsWrongSize) {
+ auto approve_size = [](size_t size) {
+ // Should get an error if size is not an integral multiple of the size
+ // of one setting.
+ return 0 != (size % Http2SettingFields::EncodedSize());
+ };
+ Http2FrameBuilder fb;
+ fb.Append(RandSettingsFields());
+ fb.Append(RandSettingsFields());
+ fb.Append(RandSettingsFields());
+ EXPECT_TRUE(VerifyDetectsFrameSizeError(0, fb.buffer(), approve_size));
+}
+
+// Confirm we get an error if the SETTINGS ACK payload is not empty.
+TEST_F(SettingsPayloadDecoderTest, SettingsAkcWrongSize) {
+ auto approve_size = [](size_t size) { return size != 0; };
+ Http2FrameBuilder fb;
+ fb.Append(RandSettingsFields());
+ fb.Append(RandSettingsFields());
+ fb.Append(RandSettingsFields());
+ EXPECT_TRUE(VerifyDetectsFrameSizeError(Http2FrameFlag::FLAG_ACK, fb.buffer(),
+ approve_size));
+}
+
+// SETTINGS must have stream_id==0, but the payload decoder doesn't check that.
+TEST_F(SettingsPayloadDecoderTest, SettingsAck) {
+ for (int stream_id = 0; stream_id < 3; ++stream_id) {
+ Http2FrameHeader header(0, Http2FrameType::SETTINGS,
+ RandFlags() | Http2FrameFlag::FLAG_ACK, stream_id);
+ set_frame_header(header);
+ FrameParts expected(header);
+ EXPECT_TRUE(DecodePayloadAndValidateSeveralWays("", expected));
+ }
+}
+
+// Try several values of each known SETTINGS parameter.
+TEST_F(SettingsPayloadDecoderTest, OneRealSetting) {
+ std::vector<uint32_t> values = {0, 1, 0xffffffff, Random().Rand32()};
+ for (auto param : AllHttp2SettingsParameters()) {
+ for (uint32_t value : values) {
+ Http2SettingFields fields(param, value);
+ Http2FrameBuilder fb;
+ fb.Append(fields);
+ Http2FrameHeader header(fb.size(), Http2FrameType::SETTINGS, RandFlags(),
+ RandStreamId());
+ set_frame_header(header);
+ FrameParts expected(header);
+ expected.settings.push_back(fields);
+ EXPECT_TRUE(DecodePayloadAndValidateSeveralWays(fb.buffer(), expected));
+ }
+ }
+}
+
+// Decode a SETTINGS frame with lots of fields.
+TEST_F(SettingsPayloadDecoderTest, ManySettings) {
+ const uint32_t num_settings = 100;
+ const uint32_t size = Http2SettingFields::EncodedSize() * num_settings;
+ Http2FrameHeader header(size, Http2FrameType::SETTINGS,
+ RandFlags(), // & ~Http2FrameFlag::FLAG_ACK,
+ RandStreamId());
+ set_frame_header(header);
+ FrameParts expected(header);
+ Http2FrameBuilder fb;
+ for (size_t n = 0; n < num_settings; ++n) {
+ Http2SettingFields fields(static_cast<Http2SettingsParameter>(n),
+ Random().Rand32());
+ fb.Append(fields);
+ expected.settings.push_back(fields);
+ }
+ ASSERT_EQ(size, fb.size());
+ EXPECT_TRUE(DecodePayloadAndValidateSeveralWays(fb.buffer(), expected));
+}
+
+} // namespace
+} // namespace test
+} // namespace net
diff --git a/chromium/net/http2/decoder/payload_decoders/unknown_payload_decoder.cc b/chromium/net/http2/decoder/payload_decoders/unknown_payload_decoder.cc
new file mode 100644
index 00000000000..ec020c1617a
--- /dev/null
+++ b/chromium/net/http2/decoder/payload_decoders/unknown_payload_decoder.cc
@@ -0,0 +1,55 @@
+// Copyright 2016 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.
+
+#include "net/http2/decoder/payload_decoders/unknown_payload_decoder.h"
+
+#include <stddef.h>
+
+#include "base/logging.h"
+#include "net/http2/decoder/decode_buffer.h"
+#include "net/http2/decoder/http2_frame_decoder_listener.h"
+#include "net/http2/http2_constants.h"
+#include "net/http2/http2_structures.h"
+
+namespace net {
+
+DecodeStatus UnknownPayloadDecoder::StartDecodingPayload(
+ FrameDecoderState* state,
+ DecodeBuffer* db) {
+ const Http2FrameHeader& frame_header = state->frame_header();
+
+ DVLOG(2) << "UnknownPayloadDecoder::StartDecodingPayload: " << frame_header;
+ DCHECK(!IsSupportedHttp2FrameType(frame_header.type)) << frame_header;
+ DCHECK_LE(db->Remaining(), frame_header.payload_length);
+
+ state->InitializeRemainders();
+ state->listener()->OnUnknownStart(frame_header);
+ return ResumeDecodingPayload(state, db);
+}
+
+DecodeStatus UnknownPayloadDecoder::ResumeDecodingPayload(
+ FrameDecoderState* state,
+ DecodeBuffer* db) {
+ DVLOG(2) << "UnknownPayloadDecoder::ResumeDecodingPayload "
+ << "remaining_payload=" << state->remaining_payload()
+ << "; db->Remaining=" << db->Remaining();
+ DCHECK(!IsSupportedHttp2FrameType(state->frame_header().type))
+ << state->frame_header();
+ DCHECK_LE(state->remaining_payload(), state->frame_header().payload_length);
+ DCHECK_LE(db->Remaining(), state->remaining_payload());
+
+ size_t avail = db->Remaining();
+ if (avail > 0) {
+ state->listener()->OnUnknownPayload(db->cursor(), avail);
+ db->AdvanceCursor(avail);
+ state->ConsumePayload(avail);
+ }
+ if (state->remaining_payload() == 0) {
+ state->listener()->OnUnknownEnd();
+ return DecodeStatus::kDecodeDone;
+ }
+ return DecodeStatus::kDecodeInProgress;
+}
+
+} // namespace net
diff --git a/chromium/net/http2/decoder/payload_decoders/unknown_payload_decoder.h b/chromium/net/http2/decoder/payload_decoders/unknown_payload_decoder.h
new file mode 100644
index 00000000000..26a1ee25988
--- /dev/null
+++ b/chromium/net/http2/decoder/payload_decoders/unknown_payload_decoder.h
@@ -0,0 +1,33 @@
+// Copyright 2016 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.
+
+#ifndef NET_HTTP2_DECODER_PAYLOAD_DECODERS_UNKNOWN_PAYLOAD_DECODER_H_
+#define NET_HTTP2_DECODER_PAYLOAD_DECODERS_UNKNOWN_PAYLOAD_DECODER_H_
+
+// Decodes the payload of a frame whose type unknown. According to the HTTP/2
+// specification (http://httpwg.org/specs/rfc7540.html#FrameHeader):
+// Implementations MUST ignore and discard any frame that has
+// a type that is unknown.
+
+#include "net/base/net_export.h"
+#include "net/http2/decoder/decode_buffer.h"
+#include "net/http2/decoder/decode_status.h"
+#include "net/http2/decoder/frame_decoder_state.h"
+
+namespace net {
+
+class NET_EXPORT_PRIVATE UnknownPayloadDecoder {
+ public:
+ // Starts decoding a payload of unknown type; just passes it to the listener.
+ DecodeStatus StartDecodingPayload(FrameDecoderState* state, DecodeBuffer* db);
+
+ // Resumes decoding a payload of unknown type that has been split across
+ // decode buffers.
+ DecodeStatus ResumeDecodingPayload(FrameDecoderState* state,
+ DecodeBuffer* db);
+};
+
+} // namespace net
+
+#endif // NET_HTTP2_DECODER_PAYLOAD_DECODERS_UNKNOWN_PAYLOAD_DECODER_H_
diff --git a/chromium/net/http2/decoder/payload_decoders/unknown_payload_decoder_test.cc b/chromium/net/http2/decoder/payload_decoders/unknown_payload_decoder_test.cc
new file mode 100644
index 00000000000..302cec47cc9
--- /dev/null
+++ b/chromium/net/http2/decoder/payload_decoders/unknown_payload_decoder_test.cc
@@ -0,0 +1,108 @@
+// Copyright 2016 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.
+
+#include "net/http2/decoder/payload_decoders/unknown_payload_decoder.h"
+
+#include <stddef.h>
+
+#include <string>
+#include <type_traits>
+
+#include "base/logging.h"
+#include "net/http2/decoder/frame_parts.h"
+#include "net/http2/decoder/frame_parts_collector.h"
+#include "net/http2/decoder/http2_frame_decoder_listener.h"
+#include "net/http2/decoder/payload_decoders/payload_decoder_base_test_util.h"
+#include "net/http2/http2_constants.h"
+#include "net/http2/http2_structures.h"
+#include "net/http2/tools/http2_random.h"
+#include "net/http2/tools/random_decoder_test.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+using std::string;
+
+namespace net {
+namespace test {
+namespace {
+Http2FrameType g_unknown_frame_type;
+} // namespace
+
+// Provides friend access to an instance of the payload decoder, and also
+// provides info to aid in testing.
+class UnknownPayloadDecoderPeer {
+ public:
+ static Http2FrameType FrameType() { return g_unknown_frame_type; }
+
+ // Returns the mask of flags that affect the decoding of the payload (i.e.
+ // flags that that indicate the presence of certain fields or padding).
+ static constexpr uint8_t FlagsAffectingPayloadDecoding() { return 0; }
+
+ static void Randomize(UnknownPayloadDecoder* p, RandomBase* rng) {
+ // UnknownPayloadDecoder has no fields, so there is nothing to randomize.
+ static_assert(std::is_empty<UnknownPayloadDecoder>::value,
+ "Need to randomize fields of UnknownPayloadDecoder");
+ }
+};
+
+namespace {
+
+struct Listener : public FramePartsCollector {
+ void OnUnknownStart(const Http2FrameHeader& header) override {
+ VLOG(1) << "OnUnknownStart: " << header;
+ StartFrame(header)->OnUnknownStart(header);
+ }
+
+ void OnUnknownPayload(const char* data, size_t len) override {
+ VLOG(1) << "OnUnknownPayload: len=" << len;
+ CurrentFrame()->OnUnknownPayload(data, len);
+ }
+
+ void OnUnknownEnd() override {
+ VLOG(1) << "OnUnknownEnd";
+ EndFrame()->OnUnknownEnd();
+ }
+};
+
+constexpr bool SupportedFrameType = false;
+
+class UnknownPayloadDecoderTest
+ : public AbstractPayloadDecoderTest<UnknownPayloadDecoder,
+ UnknownPayloadDecoderPeer,
+ Listener,
+ SupportedFrameType>,
+ public ::testing::WithParamInterface<uint32_t> {
+ protected:
+ UnknownPayloadDecoderTest() : length_(GetParam()) {
+ VLOG(1) << "################ length_=" << length_ << " ################";
+
+ // Each test case will choose a random frame type that isn't supported.
+ do {
+ g_unknown_frame_type = static_cast<Http2FrameType>(Random().Rand8());
+ } while (IsSupportedHttp2FrameType(g_unknown_frame_type));
+ }
+
+ const uint32_t length_;
+};
+
+INSTANTIATE_TEST_CASE_P(VariousLengths,
+ UnknownPayloadDecoderTest,
+ ::testing::Values(0, 1, 2, 3, 255, 256));
+
+TEST_P(UnknownPayloadDecoderTest, ValidLength) {
+ string unknown_payload = Random().RandString(length_);
+ Http2FrameHeader frame_header(length_, g_unknown_frame_type, Random().Rand8(),
+ RandStreamId());
+ set_frame_header(frame_header);
+ FrameParts expected(frame_header, unknown_payload);
+ EXPECT_TRUE(DecodePayloadAndValidateSeveralWays(unknown_payload, expected));
+ // TODO(jamessynge): Check here (and in other such tests) that the fast
+ // and slow decode counts are both non-zero. Perhaps also add some kind of
+ // test for the listener having been called. That could simply be a test
+ // that there is a single collected FrameParts instance, and that it matches
+ // expected.
+}
+
+} // namespace
+} // namespace test
+} // namespace net
diff --git a/chromium/net/http2/decoder/payload_decoders/window_update_payload_decoder.cc b/chromium/net/http2/decoder/payload_decoders/window_update_payload_decoder.cc
new file mode 100644
index 00000000000..bc1e54ce1bb
--- /dev/null
+++ b/chromium/net/http2/decoder/payload_decoders/window_update_payload_decoder.cc
@@ -0,0 +1,82 @@
+// Copyright 2016 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.
+
+#include "net/http2/decoder/payload_decoders/window_update_payload_decoder.h"
+
+#include "base/logging.h"
+#include "net/http2/decoder/decode_buffer.h"
+#include "net/http2/decoder/decode_http2_structures.h"
+#include "net/http2/decoder/http2_frame_decoder_listener.h"
+#include "net/http2/http2_constants.h"
+#include "net/http2/http2_structures.h"
+
+namespace net {
+
+DecodeStatus WindowUpdatePayloadDecoder::StartDecodingPayload(
+ FrameDecoderState* state,
+ DecodeBuffer* db) {
+ const Http2FrameHeader& frame_header = state->frame_header();
+ const uint32_t total_length = frame_header.payload_length;
+
+ DVLOG(2) << "WindowUpdatePayloadDecoder::StartDecodingPayload: "
+ << frame_header;
+
+ DCHECK_EQ(Http2FrameType::WINDOW_UPDATE, frame_header.type);
+ DCHECK_LE(db->Remaining(), total_length);
+
+ // WINDOW_UPDATE frames have no flags.
+ DCHECK_EQ(0, frame_header.flags);
+
+ // Special case for when the payload is the correct size and entirely in
+ // the buffer.
+ if (db->Remaining() == Http2WindowUpdateFields::EncodedSize() &&
+ total_length == Http2WindowUpdateFields::EncodedSize()) {
+ DoDecode(&window_update_fields_, db);
+ state->listener()->OnWindowUpdate(
+ frame_header, window_update_fields_.window_size_increment);
+ return DecodeStatus::kDecodeDone;
+ }
+ state->InitializeRemainders();
+ return HandleStatus(state, state->StartDecodingStructureInPayload(
+ &window_update_fields_, db));
+}
+
+DecodeStatus WindowUpdatePayloadDecoder::ResumeDecodingPayload(
+ FrameDecoderState* state,
+ DecodeBuffer* db) {
+ DVLOG(2) << "ResumeDecodingPayload: remaining_payload="
+ << state->remaining_payload()
+ << "; db->Remaining=" << db->Remaining();
+ DCHECK_EQ(Http2FrameType::WINDOW_UPDATE, state->frame_header().type);
+ DCHECK_LE(db->Remaining(), state->frame_header().payload_length);
+ return HandleStatus(state, state->ResumeDecodingStructureInPayload(
+ &window_update_fields_, db));
+}
+
+DecodeStatus WindowUpdatePayloadDecoder::HandleStatus(FrameDecoderState* state,
+ DecodeStatus status) {
+ DVLOG(2) << "HandleStatus: status=" << status
+ << "; remaining_payload=" << state->remaining_payload();
+ if (status == DecodeStatus::kDecodeDone) {
+ if (state->remaining_payload() == 0) {
+ state->listener()->OnWindowUpdate(
+ state->frame_header(), window_update_fields_.window_size_increment);
+ return DecodeStatus::kDecodeDone;
+ }
+ // Payload is too long.
+ return state->ReportFrameSizeError();
+ }
+ // Not done decoding the structure. Either we've got more payload to decode,
+ // or we've run out because the payload is too short, in which case
+ // OnFrameSizeError will have already been called.
+ DCHECK(
+ (status == DecodeStatus::kDecodeInProgress &&
+ state->remaining_payload() > 0) ||
+ (status == DecodeStatus::kDecodeError && state->remaining_payload() == 0))
+ << "\n status=" << status
+ << "; remaining_payload=" << state->remaining_payload();
+ return status;
+}
+
+} // namespace net
diff --git a/chromium/net/http2/decoder/payload_decoders/window_update_payload_decoder.h b/chromium/net/http2/decoder/payload_decoders/window_update_payload_decoder.h
new file mode 100644
index 00000000000..57643613664
--- /dev/null
+++ b/chromium/net/http2/decoder/payload_decoders/window_update_payload_decoder.h
@@ -0,0 +1,42 @@
+// Copyright 2016 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.
+
+#ifndef NET_HTTP2_DECODER_PAYLOAD_DECODERS_WINDOW_UPDATE_PAYLOAD_DECODER_H_
+#define NET_HTTP2_DECODER_PAYLOAD_DECODERS_WINDOW_UPDATE_PAYLOAD_DECODER_H_
+
+// Decodes the payload of a WINDOW_UPDATE frame.
+
+#include "net/base/net_export.h"
+#include "net/http2/decoder/decode_buffer.h"
+#include "net/http2/decoder/decode_status.h"
+#include "net/http2/decoder/frame_decoder_state.h"
+#include "net/http2/http2_structures.h"
+
+namespace net {
+namespace test {
+class WindowUpdatePayloadDecoderPeer;
+} // namespace test
+
+class NET_EXPORT_PRIVATE WindowUpdatePayloadDecoder {
+ public:
+ // Starts decoding a WINDOW_UPDATE frame's payload, and completes it if
+ // the entire payload is in the provided decode buffer.
+ DecodeStatus StartDecodingPayload(FrameDecoderState* state, DecodeBuffer* db);
+
+ // Resumes decoding a WINDOW_UPDATE frame's payload that has been split across
+ // decode buffers.
+ DecodeStatus ResumeDecodingPayload(FrameDecoderState* state,
+ DecodeBuffer* db);
+
+ private:
+ friend class test::WindowUpdatePayloadDecoderPeer;
+
+ DecodeStatus HandleStatus(FrameDecoderState* state, DecodeStatus status);
+
+ Http2WindowUpdateFields window_update_fields_;
+};
+
+} // namespace net
+
+#endif // NET_HTTP2_DECODER_PAYLOAD_DECODERS_WINDOW_UPDATE_PAYLOAD_DECODER_H_
diff --git a/chromium/net/http2/decoder/payload_decoders/window_update_payload_decoder_test.cc b/chromium/net/http2/decoder/payload_decoders/window_update_payload_decoder_test.cc
new file mode 100644
index 00000000000..5914b81669c
--- /dev/null
+++ b/chromium/net/http2/decoder/payload_decoders/window_update_payload_decoder_test.cc
@@ -0,0 +1,102 @@
+// Copyright 2016 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.
+
+#include "net/http2/decoder/payload_decoders/window_update_payload_decoder.h"
+
+#include <stddef.h>
+
+#include "base/logging.h"
+#include "net/http2/decoder/frame_parts.h"
+#include "net/http2/decoder/frame_parts_collector.h"
+#include "net/http2/decoder/http2_frame_decoder_listener.h"
+#include "net/http2/decoder/payload_decoders/payload_decoder_base_test_util.h"
+#include "net/http2/http2_constants.h"
+#include "net/http2/http2_structures_test_util.h"
+#include "net/http2/tools/http2_frame_builder.h"
+#include "net/http2/tools/http2_random.h"
+#include "net/http2/tools/random_decoder_test.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace net {
+namespace test {
+
+class WindowUpdatePayloadDecoderPeer {
+ public:
+ static constexpr Http2FrameType FrameType() {
+ return Http2FrameType::WINDOW_UPDATE;
+ }
+
+ // Returns the mask of flags that affect the decoding of the payload (i.e.
+ // flags that that indicate the presence of certain fields or padding).
+ static constexpr uint8_t FlagsAffectingPayloadDecoding() { return 0; }
+
+ static void Randomize(WindowUpdatePayloadDecoder* p, RandomBase* rng) {
+ test::Randomize(&p->window_update_fields_, rng);
+ VLOG(1) << "WindowUpdatePayloadDecoderPeer::Randomize "
+ << "window_update_fields_: " << p->window_update_fields_;
+ }
+};
+
+namespace {
+
+struct Listener : public FramePartsCollector {
+ void OnWindowUpdate(const Http2FrameHeader& header,
+ uint32_t window_size_increment) override {
+ VLOG(1) << "OnWindowUpdate: " << header
+ << "; window_size_increment=" << window_size_increment;
+ EXPECT_EQ(Http2FrameType::WINDOW_UPDATE, header.type);
+ StartAndEndFrame(header)->OnWindowUpdate(header, window_size_increment);
+ }
+
+ void OnFrameSizeError(const Http2FrameHeader& header) override {
+ VLOG(1) << "OnFrameSizeError: " << header;
+ FrameError(header)->OnFrameSizeError(header);
+ }
+};
+
+class WindowUpdatePayloadDecoderTest
+ : public AbstractPayloadDecoderTest<WindowUpdatePayloadDecoder,
+ WindowUpdatePayloadDecoderPeer,
+ Listener> {
+
+ protected:
+ Http2WindowUpdateFields RandWindowUpdateFields() {
+ Http2WindowUpdateFields fields;
+ test::Randomize(&fields, RandomPtr());
+ VLOG(3) << "RandWindowUpdateFields: " << fields;
+ return fields;
+ }
+};
+
+// Confirm we get an error if the payload is not the correct size to hold
+// exactly one Http2WindowUpdateFields.
+TEST_F(WindowUpdatePayloadDecoderTest, WrongSize) {
+ auto approve_size = [](size_t size) {
+ return size != Http2WindowUpdateFields::EncodedSize();
+ };
+ Http2FrameBuilder fb;
+ fb.Append(RandWindowUpdateFields());
+ fb.Append(RandWindowUpdateFields());
+ fb.Append(RandWindowUpdateFields());
+ EXPECT_TRUE(VerifyDetectsFrameSizeError(0, fb.buffer(), approve_size));
+}
+
+TEST_F(WindowUpdatePayloadDecoderTest, VariousPayloads) {
+ for (int n = 0; n < 100; ++n) {
+ uint32_t stream_id = n == 0 ? 0 : RandStreamId();
+ Http2WindowUpdateFields fields = RandWindowUpdateFields();
+ Http2FrameBuilder fb;
+ fb.Append(fields);
+ Http2FrameHeader header(fb.size(), Http2FrameType::WINDOW_UPDATE,
+ RandFlags(), stream_id);
+ set_frame_header(header);
+ FrameParts expected(header);
+ expected.opt_window_update_increment = fields.window_size_increment;
+ EXPECT_TRUE(DecodePayloadAndValidateSeveralWays(fb.buffer(), expected));
+ }
+}
+
+} // namespace
+} // namespace test
+} // namespace net
diff --git a/chromium/net/http2/hpack/decoder/README.md b/chromium/net/http2/hpack/decoder/README.md
new file mode 100644
index 00000000000..77990848e51
--- /dev/null
+++ b/chromium/net/http2/hpack/decoder/README.md
@@ -0,0 +1,50 @@
+Copyright 2017 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.
+
+## gfe/http2/hpack/decoder
+
+These are the most popular C++ files defined in this directory.
+
+* [hpack_entry_decoder_listener.h]
+ (http://google3/gfe/http2/hpack/decoder/hpack_entry_decoder_listener.h) (1
+ imports): Defines HpackEntryDecoderListener, the base class of listeners
+ that HpackEntryDecoder calls.
+* [hpack_decoder_string_buffer.h]
+ (http://google3/gfe/http2/hpack/decoder/hpack_decoder_string_buffer.h) (1
+ imports): HpackDecoderStringBuffer helps an HPACK decoder to avoid copies of
+ a string literal (name or value) except when necessary (e.g.
+* [hpack_block_decoder.h]
+ (http://google3/gfe/http2/hpack/decoder/hpack_block_decoder.h) (1 imports):
+ HpackBlockDecoder decodes an entire HPACK block (or the available portion
+ thereof in the DecodeBuffer) into entries, but doesn't include HPACK static
+ or dynamic table support, so table indices remain indices at this level.
+* [hpack_varint_decoder.h]
+ (http://google3/gfe/http2/hpack/decoder/hpack_varint_decoder.h) (zero
+ imports): HpackVarintDecoder decodes HPACK variable length unsigned
+ integers.
+* [hpack_entry_collector.h]
+ (http://google3/gfe/http2/hpack/decoder/hpack_entry_collector.h) (zero
+ imports): HpackEntryCollector records calls to HpackEntryDecoderListener in
+ support of tests of HpackEntryDecoder, or which use it.
+* [hpack_string_collector.h]
+ (http://google3/gfe/http2/hpack/decoder/hpack_string_collector.h) (zero
+ imports): Supports tests of decoding HPACK strings.
+* [hpack_string_decoder.h]
+ (http://google3/gfe/http2/hpack/decoder/hpack_string_decoder.h) (zero
+ imports): HpackStringDecoder decodes strings encoded per the HPACK spec;
+ this does not mean decompressing Huffman encoded strings, just identifying
+ the length, encoding and contents for a listener.
+* [hpack_block_collector.h]
+ (http://google3/gfe/http2/hpack/decoder/hpack_block_collector.h) (zero
+ imports): HpackBlockCollector implements HpackEntryDecoderListener in order
+ to record the calls using HpackEntryCollector instances (one per HPACK
+ entry).
+* [hpack_entry_decoder.h]
+ (http://google3/gfe/http2/hpack/decoder/hpack_entry_decoder.h) (zero
+ imports): HpackEntryDecoder decodes a single HPACK entry (i.e.
+* [hpack_entry_type_decoder.h]
+ (http://google3/gfe/http2/hpack/decoder/hpack_entry_type_decoder.h) (zero
+ imports): Decodes the type of an HPACK entry, and the variable length
+ integer whose prefix is in the low-order bits of the same byte, "below" the
+ type bits.
diff --git a/chromium/net/http2/hpack/decoder/hpack_block_collector.cc b/chromium/net/http2/hpack/decoder/hpack_block_collector.cc
new file mode 100644
index 00000000000..94f58ee408a
--- /dev/null
+++ b/chromium/net/http2/hpack/decoder/hpack_block_collector.cc
@@ -0,0 +1,154 @@
+// Copyright 2016 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.
+
+#include "net/http2/hpack/decoder/hpack_block_collector.h"
+
+#include <algorithm>
+#include <memory>
+
+#include "base/logging.h"
+#include "net/http2/tools/failure.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+using ::testing::AssertionResult;
+using ::testing::AssertionSuccess;
+using std::string;
+
+using base::StringPiece;
+
+namespace net {
+namespace test {
+
+HpackBlockCollector::HpackBlockCollector() {}
+HpackBlockCollector::HpackBlockCollector(const HpackBlockCollector& other)
+ : pending_entry_(other.pending_entry_), entries_(other.entries_) {}
+HpackBlockCollector::~HpackBlockCollector() {}
+
+void HpackBlockCollector::OnIndexedHeader(size_t index) {
+ pending_entry_.OnIndexedHeader(index);
+ PushPendingEntry();
+}
+void HpackBlockCollector::OnDynamicTableSizeUpdate(size_t size) {
+ pending_entry_.OnDynamicTableSizeUpdate(size);
+ PushPendingEntry();
+}
+void HpackBlockCollector::OnStartLiteralHeader(HpackEntryType header_type,
+ size_t maybe_name_index) {
+ pending_entry_.OnStartLiteralHeader(header_type, maybe_name_index);
+}
+void HpackBlockCollector::OnNameStart(bool huffman_encoded, size_t len) {
+ pending_entry_.OnNameStart(huffman_encoded, len);
+}
+void HpackBlockCollector::OnNameData(const char* data, size_t len) {
+ pending_entry_.OnNameData(data, len);
+}
+void HpackBlockCollector::OnNameEnd() {
+ pending_entry_.OnNameEnd();
+}
+void HpackBlockCollector::OnValueStart(bool huffman_encoded, size_t len) {
+ pending_entry_.OnValueStart(huffman_encoded, len);
+}
+void HpackBlockCollector::OnValueData(const char* data, size_t len) {
+ pending_entry_.OnValueData(data, len);
+}
+void HpackBlockCollector::OnValueEnd() {
+ pending_entry_.OnValueEnd();
+ PushPendingEntry();
+}
+
+void HpackBlockCollector::PushPendingEntry() {
+ EXPECT_TRUE(pending_entry_.IsComplete());
+ DVLOG(2) << "PushPendingEntry: " << pending_entry_;
+ entries_.push_back(pending_entry_);
+ EXPECT_TRUE(entries_.back().IsComplete());
+ pending_entry_.Clear();
+}
+void HpackBlockCollector::Clear() {
+ pending_entry_.Clear();
+ entries_.clear();
+}
+
+void HpackBlockCollector::ExpectIndexedHeader(size_t index) {
+ entries_.push_back(
+ HpackEntryCollector(HpackEntryType::kIndexedHeader, index));
+}
+void HpackBlockCollector::ExpectDynamicTableSizeUpdate(size_t size) {
+ entries_.push_back(
+ HpackEntryCollector(HpackEntryType::kDynamicTableSizeUpdate, size));
+}
+void HpackBlockCollector::ExpectNameIndexAndLiteralValue(HpackEntryType type,
+ size_t index,
+ bool value_huffman,
+ const string& value) {
+ entries_.push_back(HpackEntryCollector(type, index, value_huffman, value));
+}
+void HpackBlockCollector::ExpectLiteralNameAndValue(HpackEntryType type,
+ bool name_huffman,
+ const string& name,
+ bool value_huffman,
+ const string& value) {
+ entries_.push_back(
+ HpackEntryCollector(type, name_huffman, name, value_huffman, value));
+}
+
+void HpackBlockCollector::ShuffleEntries(RandomBase* rng) {
+ std::random_shuffle(entries_.begin(), entries_.end());
+}
+
+void HpackBlockCollector::AppendToHpackBlockBuilder(
+ HpackBlockBuilder* hbb) const {
+ CHECK(IsNotPending());
+ for (const auto& entry : entries_) {
+ entry.AppendToHpackBlockBuilder(hbb);
+ }
+}
+
+AssertionResult HpackBlockCollector::ValidateSoleIndexedHeader(
+ size_t ndx) const {
+ VERIFY_TRUE(pending_entry_.IsClear());
+ VERIFY_EQ(1u, entries_.size());
+ VERIFY_TRUE(entries_.front().ValidateIndexedHeader(ndx));
+ return AssertionSuccess();
+}
+AssertionResult HpackBlockCollector::ValidateSoleLiteralValueHeader(
+ HpackEntryType expected_type,
+ size_t expected_index,
+ bool expected_value_huffman,
+ StringPiece expected_value) const {
+ VERIFY_TRUE(pending_entry_.IsClear());
+ VERIFY_EQ(1u, entries_.size());
+ VERIFY_TRUE(entries_.front().ValidateLiteralValueHeader(
+ expected_type, expected_index, expected_value_huffman, expected_value));
+ return AssertionSuccess();
+}
+AssertionResult HpackBlockCollector::ValidateSoleLiteralNameValueHeader(
+ HpackEntryType expected_type,
+ bool expected_name_huffman,
+ StringPiece expected_name,
+ bool expected_value_huffman,
+ StringPiece expected_value) const {
+ VERIFY_TRUE(pending_entry_.IsClear());
+ VERIFY_EQ(1u, entries_.size());
+ VERIFY_TRUE(entries_.front().ValidateLiteralNameValueHeader(
+ expected_type, expected_name_huffman, expected_name,
+ expected_value_huffman, expected_value));
+ return AssertionSuccess();
+}
+AssertionResult HpackBlockCollector::ValidateSoleDynamicTableSizeUpdate(
+ size_t size) const {
+ VERIFY_TRUE(pending_entry_.IsClear());
+ VERIFY_EQ(1u, entries_.size());
+ VERIFY_TRUE(entries_.front().ValidateDynamicTableSizeUpdate(size));
+ return AssertionSuccess();
+}
+
+AssertionResult HpackBlockCollector::VerifyEq(
+ const HpackBlockCollector& that) const {
+ VERIFY_EQ(pending_entry_, that.pending_entry_);
+ VERIFY_EQ(entries_, that.entries_);
+ return AssertionSuccess();
+}
+
+} // namespace test
+} // namespace net
diff --git a/chromium/net/http2/hpack/decoder/hpack_block_collector.h b/chromium/net/http2/hpack/decoder/hpack_block_collector.h
new file mode 100644
index 00000000000..2b283b9d53e
--- /dev/null
+++ b/chromium/net/http2/hpack/decoder/hpack_block_collector.h
@@ -0,0 +1,128 @@
+// Copyright 2016 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.
+
+#ifndef NET_HTTP2_HPACK_DECODER_HPACK_BLOCK_COLLECTOR_H_
+#define NET_HTTP2_HPACK_DECODER_HPACK_BLOCK_COLLECTOR_H_
+
+// HpackBlockCollector implements HpackEntryDecoderListener in order to record
+// the calls using HpackEntryCollector instances (one per HPACK entry). This
+// supports testing of HpackBlockDecoder, which decodes entire HPACK blocks.
+//
+// In addition to implementing the callback methods, HpackBlockCollector also
+// supports comparing two HpackBlockCollector instances (i.e. an expected and
+// an actual), or a sole HPACK entry against an expected value.
+
+#include <stddef.h>
+
+#include <string>
+#include <vector>
+
+#include "base/strings/string_piece.h"
+#include "net/http2/hpack/decoder/hpack_entry_collector.h"
+#include "net/http2/hpack/decoder/hpack_entry_decoder_listener.h"
+#include "net/http2/hpack/http2_hpack_constants.h"
+#include "net/http2/hpack/tools/hpack_block_builder.h"
+
+namespace net {
+namespace test {
+
+class RandomBase;
+
+class HpackBlockCollector : public HpackEntryDecoderListener {
+ public:
+ // Implementations of HpackEntryDecoderListener, forwarding to pending_entry_,
+ // an HpackEntryCollector for the "in-progress" HPACK entry. OnIndexedHeader
+ // and OnDynamicTableSizeUpdate are pending only for that one call, while
+ // OnStartLiteralHeader is followed by many calls, ending with OnValueEnd.
+ // Once all the calls for one HPACK entry have been received, PushPendingEntry
+ // is used to append the pending_entry_ entry to the collected entries_.
+ HpackBlockCollector();
+ HpackBlockCollector(const HpackBlockCollector& other);
+ ~HpackBlockCollector() override;
+ void OnIndexedHeader(size_t index) override;
+ void OnDynamicTableSizeUpdate(size_t size) override;
+ void OnStartLiteralHeader(HpackEntryType header_type,
+ size_t maybe_name_index) override;
+ void OnNameStart(bool huffman_encoded, size_t len) override;
+ void OnNameData(const char* data, size_t len) override;
+ void OnNameEnd() override;
+ void OnValueStart(bool huffman_encoded, size_t len) override;
+ void OnValueData(const char* data, size_t len) override;
+ void OnValueEnd() override;
+
+ // Methods for creating a set of expectations (i.e. HPACK entries to compare
+ // against those collected by another instance of HpackBlockCollector).
+
+ // Add an HPACK entry for an indexed header.
+ void ExpectIndexedHeader(size_t index);
+
+ // Add an HPACK entry for a dynamic table size update.
+ void ExpectDynamicTableSizeUpdate(size_t size);
+
+ // Add an HPACK entry for a header entry with an index for the name, and a
+ // literal value.
+ void ExpectNameIndexAndLiteralValue(HpackEntryType type,
+ size_t index,
+ bool value_huffman,
+ const std::string& value);
+
+ // Add an HPACK entry for a header entry with a literal name and value.
+ void ExpectLiteralNameAndValue(HpackEntryType type,
+ bool name_huffman,
+ const std::string& name,
+ bool value_huffman,
+ const std::string& value);
+
+ // Shuffle the entries, in support of generating an HPACK block of entries
+ // in some random order.
+ void ShuffleEntries(RandomBase* rng);
+
+ // Serialize entries_ to the HpackBlockBuilder.
+ void AppendToHpackBlockBuilder(HpackBlockBuilder* hbb) const;
+
+ // Return AssertionSuccess if there is just one entry, and it is an
+ // Indexed Header with the specified index.
+ ::testing::AssertionResult ValidateSoleIndexedHeader(size_t ndx) const;
+
+ // Return AssertionSuccess if there is just one entry, and it is a
+ // Dynamic Table Size Update with the specified size.
+ ::testing::AssertionResult ValidateSoleDynamicTableSizeUpdate(
+ size_t size) const;
+
+ // Return AssertionSuccess if there is just one entry, and it is a Header
+ // entry with an index for the name and a literal value.
+ ::testing::AssertionResult ValidateSoleLiteralValueHeader(
+ HpackEntryType expected_type,
+ size_t expected_index,
+ bool expected_value_huffman,
+ base::StringPiece expected_value) const;
+
+ // Return AssertionSuccess if there is just one entry, and it is a Header
+ // with a literal name and literal value.
+ ::testing::AssertionResult ValidateSoleLiteralNameValueHeader(
+ HpackEntryType expected_type,
+ bool expected_name_huffman,
+ base::StringPiece expected_name,
+ bool expected_value_huffman,
+ base::StringPiece expected_value) const;
+
+ bool IsNotPending() const { return pending_entry_.IsClear(); }
+ bool IsClear() const { return IsNotPending() && entries_.empty(); }
+ void Clear();
+
+ ::testing::AssertionResult VerifyEq(const HpackBlockCollector& that) const;
+
+ private:
+ // Push the value of pending_entry_ onto entries_, and clear pending_entry_.
+ // The pending_entry_ must be complete.
+ void PushPendingEntry();
+
+ HpackEntryCollector pending_entry_;
+ std::vector<HpackEntryCollector> entries_;
+};
+
+} // namespace test
+} // namespace net
+
+#endif // NET_HTTP2_HPACK_DECODER_HPACK_BLOCK_COLLECTOR_H_
diff --git a/chromium/net/http2/hpack/decoder/hpack_block_decoder.cc b/chromium/net/http2/hpack/decoder/hpack_block_decoder.cc
new file mode 100644
index 00000000000..29b68691b1b
--- /dev/null
+++ b/chromium/net/http2/hpack/decoder/hpack_block_decoder.cc
@@ -0,0 +1,65 @@
+// Copyright 2016 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.
+
+#include "net/http2/hpack/decoder/hpack_block_decoder.h"
+
+#include <stdint.h>
+
+#include <sstream>
+#include <string>
+
+#include "base/logging.h"
+
+namespace net {
+
+DecodeStatus HpackBlockDecoder::Decode(DecodeBuffer* db) {
+ if (!before_entry_) {
+ DVLOG(2) << "HpackBlockDecoder::Decode resume entry, db->Remaining="
+ << db->Remaining();
+ DecodeStatus status = entry_decoder_.Resume(db, listener_);
+ switch (status) {
+ case DecodeStatus::kDecodeDone:
+ before_entry_ = true;
+ break;
+ case DecodeStatus::kDecodeInProgress:
+ DCHECK_EQ(0u, db->Remaining());
+ return DecodeStatus::kDecodeInProgress;
+ case DecodeStatus::kDecodeError:
+ return DecodeStatus::kDecodeError;
+ }
+ }
+ DCHECK(before_entry_);
+ while (db->HasData()) {
+ DVLOG(2) << "HpackBlockDecoder::Decode start entry, db->Remaining="
+ << db->Remaining();
+ DecodeStatus status = entry_decoder_.Start(db, listener_);
+ switch (status) {
+ case DecodeStatus::kDecodeDone:
+ continue;
+ case DecodeStatus::kDecodeInProgress:
+ DCHECK_EQ(0u, db->Remaining());
+ before_entry_ = false;
+ return DecodeStatus::kDecodeInProgress;
+ case DecodeStatus::kDecodeError:
+ return DecodeStatus::kDecodeError;
+ }
+ DCHECK(false);
+ }
+ DCHECK(before_entry_);
+ return DecodeStatus::kDecodeDone;
+}
+
+std::string HpackBlockDecoder::DebugString() const {
+ std::stringstream ss;
+ ss << "HpackBlockDecoder(" << entry_decoder_.DebugString() << ", listener@"
+ << std::hex << reinterpret_cast<intptr_t>(listener_)
+ << (before_entry_ ? ", between entries)" : ", in an entry)");
+ return ss.str();
+}
+
+std::ostream& operator<<(std::ostream& out, const HpackBlockDecoder& v) {
+ return out << v.DebugString();
+}
+
+} // namespace net
diff --git a/chromium/net/http2/hpack/decoder/hpack_block_decoder.h b/chromium/net/http2/hpack/decoder/hpack_block_decoder.h
new file mode 100644
index 00000000000..18b882e6b4a
--- /dev/null
+++ b/chromium/net/http2/hpack/decoder/hpack_block_decoder.h
@@ -0,0 +1,73 @@
+// Copyright 2016 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.
+
+#ifndef NET_HTTP2_HPACK_DECODER_HPACK_BLOCK_DECODER_H_
+#define NET_HTTP2_HPACK_DECODER_HPACK_BLOCK_DECODER_H_
+
+// HpackBlockDecoder decodes an entire HPACK block (or the available portion
+// thereof in the DecodeBuffer) into entries, but doesn't include HPACK static
+// or dynamic table support, so table indices remain indices at this level.
+// Reports the entries to an HpackEntryDecoderListener.
+
+#include <string>
+
+#include "base/logging.h"
+#include "base/macros.h"
+#include "net/base/net_export.h"
+#include "net/http2/decoder/decode_buffer.h"
+#include "net/http2/decoder/decode_status.h"
+#include "net/http2/hpack/decoder/hpack_entry_decoder.h"
+#include "net/http2/hpack/decoder/hpack_entry_decoder_listener.h"
+
+namespace net {
+
+class NET_EXPORT_PRIVATE HpackBlockDecoder {
+ public:
+ explicit HpackBlockDecoder(HpackEntryDecoderListener* listener)
+ : listener_(listener) {
+ DCHECK_NE(listener_, nullptr);
+ }
+ ~HpackBlockDecoder() {}
+
+ // The listener may be changed at any time. The change takes effect on the
+ // next entry into the decode loop of the Decode() method below.
+ void set_listener(HpackEntryDecoderListener* listener) {
+ DCHECK_NE(nullptr, listener);
+ listener_ = listener;
+ }
+ HpackEntryDecoderListener* listener() { return listener_; }
+
+ // Prepares the decoder to start decoding a new HPACK block. Expected
+ // to be called from an implementation of Http2FrameDecoderListener's
+ // OnHeadersStart or OnPushPromiseStart methods.
+ void Reset() {
+ DVLOG(2) << "HpackBlockDecoder::Reset";
+ before_entry_ = true;
+ }
+
+ // Decode the fragment of the HPACK block contained in the decode buffer.
+ // Expected to be called from an implementation of Http2FrameDecoderListener's
+ // OnHpackFragment method.
+ DecodeStatus Decode(DecodeBuffer* db);
+
+ // Is the decoding process between entries (i.e. would the next byte be the
+ // first byte of a new HPACK entry)?
+ bool before_entry() const { return before_entry_; }
+
+ std::string DebugString() const;
+
+ private:
+ HpackEntryDecoder entry_decoder_;
+ HpackEntryDecoderListener* listener_;
+ bool before_entry_ = true;
+
+ DISALLOW_COPY_AND_ASSIGN(HpackBlockDecoder);
+};
+
+NET_EXPORT_PRIVATE std::ostream& operator<<(std::ostream& out,
+ const HpackBlockDecoder& v);
+
+} // namespace net
+
+#endif // NET_HTTP2_HPACK_DECODER_HPACK_BLOCK_DECODER_H_
diff --git a/chromium/net/http2/hpack/decoder/hpack_block_decoder_test.cc b/chromium/net/http2/hpack/decoder/hpack_block_decoder_test.cc
new file mode 100644
index 00000000000..566963dcccf
--- /dev/null
+++ b/chromium/net/http2/hpack/decoder/hpack_block_decoder_test.cc
@@ -0,0 +1,296 @@
+// Copyright 2016 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.
+
+#include "net/http2/hpack/decoder/hpack_block_decoder.h"
+
+// Tests of HpackBlockDecoder.
+
+#include <sstream>
+
+#include "net/http2/decoder/decode_buffer.h"
+#include "net/http2/hpack/decoder/hpack_block_collector.h"
+#include "net/http2/hpack/http2_hpack_constants.h"
+#include "net/http2/hpack/tools/hpack_block_builder.h"
+#include "net/http2/hpack/tools/hpack_example.h"
+#include "net/http2/tools/failure.h"
+#include "net/http2/tools/http2_random.h"
+#include "net/http2/tools/random_decoder_test.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+using ::testing::AssertionSuccess;
+using std::string;
+using base::StringPiece;
+
+namespace net {
+namespace test {
+namespace {
+
+class HpackBlockDecoderTest : public RandomDecoderTest {
+
+ protected:
+ HpackBlockDecoderTest() : listener_(&collector_), decoder_(&listener_) {
+ stop_decode_on_done_ = false;
+ decoder_.Reset();
+ // Make sure logging doesn't crash. Not examining the result.
+ std::ostringstream strm;
+ strm << decoder_;
+ }
+
+ DecodeStatus StartDecoding(DecodeBuffer* db) override {
+ collector_.Clear();
+ decoder_.Reset();
+ return ResumeDecoding(db);
+ }
+
+ DecodeStatus ResumeDecoding(DecodeBuffer* db) override {
+ DecodeStatus status = decoder_.Decode(db);
+
+ // Make sure logging doesn't crash. Not examining the result.
+ std::ostringstream strm;
+ strm << decoder_;
+
+ return status;
+ }
+
+ AssertionResult DecodeAndValidateSeveralWays(DecodeBuffer* db,
+ Validator validator) {
+ bool return_non_zero_on_first = false;
+ return RandomDecoderTest::DecodeAndValidateSeveralWays(
+ db, return_non_zero_on_first, validator);
+ }
+
+ AssertionResult DecodeAndValidateSeveralWays(const HpackBlockBuilder& hbb,
+ Validator validator) {
+ DecodeBuffer db(hbb.buffer());
+ return DecodeAndValidateSeveralWays(&db, validator);
+ }
+
+ AssertionResult DecodeHpackExampleAndValidateSeveralWays(
+ StringPiece hpack_example,
+ Validator validator) {
+ string input = HpackExampleToStringOrDie(hpack_example);
+ DecodeBuffer db(input);
+ return DecodeAndValidateSeveralWays(&db, validator);
+ }
+
+ uint8_t Rand8() { return Random().Rand8(); }
+
+ string Rand8String() { return Random().RandString(Rand8()); }
+
+ HpackBlockCollector collector_;
+ HpackEntryDecoderVLoggingListener listener_;
+ HpackBlockDecoder decoder_;
+};
+
+// http://httpwg.org/specs/rfc7541.html#rfc.section.C.2.1
+TEST_F(HpackBlockDecoderTest, SpecExample_C_2_1) {
+ NoArgValidator do_check = [this]() {
+ VERIFY_AND_RETURN_SUCCESS(collector_.ValidateSoleLiteralNameValueHeader(
+ HpackEntryType::kIndexedLiteralHeader, false, "custom-key", false,
+ "custom-header"));
+ };
+ EXPECT_TRUE(
+ DecodeHpackExampleAndValidateSeveralWays(R"(
+ 40 | == Literal indexed ==
+ 0a | Literal name (len = 10)
+ 6375 7374 6f6d 2d6b 6579 | custom-key
+ 0d | Literal value (len = 13)
+ 6375 7374 6f6d 2d68 6561 6465 72 | custom-header
+ | -> custom-key:
+ | custom-header
+ )",
+ ValidateDoneAndEmpty(do_check)));
+ EXPECT_TRUE(do_check());
+}
+
+// http://httpwg.org/specs/rfc7541.html#rfc.section.C.2.2
+TEST_F(HpackBlockDecoderTest, SpecExample_C_2_2) {
+ NoArgValidator do_check = [this]() {
+ VERIFY_AND_RETURN_SUCCESS(collector_.ValidateSoleLiteralValueHeader(
+ HpackEntryType::kUnindexedLiteralHeader, 4, false, "/sample/path"));
+ };
+ EXPECT_TRUE(
+ DecodeHpackExampleAndValidateSeveralWays(R"(
+ 04 | == Literal not indexed ==
+ | Indexed name (idx = 4)
+ | :path
+ 0c | Literal value (len = 12)
+ 2f73 616d 706c 652f 7061 7468 | /sample/path
+ | -> :path: /sample/path
+ )",
+ ValidateDoneAndEmpty(do_check)));
+ EXPECT_TRUE(do_check());
+}
+
+// http://httpwg.org/specs/rfc7541.html#rfc.section.C.2.3
+TEST_F(HpackBlockDecoderTest, SpecExample_C_2_3) {
+ NoArgValidator do_check = [this]() {
+ VERIFY_AND_RETURN_SUCCESS(collector_.ValidateSoleLiteralNameValueHeader(
+ HpackEntryType::kNeverIndexedLiteralHeader, false, "password", false,
+ "secret"));
+ };
+ EXPECT_TRUE(
+ DecodeHpackExampleAndValidateSeveralWays(R"(
+ 10 | == Literal never indexed ==
+ 08 | Literal name (len = 8)
+ 7061 7373 776f 7264 | password
+ 06 | Literal value (len = 6)
+ 7365 6372 6574 | secret
+ | -> password: secret
+ )",
+ ValidateDoneAndEmpty(do_check)));
+ EXPECT_TRUE(do_check());
+}
+
+// http://httpwg.org/specs/rfc7541.html#rfc.section.C.2.4
+TEST_F(HpackBlockDecoderTest, SpecExample_C_2_4) {
+ NoArgValidator do_check = [this]() {
+ VERIFY_AND_RETURN_SUCCESS(collector_.ValidateSoleIndexedHeader(2));
+ };
+ EXPECT_TRUE(
+ DecodeHpackExampleAndValidateSeveralWays(R"(
+ 82 | == Indexed - Add ==
+ | idx = 2
+ | -> :method: GET
+ )",
+ ValidateDoneAndEmpty(do_check)));
+ EXPECT_TRUE(do_check());
+}
+// http://httpwg.org/specs/rfc7541.html#rfc.section.C.3.1
+TEST_F(HpackBlockDecoderTest, SpecExample_C_3_1) {
+ string example = R"(
+ 82 | == Indexed - Add ==
+ | idx = 2
+ | -> :method: GET
+ 86 | == Indexed - Add ==
+ | idx = 6
+ | -> :scheme: http
+ 84 | == Indexed - Add ==
+ | idx = 4
+ | -> :path: /
+ 41 | == Literal indexed ==
+ | Indexed name (idx = 1)
+ | :authority
+ 0f | Literal value (len = 15)
+ 7777 772e 6578 616d 706c 652e 636f 6d | www.example.com
+ | -> :authority:
+ | www.example.com
+ )";
+ HpackBlockCollector expected;
+ expected.ExpectIndexedHeader(2);
+ expected.ExpectIndexedHeader(6);
+ expected.ExpectIndexedHeader(4);
+ expected.ExpectNameIndexAndLiteralValue(HpackEntryType::kIndexedLiteralHeader,
+ 1, false, "www.example.com");
+ NoArgValidator do_check = [expected, this]() {
+ VERIFY_AND_RETURN_SUCCESS(collector_.VerifyEq(expected));
+ };
+ EXPECT_TRUE(DecodeHpackExampleAndValidateSeveralWays(
+ example, ValidateDoneAndEmpty(do_check)));
+ EXPECT_TRUE(do_check());
+}
+
+// http://httpwg.org/specs/rfc7541.html#rfc.section.C.5.1
+TEST_F(HpackBlockDecoderTest, SpecExample_C_5_1) {
+ string example = R"(
+ 48 | == Literal indexed ==
+ | Indexed name (idx = 8)
+ | :status
+ 03 | Literal value (len = 3)
+ 3330 32 | 302
+ | -> :status: 302
+ 58 | == Literal indexed ==
+ | Indexed name (idx = 24)
+ | cache-control
+ 07 | Literal value (len = 7)
+ 7072 6976 6174 65 | private
+ | -> cache-control: private
+ 61 | == Literal indexed ==
+ | Indexed name (idx = 33)
+ | date
+ 1d | Literal value (len = 29)
+ 4d6f 6e2c 2032 3120 4f63 7420 3230 3133 | Mon, 21 Oct 2013
+ 2032 303a 3133 3a32 3120 474d 54 | 20:13:21 GMT
+ | -> date: Mon, 21 Oct 2013
+ | 20:13:21 GMT
+ 6e | == Literal indexed ==
+ | Indexed name (idx = 46)
+ | location
+ 17 | Literal value (len = 23)
+ 6874 7470 733a 2f2f 7777 772e 6578 616d | https://www.exam
+ 706c 652e 636f 6d | ple.com
+ | -> location:
+ | https://www.example.com
+ )";
+ HpackBlockCollector expected;
+ expected.ExpectNameIndexAndLiteralValue(HpackEntryType::kIndexedLiteralHeader,
+ 8, false, "302");
+ expected.ExpectNameIndexAndLiteralValue(HpackEntryType::kIndexedLiteralHeader,
+ 24, false, "private");
+ expected.ExpectNameIndexAndLiteralValue(HpackEntryType::kIndexedLiteralHeader,
+ 33, false,
+ "Mon, 21 Oct 2013 20:13:21 GMT");
+ expected.ExpectNameIndexAndLiteralValue(HpackEntryType::kIndexedLiteralHeader,
+ 46, false, "https://www.example.com");
+ NoArgValidator do_check = [expected, this]() {
+ VERIFY_AND_RETURN_SUCCESS(collector_.VerifyEq(expected));
+ };
+ EXPECT_TRUE(DecodeHpackExampleAndValidateSeveralWays(
+ example, ValidateDoneAndEmpty(do_check)));
+ EXPECT_TRUE(do_check());
+}
+
+// Generate a bunch of HPACK block entries to expect, use those expectations
+// to generate an HPACK block, then decode it and confirm it matches those
+// expectations. Some of these are invalid (such as Indexed, with index=0),
+// but well-formed, and the decoder doesn't check for validity, just
+// well-formedness. That includes the validity of the strings not being checked,
+// such as lower-case ascii for the names, and valid Huffman encodings.
+TEST_F(HpackBlockDecoderTest, Computed) {
+ HpackBlockCollector expected;
+ expected.ExpectIndexedHeader(0);
+ expected.ExpectIndexedHeader(1);
+ expected.ExpectIndexedHeader(126);
+ expected.ExpectIndexedHeader(127);
+ expected.ExpectIndexedHeader(128);
+ expected.ExpectDynamicTableSizeUpdate(0);
+ expected.ExpectDynamicTableSizeUpdate(1);
+ expected.ExpectDynamicTableSizeUpdate(14);
+ expected.ExpectDynamicTableSizeUpdate(15);
+ expected.ExpectDynamicTableSizeUpdate(30);
+ expected.ExpectDynamicTableSizeUpdate(31);
+ expected.ExpectDynamicTableSizeUpdate(4095);
+ expected.ExpectDynamicTableSizeUpdate(4096);
+ expected.ExpectDynamicTableSizeUpdate(8192);
+ for (auto type : {HpackEntryType::kIndexedLiteralHeader,
+ HpackEntryType::kUnindexedLiteralHeader,
+ HpackEntryType::kNeverIndexedLiteralHeader}) {
+ for (bool value_huffman : {false, true}) {
+ // An entry with an index for the name. Ensure the name index
+ // is not zero by adding one to the Rand8() result.
+ expected.ExpectNameIndexAndLiteralValue(type, Rand8() + 1, value_huffman,
+ Rand8String());
+ // And two entries with literal names, one plain, one huffman encoded.
+ expected.ExpectLiteralNameAndValue(type, false, Rand8String(),
+ value_huffman, Rand8String());
+ expected.ExpectLiteralNameAndValue(type, true, Rand8String(),
+ value_huffman, Rand8String());
+ }
+ }
+ // Shuffle the entries and serialize them to produce an HPACK block.
+ expected.ShuffleEntries(RandomPtr());
+ HpackBlockBuilder hbb;
+ expected.AppendToHpackBlockBuilder(&hbb);
+
+ NoArgValidator do_check = [expected, this]() {
+ VERIFY_AND_RETURN_SUCCESS(collector_.VerifyEq(expected));
+ };
+ EXPECT_TRUE(
+ DecodeAndValidateSeveralWays(hbb, ValidateDoneAndEmpty(do_check)));
+ EXPECT_TRUE(do_check());
+}
+
+} // namespace
+} // namespace test
+} // namespace net
diff --git a/chromium/net/http2/hpack/decoder/hpack_decoder_listener.cc b/chromium/net/http2/hpack/decoder/hpack_decoder_listener.cc
new file mode 100644
index 00000000000..8bb0e47e9a2
--- /dev/null
+++ b/chromium/net/http2/hpack/decoder/hpack_decoder_listener.cc
@@ -0,0 +1,32 @@
+// Copyright 2016 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.
+
+#include "net/http2/hpack/decoder/hpack_decoder_listener.h"
+
+using base::StringPiece;
+
+namespace net {
+
+HpackDecoderListener::HpackDecoderListener() {}
+HpackDecoderListener::~HpackDecoderListener() {}
+
+HpackDecoderNoOpListener::HpackDecoderNoOpListener() {}
+HpackDecoderNoOpListener::~HpackDecoderNoOpListener() {}
+
+void HpackDecoderNoOpListener::OnHeaderListStart() {}
+void HpackDecoderNoOpListener::OnHeader(HpackEntryType entry_type,
+ const HpackString& name,
+ const HpackString& value) {}
+void HpackDecoderNoOpListener::OnHeaderListEnd() {}
+void HpackDecoderNoOpListener::OnHeaderErrorDetected(
+ StringPiece error_message) {}
+
+// static
+HpackDecoderNoOpListener* HpackDecoderNoOpListener::NoOpListener() {
+ static HpackDecoderNoOpListener* static_instance =
+ new HpackDecoderNoOpListener();
+ return static_instance;
+}
+
+} // namespace net
diff --git a/chromium/net/http2/hpack/decoder/hpack_decoder_listener.h b/chromium/net/http2/hpack/decoder/hpack_decoder_listener.h
new file mode 100644
index 00000000000..a5facd6ddb3
--- /dev/null
+++ b/chromium/net/http2/hpack/decoder/hpack_decoder_listener.h
@@ -0,0 +1,65 @@
+// Copyright 2016 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.
+
+// Defines HpackDecoderListener, the base class of listeners for HTTP header
+// lists decoded from an HPACK block.
+
+#ifndef NET_HTTP2_HPACK_DECODER_HPACK_DECODER_LISTENER_H_
+#define NET_HTTP2_HPACK_DECODER_HPACK_DECODER_LISTENER_H_
+
+#include "base/strings/string_piece.h"
+#include "net/base/net_export.h"
+#include "net/http2/hpack/hpack_string.h"
+#include "net/http2/hpack/http2_hpack_constants.h"
+
+namespace net {
+
+class NET_EXPORT HpackDecoderListener {
+ public:
+ HpackDecoderListener();
+ virtual ~HpackDecoderListener();
+
+ // OnHeaderListStart is called at the start of decoding an HPACK block into
+ // an HTTP/2 header list. Will only be called once per block, even if it
+ // extends into CONTINUATION frames.
+ virtual void OnHeaderListStart() = 0;
+
+ // Called for each header name-value pair that is decoded, in the order they
+ // appear in the HPACK block. Multiple values for a given key will be emitted
+ // as multiple calls to OnHeader.
+ virtual void OnHeader(HpackEntryType entry_type,
+ const HpackString& name,
+ const HpackString& value) = 0;
+
+ // OnHeaderListEnd is called after successfully decoding an HPACK block into
+ // an HTTP/2 header list. Will only be called once per block, even if it
+ // extends into CONTINUATION frames.
+ virtual void OnHeaderListEnd() = 0;
+
+ // OnHeaderErrorDetected is called if an error is detected while decoding.
+ // error_message may be used in a GOAWAY frame as the Opaque Data.
+ virtual void OnHeaderErrorDetected(base::StringPiece error_message) = 0;
+};
+
+// A no-op implementation of HpackDecoderListener, useful for ignoring
+// callbacks once an error is detected.
+class NET_EXPORT HpackDecoderNoOpListener : public HpackDecoderListener {
+ public:
+ HpackDecoderNoOpListener();
+ ~HpackDecoderNoOpListener() override;
+
+ void OnHeaderListStart() override;
+ void OnHeader(HpackEntryType entry_type,
+ const HpackString& name,
+ const HpackString& value) override;
+ void OnHeaderListEnd() override;
+ void OnHeaderErrorDetected(base::StringPiece error_message) override;
+
+ // Returns a listener that ignores all the calls.
+ static HpackDecoderNoOpListener* NoOpListener();
+};
+
+} // namespace net
+
+#endif // NET_HTTP2_HPACK_DECODER_HPACK_DECODER_LISTENER_H_
diff --git a/chromium/net/http2/hpack/decoder/hpack_decoder_state.cc b/chromium/net/http2/hpack/decoder/hpack_decoder_state.cc
new file mode 100644
index 00000000000..bebe08ac7ca
--- /dev/null
+++ b/chromium/net/http2/hpack/decoder/hpack_decoder_state.cc
@@ -0,0 +1,221 @@
+// Copyright 2016 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.
+
+#include "net/http2/hpack/decoder/hpack_decoder_state.h"
+
+#include "base/logging.h"
+#include "net/http2/hpack/hpack_string.h"
+#include "net/http2/http2_constants.h"
+
+using base::StringPiece;
+
+namespace net {
+namespace {
+
+HpackString ExtractHpackString(HpackDecoderStringBuffer* string_buffer) {
+ if (string_buffer->IsBuffered()) {
+ return HpackString(string_buffer->ReleaseString());
+ } else {
+ auto result = HpackString(string_buffer->str());
+ string_buffer->Reset();
+ return result;
+ }
+}
+
+} // namespace
+
+HpackDecoderState::HpackDecoderState(HpackDecoderListener* listener)
+ : listener_(listener),
+ final_header_table_size_(Http2SettingsInfo::DefaultHeaderTableSize()),
+ lowest_header_table_size_(final_header_table_size_),
+ require_dynamic_table_size_update_(false),
+ allow_dynamic_table_size_update_(true),
+ saw_dynamic_table_size_update_(false),
+ error_detected_(false) {
+ CHECK(listener);
+}
+HpackDecoderState::~HpackDecoderState() {}
+
+void HpackDecoderState::set_listener(HpackDecoderListener* listener) {
+ CHECK(listener);
+ listener_ = listener;
+}
+
+void HpackDecoderState::ApplyHeaderTableSizeSetting(
+ uint32_t header_table_size) {
+ DVLOG(2) << "HpackDecoderState::ApplyHeaderTableSizeSetting("
+ << header_table_size << ")";
+ DCHECK_LE(lowest_header_table_size_, final_header_table_size_);
+ if (header_table_size < lowest_header_table_size_) {
+ lowest_header_table_size_ = header_table_size;
+ }
+ final_header_table_size_ = header_table_size;
+ DVLOG(2) << "low water mark: " << lowest_header_table_size_;
+ DVLOG(2) << "final limit: " << final_header_table_size_;
+}
+
+// Called to notify this object that we're starting to decode an HPACK block
+// (e.g. a HEADERS or PUSH_PROMISE frame's header has been decoded).
+void HpackDecoderState::OnHeaderBlockStart() {
+ DVLOG(2) << "HpackDecoderState::OnHeaderBlockStart";
+ // This instance can't be reused after an error has been detected, as we must
+ // assume that the encoder and decoder compression states are no longer
+ // synchronized.
+ DCHECK(!error_detected_);
+ DCHECK_LE(lowest_header_table_size_, final_header_table_size_);
+ allow_dynamic_table_size_update_ = true;
+ saw_dynamic_table_size_update_ = false;
+ // If the peer has acknowledged a HEADER_TABLE_SIZE smaller than that which
+ // its HPACK encoder has been using, then the next HPACK block it sends MUST
+ // start with a Dynamic Table Size Update entry that is at least as low as
+ // lowest_header_table_size_. That may be followed by another as great as
+ // final_header_table_size_, if those are different.
+ require_dynamic_table_size_update_ =
+ (lowest_header_table_size_ <
+ decoder_tables_.current_header_table_size() ||
+ final_header_table_size_ < decoder_tables_.header_table_size_limit());
+ DVLOG(2) << "HpackDecoderState::OnHeaderListStart "
+ << "require_dynamic_table_size_update_="
+ << require_dynamic_table_size_update_;
+ listener_->OnHeaderListStart();
+}
+
+void HpackDecoderState::OnIndexedHeader(size_t index) {
+ DVLOG(2) << "HpackDecoderState::OnIndexedHeader: " << index;
+ if (error_detected_) {
+ return;
+ }
+ if (require_dynamic_table_size_update_) {
+ ReportError("Missing dynamic table size update.");
+ return;
+ }
+ allow_dynamic_table_size_update_ = false;
+ const HpackStringPair* entry = decoder_tables_.Lookup(index);
+ if (entry != nullptr) {
+ listener_->OnHeader(HpackEntryType::kIndexedHeader, entry->name,
+ entry->value);
+ } else {
+ ReportError("Invalid index.");
+ }
+}
+
+void HpackDecoderState::OnNameIndexAndLiteralValue(
+ HpackEntryType entry_type,
+ size_t name_index,
+ HpackDecoderStringBuffer* value_buffer) {
+ DVLOG(2) << "HpackDecoderState::OnNameIndexAndLiteralValue " << entry_type
+ << ", " << name_index << ", " << value_buffer->str();
+ if (error_detected_) {
+ return;
+ }
+ if (require_dynamic_table_size_update_) {
+ ReportError("Missing dynamic table size update.");
+ return;
+ }
+ allow_dynamic_table_size_update_ = false;
+ const HpackStringPair* entry = decoder_tables_.Lookup(name_index);
+ if (entry != nullptr) {
+ HpackString value(ExtractHpackString(value_buffer));
+ listener_->OnHeader(entry_type, entry->name, value);
+ if (entry_type == HpackEntryType::kIndexedLiteralHeader) {
+ decoder_tables_.Insert(entry->name, value);
+ }
+ } else {
+ ReportError("Invalid name index.");
+ }
+}
+
+void HpackDecoderState::OnLiteralNameAndValue(
+ HpackEntryType entry_type,
+ HpackDecoderStringBuffer* name_buffer,
+ HpackDecoderStringBuffer* value_buffer) {
+ DVLOG(2) << "HpackDecoderState::OnLiteralNameAndValue " << entry_type << ", "
+ << name_buffer->str() << ", " << value_buffer->str();
+ if (error_detected_) {
+ return;
+ }
+ if (require_dynamic_table_size_update_) {
+ ReportError("Missing dynamic table size update.");
+ return;
+ }
+ allow_dynamic_table_size_update_ = false;
+ HpackString name(ExtractHpackString(name_buffer));
+ HpackString value(ExtractHpackString(value_buffer));
+ listener_->OnHeader(entry_type, name, value);
+ if (entry_type == HpackEntryType::kIndexedLiteralHeader) {
+ decoder_tables_.Insert(name, value);
+ }
+}
+
+void HpackDecoderState::OnDynamicTableSizeUpdate(size_t size_limit) {
+ DVLOG(2) << "HpackDecoderState::OnDynamicTableSizeUpdate " << size_limit
+ << ", required="
+ << (require_dynamic_table_size_update_ ? "true" : "false")
+ << ", allowed="
+ << (allow_dynamic_table_size_update_ ? "true" : "false");
+ if (error_detected_) {
+ return;
+ }
+ DCHECK_LE(lowest_header_table_size_, final_header_table_size_);
+ if (!allow_dynamic_table_size_update_) {
+ // At most two dynamic table size updates allowed at the start, and not
+ // after a header.
+ ReportError("Dynamic table size update not allowed.");
+ return;
+ }
+ if (require_dynamic_table_size_update_) {
+ // The new size must not be greater than the low water mark.
+ if (size_limit > lowest_header_table_size_) {
+ ReportError("Initial dynamic table size update is above low water mark.");
+ return;
+ }
+ require_dynamic_table_size_update_ = false;
+ } else if (size_limit > final_header_table_size_) {
+ // The new size must not be greater than the final max header table size
+ // that the peer acknowledged.
+ ReportError("Dynamic table size update is above acknowledged setting.");
+ return;
+ }
+ decoder_tables_.DynamicTableSizeUpdate(size_limit);
+ if (saw_dynamic_table_size_update_) {
+ allow_dynamic_table_size_update_ = false;
+ } else {
+ saw_dynamic_table_size_update_ = true;
+ }
+ // We no longer need to keep an eye out for a lower header table size.
+ lowest_header_table_size_ = final_header_table_size_;
+}
+
+void HpackDecoderState::OnHpackDecodeError(StringPiece error_message) {
+ DVLOG(2) << "HpackDecoderState::OnHpackDecodeError " << error_message;
+ if (!error_detected_) {
+ ReportError(error_message);
+ }
+}
+
+void HpackDecoderState::OnHeaderBlockEnd() {
+ DVLOG(2) << "HpackDecoderState::OnHeaderBlockEnd";
+ if (error_detected_) {
+ return;
+ }
+ if (require_dynamic_table_size_update_) {
+ // Apparently the HPACK block was empty, but we needed it to contain at
+ // least 1 dynamic table size update.
+ ReportError("Missing dynamic table size update.");
+ } else {
+ listener_->OnHeaderListEnd();
+ }
+}
+
+void HpackDecoderState::ReportError(StringPiece error_message) {
+ DVLOG(2) << "HpackDecoderState::ReportError is new="
+ << (!error_detected_ ? "true" : "false")
+ << ", error_message: " << error_message;
+ if (!error_detected_) {
+ listener_->OnHeaderErrorDetected(error_message);
+ error_detected_ = true;
+ }
+}
+
+} // namespace net
diff --git a/chromium/net/http2/hpack/decoder/hpack_decoder_state.h b/chromium/net/http2/hpack/decoder/hpack_decoder_state.h
new file mode 100644
index 00000000000..28a4865aef3
--- /dev/null
+++ b/chromium/net/http2/hpack/decoder/hpack_decoder_state.h
@@ -0,0 +1,124 @@
+// Copyright 2016 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.
+
+// HpackDecoderState maintains the HPACK decompressor state; i.e. updates the
+// HPACK dynamic table according to RFC 7541 as the entries in an HPACK block
+// are decoded, and reads from the static and dynamic tables in order to build
+// complete header entries. Calls an HpackDecoderListener with the completely
+// decoded headers (i.e. after resolving table indices into names or values),
+// thus translating the decoded HPACK entries into HTTP/2 headers.
+
+#ifndef NET_HTTP2_HPACK_DECODER_HPACK_DECODER_STATE_H_
+#define NET_HTTP2_HPACK_DECODER_HPACK_DECODER_STATE_H_
+
+#include <stddef.h>
+#include <stdint.h>
+
+#include "base/macros.h"
+#include "base/strings/string_piece.h"
+#include "net/base/net_export.h"
+#include "net/http2/hpack/decoder/hpack_decoder_listener.h"
+#include "net/http2/hpack/decoder/hpack_decoder_string_buffer.h"
+#include "net/http2/hpack/decoder/hpack_decoder_tables.h"
+#include "net/http2/hpack/decoder/hpack_whole_entry_listener.h"
+#include "net/http2/hpack/http2_hpack_constants.h"
+
+namespace net {
+namespace test {
+class HpackDecoderStatePeer;
+} // namespace test
+
+class NET_EXPORT HpackDecoderState : public HpackWholeEntryListener {
+ public:
+ explicit HpackDecoderState(HpackDecoderListener* listener);
+ ~HpackDecoderState() override;
+
+ // Set the listener to be notified when a whole entry has been decoded,
+ // including resolving name or name and value references.
+ // The listener may be changed at any time.
+ void set_listener(HpackDecoderListener* listener);
+ HpackDecoderListener* listener() const { return listener_; }
+
+ // ApplyHeaderTableSizeSetting notifies this object that this endpoint has
+ // received a SETTINGS ACK frame acknowledging an earlier SETTINGS frame from
+ // this endpoint specifying a new value for SETTINGS_HEADER_TABLE_SIZE (the
+ // maximum size of the dynamic table that this endpoint will use to decode
+ // HPACK blocks).
+ // Because a SETTINGS frame can contain SETTINGS_HEADER_TABLE_SIZE values,
+ // the caller must keep track of those multiple changes, and make
+ // corresponding calls to this method. In particular, a call must be made
+ // with the lowest value acknowledged by the peer, and a call must be made
+ // with the final value acknowledged, in that order; additional calls may
+ // be made if additional values were sent. These calls must be made between
+ // decoding the SETTINGS ACK, and before the next HPACK block is decoded.
+ void ApplyHeaderTableSizeSetting(uint32_t max_header_table_size);
+
+ // OnHeaderBlockStart notifies this object that we're starting to decode the
+ // HPACK payload of a HEADERS or PUSH_PROMISE frame.
+ void OnHeaderBlockStart();
+
+ // Implement the HpackWholeEntryListener methods, each of which notifies this
+ // object when an entire entry has been decoded.
+ void OnIndexedHeader(size_t index) override;
+ void OnNameIndexAndLiteralValue(
+ HpackEntryType entry_type,
+ size_t name_index,
+ HpackDecoderStringBuffer* value_buffer) override;
+ void OnLiteralNameAndValue(HpackEntryType entry_type,
+ HpackDecoderStringBuffer* name_buffer,
+ HpackDecoderStringBuffer* value_buffer) override;
+ void OnDynamicTableSizeUpdate(size_t size) override;
+ void OnHpackDecodeError(base::StringPiece error_message) override;
+
+ // OnHeaderBlockEnd notifies this object that an entire HPACK block has been
+ // decoded, which might have extended into CONTINUATION blocks.
+ void OnHeaderBlockEnd();
+
+ // Was an error detected? After an error has been detected and reported,
+ // no further callbacks will be made to the listener.
+ bool error_detected() const { return error_detected_; }
+
+ const HpackDecoderTables& decoder_tables_for_test() const {
+ return decoder_tables_;
+ }
+
+ private:
+ friend class test::HpackDecoderStatePeer;
+
+ // Reports an error to the listener IF this is the first error detected.
+ void ReportError(base::StringPiece error_message);
+
+ // The static and dynamic HPACK tables.
+ HpackDecoderTables decoder_tables_;
+
+ // The listener to be notified of headers, the start and end of header
+ // lists, and of errors.
+ HpackDecoderListener* listener_;
+
+ // The most recent HEADER_TABLE_SIZE setting acknowledged by the peer.
+ uint32_t final_header_table_size_;
+
+ // The lowest HEADER_TABLE_SIZE setting acknowledged by the peer; valid until
+ // the next HPACK block is decoded.
+ // TODO(jamessynge): Test raising the HEADER_TABLE_SIZE.
+ uint32_t lowest_header_table_size_;
+
+ // Must the next (first) HPACK entry be a dynamic table size update?
+ bool require_dynamic_table_size_update_;
+
+ // May the next (first or second) HPACK entry be a dynamic table size update?
+ bool allow_dynamic_table_size_update_;
+
+ // Have we already seen a dynamic table size update in this HPACK block?
+ bool saw_dynamic_table_size_update_;
+
+ // Has an error already been detected and reported to the listener?
+ bool error_detected_;
+
+ DISALLOW_COPY_AND_ASSIGN(HpackDecoderState);
+};
+
+} // namespace net
+
+#endif // NET_HTTP2_HPACK_DECODER_HPACK_DECODER_STATE_H_
diff --git a/chromium/net/http2/hpack/decoder/hpack_decoder_state_test.cc b/chromium/net/http2/hpack/decoder/hpack_decoder_state_test.cc
new file mode 100644
index 00000000000..0ed4098f478
--- /dev/null
+++ b/chromium/net/http2/hpack/decoder/hpack_decoder_state_test.cc
@@ -0,0 +1,550 @@
+// Copyright 2016 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.
+
+#include "net/http2/hpack/decoder/hpack_decoder_state.h"
+
+// Tests of HpackDecoderState.
+
+#include <string>
+#include <utility>
+#include <vector>
+
+#include "base/logging.h"
+#include "net/http2/hpack/hpack_string.h"
+#include "net/http2/http2_constants.h"
+#include "net/http2/tools/failure.h"
+#include "net/test/gtest_util.h"
+#include "testing/gmock/include/gmock/gmock-matchers.h"
+#include "testing/gmock/include/gmock/gmock.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+using ::testing::AssertionResult;
+using ::testing::AssertionSuccess;
+using ::testing::Eq;
+using ::testing::HasSubstr;
+using ::testing::Mock;
+using ::testing::StrictMock;
+using base::StringPiece;
+
+namespace net {
+namespace test {
+class HpackDecoderStatePeer {
+ public:
+ static HpackDecoderTables* GetDecoderTables(HpackDecoderState* state) {
+ return &state->decoder_tables_;
+ }
+};
+
+namespace {
+
+// Define HasSubstr() for base::StringPiece arguments.
+// This shadows ::testing::HasSubstr(), which only works on argument types
+// that can be implicilty converted to a std::string.
+inline ::testing::PolymorphicMatcher<StringPieceHasSubstrMatcher> HasSubstr(
+ const std::string& substring) {
+ return ::testing::MakePolymorphicMatcher(
+ StringPieceHasSubstrMatcher(substring));
+}
+
+class MockHpackDecoderListener : public HpackDecoderListener {
+ public:
+ MOCK_METHOD0(OnHeaderListStart, void());
+ MOCK_METHOD3(OnHeader,
+ void(HpackEntryType entry_type,
+ const HpackString& name,
+ const HpackString& value));
+ MOCK_METHOD0(OnHeaderListEnd, void());
+ MOCK_METHOD1(OnHeaderErrorDetected, void(StringPiece error_message));
+};
+
+enum StringBacking { STATIC, UNBUFFERED, BUFFERED };
+
+class HpackDecoderStateTest : public ::testing::Test {
+ protected:
+ HpackDecoderStateTest() : decoder_state_(&listener_) {}
+
+ HpackDecoderTables* GetDecoderTables() {
+ return HpackDecoderStatePeer::GetDecoderTables(&decoder_state_);
+ }
+
+ const HpackStringPair* Lookup(size_t index) {
+ return GetDecoderTables()->Lookup(index);
+ }
+
+ size_t current_header_table_size() {
+ return GetDecoderTables()->current_header_table_size();
+ }
+
+ size_t header_table_size_limit() {
+ return GetDecoderTables()->header_table_size_limit();
+ }
+
+ void set_header_table_size_limit(size_t size) {
+ GetDecoderTables()->DynamicTableSizeUpdate(size);
+ }
+
+ void SetStringBuffer(const char* s,
+ StringBacking backing,
+ HpackDecoderStringBuffer* string_buffer) {
+ switch (backing) {
+ case STATIC:
+ string_buffer->Set(s, true);
+ break;
+ case UNBUFFERED:
+ string_buffer->Set(s, false);
+ break;
+ case BUFFERED:
+ string_buffer->Set(s, false);
+ string_buffer->BufferStringIfUnbuffered();
+ break;
+ }
+ }
+
+ void SetName(const char* s, StringBacking backing) {
+ SetStringBuffer(s, backing, &name_buffer_);
+ }
+
+ void SetValue(const char* s, StringBacking backing) {
+ SetStringBuffer(s, backing, &value_buffer_);
+ }
+
+ void SendStartAndVerifyCallback() {
+ EXPECT_CALL(listener_, OnHeaderListStart());
+ decoder_state_.OnHeaderBlockStart();
+ Mock::VerifyAndClearExpectations(&listener_);
+ }
+
+ void SendSizeUpdate(size_t size) {
+ decoder_state_.OnDynamicTableSizeUpdate(size);
+ Mock::VerifyAndClearExpectations(&listener_);
+ }
+
+ void SendIndexAndVerifyCallback(size_t index,
+ HpackEntryType expected_type,
+ const char* expected_name,
+ const char* expected_value) {
+ EXPECT_CALL(listener_,
+ OnHeader(expected_type, Eq(expected_name), Eq(expected_value)));
+ decoder_state_.OnIndexedHeader(index);
+ Mock::VerifyAndClearExpectations(&listener_);
+ }
+
+ void SendValueAndVerifyCallback(size_t name_index,
+ HpackEntryType entry_type,
+ const char* name,
+ const char* value,
+ StringBacking value_backing) {
+ SetValue(value, value_backing);
+ EXPECT_CALL(listener_, OnHeader(entry_type, Eq(name), Eq(value)));
+ decoder_state_.OnNameIndexAndLiteralValue(entry_type, name_index,
+ &value_buffer_);
+ Mock::VerifyAndClearExpectations(&listener_);
+ }
+
+ void SendNameAndValueAndVerifyCallback(HpackEntryType entry_type,
+ const char* name,
+ StringBacking name_backing,
+ const char* value,
+ StringBacking value_backing) {
+ SetName(name, name_backing);
+ SetValue(value, value_backing);
+ EXPECT_CALL(listener_, OnHeader(entry_type, Eq(name), Eq(value)));
+ decoder_state_.OnLiteralNameAndValue(entry_type, &name_buffer_,
+ &value_buffer_);
+ Mock::VerifyAndClearExpectations(&listener_);
+ }
+
+ void SendEndAndVerifyCallback() {
+ EXPECT_CALL(listener_, OnHeaderListEnd());
+ decoder_state_.OnHeaderBlockEnd();
+ Mock::VerifyAndClearExpectations(&listener_);
+ }
+
+ // dynamic_index is one-based, because that is the way RFC 7541 shows it.
+ AssertionResult VerifyEntry(size_t dynamic_index,
+ const char* name,
+ const char* value) {
+ const HpackStringPair* entry =
+ Lookup(dynamic_index + kFirstDynamicTableIndex - 1);
+ VERIFY_NE(entry, nullptr);
+ VERIFY_EQ(static_cast<StringPiece>(entry->name), name);
+ VERIFY_EQ(static_cast<StringPiece>(entry->value), value);
+ return AssertionSuccess();
+ }
+ AssertionResult VerifyNoEntry(size_t dynamic_index) {
+ const HpackStringPair* entry =
+ Lookup(dynamic_index + kFirstDynamicTableIndex - 1);
+ VERIFY_EQ(entry, nullptr);
+ return AssertionSuccess();
+ }
+ AssertionResult VerifyDynamicTableContents(
+ const std::vector<std::pair<const char*, const char*>>& entries) {
+ size_t index = 1;
+ for (const auto& entry : entries) {
+ VERIFY_SUCCESS(VerifyEntry(index, entry.first, entry.second));
+ ++index;
+ }
+ VERIFY_SUCCESS(VerifyNoEntry(index));
+ return AssertionSuccess();
+ }
+
+ StrictMock<MockHpackDecoderListener> listener_;
+ HpackDecoderState decoder_state_;
+ HpackDecoderStringBuffer name_buffer_, value_buffer_;
+};
+
+// Test based on RFC 7541, section C.3: Request Examples without Huffman Coding.
+// This section shows several consecutive header lists, corresponding to HTTP
+// requests, on the same connection.
+TEST_F(HpackDecoderStateTest, C3_RequestExamples) {
+ // C.3.1 First Request
+ //
+ // Header list to encode:
+ //
+ // :method: GET
+ // :scheme: http
+ // :path: /
+ // :authority: www.example.com
+
+ SendStartAndVerifyCallback();
+ SendIndexAndVerifyCallback(2, HpackEntryType::kIndexedHeader, ":method",
+ "GET");
+ SendIndexAndVerifyCallback(6, HpackEntryType::kIndexedHeader, ":scheme",
+ "http");
+ SendIndexAndVerifyCallback(4, HpackEntryType::kIndexedHeader, ":path", "/");
+ SendValueAndVerifyCallback(1, HpackEntryType::kIndexedLiteralHeader,
+ ":authority", "www.example.com", UNBUFFERED);
+ SendEndAndVerifyCallback();
+
+ // Dynamic Table (after decoding):
+ //
+ // [ 1] (s = 57) :authority: www.example.com
+ // Table size: 57
+
+ ASSERT_TRUE(VerifyDynamicTableContents({{":authority", "www.example.com"}}));
+ ASSERT_EQ(57u, current_header_table_size());
+
+ // C.3.2 Second Request
+ //
+ // Header list to encode:
+ //
+ // :method: GET
+ // :scheme: http
+ // :path: /
+ // :authority: www.example.com
+ // cache-control: no-cache
+
+ SendStartAndVerifyCallback();
+ SendIndexAndVerifyCallback(2, HpackEntryType::kIndexedHeader, ":method",
+ "GET");
+ SendIndexAndVerifyCallback(6, HpackEntryType::kIndexedHeader, ":scheme",
+ "http");
+ SendIndexAndVerifyCallback(4, HpackEntryType::kIndexedHeader, ":path", "/");
+ SendIndexAndVerifyCallback(62, HpackEntryType::kIndexedHeader, ":authority",
+ "www.example.com");
+ SendValueAndVerifyCallback(24, HpackEntryType::kIndexedLiteralHeader,
+ "cache-control", "no-cache", UNBUFFERED);
+ SendEndAndVerifyCallback();
+
+ // Dynamic Table (after decoding):
+ //
+ // [ 1] (s = 53) cache-control: no-cache
+ // [ 2] (s = 57) :authority: www.example.com
+ // Table size: 110
+
+ ASSERT_TRUE(VerifyDynamicTableContents(
+ {{"cache-control", "no-cache"}, {":authority", "www.example.com"}}));
+ ASSERT_EQ(110u, current_header_table_size());
+
+ // C.3.3 Third Request
+ //
+ // Header list to encode:
+ //
+ // :method: GET
+ // :scheme: https
+ // :path: /index.html
+ // :authority: www.example.com
+ // custom-key: custom-value
+
+ SendStartAndVerifyCallback();
+ SendIndexAndVerifyCallback(2, HpackEntryType::kIndexedHeader, ":method",
+ "GET");
+ SendIndexAndVerifyCallback(7, HpackEntryType::kIndexedHeader, ":scheme",
+ "https");
+ SendIndexAndVerifyCallback(5, HpackEntryType::kIndexedHeader, ":path",
+ "/index.html");
+ SendIndexAndVerifyCallback(63, HpackEntryType::kIndexedHeader, ":authority",
+ "www.example.com");
+ SendNameAndValueAndVerifyCallback(HpackEntryType::kIndexedLiteralHeader,
+ "custom-key", UNBUFFERED, "custom-value",
+ UNBUFFERED);
+ SendEndAndVerifyCallback();
+
+ // Dynamic Table (after decoding):
+ //
+ // [ 1] (s = 54) custom-key: custom-value
+ // [ 2] (s = 53) cache-control: no-cache
+ // [ 3] (s = 57) :authority: www.example.com
+ // Table size: 164
+
+ ASSERT_TRUE(VerifyDynamicTableContents({{"custom-key", "custom-value"},
+ {"cache-control", "no-cache"},
+ {":authority", "www.example.com"}}));
+ ASSERT_EQ(164u, current_header_table_size());
+}
+
+// Test based on RFC 7541, section C.5: Response Examples without Huffman
+// Coding. This section shows several consecutive header lists, corresponding
+// to HTTP responses, on the same connection. The HTTP/2 setting parameter
+// SETTINGS_HEADER_TABLE_SIZE is set to the value of 256 octets, causing
+// some evictions to occur.
+TEST_F(HpackDecoderStateTest, C5_ResponseExamples) {
+ set_header_table_size_limit(256);
+
+ // C.5.1 First Response
+ //
+ // Header list to encode:
+ //
+ // :status: 302
+ // cache-control: private
+ // date: Mon, 21 Oct 2013 20:13:21 GMT
+ // location: https://www.example.com
+
+ SendStartAndVerifyCallback();
+ SendValueAndVerifyCallback(8, HpackEntryType::kIndexedLiteralHeader,
+ ":status", "302", BUFFERED);
+ SendValueAndVerifyCallback(24, HpackEntryType::kIndexedLiteralHeader,
+ "cache-control", "private", UNBUFFERED);
+ SendValueAndVerifyCallback(33, HpackEntryType::kIndexedLiteralHeader, "date",
+ "Mon, 21 Oct 2013 20:13:21 GMT", UNBUFFERED);
+ SendValueAndVerifyCallback(46, HpackEntryType::kIndexedLiteralHeader,
+ "location", "https://www.example.com", UNBUFFERED);
+ SendEndAndVerifyCallback();
+
+ // Dynamic Table (after decoding):
+ //
+ // [ 1] (s = 63) location: https://www.example.com
+ // [ 2] (s = 65) date: Mon, 21 Oct 2013 20:13:21 GMT
+ // [ 3] (s = 52) cache-control: private
+ // [ 4] (s = 42) :status: 302
+ // Table size: 222
+
+ ASSERT_TRUE(
+ VerifyDynamicTableContents({{"location", "https://www.example.com"},
+ {"date", "Mon, 21 Oct 2013 20:13:21 GMT"},
+ {"cache-control", "private"},
+ {":status", "302"}}));
+ ASSERT_EQ(222u, current_header_table_size());
+
+ // C.5.2 Second Response
+ //
+ // The (":status", "302") header field is evicted from the dynamic table to
+ // free space to allow adding the (":status", "307") header field.
+ //
+ // Header list to encode:
+ //
+ // :status: 307
+ // cache-control: private
+ // date: Mon, 21 Oct 2013 20:13:21 GMT
+ // location: https://www.example.com
+
+ SendStartAndVerifyCallback();
+ SendValueAndVerifyCallback(8, HpackEntryType::kIndexedLiteralHeader,
+ ":status", "307", BUFFERED);
+ SendIndexAndVerifyCallback(65, HpackEntryType::kIndexedHeader,
+ "cache-control", "private");
+ SendIndexAndVerifyCallback(64, HpackEntryType::kIndexedHeader, "date",
+ "Mon, 21 Oct 2013 20:13:21 GMT");
+ SendIndexAndVerifyCallback(63, HpackEntryType::kIndexedHeader, "location",
+ "https://www.example.com");
+ SendEndAndVerifyCallback();
+
+ // Dynamic Table (after decoding):
+ //
+ // [ 1] (s = 42) :status: 307
+ // [ 2] (s = 63) location: https://www.example.com
+ // [ 3] (s = 65) date: Mon, 21 Oct 2013 20:13:21 GMT
+ // [ 4] (s = 52) cache-control: private
+ // Table size: 222
+
+ ASSERT_TRUE(
+ VerifyDynamicTableContents({{":status", "307"},
+ {"location", "https://www.example.com"},
+ {"date", "Mon, 21 Oct 2013 20:13:21 GMT"},
+ {"cache-control", "private"}}));
+ ASSERT_EQ(222u, current_header_table_size());
+
+ // C.5.3 Third Response
+ //
+ // Several header fields are evicted from the dynamic table during the
+ // processing of this header list.
+ //
+ // Header list to encode:
+ //
+ // :status: 200
+ // cache-control: private
+ // date: Mon, 21 Oct 2013 20:13:22 GMT
+ // location: https://www.example.com
+ // content-encoding: gzip
+ // set-cookie: foo=ASDJKHQKBZXOQWEOPIUAXQWEOIU; max-age=3600; version=1
+
+ SendStartAndVerifyCallback();
+ SendIndexAndVerifyCallback(8, HpackEntryType::kIndexedHeader, ":status",
+ "200");
+ SendIndexAndVerifyCallback(65, HpackEntryType::kIndexedHeader,
+ "cache-control", "private");
+ SendValueAndVerifyCallback(33, HpackEntryType::kIndexedLiteralHeader, "date",
+ "Mon, 21 Oct 2013 20:13:22 GMT", BUFFERED);
+ SendIndexAndVerifyCallback(64, HpackEntryType::kIndexedHeader, "location",
+ "https://www.example.com");
+ SendValueAndVerifyCallback(26, HpackEntryType::kIndexedLiteralHeader,
+ "content-encoding", "gzip", UNBUFFERED);
+ SendValueAndVerifyCallback(
+ 55, HpackEntryType::kIndexedLiteralHeader, "set-cookie",
+ "foo=ASDJKHQKBZXOQWEOPIUAXQWEOIU; max-age=3600; version=1", BUFFERED);
+ SendEndAndVerifyCallback();
+
+ // Dynamic Table (after decoding):
+ //
+ // [ 1] (s = 98) set-cookie: foo=ASDJKHQKBZXOQWEOPIUAXQWEOIU;
+ // max-age=3600; version=1
+ // [ 2] (s = 52) content-encoding: gzip
+ // [ 3] (s = 65) date: Mon, 21 Oct 2013 20:13:22 GMT
+ // Table size: 215
+
+ ASSERT_TRUE(VerifyDynamicTableContents(
+ {{"set-cookie",
+ "foo=ASDJKHQKBZXOQWEOPIUAXQWEOIU; max-age=3600; version=1"},
+ {"content-encoding", "gzip"},
+ {"date", "Mon, 21 Oct 2013 20:13:22 GMT"}}));
+ ASSERT_EQ(215u, current_header_table_size());
+}
+
+// Confirm that the table size can be changed, but at most twice.
+TEST_F(HpackDecoderStateTest, OptionalTableSizeChanges) {
+ SendStartAndVerifyCallback();
+ EXPECT_EQ(Http2SettingsInfo::DefaultHeaderTableSize(),
+ header_table_size_limit());
+ SendSizeUpdate(1024);
+ EXPECT_EQ(1024u, header_table_size_limit());
+ SendSizeUpdate(0);
+ EXPECT_EQ(0u, header_table_size_limit());
+
+ // Three updates aren't allowed.
+ EXPECT_CALL(listener_,
+ OnHeaderErrorDetected(HasSubstr("size update not allowed")));
+ SendSizeUpdate(0);
+}
+
+// Confirm that required size updates are indeed required before headers.
+TEST_F(HpackDecoderStateTest, RequiredTableSizeChangeBeforeHeader) {
+ decoder_state_.ApplyHeaderTableSizeSetting(1024);
+ decoder_state_.ApplyHeaderTableSizeSetting(2048);
+
+ // First provide the required update, and an allowed second update.
+ SendStartAndVerifyCallback();
+ EXPECT_EQ(Http2SettingsInfo::DefaultHeaderTableSize(),
+ header_table_size_limit());
+ SendSizeUpdate(1024);
+ EXPECT_EQ(1024u, header_table_size_limit());
+ SendSizeUpdate(1500);
+ EXPECT_EQ(1500u, header_table_size_limit());
+ SendEndAndVerifyCallback();
+
+ // Another HPACK block, but this time missing the required size update.
+ decoder_state_.ApplyHeaderTableSizeSetting(1024);
+ SendStartAndVerifyCallback();
+ EXPECT_CALL(listener_, OnHeaderErrorDetected(
+ HasSubstr("Missing dynamic table size update")));
+ decoder_state_.OnIndexedHeader(1);
+
+ // Further decoded entries are ignored.
+ decoder_state_.OnIndexedHeader(1);
+ decoder_state_.OnDynamicTableSizeUpdate(1);
+ SetValue("value", UNBUFFERED);
+ decoder_state_.OnNameIndexAndLiteralValue(
+ HpackEntryType::kIndexedLiteralHeader, 4, &value_buffer_);
+ SetName("name", UNBUFFERED);
+ decoder_state_.OnLiteralNameAndValue(HpackEntryType::kIndexedLiteralHeader,
+ &name_buffer_, &value_buffer_);
+ decoder_state_.OnHeaderBlockEnd();
+ decoder_state_.OnHpackDecodeError("NOT FORWARDED");
+}
+
+// Confirm that required size updates are validated.
+TEST_F(HpackDecoderStateTest, InvalidRequiredSizeUpdate) {
+ // Require a size update, but provide one that isn't small enough.
+ decoder_state_.ApplyHeaderTableSizeSetting(1024);
+ SendStartAndVerifyCallback();
+ EXPECT_EQ(Http2SettingsInfo::DefaultHeaderTableSize(),
+ header_table_size_limit());
+ EXPECT_CALL(listener_,
+ OnHeaderErrorDetected(HasSubstr("above low water mark")));
+ SendSizeUpdate(2048);
+}
+
+// Confirm that required size updates are indeed required before the end.
+TEST_F(HpackDecoderStateTest, RequiredTableSizeChangeBeforeEnd) {
+ decoder_state_.ApplyHeaderTableSizeSetting(1024);
+ SendStartAndVerifyCallback();
+ EXPECT_CALL(listener_, OnHeaderErrorDetected(
+ HasSubstr("Missing dynamic table size update")));
+ decoder_state_.OnHeaderBlockEnd();
+}
+
+// Confirm that optional size updates are validated.
+TEST_F(HpackDecoderStateTest, InvalidOptionalSizeUpdate) {
+ // Require a size update, but provide one that isn't small enough.
+ SendStartAndVerifyCallback();
+ EXPECT_EQ(Http2SettingsInfo::DefaultHeaderTableSize(),
+ header_table_size_limit());
+ EXPECT_CALL(listener_,
+ OnHeaderErrorDetected(HasSubstr("size update is above")));
+ SendSizeUpdate(Http2SettingsInfo::DefaultHeaderTableSize() + 1);
+}
+
+TEST_F(HpackDecoderStateTest, InvalidStaticIndex) {
+ SendStartAndVerifyCallback();
+ EXPECT_CALL(listener_, OnHeaderErrorDetected(HasSubstr("Invalid index")));
+ decoder_state_.OnIndexedHeader(0);
+}
+
+TEST_F(HpackDecoderStateTest, InvalidDynamicIndex) {
+ SendStartAndVerifyCallback();
+ EXPECT_CALL(listener_, OnHeaderErrorDetected(HasSubstr("Invalid index")));
+ decoder_state_.OnIndexedHeader(kFirstDynamicTableIndex);
+}
+
+TEST_F(HpackDecoderStateTest, InvalidNameIndex) {
+ SendStartAndVerifyCallback();
+ EXPECT_CALL(listener_,
+ OnHeaderErrorDetected(HasSubstr("Invalid name index")));
+ SetValue("value", UNBUFFERED);
+ decoder_state_.OnNameIndexAndLiteralValue(
+ HpackEntryType::kIndexedLiteralHeader, kFirstDynamicTableIndex,
+ &value_buffer_);
+}
+
+TEST_F(HpackDecoderStateTest, ErrorsSuppressCallbacks) {
+ SendStartAndVerifyCallback();
+ EXPECT_CALL(listener_,
+ OnHeaderErrorDetected(StringPiece("Huffman decode error.")));
+ decoder_state_.OnHpackDecodeError("Huffman decode error.");
+
+ // Further decoded entries are ignored.
+ decoder_state_.OnIndexedHeader(1);
+ decoder_state_.OnDynamicTableSizeUpdate(1);
+ SetValue("value", UNBUFFERED);
+ decoder_state_.OnNameIndexAndLiteralValue(
+ HpackEntryType::kIndexedLiteralHeader, 4, &value_buffer_);
+ SetName("name", UNBUFFERED);
+ decoder_state_.OnLiteralNameAndValue(HpackEntryType::kIndexedLiteralHeader,
+ &name_buffer_, &value_buffer_);
+ decoder_state_.OnHeaderBlockEnd();
+ decoder_state_.OnHpackDecodeError("NOT FORWARDED");
+}
+
+} // namespace
+} // namespace test
+} // namespace net
diff --git a/chromium/net/http2/hpack/decoder/hpack_decoder_string_buffer.cc b/chromium/net/http2/hpack/decoder/hpack_decoder_string_buffer.cc
new file mode 100644
index 00000000000..346a862fe46
--- /dev/null
+++ b/chromium/net/http2/hpack/decoder/hpack_decoder_string_buffer.cc
@@ -0,0 +1,225 @@
+// Copyright 2016 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.
+
+#include "net/http2/hpack/decoder/hpack_decoder_string_buffer.h"
+
+#include <utility>
+
+#include "base/logging.h"
+
+using base::StringPiece;
+using std::string;
+
+namespace net {
+
+std::ostream& operator<<(std::ostream& out,
+ const HpackDecoderStringBuffer::State v) {
+ switch (v) {
+ case HpackDecoderStringBuffer::State::RESET:
+ return out << "RESET";
+ case HpackDecoderStringBuffer::State::COLLECTING:
+ return out << "COLLECTING";
+ case HpackDecoderStringBuffer::State::COMPLETE:
+ return out << "COMPLETE";
+ default:
+ return out << "Unknown HpackDecoderStringBuffer::State!";
+ }
+}
+
+std::ostream& operator<<(std::ostream& out,
+ const HpackDecoderStringBuffer::Backing v) {
+ switch (v) {
+ case HpackDecoderStringBuffer::Backing::RESET:
+ return out << "RESET";
+ case HpackDecoderStringBuffer::Backing::UNBUFFERED:
+ return out << "UNBUFFERED";
+ case HpackDecoderStringBuffer::Backing::BUFFERED:
+ return out << "BUFFERED";
+ case HpackDecoderStringBuffer::Backing::STATIC:
+ return out << "STATIC";
+ default:
+ return out << "Unknown HpackDecoderStringBuffer::Backing!";
+ }
+}
+
+HpackDecoderStringBuffer::HpackDecoderStringBuffer()
+ : remaining_len_(0),
+ is_huffman_encoded_(false),
+ state_(State::RESET),
+ backing_(Backing::RESET) {}
+HpackDecoderStringBuffer::~HpackDecoderStringBuffer() {}
+
+void HpackDecoderStringBuffer::Reset() {
+ DVLOG(3) << "HpackDecoderStringBuffer::Reset";
+ state_ = State::RESET;
+}
+
+void HpackDecoderStringBuffer::Set(StringPiece value, bool is_static) {
+ DVLOG(2) << "HpackDecoderStringBuffer::Set";
+ DCHECK_EQ(state_, State::RESET);
+ value_ = value;
+ state_ = State::COMPLETE;
+ backing_ = is_static ? Backing::STATIC : Backing::UNBUFFERED;
+ // TODO(jamessynge): Determine which of these two fields must be set.
+ remaining_len_ = 0;
+ is_huffman_encoded_ = false;
+}
+
+void HpackDecoderStringBuffer::OnStart(bool huffman_encoded, size_t len) {
+ DVLOG(2) << "HpackDecoderStringBuffer::OnStart";
+ DCHECK_EQ(state_, State::RESET);
+
+ remaining_len_ = len;
+ is_huffman_encoded_ = huffman_encoded;
+ state_ = State::COLLECTING;
+
+ if (huffman_encoded) {
+ // We don't set, clear or use value_ for buffered strings until OnEnd.
+ decoder_.Reset();
+ buffer_.clear();
+ backing_ = Backing::BUFFERED;
+
+ // Reserve space in buffer_ for the uncompressed string, assuming the
+ // maximum expansion. The shortest Huffman codes in the RFC are 5 bits long,
+ // which then expand to 8 bits during decoding (i.e. each code is for one
+ // plain text octet, aka byte), so the maximum size is 60% longer than the
+ // encoded size.
+ len = len * 8 / 5;
+ if (buffer_.capacity() < len) {
+ buffer_.reserve(len);
+ }
+ } else {
+ // Assume for now that we won't need to use buffer_, so don't reserve space
+ // in it.
+ backing_ = Backing::RESET;
+ // OnData is not called for empty (zero length) strings, so make sure that
+ // value_ is cleared.
+ value_ = StringPiece();
+ }
+}
+
+bool HpackDecoderStringBuffer::OnData(const char* data, size_t len) {
+ DVLOG(2) << "HpackDecoderStringBuffer::OnData state=" << state_
+ << ", backing=" << backing_;
+ DCHECK_EQ(state_, State::COLLECTING);
+ DCHECK_LE(len, remaining_len_);
+ remaining_len_ -= len;
+
+ if (is_huffman_encoded_) {
+ DCHECK_EQ(backing_, Backing::BUFFERED);
+ return decoder_.Decode(StringPiece(data, len), &buffer_);
+ }
+
+ if (backing_ == Backing::RESET) {
+ // This is the first call to OnData. If data contains the entire string,
+ // don't copy the string. If we later find that the HPACK entry is split
+ // across input buffers, then we'll copy the string into buffer_.
+ if (remaining_len_ == 0) {
+ value_ = StringPiece(data, len);
+ backing_ = Backing::UNBUFFERED;
+ return true;
+ }
+
+ // We need to buffer the string because it is split across input buffers.
+ // Reserve space in buffer_ for the entire string.
+ backing_ = Backing::BUFFERED;
+ buffer_.reserve(remaining_len_ + len);
+ buffer_.assign(data, len);
+ return true;
+ }
+
+ // This is not the first call to OnData for this string, so it should be
+ // buffered.
+ DCHECK_EQ(backing_, Backing::BUFFERED);
+
+ // Append to the current contents of the buffer.
+ buffer_.append(data, len);
+ return true;
+}
+
+bool HpackDecoderStringBuffer::OnEnd() {
+ DVLOG(2) << "HpackDecoderStringBuffer::OnEnd";
+ DCHECK_EQ(state_, State::COLLECTING);
+ DCHECK_EQ(0u, remaining_len_);
+
+ if (is_huffman_encoded_) {
+ DCHECK_EQ(backing_, Backing::BUFFERED);
+ // Did the Huffman encoding of the string end properly?
+ if (!decoder_.InputProperlyTerminated()) {
+ return false; // No, it didn't.
+ }
+ value_ = buffer_;
+ } else if (backing_ == Backing::BUFFERED) {
+ value_ = buffer_;
+ }
+ state_ = State::COMPLETE;
+ return true;
+}
+
+void HpackDecoderStringBuffer::BufferStringIfUnbuffered() {
+ DVLOG(3) << "HpackDecoderStringBuffer::BufferStringIfUnbuffered state="
+ << state_ << ", backing=" << backing_;
+ if (state_ != State::RESET && backing_ == Backing::UNBUFFERED) {
+ DVLOG(2) << "HpackDecoderStringBuffer buffering string of length "
+ << value_.size();
+ value_.CopyToString(&buffer_);
+ if (state_ == State::COMPLETE) {
+ value_ = buffer_;
+ }
+ backing_ = Backing::BUFFERED;
+ }
+}
+
+bool HpackDecoderStringBuffer::IsBuffered() const {
+ DVLOG(3) << "HpackDecoderStringBuffer::IsBuffered";
+ return state_ != State::RESET && backing_ == Backing::BUFFERED;
+}
+
+size_t HpackDecoderStringBuffer::BufferedLength() const {
+ DVLOG(3) << "HpackDecoderStringBuffer::BufferedLength";
+ return IsBuffered() ? buffer_.size() : 0;
+}
+
+StringPiece HpackDecoderStringBuffer::str() const {
+ DVLOG(3) << "HpackDecoderStringBuffer::str";
+ DCHECK_EQ(state_, State::COMPLETE);
+ return value_;
+}
+
+string HpackDecoderStringBuffer::ReleaseString() {
+ DVLOG(3) << "HpackDecoderStringBuffer::ReleaseString";
+ DCHECK_EQ(state_, State::COMPLETE);
+ DCHECK_EQ(backing_, Backing::BUFFERED);
+ if (state_ == State::COMPLETE) {
+ state_ = State::RESET;
+ if (backing_ == Backing::BUFFERED) {
+ return std::move(buffer_);
+ } else {
+ return value_.as_string();
+ }
+ }
+ return "";
+}
+
+void HpackDecoderStringBuffer::OutputDebugStringTo(std::ostream& out) const {
+ out << "{state=" << state_;
+ if (state_ != State::RESET) {
+ out << ", backing=" << backing_;
+ out << ", remaining_len=" << remaining_len_;
+ out << ", is_huffman_encoded=" << is_huffman_encoded_;
+ if (backing_ == Backing::BUFFERED) {
+ out << ", buffer: " << buffer_;
+ } else {
+ out << ", value: " << value_;
+ }
+ }
+ out << "}";
+}
+
+std::ostream& operator<<(std::ostream& out, const HpackDecoderStringBuffer& v) {
+ v.OutputDebugStringTo(out);
+ return out;
+}
+
+} // namespace net
diff --git a/chromium/net/http2/hpack/decoder/hpack_decoder_string_buffer.h b/chromium/net/http2/hpack/decoder/hpack_decoder_string_buffer.h
new file mode 100644
index 00000000000..85449415860
--- /dev/null
+++ b/chromium/net/http2/hpack/decoder/hpack_decoder_string_buffer.h
@@ -0,0 +1,97 @@
+// Copyright 2016 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.
+
+#ifndef NET_HTTP2_HPACK_DECODER_HPACK_DECODER_STRING_BUFFER_H_
+#define NET_HTTP2_HPACK_DECODER_HPACK_DECODER_STRING_BUFFER_H_
+
+// HpackDecoderStringBuffer helps an HPACK decoder to avoid copies of a string
+// literal (name or value) except when necessary (e.g. when split across two
+// or more HPACK block fragments).
+
+#include <stddef.h>
+
+#include <ostream>
+#include <string>
+
+#include "base/macros.h"
+#include "base/strings/string_piece.h"
+#include "net/base/net_export.h"
+#include "net/http2/hpack/huffman/http2_hpack_huffman_decoder.h"
+
+namespace net {
+
+class NET_EXPORT_PRIVATE HpackDecoderStringBuffer {
+ public:
+ enum class State : uint8_t { RESET, COLLECTING, COMPLETE };
+ enum class Backing : uint8_t { RESET, UNBUFFERED, BUFFERED, STATIC };
+
+ HpackDecoderStringBuffer();
+ ~HpackDecoderStringBuffer();
+
+ void Reset();
+ void Set(base::StringPiece value, bool is_static);
+
+ // Note that for Huffman encoded strings the length of the string after
+ // decoding may be larger (expected), the same or even smaller; the latter
+ // are unlikely, but possible if the encoder makes odd choices.
+ void OnStart(bool huffman_encoded, size_t len);
+ bool OnData(const char* data, size_t len);
+ bool OnEnd();
+ void BufferStringIfUnbuffered();
+ bool IsBuffered() const;
+ size_t BufferedLength() const;
+
+ // Accessors for the completely collected string (i.e. Set or OnEnd has just
+ // been called, and no reset of the state has occurred).
+
+ // Returns a StringPiece pointing to the backing store for the string, either
+ // the internal buffer or the original transport buffer (e.g. for a literal
+ // value that wasn't Huffman encoded, and that wasn't split across transport
+ // buffers).
+ base::StringPiece str() const;
+
+ // Returns the completely collected string by value, using std::move in an
+ // effort to avoid unnecessary copies. ReleaseString() must not be called
+ // unless the string has been buffered (to avoid forcing a potentially
+ // unnecessary copy). ReleaseString() also resets the instance so that it can
+ // be used to collect another string.
+ std::string ReleaseString();
+
+ State state_for_testing() const { return state_; }
+ Backing backing_for_testing() const { return backing_; }
+ void OutputDebugStringTo(std::ostream& out) const;
+
+ private:
+ // Storage for the string being buffered, if buffering is necessary
+ // (e.g. if Huffman encoded, buffer_ is storage for the decoded string).
+ std::string buffer_;
+
+ // The StringPiece to be returned by HpackDecoderStringBuffer::str(). If a
+ // string has been collected, but not buffered, value_ points to that string.
+ base::StringPiece value_;
+
+ // The decoder to use if the string is Huffman encoded.
+ HpackHuffmanDecoder decoder_;
+
+ // Count of bytes not yet passed to OnData.
+ size_t remaining_len_;
+
+ // Is the HPACK string Huffman encoded?
+ bool is_huffman_encoded_;
+
+ // State of the string decoding process.
+ State state_;
+
+ // Where is the string stored?
+ Backing backing_;
+
+ DISALLOW_COPY_AND_ASSIGN(HpackDecoderStringBuffer);
+};
+
+NET_EXPORT_PRIVATE std::ostream& operator<<(std::ostream& out,
+ const HpackDecoderStringBuffer& v);
+
+} // namespace net
+
+#endif // NET_HTTP2_HPACK_DECODER_HPACK_DECODER_STRING_BUFFER_H_
diff --git a/chromium/net/http2/hpack/decoder/hpack_decoder_string_buffer_test.cc b/chromium/net/http2/hpack/decoder/hpack_decoder_string_buffer_test.cc
new file mode 100644
index 00000000000..1efb113c31e
--- /dev/null
+++ b/chromium/net/http2/hpack/decoder/hpack_decoder_string_buffer_test.cc
@@ -0,0 +1,254 @@
+// Copyright 2016 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.
+
+#include "net/http2/hpack/decoder/hpack_decoder_string_buffer.h"
+
+// Tests of HpackDecoderStringBuffer.
+
+#include <sstream>
+#include <string>
+
+#include "base/logging.h"
+#include "base/strings/string_piece.h"
+#include "net/http2/tools/failure.h"
+#include "net/spdy/spdy_test_utils.h"
+#include "testing/gmock/include/gmock/gmock.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+using ::testing::AssertionResult;
+using ::testing::AssertionSuccess;
+using ::testing::HasSubstr;
+using base::StringPiece;
+using std::string;
+
+namespace net {
+namespace test {
+namespace {
+
+class HpackDecoderStringBufferTest : public ::testing::Test {
+ protected:
+ typedef HpackDecoderStringBuffer::State State;
+ typedef HpackDecoderStringBuffer::Backing Backing;
+
+ State state() const { return buf_.state_for_testing(); }
+ Backing backing() const { return buf_.backing_for_testing(); }
+
+ // We want to know that LOG(x) << buf_ will work in production should that
+ // be needed, so we test that it outputs the expected values.
+ AssertionResult VerifyLogHasSubstrs(std::initializer_list<string> strs) {
+ VLOG(1) << buf_;
+ std::ostringstream ss;
+ buf_.OutputDebugStringTo(ss);
+ string dbg_str(ss.str());
+ for (const auto& expected : strs) {
+ VERIFY_THAT(dbg_str, HasSubstr(expected));
+ }
+ return AssertionSuccess();
+ }
+
+ HpackDecoderStringBuffer buf_;
+};
+
+TEST_F(HpackDecoderStringBufferTest, SetStatic) {
+ StringPiece data("static string");
+
+ EXPECT_EQ(state(), State::RESET);
+ EXPECT_TRUE(VerifyLogHasSubstrs({"state=RESET"}));
+
+ buf_.Set(data, /*is_static*/ true);
+ LOG(INFO) << buf_;
+ EXPECT_EQ(state(), State::COMPLETE);
+ EXPECT_EQ(backing(), Backing::STATIC);
+ EXPECT_EQ(data, buf_.str());
+ EXPECT_EQ(data.data(), buf_.str().data());
+ EXPECT_TRUE(VerifyLogHasSubstrs(
+ {"state=COMPLETE", "backing=STATIC", "value: static string"}));
+
+ // The string is static, so BufferStringIfUnbuffered won't change anything.
+ buf_.BufferStringIfUnbuffered();
+ EXPECT_EQ(state(), State::COMPLETE);
+ EXPECT_EQ(backing(), Backing::STATIC);
+ EXPECT_EQ(data, buf_.str());
+ EXPECT_EQ(data.data(), buf_.str().data());
+ EXPECT_TRUE(VerifyLogHasSubstrs(
+ {"state=COMPLETE", "backing=STATIC", "value: static string"}));
+}
+
+TEST_F(HpackDecoderStringBufferTest, PlainWhole) {
+ StringPiece data("some text.");
+
+ LOG(INFO) << buf_;
+ EXPECT_EQ(state(), State::RESET);
+
+ buf_.OnStart(/*huffman_encoded*/ false, data.size());
+ EXPECT_EQ(state(), State::COLLECTING);
+ EXPECT_EQ(backing(), Backing::RESET);
+ LOG(INFO) << buf_;
+
+ EXPECT_TRUE(buf_.OnData(data.data(), data.size()));
+ EXPECT_EQ(state(), State::COLLECTING);
+ EXPECT_EQ(backing(), Backing::UNBUFFERED);
+
+ EXPECT_TRUE(buf_.OnEnd());
+ EXPECT_EQ(state(), State::COMPLETE);
+ EXPECT_EQ(backing(), Backing::UNBUFFERED);
+ EXPECT_EQ(0u, buf_.BufferedLength());
+ EXPECT_TRUE(VerifyLogHasSubstrs(
+ {"state=COMPLETE", "backing=UNBUFFERED", "value: some text."}));
+
+ // We expect that the string buffer points to the passed in StringPiece's
+ // backing store.
+ EXPECT_EQ(data.data(), buf_.str().data());
+
+ // Now force it to buffer the string, after which it will still have the same
+ // string value, but the backing store will be different.
+ buf_.BufferStringIfUnbuffered();
+ LOG(INFO) << buf_;
+ EXPECT_EQ(backing(), Backing::BUFFERED);
+ EXPECT_EQ(buf_.BufferedLength(), data.size());
+ EXPECT_EQ(data, buf_.str());
+ EXPECT_NE(data.data(), buf_.str().data());
+ EXPECT_TRUE(VerifyLogHasSubstrs(
+ {"state=COMPLETE", "backing=BUFFERED", "buffer: some text."}));
+}
+
+TEST_F(HpackDecoderStringBufferTest, PlainSplit) {
+ StringPiece data("some text.");
+ StringPiece part1 = data.substr(0, 1);
+ StringPiece part2 = data.substr(1);
+
+ EXPECT_EQ(state(), State::RESET);
+ buf_.OnStart(/*huffman_encoded*/ false, data.size());
+ EXPECT_EQ(state(), State::COLLECTING);
+ EXPECT_EQ(backing(), Backing::RESET);
+
+ // OnData with only a part of the data, not the whole, so buf_ will buffer
+ // the data.
+ EXPECT_TRUE(buf_.OnData(part1.data(), part1.size()));
+ EXPECT_EQ(state(), State::COLLECTING);
+ EXPECT_EQ(backing(), Backing::BUFFERED);
+ EXPECT_EQ(buf_.BufferedLength(), part1.size());
+ LOG(INFO) << buf_;
+
+ EXPECT_TRUE(buf_.OnData(part2.data(), part2.size()));
+ EXPECT_EQ(state(), State::COLLECTING);
+ EXPECT_EQ(backing(), Backing::BUFFERED);
+ EXPECT_EQ(buf_.BufferedLength(), data.size());
+
+ EXPECT_TRUE(buf_.OnEnd());
+ EXPECT_EQ(state(), State::COMPLETE);
+ EXPECT_EQ(backing(), Backing::BUFFERED);
+ EXPECT_EQ(buf_.BufferedLength(), data.size());
+ LOG(INFO) << buf_;
+
+ StringPiece buffered = buf_.str();
+ EXPECT_EQ(data, buffered);
+ EXPECT_NE(data.data(), buffered.data());
+
+ // The string is already buffered, so BufferStringIfUnbuffered should not make
+ // any change.
+ buf_.BufferStringIfUnbuffered();
+ EXPECT_EQ(backing(), Backing::BUFFERED);
+ EXPECT_EQ(buf_.BufferedLength(), data.size());
+ EXPECT_EQ(buffered, buf_.str());
+ EXPECT_EQ(buffered.data(), buf_.str().data());
+}
+
+TEST_F(HpackDecoderStringBufferTest, HuffmanWhole) {
+ string encoded = a2b_hex("f1e3c2e5f23a6ba0ab90f4ff");
+ StringPiece decoded("www.example.com");
+
+ EXPECT_EQ(state(), State::RESET);
+ buf_.OnStart(/*huffman_encoded*/ true, encoded.size());
+ EXPECT_EQ(state(), State::COLLECTING);
+
+ EXPECT_TRUE(buf_.OnData(encoded.data(), encoded.size()));
+ EXPECT_EQ(state(), State::COLLECTING);
+ EXPECT_EQ(backing(), Backing::BUFFERED);
+
+ EXPECT_TRUE(buf_.OnEnd());
+ EXPECT_EQ(state(), State::COMPLETE);
+ EXPECT_EQ(backing(), Backing::BUFFERED);
+ EXPECT_EQ(buf_.BufferedLength(), decoded.size());
+ EXPECT_EQ(decoded, buf_.str());
+ EXPECT_TRUE(VerifyLogHasSubstrs(
+ {"{state=COMPLETE", "backing=BUFFERED", "buffer: www.example.com}"}));
+
+ string s = buf_.ReleaseString();
+ EXPECT_EQ(s, decoded);
+ EXPECT_EQ(state(), State::RESET);
+}
+
+TEST_F(HpackDecoderStringBufferTest, HuffmanSplit) {
+ string encoded = a2b_hex("f1e3c2e5f23a6ba0ab90f4ff");
+ string part1 = encoded.substr(0, 5);
+ string part2 = encoded.substr(5);
+ StringPiece decoded("www.example.com");
+
+ EXPECT_EQ(state(), State::RESET);
+ buf_.OnStart(/*huffman_encoded*/ true, encoded.size());
+ EXPECT_EQ(state(), State::COLLECTING);
+ EXPECT_EQ(backing(), Backing::BUFFERED);
+ EXPECT_EQ(0u, buf_.BufferedLength());
+ LOG(INFO) << buf_;
+
+ EXPECT_TRUE(buf_.OnData(part1.data(), part1.size()));
+ EXPECT_EQ(state(), State::COLLECTING);
+ EXPECT_EQ(backing(), Backing::BUFFERED);
+ EXPECT_GT(buf_.BufferedLength(), 0u);
+ EXPECT_LT(buf_.BufferedLength(), decoded.size());
+ LOG(INFO) << buf_;
+
+ EXPECT_TRUE(buf_.OnData(part2.data(), part2.size()));
+ EXPECT_EQ(state(), State::COLLECTING);
+ EXPECT_EQ(backing(), Backing::BUFFERED);
+ EXPECT_EQ(buf_.BufferedLength(), decoded.size());
+ LOG(INFO) << buf_;
+
+ EXPECT_TRUE(buf_.OnEnd());
+ EXPECT_EQ(state(), State::COMPLETE);
+ EXPECT_EQ(backing(), Backing::BUFFERED);
+ EXPECT_EQ(buf_.BufferedLength(), decoded.size());
+ EXPECT_EQ(decoded, buf_.str());
+ LOG(INFO) << buf_;
+
+ buf_.Reset();
+ EXPECT_EQ(state(), State::RESET);
+ LOG(INFO) << buf_;
+}
+
+TEST_F(HpackDecoderStringBufferTest, InvalidHuffmanOnData) {
+ // Explicitly encode the End-of-String symbol, a no-no.
+ string encoded = a2b_hex("ffffffff");
+
+ buf_.OnStart(/*huffman_encoded*/ true, encoded.size());
+ EXPECT_EQ(state(), State::COLLECTING);
+
+ EXPECT_FALSE(buf_.OnData(encoded.data(), encoded.size()));
+ EXPECT_EQ(state(), State::COLLECTING);
+ EXPECT_EQ(backing(), Backing::BUFFERED);
+
+ LOG(INFO) << buf_;
+}
+
+TEST_F(HpackDecoderStringBufferTest, InvalidHuffmanOnEnd) {
+ // Last byte of string doesn't end with prefix of End-of-String symbol.
+ string encoded = a2b_hex("00");
+
+ buf_.OnStart(/*huffman_encoded*/ true, encoded.size());
+ EXPECT_EQ(state(), State::COLLECTING);
+
+ EXPECT_TRUE(buf_.OnData(encoded.data(), encoded.size()));
+ EXPECT_EQ(state(), State::COLLECTING);
+ EXPECT_EQ(backing(), Backing::BUFFERED);
+
+ EXPECT_FALSE(buf_.OnEnd());
+ LOG(INFO) << buf_;
+}
+
+// TODO(jamessynge): Add tests for ReleaseString().
+
+} // namespace
+} // namespace test
+} // namespace net
diff --git a/chromium/net/http2/hpack/decoder/hpack_decoder_tables.cc b/chromium/net/http2/hpack/decoder/hpack_decoder_tables.cc
new file mode 100644
index 00000000000..d31573a7198
--- /dev/null
+++ b/chromium/net/http2/hpack/decoder/hpack_decoder_tables.cc
@@ -0,0 +1,118 @@
+// Copyright 2016 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.
+
+#include "net/http2/hpack/decoder/hpack_decoder_tables.h"
+
+#include "base/logging.h"
+
+namespace net {
+namespace {
+
+std::vector<HpackStringPair>* MakeStaticTable() {
+ auto ptr = new std::vector<HpackStringPair>();
+ ptr->reserve(kFirstDynamicTableIndex);
+ ptr->emplace_back("", "");
+
+#define STATIC_TABLE_ENTRY(name, value, index) \
+ DCHECK_EQ(ptr->size(), index); \
+ ptr->emplace_back(name, value)
+
+#include "net/http2/hpack/hpack_static_table_entries.inc"
+
+#undef STATIC_TABLE_ENTRY
+
+ return ptr;
+}
+
+const std::vector<HpackStringPair>* GetStaticTable() {
+ static const std::vector<HpackStringPair>* const g_static_table =
+ MakeStaticTable();
+ return g_static_table;
+}
+
+} // namespace
+
+HpackDecoderStaticTable::HpackDecoderStaticTable(
+ const std::vector<HpackStringPair>* table)
+ : table_(table) {}
+
+HpackDecoderStaticTable::HpackDecoderStaticTable() : table_(GetStaticTable()) {}
+
+const HpackStringPair* HpackDecoderStaticTable::Lookup(size_t index) const {
+ if (0 < index && index < kFirstDynamicTableIndex) {
+ return &((*table_)[index]);
+ }
+ return nullptr;
+}
+
+HpackDecoderDynamicTable::HpackDecoderDynamicTable() {}
+HpackDecoderDynamicTable::~HpackDecoderDynamicTable() {}
+
+void HpackDecoderDynamicTable::DynamicTableSizeUpdate(size_t size_limit) {
+ DVLOG(3) << "HpackDecoderDynamicTable::DynamicTableSizeUpdate " << size_limit;
+ EnsureSizeNoMoreThan(size_limit);
+ DCHECK_LE(current_size_, size_limit);
+ size_limit_ = size_limit;
+}
+
+// TODO(jamessynge): Check somewhere before here that names received from the
+// peer are valid (e.g. are lower-case, no whitespace, etc.).
+bool HpackDecoderDynamicTable::Insert(const HpackString& name,
+ const HpackString& value) {
+ HpackStringPair p(name, value);
+ size_t entry_size = p.size();
+ DVLOG(2) << "InsertEntry of size=" << entry_size << "\n name: " << name
+ << "\n value: " << value;
+ if (entry_size > size_limit_) {
+ DVLOG(2) << "InsertEntry: entry larger than table, removing "
+ << table_.size() << " entries, of total size " << current_size_
+ << " bytes.";
+ table_.clear();
+ current_size_ = 0;
+ return false; // Not inserted because too large.
+ }
+ size_t insert_limit = size_limit_ - entry_size;
+ EnsureSizeNoMoreThan(insert_limit);
+ table_.push_front(p);
+ current_size_ += entry_size;
+ DVLOG(2) << "InsertEntry: current_size_=" << current_size_;
+ DCHECK_GE(current_size_, entry_size);
+ DCHECK_LE(current_size_, size_limit_);
+ return true;
+}
+
+const HpackStringPair* HpackDecoderDynamicTable::Lookup(size_t index) const {
+ if (index < table_.size()) {
+ return &(table_[index]);
+ }
+ return nullptr;
+}
+
+void HpackDecoderDynamicTable::EnsureSizeNoMoreThan(size_t limit) {
+ DVLOG(2) << "EnsureSizeNoMoreThan limit=" << limit
+ << ", current_size_=" << current_size_;
+ // Not the most efficient choice, but any easy way to start.
+ while (current_size_ > limit) {
+ RemoveLastEntry();
+ }
+ DCHECK_LE(current_size_, limit);
+}
+
+void HpackDecoderDynamicTable::RemoveLastEntry() {
+ DCHECK(!table_.empty());
+ if (!table_.empty()) {
+ DVLOG(2) << "RemoveLastEntry current_size_=" << current_size_
+ << ", last entry size=" << table_.back().size();
+ DCHECK_GE(current_size_, table_.back().size());
+ current_size_ -= table_.back().size();
+ table_.pop_back();
+ // Empty IFF current_size_ == 0.
+ DCHECK_EQ(table_.empty(), current_size_ == 0);
+ }
+}
+
+HpackDecoderTables::HpackDecoderTables() {}
+HpackDecoderTables::~HpackDecoderTables() {}
+
+} // namespace net
diff --git a/chromium/net/http2/hpack/decoder/hpack_decoder_tables.h b/chromium/net/http2/hpack/decoder/hpack_decoder_tables.h
new file mode 100644
index 00000000000..58d315033e7
--- /dev/null
+++ b/chromium/net/http2/hpack/decoder/hpack_decoder_tables.h
@@ -0,0 +1,151 @@
+// Copyright 2016 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.
+
+#ifndef NET_HTTP2_HPACK_DECODER_HPACK_DECODER_TABLES_H_
+#define NET_HTTP2_HPACK_DECODER_HPACK_DECODER_TABLES_H_
+
+// Static and dynamic tables for the HPACK decoder. See:
+// http://httpwg.org/specs/rfc7541.html#indexing.tables
+
+// Note that the Lookup methods return nullptr if the requested index was not
+// found. This should be treated as a COMPRESSION error according to the HTTP/2
+// spec, which is a connection level protocol error (i.e. the connection must
+// be terminated). See these sections in the two RFCs:
+// http://httpwg.org/specs/rfc7541.html#indexed.header.representation
+// http://httpwg.org/specs/rfc7541.html#index.address.space
+// http://httpwg.org/specs/rfc7540.html#HeaderBlock
+
+#include <stddef.h>
+
+#include <deque>
+#include <vector>
+
+#include "base/macros.h"
+#include "net/base/net_export.h"
+#include "net/http2/hpack/hpack_string.h"
+#include "net/http2/http2_constants.h"
+
+namespace net {
+namespace test {
+class HpackDecoderTablesPeer;
+} // namespace test
+
+const size_t kFirstDynamicTableIndex = 62;
+
+// See http://httpwg.org/specs/rfc7541.html#static.table.definition for the
+// contents, and http://httpwg.org/specs/rfc7541.html#index.address.space for
+// info about accessing the static table.
+class NET_EXPORT_PRIVATE HpackDecoderStaticTable {
+ public:
+ explicit HpackDecoderStaticTable(const std::vector<HpackStringPair>* table);
+ // Uses a global table shared by all threads.
+ HpackDecoderStaticTable();
+
+ // If index is valid, returns a pointer to the entry, otherwise returns
+ // nullptr.
+ const HpackStringPair* Lookup(size_t index) const;
+
+ private:
+ friend class test::HpackDecoderTablesPeer;
+ const std::vector<HpackStringPair>* const table_;
+};
+
+// HpackDecoderDynamicTable implements HPACK compression feature "indexed
+// headers"; previously sent headers may be referenced later by their index
+// in the dynamic table. See these sections of the RFC:
+// http://httpwg.org/specs/rfc7541.html#dynamic.table
+// http://httpwg.org/specs/rfc7541.html#dynamic.table.management
+class NET_EXPORT_PRIVATE HpackDecoderDynamicTable {
+ public:
+ HpackDecoderDynamicTable();
+ ~HpackDecoderDynamicTable();
+
+ // Sets a new size limit, received from the peer; performs evictions if
+ // necessary to ensure that the current size does not exceed the new limit.
+ // The caller needs to have validated that size_limit does not
+ // exceed the acknowledged value of SETTINGS_HEADER_TABLE_SIZE.
+ void DynamicTableSizeUpdate(size_t size_limit);
+
+ // Returns true if inserted, false if too large (at which point the
+ // dynamic table will be empty.)
+ bool Insert(const HpackString& name, const HpackString& value);
+
+ // If index is valid, returns a pointer to the entry, otherwise returns
+ // nullptr.
+ const HpackStringPair* Lookup(size_t index) const;
+
+ size_t size_limit() const { return size_limit_; }
+ size_t current_size() const { return current_size_; }
+
+ private:
+ friend class test::HpackDecoderTablesPeer;
+
+ // Drop older entries to ensure the size is not greater than limit.
+ void EnsureSizeNoMoreThan(size_t limit);
+
+ // Removes the oldest dynamic table entry.
+ void RemoveLastEntry();
+
+ // The last received DynamicTableSizeUpdate value, initialized to
+ // SETTINGS_HEADER_TABLE_SIZE.
+ size_t size_limit_ = Http2SettingsInfo::DefaultHeaderTableSize();
+
+ size_t current_size_ = 0;
+
+ std::deque<HpackStringPair> table_;
+
+ DISALLOW_COPY_AND_ASSIGN(HpackDecoderDynamicTable);
+};
+
+class NET_EXPORT_PRIVATE HpackDecoderTables {
+ public:
+ HpackDecoderTables();
+ ~HpackDecoderTables();
+
+ // Sets a new size limit, received from the peer; performs evictions if
+ // necessary to ensure that the current size does not exceed the new limit.
+ // The caller needs to have validated that size_limit does not
+ // exceed the acknowledged value of SETTINGS_HEADER_TABLE_SIZE.
+ void DynamicTableSizeUpdate(size_t size_limit) {
+ dynamic_table_.DynamicTableSizeUpdate(size_limit);
+ }
+
+ // Returns true if inserted, false if too large (at which point the
+ // dynamic table will be empty.)
+ // TODO(jamessynge): Add methods for moving the string(s) into the table,
+ // or for otherwise avoiding unnecessary copies.
+ bool Insert(const HpackString& name, const HpackString& value) {
+ return dynamic_table_.Insert(name, value);
+ }
+
+ // If index is valid, returns a pointer to the entry, otherwise returns
+ // nullptr.
+ const HpackStringPair* Lookup(size_t index) const {
+ if (index < kFirstDynamicTableIndex) {
+ return static_table_.Lookup(index);
+ } else {
+ return dynamic_table_.Lookup(index - kFirstDynamicTableIndex);
+ }
+ }
+
+ // The size limit that the peer (the HPACK encoder) has told the decoder it is
+ // currently operating with. Defaults to SETTINGS_HEADER_TABLE_SIZE, 4096.
+ size_t header_table_size_limit() const { return dynamic_table_.size_limit(); }
+
+ // Sum of the sizes of the dynamic table entries.
+ size_t current_header_table_size() const {
+ return dynamic_table_.current_size();
+ }
+
+ private:
+ friend class test::HpackDecoderTablesPeer;
+ HpackDecoderStaticTable static_table_;
+ HpackDecoderDynamicTable dynamic_table_;
+
+ DISALLOW_COPY_AND_ASSIGN(HpackDecoderTables);
+};
+
+} // namespace net
+
+#endif // NET_HTTP2_HPACK_DECODER_HPACK_DECODER_TABLES_H_
diff --git a/chromium/net/http2/hpack/decoder/hpack_decoder_tables_test.cc b/chromium/net/http2/hpack/decoder/hpack_decoder_tables_test.cc
new file mode 100644
index 00000000000..13bdb6f0a96
--- /dev/null
+++ b/chromium/net/http2/hpack/decoder/hpack_decoder_tables_test.cc
@@ -0,0 +1,265 @@
+// Copyright 2016 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.
+
+#include "net/http2/hpack/decoder/hpack_decoder_tables.h"
+
+#include <algorithm>
+#include <string>
+#include <tuple>
+#include <vector>
+
+#include "base/logging.h"
+#include "net/http2/tools/failure.h"
+#include "net/http2/tools/http2_random.h"
+#include "net/http2/tools/random_util.h"
+#include "testing/gmock/include/gmock/gmock.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+using ::testing::AssertionResult;
+using ::testing::AssertionSuccess;
+using std::string;
+
+namespace net {
+namespace test {
+class HpackDecoderTablesPeer {
+ public:
+ static size_t num_dynamic_entries(const HpackDecoderTables& tables) {
+ return tables.dynamic_table_.table_.size();
+ }
+};
+
+namespace {
+struct StaticEntry {
+ const char* name;
+ const char* value;
+ size_t index;
+};
+
+std::vector<StaticEntry> MakeSpecStaticEntries() {
+ std::vector<StaticEntry> static_entries;
+
+#define STATIC_TABLE_ENTRY(name, value, index) \
+ DCHECK_EQ(static_entries.size() + 1, index); \
+ static_entries.push_back({name, value, index});
+
+#include "net/http2/hpack/hpack_static_table_entries.inc"
+
+#undef STATIC_TABLE_ENTRY
+
+ return static_entries;
+}
+
+template <class C>
+void ShuffleCollection(C* collection, RandomBase* r) {
+ std::shuffle(collection->begin(), collection->end(), *r);
+}
+
+class HpackDecoderStaticTableTest : public ::testing::Test {
+ protected:
+ HpackDecoderStaticTableTest() {}
+
+ std::vector<StaticEntry> shuffled_static_entries() {
+ std::vector<StaticEntry> entries = MakeSpecStaticEntries();
+ ShuffleCollection(&entries, &random_);
+ return entries;
+ }
+
+ // This test is in a function so that it can be applied to both the static
+ // table and the combined static+dynamic tables.
+ AssertionResult VerifyStaticTableContents() {
+ for (const auto& expected : shuffled_static_entries()) {
+ const HpackStringPair* found = Lookup(expected.index);
+ VERIFY_NE(found, nullptr);
+ VERIFY_EQ(expected.name, found->name) << expected.index;
+ VERIFY_EQ(expected.value, found->value) << expected.index;
+ }
+
+ // There should be no entry with index 0.
+ VERIFY_EQ(nullptr, Lookup(0));
+ return AssertionSuccess();
+ }
+
+ virtual const HpackStringPair* Lookup(size_t index) {
+ return static_table_.Lookup(index);
+ }
+
+ RandomBase* RandomPtr() { return &random_; }
+
+ private:
+ Http2Random random_;
+ HpackDecoderStaticTable static_table_;
+};
+
+TEST_F(HpackDecoderStaticTableTest, StaticTableContents) {
+ EXPECT_TRUE(VerifyStaticTableContents());
+}
+
+size_t Size(const string& name, const string& value) {
+ return name.size() + value.size() + 32;
+}
+
+// To support tests with more than a few of hand crafted changes to the dynamic
+// table, we have another, exceedingly simple, implementation of the HPACK
+// dynamic table containing FakeHpackEntry instances. We can thus compare the
+// contents of the actual table with those in fake_dynamic_table_.
+
+typedef std::tuple<string, string, size_t> FakeHpackEntry;
+const string& Name(const FakeHpackEntry& entry) {
+ return std::get<0>(entry);
+}
+const string& Value(const FakeHpackEntry& entry) {
+ return std::get<1>(entry);
+}
+size_t Size(const FakeHpackEntry& entry) {
+ return std::get<2>(entry);
+}
+
+class HpackDecoderTablesTest : public HpackDecoderStaticTableTest {
+ protected:
+ const HpackStringPair* Lookup(size_t index) override {
+ return tables_.Lookup(index);
+ }
+
+ size_t dynamic_size_limit() const {
+ return tables_.header_table_size_limit();
+ }
+ size_t current_dynamic_size() const {
+ return tables_.current_header_table_size();
+ }
+ size_t num_dynamic_entries() const {
+ return HpackDecoderTablesPeer::num_dynamic_entries(tables_);
+ }
+
+ // Insert the name and value into fake_dynamic_table_.
+ void FakeInsert(const string& name, const string& value) {
+ FakeHpackEntry entry(name, value, Size(name, value));
+ fake_dynamic_table_.insert(fake_dynamic_table_.begin(), entry);
+ }
+
+ // Add up the size of all entries in fake_dynamic_table_.
+ size_t FakeSize() {
+ size_t sz = 0;
+ for (const auto& entry : fake_dynamic_table_) {
+ sz += Size(entry);
+ }
+ return sz;
+ }
+
+ // If the total size of the fake_dynamic_table_ is greater than limit,
+ // keep the first N entries such that those N entries have a size not
+ // greater than limit, and such that keeping entry N+1 would have a size
+ // greater than limit. Returns the count of removed bytes.
+ size_t FakeTrim(size_t limit) {
+ size_t original_size = FakeSize();
+ size_t total_size = 0;
+ for (size_t ndx = 0; ndx < fake_dynamic_table_.size(); ++ndx) {
+ total_size += Size(fake_dynamic_table_[ndx]);
+ if (total_size > limit) {
+ // Need to get rid of ndx and all following entries.
+ fake_dynamic_table_.erase(fake_dynamic_table_.begin() + ndx,
+ fake_dynamic_table_.end());
+ return original_size - FakeSize();
+ }
+ }
+ return 0;
+ }
+
+ // Verify that the contents of the actual dynamic table match those in
+ // fake_dynamic_table_.
+ AssertionResult VerifyDynamicTableContents() {
+ VERIFY_EQ(current_dynamic_size(), FakeSize());
+ VERIFY_EQ(num_dynamic_entries(), fake_dynamic_table_.size());
+
+ for (size_t ndx = 0; ndx < fake_dynamic_table_.size(); ++ndx) {
+ const HpackStringPair* found = Lookup(ndx + kFirstDynamicTableIndex);
+ VERIFY_NE(found, nullptr);
+
+ const auto& expected = fake_dynamic_table_[ndx];
+ VERIFY_EQ(Name(expected), found->name);
+ VERIFY_EQ(Value(expected), found->value);
+ }
+
+ // Make sure there are no more entries.
+ VERIFY_EQ(nullptr,
+ Lookup(fake_dynamic_table_.size() + kFirstDynamicTableIndex));
+ return AssertionSuccess();
+ }
+
+ // Apply an update to the limit on the maximum size of the dynamic table.
+ AssertionResult DynamicTableSizeUpdate(size_t size_limit) {
+ VERIFY_EQ(current_dynamic_size(), FakeSize());
+ if (size_limit < current_dynamic_size()) {
+ // Will need to trim the dynamic table's oldest entries.
+ tables_.DynamicTableSizeUpdate(size_limit);
+ FakeTrim(size_limit);
+ return VerifyDynamicTableContents();
+ }
+ // Shouldn't change the size.
+ tables_.DynamicTableSizeUpdate(size_limit);
+ return VerifyDynamicTableContents();
+ }
+
+ // Insert an entry into the dynamic table, confirming that trimming of entries
+ // occurs if the total size is greater than the limit, and that older entries
+ // move up by 1 index.
+ AssertionResult Insert(const string& name, const string& value) {
+ size_t old_count = num_dynamic_entries();
+ if (tables_.Insert(HpackString(name), HpackString(value))) {
+ VERIFY_GT(current_dynamic_size(), 0u);
+ VERIFY_GT(num_dynamic_entries(), 0u);
+ } else {
+ VERIFY_EQ(current_dynamic_size(), 0u);
+ VERIFY_EQ(num_dynamic_entries(), 0u);
+ }
+ FakeInsert(name, value);
+ VERIFY_EQ(old_count + 1, fake_dynamic_table_.size());
+ FakeTrim(dynamic_size_limit());
+ VERIFY_EQ(current_dynamic_size(), FakeSize());
+ VERIFY_EQ(num_dynamic_entries(), fake_dynamic_table_.size());
+ return VerifyDynamicTableContents();
+ }
+
+ private:
+ HpackDecoderTables tables_;
+
+ std::vector<FakeHpackEntry> fake_dynamic_table_;
+};
+
+TEST_F(HpackDecoderTablesTest, StaticTableContents) {
+ EXPECT_TRUE(VerifyStaticTableContents());
+}
+
+// Generate a bunch of random header entries, insert them, and confirm they
+// present, as required by the RFC, using VerifyDynamicTableContents above on
+// each Insert. Also apply various resizings of the dynamic table.
+TEST_F(HpackDecoderTablesTest, RandomDynamicTable) {
+ EXPECT_EQ(0u, current_dynamic_size());
+ EXPECT_TRUE(VerifyStaticTableContents());
+ EXPECT_TRUE(VerifyDynamicTableContents());
+
+ std::vector<size_t> table_sizes;
+ table_sizes.push_back(dynamic_size_limit());
+ table_sizes.push_back(0);
+ table_sizes.push_back(dynamic_size_limit() / 2);
+ table_sizes.push_back(dynamic_size_limit());
+ table_sizes.push_back(dynamic_size_limit() / 2);
+ table_sizes.push_back(0);
+ table_sizes.push_back(dynamic_size_limit());
+
+ for (size_t limit : table_sizes) {
+ ASSERT_TRUE(DynamicTableSizeUpdate(limit));
+ for (int insert_count = 0; insert_count < 100; ++insert_count) {
+ string name = GenerateHttp2HeaderName(
+ GenerateUniformInRange(2, 40, RandomPtr()), RandomPtr());
+ string value = GenerateWebSafeString(
+ GenerateUniformInRange(2, 600, RandomPtr()), RandomPtr());
+ ASSERT_TRUE(Insert(name, value));
+ }
+ EXPECT_TRUE(VerifyStaticTableContents());
+ }
+}
+
+} // namespace
+} // namespace test
+} // namespace net
diff --git a/chromium/net/http2/hpack/decoder/hpack_entry_collector.cc b/chromium/net/http2/hpack/decoder/hpack_entry_collector.cc
new file mode 100644
index 00000000000..ea4feb6f847
--- /dev/null
+++ b/chromium/net/http2/hpack/decoder/hpack_entry_collector.cc
@@ -0,0 +1,317 @@
+// Copyright 2016 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.
+
+#include "net/http2/hpack/decoder/hpack_entry_collector.h"
+
+#include <sstream>
+#include <string>
+
+#include "base/logging.h"
+#include "net/http2/hpack/decoder/hpack_string_collector.h"
+#include "net/http2/hpack/http2_hpack_constants.h"
+#include "net/http2/tools/failure.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+using ::testing::AssertionResult;
+using std::string;
+using base::StringPiece;
+
+namespace net {
+namespace test {
+namespace {
+
+const HpackEntryType kInvalidHeaderType = static_cast<HpackEntryType>(99);
+const size_t kInvalidIndex = 99999999;
+
+} // namespace
+
+HpackEntryCollector::HpackEntryCollector() {
+ Clear();
+}
+
+HpackEntryCollector::HpackEntryCollector(const HpackEntryCollector& other)
+ : header_type_(other.header_type_),
+ index_(other.index_),
+ name_(other.name_),
+ value_(other.value_),
+ started_(other.started_),
+ ended_(other.ended_) {}
+
+HpackEntryCollector::HpackEntryCollector(HpackEntryType type,
+ size_t index_or_size)
+ : header_type_(type), index_(index_or_size), started_(true), ended_(true) {}
+HpackEntryCollector::HpackEntryCollector(HpackEntryType type,
+ size_t index,
+ bool value_huffman,
+ const string& value)
+ : header_type_(type),
+ index_(index),
+ value_(value, value_huffman),
+ started_(true),
+ ended_(true) {}
+HpackEntryCollector::HpackEntryCollector(HpackEntryType type,
+ bool name_huffman,
+ const string& name,
+ bool value_huffman,
+ const string& value)
+ : header_type_(type),
+ index_(0),
+ name_(name, name_huffman),
+ value_(value, value_huffman),
+ started_(true),
+ ended_(true) {}
+
+HpackEntryCollector::~HpackEntryCollector() {}
+
+void HpackEntryCollector::OnIndexedHeader(size_t index) {
+ ASSERT_FALSE(started_);
+ ASSERT_TRUE(IsClear()) << ToString();
+ Init(HpackEntryType::kIndexedHeader, index);
+ ended_ = true;
+}
+void HpackEntryCollector::OnStartLiteralHeader(HpackEntryType header_type,
+ size_t maybe_name_index) {
+ ASSERT_FALSE(started_);
+ ASSERT_TRUE(IsClear()) << ToString();
+ Init(header_type, maybe_name_index);
+}
+void HpackEntryCollector::OnNameStart(bool huffman_encoded, size_t len) {
+ ASSERT_TRUE(started_);
+ ASSERT_FALSE(ended_);
+ ASSERT_FALSE(IsClear());
+ ASSERT_TRUE(LiteralNameExpected()) << ToString();
+ name_.OnStringStart(huffman_encoded, len);
+}
+void HpackEntryCollector::OnNameData(const char* data, size_t len) {
+ ASSERT_TRUE(started_);
+ ASSERT_FALSE(ended_);
+ ASSERT_TRUE(LiteralNameExpected()) << ToString();
+ ASSERT_TRUE(name_.IsInProgress());
+ name_.OnStringData(data, len);
+}
+void HpackEntryCollector::OnNameEnd() {
+ ASSERT_TRUE(started_);
+ ASSERT_FALSE(ended_);
+ ASSERT_TRUE(LiteralNameExpected()) << ToString();
+ ASSERT_TRUE(name_.IsInProgress());
+ name_.OnStringEnd();
+}
+void HpackEntryCollector::OnValueStart(bool huffman_encoded, size_t len) {
+ ASSERT_TRUE(started_);
+ ASSERT_FALSE(ended_);
+ if (LiteralNameExpected()) {
+ ASSERT_TRUE(name_.HasEnded());
+ }
+ ASSERT_TRUE(LiteralValueExpected()) << ToString();
+ ASSERT_TRUE(value_.IsClear()) << value_.ToString();
+ value_.OnStringStart(huffman_encoded, len);
+}
+void HpackEntryCollector::OnValueData(const char* data, size_t len) {
+ ASSERT_TRUE(started_);
+ ASSERT_FALSE(ended_);
+ ASSERT_TRUE(LiteralValueExpected()) << ToString();
+ ASSERT_TRUE(value_.IsInProgress());
+ value_.OnStringData(data, len);
+}
+void HpackEntryCollector::OnValueEnd() {
+ ASSERT_TRUE(started_);
+ ASSERT_FALSE(ended_);
+ ASSERT_TRUE(LiteralValueExpected()) << ToString();
+ ASSERT_TRUE(value_.IsInProgress());
+ value_.OnStringEnd();
+ ended_ = true;
+}
+void HpackEntryCollector::OnDynamicTableSizeUpdate(size_t size) {
+ ASSERT_FALSE(started_);
+ ASSERT_TRUE(IsClear()) << ToString();
+ Init(HpackEntryType::kDynamicTableSizeUpdate, size);
+ ended_ = true;
+}
+
+void HpackEntryCollector::Clear() {
+ header_type_ = kInvalidHeaderType;
+ index_ = kInvalidIndex;
+ name_.Clear();
+ value_.Clear();
+ started_ = ended_ = false;
+}
+bool HpackEntryCollector::IsClear() const {
+ return header_type_ == kInvalidHeaderType && index_ == kInvalidIndex &&
+ name_.IsClear() && value_.IsClear() && !started_ && !ended_;
+}
+bool HpackEntryCollector::IsComplete() const {
+ return started_ && ended_;
+}
+bool HpackEntryCollector::LiteralNameExpected() const {
+ switch (header_type_) {
+ case HpackEntryType::kIndexedLiteralHeader:
+ case HpackEntryType::kUnindexedLiteralHeader:
+ case HpackEntryType::kNeverIndexedLiteralHeader:
+ return index_ == 0;
+ default:
+ return false;
+ }
+}
+bool HpackEntryCollector::LiteralValueExpected() const {
+ switch (header_type_) {
+ case HpackEntryType::kIndexedLiteralHeader:
+ case HpackEntryType::kUnindexedLiteralHeader:
+ case HpackEntryType::kNeverIndexedLiteralHeader:
+ return true;
+ default:
+ return false;
+ }
+}
+AssertionResult HpackEntryCollector::ValidateIndexedHeader(
+ size_t expected_index) const {
+ VERIFY_TRUE(started_);
+ VERIFY_TRUE(ended_);
+ VERIFY_EQ(HpackEntryType::kIndexedHeader, header_type_);
+ VERIFY_EQ(expected_index, index_);
+ return ::testing::AssertionSuccess();
+}
+AssertionResult HpackEntryCollector::ValidateLiteralValueHeader(
+ HpackEntryType expected_type,
+ size_t expected_index,
+ bool expected_value_huffman,
+ StringPiece expected_value) const {
+ VERIFY_TRUE(started_);
+ VERIFY_TRUE(ended_);
+ VERIFY_EQ(expected_type, header_type_);
+ VERIFY_NE(0u, expected_index);
+ VERIFY_EQ(expected_index, index_);
+ VERIFY_TRUE(name_.IsClear());
+ VERIFY_SUCCESS(value_.Collected(expected_value, expected_value_huffman));
+ return ::testing::AssertionSuccess();
+}
+AssertionResult HpackEntryCollector::ValidateLiteralNameValueHeader(
+ HpackEntryType expected_type,
+ bool expected_name_huffman,
+ StringPiece expected_name,
+ bool expected_value_huffman,
+ StringPiece expected_value) const {
+ VERIFY_TRUE(started_);
+ VERIFY_TRUE(ended_);
+ VERIFY_EQ(expected_type, header_type_);
+ VERIFY_EQ(0u, index_);
+ VERIFY_SUCCESS(name_.Collected(expected_name, expected_name_huffman));
+ VERIFY_SUCCESS(value_.Collected(expected_value, expected_value_huffman));
+ return ::testing::AssertionSuccess();
+}
+AssertionResult HpackEntryCollector::ValidateDynamicTableSizeUpdate(
+ size_t size) const {
+ VERIFY_TRUE(started_);
+ VERIFY_TRUE(ended_);
+ VERIFY_EQ(HpackEntryType::kDynamicTableSizeUpdate, header_type_);
+ VERIFY_EQ(index_, size);
+ return ::testing::AssertionSuccess();
+}
+
+void HpackEntryCollector::AppendToHpackBlockBuilder(
+ HpackBlockBuilder* hbb) const {
+ ASSERT_TRUE(started_ && ended_) << *this;
+ switch (header_type_) {
+ case HpackEntryType::kIndexedHeader:
+ hbb->AppendIndexedHeader(index_);
+ return;
+
+ case HpackEntryType::kDynamicTableSizeUpdate:
+ hbb->AppendDynamicTableSizeUpdate(index_);
+ return;
+
+ case HpackEntryType::kIndexedLiteralHeader:
+ case HpackEntryType::kUnindexedLiteralHeader:
+ case HpackEntryType::kNeverIndexedLiteralHeader:
+ ASSERT_TRUE(value_.HasEnded()) << *this;
+ if (index_ != 0) {
+ CHECK(name_.IsClear());
+ hbb->AppendNameIndexAndLiteralValue(header_type_, index_,
+ value_.huffman_encoded, value_.s);
+ } else {
+ CHECK(name_.HasEnded()) << *this;
+ hbb->AppendLiteralNameAndValue(header_type_, name_.huffman_encoded,
+ name_.s, value_.huffman_encoded,
+ value_.s);
+ }
+ return;
+
+ default:
+ ADD_FAILURE() << *this;
+ }
+}
+
+string HpackEntryCollector::ToString() const {
+ string result("Type=");
+ switch (header_type_) {
+ case HpackEntryType::kIndexedHeader:
+ result += "IndexedHeader";
+ break;
+ case HpackEntryType::kDynamicTableSizeUpdate:
+ result += "DynamicTableSizeUpdate";
+ break;
+ case HpackEntryType::kIndexedLiteralHeader:
+ result += "IndexedLiteralHeader";
+ break;
+ case HpackEntryType::kUnindexedLiteralHeader:
+ result += "UnindexedLiteralHeader";
+ break;
+ case HpackEntryType::kNeverIndexedLiteralHeader:
+ result += "NeverIndexedLiteralHeader";
+ break;
+ default:
+ if (header_type_ == kInvalidHeaderType) {
+ result += "<unset>";
+ } else {
+ std::stringstream ss;
+ ss << header_type_;
+ result.append(ss.str());
+ }
+ }
+ if (index_ != 0) {
+ result.append(" Index=");
+ std::stringstream ss;
+ ss << index_;
+ result.append(ss.str());
+ }
+ if (!name_.IsClear()) {
+ result.append(" Name");
+ result.append(name_.ToString());
+ }
+ if (!value_.IsClear()) {
+ result.append(" Value");
+ result.append(value_.ToString());
+ }
+ if (!started_) {
+ EXPECT_FALSE(ended_);
+ result.append(" !started");
+ } else if (!ended_) {
+ result.append(" !ended");
+ } else {
+ result.append(" Complete");
+ }
+ return result;
+}
+
+void HpackEntryCollector::Init(HpackEntryType type, size_t maybe_index) {
+ ASSERT_TRUE(IsClear()) << ToString();
+ header_type_ = type;
+ index_ = maybe_index;
+ started_ = true;
+}
+
+bool operator==(const HpackEntryCollector& a, const HpackEntryCollector& b) {
+ return a.name() == b.name() && a.value() == b.value() &&
+ a.index() == b.index() && a.header_type() == b.header_type() &&
+ a.started() == b.started() && a.ended() == b.ended();
+}
+bool operator!=(const HpackEntryCollector& a, const HpackEntryCollector& b) {
+ return !(a == b);
+}
+
+std::ostream& operator<<(std::ostream& out, const HpackEntryCollector& v) {
+ return out << v.ToString();
+}
+
+} // namespace test
+} // namespace net
diff --git a/chromium/net/http2/hpack/decoder/hpack_entry_collector.h b/chromium/net/http2/hpack/decoder/hpack_entry_collector.h
new file mode 100644
index 00000000000..876e0b0814f
--- /dev/null
+++ b/chromium/net/http2/hpack/decoder/hpack_entry_collector.h
@@ -0,0 +1,154 @@
+// Copyright 2016 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.
+
+#ifndef NET_HTTP2_HPACK_DECODER_HPACK_ENTRY_COLLECTOR_H_
+#define NET_HTTP2_HPACK_DECODER_HPACK_ENTRY_COLLECTOR_H_
+
+// HpackEntryCollector records calls to HpackEntryDecoderListener in support
+// of tests of HpackEntryDecoder, or which use it. Can only record the callbacks
+// for the decoding of a single entry; call Clear() between decoding successive
+// entries or use a distinct HpackEntryCollector for each entry.
+
+#include <stddef.h>
+
+#include <iosfwd>
+#include <string>
+
+#include "base/strings/string_piece.h"
+#include "net/http2/hpack/decoder/hpack_entry_decoder_listener.h"
+#include "net/http2/hpack/decoder/hpack_string_collector.h"
+#include "net/http2/hpack/http2_hpack_constants.h"
+#include "net/http2/hpack/tools/hpack_block_builder.h"
+
+namespace net {
+namespace test {
+
+class HpackEntryCollector : public HpackEntryDecoderListener {
+ public:
+ HpackEntryCollector();
+ HpackEntryCollector(const HpackEntryCollector& other);
+
+ // These next three constructors are intended for use in tests that create
+ // an HpackEntryCollector "manually", and then compare it against another
+ // that is populated via calls to the HpackEntryDecoderListener methods.
+ HpackEntryCollector(HpackEntryType type, size_t index_or_size);
+ HpackEntryCollector(HpackEntryType type,
+ size_t index,
+ bool value_huffman,
+ const std::string& value);
+ HpackEntryCollector(HpackEntryType type,
+ bool name_huffman,
+ const std::string& name,
+ bool value_huffman,
+ const std::string& value);
+
+ ~HpackEntryCollector() override;
+
+ // Methods defined by HpackEntryDecoderListener.
+ void OnIndexedHeader(size_t index) override;
+ void OnStartLiteralHeader(HpackEntryType header_type,
+ size_t maybe_name_index) override;
+ void OnNameStart(bool huffman_encoded, size_t len) override;
+ void OnNameData(const char* data, size_t len) override;
+ void OnNameEnd() override;
+ void OnValueStart(bool huffman_encoded, size_t len) override;
+ void OnValueData(const char* data, size_t len) override;
+ void OnValueEnd() override;
+ void OnDynamicTableSizeUpdate(size_t size) override;
+
+ // Clears the fields of the collector so that it is ready to start collecting
+ // another HPACK block entry.
+ void Clear();
+
+ // Is the collector ready to start collecting another HPACK block entry.
+ bool IsClear() const;
+
+ // Has a complete entry been collected?
+ bool IsComplete() const;
+
+ // Based on the HpackEntryType, is a literal name expected?
+ bool LiteralNameExpected() const;
+
+ // Based on the HpackEntryType, is a literal value expected?
+ bool LiteralValueExpected() const;
+
+ // Returns success if collected an Indexed Header (i.e. OnIndexedHeader was
+ // called).
+ ::testing::AssertionResult ValidateIndexedHeader(size_t expected_index) const;
+
+ // Returns success if collected a Header with an indexed name and literal
+ // value (i.e. OnStartLiteralHeader was called with a non-zero index for
+ // the name, which must match expected_index).
+ ::testing::AssertionResult ValidateLiteralValueHeader(
+ HpackEntryType expected_type,
+ size_t expected_index,
+ bool expected_value_huffman,
+ base::StringPiece expected_value) const;
+
+ // Returns success if collected a Header with an literal name and literal
+ // value.
+ ::testing::AssertionResult ValidateLiteralNameValueHeader(
+ HpackEntryType expected_type,
+ bool expected_name_huffman,
+ base::StringPiece expected_name,
+ bool expected_value_huffman,
+ base::StringPiece expected_value) const;
+
+ // Returns success if collected a Dynamic Table Size Update,
+ // with the specified size.
+ ::testing::AssertionResult ValidateDynamicTableSizeUpdate(
+ size_t expected_size) const;
+
+ void set_header_type(HpackEntryType v) { header_type_ = v; }
+ HpackEntryType header_type() const { return header_type_; }
+
+ void set_index(size_t v) { index_ = v; }
+ size_t index() const { return index_; }
+
+ void set_name(const HpackStringCollector& v) { name_ = v; }
+ const HpackStringCollector& name() const { return name_; }
+
+ void set_value(const HpackStringCollector& v) { value_ = v; }
+ const HpackStringCollector& value() const { return value_; }
+
+ void set_started(bool v) { started_ = v; }
+ bool started() const { return started_; }
+
+ void set_ended(bool v) { ended_ = v; }
+ bool ended() const { return ended_; }
+
+ void AppendToHpackBlockBuilder(HpackBlockBuilder* hbb) const;
+
+ // Returns a debug string.
+ std::string ToString() const;
+
+ private:
+ void Init(HpackEntryType type, size_t maybe_index);
+
+ HpackEntryType header_type_;
+ size_t index_;
+
+ HpackStringCollector name_;
+ HpackStringCollector value_;
+
+ // True if has received a call to an HpackEntryDecoderListener method
+ // indicating the start of decoding an HPACK entry; for example,
+ // OnIndexedHeader set it true, but OnNameStart does not change it.
+ bool started_ = false;
+
+ // True if has received a call to an HpackEntryDecoderListener method
+ // indicating the end of decoding an HPACK entry; for example,
+ // OnIndexedHeader and OnValueEnd both set it true, but OnNameEnd does
+ // not change it.
+ bool ended_ = false;
+};
+
+bool operator==(const HpackEntryCollector& a, const HpackEntryCollector& b);
+bool operator!=(const HpackEntryCollector& a, const HpackEntryCollector& b);
+std::ostream& operator<<(std::ostream& out, const HpackEntryCollector& v);
+
+} // namespace test
+} // namespace net
+
+#endif // NET_HTTP2_HPACK_DECODER_HPACK_ENTRY_COLLECTOR_H_
diff --git a/chromium/net/http2/hpack/decoder/hpack_entry_decoder.cc b/chromium/net/http2/hpack/decoder/hpack_entry_decoder.cc
new file mode 100644
index 00000000000..c47ef0cf713
--- /dev/null
+++ b/chromium/net/http2/hpack/decoder/hpack_entry_decoder.cc
@@ -0,0 +1,233 @@
+// Copyright 2016 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.
+
+#include "net/http2/hpack/decoder/hpack_entry_decoder.h"
+
+#include <stddef.h>
+
+#include "base/logging.h"
+#include "base/macros.h"
+
+namespace net {
+namespace {
+// Converts calls from HpackStringDecoder when decoding a header name into the
+// appropriate HpackEntryDecoderListener::OnName* calls.
+class NameDecoderListener {
+ public:
+ explicit NameDecoderListener(HpackEntryDecoderListener* listener)
+ : listener_(listener) {}
+ bool OnStringStart(bool huffman_encoded, size_t len) {
+ listener_->OnNameStart(huffman_encoded, len);
+ return true;
+ }
+ void OnStringData(const char* data, size_t len) {
+ listener_->OnNameData(data, len);
+ }
+ void OnStringEnd() { listener_->OnNameEnd(); }
+
+ private:
+ HpackEntryDecoderListener* listener_;
+};
+
+// Converts calls from HpackStringDecoder when decoding a header value into
+// the appropriate HpackEntryDecoderListener::OnValue* calls.
+class ValueDecoderListener {
+ public:
+ explicit ValueDecoderListener(HpackEntryDecoderListener* listener)
+ : listener_(listener) {}
+ bool OnStringStart(bool huffman_encoded, size_t len) {
+ listener_->OnValueStart(huffman_encoded, len);
+ return true;
+ }
+ void OnStringData(const char* data, size_t len) {
+ listener_->OnValueData(data, len);
+ }
+ void OnStringEnd() { listener_->OnValueEnd(); }
+
+ private:
+ HpackEntryDecoderListener* listener_;
+};
+} // namespace
+
+// Only call Resume if the previous call (Start or Resume) returned
+// kDecodeInProgress; Resume is also called from Start when it has succeeded
+// in decoding the entry type and its varint.
+DecodeStatus HpackEntryDecoder::Resume(DecodeBuffer* db,
+ HpackEntryDecoderListener* listener) {
+ DCHECK(db != nullptr);
+ DCHECK(listener != nullptr);
+
+ DecodeStatus status;
+
+ do {
+ switch (state_) {
+ case EntryDecoderState::kResumeDecodingType:
+ // entry_type_decoder_ returned kDecodeInProgress when last called.
+ DVLOG(1) << "kResumeDecodingType: db->Remaining=" << db->Remaining();
+ status = entry_type_decoder_.Resume(db);
+ if (status != DecodeStatus::kDecodeDone) {
+ return status;
+ }
+ state_ = EntryDecoderState::kDecodedType;
+ // FALLTHROUGH_INTENDED
+
+ case EntryDecoderState::kDecodedType:
+ // entry_type_decoder_ returned kDecodeDone, now need to decide how
+ // to proceed.
+ DVLOG(1) << "kDecodedType: db->Remaining=" << db->Remaining();
+ if (DispatchOnType(listener)) {
+ // All done.
+ return DecodeStatus::kDecodeDone;
+ }
+ continue;
+
+ case EntryDecoderState::kStartDecodingName:
+ DVLOG(1) << "kStartDecodingName: db->Remaining=" << db->Remaining();
+ {
+ NameDecoderListener ncb(listener);
+ status = string_decoder_.Start(db, &ncb);
+ }
+ if (status != DecodeStatus::kDecodeDone) {
+ // On the assumption that the status is kDecodeInProgress, set
+ // state_ accordingly; unnecessary if status is kDecodeError, but
+ // that will only happen if the varint encoding the name's length
+ // is too long.
+ state_ = EntryDecoderState::kResumeDecodingName;
+ return status;
+ }
+ state_ = EntryDecoderState::kStartDecodingValue;
+ // FALLTHROUGH_INTENDED
+
+ case EntryDecoderState::kStartDecodingValue:
+ DVLOG(1) << "kStartDecodingValue: db->Remaining=" << db->Remaining();
+ {
+ ValueDecoderListener vcb(listener);
+ status = string_decoder_.Start(db, &vcb);
+ }
+ if (status == DecodeStatus::kDecodeDone) {
+ // Done with decoding the literal value, so we've reached the
+ // end of the header entry.
+ return status;
+ }
+ // On the assumption that the status is kDecodeInProgress, set
+ // state_ accordingly; unnecessary if status is kDecodeError, but
+ // that will only happen if the varint encoding the value's length
+ // is too long.
+ state_ = EntryDecoderState::kResumeDecodingValue;
+ return status;
+
+ case EntryDecoderState::kResumeDecodingName:
+ // The literal name was split across decode buffers.
+ DVLOG(1) << "kResumeDecodingName: db->Remaining=" << db->Remaining();
+ {
+ NameDecoderListener ncb(listener);
+ status = string_decoder_.Resume(db, &ncb);
+ }
+ if (status != DecodeStatus::kDecodeDone) {
+ // On the assumption that the status is kDecodeInProgress, set
+ // state_ accordingly; unnecessary if status is kDecodeError, but
+ // that will only happen if the varint encoding the name's length
+ // is too long.
+ state_ = EntryDecoderState::kResumeDecodingName;
+ return status;
+ }
+ state_ = EntryDecoderState::kStartDecodingValue;
+ break;
+
+ case EntryDecoderState::kResumeDecodingValue:
+ // The literal value was split across decode buffers.
+ DVLOG(1) << "kResumeDecodingValue: db->Remaining=" << db->Remaining();
+ {
+ ValueDecoderListener vcb(listener);
+ status = string_decoder_.Resume(db, &vcb);
+ }
+ if (status == DecodeStatus::kDecodeDone) {
+ // Done with decoding the value, therefore the entry as a whole.
+ return status;
+ }
+ // On the assumption that the status is kDecodeInProgress, set
+ // state_ accordingly; unnecessary if status is kDecodeError, but
+ // that will only happen if the varint encoding the value's length
+ // is too long.
+ state_ = EntryDecoderState::kResumeDecodingValue;
+ return status;
+ }
+ } while (true);
+}
+
+bool HpackEntryDecoder::DispatchOnType(HpackEntryDecoderListener* listener) {
+ const HpackEntryType entry_type = entry_type_decoder_.entry_type();
+ const uint32_t varint = entry_type_decoder_.varint();
+ switch (entry_type) {
+ case HpackEntryType::kIndexedHeader:
+ // The entry consists solely of the entry type and varint. See:
+ // http://httpwg.org/specs/rfc7541.html#indexed.header.representation
+ listener->OnIndexedHeader(varint);
+ return true;
+
+ case HpackEntryType::kIndexedLiteralHeader:
+ case HpackEntryType::kUnindexedLiteralHeader:
+ case HpackEntryType::kNeverIndexedLiteralHeader:
+ // The entry has a literal value, and if the varint is zero also has a
+ // literal name preceding the value. See:
+ // http://httpwg.org/specs/rfc7541.html#literal.header.representation
+ listener->OnStartLiteralHeader(entry_type, varint);
+ if (varint == 0) {
+ state_ = EntryDecoderState::kStartDecodingName;
+ } else {
+ state_ = EntryDecoderState::kStartDecodingValue;
+ }
+ return false;
+
+ case HpackEntryType::kDynamicTableSizeUpdate:
+ // The entry consists solely of the entry type and varint. FWIW, I've
+ // never seen this type of entry in production (primarily browser
+ // traffic) so if you're designing an HPACK successor someday, consider
+ // dropping it or giving it a much longer prefix. See:
+ // http://httpwg.org/specs/rfc7541.html#encoding.context.update
+ listener->OnDynamicTableSizeUpdate(varint);
+ return true;
+ }
+
+ NOTREACHED();
+ return true;
+}
+
+void HpackEntryDecoder::OutputDebugString(std::ostream& out) const {
+ out << "HpackEntryDecoder(state=" << state_ << ", " << entry_type_decoder_
+ << ", " << string_decoder_ << ")";
+}
+
+std::string HpackEntryDecoder::DebugString() const {
+ std::stringstream s;
+ s << *this;
+ return s.str();
+}
+
+std::ostream& operator<<(std::ostream& out, const HpackEntryDecoder& v) {
+ v.OutputDebugString(out);
+ return out;
+}
+
+std::ostream& operator<<(std::ostream& out,
+ HpackEntryDecoder::EntryDecoderState state) {
+ typedef HpackEntryDecoder::EntryDecoderState EntryDecoderState;
+ switch (state) {
+ case EntryDecoderState::kResumeDecodingType:
+ return out << "kResumeDecodingType";
+ case EntryDecoderState::kDecodedType:
+ return out << "kDecodedType";
+ case EntryDecoderState::kStartDecodingName:
+ return out << "kStartDecodingName";
+ case EntryDecoderState::kResumeDecodingName:
+ return out << "kResumeDecodingName";
+ case EntryDecoderState::kStartDecodingValue:
+ return out << "kStartDecodingValue";
+ case EntryDecoderState::kResumeDecodingValue:
+ return out << "kResumeDecodingValue";
+ }
+ return out << static_cast<int>(state);
+}
+
+} // namespace net
diff --git a/chromium/net/http2/hpack/decoder/hpack_entry_decoder.h b/chromium/net/http2/hpack/decoder/hpack_entry_decoder.h
new file mode 100644
index 00000000000..9b5f696f83e
--- /dev/null
+++ b/chromium/net/http2/hpack/decoder/hpack_entry_decoder.h
@@ -0,0 +1,117 @@
+// Copyright 2016 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.
+
+#ifndef NET_HTTP2_HPACK_DECODER_HPACK_ENTRY_DECODER_H_
+#define NET_HTTP2_HPACK_DECODER_HPACK_ENTRY_DECODER_H_
+
+// HpackEntryDecoder decodes a single HPACK entry (i.e. one header or one
+// dynamic table size update), in a resumable fashion. The first call, Start(),
+// must provide a non-empty decode buffer. Continue with calls to Resume() if
+// Start, and any subsequent calls to Resume, returns kDecodeInProgress.
+
+#include <string>
+
+#include "base/logging.h"
+#include "net/base/net_export.h"
+#include "net/http2/decoder/decode_buffer.h"
+#include "net/http2/decoder/decode_status.h"
+#include "net/http2/hpack/decoder/hpack_entry_decoder_listener.h"
+#include "net/http2/hpack/decoder/hpack_entry_type_decoder.h"
+#include "net/http2/hpack/decoder/hpack_string_decoder.h"
+#include "net/http2/hpack/http2_hpack_constants.h"
+
+namespace net {
+
+class NET_EXPORT_PRIVATE HpackEntryDecoder {
+ public:
+ enum class EntryDecoderState {
+ // Have started decoding the type/varint, but didn't finish on the previous
+ // attempt. Next state is kResumeDecodingType or kDecodedType.
+ kResumeDecodingType,
+
+ // Have just finished decoding the type/varint. Final state if the type is
+ // kIndexedHeader or kDynamicTableSizeUpdate. Otherwise, the next state is
+ // kStartDecodingName (if the varint is 0), else kStartDecodingValue.
+ kDecodedType,
+
+ // Ready to start decoding the literal name of a header entry. Next state
+ // is kResumeDecodingName (if the name is split across decode buffers),
+ // else kStartDecodingValue.
+ kStartDecodingName,
+
+ // Resume decoding the literal name of a header that is split across decode
+ // buffers.
+ kResumeDecodingName,
+
+ // Ready to start decoding the literal value of a header entry. Final state
+ // if the value string is entirely in the decode buffer, else the next state
+ // is kResumeDecodingValue.
+ kStartDecodingValue,
+
+ // Resume decoding the literal value of a header that is split across decode
+ // buffers.
+ kResumeDecodingValue,
+ };
+
+ // Only call when the decode buffer has data (i.e. HpackBlockDecoder must
+ // not call until there is data).
+ DecodeStatus Start(DecodeBuffer* db, HpackEntryDecoderListener* listener) {
+ DCHECK(db != nullptr);
+ DCHECK(listener != nullptr);
+ DCHECK(db->HasData());
+ DecodeStatus status = entry_type_decoder_.Start(db);
+ switch (status) {
+ case DecodeStatus::kDecodeDone:
+ // The type of the entry and its varint fit into the current decode
+ // buffer.
+ if (entry_type_decoder_.entry_type() ==
+ HpackEntryType::kIndexedHeader) {
+ // The entry consists solely of the entry type and varint. This
+ // is by far the most common case in practice.
+ listener->OnIndexedHeader(entry_type_decoder_.varint());
+ return DecodeStatus::kDecodeDone;
+ }
+ state_ = EntryDecoderState::kDecodedType;
+ return Resume(db, listener);
+ case DecodeStatus::kDecodeInProgress:
+ // Hit the end of the decode buffer before fully decoding the entry
+ // type and varint.
+ DCHECK_EQ(0u, db->Remaining());
+ state_ = EntryDecoderState::kResumeDecodingType;
+ return status;
+ case DecodeStatus::kDecodeError:
+ // The varint must have been invalid (too long).
+ return status;
+ }
+
+ NOTREACHED();
+ return DecodeStatus::kDecodeError;
+ }
+
+ // Only call Resume if the previous call (Start or Resume) returned
+ // kDecodeInProgress; Resume is also called from Start when it has succeeded
+ // in decoding the entry type and its varint.
+ DecodeStatus Resume(DecodeBuffer* db, HpackEntryDecoderListener* listener);
+
+ std::string DebugString() const;
+ void OutputDebugString(std::ostream& out) const;
+
+ private:
+ // Implements handling state kDecodedType.
+ bool DispatchOnType(HpackEntryDecoderListener* listener);
+
+ HpackEntryTypeDecoder entry_type_decoder_;
+ HpackStringDecoder string_decoder_;
+ EntryDecoderState state_ = EntryDecoderState();
+};
+
+NET_EXPORT_PRIVATE std::ostream& operator<<(std::ostream& out,
+ const HpackEntryDecoder& v);
+NET_EXPORT_PRIVATE std::ostream& operator<<(
+ std::ostream& out,
+ HpackEntryDecoder::EntryDecoderState state);
+
+} // namespace net
+
+#endif // NET_HTTP2_HPACK_DECODER_HPACK_ENTRY_DECODER_H_
diff --git a/chromium/net/http2/hpack/decoder/hpack_entry_decoder_listener.cc b/chromium/net/http2/hpack/decoder/hpack_entry_decoder_listener.cc
new file mode 100644
index 00000000000..c7e991fb396
--- /dev/null
+++ b/chromium/net/http2/hpack/decoder/hpack_entry_decoder_listener.cc
@@ -0,0 +1,83 @@
+// Copyright 2016 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.
+
+#include "net/http2/hpack/decoder/hpack_entry_decoder_listener.h"
+
+#include "base/logging.h"
+
+namespace net {
+
+void HpackEntryDecoderVLoggingListener::OnIndexedHeader(size_t index) {
+ VLOG(1) << "OnIndexedHeader, index=" << index;
+ if (wrapped_) {
+ wrapped_->OnIndexedHeader(index);
+ }
+}
+
+void HpackEntryDecoderVLoggingListener::OnStartLiteralHeader(
+ HpackEntryType entry_type,
+ size_t maybe_name_index) {
+ VLOG(1) << "OnStartLiteralHeader: entry_type=" << entry_type
+ << ", maybe_name_index=" << maybe_name_index;
+ if (wrapped_) {
+ wrapped_->OnStartLiteralHeader(entry_type, maybe_name_index);
+ }
+}
+
+void HpackEntryDecoderVLoggingListener::OnNameStart(bool huffman_encoded,
+ size_t len) {
+ VLOG(1) << "OnNameStart: H=" << huffman_encoded << ", len=" << len;
+ if (wrapped_) {
+ wrapped_->OnNameStart(huffman_encoded, len);
+ }
+}
+
+void HpackEntryDecoderVLoggingListener::OnNameData(const char* data,
+ size_t len) {
+ VLOG(1) << "OnNameData: len=" << len;
+ if (wrapped_) {
+ wrapped_->OnNameData(data, len);
+ }
+}
+
+void HpackEntryDecoderVLoggingListener::OnNameEnd() {
+ VLOG(1) << "OnNameEnd";
+ if (wrapped_) {
+ wrapped_->OnNameEnd();
+ }
+}
+
+void HpackEntryDecoderVLoggingListener::OnValueStart(bool huffman_encoded,
+ size_t len) {
+ VLOG(1) << "OnValueStart: H=" << huffman_encoded << ", len=" << len;
+ if (wrapped_) {
+ wrapped_->OnValueStart(huffman_encoded, len);
+ }
+ return;
+}
+
+void HpackEntryDecoderVLoggingListener::OnValueData(const char* data,
+ size_t len) {
+ VLOG(1) << "OnValueData: len=" << len;
+ if (wrapped_) {
+ wrapped_->OnValueData(data, len);
+ }
+}
+
+void HpackEntryDecoderVLoggingListener::OnValueEnd() {
+ VLOG(1) << "OnValueEnd";
+ if (wrapped_) {
+ wrapped_->OnValueEnd();
+ }
+}
+
+void HpackEntryDecoderVLoggingListener::OnDynamicTableSizeUpdate(size_t size) {
+ VLOG(1) << "OnDynamicTableSizeUpdate: size=" << size;
+ if (wrapped_) {
+ wrapped_->OnDynamicTableSizeUpdate(size);
+ }
+ return;
+}
+
+} // namespace net
diff --git a/chromium/net/http2/hpack/decoder/hpack_entry_decoder_listener.h b/chromium/net/http2/hpack/decoder/hpack_entry_decoder_listener.h
new file mode 100644
index 00000000000..09fbd5432f0
--- /dev/null
+++ b/chromium/net/http2/hpack/decoder/hpack_entry_decoder_listener.h
@@ -0,0 +1,110 @@
+// Copyright 2016 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.
+
+#ifndef NET_HTTP2_HPACK_DECODER_HPACK_ENTRY_DECODER_LISTENER_H_
+#define NET_HTTP2_HPACK_DECODER_HPACK_ENTRY_DECODER_LISTENER_H_
+
+// Defines HpackEntryDecoderListener, the base class of listeners that
+// HpackEntryDecoder calls. Also defines HpackEntryDecoderVLoggingListener
+// which logs before calling another HpackEntryDecoderListener implementation.
+
+#include <stddef.h>
+
+#include "net/base/net_export.h"
+#include "net/http2/hpack/http2_hpack_constants.h"
+
+namespace net {
+
+class NET_EXPORT_PRIVATE HpackEntryDecoderListener {
+ public:
+ virtual ~HpackEntryDecoderListener() {}
+
+ // Called when an indexed header (i.e. one in the static or dynamic table) has
+ // been decoded from an HPACK block. index is supposed to be non-zero, but
+ // that has not been checked by the caller.
+ virtual void OnIndexedHeader(size_t index) = 0;
+
+ // Called when the start of a header with a literal value, and maybe a literal
+ // name, has been decoded. maybe_name_index is zero if the header has a
+ // literal name, else it is a reference into the static or dynamic table, from
+ // which the name should be determined. When the name is literal, the next
+ // call will be to OnNameStart; else it will be to OnValueStart. entry_type
+ // indicates whether the peer has added the entry to its dynamic table, and
+ // whether a proxy is permitted to do so when forwarding the entry.
+ virtual void OnStartLiteralHeader(HpackEntryType entry_type,
+ size_t maybe_name_index) = 0;
+
+ // Called when the encoding (Huffman compressed or plain text) and the encoded
+ // length of a literal name has been decoded. OnNameData will be called next,
+ // and repeatedly until the sum of lengths passed to OnNameData is len.
+ virtual void OnNameStart(bool huffman_encoded, size_t len) = 0;
+
+ // Called when len bytes of an encoded header name have been decoded.
+ virtual void OnNameData(const char* data, size_t len) = 0;
+
+ // Called after the entire name has been passed to OnNameData.
+ // OnValueStart will be called next.
+ virtual void OnNameEnd() = 0;
+
+ // Called when the encoding (Huffman compressed or plain text) and the encoded
+ // length of a literal value has been decoded. OnValueData will be called
+ // next, and repeatedly until the sum of lengths passed to OnValueData is len.
+ virtual void OnValueStart(bool huffman_encoded, size_t len) = 0;
+
+ // Called when len bytes of an encoded header value have been decoded.
+ virtual void OnValueData(const char* data, size_t len) = 0;
+
+ // Called after the entire value has been passed to OnValueData, marking the
+ // end of a header entry with a literal value, and maybe a literal name.
+ virtual void OnValueEnd() = 0;
+
+ // Called when an update to the size of the peer's dynamic table has been
+ // decoded.
+ virtual void OnDynamicTableSizeUpdate(size_t size) = 0;
+};
+
+class NET_EXPORT_PRIVATE HpackEntryDecoderVLoggingListener
+ : public HpackEntryDecoderListener {
+ public:
+ HpackEntryDecoderVLoggingListener() : wrapped_(nullptr) {}
+ explicit HpackEntryDecoderVLoggingListener(HpackEntryDecoderListener* wrapped)
+ : wrapped_(wrapped) {}
+ ~HpackEntryDecoderVLoggingListener() override {}
+
+ void OnIndexedHeader(size_t index) override;
+ void OnStartLiteralHeader(HpackEntryType entry_type,
+ size_t maybe_name_index) override;
+ void OnNameStart(bool huffman_encoded, size_t len) override;
+ void OnNameData(const char* data, size_t len) override;
+ void OnNameEnd() override;
+ void OnValueStart(bool huffman_encoded, size_t len) override;
+ void OnValueData(const char* data, size_t len) override;
+ void OnValueEnd() override;
+ void OnDynamicTableSizeUpdate(size_t size) override;
+
+ private:
+ HpackEntryDecoderListener* const wrapped_;
+};
+
+// A no-op implementation of HpackEntryDecoderListener.
+class NET_EXPORT_PRIVATE HpackEntryDecoderNoOpListener
+ : public HpackEntryDecoderListener {
+ public:
+ ~HpackEntryDecoderNoOpListener() override {}
+
+ void OnIndexedHeader(size_t index) override {}
+ void OnStartLiteralHeader(HpackEntryType entry_type,
+ size_t maybe_name_index) override {}
+ void OnNameStart(bool huffman_encoded, size_t len) override {}
+ void OnNameData(const char* data, size_t len) override {}
+ void OnNameEnd() override {}
+ void OnValueStart(bool huffman_encoded, size_t len) override {}
+ void OnValueData(const char* data, size_t len) override {}
+ void OnValueEnd() override {}
+ void OnDynamicTableSizeUpdate(size_t size) override {}
+};
+
+} // namespace net
+
+#endif // NET_HTTP2_HPACK_DECODER_HPACK_ENTRY_DECODER_LISTENER_H_
diff --git a/chromium/net/http2/hpack/decoder/hpack_entry_decoder_test.cc b/chromium/net/http2/hpack/decoder/hpack_entry_decoder_test.cc
new file mode 100644
index 00000000000..6a1c293f2f0
--- /dev/null
+++ b/chromium/net/http2/hpack/decoder/hpack_entry_decoder_test.cc
@@ -0,0 +1,213 @@
+// Copyright 2016 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.
+
+#include "net/http2/hpack/decoder/hpack_entry_decoder.h"
+
+// Tests of HpackEntryDecoder.
+
+#include "net/http2/hpack/decoder/hpack_entry_collector.h"
+#include "net/http2/hpack/tools/hpack_block_builder.h"
+#include "net/http2/tools/failure.h"
+#include "net/http2/tools/http2_random.h"
+#include "net/http2/tools/random_decoder_test.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+using ::testing::AssertionResult;
+using std::string;
+
+namespace net {
+namespace test {
+namespace {
+
+class HpackEntryDecoderTest : public RandomDecoderTest {
+
+ protected:
+ HpackEntryDecoderTest() : listener_(&collector_) {}
+
+ DecodeStatus StartDecoding(DecodeBuffer* b) override {
+ collector_.Clear();
+ return decoder_.Start(b, &listener_);
+ }
+
+ DecodeStatus ResumeDecoding(DecodeBuffer* b) override {
+ return decoder_.Resume(b, &listener_);
+ }
+
+ AssertionResult DecodeAndValidateSeveralWays(DecodeBuffer* db,
+ Validator validator) {
+ // StartDecoding, above, requires the DecodeBuffer be non-empty so that it
+ // can call Start with the prefix byte.
+ bool return_non_zero_on_first = true;
+ return RandomDecoderTest::DecodeAndValidateSeveralWays(
+ db, return_non_zero_on_first, validator);
+ }
+
+ AssertionResult DecodeAndValidateSeveralWays(const HpackBlockBuilder& hbb,
+ Validator validator) {
+ DecodeBuffer db(hbb.buffer());
+ return DecodeAndValidateSeveralWays(&db, validator);
+ }
+
+ HpackEntryDecoder decoder_;
+ HpackEntryCollector collector_;
+ HpackEntryDecoderVLoggingListener listener_;
+};
+
+TEST_F(HpackEntryDecoderTest, IndexedHeader_Literals) {
+ {
+ const char input[] = {0x82u}; // == Index 2 ==
+ DecodeBuffer b(input);
+ NoArgValidator do_check = [this]() {
+ VERIFY_AND_RETURN_SUCCESS(collector_.ValidateIndexedHeader(2));
+ };
+ EXPECT_TRUE(
+ DecodeAndValidateSeveralWays(&b, ValidateDoneAndEmpty(do_check)));
+ EXPECT_TRUE(do_check());
+ }
+ collector_.Clear();
+ {
+ const char input[] = {0xfeu}; // == Index 126 ==
+ DecodeBuffer b(input);
+ NoArgValidator do_check = [this]() {
+ VERIFY_AND_RETURN_SUCCESS(collector_.ValidateIndexedHeader(126));
+ };
+ EXPECT_TRUE(
+ DecodeAndValidateSeveralWays(&b, ValidateDoneAndEmpty(do_check)));
+ EXPECT_TRUE(do_check());
+ }
+ collector_.Clear();
+ {
+ const char input[] = {0xffu, 0x00}; // == Index 127 ==
+ DecodeBuffer b(input);
+ NoArgValidator do_check = [this]() {
+ VERIFY_AND_RETURN_SUCCESS(collector_.ValidateIndexedHeader(127));
+ };
+ EXPECT_TRUE(
+ DecodeAndValidateSeveralWays(&b, ValidateDoneAndEmpty(do_check)));
+ EXPECT_TRUE(do_check());
+ }
+}
+
+TEST_F(HpackEntryDecoderTest, IndexedHeader_Various) {
+ // Indices chosen to hit encoding and table boundaries.
+ for (const uint32_t ndx : {1, 2, 61, 62, 63, 126, 127, 254, 255, 256}) {
+ HpackBlockBuilder hbb;
+ hbb.AppendIndexedHeader(ndx);
+
+ NoArgValidator do_check = [this, ndx]() {
+ VERIFY_AND_RETURN_SUCCESS(collector_.ValidateIndexedHeader(ndx));
+ };
+ EXPECT_TRUE(
+ DecodeAndValidateSeveralWays(hbb, ValidateDoneAndEmpty(do_check)));
+ EXPECT_TRUE(do_check());
+ }
+}
+
+TEST_F(HpackEntryDecoderTest, IndexedLiteralValue_Literal) {
+ const char input[] =
+ "\x7f" // == Literal indexed, name index 0x40 ==
+ "\x01" // 2nd byte of name index (0x01 + 0x3f == 0x40)
+ "\x0d" // Value length (13)
+ "custom-header"; // Value
+ DecodeBuffer b(input, sizeof input - 1);
+ NoArgValidator do_check = [this]() {
+ VERIFY_AND_RETURN_SUCCESS(collector_.ValidateLiteralValueHeader(
+ HpackEntryType::kIndexedLiteralHeader, 0x40, false, "custom-header"));
+ };
+ EXPECT_TRUE(DecodeAndValidateSeveralWays(&b, ValidateDoneAndEmpty(do_check)));
+ EXPECT_TRUE(do_check());
+}
+
+TEST_F(HpackEntryDecoderTest, IndexedLiteralNameValue_Literal) {
+ const char input[] =
+ "\x40" // == Literal indexed ==
+ "\x0a" // Name length (10)
+ "custom-key" // Name
+ "\x0d" // Value length (13)
+ "custom-header"; // Value
+
+ DecodeBuffer b(input, sizeof input - 1);
+ NoArgValidator do_check = [this]() {
+ VERIFY_AND_RETURN_SUCCESS(collector_.ValidateLiteralNameValueHeader(
+ HpackEntryType::kIndexedLiteralHeader, false, "custom-key", false,
+ "custom-header"));
+ };
+ EXPECT_TRUE(DecodeAndValidateSeveralWays(&b, ValidateDoneAndEmpty(do_check)));
+ EXPECT_TRUE(do_check());
+}
+
+TEST_F(HpackEntryDecoderTest, DynamicTableSizeUpdate_Literal) {
+ // Size update, length 31.
+ const char input[] = "\x3f\x00";
+ DecodeBuffer b(input, 2);
+ NoArgValidator do_check = [this]() {
+ VERIFY_AND_RETURN_SUCCESS(collector_.ValidateDynamicTableSizeUpdate(31));
+ };
+ EXPECT_TRUE(DecodeAndValidateSeveralWays(&b, ValidateDoneAndEmpty(do_check)));
+ EXPECT_TRUE(do_check());
+}
+
+class HpackLiteralEntryDecoderTest
+ : public HpackEntryDecoderTest,
+ public ::testing::WithParamInterface<HpackEntryType> {
+
+ protected:
+ HpackLiteralEntryDecoderTest() : entry_type_(GetParam()) {}
+
+ const HpackEntryType entry_type_;
+};
+
+INSTANTIATE_TEST_CASE_P(
+ AllLiteralTypes,
+ HpackLiteralEntryDecoderTest,
+ testing::Values(HpackEntryType::kIndexedLiteralHeader,
+ HpackEntryType::kUnindexedLiteralHeader,
+ HpackEntryType::kNeverIndexedLiteralHeader));
+
+TEST_P(HpackLiteralEntryDecoderTest, RandNameIndexAndLiteralValue) {
+ for (int n = 0; n < 10; n++) {
+ const uint32_t ndx = 1 + Random().Rand8();
+ const bool value_is_huffman_encoded = (n % 2) == 0;
+ const string value = Random().RandString(Random().Rand8());
+ HpackBlockBuilder hbb;
+ hbb.AppendNameIndexAndLiteralValue(entry_type_, ndx,
+ value_is_huffman_encoded, value);
+ NoArgValidator do_check = [this, ndx, value_is_huffman_encoded,
+ value]() -> AssertionResult {
+ VERIFY_AND_RETURN_SUCCESS(collector_.ValidateLiteralValueHeader(
+ entry_type_, ndx, value_is_huffman_encoded, value));
+ };
+ EXPECT_TRUE(
+ DecodeAndValidateSeveralWays(hbb, ValidateDoneAndEmpty(do_check)));
+ EXPECT_TRUE(do_check());
+ }
+}
+
+TEST_P(HpackLiteralEntryDecoderTest, RandLiteralNameAndValue) {
+ for (int n = 0; n < 10; n++) {
+ const bool name_is_huffman_encoded = (n & 1) == 0;
+ const int name_len = 1 + Random().Rand8();
+ const string name = Random().RandString(name_len);
+ const bool value_is_huffman_encoded = (n & 2) == 0;
+ const int value_len = Random().Skewed(10);
+ const string value = Random().RandString(value_len);
+ HpackBlockBuilder hbb;
+ hbb.AppendLiteralNameAndValue(entry_type_, name_is_huffman_encoded, name,
+ value_is_huffman_encoded, value);
+ NoArgValidator do_check = [this, name_is_huffman_encoded, name,
+ value_is_huffman_encoded,
+ value]() -> AssertionResult {
+ VERIFY_AND_RETURN_SUCCESS(collector_.ValidateLiteralNameValueHeader(
+ entry_type_, name_is_huffman_encoded, name, value_is_huffman_encoded,
+ value));
+ };
+ EXPECT_TRUE(
+ DecodeAndValidateSeveralWays(hbb, ValidateDoneAndEmpty(do_check)));
+ EXPECT_TRUE(do_check());
+ }
+}
+
+} // namespace
+} // namespace test
+} // namespace net
diff --git a/chromium/net/http2/hpack/decoder/hpack_entry_type_decoder.cc b/chromium/net/http2/hpack/decoder/hpack_entry_type_decoder.cc
new file mode 100644
index 00000000000..a05d48b1ccd
--- /dev/null
+++ b/chromium/net/http2/hpack/decoder/hpack_entry_type_decoder.cc
@@ -0,0 +1,360 @@
+// Copyright 2016 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.
+
+#include "net/http2/hpack/decoder/hpack_entry_type_decoder.h"
+
+#include <sstream>
+
+#include "base/logging.h"
+
+namespace net {
+
+std::string HpackEntryTypeDecoder::DebugString() const {
+ std::stringstream ss;
+ ss << "HpackEntryTypeDecoder(varint_decoder=" << varint_decoder_.DebugString()
+ << ", entry_type=" << entry_type_ << ")";
+ return ss.str();
+}
+
+std::ostream& operator<<(std::ostream& out, const HpackEntryTypeDecoder& v) {
+ return out << v.DebugString();
+}
+
+// This ridiculous looking function turned out to be the winner in benchmarking
+// of several very different alternative implementations. It would be even
+// faster (~7%) if inlined in the header file, but I'm not sure if that is
+// worth doing... yet.
+// TODO(jamessynge): Benchmark again at a higher level (e.g. at least at the
+// full HTTP/2 decoder level, but preferably still higher) to determine if the
+// alternatives that take less code/data space are preferable in that situation.
+DecodeStatus HpackEntryTypeDecoder::Start(DecodeBuffer* db) {
+ DCHECK(db != nullptr);
+ DCHECK(db->HasData());
+
+ // The high four bits (nibble) of first byte of the entry determine the type
+ // of the entry, and may also be the initial bits of the varint that
+ // represents an index or table size. Note the use of the word 'initial'
+ // rather than 'high'; the HPACK encoding of varints is not in network
+ // order (i.e. not big-endian, the high-order byte isn't first), nor in
+ // little-endian order. See:
+ // http://httpwg.org/specs/rfc7541.html#integer.representation
+ uint8_t byte = db->DecodeUInt8();
+ switch (byte) {
+ case 0b00000000:
+ case 0b00000001:
+ case 0b00000010:
+ case 0b00000011:
+ case 0b00000100:
+ case 0b00000101:
+ case 0b00000110:
+ case 0b00000111:
+ case 0b00001000:
+ case 0b00001001:
+ case 0b00001010:
+ case 0b00001011:
+ case 0b00001100:
+ case 0b00001101:
+ case 0b00001110:
+ // The low 4 bits of |byte| are the initial bits of the varint.
+ // One of those bits is 0, so the varint is only one byte long.
+ entry_type_ = HpackEntryType::kUnindexedLiteralHeader;
+ varint_decoder_.set_value(byte);
+ return DecodeStatus::kDecodeDone;
+
+ case 0b00001111:
+ // The low 4 bits of |byte| are the initial bits of the varint. All 4
+ // are 1, so the varint extends into another byte.
+ entry_type_ = HpackEntryType::kUnindexedLiteralHeader;
+ return varint_decoder_.StartExtended(0x0f, db);
+
+ case 0b00010000:
+ case 0b00010001:
+ case 0b00010010:
+ case 0b00010011:
+ case 0b00010100:
+ case 0b00010101:
+ case 0b00010110:
+ case 0b00010111:
+ case 0b00011000:
+ case 0b00011001:
+ case 0b00011010:
+ case 0b00011011:
+ case 0b00011100:
+ case 0b00011101:
+ case 0b00011110:
+ // The low 4 bits of |byte| are the initial bits of the varint.
+ // One of those bits is 0, so the varint is only one byte long.
+ entry_type_ = HpackEntryType::kNeverIndexedLiteralHeader;
+ varint_decoder_.set_value(byte & 0x0f);
+ return DecodeStatus::kDecodeDone;
+
+ case 0b00011111:
+ // The low 4 bits of |byte| are the initial bits of the varint.
+ // All of those bits are 1, so the varint extends into another byte.
+ entry_type_ = HpackEntryType::kNeverIndexedLiteralHeader;
+ return varint_decoder_.StartExtended(0x0f, db);
+
+ case 0b00100000:
+ case 0b00100001:
+ case 0b00100010:
+ case 0b00100011:
+ case 0b00100100:
+ case 0b00100101:
+ case 0b00100110:
+ case 0b00100111:
+ case 0b00101000:
+ case 0b00101001:
+ case 0b00101010:
+ case 0b00101011:
+ case 0b00101100:
+ case 0b00101101:
+ case 0b00101110:
+ case 0b00101111:
+ case 0b00110000:
+ case 0b00110001:
+ case 0b00110010:
+ case 0b00110011:
+ case 0b00110100:
+ case 0b00110101:
+ case 0b00110110:
+ case 0b00110111:
+ case 0b00111000:
+ case 0b00111001:
+ case 0b00111010:
+ case 0b00111011:
+ case 0b00111100:
+ case 0b00111101:
+ case 0b00111110:
+ entry_type_ = HpackEntryType::kDynamicTableSizeUpdate;
+ // The low 5 bits of |byte| are the initial bits of the varint.
+ // One of those bits is 0, so the varint is only one byte long.
+ varint_decoder_.set_value(byte & 0x01f);
+ return DecodeStatus::kDecodeDone;
+
+ case 0b00111111:
+ entry_type_ = HpackEntryType::kDynamicTableSizeUpdate;
+ // The low 5 bits of |byte| are the initial bits of the varint.
+ // All of those bits are 1, so the varint extends into another byte.
+ return varint_decoder_.StartExtended(0x1f, db);
+
+ case 0b01000000:
+ case 0b01000001:
+ case 0b01000010:
+ case 0b01000011:
+ case 0b01000100:
+ case 0b01000101:
+ case 0b01000110:
+ case 0b01000111:
+ case 0b01001000:
+ case 0b01001001:
+ case 0b01001010:
+ case 0b01001011:
+ case 0b01001100:
+ case 0b01001101:
+ case 0b01001110:
+ case 0b01001111:
+ case 0b01010000:
+ case 0b01010001:
+ case 0b01010010:
+ case 0b01010011:
+ case 0b01010100:
+ case 0b01010101:
+ case 0b01010110:
+ case 0b01010111:
+ case 0b01011000:
+ case 0b01011001:
+ case 0b01011010:
+ case 0b01011011:
+ case 0b01011100:
+ case 0b01011101:
+ case 0b01011110:
+ case 0b01011111:
+ case 0b01100000:
+ case 0b01100001:
+ case 0b01100010:
+ case 0b01100011:
+ case 0b01100100:
+ case 0b01100101:
+ case 0b01100110:
+ case 0b01100111:
+ case 0b01101000:
+ case 0b01101001:
+ case 0b01101010:
+ case 0b01101011:
+ case 0b01101100:
+ case 0b01101101:
+ case 0b01101110:
+ case 0b01101111:
+ case 0b01110000:
+ case 0b01110001:
+ case 0b01110010:
+ case 0b01110011:
+ case 0b01110100:
+ case 0b01110101:
+ case 0b01110110:
+ case 0b01110111:
+ case 0b01111000:
+ case 0b01111001:
+ case 0b01111010:
+ case 0b01111011:
+ case 0b01111100:
+ case 0b01111101:
+ case 0b01111110:
+ entry_type_ = HpackEntryType::kIndexedLiteralHeader;
+ // The low 6 bits of |byte| are the initial bits of the varint.
+ // One of those bits is 0, so the varint is only one byte long.
+ varint_decoder_.set_value(byte & 0x03f);
+ return DecodeStatus::kDecodeDone;
+
+ case 0b01111111:
+ entry_type_ = HpackEntryType::kIndexedLiteralHeader;
+ // The low 6 bits of |byte| are the initial bits of the varint.
+ // All of those bits are 1, so the varint extends into another byte.
+ return varint_decoder_.StartExtended(0x3f, db);
+
+ case 0b10000000:
+ case 0b10000001:
+ case 0b10000010:
+ case 0b10000011:
+ case 0b10000100:
+ case 0b10000101:
+ case 0b10000110:
+ case 0b10000111:
+ case 0b10001000:
+ case 0b10001001:
+ case 0b10001010:
+ case 0b10001011:
+ case 0b10001100:
+ case 0b10001101:
+ case 0b10001110:
+ case 0b10001111:
+ case 0b10010000:
+ case 0b10010001:
+ case 0b10010010:
+ case 0b10010011:
+ case 0b10010100:
+ case 0b10010101:
+ case 0b10010110:
+ case 0b10010111:
+ case 0b10011000:
+ case 0b10011001:
+ case 0b10011010:
+ case 0b10011011:
+ case 0b10011100:
+ case 0b10011101:
+ case 0b10011110:
+ case 0b10011111:
+ case 0b10100000:
+ case 0b10100001:
+ case 0b10100010:
+ case 0b10100011:
+ case 0b10100100:
+ case 0b10100101:
+ case 0b10100110:
+ case 0b10100111:
+ case 0b10101000:
+ case 0b10101001:
+ case 0b10101010:
+ case 0b10101011:
+ case 0b10101100:
+ case 0b10101101:
+ case 0b10101110:
+ case 0b10101111:
+ case 0b10110000:
+ case 0b10110001:
+ case 0b10110010:
+ case 0b10110011:
+ case 0b10110100:
+ case 0b10110101:
+ case 0b10110110:
+ case 0b10110111:
+ case 0b10111000:
+ case 0b10111001:
+ case 0b10111010:
+ case 0b10111011:
+ case 0b10111100:
+ case 0b10111101:
+ case 0b10111110:
+ case 0b10111111:
+ case 0b11000000:
+ case 0b11000001:
+ case 0b11000010:
+ case 0b11000011:
+ case 0b11000100:
+ case 0b11000101:
+ case 0b11000110:
+ case 0b11000111:
+ case 0b11001000:
+ case 0b11001001:
+ case 0b11001010:
+ case 0b11001011:
+ case 0b11001100:
+ case 0b11001101:
+ case 0b11001110:
+ case 0b11001111:
+ case 0b11010000:
+ case 0b11010001:
+ case 0b11010010:
+ case 0b11010011:
+ case 0b11010100:
+ case 0b11010101:
+ case 0b11010110:
+ case 0b11010111:
+ case 0b11011000:
+ case 0b11011001:
+ case 0b11011010:
+ case 0b11011011:
+ case 0b11011100:
+ case 0b11011101:
+ case 0b11011110:
+ case 0b11011111:
+ case 0b11100000:
+ case 0b11100001:
+ case 0b11100010:
+ case 0b11100011:
+ case 0b11100100:
+ case 0b11100101:
+ case 0b11100110:
+ case 0b11100111:
+ case 0b11101000:
+ case 0b11101001:
+ case 0b11101010:
+ case 0b11101011:
+ case 0b11101100:
+ case 0b11101101:
+ case 0b11101110:
+ case 0b11101111:
+ case 0b11110000:
+ case 0b11110001:
+ case 0b11110010:
+ case 0b11110011:
+ case 0b11110100:
+ case 0b11110101:
+ case 0b11110110:
+ case 0b11110111:
+ case 0b11111000:
+ case 0b11111001:
+ case 0b11111010:
+ case 0b11111011:
+ case 0b11111100:
+ case 0b11111101:
+ case 0b11111110:
+ entry_type_ = HpackEntryType::kIndexedHeader;
+ // The low 7 bits of |byte| are the initial bits of the varint.
+ // One of those bits is 0, so the varint is only one byte long.
+ varint_decoder_.set_value(byte & 0x07f);
+ return DecodeStatus::kDecodeDone;
+
+ case 0b11111111:
+ entry_type_ = HpackEntryType::kIndexedHeader;
+ // The low 7 bits of |byte| are the initial bits of the varint.
+ // All of those bits are 1, so the varint extends into another byte.
+ return varint_decoder_.StartExtended(0x7f, db);
+ }
+ CHECK(false) << "Unreachable, byte=" << std::hex
+ << static_cast<uint32_t>(byte);
+ return DecodeStatus::kDecodeError;
+}
+
+} // namespace net
diff --git a/chromium/net/http2/hpack/decoder/hpack_entry_type_decoder.h b/chromium/net/http2/hpack/decoder/hpack_entry_type_decoder.h
new file mode 100644
index 00000000000..d2c1f54d219
--- /dev/null
+++ b/chromium/net/http2/hpack/decoder/hpack_entry_type_decoder.h
@@ -0,0 +1,56 @@
+// Copyright 2016 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.
+
+#ifndef NET_HTTP2_HPACK_DECODER_HPACK_ENTRY_TYPE_DECODER_H_
+#define NET_HTTP2_HPACK_DECODER_HPACK_ENTRY_TYPE_DECODER_H_
+
+// Decodes the type of an HPACK entry, and the variable length integer whose
+// prefix is in the low-order bits of the same byte, "below" the type bits.
+// The integer represents an index into static or dynamic table, which may be
+// zero, or is the new size limit of the dynamic table.
+
+#include <string>
+
+#include "base/logging.h"
+#include "net/base/net_export.h"
+#include "net/http2/decoder/decode_buffer.h"
+#include "net/http2/decoder/decode_status.h"
+#include "net/http2/hpack/decoder/hpack_varint_decoder.h"
+#include "net/http2/hpack/http2_hpack_constants.h"
+
+namespace net {
+
+class NET_EXPORT_PRIVATE HpackEntryTypeDecoder {
+ public:
+ // Only call when the decode buffer has data (i.e. HpackEntryDecoder must
+ // not call until there is data).
+ DecodeStatus Start(DecodeBuffer* db);
+
+ // Only call Resume if the previous call (Start or Resume) returned
+ // DecodeStatus::kDecodeInProgress.
+ DecodeStatus Resume(DecodeBuffer* db) { return varint_decoder_.Resume(db); }
+
+ // Returns the decoded entry type. Only call if the preceding call to Start
+ // or Resume returned kDecodeDone.
+ HpackEntryType entry_type() const { return entry_type_; }
+
+ // Returns the decoded variable length integer. Only call if the
+ // preceding call to Start or Resume returned kDecodeDone.
+ uint32_t varint() const { return varint_decoder_.value(); }
+
+ std::string DebugString() const;
+
+ private:
+ HpackVarintDecoder varint_decoder_;
+
+ // This field is initialized just to keep ASAN happy about reading it
+ // from DebugString().
+ HpackEntryType entry_type_ = HpackEntryType::kIndexedHeader;
+};
+
+NET_EXPORT_PRIVATE std::ostream& operator<<(std::ostream& out,
+ const HpackEntryTypeDecoder& v);
+
+} // namespace net
+#endif // NET_HTTP2_HPACK_DECODER_HPACK_ENTRY_TYPE_DECODER_H_
diff --git a/chromium/net/http2/hpack/decoder/hpack_entry_type_decoder_test.cc b/chromium/net/http2/hpack/decoder/hpack_entry_type_decoder_test.cc
new file mode 100644
index 00000000000..9f72eb67fe2
--- /dev/null
+++ b/chromium/net/http2/hpack/decoder/hpack_entry_type_decoder_test.cc
@@ -0,0 +1,88 @@
+// Copyright 2016 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.
+
+#include "net/http2/hpack/decoder/hpack_entry_type_decoder.h"
+
+#include <vector>
+
+#include "base/logging.h"
+#include "net/http2/hpack/tools/hpack_block_builder.h"
+#include "net/http2/tools/failure.h"
+#include "net/http2/tools/random_decoder_test.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+using ::testing::AssertionFailure;
+using ::testing::AssertionResult;
+using ::testing::AssertionSuccess;
+
+namespace net {
+namespace test {
+namespace {
+const bool kReturnNonZeroOnFirst = true;
+
+class HpackEntryTypeDecoderTest : public RandomDecoderTest {
+
+ protected:
+ DecodeStatus StartDecoding(DecodeBuffer* b) override {
+ CHECK_LT(0u, b->Remaining());
+ return decoder_.Start(b);
+ }
+
+ DecodeStatus ResumeDecoding(DecodeBuffer* b) override {
+ return decoder_.Resume(b);
+ }
+
+ HpackEntryTypeDecoder decoder_;
+};
+
+TEST_F(HpackEntryTypeDecoderTest, DynamicTableSizeUpdate) {
+ for (uint32_t size = 0; size < 1000 * 1000; size += 256) {
+ HpackBlockBuilder bb;
+ bb.AppendDynamicTableSizeUpdate(size);
+ DecodeBuffer db(bb.buffer());
+ NoArgValidator validator = [size, this]() -> AssertionResult {
+ VERIFY_EQ(HpackEntryType::kDynamicTableSizeUpdate, decoder_.entry_type());
+ VERIFY_EQ(size, decoder_.varint());
+ return AssertionSuccess();
+ };
+ EXPECT_TRUE(DecodeAndValidateSeveralWays(&db, kReturnNonZeroOnFirst,
+ ValidateDoneAndEmpty(validator)))
+ << "\nentry_type=kDynamicTableSizeUpdate, size=" << size;
+ // Run the validator again to make sure that DecodeAndValidateSeveralWays
+ // did the right thing.
+ EXPECT_TRUE(validator());
+ }
+}
+
+TEST_F(HpackEntryTypeDecoderTest, HeaderWithIndex) {
+ std::vector<HpackEntryType> entry_types = {
+ HpackEntryType::kIndexedHeader, HpackEntryType::kIndexedLiteralHeader,
+ HpackEntryType::kUnindexedLiteralHeader,
+ HpackEntryType::kNeverIndexedLiteralHeader,
+ };
+ for (const HpackEntryType entry_type : entry_types) {
+ const uint32_t first = entry_type == HpackEntryType::kIndexedHeader ? 1 : 0;
+ for (uint32_t index = first; index < 1000; ++index) {
+ HpackBlockBuilder bb;
+ bb.AppendEntryTypeAndVarint(entry_type, index);
+ DecodeBuffer db(bb.buffer());
+ NoArgValidator validator = [entry_type, index,
+ this]() -> AssertionResult {
+ VERIFY_EQ(entry_type, decoder_.entry_type());
+ VERIFY_EQ(index, decoder_.varint());
+ return AssertionSuccess();
+ };
+ EXPECT_TRUE(DecodeAndValidateSeveralWays(&db, kReturnNonZeroOnFirst,
+ ValidateDoneAndEmpty(validator)))
+ << "\nentry_type=" << entry_type << ", index=" << index;
+ // Run the validator again to make sure that DecodeAndValidateSeveralWays
+ // did the right thing.
+ EXPECT_TRUE(validator());
+ }
+ }
+}
+
+} // namespace
+} // namespace test
+} // namespace net
diff --git a/chromium/net/http2/hpack/decoder/hpack_string_collector.cc b/chromium/net/http2/hpack/decoder/hpack_string_collector.cc
new file mode 100644
index 00000000000..e7e8195f748
--- /dev/null
+++ b/chromium/net/http2/hpack/decoder/hpack_string_collector.cc
@@ -0,0 +1,127 @@
+// Copyright 2016 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.
+
+#include "net/http2/hpack/decoder/hpack_string_collector.h"
+
+#include <stddef.h>
+
+#include <iosfwd>
+#include <ostream>
+#include <string>
+
+#include "net/base/escape.h"
+#include "net/http2/tools/failure.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+using base::StringPiece;
+
+namespace net {
+namespace test {
+namespace {
+
+std::ostream& operator<<(std::ostream& out,
+ HpackStringCollector::CollectorState v) {
+ switch (v) {
+ case HpackStringCollector::CollectorState::kGenesis:
+ return out << "kGenesis";
+ case HpackStringCollector::CollectorState::kStarted:
+ return out << "kStarted";
+ case HpackStringCollector::CollectorState::kEnded:
+ return out << "kEnded";
+ }
+ return out << "UnknownCollectorState";
+}
+
+} // namespace
+
+HpackStringCollector::HpackStringCollector() {
+ Clear();
+}
+
+HpackStringCollector::HpackStringCollector(const std::string& str, bool huffman)
+ : s(str), len(str.size()), huffman_encoded(huffman), state(kEnded) {}
+
+void HpackStringCollector::Clear() {
+ s = "";
+ len = 0;
+ huffman_encoded = false;
+ state = kGenesis;
+}
+
+bool HpackStringCollector::IsClear() const {
+ return s == "" && len == 0 && huffman_encoded == false && state == kGenesis;
+}
+
+bool HpackStringCollector::IsInProgress() const {
+ return state == kStarted;
+}
+
+bool HpackStringCollector::HasEnded() const {
+ return state == kEnded;
+}
+
+void HpackStringCollector::OnStringStart(bool huffman, size_t length) {
+ EXPECT_TRUE(IsClear()) << ToString();
+ state = kStarted;
+ huffman_encoded = huffman;
+ len = length;
+ return;
+}
+
+void HpackStringCollector::OnStringData(const char* data, size_t length) {
+ StringPiece sp(data, length);
+ EXPECT_TRUE(IsInProgress()) << ToString();
+ EXPECT_LE(sp.size(), len) << ToString();
+ sp.AppendToString(&s);
+ EXPECT_LE(s.size(), len) << ToString();
+}
+
+void HpackStringCollector::OnStringEnd() {
+ EXPECT_TRUE(IsInProgress()) << ToString();
+ EXPECT_EQ(s.size(), len) << ToString();
+ state = kEnded;
+}
+
+::testing::AssertionResult HpackStringCollector::Collected(
+ StringPiece str,
+ bool is_huffman_encoded) const {
+ VERIFY_TRUE(HasEnded());
+ VERIFY_EQ(str.size(), len);
+ VERIFY_EQ(is_huffman_encoded, huffman_encoded);
+ VERIFY_EQ(str, s);
+ return ::testing::AssertionSuccess();
+}
+
+std::string HpackStringCollector::ToString() const {
+ std::stringstream ss;
+ ss << *this;
+ return ss.str();
+}
+
+bool operator==(const HpackStringCollector& a, const HpackStringCollector& b) {
+ return a.s == b.s && a.len == b.len &&
+ a.huffman_encoded == b.huffman_encoded && a.state == b.state;
+}
+
+bool operator!=(const HpackStringCollector& a, const HpackStringCollector& b) {
+ return !(a == b);
+}
+
+std::ostream& operator<<(std::ostream& out, const HpackStringCollector& v) {
+ out << "HpackStringCollector(state=" << v.state;
+ if (v.state == HpackStringCollector::kGenesis) {
+ return out << ")";
+ }
+ if (v.huffman_encoded) {
+ out << ", Huffman Encoded";
+ }
+ out << ", Length=" << v.len;
+ if (!v.s.empty() && v.len != v.s.size()) {
+ out << " (" << v.s.size() << ")";
+ }
+ return out << ", String=\"" << EscapeQueryParamValue(v.s, false) << "\")";
+}
+
+} // namespace test
+} // namespace net
diff --git a/chromium/net/http2/hpack/decoder/hpack_string_collector.h b/chromium/net/http2/hpack/decoder/hpack_string_collector.h
new file mode 100644
index 00000000000..1bc58310044
--- /dev/null
+++ b/chromium/net/http2/hpack/decoder/hpack_string_collector.h
@@ -0,0 +1,63 @@
+// Copyright 2016 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.
+
+#ifndef NET_HTTP2_HPACK_DECODER_HPACK_STRING_COLLECTOR_H_
+#define NET_HTTP2_HPACK_DECODER_HPACK_STRING_COLLECTOR_H_
+
+// Supports tests of decoding HPACK strings.
+
+#include <stddef.h>
+
+#include <iosfwd>
+#include <string>
+
+#include "base/strings/string_piece.h"
+#include "net/http2/hpack/decoder/hpack_string_decoder_listener.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace net {
+namespace test {
+
+// Records the callbacks associated with a decoding a string; must
+// call Clear() between decoding successive strings.
+struct HpackStringCollector : public HpackStringDecoderListener {
+ enum CollectorState {
+ kGenesis,
+ kStarted,
+ kEnded,
+ };
+
+ HpackStringCollector();
+ HpackStringCollector(const std::string& str, bool huffman);
+
+ void Clear();
+ bool IsClear() const;
+ bool IsInProgress() const;
+ bool HasEnded() const;
+
+ void OnStringStart(bool huffman, size_t length) override;
+ void OnStringData(const char* data, size_t length) override;
+ void OnStringEnd() override;
+
+ ::testing::AssertionResult Collected(base::StringPiece str,
+ bool is_huffman_encoded) const;
+
+ std::string ToString() const;
+
+ std::string s;
+ size_t len;
+ bool huffman_encoded;
+ CollectorState state;
+};
+
+bool operator==(const HpackStringCollector& a, const HpackStringCollector& b);
+
+bool operator!=(const HpackStringCollector& a, const HpackStringCollector& b);
+
+std::ostream& operator<<(std::ostream& out, const HpackStringCollector& v);
+
+} // namespace test
+} // namespace net
+
+#endif // NET_HTTP2_HPACK_DECODER_HPACK_STRING_COLLECTOR_H_
diff --git a/chromium/net/http2/hpack/decoder/hpack_string_decoder.cc b/chromium/net/http2/hpack/decoder/hpack_string_decoder.cc
new file mode 100644
index 00000000000..4131e01b5ce
--- /dev/null
+++ b/chromium/net/http2/hpack/decoder/hpack_string_decoder.cc
@@ -0,0 +1,39 @@
+// Copyright 2016 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.
+
+#include "net/http2/hpack/decoder/hpack_string_decoder.h"
+
+#include <sstream>
+
+namespace net {
+
+std::string HpackStringDecoder::DebugString() const {
+ std::stringstream ss;
+ ss << "HpackStringDecoder(state=" << StateToString(state_)
+ << ", length=" << length_decoder_.DebugString()
+ << ", remaining=" << remaining_
+ << ", huffman=" << (huffman_encoded_ ? "true)" : "false)");
+ return ss.str();
+}
+
+// static
+std::string HpackStringDecoder::StateToString(StringDecoderState v) {
+ switch (v) {
+ case kStartDecodingLength:
+ return "kStartDecodingLength";
+ case kDecodingString:
+ return "kDecodingString";
+ case kResumeDecodingLength:
+ return "kResumeDecodingLength";
+ }
+ std::stringstream ss;
+ ss << "UNKNOWN_STATE(" << static_cast<uint32_t>(v) << ")";
+ return ss.str();
+}
+
+std::ostream& operator<<(std::ostream& out, const HpackStringDecoder& v) {
+ return out << v.DebugString();
+}
+
+} // namespace net
diff --git a/chromium/net/http2/hpack/decoder/hpack_string_decoder.h b/chromium/net/http2/hpack/decoder/hpack_string_decoder.h
new file mode 100644
index 00000000000..baea422cebf
--- /dev/null
+++ b/chromium/net/http2/hpack/decoder/hpack_string_decoder.h
@@ -0,0 +1,236 @@
+// Copyright 2016 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.
+
+#ifndef NET_HTTP2_HPACK_DECODER_HPACK_STRING_DECODER_H_
+#define NET_HTTP2_HPACK_DECODER_HPACK_STRING_DECODER_H_
+
+// HpackStringDecoder decodes strings encoded per the HPACK spec; this does
+// not mean decompressing Huffman encoded strings, just identifying the length,
+// encoding and contents for a listener.
+
+#include <stddef.h>
+
+#include <algorithm>
+#include <string>
+
+#include "base/logging.h"
+#include "base/macros.h"
+#include "net/base/net_export.h"
+#include "net/http2/decoder/decode_buffer.h"
+#include "net/http2/decoder/decode_status.h"
+#include "net/http2/hpack/decoder/hpack_varint_decoder.h"
+
+namespace net {
+
+// Decodes a single string in an HPACK header entry. The high order bit of
+// the first byte of the length is the H (Huffman) bit indicating whether
+// the value is Huffman encoded, and the remainder of the byte is the first
+// 7 bits of an HPACK varint.
+//
+// Call Start() to begin decoding; if it returns kDecodeInProgress, then call
+// Resume() when more input is available, repeating until kDecodeInProgress is
+// not returned. If kDecodeDone or kDecodeError is returned, then Resume() must
+// not be called until Start() has been called to start decoding a new string.
+//
+// There are 3 variants of Start in this class, participants in a performance
+// experiment. Perflab experiments show it is generally fastest to call
+// StartSpecialCaseShort rather than StartOnly (~9% slower) or
+// StartAndDecodeLength (~10% slower).
+class NET_EXPORT_PRIVATE HpackStringDecoder {
+ public:
+ enum StringDecoderState {
+ kStartDecodingLength,
+ kDecodingString,
+ kResumeDecodingLength,
+ };
+
+ // TODO(jamessynge): Get rid of all but one of the Start and Resume methods
+ // after all of the HPACK decoder is checked in and has been perf tested.
+ template <class Listener>
+ DecodeStatus Start(DecodeBuffer* db, Listener* cb) {
+ return StartSpecialCaseShort(db, cb);
+ }
+
+ template <class Listener>
+ DecodeStatus StartOnly(DecodeBuffer* db, Listener* cb) {
+ state_ = kStartDecodingLength;
+ return Resume(db, cb);
+ }
+
+ template <class Listener>
+ DecodeStatus StartAndDecodeLength(DecodeBuffer* db, Listener* cb) {
+ DecodeStatus status;
+ if (StartDecodingLength(db, cb, &status)) {
+ state_ = kDecodingString;
+ return DecodeString(db, cb);
+ }
+ return status;
+ }
+
+ template <class Listener>
+ DecodeStatus StartSpecialCaseShort(DecodeBuffer* db, Listener* cb) {
+ // Fast decode path is used if the string is under 127 bytes and the
+ // entire length of the string is in the decode buffer. More than 83% of
+ // string lengths are encoded in just one byte.
+ if (db->HasData() && (*db->cursor() & 0x7f) != 0x7f) {
+ // The string is short.
+ uint8_t h_and_prefix = db->DecodeUInt8();
+ uint8_t length = h_and_prefix & 0x7f;
+ bool huffman_encoded = (h_and_prefix & 0x80) == 0x80;
+ cb->OnStringStart(huffman_encoded, length);
+ if (length <= db->Remaining()) {
+ // Yeah, we've got the whole thing in the decode buffer.
+ // Ideally this will be the common case. Note that we don't
+ // update any of the member variables in this path.
+ cb->OnStringData(db->cursor(), length);
+ db->AdvanceCursor(length);
+ cb->OnStringEnd();
+ return DecodeStatus::kDecodeDone;
+ }
+ // Not all in the buffer.
+ huffman_encoded_ = huffman_encoded;
+ remaining_ = length;
+ // Call Resume to decode the string body, which is only partially
+ // in the decode buffer (or not at all).
+ state_ = kDecodingString;
+ return Resume(db, cb);
+ }
+ // Call Resume to decode the string length, which is either not in
+ // the decode buffer, or spans multiple bytes.
+ state_ = kStartDecodingLength;
+ return Resume(db, cb);
+ }
+
+ template <class Listener>
+ DecodeStatus Resume(DecodeBuffer* db, Listener* cb) {
+ DecodeStatus status;
+ while (true) {
+ switch (state_) {
+ case kStartDecodingLength:
+ DVLOG(2) << "kStartDecodingLength: db->Remaining=" << db->Remaining();
+ if (!StartDecodingLength(db, cb, &status)) {
+ // The length is split across decode buffers.
+ return status;
+ }
+ // We've finished decoding the length, which spanned one or more
+ // bytes. Approximately 17% of strings have a length that is greater
+ // than 126 bytes, and thus the length is encoded in more than one
+ // byte, and so doesn't get the benefit of the optimization in
+ // Start() for single byte lengths. But, we still expect that most
+ // of such strings will be contained entirely in a single decode
+ // buffer, and hence this fall through skips another trip through the
+ // switch above and more importantly skips setting the state_ variable
+ // again in those cases where we don't need it.
+
+ // FALLTHROUGH_INTENDED
+
+ case kDecodingString:
+ DVLOG(2) << "kDecodingString: db->Remaining=" << db->Remaining()
+ << " remaining_=" << remaining_;
+ return DecodeString(db, cb);
+
+ case kResumeDecodingLength:
+ DVLOG(2) << "kResumeDecodingLength: db->Remaining="
+ << db->Remaining();
+ if (!ResumeDecodingLength(db, cb, &status)) {
+ return status;
+ }
+ }
+ }
+ }
+
+ std::string DebugString() const;
+
+ private:
+ static std::string StateToString(StringDecoderState v);
+
+ // Returns true if the length is fully decoded and the listener wants the
+ // decoding to continue, false otherwise; status is set to the status from
+ // the varint decoder.
+ // If the length is not fully decoded, case state_ is set appropriately
+ // for the next call to Resume.
+ template <class Listener>
+ bool StartDecodingLength(DecodeBuffer* db,
+ Listener* cb,
+ DecodeStatus* status) {
+ if (db->Empty()) {
+ *status = DecodeStatus::kDecodeInProgress;
+ state_ = kStartDecodingLength;
+ return false;
+ }
+ uint8_t h_and_prefix = db->DecodeUInt8();
+ huffman_encoded_ = (h_and_prefix & 0x80) == 0x80;
+ *status = length_decoder_.Start(h_and_prefix, 0x7f, db);
+ if (*status == DecodeStatus::kDecodeDone) {
+ OnStringStart(cb, status);
+ return true;
+ }
+ // Set the state to cover the DecodeStatus::kDecodeInProgress case.
+ // Won't be needed if the status is kDecodeError.
+ state_ = kResumeDecodingLength;
+ return false;
+ }
+
+ // Returns true if the length is fully decoded and the listener wants the
+ // decoding to continue, false otherwise; status is set to the status from
+ // the varint decoder; state_ is updated when fully decoded.
+ // If the length is not fully decoded, case state_ is set appropriately
+ // for the next call to Resume.
+ template <class Listener>
+ bool ResumeDecodingLength(DecodeBuffer* db,
+ Listener* cb,
+ DecodeStatus* status) {
+ DCHECK_EQ(state_, kResumeDecodingLength);
+ *status = length_decoder_.Resume(db);
+ if (*status == DecodeStatus::kDecodeDone) {
+ state_ = kDecodingString;
+ OnStringStart(cb, status);
+ return true;
+ }
+ return false;
+ }
+
+ // Returns true if the listener wants the decoding to continue, and
+ // false otherwise, in which case status set.
+ template <class Listener>
+ void OnStringStart(Listener* cb, DecodeStatus* status) {
+ remaining_ = length_decoder_.value();
+ // Make callback so consumer knows what is coming.
+ cb->OnStringStart(huffman_encoded_, remaining_);
+ return;
+ }
+
+ // Passes the available portion of the string to the listener, and signals
+ // the end of the string when it is reached. Returns kDecodeDone or
+ // kDecodeInProgress as appropriate.
+ template <class Listener>
+ DecodeStatus DecodeString(DecodeBuffer* db, Listener* cb) {
+ size_t len = std::min(remaining_, db->Remaining());
+ if (len > 0) {
+ cb->OnStringData(db->cursor(), len);
+ db->AdvanceCursor(len);
+ remaining_ -= len;
+ }
+ if (remaining_ == 0) {
+ cb->OnStringEnd();
+ return DecodeStatus::kDecodeDone;
+ }
+ state_ = kDecodingString;
+ return DecodeStatus::kDecodeInProgress;
+ }
+
+ HpackVarintDecoder length_decoder_;
+
+ // These fields are initialized just to keep ASAN happy about reading
+ // them from DebugString().
+ size_t remaining_ = 0;
+ StringDecoderState state_ = kStartDecodingLength;
+ bool huffman_encoded_ = false;
+};
+
+NET_EXPORT_PRIVATE std::ostream& operator<<(std::ostream& out,
+ const HpackStringDecoder& v);
+
+} // namespace net
+#endif // NET_HTTP2_HPACK_DECODER_HPACK_STRING_DECODER_H_
diff --git a/chromium/net/http2/hpack/decoder/hpack_string_decoder_listener.cc b/chromium/net/http2/hpack/decoder/hpack_string_decoder_listener.cc
new file mode 100644
index 00000000000..97ec985aa54
--- /dev/null
+++ b/chromium/net/http2/hpack/decoder/hpack_string_decoder_listener.cc
@@ -0,0 +1,36 @@
+// Copyright 2016 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.
+
+#include "net/http2/hpack/decoder/hpack_string_decoder_listener.h"
+
+#include "base/logging.h"
+
+namespace net {
+namespace test {
+
+void HpackStringDecoderVLoggingListener::OnStringStart(bool huffman_encoded,
+ size_t len) {
+ VLOG(1) << "OnStringStart: H=" << huffman_encoded << ", len=" << len;
+ if (wrapped_) {
+ wrapped_->OnStringStart(huffman_encoded, len);
+ }
+}
+
+void HpackStringDecoderVLoggingListener::OnStringData(const char* data,
+ size_t len) {
+ VLOG(1) << "OnStringData: len=" << len;
+ if (wrapped_) {
+ return wrapped_->OnStringData(data, len);
+ }
+}
+
+void HpackStringDecoderVLoggingListener::OnStringEnd() {
+ VLOG(1) << "OnStringEnd";
+ if (wrapped_) {
+ return wrapped_->OnStringEnd();
+ }
+}
+
+} // namespace test
+} // namespace net
diff --git a/chromium/net/http2/hpack/decoder/hpack_string_decoder_listener.h b/chromium/net/http2/hpack/decoder/hpack_string_decoder_listener.h
new file mode 100644
index 00000000000..fbeeeb4b544
--- /dev/null
+++ b/chromium/net/http2/hpack/decoder/hpack_string_decoder_listener.h
@@ -0,0 +1,62 @@
+// Copyright 2016 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.
+
+#ifndef NET_HTTP2_HPACK_DECODER_HPACK_STRING_DECODER_LISTENER_H_
+#define NET_HTTP2_HPACK_DECODER_HPACK_STRING_DECODER_LISTENER_H_
+
+// Defines HpackStringDecoderListener which defines the methods required by an
+// HpackStringDecoder. Also defines HpackStringDecoderVLoggingListener which
+// logs before calling another HpackStringDecoderListener implementation.
+// For now these are only used by tests, so placed in the test namespace.
+
+#include <stddef.h>
+
+#include "net/base/net_export.h"
+
+namespace net {
+namespace test {
+
+// HpackStringDecoder methods require a listener that implements the methods
+// below, but it is NOT necessary to extend this class because the methods
+// are templates.
+class NET_EXPORT_PRIVATE HpackStringDecoderListener {
+ public:
+ virtual ~HpackStringDecoderListener() {}
+
+ // Called at the start of decoding an HPACK string. The encoded length of the
+ // string is |len| bytes, which may be zero. The string is Huffman encoded
+ // if huffman_encoded is true, else it is plain text (i.e. the encoded length
+ // is then the plain text length).
+ virtual void OnStringStart(bool huffman_encoded, size_t len) = 0;
+
+ // Called when some data is available, or once when the string length is zero
+ // (to simplify the decoder, it doesn't have a special case for len==0).
+ virtual void OnStringData(const char* data, size_t len) = 0;
+
+ // Called after OnStringData has provided all of the encoded bytes of the
+ // string.
+ virtual void OnStringEnd() = 0;
+};
+
+class NET_EXPORT_PRIVATE HpackStringDecoderVLoggingListener
+ : public HpackStringDecoderListener {
+ public:
+ HpackStringDecoderVLoggingListener() : wrapped_(nullptr) {}
+ explicit HpackStringDecoderVLoggingListener(
+ HpackStringDecoderListener* wrapped)
+ : wrapped_(wrapped) {}
+ ~HpackStringDecoderVLoggingListener() override {}
+
+ void OnStringStart(bool huffman_encoded, size_t len) override;
+ void OnStringData(const char* data, size_t len) override;
+ void OnStringEnd() override;
+
+ private:
+ HpackStringDecoderListener* const wrapped_;
+};
+
+} // namespace test
+} // namespace net
+
+#endif // NET_HTTP2_HPACK_DECODER_HPACK_STRING_DECODER_LISTENER_H_
diff --git a/chromium/net/http2/hpack/decoder/hpack_string_decoder_test.cc b/chromium/net/http2/hpack/decoder/hpack_string_decoder_test.cc
new file mode 100644
index 00000000000..614fa0d5980
--- /dev/null
+++ b/chromium/net/http2/hpack/decoder/hpack_string_decoder_test.cc
@@ -0,0 +1,187 @@
+// Copyright 2016 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.
+
+#include "net/http2/hpack/decoder/hpack_string_decoder.h"
+
+// Tests of HpackStringDecoder.
+
+#include "base/strings/string_piece.h"
+#include "net/http2/hpack/decoder/hpack_string_collector.h"
+#include "net/http2/hpack/decoder/hpack_string_decoder_listener.h"
+#include "net/http2/hpack/tools/hpack_block_builder.h"
+#include "net/http2/tools/failure.h"
+#include "net/http2/tools/http2_random.h"
+#include "net/http2/tools/random_decoder_test.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+using ::testing::AssertionResult;
+using ::testing::AssertionSuccess;
+using base::StringPiece;
+using std::string;
+
+namespace net {
+namespace test {
+namespace {
+
+const bool kMayReturnZeroOnFirst = false;
+const bool kCompressed = true;
+const bool kUncompressed = false;
+
+enum StartMethod {
+ kStart,
+ kStartOnly,
+ kStartAndDecodeLength,
+ kStartSpecialCaseShort,
+};
+
+class HpackStringDecoderTest
+ : public RandomDecoderTest,
+ public ::testing::WithParamInterface<StartMethod> {
+ protected:
+ HpackStringDecoderTest()
+ : start_method_(GetParam()), listener_(&collector_) {}
+
+ DecodeStatus StartDecoding(DecodeBuffer* b) override {
+ ++start_decoding_calls_;
+ collector_.Clear();
+ switch (start_method_) {
+ case kStart:
+ return decoder_.Start(b, &listener_);
+ case kStartOnly:
+ return decoder_.StartOnly(b, &listener_);
+ case kStartAndDecodeLength:
+ return decoder_.StartAndDecodeLength(b, &listener_);
+ case kStartSpecialCaseShort:
+ return decoder_.StartSpecialCaseShort(b, &listener_);
+ default:
+ return DecodeStatus::kDecodeError;
+ }
+ }
+
+ DecodeStatus ResumeDecoding(DecodeBuffer* b) override {
+ // Provides coverage of DebugString and StateToString.
+ // Not validating output.
+ VLOG(1) << decoder_.DebugString();
+ VLOG(2) << collector_;
+ return decoder_.Resume(b, &listener_);
+ }
+
+ AssertionResult Collected(StringPiece s, bool huffman_encoded) {
+ VLOG(1) << collector_;
+ return collector_.Collected(s, huffman_encoded);
+ }
+
+ // expected_str is a string rather than a const string& or StringPiece so that
+ // the lambda makes a copy of the string, and thus the string to be passed to
+ // Collected outlives the call to MakeValidator.
+
+ Validator MakeValidator(const string& expected_str, bool expected_huffman) {
+ return
+ [expected_str, expected_huffman, this](
+ const DecodeBuffer& input, DecodeStatus status) -> AssertionResult {
+ AssertionResult result = Collected(expected_str, expected_huffman);
+ if (result) {
+ VERIFY_EQ(collector_,
+ HpackStringCollector(expected_str, expected_huffman));
+ } else {
+ VERIFY_NE(collector_,
+ HpackStringCollector(expected_str, expected_huffman));
+ }
+ VLOG(2) << collector_.ToString();
+ collector_.Clear();
+ VLOG(2) << collector_;
+ return result;
+ };
+ }
+
+ const StartMethod start_method_;
+ HpackStringDecoder decoder_;
+ HpackStringCollector collector_;
+ HpackStringDecoderVLoggingListener listener_;
+ size_t start_decoding_calls_ = 0;
+};
+
+TEST_P(HpackStringDecoderTest, DecodeEmptyString) {
+ {
+ Validator validator = ValidateDoneAndEmpty(MakeValidator("", kCompressed));
+ const char kData[] = {0x80u};
+ DecodeBuffer b(kData);
+ EXPECT_TRUE(
+ DecodeAndValidateSeveralWays(&b, kMayReturnZeroOnFirst, validator));
+ }
+ {
+ // Make sure it stops after decoding the empty string.
+ Validator validator =
+ ValidateDoneAndOffset(1, MakeValidator("", kUncompressed));
+ const char kData[] = {0x00, 0xffu};
+ DecodeBuffer b(kData);
+ EXPECT_EQ(2u, b.Remaining());
+ EXPECT_TRUE(
+ DecodeAndValidateSeveralWays(&b, kMayReturnZeroOnFirst, validator));
+ EXPECT_EQ(1u, b.Remaining());
+ }
+}
+
+TEST_P(HpackStringDecoderTest, DecodeShortString) {
+ {
+ // Make sure it stops after decoding the non-empty string.
+ Validator validator =
+ ValidateDoneAndOffset(11, MakeValidator("start end.", kCompressed));
+ const char kData[] = "\x8astart end.Don't peek at this.";
+ DecodeBuffer b(kData);
+ EXPECT_TRUE(
+ DecodeAndValidateSeveralWays(&b, kMayReturnZeroOnFirst, validator));
+ }
+ {
+ Validator validator =
+ ValidateDoneAndOffset(11, MakeValidator("start end.", kUncompressed));
+ StringPiece data("\x0astart end.");
+ DecodeBuffer b(data);
+ EXPECT_TRUE(
+ DecodeAndValidateSeveralWays(&b, kMayReturnZeroOnFirst, validator));
+ }
+}
+
+TEST_P(HpackStringDecoderTest, DecodeLongStrings) {
+ string name = Random().RandString(1024);
+ string value = Random().RandString(65536);
+ HpackBlockBuilder hbb;
+
+ hbb.AppendString(false, name);
+ uint32_t offset_after_name = hbb.size();
+ EXPECT_EQ(3 + name.size(), offset_after_name);
+
+ hbb.AppendString(true, value);
+ uint32_t offset_after_value = hbb.size();
+ EXPECT_EQ(3 + name.size() + 4 + value.size(), offset_after_value);
+
+ DecodeBuffer b(hbb.buffer());
+
+ // Decode the name...
+ EXPECT_TRUE(DecodeAndValidateSeveralWays(
+ &b, kMayReturnZeroOnFirst,
+ ValidateDoneAndOffset(offset_after_name,
+ MakeValidator(name, kUncompressed))));
+ EXPECT_EQ(offset_after_name, b.Offset());
+ EXPECT_EQ(offset_after_value - offset_after_name, b.Remaining());
+
+ // Decode the value...
+ EXPECT_TRUE(DecodeAndValidateSeveralWays(
+ &b, kMayReturnZeroOnFirst,
+ ValidateDoneAndOffset(offset_after_value - offset_after_name,
+ MakeValidator(value, kCompressed))));
+ EXPECT_EQ(offset_after_value, b.Offset());
+ EXPECT_EQ(0u, b.Remaining());
+}
+
+INSTANTIATE_TEST_CASE_P(AllStartMethods,
+ HpackStringDecoderTest,
+ ::testing::Values(kStart,
+ kStartOnly,
+ kStartAndDecodeLength,
+ kStartSpecialCaseShort));
+
+} // namespace
+} // namespace test
+} // namespace net
diff --git a/chromium/net/http2/hpack/decoder/hpack_varint_decoder.cc b/chromium/net/http2/hpack/decoder/hpack_varint_decoder.cc
new file mode 100644
index 00000000000..f04bd89d5b0
--- /dev/null
+++ b/chromium/net/http2/hpack/decoder/hpack_varint_decoder.cc
@@ -0,0 +1,36 @@
+// Copyright 2016 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.
+
+#include "net/http2/hpack/decoder/hpack_varint_decoder.h"
+
+#include <sstream>
+
+namespace net {
+
+std::string HpackVarintDecoder::DebugString() const {
+ std::stringstream ss;
+ ss << "HpackVarintDecoder(value=" << value_ << ", offset=" << offset_ << ")";
+ return ss.str();
+}
+
+DecodeStatus HpackVarintDecoder::StartForTest(uint8_t prefix_value,
+ uint8_t prefix_mask,
+ DecodeBuffer* db) {
+ return Start(prefix_value, prefix_mask, db);
+}
+
+DecodeStatus HpackVarintDecoder::StartExtendedForTest(uint8_t prefix_mask,
+ DecodeBuffer* db) {
+ return StartExtended(prefix_mask, db);
+}
+
+DecodeStatus HpackVarintDecoder::ResumeForTest(DecodeBuffer* db) {
+ return Resume(db);
+}
+
+std::ostream& operator<<(std::ostream& out, const HpackVarintDecoder& v) {
+ return out << v.DebugString();
+}
+
+} // namespace net
diff --git a/chromium/net/http2/hpack/decoder/hpack_varint_decoder.h b/chromium/net/http2/hpack/decoder/hpack_varint_decoder.h
new file mode 100644
index 00000000000..b110fad23a9
--- /dev/null
+++ b/chromium/net/http2/hpack/decoder/hpack_varint_decoder.h
@@ -0,0 +1,181 @@
+// Copyright 2016 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.
+
+// HpackVarintDecoder decodes HPACK variable length unsigned integers. These
+// integers are used to identify static or dynamic table index entries, to
+// specify string lengths, and to update the size limit of the dynamic table.
+//
+// The caller will need to validate that the decoded value is in an acceptable
+// range.
+//
+// In order to support naive encoders (i.e. which always output 5 extension
+// bytes for a uint32 that is >= prefix_mask), the decoder supports an an
+// encoding with up to 5 extension bytes, and a maximum value of 268,435,582
+// (4 "full" extension bytes plus the maximum for a prefix, 127). It could be
+// modified to support a lower maximum value (by requiring that extensions bytes
+// be "empty"), or a larger value if valuable for some reason I can't see.
+//
+// For details of the encoding, see:
+// http://httpwg.org/specs/rfc7541.html#integer.representation
+//
+// TODO(jamessynge): Consider dropping support for encodings of more than 4
+// bytes, including the prefix byte, as in practice we only see at most 3 bytes,
+// and 4 bytes would cover any desire to support large (but not ridiculously
+// large) header values.
+
+#ifndef NET_HTTP2_HPACK_DECODER_HPACK_VARINT_DECODER_H_
+#define NET_HTTP2_HPACK_DECODER_HPACK_VARINT_DECODER_H_
+
+#include <string>
+
+#include "base/logging.h"
+#include "net/base/net_export.h"
+#include "net/http2/decoder/decode_buffer.h"
+#include "net/http2/decoder/decode_status.h"
+
+namespace net {
+// Decodes an HPACK variable length unsigned integer, in a resumable fashion
+// so it can handle running out of input in the DecodeBuffer. Call Start or
+// StartExtended the first time (when decoding the byte that contains the
+// prefix), then call Resume later if it is necessary to resume. When done,
+// call value() to retrieve the decoded value.
+//
+// No constructor or destructor. Holds no resources, so destruction isn't
+// needed. Start and StartExtended handles the initialization of member
+// variables. This is necessary in order for HpackVarintDecoder to be part
+// of a union.
+class NET_EXPORT_PRIVATE HpackVarintDecoder {
+ public:
+ // |prefix_value| is the first byte of the encoded varint.
+ // |prefix_mask| is the mask of the valid bits, i.e. without the top 1 to 4
+ // high-bits set, as appropriate for the item being decoded; must be a
+ // contiguous sequence of set bits, starting with the low-order bits.
+ DecodeStatus Start(uint8_t prefix_value,
+ uint8_t prefix_mask,
+ DecodeBuffer* db) {
+ DCHECK_LE(15, prefix_mask) << std::hex << prefix_mask;
+ DCHECK_LE(prefix_mask, 127) << std::hex << prefix_mask;
+ // Confirm that |prefix_mask| is a contiguous sequence of bits.
+ DCHECK_EQ(0, (prefix_mask + 1) & prefix_mask) << std::hex << prefix_mask;
+
+ // Ignore the bits that aren't a part of the prefix of the varint.
+ value_ = prefix_value & prefix_mask;
+
+ if (value_ < prefix_mask) {
+ MarkDone();
+ return DecodeStatus::kDecodeDone;
+ }
+
+ offset_ = 0;
+ return Resume(db);
+ }
+
+ // The caller has already determined that the encoding requires multiple
+ // bytes, i.e. that the 4 to 7 low-order bits (the number determined by the
+ // prefix length, a value not passed into this function) of the first byte are
+ // are all 1. The caller passes in |prefix_mask|, which is 2^prefix_length-1.
+ DecodeStatus StartExtended(uint8_t prefix_mask, DecodeBuffer* db) {
+ DCHECK_LE(15, prefix_mask) << std::hex << prefix_mask;
+ DCHECK_LE(prefix_mask, 127) << std::hex << prefix_mask;
+ // Confirm that |prefix_mask| is a contiguous sequence of bits.
+ DCHECK_EQ(0, prefix_mask & (prefix_mask + 1)) << std::hex << prefix_mask;
+
+ value_ = prefix_mask;
+ offset_ = 0;
+ return Resume(db);
+ }
+
+ // Resume decoding a variable length integer after an earlier
+ // call to Start or StartExtended returned kDecodeInProgress.
+ DecodeStatus Resume(DecodeBuffer* db) {
+ CheckNotDone();
+ do {
+ if (db->Empty()) {
+ return DecodeStatus::kDecodeInProgress;
+ }
+ uint8_t byte = db->DecodeUInt8();
+ value_ += (byte & 0x7f) << offset_;
+ if ((byte & 0x80) == 0) {
+ if (offset_ < MaxOffset() || byte == 0) {
+ MarkDone();
+ return DecodeStatus::kDecodeDone;
+ }
+ break;
+ }
+ offset_ += 7;
+ } while (offset_ <= MaxOffset());
+ DLOG(WARNING) << "Variable length int encoding is too large or too long. "
+ << DebugString();
+ MarkDone();
+ return DecodeStatus::kDecodeError;
+ }
+
+ uint32_t value() const {
+ CheckDone();
+ return value_;
+ }
+
+ // This supports optimizations for the case of a varint with zero extension
+ // bytes, where the handling of the prefix is done by the caller.
+ void set_value(uint32_t v) {
+ MarkDone();
+ value_ = v;
+ }
+
+ // All the public methods below are for supporting assertions and tests.
+
+ std::string DebugString() const;
+
+ // For benchmarking, these methods ensure the decoder
+ // is NOT inlined into the caller.
+ DecodeStatus StartForTest(uint8_t prefix_value,
+ uint8_t prefix_mask,
+ DecodeBuffer* db);
+ DecodeStatus StartExtendedForTest(uint8_t prefix_mask, DecodeBuffer* db);
+ DecodeStatus ResumeForTest(DecodeBuffer* db);
+
+ static constexpr uint32_t MaxExtensionBytes() { return 5; }
+
+ // Returns the highest value with the specified number of extension bytes and
+ // the specified prefix length (bits).
+ static uint64_t constexpr HiValueOfExtensionBytes(uint32_t extension_bytes,
+ uint32_t prefix_length) {
+ return (1 << prefix_length) - 2 +
+ (extension_bytes == 0 ? 0 : (1LLU << (extension_bytes * 7)));
+ }
+
+ private:
+ // Protection in case Resume is called when it shouldn't be.
+ void MarkDone() {
+#ifndef NDEBUG
+ // We support up to 5 extension bytes, so offset_ should never be > 28 when
+ // it makes sense to call Resume().
+ offset_ = MaxOffset() + 7;
+#endif
+ }
+ void CheckNotDone() const {
+#ifndef NDEBUG
+ DCHECK_LE(offset_, MaxOffset());
+#endif
+ }
+ void CheckDone() const {
+#ifndef NDEBUG
+ DCHECK_GT(offset_, MaxOffset());
+#endif
+ }
+ static constexpr uint32_t MaxOffset() {
+ return 7 * (MaxExtensionBytes() - 1);
+ }
+
+ // These fields are initialized just to keep ASAN happy about reading
+ // them from DebugString().
+ uint32_t value_ = 0;
+ uint32_t offset_ = 0;
+};
+
+std::ostream& operator<<(std::ostream& out, const HpackVarintDecoder& v);
+
+} // namespace net
+
+#endif // NET_HTTP2_HPACK_DECODER_HPACK_VARINT_DECODER_H_
diff --git a/chromium/net/http2/hpack/decoder/hpack_varint_decoder_test.cc b/chromium/net/http2/hpack/decoder/hpack_varint_decoder_test.cc
new file mode 100644
index 00000000000..7cdc872ed17
--- /dev/null
+++ b/chromium/net/http2/hpack/decoder/hpack_varint_decoder_test.cc
@@ -0,0 +1,382 @@
+// Copyright 2016 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.
+
+#include "net/http2/hpack/decoder/hpack_varint_decoder.h"
+
+// Tests of HpackVarintDecoder.
+
+#include <stddef.h>
+
+#include <ios>
+#include <iterator>
+#include <ostream>
+#include <set>
+#include <sstream>
+#include <vector>
+
+#include "base/logging.h"
+#include "base/strings/string_number_conversions.h"
+#include "base/strings/string_piece.h"
+#include "base/strings/stringprintf.h"
+#include "net/http2/hpack/tools/hpack_block_builder.h"
+#include "net/http2/tools/failure.h"
+#include "net/http2/tools/http2_random.h"
+#include "net/http2/tools/random_decoder_test.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+using ::testing::AssertionFailure;
+using ::testing::AssertionSuccess;
+using base::StringPiece;
+using base::StringPrintf;
+using std::string;
+
+namespace net {
+namespace test {
+namespace {
+
+class HpackVarintDecoderTest : public RandomDecoderTest {
+
+ protected:
+ DecodeStatus StartDecoding(DecodeBuffer* b) override {
+ CHECK_LT(0u, b->Remaining());
+ CHECK_NE(0, prefix_mask_);
+ uint8_t prefix = b->DecodeUInt8();
+ return decoder_.Start(prefix, prefix_mask_, b);
+ }
+
+ DecodeStatus ResumeDecoding(DecodeBuffer* b) override {
+ return decoder_.Resume(b);
+ }
+
+ void DecodeSeveralWays(uint32_t expected_value, uint32_t expected_offset) {
+ // The validator is called after each of the several times that the input
+ // DecodeBuffer is decoded, each with a different segmentation of the input.
+ // Validate that decoder_.value() matches the expected value.
+ Validator validator = [expected_value, this](
+ const DecodeBuffer& db, DecodeStatus status) -> AssertionResult {
+ if (decoder_.value() != expected_value) {
+ return AssertionFailure()
+ << "Value doesn't match expected: " << decoder_.value()
+ << " != " << expected_value;
+ }
+ return AssertionSuccess();
+ };
+
+ // First validate that decoding is done and that we've advanced the cursor
+ // the expected amount.
+ validator = ValidateDoneAndOffset(expected_offset, validator);
+
+ // StartDecoding, above, requires the DecodeBuffer be non-empty so that it
+ // can call Start with the prefix byte.
+ bool return_non_zero_on_first = true;
+
+ DecodeBuffer b(buffer_);
+ EXPECT_TRUE(
+ DecodeAndValidateSeveralWays(&b, return_non_zero_on_first, validator));
+
+ EXPECT_EQ(expected_value, decoder_.value());
+ EXPECT_EQ(expected_offset, b.Offset());
+ }
+
+ void EncodeNoRandom(uint32_t value, uint8_t prefix_length) {
+ DCHECK_LE(4, prefix_length);
+ DCHECK_LE(prefix_length, 7);
+ prefix_length_ = prefix_length;
+
+ HpackBlockBuilder bb;
+ bb.AppendHighBitsAndVarint(0, prefix_length_, value);
+ buffer_ = bb.buffer();
+ ASSERT_LT(0u, buffer_.size());
+
+ // Note: setting member variable prefix_mask_ here, which will be read
+ // in StartDecoding above.
+ prefix_mask_ = (1 << prefix_length_) - 1;
+ ASSERT_EQ(buffer_[0], buffer_[0] & prefix_mask_);
+ }
+
+ void Encode(uint32_t value, uint8_t prefix_length) {
+ EncodeNoRandom(value, prefix_length);
+ // Add some random bits to the prefix (the first byte) above the mask.
+ uint8_t prefix = buffer_[0];
+ buffer_[0] = prefix | (Random().Rand8() << prefix_length);
+ ASSERT_EQ(prefix, buffer_[0] & prefix_mask_);
+ }
+
+ // This is really a test of HpackBlockBuilder, making sure that the input to
+ // HpackVarintDecoder is as expected, which also acts as confirmation that
+ // my thinking about the encodings being used by the tests, i.e. cover the
+ // range desired.
+ void ValidateEncoding(uint32_t value,
+ uint32_t minimum,
+ uint32_t maximum,
+ size_t expected_bytes) {
+ ASSERT_EQ(expected_bytes, buffer_.size());
+ if (expected_bytes > 1) {
+ EXPECT_EQ(prefix_mask_, buffer_[0] & prefix_mask_);
+ size_t last = expected_bytes - 1;
+ for (size_t ndx = 1; ndx < last; ++ndx) {
+ // Before the last extension byte, we expect the high-bit set.
+ uint8_t byte = buffer_[ndx];
+ if (value == minimum) {
+ EXPECT_EQ(0x80, byte) << "ndx=" << ndx;
+ } else if (value == maximum) {
+ EXPECT_EQ(0xff, byte) << "ndx=" << ndx;
+ } else {
+ EXPECT_EQ(0x80, byte & 0x80) << "ndx=" << ndx;
+ }
+ }
+ // The last extension byte should not have the high-bit set.
+ uint8_t byte = buffer_[last];
+ if (value == minimum) {
+ if (expected_bytes == 2) {
+ EXPECT_EQ(0x00, byte);
+ } else {
+ EXPECT_EQ(0x01, byte);
+ }
+ } else if (value == maximum) {
+ EXPECT_EQ(0x7f, byte);
+ } else {
+ EXPECT_EQ(0x00, byte & 0x80);
+ }
+ } else {
+ EXPECT_EQ(value, static_cast<uint32_t>(buffer_[0] & prefix_mask_));
+ EXPECT_LT(value, static_cast<uint32_t>(prefix_mask_));
+ }
+ }
+
+ void EncodeAndDecodeValues(const std::set<uint32_t>& values,
+ uint8_t prefix_length,
+ size_t expected_bytes) {
+ CHECK(!values.empty());
+ const uint32_t minimum = *values.begin();
+ const uint32_t maximum = *values.rbegin();
+ for (const uint32_t value : values) {
+ Encode(value, prefix_length); // Sets prefix_mask_ and buffer_
+
+ std::stringstream ss;
+ ss << "value=" << value << " (0x" << std::hex << value
+ << "), prefix_length=" << std::dec << prefix_length
+ << ", expected_bytes=" << expected_bytes << std::endl
+ << HexEncode(buffer_);
+ string msg(ss.str());
+
+ if (value == minimum) {
+ LOG(INFO) << "Checking minimum; " << msg;
+ } else if (value == maximum) {
+ LOG(INFO) << "Checking maximum; " << msg;
+ }
+
+ SCOPED_TRACE(msg);
+ ValidateEncoding(value, minimum, maximum, expected_bytes);
+ DecodeSeveralWays(value, expected_bytes);
+
+ // Append some random data to the end of buffer_ and repeat. That random
+ // data should be ignored.
+ buffer_.append(Random().RandString(1 + Random().Uniform(10)));
+ DecodeSeveralWays(value, expected_bytes);
+
+ // If possible, add extension bytes that don't change the value.
+ if (1 < expected_bytes) {
+ buffer_.resize(expected_bytes);
+ for (uint8_t total_bytes = expected_bytes + 1; total_bytes <= 6;
+ ++total_bytes) {
+ // Mark the current last byte as not being the last one.
+ EXPECT_EQ(0x00, 0x80 & buffer_.back());
+ buffer_.back() |= 0x80;
+ buffer_.push_back('\0');
+ DecodeSeveralWays(value, total_bytes);
+ }
+ }
+ }
+ }
+
+ void EncodeAndDecodeValuesInRange(uint32_t start,
+ uint32_t range,
+ uint8_t prefix_length,
+ size_t expected_bytes) {
+ const uint8_t prefix_mask = (1 << prefix_length) - 1;
+ const uint32_t beyond = start + range;
+
+ LOG(INFO) << "############################################################";
+ LOG(INFO) << "prefix_length=" << static_cast<int>(prefix_length);
+ LOG(INFO) << "prefix_mask=" << std::hex << static_cast<int>(prefix_mask);
+ LOG(INFO) << "start=" << start << " (" << std::hex << start << ")";
+ LOG(INFO) << "range=" << range << " (" << std::hex << range << ")";
+ LOG(INFO) << "beyond=" << beyond << " (" << std::hex << beyond << ")";
+ LOG(INFO) << "expected_bytes=" << expected_bytes;
+
+ // Confirm the claim that beyond requires more bytes.
+ Encode(beyond, prefix_length);
+ EXPECT_EQ(expected_bytes + 1, buffer_.size()) << HexEncode(buffer_);
+
+ std::set<uint32_t> values;
+ if (range < 200) {
+ // Select all values in the range.
+ for (uint32_t offset = 0; offset < range; ++offset) {
+ values.insert(start + offset);
+ }
+ } else {
+ // Select some values in this range, including the minimum and maximum
+ // values that require exactly |expected_bytes| extension bytes.
+ values.insert({start, start + 1, beyond - 2, beyond - 1});
+ while (values.size() < 100) {
+ values.insert(start + Random().Rand32() % range);
+ }
+ }
+
+ EncodeAndDecodeValues(values, prefix_length, expected_bytes);
+ }
+
+ HpackVarintDecoder decoder_;
+ string buffer_;
+ uint8_t prefix_mask_ = 0;
+ uint8_t prefix_length_ = 0;
+};
+
+// To help me and future debuggers of varint encodings, this LOGs out the
+// transition points where a new extension byte is added.
+TEST_F(HpackVarintDecoderTest, Encode) {
+ for (int prefix_length = 4; prefix_length <= 7; ++prefix_length) {
+ const uint32_t a = (1 << prefix_length) - 1;
+ const uint32_t b = a + 128;
+ const uint32_t c = b + (127 << 7);
+ const uint32_t d = c + (127 << 14);
+ const uint32_t e = d + (127 << 21);
+
+ LOG(INFO) << "############################################################";
+ LOG(INFO) << "prefix_length=" << prefix_length << " a=" << a
+ << " b=" << b << " c=" << c;
+
+ EXPECT_EQ(a - 1,
+ HpackVarintDecoder::HiValueOfExtensionBytes(0, prefix_length));
+ EXPECT_EQ(b - 1,
+ HpackVarintDecoder::HiValueOfExtensionBytes(1, prefix_length));
+ EXPECT_EQ(c - 1,
+ HpackVarintDecoder::HiValueOfExtensionBytes(2, prefix_length));
+ EXPECT_EQ(d - 1,
+ HpackVarintDecoder::HiValueOfExtensionBytes(3, prefix_length));
+ EXPECT_EQ(e - 1,
+ HpackVarintDecoder::HiValueOfExtensionBytes(4, prefix_length));
+
+ std::vector<uint32_t> values = {
+ 0, 1, // Force line break.
+ a - 2, a - 1, a, a + 1, a + 2, // Force line break.
+ b - 2, b - 1, b, b + 1, b + 2, // Force line break.
+ c - 2, c - 1, c, c + 1, c + 2, // Force line break.
+ d - 2, d - 1, d, d + 1, d + 2, // Force line break.
+ e - 2, e - 1, e, e + 1, e + 2 // Force line break.
+ };
+
+ for (uint32_t value : values) {
+ EncodeNoRandom(value, prefix_length);
+ string dump = HexEncode(buffer_);
+ LOG(INFO) << StringPrintf("%10u %0#10x ", value, value)
+ << HexEncode(buffer_);
+ }
+ }
+}
+
+TEST_F(HpackVarintDecoderTest, FromSpec1337) {
+ DecodeBuffer b(StringPiece("\x1f\x9a\x0a"));
+ uint32_t prefix_length = 5;
+ uint32_t prefix_mask = (1 << prefix_length) - 1;
+ uint8_t p = b.DecodeUInt8();
+ EXPECT_EQ(1u, b.Offset());
+ EXPECT_EQ(DecodeStatus::kDecodeDone, decoder_.Start(p, prefix_mask, &b));
+ EXPECT_EQ(3u, b.Offset());
+ EXPECT_EQ(1337u, decoder_.value());
+
+ EncodeNoRandom(1337, prefix_length);
+ EXPECT_EQ(3u, buffer_.size());
+ EXPECT_EQ('\x1f', buffer_[0]);
+ EXPECT_EQ('\x9a', buffer_[1]);
+ EXPECT_EQ('\x0a', buffer_[2]);
+}
+
+// Test all the values that fit into the prefix (one less than the mask).
+TEST_F(HpackVarintDecoderTest, ValidatePrefixOnly) {
+ for (int prefix_length = 4; prefix_length <= 7; ++prefix_length) {
+ const uint8_t prefix_mask = (1 << prefix_length) - 1;
+ EncodeAndDecodeValuesInRange(0, prefix_mask, prefix_length, 1);
+ }
+}
+
+// Test all values that require exactly 1 extension byte.
+TEST_F(HpackVarintDecoderTest, ValidateOneExtensionByte) {
+ for (int prefix_length = 4; prefix_length <= 7; ++prefix_length) {
+ const uint32_t start = (1 << prefix_length) - 1;
+ EncodeAndDecodeValuesInRange(start, 128, prefix_length, 2);
+ }
+}
+
+// Test *some* values that require exactly 2 extension bytes.
+TEST_F(HpackVarintDecoderTest, ValidateTwoExtensionBytes) {
+ for (int prefix_length = 4; prefix_length <= 7; ++prefix_length) {
+ const uint8_t prefix_mask = (1 << prefix_length) - 1;
+ const uint32_t start = prefix_mask + 128;
+ const uint32_t range = 127 << 7;
+
+ EncodeAndDecodeValuesInRange(start, range, prefix_length, 3);
+ }
+}
+
+// Test *some* values that require 3 extension bytes.
+TEST_F(HpackVarintDecoderTest, ValidateThreeExtensionBytes) {
+ for (int prefix_length = 4; prefix_length <= 7; ++prefix_length) {
+ const uint8_t prefix_mask = (1 << prefix_length) - 1;
+ const uint32_t start = prefix_mask + 128 + (127 << 7);
+ const uint32_t range = 127 << 14;
+
+ EncodeAndDecodeValuesInRange(start, range, prefix_length, 4);
+ }
+}
+
+// Test *some* values that require 4 extension bytes.
+TEST_F(HpackVarintDecoderTest, ValidateFourExtensionBytes) {
+ for (int prefix_length = 4; prefix_length <= 7; ++prefix_length) {
+ const uint8_t prefix_mask = (1 << prefix_length) - 1;
+ const uint32_t start = prefix_mask + 128 + (127 << 7) + (127 << 14);
+ const uint32_t range = 127 << 21;
+
+ EncodeAndDecodeValuesInRange(start, range, prefix_length, 5);
+ }
+}
+
+// Test *some* values that require too many extension bytes.
+TEST_F(HpackVarintDecoderTest, ValueTooLarge) {
+ const uint32_t expected_offset = HpackVarintDecoder::MaxExtensionBytes() + 1;
+ for (prefix_length_ = 4; prefix_length_ <= 7; ++prefix_length_) {
+ prefix_mask_ = (1 << prefix_length_) - 1;
+ uint64_t too_large = HpackVarintDecoder::HiValueOfExtensionBytes(
+ HpackVarintDecoder::MaxExtensionBytes() + 3, prefix_length_);
+ HpackBlockBuilder bb;
+ bb.AppendHighBitsAndVarint(0, prefix_length_, too_large);
+ buffer_ = bb.buffer();
+
+ // The validator is called after each of the several times that the input
+ // DecodeBuffer is decoded, each with a different segmentation of the input.
+ // Validate that decoder_.value() matches the expected value.
+ bool validated = false;
+ Validator validator = [&validated, expected_offset](
+ const DecodeBuffer& db, DecodeStatus status) -> AssertionResult {
+ validated = true;
+ VERIFY_EQ(DecodeStatus::kDecodeError, status);
+ VERIFY_EQ(expected_offset, db.Offset());
+ return AssertionSuccess();
+ };
+
+ // StartDecoding, above, requires the DecodeBuffer be non-empty so that it
+ // can call Start with the prefix byte.
+ bool return_non_zero_on_first = true;
+ DecodeBuffer b(buffer_);
+ EXPECT_TRUE(
+ DecodeAndValidateSeveralWays(&b, return_non_zero_on_first, validator));
+ EXPECT_EQ(expected_offset, b.Offset());
+ EXPECT_TRUE(validated);
+ }
+}
+
+} // namespace
+} // namespace test
+} // namespace net
diff --git a/chromium/net/http2/hpack/decoder/hpack_whole_entry_buffer.cc b/chromium/net/http2/hpack/decoder/hpack_whole_entry_buffer.cc
new file mode 100644
index 00000000000..8bb212f40aa
--- /dev/null
+++ b/chromium/net/http2/hpack/decoder/hpack_whole_entry_buffer.cc
@@ -0,0 +1,135 @@
+// Copyright 2016 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.
+
+#include "net/http2/hpack/decoder/hpack_whole_entry_buffer.h"
+
+#include "base/logging.h"
+
+using base::StringPiece;
+
+namespace net {
+
+HpackWholeEntryBuffer::HpackWholeEntryBuffer(HpackWholeEntryListener* listener,
+ size_t max_string_size_bytes)
+ : max_string_size_bytes_(max_string_size_bytes) {
+ set_listener(listener);
+}
+HpackWholeEntryBuffer::~HpackWholeEntryBuffer() {}
+
+void HpackWholeEntryBuffer::set_listener(HpackWholeEntryListener* listener) {
+ CHECK(listener);
+ listener_ = listener;
+}
+
+void HpackWholeEntryBuffer::set_max_string_size_bytes(
+ size_t max_string_size_bytes) {
+ max_string_size_bytes_ = max_string_size_bytes;
+}
+
+void HpackWholeEntryBuffer::BufferStringsIfUnbuffered() {
+ name_.BufferStringIfUnbuffered();
+ value_.BufferStringIfUnbuffered();
+}
+
+void HpackWholeEntryBuffer::OnIndexedHeader(size_t index) {
+ DVLOG(2) << "HpackWholeEntryBuffer::OnIndexedHeader: index=" << index;
+ listener_->OnIndexedHeader(index);
+}
+
+void HpackWholeEntryBuffer::OnStartLiteralHeader(HpackEntryType entry_type,
+ size_t maybe_name_index) {
+ DVLOG(2) << "HpackWholeEntryBuffer::OnStartLiteralHeader: entry_type="
+ << entry_type << ", maybe_name_index=" << maybe_name_index;
+ entry_type_ = entry_type;
+ maybe_name_index_ = maybe_name_index;
+}
+
+void HpackWholeEntryBuffer::OnNameStart(bool huffman_encoded, size_t len) {
+ DVLOG(2) << "HpackWholeEntryBuffer::OnNameStart: huffman_encoded="
+ << (huffman_encoded ? "true" : "false") << ", len=" << len;
+ DCHECK_EQ(maybe_name_index_, 0u);
+ if (!error_detected_) {
+ if (len > max_string_size_bytes_) {
+ DVLOG(1) << "Name length (" << len << ") is longer than permitted ("
+ << max_string_size_bytes_ << ")";
+ ReportError("HPACK entry name size is too long.");
+ return;
+ }
+ name_.OnStart(huffman_encoded, len);
+ }
+}
+
+void HpackWholeEntryBuffer::OnNameData(const char* data, size_t len) {
+ DVLOG(2) << "HpackWholeEntryBuffer::OnNameData: len=" << len
+ << "\n data: " << StringPiece(data, len);
+ DCHECK_EQ(maybe_name_index_, 0u);
+ if (!error_detected_ && !name_.OnData(data, len)) {
+ ReportError("Error decoding HPACK entry name.");
+ }
+}
+
+void HpackWholeEntryBuffer::OnNameEnd() {
+ DVLOG(2) << "HpackWholeEntryBuffer::OnNameEnd";
+ DCHECK_EQ(maybe_name_index_, 0u);
+ if (!error_detected_ && !name_.OnEnd()) {
+ ReportError("Error decoding HPACK entry name.");
+ }
+}
+
+void HpackWholeEntryBuffer::OnValueStart(bool huffman_encoded, size_t len) {
+ DVLOG(2) << "HpackWholeEntryBuffer::OnValueStart: huffman_encoded="
+ << (huffman_encoded ? "true" : "false") << ", len=" << len;
+ if (!error_detected_) {
+ if (len > max_string_size_bytes_) {
+ DVLOG(1) << "Value length (" << len << ") is longer than permitted ("
+ << max_string_size_bytes_ << ")";
+ ReportError("HPACK entry value size is too long.");
+ return;
+ }
+ value_.OnStart(huffman_encoded, len);
+ }
+}
+
+void HpackWholeEntryBuffer::OnValueData(const char* data, size_t len) {
+ DVLOG(2) << "HpackWholeEntryBuffer::OnValueData: len=" << len
+ << "\n data: " << StringPiece(data, len);
+ if (!error_detected_ && !value_.OnData(data, len)) {
+ ReportError("Error decoding HPACK entry value.");
+ }
+}
+
+void HpackWholeEntryBuffer::OnValueEnd() {
+ DVLOG(2) << "HpackWholeEntryBuffer::OnValueEnd";
+ if (error_detected_) {
+ return;
+ }
+ if (!value_.OnEnd()) {
+ ReportError("Error decoding HPACK entry value.");
+ return;
+ }
+ if (maybe_name_index_ == 0) {
+ listener_->OnLiteralNameAndValue(entry_type_, &name_, &value_);
+ name_.Reset();
+ } else {
+ listener_->OnNameIndexAndLiteralValue(entry_type_, maybe_name_index_,
+ &value_);
+ }
+ value_.Reset();
+}
+
+void HpackWholeEntryBuffer::OnDynamicTableSizeUpdate(size_t size) {
+ DVLOG(2) << "HpackWholeEntryBuffer::OnDynamicTableSizeUpdate: size=" << size;
+ listener_->OnDynamicTableSizeUpdate(size);
+}
+
+void HpackWholeEntryBuffer::ReportError(StringPiece error_message) {
+ if (!error_detected_) {
+ DVLOG(1) << "HpackWholeEntryBuffer::ReportError: " << error_message;
+ error_detected_ = true;
+ listener_->OnHpackDecodeError(error_message);
+ listener_ = HpackWholeEntryNoOpListener::NoOpListener();
+ }
+}
+
+} // namespace net
diff --git a/chromium/net/http2/hpack/decoder/hpack_whole_entry_buffer.h b/chromium/net/http2/hpack/decoder/hpack_whole_entry_buffer.h
new file mode 100644
index 00000000000..8ab5d693285
--- /dev/null
+++ b/chromium/net/http2/hpack/decoder/hpack_whole_entry_buffer.h
@@ -0,0 +1,101 @@
+// Copyright 2016 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.
+
+#ifndef NET_HTTP2_HPACK_DECODER_HPACK_WHOLE_ENTRY_BUFFER_H_
+#define NET_HTTP2_HPACK_DECODER_HPACK_WHOLE_ENTRY_BUFFER_H_
+
+// HpackWholeEntryBuffer isolates a listener from the fact that an entry may
+// be split across multiple input buffers, providing one callback per entry.
+// HpackWholeEntryBuffer requires that the HpackEntryDecoderListener be made in
+// the correct order, which is tested by hpack_entry_decoder_test.cc.
+
+#include <stddef.h>
+
+#include "base/macros.h"
+#include "base/strings/string_piece.h"
+#include "net/base/net_export.h"
+#include "net/http2/hpack/decoder/hpack_decoder_string_buffer.h"
+#include "net/http2/hpack/decoder/hpack_entry_decoder_listener.h"
+#include "net/http2/hpack/decoder/hpack_whole_entry_listener.h"
+#include "net/http2/hpack/http2_hpack_constants.h"
+
+namespace net {
+
+// TODO(jamessynge): Consider renaming HpackEntryDecoderListener to
+// HpackEntryPartsListener or HpackEntryFragmentsListener.
+class NET_EXPORT_PRIVATE HpackWholeEntryBuffer
+ : public HpackEntryDecoderListener {
+ public:
+ // max_string_size specifies the maximum size of an on-the-wire string (name
+ // or value, plain or Huffman encoded) that will be accepted. See sections
+ // 5.1 and 5.2 of RFC 7541. This is a defense against OOM attacks; HTTP/2
+ // allows a decoder to enforce any limit of the size of the header lists
+ // that it is willing decode, including less than the MAX_HEADER_LIST_SIZE
+ // setting, a setting that is initially unlimited. For example, we might
+ // choose to send a MAX_HEADER_LIST_SIZE of 64KB, and to use that same value
+ // as the upper bound for individual strings.
+ HpackWholeEntryBuffer(HpackWholeEntryListener* listener,
+ size_t max_string_size);
+ ~HpackWholeEntryBuffer() override;
+
+ // Set the listener to be notified when a whole entry has been decoded.
+ // The listener may be changed at any time.
+ void set_listener(HpackWholeEntryListener* listener);
+
+ // Set how much encoded data this decoder is willing to buffer.
+ // TODO(jamessynge): Come up with consistent semantics for this protection
+ // across the various decoders; e.g. should it be for a single string or
+ // a single header entry?
+ void set_max_string_size_bytes(size_t max_string_size_bytes);
+
+ // Ensure that decoded strings pointed to by the HpackDecoderStringBuffer
+ // instances name_ and value_ are buffered, which allows any underlying
+ // transport buffer to be freed or reused without overwriting the decoded
+ // strings. This is needed only when an HPACK entry is split across transport
+ // buffers. See HpackDecoder::DecodeFragment.
+ void BufferStringsIfUnbuffered();
+
+ // Was an error detected? After an error has been detected and reported,
+ // no further callbacks will be made to the listener.
+ bool error_detected() const { return error_detected_; }
+
+ // Implement the HpackEntryDecoderListener methods.
+
+ void OnIndexedHeader(size_t index) override;
+ void OnStartLiteralHeader(HpackEntryType entry_type,
+ size_t maybe_name_index) override;
+ void OnNameStart(bool huffman_encoded, size_t len) override;
+ void OnNameData(const char* data, size_t len) override;
+ void OnNameEnd() override;
+ void OnValueStart(bool huffman_encoded, size_t len) override;
+ void OnValueData(const char* data, size_t len) override;
+ void OnValueEnd() override;
+ void OnDynamicTableSizeUpdate(size_t size) override;
+
+ private:
+ void ReportError(base::StringPiece error_message);
+
+ HpackWholeEntryListener* listener_;
+ HpackDecoderStringBuffer name_, value_;
+
+ // max_string_size_bytes_ specifies the maximum allowed size of an on-the-wire
+ // string. Larger strings will be reported as errors to the listener; the
+ // endpoint should treat these as COMPRESSION errors, which are CONNECTION
+ // level errors.
+ size_t max_string_size_bytes_;
+
+ // The name index (or zero) of the current header entry with a literal value.
+ size_t maybe_name_index_;
+
+ // The type of the current header entry (with literals) that is being decoded.
+ HpackEntryType entry_type_;
+
+ bool error_detected_ = false;
+
+ DISALLOW_COPY_AND_ASSIGN(HpackWholeEntryBuffer);
+};
+
+} // namespace net
+
+#endif // NET_HTTP2_HPACK_DECODER_HPACK_WHOLE_ENTRY_BUFFER_H_
diff --git a/chromium/net/http2/hpack/decoder/hpack_whole_entry_buffer_test.cc b/chromium/net/http2/hpack/decoder/hpack_whole_entry_buffer_test.cc
new file mode 100644
index 00000000000..0b5564ff8e6
--- /dev/null
+++ b/chromium/net/http2/hpack/decoder/hpack_whole_entry_buffer_test.cc
@@ -0,0 +1,219 @@
+// Copyright 2016 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.
+
+#include "net/http2/hpack/decoder/hpack_whole_entry_buffer.h"
+
+// Tests of HpackWholeEntryBuffer: does it buffer correctly, and does it
+// detect Huffman decoding errors and oversize string errors?
+
+#include "net/test/gtest_util.h"
+#include "testing/gmock/include/gmock/gmock-matchers.h"
+#include "testing/gmock/include/gmock/gmock.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+using base::StringPiece;
+using ::testing::AllOf;
+using ::testing::HasSubstr;
+using ::testing::InSequence;
+using ::testing::Property;
+using ::testing::StrictMock;
+using ::testing::_;
+
+namespace net {
+namespace test {
+namespace {
+
+constexpr size_t kMaxStringSize = 20;
+
+// Define HasSubstr() for base::StringPiece arguments.
+// This shadows ::testing::HasSubstr(), which only works on argument types
+// that can be implicilty converted to a std::string.
+inline ::testing::PolymorphicMatcher<StringPieceHasSubstrMatcher> HasSubstr(
+ const std::string& substring) {
+ return ::testing::MakePolymorphicMatcher(
+ StringPieceHasSubstrMatcher(substring));
+}
+
+class MockHpackWholeEntryListener : public HpackWholeEntryListener {
+ public:
+ ~MockHpackWholeEntryListener() override {}
+
+ MOCK_METHOD1(OnIndexedHeader, void(size_t index));
+ MOCK_METHOD3(OnNameIndexAndLiteralValue,
+ void(HpackEntryType entry_type,
+ size_t name_index,
+ HpackDecoderStringBuffer* value_buffer));
+ MOCK_METHOD3(OnLiteralNameAndValue,
+ void(HpackEntryType entry_type,
+ HpackDecoderStringBuffer* name_buffer,
+ HpackDecoderStringBuffer* value_buffer));
+ MOCK_METHOD1(OnDynamicTableSizeUpdate, void(size_t size));
+ MOCK_METHOD1(OnHpackDecodeError, void(StringPiece error_message));
+};
+
+class HpackWholeEntryBufferTest : public ::testing::Test {
+ protected:
+ HpackWholeEntryBufferTest() : entry_buffer_(&listener_, kMaxStringSize) {}
+ ~HpackWholeEntryBufferTest() override {}
+
+ StrictMock<MockHpackWholeEntryListener> listener_;
+ HpackWholeEntryBuffer entry_buffer_;
+};
+
+// OnIndexedHeader is an immediate pass through.
+TEST_F(HpackWholeEntryBufferTest, OnIndexedHeader) {
+ {
+ InSequence seq;
+ EXPECT_CALL(listener_, OnIndexedHeader(17));
+ entry_buffer_.OnIndexedHeader(17);
+ }
+ {
+ InSequence seq;
+ EXPECT_CALL(listener_, OnIndexedHeader(62));
+ entry_buffer_.OnIndexedHeader(62);
+ }
+ {
+ InSequence seq;
+ EXPECT_CALL(listener_, OnIndexedHeader(62));
+ entry_buffer_.OnIndexedHeader(62);
+ }
+ {
+ InSequence seq;
+ EXPECT_CALL(listener_, OnIndexedHeader(128));
+ entry_buffer_.OnIndexedHeader(128);
+ }
+ StrictMock<MockHpackWholeEntryListener> listener2;
+ entry_buffer_.set_listener(&listener2);
+ {
+ InSequence seq;
+ EXPECT_CALL(listener2, OnIndexedHeader(100));
+ entry_buffer_.OnIndexedHeader(100);
+ }
+}
+
+// OnDynamicTableSizeUpdate is an immediate pass through.
+TEST_F(HpackWholeEntryBufferTest, OnDynamicTableSizeUpdate) {
+ {
+ InSequence seq;
+ EXPECT_CALL(listener_, OnDynamicTableSizeUpdate(4096));
+ entry_buffer_.OnDynamicTableSizeUpdate(4096);
+ }
+ {
+ InSequence seq;
+ EXPECT_CALL(listener_, OnDynamicTableSizeUpdate(0));
+ entry_buffer_.OnDynamicTableSizeUpdate(0);
+ }
+ {
+ InSequence seq;
+ EXPECT_CALL(listener_, OnDynamicTableSizeUpdate(1024));
+ entry_buffer_.OnDynamicTableSizeUpdate(1024);
+ }
+ {
+ InSequence seq;
+ EXPECT_CALL(listener_, OnDynamicTableSizeUpdate(1024));
+ entry_buffer_.OnDynamicTableSizeUpdate(1024);
+ }
+ StrictMock<MockHpackWholeEntryListener> listener2;
+ entry_buffer_.set_listener(&listener2);
+ {
+ InSequence seq;
+ EXPECT_CALL(listener2, OnDynamicTableSizeUpdate(0));
+ entry_buffer_.OnDynamicTableSizeUpdate(0);
+ }
+}
+
+TEST_F(HpackWholeEntryBufferTest, OnNameIndexAndLiteralValue) {
+ entry_buffer_.OnStartLiteralHeader(HpackEntryType::kNeverIndexedLiteralHeader,
+ 123);
+ entry_buffer_.OnValueStart(false, 10);
+ entry_buffer_.OnValueData("some data.", 10);
+
+ // Force the value to be buffered.
+ entry_buffer_.BufferStringsIfUnbuffered();
+
+ EXPECT_CALL(
+ listener_,
+ OnNameIndexAndLiteralValue(
+ HpackEntryType::kNeverIndexedLiteralHeader, 123,
+ AllOf(Property(&HpackDecoderStringBuffer::str, "some data."),
+ Property(&HpackDecoderStringBuffer::BufferedLength, 10))));
+
+ entry_buffer_.OnValueEnd();
+}
+
+TEST_F(HpackWholeEntryBufferTest, OnLiteralNameAndValue) {
+ entry_buffer_.OnStartLiteralHeader(HpackEntryType::kIndexedLiteralHeader, 0);
+ // Force the name to be buffered by delivering it in two pieces.
+ entry_buffer_.OnNameStart(false, 9);
+ entry_buffer_.OnNameData("some-", 5);
+ entry_buffer_.OnNameData("name", 4);
+ entry_buffer_.OnNameEnd();
+ entry_buffer_.OnValueStart(false, 12);
+ entry_buffer_.OnValueData("Header Value", 12);
+
+ EXPECT_CALL(
+ listener_,
+ OnLiteralNameAndValue(
+ HpackEntryType::kIndexedLiteralHeader,
+ AllOf(Property(&HpackDecoderStringBuffer::str, "some-name"),
+ Property(&HpackDecoderStringBuffer::BufferedLength, 9)),
+ AllOf(Property(&HpackDecoderStringBuffer::str, "Header Value"),
+ Property(&HpackDecoderStringBuffer::BufferedLength, 0))));
+
+ entry_buffer_.OnValueEnd();
+}
+
+// Verify that a name longer than the allowed size generates an error.
+TEST_F(HpackWholeEntryBufferTest, NameTooLong) {
+ entry_buffer_.OnStartLiteralHeader(HpackEntryType::kIndexedLiteralHeader, 0);
+ EXPECT_CALL(listener_, OnHpackDecodeError(HasSubstr("HPACK entry name")));
+ entry_buffer_.OnNameStart(false, kMaxStringSize + 1);
+}
+
+// Verify that a name longer than the allowed size generates an error.
+TEST_F(HpackWholeEntryBufferTest, ValueTooLong) {
+ entry_buffer_.OnStartLiteralHeader(HpackEntryType::kIndexedLiteralHeader, 1);
+ EXPECT_CALL(listener_, OnHpackDecodeError(HasSubstr("HPACK entry value")));
+ entry_buffer_.OnValueStart(false, kMaxStringSize + 1);
+}
+
+// Verify that a Huffman encoded name with an explicit EOS generates an error
+// for an explicit EOS.
+TEST_F(HpackWholeEntryBufferTest, NameHuffmanError) {
+ const char data[] = "\xff\xff\xff";
+ entry_buffer_.OnStartLiteralHeader(HpackEntryType::kUnindexedLiteralHeader,
+ 0);
+ entry_buffer_.OnNameStart(true, 4);
+ entry_buffer_.OnNameData(data, 3);
+
+ EXPECT_CALL(listener_, OnHpackDecodeError(HasSubstr("HPACK entry name")));
+
+ entry_buffer_.OnNameData(data, 1);
+
+ // After an error is reported, the listener is not called again.
+ EXPECT_CALL(listener_, OnDynamicTableSizeUpdate(8096)).Times(0);
+ entry_buffer_.OnDynamicTableSizeUpdate(8096);
+}
+
+// Verify that a Huffman encoded value that isn't properly terminated with
+// a partial EOS symbol generates an error.
+TEST_F(HpackWholeEntryBufferTest, ValueeHuffmanError) {
+ const char data[] = "\x00\x00\x00";
+ entry_buffer_.OnStartLiteralHeader(HpackEntryType::kNeverIndexedLiteralHeader,
+ 61);
+ entry_buffer_.OnValueStart(true, 3);
+ entry_buffer_.OnValueData(data, 3);
+
+ EXPECT_CALL(listener_, OnHpackDecodeError(HasSubstr("HPACK entry value")));
+
+ entry_buffer_.OnValueEnd();
+
+ // After an error is reported, the listener is not called again.
+ EXPECT_CALL(listener_, OnIndexedHeader(17)).Times(0);
+ entry_buffer_.OnIndexedHeader(17);
+}
+
+} // namespace
+} // namespace test
+} // namespace net
diff --git a/chromium/net/http2/hpack/decoder/hpack_whole_entry_listener.cc b/chromium/net/http2/hpack/decoder/hpack_whole_entry_listener.cc
new file mode 100644
index 00000000000..b10bcd56e3f
--- /dev/null
+++ b/chromium/net/http2/hpack/decoder/hpack_whole_entry_listener.cc
@@ -0,0 +1,35 @@
+// Copyright 2016 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.
+
+#include "net/http2/hpack/decoder/hpack_whole_entry_listener.h"
+
+using base::StringPiece;
+
+namespace net {
+
+HpackWholeEntryListener::~HpackWholeEntryListener() {}
+
+HpackWholeEntryNoOpListener::~HpackWholeEntryNoOpListener() {}
+
+void HpackWholeEntryNoOpListener::OnIndexedHeader(size_t index) {}
+void HpackWholeEntryNoOpListener::OnNameIndexAndLiteralValue(
+ HpackEntryType entry_type,
+ size_t name_index,
+ HpackDecoderStringBuffer* value_buffer) {}
+void HpackWholeEntryNoOpListener::OnLiteralNameAndValue(
+ HpackEntryType entry_type,
+ HpackDecoderStringBuffer* name_buffer,
+ HpackDecoderStringBuffer* value_buffer) {}
+void HpackWholeEntryNoOpListener::OnDynamicTableSizeUpdate(size_t size) {}
+void HpackWholeEntryNoOpListener::OnHpackDecodeError(
+ StringPiece error_message) {}
+
+// static
+HpackWholeEntryNoOpListener* HpackWholeEntryNoOpListener::NoOpListener() {
+ static HpackWholeEntryNoOpListener* static_instance =
+ new HpackWholeEntryNoOpListener();
+ return static_instance;
+}
+
+} // namespace net
diff --git a/chromium/net/http2/hpack/decoder/hpack_whole_entry_listener.h b/chromium/net/http2/hpack/decoder/hpack_whole_entry_listener.h
new file mode 100644
index 00000000000..af1457ed806
--- /dev/null
+++ b/chromium/net/http2/hpack/decoder/hpack_whole_entry_listener.h
@@ -0,0 +1,80 @@
+// Copyright 2016 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.
+
+// Defines HpackWholeEntryListener, the base class of listeners for decoded
+// complete HPACK entries, as opposed to HpackEntryDecoderListener which
+// receives multiple callbacks for some single entries.
+
+#ifndef NET_HTTP2_HPACK_DECODER_HPACK_WHOLE_ENTRY_LISTENER_H_
+#define NET_HTTP2_HPACK_DECODER_HPACK_WHOLE_ENTRY_LISTENER_H_
+
+#include <stddef.h>
+
+#include "base/strings/string_piece.h"
+#include "net/base/net_export.h"
+#include "net/http2/hpack/decoder/hpack_decoder_string_buffer.h"
+#include "net/http2/hpack/http2_hpack_constants.h"
+
+namespace net {
+
+class NET_EXPORT_PRIVATE HpackWholeEntryListener {
+ public:
+ virtual ~HpackWholeEntryListener();
+
+ // Called when an indexed header (i.e. one in the static or dynamic table) has
+ // been decoded from an HPACK block. index is supposed to be non-zero, but
+ // that has not been checked by the caller.
+ virtual void OnIndexedHeader(size_t index) = 0;
+
+ // Called when a header entry with a name index and literal value has
+ // been fully decoded from an HPACK block. name_index is NOT zero.
+ // entry_type will be kIndexedLiteralHeader, kUnindexedLiteralHeader, or
+ // kNeverIndexedLiteralHeader.
+ virtual void OnNameIndexAndLiteralValue(
+ HpackEntryType entry_type,
+ size_t name_index,
+ HpackDecoderStringBuffer* value_buffer) = 0;
+
+ // Called when a header entry with a literal name and literal value
+ // has been fully decoded from an HPACK block. entry_type will be
+ // kIndexedLiteralHeader, kUnindexedLiteralHeader, or
+ // kNeverIndexedLiteralHeader.
+ virtual void OnLiteralNameAndValue(
+ HpackEntryType entry_type,
+ HpackDecoderStringBuffer* name_buffer,
+ HpackDecoderStringBuffer* value_buffer) = 0;
+
+ // Called when an update to the size of the peer's dynamic table has been
+ // decoded.
+ virtual void OnDynamicTableSizeUpdate(size_t size) = 0;
+
+ // OnHpackDecodeError is called if an error is detected while decoding.
+ // error_message may be used in a GOAWAY frame as the Opaque Data.
+ virtual void OnHpackDecodeError(base::StringPiece error_message) = 0;
+};
+
+// A no-op implementation of HpackWholeEntryDecoderListener, useful for ignoring
+// callbacks once an error is detected.
+class HpackWholeEntryNoOpListener : public HpackWholeEntryListener {
+ public:
+ ~HpackWholeEntryNoOpListener() override;
+
+ void OnIndexedHeader(size_t index) override;
+ void OnNameIndexAndLiteralValue(
+ HpackEntryType entry_type,
+ size_t name_index,
+ HpackDecoderStringBuffer* value_buffer) override;
+ void OnLiteralNameAndValue(HpackEntryType entry_type,
+ HpackDecoderStringBuffer* name_buffer,
+ HpackDecoderStringBuffer* value_buffer) override;
+ void OnDynamicTableSizeUpdate(size_t size) override;
+ void OnHpackDecodeError(base::StringPiece error_message) override;
+
+ // Returns a listener that ignores all the calls.
+ static HpackWholeEntryNoOpListener* NoOpListener();
+};
+
+} // namespace net
+
+#endif // NET_HTTP2_HPACK_DECODER_HPACK_WHOLE_ENTRY_LISTENER_H_
diff --git a/chromium/net/http2/hpack/decoder/http2_hpack_decoder.cc b/chromium/net/http2/hpack/decoder/http2_hpack_decoder.cc
new file mode 100644
index 00000000000..4a69710dfa3
--- /dev/null
+++ b/chromium/net/http2/hpack/decoder/http2_hpack_decoder.cc
@@ -0,0 +1,124 @@
+// Copyright 2017 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.
+
+#include "net/http2/hpack/decoder/http2_hpack_decoder.h"
+
+#include "base/logging.h"
+#include "net/http2/decoder/decode_status.h"
+
+using base::StringPiece;
+
+namespace net {
+
+Http2HpackDecoder::Http2HpackDecoder(HpackDecoderListener* listener,
+ size_t max_string_size)
+ : decoder_state_(listener),
+ entry_buffer_(&decoder_state_, max_string_size),
+ block_decoder_(&entry_buffer_),
+ error_detected_(false) {}
+
+Http2HpackDecoder::~Http2HpackDecoder() {}
+
+void Http2HpackDecoder::set_listener(HpackDecoderListener* listener) {
+ return decoder_state_.set_listener(listener);
+}
+
+HpackDecoderListener* Http2HpackDecoder::listener() const {
+ return decoder_state_.listener();
+}
+
+void Http2HpackDecoder::set_max_string_size_bytes(
+ size_t max_string_size_bytes) {
+ entry_buffer_.set_max_string_size_bytes(max_string_size_bytes);
+}
+
+void Http2HpackDecoder::ApplyHeaderTableSizeSetting(
+ uint32_t max_header_table_size) {
+ decoder_state_.ApplyHeaderTableSizeSetting(max_header_table_size);
+}
+
+bool Http2HpackDecoder::StartDecodingBlock() {
+ DVLOG(3) << "Http2HpackDecoder::StartDecodingBlock, error_detected="
+ << (error_detected() ? "true" : "false");
+ if (error_detected()) {
+ return false;
+ }
+ // TODO(jamessynge): Eliminate Reset(), which shouldn't be necessary
+ // if there are no errors, and shouldn't be necessary with errors if
+ // we never resume decoding after an error has been detected.
+ block_decoder_.Reset();
+ decoder_state_.OnHeaderBlockStart();
+ return true;
+}
+
+bool Http2HpackDecoder::DecodeFragment(DecodeBuffer* db) {
+ DVLOG(3) << "Http2HpackDecoder::DecodeFragment, error_detected="
+ << (error_detected() ? "true" : "false")
+ << ", size=" << db->Remaining();
+ if (error_detected()) {
+ return false;
+ }
+ // Decode contents of db as an HPACK block fragment, forwards the decoded
+ // entries to entry_buffer_, which in turn forwards them to decode_state_,
+ // which finally forwards them to the HpackDecoderListener.
+ DecodeStatus status = block_decoder_.Decode(db);
+ if (status == DecodeStatus::kDecodeError) {
+ // This has probably already been reported, but just in case...
+ ReportError("HPACK block malformed.");
+ return false;
+ } else if (error_detected()) {
+ return false;
+ }
+ // Should be positioned between entries iff decoding is complete.
+ DCHECK_EQ(block_decoder_.before_entry(), status == DecodeStatus::kDecodeDone)
+ << status;
+ if (!block_decoder_.before_entry()) {
+ entry_buffer_.BufferStringsIfUnbuffered();
+ }
+ return true;
+}
+
+bool Http2HpackDecoder::EndDecodingBlock() {
+ DVLOG(3) << "Http2HpackDecoder::EndDecodingBlock, error_detected="
+ << (error_detected() ? "true" : "false");
+ if (error_detected()) {
+ return false;
+ }
+ if (!block_decoder_.before_entry()) {
+ // The HPACK block ended in the middle of an entry.
+ ReportError("HPACK block truncated.");
+ return false;
+ }
+ decoder_state_.OnHeaderBlockEnd();
+ if (error_detected()) {
+ // HpackDecoderState will have reported the error.
+ return false;
+ }
+ return true;
+}
+
+bool Http2HpackDecoder::error_detected() {
+ if (!error_detected_) {
+ if (entry_buffer_.error_detected()) {
+ DVLOG(2) << "Http2HpackDecoder::error_detected in entry_buffer_";
+ error_detected_ = true;
+ } else if (decoder_state_.error_detected()) {
+ DVLOG(2) << "Http2HpackDecoder::error_detected in decoder_state_";
+ error_detected_ = true;
+ }
+ }
+ return error_detected_;
+}
+
+void Http2HpackDecoder::ReportError(StringPiece error_message) {
+ DVLOG(3) << "Http2HpackDecoder::ReportError is new="
+ << (!error_detected_ ? "true" : "false")
+ << ", error_message: " << error_message;
+ if (!error_detected_) {
+ error_detected_ = true;
+ listener()->OnHeaderErrorDetected(error_message);
+ }
+}
+
+} // namespace net
diff --git a/chromium/net/http2/hpack/decoder/http2_hpack_decoder.h b/chromium/net/http2/hpack/decoder/http2_hpack_decoder.h
new file mode 100644
index 00000000000..c61c54deede
--- /dev/null
+++ b/chromium/net/http2/hpack/decoder/http2_hpack_decoder.h
@@ -0,0 +1,116 @@
+// Copyright 2017 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.
+
+#ifndef NET_HTTP2_HPACK_DECODER_HTTP2_HPACK_DECODER_H_
+#define NET_HTTP2_HPACK_DECODER_HTTP2_HPACK_DECODER_H_
+
+// Decodes HPACK blocks, calls an Http2HpackDecoderListener with the decoded
+// header entries. Also notifies the listener of errors and of the boundaries of
+// the HPACK blocks.
+
+// TODO(jamessynge): Add feature allowing an HpackEntryDecoderListener
+// sub-class (and possibly others) to be passed in for counting events,
+// so that deciding whether to count is not done by having lots of if
+// statements, but instead by inserting an indirection only when needed.
+
+// TODO(jamessynge): Consider whether to return false from methods below
+// when an error has been previously detected. It protects calling code
+// from its failure to pay attention to previous errors, but should we
+// spend time to do that?
+
+#include <stddef.h>
+#include <stdint.h>
+
+#include "base/macros.h"
+#include "base/strings/string_piece.h"
+#include "net/base/net_export.h"
+#include "net/http2/decoder/decode_buffer.h"
+#include "net/http2/hpack/decoder/hpack_block_decoder.h"
+#include "net/http2/hpack/decoder/hpack_decoder_listener.h"
+#include "net/http2/hpack/decoder/hpack_decoder_state.h"
+#include "net/http2/hpack/decoder/hpack_whole_entry_buffer.h"
+
+namespace net {
+namespace test {
+class Http2HpackDecoderPeer;
+} // namespace test
+
+class NET_EXPORT_PRIVATE Http2HpackDecoder {
+ public:
+ Http2HpackDecoder(HpackDecoderListener* listener, size_t max_string_size);
+ virtual ~Http2HpackDecoder();
+
+ void set_listener(HpackDecoderListener* listener);
+ HpackDecoderListener* listener() const;
+
+ // max_string_size specifies the maximum size of an on-the-wire string (name
+ // or value, plain or Huffman encoded) that will be accepted. See sections
+ // 5.1 and 5.2 of RFC 7541. This is a defense against OOM attacks; HTTP/2
+ // allows a decoder to enforce any limit of the size of the header lists
+ // that it is willing to decode, including less than the MAX_HEADER_LIST_SIZE
+ // setting, a setting that is initially unlimited. For example, we might
+ // choose to send a MAX_HEADER_LIST_SIZE of 64KB, and to use that same value
+ // as the upper bound for individual strings.
+ void set_max_string_size_bytes(size_t max_string_size_bytes);
+
+ // ApplyHeaderTableSizeSetting notifies this object that this endpoint has
+ // received a SETTINGS ACK frame acknowledging an earlier SETTINGS frame from
+ // this endpoint specifying a new value for SETTINGS_HEADER_TABLE_SIZE (the
+ // maximum size of the dynamic table that this endpoint will use to decode
+ // HPACK blocks).
+ // Because a SETTINGS frame can contain SETTINGS_HEADER_TABLE_SIZE values,
+ // the caller must keep track of those multiple changes, and make
+ // corresponding calls to this method. In particular, a call must be made
+ // with the lowest value acknowledged by the peer, and a call must be made
+ // with the final value acknowledged, in that order; additional calls may
+ // be made if additional values were sent. These calls must be made between
+ // decoding the SETTINGS ACK, and before the next HPACK block is decoded.
+ void ApplyHeaderTableSizeSetting(uint32_t max_header_table_size);
+
+ // Prepares the decoder for decoding a new HPACK block, and announces this to
+ // its listener. Returns true if OK to continue with decoding, false if an
+ // error has been detected, which for StartDecodingBlock means the error was
+ // detected while decoding a previous HPACK block.
+ bool StartDecodingBlock();
+
+ // Decodes a fragment (some or all of the remainder) of an HPACK block,
+ // reporting header entries (name & value pairs) that it completely decodes
+ // in the process to the listener. Returns true successfully decoded, false if
+ // an error has been detected, either during decoding of the fragment, or
+ // prior to this call.
+ bool DecodeFragment(DecodeBuffer* db);
+
+ // Completes the process of decoding an HPACK block: if the HPACK block was
+ // properly terminated, announces the end of the header list to the listener
+ // and returns true; else returns false.
+ bool EndDecodingBlock();
+
+ // Was an error detected?
+ bool error_detected();
+
+ private:
+ friend class test::Http2HpackDecoderPeer;
+
+ // Reports an error to the listener IF this is the first error detected.
+ void ReportError(base::StringPiece error_message);
+
+ // The decompressor state, as defined by HPACK (i.e. the static and dynamic
+ // tables).
+ HpackDecoderState decoder_state_;
+
+ // Assembles the various parts of a header entry into whole entries.
+ HpackWholeEntryBuffer entry_buffer_;
+
+ // The decoder of HPACK blocks into entry parts, passed to entry_buffer_.
+ HpackBlockDecoder block_decoder_;
+
+ // Has an error been detected?
+ bool error_detected_;
+
+ DISALLOW_COPY_AND_ASSIGN(Http2HpackDecoder);
+};
+
+} // namespace net
+
+#endif // NET_HTTP2_HPACK_DECODER_HTTP2_HPACK_DECODER_H_
diff --git a/chromium/net/http2/hpack/decoder/http2_hpack_decoder_test.cc b/chromium/net/http2/hpack/decoder/http2_hpack_decoder_test.cc
new file mode 100644
index 00000000000..1d969b129ac
--- /dev/null
+++ b/chromium/net/http2/hpack/decoder/http2_hpack_decoder_test.cc
@@ -0,0 +1,1219 @@
+// Copyright 2017 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.
+
+#include "net/http2/hpack/decoder/http2_hpack_decoder.h"
+
+// Tests of Http2HpackDecoder.
+
+#include <string>
+#include <tuple>
+#include <utility>
+#include <vector>
+
+#include "base/logging.h"
+#include "base/strings/string_piece.h"
+#include "net/http2/decoder/decode_buffer.h"
+#include "net/http2/hpack/decoder/hpack_decoder_listener.h"
+#include "net/http2/hpack/decoder/hpack_decoder_state.h"
+#include "net/http2/hpack/decoder/hpack_decoder_tables.h"
+#include "net/http2/hpack/hpack_string.h"
+#include "net/http2/hpack/http2_hpack_constants.h"
+#include "net/http2/hpack/tools/hpack_block_builder.h"
+#include "net/http2/hpack/tools/hpack_example.h"
+#include "net/http2/http2_constants.h"
+#include "net/http2/tools/failure.h"
+#include "net/http2/tools/http2_random.h"
+#include "net/http2/tools/random_util.h"
+#include "testing/gmock/include/gmock/gmock.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+using base::StringPiece;
+using std::string;
+using ::testing::AssertionFailure;
+using ::testing::AssertionResult;
+using ::testing::AssertionSuccess;
+using ::testing::ElementsAreArray;
+using ::testing::HasSubstr;
+
+namespace net {
+namespace test {
+class HpackDecoderStatePeer {
+ public:
+ static HpackDecoderTables* GetDecoderTables(HpackDecoderState* state) {
+ return &state->decoder_tables_;
+ }
+};
+class Http2HpackDecoderPeer {
+ public:
+ static HpackDecoderState* GetDecoderState(Http2HpackDecoder* decoder) {
+ return &decoder->decoder_state_;
+ }
+ static HpackDecoderTables* GetDecoderTables(Http2HpackDecoder* decoder) {
+ return HpackDecoderStatePeer::GetDecoderTables(GetDecoderState(decoder));
+ }
+};
+
+namespace {
+
+typedef std::tuple<HpackEntryType, string, string> HpackHeaderEntry;
+typedef std::vector<HpackHeaderEntry> HpackHeaderEntries;
+
+// TODO(jamessynge): Create a ...test_utils.h file with the mock listener
+// and with VerifyDynamicTableContents.
+class MockHpackDecoderListener : public HpackDecoderListener {
+ public:
+ MOCK_METHOD0(OnHeaderListStart, void());
+ MOCK_METHOD3(OnHeader,
+ void(HpackEntryType entry_type,
+ const HpackString& name,
+ const HpackString& value));
+ MOCK_METHOD0(OnHeaderListEnd, void());
+ MOCK_METHOD1(OnHeaderErrorDetected, void(StringPiece error_message));
+};
+
+class Http2HpackDecoderTest : public ::testing::TestWithParam<bool>,
+ public HpackDecoderListener {
+ protected:
+ // Note that we initialize the random number generator with the same seed
+ // for each individual test, therefore the order in which the tests are
+ // executed does not effect the sequence produced by the RNG within any
+ // one test.
+ Http2HpackDecoderTest() : decoder_(this, 4096) {
+ fragment_the_hpack_block_ = GetParam();
+ }
+ ~Http2HpackDecoderTest() override {}
+
+ void OnHeaderListStart() override {
+ ASSERT_FALSE(saw_start_);
+ ASSERT_FALSE(saw_end_);
+ saw_start_ = true;
+ header_entries_.clear();
+ }
+
+ // Called for each header name-value pair that is decoded, in the order they
+ // appear in the HPACK block. Multiple values for a given key will be emitted
+ // as multiple calls to OnHeader.
+ void OnHeader(HpackEntryType entry_type,
+ const HpackString& name,
+ const HpackString& value) override {
+ ASSERT_TRUE(saw_start_);
+ ASSERT_FALSE(saw_end_);
+ // header_entries_.push_back({entry_type, name.ToString(),
+ // value.ToString()});
+ header_entries_.emplace_back(entry_type, name.ToString(), value.ToString());
+ }
+
+ // OnHeaderBlockEnd is called after successfully decoding an HPACK block. Will
+ // only be called once per block, even if it extends into CONTINUATION frames.
+ // A callback method which notifies when the parser finishes handling a
+ // header block (i.e. the containing frame has the END_STREAM flag set).
+ // Also indicates the total number of bytes in this block.
+ void OnHeaderListEnd() override {
+ ASSERT_TRUE(saw_start_);
+ ASSERT_FALSE(saw_end_);
+ ASSERT_TRUE(error_messages_.empty());
+ saw_end_ = true;
+ }
+
+ // OnHeaderErrorDetected is called if an error is detected while decoding.
+ // error_message may be used in a GOAWAY frame as the Opaque Data.
+ void OnHeaderErrorDetected(StringPiece error_message) override {
+ ASSERT_TRUE(saw_start_);
+ error_messages_.push_back(error_message.as_string());
+ // No further callbacks should be made at this point, so replace 'this' as
+ // the listener with mock_listener_, which is a strict mock, so will
+ // generate an error for any calls.
+ decoder_.set_listener(&mock_listener_);
+ }
+
+ AssertionResult DecodeBlock(StringPiece block) {
+ VLOG(1) << "Http2HpackDecoderTest::DecodeBlock";
+
+ VERIFY_FALSE(decoder_.error_detected());
+ VERIFY_TRUE(error_messages_.empty());
+ VERIFY_FALSE(saw_start_);
+ VERIFY_FALSE(saw_end_);
+ header_entries_.clear();
+
+ VERIFY_FALSE(decoder_.error_detected());
+ VERIFY_TRUE(decoder_.StartDecodingBlock());
+ VERIFY_FALSE(decoder_.error_detected());
+
+ if (fragment_the_hpack_block_) {
+ // See note in ctor regarding RNG.
+ while (!block.empty()) {
+ size_t fragment_size =
+ GenerateRandomSizeSkewedLow(block.size(), &random_);
+ DecodeBuffer db(block.substr(0, fragment_size));
+ VERIFY_TRUE(decoder_.DecodeFragment(&db));
+ VERIFY_EQ(0u, db.Remaining());
+ block.remove_prefix(fragment_size);
+ }
+ } else {
+ DecodeBuffer db(block);
+ VERIFY_TRUE(decoder_.DecodeFragment(&db));
+ VERIFY_EQ(0u, db.Remaining());
+ }
+ VERIFY_FALSE(decoder_.error_detected());
+
+ VERIFY_TRUE(decoder_.EndDecodingBlock());
+ if (saw_end_) {
+ VERIFY_FALSE(decoder_.error_detected());
+ VERIFY_TRUE(error_messages_.empty());
+ } else {
+ VERIFY_TRUE(decoder_.error_detected());
+ VERIFY_FALSE(error_messages_.empty());
+ }
+
+ saw_start_ = saw_end_ = false;
+ return AssertionSuccess();
+ }
+
+ const HpackDecoderTables& GetDecoderTables() {
+ return *Http2HpackDecoderPeer::GetDecoderTables(&decoder_);
+ }
+ const HpackStringPair* Lookup(size_t index) {
+ return GetDecoderTables().Lookup(index);
+ }
+ size_t current_header_table_size() {
+ return GetDecoderTables().current_header_table_size();
+ }
+ size_t header_table_size_limit() {
+ return GetDecoderTables().header_table_size_limit();
+ }
+ void set_header_table_size_limit(size_t size) {
+ Http2HpackDecoderPeer::GetDecoderTables(&decoder_)->DynamicTableSizeUpdate(
+ size);
+ }
+
+ // dynamic_index is one-based, because that is the way RFC 7541 shows it.
+ AssertionResult VerifyEntry(size_t dynamic_index,
+ const char* name,
+ const char* value) {
+ const HpackStringPair* entry =
+ Lookup(dynamic_index + kFirstDynamicTableIndex - 1);
+ VERIFY_NE(entry, nullptr);
+ VERIFY_EQ(static_cast<StringPiece>(entry->name), name);
+ VERIFY_EQ(static_cast<StringPiece>(entry->value), value);
+ return AssertionSuccess();
+ }
+ AssertionResult VerifyNoEntry(size_t dynamic_index) {
+ const HpackStringPair* entry =
+ Lookup(dynamic_index + kFirstDynamicTableIndex - 1);
+ VERIFY_EQ(entry, nullptr);
+ return AssertionSuccess();
+ }
+ AssertionResult VerifyDynamicTableContents(
+ const std::vector<std::pair<const char*, const char*>>& entries) {
+ size_t index = 1;
+ for (const auto& entry : entries) {
+ VERIFY_SUCCESS(VerifyEntry(index, entry.first, entry.second));
+ ++index;
+ }
+ VERIFY_SUCCESS(VerifyNoEntry(index));
+ return AssertionSuccess();
+ }
+
+ Http2Random random_;
+ Http2HpackDecoder decoder_;
+ testing::StrictMock<MockHpackDecoderListener> mock_listener_;
+ HpackHeaderEntries header_entries_;
+ std::vector<string> error_messages_;
+ bool fragment_the_hpack_block_;
+ bool saw_start_ = false;
+ bool saw_end_ = false;
+};
+INSTANTIATE_TEST_CASE_P(AllWays, Http2HpackDecoderTest, ::testing::Bool());
+
+// Test based on RFC 7541, section C.3: Request Examples without Huffman Coding.
+// This section shows several consecutive header lists, corresponding to HTTP
+// requests, on the same connection.
+// http://httpwg.org/specs/rfc7541.html#rfc.section.C.3
+TEST_P(Http2HpackDecoderTest, C3_RequestExamples) {
+ // C.3.1 First Request
+ string hpack_block = HpackExampleToStringOrDie(R"(
+ 82 | == Indexed - Add ==
+ | idx = 2
+ | -> :method: GET
+ 86 | == Indexed - Add ==
+ | idx = 6
+ | -> :scheme: http
+ 84 | == Indexed - Add ==
+ | idx = 4
+ | -> :path: /
+ 41 | == Literal indexed ==
+ | Indexed name (idx = 1)
+ | :authority
+ 0f | Literal value (len = 15)
+ 7777 772e 6578 616d 706c 652e 636f 6d | www.example.com
+ | -> :authority:
+ | www.example.com
+ )");
+ EXPECT_TRUE(DecodeBlock(hpack_block));
+ ASSERT_THAT(
+ header_entries_,
+ ElementsAreArray({
+ HpackHeaderEntry{HpackEntryType::kIndexedHeader, ":method", "GET"},
+ HpackHeaderEntry{HpackEntryType::kIndexedHeader, ":scheme", "http"},
+ HpackHeaderEntry{HpackEntryType::kIndexedHeader, ":path", "/"},
+ HpackHeaderEntry{HpackEntryType::kIndexedLiteralHeader, ":authority",
+ "www.example.com"},
+ }));
+
+ // Dynamic Table (after decoding):
+ //
+ // [ 1] (s = 57) :authority: www.example.com
+ // Table size: 57
+ ASSERT_TRUE(VerifyDynamicTableContents({{":authority", "www.example.com"}}));
+ ASSERT_EQ(57u, current_header_table_size());
+
+ // C.3.2 Second Request
+ hpack_block = HpackExampleToStringOrDie(R"(
+ 82 | == Indexed - Add ==
+ | idx = 2
+ | -> :method: GET
+ 86 | == Indexed - Add ==
+ | idx = 6
+ | -> :scheme: http
+ 84 | == Indexed - Add ==
+ | idx = 4
+ | -> :path: /
+ be | == Indexed - Add ==
+ | idx = 62
+ | -> :authority:
+ | www.example.com
+ 58 | == Literal indexed ==
+ | Indexed name (idx = 24)
+ | cache-control
+ 08 | Literal value (len = 8)
+ 6e6f 2d63 6163 6865 | no-cache
+ | -> cache-control: no-cache
+ )");
+ EXPECT_TRUE(DecodeBlock(hpack_block));
+ ASSERT_THAT(
+ header_entries_,
+ ElementsAreArray({
+ HpackHeaderEntry{HpackEntryType::kIndexedHeader, ":method", "GET"},
+ HpackHeaderEntry{HpackEntryType::kIndexedHeader, ":scheme", "http"},
+ HpackHeaderEntry{HpackEntryType::kIndexedHeader, ":path", "/"},
+ HpackHeaderEntry{HpackEntryType::kIndexedHeader, ":authority",
+ "www.example.com"},
+ HpackHeaderEntry{HpackEntryType::kIndexedLiteralHeader,
+ "cache-control", "no-cache"},
+ }));
+
+ // Dynamic Table (after decoding):
+ //
+ // [ 1] (s = 53) cache-control: no-cache
+ // [ 2] (s = 57) :authority: www.example.com
+ // Table size: 110
+ ASSERT_TRUE(VerifyDynamicTableContents(
+ {{"cache-control", "no-cache"}, {":authority", "www.example.com"}}));
+ ASSERT_EQ(110u, current_header_table_size());
+
+ // C.3.2 Third Request
+ hpack_block = HpackExampleToStringOrDie(R"(
+ 82 | == Indexed - Add ==
+ | idx = 2
+ | -> :method: GET
+ 87 | == Indexed - Add ==
+ | idx = 7
+ | -> :scheme: https
+ 85 | == Indexed - Add ==
+ | idx = 5
+ | -> :path: /index.html
+ bf | == Indexed - Add ==
+ | idx = 63
+ | -> :authority:
+ | www.example.com
+ 40 | == Literal indexed ==
+ 0a | Literal name (len = 10)
+ 6375 7374 6f6d 2d6b 6579 | custom-key
+ 0c | Literal value (len = 12)
+ 6375 7374 6f6d 2d76 616c 7565 | custom-value
+ | -> custom-key:
+ | custom-value
+ )");
+ EXPECT_TRUE(DecodeBlock(hpack_block));
+ ASSERT_THAT(
+ header_entries_,
+ ElementsAreArray({
+ HpackHeaderEntry{HpackEntryType::kIndexedHeader, ":method", "GET"},
+ HpackHeaderEntry{HpackEntryType::kIndexedHeader, ":scheme", "https"},
+ HpackHeaderEntry{HpackEntryType::kIndexedHeader, ":path",
+ "/index.html"},
+ HpackHeaderEntry{HpackEntryType::kIndexedHeader, ":authority",
+ "www.example.com"},
+ HpackHeaderEntry{HpackEntryType::kIndexedLiteralHeader, "custom-key",
+ "custom-value"},
+ }));
+
+ // Dynamic Table (after decoding):
+ //
+ // [ 1] (s = 54) custom-key: custom-value
+ // [ 2] (s = 53) cache-control: no-cache
+ // [ 3] (s = 57) :authority: www.example.com
+ // Table size: 164
+ ASSERT_TRUE(VerifyDynamicTableContents({{"custom-key", "custom-value"},
+ {"cache-control", "no-cache"},
+ {":authority", "www.example.com"}}));
+ ASSERT_EQ(164u, current_header_table_size());
+}
+
+// Test based on RFC 7541, section C.4 Request Examples with Huffman Coding.
+// This section shows the same examples as the previous section but uses
+// Huffman encoding for the literal values.
+// http://httpwg.org/specs/rfc7541.html#rfc.section.C.4
+TEST_P(Http2HpackDecoderTest, C4_RequestExamplesWithHuffmanEncoding) {
+ // C.4.1 First Request
+ string hpack_block = HpackExampleToStringOrDie(R"(
+ 82 | == Indexed - Add ==
+ | idx = 2
+ | -> :method: GET
+ 86 | == Indexed - Add ==
+ | idx = 6
+ | -> :scheme: http
+ 84 | == Indexed - Add ==
+ | idx = 4
+ | -> :path: /
+ 41 | == Literal indexed ==
+ | Indexed name (idx = 1)
+ | :authority
+ 8c | Literal value (len = 12)
+ | Huffman encoded:
+ f1e3 c2e5 f23a 6ba0 ab90 f4ff | .....:k.....
+ | Decoded:
+ | www.example.com
+ | -> :authority:
+ | www.example.com
+ )");
+ EXPECT_TRUE(DecodeBlock(hpack_block));
+ ASSERT_THAT(
+ header_entries_,
+ ElementsAreArray({
+ HpackHeaderEntry{HpackEntryType::kIndexedHeader, ":method", "GET"},
+ HpackHeaderEntry{HpackEntryType::kIndexedHeader, ":scheme", "http"},
+ HpackHeaderEntry{HpackEntryType::kIndexedHeader, ":path", "/"},
+ HpackHeaderEntry{HpackEntryType::kIndexedLiteralHeader, ":authority",
+ "www.example.com"},
+ }));
+
+ // Dynamic Table (after decoding):
+ //
+ // [ 1] (s = 57) :authority: www.example.com
+ // Table size: 57
+ ASSERT_TRUE(VerifyDynamicTableContents({{":authority", "www.example.com"}}));
+ ASSERT_EQ(57u, current_header_table_size());
+
+ // C.4.2 Second Request
+ hpack_block = HpackExampleToStringOrDie(R"(
+ 82 | == Indexed - Add ==
+ | idx = 2
+ | -> :method: GET
+ 86 | == Indexed - Add ==
+ | idx = 6
+ | -> :scheme: http
+ 84 | == Indexed - Add ==
+ | idx = 4
+ | -> :path: /
+ be | == Indexed - Add ==
+ | idx = 62
+ | -> :authority:
+ | www.example.com
+ 58 | == Literal indexed ==
+ | Indexed name (idx = 24)
+ | cache-control
+ 86 | Literal value (len = 6)
+ | Huffman encoded:
+ a8eb 1064 9cbf | ...d..
+ | Decoded:
+ | no-cache
+ | -> cache-control: no-cache
+ )");
+ EXPECT_TRUE(DecodeBlock(hpack_block));
+ ASSERT_THAT(
+ header_entries_,
+ ElementsAreArray({
+ HpackHeaderEntry{HpackEntryType::kIndexedHeader, ":method", "GET"},
+ HpackHeaderEntry{HpackEntryType::kIndexedHeader, ":scheme", "http"},
+ HpackHeaderEntry{HpackEntryType::kIndexedHeader, ":path", "/"},
+ HpackHeaderEntry{HpackEntryType::kIndexedHeader, ":authority",
+ "www.example.com"},
+ HpackHeaderEntry{HpackEntryType::kIndexedLiteralHeader,
+ "cache-control", "no-cache"},
+ }));
+
+ // Dynamic Table (after decoding):
+ //
+ // [ 1] (s = 53) cache-control: no-cache
+ // [ 2] (s = 57) :authority: www.example.com
+ // Table size: 110
+ ASSERT_TRUE(VerifyDynamicTableContents(
+ {{"cache-control", "no-cache"}, {":authority", "www.example.com"}}));
+ ASSERT_EQ(110u, current_header_table_size());
+
+ // C.4.2 Third Request
+ hpack_block = HpackExampleToStringOrDie(R"(
+ 82 | == Indexed - Add ==
+ | idx = 2
+ | -> :method: GET
+ 87 | == Indexed - Add ==
+ | idx = 7
+ | -> :scheme: https
+ 85 | == Indexed - Add ==
+ | idx = 5
+ | -> :path: /index.html
+ bf | == Indexed - Add ==
+ | idx = 63
+ | -> :authority:
+ | www.example.com
+ 40 | == Literal indexed ==
+ 88 | Literal name (len = 8)
+ | Huffman encoded:
+ 25a8 49e9 5ba9 7d7f | %.I.[.}.
+ | Decoded:
+ | custom-key
+ 89 | Literal value (len = 9)
+ | Huffman encoded:
+ 25a8 49e9 5bb8 e8b4 bf | %.I.[....
+ | Decoded:
+ | custom-value
+ | -> custom-key:
+ | custom-value
+ )");
+ EXPECT_TRUE(DecodeBlock(hpack_block));
+ ASSERT_THAT(
+ header_entries_,
+ ElementsAreArray({
+ HpackHeaderEntry{HpackEntryType::kIndexedHeader, ":method", "GET"},
+ HpackHeaderEntry{HpackEntryType::kIndexedHeader, ":scheme", "https"},
+ HpackHeaderEntry{HpackEntryType::kIndexedHeader, ":path",
+ "/index.html"},
+ HpackHeaderEntry{HpackEntryType::kIndexedHeader, ":authority",
+ "www.example.com"},
+ HpackHeaderEntry{HpackEntryType::kIndexedLiteralHeader, "custom-key",
+ "custom-value"},
+ }));
+
+ // Dynamic Table (after decoding):
+ //
+ // [ 1] (s = 54) custom-key: custom-value
+ // [ 2] (s = 53) cache-control: no-cache
+ // [ 3] (s = 57) :authority: www.example.com
+ // Table size: 164
+ ASSERT_TRUE(VerifyDynamicTableContents({{"custom-key", "custom-value"},
+ {"cache-control", "no-cache"},
+ {":authority", "www.example.com"}}));
+ ASSERT_EQ(164u, current_header_table_size());
+}
+
+// Test based on RFC 7541, section C.5: Response Examples without Huffman
+// Coding. This section shows several consecutive header lists, corresponding
+// to HTTP responses, on the same connection. The HTTP/2 setting parameter
+// SETTINGS_HEADER_TABLE_SIZE is set to the value of 256 octets, causing
+// some evictions to occur.
+// http://httpwg.org/specs/rfc7541.html#rfc.section.C.5
+TEST_P(Http2HpackDecoderTest, C5_ResponseExamples) {
+ set_header_table_size_limit(256);
+
+ // C.5.1 First Response
+ //
+ // Header list to encode:
+ //
+ // :status: 302
+ // cache-control: private
+ // date: Mon, 21 Oct 2013 20:13:21 GMT
+ // location: https://www.example.com
+
+ string hpack_block = HpackExampleToStringOrDie(R"(
+ 48 | == Literal indexed ==
+ | Indexed name (idx = 8)
+ | :status
+ 03 | Literal value (len = 3)
+ 3330 32 | 302
+ | -> :status: 302
+ 58 | == Literal indexed ==
+ | Indexed name (idx = 24)
+ | cache-control
+ 07 | Literal value (len = 7)
+ 7072 6976 6174 65 | private
+ | -> cache-control: private
+ 61 | == Literal indexed ==
+ | Indexed name (idx = 33)
+ | date
+ 1d | Literal value (len = 29)
+ 4d6f 6e2c 2032 3120 4f63 7420 3230 3133 | Mon, 21 Oct 2013
+ 2032 303a 3133 3a32 3120 474d 54 | 20:13:21 GMT
+ | -> date: Mon, 21 Oct 2013
+ | 20:13:21 GMT
+ 6e | == Literal indexed ==
+ | Indexed name (idx = 46)
+ | location
+ 17 | Literal value (len = 23)
+ 6874 7470 733a 2f2f 7777 772e 6578 616d | https://www.exam
+ 706c 652e 636f 6d | ple.com
+ | -> location:
+ | https://www.example.com
+ )");
+ EXPECT_TRUE(DecodeBlock(hpack_block));
+ ASSERT_THAT(header_entries_,
+ ElementsAreArray({
+ HpackHeaderEntry{HpackEntryType::kIndexedLiteralHeader,
+ ":status", "302"},
+ HpackHeaderEntry{HpackEntryType::kIndexedLiteralHeader,
+ "cache-control", "private"},
+ HpackHeaderEntry{HpackEntryType::kIndexedLiteralHeader,
+ "date", "Mon, 21 Oct 2013 20:13:21 GMT"},
+ HpackHeaderEntry{HpackEntryType::kIndexedLiteralHeader,
+ "location", "https://www.example.com"},
+ }));
+
+ // Dynamic Table (after decoding):
+ //
+ // [ 1] (s = 63) location: https://www.example.com
+ // [ 2] (s = 65) date: Mon, 21 Oct 2013 20:13:21 GMT
+ // [ 3] (s = 52) cache-control: private
+ // [ 4] (s = 42) :status: 302
+ // Table size: 222
+ ASSERT_TRUE(
+ VerifyDynamicTableContents({{"location", "https://www.example.com"},
+ {"date", "Mon, 21 Oct 2013 20:13:21 GMT"},
+ {"cache-control", "private"},
+ {":status", "302"}}));
+ ASSERT_EQ(222u, current_header_table_size());
+
+ // C.5.2 Second Response
+ //
+ // The (":status", "302") header field is evicted from the dynamic table to
+ // free space to allow adding the (":status", "307") header field.
+ //
+ // Header list to encode:
+ //
+ // :status: 307
+ // cache-control: private
+ // date: Mon, 21 Oct 2013 20:13:21 GMT
+ // location: https://www.example.com
+
+ hpack_block = HpackExampleToStringOrDie(R"(
+ 48 | == Literal indexed ==
+ | Indexed name (idx = 8)
+ | :status
+ 03 | Literal value (len = 3)
+ 3330 37 | 307
+ | - evict: :status: 302
+ | -> :status: 307
+ c1 | == Indexed - Add ==
+ | idx = 65
+ | -> cache-control: private
+ c0 | == Indexed - Add ==
+ | idx = 64
+ | -> date: Mon, 21 Oct 2013
+ | 20:13:21 GMT
+ bf | == Indexed - Add ==
+ | idx = 63
+ | -> location:
+ | https://www.example.com
+ )");
+ EXPECT_TRUE(DecodeBlock(hpack_block));
+ ASSERT_THAT(header_entries_,
+ ElementsAreArray({
+ HpackHeaderEntry{HpackEntryType::kIndexedLiteralHeader,
+ ":status", "307"},
+ HpackHeaderEntry{HpackEntryType::kIndexedHeader,
+ "cache-control", "private"},
+ HpackHeaderEntry{HpackEntryType::kIndexedHeader, "date",
+ "Mon, 21 Oct 2013 20:13:21 GMT"},
+ HpackHeaderEntry{HpackEntryType::kIndexedHeader, "location",
+ "https://www.example.com"},
+ }));
+
+ // Dynamic Table (after decoding):
+ //
+ // [ 1] (s = 42) :status: 307
+ // [ 2] (s = 63) location: https://www.example.com
+ // [ 3] (s = 65) date: Mon, 21 Oct 2013 20:13:21 GMT
+ // [ 4] (s = 52) cache-control: private
+ // Table size: 222
+
+ ASSERT_TRUE(
+ VerifyDynamicTableContents({{":status", "307"},
+ {"location", "https://www.example.com"},
+ {"date", "Mon, 21 Oct 2013 20:13:21 GMT"},
+ {"cache-control", "private"}}));
+ ASSERT_EQ(222u, current_header_table_size());
+
+ // C.5.3 Third Response
+ //
+ // Several header fields are evicted from the dynamic table during the
+ // processing of this header list.
+ //
+ // Header list to encode:
+ //
+ // :status: 200
+ // cache-control: private
+ // date: Mon, 21 Oct 2013 20:13:22 GMT
+ // location: https://www.example.com
+ // content-encoding: gzip
+ // set-cookie: foo=ASDJKHQKBZXOQWEOPIUAXQWEOIU; max-age=3600; version=1
+ hpack_block = HpackExampleToStringOrDie(R"(
+ 88 | == Indexed - Add ==
+ | idx = 8
+ | -> :status: 200
+ c1 | == Indexed - Add ==
+ | idx = 65
+ | -> cache-control: private
+ 61 | == Literal indexed ==
+ | Indexed name (idx = 33)
+ | date
+ 1d | Literal value (len = 29)
+ 4d6f 6e2c 2032 3120 4f63 7420 3230 3133 | Mon, 21 Oct 2013
+ 2032 303a 3133 3a32 3220 474d 54 | 20:13:22 GMT
+ | - evict: cache-control:
+ | private
+ | -> date: Mon, 21 Oct 2013
+ | 20:13:22 GMT
+ c0 | == Indexed - Add ==
+ | idx = 64
+ | -> location:
+ | https://www.example.com
+ 5a | == Literal indexed ==
+ | Indexed name (idx = 26)
+ | content-encoding
+ 04 | Literal value (len = 4)
+ 677a 6970 | gzip
+ | - evict: date: Mon, 21 Oct
+ | 2013 20:13:21 GMT
+ | -> content-encoding: gzip
+ 77 | == Literal indexed ==
+ | Indexed name (idx = 55)
+ | set-cookie
+ 38 | Literal value (len = 56)
+ 666f 6f3d 4153 444a 4b48 514b 425a 584f | foo=ASDJKHQKBZXO
+ 5157 454f 5049 5541 5851 5745 4f49 553b | QWEOPIUAXQWEOIU;
+ 206d 6178 2d61 6765 3d33 3630 303b 2076 | max-age=3600; v
+ 6572 7369 6f6e 3d31 | ersion=1
+ | - evict: location:
+ | https://www.example.com
+ | - evict: :status: 307
+ | -> set-cookie: foo=ASDJKHQ
+ | KBZXOQWEOPIUAXQWEOIU; ma
+ | x-age=3600; version=1
+ )");
+ EXPECT_TRUE(DecodeBlock(hpack_block));
+ ASSERT_THAT(
+ header_entries_,
+ ElementsAreArray({
+ HpackHeaderEntry{HpackEntryType::kIndexedHeader, ":status", "200"},
+ HpackHeaderEntry{HpackEntryType::kIndexedHeader, "cache-control",
+ "private"},
+ HpackHeaderEntry{HpackEntryType::kIndexedLiteralHeader, "date",
+ "Mon, 21 Oct 2013 20:13:22 GMT"},
+ HpackHeaderEntry{HpackEntryType::kIndexedHeader, "location",
+ "https://www.example.com"},
+ HpackHeaderEntry{HpackEntryType::kIndexedLiteralHeader,
+ "content-encoding", "gzip"},
+ HpackHeaderEntry{
+ HpackEntryType::kIndexedLiteralHeader, "set-cookie",
+ "foo=ASDJKHQKBZXOQWEOPIUAXQWEOIU; max-age=3600; version=1"},
+ }));
+
+ // Dynamic Table (after decoding):
+ //
+ // [ 1] (s = 98) set-cookie: foo=ASDJKHQKBZXOQWEOPIUAXQWEOIU;
+ // max-age=3600; version=1
+ // [ 2] (s = 52) content-encoding: gzip
+ // [ 3] (s = 65) date: Mon, 21 Oct 2013 20:13:22 GMT
+ // Table size: 215
+ ASSERT_TRUE(VerifyDynamicTableContents(
+ {{"set-cookie",
+ "foo=ASDJKHQKBZXOQWEOPIUAXQWEOIU; max-age=3600; version=1"},
+ {"content-encoding", "gzip"},
+ {"date", "Mon, 21 Oct 2013 20:13:22 GMT"}}));
+ ASSERT_EQ(215u, current_header_table_size());
+}
+
+// Test based on RFC 7541, section C.6: Response Examples with Huffman Coding.
+// This section shows the same examples as the previous section but uses Huffman
+// encoding for the literal values. The HTTP/2 setting parameter
+// SETTINGS_HEADER_TABLE_SIZE is set to the value of 256 octets, causing some
+// evictions to occur. The eviction mechanism uses the length of the decoded
+// literal values, so the same evictions occur as in the previous section.
+// http://httpwg.org/specs/rfc7541.html#rfc.section.C.6
+TEST_P(Http2HpackDecoderTest, C6_ResponseExamplesWithHuffmanEncoding) {
+ set_header_table_size_limit(256);
+
+ // C.5.1 First Response
+ //
+ // Header list to encode:
+ //
+ // :status: 302
+ // cache-control: private
+ // date: Mon, 21 Oct 2013 20:13:21 GMT
+ // location: https://www.example.com
+ string hpack_block = HpackExampleToStringOrDie(R"(
+ 48 | == Literal indexed ==
+ | Indexed name (idx = 8)
+ | :status
+ 03 | Literal value (len = 3)
+ 3330 32 | 302
+ | -> :status: 302
+ 58 | == Literal indexed ==
+ | Indexed name (idx = 24)
+ | cache-control
+ 07 | Literal value (len = 7)
+ 7072 6976 6174 65 | private
+ | -> cache-control: private
+ 61 | == Literal indexed ==
+ | Indexed name (idx = 33)
+ | date
+ 1d | Literal value (len = 29)
+ 4d6f 6e2c 2032 3120 4f63 7420 3230 3133 | Mon, 21 Oct 2013
+ 2032 303a 3133 3a32 3120 474d 54 | 20:13:21 GMT
+ | -> date: Mon, 21 Oct 2013
+ | 20:13:21 GMT
+ 6e | == Literal indexed ==
+ | Indexed name (idx = 46)
+ | location
+ 17 | Literal value (len = 23)
+ 6874 7470 733a 2f2f 7777 772e 6578 616d | https://www.exam
+ 706c 652e 636f 6d | ple.com
+ | -> location:
+ | https://www.example.com
+ )");
+ EXPECT_TRUE(DecodeBlock(hpack_block));
+ ASSERT_THAT(header_entries_,
+ ElementsAreArray({
+ HpackHeaderEntry{HpackEntryType::kIndexedLiteralHeader,
+ ":status", "302"},
+ HpackHeaderEntry{HpackEntryType::kIndexedLiteralHeader,
+ "cache-control", "private"},
+ HpackHeaderEntry{HpackEntryType::kIndexedLiteralHeader,
+ "date", "Mon, 21 Oct 2013 20:13:21 GMT"},
+ HpackHeaderEntry{HpackEntryType::kIndexedLiteralHeader,
+ "location", "https://www.example.com"},
+ }));
+
+ // Dynamic Table (after decoding):
+ //
+ // [ 1] (s = 63) location: https://www.example.com
+ // [ 2] (s = 65) date: Mon, 21 Oct 2013 20:13:21 GMT
+ // [ 3] (s = 52) cache-control: private
+ // [ 4] (s = 42) :status: 302
+ // Table size: 222
+ ASSERT_TRUE(
+ VerifyDynamicTableContents({{"location", "https://www.example.com"},
+ {"date", "Mon, 21 Oct 2013 20:13:21 GMT"},
+ {"cache-control", "private"},
+ {":status", "302"}}));
+ ASSERT_EQ(222u, current_header_table_size());
+
+ // C.5.2 Second Response
+ //
+ // The (":status", "302") header field is evicted from the dynamic table to
+ // free space to allow adding the (":status", "307") header field.
+ //
+ // Header list to encode:
+ //
+ // :status: 307
+ // cache-control: private
+ // date: Mon, 21 Oct 2013 20:13:21 GMT
+ // location: https://www.example.com
+ hpack_block = HpackExampleToStringOrDie(R"(
+ 48 | == Literal indexed ==
+ | Indexed name (idx = 8)
+ | :status
+ 03 | Literal value (len = 3)
+ 3330 37 | 307
+ | - evict: :status: 302
+ | -> :status: 307
+ c1 | == Indexed - Add ==
+ | idx = 65
+ | -> cache-control: private
+ c0 | == Indexed - Add ==
+ | idx = 64
+ | -> date: Mon, 21 Oct 2013
+ | 20:13:21 GMT
+ bf | == Indexed - Add ==
+ | idx = 63
+ | -> location:
+ | https://www.example.com
+ )");
+ EXPECT_TRUE(DecodeBlock(hpack_block));
+ ASSERT_THAT(header_entries_,
+ ElementsAreArray({
+ HpackHeaderEntry{HpackEntryType::kIndexedLiteralHeader,
+ ":status", "307"},
+ HpackHeaderEntry{HpackEntryType::kIndexedHeader,
+ "cache-control", "private"},
+ HpackHeaderEntry{HpackEntryType::kIndexedHeader, "date",
+ "Mon, 21 Oct 2013 20:13:21 GMT"},
+ HpackHeaderEntry{HpackEntryType::kIndexedHeader, "location",
+ "https://www.example.com"},
+ }));
+
+ // Dynamic Table (after decoding):
+ //
+ // [ 1] (s = 42) :status: 307
+ // [ 2] (s = 63) location: https://www.example.com
+ // [ 3] (s = 65) date: Mon, 21 Oct 2013 20:13:21 GMT
+ // [ 4] (s = 52) cache-control: private
+ // Table size: 222
+ ASSERT_TRUE(
+ VerifyDynamicTableContents({{":status", "307"},
+ {"location", "https://www.example.com"},
+ {"date", "Mon, 21 Oct 2013 20:13:21 GMT"},
+ {"cache-control", "private"}}));
+ ASSERT_EQ(222u, current_header_table_size());
+
+ // C.5.3 Third Response
+ //
+ // Several header fields are evicted from the dynamic table during the
+ // processing of this header list.
+ //
+ // Header list to encode:
+ //
+ // :status: 200
+ // cache-control: private
+ // date: Mon, 21 Oct 2013 20:13:22 GMT
+ // location: https://www.example.com
+ // content-encoding: gzip
+ // set-cookie: foo=ASDJKHQKBZXOQWEOPIUAXQWEOIU; max-age=3600; version=1
+ hpack_block = HpackExampleToStringOrDie(R"(
+ 88 | == Indexed - Add ==
+ | idx = 8
+ | -> :status: 200
+ c1 | == Indexed - Add ==
+ | idx = 65
+ | -> cache-control: private
+ 61 | == Literal indexed ==
+ | Indexed name (idx = 33)
+ | date
+ 1d | Literal value (len = 29)
+ 4d6f 6e2c 2032 3120 4f63 7420 3230 3133 | Mon, 21 Oct 2013
+ 2032 303a 3133 3a32 3220 474d 54 | 20:13:22 GMT
+ | - evict: cache-control:
+ | private
+ | -> date: Mon, 21 Oct 2013
+ | 20:13:22 GMT
+ c0 | == Indexed - Add ==
+ | idx = 64
+ | -> location:
+ | https://www.example.com
+ 5a | == Literal indexed ==
+ | Indexed name (idx = 26)
+ | content-encoding
+ 04 | Literal value (len = 4)
+ 677a 6970 | gzip
+ | - evict: date: Mon, 21 Oct
+ | 2013 20:13:21 GMT
+ | -> content-encoding: gzip
+ 77 | == Literal indexed ==
+ | Indexed name (idx = 55)
+ | set-cookie
+ 38 | Literal value (len = 56)
+ 666f 6f3d 4153 444a 4b48 514b 425a 584f | foo=ASDJKHQKBZXO
+ 5157 454f 5049 5541 5851 5745 4f49 553b | QWEOPIUAXQWEOIU;
+ 206d 6178 2d61 6765 3d33 3630 303b 2076 | max-age=3600; v
+ 6572 7369 6f6e 3d31 | ersion=1
+ | - evict: location:
+ | https://www.example.com
+ | - evict: :status: 307
+ | -> set-cookie: foo=ASDJKHQ
+ | KBZXOQWEOPIUAXQWEOIU; ma
+ | x-age=3600; version=1
+ )");
+ EXPECT_TRUE(DecodeBlock(hpack_block));
+ ASSERT_THAT(
+ header_entries_,
+ ElementsAreArray({
+ HpackHeaderEntry{HpackEntryType::kIndexedHeader, ":status", "200"},
+ HpackHeaderEntry{HpackEntryType::kIndexedHeader, "cache-control",
+ "private"},
+ HpackHeaderEntry{HpackEntryType::kIndexedLiteralHeader, "date",
+ "Mon, 21 Oct 2013 20:13:22 GMT"},
+ HpackHeaderEntry{HpackEntryType::kIndexedHeader, "location",
+ "https://www.example.com"},
+ HpackHeaderEntry{HpackEntryType::kIndexedLiteralHeader,
+ "content-encoding", "gzip"},
+ HpackHeaderEntry{
+ HpackEntryType::kIndexedLiteralHeader, "set-cookie",
+ "foo=ASDJKHQKBZXOQWEOPIUAXQWEOIU; max-age=3600; version=1"},
+ }));
+
+ // Dynamic Table (after decoding):
+ //
+ // [ 1] (s = 98) set-cookie: foo=ASDJKHQKBZXOQWEOPIUAXQWEOIU;
+ // max-age=3600; version=1
+ // [ 2] (s = 52) content-encoding: gzip
+ // [ 3] (s = 65) date: Mon, 21 Oct 2013 20:13:22 GMT
+ // Table size: 215
+ ASSERT_TRUE(VerifyDynamicTableContents(
+ {{"set-cookie",
+ "foo=ASDJKHQKBZXOQWEOPIUAXQWEOIU; max-age=3600; version=1"},
+ {"content-encoding", "gzip"},
+ {"date", "Mon, 21 Oct 2013 20:13:22 GMT"}}));
+ ASSERT_EQ(215u, current_header_table_size());
+}
+
+// Confirm that the table size can be changed, but at most twice.
+TEST_P(Http2HpackDecoderTest, ProcessesOptionalTableSizeUpdates) {
+ EXPECT_EQ(Http2SettingsInfo::DefaultHeaderTableSize(),
+ header_table_size_limit());
+ // One update allowed.
+ {
+ HpackBlockBuilder hbb;
+ hbb.AppendDynamicTableSizeUpdate(3000);
+ EXPECT_TRUE(DecodeBlock(hbb.buffer()));
+ EXPECT_EQ(3000u, header_table_size_limit());
+ EXPECT_EQ(0u, current_header_table_size());
+ EXPECT_TRUE(header_entries_.empty());
+ }
+ // Two updates allowed.
+ {
+ HpackBlockBuilder hbb;
+ hbb.AppendDynamicTableSizeUpdate(2000);
+ hbb.AppendDynamicTableSizeUpdate(2500);
+ EXPECT_TRUE(DecodeBlock(hbb.buffer()));
+ EXPECT_EQ(2500u, header_table_size_limit());
+ EXPECT_EQ(0u, current_header_table_size());
+ EXPECT_TRUE(header_entries_.empty());
+ }
+ // A third update in the same HPACK block is rejected, so the final
+ // size is 1000, not 500.
+ {
+ HpackBlockBuilder hbb;
+ hbb.AppendDynamicTableSizeUpdate(1500);
+ hbb.AppendDynamicTableSizeUpdate(1000);
+ hbb.AppendDynamicTableSizeUpdate(500);
+ EXPECT_FALSE(DecodeBlock(hbb.buffer()));
+ EXPECT_EQ(1u, error_messages_.size());
+ EXPECT_THAT(error_messages_[0], HasSubstr("size update not allowed"));
+ EXPECT_EQ(1000u, header_table_size_limit());
+ EXPECT_EQ(0u, current_header_table_size());
+ EXPECT_TRUE(header_entries_.empty());
+ }
+ // An error has been detected, so calls to Http2HpackDecoder::DecodeFragment
+ // should return immediately.
+ DecodeBuffer db("\x80");
+ EXPECT_FALSE(decoder_.DecodeFragment(&db));
+ EXPECT_EQ(0u, db.Offset());
+ EXPECT_EQ(1u, error_messages_.size());
+}
+
+// Confirm that the table size can be changed when required, but at most twice.
+TEST_P(Http2HpackDecoderTest, ProcessesRequiredTableSizeUpdate) {
+ // One update required, two allowed, one provided, followed by a header.
+ decoder_.ApplyHeaderTableSizeSetting(1024);
+ decoder_.ApplyHeaderTableSizeSetting(2048);
+ EXPECT_EQ(Http2SettingsInfo::DefaultHeaderTableSize(),
+ header_table_size_limit());
+ {
+ HpackBlockBuilder hbb;
+ hbb.AppendDynamicTableSizeUpdate(1024);
+ hbb.AppendIndexedHeader(4); // :path: /
+ EXPECT_TRUE(DecodeBlock(hbb.buffer()));
+ EXPECT_THAT(header_entries_,
+ ElementsAreArray({HpackHeaderEntry{
+ HpackEntryType::kIndexedHeader, ":path", "/"}}));
+ EXPECT_EQ(1024u, header_table_size_limit());
+ EXPECT_EQ(0u, current_header_table_size());
+ }
+ // One update required, two allowed, two provided, followed by a header.
+ decoder_.ApplyHeaderTableSizeSetting(1000);
+ decoder_.ApplyHeaderTableSizeSetting(1500);
+ {
+ HpackBlockBuilder hbb;
+ hbb.AppendDynamicTableSizeUpdate(500);
+ hbb.AppendDynamicTableSizeUpdate(1250);
+ hbb.AppendIndexedHeader(5); // :path: /index.html
+ EXPECT_TRUE(DecodeBlock(hbb.buffer()));
+ EXPECT_THAT(header_entries_,
+ ElementsAreArray({HpackHeaderEntry{
+ HpackEntryType::kIndexedHeader, ":path", "/index.html"}}));
+ EXPECT_EQ(1250u, header_table_size_limit());
+ EXPECT_EQ(0u, current_header_table_size());
+ }
+ // One update required, two allowed, three provided, followed by a header.
+ // The third update is rejected, so the final size is 1000, not 500.
+ decoder_.ApplyHeaderTableSizeSetting(500);
+ decoder_.ApplyHeaderTableSizeSetting(1000);
+ {
+ HpackBlockBuilder hbb;
+ hbb.AppendDynamicTableSizeUpdate(200);
+ hbb.AppendDynamicTableSizeUpdate(700);
+ hbb.AppendDynamicTableSizeUpdate(900);
+ hbb.AppendIndexedHeader(5); // Not decoded.
+ EXPECT_FALSE(DecodeBlock(hbb.buffer()));
+ EXPECT_FALSE(saw_end_);
+ EXPECT_EQ(1u, error_messages_.size());
+ EXPECT_THAT(error_messages_[0], HasSubstr("size update not allowed"));
+ EXPECT_EQ(700u, header_table_size_limit());
+ EXPECT_EQ(0u, current_header_table_size());
+ EXPECT_TRUE(header_entries_.empty());
+ }
+ // Now that an error has been detected, StartDecodingBlock should return
+ // false.
+ EXPECT_FALSE(decoder_.StartDecodingBlock());
+}
+
+// Confirm that required size updates are validated.
+TEST_P(Http2HpackDecoderTest, InvalidRequiredSizeUpdate) {
+ // Require a size update, but provide one that isn't small enough (must be
+ // zero or one, in this case).
+ decoder_.ApplyHeaderTableSizeSetting(1);
+ decoder_.ApplyHeaderTableSizeSetting(1024);
+ HpackBlockBuilder hbb;
+ hbb.AppendDynamicTableSizeUpdate(2);
+ EXPECT_TRUE(decoder_.StartDecodingBlock());
+ DecodeBuffer db(hbb.buffer());
+ EXPECT_FALSE(decoder_.DecodeFragment(&db));
+ EXPECT_FALSE(saw_end_);
+ EXPECT_EQ(1u, error_messages_.size());
+ EXPECT_THAT(error_messages_[0], HasSubstr("above low water mark"));
+ EXPECT_EQ(Http2SettingsInfo::DefaultHeaderTableSize(),
+ header_table_size_limit());
+}
+
+// Confirm that required size updates are indeed required before the end.
+TEST_P(Http2HpackDecoderTest, RequiredTableSizeChangeBeforeEnd) {
+ decoder_.ApplyHeaderTableSizeSetting(1024);
+ EXPECT_FALSE(DecodeBlock(""));
+ EXPECT_EQ(1u, error_messages_.size());
+ EXPECT_THAT(error_messages_[0],
+ HasSubstr("Missing dynamic table size update"));
+ EXPECT_FALSE(saw_end_);
+}
+
+// Confirm that required size updates are indeed required before an
+// indexed header.
+TEST_P(Http2HpackDecoderTest, RequiredTableSizeChangeBeforeIndexedHeader) {
+ decoder_.ApplyHeaderTableSizeSetting(1024);
+ HpackBlockBuilder hbb;
+ hbb.AppendIndexedHeader(1);
+ EXPECT_FALSE(DecodeBlock(hbb.buffer()));
+ EXPECT_EQ(1u, error_messages_.size());
+ EXPECT_THAT(error_messages_[0],
+ HasSubstr("Missing dynamic table size update"));
+ EXPECT_FALSE(saw_end_);
+ EXPECT_TRUE(header_entries_.empty());
+}
+
+// Confirm that required size updates are indeed required before an indexed
+// header name.
+// TODO(jamessynge): Move some of these to hpack_decoder_state_test.cc.
+TEST_P(Http2HpackDecoderTest, RequiredTableSizeChangeBeforeIndexedHeaderName) {
+ decoder_.ApplyHeaderTableSizeSetting(1024);
+ HpackBlockBuilder hbb;
+ hbb.AppendNameIndexAndLiteralValue(HpackEntryType::kIndexedLiteralHeader, 2,
+ false, "PUT");
+ EXPECT_FALSE(DecodeBlock(hbb.buffer()));
+ EXPECT_EQ(1u, error_messages_.size());
+ EXPECT_THAT(error_messages_[0],
+ HasSubstr("Missing dynamic table size update"));
+ EXPECT_FALSE(saw_end_);
+ EXPECT_TRUE(header_entries_.empty());
+}
+
+// Confirm that required size updates are indeed required before a literal
+// header name.
+TEST_P(Http2HpackDecoderTest, RequiredTableSizeChangeBeforeLiteralName) {
+ decoder_.ApplyHeaderTableSizeSetting(1024);
+ HpackBlockBuilder hbb;
+ hbb.AppendLiteralNameAndValue(HpackEntryType::kNeverIndexedLiteralHeader,
+ false, "name", false, "some data.");
+ EXPECT_FALSE(DecodeBlock(hbb.buffer()));
+ EXPECT_EQ(1u, error_messages_.size());
+ EXPECT_THAT(error_messages_[0],
+ HasSubstr("Missing dynamic table size update"));
+ EXPECT_FALSE(saw_end_);
+ EXPECT_TRUE(header_entries_.empty());
+}
+
+// Confirm that an excessively long varint is detected, in this case an
+// index of 127, but with lots of additional high-order 0 bits provided,
+// too many to be allowed.
+TEST_P(Http2HpackDecoderTest, InvalidIndexedHeaderVarint) {
+ EXPECT_TRUE(decoder_.StartDecodingBlock());
+ DecodeBuffer db("\xff\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x00");
+ EXPECT_FALSE(decoder_.DecodeFragment(&db));
+ EXPECT_TRUE(decoder_.error_detected());
+ EXPECT_FALSE(saw_end_);
+ EXPECT_EQ(1u, error_messages_.size());
+ EXPECT_THAT(error_messages_[0], HasSubstr("malformed"));
+ EXPECT_TRUE(header_entries_.empty());
+ // Now that an error has been detected, EndDecodingBlock should not succeed.
+ EXPECT_FALSE(decoder_.EndDecodingBlock());
+}
+
+// Confirm that an invalid index into the tables is detected, in this case an
+// index of 0.
+TEST_P(Http2HpackDecoderTest, InvalidIndex) {
+ EXPECT_TRUE(decoder_.StartDecodingBlock());
+ DecodeBuffer db("\x80");
+ EXPECT_FALSE(decoder_.DecodeFragment(&db));
+ EXPECT_TRUE(decoder_.error_detected());
+ EXPECT_FALSE(saw_end_);
+ EXPECT_EQ(1u, error_messages_.size());
+ EXPECT_THAT(error_messages_[0], HasSubstr("Invalid index"));
+ EXPECT_TRUE(header_entries_.empty());
+ // Now that an error has been detected, EndDecodingBlock should not succeed.
+ EXPECT_FALSE(decoder_.EndDecodingBlock());
+}
+
+// Confirm that EndDecodingBlock detects a truncated HPACK block.
+TEST_P(Http2HpackDecoderTest, TruncatedBlock) {
+ HpackBlockBuilder hbb;
+ hbb.AppendDynamicTableSizeUpdate(3000);
+ EXPECT_EQ(3u, hbb.size());
+ hbb.AppendDynamicTableSizeUpdate(4000);
+ EXPECT_EQ(6u, hbb.size());
+ // Decodes this block if the whole thing is provided.
+ EXPECT_TRUE(DecodeBlock(hbb.buffer()));
+ EXPECT_EQ(4000u, header_table_size_limit());
+ // Multiple times even.
+ EXPECT_TRUE(DecodeBlock(hbb.buffer()));
+ EXPECT_EQ(4000u, header_table_size_limit());
+ // But not if the block is truncated.
+ EXPECT_FALSE(DecodeBlock(hbb.buffer().substr(0, hbb.size() - 1)));
+ EXPECT_FALSE(saw_end_);
+ EXPECT_EQ(1u, error_messages_.size());
+ EXPECT_THAT(error_messages_[0], HasSubstr("truncated"));
+ // The first update was decoded.
+ EXPECT_EQ(3000u, header_table_size_limit());
+ EXPECT_EQ(0u, current_header_table_size());
+ EXPECT_TRUE(header_entries_.empty());
+}
+
+// Confirm that an oversized string is detected, ending decoding.
+TEST_P(Http2HpackDecoderTest, OversizeStringDetected) {
+ HpackBlockBuilder hbb;
+ hbb.AppendLiteralNameAndValue(HpackEntryType::kNeverIndexedLiteralHeader,
+ false, "name", false, "some data.");
+ hbb.AppendLiteralNameAndValue(HpackEntryType::kUnindexedLiteralHeader, false,
+ "name2", false, "longer data");
+
+ // Normally able to decode this block.
+ EXPECT_TRUE(DecodeBlock(hbb.buffer()));
+ EXPECT_THAT(header_entries_,
+ ElementsAreArray(
+ {HpackHeaderEntry{HpackEntryType::kNeverIndexedLiteralHeader,
+ "name", "some data."},
+ HpackHeaderEntry{HpackEntryType::kUnindexedLiteralHeader,
+ "name2", "longer data"}}));
+
+ // But not if the maximum size of strings is less than the longest string.
+ decoder_.set_max_string_size_bytes(10);
+ EXPECT_FALSE(DecodeBlock(hbb.buffer()));
+ EXPECT_THAT(
+ header_entries_,
+ ElementsAreArray({HpackHeaderEntry{
+ HpackEntryType::kNeverIndexedLiteralHeader, "name", "some data."}}));
+ EXPECT_FALSE(saw_end_);
+ EXPECT_EQ(1u, error_messages_.size());
+ EXPECT_THAT(error_messages_[0], HasSubstr("too long"));
+}
+
+} // namespace
+} // namespace test
+} // namespace net
diff --git a/chromium/net/http2/hpack/hpack_static_table_entries.inc b/chromium/net/http2/hpack/hpack_static_table_entries.inc
new file mode 100644
index 00000000000..3d2f1087bf6
--- /dev/null
+++ b/chromium/net/http2/hpack/hpack_static_table_entries.inc
@@ -0,0 +1,69 @@
+// Copyright 2016 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.
+
+// This file is designed to be included by C/C++ files which need the contents
+// of the HPACK static table. It may be included more than once if necessary.
+// See http://httpwg.org/specs/rfc7541.html#static.table.definition
+
+STATIC_TABLE_ENTRY(":authority", "", 1u);
+STATIC_TABLE_ENTRY(":method", "GET", 2u);
+STATIC_TABLE_ENTRY(":method", "POST", 3u);
+STATIC_TABLE_ENTRY(":path", "/", 4u);
+STATIC_TABLE_ENTRY(":path", "/index.html", 5u);
+STATIC_TABLE_ENTRY(":scheme", "http", 6u);
+STATIC_TABLE_ENTRY(":scheme", "https", 7u);
+STATIC_TABLE_ENTRY(":status", "200", 8u);
+STATIC_TABLE_ENTRY(":status", "204", 9u);
+STATIC_TABLE_ENTRY(":status", "206", 10u);
+STATIC_TABLE_ENTRY(":status", "304", 11u);
+STATIC_TABLE_ENTRY(":status", "400", 12u);
+STATIC_TABLE_ENTRY(":status", "404", 13u);
+STATIC_TABLE_ENTRY(":status", "500", 14u);
+STATIC_TABLE_ENTRY("accept-charset", "", 15u);
+STATIC_TABLE_ENTRY("accept-encoding", "gzip, deflate", 16u);
+STATIC_TABLE_ENTRY("accept-language", "", 17u);
+STATIC_TABLE_ENTRY("accept-ranges", "", 18u);
+STATIC_TABLE_ENTRY("accept", "", 19u);
+STATIC_TABLE_ENTRY("access-control-allow-origin", "", 20u);
+STATIC_TABLE_ENTRY("age", "", 21u);
+STATIC_TABLE_ENTRY("allow", "", 22u);
+STATIC_TABLE_ENTRY("authorization", "", 23u);
+STATIC_TABLE_ENTRY("cache-control", "", 24u);
+STATIC_TABLE_ENTRY("content-disposition", "", 25u);
+STATIC_TABLE_ENTRY("content-encoding", "", 26u);
+STATIC_TABLE_ENTRY("content-language", "", 27u);
+STATIC_TABLE_ENTRY("content-length", "", 28u);
+STATIC_TABLE_ENTRY("content-location", "", 29u);
+STATIC_TABLE_ENTRY("content-range", "", 30u);
+STATIC_TABLE_ENTRY("content-type", "", 31u);
+STATIC_TABLE_ENTRY("cookie", "", 32u);
+STATIC_TABLE_ENTRY("date", "", 33u);
+STATIC_TABLE_ENTRY("etag", "", 34u);
+STATIC_TABLE_ENTRY("expect", "", 35u);
+STATIC_TABLE_ENTRY("expires", "", 36u);
+STATIC_TABLE_ENTRY("from", "", 37u);
+STATIC_TABLE_ENTRY("host", "", 38u);
+STATIC_TABLE_ENTRY("if-match", "", 39u);
+STATIC_TABLE_ENTRY("if-modified-since", "", 40u);
+STATIC_TABLE_ENTRY("if-none-match", "", 41u);
+STATIC_TABLE_ENTRY("if-range", "", 42u);
+STATIC_TABLE_ENTRY("if-unmodified-since", "", 43u);
+STATIC_TABLE_ENTRY("last-modified", "", 44u);
+STATIC_TABLE_ENTRY("link", "", 45u);
+STATIC_TABLE_ENTRY("location", "", 46u);
+STATIC_TABLE_ENTRY("max-forwards", "", 47u);
+STATIC_TABLE_ENTRY("proxy-authenticate", "", 48u);
+STATIC_TABLE_ENTRY("proxy-authorization", "", 49u);
+STATIC_TABLE_ENTRY("range", "", 50u);
+STATIC_TABLE_ENTRY("referer", "", 51u);
+STATIC_TABLE_ENTRY("refresh", "", 52u);
+STATIC_TABLE_ENTRY("retry-after", "", 53u);
+STATIC_TABLE_ENTRY("server", "", 54u);
+STATIC_TABLE_ENTRY("set-cookie", "", 55u);
+STATIC_TABLE_ENTRY("strict-transport-security", "", 56u);
+STATIC_TABLE_ENTRY("transfer-encoding", "", 57u);
+STATIC_TABLE_ENTRY("user-agent", "", 58u);
+STATIC_TABLE_ENTRY("vary", "", 59u);
+STATIC_TABLE_ENTRY("via", "", 60u);
+STATIC_TABLE_ENTRY("www-authenticate", "", 61u);
diff --git a/chromium/net/http2/hpack/hpack_string.cc b/chromium/net/http2/hpack/hpack_string.cc
new file mode 100644
index 00000000000..b4b820b843a
--- /dev/null
+++ b/chromium/net/http2/hpack/hpack_string.cc
@@ -0,0 +1,78 @@
+// Copyright 2016 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.
+
+#include "net/http2/hpack/hpack_string.h"
+
+#include <utility>
+
+#include "base/logging.h"
+
+using base::StringPiece;
+using std::string;
+
+namespace net {
+
+HpackString::HpackString(const char* data) : str_(data) {}
+HpackString::HpackString(StringPiece str) : str_(str.as_string()) {}
+HpackString::HpackString(string str) : str_(std::move(str)) {}
+HpackString::HpackString(const HpackString& other) : str_(other.str_) {}
+HpackString::~HpackString() {}
+
+HpackString::operator StringPiece() const {
+ return str_;
+}
+
+bool HpackString::operator==(const HpackString& other) const {
+ return str_ == other.str_;
+}
+bool HpackString::operator==(StringPiece str) const {
+ return str == str_;
+}
+
+bool operator==(StringPiece a, const HpackString& b) {
+ return b == a;
+}
+bool operator!=(StringPiece a, const HpackString& b) {
+ return !(b == a);
+}
+bool operator!=(const HpackString& a, const HpackString& b) {
+ return !(a == b);
+}
+bool operator!=(const HpackString& a, StringPiece b) {
+ return !(a == b);
+}
+std::ostream& operator<<(std::ostream& out, const HpackString& v) {
+ return out << v.ToString();
+}
+
+HpackStringPair::HpackStringPair(const HpackString& name,
+ const HpackString& value)
+ : name(name), value(value) {
+ DVLOG(3) << DebugString() << " ctor";
+}
+
+HpackStringPair::HpackStringPair(StringPiece name, StringPiece value)
+ : name(name), value(value) {
+ DVLOG(3) << DebugString() << " ctor";
+}
+
+HpackStringPair::~HpackStringPair() {
+ DVLOG(3) << DebugString() << " dtor";
+}
+
+string HpackStringPair::DebugString() const {
+ string debug_string("HpackStringPair(name=");
+ debug_string.append(name.ToString());
+ debug_string.append(", value=");
+ debug_string.append(value.ToString());
+ debug_string.append(")");
+ return debug_string;
+}
+
+std::ostream& operator<<(std::ostream& os, const HpackStringPair& p) {
+ os << p.DebugString();
+ return os;
+}
+
+} // namespace net
diff --git a/chromium/net/http2/hpack/hpack_string.h b/chromium/net/http2/hpack/hpack_string.h
new file mode 100644
index 00000000000..5a7b693e4a4
--- /dev/null
+++ b/chromium/net/http2/hpack/hpack_string.h
@@ -0,0 +1,76 @@
+// Copyright 2016 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.
+
+#ifndef NET_HTTP2_HPACK_HPACK_STRING_H_
+#define NET_HTTP2_HPACK_HPACK_STRING_H_
+
+// HpackString is currently a very simple container for a string, but allows us
+// to relatively easily experiment with alternate string storage mechanisms for
+// handling strings to be encoded with HPACK, or decoded from HPACK, such as
+// a ref-counted string.
+
+#include <stddef.h>
+
+#include <iosfwd>
+#include <string>
+
+#include "base/strings/string_piece.h"
+#include "net/base/net_export.h"
+
+namespace net {
+
+class NET_EXPORT_PRIVATE HpackString {
+ public:
+ explicit HpackString(const char* data);
+ explicit HpackString(base::StringPiece str);
+ explicit HpackString(std::string str);
+ HpackString(const HpackString& other);
+
+ // Not sure yet whether this move ctor is required/sensible.
+ HpackString(HpackString&& other) = default;
+
+ HpackString& operator=(const HpackString& other) = default;
+
+ ~HpackString();
+
+ size_t size() const { return str_.size(); }
+ const std::string& ToString() const { return str_; }
+ operator base::StringPiece() const;
+
+ bool operator==(const HpackString& other) const;
+
+ bool operator==(base::StringPiece str) const;
+
+ private:
+ std::string str_;
+};
+
+NET_EXPORT_PRIVATE bool operator==(base::StringPiece a, const HpackString& b);
+NET_EXPORT_PRIVATE bool operator!=(base::StringPiece a, const HpackString& b);
+NET_EXPORT_PRIVATE bool operator!=(const HpackString& a, const HpackString& b);
+NET_EXPORT_PRIVATE bool operator!=(const HpackString& a, base::StringPiece b);
+NET_EXPORT_PRIVATE std::ostream& operator<<(std::ostream& out,
+ const HpackString& v);
+
+struct NET_EXPORT_PRIVATE HpackStringPair {
+ HpackStringPair(const HpackString& name, const HpackString& value);
+ HpackStringPair(base::StringPiece name, base::StringPiece value);
+ ~HpackStringPair();
+
+ // Returns the size of a header entry with this name and value, per the RFC:
+ // http://httpwg.org/specs/rfc7541.html#calculating.table.size
+ size_t size() const { return 32 + name.size() + value.size(); }
+
+ std::string DebugString() const;
+
+ HpackString name;
+ HpackString value;
+};
+
+NET_EXPORT_PRIVATE std::ostream& operator<<(std::ostream& os,
+ const HpackStringPair& p);
+
+} // namespace net
+
+#endif // NET_HTTP2_HPACK_HPACK_STRING_H_
diff --git a/chromium/net/http2/hpack/hpack_string_test.cc b/chromium/net/http2/hpack/hpack_string_test.cc
new file mode 100644
index 00000000000..b2181f8a239
--- /dev/null
+++ b/chromium/net/http2/hpack/hpack_string_test.cc
@@ -0,0 +1,150 @@
+// Copyright 2016 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.
+
+#include "net/http2/hpack/hpack_string.h"
+
+// Tests of HpackString.
+
+#include <utility>
+
+#include "base/logging.h"
+#include "net/http2/tools/failure.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+using ::testing::AssertionFailure;
+using ::testing::AssertionResult;
+using ::testing::AssertionSuccess;
+using base::StringPiece;
+using std::string;
+
+namespace net {
+namespace test {
+namespace {
+
+const char kStr0[] = "s0: Some string to be copied into another string.";
+const char kStr1[] = "S1 - some string to be copied into yet another string.";
+
+class HpackStringTest : public ::testing::Test {
+ protected:
+ AssertionResult VerifyNotEqual(HpackString* actual,
+ const string& not_expected_str) {
+ const char* not_expected_ptr = not_expected_str.c_str();
+ StringPiece not_expected_sp(not_expected_str);
+
+ VERIFY_NE(*actual, not_expected_ptr);
+ VERIFY_NE(*actual, not_expected_sp);
+ VERIFY_NE(*actual, not_expected_str);
+ VERIFY_NE(static_cast<StringPiece>(*actual), not_expected_sp);
+
+ if (!(not_expected_ptr != *actual)) {
+ return AssertionFailure();
+ }
+ if (!(not_expected_sp != *actual)) {
+ return AssertionFailure();
+ }
+ if (!(not_expected_str != *actual)) {
+ return AssertionFailure();
+ }
+ if (!(not_expected_sp != static_cast<StringPiece>(*actual))) {
+ return AssertionFailure();
+ }
+
+ return AssertionSuccess();
+ }
+
+ AssertionResult VerifyEqual(HpackString* actual, const string& expected_str) {
+ VERIFY_EQ(actual->size(), expected_str.size());
+
+ const char* expected_ptr = expected_str.c_str();
+ const StringPiece expected_sp(expected_str);
+
+ VERIFY_EQ(*actual, expected_ptr);
+ VERIFY_EQ(*actual, expected_sp);
+ VERIFY_EQ(*actual, expected_str);
+ VERIFY_EQ(static_cast<StringPiece>(*actual), expected_sp);
+
+ if (!(expected_sp == *actual)) {
+ return AssertionFailure();
+ }
+ if (!(expected_ptr == *actual)) {
+ return AssertionFailure();
+ }
+ if (!(expected_str == *actual)) {
+ return AssertionFailure();
+ }
+ if (!(expected_sp == static_cast<StringPiece>(*actual))) {
+ return AssertionFailure();
+ }
+
+ return AssertionSuccess();
+ }
+};
+
+TEST_F(HpackStringTest, CharArrayConstructor) {
+ HpackString hs0(kStr0);
+ EXPECT_TRUE(VerifyEqual(&hs0, kStr0));
+ EXPECT_TRUE(VerifyNotEqual(&hs0, kStr1));
+
+ HpackString hs1(kStr1);
+ EXPECT_TRUE(VerifyEqual(&hs1, kStr1));
+ EXPECT_TRUE(VerifyNotEqual(&hs1, kStr0));
+}
+
+TEST_F(HpackStringTest, StringPieceConstructor) {
+ StringPiece sp0(kStr0);
+ HpackString hs0(sp0);
+ EXPECT_TRUE(VerifyEqual(&hs0, kStr0));
+ EXPECT_TRUE(VerifyNotEqual(&hs0, kStr1));
+
+ StringPiece sp1(kStr1);
+ HpackString hs1(sp1);
+ EXPECT_TRUE(VerifyEqual(&hs1, kStr1));
+ EXPECT_TRUE(VerifyNotEqual(&hs1, kStr0));
+}
+
+TEST_F(HpackStringTest, MoveStringConstructor) {
+ string str0(kStr0);
+ HpackString hs0(str0);
+ EXPECT_TRUE(VerifyEqual(&hs0, kStr0));
+ EXPECT_TRUE(VerifyNotEqual(&hs0, kStr1));
+
+ string str1(kStr1);
+ HpackString hs1(str1);
+ EXPECT_TRUE(VerifyEqual(&hs1, kStr1));
+ EXPECT_TRUE(VerifyNotEqual(&hs1, kStr0));
+}
+
+TEST_F(HpackStringTest, CopyConstructor) {
+ StringPiece sp0(kStr0);
+ HpackString hs0(sp0);
+ HpackString hs1(hs0);
+ EXPECT_EQ(hs0, hs1);
+
+ EXPECT_TRUE(VerifyEqual(&hs0, kStr0));
+ EXPECT_TRUE(VerifyEqual(&hs1, kStr0));
+
+ EXPECT_TRUE(VerifyNotEqual(&hs0, kStr1));
+ EXPECT_TRUE(VerifyNotEqual(&hs1, kStr1));
+}
+
+TEST_F(HpackStringTest, MoveConstructor) {
+ StringPiece sp0(kStr0);
+ HpackString hs0(sp0);
+ EXPECT_TRUE(VerifyEqual(&hs0, kStr0));
+ EXPECT_TRUE(VerifyNotEqual(&hs0, ""));
+
+ HpackString hs1(std::move(hs0));
+ EXPECT_NE(hs0, hs1);
+
+ EXPECT_TRUE(VerifyEqual(&hs1, kStr0));
+ EXPECT_TRUE(VerifyEqual(&hs0, ""));
+ EXPECT_TRUE(VerifyNotEqual(&hs1, ""));
+
+ LOG(INFO) << hs0;
+ LOG(INFO) << hs1;
+}
+
+} // namespace
+} // namespace test
+} // namespace net
diff --git a/chromium/net/http2/hpack/http2_hpack_constants.cc b/chromium/net/http2/hpack/http2_hpack_constants.cc
new file mode 100644
index 00000000000..bc0ee9e9f7a
--- /dev/null
+++ b/chromium/net/http2/hpack/http2_hpack_constants.cc
@@ -0,0 +1,33 @@
+// Copyright 2016 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.
+
+#include "net/http2/hpack/http2_hpack_constants.h"
+
+#include <sstream>
+
+namespace net {
+
+std::string HpackEntryTypeToString(HpackEntryType v) {
+ switch (v) {
+ case HpackEntryType::kIndexedHeader:
+ return "kIndexedHeader";
+ case HpackEntryType::kDynamicTableSizeUpdate:
+ return "kDynamicTableSizeUpdate";
+ case HpackEntryType::kIndexedLiteralHeader:
+ return "kIndexedLiteralHeader";
+ case HpackEntryType::kUnindexedLiteralHeader:
+ return "kUnindexedLiteralHeader";
+ case HpackEntryType::kNeverIndexedLiteralHeader:
+ return "kNeverIndexedLiteralHeader";
+ }
+ std::stringstream ss;
+ ss << "UnknownHpackEntryType(" << static_cast<int>(v) << ")";
+ return ss.str();
+}
+
+std::ostream& operator<<(std::ostream& out, HpackEntryType v) {
+ return out << HpackEntryTypeToString(v);
+}
+
+} // namespace net
diff --git a/chromium/net/http2/hpack/http2_hpack_constants.h b/chromium/net/http2/hpack/http2_hpack_constants.h
new file mode 100644
index 00000000000..b9883a01cf7
--- /dev/null
+++ b/chromium/net/http2/hpack/http2_hpack_constants.h
@@ -0,0 +1,61 @@
+// Copyright 2016 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.
+
+#ifndef NET_HTTP2_HPACK_HTTP2_HPACK_CONSTANTS_H_
+#define NET_HTTP2_HPACK_HTTP2_HPACK_CONSTANTS_H_
+
+// Enum HpackEntryType identifies the 5 basic types of HPACK Block Entries.
+//
+// See the spec for details:
+// https://http2.github.io/http2-spec/compression.html#rfc.section.6
+
+#include <ostream>
+#include <string>
+
+#include "net/base/net_export.h"
+
+namespace net {
+
+enum class HpackEntryType {
+ // Entry is an index into the static or dynamic table. Decoding it has no
+ // effect on the dynamic table.
+ kIndexedHeader,
+
+ // The entry contains a literal value. The name may be either a literal or a
+ // reference to an entry in the static or dynamic table.
+ // The entry is added to the dynamic table after decoding.
+ kIndexedLiteralHeader,
+
+ // The entry contains a literal value. The name may be either a literal or a
+ // reference to an entry in the static or dynamic table.
+ // The entry is not added to the dynamic table after decoding, but a proxy
+ // may choose to insert the entry into its dynamic table when forwarding
+ // to another endpoint.
+ kUnindexedLiteralHeader,
+
+ // The entry contains a literal value. The name may be either a literal or a
+ // reference to an entry in the static or dynamic table.
+ // The entry is not added to the dynamic table after decoding, and a proxy
+ // must NOT insert the entry into its dynamic table when forwarding to another
+ // endpoint.
+ kNeverIndexedLiteralHeader,
+
+ // Entry conveys the size limit of the dynamic table of the encoder to
+ // the decoder. May be used to flush the table by sending a zero and then
+ // resetting the size back up to the maximum that the encoder will use
+ // (within the limits of SETTINGS_HEADER_TABLE_SIZE sent by the
+ // decoder to the encoder, with the default of 4096 assumed).
+ kDynamicTableSizeUpdate,
+};
+
+// Returns the name of the enum member.
+NET_EXPORT_PRIVATE std::string HpackEntryTypeToString(HpackEntryType v);
+
+// Inserts the name of the enum member into |out|.
+NET_EXPORT_PRIVATE std::ostream& operator<<(std::ostream& out,
+ HpackEntryType v);
+
+} // namespace net
+
+#endif // NET_HTTP2_HPACK_HTTP2_HPACK_CONSTANTS_H_
diff --git a/chromium/net/http2/hpack/http2_hpack_constants_test.cc b/chromium/net/http2/hpack/http2_hpack_constants_test.cc
new file mode 100644
index 00000000000..217b64df93f
--- /dev/null
+++ b/chromium/net/http2/hpack/http2_hpack_constants_test.cc
@@ -0,0 +1,34 @@
+// Copyright 2016 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.
+
+#include "net/http2/hpack/http2_hpack_constants.h"
+
+#include "base/logging.h"
+#include "testing/gmock/include/gmock/gmock.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace net {
+namespace test {
+namespace {
+
+class HpackEntryTypeTest : public testing::Test {};
+
+TEST(HpackEntryTypeTest, HpackEntryTypeToString) {
+ EXPECT_EQ("kIndexedHeader",
+ HpackEntryTypeToString(HpackEntryType::kIndexedHeader));
+ EXPECT_EQ("kDynamicTableSizeUpdate",
+ HpackEntryTypeToString(HpackEntryType::kDynamicTableSizeUpdate));
+ EXPECT_EQ("kIndexedLiteralHeader",
+ HpackEntryTypeToString(HpackEntryType::kIndexedLiteralHeader));
+ EXPECT_EQ("kUnindexedLiteralHeader",
+ HpackEntryTypeToString(HpackEntryType::kUnindexedLiteralHeader));
+ EXPECT_EQ("kNeverIndexedLiteralHeader",
+ HpackEntryTypeToString(HpackEntryType::kNeverIndexedLiteralHeader));
+ EXPECT_EQ("UnknownHpackEntryType(12321)",
+ HpackEntryTypeToString(static_cast<HpackEntryType>(12321)));
+}
+
+} // namespace
+} // namespace test
+} // namespace net
diff --git a/chromium/net/http2/hpack/huffman/http2_hpack_huffman_decoder.cc b/chromium/net/http2/hpack/huffman/http2_hpack_huffman_decoder.cc
new file mode 100644
index 00000000000..45c32c08b22
--- /dev/null
+++ b/chromium/net/http2/hpack/huffman/http2_hpack_huffman_decoder.cc
@@ -0,0 +1,542 @@
+// Copyright 2016 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.
+
+#include "net/http2/hpack/huffman/http2_hpack_huffman_decoder.h"
+
+#include <bitset>
+#include <limits>
+
+#include "base/logging.h"
+
+using base::StringPiece;
+using std::string;
+
+// Terminology:
+//
+// Symbol - a plain text (unencoded) character (uint8), or the End-of-String
+// (EOS) symbol, 256.
+//
+// Code - the sequence of bits used to encode a symbol, varying in length from
+// 5 bits for the most common symbols (e.g. '0', '1', and 'a'), to
+// 30 bits for the least common (e.g. the EOS symbol).
+// For those symbols whose codes have the same length, their code values
+// are sorted such that the lower symbol value has a lower code value.
+//
+// Canonical - a symbol's cardinal value when sorted first by code length, and
+// then by symbol value. For example, canonical 0 is for ASCII '0'
+// (uint8 value 0x30), which is the first of the symbols whose code
+// is 5 bits long, and the last canonical is EOS, which is the last
+// of the symbols whose code is 30 bits long.
+
+// TODO(jamessynge): Remove use of binary literals, that is a C++ 14 feature.
+
+namespace net {
+namespace {
+
+// HuffmanCode is used to store the codes associated with symbols (a pattern of
+// from 5 to 30 bits).
+typedef uint32_t HuffmanCode;
+
+// HuffmanCodeBitCount is used to store a count of bits in a code.
+typedef uint16_t HuffmanCodeBitCount;
+
+// HuffmanCodeBitSet is used for producing a string version of a code because
+// std::bitset logs nicely.
+typedef std::bitset<32> HuffmanCodeBitSet;
+typedef std::bitset<64> HuffmanAccumulatorBitSet;
+
+static constexpr HuffmanCodeBitCount kMinCodeBitCount = 5;
+static constexpr HuffmanCodeBitCount kMaxCodeBitCount = 30;
+static constexpr HuffmanCodeBitCount kHuffmanCodeBitCount =
+ std::numeric_limits<HuffmanCode>::digits;
+
+static_assert(std::numeric_limits<HuffmanCode>::digits >= kMaxCodeBitCount,
+ "HuffmanCode isn't big enough.");
+
+static_assert(std::numeric_limits<HuffmanAccumulator>::digits >=
+ kMaxCodeBitCount,
+ "HuffmanAccumulator isn't big enough.");
+
+static constexpr HuffmanAccumulatorBitCount kHuffmanAccumulatorBitCount =
+ std::numeric_limits<HuffmanAccumulator>::digits;
+static constexpr HuffmanAccumulatorBitCount kExtraAccumulatorBitCount =
+ kHuffmanAccumulatorBitCount - kHuffmanCodeBitCount;
+
+// PrefixInfo holds info about a group of codes that are all of the same length.
+struct PrefixInfo {
+ // Given the leading bits (32 in this case) of the encoded string, and that
+ // they start with a code of length |code_length|, return the corresponding
+ // canonical for that leading code.
+ uint32_t DecodeToCanonical(HuffmanCode bits) const {
+ // What is the position of the canonical symbol being decoded within
+ // the canonical symbols of |length|?
+ HuffmanCode ordinal_in_length =
+ ((bits - first_code) >> (kHuffmanCodeBitCount - code_length));
+
+ // Combined with |canonical| to produce the position of the canonical symbol
+ // being decoded within all of the canonical symbols.
+ return first_canonical + ordinal_in_length;
+ }
+
+ const HuffmanCode first_code; // First code of this length, left justified in
+ // the field (i.e. the first bit of the code is
+ // the high-order bit).
+ const uint16_t code_length; // Length of the prefix code |base|.
+ const uint16_t first_canonical; // First canonical symbol of this length.
+};
+
+inline std::ostream& operator<<(std::ostream& out, const PrefixInfo& v) {
+ return out << "{first_code: " << HuffmanCodeBitSet(v.first_code)
+ << ", code_length: " << v.code_length
+ << ", first_canonical: " << v.first_canonical << "}";
+}
+
+// Given |value|, a sequence of the leading bits remaining to be decoded,
+// figure out which group of canonicals (by code length) that value starts
+// with. This function was generated.
+PrefixInfo PrefixToInfo(HuffmanCode value) {
+ if (value < 0b10111000000000000000000000000000) {
+ if (value < 0b01010000000000000000000000000000) {
+ return {0b00000000000000000000000000000000, 5, 0};
+ } else {
+ return {0b01010000000000000000000000000000, 6, 10};
+ }
+ } else {
+ if (value < 0b11111110000000000000000000000000) {
+ if (value < 0b11111000000000000000000000000000) {
+ return {0b10111000000000000000000000000000, 7, 36};
+ } else {
+ return {0b11111000000000000000000000000000, 8, 68};
+ }
+ } else {
+ if (value < 0b11111111110000000000000000000000) {
+ if (value < 0b11111111101000000000000000000000) {
+ if (value < 0b11111111010000000000000000000000) {
+ return {0b11111110000000000000000000000000, 10, 74};
+ } else {
+ return {0b11111111010000000000000000000000, 11, 79};
+ }
+ } else {
+ return {0b11111111101000000000000000000000, 12, 82};
+ }
+ } else {
+ if (value < 0b11111111111111100000000000000000) {
+ if (value < 0b11111111111110000000000000000000) {
+ if (value < 0b11111111111100000000000000000000) {
+ return {0b11111111110000000000000000000000, 13, 84};
+ } else {
+ return {0b11111111111100000000000000000000, 14, 90};
+ }
+ } else {
+ return {0b11111111111110000000000000000000, 15, 92};
+ }
+ } else {
+ if (value < 0b11111111111111110100100000000000) {
+ if (value < 0b11111111111111101110000000000000) {
+ if (value < 0b11111111111111100110000000000000) {
+ return {0b11111111111111100000000000000000, 19, 95};
+ } else {
+ return {0b11111111111111100110000000000000, 20, 98};
+ }
+ } else {
+ return {0b11111111111111101110000000000000, 21, 106};
+ }
+ } else {
+ if (value < 0b11111111111111111110101000000000) {
+ if (value < 0b11111111111111111011000000000000) {
+ return {0b11111111111111110100100000000000, 22, 119};
+ } else {
+ return {0b11111111111111111011000000000000, 23, 145};
+ }
+ } else {
+ if (value < 0b11111111111111111111101111000000) {
+ if (value < 0b11111111111111111111100000000000) {
+ if (value < 0b11111111111111111111011000000000) {
+ return {0b11111111111111111110101000000000, 24, 174};
+ } else {
+ return {0b11111111111111111111011000000000, 25, 186};
+ }
+ } else {
+ return {0b11111111111111111111100000000000, 26, 190};
+ }
+ } else {
+ if (value < 0b11111111111111111111111111110000) {
+ if (value < 0b11111111111111111111111000100000) {
+ return {0b11111111111111111111101111000000, 27, 205};
+ } else {
+ return {0b11111111111111111111111000100000, 28, 224};
+ }
+ } else {
+ return {0b11111111111111111111111111110000, 30, 253};
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+}
+
+// Mapping from canonical symbol (0 to 255) to actual symbol.
+// clang-format off
+constexpr unsigned char kCanonicalToSymbol[] = {
+ '0', '1', '2', 'a', 'c', 'e', 'i', 'o',
+ 's', 't', 0x20, '%', '-', '.', '/', '3',
+ '4', '5', '6', '7', '8', '9', '=', 'A',
+ '_', 'b', 'd', 'f', 'g', 'h', 'l', 'm',
+ 'n', 'p', 'r', 'u', ':', 'B', 'C', 'D',
+ 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L',
+ 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T',
+ 'U', 'V', 'W', 'Y', 'j', 'k', 'q', 'v',
+ 'w', 'x', 'y', 'z', '&', '*', ',', ';',
+ 'X', 'Z', '!', '\"', '(', ')', '?', '\'',
+ '+', '|', '#', '>', 0x00, '$', '@', '[',
+ ']', '~', '^', '}', '<', '`', '{', '\\',
+ 0xc3, 0xd0, 0x80, 0x82, 0x83, 0xa2, 0xb8, 0xc2,
+ 0xe0, 0xe2, 0x99, 0xa1, 0xa7, 0xac, 0xb0, 0xb1,
+ 0xb3, 0xd1, 0xd8, 0xd9, 0xe3, 0xe5, 0xe6, 0x81,
+ 0x84, 0x85, 0x86, 0x88, 0x92, 0x9a, 0x9c, 0xa0,
+ 0xa3, 0xa4, 0xa9, 0xaa, 0xad, 0xb2, 0xb5, 0xb9,
+ 0xba, 0xbb, 0xbd, 0xbe, 0xc4, 0xc6, 0xe4, 0xe8,
+ 0xe9, 0x01, 0x87, 0x89, 0x8a, 0x8b, 0x8c, 0x8d,
+ 0x8f, 0x93, 0x95, 0x96, 0x97, 0x98, 0x9b, 0x9d,
+ 0x9e, 0xa5, 0xa6, 0xa8, 0xae, 0xaf, 0xb4, 0xb6,
+ 0xb7, 0xbc, 0xbf, 0xc5, 0xe7, 0xef, 0x09, 0x8e,
+ 0x90, 0x91, 0x94, 0x9f, 0xab, 0xce, 0xd7, 0xe1,
+ 0xec, 0xed, 0xc7, 0xcf, 0xea, 0xeb, 0xc0, 0xc1,
+ 0xc8, 0xc9, 0xca, 0xcd, 0xd2, 0xd5, 0xda, 0xdb,
+ 0xee, 0xf0, 0xf2, 0xf3, 0xff, 0xcb, 0xcc, 0xd3,
+ 0xd4, 0xd6, 0xdd, 0xde, 0xdf, 0xf1, 0xf4, 0xf5,
+ 0xf6, 0xf7, 0xf8, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe,
+ 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x0b,
+ 0x0c, 0x0e, 0x0f, 0x10, 0x11, 0x12, 0x13, 0x14,
+ 0x15, 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d,
+ 0x1e, 0x1f, 0x7f, 0xdc, 0xf9, 0x0a, 0x0d, 0x16,
+};
+// clang-format on
+
+constexpr size_t kShortCodeTableSize = 124;
+struct ShortCodeInfo {
+ uint8_t symbol;
+ uint8_t length;
+} kShortCodeTable[kShortCodeTableSize] = {
+ {0x30, 5}, // Match: 0b0000000, Symbol: 0
+ {0x30, 5}, // Match: 0b0000001, Symbol: 0
+ {0x30, 5}, // Match: 0b0000010, Symbol: 0
+ {0x30, 5}, // Match: 0b0000011, Symbol: 0
+ {0x31, 5}, // Match: 0b0000100, Symbol: 1
+ {0x31, 5}, // Match: 0b0000101, Symbol: 1
+ {0x31, 5}, // Match: 0b0000110, Symbol: 1
+ {0x31, 5}, // Match: 0b0000111, Symbol: 1
+ {0x32, 5}, // Match: 0b0001000, Symbol: 2
+ {0x32, 5}, // Match: 0b0001001, Symbol: 2
+ {0x32, 5}, // Match: 0b0001010, Symbol: 2
+ {0x32, 5}, // Match: 0b0001011, Symbol: 2
+ {0x61, 5}, // Match: 0b0001100, Symbol: a
+ {0x61, 5}, // Match: 0b0001101, Symbol: a
+ {0x61, 5}, // Match: 0b0001110, Symbol: a
+ {0x61, 5}, // Match: 0b0001111, Symbol: a
+ {0x63, 5}, // Match: 0b0010000, Symbol: c
+ {0x63, 5}, // Match: 0b0010001, Symbol: c
+ {0x63, 5}, // Match: 0b0010010, Symbol: c
+ {0x63, 5}, // Match: 0b0010011, Symbol: c
+ {0x65, 5}, // Match: 0b0010100, Symbol: e
+ {0x65, 5}, // Match: 0b0010101, Symbol: e
+ {0x65, 5}, // Match: 0b0010110, Symbol: e
+ {0x65, 5}, // Match: 0b0010111, Symbol: e
+ {0x69, 5}, // Match: 0b0011000, Symbol: i
+ {0x69, 5}, // Match: 0b0011001, Symbol: i
+ {0x69, 5}, // Match: 0b0011010, Symbol: i
+ {0x69, 5}, // Match: 0b0011011, Symbol: i
+ {0x6f, 5}, // Match: 0b0011100, Symbol: o
+ {0x6f, 5}, // Match: 0b0011101, Symbol: o
+ {0x6f, 5}, // Match: 0b0011110, Symbol: o
+ {0x6f, 5}, // Match: 0b0011111, Symbol: o
+ {0x73, 5}, // Match: 0b0100000, Symbol: s
+ {0x73, 5}, // Match: 0b0100001, Symbol: s
+ {0x73, 5}, // Match: 0b0100010, Symbol: s
+ {0x73, 5}, // Match: 0b0100011, Symbol: s
+ {0x74, 5}, // Match: 0b0100100, Symbol: t
+ {0x74, 5}, // Match: 0b0100101, Symbol: t
+ {0x74, 5}, // Match: 0b0100110, Symbol: t
+ {0x74, 5}, // Match: 0b0100111, Symbol: t
+ {0x20, 6}, // Match: 0b0101000, Symbol: (space)
+ {0x20, 6}, // Match: 0b0101001, Symbol: (space)
+ {0x25, 6}, // Match: 0b0101010, Symbol: %
+ {0x25, 6}, // Match: 0b0101011, Symbol: %
+ {0x2d, 6}, // Match: 0b0101100, Symbol: -
+ {0x2d, 6}, // Match: 0b0101101, Symbol: -
+ {0x2e, 6}, // Match: 0b0101110, Symbol: .
+ {0x2e, 6}, // Match: 0b0101111, Symbol: .
+ {0x2f, 6}, // Match: 0b0110000, Symbol: /
+ {0x2f, 6}, // Match: 0b0110001, Symbol: /
+ {0x33, 6}, // Match: 0b0110010, Symbol: 3
+ {0x33, 6}, // Match: 0b0110011, Symbol: 3
+ {0x34, 6}, // Match: 0b0110100, Symbol: 4
+ {0x34, 6}, // Match: 0b0110101, Symbol: 4
+ {0x35, 6}, // Match: 0b0110110, Symbol: 5
+ {0x35, 6}, // Match: 0b0110111, Symbol: 5
+ {0x36, 6}, // Match: 0b0111000, Symbol: 6
+ {0x36, 6}, // Match: 0b0111001, Symbol: 6
+ {0x37, 6}, // Match: 0b0111010, Symbol: 7
+ {0x37, 6}, // Match: 0b0111011, Symbol: 7
+ {0x38, 6}, // Match: 0b0111100, Symbol: 8
+ {0x38, 6}, // Match: 0b0111101, Symbol: 8
+ {0x39, 6}, // Match: 0b0111110, Symbol: 9
+ {0x39, 6}, // Match: 0b0111111, Symbol: 9
+ {0x3d, 6}, // Match: 0b1000000, Symbol: =
+ {0x3d, 6}, // Match: 0b1000001, Symbol: =
+ {0x41, 6}, // Match: 0b1000010, Symbol: A
+ {0x41, 6}, // Match: 0b1000011, Symbol: A
+ {0x5f, 6}, // Match: 0b1000100, Symbol: _
+ {0x5f, 6}, // Match: 0b1000101, Symbol: _
+ {0x62, 6}, // Match: 0b1000110, Symbol: b
+ {0x62, 6}, // Match: 0b1000111, Symbol: b
+ {0x64, 6}, // Match: 0b1001000, Symbol: d
+ {0x64, 6}, // Match: 0b1001001, Symbol: d
+ {0x66, 6}, // Match: 0b1001010, Symbol: f
+ {0x66, 6}, // Match: 0b1001011, Symbol: f
+ {0x67, 6}, // Match: 0b1001100, Symbol: g
+ {0x67, 6}, // Match: 0b1001101, Symbol: g
+ {0x68, 6}, // Match: 0b1001110, Symbol: h
+ {0x68, 6}, // Match: 0b1001111, Symbol: h
+ {0x6c, 6}, // Match: 0b1010000, Symbol: l
+ {0x6c, 6}, // Match: 0b1010001, Symbol: l
+ {0x6d, 6}, // Match: 0b1010010, Symbol: m
+ {0x6d, 6}, // Match: 0b1010011, Symbol: m
+ {0x6e, 6}, // Match: 0b1010100, Symbol: n
+ {0x6e, 6}, // Match: 0b1010101, Symbol: n
+ {0x70, 6}, // Match: 0b1010110, Symbol: p
+ {0x70, 6}, // Match: 0b1010111, Symbol: p
+ {0x72, 6}, // Match: 0b1011000, Symbol: r
+ {0x72, 6}, // Match: 0b1011001, Symbol: r
+ {0x75, 6}, // Match: 0b1011010, Symbol: u
+ {0x75, 6}, // Match: 0b1011011, Symbol: u
+ {0x3a, 7}, // Match: 0b1011100, Symbol: :
+ {0x42, 7}, // Match: 0b1011101, Symbol: B
+ {0x43, 7}, // Match: 0b1011110, Symbol: C
+ {0x44, 7}, // Match: 0b1011111, Symbol: D
+ {0x45, 7}, // Match: 0b1100000, Symbol: E
+ {0x46, 7}, // Match: 0b1100001, Symbol: F
+ {0x47, 7}, // Match: 0b1100010, Symbol: G
+ {0x48, 7}, // Match: 0b1100011, Symbol: H
+ {0x49, 7}, // Match: 0b1100100, Symbol: I
+ {0x4a, 7}, // Match: 0b1100101, Symbol: J
+ {0x4b, 7}, // Match: 0b1100110, Symbol: K
+ {0x4c, 7}, // Match: 0b1100111, Symbol: L
+ {0x4d, 7}, // Match: 0b1101000, Symbol: M
+ {0x4e, 7}, // Match: 0b1101001, Symbol: N
+ {0x4f, 7}, // Match: 0b1101010, Symbol: O
+ {0x50, 7}, // Match: 0b1101011, Symbol: P
+ {0x51, 7}, // Match: 0b1101100, Symbol: Q
+ {0x52, 7}, // Match: 0b1101101, Symbol: R
+ {0x53, 7}, // Match: 0b1101110, Symbol: S
+ {0x54, 7}, // Match: 0b1101111, Symbol: T
+ {0x55, 7}, // Match: 0b1110000, Symbol: U
+ {0x56, 7}, // Match: 0b1110001, Symbol: V
+ {0x57, 7}, // Match: 0b1110010, Symbol: W
+ {0x59, 7}, // Match: 0b1110011, Symbol: Y
+ {0x6a, 7}, // Match: 0b1110100, Symbol: j
+ {0x6b, 7}, // Match: 0b1110101, Symbol: k
+ {0x71, 7}, // Match: 0b1110110, Symbol: q
+ {0x76, 7}, // Match: 0b1110111, Symbol: v
+ {0x77, 7}, // Match: 0b1111000, Symbol: w
+ {0x78, 7}, // Match: 0b1111001, Symbol: x
+ {0x79, 7}, // Match: 0b1111010, Symbol: y
+ {0x7a, 7}, // Match: 0b1111011, Symbol: z
+};
+
+} // namespace
+
+HuffmanBitBuffer::HuffmanBitBuffer() {
+ Reset();
+}
+
+void HuffmanBitBuffer::Reset() {
+ accumulator_ = 0;
+ count_ = 0;
+}
+
+size_t HuffmanBitBuffer::AppendBytes(StringPiece input) {
+ HuffmanAccumulatorBitCount free_cnt = free_count();
+ size_t bytes_available = input.size();
+ if (free_cnt < 8 || bytes_available == 0) {
+ return 0;
+ }
+
+ // Top up |accumulator_| until there isn't room for a whole byte.
+ size_t bytes_used = 0;
+ auto ptr = reinterpret_cast<const uint8_t*>(input.data());
+ do {
+ auto b = static_cast<HuffmanAccumulator>(*ptr++);
+ free_cnt -= 8;
+ accumulator_ |= (b << free_cnt);
+ ++bytes_used;
+ } while (free_cnt >= 8 && bytes_used < bytes_available);
+ count_ += (bytes_used * 8);
+ return bytes_used;
+}
+
+HuffmanAccumulatorBitCount HuffmanBitBuffer::free_count() const {
+ return kHuffmanAccumulatorBitCount - count_;
+}
+
+void HuffmanBitBuffer::ConsumeBits(HuffmanAccumulatorBitCount code_length) {
+ DCHECK_LE(code_length, count_);
+ accumulator_ <<= code_length;
+ count_ -= code_length;
+}
+
+bool HuffmanBitBuffer::InputProperlyTerminated() const {
+ auto cnt = count();
+ if (cnt < 8) {
+ if (cnt == 0) {
+ return true;
+ }
+ HuffmanAccumulator expected = ~(~HuffmanAccumulator() >> cnt);
+ // We expect all the bits below the high order |cnt| bits of accumulator_
+ // to be cleared as we perform left shift operations while decoding.
+ DCHECK_EQ(accumulator_ & ~expected, 0u)
+ << "\n expected: " << HuffmanAccumulatorBitSet(expected) << "\n "
+ << *this;
+ return accumulator_ == expected;
+ }
+ return false;
+}
+
+string HuffmanBitBuffer::DebugString() const {
+ std::stringstream ss;
+ ss << "{accumulator: " << HuffmanAccumulatorBitSet(accumulator_)
+ << "; count: " << count_ << "}";
+ return ss.str();
+}
+
+HpackHuffmanDecoder::HpackHuffmanDecoder() {}
+
+HpackHuffmanDecoder::~HpackHuffmanDecoder() {}
+
+bool HpackHuffmanDecoder::Decode(StringPiece input, string* output) {
+ return DecodeShortCodesFirst(input, output);
+}
+
+// "Legacy" decoder, used until cl/129771019 submitted, which added
+// DecodeShortCodesFirst() as primary decoder method.
+// TODO(jamessynge): Remove this once satisfied that there is no going back.
+bool HpackHuffmanDecoder::DecodeWithIfTreeAndStruct(StringPiece input,
+ string* output) {
+ DVLOG(1) << "HpackHuffmanDecoder::DecodeWithIfTreeAndStruct";
+
+ // Fill bit_buffer_ from input.
+ input.remove_prefix(bit_buffer_.AppendBytes(input));
+
+ while (true) {
+ DVLOG(3) << "Enter Decode Loop, bit_buffer_: " << bit_buffer_;
+
+ HuffmanCode code_prefix = bit_buffer_.value() >> kExtraAccumulatorBitCount;
+ DVLOG(3) << "code_prefix: " << HuffmanCodeBitSet(code_prefix);
+
+ PrefixInfo prefix_info = PrefixToInfo(code_prefix);
+ DVLOG(3) << "prefix_info: " << prefix_info;
+ DCHECK_LE(kMinCodeBitCount, prefix_info.code_length);
+ DCHECK_LE(prefix_info.code_length, kMaxCodeBitCount);
+
+ if (prefix_info.code_length <= bit_buffer_.count()) {
+ // We have enough bits for one code.
+ uint32_t canonical = prefix_info.DecodeToCanonical(code_prefix);
+ if (canonical < 256) {
+ // Valid code.
+ char c = kCanonicalToSymbol[canonical];
+ output->push_back(c);
+ bit_buffer_.ConsumeBits(prefix_info.code_length);
+ continue;
+ }
+ // Encoder is not supposed to explicity encode the EOS symbol.
+ DLOG(ERROR) << "EOS explicitly encoded!\n " << bit_buffer_ << "\n "
+ << prefix_info;
+ return false;
+ }
+ // bit_buffer_ doesn't have enough bits in it to decode the next symbol.
+ // Append to it as many bytes as are available AND fit.
+ size_t byte_count = bit_buffer_.AppendBytes(input);
+ if (byte_count == 0) {
+ DCHECK_EQ(input.size(), 0u);
+ return true;
+ }
+ input.remove_prefix(byte_count);
+ }
+}
+
+bool HpackHuffmanDecoder::DecodeShortCodesFirst(StringPiece input,
+ string* output) {
+ DVLOG(1) << "HpackHuffmanDecoder::DecodeShortCodesFirst";
+
+ // Fill bit_buffer_ from input.
+ input.remove_prefix(bit_buffer_.AppendBytes(input));
+
+ while (true) {
+ DVLOG(3) << "Enter Decode Loop, bit_buffer_: " << bit_buffer_;
+ if (bit_buffer_.count() >= 7) {
+ // Get high 7 bits of the bit buffer, see if that contains a complete
+ // code of 5, 6 or 7 bits.
+ uint8_t short_code =
+ bit_buffer_.value() >> (kHuffmanAccumulatorBitCount - 7);
+ DCHECK_LT(short_code, 128);
+ if (short_code < kShortCodeTableSize) {
+ ShortCodeInfo info = kShortCodeTable[short_code];
+ bit_buffer_.ConsumeBits(info.length);
+ output->push_back(static_cast<char>(info.symbol));
+ continue;
+ }
+ // The code is more than 7 bits long. Use PrefixToInfo, etc. to decode
+ // longer codes.
+ } else {
+ // We may have (mostly) drained bit_buffer_. If we can top it up, try
+ // using the table decoder above.
+ size_t byte_count = bit_buffer_.AppendBytes(input);
+ if (byte_count > 0) {
+ input.remove_prefix(byte_count);
+ continue;
+ }
+ }
+
+ HuffmanCode code_prefix = bit_buffer_.value() >> kExtraAccumulatorBitCount;
+ DVLOG(3) << "code_prefix: " << HuffmanCodeBitSet(code_prefix);
+
+ PrefixInfo prefix_info = PrefixToInfo(code_prefix);
+ DVLOG(3) << "prefix_info: " << prefix_info;
+ DCHECK_LE(kMinCodeBitCount, prefix_info.code_length);
+ DCHECK_LE(prefix_info.code_length, kMaxCodeBitCount);
+
+ if (prefix_info.code_length <= bit_buffer_.count()) {
+ // We have enough bits for one code.
+ uint32_t canonical = prefix_info.DecodeToCanonical(code_prefix);
+ if (canonical < 256) {
+ // Valid code.
+ char c = kCanonicalToSymbol[canonical];
+ output->push_back(c);
+ bit_buffer_.ConsumeBits(prefix_info.code_length);
+ continue;
+ }
+ // Encoder is not supposed to explicity encode the EOS symbol.
+ DLOG(ERROR) << "EOS explicitly encoded!\n " << bit_buffer_ << "\n "
+ << prefix_info;
+ return false;
+ }
+ // bit_buffer_ doesn't have enough bits in it to decode the next symbol.
+ // Append to it as many bytes as are available AND fit.
+ size_t byte_count = bit_buffer_.AppendBytes(input);
+ if (byte_count == 0) {
+ DCHECK_EQ(input.size(), 0u);
+ return true;
+ }
+ input.remove_prefix(byte_count);
+ }
+}
+
+string HpackHuffmanDecoder::DebugString() const {
+ return bit_buffer_.DebugString();
+}
+
+} // namespace net
diff --git a/chromium/net/http2/hpack/huffman/http2_hpack_huffman_decoder.h b/chromium/net/http2/hpack/huffman/http2_hpack_huffman_decoder.h
new file mode 100644
index 00000000000..7b8edd10c63
--- /dev/null
+++ b/chromium/net/http2/hpack/huffman/http2_hpack_huffman_decoder.h
@@ -0,0 +1,149 @@
+// Copyright 2016 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.
+
+#ifndef NET_HTTP2_HPACK_HUFFMAN_HTTP2_HPACK_HUFFMAN_DECODER_H_
+#define NET_HTTP2_HPACK_HUFFMAN_HTTP2_HPACK_HUFFMAN_DECODER_H_
+
+// HpackHuffmanDecoder is an incremental decoder of strings that have been
+// encoded using the Huffman table defined in the HPACK spec.
+// By incremental, we mean that the HpackHuffmanDecoder::Decode method does
+// not require the entire string to be provided, and can instead decode the
+// string as fragments of it become available (e.g. as HPACK block fragments
+// are received for decoding by HpackEntryDecoder).
+
+#include <stddef.h>
+
+#include <iosfwd>
+#include <string>
+
+#include "base/strings/string_piece.h"
+#include "net/base/net_export.h"
+
+namespace net {
+
+// HuffmanAccumulator is used to store bits during decoding, e.g. next N bits
+// that have not yet been decoded, but have been extracted from the encoded
+// string). An advantage of using a uint64 for the accumulator
+// is that it has room for the bits of the longest code plus the bits of a full
+// byte; that means that when adding more bits to the accumulator, it can always
+// be done in whole bytes. For example, if we currently have 26 bits in the
+// accumulator, and need more to decode the current symbol, we can add a whole
+// byte to the accumulator, and not have to do juggling with adding 6 bits (to
+// reach 30), and then keep track of the last two bits we've not been able to
+// add to the accumulator.
+typedef uint64_t HuffmanAccumulator;
+typedef size_t HuffmanAccumulatorBitCount;
+
+// HuffmanBitBuffer stores the leading edge of bits to be decoded. The high
+// order bit of accumulator_ is the next bit to be decoded.
+class NET_EXPORT_PRIVATE HuffmanBitBuffer {
+ public:
+ HuffmanBitBuffer();
+
+ // Prepare for decoding a new Huffman encoded string.
+ void Reset();
+
+ // Add as many whole bytes to the accumulator (accumulator_) as possible,
+ // returning the number of bytes added.
+ size_t AppendBytes(base::StringPiece input);
+
+ // Get the bits of the accumulator.
+ HuffmanAccumulator value() const { return accumulator_; }
+
+ // Number of bits of the encoded string that are in the accumulator
+ // (accumulator_).
+ HuffmanAccumulatorBitCount count() const { return count_; }
+
+ // Are there no bits in the accumulator?
+ bool IsEmpty() const { return count_ == 0; }
+
+ // Number of additional bits that can be added to the accumulator.
+ HuffmanAccumulatorBitCount free_count() const;
+
+ // Consume the leading |code_length| bits of the accumulator.
+ void ConsumeBits(HuffmanAccumulatorBitCount code_length);
+
+ // Are the contents valid for the end of a Huffman encoded string? The RFC
+ // states that EOS (end-of-string) symbol must not be explicitly encoded in
+ // the bit stream, but any unused bits in the final byte must be set to the
+ // prefix of the EOS symbol, which is all 1 bits. So there can be at most 7
+ // such bits.
+ // Returns true if the bit buffer is empty, or contains at most 7 bits, all
+ // of them 1. Otherwise returns false.
+ bool InputProperlyTerminated() const;
+
+ std::string DebugString() const;
+
+ private:
+ HuffmanAccumulator accumulator_;
+ HuffmanAccumulatorBitCount count_;
+};
+
+inline std::ostream& operator<<(std::ostream& out, const HuffmanBitBuffer& v) {
+ return out << v.DebugString();
+}
+
+class NET_EXPORT_PRIVATE HpackHuffmanDecoder {
+ public:
+ HpackHuffmanDecoder();
+ ~HpackHuffmanDecoder();
+
+ // Prepare for decoding a new Huffman encoded string.
+ void Reset() { bit_buffer_.Reset(); }
+
+ // Decode the portion of a HPACK Huffman encoded string that is in |input|,
+ // appending the decoded symbols into |*output|, stopping when more bits are
+ // needed to determine the next symbol, which/ means that the input has been
+ // drained, and also that the bit_buffer_ is empty or that the bits that are
+ // in it are not a whole symbol.
+ // If |input| is the start of a string, the caller must first call Reset.
+ // If |input| includes the end of the encoded string, the caller must call
+ // InputProperlyTerminated after Decode has returned true in order to
+ // determine if the encoded string was properly terminated.
+ // Returns false if something went wrong (e.g. the encoding contains the code
+ // EOS symbol). Otherwise returns true, in which case input has been fully
+ // decoded or buffered; in particular, if the low-order bit of the final byte
+ // of the input is not the last bit of an encoded symbol, then bit_buffer_
+ // will contain the leading bits of the code for that symbol, but not the
+ // final bits of that code.
+ // Note that output should be empty, but that it is not cleared by Decode().
+ bool Decode(base::StringPiece input, std::string* output);
+
+ // Is what remains in the bit_buffer_ valid at the end of an encoded string?
+ // Call after passing the the final portion of a Huffman string to Decode,
+ // and getting true as the result.
+ bool InputProperlyTerminated() const {
+ return bit_buffer_.InputProperlyTerminated();
+ }
+
+ bool IsEmptyForTest() const { return bit_buffer_.IsEmpty(); }
+
+ std::string DebugString() const;
+
+ //////////////////////////////////////////////////////////////////////////////
+ // Alternate implementations of Decode:
+
+ // As above, implemented using a tree of if statements to determine the code
+ // length, etc., which are returned as a tree. See PrefixToInfo. This is the
+ // original implementation, current as of 2016-8-8.
+ bool DecodeWithIfTreeAndStruct(base::StringPiece input, std::string* output);
+
+ // Based on DecodeWithIfTreeAndStruct, but adds an optimization for the common
+ // case of short codes (5, 6 or 7), which make up a large fraction of the
+ // frequency distribution on which the HPACK table was based.
+ // TODO(jamessynge): Be precise about that fraction.
+ bool DecodeShortCodesFirst(base::StringPiece input, std::string* output);
+
+ private:
+ HuffmanBitBuffer bit_buffer_;
+};
+
+inline std::ostream& operator<<(std::ostream& out,
+ const HpackHuffmanDecoder& v) {
+ return out << v.DebugString();
+}
+
+} // namespace net
+
+#endif // NET_HTTP2_HPACK_HUFFMAN_HTTP2_HPACK_HUFFMAN_DECODER_H_
diff --git a/chromium/net/http2/hpack/huffman/http2_hpack_huffman_decoder_test.cc b/chromium/net/http2/hpack/huffman/http2_hpack_huffman_decoder_test.cc
new file mode 100644
index 00000000000..3eb52adcf84
--- /dev/null
+++ b/chromium/net/http2/hpack/huffman/http2_hpack_huffman_decoder_test.cc
@@ -0,0 +1,284 @@
+// Copyright 2016 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.
+
+#include "net/http2/hpack/huffman/http2_hpack_huffman_decoder.h"
+
+// Tests of HpackHuffmanDecoder and HuffmanBitBuffer.
+
+#include <iostream>
+#include <string>
+
+#include "base/macros.h"
+#include "base/strings/string_piece.h"
+#include "net/http2/decoder/decode_buffer.h"
+#include "net/http2/decoder/decode_status.h"
+#include "net/http2/tools/failure.h"
+#include "net/http2/tools/random_decoder_test.h"
+#include "net/spdy/spdy_test_utils.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+using ::testing::AssertionResult;
+using ::testing::AssertionSuccess;
+using base::StringPiece;
+using std::string;
+
+namespace net {
+namespace test {
+namespace {
+
+TEST(HuffmanBitBufferTest, Reset) {
+ HuffmanBitBuffer bb;
+ EXPECT_TRUE(bb.IsEmpty());
+ EXPECT_TRUE(bb.InputProperlyTerminated());
+ EXPECT_EQ(bb.count(), 0u);
+ EXPECT_EQ(bb.free_count(), 64u);
+ EXPECT_EQ(bb.value(), 0u);
+}
+
+TEST(HuffmanBitBufferTest, AppendBytesAligned) {
+ string s;
+ s.push_back('\x11');
+ s.push_back('\x22');
+ s.push_back('\x33');
+ StringPiece sp(s);
+
+ HuffmanBitBuffer bb;
+ sp.remove_prefix(bb.AppendBytes(sp));
+ EXPECT_TRUE(sp.empty());
+ EXPECT_FALSE(bb.IsEmpty()) << bb;
+ EXPECT_FALSE(bb.InputProperlyTerminated());
+ EXPECT_EQ(bb.count(), 24u) << bb;
+ EXPECT_EQ(bb.free_count(), 40u) << bb;
+ EXPECT_EQ(bb.value(), HuffmanAccumulator(0x112233) << 40) << bb;
+
+ s.clear();
+ s.push_back('\x44');
+ sp = s;
+
+ sp.remove_prefix(bb.AppendBytes(sp));
+ EXPECT_TRUE(sp.empty());
+ EXPECT_EQ(bb.count(), 32u) << bb;
+ EXPECT_EQ(bb.free_count(), 32u) << bb;
+ EXPECT_EQ(bb.value(), HuffmanAccumulator(0x11223344) << 32) << bb;
+
+ s.clear();
+ s.push_back('\x55');
+ s.push_back('\x66');
+ s.push_back('\x77');
+ s.push_back('\x88');
+ s.push_back('\x99');
+ sp = s;
+
+ sp.remove_prefix(bb.AppendBytes(sp));
+ EXPECT_EQ(sp.size(), 1u);
+ EXPECT_EQ('\x99', sp[0]);
+ EXPECT_EQ(bb.count(), 64u) << bb;
+ EXPECT_EQ(bb.free_count(), 0u) << bb;
+ EXPECT_EQ(bb.value(), HuffmanAccumulator(0x1122334455667788LL)) << bb;
+
+ sp.remove_prefix(bb.AppendBytes(sp));
+ EXPECT_EQ(sp.size(), 1u);
+ EXPECT_EQ('\x99', sp[0]);
+ EXPECT_EQ(bb.count(), 64u) << bb;
+ EXPECT_EQ(bb.free_count(), 0u) << bb;
+ EXPECT_EQ(bb.value(), HuffmanAccumulator(0x1122334455667788LL)) << bb;
+}
+
+TEST(HuffmanBitBufferTest, ConsumeBits) {
+ string s;
+ s.push_back('\x11');
+ s.push_back('\x22');
+ s.push_back('\x33');
+ StringPiece sp(s);
+
+ HuffmanBitBuffer bb;
+ sp.remove_prefix(bb.AppendBytes(sp));
+ EXPECT_TRUE(sp.empty());
+
+ bb.ConsumeBits(1);
+ EXPECT_EQ(bb.count(), 23u) << bb;
+ EXPECT_EQ(bb.free_count(), 41u) << bb;
+ EXPECT_EQ(bb.value(), HuffmanAccumulator(0x112233) << 41) << bb;
+
+ bb.ConsumeBits(20);
+ EXPECT_EQ(bb.count(), 3u) << bb;
+ EXPECT_EQ(bb.free_count(), 61u) << bb;
+ EXPECT_EQ(bb.value(), HuffmanAccumulator(0x3) << 61) << bb;
+}
+
+TEST(HuffmanBitBufferTest, AppendBytesUnaligned) {
+ string s;
+ s.push_back('\x11');
+ s.push_back('\x22');
+ s.push_back('\x33');
+ s.push_back('\x44');
+ s.push_back('\x55');
+ s.push_back('\x66');
+ s.push_back('\x77');
+ s.push_back('\x88');
+ s.push_back('\x99');
+ s.push_back('\xaa');
+ s.push_back('\xbb');
+ s.push_back('\xcc');
+ s.push_back('\xdd');
+ StringPiece sp(s);
+
+ HuffmanBitBuffer bb;
+ sp.remove_prefix(bb.AppendBytes(sp));
+ EXPECT_EQ(sp.size(), 5u);
+ EXPECT_FALSE(bb.InputProperlyTerminated());
+
+ bb.ConsumeBits(15);
+ EXPECT_EQ(bb.count(), 49u) << bb;
+ EXPECT_EQ(bb.free_count(), 15u) << bb;
+
+ HuffmanAccumulator expected(0x1122334455667788);
+ expected <<= 15;
+ EXPECT_EQ(bb.value(), expected);
+
+ sp.remove_prefix(bb.AppendBytes(sp));
+ EXPECT_EQ(sp.size(), 4u);
+ EXPECT_EQ(bb.count(), 57u) << bb;
+ EXPECT_EQ(bb.free_count(), 7u) << bb;
+
+ expected |= (HuffmanAccumulator(0x99) << 7);
+ EXPECT_EQ(bb.value(), expected) << bb << std::hex
+ << "\n actual: " << bb.value()
+ << "\n expected: " << expected;
+}
+
+enum class DecoderChoice { IF_TREE, SHORT_CODE };
+
+class HpackHuffmanDecoderTest
+ : public RandomDecoderTest,
+ public ::testing::WithParamInterface<DecoderChoice> {
+ protected:
+ HpackHuffmanDecoderTest() {
+ // The decoder may return true, and its accumulator may be empty, at
+ // many boundaries while decoding, and yet the whole string hasn't
+ // been decoded.
+ stop_decode_on_done_ = false;
+ }
+
+ DecodeStatus StartDecoding(DecodeBuffer* b) override {
+ input_bytes_seen_ = 0;
+ output_buffer_.clear();
+ decoder_.Reset();
+ return ResumeDecoding(b);
+ }
+
+ DecodeStatus ResumeDecoding(DecodeBuffer* b) override {
+ input_bytes_seen_ += b->Remaining();
+ StringPiece sp(b->cursor(), b->Remaining());
+ if (DecodeFragment(sp)) {
+ b->AdvanceCursor(b->Remaining());
+ // Successfully decoded (or buffered) the bytes in StringPiece.
+ EXPECT_LE(input_bytes_seen_, input_bytes_expected_);
+ // Have we reached the end of the encoded string?
+ if (input_bytes_expected_ == input_bytes_seen_) {
+ if (decoder_.InputProperlyTerminated()) {
+ return DecodeStatus::kDecodeDone;
+ } else {
+ return DecodeStatus::kDecodeError;
+ }
+ }
+ return DecodeStatus::kDecodeInProgress;
+ }
+ return DecodeStatus::kDecodeError;
+ }
+
+ bool DecodeFragment(StringPiece sp) {
+ switch (GetParam()) {
+ case DecoderChoice::IF_TREE:
+ return decoder_.DecodeWithIfTreeAndStruct(sp, &output_buffer_);
+ case DecoderChoice::SHORT_CODE:
+ return decoder_.DecodeShortCodesFirst(sp, &output_buffer_);
+ }
+
+ NOTREACHED();
+ return false;
+ }
+
+ AssertionResult HuffmanDecodeAndValidateSeveralWays(
+ StringPiece encoded,
+ StringPiece expected_plain) {
+ input_bytes_expected_ = encoded.size();
+ NoArgValidator validator = [expected_plain, this]() -> AssertionResult {
+ VERIFY_EQ(output_buffer_.size(), expected_plain.size());
+ VERIFY_EQ(output_buffer_, expected_plain);
+ return AssertionSuccess();
+ };
+ DecodeBuffer db(encoded);
+ bool return_non_zero_on_first = false;
+ return DecodeAndValidateSeveralWays(&db, return_non_zero_on_first,
+ ValidateDoneAndEmpty(validator));
+ }
+
+ HpackHuffmanDecoder decoder_;
+ string output_buffer_;
+ size_t input_bytes_seen_;
+ size_t input_bytes_expected_;
+};
+INSTANTIATE_TEST_CASE_P(AllDecoders,
+ HpackHuffmanDecoderTest,
+ ::testing::Values(DecoderChoice::IF_TREE,
+ DecoderChoice::SHORT_CODE));
+
+TEST_P(HpackHuffmanDecoderTest, SpecRequestExamples) {
+ HpackHuffmanDecoder decoder;
+ string test_table[] = {
+ a2b_hex("f1e3c2e5f23a6ba0ab90f4ff"),
+ "www.example.com",
+ a2b_hex("a8eb10649cbf"),
+ "no-cache",
+ a2b_hex("25a849e95ba97d7f"),
+ "custom-key",
+ a2b_hex("25a849e95bb8e8b4bf"),
+ "custom-value",
+ };
+ for (size_t i = 0; i != arraysize(test_table); i += 2) {
+ const string& huffman_encoded(test_table[i]);
+ const string& plain_string(test_table[i + 1]);
+ string buffer;
+ decoder.Reset();
+ EXPECT_TRUE(decoder.Decode(huffman_encoded, &buffer)) << decoder;
+ EXPECT_TRUE(decoder.InputProperlyTerminated()) << decoder;
+ EXPECT_EQ(buffer, plain_string);
+ }
+}
+
+TEST_P(HpackHuffmanDecoderTest, SpecResponseExamples) {
+ HpackHuffmanDecoder decoder;
+ // clang-format off
+ string test_table[] = {
+ a2b_hex("6402"),
+ "302",
+ a2b_hex("aec3771a4b"),
+ "private",
+ a2b_hex("d07abe941054d444a8200595040b8166"
+ "e082a62d1bff"),
+ "Mon, 21 Oct 2013 20:13:21 GMT",
+ a2b_hex("9d29ad171863c78f0b97c8e9ae82ae43"
+ "d3"),
+ "https://www.example.com",
+ a2b_hex("94e7821dd7f2e6c7b335dfdfcd5b3960"
+ "d5af27087f3672c1ab270fb5291f9587"
+ "316065c003ed4ee5b1063d5007"),
+ "foo=ASDJKHQKBZXOQWEOPIUAXQWEOIU; max-age=3600; version=1",
+ };
+ // clang-format on
+ for (size_t i = 0; i != arraysize(test_table); i += 2) {
+ const string& huffman_encoded(test_table[i]);
+ const string& plain_string(test_table[i + 1]);
+ string buffer;
+ decoder.Reset();
+ EXPECT_TRUE(decoder.Decode(huffman_encoded, &buffer)) << decoder;
+ EXPECT_TRUE(decoder.InputProperlyTerminated()) << decoder;
+ EXPECT_EQ(buffer, plain_string);
+ }
+}
+
+} // namespace
+} // namespace test
+} // namespace net
diff --git a/chromium/net/http2/hpack/tools/hpack_block_builder.cc b/chromium/net/http2/hpack/tools/hpack_block_builder.cc
new file mode 100644
index 00000000000..49eba0d6719
--- /dev/null
+++ b/chromium/net/http2/hpack/tools/hpack_block_builder.cc
@@ -0,0 +1,84 @@
+// Copyright 2016 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.
+
+#include "net/http2/hpack/tools/hpack_block_builder.h"
+
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace net {
+namespace test {
+
+void HpackBlockBuilder::AppendHighBitsAndVarint(uint8_t high_bits,
+ uint8_t prefix_length,
+ uint64_t varint) {
+ EXPECT_LE(4, prefix_length);
+ EXPECT_LE(prefix_length, 7);
+
+ // prefix_mask defines the sequence of low-order bits of the first byte
+ // that encode the prefix of the value. It is also the marker in those bits
+ // of the first byte indicating that at least one extension byte is needed.
+ uint8_t prefix_mask = (1 << prefix_length) - 1;
+ EXPECT_EQ(0, high_bits & prefix_mask);
+
+ if (varint < prefix_mask) {
+ uint8_t b = high_bits | static_cast<uint8_t>(varint);
+ buffer_.push_back(static_cast<char>(b));
+ return;
+ }
+
+ // We need extension bytes.
+ buffer_.push_back(static_cast<char>(high_bits | prefix_mask));
+ varint -= prefix_mask;
+ while (varint >= 128) {
+ uint8_t b = static_cast<uint8_t>((varint % 128) + 128);
+ buffer_.push_back(static_cast<char>(b));
+ varint = varint / 128;
+ }
+ char c = static_cast<char>(varint);
+ buffer_.push_back(c);
+}
+
+void HpackBlockBuilder::AppendEntryTypeAndVarint(HpackEntryType entry_type,
+ uint64_t varint) {
+ uint8_t high_bits;
+ uint8_t prefix_length; // Bits of the varint prefix in the first byte.
+ switch (entry_type) {
+ case HpackEntryType::kIndexedHeader:
+ high_bits = 0x80;
+ prefix_length = 7;
+ break;
+ case HpackEntryType::kDynamicTableSizeUpdate:
+ high_bits = 0x20;
+ prefix_length = 5;
+ break;
+ case HpackEntryType::kIndexedLiteralHeader:
+ high_bits = 0x40;
+ prefix_length = 6;
+ break;
+ case HpackEntryType::kUnindexedLiteralHeader:
+ high_bits = 0x00;
+ prefix_length = 4;
+ break;
+ case HpackEntryType::kNeverIndexedLiteralHeader:
+ high_bits = 0x10;
+ prefix_length = 4;
+ break;
+ default:
+ NOTREACHED();
+ high_bits = 0;
+ prefix_length = 0;
+ }
+ AppendHighBitsAndVarint(high_bits, prefix_length, varint);
+}
+
+void HpackBlockBuilder::AppendString(bool is_huffman_encoded,
+ base::StringPiece str) {
+ uint8_t high_bits = is_huffman_encoded ? 0x80 : 0;
+ uint8_t prefix_length = 7;
+ AppendHighBitsAndVarint(high_bits, prefix_length, str.size());
+ str.AppendToString(&buffer_);
+}
+
+} // namespace test
+} // namespace net
diff --git a/chromium/net/http2/hpack/tools/hpack_block_builder.h b/chromium/net/http2/hpack/tools/hpack_block_builder.h
new file mode 100644
index 00000000000..06502b2a6bb
--- /dev/null
+++ b/chromium/net/http2/hpack/tools/hpack_block_builder.h
@@ -0,0 +1,95 @@
+// Copyright 2016 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.
+
+#ifndef NET_HTTP2_HPACK_TOOLS_HPACK_BLOCK_BUILDER_H_
+#define NET_HTTP2_HPACK_TOOLS_HPACK_BLOCK_BUILDER_H_
+
+// HpackBlockBuilder builds wire-format HPACK blocks (or fragments thereof)
+// from components.
+
+// Supports very large varints to enable tests to create HPACK blocks with
+// values that the decoder should reject. For now, this is only intended for
+// use in tests, and thus has EXPECT* in the code. If desired to use it in an
+// encoder, it will need optimization work, especially w.r.t memory mgmt, and
+// the EXPECT* will need to be removed or replaced with DCHECKs. And of course
+// the support for very large varints will not be needed in production code.
+
+#include <stddef.h>
+#include <string>
+
+#include "base/strings/string_piece.h"
+#include "net/http2/hpack/http2_hpack_constants.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace net {
+namespace test {
+
+class HpackBlockBuilder {
+ public:
+ explicit HpackBlockBuilder(base::StringPiece initial_contents) {
+ initial_contents.AppendToString(&buffer_);
+ }
+ HpackBlockBuilder() {}
+ ~HpackBlockBuilder() {}
+
+ size_t size() const { return buffer_.size(); }
+ const std::string& buffer() const { return buffer_; }
+
+ //----------------------------------------------------------------------------
+ // Methods for appending a valid HPACK entry.
+
+ void AppendIndexedHeader(uint64_t index) {
+ AppendEntryTypeAndVarint(HpackEntryType::kIndexedHeader, index);
+ }
+
+ void AppendDynamicTableSizeUpdate(uint64_t size) {
+ AppendEntryTypeAndVarint(HpackEntryType::kDynamicTableSizeUpdate, size);
+ }
+
+ void AppendNameIndexAndLiteralValue(HpackEntryType entry_type,
+ uint64_t name_index,
+ bool value_is_huffman_encoded,
+ base::StringPiece value) {
+ // name_index==0 would indicate that the entry includes a literal name.
+ // Call AppendLiteralNameAndValue in that case.
+ EXPECT_NE(0u, name_index);
+ AppendEntryTypeAndVarint(entry_type, name_index);
+ AppendString(value_is_huffman_encoded, value);
+ }
+
+ void AppendLiteralNameAndValue(HpackEntryType entry_type,
+ bool name_is_huffman_encoded,
+ base::StringPiece name,
+ bool value_is_huffman_encoded,
+ base::StringPiece value) {
+ AppendEntryTypeAndVarint(entry_type, 0);
+ AppendString(name_is_huffman_encoded, name);
+ AppendString(value_is_huffman_encoded, value);
+ }
+
+ //----------------------------------------------------------------------------
+ // Primitive methods that are not guaranteed to write a valid HPACK entry.
+
+ // Appends a varint, with the specified high_bits above the prefix of the
+ // varint.
+ void AppendHighBitsAndVarint(uint8_t high_bits,
+ uint8_t prefix_length,
+ uint64_t varint);
+
+ // Append the start of an HPACK entry for the specified type, with the
+ // specified varint.
+ void AppendEntryTypeAndVarint(HpackEntryType entry_type, uint64_t varint);
+
+ // Append a header string (i.e. a header name or value) in HPACK format.
+ // Does NOT perform Huffman encoding.
+ void AppendString(bool is_huffman_encoded, base::StringPiece str);
+
+ private:
+ std::string buffer_;
+};
+
+} // namespace test
+} // namespace net
+
+#endif // NET_HTTP2_HPACK_TOOLS_HPACK_BLOCK_BUILDER_H_
diff --git a/chromium/net/http2/hpack/tools/hpack_block_builder_test.cc b/chromium/net/http2/hpack/tools/hpack_block_builder_test.cc
new file mode 100644
index 00000000000..e59104982e1
--- /dev/null
+++ b/chromium/net/http2/hpack/tools/hpack_block_builder_test.cc
@@ -0,0 +1,169 @@
+// Copyright 2016 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.
+
+#include "net/http2/hpack/tools/hpack_block_builder.h"
+
+#include "net/spdy/spdy_test_utils.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+using base::StringPiece;
+
+namespace net {
+namespace test {
+namespace {
+const bool kUncompressed = false;
+const bool kCompressed = true;
+
+// TODO(jamessynge): Once static table code is checked in, switch to using
+// constants from there.
+const uint32_t kStaticTableMethodGET = 2;
+const uint32_t kStaticTablePathSlash = 4;
+const uint32_t kStaticTableSchemeHttp = 6;
+
+// Tests of encoding per the RFC. See:
+// http://httpwg.org/specs/rfc7541.html#header.field.representation.examples
+// The expected values have been copied from the RFC.
+TEST(HpackBlockBuilderTest, ExamplesFromSpecC2) {
+ {
+ HpackBlockBuilder b;
+ b.AppendLiteralNameAndValue(HpackEntryType::kIndexedLiteralHeader,
+ kUncompressed, "custom-key", kUncompressed,
+ "custom-header");
+ EXPECT_EQ(26u, b.size());
+
+ const char kExpected[] =
+ "\x40" // == Literal indexed ==
+ "\x0a" // Name length (10)
+ "custom-key" // Name
+ "\x0d" // Value length (13)
+ "custom-header"; // Value
+ EXPECT_EQ(kExpected, b.buffer());
+ }
+ {
+ HpackBlockBuilder b;
+ b.AppendNameIndexAndLiteralValue(HpackEntryType::kUnindexedLiteralHeader, 4,
+ kUncompressed, "/sample/path");
+ EXPECT_EQ(14u, b.size());
+
+ const char kExpected[] =
+ "\x04" // == Literal unindexed, name index 0x04 ==
+ "\x0c" // Value length (12)
+ "/sample/path"; // Value
+ EXPECT_EQ(kExpected, b.buffer());
+ }
+ {
+ HpackBlockBuilder b;
+ b.AppendLiteralNameAndValue(HpackEntryType::kNeverIndexedLiteralHeader,
+ kUncompressed, "password", kUncompressed,
+ "secret");
+ EXPECT_EQ(17u, b.size());
+
+ const char kExpected[] =
+ "\x10" // == Literal never indexed ==
+ "\x08" // Name length (8)
+ "password" // Name
+ "\x06" // Value length (6)
+ "secret"; // Value
+ EXPECT_EQ(kExpected, b.buffer());
+ }
+ {
+ HpackBlockBuilder b;
+ b.AppendIndexedHeader(2);
+ EXPECT_EQ(1u, b.size());
+
+ const char kExpected[] = "\x82"; // == Indexed (2) ==
+ EXPECT_EQ(kExpected, b.buffer());
+ }
+}
+
+// Tests of encoding per the RFC. See:
+// http://httpwg.org/specs/rfc7541.html#request.examples.without.huffman.coding
+TEST(HpackBlockBuilderTest, ExamplesFromSpecC3) {
+ {
+ // Header block to encode:
+ // :method: GET
+ // :scheme: http
+ // :path: /
+ // :authority: www.example.com
+ HpackBlockBuilder b;
+ b.AppendIndexedHeader(2); // :method: GET
+ b.AppendIndexedHeader(6); // :scheme: http
+ b.AppendIndexedHeader(4); // :path: /
+ b.AppendNameIndexAndLiteralValue(HpackEntryType::kIndexedLiteralHeader, 1,
+ kUncompressed, "www.example.com");
+ EXPECT_EQ(20u, b.size());
+
+ // Hex dump of encoded data (copied from RFC):
+ // 0x0000: 8286 8441 0f77 7777 2e65 7861 6d70 6c65 ...A.www.example
+ // 0x0010: 2e63 6f6d .com
+
+ const std::string expected =
+ a2b_hex("828684410f7777772e6578616d706c652e636f6d");
+ EXPECT_EQ(expected, b.buffer());
+ }
+}
+
+// Tests of encoding per the RFC. See:
+// http://httpwg.org/specs/rfc7541.html#request.examples.with.huffman.coding
+TEST(HpackBlockBuilderTest, ExamplesFromSpecC4) {
+ {
+ // Header block to encode:
+ // :method: GET
+ // :scheme: http
+ // :path: /
+ // :authority: www.example.com (Huffman encoded)
+ HpackBlockBuilder b;
+ b.AppendIndexedHeader(kStaticTableMethodGET);
+ b.AppendIndexedHeader(kStaticTableSchemeHttp);
+ b.AppendIndexedHeader(kStaticTablePathSlash);
+ const char kHuffmanWwwExampleCom[] = {0xf1u, 0xe3u, 0xc2u, 0xe5u,
+ 0xf2u, 0x3au, 0x6bu, 0xa0u,
+ 0xabu, 0x90u, 0xf4u, 0xffu};
+ b.AppendNameIndexAndLiteralValue(
+ HpackEntryType::kIndexedLiteralHeader, 1, kCompressed,
+ StringPiece(kHuffmanWwwExampleCom, sizeof kHuffmanWwwExampleCom));
+ EXPECT_EQ(17u, b.size());
+
+ // Hex dump of encoded data (copied from RFC):
+ // 0x0000: 8286 8441 8cf1 e3c2 e5f2 3a6b a0ab 90f4 ...A......:k....
+ // 0x0010: ff .
+
+ const std::string expected = a2b_hex("828684418cf1e3c2e5f23a6ba0ab90f4ff");
+ EXPECT_EQ(expected, b.buffer());
+ }
+}
+
+TEST(HpackBlockBuilderTest, DynamicTableSizeUpdate) {
+ {
+ HpackBlockBuilder b;
+ b.AppendDynamicTableSizeUpdate(0);
+ EXPECT_EQ(1u, b.size());
+
+ const char kData[] = {0x20};
+ StringPiece expected(kData, sizeof kData);
+ EXPECT_EQ(expected, b.buffer());
+ }
+ {
+ HpackBlockBuilder b;
+ b.AppendDynamicTableSizeUpdate(4096); // The default size.
+ EXPECT_EQ(3u, b.size());
+
+ const char kData[] = {0x3f, 0xe1u, 0x1f};
+ StringPiece expected(kData, sizeof kData);
+ EXPECT_EQ(expected, b.buffer());
+ }
+ {
+ HpackBlockBuilder b;
+ b.AppendDynamicTableSizeUpdate(1000000000000); // A very large value.
+ EXPECT_EQ(7u, b.size());
+
+ const char kData[] = {0x3fu, 0xe1u, 0x9fu, 0x94u, 0xa5u, 0x8du, 0x1du};
+ StringPiece expected(kData, sizeof kData);
+ EXPECT_EQ(expected, b.buffer());
+ }
+}
+
+} // namespace
+} // namespace test
+} // namespace net
diff --git a/chromium/net/http2/hpack/tools/hpack_example.cc b/chromium/net/http2/hpack/tools/hpack_example.cc
new file mode 100644
index 00000000000..72fd5810e99
--- /dev/null
+++ b/chromium/net/http2/hpack/tools/hpack_example.cc
@@ -0,0 +1,61 @@
+// Copyright 2016 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.
+
+#include "net/http2/hpack/tools/hpack_example.h"
+
+#include <ctype.h>
+
+#include "base/logging.h"
+#include "net/spdy/spdy_test_utils.h"
+
+using base::StringPiece;
+using std::string;
+
+namespace net {
+namespace test {
+namespace {
+
+void HpackExampleToStringOrDie(StringPiece example, string* output) {
+ while (!example.empty()) {
+ const char c0 = example[0];
+ if (isxdigit(c0)) {
+ CHECK_GT(example.size(), 1u) << "Truncated hex byte?";
+ const char c1 = example[1];
+ CHECK(isxdigit(c1)) << "Found half a byte?";
+ *output += a2b_hex(example.substr(0, 2).as_string().c_str());
+ example.remove_prefix(2);
+ continue;
+ }
+ if (isspace(c0)) {
+ example.remove_prefix(1);
+ continue;
+ }
+ if (example.starts_with("|")) {
+ // Start of a comment. Skip to end of line or of input.
+ auto pos = example.find('\n');
+ if (pos == StringPiece::npos) {
+ // End of input.
+ break;
+ }
+ example.remove_prefix(pos + 1);
+ continue;
+ }
+ CHECK(false) << "Can't parse byte " << static_cast<int>(c0) << " (0x"
+ << std::hex << c0 << ")"
+ << "\nExample: " << example;
+ }
+ CHECK_LT(0u, output->size()) << "Example is empty.";
+ return;
+}
+
+} // namespace
+
+string HpackExampleToStringOrDie(StringPiece example) {
+ string output;
+ HpackExampleToStringOrDie(example, &output);
+ return output;
+}
+
+} // namespace test
+} // namespace net
diff --git a/chromium/net/http2/hpack/tools/hpack_example.h b/chromium/net/http2/hpack/tools/hpack_example.h
new file mode 100644
index 00000000000..1567cbf7d61
--- /dev/null
+++ b/chromium/net/http2/hpack/tools/hpack_example.h
@@ -0,0 +1,32 @@
+// Copyright 2016 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.
+
+#ifndef NET_HTTP2_HPACK_TOOLS_HPACK_EXAMPLE_H_
+#define NET_HTTP2_HPACK_TOOLS_HPACK_EXAMPLE_H_
+
+// Parses HPACK examples in the format seen in the HPACK specification,
+// RFC 7541. For example:
+//
+// 10 | == Literal never indexed ==
+// 08 | Literal name (len = 8)
+// 7061 7373 776f 7264 | password
+// 06 | Literal value (len = 6)
+// 7365 6372 6574 | secret
+// | -> password: secret
+//
+// (excluding the leading "//").
+
+#include <string>
+
+#include "base/strings/string_piece.h"
+
+namespace net {
+namespace test {
+
+std::string HpackExampleToStringOrDie(base::StringPiece example);
+
+} // namespace test
+} // namespace net
+
+#endif // NET_HTTP2_HPACK_TOOLS_HPACK_EXAMPLE_H_
diff --git a/chromium/net/http2/http2_constants.cc b/chromium/net/http2/http2_constants.cc
new file mode 100644
index 00000000000..ca28f15eb50
--- /dev/null
+++ b/chromium/net/http2/http2_constants.cc
@@ -0,0 +1,161 @@
+// Copyright 2016 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.
+
+#include "net/http2/http2_constants.h"
+
+#include <ios>
+#include <sstream>
+
+#include "base/logging.h"
+#include "base/strings/string_piece.h"
+#include "base/strings/stringprintf.h"
+
+using base::StringPrintf;
+using std::string;
+
+namespace net {
+
+string Http2FrameTypeToString(Http2FrameType v) {
+ switch (v) {
+ case Http2FrameType::DATA:
+ return "DATA";
+ case Http2FrameType::HEADERS:
+ return "HEADERS";
+ case Http2FrameType::PRIORITY:
+ return "PRIORITY";
+ case Http2FrameType::RST_STREAM:
+ return "RST_STREAM";
+ case Http2FrameType::SETTINGS:
+ return "SETTINGS";
+ case Http2FrameType::PUSH_PROMISE:
+ return "PUSH_PROMISE";
+ case Http2FrameType::PING:
+ return "PING";
+ case Http2FrameType::GOAWAY:
+ return "GOAWAY";
+ case Http2FrameType::WINDOW_UPDATE:
+ return "WINDOW_UPDATE";
+ case Http2FrameType::CONTINUATION:
+ return "CONTINUATION";
+ case Http2FrameType::ALTSVC:
+ return "ALTSVC";
+ }
+ std::stringstream ss;
+ ss << "UnknownFrameType(" << static_cast<int>(v) << ")";
+ return ss.str();
+}
+string Http2FrameTypeToString(uint8_t v) {
+ return Http2FrameTypeToString(static_cast<Http2FrameType>(v));
+}
+
+string Http2FrameFlagsToString(Http2FrameType type, uint8_t flags) {
+ string s;
+ // Closure to append flag name |v| to the string |s|, and to clear
+ // |bit| from |flags|.
+ auto append_and_clear = [&s, &flags](base::StringPiece v, uint8_t bit) {
+ if (!s.empty()) {
+ s.push_back('|');
+ }
+ v.AppendToString(&s);
+ flags ^= bit;
+ };
+ if (flags & 0x01) {
+ if (type == Http2FrameType::DATA || type == Http2FrameType::HEADERS) {
+ append_and_clear("END_STREAM", Http2FrameFlag::FLAG_END_STREAM);
+ } else if (type == Http2FrameType::SETTINGS ||
+ type == Http2FrameType::PING) {
+ append_and_clear("ACK", Http2FrameFlag::FLAG_ACK);
+ }
+ }
+ if (flags & 0x04) {
+ if (type == Http2FrameType::HEADERS ||
+ type == Http2FrameType::PUSH_PROMISE ||
+ type == Http2FrameType::CONTINUATION) {
+ append_and_clear("END_HEADERS", Http2FrameFlag::FLAG_END_HEADERS);
+ }
+ }
+ if (flags & 0x08) {
+ if (type == Http2FrameType::DATA || type == Http2FrameType::HEADERS ||
+ type == Http2FrameType::PUSH_PROMISE) {
+ append_and_clear("PADDED", Http2FrameFlag::FLAG_PADDED);
+ }
+ }
+ if (flags & 0x20) {
+ if (type == Http2FrameType::HEADERS) {
+ append_and_clear("PRIORITY", Http2FrameFlag::FLAG_PRIORITY);
+ }
+ }
+ if (flags != 0) {
+ append_and_clear(StringPrintf("0x%02x", flags), flags);
+ }
+ DCHECK_EQ(0, flags);
+ return s;
+}
+string Http2FrameFlagsToString(uint8_t type, uint8_t flags) {
+ return Http2FrameFlagsToString(static_cast<Http2FrameType>(type), flags);
+}
+
+string Http2ErrorCodeToString(uint32_t v) {
+ switch (v) {
+ case 0x0:
+ return "NO_ERROR";
+ case 0x1:
+ return "PROTOCOL_ERROR";
+ case 0x2:
+ return "INTERNAL_ERROR";
+ case 0x3:
+ return "FLOW_CONTROL_ERROR";
+ case 0x4:
+ return "SETTINGS_TIMEOUT";
+ case 0x5:
+ return "STREAM_CLOSED";
+ case 0x6:
+ return "FRAME_SIZE_ERROR";
+ case 0x7:
+ return "REFUSED_STREAM";
+ case 0x8:
+ return "CANCEL";
+ case 0x9:
+ return "COMPRESSION_ERROR";
+ case 0xa:
+ return "CONNECT_ERROR";
+ case 0xb:
+ return "ENHANCE_YOUR_CALM";
+ case 0xc:
+ return "INADEQUATE_SECURITY";
+ case 0xd:
+ return "HTTP_1_1_REQUIRED";
+ }
+ std::stringstream ss;
+ ss << "UnknownErrorCode(0x" << std::hex << v << ")";
+ return ss.str();
+}
+string Http2ErrorCodeToString(Http2ErrorCode v) {
+ return Http2ErrorCodeToString(static_cast<uint32_t>(v));
+}
+
+string Http2SettingsParameterToString(uint32_t v) {
+ switch (v) {
+ case 0x1:
+ return "HEADER_TABLE_SIZE";
+ case 0x2:
+ return "ENABLE_PUSH";
+ case 0x3:
+ return "MAX_CONCURRENT_STREAMS";
+ case 0x4:
+ return "INITIAL_WINDOW_SIZE";
+ case 0x5:
+ return "MAX_FRAME_SIZE";
+ case 0x6:
+ return "MAX_HEADER_LIST_SIZE";
+ }
+ std::stringstream ss;
+ ss << "UnknownSettingsParameter(0x" << std::hex << v << ")";
+ return ss.str();
+}
+string Http2SettingsParameterToString(Http2SettingsParameter v) {
+ return Http2SettingsParameterToString(static_cast<uint32_t>(v));
+}
+
+} // namespace net
diff --git a/chromium/net/http2/http2_constants.h b/chromium/net/http2/http2_constants.h
new file mode 100644
index 00000000000..61c63079ca6
--- /dev/null
+++ b/chromium/net/http2/http2_constants.h
@@ -0,0 +1,265 @@
+// Copyright 2016 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.
+
+#ifndef NET_HTTP2_HTTP2_CONSTANTS_H_
+#define NET_HTTP2_HTTP2_CONSTANTS_H_
+
+// Constants from the HTTP/2 spec, RFC 7540, and associated helper functions.
+
+#include <stdint.h>
+
+#include <iosfwd>
+#include <ostream>
+#include <string>
+
+#include "net/base/net_export.h"
+
+namespace net {
+
+// TODO(jamessynge): create http2_simple_types for types similar to
+// SpdyStreamId, but not for structures like Http2FrameHeader. Then will be
+// able to move these stream id functions there.
+constexpr uint32_t UInt31Mask() {
+ return 0x7fffffff;
+}
+constexpr uint32_t StreamIdMask() {
+ return UInt31Mask();
+}
+
+// The value used to identify types of frames. Upper case to match the RFC.
+// The comments indicate which flags are valid for that frame type.
+// ALTSVC is defined in http://httpwg.org/http-extensions/alt-svc.html
+// (not yet final standard as of March 2016, but close).
+enum class Http2FrameType : uint8_t {
+ DATA = 0, // END_STREAM | PADDED
+ HEADERS = 1, // END_STREAM | END_HEADERS | PADDED | PRIORITY
+ PRIORITY = 2, //
+ RST_STREAM = 3, //
+ SETTINGS = 4, // ACK
+ PUSH_PROMISE = 5, // END_HEADERS | PADDED
+ PING = 6, // ACK
+ GOAWAY = 7, //
+ WINDOW_UPDATE = 8, //
+ CONTINUATION = 9, // END_HEADERS
+ ALTSVC = 10, //
+};
+
+// Is the frame type known/supported?
+inline bool IsSupportedHttp2FrameType(uint32_t v) {
+ return v <= static_cast<uint32_t>(Http2FrameType::ALTSVC);
+}
+inline bool IsSupportedHttp2FrameType(Http2FrameType v) {
+ return IsSupportedHttp2FrameType(static_cast<uint32_t>(v));
+}
+
+// The return type is 'string' so that they can generate a unique string for
+// each unsupported value. Since these are just used for debugging/error
+// messages, that isn't a cost to we need to worry about.
+// The same applies to the functions later in this file.
+NET_EXPORT_PRIVATE std::string Http2FrameTypeToString(Http2FrameType v);
+NET_EXPORT_PRIVATE std::string Http2FrameTypeToString(uint8_t v);
+NET_EXPORT_PRIVATE inline std::ostream& operator<<(std::ostream& out,
+ Http2FrameType v) {
+ return out << Http2FrameTypeToString(v);
+}
+
+// Flags that appear in supported frame types. These are treated as bit masks.
+// The comments indicate for which frame types the flag is valid.
+// TODO(bnc): Remove FLAG_ prefix once enum SpdyFrameType is removed
+// (both enums have a PRIORITY member).
+enum Http2FrameFlag {
+ FLAG_END_STREAM = 0x01, // DATA, HEADERS
+ FLAG_ACK = 0x01, // SETTINGS, PING
+ FLAG_END_HEADERS = 0x04, // HEADERS, PUSH_PROMISE, CONTINUATION
+ FLAG_PADDED = 0x08, // DATA, HEADERS, PUSH_PROMISE
+ FLAG_PRIORITY = 0x20, // HEADERS
+};
+
+// Formats zero or more flags for the specified type of frame. Returns an
+// empty string if flags==0.
+NET_EXPORT_PRIVATE std::string Http2FrameFlagsToString(Http2FrameType type,
+ uint8_t flags);
+NET_EXPORT_PRIVATE std::string Http2FrameFlagsToString(uint8_t type,
+ uint8_t flags);
+
+// Error codes for GOAWAY and RST_STREAM frames.
+enum class Http2ErrorCode : uint32_t {
+ // The associated condition is not a result of an error. For example, a GOAWAY
+ // might include this code to indicate graceful shutdown of a connection.
+ HTTP2_NO_ERROR = 0x0,
+
+ // The endpoint detected an unspecific protocol error. This error is for use
+ // when a more specific error code is not available.
+ PROTOCOL_ERROR = 0x1,
+
+ // The endpoint encountered an unexpected internal error.
+ INTERNAL_ERROR = 0x2,
+
+ // The endpoint detected that its peer violated the flow-control protocol.
+ FLOW_CONTROL_ERROR = 0x3,
+
+ // The endpoint sent a SETTINGS frame but did not receive a response in a
+ // timely manner. See Section 6.5.3 ("Settings Synchronization").
+ SETTINGS_TIMEOUT = 0x4,
+
+ // The endpoint received a frame after a stream was half-closed.
+ STREAM_CLOSED = 0x5,
+
+ // The endpoint received a frame with an invalid size.
+ FRAME_SIZE_ERROR = 0x6,
+
+ // The endpoint refused the stream prior to performing any application
+ // processing (see Section 8.1.4 for details).
+ REFUSED_STREAM = 0x7,
+
+ // Used by the endpoint to indicate that the stream is no longer needed.
+ CANCEL = 0x8,
+
+ // The endpoint is unable to maintain the header compression context
+ // for the connection.
+ COMPRESSION_ERROR = 0x9,
+
+ // The connection established in response to a CONNECT request (Section 8.3)
+ // was reset or abnormally closed.
+ CONNECT_ERROR = 0xa,
+
+ // The endpoint detected that its peer is exhibiting a behavior that might
+ // be generating excessive load.
+ ENHANCE_YOUR_CALM = 0xb,
+
+ // The underlying transport has properties that do not meet minimum
+ // security requirements (see Section 9.2).
+ INADEQUATE_SECURITY = 0xc,
+
+ // The endpoint requires that HTTP/1.1 be used instead of HTTP/2.
+ HTTP_1_1_REQUIRED = 0xd,
+};
+
+// Is the error code supported? (So far that means it is in RFC 7540.)
+inline bool IsSupportedHttp2ErrorCode(uint32_t v) {
+ return v <= static_cast<uint32_t>(Http2ErrorCode::HTTP_1_1_REQUIRED);
+}
+inline bool IsSupportedHttp2ErrorCode(Http2ErrorCode v) {
+ return IsSupportedHttp2ErrorCode(static_cast<uint32_t>(v));
+}
+
+// Format the specified error code.
+NET_EXPORT_PRIVATE std::string Http2ErrorCodeToString(uint32_t v);
+NET_EXPORT_PRIVATE std::string Http2ErrorCodeToString(Http2ErrorCode v);
+NET_EXPORT_PRIVATE inline std::ostream& operator<<(std::ostream& out,
+ Http2ErrorCode v) {
+ return out << Http2ErrorCodeToString(v);
+}
+
+// Supported parameters in SETTINGS frames; so far just those in RFC 7540.
+enum class Http2SettingsParameter : uint16_t {
+ // Allows the sender to inform the remote endpoint of the maximum size of the
+ // header compression table used to decode header blocks, in octets. The
+ // encoder can select any size equal to or less than this value by using
+ // signaling specific to the header compression format inside a header block
+ // (see [COMPRESSION]). The initial value is 4,096 octets.
+ HEADER_TABLE_SIZE = 0x1,
+
+ // This setting can be used to disable server push (Section 8.2). An endpoint
+ // MUST NOT send a PUSH_PROMISE frame if it receives this parameter set to a
+ // value of 0. An endpoint that has both set this parameter to 0 and had it
+ // acknowledged MUST treat the receipt of a PUSH_PROMISE frame as a connection
+ // error (Section 5.4.1) of type PROTOCOL_ERROR.
+ //
+ // The initial value is 1, which indicates that server push is permitted. Any
+ // value other than 0 or 1 MUST be treated as a connection error (Section
+ // 5.4.1) of type PROTOCOL_ERROR.
+ ENABLE_PUSH = 0x2,
+
+ // Indicates the maximum number of concurrent streams that the sender will
+ // allow. This limit is directional: it applies to the number of streams that
+ // the sender permits the receiver to create. Initially, there is no limit to
+ // this value. It is recommended that this value be no smaller than 100, so as
+ // to not unnecessarily limit parallelism.
+ //
+ // A value of 0 for MAX_CONCURRENT_STREAMS SHOULD NOT be treated as
+ // special by endpoints. A zero value does prevent the creation of new
+ // streams; however, this can also happen for any limit that is exhausted with
+ // active streams. Servers SHOULD only set a zero value for short durations;
+ // if a server does not wish to accept requests, closing the connection is
+ // more appropriate.
+ MAX_CONCURRENT_STREAMS = 0x3,
+
+ // Indicates the sender's initial window size (in octets) for stream-level
+ // flow control. The initial value is 2^16-1 (65,535) octets.
+ //
+ // This setting affects the window size of all streams (see Section 6.9.2).
+ //
+ // Values above the maximum flow-control window size of 2^31-1 MUST be treated
+ // as a connection error (Section 5.4.1) of type FLOW_CONTROL_ERROR.
+ INITIAL_WINDOW_SIZE = 0x4,
+
+ // Indicates the size of the largest frame payload that the sender is willing
+ // to receive, in octets.
+ //
+ // The initial value is 2^14 (16,384) octets. The value advertised by an
+ // endpoint MUST be between this initial value and the maximum allowed frame
+ // size (2^24-1 or 16,777,215 octets), inclusive. Values outside this range
+ // MUST be treated as a connection error (Section 5.4.1) of type
+ // PROTOCOL_ERROR.
+ MAX_FRAME_SIZE = 0x5,
+
+ // This advisory setting informs a peer of the maximum size of header list
+ // that the sender is prepared to accept, in octets. The value is based on the
+ // uncompressed size of header fields, including the length of the name and
+ // value in octets plus an overhead of 32 octets for each header field.
+ //
+ // For any given request, a lower limit than what is advertised MAY be
+ // enforced. The initial value of this setting is unlimited.
+ MAX_HEADER_LIST_SIZE = 0x6,
+};
+
+// Is the settings parameter supported (so far that means it is in RFC 7540)?
+inline bool IsSupportedHttp2SettingsParameter(uint32_t v) {
+ return 0 < v &&
+ v <= static_cast<uint32_t>(
+ Http2SettingsParameter::MAX_HEADER_LIST_SIZE);
+}
+inline bool IsSupportedHttp2SettingsParameter(Http2SettingsParameter v) {
+ return IsSupportedHttp2SettingsParameter(static_cast<uint32_t>(v));
+}
+
+// Format the specified settings parameter.
+NET_EXPORT_PRIVATE std::string Http2SettingsParameterToString(uint32_t v);
+NET_EXPORT_PRIVATE std::string Http2SettingsParameterToString(
+ Http2SettingsParameter v);
+inline std::ostream& operator<<(std::ostream& out, Http2SettingsParameter v) {
+ return out << Http2SettingsParameterToString(v);
+}
+
+// Information about the initial, minimum and maximum value of settings (not
+// applicable to all settings parameters).
+class Http2SettingsInfo {
+ public:
+ // Default value for HEADER_TABLE_SIZE.
+ static constexpr uint32_t DefaultHeaderTableSize() { return 4096; }
+
+ // Default value for ENABLE_PUSH.
+ static constexpr bool DefaultEnablePush() { return true; }
+
+ // Default value for INITIAL_WINDOW_SIZE.
+ static constexpr uint32_t DefaultInitialWindowSize() { return 65535; }
+
+ // Maximum value for INITIAL_WINDOW_SIZE, and for the connection flow control
+ // window, and for each stream flow control window.
+ static constexpr uint32_t MaximumWindowSize() { return UInt31Mask(); }
+
+ // Default value for MAX_FRAME_SIZE.
+ static constexpr uint32_t DefaultMaxFrameSize() { return 16384; }
+
+ // Minimum value for MAX_FRAME_SIZE.
+ static constexpr uint32_t MinimumMaxFrameSize() { return 16384; }
+
+ // Maximum value for MAX_FRAME_SIZE.
+ static constexpr uint32_t MaximumMaxFrameSize() { return (1 << 24) - 1; }
+};
+
+} // namespace net
+
+#endif // NET_HTTP2_HTTP2_CONSTANTS_H_
diff --git a/chromium/net/http2/http2_constants_test.cc b/chromium/net/http2/http2_constants_test.cc
new file mode 100644
index 00000000000..f7f24f79a8d
--- /dev/null
+++ b/chromium/net/http2/http2_constants_test.cc
@@ -0,0 +1,272 @@
+// Copyright 2016 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.
+
+#include "net/http2/http2_constants.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace net {
+namespace test {
+namespace {
+
+class Http2ConstantsTest : public testing::Test {};
+
+TEST(Http2ConstantsTest, Http2FrameType) {
+ EXPECT_EQ(Http2FrameType::DATA, static_cast<Http2FrameType>(0));
+ EXPECT_EQ(Http2FrameType::HEADERS, static_cast<Http2FrameType>(1));
+ EXPECT_EQ(Http2FrameType::PRIORITY, static_cast<Http2FrameType>(2));
+ EXPECT_EQ(Http2FrameType::RST_STREAM, static_cast<Http2FrameType>(3));
+ EXPECT_EQ(Http2FrameType::SETTINGS, static_cast<Http2FrameType>(4));
+ EXPECT_EQ(Http2FrameType::PUSH_PROMISE, static_cast<Http2FrameType>(5));
+ EXPECT_EQ(Http2FrameType::PING, static_cast<Http2FrameType>(6));
+ EXPECT_EQ(Http2FrameType::GOAWAY, static_cast<Http2FrameType>(7));
+ EXPECT_EQ(Http2FrameType::WINDOW_UPDATE, static_cast<Http2FrameType>(8));
+ EXPECT_EQ(Http2FrameType::CONTINUATION, static_cast<Http2FrameType>(9));
+ EXPECT_EQ(Http2FrameType::ALTSVC, static_cast<Http2FrameType>(10));
+}
+
+TEST(Http2ConstantsTest, Http2FrameTypeToString) {
+ EXPECT_EQ("DATA", Http2FrameTypeToString(Http2FrameType::DATA));
+ EXPECT_EQ("HEADERS", Http2FrameTypeToString(Http2FrameType::HEADERS));
+ EXPECT_EQ("PRIORITY", Http2FrameTypeToString(Http2FrameType::PRIORITY));
+ EXPECT_EQ("RST_STREAM", Http2FrameTypeToString(Http2FrameType::RST_STREAM));
+ EXPECT_EQ("SETTINGS", Http2FrameTypeToString(Http2FrameType::SETTINGS));
+ EXPECT_EQ("PUSH_PROMISE",
+ Http2FrameTypeToString(Http2FrameType::PUSH_PROMISE));
+ EXPECT_EQ("PING", Http2FrameTypeToString(Http2FrameType::PING));
+ EXPECT_EQ("GOAWAY", Http2FrameTypeToString(Http2FrameType::GOAWAY));
+ EXPECT_EQ("WINDOW_UPDATE",
+ Http2FrameTypeToString(Http2FrameType::WINDOW_UPDATE));
+ EXPECT_EQ("CONTINUATION",
+ Http2FrameTypeToString(Http2FrameType::CONTINUATION));
+ EXPECT_EQ("ALTSVC", Http2FrameTypeToString(Http2FrameType::ALTSVC));
+
+ EXPECT_EQ("DATA", Http2FrameTypeToString(0));
+ EXPECT_EQ("HEADERS", Http2FrameTypeToString(1));
+ EXPECT_EQ("PRIORITY", Http2FrameTypeToString(2));
+ EXPECT_EQ("RST_STREAM", Http2FrameTypeToString(3));
+ EXPECT_EQ("SETTINGS", Http2FrameTypeToString(4));
+ EXPECT_EQ("PUSH_PROMISE", Http2FrameTypeToString(5));
+ EXPECT_EQ("PING", Http2FrameTypeToString(6));
+ EXPECT_EQ("GOAWAY", Http2FrameTypeToString(7));
+ EXPECT_EQ("WINDOW_UPDATE", Http2FrameTypeToString(8));
+ EXPECT_EQ("CONTINUATION", Http2FrameTypeToString(9));
+ EXPECT_EQ("ALTSVC", Http2FrameTypeToString(10));
+
+ EXPECT_EQ("UnknownFrameType(99)", Http2FrameTypeToString(99));
+}
+
+TEST(Http2ConstantsTest, Http2FrameFlag) {
+ EXPECT_EQ(Http2FrameFlag::FLAG_END_STREAM, static_cast<Http2FrameFlag>(0x01));
+ EXPECT_EQ(Http2FrameFlag::FLAG_ACK, static_cast<Http2FrameFlag>(0x01));
+ EXPECT_EQ(Http2FrameFlag::FLAG_END_HEADERS,
+ static_cast<Http2FrameFlag>(0x04));
+ EXPECT_EQ(Http2FrameFlag::FLAG_PADDED, static_cast<Http2FrameFlag>(0x08));
+ EXPECT_EQ(Http2FrameFlag::FLAG_PRIORITY, static_cast<Http2FrameFlag>(0x20));
+
+ EXPECT_EQ(Http2FrameFlag::FLAG_END_STREAM, 0x01);
+ EXPECT_EQ(Http2FrameFlag::FLAG_ACK, 0x01);
+ EXPECT_EQ(Http2FrameFlag::FLAG_END_HEADERS, 0x04);
+ EXPECT_EQ(Http2FrameFlag::FLAG_PADDED, 0x08);
+ EXPECT_EQ(Http2FrameFlag::FLAG_PRIORITY, 0x20);
+}
+
+TEST(Http2ConstantsTest, Http2FrameFlagsToString) {
+ // Single flags...
+
+ // 0b00000001
+ EXPECT_EQ("END_STREAM",
+ Http2FrameFlagsToString(Http2FrameType::DATA,
+ Http2FrameFlag::FLAG_END_STREAM));
+ EXPECT_EQ("END_STREAM",
+ Http2FrameFlagsToString(Http2FrameType::HEADERS, 0x01));
+ EXPECT_EQ("ACK", Http2FrameFlagsToString(Http2FrameType::SETTINGS,
+ Http2FrameFlag::FLAG_ACK));
+ EXPECT_EQ("ACK", Http2FrameFlagsToString(Http2FrameType::PING, 0x01));
+
+ // 0b00000010
+ EXPECT_EQ("0x02", Http2FrameFlagsToString(0xff, 0x02));
+
+ // 0b00000100
+ EXPECT_EQ("END_HEADERS",
+ Http2FrameFlagsToString(Http2FrameType::HEADERS,
+ Http2FrameFlag::FLAG_END_HEADERS));
+ EXPECT_EQ("END_HEADERS",
+ Http2FrameFlagsToString(Http2FrameType::PUSH_PROMISE, 0x04));
+ EXPECT_EQ("END_HEADERS", Http2FrameFlagsToString(0x09, 0x04));
+ EXPECT_EQ("0x04", Http2FrameFlagsToString(0xff, 0x04));
+
+ // 0b00001000
+ EXPECT_EQ("PADDED", Http2FrameFlagsToString(Http2FrameType::DATA,
+ Http2FrameFlag::FLAG_PADDED));
+ EXPECT_EQ("PADDED", Http2FrameFlagsToString(Http2FrameType::HEADERS, 0x08));
+ EXPECT_EQ("PADDED", Http2FrameFlagsToString(0x05, 0x08));
+ EXPECT_EQ("0x08", Http2FrameFlagsToString(0xff, Http2FrameFlag::FLAG_PADDED));
+
+ // 0b00010000
+ EXPECT_EQ("0x10", Http2FrameFlagsToString(Http2FrameType::SETTINGS, 0x10));
+
+ // 0b00100000
+ EXPECT_EQ("PRIORITY", Http2FrameFlagsToString(Http2FrameType::HEADERS, 0x20));
+ EXPECT_EQ("0x20",
+ Http2FrameFlagsToString(Http2FrameType::PUSH_PROMISE, 0x20));
+
+ // 0b01000000
+ EXPECT_EQ("0x40", Http2FrameFlagsToString(0xff, 0x40));
+
+ // 0b10000000
+ EXPECT_EQ("0x80", Http2FrameFlagsToString(0xff, 0x80));
+
+ // Combined flags...
+
+ EXPECT_EQ("END_STREAM|PADDED|0xf6",
+ Http2FrameFlagsToString(Http2FrameType::DATA, 0xff));
+ EXPECT_EQ("END_STREAM|END_HEADERS|PADDED|PRIORITY|0xd2",
+ Http2FrameFlagsToString(Http2FrameType::HEADERS, 0xff));
+ EXPECT_EQ("0xff", Http2FrameFlagsToString(Http2FrameType::PRIORITY, 0xff));
+ EXPECT_EQ("0xff", Http2FrameFlagsToString(Http2FrameType::RST_STREAM, 0xff));
+ EXPECT_EQ("ACK|0xfe",
+ Http2FrameFlagsToString(Http2FrameType::SETTINGS, 0xff));
+ EXPECT_EQ("END_HEADERS|PADDED|0xf3",
+ Http2FrameFlagsToString(Http2FrameType::PUSH_PROMISE, 0xff));
+ EXPECT_EQ("ACK|0xfe", Http2FrameFlagsToString(Http2FrameType::PING, 0xff));
+ EXPECT_EQ("0xff", Http2FrameFlagsToString(Http2FrameType::GOAWAY, 0xff));
+ EXPECT_EQ("0xff",
+ Http2FrameFlagsToString(Http2FrameType::WINDOW_UPDATE, 0xff));
+ EXPECT_EQ("END_HEADERS|0xfb",
+ Http2FrameFlagsToString(Http2FrameType::CONTINUATION, 0xff));
+ EXPECT_EQ("0xff", Http2FrameFlagsToString(Http2FrameType::ALTSVC, 0xff));
+ EXPECT_EQ("0xff", Http2FrameFlagsToString(0xff, 0xff));
+}
+
+TEST(Http2ConstantsTest, Http2ErrorCode) {
+ EXPECT_EQ(Http2ErrorCode::HTTP2_NO_ERROR, static_cast<Http2ErrorCode>(0x0));
+ EXPECT_EQ(Http2ErrorCode::PROTOCOL_ERROR, static_cast<Http2ErrorCode>(0x1));
+ EXPECT_EQ(Http2ErrorCode::INTERNAL_ERROR, static_cast<Http2ErrorCode>(0x2));
+ EXPECT_EQ(Http2ErrorCode::FLOW_CONTROL_ERROR,
+ static_cast<Http2ErrorCode>(0x3));
+ EXPECT_EQ(Http2ErrorCode::SETTINGS_TIMEOUT, static_cast<Http2ErrorCode>(0x4));
+ EXPECT_EQ(Http2ErrorCode::STREAM_CLOSED, static_cast<Http2ErrorCode>(0x5));
+ EXPECT_EQ(Http2ErrorCode::FRAME_SIZE_ERROR, static_cast<Http2ErrorCode>(0x6));
+ EXPECT_EQ(Http2ErrorCode::REFUSED_STREAM, static_cast<Http2ErrorCode>(0x7));
+ EXPECT_EQ(Http2ErrorCode::CANCEL, static_cast<Http2ErrorCode>(0x8));
+ EXPECT_EQ(Http2ErrorCode::COMPRESSION_ERROR,
+ static_cast<Http2ErrorCode>(0x9));
+ EXPECT_EQ(Http2ErrorCode::CONNECT_ERROR, static_cast<Http2ErrorCode>(0xa));
+ EXPECT_EQ(Http2ErrorCode::ENHANCE_YOUR_CALM,
+ static_cast<Http2ErrorCode>(0xb));
+ EXPECT_EQ(Http2ErrorCode::INADEQUATE_SECURITY,
+ static_cast<Http2ErrorCode>(0xc));
+ EXPECT_EQ(Http2ErrorCode::HTTP_1_1_REQUIRED,
+ static_cast<Http2ErrorCode>(0xd));
+}
+
+TEST(Http2ConstantsTest, Http2ErrorCodeToString) {
+ EXPECT_EQ("NO_ERROR", Http2ErrorCodeToString(Http2ErrorCode::HTTP2_NO_ERROR));
+ EXPECT_EQ("NO_ERROR", Http2ErrorCodeToString(0x0));
+ EXPECT_EQ("PROTOCOL_ERROR",
+ Http2ErrorCodeToString(Http2ErrorCode::PROTOCOL_ERROR));
+ EXPECT_EQ("PROTOCOL_ERROR", Http2ErrorCodeToString(0x1));
+ EXPECT_EQ("INTERNAL_ERROR",
+ Http2ErrorCodeToString(Http2ErrorCode::INTERNAL_ERROR));
+ EXPECT_EQ("INTERNAL_ERROR", Http2ErrorCodeToString(0x2));
+ EXPECT_EQ("FLOW_CONTROL_ERROR",
+ Http2ErrorCodeToString(Http2ErrorCode::FLOW_CONTROL_ERROR));
+ EXPECT_EQ("FLOW_CONTROL_ERROR", Http2ErrorCodeToString(0x3));
+ EXPECT_EQ("SETTINGS_TIMEOUT",
+ Http2ErrorCodeToString(Http2ErrorCode::SETTINGS_TIMEOUT));
+ EXPECT_EQ("SETTINGS_TIMEOUT", Http2ErrorCodeToString(0x4));
+ EXPECT_EQ("STREAM_CLOSED",
+ Http2ErrorCodeToString(Http2ErrorCode::STREAM_CLOSED));
+ EXPECT_EQ("STREAM_CLOSED", Http2ErrorCodeToString(0x5));
+ EXPECT_EQ("FRAME_SIZE_ERROR",
+ Http2ErrorCodeToString(Http2ErrorCode::FRAME_SIZE_ERROR));
+ EXPECT_EQ("FRAME_SIZE_ERROR", Http2ErrorCodeToString(0x6));
+ EXPECT_EQ("REFUSED_STREAM",
+ Http2ErrorCodeToString(Http2ErrorCode::REFUSED_STREAM));
+ EXPECT_EQ("REFUSED_STREAM", Http2ErrorCodeToString(0x7));
+ EXPECT_EQ("CANCEL", Http2ErrorCodeToString(Http2ErrorCode::CANCEL));
+ EXPECT_EQ("CANCEL", Http2ErrorCodeToString(0x8));
+ EXPECT_EQ("COMPRESSION_ERROR",
+ Http2ErrorCodeToString(Http2ErrorCode::COMPRESSION_ERROR));
+ EXPECT_EQ("COMPRESSION_ERROR", Http2ErrorCodeToString(0x9));
+ EXPECT_EQ("CONNECT_ERROR",
+ Http2ErrorCodeToString(Http2ErrorCode::CONNECT_ERROR));
+ EXPECT_EQ("CONNECT_ERROR", Http2ErrorCodeToString(0xa));
+ EXPECT_EQ("ENHANCE_YOUR_CALM",
+ Http2ErrorCodeToString(Http2ErrorCode::ENHANCE_YOUR_CALM));
+ EXPECT_EQ("ENHANCE_YOUR_CALM", Http2ErrorCodeToString(0xb));
+ EXPECT_EQ("INADEQUATE_SECURITY",
+ Http2ErrorCodeToString(Http2ErrorCode::INADEQUATE_SECURITY));
+ EXPECT_EQ("INADEQUATE_SECURITY", Http2ErrorCodeToString(0xc));
+ EXPECT_EQ("HTTP_1_1_REQUIRED",
+ Http2ErrorCodeToString(Http2ErrorCode::HTTP_1_1_REQUIRED));
+ EXPECT_EQ("HTTP_1_1_REQUIRED", Http2ErrorCodeToString(0xd));
+
+ EXPECT_EQ("UnknownErrorCode(0x123)", Http2ErrorCodeToString(0x123));
+}
+
+TEST(Http2ConstantsTest, Http2SettingsParameter) {
+ EXPECT_EQ(Http2SettingsParameter::HEADER_TABLE_SIZE,
+ static_cast<Http2SettingsParameter>(0x1));
+ EXPECT_EQ(Http2SettingsParameter::ENABLE_PUSH,
+ static_cast<Http2SettingsParameter>(0x2));
+ EXPECT_EQ(Http2SettingsParameter::MAX_CONCURRENT_STREAMS,
+ static_cast<Http2SettingsParameter>(0x3));
+ EXPECT_EQ(Http2SettingsParameter::INITIAL_WINDOW_SIZE,
+ static_cast<Http2SettingsParameter>(0x4));
+ EXPECT_EQ(Http2SettingsParameter::MAX_FRAME_SIZE,
+ static_cast<Http2SettingsParameter>(0x5));
+ EXPECT_EQ(Http2SettingsParameter::MAX_HEADER_LIST_SIZE,
+ static_cast<Http2SettingsParameter>(0x6));
+
+ EXPECT_TRUE(IsSupportedHttp2SettingsParameter(
+ Http2SettingsParameter::HEADER_TABLE_SIZE));
+ EXPECT_TRUE(
+ IsSupportedHttp2SettingsParameter(Http2SettingsParameter::ENABLE_PUSH));
+ EXPECT_TRUE(IsSupportedHttp2SettingsParameter(
+ Http2SettingsParameter::MAX_CONCURRENT_STREAMS));
+ EXPECT_TRUE(IsSupportedHttp2SettingsParameter(
+ Http2SettingsParameter::INITIAL_WINDOW_SIZE));
+ EXPECT_TRUE(IsSupportedHttp2SettingsParameter(
+ Http2SettingsParameter::MAX_FRAME_SIZE));
+ EXPECT_TRUE(IsSupportedHttp2SettingsParameter(
+ Http2SettingsParameter::MAX_HEADER_LIST_SIZE));
+
+ EXPECT_FALSE(IsSupportedHttp2SettingsParameter(
+ static_cast<Http2SettingsParameter>(0)));
+ EXPECT_FALSE(IsSupportedHttp2SettingsParameter(
+ static_cast<Http2SettingsParameter>(7)));
+}
+
+TEST(Http2ConstantsTest, Http2SettingsParameterToString) {
+ EXPECT_EQ("HEADER_TABLE_SIZE",
+ Http2SettingsParameterToString(
+ Http2SettingsParameter::HEADER_TABLE_SIZE));
+ EXPECT_EQ("HEADER_TABLE_SIZE", Http2SettingsParameterToString(0x1));
+ EXPECT_EQ("ENABLE_PUSH", Http2SettingsParameterToString(
+ Http2SettingsParameter::ENABLE_PUSH));
+ EXPECT_EQ("ENABLE_PUSH", Http2SettingsParameterToString(0x2));
+ EXPECT_EQ("MAX_CONCURRENT_STREAMS",
+ Http2SettingsParameterToString(
+ Http2SettingsParameter::MAX_CONCURRENT_STREAMS));
+ EXPECT_EQ("MAX_CONCURRENT_STREAMS", Http2SettingsParameterToString(0x3));
+ EXPECT_EQ("INITIAL_WINDOW_SIZE",
+ Http2SettingsParameterToString(
+ Http2SettingsParameter::INITIAL_WINDOW_SIZE));
+ EXPECT_EQ("INITIAL_WINDOW_SIZE", Http2SettingsParameterToString(0x4));
+ EXPECT_EQ("MAX_FRAME_SIZE", Http2SettingsParameterToString(
+ Http2SettingsParameter::MAX_FRAME_SIZE));
+ EXPECT_EQ("MAX_FRAME_SIZE", Http2SettingsParameterToString(0x5));
+ EXPECT_EQ("MAX_HEADER_LIST_SIZE",
+ Http2SettingsParameterToString(
+ Http2SettingsParameter::MAX_HEADER_LIST_SIZE));
+ EXPECT_EQ("MAX_HEADER_LIST_SIZE", Http2SettingsParameterToString(0x6));
+
+ EXPECT_EQ("UnknownSettingsParameter(0x123)",
+ Http2SettingsParameterToString(0x123));
+}
+
+} // namespace
+} // namespace test
+} // namespace net
diff --git a/chromium/net/http2/http2_constants_test_util.cc b/chromium/net/http2/http2_constants_test_util.cc
new file mode 100644
index 00000000000..2f4be401138
--- /dev/null
+++ b/chromium/net/http2/http2_constants_test_util.cc
@@ -0,0 +1,142 @@
+// Copyright 2016 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.
+
+#include "net/http2/http2_constants_test_util.h"
+
+namespace net {
+namespace test {
+
+std::vector<Http2FrameType> AllHttp2FrameTypes() {
+ // clang-format off
+ return {
+ Http2FrameType::DATA,
+ Http2FrameType::HEADERS,
+ Http2FrameType::PRIORITY,
+ Http2FrameType::RST_STREAM,
+ Http2FrameType::SETTINGS,
+ Http2FrameType::PUSH_PROMISE,
+ Http2FrameType::PING,
+ Http2FrameType::GOAWAY,
+ Http2FrameType::WINDOW_UPDATE,
+ Http2FrameType::CONTINUATION,
+ Http2FrameType::ALTSVC,
+ };
+ // clang-format on
+}
+
+std::vector<Http2FrameFlag> AllHttp2FrameFlagsForFrameType(
+ Http2FrameType type) {
+ // clang-format off
+ switch (type) {
+ case Http2FrameType::DATA:
+ return {
+ Http2FrameFlag::FLAG_END_STREAM,
+ Http2FrameFlag::FLAG_PADDED,
+ };
+ case Http2FrameType::HEADERS:
+ return {
+ Http2FrameFlag::FLAG_END_STREAM,
+ Http2FrameFlag::FLAG_END_HEADERS,
+ Http2FrameFlag::FLAG_PADDED,
+ Http2FrameFlag::FLAG_PRIORITY,
+ };
+ case Http2FrameType::SETTINGS:
+ return {
+ Http2FrameFlag::FLAG_ACK,
+ };
+ case Http2FrameType::PUSH_PROMISE:
+ return {
+ Http2FrameFlag::FLAG_END_HEADERS,
+ Http2FrameFlag::FLAG_PADDED,
+ };
+ case Http2FrameType::PING:
+ return {
+ Http2FrameFlag::FLAG_ACK,
+ };
+ case Http2FrameType::CONTINUATION:
+ return {
+ Http2FrameFlag::FLAG_END_HEADERS,
+ };
+ default:
+ return std::vector<Http2FrameFlag>{};
+ }
+ // clang-format on
+}
+
+std::vector<Http2ErrorCode> AllHttp2ErrorCodes() {
+ // clang-format off
+ return {
+ Http2ErrorCode::HTTP2_NO_ERROR,
+ Http2ErrorCode::PROTOCOL_ERROR,
+ Http2ErrorCode::INTERNAL_ERROR,
+ Http2ErrorCode::FLOW_CONTROL_ERROR,
+ Http2ErrorCode::SETTINGS_TIMEOUT,
+ Http2ErrorCode::STREAM_CLOSED,
+ Http2ErrorCode::FRAME_SIZE_ERROR,
+ Http2ErrorCode::REFUSED_STREAM,
+ Http2ErrorCode::CANCEL,
+ Http2ErrorCode::COMPRESSION_ERROR,
+ Http2ErrorCode::CONNECT_ERROR,
+ Http2ErrorCode::ENHANCE_YOUR_CALM,
+ Http2ErrorCode::INADEQUATE_SECURITY,
+ Http2ErrorCode::HTTP_1_1_REQUIRED,
+ };
+ // clang-format on
+}
+
+std::vector<Http2SettingsParameter> AllHttp2SettingsParameters() {
+ // clang-format off
+ return {
+ Http2SettingsParameter::HEADER_TABLE_SIZE,
+ Http2SettingsParameter::ENABLE_PUSH,
+ Http2SettingsParameter::MAX_CONCURRENT_STREAMS,
+ Http2SettingsParameter::INITIAL_WINDOW_SIZE,
+ Http2SettingsParameter::MAX_FRAME_SIZE,
+ Http2SettingsParameter::MAX_HEADER_LIST_SIZE,
+ };
+ // clang-format on
+}
+
+// Returns a mask of flags supported for the specified frame type. Returns
+// zero for unknown frame types.
+uint8_t KnownFlagsMaskForFrameType(Http2FrameType type) {
+ switch (type) {
+ case Http2FrameType::DATA:
+ return Http2FrameFlag::FLAG_END_STREAM | Http2FrameFlag::FLAG_PADDED;
+ case Http2FrameType::HEADERS:
+ return Http2FrameFlag::FLAG_END_STREAM |
+ Http2FrameFlag::FLAG_END_HEADERS | Http2FrameFlag::FLAG_PADDED |
+ Http2FrameFlag::FLAG_PRIORITY;
+ case Http2FrameType::PRIORITY:
+ return 0x00;
+ case Http2FrameType::RST_STREAM:
+ return 0x00;
+ case Http2FrameType::SETTINGS:
+ return Http2FrameFlag::FLAG_ACK;
+ case Http2FrameType::PUSH_PROMISE:
+ return Http2FrameFlag::FLAG_END_HEADERS | Http2FrameFlag::FLAG_PADDED;
+ case Http2FrameType::PING:
+ return Http2FrameFlag::FLAG_ACK;
+ case Http2FrameType::GOAWAY:
+ return 0x00;
+ case Http2FrameType::WINDOW_UPDATE:
+ return 0x00;
+ case Http2FrameType::CONTINUATION:
+ return Http2FrameFlag::FLAG_END_HEADERS;
+ case Http2FrameType::ALTSVC:
+ return 0x00;
+ default:
+ return 0x00;
+ }
+}
+
+uint8_t InvalidFlagMaskForFrameType(Http2FrameType type) {
+ if (IsSupportedHttp2FrameType(type)) {
+ return ~KnownFlagsMaskForFrameType(type);
+ }
+ return 0x00;
+}
+
+} // namespace test
+} // namespace net
diff --git a/chromium/net/http2/http2_constants_test_util.h b/chromium/net/http2/http2_constants_test_util.h
new file mode 100644
index 00000000000..6d20cec9d83
--- /dev/null
+++ b/chromium/net/http2/http2_constants_test_util.h
@@ -0,0 +1,40 @@
+// Copyright 2016 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.
+
+#ifndef NET_HTTP2_HTTP2_CONSTANTS_TEST_UTIL_H_
+#define NET_HTTP2_HTTP2_CONSTANTS_TEST_UTIL_H_
+
+#include <vector>
+
+#include "net/http2/http2_constants.h"
+
+namespace net {
+namespace test {
+
+// Returns a vector of all supported frame types.
+std::vector<Http2FrameType> AllHttp2FrameTypes();
+
+// Returns a vector of all supported frame flags for the specified
+// frame type. Empty if the type is unknown.
+std::vector<Http2FrameFlag> AllHttp2FrameFlagsForFrameType(Http2FrameType type);
+
+// Returns a vector of all supported RST_STREAM and GOAWAY error codes.
+std::vector<Http2ErrorCode> AllHttp2ErrorCodes();
+
+// Returns a vector of all supported parameters in SETTINGS frames.
+std::vector<Http2SettingsParameter> AllHttp2SettingsParameters();
+
+// Returns a mask of flags supported for the specified frame type. Returns
+// zero for unknown frame types.
+uint8_t KnownFlagsMaskForFrameType(Http2FrameType type);
+
+// Returns a mask of flag bits known to be invalid for the frame type.
+// For unknown frame types, the mask is zero; i.e., we don't know that any
+// are invalid.
+uint8_t InvalidFlagMaskForFrameType(Http2FrameType type);
+
+} // namespace test
+} // namespace net
+
+#endif // NET_HTTP2_HTTP2_CONSTANTS_TEST_UTIL_H_
diff --git a/chromium/net/http2/http2_structures.cc b/chromium/net/http2/http2_structures.cc
new file mode 100644
index 00000000000..83360430802
--- /dev/null
+++ b/chromium/net/http2/http2_structures.cc
@@ -0,0 +1,138 @@
+// Copyright 2016 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.
+
+#include "net/http2/http2_structures.h"
+
+#include <cstring> // For std::memcmp
+#include <sstream>
+#include <string>
+
+#include "base/strings/string_number_conversions.h"
+#include "base/strings/string_util.h"
+
+using std::string;
+using base::StringPiece;
+
+namespace net {
+
+// Http2FrameHeader:
+
+bool Http2FrameHeader::IsProbableHttpResponse() const {
+ return (payload_length == 0x485454 && // "HTT"
+ static_cast<char>(type) == 'P' && // "P"
+ flags == '/'); // "/"
+}
+
+string Http2FrameHeader::ToString() const {
+ std::stringstream ss;
+ ss << "length=" << payload_length << ", type=" << Http2FrameTypeToString(type)
+ << ", flags=" << FlagsToString() << ", stream=" << stream_id;
+ return ss.str();
+}
+
+string Http2FrameHeader::FlagsToString() const {
+ return Http2FrameFlagsToString(type, flags);
+}
+
+bool operator==(const Http2FrameHeader& a, const Http2FrameHeader& b) {
+ return a.payload_length == b.payload_length && a.stream_id == b.stream_id &&
+ a.type == b.type && a.flags == b.flags;
+}
+
+std::ostream& operator<<(std::ostream& out, const Http2FrameHeader& v) {
+ return out << v.ToString();
+}
+
+// Http2PriorityFields:
+
+bool operator==(const Http2PriorityFields& a, const Http2PriorityFields& b) {
+ return a.stream_dependency == b.stream_dependency && a.weight == b.weight;
+}
+
+std::string Http2PriorityFields::ToString() const {
+ std::stringstream ss;
+ ss << "E=" << (is_exclusive ? "true" : "false")
+ << ", stream=" << stream_dependency
+ << ", weight=" << static_cast<uint32_t>(weight);
+ return ss.str();
+}
+
+std::ostream& operator<<(std::ostream& out, const Http2PriorityFields& v) {
+ return out << v.ToString();
+}
+
+// Http2RstStreamFields:
+
+bool operator==(const Http2RstStreamFields& a, const Http2RstStreamFields& b) {
+ return a.error_code == b.error_code;
+}
+
+std::ostream& operator<<(std::ostream& out, const Http2RstStreamFields& v) {
+ return out << "error_code=" << v.error_code;
+}
+
+// Http2SettingFields:
+
+bool operator==(const Http2SettingFields& a, const Http2SettingFields& b) {
+ return a.parameter == b.parameter && a.value == b.value;
+}
+std::ostream& operator<<(std::ostream& out, const Http2SettingFields& v) {
+ return out << "parameter=" << v.parameter << ", value=" << v.value;
+}
+
+// Http2PushPromiseFields:
+
+bool operator==(const Http2PushPromiseFields& a,
+ const Http2PushPromiseFields& b) {
+ return a.promised_stream_id == b.promised_stream_id;
+}
+
+std::ostream& operator<<(std::ostream& out, const Http2PushPromiseFields& v) {
+ return out << "promised_stream_id=" << v.promised_stream_id;
+}
+
+// Http2PingFields:
+
+bool operator==(const Http2PingFields& a, const Http2PingFields& b) {
+ static_assert((sizeof a.opaque_data) == Http2PingFields::EncodedSize(),
+ "Why not the same size?");
+ return 0 == std::memcmp(a.opaque_data, b.opaque_data, sizeof a.opaque_data);
+}
+
+std::ostream& operator<<(std::ostream& out, const Http2PingFields& v) {
+ string s = base::HexEncode(v.opaque_data, sizeof v.opaque_data);
+ base::CollapseWhitespaceASCII(s, /*trim_sequences_with_line_breaks=*/false);
+ return out << "opaque_data=[" << s << "]";
+}
+
+// Http2GoAwayFields:
+
+bool operator==(const Http2GoAwayFields& a, const Http2GoAwayFields& b) {
+ return a.last_stream_id == b.last_stream_id && a.error_code == b.error_code;
+}
+std::ostream& operator<<(std::ostream& out, const Http2GoAwayFields& v) {
+ return out << "last_stream_id=" << v.last_stream_id
+ << ", error_code=" << v.error_code;
+}
+
+// Http2WindowUpdateFields:
+
+bool operator==(const Http2WindowUpdateFields& a,
+ const Http2WindowUpdateFields& b) {
+ return a.window_size_increment == b.window_size_increment;
+}
+std::ostream& operator<<(std::ostream& out, const Http2WindowUpdateFields& v) {
+ return out << "window_size_increment=" << v.window_size_increment;
+}
+
+// Http2AltSvcFields:
+
+bool operator==(const Http2AltSvcFields& a, const Http2AltSvcFields& b) {
+ return a.origin_length == b.origin_length;
+}
+std::ostream& operator<<(std::ostream& out, const Http2AltSvcFields& v) {
+ return out << "origin_length=" << v.origin_length;
+}
+
+} // namespace net
diff --git a/chromium/net/http2/http2_structures.h b/chromium/net/http2/http2_structures.h
new file mode 100644
index 00000000000..95328e1f5ab
--- /dev/null
+++ b/chromium/net/http2/http2_structures.h
@@ -0,0 +1,326 @@
+// Copyright 2016 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.
+
+#ifndef NET_HTTP2_HTTP2_STRUCTURES_H_
+#define NET_HTTP2_HTTP2_STRUCTURES_H_
+
+// Defines structs for various fixed sized structures in HTTP/2.
+//
+// Those structs with multiple fields have constructors that take arguments in
+// the same order as their encoding (which may be different from their order
+// in the struct). For single field structs, use aggregate initialization if
+// desired, e.g.:
+//
+// Http2RstStreamFields var{Http2ErrorCode::ENHANCE_YOUR_CALM};
+// or:
+// SomeFunc(Http2RstStreamFields{Http2ErrorCode::ENHANCE_YOUR_CALM});
+//
+// Each struct includes a static method EncodedSize which returns the number
+// of bytes of the encoding.
+//
+// With the exception of Http2FrameHeader, all the types are named
+// Http2<X>Fields, where X is the title-case form of the frame which always
+// includes the fields; the "always" is to cover the case of the PRIORITY frame;
+// its fields optionally appear in the HEADERS frame, but the struct is called
+// Http2PriorityFields.
+
+#include <stddef.h>
+#include <stdint.h>
+
+#include <ostream>
+#include <string>
+
+#include "base/logging.h"
+#include "net/base/net_export.h"
+#include "net/http2/http2_constants.h"
+
+namespace net {
+
+struct NET_EXPORT_PRIVATE Http2FrameHeader {
+ Http2FrameHeader() {}
+ Http2FrameHeader(uint32_t payload_length,
+ Http2FrameType type,
+ uint8_t flags,
+ uint32_t stream_id)
+ : payload_length(payload_length),
+ stream_id(stream_id),
+ type(type),
+ flags(static_cast<Http2FrameFlag>(flags)) {
+ DCHECK_LT(payload_length, static_cast<uint32_t>(1 << 24))
+ << "Payload Length is only a 24 bit field\n"
+ << ToString();
+ }
+
+ static constexpr size_t EncodedSize() { return 9; }
+
+ // Keep the current value of those flags that are in
+ // valid_flags, and clear all the others.
+ void RetainFlags(uint8_t valid_flags) {
+ flags = static_cast<Http2FrameFlag>(flags & valid_flags);
+ }
+
+ // Returns true if any of the flags in flag_mask are set,
+ // otherwise false.
+ bool HasAnyFlags(uint8_t flag_mask) const { return 0 != (flags & flag_mask); }
+
+ // Is the END_STREAM flag set?
+ bool IsEndStream() const {
+ DCHECK(type == Http2FrameType::DATA || type == Http2FrameType::HEADERS)
+ << ToString();
+ return (flags & Http2FrameFlag::FLAG_END_STREAM) != 0;
+ }
+
+ // Is the ACK flag set?
+ bool IsAck() const {
+ DCHECK(type == Http2FrameType::SETTINGS || type == Http2FrameType::PING)
+ << ToString();
+ return (flags & Http2FrameFlag::FLAG_ACK) != 0;
+ }
+
+ // Is the END_HEADERS flag set?
+ bool IsEndHeaders() const {
+ DCHECK(type == Http2FrameType::HEADERS ||
+ type == Http2FrameType::PUSH_PROMISE ||
+ type == Http2FrameType::CONTINUATION)
+ << ToString();
+ return (flags & Http2FrameFlag::FLAG_END_HEADERS) != 0;
+ }
+
+ // Is the PADDED flag set?
+ bool IsPadded() const {
+ DCHECK(type == Http2FrameType::DATA || type == Http2FrameType::HEADERS ||
+ type == Http2FrameType::PUSH_PROMISE)
+ << ToString();
+ return (flags & Http2FrameFlag::FLAG_PADDED) != 0;
+ }
+
+ // Is the PRIORITY flag set?
+ bool HasPriority() const {
+ DCHECK_EQ(type, Http2FrameType::HEADERS) << ToString();
+ return (flags & Http2FrameFlag::FLAG_PRIORITY) != 0;
+ }
+
+ // Does the encoding of this header start with "HTTP/", indicating that it
+ // might be from a non-HTTP/2 server.
+ bool IsProbableHttpResponse() const;
+
+ // Produce strings useful for debugging/logging messages.
+ std::string ToString() const;
+ std::string FlagsToString() const;
+
+ // 24 bit length of the payload after the header, including any padding.
+ // First field in encoding.
+ uint32_t payload_length; // 24 bits
+
+ // 31 bit stream id, with high bit (32nd bit) reserved (must be zero),
+ // and is cleared during decoding.
+ // Fourth field in encoding.
+ uint32_t stream_id;
+
+ // Type of the frame.
+ // Second field in encoding.
+ Http2FrameType type;
+
+ // Flag bits, with interpretations that depend upon the frame type.
+ // Flag bits not used by the frame type are cleared.
+ // Third field in encoding.
+ Http2FrameFlag flags;
+};
+
+NET_EXPORT_PRIVATE bool operator==(const Http2FrameHeader& a,
+ const Http2FrameHeader& b);
+NET_EXPORT_PRIVATE inline bool operator!=(const Http2FrameHeader& a,
+ const Http2FrameHeader& b) {
+ return !(a == b);
+}
+NET_EXPORT_PRIVATE std::ostream& operator<<(std::ostream& out,
+ const Http2FrameHeader& v);
+
+// Http2PriorityFields:
+
+struct NET_EXPORT_PRIVATE Http2PriorityFields {
+ Http2PriorityFields() {}
+ Http2PriorityFields(uint32_t stream_dependency,
+ uint32_t weight,
+ bool is_exclusive)
+ : stream_dependency(stream_dependency),
+ weight(weight),
+ is_exclusive(is_exclusive) {
+ // Can't have the high-bit set in the stream id because we need to use
+ // that for the EXCLUSIVE flag bit.
+ DCHECK_EQ(stream_dependency, stream_dependency & StreamIdMask())
+ << "Stream Dependency is only a 31-bit field.\n"
+ << ToString();
+ DCHECK_LE(1u, weight) << "Weight is too small.";
+ DCHECK_LE(weight, 256u) << "Weight is too large.";
+ }
+ static constexpr size_t EncodedSize() { return 5; }
+
+ // Produce strings useful for debugging/logging messages.
+ std::string ToString() const;
+
+ // A 31-bit stream identifier for the stream that this stream depends on.
+ uint32_t stream_dependency;
+
+ // Weight (1 to 256) is encoded as a byte in the range 0 to 255, so we
+ // add one when decoding, and store it in a field larger than a byte.
+ uint32_t weight;
+
+ // A single-bit flag indicating that the stream dependency is exclusive;
+ // extracted from high bit of stream dependency field during decoding.
+ bool is_exclusive;
+};
+
+NET_EXPORT_PRIVATE bool operator==(const Http2PriorityFields& a,
+ const Http2PriorityFields& b);
+NET_EXPORT_PRIVATE inline bool operator!=(const Http2PriorityFields& a,
+ const Http2PriorityFields& b) {
+ return !(a == b);
+}
+NET_EXPORT_PRIVATE std::ostream& operator<<(std::ostream& out,
+ const Http2PriorityFields& v);
+
+// Http2RstStreamFields:
+
+struct Http2RstStreamFields {
+ static constexpr size_t EncodedSize() { return 4; }
+ bool IsSupportedErrorCode() const {
+ return IsSupportedHttp2ErrorCode(error_code);
+ }
+
+ Http2ErrorCode error_code;
+};
+
+NET_EXPORT_PRIVATE bool operator==(const Http2RstStreamFields& a,
+ const Http2RstStreamFields& b);
+NET_EXPORT_PRIVATE inline bool operator!=(const Http2RstStreamFields& a,
+ const Http2RstStreamFields& b) {
+ return !(a == b);
+}
+NET_EXPORT_PRIVATE std::ostream& operator<<(std::ostream& out,
+ const Http2RstStreamFields& v);
+
+// Http2SettingFields:
+
+struct Http2SettingFields {
+ Http2SettingFields() {}
+ Http2SettingFields(Http2SettingsParameter parameter, uint32_t value)
+ : parameter(parameter), value(value) {}
+ static constexpr size_t EncodedSize() { return 6; }
+ bool IsSupportedParameter() const {
+ return IsSupportedHttp2SettingsParameter(parameter);
+ }
+
+ Http2SettingsParameter parameter;
+ uint32_t value;
+};
+
+NET_EXPORT_PRIVATE bool operator==(const Http2SettingFields& a,
+ const Http2SettingFields& b);
+NET_EXPORT_PRIVATE inline bool operator!=(const Http2SettingFields& a,
+ const Http2SettingFields& b) {
+ return !(a == b);
+}
+NET_EXPORT_PRIVATE std::ostream& operator<<(std::ostream& out,
+ const Http2SettingFields& v);
+
+// Http2PushPromiseFields:
+
+struct Http2PushPromiseFields {
+ static constexpr size_t EncodedSize() { return 4; }
+
+ uint32_t promised_stream_id;
+};
+
+NET_EXPORT_PRIVATE bool operator==(const Http2PushPromiseFields& a,
+ const Http2PushPromiseFields& b);
+NET_EXPORT_PRIVATE inline bool operator!=(const Http2PushPromiseFields& a,
+ const Http2PushPromiseFields& b) {
+ return !(a == b);
+}
+NET_EXPORT_PRIVATE std::ostream& operator<<(std::ostream& out,
+ const Http2PushPromiseFields& v);
+
+// Http2PingFields:
+
+struct Http2PingFields {
+ static constexpr size_t EncodedSize() { return 8; }
+
+ // TODO(jamessynge): Rename opaque_data to opaque_bytes.
+ uint8_t opaque_data[8];
+};
+
+NET_EXPORT_PRIVATE bool operator==(const Http2PingFields& a,
+ const Http2PingFields& b);
+NET_EXPORT_PRIVATE inline bool operator!=(const Http2PingFields& a,
+ const Http2PingFields& b) {
+ return !(a == b);
+}
+NET_EXPORT_PRIVATE std::ostream& operator<<(std::ostream& out,
+ const Http2PingFields& v);
+
+// Http2GoAwayFields:
+
+struct Http2GoAwayFields {
+ Http2GoAwayFields() {}
+ Http2GoAwayFields(uint32_t last_stream_id, Http2ErrorCode error_code)
+ : last_stream_id(last_stream_id), error_code(error_code) {}
+ static constexpr size_t EncodedSize() { return 8; }
+ bool IsSupportedErrorCode() const {
+ return IsSupportedHttp2ErrorCode(error_code);
+ }
+
+ uint32_t last_stream_id;
+ Http2ErrorCode error_code;
+};
+
+NET_EXPORT_PRIVATE bool operator==(const Http2GoAwayFields& a,
+ const Http2GoAwayFields& b);
+NET_EXPORT_PRIVATE inline bool operator!=(const Http2GoAwayFields& a,
+ const Http2GoAwayFields& b) {
+ return !(a == b);
+}
+NET_EXPORT_PRIVATE std::ostream& operator<<(std::ostream& out,
+ const Http2GoAwayFields& v);
+
+// Http2WindowUpdateFields:
+
+struct Http2WindowUpdateFields {
+ static constexpr size_t EncodedSize() { return 4; }
+
+ // 31-bit, unsigned increase in the window size (only positive values are
+ // allowed). The high-bit is reserved for the future.
+ uint32_t window_size_increment;
+};
+
+NET_EXPORT_PRIVATE bool operator==(const Http2WindowUpdateFields& a,
+ const Http2WindowUpdateFields& b);
+NET_EXPORT_PRIVATE inline bool operator!=(const Http2WindowUpdateFields& a,
+ const Http2WindowUpdateFields& b) {
+ return !(a == b);
+}
+NET_EXPORT_PRIVATE std::ostream& operator<<(std::ostream& out,
+ const Http2WindowUpdateFields& v);
+
+// Http2AltSvcFields:
+
+struct Http2AltSvcFields {
+ static constexpr size_t EncodedSize() { return 2; }
+
+ // This is the one fixed size portion of the ALTSVC payload.
+ uint16_t origin_length;
+};
+
+NET_EXPORT_PRIVATE bool operator==(const Http2AltSvcFields& a,
+ const Http2AltSvcFields& b);
+NET_EXPORT_PRIVATE inline bool operator!=(const Http2AltSvcFields& a,
+ const Http2AltSvcFields& b) {
+ return !(a == b);
+}
+NET_EXPORT_PRIVATE std::ostream& operator<<(std::ostream& out,
+ const Http2AltSvcFields& v);
+
+} // namespace net
+
+#endif // NET_HTTP2_HTTP2_STRUCTURES_H_
diff --git a/chromium/net/http2/http2_structures_test.cc b/chromium/net/http2/http2_structures_test.cc
new file mode 100644
index 00000000000..96035c77493
--- /dev/null
+++ b/chromium/net/http2/http2_structures_test.cc
@@ -0,0 +1,486 @@
+// Copyright 2016 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.
+
+#include "net/http2/http2_structures.h"
+
+// Tests are focused on Http2FrameHeader because it has by far the most
+// methods of any of the structures.
+// Note that EXPECT.*DEATH tests are slow (a fork is probably involved).
+
+// And in case you're wondering, yes, these are ridiculously thorough tests,
+// but believe it or not, I've found stupid bugs this way.
+
+#include <memory>
+#include <ostream>
+#include <sstream>
+#include <tuple>
+#include <type_traits>
+#include <vector>
+
+#include "base/template_util.h"
+#include "net/http2/http2_structures_test_util.h"
+#include "net/http2/tools/failure.h"
+#include "net/http2/tools/http2_random.h"
+#include "testing/gmock/include/gmock/gmock.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+using ::testing::AssertionResult;
+using ::testing::AssertionSuccess;
+using ::testing::Combine;
+using ::testing::EndsWith;
+using ::testing::HasSubstr;
+using ::testing::MatchesRegex;
+using ::testing::Not;
+using ::testing::Values;
+using ::testing::ValuesIn;
+
+namespace net {
+namespace test {
+namespace {
+
+template <typename E>
+E IncrementEnum(E e) {
+ typedef typename base::underlying_type<E>::type I;
+ return static_cast<E>(1 + static_cast<I>(e));
+}
+
+#if GTEST_HAS_DEATH_TEST && !defined(NDEBUG)
+std::vector<Http2FrameType> ValidFrameTypes() {
+ std::vector<Http2FrameType> valid_types{Http2FrameType::DATA};
+ while (valid_types.back() != Http2FrameType::ALTSVC) {
+ valid_types.push_back(IncrementEnum(valid_types.back()));
+ }
+ return valid_types;
+}
+#endif // GTEST_HAS_DEATH_TEST && !defined(NDEBUG)
+
+TEST(Http2FrameHeaderTest, Constructor) {
+ Http2Random random;
+ uint8_t frame_type = 0;
+ do {
+ // Only the payload length is DCHECK'd in the constructor, so we need to
+ // make sure it is a "uint24".
+ uint32_t payload_length = random.Rand32() & 0xffffff;
+ Http2FrameType type = static_cast<Http2FrameType>(frame_type);
+ uint8_t flags = random.Rand8();
+ uint32_t stream_id = random.Rand32();
+
+ Http2FrameHeader v(payload_length, type, flags, stream_id);
+
+ EXPECT_EQ(payload_length, v.payload_length);
+ EXPECT_EQ(type, v.type);
+ EXPECT_EQ(flags, v.flags);
+ EXPECT_EQ(stream_id, v.stream_id);
+ } while (frame_type++ == 255);
+
+#if GTEST_HAS_DEATH_TEST && !defined(NDEBUG)
+ EXPECT_DEBUG_DEATH(Http2FrameHeader(0x01000000, Http2FrameType::DATA, 0, 1),
+ "payload_length");
+#endif // GTEST_HAS_DEATH_TEST && !defined(NDEBUG)
+}
+
+TEST(Http2FrameHeaderTest, Eq) {
+ Http2Random random;
+ uint32_t payload_length = random.Rand32() & 0xffffff;
+ Http2FrameType type = static_cast<Http2FrameType>(random.Rand8());
+
+ uint8_t flags = random.Rand8();
+ uint32_t stream_id = random.Rand32();
+
+ Http2FrameHeader v(payload_length, type, flags, stream_id);
+
+ EXPECT_EQ(payload_length, v.payload_length);
+ EXPECT_EQ(type, v.type);
+ EXPECT_EQ(flags, v.flags);
+ EXPECT_EQ(stream_id, v.stream_id);
+
+ Http2FrameHeader u(0, type, ~flags, stream_id);
+
+ EXPECT_NE(u, v);
+ EXPECT_NE(v, u);
+ EXPECT_FALSE(u == v);
+ EXPECT_FALSE(v == u);
+ EXPECT_TRUE(u != v);
+ EXPECT_TRUE(v != u);
+
+ u = v;
+
+ EXPECT_EQ(u, v);
+ EXPECT_EQ(v, u);
+ EXPECT_TRUE(u == v);
+ EXPECT_TRUE(v == u);
+ EXPECT_FALSE(u != v);
+ EXPECT_FALSE(v != u);
+}
+
+#if GTEST_HAS_DEATH_TEST && !defined(NDEBUG)
+// The tests of the valid frame types include EXPECT_DEBUG_DEATH, which is
+// quite slow, so using value parameterized tests in order to allow sharding.
+class Http2FrameHeaderTypeAndFlagTest
+ : public ::testing::TestWithParam<
+ std::tuple<Http2FrameType, Http2FrameFlag>> {
+ protected:
+ Http2FrameHeaderTypeAndFlagTest()
+ : type_(std::get<0>(GetParam())), flags_(std::get<1>(GetParam())) {
+ LOG(INFO) << "Frame type: " << type_;
+ LOG(INFO) << "Frame flags: " << Http2FrameFlagsToString(type_, flags_);
+ }
+
+ const Http2FrameType type_;
+ const Http2FrameFlag flags_;
+};
+
+class IsEndStreamTest : public Http2FrameHeaderTypeAndFlagTest {};
+INSTANTIATE_TEST_CASE_P(IsEndStream,
+ IsEndStreamTest,
+ Combine(ValuesIn(ValidFrameTypes()),
+ Values(~Http2FrameFlag::FLAG_END_STREAM,
+ 0xff)));
+TEST_P(IsEndStreamTest, IsEndStream) {
+ const bool is_set = (flags_ & Http2FrameFlag::FLAG_END_STREAM) ==
+ Http2FrameFlag::FLAG_END_STREAM;
+ LOG(INFO) << "is_set=" << is_set;
+ Http2FrameHeader v(0, type_, flags_, 0);
+ switch (type_) {
+ case Http2FrameType::DATA:
+ case Http2FrameType::HEADERS:
+ EXPECT_EQ(is_set, v.IsEndStream()) << v;
+ if (is_set) {
+ EXPECT_THAT(v.FlagsToString(), MatchesRegex(".*\\|?END_STREAM\\|.*"));
+ } else {
+ EXPECT_THAT(v.FlagsToString(), Not(HasSubstr("END_STREAM")));
+ }
+ v.RetainFlags(Http2FrameFlag::FLAG_END_STREAM);
+ EXPECT_EQ(is_set, v.IsEndStream()) << v;
+ {
+ std::stringstream s;
+ s << v;
+ EXPECT_EQ(v.ToString(), s.str());
+ if (is_set) {
+ EXPECT_THAT(s.str(), HasSubstr("flags=END_STREAM,"));
+ } else {
+ EXPECT_THAT(s.str(), HasSubstr("flags=,"));
+ }
+ }
+ break;
+ default:
+ EXPECT_DEBUG_DEATH(v.IsEndStream(), "DATA.*HEADERS") << v;
+ }
+}
+
+class IsACKTest : public Http2FrameHeaderTypeAndFlagTest {};
+INSTANTIATE_TEST_CASE_P(IsAck,
+ IsACKTest,
+ Combine(ValuesIn(ValidFrameTypes()),
+ Values(~Http2FrameFlag::FLAG_ACK, 0xff)));
+TEST_P(IsACKTest, IsAck) {
+ const bool is_set =
+ (flags_ & Http2FrameFlag::FLAG_ACK) == Http2FrameFlag::FLAG_ACK;
+ LOG(INFO) << "is_set=" << is_set;
+ Http2FrameHeader v(0, type_, flags_, 0);
+ switch (type_) {
+ case Http2FrameType::SETTINGS:
+ case Http2FrameType::PING:
+ EXPECT_EQ(is_set, v.IsAck()) << v;
+ if (is_set) {
+ EXPECT_THAT(v.FlagsToString(), MatchesRegex(".*\\|?ACK\\|.*"));
+ } else {
+ EXPECT_THAT(v.FlagsToString(), Not(HasSubstr("ACK")));
+ }
+ v.RetainFlags(Http2FrameFlag::FLAG_ACK);
+ EXPECT_EQ(is_set, v.IsAck()) << v;
+ {
+ std::stringstream s;
+ s << v;
+ EXPECT_EQ(v.ToString(), s.str());
+ if (is_set) {
+ EXPECT_THAT(s.str(), HasSubstr("flags=ACK,"));
+ } else {
+ EXPECT_THAT(s.str(), HasSubstr("flags=,"));
+ }
+ }
+ break;
+ default:
+ EXPECT_DEBUG_DEATH(v.IsAck(), "SETTINGS.*PING") << v;
+ }
+}
+
+class IsEndHeadersTest : public Http2FrameHeaderTypeAndFlagTest {};
+INSTANTIATE_TEST_CASE_P(IsEndHeaders,
+ IsEndHeadersTest,
+ Combine(ValuesIn(ValidFrameTypes()),
+ Values(~Http2FrameFlag::FLAG_END_HEADERS,
+ 0xff)));
+TEST_P(IsEndHeadersTest, IsEndHeaders) {
+ const bool is_set = (flags_ & Http2FrameFlag::FLAG_END_HEADERS) ==
+ Http2FrameFlag::FLAG_END_HEADERS;
+ LOG(INFO) << "is_set=" << is_set;
+ Http2FrameHeader v(0, type_, flags_, 0);
+ switch (type_) {
+ case Http2FrameType::HEADERS:
+ case Http2FrameType::PUSH_PROMISE:
+ case Http2FrameType::CONTINUATION:
+ EXPECT_EQ(is_set, v.IsEndHeaders()) << v;
+ if (is_set) {
+ EXPECT_THAT(v.FlagsToString(), MatchesRegex(".*\\|?END_HEADERS\\|.*"));
+ } else {
+ EXPECT_THAT(v.FlagsToString(), Not(HasSubstr("END_HEADERS")));
+ }
+ v.RetainFlags(Http2FrameFlag::FLAG_END_HEADERS);
+ EXPECT_EQ(is_set, v.IsEndHeaders()) << v;
+ {
+ std::stringstream s;
+ s << v;
+ EXPECT_EQ(v.ToString(), s.str());
+ if (is_set) {
+ EXPECT_THAT(s.str(), HasSubstr("flags=END_HEADERS,"));
+ } else {
+ EXPECT_THAT(s.str(), HasSubstr("flags=,"));
+ }
+ }
+ break;
+ default:
+ EXPECT_DEBUG_DEATH(v.IsEndHeaders(),
+ "HEADERS.*PUSH_PROMISE.*CONTINUATION")
+ << v;
+ }
+}
+
+class IsPaddedTest : public Http2FrameHeaderTypeAndFlagTest {};
+INSTANTIATE_TEST_CASE_P(IsPadded,
+ IsPaddedTest,
+ Combine(ValuesIn(ValidFrameTypes()),
+ Values(~Http2FrameFlag::FLAG_PADDED, 0xff)));
+TEST_P(IsPaddedTest, IsPadded) {
+ const bool is_set =
+ (flags_ & Http2FrameFlag::FLAG_PADDED) == Http2FrameFlag::FLAG_PADDED;
+ LOG(INFO) << "is_set=" << is_set;
+ Http2FrameHeader v(0, type_, flags_, 0);
+ switch (type_) {
+ case Http2FrameType::DATA:
+ case Http2FrameType::HEADERS:
+ case Http2FrameType::PUSH_PROMISE:
+ EXPECT_EQ(is_set, v.IsPadded()) << v;
+ if (is_set) {
+ EXPECT_THAT(v.FlagsToString(), MatchesRegex(".*\\|?PADDED\\|.*"));
+ } else {
+ EXPECT_THAT(v.FlagsToString(), Not(HasSubstr("PADDED")));
+ }
+ v.RetainFlags(Http2FrameFlag::FLAG_PADDED);
+ EXPECT_EQ(is_set, v.IsPadded()) << v;
+ {
+ std::stringstream s;
+ s << v;
+ EXPECT_EQ(v.ToString(), s.str());
+ if (is_set) {
+ EXPECT_THAT(s.str(), HasSubstr("flags=PADDED,"));
+ } else {
+ EXPECT_THAT(s.str(), HasSubstr("flags=,"));
+ }
+ }
+ break;
+ default:
+ EXPECT_DEBUG_DEATH(v.IsPadded(), "DATA.*HEADERS.*PUSH_PROMISE") << v;
+ }
+}
+
+class HasPriorityTest : public Http2FrameHeaderTypeAndFlagTest {};
+INSTANTIATE_TEST_CASE_P(HasPriority,
+ HasPriorityTest,
+ Combine(ValuesIn(ValidFrameTypes()),
+ Values(~Http2FrameFlag::FLAG_PRIORITY, 0xff)));
+TEST_P(HasPriorityTest, HasPriority) {
+ const bool is_set =
+ (flags_ & Http2FrameFlag::FLAG_PRIORITY) == Http2FrameFlag::FLAG_PRIORITY;
+ LOG(INFO) << "is_set=" << is_set;
+ Http2FrameHeader v(0, type_, flags_, 0);
+ switch (type_) {
+ case Http2FrameType::HEADERS:
+ EXPECT_EQ(is_set, v.HasPriority()) << v;
+ if (is_set) {
+ EXPECT_THAT(v.FlagsToString(), MatchesRegex(".*\\|?PRIORITY\\|.*"));
+ } else {
+ EXPECT_THAT(v.FlagsToString(), Not(HasSubstr("PRIORITY")));
+ }
+ v.RetainFlags(Http2FrameFlag::FLAG_PRIORITY);
+ EXPECT_EQ(is_set, v.HasPriority()) << v;
+ {
+ std::stringstream s;
+ s << v;
+ EXPECT_EQ(v.ToString(), s.str());
+ if (is_set) {
+ EXPECT_THAT(s.str(), HasSubstr("flags=PRIORITY,"));
+ } else {
+ EXPECT_THAT(s.str(), HasSubstr("flags=,"));
+ }
+ }
+ break;
+ default:
+ EXPECT_DEBUG_DEATH(v.HasPriority(), "HEADERS") << v;
+ }
+}
+
+TEST(Http2PriorityFieldsTest, Constructor) {
+ Http2Random random;
+ uint32_t stream_dependency = random.Rand32() & StreamIdMask();
+ uint32_t weight = 1 + random.Rand8();
+ bool is_exclusive = random.OneIn(2);
+
+ Http2PriorityFields v(stream_dependency, weight, is_exclusive);
+
+ EXPECT_EQ(stream_dependency, v.stream_dependency);
+ EXPECT_EQ(weight, v.weight);
+ EXPECT_EQ(is_exclusive, v.is_exclusive);
+
+ // The high-bit must not be set on the stream id.
+ EXPECT_DEBUG_DEATH(
+ Http2PriorityFields(stream_dependency | 0x80000000, weight, is_exclusive),
+ "31-bit");
+
+ // The weight must be in the range 1-256.
+ EXPECT_DEBUG_DEATH(Http2PriorityFields(stream_dependency, 0, is_exclusive),
+ "too small");
+ EXPECT_DEBUG_DEATH(
+ Http2PriorityFields(stream_dependency, weight + 256, is_exclusive),
+ "too large");
+}
+#endif // GTEST_HAS_DEATH_TEST && !defined(NDEBUG)
+
+TEST(Http2RstStreamFieldsTest, IsSupported) {
+ Http2RstStreamFields v{Http2ErrorCode::HTTP2_NO_ERROR};
+ EXPECT_TRUE(v.IsSupportedErrorCode()) << v;
+
+ Http2RstStreamFields u{static_cast<Http2ErrorCode>(~0)};
+ EXPECT_FALSE(u.IsSupportedErrorCode()) << v;
+}
+
+TEST(Http2SettingFieldsTest, Misc) {
+ Http2Random random;
+ Http2SettingsParameter parameter =
+ static_cast<Http2SettingsParameter>(random.Rand16());
+ uint32_t value = random.Rand32();
+
+ Http2SettingFields v(parameter, value);
+
+ EXPECT_EQ(v, v);
+ EXPECT_EQ(parameter, v.parameter);
+ EXPECT_EQ(value, v.value);
+
+ if (static_cast<uint16_t>(parameter) < 7) {
+ EXPECT_TRUE(v.IsSupportedParameter()) << v;
+ } else {
+ EXPECT_FALSE(v.IsSupportedParameter()) << v;
+ }
+
+ Http2SettingFields u(parameter, ~value);
+ EXPECT_NE(v, u);
+ EXPECT_EQ(v.parameter, u.parameter);
+ EXPECT_NE(v.value, u.value);
+
+ Http2SettingFields w(IncrementEnum(parameter), value);
+ EXPECT_NE(v, w);
+ EXPECT_NE(v.parameter, w.parameter);
+ EXPECT_EQ(v.value, w.value);
+
+ Http2SettingFields x(Http2SettingsParameter::MAX_FRAME_SIZE, 123);
+ std::stringstream s;
+ s << x;
+ EXPECT_EQ("parameter=MAX_FRAME_SIZE, value=123", s.str());
+}
+
+TEST(Http2PushPromiseTest, Misc) {
+ Http2Random random;
+ uint32_t promised_stream_id = random.Rand32() & StreamIdMask();
+
+ Http2PushPromiseFields v{promised_stream_id};
+ EXPECT_EQ(promised_stream_id, v.promised_stream_id);
+ EXPECT_EQ(v, v);
+
+ std::stringstream s1;
+ s1 << "promised_stream_id=" << promised_stream_id;
+ std::stringstream s2;
+ s2 << v;
+ EXPECT_EQ(s1.str(), s2.str());
+
+ // High-bit is reserved, but not used, so we can set it.
+ promised_stream_id |= 0x80000000;
+ Http2PushPromiseFields w{promised_stream_id};
+ EXPECT_EQ(w, w);
+ EXPECT_NE(v, w);
+
+ v.promised_stream_id = promised_stream_id;
+ EXPECT_EQ(v, w);
+}
+
+TEST(Http2GoAwayFieldsTest, Misc) {
+ Http2Random random;
+ uint32_t last_stream_id = random.Rand32() & StreamIdMask();
+ Http2ErrorCode error_code = static_cast<Http2ErrorCode>(random.Rand32());
+
+ Http2GoAwayFields v(last_stream_id, error_code);
+ EXPECT_EQ(v, v);
+ EXPECT_EQ(last_stream_id, v.last_stream_id);
+ EXPECT_EQ(error_code, v.error_code);
+
+ if (static_cast<uint32_t>(error_code) < 14) {
+ EXPECT_TRUE(v.IsSupportedErrorCode()) << v;
+ } else {
+ EXPECT_FALSE(v.IsSupportedErrorCode()) << v;
+ }
+
+ Http2GoAwayFields u(~last_stream_id, error_code);
+ EXPECT_NE(v, u);
+ EXPECT_NE(v.last_stream_id, u.last_stream_id);
+ EXPECT_EQ(v.error_code, u.error_code);
+}
+
+TEST(Http2WindowUpdateTest, Misc) {
+ Http2Random random;
+ uint32_t window_size_increment = random.Rand32() & UInt31Mask();
+
+ Http2WindowUpdateFields v{window_size_increment};
+ EXPECT_EQ(window_size_increment, v.window_size_increment);
+ EXPECT_EQ(v, v);
+
+ std::stringstream s1;
+ s1 << "window_size_increment=" << window_size_increment;
+ std::stringstream s2;
+ s2 << v;
+ EXPECT_EQ(s1.str(), s2.str());
+
+ // High-bit is reserved, but not used, so we can set it.
+ window_size_increment |= 0x80000000;
+ Http2WindowUpdateFields w{window_size_increment};
+ EXPECT_EQ(w, w);
+ EXPECT_NE(v, w);
+
+ v.window_size_increment = window_size_increment;
+ EXPECT_EQ(v, w);
+}
+
+TEST(Http2AltSvcTest, Misc) {
+ Http2Random random;
+ uint16_t origin_length = random.Rand16();
+
+ Http2AltSvcFields v{origin_length};
+ EXPECT_EQ(origin_length, v.origin_length);
+ EXPECT_EQ(v, v);
+
+ std::stringstream s1;
+ s1 << "origin_length=" << origin_length;
+ std::stringstream s2;
+ s2 << v;
+ EXPECT_EQ(s1.str(), s2.str());
+
+ Http2AltSvcFields w{++origin_length};
+ EXPECT_EQ(w, w);
+ EXPECT_NE(v, w);
+
+ v.origin_length = w.origin_length;
+ EXPECT_EQ(v, w);
+}
+
+} // namespace
+} // namespace test
+} // namespace net
diff --git a/chromium/net/http2/http2_structures_test_util.cc b/chromium/net/http2/http2_structures_test_util.cc
new file mode 100644
index 00000000000..1e6f4290af3
--- /dev/null
+++ b/chromium/net/http2/http2_structures_test_util.cc
@@ -0,0 +1,107 @@
+// Copyright 2016 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.
+
+#include "net/http2/http2_structures_test_util.h"
+
+#include "net/http2/http2_constants.h"
+#include "net/http2/http2_constants_test_util.h"
+#include "net/http2/http2_structures.h"
+#include "net/http2/tools/http2_random.h"
+
+namespace net {
+namespace test {
+
+void Randomize(Http2FrameHeader* p, RandomBase* rng) {
+ p->payload_length = rng->Rand32() & 0xffffff;
+ p->type = static_cast<Http2FrameType>(rng->Rand8());
+ p->flags = static_cast<Http2FrameFlag>(rng->Rand8());
+ p->stream_id = rng->Rand32() & StreamIdMask();
+}
+void Randomize(Http2PriorityFields* p, RandomBase* rng) {
+ p->stream_dependency = rng->Rand32() & StreamIdMask();
+ p->weight = rng->Rand8() + 1;
+ p->is_exclusive = rng->OneIn(2);
+}
+void Randomize(Http2RstStreamFields* p, RandomBase* rng) {
+ p->error_code = static_cast<Http2ErrorCode>(rng->Rand32());
+}
+void Randomize(Http2SettingFields* p, RandomBase* rng) {
+ p->parameter = static_cast<Http2SettingsParameter>(rng->Rand16());
+ p->value = rng->Rand32();
+}
+void Randomize(Http2PushPromiseFields* p, RandomBase* rng) {
+ p->promised_stream_id = rng->Rand32() & StreamIdMask();
+}
+void Randomize(Http2PingFields* p, RandomBase* rng) {
+ for (int ndx = 0; ndx < 8; ++ndx) {
+ p->opaque_data[ndx] = rng->Rand8();
+ }
+}
+void Randomize(Http2GoAwayFields* p, RandomBase* rng) {
+ p->last_stream_id = rng->Rand32() & StreamIdMask();
+ p->error_code = static_cast<Http2ErrorCode>(rng->Rand32());
+}
+void Randomize(Http2WindowUpdateFields* p, RandomBase* rng) {
+ p->window_size_increment = rng->Rand32() & 0x7fffffff;
+}
+void Randomize(Http2AltSvcFields* p, RandomBase* rng) {
+ p->origin_length = rng->Rand16();
+}
+
+void ScrubFlagsOfHeader(Http2FrameHeader* header) {
+ uint8_t invalid_mask = InvalidFlagMaskForFrameType(header->type);
+ uint8_t keep_mask = ~invalid_mask;
+ header->RetainFlags(keep_mask);
+}
+
+bool FrameIsPadded(const Http2FrameHeader& header) {
+ switch (header.type) {
+ case Http2FrameType::DATA:
+ case Http2FrameType::HEADERS:
+ case Http2FrameType::PUSH_PROMISE:
+ return header.IsPadded();
+ default:
+ return false;
+ }
+}
+
+bool FrameHasPriority(const Http2FrameHeader& header) {
+ switch (header.type) {
+ case Http2FrameType::HEADERS:
+ return header.HasPriority();
+ case Http2FrameType::PRIORITY:
+ return true;
+ default:
+ return false;
+ }
+}
+
+bool FrameCanHavePayload(const Http2FrameHeader& header) {
+ switch (header.type) {
+ case Http2FrameType::DATA:
+ case Http2FrameType::HEADERS:
+ case Http2FrameType::PUSH_PROMISE:
+ case Http2FrameType::CONTINUATION:
+ case Http2FrameType::PING:
+ case Http2FrameType::GOAWAY:
+ case Http2FrameType::ALTSVC:
+ return true;
+ default:
+ return false;
+ }
+}
+
+bool FrameCanHaveHpackPayload(const Http2FrameHeader& header) {
+ switch (header.type) {
+ case Http2FrameType::HEADERS:
+ case Http2FrameType::PUSH_PROMISE:
+ case Http2FrameType::CONTINUATION:
+ return true;
+ default:
+ return false;
+ }
+}
+
+} // namespace test
+} // namespace net
diff --git a/chromium/net/http2/http2_structures_test_util.h b/chromium/net/http2/http2_structures_test_util.h
new file mode 100644
index 00000000000..710a530ddc0
--- /dev/null
+++ b/chromium/net/http2/http2_structures_test_util.h
@@ -0,0 +1,61 @@
+// Copyright 2016 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.
+
+#ifndef NET_HTTP2_HTTP2_STRUCTURES_TEST_UTIL_H_
+#define NET_HTTP2_HTTP2_STRUCTURES_TEST_UTIL_H_
+
+#include <string>
+
+#include "net/http2/http2_structures.h"
+#include "net/http2/tools/http2_frame_builder.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace net {
+namespace test {
+
+class RandomBase;
+
+template <class S>
+std::string SerializeStructure(const S& s) {
+ Http2FrameBuilder fb;
+ fb.Append(s);
+ EXPECT_EQ(S::EncodedSize(), fb.size());
+ return fb.buffer();
+}
+
+// Randomize the members of out, in a manner that yields encodeable contents
+// (e.g. a "uint24" field has only the low 24 bits set).
+void Randomize(Http2FrameHeader* out, RandomBase* rng);
+void Randomize(Http2PriorityFields* out, RandomBase* rng);
+void Randomize(Http2RstStreamFields* out, RandomBase* rng);
+void Randomize(Http2SettingFields* out, RandomBase* rng);
+void Randomize(Http2PushPromiseFields* out, RandomBase* rng);
+void Randomize(Http2PingFields* out, RandomBase* rng);
+void Randomize(Http2GoAwayFields* out, RandomBase* rng);
+void Randomize(Http2WindowUpdateFields* out, RandomBase* rng);
+void Randomize(Http2AltSvcFields* out, RandomBase* rng);
+
+// Clear bits of header->flags that are known to be invalid for the
+// type. For unknown frame types, no change is made.
+void ScrubFlagsOfHeader(Http2FrameHeader* header);
+
+// Is the frame with this header padded? Only true for known/supported frame
+// types.
+bool FrameIsPadded(const Http2FrameHeader& header);
+
+// Does the frame with this header have Http2PriorityFields?
+bool FrameHasPriority(const Http2FrameHeader& header);
+
+// Does the frame with this header have a variable length payload (including
+// empty) payload (e.g. DATA or HEADERS)? Really a test of the frame type.
+bool FrameCanHavePayload(const Http2FrameHeader& header);
+
+// Does the frame with this header have a variable length HPACK payload
+// (including empty) payload (e.g. HEADERS)? Really a test of the frame type.
+bool FrameCanHaveHpackPayload(const Http2FrameHeader& header);
+
+} // namespace test
+} // namespace net
+
+#endif // NET_HTTP2_HTTP2_STRUCTURES_TEST_UTIL_H_
diff --git a/chromium/net/http2/tools/failure.cc b/chromium/net/http2/tools/failure.cc
new file mode 100644
index 00000000000..b354be1e56f
--- /dev/null
+++ b/chromium/net/http2/tools/failure.cc
@@ -0,0 +1,29 @@
+// Copyright 2016 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.
+
+#include "net/http2/tools/failure.h"
+
+namespace net {
+namespace test {
+
+// This is a copy of the same named method in ::testing::internal.
+// TODO(jamessynge): See about getting something like VERIFY_* adopted by
+// gUnit (probably a very difficult task!).
+std::string GetBoolAssertionFailureMessage(
+ const ::testing::AssertionResult& assertion_result,
+ const char* expression_text,
+ const char* actual_predicate_value,
+ const char* expected_predicate_value) {
+ const char* actual_message = assertion_result.message();
+ ::testing::Message msg;
+ msg << "Value of: " << expression_text
+ << "\n Actual: " << actual_predicate_value;
+ if (actual_message[0] != '\0')
+ msg << " (" << actual_message << ")";
+ msg << "\nExpected: " << expected_predicate_value;
+ return msg.GetString();
+}
+
+} // namespace test
+} // namespace net
diff --git a/chromium/net/http2/tools/failure.h b/chromium/net/http2/tools/failure.h
new file mode 100644
index 00000000000..aa36d79f56e
--- /dev/null
+++ b/chromium/net/http2/tools/failure.h
@@ -0,0 +1,154 @@
+// Copyright 2016 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.
+
+#ifndef NET_HTTP2_TOOLS_FAILURE_H_
+#define NET_HTTP2_TOOLS_FAILURE_H_
+
+// Defines VERIFY_* macros, analogous to gUnit's EXPECT_* and ASSERT_* macros,
+// but these return an appropriate AssertionResult if the condition is not
+// satisfied. This enables one to create a function for verifying expectations
+// that are needed by multiple callers or that rely on arguments not accessible
+// to the main test method. Using VERIFY_SUCCESS allows one to annotate the
+// a failing AssertionResult with more context.
+
+#include <iosfwd>
+#include <sstream>
+#include <string>
+
+#include "base/macros.h"
+#include "testing/gmock/include/gmock/gmock.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace net {
+namespace test {
+
+template <typename T>
+class VerifyThatHelper {
+ public:
+ VerifyThatHelper(const T& value, ::testing::Matcher<T> matcher) {
+ matches_ = matcher.Matches(value);
+ if (!matches_) {
+ printed_value_ = ::testing::PrintToString(value);
+
+ std::ostringstream os;
+ matcher.DescribeTo(&os);
+ matcher_description_ = os.str();
+ }
+ }
+
+ operator bool() const { return matches_; }
+
+ const std::string& printed_value() const { return printed_value_; }
+ const std::string& matcher_description() const {
+ return matcher_description_;
+ }
+
+ private:
+ bool matches_;
+ std::string printed_value_;
+ std::string matcher_description_;
+
+ DISALLOW_COPY_AND_ASSIGN(VerifyThatHelper);
+};
+
+// Constructs a failure message for Boolean assertions such as VERIFY_TRUE.
+std::string GetBoolAssertionFailureMessage(
+ const ::testing::AssertionResult& assertion_result,
+ const char* expression_text,
+ const char* actual_predicate_value,
+ const char* expected_predicate_value);
+
+} // namespace test
+} // namespace net
+
+// Macro for adding verification location to output stream or AssertionResult.
+// Starts with a new-line because of the way that gUnit displays failures for
+// EXPECT_TRUE(CallToFunctionThatFailsToVerify()).
+#define VERIFY_FAILED_LOCATION_ \
+ "\n" \
+ << "(VERIFY failed in " << __func__ << "\n" \
+ << " at " __FILE__ " : " << __LINE__ << ")\n"
+
+// Implements Boolean test verifications VERIFY_TRUE and VERIFY_FALSE.
+// text is a textual represenation of expression as it was passed into
+// VERIFY_TRUE or VERIFY_FALSE.
+// clang-format off
+#define VERIFY_TEST_BOOLEAN_(condition, text, actual, expected) \
+ if (const ::testing::AssertionResult __assertion_result = \
+ ::testing::AssertionResult((condition) ? expected : actual)) \
+ ; \
+ else \
+ return ::testing::AssertionFailure() \
+ << VERIFY_FAILED_LOCATION_ \
+ << ::net::test::GetBoolAssertionFailureMessage( \
+ __assertion_result, text, #actual, #expected)
+// clang-format on
+
+// Boolean assertions. condition can be either a Boolean expression or an
+// expression convertable to a boolean (such as a ::gtl::labs::optional).
+#define VERIFY_TRUE(condition) \
+ VERIFY_TEST_BOOLEAN_(condition, #condition, false, true)
+
+#define VERIFY_FALSE(condition) \
+ VERIFY_TEST_BOOLEAN_(condition, #condition, true, false)
+
+// Convenient helper macro for writing methods that return an AssertionFailure
+// that includes the tested condition in the message (in the manner of
+// ASSERT_THAT and EXPECT_THAT).
+//
+// This macro avoids the do {} while(false) trick and putting braces around
+// the if so you can do things like:
+// VERIFY_THAT(foo, Lt(4)) << "foo too big in iteration " << i;
+// (This parallels the implementation of CHECK().)
+//
+// We use an if statement with an empty true branch so that this doesn't eat
+// a neighboring else when used in an unbraced if statement like:
+// if (condition)
+// VERIFY_THAT(foo, Eq(bar));
+// else
+// FAIL();
+#define VERIFY_THAT(value, matcher) \
+ if (const auto& _verify_that_helper = \
+ ::net::test::VerifyThatHelper<decltype(value)>(value, matcher)) \
+ ; \
+ else \
+ return ::testing::AssertionFailure() \
+ << "Failed to verify that '" #value "' (" \
+ << _verify_that_helper.printed_value() << ") " \
+ << _verify_that_helper.matcher_description() \
+ << " (on " __FILE__ ":" << __LINE__ << "). "
+
+// Useful variants of VERIFY_THAT, similar to the corresponding EXPECT_X or
+// ASSERT_X defined by gUnit.
+#define VERIFY_EQ(val1, val2) VERIFY_THAT(val1, ::testing::Eq(val2))
+#define VERIFY_NE(val1, val2) VERIFY_THAT(val1, ::testing::Ne(val2))
+#define VERIFY_GT(val1, val2) VERIFY_THAT(val1, ::testing::Gt(val2))
+#define VERIFY_LT(val1, val2) VERIFY_THAT(val1, ::testing::Lt(val2))
+#define VERIFY_GE(val1, val2) VERIFY_THAT(val1, ::testing::Ge(val2))
+#define VERIFY_LE(val1, val2) VERIFY_THAT(val1, ::testing::Le(val2))
+
+// Convenience macro matching EXPECT_OK
+#define VERIFY_OK(statement) VERIFY_EQ(::util::Status::OK, (statement))
+
+// This version verifies that an expression of type AssertionResult is
+// AssertionSuccess. If instead the value is an AssertionFailure, it appends
+// info about the current code location to the failure's message and returns
+// the failure to the caller of the current method. It permits the code site
+// to append further messages to the failure message. For example:
+// VERIFY_SUCCESS(SomeCall()) << "Some more context about SomeCall";
+// clang-format off
+#define VERIFY_SUCCESS(expr) \
+ if (::testing::AssertionResult __assertion_result = (expr)) \
+ ; \
+ else \
+ return __assertion_result << VERIFY_FAILED_LOCATION_
+// clang-format on
+
+#define VERIFY_AND_RETURN_SUCCESS(expression) \
+ { \
+ VERIFY_SUCCESS(expression); \
+ return ::testing::AssertionSuccess(); \
+ }
+
+#endif // NET_HTTP2_TOOLS_FAILURE_H_
diff --git a/chromium/net/http2/tools/http2_bug_tracker.h b/chromium/net/http2/tools/http2_bug_tracker.h
new file mode 100644
index 00000000000..0e31bc2aaef
--- /dev/null
+++ b/chromium/net/http2/tools/http2_bug_tracker.h
@@ -0,0 +1,14 @@
+// Copyright 2016 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.
+
+#ifndef NET_HTTP2_TOOLS_HTTP2_BUG_TRACKER_H_
+#define NET_HTTP2_TOOLS_HTTP2_BUG_TRACKER_H_
+
+#include "base/logging.h"
+
+#define HTTP2_BUG LOG(DFATAL)
+#define HTTP2_BUG_IF LOG_IF(DFATAL, (condition))
+#define FLAGS_http2_always_log_bugs_for_tests (true)
+
+#endif // NET_HTTP2_TOOLS_HTTP2_BUG_TRACKER_H_
diff --git a/chromium/net/http2/tools/http2_frame_builder.cc b/chromium/net/http2/tools/http2_frame_builder.cc
new file mode 100644
index 00000000000..c072525e34a
--- /dev/null
+++ b/chromium/net/http2/tools/http2_frame_builder.cc
@@ -0,0 +1,182 @@
+// Copyright 2016 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.
+
+#include "net/http2/tools/http2_frame_builder.h"
+
+#ifdef WIN32
+#include <winsock2.h> // for htonl() functions
+#else
+#include <arpa/inet.h>
+#include <netinet/in.h> // for htonl, htons
+#endif
+
+#include "testing/gtest/include/gtest/gtest.h"
+
+using base::StringPiece;
+
+namespace net {
+namespace test {
+
+Http2FrameBuilder::Http2FrameBuilder(Http2FrameType type,
+ uint8_t flags,
+ uint32_t stream_id) {
+ AppendUInt24(0); // Frame payload length, unknown so far.
+ Append(type);
+ AppendUInt8(flags);
+ AppendUInt31(stream_id);
+}
+
+Http2FrameBuilder::Http2FrameBuilder(const Http2FrameHeader& v) {
+ Append(v);
+}
+
+void Http2FrameBuilder::Append(StringPiece s) {
+ s.AppendToString(&buffer_);
+}
+
+void Http2FrameBuilder::AppendBytes(const void* data, uint32_t num_bytes) {
+ Append(StringPiece(static_cast<const char*>(data), num_bytes));
+}
+
+void Http2FrameBuilder::AppendZeroes(size_t num_zero_bytes) {
+ char zero = 0;
+ buffer_.append(num_zero_bytes, zero);
+}
+
+void Http2FrameBuilder::AppendUInt8(uint8_t value) {
+ AppendBytes(&value, 1);
+}
+
+void Http2FrameBuilder::AppendUInt16(uint16_t value) {
+ value = htons(value);
+ AppendBytes(&value, 2);
+}
+
+void Http2FrameBuilder::AppendUInt24(uint32_t value) {
+ // Doesn't make sense to try to append a larger value, as that doesn't
+ // simulate something an encoder could do (i.e. the other 8 bits simply aren't
+ // there to be occupied).
+ EXPECT_EQ(value, value & 0xffffff);
+ value = htonl(value);
+ AppendBytes(reinterpret_cast<char*>(&value) + 1, 3);
+}
+
+void Http2FrameBuilder::AppendUInt31(uint32_t value) {
+ // If you want to test the high-bit being set, call AppendUInt32 instead.
+ uint32_t tmp = value & StreamIdMask();
+ EXPECT_EQ(value, value & StreamIdMask())
+ << "High-bit of uint32 should be clear.";
+ value = htonl(tmp);
+ AppendBytes(&value, 4);
+}
+
+void Http2FrameBuilder::AppendUInt32(uint32_t value) {
+ value = htonl(value);
+ AppendBytes(&value, sizeof(value));
+}
+
+void Http2FrameBuilder::Append(Http2ErrorCode error_code) {
+ AppendUInt32(static_cast<uint32_t>(error_code));
+}
+
+void Http2FrameBuilder::Append(Http2FrameType type) {
+ AppendUInt8(static_cast<uint8_t>(type));
+}
+
+void Http2FrameBuilder::Append(Http2SettingsParameter parameter) {
+ AppendUInt16(static_cast<uint16_t>(parameter));
+}
+
+void Http2FrameBuilder::Append(const Http2FrameHeader& v) {
+ AppendUInt24(v.payload_length);
+ Append(v.type);
+ AppendUInt8(v.flags);
+ AppendUInt31(v.stream_id);
+}
+
+void Http2FrameBuilder::Append(const Http2PriorityFields& v) {
+ // The EXCLUSIVE flag is the high-bit of the 32-bit stream dependency field.
+ uint32_t tmp = v.stream_dependency & StreamIdMask();
+ EXPECT_EQ(tmp, v.stream_dependency);
+ if (v.is_exclusive) {
+ tmp |= 0x80000000;
+ }
+ AppendUInt32(tmp);
+
+ // The PRIORITY frame's weight field is logically in the range [1, 256],
+ // but is encoded as a byte in the range [0, 255].
+ ASSERT_LE(1u, v.weight);
+ ASSERT_LE(v.weight, 256u);
+ AppendUInt8(v.weight - 1);
+}
+
+void Http2FrameBuilder::Append(const Http2RstStreamFields& v) {
+ Append(v.error_code);
+}
+
+void Http2FrameBuilder::Append(const Http2SettingFields& v) {
+ Append(v.parameter);
+ AppendUInt32(v.value);
+}
+
+void Http2FrameBuilder::Append(const Http2PushPromiseFields& v) {
+ AppendUInt31(v.promised_stream_id);
+}
+
+void Http2FrameBuilder::Append(const Http2PingFields& v) {
+ AppendBytes(v.opaque_data, sizeof Http2PingFields::opaque_data);
+}
+
+void Http2FrameBuilder::Append(const Http2GoAwayFields& v) {
+ AppendUInt31(v.last_stream_id);
+ Append(v.error_code);
+}
+
+void Http2FrameBuilder::Append(const Http2WindowUpdateFields& v) {
+ EXPECT_NE(0u, v.window_size_increment) << "Increment must be non-zero.";
+ AppendUInt31(v.window_size_increment);
+}
+
+void Http2FrameBuilder::Append(const Http2AltSvcFields& v) {
+ AppendUInt16(v.origin_length);
+}
+
+// Methods for changing existing buffer contents.
+
+void Http2FrameBuilder::WriteAt(StringPiece s, size_t offset) {
+ ASSERT_LE(offset, buffer_.size());
+ size_t len = offset + s.size();
+ if (len > buffer_.size()) {
+ buffer_.resize(len);
+ }
+ for (size_t ndx = 0; ndx < s.size(); ++ndx) {
+ buffer_[offset + ndx] = s[ndx];
+ }
+}
+
+void Http2FrameBuilder::WriteBytesAt(const void* data,
+ uint32_t num_bytes,
+ size_t offset) {
+ WriteAt(StringPiece(static_cast<const char*>(data), num_bytes), offset);
+}
+
+void Http2FrameBuilder::WriteUInt24At(uint32_t value, size_t offset) {
+ ASSERT_LT(value, static_cast<uint32_t>(1 << 24));
+ value = htonl(value);
+ WriteBytesAt(reinterpret_cast<char*>(&value) + 1, sizeof(value) - 1, offset);
+}
+
+void Http2FrameBuilder::SetPayloadLength(uint32_t payload_length) {
+ WriteUInt24At(payload_length, 0);
+}
+
+size_t Http2FrameBuilder::SetPayloadLength() {
+ EXPECT_GE(size(), Http2FrameHeader::EncodedSize());
+ uint32_t payload_length = size() - Http2FrameHeader::EncodedSize();
+ SetPayloadLength(payload_length);
+ return payload_length;
+}
+
+} // namespace test
+} // namespace net
diff --git a/chromium/net/http2/tools/http2_frame_builder.h b/chromium/net/http2/tools/http2_frame_builder.h
new file mode 100644
index 00000000000..c665c759e1d
--- /dev/null
+++ b/chromium/net/http2/tools/http2_frame_builder.h
@@ -0,0 +1,100 @@
+// Copyright 2016 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.
+
+#ifndef NET_HTTP2_TOOLS_HTTP2_FRAME_BUILDER_H_
+#define NET_HTTP2_TOOLS_HTTP2_FRAME_BUILDER_H_
+
+// Http2FrameBuilder builds wire-format HTTP/2 frames (or fragments thereof)
+// from components.
+//
+// For now, this is only intended for use in tests, and thus has EXPECT* in the
+// code. If desired to use it in an encoder, it will need optimization work,
+// especially w.r.t memory mgmt, and the EXPECT* will need to be removed or
+// replaced with DCHECKs.
+
+#include <stddef.h> // for size_t
+
+#include <string>
+
+#include "base/strings/string_piece.h"
+#include "net/http2/http2_constants.h"
+#include "net/http2/http2_structures.h"
+
+namespace net {
+namespace test {
+
+class Http2FrameBuilder {
+ public:
+ Http2FrameBuilder(Http2FrameType type, uint8_t flags, uint32_t stream_id);
+ explicit Http2FrameBuilder(const Http2FrameHeader& v);
+ Http2FrameBuilder() {}
+ ~Http2FrameBuilder() {}
+
+ size_t size() const { return buffer_.size(); }
+ const std::string& buffer() const { return buffer_; }
+
+ //----------------------------------------------------------------------------
+ // Methods for appending to the end of the buffer.
+
+ // Append a sequence of bytes from various sources.
+ void Append(base::StringPiece s);
+ void AppendBytes(const void* data, uint32_t num_bytes);
+
+ // Append an array of type T[N] to the string. Intended for tests with arrays
+ // initialized from literals, such as:
+ // const char kData[] = {0x12, 0x23, ...};
+ // builder.AppendBytes(kData);
+ template <typename T, size_t N>
+ void AppendBytes(T (&buf)[N]) {
+ AppendBytes(buf, N * sizeof(buf[0]));
+ }
+
+ // Support for appending padding. Does not read or write the Pad Length field.
+ void AppendZeroes(size_t num_zero_bytes);
+
+ // Append various sizes of unsigned integers.
+ void AppendUInt8(uint8_t value);
+ void AppendUInt16(uint16_t value);
+ void AppendUInt24(uint32_t value);
+ void AppendUInt31(uint32_t value);
+ void AppendUInt32(uint32_t value);
+
+ // Append various enums.
+ void Append(Http2ErrorCode error_code);
+ void Append(Http2FrameType type);
+ void Append(Http2SettingsParameter parameter);
+
+ // Append various structures.
+ void Append(const Http2FrameHeader& v);
+ void Append(const Http2PriorityFields& v);
+ void Append(const Http2RstStreamFields& v);
+ void Append(const Http2SettingFields& v);
+ void Append(const Http2PushPromiseFields& v);
+ void Append(const Http2PingFields& v);
+ void Append(const Http2GoAwayFields& v);
+ void Append(const Http2WindowUpdateFields& v);
+ void Append(const Http2AltSvcFields& v);
+
+ // Methods for changing existing buffer contents (mostly focused on updating
+ // the payload length).
+
+ void WriteAt(base::StringPiece s, size_t offset);
+ void WriteBytesAt(const void* data, uint32_t num_bytes, size_t offset);
+ void WriteUInt24At(uint32_t value, size_t offset);
+
+ // Set the payload length to the specified size.
+ void SetPayloadLength(uint32_t payload_length);
+
+ // Sets the payload length to the size of the buffer minus the size of
+ // the frame header.
+ size_t SetPayloadLength();
+
+ private:
+ std::string buffer_;
+};
+
+} // namespace test
+} // namespace net
+
+#endif // NET_HTTP2_TOOLS_HTTP2_FRAME_BUILDER_H_
diff --git a/chromium/net/http2/tools/http2_random.cc b/chromium/net/http2/tools/http2_random.cc
new file mode 100644
index 00000000000..12dd74361e3
--- /dev/null
+++ b/chromium/net/http2/tools/http2_random.cc
@@ -0,0 +1,58 @@
+// Copyright 2016 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.
+
+#include "net/http2/tools/http2_random.h"
+
+#include <memory>
+
+#include "base/rand_util.h"
+
+namespace net {
+namespace test {
+
+bool Http2Random::OneIn(int n) {
+ return base::RandGenerator(n) == 0;
+}
+
+int32_t Http2Random::Uniform(int32_t n) {
+ return base::RandGenerator(n);
+}
+
+uint8_t Http2Random::Rand8() {
+ return base::RandGenerator(
+ static_cast<uint64_t>(std::numeric_limits<uint8_t>::max()) + 1);
+}
+
+uint16_t Http2Random::Rand16() {
+ return base::RandGenerator(
+ static_cast<uint64_t>(std::numeric_limits<uint16_t>::max()) + 1);
+}
+
+uint32_t Http2Random::Rand32() {
+ return base::RandGenerator(
+ static_cast<uint64_t>(std::numeric_limits<uint32_t>::max()) + 1);
+}
+
+uint64_t Http2Random::Rand64() {
+ return base::RandUint64();
+}
+
+int32_t Http2Random::Next() {
+ return Rand32();
+}
+
+int32_t Http2Random::Skewed(int max_log) {
+ const uint32_t base = Rand32() % (max_log + 1);
+ const uint32_t mask = ((base < 32) ? (1u << base) : 0u) - 1u;
+ return Rand32() & mask;
+}
+
+std::string Http2Random::RandString(int length) {
+ std::unique_ptr<char[]> buffer(new char[length]);
+ base::RandBytes(buffer.get(), length);
+ return std::string(buffer.get(), length);
+}
+
+} // namespace test
+} // namespace net
diff --git a/chromium/net/http2/tools/http2_random.h b/chromium/net/http2/tools/http2_random.h
new file mode 100644
index 00000000000..eb3f6aa7d11
--- /dev/null
+++ b/chromium/net/http2/tools/http2_random.h
@@ -0,0 +1,57 @@
+// Copyright 2016 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.
+
+#ifndef NET_HTTP2_TOOLS_HTTP2_RANDOM_H_
+#define NET_HTTP2_TOOLS_HTTP2_RANDOM_H_
+
+#include <stdint.h>
+
+#include <limits>
+#include <string>
+
+namespace net {
+namespace test {
+
+class RandomBase {
+ public:
+ virtual ~RandomBase() {}
+ virtual bool OneIn(int n) = 0;
+ virtual int32_t Uniform(int32_t n) = 0;
+ virtual uint8_t Rand8() = 0;
+ virtual uint16_t Rand16() = 0;
+ virtual uint32_t Rand32() = 0;
+ virtual uint64_t Rand64() = 0;
+ virtual int32_t Next() = 0;
+ virtual int32_t Skewed(int max_log) = 0;
+ virtual std::string RandString(int length) = 0;
+
+ // STL UniformRandomNumberGenerator implementation.
+ typedef uint32_t result_type;
+ static constexpr result_type min() { return 0; }
+ static constexpr result_type max() {
+ return std::numeric_limits<uint32_t>::max();
+ }
+ result_type operator()() { return Rand32(); }
+};
+
+// Http2Random holds no state: instances use the same base::RandGenerator
+// with a global state.
+class Http2Random : public RandomBase {
+ public:
+ ~Http2Random() override {}
+ bool OneIn(int n) override;
+ int32_t Uniform(int32_t n) override;
+ uint8_t Rand8() override;
+ uint16_t Rand16() override;
+ uint32_t Rand32() override;
+ uint64_t Rand64() override;
+ int32_t Next() override;
+ int32_t Skewed(int max_log) override;
+ std::string RandString(int length) override;
+};
+
+} // namespace test
+} // namespace net
+
+#endif // NET_HTTP2_TOOLS_HTTP2_RANDOM_H_
diff --git a/chromium/net/http2/tools/random_decoder_test.cc b/chromium/net/http2/tools/random_decoder_test.cc
new file mode 100644
index 00000000000..224a825b612
--- /dev/null
+++ b/chromium/net/http2/tools/random_decoder_test.cc
@@ -0,0 +1,178 @@
+// Copyright 2016 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.
+
+#include "net/http2/tools/random_decoder_test.h"
+
+#include <stddef.h>
+
+#include <algorithm>
+#include <memory>
+
+#include "base/logging.h"
+#include "base/strings/string_number_conversions.h"
+#include "base/strings/string_piece.h"
+#include "net/http2/decoder/decode_buffer.h"
+#include "net/http2/decoder/decode_status.h"
+#include "net/http2/http2_constants.h"
+#include "net/http2/tools/failure.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+// It's rather time consuming to decode large buffers one at a time,
+// especially with the log level cranked up. So, by default we don't do
+// that unless explicitly requested.
+
+using ::testing::AssertionFailure;
+using ::testing::AssertionResult;
+using ::testing::AssertionSuccess;
+using base::StringPiece;
+
+namespace net {
+namespace test {
+
+std::string HexEncode(StringPiece s) {
+ return base::HexEncode(s.data(), s.size());
+}
+
+RandomDecoderTest::RandomDecoderTest() {}
+
+bool RandomDecoderTest::StopDecodeOnDone() {
+ return stop_decode_on_done_;
+}
+
+DecodeStatus RandomDecoderTest::DecodeSegments(DecodeBuffer* original,
+ const SelectSize& select_size) {
+ DecodeStatus status = DecodeStatus::kDecodeInProgress;
+ bool first = true;
+ VLOG(2) << "DecodeSegments: input size=" << original->Remaining();
+ while (first || original->HasData()) {
+ size_t remaining = original->Remaining();
+ size_t size =
+ std::min(remaining, select_size(first, original->Offset(), remaining));
+ DecodeBuffer db(original->cursor(), size);
+ VLOG(2) << "Decoding " << size << " bytes of " << remaining << " remaining";
+ if (first) {
+ first = false;
+ status = StartDecoding(&db);
+ } else {
+ status = ResumeDecoding(&db);
+ }
+ // A decoder MUST consume some input (if any is available), else we could
+ // get stuck in infinite loops.
+ if (db.Offset() == 0 && db.HasData() &&
+ status != DecodeStatus::kDecodeError) {
+ ADD_FAILURE() << "Decoder didn't make any progress; db.FullSize="
+ << db.FullSize()
+ << " original.Offset=" << original->Offset();
+ return DecodeStatus::kDecodeError;
+ }
+ original->AdvanceCursor(db.Offset());
+ switch (status) {
+ case DecodeStatus::kDecodeDone:
+ if (original->Empty() || StopDecodeOnDone()) {
+ return DecodeStatus::kDecodeDone;
+ }
+ continue;
+ case DecodeStatus::kDecodeInProgress:
+ continue;
+ case DecodeStatus::kDecodeError:
+ return DecodeStatus::kDecodeError;
+ }
+ }
+ return status;
+}
+
+// Decode |original| multiple times, with different segmentations, validating
+// after each decode, returning on the first failure.
+AssertionResult RandomDecoderTest::DecodeAndValidateSeveralWays(
+ DecodeBuffer* original,
+ bool return_non_zero_on_first,
+ const Validator& validator) {
+ const uint32_t original_remaining = original->Remaining();
+ VLOG(1) << "DecodeAndValidateSeveralWays - Start, remaining = "
+ << original_remaining;
+ uint32_t first_consumed;
+ {
+ // Fast decode (no stopping unless decoder does so).
+ DecodeBuffer input(original->cursor(), original_remaining);
+ VLOG(2) << "DecodeSegmentsAndValidate with SelectRemaining";
+ VERIFY_SUCCESS(
+ DecodeSegmentsAndValidate(&input, SelectRemaining(), validator))
+ << "\nFailed with SelectRemaining; input.Offset=" << input.Offset()
+ << "; input.Remaining=" << input.Remaining();
+ first_consumed = input.Offset();
+ }
+ if (original_remaining <= 30) {
+ // Decode again, one byte at a time.
+ DecodeBuffer input(original->cursor(), original_remaining);
+ VLOG(2) << "DecodeSegmentsAndValidate with SelectOne";
+ VERIFY_SUCCESS(DecodeSegmentsAndValidate(&input, SelectOne(), validator))
+ << "\nFailed with SelectOne; input.Offset=" << input.Offset()
+ << "; input.Remaining=" << input.Remaining();
+ VERIFY_EQ(first_consumed, input.Offset()) << "\nFailed with SelectOne";
+ }
+ if (original_remaining <= 20) {
+ // Decode again, one or zero bytes at a time.
+ DecodeBuffer input(original->cursor(), original_remaining);
+ VLOG(2) << "DecodeSegmentsAndValidate with SelectZeroAndOne";
+ VERIFY_SUCCESS(DecodeSegmentsAndValidate(
+ &input, SelectZeroAndOne(return_non_zero_on_first), validator))
+ << "\nFailed with SelectZeroAndOne";
+ VERIFY_EQ(first_consumed, input.Offset())
+ << "\nFailed with SelectZeroAndOne; input.Offset=" << input.Offset()
+ << "; input.Remaining=" << input.Remaining();
+ }
+ {
+ // Decode again, with randomly selected segment sizes.
+ DecodeBuffer input(original->cursor(), original_remaining);
+ VLOG(2) << "DecodeSegmentsAndValidate with SelectRandom";
+ VERIFY_SUCCESS(DecodeSegmentsAndValidate(
+ &input, SelectRandom(return_non_zero_on_first), validator))
+ << "\nFailed with SelectRandom; input.Offset=" << input.Offset()
+ << "; input.Remaining=" << input.Remaining();
+ VERIFY_EQ(first_consumed, input.Offset()) << "\nFailed with SelectRandom";
+ }
+ VERIFY_EQ(original_remaining, original->Remaining());
+ original->AdvanceCursor(first_consumed);
+ VLOG(1) << "DecodeAndValidateSeveralWays - SUCCESS";
+ return ::testing::AssertionSuccess();
+}
+
+// static
+RandomDecoderTest::SelectSize RandomDecoderTest::SelectZeroAndOne(
+ bool return_non_zero_on_first) {
+ std::shared_ptr<bool> zero_next(new bool);
+ *zero_next = !return_non_zero_on_first;
+ return [zero_next](bool first, size_t offset, size_t remaining) -> size_t {
+ if (*zero_next) {
+ *zero_next = false;
+ return 0;
+ } else {
+ *zero_next = true;
+ return 1;
+ }
+ };
+}
+
+RandomDecoderTest::SelectSize RandomDecoderTest::SelectRandom(
+ bool return_non_zero_on_first) {
+ return [this, return_non_zero_on_first](bool first, size_t offset,
+ size_t remaining) -> size_t {
+ uint32_t r = random_.Rand32();
+ if (first && return_non_zero_on_first) {
+ CHECK_LT(0u, remaining);
+ if (remaining == 1) {
+ return 1;
+ }
+ return 1 + (r % remaining); // size in range [1, remaining).
+ }
+ return r % (remaining + 1); // size in range [0, remaining].
+ };
+}
+
+uint32_t RandomDecoderTest::RandStreamId() {
+ return random_.Rand32() & StreamIdMask();
+}
+
+} // namespace test
+} // namespace net
diff --git a/chromium/net/http2/tools/random_decoder_test.h b/chromium/net/http2/tools/random_decoder_test.h
new file mode 100644
index 00000000000..5cb10f647fe
--- /dev/null
+++ b/chromium/net/http2/tools/random_decoder_test.h
@@ -0,0 +1,260 @@
+// Copyright 2016 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.
+
+#ifndef NET_HTTP2_TOOLS_RANDOM_DECODER_TEST_H_
+#define NET_HTTP2_TOOLS_RANDOM_DECODER_TEST_H_
+
+// RandomDecoderTest is a base class for tests of decoding various kinds
+// of HTTP/2 and HPACK encodings.
+
+// TODO(jamessynge): Move more methods into .cc file.
+
+#include <stddef.h>
+
+#include <functional>
+#include <memory>
+#include <string>
+#include <type_traits>
+
+#include "base/logging.h"
+#include "base/strings/string_piece.h"
+#include "base/template_util.h"
+#include "net/http2/decoder/decode_buffer.h"
+#include "net/http2/decoder/decode_status.h"
+#include "net/http2/tools/failure.h"
+#include "net/http2/tools/http2_random.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace net {
+namespace test {
+
+// Some helpers.
+
+template <typename T, size_t N>
+base::StringPiece ToStringPiece(T (&data)[N]) {
+ return base::StringPiece(reinterpret_cast<const char*>(data), N * sizeof(T));
+}
+
+// strings/hex_ascii_dump.h doesn't support StringPiece args for this case.
+std::string HexEncode(base::StringPiece s);
+
+// Overwrite the enum with some random value, probably not a valid value for
+// the enum type, but which fits into its storage.
+template <typename T,
+ typename E = typename std::enable_if<std::is_enum<T>::value>::type>
+void CorruptEnum(T* out, RandomBase* rng) {
+ // Per cppreference.com, if the destination type of a static_cast is
+ // smaller than the source type (i.e. type of r and uint32 below), the
+ // resulting value is the smallest unsigned value equal to the source value
+ // modulo 2^n, where n is the number of bits used to represent the
+ // destination type unsigned U.
+ typedef typename base::underlying_type<T>::type underlying_type_T;
+ typedef typename std::make_unsigned<underlying_type_T>::type
+ unsigned_underlying_type_T;
+ auto r = static_cast<unsigned_underlying_type_T>(rng->Rand32());
+ *out = static_cast<T>(r);
+}
+
+// Base class for tests of the ability to decode a sequence of bytes with
+// various boundaries between the DecodeBuffers provided to the decoder.
+class RandomDecoderTest : public ::testing::Test {
+ public:
+ // SelectSize returns the size of the next DecodeBuffer to be passed to the
+ // decoder. Note that RandomDecoderTest allows that size to be zero, though
+ // some decoders can't deal with that on the first byte, hence the |first|
+ // parameter.
+ typedef std::function<size_t(bool first, size_t offset, size_t remaining)>
+ SelectSize;
+
+ // Validator returns an AssertionResult so test can do:
+ // EXPECT_THAT(DecodeAndValidate(..., validator));
+ typedef ::testing::AssertionResult AssertionResult;
+ typedef std::function<AssertionResult(const DecodeBuffer& input,
+ DecodeStatus status)>
+ Validator;
+ typedef std::function<AssertionResult()> NoArgValidator;
+
+ RandomDecoderTest();
+
+ protected:
+ // TODO(jamessynge): Modify StartDecoding, etc. to (somehow) return
+ // AssertionResult so that the VERIFY_* methods exported from
+ // gunit_helpers.h can be widely used.
+
+ // Start decoding; call allows sub-class to Reset the decoder, or deal with
+ // the first byte if that is done in a unique fashion. Might be called with
+ // a zero byte buffer.
+ virtual DecodeStatus StartDecoding(DecodeBuffer* db) = 0;
+
+ // Resume decoding of the input after a prior call to StartDecoding, and
+ // possibly many calls to ResumeDecoding.
+ virtual DecodeStatus ResumeDecoding(DecodeBuffer* db) = 0;
+
+ // Return true if a decode status of kDecodeDone indicates that
+ // decoding should stop.
+ virtual bool StopDecodeOnDone();
+
+ // Decode buffer |original| until we run out of input, or kDecodeDone is
+ // returned by the decoder AND StopDecodeOnDone() returns true. Segments
+ // (i.e. cuts up) the original DecodeBuffer into (potentially) smaller buffers
+ // by calling |select_size| to decide how large each buffer should be.
+ // We do this to test the ability to deal with arbitrary boundaries, as might
+ // happen in transport.
+ // Returns the final DecodeStatus.
+ DecodeStatus DecodeSegments(DecodeBuffer* original,
+ const SelectSize& select_size);
+
+ // Decode buffer |original| until we run out of input, or kDecodeDone is
+ // returned by the decoder AND StopDecodeOnDone() returns true. Segments
+ // (i.e. cuts up) the original DecodeBuffer into (potentially) smaller buffers
+ // by calling |select_size| to decide how large each buffer should be.
+ // We do this to test the ability to deal with arbitrary boundaries, as might
+ // happen in transport.
+ // Invokes |validator| with the final decode status and the original decode
+ // buffer, with the cursor advanced as far as has been consumed by the decoder
+ // and returns validator's result.
+ ::testing::AssertionResult DecodeSegmentsAndValidate(
+ DecodeBuffer* original,
+ const SelectSize& select_size,
+ const Validator& validator) {
+ DecodeStatus status = DecodeSegments(original, select_size);
+ VERIFY_AND_RETURN_SUCCESS(validator(*original, status));
+ }
+
+ // Returns a SelectSize function for fast decoding, i.e. passing all that
+ // is available to the decoder.
+ static SelectSize SelectRemaining() {
+ return [](bool first, size_t offset, size_t remaining) -> size_t {
+ return remaining;
+ };
+ }
+
+ // Returns a SelectSize function for decoding a single byte at a time.
+ static SelectSize SelectOne() {
+ return
+ [](bool first, size_t offset, size_t remaining) -> size_t { return 1; };
+ }
+
+ // Returns a SelectSize function for decoding a single byte at a time, where
+ // zero byte buffers are also allowed. Alternates between zero and one.
+ static SelectSize SelectZeroAndOne(bool return_non_zero_on_first);
+
+ // Returns a SelectSize function for decoding random sized segments.
+ SelectSize SelectRandom(bool return_non_zero_on_first);
+
+ // Decode |original| multiple times, with different segmentations of the
+ // decode buffer, validating after each decode, and confirming that they
+ // each decode the same amount. Returns on the first failure, else returns
+ // success.
+ AssertionResult DecodeAndValidateSeveralWays(DecodeBuffer* original,
+ bool return_non_zero_on_first,
+ const Validator& validator);
+
+ static Validator ToValidator(std::nullptr_t) {
+ return [](const DecodeBuffer& input, DecodeStatus status) {
+ return ::testing::AssertionSuccess();
+ };
+ }
+
+ static Validator ToValidator(const Validator& validator) {
+ if (validator == nullptr) {
+ return ToValidator(nullptr);
+ }
+ return validator;
+ }
+
+ static Validator ToValidator(const NoArgValidator& validator) {
+ if (validator == nullptr) {
+ return ToValidator(nullptr);
+ }
+ return [validator](const DecodeBuffer& input, DecodeStatus status) {
+ return validator();
+ };
+ }
+
+ // Wraps a validator with another validator
+ // that first checks that the DecodeStatus is kDecodeDone and
+ // that the DecodeBuffer is empty.
+ // TODO(jamessynge): Replace this overload with the next, as using this method
+ // usually means that the wrapped function doesn't need to be passed the
+ // DecodeBuffer nor the DecodeStatus.
+ static Validator ValidateDoneAndEmpty(const Validator& wrapped) {
+ return [wrapped](const DecodeBuffer& input,
+ DecodeStatus status) -> AssertionResult {
+ VERIFY_EQ(status, DecodeStatus::kDecodeDone);
+ VERIFY_EQ(0u, input.Remaining()) << "\nOffset=" << input.Offset();
+ if (wrapped) {
+ return wrapped(input, status);
+ }
+ return ::testing::AssertionSuccess();
+ };
+ }
+ static Validator ValidateDoneAndEmpty(NoArgValidator wrapped) {
+ return [wrapped](const DecodeBuffer& input,
+ DecodeStatus status) -> AssertionResult {
+ VERIFY_EQ(status, DecodeStatus::kDecodeDone);
+ VERIFY_EQ(0u, input.Remaining()) << "\nOffset=" << input.Offset();
+ if (wrapped) {
+ return wrapped();
+ }
+ return ::testing::AssertionSuccess();
+ };
+ }
+ static Validator ValidateDoneAndEmpty() {
+ NoArgValidator validator;
+ return ValidateDoneAndEmpty(validator);
+ }
+
+ // Wraps a validator with another validator
+ // that first checks that the DecodeStatus is kDecodeDone and
+ // that the DecodeBuffer has the expected offset.
+ // TODO(jamessynge): Replace this overload with the next, as using this method
+ // usually means that the wrapped function doesn't need to be passed the
+ // DecodeBuffer nor the DecodeStatus.
+ static Validator ValidateDoneAndOffset(uint32_t offset, Validator wrapped) {
+ return [wrapped, offset](const DecodeBuffer& input,
+ DecodeStatus status) -> AssertionResult {
+ VERIFY_EQ(status, DecodeStatus::kDecodeDone);
+ VERIFY_EQ(offset, input.Offset()) << "\nRemaining=" << input.Remaining();
+ if (wrapped) {
+ return wrapped(input, status);
+ }
+ return ::testing::AssertionSuccess();
+ };
+ }
+ static Validator ValidateDoneAndOffset(uint32_t offset,
+ NoArgValidator wrapped) {
+ return [wrapped, offset](const DecodeBuffer& input,
+ DecodeStatus status) -> AssertionResult {
+ VERIFY_EQ(status, DecodeStatus::kDecodeDone);
+ VERIFY_EQ(offset, input.Offset()) << "\nRemaining=" << input.Remaining();
+ if (wrapped) {
+ return wrapped();
+ }
+ return ::testing::AssertionSuccess();
+ };
+ }
+ static Validator ValidateDoneAndOffset(uint32_t offset) {
+ NoArgValidator validator;
+ return ValidateDoneAndOffset(offset, validator);
+ }
+
+ // Expose |random_| as RandomBase so callers do not have to care about which
+ // sub-class of RandomBase is used, nor can they rely on the specific
+ // sub-class that RandomDecoderTest uses.
+ RandomBase& Random() { return random_; }
+ RandomBase* RandomPtr() { return &random_; }
+
+ uint32_t RandStreamId();
+
+ bool stop_decode_on_done_ = true;
+
+ private:
+ Http2Random random_;
+};
+
+} // namespace test
+} // namespace net
+
+#endif // NET_HTTP2_TOOLS_RANDOM_DECODER_TEST_H_
diff --git a/chromium/net/http2/tools/random_util.cc b/chromium/net/http2/tools/random_util.cc
new file mode 100644
index 00000000000..90933b5f127
--- /dev/null
+++ b/chromium/net/http2/tools/random_util.cc
@@ -0,0 +1,96 @@
+// Copyright 2016 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.
+
+#include "net/http2/tools/random_util.h"
+
+#include <cmath>
+
+#include "base/rand_util.h"
+#include "net/http2/tools/http2_random.h"
+
+using std::string;
+using base::StringPiece;
+
+namespace net {
+namespace test {
+namespace {
+
+const char kWebsafe64[] =
+ "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ-_";
+
+// Generate two independent standard normal random variables using the polar
+// method.
+void GenerateRandomSizeSkewedLowHelper(size_t max, size_t* x, size_t* y) {
+ double a, b, s;
+ do {
+ // Draw uniformly on [-1, 1).
+ a = 2 * base::RandDouble() - 1.0;
+ b = 2 * base::RandDouble() - 1.0;
+ s = a * a + b * b;
+ } while (s >= 1.0);
+ double t = std::sqrt(-2.0 * std::log(s) / s);
+ *x = static_cast<size_t>(a * t * max);
+ *y = static_cast<size_t>(b * t * max);
+}
+
+} // anonymous namespace
+
+string RandomString(RandomBase* rng, int len, StringPiece alphabet) {
+ string random_string;
+ random_string.reserve(len);
+ for (int i = 0; i < len; ++i)
+ random_string.push_back(alphabet[rng->Uniform(alphabet.size())]);
+ return random_string;
+}
+
+size_t GenerateUniformInRange(size_t lo, size_t hi, RandomBase* rng) {
+ if (lo + 1 >= hi) {
+ return lo;
+ }
+ return lo + rng->Rand64() % (hi - lo);
+}
+
+// Here "word" means something that starts with a lower-case letter, and has
+// zero or more additional characters that are numbers or lower-case letters.
+string GenerateHttp2HeaderName(size_t len, RandomBase* rng) {
+ StringPiece alpha_lc = "abcdefghijklmnopqrstuvwxyz";
+ // If the name is short, just make it one word.
+ if (len < 8) {
+ return RandomString(rng, len, alpha_lc);
+ }
+ // If the name is longer, ensure it starts with a word, and after that may
+ // have any character in alphanumdash_lc. 4 is arbitrary, could be as low
+ // as 1.
+ StringPiece alphanumdash_lc = "abcdefghijklmnopqrstuvwxyz0123456789-";
+ return RandomString(rng, 4, alpha_lc) +
+ RandomString(rng, len - 4, alphanumdash_lc);
+}
+
+string GenerateWebSafeString(size_t len, RandomBase* rng) {
+ return RandomString(rng, len, kWebsafe64);
+}
+
+string GenerateWebSafeString(size_t lo, size_t hi, RandomBase* rng) {
+ return GenerateWebSafeString(GenerateUniformInRange(lo, hi, rng), rng);
+}
+
+size_t GenerateRandomSizeSkewedLow(size_t max, RandomBase* rng) {
+ if (max == 0) {
+ return 0;
+ }
+ // Generate a random number with a Gaussian distribution, centered on zero;
+ // take the absolute, and then keep in range 0 to max.
+ for (int i = 0; i < 5; i++) {
+ size_t x, y;
+ GenerateRandomSizeSkewedLowHelper(max, &x, &y);
+ if (x <= max)
+ return x;
+ if (y <= max)
+ return y;
+ }
+ return rng->Uniform(max + 1);
+}
+
+} // namespace test
+} // namespace net
diff --git a/chromium/net/http2/tools/random_util.h b/chromium/net/http2/tools/random_util.h
new file mode 100644
index 00000000000..aeeb3c6e9f4
--- /dev/null
+++ b/chromium/net/http2/tools/random_util.h
@@ -0,0 +1,43 @@
+// Copyright 2016 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.
+
+#ifndef NET_HTTP2_TOOLS_RANDOM_UTIL_H_
+#define NET_HTTP2_TOOLS_RANDOM_UTIL_H_
+
+#include <stddef.h>
+
+#include <string>
+
+#include "base/strings/string_piece.h"
+
+namespace net {
+namespace test {
+
+class RandomBase;
+
+// Returns a random string of length |len|, each character drawn uniformly and
+// independently fom |alphabet|.
+std::string RandomString(RandomBase* rng, int len, base::StringPiece alphabet);
+
+// Returns a random integer in the range [lo, hi).
+size_t GenerateUniformInRange(size_t lo, size_t hi, RandomBase* rng);
+
+// Generate a string with the allowed character set for HTTP/2 / HPACK header
+// names.
+std::string GenerateHttp2HeaderName(size_t len, RandomBase* rng);
+
+// Generate a string with the web-safe string character set of specified len.
+std::string GenerateWebSafeString(size_t len, RandomBase* rng);
+
+// Generate a string with the web-safe string character set of length [lo, hi).
+std::string GenerateWebSafeString(size_t lo, size_t hi, RandomBase* rng);
+
+// Returns a random integer in the range [0, max], with a bias towards producing
+// lower numbers.
+size_t GenerateRandomSizeSkewedLow(size_t max, RandomBase* rng);
+
+} // namespace test
+} // namespace net
+
+#endif // NET_HTTP2_TOOLS_RANDOM_UTIL_H_
diff --git a/chromium/net/log/bounded_file_net_log_observer.h b/chromium/net/log/bounded_file_net_log_observer.h
deleted file mode 100644
index 918398ca941..00000000000
--- a/chromium/net/log/bounded_file_net_log_observer.h
+++ /dev/null
@@ -1,136 +0,0 @@
-// Copyright 2016 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.
-
-#ifndef BOUNDED_FILE_NET_LOG_OBSERVER_H_
-#define BOUNDED_FILE_NET_LOG_OBSERVER_H_
-
-#include <queue>
-
-#include "base/files/file_path.h"
-#include "base/files/scoped_file.h"
-#include "base/macros.h"
-#include "base/memory/ref_counted.h"
-#include "base/memory/weak_ptr.h"
-#include "base/synchronization/lock.h"
-#include "base/threading/thread.h"
-#include "base/threading/thread_task_runner_handle.h"
-#include "net/base/net_export.h"
-#include "net/log/net_log.h"
-#include "net/log/net_log_capture_mode.h"
-
-namespace base {
-class DictionaryValue;
-class Value;
-} // namespace base
-
-namespace net {
-
-class URLRequestContext;
-
-// BoundedFileNetLogObserver watches the NetLog event stream and sends all
-// entries to a group of files in the directory specified when observation
-// starts.
-//
-// The events are written to a single JSON object that is split across the
-// files, and the files must be stitched together once the observation period
-// is over. The first file is constants.json, followed by a consumer-specified
-// number of event files named event_file_<index>.json, and the last file is
-// end_netlog.json.
-//
-// The user is able to specify an approximate maximum cumulative size for the
-// netlog files and the observer overwrites old events when the maximum file
-// size is reached.
-//
-// The consumer must call StartObserving before calling StopObserving, and must
-// call each method exactly once in the lifetime of the observer. StartObserving
-// and StopObserving must be called on the same thread, but there is no
-// restriction on which thread is used.
-class NET_EXPORT BoundedFileNetLogObserver : public NetLog::ThreadSafeObserver {
- public:
- // |task_runner| indicates the task runner that should be used to post tasks
- // from the main thread to the file thread.
- //
- // |num_event_files| sets the number of event files that should be used to
- // write events to file.
- BoundedFileNetLogObserver(
- scoped_refptr<base::SingleThreadTaskRunner> task_runner);
-
- ~BoundedFileNetLogObserver() override;
-
- // Sets the capture mode to log at. Must be called before StartObserving.
- void set_capture_mode(NetLogCaptureMode capture_mode);
-
- // Starts observing |net_log| and writes output to files in |filepath|.
- // May only be called once in the lifetime of the object.
- //
- // |max_total_size| is the approximate limit on the cumulative size of all
- // netlog files.
- //
- // |total_num_files| sets the total number of event files that are used to
- // write the events. It must be greater than 0.
- //
- // |constants| is an optional legend for decoding constant values used in
- // the log. It should generally be a modified version of GetNetConstants().
- // If not present, the output of GetNetConstants() will be used.
- //
- // |url_request_context| is an optional URLRequestContext that will be used
- // to pre-populate the log with information about in-progress events. If the
- // context is non-NULL, StartObserving() must be called on the context's
- // thread.
- void StartObserving(NetLog* net_log,
- const base::FilePath& filepath,
- base::Value* constants,
- URLRequestContext* url_request_context,
- size_t max_total_size,
- size_t total_num_files);
-
- // Stops observing net_log(). Must be called after StartObserving(). Should
- // be called before destruction of the BoundedFileNetLogObserver and the
- // NetLog, or the NetLog files will be deleted when the observer is
- // destroyed.
- //
- // |callback| will be run on whichever thread StopObserving() was called on
- // once all file writing is complete and the netlog files can be accessed
- // safely.
- //
- // |url_request_context| is an optional argument used to add additional
- // network stack state to the log. If the context is non-NULL,
- // StopObserving() must be called on the context's thread.
- void StopObserving(URLRequestContext* url_request_context,
- const base::Closure& callback);
-
- // NetLog::ThreadSafeObserver
- void OnAddEntry(const NetLogEntry& entry) override;
-
- private:
- class WriteQueue;
- class FileWriter;
-
- // The capture mode to log at.
- NetLogCaptureMode capture_mode_;
-
- scoped_refptr<base::SingleThreadTaskRunner> task_runner_;
-
- // The |write_queue_| object is shared between the file thread and the main
- // thread, and should be alive for the entirety of the observer's lifetime.
- // It should be destroyed once both the observer has been destroyed and all
- // tasks posted to the file thread have completed.
- scoped_refptr<WriteQueue> write_queue_;
-
- // This is the owning reference to a file thread object. The observer is
- // responsible for destroying the file thread object by posting a task from
- // the main thread to the file thread to destroy the FileWriter when the
- // observer is destroyed.
- //
- // The use of base::Unretained with |file_writer_| to post tasks to the file
- // thread is safe because the FileWriter object will be alive until the
- // observer's destruction.
- FileWriter* file_writer_;
-
- DISALLOW_COPY_AND_ASSIGN(BoundedFileNetLogObserver);
-};
-
-} // namespace net
-
-#endif // BOUNDED_FILE_NET_LOG_OBSERVER_H_
diff --git a/chromium/net/log/bounded_file_net_log_observer.cc b/chromium/net/log/file_net_log_observer.cc
index 833e84753d5..e49452df832 100644
--- a/chromium/net/log/bounded_file_net_log_observer.cc
+++ b/chromium/net/log/file_net_log_observer.cc
@@ -2,10 +2,13 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#include "net/log/bounded_file_net_log_observer.h"
+#include "net/log/file_net_log_observer.h"
+#include <limits>
#include <memory>
+#include <queue>
#include <set>
+#include <string>
#include <utility>
#include <vector>
@@ -17,6 +20,7 @@
#include "base/synchronization/lock.h"
#include "base/threading/thread.h"
#include "base/values.h"
+#include "net/log/net_log_capture_mode.h"
#include "net/log/net_log_entry.h"
#include "net/log/net_log_util.h"
#include "net/url_request/url_request_context.h"
@@ -34,9 +38,9 @@ namespace net {
// Used to store events to be written to file.
using EventQueue = std::queue<std::unique_ptr<std::string>>;
-// WriteQueue receives events from BoundedFileNetLogObserver on the main
-// thread and holds them in a queue until they are drained from the queue
-// and written to file on the file thread.
+// WriteQueue receives events from FileNetLogObserver on the main thread and
+// holds them in a queue until they are drained from the queue and written to
+// file on the file thread.
//
// WriteQueue contains the resources shared between the main thread and the
// file thread. |lock_| must be acquired to read or write to |queue_| and
@@ -44,13 +48,13 @@ using EventQueue = std::queue<std::unique_ptr<std::string>>;
//
// WriteQueue is refcounted and should be destroyed once all events on the
// file thread have finished executing.
-class BoundedFileNetLogObserver::WriteQueue
+class FileNetLogObserver::WriteQueue
: public base::RefCountedThreadSafe<WriteQueue> {
public:
// |memory_max| indicates the maximum amount of memory that the virtual write
// queue can use. If |memory_| exceeds |memory_max_|, the |queue_| of events
// is overwritten.
- WriteQueue(size_t memory_max);
+ explicit WriteQueue(size_t memory_max);
// Adds |event| to |queue_|. Also manages the size of |memory_|; if it
// exceeds |memory_max_|, then old events are dropped from |queue_| without
@@ -103,36 +107,49 @@ class BoundedFileNetLogObserver::WriteQueue
DISALLOW_COPY_AND_ASSIGN(WriteQueue);
};
-// FileWriter drains events from WriteQueue and writes them to file.
-//
-// Owned by BoundedFileNetLogObserver. FileWriter can be constructed on any
-// thread, and afterwards is only accessed on the file thread.
-class BoundedFileNetLogObserver::FileWriter {
+// FileWriter is an interface describing an object that drains events from a
+// WriteQueue and writes them to disk.
+class FileNetLogObserver::FileWriter {
public:
- FileWriter(const base::FilePath& path,
- size_t max_file_size,
- size_t total_num_files,
- scoped_refptr<base::SingleThreadTaskRunner> task_runner);
-
- ~FileWriter();
+ virtual ~FileWriter();
- // Writes |constants_value| to constants.json, and opens the
- // events array (closed in Stop()).
- void Initialize(std::unique_ptr<base::Value> constants_value);
+ // Writes |constants_value| to disk and opens the events array (closed in
+ // Stop()).
+ virtual void Initialize(std::unique_ptr<base::Value> constants_value) = 0;
// Closes the events array opened in Initialize() and writes |tab_info| to
- // end_netlog.json. If |tab_info| cannot be converted to proper JSON, then it
+ // disk. If |tab_info| cannot be converted to proper JSON, then it
// is ignored.
- void Stop(std::unique_ptr<base::Value> tab_info);
+ virtual void Stop(std::unique_ptr<base::Value> tab_info) = 0;
// Drains |queue_| from WriteQueue into a local file queue and writes the
- // events in the queue to file.
- void Flush(scoped_refptr<WriteQueue> write_queue);
+ // events in the queue to disk.
+ virtual void Flush(scoped_refptr<WriteQueue> write_queue) = 0;
+
+ // Deletes all netlog files. It is not valid to call any method of
+ // FileNetLogObserver after DeleteAllFiles().
+ virtual void DeleteAllFiles() = 0;
+};
+
+// This implementation of FileWriter is used when the observer is in bounded
+// mode.
+// BoundedFileWriter can be constructed on any thread, and afterwards is only
+// accessed on the file thread.
+class FileNetLogObserver::BoundedFileWriter
+ : public FileNetLogObserver::FileWriter {
+ public:
+ BoundedFileWriter(const base::FilePath& directory,
+ size_t max_file_size,
+ size_t total_num_files,
+ scoped_refptr<base::SingleThreadTaskRunner> task_runner);
+
+ ~BoundedFileWriter() override;
- // Deletes all netlog files, including constants.json and end_netlog.json.
- // It is not valid to call any method of BoundedFileNetLogObserver after
- // DeleteAllFiles().
- void DeleteAllFiles();
+ // FileNetLogObserver::FileWriter implementation
+ void Initialize(std::unique_ptr<base::Value> constants_value) override;
+ void Stop(std::unique_ptr<base::Value> tab_info) override;
+ void Flush(scoped_refptr<WriteQueue> write_queue) override;
+ void DeleteAllFiles() override;
private:
// Increments |current_file_idx_|, and handles the clearing and openining of
@@ -162,43 +179,69 @@ class BoundedFileNetLogObserver::FileWriter {
// Task runner from the file thread.
const scoped_refptr<base::SingleThreadTaskRunner> task_runner_;
- DISALLOW_COPY_AND_ASSIGN(FileWriter);
+ DISALLOW_COPY_AND_ASSIGN(BoundedFileWriter);
};
-BoundedFileNetLogObserver::BoundedFileNetLogObserver(
- scoped_refptr<base::SingleThreadTaskRunner> task_runner)
- : capture_mode_(NetLogCaptureMode::Default()), task_runner_(task_runner) {}
+// This implementation of FileWriter is used when the observer is in unbounded
+// mode.
+// UnboundedFileWriter can be constructed on any thread, and afterwards is only
+// accessed on the file thread.
+class FileNetLogObserver::UnboundedFileWriter
+ : public FileNetLogObserver::FileWriter {
+ public:
+ UnboundedFileWriter(const base::FilePath& path,
+ scoped_refptr<base::SingleThreadTaskRunner> task_runner);
+
+ ~UnboundedFileWriter() override;
+
+ // FileNetLogObserver::FileWriter implementation
+ void Initialize(std::unique_ptr<base::Value> constants_value) override;
+ void Stop(std::unique_ptr<base::Value> tab_info) override;
+ void Flush(scoped_refptr<WriteQueue> write_queue) override;
+ void DeleteAllFiles() override;
+
+ private:
+ base::FilePath file_path_;
+ base::ScopedFILE file_;
+
+ // Is set to true after the first event is written to the log file.
+ bool first_event_written_;
+
+ // Task runner from the file thread.
+ const scoped_refptr<base::SingleThreadTaskRunner> task_runner_;
+
+ DISALLOW_COPY_AND_ASSIGN(UnboundedFileWriter);
+};
+
+FileNetLogObserver::FileNetLogObserver(
+ scoped_refptr<base::SingleThreadTaskRunner> file_task_runner)
+ : file_task_runner_(file_task_runner) {}
-BoundedFileNetLogObserver::~BoundedFileNetLogObserver() {
+FileNetLogObserver::~FileNetLogObserver() {
if (net_log()) {
// StopObserving was not called.
- task_runner_->PostTask(
- FROM_HERE,
- base::Bind(&BoundedFileNetLogObserver::FileWriter::DeleteAllFiles,
- base::Unretained(file_writer_)));
+ file_task_runner_->PostTask(
+ FROM_HERE, base::Bind(&FileNetLogObserver::FileWriter::DeleteAllFiles,
+ base::Unretained(file_writer_)));
net_log()->DeprecatedRemoveObserver(this);
}
- task_runner_->DeleteSoon(FROM_HERE, file_writer_);
+ file_task_runner_->DeleteSoon(FROM_HERE, file_writer_);
}
-void BoundedFileNetLogObserver::set_capture_mode(
- NetLogCaptureMode capture_mode) {
- DCHECK(!net_log());
- capture_mode_ = capture_mode;
-}
-
-void BoundedFileNetLogObserver::StartObserving(
+void FileNetLogObserver::StartObservingBounded(
NetLog* net_log,
- const base::FilePath& filepath,
- base::Value* constants,
+ NetLogCaptureMode capture_mode,
+ const base::FilePath& directory,
+ std::unique_ptr<base::Value> constants,
URLRequestContext* url_request_context,
size_t max_total_size,
size_t total_num_files) {
DCHECK_GT(total_num_files, 0u);
- file_writer_ = new FileWriter(filepath, max_total_size / total_num_files,
- total_num_files, task_runner_);
+ file_writer_ =
+ new BoundedFileWriter(directory, max_total_size / total_num_files,
+ total_num_files, file_task_runner_);
// The |file_writer_| uses a soft limit to write events to file that allows
// the size of the file to exceed the limit, but the |write_queue_| uses a
@@ -212,13 +255,37 @@ void BoundedFileNetLogObserver::StartObserving(
// TODO(dconnol): Handle the case when the |write_queue_| still doesn't
// contain enough events to fill all files, because of very large events
// relative to file size.
- write_queue_ = make_scoped_refptr(new WriteQueue(max_total_size * 2));
+ write_queue_ = new WriteQueue(max_total_size * 2);
+
+ StartObservingHelper(net_log, capture_mode, std::move(constants),
+ url_request_context);
+}
- task_runner_->PostTask(
- FROM_HERE, base::Bind(&BoundedFileNetLogObserver::FileWriter::Initialize,
- base::Unretained(file_writer_),
- base::Passed(constants ? constants->CreateDeepCopy()
- : GetNetConstants())));
+void FileNetLogObserver::StartObservingUnbounded(
+ NetLog* net_log,
+ NetLogCaptureMode capture_mode,
+ const base::FilePath& filepath,
+ std::unique_ptr<base::Value> constants,
+ URLRequestContext* url_request_context) {
+ file_writer_ = new UnboundedFileWriter(filepath, file_task_runner_);
+
+ write_queue_ = new WriteQueue(std::numeric_limits<size_t>::max());
+
+ StartObservingHelper(net_log, capture_mode, std::move(constants),
+ url_request_context);
+}
+
+void FileNetLogObserver::StartObservingHelper(
+ NetLog* net_log,
+ NetLogCaptureMode capture_mode,
+ std::unique_ptr<base::Value> constants,
+ URLRequestContext* url_request_context) {
+ if (!constants)
+ constants = GetNetConstants();
+ file_task_runner_->PostTask(
+ FROM_HERE,
+ base::Bind(&FileNetLogObserver::FileWriter::Initialize,
+ base::Unretained(file_writer_), base::Passed(&constants)));
if (url_request_context) {
DCHECK(url_request_context->CalledOnValidThread());
@@ -227,29 +294,28 @@ void BoundedFileNetLogObserver::StartObserving(
CreateNetLogEntriesForActiveObjects(contexts, this);
}
- net_log->DeprecatedAddObserver(this, capture_mode_);
+ net_log->DeprecatedAddObserver(this, capture_mode);
}
-void BoundedFileNetLogObserver::StopObserving(
- URLRequestContext* url_request_context,
- const base::Closure& callback) {
- task_runner_->PostTask(
- FROM_HERE, base::Bind(&BoundedFileNetLogObserver::FileWriter::Flush,
+void FileNetLogObserver::StopObserving(URLRequestContext* url_request_context,
+ const base::Closure& callback) {
+ file_task_runner_->PostTask(
+ FROM_HERE, base::Bind(&FileNetLogObserver::FileWriter::Flush,
base::Unretained(file_writer_), write_queue_));
- task_runner_->PostTaskAndReply(
- FROM_HERE, base::Bind(&BoundedFileNetLogObserver::FileWriter::Stop,
- base::Unretained(file_writer_),
- base::Passed(url_request_context
- ? GetNetInfo(url_request_context,
- NET_INFO_ALL_SOURCES)
- : nullptr)),
+ file_task_runner_->PostTaskAndReply(
+ FROM_HERE,
+ base::Bind(
+ &FileNetLogObserver::FileWriter::Stop, base::Unretained(file_writer_),
+ base::Passed(url_request_context ? GetNetInfo(url_request_context,
+ NET_INFO_ALL_SOURCES)
+ : nullptr)),
callback);
net_log()->DeprecatedRemoveObserver(this);
}
-void BoundedFileNetLogObserver::OnAddEntry(const NetLogEntry& entry) {
+void FileNetLogObserver::OnAddEntry(const NetLogEntry& entry) {
std::unique_ptr<std::string> json(new std::string);
// If |entry| cannot be converted to proper JSON, ignore it.
@@ -259,18 +325,20 @@ void BoundedFileNetLogObserver::OnAddEntry(const NetLogEntry& entry) {
size_t queue_size = write_queue_->AddEntryToQueue(std::move(json));
// If events build up in |write_queue_|, trigger the file thread to drain
- // the queue.
- if (queue_size >= kNumWriteQueueEvents) {
- task_runner_->PostTask(
- FROM_HERE, base::Bind(&BoundedFileNetLogObserver::FileWriter::Flush,
+ // the queue. Because only 1 item is added to the queue at a time, if
+ // queue_size > kNumWriteQueueEvents a task has already been posted, or will
+ // be posted.
+ if (queue_size == kNumWriteQueueEvents) {
+ file_task_runner_->PostTask(
+ FROM_HERE, base::Bind(&FileNetLogObserver::FileWriter::Flush,
base::Unretained(file_writer_), write_queue_));
}
}
-BoundedFileNetLogObserver::WriteQueue::WriteQueue(size_t memory_max)
+FileNetLogObserver::WriteQueue::WriteQueue(size_t memory_max)
: memory_(0), memory_max_(memory_max) {}
-size_t BoundedFileNetLogObserver::WriteQueue::AddEntryToQueue(
+size_t FileNetLogObserver::WriteQueue::AddEntryToQueue(
std::unique_ptr<std::string> event) {
base::AutoLock lock(lock_);
@@ -286,21 +354,23 @@ size_t BoundedFileNetLogObserver::WriteQueue::AddEntryToQueue(
return queue_.size();
}
-void BoundedFileNetLogObserver::WriteQueue::SwapQueue(EventQueue* local_queue) {
+void FileNetLogObserver::WriteQueue::SwapQueue(EventQueue* local_queue) {
DCHECK(local_queue->empty());
base::AutoLock lock(lock_);
queue_.swap(*local_queue);
memory_ = 0;
}
-BoundedFileNetLogObserver::WriteQueue::~WriteQueue() {}
+FileNetLogObserver::WriteQueue::~WriteQueue() {}
-BoundedFileNetLogObserver::FileWriter::FileWriter(
- const base::FilePath& path,
+FileNetLogObserver::FileWriter::~FileWriter() {}
+
+FileNetLogObserver::BoundedFileWriter::BoundedFileWriter(
+ const base::FilePath& directory,
size_t max_file_size,
size_t total_num_files,
scoped_refptr<base::SingleThreadTaskRunner> task_runner)
- : directory_(path),
+ : directory_(directory),
total_num_files_(total_num_files),
current_file_idx_(0),
max_file_size_(max_file_size),
@@ -308,9 +378,9 @@ BoundedFileNetLogObserver::FileWriter::FileWriter(
event_files_.resize(total_num_files_);
}
-BoundedFileNetLogObserver::FileWriter::~FileWriter() {}
+FileNetLogObserver::BoundedFileWriter::~BoundedFileWriter() {}
-void BoundedFileNetLogObserver::FileWriter::Initialize(
+void FileNetLogObserver::BoundedFileWriter::Initialize(
std::unique_ptr<base::Value> constants_value) {
DCHECK(task_runner_->RunsTasksOnCurrentThread());
@@ -330,7 +400,7 @@ void BoundedFileNetLogObserver::FileWriter::Initialize(
json.c_str());
}
-void BoundedFileNetLogObserver::FileWriter::Stop(
+void FileNetLogObserver::BoundedFileWriter::Stop(
std::unique_ptr<base::Value> tab_info) {
DCHECK(task_runner_->RunsTasksOnCurrentThread());
@@ -341,7 +411,7 @@ void BoundedFileNetLogObserver::FileWriter::Stop(
if (tab_info)
base::JSONWriter::Write(*tab_info, &json);
- fprintf(closing_file.get(), "]%s}",
+ fprintf(closing_file.get(), "]%s}\n",
json.empty() ? "" : (",\"tabInfo\": " + json + "\n").c_str());
// Flush all fprintfs to disk so that files can be safely accessed on
@@ -349,7 +419,7 @@ void BoundedFileNetLogObserver::FileWriter::Stop(
event_files_.clear();
}
-void BoundedFileNetLogObserver::FileWriter::IncrementCurrentFile() {
+void FileNetLogObserver::BoundedFileWriter::IncrementCurrentFile() {
DCHECK(task_runner_->RunsTasksOnCurrentThread());
current_file_idx_++;
@@ -361,8 +431,8 @@ void BoundedFileNetLogObserver::FileWriter::IncrementCurrentFile() {
"w"));
}
-void BoundedFileNetLogObserver::FileWriter::Flush(
- scoped_refptr<BoundedFileNetLogObserver::WriteQueue> write_queue) {
+void FileNetLogObserver::BoundedFileWriter::Flush(
+ scoped_refptr<FileNetLogObserver::WriteQueue> write_queue) {
DCHECK(task_runner_->RunsTasksOnCurrentThread());
EventQueue local_file_queue;
@@ -386,7 +456,7 @@ void BoundedFileNetLogObserver::FileWriter::Flush(
}
}
-void BoundedFileNetLogObserver::FileWriter::DeleteAllFiles() {
+void FileNetLogObserver::BoundedFileWriter::DeleteAllFiles() {
DCHECK(task_runner_->RunsTasksOnCurrentThread());
// Reset |event_files_| to release all file handles so base::DeleteFile can
@@ -402,4 +472,70 @@ void BoundedFileNetLogObserver::FileWriter::DeleteAllFiles() {
}
}
+FileNetLogObserver::UnboundedFileWriter::UnboundedFileWriter(
+ const base::FilePath& path,
+ scoped_refptr<base::SingleThreadTaskRunner> task_runner)
+ : file_path_(path), task_runner_(task_runner) {}
+
+FileNetLogObserver::UnboundedFileWriter::~UnboundedFileWriter() {}
+
+void FileNetLogObserver::UnboundedFileWriter::Initialize(
+ std::unique_ptr<base::Value> constants_value) {
+ DCHECK(task_runner_->RunsTasksOnCurrentThread());
+
+ file_.reset(base::OpenFile(file_path_, "w"));
+ first_event_written_ = false;
+
+ // Print constants to file and open events array.
+ std::string json;
+
+ // It should always be possible to convert constants to JSON.
+ if (!base::JSONWriter::Write(*constants_value, &json))
+ DCHECK(false);
+ fprintf(file_.get(), "{\"constants\":%s,\n\"events\": [\n", json.c_str());
+}
+
+void FileNetLogObserver::UnboundedFileWriter::Stop(
+ std::unique_ptr<base::Value> tab_info) {
+ DCHECK(task_runner_->RunsTasksOnCurrentThread());
+
+ std::string json;
+ if (tab_info)
+ base::JSONWriter::Write(*tab_info, &json);
+
+ fprintf(file_.get(), "]%s}\n",
+ json.empty() ? "" : (",\n\"tabInfo\": " + json + "\n").c_str());
+
+ // Flush all fprintfs to disk so that the file can be safely accessed on
+ // callback.
+ file_.reset();
+}
+
+void FileNetLogObserver::UnboundedFileWriter::Flush(
+ scoped_refptr<FileNetLogObserver::WriteQueue> write_queue) {
+ DCHECK(task_runner_->RunsTasksOnCurrentThread());
+
+ EventQueue local_file_queue;
+ write_queue->SwapQueue(&local_file_queue);
+
+ while (!local_file_queue.empty()) {
+ if (first_event_written_) {
+ fputs(",\n", file_.get());
+ } else {
+ first_event_written_ = true;
+ }
+ fputs(local_file_queue.front()->c_str(), file_.get());
+ local_file_queue.pop();
+ }
+}
+
+void FileNetLogObserver::UnboundedFileWriter::DeleteAllFiles() {
+ DCHECK(task_runner_->RunsTasksOnCurrentThread());
+
+ // Reset |file_| to release the file handle so base::DeleteFile can
+ // safely access it.
+ file_.reset();
+ base::DeleteFile(file_path_, false);
+}
+
} // namespace net
diff --git a/chromium/net/log/file_net_log_observer.h b/chromium/net/log/file_net_log_observer.h
new file mode 100644
index 00000000000..f8a8d902831
--- /dev/null
+++ b/chromium/net/log/file_net_log_observer.h
@@ -0,0 +1,157 @@
+// Copyright 2016 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.
+
+#ifndef NET_LOG_FILE_NET_LOG_OBSERVER_H_
+#define NET_LOG_FILE_NET_LOG_OBSERVER_H_
+
+#include <memory>
+
+#include "base/macros.h"
+#include "base/memory/ref_counted.h"
+#include "net/base/net_export.h"
+#include "net/log/net_log.h"
+
+namespace base {
+class Value;
+class FilePath;
+class SingleThreadTaskRunner;
+} // namespace base
+
+namespace net {
+
+class NetLogCaptureMode;
+class URLRequestContext;
+
+// FileNetLogObserver watches the NetLog event stream and sends all entries to
+// either a group of files in a directory (bounded mode) or to a single file
+// (unbounded mode).
+//
+// Bounded mode:
+// The events are written to a single JSON object that is split across the
+// files, and the files must be stitched together once the observation period
+// is over. The first file is constants.json, followed by a consumer-specified
+// number of event files named event_file_<index>.json, and the last file is
+// end_netlog.json.
+//
+// The user is able to specify an approximate maximum cumulative size for the
+// netlog files and the observer overwrites old events when the maximum file
+// size is reached.
+//
+// Unbounded mode:
+// The entire JSON object is put into one file. There is no size limit to how
+// large this file can grow; all events added will be written to the file.
+//
+// The consumer must call StartObservingBounded/StartObservingUnbounded before
+// calling StopObserving, and must call each method exactly once in the lifetime
+// of the observer. StartObservingBounded/StartObservingUnbounded and
+// StopObserving must be called on the same thread, but there is no restriction
+// on which thread is used.
+class NET_EXPORT FileNetLogObserver : public NetLog::ThreadSafeObserver {
+ public:
+ // |file_task_runner| indicates the task runner that should be used to post
+ // tasks from the main thread to the file thread.
+ explicit FileNetLogObserver(
+ scoped_refptr<base::SingleThreadTaskRunner> file_task_runner);
+
+ ~FileNetLogObserver() override;
+
+ // Starts observing |net_log| in bounded mode and writes output files to
+ // |directory|.
+ // May only be called once in the lifetime of the object.
+ //
+ // |max_total_size| is the approximate limit on the cumulative size of all
+ // netlog files.
+ //
+ // |total_num_files| sets the total number of event files that are used to
+ // write the events. It must be greater than 0.
+ //
+ // |constants| is an optional legend for decoding constant values used in
+ // the log. It should generally be a modified version of GetNetConstants().
+ // If not present, the output of GetNetConstants() will be used.
+ //
+ // |url_request_context| is an optional URLRequestContext that will be used
+ // to pre-populate the log with information about in-progress events. If the
+ // context is non-NULL, StartObservingBounded() must be called on the
+ // context's thread.
+ void StartObservingBounded(NetLog* net_log,
+ NetLogCaptureMode capture_mode,
+ const base::FilePath& directory,
+ std::unique_ptr<base::Value> constants,
+ URLRequestContext* url_request_context,
+ size_t max_total_size,
+ size_t total_num_files);
+
+ // Starts observing |net_log| in unbounded mode and writes to the file at
+ // |filepath|.
+ // May only be called once in the lifetime of the object.
+ //
+ // |constants| is an optional legend for decoding constant values used in
+ // the log. It should generally be a modified version of GetNetConstants().
+ // If not present, the output of GetNetConstants() will be used.
+ //
+ // |url_request_context| is an optional URLRequestContext that will be used
+ // to pre-populate the log with information about in-progress events. If the
+ // context is non-NULL, StartObservingUnbounded() must be called on
+ // the context's thread.
+ void StartObservingUnbounded(NetLog* net_log,
+ NetLogCaptureMode capture_mode,
+ const base::FilePath& filepath,
+ std::unique_ptr<base::Value> constants,
+ URLRequestContext* url_request_context);
+
+ // Stops observing net_log(). Must be called after StartObservingBounded/
+ // StartObservingUnbounded. Should be called before destruction of the
+ // FileNetLogObserver and the NetLog, or the NetLog files will be deleted when
+ // the observer is destroyed.
+ //
+ // |callback| will be run on whichever thread StopObserving() was called on
+ // once all file writing is complete and the netlog files can be accessed
+ // safely.
+ //
+ // |url_request_context| is an optional argument used to add additional
+ // network stack state to the log. If the context is non-NULL,
+ // StopObserving() must be called on the context's thread.
+ void StopObserving(URLRequestContext* url_request_context,
+ const base::Closure& callback);
+
+ // NetLog::ThreadSafeObserver
+ void OnAddEntry(const NetLogEntry& entry) override;
+
+ private:
+ class WriteQueue;
+ class FileWriter;
+ class BoundedFileWriter;
+ class UnboundedFileWriter;
+
+ // Performs tasks common to both StartObservingBounded() and
+ // StartObservingUnbounded().
+ void StartObservingHelper(NetLog* net_log,
+ NetLogCaptureMode capture_mode,
+ std::unique_ptr<base::Value> constants,
+ URLRequestContext* url_request_context);
+
+ scoped_refptr<base::SingleThreadTaskRunner> file_task_runner_;
+
+ // The |write_queue_| object is shared between the file thread and the main
+ // thread, and should be alive for the entirety of the observer's lifetime.
+ // It should be destroyed once both the observer has been destroyed and all
+ // tasks posted to the file thread have completed.
+ scoped_refptr<WriteQueue> write_queue_;
+
+ // This is the owning reference to a file thread object. The observer is
+ // responsible for destroying the file thread object by posting a task from
+ // the main thread to the file thread to destroy the FileWriter when the
+ // observer is destroyed.
+ //
+ // The use of base::Unretained with |file_writer_| to post tasks to the file
+ // thread is safe because the FileWriter object will be alive until the
+ // observer's destruction.
+ FileWriter* file_writer_;
+
+ DISALLOW_COPY_AND_ASSIGN(FileNetLogObserver);
+};
+
+} // namespace net
+
+#endif // NET_LOG_FILE_NET_LOG_OBSERVER_H_
diff --git a/chromium/net/log/bounded_file_net_log_observer_unittest.cc b/chromium/net/log/file_net_log_observer_unittest.cc
index 6296c446df1..ffe6ba45ca3 100644
--- a/chromium/net/log/bounded_file_net_log_observer_unittest.cc
+++ b/chromium/net/log/file_net_log_observer_unittest.cc
@@ -2,13 +2,14 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#include "net/log/bounded_file_net_log_observer.h"
+#include "net/log/file_net_log_observer.h"
#include <math.h>
#include <memory>
#include <string>
#include <utility>
+#include <vector>
#include "base/files/file_path.h"
#include "base/files/file_util.h"
@@ -16,7 +17,10 @@
#include "base/files/scoped_temp_dir.h"
#include "base/json/json_reader.h"
#include "base/json/json_writer.h"
+#include "base/memory/ptr_util.h"
#include "base/strings/string_util.h"
+#include "base/strings/stringprintf.h"
+#include "base/threading/thread.h"
#include "base/values.h"
#include "net/base/test_completion_callback.h"
#include "net/log/net_log_entry.h"
@@ -45,251 +49,433 @@ const int kLargeFileSize = 100000000;
// where event size doesn't matter.
const size_t kDummyEventSize = 150;
-const std::string kWinLineEnd = "\r\n";
-const std::string kLinuxLineEnd = "\n";
+const char kWinLineEnd[] = "\r\n";
+const char kLinuxLineEnd[] = "\n";
+
+void AddEntries(FileNetLogObserver* logger,
+ int num_entries,
+ size_t entry_size) {
+ // Get base size of event.
+ const int kDummyId = 0;
+ std::string message = "";
+ NetLogParametersCallback callback =
+ NetLog::StringCallback("message", &message);
+ NetLogSource source(NetLogSourceType::HTTP2_SESSION, kDummyId);
+ NetLogEntryData base_entry_data(NetLogEventType::PAC_JAVASCRIPT_ERROR, source,
+ NetLogEventPhase::BEGIN,
+ base::TimeTicks::Now(), &callback);
+ NetLogEntry base_entry(&base_entry_data,
+ NetLogCaptureMode::IncludeSocketBytes());
+ std::unique_ptr<base::Value> value(base_entry.ToValue());
+ std::string json;
+ base::JSONWriter::Write(*value, &json);
+ size_t base_entry_size = json.size();
+
+ // The maximum value of base::TimeTicks::Now() will be the maximum value of
+ // int64_t, and if the maximum number of digits are included, the
+ // |base_entry_size| could be up to 101 characters. Check that the event
+ // format does not include additional padding.
+ DCHECK_LE(base_entry_size, 101u);
+
+ // |entry_size| should be at least as big as the largest possible base
+ // entry.
+ EXPECT_GE(entry_size, 101u);
+
+ // |entry_size| cannot be smaller than the minimum event size.
+ EXPECT_GE(entry_size, base_entry_size);
+
+ for (int i = 0; i < num_entries; i++) {
+ source = NetLogSource(NetLogSourceType::HTTP2_SESSION, i);
+ std::string id = std::to_string(i);
+
+ // String size accounts for the number of digits in id so that all events
+ // are the same size.
+ message = std::string(entry_size - base_entry_size - id.size() + 1, 'x');
+ callback = NetLog::StringCallback("message", &message);
+ NetLogEntryData entry_data(NetLogEventType::PAC_JAVASCRIPT_ERROR, source,
+ NetLogEventPhase::BEGIN, base::TimeTicks::Now(),
+ &callback);
+ NetLogEntry entry(&entry_data, NetLogCaptureMode::IncludeSocketBytes());
+ logger->OnAddEntry(entry);
+ }
+}
+
+// Loads and concatenates the contents of bounded log files into a string
+void ReadBoundedLogFiles(const base::FilePath& log_dir, std::string* input) {
+ base::ReadFileToString(log_dir.AppendASCII("constants.json"), input);
+ size_t input_no_events = input->length();
+ std::string to_add;
+ for (int i = 0; base::ReadFileToString(
+ log_dir.AppendASCII("event_file_" + std::to_string(i) + ".json"),
+ &to_add);
+ ++i) {
+ *input += to_add;
+ }
+
+ // Delete the hanging comma and newline from the events array.
+ if (input->length() > input_no_events) {
+ // Remove carriage returns in case of Windows machine.
+ base::ReplaceSubstringsAfterOffset(input, 0, kWinLineEnd, kLinuxLineEnd);
+ ASSERT_GE(input->length() - input_no_events, 2u);
+ ASSERT_EQ(std::string(",\n"), std::string(*input, input->length() - 2));
+ input->erase(input->end() - 2, input->end() - 1);
+ }
+
+ base::ReadFileToString(log_dir.AppendASCII("end_netlog.json"), &to_add);
+ *input += to_add;
+}
+
+::testing::AssertionResult ParseNetLogString(const std::string& input,
+ std::unique_ptr<base::Value>* root,
+ base::ListValue** events) {
+ if (input.empty()) {
+ return ::testing::AssertionFailure() << "input is empty";
+ }
+
+ base::JSONReader reader;
+ *root = reader.ReadToValue(input);
+ if (!*root) {
+ return ::testing::AssertionFailure() << reader.GetErrorMessage();
+ }
+
+ base::DictionaryValue* dict;
+ if (!(*root)->GetAsDictionary(&dict)) {
+ return ::testing::AssertionFailure() << "Not a dictionary";
+ }
+
+ if (!dict->GetList("events", events)) {
+ return ::testing::AssertionFailure() << "No events list";
+ }
+
+ return ::testing::AssertionSuccess();
+}
-class BoundedFileNetLogObserverTest : public testing::Test {
+// Used for tests that are common to both bounded and unbounded modes of the
+// the FileNetLogObserver. The param is true if bounded mode is used.
+class FileNetLogObserverTest : public ::testing::TestWithParam<bool> {
public:
void SetUp() override {
ASSERT_TRUE(temp_dir_.CreateUniqueTempDir());
- log_path_ = temp_dir_.GetPath();
+ bounded_log_dir_ = temp_dir_.GetPath();
+ unbounded_log_path_ = bounded_log_dir_.AppendASCII("net-log.json");
file_thread_.reset(new base::Thread("NetLog File Thread"));
file_thread_->StartWithOptions(
base::Thread::Options(base::MessageLoop::TYPE_DEFAULT, 0));
- if (file_thread_->WaitUntilThreadStarted()) {
- logger_ = std::unique_ptr<BoundedFileNetLogObserver>(
- new BoundedFileNetLogObserver(file_thread_->task_runner()));
+ ASSERT_TRUE(file_thread_->WaitUntilThreadStarted());
+ logger_.reset(new FileNetLogObserver(file_thread_->task_runner()));
+ }
+
+ void StartObserving(std::unique_ptr<base::Value> constants,
+ URLRequestContext* url_request_context) {
+ bool bounded = GetParam();
+ if (bounded) {
+ logger_->StartObservingBounded(&net_log_, NetLogCaptureMode::Default(),
+ bounded_log_dir_, std::move(constants),
+ url_request_context, kLargeFileSize,
+ kTotalNumFiles);
+ } else {
+ logger_->StartObservingUnbounded(
+ &net_log_, NetLogCaptureMode::Default(), unbounded_log_path_,
+ std::move(constants), url_request_context);
}
}
- // Concatenates all files together, including constants file and end file.
- void AddAllFiles(std::string* input) {
- base::ReadFileToString(log_path_.AppendASCII("constants.json"), input);
- std::string to_add;
- size_t input_no_events = input->length();
- for (int i = 0; i < kTotalNumFiles; i++) {
- base::ReadFileToString(
- log_path_.AppendASCII("event_file_" + std::to_string(i) + ".json"),
- &to_add);
- *input += to_add;
+ ::testing::AssertionResult ReadNetLogFromDisk(
+ std::unique_ptr<base::Value>* root,
+ base::ListValue** events) {
+ bool bounded = GetParam();
+ std::string input;
+ if (bounded) {
+ ReadBoundedLogFiles(bounded_log_dir_, &input);
+ } else {
+ base::ReadFileToString(unbounded_log_path_, &input);
}
+ return ParseNetLogString(input, root, events);
+ }
- // Delete the hanging comma and newline from the events array.
- if (input->length() > input_no_events) {
- // Remove carriage returns in case of Windows machine.
- base::ReplaceSubstringsAfterOffset(input, 0, kWinLineEnd, kLinuxLineEnd);
- ASSERT_GE(input->length() - input_no_events, 2u);
- ASSERT_EQ(std::string(",\n"), std::string(*input, input->length() - 2));
- input->erase(input->end() - 2, input->end() - 1);
+ bool LogFilesExist() {
+ bool bounded = GetParam();
+ if (bounded) {
+ if (base::PathExists(bounded_log_dir_.AppendASCII("constants.json")) ||
+ base::PathExists(bounded_log_dir_.AppendASCII("end_netlog.json")))
+ return true;
+ for (int i = 0; i < kTotalNumFiles; i++) {
+ if (base::PathExists(bounded_log_dir_.AppendASCII(
+ "event_file_" + std::to_string(i) + ".json")))
+ return true;
+ }
+ return false;
+ } else {
+ return base::PathExists(unbounded_log_path_);
}
+ }
- base::ReadFileToString(log_path_.AppendASCII("end_netlog.json"), &to_add);
- *input += to_add;
+ protected:
+ NetLog net_log_;
+ std::unique_ptr<base::Thread> file_thread_;
+ std::unique_ptr<FileNetLogObserver> logger_;
+
+ private:
+ base::ScopedTempDir temp_dir_;
+ base::FilePath bounded_log_dir_;
+ base::FilePath unbounded_log_path_;
+};
+
+// Used for tests that are exclusive to the bounded mode of FileNetLogObserver.
+class FileNetLogObserverBoundedTest : public ::testing::Test {
+ public:
+ void SetUp() override {
+ ASSERT_TRUE(temp_dir_.CreateUniqueTempDir());
+ bounded_log_dir_ = temp_dir_.GetPath();
+ file_thread_.reset(new base::Thread("NetLog File Thread"));
+ file_thread_->StartWithOptions(
+ base::Thread::Options(base::MessageLoop::TYPE_DEFAULT, 0));
+ ASSERT_TRUE(file_thread_->WaitUntilThreadStarted());
+ logger_.reset(new FileNetLogObserver(file_thread_->task_runner()));
}
- // Sends |num_entries_to_add| number of events of size |entry_size| to
- // |logger_|.
- //
- // |entry_size| must be >= 101, since the size of entries without a message,
- // |base_entry_size|, is dependent on TimeTicks formatting, and
- // |base_entry_size| can be up to 101 and cannot be shortened.
- void AddEntries(int num_entries_to_add, size_t entry_size) {
- // Get base size of event.
- const int kDummyId = 0;
- std::string message = "";
- NetLogParametersCallback callback =
- NetLog::StringCallback("message", &message);
- NetLogSource source(NetLogSourceType::HTTP2_SESSION, kDummyId);
- NetLogEntryData base_entry_data(NetLogEventType::PAC_JAVASCRIPT_ERROR,
- source, NetLogEventPhase::BEGIN,
- base::TimeTicks::Now(), &callback);
- NetLogEntry base_entry(&base_entry_data,
- NetLogCaptureMode::IncludeSocketBytes());
- std::unique_ptr<base::Value> value(base_entry.ToValue());
- std::string json;
- base::JSONWriter::Write(*value, &json);
- size_t base_entry_size = json.size();
-
- // The maximum value of base::TimeTicks::Now() will be the maximum value of
- // int64_t, and if the maximum number of digits are included, the
- // |base_entry_size| could be up to 101 characters. Check that the event
- // format does not include additional padding.
- DCHECK_LE(base_entry_size, 101u);
-
- // |entry_size| should be at least as big as the largest possible base
- // entry.
- EXPECT_GE(entry_size, 101u);
-
- // |entry_size| cannot be smaller than the minimum event size.
- EXPECT_GE(entry_size, base_entry_size);
-
- for (int i = 0; i < num_entries_to_add; i++) {
- source = NetLogSource(NetLogSourceType::HTTP2_SESSION, i);
- std::string id = std::to_string(i);
-
- // String size accounts for the number of digits in id so that all events
- // are the same size.
- message = std::string(entry_size - base_entry_size - id.size() + 1, 'x');
- callback = NetLog::StringCallback("message", &message);
- NetLogEntryData entry_data(NetLogEventType::PAC_JAVASCRIPT_ERROR, source,
- NetLogEventPhase::BEGIN,
- base::TimeTicks::Now(), &callback);
- NetLogEntry entry(&entry_data, NetLogCaptureMode::IncludeSocketBytes());
- logger_->OnAddEntry(entry);
- }
+ void StartObserving(std::unique_ptr<base::Value> constants,
+ URLRequestContext* url_request_context,
+ int total_file_size,
+ int num_files) {
+ logger_->StartObservingBounded(
+ &net_log_, NetLogCaptureMode::Default(), bounded_log_dir_,
+ std::move(constants), url_request_context, total_file_size, num_files);
+ }
+
+ ::testing::AssertionResult ReadNetLogFromDisk(
+ std::unique_ptr<base::Value>* root,
+ base::ListValue** events) {
+ std::string input;
+ ReadBoundedLogFiles(bounded_log_dir_, &input);
+ return ParseNetLogString(input, root, events);
+ }
+
+ base::FilePath GetEventFilePath(int index) const {
+ return bounded_log_dir_.AppendASCII("event_file_" + std::to_string(index) +
+ ".json");
+ }
+
+ static int64_t GetFileSize(const base::FilePath& path) {
+ int64_t file_size;
+ EXPECT_TRUE(base::GetFileSize(path, &file_size));
+ return file_size;
}
protected:
- base::FilePath log_path_;
NetLog net_log_;
std::unique_ptr<base::Thread> file_thread_;
- std::unique_ptr<BoundedFileNetLogObserver> logger_;
+ std::unique_ptr<FileNetLogObserver> logger_;
private:
base::ScopedTempDir temp_dir_;
+ base::FilePath bounded_log_dir_;
};
-TEST_F(BoundedFileNetLogObserverTest, ObserverDestroyedWithoutStopObserving) {
- logger_->StartObserving(&net_log_, log_path_, nullptr, nullptr,
- kLargeFileSize, kTotalNumFiles);
+// Instantiates each FileNetLogObserverTest to use bounded and unbounded modes.
+INSTANTIATE_TEST_CASE_P(,
+ FileNetLogObserverTest,
+ ::testing::Values(true, false));
+
+TEST_P(FileNetLogObserverTest, ObserverDestroyedWithoutStopObserving) {
+ StartObserving(nullptr, nullptr);
// Send dummy event
- AddEntries(1, kDummyEventSize);
+ AddEntries(logger_.get(), 1, kDummyEventSize);
logger_.reset();
file_thread_.reset();
- ASSERT_FALSE(base::PathExists(log_path_.AppendASCII("constants.json")));
- ASSERT_FALSE(base::PathExists(log_path_.AppendASCII("end_netlog.json")));
- for (int i = 0; i < kTotalNumFiles; i++) {
- ASSERT_FALSE(base::PathExists(
- log_path_.AppendASCII("event_file_" + std::to_string(i) + ".json")));
- }
+ ASSERT_FALSE(LogFilesExist());
}
-TEST_F(BoundedFileNetLogObserverTest, GeneratesValidJSONForNoEvents) {
+TEST_P(FileNetLogObserverTest, GeneratesValidJSONWithNoEvents) {
TestClosure closure;
- logger_->StartObserving(&net_log_, log_path_, nullptr, nullptr,
- kLargeFileSize, kTotalNumFiles);
+ StartObserving(nullptr, nullptr);
+
logger_->StopObserving(nullptr, closure.closure());
closure.WaitForResult();
- std::string input;
- AddAllFiles(&input);
- ASSERT_FALSE(input.empty());
-
- // Parse JSON
- base::JSONReader reader;
- std::unique_ptr<base::Value> root(reader.Read(input));
- ASSERT_TRUE(root) << reader.GetErrorMessage();
+ std::unique_ptr<base::Value> root;
+ base::ListValue* events;
+ ASSERT_TRUE(ReadNetLogFromDisk(&root, &events));
// Check that there are no events
- base::DictionaryValue* dict;
- ASSERT_TRUE(root->GetAsDictionary(&dict));
- base::ListValue* events;
- ASSERT_TRUE(dict->GetList("events", &events));
ASSERT_EQ(0u, events->GetSize());
// Check that constants are printed
+ base::DictionaryValue* dict;
+ ASSERT_TRUE(root->GetAsDictionary(&dict));
base::DictionaryValue* constants;
ASSERT_TRUE(dict->GetDictionary("constants", &constants));
}
-// Checks that capture_mode_ defaults correctly when set_capture_mode is not
-// called, and that |capture_mode_| is changed when set_capture_mode is called.
-TEST_F(BoundedFileNetLogObserverTest, SetsCaptureMode) {
- TestClosure default_closure;
+TEST_P(FileNetLogObserverTest, GeneratesValidJSONWithOneEvent) {
+ TestClosure closure;
- logger_->StartObserving(&net_log_, log_path_, nullptr, nullptr,
- kLargeFileSize, kTotalNumFiles);
- EXPECT_EQ(NetLogCaptureMode::Default(), logger_->capture_mode());
- logger_->StopObserving(nullptr, default_closure.closure());
+ StartObserving(nullptr, nullptr);
- default_closure.WaitForResult();
+ // Send dummy event.
+ AddEntries(logger_.get(), 1, kDummyEventSize);
- TestClosure new_capture_mode_closure;
- logger_ = std::unique_ptr<BoundedFileNetLogObserver>(
- new BoundedFileNetLogObserver(file_thread_->task_runner()));
+ logger_->StopObserving(nullptr, closure.closure());
- logger_->set_capture_mode(NetLogCaptureMode::IncludeCookiesAndCredentials());
- logger_->StartObserving(&net_log_, log_path_, nullptr, nullptr,
- kLargeFileSize, kTotalNumFiles);
- EXPECT_EQ(NetLogCaptureMode::IncludeCookiesAndCredentials(),
- logger_->capture_mode());
- logger_->StopObserving(nullptr, new_capture_mode_closure.closure());
+ closure.WaitForResult();
- new_capture_mode_closure.WaitForResult();
+ std::unique_ptr<base::Value> root;
+ base::ListValue* events;
+ ASSERT_TRUE(ReadNetLogFromDisk(&root, &events));
- std::string input;
- AddAllFiles(&input);
- ASSERT_FALSE(input.empty());
+ // Check that there is 1 event written.
+ ASSERT_EQ(1u, events->GetSize());
}
-TEST_F(BoundedFileNetLogObserverTest, GeneratesValidJSONWithOneEvent) {
+TEST_P(FileNetLogObserverTest, CustomConstants) {
TestClosure closure;
- logger_->StartObserving(&net_log_, log_path_, nullptr, nullptr,
- kLargeFileSize, kTotalNumFiles);
+ const char kConstantString[] = "awesome constant";
+ std::unique_ptr<base::Value> constants(
+ new base::StringValue(kConstantString));
- // Send dummy event.
- AddEntries(1, kDummyEventSize);
+ StartObserving(std::move(constants), nullptr);
logger_->StopObserving(nullptr, closure.closure());
closure.WaitForResult();
- std::string input;
- AddAllFiles(&input);
- ASSERT_FALSE(input.empty());
+ std::unique_ptr<base::Value> root;
+ base::ListValue* events;
+ ASSERT_TRUE(ReadNetLogFromDisk(&root, &events));
- // Parse input.
- base::JSONReader reader;
- std::unique_ptr<base::Value> root(reader.ReadToValue(input));
+ // Check that custom constant was correctly printed.
+ base::DictionaryValue* dict;
+ ASSERT_TRUE(root->GetAsDictionary(&dict));
+ std::string constants_string;
+ ASSERT_TRUE(dict->GetString("constants", &constants_string));
+ ASSERT_EQ(kConstantString, constants_string);
+}
- ASSERT_TRUE(root) << reader.GetErrorMessage();
+TEST_P(FileNetLogObserverTest, GeneratesValidJSONWithContext) {
+ TestClosure closure;
- // Check that there is 1 event written.
+ StartObserving(nullptr, nullptr);
+
+ // Create unique context.
+ TestURLRequestContext context(true);
+ context.set_net_log(&net_log_);
+ const int kDummyParam = 75;
+ std::unique_ptr<HttpNetworkSession::Params> params(
+ new HttpNetworkSession::Params);
+ params->quic_idle_connection_timeout_seconds = kDummyParam;
+ context.set_http_network_session_params(std::move(params));
+ context.Init();
+
+ logger_->StopObserving(&context, closure.closure());
+
+ closure.WaitForResult();
+
+ std::unique_ptr<base::Value> root;
+ base::ListValue* events;
+ ASSERT_TRUE(ReadNetLogFromDisk(&root, &events));
+
+ // Check that no events were written.
+ ASSERT_EQ(0u, events->GetSize());
+
+ // Make sure additional information is present and validate it.
base::DictionaryValue* dict;
ASSERT_TRUE(root->GetAsDictionary(&dict));
- base::ListValue* events;
- ASSERT_TRUE(dict->GetList("events", &events));
- ASSERT_EQ(1u, events->GetSize());
+ base::DictionaryValue* tab_info;
+ base::DictionaryValue* quic_info;
+ ASSERT_TRUE(dict->GetDictionary("tabInfo", &tab_info));
+ ASSERT_TRUE(tab_info->GetDictionary("quicInfo", &quic_info));
+ base::Value* timeout_value = nullptr;
+ int timeout;
+ ASSERT_TRUE(
+ quic_info->Get("idle_connection_timeout_seconds", &timeout_value));
+ ASSERT_TRUE(timeout_value->GetAsInteger(&timeout));
+ ASSERT_EQ(timeout, kDummyParam);
}
-TEST_F(BoundedFileNetLogObserverTest, GeneratesValidJSONWithMultipleEvents) {
- const int kTotalFileSize = 250000;
+TEST_P(FileNetLogObserverTest, GeneratesValidJSONWithContextWithActiveRequest) {
TestClosure closure;
- logger_->StartObserving(&net_log_, log_path_, nullptr, nullptr,
- kTotalFileSize, kTotalNumFiles);
+ // Create context, start a request.
+ TestURLRequestContext context(true);
+ context.set_net_log(&net_log_);
+ context.Init();
+ TestDelegate delegate;
+ delegate.set_quit_on_complete(false);
+
+ // URL doesn't matter. Requests can't fail synchronously.
+ std::unique_ptr<URLRequest> request(
+ context.CreateRequest(GURL("blah:blah"), IDLE, &delegate));
+ request->Start();
- AddEntries(2, kDummyEventSize);
+ StartObserving(nullptr, &context);
- logger_->StopObserving(nullptr, closure.closure());
+ logger_->StopObserving(&context, closure.closure());
closure.WaitForResult();
- std::string input;
- AddAllFiles(&input);
- ASSERT_FALSE(input.empty());
+ std::unique_ptr<base::Value> root;
+ base::ListValue* events;
+ ASSERT_TRUE(ReadNetLogFromDisk(&root, &events));
- base::JSONReader reader;
- std::unique_ptr<base::Value> root(reader.ReadToValue(input));
- ASSERT_TRUE(root) << reader.GetErrorMessage();
+ // Check that 1 event was written
+ ASSERT_EQ(1u, events->GetSize());
- // Check that 2 events are written.
+ // Make sure additional information is present, but don't validate it.
base::DictionaryValue* dict;
ASSERT_TRUE(root->GetAsDictionary(&dict));
+ base::DictionaryValue* tab_info;
+ ASSERT_TRUE(dict->GetDictionary("tabInfo", &tab_info));
+}
+
+// Adds events concurrently from several different threads. The exact order of
+// events seen by this test is non-deterministic.
+TEST_P(FileNetLogObserverTest, AddEventsFromMultipleThreads) {
+ const size_t kNumThreads = 10;
+ std::vector<std::unique_ptr<base::Thread>> threads(kNumThreads);
+ // Start all the threads. Waiting for them to start is to hopefuly improve
+ // the odds of hitting interesting races once events start being added.
+ for (size_t i = 0; i < threads.size(); ++i) {
+ threads[i] = base::MakeUnique<base::Thread>(
+ base::StringPrintf("WorkerThread%i", static_cast<int>(i)));
+ threads[i]->Start();
+ threads[i]->WaitUntilThreadStarted();
+ }
+
+ StartObserving(nullptr, nullptr);
+
+ const size_t kNumEventsAddedPerThread = 200;
+
+ // Add events in parallel from all the threads.
+ for (size_t i = 0; i < kNumThreads; ++i) {
+ threads[i]->task_runner()->PostTask(
+ FROM_HERE, base::Bind(&AddEntries, base::Unretained(logger_.get()),
+ kNumEventsAddedPerThread, kDummyEventSize));
+ }
+
+ // Join all the threads.
+ threads.clear();
+
+ // Stop observing.
+ TestClosure closure;
+ logger_->StopObserving(nullptr, closure.closure());
+ closure.WaitForResult();
+
+ // Check that the expected number of events were written to disk.
+ std::unique_ptr<base::Value> root;
base::ListValue* events;
- ASSERT_TRUE(dict->GetList("events", &events));
- ASSERT_EQ(2u, events->GetSize());
+ ASSERT_TRUE(ReadNetLogFromDisk(&root, &events));
+ ASSERT_EQ(kNumEventsAddedPerThread * kNumThreads, events->GetSize());
}
// Sends enough events to the observer to completely fill one file, but not
// write any events to an additional file. Checks the file bounds.
-TEST_F(BoundedFileNetLogObserverTest, EqualToOneFile) {
+TEST_F(FileNetLogObserverBoundedTest, EqualToOneFile) {
// The total size of the events is equal to the size of one file.
// |kNumEvents| * |kEventSize| = |kTotalFileSize| / |kTotalNumEvents|
const int kTotalFileSize = 5000;
@@ -297,32 +483,24 @@ TEST_F(BoundedFileNetLogObserverTest, EqualToOneFile) {
const int kEventSize = 250;
TestClosure closure;
- logger_->StartObserving(&net_log_, log_path_, nullptr, nullptr,
- kTotalFileSize, kTotalNumFiles);
+ StartObserving(nullptr, nullptr, kTotalFileSize, kTotalNumFiles);
- AddEntries(kNumEvents, kEventSize);
+ AddEntries(logger_.get(), kNumEvents, kEventSize);
logger_->StopObserving(nullptr, closure.closure());
closure.WaitForResult();
- std::string input;
- AddAllFiles(&input);
- ASSERT_FALSE(input.empty());
-
- base::JSONReader reader;
- std::unique_ptr<base::Value> root(reader.ReadToValue(input));
- ASSERT_TRUE(root) << reader.GetErrorMessage();
+ std::unique_ptr<base::Value> root;
+ base::ListValue* events;
+ ASSERT_TRUE(ReadNetLogFromDisk(&root, &events));
// Check that the correct number of events were written.
- base::DictionaryValue* dict;
- ASSERT_TRUE(root->GetAsDictionary(&dict));
- base::ListValue* events;
- ASSERT_TRUE(dict->GetList("events", &events));
ASSERT_EQ(static_cast<size_t>(kNumEvents), events->GetSize());
// Check that the last event in array is the last event written.
base::Value* last_event = nullptr;
ASSERT_TRUE(events->Get(events->GetSize() - 1, &last_event));
+ base::DictionaryValue* dict;
last_event->GetAsDictionary(&dict);
base::Value* id_value = nullptr;
ASSERT_TRUE(dict->Get("source.id", &id_value));
@@ -331,23 +509,17 @@ TEST_F(BoundedFileNetLogObserverTest, EqualToOneFile) {
ASSERT_EQ(kNumEvents - 1, id);
// Check that events have been written to the first file.
- base::ScopedFILE first_file(base::OpenFile(
- log_path_.AppendASCII("event_file_" + std::to_string(0) + ".json"),
- "rb"));
- ASSERT_TRUE(first_file.get());
- fseek(first_file.get(), 0, SEEK_END);
- ASSERT_TRUE(ftell(first_file.get()));
+ ASSERT_GT(GetFileSize(GetEventFilePath(0)), 0);
// Check that all event files except the first do not exist.
for (int i = 1; i < kTotalNumFiles; i++) {
- ASSERT_FALSE(base::PathExists(
- log_path_.AppendASCII("event_file_" + std::to_string(i) + ".json")));
+ ASSERT_FALSE(base::PathExists(GetEventFilePath(i)));
}
}
// Sends enough events to fill one file, and partially fill a second file.
// Checks the file bounds and writing to a new file.
-TEST_F(BoundedFileNetLogObserverTest, OneEventOverOneFile) {
+TEST_F(FileNetLogObserverBoundedTest, OneEventOverOneFile) {
// The total size of the events is greater than the size of one file, and
// less than the size of two files. The total size of all events except one
// is equal to the size of one file, so the last event will be the only event
@@ -358,33 +530,25 @@ TEST_F(BoundedFileNetLogObserverTest, OneEventOverOneFile) {
const int kEventSize = 200;
TestClosure closure;
- logger_->StartObserving(&net_log_, log_path_, nullptr, nullptr,
- kTotalFileSize, kTotalNumFiles);
+ StartObserving(nullptr, nullptr, kTotalFileSize, kTotalNumFiles);
- AddEntries(kNumEvents, kEventSize);
+ AddEntries(logger_.get(), kNumEvents, kEventSize);
logger_->StopObserving(nullptr, closure.closure());
closure.WaitForResult();
- std::string input;
- AddAllFiles(&input);
- ASSERT_FALSE(input.empty());
-
- base::JSONReader reader;
- std::unique_ptr<base::Value> root(reader.ReadToValue(input));
- ASSERT_TRUE(root) << reader.GetErrorMessage();
+ std::unique_ptr<base::Value> root;
+ base::ListValue* events;
+ ASSERT_TRUE(ReadNetLogFromDisk(&root, &events));
// Check that the correct number of events were written.
- base::DictionaryValue* dict;
- ASSERT_TRUE(root->GetAsDictionary(&dict));
- base::ListValue* events;
- ASSERT_TRUE(dict->GetList("events", &events));
ASSERT_EQ(static_cast<size_t>(kNumEvents), events->GetSize());
// Check that the last event in array is the last event written.
base::Value* last_event = nullptr;
ASSERT_TRUE(events->Get(events->GetSize() - 1, &last_event));
+ base::DictionaryValue* dict;
last_event->GetAsDictionary(&dict);
base::Value* id_value = nullptr;
ASSERT_TRUE(dict->Get("source.id", &id_value));
@@ -394,13 +558,12 @@ TEST_F(BoundedFileNetLogObserverTest, OneEventOverOneFile) {
// Check that all event files except the first two do not exist.
for (int i = 2; i < kTotalNumFiles; i++) {
- ASSERT_FALSE(base::PathExists(
- log_path_.AppendASCII("event_file_" + std::to_string(i) + ".json")));
+ ASSERT_FALSE(base::PathExists(GetEventFilePath(i)));
}
}
// Sends enough events to the observer to completely fill two files.
-TEST_F(BoundedFileNetLogObserverTest, EqualToTwoFiles) {
+TEST_F(FileNetLogObserverBoundedTest, EqualToTwoFiles) {
// The total size of the events is equal to the total size of two files.
// |kNumEvents| * |kEventSize| = 2 * |kTotalFileSize| / |kTotalNumEvents|
const int kTotalFileSize = 6000;
@@ -408,33 +571,25 @@ TEST_F(BoundedFileNetLogObserverTest, EqualToTwoFiles) {
const int kEventSize = 200;
TestClosure closure;
- logger_->StartObserving(&net_log_, log_path_, nullptr, nullptr,
- kTotalFileSize, kTotalNumFiles);
+ StartObserving(nullptr, nullptr, kTotalFileSize, kTotalNumFiles);
- AddEntries(kNumEvents, kEventSize);
+ AddEntries(logger_.get(), kNumEvents, kEventSize);
logger_->StopObserving(nullptr, closure.closure());
closure.WaitForResult();
- std::string input;
- AddAllFiles(&input);
- ASSERT_FALSE(input.empty());
-
- base::JSONReader reader;
- std::unique_ptr<base::Value> root(reader.ReadToValue(input));
- ASSERT_TRUE(root) << reader.GetErrorMessage();
+ std::unique_ptr<base::Value> root;
+ base::ListValue* events;
+ ASSERT_TRUE(ReadNetLogFromDisk(&root, &events));
// Check that the correct number of events were written.
- base::DictionaryValue* dict;
- ASSERT_TRUE(root->GetAsDictionary(&dict));
- base::ListValue* events;
- ASSERT_TRUE(dict->GetList("events", &events));
ASSERT_EQ(static_cast<size_t>(kNumEvents), events->GetSize());
// Check that the last event in array is the last event written.
base::Value* last_event = nullptr;
ASSERT_TRUE(events->Get(events->GetSize() - 1, &last_event));
+ base::DictionaryValue* dict;
last_event->GetAsDictionary(&dict);
base::Value* id_value = nullptr;
ASSERT_TRUE(dict->Get("source.id", &id_value));
@@ -446,25 +601,20 @@ TEST_F(BoundedFileNetLogObserverTest, EqualToTwoFiles) {
for (int i = 0; i < (kNumEvents * kEventSize) /
((kTotalFileSize - 1) / kTotalNumFiles + 1);
i++) {
- base::ScopedFILE file_to_test(base::OpenFile(
- log_path_.AppendASCII("event_file_" + std::to_string(i) + ".json"),
- "rb"));
- ASSERT_TRUE(file_to_test.get());
- fseek(file_to_test.get(), 0, SEEK_END);
- ASSERT_GE(ftell(file_to_test.get()), kTotalFileSize / kTotalNumFiles);
+ ASSERT_GE(GetFileSize(GetEventFilePath(i)),
+ static_cast<int64_t>(kTotalFileSize / kTotalNumFiles));
}
// Check that all event files except the first two do not exist.
for (int i = 2; i < kTotalNumFiles; i++) {
- ASSERT_FALSE(base::PathExists(
- log_path_.AppendASCII("event_file_" + std::to_string(i) + ".json")));
+ ASSERT_FALSE(base::PathExists(GetEventFilePath(i)));
}
}
// Sends exactly enough events to the observer to completely fill all files,
// so that all events fit into the event files and no files need to be
// overwritten.
-TEST_F(BoundedFileNetLogObserverTest, FillAllFilesNoOverwriting) {
+TEST_F(FileNetLogObserverBoundedTest, FillAllFilesNoOverwriting) {
// The total size of events is equal to the total size of all files.
// |kEventSize| * |kNumEvents| = |kTotalFileSize|
const int kTotalFileSize = 10000;
@@ -473,33 +623,25 @@ TEST_F(BoundedFileNetLogObserverTest, FillAllFilesNoOverwriting) {
const int kNumEvents = kTotalNumFiles * ((kFileSize - 1) / kEventSize + 1);
TestClosure closure;
- logger_->StartObserving(&net_log_, log_path_, nullptr, nullptr,
- kTotalFileSize, kTotalNumFiles);
+ StartObserving(nullptr, nullptr, kTotalFileSize, kTotalNumFiles);
- AddEntries(kNumEvents, kEventSize);
+ AddEntries(logger_.get(), kNumEvents, kEventSize);
logger_->StopObserving(nullptr, closure.closure());
closure.WaitForResult();
- std::string input;
- AddAllFiles(&input);
- ASSERT_FALSE(input.empty());
-
- base::JSONReader reader;
- std::unique_ptr<base::Value> root(reader.ReadToValue(input));
- ASSERT_TRUE(root) << reader.GetErrorMessage();
+ std::unique_ptr<base::Value> root;
+ base::ListValue* events;
+ ASSERT_TRUE(ReadNetLogFromDisk(&root, &events));
// Check that the correct number of events were written.
- base::DictionaryValue* dict;
- ASSERT_TRUE(root->GetAsDictionary(&dict));
- base::ListValue* events;
- ASSERT_TRUE(dict->GetList("events", &events));
ASSERT_EQ(static_cast<size_t>(kNumEvents), events->GetSize());
// Check that the last event in array is the last event written.
base::Value* last_event = nullptr;
ASSERT_TRUE(events->Get(events->GetSize() - 1, &last_event));
+ base::DictionaryValue* dict;
last_event->GetAsDictionary(&dict);
base::Value* id_value = nullptr;
ASSERT_TRUE(dict->Get("source.id", &id_value));
@@ -509,18 +651,14 @@ TEST_F(BoundedFileNetLogObserverTest, FillAllFilesNoOverwriting) {
// Check that all the event files are full.
for (int i = 0; i < kTotalNumFiles; i++) {
- base::ScopedFILE file_to_test(base::OpenFile(
- log_path_.AppendASCII("event_file_" + std::to_string(i) + ".json"),
- "rb"));
- ASSERT_TRUE(file_to_test.get());
- fseek(file_to_test.get(), 0, SEEK_END);
- ASSERT_GE(ftell(file_to_test.get()), kTotalFileSize / kTotalNumFiles);
+ ASSERT_GE(GetFileSize(GetEventFilePath(i)),
+ static_cast<int64_t>(kTotalFileSize / kTotalNumFiles));
}
}
// Sends more events to the observer than will fill the WriteQueue, forcing the
// queue to drop an event. Checks that the queue drops the oldest event.
-TEST_F(BoundedFileNetLogObserverTest, DropOldEventsFromWriteQueue) {
+TEST_F(FileNetLogObserverBoundedTest, DropOldEventsFromWriteQueue) {
// The total size of events is greater than the WriteQueue's memory limit, so
// the oldest event must be dropped from the queue and not written to any
// file.
@@ -531,28 +669,19 @@ TEST_F(BoundedFileNetLogObserverTest, DropOldEventsFromWriteQueue) {
const int kFileSize = kTotalFileSize / kTotalNumFiles;
TestClosure closure;
- logger_->StartObserving(&net_log_, log_path_, nullptr, nullptr,
- kTotalFileSize, kTotalNumFiles);
+ StartObserving(nullptr, nullptr, kTotalFileSize, kTotalNumFiles);
- AddEntries(kNumEvents, kEventSize);
+ AddEntries(logger_.get(), kNumEvents, kEventSize);
logger_->StopObserving(nullptr, closure.closure());
closure.WaitForResult();
- std::string input;
- AddAllFiles(&input);
- ASSERT_FALSE(input.empty());
-
- base::JSONReader reader;
- std::unique_ptr<base::Value> root(reader.ReadToValue(input));
- ASSERT_TRUE(root) << reader.GetErrorMessage();
+ std::unique_ptr<base::Value> root;
+ base::ListValue* events;
+ ASSERT_TRUE(ReadNetLogFromDisk(&root, &events));
// Check that the correct number of events were written.
- base::DictionaryValue* dict;
- ASSERT_TRUE(root->GetAsDictionary(&dict));
- base::ListValue* events;
- ASSERT_TRUE(dict->GetList("events", &events));
ASSERT_EQ(
static_cast<size_t>(kTotalNumFiles * ((kFileSize - 1) / kEventSize + 1)),
events->GetSize());
@@ -560,6 +689,7 @@ TEST_F(BoundedFileNetLogObserverTest, DropOldEventsFromWriteQueue) {
// Check that the oldest event was dropped from the queue.
base::Value* event_to_check = nullptr;
ASSERT_TRUE(events->Get(0, &event_to_check));
+ base::DictionaryValue* dict;
event_to_check->GetAsDictionary(&dict);
base::Value* id_value = nullptr;
ASSERT_TRUE(dict->Get("source.id", &id_value));
@@ -579,7 +709,7 @@ TEST_F(BoundedFileNetLogObserverTest, DropOldEventsFromWriteQueue) {
// Sends twice as many events as will fill all files to the observer, so that
// all of the event files will be filled twice, and every file will be
// overwritten.
-TEST_F(BoundedFileNetLogObserverTest, OverwriteAllFiles) {
+TEST_F(FileNetLogObserverBoundedTest, OverwriteAllFiles) {
// The total size of the events is much greater than twice the number of
// events that can fit in the event files, to make sure that the extra events
// are written to a file, not just dropped from the queue.
@@ -590,28 +720,17 @@ TEST_F(BoundedFileNetLogObserverTest, OverwriteAllFiles) {
const int kFileSize = kTotalFileSize / kTotalNumFiles;
TestClosure closure;
- logger_->StartObserving(&net_log_, log_path_, nullptr, nullptr,
- kTotalFileSize, kTotalNumFiles);
+ StartObserving(nullptr, nullptr, kTotalFileSize, kTotalNumFiles);
- AddEntries(kNumEvents, kEventSize);
+ AddEntries(logger_.get(), kNumEvents, kEventSize);
logger_->StopObserving(nullptr, closure.closure());
closure.WaitForResult();
- std::string input;
- AddAllFiles(&input);
- ASSERT_FALSE(input.empty());
-
- base::JSONReader reader;
- std::unique_ptr<base::Value> root(reader.ReadToValue(input));
- ASSERT_TRUE(root) << reader.GetErrorMessage();
-
- // Check that the correct number of events were written.
- base::DictionaryValue* dict;
- ASSERT_TRUE(root->GetAsDictionary(&dict));
+ std::unique_ptr<base::Value> root;
base::ListValue* events;
- ASSERT_TRUE(dict->GetList("events", &events));
+ ASSERT_TRUE(ReadNetLogFromDisk(&root, &events));
// Check that the minimum number of events that should fit in event files
// have been written to all files.
@@ -635,6 +754,7 @@ TEST_F(BoundedFileNetLogObserverTest, OverwriteAllFiles) {
// file, mark the corresponding bool in |events_written| as true.
for (size_t i = 0; i < events->GetSize(); i++) {
ASSERT_TRUE(events->Get(i, &event));
+ base::DictionaryValue* dict;
event->GetAsDictionary(&dict);
ASSERT_TRUE(dict->Get("source.id", &id_value));
ASSERT_TRUE(id_value->GetAsInteger(&id));
@@ -651,19 +771,15 @@ TEST_F(BoundedFileNetLogObserverTest, OverwriteAllFiles) {
// Check that there are events written to all files.
for (int i = 0; i < kTotalNumFiles; i++) {
- base::ScopedFILE file_to_test(base::OpenFile(
- log_path_.AppendASCII("event_file_" + std::to_string(i) + ".json"),
- "rb"));
- ASSERT_TRUE(file_to_test.get());
- fseek(file_to_test.get(), 0, SEEK_END);
- ASSERT_GE(ftell(file_to_test.get()), kEventSize);
+ ASSERT_GE(GetFileSize(GetEventFilePath(i)),
+ static_cast<int64_t>(kEventSize));
}
}
// Sends enough events to the observer to fill all event files, plus overwrite
// some files, without overwriting all of them. Checks that the FileWriter
// overwrites the file with the oldest events.
-TEST_F(BoundedFileNetLogObserverTest, PartiallyOverwriteFiles) {
+TEST_F(FileNetLogObserverBoundedTest, PartiallyOverwriteFiles) {
// The number of events sent to the observer is greater than the number of
// events that can fit into the event files, but the events can fit in less
// than twice the number of event files, so not every file will need to be
@@ -676,27 +792,17 @@ TEST_F(BoundedFileNetLogObserverTest, PartiallyOverwriteFiles) {
const int kFileSize = kTotalFileSize / kTotalNumFiles;
TestClosure closure;
- logger_->StartObserving(&net_log_, log_path_, nullptr, nullptr,
- kTotalFileSize, kTotalNumFiles);
+ StartObserving(nullptr, nullptr, kTotalFileSize, kTotalNumFiles);
- AddEntries(kNumEvents, kEventSize);
+ AddEntries(logger_.get(), kNumEvents, kEventSize);
logger_->StopObserving(nullptr, closure.closure());
closure.WaitForResult();
- std::string input;
- AddAllFiles(&input);
- ASSERT_FALSE(input.empty());
-
- base::JSONReader reader;
- std::unique_ptr<base::Value> root(reader.ReadToValue(input));
- ASSERT_TRUE(root) << reader.GetErrorMessage();
-
- base::DictionaryValue* dict;
- ASSERT_TRUE(root->GetAsDictionary(&dict));
+ std::unique_ptr<base::Value> root;
base::ListValue* events;
- ASSERT_TRUE(dict->GetList("events", &events));
+ ASSERT_TRUE(ReadNetLogFromDisk(&root, &events));
// Check that the minimum number of events that should fit in event files
// have been written to a file.
@@ -712,6 +818,7 @@ TEST_F(BoundedFileNetLogObserverTest, PartiallyOverwriteFiles) {
int id;
for (size_t i = 0; i < events->GetSize(); i++) {
ASSERT_TRUE(events->Get(i, &event));
+ base::DictionaryValue* dict;
event->GetAsDictionary(&dict);
ASSERT_TRUE(dict->Get("source.id", &id_value));
ASSERT_TRUE(id_value->GetAsInteger(&id));
@@ -725,136 +832,11 @@ TEST_F(BoundedFileNetLogObserverTest, PartiallyOverwriteFiles) {
// Check that there are events written to all files.
for (int i = 0; i < kTotalNumFiles; i++) {
- base::ScopedFILE file_to_test(base::OpenFile(
- log_path_.AppendASCII("event_file_" + std::to_string(i) + ".json"),
- "rb"));
- ASSERT_TRUE(file_to_test.get());
- fseek(file_to_test.get(), 0, SEEK_END);
- ASSERT_GE(ftell(file_to_test.get()), kEventSize);
+ ASSERT_GE(GetFileSize(GetEventFilePath(i)),
+ static_cast<int64_t>(kEventSize));
}
}
-TEST_F(BoundedFileNetLogObserverTest, CustomConstants) {
- TestClosure closure;
-
- const char kConstantString[] = "awesome constant";
- std::unique_ptr<base::Value> constants(
- new base::StringValue(kConstantString));
-
- logger_->StartObserving(&net_log_, log_path_, constants.get(), nullptr,
- kLargeFileSize, kTotalNumFiles);
-
- logger_->StopObserving(nullptr, closure.closure());
-
- closure.WaitForResult();
-
- std::string input;
- AddAllFiles(&input);
- ASSERT_FALSE(input.empty());
-
- base::JSONReader reader;
- std::unique_ptr<base::Value> root(reader.ReadToValue(input));
- ASSERT_TRUE(root) << reader.GetErrorMessage();
-
- // Check that custom constant was correctly printed.
- base::DictionaryValue* dict;
- ASSERT_TRUE(root->GetAsDictionary(&dict));
- std::string constants_string;
- ASSERT_TRUE(dict->GetString("constants", &constants_string));
- ASSERT_EQ(kConstantString, constants_string);
-}
-
-TEST_F(BoundedFileNetLogObserverTest, GeneratesValidJSONWithContext) {
- TestClosure closure;
-
- logger_->StartObserving(&net_log_, log_path_, nullptr, nullptr,
- kLargeFileSize, kTotalNumFiles);
-
- // Create unique context.
- TestURLRequestContext context(true);
- context.set_net_log(&net_log_);
- const int kDummyParam = 75;
- std::unique_ptr<HttpNetworkSession::Params> params(
- new HttpNetworkSession::Params);
- params->quic_idle_connection_timeout_seconds = kDummyParam;
- context.set_http_network_session_params(std::move(params));
- context.Init();
-
- logger_->StopObserving(&context, closure.closure());
-
- closure.WaitForResult();
-
- std::string input;
- AddAllFiles(&input);
- ASSERT_FALSE(input.empty());
-
- base::JSONReader reader;
- std::unique_ptr<base::Value> root(reader.ReadToValue(input));
- ASSERT_TRUE(root) << reader.GetErrorMessage();
-
- // Check that no events were written.
- base::DictionaryValue* dict;
- ASSERT_TRUE(root->GetAsDictionary(&dict));
- base::ListValue* events;
- ASSERT_TRUE(dict->GetList("events", &events));
- ASSERT_EQ(0u, events->GetSize());
-
- // Make sure additional information is present and validate it.
- base::DictionaryValue* tab_info;
- base::DictionaryValue* quic_info;
- ASSERT_TRUE(dict->GetDictionary("tabInfo", &tab_info));
- ASSERT_TRUE(tab_info->GetDictionary("quicInfo", &quic_info));
- base::Value* timeout_value = nullptr;
- int timeout;
- ASSERT_TRUE(
- quic_info->Get("idle_connection_timeout_seconds", &timeout_value));
- ASSERT_TRUE(timeout_value->GetAsInteger(&timeout));
- ASSERT_EQ(timeout, kDummyParam);
-}
-
-TEST_F(BoundedFileNetLogObserverTest,
- GeneratesValidJSONWithContextWithActiveRequest) {
- TestClosure closure;
-
- // Create context, start a request.
- TestURLRequestContext context(true);
- context.set_net_log(&net_log_);
- context.Init();
- TestDelegate delegate;
- delegate.set_quit_on_complete(false);
-
- // URL doesn't matter. Requests can't fail synchronously.
- std::unique_ptr<URLRequest> request(
- context.CreateRequest(GURL("blah:blah"), IDLE, &delegate));
- request->Start();
-
- logger_->StartObserving(&net_log_, log_path_, nullptr, &context,
- kLargeFileSize, kTotalNumFiles);
-
- logger_->StopObserving(&context, closure.closure());
-
- closure.WaitForResult();
-
- std::string input;
- AddAllFiles(&input);
- ASSERT_FALSE(input.empty());
-
- base::JSONReader reader;
- std::unique_ptr<base::Value> root(reader.ReadToValue(input));
- ASSERT_TRUE(root) << reader.GetErrorMessage();
-
- // Check that 1 event was written
- base::DictionaryValue* dict;
- ASSERT_TRUE(root->GetAsDictionary(&dict));
- base::ListValue* events;
- ASSERT_TRUE(dict->GetList("events", &events));
- ASSERT_EQ(1u, events->GetSize());
-
- // Make sure additional information is present, but don't validate it.
- base::DictionaryValue* tab_info;
- ASSERT_TRUE(dict->GetDictionary("tabInfo", &tab_info));
-}
-
} // namespace
} // namespace net
diff --git a/chromium/net/log/net_log.cc b/chromium/net/log/net_log.cc
index 669b1110321..c482877b1ba 100644
--- a/chromium/net/log/net_log.cc
+++ b/chromium/net/log/net_log.cc
@@ -4,6 +4,7 @@
#include "net/log/net_log.h"
+#include <algorithm>
#include <utility>
#include "base/bind.h"
@@ -133,7 +134,11 @@ void NetLog::DeprecatedAddObserver(NetLog::ThreadSafeObserver* observer,
base::AutoLock lock(lock_);
DCHECK(!observer->net_log_);
- observers_.AddObserver(observer);
+ DCHECK(!HasObserver(observer));
+ DCHECK_LT(observers_.size(), 20u); // Performance sanity check.
+
+ observers_.push_back(observer);
+
observer->net_log_ = this;
observer->capture_mode_ = capture_mode;
UpdateIsCapturing();
@@ -143,7 +148,7 @@ void NetLog::SetObserverCaptureMode(NetLog::ThreadSafeObserver* observer,
NetLogCaptureMode capture_mode) {
base::AutoLock lock(lock_);
- DCHECK(observers_.HasObserver(observer));
+ DCHECK(HasObserver(observer));
DCHECK_EQ(this, observer->net_log_);
observer->capture_mode_ = capture_mode;
}
@@ -151,9 +156,12 @@ void NetLog::SetObserverCaptureMode(NetLog::ThreadSafeObserver* observer,
void NetLog::DeprecatedRemoveObserver(NetLog::ThreadSafeObserver* observer) {
base::AutoLock lock(lock_);
- DCHECK(observers_.HasObserver(observer));
DCHECK_EQ(this, observer->net_log_);
- observers_.RemoveObserver(observer);
+
+ auto it = std::find(observers_.begin(), observers_.end(), observer);
+ DCHECK(it != observers_.end());
+ observers_.erase(it);
+
observer->net_log_ = NULL;
observer->capture_mode_ = NetLogCaptureMode();
UpdateIsCapturing();
@@ -161,8 +169,13 @@ void NetLog::DeprecatedRemoveObserver(NetLog::ThreadSafeObserver* observer) {
void NetLog::UpdateIsCapturing() {
lock_.AssertAcquired();
- base::subtle::NoBarrier_Store(&is_capturing_,
- observers_.might_have_observers() ? 1 : 0);
+ base::subtle::NoBarrier_Store(&is_capturing_, observers_.size() ? 1 : 0);
+}
+
+bool NetLog::HasObserver(ThreadSafeObserver* observer) {
+ lock_.AssertAcquired();
+ auto it = std::find(observers_.begin(), observers_.end(), observer);
+ return it != observers_.end();
}
// static
@@ -279,8 +292,8 @@ void NetLog::AddEntry(NetLogEventType type,
// Notify all of the log observers.
base::AutoLock lock(lock_);
- for (auto& observer : observers_)
- observer.OnAddEntryData(entry_data);
+ for (auto* observer : observers_)
+ observer->OnAddEntryData(entry_data);
}
} // namespace net
diff --git a/chromium/net/log/net_log.h b/chromium/net/log/net_log.h
index 486e6b6fd70..41e8cc64e83 100644
--- a/chromium/net/log/net_log.h
+++ b/chromium/net/log/net_log.h
@@ -8,11 +8,11 @@
#include <stdint.h>
#include <string>
+#include <vector>
#include "base/atomicops.h"
#include "base/compiler_specific.h"
#include "base/macros.h"
-#include "base/observer_list.h"
#include "base/strings/string16.h"
#include "base/synchronization/lock.h"
#include "base/time/time.h"
@@ -26,7 +26,6 @@
#include "net/log/net_log_source_type.h"
namespace base {
-class DictionaryValue;
class Value;
}
@@ -208,6 +207,10 @@ class NET_EXPORT NetLog {
// |has_observers_|. Must have acquired |lock_| prior to calling.
void UpdateIsCapturing();
+ // Returns true if |observer| is watching this NetLog. Must
+ // be called while |lock_| is already held.
+ bool HasObserver(ThreadSafeObserver* observer);
+
// |lock_| protects access to |observers_|.
base::Lock lock_;
@@ -219,8 +222,15 @@ class NET_EXPORT NetLog {
// so it can be accessed without needing a lock.
base::subtle::Atomic32 is_capturing_;
+ // |observers_| is a list of observers, ordered by when they were added.
+ // Pointers contained in |observers_| are non-owned, and must
+ // remain valid.
+ //
// |lock_| must be acquired whenever reading or writing to this.
- base::ObserverList<ThreadSafeObserver, true> observers_;
+ //
+ // In practice |observers_| will be very small (<5) so O(n)
+ // operations on it are fine.
+ std::vector<ThreadSafeObserver*> observers_;
DISALLOW_COPY_AND_ASSIGN(NetLog);
};
diff --git a/chromium/net/log/net_log_event_type_list.h b/chromium/net/log/net_log_event_type_list.h
index 2508cc50514..50e9a8491e7 100644
--- a/chromium/net/log/net_log_event_type_list.h
+++ b/chromium/net/log/net_log_event_type_list.h
@@ -850,7 +850,7 @@ EVENT_TYPE(URL_REQUEST_DELEGATE)
// Logged when a delegate informs the URL_REQUEST of what's currently blocking
// the request. The parameters attached to the begin event are:
// {
-// "delegate_info": <Information about what's blocking the request>,
+// "delegate_blocked_by": <Information about what's blocking the request>,
// }
EVENT_TYPE(DELEGATE_INFO)
@@ -1435,6 +1435,14 @@ EVENT_TYPE(HTTP2_SESSION_CLOSE)
// Event when the creation of a stream is stalled because we're at
// the maximum number of concurrent streams.
+// {
+//
+// "num_active_streams": <Number of active streams>,
+// "num_created_streams": <Number of created streams>,
+// "num_pushed_streams": <Number of pushed streams>,
+// "max_concurrent_streams": <Maximum number of concurrent streams>,
+// "url": <Request URL>,
+// }
EVENT_TYPE(HTTP2_SESSION_STALLED_MAX_STREAMS)
// Received an out-of-range value for initial window size in SETTINGS
@@ -1527,6 +1535,15 @@ EVENT_TYPE(HTTP2_STREAM_UPDATE_RECV_WINDOW)
// }
EVENT_TYPE(HTTP2_STREAM_ERROR)
+// A PRIORITY update is sent to the server.
+// {
+// "stream_id": <The stream id>,
+// "parent_stream_id": <The stream's new parent stream>,
+// "weight": <The stream's new weight>,
+// "exclusive": <Whether the new dependency is exclusive>,
+// }
+EVENT_TYPE(HTTP2_STREAM_SEND_PRIORITY)
+
// ------------------------------------------------------------------------
// SpdyProxyClientSocket
// ------------------------------------------------------------------------
@@ -1754,48 +1771,6 @@ EVENT_TYPE(QUIC_SESSION_RST_STREAM_FRAME_RECEIVED)
// }
EVENT_TYPE(QUIC_SESSION_RST_STREAM_FRAME_SENT)
-// Session received a CONGESTION_FEEDBACK frame.
-// {
-// "type": <The specific type of feedback being provided>,
-// Other per-feedback type details:
-//
-// for InterArrival:
-// "accumulated_number_of_lost_packets": <Total number of lost packets
-// over the life of this session>,
-// "received_packets": <List of strings of the form:
-// <sequence_number>@<receive_time_in_ms>>,
-//
-// for FixRate:
-// "bitrate_in_bytes_per_second": <The configured bytes per second>,
-//
-// for TCP:
-// "accumulated_number_of_lost_packets": <Total number of lost packets
-// over the life of this session>,
-// "receive_window": <Number of bytes in the receive window>,
-// }
-EVENT_TYPE(QUIC_SESSION_CONGESTION_FEEDBACK_FRAME_RECEIVED)
-
-// Session received a CONGESTION_FEEDBACK frame.
-// {
-// "type": <The specific type of feedback being provided>,
-// Other per-feedback type details:
-//
-// for InterArrival:
-// "accumulated_number_of_lost_packets": <Total number of lost packets
-// over the life of this session>,
-// "received_packets": <List of strings of the form:
-// <sequence_number>@<receive_time_in_ms>>,
-//
-// for FixRate:
-// "bitrate_in_bytes_per_second": <The configured bytes per second>,
-//
-// for TCP:
-// "accumulated_number_of_lost_packets": <Total number of lost packets
-// over the life of this session>,
-// "receive_window": <Number of bytes in the receive window>,
-// }
-EVENT_TYPE(QUIC_SESSION_CONGESTION_FEEDBACK_FRAME_SENT)
-
// Session received a CONNECTION_CLOSE frame.
// {
// "quic_error": <QuicErrorCode in the frame>,
@@ -2123,6 +2098,13 @@ EVENT_TYPE(SERVICE_WORKER_START_WORKER)
// }
EVENT_TYPE(SERVICE_WORKER_FETCH_EVENT)
+// This event is emitted when a request for a service worker script or its
+// imported scripts could not be handled.
+// {
+// "error": The error reason as a string.
+// }
+EVENT_TYPE(SERVICE_WORKER_SCRIPT_LOAD_UNHANDLED_REQUEST_ERROR)
+
// ------------------------------------------------------------------------
// Global events
// ------------------------------------------------------------------------
@@ -3064,3 +3046,13 @@ EVENT_TYPE(UPLOAD_DATA_STREAM_INIT)
// the end of file. Result < 0 means an error.>
// }
EVENT_TYPE(UPLOAD_DATA_STREAM_READ)
+
+// -----------------------------------------------------------------------------
+// ResourceScheduler related events
+// -----------------------------------------------------------------------------
+
+// The ResourceScheduler has started a previously blocked request. Parameters:
+// {
+// "trigger": <Trigger for evaluation that caused request start>
+// }
+EVENT_TYPE(RESOURCE_SCHEDULER_REQUEST_STARTED)
diff --git a/chromium/net/log/net_log_source_type_list.h b/chromium/net/log/net_log_source_type_list.h
index 1c729a68895..b874529b32c 100644
--- a/chromium/net/log/net_log_source_type_list.h
+++ b/chromium/net/log/net_log_source_type_list.h
@@ -10,7 +10,11 @@ SOURCE_TYPE(NONE)
SOURCE_TYPE(URL_REQUEST)
SOURCE_TYPE(PROXY_SCRIPT_DECIDER)
-SOURCE_TYPE(CONNECT_JOB)
+SOURCE_TYPE(HTTP_PROXY_CONNECT_JOB)
+SOURCE_TYPE(SOCKS_CONNECT_JOB)
+SOURCE_TYPE(SSL_CONNECT_JOB)
+SOURCE_TYPE(TRANSPORT_CONNECT_JOB)
+SOURCE_TYPE(WEB_SOCKET_TRANSPORT_CONNECT_JOB)
SOURCE_TYPE(SOCKET)
SOURCE_TYPE(HTTP2_SESSION)
SOURCE_TYPE(QUIC_SESSION)
diff --git a/chromium/net/log/net_log_util.cc b/chromium/net/log/net_log_util.cc
index 1633e529110..75c88ea4599 100644
--- a/chromium/net/log/net_log_util.cc
+++ b/chromium/net/log/net_log_util.cc
@@ -37,9 +37,9 @@
#include "net/proxy/proxy_config.h"
#include "net/proxy/proxy_retry_info.h"
#include "net/proxy/proxy_service.h"
-#include "net/quic/core/quic_protocol.h"
-#include "net/quic/core/quic_utils.h"
-#include "net/socket/next_proto.h"
+#include "net/quic/core/quic_error_codes.h"
+#include "net/quic/core/quic_packets.h"
+#include "net/socket/ssl_client_socket.h"
#include "net/url_request/url_request.h"
#include "net/url_request/url_request_context.h"
@@ -213,8 +213,7 @@ std::unique_ptr<base::DictionaryValue> GetNetConstants() {
for (QuicErrorCode error = QUIC_NO_ERROR; error < QUIC_LAST_ERROR;
error = static_cast<QuicErrorCode>(error + 1)) {
- dict->SetInteger(QuicUtils::ErrorToString(error),
- static_cast<int>(error));
+ dict->SetInteger(QuicErrorCodeToString(error), static_cast<int>(error));
}
constants_dict->Set("quicError", std::move(dict));
@@ -228,7 +227,7 @@ std::unique_ptr<base::DictionaryValue> GetNetConstants() {
for (QuicRstStreamErrorCode error = QUIC_STREAM_NO_ERROR;
error < QUIC_STREAM_LAST_ERROR;
error = static_cast<QuicRstStreamErrorCode>(error + 1)) {
- dict->SetInteger(QuicUtils::StreamErrorToString(error),
+ dict->SetInteger(QuicRstStreamErrorCodeToString(error),
static_cast<int>(error));
}
diff --git a/chromium/net/log/net_log_util.h b/chromium/net/log/net_log_util.h
index 829dcf569a5..9558defc58d 100644
--- a/chromium/net/log/net_log_util.h
+++ b/chromium/net/log/net_log_util.h
@@ -13,7 +13,6 @@
namespace base {
class DictionaryValue;
-class Value;
}
namespace net {
diff --git a/chromium/net/log/trace_net_log_observer.cc b/chromium/net/log/trace_net_log_observer.cc
index 4c7b7dcc605..af69aca14ad 100644
--- a/chromium/net/log/trace_net_log_observer.cc
+++ b/chromium/net/log/trace_net_log_observer.cc
@@ -90,6 +90,10 @@ void TraceNetLogObserver::WatchForTraceStart(NetLog* netlog) {
DCHECK(!net_log_to_watch_);
DCHECK(!net_log());
net_log_to_watch_ = netlog;
+ // Tracing can start before the observer is even created, for instance for
+ // startup tracing.
+ if (base::trace_event::TraceLog::GetInstance()->IsEnabled())
+ OnTraceLogEnabled();
base::trace_event::TraceLog::GetInstance()->AddEnabledStateObserver(this);
}
@@ -97,12 +101,21 @@ void TraceNetLogObserver::StopWatchForTraceStart() {
// Should only stop if is currently watching.
DCHECK(net_log_to_watch_);
base::trace_event::TraceLog::GetInstance()->RemoveEnabledStateObserver(this);
+ // net_log() != nullptr iff NetLog::DeprecatedAddObserver() has been called.
+ // This implies that if the netlog category wasn't enabled, then
+ // NetLog::DeprecatedRemoveObserver() will not get called, and there won't be
+ // a crash in NetLog::DeprecatedRemoveObserver().
if (net_log())
net_log()->DeprecatedRemoveObserver(this);
- net_log_to_watch_ = NULL;
+ net_log_to_watch_ = nullptr;
}
void TraceNetLogObserver::OnTraceLogEnabled() {
+ bool enabled;
+ TRACE_EVENT_CATEGORY_GROUP_ENABLED(kNetLogTracingCategory, &enabled);
+ if (!enabled)
+ return;
+
net_log_to_watch_->DeprecatedAddObserver(this, NetLogCaptureMode::Default());
}
diff --git a/chromium/net/log/trace_net_log_observer_unittest.cc b/chromium/net/log/trace_net_log_observer_unittest.cc
index 60c54ee0f9f..6a3c5b05ebc 100644
--- a/chromium/net/log/trace_net_log_observer_unittest.cc
+++ b/chromium/net/log/trace_net_log_observer_unittest.cc
@@ -319,6 +319,31 @@ TEST_F(TraceNetLogObserverTest, CreateObserverAfterTracingStarts) {
TestNetLogEntry::List entries;
net_log()->GetEntries(&entries);
EXPECT_EQ(3u, entries.size());
+ EXPECT_EQ(1u, trace_events()->GetSize());
+}
+
+TEST_F(TraceNetLogObserverTest,
+ CreateObserverAfterTracingStartsDisabledCategory) {
+ set_trace_net_log_observer(nullptr);
+
+ std::string disabled_netlog_category =
+ std::string("-") + kNetLogTracingCategory;
+ TraceLog::GetInstance()->SetEnabled(
+ base::trace_event::TraceConfig(disabled_netlog_category, ""),
+ TraceLog::RECORDING_MODE);
+
+ set_trace_net_log_observer(new TraceNetLogObserver());
+ trace_net_log_observer()->WatchForTraceStart(net_log());
+ net_log()->AddGlobalEntry(NetLogEventType::CANCELLED);
+ trace_net_log_observer()->StopWatchForTraceStart();
+ net_log()->AddGlobalEntry(NetLogEventType::REQUEST_ALIVE);
+ net_log()->AddGlobalEntry(NetLogEventType::URL_REQUEST_START_JOB);
+
+ EndTraceAndFlush();
+
+ TestNetLogEntry::List entries;
+ net_log()->GetEntries(&entries);
+ EXPECT_EQ(3u, entries.size());
EXPECT_EQ(0u, trace_events()->GetSize());
}
@@ -373,6 +398,44 @@ TEST_F(TraceNetLogObserverTest, EventsWithAndWithoutParameters) {
EXPECT_TRUE(item2_params.empty());
}
+TEST(TraceNetLogObserverCategoryTest, DisabledCategory) {
+ TraceNetLogObserver observer;
+ NetLog net_log;
+ observer.WatchForTraceStart(&net_log);
+
+ EXPECT_FALSE(net_log.IsCapturing());
+
+ std::string disabled_netlog_category =
+ std::string("-") + kNetLogTracingCategory;
+ TraceLog::GetInstance()->SetEnabled(
+ base::trace_event::TraceConfig(disabled_netlog_category, ""),
+ TraceLog::RECORDING_MODE);
+
+ EXPECT_FALSE(net_log.IsCapturing());
+ observer.StopWatchForTraceStart();
+ EXPECT_FALSE(net_log.IsCapturing());
+
+ TraceLog::GetInstance()->SetDisabled();
+}
+
+TEST(TraceNetLogObserverCategoryTest, EnabledCategory) {
+ TraceNetLogObserver observer;
+ NetLog net_log;
+ observer.WatchForTraceStart(&net_log);
+
+ EXPECT_FALSE(net_log.IsCapturing());
+
+ TraceLog::GetInstance()->SetEnabled(
+ base::trace_event::TraceConfig(kNetLogTracingCategory, ""),
+ TraceLog::RECORDING_MODE);
+
+ EXPECT_TRUE(net_log.IsCapturing());
+ observer.StopWatchForTraceStart();
+ EXPECT_FALSE(net_log.IsCapturing());
+
+ TraceLog::GetInstance()->SetDisabled();
+}
+
} // namespace
} // namespace net
diff --git a/chromium/net/log/write_to_file_net_log_observer.h b/chromium/net/log/write_to_file_net_log_observer.h
index 0d6372465b8..2ef4189f2ff 100644
--- a/chromium/net/log/write_to_file_net_log_observer.h
+++ b/chromium/net/log/write_to_file_net_log_observer.h
@@ -2,8 +2,8 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#ifndef WRITE_TO_FILE_NET_LOG_OBSERVER_H_
-#define WRITE_TO_FILE_NET_LOG_OBSERVER_H_
+#ifndef NET_LOG_WRITE_TO_FILE_NET_LOG_OBSERVER_H_
+#define NET_LOG_WRITE_TO_FILE_NET_LOG_OBSERVER_H_
#include <stdio.h>
@@ -14,8 +14,6 @@
#include "net/log/net_log.h"
namespace base {
-class DictionaryValue;
-class FilePath;
class Value;
}
@@ -92,4 +90,4 @@ class NET_EXPORT WriteToFileNetLogObserver : public NetLog::ThreadSafeObserver {
} // namespace net
-#endif // WRITE_TO_FILE_NET_LOG_OBSERVER_H_
+#endif // NET_LOG_WRITE_TO_FILE_NET_LOG_OBSERVER_H_
diff --git a/chromium/net/net.gypi b/chromium/net/net.gypi
index c3796a6fcac..efe69ec24c3 100644
--- a/chromium/net/net.gypi
+++ b/chromium/net/net.gypi
@@ -15,6 +15,8 @@
'base/address_family.h',
'base/address_list.cc',
'base/address_list.h',
+ 'base/arena.cc',
+ 'base/arena.h',
'base/auth.cc',
'base/auth.h',
'base/completion_callback.h',
@@ -30,6 +32,7 @@
'base/ip_address.h',
'base/ip_endpoint.cc',
'base/ip_endpoint.h',
+ 'base/linked_hash_map.h',
'base/load_timing_info.cc',
'base/load_timing_info.h',
'base/lookup_string_in_fixed_set.cc',
@@ -46,9 +49,6 @@
'base/network_interfaces.cc',
'base/network_interfaces.h',
'base/network_interfaces_posix.cc',
- 'base/openssl_private_key_store.h',
- 'base/openssl_private_key_store_android.cc',
- 'base/openssl_private_key_store_memory.cc',
'base/parse_number.cc',
'base/parse_number.h',
'base/port_util.cc',
@@ -86,6 +86,8 @@
'cert/ct_verifier.h',
'cert/ct_verify_result.cc',
'cert/ct_verify_result.h',
+ 'cert/do_nothing_ct_verifier.cc',
+ 'cert/do_nothing_ct_verifier.h',
'cert/internal/cert_error_id.cc',
'cert/internal/cert_error_id.h',
'cert/internal/cert_error_params.cc',
@@ -187,8 +189,6 @@
'http/http_response_info.h',
'http/http_security_headers.cc',
'http/http_security_headers.h',
- 'http/http_status_line_validator.cc',
- 'http/http_status_line_validator.h',
'http/http_util.cc',
'http/http_util.h',
'http/http_vary_data.cc',
@@ -222,6 +222,8 @@
'socket/ssl_client_socket_impl.cc',
'socket/ssl_client_socket_impl.h',
'socket/ssl_socket.h',
+ 'spdy/spdy_header_block.cc',
+ 'spdy/spdy_header_block.h',
'ssl/channel_id_service.cc',
'ssl/channel_id_service.h',
'ssl/channel_id_store.cc',
@@ -282,8 +284,6 @@
'android/traffic_stats.h',
'base/address_tracker_linux.cc',
'base/address_tracker_linux.h',
- 'base/arena.cc',
- 'base/arena.h',
'base/backoff_entry.cc',
'base/backoff_entry.h',
'base/backoff_entry_serializer.cc',
@@ -316,16 +316,9 @@
'base/iovec.h',
'base/ip_pattern.cc',
'base/ip_pattern.h',
- 'base/keygen_handler.cc',
- 'base/keygen_handler.h',
- 'base/keygen_handler_mac.cc',
- 'base/keygen_handler_nss.cc',
- 'base/keygen_handler_openssl.cc',
- 'base/keygen_handler_win.cc',
# TODO(tc): gnome-vfs? xdgmime? /etc/mime.types?
'base/layered_network_delegate.cc',
'base/layered_network_delegate.h',
- 'base/linked_hash_map.h',
'base/load_flags.h',
'base/load_flags_list.h',
'base/load_states.h',
@@ -360,8 +353,11 @@
'base/network_interfaces_linux.cc',
'base/network_interfaces_mac.cc',
'base/network_interfaces_win.cc',
- 'base/network_throttle_manager.cc',
'base/network_throttle_manager.h',
+ 'base/network_throttle_manager_impl.cc',
+ 'base/network_throttle_manager_impl.h',
+ 'base/percentile_estimator.cc',
+ 'base/percentile_estimator.h',
'base/platform_mime_util.h',
'base/platform_mime_util_linux.cc',
'base/platform_mime_util_mac.mm',
@@ -442,6 +438,8 @@
'cert/ct_signed_certificate_timestamp_log_param.h',
'cert/ev_root_ca_metadata.cc',
'cert/ev_root_ca_metadata.h',
+ 'cert/internal/cert_issuer_source_nss.cc',
+ 'cert/internal/cert_issuer_source_nss.h',
'cert/internal/trust_store_nss.cc',
'cert/internal/trust_store_nss.h',
'cert/jwk_serializer.cc',
@@ -547,11 +545,11 @@
'disk_cache/blockfile/trace.h',
'disk_cache/blockfile/webfonts_histogram.cc',
'disk_cache/blockfile/webfonts_histogram.h',
- 'disk_cache/cache_creator.cc',
'disk_cache/cache_util.cc',
'disk_cache/cache_util.h',
'disk_cache/cache_util_posix.cc',
'disk_cache/cache_util_win.cc',
+ 'disk_cache/disk_cache.cc',
'disk_cache/disk_cache.h',
'disk_cache/memory/mem_backend_impl.cc',
'disk_cache/memory/mem_backend_impl.h',
@@ -571,8 +569,8 @@
'disk_cache/simple/simple_entry_operation.h',
'disk_cache/simple/simple_experiment.cc',
'disk_cache/simple/simple_experiment.h',
- 'log/bounded_file_net_log_observer.cc',
- 'log/bounded_file_net_log_observer.h',
+ 'log/file_net_log_observer.cc',
+ 'log/file_net_log_observer.h',
'log/net_log_util.cc',
'log/net_log_util.h',
'log/trace_net_log_observer.cc',
@@ -714,6 +712,8 @@
'http/http_basic_stream.h',
'http/http_cache.cc',
'http/http_cache.h',
+ 'http/http_cache_lookup_manager.cc',
+ 'http/http_cache_lookup_manager.h',
'http/http_cache_transaction.cc',
'http/http_cache_transaction.h',
'http/http_chunked_decoder.cc',
@@ -777,6 +777,84 @@
'http/url_security_manager.h',
'http/url_security_manager_posix.cc',
'http/url_security_manager_win.cc',
+ 'http2/decoder/decode_buffer.cc',
+ 'http2/decoder/decode_buffer.h',
+ 'http2/decoder/decode_http2_structures.cc',
+ 'http2/decoder/decode_http2_structures.h',
+ 'http2/decoder/decode_status.cc',
+ 'http2/decoder/decode_status.h',
+ 'http2/decoder/frame_decoder_state.cc',
+ 'http2/decoder/frame_decoder_state.h',
+ 'http2/decoder/http2_frame_decoder.cc',
+ 'http2/decoder/http2_frame_decoder.h',
+ 'http2/decoder/http2_frame_decoder_listener.cc',
+ 'http2/decoder/http2_frame_decoder_listener.h',
+ 'http2/decoder/http2_structure_decoder.cc',
+ 'http2/decoder/http2_structure_decoder.h',
+ 'http2/decoder/payload_decoders/altsvc_payload_decoder.cc',
+ 'http2/decoder/payload_decoders/altsvc_payload_decoder.h',
+ 'http2/decoder/payload_decoders/continuation_payload_decoder.cc',
+ 'http2/decoder/payload_decoders/continuation_payload_decoder.h',
+ 'http2/decoder/payload_decoders/data_payload_decoder.cc',
+ 'http2/decoder/payload_decoders/data_payload_decoder.h',
+ 'http2/decoder/payload_decoders/goaway_payload_decoder.cc',
+ 'http2/decoder/payload_decoders/goaway_payload_decoder.h',
+ 'http2/decoder/payload_decoders/headers_payload_decoder.cc',
+ 'http2/decoder/payload_decoders/headers_payload_decoder.h',
+ 'http2/decoder/payload_decoders/ping_payload_decoder.cc',
+ 'http2/decoder/payload_decoders/ping_payload_decoder.h',
+ 'http2/decoder/payload_decoders/priority_payload_decoder.cc',
+ 'http2/decoder/payload_decoders/priority_payload_decoder.h',
+ 'http2/decoder/payload_decoders/push_promise_payload_decoder.cc',
+ 'http2/decoder/payload_decoders/push_promise_payload_decoder.h',
+ 'http2/decoder/payload_decoders/rst_stream_payload_decoder.cc',
+ 'http2/decoder/payload_decoders/rst_stream_payload_decoder.h',
+ 'http2/decoder/payload_decoders/settings_payload_decoder.cc',
+ 'http2/decoder/payload_decoders/settings_payload_decoder.h',
+ 'http2/decoder/payload_decoders/unknown_payload_decoder.cc',
+ 'http2/decoder/payload_decoders/unknown_payload_decoder.h',
+ 'http2/decoder/payload_decoders/window_update_payload_decoder.cc',
+ 'http2/decoder/payload_decoders/window_update_payload_decoder.h',
+ 'http2/hpack/decoder/hpack_block_decoder.cc',
+ 'http2/hpack/decoder/hpack_block_decoder.h',
+ 'http2/hpack/decoder/hpack_decoder_listener.cc',
+ 'http2/hpack/decoder/hpack_decoder_listener.h',
+ 'http2/hpack/decoder/hpack_decoder_state.cc',
+ 'http2/hpack/decoder/hpack_decoder_state.h',
+ 'http2/hpack/decoder/hpack_decoder_string_buffer.cc',
+ 'http2/hpack/decoder/hpack_decoder_string_buffer.h',
+ 'http2/hpack/decoder/hpack_decoder_tables.cc',
+ 'http2/hpack/decoder/hpack_decoder_tables.h',
+ 'http2/hpack/decoder/hpack_entry_decoder.cc',
+ 'http2/hpack/decoder/hpack_entry_decoder.h',
+ 'http2/hpack/decoder/hpack_entry_decoder_listener.cc',
+ 'http2/hpack/decoder/hpack_entry_decoder_listener.h',
+ 'http2/hpack/decoder/hpack_entry_type_decoder.cc',
+ 'http2/hpack/decoder/hpack_entry_type_decoder.h',
+ 'http2/hpack/decoder/hpack_string_decoder.cc',
+ 'http2/hpack/decoder/hpack_string_decoder.h',
+ 'http2/hpack/decoder/hpack_string_decoder_listener.cc',
+ 'http2/hpack/decoder/hpack_string_decoder_listener.h',
+ 'http2/hpack/decoder/hpack_varint_decoder.cc',
+ 'http2/hpack/decoder/hpack_varint_decoder.h',
+ 'http2/hpack/decoder/hpack_whole_entry_buffer.cc',
+ 'http2/hpack/decoder/hpack_whole_entry_buffer.h',
+ 'http2/hpack/decoder/hpack_whole_entry_listener.cc',
+ 'http2/hpack/decoder/hpack_whole_entry_listener.h',
+ 'http2/hpack/decoder/http2_hpack_decoder.cc',
+ 'http2/hpack/decoder/http2_hpack_decoder.h',
+ 'http2/hpack/hpack_static_table_entries.inc',
+ 'http2/hpack/hpack_string.cc',
+ 'http2/hpack/hpack_string.h',
+ 'http2/hpack/http2_hpack_constants.cc',
+ 'http2/hpack/http2_hpack_constants.h',
+ 'http2/hpack/huffman/http2_hpack_huffman_decoder.cc',
+ 'http2/hpack/huffman/http2_hpack_huffman_decoder.h',
+ 'http2/http2_constants.cc',
+ 'http2/http2_constants.h',
+ 'http2/http2_structures.cc',
+ 'http2/http2_structures.h',
+ 'http2/tools/http2_bug_tracker.h',
'nqe/cached_network_quality.cc',
'nqe/cached_network_quality.h',
'nqe/effective_connection_type.cc',
@@ -874,8 +952,10 @@
'quic/chromium/crypto/proof_verifier_chromium.h',
'quic/chromium/network_connection.cc',
'quic/chromium/network_connection.h',
- 'quic/chromium/port_suggester.cc',
- 'quic/chromium/port_suggester.h',
+ 'quic/chromium/quic_address_mismatch.cc',
+ 'quic/chromium/quic_address_mismatch.h',
+ 'quic/chromium/properties_based_quic_server_info.cc',
+ 'quic/chromium/properties_based_quic_server_info.h',
'quic/chromium/quic_chromium_alarm_factory.cc',
'quic/chromium/quic_chromium_alarm_factory.h',
'quic/chromium/quic_chromium_client_session.cc',
@@ -892,11 +972,18 @@
'quic/chromium/quic_clock_skew_detector.h',
'quic/chromium/quic_connection_logger.cc',
'quic/chromium/quic_connection_logger.h',
+ 'quic/chromium/quic_crypto_client_stream_factory.cc',
+ 'quic/chromium/quic_crypto_client_stream_factory.h',
'quic/chromium/quic_http_stream.cc',
'quic/chromium/quic_http_stream.h',
+ 'quic/chromium/quic_http_utils.cc',
+ 'quic/chromium/quic_http_utils.h',
+ 'quic/chromium/quic_server_info.cc',
+ 'quic/chromium/quic_server_info.h',
'quic/chromium/quic_stream_factory.cc',
'quic/chromium/quic_stream_factory.h',
'quic/chromium/quic_utils_chromium.h',
+ 'quic/chromium/quic_utils_chromium.cc',
'quic/core/congestion_control/bandwidth_sampler.cc',
'quic/core/congestion_control/bandwidth_sampler.h',
'quic/core/congestion_control/bbr_sender.cc',
@@ -971,12 +1058,12 @@
'quic/core/crypto/proof_source.cc',
'quic/core/crypto/proof_source.h',
'quic/core/crypto/proof_verifier.h',
- 'quic/core/crypto/properties_based_quic_server_info.cc',
- 'quic/core/crypto/properties_based_quic_server_info.h',
'quic/core/crypto/quic_compressed_certs_cache.cc',
'quic/core/crypto/quic_compressed_certs_cache.h',
'quic/core/crypto/quic_crypto_client_config.cc',
'quic/core/crypto/quic_crypto_client_config.h',
+ 'quic/core/crypto/quic_crypto_proof.cc',
+ 'quic/core/crypto/quic_crypto_proof.h',
'quic/core/crypto/quic_crypto_server_config.cc',
'quic/core/crypto/quic_crypto_server_config.h',
'quic/core/crypto/quic_decrypter.cc',
@@ -985,8 +1072,6 @@
'quic/core/crypto/quic_encrypter.h',
'quic/core/crypto/quic_random.cc',
'quic/core/crypto/quic_random.h',
- 'quic/core/crypto/quic_server_info.cc',
- 'quic/core/crypto/quic_server_info.h',
'quic/core/crypto/scoped_evp_aead_ctx.cc',
'quic/core/crypto/scoped_evp_aead_ctx.h',
'quic/core/crypto/strike_register.cc',
@@ -994,35 +1079,59 @@
'quic/core/crypto/strike_register_client.h',
'quic/core/interval.h',
'quic/core/interval_set.h',
- 'quic/core/quic_address_mismatch.cc',
- 'quic/core/quic_address_mismatch.h',
+ 'quic/core/frames/quic_ack_frame.cc',
+ 'quic/core/frames/quic_ack_frame.h',
+ 'quic/core/frames/quic_blocked_frame.cc',
+ 'quic/core/frames/quic_blocked_frame.h',
+ 'quic/core/frames/quic_connection_close_frame.cc',
+ 'quic/core/frames/quic_connection_close_frame.h',
+ 'quic/core/frames/quic_frame.cc',
+ 'quic/core/frames/quic_frame.h',
+ 'quic/core/frames/quic_goaway_frame.cc',
+ 'quic/core/frames/quic_goaway_frame.h',
+ 'quic/core/frames/quic_mtu_discovery_frame.h',
+ 'quic/core/frames/quic_padding_frame.cc',
+ 'quic/core/frames/quic_padding_frame.h',
+ 'quic/core/frames/quic_path_close_frame.cc',
+ 'quic/core/frames/quic_path_close_frame.h',
+ 'quic/core/frames/quic_ping_frame.h',
+ 'quic/core/frames/quic_rst_stream_frame.cc',
+ 'quic/core/frames/quic_rst_stream_frame.h',
+ 'quic/core/frames/quic_stop_waiting_frame.cc',
+ 'quic/core/frames/quic_stop_waiting_frame.h',
+ 'quic/core/frames/quic_stream_frame.cc',
+ 'quic/core/frames/quic_stream_frame.h',
+ 'quic/core/frames/quic_window_update_frame.cc',
+ 'quic/core/frames/quic_window_update_frame.h',
+ 'quic/core/quic_ack_listener_interface.cc',
+ 'quic/core/quic_ack_listener_interface.h',
'quic/core/quic_alarm.cc',
'quic/core/quic_alarm.h',
'quic/core/quic_arena_scoped_ptr.h',
'quic/core/quic_bandwidth.cc',
'quic/core/quic_bandwidth.h',
'quic/core/quic_blocked_writer_interface.h',
+ 'quic/core/quic_buffer_allocator.cc',
+ 'quic/core/quic_buffer_allocator.h',
'quic/core/quic_buffered_packet_store.cc',
'quic/core/quic_buffered_packet_store.h',
- 'quic/core/quic_bug_tracker.h',
'quic/core/quic_client_promised_info.cc',
'quic/core/quic_client_promised_info.h',
'quic/core/quic_client_push_promise_index.cc',
'quic/core/quic_client_push_promise_index.h',
'quic/core/quic_client_session_base.cc',
'quic/core/quic_client_session_base.h',
- 'quic/core/quic_clock.cc',
- 'quic/core/quic_clock.h',
'quic/core/quic_config.cc',
'quic/core/quic_config.h',
'quic/core/quic_connection.cc',
'quic/core/quic_connection.h',
+ 'quic/core/quic_connection_close_delegate_interface.h',
'quic/core/quic_connection_stats.cc',
'quic/core/quic_connection_stats.h',
+ 'quic/core/quic_constants.cc',
+ 'quic/core/quic_constants.h',
'quic/core/quic_crypto_client_stream.cc',
'quic/core/quic_crypto_client_stream.h',
- 'quic/core/quic_crypto_client_stream_factory.cc',
- 'quic/core/quic_crypto_client_stream_factory.h',
'quic/core/quic_crypto_server_stream.cc',
'quic/core/quic_crypto_server_stream.h',
'quic/core/quic_crypto_stream.cc',
@@ -1031,24 +1140,21 @@
'quic/core/quic_data_reader.h',
'quic/core/quic_data_writer.cc',
'quic/core/quic_data_writer.h',
+ 'quic/core/quic_error_codes.cc',
+ 'quic/core/quic_error_codes.h',
'quic/core/quic_flags.cc',
'quic/core/quic_flags.h',
'quic/core/quic_flow_controller.cc',
'quic/core/quic_flow_controller.h',
- 'quic/core/quic_frame_list.cc',
- 'quic/core/quic_frame_list.h',
'quic/core/quic_framer.cc',
'quic/core/quic_framer.h',
'quic/core/quic_header_list.cc',
'quic/core/quic_header_list.h',
'quic/core/quic_headers_stream.cc',
'quic/core/quic_headers_stream.h',
- 'quic/core/quic_http_utils.cc',
- 'quic/core/quic_http_utils.h',
+ 'quic/core/quic_iovector.h',
'quic/core/quic_multipath_received_packet_manager.cc',
'quic/core/quic_multipath_received_packet_manager.h',
- 'quic/core/quic_multipath_sent_packet_manager.cc',
- 'quic/core/quic_multipath_sent_packet_manager.h',
'quic/core/quic_multipath_transmissions_map.cc',
'quic/core/quic_multipath_transmissions_map.h',
'quic/core/quic_one_block_arena.h',
@@ -1057,15 +1163,13 @@
'quic/core/quic_packet_generator.cc',
'quic/core/quic_packet_generator.h',
'quic/core/quic_packet_writer.h',
- 'quic/core/quic_protocol.cc',
- 'quic/core/quic_protocol.h',
+ 'quic/core/quic_packets.cc',
+ 'quic/core/quic_packets.h',
+ 'quic/core/quic_pending_retransmission.h',
'quic/core/quic_received_packet_manager.cc',
'quic/core/quic_received_packet_manager.h',
- 'quic/core/quic_sent_entropy_manager.cc',
- 'quic/core/quic_sent_entropy_manager.h',
'quic/core/quic_sent_packet_manager.cc',
'quic/core/quic_sent_packet_manager.h',
- 'quic/core/quic_sent_packet_manager_interface.h',
'quic/core/quic_server_id.cc',
'quic/core/quic_server_id.h',
'quic/core/quic_server_session_base.cc',
@@ -1086,21 +1190,63 @@
'quic/core/quic_stream_sequencer.h',
'quic/core/quic_stream_sequencer_buffer.cc',
'quic/core/quic_stream_sequencer_buffer.h',
- 'quic/core/quic_stream_sequencer_buffer_interface.h',
'quic/core/quic_sustained_bandwidth_recorder.cc',
'quic/core/quic_sustained_bandwidth_recorder.h',
+ 'quic/core/quic_tag.cc',
+ 'quic/core/quic_tag.h',
'quic/core/quic_time.cc',
'quic/core/quic_time.h',
+ 'quic/core/quic_transmission_info.cc',
+ 'quic/core/quic_transmission_info.h',
'quic/core/quic_types.cc',
'quic/core/quic_types.h',
'quic/core/quic_unacked_packet_map.cc',
'quic/core/quic_unacked_packet_map.h',
'quic/core/quic_utils.cc',
'quic/core/quic_utils.h',
+ 'quic/core/quic_version_manager.cc',
+ 'quic/core/quic_version_manager.h',
+ 'quic/core/quic_versions.cc',
+ 'quic/core/quic_versions.h',
'quic/core/quic_write_blocked_list.cc',
'quic/core/quic_write_blocked_list.h',
'quic/core/spdy_utils.cc',
'quic/core/spdy_utils.h',
+ 'quic/platform/api/quic_aligned.h',
+ 'quic/platform/api/quic_bug_tracker.h',
+ 'quic/platform/api/quic_clock.cc',
+ 'quic/platform/api/quic_clock.h',
+ 'quic/platform/api/quic_export.h',
+ 'quic/platform/api/quic_ip_address_family.h',
+ 'quic/platform/api/quic_ip_address.cc',
+ 'quic/platform/api/quic_ip_address.h',
+ 'quic/platform/api/quic_logging.h',
+ 'quic/platform/api/quic_lru_cache.h',
+ 'quic/platform/api/quic_mutex.cc',
+ 'quic/platform/api/quic_mutex.h',
+ 'quic/platform/api/quic_ptr_util.h',
+ 'quic/platform/api/quic_reference_counted.h',
+ 'quic/platform/api/quic_socket_address.cc',
+ 'quic/platform/api/quic_socket_address.h',
+ 'quic/platform/api/quic_str_cat.h',
+ 'quic/platform/api/quic_text_utils.h',
+ 'quic/platform/impl/quic_aligned_impl.h',
+ 'quic/platform/impl/quic_bug_tracker_impl.h',
+ 'quic/platform/impl/quic_chromium_clock.cc',
+ 'quic/platform/impl/quic_chromium_clock.h',
+ 'quic/platform/impl/quic_export_impl.h',
+ 'quic/platform/impl/quic_ip_address_impl.cc',
+ 'quic/platform/impl/quic_ip_address_impl.h',
+ 'quic/platform/impl/quic_logging_impl.h',
+ 'quic/platform/impl/quic_lru_cache_impl.h',
+ 'quic/platform/impl/quic_mutex_impl.cc',
+ 'quic/platform/impl/quic_mutex_impl.h',
+ 'quic/platform/impl/quic_ptr_util_impl.h',
+ 'quic/platform/impl/quic_reference_counted_impl.h',
+ 'quic/platform/impl/quic_socket_address_impl.cc',
+ 'quic/platform/impl/quic_socket_address_impl.h',
+ 'quic/platform/impl/quic_str_cat_impl.h',
+ 'quic/platform/impl/quic_text_utils_impl.h',
'quic/quartc/quartc_alarm_factory.cc',
'quic/quartc/quartc_alarm_factory.h',
'quic/quartc/quartc_factory.cc',
@@ -1197,6 +1343,10 @@
'spdy/hpack/hpack_decoder.cc',
'spdy/hpack/hpack_decoder.h',
'spdy/hpack/hpack_decoder_interface.h',
+ 'spdy/hpack/hpack_decoder2.cc',
+ 'spdy/hpack/hpack_decoder2.h',
+ 'spdy/hpack/hpack_decoder3.cc',
+ 'spdy/hpack/hpack_decoder3.h',
'spdy/hpack/hpack_encoder.cc',
'spdy/hpack/hpack_encoder.h',
'spdy/hpack/hpack_entry.cc',
@@ -1213,9 +1363,15 @@
'spdy/hpack/hpack_output_stream.h',
'spdy/hpack/hpack_static_table.cc',
'spdy/hpack/hpack_static_table.h',
+ 'spdy/http2_frame_decoder_adapter.cc',
+ 'spdy/http2_frame_decoder_adapter.h',
'spdy/http2_priority_dependencies.cc',
'spdy/http2_priority_dependencies.h',
'spdy/http2_write_scheduler.h',
+ 'spdy/multiplexed_http_stream.cc',
+ 'spdy/multiplexed_http_stream.h',
+ 'spdy/multiplexed_session.cc',
+ 'spdy/multiplexed_session.h',
'spdy/priority_write_scheduler.h',
'spdy/server_push_delegate.h',
'spdy/spdy_alt_svc_wire_format.cc',
@@ -1236,8 +1392,6 @@
'spdy/spdy_framer.h',
'spdy/spdy_framer_decoder_adapter.cc',
'spdy/spdy_framer_decoder_adapter.h',
- 'spdy/spdy_header_block.cc',
- 'spdy/spdy_header_block.h',
'spdy/spdy_header_indexing.cc',
'spdy/spdy_header_indexing.h',
'spdy/spdy_headers_block_parser.cc',
@@ -1291,8 +1445,6 @@
'ssl/test_ssl_private_key.h',
'ssl/threaded_ssl_private_key.cc',
'ssl/threaded_ssl_private_key.h',
- 'third_party/mozilla_security_manager/nsKeygenHandler.cpp',
- 'third_party/mozilla_security_manager/nsKeygenHandler.h',
'third_party/mozilla_security_manager/nsNSSCertificateDB.cpp',
'third_party/mozilla_security_manager/nsNSSCertificateDB.h',
'third_party/mozilla_security_manager/nsPKCS12Blob.cpp',
@@ -1398,6 +1550,7 @@
'android/dummy_spnego_authenticator.h',
'android/http_auth_negotiate_android_unittest.cc',
'android/network_change_notifier_android_unittest.cc',
+ 'android/network_library_unittest.cc',
'android/traffic_stats_unittest.cc',
'base/address_family_unittest.cc',
'base/address_list_unittest.cc',
@@ -1420,7 +1573,6 @@
'base/ip_address_unittest.cc',
'base/ip_endpoint_unittest.cc',
'base/ip_pattern_unittest.cc',
- 'base/keygen_handler_unittest.cc',
'base/layered_network_delegate_unittest.cc',
'base/lookup_string_in_fixed_set_unittest.cc',
'base/mime_sniffer_unittest.cc',
@@ -1429,8 +1581,9 @@
'base/network_change_notifier_unittest.cc',
'base/network_change_notifier_win_unittest.cc',
'base/network_interfaces_unittest.cc',
- 'base/network_throttle_manager_unittest.cc',
+ 'base/network_throttle_manager_impl_unittest.cc',
'base/parse_number_unittest.cc',
+ 'base/percentile_estimator_unittest.cc',
'base/port_util_unittest.cc',
'base/prioritized_dispatcher_unittest.cc',
'base/priority_queue_unittest.cc',
@@ -1458,7 +1611,9 @@
'cert/ct_serialization_unittest.cc',
'cert/ev_root_ca_metadata_unittest.cc',
'cert/internal/cert_issuer_source_aia_unittest.cc',
+ 'cert/internal/cert_issuer_source_nss_unittest.cc',
'cert/internal/cert_issuer_source_static_unittest.cc',
+ 'cert/internal/cert_issuer_source_sync_unittest.h',
'cert/internal/certificate_policies_unittest.cc',
'cert/internal/extended_key_usage_unittest.cc',
'cert/internal/name_constraints_unittest.cc',
@@ -1466,6 +1621,7 @@
'cert/internal/parse_certificate_unittest.cc',
'cert/internal/parse_name_unittest.cc',
'cert/internal/parse_ocsp_unittest.cc',
+ 'cert/internal/parsed_certificate_unittest.cc',
'cert/internal/path_builder_pkits_unittest.cc',
'cert/internal/path_builder_unittest.cc',
'cert/internal/path_builder_verify_certificate_chain_unittest.cc',
@@ -1474,8 +1630,6 @@
'cert/internal/test_helpers.h',
'cert/internal/trust_store_collection_unittest.cc',
'cert/internal/trust_store_nss_unittest.cc',
- 'cert/internal/trust_store_test_helpers.cc',
- 'cert/internal/trust_store_test_helpers.h',
'cert/internal/verify_certificate_chain_pkits_unittest.cc',
'cert/internal/verify_certificate_chain_typed_unittest.h',
'cert/internal/verify_certificate_chain_unittest.cc',
@@ -1584,6 +1738,7 @@
'http/http_auth_unittest.cc',
'http/http_basic_state_unittest.cc',
'http/http_byte_range_unittest.cc',
+ 'http/http_cache_lookup_manager_unittest.cc',
'http/http_cache_unittest.cc',
'http/http_chunked_decoder_unittest.cc',
'http/http_content_disposition_unittest.cc',
@@ -1600,7 +1755,6 @@
'http/http_server_properties_impl_unittest.cc',
'http/http_server_properties_manager_unittest.cc',
'http/http_status_code_unittest.cc',
- 'http/http_status_line_validator_unittest.cc',
'http/http_stream_factory_impl_job_controller_unittest.cc',
'http/http_stream_factory_impl_request_unittest.cc',
'http/http_stream_factory_impl_unittest.cc',
@@ -1618,7 +1772,76 @@
'http/transport_security_persister_unittest.cc',
'http/transport_security_state_unittest.cc',
'http/url_security_manager_unittest.cc',
- 'log/bounded_file_net_log_observer_unittest.cc',
+ 'http2/decoder/decode_buffer_test.cc',
+ 'http2/decoder/decode_http2_structures_test.cc',
+ 'http2/decoder/frame_decoder_state_test_util.cc',
+ 'http2/decoder/frame_decoder_state_test_util.h',
+ 'http2/decoder/frame_parts.cc',
+ 'http2/decoder/frame_parts.h',
+ 'http2/decoder/frame_parts_collector.cc',
+ 'http2/decoder/frame_parts_collector.h',
+ 'http2/decoder/frame_parts_collector_listener.cc',
+ 'http2/decoder/frame_parts_collector_listener.h',
+ 'http2/decoder/http2_frame_decoder_listener_test_util.cc',
+ 'http2/decoder/http2_frame_decoder_listener_test_util.h',
+ 'http2/decoder/http2_frame_decoder_test.cc',
+ 'http2/decoder/http2_structure_decoder_test.cc',
+ 'http2/decoder/http2_structure_decoder_test_util.h',
+ 'http2/decoder/payload_decoders/altsvc_payload_decoder_test.cc',
+ 'http2/decoder/payload_decoders/continuation_payload_decoder_test.cc',
+ 'http2/decoder/payload_decoders/data_payload_decoder_test.cc',
+ 'http2/decoder/payload_decoders/goaway_payload_decoder_test.cc',
+ 'http2/decoder/payload_decoders/headers_payload_decoder_test.cc',
+ 'http2/decoder/payload_decoders/payload_decoder_base_test_util.cc',
+ 'http2/decoder/payload_decoders/payload_decoder_base_test_util.h',
+ 'http2/decoder/payload_decoders/ping_payload_decoder_test.cc',
+ 'http2/decoder/payload_decoders/priority_payload_decoder_test.cc',
+ 'http2/decoder/payload_decoders/push_promise_payload_decoder_test.cc',
+ 'http2/decoder/payload_decoders/rst_stream_payload_decoder_test.cc',
+ 'http2/decoder/payload_decoders/settings_payload_decoder_test.cc',
+ 'http2/decoder/payload_decoders/unknown_payload_decoder_test.cc',
+ 'http2/decoder/payload_decoders/window_update_payload_decoder_test.cc',
+ 'http2/hpack/decoder/hpack_block_collector.cc',
+ 'http2/hpack/decoder/hpack_block_collector.h',
+ 'http2/hpack/decoder/hpack_block_decoder_test.cc',
+ 'http2/hpack/decoder/hpack_decoder_state_test.cc',
+ 'http2/hpack/decoder/hpack_decoder_string_buffer_test.cc',
+ 'http2/hpack/decoder/hpack_decoder_tables_test.cc',
+ 'http2/hpack/decoder/hpack_entry_collector.cc',
+ 'http2/hpack/decoder/hpack_entry_collector.h',
+ 'http2/hpack/decoder/hpack_entry_decoder_test.cc',
+ 'http2/hpack/decoder/hpack_entry_type_decoder_test.cc',
+ 'http2/hpack/decoder/hpack_string_collector.cc',
+ 'http2/hpack/decoder/hpack_string_collector.h',
+ 'http2/hpack/decoder/hpack_string_decoder_test.cc',
+ 'http2/hpack/decoder/hpack_varint_decoder_test.cc',
+ 'http2/hpack/decoder/hpack_whole_entry_buffer_test.cc',
+ 'http2/hpack/decoder/http2_hpack_decoder_test.cc',
+ 'http2/hpack/hpack_string_test.cc',
+ 'http2/hpack/http2_hpack_constants_test.cc',
+ 'http2/hpack/huffman/http2_hpack_huffman_decoder_test.cc',
+ 'http2/hpack/tools/hpack_block_builder.cc',
+ 'http2/hpack/tools/hpack_block_builder.h',
+ 'http2/hpack/tools/hpack_block_builder_test.cc',
+ 'http2/hpack/tools/hpack_example.cc',
+ 'http2/hpack/tools/hpack_example.h',
+ 'http2/http2_constants_test.cc',
+ 'http2/http2_constants_test_util.cc',
+ 'http2/http2_constants_test_util.h',
+ 'http2/http2_structures_test.cc',
+ 'http2/http2_structures_test_util.cc',
+ 'http2/http2_structures_test_util.h',
+ 'http2/tools/failure.cc',
+ 'http2/tools/failure.h',
+ 'http2/tools/http2_frame_builder.cc',
+ 'http2/tools/http2_frame_builder.h',
+ 'http2/tools/http2_random.cc',
+ 'http2/tools/http2_random.h',
+ 'http2/tools/random_decoder_test.cc',
+ 'http2/tools/random_decoder_test.h',
+ 'http2/tools/random_util.cc',
+ 'http2/tools/random_util.h',
+ 'log/file_net_log_observer_unittest.cc',
'log/net_log_capture_mode_unittest.cc',
'log/net_log_unittest.cc',
'log/net_log_util_unittest.cc',
@@ -1629,6 +1852,7 @@
'nqe/network_quality_estimator_unittest.cc',
'nqe/network_quality_store_unittest.cc',
'nqe/observation_buffer_unittest.cc',
+ 'nqe/socket_watcher_unittest.cc',
'nqe/throughput_analyzer_unittest.cc',
'proxy/dhcp_proxy_script_adapter_fetcher_win_unittest.cc',
'proxy/dhcp_proxy_script_fetcher_factory_unittest.cc',
@@ -1658,12 +1882,15 @@
'quic/chromium/crypto/proof_test_chromium.cc',
'quic/chromium/crypto/proof_verifier_chromium_test.cc',
'quic/chromium/crypto_test_utils_chromium.cc',
+ 'quic/chromium/mock_crypto_client_stream_factory.cc',
+ 'quic/chromium/mock_crypto_client_stream_factory.h',
'quic/chromium/mock_network_change_notifier.cc',
'quic/chromium/mock_network_change_notifier.h',
'quic/chromium/mock_quic_data.cc',
'quic/chromium/mock_quic_data.h',
'quic/chromium/network_connection_unittest.cc',
- 'quic/chromium/port_suggester_unittest.cc',
+ 'quic/chromium/quic_address_mismatch_test.cc',
+ 'quic/chromium/properties_based_quic_server_info_test.cc',
'quic/chromium/quic_chromium_alarm_factory_test.cc',
'quic/chromium/quic_chromium_client_session_peer.cc',
'quic/chromium/quic_chromium_client_session_peer.h',
@@ -1673,8 +1900,11 @@
'quic/chromium/quic_clock_skew_detector_test.cc',
'quic/chromium/quic_end_to_end_unittest.cc',
'quic/chromium/quic_http_stream_test.cc',
+ 'quic/chromium/quic_http_utils_test.cc',
'quic/chromium/quic_network_transaction_unittest.cc',
'quic/chromium/quic_stream_factory_test.cc',
+ 'quic/chromium/quic_test_packet_maker.cc',
+ 'quic/chromium/quic_test_packet_maker.h',
'quic/chromium/quic_utils_chromium_test.cc',
'quic/core/congestion_control/bandwidth_sampler_test.cc',
'quic/core/congestion_control/bbr_sender_test.cc',
@@ -1685,6 +1915,7 @@
'quic/core/congestion_control/pacing_sender_test.cc',
'quic/core/congestion_control/prr_sender_test.cc',
'quic/core/congestion_control/rtt_stats_test.cc',
+ 'quic/core/congestion_control/send_algorithm_test.cc',
'quic/core/congestion_control/tcp_cubic_sender_bytes_test.cc',
'quic/core/congestion_control/tcp_cubic_sender_packets_test.cc',
'quic/core/congestion_control/windowed_filter_test.cc',
@@ -1705,42 +1936,37 @@
'quic/core/crypto/null_decrypter_test.cc',
'quic/core/crypto/null_encrypter_test.cc',
'quic/core/crypto/p256_key_exchange_test.cc',
- 'quic/core/crypto/properties_based_quic_server_info_test.cc',
'quic/core/crypto/quic_compressed_certs_cache_test.cc',
'quic/core/crypto/quic_crypto_client_config_test.cc',
'quic/core/crypto/quic_crypto_server_config_test.cc',
'quic/core/crypto/quic_random_test.cc',
'quic/core/crypto/strike_register_test.cc',
+ 'quic/core/frames/quic_frames_test.cc',
'quic/core/interval_set_test.cc',
'quic/core/interval_test.cc',
- 'quic/core/quic_address_mismatch_test.cc',
'quic/core/quic_alarm_test.cc',
'quic/core/quic_arena_scoped_ptr_test.cc',
'quic/core/quic_bandwidth_test.cc',
'quic/core/quic_buffered_packet_store_test.cc',
'quic/core/quic_client_promised_info_test.cc',
'quic/core/quic_client_push_promise_index_test.cc',
- 'quic/core/quic_clock_test.cc',
'quic/core/quic_config_test.cc',
'quic/core/quic_connection_test.cc',
'quic/core/quic_crypto_client_stream_test.cc',
'quic/core/quic_crypto_server_stream_test.cc',
'quic/core/quic_crypto_stream_test.cc',
'quic/core/quic_data_writer_test.cc',
+ 'quic/core/quic_error_codes_test.cc',
'quic/core/quic_flow_controller_test.cc',
'quic/core/quic_framer_test.cc',
'quic/core/quic_header_list_test.cc',
'quic/core/quic_headers_stream_test.cc',
- 'quic/core/quic_http_utils_test.cc',
'quic/core/quic_multipath_received_packet_manager_test.cc',
- 'quic/core/quic_multipath_sent_packet_manager_test.cc',
'quic/core/quic_multipath_transmissions_map_test.cc',
'quic/core/quic_one_block_arena_test.cc',
'quic/core/quic_packet_creator_test.cc',
'quic/core/quic_packet_generator_test.cc',
- 'quic/core/quic_protocol_test.cc',
'quic/core/quic_received_packet_manager_test.cc',
- 'quic/core/quic_sent_entropy_manager_test.cc',
'quic/core/quic_sent_packet_manager_test.cc',
'quic/core/quic_server_id_test.cc',
'quic/core/quic_server_session_base_test.cc',
@@ -1752,11 +1978,19 @@
'quic/core/quic_stream_sequencer_test.cc',
'quic/core/quic_stream_test.cc',
'quic/core/quic_sustained_bandwidth_recorder_test.cc',
+ 'quic/core/quic_tag_test.cc',
'quic/core/quic_time_test.cc',
'quic/core/quic_unacked_packet_map_test.cc',
'quic/core/quic_utils_test.cc',
+ 'quic/core/quic_version_manager_test.cc',
+ 'quic/core/quic_versions_test.cc',
'quic/core/quic_write_blocked_list_test.cc',
'quic/core/spdy_utils_test.cc',
+ 'quic/platform/api/quic_lru_cache_test.cc',
+ 'quic/platform/api/quic_reference_counted_test.cc',
+ 'quic/platform/api/quic_str_cat_test.cc',
+ 'quic/platform/api/quic_text_utils_test.cc',
+ 'quic/platform/impl/quic_chromium_clock_test.cc',
'quic/quartc/quartc_alarm_factory_test.cc',
'quic/quartc/quartc_session_test.cc',
'quic/quartc/quartc_stream_test.cc',
@@ -1765,14 +1999,14 @@
'quic/test_tools/crypto_test_utils_test.cc',
'quic/test_tools/delayed_verify_strike_register_client.cc',
'quic/test_tools/delayed_verify_strike_register_client.h',
+ 'quic/test_tools/failing_proof_source.cc',
+ 'quic/test_tools/failing_proof_source.h',
'quic/test_tools/fake_proof_source.cc',
'quic/test_tools/fake_proof_source.h',
'quic/test_tools/mock_clock.cc',
'quic/test_tools/mock_clock.h',
'quic/test_tools/mock_crypto_client_stream.cc',
'quic/test_tools/mock_crypto_client_stream.h',
- 'quic/test_tools/mock_crypto_client_stream_factory.cc',
- 'quic/test_tools/mock_crypto_client_stream_factory.h',
'quic/test_tools/mock_quic_client_promised_info.cc',
'quic/test_tools/mock_quic_client_promised_info.h',
'quic/test_tools/mock_quic_dispatcher.cc',
@@ -1795,10 +2029,6 @@
'quic/test_tools/quic_flow_controller_peer.h',
'quic/test_tools/quic_framer_peer.cc',
'quic/test_tools/quic_framer_peer.h',
- 'quic/test_tools/quic_headers_stream_peer.cc',
- 'quic/test_tools/quic_headers_stream_peer.h',
- 'quic/test_tools/quic_multipath_sent_packet_manager_peer.cc',
- 'quic/test_tools/quic_multipath_sent_packet_manager_peer.h',
'quic/test_tools/quic_packet_creator_peer.cc',
'quic/test_tools/quic_packet_creator_peer.h',
'quic/test_tools/quic_packet_generator_peer.cc',
@@ -1823,8 +2053,6 @@
'quic/test_tools/quic_stream_sequencer_peer.h',
'quic/test_tools/quic_sustained_bandwidth_recorder_peer.cc',
'quic/test_tools/quic_sustained_bandwidth_recorder_peer.h',
- 'quic/test_tools/quic_test_packet_maker.cc',
- 'quic/test_tools/quic_test_packet_maker.h',
'quic/test_tools/quic_test_utils.cc',
'quic/test_tools/quic_test_utils.h',
'quic/test_tools/quic_test_utils_test.cc',
@@ -1840,6 +2068,8 @@
'quic/test_tools/simulator/alarm_factory.h',
'quic/test_tools/simulator/link.cc',
'quic/test_tools/simulator/link.h',
+ 'quic/test_tools/simulator/packet_filter.cc',
+ 'quic/test_tools/simulator/packet_filter.h',
'quic/test_tools/simulator/port.cc',
'quic/test_tools/simulator/port.h',
'quic/test_tools/simulator/queue.cc',
@@ -1885,6 +2115,8 @@
'spdy/fuzzing/hpack_fuzz_util_test.cc',
'spdy/header_coalescer_test.cc',
'spdy/hpack/hpack_decoder_test.cc',
+ 'spdy/hpack/hpack_decoder2_test.cc',
+ 'spdy/hpack/hpack_decoder3_test.cc',
'spdy/hpack/hpack_encoder_test.cc',
'spdy/hpack/hpack_entry_test.cc',
'spdy/hpack/hpack_header_table_test.cc',
@@ -1949,7 +2181,11 @@
'ssl/ssl_config_unittest.cc',
'ssl/ssl_connection_status_flags_unittest.cc',
'ssl/ssl_platform_key_android_unittest.cc',
+ 'ssl/ssl_platform_key_mac_unittest.cc',
+ 'ssl/ssl_platform_key_nss_unittest.cc',
'ssl/ssl_platform_key_util_unittest.cc',
+ 'ssl/ssl_private_key_test_util.cc',
+ 'ssl/ssl_private_key_test_util.h',
'test/embedded_test_server/embedded_test_server_unittest.cc',
'test/embedded_test_server/http_request_unittest.cc',
'test/embedded_test_server/http_response_unittest.cc',
@@ -1962,14 +2198,13 @@
'tools/quic/quic_simple_client_test.cc',
'tools/quic/test_tools/mock_quic_server_session_visitor.cc',
'tools/quic/test_tools/mock_quic_server_session_visitor.h',
- 'tools/quic/test_tools/quic_in_memory_cache_peer.cc',
- 'tools/quic/test_tools/quic_in_memory_cache_peer.h',
'tools/tld_cleanup/tld_cleanup_util_unittest.cc',
'url_request/report_sender_unittest.cc',
'url_request/sdch_dictionary_fetcher_unittest.cc',
'url_request/url_fetcher_impl_unittest.cc',
'url_request/url_fetcher_response_writer_unittest.cc',
'url_request/url_request_context_builder_unittest.cc',
+ 'url_request/url_request_context_unittest.cc',
'url_request/url_request_data_job_unittest.cc',
'url_request/url_request_file_dir_job_unittest.cc',
'url_request/url_request_file_job_unittest.cc',
@@ -1989,20 +2224,22 @@
],
'net_linux_test_sources': [
'tools/quic/chlo_extractor_test.cc',
+ 'tools/quic/platform/impl/quic_epoll_clock_test.cc',
+ "tools/quic/platform/impl/quic_socket_utils_test.cc",
'tools/quic/end_to_end_test.cc',
'tools/quic/quic_client_session_test.cc',
'tools/quic/quic_client_test.cc',
'tools/quic/quic_dispatcher_test.cc',
'tools/quic/quic_epoll_alarm_factory_test.cc',
- 'tools/quic/quic_epoll_clock_test.cc',
'tools/quic/quic_epoll_connection_helper_test.cc',
- 'tools/quic/quic_in_memory_cache_test.cc',
+ 'tools/quic/quic_http_response_cache_test.cc',
'tools/quic/quic_server_test.cc',
'tools/quic/quic_simple_server_session_helper_test.cc',
'tools/quic/quic_simple_server_session_test.cc',
'tools/quic/quic_simple_server_stream_test.cc',
'tools/quic/quic_simple_server_test.cc',
'tools/quic/quic_spdy_client_stream_test.cc',
+ 'tools/quic/quic_spdy_server_stream_base_test.cc',
'tools/quic/quic_time_wait_list_manager_test.cc',
'tools/quic/stateless_rejector_test.cc',
'tools/quic/test_tools/limited_mtu_test_writer.cc',
@@ -2179,7 +2416,9 @@
'data/ssl/certificates/aia-intermediate.der',
'data/ssl/certificates/aia-root.pem',
'data/ssl/certificates/bad_validity.pem',
+ 'data/ssl/certificates/client-empty-password.p12',
'data/ssl/certificates/client-nokey.p12',
+ 'data/ssl/certificates/client-null-password.p12',
'data/ssl/certificates/client.p12',
'data/ssl/certificates/client_1.key',
'data/ssl/certificates/client_1.pem',
@@ -2197,6 +2436,14 @@
'data/ssl/certificates/client_4.pem',
'data/ssl/certificates/client_4.pk8',
'data/ssl/certificates/client_4_ca.pem',
+ 'data/ssl/certificates/client_5.key',
+ 'data/ssl/certificates/client_5.pem',
+ 'data/ssl/certificates/client_5.pk8',
+ 'data/ssl/certificates/client_5_ca.pem',
+ 'data/ssl/certificates/client_6.key',
+ 'data/ssl/certificates/client_6.pem',
+ 'data/ssl/certificates/client_6.pk8',
+ 'data/ssl/certificates/client_6_ca.pem',
'data/ssl/certificates/client_root_ca.pem',
'data/ssl/certificates/comodo.chain.pem',
'data/ssl/certificates/crit-codeSigning-chain.pem',
@@ -2236,6 +2483,7 @@
'data/ssl/certificates/google.single.pem',
'data/ssl/certificates/google_diginotar.pem',
'data/ssl/certificates/googlenew.chain.pem',
+ 'data/ssl/certificates/intermediate_ca_cert.pem',
'data/ssl/certificates/invalid_key_usage_cert.der',
'data/ssl/certificates/large_key.pem',
'data/ssl/certificates/localhost_cert.pem',
@@ -2265,6 +2513,7 @@
'data/ssl/certificates/non-crit-codeSigning-chain.pem',
'data/ssl/certificates/ocsp-test-root.pem',
'data/ssl/certificates/ok_cert.pem',
+ 'data/ssl/certificates/ok_cert_by_intermediate.pem',
'data/ssl/certificates/post_june_2016.pem',
'data/ssl/certificates/pre_br_validity_bad_121.pem',
'data/ssl/certificates/pre_br_validity_bad_2020.pem',
@@ -2287,6 +2536,7 @@
'data/ssl/certificates/quic_test.example.com.key.sct',
'data/ssl/certificates/quic_test_ecc.example.com.crt',
'data/ssl/certificates/quic_test_ecc.example.com.key',
+ 'data/ssl/certificates/quic_test_ecc.example.com.sct',
'data/ssl/certificates/redundant-server-chain.pem',
'data/ssl/certificates/redundant-validated-chain-root.pem',
'data/ssl/certificates/redundant-validated-chain.pem',
@@ -2353,9 +2603,13 @@
'data/cert_issuer_source_static_unittest/c1.pem',
'data/cert_issuer_source_static_unittest/c2.pem',
'data/cert_issuer_source_static_unittest/d.pem',
+ 'data/cert_issuer_source_static_unittest/e1.pem',
+ 'data/cert_issuer_source_static_unittest/e2.pem',
'data/cert_issuer_source_static_unittest/i1_1.pem',
'data/cert_issuer_source_static_unittest/i1_2.pem',
'data/cert_issuer_source_static_unittest/i2.pem',
+ 'data/cert_issuer_source_static_unittest/i3_1.pem',
+ 'data/cert_issuer_source_static_unittest/i3_2.pem',
'data/cert_issuer_source_static_unittest/root.pem',
'data/certificate_policies_unittest/anypolicy.pem',
'data/certificate_policies_unittest/anypolicy_with_qualifier.pem',
@@ -2381,6 +2635,8 @@
'data/name_constraints_unittest/dnsname-exclude_dot.pem',
'data/name_constraints_unittest/dnsname-excludeall.pem',
'data/name_constraints_unittest/dnsname-excluded.pem',
+ 'data/name_constraints_unittest/dnsname-excluded_with_leading_dot.pem',
+ 'data/name_constraints_unittest/dnsname-permitted_two_dot.pem',
'data/name_constraints_unittest/dnsname-permitted_with_leading_dot.pem',
'data/name_constraints_unittest/dnsname-with_max.pem',
'data/name_constraints_unittest/dnsname-with_min_0.pem',
@@ -3313,5 +3569,28 @@
'third_party/nist-pkits/crls/requireExplicitPolicy7subsubCARE2RE4CRL.crl',
'third_party/nist-pkits/crls/requireExplicitPolicy7subsubsubCARE2RE4CRL.crl',
],
+ 'net_domain_security_state_generator_sources': [
+ 'tools/domain_security_preload_generator/bit_writer.cc',
+ 'tools/domain_security_preload_generator/bit_writer.h',
+ 'tools/domain_security_preload_generator/cert_util.cc',
+ 'tools/domain_security_preload_generator/cert_util.h',
+ 'tools/domain_security_preload_generator/domain_security_entry.cc',
+ 'tools/domain_security_preload_generator/domain_security_entry.h',
+ 'tools/domain_security_preload_generator/domain_security_preload_generator.cc',
+ 'tools/domain_security_preload_generator/huffman/huffman_frequency_tracker.cc',
+ 'tools/domain_security_preload_generator/huffman/huffman_frequency_tracker.h',
+ 'tools/domain_security_preload_generator/pinset.cc',
+ 'tools/domain_security_preload_generator/pinset.h',
+ 'tools/domain_security_preload_generator/pinsets.cc',
+ 'tools/domain_security_preload_generator/pinsets.h',
+ 'tools/domain_security_preload_generator/preloaded_state_generator.cc',
+ 'tools/domain_security_preload_generator/preloaded_state_generator.h',
+ 'tools/domain_security_preload_generator/spki_hash.cc',
+ 'tools/domain_security_preload_generator/spki_hash.h',
+ 'tools/domain_security_preload_generator/trie/trie_bit_buffer.cc',
+ 'tools/domain_security_preload_generator/trie/trie_bit_buffer.h',
+ 'tools/domain_security_preload_generator/trie/trie_writer.cc',
+ 'tools/domain_security_preload_generator/trie/trie_writer.h',
+ ],
}
}
diff --git a/chromium/net/nqe/OWNERS b/chromium/net/nqe/OWNERS
index ae2513b27d3..6bb7ca34261 100644
--- a/chromium/net/nqe/OWNERS
+++ b/chromium/net/nqe/OWNERS
@@ -1,2 +1,3 @@
bengr@chromium.org
-tbansal@chromium.org \ No newline at end of file
+tbansal@chromium.org
+ryansturm@chromium.org \ No newline at end of file
diff --git a/chromium/net/nqe/cached_network_quality.cc b/chromium/net/nqe/cached_network_quality.cc
index bcdd885128c..9b78de21da2 100644
--- a/chromium/net/nqe/cached_network_quality.cc
+++ b/chromium/net/nqe/cached_network_quality.cc
@@ -44,4 +44,4 @@ bool CachedNetworkQuality::OlderThan(
} // namespace nqe
-} // namespace net \ No newline at end of file
+} // namespace net
diff --git a/chromium/net/nqe/cached_network_quality.h b/chromium/net/nqe/cached_network_quality.h
index 0f6720ce7ad..9f437da93ca 100644
--- a/chromium/net/nqe/cached_network_quality.h
+++ b/chromium/net/nqe/cached_network_quality.h
@@ -64,4 +64,4 @@ class NET_EXPORT_PRIVATE CachedNetworkQuality {
} // namespace net
-#endif // NET_NQE_CACHED_NETWORK_QUALITY_H_ \ No newline at end of file
+#endif // NET_NQE_CACHED_NETWORK_QUALITY_H_
diff --git a/chromium/net/nqe/effective_connection_type.cc b/chromium/net/nqe/effective_connection_type.cc
index 94908d4c046..ea1fec4e141 100644
--- a/chromium/net/nqe/effective_connection_type.cc
+++ b/chromium/net/nqe/effective_connection_type.cc
@@ -71,4 +71,4 @@ bool GetEffectiveConnectionTypeForName(
return false;
}
-} // namespace net \ No newline at end of file
+} // namespace net
diff --git a/chromium/net/nqe/effective_connection_type_unittest.cc b/chromium/net/nqe/effective_connection_type_unittest.cc
index f5dffba9eb9..841a9115ca6 100644
--- a/chromium/net/nqe/effective_connection_type_unittest.cc
+++ b/chromium/net/nqe/effective_connection_type_unittest.cc
@@ -50,4 +50,4 @@ TEST(EffectiveConnectionTypeTest, NameConnectionTypeConversion) {
} // namespace
-} // namespace net \ No newline at end of file
+} // namespace net
diff --git a/chromium/net/nqe/network_id.h b/chromium/net/nqe/network_id.h
index 083a55fad4c..78b45884e30 100644
--- a/chromium/net/nqe/network_id.h
+++ b/chromium/net/nqe/network_id.h
@@ -27,7 +27,7 @@ net::NetworkChangeNotifier::ConnectionType ConvertStringToConnectionType(
base::StringToInt(connection_type_string, &connection_type_int);
if (!connection_type_available || connection_type_int < 0 ||
- connection_type_int >=
+ connection_type_int >
static_cast<int>(net::NetworkChangeNotifier::CONNECTION_LAST)) {
DCHECK(false);
return net::NetworkChangeNotifier::CONNECTION_UNKNOWN;
@@ -105,4 +105,4 @@ struct NET_EXPORT_PRIVATE NetworkID {
} // namespace nqe
} // namespace net
-#endif // NET_NQE_NETWORK_QUALITY_ESTIMATOR_H_ \ No newline at end of file
+#endif // NET_NQE_NETWORK_ID_H_
diff --git a/chromium/net/nqe/network_qualities_prefs_manager.cc b/chromium/net/nqe/network_qualities_prefs_manager.cc
index 64c9f5c4451..82e22c47a44 100644
--- a/chromium/net/nqe/network_qualities_prefs_manager.cc
+++ b/chromium/net/nqe/network_qualities_prefs_manager.cc
@@ -8,6 +8,7 @@
#include <utility>
#include "base/bind.h"
+#include "base/rand_util.h"
#include "base/sequenced_task_runner.h"
#include "base/threading/thread_checker.h"
#include "base/threading/thread_task_runner_handle.h"
@@ -18,7 +19,14 @@ namespace net {
namespace {
// Maximum size of the prefs that hold the qualities of different networks.
-static const size_t kMaxCacheSize = 3u;
+// A single entry in the cache consists of three tuples:
+// (i) SSID or MCCMNC of the network. SSID is at most 32 characters in length
+// (but is typically shorter than that). MCCMNC is at most 6 characters
+// long.
+// (ii) Connection type of the network as reported by network
+// change notifier (an enum).
+// (iii) Effective connection type of the network (an enum).
+static const size_t kMaxCacheSize = 10u;
// Parses |value| into a map of NetworkIDs and CachedNetworkQualities,
// and returns the map.
@@ -56,11 +64,12 @@ NetworkQualitiesPrefsManager::NetworkQualitiesPrefsManager(
std::unique_ptr<PrefDelegate> pref_delegate)
: pref_delegate_(std::move(pref_delegate)),
pref_task_runner_(base::ThreadTaskRunnerHandle::Get()),
- prefs_(pref_delegate_->GetDictionaryValue().CreateDeepCopy()),
+ prefs_(pref_delegate_->GetDictionaryValue()),
network_quality_estimator_(nullptr),
read_prefs_startup_(ConvertDictionaryValueToMap(prefs_.get())),
pref_weak_ptr_factory_(this) {
DCHECK(pref_delegate_);
+ DCHECK(pref_task_runner_);
DCHECK_GE(kMaxCacheSize, prefs_->size());
pref_weak_ptr_ = pref_weak_ptr_factory_.GetWeakPtr();
@@ -132,16 +141,26 @@ void NetworkQualitiesPrefsManager::OnChangeInCachedNetworkQualityOnPrefThread(
cached_network_quality.effective_connection_type()));
if (prefs_->size() > kMaxCacheSize) {
- // Delete one value that has key different than |network_id|.
+ // Delete one randomly selected value that has a key that is different from
+ // |network_id|.
DCHECK_EQ(kMaxCacheSize + 1, prefs_->size());
+ // Generate a random number between 0 and |kMaxCacheSize| -1 (both
+ // inclusive) since the number of network IDs in |prefs_| other than
+ // |network_id| is |kMaxCacheSize|.
+ int index_to_delete = base::RandInt(0, kMaxCacheSize - 1);
+
for (base::DictionaryValue::Iterator it(*prefs_); !it.IsAtEnd();
it.Advance()) {
- const nqe::internal::NetworkID it_network_id =
- nqe::internal::NetworkID::FromString(it.key());
- if (it_network_id != network_id) {
+ // Delete the kth element in the dictionary, not including the element
+ // that represents the current network. k == |index_to_delete|.
+ if (nqe::internal::NetworkID::FromString(it.key()) == network_id)
+ continue;
+
+ if (index_to_delete == 0) {
prefs_->RemovePath(it.key(), nullptr);
break;
}
+ index_to_delete--;
}
}
DCHECK_GE(kMaxCacheSize, prefs_->size());
@@ -153,7 +172,7 @@ void NetworkQualitiesPrefsManager::OnChangeInCachedNetworkQualityOnPrefThread(
ParsedPrefs NetworkQualitiesPrefsManager::ForceReadPrefsForTesting() const {
DCHECK(pref_task_runner_->RunsTasksOnCurrentThread());
std::unique_ptr<base::DictionaryValue> value(
- pref_delegate_->GetDictionaryValue().CreateDeepCopy());
+ pref_delegate_->GetDictionaryValue());
return ConvertDictionaryValueToMap(value.get());
}
diff --git a/chromium/net/nqe/network_qualities_prefs_manager.h b/chromium/net/nqe/network_qualities_prefs_manager.h
index 59151096866..db315e36445 100644
--- a/chromium/net/nqe/network_qualities_prefs_manager.h
+++ b/chromium/net/nqe/network_qualities_prefs_manager.h
@@ -54,8 +54,8 @@ class NET_EXPORT NetworkQualitiesPrefsManager
// Sets the persistent pref to the given value.
virtual void SetDictionaryValue(const base::DictionaryValue& value) = 0;
- // Returns the peristent prefs.
- virtual const base::DictionaryValue& GetDictionaryValue() = 0;
+ // Returns a copy of the persistent prefs.
+ virtual std::unique_ptr<base::DictionaryValue> GetDictionaryValue() = 0;
};
// Creates an instance of the NetworkQualitiesPrefsManager. Ownership of
diff --git a/chromium/net/nqe/network_qualities_prefs_manager_unittest.cc b/chromium/net/nqe/network_qualities_prefs_manager_unittest.cc
index 51bb8c5bf4e..34cb11b288c 100644
--- a/chromium/net/nqe/network_qualities_prefs_manager_unittest.cc
+++ b/chromium/net/nqe/network_qualities_prefs_manager_unittest.cc
@@ -4,11 +4,14 @@
#include "net/nqe/network_qualities_prefs_manager.h"
+#include <algorithm>
#include <map>
#include <memory>
#include "base/macros.h"
#include "base/run_loop.h"
+#include "base/strings/string_number_conversions.h"
+#include "base/test/histogram_tester.h"
#include "base/threading/thread_checker.h"
#include "base/values.h"
#include "net/base/network_change_notifier.h"
@@ -40,11 +43,11 @@ class TestPrefDelegate : public NetworkQualitiesPrefsManager::PrefDelegate {
ASSERT_EQ(value.size(), value_->size());
}
- const base::DictionaryValue& GetDictionaryValue() override {
+ std::unique_ptr<base::DictionaryValue> GetDictionaryValue() override {
DCHECK(thread_checker_.CalledOnValidThread());
read_count_++;
- return *(value_.get());
+ return value_->CreateDeepCopy();
}
size_t write_count() const {
@@ -71,8 +74,7 @@ class TestPrefDelegate : public NetworkQualitiesPrefsManager::PrefDelegate {
};
TEST(NetworkQualitiesPrefManager, Write) {
- std::map<std::string, std::string> variation_params;
- TestNetworkQualityEstimator estimator(variation_params, nullptr);
+ TestNetworkQualityEstimator estimator;
std::unique_ptr<TestPrefDelegate> prefs_delegate(new TestPrefDelegate());
TestPrefDelegate* prefs_delegate_ptr = prefs_delegate.get();
@@ -110,8 +112,7 @@ TEST(NetworkQualitiesPrefManager, Write) {
// Verify that the pref is not written if the network ID contains a period.
TEST(NetworkQualitiesPrefManager, WriteWithPeriodInNetworkID) {
- std::map<std::string, std::string> variation_params;
- TestNetworkQualityEstimator estimator(variation_params, nullptr);
+ TestNetworkQualityEstimator estimator;
std::unique_ptr<TestPrefDelegate> prefs_delegate(new TestPrefDelegate());
TestPrefDelegate* prefs_delegate_ptr = prefs_delegate.get();
@@ -137,8 +138,8 @@ TEST(NetworkQualitiesPrefManager, WriteWithPeriodInNetworkID) {
}
TEST(NetworkQualitiesPrefManager, WriteAndReadWithMultipleNetworkIDs) {
- std::map<std::string, std::string> variation_params;
- TestNetworkQualityEstimator estimator(variation_params, nullptr);
+ static const size_t kMaxCacheSize = 10u;
+ TestNetworkQualityEstimator estimator;
std::unique_ptr<TestPrefDelegate> prefs_delegate(new TestPrefDelegate());
@@ -147,7 +148,7 @@ TEST(NetworkQualitiesPrefManager, WriteAndReadWithMultipleNetworkIDs) {
base::RunLoop().RunUntilIdle();
estimator.SimulateNetworkChange(
- NetworkChangeNotifier::ConnectionType::CONNECTION_UNKNOWN, "test");
+ NetworkChangeNotifier::ConnectionType::CONNECTION_2G, "test");
EXPECT_EQ(0u, manager.ForceReadPrefsForTesting().size());
@@ -161,77 +162,44 @@ TEST(NetworkQualitiesPrefManager, WriteAndReadWithMultipleNetworkIDs) {
// written to the prefs.
EXPECT_EQ(1u, manager.ForceReadPrefsForTesting().size());
- // Chnage the network ID.
- estimator.SimulateNetworkChange(
- NetworkChangeNotifier::ConnectionType::CONNECTION_2G, "test");
- estimator.set_recent_effective_connection_type(EFFECTIVE_CONNECTION_TYPE_2G);
- estimator.RunOneRequest();
- base::RunLoop().RunUntilIdle();
- EXPECT_EQ(2u, manager.ForceReadPrefsForTesting().size());
+ // Change the network ID.
+ for (size_t i = 0; i < kMaxCacheSize; ++i) {
+ estimator.SimulateNetworkChange(
+ NetworkChangeNotifier::ConnectionType::CONNECTION_2G,
+ "test" + base::IntToString(i));
- estimator.SimulateNetworkChange(
- NetworkChangeNotifier::ConnectionType::CONNECTION_3G, "test");
- estimator.set_recent_effective_connection_type(EFFECTIVE_CONNECTION_TYPE_3G);
- estimator.RunOneRequest();
- base::RunLoop().RunUntilIdle();
- EXPECT_EQ(3u, manager.ForceReadPrefsForTesting().size());
+ estimator.RunOneRequest();
+ base::RunLoop().RunUntilIdle();
- estimator.SimulateNetworkChange(
- NetworkChangeNotifier::ConnectionType::CONNECTION_4G, "test");
- estimator.set_recent_effective_connection_type(EFFECTIVE_CONNECTION_TYPE_4G);
- estimator.RunOneRequest();
- base::RunLoop().RunUntilIdle();
- // Size of prefs must not exceed 3.
- EXPECT_EQ(3u, manager.ForceReadPrefsForTesting().size());
+ EXPECT_EQ(std::min(i + 2, kMaxCacheSize),
+ manager.ForceReadPrefsForTesting().size());
+ }
- estimator.SimulateNetworkChange(
- NetworkChangeNotifier::ConnectionType::CONNECTION_WIFI, "test");
- estimator.set_recent_effective_connection_type(
- EFFECTIVE_CONNECTION_TYPE_SLOW_2G);
- estimator.RunOneRequest();
- base::RunLoop().RunUntilIdle();
std::map<nqe::internal::NetworkID, nqe::internal::CachedNetworkQuality>
read_prefs = manager.ForceReadPrefsForTesting();
- EXPECT_EQ(3u, read_prefs.size());
// Verify the contents of the prefs.
for (std::map<nqe::internal::NetworkID,
nqe::internal::CachedNetworkQuality>::const_iterator it =
read_prefs.begin();
it != read_prefs.end(); ++it) {
- EXPECT_EQ("test", it->first.id);
- switch (it->first.type) {
- case NetworkChangeNotifier::ConnectionType::CONNECTION_UNKNOWN:
- EXPECT_EQ(EFFECTIVE_CONNECTION_TYPE_SLOW_2G,
- it->second.effective_connection_type());
- break;
- case NetworkChangeNotifier::ConnectionType::CONNECTION_2G:
- EXPECT_EQ(EFFECTIVE_CONNECTION_TYPE_2G,
- it->second.effective_connection_type());
- break;
- case NetworkChangeNotifier::ConnectionType::CONNECTION_3G:
- EXPECT_EQ(EFFECTIVE_CONNECTION_TYPE_3G,
- it->second.effective_connection_type());
- break;
- case NetworkChangeNotifier::ConnectionType::CONNECTION_4G:
- EXPECT_EQ(EFFECTIVE_CONNECTION_TYPE_4G,
- it->second.effective_connection_type());
- break;
- case NetworkChangeNotifier::ConnectionType::CONNECTION_WIFI:
- EXPECT_EQ(EFFECTIVE_CONNECTION_TYPE_SLOW_2G,
- it->second.effective_connection_type());
- break;
- default:
- NOTREACHED();
- }
+ EXPECT_EQ(0u, it->first.id.find("test", 0u));
+ EXPECT_EQ(NetworkChangeNotifier::ConnectionType::CONNECTION_2G,
+ it->first.type);
+ EXPECT_EQ(EFFECTIVE_CONNECTION_TYPE_SLOW_2G,
+ it->second.effective_connection_type());
}
+
+ base::HistogramTester histogram_tester;
+ estimator.OnPrefsRead(read_prefs);
+ histogram_tester.ExpectUniqueSample("NQE.Prefs.ReadSize", kMaxCacheSize, 1);
+
manager.ShutdownOnPrefThread();
}
// Verifies that the prefs are cleared correctly.
TEST(NetworkQualitiesPrefManager, ClearPrefs) {
- std::map<std::string, std::string> variation_params;
- TestNetworkQualityEstimator estimator(variation_params, nullptr);
+ TestNetworkQualityEstimator estimator;
std::unique_ptr<TestPrefDelegate> prefs_delegate(new TestPrefDelegate());
@@ -270,4 +238,4 @@ TEST(NetworkQualitiesPrefManager, ClearPrefs) {
} // namespace
-} // namespace net \ No newline at end of file
+} // namespace net
diff --git a/chromium/net/nqe/network_quality.cc b/chromium/net/nqe/network_quality.cc
index 6c572dc917d..293d4cbfd7e 100644
--- a/chromium/net/nqe/network_quality.cc
+++ b/chromium/net/nqe/network_quality.cc
@@ -57,4 +57,4 @@ bool NetworkQuality::IsFaster(const NetworkQuality& other) const {
} // namespace internal
} // namespace nqe
-} // namespace net \ No newline at end of file
+} // namespace net
diff --git a/chromium/net/nqe/network_quality.h b/chromium/net/nqe/network_quality.h
index 9a7dbe460c4..a4c5f8462f2 100644
--- a/chromium/net/nqe/network_quality.h
+++ b/chromium/net/nqe/network_quality.h
@@ -96,4 +96,4 @@ class NET_EXPORT_PRIVATE NetworkQuality {
} // namespace nqe
} // namespace net
-#endif // NET_NQE_NETWORK_QUALITY_H_ \ No newline at end of file
+#endif // NET_NQE_NETWORK_QUALITY_H_
diff --git a/chromium/net/nqe/network_quality_estimator.cc b/chromium/net/nqe/network_quality_estimator.cc
index 55da1c78532..095a044967a 100644
--- a/chromium/net/nqe/network_quality_estimator.cc
+++ b/chromium/net/nqe/network_quality_estimator.cc
@@ -28,6 +28,7 @@
#include "net/base/load_flags.h"
#include "net/base/load_timing_info.h"
#include "net/base/network_interfaces.h"
+#include "net/base/trace_constants.h"
#include "net/base/url_util.h"
#include "net/http/http_response_headers.h"
#include "net/http/http_response_info.h"
@@ -44,39 +45,39 @@
#include "net/android/network_library.h"
#endif // OS_ANDROID
+namespace net {
+
namespace {
// Returns the histogram that should be used to record the given statistic.
// |max_limit| is the maximum value that can be stored in the histogram.
-base::HistogramBase* GetHistogram(
- const std::string& statistic_name,
- net::NetworkChangeNotifier::ConnectionType type,
- int32_t max_limit) {
+base::HistogramBase* GetHistogram(const std::string& statistic_name,
+ NetworkChangeNotifier::ConnectionType type,
+ int32_t max_limit) {
const base::LinearHistogram::Sample kLowerLimit = 1;
DCHECK_GT(max_limit, kLowerLimit);
const size_t kBucketCount = 50;
return base::Histogram::FactoryGet(
- "NQE." + statistic_name +
- net::nqe::internal::GetNameForConnectionType(type),
+ "NQE." + statistic_name + nqe::internal::GetNameForConnectionType(type),
kLowerLimit, max_limit, kBucketCount,
base::HistogramBase::kUmaTargetedHistogramFlag);
}
-net::NetworkQualityObservationSource ProtocolSourceToObservationSource(
- net::SocketPerformanceWatcherFactory::Protocol protocol) {
+NetworkQualityObservationSource ProtocolSourceToObservationSource(
+ SocketPerformanceWatcherFactory::Protocol protocol) {
switch (protocol) {
- case net::SocketPerformanceWatcherFactory::PROTOCOL_TCP:
- return net::NETWORK_QUALITY_OBSERVATION_SOURCE_TCP;
- case net::SocketPerformanceWatcherFactory::PROTOCOL_QUIC:
- return net::NETWORK_QUALITY_OBSERVATION_SOURCE_QUIC;
+ case SocketPerformanceWatcherFactory::PROTOCOL_TCP:
+ return NETWORK_QUALITY_OBSERVATION_SOURCE_TCP;
+ case SocketPerformanceWatcherFactory::PROTOCOL_QUIC:
+ return NETWORK_QUALITY_OBSERVATION_SOURCE_QUIC;
}
NOTREACHED();
- return net::NETWORK_QUALITY_OBSERVATION_SOURCE_TCP;
+ return NETWORK_QUALITY_OBSERVATION_SOURCE_TCP;
}
// Returns true if the scheme of the |request| is either HTTP or HTTPS.
-bool RequestSchemeIsHTTPOrHTTPS(const net::URLRequest& request) {
+bool RequestSchemeIsHTTPOrHTTPS(const URLRequest& request) {
return request.url().is_valid() && request.url().SchemeIsHTTPOrHTTPS();
}
@@ -139,6 +140,7 @@ static_assert(32 >= kBitsPerMetric * 4,
int32_t FitInKBitsPerMetricBits(int32_t metric) {
// Remove the last kTrimBits. This will allow the metric to fit within
// kBitsPerMetric while losing only the least significant bits.
+ DCHECK_LE(0, metric);
metric = metric >> kTrimBits;
// kLargestValuePossible is the largest value that can be recorded using
@@ -148,7 +150,7 @@ int32_t FitInKBitsPerMetricBits(int32_t metric) {
// Fit |metric| in kBitsPerMetric by clamping it down.
metric = kLargestValuePossible;
}
- DCHECK_EQ(0, metric >> kBitsPerMetric);
+ DCHECK_EQ(0, metric >> kBitsPerMetric) << metric;
return metric;
}
@@ -188,25 +190,22 @@ void RecordEffectiveConnectionTypeAccuracy(
const char* prefix,
int32_t metric,
base::TimeDelta measuring_duration,
- net::EffectiveConnectionType observed_effective_connection_type) {
- const std::string histogram_name =
- base::StringPrintf("%s.EstimatedObservedDiff.%s.%d.%s", prefix,
- metric >= 0 ? "Positive" : "Negative",
- static_cast<int32_t>(measuring_duration.InSeconds()),
- net::GetNameForEffectiveConnectionType(
- observed_effective_connection_type));
+ EffectiveConnectionType observed_effective_connection_type) {
+ const std::string histogram_name = base::StringPrintf(
+ "%s.EstimatedObservedDiff.%s.%d.%s", prefix,
+ metric >= 0 ? "Positive" : "Negative",
+ static_cast<int32_t>(measuring_duration.InSeconds()),
+ GetNameForEffectiveConnectionType(observed_effective_connection_type));
base::HistogramBase* histogram = base::Histogram::FactoryGet(
- histogram_name, 0, net::EFFECTIVE_CONNECTION_TYPE_LAST,
- net::EFFECTIVE_CONNECTION_TYPE_LAST /* Number of buckets */,
+ histogram_name, 0, EFFECTIVE_CONNECTION_TYPE_LAST,
+ EFFECTIVE_CONNECTION_TYPE_LAST /* Number of buckets */,
base::HistogramBase::kUmaTargetedHistogramFlag);
histogram->Add(std::abs(metric));
}
} // namespace
-namespace net {
-
NetworkQualityEstimator::NetworkQualityEstimator(
std::unique_ptr<ExternalEstimateProvider> external_estimates_provider,
const std::map<std::string, std::string>& variation_params)
@@ -220,6 +219,18 @@ NetworkQualityEstimator::NetworkQualityEstimator(
const std::map<std::string, std::string>& variation_params,
bool use_local_host_requests_for_tests,
bool use_smaller_responses_for_tests)
+ : NetworkQualityEstimator(std::move(external_estimates_provider),
+ variation_params,
+ use_local_host_requests_for_tests,
+ use_smaller_responses_for_tests,
+ true) {}
+
+NetworkQualityEstimator::NetworkQualityEstimator(
+ std::unique_ptr<ExternalEstimateProvider> external_estimates_provider,
+ const std::map<std::string, std::string>& variation_params,
+ bool use_local_host_requests_for_tests,
+ bool use_smaller_responses_for_tests,
+ bool add_default_platform_observations)
: algorithm_name_to_enum_({{"HttpRTTAndDownstreamThroughput",
EffectiveConnectionTypeAlgorithm::
HTTP_RTT_AND_DOWNSTREAM_THROUGHOUT},
@@ -228,25 +239,30 @@ NetworkQualityEstimator::NetworkQualityEstimator(
TRANSPORT_RTT_OR_DOWNSTREAM_THROUGHOUT}}),
use_localhost_requests_(use_local_host_requests_for_tests),
use_small_responses_(use_smaller_responses_for_tests),
+ disable_offline_check_(false),
+ add_default_platform_observations_(add_default_platform_observations),
weight_multiplier_per_second_(
nqe::internal::GetWeightMultiplierPerSecond(variation_params)),
+ weight_multiplier_per_dbm_(
+ nqe::internal::GetWeightMultiplierPerDbm(variation_params)),
effective_connection_type_algorithm_(
algorithm_name_to_enum_.find(
- net::nqe::internal::GetEffectiveConnectionTypeAlgorithm(
+ nqe::internal::GetEffectiveConnectionTypeAlgorithm(
variation_params)) == algorithm_name_to_enum_.end()
? kDefaultEffectiveConnectionTypeAlgorithm
: algorithm_name_to_enum_
- .find(
- net::nqe::internal::GetEffectiveConnectionTypeAlgorithm(
- variation_params))
+ .find(nqe::internal::GetEffectiveConnectionTypeAlgorithm(
+ variation_params))
->second),
tick_clock_(new base::DefaultTickClock()),
last_connection_change_(tick_clock_->NowTicks()),
current_network_id_(nqe::internal::NetworkID(
NetworkChangeNotifier::ConnectionType::CONNECTION_UNKNOWN,
std::string())),
- downstream_throughput_kbps_observations_(weight_multiplier_per_second_),
- rtt_observations_(weight_multiplier_per_second_),
+ downstream_throughput_kbps_observations_(weight_multiplier_per_second_,
+ weight_multiplier_per_dbm_),
+ rtt_observations_(weight_multiplier_per_second_,
+ weight_multiplier_per_dbm_),
effective_connection_type_at_last_main_frame_(
EFFECTIVE_CONNECTION_TYPE_UNKNOWN),
external_estimate_provider_(std::move(external_estimates_provider)),
@@ -255,6 +271,7 @@ NetworkQualityEstimator::NetworkQualityEstimator(
rtt_observations_size_at_last_ect_computation_(0),
throughput_observations_size_at_last_ect_computation_(0),
effective_connection_type_(EFFECTIVE_CONNECTION_TYPE_UNKNOWN),
+ signal_strength_dbm_(INT32_MIN),
min_signal_strength_since_connection_change_(INT32_MAX),
max_signal_strength_since_connection_change_(INT32_MIN),
correlation_uma_logging_probability_(
@@ -264,6 +281,8 @@ NetworkQualityEstimator::NetworkQualityEstimator(
variation_params)),
forced_effective_connection_type_(
nqe::internal::forced_effective_connection_type(variation_params)),
+ persistent_cache_reading_enabled_(
+ nqe::internal::persistent_cache_reading_enabled(variation_params)),
weak_ptr_factory_(this) {
// None of the algorithms can have an empty name.
DCHECK(algorithm_name_to_enum_.end() ==
@@ -298,15 +317,15 @@ NetworkQualityEstimator::NetworkQualityEstimator(
watcher_factory_.reset(new nqe::internal::SocketWatcherFactory(
base::ThreadTaskRunnerHandle::Get(),
+ nqe::internal::GetMinSocketWatcherNotificationInterval(variation_params),
base::Bind(&NetworkQualityEstimator::OnUpdatedRTTAvailable,
- base::Unretained(this))));
+ base::Unretained(this)),
+ tick_clock_.get()));
- // Record accuracy at 3 different intervals. The values used here must remain
- // in sync with the suffixes specified in
+ // Record accuracy after a 15 second interval. The values used here must
+ // remain in sync with the suffixes specified in
// tools/metrics/histograms/histograms.xml.
accuracy_recording_intervals_.push_back(base::TimeDelta::FromSeconds(15));
- accuracy_recording_intervals_.push_back(base::TimeDelta::FromSeconds(30));
- accuracy_recording_intervals_.push_back(base::TimeDelta::FromSeconds(60));
}
void NetworkQualityEstimator::ObtainOperatingParams(
@@ -316,27 +335,41 @@ void NetworkQualityEstimator::ObtainOperatingParams(
default_observations_);
nqe::internal::ObtainEffectiveConnectionTypeModelParams(
variation_params, connection_thresholds_);
+ nqe::internal::ObtainTypicalNetworkQuality(typical_network_quality_);
}
void NetworkQualityEstimator::AddDefaultEstimates() {
DCHECK(thread_checker_.CalledOnValidThread());
+ if (!add_default_platform_observations_)
+ return;
+
if (default_observations_[current_network_id_.type].http_rtt() !=
nqe::internal::InvalidRTT()) {
RttObservation rtt_observation(
default_observations_[current_network_id_.type].http_rtt(),
- tick_clock_->NowTicks(),
+ tick_clock_->NowTicks(), INT32_MIN,
NETWORK_QUALITY_OBSERVATION_SOURCE_DEFAULT_HTTP_FROM_PLATFORM);
rtt_observations_.AddObservation(rtt_observation);
NotifyObserversOfRTT(rtt_observation);
}
+ if (default_observations_[current_network_id_.type].transport_rtt() !=
+ nqe::internal::InvalidRTT()) {
+ RttObservation rtt_observation(
+ default_observations_[current_network_id_.type].transport_rtt(),
+ tick_clock_->NowTicks(), INT32_MIN,
+ NETWORK_QUALITY_OBSERVATION_SOURCE_DEFAULT_TRANSPORT_FROM_PLATFORM);
+ rtt_observations_.AddObservation(rtt_observation);
+ NotifyObserversOfRTT(rtt_observation);
+ }
+
if (default_observations_[current_network_id_.type]
.downstream_throughput_kbps() != nqe::internal::kInvalidThroughput) {
ThroughputObservation throughput_observation(
default_observations_[current_network_id_.type]
.downstream_throughput_kbps(),
- tick_clock_->NowTicks(),
+ tick_clock_->NowTicks(), INT32_MIN,
NETWORK_QUALITY_OBSERVATION_SOURCE_DEFAULT_HTTP_FROM_PLATFORM);
downstream_throughput_kbps_observations_.AddObservation(
throughput_observation);
@@ -362,33 +395,17 @@ void NetworkQualityEstimator::NotifyStartTransaction(
if (!RequestSchemeIsHTTPOrHTTPS(request))
return;
- throughput_analyzer_->NotifyStartTransaction(request);
-}
-
-void NetworkQualityEstimator::NotifyHeadersReceived(const URLRequest& request) {
- TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("net"),
- "NetworkQualityEstimator::NotifyHeadersReceived");
- DCHECK(thread_checker_.CalledOnValidThread());
-
- if (!RequestSchemeIsHTTPOrHTTPS(request) ||
- !RequestProvidesRTTObservation(request)) {
- return;
- }
-
- const base::TimeTicks now = tick_clock_->NowTicks();
-
// Update |estimated_quality_at_last_main_frame_| if this is a main frame
// request.
+ // TODO(tbansal): Refactor this to a separate method.
if (request.load_flags() & LOAD_MAIN_FRAME_DEPRECATED) {
+ base::TimeTicks now = tick_clock_->NowTicks();
last_main_frame_request_ = now;
- ComputeEffectiveConnectionType();
+ MaybeComputeEffectiveConnectionType();
effective_connection_type_at_last_main_frame_ = effective_connection_type_;
estimated_quality_at_last_main_frame_ = network_quality_;
- RecordMetricsOnMainFrameRequest();
- MaybeQueryExternalEstimateProvider();
-
// Post the tasks which will run in the future and record the estimation
// accuracy based on the observations received between now and the time of
// task execution. Posting the task at different intervals makes it
@@ -404,6 +421,24 @@ void NetworkQualityEstimator::NotifyHeadersReceived(const URLRequest& request) {
}
UpdateSignalStrength();
}
+ throughput_analyzer_->NotifyStartTransaction(request);
+}
+
+void NetworkQualityEstimator::NotifyHeadersReceived(const URLRequest& request) {
+ TRACE_EVENT0(kNetTracingCategory,
+ "NetworkQualityEstimator::NotifyHeadersReceived");
+ DCHECK(thread_checker_.CalledOnValidThread());
+
+ if (!RequestSchemeIsHTTPOrHTTPS(request) ||
+ !RequestProvidesRTTObservation(request)) {
+ return;
+ }
+
+ if (request.load_flags() & LOAD_MAIN_FRAME_DEPRECATED) {
+ ComputeEffectiveConnectionType();
+ RecordMetricsOnMainFrameRequest();
+ MaybeQueryExternalEstimateProvider();
+ }
LoadTimingInfo load_timing_info;
request.GetLoadTimingInfo(&load_timing_info);
@@ -428,8 +463,9 @@ void NetworkQualityEstimator::NotifyHeadersReceived(const URLRequest& request) {
peak_network_quality_.downstream_throughput_kbps());
}
- RttObservation http_rtt_observation(observed_http_rtt, now,
- NETWORK_QUALITY_OBSERVATION_SOURCE_HTTP);
+ RttObservation http_rtt_observation(
+ observed_http_rtt, tick_clock_->NowTicks(), signal_strength_dbm_,
+ NETWORK_QUALITY_OBSERVATION_SOURCE_HTTP);
rtt_observations_.AddObservation(http_rtt_observation);
NotifyObserversOfRTT(http_rtt_observation);
}
@@ -533,7 +569,7 @@ void NetworkQualityEstimator::RecordAccuracyAfterMainFrame(
void NetworkQualityEstimator::NotifyRequestCompleted(const URLRequest& request,
int net_error) {
- TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("net"),
+ TRACE_EVENT0(kNetTracingCategory,
"NetworkQualityEstimator::NotifyRequestCompleted");
DCHECK(thread_checker_.CalledOnValidThread());
@@ -579,37 +615,44 @@ void NetworkQualityEstimator::RecordCorrelationMetric(const URLRequest& request,
if (load_timing_info.receive_headers_end < last_main_frame_request_)
return;
- const base::TimeTicks now = tick_clock_->NowTicks();
+ // Use the system clock instead of |tick_clock_| to compare the current
+ // timestamp with the |load_timing_info| timestamp since the latter is set by
+ // the system clock, and may be different from |tick_clock_| in tests.
+ const base::TimeTicks now = base::TimeTicks::Now();
// Record UMA only for requests that started recently.
if (now - last_main_frame_request_ > base::TimeDelta::FromSeconds(15))
return;
+ if (last_connection_change_ >= last_main_frame_request_)
+ return;
+
DCHECK_GE(now, load_timing_info.send_start);
int32_t rtt = 0;
+ if (estimated_quality_at_last_main_frame_.downstream_throughput_kbps() ==
+ nqe::internal::kInvalidThroughput) {
+ return;
+ }
+
if (UseTransportRTT()) {
- rtt = estimated_quality_at_last_main_frame_.transport_rtt() !=
- nqe::internal::InvalidRTT()
- ? FitInKBitsPerMetricBits(
- estimated_quality_at_last_main_frame_.transport_rtt()
- .InMilliseconds())
- : 0;
+ if (estimated_quality_at_last_main_frame_.transport_rtt() ==
+ nqe::internal::InvalidRTT()) {
+ return;
+ }
+ rtt = FitInKBitsPerMetricBits(
+ estimated_quality_at_last_main_frame_.transport_rtt().InMilliseconds());
} else {
- rtt = estimated_quality_at_last_main_frame_.http_rtt() !=
- nqe::internal::InvalidRTT()
- ? FitInKBitsPerMetricBits(
- estimated_quality_at_last_main_frame_.http_rtt()
- .InMilliseconds())
- : 0;
+ if (estimated_quality_at_last_main_frame_.http_rtt() ==
+ nqe::internal::InvalidRTT()) {
+ return;
+ }
+ rtt = FitInKBitsPerMetricBits(
+ estimated_quality_at_last_main_frame_.http_rtt().InMilliseconds());
}
- const int32_t downstream_throughput =
- estimated_quality_at_last_main_frame_.downstream_throughput_kbps() !=
- nqe::internal::kInvalidThroughput
- ? FitInKBitsPerMetricBits(estimated_quality_at_last_main_frame_
- .downstream_throughput_kbps())
- : 0;
+ const int32_t downstream_throughput = FitInKBitsPerMetricBits(
+ estimated_quality_at_last_main_frame_.downstream_throughput_kbps());
const int32_t resource_load_time = FitInKBitsPerMetricBits(
(now - load_timing_info.send_start).InMilliseconds());
@@ -692,6 +735,13 @@ void NetworkQualityEstimator::SetUseSmallResponsesForTesting(
throughput_analyzer_->SetUseSmallResponsesForTesting(use_small_responses_);
}
+void NetworkQualityEstimator::DisableOfflineCheckForTesting(
+ bool disable_offline_check) {
+ DCHECK(thread_checker_.CalledOnValidThread());
+ disable_offline_check_ = disable_offline_check;
+ network_quality_store_->DisableOfflineCheckForTesting(disable_offline_check_);
+}
+
void NetworkQualityEstimator::ReportEffectiveConnectionTypeForTesting(
EffectiveConnectionType effective_connection_type) {
DCHECK(thread_checker_.CalledOnValidThread());
@@ -746,14 +796,25 @@ void NetworkQualityEstimator::OnConnectionTypeChanged(
"NQE.CellularSignalStrengthAvailable",
min_signal_strength_since_connection_change_ != INT32_MAX &&
max_signal_strength_since_connection_change_ != INT32_MIN);
+
+ if (min_signal_strength_since_connection_change_ != INT32_MAX &&
+ max_signal_strength_since_connection_change_ != INT32_MIN) {
+ UMA_HISTOGRAM_COUNTS_100(
+ "NQE.CellularSignalStrengthDifference",
+ max_signal_strength_since_connection_change_ -
+ min_signal_strength_since_connection_change_);
+ }
}
#endif // OS_ANDROID
+ signal_strength_dbm_ = INT32_MIN;
min_signal_strength_since_connection_change_ = INT32_MAX;
max_signal_strength_since_connection_change_ = INT32_MIN;
network_quality_ = nqe::internal::NetworkQuality();
effective_connection_type_ = EFFECTIVE_CONNECTION_TYPE_UNKNOWN;
effective_connection_type_at_last_main_frame_ =
EFFECTIVE_CONNECTION_TYPE_UNKNOWN;
+ rtt_observations_size_at_last_ect_computation_ = 0;
+ throughput_observations_size_at_last_ect_computation_ = 0;
// Update the local state as part of preparation for the new connection.
current_network_id_ = GetCurrentNetworkID();
@@ -788,15 +849,14 @@ void NetworkQualityEstimator::MaybeQueryExternalEstimateProvider() const {
void NetworkQualityEstimator::UpdateSignalStrength() {
#if defined(OS_ANDROID)
- int32_t signal_strength_dbm;
if (!android::cellular_signal_strength::GetSignalStrengthDbm(
- &signal_strength_dbm)) {
- return;
+ &signal_strength_dbm_)) {
+ signal_strength_dbm_ = INT32_MIN;
}
min_signal_strength_since_connection_change_ = std::min(
- min_signal_strength_since_connection_change_, signal_strength_dbm);
+ min_signal_strength_since_connection_change_, signal_strength_dbm_);
max_signal_strength_since_connection_change_ = std::max(
- max_signal_strength_since_connection_change_, signal_strength_dbm);
+ max_signal_strength_since_connection_change_, signal_strength_dbm_);
#endif // OS_ANDROID
}
@@ -830,6 +890,10 @@ void NetworkQualityEstimator::RecordMetricsOnConnectionTypeChanged() const {
NETWORK_QUALITY_OBSERVATION_SOURCE_TCP);
disallowed_observation_sources.push_back(
NETWORK_QUALITY_OBSERVATION_SOURCE_QUIC);
+ disallowed_observation_sources.push_back(
+ NETWORK_QUALITY_OBSERVATION_SOURCE_TRANSPORT_CACHED_ESTIMATE);
+ disallowed_observation_sources.push_back(
+ NETWORK_QUALITY_OBSERVATION_SOURCE_DEFAULT_TRANSPORT_FROM_PLATFORM);
for (size_t i = 0; i < arraysize(kPercentiles); ++i) {
rtt = GetRTTEstimateInternal(disallowed_observation_sources,
base::TimeTicks(), kPercentiles[i]);
@@ -1004,12 +1068,13 @@ NetworkQualityEstimator::GetRecentEffectiveConnectionTypeAndNetworkQuality(
if (effective_connection_type_algorithm_ ==
EffectiveConnectionTypeAlgorithm::HTTP_RTT_AND_DOWNSTREAM_THROUGHOUT) {
return GetRecentEffectiveConnectionTypeUsingMetrics(
- start_time, NetworkQualityEstimator::MetricUsage::
- MUST_BE_USED /* http_rtt_metric */,
+ start_time,
+ NetworkQualityEstimator::MetricUsage::
+ MUST_BE_USED /* http_rtt_metric */,
NetworkQualityEstimator::MetricUsage::
DO_NOT_USE /* transport_rtt_metric */,
NetworkQualityEstimator::MetricUsage::
- MUST_BE_USED /* downstream_throughput_kbps_metric */,
+ USE_IF_AVAILABLE /* downstream_throughput_kbps_metric */,
http_rtt, transport_rtt, downstream_throughput_kbps);
}
if (effective_connection_type_algorithm_ ==
@@ -1066,8 +1131,11 @@ NetworkQualityEstimator::GetRecentEffectiveConnectionTypeUsingMetrics(
// If the device is currently offline, then return
// EFFECTIVE_CONNECTION_TYPE_OFFLINE.
- if (current_network_id_.type == NetworkChangeNotifier::CONNECTION_NONE)
+
+ if (current_network_id_.type == NetworkChangeNotifier::CONNECTION_NONE &&
+ !disable_offline_check_) {
return EFFECTIVE_CONNECTION_TYPE_OFFLINE;
+ }
if (!GetRecentHttpRTT(start_time, http_rtt))
*http_rtt = nqe::internal::InvalidRTT();
@@ -1194,6 +1262,10 @@ bool NetworkQualityEstimator::GetRecentHttpRTT(
NETWORK_QUALITY_OBSERVATION_SOURCE_TCP);
disallowed_observation_sources.push_back(
NETWORK_QUALITY_OBSERVATION_SOURCE_QUIC);
+ disallowed_observation_sources.push_back(
+ NETWORK_QUALITY_OBSERVATION_SOURCE_TRANSPORT_CACHED_ESTIMATE);
+ disallowed_observation_sources.push_back(
+ NETWORK_QUALITY_OBSERVATION_SOURCE_DEFAULT_TRANSPORT_FROM_PLATFORM);
*rtt = GetRTTEstimateInternal(disallowed_observation_sources, start_time, 50);
return (*rtt != nqe::internal::InvalidRTT());
}
@@ -1235,7 +1307,8 @@ base::TimeDelta NetworkQualityEstimator::GetRTTEstimateInternal(
// RTT observations are sorted by duration from shortest to longest, thus
// a higher percentile RTT will have a longer RTT than a lower percentile.
base::TimeDelta rtt = nqe::internal::InvalidRTT();
- if (!rtt_observations_.GetPercentile(start_time, &rtt, percentile,
+ if (!rtt_observations_.GetPercentile(start_time, signal_strength_dbm_, &rtt,
+ percentile,
disallowed_observation_sources)) {
return nqe::internal::InvalidRTT();
}
@@ -1251,7 +1324,7 @@ int32_t NetworkQualityEstimator::GetDownlinkThroughputKbpsEstimateInternal(
// thus a higher percentile throughput will be faster than a lower one.
int32_t kbps = nqe::internal::kInvalidThroughput;
if (!downstream_throughput_kbps_observations_.GetPercentile(
- start_time, &kbps, 100 - percentile,
+ start_time, signal_strength_dbm_, &kbps, 100 - percentile,
std::vector<NetworkQualityObservationSource>())) {
return nqe::internal::kInvalidThroughput;
}
@@ -1307,6 +1380,9 @@ nqe::internal::NetworkID NetworkQualityEstimator::GetCurrentNetworkID() const {
bool NetworkQualityEstimator::ReadCachedNetworkQualityEstimate() {
DCHECK(thread_checker_.CalledOnValidThread());
+ if (!persistent_cache_reading_enabled_)
+ return false;
+
nqe::internal::CachedNetworkQuality cached_network_quality;
const bool cached_estimate_available = network_quality_store_->GetById(
@@ -1319,22 +1395,12 @@ bool NetworkQualityEstimator::ReadCachedNetworkQualityEstimate() {
const base::TimeTicks now = tick_clock_->NowTicks();
- if (effective_connection_type_ == EFFECTIVE_CONNECTION_TYPE_UNKNOWN) {
- // Read the effective connection type from the cached estimate.
- last_effective_connection_type_computation_ = now;
- network_quality_ = cached_network_quality.network_quality();
- effective_connection_type_ =
- cached_network_quality.effective_connection_type();
-
- if (effective_connection_type_ != EFFECTIVE_CONNECTION_TYPE_UNKNOWN)
- NotifyObserversOfEffectiveConnectionTypeChanged();
- }
-
if (cached_network_quality.network_quality().downstream_throughput_kbps() !=
nqe::internal::kInvalidThroughput) {
ThroughputObservation througphput_observation(
cached_network_quality.network_quality().downstream_throughput_kbps(),
- now, NETWORK_QUALITY_OBSERVATION_SOURCE_HTTP_CACHED_ESTIMATE);
+ now, INT32_MIN,
+ NETWORK_QUALITY_OBSERVATION_SOURCE_HTTP_CACHED_ESTIMATE);
downstream_throughput_kbps_observations_.AddObservation(
througphput_observation);
NotifyObserversOfThroughput(througphput_observation);
@@ -1343,11 +1409,22 @@ bool NetworkQualityEstimator::ReadCachedNetworkQualityEstimate() {
if (cached_network_quality.network_quality().http_rtt() !=
nqe::internal::InvalidRTT()) {
RttObservation rtt_observation(
- cached_network_quality.network_quality().http_rtt(), now,
+ cached_network_quality.network_quality().http_rtt(), now, INT32_MIN,
NETWORK_QUALITY_OBSERVATION_SOURCE_HTTP_CACHED_ESTIMATE);
rtt_observations_.AddObservation(rtt_observation);
NotifyObserversOfRTT(rtt_observation);
}
+
+ if (cached_network_quality.network_quality().transport_rtt() !=
+ nqe::internal::InvalidRTT()) {
+ RttObservation rtt_observation(
+ cached_network_quality.network_quality().transport_rtt(), now,
+ INT32_MIN,
+ NETWORK_QUALITY_OBSERVATION_SOURCE_TRANSPORT_CACHED_ESTIMATE);
+ rtt_observations_.AddObservation(rtt_observation);
+ NotifyObserversOfRTT(rtt_observation);
+ }
+ ComputeEffectiveConnectionType();
return true;
}
@@ -1368,7 +1445,7 @@ void NetworkQualityEstimator::OnUpdatedEstimateAvailable(
EXTERNAL_ESTIMATE_PROVIDER_STATUS_RTT_AVAILABLE);
UMA_HISTOGRAM_TIMES("NQE.ExternalEstimateProvider.RTT", rtt);
rtt_observations_.AddObservation(RttObservation(
- rtt, tick_clock_->NowTicks(),
+ rtt, tick_clock_->NowTicks(), signal_strength_dbm_,
NETWORK_QUALITY_OBSERVATION_SOURCE_HTTP_EXTERNAL_ESTIMATE));
external_estimate_provider_quality_.set_http_rtt(rtt);
}
@@ -1381,6 +1458,7 @@ void NetworkQualityEstimator::OnUpdatedEstimateAvailable(
downstream_throughput_kbps_observations_.AddObservation(
ThroughputObservation(
downstream_throughput_kbps, tick_clock_->NowTicks(),
+ signal_strength_dbm_,
NETWORK_QUALITY_OBSERVATION_SOURCE_HTTP_EXTERNAL_ESTIMATE));
external_estimate_provider_quality_.set_downstream_throughput_kbps(
downstream_throughput_kbps);
@@ -1403,7 +1481,7 @@ void NetworkQualityEstimator::OnUpdatedRTTAvailable(
DCHECK(thread_checker_.CalledOnValidThread());
DCHECK_NE(nqe::internal::InvalidRTT(), rtt);
- RttObservation observation(rtt, tick_clock_->NowTicks(),
+ RttObservation observation(rtt, tick_clock_->NowTicks(), signal_strength_dbm_,
ProtocolSourceToObservationSource(protocol));
NotifyObserversOfRTT(observation);
rtt_observations_.AddObservation(observation);
@@ -1454,7 +1532,7 @@ void NetworkQualityEstimator::OnNewThroughputObservationAvailable(
downstream_kbps);
}
ThroughputObservation throughput_observation(
- downstream_kbps, tick_clock_->NowTicks(),
+ downstream_kbps, tick_clock_->NowTicks(), signal_strength_dbm_,
NETWORK_QUALITY_OBSERVATION_SOURCE_HTTP);
downstream_throughput_kbps_observations_.AddObservation(
throughput_observation);
@@ -1558,9 +1636,77 @@ void NetworkQualityEstimator::OnPrefsRead(
const std::map<nqe::internal::NetworkID,
nqe::internal::CachedNetworkQuality> read_prefs) {
DCHECK(thread_checker_.CalledOnValidThread());
+
UMA_HISTOGRAM_COUNTS("NQE.Prefs.ReadSize", read_prefs.size());
- // TODO(tbansal): crbug.com/490870. Incorporate the network quality into the
- // current estimates.
+ for (auto& it : read_prefs) {
+ EffectiveConnectionType effective_connection_type =
+ it.second.effective_connection_type();
+ if (effective_connection_type == EFFECTIVE_CONNECTION_TYPE_UNKNOWN ||
+ effective_connection_type == EFFECTIVE_CONNECTION_TYPE_OFFLINE) {
+ continue;
+ }
+
+ // RTT and throughput values are not set in the prefs.
+ DCHECK_EQ(nqe::internal::InvalidRTT(),
+ it.second.network_quality().http_rtt());
+ DCHECK_EQ(nqe::internal::InvalidRTT(),
+ it.second.network_quality().transport_rtt());
+ DCHECK_EQ(nqe::internal::kInvalidThroughput,
+ it.second.network_quality().downstream_throughput_kbps());
+
+ nqe::internal::NetworkQuality network_quality(
+ typical_network_quality_[effective_connection_type].http_rtt(),
+ typical_network_quality_[effective_connection_type].transport_rtt(),
+ typical_network_quality_[effective_connection_type]
+ .downstream_throughput_kbps());
+
+ nqe::internal::CachedNetworkQuality cached_network_quality(
+ base::TimeTicks::Now(), network_quality, effective_connection_type);
+
+ network_quality_store_->Add(it.first, cached_network_quality);
+ MaybeUpdateNetworkQualityFromCache(it.first, cached_network_quality);
+ }
+}
+
+void NetworkQualityEstimator::MaybeUpdateNetworkQualityFromCache(
+ const nqe::internal::NetworkID& network_id,
+ const nqe::internal::CachedNetworkQuality& cached_network_quality) {
+ DCHECK(thread_checker_.CalledOnValidThread());
+
+ if (!persistent_cache_reading_enabled_)
+ return;
+ if (network_id != current_network_id_)
+ return;
+
+ // Since the cached network quality is for the current network, add it to
+ // the current observations.
+ RttObservation http_rtt_observation(
+ cached_network_quality.network_quality().http_rtt(),
+ base::TimeTicks::Now(), INT32_MIN,
+ NETWORK_QUALITY_OBSERVATION_SOURCE_HTTP_CACHED_ESTIMATE);
+ rtt_observations_.AddObservation(http_rtt_observation);
+ NotifyObserversOfRTT(http_rtt_observation);
+
+ RttObservation transport_rtt_observation(
+ cached_network_quality.network_quality().transport_rtt(),
+ base::TimeTicks::Now(), INT32_MIN,
+ NETWORK_QUALITY_OBSERVATION_SOURCE_TRANSPORT_CACHED_ESTIMATE);
+ rtt_observations_.AddObservation(transport_rtt_observation);
+ NotifyObserversOfRTT(transport_rtt_observation);
+
+ // TODO(tbansal): crbug.com/673977: Remove this check.
+ if (cached_network_quality.network_quality().downstream_throughput_kbps() !=
+ nqe::internal::kInvalidThroughput) {
+ ThroughputObservation throughput_observation(
+ cached_network_quality.network_quality().downstream_throughput_kbps(),
+ base::TimeTicks::Now(), INT32_MIN,
+ NETWORK_QUALITY_OBSERVATION_SOURCE_HTTP_CACHED_ESTIMATE);
+ downstream_throughput_kbps_observations_.AddObservation(
+ throughput_observation);
+ NotifyObserversOfThroughput(throughput_observation);
+ }
+
+ ComputeEffectiveConnectionType();
}
} // namespace net
diff --git a/chromium/net/nqe/network_quality_estimator.h b/chromium/net/nqe/network_quality_estimator.h
index 6b104e68b0b..115d9783f27 100644
--- a/chromium/net/nqe/network_quality_estimator.h
+++ b/chromium/net/nqe/network_quality_estimator.h
@@ -278,6 +278,11 @@ class NET_EXPORT NetworkQualityEstimator
// network quality estimation.
void SetUseSmallResponsesForTesting(bool use_small_responses);
+ // If |disable_offline_check| is set to true, then the device offline check is
+ // disabled when computing the effective connection type or when writing the
+ // prefs.
+ void DisableOfflineCheckForTesting(bool disable_offline_check);
+
// Reports |effective_connection_type| to all
// EffectiveConnectionTypeObservers.
void ReportEffectiveConnectionTypeForTesting(
@@ -298,6 +303,15 @@ class NET_EXPORT NetworkQualityEstimator
nqe::internal::CachedNetworkQuality> read_prefs);
protected:
+ // A protected constructor for testing that allows setting the value of
+ // |add_default_platform_observations_|.
+ NetworkQualityEstimator(
+ std::unique_ptr<ExternalEstimateProvider> external_estimates_provider,
+ const std::map<std::string, std::string>& variation_params,
+ bool use_local_host_requests_for_tests,
+ bool use_smaller_responses_for_tests,
+ bool add_default_platform_observations);
+
// NetworkChangeNotifier::ConnectionTypeObserver implementation:
void OnConnectionTypeChanged(
NetworkChangeNotifier::ConnectionType type) override;
@@ -363,7 +377,8 @@ class NET_EXPORT NetworkQualityEstimator
AdaptiveRecomputationEffectiveConnectionType);
FRIEND_TEST_ALL_PREFIXES(NetworkQualityEstimatorTest, StoreObservations);
FRIEND_TEST_ALL_PREFIXES(NetworkQualityEstimatorTest, TestAddObservation);
- FRIEND_TEST_ALL_PREFIXES(NetworkQualityEstimatorTest, ObtainOperatingParams);
+ FRIEND_TEST_ALL_PREFIXES(NetworkQualityEstimatorTest,
+ DefaultObservationsOverridden);
FRIEND_TEST_ALL_PREFIXES(NetworkQualityEstimatorTest,
ObtainAlgorithmToUseFromParams);
FRIEND_TEST_ALL_PREFIXES(NetworkQualityEstimatorTest, HalfLifeParam);
@@ -373,6 +388,10 @@ class NET_EXPORT NetworkQualityEstimator
TestExternalEstimateProviderMergeEstimates);
FRIEND_TEST_ALL_PREFIXES(NetworkQualityEstimatorTest,
UnknownEffectiveConnectionType);
+ FRIEND_TEST_ALL_PREFIXES(NetworkQualityEstimatorTest,
+ TypicalNetworkQualities);
+ FRIEND_TEST_ALL_PREFIXES(NetworkQualityEstimatorTest,
+ OnPrefsReadWithReadingDisabled);
// Value of round trip time observations is in base::TimeDelta.
typedef nqe::internal::Observation<base::TimeDelta> RttObservation;
@@ -477,8 +496,12 @@ class NET_EXPORT NetworkQualityEstimator
// Virtualized for testing.
virtual nqe::internal::NetworkID GetCurrentNetworkID() const;
+ // Notifies RTT observers of |observation|. May also trigger recomputation
+ // of effective connection type.
void NotifyObserversOfRTT(const RttObservation& observation);
+ // Notifies throughput observers of |observation|. May also trigger
+ // recomputation of effective connection type.
void NotifyObserversOfThroughput(const ThroughputObservation& observation);
// Returns true only if the |request| can be used for RTT estimation.
@@ -567,6 +590,13 @@ class NET_EXPORT NetworkQualityEstimator
// if there is a change in its value.
void ComputeEffectiveConnectionType();
+ // May update the network quality of the current network if |network_id|
+ // matches the ID of the current network. |cached_network_quality| is the
+ // cached network quality of the network with id |network_id|.
+ void MaybeUpdateNetworkQualityFromCache(
+ const nqe::internal::NetworkID& network_id,
+ const nqe::internal::CachedNetworkQuality& cached_network_quality);
+
// Determines if the requests to local host can be used in estimating the
// network quality. Set to true only for tests.
bool use_localhost_requests_;
@@ -576,9 +606,21 @@ class NET_EXPORT NetworkQualityEstimator
// network quality. Set to true only for tests.
bool use_small_responses_;
+ // When set to true, the device offline check is disabled when computing the
+ // effective connection type or when writing the prefs.
+ bool disable_offline_check_;
+
+ // If true, default values provided by the platform are used for estimation.
+ const bool add_default_platform_observations_;
+
// The factor by which the weight of an observation reduces every second.
const double weight_multiplier_per_second_;
+ // The factor by which the weight of an observation reduces for every dBm
+ // difference between the current signal strength (in dBm), and the signal
+ // strength at the time when the observation was taken.
+ const double weight_multiplier_per_dbm_;
+
// Algorithm to use for computing effective connection type. The value is
// obtained from field trial parameters. If the value from field trial
// parameters is unavailable, it is set to
@@ -617,7 +659,7 @@ class NET_EXPORT NetworkQualityEstimator
// estimator field trial parameters. The observations are indexed by
// ConnectionType.
nqe::internal::NetworkQuality
- default_observations_[NetworkChangeNotifier::CONNECTION_LAST];
+ default_observations_[NetworkChangeNotifier::CONNECTION_LAST + 1];
// Thresholds for different effective connection types obtained from field
// trial variation params. These thresholds encode how different connection
@@ -626,11 +668,15 @@ class NET_EXPORT NetworkQualityEstimator
nqe::internal::NetworkQuality connection_thresholds_
[EffectiveConnectionType::EFFECTIVE_CONNECTION_TYPE_LAST];
- // Latest time when the headers for a main frame request were received.
+ // Typical network quality for different effective connection types.
+ nqe::internal::NetworkQuality typical_network_quality_
+ [EffectiveConnectionType::EFFECTIVE_CONNECTION_TYPE_LAST];
+
+ // Time when the transaction for the last main frame request was started.
base::TimeTicks last_main_frame_request_;
- // Estimated network quality when the response headers for the last mainframe
- // request were received.
+ // Estimated network quality when the transaction for the last main frame
+ // request was started.
nqe::internal::NetworkQuality estimated_quality_at_last_main_frame_;
EffectiveConnectionType effective_connection_type_at_last_main_frame_;
@@ -683,7 +729,12 @@ class NET_EXPORT NetworkQualityEstimator
// |effective_connection_type_recomputation_interval_| ago).
EffectiveConnectionType effective_connection_type_;
- // Minimum and Maximum signal strength (in dbM) observed since last connection
+ // Last known value of the wireless signal strength. Set to INT32_MIN if
+ // unavailable. |signal_strength_dbm_| is reset to INT32_MIN on connection
+ // change events.
+ int32_t signal_strength_dbm_;
+
+ // Minimum and maximum signal strength (in dBm) observed since last connection
// change. Updated on connection change and main frame requests.
int32_t min_signal_strength_since_connection_change_;
int32_t max_signal_strength_since_connection_change_;
@@ -704,6 +755,9 @@ class NET_EXPORT NetworkQualityEstimator
const bool forced_effective_connection_type_set_;
const EffectiveConnectionType forced_effective_connection_type_;
+ // Set to true if reading of the network quality prefs is enabled.
+ const bool persistent_cache_reading_enabled_;
+
base::ThreadChecker thread_checker_;
base::WeakPtrFactory<NetworkQualityEstimator> weak_ptr_factory_;
diff --git a/chromium/net/nqe/network_quality_estimator_params.cc b/chromium/net/nqe/network_quality_estimator_params.cc
index bf73109c755..63ace6323fd 100644
--- a/chromium/net/nqe/network_quality_estimator_params.cc
+++ b/chromium/net/nqe/network_quality_estimator_params.cc
@@ -97,6 +97,14 @@ double GetWeightMultiplierPerSecond(
return pow(0.5, 1.0 / half_life_seconds);
}
+double GetWeightMultiplierPerDbm(
+ const std::map<std::string, std::string>& variation_params) {
+ // The default weight is set to 1.0, so by default, RSSI has no effect on the
+ // observation's weight.
+ return GetDoubleValueForVariationParamWithDefaultValue(
+ variation_params, "rssi_weight_per_dbm", 1.0);
+}
+
const char* GetNameForConnectionType(
net::NetworkChangeNotifier::ConnectionType connection_type) {
switch (connection_type) {
@@ -127,26 +135,79 @@ void ObtainDefaultObservations(
const std::map<std::string, std::string>& variation_params,
NetworkQuality default_observations[]) {
for (size_t i = 0; i < NetworkChangeNotifier::CONNECTION_LAST; ++i) {
- NetworkChangeNotifier::ConnectionType type =
- static_cast<NetworkChangeNotifier::ConnectionType>(i);
DCHECK_EQ(InvalidRTT(), default_observations[i].http_rtt());
DCHECK_EQ(InvalidRTT(), default_observations[i].transport_rtt());
DCHECK_EQ(kInvalidThroughput,
default_observations[i].downstream_throughput_kbps());
+ }
+
+ // Default observations for HTTP RTT, transport RTT, and downstream throughput
+ // Kbps for the various connection types. These may be overridden by
+ // variations params. The default observation for a connection type
+ // corresponds to typical network quality for that connection type.
+ default_observations[NetworkChangeNotifier::CONNECTION_UNKNOWN] =
+ NetworkQuality(base::TimeDelta::FromMilliseconds(115),
+ base::TimeDelta::FromMilliseconds(55), 1961);
+
+ default_observations[NetworkChangeNotifier::CONNECTION_ETHERNET] =
+ NetworkQuality(base::TimeDelta::FromMilliseconds(90),
+ base::TimeDelta::FromMilliseconds(33), 1456);
+
+ default_observations[NetworkChangeNotifier::CONNECTION_WIFI] =
+ NetworkQuality(base::TimeDelta::FromMilliseconds(116),
+ base::TimeDelta::FromMilliseconds(66), 2658);
+
+ default_observations[NetworkChangeNotifier::CONNECTION_2G] =
+ NetworkQuality(base::TimeDelta::FromMilliseconds(1726),
+ base::TimeDelta::FromMilliseconds(1531), 74);
+
+ default_observations[NetworkChangeNotifier::CONNECTION_3G] =
+ NetworkQuality(base::TimeDelta::FromMilliseconds(272),
+ base::TimeDelta::FromMilliseconds(209), 749);
+
+ default_observations[NetworkChangeNotifier::CONNECTION_4G] =
+ NetworkQuality(base::TimeDelta::FromMilliseconds(137),
+ base::TimeDelta::FromMilliseconds(80), 1708);
+
+ default_observations[NetworkChangeNotifier::CONNECTION_NONE] =
+ NetworkQuality(base::TimeDelta::FromMilliseconds(163),
+ base::TimeDelta::FromMilliseconds(83), 575);
+
+ default_observations[NetworkChangeNotifier::CONNECTION_BLUETOOTH] =
+ NetworkQuality(base::TimeDelta::FromMilliseconds(385),
+ base::TimeDelta::FromMilliseconds(318), 476);
+
+ // Override using the values provided via variation params.
+ for (size_t i = 0; i <= NetworkChangeNotifier::CONNECTION_LAST; ++i) {
+ NetworkChangeNotifier::ConnectionType type =
+ static_cast<NetworkChangeNotifier::ConnectionType>(i);
- base::TimeDelta default_rtt = InvalidRTT();
int32_t variations_value = kMinimumRTTVariationParameterMsec - 1;
std::string parameter_name = std::string(GetNameForConnectionType(type))
.append(".DefaultMedianRTTMsec");
auto it = variation_params.find(parameter_name);
+ if (it != variation_params.end() &&
+ base::StringToInt(it->second, &variations_value) &&
+ variations_value >= kMinimumRTTVariationParameterMsec) {
+ default_observations[i] =
+ NetworkQuality(base::TimeDelta::FromMilliseconds(variations_value),
+ default_observations[i].transport_rtt(),
+ default_observations[i].downstream_throughput_kbps());
+ }
+ variations_value = kMinimumRTTVariationParameterMsec - 1;
+ parameter_name = std::string(GetNameForConnectionType(type))
+ .append(".DefaultMedianTransportRTTMsec");
+ it = variation_params.find(parameter_name);
if (it != variation_params.end() &&
base::StringToInt(it->second, &variations_value) &&
variations_value >= kMinimumRTTVariationParameterMsec) {
- default_rtt = base::TimeDelta::FromMilliseconds(variations_value);
+ default_observations[i] =
+ NetworkQuality(default_observations[i].http_rtt(),
+ base::TimeDelta::FromMilliseconds(variations_value),
+ default_observations[i].downstream_throughput_kbps());
}
- int32_t downstream_throughput_kbps = kInvalidThroughput;
variations_value = kMinimumThroughputVariationParameterKbps - 1;
parameter_name = std::string(GetNameForConnectionType(type))
.append(".DefaultMedianKbps");
@@ -155,13 +216,50 @@ void ObtainDefaultObservations(
if (it != variation_params.end() &&
base::StringToInt(it->second, &variations_value) &&
variations_value >= kMinimumThroughputVariationParameterKbps) {
- downstream_throughput_kbps = variations_value;
+ default_observations[i] = NetworkQuality(
+ default_observations[i].http_rtt(),
+ default_observations[i].transport_rtt(), variations_value);
}
+ }
+}
- default_observations[i] =
- NetworkQuality(default_rtt, default_observations[i].transport_rtt(),
- downstream_throughput_kbps);
+void ObtainTypicalNetworkQuality(NetworkQuality typical_network_quality[]) {
+ for (size_t i = 0; i < EFFECTIVE_CONNECTION_TYPE_LAST; ++i) {
+ DCHECK_EQ(InvalidRTT(), typical_network_quality[i].http_rtt());
+ DCHECK_EQ(InvalidRTT(), typical_network_quality[i].transport_rtt());
+ DCHECK_EQ(kInvalidThroughput,
+ typical_network_quality[i].downstream_throughput_kbps());
}
+
+ typical_network_quality[EFFECTIVE_CONNECTION_TYPE_SLOW_2G] = NetworkQuality(
+ // Set to the 77.5th percentile of 2G RTT observations on Android. This
+ // corresponds to the median RTT observation when effective connection
+ // type is Slow 2G.
+ base::TimeDelta::FromMilliseconds(3600),
+ base::TimeDelta::FromMilliseconds(3000), 40);
+
+ typical_network_quality[EFFECTIVE_CONNECTION_TYPE_2G] = NetworkQuality(
+ // Set to the 58th percentile of 2G RTT observations on Android. This
+ // corresponds to the median RTT observation when effective connection
+ // type is 2G.
+ base::TimeDelta::FromMilliseconds(1800),
+ base::TimeDelta::FromMilliseconds(1500), 75);
+
+ typical_network_quality[EFFECTIVE_CONNECTION_TYPE_3G] = NetworkQuality(
+ // Set to the 75th percentile of 3G RTT observations on Android. This
+ // corresponds to the median RTT observation when effective connection
+ // type is 3G.
+ base::TimeDelta::FromMilliseconds(450),
+ base::TimeDelta::FromMilliseconds(400), 400);
+
+ // Set to the 25th percentile of 3G RTT observations on Android.
+ typical_network_quality[EFFECTIVE_CONNECTION_TYPE_4G] =
+ NetworkQuality(base::TimeDelta::FromMilliseconds(175),
+ base::TimeDelta::FromMilliseconds(125), 1600);
+
+ static_assert(
+ EFFECTIVE_CONNECTION_TYPE_4G + 1 == EFFECTIVE_CONNECTION_TYPE_LAST,
+ "Missing effective connection type");
}
void ObtainEffectiveConnectionTypeModelParams(
@@ -173,34 +271,31 @@ void ObtainEffectiveConnectionTypeModelParams(
default_effective_connection_type_thresholds
[EFFECTIVE_CONNECTION_TYPE_SLOW_2G] = NetworkQuality(
- // Set to 2010 milliseconds, which corresponds to the 33rd percentile
- // of 2G HTTP RTT observations on Android.
+ // Set to the 66th percentile of 2G RTT observations on Android.
base::TimeDelta::FromMilliseconds(2010),
- // Set to 1870 milliseconds, which corresponds to the 33rd percentile
- // of 2G transport RTT observations on Android.
base::TimeDelta::FromMilliseconds(1870), kInvalidThroughput);
default_effective_connection_type_thresholds[EFFECTIVE_CONNECTION_TYPE_2G] =
NetworkQuality(
- // Set to 1420 milliseconds, which corresponds to 50th percentile of
- // 2G
- // HTTP RTT observations on Android.
+ // Set to the 50th percentile of RTT observations on Android.
base::TimeDelta::FromMilliseconds(1420),
- // Set to 1280 milliseconds, which corresponds to 50th percentile of
- // 2G
- // transport RTT observations on Android.
base::TimeDelta::FromMilliseconds(1280), kInvalidThroughput);
default_effective_connection_type_thresholds[EFFECTIVE_CONNECTION_TYPE_3G] =
NetworkQuality(
- // Set to 273 milliseconds, which corresponds to 50th percentile of
- // 3G HTTP RTT observations on Android.
+ // Set to the 50th percentile of 3G RTT observations on Android.
base::TimeDelta::FromMilliseconds(273),
- // Set to 204 milliseconds, which corresponds to 50th percentile of
- // 3G transport RTT observations on Android.
base::TimeDelta::FromMilliseconds(204), kInvalidThroughput);
- for (size_t i = 0; i < EFFECTIVE_CONNECTION_TYPE_LAST; ++i) {
+ // Connection threshold should not be set for 4G effective connection type
+ // since it is the fastest.
+ static_assert(
+ EFFECTIVE_CONNECTION_TYPE_3G + 1 == EFFECTIVE_CONNECTION_TYPE_4G,
+ "Missing effective connection type");
+ static_assert(
+ EFFECTIVE_CONNECTION_TYPE_4G + 1 == EFFECTIVE_CONNECTION_TYPE_LAST,
+ "Missing effective connection type");
+ for (size_t i = 0; i <= EFFECTIVE_CONNECTION_TYPE_3G; ++i) {
EffectiveConnectionType effective_connection_type =
static_cast<EffectiveConnectionType>(i);
DCHECK_EQ(InvalidRTT(), connection_thresholds[i].http_rtt());
@@ -243,7 +338,7 @@ double correlation_uma_logging_probability(
const std::map<std::string, std::string>& variation_params) {
double correlation_uma_logging_probability =
GetDoubleValueForVariationParamWithDefaultValue(
- variation_params, "correlation_logging_probability", 0.0);
+ variation_params, "correlation_logging_probability", 0.01);
DCHECK_LE(0.0, correlation_uma_logging_probability);
DCHECK_GE(1.0, correlation_uma_logging_probability);
return correlation_uma_logging_probability;
@@ -274,8 +369,25 @@ EffectiveConnectionType forced_effective_connection_type(
return forced_effective_connection_type;
}
+bool persistent_cache_reading_enabled(
+ const std::map<std::string, std::string>& variation_params) {
+ if (GetStringValueForVariationParamWithDefaultValue(
+ variation_params, "persistent_cache_reading_enabled", "false") !=
+ "true") {
+ return false;
+ }
+ return true;
+}
+
+base::TimeDelta GetMinSocketWatcherNotificationInterval(
+ const std::map<std::string, std::string>& variation_params) {
+ // Use 1000 milliseconds as the default value.
+ return base::TimeDelta::FromMilliseconds(GetValueForVariationParam(
+ variation_params, "min_socket_watcher_notification_interval_msec", 1000));
+}
+
} // namespace internal
} // namespace nqe
-} // namespace net \ No newline at end of file
+} // namespace net
diff --git a/chromium/net/nqe/network_quality_estimator_params.h b/chromium/net/nqe/network_quality_estimator_params.h
index 62a8e7912ce..6d7310f95ea 100644
--- a/chromium/net/nqe/network_quality_estimator_params.h
+++ b/chromium/net/nqe/network_quality_estimator_params.h
@@ -31,6 +31,12 @@ std::string GetEffectiveConnectionTypeAlgorithm(
double GetWeightMultiplierPerSecond(
const std::map<std::string, std::string>& variation_params);
+// Returns the factor by which the weight of an observation reduces for every
+// dBm difference between the current signal strength (in dBm), and the signal
+// strength at the time when the observation was taken.
+double GetWeightMultiplierPerDbm(
+ const std::map<std::string, std::string>& variation_params);
+
// Returns a descriptive name corresponding to |connection_type|.
const char* GetNameForConnectionType(
net::NetworkChangeNotifier::ConnectionType connection_type);
@@ -43,6 +49,10 @@ void ObtainDefaultObservations(
const std::map<std::string, std::string>& variation_params,
nqe::internal::NetworkQuality default_observations[]);
+// Sets |typical_network_quality| to typical network quality for different
+// effective connection types.
+void ObtainTypicalNetworkQuality(NetworkQuality typical_network_quality[]);
+
// Parses the variation paramaters and sets the thresholds for different
// effective connection types in |connection_thresholds|.
void ObtainEffectiveConnectionTypeModelParams(
@@ -63,10 +73,20 @@ bool forced_effective_connection_type_set(
EffectiveConnectionType forced_effective_connection_type(
const std::map<std::string, std::string>& variation_params);
+// Returns true if reading from the persistent cache has been enabled via field
+// trial.
+bool persistent_cache_reading_enabled(
+ const std::map<std::string, std::string>& variation_params);
+
+// Returns the the minimum interval betweeen consecutive notifications to a
+// single socket watcher.
+base::TimeDelta GetMinSocketWatcherNotificationInterval(
+ const std::map<std::string, std::string>& variation_params);
+
} // namespace internal
} // namespace nqe
} // namespace net
-#endif // NET_NQE_NETWORK_QUALITY_ESTIMATOR_PARAMS_H_ \ No newline at end of file
+#endif // NET_NQE_NETWORK_QUALITY_ESTIMATOR_PARAMS_H_
diff --git a/chromium/net/nqe/network_quality_estimator_test_util.cc b/chromium/net/nqe/network_quality_estimator_test_util.cc
index 382a8a3c056..d93e286180e 100644
--- a/chromium/net/nqe/network_quality_estimator_test_util.cc
+++ b/chromium/net/nqe/network_quality_estimator_test_util.cc
@@ -20,23 +20,35 @@ const base::FilePath::CharType kTestFilePath[] =
namespace net {
+TestNetworkQualityEstimator::TestNetworkQualityEstimator()
+ : TestNetworkQualityEstimator(std::map<std::string, std::string>()) {}
+
+TestNetworkQualityEstimator::TestNetworkQualityEstimator(
+ const std::map<std::string, std::string>& variation_params)
+ : TestNetworkQualityEstimator(variation_params,
+ std::unique_ptr<ExternalEstimateProvider>()) {
+}
+
TestNetworkQualityEstimator::TestNetworkQualityEstimator(
const std::map<std::string, std::string>& variation_params,
std::unique_ptr<net::ExternalEstimateProvider> external_estimate_provider)
: TestNetworkQualityEstimator(std::move(external_estimate_provider),
variation_params,
true,
- true) {}
+ true,
+ false) {}
TestNetworkQualityEstimator::TestNetworkQualityEstimator(
std::unique_ptr<net::ExternalEstimateProvider> external_estimate_provider,
const std::map<std::string, std::string>& variation_params,
bool allow_local_host_requests_for_tests,
- bool allow_smaller_responses_for_tests)
+ bool allow_smaller_responses_for_tests,
+ bool add_default_platform_observations)
: NetworkQualityEstimator(std::move(external_estimate_provider),
variation_params,
allow_local_host_requests_for_tests,
- allow_smaller_responses_for_tests),
+ allow_smaller_responses_for_tests,
+ add_default_platform_observations),
current_network_type_(NetworkChangeNotifier::CONNECTION_UNKNOWN),
accuracy_recording_intervals_set_(false),
rand_double_(0.0),
@@ -45,12 +57,6 @@ TestNetworkQualityEstimator::TestNetworkQualityEstimator(
EXPECT_TRUE(embedded_test_server_.Start());
}
-TestNetworkQualityEstimator::TestNetworkQualityEstimator(
- const std::map<std::string, std::string>& variation_params)
- : TestNetworkQualityEstimator(variation_params,
- std::unique_ptr<ExternalEstimateProvider>()) {
-}
-
TestNetworkQualityEstimator::~TestNetworkQualityEstimator() {}
void TestNetworkQualityEstimator::RunOneRequest() {
diff --git a/chromium/net/nqe/network_quality_estimator_test_util.h b/chromium/net/nqe/network_quality_estimator_test_util.h
index b71b521e16f..6faa363b328 100644
--- a/chromium/net/nqe/network_quality_estimator_test_util.h
+++ b/chromium/net/nqe/network_quality_estimator_test_util.h
@@ -25,14 +25,14 @@ namespace net {
class ExternalEstimateProvider;
-namespace test_server {
-struct HttpRequest;
-class HttpResponse;
-}
-
// Helps in setting the current network type and id.
class TestNetworkQualityEstimator : public NetworkQualityEstimator {
public:
+ TestNetworkQualityEstimator();
+
+ explicit TestNetworkQualityEstimator(
+ const std::map<std::string, std::string>& variation_params);
+
TestNetworkQualityEstimator(
const std::map<std::string, std::string>& variation_params,
std::unique_ptr<net::ExternalEstimateProvider>
@@ -42,10 +42,8 @@ class TestNetworkQualityEstimator : public NetworkQualityEstimator {
std::unique_ptr<net::ExternalEstimateProvider> external_estimate_provider,
const std::map<std::string, std::string>& variation_params,
bool allow_local_host_requests_for_tests,
- bool allow_smaller_responses_for_tests);
-
- explicit TestNetworkQualityEstimator(
- const std::map<std::string, std::string>& variation_params);
+ bool allow_smaller_responses_for_tests,
+ bool add_default_platform_observations);
~TestNetworkQualityEstimator() override;
@@ -230,4 +228,4 @@ class TestNetworkQualityEstimator : public NetworkQualityEstimator {
} // namespace net
-#endif // NET_NQE_NETWORK_QUALITY_ESTIMATOR_TEST_UTIL_H_ \ No newline at end of file
+#endif // NET_NQE_NETWORK_QUALITY_ESTIMATOR_TEST_UTIL_H_
diff --git a/chromium/net/nqe/network_quality_estimator_unittest.cc b/chromium/net/nqe/network_quality_estimator_unittest.cc
index f36de1811f1..24653bfd350 100644
--- a/chromium/net/nqe/network_quality_estimator_unittest.cc
+++ b/chromium/net/nqe/network_quality_estimator_unittest.cc
@@ -118,6 +118,17 @@ class TestRTTObserver : public NetworkQualityEstimator::RTTObserver {
observations_.push_back(Observation(rtt_ms, timestamp, source));
}
+ // Returns the last received RTT observation that has source set to |source|.
+ base::TimeDelta last_rtt(NetworkQualityObservationSource source) {
+ for (std::vector<Observation>::reverse_iterator i = observations_.rbegin();
+ i != observations_.rend(); ++i) {
+ Observation observation = *i;
+ if (observation.source == source)
+ return base::TimeDelta::FromMilliseconds(observation.rtt_ms);
+ }
+ return nqe::internal::InvalidRTT();
+ }
+
private:
std::vector<Observation> observations_;
};
@@ -155,6 +166,7 @@ TEST(NetworkQualityEstimatorTest, TestKbpsRTTUpdates) {
base::HistogramTester histogram_tester;
// Enable requests to local host to be used for network quality estimation.
std::map<std::string, std::string> variation_params;
+ variation_params["persistent_cache_reading_enabled"] = "true";
TestNetworkQualityEstimator estimator(variation_params);
estimator.SimulateNetworkChange(
@@ -293,6 +305,7 @@ TEST(NetworkQualityEstimatorTest, TestKbpsRTTUpdates) {
TEST(NetworkQualityEstimatorTest, Caching) {
base::HistogramTester histogram_tester;
std::map<std::string, std::string> variation_params;
+ variation_params["persistent_cache_reading_enabled"] = "true";
TestNetworkQualityEstimator estimator(variation_params);
estimator.SimulateNetworkChange(
@@ -343,6 +356,10 @@ TEST(NetworkQualityEstimatorTest, Caching) {
TestThroughputObserver throughput_observer;
estimator.AddThroughputObserver(&throughput_observer);
+ // |observer| should be notified as soon as it is added.
+ base::RunLoop().RunUntilIdle();
+ EXPECT_EQ(1U, observer.effective_connection_types().size());
+
estimator.SimulateNetworkChange(
NetworkChangeNotifier::ConnectionType::CONNECTION_2G, "test");
histogram_tester.ExpectBucketCount("NQE.CachedNetworkQualityAvailable", true,
@@ -353,15 +370,81 @@ TEST(NetworkQualityEstimatorTest, Caching) {
// Verify that the cached network quality was read, and observers were
// notified. |observer| must be notified once right after it was added, and
// once again after the cached network quality was read.
- EXPECT_EQ(2U, observer.effective_connection_types().size());
+ EXPECT_LE(2U, observer.effective_connection_types().size());
+ EXPECT_EQ(estimator.GetEffectiveConnectionType(),
+ observer.effective_connection_types().back());
EXPECT_EQ(1U, rtt_observer.observations().size());
EXPECT_EQ(1U, throughput_observer.observations().size());
}
-TEST(NetworkQualityEstimatorTest, StoreObservations) {
+// Tests that the network quality estimator does not read the network quality
+// from the cache store when caching is not enabled.
+TEST(NetworkQualityEstimatorTest, CachingDisabled) {
+ base::HistogramTester histogram_tester;
std::map<std::string, std::string> variation_params;
+ // Do not set |persistent_cache_reading_enabled| variation param.
TestNetworkQualityEstimator estimator(variation_params);
+ estimator.SimulateNetworkChange(
+ NetworkChangeNotifier::ConnectionType::CONNECTION_2G, "test");
+ histogram_tester.ExpectTotalCount("NQE.CachedNetworkQualityAvailable", 0);
+
+ base::TimeDelta rtt;
+ int32_t kbps;
+ EXPECT_FALSE(estimator.GetRecentHttpRTT(base::TimeTicks(), &rtt));
+ EXPECT_FALSE(
+ estimator.GetRecentDownlinkThroughputKbps(base::TimeTicks(), &kbps));
+
+ TestDelegate test_delegate;
+ TestURLRequestContext context(true);
+ context.set_network_quality_estimator(&estimator);
+ context.Init();
+
+ // Start two requests so that the network quality is added to cache store at
+ // the beginning of the second request from the network traffic observed from
+ // the first request.
+ for (size_t i = 0; i < 2; ++i) {
+ std::unique_ptr<URLRequest> request(context.CreateRequest(
+ estimator.GetEchoURL(), DEFAULT_PRIORITY, &test_delegate));
+ request->SetLoadFlags(request->load_flags() | LOAD_MAIN_FRAME_DEPRECATED);
+ request->Start();
+ base::RunLoop().Run();
+ }
+
+ base::RunLoop().RunUntilIdle();
+
+ // Both RTT and downstream throughput should be updated.
+ EXPECT_TRUE(estimator.GetRecentHttpRTT(base::TimeTicks(), &rtt));
+ EXPECT_TRUE(
+ estimator.GetRecentDownlinkThroughputKbps(base::TimeTicks(), &kbps));
+ EXPECT_NE(EFFECTIVE_CONNECTION_TYPE_UNKNOWN,
+ estimator.GetEffectiveConnectionType());
+ EXPECT_FALSE(estimator.GetRecentTransportRTT(base::TimeTicks(), &rtt));
+
+ histogram_tester.ExpectTotalCount("NQE.CachedNetworkQualityAvailable", 0);
+
+ // Add the observers before changing the network type.
+ TestRTTObserver rtt_observer;
+ estimator.AddRTTObserver(&rtt_observer);
+ TestThroughputObserver throughput_observer;
+ estimator.AddThroughputObserver(&throughput_observer);
+
+ estimator.SimulateNetworkChange(
+ NetworkChangeNotifier::ConnectionType::CONNECTION_2G, "test");
+
+ histogram_tester.ExpectTotalCount("NQE.CachedNetworkQualityAvailable", 0);
+ base::RunLoop().RunUntilIdle();
+
+ // Verify that the cached network quality was read, and observers were
+ // notified. |observer| must be notified once right after it was added, and
+ // once again after the cached network quality was read.
+ EXPECT_EQ(0U, rtt_observer.observations().size());
+ EXPECT_EQ(0U, throughput_observer.observations().size());
+}
+
+TEST(NetworkQualityEstimatorTest, StoreObservations) {
+ TestNetworkQualityEstimator estimator;
+
base::TimeDelta rtt;
int32_t kbps;
EXPECT_FALSE(estimator.GetRecentHttpRTT(base::TimeTicks(), &rtt));
@@ -397,8 +480,7 @@ TEST(NetworkQualityEstimatorTest, StoreObservations) {
// throughput and RTT percentiles are checked for correctness by doing simple
// verifications.
TEST(NetworkQualityEstimatorTest, ComputedPercentiles) {
- std::map<std::string, std::string> variation_params;
- TestNetworkQualityEstimator estimator(variation_params);
+ TestNetworkQualityEstimator estimator;
std::vector<NetworkQualityObservationSource> disallowed_observation_sources;
disallowed_observation_sources.push_back(
@@ -451,7 +533,83 @@ TEST(NetworkQualityEstimatorTest, ComputedPercentiles) {
}
}
-TEST(NetworkQualityEstimatorTest, ObtainOperatingParams) {
+// Verifies that the observers receive the notifications when default estimates
+// are added to the observations.
+TEST(NetworkQualityEstimatorTest, DefaultObservations) {
+ TestEffectiveConnectionTypeObserver effective_connection_type_observer;
+ TestRTTAndThroughputEstimatesObserver rtt_throughput_estimates_observer;
+ TestRTTObserver rtt_observer;
+ TestThroughputObserver throughput_observer;
+ std::map<std::string, std::string> variation_params;
+ TestNetworkQualityEstimator estimator(
+ nullptr, variation_params, false, false,
+ true /* add_default_platform_observations */);
+ base::TimeDelta rtt;
+ int32_t kbps;
+
+ // Default estimates should be available.
+ EXPECT_TRUE(estimator.GetRecentHttpRTT(base::TimeTicks(), &rtt));
+ EXPECT_EQ(base::TimeDelta::FromMilliseconds(115), rtt);
+ EXPECT_TRUE(estimator.GetRecentTransportRTT(base::TimeTicks(), &rtt));
+ EXPECT_EQ(base::TimeDelta::FromMilliseconds(55), rtt);
+ EXPECT_TRUE(
+ estimator.GetRecentDownlinkThroughputKbps(base::TimeTicks(), &kbps));
+ EXPECT_EQ(1961, kbps);
+
+ estimator.AddEffectiveConnectionTypeObserver(
+ &effective_connection_type_observer);
+ estimator.AddRTTAndThroughputEstimatesObserver(
+ &rtt_throughput_estimates_observer);
+ estimator.AddRTTObserver(&rtt_observer);
+ estimator.AddThroughputObserver(&throughput_observer);
+
+ // Simulate network change to 3G. Default estimates should be available.
+ estimator.SimulateNetworkChange(
+ NetworkChangeNotifier::ConnectionType::CONNECTION_3G, "test-3");
+ EXPECT_TRUE(estimator.GetRecentHttpRTT(base::TimeTicks(), &rtt));
+ // Taken from network_quality_estimator_params.cc.
+ EXPECT_EQ(base::TimeDelta::FromMilliseconds(272), rtt);
+ EXPECT_TRUE(estimator.GetRecentTransportRTT(base::TimeTicks(), &rtt));
+ EXPECT_EQ(base::TimeDelta::FromMilliseconds(209), rtt);
+ EXPECT_TRUE(
+ estimator.GetRecentDownlinkThroughputKbps(base::TimeTicks(), &kbps));
+ EXPECT_EQ(749, kbps);
+
+ EXPECT_NE(EFFECTIVE_CONNECTION_TYPE_UNKNOWN,
+ estimator.GetEffectiveConnectionType());
+ EXPECT_EQ(
+ 1U,
+ effective_connection_type_observer.effective_connection_types().size());
+ EXPECT_NE(
+ EFFECTIVE_CONNECTION_TYPE_UNKNOWN,
+ effective_connection_type_observer.effective_connection_types().front());
+
+ EXPECT_EQ(3, rtt_throughput_estimates_observer.notifications_received());
+ EXPECT_EQ(base::TimeDelta::FromMilliseconds(272),
+ rtt_throughput_estimates_observer.http_rtt());
+ EXPECT_EQ(base::TimeDelta::FromMilliseconds(209),
+ rtt_throughput_estimates_observer.transport_rtt());
+ EXPECT_EQ(749,
+ rtt_throughput_estimates_observer.downstream_throughput_kbps());
+
+ EXPECT_EQ(2U, rtt_observer.observations().size());
+ EXPECT_EQ(272, rtt_observer.observations().at(0).rtt_ms);
+ EXPECT_EQ(NETWORK_QUALITY_OBSERVATION_SOURCE_DEFAULT_HTTP_FROM_PLATFORM,
+ rtt_observer.observations().at(0).source);
+ EXPECT_EQ(209, rtt_observer.observations().at(1).rtt_ms);
+ EXPECT_EQ(NETWORK_QUALITY_OBSERVATION_SOURCE_DEFAULT_TRANSPORT_FROM_PLATFORM,
+ rtt_observer.observations().at(1).source);
+
+ EXPECT_EQ(1U, throughput_observer.observations().size());
+ EXPECT_EQ(749, throughput_observer.observations().at(0).throughput_kbps);
+ EXPECT_EQ(NETWORK_QUALITY_OBSERVATION_SOURCE_DEFAULT_HTTP_FROM_PLATFORM,
+ throughput_observer.observations().at(0).source);
+}
+
+// Verifies that the default observations are added to the set of observations.
+// If default observations are overridden using field trial parameters, verify
+// that the overriding values are used.
+TEST(NetworkQualityEstimatorTest, DefaultObservationsOverridden) {
std::map<std::string, std::string> variation_params;
variation_params["Unknown.DefaultMedianKbps"] = "100";
variation_params["WiFi.DefaultMedianKbps"] = "200";
@@ -462,29 +620,36 @@ TEST(NetworkQualityEstimatorTest, ObtainOperatingParams) {
// Negative variation value should not be used.
variation_params["2G.DefaultMedianRTTMsec"] = "-5";
- TestNetworkQualityEstimator estimator(variation_params);
+ variation_params["Unknown.DefaultMedianTransportRTTMsec"] = "500";
+ variation_params["WiFi.DefaultMedianTransportRTTMsec"] = "1000";
+ // Negative variation value should not be used.
+ variation_params["2G.DefaultMedianTransportRTTMsec"] = "-5";
+
+ TestNetworkQualityEstimator estimator(
+ nullptr, variation_params, false, false,
+ true /* add_default_platform_observations */);
base::TimeDelta rtt;
- EXPECT_TRUE(estimator.GetRecentHttpRTT(base::TimeTicks(), &rtt));
int32_t kbps;
+
+ EXPECT_TRUE(estimator.GetRecentHttpRTT(base::TimeTicks(), &rtt));
+ EXPECT_EQ(base::TimeDelta::FromMilliseconds(1000), rtt);
+ EXPECT_TRUE(estimator.GetRecentTransportRTT(base::TimeTicks(), &rtt));
+ EXPECT_EQ(base::TimeDelta::FromMilliseconds(500), rtt);
EXPECT_TRUE(
estimator.GetRecentDownlinkThroughputKbps(base::TimeTicks(), &kbps));
-
EXPECT_EQ(100, kbps);
- EXPECT_EQ(base::TimeDelta::FromMilliseconds(1000), rtt);
-
- EXPECT_FALSE(estimator.GetRecentTransportRTT(base::TimeTicks(), &rtt));
// Simulate network change to Wi-Fi.
estimator.SimulateNetworkChange(
NetworkChangeNotifier::ConnectionType::CONNECTION_WIFI, "test-1");
-
EXPECT_TRUE(estimator.GetRecentHttpRTT(base::TimeTicks(), &rtt));
+ EXPECT_EQ(base::TimeDelta::FromMilliseconds(2000), rtt);
+ EXPECT_TRUE(estimator.GetRecentTransportRTT(base::TimeTicks(), &rtt));
+ EXPECT_EQ(base::TimeDelta::FromMilliseconds(1000), rtt);
EXPECT_TRUE(
estimator.GetRecentDownlinkThroughputKbps(base::TimeTicks(), &kbps));
EXPECT_EQ(200, kbps);
- EXPECT_EQ(base::TimeDelta::FromMilliseconds(2000), rtt);
- EXPECT_FALSE(estimator.GetRecentTransportRTT(base::TimeTicks(), &rtt));
// Peak network quality should not be affected by the network quality
// estimator field trial.
@@ -497,19 +662,25 @@ TEST(NetworkQualityEstimatorTest, ObtainOperatingParams) {
// available.
estimator.SimulateNetworkChange(
NetworkChangeNotifier::ConnectionType::CONNECTION_2G, "test-2");
-
- EXPECT_FALSE(estimator.GetRecentHttpRTT(base::TimeTicks(), &rtt));
+ EXPECT_TRUE(estimator.GetRecentHttpRTT(base::TimeTicks(), &rtt));
+ // Taken from network_quality_estimator_params.cc.
+ EXPECT_EQ(base::TimeDelta::FromMilliseconds(1726), rtt);
+ EXPECT_TRUE(estimator.GetRecentTransportRTT(base::TimeTicks(), &rtt));
+ EXPECT_EQ(base::TimeDelta::FromMilliseconds(1531), rtt);
EXPECT_TRUE(
estimator.GetRecentDownlinkThroughputKbps(base::TimeTicks(), &kbps));
EXPECT_EQ(300, kbps);
- // Simulate network change to 3G. Default estimates should be unavailable.
+ // Simulate network change to 3G. Default estimates should be available.
estimator.SimulateNetworkChange(
NetworkChangeNotifier::ConnectionType::CONNECTION_3G, "test-3");
-
- EXPECT_FALSE(estimator.GetRecentHttpRTT(base::TimeTicks(), &rtt));
- EXPECT_FALSE(
+ EXPECT_TRUE(estimator.GetRecentHttpRTT(base::TimeTicks(), &rtt));
+ EXPECT_EQ(base::TimeDelta::FromMilliseconds(272), rtt);
+ EXPECT_TRUE(estimator.GetRecentTransportRTT(base::TimeTicks(), &rtt));
+ EXPECT_EQ(base::TimeDelta::FromMilliseconds(209), rtt);
+ EXPECT_TRUE(
estimator.GetRecentDownlinkThroughputKbps(base::TimeTicks(), &kbps));
+ EXPECT_EQ(749, kbps);
}
TEST(NetworkQualityEstimatorTest, ObtainAlgorithmToUseFromParams) {
@@ -563,8 +734,7 @@ TEST(NetworkQualityEstimatorTest, ObtainAlgorithmToUseFromParams) {
// Tests that |GetEffectiveConnectionType| returns
// EFFECTIVE_CONNECTION_TYPE_OFFLINE when the device is currently offline.
TEST(NetworkQualityEstimatorTest, Offline) {
- std::map<std::string, std::string> variation_params;
- TestNetworkQualityEstimator estimator(variation_params);
+ TestNetworkQualityEstimator estimator;
const struct {
NetworkChangeNotifier::ConnectionType connection_type;
@@ -592,7 +762,6 @@ TEST(NetworkQualityEstimatorTest, ObtainThresholdsOnlyRTT) {
variation_params["Slow2G.ThresholdMedianHttpRTTMsec"] = "2000";
variation_params["2G.ThresholdMedianHttpRTTMsec"] = "1000";
variation_params["3G.ThresholdMedianHttpRTTMsec"] = "500";
- variation_params["4G.ThresholdMedianHttpRTTMsec"] = "300";
TestNetworkQualityEstimator estimator(variation_params);
@@ -750,7 +919,14 @@ TEST(NetworkQualityEstimatorTest, DefaultHttpRTTBasedThresholds) {
// Tests that |GetEffectiveConnectionType| returns correct connection type when
// only transport RTT thresholds are specified in the variation params.
-TEST(NetworkQualityEstimatorTest, ObtainThresholdsOnlyTransportRTT) {
+#if defined(OS_IOS)
+// Flaky on iOS: crbug.com/672917.
+#define MAYBE_ObtainThresholdsOnlyTransportRTT \
+ DISABLED_ObtainThresholdsOnlyTransportRTT
+#else
+#define MAYBE_ObtainThresholdsOnlyTransportRTT ObtainThresholdsOnlyTransportRTT
+#endif
+TEST(NetworkQualityEstimatorTest, MAYBE_ObtainThresholdsOnlyTransportRTT) {
std::map<std::string, std::string> variation_params;
variation_params["effective_connection_type_algorithm"] =
"TransportRTTOrDownstreamThroughput";
@@ -759,7 +935,6 @@ TEST(NetworkQualityEstimatorTest, ObtainThresholdsOnlyTransportRTT) {
variation_params["Slow2G.ThresholdMedianTransportRTTMsec"] = "2000";
variation_params["2G.ThresholdMedianTransportRTTMsec"] = "1000";
variation_params["3G.ThresholdMedianTransportRTTMsec"] = "500";
- variation_params["4G.ThresholdMedianTransportRTTMsec"] = "300";
TestNetworkQualityEstimator estimator(variation_params);
@@ -811,13 +986,11 @@ TEST(NetworkQualityEstimatorTest, ObtainThresholdsHttpRTTandThroughput) {
variation_params["Slow2G.ThresholdMedianHttpRTTMsec"] = "2000";
variation_params["2G.ThresholdMedianHttpRTTMsec"] = "1000";
variation_params["3G.ThresholdMedianHttpRTTMsec"] = "500";
- variation_params["4G.ThresholdMedianHttpRTTMsec"] = "300";
variation_params["Offline.ThresholdMedianKbps"] = "10";
variation_params["Slow2G.ThresholdMedianKbps"] = "100";
variation_params["2G.ThresholdMedianKbps"] = "300";
variation_params["3G.ThresholdMedianKbps"] = "500";
- variation_params["4G.ThresholdMedianKbps"] = "1000";
TestNetworkQualityEstimator estimator(variation_params);
@@ -878,13 +1051,11 @@ TEST(NetworkQualityEstimatorTest, ObtainThresholdsTransportRTTandThroughput) {
variation_params["Slow2G.ThresholdMedianTransportRTTMsec"] = "2000";
variation_params["2G.ThresholdMedianTransportRTTMsec"] = "1000";
variation_params["3G.ThresholdMedianTransportRTTMsec"] = "500";
- variation_params["4G.ThresholdMedianTransportRTTMsec"] = "300";
variation_params["Offline.ThresholdMedianKbps"] = "10";
variation_params["Slow2G.ThresholdMedianKbps"] = "100";
variation_params["2G.ThresholdMedianKbps"] = "300";
variation_params["3G.ThresholdMedianKbps"] = "500";
- variation_params["4G.ThresholdMedianKbps"] = "1000";
TestNetworkQualityEstimator estimator(variation_params);
@@ -970,8 +1141,6 @@ TEST(NetworkQualityEstimatorTest, TestGetMetricsSince) {
variation_params["3G.ThresholdMedianHttpRTTMsec"] =
base::IntToString(rtt_threshold_3g.InMilliseconds());
- variation_params["4G.ThresholdMedianHttpRTTMsec"] =
- base::IntToString(rtt_threshold_4g.InMilliseconds());
variation_params["HalfLifeSeconds"] = "300000";
TestNetworkQualityEstimator estimator(variation_params);
@@ -993,13 +1162,16 @@ TEST(NetworkQualityEstimatorTest, TestGetMetricsSince) {
for (size_t i = 0; i < 2; ++i) {
estimator.downstream_throughput_kbps_observations_.AddObservation(
NetworkQualityEstimator::ThroughputObservation(
- old_downlink_kbps, old, NETWORK_QUALITY_OBSERVATION_SOURCE_HTTP));
+ old_downlink_kbps, old, INT32_MIN,
+ NETWORK_QUALITY_OBSERVATION_SOURCE_HTTP));
estimator.rtt_observations_.AddObservation(
NetworkQualityEstimator::RttObservation(
- old_url_rtt, old, NETWORK_QUALITY_OBSERVATION_SOURCE_HTTP));
+ old_url_rtt, old, INT32_MIN,
+ NETWORK_QUALITY_OBSERVATION_SOURCE_HTTP));
estimator.rtt_observations_.AddObservation(
NetworkQualityEstimator::RttObservation(
- old_tcp_rtt, old, NETWORK_QUALITY_OBSERVATION_SOURCE_TCP));
+ old_tcp_rtt, old, INT32_MIN,
+ NETWORK_QUALITY_OBSERVATION_SOURCE_TCP));
}
const int32_t new_downlink_kbps = 100;
@@ -1016,13 +1188,15 @@ TEST(NetworkQualityEstimatorTest, TestGetMetricsSince) {
estimator.downstream_throughput_kbps_observations_.AddObservation(
NetworkQualityEstimator::ThroughputObservation(
- new_downlink_kbps, now, NETWORK_QUALITY_OBSERVATION_SOURCE_HTTP));
+ new_downlink_kbps, now, INT32_MIN,
+ NETWORK_QUALITY_OBSERVATION_SOURCE_HTTP));
estimator.rtt_observations_.AddObservation(
NetworkQualityEstimator::RttObservation(
- new_url_rtt, now, NETWORK_QUALITY_OBSERVATION_SOURCE_HTTP));
+ new_url_rtt, now, INT32_MIN,
+ NETWORK_QUALITY_OBSERVATION_SOURCE_HTTP));
estimator.rtt_observations_.AddObservation(
NetworkQualityEstimator::RttObservation(
- new_tcp_rtt, now, NETWORK_QUALITY_OBSERVATION_SOURCE_TCP));
+ new_tcp_rtt, now, INT32_MIN, NETWORK_QUALITY_OBSERVATION_SOURCE_TCP));
const struct {
base::TimeTicks start_timestamp;
@@ -1222,8 +1396,7 @@ TEST(NetworkQualityEstimatorTest, TestExternalEstimateProvider) {
external_estimate_provider_downstream_throughput);
std::unique_ptr<ExternalEstimateProvider> external_estimate_provider(
test_external_estimate_provider);
- std::map<std::string, std::string> variation_params;
- TestNetworkQualityEstimator estimator(variation_params,
+ TestNetworkQualityEstimator estimator(std::map<std::string, std::string>(),
std::move(external_estimate_provider));
estimator.SimulateNetworkChange(net::NetworkChangeNotifier::CONNECTION_WIFI,
"test");
@@ -1347,7 +1520,7 @@ TEST(NetworkQualityEstimatorTest, TestThroughputNoRequestOverlap) {
TestNetworkQualityEstimator estimator(
std::unique_ptr<net::ExternalEstimateProvider>(), variation_params,
test.allow_small_localhost_requests,
- test.allow_small_localhost_requests);
+ test.allow_small_localhost_requests, false);
base::TimeDelta rtt;
EXPECT_FALSE(estimator.GetRecentHttpRTT(base::TimeTicks(), &rtt));
@@ -1374,18 +1547,29 @@ TEST(NetworkQualityEstimatorTest, TestThroughputNoRequestOverlap) {
}
}
+#if defined(OS_IOS)
+// Flaky on iOS: crbug.com/672917.
+#define MAYBE_TestEffectiveConnectionTypeObserver \
+ DISABLED_TestEffectiveConnectionTypeObserver
+#else
+#define MAYBE_TestEffectiveConnectionTypeObserver \
+ TestEffectiveConnectionTypeObserver
+#endif
+
// Tests that the effective connection type is computed at the specified
// interval, and that the observers are notified of any change.
-TEST(NetworkQualityEstimatorTest, TestEffectiveConnectionTypeObserver) {
+TEST(NetworkQualityEstimatorTest, MAYBE_TestEffectiveConnectionTypeObserver) {
base::HistogramTester histogram_tester;
std::unique_ptr<base::SimpleTestTickClock> tick_clock(
new base::SimpleTestTickClock());
base::SimpleTestTickClock* tick_clock_ptr = tick_clock.get();
TestEffectiveConnectionTypeObserver observer;
- std::map<std::string, std::string> variation_params;
- TestNetworkQualityEstimator estimator(variation_params);
+ TestNetworkQualityEstimator estimator;
estimator.AddEffectiveConnectionTypeObserver(&observer);
+ // |observer| may be notified as soon as it is added. Run the loop to so that
+ // the notification to |observer| is finished.
+ base::RunLoop().RunUntilIdle();
estimator.SetTickClockForTesting(std::move(tick_clock));
TestDelegate test_delegate;
@@ -1462,8 +1646,7 @@ TEST(NetworkQualityEstimatorTest, TestRTTAndThroughputEstimatesObserver) {
base::SimpleTestTickClock* tick_clock_ptr = tick_clock.get();
TestRTTAndThroughputEstimatesObserver observer;
- std::map<std::string, std::string> variation_params;
- TestNetworkQualityEstimator estimator(variation_params);
+ TestNetworkQualityEstimator estimator;
estimator.AddRTTAndThroughputEstimatesObserver(&observer);
estimator.SetTickClockForTesting(std::move(tick_clock));
@@ -1561,8 +1744,7 @@ TEST(NetworkQualityEstimatorTest, UnknownEffectiveConnectionType) {
base::SimpleTestTickClock* tick_clock_ptr = tick_clock.get();
TestEffectiveConnectionTypeObserver observer;
- std::map<std::string, std::string> variation_params;
- TestNetworkQualityEstimator estimator(variation_params);
+ TestNetworkQualityEstimator estimator;
estimator.SetTickClockForTesting(std::move(tick_clock));
estimator.AddEffectiveConnectionTypeObserver(&observer);
tick_clock_ptr->Advance(base::TimeDelta::FromMinutes(60));
@@ -1577,7 +1759,7 @@ TEST(NetworkQualityEstimatorTest, UnknownEffectiveConnectionType) {
"test");
NetworkQualityEstimator::RttObservation rtt_observation(
- base::TimeDelta::FromSeconds(5), tick_clock_ptr->NowTicks(),
+ base::TimeDelta::FromSeconds(5), tick_clock_ptr->NowTicks(), INT32_MIN,
NETWORK_QUALITY_OBSERVATION_SOURCE_HTTP);
for (size_t i = 0; i < 10; ++i) {
@@ -1591,7 +1773,7 @@ TEST(NetworkQualityEstimatorTest, UnknownEffectiveConnectionType) {
// more RTT sample should trigger recomputation of the effective connection
// type since the last computed effective connection type was unknown.
estimator.NotifyObserversOfRTT(NetworkQualityEstimator::RttObservation(
- base::TimeDelta::FromSeconds(5), tick_clock_ptr->NowTicks(),
+ base::TimeDelta::FromSeconds(5), tick_clock_ptr->NowTicks(), INT32_MIN,
NETWORK_QUALITY_OBSERVATION_SOURCE_HTTP));
++expected_effective_connection_type_notifications;
EXPECT_EQ(expected_effective_connection_type_notifications,
@@ -1608,12 +1790,14 @@ TEST(NetworkQualityEstimatorTest,
base::SimpleTestTickClock* tick_clock_ptr = tick_clock.get();
TestEffectiveConnectionTypeObserver observer;
- std::map<std::string, std::string> variation_params;
- TestNetworkQualityEstimator estimator(variation_params);
+ TestNetworkQualityEstimator estimator;
estimator.SetTickClockForTesting(std::move(tick_clock));
estimator.SimulateNetworkChange(NetworkChangeNotifier::CONNECTION_WIFI,
"test");
estimator.AddEffectiveConnectionTypeObserver(&observer);
+ // |observer| may be notified as soon as it is added. Run the loop to so that
+ // the notification to |observer| is finished.
+ base::RunLoop().RunUntilIdle();
TestDelegate test_delegate;
TestURLRequestContext context(true);
@@ -1671,11 +1855,11 @@ TEST(NetworkQualityEstimatorTest,
estimator.rtt_observations_.AddObservation(
NetworkQualityEstimator::RttObservation(
base::TimeDelta::FromSeconds(5), tick_clock_ptr->NowTicks(),
- NETWORK_QUALITY_OBSERVATION_SOURCE_HTTP));
+ INT32_MIN, NETWORK_QUALITY_OBSERVATION_SOURCE_HTTP));
estimator.NotifyObserversOfRTT(NetworkQualityEstimator::RttObservation(
base::TimeDelta::FromSeconds(5), tick_clock_ptr->NowTicks(),
- NETWORK_QUALITY_OBSERVATION_SOURCE_HTTP));
+ INT32_MIN, NETWORK_QUALITY_OBSERVATION_SOURCE_HTTP));
if (i == rtt_observations_count) {
// Effective connection type must be recomputed since the number of RTT
@@ -1692,8 +1876,7 @@ TEST(NetworkQualityEstimatorTest,
TEST(NetworkQualityEstimatorTest, TestRttThroughputObservers) {
TestRTTObserver rtt_observer;
TestThroughputObserver throughput_observer;
- std::map<std::string, std::string> variation_params;
- TestNetworkQualityEstimator estimator(variation_params);
+ TestNetworkQualityEstimator estimator;
estimator.AddRTTObserver(&rtt_observer);
estimator.AddThroughputObserver(&throughput_observer);
@@ -1782,9 +1965,19 @@ TEST(NetworkQualityEstimatorTest, TestRttThroughputObservers) {
TEST(NetworkQualityEstimatorTest, MAYBE_TestTCPSocketRTT) {
base::HistogramTester histogram_tester;
TestRTTObserver rtt_observer;
+
std::map<std::string, std::string> variation_params;
- TestNetworkQualityEstimator estimator(variation_params);
+ variation_params["persistent_cache_reading_enabled"] = "true";
+ TestNetworkQualityEstimator estimator(
+ nullptr, variation_params, true, true,
+ true /* add_default_platform_observations */);
+ estimator.SimulateNetworkChange(
+ NetworkChangeNotifier::ConnectionType::CONNECTION_2G, "test");
+
estimator.AddRTTObserver(&rtt_observer);
+ // |observer| may be notified as soon as it is added. Run the loop to so that
+ // the notification to |observer| is finished.
+ base::RunLoop().RunUntilIdle();
TestDelegate test_delegate;
TestURLRequestContext context(true);
@@ -1800,8 +1993,8 @@ TEST(NetworkQualityEstimatorTest, MAYBE_TestTCPSocketRTT) {
EXPECT_EQ(0U, rtt_observer.observations().size());
base::TimeDelta rtt;
- EXPECT_FALSE(estimator.GetRecentHttpRTT(base::TimeTicks(), &rtt));
- EXPECT_FALSE(estimator.GetRecentTransportRTT(base::TimeTicks(), &rtt));
+ EXPECT_TRUE(estimator.GetRecentHttpRTT(base::TimeTicks(), &rtt));
+ EXPECT_TRUE(estimator.GetRecentTransportRTT(base::TimeTicks(), &rtt));
// Send two requests. Verify that the completion of each request generates at
// least one TCP RTT observation.
@@ -1835,38 +2028,32 @@ TEST(NetworkQualityEstimatorTest, MAYBE_TestTCPSocketRTT) {
estimator.SimulateNetworkChange(
NetworkChangeNotifier::ConnectionType::CONNECTION_WIFI, "test-1");
- histogram_tester.ExpectTotalCount("NQE.TransportRTT.Percentile50.Unknown", 1);
- histogram_tester.ExpectBucketCount("NQE.TransportRTT.Percentile50.Unknown",
+ histogram_tester.ExpectTotalCount("NQE.TransportRTT.Percentile50.2G", 1);
+ histogram_tester.ExpectBucketCount("NQE.TransportRTT.Percentile50.2G",
rtt.InMilliseconds(), 1);
- histogram_tester.ExpectTotalCount("NQE.TransportRTT.Percentile10.Unknown", 1);
- histogram_tester.ExpectTotalCount("NQE.TransportRTT.Percentile50.Unknown", 1);
- histogram_tester.ExpectTotalCount("NQE.TransportRTT.Percentile90.Unknown", 1);
- histogram_tester.ExpectTotalCount("NQE.TransportRTT.Percentile100.Unknown",
- 1);
+ histogram_tester.ExpectTotalCount("NQE.TransportRTT.Percentile10.2G", 1);
+ histogram_tester.ExpectTotalCount("NQE.TransportRTT.Percentile50.2G", 1);
+ histogram_tester.ExpectTotalCount("NQE.TransportRTT.Percentile90.2G", 1);
+ histogram_tester.ExpectTotalCount("NQE.TransportRTT.Percentile100.2G", 1);
// Verify that metrics are logged correctly on main-frame requests.
histogram_tester.ExpectTotalCount("NQE.MainFrame.TransportRTT.Percentile50",
num_requests);
- histogram_tester.ExpectBucketCount("NQE.EstimateAvailable.MainFrame.RTT", 0,
- 1);
- histogram_tester.ExpectBucketCount("NQE.EstimateAvailable.MainFrame.RTT", 1,
- num_requests - 1);
+ histogram_tester.ExpectUniqueSample("NQE.EstimateAvailable.MainFrame.RTT", 1,
+ num_requests);
histogram_tester.ExpectUniqueSample(
"NQE.EstimateAvailable.MainFrame.TransportRTT", 1, num_requests);
- histogram_tester.ExpectBucketCount("NQE.EstimateAvailable.MainFrame.Kbps", 0,
- 1);
- histogram_tester.ExpectBucketCount("NQE.EstimateAvailable.MainFrame.Kbps", 1,
- num_requests - 1);
+ histogram_tester.ExpectUniqueSample("NQE.EstimateAvailable.MainFrame.Kbps", 1,
+ num_requests);
histogram_tester.ExpectTotalCount(
- "NQE.MainFrame.TransportRTT.Percentile50.Unknown", num_requests);
+ "NQE.MainFrame.TransportRTT.Percentile50.2G", num_requests);
histogram_tester.ExpectTotalCount("NQE.MainFrame.EffectiveConnectionType",
num_requests);
- histogram_tester.ExpectTotalCount(
- "NQE.MainFrame.EffectiveConnectionType.Unknown", num_requests);
- histogram_tester.ExpectBucketCount(
- "NQE.MainFrame.EffectiveConnectionType.Unknown",
- EFFECTIVE_CONNECTION_TYPE_UNKNOWN, 1);
+ histogram_tester.ExpectTotalCount("NQE.MainFrame.EffectiveConnectionType.2G",
+ num_requests);
+ histogram_tester.ExpectBucketCount("NQE.MainFrame.EffectiveConnectionType.2G",
+ EFFECTIVE_CONNECTION_TYPE_UNKNOWN, 0);
}
#if defined(OS_IOS)
@@ -2061,8 +2248,7 @@ TEST(NetworkQualityEstimatorTest, MAYBE_RecordAccuracy) {
TEST(NetworkQualityEstimatorTest, TestRecordNetworkIDAvailability) {
base::HistogramTester histogram_tester;
- std::map<std::string, std::string> variation_params;
- TestNetworkQualityEstimator estimator(variation_params);
+ TestNetworkQualityEstimator estimator;
// The NetworkID is recorded as available on Wi-Fi connection.
estimator.SimulateNetworkChange(
@@ -2135,6 +2321,27 @@ TEST(NetworkQualityEstimatorTest, CorrelationHistogram) {
3000 >> kTrimBits,
},
{
+ // Verify that the metric is not recorded if the HTTP RTT is
+ // unavailable.
+ false, 0.3, 0.4, base::TimeDelta::FromSeconds(1), 1000 >> kTrimBits,
+ nqe::internal::InvalidRTT(), 2000 >> kTrimBits, 3000,
+ 3000 >> kTrimBits,
+ },
+ {
+ // Verify that the metric is not recorded if the transport RTT is
+ // unavailable.
+ true, 0.3, 0.4, nqe::internal::InvalidRTT(), 1000 >> kTrimBits,
+ base::TimeDelta::FromSeconds(2), 2000 >> kTrimBits, 3000,
+ 3000 >> kTrimBits,
+ },
+ {
+ // Verify that the metric is not recorded if the throughput is
+ // unavailable.
+ false, 0.3, 0.4, base::TimeDelta::FromSeconds(1), 1000 >> kTrimBits,
+ base::TimeDelta::FromSeconds(2), 2000 >> kTrimBits,
+ nqe::internal::kInvalidThroughput, 3000 >> kTrimBits,
+ },
+ {
// Verify that the metric is recorded if the logging probability is
// set to 1.0.
false, 0.5, 1.0, base::TimeDelta::FromSeconds(1), 1000 >> kTrimBits,
@@ -2183,6 +2390,9 @@ TEST(NetworkQualityEstimatorTest, CorrelationHistogram) {
context.set_network_quality_estimator(&estimator);
context.Init();
+ histogram_tester.ExpectTotalCount(
+ "NQE.Correlation.ResourceLoadTime.0Kb_128Kb", 0);
+
// Start a main-frame request that should cause network quality estimator to
// record the network quality at the last main frame request.
std::unique_ptr<URLRequest> request_1(context.CreateRequest(
@@ -2191,21 +2401,30 @@ TEST(NetworkQualityEstimatorTest, CorrelationHistogram) {
LOAD_MAIN_FRAME_DEPRECATED);
request_1->Start();
base::RunLoop().Run();
- histogram_tester.ExpectTotalCount(
- "NQE.Correlation.ResourceLoadTime.0Kb_128Kb", 0);
-
- // Start another main-frame request which should cause network quality
- // estimator to record the correlation UMA.
- std::unique_ptr<URLRequest> request_2(context.CreateRequest(
- estimator.GetEchoURL(), DEFAULT_PRIORITY, &test_delegate));
- request_2->Start();
- base::RunLoop().Run();
if (test.rand_double >= test.correlation_logging_probability) {
histogram_tester.ExpectTotalCount(
"NQE.Correlation.ResourceLoadTime.0Kb_128Kb", 0);
continue;
}
+ if (!test.use_transport_rtt &&
+ test.http_rtt == nqe::internal::InvalidRTT()) {
+ histogram_tester.ExpectTotalCount(
+ "NQE.Correlation.ResourceLoadTime.0Kb_128Kb", 0);
+ continue;
+ }
+ if (test.use_transport_rtt &&
+ test.transport_rtt == nqe::internal::InvalidRTT()) {
+ histogram_tester.ExpectTotalCount(
+ "NQE.Correlation.ResourceLoadTime.0Kb_128Kb", 0);
+ continue;
+ }
+ if (test.downstream_throughput_kbps == nqe::internal::kInvalidThroughput) {
+ histogram_tester.ExpectTotalCount(
+ "NQE.Correlation.ResourceLoadTime.0Kb_128Kb", 0);
+ continue;
+ }
+
histogram_tester.ExpectTotalCount(
"NQE.Correlation.ResourceLoadTime.0Kb_128Kb", 1);
std::vector<base::Bucket> buckets = histogram_tester.GetAllSamples(
@@ -2281,8 +2500,7 @@ class TestNetworkQualitiesCacheObserver
TEST(NetworkQualityEstimatorTest, CacheObserver) {
TestNetworkQualitiesCacheObserver observer;
- std::map<std::string, std::string> variation_params;
- TestNetworkQualityEstimator estimator(variation_params);
+ TestNetworkQualityEstimator estimator;
// Add |observer| as a persistent caching observer.
estimator.AddNetworkQualitiesCacheObserver(&observer);
@@ -2291,7 +2509,7 @@ TEST(NetworkQualityEstimatorTest, CacheObserver) {
estimator.SimulateNetworkChange(
NetworkChangeNotifier::ConnectionType::CONNECTION_UNKNOWN, "test3g");
estimator.RunOneRequest();
- EXPECT_EQ(1u, observer.get_notification_received_and_reset());
+ EXPECT_EQ(2u, observer.get_notification_received_and_reset());
EXPECT_EQ("test3g", observer.network_id().id);
estimator.set_recent_effective_connection_type(EFFECTIVE_CONNECTION_TYPE_2G);
@@ -2340,6 +2558,9 @@ TEST(NetworkQualityEstimatorTest,
TestEffectiveConnectionTypeObserver observer;
estimator.AddEffectiveConnectionTypeObserver(&observer);
+ // |observer| may be notified as soon as it is added. Run the loop to so
+ // that the notification to |observer| is finished.
+ base::RunLoop().RunUntilIdle();
TestDelegate test_delegate;
TestURLRequestContext context(true);
@@ -2370,4 +2591,320 @@ TEST(NetworkQualityEstimatorTest,
}
}
+// Test that the typical network qualities are set correctly.
+TEST(NetworkQualityEstimatorTest, TypicalNetworkQualities) {
+ const struct {
+ bool use_transport_rtt;
+ } tests[] = {
+ {
+ false,
+ },
+ {
+ true,
+ },
+ };
+
+ for (const auto& test : tests) {
+ TestNetworkQualitiesCacheObserver observer;
+ std::map<std::string, std::string> variation_params;
+ if (test.use_transport_rtt) {
+ variation_params["effective_connection_type_algorithm"] =
+ "TransportRTTOrDownstreamThroughput";
+ }
+ TestNetworkQualityEstimator estimator(variation_params);
+
+ // Typical network quality should not be set for Unknown and Offline.
+ for (size_t i = EFFECTIVE_CONNECTION_TYPE_UNKNOWN;
+ i <= EFFECTIVE_CONNECTION_TYPE_OFFLINE; ++i) {
+ EXPECT_EQ(nqe::internal::InvalidRTT(),
+ estimator.typical_network_quality_[i].http_rtt());
+
+ EXPECT_EQ(nqe::internal::InvalidRTT(),
+ estimator.typical_network_quality_[i].transport_rtt());
+ }
+
+ // Typical network quality should be set for other effective connection
+ // types.
+ for (size_t i = EFFECTIVE_CONNECTION_TYPE_SLOW_2G;
+ i <= EFFECTIVE_CONNECTION_TYPE_3G; ++i) {
+ // The typical RTT for an effective connection type should be at least as
+ // much as the threshold RTT.
+ EXPECT_NE(nqe::internal::InvalidRTT(),
+ estimator.typical_network_quality_[i].http_rtt());
+ EXPECT_GT(estimator.typical_network_quality_[i].http_rtt(),
+ estimator.connection_thresholds_[i].http_rtt());
+
+ EXPECT_NE(nqe::internal::InvalidRTT(),
+ estimator.typical_network_quality_[i].transport_rtt());
+ EXPECT_GT(estimator.typical_network_quality_[i].transport_rtt(),
+ estimator.connection_thresholds_[i].transport_rtt());
+
+ // The typical throughput for an effective connection type should not be
+ // more than the threshold throughput.
+ if (estimator.connection_thresholds_[i].downstream_throughput_kbps() !=
+ nqe::internal::kInvalidThroughput) {
+ EXPECT_LT(
+ estimator.typical_network_quality_[i].downstream_throughput_kbps(),
+ estimator.connection_thresholds_[i].downstream_throughput_kbps());
+ }
+ }
+
+ // The typical network quality of 4G connection should be at least as fast
+ // as the threshold for 3G connection.
+ EXPECT_LT(estimator.typical_network_quality_[EFFECTIVE_CONNECTION_TYPE_4G]
+ .http_rtt(),
+ estimator.connection_thresholds_[EFFECTIVE_CONNECTION_TYPE_3G]
+ .http_rtt());
+ EXPECT_LT(estimator.typical_network_quality_[EFFECTIVE_CONNECTION_TYPE_4G]
+ .transport_rtt(),
+ estimator.connection_thresholds_[EFFECTIVE_CONNECTION_TYPE_3G]
+ .transport_rtt());
+ if (estimator.connection_thresholds_[EFFECTIVE_CONNECTION_TYPE_3G]
+ .downstream_throughput_kbps() !=
+ nqe::internal::kInvalidThroughput) {
+ EXPECT_GT(estimator.typical_network_quality_[EFFECTIVE_CONNECTION_TYPE_4G]
+ .downstream_throughput_kbps(),
+ estimator.connection_thresholds_[EFFECTIVE_CONNECTION_TYPE_3G]
+ .downstream_throughput_kbps());
+ }
+
+ TestDelegate test_delegate;
+ TestURLRequestContext context(true);
+ context.set_network_quality_estimator(&estimator);
+ context.Init();
+
+ for (size_t effective_connection_type = EFFECTIVE_CONNECTION_TYPE_SLOW_2G;
+ effective_connection_type <= EFFECTIVE_CONNECTION_TYPE_4G;
+ ++effective_connection_type) {
+ // Set the RTT and throughput values to the typical values for
+ // |effective_connection_type|. The effective connection type should be
+ // computed as |effective_connection_type|.
+ estimator.set_start_time_null_http_rtt(
+ estimator.typical_network_quality_[effective_connection_type]
+ .http_rtt());
+ estimator.set_start_time_null_transport_rtt(
+ estimator.typical_network_quality_[effective_connection_type]
+ .transport_rtt());
+ estimator.set_start_time_null_downlink_throughput_kbps(INT32_MAX);
+
+ // Force recomputation of effective connection type by starting a main
+ // frame request.
+ std::unique_ptr<URLRequest> request(context.CreateRequest(
+ estimator.GetEchoURL(), DEFAULT_PRIORITY, &test_delegate));
+ request->SetLoadFlags(request->load_flags() | LOAD_MAIN_FRAME_DEPRECATED);
+ request->Start();
+ base::RunLoop().Run();
+
+ EXPECT_EQ(effective_connection_type,
+ estimator.GetEffectiveConnectionType());
+ }
+ }
+}
+
+// Verify that the cached network qualities from the prefs are correctly used.
+TEST(NetworkQualityEstimatorTest, OnPrefsRead) {
+ base::HistogramTester histogram_tester;
+
+ // Construct the read prefs.
+ std::map<nqe::internal::NetworkID, nqe::internal::CachedNetworkQuality>
+ read_prefs;
+ read_prefs[nqe::internal::NetworkID(NetworkChangeNotifier::CONNECTION_WIFI,
+ "test_ect_2g")] =
+ nqe::internal::CachedNetworkQuality(EFFECTIVE_CONNECTION_TYPE_2G);
+ read_prefs[nqe::internal::NetworkID(NetworkChangeNotifier::CONNECTION_WIFI,
+ "test_ect_slow_2g")] =
+ nqe::internal::CachedNetworkQuality(EFFECTIVE_CONNECTION_TYPE_SLOW_2G);
+ read_prefs[nqe::internal::NetworkID(NetworkChangeNotifier::CONNECTION_4G,
+ "test_ect_4g")] =
+ nqe::internal::CachedNetworkQuality(EFFECTIVE_CONNECTION_TYPE_4G);
+
+ std::map<std::string, std::string> variation_params;
+ variation_params["effective_connection_type_algorithm"] =
+ "TransportRTTOrDownstreamThroughput";
+ variation_params["persistent_cache_reading_enabled"] = "true";
+ // Disable default platform values so that the effect of cached estimates
+ // at the time of startup can be studied in isolation.
+ TestNetworkQualityEstimator estimator(
+ std::unique_ptr<net::ExternalEstimateProvider>(), variation_params, true,
+ true, false /* use_default_platform_values */);
+
+ // Add observers.
+ TestRTTObserver rtt_observer;
+ TestThroughputObserver throughput_observer;
+ TestRTTAndThroughputEstimatesObserver rtt_throughput_observer;
+ TestEffectiveConnectionTypeObserver effective_connection_type_observer;
+ estimator.AddRTTObserver(&rtt_observer);
+ estimator.AddThroughputObserver(&throughput_observer);
+ estimator.AddRTTAndThroughputEstimatesObserver(&rtt_throughput_observer);
+ estimator.AddEffectiveConnectionTypeObserver(
+ &effective_connection_type_observer);
+
+ std::string network_name("test_ect_2g");
+
+ estimator.SimulateNetworkChange(
+ NetworkChangeNotifier::ConnectionType::CONNECTION_WIFI, network_name);
+ EXPECT_EQ(0u, rtt_observer.observations().size());
+ EXPECT_EQ(0u, throughput_observer.observations().size());
+ EXPECT_LE(0, rtt_throughput_observer.notifications_received());
+
+ // Simulate reading of prefs.
+ estimator.OnPrefsRead(read_prefs);
+ histogram_tester.ExpectUniqueSample("NQE.Prefs.ReadSize", read_prefs.size(),
+ 1);
+
+ // Taken from network_quality_estimator_params.cc.
+ EXPECT_EQ(base::TimeDelta::FromMilliseconds(1800),
+ rtt_observer.last_rtt(
+ NETWORK_QUALITY_OBSERVATION_SOURCE_HTTP_CACHED_ESTIMATE));
+ EXPECT_EQ(base::TimeDelta::FromMilliseconds(1500),
+ rtt_observer.last_rtt(
+ NETWORK_QUALITY_OBSERVATION_SOURCE_TRANSPORT_CACHED_ESTIMATE));
+ EXPECT_EQ(1u, throughput_observer.observations().size());
+ EXPECT_EQ(base::TimeDelta::FromMilliseconds(1800),
+ rtt_throughput_observer.http_rtt());
+ EXPECT_EQ(base::TimeDelta::FromMilliseconds(1500),
+ rtt_throughput_observer.transport_rtt());
+ EXPECT_EQ(75, rtt_throughput_observer.downstream_throughput_kbps());
+ EXPECT_LE(
+ 1u,
+ effective_connection_type_observer.effective_connection_types().size());
+ // Compare the ECT stored in prefs with the observer's last entry.
+ EXPECT_EQ(
+ read_prefs[nqe::internal::NetworkID(
+ NetworkChangeNotifier::CONNECTION_WIFI, network_name)]
+ .effective_connection_type(),
+ effective_connection_type_observer.effective_connection_types().back());
+
+ // Change to a different connection type.
+ network_name = "test_ect_slow_2g";
+ estimator.SimulateNetworkChange(
+ NetworkChangeNotifier::ConnectionType::CONNECTION_WIFI, network_name);
+
+ EXPECT_EQ(base::TimeDelta::FromMilliseconds(3600),
+ rtt_observer.last_rtt(
+ NETWORK_QUALITY_OBSERVATION_SOURCE_HTTP_CACHED_ESTIMATE));
+ EXPECT_EQ(base::TimeDelta::FromMilliseconds(3000),
+ rtt_observer.last_rtt(
+ NETWORK_QUALITY_OBSERVATION_SOURCE_TRANSPORT_CACHED_ESTIMATE));
+ EXPECT_EQ(2U, throughput_observer.observations().size());
+ EXPECT_EQ(base::TimeDelta::FromMilliseconds(3600),
+ rtt_throughput_observer.http_rtt());
+ EXPECT_EQ(base::TimeDelta::FromMilliseconds(3000),
+ rtt_throughput_observer.transport_rtt());
+ EXPECT_EQ(40, rtt_throughput_observer.downstream_throughput_kbps());
+ EXPECT_LE(
+ 2u,
+ effective_connection_type_observer.effective_connection_types().size());
+ // Compare with the last entry.
+ EXPECT_EQ(
+ read_prefs[nqe::internal::NetworkID(
+ NetworkChangeNotifier::CONNECTION_WIFI, network_name)]
+ .effective_connection_type(),
+ effective_connection_type_observer.effective_connection_types().back());
+
+ // Cleanup.
+ estimator.RemoveRTTObserver(&rtt_observer);
+ estimator.RemoveThroughputObserver(&throughput_observer);
+ estimator.RemoveRTTAndThroughputEstimatesObserver(&rtt_throughput_observer);
+ estimator.RemoveEffectiveConnectionTypeObserver(
+ &effective_connection_type_observer);
+}
+
+// Verify that the cached network qualities from the prefs are not used if the
+// reading of the network quality prefs is not enabled..
+TEST(NetworkQualityEstimatorTest, OnPrefsReadWithReadingDisabled) {
+ base::HistogramTester histogram_tester;
+
+ // Construct the read prefs.
+ std::map<nqe::internal::NetworkID, nqe::internal::CachedNetworkQuality>
+ read_prefs;
+ read_prefs[nqe::internal::NetworkID(NetworkChangeNotifier::CONNECTION_WIFI,
+ "test_ect_2g")] =
+ nqe::internal::CachedNetworkQuality(EFFECTIVE_CONNECTION_TYPE_2G);
+ read_prefs[nqe::internal::NetworkID(NetworkChangeNotifier::CONNECTION_WIFI,
+ "test_ect_slow_2g")] =
+ nqe::internal::CachedNetworkQuality(EFFECTIVE_CONNECTION_TYPE_SLOW_2G);
+ read_prefs[nqe::internal::NetworkID(NetworkChangeNotifier::CONNECTION_4G,
+ "test_ect_4g")] =
+ nqe::internal::CachedNetworkQuality(EFFECTIVE_CONNECTION_TYPE_4G);
+
+ std::map<std::string, std::string> variation_params;
+ variation_params["effective_connection_type_algorithm"] =
+ "TransportRTTOrDownstreamThroughput";
+ // |persistent_cache_reading_enabled| variation param is not set.
+
+ // Disable default platform values so that the effect of cached estimates
+ // at the time of startup can be studied in isolation.
+ TestNetworkQualityEstimator estimator(
+ std::unique_ptr<net::ExternalEstimateProvider>(), variation_params, true,
+ true, false /* use_default_platform_values */);
+
+ // Add observers.
+ TestRTTObserver rtt_observer;
+ TestThroughputObserver throughput_observer;
+ TestRTTAndThroughputEstimatesObserver rtt_throughput_observer;
+ TestEffectiveConnectionTypeObserver effective_connection_type_observer;
+ estimator.AddRTTObserver(&rtt_observer);
+ estimator.AddThroughputObserver(&throughput_observer);
+ estimator.AddRTTAndThroughputEstimatesObserver(&rtt_throughput_observer);
+ estimator.AddEffectiveConnectionTypeObserver(
+ &effective_connection_type_observer);
+
+ std::string network_name("test_ect_2g");
+
+ estimator.SimulateNetworkChange(
+ NetworkChangeNotifier::ConnectionType::CONNECTION_WIFI, network_name);
+ EXPECT_EQ(0u, rtt_observer.observations().size());
+ EXPECT_EQ(0u, throughput_observer.observations().size());
+ EXPECT_LE(0, rtt_throughput_observer.notifications_received());
+
+ // Simulate reading of prefs.
+ estimator.OnPrefsRead(read_prefs);
+ histogram_tester.ExpectUniqueSample("NQE.Prefs.ReadSize", read_prefs.size(),
+ 1);
+
+ // Force read the network quality store from the store to verify that store
+ // gets populated even if reading of prefs is not enabled.
+ nqe::internal::CachedNetworkQuality cached_network_quality;
+ EXPECT_TRUE(estimator.network_quality_store_->GetById(
+ nqe::internal::NetworkID(NetworkChangeNotifier::CONNECTION_WIFI,
+ "test_ect_2g"),
+ &cached_network_quality));
+ EXPECT_EQ(EFFECTIVE_CONNECTION_TYPE_2G,
+ cached_network_quality.effective_connection_type());
+
+ // Taken from network_quality_estimator_params.cc.
+ EXPECT_EQ(nqe::internal::InvalidRTT(),
+ rtt_observer.last_rtt(
+ NETWORK_QUALITY_OBSERVATION_SOURCE_HTTP_CACHED_ESTIMATE));
+ EXPECT_EQ(nqe::internal::InvalidRTT(),
+ rtt_observer.last_rtt(
+ NETWORK_QUALITY_OBSERVATION_SOURCE_TRANSPORT_CACHED_ESTIMATE));
+ EXPECT_EQ(0u, throughput_observer.observations().size());
+
+ EXPECT_EQ(
+ 0u,
+ effective_connection_type_observer.effective_connection_types().size());
+
+ // Change to a different connection type.
+ network_name = "test_ect_slow_2g";
+ estimator.SimulateNetworkChange(
+ NetworkChangeNotifier::ConnectionType::CONNECTION_WIFI, network_name);
+
+ EXPECT_EQ(nqe::internal::InvalidRTT(),
+ rtt_observer.last_rtt(
+ NETWORK_QUALITY_OBSERVATION_SOURCE_HTTP_CACHED_ESTIMATE));
+ EXPECT_EQ(nqe::internal::InvalidRTT(),
+ rtt_observer.last_rtt(
+ NETWORK_QUALITY_OBSERVATION_SOURCE_TRANSPORT_CACHED_ESTIMATE));
+ EXPECT_EQ(0U, throughput_observer.observations().size());
+
+ // Cleanup.
+ estimator.RemoveRTTObserver(&rtt_observer);
+ estimator.RemoveThroughputObserver(&throughput_observer);
+ estimator.RemoveRTTAndThroughputEstimatesObserver(&rtt_throughput_observer);
+ estimator.RemoveEffectiveConnectionTypeObserver(
+ &effective_connection_type_observer);
+}
+
} // namespace net
diff --git a/chromium/net/nqe/network_quality_observation.h b/chromium/net/nqe/network_quality_observation.h
index 5349338de39..91d163303ba 100644
--- a/chromium/net/nqe/network_quality_observation.h
+++ b/chromium/net/nqe/network_quality_observation.h
@@ -28,8 +28,12 @@ template <typename ValueType>
struct NET_EXPORT_PRIVATE Observation {
Observation(const ValueType& value,
base::TimeTicks timestamp,
+ int32_t signal_strength_dbm,
NetworkQualityObservationSource source)
- : value(value), timestamp(timestamp), source(source) {
+ : value(value),
+ timestamp(timestamp),
+ signal_strength_dbm(signal_strength_dbm),
+ source(source) {
DCHECK(!timestamp.is_null());
}
~Observation() {}
@@ -40,6 +44,10 @@ struct NET_EXPORT_PRIVATE Observation {
// Time when the observation was taken.
const base::TimeTicks timestamp;
+ // Signal strength (in dBm) when the observation was taken. Set to INT32_MIN
+ // if the signal strength is unavailable.
+ const int32_t signal_strength_dbm;
+
// The source of the observation.
const NetworkQualityObservationSource source;
};
@@ -50,4 +58,4 @@ struct NET_EXPORT_PRIVATE Observation {
} // namespace net
-#endif // NET_NQE_NETWORK_QUALITY_OBSERVATION_H_ \ No newline at end of file
+#endif // NET_NQE_NETWORK_QUALITY_OBSERVATION_H_
diff --git a/chromium/net/nqe/network_quality_observation_source.h b/chromium/net/nqe/network_quality_observation_source.h
index 82b333cedec..e4a8454359c 100644
--- a/chromium/net/nqe/network_quality_observation_source.h
+++ b/chromium/net/nqe/network_quality_observation_source.h
@@ -52,4 +52,4 @@ enum NetworkQualityObservationSource {
} // namespace net
-#endif // NET_NQE_NETWORK_QUALITY_OBSERVATION_SOURCE_H_ \ No newline at end of file
+#endif // NET_NQE_NETWORK_QUALITY_OBSERVATION_SOURCE_H_
diff --git a/chromium/net/nqe/network_quality_store.cc b/chromium/net/nqe/network_quality_store.cc
index 01b50054a5e..43d2bcafaf8 100644
--- a/chromium/net/nqe/network_quality_store.cc
+++ b/chromium/net/nqe/network_quality_store.cc
@@ -4,6 +4,8 @@
#include "net/nqe/network_quality_store.h"
+#include "base/location.h"
+#include "base/threading/thread_task_runner_handle.h"
#include "net/base/network_change_notifier.h"
namespace net {
@@ -12,7 +14,8 @@ namespace nqe {
namespace internal {
-NetworkQualityStore::NetworkQualityStore() {
+NetworkQualityStore::NetworkQualityStore()
+ : disable_offline_check_(false), weak_ptr_factory_(this) {
static_assert(kMaximumNetworkQualityCacheSize > 0,
"Size of the network quality cache must be > 0");
// This limit should not be increased unless the logic for removing the
@@ -32,9 +35,13 @@ void NetworkQualityStore::Add(
DCHECK_LE(cached_network_qualities_.size(),
static_cast<size_t>(kMaximumNetworkQualityCacheSize));
- // If the network name is unavailable, caching should not be performed.
- if (network_id.type != net::NetworkChangeNotifier::CONNECTION_ETHERNET &&
- network_id.id.empty()) {
+ // If the network name is unavailable, caching should not be performed. If
+ // |disable_offline_check_| is set to true, cache the network quality even if
+ // the network is set to offline.
+ if (network_id.type != NetworkChangeNotifier::CONNECTION_ETHERNET &&
+ network_id.id.empty() &&
+ (network_id.type != NetworkChangeNotifier::CONNECTION_NONE ||
+ !disable_offline_check_)) {
return;
}
@@ -80,19 +87,39 @@ bool NetworkQualityStore::GetById(
}
void NetworkQualityStore::AddNetworkQualitiesCacheObserver(
- nqe::internal::NetworkQualityStore::NetworkQualitiesCacheObserver*
- observer) {
+ NetworkQualitiesCacheObserver* observer) {
DCHECK(thread_checker_.CalledOnValidThread());
network_qualities_cache_observer_list_.AddObserver(observer);
+
+ // Notify the |observer| on the next message pump since |observer| may not
+ // be completely set up for receiving the callbacks.
+ base::ThreadTaskRunnerHandle::Get()->PostTask(
+ FROM_HERE, base::Bind(&NetworkQualityStore::NotifyCacheObserverIfPresent,
+ weak_ptr_factory_.GetWeakPtr(), observer));
}
void NetworkQualityStore::RemoveNetworkQualitiesCacheObserver(
- nqe::internal::NetworkQualityStore::NetworkQualitiesCacheObserver*
- observer) {
+ NetworkQualitiesCacheObserver* observer) {
DCHECK(thread_checker_.CalledOnValidThread());
network_qualities_cache_observer_list_.RemoveObserver(observer);
}
+void NetworkQualityStore::DisableOfflineCheckForTesting(
+ bool disable_offline_check) {
+ DCHECK(thread_checker_.CalledOnValidThread());
+ disable_offline_check_ = disable_offline_check;
+}
+
+void NetworkQualityStore::NotifyCacheObserverIfPresent(
+ NetworkQualitiesCacheObserver* observer) const {
+ DCHECK(thread_checker_.CalledOnValidThread());
+
+ if (!network_qualities_cache_observer_list_.HasObserver(observer))
+ return;
+ for (const auto it : cached_network_qualities_)
+ observer->OnChangeInCachedNetworkQuality(it.first, it.second);
+}
+
} // namespace internal
} // namespace nqe
diff --git a/chromium/net/nqe/network_quality_store.h b/chromium/net/nqe/network_quality_store.h
index 6b71a646b46..8970c350e11 100644
--- a/chromium/net/nqe/network_quality_store.h
+++ b/chromium/net/nqe/network_quality_store.h
@@ -8,6 +8,7 @@
#include <map>
#include "base/macros.h"
+#include "base/memory/weak_ptr.h"
#include "base/observer_list.h"
#include "base/threading/thread_checker.h"
#include "net/base/net_export.h"
@@ -66,12 +67,21 @@ class NET_EXPORT_PRIVATE NetworkQualityStore {
void RemoveNetworkQualitiesCacheObserver(
NetworkQualitiesCacheObserver* observer);
+ // If |disable_offline_check| is set to true, the offline check is disabled
+ // when storing the network quality.
+ void DisableOfflineCheckForTesting(bool disable_offline_check);
+
private:
// Maximum size of the store that holds network quality estimates.
// A smaller size may reduce the cache hit rate due to frequent evictions.
// A larger size may affect performance.
static const size_t kMaximumNetworkQualityCacheSize = 10;
+ // Notifies |observer| of the current effective connection type if |observer|
+ // is still registered as an observer.
+ void NotifyCacheObserverIfPresent(
+ NetworkQualitiesCacheObserver* observer) const;
+
// This does not use an unordered_map or hash_map for code simplicity (the key
// just implements operator<, rather than hash and equality) and because the
// map is tiny.
@@ -86,8 +96,14 @@ class NET_EXPORT_PRIVATE NetworkQualityStore {
base::ObserverList<NetworkQualitiesCacheObserver>
network_qualities_cache_observer_list_;
+ // When set to true, disables the offline check when storing the network
+ // quality.
+ bool disable_offline_check_;
+
base::ThreadChecker thread_checker_;
+ base::WeakPtrFactory<NetworkQualityStore> weak_ptr_factory_;
+
DISALLOW_COPY_AND_ASSIGN(NetworkQualityStore);
};
diff --git a/chromium/net/nqe/network_quality_store_unittest.cc b/chromium/net/nqe/network_quality_store_unittest.cc
index 5a17e639169..be4945e61cb 100644
--- a/chromium/net/nqe/network_quality_store_unittest.cc
+++ b/chromium/net/nqe/network_quality_store_unittest.cc
@@ -186,4 +186,4 @@ TEST(NetworkQualityStoreTest, TestLRUCacheMaximumSize) {
} // namespace
-} // namespace net \ No newline at end of file
+} // namespace net
diff --git a/chromium/net/nqe/observation_buffer.h b/chromium/net/nqe/observation_buffer.h
index b9339a85ec1..10f60099112 100644
--- a/chromium/net/nqe/observation_buffer.h
+++ b/chromium/net/nqe/observation_buffer.h
@@ -32,13 +32,17 @@ namespace internal {
template <typename ValueType>
class NET_EXPORT_PRIVATE ObservationBuffer {
public:
- explicit ObservationBuffer(double weight_multiplier_per_second)
+ ObservationBuffer(double weight_multiplier_per_second,
+ double weight_multiplier_per_dbm)
: weight_multiplier_per_second_(weight_multiplier_per_second),
+ weight_multiplier_per_dbm_(weight_multiplier_per_dbm),
tick_clock_(new base::DefaultTickClock()) {
static_assert(kMaximumObservationsBufferSize > 0U,
"Minimum size of observation buffer must be > 0");
- DCHECK_GE(weight_multiplier_per_second_, 0.0);
- DCHECK_LE(weight_multiplier_per_second_, 1.0);
+ DCHECK_LE(0.0, weight_multiplier_per_second_);
+ DCHECK_GE(1.0, weight_multiplier_per_second_);
+ DCHECK_LE(0.0, weight_multiplier_per_dbm_);
+ DCHECK_GE(1.0, weight_multiplier_per_dbm_);
}
~ObservationBuffer() {}
@@ -73,10 +77,12 @@ class NET_EXPORT_PRIVATE ObservationBuffer {
// value of all observations made on or after |begin_timestamp|. If the
// value is unavailable, false is returned and |result| is not modified.
// Percentile value is unavailable if all the values in observation buffer are
- // older than |begin_timestamp|.
+ // older than |begin_timestamp|. |current_signal_strength_dbm| is the current
+ // signal strength in dBm.
// |result| must not be null.
// TODO(tbansal): Move out param |result| as the last param of the function.
bool GetPercentile(base::TimeTicks begin_timestamp,
+ int32_t current_signal_strength_dbm,
ValueType* result,
int percentile,
const std::vector<NetworkQualityObservationSource>&
@@ -87,8 +93,9 @@ class NET_EXPORT_PRIVATE ObservationBuffer {
// Total weight of all observations in |weighted_observations|.
double total_weight = 0.0;
- ComputeWeightedObservations(begin_timestamp, weighted_observations,
- &total_weight, disallowed_observation_sources);
+ ComputeWeightedObservations(begin_timestamp, current_signal_strength_dbm,
+ weighted_observations, &total_weight,
+ disallowed_observation_sources);
if (weighted_observations.empty())
return false;
@@ -118,8 +125,10 @@ class NET_EXPORT_PRIVATE ObservationBuffer {
// of all observations made on or after |begin_timestamp|. If the value is
// unavailable, false is returned and |result| is not modified. The unweighted
// average value is unavailable if all the values in the observation buffer
- // are older than |begin_timestamp|. |result| must not be null.
+ // are older than |begin_timestamp|. |current_signal_strength_dbm| is the
+ // current signal strength in dBm. |result| must not be null.
bool GetWeightedAverage(base::TimeTicks begin_timestamp,
+ int32_t current_signal_strength_dbm,
const std::vector<NetworkQualityObservationSource>&
disallowed_observation_sources,
ValueType* result) const {
@@ -129,8 +138,9 @@ class NET_EXPORT_PRIVATE ObservationBuffer {
// Total weight of all observations in |weighted_observations|.
double total_weight = 0.0;
- ComputeWeightedObservations(begin_timestamp, weighted_observations,
- &total_weight, disallowed_observation_sources);
+ ComputeWeightedObservations(begin_timestamp, current_signal_strength_dbm,
+ weighted_observations, &total_weight,
+ disallowed_observation_sources);
if (weighted_observations.empty())
return false;
@@ -152,8 +162,10 @@ class NET_EXPORT_PRIVATE ObservationBuffer {
// all observations made on or after |begin_timestamp|. If the value is
// unavailable, false is returned and |result| is not modified. The weighted
// average value is unavailable if all the values in the observation buffer
- // are older than |begin_timestamp|. |result| must not be null.
+ // are older than |begin_timestamp|. |current_signal_strength_dbm| is the
+ // current signal strength in dBm. |result| must not be null.
bool GetUnweightedAverage(base::TimeTicks begin_timestamp,
+ int32_t current_signal_strength_dbm,
const std::vector<NetworkQualityObservationSource>&
disallowed_observation_sources,
ValueType* result) const {
@@ -163,8 +175,9 @@ class NET_EXPORT_PRIVATE ObservationBuffer {
// Total weight of all observations in |weighted_observations|.
double total_weight = 0.0;
- ComputeWeightedObservations(begin_timestamp, weighted_observations,
- &total_weight, disallowed_observation_sources);
+ ComputeWeightedObservations(begin_timestamp, current_signal_strength_dbm,
+ weighted_observations, &total_weight,
+ disallowed_observation_sources);
if (weighted_observations.empty())
return false;
@@ -205,11 +218,14 @@ class NET_EXPORT_PRIVATE ObservationBuffer {
// Computes the weighted observations and stores them in
// |weighted_observations| sorted by ascending |WeightedObservation.value|.
// Only the observations with timestamp later than |begin_timestamp| are
- // considered. Also, sets |total_weight| to the total weight of all
- // observations. Should be called only when there is at least one
- // observation in the buffer.
+ // considered. |current_signal_strength_dbm| is the current signal strength
+ // (in dBm) when the observation was taken, and is set to INT32_MIN if the
+ // signal strength is currently unavailable. This method also sets
+ // |total_weight| to the total weight of all observations. Should be called
+ // only when there is at least one observation in the buffer.
void ComputeWeightedObservations(
const base::TimeTicks& begin_timestamp,
+ int32_t current_signal_strength_dbm,
std::vector<WeightedObservation<ValueType>>& weighted_observations,
double* total_weight,
const std::vector<NetworkQualityObservationSource>&
@@ -231,8 +247,22 @@ class NET_EXPORT_PRIVATE ObservationBuffer {
if (disallowed)
continue;
base::TimeDelta time_since_sample_taken = now - observation.timestamp;
- double weight = pow(weight_multiplier_per_second_,
- time_since_sample_taken.InSeconds());
+ double time_weight = pow(weight_multiplier_per_second_,
+ time_since_sample_taken.InSeconds());
+
+ double signal_strength_weight = 1.0;
+ if (current_signal_strength_dbm != INT32_MIN &&
+ observation.signal_strength_dbm != INT32_MIN &&
+ current_signal_strength_dbm != INT32_MAX &&
+ observation.signal_strength_dbm != INT32_MAX) {
+ int32_t signal_strength_weight_diff = std::abs(
+ current_signal_strength_dbm - observation.signal_strength_dbm);
+ signal_strength_weight =
+ pow(weight_multiplier_per_dbm_, signal_strength_weight_diff);
+ }
+
+ double weight = time_weight * signal_strength_weight;
+
weight = std::max(DBL_MIN, std::min(1.0, weight));
weighted_observations.push_back(
@@ -264,6 +294,14 @@ class NET_EXPORT_PRIVATE ObservationBuffer {
// weight_multiplier_per_second_ ^ kHalfLifeSeconds = 0.5
const double weight_multiplier_per_second_;
+ // The factor by which the weight of an observation reduces for every dbM
+ // difference in the current signal strength, and the signal strength at
+ // which the observation was taken.
+ // For example, if the observation was taken at 90 dBm, and current signal
+ // strength is 95 dBm, the weight of the observation would be:
+ // |weight_multiplier_per_dbm_| ^ 5.
+ const double weight_multiplier_per_dbm_;
+
std::unique_ptr<base::TickClock> tick_clock_;
DISALLOW_COPY_AND_ASSIGN(ObservationBuffer);
@@ -275,4 +313,4 @@ class NET_EXPORT_PRIVATE ObservationBuffer {
} // namespace net
-#endif // NET_NQE_OBSERVATION_BUFFER_H_ \ No newline at end of file
+#endif // NET_NQE_OBSERVATION_BUFFER_H_
diff --git a/chromium/net/nqe/observation_buffer_unittest.cc b/chromium/net/nqe/observation_buffer_unittest.cc
index 5838fc9692f..a29e98256e3 100644
--- a/chromium/net/nqe/observation_buffer_unittest.cc
+++ b/chromium/net/nqe/observation_buffer_unittest.cc
@@ -29,12 +29,12 @@ namespace {
// Verify that the buffer size is never exceeded.
TEST(NetworkQualityObservationBufferTest, BoundedBuffer) {
- ObservationBuffer<int32_t> observation_buffer(1.0);
+ ObservationBuffer<int32_t> observation_buffer(1.0, 1.0);
const base::TimeTicks now =
base::TimeTicks() + base::TimeDelta::FromSeconds(1);
for (int i = 1; i <= 1000; ++i) {
- observation_buffer.AddObservation(
- Observation<int32_t>(i, now, NETWORK_QUALITY_OBSERVATION_SOURCE_TCP));
+ observation_buffer.AddObservation(Observation<int32_t>(
+ i, now, INT32_MIN, NETWORK_QUALITY_OBSERVATION_SOURCE_TCP));
// The number of entries should be at most the maximum buffer size.
EXPECT_GE(300u, observation_buffer.Size());
}
@@ -51,13 +51,14 @@ TEST(NetworkQualityObservationBufferTest, GetPercentileWithWeights) {
new base::SimpleTestTickClock());
base::SimpleTestTickClock* tick_clock_ptr = tick_clock.get();
- ObservationBuffer<int32_t> observation_buffer(0.98);
+ ObservationBuffer<int32_t> observation_buffer(0.98, 1.0);
observation_buffer.SetTickClockForTesting(std::move(tick_clock));
const base::TimeTicks now = tick_clock_ptr->NowTicks();
for (int i = 1; i <= 100; ++i) {
tick_clock_ptr->Advance(base::TimeDelta::FromSeconds(1));
- observation_buffer.AddObservation(Observation<int32_t>(
- i, tick_clock_ptr->NowTicks(), NETWORK_QUALITY_OBSERVATION_SOURCE_TCP));
+ observation_buffer.AddObservation(
+ Observation<int32_t>(i, tick_clock_ptr->NowTicks(), INT32_MIN,
+ NETWORK_QUALITY_OBSERVATION_SOURCE_TCP));
}
EXPECT_EQ(100U, observation_buffer.Size());
@@ -68,14 +69,15 @@ TEST(NetworkQualityObservationBufferTest, GetPercentileWithWeights) {
// Verify that i'th percentile is more than i-1'th percentile.
int32_t result_i;
EXPECT_TRUE(observation_buffer.GetPercentile(
- now, &result_i, i, std::vector<NetworkQualityObservationSource>()));
+ now, INT32_MIN, &result_i, i,
+ std::vector<NetworkQualityObservationSource>()));
result_lowest = std::min(result_lowest, result_i);
result_highest = std::max(result_highest, result_i);
int32_t result_i_1;
EXPECT_TRUE(observation_buffer.GetPercentile(
- now, &result_i_1, i - 1,
+ now, INT32_MIN, &result_i_1, i - 1,
std::vector<NetworkQualityObservationSource>()));
EXPECT_LE(result_i_1, result_i);
@@ -87,8 +89,8 @@ TEST(NetworkQualityObservationBufferTest, GetPercentileWithWeights) {
// Verifies that the percentiles are correctly computed. All observations have
// the same timestamp.
TEST(NetworkQualityObservationBufferTest, PercentileSameTimestamps) {
- ObservationBuffer<int32_t> int_buffer(0.5);
- ObservationBuffer<base::TimeDelta> time_delta_buffer(0.5);
+ ObservationBuffer<int32_t> int_buffer(0.5, 1.0);
+ ObservationBuffer<base::TimeDelta> time_delta_buffer(0.5, 1.0);
ASSERT_EQ(0u, int_buffer.Size());
ASSERT_LT(0u, int_buffer.Capacity());
ASSERT_EQ(0u, time_delta_buffer.Size());
@@ -101,42 +103,42 @@ TEST(NetworkQualityObservationBufferTest, PercentileSameTimestamps) {
// Percentiles should be unavailable when no observations are available.
EXPECT_FALSE(
- int_buffer.GetPercentile(base::TimeTicks(), &result, 50,
+ int_buffer.GetPercentile(base::TimeTicks(), INT32_MIN, &result, 50,
std::vector<NetworkQualityObservationSource>()));
EXPECT_FALSE(time_delta_buffer.GetPercentile(
- base::TimeTicks(), &time_delta_result, 50,
+ base::TimeTicks(), INT32_MIN, &time_delta_result, 50,
std::vector<NetworkQualityObservationSource>()));
// Insert samples from {1,2,3,..., 100}. First insert odd samples, then even
// samples. This helps in verifying that the order of samples does not matter.
for (int i = 1; i <= 99; i += 2) {
- int_buffer.AddObservation(
- Observation<int32_t>(i, now, NETWORK_QUALITY_OBSERVATION_SOURCE_HTTP));
- time_delta_buffer.AddObservation(
- Observation<base::TimeDelta>(base::TimeDelta::FromMilliseconds(i), now,
- NETWORK_QUALITY_OBSERVATION_SOURCE_HTTP));
+ int_buffer.AddObservation(Observation<int32_t>(
+ i, now, INT32_MIN, NETWORK_QUALITY_OBSERVATION_SOURCE_HTTP));
+ time_delta_buffer.AddObservation(Observation<base::TimeDelta>(
+ base::TimeDelta::FromMilliseconds(i), now, INT32_MIN,
+ NETWORK_QUALITY_OBSERVATION_SOURCE_HTTP));
EXPECT_TRUE(int_buffer.GetPercentile(
- base::TimeTicks(), &result, 50,
+ base::TimeTicks(), INT32_MIN, &result, 50,
std::vector<NetworkQualityObservationSource>()));
ASSERT_EQ(static_cast<size_t>(i / 2 + 1), int_buffer.Size());
EXPECT_TRUE(time_delta_buffer.GetPercentile(
- base::TimeTicks(), &time_delta_result, 50,
+ base::TimeTicks(), INT32_MIN, &time_delta_result, 50,
std::vector<NetworkQualityObservationSource>()));
ASSERT_EQ(static_cast<size_t>(i / 2 + 1), time_delta_buffer.Size());
}
for (int i = 2; i <= 100; i += 2) {
- int_buffer.AddObservation(
- Observation<int32_t>(i, now, NETWORK_QUALITY_OBSERVATION_SOURCE_HTTP));
- time_delta_buffer.AddObservation(
- Observation<base::TimeDelta>(base::TimeDelta::FromMilliseconds(i), now,
- NETWORK_QUALITY_OBSERVATION_SOURCE_HTTP));
+ int_buffer.AddObservation(Observation<int32_t>(
+ i, now, INT32_MIN, NETWORK_QUALITY_OBSERVATION_SOURCE_HTTP));
+ time_delta_buffer.AddObservation(Observation<base::TimeDelta>(
+ base::TimeDelta::FromMilliseconds(i), now, INT32_MIN,
+ NETWORK_QUALITY_OBSERVATION_SOURCE_HTTP));
EXPECT_TRUE(int_buffer.GetPercentile(
- base::TimeTicks(), &result, 50,
+ base::TimeTicks(), INT32_MIN, &result, 50,
std::vector<NetworkQualityObservationSource>()));
ASSERT_EQ(static_cast<size_t>(i / 2 + 50), int_buffer.Size());
EXPECT_TRUE(time_delta_buffer.GetPercentile(
- base::TimeTicks(), &time_delta_result, 50,
+ base::TimeTicks(), INT32_MIN, &time_delta_result, 50,
std::vector<NetworkQualityObservationSource>()));
ASSERT_EQ(static_cast<size_t>(i / 2 + 50), time_delta_buffer.Size());
}
@@ -150,30 +152,30 @@ TEST(NetworkQualityObservationBufferTest, PercentileSameTimestamps) {
// what is expected due to floating point computation errors and integer
// rounding off errors.
EXPECT_TRUE(int_buffer.GetPercentile(
- base::TimeTicks(), &result, i,
+ base::TimeTicks(), INT32_MIN, &result, i,
std::vector<NetworkQualityObservationSource>()));
EXPECT_TRUE(time_delta_buffer.GetPercentile(
- base::TimeTicks(), &time_delta_result, i,
+ base::TimeTicks(), INT32_MIN, &time_delta_result, i,
std::vector<NetworkQualityObservationSource>()));
EXPECT_NEAR(result, i, 1);
EXPECT_NEAR(time_delta_result.InMilliseconds(), i, 1);
}
EXPECT_FALSE(int_buffer.GetPercentile(
- now + base::TimeDelta::FromSeconds(1), &result, 50,
+ now + base::TimeDelta::FromSeconds(1), INT32_MIN, &result, 50,
std::vector<NetworkQualityObservationSource>()));
EXPECT_FALSE(time_delta_buffer.GetPercentile(
- now + base::TimeDelta::FromSeconds(1), &time_delta_result, 50,
+ now + base::TimeDelta::FromSeconds(1), INT32_MIN, &time_delta_result, 50,
std::vector<NetworkQualityObservationSource>()));
// Percentiles should be unavailable when no observations are available.
int_buffer.Clear();
time_delta_buffer.Clear();
EXPECT_FALSE(
- int_buffer.GetPercentile(base::TimeTicks(), &result, 50,
+ int_buffer.GetPercentile(base::TimeTicks(), INT32_MIN, &result, 50,
std::vector<NetworkQualityObservationSource>()));
EXPECT_FALSE(time_delta_buffer.GetPercentile(
- base::TimeTicks(), &time_delta_result, 50,
+ base::TimeTicks(), INT32_MIN, &time_delta_result, 50,
std::vector<NetworkQualityObservationSource>()));
}
@@ -182,8 +184,8 @@ TEST(NetworkQualityObservationBufferTest, PercentileSameTimestamps) {
// of them being very recent. Percentiles should factor in recent observations
// much more heavily than older samples.
TEST(NetworkQualityObservationBufferTest, PercentileDifferentTimestamps) {
- ObservationBuffer<int32_t> int_buffer(0.5);
- ObservationBuffer<base::TimeDelta> time_delta_buffer(0.5);
+ ObservationBuffer<int32_t> int_buffer(0.5, 1.0);
+ ObservationBuffer<base::TimeDelta> time_delta_buffer(0.5, 1.0);
const base::TimeTicks now = base::TimeTicks::Now();
const base::TimeTicks very_old = now - base::TimeDelta::FromDays(7);
@@ -192,28 +194,28 @@ TEST(NetworkQualityObservationBufferTest, PercentileDifferentTimestamps) {
// Network quality should be unavailable when no observations are available.
EXPECT_FALSE(
- int_buffer.GetPercentile(base::TimeTicks(), &result, 50,
+ int_buffer.GetPercentile(base::TimeTicks(), INT32_MIN, &result, 50,
std::vector<NetworkQualityObservationSource>()));
EXPECT_FALSE(time_delta_buffer.GetPercentile(
- base::TimeTicks(), &time_delta_result, 50,
+ base::TimeTicks(), INT32_MIN, &time_delta_result, 50,
std::vector<NetworkQualityObservationSource>()));
// First 50 samples have very old timestamps.
for (int i = 1; i <= 50; ++i) {
int_buffer.AddObservation(Observation<int32_t>(
- i, very_old, NETWORK_QUALITY_OBSERVATION_SOURCE_HTTP));
+ i, very_old, INT32_MIN, NETWORK_QUALITY_OBSERVATION_SOURCE_HTTP));
time_delta_buffer.AddObservation(Observation<base::TimeDelta>(
- base::TimeDelta::FromMilliseconds(i), very_old,
+ base::TimeDelta::FromMilliseconds(i), very_old, INT32_MIN,
NETWORK_QUALITY_OBSERVATION_SOURCE_HTTP));
}
// Next 50 (i.e., from 51 to 100) have recent timestamps.
for (int i = 51; i <= 100; ++i) {
- int_buffer.AddObservation(
- Observation<int32_t>(i, now, NETWORK_QUALITY_OBSERVATION_SOURCE_HTTP));
- time_delta_buffer.AddObservation(
- Observation<base::TimeDelta>(base::TimeDelta::FromMilliseconds(i), now,
- NETWORK_QUALITY_OBSERVATION_SOURCE_HTTP));
+ int_buffer.AddObservation(Observation<int32_t>(
+ i, now, INT32_MIN, NETWORK_QUALITY_OBSERVATION_SOURCE_HTTP));
+ time_delta_buffer.AddObservation(Observation<base::TimeDelta>(
+ base::TimeDelta::FromMilliseconds(i), now, INT32_MIN,
+ NETWORK_QUALITY_OBSERVATION_SOURCE_HTTP));
}
// Older samples have very little weight. So, all percentiles are >= 51
@@ -224,23 +226,93 @@ TEST(NetworkQualityObservationBufferTest, PercentileDifferentTimestamps) {
// what is expected due to floating point computation errors and integer
// rounding off errors.
EXPECT_TRUE(int_buffer.GetPercentile(
- very_old, &result, i, std::vector<NetworkQualityObservationSource>()));
+ very_old, INT32_MIN, &result, i,
+ std::vector<NetworkQualityObservationSource>()));
EXPECT_NEAR(result, 51 + 0.49 * i, 1);
EXPECT_TRUE(time_delta_buffer.GetPercentile(
- very_old, &time_delta_result, i,
+ very_old, INT32_MIN, &time_delta_result, i,
std::vector<NetworkQualityObservationSource>()));
EXPECT_NEAR(time_delta_result.InMilliseconds(), 51 + 0.49 * i, 1);
}
EXPECT_FALSE(int_buffer.GetPercentile(
- now + base::TimeDelta::FromSeconds(1), &result, 50,
+ now + base::TimeDelta::FromSeconds(1), INT32_MIN, &result, 50,
std::vector<NetworkQualityObservationSource>()));
EXPECT_FALSE(time_delta_buffer.GetPercentile(
- now + base::TimeDelta::FromSeconds(1), &time_delta_result, 50,
+ now + base::TimeDelta::FromSeconds(1), INT32_MIN, &time_delta_result, 50,
std::vector<NetworkQualityObservationSource>()));
}
+// Verifies that the percentiles are correctly computed. All observations have
+// same timestamp with half the observations taken at low RSSI, and half the
+// observations with high RSSI. Percentiles should be computed based on the
+// current RSSI and the RSSI of the observations.
+TEST(NetworkQualityObservationBufferTest, PercentileDifferentRSSI) {
+ ObservationBuffer<int32_t> int_buffer(1.0, 0.5);
+ ObservationBuffer<base::TimeDelta> time_delta_buffer(1.0, 0.5);
+ const base::TimeTicks now = base::TimeTicks::Now();
+ int32_t high_rssi = 0;
+ int32_t low_rssi = -100;
+
+ int32_t result;
+ base::TimeDelta time_delta_result;
+
+ // Network quality should be unavailable when no observations are available.
+ EXPECT_FALSE(
+ int_buffer.GetPercentile(base::TimeTicks(), INT32_MIN, &result, 50,
+ std::vector<NetworkQualityObservationSource>()));
+ EXPECT_FALSE(time_delta_buffer.GetPercentile(
+ base::TimeTicks(), INT32_MIN, &time_delta_result, 50,
+ std::vector<NetworkQualityObservationSource>()));
+
+ // First 50 samples have very low RSSI.
+ for (int i = 1; i <= 50; ++i) {
+ int_buffer.AddObservation(Observation<int32_t>(
+ i, now, low_rssi, NETWORK_QUALITY_OBSERVATION_SOURCE_HTTP));
+ time_delta_buffer.AddObservation(Observation<base::TimeDelta>(
+ base::TimeDelta::FromMilliseconds(i), now, low_rssi,
+ NETWORK_QUALITY_OBSERVATION_SOURCE_HTTP));
+ }
+
+ // Next 50 (i.e., from 51 to 100) have high RSSI.
+ for (int i = 51; i <= 100; ++i) {
+ int_buffer.AddObservation(Observation<int32_t>(
+ i, now, high_rssi, NETWORK_QUALITY_OBSERVATION_SOURCE_HTTP));
+ time_delta_buffer.AddObservation(Observation<base::TimeDelta>(
+ base::TimeDelta::FromMilliseconds(i), now, high_rssi,
+ NETWORK_QUALITY_OBSERVATION_SOURCE_HTTP));
+ }
+
+ // When the current RSSI is |high_rssi|, higher weight should be assigned
+ // to observations that were taken at |high_rssi|.
+ for (int i = 1; i < 100; ++i) {
+ EXPECT_TRUE(int_buffer.GetPercentile(
+ now, high_rssi, &result, i,
+ std::vector<NetworkQualityObservationSource>()));
+ EXPECT_NEAR(result, 51 + 0.49 * i, 1);
+
+ EXPECT_TRUE(time_delta_buffer.GetPercentile(
+ now, high_rssi, &time_delta_result, i,
+ std::vector<NetworkQualityObservationSource>()));
+ EXPECT_NEAR(time_delta_result.InMilliseconds(), 51 + 0.49 * i, 1);
+ }
+
+ // When the current RSSI is |low_rssi|, higher weight should be assigned
+ // to observations that were taken at |low_rssi|.
+ for (int i = 1; i < 100; ++i) {
+ EXPECT_TRUE(int_buffer.GetPercentile(
+ now, low_rssi, &result, i,
+ std::vector<NetworkQualityObservationSource>()));
+ EXPECT_NEAR(result, i / 2, 1);
+
+ EXPECT_TRUE(time_delta_buffer.GetPercentile(
+ now, low_rssi, &time_delta_result, i,
+ std::vector<NetworkQualityObservationSource>()));
+ EXPECT_NEAR(time_delta_result.InMilliseconds(), i / 2, 1);
+ }
+}
+
#if !defined(OS_WIN)
// Disabled on OS_WIN since the GetUnweightedAverage() and
// GetUnweightedAverage() functions are not yet called outside tests, and so the
@@ -249,8 +321,8 @@ TEST(NetworkQualityObservationBufferTest, PercentileDifferentTimestamps) {
// functions are called outside the tests.
TEST(NetworkQualityObservationBufferTest,
UnweightedAverageDifferentTimestamps) {
- ObservationBuffer<base::TimeDelta> time_delta_buffer(0.5);
- ObservationBuffer<int32_t> int_buffer(0.5);
+ ObservationBuffer<base::TimeDelta> time_delta_buffer(0.5, 1.0);
+ ObservationBuffer<int32_t> int_buffer(0.5, 1.0);
const base::TimeTicks now = base::TimeTicks::Now();
const base::TimeTicks very_old = now - base::TimeDelta::FromDays(7);
@@ -259,52 +331,53 @@ TEST(NetworkQualityObservationBufferTest,
// Network quality should be unavailable when no observations are available.
EXPECT_FALSE(time_delta_buffer.GetUnweightedAverage(
- base::TimeTicks(), std::vector<NetworkQualityObservationSource>(),
- &time_delta_result));
+ base::TimeTicks(), INT32_MIN,
+ std::vector<NetworkQualityObservationSource>(), &time_delta_result));
EXPECT_FALSE(int_buffer.GetUnweightedAverage(
- base::TimeTicks(), std::vector<NetworkQualityObservationSource>(),
- &int_result));
+ base::TimeTicks(), INT32_MIN,
+ std::vector<NetworkQualityObservationSource>(), &int_result));
// The first 50 samples have very old timestamps.
for (int i = 1; i <= 50; ++i) {
time_delta_buffer.AddObservation(Observation<base::TimeDelta>(
- base::TimeDelta::FromMilliseconds(i), very_old,
+ base::TimeDelta::FromMilliseconds(i), very_old, INT32_MIN,
NETWORK_QUALITY_OBSERVATION_SOURCE_HTTP));
int_buffer.AddObservation(Observation<int32_t>(
- i, very_old, NETWORK_QUALITY_OBSERVATION_SOURCE_HTTP));
+ i, very_old, INT32_MIN, NETWORK_QUALITY_OBSERVATION_SOURCE_HTTP));
}
// The next 50 (i.e., from 51 to 100) samples have recent timestamps.
for (int i = 51; i <= 100; ++i) {
- time_delta_buffer.AddObservation(
- Observation<base::TimeDelta>(base::TimeDelta::FromMilliseconds(i), now,
- NETWORK_QUALITY_OBSERVATION_SOURCE_HTTP));
- int_buffer.AddObservation(
- Observation<int32_t>(i, now, NETWORK_QUALITY_OBSERVATION_SOURCE_HTTP));
+ time_delta_buffer.AddObservation(Observation<base::TimeDelta>(
+ base::TimeDelta::FromMilliseconds(i), now, INT32_MIN,
+ NETWORK_QUALITY_OBSERVATION_SOURCE_HTTP));
+ int_buffer.AddObservation(Observation<int32_t>(
+ i, now, INT32_MIN, NETWORK_QUALITY_OBSERVATION_SOURCE_HTTP));
}
// All samples have equal weight. So, the unweighted average is the average of
// all samples.
EXPECT_TRUE(time_delta_buffer.GetUnweightedAverage(
- very_old, std::vector<NetworkQualityObservationSource>(),
+ very_old, INT32_MIN, std::vector<NetworkQualityObservationSource>(),
&time_delta_result));
EXPECT_NEAR(time_delta_result.InMilliseconds(), (1 + 100) / 2, 1);
EXPECT_TRUE(int_buffer.GetUnweightedAverage(
- very_old, std::vector<NetworkQualityObservationSource>(), &int_result));
+ very_old, INT32_MIN, std::vector<NetworkQualityObservationSource>(),
+ &int_result));
EXPECT_NEAR(int_result, (1 + 100) / 2, 1);
EXPECT_FALSE(time_delta_buffer.GetUnweightedAverage(
- now + base::TimeDelta::FromSeconds(1),
+ now + base::TimeDelta::FromSeconds(1), INT32_MIN,
std::vector<NetworkQualityObservationSource>(), &time_delta_result));
EXPECT_FALSE(int_buffer.GetUnweightedAverage(
- now + base::TimeDelta::FromSeconds(1),
+ now + base::TimeDelta::FromSeconds(1), INT32_MIN,
std::vector<NetworkQualityObservationSource>(), &int_result));
}
TEST(NetworkQualityObservationBufferTest, WeightedAverageDifferentTimestamps) {
- ObservationBuffer<base::TimeDelta> time_delta_buffer(0.5);
- ObservationBuffer<int32_t> int_buffer(0.5);
+ ObservationBuffer<base::TimeDelta> time_delta_buffer(0.5, 1.0);
+ ObservationBuffer<int32_t> int_buffer(0.5, 1.0);
const base::TimeTicks now = base::TimeTicks::Now();
const base::TimeTicks very_old = now - base::TimeDelta::FromDays(7);
@@ -313,46 +386,47 @@ TEST(NetworkQualityObservationBufferTest, WeightedAverageDifferentTimestamps) {
// Network quality should be unavailable when no observations are available.
EXPECT_FALSE(time_delta_buffer.GetWeightedAverage(
- base::TimeTicks(), std::vector<NetworkQualityObservationSource>(),
- &time_delta_result));
+ base::TimeTicks(), INT32_MIN,
+ std::vector<NetworkQualityObservationSource>(), &time_delta_result));
EXPECT_FALSE(int_buffer.GetWeightedAverage(
- base::TimeTicks(), std::vector<NetworkQualityObservationSource>(),
- &int_result));
+ base::TimeTicks(), INT32_MIN,
+ std::vector<NetworkQualityObservationSource>(), &int_result));
// The first 50 samples have very old timestamps.
for (int i = 1; i <= 50; ++i) {
time_delta_buffer.AddObservation(Observation<base::TimeDelta>(
- base::TimeDelta::FromMilliseconds(i), very_old,
+ base::TimeDelta::FromMilliseconds(i), very_old, INT32_MIN,
NETWORK_QUALITY_OBSERVATION_SOURCE_HTTP));
int_buffer.AddObservation(Observation<int32_t>(
- i, very_old, NETWORK_QUALITY_OBSERVATION_SOURCE_HTTP));
+ i, very_old, INT32_MIN, NETWORK_QUALITY_OBSERVATION_SOURCE_HTTP));
}
// The next 50 (i.e., from 51 to 100) samples have recent timestamps.
for (int i = 51; i <= 100; ++i) {
- time_delta_buffer.AddObservation(
- Observation<base::TimeDelta>(base::TimeDelta::FromMilliseconds(i), now,
- NETWORK_QUALITY_OBSERVATION_SOURCE_HTTP));
- int_buffer.AddObservation(
- Observation<int32_t>(i, now, NETWORK_QUALITY_OBSERVATION_SOURCE_HTTP));
+ time_delta_buffer.AddObservation(Observation<base::TimeDelta>(
+ base::TimeDelta::FromMilliseconds(i), now, INT32_MIN,
+ NETWORK_QUALITY_OBSERVATION_SOURCE_HTTP));
+ int_buffer.AddObservation(Observation<int32_t>(
+ i, now, INT32_MIN, NETWORK_QUALITY_OBSERVATION_SOURCE_HTTP));
}
// The older samples have very little weight, and so the weighted average must
// be approximately equal to the average of all recent samples.
EXPECT_TRUE(time_delta_buffer.GetWeightedAverage(
- very_old, std::vector<NetworkQualityObservationSource>(),
+ very_old, INT32_MIN, std::vector<NetworkQualityObservationSource>(),
&time_delta_result));
EXPECT_NEAR(time_delta_result.InMilliseconds(), (51 + 100) / 2, 1);
EXPECT_TRUE(int_buffer.GetWeightedAverage(
- very_old, std::vector<NetworkQualityObservationSource>(), &int_result));
+ very_old, INT32_MIN, std::vector<NetworkQualityObservationSource>(),
+ &int_result));
EXPECT_NEAR(int_result, (51 + 100) / 2, 1);
EXPECT_FALSE(time_delta_buffer.GetWeightedAverage(
- now + base::TimeDelta::FromSeconds(1),
+ now + base::TimeDelta::FromSeconds(1), INT32_MIN,
std::vector<NetworkQualityObservationSource>(), &time_delta_result));
EXPECT_FALSE(int_buffer.GetWeightedAverage(
- now + base::TimeDelta::FromSeconds(1),
+ now + base::TimeDelta::FromSeconds(1), INT32_MIN,
std::vector<NetworkQualityObservationSource>(), &int_result));
}
#endif // !defined(OS_WIN)
@@ -360,8 +434,8 @@ TEST(NetworkQualityObservationBufferTest, WeightedAverageDifferentTimestamps) {
// Verifies that the percentiles are correctly computed when some of the
// observation sources are disallowed. All observations have the same timestamp.
TEST(NetworkQualityObservationBufferTest, DisallowedObservationSources) {
- ObservationBuffer<int32_t> int_buffer(0.5);
- ObservationBuffer<base::TimeDelta> time_delta_buffer(0.5);
+ ObservationBuffer<int32_t> int_buffer(0.5, 1.0);
+ ObservationBuffer<base::TimeDelta> time_delta_buffer(0.5, 1.0);
const base::TimeTicks now = base::TimeTicks::Now();
int32_t result;
@@ -369,43 +443,43 @@ TEST(NetworkQualityObservationBufferTest, DisallowedObservationSources) {
// Network quality should be unavailable when no observations are available.
EXPECT_FALSE(
- int_buffer.GetPercentile(base::TimeTicks(), &result, 50,
+ int_buffer.GetPercentile(base::TimeTicks(), INT32_MIN, &result, 50,
std::vector<NetworkQualityObservationSource>()));
EXPECT_FALSE(time_delta_buffer.GetPercentile(
- base::TimeTicks(), &time_delta_result, 50,
+ base::TimeTicks(), INT32_MIN, &time_delta_result, 50,
std::vector<NetworkQualityObservationSource>()));
// Insert samples from {1,2,3,..., 100}. First insert odd samples, then even
// samples. This helps in verifying that the order of samples does not matter.
for (int i = 1; i <= 99; i += 2) {
- int_buffer.AddObservation(
- Observation<int32_t>(i, now, NETWORK_QUALITY_OBSERVATION_SOURCE_HTTP));
- time_delta_buffer.AddObservation(
- Observation<base::TimeDelta>(base::TimeDelta::FromMilliseconds(i), now,
- NETWORK_QUALITY_OBSERVATION_SOURCE_HTTP));
+ int_buffer.AddObservation(Observation<int32_t>(
+ i, now, INT32_MIN, NETWORK_QUALITY_OBSERVATION_SOURCE_HTTP));
+ time_delta_buffer.AddObservation(Observation<base::TimeDelta>(
+ base::TimeDelta::FromMilliseconds(i), now, INT32_MIN,
+ NETWORK_QUALITY_OBSERVATION_SOURCE_HTTP));
}
// Add samples for TCP and QUIC observations which should not be taken into
// account when computing the percentile.
for (int i = 1; i <= 99; i += 2) {
int_buffer.AddObservation(Observation<int32_t>(
- 10000, now, NETWORK_QUALITY_OBSERVATION_SOURCE_TCP));
+ 10000, now, INT32_MIN, NETWORK_QUALITY_OBSERVATION_SOURCE_TCP));
int_buffer.AddObservation(Observation<int32_t>(
- 10000, now, NETWORK_QUALITY_OBSERVATION_SOURCE_QUIC));
+ 10000, now, INT32_MIN, NETWORK_QUALITY_OBSERVATION_SOURCE_QUIC));
time_delta_buffer.AddObservation(Observation<base::TimeDelta>(
- base::TimeDelta::FromMilliseconds(10000), now,
+ base::TimeDelta::FromMilliseconds(10000), now, INT32_MIN,
NETWORK_QUALITY_OBSERVATION_SOURCE_TCP));
time_delta_buffer.AddObservation(Observation<base::TimeDelta>(
- base::TimeDelta::FromMilliseconds(10000), now,
+ base::TimeDelta::FromMilliseconds(10000), now, INT32_MIN,
NETWORK_QUALITY_OBSERVATION_SOURCE_QUIC));
}
for (int i = 2; i <= 100; i += 2) {
- int_buffer.AddObservation(
- Observation<int32_t>(i, now, NETWORK_QUALITY_OBSERVATION_SOURCE_HTTP));
- time_delta_buffer.AddObservation(
- Observation<base::TimeDelta>(base::TimeDelta::FromMilliseconds(i), now,
- NETWORK_QUALITY_OBSERVATION_SOURCE_HTTP));
+ int_buffer.AddObservation(Observation<int32_t>(
+ i, now, INT32_MIN, NETWORK_QUALITY_OBSERVATION_SOURCE_HTTP));
+ time_delta_buffer.AddObservation(Observation<base::TimeDelta>(
+ base::TimeDelta::FromMilliseconds(i), now, INT32_MIN,
+ NETWORK_QUALITY_OBSERVATION_SOURCE_HTTP));
}
std::vector<NetworkQualityObservationSource> disallowed_observation_sources;
@@ -419,12 +493,12 @@ TEST(NetworkQualityObservationBufferTest, DisallowedObservationSources) {
// required because computed percentiles may be slightly different from
// what is expected due to floating point computation errors and integer
// rounding off errors.
- EXPECT_TRUE(int_buffer.GetPercentile(base::TimeTicks(), &result, i,
- disallowed_observation_sources));
+ EXPECT_TRUE(int_buffer.GetPercentile(base::TimeTicks(), INT32_MIN, &result,
+ i, disallowed_observation_sources));
EXPECT_NEAR(result, i, 1);
- EXPECT_TRUE(
- time_delta_buffer.GetPercentile(base::TimeTicks(), &time_delta_result,
- i, disallowed_observation_sources));
+ EXPECT_TRUE(time_delta_buffer.GetPercentile(
+ base::TimeTicks(), INT32_MIN, &time_delta_result, i,
+ disallowed_observation_sources));
EXPECT_NEAR(time_delta_result.InMilliseconds(), i, 1);
}
@@ -437,35 +511,35 @@ TEST(NetworkQualityObservationBufferTest, DisallowedObservationSources) {
// required because computed percentiles may be slightly different from
// what is expected due to floating point computation errors and integer
// rounding off errors.
- EXPECT_TRUE(int_buffer.GetPercentile(base::TimeTicks(), &result, i,
- disallowed_observation_sources));
+ EXPECT_TRUE(int_buffer.GetPercentile(base::TimeTicks(), INT32_MIN, &result,
+ i, disallowed_observation_sources));
EXPECT_NEAR(result, 10000, 1);
- EXPECT_TRUE(
- time_delta_buffer.GetPercentile(base::TimeTicks(), &time_delta_result,
- i, disallowed_observation_sources));
+ EXPECT_TRUE(time_delta_buffer.GetPercentile(
+ base::TimeTicks(), INT32_MIN, &time_delta_result, i,
+ disallowed_observation_sources));
EXPECT_NEAR(time_delta_result.InMilliseconds(), 10000, 1);
}
}
TEST(NetworkQualityObservationBufferTest, TestGetMedianRTTSince) {
- ObservationBuffer<int32_t> int_buffer(0.5);
- ObservationBuffer<base::TimeDelta> time_delta_buffer(0.5);
+ ObservationBuffer<int32_t> int_buffer(0.5, 1.0);
+ ObservationBuffer<base::TimeDelta> time_delta_buffer(0.5, 1.0);
base::TimeTicks now = base::TimeTicks::Now();
base::TimeTicks old = now - base::TimeDelta::FromMilliseconds(1);
ASSERT_NE(old, now);
// First sample has very old timestamp.
- int_buffer.AddObservation(
- Observation<int32_t>(1, old, NETWORK_QUALITY_OBSERVATION_SOURCE_HTTP));
- time_delta_buffer.AddObservation(
- Observation<base::TimeDelta>(base::TimeDelta::FromMilliseconds(1), old,
- NETWORK_QUALITY_OBSERVATION_SOURCE_HTTP));
-
- int_buffer.AddObservation(
- Observation<int32_t>(100, now, NETWORK_QUALITY_OBSERVATION_SOURCE_HTTP));
- time_delta_buffer.AddObservation(
- Observation<base::TimeDelta>(base::TimeDelta::FromMilliseconds(100), now,
- NETWORK_QUALITY_OBSERVATION_SOURCE_HTTP));
+ int_buffer.AddObservation(Observation<int32_t>(
+ 1, old, INT32_MIN, NETWORK_QUALITY_OBSERVATION_SOURCE_HTTP));
+ time_delta_buffer.AddObservation(Observation<base::TimeDelta>(
+ base::TimeDelta::FromMilliseconds(1), old, INT32_MIN,
+ NETWORK_QUALITY_OBSERVATION_SOURCE_HTTP));
+
+ int_buffer.AddObservation(Observation<int32_t>(
+ 100, now, INT32_MIN, NETWORK_QUALITY_OBSERVATION_SOURCE_HTTP));
+ time_delta_buffer.AddObservation(Observation<base::TimeDelta>(
+ base::TimeDelta::FromMilliseconds(100), now, INT32_MIN,
+ NETWORK_QUALITY_OBSERVATION_SOURCE_HTTP));
const struct {
base::TimeTicks start_timestamp;
@@ -486,12 +560,12 @@ TEST(NetworkQualityObservationBufferTest, TestGetMedianRTTSince) {
int32_t downstream_throughput_kbps;
std::vector<NetworkQualityObservationSource> disallowed_observation_sources;
- EXPECT_EQ(
- test.expect_network_quality_available,
- time_delta_buffer.GetPercentile(test.start_timestamp, &url_request_rtt,
- 50, disallowed_observation_sources));
EXPECT_EQ(test.expect_network_quality_available,
- int_buffer.GetPercentile(test.start_timestamp,
+ time_delta_buffer.GetPercentile(test.start_timestamp, INT32_MIN,
+ &url_request_rtt, 50,
+ disallowed_observation_sources));
+ EXPECT_EQ(test.expect_network_quality_available,
+ int_buffer.GetPercentile(test.start_timestamp, INT32_MIN,
&downstream_throughput_kbps, 50,
disallowed_observation_sources));
@@ -509,4 +583,4 @@ TEST(NetworkQualityObservationBufferTest, TestGetMedianRTTSince) {
} // namespace nqe
-} // namespace net \ No newline at end of file
+} // namespace net
diff --git a/chromium/net/nqe/socket_watcher.cc b/chromium/net/nqe/socket_watcher.cc
index d03b98ecf81..174c388a216 100644
--- a/chromium/net/nqe/socket_watcher.cc
+++ b/chromium/net/nqe/socket_watcher.cc
@@ -7,6 +7,7 @@
#include "base/bind.h"
#include "base/location.h"
#include "base/single_thread_task_runner.h"
+#include "base/time/tick_clock.h"
#include "base/time/time.h"
namespace net {
@@ -17,23 +18,34 @@ namespace internal {
SocketWatcher::SocketWatcher(
SocketPerformanceWatcherFactory::Protocol protocol,
+ base::TimeDelta min_notification_interval,
scoped_refptr<base::SingleThreadTaskRunner> task_runner,
- OnUpdatedRTTAvailableCallback updated_rtt_observation_callback)
+ OnUpdatedRTTAvailableCallback updated_rtt_observation_callback,
+ base::TickClock* tick_clock)
: protocol_(protocol),
task_runner_(std::move(task_runner)),
- updated_rtt_observation_callback_(updated_rtt_observation_callback) {}
+ updated_rtt_observation_callback_(updated_rtt_observation_callback),
+ rtt_notifications_minimum_interval_(min_notification_interval),
+ tick_clock_(tick_clock) {
+ DCHECK(tick_clock_);
+}
SocketWatcher::~SocketWatcher() {}
bool SocketWatcher::ShouldNotifyUpdatedRTT() const {
DCHECK(thread_checker_.CalledOnValidThread());
- return true;
+ // Do not allow incoming notifications if the last notification was more
+ // recent than |rtt_notifications_minimum_interval_| ago. This helps in
+ // reducing the overhead of obtaining the RTT values.
+ return tick_clock_->NowTicks() - last_rtt_notification_ >=
+ rtt_notifications_minimum_interval_;
}
void SocketWatcher::OnUpdatedRTTAvailable(const base::TimeDelta& rtt) {
DCHECK(thread_checker_.CalledOnValidThread());
+ last_rtt_notification_ = tick_clock_->NowTicks();
task_runner_->PostTask(
FROM_HERE, base::Bind(updated_rtt_observation_callback_, protocol_, rtt));
}
diff --git a/chromium/net/nqe/socket_watcher.h b/chromium/net/nqe/socket_watcher.h
index 25528f4bf87..9c4a578d09d 100644
--- a/chromium/net/nqe/socket_watcher.h
+++ b/chromium/net/nqe/socket_watcher.h
@@ -5,15 +5,20 @@
#ifndef NET_NQE_SOCKET_WATCHER_H_
#define NET_NQE_SOCKET_WATCHER_H_
+#include <memory>
+
#include "base/callback.h"
#include "base/memory/ref_counted.h"
#include "base/memory/weak_ptr.h"
#include "base/threading/thread_checker.h"
+#include "base/time/time.h"
+#include "net/base/net_export.h"
#include "net/socket/socket_performance_watcher.h"
#include "net/socket/socket_performance_watcher_factory.h"
namespace base {
class SingleThreadTaskRunner;
+class TickClock;
class TimeDelta;
} // namespace base
@@ -30,15 +35,19 @@ namespace nqe {
namespace internal {
// SocketWatcher implements SocketPerformanceWatcher, and is not thread-safe.
-class SocketWatcher : public SocketPerformanceWatcher {
+class NET_EXPORT_PRIVATE SocketWatcher : public SocketPerformanceWatcher {
public:
// Creates a SocketWatcher which can be used to watch a socket that uses
// |protocol| as the transport layer protocol. The socket watcher will call
// |updated_rtt_observation_callback| on |task_runner| every time a new RTT
- // observation is available.
+ // observation is available. |min_notification_interval| is the minimum
+ // interval betweeen consecutive notifications to this socket watcher.
+ // |tick_clock| is guaranteed to be non-null.
SocketWatcher(SocketPerformanceWatcherFactory::Protocol protocol,
+ base::TimeDelta min_notification_interval,
scoped_refptr<base::SingleThreadTaskRunner> task_runner,
- OnUpdatedRTTAvailableCallback updated_rtt_observation_callback);
+ OnUpdatedRTTAvailableCallback updated_rtt_observation_callback,
+ base::TickClock* tick_clock);
~SocketWatcher() override;
@@ -56,6 +65,14 @@ class SocketWatcher : public SocketPerformanceWatcher {
// Called every time a new RTT observation is available.
OnUpdatedRTTAvailableCallback updated_rtt_observation_callback_;
+ // Minimum interval betweeen consecutive incoming notifications.
+ const base::TimeDelta rtt_notifications_minimum_interval_;
+
+ // Time when this was last notified of updated RTT.
+ base::TimeTicks last_rtt_notification_;
+
+ base::TickClock* tick_clock_;
+
base::ThreadChecker thread_checker_;
DISALLOW_COPY_AND_ASSIGN(SocketWatcher);
@@ -67,4 +84,4 @@ class SocketWatcher : public SocketPerformanceWatcher {
} // namespace net
-#endif // NET_NQE_SOCKET_WATCHER_H_ \ No newline at end of file
+#endif // NET_NQE_SOCKET_WATCHER_H_
diff --git a/chromium/net/nqe/socket_watcher_factory.cc b/chromium/net/nqe/socket_watcher_factory.cc
index 88fa5a94cb2..496dd9bc74c 100644
--- a/chromium/net/nqe/socket_watcher_factory.cc
+++ b/chromium/net/nqe/socket_watcher_factory.cc
@@ -4,6 +4,7 @@
#include "net/nqe/socket_watcher_factory.h"
+#include "base/memory/ptr_util.h"
#include "base/time/time.h"
#include "net/nqe/socket_watcher.h"
@@ -15,16 +16,23 @@ namespace internal {
SocketWatcherFactory::SocketWatcherFactory(
scoped_refptr<base::SingleThreadTaskRunner> task_runner,
- OnUpdatedRTTAvailableCallback updated_rtt_observation_callback)
+ base::TimeDelta min_notification_interval,
+ OnUpdatedRTTAvailableCallback updated_rtt_observation_callback,
+ base::TickClock* tick_clock)
: task_runner_(std::move(task_runner)),
- updated_rtt_observation_callback_(updated_rtt_observation_callback) {}
+ min_notification_interval_(min_notification_interval),
+ updated_rtt_observation_callback_(updated_rtt_observation_callback),
+ tick_clock_(tick_clock) {
+ DCHECK(tick_clock_);
+}
SocketWatcherFactory::~SocketWatcherFactory() {}
std::unique_ptr<SocketPerformanceWatcher>
SocketWatcherFactory::CreateSocketPerformanceWatcher(const Protocol protocol) {
- return std::unique_ptr<SocketPerformanceWatcher>(new SocketWatcher(
- protocol, task_runner_, updated_rtt_observation_callback_));
+ return base::MakeUnique<SocketWatcher>(
+ protocol, min_notification_interval_, task_runner_,
+ updated_rtt_observation_callback_, tick_clock_);
}
} // namespace internal
diff --git a/chromium/net/nqe/socket_watcher_factory.h b/chromium/net/nqe/socket_watcher_factory.h
index 5cffb720426..e4fd23fd084 100644
--- a/chromium/net/nqe/socket_watcher_factory.h
+++ b/chromium/net/nqe/socket_watcher_factory.h
@@ -12,10 +12,12 @@
#include "base/memory/weak_ptr.h"
#include "base/single_thread_task_runner.h"
#include "base/threading/thread_checker.h"
+#include "base/time/time.h"
#include "net/socket/socket_performance_watcher.h"
#include "net/socket/socket_performance_watcher_factory.h"
namespace base {
+class TickClock;
class TimeDelta;
} // namespace base
@@ -38,9 +40,14 @@ class SocketWatcherFactory : public SocketPerformanceWatcherFactory {
// Creates a SocketWatcherFactory. All socket watchers created by
// SocketWatcherFactory call |updated_rtt_observation_callback| on
// |task_runner| every time a new RTT observation is available.
+ // |min_notification_interval| is the minimum interval betweeen consecutive
+ // notifications to the socket watchers created by this factory. |tick_clock|
+ // is guaranteed to be non-null.
SocketWatcherFactory(
scoped_refptr<base::SingleThreadTaskRunner> task_runner,
- OnUpdatedRTTAvailableCallback updated_rtt_observation_callback);
+ base::TimeDelta min_notification_interval,
+ OnUpdatedRTTAvailableCallback updated_rtt_observation_callback,
+ base::TickClock* tick_clock);
~SocketWatcherFactory() override;
@@ -51,9 +58,15 @@ class SocketWatcherFactory : public SocketPerformanceWatcherFactory {
private:
scoped_refptr<base::SingleThreadTaskRunner> task_runner_;
+ // Minimum interval betweeen consecutive notifications to the socket watchers
+ // created by this factory.
+ const base::TimeDelta min_notification_interval_;
+
// Called every time a new RTT observation is available.
OnUpdatedRTTAvailableCallback updated_rtt_observation_callback_;
+ base::TickClock* tick_clock_;
+
DISALLOW_COPY_AND_ASSIGN(SocketWatcherFactory);
};
diff --git a/chromium/net/nqe/socket_watcher_unittest.cc b/chromium/net/nqe/socket_watcher_unittest.cc
new file mode 100644
index 00000000000..e2eab8f6d37
--- /dev/null
+++ b/chromium/net/nqe/socket_watcher_unittest.cc
@@ -0,0 +1,57 @@
+// Copyright 2017 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.
+
+#include "net/nqe/socket_watcher.h"
+
+#include "base/bind.h"
+#include "base/test/simple_test_tick_clock.h"
+#include "base/threading/thread_task_runner_handle.h"
+#include "base/time/time.h"
+#include "net/socket/socket_performance_watcher.h"
+#include "net/socket/socket_performance_watcher_factory.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace net {
+
+namespace nqe {
+
+namespace internal {
+
+namespace {
+
+void OnUpdatedRTTAvailable(SocketPerformanceWatcherFactory::Protocol protocol,
+ const base::TimeDelta& rtt) {}
+
+// Verify that the buffer size is never exceeded.
+TEST(NetworkQualitySocketWatcherTest, NotificationsThrottled) {
+ base::SimpleTestTickClock tick_clock;
+ tick_clock.SetNowTicks(base::TimeTicks::Now());
+
+ SocketWatcher socket_watcher(SocketPerformanceWatcherFactory::PROTOCOL_QUIC,
+ base::TimeDelta::FromMilliseconds(2000),
+ base::ThreadTaskRunnerHandle::Get(),
+ base::Bind(OnUpdatedRTTAvailable), &tick_clock);
+
+ EXPECT_TRUE(socket_watcher.ShouldNotifyUpdatedRTT());
+ socket_watcher.OnUpdatedRTTAvailable(base::TimeDelta::FromSeconds(10));
+
+ EXPECT_FALSE(socket_watcher.ShouldNotifyUpdatedRTT());
+
+ tick_clock.Advance(base::TimeDelta::FromMilliseconds(1000));
+ // Minimum interval between consecutive notifications is 2000 msec.
+ EXPECT_FALSE(socket_watcher.ShouldNotifyUpdatedRTT());
+
+ // Advance the clock by 1000 msec more so that the current time is at least
+ // 2000 msec more than the last time |socket_watcher| received a notification.
+ tick_clock.Advance(base::TimeDelta::FromMilliseconds(1000));
+ EXPECT_TRUE(socket_watcher.ShouldNotifyUpdatedRTT());
+}
+
+} // namespace
+
+} // namespace internal
+
+} // namespace nqe
+
+} // namespace net \ No newline at end of file
diff --git a/chromium/net/nqe/throughput_analyzer.cc b/chromium/net/nqe/throughput_analyzer.cc
index 716613f4dd1..6785d143805 100644
--- a/chromium/net/nqe/throughput_analyzer.cc
+++ b/chromium/net/nqe/throughput_analyzer.cc
@@ -296,4 +296,4 @@ void ThroughputAnalyzer::BoundRequestsSize() {
} // namespace nqe
-} // namespace net \ No newline at end of file
+} // namespace net
diff --git a/chromium/net/nqe/throughput_analyzer.h b/chromium/net/nqe/throughput_analyzer.h
index a93be45d96f..e94102ba6f4 100644
--- a/chromium/net/nqe/throughput_analyzer.h
+++ b/chromium/net/nqe/throughput_analyzer.h
@@ -184,4 +184,4 @@ class NET_EXPORT_PRIVATE ThroughputAnalyzer {
} // namespace net
-#endif // NET_NQE_THROUGHPUT_ANALYZER_H_ \ No newline at end of file
+#endif // NET_NQE_THROUGHPUT_ANALYZER_H_
diff --git a/chromium/net/nqe/weighted_observation.h b/chromium/net/nqe/weighted_observation.h
index 287442a0229..334039fa90a 100644
--- a/chromium/net/nqe/weighted_observation.h
+++ b/chromium/net/nqe/weighted_observation.h
@@ -52,4 +52,4 @@ struct NET_EXPORT_PRIVATE WeightedObservation {
} // namespace net
-#endif // NET_NQE_WEIGHTED_OBSERVATION_H_ \ No newline at end of file
+#endif // NET_NQE_WEIGHTED_OBSERVATION_H_
diff --git a/chromium/net/proxy/dhcp_proxy_script_fetcher.h b/chromium/net/proxy/dhcp_proxy_script_fetcher.h
index 2d33e2fe785..a85234dcc61 100644
--- a/chromium/net/proxy/dhcp_proxy_script_fetcher.h
+++ b/chromium/net/proxy/dhcp_proxy_script_fetcher.h
@@ -2,8 +2,8 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#ifndef NET_PROXY_DHCP_SCRIPT_FETCHER_H_
-#define NET_PROXY_DHCP_SCRIPT_FETCHER_H_
+#ifndef NET_PROXY_DHCP_PROXY_SCRIPT_FETCHER_H_
+#define NET_PROXY_DHCP_PROXY_SCRIPT_FETCHER_H_
#include "base/compiler_specific.h"
#include "base/macros.h"
@@ -97,4 +97,4 @@ class NET_EXPORT_PRIVATE DoNothingDhcpProxyScriptFetcher
} // namespace net
-#endif // NET_PROXY_DHCP_SCRIPT_FETCHER_H_
+#endif // NET_PROXY_DHCP_PROXY_SCRIPT_FETCHER_H_
diff --git a/chromium/net/proxy/dhcp_proxy_script_fetcher_factory.h b/chromium/net/proxy/dhcp_proxy_script_fetcher_factory.h
index 46d3845c133..bad2d9d9ff7 100644
--- a/chromium/net/proxy/dhcp_proxy_script_fetcher_factory.h
+++ b/chromium/net/proxy/dhcp_proxy_script_fetcher_factory.h
@@ -2,8 +2,8 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#ifndef NET_PROXY_DHCP_SCRIPT_FETCHER_FACTORY_H_
-#define NET_PROXY_DHCP_SCRIPT_FETCHER_FACTORY_H_
+#ifndef NET_PROXY_DHCP_PROXY_SCRIPT_FETCHER_FACTORY_H_
+#define NET_PROXY_DHCP_PROXY_SCRIPT_FETCHER_FACTORY_H_
#include <memory>
@@ -68,4 +68,4 @@ class NET_EXPORT DhcpProxyScriptFetcherFactory {
} // namespace net
-#endif // NET_PROXY_DHCP_SCRIPT_FETCHER_FACTORY_H_
+#endif // NET_PROXY_DHCP_PROXY_SCRIPT_FETCHER_FACTORY_H_
diff --git a/chromium/net/proxy/dhcpcsvc_init_win.h b/chromium/net/proxy/dhcpcsvc_init_win.h
index 39bdf24c10c..ec72d412169 100644
--- a/chromium/net/proxy/dhcpcsvc_init_win.h
+++ b/chromium/net/proxy/dhcpcsvc_init_win.h
@@ -1,8 +1,9 @@
// Copyright (c) 2011 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.
-#ifndef NET_PROXY_DHCPCSVC_INIT_WIN_H
-#define NET_PROXY_DHCPCSVC_INIT_WIN_H
+
+#ifndef NET_PROXY_DHCPCSVC_INIT_WIN_H_
+#define NET_PROXY_DHCPCSVC_INIT_WIN_H_
namespace net {
@@ -16,4 +17,4 @@ void EnsureDhcpcsvcInit();
} // namespace net
-#endif // NET_PROXY_DHCPCSVC_INIT_WIN_H
+#endif // NET_PROXY_DHCPCSVC_INIT_WIN_H_
diff --git a/chromium/net/proxy/in_process_mojo_proxy_resolver_factory.cc b/chromium/net/proxy/in_process_mojo_proxy_resolver_factory.cc
deleted file mode 100644
index 5c3920a005b..00000000000
--- a/chromium/net/proxy/in_process_mojo_proxy_resolver_factory.cc
+++ /dev/null
@@ -1,38 +0,0 @@
-// Copyright 2015 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.
-
-#include "net/proxy/in_process_mojo_proxy_resolver_factory.h"
-
-#include <utility>
-
-#include "base/memory/singleton.h"
-#include "mojo/public/cpp/bindings/strong_binding.h"
-#include "net/proxy/mojo_proxy_resolver_factory_impl.h"
-
-namespace net {
-
-// static
-InProcessMojoProxyResolverFactory*
-InProcessMojoProxyResolverFactory::GetInstance() {
- return base::Singleton<InProcessMojoProxyResolverFactory>::get();
-}
-
-InProcessMojoProxyResolverFactory::InProcessMojoProxyResolverFactory() {
- mojo::MakeStrongBinding(base::MakeUnique<MojoProxyResolverFactoryImpl>(),
- mojo::GetProxy(&factory_));
-}
-
-InProcessMojoProxyResolverFactory::~InProcessMojoProxyResolverFactory() =
- default;
-
-std::unique_ptr<base::ScopedClosureRunner>
-InProcessMojoProxyResolverFactory::CreateResolver(
- const std::string& pac_script,
- mojo::InterfaceRequest<interfaces::ProxyResolver> req,
- interfaces::ProxyResolverFactoryRequestClientPtr client) {
- factory_->CreateResolver(pac_script, std::move(req), std::move(client));
- return nullptr;
-}
-
-} // namespace net
diff --git a/chromium/net/proxy/in_process_mojo_proxy_resolver_factory.h b/chromium/net/proxy/in_process_mojo_proxy_resolver_factory.h
deleted file mode 100644
index d7b7265388f..00000000000
--- a/chromium/net/proxy/in_process_mojo_proxy_resolver_factory.h
+++ /dev/null
@@ -1,43 +0,0 @@
-// Copyright 2015 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.
-
-#ifndef NET_PROXY_IN_PROCESS_MOJO_PROXY_RESOLVER_FACTORY_H_
-#define NET_PROXY_IN_PROCESS_MOJO_PROXY_RESOLVER_FACTORY_H_
-
-#include "base/macros.h"
-#include "net/proxy/mojo_proxy_resolver_factory.h"
-
-namespace base {
-template <typename T>
-struct DefaultSingletonTraits;
-}
-
-namespace net {
-
-// Factory to connect to an in-process Mojo proxy resolver service.
-// NOTE: This is intended to be temporary for debugging purposes and will be
-// removed when we're confident with the out-of-process implementation.
-class InProcessMojoProxyResolverFactory : public MojoProxyResolverFactory {
- public:
- static InProcessMojoProxyResolverFactory* GetInstance();
-
- // Overridden from MojoProxyResolverFactory:
- std::unique_ptr<base::ScopedClosureRunner> CreateResolver(
- const std::string& pac_script,
- mojo::InterfaceRequest<interfaces::ProxyResolver> req,
- interfaces::ProxyResolverFactoryRequestClientPtr client) override;
-
- private:
- InProcessMojoProxyResolverFactory();
- ~InProcessMojoProxyResolverFactory() override;
- friend struct base::DefaultSingletonTraits<InProcessMojoProxyResolverFactory>;
-
- interfaces::ProxyResolverFactoryPtr factory_;
-
- DISALLOW_COPY_AND_ASSIGN(InProcessMojoProxyResolverFactory);
-};
-
-} // namespace net
-
-#endif // NET_PROXY_IN_PROCESS_MOJO_PROXY_RESOLVER_FACTORY_H_
diff --git a/chromium/net/proxy/mojo_proxy_resolver_factory_impl.h b/chromium/net/proxy/mojo_proxy_resolver_factory_impl.h
index 25f6c0cf590..ca29f425bc4 100644
--- a/chromium/net/proxy/mojo_proxy_resolver_factory_impl.h
+++ b/chromium/net/proxy/mojo_proxy_resolver_factory_impl.h
@@ -12,8 +12,6 @@
#include "net/interfaces/proxy_resolver_service.mojom.h"
namespace net {
-class HostResolver;
-class ProxyResolverErrorObserver;
class ProxyResolverV8TracingFactory;
class MojoProxyResolverFactoryImpl : public interfaces::ProxyResolverFactory {
diff --git a/chromium/net/proxy/mojo_proxy_resolver_factory_impl_unittest.cc b/chromium/net/proxy/mojo_proxy_resolver_factory_impl_unittest.cc
index a266131f7bd..945e9e55a01 100644
--- a/chromium/net/proxy/mojo_proxy_resolver_factory_impl_unittest.cc
+++ b/chromium/net/proxy/mojo_proxy_resolver_factory_impl_unittest.cc
@@ -101,7 +101,7 @@ class MojoProxyResolverFactoryImplTest
mock_factory_ = new TestProxyResolverFactory(&waiter_);
mojo::MakeStrongBinding(base::MakeUnique<MojoProxyResolverFactoryImpl>(
base::WrapUnique(mock_factory_)),
- mojo::GetProxy(&factory_));
+ mojo::MakeRequest(&factory_));
}
void OnConnectionError() { waiter_.NotifyEvent(CONNECTION_ERROR); }
@@ -135,8 +135,8 @@ TEST_F(MojoProxyResolverFactoryImplTest, DisconnectProxyResolverClient) {
interfaces::ProxyResolverPtr proxy_resolver;
interfaces::ProxyResolverFactoryRequestClientPtr client_ptr;
mojo::Binding<ProxyResolverFactoryRequestClient> client_binding(
- this, mojo::GetProxy(&client_ptr));
- factory_->CreateResolver(kScriptData, mojo::GetProxy(&proxy_resolver),
+ this, mojo::MakeRequest(&client_ptr));
+ factory_->CreateResolver(kScriptData, mojo::MakeRequest(&proxy_resolver),
std::move(client_ptr));
proxy_resolver.set_connection_error_handler(
base::Bind(&MojoProxyResolverFactoryImplTest::OnConnectionError,
@@ -162,8 +162,8 @@ TEST_F(MojoProxyResolverFactoryImplTest, Error) {
interfaces::ProxyResolverPtr proxy_resolver;
interfaces::ProxyResolverFactoryRequestClientPtr client_ptr;
mojo::Binding<ProxyResolverFactoryRequestClient> client_binding(
- this, mojo::GetProxy(&client_ptr));
- factory_->CreateResolver(kScriptData, mojo::GetProxy(&proxy_resolver),
+ this, mojo::MakeRequest(&client_ptr));
+ factory_->CreateResolver(kScriptData, mojo::MakeRequest(&proxy_resolver),
std::move(client_ptr));
proxy_resolver.set_connection_error_handler(
base::Bind(&MojoProxyResolverFactoryImplTest::OnConnectionError,
@@ -183,8 +183,8 @@ TEST_F(MojoProxyResolverFactoryImplTest,
interfaces::ProxyResolverPtr proxy_resolver;
interfaces::ProxyResolverFactoryRequestClientPtr client_ptr;
mojo::Binding<ProxyResolverFactoryRequestClient> client_binding(
- this, mojo::GetProxy(&client_ptr));
- factory_->CreateResolver(kScriptData, mojo::GetProxy(&proxy_resolver),
+ this, mojo::MakeRequest(&client_ptr));
+ factory_->CreateResolver(kScriptData, mojo::MakeRequest(&proxy_resolver),
std::move(client_ptr));
proxy_resolver.set_connection_error_handler(
base::Bind(&MojoProxyResolverFactoryImplTest::OnConnectionError,
@@ -201,8 +201,8 @@ TEST_F(MojoProxyResolverFactoryImplTest,
interfaces::ProxyResolverPtr proxy_resolver;
interfaces::ProxyResolverFactoryRequestClientPtr client_ptr;
mojo::Binding<ProxyResolverFactoryRequestClient> client_binding(
- this, mojo::GetProxy(&client_ptr));
- factory_->CreateResolver(kScriptData, mojo::GetProxy(&proxy_resolver),
+ this, mojo::MakeRequest(&client_ptr));
+ factory_->CreateResolver(kScriptData, mojo::MakeRequest(&proxy_resolver),
std::move(client_ptr));
proxy_resolver.set_connection_error_handler(
base::Bind(&MojoProxyResolverFactoryImplTest::OnConnectionError,
diff --git a/chromium/net/proxy/mojo_proxy_resolver_impl_unittest.cc b/chromium/net/proxy/mojo_proxy_resolver_impl_unittest.cc
index 0022478283f..87a6427c33b 100644
--- a/chromium/net/proxy/mojo_proxy_resolver_impl_unittest.cc
+++ b/chromium/net/proxy/mojo_proxy_resolver_impl_unittest.cc
@@ -8,6 +8,7 @@
#include <utility>
#include <vector>
+#include "base/memory/ptr_util.h"
#include "base/run_loop.h"
#include "mojo/public/cpp/bindings/binding.h"
#include "net/base/net_errors.h"
@@ -208,7 +209,7 @@ class MojoProxyResolverImplTest : public testing::Test {
TEST_F(MojoProxyResolverImplTest, GetProxyForUrl) {
interfaces::ProxyResolverRequestClientPtr client_ptr;
- TestRequestClient client(mojo::GetProxy(&client_ptr));
+ TestRequestClient client(mojo::MakeRequest(&client_ptr));
resolver_->GetProxyForUrl(GURL(GURL("http://example.com")),
std::move(client_ptr));
@@ -255,7 +256,7 @@ TEST_F(MojoProxyResolverImplTest, GetProxyForUrl) {
TEST_F(MojoProxyResolverImplTest, GetProxyForUrlFailure) {
interfaces::ProxyResolverRequestClientPtr client_ptr;
- TestRequestClient client(mojo::GetProxy(&client_ptr));
+ TestRequestClient client(mojo::MakeRequest(&client_ptr));
resolver_->GetProxyForUrl(GURL("http://example.com"), std::move(client_ptr));
ASSERT_EQ(1u, mock_proxy_resolver_->pending_jobs().size());
@@ -273,9 +274,9 @@ TEST_F(MojoProxyResolverImplTest, GetProxyForUrlFailure) {
TEST_F(MojoProxyResolverImplTest, GetProxyForUrlMultiple) {
interfaces::ProxyResolverRequestClientPtr client_ptr1;
- TestRequestClient client1(mojo::GetProxy(&client_ptr1));
+ TestRequestClient client1(mojo::MakeRequest(&client_ptr1));
interfaces::ProxyResolverRequestClientPtr client_ptr2;
- TestRequestClient client2(mojo::GetProxy(&client_ptr2));
+ TestRequestClient client2(mojo::MakeRequest(&client_ptr2));
resolver_->GetProxyForUrl(GURL("http://example.com"), std::move(client_ptr1));
resolver_->GetProxyForUrl(GURL("https://example.com"),
@@ -316,7 +317,7 @@ TEST_F(MojoProxyResolverImplTest, GetProxyForUrlMultiple) {
TEST_F(MojoProxyResolverImplTest, DestroyClient) {
interfaces::ProxyResolverRequestClientPtr client_ptr;
std::unique_ptr<TestRequestClient> client(
- new TestRequestClient(mojo::GetProxy(&client_ptr)));
+ new TestRequestClient(mojo::MakeRequest(&client_ptr)));
resolver_->GetProxyForUrl(GURL("http://example.com"), std::move(client_ptr));
ASSERT_EQ(1u, mock_proxy_resolver_->pending_jobs().size());
@@ -330,7 +331,7 @@ TEST_F(MojoProxyResolverImplTest, DestroyClient) {
TEST_F(MojoProxyResolverImplTest, DestroyService) {
interfaces::ProxyResolverRequestClientPtr client_ptr;
- TestRequestClient client(mojo::GetProxy(&client_ptr));
+ TestRequestClient client(mojo::MakeRequest(&client_ptr));
resolver_->GetProxyForUrl(GURL("http://example.com"), std::move(client_ptr));
ASSERT_EQ(1u, mock_proxy_resolver_->pending_jobs().size());
diff --git a/chromium/net/proxy/proxy_config_service_linux.cc b/chromium/net/proxy/proxy_config_service_linux.cc
index 71d43a1706e..f0f03dc42ab 100644
--- a/chromium/net/proxy/proxy_config_service_linux.cc
+++ b/chromium/net/proxy/proxy_config_service_linux.cc
@@ -1548,7 +1548,7 @@ ProxyConfigServiceLinux::Delegate::Delegate(
// We have to load symbols and check the GNOME version in use to decide
// if we should use the gsettings getter. See LoadAndCheckVersion().
if (gs_getter->LoadAndCheckVersion(env_var_getter_.get()))
- setting_getter_.reset(gs_getter.release());
+ setting_getter_ = std::move(gs_getter);
}
#endif
#if defined(USE_GCONF)
diff --git a/chromium/net/proxy/proxy_resolver_factory_mojo.cc b/chromium/net/proxy/proxy_resolver_factory_mojo.cc
index 948328bca58..222e884e405 100644
--- a/chromium/net/proxy/proxy_resolver_factory_mojo.cc
+++ b/chromium/net/proxy/proxy_resolver_factory_mojo.cc
@@ -11,6 +11,7 @@
#include "base/callback.h"
#include "base/logging.h"
#include "base/macros.h"
+#include "base/memory/ptr_util.h"
#include "base/stl_util.h"
#include "base/strings/utf_string_conversions.h"
#include "base/threading/thread_checker.h"
@@ -305,7 +306,8 @@ class ProxyResolverFactoryMojo::Job
binding_(this),
error_observer_(std::move(error_observer)) {
on_delete_callback_runner_ = factory_->mojo_proxy_factory_->CreateResolver(
- base::UTF16ToUTF8(pac_script->utf16()), mojo::GetProxy(&resolver_ptr_),
+ base::UTF16ToUTF8(pac_script->utf16()),
+ mojo::MakeRequest(&resolver_ptr_),
binding_.CreateInterfacePtrAndBind());
resolver_ptr_.set_connection_error_handler(
base::Bind(&ProxyResolverFactoryMojo::Job::OnConnectionError,
diff --git a/chromium/net/proxy/proxy_resolver_factory_mojo_unittest.cc b/chromium/net/proxy/proxy_resolver_factory_mojo_unittest.cc
index a53bbd034e3..29ba63060f9 100644
--- a/chromium/net/proxy/proxy_resolver_factory_mojo_unittest.cc
+++ b/chromium/net/proxy/proxy_resolver_factory_mojo_unittest.cc
@@ -279,7 +279,7 @@ void MockMojoProxyResolver::GetProxyForUrl(
auto request = base::MakeUnique<HostResolver::RequestInfo>(
HostPortPair(url.spec(), 12345));
interfaces::HostResolverRequestClientPtr dns_client;
- mojo::GetProxy(&dns_client);
+ mojo::MakeRequest(&dns_client);
client->ResolveDns(std::move(request), std::move(dns_client));
blocked_clients_.push_back(
base::MakeUnique<interfaces::ProxyResolverRequestClientPtr>(
@@ -447,7 +447,7 @@ void MockMojoProxyResolverFactory::CreateResolver(
auto request = base::MakeUnique<HostResolver::RequestInfo>(
HostPortPair(pac_script, 12345));
interfaces::HostResolverRequestClientPtr dns_client;
- mojo::GetProxy(&dns_client);
+ mojo::MakeRequest(&dns_client);
client->ResolveDns(std::move(request), std::move(dns_client));
blocked_clients_.push_back(
base::MakeUnique<interfaces::ProxyResolverFactoryRequestClientPtr>(
@@ -523,7 +523,7 @@ class ProxyResolverFactoryMojoTest : public testing::Test,
public:
void SetUp() override {
mock_proxy_resolver_factory_.reset(new MockMojoProxyResolverFactory(
- &mock_proxy_resolver_, mojo::GetProxy(&factory_ptr_)));
+ &mock_proxy_resolver_, mojo::MakeRequest(&factory_ptr_)));
proxy_resolver_factory_mojo_.reset(new ProxyResolverFactoryMojo(
this, &host_resolver_,
base::Callback<std::unique_ptr<ProxyResolverErrorObserver>()>(),
@@ -827,6 +827,9 @@ TEST_F(ProxyResolverFactoryMojoTest, GetProxyForURL_Disconnect) {
EXPECT_TRUE(request->results().is_empty());
}
+ // Run Watcher::OnHandleReady() tasks posted by Watcher::CallOnHandleReady().
+ base::RunLoop().RunUntilIdle();
+
{
// Calling GetProxyForURL after a disconnect should fail.
std::unique_ptr<Request> request(MakeRequest(GURL(kExampleUrl)));
diff --git a/chromium/net/proxy/proxy_resolver_v8.cc b/chromium/net/proxy/proxy_resolver_v8.cc
index 16ad61f7424..a54fa69d0b5 100644
--- a/chromium/net/proxy/proxy_resolver_v8.cc
+++ b/chromium/net/proxy/proxy_resolver_v8.cc
@@ -18,6 +18,7 @@
#include "base/strings/string_util.h"
#include "base/strings/utf_string_conversions.h"
#include "base/synchronization/lock.h"
+#include "base/threading/thread_task_runner_handle.h"
#include "gin/array_buffer.h"
#include "gin/public/isolate_holder.h"
#include "gin/v8_initializer.h"
@@ -391,7 +392,8 @@ class SharedIsolateFactory {
has_initialized_v8_ = true;
}
- holder_.reset(new gin::IsolateHolder(gin::IsolateHolder::kUseLocker));
+ holder_.reset(new gin::IsolateHolder(base::ThreadTaskRunnerHandle::Get(),
+ gin::IsolateHolder::kUseLocker));
}
return holder_->isolate();
diff --git a/chromium/net/proxy/proxy_resolver_v8_tracing.cc b/chromium/net/proxy/proxy_resolver_v8_tracing.cc
index 57cbfb04ebc..1019e841da7 100644
--- a/chromium/net/proxy/proxy_resolver_v8_tracing.cc
+++ b/chromium/net/proxy/proxy_resolver_v8_tracing.cc
@@ -23,6 +23,7 @@
#include "net/base/address_list.h"
#include "net/base/net_errors.h"
#include "net/base/network_interfaces.h"
+#include "net/base/trace_constants.h"
#include "net/dns/host_resolver.h"
#include "net/log/net_log_with_source.h"
#include "net/proxy/proxy_info.h"
@@ -562,7 +563,7 @@ void Job::ExecuteNonBlocking() {
}
int Job::ExecuteProxyResolver() {
- TRACE_EVENT0("net", "Job::ExecuteProxyResolver");
+ TRACE_EVENT0(kNetTracingCategory, "Job::ExecuteProxyResolver");
int result = ERR_UNEXPECTED; // Initialized to silence warnings.
switch (operation_) {
diff --git a/chromium/net/proxy/proxy_script_decider.h b/chromium/net/proxy/proxy_script_decider.h
index 7e4177b0f73..c4139087d7e 100644
--- a/chromium/net/proxy/proxy_script_decider.h
+++ b/chromium/net/proxy/proxy_script_decider.h
@@ -33,7 +33,6 @@ namespace net {
class DhcpProxyScriptFetcher;
class NetLog;
class NetLogCaptureMode;
-class NetLogParameter;
class ProxyResolver;
class ProxyScriptFetcher;
diff --git a/chromium/net/proxy/proxy_service.h b/chromium/net/proxy/proxy_service.h
index c5ae5a54aa4..71ab1100bc3 100644
--- a/chromium/net/proxy/proxy_service.h
+++ b/chromium/net/proxy/proxy_service.h
@@ -36,14 +36,12 @@ class TimeDelta;
namespace net {
class DhcpProxyScriptFetcher;
-class HostResolver;
class NetLog;
class NetLogWithSource;
class ProxyDelegate;
class ProxyResolver;
class ProxyResolverFactory;
class ProxyResolverScriptData;
-class ProxyScriptDecider;
class ProxyScriptFetcher;
// This class can be used to resolve the proxy server to use when loading a
diff --git a/chromium/net/proxy/proxy_service_mojo.cc b/chromium/net/proxy/proxy_service_mojo.cc
index 65bdf2c8642..4c8d41e4593 100644
--- a/chromium/net/proxy/proxy_service_mojo.cc
+++ b/chromium/net/proxy/proxy_service_mojo.cc
@@ -12,9 +12,7 @@
#include "base/threading/thread_task_runner_handle.h"
#include "net/dns/mojo_host_resolver_impl.h"
#include "net/interfaces/proxy_resolver_service.mojom.h"
-#include "net/proxy/in_process_mojo_proxy_resolver_factory.h"
#include "net/proxy/mojo_proxy_resolver_factory.h"
-#include "net/proxy/mojo_proxy_resolver_impl.h"
#include "net/proxy/network_delegate_error_observer.h"
#include "net/proxy/proxy_resolver_factory.h"
#include "net/proxy/proxy_resolver_factory_mojo.h"
@@ -52,18 +50,4 @@ std::unique_ptr<ProxyService> CreateProxyServiceUsingMojoFactory(
return proxy_service;
}
-std::unique_ptr<ProxyService> CreateProxyServiceUsingMojoInProcess(
- std::unique_ptr<ProxyConfigService> proxy_config_service,
- ProxyScriptFetcher* proxy_script_fetcher,
- std::unique_ptr<DhcpProxyScriptFetcher> dhcp_proxy_script_fetcher,
- HostResolver* host_resolver,
- NetLog* net_log,
- NetworkDelegate* network_delegate) {
- return CreateProxyServiceUsingMojoFactory(
- InProcessMojoProxyResolverFactory::GetInstance(),
- std::move(proxy_config_service), proxy_script_fetcher,
- std::move(dhcp_proxy_script_fetcher), host_resolver, net_log,
- network_delegate);
-}
-
} // namespace net
diff --git a/chromium/net/proxy/proxy_service_mojo.h b/chromium/net/proxy/proxy_service_mojo.h
index 32a08730574..403b9dee3dd 100644
--- a/chromium/net/proxy/proxy_service_mojo.h
+++ b/chromium/net/proxy/proxy_service_mojo.h
@@ -10,9 +10,6 @@
#include "net/proxy/dhcp_proxy_script_fetcher.h"
namespace net {
-namespace interfaces {
-class ProxyResolverFactory;
-}
class HostResolver;
class MojoProxyResolverFactory;
@@ -44,22 +41,6 @@ std::unique_ptr<ProxyService> CreateProxyServiceUsingMojoFactory(
NetLog* net_log,
NetworkDelegate* network_delegate);
-// Creates a proxy service that connects to an in-process Mojo proxy resolver
-// service. See above for information about other arguments.
-//
-// ##########################################################################
-// # See the warnings in net/proxy/proxy_resolver_v8.h describing the
-// # multi-threading model. In order for this to be safe to use, *ALL* the
-// # other V8's running in the process must use v8::Locker.
-// ##########################################################################
-std::unique_ptr<ProxyService> CreateProxyServiceUsingMojoInProcess(
- std::unique_ptr<ProxyConfigService> proxy_config_service,
- ProxyScriptFetcher* proxy_script_fetcher,
- std::unique_ptr<DhcpProxyScriptFetcher> dhcp_proxy_script_fetcher,
- HostResolver* host_resolver,
- NetLog* net_log,
- NetworkDelegate* network_delegate);
-
} // namespace net
#endif // NET_PROXY_PROXY_SERVICE_MOJO_H_
diff --git a/chromium/net/proxy/proxy_service_mojo_unittest.cc b/chromium/net/proxy/proxy_service_mojo_unittest.cc
index ec8c999f0f0..d2b3526f540 100644
--- a/chromium/net/proxy/proxy_service_mojo_unittest.cc
+++ b/chromium/net/proxy/proxy_service_mojo_unittest.cc
@@ -11,8 +11,10 @@
#include "base/callback_helpers.h"
#include "base/memory/ptr_util.h"
+#include "base/memory/singleton.h"
#include "base/strings/utf_string_conversions.h"
#include "base/values.h"
+#include "mojo/public/cpp/bindings/strong_binding.h"
#include "net/base/network_delegate_impl.h"
#include "net/base/test_completion_callback.h"
#include "net/dns/mock_host_resolver.h"
@@ -21,9 +23,9 @@
#include "net/log/test_net_log.h"
#include "net/log/test_net_log_entry.h"
#include "net/proxy/dhcp_proxy_script_fetcher.h"
-#include "net/proxy/in_process_mojo_proxy_resolver_factory.h"
#include "net/proxy/mock_proxy_script_fetcher.h"
#include "net/proxy/mojo_proxy_resolver_factory.h"
+#include "net/proxy/mojo_proxy_resolver_factory_impl.h"
#include "net/proxy/proxy_config_service_fixed.h"
#include "net/proxy/proxy_service.h"
#include "net/test/event_waiter.h"
@@ -122,6 +124,34 @@ class LoggingMockHostResolver : public MockHostResolver {
}
};
+class InProcessMojoProxyResolverFactory : public MojoProxyResolverFactory {
+ public:
+ static InProcessMojoProxyResolverFactory* GetInstance() {
+ return base::Singleton<InProcessMojoProxyResolverFactory>::get();
+ }
+
+ // Overridden from MojoProxyResolverFactory:
+ std::unique_ptr<base::ScopedClosureRunner> CreateResolver(
+ const std::string& pac_script,
+ mojo::InterfaceRequest<interfaces::ProxyResolver> req,
+ interfaces::ProxyResolverFactoryRequestClientPtr client) override {
+ factory_->CreateResolver(pac_script, std::move(req), std::move(client));
+ return nullptr;
+ }
+
+ private:
+ InProcessMojoProxyResolverFactory() {
+ mojo::MakeStrongBinding(base::MakeUnique<MojoProxyResolverFactoryImpl>(),
+ mojo::MakeRequest(&factory_));
+ }
+ ~InProcessMojoProxyResolverFactory() override = default;
+ friend struct base::DefaultSingletonTraits<InProcessMojoProxyResolverFactory>;
+
+ interfaces::ProxyResolverFactoryPtr factory_;
+
+ DISALLOW_COPY_AND_ASSIGN(InProcessMojoProxyResolverFactory);
+};
+
} // namespace
class ProxyServiceMojoTest : public testing::Test,
diff --git a/chromium/net/quic/chromium/bidirectional_stream_quic_impl.cc b/chromium/net/quic/chromium/bidirectional_stream_quic_impl.cc
index be891760c3c..b4aaa5335e0 100644
--- a/chromium/net/quic/chromium/bidirectional_stream_quic_impl.cc
+++ b/chromium/net/quic/chromium/bidirectional_stream_quic_impl.cc
@@ -9,6 +9,7 @@
#include "base/bind.h"
#include "base/location.h"
#include "base/logging.h"
+#include "base/threading/thread_task_runner_handle.h"
#include "base/timer/timer.h"
#include "net/http/bidirectional_stream_request_info.h"
#include "net/quic/core/quic_connection.h"
diff --git a/chromium/net/quic/chromium/bidirectional_stream_quic_impl.h b/chromium/net/quic/chromium/bidirectional_stream_quic_impl.h
index ee718f35913..a6f661450e8 100644
--- a/chromium/net/quic/chromium/bidirectional_stream_quic_impl.h
+++ b/chromium/net/quic/chromium/bidirectional_stream_quic_impl.h
@@ -2,8 +2,8 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#ifndef NET_QUIC_BIDIRECTIONAL_STREAM_QUIC_IMPL_H_
-#define NET_QUIC_BIDIRECTIONAL_STREAM_QUIC_IMPL_H_
+#ifndef NET_QUIC_CHROMIUM_BIDIRECTIONAL_STREAM_QUIC_IMPL_H_
+#define NET_QUIC_CHROMIUM_BIDIRECTIONAL_STREAM_QUIC_IMPL_H_
#include <stdint.h>
@@ -140,4 +140,4 @@ class NET_EXPORT_PRIVATE BidirectionalStreamQuicImpl
} // namespace net
-#endif // NET_QUIC_BIDIRECTIONAL_STREAM_QUIC_IMPL_H_
+#endif // NET_QUIC_CHROMIUM_BIDIRECTIONAL_STREAM_QUIC_IMPL_H_
diff --git a/chromium/net/quic/chromium/bidirectional_stream_quic_impl_unittest.cc b/chromium/net/quic/chromium/bidirectional_stream_quic_impl_unittest.cc
index f673fa11a38..c6a4efd797a 100644
--- a/chromium/net/quic/chromium/bidirectional_stream_quic_impl_unittest.cc
+++ b/chromium/net/quic/chromium/bidirectional_stream_quic_impl_unittest.cc
@@ -10,6 +10,7 @@
#include "base/memory/ptr_util.h"
#include "base/run_loop.h"
#include "base/strings/string_number_conversions.h"
+#include "base/threading/thread_task_runner_handle.h"
#include "base/time/time.h"
#include "net/base/ip_address.h"
#include "net/base/load_timing_info.h"
@@ -20,23 +21,24 @@
#include "net/log/net_log_event_type.h"
#include "net/log/test_net_log.h"
#include "net/log/test_net_log_util.h"
+#include "net/quic/chromium/mock_crypto_client_stream_factory.h"
#include "net/quic/chromium/quic_chromium_alarm_factory.h"
#include "net/quic/chromium/quic_chromium_connection_helper.h"
#include "net/quic/chromium/quic_chromium_packet_reader.h"
#include "net/quic/chromium/quic_chromium_packet_writer.h"
+#include "net/quic/chromium/quic_http_utils.h"
+#include "net/quic/chromium/quic_server_info.h"
+#include "net/quic/chromium/quic_test_packet_maker.h"
#include "net/quic/core/crypto/crypto_protocol.h"
#include "net/quic/core/crypto/quic_decrypter.h"
#include "net/quic/core/crypto/quic_encrypter.h"
-#include "net/quic/core/crypto/quic_server_info.h"
#include "net/quic/core/quic_connection.h"
-#include "net/quic/core/quic_http_utils.h"
#include "net/quic/core/spdy_utils.h"
+#include "net/quic/platform/api/quic_text_utils.h"
#include "net/quic/test_tools/crypto_test_utils.h"
#include "net/quic/test_tools/mock_clock.h"
-#include "net/quic/test_tools/mock_crypto_client_stream_factory.h"
#include "net/quic/test_tools/mock_random.h"
#include "net/quic/test_tools/quic_connection_peer.h"
-#include "net/quic/test_tools/quic_test_packet_maker.h"
#include "net/quic/test_tools/quic_test_utils.h"
#include "net/quic/test_tools/test_task_runner.h"
#include "net/socket/socket_test_util.h"
@@ -44,9 +46,6 @@
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
-using net::test::IsError;
-using net::test::IsOk;
-
namespace net {
namespace test {
@@ -392,7 +391,9 @@ class BidirectionalStreamQuicImplTest
}
void ProcessPacket(std::unique_ptr<QuicReceivedPacket> packet) {
- connection_->ProcessUdpPacket(self_addr_, peer_addr_, *packet);
+ connection_->ProcessUdpPacket(
+ QuicSocketAddress(QuicSocketAddressImpl(self_addr_)),
+ QuicSocketAddress(QuicSocketAddressImpl(peer_addr_)), *packet);
}
// Configures the test fixture to use the list of expected writes.
@@ -420,7 +421,8 @@ class BidirectionalStreamQuicImplTest
new QuicChromiumConnectionHelper(&clock_, &random_generator_));
alarm_factory_.reset(new QuicChromiumAlarmFactory(runner_.get(), &clock_));
connection_ = new QuicConnection(
- connection_id_, peer_addr_, helper_.get(), alarm_factory_.get(),
+ connection_id_, QuicSocketAddress(QuicSocketAddressImpl(peer_addr_)),
+ helper_.get(), alarm_factory_.get(),
new QuicChromiumPacketWriter(socket.get()), true /* owns_writer */,
Perspective::IS_CLIENT, SupportedVersions(GetParam()));
base::TimeTicks dns_end = base::TimeTicks::Now();
@@ -436,7 +438,7 @@ class BidirectionalStreamQuicImplTest
kQuicYieldAfterPacketsRead,
QuicTime::Delta::FromMilliseconds(kQuicYieldAfterDurationMilliseconds),
/*cert_verify_flags=*/0, DefaultQuicConfig(), &crypto_config_,
- "CONNECTION_UNKNOWN", dns_start, dns_end, &push_promise_index_,
+ "CONNECTION_UNKNOWN", dns_start, dns_end, &push_promise_index_, nullptr,
base::ThreadTaskRunnerHandle::Get().get(),
/*socket_performance_watcher=*/nullptr, net_log().bound().net_log()));
session_->Initialize();
@@ -471,7 +473,7 @@ class BidirectionalStreamQuicImplTest
std::unique_ptr<QuicReceivedPacket> packet(maker->MakeDataPacket(
packet_number, stream_id_, should_include_version, fin, offset, data));
DVLOG(2) << "packet(" << packet_number << "): " << std::endl
- << QuicUtils::HexDump(packet->AsStringPiece());
+ << QuicTextUtils::HexDump(packet->AsStringPiece());
return packet;
}
@@ -497,7 +499,7 @@ class BidirectionalStreamQuicImplTest
should_include_version, fin,
offset, data_writes));
DVLOG(2) << "packet(" << packet_number << "): " << std::endl
- << QuicUtils::HexDump(packet->AsStringPiece());
+ << QuicTextUtils::HexDump(packet->AsStringPiece());
return packet;
}
@@ -525,7 +527,7 @@ class BidirectionalStreamQuicImplTest
packet_number, stream_id, kIncludeVersion, fin, priority,
std::move(request_headers_), spdy_headers_frame_length, offset));
DVLOG(2) << "packet(" << packet_number << "): " << std::endl
- << QuicUtils::HexDump(packet->AsStringPiece());
+ << QuicTextUtils::HexDump(packet->AsStringPiece());
return packet;
}
@@ -534,6 +536,7 @@ class BidirectionalStreamQuicImplTest
QuicPacketNumber packet_number,
bool fin,
RequestPriority request_priority,
+ QuicStreamOffset* header_stream_offset,
size_t* spdy_headers_frame_length,
const std::vector<std::string>& data) {
SpdyPriority priority =
@@ -541,9 +544,10 @@ class BidirectionalStreamQuicImplTest
std::unique_ptr<QuicReceivedPacket> packet(
client_maker_.MakeRequestHeadersAndMultipleDataFramesPacket(
packet_number, stream_id_, kIncludeVersion, fin, priority,
- std::move(request_headers_), spdy_headers_frame_length, data));
+ std::move(request_headers_), header_stream_offset,
+ spdy_headers_frame_length, data));
DVLOG(2) << "packet(" << packet_number << "): " << std::endl
- << QuicUtils::HexDump(packet->AsStringPiece());
+ << QuicTextUtils::HexDump(packet->AsStringPiece());
return packet;
}
@@ -599,7 +603,7 @@ class BidirectionalStreamQuicImplTest
maker->MakeRstPacket(packet_number, !kIncludeVersion, stream_id_,
QUIC_STREAM_CANCELLED, bytes_written));
DVLOG(2) << "packet(" << packet_number << "): " << std::endl
- << QuicUtils::HexDump(packet->AsStringPiece());
+ << QuicTextUtils::HexDump(packet->AsStringPiece());
return packet;
}
@@ -627,7 +631,7 @@ class BidirectionalStreamQuicImplTest
packet_number, should_include_version, stream_id_, largest_received,
least_unacked, fin, offset, data));
DVLOG(2) << "packet(" << packet_number << "): " << std::endl
- << QuicUtils::HexDump(packet->AsStringPiece());
+ << QuicTextUtils::HexDump(packet->AsStringPiece());
return packet;
}
@@ -649,6 +653,15 @@ class BidirectionalStreamQuicImplTest
!kIncludeCongestionFeedback);
}
+ std::unique_ptr<QuicReceivedPacket> ConstructSettingsPacket(
+ QuicPacketNumber packet_number,
+ SpdySettingsIds id,
+ size_t value,
+ QuicStreamOffset* offset) {
+ return client_maker_.MakeSettingsPacket(packet_number, id, value,
+ kIncludeVersion, offset);
+ }
+
void ExpectLoadTimingValid(const LoadTimingInfo& load_timing_info,
bool session_reused) {
EXPECT_EQ(session_reused, load_timing_info.socket_reused);
@@ -702,10 +715,15 @@ INSTANTIATE_TEST_CASE_P(Version,
TEST_P(BidirectionalStreamQuicImplTest, GetRequest) {
SetRequest("GET", "/", DEFAULT_PRIORITY);
size_t spdy_request_headers_frame_length;
- AddWrite(ConstructRequestHeadersPacket(1, kFin, DEFAULT_PRIORITY,
- &spdy_request_headers_frame_length));
+ QuicStreamOffset header_stream_offset = 0;
+ AddWrite(ConstructRequestHeadersPacketInner(
+ 1, kClientDataStreamId1, kFin, DEFAULT_PRIORITY,
+ &spdy_request_headers_frame_length, &header_stream_offset));
+ AddWrite(ConstructSettingsPacket(2, SETTINGS_MAX_HEADER_LIST_SIZE,
+ kDefaultMaxUncompressedHeaderSize,
+ &header_stream_offset));
+ AddWrite(ConstructClientAckPacket(3, 3, 1));
- AddWrite(ConstructClientAckPacket(2, 3, 1));
Initialize();
BidirectionalStreamRequestInfo request;
@@ -803,7 +821,9 @@ TEST_P(BidirectionalStreamQuicImplTest, LoadTimingTwoRequests) {
SetRequest("GET", "/", DEFAULT_PRIORITY);
AddWrite(ConstructRequestHeadersPacketInner(
2, kClientDataStreamId2, kFin, DEFAULT_PRIORITY, nullptr, &offset));
- AddWrite(ConstructClientAckPacket(3, 3, 1));
+ AddWrite(ConstructSettingsPacket(3, SETTINGS_MAX_HEADER_LIST_SIZE,
+ kDefaultMaxUncompressedHeaderSize, &offset));
+ AddWrite(ConstructClientAckPacket(4, 3, 1));
Initialize();
BidirectionalStreamRequestInfo request;
@@ -863,22 +883,26 @@ TEST_P(BidirectionalStreamQuicImplTest, LoadTimingTwoRequests) {
TEST_P(BidirectionalStreamQuicImplTest, CoalesceDataBuffersNotHeadersFrame) {
SetRequest("POST", "/", DEFAULT_PRIORITY);
size_t spdy_request_headers_frame_length;
-
+ QuicStreamOffset header_stream_offset = 0;
+ AddWrite(ConstructSettingsPacket(1, SETTINGS_MAX_HEADER_LIST_SIZE,
+ kDefaultMaxUncompressedHeaderSize,
+ &header_stream_offset));
const char kBody1[] = "here are some data";
const char kBody2[] = "data keep coming";
std::vector<std::string> two_writes = {kBody1, kBody2};
- AddWrite(ConstructRequestHeadersPacket(1, !kFin, DEFAULT_PRIORITY,
- &spdy_request_headers_frame_length));
- AddWrite(ConstructClientMultipleDataFramesPacket(2, kIncludeVersion, !kFin, 0,
+ AddWrite(ConstructRequestHeadersPacketInner(
+ 2, kClientDataStreamId1, !kFin, DEFAULT_PRIORITY,
+ &spdy_request_headers_frame_length, &header_stream_offset));
+ AddWrite(ConstructClientMultipleDataFramesPacket(3, kIncludeVersion, !kFin, 0,
{kBody1, kBody2}));
// Ack server's data packet.
- AddWrite(ConstructClientAckPacket(3, 3, 1));
+ AddWrite(ConstructClientAckPacket(4, 3, 1));
const char kBody3[] = "hello there";
const char kBody4[] = "another piece of small data";
const char kBody5[] = "really small";
QuicStreamOffset data_offset = strlen(kBody1) + strlen(kBody2);
AddWrite(ConstructClientMultipleDataFramesPacket(
- 4, !kIncludeVersion, kFin, data_offset, {kBody3, kBody4, kBody5}));
+ 5, !kIncludeVersion, kFin, data_offset, {kBody3, kBody4, kBody5}));
Initialize();
@@ -973,16 +997,19 @@ TEST_P(BidirectionalStreamQuicImplTest,
SendDataCoalesceDataBufferAndHeaderFrame) {
SetRequest("POST", "/", DEFAULT_PRIORITY);
size_t spdy_request_headers_frame_length;
-
+ QuicStreamOffset header_stream_offset = 0;
+ AddWrite(ConstructSettingsPacket(1, SETTINGS_MAX_HEADER_LIST_SIZE,
+ kDefaultMaxUncompressedHeaderSize,
+ &header_stream_offset));
const char kBody1[] = "here are some data";
AddWrite(ConstructRequestHeadersAndMultipleDataFramesPacket(
- 1, !kFin, DEFAULT_PRIORITY, &spdy_request_headers_frame_length,
- {kBody1}));
+ 2, !kFin, DEFAULT_PRIORITY, &header_stream_offset,
+ &spdy_request_headers_frame_length, {kBody1}));
// Ack server's data packet.
- AddWrite(ConstructClientAckPacket(2, 3, 1));
+ AddWrite(ConstructClientAckPacket(3, 3, 1));
const char kBody2[] = "really small";
QuicStreamOffset data_offset = strlen(kBody1);
- AddWrite(ConstructClientMultipleDataFramesPacket(3, !kIncludeVersion, kFin,
+ AddWrite(ConstructClientMultipleDataFramesPacket(4, !kIncludeVersion, kFin,
data_offset, {kBody2}));
Initialize();
@@ -1067,21 +1094,24 @@ TEST_P(BidirectionalStreamQuicImplTest,
SendvDataCoalesceDataBuffersAndHeaderFrame) {
SetRequest("POST", "/", DEFAULT_PRIORITY);
size_t spdy_request_headers_frame_length;
-
+ QuicStreamOffset header_stream_offset = 0;
+ AddWrite(ConstructSettingsPacket(1, SETTINGS_MAX_HEADER_LIST_SIZE,
+ kDefaultMaxUncompressedHeaderSize,
+ &header_stream_offset));
const char kBody1[] = "here are some data";
const char kBody2[] = "data keep coming";
std::vector<std::string> two_writes = {kBody1, kBody2};
AddWrite(ConstructRequestHeadersAndMultipleDataFramesPacket(
- 1, !kFin, DEFAULT_PRIORITY, &spdy_request_headers_frame_length,
- two_writes));
+ 2, !kFin, DEFAULT_PRIORITY, &header_stream_offset,
+ &spdy_request_headers_frame_length, two_writes));
// Ack server's data packet.
- AddWrite(ConstructClientAckPacket(2, 3, 1));
+ AddWrite(ConstructClientAckPacket(3, 3, 1));
const char kBody3[] = "hello there";
const char kBody4[] = "another piece of small data";
const char kBody5[] = "really small";
QuicStreamOffset data_offset = strlen(kBody1) + strlen(kBody2);
AddWrite(ConstructClientMultipleDataFramesPacket(
- 3, !kIncludeVersion, kFin, data_offset, {kBody3, kBody4, kBody5}));
+ 4, !kIncludeVersion, kFin, data_offset, {kBody3, kBody4, kBody5}));
Initialize();
@@ -1169,11 +1199,16 @@ TEST_P(BidirectionalStreamQuicImplTest,
TEST_P(BidirectionalStreamQuicImplTest, PostRequest) {
SetRequest("POST", "/", DEFAULT_PRIORITY);
size_t spdy_request_headers_frame_length;
- AddWrite(ConstructRequestHeadersPacket(1, !kFin, DEFAULT_PRIORITY,
- &spdy_request_headers_frame_length));
- AddWrite(ConstructDataPacket(2, kIncludeVersion, kFin, 0, kUploadData,
+ QuicStreamOffset header_stream_offset = 0;
+ AddWrite(ConstructRequestHeadersPacketInner(
+ 1, kClientDataStreamId1, !kFin, DEFAULT_PRIORITY,
+ &spdy_request_headers_frame_length, &header_stream_offset));
+ AddWrite(ConstructSettingsPacket(2, SETTINGS_MAX_HEADER_LIST_SIZE,
+ kDefaultMaxUncompressedHeaderSize,
+ &header_stream_offset));
+ AddWrite(ConstructDataPacket(3, kIncludeVersion, kFin, 0, kUploadData,
&client_maker_));
- AddWrite(ConstructClientAckPacket(3, 3, 1));
+ AddWrite(ConstructClientAckPacket(4, 3, 1));
Initialize();
@@ -1324,11 +1359,17 @@ TEST_P(BidirectionalStreamQuicImplTest, PutRequest) {
TEST_P(BidirectionalStreamQuicImplTest, InterleaveReadDataAndSendData) {
SetRequest("POST", "/", DEFAULT_PRIORITY);
size_t spdy_request_headers_frame_length;
- AddWrite(ConstructRequestHeadersPacket(1, !kFin, DEFAULT_PRIORITY,
- &spdy_request_headers_frame_length));
- AddWrite(ConstructAckAndDataPacket(2, !kIncludeVersion, 2, 1, !kFin, 0,
+ QuicStreamOffset header_stream_offset = 0;
+ AddWrite(ConstructRequestHeadersPacketInner(
+ 1, kClientDataStreamId1, !kFin, DEFAULT_PRIORITY,
+ &spdy_request_headers_frame_length, &header_stream_offset));
+
+ AddWrite(ConstructSettingsPacket(2, SETTINGS_MAX_HEADER_LIST_SIZE,
+ kDefaultMaxUncompressedHeaderSize,
+ &header_stream_offset));
+ AddWrite(ConstructAckAndDataPacket(3, !kIncludeVersion, 2, 1, !kFin, 0,
kUploadData, &client_maker_));
- AddWrite(ConstructAckAndDataPacket(3, !kIncludeVersion, 3, 3, kFin,
+ AddWrite(ConstructAckAndDataPacket(4, !kIncludeVersion, 3, 3, kFin,
strlen(kUploadData), kUploadData,
&client_maker_));
Initialize();
@@ -1409,8 +1450,13 @@ TEST_P(BidirectionalStreamQuicImplTest, InterleaveReadDataAndSendData) {
TEST_P(BidirectionalStreamQuicImplTest, ServerSendsRstAfterHeaders) {
SetRequest("GET", "/", DEFAULT_PRIORITY);
size_t spdy_request_headers_frame_length;
- AddWrite(ConstructRequestHeadersPacket(1, kFin, DEFAULT_PRIORITY,
- &spdy_request_headers_frame_length));
+ QuicStreamOffset header_stream_offset = 0;
+ AddWrite(ConstructRequestHeadersPacketInner(
+ 1, kClientDataStreamId1, kFin, DEFAULT_PRIORITY,
+ &spdy_request_headers_frame_length, &header_stream_offset));
+ AddWrite(ConstructSettingsPacket(2, SETTINGS_MAX_HEADER_LIST_SIZE,
+ kDefaultMaxUncompressedHeaderSize,
+ &header_stream_offset));
Initialize();
BidirectionalStreamRequestInfo request;
@@ -1447,10 +1493,15 @@ TEST_P(BidirectionalStreamQuicImplTest, ServerSendsRstAfterHeaders) {
TEST_P(BidirectionalStreamQuicImplTest, ServerSendsRstAfterReadData) {
SetRequest("GET", "/", DEFAULT_PRIORITY);
size_t spdy_request_headers_frame_length;
- AddWrite(ConstructRequestHeadersPacket(1, kFin, DEFAULT_PRIORITY,
- &spdy_request_headers_frame_length));
+ QuicStreamOffset header_stream_offset = 0;
+ AddWrite(ConstructRequestHeadersPacketInner(
+ 1, kClientDataStreamId1, kFin, DEFAULT_PRIORITY,
+ &spdy_request_headers_frame_length, &header_stream_offset));
+ AddWrite(ConstructSettingsPacket(2, SETTINGS_MAX_HEADER_LIST_SIZE,
+ kDefaultMaxUncompressedHeaderSize,
+ &header_stream_offset));
// Why does QUIC ack Rst? Is this expected?
- AddWrite(ConstructClientAckPacket(2, 3, 1));
+ AddWrite(ConstructClientAckPacket(3, 3, 1));
Initialize();
@@ -1505,8 +1556,13 @@ TEST_P(BidirectionalStreamQuicImplTest, ServerSendsRstAfterReadData) {
TEST_P(BidirectionalStreamQuicImplTest, SessionClosedBeforeReadData) {
SetRequest("POST", "/", DEFAULT_PRIORITY);
size_t spdy_request_headers_frame_length;
- AddWrite(ConstructRequestHeadersPacket(1, !kFin, DEFAULT_PRIORITY,
- &spdy_request_headers_frame_length));
+ QuicStreamOffset header_stream_offset = 0;
+ AddWrite(ConstructRequestHeadersPacketInner(
+ 1, kClientDataStreamId1, !kFin, DEFAULT_PRIORITY,
+ &spdy_request_headers_frame_length, &header_stream_offset));
+ AddWrite(ConstructSettingsPacket(2, SETTINGS_MAX_HEADER_LIST_SIZE,
+ kDefaultMaxUncompressedHeaderSize,
+ &header_stream_offset));
Initialize();
BidirectionalStreamRequestInfo request;
@@ -1562,9 +1618,14 @@ TEST_P(BidirectionalStreamQuicImplTest, SessionClosedBeforeReadData) {
TEST_P(BidirectionalStreamQuicImplTest, DeleteStreamAfterReadData) {
SetRequest("POST", "/", DEFAULT_PRIORITY);
size_t spdy_request_headers_frame_length;
- AddWrite(ConstructRequestHeadersPacket(1, !kFin, DEFAULT_PRIORITY,
- &spdy_request_headers_frame_length));
- AddWrite(ConstructClientAckAndRstStreamPacket(2, 2, 1, 1));
+ QuicStreamOffset header_stream_offset = 0;
+ AddWrite(ConstructRequestHeadersPacketInner(
+ 1, kClientDataStreamId1, !kFin, DEFAULT_PRIORITY,
+ &spdy_request_headers_frame_length, &header_stream_offset));
+ AddWrite(ConstructSettingsPacket(2, SETTINGS_MAX_HEADER_LIST_SIZE,
+ kDefaultMaxUncompressedHeaderSize,
+ &header_stream_offset));
+ AddWrite(ConstructClientAckAndRstStreamPacket(3, 2, 1, 1));
Initialize();
@@ -1613,9 +1674,14 @@ TEST_P(BidirectionalStreamQuicImplTest, DeleteStreamAfterReadData) {
TEST_P(BidirectionalStreamQuicImplTest, DeleteStreamDuringOnHeadersReceived) {
SetRequest("POST", "/", DEFAULT_PRIORITY);
size_t spdy_request_headers_frame_length;
- AddWrite(ConstructRequestHeadersPacket(1, !kFin, DEFAULT_PRIORITY,
- &spdy_request_headers_frame_length));
- AddWrite(ConstructClientAckAndRstStreamPacket(2, 2, 1, 1));
+ QuicStreamOffset header_stream_offset = 0;
+ AddWrite(ConstructRequestHeadersPacketInner(
+ 1, kClientDataStreamId1, !kFin, DEFAULT_PRIORITY,
+ &spdy_request_headers_frame_length, &header_stream_offset));
+ AddWrite(ConstructSettingsPacket(2, SETTINGS_MAX_HEADER_LIST_SIZE,
+ kDefaultMaxUncompressedHeaderSize,
+ &header_stream_offset));
+ AddWrite(ConstructClientAckAndRstStreamPacket(3, 2, 1, 1));
Initialize();
@@ -1656,10 +1722,15 @@ TEST_P(BidirectionalStreamQuicImplTest, DeleteStreamDuringOnHeadersReceived) {
TEST_P(BidirectionalStreamQuicImplTest, DeleteStreamDuringOnDataRead) {
SetRequest("POST", "/", DEFAULT_PRIORITY);
size_t spdy_request_headers_frame_length;
- AddWrite(ConstructRequestHeadersPacket(1, !kFin, DEFAULT_PRIORITY,
- &spdy_request_headers_frame_length));
- AddWrite(ConstructClientAckPacket(2, 3, 1));
- AddWrite(ConstructClientRstStreamPacket(3));
+ QuicStreamOffset header_stream_offset = 0;
+ AddWrite(ConstructRequestHeadersPacketInner(
+ 1, kClientDataStreamId1, !kFin, DEFAULT_PRIORITY,
+ &spdy_request_headers_frame_length, &header_stream_offset));
+ AddWrite(ConstructSettingsPacket(2, SETTINGS_MAX_HEADER_LIST_SIZE,
+ kDefaultMaxUncompressedHeaderSize,
+ &header_stream_offset));
+ AddWrite(ConstructClientAckPacket(3, 3, 1));
+ AddWrite(ConstructClientRstStreamPacket(4));
Initialize();
diff --git a/chromium/net/quic/chromium/crypto/channel_id_chromium.cc b/chromium/net/quic/chromium/crypto/channel_id_chromium.cc
index 164e1e5841e..f91f466aa8c 100644
--- a/chromium/net/quic/chromium/crypto/channel_id_chromium.cc
+++ b/chromium/net/quic/chromium/crypto/channel_id_chromium.cc
@@ -128,7 +128,7 @@ QuicAsyncStatus ChannelIDSourceChromium::Job::GetChannelIDKey(
next_state_ = STATE_GET_CHANNEL_ID_KEY;
switch (DoLoop(OK)) {
case OK:
- channel_id_key->reset(channel_id_key_.release());
+ *channel_id_key = std::move(channel_id_key_);
return QUIC_SUCCESS;
case ERR_IO_PENDING:
callback_.reset(callback);
diff --git a/chromium/net/quic/chromium/crypto/channel_id_chromium.h b/chromium/net/quic/chromium/crypto/channel_id_chromium.h
index fa842969f1d..2c9869c30b2 100644
--- a/chromium/net/quic/chromium/crypto/channel_id_chromium.h
+++ b/chromium/net/quic/chromium/crypto/channel_id_chromium.h
@@ -2,8 +2,8 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#ifndef NET_QUIC_CRYPTO_CHANNEL_ID_CHROMIUM_H_
-#define NET_QUIC_CRYPTO_CHANNEL_ID_CHROMIUM_H_
+#ifndef NET_QUIC_CHROMIUM_CRYPTO_CHANNEL_ID_CHROMIUM_H_
+#define NET_QUIC_CHROMIUM_CRYPTO_CHANNEL_ID_CHROMIUM_H_
#include <map>
#include <memory>
@@ -63,4 +63,4 @@ class ChannelIDSourceChromium : public ChannelIDSource {
} // namespace net
-#endif // NET_QUIC_CRYPTO_CHANNEL_ID_CHROMIUM_H_
+#endif // NET_QUIC_CHROMIUM_CRYPTO_CHANNEL_ID_CHROMIUM_H_
diff --git a/chromium/net/quic/chromium/crypto/proof_source_chromium.cc b/chromium/net/quic/chromium/crypto/proof_source_chromium.cc
index c03305d655c..dd8ce1f8881 100644
--- a/chromium/net/quic/chromium/crypto/proof_source_chromium.cc
+++ b/chromium/net/quic/chromium/crypto/proof_source_chromium.cc
@@ -12,7 +12,6 @@
#include "third_party/boringssl/src/include/openssl/rsa.h"
using std::string;
-using std::vector;
namespace net {
@@ -40,7 +39,7 @@ bool ProofSourceChromium::Initialize(const base::FilePath& cert_path,
return false;
}
- vector<string> certs;
+ std::vector<string> certs;
for (const scoped_refptr<X509Certificate>& cert : certs_in_file) {
std::string der_encoded_cert;
if (!X509Certificate::GetDEREncoded(cert->os_cert_handle(),
@@ -78,15 +77,15 @@ bool ProofSourceChromium::Initialize(const base::FilePath& cert_path,
}
bool ProofSourceChromium::GetProof(
- const IPAddress& server_ip,
+ const QuicSocketAddress& server_addr,
const string& hostname,
const string& server_config,
QuicVersion quic_version,
base::StringPiece chlo_hash,
const QuicTagVector& /* connection_options */,
- scoped_refptr<ProofSource::Chain>* out_chain,
- string* out_signature,
- string* out_leaf_cert_sct) {
+ QuicReferenceCountedPointer<ProofSource::Chain>* out_chain,
+ QuicCryptoProof* proof) {
+ DCHECK(proof != nullptr);
DCHECK(private_key_.get()) << " this: " << this;
crypto::OpenSSLErrStackTracer err_tracer(FROM_HERE);
@@ -125,16 +124,16 @@ bool ProofSourceChromium::GetProof(
return false;
}
signature.resize(len);
- out_signature->assign(reinterpret_cast<const char*>(signature.data()),
- signature.size());
+ proof->signature.assign(reinterpret_cast<const char*>(signature.data()),
+ signature.size());
*out_chain = chain_;
VLOG(1) << "signature: "
- << base::HexEncode(out_signature->data(), out_signature->size());
- *out_leaf_cert_sct = signed_certificate_timestamp_;
+ << base::HexEncode(proof->signature.data(), proof->signature.size());
+ proof->leaf_cert_scts = signed_certificate_timestamp_;
return true;
}
-void ProofSourceChromium::GetProof(const IPAddress& server_ip,
+void ProofSourceChromium::GetProof(const QuicSocketAddress& server_addr,
const std::string& hostname,
const std::string& server_config,
QuicVersion quic_version,
@@ -143,13 +142,13 @@ void ProofSourceChromium::GetProof(const IPAddress& server_ip,
std::unique_ptr<Callback> callback) {
// As a transitional implementation, just call the synchronous version of
// GetProof, then invoke the callback with the results and destroy it.
- scoped_refptr<ProofSource::Chain> chain;
+ QuicReferenceCountedPointer<ProofSource::Chain> chain;
string signature;
string leaf_cert_sct;
- const bool ok =
- GetProof(server_ip, hostname, server_config, quic_version, chlo_hash,
- connection_options, &chain, &signature, &leaf_cert_sct);
- callback->Run(ok, chain, signature, leaf_cert_sct, nullptr /* details */);
+ QuicCryptoProof out_proof;
+ const bool ok = GetProof(server_addr, hostname, server_config, quic_version,
+ chlo_hash, connection_options, &chain, &out_proof);
+ callback->Run(ok, chain, out_proof, nullptr /* details */);
}
} // namespace net
diff --git a/chromium/net/quic/chromium/crypto/proof_source_chromium.h b/chromium/net/quic/chromium/crypto/proof_source_chromium.h
index 2cbf44b6250..95b892d61f9 100644
--- a/chromium/net/quic/chromium/crypto/proof_source_chromium.h
+++ b/chromium/net/quic/chromium/crypto/proof_source_chromium.h
@@ -2,8 +2,8 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#ifndef NET_QUIC_CRYPTO_PROOF_SOURCE_CHROMIUM_H_
-#define NET_QUIC_CRYPTO_PROOF_SOURCE_CHROMIUM_H_
+#ifndef NET_QUIC_CHROMIUM_CRYPTO_PROOF_SOURCE_CHROMIUM_H_
+#define NET_QUIC_CHROMIUM_CRYPTO_PROOF_SOURCE_CHROMIUM_H_
#include <string>
#include <vector>
@@ -33,17 +33,16 @@ class NET_EXPORT_PRIVATE ProofSourceChromium : public ProofSource {
const base::FilePath& sct_path);
// ProofSource interface
- bool GetProof(const IPAddress& server_ip,
+ bool GetProof(const QuicSocketAddress& server_ip,
const std::string& hostname,
const std::string& server_config,
QuicVersion quic_version,
base::StringPiece chlo_hash,
const QuicTagVector& connection_options,
- scoped_refptr<ProofSource::Chain>* out_chain,
- std::string* out_signature,
- std::string* out_leaf_cert_sct) override;
+ QuicReferenceCountedPointer<ProofSource::Chain>* out_chain,
+ QuicCryptoProof* proof) override;
- void GetProof(const IPAddress& server_ip,
+ void GetProof(const QuicSocketAddress& server_ip,
const std::string& hostname,
const std::string& server_config,
QuicVersion quic_version,
@@ -53,7 +52,7 @@ class NET_EXPORT_PRIVATE ProofSourceChromium : public ProofSource {
private:
std::unique_ptr<crypto::RSAPrivateKey> private_key_;
- scoped_refptr<ProofSource::Chain> chain_;
+ QuicReferenceCountedPointer<ProofSource::Chain> chain_;
std::string signed_certificate_timestamp_;
DISALLOW_COPY_AND_ASSIGN(ProofSourceChromium);
@@ -61,4 +60,4 @@ class NET_EXPORT_PRIVATE ProofSourceChromium : public ProofSource {
} // namespace net
-#endif // NET_QUIC_CRYPTO_PROOF_SOURCE_CHROMIUM_H_
+#endif // NET_QUIC_CHROMIUM_CRYPTO_PROOF_SOURCE_CHROMIUM_H_
diff --git a/chromium/net/quic/chromium/crypto/proof_test_chromium.cc b/chromium/net/quic/chromium/crypto/proof_test_chromium.cc
index f6eb00490fb..023a4332511 100644
--- a/chromium/net/quic/chromium/crypto/proof_test_chromium.cc
+++ b/chromium/net/quic/chromium/crypto/proof_test_chromium.cc
@@ -19,7 +19,6 @@
#include "testing/gtest/include/gtest/gtest.h"
using std::string;
-using std::vector;
namespace net {
namespace test {
@@ -58,7 +57,7 @@ void RunVerification(ProofVerifier* verifier,
const string& server_config,
QuicVersion quic_version,
StringPiece chlo_hash,
- const vector<string>& certs,
+ const std::vector<string>& certs,
const string& proof,
bool expected_ok) {
std::unique_ptr<ProofVerifyDetails> details;
@@ -94,33 +93,25 @@ class TestCallback : public ProofSource::Callback {
public:
explicit TestCallback(bool* called,
bool* ok,
- scoped_refptr<ProofSource::Chain>* chain,
- string* signature,
- string* leaf_cert_sct)
- : called_(called),
- ok_(ok),
- chain_(chain),
- signature_(signature),
- leaf_cert_sct_(leaf_cert_sct) {}
+ QuicReferenceCountedPointer<ProofSource::Chain>* chain,
+ QuicCryptoProof* proof)
+ : called_(called), ok_(ok), chain_(chain), proof_(proof) {}
void Run(bool ok,
- const scoped_refptr<ProofSource::Chain>& chain,
- const string& signature,
- const string& leaf_cert_sct,
+ const QuicReferenceCountedPointer<ProofSource::Chain>& chain,
+ const QuicCryptoProof& proof,
std::unique_ptr<ProofSource::Details> /* details */) override {
*ok_ = ok;
*chain_ = chain;
- *signature_ = signature;
- *leaf_cert_sct_ = leaf_cert_sct;
+ *proof_ = proof;
*called_ = true;
}
private:
bool* called_;
bool* ok_;
- scoped_refptr<ProofSource::Chain>* chain_;
- string* signature_;
- string* leaf_cert_sct_;
+ QuicReferenceCountedPointer<ProofSource::Chain>* chain_;
+ QuicCryptoProof* proof_;
};
class ProofTest : public ::testing::TestWithParam<QuicVersion> {};
@@ -144,38 +135,39 @@ TEST_P(ProofTest, DISABLED_Verify) {
const string second_chlo_hash = "first chlo hash bytes";
const QuicVersion quic_version = GetParam();
- scoped_refptr<ProofSource::Chain> chain;
- scoped_refptr<ProofSource::Chain> first_chain;
- string error_details, signature, first_signature, first_cert_sct, cert_sct;
- IPAddress server_ip;
+ QuicReferenceCountedPointer<ProofSource::Chain> chain;
+ QuicReferenceCountedPointer<ProofSource::Chain> first_chain;
+ string error_details;
+ QuicCryptoProof proof, first_proof;
+ QuicSocketAddress server_addr;
- ASSERT_TRUE(source->GetProof(server_ip, hostname, server_config, quic_version,
- first_chlo_hash, QuicTagVector(), &first_chain,
- &first_signature, &first_cert_sct));
- ASSERT_TRUE(source->GetProof(server_ip, hostname, server_config, quic_version,
- second_chlo_hash, QuicTagVector(), &chain,
- &signature, &cert_sct));
+ ASSERT_TRUE(source->GetProof(server_addr, hostname, server_config,
+ quic_version, first_chlo_hash, QuicTagVector(),
+ &first_chain, &first_proof));
+ ASSERT_TRUE(source->GetProof(server_addr, hostname, server_config,
+ quic_version, second_chlo_hash, QuicTagVector(),
+ &chain, &proof));
// Check that the proof source is caching correctly:
ASSERT_EQ(first_chain->certs, chain->certs);
- ASSERT_NE(signature, first_signature);
- ASSERT_EQ(first_cert_sct, cert_sct);
+ ASSERT_NE(proof.signature, first_proof.signature);
+ ASSERT_EQ(first_proof.leaf_cert_scts, proof.leaf_cert_scts);
RunVerification(verifier.get(), hostname, port, server_config, quic_version,
- first_chlo_hash, chain->certs, signature, true);
+ first_chlo_hash, chain->certs, proof.signature, true);
RunVerification(verifier.get(), "foo.com", port, server_config, quic_version,
- first_chlo_hash, chain->certs, signature, false);
+ first_chlo_hash, chain->certs, proof.signature, false);
RunVerification(verifier.get(), server_config.substr(1, string::npos), port,
server_config, quic_version, first_chlo_hash, chain->certs,
- signature, false);
+ proof.signature, false);
- const string corrupt_signature = "1" + signature;
+ const string corrupt_signature = "1" + proof.signature;
RunVerification(verifier.get(), hostname, port, server_config, quic_version,
first_chlo_hash, chain->certs, corrupt_signature, false);
- vector<string> wrong_certs;
+ std::vector<string> wrong_certs;
for (size_t i = 1; i < chain->certs.size(); i++) {
wrong_certs.push_back(chain->certs[i]);
}
@@ -192,33 +184,30 @@ TEST_P(ProofTest, VerifySourceAsync) {
const string first_chlo_hash = "first chlo hash bytes";
const string second_chlo_hash = "first chlo hash bytes";
const QuicVersion quic_version = GetParam();
- IPAddress server_ip;
+ QuicSocketAddress server_addr;
// Call synchronous version
- scoped_refptr<ProofSource::Chain> expected_chain;
- string expected_signature;
- string expected_leaf_cert_sct;
- ASSERT_TRUE(source->GetProof(server_ip, hostname, server_config, quic_version,
- first_chlo_hash, QuicTagVector(),
- &expected_chain, &expected_signature,
- &expected_leaf_cert_sct));
+ QuicReferenceCountedPointer<ProofSource::Chain> expected_chain;
+ QuicCryptoProof expected_proof;
+ ASSERT_TRUE(source->GetProof(server_addr, hostname, server_config,
+ quic_version, first_chlo_hash, QuicTagVector(),
+ &expected_chain, &expected_proof));
// Call asynchronous version and compare results
bool called = false;
bool ok;
- scoped_refptr<ProofSource::Chain> chain;
- string signature;
- string leaf_cert_sct;
+ QuicReferenceCountedPointer<ProofSource::Chain> chain;
+ QuicCryptoProof proof;
std::unique_ptr<ProofSource::Callback> cb(
- new TestCallback(&called, &ok, &chain, &signature, &leaf_cert_sct));
- source->GetProof(server_ip, hostname, server_config, quic_version,
+ new TestCallback(&called, &ok, &chain, &proof));
+ source->GetProof(server_addr, hostname, server_config, quic_version,
first_chlo_hash, QuicTagVector(), std::move(cb));
// TODO(gredner): whan GetProof really invokes the callback asynchronously,
// figure out what to do here.
ASSERT_TRUE(called);
ASSERT_TRUE(ok);
EXPECT_THAT(chain->certs, ::testing::ContainerEq(expected_chain->certs));
- EXPECT_EQ(leaf_cert_sct, expected_leaf_cert_sct);
+ EXPECT_EQ(proof.leaf_cert_scts, expected_proof.leaf_cert_scts);
}
TEST_P(ProofTest, UseAfterFree) {
@@ -227,13 +216,13 @@ TEST_P(ProofTest, UseAfterFree) {
const string server_config = "server config bytes";
const string hostname = "test.example.com";
const string chlo_hash = "proof nonce bytes";
- scoped_refptr<ProofSource::Chain> chain;
- string error_details, signature, cert_sct;
- IPAddress server_ip;
+ QuicReferenceCountedPointer<ProofSource::Chain> chain;
+ string error_details;
+ QuicCryptoProof proof;
+ QuicSocketAddress server_addr;
- ASSERT_TRUE(source->GetProof(server_ip, hostname, server_config, GetParam(),
- chlo_hash, QuicTagVector(), &chain, &signature,
- &cert_sct));
+ ASSERT_TRUE(source->GetProof(server_addr, hostname, server_config, GetParam(),
+ chlo_hash, QuicTagVector(), &chain, &proof));
// Make sure we can safely access results after deleting where they came from.
EXPECT_FALSE(chain->HasOneRef());
diff --git a/chromium/net/quic/chromium/crypto/proof_verifier_chromium.cc b/chromium/net/quic/chromium/crypto/proof_verifier_chromium.cc
index 160191bf622..35503e60776 100644
--- a/chromium/net/quic/chromium/crypto/proof_verifier_chromium.cc
+++ b/chromium/net/quic/chromium/crypto/proof_verifier_chromium.cc
@@ -30,7 +30,6 @@
using base::StringPiece;
using base::StringPrintf;
using std::string;
-using std::vector;
namespace net {
@@ -96,7 +95,7 @@ class ProofVerifierChromium::Job {
};
// Convert |certs| to |cert_|(X509Certificate). Returns true if successful.
- bool GetX509Certificate(const vector<string>& certs,
+ bool GetX509Certificate(const std::vector<string>& certs,
std::string* error_details,
std::unique_ptr<ProofVerifyDetails>* verify_details);
@@ -202,7 +201,7 @@ QuicAsyncStatus ProofVerifierChromium::Job::VerifyProof(
const string& server_config,
QuicVersion quic_version,
StringPiece chlo_hash,
- const vector<string>& certs,
+ const std::vector<string>& certs,
const std::string& cert_sct,
const string& signature,
std::string* error_details,
@@ -254,7 +253,7 @@ QuicAsyncStatus ProofVerifierChromium::Job::VerifyProof(
QuicAsyncStatus ProofVerifierChromium::Job::VerifyCertChain(
const string& hostname,
- const vector<string>& certs,
+ const std::vector<string>& certs,
std::string* error_details,
std::unique_ptr<ProofVerifyDetails>* verify_details,
std::unique_ptr<ProofVerifierCallback> callback) {
@@ -283,7 +282,7 @@ QuicAsyncStatus ProofVerifierChromium::Job::VerifyCertChain(
}
bool ProofVerifierChromium::Job::GetX509Certificate(
- const vector<string>& certs,
+ const std::vector<string>& certs,
std::string* error_details,
std::unique_ptr<ProofVerifyDetails>* verify_details) {
if (certs.empty()) {
@@ -295,7 +294,7 @@ bool ProofVerifierChromium::Job::GetX509Certificate(
}
// Convert certs to X509Certificate.
- vector<StringPiece> cert_pieces(certs.size());
+ std::vector<StringPiece> cert_pieces(certs.size());
for (unsigned i = 0; i < certs.size(); i++) {
cert_pieces[i] = base::StringPiece(certs[i]);
}
diff --git a/chromium/net/quic/chromium/crypto/proof_verifier_chromium.h b/chromium/net/quic/chromium/crypto/proof_verifier_chromium.h
index 192b33f0db3..d7c88522206 100644
--- a/chromium/net/quic/chromium/crypto/proof_verifier_chromium.h
+++ b/chromium/net/quic/chromium/crypto/proof_verifier_chromium.h
@@ -2,8 +2,8 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#ifndef NET_QUIC_CRYPTO_PROOF_VERIFIER_CHROMIUM_H_
-#define NET_QUIC_CRYPTO_PROOF_VERIFIER_CHROMIUM_H_
+#ifndef NET_QUIC_CHROMIUM_CRYPTO_PROOF_VERIFIER_CHROMIUM_H_
+#define NET_QUIC_CHROMIUM_CRYPTO_PROOF_VERIFIER_CHROMIUM_H_
#include <map>
#include <memory>
@@ -114,4 +114,4 @@ class NET_EXPORT_PRIVATE ProofVerifierChromium : public ProofVerifier {
} // namespace net
-#endif // NET_QUIC_CRYPTO_PROOF_VERIFIER_CHROMIUM_H_
+#endif // NET_QUIC_CHROMIUM_CRYPTO_PROOF_VERIFIER_CHROMIUM_H_
diff --git a/chromium/net/quic/chromium/crypto_test_utils_chromium.cc b/chromium/net/quic/chromium/crypto_test_utils_chromium.cc
index d1c6db0ec02..a7b8df41020 100644
--- a/chromium/net/quic/chromium/crypto_test_utils_chromium.cc
+++ b/chromium/net/quic/chromium/crypto_test_utils_chromium.cc
@@ -35,9 +35,7 @@
#include "net/test/test_data_directory.h"
using base::StringPiece;
-using base::StringPrintf;
using std::string;
-using std::vector;
namespace net {
@@ -93,8 +91,7 @@ std::unique_ptr<ProofSource> CryptoTestUtils::ProofSourceForTesting() {
}
// static
-std::unique_ptr<ProofVerifier> ProofVerifierForTestingInternal(
- bool use_real_proof_verifier) {
+std::unique_ptr<ProofVerifier> CryptoTestUtils::ProofVerifierForTesting() {
// TODO(rch): use a real cert verifier?
std::unique_ptr<MockCertVerifier> cert_verifier(new MockCertVerifier());
net::CertVerifyResult verify_result;
@@ -106,12 +103,6 @@ std::unique_ptr<ProofVerifier> ProofVerifierForTestingInternal(
GetTestCertsDirectory(), "quic_test_ecc.example.com.crt");
cert_verifier->AddResultForCertAndHost(verify_result.verified_cert.get(),
"test.example.com", verify_result, OK);
- if (use_real_proof_verifier) {
- return base::MakeUnique<TestProofVerifierChromium>(
- std::move(cert_verifier), base::WrapUnique(new TransportSecurityState),
- base::WrapUnique(new MultiLogCTVerifier),
- base::WrapUnique(new CTPolicyEnforcer), "quic_root.crt");
- }
return base::MakeUnique<TestProofVerifierChromium>(
std::move(cert_verifier), base::WrapUnique(new TransportSecurityState),
base::WrapUnique(new MultiLogCTVerifier),
@@ -119,16 +110,6 @@ std::unique_ptr<ProofVerifier> ProofVerifierForTestingInternal(
}
// static
-std::unique_ptr<ProofVerifier> CryptoTestUtils::ProofVerifierForTesting() {
- return ProofVerifierForTestingInternal(/*use_real_proof_verifier=*/false);
-}
-
-// static
-std::unique_ptr<ProofVerifier> CryptoTestUtils::RealProofVerifierForTesting() {
- return ProofVerifierForTestingInternal(/*use_real_proof_verifier=*/true);
-}
-
-// static
ProofVerifyContext* CryptoTestUtils::ProofVerifyContextForTesting() {
return new ProofVerifyContextChromium(/*cert_verify_flags=*/0,
NetLogWithSource());
diff --git a/chromium/net/quic/test_tools/mock_crypto_client_stream_factory.cc b/chromium/net/quic/chromium/mock_crypto_client_stream_factory.cc
index dfda4db7a36..51f5c811379 100644
--- a/chromium/net/quic/test_tools/mock_crypto_client_stream_factory.cc
+++ b/chromium/net/quic/chromium/mock_crypto_client_stream_factory.cc
@@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#include "net/quic/test_tools/mock_crypto_client_stream_factory.h"
+#include "net/quic/chromium/mock_crypto_client_stream_factory.h"
#include "base/lazy_instance.h"
#include "net/quic/chromium/quic_chromium_client_session.h"
diff --git a/chromium/net/quic/test_tools/mock_crypto_client_stream_factory.h b/chromium/net/quic/chromium/mock_crypto_client_stream_factory.h
index 6f645dac6ed..c61ea05c964 100644
--- a/chromium/net/quic/test_tools/mock_crypto_client_stream_factory.h
+++ b/chromium/net/quic/chromium/mock_crypto_client_stream_factory.h
@@ -2,15 +2,15 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#ifndef NET_QUIC_TEST_TOOLS_MOCK_CRYPTO_CLIENT_STREAM_FACTORY_H_
-#define NET_QUIC_TEST_TOOLS_MOCK_CRYPTO_CLIENT_STREAM_FACTORY_H_
+#ifndef NET_QUIC_CHROMIUM_MOCK_CRYPTO_CLIENT_STREAM_FACTORY_H_
+#define NET_QUIC_CHROMIUM_MOCK_CRYPTO_CLIENT_STREAM_FACTORY_H_
#include <queue>
#include <string>
#include "base/macros.h"
#include "net/quic/chromium/crypto/proof_verifier_chromium.h"
-#include "net/quic/core/quic_crypto_client_stream_factory.h"
+#include "net/quic/chromium/quic_crypto_client_stream_factory.h"
#include "net/quic/core/quic_server_id.h"
#include "net/quic/test_tools/mock_crypto_client_stream.h"
@@ -56,4 +56,4 @@ class MockCryptoClientStreamFactory : public QuicCryptoClientStreamFactory {
} // namespace net
-#endif // NET_QUIC_TEST_TOOLS_MOCK_CRYPTO_CLIENT_STREAM_FACTORY_H_
+#endif // NET_QUIC_CHROMIUM_MOCK_CRYPTO_CLIENT_STREAM_FACTORY_H_
diff --git a/chromium/net/quic/chromium/mock_quic_data.h b/chromium/net/quic/chromium/mock_quic_data.h
index 8a1e1d27981..c58ce2e210b 100644
--- a/chromium/net/quic/chromium/mock_quic_data.h
+++ b/chromium/net/quic/chromium/mock_quic_data.h
@@ -2,7 +2,10 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#include "net/quic/core/quic_protocol.h"
+#ifndef NET_QUIC_CHROMIUM_MOCK_QUIC_DATA_H_
+#define NET_QUIC_CHROMIUM_MOCK_QUIC_DATA_H_
+
+#include "net/quic/core/quic_packets.h"
#include "net/socket/socket_test_util.h"
namespace net {
@@ -62,3 +65,5 @@ class MockQuicData {
} // namespace test
} // namespace net
+
+#endif // NET_QUIC_CHROMIUM_MOCK_QUIC_DATA_H_
diff --git a/chromium/net/quic/chromium/network_connection.h b/chromium/net/quic/chromium/network_connection.h
index 089fe34ced5..e9c64d2649a 100644
--- a/chromium/net/quic/chromium/network_connection.h
+++ b/chromium/net/quic/chromium/network_connection.h
@@ -2,8 +2,8 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#ifndef NET_QUIC_NETWORK_CONNECTION_H_
-#define NET_QUIC_NETWORK_CONNECTION_H_
+#ifndef NET_QUIC_CHROMIUM_NETWORK_CONNECTION_H_
+#define NET_QUIC_CHROMIUM_NETWORK_CONNECTION_H_
#include "base/macros.h"
#include "net/base/net_export.h"
@@ -58,4 +58,4 @@ class NET_EXPORT NetworkConnection
} // namespace net
-#endif // NET_QUIC_NETWORK_CONNECTION_H_
+#endif // NET_QUIC_CHROMIUM_NETWORK_CONNECTION_H_
diff --git a/chromium/net/quic/chromium/port_suggester.cc b/chromium/net/quic/chromium/port_suggester.cc
deleted file mode 100644
index b88ce0d98ca..00000000000
--- a/chromium/net/quic/chromium/port_suggester.cc
+++ /dev/null
@@ -1,47 +0,0 @@
-// Copyright 2013 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.
-
-#include "net/quic/chromium/port_suggester.h"
-
-#include "base/logging.h"
-
-namespace net {
-
-PortSuggester::PortSuggester(const HostPortPair& server, uint64_t seed)
- : call_count_(0), previous_suggestion_(-1) {
- unsigned char hash_bytes[base::kSHA1Length];
- base::SHA1HashBytes(
- reinterpret_cast<const unsigned char*>(server.host().data()),
- server.host().length(), hash_bytes);
- static_assert(sizeof(seed_) < sizeof(hash_bytes), "seed larger than hash");
- memcpy(&seed_, hash_bytes, sizeof(seed_));
- seed_ ^= seed ^ server.port();
-}
-
-int PortSuggester::SuggestPort(int min, int max) {
- // Sometimes our suggestion can't be used, so we ensure that if additional
- // calls are made, then each call (probably) provides a new suggestion.
- if (++call_count_ > 1) {
- // Evolve the seed.
- unsigned char hash_bytes[base::kSHA1Length];
- base::SHA1HashBytes(reinterpret_cast<const unsigned char*>(&seed_),
- sizeof(seed_), hash_bytes);
- memcpy(&seed_, hash_bytes, sizeof(seed_));
- }
- DCHECK_LE(min, max);
- DCHECK_GT(min, 0);
- int range = max - min + 1;
- // Ports (and hence the extent of the |range|) are generally under 2^16, so
- // the tiny non-uniformity in the pseudo-random distribution is not
- // significant.
- previous_suggestion_ = static_cast<int>(seed_ % range) + min;
- return previous_suggestion_;
-}
-
-int PortSuggester::previous_suggestion() const {
- DCHECK_LT(0u, call_count_);
- return previous_suggestion_;
-}
-
-} // namespace net
diff --git a/chromium/net/quic/chromium/port_suggester.h b/chromium/net/quic/chromium/port_suggester.h
deleted file mode 100644
index d3f41a316ee..00000000000
--- a/chromium/net/quic/chromium/port_suggester.h
+++ /dev/null
@@ -1,51 +0,0 @@
-// Copyright 2013 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.
-
-#ifndef NET_QUIC_PORT_SUGGESTER_H_
-#define NET_QUIC_PORT_SUGGESTER_H_
-
-#include <stdint.h>
-
-#include "base/macros.h"
-#include "base/memory/ref_counted.h"
-#include "base/sha1.h"
-#include "net/base/host_port_pair.h"
-#include "net/base/net_export.h"
-
-namespace net {
-
-// We provide a pseudo-random number generator that is always seeded the same
-// way for a given destination host-port pair. The generator is used to
-// consistently suggest (for that host-port pair) an ephemeral source port,
-// and hence increase the likelihood that a server's load balancer will direct
-// a repeated connection to the same server (with QUIC, further increasing the
-// chance of connection establishment with 0-RTT).
-class NET_EXPORT_PRIVATE PortSuggester
- : public base::RefCounted<PortSuggester> {
- public:
- PortSuggester(const HostPortPair& server, uint64_t seed);
-
- // Generate a pseudo-random int in the inclusive range from |min| to |max|.
- // Will (probably) return different numbers when called repeatedly.
- int SuggestPort(int min, int max);
-
- uint32_t call_count() const { return call_count_; }
- int previous_suggestion() const;
-
- private:
- friend class base::RefCounted<PortSuggester>;
-
- virtual ~PortSuggester() {}
-
- // We maintain the first 8 bytes of a hash as our seed_ state.
- uint64_t seed_;
- uint32_t call_count_; // Number of suggestions made.
- int previous_suggestion_;
-
- DISALLOW_COPY_AND_ASSIGN(PortSuggester);
-};
-
-} // namespace net
-
-#endif // NET_QUIC_PORT_SUGGESTER_H_
diff --git a/chromium/net/quic/chromium/port_suggester_unittest.cc b/chromium/net/quic/chromium/port_suggester_unittest.cc
deleted file mode 100644
index 5bf757bde20..00000000000
--- a/chromium/net/quic/chromium/port_suggester_unittest.cc
+++ /dev/null
@@ -1,108 +0,0 @@
-// Copyright 2013 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.
-
-#include "net/quic/chromium/port_suggester.h"
-
-#include <set>
-
-#include "testing/gtest/include/gtest/gtest.h"
-
-namespace net {
-namespace test {
-
-class PortSuggesterTest : public ::testing::Test {
- protected:
- PortSuggesterTest()
- : entropy_(1345689),
- min_ephemeral_port_(1025),
- max_ephemeral_port_(65535) {}
-
- uint64_t entropy_;
- int min_ephemeral_port_;
- int max_ephemeral_port_;
-};
-
-TEST_F(PortSuggesterTest, SmallRangeTest) {
- // When the range is small (one wide), we always get that as our answer.
- scoped_refptr<PortSuggester> port_suggester =
- new PortSuggester(HostPortPair("www.example.com", 443), entropy_);
- // Test this for a few different (small) ranges.
- for (int port = 2000; port < 2010; ++port) {
- // Use |port| for both |min| and |max| delimiting the suggestion range.
- EXPECT_EQ(port, port_suggester->SuggestPort(port, port));
- EXPECT_EQ(port, port_suggester->previous_suggestion());
- }
-}
-
-TEST_F(PortSuggesterTest, SuggestAllPorts) {
- // We should eventually fill out any range, but we'll just ensure that we
- // fill out a small range of ports.
- scoped_refptr<PortSuggester> port_suggester =
- new PortSuggester(HostPortPair("www.example.com", 443), entropy_);
- std::set<int> ports;
- const uint32_t port_range = 20;
- const int insertion_limit = 200; // We should be done by then.
- for (int i = 0; i < insertion_limit; ++i) {
- ports.insert(port_suggester->SuggestPort(
- min_ephemeral_port_, min_ephemeral_port_ + port_range - 1));
- if (ports.size() == port_range) {
- break;
- }
- }
- EXPECT_EQ(port_range, ports.size());
-}
-
-TEST_F(PortSuggesterTest, AvoidDuplication) {
- // When the range is large, duplicates are rare, but we'll ask for a few
- // suggestions and make sure they are unique.
- scoped_refptr<PortSuggester> port_suggester =
- new PortSuggester(HostPortPair("www.example.com", 80), entropy_);
- std::set<int> ports;
- const size_t port_count = 200;
- for (size_t i = 0; i < port_count; ++i) {
- ports.insert(
- port_suggester->SuggestPort(min_ephemeral_port_, max_ephemeral_port_));
- }
- EXPECT_EQ(port_suggester->call_count(), port_count);
- EXPECT_EQ(port_count, ports.size());
-}
-
-TEST_F(PortSuggesterTest, ConsistentPorts) {
- // For given hostname, port, and entropy, we should always get the same
- // suggestions.
- scoped_refptr<PortSuggester> port_suggester1 =
- new PortSuggester(HostPortPair("www.example.com", 443), entropy_);
- scoped_refptr<PortSuggester> port_suggester2 =
- new PortSuggester(HostPortPair("www.example.com", 443), entropy_);
- for (int test_count = 20; test_count > 0; --test_count) {
- EXPECT_EQ(
- port_suggester1->SuggestPort(min_ephemeral_port_, min_ephemeral_port_),
- port_suggester2->SuggestPort(min_ephemeral_port_, min_ephemeral_port_));
- }
-}
-
-TEST_F(PortSuggesterTest, DifferentHostPortEntropy) {
- // When we have different hosts, port, or entropy, we probably won't collide.
- scoped_refptr<PortSuggester> port_suggester[] = {
- new PortSuggester(HostPortPair("www.example.com", 80), entropy_),
- new PortSuggester(HostPortPair("www.example.ORG", 80), entropy_),
- new PortSuggester(HostPortPair("www.example.com", 443), entropy_),
- new PortSuggester(HostPortPair("www.example.com", 80), entropy_ + 123456),
- };
-
- std::set<int> ports;
- const int port_count = 40;
- size_t insertion_count = 0;
- for (size_t j = 0; j < arraysize(port_suggester); ++j) {
- for (int i = 0; i < port_count; ++i) {
- ports.insert(port_suggester[j]->SuggestPort(min_ephemeral_port_,
- max_ephemeral_port_));
- ++insertion_count;
- }
- }
- EXPECT_EQ(insertion_count, ports.size());
-}
-
-} // namespace test
-} // namespace net
diff --git a/chromium/net/quic/core/crypto/properties_based_quic_server_info.cc b/chromium/net/quic/chromium/properties_based_quic_server_info.cc
index 0ab4f6cef1a..38814545bb1 100644
--- a/chromium/net/quic/core/crypto/properties_based_quic_server_info.cc
+++ b/chromium/net/quic/chromium/properties_based_quic_server_info.cc
@@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#include "net/quic/core/crypto/properties_based_quic_server_info.h"
+#include "net/quic/chromium/properties_based_quic_server_info.h"
#include "base/base64.h"
#include "base/metrics/histogram_macros.h"
diff --git a/chromium/net/quic/core/crypto/properties_based_quic_server_info.h b/chromium/net/quic/chromium/properties_based_quic_server_info.h
index 276c8ef6c4a..6fe9f78da6c 100644
--- a/chromium/net/quic/core/crypto/properties_based_quic_server_info.h
+++ b/chromium/net/quic/chromium/properties_based_quic_server_info.h
@@ -2,8 +2,8 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#ifndef NET_QUIC_CRYPTO_PROPERTIES_BASED_QUIC_SERVER_INFO_H_
-#define NET_QUIC_CRYPTO_PROPERTIES_BASED_QUIC_SERVER_INFO_H_
+#ifndef NET_QUIC_CHROMIUM_PROPERTIES_BASED_QUIC_SERVER_INFO_H_
+#define NET_QUIC_CHROMIUM_PROPERTIES_BASED_QUIC_SERVER_INFO_H_
#include <string>
#include <vector>
@@ -11,8 +11,8 @@
#include "base/macros.h"
#include "base/memory/weak_ptr.h"
#include "net/base/completion_callback.h"
-#include "net/base/net_export.h"
-#include "net/quic/core/crypto/quic_server_info.h"
+#include "net/quic/chromium/quic_server_info.h"
+#include "net/quic/platform/api/quic_export.h"
namespace net {
@@ -21,7 +21,8 @@ class HttpServerProperties;
// PropertiesBasedQuicServerInfo fetches information about a QUIC server from
// HttpServerProperties. Since the information is defined to be non-sensitive,
// it's ok for us to keep it on disk.
-class NET_EXPORT_PRIVATE PropertiesBasedQuicServerInfo : public QuicServerInfo {
+class QUIC_EXPORT_PRIVATE PropertiesBasedQuicServerInfo
+ : public QuicServerInfo {
public:
PropertiesBasedQuicServerInfo(const QuicServerId& server_id,
HttpServerProperties* http_server_properties);
@@ -43,7 +44,7 @@ class NET_EXPORT_PRIVATE PropertiesBasedQuicServerInfo : public QuicServerInfo {
DISALLOW_COPY_AND_ASSIGN(PropertiesBasedQuicServerInfo);
};
-class NET_EXPORT_PRIVATE PropertiesBasedQuicServerInfoFactory
+class QUIC_EXPORT_PRIVATE PropertiesBasedQuicServerInfoFactory
: public QuicServerInfoFactory {
public:
explicit PropertiesBasedQuicServerInfoFactory(
@@ -60,4 +61,4 @@ class NET_EXPORT_PRIVATE PropertiesBasedQuicServerInfoFactory
} // namespace net
-#endif // NET_QUIC_CRYPTO_PROPERTIES_BASED_QUIC_SERVER_INFO_H_
+#endif // NET_QUIC_CHROMIUM_PROPERTIES_BASED_QUIC_SERVER_INFO_H_
diff --git a/chromium/net/quic/core/crypto/properties_based_quic_server_info_test.cc b/chromium/net/quic/chromium/properties_based_quic_server_info_test.cc
index 747905f122e..aba7c635f48 100644
--- a/chromium/net/quic/core/crypto/properties_based_quic_server_info_test.cc
+++ b/chromium/net/quic/chromium/properties_based_quic_server_info_test.cc
@@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#include "net/quic/core/crypto/properties_based_quic_server_info.h"
+#include "net/quic/chromium/properties_based_quic_server_info.h"
#include <string>
diff --git a/chromium/net/quic/core/quic_address_mismatch.cc b/chromium/net/quic/chromium/quic_address_mismatch.cc
index b37fb096f7d..7ee84c94bb2 100644
--- a/chromium/net/quic/core/quic_address_mismatch.cc
+++ b/chromium/net/quic/chromium/quic_address_mismatch.cc
@@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#include "net/quic/core/quic_address_mismatch.h"
+#include "net/quic/chromium/quic_address_mismatch.h"
#include "base/logging.h"
#include "net/base/ip_address.h"
diff --git a/chromium/net/quic/core/quic_address_mismatch.h b/chromium/net/quic/chromium/quic_address_mismatch.h
index 0ac09a261db..55271694a2c 100644
--- a/chromium/net/quic/core/quic_address_mismatch.h
+++ b/chromium/net/quic/chromium/quic_address_mismatch.h
@@ -2,8 +2,8 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#ifndef NET_QUIC_QUIC_ADDRESS_MISMATCH_H_
-#define NET_QUIC_QUIC_ADDRESS_MISMATCH_H_
+#ifndef NET_QUIC_CHROMIUM_QUIC_ADDRESS_MISMATCH_H_
+#define NET_QUIC_CHROMIUM_QUIC_ADDRESS_MISMATCH_H_
#include "net/base/ip_endpoint.h"
#include "net/base/net_export.h"
@@ -40,4 +40,4 @@ NET_EXPORT_PRIVATE int GetAddressMismatch(const IPEndPoint& first_address,
} // namespace net
-#endif // NET_QUIC_QUIC_ADDRESS_MISMATCH_H_
+#endif // NET_QUIC_CHROMIUM_QUIC_ADDRESS_MISMATCH_H_
diff --git a/chromium/net/quic/core/quic_address_mismatch_test.cc b/chromium/net/quic/chromium/quic_address_mismatch_test.cc
index 63aa627ccf2..3da13789897 100644
--- a/chromium/net/quic/core/quic_address_mismatch_test.cc
+++ b/chromium/net/quic/chromium/quic_address_mismatch_test.cc
@@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#include "net/quic/core/quic_address_mismatch.h"
+#include "net/quic/chromium/quic_address_mismatch.h"
#include "testing/gtest/include/gtest/gtest.h"
diff --git a/chromium/net/quic/chromium/quic_chromium_alarm_factory.h b/chromium/net/quic/chromium/quic_chromium_alarm_factory.h
index 436379c8fee..e033de18365 100644
--- a/chromium/net/quic/chromium/quic_chromium_alarm_factory.h
+++ b/chromium/net/quic/chromium/quic_chromium_alarm_factory.h
@@ -5,8 +5,8 @@
// The Chrome-specific helper for QuicConnection which uses
// a TaskRunner for alarms, and uses a DatagramClientSocket for writing data.
-#ifndef NET_QUIC_QUIC_CHROMIUM_ALARM_FACTORY_H_
-#define NET_QUIC_QUIC_CHROMIUM_ALARM_FACTORY_H_
+#ifndef NET_QUIC_CHROMIUM_QUIC_CHROMIUM_ALARM_FACTORY_H_
+#define NET_QUIC_CHROMIUM_QUIC_CHROMIUM_ALARM_FACTORY_H_
#include <set>
@@ -14,9 +14,9 @@
#include "base/memory/weak_ptr.h"
#include "net/base/net_export.h"
#include "net/quic/core/quic_alarm_factory.h"
-#include "net/quic/core/quic_clock.h"
-#include "net/quic/core/quic_protocol.h"
+#include "net/quic/core/quic_packets.h"
#include "net/quic/core/quic_time.h"
+#include "net/quic/platform/api/quic_clock.h"
namespace base {
class TaskRunner;
@@ -46,4 +46,4 @@ class NET_EXPORT_PRIVATE QuicChromiumAlarmFactory : public QuicAlarmFactory {
} // namespace net
-#endif // NET_QUIC_QUIC_CHROMIUM_ALARM_FACTORY_H_
+#endif // NET_QUIC_CHROMIUM_QUIC_CHROMIUM_ALARM_FACTORY_H_
diff --git a/chromium/net/quic/chromium/quic_chromium_client_session.cc b/chromium/net/quic/chromium/quic_chromium_client_session.cc
index a67653331a3..96a8eea48f3 100644
--- a/chromium/net/quic/chromium/quic_chromium_client_session.cc
+++ b/chromium/net/quic/chromium/quic_chromium_client_session.cc
@@ -26,10 +26,10 @@
#include "net/quic/chromium/crypto/proof_verifier_chromium.h"
#include "net/quic/chromium/quic_chromium_connection_helper.h"
#include "net/quic/chromium/quic_chromium_packet_writer.h"
+#include "net/quic/chromium/quic_crypto_client_stream_factory.h"
+#include "net/quic/chromium/quic_server_info.h"
#include "net/quic/chromium/quic_stream_factory.h"
-#include "net/quic/core/crypto/quic_server_info.h"
#include "net/quic/core/quic_client_promised_info.h"
-#include "net/quic/core/quic_crypto_client_stream_factory.h"
#include "net/quic/core/spdy_utils.h"
#include "net/socket/datagram_client_socket.h"
#include "net/spdy/spdy_http_utils.h"
@@ -147,7 +147,7 @@ std::unique_ptr<base::Value> NetLogQuicPushPromiseReceivedCallback(
return std::move(dict);
}
-class HpackEncoderDebugVisitor : public QuicHeadersStream::HpackDebugVisitor {
+class HpackEncoderDebugVisitor : public QuicHpackDebugVisitor {
void OnUseEntry(QuicTime::Delta elapsed) override {
UMA_HISTOGRAM_TIMES(
"Net.QuicHpackEncoder.IndexedEntryAge",
@@ -155,7 +155,7 @@ class HpackEncoderDebugVisitor : public QuicHeadersStream::HpackDebugVisitor {
}
};
-class HpackDecoderDebugVisitor : public QuicHeadersStream::HpackDebugVisitor {
+class HpackDecoderDebugVisitor : public QuicHpackDebugVisitor {
void OnUseEntry(QuicTime::Delta elapsed) override {
UMA_HISTOGRAM_TIMES(
"Net.QuicHpackDecoder.IndexedEntryAge",
@@ -243,6 +243,7 @@ QuicChromiumClientSession::QuicChromiumClientSession(
base::TimeTicks dns_resolution_start_time,
base::TimeTicks dns_resolution_end_time,
QuicClientPushPromiseIndex* push_promise_index,
+ ServerPushDelegate* push_delegate,
base::TaskRunner* task_runner,
std::unique_ptr<SocketPerformanceWatcher> socket_performance_watcher,
NetLog* net_log)
@@ -263,7 +264,7 @@ QuicChromiumClientSession::QuicChromiumClientSession(
going_away_(false),
port_migration_detected_(false),
token_binding_signatures_(kTokenBindingSignatureMapSize),
- push_delegate_(nullptr),
+ push_delegate_(push_delegate),
streams_pushed_count_(0),
streams_pushed_and_claimed_count_(0),
bytes_pushed_count_(0),
@@ -311,7 +312,9 @@ QuicChromiumClientSession::~QuicChromiumClientSession() {
CloseAllObservers(ERR_UNEXPECTED);
connection()->set_debug_visitor(nullptr);
- net_log_.EndEvent(NetLogEventType::QUIC_SESSION);
+
+ UMA_HISTOGRAM_COUNTS_1000("Net.QuicSession.AbortedPendingStreamRequests",
+ stream_requests_.size());
while (!stream_requests_.empty()) {
StreamRequest* request = stream_requests_.front();
@@ -356,18 +359,15 @@ QuicChromiumClientSession::~QuicChromiumClientSession() {
if (round_trip_handshakes < 0 || !stream_factory_)
return;
- bool port_selected = stream_factory_->enable_port_selection();
SSLInfo ssl_info;
// QUIC supports only secure urls.
if (GetSSLInfo(&ssl_info) && ssl_info.cert.get()) {
- if (!port_selected) {
- UMA_HISTOGRAM_CUSTOM_COUNTS("Net.QuicSession.ConnectRandomPortForHTTPS",
- round_trip_handshakes, 1, 3, 4);
- if (require_confirmation_) {
- UMA_HISTOGRAM_CUSTOM_COUNTS(
- "Net.QuicSession.ConnectRandomPortRequiringConfirmationForHTTPS",
- round_trip_handshakes, 1, 3, 4);
- }
+ UMA_HISTOGRAM_CUSTOM_COUNTS("Net.QuicSession.ConnectRandomPortForHTTPS",
+ round_trip_handshakes, 1, 3, 4);
+ if (require_confirmation_) {
+ UMA_HISTOGRAM_CUSTOM_COUNTS(
+ "Net.QuicSession.ConnectRandomPortRequiringConfirmationForHTTPS",
+ round_trip_handshakes, 1, 3, 4);
}
}
const QuicConnectionStats stats = connection()->GetStats();
@@ -424,13 +424,14 @@ QuicChromiumClientSession::~QuicChromiumClientSession() {
UMA_HISTOGRAM_COUNTS(
"Net.QuicSession.MaxReordering",
static_cast<base::HistogramBase::Sample>(stats.max_sequence_reordering));
+ net_log_.EndEvent(NetLogEventType::QUIC_SESSION);
}
void QuicChromiumClientSession::Initialize() {
QuicClientSessionBase::Initialize();
- headers_stream()->SetHpackEncoderDebugVisitor(
+ SetHpackEncoderDebugVisitor(
base::MakeUnique<HpackEncoderDebugVisitor>());
- headers_stream()->SetHpackDecoderDebugVisitor(
+ SetHpackDecoderDebugVisitor(
base::MakeUnique<HpackDecoderDebugVisitor>());
}
@@ -490,7 +491,10 @@ int QuicChromiumClientSession::TryCreateStream(
return OK;
}
+ request->pending_start_time_ = base::TimeTicks::Now();
stream_requests_.push_back(request);
+ UMA_HISTOGRAM_COUNTS_1000("Net.QuicSession.NumPendingStreamRequests",
+ stream_requests_.size());
return ERR_IO_PENDING;
}
@@ -557,6 +561,11 @@ QuicCryptoClientStream* QuicChromiumClientSession::GetCryptoStream() {
return crypto_stream_.get();
}
+bool QuicChromiumClientSession::GetRemoteEndpoint(IPEndPoint* endpoint) {
+ *endpoint = peer_address().impl().socket_address();
+ return true;
+}
+
// TODO(rtenneti): Add unittests for GetSSLInfo which exercise the various ways
// we learn about SSL info (sync vs async vs cached).
bool QuicChromiumClientSession::GetSSLInfo(SSLInfo* ssl_info) const {
@@ -796,6 +805,10 @@ void QuicChromiumClientSession::OnClosedStream() {
!stream_requests_.empty() && crypto_stream_->encryption_established() &&
!goaway_received() && !going_away_ && connection()->connected()) {
StreamRequest* request = stream_requests_.front();
+ // TODO(ckrasic) - analyze data and then add logic to mark QUIC
+ // broken if wait times are excessive.
+ UMA_HISTOGRAM_TIMES("Net.QuicSession.PendingStreamsWaitTime",
+ base::TimeTicks::Now() - request->pending_start_time_);
stream_requests_.pop_front();
request->OnRequestCompleteSuccess(CreateOutgoingReliableStreamImpl());
}
@@ -811,7 +824,8 @@ void QuicChromiumClientSession::OnConfigNegotiated() {
return;
// Server has sent an alternate address to connect to.
- IPEndPoint new_address = config()->ReceivedAlternateServerAddress();
+ IPEndPoint new_address =
+ config()->ReceivedAlternateServerAddress().impl().socket_address();
IPEndPoint old_address;
GetDefaultSocket()->GetPeerAddress(&old_address);
@@ -1339,7 +1353,9 @@ void QuicChromiumClientSession::OnReadError(
bool QuicChromiumClientSession::OnPacket(const QuicReceivedPacket& packet,
IPEndPoint local_address,
IPEndPoint peer_address) {
- ProcessUdpPacket(local_address, peer_address, packet);
+ ProcessUdpPacket(QuicSocketAddress(QuicSocketAddressImpl(local_address)),
+ QuicSocketAddress(QuicSocketAddressImpl(peer_address)),
+ packet);
if (!connection()->connected()) {
NotifyFactoryOfSessionClosedLater();
return false;
diff --git a/chromium/net/quic/chromium/quic_chromium_client_session.h b/chromium/net/quic/chromium/quic_chromium_client_session.h
index 04eeda4a4b3..1276e55a273 100644
--- a/chromium/net/quic/chromium/quic_chromium_client_session.h
+++ b/chromium/net/quic/chromium/quic_chromium_client_session.h
@@ -7,8 +7,8 @@
// a non-owning pointer to the helper so this session needs to ensure that
// the helper outlives the connection.
-#ifndef NET_QUIC_QUIC_CHROMIUM_CLIENT_SESSION_H_
-#define NET_QUIC_QUIC_CHROMIUM_CLIENT_SESSION_H_
+#ifndef NET_QUIC_CHROMIUM_QUIC_CHROMIUM_CLIENT_SESSION_H_
+#define NET_QUIC_CHROMIUM_QUIC_CHROMIUM_CLIENT_SESSION_H_
#include <stddef.h>
@@ -34,10 +34,11 @@
#include "net/quic/chromium/quic_connection_logger.h"
#include "net/quic/core/quic_client_session_base.h"
#include "net/quic/core/quic_crypto_client_stream.h"
-#include "net/quic/core/quic_protocol.h"
+#include "net/quic/core/quic_packets.h"
#include "net/quic/core/quic_server_id.h"
#include "net/quic/core/quic_time.h"
#include "net/socket/socket_performance_watcher.h"
+#include "net/spdy/multiplexed_session.h"
#include "net/spdy/server_push_delegate.h"
namespace net {
@@ -61,6 +62,7 @@ class QuicChromiumClientSessionPeer;
class NET_EXPORT_PRIVATE QuicChromiumClientSession
: public QuicClientSessionBase,
+ public MultiplexedSession,
public QuicChromiumPacketReader::Visitor,
public QuicChromiumPacketWriter::Delegate {
public:
@@ -106,6 +108,8 @@ class NET_EXPORT_PRIVATE QuicChromiumClientSession
base::WeakPtr<QuicChromiumClientSession> session_;
CompletionCallback callback_;
QuicChromiumClientStream** stream_;
+ // For tracking how much time pending stream requests wait.
+ base::TimeTicks pending_start_time_;
DISALLOW_COPY_AND_ASSIGN(StreamRequest);
};
@@ -131,6 +135,7 @@ class NET_EXPORT_PRIVATE QuicChromiumClientSession
base::TimeTicks dns_resolution_start_time,
base::TimeTicks dns_resolution_end_time,
QuicClientPushPromiseIndex* push_promise_index,
+ ServerPushDelegate* push_delegate,
base::TaskRunner* task_runner,
std::unique_ptr<SocketPerformanceWatcher> socket_performance_watcher,
NetLog* net_log);
@@ -200,15 +205,12 @@ class NET_EXPORT_PRIVATE QuicChromiumClientSession
IPEndPoint local_address,
IPEndPoint peer_address) override;
- // Gets the SSL connection information.
- bool GetSSLInfo(SSLInfo* ssl_info) const;
-
- // Generates the signature used in Token Binding using key |*key| and for a
- // Token Binding of type |tb_type|, putting the signature in |*out|. Returns a
- // net error code.
+ // MultiplexedSession methods:
+ bool GetRemoteEndpoint(IPEndPoint* endpoint) override;
+ bool GetSSLInfo(SSLInfo* ssl_info) const override;
Error GetTokenBindingSignature(crypto::ECPrivateKey* key,
TokenBindingType tb_type,
- std::vector<uint8_t>* out);
+ std::vector<uint8_t>* out) override;
// Performs a crypto handshake with the server.
int CryptoConnect(bool require_confirmation,
@@ -307,10 +309,6 @@ class NET_EXPORT_PRIVATE QuicChromiumClientSession
void OnPushStreamTimedOut(QuicStreamId stream_id) override;
- void set_push_delegate(ServerPushDelegate* push_delegate) {
- push_delegate_ = push_delegate;
- }
-
// Cancels the push if the push stream for |url| has not been claimed and is
// still active. Otherwise, no-op.
void CancelPush(const GURL& url);
@@ -416,4 +414,4 @@ class NET_EXPORT_PRIVATE QuicChromiumClientSession
} // namespace net
-#endif // NET_QUIC_QUIC_CHROMIUM_CLIENT_SESSION_H_
+#endif // NET_QUIC_CHROMIUM_QUIC_CHROMIUM_CLIENT_SESSION_H_
diff --git a/chromium/net/quic/chromium/quic_chromium_client_session_peer.h b/chromium/net/quic/chromium/quic_chromium_client_session_peer.h
index a781fa510ee..39dbb8a54b1 100644
--- a/chromium/net/quic/chromium/quic_chromium_client_session_peer.h
+++ b/chromium/net/quic/chromium/quic_chromium_client_session_peer.h
@@ -2,15 +2,15 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#ifndef NET_QUIC_TEST_TOOLS_QUIC_CHROMIUM_CLIENT_SESSION_PEER_H_
-#define NET_QUIC_TEST_TOOLS_QUIC_CHROMIUM_CLIENT_SESSION_PEER_H_
+#ifndef NET_QUIC_CHROMIUM_QUIC_CHROMIUM_CLIENT_SESSION_PEER_H_
+#define NET_QUIC_CHROMIUM_QUIC_CHROMIUM_CLIENT_SESSION_PEER_H_
#include <stddef.h>
#include <string>
#include "base/macros.h"
-#include "net/quic/core/quic_protocol.h"
+#include "net/quic/core/quic_packets.h"
namespace net {
@@ -42,4 +42,4 @@ class QuicChromiumClientSessionPeer {
} // namespace test
} // namespace net
-#endif // NET_QUIC_TEST_TOOLS_QUIC_CHROMIUM_CLIENT_SESSION_PEER_H_
+#endif // NET_QUIC_CHROMIUM_QUIC_CHROMIUM_CLIENT_SESSION_PEER_H_
diff --git a/chromium/net/quic/chromium/quic_chromium_client_session_test.cc b/chromium/net/quic/chromium/quic_chromium_client_session_test.cc
index 4d289d3a1c2..77f6400ebb3 100644
--- a/chromium/net/quic/chromium/quic_chromium_client_session_test.cc
+++ b/chromium/net/quic/chromium/quic_chromium_client_session_test.cc
@@ -17,26 +17,26 @@
#include "net/log/net_log_source.h"
#include "net/log/test_net_log.h"
#include "net/quic/chromium/crypto/proof_verifier_chromium.h"
+#include "net/quic/chromium/mock_crypto_client_stream_factory.h"
#include "net/quic/chromium/quic_chromium_alarm_factory.h"
#include "net/quic/chromium/quic_chromium_client_session_peer.h"
#include "net/quic/chromium/quic_chromium_connection_helper.h"
#include "net/quic/chromium/quic_chromium_packet_reader.h"
#include "net/quic/chromium/quic_chromium_packet_writer.h"
+#include "net/quic/chromium/quic_crypto_client_stream_factory.h"
+#include "net/quic/chromium/quic_http_utils.h"
+#include "net/quic/chromium/quic_server_info.h"
+#include "net/quic/chromium/quic_test_packet_maker.h"
#include "net/quic/core/crypto/aes_128_gcm_12_encrypter.h"
#include "net/quic/core/crypto/crypto_protocol.h"
#include "net/quic/core/crypto/quic_decrypter.h"
#include "net/quic/core/crypto/quic_encrypter.h"
-#include "net/quic/core/crypto/quic_server_info.h"
#include "net/quic/core/quic_client_promised_info.h"
-#include "net/quic/core/quic_crypto_client_stream_factory.h"
#include "net/quic/core/quic_flags.h"
-#include "net/quic/core/quic_http_utils.h"
#include "net/quic/core/quic_packet_writer.h"
#include "net/quic/test_tools/crypto_test_utils.h"
-#include "net/quic/test_tools/mock_crypto_client_stream_factory.h"
#include "net/quic/test_tools/quic_client_promised_info_peer.h"
#include "net/quic/test_tools/quic_spdy_session_peer.h"
-#include "net/quic/test_tools/quic_test_packet_maker.h"
#include "net/quic/test_tools/quic_test_utils.h"
#include "net/quic/test_tools/simple_quic_framer.h"
#include "net/socket/datagram_client_socket.h"
@@ -112,8 +112,9 @@ class QuicChromiumClientSessionTest
QuicChromiumPacketWriter* writer =
new net::QuicChromiumPacketWriter(socket.get());
QuicConnection* connection = new QuicConnection(
- 0, kIpEndPoint, &helper_, &alarm_factory_, writer, true,
- Perspective::IS_CLIENT, SupportedVersions(GetParam()));
+ 0, QuicSocketAddress(QuicSocketAddressImpl(kIpEndPoint)), &helper_,
+ &alarm_factory_, writer, true, Perspective::IS_CLIENT,
+ SupportedVersions(GetParam()));
session_.reset(new QuicChromiumClientSession(
connection, std::move(socket),
/*stream_factory=*/nullptr, &crypto_client_stream_factory_, &clock_,
@@ -124,7 +125,8 @@ class QuicChromiumClientSessionTest
QuicTime::Delta::FromMilliseconds(kQuicYieldAfterDurationMilliseconds),
/*cert_verify_flags=*/0, DefaultQuicConfig(), &crypto_config_,
"CONNECTION_UNKNOWN", base::TimeTicks::Now(), base::TimeTicks::Now(),
- &push_promise_index_, base::ThreadTaskRunnerHandle::Get().get(),
+ &push_promise_index_, &test_push_delegate_,
+ base::ThreadTaskRunnerHandle::Get().get(),
/*socket_performance_watcher=*/nullptr, &net_log_));
scoped_refptr<X509Certificate> cert(
@@ -180,16 +182,30 @@ INSTANTIATE_TEST_CASE_P(Tests,
::testing::ValuesIn(AllSupportedVersions()));
TEST_P(QuicChromiumClientSessionTest, CryptoConnect) {
+ MockRead reads[] = {MockRead(SYNCHRONOUS, ERR_IO_PENDING, 0)};
+ std::unique_ptr<QuicEncryptedPacket> settings_packet(
+ client_maker_.MakeSettingsPacket(1, SETTINGS_MAX_HEADER_LIST_SIZE,
+ kDefaultMaxUncompressedHeaderSize, true,
+ nullptr));
+ MockWrite writes[] = {
+ MockWrite(ASYNC, settings_packet->data(), settings_packet->length(), 1)};
+ socket_data_.reset(new SequencedSocketData(reads, arraysize(reads), writes,
+ arraysize(writes)));
Initialize();
CompleteCryptoHandshake();
}
TEST_P(QuicChromiumClientSessionTest, MaxNumStreams) {
MockRead reads[] = {MockRead(SYNCHRONOUS, ERR_IO_PENDING, 0)};
+ std::unique_ptr<QuicEncryptedPacket> settings_packet(
+ client_maker_.MakeSettingsPacket(1, SETTINGS_MAX_HEADER_LIST_SIZE,
+ kDefaultMaxUncompressedHeaderSize, true,
+ nullptr));
std::unique_ptr<QuicEncryptedPacket> client_rst(client_maker_.MakeRstPacket(
- 1, true, kClientDataStreamId1, QUIC_RST_ACKNOWLEDGEMENT));
+ 2, true, kClientDataStreamId1, QUIC_RST_ACKNOWLEDGEMENT));
MockWrite writes[] = {
- MockWrite(ASYNC, client_rst->data(), client_rst->length(), 1)};
+ MockWrite(ASYNC, settings_packet->data(), settings_packet->length(), 1),
+ MockWrite(ASYNC, client_rst->data(), client_rst->length(), 2)};
socket_data_.reset(new SequencedSocketData(reads, arraysize(reads), writes,
arraysize(writes)));
@@ -222,10 +238,15 @@ TEST_P(QuicChromiumClientSessionTest, MaxNumStreams) {
TEST_P(QuicChromiumClientSessionTest, PushStreamTimedOutNoResponse) {
base::HistogramTester histogram_tester;
MockRead reads[] = {MockRead(SYNCHRONOUS, ERR_IO_PENDING, 0)};
+ std::unique_ptr<QuicEncryptedPacket> settings_packet(
+ client_maker_.MakeSettingsPacket(1, SETTINGS_MAX_HEADER_LIST_SIZE,
+ kDefaultMaxUncompressedHeaderSize, true,
+ nullptr));
std::unique_ptr<QuicEncryptedPacket> client_rst(client_maker_.MakeRstPacket(
- 1, true, kServerDataStreamId1, QUIC_PUSH_STREAM_TIMED_OUT));
+ 2, true, kServerDataStreamId1, QUIC_PUSH_STREAM_TIMED_OUT));
MockWrite writes[] = {
- MockWrite(ASYNC, client_rst->data(), client_rst->length(), 1)};
+ MockWrite(ASYNC, settings_packet->data(), settings_packet->length(), 1),
+ MockWrite(ASYNC, client_rst->data(), client_rst->length(), 2)};
socket_data_.reset(new SequencedSocketData(reads, arraysize(reads), writes,
arraysize(writes)));
Initialize();
@@ -268,10 +289,15 @@ TEST_P(QuicChromiumClientSessionTest, PushStreamTimedOutNoResponse) {
TEST_P(QuicChromiumClientSessionTest, PushStreamTimedOutWithResponse) {
base::HistogramTester histogram_tester;
MockRead reads[] = {MockRead(SYNCHRONOUS, ERR_IO_PENDING, 0)};
+ std::unique_ptr<QuicEncryptedPacket> settings_packet(
+ client_maker_.MakeSettingsPacket(1, SETTINGS_MAX_HEADER_LIST_SIZE,
+ kDefaultMaxUncompressedHeaderSize, true,
+ nullptr));
std::unique_ptr<QuicEncryptedPacket> client_rst(client_maker_.MakeRstPacket(
- 1, true, kServerDataStreamId1, QUIC_PUSH_STREAM_TIMED_OUT));
+ 2, true, kServerDataStreamId1, QUIC_PUSH_STREAM_TIMED_OUT));
MockWrite writes[] = {
- MockWrite(ASYNC, client_rst->data(), client_rst->length(), 1)};
+ MockWrite(ASYNC, settings_packet->data(), settings_packet->length(), 1),
+ MockWrite(ASYNC, client_rst->data(), client_rst->length(), 2)};
socket_data_.reset(new SequencedSocketData(reads, arraysize(reads), writes,
arraysize(writes)));
Initialize();
@@ -316,15 +342,19 @@ TEST_P(QuicChromiumClientSessionTest, PushStreamTimedOutWithResponse) {
TEST_P(QuicChromiumClientSessionTest, CancelPushWhenPendingValidation) {
MockRead reads[] = {MockRead(SYNCHRONOUS, ERR_IO_PENDING, 0)};
+ std::unique_ptr<QuicEncryptedPacket> settings_packet(
+ client_maker_.MakeSettingsPacket(1, SETTINGS_MAX_HEADER_LIST_SIZE,
+ kDefaultMaxUncompressedHeaderSize, true,
+ nullptr));
std::unique_ptr<QuicEncryptedPacket> client_rst(client_maker_.MakeRstPacket(
- 1, true, kClientDataStreamId1, QUIC_RST_ACKNOWLEDGEMENT));
+ 2, true, kClientDataStreamId1, QUIC_RST_ACKNOWLEDGEMENT));
MockWrite writes[] = {
- MockWrite(ASYNC, client_rst->data(), client_rst->length(), 1)};
+ MockWrite(ASYNC, settings_packet->data(), settings_packet->length(), 1),
+ MockWrite(ASYNC, client_rst->data(), client_rst->length(), 2)};
socket_data_.reset(new SequencedSocketData(reads, arraysize(reads), writes,
arraysize(writes)));
Initialize();
- session_->set_push_delegate(&test_push_delegate_);
ProofVerifyDetailsChromium details;
details.cert_verify_result.verified_cert =
@@ -369,14 +399,18 @@ TEST_P(QuicChromiumClientSessionTest, CancelPushWhenPendingValidation) {
TEST_P(QuicChromiumClientSessionTest, CancelPushBeforeReceivingResponse) {
base::HistogramTester histogram_tester;
MockRead reads[] = {MockRead(SYNCHRONOUS, ERR_IO_PENDING, 0)};
+ std::unique_ptr<QuicEncryptedPacket> settings_packet(
+ client_maker_.MakeSettingsPacket(1, SETTINGS_MAX_HEADER_LIST_SIZE,
+ kDefaultMaxUncompressedHeaderSize, true,
+ nullptr));
std::unique_ptr<QuicEncryptedPacket> client_rst(client_maker_.MakeRstPacket(
- 1, true, kServerDataStreamId1, QUIC_STREAM_CANCELLED));
+ 2, true, kServerDataStreamId1, QUIC_STREAM_CANCELLED));
MockWrite writes[] = {
- MockWrite(ASYNC, client_rst->data(), client_rst->length(), 1)};
+ MockWrite(ASYNC, settings_packet->data(), settings_packet->length(), 1),
+ MockWrite(ASYNC, client_rst->data(), client_rst->length(), 2)};
socket_data_.reset(new SequencedSocketData(reads, arraysize(reads), writes,
arraysize(writes)));
Initialize();
- session_->set_push_delegate(&test_push_delegate_);
ProofVerifyDetailsChromium details;
details.cert_verify_result.verified_cert =
@@ -417,14 +451,18 @@ TEST_P(QuicChromiumClientSessionTest, CancelPushBeforeReceivingResponse) {
TEST_P(QuicChromiumClientSessionTest, CancelPushAfterReceivingResponse) {
base::HistogramTester histogram_tester;
MockRead reads[] = {MockRead(SYNCHRONOUS, ERR_IO_PENDING, 0)};
+ std::unique_ptr<QuicEncryptedPacket> settings_packet(
+ client_maker_.MakeSettingsPacket(1, SETTINGS_MAX_HEADER_LIST_SIZE,
+ kDefaultMaxUncompressedHeaderSize, true,
+ nullptr));
std::unique_ptr<QuicEncryptedPacket> client_rst(client_maker_.MakeRstPacket(
- 1, true, kServerDataStreamId1, QUIC_STREAM_CANCELLED));
+ 2, true, kServerDataStreamId1, QUIC_STREAM_CANCELLED));
MockWrite writes[] = {
- MockWrite(ASYNC, client_rst->data(), client_rst->length(), 1)};
+ MockWrite(ASYNC, settings_packet->data(), settings_packet->length(), 1),
+ MockWrite(ASYNC, client_rst->data(), client_rst->length(), 2)};
socket_data_.reset(new SequencedSocketData(reads, arraysize(reads), writes,
arraysize(writes)));
Initialize();
- session_->set_push_delegate(&test_push_delegate_);
ProofVerifyDetailsChromium details;
details.cert_verify_result.verified_cert =
@@ -469,10 +507,15 @@ TEST_P(QuicChromiumClientSessionTest, CancelPushAfterReceivingResponse) {
TEST_P(QuicChromiumClientSessionTest, Priority) {
MockRead reads[] = {MockRead(SYNCHRONOUS, ERR_IO_PENDING, 0)};
+ std::unique_ptr<QuicEncryptedPacket> settings_packet(
+ client_maker_.MakeSettingsPacket(1, SETTINGS_MAX_HEADER_LIST_SIZE,
+ kDefaultMaxUncompressedHeaderSize, true,
+ nullptr));
std::unique_ptr<QuicEncryptedPacket> client_rst(client_maker_.MakeRstPacket(
- 1, true, kClientDataStreamId1, QUIC_RST_ACKNOWLEDGEMENT));
+ 2, true, kClientDataStreamId1, QUIC_RST_ACKNOWLEDGEMENT));
MockWrite writes[] = {
- MockWrite(ASYNC, client_rst->data(), client_rst->length(), 1)};
+ MockWrite(ASYNC, settings_packet->data(), settings_packet->length(), 1),
+ MockWrite(ASYNC, client_rst->data(), client_rst->length(), 2)};
socket_data_.reset(new SequencedSocketData(reads, arraysize(reads), writes,
arraysize(writes)));
@@ -495,10 +538,15 @@ TEST_P(QuicChromiumClientSessionTest, Priority) {
TEST_P(QuicChromiumClientSessionTest, MaxNumStreamsViaRequest) {
MockRead reads[] = {MockRead(SYNCHRONOUS, ERR_IO_PENDING, 0)};
+ std::unique_ptr<QuicEncryptedPacket> settings_packet(
+ client_maker_.MakeSettingsPacket(1, SETTINGS_MAX_HEADER_LIST_SIZE,
+ kDefaultMaxUncompressedHeaderSize, true,
+ nullptr));
std::unique_ptr<QuicEncryptedPacket> client_rst(client_maker_.MakeRstPacket(
- 1, true, kClientDataStreamId1, QUIC_RST_ACKNOWLEDGEMENT));
+ 2, true, kClientDataStreamId1, QUIC_RST_ACKNOWLEDGEMENT));
MockWrite writes[] = {
- MockWrite(ASYNC, client_rst->data(), client_rst->length(), 1)};
+ MockWrite(ASYNC, settings_packet->data(), settings_packet->length(), 1),
+ MockWrite(ASYNC, client_rst->data(), client_rst->length(), 2)};
socket_data_.reset(new SequencedSocketData(reads, arraysize(reads), writes,
arraysize(writes)));
@@ -532,6 +580,15 @@ TEST_P(QuicChromiumClientSessionTest, MaxNumStreamsViaRequest) {
}
TEST_P(QuicChromiumClientSessionTest, GoAwayReceived) {
+ MockRead reads[] = {MockRead(SYNCHRONOUS, ERR_IO_PENDING, 0)};
+ std::unique_ptr<QuicEncryptedPacket> settings_packet(
+ client_maker_.MakeSettingsPacket(1, SETTINGS_MAX_HEADER_LIST_SIZE,
+ kDefaultMaxUncompressedHeaderSize, true,
+ nullptr));
+ MockWrite writes[] = {
+ MockWrite(ASYNC, settings_packet->data(), settings_packet->length(), 1)};
+ socket_data_.reset(new SequencedSocketData(reads, arraysize(reads), writes,
+ arraysize(writes)));
Initialize();
CompleteCryptoHandshake();
@@ -543,6 +600,15 @@ TEST_P(QuicChromiumClientSessionTest, GoAwayReceived) {
}
TEST_P(QuicChromiumClientSessionTest, CanPool) {
+ MockRead reads[] = {MockRead(SYNCHRONOUS, ERR_IO_PENDING, 0)};
+ std::unique_ptr<QuicEncryptedPacket> settings_packet(
+ client_maker_.MakeSettingsPacket(1, SETTINGS_MAX_HEADER_LIST_SIZE,
+ kDefaultMaxUncompressedHeaderSize, true,
+ nullptr));
+ MockWrite writes[] = {
+ MockWrite(ASYNC, settings_packet->data(), settings_packet->length(), 1)};
+ socket_data_.reset(new SequencedSocketData(reads, arraysize(reads), writes,
+ arraysize(writes)));
Initialize();
// Load a cert that is valid for:
// www.example.org
@@ -565,6 +631,15 @@ TEST_P(QuicChromiumClientSessionTest, CanPool) {
}
TEST_P(QuicChromiumClientSessionTest, ConnectionPooledWithTlsChannelId) {
+ MockRead reads[] = {MockRead(SYNCHRONOUS, ERR_IO_PENDING, 0)};
+ std::unique_ptr<QuicEncryptedPacket> settings_packet(
+ client_maker_.MakeSettingsPacket(1, SETTINGS_MAX_HEADER_LIST_SIZE,
+ kDefaultMaxUncompressedHeaderSize, true,
+ nullptr));
+ MockWrite writes[] = {
+ MockWrite(ASYNC, settings_packet->data(), settings_packet->length(), 1)};
+ socket_data_.reset(new SequencedSocketData(reads, arraysize(reads), writes,
+ arraysize(writes)));
Initialize();
// Load a cert that is valid for:
// www.example.org
@@ -588,6 +663,15 @@ TEST_P(QuicChromiumClientSessionTest, ConnectionPooledWithTlsChannelId) {
}
TEST_P(QuicChromiumClientSessionTest, ConnectionNotPooledWithDifferentPin) {
+ MockRead reads[] = {MockRead(SYNCHRONOUS, ERR_IO_PENDING, 0)};
+ std::unique_ptr<QuicEncryptedPacket> settings_packet(
+ client_maker_.MakeSettingsPacket(1, SETTINGS_MAX_HEADER_LIST_SIZE,
+ kDefaultMaxUncompressedHeaderSize, true,
+ nullptr));
+ MockWrite writes[] = {
+ MockWrite(ASYNC, settings_packet->data(), settings_packet->length(), 1)};
+ socket_data_.reset(new SequencedSocketData(reads, arraysize(reads), writes,
+ arraysize(writes)));
Initialize();
uint8_t primary_pin = 1;
@@ -614,6 +698,15 @@ TEST_P(QuicChromiumClientSessionTest, ConnectionNotPooledWithDifferentPin) {
}
TEST_P(QuicChromiumClientSessionTest, ConnectionPooledWithMatchingPin) {
+ MockRead reads[] = {MockRead(SYNCHRONOUS, ERR_IO_PENDING, 0)};
+ std::unique_ptr<QuicEncryptedPacket> settings_packet(
+ client_maker_.MakeSettingsPacket(1, SETTINGS_MAX_HEADER_LIST_SIZE,
+ kDefaultMaxUncompressedHeaderSize, true,
+ nullptr));
+ MockWrite writes[] = {
+ MockWrite(ASYNC, settings_packet->data(), settings_packet->length(), 1)};
+ socket_data_.reset(new SequencedSocketData(reads, arraysize(reads), writes,
+ arraysize(writes)));
Initialize();
uint8_t primary_pin = 1;
@@ -639,16 +732,25 @@ TEST_P(QuicChromiumClientSessionTest, ConnectionPooledWithMatchingPin) {
}
TEST_P(QuicChromiumClientSessionTest, MigrateToSocket) {
+ MockRead old_reads[] = {MockRead(SYNCHRONOUS, ERR_IO_PENDING, 0)};
+ std::unique_ptr<QuicEncryptedPacket> settings_packet(
+ client_maker_.MakeSettingsPacket(1, SETTINGS_MAX_HEADER_LIST_SIZE,
+ kDefaultMaxUncompressedHeaderSize, true,
+ nullptr));
+ MockWrite old_writes[] = {
+ MockWrite(ASYNC, settings_packet->data(), settings_packet->length(), 1)};
+ socket_data_.reset(new SequencedSocketData(
+ old_reads, arraysize(old_reads), old_writes, arraysize(old_writes)));
Initialize();
CompleteCryptoHandshake();
char data[] = "ABCD";
std::unique_ptr<QuicEncryptedPacket> client_ping(
- client_maker_.MakePingPacket(1, /*include_version=*/false));
+ client_maker_.MakePingPacket(2, /*include_version=*/false));
std::unique_ptr<QuicEncryptedPacket> server_ping(
server_maker_.MakePingPacket(1, /*include_version=*/false));
std::unique_ptr<QuicEncryptedPacket> ack_and_data_out(
- client_maker_.MakeAckAndDataPacket(2, false, 5, 1, 1, false, 0,
+ client_maker_.MakeAckAndDataPacket(3, false, 5, 1, 1, false, 0,
StringPiece(data)));
MockRead reads[] = {
MockRead(SYNCHRONOUS, server_ping->data(), server_ping->length(), 0),
@@ -660,7 +762,6 @@ TEST_P(QuicChromiumClientSessionTest, MigrateToSocket) {
StaticSocketDataProvider socket_data(reads, arraysize(reads), writes,
arraysize(writes));
socket_factory_.AddSocketDataProvider(&socket_data);
-
// Create connected socket.
std::unique_ptr<DatagramClientSocket> new_socket =
socket_factory_.CreateDatagramClientSocket(DatagramSocket::DEFAULT_BIND,
@@ -698,13 +799,22 @@ TEST_P(QuicChromiumClientSessionTest, MigrateToSocket) {
}
TEST_P(QuicChromiumClientSessionTest, MigrateToSocketMaxReaders) {
+ MockRead old_reads[] = {MockRead(SYNCHRONOUS, ERR_IO_PENDING, 0)};
+ std::unique_ptr<QuicEncryptedPacket> settings_packet(
+ client_maker_.MakeSettingsPacket(1, SETTINGS_MAX_HEADER_LIST_SIZE,
+ kDefaultMaxUncompressedHeaderSize, true,
+ nullptr));
+ MockWrite old_writes[] = {
+ MockWrite(ASYNC, settings_packet->data(), settings_packet->length(), 1)};
+ socket_data_.reset(new SequencedSocketData(
+ old_reads, arraysize(old_reads), old_writes, arraysize(old_writes)));
Initialize();
CompleteCryptoHandshake();
for (size_t i = 0; i < kMaxReadersPerQuicSession; ++i) {
MockRead reads[] = {MockRead(SYNCHRONOUS, ERR_IO_PENDING, 1)};
std::unique_ptr<QuicEncryptedPacket> ping_out(
- client_maker_.MakePingPacket(i + 1, /*include_version=*/true));
+ client_maker_.MakePingPacket(i + 2, /*include_version=*/true));
MockWrite writes[] = {
MockWrite(SYNCHRONOUS, ping_out->data(), ping_out->length(), i + 2)};
StaticSocketDataProvider socket_data(reads, arraysize(reads), writes,
@@ -747,19 +857,23 @@ TEST_P(QuicChromiumClientSessionTest, MigrateToSocketMaxReaders) {
}
TEST_P(QuicChromiumClientSessionTest, MigrateToSocketReadError) {
+ std::unique_ptr<QuicEncryptedPacket> settings_packet(
+ client_maker_.MakeSettingsPacket(1, SETTINGS_MAX_HEADER_LIST_SIZE,
+ kDefaultMaxUncompressedHeaderSize, true,
+ nullptr));
std::unique_ptr<QuicEncryptedPacket> client_ping(
- client_maker_.MakePingPacket(1, /*include_version=*/false));
+ client_maker_.MakePingPacket(2, /*include_version=*/false));
std::unique_ptr<QuicEncryptedPacket> server_ping(
server_maker_.MakePingPacket(1, /*include_version=*/false));
+ MockWrite old_writes[] = {
+ MockWrite(ASYNC, settings_packet->data(), settings_packet->length(), 0)};
MockRead old_reads[] = {
- MockRead(SYNCHRONOUS, client_ping->data(), client_ping->length(), 0),
MockRead(ASYNC, ERR_IO_PENDING, 1), // causes reading to pause.
MockRead(ASYNC, ERR_NETWORK_CHANGED, 2)};
- socket_data_.reset(
- new SequencedSocketData(old_reads, arraysize(old_reads), nullptr, 0));
+ socket_data_.reset(new SequencedSocketData(
+ old_reads, arraysize(old_reads), old_writes, arraysize(old_writes)));
Initialize();
CompleteCryptoHandshake();
-
MockWrite writes[] = {
MockWrite(SYNCHRONOUS, client_ping->data(), client_ping->length(), 1)};
MockRead new_reads[] = {
diff --git a/chromium/net/quic/chromium/quic_chromium_client_stream.cc b/chromium/net/quic/chromium/quic_chromium_client_stream.cc
index e7c4c842166..0bf3d2146ff 100644
--- a/chromium/net/quic/chromium/quic_chromium_client_stream.cc
+++ b/chromium/net/quic/chromium/quic_chromium_client_stream.cc
@@ -14,7 +14,7 @@
#include "net/base/net_errors.h"
#include "net/log/net_log_event_type.h"
#include "net/quic/chromium/quic_chromium_client_session.h"
-#include "net/quic/core/quic_http_utils.h"
+#include "net/quic/chromium/quic_http_utils.h"
#include "net/quic/core/quic_spdy_session.h"
#include "net/quic/core/quic_write_blocked_list.h"
#include "net/quic/core/spdy_utils.h"
@@ -123,7 +123,7 @@ void QuicChromiumClientStream::OnCanWrite() {
size_t QuicChromiumClientStream::WriteHeaders(
SpdyHeaderBlock header_block,
bool fin,
- QuicAckListenerInterface* ack_notifier_delegate) {
+ QuicReferenceCountedPointer<QuicAckListenerInterface> ack_listener) {
if (!session()->IsCryptoHandshakeConfirmed()) {
auto entry = header_block.find(":method");
DCHECK(entry != header_block.end());
@@ -134,7 +134,7 @@ size_t QuicChromiumClientStream::WriteHeaders(
base::Bind(&QuicRequestNetLogCallback, id(), &header_block,
QuicSpdyStream::priority()));
return QuicSpdyStream::WriteHeaders(std::move(header_block), fin,
- ack_notifier_delegate);
+ std::move(ack_listener));
}
SpdyPriority QuicChromiumClientStream::priority() const {
diff --git a/chromium/net/quic/chromium/quic_chromium_client_stream.h b/chromium/net/quic/chromium/quic_chromium_client_stream.h
index 77146cd56fd..01afae71e1e 100644
--- a/chromium/net/quic/chromium/quic_chromium_client_stream.h
+++ b/chromium/net/quic/chromium/quic_chromium_client_stream.h
@@ -4,8 +4,8 @@
//
// NOTE: This code is not shared between Google and Chrome.
-#ifndef NET_QUIC_QUIC_CHROMIUM_CLIENT_STREAM_H_
-#define NET_QUIC_QUIC_CHROMIUM_CLIENT_STREAM_H_
+#ifndef NET_QUIC_CHROMIUM_QUIC_CHROMIUM_CLIENT_STREAM_H_
+#define NET_QUIC_CHROMIUM_QUIC_CHROMIUM_CLIENT_STREAM_H_
#include <stddef.h>
@@ -80,7 +80,8 @@ class NET_EXPORT_PRIVATE QuicChromiumClientStream : public QuicSpdyStream {
void OnCanWrite() override;
size_t WriteHeaders(SpdyHeaderBlock header_block,
bool fin,
- QuicAckListenerInterface* ack_notifier_delegate) override;
+ QuicReferenceCountedPointer<QuicAckListenerInterface>
+ ack_listener) override;
SpdyPriority priority() const override;
// While the server's set_priority shouldn't be called externally, the creator
@@ -156,4 +157,4 @@ class NET_EXPORT_PRIVATE QuicChromiumClientStream : public QuicSpdyStream {
} // namespace net
-#endif // NET_QUIC_QUIC_CHROMIUM_CLIENT_STREAM_H_
+#endif // NET_QUIC_CHROMIUM_QUIC_CHROMIUM_CLIENT_STREAM_H_
diff --git a/chromium/net/quic/chromium/quic_chromium_client_stream_test.cc b/chromium/net/quic/chromium/quic_chromium_client_stream_test.cc
index 975fb0c4e66..03be8e877c9 100644
--- a/chromium/net/quic/chromium/quic_chromium_client_stream_test.cc
+++ b/chromium/net/quic/chromium/quic_chromium_client_stream_test.cc
@@ -22,9 +22,6 @@
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gmock_mutant.h"
-using net::test::IsError;
-using net::test::IsOk;
-
using testing::AnyNumber;
using testing::CreateFunctor;
using testing::Invoke;
@@ -79,13 +76,14 @@ class MockQuicClientSessionBase : public QuicClientSessionBase {
MOCK_METHOD1(CreateIncomingDynamicStream, QuicSpdyStream*(QuicStreamId id));
MOCK_METHOD1(CreateOutgoingDynamicStream,
QuicChromiumClientStream*(SpdyPriority priority));
- MOCK_METHOD6(WritevData,
- QuicConsumedData(QuicStream* stream,
- QuicStreamId id,
- QuicIOVector data,
- QuicStreamOffset offset,
- bool fin,
- QuicAckListenerInterface*));
+ MOCK_METHOD6(
+ WritevData,
+ QuicConsumedData(QuicStream* stream,
+ QuicStreamId id,
+ QuicIOVector data,
+ QuicStreamOffset offset,
+ bool fin,
+ QuicReferenceCountedPointer<QuicAckListenerInterface>));
MOCK_METHOD3(SendRstStream,
void(QuicStreamId stream_id,
QuicRstStreamErrorCode error,
@@ -106,20 +104,23 @@ class MockQuicClientSessionBase : public QuicClientSessionBase {
MOCK_METHOD0(IsCryptoHandshakeConfirmed, bool());
// Methods taking non-copyable types like SpdyHeaderBlock by value cannot be
// mocked directly.
- size_t WriteHeaders(
- QuicStreamId id,
- SpdyHeaderBlock headers,
- bool fin,
- SpdyPriority priority,
- QuicAckListenerInterface* ack_notifier_delegate) override {
- return WriteHeadersMock(id, headers, fin, priority, ack_notifier_delegate);
- }
- MOCK_METHOD5(WriteHeadersMock,
- size_t(QuicStreamId id,
- const SpdyHeaderBlock& headers,
+ size_t WriteHeaders(QuicStreamId id,
+ SpdyHeaderBlock headers,
bool fin,
SpdyPriority priority,
- QuicAckListenerInterface* ack_notifier_delegate));
+ QuicReferenceCountedPointer<QuicAckListenerInterface>
+ ack_listener) override {
+ return WriteHeadersMock(id, headers, fin, priority,
+ std::move(ack_listener));
+ }
+ MOCK_METHOD5(
+ WriteHeadersMock,
+ size_t(QuicStreamId id,
+ const SpdyHeaderBlock& headers,
+ bool fin,
+ SpdyPriority priority,
+ const QuicReferenceCountedPointer<QuicAckListenerInterface>&
+ ack_listener));
MOCK_METHOD1(OnHeadersHeadOfLineBlocking, void(QuicTime::Delta delta));
using QuicSession::ActivateStream;
@@ -131,7 +132,7 @@ class MockQuicClientSessionBase : public QuicClientSessionBase {
const QuicIOVector& data,
QuicStreamOffset offset,
bool fin,
- QuicAckListenerInterface* ack_notifier_delegate);
+ QuicAckListenerInterface* ack_listener);
void OnProofValid(
const QuicCryptoClientConfig::CachedState& cached) override {}
diff --git a/chromium/net/quic/chromium/quic_chromium_connection_helper.h b/chromium/net/quic/chromium/quic_chromium_connection_helper.h
index 9271a6d965d..b6d8af0bd1e 100644
--- a/chromium/net/quic/chromium/quic_chromium_connection_helper.h
+++ b/chromium/net/quic/chromium/quic_chromium_connection_helper.h
@@ -5,14 +5,14 @@
// The Chrome-specific helper for QuicConnection which uses
// a TaskRunner for alarms, and uses a DatagramClientSocket for writing data.
-#ifndef NET_QUIC_QUIC_CHROMIUM_CONNECTION_HELPER_H_
-#define NET_QUIC_QUIC_CHROMIUM_CONNECTION_HELPER_H_
+#ifndef NET_QUIC_CHROMIUM_QUIC_CHROMIUM_CONNECTION_HELPER_H_
+#define NET_QUIC_CHROMIUM_QUIC_CHROMIUM_CONNECTION_HELPER_H_
#include "base/macros.h"
#include "net/base/ip_endpoint.h"
#include "net/base/net_export.h"
#include "net/quic/core/quic_connection.h"
-#include "net/quic/core/quic_protocol.h"
+#include "net/quic/core/quic_packets.h"
#include "net/quic/core/quic_simple_buffer_allocator.h"
#include "net/quic/core/quic_time.h"
#include "net/socket/datagram_client_socket.h"
@@ -44,4 +44,4 @@ class NET_EXPORT_PRIVATE QuicChromiumConnectionHelper
} // namespace net
-#endif // NET_QUIC_QUIC_CHROMIUM_CONNECTION_HELPER_H_
+#endif // NET_QUIC_CHROMIUM_QUIC_CHROMIUM_CONNECTION_HELPER_H_
diff --git a/chromium/net/quic/chromium/quic_chromium_packet_reader.cc b/chromium/net/quic/chromium/quic_chromium_packet_reader.cc
index 1c5d660ed0e..20645fc0788 100644
--- a/chromium/net/quic/chromium/quic_chromium_packet_reader.cc
+++ b/chromium/net/quic/chromium/quic_chromium_packet_reader.cc
@@ -9,7 +9,7 @@
#include "base/single_thread_task_runner.h"
#include "base/threading/thread_task_runner_handle.h"
#include "net/base/net_errors.h"
-#include "net/quic/core/quic_clock.h"
+#include "net/quic/platform/api/quic_clock.h"
namespace net {
diff --git a/chromium/net/quic/chromium/quic_chromium_packet_reader.h b/chromium/net/quic/chromium/quic_chromium_packet_reader.h
index 5e700a7e0d3..a58c623ba9a 100644
--- a/chromium/net/quic/chromium/quic_chromium_packet_reader.h
+++ b/chromium/net/quic/chromium/quic_chromium_packet_reader.h
@@ -3,15 +3,15 @@
// found in the LICENSE file.
//
-#ifndef NET_QUIC_QUIC_CHROMIUM_PACKET_READER_H_
-#define NET_QUIC_QUIC_CHROMIUM_PACKET_READER_H_
+#ifndef NET_QUIC_CHROMIUM_QUIC_CHROMIUM_PACKET_READER_H_
+#define NET_QUIC_CHROMIUM_QUIC_CHROMIUM_PACKET_READER_H_
#include "base/macros.h"
#include "base/memory/weak_ptr.h"
#include "net/base/io_buffer.h"
#include "net/base/net_export.h"
#include "net/log/net_log_with_source.h"
-#include "net/quic/core/quic_protocol.h"
+#include "net/quic/core/quic_packets.h"
#include "net/quic/core/quic_time.h"
#include "net/socket/datagram_client_socket.h"
@@ -71,4 +71,4 @@ class NET_EXPORT_PRIVATE QuicChromiumPacketReader {
} // namespace net
-#endif // NET_QUIC_QUIC_CHROMIUM_PACKET_READER_H_
+#endif // NET_QUIC_CHROMIUM_QUIC_CHROMIUM_PACKET_READER_H_
diff --git a/chromium/net/quic/chromium/quic_chromium_packet_writer.cc b/chromium/net/quic/chromium/quic_chromium_packet_writer.cc
index 5478d7173c8..347457dbc5e 100644
--- a/chromium/net/quic/chromium/quic_chromium_packet_writer.cc
+++ b/chromium/net/quic/chromium/quic_chromium_packet_writer.cc
@@ -30,8 +30,8 @@ QuicChromiumPacketWriter::~QuicChromiumPacketWriter() {}
WriteResult QuicChromiumPacketWriter::WritePacket(
const char* buffer,
size_t buf_len,
- const IPAddress& self_address,
- const IPEndPoint& peer_address,
+ const QuicIpAddress& self_address,
+ const QuicSocketAddress& peer_address,
PerPacketOptions* /*options*/) {
scoped_refptr<StringIOBuffer> buf(
new StringIOBuffer(std::string(buffer, buf_len)));
@@ -110,7 +110,7 @@ void QuicChromiumPacketWriter::OnWriteComplete(int rv) {
}
QuicByteCount QuicChromiumPacketWriter::GetMaxPacketSize(
- const IPEndPoint& peer_address) const {
+ const QuicSocketAddress& peer_address) const {
return kMaxPacketSize;
}
diff --git a/chromium/net/quic/chromium/quic_chromium_packet_writer.h b/chromium/net/quic/chromium/quic_chromium_packet_writer.h
index 8141466ca3c..09e03fd16de 100644
--- a/chromium/net/quic/chromium/quic_chromium_packet_writer.h
+++ b/chromium/net/quic/chromium/quic_chromium_packet_writer.h
@@ -2,19 +2,18 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#ifndef NET_QUIC_QUIC_CHROMIUM_PACKET_WRITER_H_
-#define NET_QUIC_QUIC_CHROMIUM_PACKET_WRITER_H_
+#ifndef NET_QUIC_CHROMIUM_QUIC_CHROMIUM_PACKET_WRITER_H_
+#define NET_QUIC_CHROMIUM_QUIC_CHROMIUM_PACKET_WRITER_H_
#include <stddef.h>
#include "base/macros.h"
#include "base/memory/weak_ptr.h"
#include "net/base/io_buffer.h"
-#include "net/base/ip_endpoint.h"
#include "net/base/net_export.h"
#include "net/quic/core/quic_connection.h"
#include "net/quic/core/quic_packet_writer.h"
-#include "net/quic/core/quic_protocol.h"
+#include "net/quic/core/quic_packets.h"
#include "net/quic/core/quic_types.h"
#include "net/socket/datagram_client_socket.h"
@@ -57,13 +56,14 @@ class NET_EXPORT_PRIVATE QuicChromiumPacketWriter : public QuicPacketWriter {
// QuicPacketWriter
WriteResult WritePacket(const char* buffer,
size_t buf_len,
- const IPAddress& self_address,
- const IPEndPoint& peer_address,
+ const QuicIpAddress& self_address,
+ const QuicSocketAddress& peer_address,
PerPacketOptions* options) override;
bool IsWriteBlockedDataBuffered() const override;
bool IsWriteBlocked() const override;
void SetWritable() override;
- QuicByteCount GetMaxPacketSize(const IPEndPoint& peer_address) const override;
+ QuicByteCount GetMaxPacketSize(
+ const QuicSocketAddress& peer_address) const override;
void OnWriteComplete(int rv);
@@ -84,4 +84,4 @@ class NET_EXPORT_PRIVATE QuicChromiumPacketWriter : public QuicPacketWriter {
} // namespace net
-#endif // NET_QUIC_QUIC_CHROMIUM_PACKET_WRITER_H_
+#endif // NET_QUIC_CHROMIUM_QUIC_CHROMIUM_PACKET_WRITER_H_
diff --git a/chromium/net/quic/chromium/quic_connection_logger.cc b/chromium/net/quic/chromium/quic_connection_logger.cc
index b687de1929c..2bfd9eb0fd7 100644
--- a/chromium/net/quic/chromium/quic_connection_logger.cc
+++ b/chromium/net/quic/chromium/quic_connection_logger.cc
@@ -23,10 +23,10 @@
#include "net/log/net_log.h"
#include "net/log/net_log_capture_mode.h"
#include "net/log/net_log_event_type.h"
+#include "net/quic/chromium/quic_address_mismatch.h"
#include "net/quic/core/crypto/crypto_handshake_message.h"
#include "net/quic/core/crypto/crypto_protocol.h"
-#include "net/quic/core/quic_address_mismatch.h"
-#include "net/quic/core/quic_protocol.h"
+#include "net/quic/core/quic_packets.h"
#include "net/quic/core/quic_socket_address_coder.h"
#include "net/quic/core/quic_time.h"
@@ -113,22 +113,10 @@ std::unique_ptr<base::Value> NetLogQuicAckFrameCallback(
base::Uint64ToString(frame->largest_observed));
dict->SetString("delta_time_largest_observed_us",
base::Int64ToString(frame->ack_delay_time.ToMicroseconds()));
- if (frame->missing) {
- // Entropy and Truncated are not present in v34 and above.
- dict->SetInteger("entropy_hash", frame->entropy_hash);
- dict->SetBoolean("truncated", frame->is_truncated);
- }
base::ListValue* missing = new base::ListValue();
dict->Set("missing_packets", missing);
- if (frame->missing) {
- for (const Interval<QuicPacketNumber>& interval : frame->packets) {
- for (QuicPacketNumber packet = interval.min(); packet < interval.max();
- ++packet) {
- missing->AppendString(base::Uint64ToString(packet));
- }
- }
- } else if (!frame->packets.Empty()) {
+ if (!frame->packets.Empty()) {
// V34 and above express acked packets, but only print
// missing packets, because it's typically a shorter list.
for (QuicPacketNumber packet = frame->packets.Min();
@@ -269,11 +257,6 @@ std::unique_ptr<base::Value> NetLogQuicCertificateVerifiedCallback(
return std::move(dict);
}
-void UpdatePacketGapSentHistogram(size_t num_consecutive_missing_packets) {
- UMA_HISTOGRAM_COUNTS("Net.QuicSession.PacketGapSent",
- num_consecutive_missing_packets);
-}
-
void UpdatePublicResetAddressMismatchHistogram(
const IPEndPoint& server_hello_address,
const IPEndPoint& public_reset_address) {
@@ -308,7 +291,6 @@ QuicConnectionLogger::QuicConnectionLogger(
no_packet_received_after_ping_(false),
previous_received_packet_size_(0),
largest_received_packet_number_(0),
- largest_received_missing_packet_number_(0),
num_out_of_order_received_packets_(0),
num_out_of_order_large_received_packets_(0),
num_packets_received_(0),
@@ -450,21 +432,25 @@ void QuicConnectionLogger::OnPingSent() {
no_packet_received_after_ping_ = true;
}
-void QuicConnectionLogger::OnPacketReceived(const IPEndPoint& self_address,
- const IPEndPoint& peer_address,
- const QuicEncryptedPacket& packet) {
+void QuicConnectionLogger::OnPacketReceived(
+ const QuicSocketAddress& self_address,
+ const QuicSocketAddress& peer_address,
+ const QuicEncryptedPacket& packet) {
if (local_address_from_self_.GetFamily() == ADDRESS_FAMILY_UNSPECIFIED) {
- local_address_from_self_ = self_address;
- UMA_HISTOGRAM_ENUMERATION("Net.QuicSession.ConnectionTypeFromSelf",
- GetRealAddressFamily(self_address.address()),
- ADDRESS_FAMILY_LAST);
+ local_address_from_self_ = self_address.impl().socket_address();
+ UMA_HISTOGRAM_ENUMERATION(
+ "Net.QuicSession.ConnectionTypeFromSelf",
+ GetRealAddressFamily(self_address.impl().socket_address().address()),
+ ADDRESS_FAMILY_LAST);
}
previous_received_packet_size_ = last_received_packet_size_;
last_received_packet_size_ = packet.length();
- net_log_.AddEvent(NetLogEventType::QUIC_SESSION_PACKET_RECEIVED,
- base::Bind(&NetLogQuicPacketCallback, &self_address,
- &peer_address, packet.length()));
+ net_log_.AddEvent(
+ NetLogEventType::QUIC_SESSION_PACKET_RECEIVED,
+ base::Bind(&NetLogQuicPacketCallback,
+ &self_address.impl().socket_address(),
+ &peer_address.impl().socket_address(), packet.length()));
}
void QuicConnectionLogger::OnUnauthenticatedHeader(
@@ -550,42 +536,6 @@ void QuicConnectionLogger::OnAckFrame(const QuicAckFrame& frame) {
return;
// TODO(rch, rtenneti) sort out histograms for QUIC_VERSION_34 and above.
- if (session_->connection()->version() > QUIC_VERSION_33) {
- return;
- }
- const PacketNumberQueue& missing_packets = frame.packets;
- PacketNumberQueue::const_iterator it =
- missing_packets.lower_bound(largest_received_missing_packet_number_);
- if (it == missing_packets.end() ||
- largest_received_missing_packet_number_ == missing_packets.Max()) {
- return;
- }
-
- // Scan through the list and log consecutive ranges of missing packets.
- size_t num_consecutive_missing_packets = 1;
- QuicPacketNumber previous_missing_packet =
- largest_received_missing_packet_number_;
- for (; it != missing_packets.end(); ++it) {
- // Account for case where first interval starts below
- // largest_received_missing_packet_number_.
- QuicPacketNumber interval_min =
- std::max(previous_missing_packet + 1, it->min());
- DCHECK_LE(interval_min, it->max());
-
- size_t interval_len = it->max() - interval_min;
- if (interval_len == 0) {
- continue;
- }
- if (interval_min == previous_missing_packet + 1) {
- num_consecutive_missing_packets += interval_len;
- } else {
- UpdatePacketGapSentHistogram(num_consecutive_missing_packets);
- num_consecutive_missing_packets = interval_len;
- }
- previous_missing_packet = it->max() - 1;
- }
- UpdatePacketGapSentHistogram(num_consecutive_missing_packets);
- largest_received_missing_packet_number_ = missing_packets.Max();
}
void QuicConnectionLogger::OnStopWaitingFrame(
@@ -635,12 +585,12 @@ void QuicConnectionLogger::OnPingFrame(const QuicPingFrame& frame) {
void QuicConnectionLogger::OnPublicResetPacket(
const QuicPublicResetPacket& packet) {
- net_log_.AddEvent(
- NetLogEventType::QUIC_SESSION_PUBLIC_RESET_PACKET_RECEIVED,
- base::Bind(&NetLogQuicPublicResetPacketCallback,
- &local_address_from_shlo_, &packet.client_address));
- UpdatePublicResetAddressMismatchHistogram(local_address_from_shlo_,
- packet.client_address);
+ net_log_.AddEvent(NetLogEventType::QUIC_SESSION_PUBLIC_RESET_PACKET_RECEIVED,
+ base::Bind(&NetLogQuicPublicResetPacketCallback,
+ &local_address_from_shlo_,
+ &packet.client_address.impl().socket_address()));
+ UpdatePublicResetAddressMismatchHistogram(
+ local_address_from_shlo_, packet.client_address.impl().socket_address());
}
void QuicConnectionLogger::OnVersionNegotiationPacket(
@@ -661,7 +611,8 @@ void QuicConnectionLogger::OnCryptoHandshakeMessageReceived(
QuicSocketAddressCoder decoder;
if (message.GetStringPiece(kCADR, &address) &&
decoder.Decode(address.data(), address.size())) {
- local_address_from_shlo_ = IPEndPoint(decoder.ip(), decoder.port());
+ local_address_from_shlo_ =
+ IPEndPoint(decoder.ip().impl().ip_address(), decoder.port());
UMA_HISTOGRAM_ENUMERATION(
"Net.QuicSession.ConnectionTypeFromPeer",
GetRealAddressFamily(local_address_from_shlo_.address()),
@@ -736,7 +687,8 @@ void QuicConnectionLogger::OnRttChanged(QuicTime::Delta rtt) const {
return;
int64_t microseconds = rtt.ToMicroseconds();
- if (microseconds != 0) {
+ if (microseconds != 0 &&
+ socket_performance_watcher_->ShouldNotifyUpdatedRTT()) {
socket_performance_watcher_->OnUpdatedRTTAvailable(
base::TimeDelta::FromMicroseconds(rtt.ToMicroseconds()));
}
diff --git a/chromium/net/quic/chromium/quic_connection_logger.h b/chromium/net/quic/chromium/quic_connection_logger.h
index 98e74ea02aa..8d71147d530 100644
--- a/chromium/net/quic/chromium/quic_connection_logger.h
+++ b/chromium/net/quic/chromium/quic_connection_logger.h
@@ -2,8 +2,8 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#ifndef NET_QUIC_QUIC_CONNECTION_LOGGER_H_
-#define NET_QUIC_QUIC_CONNECTION_LOGGER_H_
+#ifndef NET_QUIC_CHROMIUM_QUIC_CONNECTION_LOGGER_H_
+#define NET_QUIC_CHROMIUM_QUIC_CONNECTION_LOGGER_H_
#include <stddef.h>
@@ -11,14 +11,13 @@
#include <string>
#include "base/macros.h"
-#include "net/base/ip_endpoint.h"
#include "net/base/net_export.h"
#include "net/base/network_change_notifier.h"
#include "net/cert/cert_verify_result.h"
#include "net/log/net_log_with_source.h"
#include "net/quic/core/crypto/crypto_handshake_message.h"
#include "net/quic/core/quic_connection.h"
-#include "net/quic/core/quic_protocol.h"
+#include "net/quic/core/quic_packets.h"
#include "net/quic/core/quic_spdy_session.h"
#include "net/socket/socket_performance_watcher.h"
@@ -52,8 +51,8 @@ class NET_EXPORT_PRIVATE QuicConnectionLogger
TransmissionType transmission_type,
QuicTime sent_time) override;
void OnPingSent() override;
- void OnPacketReceived(const IPEndPoint& self_address,
- const IPEndPoint& peer_address,
+ void OnPacketReceived(const QuicSocketAddress& self_address,
+ const QuicSocketAddress& peer_address,
const QuicEncryptedPacket& packet) override;
void OnUnauthenticatedHeader(const QuicPacketHeader& header) override;
void OnIncorrectConnectionId(QuicConnectionId connection_id) override;
@@ -112,9 +111,6 @@ class NET_EXPORT_PRIVATE QuicConnectionLogger
// The largest packet number received. In the case where a packet is
// received late (out of order), this value will not be updated.
QuicPacketNumber largest_received_packet_number_;
- // The largest packet number which the peer has failed to
- // receive, according to the missing packet set in their ack frames.
- QuicPacketNumber largest_received_missing_packet_number_;
// Number of times that the current received packet number is
// smaller than the last received packet number.
size_t num_out_of_order_received_packets_;
@@ -165,4 +161,4 @@ class NET_EXPORT_PRIVATE QuicConnectionLogger
} // namespace net
-#endif // NET_QUIC_QUIC_CONNECTION_LOGGER_H_
+#endif // NET_QUIC_CHROMIUM_QUIC_CONNECTION_LOGGER_H_
diff --git a/chromium/net/quic/core/quic_crypto_client_stream_factory.cc b/chromium/net/quic/chromium/quic_crypto_client_stream_factory.cc
index af6e00340d5..e0ab19d87f2 100644
--- a/chromium/net/quic/core/quic_crypto_client_stream_factory.cc
+++ b/chromium/net/quic/chromium/quic_crypto_client_stream_factory.cc
@@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#include "net/quic/core/quic_crypto_client_stream_factory.h"
+#include "net/quic/chromium/quic_crypto_client_stream_factory.h"
#include "base/lazy_instance.h"
#include "net/quic/chromium/crypto/proof_verifier_chromium.h"
diff --git a/chromium/net/quic/core/quic_crypto_client_stream_factory.h b/chromium/net/quic/chromium/quic_crypto_client_stream_factory.h
index 319d7d57855..8a4a9a1df4c 100644
--- a/chromium/net/quic/core/quic_crypto_client_stream_factory.h
+++ b/chromium/net/quic/chromium/quic_crypto_client_stream_factory.h
@@ -2,8 +2,8 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#ifndef NET_QUIC_QUIC_CRYPTO_CLIENT_STREAM_FACTORY_H_
-#define NET_QUIC_QUIC_CRYPTO_CLIENT_STREAM_FACTORY_H_
+#ifndef NET_QUIC_CHROMIUM_QUIC_CRYPTO_CLIENT_STREAM_FACTORY_H_
+#define NET_QUIC_CHROMIUM_QUIC_CRYPTO_CLIENT_STREAM_FACTORY_H_
#include <memory>
#include <string>
@@ -35,4 +35,4 @@ class NET_EXPORT QuicCryptoClientStreamFactory {
} // namespace net
-#endif // NET_QUIC_QUIC_CRYPTO_CLIENT_STREAM_FACTORY_H_
+#endif // NET_QUIC_CHROMIUM_QUIC_CRYPTO_CLIENT_STREAM_FACTORY_H_
diff --git a/chromium/net/quic/chromium/quic_end_to_end_unittest.cc b/chromium/net/quic/chromium/quic_end_to_end_unittest.cc
index a7720affc7f..0df6b3cd8d1 100644
--- a/chromium/net/quic/chromium/quic_end_to_end_unittest.cc
+++ b/chromium/net/quic/chromium/quic_end_to_end_unittest.cc
@@ -11,6 +11,7 @@
#include "base/memory/ptr_util.h"
#include "base/run_loop.h"
#include "base/strings/string_number_conversions.h"
+#include "base/threading/thread_task_runner_handle.h"
#include "net/base/elements_upload_data_stream.h"
#include "net/base/ip_address.h"
#include "net/base/test_completion_callback.h"
@@ -36,9 +37,8 @@
#include "net/test/cert_test_util.h"
#include "net/test/gtest_util.h"
#include "net/test/test_data_directory.h"
-#include "net/tools/quic/quic_in_memory_cache.h"
+#include "net/tools/quic/quic_http_response_cache.h"
#include "net/tools/quic/quic_simple_server.h"
-#include "net/tools/quic/test_tools/quic_in_memory_cache_peer.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "testing/platform_test.h"
@@ -48,7 +48,6 @@ using base::StringPiece;
namespace net {
using test::IsOk;
-using test::QuicInMemoryCachePeer;
namespace test {
@@ -153,7 +152,6 @@ class QuicEndToEndTest : public ::testing::TestWithParam<TestParams> {
}
void SetUp() override {
- QuicInMemoryCachePeer::ResetForTests();
StartServer();
// Use a mapped host resolver so that request for test.example.com (port 80)
@@ -170,7 +168,7 @@ class QuicEndToEndTest : public ::testing::TestWithParam<TestParams> {
transaction_factory_.reset(new TestTransactionFactory(params_));
}
- void TearDown() override { QuicInMemoryCachePeer::ResetForTests(); }
+ void TearDown() override {}
// Starts the QUIC server listening on a random port.
void StartServer() {
@@ -180,9 +178,9 @@ class QuicEndToEndTest : public ::testing::TestWithParam<TestParams> {
server_config_.SetInitialSessionFlowControlWindowToSend(
kInitialSessionFlowControlWindowForTest);
server_config_options_.token_binding_params = QuicTagVector{kTB10, kP256};
- server_.reset(new QuicSimpleServer(CryptoTestUtils::ProofSourceForTesting(),
- server_config_, server_config_options_,
- AllSupportedVersions()));
+ server_.reset(new QuicSimpleServer(
+ CryptoTestUtils::ProofSourceForTesting(), server_config_,
+ server_config_options_, AllSupportedVersions(), &response_cache_));
server_->Listen(server_address_);
server_address_ = server_->server_address();
server_->StartReading();
@@ -195,8 +193,8 @@ class QuicEndToEndTest : public ::testing::TestWithParam<TestParams> {
int response_code,
StringPiece response_detail,
StringPiece body) {
- QuicInMemoryCache::GetInstance()->AddSimpleResponse(
- "test.example.com", path, response_code, body);
+ response_cache_.AddSimpleResponse("test.example.com", path, response_code,
+ body);
}
// Populates |request_body_| with |length_| ASCII bytes.
@@ -251,6 +249,7 @@ class QuicEndToEndTest : public ::testing::TestWithParam<TestParams> {
std::string request_body_;
std::unique_ptr<UploadDataStream> upload_data_stream_;
std::unique_ptr<QuicSimpleServer> server_;
+ QuicHttpResponseCache response_cache_;
IPEndPoint server_address_;
std::string server_hostname_;
QuicConfig server_config_;
diff --git a/chromium/net/quic/chromium/quic_http_stream.cc b/chromium/net/quic/chromium/quic_http_stream.cc
index d9f99290ac5..ef48ef66a90 100644
--- a/chromium/net/quic/chromium/quic_http_stream.cc
+++ b/chromium/net/quic/chromium/quic_http_stream.cc
@@ -10,15 +10,15 @@
#include "base/callback_helpers.h"
#include "base/metrics/histogram_macros.h"
#include "base/strings/string_split.h"
-#include "base/strings/stringprintf.h"
+#include "base/threading/thread_task_runner_handle.h"
#include "net/base/load_flags.h"
#include "net/base/net_errors.h"
#include "net/http/http_response_headers.h"
#include "net/http/http_util.h"
#include "net/log/net_log_event_type.h"
#include "net/log/net_log_source.h"
+#include "net/quic/chromium/quic_http_utils.h"
#include "net/quic/core/quic_client_promised_info.h"
-#include "net/quic/core/quic_http_utils.h"
#include "net/quic/core/quic_utils.h"
#include "net/quic/core/spdy_utils.h"
#include "net/spdy/spdy_frame_builder.h"
@@ -44,7 +44,8 @@ std::unique_ptr<base::Value> NetLogQuicPushStreamCallback(
QuicHttpStream::QuicHttpStream(
const base::WeakPtr<QuicChromiumClientSession>& session)
- : next_state_(STATE_NONE),
+ : MultiplexedHttpStream(MultiplexedSessionHandle(session)),
+ next_state_(STATE_NONE),
session_(session),
quic_version_(session->GetQuicVersion()),
session_error_(OK),
@@ -133,16 +134,14 @@ HttpResponseInfo::ConnectionInfo QuicHttpStream::ConnectionInfoFromQuicVersion(
switch (quic_version) {
case QUIC_VERSION_UNSUPPORTED:
return HttpResponseInfo::CONNECTION_INFO_QUIC_UNKNOWN_VERSION;
- case QUIC_VERSION_32:
- return HttpResponseInfo::CONNECTION_INFO_QUIC_32;
- case QUIC_VERSION_33:
- return HttpResponseInfo::CONNECTION_INFO_QUIC_33;
case QUIC_VERSION_34:
return HttpResponseInfo::CONNECTION_INFO_QUIC_34;
case QUIC_VERSION_35:
return HttpResponseInfo::CONNECTION_INFO_QUIC_35;
case QUIC_VERSION_36:
return HttpResponseInfo::CONNECTION_INFO_QUIC_36;
+ case QUIC_VERSION_37:
+ return HttpResponseInfo::CONNECTION_INFO_QUIC_37;
}
NOTREACHED();
return HttpResponseInfo::CONNECTION_INFO_QUIC_UNKNOWN_VERSION;
@@ -167,9 +166,7 @@ int QuicHttpStream::InitializeStream(const HttpRequestInfo* request_info,
request_time_ = base::Time::Now();
priority_ = priority;
- bool success = session_->GetSSLInfo(&ssl_info_);
- DCHECK(success);
- DCHECK(ssl_info_.cert.get());
+ SaveSSLInfo();
std::string url(request_info->url.spec());
QuicClientPromisedInfo* promised =
@@ -244,8 +241,10 @@ int QuicHttpStream::SendRequest(const HttpRequestHeaders& request_headers,
HostPortPair origin = HostPortPair::FromURL(request_info_->url);
if (origin.Equals(HostPortPair("accounts.google.com", 443)) &&
request_headers.HasHeader(HttpRequestHeaders::kCookie)) {
+ SSLInfo ssl_info;
+ GetSSLInfo(&ssl_info);
UMA_HISTOGRAM_BOOLEAN("Net.QuicSession.CookieSentToAccountsOverChannelId",
- ssl_info_.channel_id_sent);
+ ssl_info.channel_id_sent);
}
if ((!found_promise_ && !stream_) || !session_) {
return was_handshake_confirmed_ ? ERR_CONNECTION_CLOSED
@@ -361,10 +360,6 @@ void QuicHttpStream::Close(bool not_reusable) {
ResetStream();
}
-HttpStream* QuicHttpStream::RenewStreamForAuth() {
- return nullptr;
-}
-
bool QuicHttpStream::IsResponseBodyComplete() const {
return next_state_ == STATE_OPEN && !stream_;
}
@@ -374,15 +369,6 @@ bool QuicHttpStream::IsConnectionReused() const {
return stream_ && stream_->id() > 1;
}
-void QuicHttpStream::SetConnectionReused() {
- // QUIC doesn't need an indicator here.
-}
-
-bool QuicHttpStream::CanReuseConnection() const {
- // QUIC streams aren't considered reusable.
- return false;
-}
-
int64_t QuicHttpStream::GetTotalReceivedBytes() const {
// TODO(sclittle): Currently, this only includes headers and response body
// bytes. Change this to include QUIC overhead as well.
@@ -420,36 +406,6 @@ bool QuicHttpStream::GetLoadTimingInfo(LoadTimingInfo* load_timing_info) const {
return true;
}
-void QuicHttpStream::GetSSLInfo(SSLInfo* ssl_info) {
- *ssl_info = ssl_info_;
-}
-
-void QuicHttpStream::GetSSLCertRequestInfo(
- SSLCertRequestInfo* cert_request_info) {
- DCHECK(stream_);
- NOTIMPLEMENTED();
-}
-
-bool QuicHttpStream::GetRemoteEndpoint(IPEndPoint* endpoint) {
- if (!session_)
- return false;
-
- *endpoint = session_->peer_address();
- return true;
-}
-
-Error QuicHttpStream::GetTokenBindingSignature(crypto::ECPrivateKey* key,
- TokenBindingType tb_type,
- std::vector<uint8_t>* out) {
- return session_->GetTokenBindingSignature(key, tb_type, out);
-}
-
-void QuicHttpStream::Drain(HttpNetworkSession* session) {
- NOTREACHED();
- Close(false);
- delete this;
-}
-
void QuicHttpStream::PopulateNetErrorDetails(NetErrorDetails* details) {
details->connection_info = ConnectionInfoFromQuicVersion(quic_version_);
if (was_handshake_confirmed_)
@@ -544,11 +500,10 @@ bool QuicHttpStream::HasSendHeadersComplete() {
void QuicHttpStream::OnCryptoHandshakeConfirmed() {
was_handshake_confirmed_ = true;
if (next_state_ == STATE_WAIT_FOR_CONFIRMATION_COMPLETE) {
- int rv = DoLoop(OK);
-
- if (rv != ERR_IO_PENDING && !callback_.is_null()) {
- DoCallback(rv);
- }
+ // Post a task to avoid reentrant calls into the session.
+ base::ThreadTaskRunnerHandle::Get()->PostTask(
+ FROM_HERE, base::Bind(&QuicHttpStream::OnIOComplete,
+ weak_factory_.GetWeakPtr(), OK));
}
}
@@ -812,7 +767,7 @@ int QuicHttpStream::ProcessResponseHeaders(const SpdyHeaderBlock& headers) {
return ERR_QUIC_PROTOCOL_ERROR;
}
// Put the peer's IP address and port into the response.
- IPEndPoint address = session_->peer_address();
+ IPEndPoint address = session_->peer_address().impl().socket_address();
response_info_->socket_address = HostPortPair::FromIPEndPoint(address);
response_info_->connection_info =
ConnectionInfoFromQuicVersion(quic_version_);
diff --git a/chromium/net/quic/chromium/quic_http_stream.h b/chromium/net/quic/chromium/quic_http_stream.h
index 4c785031887..29365a47bb1 100644
--- a/chromium/net/quic/chromium/quic_http_stream.h
+++ b/chromium/net/quic/chromium/quic_http_stream.h
@@ -2,8 +2,8 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#ifndef NET_QUIC_QUIC_HTTP_STREAM_H_
-#define NET_QUIC_QUIC_HTTP_STREAM_H_
+#ifndef NET_QUIC_CHROMIUM_QUIC_HTTP_STREAM_H_
+#define NET_QUIC_CHROMIUM_QUIC_HTTP_STREAM_H_
#include <stddef.h>
#include <stdint.h>
@@ -18,12 +18,12 @@
#include "net/base/load_timing_info.h"
#include "net/base/net_export.h"
#include "net/http/http_response_info.h"
-#include "net/http/http_stream.h"
#include "net/log/net_log_with_source.h"
#include "net/quic/chromium/quic_chromium_client_session.h"
#include "net/quic/chromium/quic_chromium_client_stream.h"
#include "net/quic/core/quic_client_push_promise_index.h"
-#include "net/quic/core/quic_protocol.h"
+#include "net/quic/core/quic_packets.h"
+#include "net/spdy/multiplexed_http_stream.h"
namespace net {
@@ -38,7 +38,7 @@ class NET_EXPORT_PRIVATE QuicHttpStream
: public QuicChromiumClientSession::Observer,
public QuicChromiumClientStream::Delegate,
public QuicClientPushPromiseIndex::Delegate,
- public HttpStream {
+ public MultiplexedHttpStream {
public:
explicit QuicHttpStream(
const base::WeakPtr<QuicChromiumClientSession>& session);
@@ -58,21 +58,11 @@ class NET_EXPORT_PRIVATE QuicHttpStream
int buf_len,
const CompletionCallback& callback) override;
void Close(bool not_reusable) override;
- HttpStream* RenewStreamForAuth() override;
bool IsResponseBodyComplete() const override;
bool IsConnectionReused() const override;
- void SetConnectionReused() override;
- bool CanReuseConnection() const override;
int64_t GetTotalReceivedBytes() const override;
int64_t GetTotalSentBytes() const override;
bool GetLoadTimingInfo(LoadTimingInfo* load_timing_info) const override;
- void GetSSLInfo(SSLInfo* ssl_info) override;
- void GetSSLCertRequestInfo(SSLCertRequestInfo* cert_request_info) override;
- bool GetRemoteEndpoint(IPEndPoint* endpoint) override;
- Error GetTokenBindingSignature(crypto::ECPrivateKey* key,
- TokenBindingType tb_type,
- std::vector<uint8_t>* out) override;
- void Drain(HttpNetworkSession* session) override;
void PopulateNetErrorDetails(NetErrorDetails* details) override;
void SetPriority(RequestPriority priority) override;
@@ -213,9 +203,6 @@ class NET_EXPORT_PRIVATE QuicHttpStream
QuicErrorCode quic_connection_error_;
- // SSLInfo from the underlying QuicSession.
- SSLInfo ssl_info_;
-
// True when this stream receives a go away from server due to port migration.
bool port_migration_detected_;
@@ -239,4 +226,4 @@ class NET_EXPORT_PRIVATE QuicHttpStream
} // namespace net
-#endif // NET_QUIC_QUIC_HTTP_STREAM_H_
+#endif // NET_QUIC_CHROMIUM_QUIC_HTTP_STREAM_H_
diff --git a/chromium/net/quic/chromium/quic_http_stream_test.cc b/chromium/net/quic/chromium/quic_http_stream_test.cc
index c9ae6011e79..6f4e4ec25bc 100644
--- a/chromium/net/quic/chromium/quic_http_stream_test.cc
+++ b/chromium/net/quic/chromium/quic_http_stream_test.cc
@@ -27,25 +27,25 @@
#include "net/log/test_net_log.h"
#include "net/log/test_net_log_util.h"
#include "net/quic/chromium/crypto/proof_verifier_chromium.h"
+#include "net/quic/chromium/mock_crypto_client_stream_factory.h"
#include "net/quic/chromium/quic_chromium_alarm_factory.h"
#include "net/quic/chromium/quic_chromium_connection_helper.h"
#include "net/quic/chromium/quic_chromium_packet_reader.h"
#include "net/quic/chromium/quic_chromium_packet_writer.h"
+#include "net/quic/chromium/quic_http_utils.h"
+#include "net/quic/chromium/quic_server_info.h"
+#include "net/quic/chromium/quic_test_packet_maker.h"
#include "net/quic/core/congestion_control/send_algorithm_interface.h"
#include "net/quic/core/crypto/crypto_protocol.h"
#include "net/quic/core/crypto/quic_decrypter.h"
#include "net/quic/core/crypto/quic_encrypter.h"
-#include "net/quic/core/crypto/quic_server_info.h"
#include "net/quic/core/quic_connection.h"
-#include "net/quic/core/quic_http_utils.h"
#include "net/quic/core/quic_write_blocked_list.h"
#include "net/quic/core/spdy_utils.h"
#include "net/quic/test_tools/crypto_test_utils.h"
#include "net/quic/test_tools/mock_clock.h"
-#include "net/quic/test_tools/mock_crypto_client_stream_factory.h"
#include "net/quic/test_tools/mock_random.h"
#include "net/quic/test_tools/quic_connection_peer.h"
-#include "net/quic/test_tools/quic_test_packet_maker.h"
#include "net/quic/test_tools/quic_test_utils.h"
#include "net/quic/test_tools/test_task_runner.h"
#include "net/socket/socket_performance_watcher.h"
@@ -60,9 +60,6 @@
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
-using net::test::IsError;
-using net::test::IsOk;
-
using std::string;
using testing::_;
using testing::AnyNumber;
@@ -85,7 +82,7 @@ class TestQuicConnection : public QuicConnection {
QuicChromiumAlarmFactory* alarm_factory,
QuicPacketWriter* writer)
: QuicConnection(connection_id,
- address,
+ QuicSocketAddress(QuicSocketAddressImpl(address)),
helper,
alarm_factory,
writer,
@@ -94,7 +91,7 @@ class TestQuicConnection : public QuicConnection {
versions) {}
void SetSendAlgorithm(SendAlgorithmInterface* send_algorithm) {
- QuicConnectionPeer::SetSendAlgorithm(this, kDefaultPathId, send_algorithm);
+ QuicConnectionPeer::SetSendAlgorithm(this, send_algorithm);
}
};
@@ -253,7 +250,9 @@ class QuicHttpStreamTest : public ::testing::TestWithParam<QuicVersion> {
}
void ProcessPacket(std::unique_ptr<QuicReceivedPacket> packet) {
- connection_->ProcessUdpPacket(self_addr_, peer_addr_, *packet);
+ connection_->ProcessUdpPacket(
+ QuicSocketAddress(QuicSocketAddressImpl(self_addr_)),
+ QuicSocketAddress(QuicSocketAddressImpl(peer_addr_)), *packet);
}
// Configures the test fixture to use the list of expected writes.
@@ -321,7 +320,7 @@ class QuicHttpStreamTest : public ::testing::TestWithParam<QuicVersion> {
kQuicYieldAfterPacketsRead,
QuicTime::Delta::FromMilliseconds(kQuicYieldAfterDurationMilliseconds),
/*cert_verify_flags=*/0, DefaultQuicConfig(), &crypto_config_,
- "CONNECTION_UNKNOWN", dns_start, dns_end, &push_promise_index_,
+ "CONNECTION_UNKNOWN", dns_start, dns_end, &push_promise_index_, nullptr,
base::ThreadTaskRunnerHandle::Get().get(),
/*socket_performance_watcher=*/nullptr, net_log_.bound().net_log()));
session_->Initialize();
@@ -523,6 +522,15 @@ class QuicHttpStreamTest : public ::testing::TestWithParam<QuicVersion> {
!kIncludeCongestionFeedback);
}
+ std::unique_ptr<QuicReceivedPacket> ConstructSettingsPacket(
+ QuicPacketNumber packet_number,
+ SpdySettingsIds id,
+ size_t value,
+ QuicStreamOffset* offset) {
+ return client_maker_.MakeSettingsPacket(packet_number, id, value,
+ kIncludeVersion, offset);
+ }
+
void ReceivePromise(QuicStreamId id) {
auto headers = AsHeaderList(push_promise_);
QuicChromiumClientStream* stream =
@@ -619,8 +627,14 @@ TEST_P(QuicHttpStreamTest, DisableConnectionMigrationForStream) {
TEST_P(QuicHttpStreamTest, GetRequest) {
SetRequest("GET", "/", DEFAULT_PRIORITY);
size_t spdy_request_header_frame_length;
- AddWrite(ConstructRequestHeadersPacket(1, kFin, DEFAULT_PRIORITY,
- &spdy_request_header_frame_length));
+ QuicStreamOffset header_stream_offset = 0;
+ AddWrite(ConstructSettingsPacket(1, SETTINGS_MAX_HEADER_LIST_SIZE,
+ kDefaultMaxUncompressedHeaderSize,
+ &header_stream_offset));
+ AddWrite(InnerConstructRequestHeadersPacket(
+ 2, kClientDataStreamId1, kIncludeVersion, kFin, DEFAULT_PRIORITY,
+ &spdy_request_header_frame_length, &header_stream_offset));
+
Initialize();
request_.method = "GET";
@@ -678,16 +692,18 @@ TEST_P(QuicHttpStreamTest, LoadTimingTwoRequests) {
size_t spdy_request_header_frame_length;
QuicStreamOffset offset = 0;
+ AddWrite(ConstructSettingsPacket(1, SETTINGS_MAX_HEADER_LIST_SIZE,
+ kDefaultMaxUncompressedHeaderSize, &offset));
AddWrite(InnerConstructRequestHeadersPacket(
- 1, kClientDataStreamId1, kIncludeVersion, kFin, DEFAULT_PRIORITY,
+ 2, kClientDataStreamId1, kIncludeVersion, kFin, DEFAULT_PRIORITY,
&spdy_request_header_frame_length, &offset));
// SetRequest() again for second request as |request_headers_| was moved.
SetRequest("GET", "/", DEFAULT_PRIORITY);
AddWrite(InnerConstructRequestHeadersPacket(
- 2, kClientDataStreamId2, kIncludeVersion, kFin, DEFAULT_PRIORITY,
+ 3, kClientDataStreamId2, kIncludeVersion, kFin, DEFAULT_PRIORITY,
&spdy_request_header_frame_length, &offset));
- AddWrite(ConstructClientAckPacket(3, 3, 1)); // Ack the responses.
+ AddWrite(ConstructClientAckPacket(4, 3, 1)); // Ack the responses.
Initialize();
@@ -759,9 +775,14 @@ TEST_P(QuicHttpStreamTest, LoadTimingTwoRequests) {
TEST_P(QuicHttpStreamTest, GetRequestWithTrailers) {
SetRequest("GET", "/", DEFAULT_PRIORITY);
size_t spdy_request_header_frame_length;
- AddWrite(ConstructRequestHeadersPacket(1, kFin, DEFAULT_PRIORITY,
- &spdy_request_header_frame_length));
- AddWrite(ConstructClientAckPacket(2, 3, 1)); // Ack the data packet.
+ QuicStreamOffset header_stream_offset = 0;
+ AddWrite(ConstructSettingsPacket(1, SETTINGS_MAX_HEADER_LIST_SIZE,
+ kDefaultMaxUncompressedHeaderSize,
+ &header_stream_offset));
+ AddWrite(InnerConstructRequestHeadersPacket(
+ 2, kClientDataStreamId1, kIncludeVersion, kFin, DEFAULT_PRIORITY,
+ &spdy_request_header_frame_length, &header_stream_offset));
+ AddWrite(ConstructClientAckPacket(3, 3, 1)); // Ack the data packet.
Initialize();
@@ -850,8 +871,13 @@ TEST_P(QuicHttpStreamTest, GetRequestWithTrailers) {
TEST_P(QuicHttpStreamTest, GetRequestLargeResponse) {
SetRequest("GET", "/", DEFAULT_PRIORITY);
size_t spdy_request_headers_frame_length;
- AddWrite(ConstructRequestHeadersPacket(1, kFin, DEFAULT_PRIORITY,
- &spdy_request_headers_frame_length));
+ QuicStreamOffset header_stream_offset = 0;
+ AddWrite(ConstructSettingsPacket(1, SETTINGS_MAX_HEADER_LIST_SIZE,
+ kDefaultMaxUncompressedHeaderSize,
+ &header_stream_offset));
+ AddWrite(InnerConstructRequestHeadersPacket(
+ 2, kClientDataStreamId1, kIncludeVersion, kFin, DEFAULT_PRIORITY,
+ &spdy_request_headers_frame_length, &header_stream_offset));
Initialize();
request_.method = "GET";
@@ -949,9 +975,14 @@ TEST_P(QuicHttpStreamTest, GetSSLInfoAfterSessionClosed) {
TEST_P(QuicHttpStreamTest, LogGranularQuicConnectionError) {
SetRequest("GET", "/", DEFAULT_PRIORITY);
size_t spdy_request_headers_frame_length;
- AddWrite(ConstructRequestHeadersPacket(1, kFin, DEFAULT_PRIORITY,
- &spdy_request_headers_frame_length));
- AddWrite(ConstructAckAndRstStreamPacket(2));
+ QuicStreamOffset header_stream_offset = 0;
+ AddWrite(ConstructSettingsPacket(1, SETTINGS_MAX_HEADER_LIST_SIZE,
+ kDefaultMaxUncompressedHeaderSize,
+ &header_stream_offset));
+ AddWrite(InnerConstructRequestHeadersPacket(
+ 2, kClientDataStreamId1, kIncludeVersion, kFin, DEFAULT_PRIORITY,
+ &spdy_request_headers_frame_length, &header_stream_offset));
+ AddWrite(ConstructAckAndRstStreamPacket(3));
use_closing_stream_ = true;
Initialize();
@@ -984,9 +1015,14 @@ TEST_P(QuicHttpStreamTest, LogGranularQuicConnectionError) {
TEST_P(QuicHttpStreamTest, DoNotLogGranularQuicErrorIfHandshakeNotConfirmed) {
SetRequest("GET", "/", DEFAULT_PRIORITY);
size_t spdy_request_headers_frame_length;
- AddWrite(ConstructRequestHeadersPacket(1, kFin, DEFAULT_PRIORITY,
- &spdy_request_headers_frame_length));
- AddWrite(ConstructAckAndRstStreamPacket(2));
+ QuicStreamOffset header_stream_offset = 0;
+ AddWrite(ConstructSettingsPacket(1, SETTINGS_MAX_HEADER_LIST_SIZE,
+ kDefaultMaxUncompressedHeaderSize,
+ &header_stream_offset));
+ AddWrite(InnerConstructRequestHeadersPacket(
+ 2, kClientDataStreamId1, kIncludeVersion, kFin, DEFAULT_PRIORITY,
+ &spdy_request_headers_frame_length, &header_stream_offset));
+ AddWrite(ConstructAckAndRstStreamPacket(3));
use_closing_stream_ = true;
Initialize();
@@ -1024,8 +1060,13 @@ TEST_P(QuicHttpStreamTest, DoNotLogGranularQuicErrorIfHandshakeNotConfirmed) {
TEST_P(QuicHttpStreamTest, SessionClosedBeforeReadResponseHeaders) {
SetRequest("GET", "/", DEFAULT_PRIORITY);
size_t spdy_request_headers_frame_length;
- AddWrite(ConstructRequestHeadersPacket(1, kFin, DEFAULT_PRIORITY,
- &spdy_request_headers_frame_length));
+ QuicStreamOffset header_stream_offset = 0;
+ AddWrite(ConstructSettingsPacket(1, SETTINGS_MAX_HEADER_LIST_SIZE,
+ kDefaultMaxUncompressedHeaderSize,
+ &header_stream_offset));
+ AddWrite(InnerConstructRequestHeadersPacket(
+ 2, kClientDataStreamId1, kIncludeVersion, kFin, DEFAULT_PRIORITY,
+ &spdy_request_headers_frame_length, &header_stream_offset));
Initialize();
request_.method = "GET";
@@ -1053,10 +1094,15 @@ TEST_P(QuicHttpStreamTest, SessionClosedBeforeReadResponseHeaders) {
TEST_P(QuicHttpStreamTest, SendPostRequest) {
SetRequest("POST", "/", DEFAULT_PRIORITY);
size_t spdy_request_headers_frame_length;
- AddWrite(ConstructRequestHeadersPacket(1, !kFin, DEFAULT_PRIORITY,
- &spdy_request_headers_frame_length));
- AddWrite(ConstructClientDataPacket(2, kIncludeVersion, kFin, 0, kUploadData));
- AddWrite(ConstructClientAckPacket(3, 3, 1));
+ QuicStreamOffset header_stream_offset = 0;
+ AddWrite(ConstructSettingsPacket(1, SETTINGS_MAX_HEADER_LIST_SIZE,
+ kDefaultMaxUncompressedHeaderSize,
+ &header_stream_offset));
+ AddWrite(InnerConstructRequestHeadersPacket(
+ 2, kClientDataStreamId1, kIncludeVersion, !kFin, DEFAULT_PRIORITY,
+ &spdy_request_headers_frame_length, &header_stream_offset));
+ AddWrite(ConstructClientDataPacket(3, kIncludeVersion, kFin, 0, kUploadData));
+ AddWrite(ConstructClientAckPacket(4, 3, 1));
Initialize();
@@ -1119,13 +1165,18 @@ TEST_P(QuicHttpStreamTest, SendChunkedPostRequest) {
SetRequest("POST", "/", DEFAULT_PRIORITY);
size_t chunk_size = strlen(kUploadData);
size_t spdy_request_headers_frame_length;
- AddWrite(ConstructRequestHeadersPacket(1, !kFin, DEFAULT_PRIORITY,
- &spdy_request_headers_frame_length));
+ QuicStreamOffset header_stream_offset = 0;
+ AddWrite(ConstructSettingsPacket(1, SETTINGS_MAX_HEADER_LIST_SIZE,
+ kDefaultMaxUncompressedHeaderSize,
+ &header_stream_offset));
+ AddWrite(InnerConstructRequestHeadersPacket(
+ 2, kClientDataStreamId1, kIncludeVersion, !kFin, DEFAULT_PRIORITY,
+ &spdy_request_headers_frame_length, &header_stream_offset));
AddWrite(
- ConstructClientDataPacket(2, kIncludeVersion, !kFin, 0, kUploadData));
- AddWrite(ConstructClientDataPacket(3, kIncludeVersion, kFin, chunk_size,
+ ConstructClientDataPacket(3, kIncludeVersion, !kFin, 0, kUploadData));
+ AddWrite(ConstructClientDataPacket(4, kIncludeVersion, kFin, chunk_size,
kUploadData));
- AddWrite(ConstructClientAckPacket(4, 3, 1));
+ AddWrite(ConstructClientAckPacket(5, 3, 1));
Initialize();
ChunkedUploadDataStream upload_data_stream(0);
@@ -1190,12 +1241,17 @@ TEST_P(QuicHttpStreamTest, SendChunkedPostRequestWithFinalEmptyDataPacket) {
SetRequest("POST", "/", DEFAULT_PRIORITY);
size_t chunk_size = strlen(kUploadData);
size_t spdy_request_headers_frame_length;
- AddWrite(ConstructRequestHeadersPacket(1, !kFin, DEFAULT_PRIORITY,
- &spdy_request_headers_frame_length));
+ QuicStreamOffset header_stream_offset = 0;
+ AddWrite(ConstructSettingsPacket(1, SETTINGS_MAX_HEADER_LIST_SIZE,
+ kDefaultMaxUncompressedHeaderSize,
+ &header_stream_offset));
+ AddWrite(InnerConstructRequestHeadersPacket(
+ 2, kClientDataStreamId1, kIncludeVersion, !kFin, DEFAULT_PRIORITY,
+ &spdy_request_headers_frame_length, &header_stream_offset));
AddWrite(
- ConstructClientDataPacket(2, kIncludeVersion, !kFin, 0, kUploadData));
- AddWrite(ConstructClientDataPacket(3, kIncludeVersion, kFin, chunk_size, ""));
- AddWrite(ConstructClientAckPacket(4, 3, 1));
+ ConstructClientDataPacket(3, kIncludeVersion, !kFin, 0, kUploadData));
+ AddWrite(ConstructClientDataPacket(4, kIncludeVersion, kFin, chunk_size, ""));
+ AddWrite(ConstructClientAckPacket(5, 3, 1));
Initialize();
ChunkedUploadDataStream upload_data_stream(0);
@@ -1257,10 +1313,15 @@ TEST_P(QuicHttpStreamTest, SendChunkedPostRequestWithFinalEmptyDataPacket) {
TEST_P(QuicHttpStreamTest, SendChunkedPostRequestWithOneEmptyDataPacket) {
SetRequest("POST", "/", DEFAULT_PRIORITY);
size_t spdy_request_headers_frame_length;
- AddWrite(ConstructRequestHeadersPacket(1, !kFin, DEFAULT_PRIORITY,
- &spdy_request_headers_frame_length));
- AddWrite(ConstructClientDataPacket(2, kIncludeVersion, kFin, 0, ""));
- AddWrite(ConstructClientAckPacket(3, 3, 1));
+ QuicStreamOffset header_stream_offset = 0;
+ AddWrite(ConstructSettingsPacket(1, SETTINGS_MAX_HEADER_LIST_SIZE,
+ kDefaultMaxUncompressedHeaderSize,
+ &header_stream_offset));
+ AddWrite(InnerConstructRequestHeadersPacket(
+ 2, kClientDataStreamId1, kIncludeVersion, !kFin, DEFAULT_PRIORITY,
+ &spdy_request_headers_frame_length, &header_stream_offset));
+ AddWrite(ConstructClientDataPacket(3, kIncludeVersion, kFin, 0, ""));
+ AddWrite(ConstructClientAckPacket(4, 3, 1));
Initialize();
ChunkedUploadDataStream upload_data_stream(0);
@@ -1321,9 +1382,14 @@ TEST_P(QuicHttpStreamTest, SendChunkedPostRequestWithOneEmptyDataPacket) {
TEST_P(QuicHttpStreamTest, DestroyedEarly) {
SetRequest("GET", "/", DEFAULT_PRIORITY);
size_t spdy_request_headers_frame_length;
- AddWrite(ConstructRequestHeadersPacket(1, kFin, DEFAULT_PRIORITY,
- &spdy_request_headers_frame_length));
- AddWrite(ConstructAckAndRstStreamPacket(2));
+ QuicStreamOffset header_stream_offset = 0;
+ AddWrite(ConstructSettingsPacket(1, SETTINGS_MAX_HEADER_LIST_SIZE,
+ kDefaultMaxUncompressedHeaderSize,
+ &header_stream_offset));
+ AddWrite(InnerConstructRequestHeadersPacket(
+ 2, kClientDataStreamId1, kIncludeVersion, kFin, DEFAULT_PRIORITY,
+ &spdy_request_headers_frame_length, &header_stream_offset));
+ AddWrite(ConstructAckAndRstStreamPacket(3));
use_closing_stream_ = true;
Initialize();
@@ -1361,9 +1427,14 @@ TEST_P(QuicHttpStreamTest, DestroyedEarly) {
TEST_P(QuicHttpStreamTest, Priority) {
SetRequest("GET", "/", MEDIUM);
size_t spdy_request_headers_frame_length;
- AddWrite(ConstructRequestHeadersPacket(1, kFin, MEDIUM,
- &spdy_request_headers_frame_length));
- AddWrite(ConstructAckAndRstStreamPacket(2));
+ QuicStreamOffset header_stream_offset = 0;
+ AddWrite(ConstructSettingsPacket(1, SETTINGS_MAX_HEADER_LIST_SIZE,
+ kDefaultMaxUncompressedHeaderSize,
+ &header_stream_offset));
+ AddWrite(InnerConstructRequestHeadersPacket(
+ 2, kClientDataStreamId1, kIncludeVersion, kFin, MEDIUM,
+ &spdy_request_headers_frame_length, &header_stream_offset));
+ AddWrite(ConstructAckAndRstStreamPacket(3));
use_closing_stream_ = true;
Initialize();
@@ -1412,8 +1483,11 @@ TEST_P(QuicHttpStreamTest, Priority) {
TEST_P(QuicHttpStreamTest, CheckPriorityWithNoDelegate) {
SetRequest("GET", "/", MEDIUM);
use_closing_stream_ = true;
-
- AddWrite(ConstructClientRstStreamPacket(1));
+ QuicStreamOffset header_stream_offset = 0;
+ AddWrite(ConstructSettingsPacket(1, SETTINGS_MAX_HEADER_LIST_SIZE,
+ kDefaultMaxUncompressedHeaderSize,
+ &header_stream_offset));
+ AddWrite(ConstructClientRstStreamPacket(2));
Initialize();
@@ -1444,10 +1518,15 @@ TEST_P(QuicHttpStreamTest, CheckPriorityWithNoDelegate) {
TEST_P(QuicHttpStreamTest, SessionClosedDuringDoLoop) {
SetRequest("POST", "/", DEFAULT_PRIORITY);
size_t spdy_request_headers_frame_length;
- AddWrite(ConstructRequestHeadersPacket(1, !kFin, DEFAULT_PRIORITY,
- &spdy_request_headers_frame_length));
+ QuicStreamOffset header_stream_offset = 0;
+ AddWrite(ConstructSettingsPacket(1, SETTINGS_MAX_HEADER_LIST_SIZE,
+ kDefaultMaxUncompressedHeaderSize,
+ &header_stream_offset));
+ AddWrite(InnerConstructRequestHeadersPacket(
+ 2, kClientDataStreamId1, kIncludeVersion, !kFin, DEFAULT_PRIORITY,
+ &spdy_request_headers_frame_length, &header_stream_offset));
AddWrite(
- ConstructClientDataPacket(2, kIncludeVersion, !kFin, 0, kUploadData));
+ ConstructClientDataPacket(3, kIncludeVersion, !kFin, 0, kUploadData));
// Second data write will result in a synchronous failure which will close
// the session.
AddWrite(SYNCHRONOUS, ERR_FAILED);
@@ -1478,6 +1557,10 @@ TEST_P(QuicHttpStreamTest, SessionClosedDuringDoLoop) {
TEST_P(QuicHttpStreamTest, SessionClosedBeforeSendHeadersComplete) {
SetRequest("POST", "/", DEFAULT_PRIORITY);
+ QuicStreamOffset header_stream_offset = 0;
+ AddWrite(ConstructSettingsPacket(1, SETTINGS_MAX_HEADER_LIST_SIZE,
+ kDefaultMaxUncompressedHeaderSize,
+ &header_stream_offset));
AddWrite(SYNCHRONOUS, ERR_FAILED);
Initialize();
@@ -1499,8 +1582,13 @@ TEST_P(QuicHttpStreamTest, SessionClosedBeforeSendHeadersComplete) {
TEST_P(QuicHttpStreamTest, SessionClosedBeforeSendBodyComplete) {
SetRequest("POST", "/", DEFAULT_PRIORITY);
size_t spdy_request_headers_frame_length;
- AddWrite(ConstructRequestHeadersPacket(1, !kFin, DEFAULT_PRIORITY,
- &spdy_request_headers_frame_length));
+ QuicStreamOffset header_stream_offset = 0;
+ AddWrite(ConstructSettingsPacket(1, SETTINGS_MAX_HEADER_LIST_SIZE,
+ kDefaultMaxUncompressedHeaderSize,
+ &header_stream_offset));
+ AddWrite(InnerConstructRequestHeadersPacket(
+ 2, kClientDataStreamId1, kIncludeVersion, !kFin, DEFAULT_PRIORITY,
+ &spdy_request_headers_frame_length, &header_stream_offset));
AddWrite(SYNCHRONOUS, ERR_FAILED);
Initialize();
@@ -1887,12 +1975,16 @@ TEST_P(QuicHttpStreamTest, ServerPushVaryCheckFail) {
request_headers_["accept-encoding"] = "sdch";
size_t spdy_request_header_frame_length;
- AddWrite(ConstructClientRstStreamVaryMismatchPacket(1));
+ QuicStreamOffset header_stream_offset = 0;
+ AddWrite(ConstructSettingsPacket(1, SETTINGS_MAX_HEADER_LIST_SIZE,
+ kDefaultMaxUncompressedHeaderSize,
+ &header_stream_offset));
+ AddWrite(ConstructClientRstStreamVaryMismatchPacket(2));
AddWrite(InnerConstructRequestHeadersPacket(
- 2, stream_id_ + 2, !kIncludeVersion, kFin, DEFAULT_PRIORITY,
- &spdy_request_header_frame_length, /*offset=*/nullptr));
- AddWrite(ConstructClientAckPacket(3, 3, 1));
- AddWrite(ConstructClientRstStreamCancelledPacket(4));
+ 3, stream_id_ + 2, !kIncludeVersion, kFin, DEFAULT_PRIORITY,
+ &spdy_request_header_frame_length, &header_stream_offset));
+ AddWrite(ConstructClientAckPacket(4, 3, 1));
+ AddWrite(ConstructClientRstStreamCancelledPacket(5));
Initialize();
// Initialize the first stream, for receiving the promise on.
@@ -1998,9 +2090,14 @@ TEST_P(QuicHttpStreamTest, ServerPushVaryCheckFail) {
TEST_P(QuicHttpStreamTest, DataReadErrorSynchronous) {
SetRequest("POST", "/", DEFAULT_PRIORITY);
size_t spdy_request_headers_frame_length;
- AddWrite(ConstructRequestHeadersPacket(1, !kFin, DEFAULT_PRIORITY,
- &spdy_request_headers_frame_length));
- AddWrite(ConstructClientRstStreamErrorPacket(2, kIncludeVersion));
+ QuicStreamOffset header_stream_offset = 0;
+ AddWrite(ConstructSettingsPacket(1, SETTINGS_MAX_HEADER_LIST_SIZE,
+ kDefaultMaxUncompressedHeaderSize,
+ &header_stream_offset));
+ AddWrite(InnerConstructRequestHeadersPacket(
+ 2, kClientDataStreamId1, kIncludeVersion, !kFin, DEFAULT_PRIORITY,
+ &spdy_request_headers_frame_length, &header_stream_offset));
+ AddWrite(ConstructClientRstStreamErrorPacket(3, kIncludeVersion));
Initialize();
@@ -2030,9 +2127,14 @@ TEST_P(QuicHttpStreamTest, DataReadErrorSynchronous) {
TEST_P(QuicHttpStreamTest, DataReadErrorAsynchronous) {
SetRequest("POST", "/", DEFAULT_PRIORITY);
size_t spdy_request_headers_frame_length;
- AddWrite(ConstructRequestHeadersPacket(1, !kFin, DEFAULT_PRIORITY,
- &spdy_request_headers_frame_length));
- AddWrite(ConstructClientRstStreamErrorPacket(2, !kIncludeVersion));
+ QuicStreamOffset header_stream_offset = 0;
+ AddWrite(ConstructSettingsPacket(1, SETTINGS_MAX_HEADER_LIST_SIZE,
+ kDefaultMaxUncompressedHeaderSize,
+ &header_stream_offset));
+ AddWrite(InnerConstructRequestHeadersPacket(
+ 2, kClientDataStreamId1, kIncludeVersion, !kFin, DEFAULT_PRIORITY,
+ &spdy_request_headers_frame_length, &header_stream_offset));
+ AddWrite(ConstructClientRstStreamErrorPacket(3, !kIncludeVersion));
Initialize();
diff --git a/chromium/net/quic/core/quic_http_utils.cc b/chromium/net/quic/chromium/quic_http_utils.cc
index f9e953da1e9..09e9e248794 100644
--- a/chromium/net/quic/core/quic_http_utils.cc
+++ b/chromium/net/quic/chromium/quic_http_utils.cc
@@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#include "net/quic/core/quic_http_utils.h"
+#include "net/quic/chromium/quic_http_utils.h"
#include <utility>
diff --git a/chromium/net/quic/core/quic_http_utils.h b/chromium/net/quic/chromium/quic_http_utils.h
index 6b3e38f19ed..44435130517 100644
--- a/chromium/net/quic/core/quic_http_utils.h
+++ b/chromium/net/quic/chromium/quic_http_utils.h
@@ -2,13 +2,13 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#ifndef NET_QUIC_QUIC_HTTP_UTILS_H_
-#define NET_QUIC_QUIC_HTTP_UTILS_H_
+#ifndef NET_QUIC_CHROMIUM_QUIC_HTTP_UTILS_H_
+#define NET_QUIC_CHROMIUM_QUIC_HTTP_UTILS_H_
#include "base/values.h"
#include "net/base/net_export.h"
#include "net/base/request_priority.h"
-#include "net/quic/core/quic_protocol.h"
+#include "net/quic/core/quic_packets.h"
#include "net/spdy/spdy_header_block.h"
#include "net/spdy/spdy_protocol.h"
@@ -29,4 +29,4 @@ NET_EXPORT std::unique_ptr<base::Value> QuicRequestNetLogCallback(
} // namespace net
-#endif // NET_QUIC_QUIC_HTTP_UTILS_H_
+#endif // NET_QUIC_CHROMIUM_QUIC_HTTP_UTILS_H_
diff --git a/chromium/net/quic/core/quic_http_utils_test.cc b/chromium/net/quic/chromium/quic_http_utils_test.cc
index 330e8e8cdc4..39c9c68b8e6 100644
--- a/chromium/net/quic/core/quic_http_utils_test.cc
+++ b/chromium/net/quic/chromium/quic_http_utils_test.cc
@@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#include "net/quic/core/quic_http_utils.h"
+#include "net/quic/chromium/quic_http_utils.h"
#include <stdint.h>
diff --git a/chromium/net/quic/chromium/quic_network_transaction_unittest.cc b/chromium/net/quic/chromium/quic_network_transaction_unittest.cc
index 6fe6e30c50e..fe8e2bc8aae 100644
--- a/chromium/net/quic/chromium/quic_network_transaction_unittest.cc
+++ b/chromium/net/quic/chromium/quic_network_transaction_unittest.cc
@@ -10,6 +10,7 @@
#include "base/compiler_specific.h"
#include "base/macros.h"
+#include "base/memory/ptr_util.h"
#include "base/run_loop.h"
#include "base/stl_util.h"
#include "base/strings/stringprintf.h"
@@ -37,17 +38,17 @@
#include "net/proxy/proxy_resolver.h"
#include "net/proxy/proxy_service.h"
#include "net/quic/chromium/crypto/proof_verifier_chromium.h"
+#include "net/quic/chromium/mock_crypto_client_stream_factory.h"
#include "net/quic/chromium/mock_network_change_notifier.h"
#include "net/quic/chromium/mock_quic_data.h"
+#include "net/quic/chromium/quic_http_utils.h"
+#include "net/quic/chromium/quic_test_packet_maker.h"
#include "net/quic/core/crypto/quic_decrypter.h"
#include "net/quic/core/crypto/quic_encrypter.h"
#include "net/quic/core/quic_framer.h"
-#include "net/quic/core/quic_http_utils.h"
#include "net/quic/test_tools/crypto_test_utils.h"
#include "net/quic/test_tools/mock_clock.h"
-#include "net/quic/test_tools/mock_crypto_client_stream_factory.h"
#include "net/quic/test_tools/mock_random.h"
-#include "net/quic/test_tools/quic_test_packet_maker.h"
#include "net/quic/test_tools/quic_test_utils.h"
#include "net/socket/client_socket_factory.h"
#include "net/socket/mock_client_socket_pool_manager.h"
@@ -69,9 +70,6 @@
#include "testing/platform_test.h"
#include "url/gurl.h"
-using net::test::IsError;
-using net::test::IsOk;
-
namespace net {
namespace test {
@@ -155,11 +153,15 @@ class HeadersHandler {
class TestSocketPerformanceWatcher : public SocketPerformanceWatcher {
public:
- explicit TestSocketPerformanceWatcher(bool* rtt_notification_received)
- : rtt_notification_received_(rtt_notification_received) {}
+ TestSocketPerformanceWatcher(bool* should_notify_updated_rtt,
+ bool* rtt_notification_received)
+ : should_notify_updated_rtt_(should_notify_updated_rtt),
+ rtt_notification_received_(rtt_notification_received) {}
~TestSocketPerformanceWatcher() override {}
- bool ShouldNotifyUpdatedRTT() const override { return true; }
+ bool ShouldNotifyUpdatedRTT() const override {
+ return *should_notify_updated_rtt_;
+ }
void OnUpdatedRTTAvailable(const base::TimeDelta& rtt) override {
*rtt_notification_received_ = true;
@@ -168,6 +170,7 @@ class TestSocketPerformanceWatcher : public SocketPerformanceWatcher {
void OnConnectionChanged() override {}
private:
+ bool* should_notify_updated_rtt_;
bool* rtt_notification_received_;
DISALLOW_COPY_AND_ASSIGN(TestSocketPerformanceWatcher);
@@ -177,7 +180,9 @@ class TestSocketPerformanceWatcherFactory
: public SocketPerformanceWatcherFactory {
public:
TestSocketPerformanceWatcherFactory()
- : watcher_count_(0u), rtt_notification_received_(false) {}
+ : watcher_count_(0u),
+ should_notify_updated_rtt_(true),
+ rtt_notification_received_(false) {}
~TestSocketPerformanceWatcherFactory() override {}
// SocketPerformanceWatcherFactory implementation:
@@ -188,15 +193,21 @@ class TestSocketPerformanceWatcherFactory
}
++watcher_count_;
return std::unique_ptr<SocketPerformanceWatcher>(
- new TestSocketPerformanceWatcher(&rtt_notification_received_));
+ new TestSocketPerformanceWatcher(&should_notify_updated_rtt_,
+ &rtt_notification_received_));
}
size_t watcher_count() const { return watcher_count_; }
bool rtt_notification_received() const { return rtt_notification_received_; }
+ void set_should_notify_updated_rtt(bool should_notify_updated_rtt) {
+ should_notify_updated_rtt_ = should_notify_updated_rtt;
+ }
+
private:
size_t watcher_count_;
+ bool should_notify_updated_rtt_;
bool rtt_notification_received_;
DISALLOW_COPY_AND_ASSIGN(TestSocketPerformanceWatcherFactory);
@@ -273,6 +284,14 @@ class QuicNetworkTransactionTest
}
std::unique_ptr<QuicEncryptedPacket> ConstructClientAckPacket(
+ QuicPacketNumber packet_number,
+ QuicPacketNumber largest_received,
+ QuicPacketNumber least_unacked) {
+ return client_maker_.MakeAckPacket(packet_number, largest_received,
+ least_unacked, least_unacked, true);
+ }
+
+ std::unique_ptr<QuicEncryptedPacket> ConstructClientAckPacket(
QuicPacketNumber largest_received,
QuicPacketNumber least_unacked) {
return client_maker_.MakeAckPacket(2, largest_received, least_unacked,
@@ -334,6 +353,23 @@ class QuicNetworkTransactionTest
error_code);
}
+ std::unique_ptr<QuicReceivedPacket> ConstructSettingsPacket(
+ QuicPacketNumber packet_number,
+ SpdySettingsIds id,
+ size_t value,
+ QuicStreamOffset* offset) {
+ return client_maker_.MakeSettingsPacket(packet_number, id, value,
+ kIncludeVersion, offset);
+ }
+
+ std::unique_ptr<QuicReceivedPacket> ConstructServerAckPacket(
+ QuicPacketNumber packet_number,
+ QuicPacketNumber largest_received,
+ QuicPacketNumber least_unacked) {
+ return server_maker_.MakeAckPacket(packet_number, largest_received,
+ least_unacked, false);
+ }
+
// Uses default QuicTestPacketMaker.
SpdyHeaderBlock GetRequestHeaders(const std::string& method,
const std::string& scheme,
@@ -730,30 +766,92 @@ INSTANTIATE_TEST_CASE_P(Version,
QuicNetworkTransactionTest,
::testing::ValuesIn(AllSupportedVersions()));
-TEST_P(QuicNetworkTransactionTest, ForceQuic) {
+TEST_P(QuicNetworkTransactionTest, SocketWatcherEnabled) {
params_.origins_to_force_quic_on.insert(
HostPortPair::FromString("mail.example.org:443"));
MockQuicData mock_quic_data;
+ QuicStreamOffset header_stream_offset = 0;
+ mock_quic_data.AddWrite(ConstructSettingsPacket(
+ 1, SETTINGS_MAX_HEADER_LIST_SIZE, kDefaultMaxUncompressedHeaderSize,
+ &header_stream_offset));
mock_quic_data.AddWrite(ConstructClientRequestHeadersPacket(
- 1, kClientDataStreamId1, true, true,
- GetRequestHeaders("GET", "https", "/")));
+ 2, kClientDataStreamId1, true, true,
+ GetRequestHeaders("GET", "https", "/"), &header_stream_offset));
mock_quic_data.AddRead(ConstructServerResponseHeadersPacket(
1, kClientDataStreamId1, false, false, GetResponseHeaders("200 OK")));
mock_quic_data.AddRead(ConstructServerDataPacket(2, kClientDataStreamId1,
false, true, 0, "hello!"));
- mock_quic_data.AddWrite(ConstructClientAckPacket(2, 1));
+ mock_quic_data.AddWrite(ConstructClientAckPacket(3, 2, 1));
mock_quic_data.AddRead(SYNCHRONOUS, ERR_IO_PENDING); // No more data to read
mock_quic_data.AddSocketDataToFactory(&socket_factory_);
CreateSession();
+ test_socket_performance_watcher_factory_.set_should_notify_updated_rtt(true);
EXPECT_FALSE(
test_socket_performance_watcher_factory_.rtt_notification_received());
SendRequestAndExpectQuicResponse("hello!");
EXPECT_TRUE(
test_socket_performance_watcher_factory_.rtt_notification_received());
+}
+
+TEST_P(QuicNetworkTransactionTest, SocketWatcherDisabled) {
+ params_.origins_to_force_quic_on.insert(
+ HostPortPair::FromString("mail.example.org:443"));
+
+ MockQuicData mock_quic_data;
+ QuicStreamOffset header_stream_offset = 0;
+ mock_quic_data.AddWrite(ConstructSettingsPacket(
+ 1, SETTINGS_MAX_HEADER_LIST_SIZE, kDefaultMaxUncompressedHeaderSize,
+ &header_stream_offset));
+ mock_quic_data.AddWrite(ConstructClientRequestHeadersPacket(
+ 2, kClientDataStreamId1, true, true,
+ GetRequestHeaders("GET", "https", "/"), &header_stream_offset));
+ mock_quic_data.AddRead(ConstructServerResponseHeadersPacket(
+ 1, kClientDataStreamId1, false, false, GetResponseHeaders("200 OK")));
+ mock_quic_data.AddRead(ConstructServerDataPacket(2, kClientDataStreamId1,
+ false, true, 0, "hello!"));
+ mock_quic_data.AddWrite(ConstructClientAckPacket(3, 2, 1));
+ mock_quic_data.AddRead(SYNCHRONOUS, ERR_IO_PENDING); // No more data to read
+
+ mock_quic_data.AddSocketDataToFactory(&socket_factory_);
+
+ CreateSession();
+ test_socket_performance_watcher_factory_.set_should_notify_updated_rtt(false);
+
+ EXPECT_FALSE(
+ test_socket_performance_watcher_factory_.rtt_notification_received());
+ SendRequestAndExpectQuicResponse("hello!");
+ EXPECT_FALSE(
+ test_socket_performance_watcher_factory_.rtt_notification_received());
+}
+
+TEST_P(QuicNetworkTransactionTest, ForceQuic) {
+ params_.origins_to_force_quic_on.insert(
+ HostPortPair::FromString("mail.example.org:443"));
+
+ MockQuicData mock_quic_data;
+ QuicStreamOffset header_stream_offset = 0;
+ mock_quic_data.AddWrite(ConstructSettingsPacket(
+ 1, SETTINGS_MAX_HEADER_LIST_SIZE, kDefaultMaxUncompressedHeaderSize,
+ &header_stream_offset));
+ mock_quic_data.AddWrite(ConstructClientRequestHeadersPacket(
+ 2, kClientDataStreamId1, true, true,
+ GetRequestHeaders("GET", "https", "/"), &header_stream_offset));
+ mock_quic_data.AddRead(ConstructServerResponseHeadersPacket(
+ 1, kClientDataStreamId1, false, false, GetResponseHeaders("200 OK")));
+ mock_quic_data.AddRead(ConstructServerDataPacket(2, kClientDataStreamId1,
+ false, true, 0, "hello!"));
+ mock_quic_data.AddWrite(ConstructClientAckPacket(3, 2, 1));
+ mock_quic_data.AddRead(SYNCHRONOUS, ERR_IO_PENDING); // No more data to read
+
+ mock_quic_data.AddSocketDataToFactory(&socket_factory_);
+
+ CreateSession();
+
+ SendRequestAndExpectQuicResponse("hello!");
// Check that the NetLog was filled reasonably.
TestNetLogEntry::List entries;
@@ -800,14 +898,18 @@ TEST_P(QuicNetworkTransactionTest, ForceQuicForAll) {
AddQuicAlternateProtocolMapping(MockCryptoClientStream::CONFIRM_HANDSHAKE);
MockQuicData mock_quic_data;
+ QuicStreamOffset header_stream_offset = 0;
+ mock_quic_data.AddWrite(ConstructSettingsPacket(
+ 1, SETTINGS_MAX_HEADER_LIST_SIZE, kDefaultMaxUncompressedHeaderSize,
+ &header_stream_offset));
mock_quic_data.AddWrite(ConstructClientRequestHeadersPacket(
- 1, kClientDataStreamId1, true, true,
- GetRequestHeaders("GET", "https", "/")));
+ 2, kClientDataStreamId1, true, true,
+ GetRequestHeaders("GET", "https", "/"), &header_stream_offset));
mock_quic_data.AddRead(ConstructServerResponseHeadersPacket(
1, kClientDataStreamId1, false, false, GetResponseHeaders("200 OK")));
mock_quic_data.AddRead(ConstructServerDataPacket(2, kClientDataStreamId1,
false, true, 0, "hello!"));
- mock_quic_data.AddWrite(ConstructClientAckPacket(2, 1));
+ mock_quic_data.AddWrite(ConstructClientAckPacket(3, 2, 1));
mock_quic_data.AddRead(SYNCHRONOUS, ERR_IO_PENDING); // No more data to read
mock_quic_data.AddSocketDataToFactory(&socket_factory_);
@@ -825,14 +927,18 @@ TEST_P(QuicNetworkTransactionTest, QuicProxy) {
ProxyService::CreateFixedFromPacResult("QUIC mail.example.org:70");
MockQuicData mock_quic_data;
+ QuicStreamOffset header_stream_offset = 0;
+ mock_quic_data.AddWrite(ConstructSettingsPacket(
+ 1, SETTINGS_MAX_HEADER_LIST_SIZE, kDefaultMaxUncompressedHeaderSize,
+ &header_stream_offset));
mock_quic_data.AddWrite(ConstructClientRequestHeadersPacket(
- 1, kClientDataStreamId1, true, true,
- GetRequestHeaders("GET", "http", "/")));
+ 2, kClientDataStreamId1, true, true,
+ GetRequestHeaders("GET", "http", "/"), &header_stream_offset));
mock_quic_data.AddRead(ConstructServerResponseHeadersPacket(
1, kClientDataStreamId1, false, false, GetResponseHeaders("200 OK")));
mock_quic_data.AddRead(ConstructServerDataPacket(2, kClientDataStreamId1,
false, true, 0, "hello!"));
- mock_quic_data.AddWrite(ConstructClientAckPacket(2, 1));
+ mock_quic_data.AddWrite(ConstructClientAckPacket(3, 2, 1));
mock_quic_data.AddRead(ASYNC, ERR_IO_PENDING); // No more data to read
mock_quic_data.AddRead(ASYNC, 0); // EOF
@@ -864,14 +970,18 @@ TEST_P(QuicNetworkTransactionTest, QuicProxyWithCert) {
client_maker_.set_hostname(origin_host);
MockQuicData mock_quic_data;
+ QuicStreamOffset header_stream_offset = 0;
+ mock_quic_data.AddWrite(ConstructSettingsPacket(
+ 1, SETTINGS_MAX_HEADER_LIST_SIZE, kDefaultMaxUncompressedHeaderSize,
+ &header_stream_offset));
mock_quic_data.AddWrite(ConstructClientRequestHeadersPacket(
- 1, kClientDataStreamId1, true, true,
- GetRequestHeaders("GET", "http", "/")));
+ 2, kClientDataStreamId1, true, true,
+ GetRequestHeaders("GET", "http", "/"), &header_stream_offset));
mock_quic_data.AddRead(ConstructServerResponseHeadersPacket(
1, kClientDataStreamId1, false, false, GetResponseHeaders("200 OK")));
mock_quic_data.AddRead(ConstructServerDataPacket(2, kClientDataStreamId1,
false, true, 0, "hello!"));
- mock_quic_data.AddWrite(ConstructClientAckPacket(2, 1));
+ mock_quic_data.AddWrite(ConstructClientAckPacket(3, 2, 1));
mock_quic_data.AddRead(ASYNC, ERR_IO_PENDING); // No more data to read
mock_quic_data.AddRead(ASYNC, 0);
mock_quic_data.AddSocketDataToFactory(&socket_factory_);
@@ -917,14 +1027,18 @@ TEST_P(QuicNetworkTransactionTest, AlternativeServicesDifferentHost) {
client_maker_.set_hostname(origin.host());
MockQuicData mock_quic_data;
+ QuicStreamOffset header_stream_offset = 0;
+ mock_quic_data.AddWrite(ConstructSettingsPacket(
+ 1, SETTINGS_MAX_HEADER_LIST_SIZE, kDefaultMaxUncompressedHeaderSize,
+ &header_stream_offset));
mock_quic_data.AddWrite(ConstructClientRequestHeadersPacket(
- 1, kClientDataStreamId1, true, true,
- GetRequestHeaders("GET", "https", "/")));
+ 2, kClientDataStreamId1, true, true,
+ GetRequestHeaders("GET", "https", "/"), &header_stream_offset));
mock_quic_data.AddRead(ConstructServerResponseHeadersPacket(
1, kClientDataStreamId1, false, false, GetResponseHeaders("200 OK")));
mock_quic_data.AddRead(ConstructServerDataPacket(2, kClientDataStreamId1,
false, true, 0, "hello!"));
- mock_quic_data.AddWrite(ConstructClientAckPacket(2, 1));
+ mock_quic_data.AddWrite(ConstructClientAckPacket(3, 2, 1));
mock_quic_data.AddRead(ASYNC, ERR_IO_PENDING); // No more data to read
mock_quic_data.AddRead(ASYNC, 0);
mock_quic_data.AddSocketDataToFactory(&socket_factory_);
@@ -943,9 +1057,16 @@ TEST_P(QuicNetworkTransactionTest, ForceQuicWithErrorConnecting) {
HostPortPair::FromString("mail.example.org:443"));
MockQuicData mock_quic_data1;
+ QuicStreamOffset header_stream_offset = 0;
+ mock_quic_data1.AddWrite(ConstructSettingsPacket(
+ 1, SETTINGS_MAX_HEADER_LIST_SIZE, kDefaultMaxUncompressedHeaderSize,
+ &header_stream_offset));
mock_quic_data1.AddRead(ASYNC, ERR_SOCKET_NOT_CONNECTED);
-
MockQuicData mock_quic_data2;
+ header_stream_offset = 0;
+ mock_quic_data2.AddWrite(ConstructSettingsPacket(
+ 1, SETTINGS_MAX_HEADER_LIST_SIZE, kDefaultMaxUncompressedHeaderSize,
+ &header_stream_offset));
crypto_client_stream_factory_.AddProofVerifyDetails(&verify_details_);
mock_quic_data2.AddRead(ASYNC, ERR_SOCKET_NOT_CONNECTED);
crypto_client_stream_factory_.AddProofVerifyDetails(&verify_details_);
@@ -1000,14 +1121,18 @@ TEST_P(QuicNetworkTransactionTest, UseAlternativeServiceForQuic) {
socket_factory_.AddSSLSocketDataProvider(&ssl_data_);
MockQuicData mock_quic_data;
+ QuicStreamOffset header_stream_offset = 0;
+ mock_quic_data.AddWrite(ConstructSettingsPacket(
+ 1, SETTINGS_MAX_HEADER_LIST_SIZE, kDefaultMaxUncompressedHeaderSize,
+ &header_stream_offset));
mock_quic_data.AddWrite(ConstructClientRequestHeadersPacket(
- 1, kClientDataStreamId1, true, true,
- GetRequestHeaders("GET", "https", "/")));
+ 2, kClientDataStreamId1, true, true,
+ GetRequestHeaders("GET", "https", "/"), &header_stream_offset));
mock_quic_data.AddRead(ConstructServerResponseHeadersPacket(
1, kClientDataStreamId1, false, false, GetResponseHeaders("200 OK")));
mock_quic_data.AddRead(ConstructServerDataPacket(2, kClientDataStreamId1,
false, true, 0, "hello!"));
- mock_quic_data.AddWrite(ConstructClientAckPacket(2, 1));
+ mock_quic_data.AddWrite(ConstructClientAckPacket(3, 2, 1));
mock_quic_data.AddRead(ASYNC, ERR_IO_PENDING); // No more data to read
mock_quic_data.AddRead(ASYNC, 0); // EOF
@@ -1035,14 +1160,18 @@ TEST_P(QuicNetworkTransactionTest,
socket_factory_.AddSSLSocketDataProvider(&ssl_data_);
MockQuicData mock_quic_data;
+ QuicStreamOffset header_stream_offset = 0;
+ mock_quic_data.AddWrite(ConstructSettingsPacket(
+ 1, SETTINGS_MAX_HEADER_LIST_SIZE, kDefaultMaxUncompressedHeaderSize,
+ &header_stream_offset));
mock_quic_data.AddWrite(ConstructClientRequestHeadersPacket(
- 1, kClientDataStreamId1, true, true,
- GetRequestHeaders("GET", "https", "/")));
+ 2, kClientDataStreamId1, true, true,
+ GetRequestHeaders("GET", "https", "/"), &header_stream_offset));
mock_quic_data.AddRead(ConstructServerResponseHeadersPacket(
1, kClientDataStreamId1, false, false, GetResponseHeaders("200 OK")));
mock_quic_data.AddRead(ConstructServerDataPacket(2, kClientDataStreamId1,
false, true, 0, "hello!"));
- mock_quic_data.AddWrite(ConstructClientAckPacket(2, 1));
+ mock_quic_data.AddWrite(ConstructClientAckPacket(3, 2, 1));
mock_quic_data.AddRead(ASYNC, ERR_IO_PENDING); // No more data to read
mock_quic_data.AddRead(ASYNC, 0); // EOF
@@ -1136,14 +1265,18 @@ TEST_P(QuicNetworkTransactionTest, UseAlternativeServiceAllSupportedVersion) {
socket_factory_.AddSSLSocketDataProvider(&ssl_data_);
MockQuicData mock_quic_data;
+ QuicStreamOffset header_stream_offset = 0;
+ mock_quic_data.AddWrite(ConstructSettingsPacket(
+ 1, SETTINGS_MAX_HEADER_LIST_SIZE, kDefaultMaxUncompressedHeaderSize,
+ &header_stream_offset));
mock_quic_data.AddWrite(ConstructClientRequestHeadersPacket(
- 1, kClientDataStreamId1, true, true,
- GetRequestHeaders("GET", "https", "/")));
+ 2, kClientDataStreamId1, true, true,
+ GetRequestHeaders("GET", "https", "/"), &header_stream_offset));
mock_quic_data.AddRead(ConstructServerResponseHeadersPacket(
1, kClientDataStreamId1, false, false, GetResponseHeaders("200 OK")));
mock_quic_data.AddRead(ConstructServerDataPacket(2, kClientDataStreamId1,
false, true, 0, "hello!"));
- mock_quic_data.AddWrite(ConstructClientAckPacket(2, 1));
+ mock_quic_data.AddWrite(ConstructClientAckPacket(3, 2, 1));
mock_quic_data.AddRead(ASYNC, ERR_IO_PENDING); // No more data to read
mock_quic_data.AddRead(ASYNC, 0); // EOF
@@ -1158,21 +1291,25 @@ TEST_P(QuicNetworkTransactionTest, UseAlternativeServiceAllSupportedVersion) {
TEST_P(QuicNetworkTransactionTest, GoAwayWithConnectionMigrationOnPortsOnly) {
MockQuicData mock_quic_data;
+ QuicStreamOffset header_stream_offset = 0;
+ mock_quic_data.AddWrite(ConstructSettingsPacket(
+ 1, SETTINGS_MAX_HEADER_LIST_SIZE, kDefaultMaxUncompressedHeaderSize,
+ &header_stream_offset));
mock_quic_data.AddWrite(ConstructClientRequestHeadersPacket(
- 1, kClientDataStreamId1, true, true,
- GetRequestHeaders("GET", "https", "/")));
+ 2, kClientDataStreamId1, true, true,
+ GetRequestHeaders("GET", "https", "/"), &header_stream_offset));
mock_quic_data.AddRead(ConstructServerResponseHeadersPacket(
1, kClientDataStreamId1, false, false, GetResponseHeaders("200 OK")));
// Read a GoAway packet with
// QuicErrorCode: QUIC_ERROR_MIGRATING_PORT from the peer.
- mock_quic_data.AddRead(ConstructServerGoAwayPacket(
+ mock_quic_data.AddSynchronousRead(ConstructServerGoAwayPacket(
2, QUIC_ERROR_MIGRATING_PORT,
"connection migration with port change only"));
- mock_quic_data.AddWrite(ConstructClientAckPacket(2, 1));
- mock_quic_data.AddRead(ConstructServerDataPacket(3, kClientDataStreamId1,
- false, true, 0, "hello!"));
+ mock_quic_data.AddWrite(ConstructClientAckPacket(3, 2, 1));
+ mock_quic_data.AddSynchronousRead(ConstructServerDataPacket(
+ 3, kClientDataStreamId1, false, true, 0, "hello!"));
mock_quic_data.AddWrite(ConstructClientAckAndRstPacket(
- 3, kClientDataStreamId1, QUIC_STREAM_CANCELLED, 3, 3, 1));
+ 4, kClientDataStreamId1, QUIC_STREAM_CANCELLED, 3, 3, 1));
mock_quic_data.AddRead(ASYNC, ERR_IO_PENDING); // No more data to read
mock_quic_data.AddRead(ASYNC, 0); // EOF
@@ -1263,8 +1400,11 @@ TEST_P(QuicNetworkTransactionTest, UseExistingAlternativeServiceForQuic) {
// Open a session to foo.example.org:443 using the first entry of the
// alternative service list.
MockQuicData mock_quic_data;
+ mock_quic_data.AddWrite(ConstructSettingsPacket(
+ 1, SETTINGS_MAX_HEADER_LIST_SIZE, kDefaultMaxUncompressedHeaderSize,
+ &request_header_offset));
mock_quic_data.AddWrite(ConstructClientRequestHeadersPacket(
- 1, kClientDataStreamId1, true, true,
+ 2, kClientDataStreamId1, true, true,
GetRequestHeaders("GET", "https", "/"), &request_header_offset));
std::string alt_svc_list =
@@ -1275,13 +1415,13 @@ TEST_P(QuicNetworkTransactionTest, UseExistingAlternativeServiceForQuic) {
GetResponseHeaders("200 OK", alt_svc_list), &response_header_offset));
mock_quic_data.AddRead(ConstructServerDataPacket(2, kClientDataStreamId1,
false, true, 0, "hello!"));
- mock_quic_data.AddWrite(ConstructClientAckPacket(2, 1));
+ mock_quic_data.AddWrite(ConstructClientAckPacket(3, 2, 1));
// Second QUIC request data.
// Connection pooling, using existing session, no need to include version
// as version negotiation has been completed.
mock_quic_data.AddWrite(ConstructClientRequestHeadersPacket(
- 3, kClientDataStreamId2, false, true,
+ 4, kClientDataStreamId2, false, true,
GetRequestHeaders("GET", "https", "/"), &request_header_offset));
mock_quic_data.AddRead(ConstructServerResponseHeadersPacket(
3, kClientDataStreamId2, false, false, GetResponseHeaders("200 OK"),
@@ -1289,7 +1429,7 @@ TEST_P(QuicNetworkTransactionTest, UseExistingAlternativeServiceForQuic) {
mock_quic_data.AddRead(ConstructServerDataPacket(4, kClientDataStreamId2,
false, true, 0, "hello!"));
mock_quic_data.AddWrite(
- ConstructClientAckAndConnectionClosePacket(4, 4, 3, 1));
+ ConstructClientAckAndConnectionClosePacket(5, 4, 3, 1));
mock_quic_data.AddRead(ASYNC, ERR_IO_PENDING); // No more data to read
mock_quic_data.AddRead(ASYNC, 0); // EOF
@@ -1315,8 +1455,11 @@ TEST_P(QuicNetworkTransactionTest, UseExistingQUICAlternativeProxy) {
// Open a session to foo.example.org:443 using the first entry of the
// alternative service list.
MockQuicData mock_quic_data;
+ mock_quic_data.AddWrite(ConstructSettingsPacket(
+ 1, SETTINGS_MAX_HEADER_LIST_SIZE, kDefaultMaxUncompressedHeaderSize,
+ &request_header_offset));
mock_quic_data.AddWrite(ConstructClientRequestHeadersPacket(
- 1, kClientDataStreamId1, true, true,
+ 2, kClientDataStreamId1, true, true,
GetRequestHeaders("GET", "http", "/"), &request_header_offset));
std::string alt_svc_list;
@@ -1325,13 +1468,13 @@ TEST_P(QuicNetworkTransactionTest, UseExistingQUICAlternativeProxy) {
GetResponseHeaders("200 OK", alt_svc_list), &response_header_offset));
mock_quic_data.AddRead(ConstructServerDataPacket(2, kClientDataStreamId1,
false, true, 0, "hello!"));
- mock_quic_data.AddWrite(ConstructClientAckPacket(2, 1));
+ mock_quic_data.AddWrite(ConstructClientAckPacket(3, 2, 1));
// Second QUIC request data.
// Connection pooling, using existing session, no need to include version
// as version negotiation has been completed.
mock_quic_data.AddWrite(ConstructClientRequestHeadersPacket(
- 3, kClientDataStreamId2, false, true,
+ 4, kClientDataStreamId2, false, true,
GetRequestHeaders("GET", "http", "/"), &request_header_offset));
mock_quic_data.AddRead(ConstructServerResponseHeadersPacket(
3, kClientDataStreamId2, false, false, GetResponseHeaders("200 OK"),
@@ -1339,7 +1482,7 @@ TEST_P(QuicNetworkTransactionTest, UseExistingQUICAlternativeProxy) {
mock_quic_data.AddRead(ConstructServerDataPacket(4, kClientDataStreamId2,
false, true, 0, "hello!"));
mock_quic_data.AddWrite(
- ConstructClientAckAndConnectionClosePacket(4, 4, 3, 1));
+ ConstructClientAckAndConnectionClosePacket(5, 4, 3, 1));
mock_quic_data.AddRead(ASYNC, ERR_IO_PENDING); // No more data to read
mock_quic_data.AddRead(ASYNC, 0); // EOF
@@ -1379,20 +1522,23 @@ TEST_P(QuicNetworkTransactionTest, PoolByOrigin) {
QuicStreamOffset request_header_offset(0);
QuicStreamOffset response_header_offset(0);
+ mock_quic_data.AddWrite(ConstructSettingsPacket(
+ 1, SETTINGS_MAX_HEADER_LIST_SIZE, kDefaultMaxUncompressedHeaderSize,
+ &request_header_offset));
// First request.
mock_quic_data.AddWrite(ConstructClientRequestHeadersPacket(
- 1, kClientDataStreamId1, true, true,
+ 2, kClientDataStreamId1, true, true,
GetRequestHeaders("GET", "https", "/"), &request_header_offset));
mock_quic_data.AddRead(ConstructServerResponseHeadersPacket(
1, kClientDataStreamId1, false, false, GetResponseHeaders("200 OK"),
&response_header_offset));
mock_quic_data.AddRead(ConstructServerDataPacket(2, kClientDataStreamId1,
false, true, 0, "hello!"));
- mock_quic_data.AddWrite(ConstructClientAckPacket(2, 1));
+ mock_quic_data.AddWrite(ConstructClientAckPacket(3, 2, 1));
// Second request.
mock_quic_data.AddWrite(ConstructClientRequestHeadersPacket(
- 3, kClientDataStreamId2, false, true,
+ 4, kClientDataStreamId2, false, true,
GetRequestHeaders("GET", "https", "/"), &request_header_offset));
mock_quic_data.AddRead(ConstructServerResponseHeadersPacket(
3, kClientDataStreamId2, false, false, GetResponseHeaders("200 OK"),
@@ -1400,7 +1546,7 @@ TEST_P(QuicNetworkTransactionTest, PoolByOrigin) {
mock_quic_data.AddRead(ConstructServerDataPacket(4, kClientDataStreamId2,
false, true, 0, "hello!"));
mock_quic_data.AddWrite(
- ConstructClientAckAndConnectionClosePacket(4, 4, 3, 1));
+ ConstructClientAckAndConnectionClosePacket(5, 4, 3, 1));
mock_quic_data.AddRead(ASYNC, ERR_IO_PENDING); // No more data to read
mock_quic_data.AddRead(ASYNC, 0); // EOF
@@ -1445,16 +1591,20 @@ TEST_P(QuicNetworkTransactionTest, PoolByDestination) {
QuicStreamOffset request_header_offset(0);
QuicStreamOffset response_header_offset(0);
+ mock_quic_data.AddWrite(ConstructSettingsPacket(
+ 1, SETTINGS_MAX_HEADER_LIST_SIZE, kDefaultMaxUncompressedHeaderSize,
+ &request_header_offset));
+
// First request.
mock_quic_data.AddWrite(ConstructClientRequestHeadersPacket(
- 1, kClientDataStreamId1, true, true,
+ 2, kClientDataStreamId1, true, true,
GetRequestHeaders("GET", "https", "/"), &request_header_offset));
mock_quic_data.AddRead(ConstructServerResponseHeadersPacket(
1, kClientDataStreamId1, false, false, GetResponseHeaders("200 OK"),
&response_header_offset));
mock_quic_data.AddRead(ConstructServerDataPacket(2, kClientDataStreamId1,
false, true, 0, "hello!"));
- mock_quic_data.AddWrite(ConstructClientAckPacket(2, 1));
+ mock_quic_data.AddWrite(ConstructClientAckPacket(3, 2, 1));
// Second request.
QuicTestPacketMaker client_maker2(version_, 0, clock_, origin2.host(),
@@ -1462,7 +1612,7 @@ TEST_P(QuicNetworkTransactionTest, PoolByDestination) {
QuicTestPacketMaker server_maker2(version_, 0, clock_, origin2.host(),
Perspective::IS_SERVER);
mock_quic_data.AddWrite(ConstructClientRequestHeadersPacket(
- 3, kClientDataStreamId2, false, true,
+ 4, kClientDataStreamId2, false, true,
GetRequestHeaders("GET", "https", "/", &client_maker2),
&request_header_offset));
mock_quic_data.AddRead(ConstructServerResponseHeadersPacket(
@@ -1471,7 +1621,7 @@ TEST_P(QuicNetworkTransactionTest, PoolByDestination) {
mock_quic_data.AddRead(ConstructServerDataPacket(4, kClientDataStreamId2,
false, true, 0, "hello!"));
mock_quic_data.AddWrite(
- ConstructClientAckAndConnectionClosePacket(4, 4, 3, 1));
+ ConstructClientAckAndConnectionClosePacket(5, 4, 3, 1));
mock_quic_data.AddRead(ASYNC, ERR_IO_PENDING); // No more data to read
mock_quic_data.AddRead(ASYNC, 0); // EOF
@@ -1556,10 +1706,12 @@ TEST_P(QuicNetworkTransactionTest,
server_maker_.set_hostname("www.example.org");
client_maker_.set_hostname("www.example.org");
MockQuicData mock_quic_data;
-
+ mock_quic_data.AddWrite(ConstructSettingsPacket(
+ 1, SETTINGS_MAX_HEADER_LIST_SIZE, kDefaultMaxUncompressedHeaderSize,
+ &request_header_offset));
// First QUIC request data.
mock_quic_data.AddWrite(ConstructClientRequestHeadersPacket(
- 1, kClientDataStreamId1, true, true,
+ 2, kClientDataStreamId1, true, true,
GetRequestHeaders("GET", "https", "/"), &request_header_offset));
mock_quic_data.AddRead(ConstructServerResponseHeadersPacket(
@@ -1567,10 +1719,10 @@ TEST_P(QuicNetworkTransactionTest,
&response_header_offset));
mock_quic_data.AddRead(ConstructServerDataPacket(
2, kClientDataStreamId1, false, true, 0, "hello from mail QUIC!"));
- mock_quic_data.AddWrite(ConstructClientAckPacket(2, 1));
+ mock_quic_data.AddWrite(ConstructClientAckPacket(3, 2, 1));
// Second QUIC request data.
mock_quic_data.AddWrite(ConstructClientRequestHeadersPacket(
- 3, kClientDataStreamId2, false, true,
+ 4, kClientDataStreamId2, false, true,
GetRequestHeaders("GET", "https", "/", &client_maker),
&request_header_offset));
mock_quic_data.AddRead(ConstructServerResponseHeadersPacket(
@@ -1579,7 +1731,7 @@ TEST_P(QuicNetworkTransactionTest,
mock_quic_data.AddRead(ConstructServerDataPacket(
4, kClientDataStreamId2, false, true, 0, "hello from mail QUIC!"));
mock_quic_data.AddWrite(
- ConstructClientAckAndConnectionClosePacket(4, 4, 3, 1));
+ ConstructClientAckAndConnectionClosePacket(5, 4, 3, 1));
mock_quic_data.AddRead(ASYNC, ERR_IO_PENDING); // No more data to read
mock_quic_data.AddRead(ASYNC, 0); // EOF
@@ -1645,14 +1797,18 @@ TEST_P(QuicNetworkTransactionTest, ConfirmAlternativeService) {
socket_factory_.AddSSLSocketDataProvider(&ssl_data_);
MockQuicData mock_quic_data;
+ QuicStreamOffset header_stream_offset = 0;
+ mock_quic_data.AddWrite(ConstructSettingsPacket(
+ 1, SETTINGS_MAX_HEADER_LIST_SIZE, kDefaultMaxUncompressedHeaderSize,
+ &header_stream_offset));
mock_quic_data.AddWrite(ConstructClientRequestHeadersPacket(
- 1, kClientDataStreamId1, true, true,
- GetRequestHeaders("GET", "https", "/")));
+ 2, kClientDataStreamId1, true, true,
+ GetRequestHeaders("GET", "https", "/"), &header_stream_offset));
mock_quic_data.AddRead(ConstructServerResponseHeadersPacket(
1, kClientDataStreamId1, false, false, GetResponseHeaders("200 OK")));
mock_quic_data.AddRead(ConstructServerDataPacket(2, kClientDataStreamId1,
false, true, 0, "hello!"));
- mock_quic_data.AddWrite(ConstructClientAckPacket(2, 1));
+ mock_quic_data.AddWrite(ConstructClientAckPacket(3, 2, 1));
mock_quic_data.AddRead(ASYNC, ERR_IO_PENDING); // No more data to read
mock_quic_data.AddRead(ASYNC, 0); // EOF
@@ -1690,14 +1846,18 @@ TEST_P(QuicNetworkTransactionTest, UseAlternativeServiceForQuicForHttps) {
socket_factory_.AddSSLSocketDataProvider(&ssl_data_);
MockQuicData mock_quic_data;
+ QuicStreamOffset header_stream_offset = 0;
+ mock_quic_data.AddWrite(ConstructSettingsPacket(
+ 1, SETTINGS_MAX_HEADER_LIST_SIZE, kDefaultMaxUncompressedHeaderSize,
+ &header_stream_offset));
mock_quic_data.AddWrite(ConstructClientRequestHeadersPacket(
- 1, kClientDataStreamId1, true, true,
- GetRequestHeaders("GET", "https", "/")));
+ 2, kClientDataStreamId1, true, true,
+ GetRequestHeaders("GET", "https", "/"), &header_stream_offset));
mock_quic_data.AddRead(ConstructServerResponseHeadersPacket(
1, kClientDataStreamId1, false, false, GetResponseHeaders("200 OK")));
mock_quic_data.AddRead(ConstructServerDataPacket(2, kClientDataStreamId1,
false, true, 0, "hello!"));
- mock_quic_data.AddWrite(ConstructClientAckPacket(2, 1));
+ mock_quic_data.AddWrite(ConstructClientAckPacket(3, 2, 1));
mock_quic_data.AddRead(SYNCHRONOUS, 0); // EOF
mock_quic_data.AddSocketDataToFactory(&socket_factory_);
@@ -1717,14 +1877,18 @@ TEST_P(QuicNetworkTransactionTest, QuicProxyWithRacing) {
ProxyService::CreateFixedFromPacResult("HTTPS mail.example.org:443");
MockQuicData mock_quic_data;
+ QuicStreamOffset header_stream_offset = 0;
+ mock_quic_data.AddWrite(ConstructSettingsPacket(
+ 1, SETTINGS_MAX_HEADER_LIST_SIZE, kDefaultMaxUncompressedHeaderSize,
+ &header_stream_offset));
mock_quic_data.AddWrite(ConstructClientRequestHeadersPacket(
- 1, kClientDataStreamId1, true, true,
- GetRequestHeaders("GET", "http", "/")));
+ 2, kClientDataStreamId1, true, true,
+ GetRequestHeaders("GET", "http", "/"), &header_stream_offset));
mock_quic_data.AddRead(ConstructServerResponseHeadersPacket(
1, kClientDataStreamId1, false, false, GetResponseHeaders("200 OK")));
mock_quic_data.AddRead(ConstructServerDataPacket(2, kClientDataStreamId1,
false, true, 0, "hello!"));
- mock_quic_data.AddWrite(ConstructClientAckPacket(2, 1));
+ mock_quic_data.AddWrite(ConstructClientAckPacket(3, 2, 1));
mock_quic_data.AddRead(ASYNC, ERR_IO_PENDING); // No more data to read
mock_quic_data.AddRead(ASYNC, 0); // EOF
@@ -1813,9 +1977,10 @@ TEST_P(QuicNetworkTransactionTest, HungAlternativeService) {
TEST_P(QuicNetworkTransactionTest, ZeroRTTWithHttpRace) {
MockQuicData mock_quic_data;
+ QuicStreamOffset header_stream_offset = 0;
mock_quic_data.AddWrite(ConstructClientRequestHeadersPacket(
1, kClientDataStreamId1, true, true,
- GetRequestHeaders("GET", "https", "/")));
+ GetRequestHeaders("GET", "https", "/"), &header_stream_offset));
mock_quic_data.AddRead(ConstructServerResponseHeadersPacket(
1, kClientDataStreamId1, false, false, GetResponseHeaders("200 OK")));
mock_quic_data.AddRead(ConstructServerDataPacket(2, kClientDataStreamId1,
@@ -1905,14 +2070,18 @@ TEST_P(QuicNetworkTransactionTest, ZeroRTTWithProxy) {
TEST_P(QuicNetworkTransactionTest, ZeroRTTWithConfirmationRequired) {
MockQuicData mock_quic_data;
+ QuicStreamOffset header_stream_offset = 0;
+ mock_quic_data.AddWrite(ConstructSettingsPacket(
+ 1, SETTINGS_MAX_HEADER_LIST_SIZE, kDefaultMaxUncompressedHeaderSize,
+ &header_stream_offset));
mock_quic_data.AddWrite(ConstructClientRequestHeadersPacket(
- 1, kClientDataStreamId1, true, true,
- GetRequestHeaders("GET", "https", "/")));
+ 2, kClientDataStreamId1, true, true,
+ GetRequestHeaders("GET", "https", "/"), &header_stream_offset));
mock_quic_data.AddRead(ConstructServerResponseHeadersPacket(
1, kClientDataStreamId1, false, false, GetResponseHeaders("200 OK")));
mock_quic_data.AddRead(ConstructServerDataPacket(2, kClientDataStreamId1,
false, true, 0, "hello!"));
- mock_quic_data.AddWrite(ConstructClientAckPacket(2, 1));
+ mock_quic_data.AddWrite(ConstructClientAckPacket(3, 2, 1));
mock_quic_data.AddRead(SYNCHRONOUS, ERR_IO_PENDING); // No more data to read
mock_quic_data.AddSocketDataToFactory(&socket_factory_);
@@ -1954,9 +2123,13 @@ TEST_P(QuicNetworkTransactionTest, ZeroRTTWithConfirmationRequired) {
TEST_P(QuicNetworkTransactionTest,
LogGranularQuicErrorCodeOnQuicProtocolErrorLocal) {
MockQuicData mock_quic_data;
+ QuicStreamOffset header_stream_offset = 0;
+ mock_quic_data.AddWrite(ConstructSettingsPacket(
+ 1, SETTINGS_MAX_HEADER_LIST_SIZE, kDefaultMaxUncompressedHeaderSize,
+ &header_stream_offset));
mock_quic_data.AddWrite(ConstructClientRequestHeadersPacket(
- 1, kClientDataStreamId1, true, true,
- GetRequestHeaders("GET", "https", "/")));
+ 2, kClientDataStreamId1, true, true,
+ GetRequestHeaders("GET", "https", "/"), &header_stream_offset));
// Read a close connection packet with
// QuicErrorCode: QUIC_CRYPTO_VERSION_NOT_SUPPORTED from the peer.
mock_quic_data.AddRead(ConstructServerConnectionClosePacket(1));
@@ -2004,16 +2177,20 @@ TEST_P(QuicNetworkTransactionTest,
TEST_P(QuicNetworkTransactionTest,
LogGranularQuicErrorCodeOnQuicProtocolErrorRemote) {
MockQuicData mock_quic_data;
+ QuicStreamOffset header_stream_offset = 0;
+ mock_quic_data.AddWrite(ConstructSettingsPacket(
+ 1, SETTINGS_MAX_HEADER_LIST_SIZE, kDefaultMaxUncompressedHeaderSize,
+ &header_stream_offset));
mock_quic_data.AddWrite(ConstructClientRequestHeadersPacket(
- 1, kClientDataStreamId1, true, true,
- GetRequestHeaders("GET", "https", "/")));
+ 2, kClientDataStreamId1, true, true,
+ GetRequestHeaders("GET", "https", "/"), &header_stream_offset));
// Peer sending data from an non-existing stream causes this end to raise
// error and close connection.
mock_quic_data.AddRead(
ConstructServerRstPacket(1, false, 99, QUIC_STREAM_LAST_ERROR));
std::string quic_error_details = "Data for nonexistent stream";
mock_quic_data.AddWrite(ConstructClientAckAndConnectionClosePacket(
- 2, QuicTime::Delta::Infinite(), 0, 1, QUIC_INVALID_STREAM_ID,
+ 3, QuicTime::Delta::Infinite(), 0, 1, QUIC_INVALID_STREAM_ID,
quic_error_details));
mock_quic_data.AddSocketDataToFactory(&socket_factory_);
@@ -2056,15 +2233,19 @@ TEST_P(QuicNetworkTransactionTest,
TEST_P(QuicNetworkTransactionTest, RstSteamErrorHandling) {
MockQuicData mock_quic_data;
+ QuicStreamOffset header_stream_offset = 0;
+ mock_quic_data.AddWrite(ConstructSettingsPacket(
+ 1, SETTINGS_MAX_HEADER_LIST_SIZE, kDefaultMaxUncompressedHeaderSize,
+ &header_stream_offset));
mock_quic_data.AddWrite(ConstructClientRequestHeadersPacket(
- 1, kClientDataStreamId1, true, true,
- GetRequestHeaders("GET", "https", "/")));
+ 2, kClientDataStreamId1, true, true,
+ GetRequestHeaders("GET", "https", "/"), &header_stream_offset));
// Read the response headers, then a RST_STREAM frame.
mock_quic_data.AddRead(ConstructServerResponseHeadersPacket(
1, kClientDataStreamId1, false, false, GetResponseHeaders("200 OK")));
mock_quic_data.AddRead(ConstructServerRstPacket(
2, false, kClientDataStreamId1, QUIC_STREAM_CANCELLED));
- mock_quic_data.AddWrite(ConstructClientAckPacket(2, 1));
+ mock_quic_data.AddWrite(ConstructClientAckPacket(3, 2, 1));
mock_quic_data.AddRead(SYNCHRONOUS, ERR_IO_PENDING); // No more read data.
mock_quic_data.AddSocketDataToFactory(&socket_factory_);
@@ -2115,9 +2296,13 @@ TEST_P(QuicNetworkTransactionTest, RstSteamErrorHandling) {
TEST_P(QuicNetworkTransactionTest, RstSteamBeforeHeaders) {
MockQuicData mock_quic_data;
+ QuicStreamOffset header_stream_offset = 0;
+ mock_quic_data.AddWrite(ConstructSettingsPacket(
+ 1, SETTINGS_MAX_HEADER_LIST_SIZE, kDefaultMaxUncompressedHeaderSize,
+ &header_stream_offset));
mock_quic_data.AddWrite(ConstructClientRequestHeadersPacket(
- 1, kClientDataStreamId1, true, true,
- GetRequestHeaders("GET", "https", "/")));
+ 2, kClientDataStreamId1, true, true,
+ GetRequestHeaders("GET", "https", "/"), &header_stream_offset));
mock_quic_data.AddRead(ConstructServerRstPacket(
1, false, kClientDataStreamId1, QUIC_STREAM_CANCELLED));
mock_quic_data.AddRead(SYNCHRONOUS, ERR_IO_PENDING); // No more read data.
@@ -2455,14 +2640,18 @@ TEST_P(QuicNetworkTransactionTest, SecureResourceOverSecureQuic) {
EXPECT_FALSE(
test_socket_performance_watcher_factory_.rtt_notification_received());
MockQuicData mock_quic_data;
+ QuicStreamOffset header_stream_offset = 0;
+ mock_quic_data.AddWrite(ConstructSettingsPacket(
+ 1, SETTINGS_MAX_HEADER_LIST_SIZE, kDefaultMaxUncompressedHeaderSize,
+ &header_stream_offset));
mock_quic_data.AddWrite(ConstructClientRequestHeadersPacket(
- 1, kClientDataStreamId1, true, true,
- GetRequestHeaders("GET", "https", "/")));
+ 2, kClientDataStreamId1, true, true,
+ GetRequestHeaders("GET", "https", "/"), &header_stream_offset));
mock_quic_data.AddRead(ConstructServerResponseHeadersPacket(
1, kClientDataStreamId1, false, false, GetResponseHeaders("200 OK")));
mock_quic_data.AddRead(ConstructServerDataPacket(2, kClientDataStreamId1,
false, true, 0, "hello!"));
- mock_quic_data.AddWrite(ConstructClientAckPacket(2, 1));
+ mock_quic_data.AddWrite(ConstructClientAckPacket(3, 2, 1));
mock_quic_data.AddRead(SYNCHRONOUS, ERR_IO_PENDING); // No more read data.
mock_quic_data.AddSocketDataToFactory(&socket_factory_);
@@ -2565,8 +2754,11 @@ TEST_P(QuicNetworkTransactionTest, QuicUploadWriteError) {
MockQuicData socket_data;
socket_data.AddRead(SYNCHRONOUS, ERR_IO_PENDING);
QuicStreamOffset offset = 0;
+ socket_data.AddWrite(
+ ConstructSettingsPacket(1, SETTINGS_MAX_HEADER_LIST_SIZE,
+ kDefaultMaxUncompressedHeaderSize, &offset));
socket_data.AddWrite(ConstructClientRequestHeadersPacket(
- 1, kClientDataStreamId1, true, false,
+ 2, kClientDataStreamId1, true, false,
GetRequestHeaders("POST", "https", "/"), &offset));
socket_data.AddWrite(SYNCHRONOUS, ERR_FAILED);
socket_data.AddSocketDataToFactory(&socket_factory_);
@@ -2606,9 +2798,13 @@ TEST_P(QuicNetworkTransactionTest, QuicServerPush) {
HostPortPair::FromString("mail.example.org:443"));
MockQuicData mock_quic_data;
+ QuicStreamOffset header_stream_offset = 0;
+ mock_quic_data.AddWrite(ConstructSettingsPacket(
+ 1, SETTINGS_MAX_HEADER_LIST_SIZE, kDefaultMaxUncompressedHeaderSize,
+ &header_stream_offset));
mock_quic_data.AddWrite(ConstructClientRequestHeadersPacket(
- 1, kClientDataStreamId1, true, true,
- GetRequestHeaders("GET", "https", "/")));
+ 2, kClientDataStreamId1, true, true,
+ GetRequestHeaders("GET", "https", "/"), &header_stream_offset));
QuicStreamOffset server_header_offset = 0;
mock_quic_data.AddRead(ConstructServerPushPromisePacket(
1, kClientDataStreamId1, kServerDataStreamId1, false,
@@ -2617,17 +2813,17 @@ TEST_P(QuicNetworkTransactionTest, QuicServerPush) {
mock_quic_data.AddRead(ConstructServerResponseHeadersPacket(
2, kClientDataStreamId1, false, false, GetResponseHeaders("200 OK"),
&server_header_offset));
- mock_quic_data.AddWrite(ConstructClientAckPacket(2, 2, 1, 1));
+ mock_quic_data.AddWrite(ConstructClientAckPacket(3, 2, 1, 1));
mock_quic_data.AddRead(ConstructServerResponseHeadersPacket(
3, kServerDataStreamId1, false, false, GetResponseHeaders("200 OK"),
&server_header_offset));
mock_quic_data.AddRead(ConstructServerDataPacket(4, kClientDataStreamId1,
false, true, 0, "hello!"));
- mock_quic_data.AddWrite(ConstructClientAckPacket(3, 4, 3, 1));
+ mock_quic_data.AddWrite(ConstructClientAckPacket(4, 4, 3, 1));
mock_quic_data.AddRead(ConstructServerDataPacket(
5, kServerDataStreamId1, false, true, 0, "and hello!"));
mock_quic_data.AddWrite(ConstructClientAckAndRstPacket(
- 4, kServerDataStreamId1, QUIC_RST_ACKNOWLEDGEMENT, 5, 5, 1));
+ 5, kServerDataStreamId1, QUIC_RST_ACKNOWLEDGEMENT, 5, 5, 1));
mock_quic_data.AddRead(ASYNC, ERR_IO_PENDING); // No more data to read
mock_quic_data.AddRead(ASYNC, 0); // EOF
mock_quic_data.AddSocketDataToFactory(&socket_factory_);
@@ -2657,8 +2853,7 @@ TEST_P(QuicNetworkTransactionTest, QuicServerPush) {
}
TEST_P(QuicNetworkTransactionTest, QuicForceHolBlocking) {
- FLAGS_quic_enable_version_35 = true;
- FLAGS_quic_enable_version_36_v2 = true;
+ FLAGS_quic_reloadable_flag_quic_enable_version_36_v3 = true;
params_.quic_force_hol_blocking = true;
params_.origins_to_force_quic_on.insert(
HostPortPair::FromString("mail.example.org:443"));
@@ -2666,17 +2861,20 @@ TEST_P(QuicNetworkTransactionTest, QuicForceHolBlocking) {
MockQuicData mock_quic_data;
QuicStreamOffset offset = 0;
+ mock_quic_data.AddWrite(
+ ConstructSettingsPacket(1, SETTINGS_MAX_HEADER_LIST_SIZE,
+ kDefaultMaxUncompressedHeaderSize, &offset));
mock_quic_data.AddWrite(ConstructClientRequestHeadersPacket(
- 1, kClientDataStreamId1, true, false,
+ 2, kClientDataStreamId1, true, false,
GetRequestHeaders("POST", "https", "/"), &offset));
std::unique_ptr<QuicEncryptedPacket> packet;
if (version_ > QUIC_VERSION_35) {
- packet = ConstructClientForceHolDataPacket(2, kClientDataStreamId1, true,
+ packet = ConstructClientForceHolDataPacket(3, kClientDataStreamId1, true,
true, &offset, "1");
} else {
packet =
- ConstructClientDataPacket(2, kClientDataStreamId1, true, true, 0, "1");
+ ConstructClientDataPacket(3, kClientDataStreamId1, true, true, 0, "1");
}
mock_quic_data.AddWrite(std::move(packet));
@@ -2686,7 +2884,7 @@ TEST_P(QuicNetworkTransactionTest, QuicForceHolBlocking) {
mock_quic_data.AddRead(ConstructServerDataPacket(2, kClientDataStreamId1,
false, true, 0, "hello!"));
- mock_quic_data.AddWrite(ConstructClientAckPacket(3, 2, 1, 1));
+ mock_quic_data.AddWrite(ConstructClientAckPacket(4, 2, 1, 1));
mock_quic_data.AddRead(ASYNC, ERR_IO_PENDING); // No more data to read
mock_quic_data.AddRead(ASYNC, 0); // EOF
@@ -2744,11 +2942,16 @@ TEST_P(QuicNetworkTransactionTest, RawHeaderSizeSuccessfullRequest) {
HostPortPair::FromString("mail.example.org:443"));
MockQuicData mock_quic_data;
+ QuicStreamOffset header_stream_offset = 0;
+ mock_quic_data.AddWrite(ConstructSettingsPacket(
+ 1, SETTINGS_MAX_HEADER_LIST_SIZE, kDefaultMaxUncompressedHeaderSize,
+ &header_stream_offset));
SpdyHeaderBlock headers(GetRequestHeaders("GET", "https", "/"));
headers["user-agent"] = "";
headers["accept-encoding"] = "gzip, deflate";
mock_quic_data.AddWrite(ConstructClientRequestHeadersPacket(
- 1, kClientDataStreamId1, true, true, std::move(headers)));
+ 2, kClientDataStreamId1, true, true, std::move(headers),
+ &header_stream_offset));
QuicStreamOffset expected_raw_header_response_size = 0;
mock_quic_data.AddRead(ConstructServerResponseHeadersPacket(
@@ -2757,7 +2960,7 @@ TEST_P(QuicNetworkTransactionTest, RawHeaderSizeSuccessfullRequest) {
mock_quic_data.AddRead(ConstructServerDataPacket(
2, kClientDataStreamId1, false, true, 0, "Main Resource Data"));
- mock_quic_data.AddWrite(ConstructClientAckPacket(2, 1));
+ mock_quic_data.AddWrite(ConstructClientAckPacket(3, 2, 1));
mock_quic_data.AddRead(ASYNC, 0); // EOF
@@ -2797,11 +3000,16 @@ TEST_P(QuicNetworkTransactionTest, RawHeaderSizeSuccessfullPushHeadersFirst) {
HostPortPair::FromString("mail.example.org:443"));
MockQuicData mock_quic_data;
+ QuicStreamOffset header_stream_offset = 0;
+ mock_quic_data.AddWrite(ConstructSettingsPacket(
+ 1, SETTINGS_MAX_HEADER_LIST_SIZE, kDefaultMaxUncompressedHeaderSize,
+ &header_stream_offset));
SpdyHeaderBlock headers(GetRequestHeaders("GET", "https", "/"));
headers["user-agent"] = "";
headers["accept-encoding"] = "gzip, deflate";
mock_quic_data.AddWrite(ConstructClientRequestHeadersPacket(
- 1, kClientDataStreamId1, true, true, std::move(headers)));
+ 2, kClientDataStreamId1, true, true, std::move(headers),
+ &header_stream_offset));
QuicStreamOffset server_header_offset = 0;
QuicStreamOffset expected_raw_header_response_size = 0;
@@ -2818,7 +3026,7 @@ TEST_P(QuicNetworkTransactionTest, RawHeaderSizeSuccessfullPushHeadersFirst) {
expected_raw_header_response_size =
server_header_offset - expected_raw_header_response_size;
- mock_quic_data.AddWrite(ConstructClientAckPacket(2, 2, 1, 1));
+ mock_quic_data.AddWrite(ConstructClientAckPacket(3, 2, 1, 1));
mock_quic_data.AddRead(ConstructServerResponseHeadersPacket(
3, kServerDataStreamId1, false, false, GetResponseHeaders("200 OK"),
@@ -2826,7 +3034,7 @@ TEST_P(QuicNetworkTransactionTest, RawHeaderSizeSuccessfullPushHeadersFirst) {
mock_quic_data.AddRead(ConstructServerDataPacket(
4, kServerDataStreamId1, false, true, 0, "Pushed Resource Data"));
- mock_quic_data.AddWrite(ConstructClientAckPacket(3, 4, 3, 1));
+ mock_quic_data.AddWrite(ConstructClientAckPacket(4, 4, 3, 1));
mock_quic_data.AddRead(ConstructServerDataPacket(
5, kClientDataStreamId1, false, true, 0, "Main Resource Data"));
@@ -3006,6 +3214,16 @@ class QuicNetworkTransactionWithDestinationTest
ack_least_unacked, stop_least_unacked, true);
}
+ std::unique_ptr<QuicReceivedPacket> ConstructSettingsPacket(
+ QuicPacketNumber packet_number,
+ SpdySettingsIds id,
+ size_t value,
+ QuicStreamOffset* offset,
+ QuicTestPacketMaker* maker) {
+ return maker->MakeSettingsPacket(packet_number, id, value, kIncludeVersion,
+ offset);
+ }
+
void AddRefusedSocketData() {
std::unique_ptr<StaticSocketDataProvider> refused_data(
new StaticSocketDataProvider());
@@ -3167,13 +3385,16 @@ TEST_P(QuicNetworkTransactionWithDestinationTest, PoolIfCertificateValid) {
QuicStreamOffset response_header_offset(0);
MockQuicData mock_quic_data;
+ mock_quic_data.AddWrite(ConstructSettingsPacket(
+ 1, SETTINGS_MAX_HEADER_LIST_SIZE, kDefaultMaxUncompressedHeaderSize,
+ &request_header_offset, &client_maker1));
mock_quic_data.AddWrite(ConstructClientRequestHeadersPacket(
- 1, kClientDataStreamId1, true, &request_header_offset, &client_maker1));
+ 2, kClientDataStreamId1, true, &request_header_offset, &client_maker1));
mock_quic_data.AddRead(ConstructServerResponseHeadersPacket(
1, kClientDataStreamId1, &response_header_offset, &server_maker1));
mock_quic_data.AddRead(
ConstructServerDataPacket(2, kClientDataStreamId1, &server_maker1));
- mock_quic_data.AddWrite(ConstructClientAckPacket(2, 2, 1, 1, &client_maker1));
+ mock_quic_data.AddWrite(ConstructClientAckPacket(3, 2, 1, 1, &client_maker1));
QuicTestPacketMaker client_maker2(version_, 0, clock_, origin2_,
Perspective::IS_CLIENT);
@@ -3181,12 +3402,12 @@ TEST_P(QuicNetworkTransactionWithDestinationTest, PoolIfCertificateValid) {
Perspective::IS_SERVER);
mock_quic_data.AddWrite(ConstructClientRequestHeadersPacket(
- 3, kClientDataStreamId2, false, &request_header_offset, &client_maker2));
+ 4, kClientDataStreamId2, false, &request_header_offset, &client_maker2));
mock_quic_data.AddRead(ConstructServerResponseHeadersPacket(
3, kClientDataStreamId2, &response_header_offset, &server_maker2));
mock_quic_data.AddRead(
ConstructServerDataPacket(4, kClientDataStreamId2, &server_maker2));
- mock_quic_data.AddWrite(ConstructClientAckPacket(4, 4, 3, 1, &client_maker2));
+ mock_quic_data.AddWrite(ConstructClientAckPacket(5, 4, 3, 1, &client_maker2));
mock_quic_data.AddRead(ASYNC, ERR_IO_PENDING); // No more data to read
mock_quic_data.AddRead(ASYNC, 0); // EOF
@@ -3241,14 +3462,18 @@ TEST_P(QuicNetworkTransactionWithDestinationTest,
Perspective::IS_SERVER);
MockQuicData mock_quic_data1;
+ QuicStreamOffset header_stream_offset1 = 0;
+ mock_quic_data1.AddWrite(ConstructSettingsPacket(
+ 1, SETTINGS_MAX_HEADER_LIST_SIZE, kDefaultMaxUncompressedHeaderSize,
+ &header_stream_offset1, &client_maker1));
mock_quic_data1.AddWrite(ConstructClientRequestHeadersPacket(
- 1, kClientDataStreamId1, true, &client_maker1));
+ 2, kClientDataStreamId1, true, &header_stream_offset1, &client_maker1));
mock_quic_data1.AddRead(ConstructServerResponseHeadersPacket(
1, kClientDataStreamId1, &server_maker1));
mock_quic_data1.AddRead(
ConstructServerDataPacket(2, kClientDataStreamId1, &server_maker1));
mock_quic_data1.AddWrite(
- ConstructClientAckPacket(2, 2, 1, 1, &client_maker1));
+ ConstructClientAckPacket(3, 2, 1, 1, &client_maker1));
mock_quic_data1.AddRead(ASYNC, ERR_IO_PENDING); // No more data to read
mock_quic_data1.AddRead(ASYNC, 0); // EOF
@@ -3262,14 +3487,18 @@ TEST_P(QuicNetworkTransactionWithDestinationTest,
Perspective::IS_SERVER);
MockQuicData mock_quic_data2;
+ QuicStreamOffset header_stream_offset2 = 0;
+ mock_quic_data2.AddWrite(ConstructSettingsPacket(
+ 1, SETTINGS_MAX_HEADER_LIST_SIZE, kDefaultMaxUncompressedHeaderSize,
+ &header_stream_offset2, &client_maker2));
mock_quic_data2.AddWrite(ConstructClientRequestHeadersPacket(
- 1, kClientDataStreamId1, true, &client_maker2));
+ 2, kClientDataStreamId1, true, &header_stream_offset2, &client_maker2));
mock_quic_data2.AddRead(ConstructServerResponseHeadersPacket(
1, kClientDataStreamId1, &server_maker2));
mock_quic_data2.AddRead(
ConstructServerDataPacket(2, kClientDataStreamId1, &server_maker2));
mock_quic_data2.AddWrite(
- ConstructClientAckPacket(2, 2, 1, 1, &client_maker2));
+ ConstructClientAckPacket(3, 2, 1, 1, &client_maker2));
mock_quic_data2.AddRead(ASYNC, ERR_IO_PENDING); // No more data to read
mock_quic_data2.AddRead(ASYNC, 0); // EOF
diff --git a/chromium/net/quic/core/crypto/quic_server_info.cc b/chromium/net/quic/chromium/quic_server_info.cc
index fa5be4a91e3..7259dbac10b 100644
--- a/chromium/net/quic/core/crypto/quic_server_info.cc
+++ b/chromium/net/quic/chromium/quic_server_info.cc
@@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#include "net/quic/core/crypto/quic_server_info.h"
+#include "net/quic/chromium/quic_server_info.h"
#include <limits>
diff --git a/chromium/net/quic/core/crypto/quic_server_info.h b/chromium/net/quic/chromium/quic_server_info.h
index 12c807ee37f..34c6f1e876c 100644
--- a/chromium/net/quic/core/crypto/quic_server_info.h
+++ b/chromium/net/quic/chromium/quic_server_info.h
@@ -2,29 +2,26 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#ifndef NET_QUIC_CRYPTO_QUIC_SERVER_INFO_H_
-#define NET_QUIC_CRYPTO_QUIC_SERVER_INFO_H_
+#ifndef NET_QUIC_CHROMIUM_QUIC_SERVER_INFO_H_
+#define NET_QUIC_CHROMIUM_QUIC_SERVER_INFO_H_
#include <string>
#include <vector>
#include "base/macros.h"
-#include "base/memory/ref_counted.h"
#include "base/memory/weak_ptr.h"
#include "base/time/time.h"
#include "net/base/completion_callback.h"
-#include "net/base/net_export.h"
#include "net/quic/core/quic_server_id.h"
+#include "net/quic/platform/api/quic_export.h"
namespace net {
-class X509Certificate;
-
// QuicServerInfo is an interface for fetching information about a QUIC server.
// This information may be stored on disk so does not include keys or other
// sensitive information. Primarily it's intended for caching the QUIC server's
// crypto config.
-class NET_EXPORT_PRIVATE QuicServerInfo {
+class QUIC_EXPORT_PRIVATE QuicServerInfo {
public:
// Enum to track number of times data read/parse/write API calls of
// QuicServerInfo to and from disk cache is called.
@@ -163,7 +160,7 @@ class NET_EXPORT_PRIVATE QuicServerInfo {
DISALLOW_COPY_AND_ASSIGN(QuicServerInfo);
};
-class NET_EXPORT_PRIVATE QuicServerInfoFactory {
+class QUIC_EXPORT_PRIVATE QuicServerInfoFactory {
public:
QuicServerInfoFactory() {}
virtual ~QuicServerInfoFactory();
@@ -178,4 +175,4 @@ class NET_EXPORT_PRIVATE QuicServerInfoFactory {
} // namespace net
-#endif // NET_QUIC_CRYPTO_QUIC_SERVER_INFO_H_
+#endif // NET_QUIC_CHROMIUM_QUIC_SERVER_INFO_H_
diff --git a/chromium/net/quic/chromium/quic_stream_factory.cc b/chromium/net/quic/chromium/quic_stream_factory.cc
index efd22989905..48cc2a61b2a 100644
--- a/chromium/net/quic/chromium/quic_stream_factory.cc
+++ b/chromium/net/quic/chromium/quic_stream_factory.cc
@@ -25,6 +25,7 @@
#include "net/base/ip_address.h"
#include "net/base/net_errors.h"
#include "net/base/proxy_delegate.h"
+#include "net/base/trace_constants.h"
#include "net/cert/cert_verifier.h"
#include "net/cert/ct_verifier.h"
#include "net/dns/host_resolver.h"
@@ -35,20 +36,19 @@
#include "net/quic/chromium/bidirectional_stream_quic_impl.h"
#include "net/quic/chromium/crypto/channel_id_chromium.h"
#include "net/quic/chromium/crypto/proof_verifier_chromium.h"
-#include "net/quic/chromium/port_suggester.h"
+#include "net/quic/chromium/properties_based_quic_server_info.h"
#include "net/quic/chromium/quic_chromium_alarm_factory.h"
#include "net/quic/chromium/quic_chromium_connection_helper.h"
#include "net/quic/chromium/quic_chromium_packet_reader.h"
#include "net/quic/chromium/quic_chromium_packet_writer.h"
+#include "net/quic/chromium/quic_crypto_client_stream_factory.h"
+#include "net/quic/chromium/quic_server_info.h"
#include "net/quic/core/crypto/proof_verifier.h"
-#include "net/quic/core/crypto/properties_based_quic_server_info.h"
#include "net/quic/core/crypto/quic_random.h"
-#include "net/quic/core/crypto/quic_server_info.h"
#include "net/quic/core/quic_client_promised_info.h"
-#include "net/quic/core/quic_clock.h"
#include "net/quic/core/quic_connection.h"
-#include "net/quic/core/quic_crypto_client_stream_factory.h"
#include "net/quic/core/quic_flags.h"
+#include "net/quic/platform/api/quic_clock.h"
#include "net/socket/client_socket_factory.h"
#include "net/socket/next_proto.h"
#include "net/socket/socket_performance_watcher.h"
@@ -59,7 +59,6 @@
#include "url/gurl.h"
#include "url/url_constants.h"
-using std::min;
using NetworkHandle = net::NetworkChangeNotifier::NetworkHandle;
namespace net {
@@ -402,7 +401,7 @@ int QuicStreamFactory::Job::Run(const CompletionCallback& callback) {
}
int QuicStreamFactory::Job::DoLoop(int rv) {
- TRACE_EVENT0("net", "QuicStreamFactory::Job::DoLoop");
+ TRACE_EVENT0(kNetTracingCategory, "QuicStreamFactory::Job::DoLoop");
do {
IoState state = io_state_;
io_state_ = STATE_NONE;
@@ -624,7 +623,8 @@ int QuicStreamFactory::Job::DoConnectComplete(int rv) {
DCHECK(!factory_->HasActiveSession(key_.server_id()));
// There may well now be an active session for this IP. If so, use the
// existing session instead.
- AddressList address(session_->connection()->peer_address());
+ AddressList address(
+ session_->connection()->peer_address().impl().socket_address());
if (factory_->OnResolution(key_, address)) {
session_->connection()->CloseConnection(
QUIC_CONNECTION_IP_POOLED, "An active session exists for the given IP.",
@@ -718,7 +718,6 @@ QuicStreamFactory::QuicStreamFactory(
size_t max_packet_length,
const std::string& user_agent_id,
const QuicVersionVector& supported_versions,
- bool enable_port_selection,
bool always_require_handshake_confirmation,
bool disable_connection_pooling,
float load_server_info_timeout_srtt_multiplier,
@@ -747,6 +746,7 @@ QuicStreamFactory::QuicStreamFactory(
host_resolver_(host_resolver),
client_socket_factory_(client_socket_factory),
http_server_properties_(http_server_properties),
+ push_delegate_(nullptr),
proxy_delegate_(proxy_delegate),
transport_security_state_(transport_security_state),
cert_transparency_verifier_(cert_transparency_verifier),
@@ -764,7 +764,6 @@ QuicStreamFactory::QuicStreamFactory(
transport_security_state,
cert_transparency_verifier))),
supported_versions_(supported_versions),
- enable_port_selection_(enable_port_selection),
always_require_handshake_confirmation_(
always_require_handshake_confirmation),
disable_connection_pooling_(disable_connection_pooling),
@@ -796,7 +795,6 @@ QuicStreamFactory::QuicStreamFactory(
force_hol_blocking_(force_hol_blocking),
race_cert_verification_(race_cert_verification),
quic_do_not_fragment_(quic_do_not_fragment),
- port_seed_(random_generator_->RandUint64()),
check_persisted_supports_quic_(true),
has_initialized_data_(false),
num_push_streams_created_(0),
@@ -1453,8 +1451,9 @@ MigrationResult QuicStreamFactory::MigrateSessionToNewNetwork(
NetworkHandle network,
bool close_session_on_error,
const NetLogWithSource& net_log) {
- return MigrateSessionInner(session, session->connection()->peer_address(),
- network, close_session_on_error, net_log);
+ return MigrateSessionInner(
+ session, session->connection()->peer_address().impl().socket_address(),
+ network, close_session_on_error, net_log);
}
MigrationResult QuicStreamFactory::MigrateSessionInner(
@@ -1615,28 +1614,13 @@ int QuicStreamFactory::CreateSession(
need_to_evaluate_consecutive_disabled_count_ = false;
}
- TRACE_EVENT0("net", "QuicStreamFactory::CreateSession");
+ TRACE_EVENT0(kNetTracingCategory, "QuicStreamFactory::CreateSession");
IPEndPoint addr = *address_list.begin();
- bool enable_port_selection = enable_port_selection_;
- if (enable_port_selection && base::ContainsKey(gone_away_aliases_, key)) {
- // Disable port selection when the server is going away.
- // There is no point in trying to return to the same server, if
- // that server is no longer handling requests.
- enable_port_selection = false;
- gone_away_aliases_.erase(key);
- }
const QuicServerId& server_id = key.server_id();
- scoped_refptr<PortSuggester> port_suggester =
- new PortSuggester(server_id.host_port_pair(), port_seed_);
- DatagramSocket::BindType bind_type =
- enable_port_selection ? DatagramSocket::RANDOM_BIND
- : // Use our callback.
- DatagramSocket::DEFAULT_BIND; // Use OS to randomize.
-
+ DatagramSocket::BindType bind_type = DatagramSocket::DEFAULT_BIND;
std::unique_ptr<DatagramClientSocket> socket(
client_socket_factory_->CreateDatagramClientSocket(
- bind_type, base::Bind(&PortSuggester::SuggestPort, port_suggester),
- net_log.net_log(), net_log.source()));
+ bind_type, RandIntCallback(), net_log.net_log(), net_log.source()));
// Passing in kInvalidNetworkHandle binds socket to default network.
int rv = ConfigureSocket(socket.get(), addr,
@@ -1644,11 +1628,6 @@ int QuicStreamFactory::CreateSession(
if (rv != OK)
return rv;
- if (enable_port_selection)
- DCHECK_LE(1u, port_suggester->call_count());
- else
- DCHECK_EQ(0u, port_suggester->call_count());
-
if (!helper_.get()) {
helper_.reset(
new QuicChromiumConnectionHelper(clock_.get(), random_generator_));
@@ -1663,8 +1642,9 @@ int QuicStreamFactory::CreateSession(
QuicChromiumPacketWriter* writer = new QuicChromiumPacketWriter(socket.get());
QuicConnection* connection = new QuicConnection(
- connection_id, addr, helper_.get(), alarm_factory_.get(), writer,
- true /* owns_writer */, Perspective::IS_CLIENT, supported_versions_);
+ connection_id, QuicSocketAddress(QuicSocketAddressImpl(addr)),
+ helper_.get(), alarm_factory_.get(), writer, true /* owns_writer */,
+ Perspective::IS_CLIENT, supported_versions_);
connection->set_ping_timeout(ping_timeout_);
connection->SetMaxPacketLength(max_packet_length_);
@@ -1705,7 +1685,8 @@ int QuicStreamFactory::CreateSession(
server_id, yield_after_packets_, yield_after_duration_, cert_verify_flags,
config, &crypto_config_, network_connection_.GetDescription(),
dns_resolution_start_time, dns_resolution_end_time, &push_promise_index_,
- task_runner_, std::move(socket_performance_watcher), net_log.net_log());
+ push_delegate_, task_runner_, std::move(socket_performance_watcher),
+ net_log.net_log());
all_sessions_[*session] = key; // owning pointer
writer->set_delegate(*session);
@@ -1730,7 +1711,8 @@ void QuicStreamFactory::ActivateSession(const QuicSessionKey& key,
UMA_HISTOGRAM_COUNTS("Net.QuicActiveSessions", active_sessions_.size());
active_sessions_[server_id] = session;
session_aliases_[session].insert(key);
- const IPEndPoint peer_address = session->connection()->peer_address();
+ const IPEndPoint peer_address =
+ session->connection()->peer_address().impl().socket_address();
DCHECK(!base::ContainsKey(ip_aliases_[peer_address], session));
ip_aliases_[peer_address].insert(session);
DCHECK(!base::ContainsKey(session_peer_ip_, session));
diff --git a/chromium/net/quic/chromium/quic_stream_factory.h b/chromium/net/quic/chromium/quic_stream_factory.h
index afe0836afab..212cdf77964 100644
--- a/chromium/net/quic/chromium/quic_stream_factory.h
+++ b/chromium/net/quic/chromium/quic_stream_factory.h
@@ -2,8 +2,8 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#ifndef NET_QUIC_QUIC_STREAM_FACTORY_H_
-#define NET_QUIC_QUIC_STREAM_FACTORY_H_
+#ifndef NET_QUIC_CHROMIUM_QUIC_STREAM_FACTORY_H_
+#define NET_QUIC_CHROMIUM_QUIC_STREAM_FACTORY_H_
#include <stddef.h>
#include <stdint.h>
@@ -37,7 +37,7 @@
#include "net/quic/core/quic_client_push_promise_index.h"
#include "net/quic/core/quic_config.h"
#include "net/quic/core/quic_crypto_stream.h"
-#include "net/quic/core/quic_protocol.h"
+#include "net/quic/core/quic_packets.h"
#include "net/quic/core/quic_server_id.h"
#include "net/ssl/ssl_config_service.h"
@@ -199,7 +199,6 @@ class NET_EXPORT_PRIVATE QuicStreamFactory
size_t max_packet_length,
const std::string& user_agent_id,
const QuicVersionVector& supported_versions,
- bool enable_port_selection,
bool always_require_handshake_confirmation,
bool disable_connection_pooling,
float load_server_info_timeout_srtt_multiplier,
@@ -369,8 +368,6 @@ class NET_EXPORT_PRIVATE QuicStreamFactory
QuicChromiumAlarmFactory* alarm_factory() { return alarm_factory_.get(); }
- bool enable_port_selection() const { return enable_port_selection_; }
-
bool has_quic_server_info_factory() {
return quic_server_info_factory_.get() != nullptr;
}
@@ -378,6 +375,10 @@ class NET_EXPORT_PRIVATE QuicStreamFactory
void set_quic_server_info_factory(
QuicServerInfoFactory* quic_server_info_factory);
+ void set_server_push_delegate(ServerPushDelegate* push_delegate) {
+ push_delegate_ = push_delegate;
+ }
+
bool enable_connection_racing() const { return enable_connection_racing_; }
void set_enable_connection_racing(bool enable_connection_racing) {
enable_connection_racing_ = enable_connection_racing;
@@ -502,6 +503,7 @@ class NET_EXPORT_PRIVATE QuicStreamFactory
HostResolver* host_resolver_;
ClientSocketFactory* client_socket_factory_;
HttpServerProperties* http_server_properties_;
+ ServerPushDelegate* push_delegate_;
ProxyDelegate* proxy_delegate_;
TransportSecurityState* transport_security_state_;
CTVerifier* cert_transparency_verifier_;
@@ -549,11 +551,6 @@ class NET_EXPORT_PRIVATE QuicStreamFactory
QuicVersionVector supported_versions_;
- // Determine if we should consistently select a client UDP port. If false,
- // then we will just let the OS select a random client port for each new
- // connection.
- bool enable_port_selection_;
-
// Set if we always require handshake confirmation. If true, this will
// introduce at least one RTT for the handshake before the client sends data.
bool always_require_handshake_confirmation_;
@@ -629,14 +626,6 @@ class NET_EXPORT_PRIVATE QuicStreamFactory
// If set, configure QUIC sockets to not fragment packets.
bool quic_do_not_fragment_;
- // Each profile will (probably) have a unique port_seed_ value. This value
- // is used to help seed a pseudo-random number generator (PortSuggester) so
- // that we consistently (within this profile) suggest the same ephemeral
- // port when we re-connect to any given server/port. The differences between
- // profiles (probablistically) prevent two profiles from colliding in their
- // ephemeral port requests.
- uint64_t port_seed_;
-
// Local address of socket that was created in CreateSession.
IPEndPoint local_address_;
bool check_persisted_supports_quic_;
@@ -663,4 +652,4 @@ class NET_EXPORT_PRIVATE QuicStreamFactory
} // namespace net
-#endif // NET_QUIC_QUIC_STREAM_FACTORY_H_
+#endif // NET_QUIC_CHROMIUM_QUIC_STREAM_FACTORY_H_
diff --git a/chromium/net/quic/chromium/quic_stream_factory_test.cc b/chromium/net/quic/chromium/quic_stream_factory_test.cc
index 8b2d32620a0..68fb84499f9 100644
--- a/chromium/net/quic/chromium/quic_stream_factory_test.cc
+++ b/chromium/net/quic/chromium/quic_stream_factory_test.cc
@@ -25,22 +25,22 @@
#include "net/http/http_util.h"
#include "net/http/transport_security_state.h"
#include "net/quic/chromium/crypto/proof_verifier_chromium.h"
+#include "net/quic/chromium/mock_crypto_client_stream_factory.h"
#include "net/quic/chromium/mock_network_change_notifier.h"
#include "net/quic/chromium/mock_quic_data.h"
+#include "net/quic/chromium/properties_based_quic_server_info.h"
+#include "net/quic/chromium/quic_http_utils.h"
+#include "net/quic/chromium/quic_server_info.h"
+#include "net/quic/chromium/quic_test_packet_maker.h"
#include "net/quic/core/crypto/crypto_handshake.h"
-#include "net/quic/core/crypto/properties_based_quic_server_info.h"
#include "net/quic/core/crypto/quic_crypto_client_config.h"
#include "net/quic/core/crypto/quic_decrypter.h"
#include "net/quic/core/crypto/quic_encrypter.h"
-#include "net/quic/core/crypto/quic_server_info.h"
#include "net/quic/core/quic_client_promised_info.h"
-#include "net/quic/core/quic_http_utils.h"
#include "net/quic/test_tools/mock_clock.h"
-#include "net/quic/test_tools/mock_crypto_client_stream_factory.h"
#include "net/quic/test_tools/mock_random.h"
#include "net/quic/test_tools/quic_config_peer.h"
#include "net/quic/test_tools/quic_stream_factory_peer.h"
-#include "net/quic/test_tools/quic_test_packet_maker.h"
#include "net/quic/test_tools/quic_test_utils.h"
#include "net/quic/test_tools/test_task_runner.h"
#include "net/socket/next_proto.h"
@@ -56,11 +56,7 @@
#include "testing/gtest/include/gtest/gtest.h"
#include "url/gurl.h"
-using net::test::IsError;
-using net::test::IsOk;
-
using std::string;
-using std::vector;
namespace net {
@@ -115,8 +111,8 @@ struct TestParams {
bool enable_connection_racing;
};
-vector<TestParams> GetTestParams() {
- vector<TestParams> params;
+std::vector<TestParams> GetTestParams() {
+ std::vector<TestParams> params;
QuicVersionVector all_supported_versions = AllSupportedVersions();
for (const QuicVersion version : all_supported_versions) {
params.push_back(TestParams{version, false});
@@ -154,8 +150,8 @@ struct PoolingTestParams {
DestinationType destination_type;
};
-vector<PoolingTestParams> GetPoolingTestParams() {
- vector<PoolingTestParams> params;
+std::vector<PoolingTestParams> GetPoolingTestParams() {
+ std::vector<PoolingTestParams> params;
QuicVersionVector all_supported_versions = AllSupportedVersions();
for (const QuicVersion version : all_supported_versions) {
params.push_back(PoolingTestParams{version, false, SAME_AS_FIRST});
@@ -243,7 +239,6 @@ class QuicStreamFactoryTestBase {
url3_(kServer3Url),
url4_(kServer4Url),
privacy_mode_(PRIVACY_MODE_DISABLED),
- enable_port_selection_(true),
always_require_handshake_confirmation_(false),
disable_connection_pooling_(false),
load_server_info_timeout_srtt_multiplier_(0.0f),
@@ -284,10 +279,10 @@ class QuicStreamFactoryTestBase {
/*SocketPerformanceWatcherFactory*/ nullptr,
&crypto_client_stream_factory_, &random_generator_, clock_,
kDefaultMaxPacketSize, string(), SupportedVersions(version_),
- enable_port_selection_, always_require_handshake_confirmation_,
- disable_connection_pooling_, load_server_info_timeout_srtt_multiplier_,
- enable_connection_racing_, enable_non_blocking_io_, disable_disk_cache_,
- prefer_aes_, receive_buffer_size_, delay_tcp_race_,
+ always_require_handshake_confirmation_, disable_connection_pooling_,
+ load_server_info_timeout_srtt_multiplier_, enable_connection_racing_,
+ enable_non_blocking_io_, disable_disk_cache_, prefer_aes_,
+ receive_buffer_size_, delay_tcp_race_,
/*max_server_configs_stored_in_properties*/ 0,
close_sessions_on_ip_change_,
disable_quic_on_timeout_with_open_streams_,
@@ -354,6 +349,9 @@ class QuicStreamFactoryTestBase {
MockQuicData socket_data;
socket_data.AddRead(SYNCHRONOUS, ERR_IO_PENDING);
+ socket_data.AddWrite(
+ ConstructSettingsPacket(1, SETTINGS_MAX_HEADER_LIST_SIZE,
+ kDefaultMaxUncompressedHeaderSize, nullptr));
socket_data.AddSocketDataToFactory(&socket_factory_);
QuicStreamRequest request(factory_.get());
@@ -398,6 +396,13 @@ class QuicStreamFactoryTestBase {
QUIC_RST_ACKNOWLEDGEMENT);
}
+ std::unique_ptr<QuicEncryptedPacket> ConstructClientRstPacket(
+ QuicPacketNumber packet_number) {
+ QuicStreamId stream_id = kClientDataStreamId1;
+ return client_maker_.MakeRstPacket(packet_number, true, stream_id,
+ QUIC_RST_ACKNOWLEDGEMENT);
+ }
+
static ProofVerifyDetailsChromium DefaultProofVerifyDetails() {
// Load a certificate that is valid for *.example.org
scoped_refptr<X509Certificate> test_cert(
@@ -430,6 +435,22 @@ class QuicStreamFactoryTestBase {
std::move(headers), &spdy_headers_frame_len);
}
+ std::unique_ptr<QuicEncryptedPacket> ConstructGetRequestPacket(
+ QuicPacketNumber packet_number,
+ QuicStreamId stream_id,
+ bool should_include_version,
+ bool fin,
+ QuicStreamOffset* offset) {
+ SpdyHeaderBlock headers =
+ client_maker_.GetRequestHeaders("GET", "https", "/");
+ SpdyPriority priority =
+ ConvertRequestPriorityToQuicPriority(DEFAULT_PRIORITY);
+ size_t spdy_headers_frame_len;
+ return client_maker_.MakeRequestHeadersPacket(
+ packet_number, stream_id, should_include_version, fin, priority,
+ std::move(headers), &spdy_headers_frame_len, offset);
+ }
+
std::unique_ptr<QuicEncryptedPacket> ConstructOkResponsePacket(
QuicPacketNumber packet_number,
QuicStreamId stream_id,
@@ -442,6 +463,15 @@ class QuicStreamFactoryTestBase {
std::move(headers), &spdy_headers_frame_len);
}
+ std::unique_ptr<QuicReceivedPacket> ConstructSettingsPacket(
+ QuicPacketNumber packet_number,
+ SpdySettingsIds id,
+ size_t value,
+ QuicStreamOffset* offset) {
+ return client_maker_.MakeSettingsPacket(packet_number, id, value,
+ kIncludeVersion, offset);
+ }
+
// Helper method for server migration tests.
void VerifyServerMigration(QuicConfig& config, IPEndPoint expected_address) {
allow_server_migration_ = true;
@@ -461,9 +491,12 @@ class QuicStreamFactoryTestBase {
MockQuicData socket_data2;
socket_data2.AddRead(SYNCHRONOUS, ERR_IO_PENDING);
socket_data2.AddWrite(
- client_maker_.MakePingPacket(1, /*include_version=*/true));
+ ConstructSettingsPacket(1, SETTINGS_MAX_HEADER_LIST_SIZE,
+ kDefaultMaxUncompressedHeaderSize, nullptr));
+ socket_data2.AddWrite(
+ client_maker_.MakePingPacket(2, /*include_version=*/true));
socket_data2.AddWrite(client_maker_.MakeRstPacket(
- 2, true, kClientDataStreamId1, QUIC_STREAM_CANCELLED));
+ 3, true, kClientDataStreamId1, QUIC_STREAM_CANCELLED));
socket_data2.AddSocketDataToFactory(&socket_factory_);
// Create request and QuicHttpStream.
@@ -473,6 +506,11 @@ class QuicStreamFactoryTestBase {
/*cert_verify_flags=*/0, url_, "GET", net_log_,
callback_.callback()));
EXPECT_EQ(OK, callback_.WaitForResult());
+
+ // Run QuicChromiumClientSession::WriteToNewSocket()
+ // posted by QuicChromiumClientSession::MigrateToSocket().
+ base::RunLoop().RunUntilIdle();
+
std::unique_ptr<QuicHttpStream> stream = request.CreateStream();
EXPECT_TRUE(stream.get());
@@ -582,7 +620,7 @@ class QuicStreamFactoryTestBase {
string chlo_hash("test_chlo_hash");
string signature("test_signature");
string test_cert("test_cert");
- vector<string> certs;
+ std::vector<string> certs;
certs.push_back(test_cert);
state->server_config = server_config;
state->source_address_token = source_address_token;
@@ -622,7 +660,7 @@ class QuicStreamFactoryTestBase {
string chlo_hash2("test_chlo_hash2");
string signature2("test_signature2");
string test_cert2("test_cert2");
- vector<string> certs2;
+ std::vector<string> certs2;
certs2.push_back(test_cert2);
state2->server_config = server_config2;
state2->source_address_token = source_address_token2;
@@ -735,7 +773,6 @@ class QuicStreamFactoryTestBase {
TestCompletionCallback callback_;
// Variables to configure QuicStreamFactory.
- bool enable_port_selection_;
bool always_require_handshake_confirmation_;
bool disable_connection_pooling_;
double load_server_info_timeout_srtt_multiplier_;
@@ -776,6 +813,9 @@ TEST_P(QuicStreamFactoryTest, Create) {
MockQuicData socket_data;
socket_data.AddRead(SYNCHRONOUS, ERR_IO_PENDING);
+ socket_data.AddWrite(
+ ConstructSettingsPacket(1, SETTINGS_MAX_HEADER_LIST_SIZE,
+ kDefaultMaxUncompressedHeaderSize, nullptr));
socket_data.AddSocketDataToFactory(&socket_factory_);
QuicStreamRequest request(factory_.get());
@@ -864,6 +904,9 @@ TEST_P(QuicStreamFactoryTest, GoAway) {
MockQuicData socket_data;
socket_data.AddRead(SYNCHRONOUS, ERR_IO_PENDING);
+ socket_data.AddWrite(
+ ConstructSettingsPacket(1, SETTINGS_MAX_HEADER_LIST_SIZE,
+ kDefaultMaxUncompressedHeaderSize, nullptr));
socket_data.AddSocketDataToFactory(&socket_factory_);
QuicStreamRequest request(factory_.get());
@@ -893,6 +936,9 @@ TEST_P(QuicStreamFactoryTest, GoAwayForConnectionMigrationWithPortOnly) {
MockQuicData socket_data;
socket_data.AddRead(SYNCHRONOUS, ERR_IO_PENDING);
+ socket_data.AddWrite(
+ ConstructSettingsPacket(1, SETTINGS_MAX_HEADER_LIST_SIZE,
+ kDefaultMaxUncompressedHeaderSize, nullptr));
socket_data.AddSocketDataToFactory(&socket_factory_);
QuicStreamRequest request(factory_.get());
@@ -931,6 +977,9 @@ TEST_P(QuicStreamFactoryTest, Pooling) {
MockQuicData socket_data;
socket_data.AddRead(SYNCHRONOUS, ERR_IO_PENDING);
+ socket_data.AddWrite(
+ ConstructSettingsPacket(1, SETTINGS_MAX_HEADER_LIST_SIZE,
+ kDefaultMaxUncompressedHeaderSize, nullptr));
socket_data.AddSocketDataToFactory(&socket_factory_);
HostPortPair server2(kServer2HostName, kDefaultServerPort);
@@ -966,7 +1015,8 @@ TEST_P(QuicStreamFactoryTest, PoolingWithServerMigration) {
"192.168.0.1", "");
IPEndPoint alt_address = IPEndPoint(IPAddress(1, 2, 3, 4), 443);
QuicConfig config;
- config.SetAlternateServerAddressToSend(alt_address);
+ config.SetAlternateServerAddressToSend(
+ QuicSocketAddress(QuicSocketAddressImpl(alt_address)));
VerifyServerMigration(config, alt_address);
@@ -979,7 +1029,15 @@ TEST_P(QuicStreamFactoryTest, PoolingWithServerMigration) {
host_resolver_.rules()->AddIPLiteralRule(server2.host(), "192.168.0.1", "");
MockRead reads[] = {MockRead(SYNCHRONOUS, ERR_IO_PENDING, 0)};
- SequencedSocketData socket_data(reads, arraysize(reads), nullptr, 0);
+ std::unique_ptr<QuicEncryptedPacket> settings_packet(
+ client_maker_.MakeSettingsPacket(1, SETTINGS_MAX_HEADER_LIST_SIZE,
+ kDefaultMaxUncompressedHeaderSize, true,
+ nullptr));
+ MockWrite writes[] = {MockWrite(SYNCHRONOUS, settings_packet->data(),
+ settings_packet->length(), 1)};
+
+ SequencedSocketData socket_data(reads, arraysize(reads), writes,
+ arraysize(writes));
socket_factory_.AddSocketDataProvider(&socket_data);
ProofVerifyDetailsChromium verify_details = DefaultProofVerifyDetails();
@@ -1012,9 +1070,15 @@ TEST_P(QuicStreamFactoryTest, NoPoolingIfDisabled) {
MockQuicData socket_data1;
socket_data1.AddRead(SYNCHRONOUS, ERR_IO_PENDING);
+ socket_data1.AddWrite(
+ ConstructSettingsPacket(1, SETTINGS_MAX_HEADER_LIST_SIZE,
+ kDefaultMaxUncompressedHeaderSize, nullptr));
socket_data1.AddSocketDataToFactory(&socket_factory_);
MockQuicData socket_data2;
socket_data2.AddRead(SYNCHRONOUS, ERR_IO_PENDING);
+ socket_data2.AddWrite(
+ ConstructSettingsPacket(1, SETTINGS_MAX_HEADER_LIST_SIZE,
+ kDefaultMaxUncompressedHeaderSize, nullptr));
socket_data2.AddSocketDataToFactory(&socket_factory_);
HostPortPair server2(kServer2HostName, kDefaultServerPort);
@@ -1054,9 +1118,15 @@ TEST_P(QuicStreamFactoryTest, NoPoolingAfterGoAway) {
MockQuicData socket_data1;
socket_data1.AddRead(SYNCHRONOUS, ERR_IO_PENDING);
+ socket_data1.AddWrite(
+ ConstructSettingsPacket(1, SETTINGS_MAX_HEADER_LIST_SIZE,
+ kDefaultMaxUncompressedHeaderSize, nullptr));
socket_data1.AddSocketDataToFactory(&socket_factory_);
MockQuicData socket_data2;
socket_data2.AddRead(SYNCHRONOUS, ERR_IO_PENDING);
+ socket_data2.AddWrite(
+ ConstructSettingsPacket(1, SETTINGS_MAX_HEADER_LIST_SIZE,
+ kDefaultMaxUncompressedHeaderSize, nullptr));
socket_data2.AddSocketDataToFactory(&socket_factory_);
HostPortPair server2(kServer2HostName, kDefaultServerPort);
@@ -1105,6 +1175,9 @@ TEST_P(QuicStreamFactoryTest, HttpsPooling) {
MockQuicData socket_data;
socket_data.AddRead(SYNCHRONOUS, ERR_IO_PENDING);
+ socket_data.AddWrite(
+ ConstructSettingsPacket(1, SETTINGS_MAX_HEADER_LIST_SIZE,
+ kDefaultMaxUncompressedHeaderSize, nullptr));
socket_data.AddSocketDataToFactory(&socket_factory_);
HostPortPair server1(kDefaultServerHostName, 443);
@@ -1144,9 +1217,15 @@ TEST_P(QuicStreamFactoryTest, NoHttpsPoolingIfDisabled) {
MockQuicData socket_data1;
socket_data1.AddRead(SYNCHRONOUS, ERR_IO_PENDING);
+ socket_data1.AddWrite(
+ ConstructSettingsPacket(1, SETTINGS_MAX_HEADER_LIST_SIZE,
+ kDefaultMaxUncompressedHeaderSize, nullptr));
socket_data1.AddSocketDataToFactory(&socket_factory_);
MockQuicData socket_data2;
socket_data2.AddRead(SYNCHRONOUS, ERR_IO_PENDING);
+ socket_data2.AddWrite(
+ ConstructSettingsPacket(1, SETTINGS_MAX_HEADER_LIST_SIZE,
+ kDefaultMaxUncompressedHeaderSize, nullptr));
socket_data2.AddSocketDataToFactory(&socket_factory_);
HostPortPair server1(kDefaultServerHostName, 443);
@@ -1187,6 +1266,9 @@ TEST_P(QuicStreamFactoryTest, HttpsPoolingWithMatchingPins) {
Initialize();
MockQuicData socket_data;
socket_data.AddRead(SYNCHRONOUS, ERR_IO_PENDING);
+ socket_data.AddWrite(
+ ConstructSettingsPacket(1, SETTINGS_MAX_HEADER_LIST_SIZE,
+ kDefaultMaxUncompressedHeaderSize, nullptr));
socket_data.AddSocketDataToFactory(&socket_factory_);
HostPortPair server1(kDefaultServerHostName, 443);
@@ -1232,9 +1314,15 @@ TEST_P(QuicStreamFactoryTest, NoHttpsPoolingWithMatchingPinsIfDisabled) {
MockQuicData socket_data1;
socket_data1.AddRead(SYNCHRONOUS, ERR_IO_PENDING);
+ socket_data1.AddWrite(
+ ConstructSettingsPacket(1, SETTINGS_MAX_HEADER_LIST_SIZE,
+ kDefaultMaxUncompressedHeaderSize, nullptr));
socket_data1.AddSocketDataToFactory(&socket_factory_);
MockQuicData socket_data2;
socket_data2.AddRead(SYNCHRONOUS, ERR_IO_PENDING);
+ socket_data2.AddWrite(
+ ConstructSettingsPacket(1, SETTINGS_MAX_HEADER_LIST_SIZE,
+ kDefaultMaxUncompressedHeaderSize, nullptr));
socket_data2.AddSocketDataToFactory(&socket_factory_);
HostPortPair server1(kDefaultServerHostName, 443);
@@ -1282,9 +1370,15 @@ TEST_P(QuicStreamFactoryTest, NoHttpsPoolingWithDifferentPins) {
MockQuicData socket_data1;
socket_data1.AddRead(SYNCHRONOUS, ERR_IO_PENDING);
+ socket_data1.AddWrite(
+ ConstructSettingsPacket(1, SETTINGS_MAX_HEADER_LIST_SIZE,
+ kDefaultMaxUncompressedHeaderSize, nullptr));
socket_data1.AddSocketDataToFactory(&socket_factory_);
MockQuicData socket_data2;
socket_data2.AddRead(SYNCHRONOUS, ERR_IO_PENDING);
+ socket_data2.AddWrite(
+ ConstructSettingsPacket(1, SETTINGS_MAX_HEADER_LIST_SIZE,
+ kDefaultMaxUncompressedHeaderSize, nullptr));
socket_data2.AddSocketDataToFactory(&socket_factory_);
HostPortPair server1(kDefaultServerHostName, 443);
@@ -1340,9 +1434,15 @@ TEST_P(QuicStreamFactoryTest, Goaway) {
MockQuicData socket_data;
socket_data.AddRead(SYNCHRONOUS, ERR_IO_PENDING);
+ socket_data.AddWrite(
+ ConstructSettingsPacket(1, SETTINGS_MAX_HEADER_LIST_SIZE,
+ kDefaultMaxUncompressedHeaderSize, nullptr));
socket_data.AddSocketDataToFactory(&socket_factory_);
MockQuicData socket_data2;
socket_data2.AddRead(SYNCHRONOUS, ERR_IO_PENDING);
+ socket_data2.AddWrite(
+ ConstructSettingsPacket(1, SETTINGS_MAX_HEADER_LIST_SIZE,
+ kDefaultMaxUncompressedHeaderSize, nullptr));
socket_data2.AddSocketDataToFactory(&socket_factory_);
QuicStreamRequest request(factory_.get());
@@ -1396,14 +1496,17 @@ TEST_P(QuicStreamFactoryTest, MaxOpenStream) {
QuicStreamId stream_id = kClientDataStreamId1;
MockQuicData socket_data;
socket_data.AddWrite(
- client_maker_.MakeRstPacket(1, true, stream_id, QUIC_STREAM_CANCELLED));
+ ConstructSettingsPacket(1, SETTINGS_MAX_HEADER_LIST_SIZE,
+ kDefaultMaxUncompressedHeaderSize, nullptr));
+ socket_data.AddWrite(
+ client_maker_.MakeRstPacket(2, true, stream_id, QUIC_STREAM_CANCELLED));
socket_data.AddRead(
server_maker_.MakeRstPacket(1, false, stream_id, QUIC_STREAM_CANCELLED));
socket_data.AddRead(SYNCHRONOUS, ERR_IO_PENDING);
socket_data.AddSocketDataToFactory(&socket_factory_);
HttpRequestInfo request_info;
- vector<std::unique_ptr<QuicHttpStream>> streams;
+ std::vector<std::unique_ptr<QuicHttpStream>> streams;
// The MockCryptoClientStream sets max_open_streams to be
// kDefaultMaxStreamsPerConnection / 2.
for (size_t i = 0; i < kDefaultMaxStreamsPerConnection / 2; i++) {
@@ -1493,6 +1596,9 @@ TEST_P(QuicStreamFactoryTest, CancelCreate) {
Initialize();
MockQuicData socket_data;
socket_data.AddRead(SYNCHRONOUS, ERR_IO_PENDING);
+ socket_data.AddWrite(
+ ConstructSettingsPacket(1, SETTINGS_MAX_HEADER_LIST_SIZE,
+ kDefaultMaxUncompressedHeaderSize, nullptr));
socket_data.AddSocketDataToFactory(&socket_factory_);
{
QuicStreamRequest request(factory_.get());
@@ -1512,41 +1618,6 @@ TEST_P(QuicStreamFactoryTest, CancelCreate) {
EXPECT_TRUE(socket_data.AllWriteDataConsumed());
}
-TEST_P(QuicStreamFactoryTest, CreateConsistentEphemeralPort) {
- Initialize();
- ProofVerifyDetailsChromium verify_details = DefaultProofVerifyDetails();
- crypto_client_stream_factory_.AddProofVerifyDetails(&verify_details);
- crypto_client_stream_factory_.AddProofVerifyDetails(&verify_details);
- crypto_client_stream_factory_.AddProofVerifyDetails(&verify_details);
-
- // Sequentially connect to the default host, then another host, and then the
- // default host. Verify that the default host gets a consistent ephemeral
- // port, that is different from the other host's connection.
-
- string other_server_name = kServer2HostName;
- EXPECT_NE(kDefaultServerHostName, other_server_name);
- HostPortPair host_port_pair2(other_server_name, kDefaultServerPort);
-
- int original_port = GetSourcePortForNewSession(host_port_pair_);
- EXPECT_NE(original_port, GetSourcePortForNewSession(host_port_pair2));
- EXPECT_EQ(original_port, GetSourcePortForNewSession(host_port_pair_));
-}
-
-TEST_P(QuicStreamFactoryTest, GoAwayDisablesConsistentEphemeralPort) {
- Initialize();
- ProofVerifyDetailsChromium verify_details = DefaultProofVerifyDetails();
- crypto_client_stream_factory_.AddProofVerifyDetails(&verify_details);
- crypto_client_stream_factory_.AddProofVerifyDetails(&verify_details);
- crypto_client_stream_factory_.AddProofVerifyDetails(&verify_details);
-
- // Get a session to the host using the port suggester.
- int original_port = GetSourcePortForNewSessionAndGoAway(host_port_pair_);
- // Verify that the port is different after the goaway.
- EXPECT_NE(original_port, GetSourcePortForNewSession(host_port_pair_));
- // Since the previous session did not goaway we should see the original port.
- EXPECT_EQ(original_port, GetSourcePortForNewSession(host_port_pair_));
-}
-
TEST_P(QuicStreamFactoryTest, CloseAllSessions) {
Initialize();
ProofVerifyDetailsChromium verify_details = DefaultProofVerifyDetails();
@@ -1555,11 +1626,17 @@ TEST_P(QuicStreamFactoryTest, CloseAllSessions) {
MockQuicData socket_data;
socket_data.AddRead(SYNCHRONOUS, ERR_IO_PENDING);
- socket_data.AddWrite(ConstructClientRstPacket());
+ socket_data.AddWrite(
+ ConstructSettingsPacket(1, SETTINGS_MAX_HEADER_LIST_SIZE,
+ kDefaultMaxUncompressedHeaderSize, nullptr));
+ socket_data.AddWrite(ConstructClientRstPacket(2));
socket_data.AddSocketDataToFactory(&socket_factory_);
MockQuicData socket_data2;
socket_data2.AddRead(SYNCHRONOUS, ERR_IO_PENDING);
+ socket_data2.AddWrite(
+ ConstructSettingsPacket(1, SETTINGS_MAX_HEADER_LIST_SIZE,
+ kDefaultMaxUncompressedHeaderSize, nullptr));
socket_data2.AddSocketDataToFactory(&socket_factory_);
QuicStreamRequest request(factory_.get());
@@ -1607,11 +1684,17 @@ TEST_P(QuicStreamFactoryTest, OnIPAddressChanged) {
MockQuicData socket_data;
socket_data.AddRead(SYNCHRONOUS, ERR_IO_PENDING);
- socket_data.AddWrite(ConstructClientRstPacket());
+ socket_data.AddWrite(
+ ConstructSettingsPacket(1, SETTINGS_MAX_HEADER_LIST_SIZE,
+ kDefaultMaxUncompressedHeaderSize, nullptr));
+ socket_data.AddWrite(ConstructClientRstPacket(2));
socket_data.AddSocketDataToFactory(&socket_factory_);
MockQuicData socket_data2;
socket_data2.AddRead(SYNCHRONOUS, ERR_IO_PENDING);
+ socket_data2.AddWrite(
+ ConstructSettingsPacket(1, SETTINGS_MAX_HEADER_LIST_SIZE,
+ kDefaultMaxUncompressedHeaderSize, nullptr));
socket_data2.AddSocketDataToFactory(&socket_factory_);
QuicStreamRequest request(factory_.get());
@@ -1668,9 +1751,14 @@ void QuicStreamFactoryTestBase::OnNetworkMadeDefault(bool async_write_before) {
int packet_number = 1;
MockQuicData socket_data;
+ QuicStreamOffset header_stream_offset = 0;
socket_data.AddRead(SYNCHRONOUS, ERR_IO_PENDING);
- socket_data.AddWrite(ConstructGetRequestPacket(
- packet_number++, kClientDataStreamId1, true, true));
+ socket_data.AddWrite(ConstructSettingsPacket(
+ packet_number++, SETTINGS_MAX_HEADER_LIST_SIZE,
+ kDefaultMaxUncompressedHeaderSize, &header_stream_offset));
+ socket_data.AddWrite(ConstructGetRequestPacket(packet_number++,
+ kClientDataStreamId1, true,
+ true, &header_stream_offset));
if (async_write_before) {
socket_data.AddWrite(ASYNC, OK);
packet_number++;
@@ -1742,6 +1830,9 @@ void QuicStreamFactoryTestBase::OnNetworkMadeDefault(bool async_write_before) {
// new session is created.
MockQuicData socket_data2;
socket_data2.AddRead(SYNCHRONOUS, ERR_IO_PENDING);
+ socket_data2.AddWrite(
+ ConstructSettingsPacket(1, SETTINGS_MAX_HEADER_LIST_SIZE,
+ kDefaultMaxUncompressedHeaderSize, nullptr));
socket_data2.AddSocketDataToFactory(&socket_factory_);
QuicStreamRequest request2(factory_.get());
@@ -1793,9 +1884,14 @@ void QuicStreamFactoryTestBase::OnNetworkDisconnected(bool async_write_before) {
int packet_number = 1;
MockQuicData socket_data;
+ QuicStreamOffset header_stream_offset = 0;
socket_data.AddRead(SYNCHRONOUS, ERR_IO_PENDING);
- socket_data.AddWrite(ConstructGetRequestPacket(
- packet_number++, kClientDataStreamId1, true, true));
+ socket_data.AddWrite(ConstructSettingsPacket(
+ packet_number++, SETTINGS_MAX_HEADER_LIST_SIZE,
+ kDefaultMaxUncompressedHeaderSize, &header_stream_offset));
+ socket_data.AddWrite(ConstructGetRequestPacket(packet_number++,
+ kClientDataStreamId1, true,
+ true, &header_stream_offset));
if (async_write_before) {
socket_data.AddWrite(ASYNC, OK);
packet_number++;
@@ -1862,6 +1958,9 @@ void QuicStreamFactoryTestBase::OnNetworkDisconnected(bool async_write_before) {
// new session is created.
MockQuicData socket_data2;
socket_data2.AddRead(SYNCHRONOUS, ERR_IO_PENDING);
+ socket_data2.AddWrite(
+ ConstructSettingsPacket(1, SETTINGS_MAX_HEADER_LIST_SIZE,
+ kDefaultMaxUncompressedHeaderSize, nullptr));
socket_data2.AddSocketDataToFactory(&socket_factory_);
QuicStreamRequest request2(factory_.get());
@@ -1908,6 +2007,9 @@ void QuicStreamFactoryTestBase::OnNetworkDisconnectedWithNetworkList(
MockQuicData socket_data;
socket_data.AddRead(SYNCHRONOUS, ERR_IO_PENDING);
+ socket_data.AddWrite(
+ ConstructSettingsPacket(1, SETTINGS_MAX_HEADER_LIST_SIZE,
+ kDefaultMaxUncompressedHeaderSize, nullptr));
socket_data.AddSocketDataToFactory(&socket_factory_);
// Create request and QuicHttpStream.
@@ -1963,8 +2065,11 @@ TEST_P(QuicStreamFactoryTest, OnNetworkMadeDefaultNonMigratableStream) {
MockQuicData socket_data;
socket_data.AddRead(SYNCHRONOUS, ERR_IO_PENDING);
+ socket_data.AddWrite(
+ ConstructSettingsPacket(1, SETTINGS_MAX_HEADER_LIST_SIZE,
+ kDefaultMaxUncompressedHeaderSize, nullptr));
socket_data.AddWrite(client_maker_.MakeRstPacket(
- 1, true, kClientDataStreamId1, QUIC_STREAM_CANCELLED));
+ 2, true, kClientDataStreamId1, QUIC_STREAM_CANCELLED));
socket_data.AddSocketDataToFactory(&socket_factory_);
// Create request and QuicHttpStream.
@@ -2011,8 +2116,11 @@ TEST_P(QuicStreamFactoryTest, OnNetworkMadeDefaultConnectionMigrationDisabled) {
MockQuicData socket_data;
socket_data.AddRead(SYNCHRONOUS, ERR_IO_PENDING);
+ socket_data.AddWrite(
+ ConstructSettingsPacket(1, SETTINGS_MAX_HEADER_LIST_SIZE,
+ kDefaultMaxUncompressedHeaderSize, nullptr));
socket_data.AddWrite(client_maker_.MakeRstPacket(
- 1, true, kClientDataStreamId1, QUIC_STREAM_CANCELLED));
+ 2, true, kClientDataStreamId1, QUIC_STREAM_CANCELLED));
socket_data.AddSocketDataToFactory(&socket_factory_);
// Create request and QuicHttpStream.
@@ -2062,8 +2170,11 @@ TEST_P(QuicStreamFactoryTest, OnNetworkDisconnectedNonMigratableStream) {
MockQuicData socket_data;
socket_data.AddRead(SYNCHRONOUS, ERR_IO_PENDING);
+ socket_data.AddWrite(
+ ConstructSettingsPacket(1, SETTINGS_MAX_HEADER_LIST_SIZE,
+ kDefaultMaxUncompressedHeaderSize, nullptr));
socket_data.AddWrite(client_maker_.MakeRstPacket(
- 1, true, kClientDataStreamId1, QUIC_RST_ACKNOWLEDGEMENT));
+ 2, true, kClientDataStreamId1, QUIC_RST_ACKNOWLEDGEMENT));
socket_data.AddSocketDataToFactory(&socket_factory_);
// Create request and QuicHttpStream.
@@ -2109,8 +2220,11 @@ TEST_P(QuicStreamFactoryTest,
MockQuicData socket_data;
socket_data.AddRead(SYNCHRONOUS, ERR_IO_PENDING);
+ socket_data.AddWrite(
+ ConstructSettingsPacket(1, SETTINGS_MAX_HEADER_LIST_SIZE,
+ kDefaultMaxUncompressedHeaderSize, nullptr));
socket_data.AddWrite(client_maker_.MakeRstPacket(
- 1, true, kClientDataStreamId1, QUIC_RST_ACKNOWLEDGEMENT));
+ 2, true, kClientDataStreamId1, QUIC_RST_ACKNOWLEDGEMENT));
socket_data.AddSocketDataToFactory(&socket_factory_);
// Create request and QuicHttpStream.
@@ -2158,6 +2272,9 @@ TEST_P(QuicStreamFactoryTest, OnNetworkMadeDefaultNoOpenStreams) {
MockQuicData socket_data;
socket_data.AddRead(SYNCHRONOUS, ERR_IO_PENDING);
+ socket_data.AddWrite(
+ ConstructSettingsPacket(1, SETTINGS_MAX_HEADER_LIST_SIZE,
+ kDefaultMaxUncompressedHeaderSize, nullptr));
socket_data.AddSocketDataToFactory(&socket_factory_);
// Create request and QuicHttpStream.
@@ -2195,6 +2312,9 @@ TEST_P(QuicStreamFactoryTest, OnNetworkDisconnectedNoOpenStreams) {
MockQuicData socket_data;
socket_data.AddRead(SYNCHRONOUS, ERR_IO_PENDING);
+ socket_data.AddWrite(
+ ConstructSettingsPacket(1, SETTINGS_MAX_HEADER_LIST_SIZE,
+ kDefaultMaxUncompressedHeaderSize, nullptr));
socket_data.AddSocketDataToFactory(&socket_factory_);
// Create request and QuicHttpStream.
@@ -2231,9 +2351,13 @@ TEST_P(QuicStreamFactoryTest, OnNetworkChangeDisconnectedPauseBeforeConnected) {
crypto_client_stream_factory_.AddProofVerifyDetails(&verify_details);
MockQuicData socket_data;
+ QuicStreamOffset header_stream_offset = 0;
socket_data.AddRead(SYNCHRONOUS, ERR_IO_PENDING);
- socket_data.AddWrite(
- ConstructGetRequestPacket(1, kClientDataStreamId1, true, true));
+ socket_data.AddWrite(ConstructSettingsPacket(
+ 1, SETTINGS_MAX_HEADER_LIST_SIZE, kDefaultMaxUncompressedHeaderSize,
+ &header_stream_offset));
+ socket_data.AddWrite(ConstructGetRequestPacket(2, kClientDataStreamId1, true,
+ true, &header_stream_offset));
socket_data.AddSocketDataToFactory(&socket_factory_);
// Create request and QuicHttpStream.
@@ -2279,12 +2403,12 @@ TEST_P(QuicStreamFactoryTest, OnNetworkChangeDisconnectedPauseBeforeConnected) {
// The response to the earlier request is read on this new socket.
MockQuicData socket_data1;
socket_data1.AddWrite(
- client_maker_.MakePingPacket(2, /*include_version=*/true));
+ client_maker_.MakePingPacket(3, /*include_version=*/true));
socket_data1.AddRead(
ConstructOkResponsePacket(1, kClientDataStreamId1, false, false));
socket_data1.AddRead(SYNCHRONOUS, ERR_IO_PENDING);
socket_data1.AddWrite(client_maker_.MakeAckAndRstPacket(
- 3, false, kClientDataStreamId1, QUIC_STREAM_CANCELLED, 1, 1, 1, true));
+ 4, false, kClientDataStreamId1, QUIC_STREAM_CANCELLED, 1, 1, 1, true));
socket_data1.AddSocketDataToFactory(&socket_factory_);
// Add a new network and notify the stream factory of a new connected network.
@@ -2310,6 +2434,9 @@ TEST_P(QuicStreamFactoryTest, OnNetworkChangeDisconnectedPauseBeforeConnected) {
// Create a new request and verify that a new session is created.
MockQuicData socket_data2;
socket_data2.AddRead(SYNCHRONOUS, ERR_IO_PENDING);
+ socket_data2.AddWrite(
+ ConstructSettingsPacket(1, SETTINGS_MAX_HEADER_LIST_SIZE,
+ kDefaultMaxUncompressedHeaderSize, nullptr));
socket_data2.AddSocketDataToFactory(&socket_factory_);
QuicStreamRequest request2(factory_.get());
EXPECT_EQ(ERR_IO_PENDING,
@@ -2339,11 +2466,16 @@ TEST_P(QuicStreamFactoryTest,
MockQuicData socket_data1;
socket_data1.AddRead(SYNCHRONOUS, ERR_IO_PENDING);
+ socket_data1.AddWrite(
+ ConstructSettingsPacket(1, SETTINGS_MAX_HEADER_LIST_SIZE,
+ kDefaultMaxUncompressedHeaderSize, nullptr));
socket_data1.AddWrite(ASYNC, OK);
socket_data1.AddSocketDataToFactory(&socket_factory_);
MockQuicData socket_data2;
socket_data2.AddRead(SYNCHRONOUS, ERR_IO_PENDING);
-
+ socket_data2.AddWrite(
+ ConstructSettingsPacket(1, SETTINGS_MAX_HEADER_LIST_SIZE,
+ kDefaultMaxUncompressedHeaderSize, nullptr));
socket_data2.AddWrite(ASYNC, OK);
socket_data2.AddSocketDataToFactory(&socket_factory_);
@@ -2442,9 +2574,13 @@ TEST_P(QuicStreamFactoryTest, MigrateSessionEarly) {
crypto_client_stream_factory_.AddProofVerifyDetails(&verify_details);
MockQuicData socket_data;
+ QuicStreamOffset header_stream_offset = 0;
socket_data.AddRead(SYNCHRONOUS, ERR_IO_PENDING);
- socket_data.AddWrite(
- ConstructGetRequestPacket(1, kClientDataStreamId1, true, true));
+ socket_data.AddWrite(ConstructSettingsPacket(
+ 1, SETTINGS_MAX_HEADER_LIST_SIZE, kDefaultMaxUncompressedHeaderSize,
+ &header_stream_offset));
+ socket_data.AddWrite(ConstructGetRequestPacket(2, kClientDataStreamId1, true,
+ true, &header_stream_offset));
socket_data.AddSocketDataToFactory(&socket_factory_);
// Create request and QuicHttpStream.
@@ -2477,12 +2613,12 @@ TEST_P(QuicStreamFactoryTest, MigrateSessionEarly) {
MockQuicData socket_data1;
socket_data1.AddWrite(
- client_maker_.MakePingPacket(2, /*include_version=*/true));
+ client_maker_.MakePingPacket(3, /*include_version=*/true));
socket_data1.AddRead(
ConstructOkResponsePacket(1, kClientDataStreamId1, false, false));
socket_data1.AddRead(SYNCHRONOUS, ERR_IO_PENDING);
socket_data1.AddWrite(client_maker_.MakeAckAndRstPacket(
- 3, false, kClientDataStreamId1, QUIC_STREAM_CANCELLED, 1, 1, 1, true));
+ 4, false, kClientDataStreamId1, QUIC_STREAM_CANCELLED, 1, 1, 1, true));
socket_data1.AddSocketDataToFactory(&socket_factory_);
// Trigger early connection migration. This should cause a PING frame
@@ -2508,6 +2644,9 @@ TEST_P(QuicStreamFactoryTest, MigrateSessionEarly) {
// new session is created.
MockQuicData socket_data2;
socket_data2.AddRead(SYNCHRONOUS, ERR_IO_PENDING);
+ socket_data2.AddWrite(
+ ConstructSettingsPacket(1, SETTINGS_MAX_HEADER_LIST_SIZE,
+ kDefaultMaxUncompressedHeaderSize, nullptr));
socket_data2.AddSocketDataToFactory(&socket_factory_);
QuicStreamRequest request2(factory_.get());
@@ -2562,9 +2701,13 @@ TEST_P(QuicStreamFactoryTest, MigrateSessionEarlyWithAsyncWrites) {
crypto_client_stream_factory_.AddProofVerifyDetails(&verify_details);
MockQuicData socket_data;
+ QuicStreamOffset header_stream_offset = 0;
socket_data.AddRead(SYNCHRONOUS, ERR_IO_PENDING);
- socket_data.AddWrite(
- ConstructGetRequestPacket(1, kClientDataStreamId1, true, true));
+ socket_data.AddWrite(ConstructSettingsPacket(
+ 1, SETTINGS_MAX_HEADER_LIST_SIZE, kDefaultMaxUncompressedHeaderSize,
+ &header_stream_offset));
+ socket_data.AddWrite(ConstructGetRequestPacket(2, kClientDataStreamId1, true,
+ true, &header_stream_offset));
socket_data.AddSocketDataToFactory(&socket_factory_);
// Create request and QuicHttpStream.
@@ -2599,12 +2742,12 @@ TEST_P(QuicStreamFactoryTest, MigrateSessionEarlyWithAsyncWrites) {
// The response to the earlier request is read on this new socket.
MockQuicData socket_data1;
socket_data1.AddWrite(
- client_maker_.MakePingPacket(2, /*include_version=*/true));
+ client_maker_.MakePingPacket(3, /*include_version=*/true));
socket_data1.AddRead(
ConstructOkResponsePacket(1, kClientDataStreamId1, false, false));
socket_data1.AddRead(SYNCHRONOUS, ERR_IO_PENDING);
socket_data1.AddWrite(client_maker_.MakeAckAndRstPacket(
- 3, false, kClientDataStreamId1, QUIC_STREAM_CANCELLED, 1, 1, 1, true));
+ 4, false, kClientDataStreamId1, QUIC_STREAM_CANCELLED, 1, 1, 1, true));
socket_data1.AddSocketDataToFactory(&socket_factory_);
// Trigger early connection migration. This should cause a PING frame
@@ -2630,6 +2773,9 @@ TEST_P(QuicStreamFactoryTest, MigrateSessionEarlyWithAsyncWrites) {
// new session is created.
MockQuicData socket_data2;
socket_data2.AddRead(SYNCHRONOUS, ERR_IO_PENDING);
+ socket_data2.AddWrite(
+ ConstructSettingsPacket(1, SETTINGS_MAX_HEADER_LIST_SIZE,
+ kDefaultMaxUncompressedHeaderSize, nullptr));
socket_data2.AddSocketDataToFactory(&socket_factory_);
QuicStreamRequest request2(factory_.get());
@@ -2679,8 +2825,11 @@ TEST_P(QuicStreamFactoryTest, MigrateSessionEarlyNoNewNetwork) {
MockQuicData socket_data;
socket_data.AddRead(SYNCHRONOUS, ERR_IO_PENDING);
+ socket_data.AddWrite(
+ ConstructSettingsPacket(1, SETTINGS_MAX_HEADER_LIST_SIZE,
+ kDefaultMaxUncompressedHeaderSize, nullptr));
socket_data.AddWrite(client_maker_.MakeRstPacket(
- 1, true, kClientDataStreamId1, QUIC_STREAM_CANCELLED));
+ 2, true, kClientDataStreamId1, QUIC_STREAM_CANCELLED));
socket_data.AddSocketDataToFactory(&socket_factory_);
// Create request and QuicHttpStream.
@@ -2730,8 +2879,11 @@ TEST_P(QuicStreamFactoryTest, MigrateSessionEarlyNonMigratableStream) {
MockQuicData socket_data;
socket_data.AddRead(SYNCHRONOUS, ERR_IO_PENDING);
+ socket_data.AddWrite(
+ ConstructSettingsPacket(1, SETTINGS_MAX_HEADER_LIST_SIZE,
+ kDefaultMaxUncompressedHeaderSize, nullptr));
socket_data.AddWrite(client_maker_.MakeRstPacket(
- 1, true, kClientDataStreamId1, QUIC_STREAM_CANCELLED));
+ 2, true, kClientDataStreamId1, QUIC_STREAM_CANCELLED));
socket_data.AddSocketDataToFactory(&socket_factory_);
// Create request and QuicHttpStream.
@@ -2781,8 +2933,11 @@ TEST_P(QuicStreamFactoryTest, MigrateSessionEarlyConnectionMigrationDisabled) {
MockQuicData socket_data;
socket_data.AddRead(SYNCHRONOUS, ERR_IO_PENDING);
+ socket_data.AddWrite(
+ ConstructSettingsPacket(1, SETTINGS_MAX_HEADER_LIST_SIZE,
+ kDefaultMaxUncompressedHeaderSize, nullptr));
socket_data.AddWrite(client_maker_.MakeRstPacket(
- 1, true, kClientDataStreamId1, QUIC_STREAM_CANCELLED));
+ 2, true, kClientDataStreamId1, QUIC_STREAM_CANCELLED));
socket_data.AddSocketDataToFactory(&socket_factory_);
// Create request and QuicHttpStream.
@@ -2836,7 +2991,11 @@ void QuicStreamFactoryTestBase::TestMigrationOnWriteError(
crypto_client_stream_factory_.AddProofVerifyDetails(&verify_details);
MockQuicData socket_data;
+ QuicStreamOffset header_stream_offset = 0;
socket_data.AddRead(SYNCHRONOUS, ERR_IO_PENDING);
+ socket_data.AddWrite(ConstructSettingsPacket(
+ 1, SETTINGS_MAX_HEADER_LIST_SIZE, kDefaultMaxUncompressedHeaderSize,
+ &header_stream_offset));
socket_data.AddWrite(write_error_mode, ERR_ADDRESS_UNREACHABLE);
socket_data.AddSocketDataToFactory(&socket_factory_);
@@ -2866,13 +3025,13 @@ void QuicStreamFactoryTestBase::TestMigrationOnWriteError(
// migration. The request is rewritten to this new socket, and the
// response to the request is read on this new socket.
MockQuicData socket_data1;
- socket_data1.AddWrite(
- ConstructGetRequestPacket(1, kClientDataStreamId1, true, true));
+ socket_data1.AddWrite(ConstructGetRequestPacket(2, kClientDataStreamId1, true,
+ true, &header_stream_offset));
socket_data1.AddRead(
ConstructOkResponsePacket(1, kClientDataStreamId1, false, false));
socket_data1.AddRead(SYNCHRONOUS, ERR_IO_PENDING);
socket_data1.AddWrite(client_maker_.MakeAckAndRstPacket(
- 2, false, kClientDataStreamId1, QUIC_STREAM_CANCELLED, 1, 1, 1, true));
+ 3, false, kClientDataStreamId1, QUIC_STREAM_CANCELLED, 1, 1, 1, true));
socket_data1.AddSocketDataToFactory(&socket_factory_);
// Send GET request on stream. This should cause a write error, which triggers
@@ -2924,6 +3083,9 @@ void QuicStreamFactoryTestBase::TestMigrationOnWriteErrorNoNewNetwork(
MockQuicData socket_data;
socket_data.AddRead(SYNCHRONOUS, ERR_IO_PENDING);
+ socket_data.AddWrite(
+ ConstructSettingsPacket(1, SETTINGS_MAX_HEADER_LIST_SIZE,
+ kDefaultMaxUncompressedHeaderSize, nullptr));
socket_data.AddWrite(write_error_mode, ERR_ADDRESS_UNREACHABLE);
socket_data.AddSocketDataToFactory(&socket_factory_);
@@ -3012,6 +3174,9 @@ void QuicStreamFactoryTestBase::TestMigrationOnWriteErrorNonMigratableStream(
MockQuicData socket_data;
socket_data.AddRead(SYNCHRONOUS, ERR_IO_PENDING);
+ socket_data.AddWrite(
+ ConstructSettingsPacket(1, SETTINGS_MAX_HEADER_LIST_SIZE,
+ kDefaultMaxUncompressedHeaderSize, nullptr));
socket_data.AddWrite(write_error_mode, ERR_ADDRESS_UNREACHABLE);
socket_data.AddSocketDataToFactory(&socket_factory_);
@@ -3075,6 +3240,9 @@ void QuicStreamFactoryTestBase::TestMigrationOnWriteErrorMigrationDisabled(
MockQuicData socket_data;
socket_data.AddRead(SYNCHRONOUS, ERR_IO_PENDING);
+ socket_data.AddWrite(
+ ConstructSettingsPacket(1, SETTINGS_MAX_HEADER_LIST_SIZE,
+ kDefaultMaxUncompressedHeaderSize, nullptr));
socket_data.AddWrite(write_error_mode, ERR_ADDRESS_UNREACHABLE);
socket_data.AddSocketDataToFactory(&socket_factory_);
@@ -3147,6 +3315,11 @@ void QuicStreamFactoryTestBase::TestMigrationOnMultipleWriteErrors(
// The last socket is created but never used.
if (i < kMaxReadersPerQuicSession) {
socket_data[i].AddRead(SYNCHRONOUS, ERR_IO_PENDING);
+ if (i == 0) {
+ socket_data[i].AddWrite(ConstructSettingsPacket(
+ 1, SETTINGS_MAX_HEADER_LIST_SIZE, kDefaultMaxUncompressedHeaderSize,
+ nullptr));
+ }
socket_data[i].AddWrite(
(i % 2 == 0) ? first_write_error_mode : second_write_error_mode,
ERR_FAILED);
@@ -3227,7 +3400,11 @@ void QuicStreamFactoryTestBase::TestMigrationOnWriteErrorWithNotificationQueued(
crypto_client_stream_factory_.AddProofVerifyDetails(&verify_details);
MockQuicData socket_data;
+ QuicStreamOffset header_stream_offset = 0;
socket_data.AddRead(SYNCHRONOUS, ERR_IO_PENDING);
+ socket_data.AddWrite(ConstructSettingsPacket(
+ 1, SETTINGS_MAX_HEADER_LIST_SIZE, kDefaultMaxUncompressedHeaderSize,
+ &header_stream_offset));
socket_data.AddWrite(SYNCHRONOUS, ERR_ADDRESS_UNREACHABLE);
socket_data.AddSocketDataToFactory(&socket_factory_);
@@ -3257,13 +3434,13 @@ void QuicStreamFactoryTestBase::TestMigrationOnWriteErrorWithNotificationQueued(
// migration. The request is rewritten to this new socket, and the
// response to the request is read on this new socket.
MockQuicData socket_data1;
- socket_data1.AddWrite(
- ConstructGetRequestPacket(1, kClientDataStreamId1, true, true));
+ socket_data1.AddWrite(ConstructGetRequestPacket(2, kClientDataStreamId1, true,
+ true, &header_stream_offset));
socket_data1.AddRead(
ConstructOkResponsePacket(1, kClientDataStreamId1, false, false));
socket_data1.AddRead(SYNCHRONOUS, ERR_IO_PENDING);
socket_data1.AddWrite(client_maker_.MakeAckAndRstPacket(
- 2, false, kClientDataStreamId1, QUIC_STREAM_CANCELLED, 1, 1, 1, true));
+ 3, false, kClientDataStreamId1, QUIC_STREAM_CANCELLED, 1, 1, 1, true));
socket_data1.AddSocketDataToFactory(&socket_factory_);
// First queue a network change notification in the message loop.
@@ -3321,7 +3498,11 @@ void QuicStreamFactoryTestBase::TestMigrationOnNotificationWithWriteErrorQueued(
crypto_client_stream_factory_.AddProofVerifyDetails(&verify_details);
MockQuicData socket_data;
+ QuicStreamOffset header_stream_offset = 0;
socket_data.AddRead(SYNCHRONOUS, ERR_IO_PENDING);
+ socket_data.AddWrite(ConstructSettingsPacket(
+ 1, SETTINGS_MAX_HEADER_LIST_SIZE, kDefaultMaxUncompressedHeaderSize,
+ &header_stream_offset));
socket_data.AddWrite(SYNCHRONOUS, ERR_ADDRESS_UNREACHABLE);
socket_data.AddSocketDataToFactory(&socket_factory_);
@@ -3351,13 +3532,13 @@ void QuicStreamFactoryTestBase::TestMigrationOnNotificationWithWriteErrorQueued(
// migration. The request is rewritten to this new socket, and the
// response to the request is read on this new socket.
MockQuicData socket_data1;
- socket_data1.AddWrite(
- ConstructGetRequestPacket(1, kClientDataStreamId1, true, true));
+ socket_data1.AddWrite(ConstructGetRequestPacket(2, kClientDataStreamId1, true,
+ true, &header_stream_offset));
socket_data1.AddRead(
ConstructOkResponsePacket(1, kClientDataStreamId1, false, false));
socket_data1.AddRead(SYNCHRONOUS, ERR_IO_PENDING);
socket_data1.AddWrite(client_maker_.MakeAckAndRstPacket(
- 2, false, kClientDataStreamId1, QUIC_STREAM_CANCELLED, 1, 1, 1, true));
+ 3, false, kClientDataStreamId1, QUIC_STREAM_CANCELLED, 1, 1, 1, true));
socket_data1.AddSocketDataToFactory(&socket_factory_);
// Send GET request on stream. This should cause a write error,
@@ -3416,7 +3597,11 @@ void QuicStreamFactoryTestBase::TestMigrationOnWriteErrorPauseBeforeConnected(
crypto_client_stream_factory_.AddProofVerifyDetails(&verify_details);
MockQuicData socket_data;
+ QuicStreamOffset header_stream_offset = 0;
socket_data.AddRead(SYNCHRONOUS, ERR_IO_PENDING);
+ socket_data.AddWrite(ConstructSettingsPacket(
+ 1, SETTINGS_MAX_HEADER_LIST_SIZE, kDefaultMaxUncompressedHeaderSize,
+ &header_stream_offset));
socket_data.AddWrite(SYNCHRONOUS, ERR_FAILED);
socket_data.AddSocketDataToFactory(&socket_factory_);
@@ -3468,13 +3653,13 @@ void QuicStreamFactoryTestBase::TestMigrationOnWriteErrorPauseBeforeConnected(
// migration. The request is rewritten to this new socket, and the
// response to the request is read on this new socket.
MockQuicData socket_data1;
- socket_data1.AddWrite(
- ConstructGetRequestPacket(1, kClientDataStreamId1, true, true));
+ socket_data1.AddWrite(ConstructGetRequestPacket(2, kClientDataStreamId1, true,
+ true, &header_stream_offset));
socket_data1.AddRead(
ConstructOkResponsePacket(1, kClientDataStreamId1, false, false));
socket_data1.AddRead(SYNCHRONOUS, ERR_IO_PENDING);
socket_data1.AddWrite(client_maker_.MakeAckAndRstPacket(
- 2, false, kClientDataStreamId1, QUIC_STREAM_CANCELLED, 1, 1, 1, true));
+ 3, false, kClientDataStreamId1, QUIC_STREAM_CANCELLED, 1, 1, 1, true));
socket_data1.AddSocketDataToFactory(&socket_factory_);
scoped_mock_network_change_notifier_->mock_network_change_notifier()
@@ -3498,6 +3683,9 @@ void QuicStreamFactoryTestBase::TestMigrationOnWriteErrorPauseBeforeConnected(
// new session is created.
MockQuicData socket_data2;
socket_data2.AddRead(SYNCHRONOUS, ERR_IO_PENDING);
+ socket_data2.AddWrite(
+ ConstructSettingsPacket(1, SETTINGS_MAX_HEADER_LIST_SIZE,
+ kDefaultMaxUncompressedHeaderSize, nullptr));
socket_data2.AddSocketDataToFactory(&socket_factory_);
QuicStreamRequest request2(factory_.get());
@@ -3544,7 +3732,11 @@ void QuicStreamFactoryTestBase::
crypto_client_stream_factory_.AddProofVerifyDetails(&verify_details);
MockQuicData socket_data;
+ QuicStreamOffset header_stream_offset = 0;
socket_data.AddRead(SYNCHRONOUS, ERR_IO_PENDING);
+ socket_data.AddWrite(ConstructSettingsPacket(
+ 1, SETTINGS_MAX_HEADER_LIST_SIZE, kDefaultMaxUncompressedHeaderSize,
+ &header_stream_offset));
socket_data.AddWrite(SYNCHRONOUS, ERR_FAILED);
socket_data.AddSocketDataToFactory(&socket_factory_);
@@ -3592,13 +3784,13 @@ void QuicStreamFactoryTestBase::
// migration. The request is rewritten to this new socket, and the
// response to the request is read on this new socket.
MockQuicData socket_data1;
- socket_data1.AddWrite(
- ConstructGetRequestPacket(1, kClientDataStreamId1, true, true));
+ socket_data1.AddWrite(ConstructGetRequestPacket(2, kClientDataStreamId1, true,
+ true, &header_stream_offset));
socket_data1.AddRead(
ConstructOkResponsePacket(1, kClientDataStreamId1, false, false));
socket_data1.AddRead(SYNCHRONOUS, ERR_IO_PENDING);
socket_data1.AddWrite(client_maker_.MakeAckAndRstPacket(
- 2, false, kClientDataStreamId1, QUIC_STREAM_CANCELLED, 1, 1, 1, true));
+ 3, false, kClientDataStreamId1, QUIC_STREAM_CANCELLED, 1, 1, 1, true));
socket_data1.AddSocketDataToFactory(&socket_factory_);
scoped_mock_network_change_notifier_->mock_network_change_notifier()
@@ -3634,6 +3826,9 @@ void QuicStreamFactoryTestBase::
// new session is created.
MockQuicData socket_data2;
socket_data2.AddRead(SYNCHRONOUS, ERR_IO_PENDING);
+ socket_data2.AddWrite(
+ ConstructSettingsPacket(1, SETTINGS_MAX_HEADER_LIST_SIZE,
+ kDefaultMaxUncompressedHeaderSize, nullptr));
socket_data2.AddSocketDataToFactory(&socket_factory_);
QuicStreamRequest request2(factory_.get());
@@ -3692,9 +3887,13 @@ TEST_P(QuicStreamFactoryTest, MigrateSessionEarlyToBadSocket) {
crypto_client_stream_factory_.AddProofVerifyDetails(&verify_details);
MockQuicData socket_data;
+ QuicStreamOffset header_stream_offset = 0;
socket_data.AddRead(SYNCHRONOUS, ERR_IO_PENDING);
- socket_data.AddWrite(
- ConstructGetRequestPacket(1, kClientDataStreamId1, true, true));
+ socket_data.AddWrite(ConstructSettingsPacket(
+ 1, SETTINGS_MAX_HEADER_LIST_SIZE, kDefaultMaxUncompressedHeaderSize,
+ &header_stream_offset));
+ socket_data.AddWrite(ConstructGetRequestPacket(2, kClientDataStreamId1, true,
+ true, &header_stream_offset));
socket_data.AddSocketDataToFactory(&socket_factory_);
// Create request and QuicHttpStream.
@@ -3752,9 +3951,13 @@ TEST_P(QuicStreamFactoryTest, ServerMigration) {
crypto_client_stream_factory_.AddProofVerifyDetails(&verify_details);
MockQuicData socket_data1;
+ QuicStreamOffset header_stream_offset = 0;
socket_data1.AddRead(SYNCHRONOUS, ERR_IO_PENDING);
- socket_data1.AddWrite(
- ConstructGetRequestPacket(1, kClientDataStreamId1, true, true));
+ socket_data1.AddWrite(ConstructSettingsPacket(
+ 1, SETTINGS_MAX_HEADER_LIST_SIZE, kDefaultMaxUncompressedHeaderSize,
+ &header_stream_offset));
+ socket_data1.AddWrite(ConstructGetRequestPacket(2, kClientDataStreamId1, true,
+ true, &header_stream_offset));
socket_data1.AddSocketDataToFactory(&socket_factory_);
// Create request and QuicHttpStream.
@@ -3795,12 +3998,12 @@ TEST_P(QuicStreamFactoryTest, ServerMigration) {
// response to the request is read on this new socket.
MockQuicData socket_data2;
socket_data2.AddWrite(
- client_maker_.MakePingPacket(2, /*include_version=*/true));
+ client_maker_.MakePingPacket(3, /*include_version=*/true));
socket_data2.AddRead(
ConstructOkResponsePacket(1, kClientDataStreamId1, false, false));
socket_data2.AddRead(SYNCHRONOUS, ERR_IO_PENDING);
socket_data2.AddWrite(client_maker_.MakeAckAndRstPacket(
- 3, false, kClientDataStreamId1, QUIC_STREAM_CANCELLED, 1, 1, 1, true));
+ 4, false, kClientDataStreamId1, QUIC_STREAM_CANCELLED, 1, 1, 1, true));
socket_data2.AddSocketDataToFactory(&socket_factory_);
const uint8_t kTestIpAddress[] = {1, 2, 3, 4};
@@ -3838,7 +4041,8 @@ TEST_P(QuicStreamFactoryTest, ServerMigrationIPv4ToIPv4) {
// Add alternate IPv4 server address to config.
IPEndPoint alt_address = IPEndPoint(IPAddress(1, 2, 3, 4), 123);
QuicConfig config;
- config.SetAlternateServerAddressToSend(alt_address);
+ config.SetAlternateServerAddressToSend(
+ QuicSocketAddress(QuicSocketAddressImpl(alt_address)));
VerifyServerMigration(config, alt_address);
}
@@ -3850,7 +4054,8 @@ TEST_P(QuicStreamFactoryTest, ServerMigrationIPv6ToIPv6) {
IPEndPoint alt_address = IPEndPoint(
IPAddress(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16), 123);
QuicConfig config;
- config.SetAlternateServerAddressToSend(alt_address);
+ config.SetAlternateServerAddressToSend(
+ QuicSocketAddress(QuicSocketAddressImpl(alt_address)));
VerifyServerMigration(config, alt_address);
}
@@ -3861,7 +4066,8 @@ TEST_P(QuicStreamFactoryTest, ServerMigrationIPv6ToIPv4) {
// Add alternate IPv4 server address to config.
IPEndPoint alt_address = IPEndPoint(IPAddress(1, 2, 3, 4), 123);
QuicConfig config;
- config.SetAlternateServerAddressToSend(alt_address);
+ config.SetAlternateServerAddressToSend(
+ QuicSocketAddress(QuicSocketAddressImpl(alt_address)));
IPEndPoint expected_address(
ConvertIPv4ToIPv4MappedIPv6(alt_address.address()), alt_address.port());
VerifyServerMigration(config, expected_address);
@@ -3878,7 +4084,8 @@ TEST_P(QuicStreamFactoryTest, ServerMigrationIPv4ToIPv6Fails) {
IPEndPoint alt_address = IPEndPoint(
IPAddress(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16), 123);
QuicConfig config;
- config.SetAlternateServerAddressToSend(alt_address);
+ config.SetAlternateServerAddressToSend(
+ QuicSocketAddress(QuicSocketAddressImpl(alt_address)));
ProofVerifyDetailsChromium verify_details = DefaultProofVerifyDetails();
crypto_client_stream_factory_.AddProofVerifyDetails(&verify_details);
@@ -3889,8 +4096,11 @@ TEST_P(QuicStreamFactoryTest, ServerMigrationIPv4ToIPv6Fails) {
// Set up only socket data provider.
MockQuicData socket_data1;
socket_data1.AddRead(SYNCHRONOUS, ERR_IO_PENDING);
+ socket_data1.AddWrite(
+ ConstructSettingsPacket(1, SETTINGS_MAX_HEADER_LIST_SIZE,
+ kDefaultMaxUncompressedHeaderSize, nullptr));
socket_data1.AddWrite(client_maker_.MakeRstPacket(
- 1, true, kClientDataStreamId1, QUIC_STREAM_CANCELLED));
+ 2, true, kClientDataStreamId1, QUIC_STREAM_CANCELLED));
socket_data1.AddSocketDataToFactory(&socket_factory_);
// Create request and QuicHttpStream.
@@ -3939,11 +4149,17 @@ TEST_P(QuicStreamFactoryTest, OnSSLConfigChanged) {
MockQuicData socket_data;
socket_data.AddRead(SYNCHRONOUS, ERR_IO_PENDING);
- socket_data.AddWrite(ConstructClientRstPacket());
+ socket_data.AddWrite(
+ ConstructSettingsPacket(1, SETTINGS_MAX_HEADER_LIST_SIZE,
+ kDefaultMaxUncompressedHeaderSize, nullptr));
+ socket_data.AddWrite(ConstructClientRstPacket(2));
socket_data.AddSocketDataToFactory(&socket_factory_);
MockQuicData socket_data2;
socket_data2.AddRead(SYNCHRONOUS, ERR_IO_PENDING);
+ socket_data2.AddWrite(
+ ConstructSettingsPacket(1, SETTINGS_MAX_HEADER_LIST_SIZE,
+ kDefaultMaxUncompressedHeaderSize, nullptr));
socket_data2.AddSocketDataToFactory(&socket_factory_);
QuicStreamRequest request(factory_.get());
@@ -3990,11 +4206,17 @@ TEST_P(QuicStreamFactoryTest, OnCertDBChanged) {
MockQuicData socket_data;
socket_data.AddRead(SYNCHRONOUS, ERR_IO_PENDING);
- socket_data.AddWrite(ConstructClientRstPacket());
+ socket_data.AddWrite(
+ ConstructSettingsPacket(1, SETTINGS_MAX_HEADER_LIST_SIZE,
+ kDefaultMaxUncompressedHeaderSize, nullptr));
+ socket_data.AddWrite(ConstructClientRstPacket(2));
socket_data.AddSocketDataToFactory(&socket_factory_);
MockQuicData socket_data2;
socket_data2.AddRead(SYNCHRONOUS, ERR_IO_PENDING);
+ socket_data2.AddWrite(
+ ConstructSettingsPacket(1, SETTINGS_MAX_HEADER_LIST_SIZE,
+ kDefaultMaxUncompressedHeaderSize, nullptr));
socket_data2.AddSocketDataToFactory(&socket_factory_);
QuicStreamRequest request(factory_.get());
@@ -4037,7 +4259,7 @@ TEST_P(QuicStreamFactoryTest, OnCertDBChanged) {
TEST_P(QuicStreamFactoryTest, SharedCryptoConfig) {
Initialize();
- vector<string> cannoncial_suffixes;
+ std::vector<string> cannoncial_suffixes;
cannoncial_suffixes.push_back(string(".c.youtube.com"));
cannoncial_suffixes.push_back(string(".googlevideo.com"));
@@ -4072,7 +4294,7 @@ TEST_P(QuicStreamFactoryTest, SharedCryptoConfig) {
TEST_P(QuicStreamFactoryTest, CryptoConfigWhenProofIsInvalid) {
Initialize();
- vector<string> cannoncial_suffixes;
+ std::vector<string> cannoncial_suffixes;
cannoncial_suffixes.push_back(string(".c.youtube.com"));
cannoncial_suffixes.push_back(string(".googlevideo.com"));
@@ -4206,10 +4428,16 @@ TEST_P(QuicStreamFactoryTest, ReducePingTimeoutOnConnectionTimeOutOpenStreams) {
MockQuicData socket_data;
socket_data.AddRead(SYNCHRONOUS, ERR_IO_PENDING);
+ socket_data.AddWrite(
+ ConstructSettingsPacket(1, SETTINGS_MAX_HEADER_LIST_SIZE,
+ kDefaultMaxUncompressedHeaderSize, nullptr));
socket_data.AddSocketDataToFactory(&socket_factory_);
MockQuicData socket_data2;
socket_data2.AddRead(SYNCHRONOUS, ERR_IO_PENDING);
+ socket_data2.AddWrite(
+ ConstructSettingsPacket(1, SETTINGS_MAX_HEADER_LIST_SIZE,
+ kDefaultMaxUncompressedHeaderSize, nullptr));
socket_data2.AddSocketDataToFactory(&socket_factory_);
HostPortPair server2(kServer2HostName, kDefaultServerPort);
@@ -4297,6 +4525,9 @@ TEST_P(QuicStreamFactoryTest, DisableQuicWhenTimeoutsWithOpenStreams) {
MockQuicData socket_data;
socket_data.AddRead(SYNCHRONOUS, ERR_IO_PENDING);
+ socket_data.AddWrite(
+ ConstructSettingsPacket(1, SETTINGS_MAX_HEADER_LIST_SIZE,
+ kDefaultMaxUncompressedHeaderSize, nullptr));
socket_data.AddSocketDataToFactory(&socket_factory_);
crypto_client_stream_factory_.set_handshake_mode(
@@ -4357,10 +4588,16 @@ TEST_P(QuicStreamFactoryTest,
MockQuicData socket_data;
socket_data.AddRead(SYNCHRONOUS, ERR_IO_PENDING);
+ socket_data.AddWrite(
+ ConstructSettingsPacket(1, SETTINGS_MAX_HEADER_LIST_SIZE,
+ kDefaultMaxUncompressedHeaderSize, nullptr));
socket_data.AddSocketDataToFactory(&socket_factory_);
MockQuicData socket_data2;
socket_data2.AddRead(SYNCHRONOUS, ERR_IO_PENDING);
+ socket_data2.AddWrite(
+ ConstructSettingsPacket(1, SETTINGS_MAX_HEADER_LIST_SIZE,
+ kDefaultMaxUncompressedHeaderSize, nullptr));
socket_data2.AddSocketDataToFactory(&socket_factory_);
crypto_client_stream_factory_.set_handshake_mode(
@@ -4451,10 +4688,16 @@ TEST_P(QuicStreamFactoryTest,
MockQuicData socket_data;
socket_data.AddRead(SYNCHRONOUS, ERR_IO_PENDING);
+ socket_data.AddWrite(
+ ConstructSettingsPacket(1, SETTINGS_MAX_HEADER_LIST_SIZE,
+ kDefaultMaxUncompressedHeaderSize, nullptr));
socket_data.AddSocketDataToFactory(&socket_factory_);
MockQuicData socket_data2;
socket_data2.AddRead(SYNCHRONOUS, ERR_IO_PENDING);
+ socket_data2.AddWrite(
+ ConstructSettingsPacket(1, SETTINGS_MAX_HEADER_LIST_SIZE,
+ kDefaultMaxUncompressedHeaderSize, nullptr));
socket_data2.AddSocketDataToFactory(&socket_factory_);
crypto_client_stream_factory_.set_handshake_mode(
@@ -4541,6 +4784,9 @@ TEST_P(QuicStreamFactoryTest, EnableDelayTcpRace) {
QuicStreamFactoryPeer::SetDelayTcpRace(factory_.get(), false);
MockQuicData socket_data;
socket_data.AddRead(SYNCHRONOUS, ERR_IO_PENDING);
+ socket_data.AddWrite(
+ ConstructSettingsPacket(1, SETTINGS_MAX_HEADER_LIST_SIZE,
+ kDefaultMaxUncompressedHeaderSize, nullptr));
socket_data.AddSocketDataToFactory(&socket_factory_);
ServerNetworkStats stats1;
@@ -4601,6 +4847,9 @@ TEST_P(QuicStreamFactoryTest, StartCertVerifyJob) {
MockQuicData socket_data;
socket_data.AddRead(SYNCHRONOUS, ERR_IO_PENDING);
+ socket_data.AddWrite(
+ ConstructSettingsPacket(1, SETTINGS_MAX_HEADER_LIST_SIZE,
+ kDefaultMaxUncompressedHeaderSize, nullptr));
socket_data.AddSocketDataToFactory(&socket_factory_);
// Save current state of |race_cert_verification|.
@@ -4764,6 +5013,9 @@ TEST_P(QuicStreamFactoryTest, ServerPushSessionAffinity) {
MockQuicData socket_data;
socket_data.AddRead(SYNCHRONOUS, ERR_IO_PENDING);
+ socket_data.AddWrite(
+ ConstructSettingsPacket(1, SETTINGS_MAX_HEADER_LIST_SIZE,
+ kDefaultMaxUncompressedHeaderSize, nullptr));
socket_data.AddSocketDataToFactory(&socket_factory_);
QuicStreamRequest request(factory_.get());
@@ -4802,12 +5054,18 @@ TEST_P(QuicStreamFactoryTest, ServerPushPrivacyModeMismatch) {
MockQuicData socket_data1;
socket_data1.AddRead(SYNCHRONOUS, ERR_IO_PENDING);
+ socket_data1.AddWrite(
+ ConstructSettingsPacket(1, SETTINGS_MAX_HEADER_LIST_SIZE,
+ kDefaultMaxUncompressedHeaderSize, nullptr));
socket_data1.AddWrite(client_maker_.MakeRstPacket(
- 1, true, kServerDataStreamId1, QUIC_STREAM_CANCELLED));
+ 2, true, kServerDataStreamId1, QUIC_STREAM_CANCELLED));
socket_data1.AddSocketDataToFactory(&socket_factory_);
MockQuicData socket_data2;
socket_data2.AddRead(SYNCHRONOUS, ERR_IO_PENDING);
+ socket_data2.AddWrite(
+ ConstructSettingsPacket(1, SETTINGS_MAX_HEADER_LIST_SIZE,
+ kDefaultMaxUncompressedHeaderSize, nullptr));
socket_data2.AddSocketDataToFactory(&socket_factory_);
QuicStreamRequest request(factory_.get());
@@ -4867,6 +5125,9 @@ TEST_P(QuicStreamFactoryTest, PoolByOrigin) {
MockQuicData socket_data;
socket_data.AddRead(SYNCHRONOUS, ERR_IO_PENDING);
+ socket_data.AddWrite(
+ ConstructSettingsPacket(1, SETTINGS_MAX_HEADER_LIST_SIZE,
+ kDefaultMaxUncompressedHeaderSize, nullptr));
socket_data.AddSocketDataToFactory(&socket_factory_);
QuicStreamRequest request1(factory_.get());
@@ -4909,6 +5170,9 @@ TEST_P(QuicStreamFactoryTest, ForceHolBlockingEnabled) {
MockQuicData socket_data;
socket_data.AddRead(SYNCHRONOUS, ERR_IO_PENDING);
+ socket_data.AddWrite(
+ ConstructSettingsPacket(1, SETTINGS_MAX_HEADER_LIST_SIZE,
+ kDefaultMaxUncompressedHeaderSize, nullptr));
socket_data.AddSocketDataToFactory(&socket_factory_);
QuicStreamRequest request(factory_.get());
@@ -4972,7 +5236,8 @@ class QuicStreamFactoryWithDestinationTest
HostPortPair origin1_;
HostPortPair origin2_;
MockRead hanging_read_;
- vector<std::unique_ptr<SequencedSocketData>> sequenced_socket_data_vector_;
+ std::vector<std::unique_ptr<SequencedSocketData>>
+ sequenced_socket_data_vector_;
};
INSTANTIATE_TEST_CASE_P(Version,
@@ -5042,7 +5307,17 @@ TEST_P(QuicStreamFactoryWithDestinationTest, SharedCertificate) {
verify_details.cert_verify_result.is_issued_by_known_root = true;
crypto_client_stream_factory_.AddProofVerifyDetails(&verify_details);
- AddHangingSocketData();
+ MockRead reads[] = {MockRead(SYNCHRONOUS, ERR_IO_PENDING, 0)};
+ std::unique_ptr<QuicEncryptedPacket> settings_packet(
+ client_maker_.MakeSettingsPacket(1, SETTINGS_MAX_HEADER_LIST_SIZE,
+ kDefaultMaxUncompressedHeaderSize, true,
+ nullptr));
+ MockWrite writes[] = {MockWrite(SYNCHRONOUS, settings_packet->data(),
+ settings_packet->length(), 1)};
+ std::unique_ptr<SequencedSocketData> sequenced_socket_data(
+ new SequencedSocketData(reads, 1, writes, arraysize(writes)));
+ socket_factory_.AddSocketDataProvider(sequenced_socket_data.get());
+ sequenced_socket_data_vector_.push_back(std::move(sequenced_socket_data));
QuicStreamRequest request1(factory_.get());
EXPECT_EQ(ERR_IO_PENDING,
@@ -5050,6 +5325,7 @@ TEST_P(QuicStreamFactoryWithDestinationTest, SharedCertificate) {
/*cert_verify_flags=*/0, url1, "GET", net_log_,
callback_.callback()));
EXPECT_THAT(callback_.WaitForResult(), IsOk());
+
std::unique_ptr<QuicHttpStream> stream1 = request1.CreateStream();
EXPECT_TRUE(stream1.get());
EXPECT_TRUE(HasActiveSession(origin1_));
@@ -5102,8 +5378,21 @@ TEST_P(QuicStreamFactoryWithDestinationTest, DifferentPrivacyMode) {
verify_details2.cert_verify_result.is_issued_by_known_root = true;
crypto_client_stream_factory_.AddProofVerifyDetails(&verify_details2);
- AddHangingSocketData();
- AddHangingSocketData();
+ MockRead reads[] = {MockRead(SYNCHRONOUS, ERR_IO_PENDING, 0)};
+ std::unique_ptr<QuicEncryptedPacket> settings_packet(
+ client_maker_.MakeSettingsPacket(1, SETTINGS_MAX_HEADER_LIST_SIZE,
+ kDefaultMaxUncompressedHeaderSize, true,
+ nullptr));
+ MockWrite writes[] = {MockWrite(SYNCHRONOUS, settings_packet->data(),
+ settings_packet->length(), 1)};
+ std::unique_ptr<SequencedSocketData> sequenced_socket_data(
+ new SequencedSocketData(reads, 1, writes, arraysize(writes)));
+ socket_factory_.AddSocketDataProvider(sequenced_socket_data.get());
+ sequenced_socket_data_vector_.push_back(std::move(sequenced_socket_data));
+ std::unique_ptr<SequencedSocketData> sequenced_socket_data1(
+ new SequencedSocketData(reads, 1, writes, arraysize(writes)));
+ socket_factory_.AddSocketDataProvider(sequenced_socket_data1.get());
+ sequenced_socket_data_vector_.push_back(std::move(sequenced_socket_data1));
QuicStreamRequest request1(factory_.get());
EXPECT_EQ(ERR_IO_PENDING,
@@ -5175,8 +5464,21 @@ TEST_P(QuicStreamFactoryWithDestinationTest, DisjointCertificate) {
verify_details2.cert_verify_result.is_issued_by_known_root = true;
crypto_client_stream_factory_.AddProofVerifyDetails(&verify_details2);
- AddHangingSocketData();
- AddHangingSocketData();
+ MockRead reads[] = {MockRead(SYNCHRONOUS, ERR_IO_PENDING, 0)};
+ std::unique_ptr<QuicEncryptedPacket> settings_packet(
+ client_maker_.MakeSettingsPacket(1, SETTINGS_MAX_HEADER_LIST_SIZE,
+ kDefaultMaxUncompressedHeaderSize, true,
+ nullptr));
+ MockWrite writes[] = {MockWrite(SYNCHRONOUS, settings_packet->data(),
+ settings_packet->length(), 1)};
+ std::unique_ptr<SequencedSocketData> sequenced_socket_data(
+ new SequencedSocketData(reads, 1, writes, arraysize(writes)));
+ socket_factory_.AddSocketDataProvider(sequenced_socket_data.get());
+ sequenced_socket_data_vector_.push_back(std::move(sequenced_socket_data));
+ std::unique_ptr<SequencedSocketData> sequenced_socket_data1(
+ new SequencedSocketData(reads, 1, writes, arraysize(writes)));
+ socket_factory_.AddSocketDataProvider(sequenced_socket_data1.get());
+ sequenced_socket_data_vector_.push_back(std::move(sequenced_socket_data1));
QuicStreamRequest request1(factory_.get());
EXPECT_EQ(ERR_IO_PENDING,
@@ -5228,7 +5530,7 @@ TEST_P(QuicStreamFactoryTest, ClearCachedStatesInCryptoConfig) {
QuicCryptoClientConfig* crypto_config)
: server_id(host, port, privacy_mode),
state(crypto_config->LookupOrCreate(server_id)) {
- vector<string> certs(1);
+ std::vector<string> certs(1);
certs[0] = "cert";
state->SetProof(certs, "cert_sct", "chlo_hash", "signature");
state->set_source_address_token("TOKEN");
diff --git a/chromium/net/quic/test_tools/quic_test_packet_maker.cc b/chromium/net/quic/chromium/quic_test_packet_maker.cc
index f2f5d356694..43a99dbbb8a 100644
--- a/chromium/net/quic/test_tools/quic_test_packet_maker.cc
+++ b/chromium/net/quic/chromium/quic_test_packet_maker.cc
@@ -2,19 +2,17 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#include "net/quic/test_tools/quic_test_packet_maker.h"
+#include "net/quic/chromium/quic_test_packet_maker.h"
#include <list>
#include <utility>
#include "base/memory/ptr_util.h"
+#include "net/quic/chromium/quic_http_utils.h"
#include "net/quic/core/quic_framer.h"
-#include "net/quic/core/quic_http_utils.h"
#include "net/quic/core/quic_utils.h"
#include "net/quic/test_tools/quic_test_utils.h"
-using std::make_pair;
-
namespace net {
namespace test {
@@ -27,8 +25,8 @@ QuicTestPacketMaker::QuicTestPacketMaker(QuicVersion version,
connection_id_(connection_id),
clock_(clock),
host_(host),
- spdy_request_framer_(HTTP2),
- spdy_response_framer_(HTTP2),
+ spdy_request_framer_(SpdyFramer::ENABLE_COMPRESSION),
+ spdy_response_framer_(SpdyFramer::ENABLE_COMPRESSION),
perspective_(perspective) {}
QuicTestPacketMaker::~QuicTestPacketMaker() {}
@@ -46,7 +44,6 @@ std::unique_ptr<QuicReceivedPacket> QuicTestPacketMaker::MakePingPacket(
header.public_header.version_flag = include_version;
header.public_header.packet_number_length = PACKET_1BYTE_PACKET_NUMBER;
header.packet_number = num;
- header.entropy_flag = false;
QuicPingFrame ping;
return std::unique_ptr<QuicReceivedPacket>(
@@ -73,7 +70,6 @@ std::unique_ptr<QuicReceivedPacket> QuicTestPacketMaker::MakeRstPacket(
header.public_header.version_flag = include_version;
header.public_header.packet_number_length = PACKET_1BYTE_PACKET_NUMBER;
header.packet_number = num;
- header.entropy_flag = false;
QuicRstStreamFrame rst(stream_id, error_code, bytes_written);
DVLOG(1) << "Adding frame: " << QuicFrame(&rst);
@@ -96,15 +92,13 @@ std::unique_ptr<QuicReceivedPacket> QuicTestPacketMaker::MakeAckAndRstPacket(
header.public_header.version_flag = include_version;
header.public_header.packet_number_length = PACKET_1BYTE_PACKET_NUMBER;
header.packet_number = num;
- header.entropy_flag = false;
QuicAckFrame ack(MakeAckFrame(largest_received));
ack.ack_delay_time = QuicTime::Delta::Zero();
for (QuicPacketNumber i = ack_least_unacked; i <= largest_received; ++i) {
- ack.received_packet_times.push_back(make_pair(i, clock_->Now()));
+ ack.received_packet_times.push_back(std::make_pair(i, clock_->Now()));
}
- if (largest_received > 0 && version_ > QUIC_VERSION_33) {
- ack.missing = false;
+ if (largest_received > 0) {
ack.packets.Add(1, largest_received + 1);
}
QuicFrames frames;
@@ -147,15 +141,13 @@ QuicTestPacketMaker::MakeAckAndConnectionClosePacket(
header.public_header.version_flag = include_version;
header.public_header.packet_number_length = PACKET_1BYTE_PACKET_NUMBER;
header.packet_number = num;
- header.entropy_flag = false;
QuicAckFrame ack(MakeAckFrame(largest_received));
ack.ack_delay_time = ack_delay_time;
for (QuicPacketNumber i = least_unacked; i <= largest_received; ++i) {
- ack.received_packet_times.push_back(make_pair(i, clock_->Now()));
+ ack.received_packet_times.push_back(std::make_pair(i, clock_->Now()));
}
- if (largest_received > 0 && version_ > QUIC_VERSION_33) {
- ack.missing = false;
+ if (largest_received > 0) {
ack.packets.Add(1, largest_received + 1);
}
QuicFrames frames;
@@ -194,7 +186,6 @@ QuicTestPacketMaker::MakeConnectionClosePacket(QuicPacketNumber num) {
header.public_header.version_flag = false;
header.public_header.packet_number_length = PACKET_1BYTE_PACKET_NUMBER;
header.packet_number = num;
- header.entropy_flag = false;
QuicConnectionCloseFrame close;
close.error_code = QUIC_CRYPTO_VERSION_NOT_SUPPORTED;
@@ -213,7 +204,6 @@ std::unique_ptr<QuicReceivedPacket> QuicTestPacketMaker::MakeGoAwayPacket(
header.public_header.version_flag = false;
header.public_header.packet_number_length = PACKET_1BYTE_PACKET_NUMBER;
header.packet_number = num;
- header.entropy_flag = false;
QuicGoAwayFrame goaway;
goaway.error_code = error_code;
@@ -246,15 +236,13 @@ std::unique_ptr<QuicReceivedPacket> QuicTestPacketMaker::MakeAckPacket(
header.public_header.version_flag = false;
header.public_header.packet_number_length = PACKET_1BYTE_PACKET_NUMBER;
header.packet_number = packet_number;
- header.entropy_flag = false;
QuicAckFrame ack(MakeAckFrame(largest_received));
ack.ack_delay_time = QuicTime::Delta::Zero();
for (QuicPacketNumber i = ack_least_unacked; i <= largest_received; ++i) {
- ack.received_packet_times.push_back(make_pair(i, clock_->Now()));
+ ack.received_packet_times.push_back(std::make_pair(i, clock_->Now()));
}
- if (largest_received > 0 && version_ > QUIC_VERSION_33) {
- ack.missing = false;
+ if (largest_received > 0) {
ack.packets.Add(1, largest_received + 1);
}
@@ -334,10 +322,9 @@ std::unique_ptr<QuicReceivedPacket> QuicTestPacketMaker::MakeAckAndDataPacket(
QuicAckFrame ack(MakeAckFrame(largest_received));
ack.ack_delay_time = QuicTime::Delta::Zero();
for (QuicPacketNumber i = least_unacked; i <= largest_received; ++i) {
- ack.received_packet_times.push_back(make_pair(i, clock_->Now()));
+ ack.received_packet_times.push_back(std::make_pair(i, clock_->Now()));
}
- if (largest_received > 0 && version_ > QUIC_VERSION_33) {
- ack.missing = false;
+ if (largest_received > 0) {
ack.packets.Add(1, largest_received + 1);
}
QuicFrames frames;
@@ -361,31 +348,30 @@ QuicTestPacketMaker::MakeRequestHeadersAndMultipleDataFramesPacket(
bool fin,
SpdyPriority priority,
SpdyHeaderBlock headers,
+ QuicStreamOffset* header_stream_offset,
size_t* spdy_headers_frame_length,
const std::vector<std::string>& data_writes) {
InitializeHeader(packet_number, should_include_version);
SpdySerializedFrame spdy_frame;
- if (spdy_request_framer_.protocol_version() == SPDY3) {
- SpdySynStreamIR syn_stream(stream_id, std::move(headers));
- syn_stream.set_fin(fin);
- syn_stream.set_priority(priority);
- spdy_frame = spdy_request_framer_.SerializeSynStream(syn_stream);
- } else {
- SpdyHeadersIR headers_frame(stream_id, std::move(headers));
- headers_frame.set_fin(fin);
- headers_frame.set_weight(Spdy3PriorityToHttp2Weight(priority));
- headers_frame.set_has_priority(true);
- spdy_frame = spdy_request_framer_.SerializeFrame(headers_frame);
- }
+ SpdyHeadersIR headers_frame(stream_id, std::move(headers));
+ headers_frame.set_fin(fin);
+ headers_frame.set_weight(Spdy3PriorityToHttp2Weight(priority));
+ headers_frame.set_has_priority(true);
+ spdy_frame = spdy_request_framer_.SerializeFrame(headers_frame);
+
if (spdy_headers_frame_length) {
*spdy_headers_frame_length = spdy_frame.size();
}
+ QuicFrames frames;
+ QuicStreamOffset header_offset =
+ header_stream_offset == nullptr ? 0 : *header_stream_offset;
QuicStreamFrame frame(
- kHeadersStreamId, false, 0,
+ kHeadersStreamId, false, header_offset,
base::StringPiece(spdy_frame.data(), spdy_frame.size()));
-
- QuicFrames frames;
frames.push_back(QuicFrame(&frame));
+ if (header_stream_offset != nullptr) {
+ *header_stream_offset += spdy_frame.size();
+ }
QuicStreamOffset offset = 0;
// QuicFrame takes a raw pointer. Use a std::vector here so we keep
@@ -432,18 +418,12 @@ QuicTestPacketMaker::MakeRequestHeadersPacket(QuicPacketNumber packet_number,
QuicStreamOffset* offset) {
InitializeHeader(packet_number, should_include_version);
SpdySerializedFrame spdy_frame;
- if (spdy_request_framer_.protocol_version() == SPDY3) {
- SpdySynStreamIR syn_stream(stream_id, std::move(headers));
- syn_stream.set_fin(fin);
- syn_stream.set_priority(priority);
- spdy_frame = spdy_request_framer_.SerializeSynStream(syn_stream);
- } else {
- SpdyHeadersIR headers_frame(stream_id, std::move(headers));
- headers_frame.set_fin(fin);
- headers_frame.set_weight(Spdy3PriorityToHttp2Weight(priority));
- headers_frame.set_has_priority(true);
- spdy_frame = spdy_request_framer_.SerializeFrame(headers_frame);
- }
+ SpdyHeadersIR headers_frame(stream_id, std::move(headers));
+ headers_frame.set_fin(fin);
+ headers_frame.set_weight(Spdy3PriorityToHttp2Weight(priority));
+ headers_frame.set_has_priority(true);
+ spdy_frame = spdy_request_framer_.SerializeFrame(headers_frame);
+
if (spdy_headers_frame_length) {
*spdy_headers_frame_length = spdy_frame.size();
}
@@ -543,15 +523,10 @@ QuicTestPacketMaker::MakeResponseHeadersPacket(
QuicStreamOffset* offset) {
InitializeHeader(packet_number, should_include_version);
SpdySerializedFrame spdy_frame;
- if (spdy_response_framer_.protocol_version() == SPDY3) {
- SpdySynReplyIR syn_reply(stream_id, std::move(headers));
- syn_reply.set_fin(fin);
- spdy_frame = spdy_response_framer_.SerializeSynReply(syn_reply);
- } else {
- SpdyHeadersIR headers_frame(stream_id, std::move(headers));
- headers_frame.set_fin(fin);
- spdy_frame = spdy_response_framer_.SerializeFrame(headers_frame);
- }
+ SpdyHeadersIR headers_frame(stream_id, std::move(headers));
+ headers_frame.set_fin(fin);
+ spdy_frame = spdy_response_framer_.SerializeFrame(headers_frame);
+
if (spdy_headers_frame_length) {
*spdy_headers_frame_length = spdy_frame.size();
}
@@ -657,7 +632,29 @@ void QuicTestPacketMaker::InitializeHeader(QuicPacketNumber packet_number,
header_.public_header.version_flag = should_include_version;
header_.public_header.packet_number_length = PACKET_1BYTE_PACKET_NUMBER;
header_.packet_number = packet_number;
- header_.entropy_flag = false;
+}
+
+std::unique_ptr<QuicReceivedPacket> QuicTestPacketMaker::MakeSettingsPacket(
+ QuicPacketNumber packet_number,
+ SpdySettingsIds id,
+ size_t value,
+ bool should_include_version,
+ QuicStreamOffset* offset) {
+ SpdySettingsIR settings_frame;
+ settings_frame.AddSetting(id, value);
+ SpdySerializedFrame spdy_frame(
+ spdy_request_framer_.SerializeFrame(settings_frame));
+ InitializeHeader(packet_number, should_include_version);
+ if (offset != nullptr) {
+ QuicStreamFrame quic_frame(
+ kHeadersStreamId, false, *offset,
+ StringPiece(spdy_frame.data(), spdy_frame.size()));
+ *offset += spdy_frame.size();
+ return MakePacket(header_, QuicFrame(&quic_frame));
+ }
+ QuicStreamFrame quic_frame(kHeadersStreamId, false, 0,
+ StringPiece(spdy_frame.data(), spdy_frame.size()));
+ return MakePacket(header_, QuicFrame(&quic_frame));
}
} // namespace test
diff --git a/chromium/net/quic/test_tools/quic_test_packet_maker.h b/chromium/net/quic/chromium/quic_test_packet_maker.h
index 995b74841f6..2ee66b3eb4e 100644
--- a/chromium/net/quic/test_tools/quic_test_packet_maker.h
+++ b/chromium/net/quic/chromium/quic_test_packet_maker.h
@@ -4,8 +4,8 @@
//
// Provides a simple interface for QUIC tests to create a variety of packets.
-#ifndef NET_QUIC_TEST_TOOLS_QUIC_TEST_PACKET_MAKER_H_
-#define NET_QUIC_TEST_TOOLS_QUIC_TEST_PACKET_MAKER_H_
+#ifndef NET_QUIC_CHROMIUM_QUIC_TEST_PACKET_MAKER_H_
+#define NET_QUIC_CHROMIUM_QUIC_TEST_PACKET_MAKER_H_
#include <stddef.h>
@@ -15,7 +15,7 @@
#include "base/macros.h"
#include "net/base/request_priority.h"
-#include "net/quic/core/quic_protocol.h"
+#include "net/quic/core/quic_packets.h"
#include "net/quic/test_tools/mock_clock.h"
#include "net/quic/test_tools/mock_random.h"
#include "net/spdy/spdy_framer.h"
@@ -122,6 +122,7 @@ class QuicTestPacketMaker {
bool fin,
SpdyPriority priority,
SpdyHeaderBlock headers,
+ QuicStreamOffset* header_stream_offset,
size_t* spdy_headers_frame_length,
const std::vector<std::string>& data_writes);
@@ -198,6 +199,13 @@ class QuicTestPacketMaker {
SpdyHeaderBlock headers,
QuicStreamOffset* offset);
+ std::unique_ptr<QuicReceivedPacket> MakeSettingsPacket(
+ QuicPacketNumber packet_number,
+ SpdySettingsIds id,
+ size_t value,
+ bool should_include_version,
+ QuicStreamOffset* offset);
+
SpdyHeaderBlock GetRequestHeaders(const std::string& method,
const std::string& scheme,
const std::string& path);
@@ -232,4 +240,4 @@ class QuicTestPacketMaker {
} // namespace test
} // namespace net
-#endif // NET_QUIC_TEST_TOOLS_QUIC_TEST_PACKET_MAKER_H_
+#endif // NET_QUIC_CHROMIUM_QUIC_TEST_PACKET_MAKER_H_
diff --git a/chromium/net/quic/chromium/quic_utils_chromium.cc b/chromium/net/quic/chromium/quic_utils_chromium.cc
new file mode 100644
index 00000000000..7d3ba451f91
--- /dev/null
+++ b/chromium/net/quic/chromium/quic_utils_chromium.cc
@@ -0,0 +1,31 @@
+// Copyright (c) 2016 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.
+
+#include "net/quic/chromium/quic_utils_chromium.h"
+
+#include "base/containers/adapters.h"
+#include "base/strings/string_piece.h"
+#include "base/strings/string_split.h"
+
+namespace net {
+
+QuicTagVector ParseQuicConnectionOptions(
+ const std::string& connection_options) {
+ QuicTagVector options;
+ // Tokens are expected to be no more than 4 characters long, but
+ // handle overflow gracefully.
+ for (const base::StringPiece& token :
+ base::SplitStringPiece(connection_options, ",", base::TRIM_WHITESPACE,
+ base::SPLIT_WANT_ALL)) {
+ uint32_t option = 0;
+ for (char token_char : base::Reversed(token)) {
+ option <<= 8;
+ option |= static_cast<unsigned char>(token_char);
+ }
+ options.push_back(option);
+ }
+ return options;
+}
+
+} // namespace net
diff --git a/chromium/net/quic/chromium/quic_utils_chromium.h b/chromium/net/quic/chromium/quic_utils_chromium.h
index daa34dd2a1e..8735e8b93ee 100644
--- a/chromium/net/quic/chromium/quic_utils_chromium.h
+++ b/chromium/net/quic/chromium/quic_utils_chromium.h
@@ -4,10 +4,14 @@
//
// Some helpers for quic that are for chromium codebase.
-#ifndef NET_QUIC_QUIC_UTILS_CHROMIUM_H_
-#define NET_QUIC_QUIC_UTILS_CHROMIUM_H_
+#ifndef NET_QUIC_CHROMIUM_QUIC_UTILS_CHROMIUM_H_
+#define NET_QUIC_CHROMIUM_QUIC_UTILS_CHROMIUM_H_
+
+#include <string>
#include "base/logging.h"
+#include "net/base/net_export.h"
+#include "net/quic/core/quic_tag.h"
namespace net {
@@ -74,6 +78,11 @@ typename Collection::value_type::second_type* FindOrNull(
return &it->second;
}
+// Returns the list of QUIC tags represented by the comma separated
+// string in |connection_options|.
+NET_EXPORT QuicTagVector
+ParseQuicConnectionOptions(const std::string& connection_options);
+
} // namespace net
-#endif // NET_QUIC_QUIC_UTILS_CHROMIUM_H_
+#endif // NET_QUIC_CHROMIUM_QUIC_UTILS_CHROMIUM_H_
diff --git a/chromium/net/quic/chromium/quic_utils_chromium_test.cc b/chromium/net/quic/chromium/quic_utils_chromium_test.cc
index b0cdfefb0f4..31d8c05c0b3 100644
--- a/chromium/net/quic/chromium/quic_utils_chromium_test.cc
+++ b/chromium/net/quic/chromium/quic_utils_chromium_test.cc
@@ -6,23 +6,34 @@
#include <map>
+#include "net/quic/core/crypto/crypto_protocol.h"
#include "testing/gtest/include/gtest/gtest.h"
-using std::map;
-
namespace net {
namespace test {
namespace {
+TEST(QuicUtilsTest, ParseQuicConnectionOptions) {
+ QuicTagVector empty_options = ParseQuicConnectionOptions("");
+ EXPECT_TRUE(empty_options.empty());
+
+ QuicTagVector parsed_options = ParseQuicConnectionOptions("TIMER,TBBR,REJ");
+ QuicTagVector expected_options;
+ expected_options.push_back(kTIME);
+ expected_options.push_back(kTBBR);
+ expected_options.push_back(kREJ);
+ EXPECT_EQ(expected_options, parsed_options);
+}
+
TEST(QuicUtilsChromiumTest, FindOrNullTest) {
- map<int, int> m;
+ std::map<int, int> m;
m[0] = 2;
// Check FindOrNull
int* p1 = FindOrNull(m, 0);
CHECK_EQ(*p1, 2);
++(*p1);
- const map<int, int>& const_m = m;
+ const std::map<int, int>& const_m = m;
const int* p2 = FindOrNull(const_m, 0);
CHECK_EQ(*p2, 3);
CHECK(FindOrNull(m, 1) == nullptr);
@@ -41,7 +52,7 @@ TEST(QuicUtilsChromiumTest, FindOrDieTest) {
EXPECT_EQ(20, FindOrDie(m, 10));
// Make sure we can lookup values in a const map.
- const map<int, int>& const_m = m;
+ const std::map<int, int>& const_m = m;
EXPECT_EQ(20, FindOrDie(const_m, 10));
}
diff --git a/chromium/net/quic/core/congestion_control/bandwidth_sampler.cc b/chromium/net/quic/core/congestion_control/bandwidth_sampler.cc
index eb7888e0895..6f150044dec 100644
--- a/chromium/net/quic/core/congestion_control/bandwidth_sampler.cc
+++ b/chromium/net/quic/core/congestion_control/bandwidth_sampler.cc
@@ -6,7 +6,7 @@
#include <algorithm>
-#include "net/quic/core/quic_bug_tracker.h"
+#include "net/quic/platform/api/quic_bug_tracker.h"
namespace net {
BandwidthSampler::BandwidthSampler()
diff --git a/chromium/net/quic/core/congestion_control/bandwidth_sampler.h b/chromium/net/quic/core/congestion_control/bandwidth_sampler.h
index fe59a606f1c..7283506ae2a 100644
--- a/chromium/net/quic/core/congestion_control/bandwidth_sampler.h
+++ b/chromium/net/quic/core/congestion_control/bandwidth_sampler.h
@@ -7,8 +7,9 @@
#include "net/base/linked_hash_map.h"
#include "net/quic/core/quic_bandwidth.h"
-#include "net/quic/core/quic_protocol.h"
+#include "net/quic/core/quic_packets.h"
#include "net/quic/core/quic_time.h"
+#include "net/quic/platform/api/quic_export.h"
namespace net {
@@ -16,7 +17,7 @@ namespace test {
class BandwidthSamplerPeer;
} // namespace test
-struct NET_EXPORT_PRIVATE BandwidthSample {
+struct QUIC_EXPORT_PRIVATE BandwidthSample {
// The bandwidth at that particular sample. Zero if no valid bandwidth sample
// is available.
QuicBandwidth bandwidth;
@@ -115,7 +116,7 @@ struct NET_EXPORT_PRIVATE BandwidthSample {
// up until an ack for a packet that was sent after OnAppLimited() was called.
// Note that while the scenario above is not the only scenario when the
// connection is app-limited, the approach works in other cases too.
-class NET_EXPORT_PRIVATE BandwidthSampler {
+class QUIC_EXPORT_PRIVATE BandwidthSampler {
public:
BandwidthSampler();
~BandwidthSampler();
diff --git a/chromium/net/quic/core/congestion_control/bbr_sender.cc b/chromium/net/quic/core/congestion_control/bbr_sender.cc
index d8ab1cef8e7..33fdfe216f3 100644
--- a/chromium/net/quic/core/congestion_control/bbr_sender.cc
+++ b/chromium/net/quic/core/congestion_control/bbr_sender.cc
@@ -7,9 +7,11 @@
#include <algorithm>
#include <sstream>
+#include "base/stl_util.h"
#include "net/quic/core/congestion_control/rtt_stats.h"
-#include "net/quic/core/quic_bug_tracker.h"
#include "net/quic/core/quic_flags.h"
+#include "net/quic/platform/api/quic_bug_tracker.h"
+#include "net/quic/platform/api/quic_logging.h"
namespace net {
@@ -63,14 +65,12 @@ BbrSender::DebugState::DebugState(const BbrSender& sender)
BbrSender::DebugState::DebugState(const DebugState& state) = default;
-BbrSender::BbrSender(const QuicClock* clock,
- const RttStats* rtt_stats,
+BbrSender::BbrSender(const RttStats* rtt_stats,
const QuicUnackedPacketMap* unacked_packets,
QuicPacketCount initial_tcp_congestion_window,
QuicPacketCount max_tcp_congestion_window,
QuicRandom* random)
- : clock_(clock),
- rtt_stats_(rtt_stats),
+ : rtt_stats_(rtt_stats),
unacked_packets_(unacked_packets),
random_(random),
mode_(STARTUP),
@@ -98,7 +98,10 @@ BbrSender::BbrSender(const QuicClock* clock,
probe_rtt_round_passed_(false),
last_sample_is_app_limited_(false),
recovery_state_(NOT_IN_RECOVERY),
- end_recovery_at_(0) {
+ end_recovery_at_(0),
+ recovery_window_(max_congestion_window_),
+ enforce_startup_pacing_rate_increase_(
+ FLAGS_quic_reloadable_flag_quic_bbr_faster_startup) {
EnterStartupMode();
}
@@ -300,9 +303,9 @@ bool BbrSender::UpdateBandwidthAndMinRtt(
!min_rtt_.IsZero() && (now > (min_rtt_timestamp_ + kMinRttExpiry));
if (min_rtt_expired || sample_min_rtt < min_rtt_ || min_rtt_.IsZero()) {
- DVLOG(2) << "Min RTT updated, old value: " << min_rtt_
- << ", new value: " << sample_min_rtt
- << ", current time: " << now.ToDebuggingValue();
+ QUIC_DVLOG(2) << "Min RTT updated, old value: " << min_rtt_
+ << ", new value: " << sample_min_rtt
+ << ", current time: " << now.ToDebuggingValue();
min_rtt_ = sample_min_rtt;
min_rtt_timestamp_ = now;
@@ -453,7 +456,24 @@ void BbrSender::CalculatePacingRate() {
return;
}
- pacing_rate_ = pacing_gain_ * BandwidthEstimate();
+ QuicBandwidth target_rate = pacing_gain_ * BandwidthEstimate();
+
+ // Ensure that the pacing rate does not drop too low during the startup.
+ if (!is_at_full_bandwidth_ && enforce_startup_pacing_rate_increase_) {
+ // Pace at the rate of initial_window / RTT as soon as RTT measurements are
+ // available.
+ if (pacing_rate_.IsZero() && !rtt_stats_->min_rtt().IsZero()) {
+ pacing_rate_ = QuicBandwidth::FromBytesAndTimeDelta(
+ initial_congestion_window_, rtt_stats_->min_rtt());
+ return;
+ }
+
+ // Do not decrease the pacing rate during the startup.
+ pacing_rate_ = std::max(pacing_rate_, target_rate);
+ return;
+ }
+
+ pacing_rate_ = target_rate;
}
void BbrSender::CalculateCongestionWindow(QuicByteCount bytes_acked) {
@@ -508,8 +528,8 @@ void BbrSender::OnApplicationLimited(QuicByteCount bytes_in_flight) {
}
sampler_.OnAppLimited();
- DVLOG(2) << "Becoming application limited. Last sent packet: "
- << last_sent_packet_ << ", CWND: " << GetCongestionWindow();
+ QUIC_DVLOG(2) << "Becoming application limited. Last sent packet: "
+ << last_sent_packet_ << ", CWND: " << GetCongestionWindow();
}
BbrSender::DebugState BbrSender::ExportDebugState() const {
diff --git a/chromium/net/quic/core/congestion_control/bbr_sender.h b/chromium/net/quic/core/congestion_control/bbr_sender.h
index e146eece838..04b71a2790a 100644
--- a/chromium/net/quic/core/congestion_control/bbr_sender.h
+++ b/chromium/net/quic/core/congestion_control/bbr_sender.h
@@ -10,14 +10,16 @@
#include <cstdint>
#include <ostream>
+#include "base/macros.h"
#include "net/quic/core/congestion_control/bandwidth_sampler.h"
#include "net/quic/core/congestion_control/send_algorithm_interface.h"
#include "net/quic/core/congestion_control/windowed_filter.h"
#include "net/quic/core/crypto/quic_random.h"
#include "net/quic/core/quic_bandwidth.h"
-#include "net/quic/core/quic_protocol.h"
+#include "net/quic/core/quic_packets.h"
#include "net/quic/core/quic_time.h"
#include "net/quic/core/quic_unacked_packet_map.h"
+#include "net/quic/platform/api/quic_export.h"
namespace net {
@@ -36,7 +38,7 @@ typedef uint64_t QuicRoundTripCount;
// TODO(vasilvv): implement traffic policer (long-term sampling) mode.
//
// TODO(vasilvv): implement packet conservation.
-class NET_EXPORT_PRIVATE BbrSender : public SendAlgorithmInterface {
+class QUIC_EXPORT_PRIVATE BbrSender : public SendAlgorithmInterface {
public:
enum Mode {
// Startup phase of the connection.
@@ -87,8 +89,7 @@ class NET_EXPORT_PRIVATE BbrSender : public SendAlgorithmInterface {
bool last_sample_is_app_limited;
};
- BbrSender(const QuicClock* clock,
- const RttStats* rtt_stats,
+ BbrSender(const RttStats* rtt_stats,
const QuicUnackedPacketMap* unacked_packets,
QuicPacketCount initial_tcp_congestion_window,
QuicPacketCount max_tcp_congestion_window,
@@ -188,7 +189,6 @@ class NET_EXPORT_PRIVATE BbrSender : public SendAlgorithmInterface {
// recovery.
void CalculateRecoveryWindow(QuicByteCount bytes_acked);
- const QuicClock* clock_;
const RttStats* rtt_stats_;
const QuicUnackedPacketMap* unacked_packets_;
QuicRandom* random_;
@@ -270,13 +270,18 @@ class NET_EXPORT_PRIVATE BbrSender : public SendAlgorithmInterface {
// A window used to limit the number of bytes in flight during loss recovery.
QuicByteCount recovery_window_;
+ // Indicates whether to always only increase the pacing rate during startup.
+ // Latches |FLAGS_quic_reloadable_flag_quic_bbr_faster_startup|.
+ bool enforce_startup_pacing_rate_increase_;
+
DISALLOW_COPY_AND_ASSIGN(BbrSender);
};
-NET_EXPORT_PRIVATE std::ostream& operator<<(std::ostream& os,
- const BbrSender::Mode& mode);
-NET_EXPORT_PRIVATE std::ostream& operator<<(std::ostream& os,
- const BbrSender::DebugState& state);
+QUIC_EXPORT_PRIVATE std::ostream& operator<<(std::ostream& os,
+ const BbrSender::Mode& mode);
+QUIC_EXPORT_PRIVATE std::ostream& operator<<(
+ std::ostream& os,
+ const BbrSender::DebugState& state);
} // namespace net
diff --git a/chromium/net/quic/core/congestion_control/bbr_sender_test.cc b/chromium/net/quic/core/congestion_control/bbr_sender_test.cc
index c50c8cd8be0..c903c751671 100644
--- a/chromium/net/quic/core/congestion_control/bbr_sender_test.cc
+++ b/chromium/net/quic/core/congestion_control/bbr_sender_test.cc
@@ -8,10 +8,10 @@
#include <map>
#include <memory>
-#include "base/logging.h"
#include "net/quic/core/congestion_control/rtt_stats.h"
-#include "net/quic/core/quic_protocol.h"
+#include "net/quic/core/quic_packets.h"
#include "net/quic/core/quic_utils.h"
+#include "net/quic/platform/api/quic_logging.h"
#include "net/quic/test_tools/mock_clock.h"
#include "net/quic/test_tools/quic_config_peer.h"
#include "net/quic/test_tools/quic_connection_peer.h"
@@ -78,22 +78,23 @@ class BbrSenderTest : public ::testing::Test {
"BBR sender",
Perspective::IS_SERVER,
42) {
+ FLAGS_quic_reloadable_flag_quic_bbr_faster_startup = true;
+
rtt_stats_ = bbr_sender_.connection()->sent_packet_manager().GetRttStats();
- sender_ = new BbrSender(simulator_.GetClock(), rtt_stats_,
- QuicSentPacketManagerPeer::GetUnackedPacketMap(
- QuicConnectionPeer::GetSentPacketManager(
- bbr_sender_.connection(), kDefaultPathId)),
- kInitialCongestionWindowPackets,
- kDefaultMaxCongestionWindowPackets, &random_);
- QuicConnectionPeer::SetSendAlgorithm(bbr_sender_.connection(),
- kDefaultPathId, sender_);
+ sender_ = new BbrSender(
+ rtt_stats_,
+ QuicSentPacketManagerPeer::GetUnackedPacketMap(
+ QuicConnectionPeer::GetSentPacketManager(bbr_sender_.connection())),
+ kInitialCongestionWindowPackets, kDefaultMaxCongestionWindowPackets,
+ &random_);
+ QuicConnectionPeer::SetSendAlgorithm(bbr_sender_.connection(), sender_);
clock_ = simulator_.GetClock();
simulator_.set_random_generator(&random_);
uint64_t seed = QuicRandom::GetInstance()->RandUint64();
random_.set_seed(seed);
- LOG(INFO) << "BbrSenderTest simulator set up. Seed: " << seed;
+ QUIC_LOG(INFO) << "BbrSenderTest simulator set up. Seed: " << seed;
}
simulator::Simulator simulator_;
@@ -109,6 +110,7 @@ class BbrSenderTest : public ::testing::Test {
const QuicClock* clock_;
const RttStats* rtt_stats_;
BbrSender* sender_;
+ QuicFlagSaver flags_;
// Creates a default setup, which is a network with a bottleneck between the
// receiver and the switch. The switch has the buffers four times larger than
@@ -143,7 +145,7 @@ class BbrSenderTest : public ::testing::Test {
EXPECT_TRUE(simulator_result)
<< "Simple transfer failed. Bytes remaining: "
<< bbr_sender_.bytes_to_transfer();
- LOG(INFO) << "Simple transfer state: " << sender_->ExportDebugState();
+ QUIC_LOG(INFO) << "Simple transfer state: " << sender_->ExportDebugState();
}
// Drive the simulator by sending enough data to enter PROBE_BW.
@@ -233,7 +235,7 @@ TEST_F(BbrSenderTest, PacketLossOnSmallBufferStartup) {
float loss_rate =
static_cast<float>(bbr_sender_.connection()->GetStats().packets_lost) /
bbr_sender_.connection()->GetStats().packets_sent;
- EXPECT_LE(loss_rate, 0.20);
+ EXPECT_LE(loss_rate, 0.27);
}
// Ensures the code transitions loss recovery states correctly (NOT_IN_RECOVERY
@@ -430,5 +432,36 @@ TEST_F(BbrSenderTest, InFlightAwareGainCycling) {
EXPECT_EQ(2, sender_->ExportDebugState().gain_cycle_index);
}
+// Ensure that the pacing rate does not drop at startup.
+TEST_F(BbrSenderTest, NoBandwidthDropOnStartup) {
+ CreateDefaultSetup();
+
+ const QuicTime::Delta timeout = QuicTime::Delta::FromSeconds(5);
+ bool simulator_result;
+
+ QuicBandwidth initial_rate = QuicBandwidth::FromBytesAndTimeDelta(
+ kInitialCongestionWindowPackets * kDefaultTCPMSS,
+ QuicTime::Delta::FromMicroseconds(rtt_stats_->initial_rtt_us()));
+ EXPECT_GE(sender_->PacingRate(0), initial_rate);
+
+ // Send a packet.
+ bbr_sender_.AddBytesToTransfer(1000);
+ simulator_result = simulator_.RunUntilOrTimeout(
+ [this]() { return receiver_.bytes_received() == 1000; }, timeout);
+ ASSERT_TRUE(simulator_result);
+ EXPECT_GE(sender_->PacingRate(0), initial_rate);
+
+ // Wait for a while.
+ simulator_.RunFor(QuicTime::Delta::FromSeconds(2));
+ EXPECT_GE(sender_->PacingRate(0), initial_rate);
+
+ // Send another packet.
+ bbr_sender_.AddBytesToTransfer(1000);
+ simulator_result = simulator_.RunUntilOrTimeout(
+ [this]() { return receiver_.bytes_received() == 2000; }, timeout);
+ ASSERT_TRUE(simulator_result);
+ EXPECT_GE(sender_->PacingRate(0), initial_rate);
+}
+
} // namespace test
} // namespace net
diff --git a/chromium/net/quic/core/congestion_control/cubic.cc b/chromium/net/quic/core/congestion_control/cubic.cc
index 89a347e7e8e..d3e04aa53e4 100644
--- a/chromium/net/quic/core/congestion_control/cubic.cc
+++ b/chromium/net/quic/core/congestion_control/cubic.cc
@@ -4,17 +4,13 @@
#include "net/quic/core/congestion_control/cubic.h"
-#include <stdint.h>
#include <algorithm>
#include <cmath>
+#include <cstdint>
-#include "base/logging.h"
#include "net/quic/core/quic_flags.h"
-#include "net/quic/core/quic_protocol.h"
-#include "net/quic/core/quic_time.h"
-
-using std::max;
-using std::min;
+#include "net/quic/core/quic_packets.h"
+#include "net/quic/platform/api/quic_logging.h"
namespace net {
@@ -44,7 +40,9 @@ Cubic::Cubic(const QuicClock* clock)
num_connections_(kDefaultNumConnections),
epoch_(QuicTime::Zero()),
app_limited_start_time_(QuicTime::Zero()),
- last_update_time_(QuicTime::Zero()) {
+ last_update_time_(QuicTime::Zero()),
+ fix_convex_mode_(false),
+ fix_beta_last_max_(false) {
Reset();
}
@@ -68,6 +66,16 @@ float Cubic::Beta() const {
return (num_connections_ - 1 + kBeta) / num_connections_;
}
+float Cubic::BetaLastMax() const {
+ // BetaLastMax is the additional backoff factor after loss for our
+ // N-connection emulation, which emulates the additional backoff of
+ // an ensemble of N TCP-Reno connections on a single loss event. The
+ // effective multiplier is computed as:
+ return fix_beta_last_max_
+ ? (num_connections_ - 1 + kBetaLastMax) / num_connections_
+ : kBetaLastMax;
+}
+
void Cubic::Reset() {
epoch_ = QuicTime::Zero(); // Reset time.
app_limited_start_time_ = QuicTime::Zero();
@@ -88,13 +96,21 @@ void Cubic::OnApplicationLimited() {
epoch_ = QuicTime::Zero();
}
+void Cubic::SetFixConvexMode(bool fix_convex_mode) {
+ fix_convex_mode_ = fix_convex_mode;
+}
+
+void Cubic::SetFixBetaLastMax(bool fix_beta_last_max) {
+ fix_beta_last_max_ = fix_beta_last_max;
+}
+
QuicPacketCount Cubic::CongestionWindowAfterPacketLoss(
QuicPacketCount current_congestion_window) {
if (current_congestion_window < last_max_congestion_window_) {
// We never reached the old max, so assume we are competing with another
// flow. Use our extra back off factor to allow the other flow to go up.
last_max_congestion_window_ =
- static_cast<int>(kBetaLastMax * current_congestion_window);
+ static_cast<int>(BetaLastMax() * current_congestion_window);
} else {
last_max_congestion_window_ = current_congestion_window;
}
@@ -104,16 +120,19 @@ QuicPacketCount Cubic::CongestionWindowAfterPacketLoss(
QuicPacketCount Cubic::CongestionWindowAfterAck(
QuicPacketCount current_congestion_window,
- QuicTime::Delta delay_min) {
+ QuicTime::Delta delay_min,
+ QuicTime event_time) {
acked_packets_count_ += 1; // Packets acked.
epoch_packets_count_ += 1;
- QuicTime current_time = clock_->ApproximateNow();
+ QuicTime current_time = FLAGS_quic_reloadable_flag_quic_use_event_time
+ ? event_time
+ : clock_->ApproximateNow();
// Cubic is "independent" of RTT, the update is limited by the time elapsed.
if (last_congestion_window_ == current_congestion_window &&
(current_time - last_update_time_ <= MaxCubicTimeInterval())) {
- return max(last_target_congestion_window_,
- estimated_tcp_congestion_window_);
+ return std::max(last_target_congestion_window_,
+ estimated_tcp_congestion_window_);
}
last_congestion_window_ = current_congestion_window;
last_update_time_ = current_time;
@@ -139,24 +158,35 @@ QuicPacketCount Cubic::CongestionWindowAfterAck(
// Change the time unit from microseconds to 2^10 fractions per second. Take
// the round trip time in account. This is done to allow us to use shift as a
// divide operator.
- int64_t elapsed_time =
+ const int64_t elapsed_time =
((current_time + delay_min - epoch_).ToMicroseconds() << 10) /
kNumMicrosPerSecond;
+ DCHECK_GE(elapsed_time, 0);
int64_t offset = time_to_origin_point_ - elapsed_time;
+ if (fix_convex_mode_) {
+ // Right-shifts of negative, signed numbers have
+ // implementation-dependent behavior. Force the offset to be
+ // positive, similar to the kernel implementation.
+ offset = std::abs(time_to_origin_point_ - elapsed_time);
+ }
+
QuicPacketCount delta_congestion_window =
(kCubeCongestionWindowScale * offset * offset * offset) >> kCubeScale;
+ const bool add_delta = elapsed_time > time_to_origin_point_;
+ DCHECK(add_delta ||
+ (origin_point_congestion_window_ > delta_congestion_window));
QuicPacketCount target_congestion_window =
- origin_point_congestion_window_ - delta_congestion_window;
-
- if (FLAGS_quic_limit_cubic_cwnd_increase) {
- // Limit the CWND increase to half the acked packets rounded up to the
- // nearest packet.
- target_congestion_window =
- min(target_congestion_window,
- current_congestion_window + (epoch_packets_count_ + 1) / 2);
- }
+ (fix_convex_mode_ && add_delta)
+ ? origin_point_congestion_window_ + delta_congestion_window
+ : origin_point_congestion_window_ - delta_congestion_window;
+
+ // Limit the CWND increase to half the acked packets rounded up to the
+ // nearest packet.
+ target_congestion_window =
+ std::min(target_congestion_window,
+ current_congestion_window + (epoch_packets_count_ + 1) / 2);
DCHECK_LT(0u, estimated_tcp_congestion_window_);
// With dynamic beta/alpha based on number of active streams, it is possible
@@ -183,7 +213,8 @@ QuicPacketCount Cubic::CongestionWindowAfterAck(
target_congestion_window = estimated_tcp_congestion_window_;
}
- DVLOG(1) << "Final target congestion_window: " << target_congestion_window;
+ QUIC_DVLOG(1) << "Final target congestion_window: "
+ << target_congestion_window;
return target_congestion_window;
}
diff --git a/chromium/net/quic/core/congestion_control/cubic.h b/chromium/net/quic/core/congestion_control/cubic.h
index 30657e57c9d..8c1afb3d5a3 100644
--- a/chromium/net/quic/core/congestion_control/cubic.h
+++ b/chromium/net/quic/core/congestion_control/cubic.h
@@ -5,21 +5,25 @@
// Cubic algorithm, helper class to TCP cubic.
// For details see http://netsrv.csc.ncsu.edu/export/cubic_a_new_tcp_2008.pdf.
-#ifndef NET_QUIC_CONGESTION_CONTROL_CUBIC_H_
-#define NET_QUIC_CONGESTION_CONTROL_CUBIC_H_
+#ifndef NET_QUIC_CORE_CONGESTION_CONTROL_CUBIC_H_
+#define NET_QUIC_CORE_CONGESTION_CONTROL_CUBIC_H_
-#include <stdint.h>
+#include <cstdint>
#include "base/macros.h"
-#include "net/base/net_export.h"
#include "net/quic/core/quic_bandwidth.h"
-#include "net/quic/core/quic_clock.h"
#include "net/quic/core/quic_connection_stats.h"
#include "net/quic/core/quic_time.h"
+#include "net/quic/platform/api/quic_clock.h"
+#include "net/quic/platform/api/quic_export.h"
namespace net {
-class NET_EXPORT_PRIVATE Cubic {
+namespace test {
+class CubicTest;
+} // namespace test
+
+class QUIC_EXPORT_PRIVATE Cubic {
public:
explicit Cubic(const QuicClock* clock);
@@ -34,25 +38,43 @@ class NET_EXPORT_PRIVATE Cubic {
QuicPacketCount CongestionWindowAfterPacketLoss(QuicPacketCount current);
// Compute a new congestion window to use after a received ACK.
- // Returns the new congestion window in packets. The new congestion window
- // follows a cubic function that depends on the time passed since last
- // packet loss.
+ // Returns the new congestion window in packets. The new congestion
+ // window follows a cubic function that depends on the time passed
+ // since last packet loss.
QuicPacketCount CongestionWindowAfterAck(QuicPacketCount current,
- QuicTime::Delta delay_min);
+ QuicTime::Delta delay_min,
+ QuicTime event_time);
// Call on ack arrival when sender is unable to use the available congestion
// window. Resets Cubic state during quiescence.
void OnApplicationLimited();
+ // If true, enable the fix for the convex-mode signing bug. See
+ // b/32170105 for more information about the bug.
+ // TODO(jokulik): Remove once the fix is enabled by default.
+ void SetFixConvexMode(bool fix_convex_mode);
+
+ // If true, enable the fix for scaling BetaLastMax for n-nonnection
+ // emulation. See b/33272010 for more information about the bug.
+ // TODO(jokulik): Remove once the fix is enabled by default.
+ void SetFixBetaLastMax(bool fix_bet_last_max);
+
private:
+ friend class test::CubicTest;
+
static const QuicTime::Delta MaxCubicTimeInterval() {
return QuicTime::Delta::FromMilliseconds(30);
}
- // Compute the TCP Cubic alpha and beta based on the current number of
- // connections.
+ // Compute the TCP Cubic alpha, beta, and beta-last-max based on the
+ // current number of connections.
float Alpha() const;
float Beta() const;
+ float BetaLastMax() const;
+
+ QuicByteCount last_max_congestion_window() const {
+ return last_max_congestion_window_;
+ }
const QuicClock* clock_;
@@ -97,9 +119,17 @@ class NET_EXPORT_PRIVATE Cubic {
// Last congestion window in packets computed by cubic function.
QuicPacketCount last_target_congestion_window_;
+ // Fix convex mode for cubic.
+ // TODO(jokulik): Remove once the cubic convex experiment is done.
+ bool fix_convex_mode_;
+
+ // Fix beta last max for n-connection-emulation.
+ // TODO(jokulik): Remove once the corresponding experiment is done.
+ bool fix_beta_last_max_;
+
DISALLOW_COPY_AND_ASSIGN(Cubic);
};
} // namespace net
-#endif // NET_QUIC_CONGESTION_CONTROL_CUBIC_H_
+#endif // NET_QUIC_CORE_CONGESTION_CONTROL_CUBIC_H_
diff --git a/chromium/net/quic/core/congestion_control/cubic_bytes.cc b/chromium/net/quic/core/congestion_control/cubic_bytes.cc
index 91924b06e9f..ea19622e8de 100644
--- a/chromium/net/quic/core/congestion_control/cubic_bytes.cc
+++ b/chromium/net/quic/core/congestion_control/cubic_bytes.cc
@@ -4,16 +4,13 @@
#include "net/quic/core/congestion_control/cubic_bytes.h"
-#include <stdint.h>
#include <algorithm>
#include <cmath>
+#include <cstdint>
-#include "base/logging.h"
#include "net/quic/core/quic_flags.h"
-#include "net/quic/core/quic_protocol.h"
-
-using std::max;
-using std::min;
+#include "net/quic/core/quic_packets.h"
+#include "net/quic/platform/api/quic_logging.h"
namespace net {
@@ -43,7 +40,10 @@ CubicBytes::CubicBytes(const QuicClock* clock)
: clock_(clock),
num_connections_(kDefaultNumConnections),
epoch_(QuicTime::Zero()),
- last_update_time_(QuicTime::Zero()) {
+ last_update_time_(QuicTime::Zero()),
+ fix_convex_mode_(false),
+ fix_cubic_quantization_(false),
+ fix_beta_last_max_(false) {
Reset();
}
@@ -67,6 +67,16 @@ float CubicBytes::Beta() const {
return (num_connections_ - 1 + kBeta) / num_connections_;
}
+float CubicBytes::BetaLastMax() const {
+ // BetaLastMax is the additional backoff factor after loss for our
+ // N-connection emulation, which emulates the additional backoff of
+ // an ensemble of N TCP-Reno connections on a single loss event. The
+ // effective multiplier is computed as:
+ return fix_beta_last_max_
+ ? (num_connections_ - 1 + kBetaLastMax) / num_connections_
+ : kBetaLastMax;
+}
+
void CubicBytes::Reset() {
epoch_ = QuicTime::Zero(); // Reset time.
last_update_time_ = QuicTime::Zero(); // Reset time.
@@ -77,6 +87,19 @@ void CubicBytes::Reset() {
origin_point_congestion_window_ = 0;
time_to_origin_point_ = 0;
last_target_congestion_window_ = 0;
+ fix_convex_mode_ = false;
+}
+
+void CubicBytes::SetFixConvexMode(bool fix_convex_mode) {
+ fix_convex_mode_ = fix_convex_mode;
+}
+
+void CubicBytes::SetFixCubicQuantization(bool fix_cubic_quantization) {
+ fix_cubic_quantization_ = fix_cubic_quantization;
+}
+
+void CubicBytes::SetFixBetaLastMax(bool fix_beta_last_max) {
+ fix_beta_last_max_ = fix_beta_last_max;
}
void CubicBytes::OnApplicationLimited() {
@@ -93,11 +116,18 @@ void CubicBytes::OnApplicationLimited() {
QuicByteCount CubicBytes::CongestionWindowAfterPacketLoss(
QuicByteCount current_congestion_window) {
- if (current_congestion_window < last_max_congestion_window_) {
- // We never reached the old max, so assume we are competing with another
- // flow. Use our extra back off factor to allow the other flow to go up.
+ // Since bytes-mode Reno mode slightly under-estimates the cwnd, we
+ // may never reach precisely the last cwnd over the course of an
+ // RTT. Do not interpret a slight under-estimation as competing traffic.
+ const QuicByteCount last_window_delta =
+ fix_beta_last_max_ ? kDefaultTCPMSS : 0;
+ if (current_congestion_window + last_window_delta <
+ last_max_congestion_window_) {
+ // We never reached the old max, so assume we are competing with
+ // another flow. Use our extra back off factor to allow the other
+ // flow to go up.
last_max_congestion_window_ =
- static_cast<int>(kBetaLastMax * current_congestion_window);
+ static_cast<int>(BetaLastMax() * current_congestion_window);
} else {
last_max_congestion_window_ = current_congestion_window;
}
@@ -108,22 +138,25 @@ QuicByteCount CubicBytes::CongestionWindowAfterPacketLoss(
QuicByteCount CubicBytes::CongestionWindowAfterAck(
QuicByteCount acked_bytes,
QuicByteCount current_congestion_window,
- QuicTime::Delta delay_min) {
+ QuicTime::Delta delay_min,
+ QuicTime event_time) {
acked_bytes_count_ += acked_bytes;
- QuicTime current_time = clock_->ApproximateNow();
+ QuicTime current_time = FLAGS_quic_reloadable_flag_quic_use_event_time
+ ? event_time
+ : clock_->ApproximateNow();
// Cubic is "independent" of RTT, the update is limited by the time elapsed.
if (last_congestion_window_ == current_congestion_window &&
(current_time - last_update_time_ <= MaxCubicTimeInterval())) {
- return max(last_target_congestion_window_,
- estimated_tcp_congestion_window_);
+ return std::max(last_target_congestion_window_,
+ estimated_tcp_congestion_window_);
}
last_congestion_window_ = current_congestion_window;
last_update_time_ = current_time;
if (!epoch_.IsInitialized()) {
// First ACK after a loss event.
- DVLOG(1) << "Start of epoch";
+ QUIC_DVLOG(1) << "Start of epoch";
epoch_ = current_time; // Start of epoch.
acked_bytes_count_ = acked_bytes; // Reset count.
// Reset estimated_tcp_congestion_window_ to be in sync with cubic.
@@ -146,22 +179,41 @@ QuicByteCount CubicBytes::CongestionWindowAfterAck(
kNumMicrosPerSecond;
int64_t offset = time_to_origin_point_ - elapsed_time;
+ if (fix_convex_mode_) {
+ // Right-shifts of negative, signed numbers have
+ // implementation-dependent behavior. In the fix, force the
+ // offset to be positive, as is done in the kernel.
+ const int64_t positive_offset =
+ std::abs(time_to_origin_point_ - elapsed_time);
+ offset = positive_offset;
+ }
QuicByteCount delta_congestion_window =
- ((kCubeCongestionWindowScale * offset * offset * offset) >> kCubeScale) *
- kDefaultTCPMSS;
-
+ fix_cubic_quantization_
+ ? (kCubeCongestionWindowScale * offset * offset * offset *
+ kDefaultTCPMSS) >>
+ kCubeScale
+ : ((kCubeCongestionWindowScale * offset * offset * offset) >>
+ kCubeScale) *
+ kDefaultTCPMSS;
+
+ const bool add_delta = elapsed_time > time_to_origin_point_;
+ DCHECK(add_delta ||
+ (origin_point_congestion_window_ > delta_congestion_window));
QuicByteCount target_congestion_window =
- origin_point_congestion_window_ - delta_congestion_window;
- if (FLAGS_quic_limit_cubic_cwnd_increase) {
- // Limit the CWND increase to half the acked bytes.
- target_congestion_window =
- min(target_congestion_window,
- current_congestion_window + acked_bytes_count_ / 2);
- }
+ (fix_convex_mode_ && add_delta)
+ ? origin_point_congestion_window_ + delta_congestion_window
+ : origin_point_congestion_window_ - delta_congestion_window;
+ // Limit the CWND increase to half the acked bytes.
+ target_congestion_window =
+ std::min(target_congestion_window,
+ current_congestion_window + acked_bytes_count_ / 2);
DCHECK_LT(0u, estimated_tcp_congestion_window_);
- // Increase the window by Alpha * 1 MSS of bytes every time we ack an
- // estimated tcp window of bytes.
+ // Increase the window by approximately Alpha * 1 MSS of bytes every
+ // time we ack an estimated tcp window of bytes. For small
+ // congestion windows (less than 25), the formula below will
+ // increase slightly slower than linearly per estimated tcp window
+ // of bytes.
estimated_tcp_congestion_window_ += acked_bytes_count_ *
(Alpha() * kDefaultTCPMSS) /
estimated_tcp_congestion_window_;
@@ -176,7 +228,8 @@ QuicByteCount CubicBytes::CongestionWindowAfterAck(
target_congestion_window = estimated_tcp_congestion_window_;
}
- DVLOG(1) << "Final target congestion_window: " << target_congestion_window;
+ QUIC_DVLOG(1) << "Final target congestion_window: "
+ << target_congestion_window;
return target_congestion_window;
}
diff --git a/chromium/net/quic/core/congestion_control/cubic_bytes.h b/chromium/net/quic/core/congestion_control/cubic_bytes.h
index 73998ad2708..c205cef05e5 100644
--- a/chromium/net/quic/core/congestion_control/cubic_bytes.h
+++ b/chromium/net/quic/core/congestion_control/cubic_bytes.h
@@ -5,21 +5,25 @@
// Cubic algorithm, helper class to TCP cubic.
// For details see http://netsrv.csc.ncsu.edu/export/cubic_a_new_tcp_2008.pdf.
-#ifndef NET_QUIC_CONGESTION_CONTROL_CUBIC_BYTES_H_
-#define NET_QUIC_CONGESTION_CONTROL_CUBIC_BYTES_H_
+#ifndef NET_QUIC_CORE_CONGESTION_CONTROL_CUBIC_BYTES_H_
+#define NET_QUIC_CORE_CONGESTION_CONTROL_CUBIC_BYTES_H_
-#include <stdint.h>
+#include <cstdint>
#include "base/macros.h"
-#include "net/base/net_export.h"
#include "net/quic/core/quic_bandwidth.h"
-#include "net/quic/core/quic_clock.h"
#include "net/quic/core/quic_connection_stats.h"
#include "net/quic/core/quic_time.h"
+#include "net/quic/platform/api/quic_clock.h"
+#include "net/quic/platform/api/quic_export.h"
namespace net {
-class NET_EXPORT_PRIVATE CubicBytes {
+namespace test {
+class CubicBytesTest;
+} // namespace test
+
+class QUIC_EXPORT_PRIVATE CubicBytes {
public:
explicit CubicBytes(const QuicClock* clock);
@@ -39,21 +43,44 @@ class NET_EXPORT_PRIVATE CubicBytes {
// loss.
QuicByteCount CongestionWindowAfterAck(QuicByteCount acked_bytes,
QuicByteCount current,
- QuicTime::Delta delay_min);
+ QuicTime::Delta delay_min,
+ QuicTime event_time);
// Call on ack arrival when sender is unable to use the available congestion
// window. Resets Cubic state during quiescence.
void OnApplicationLimited();
+ // If true, enable the fix for the convex-mode signing bug. See
+ // b/32170105 for more information about the bug.
+ // TODO(jokulik): Remove once the fix is enabled by default.
+ void SetFixConvexMode(bool fix_convex_mode);
+
+ // If true, fix CubicBytes quantization bug. See b/33273459 for
+ // more information about the bug.
+ // TODO(jokulik): Remove once the fix is enabled by default.
+ void SetFixCubicQuantization(bool fix_cubic_quantization);
+
+ // If true, enable the fix for scaling BetaLastMax for n-nonnection
+ // emulation. See b/33272010 for more information about the bug.
+ // TODO(jokulik): Remove once the fix is enabled by default.
+ void SetFixBetaLastMax(bool fix_beta_last_max);
+
private:
+ friend class test::CubicBytesTest;
+
static const QuicTime::Delta MaxCubicTimeInterval() {
return QuicTime::Delta::FromMilliseconds(30);
}
- // Compute the TCP Cubic alpha and beta based on the current number of
- // connections.
+ // Compute the TCP Cubic alpha, beta, and beta-last-max based on the
+ // current number of connections.
float Alpha() const;
float Beta() const;
+ float BetaLastMax() const;
+
+ QuicByteCount last_max_congestion_window() const {
+ return last_max_congestion_window_;
+ }
const QuicClock* clock_;
@@ -89,9 +116,21 @@ class NET_EXPORT_PRIVATE CubicBytes {
// Last congestion window in packets computed by cubic function.
QuicByteCount last_target_congestion_window_;
+ // Fix convex mode for cubic.
+ // TODO(jokulik): Remove once the cubic convex experiment is done.
+ bool fix_convex_mode_;
+
+ // Fix for quantization in cubic mode.
+ // TODO(jokulik): Remove once the experiment is done.
+ bool fix_cubic_quantization_;
+
+ // Fix beta last max for n-connection-emulation.
+ // TODO(jokulik): Remove once the corresponding experiment is done.
+ bool fix_beta_last_max_;
+
DISALLOW_COPY_AND_ASSIGN(CubicBytes);
};
} // namespace net
-#endif // NET_QUIC_CONGESTION_CONTROL_CUBIC_BYTES_H_
+#endif // NET_QUIC_CORE_CONGESTION_CONTROL_CUBIC_BYTES_H_
diff --git a/chromium/net/quic/core/congestion_control/cubic_bytes_test.cc b/chromium/net/quic/core/congestion_control/cubic_bytes_test.cc
index 8c5f12d48fe..e64865bf7c5 100644
--- a/chromium/net/quic/core/congestion_control/cubic_bytes_test.cc
+++ b/chromium/net/quic/core/congestion_control/cubic_bytes_test.cc
@@ -4,7 +4,8 @@
#include "net/quic/core/congestion_control/cubic_bytes.h"
-#include "base/logging.h"
+#include <cstdint>
+
#include "net/quic/core/quic_flags.h"
#include "net/quic/test_tools/mock_clock.h"
#include "testing/gtest/include/gtest/gtest.h"
@@ -12,9 +13,12 @@
namespace net {
namespace test {
-const float kBeta = 0.7f; // Default Cubic backoff factor.
+const float kBeta = 0.7f; // Default Cubic backoff factor.
+const float kBetaLastMax = 0.85f; // Default Cubic backoff factor.
const uint32_t kNumConnections = 2;
const float kNConnectionBeta = (kNumConnections - 1 + kBeta) / kNumConnections;
+const float kNConnectionBetaLastMax =
+ (kNumConnections - 1 + kBetaLastMax) / kNumConnections;
const float kNConnectionAlpha = 3 * kNumConnections * kNumConnections *
(1 - kNConnectionBeta) / (1 + kNConnectionBeta);
@@ -23,104 +27,373 @@ class CubicBytesTest : public ::testing::Test {
CubicBytesTest()
: one_ms_(QuicTime::Delta::FromMilliseconds(1)),
hundred_ms_(QuicTime::Delta::FromMilliseconds(100)),
- cubic_(&clock_) {}
+ cubic_(&clock_) {
+ cubic_.SetFixConvexMode(
+ FLAGS_quic_reloadable_flag_quic_fix_cubic_convex_mode);
+ cubic_.SetFixCubicQuantization(
+ FLAGS_quic_reloadable_flag_quic_fix_cubic_bytes_quantization);
+ cubic_.SetFixBetaLastMax(FLAGS_quic_reloadable_flag_quic_fix_beta_last_max);
+ }
+
+ QuicByteCount RenoCwndInBytes(QuicByteCount current_cwnd) {
+ QuicByteCount reno_estimated_cwnd =
+ current_cwnd +
+ kDefaultTCPMSS * (kNConnectionAlpha * kDefaultTCPMSS) / current_cwnd;
+ return reno_estimated_cwnd;
+ }
+
+ QuicByteCount ConservativeCwndInBytes(QuicByteCount current_cwnd) {
+ QuicByteCount conservative_cwnd = current_cwnd + kDefaultTCPMSS / 2;
+ return conservative_cwnd;
+ }
+
+ QuicByteCount CubicConvexCwndInBytes(QuicByteCount initial_cwnd,
+ QuicTime::Delta rtt,
+ QuicTime::Delta elapsed_time) {
+ const int64_t offset =
+ ((elapsed_time + rtt).ToMicroseconds() << 10) / 1000000;
+ const QuicByteCount delta_congestion_window =
+ FLAGS_quic_reloadable_flag_quic_fix_cubic_bytes_quantization
+ ? ((410 * offset * offset * offset) * kDefaultTCPMSS >> 40)
+ : ((410 * offset * offset * offset) >> 40) * kDefaultTCPMSS;
+ const QuicByteCount cubic_cwnd = initial_cwnd + delta_congestion_window;
+ return cubic_cwnd;
+ }
+
+ QuicByteCount LastMaxCongestionWindow() {
+ return cubic_.last_max_congestion_window();
+ }
+
const QuicTime::Delta one_ms_;
const QuicTime::Delta hundred_ms_;
MockClock clock_;
CubicBytes cubic_;
};
+// TODO(jokulik): The original "AboveOrigin" test, below, is very
+// loose. It's nearly impossible to make the test tighter without
+// deploying the fix for convex mode. Once cubic convex is deployed,
+// replace "AboveOrigin" with this test.
+TEST_F(CubicBytesTest, AboveOriginWithTighterBounds) {
+ if (!FLAGS_quic_reloadable_flag_quic_fix_cubic_convex_mode) {
+ // Without convex mode fixed, the behavior of the algorithm is so
+ // far from expected, there's no point in doing a tighter test.
+ return;
+ }
+ // Convex growth.
+ const QuicTime::Delta rtt_min = hundred_ms_;
+ int64_t rtt_min_ms = rtt_min.ToMilliseconds();
+ float rtt_min_s = rtt_min_ms / 1000.0;
+ QuicByteCount current_cwnd = 10 * kDefaultTCPMSS;
+ const QuicByteCount initial_cwnd = current_cwnd;
+
+ clock_.AdvanceTime(one_ms_);
+ const QuicTime initial_time = clock_.ApproximateNow();
+ const QuicByteCount expected_first_cwnd = RenoCwndInBytes(current_cwnd);
+ current_cwnd = cubic_.CongestionWindowAfterAck(kDefaultTCPMSS, current_cwnd,
+ rtt_min, initial_time);
+ ASSERT_EQ(expected_first_cwnd, current_cwnd);
+
+ // Normal TCP phase.
+ // The maximum number of expected Reno RTTs is calculated by
+ // finding the point where the cubic curve and the reno curve meet.
+ const int max_reno_rtts =
+ FLAGS_quic_reloadable_flag_quic_fix_cubic_bytes_quantization
+ ? std::sqrt(kNConnectionAlpha /
+ (.4 * rtt_min_s * rtt_min_s * rtt_min_s)) -
+ 2
+ : std::sqrt(kNConnectionAlpha /
+ (.4 * rtt_min_s * rtt_min_s * rtt_min_s)) -
+ 1;
+ for (int i = 0; i < max_reno_rtts; ++i) {
+ // Alternatively, we expect it to increase by one, every time we
+ // receive current_cwnd/Alpha acks back. (This is another way of
+ // saying we expect cwnd to increase by approximately Alpha once
+ // we receive current_cwnd number ofacks back).
+ const uint64_t num_acks_this_epoch =
+ current_cwnd / kDefaultTCPMSS / kNConnectionAlpha;
+ const QuicByteCount initial_cwnd_this_epoch = current_cwnd;
+ for (QuicPacketCount n = 0; n < num_acks_this_epoch; ++n) {
+ // Call once per ACK.
+ const QuicByteCount expected_next_cwnd = RenoCwndInBytes(current_cwnd);
+ current_cwnd = cubic_.CongestionWindowAfterAck(
+ kDefaultTCPMSS, current_cwnd, rtt_min, clock_.ApproximateNow());
+ ASSERT_EQ(expected_next_cwnd, current_cwnd);
+ }
+ // Our byte-wise Reno implementation is an estimate. We expect
+ // the cwnd to increase by approximately one MSS every
+ // cwnd/kDefaultTCPMSS/Alpha acks, but it may be off by as much as
+ // half a packet for smaller values of current_cwnd.
+ const QuicByteCount cwnd_change_this_epoch =
+ current_cwnd - initial_cwnd_this_epoch;
+ ASSERT_NEAR(kDefaultTCPMSS, cwnd_change_this_epoch, kDefaultTCPMSS / 2);
+ clock_.AdvanceTime(hundred_ms_);
+ }
+
+ if (!FLAGS_quic_reloadable_flag_quic_fix_cubic_bytes_quantization) {
+ // Because our byte-wise Reno under-estimates the cwnd, we switch to
+ // conservative increases for a few acks before switching to true
+ // cubic increases.
+ for (int i = 0; i < 3; ++i) {
+ const QuicByteCount next_expected_cwnd =
+ ConservativeCwndInBytes(current_cwnd);
+ current_cwnd = cubic_.CongestionWindowAfterAck(
+ kDefaultTCPMSS, current_cwnd, rtt_min, clock_.ApproximateNow());
+ ASSERT_EQ(next_expected_cwnd, current_cwnd);
+ }
+ }
+
+ for (int i = 0; i < 54; ++i) {
+ const uint64_t max_acks_this_epoch = current_cwnd / kDefaultTCPMSS;
+ const QuicByteCount expected_cwnd = CubicConvexCwndInBytes(
+ initial_cwnd, rtt_min, (clock_.ApproximateNow() - initial_time));
+ current_cwnd = cubic_.CongestionWindowAfterAck(
+ kDefaultTCPMSS, current_cwnd, rtt_min, clock_.ApproximateNow());
+ ASSERT_EQ(expected_cwnd, current_cwnd);
+
+ for (QuicPacketCount n = 1; n < max_acks_this_epoch; ++n) {
+ // Call once per ACK.
+ ASSERT_EQ(current_cwnd, cubic_.CongestionWindowAfterAck(
+ kDefaultTCPMSS, current_cwnd, rtt_min,
+ clock_.ApproximateNow()));
+ }
+ clock_.AdvanceTime(hundred_ms_);
+ }
+ const QuicByteCount expected_cwnd = CubicConvexCwndInBytes(
+ initial_cwnd, rtt_min, (clock_.ApproximateNow() - initial_time));
+ current_cwnd = cubic_.CongestionWindowAfterAck(
+ kDefaultTCPMSS, current_cwnd, rtt_min, clock_.ApproximateNow());
+ ASSERT_EQ(expected_cwnd, current_cwnd);
+}
+
TEST_F(CubicBytesTest, AboveOrigin) {
+ if (!FLAGS_quic_reloadable_flag_quic_fix_cubic_convex_mode &&
+ FLAGS_quic_reloadable_flag_quic_fix_cubic_bytes_quantization) {
+ // Without convex mode fixed, the behavior of the algorithm does
+ // not fit the exact pattern of this test.
+ // TODO(jokulik): Once the convex mode fix becomes default, this
+ // test can be replaced with the better AboveOriginTighterBounds
+ // test.
+ return;
+ }
// Convex growth.
const QuicTime::Delta rtt_min = hundred_ms_;
QuicByteCount current_cwnd = 10 * kDefaultTCPMSS;
- QuicByteCount expected_cwnd =
- current_cwnd + (FLAGS_quic_limit_cubic_cwnd_increase ? kDefaultTCPMSS / 2
- : kDefaultTCPMSS);
+ // Without the signed-integer, cubic-convex fix, we start out in the
+ // wrong mode.
+ QuicPacketCount expected_cwnd =
+ FLAGS_quic_reloadable_flag_quic_fix_cubic_convex_mode
+ ? RenoCwndInBytes(current_cwnd)
+ : ConservativeCwndInBytes(current_cwnd);
// Initialize the state.
clock_.AdvanceTime(one_ms_);
- EXPECT_EQ(expected_cwnd, cubic_.CongestionWindowAfterAck(
- kDefaultTCPMSS, current_cwnd, rtt_min));
+ ASSERT_EQ(expected_cwnd,
+ cubic_.CongestionWindowAfterAck(kDefaultTCPMSS, current_cwnd,
+ rtt_min, clock_.ApproximateNow()));
current_cwnd = expected_cwnd;
+ const QuicPacketCount initial_cwnd = expected_cwnd;
// Normal TCP phase.
for (int i = 0; i < 48; ++i) {
for (QuicPacketCount n = 1;
n < current_cwnd / kDefaultTCPMSS / kNConnectionAlpha; ++n) {
// Call once per ACK.
- EXPECT_NEAR(current_cwnd, cubic_.CongestionWindowAfterAck(
- kDefaultTCPMSS, current_cwnd, rtt_min),
+ ASSERT_NEAR(current_cwnd, cubic_.CongestionWindowAfterAck(
+ kDefaultTCPMSS, current_cwnd, rtt_min,
+ clock_.ApproximateNow()),
kDefaultTCPMSS);
}
clock_.AdvanceTime(hundred_ms_);
- current_cwnd =
- cubic_.CongestionWindowAfterAck(kDefaultTCPMSS, current_cwnd, rtt_min);
- EXPECT_NEAR(expected_cwnd, current_cwnd, kDefaultTCPMSS);
- expected_cwnd += kDefaultTCPMSS;
+ current_cwnd = cubic_.CongestionWindowAfterAck(
+ kDefaultTCPMSS, current_cwnd, rtt_min, clock_.ApproximateNow());
+ if (FLAGS_quic_reloadable_flag_quic_fix_cubic_convex_mode) {
+ // When we fix convex mode and the uint64 arithmetic, we
+ // increase the expected_cwnd only after after the first 100ms,
+ // rather than after the initial 1ms.
+ expected_cwnd += kDefaultTCPMSS;
+ ASSERT_NEAR(expected_cwnd, current_cwnd, kDefaultTCPMSS);
+ } else {
+ ASSERT_NEAR(expected_cwnd, current_cwnd, kDefaultTCPMSS);
+ expected_cwnd += kDefaultTCPMSS;
+ }
}
// Cubic phase.
for (int i = 0; i < 52; ++i) {
for (QuicPacketCount n = 1; n < current_cwnd / kDefaultTCPMSS; ++n) {
// Call once per ACK.
- EXPECT_NEAR(current_cwnd, cubic_.CongestionWindowAfterAck(
- kDefaultTCPMSS, current_cwnd, rtt_min),
+ ASSERT_NEAR(current_cwnd, cubic_.CongestionWindowAfterAck(
+ kDefaultTCPMSS, current_cwnd, rtt_min,
+ clock_.ApproximateNow()),
kDefaultTCPMSS);
}
clock_.AdvanceTime(hundred_ms_);
- current_cwnd =
- cubic_.CongestionWindowAfterAck(kDefaultTCPMSS, current_cwnd, rtt_min);
+ current_cwnd = cubic_.CongestionWindowAfterAck(
+ kDefaultTCPMSS, current_cwnd, rtt_min, clock_.ApproximateNow());
}
// Total time elapsed so far; add min_rtt (0.1s) here as well.
float elapsed_time_s = 10.0f + 0.1f;
// |expected_cwnd| is initial value of cwnd + K * t^3, where K = 0.4.
expected_cwnd =
- 11 + (elapsed_time_s * elapsed_time_s * elapsed_time_s * 410) / 1024;
+ initial_cwnd / kDefaultTCPMSS +
+ (elapsed_time_s * elapsed_time_s * elapsed_time_s * 410) / 1024;
+ // Without the convex mode fix, the result is off by one.
+ if (!FLAGS_quic_reloadable_flag_quic_fix_cubic_convex_mode) {
+ ++expected_cwnd;
+ }
EXPECT_EQ(expected_cwnd, current_cwnd / kDefaultTCPMSS);
}
+// Constructs an artificial scenario to ensure that cubic-convex
+// increases are truly fine-grained:
+//
+// - After starting the epoch, this test advances the elapsed time
+// sufficiently far that cubic will do small increases at less than
+// MaxCubicTimeInterval() intervals.
+//
+// - Sets an artificially large initial cwnd to prevent Reno from the
+// convex increases on every ack.
+TEST_F(CubicBytesTest, AboveOriginFineGrainedCubing) {
+ if (!FLAGS_quic_reloadable_flag_quic_fix_cubic_convex_mode ||
+ !FLAGS_quic_reloadable_flag_quic_fix_cubic_bytes_quantization) {
+ // Without these two fixes, this test cannot pass.
+ return;
+ }
+
+ // Start the test with an artificially large cwnd to prevent Reno
+ // from over-taking cubic.
+ QuicByteCount current_cwnd = 1000 * kDefaultTCPMSS;
+ const QuicByteCount initial_cwnd = current_cwnd;
+ const QuicTime::Delta rtt_min = hundred_ms_;
+ clock_.AdvanceTime(one_ms_);
+ QuicTime initial_time = clock_.ApproximateNow();
+
+ // Start the epoch and then artificially advance the time.
+ current_cwnd = cubic_.CongestionWindowAfterAck(
+ kDefaultTCPMSS, current_cwnd, rtt_min, clock_.ApproximateNow());
+ clock_.AdvanceTime(QuicTime::Delta::FromMilliseconds(600));
+ current_cwnd = cubic_.CongestionWindowAfterAck(
+ kDefaultTCPMSS, current_cwnd, rtt_min, clock_.ApproximateNow());
+
+ // We expect the algorithm to perform only non-zero, fine-grained cubic
+ // increases on every ack in this case.
+ for (int i = 0; i < 100; ++i) {
+ clock_.AdvanceTime(QuicTime::Delta::FromMilliseconds(10));
+ const QuicByteCount expected_cwnd = CubicConvexCwndInBytes(
+ initial_cwnd, rtt_min, (clock_.ApproximateNow() - initial_time));
+ const QuicByteCount next_cwnd = cubic_.CongestionWindowAfterAck(
+ kDefaultTCPMSS, current_cwnd, rtt_min, clock_.ApproximateNow());
+ // Make sure we are performing cubic increases.
+ ASSERT_EQ(expected_cwnd, next_cwnd);
+ // Make sure that these are non-zero, less-than-packet sized
+ // increases.
+ ASSERT_GT(next_cwnd, current_cwnd);
+ const QuicByteCount cwnd_delta = next_cwnd - current_cwnd;
+ ASSERT_GT(kDefaultTCPMSS * .1, cwnd_delta);
+
+ current_cwnd = next_cwnd;
+ }
+}
+
TEST_F(CubicBytesTest, LossEvents) {
const QuicTime::Delta rtt_min = hundred_ms_;
QuicByteCount current_cwnd = 422 * kDefaultTCPMSS;
+ // Without the signed-integer, cubic-convex fix, we mistakenly
+ // increment cwnd after only one_ms_ and a single ack.
QuicPacketCount expected_cwnd =
- current_cwnd + (FLAGS_quic_limit_cubic_cwnd_increase ? kDefaultTCPMSS / 2
- : kDefaultTCPMSS);
+ FLAGS_quic_reloadable_flag_quic_fix_cubic_convex_mode
+ ? RenoCwndInBytes(current_cwnd)
+ : current_cwnd + kDefaultTCPMSS / 2;
// Initialize the state.
clock_.AdvanceTime(one_ms_);
- EXPECT_EQ(expected_cwnd, cubic_.CongestionWindowAfterAck(
- kDefaultTCPMSS, current_cwnd, rtt_min));
- expected_cwnd = static_cast<QuicPacketCount>(current_cwnd * kNConnectionBeta);
+ EXPECT_EQ(expected_cwnd,
+ cubic_.CongestionWindowAfterAck(kDefaultTCPMSS, current_cwnd,
+ rtt_min, clock_.ApproximateNow()));
+
+ // On the first loss, the last max congestion window is set to the
+ // congestion window before the loss.
+ QuicByteCount pre_loss_cwnd = current_cwnd;
+ ASSERT_EQ(0u, LastMaxCongestionWindow());
+ expected_cwnd = static_cast<QuicByteCount>(current_cwnd * kNConnectionBeta);
EXPECT_EQ(expected_cwnd,
cubic_.CongestionWindowAfterPacketLoss(current_cwnd));
- expected_cwnd = static_cast<QuicPacketCount>(current_cwnd * kNConnectionBeta);
+ ASSERT_EQ(pre_loss_cwnd, LastMaxCongestionWindow());
+ current_cwnd = expected_cwnd;
+
+ // On the second loss, the current congestion window has not yet
+ // reached the last max congestion window. The last max congestion
+ // window will be reduced by an additional backoff factor to allow
+ // for competition.
+ pre_loss_cwnd = current_cwnd;
+ expected_cwnd = static_cast<QuicByteCount>(current_cwnd * kNConnectionBeta);
+ ASSERT_EQ(expected_cwnd,
+ cubic_.CongestionWindowAfterPacketLoss(current_cwnd));
+ current_cwnd = expected_cwnd;
+ EXPECT_GT(pre_loss_cwnd, LastMaxCongestionWindow());
+ QuicByteCount expected_last_max =
+ FLAGS_quic_reloadable_flag_quic_fix_beta_last_max
+ ? static_cast<QuicByteCount>(pre_loss_cwnd * kNConnectionBetaLastMax)
+ : static_cast<QuicByteCount>(pre_loss_cwnd * kBetaLastMax);
+ EXPECT_EQ(expected_last_max, LastMaxCongestionWindow());
+ if (FLAGS_quic_reloadable_flag_quic_fix_beta_last_max) {
+ EXPECT_LT(expected_cwnd, LastMaxCongestionWindow());
+ } else {
+ // If we don't scale kLastBetaMax, the current window is exactly
+ // equal to the last max congestion window, which would cause us
+ // to land above the origin on the next increase.
+ EXPECT_EQ(expected_cwnd, LastMaxCongestionWindow());
+ }
+ // Simulate an increase, and check that we are below the origin.
+ current_cwnd = cubic_.CongestionWindowAfterAck(
+ kDefaultTCPMSS, current_cwnd, rtt_min, clock_.ApproximateNow());
+ if (FLAGS_quic_reloadable_flag_quic_fix_beta_last_max) {
+ EXPECT_GT(LastMaxCongestionWindow(), current_cwnd);
+ } else {
+ // Without the bug fix, we will be at or above the origin.
+ EXPECT_LE(LastMaxCongestionWindow(), current_cwnd);
+ }
+
+ // On the final loss, simulate the condition where the congestion
+ // window had a chance to grow nearly to the last congestion window.
+ current_cwnd = LastMaxCongestionWindow() - 1;
+ pre_loss_cwnd = current_cwnd;
+ expected_cwnd = static_cast<QuicByteCount>(current_cwnd * kNConnectionBeta);
EXPECT_EQ(expected_cwnd,
cubic_.CongestionWindowAfterPacketLoss(current_cwnd));
+ expected_last_max =
+ FLAGS_quic_reloadable_flag_quic_fix_beta_last_max
+ ? pre_loss_cwnd
+ : static_cast<QuicByteCount>(pre_loss_cwnd * kBetaLastMax);
+ ASSERT_EQ(expected_last_max, LastMaxCongestionWindow());
}
TEST_F(CubicBytesTest, BelowOrigin) {
// Concave growth.
const QuicTime::Delta rtt_min = hundred_ms_;
QuicByteCount current_cwnd = 422 * kDefaultTCPMSS;
+ // Without the signed-integer, cubic-convex fix, we mistakenly
+ // increment cwnd after only one_ms_ and a single ack.
QuicPacketCount expected_cwnd =
- current_cwnd + (FLAGS_quic_limit_cubic_cwnd_increase ? kDefaultTCPMSS / 2
- : kDefaultTCPMSS);
+ FLAGS_quic_reloadable_flag_quic_fix_cubic_convex_mode
+ ? RenoCwndInBytes(current_cwnd)
+ : current_cwnd + kDefaultTCPMSS / 2;
// Initialize the state.
clock_.AdvanceTime(one_ms_);
- EXPECT_EQ(expected_cwnd, cubic_.CongestionWindowAfterAck(
- kDefaultTCPMSS, current_cwnd, rtt_min));
+ EXPECT_EQ(expected_cwnd,
+ cubic_.CongestionWindowAfterAck(kDefaultTCPMSS, current_cwnd,
+ rtt_min, clock_.ApproximateNow()));
expected_cwnd = static_cast<QuicPacketCount>(current_cwnd * kNConnectionBeta);
EXPECT_EQ(expected_cwnd,
cubic_.CongestionWindowAfterPacketLoss(current_cwnd));
current_cwnd = expected_cwnd;
// First update after loss to initialize the epoch.
- current_cwnd =
- cubic_.CongestionWindowAfterAck(kDefaultTCPMSS, current_cwnd, rtt_min);
+ current_cwnd = cubic_.CongestionWindowAfterAck(
+ kDefaultTCPMSS, current_cwnd, rtt_min, clock_.ApproximateNow());
// Cubic phase.
for (int i = 0; i < 40; ++i) {
clock_.AdvanceTime(hundred_ms_);
- current_cwnd =
- cubic_.CongestionWindowAfterAck(kDefaultTCPMSS, current_cwnd, rtt_min);
+ current_cwnd = cubic_.CongestionWindowAfterAck(
+ kDefaultTCPMSS, current_cwnd, rtt_min, clock_.ApproximateNow());
}
- expected_cwnd =
- FLAGS_quic_limit_cubic_cwnd_increase ? 553632 : 422 * kDefaultTCPMSS;
+ expected_cwnd = 553632;
EXPECT_EQ(expected_cwnd, current_cwnd);
}
diff --git a/chromium/net/quic/core/congestion_control/cubic_test.cc b/chromium/net/quic/core/congestion_control/cubic_test.cc
index ea07888a0eb..f9d8aee97f3 100644
--- a/chromium/net/quic/core/congestion_control/cubic_test.cc
+++ b/chromium/net/quic/core/congestion_control/cubic_test.cc
@@ -4,7 +4,8 @@
#include "net/quic/core/congestion_control/cubic.h"
-#include "base/logging.h"
+#include <cstdint>
+
#include "net/quic/core/quic_flags.h"
#include "net/quic/test_tools/mock_clock.h"
#include "testing/gtest/include/gtest/gtest.h"
@@ -12,101 +13,201 @@
namespace net {
namespace test {
-const float kBeta = 0.7f; // Default Cubic backoff factor.
+const float kBeta = 0.7f; // Default Cubic backoff factor.
+const float kBetaLastMax = 0.85f; // Default Cubic backoff factor.
const uint32_t kNumConnections = 2;
const float kNConnectionBeta = (kNumConnections - 1 + kBeta) / kNumConnections;
+const float kNConnectionBetaLastMax =
+ (kNumConnections - 1 + kBetaLastMax) / kNumConnections;
const float kNConnectionAlpha = 3 * kNumConnections * kNumConnections *
(1 - kNConnectionBeta) / (1 + kNConnectionBeta);
-class CubicTest : public ::testing::Test {
+// TODO(jokulik): Once we've rolled out the cubic convex fix, we will
+// no longer need a parameterized test.
+class CubicTest : public ::testing::TestWithParam<bool> {
protected:
CubicTest()
: one_ms_(QuicTime::Delta::FromMilliseconds(1)),
hundred_ms_(QuicTime::Delta::FromMilliseconds(100)),
- cubic_(&clock_) {}
+ cubic_(&clock_) {
+ fix_convex_mode_ = GetParam();
+ cubic_.SetFixConvexMode(fix_convex_mode_);
+ cubic_.SetFixBetaLastMax(FLAGS_quic_reloadable_flag_quic_fix_beta_last_max);
+ }
+
+ QuicByteCount LastMaxCongestionWindow() {
+ return cubic_.last_max_congestion_window();
+ }
+
const QuicTime::Delta one_ms_;
const QuicTime::Delta hundred_ms_;
MockClock clock_;
Cubic cubic_;
+ bool fix_convex_mode_;
};
-TEST_F(CubicTest, AboveOrigin) {
+INSTANTIATE_TEST_CASE_P(CubicTests, CubicTest, testing::Bool());
+
+TEST_P(CubicTest, AboveOrigin) {
// Convex growth.
const QuicTime::Delta rtt_min = hundred_ms_;
+ const float rtt_min_s = rtt_min.ToMilliseconds() / 1000.0;
QuicPacketCount current_cwnd = 10;
- QuicPacketCount expected_cwnd = current_cwnd + 1;
+ // Without the signed-integer, cubic-convex fix, we mistakenly
+ // increment cwnd after only one_ms_ and a single ack.
+ QuicPacketCount expected_cwnd =
+ fix_convex_mode_ ? current_cwnd : current_cwnd + 1;
// Initialize the state.
clock_.AdvanceTime(one_ms_);
- EXPECT_EQ(expected_cwnd,
- cubic_.CongestionWindowAfterAck(current_cwnd, rtt_min));
- current_cwnd = expected_cwnd;
+ const QuicTime initial_time = clock_.ApproximateNow();
+ current_cwnd =
+ cubic_.CongestionWindowAfterAck(current_cwnd, rtt_min, initial_time);
+ ASSERT_EQ(expected_cwnd, current_cwnd);
+ const QuicPacketCount initial_cwnd = current_cwnd;
// Normal TCP phase.
- for (int i = 0; i < 48; ++i) {
- for (QuicPacketCount n = 1; n < current_cwnd / kNConnectionAlpha; ++n) {
+ // The maximum number of expected reno RTTs can be calculated by
+ // finding the point where the cubic curve and the reno curve meet.
+ const int max_reno_rtts =
+ std::sqrt(kNConnectionAlpha / (.4 * rtt_min_s * rtt_min_s * rtt_min_s)) -
+ 1;
+ for (int i = 0; i < max_reno_rtts; ++i) {
+ const QuicByteCount max_per_ack_cwnd = current_cwnd;
+ for (QuicPacketCount n = 1; n < max_per_ack_cwnd / kNConnectionAlpha; ++n) {
// Call once per ACK.
- EXPECT_NEAR(current_cwnd,
- cubic_.CongestionWindowAfterAck(current_cwnd, rtt_min), 1);
+ const QuicByteCount next_cwnd = cubic_.CongestionWindowAfterAck(
+ current_cwnd, rtt_min, clock_.ApproximateNow());
+ ASSERT_EQ(current_cwnd, next_cwnd);
}
clock_.AdvanceTime(hundred_ms_);
- current_cwnd = cubic_.CongestionWindowAfterAck(current_cwnd, rtt_min);
- EXPECT_NEAR(expected_cwnd, current_cwnd, 1);
- expected_cwnd++;
+ current_cwnd = cubic_.CongestionWindowAfterAck(current_cwnd, rtt_min,
+ clock_.ApproximateNow());
+ if (fix_convex_mode_) {
+ // When we fix convex mode and the uint64 arithmetic, we
+ // increase the expected_cwnd only after after the first 100ms,
+ // rather than after the initial 1ms.
+ expected_cwnd++;
+ ASSERT_EQ(expected_cwnd, current_cwnd);
+ } else {
+ ASSERT_EQ(expected_cwnd, current_cwnd);
+ expected_cwnd++;
+ }
}
// Cubic phase.
for (int i = 0; i < 52; ++i) {
for (QuicPacketCount n = 1; n < current_cwnd; ++n) {
// Call once per ACK.
- EXPECT_EQ(current_cwnd,
- cubic_.CongestionWindowAfterAck(current_cwnd, rtt_min));
+ ASSERT_EQ(current_cwnd,
+ cubic_.CongestionWindowAfterAck(current_cwnd, rtt_min,
+ clock_.ApproximateNow()));
}
clock_.AdvanceTime(hundred_ms_);
- current_cwnd = cubic_.CongestionWindowAfterAck(current_cwnd, rtt_min);
+ current_cwnd = cubic_.CongestionWindowAfterAck(current_cwnd, rtt_min,
+ clock_.ApproximateNow());
}
// Total time elapsed so far; add min_rtt (0.1s) here as well.
- float elapsed_time_s = 10.0f + 0.1f;
+ const float elapsed_time_ms =
+ (clock_.ApproximateNow() - initial_time).ToMilliseconds() +
+ rtt_min.ToMilliseconds();
+ const float elapsed_time_s = elapsed_time_ms / 1000.0;
// |expected_cwnd| is initial value of cwnd + K * t^3, where K = 0.4.
expected_cwnd =
- 11 + (elapsed_time_s * elapsed_time_s * elapsed_time_s * 410) / 1024;
+ initial_cwnd +
+ (elapsed_time_s * elapsed_time_s * elapsed_time_s * 410) / 1024;
EXPECT_EQ(expected_cwnd, current_cwnd);
}
-TEST_F(CubicTest, LossEvents) {
+TEST_P(CubicTest, LossEvents) {
const QuicTime::Delta rtt_min = hundred_ms_;
QuicPacketCount current_cwnd = 422;
- QuicPacketCount expected_cwnd = current_cwnd + 1;
+ // Without the signed-integer, cubic-convex fix, we mistakenly
+ // increment cwnd after only one_ms_ and a single ack.
+ QuicPacketCount expected_cwnd =
+ fix_convex_mode_ ? current_cwnd : current_cwnd + 1;
// Initialize the state.
clock_.AdvanceTime(one_ms_);
- EXPECT_EQ(expected_cwnd,
- cubic_.CongestionWindowAfterAck(current_cwnd, rtt_min));
+ EXPECT_EQ(expected_cwnd, cubic_.CongestionWindowAfterAck(
+ current_cwnd, rtt_min, clock_.ApproximateNow()));
+
+ // On the first loss, the last max congestion window is set to the
+ // congestion window before the loss.
+ QuicByteCount pre_loss_cwnd = current_cwnd;
expected_cwnd = static_cast<QuicPacketCount>(current_cwnd * kNConnectionBeta);
+ ASSERT_EQ(0u, LastMaxCongestionWindow());
EXPECT_EQ(expected_cwnd,
cubic_.CongestionWindowAfterPacketLoss(current_cwnd));
+ ASSERT_EQ(pre_loss_cwnd, LastMaxCongestionWindow());
+ current_cwnd = expected_cwnd;
+
+ // On the second loss, the current congestion window is
+ // significantly lower than the last max congestion window. The
+ // last max congestion window will be reduced by an additional
+ // backoff factor to allow for competition.
+ pre_loss_cwnd = current_cwnd;
+ expected_cwnd = static_cast<QuicPacketCount>(current_cwnd * kNConnectionBeta);
+ ASSERT_EQ(expected_cwnd,
+ cubic_.CongestionWindowAfterPacketLoss(current_cwnd));
+ current_cwnd = expected_cwnd;
+ EXPECT_GT(pre_loss_cwnd, LastMaxCongestionWindow());
+ QuicByteCount expected_last_max =
+ FLAGS_quic_reloadable_flag_quic_fix_beta_last_max
+ ? static_cast<QuicPacketCount>(pre_loss_cwnd *
+ kNConnectionBetaLastMax)
+ : static_cast<QuicPacketCount>(pre_loss_cwnd * kBetaLastMax);
+ EXPECT_EQ(expected_last_max, LastMaxCongestionWindow());
+ if (FLAGS_quic_reloadable_flag_quic_fix_beta_last_max) {
+ EXPECT_LT(expected_cwnd, LastMaxCongestionWindow());
+ } else {
+ // If we don't scale kLastBetaMax, the current window is exactly
+ // equal to the last max congestion window, which would cause us
+ // to land above the origin on the next increase.
+ EXPECT_EQ(expected_cwnd, LastMaxCongestionWindow());
+ }
+ // Simulate an increase, and check that we are below the origin.
+ current_cwnd = cubic_.CongestionWindowAfterAck(current_cwnd, rtt_min,
+ clock_.ApproximateNow());
+ if (FLAGS_quic_reloadable_flag_quic_fix_beta_last_max) {
+ EXPECT_GT(LastMaxCongestionWindow(), current_cwnd);
+ } else {
+ // Without the bug fix, we will be at or above the origin.
+ EXPECT_LE(LastMaxCongestionWindow(), current_cwnd);
+ }
+
+ // On the final loss, simulate the condition where the congestion
+ // window had a chance to grow back to the last congestion window.
+ current_cwnd = LastMaxCongestionWindow();
+ pre_loss_cwnd = current_cwnd;
expected_cwnd = static_cast<QuicPacketCount>(current_cwnd * kNConnectionBeta);
EXPECT_EQ(expected_cwnd,
cubic_.CongestionWindowAfterPacketLoss(current_cwnd));
+ ASSERT_EQ(pre_loss_cwnd, LastMaxCongestionWindow());
}
-TEST_F(CubicTest, BelowOrigin) {
+TEST_P(CubicTest, BelowOrigin) {
// Concave growth.
const QuicTime::Delta rtt_min = hundred_ms_;
QuicPacketCount current_cwnd = 422;
- QuicPacketCount expected_cwnd = current_cwnd + 1;
+ // Without the signed-integer, cubic-convex fix, we mistakenly
+ // increment cwnd after only one_ms_ and a single ack.
+ QuicPacketCount expected_cwnd =
+ fix_convex_mode_ ? current_cwnd : current_cwnd + 1;
// Initialize the state.
clock_.AdvanceTime(one_ms_);
- EXPECT_EQ(expected_cwnd,
- cubic_.CongestionWindowAfterAck(current_cwnd, rtt_min));
+ EXPECT_EQ(expected_cwnd, cubic_.CongestionWindowAfterAck(
+ current_cwnd, rtt_min, clock_.ApproximateNow()));
expected_cwnd = static_cast<QuicPacketCount>(current_cwnd * kNConnectionBeta);
EXPECT_EQ(expected_cwnd,
cubic_.CongestionWindowAfterPacketLoss(current_cwnd));
current_cwnd = expected_cwnd;
// First update after loss to initialize the epoch.
- current_cwnd = cubic_.CongestionWindowAfterAck(current_cwnd, rtt_min);
+ current_cwnd = cubic_.CongestionWindowAfterAck(current_cwnd, rtt_min,
+ clock_.ApproximateNow());
// Cubic phase.
for (int i = 0; i < 40; ++i) {
clock_.AdvanceTime(hundred_ms_);
- current_cwnd = cubic_.CongestionWindowAfterAck(current_cwnd, rtt_min);
+ current_cwnd = cubic_.CongestionWindowAfterAck(current_cwnd, rtt_min,
+ clock_.ApproximateNow());
}
- expected_cwnd = FLAGS_quic_limit_cubic_cwnd_increase ? 399 : 422;
+ expected_cwnd = 399;
EXPECT_EQ(expected_cwnd, current_cwnd);
}
diff --git a/chromium/net/quic/core/congestion_control/general_loss_algorithm.cc b/chromium/net/quic/core/congestion_control/general_loss_algorithm.cc
index 6d7521c6036..a68520f0ac6 100644
--- a/chromium/net/quic/core/congestion_control/general_loss_algorithm.cc
+++ b/chromium/net/quic/core/congestion_control/general_loss_algorithm.cc
@@ -5,9 +5,9 @@
#include "net/quic/core/congestion_control/general_loss_algorithm.h"
#include "net/quic/core/congestion_control/rtt_stats.h"
-#include "net/quic/core/quic_bug_tracker.h"
#include "net/quic/core/quic_flags.h"
-#include "net/quic/core/quic_protocol.h"
+#include "net/quic/core/quic_packets.h"
+#include "net/quic/platform/api/quic_bug_tracker.h"
namespace net {
@@ -100,7 +100,7 @@ void GeneralLossAlgorithm::DetectLosses(
// there are retransmittable packets in flight.
// This also implements a timer-protected variant of FACK.
if ((!it->retransmittable_frames.empty() &&
- (FLAGS_quic_largest_sent_retransmittable
+ (FLAGS_quic_reloadable_flag_quic_largest_sent_retransmittable
? unacked_packets.largest_sent_retransmittable_packet()
: unacked_packets.largest_sent_packet()) <=
largest_newly_acked) ||
diff --git a/chromium/net/quic/core/congestion_control/general_loss_algorithm.h b/chromium/net/quic/core/congestion_control/general_loss_algorithm.h
index 7b2a253b258..d2557e56779 100644
--- a/chromium/net/quic/core/congestion_control/general_loss_algorithm.h
+++ b/chromium/net/quic/core/congestion_control/general_loss_algorithm.h
@@ -2,25 +2,25 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#ifndef NET_QUIC_CONGESTION_CONTROL_GENERAL_LOSS_ALGORITHM_H_
-#define NET_QUIC_CONGESTION_CONTROL_GENERAL_LOSS_ALGORITHM_H_
+#ifndef NET_QUIC_CORE_CONGESTION_CONTROL_GENERAL_LOSS_ALGORITHM_H_
+#define NET_QUIC_CORE_CONGESTION_CONTROL_GENERAL_LOSS_ALGORITHM_H_
#include <algorithm>
#include <map>
#include "base/macros.h"
-#include "net/base/net_export.h"
#include "net/quic/core/congestion_control/loss_detection_interface.h"
-#include "net/quic/core/quic_protocol.h"
+#include "net/quic/core/quic_packets.h"
#include "net/quic/core/quic_time.h"
#include "net/quic/core/quic_unacked_packet_map.h"
+#include "net/quic/platform/api/quic_export.h"
namespace net {
// Class which can be configured to implement's TCP's approach of detecting loss
// when 3 nacks have been received for a packet or with a time threshold.
// Also implements TCP's early retransmit(RFC5827).
-class NET_EXPORT_PRIVATE GeneralLossAlgorithm : public LossDetectionInterface {
+class QUIC_EXPORT_PRIVATE GeneralLossAlgorithm : public LossDetectionInterface {
public:
// TCP retransmits after 3 nacks.
static const QuicPacketCount kNumberOfNacksBeforeRetransmission = 3;
@@ -73,4 +73,4 @@ class NET_EXPORT_PRIVATE GeneralLossAlgorithm : public LossDetectionInterface {
} // namespace net
-#endif // NET_QUIC_CONGESTION_CONTROL_GENERAL_LOSS_ALGORITHM_H_
+#endif // NET_QUIC_CORE_CONGESTION_CONTROL_GENERAL_LOSS_ALGORITHM_H_
diff --git a/chromium/net/quic/core/congestion_control/general_loss_algorithm_test.cc b/chromium/net/quic/core/congestion_control/general_loss_algorithm_test.cc
index 0a0725ef82e..1e9b11e3fa6 100644
--- a/chromium/net/quic/core/congestion_control/general_loss_algorithm_test.cc
+++ b/chromium/net/quic/core/congestion_control/general_loss_algorithm_test.cc
@@ -5,8 +5,9 @@
#include "net/quic/core/congestion_control/general_loss_algorithm.h"
#include <algorithm>
+#include <cstdint>
-#include "base/logging.h"
+#include "base/stl_util.h"
#include "net/quic/core/congestion_control/rtt_stats.h"
#include "net/quic/core/quic_flags.h"
#include "net/quic/core/quic_unacked_packet_map.h"
@@ -14,8 +15,6 @@
#include "net/quic/test_tools/quic_test_utils.h"
#include "testing/gtest/include/gtest/gtest.h"
-using std::vector;
-
namespace net {
namespace test {
namespace {
@@ -38,7 +37,7 @@ class GeneralLossAlgorithmTest : public ::testing::Test {
frame->stream_id = kHeadersStreamId;
SerializedPacket packet(kDefaultPathId, packet_number,
PACKET_1BYTE_PACKET_NUMBER, nullptr, kDefaultLength,
- 0, false, false);
+ false, false);
packet.retransmittable_frames.push_back(QuicFrame(frame));
unacked_packets_.AddSentPacket(&packet, 0, NOT_RETRANSMISSION, clock_.Now(),
true);
@@ -47,7 +46,7 @@ class GeneralLossAlgorithmTest : public ::testing::Test {
void SendAckPacket(QuicPacketNumber packet_number) {
SerializedPacket packet(kDefaultPathId, packet_number,
PACKET_1BYTE_PACKET_NUMBER, nullptr, kDefaultLength,
- 0, true, false);
+ true, false);
unacked_packets_.AddSentPacket(&packet, 0, NOT_RETRANSMISSION, clock_.Now(),
false);
}
@@ -193,7 +192,7 @@ TEST_F(GeneralLossAlgorithmTest, DontEarlyRetransmitNeuteredPacket) {
}
TEST_F(GeneralLossAlgorithmTest, EarlyRetransmitWithLargerUnackablePackets) {
- FLAGS_quic_largest_sent_retransmittable = true;
+ FLAGS_quic_reloadable_flag_quic_largest_sent_retransmittable = true;
// Transmit 2 data packets and one ack.
SendDataPacket(1);
SendDataPacket(2);
diff --git a/chromium/net/quic/core/congestion_control/hybrid_slow_start.cc b/chromium/net/quic/core/congestion_control/hybrid_slow_start.cc
index 3224cd67cf6..74364cc427c 100644
--- a/chromium/net/quic/core/congestion_control/hybrid_slow_start.cc
+++ b/chromium/net/quic/core/congestion_control/hybrid_slow_start.cc
@@ -6,8 +6,7 @@
#include <algorithm>
-using std::max;
-using std::min;
+#include "net/quic/platform/api/quic_logging.h"
namespace net {
@@ -49,7 +48,7 @@ void HybridSlowStart::Restart() {
}
void HybridSlowStart::StartReceiveRound(QuicPacketNumber last_sent) {
- DVLOG(1) << "Reset hybrid slow start @" << last_sent;
+ QUIC_DVLOG(1) << "Reset hybrid slow start @" << last_sent;
end_packet_number_ = last_sent;
current_min_rtt_ = QuicTime::Delta::Zero();
rtt_sample_count_ = 0;
@@ -88,11 +87,11 @@ bool HybridSlowStart::ShouldExitSlowStart(QuicTime::Delta latest_rtt,
int64_t min_rtt_increase_threshold_us =
min_rtt.ToMicroseconds() >> kHybridStartDelayFactorExp;
// Ensure the rtt threshold is never less than 2ms or more than 16ms.
- min_rtt_increase_threshold_us =
- min(min_rtt_increase_threshold_us, kHybridStartDelayMaxThresholdUs);
+ min_rtt_increase_threshold_us = std::min(min_rtt_increase_threshold_us,
+ kHybridStartDelayMaxThresholdUs);
QuicTime::Delta min_rtt_increase_threshold =
- QuicTime::Delta::FromMicroseconds(max(min_rtt_increase_threshold_us,
- kHybridStartDelayMinThresholdUs));
+ QuicTime::Delta::FromMicroseconds(std::max(
+ min_rtt_increase_threshold_us, kHybridStartDelayMinThresholdUs));
if (current_min_rtt_ > min_rtt + min_rtt_increase_threshold) {
hystart_found_ = DELAY;
diff --git a/chromium/net/quic/core/congestion_control/hybrid_slow_start.h b/chromium/net/quic/core/congestion_control/hybrid_slow_start.h
index 1ca14484e14..7956178999c 100644
--- a/chromium/net/quic/core/congestion_control/hybrid_slow_start.h
+++ b/chromium/net/quic/core/congestion_control/hybrid_slow_start.h
@@ -13,19 +13,19 @@
// http://netsrv.csc.ncsu.edu/export/hybridstart_pfldnet08.pdf
// http://research.csc.ncsu.edu/netsrv/sites/default/files/hystart_techreport_2008.pdf
-#ifndef NET_QUIC_CONGESTION_CONTROL_HYBRID_SLOW_START_H_
-#define NET_QUIC_CONGESTION_CONTROL_HYBRID_SLOW_START_H_
+#ifndef NET_QUIC_CORE_CONGESTION_CONTROL_HYBRID_SLOW_START_H_
+#define NET_QUIC_CORE_CONGESTION_CONTROL_HYBRID_SLOW_START_H_
-#include <stdint.h>
+#include <cstdint>
#include "base/macros.h"
-#include "net/base/net_export.h"
-#include "net/quic/core/quic_protocol.h"
+#include "net/quic/core/quic_packets.h"
#include "net/quic/core/quic_time.h"
+#include "net/quic/platform/api/quic_export.h"
namespace net {
-class NET_EXPORT_PRIVATE HybridSlowStart {
+class QUIC_EXPORT_PRIVATE HybridSlowStart {
public:
HybridSlowStart();
@@ -81,4 +81,4 @@ class NET_EXPORT_PRIVATE HybridSlowStart {
} // namespace net
-#endif // NET_QUIC_CONGESTION_CONTROL_HYBRID_SLOW_START_H_
+#endif // NET_QUIC_CORE_CONGESTION_CONTROL_HYBRID_SLOW_START_H_
diff --git a/chromium/net/quic/core/congestion_control/hybrid_slow_start_test.cc b/chromium/net/quic/core/congestion_control/hybrid_slow_start_test.cc
index 7a580fac421..24310569849 100644
--- a/chromium/net/quic/core/congestion_control/hybrid_slow_start_test.cc
+++ b/chromium/net/quic/core/congestion_control/hybrid_slow_start_test.cc
@@ -6,7 +6,6 @@
#include <memory>
-#include "base/logging.h"
#include "testing/gtest/include/gtest/gtest.h"
namespace net {
diff --git a/chromium/net/quic/core/congestion_control/loss_detection_interface.h b/chromium/net/quic/core/congestion_control/loss_detection_interface.h
index 5fce89f683b..919de77c4af 100644
--- a/chromium/net/quic/core/congestion_control/loss_detection_interface.h
+++ b/chromium/net/quic/core/congestion_control/loss_detection_interface.h
@@ -4,20 +4,20 @@
//
// The pure virtual class for send side loss detection algorithm.
-#ifndef NET_QUIC_CONGESTION_CONTROL_LOSS_DETECTION_INTERFACE_H_
-#define NET_QUIC_CONGESTION_CONTROL_LOSS_DETECTION_INTERFACE_H_
+#ifndef NET_QUIC_CORE_CONGESTION_CONTROL_LOSS_DETECTION_INTERFACE_H_
+#define NET_QUIC_CORE_CONGESTION_CONTROL_LOSS_DETECTION_INTERFACE_H_
-#include "net/base/net_export.h"
#include "net/quic/core/congestion_control/send_algorithm_interface.h"
-#include "net/quic/core/quic_protocol.h"
+#include "net/quic/core/quic_packets.h"
#include "net/quic/core/quic_time.h"
+#include "net/quic/platform/api/quic_export.h"
namespace net {
class QuicUnackedPacketMap;
class RttStats;
-class NET_EXPORT_PRIVATE LossDetectionInterface {
+class QUIC_EXPORT_PRIVATE LossDetectionInterface {
public:
virtual ~LossDetectionInterface() {}
@@ -46,4 +46,4 @@ class NET_EXPORT_PRIVATE LossDetectionInterface {
} // namespace net
-#endif // NET_QUIC_CONGESTION_CONTROL_LOSS_DETECTION_INTERFACE_H_
+#endif // NET_QUIC_CORE_CONGESTION_CONTROL_LOSS_DETECTION_INTERFACE_H_
diff --git a/chromium/net/quic/core/congestion_control/pacing_sender.cc b/chromium/net/quic/core/congestion_control/pacing_sender.cc
index 8ce6e8ae962..976c408134c 100644
--- a/chromium/net/quic/core/congestion_control/pacing_sender.cc
+++ b/chromium/net/quic/core/congestion_control/pacing_sender.cc
@@ -4,11 +4,7 @@
#include "net/quic/core/congestion_control/pacing_sender.h"
-#include <string>
-
-#include "net/quic/core/quic_flags.h"
-
-using std::min;
+#include "net/quic/platform/api/quic_logging.h"
namespace net {
namespace {
@@ -71,7 +67,7 @@ bool PacingSender::OnPacketSent(
// Add more burst tokens anytime the connection is leaving quiescence, but
// limit it to the equivalent of a single bulk write, not exceeding the
// current CWND in packets.
- burst_tokens_ = min(
+ burst_tokens_ = std::min(
kInitialUnpacedBurst,
static_cast<uint32_t>(sender_->GetCongestionWindow() / kDefaultTCPMSS));
}
@@ -132,13 +128,13 @@ QuicTime::Delta PacingSender::TimeUntilSend(
// If the next send time is within the alarm granularity, send immediately.
if (ideal_next_packet_send_time_ > now + kAlarmGranularity) {
- DVLOG(1) << "Delaying packet: "
- << (ideal_next_packet_send_time_ - now).ToMicroseconds();
+ QUIC_DVLOG(1) << "Delaying packet: "
+ << (ideal_next_packet_send_time_ - now).ToMicroseconds();
was_last_send_delayed_ = true;
return ideal_next_packet_send_time_ - now;
}
- DVLOG(1) << "Sending packet now";
+ QUIC_DVLOG(1) << "Sending packet now";
return QuicTime::Delta::Zero();
}
@@ -146,8 +142,8 @@ QuicBandwidth PacingSender::PacingRate(QuicByteCount bytes_in_flight) const {
DCHECK(sender_ != nullptr);
if (!max_pacing_rate_.IsZero()) {
return QuicBandwidth::FromBitsPerSecond(
- min(max_pacing_rate_.ToBitsPerSecond(),
- sender_->PacingRate(bytes_in_flight).ToBitsPerSecond()));
+ std::min(max_pacing_rate_.ToBitsPerSecond(),
+ sender_->PacingRate(bytes_in_flight).ToBitsPerSecond()));
}
return sender_->PacingRate(bytes_in_flight);
}
diff --git a/chromium/net/quic/core/congestion_control/pacing_sender.h b/chromium/net/quic/core/congestion_control/pacing_sender.h
index 8e839c9a50c..b297b8f8050 100644
--- a/chromium/net/quic/core/congestion_control/pacing_sender.h
+++ b/chromium/net/quic/core/congestion_control/pacing_sender.h
@@ -8,25 +8,24 @@
// alarm to ensure that alarms are not set too aggressively, and err towards
// sending packets too early instead of too late.
-#ifndef NET_QUIC_CONGESTION_CONTROL_PACING_SENDER_H_
-#define NET_QUIC_CONGESTION_CONTROL_PACING_SENDER_H_
-
-#include <stdint.h>
+#ifndef NET_QUIC_CORE_CONGESTION_CONTROL_PACING_SENDER_H_
+#define NET_QUIC_CORE_CONGESTION_CONTROL_PACING_SENDER_H_
+#include <cstdint>
#include <map>
#include <memory>
#include "base/macros.h"
-#include "net/base/net_export.h"
#include "net/quic/core/congestion_control/send_algorithm_interface.h"
#include "net/quic/core/quic_bandwidth.h"
#include "net/quic/core/quic_config.h"
-#include "net/quic/core/quic_protocol.h"
+#include "net/quic/core/quic_packets.h"
#include "net/quic/core/quic_time.h"
+#include "net/quic/platform/api/quic_export.h"
namespace net {
-class NET_EXPORT_PRIVATE PacingSender {
+class QUIC_EXPORT_PRIVATE PacingSender {
public:
PacingSender();
~PacingSender();
@@ -73,4 +72,4 @@ class NET_EXPORT_PRIVATE PacingSender {
} // namespace net
-#endif // NET_QUIC_CONGESTION_CONTROL_PACING_SENDER_H_
+#endif // NET_QUIC_CORE_CONGESTION_CONTROL_PACING_SENDER_H_
diff --git a/chromium/net/quic/core/congestion_control/pacing_sender_test.cc b/chromium/net/quic/core/congestion_control/pacing_sender_test.cc
index 3a6ab9367b0..7fc3019d0fd 100644
--- a/chromium/net/quic/core/congestion_control/pacing_sender_test.cc
+++ b/chromium/net/quic/core/congestion_control/pacing_sender_test.cc
@@ -6,8 +6,8 @@
#include <memory>
-#include "base/logging.h"
-#include "net/quic/core/quic_protocol.h"
+#include "net/quic/core/quic_packets.h"
+#include "net/quic/platform/api/quic_logging.h"
#include "net/quic/test_tools/mock_clock.h"
#include "net/quic/test_tools/quic_test_utils.h"
#include "testing/gtest/include/gtest/gtest.h"
@@ -50,9 +50,9 @@ class PacingSenderTest : public ::testing::Test {
pacing_sender_->OnCongestionEvent(true, 1234, clock_.Now(), empty,
lost_packets);
} else if (burst_size != kInitialBurstPackets) {
- LOG(FATAL) << "Unsupported burst_size " << burst_size
- << " specificied, only 0 and " << kInitialBurstPackets
- << " are supported.";
+ QUIC_LOG(FATAL) << "Unsupported burst_size " << burst_size
+ << " specificied, only 0 and " << kInitialBurstPackets
+ << " are supported.";
}
}
diff --git a/chromium/net/quic/core/congestion_control/prr_sender.cc b/chromium/net/quic/core/congestion_control/prr_sender.cc
index 0be617c9c71..bb8ac5c5366 100644
--- a/chromium/net/quic/core/congestion_control/prr_sender.cc
+++ b/chromium/net/quic/core/congestion_control/prr_sender.cc
@@ -4,7 +4,7 @@
#include "net/quic/core/congestion_control/prr_sender.h"
-#include "net/quic/core/quic_protocol.h"
+#include "net/quic/core/quic_packets.h"
namespace net {
diff --git a/chromium/net/quic/core/congestion_control/prr_sender.h b/chromium/net/quic/core/congestion_control/prr_sender.h
index a68fa7a6834..2bc842a3b64 100644
--- a/chromium/net/quic/core/congestion_control/prr_sender.h
+++ b/chromium/net/quic/core/congestion_control/prr_sender.h
@@ -4,18 +4,16 @@
//
// Implements Proportional Rate Reduction (PRR) per RFC 6937.
-#ifndef NET_QUIC_CONGESTION_CONTROL_PRR_SENDER_H_
-#define NET_QUIC_CONGESTION_CONTROL_PRR_SENDER_H_
+#ifndef NET_QUIC_CORE_CONGESTION_CONTROL_PRR_SENDER_H_
+#define NET_QUIC_CORE_CONGESTION_CONTROL_PRR_SENDER_H_
-#include <stddef.h>
-
-#include "net/base/net_export.h"
#include "net/quic/core/quic_bandwidth.h"
#include "net/quic/core/quic_time.h"
+#include "net/quic/platform/api/quic_export.h"
namespace net {
-class NET_EXPORT_PRIVATE PrrSender {
+class QUIC_EXPORT_PRIVATE PrrSender {
public:
PrrSender();
// OnPacketLost should be called on the first loss that triggers a recovery
@@ -42,4 +40,4 @@ class NET_EXPORT_PRIVATE PrrSender {
} // namespace net
-#endif // NET_QUIC_CONGESTION_CONTROL_PRR_SENDER_H_
+#endif // NET_QUIC_CORE_CONGESTION_CONTROL_PRR_SENDER_H_
diff --git a/chromium/net/quic/core/congestion_control/prr_sender_test.cc b/chromium/net/quic/core/congestion_control/prr_sender_test.cc
index d132c3307ba..aa54700add5 100644
--- a/chromium/net/quic/core/congestion_control/prr_sender_test.cc
+++ b/chromium/net/quic/core/congestion_control/prr_sender_test.cc
@@ -6,10 +6,8 @@
#include <algorithm>
-#include "base/logging.h"
#include "net/quic/core/crypto/crypto_protocol.h"
-#include "net/quic/core/quic_bandwidth.h"
-#include "net/quic/core/quic_protocol.h"
+#include "net/quic/core/quic_constants.h"
#include "testing/gtest/include/gtest/gtest.h"
namespace net {
diff --git a/chromium/net/quic/core/congestion_control/rtt_stats.cc b/chromium/net/quic/core/congestion_control/rtt_stats.cc
index 086511cd3a2..1fd7a2c9580 100644
--- a/chromium/net/quic/core/congestion_control/rtt_stats.cc
+++ b/chromium/net/quic/core/congestion_control/rtt_stats.cc
@@ -6,9 +6,7 @@
#include <cstdlib> // std::abs
-#include "net/quic/core/quic_flags.h"
-
-using std::max;
+#include "net/quic/platform/api/quic_logging.h"
namespace net {
@@ -32,10 +30,10 @@ RttStats::RttStats()
initial_rtt_us_(kInitialRttMs * kNumMicrosPerMilli) {}
void RttStats::ExpireSmoothedMetrics() {
- mean_deviation_ = max(mean_deviation_,
- QuicTime::Delta::FromMicroseconds(std::abs(
- (smoothed_rtt_ - latest_rtt_).ToMicroseconds())));
- smoothed_rtt_ = max(smoothed_rtt_, latest_rtt_);
+ mean_deviation_ = std::max(
+ mean_deviation_, QuicTime::Delta::FromMicroseconds(std::abs(
+ (smoothed_rtt_ - latest_rtt_).ToMicroseconds())));
+ smoothed_rtt_ = std::max(smoothed_rtt_, latest_rtt_);
}
// Updates the RTT based on a new sample.
@@ -43,9 +41,10 @@ void RttStats::UpdateRtt(QuicTime::Delta send_delta,
QuicTime::Delta ack_delay,
QuicTime now) {
if (send_delta.IsInfinite() || send_delta <= QuicTime::Delta::Zero()) {
- LOG(WARNING) << "Ignoring measured send_delta, because it's is "
- << "either infinite, zero, or negative. send_delta = "
- << send_delta.ToMicroseconds();
+ QUIC_LOG_FIRST_N(WARNING, 3)
+ << "Ignoring measured send_delta, because it's is "
+ << "either infinite, zero, or negative. send_delta = "
+ << send_delta.ToMicroseconds();
return;
}
@@ -77,8 +76,8 @@ void RttStats::UpdateRtt(QuicTime::Delta send_delta,
kOneMinusBeta * mean_deviation_.ToMicroseconds() +
kBeta * std::abs((smoothed_rtt_ - rtt_sample).ToMicroseconds())));
smoothed_rtt_ = kOneMinusAlpha * smoothed_rtt_ + kAlpha * rtt_sample;
- DVLOG(1) << " smoothed_rtt(us):" << smoothed_rtt_.ToMicroseconds()
- << " mean_deviation(us):" << mean_deviation_.ToMicroseconds();
+ QUIC_DVLOG(1) << " smoothed_rtt(us):" << smoothed_rtt_.ToMicroseconds()
+ << " mean_deviation(us):" << mean_deviation_.ToMicroseconds();
}
}
diff --git a/chromium/net/quic/core/congestion_control/rtt_stats.h b/chromium/net/quic/core/congestion_control/rtt_stats.h
index 242e3419e95..5b54cf9ef9e 100644
--- a/chromium/net/quic/core/congestion_control/rtt_stats.h
+++ b/chromium/net/quic/core/congestion_control/rtt_stats.h
@@ -4,18 +4,17 @@
//
// A convenience class to store rtt samples and calculate smoothed rtt.
-#ifndef NET_QUIC_CONGESTION_CONTROL_RTT_STATS_H_
-#define NET_QUIC_CONGESTION_CONTROL_RTT_STATS_H_
-
-#include <stdint.h>
+#ifndef NET_QUIC_CORE_CONGESTION_CONTROL_RTT_STATS_H_
+#define NET_QUIC_CORE_CONGESTION_CONTROL_RTT_STATS_H_
#include <algorithm>
+#include <cstdint>
#include "base/macros.h"
-#include "net/base/net_export.h"
-#include "net/quic/core/quic_bug_tracker.h"
-#include "net/quic/core/quic_protocol.h"
+#include "net/quic/core/quic_packets.h"
#include "net/quic/core/quic_time.h"
+#include "net/quic/platform/api/quic_bug_tracker.h"
+#include "net/quic/platform/api/quic_export.h"
namespace net {
@@ -23,7 +22,7 @@ namespace test {
class RttStatsPeer;
} // namespace test
-class NET_EXPORT_PRIVATE RttStats {
+class QUIC_EXPORT_PRIVATE RttStats {
public:
RttStats();
@@ -87,4 +86,4 @@ class NET_EXPORT_PRIVATE RttStats {
} // namespace net
-#endif // NET_QUIC_CONGESTION_CONTROL_RTT_STATS_H_
+#endif // NET_QUIC_CORE_CONGESTION_CONTROL_RTT_STATS_H_
diff --git a/chromium/net/quic/core/congestion_control/rtt_stats_test.cc b/chromium/net/quic/core/congestion_control/rtt_stats_test.cc
index 27b08d4f602..b249a2b927a 100644
--- a/chromium/net/quic/core/congestion_control/rtt_stats_test.cc
+++ b/chromium/net/quic/core/congestion_control/rtt_stats_test.cc
@@ -5,11 +5,8 @@
#include "net/quic/core/congestion_control/rtt_stats.h"
#include <cmath>
-#include <vector>
-#include "base/logging.h"
#include "base/test/mock_log.h"
-#include "net/quic/core/quic_flags.h"
#include "net/quic/test_tools/rtt_stats_peer.h"
#include "testing/gtest/include/gtest/gtest.h"
@@ -156,7 +153,9 @@ TEST_F(RttStatsTest, UpdateRttWithBadSendDeltas) {
for (QuicTime::Delta bad_send_delta : bad_send_deltas) {
SCOPED_TRACE(Message() << "bad_send_delta = "
<< bad_send_delta.ToMicroseconds());
+#ifndef NDEBUG
EXPECT_CALL(log, Log(LOG_WARNING, _, _, _, HasSubstr("Ignoring")));
+#endif
rtt_stats_.UpdateRtt(bad_send_delta, QuicTime::Delta::Zero(),
QuicTime::Zero());
EXPECT_EQ(initial_rtt, rtt_stats_.min_rtt());
diff --git a/chromium/net/quic/core/congestion_control/send_algorithm_interface.cc b/chromium/net/quic/core/congestion_control/send_algorithm_interface.cc
index 58d395e2a36..f754366944d 100644
--- a/chromium/net/quic/core/congestion_control/send_algorithm_interface.cc
+++ b/chromium/net/quic/core/congestion_control/send_algorithm_interface.cc
@@ -7,9 +7,9 @@
#include "net/quic/core/congestion_control/bbr_sender.h"
#include "net/quic/core/congestion_control/tcp_cubic_sender_bytes.h"
#include "net/quic/core/congestion_control/tcp_cubic_sender_packets.h"
-#include "net/quic/core/quic_bug_tracker.h"
#include "net/quic/core/quic_flags.h"
-#include "net/quic/core/quic_protocol.h"
+#include "net/quic/core/quic_packets.h"
+#include "net/quic/platform/api/quic_bug_tracker.h"
namespace net {
@@ -27,8 +27,8 @@ SendAlgorithmInterface* SendAlgorithmInterface::Create(
QuicPacketCount max_congestion_window = kDefaultMaxCongestionWindowPackets;
switch (congestion_control_type) {
case kBBR:
- if (FLAGS_quic_allow_new_bbr) {
- return new BbrSender(clock, rtt_stats, unacked_packets,
+ if (FLAGS_quic_reloadable_flag_quic_allow_new_bbr) {
+ return new BbrSender(rtt_stats, unacked_packets,
initial_congestion_window, max_congestion_window,
random);
}
diff --git a/chromium/net/quic/core/congestion_control/send_algorithm_interface.h b/chromium/net/quic/core/congestion_control/send_algorithm_interface.h
index a9e06b3203e..dacccba33a7 100644
--- a/chromium/net/quic/core/congestion_control/send_algorithm_interface.h
+++ b/chromium/net/quic/core/congestion_control/send_algorithm_interface.h
@@ -4,21 +4,21 @@
//
// The pure virtual class for send side congestion control algorithm.
-#ifndef NET_QUIC_CONGESTION_CONTROL_SEND_ALGORITHM_INTERFACE_H_
-#define NET_QUIC_CONGESTION_CONTROL_SEND_ALGORITHM_INTERFACE_H_
+#ifndef NET_QUIC_CORE_CONGESTION_CONTROL_SEND_ALGORITHM_INTERFACE_H_
+#define NET_QUIC_CORE_CONGESTION_CONTROL_SEND_ALGORITHM_INTERFACE_H_
#include <algorithm>
#include <map>
-#include "net/base/net_export.h"
#include "net/quic/core/crypto/quic_random.h"
#include "net/quic/core/quic_bandwidth.h"
-#include "net/quic/core/quic_clock.h"
#include "net/quic/core/quic_config.h"
#include "net/quic/core/quic_connection_stats.h"
-#include "net/quic/core/quic_protocol.h"
+#include "net/quic/core/quic_packets.h"
#include "net/quic/core/quic_time.h"
#include "net/quic/core/quic_unacked_packet_map.h"
+#include "net/quic/platform/api/quic_clock.h"
+#include "net/quic/platform/api/quic_export.h"
namespace net {
@@ -27,9 +27,9 @@ class RttStats;
const QuicPacketCount kDefaultMaxCongestionWindowPackets = 2000;
-class NET_EXPORT_PRIVATE SendAlgorithmInterface {
+class QUIC_EXPORT_PRIVATE SendAlgorithmInterface {
public:
- // A sorted std::vector of packets.
+ // A sorted vector of packets.
typedef std::vector<std::pair<QuicPacketNumber, QuicPacketLength>>
CongestionVector;
@@ -139,4 +139,4 @@ class NET_EXPORT_PRIVATE SendAlgorithmInterface {
} // namespace net
-#endif // NET_QUIC_CONGESTION_CONTROL_SEND_ALGORITHM_INTERFACE_H_
+#endif // NET_QUIC_CORE_CONGESTION_CONTROL_SEND_ALGORITHM_INTERFACE_H_
diff --git a/chromium/net/quic/core/congestion_control/send_algorithm_test.cc b/chromium/net/quic/core/congestion_control/send_algorithm_test.cc
new file mode 100644
index 00000000000..5e882ea4461
--- /dev/null
+++ b/chromium/net/quic/core/congestion_control/send_algorithm_test.cc
@@ -0,0 +1,380 @@
+// Copyright 2013 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.
+
+#include <algorithm>
+#include <map>
+#include <memory>
+
+#include "net/quic/core/congestion_control/rtt_stats.h"
+#include "net/quic/core/congestion_control/send_algorithm_interface.h"
+#include "net/quic/core/quic_types.h"
+#include "net/quic/core/quic_utils.h"
+#include "net/quic/platform/api/quic_logging.h"
+#include "net/quic/test_tools/mock_clock.h"
+#include "net/quic/test_tools/quic_config_peer.h"
+#include "net/quic/test_tools/quic_connection_peer.h"
+#include "net/quic/test_tools/quic_sent_packet_manager_peer.h"
+#include "net/quic/test_tools/quic_test_utils.h"
+#include "net/quic/test_tools/simulator/quic_endpoint.h"
+#include "net/quic/test_tools/simulator/simulator.h"
+#include "net/quic/test_tools/simulator/switch.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+using std::string;
+
+namespace net {
+namespace test {
+namespace {
+
+// Use the initial CWND of 10, as 32 is too much for the test network.
+const uint32_t kInitialCongestionWindowPackets = 10;
+
+// Test network parameters. Here, the topology of the network is:
+//
+// QUIC Sender
+// |
+// | <-- local link
+// |
+// Network switch
+// * <-- the bottleneck queue in the direction
+// | of the receiver
+// |
+// | <-- test link
+// |
+// |
+// Receiver
+//
+// When setting the bandwidth of the local link and test link, choose
+// a bandwidth lower than 20Mbps, as the clock-granularity of the
+// simulator can only handle a granularity of 1us.
+
+// Default settings between the switch and the sender.
+const QuicBandwidth kLocalLinkBandwidth =
+ QuicBandwidth::FromKBitsPerSecond(10000);
+const QuicTime::Delta kLocalPropagationDelay =
+ QuicTime::Delta::FromMilliseconds(2);
+
+// Wired network settings. A typical desktop network setup, a
+// high-bandwidth, 30ms test link to the receiver.
+const QuicBandwidth kTestLinkWiredBandwidth =
+ QuicBandwidth::FromKBitsPerSecond(4000);
+const QuicTime::Delta kTestLinkWiredPropagationDelay =
+ QuicTime::Delta::FromMilliseconds(50);
+const QuicTime::Delta kTestWiredTransferTime =
+ kTestLinkWiredBandwidth.TransferTime(kMaxPacketSize) +
+ kLocalLinkBandwidth.TransferTime(kMaxPacketSize);
+const QuicTime::Delta kTestWiredRtt =
+ (kTestLinkWiredPropagationDelay + kLocalPropagationDelay +
+ kTestWiredTransferTime) *
+ 2;
+const QuicByteCount kTestWiredBdp = kTestWiredRtt * kTestLinkWiredBandwidth;
+
+// Small BDP, Bandwidth-policed network settings. In this scenario,
+// the receiver has a low-bandwidth, short propagation-delay link,
+// resulting in a small BDP. We model the policer by setting the
+// queue size to only one packet.
+const QuicBandwidth kTestLinkLowBdpBandwidth =
+ QuicBandwidth::FromKBitsPerSecond(200);
+const QuicTime::Delta kTestLinkLowBdpPropagationDelay =
+ QuicTime::Delta::FromMilliseconds(50);
+const QuicByteCount kTestPolicerQueue = kMaxPacketSize;
+
+// Satellite network settings. In a satellite network, the bottleneck
+// buffer is typically sized for non-satellite links , but the
+// propagation delay of the test link to the receiver is as much as a
+// quarter second.
+const QuicTime::Delta kTestSatellitePropagationDelay =
+ QuicTime::Delta::FromMilliseconds(250);
+
+// Cellular scenarios. In a cellular network, the bottleneck queue at
+// the edge of the network can be as great as 3MB.
+const QuicBandwidth kTestLink2GBandwidth =
+ QuicBandwidth::FromKBitsPerSecond(100);
+const QuicBandwidth kTestLink3GBandwidth =
+ QuicBandwidth::FromKBitsPerSecond(1500);
+const QuicByteCount kCellularQueue = 3 * 1024 * 1024;
+const QuicTime::Delta kTestCellularPropagationDelay =
+ QuicTime::Delta::FromMilliseconds(40);
+
+const char* CongestionControlTypeToString(CongestionControlType cc_type) {
+ switch (cc_type) {
+ case kCubic:
+ return "CUBIC_PACKETS";
+ case kCubicBytes:
+ return "CUBIC_BYTES";
+ case kReno:
+ return "RENO_PACKETS";
+ case kRenoBytes:
+ return "RENO_BYTES";
+ case kBBR:
+ return "BBR";
+ default:
+ QUIC_DLOG(FATAL) << "Unexpected CongestionControlType";
+ return nullptr;
+ }
+}
+
+struct TestParams {
+ explicit TestParams(CongestionControlType congestion_control_type)
+ : congestion_control_type(congestion_control_type) {}
+
+ friend std::ostream& operator<<(std::ostream& os, const TestParams& p) {
+ os << "{ congestion_control_type: "
+ << CongestionControlTypeToString(p.congestion_control_type);
+ os << " }";
+ return os;
+ }
+
+ CongestionControlType congestion_control_type;
+};
+
+string TestParamToString(const testing::TestParamInfo<TestParams>& params) {
+ return CongestionControlTypeToString(params.param.congestion_control_type);
+}
+
+// Constructs various test permutations.
+std::vector<TestParams> GetTestParams() {
+ std::vector<TestParams> params;
+ for (const CongestionControlType congestion_control_type :
+ {kBBR, kCubic, kCubicBytes, kReno, kRenoBytes}) {
+ params.push_back(TestParams(congestion_control_type));
+ }
+ return params;
+}
+
+} // namespace
+
+class SendAlgorithmTest : public ::testing::TestWithParam<TestParams> {
+ protected:
+ SendAlgorithmTest()
+ : simulator_(),
+ quic_sender_(&simulator_,
+ "QUIC sender",
+ "Receiver",
+ Perspective::IS_CLIENT,
+ 42),
+ receiver_(&simulator_,
+ "Receiver",
+ "QUIC sender",
+ Perspective::IS_SERVER,
+ 42) {
+ rtt_stats_ = quic_sender_.connection()->sent_packet_manager().GetRttStats();
+ sender_ = SendAlgorithmInterface::Create(
+ simulator_.GetClock(), rtt_stats_,
+ QuicSentPacketManagerPeer::GetUnackedPacketMap(
+ QuicConnectionPeer::GetSentPacketManager(
+ quic_sender_.connection())),
+ GetParam().congestion_control_type, &random_, &stats_,
+ kInitialCongestionWindowPackets);
+
+ SetExperimentalOptionsInServerConfig();
+
+ QuicConnectionPeer::SetSendAlgorithm(quic_sender_.connection(), sender_);
+
+ clock_ = simulator_.GetClock();
+ simulator_.set_random_generator(&random_);
+
+ uint64_t seed = QuicRandom::GetInstance()->RandUint64();
+ random_.set_seed(seed);
+ QUIC_LOG(INFO) << "SendAlgorithmTest simulator set up. Seed: " << seed;
+ }
+
+ // Sets experimental options in the server config, as if they had
+ // been sent by the client.
+ void SetExperimentalOptionsInServerConfig() {
+ QuicConfig client_config;
+ QuicTagVector options;
+ if (FLAGS_quic_reloadable_flag_quic_fix_cubic_convex_mode) {
+ options.push_back(kCCVX);
+ }
+ if (FLAGS_quic_reloadable_flag_quic_fix_cubic_convex_mode &&
+ FLAGS_quic_reloadable_flag_quic_fix_cubic_bytes_quantization) {
+ options.push_back(kCCVX);
+ options.push_back(kCBQT);
+ }
+
+ if (FLAGS_quic_reloadable_flag_quic_fix_beta_last_max) {
+ options.push_back(kBLMX);
+ }
+
+ if (!options.empty()) {
+ client_config.SetInitialReceivedConnectionOptions(options);
+ sender_->SetFromConfig(client_config, Perspective::IS_SERVER);
+ }
+ }
+
+ // Creates a simulated network, with default settings between the
+ // sender and the switch and the given settings from the switch to
+ // the receiver.
+ void CreateSetup(const QuicBandwidth& test_bandwidth,
+ const QuicTime::Delta& test_link_delay,
+ QuicByteCount bottleneck_queue_length) {
+ switch_.reset(new simulator::Switch(&simulator_, "Switch", 8,
+ bottleneck_queue_length));
+ quic_sender_link_.reset(new simulator::SymmetricLink(
+ &quic_sender_, switch_->port(1), kLocalLinkBandwidth,
+ kLocalPropagationDelay));
+ receiver_link_.reset(new simulator::SymmetricLink(
+ &receiver_, switch_->port(2), test_bandwidth, test_link_delay));
+ }
+
+ void DoSimpleTransfer(QuicByteCount transfer_size, QuicTime::Delta deadline) {
+ quic_sender_.AddBytesToTransfer(transfer_size);
+ bool simulator_result = simulator_.RunUntilOrTimeout(
+ [this]() { return quic_sender_.bytes_to_transfer() == 0; }, deadline);
+ EXPECT_TRUE(simulator_result)
+ << "Simple transfer failed. Bytes remaining: "
+ << quic_sender_.bytes_to_transfer();
+ }
+
+ void SendBursts(size_t number_of_bursts,
+ QuicByteCount bytes,
+ QuicTime::Delta rtt,
+ QuicTime::Delta wait_time) {
+ ASSERT_EQ(0u, quic_sender_.bytes_to_transfer());
+ for (size_t i = 0; i < number_of_bursts; i++) {
+ quic_sender_.AddBytesToTransfer(bytes);
+
+ // Transfer data and wait for three seconds between each transfer.
+ simulator_.RunFor(wait_time);
+
+ // Ensure the connection did not time out.
+ ASSERT_TRUE(quic_sender_.connection()->connected());
+ ASSERT_TRUE(receiver_.connection()->connected());
+ }
+
+ simulator_.RunFor(wait_time + rtt);
+ EXPECT_EQ(0u, quic_sender_.bytes_to_transfer());
+ }
+
+ // Estimates the elapsed time for a given transfer size, given the
+ // bottleneck bandwidth and link propagation delay.
+ QuicTime::Delta EstimatedElapsedTime(
+ QuicByteCount transfer_size_bytes,
+ QuicBandwidth test_link_bandwidth,
+ const QuicTime::Delta& test_link_delay) const {
+ return test_link_bandwidth.TransferTime(transfer_size_bytes) +
+ 2 * test_link_delay;
+ }
+
+ QuicTime QuicSenderStartTime() {
+ return quic_sender_.connection()->GetStats().connection_creation_time;
+ }
+
+ void PrintTransferStats() {
+ const QuicConnectionStats& stats = quic_sender_.connection()->GetStats();
+ QUIC_LOG(INFO) << "Summary for scenario " << GetParam();
+ QUIC_LOG(INFO) << "Sender stats is " << stats;
+ const double rtx_rate =
+ static_cast<double>(stats.bytes_retransmitted) / stats.bytes_sent;
+ QUIC_LOG(INFO) << "Retransmit rate (num_rtx/num_total_sent): " << rtx_rate;
+ QUIC_LOG(INFO) << "Connection elapsed time: "
+ << (clock_->Now() - QuicSenderStartTime()).ToMilliseconds()
+ << " (ms)";
+ }
+
+ simulator::Simulator simulator_;
+ simulator::QuicEndpoint quic_sender_;
+ simulator::QuicEndpoint receiver_;
+ std::unique_ptr<simulator::Switch> switch_;
+ std::unique_ptr<simulator::SymmetricLink> quic_sender_link_;
+ std::unique_ptr<simulator::SymmetricLink> receiver_link_;
+ QuicConnectionStats stats_;
+
+ SimpleRandom random_;
+
+ // Owned by different components of the connection.
+ const QuicClock* clock_;
+ const RttStats* rtt_stats_;
+ SendAlgorithmInterface* sender_;
+};
+
+INSTANTIATE_TEST_CASE_P(SendAlgorithmTests,
+ SendAlgorithmTest,
+ ::testing::ValuesIn(GetTestParams()),
+ TestParamToString);
+
+// Test a simple long data transfer in the default setup.
+TEST_P(SendAlgorithmTest, SimpleWiredNetworkTransfer) {
+ CreateSetup(kTestLinkWiredBandwidth, kTestLinkWiredPropagationDelay,
+ kTestWiredBdp);
+ const QuicByteCount kTransferSizeBytes = 12 * 1024 * 1024;
+ const QuicTime::Delta maximum_elapsed_time =
+ EstimatedElapsedTime(kTransferSizeBytes, kTestLinkWiredBandwidth,
+ kTestLinkWiredPropagationDelay) *
+ 1.2;
+ DoSimpleTransfer(kTransferSizeBytes, maximum_elapsed_time);
+ PrintTransferStats();
+}
+
+TEST_P(SendAlgorithmTest, LowBdpPolicedNetworkTransfer) {
+ CreateSetup(kTestLinkLowBdpBandwidth, kTestLinkLowBdpPropagationDelay,
+ kTestPolicerQueue);
+ const QuicByteCount kTransferSizeBytes = 5 * 1024 * 1024;
+ const QuicTime::Delta maximum_elapsed_time =
+ EstimatedElapsedTime(kTransferSizeBytes, kTestLinkLowBdpBandwidth,
+ kTestLinkLowBdpPropagationDelay) *
+ 1.2;
+ DoSimpleTransfer(kTransferSizeBytes, maximum_elapsed_time);
+ PrintTransferStats();
+}
+
+TEST_P(SendAlgorithmTest, AppLimitedBurstsOverWiredNetwork) {
+ CreateSetup(kTestLinkWiredBandwidth, kTestLinkWiredPropagationDelay,
+ kTestWiredBdp);
+ const QuicByteCount kBurstSizeBytes = 512;
+ const int kNumBursts = 20;
+ const QuicTime::Delta kWaitTime = QuicTime::Delta::FromSeconds(3);
+ SendBursts(kNumBursts, kBurstSizeBytes, kTestWiredRtt, kWaitTime);
+ PrintTransferStats();
+
+ const QuicTime::Delta estimated_burst_time =
+ EstimatedElapsedTime(kBurstSizeBytes, kTestLinkWiredBandwidth,
+ kTestLinkWiredPropagationDelay) +
+ kWaitTime;
+ const QuicTime::Delta max_elapsed_time =
+ kNumBursts * estimated_burst_time + kWaitTime;
+ const QuicTime::Delta actual_elapsed_time =
+ clock_->Now() - QuicSenderStartTime();
+ EXPECT_GE(max_elapsed_time, actual_elapsed_time);
+}
+
+TEST_P(SendAlgorithmTest, SatelliteNetworkTransfer) {
+ CreateSetup(kTestLinkWiredBandwidth, kTestSatellitePropagationDelay,
+ kTestWiredBdp);
+ const QuicByteCount kTransferSizeBytes = 20 * 1024 * 1024;
+ const QuicTime::Delta maximum_elapsed_time =
+ EstimatedElapsedTime(kTransferSizeBytes, kTestLinkWiredBandwidth,
+ kTestSatellitePropagationDelay) *
+ 1.25;
+ DoSimpleTransfer(kTransferSizeBytes, maximum_elapsed_time);
+ PrintTransferStats();
+}
+
+TEST_P(SendAlgorithmTest, 2GNetworkTransfer) {
+ CreateSetup(kTestLink2GBandwidth, kTestCellularPropagationDelay,
+ kCellularQueue);
+ const QuicByteCount kTransferSizeBytes = 1024 * 1024;
+ const QuicTime::Delta maximum_elapsed_time =
+ EstimatedElapsedTime(kTransferSizeBytes, kTestLink2GBandwidth,
+ kTestCellularPropagationDelay) *
+ 1.2;
+ DoSimpleTransfer(kTransferSizeBytes, maximum_elapsed_time);
+ PrintTransferStats();
+}
+
+TEST_P(SendAlgorithmTest, 3GNetworkTransfer) {
+ CreateSetup(kTestLink3GBandwidth, kTestCellularPropagationDelay,
+ kCellularQueue);
+ const QuicByteCount kTransferSizeBytes = 5 * 1024 * 1024;
+ const QuicTime::Delta maximum_elapsed_time =
+ EstimatedElapsedTime(kTransferSizeBytes, kTestLink3GBandwidth,
+ kTestCellularPropagationDelay) *
+ 1.2;
+ DoSimpleTransfer(kTransferSizeBytes, maximum_elapsed_time);
+ PrintTransferStats();
+}
+
+} // namespace test
+} // namespace net
diff --git a/chromium/net/quic/core/congestion_control/tcp_cubic_sender_base.cc b/chromium/net/quic/core/congestion_control/tcp_cubic_sender_base.cc
index b545d68073e..151cc3ec6a3 100644
--- a/chromium/net/quic/core/congestion_control/tcp_cubic_sender_base.cc
+++ b/chromium/net/quic/core/congestion_control/tcp_cubic_sender_base.cc
@@ -5,18 +5,12 @@
#include "net/quic/core/congestion_control/tcp_cubic_sender_base.h"
#include <algorithm>
-#include <string>
-#include "base/metrics/histogram_macros.h"
#include "net/quic/core/congestion_control/prr_sender.h"
#include "net/quic/core/congestion_control/rtt_stats.h"
#include "net/quic/core/crypto/crypto_protocol.h"
#include "net/quic/core/proto/cached_network_parameters.pb.h"
-#include "net/quic/core/quic_bug_tracker.h"
-#include "net/quic/core/quic_flags.h"
-
-using std::max;
-using std::min;
+#include "net/quic/platform/api/quic_bug_tracker.h"
namespace net {
@@ -115,7 +109,7 @@ void TcpCubicSenderBase::ResumeConnectionState(
}
void TcpCubicSenderBase::SetNumEmulatedConnections(int num_connections) {
- num_connections_ = max(1, num_connections);
+ num_connections_ = std::max(1, num_connections);
}
float TcpCubicSenderBase::RenoBeta() const {
@@ -129,7 +123,7 @@ float TcpCubicSenderBase::RenoBeta() const {
void TcpCubicSenderBase::OnCongestionEvent(
bool rtt_updated,
QuicByteCount prior_in_flight,
- QuicTime /*event_time*/,
+ QuicTime event_time,
const CongestionVector& acked_packets,
const CongestionVector& lost_packets) {
if (rtt_updated && InSlowStart() &&
@@ -144,15 +138,16 @@ void TcpCubicSenderBase::OnCongestionEvent(
}
for (CongestionVector::const_iterator it = acked_packets.begin();
it != acked_packets.end(); ++it) {
- OnPacketAcked(it->first, it->second, prior_in_flight);
+ OnPacketAcked(it->first, it->second, prior_in_flight, event_time);
}
}
void TcpCubicSenderBase::OnPacketAcked(QuicPacketNumber acked_packet_number,
QuicByteCount acked_bytes,
- QuicByteCount prior_in_flight) {
+ QuicByteCount prior_in_flight,
+ QuicTime event_time) {
largest_acked_packet_number_ =
- max(acked_packet_number, largest_acked_packet_number_);
+ std::max(acked_packet_number, largest_acked_packet_number_);
if (InRecovery()) {
if (!no_prr_) {
// PRR is used when in recovery.
@@ -160,7 +155,8 @@ void TcpCubicSenderBase::OnPacketAcked(QuicPacketNumber acked_packet_number,
}
return;
}
- MaybeIncreaseCwnd(acked_packet_number, acked_bytes, prior_in_flight);
+ MaybeIncreaseCwnd(acked_packet_number, acked_bytes, prior_in_flight,
+ event_time);
if (InSlowStart()) {
hybrid_slow_start_.OnPacketAcked(acked_packet_number);
}
diff --git a/chromium/net/quic/core/congestion_control/tcp_cubic_sender_base.h b/chromium/net/quic/core/congestion_control/tcp_cubic_sender_base.h
index 6a7ef231c72..a4ac1e57128 100644
--- a/chromium/net/quic/core/congestion_control/tcp_cubic_sender_base.h
+++ b/chromium/net/quic/core/congestion_control/tcp_cubic_sender_base.h
@@ -4,22 +4,22 @@
//
// TCP cubic send side congestion algorithm, emulates the behavior of TCP cubic.
-#ifndef NET_QUIC_CONGESTION_CONTROL_TCP_CUBIC_SENDER_BASE_H_
-#define NET_QUIC_CONGESTION_CONTROL_TCP_CUBIC_SENDER_BASE_H_
+#ifndef NET_QUIC_CORE_CONGESTION_CONTROL_TCP_CUBIC_SENDER_BASE_H_
+#define NET_QUIC_CORE_CONGESTION_CONTROL_TCP_CUBIC_SENDER_BASE_H_
-#include <stdint.h>
+#include <cstdint>
#include "base/compiler_specific.h"
#include "base/macros.h"
-#include "net/base/net_export.h"
#include "net/quic/core/congestion_control/cubic.h"
#include "net/quic/core/congestion_control/hybrid_slow_start.h"
#include "net/quic/core/congestion_control/prr_sender.h"
#include "net/quic/core/congestion_control/send_algorithm_interface.h"
#include "net/quic/core/quic_bandwidth.h"
#include "net/quic/core/quic_connection_stats.h"
-#include "net/quic/core/quic_protocol.h"
+#include "net/quic/core/quic_packets.h"
#include "net/quic/core/quic_time.h"
+#include "net/quic/platform/api/quic_export.h"
namespace net {
@@ -32,13 +32,14 @@ namespace test {
class TcpCubicSenderBasePeer;
} // namespace test
-class NET_EXPORT_PRIVATE TcpCubicSenderBase : public SendAlgorithmInterface {
+class QUIC_EXPORT_PRIVATE TcpCubicSenderBase : public SendAlgorithmInterface {
public:
// Reno option and max_tcp_congestion_window are provided for testing.
TcpCubicSenderBase(const QuicClock* clock,
const RttStats* rtt_stats,
bool reno,
QuicConnectionStats* stats);
+
~TcpCubicSenderBase() override;
// Start implementation of SendAlgorithmInterface.
@@ -94,7 +95,8 @@ class NET_EXPORT_PRIVATE TcpCubicSenderBase : public SendAlgorithmInterface {
// window.
virtual void MaybeIncreaseCwnd(QuicPacketNumber acked_packet_number,
QuicByteCount acked_bytes,
- QuicByteCount prior_in_flight) = 0;
+ QuicByteCount prior_in_flight,
+ QuicTime event_time) = 0;
// Called when a retransmission has occured which resulted in packets
// being retransmitted.
@@ -111,7 +113,8 @@ class NET_EXPORT_PRIVATE TcpCubicSenderBase : public SendAlgorithmInterface {
// TODO(ianswett): Remove these and migrate to OnCongestionEvent.
void OnPacketAcked(QuicPacketNumber acked_packet_number,
QuicByteCount acked_bytes,
- QuicByteCount prior_in_flight);
+ QuicByteCount prior_in_flight,
+ QuicTime event_time);
protected:
// TODO(rch): Make these private and clean up subclass access to them.
@@ -157,4 +160,4 @@ class NET_EXPORT_PRIVATE TcpCubicSenderBase : public SendAlgorithmInterface {
} // namespace net
-#endif // NET_QUIC_CONGESTION_CONTROL_TCP_CUBIC_SENDER_BASE_H_
+#endif // NET_QUIC_CORE_CONGESTION_CONTROL_TCP_CUBIC_SENDER_BASE_H_
diff --git a/chromium/net/quic/core/congestion_control/tcp_cubic_sender_bytes.cc b/chromium/net/quic/core/congestion_control/tcp_cubic_sender_bytes.cc
index f7932118497..94d3de2e249 100644
--- a/chromium/net/quic/core/congestion_control/tcp_cubic_sender_bytes.cc
+++ b/chromium/net/quic/core/congestion_control/tcp_cubic_sender_bytes.cc
@@ -5,16 +5,14 @@
#include "net/quic/core/congestion_control/tcp_cubic_sender_bytes.h"
#include <algorithm>
+#include <cstdint>
#include "net/quic/core/congestion_control/prr_sender.h"
#include "net/quic/core/congestion_control/rtt_stats.h"
#include "net/quic/core/crypto/crypto_protocol.h"
-#include "net/quic/core/proto/cached_network_parameters.pb.h"
-#include "net/quic/core/quic_bug_tracker.h"
#include "net/quic/core/quic_flags.h"
-
-using std::max;
-using std::min;
+#include "net/quic/platform/api/quic_bug_tracker.h"
+#include "net/quic/platform/api/quic_logging.h"
namespace net {
@@ -47,15 +45,35 @@ TcpCubicSenderBytes::TcpCubicSenderBytes(
TcpCubicSenderBytes::~TcpCubicSenderBytes() {}
+void TcpCubicSenderBytes::SetFromConfig(const QuicConfig& config,
+ Perspective perspective) {
+ TcpCubicSenderBase::SetFromConfig(config, perspective);
+ if (FLAGS_quic_reloadable_flag_quic_fix_cubic_convex_mode &&
+ config.HasReceivedConnectionOptions() &&
+ ContainsQuicTag(config.ReceivedConnectionOptions(), kCCVX)) {
+ cubic_.SetFixConvexMode(true);
+ }
+ if (FLAGS_quic_reloadable_flag_quic_fix_cubic_bytes_quantization &&
+ config.HasReceivedConnectionOptions() &&
+ ContainsQuicTag(config.ReceivedConnectionOptions(), kCBQT)) {
+ cubic_.SetFixCubicQuantization(true);
+ }
+ if (FLAGS_quic_reloadable_flag_quic_fix_beta_last_max &&
+ config.HasReceivedConnectionOptions() &&
+ ContainsQuicTag(config.ReceivedConnectionOptions(), kBLMX)) {
+ cubic_.SetFixBetaLastMax(true);
+ }
+}
+
void TcpCubicSenderBytes::SetCongestionWindowFromBandwidthAndRtt(
QuicBandwidth bandwidth,
QuicTime::Delta rtt) {
QuicByteCount new_congestion_window = bandwidth.ToBytesPerPeriod(rtt);
// Limit new CWND if needed.
congestion_window_ =
- max(min_congestion_window_,
- min(new_congestion_window,
- kMaxResumptionCongestionWindow * kDefaultTCPMSS));
+ std::max(min_congestion_window_,
+ std::min(new_congestion_window,
+ kMaxResumptionCongestionWindow * kDefaultTCPMSS));
}
void TcpCubicSenderBytes::SetCongestionWindowInPackets(
@@ -88,13 +106,13 @@ void TcpCubicSenderBytes::OnPacketLost(QuicPacketNumber packet_number,
stats_->slowstart_bytes_lost += lost_bytes;
if (slow_start_large_reduction_) {
// Reduce congestion window by lost_bytes for every loss.
- congestion_window_ =
- max(congestion_window_ - lost_bytes, min_slow_start_exit_window_);
+ congestion_window_ = std::max(congestion_window_ - lost_bytes,
+ min_slow_start_exit_window_);
slowstart_threshold_ = congestion_window_;
}
}
- DVLOG(1) << "Ignoring loss for largest_missing:" << packet_number
- << " because it was sent prior to the last CWND cutback.";
+ QUIC_DVLOG(1) << "Ignoring loss for largest_missing:" << packet_number
+ << " because it was sent prior to the last CWND cutback.";
return;
}
++stats_->tcp_loss_events;
@@ -128,8 +146,8 @@ void TcpCubicSenderBytes::OnPacketLost(QuicPacketNumber packet_number,
// Reset packet count from congestion avoidance mode. We start counting again
// when we're out of recovery.
num_acked_packets_ = 0;
- DVLOG(1) << "Incoming loss; congestion window: " << congestion_window_
- << " slowstart threshold: " << slowstart_threshold_;
+ QUIC_DVLOG(1) << "Incoming loss; congestion window: " << congestion_window_
+ << " slowstart threshold: " << slowstart_threshold_;
}
QuicByteCount TcpCubicSenderBytes::GetCongestionWindow() const {
@@ -145,7 +163,8 @@ QuicByteCount TcpCubicSenderBytes::GetSlowStartThreshold() const {
void TcpCubicSenderBytes::MaybeIncreaseCwnd(
QuicPacketNumber acked_packet_number,
QuicByteCount acked_bytes,
- QuicByteCount prior_in_flight) {
+ QuicByteCount prior_in_flight,
+ QuicTime event_time) {
QUIC_BUG_IF(InRecovery()) << "Never increase the CWND during recovery.";
// Do not increase the congestion window unless the sender is close to using
// the current window.
@@ -159,8 +178,8 @@ void TcpCubicSenderBytes::MaybeIncreaseCwnd(
if (InSlowStart()) {
// TCP slow start, exponential growth, increase by one for each ACK.
congestion_window_ += kDefaultTCPMSS;
- DVLOG(1) << "Slow start; congestion window: " << congestion_window_
- << " slowstart threshold: " << slowstart_threshold_;
+ QUIC_DVLOG(1) << "Slow start; congestion window: " << congestion_window_
+ << " slowstart threshold: " << slowstart_threshold_;
return;
}
// Congestion avoidance.
@@ -175,16 +194,16 @@ void TcpCubicSenderBytes::MaybeIncreaseCwnd(
num_acked_packets_ = 0;
}
- DVLOG(1) << "Reno; congestion window: " << congestion_window_
- << " slowstart threshold: " << slowstart_threshold_
- << " congestion window count: " << num_acked_packets_;
+ QUIC_DVLOG(1) << "Reno; congestion window: " << congestion_window_
+ << " slowstart threshold: " << slowstart_threshold_
+ << " congestion window count: " << num_acked_packets_;
} else {
- congestion_window_ =
- min(max_congestion_window_,
- cubic_.CongestionWindowAfterAck(acked_bytes, congestion_window_,
- rtt_stats_->min_rtt()));
- DVLOG(1) << "Cubic; congestion window: " << congestion_window_
- << " slowstart threshold: " << slowstart_threshold_;
+ congestion_window_ = std::min(
+ max_congestion_window_,
+ cubic_.CongestionWindowAfterAck(acked_bytes, congestion_window_,
+ rtt_stats_->min_rtt(), event_time));
+ QUIC_DVLOG(1) << "Cubic; congestion window: " << congestion_window_
+ << " slowstart threshold: " << slowstart_threshold_;
}
}
diff --git a/chromium/net/quic/core/congestion_control/tcp_cubic_sender_bytes.h b/chromium/net/quic/core/congestion_control/tcp_cubic_sender_bytes.h
index ab2a4c195ce..d49543f71a9 100644
--- a/chromium/net/quic/core/congestion_control/tcp_cubic_sender_bytes.h
+++ b/chromium/net/quic/core/congestion_control/tcp_cubic_sender_bytes.h
@@ -4,21 +4,21 @@
// TCP cubic send side congestion algorithm, emulates the behavior of TCP cubic.
-#ifndef NET_QUIC_CONGESTION_CONTROL_TCP_CUBIC_SENDER_BYTES_H_
-#define NET_QUIC_CONGESTION_CONTROL_TCP_CUBIC_SENDER_BYTES_H_
+#ifndef NET_QUIC_CORE_CONGESTION_CONTROL_TCP_CUBIC_SENDER_BYTES_H_
+#define NET_QUIC_CORE_CONGESTION_CONTROL_TCP_CUBIC_SENDER_BYTES_H_
-#include <stdint.h>
+#include <cstdint>
#include "base/macros.h"
-#include "net/base/net_export.h"
#include "net/quic/core/congestion_control/cubic_bytes.h"
#include "net/quic/core/congestion_control/hybrid_slow_start.h"
#include "net/quic/core/congestion_control/prr_sender.h"
#include "net/quic/core/congestion_control/tcp_cubic_sender_base.h"
#include "net/quic/core/quic_bandwidth.h"
#include "net/quic/core/quic_connection_stats.h"
-#include "net/quic/core/quic_protocol.h"
+#include "net/quic/core/quic_packets.h"
#include "net/quic/core/quic_time.h"
+#include "net/quic/platform/api/quic_export.h"
namespace net {
@@ -28,7 +28,7 @@ namespace test {
class TcpCubicSenderBytesPeer;
} // namespace test
-class NET_EXPORT_PRIVATE TcpCubicSenderBytes : public TcpCubicSenderBase {
+class QUIC_EXPORT_PRIVATE TcpCubicSenderBytes : public TcpCubicSenderBase {
public:
TcpCubicSenderBytes(const QuicClock* clock,
const RttStats* rtt_stats,
@@ -39,6 +39,8 @@ class NET_EXPORT_PRIVATE TcpCubicSenderBytes : public TcpCubicSenderBase {
~TcpCubicSenderBytes() override;
// Start implementation of SendAlgorithmInterface.
+ void SetFromConfig(const QuicConfig& config,
+ Perspective perspective) override;
void SetNumEmulatedConnections(int num_connections) override;
void OnConnectionMigration() override;
QuicByteCount GetCongestionWindow() const override;
@@ -61,7 +63,8 @@ class NET_EXPORT_PRIVATE TcpCubicSenderBytes : public TcpCubicSenderBase {
QuicByteCount prior_in_flight) override;
void MaybeIncreaseCwnd(QuicPacketNumber acked_packet_number,
QuicByteCount acked_bytes,
- QuicByteCount prior_in_flight) override;
+ QuicByteCount prior_in_flight,
+ QuicTime event_time) override;
void HandleRetransmissionTimeout() override;
private:
@@ -100,4 +103,4 @@ class NET_EXPORT_PRIVATE TcpCubicSenderBytes : public TcpCubicSenderBase {
} // namespace net
-#endif // NET_QUIC_CONGESTION_CONTROL_TCP_CUBIC_BYTES_SENDER_H_
+#endif // NET_QUIC_CORE_CONGESTION_CONTROL_TCP_CUBIC_SENDER_BYTES_H_
diff --git a/chromium/net/quic/core/congestion_control/tcp_cubic_sender_bytes_test.cc b/chromium/net/quic/core/congestion_control/tcp_cubic_sender_bytes_test.cc
index a4f012e0c9e..7c265e17324 100644
--- a/chromium/net/quic/core/congestion_control/tcp_cubic_sender_bytes_test.cc
+++ b/chromium/net/quic/core/congestion_control/tcp_cubic_sender_bytes_test.cc
@@ -8,17 +8,15 @@
#include <cstdint>
#include <memory>
-#include "base/logging.h"
#include "net/quic/core/congestion_control/rtt_stats.h"
#include "net/quic/core/congestion_control/send_algorithm_interface.h"
#include "net/quic/core/crypto/crypto_protocol.h"
#include "net/quic/core/proto/cached_network_parameters.pb.h"
-#include "net/quic/core/quic_flags.h"
-#include "net/quic/core/quic_protocol.h"
+#include "net/quic/core/quic_packets.h"
#include "net/quic/core/quic_utils.h"
+#include "net/quic/platform/api/quic_logging.h"
#include "net/quic/test_tools/mock_clock.h"
#include "net/quic/test_tools/quic_config_peer.h"
-#include "net/quic/test_tools/quic_test_utils.h"
#include "testing/gtest/include/gtest/gtest.h"
namespace net {
@@ -211,7 +209,7 @@ TEST_F(TcpCubicSenderBytesTest, SlowStartPacketLoss) {
// Recovery phase. We need to ack every packet in the recovery window before
// we exit recovery.
size_t number_of_packets_in_window = expected_send_window / kDefaultTCPMSS;
- DVLOG(1) << "number_packets: " << number_of_packets_in_window;
+ QUIC_DLOG(INFO) << "number_packets: " << number_of_packets_in_window;
AckNPackets(packets_in_recovery_window);
SendAvailableSendWindow();
EXPECT_EQ(expected_send_window, sender_->GetCongestionWindow());
@@ -273,7 +271,7 @@ TEST_F(TcpCubicSenderBytesTest, SlowStartPacketLossWithLargeReduction) {
// Recovery phase. We need to ack every packet in the recovery window before
// we exit recovery.
size_t number_of_packets_in_window = expected_send_window / kDefaultTCPMSS;
- DVLOG(1) << "number_packets: " << number_of_packets_in_window;
+ QUIC_DLOG(INFO) << "number_packets: " << number_of_packets_in_window;
AckNPackets(packets_in_recovery_window);
SendAvailableSendWindow();
EXPECT_EQ(expected_send_window, sender_->GetCongestionWindow());
@@ -849,7 +847,6 @@ TEST_F(TcpCubicSenderBytesTest, DefaultMaxCwnd) {
}
TEST_F(TcpCubicSenderBytesTest, LimitCwndIncreaseInCongestionAvoidance) {
- FLAGS_quic_limit_cubic_cwnd_increase = true;
// Enable Cubic.
sender_.reset(new TcpCubicSenderBytesPeer(&clock_, false));
diff --git a/chromium/net/quic/core/congestion_control/tcp_cubic_sender_packets.cc b/chromium/net/quic/core/congestion_control/tcp_cubic_sender_packets.cc
index 0a5d2656394..efee6d875cb 100644
--- a/chromium/net/quic/core/congestion_control/tcp_cubic_sender_packets.cc
+++ b/chromium/net/quic/core/congestion_control/tcp_cubic_sender_packets.cc
@@ -6,16 +6,12 @@
#include <algorithm>
-#include "base/metrics/histogram_macros.h"
#include "net/quic/core/congestion_control/prr_sender.h"
#include "net/quic/core/congestion_control/rtt_stats.h"
#include "net/quic/core/crypto/crypto_protocol.h"
-#include "net/quic/core/proto/cached_network_parameters.pb.h"
-#include "net/quic/core/quic_bug_tracker.h"
#include "net/quic/core/quic_flags.h"
-
-using std::max;
-using std::min;
+#include "net/quic/platform/api/quic_bug_tracker.h"
+#include "net/quic/platform/api/quic_logging.h"
namespace net {
@@ -46,6 +42,21 @@ TcpCubicSenderPackets::TcpCubicSenderPackets(
TcpCubicSenderPackets::~TcpCubicSenderPackets() {}
+void TcpCubicSenderPackets::SetFromConfig(const QuicConfig& config,
+ Perspective perspective) {
+ TcpCubicSenderBase::SetFromConfig(config, perspective);
+ if (FLAGS_quic_reloadable_flag_quic_fix_cubic_convex_mode &&
+ config.HasReceivedConnectionOptions() &&
+ ContainsQuicTag(config.ReceivedConnectionOptions(), kCCVX)) {
+ cubic_.SetFixConvexMode(true);
+ }
+ if (FLAGS_quic_reloadable_flag_quic_fix_beta_last_max &&
+ config.HasReceivedConnectionOptions() &&
+ ContainsQuicTag(config.ReceivedConnectionOptions(), kBLMX)) {
+ cubic_.SetFixBetaLastMax(true);
+ }
+}
+
void TcpCubicSenderPackets::SetCongestionWindowFromBandwidthAndRtt(
QuicBandwidth bandwidth,
QuicTime::Delta rtt) {
@@ -53,8 +64,8 @@ void TcpCubicSenderPackets::SetCongestionWindowFromBandwidthAndRtt(
bandwidth.ToBytesPerPeriod(rtt) / kDefaultTCPMSS;
// Limit new CWND to be in the range [1, kMaxCongestionWindow].
congestion_window_ =
- max(min_congestion_window_,
- min(new_congestion_window, kMaxResumptionCongestionWindow));
+ std::max(min_congestion_window_,
+ std::min(new_congestion_window, kMaxResumptionCongestionWindow));
}
void TcpCubicSenderPackets::SetCongestionWindowInPackets(
@@ -91,13 +102,13 @@ void TcpCubicSenderPackets::OnPacketLost(QuicPacketNumber packet_number,
(stats_->slowstart_bytes_lost - lost_bytes) / kDefaultTCPMSS) {
// Reduce congestion window by 1 for every mss of bytes lost.
congestion_window_ =
- max(congestion_window_ - 1, min_slow_start_exit_window_);
+ std::max(congestion_window_ - 1, min_slow_start_exit_window_);
}
slowstart_threshold_ = congestion_window_;
}
}
- DVLOG(1) << "Ignoring loss for largest_missing:" << packet_number
- << " because it was sent prior to the last CWND cutback.";
+ QUIC_DVLOG(1) << "Ignoring loss for largest_missing:" << packet_number
+ << " because it was sent prior to the last CWND cutback.";
return;
}
++stats_->tcp_loss_events;
@@ -132,8 +143,8 @@ void TcpCubicSenderPackets::OnPacketLost(QuicPacketNumber packet_number,
// reset packet count from congestion avoidance mode. We start
// counting again when we're out of recovery.
congestion_window_count_ = 0;
- DVLOG(1) << "Incoming loss; congestion window: " << congestion_window_
- << " slowstart threshold: " << slowstart_threshold_;
+ QUIC_DVLOG(1) << "Incoming loss; congestion window: " << congestion_window_
+ << " slowstart threshold: " << slowstart_threshold_;
}
QuicByteCount TcpCubicSenderPackets::GetCongestionWindow() const {
@@ -149,7 +160,8 @@ QuicByteCount TcpCubicSenderPackets::GetSlowStartThreshold() const {
void TcpCubicSenderPackets::MaybeIncreaseCwnd(
QuicPacketNumber acked_packet_number,
QuicByteCount /*acked_bytes*/,
- QuicByteCount prior_in_flight) {
+ QuicByteCount prior_in_flight,
+ QuicTime event_time) {
QUIC_BUG_IF(InRecovery()) << "Never increase the CWND during recovery.";
// Do not increase the congestion window unless the sender is close to using
// the current window.
@@ -163,8 +175,8 @@ void TcpCubicSenderPackets::MaybeIncreaseCwnd(
if (InSlowStart()) {
// TCP slow start, exponential growth, increase by one for each ACK.
++congestion_window_;
- DVLOG(1) << "Slow start; congestion window: " << congestion_window_
- << " slowstart threshold: " << slowstart_threshold_;
+ QUIC_DVLOG(1) << "Slow start; congestion window: " << congestion_window_
+ << " slowstart threshold: " << slowstart_threshold_;
return;
}
// Congestion avoidance
@@ -178,15 +190,16 @@ void TcpCubicSenderPackets::MaybeIncreaseCwnd(
congestion_window_count_ = 0;
}
- DVLOG(1) << "Reno; congestion window: " << congestion_window_
- << " slowstart threshold: " << slowstart_threshold_
- << " congestion window count: " << congestion_window_count_;
+ QUIC_DVLOG(1) << "Reno; congestion window: " << congestion_window_
+ << " slowstart threshold: " << slowstart_threshold_
+ << " congestion window count: " << congestion_window_count_;
} else {
- congestion_window_ = min(max_tcp_congestion_window_,
- cubic_.CongestionWindowAfterAck(
- congestion_window_, rtt_stats_->min_rtt()));
- DVLOG(1) << "Cubic; congestion window: " << congestion_window_
- << " slowstart threshold: " << slowstart_threshold_;
+ congestion_window_ =
+ std::min(max_tcp_congestion_window_,
+ cubic_.CongestionWindowAfterAck(
+ congestion_window_, rtt_stats_->min_rtt(), event_time));
+ QUIC_DVLOG(1) << "Cubic; congestion window: " << congestion_window_
+ << " slowstart threshold: " << slowstart_threshold_;
}
}
diff --git a/chromium/net/quic/core/congestion_control/tcp_cubic_sender_packets.h b/chromium/net/quic/core/congestion_control/tcp_cubic_sender_packets.h
index 8cb21dbcd0f..cf0a29719f2 100644
--- a/chromium/net/quic/core/congestion_control/tcp_cubic_sender_packets.h
+++ b/chromium/net/quic/core/congestion_control/tcp_cubic_sender_packets.h
@@ -4,22 +4,22 @@
//
// TCP cubic send side congestion algorithm, emulates the behavior of TCP cubic.
-#ifndef NET_QUIC_CONGESTION_CONTROL_TCP_CUBIC_SENDER_PACKETS_H_
-#define NET_QUIC_CONGESTION_CONTROL_TCP_CUBIC_SENDER_PACKETS_H_
+#ifndef NET_QUIC_CORE_CONGESTION_CONTROL_TCP_CUBIC_SENDER_PACKETS_H_
+#define NET_QUIC_CORE_CONGESTION_CONTROL_TCP_CUBIC_SENDER_PACKETS_H_
-#include <stdint.h>
+#include <cstdint>
#include "base/compiler_specific.h"
#include "base/macros.h"
-#include "net/base/net_export.h"
#include "net/quic/core/congestion_control/cubic.h"
#include "net/quic/core/congestion_control/hybrid_slow_start.h"
#include "net/quic/core/congestion_control/prr_sender.h"
#include "net/quic/core/congestion_control/tcp_cubic_sender_base.h"
#include "net/quic/core/quic_bandwidth.h"
#include "net/quic/core/quic_connection_stats.h"
-#include "net/quic/core/quic_protocol.h"
+#include "net/quic/core/quic_packets.h"
#include "net/quic/core/quic_time.h"
+#include "net/quic/platform/api/quic_export.h"
namespace net {
@@ -29,7 +29,7 @@ namespace test {
class TcpCubicSenderPacketsPeer;
} // namespace test
-class NET_EXPORT_PRIVATE TcpCubicSenderPackets : public TcpCubicSenderBase {
+class QUIC_EXPORT_PRIVATE TcpCubicSenderPackets : public TcpCubicSenderBase {
public:
// Reno option and max_tcp_congestion_window are provided for testing.
TcpCubicSenderPackets(const QuicClock* clock,
@@ -41,6 +41,8 @@ class NET_EXPORT_PRIVATE TcpCubicSenderPackets : public TcpCubicSenderBase {
~TcpCubicSenderPackets() override;
// Start implementation of SendAlgorithmInterface.
+ void SetFromConfig(const QuicConfig& config,
+ Perspective perspective) override;
void SetNumEmulatedConnections(int num_connections) override;
void OnConnectionMigration() override;
QuicByteCount GetCongestionWindow() const override;
@@ -63,7 +65,8 @@ class NET_EXPORT_PRIVATE TcpCubicSenderPackets : public TcpCubicSenderBase {
QuicByteCount prior_in_flight) override;
void MaybeIncreaseCwnd(QuicPacketNumber acked_packet_number,
QuicByteCount acked_bytes,
- QuicByteCount prior_in_flight) override;
+ QuicByteCount prior_in_flight,
+ QuicTime event_time) override;
void HandleRetransmissionTimeout() override;
private:
@@ -102,4 +105,4 @@ class NET_EXPORT_PRIVATE TcpCubicSenderPackets : public TcpCubicSenderBase {
} // namespace net
-#endif // NET_QUIC_CONGESTION_CONTROL_TCP_CUBIC_SENDER_H_
+#endif // NET_QUIC_CORE_CONGESTION_CONTROL_TCP_CUBIC_SENDER_PACKETS_H_
diff --git a/chromium/net/quic/core/congestion_control/tcp_cubic_sender_packets_test.cc b/chromium/net/quic/core/congestion_control/tcp_cubic_sender_packets_test.cc
index d56d394a671..2b4cfa6577b 100644
--- a/chromium/net/quic/core/congestion_control/tcp_cubic_sender_packets_test.cc
+++ b/chromium/net/quic/core/congestion_control/tcp_cubic_sender_packets_test.cc
@@ -7,21 +7,17 @@
#include <algorithm>
#include <memory>
-#include "base/logging.h"
#include "net/quic/core/congestion_control/rtt_stats.h"
#include "net/quic/core/congestion_control/send_algorithm_interface.h"
#include "net/quic/core/crypto/crypto_protocol.h"
#include "net/quic/core/proto/cached_network_parameters.pb.h"
-#include "net/quic/core/quic_flags.h"
-#include "net/quic/core/quic_protocol.h"
+#include "net/quic/core/quic_packets.h"
#include "net/quic/core/quic_utils.h"
+#include "net/quic/platform/api/quic_logging.h"
#include "net/quic/test_tools/mock_clock.h"
#include "net/quic/test_tools/quic_config_peer.h"
-#include "net/quic/test_tools/quic_test_utils.h"
#include "testing/gtest/include/gtest/gtest.h"
-using std::min;
-
namespace net {
namespace test {
@@ -135,7 +131,6 @@ class TcpCubicSenderPacketsTest : public ::testing::Test {
bytes_in_flight_ -= kDefaultTCPMSS;
}
- QuicFlagSaver flags_; // Save/restore all QUIC flag values.
const QuicTime::Delta one_ms_;
MockClock clock_;
std::unique_ptr<TcpCubicSenderPacketsPeer> sender_;
@@ -223,7 +218,7 @@ TEST_F(TcpCubicSenderPacketsTest, SlowStartPacketLoss) {
// Recovery phase. We need to ack every packet in the recovery window before
// we exit recovery.
size_t number_of_packets_in_window = expected_send_window / kDefaultTCPMSS;
- DVLOG(1) << "number_packets: " << number_of_packets_in_window;
+ QUIC_DLOG(INFO) << "number_packets: " << number_of_packets_in_window;
AckNPackets(packets_in_recovery_window);
SendAvailableSendWindow();
EXPECT_EQ(expected_send_window, sender_->GetCongestionWindow());
@@ -285,7 +280,7 @@ TEST_F(TcpCubicSenderPacketsTest, SlowStartPacketLossWithLargeReduction) {
// Recovery phase. We need to ack every packet in the recovery window before
// we exit recovery.
size_t number_of_packets_in_window = expected_send_window / kDefaultTCPMSS;
- DVLOG(1) << "number_packets: " << number_of_packets_in_window;
+ QUIC_DLOG(INFO) << "number_packets: " << number_of_packets_in_window;
AckNPackets(packets_in_recovery_window);
SendAvailableSendWindow();
EXPECT_EQ(expected_send_window, sender_->GetCongestionWindow());
@@ -958,7 +953,6 @@ TEST_F(TcpCubicSenderPacketsTest, DefaultMaxCwnd) {
}
TEST_F(TcpCubicSenderPacketsTest, LimitCwndIncreaseInCongestionAvoidance) {
- FLAGS_quic_limit_cubic_cwnd_increase = true;
// Enable Cubic.
sender_.reset(new TcpCubicSenderPacketsPeer(
&clock_, false, kDefaultMaxCongestionWindowPackets));
diff --git a/chromium/net/quic/core/congestion_control/windowed_filter.h b/chromium/net/quic/core/congestion_control/windowed_filter.h
index 4012cb2b5c5..451164950b0 100644
--- a/chromium/net/quic/core/congestion_control/windowed_filter.h
+++ b/chromium/net/quic/core/congestion_control/windowed_filter.h
@@ -2,8 +2,8 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
//
-#ifndef NET_QUIC_CONGESTION_CONTROL_WINDOWED_FILTER_H_
-#define NET_QUIC_CONGESTION_CONTROL_WINDOWED_FILTER_H_
+#ifndef NET_QUIC_CORE_CONGESTION_CONTROL_WINDOWED_FILTER_H_
+#define NET_QUIC_CORE_CONGESTION_CONTROL_WINDOWED_FILTER_H_
// Implements Kathleen Nichols' algorithm for tracking the minimum (or maximum)
// estimate of a stream of samples over some fixed time interval. (E.g.,
@@ -31,7 +31,6 @@
// turn is replaced by the third best. The newest sample replaces the third
// best.
-#include "base/logging.h"
#include "net/quic/core/quic_time.h"
namespace net {
@@ -153,4 +152,4 @@ class WindowedFilter {
} // namespace net
-#endif // NET_QUIC_CONGESTION_CONTROL_WINDOWED_FILTER_H_
+#endif // NET_QUIC_CORE_CONGESTION_CONTROL_WINDOWED_FILTER_H_
diff --git a/chromium/net/quic/core/congestion_control/windowed_filter_test.cc b/chromium/net/quic/core/congestion_control/windowed_filter_test.cc
index 92a8f60708a..38c0658a1bc 100644
--- a/chromium/net/quic/core/congestion_control/windowed_filter_test.cc
+++ b/chromium/net/quic/core/congestion_control/windowed_filter_test.cc
@@ -4,15 +4,13 @@
//
#include "net/quic/core/congestion_control/windowed_filter.h"
-#include "base/logging.h"
#include "net/quic/core/congestion_control/rtt_stats.h"
#include "net/quic/core/quic_bandwidth.h"
-#include "net/quic/core/quic_protocol.h"
+#include "net/quic/core/quic_packets.h"
#include "testing/gtest/include/gtest/gtest.h"
namespace net {
namespace test {
-namespace {
class WindowedFilterTest : public ::testing::Test {
public:
@@ -182,7 +180,6 @@ TEST_F(WindowedFilterTest, SampleChangesThirdBestMin) {
// Latest sample was recorded at 100ms.
QuicTime now = QuicTime::Zero() + QuicTime::Delta::FromMilliseconds(101);
windowed_min_rtt_.Update(rtt_sample, now);
- windowed_min_rtt_.Update(rtt_sample, now);
EXPECT_EQ(rtt_sample, windowed_min_rtt_.GetThirdBest());
EXPECT_EQ(QuicTime::Delta::FromMilliseconds(40),
windowed_min_rtt_.GetSecondBest());
@@ -328,7 +325,6 @@ TEST_F(WindowedFilterTest, ExpireAllMins) {
// See crbug/616957
ASSERT_LT(windowed_min_rtt_.GetThirdBest(),
QuicTime::Delta::Infinite() - QuicTime::Delta::FromMilliseconds(5));
-
// Third best min sample was recorded at 100ms, so expiry time is 199ms.
QuicTime now = QuicTime::Zero() + QuicTime::Delta::FromMilliseconds(200);
windowed_min_rtt_.Update(rtt_sample, now);
@@ -357,8 +353,8 @@ TEST_F(WindowedFilterTest, ExpireCounterBasedMax) {
WindowedFilter<uint64_t, MaxFilter<uint64_t>, uint64_t, uint64_t> max_filter(
2, 0, 0);
- // Insert 50000 at t = 1.
const uint64_t kBest = 50000;
+ // Insert 50000 at t = 1.
max_filter.Update(50000, 1);
EXPECT_EQ(kBest, max_filter.GetBest());
UpdateWithIrrelevantSamples(&max_filter, 20, 1);
@@ -387,6 +383,5 @@ TEST_F(WindowedFilterTest, ExpireCounterBasedMax) {
EXPECT_EQ(kNewBest, max_filter.GetBest());
}
-} // namespace
} // namespace test
} // namespace net
diff --git a/chromium/net/quic/core/crypto/aead_base_decrypter.cc b/chromium/net/quic/core/crypto/aead_base_decrypter.cc
index 1da2261fca5..57984245c7a 100644
--- a/chromium/net/quic/core/crypto/aead_base_decrypter.cc
+++ b/chromium/net/quic/core/crypto/aead_base_decrypter.cc
@@ -4,11 +4,11 @@
#include "net/quic/core/crypto/aead_base_decrypter.h"
-#include <memory>
+#include <cstdint>
-#include "net/quic/core/quic_bug_tracker.h"
-#include "net/quic/core/quic_flags.h"
#include "net/quic/core/quic_utils.h"
+#include "net/quic/platform/api/quic_bug_tracker.h"
+#include "net/quic/platform/api/quic_logging.h"
#include "third_party/boringssl/src/include/openssl/err.h"
#include "third_party/boringssl/src/include/openssl/evp.h"
@@ -34,7 +34,7 @@ void DLogOpenSslErrors() {
while (uint32_t error = ERR_get_error()) {
char buf[120];
ERR_error_string_n(error, buf, arraysize(buf));
- DLOG(ERROR) << "OpenSSL error: " << buf;
+ QUIC_DLOG(ERROR) << "OpenSSL error: " << buf;
}
#endif
}
@@ -115,7 +115,8 @@ bool AeadBaseDecrypter::SetDiversificationNonce(
return true;
}
-bool AeadBaseDecrypter::DecryptPacket(QuicPathId path_id,
+bool AeadBaseDecrypter::DecryptPacket(QuicVersion /*version*/,
+ QuicPathId path_id,
QuicPacketNumber packet_number,
StringPiece associated_data,
StringPiece ciphertext,
diff --git a/chromium/net/quic/core/crypto/aead_base_decrypter.h b/chromium/net/quic/core/crypto/aead_base_decrypter.h
index f6da359b806..58f8fb595d8 100644
--- a/chromium/net/quic/core/crypto/aead_base_decrypter.h
+++ b/chromium/net/quic/core/crypto/aead_base_decrypter.h
@@ -2,21 +2,21 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#ifndef NET_QUIC_CRYPTO_AEAD_BASE_DECRYPTER_H_
-#define NET_QUIC_CRYPTO_AEAD_BASE_DECRYPTER_H_
+#ifndef NET_QUIC_CORE_CRYPTO_AEAD_BASE_DECRYPTER_H_
+#define NET_QUIC_CORE_CRYPTO_AEAD_BASE_DECRYPTER_H_
-#include <stddef.h>
+#include <cstddef>
#include "base/compiler_specific.h"
#include "base/macros.h"
-#include "net/base/net_export.h"
#include "net/quic/core/crypto/quic_decrypter.h"
#include "net/quic/core/crypto/scoped_evp_aead_ctx.h"
+#include "net/quic/platform/api/quic_export.h"
namespace net {
// AeadBaseDecrypter is the base class of AEAD QuicDecrypter subclasses.
-class NET_EXPORT_PRIVATE AeadBaseDecrypter : public QuicDecrypter {
+class QUIC_EXPORT_PRIVATE AeadBaseDecrypter : public QuicDecrypter {
public:
AeadBaseDecrypter(const EVP_AEAD* aead_alg,
size_t key_size,
@@ -29,7 +29,8 @@ class NET_EXPORT_PRIVATE AeadBaseDecrypter : public QuicDecrypter {
bool SetNoncePrefix(base::StringPiece nonce_prefix) override;
bool SetPreliminaryKey(base::StringPiece key) override;
bool SetDiversificationNonce(const DiversificationNonce& nonce) override;
- bool DecryptPacket(QuicPathId path_id,
+ bool DecryptPacket(QuicVersion version,
+ QuicPathId path_id,
QuicPacketNumber packet_number,
base::StringPiece associated_data,
base::StringPiece ciphertext,
@@ -65,4 +66,4 @@ class NET_EXPORT_PRIVATE AeadBaseDecrypter : public QuicDecrypter {
} // namespace net
-#endif // NET_QUIC_CRYPTO_AEAD_BASE_DECRYPTER_H_
+#endif // NET_QUIC_CORE_CRYPTO_AEAD_BASE_DECRYPTER_H_
diff --git a/chromium/net/quic/core/crypto/aead_base_encrypter.cc b/chromium/net/quic/core/crypto/aead_base_encrypter.cc
index 477810fc6ee..1420b009b16 100644
--- a/chromium/net/quic/core/crypto/aead_base_encrypter.cc
+++ b/chromium/net/quic/core/crypto/aead_base_encrypter.cc
@@ -2,13 +2,13 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#include <string.h>
+#include "net/quic/core/crypto/aead_base_encrypter.h"
-#include <memory>
+#include <string>
-#include "net/quic/core/crypto/aead_base_encrypter.h"
-#include "net/quic/core/quic_flags.h"
#include "net/quic/core/quic_utils.h"
+#include "net/quic/platform/api/quic_aligned.h"
+#include "net/quic/platform/api/quic_logging.h"
#include "third_party/boringssl/src/include/openssl/err.h"
#include "third_party/boringssl/src/include/openssl/evp.h"
@@ -32,7 +32,7 @@ void DLogOpenSslErrors() {
while (unsigned long error = ERR_get_error()) {
char buf[120];
ERR_error_string_n(error, buf, arraysize(buf));
- DLOG(ERROR) << "OpenSSL error: " << buf;
+ QUIC_DLOG(ERROR) << "OpenSSL error: " << buf;
}
#endif
}
@@ -85,9 +85,7 @@ bool AeadBaseEncrypter::Encrypt(StringPiece nonce,
StringPiece associated_data,
StringPiece plaintext,
unsigned char* output) {
- if (nonce.size() != nonce_prefix_size_ + sizeof(QuicPacketNumber)) {
- return false;
- }
+ DCHECK_EQ(nonce.size(), nonce_prefix_size_ + sizeof(QuicPacketNumber));
size_t ciphertext_len;
if (!EVP_AEAD_CTX_seal(
@@ -104,7 +102,8 @@ bool AeadBaseEncrypter::Encrypt(StringPiece nonce,
return true;
}
-bool AeadBaseEncrypter::EncryptPacket(QuicPathId path_id,
+bool AeadBaseEncrypter::EncryptPacket(QuicVersion /*version*/,
+ QuicPathId path_id,
QuicPacketNumber packet_number,
StringPiece associated_data,
StringPiece plaintext,
@@ -118,7 +117,7 @@ bool AeadBaseEncrypter::EncryptPacket(QuicPathId path_id,
// TODO(ianswett): Introduce a check to ensure that we don't encrypt with the
// same packet number twice.
const size_t nonce_size = nonce_prefix_size_ + sizeof(packet_number);
- ALIGNAS(4) char nonce_buffer[kMaxNonceSize];
+ QUIC_ALIGNED(4) char nonce_buffer[kMaxNonceSize];
memcpy(nonce_buffer, nonce_prefix_, nonce_prefix_size_);
uint64_t path_id_packet_number =
QuicUtils::PackPathIdAndPacketNumber(path_id, packet_number);
diff --git a/chromium/net/quic/core/crypto/aead_base_encrypter.h b/chromium/net/quic/core/crypto/aead_base_encrypter.h
index 4e2c68ad139..7636276681d 100644
--- a/chromium/net/quic/core/crypto/aead_base_encrypter.h
+++ b/chromium/net/quic/core/crypto/aead_base_encrypter.h
@@ -2,21 +2,21 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#ifndef NET_QUIC_CRYPTO_AEAD_BASE_ENCRYPTER_H_
-#define NET_QUIC_CRYPTO_AEAD_BASE_ENCRYPTER_H_
+#ifndef NET_QUIC_CORE_CRYPTO_AEAD_BASE_ENCRYPTER_H_
+#define NET_QUIC_CORE_CRYPTO_AEAD_BASE_ENCRYPTER_H_
-#include <stddef.h>
+#include <cstddef>
#include "base/compiler_specific.h"
#include "base/macros.h"
-#include "net/base/net_export.h"
#include "net/quic/core/crypto/quic_encrypter.h"
#include "net/quic/core/crypto/scoped_evp_aead_ctx.h"
+#include "net/quic/platform/api/quic_export.h"
namespace net {
// AeadBaseEncrypter is the base class of AEAD QuicEncrypter subclasses.
-class NET_EXPORT_PRIVATE AeadBaseEncrypter : public QuicEncrypter {
+class QUIC_EXPORT_PRIVATE AeadBaseEncrypter : public QuicEncrypter {
public:
AeadBaseEncrypter(const EVP_AEAD* aead_alg,
size_t key_size,
@@ -27,7 +27,8 @@ class NET_EXPORT_PRIVATE AeadBaseEncrypter : public QuicEncrypter {
// QuicEncrypter implementation
bool SetKey(base::StringPiece key) override;
bool SetNoncePrefix(base::StringPiece nonce_prefix) override;
- bool EncryptPacket(QuicPathId path_id,
+ bool EncryptPacket(QuicVersion version,
+ QuicPathId path_id,
QuicPacketNumber packet_number,
base::StringPiece associated_data,
base::StringPiece plaintext,
@@ -73,4 +74,4 @@ class NET_EXPORT_PRIVATE AeadBaseEncrypter : public QuicEncrypter {
} // namespace net
-#endif // NET_QUIC_CRYPTO_AEAD_BASE_ENCRYPTER_H_
+#endif // NET_QUIC_CORE_CRYPTO_AEAD_BASE_ENCRYPTER_H_
diff --git a/chromium/net/quic/core/crypto/aes_128_gcm_12_decrypter.h b/chromium/net/quic/core/crypto/aes_128_gcm_12_decrypter.h
index 58d992b5508..f568c2ef252 100644
--- a/chromium/net/quic/core/crypto/aes_128_gcm_12_decrypter.h
+++ b/chromium/net/quic/core/crypto/aes_128_gcm_12_decrypter.h
@@ -2,15 +2,14 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#ifndef NET_QUIC_CRYPTO_AES_128_GCM_12_DECRYPTER_H_
-#define NET_QUIC_CRYPTO_AES_128_GCM_12_DECRYPTER_H_
+#ifndef NET_QUIC_CORE_CRYPTO_AES_128_GCM_12_DECRYPTER_H_
+#define NET_QUIC_CORE_CRYPTO_AES_128_GCM_12_DECRYPTER_H_
-#include <stddef.h>
-#include <stdint.h>
+#include <cstdint>
#include "base/macros.h"
-#include "net/base/net_export.h"
#include "net/quic/core/crypto/aead_base_decrypter.h"
+#include "net/quic/platform/api/quic_export.h"
namespace net {
@@ -20,7 +19,7 @@ namespace net {
//
// It uses an authentication tag of 12 bytes (96 bits). The fixed prefix
// of the nonce is four bytes.
-class NET_EXPORT_PRIVATE Aes128Gcm12Decrypter : public AeadBaseDecrypter {
+class QUIC_EXPORT_PRIVATE Aes128Gcm12Decrypter : public AeadBaseDecrypter {
public:
enum {
// Authentication tags are truncated to 96 bits.
@@ -39,4 +38,4 @@ class NET_EXPORT_PRIVATE Aes128Gcm12Decrypter : public AeadBaseDecrypter {
} // namespace net
-#endif // NET_QUIC_CRYPTO_AES_128_GCM_12_DECRYPTER_H_
+#endif // NET_QUIC_CORE_CRYPTO_AES_128_GCM_12_DECRYPTER_H_
diff --git a/chromium/net/quic/core/crypto/aes_128_gcm_12_decrypter_test.cc b/chromium/net/quic/core/crypto/aes_128_gcm_12_decrypter_test.cc
index 64e8f30bc10..4a04d21af3d 100644
--- a/chromium/net/quic/core/crypto/aes_128_gcm_12_decrypter_test.cc
+++ b/chromium/net/quic/core/crypto/aes_128_gcm_12_decrypter_test.cc
@@ -6,8 +6,8 @@
#include <memory>
-#include "net/quic/core/quic_flags.h"
#include "net/quic/core/quic_utils.h"
+#include "net/quic/platform/api/quic_text_utils.h"
#include "net/quic/test_tools/quic_test_utils.h"
using base::StringPiece;
@@ -215,8 +215,8 @@ QuicData* DecryptWithNonce(Aes128Gcm12Decrypter* decrypter,
std::unique_ptr<char[]> output(new char[ciphertext.length()]);
size_t output_length = 0;
const bool success = decrypter->DecryptPacket(
- path_id, packet_number, associated_data, ciphertext, output.get(),
- &output_length, ciphertext.length());
+ QuicVersionMax(), path_id, packet_number, associated_data, ciphertext,
+ output.get(), &output_length, ciphertext.length());
if (!success) {
return nullptr;
}
@@ -233,14 +233,14 @@ TEST(Aes128Gcm12DecrypterTest, Decrypt) {
bool has_pt = test_vectors[j].pt;
// Decode the test vector.
- string key = QuicUtils::HexDecode(test_vectors[j].key);
- string iv = QuicUtils::HexDecode(test_vectors[j].iv);
- string ct = QuicUtils::HexDecode(test_vectors[j].ct);
- string aad = QuicUtils::HexDecode(test_vectors[j].aad);
- string tag = QuicUtils::HexDecode(test_vectors[j].tag);
+ string key = QuicTextUtils::HexDecode(test_vectors[j].key);
+ string iv = QuicTextUtils::HexDecode(test_vectors[j].iv);
+ string ct = QuicTextUtils::HexDecode(test_vectors[j].ct);
+ string aad = QuicTextUtils::HexDecode(test_vectors[j].aad);
+ string tag = QuicTextUtils::HexDecode(test_vectors[j].tag);
string pt;
if (has_pt) {
- pt = QuicUtils::HexDecode(test_vectors[j].pt);
+ pt = QuicTextUtils::HexDecode(test_vectors[j].pt);
}
// The test vector's lengths should look sane. Note that the lengths
diff --git a/chromium/net/quic/core/crypto/aes_128_gcm_12_encrypter.h b/chromium/net/quic/core/crypto/aes_128_gcm_12_encrypter.h
index 70b86237f5a..4ee5e47eeef 100644
--- a/chromium/net/quic/core/crypto/aes_128_gcm_12_encrypter.h
+++ b/chromium/net/quic/core/crypto/aes_128_gcm_12_encrypter.h
@@ -2,14 +2,12 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#ifndef NET_QUIC_CRYPTO_AES_128_GCM_12_ENCRYPTER_H_
-#define NET_QUIC_CRYPTO_AES_128_GCM_12_ENCRYPTER_H_
-
-#include <stddef.h>
+#ifndef NET_QUIC_CORE_CRYPTO_AES_128_GCM_12_ENCRYPTER_H_
+#define NET_QUIC_CORE_CRYPTO_AES_128_GCM_12_ENCRYPTER_H_
#include "base/macros.h"
-#include "net/base/net_export.h"
#include "net/quic/core/crypto/aead_base_encrypter.h"
+#include "net/quic/platform/api/quic_export.h"
namespace net {
@@ -19,7 +17,7 @@ namespace net {
//
// It uses an authentication tag of 12 bytes (96 bits). The fixed prefix
// of the nonce is four bytes.
-class NET_EXPORT_PRIVATE Aes128Gcm12Encrypter : public AeadBaseEncrypter {
+class QUIC_EXPORT_PRIVATE Aes128Gcm12Encrypter : public AeadBaseEncrypter {
public:
enum {
// Authentication tags are truncated to 96 bits.
@@ -35,4 +33,4 @@ class NET_EXPORT_PRIVATE Aes128Gcm12Encrypter : public AeadBaseEncrypter {
} // namespace net
-#endif // NET_QUIC_CRYPTO_AES_128_GCM_12_ENCRYPTER_H_
+#endif // NET_QUIC_CORE_CRYPTO_AES_128_GCM_12_ENCRYPTER_H_
diff --git a/chromium/net/quic/core/crypto/aes_128_gcm_12_encrypter_test.cc b/chromium/net/quic/core/crypto/aes_128_gcm_12_encrypter_test.cc
index 037d90f77e0..9236329b8a8 100644
--- a/chromium/net/quic/core/crypto/aes_128_gcm_12_encrypter_test.cc
+++ b/chromium/net/quic/core/crypto/aes_128_gcm_12_encrypter_test.cc
@@ -7,6 +7,7 @@
#include <memory>
#include "net/quic/core/quic_utils.h"
+#include "net/quic/platform/api/quic_text_utils.h"
#include "net/quic/test_tools/quic_test_utils.h"
using base::StringPiece;
@@ -178,12 +179,12 @@ TEST(Aes128Gcm12EncrypterTest, Encrypt) {
const TestGroupInfo& test_info = test_group_info[i];
for (size_t j = 0; test_vectors[j].key != nullptr; j++) {
// Decode the test vector.
- string key = QuicUtils::HexDecode(test_vectors[j].key);
- string iv = QuicUtils::HexDecode(test_vectors[j].iv);
- string pt = QuicUtils::HexDecode(test_vectors[j].pt);
- string aad = QuicUtils::HexDecode(test_vectors[j].aad);
- string ct = QuicUtils::HexDecode(test_vectors[j].ct);
- string tag = QuicUtils::HexDecode(test_vectors[j].tag);
+ string key = QuicTextUtils::HexDecode(test_vectors[j].key);
+ string iv = QuicTextUtils::HexDecode(test_vectors[j].iv);
+ string pt = QuicTextUtils::HexDecode(test_vectors[j].pt);
+ string aad = QuicTextUtils::HexDecode(test_vectors[j].aad);
+ string ct = QuicTextUtils::HexDecode(test_vectors[j].ct);
+ string tag = QuicTextUtils::HexDecode(test_vectors[j].tag);
// The test vector's lengths should look sane. Note that the lengths
// in |test_info| are in bits.
diff --git a/chromium/net/quic/core/crypto/cert_compressor.cc b/chromium/net/quic/core/crypto/cert_compressor.cc
index 0e0ca063a37..522ce311af3 100644
--- a/chromium/net/quic/core/crypto/cert_compressor.cc
+++ b/chromium/net/quic/core/crypto/cert_compressor.cc
@@ -7,7 +7,6 @@
#include <cstdint>
#include <memory>
-#include "base/logging.h"
#include "net/quic/core/quic_utils.h"
#include "third_party/zlib/zlib.h"
@@ -194,7 +193,7 @@ std::vector<CertEntry> MatchCerts(const std::vector<string>& certs,
if (cached_valid) {
bool cached = false;
- uint64_t hash = QuicUtils::FNV1a_64_Hash(i->data(), i->size());
+ uint64_t hash = QuicUtils::FNV1a_64_Hash(*i);
// This assumes that the machine is little-endian.
for (size_t j = 0; j < client_cached_cert_hashes.size();
j += sizeof(uint64_t)) {
@@ -325,7 +324,7 @@ std::vector<uint64_t> HashCerts(const std::vector<string>& certs) {
for (std::vector<string>::const_iterator i = certs.begin(); i != certs.end();
++i) {
- ret.push_back(QuicUtils::FNV1a_64_Hash(i->data(), i->size()));
+ ret.push_back(QuicUtils::FNV1a_64_Hash(*i));
}
return ret;
diff --git a/chromium/net/quic/core/crypto/cert_compressor.h b/chromium/net/quic/core/crypto/cert_compressor.h
index f43df1a67ec..7e0031ca253 100644
--- a/chromium/net/quic/core/crypto/cert_compressor.h
+++ b/chromium/net/quic/core/crypto/cert_compressor.h
@@ -2,17 +2,17 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#ifndef NET_QUIC_CRYPTO_CERT_COMPRESSOR_H_
-#define NET_QUIC_CRYPTO_CERT_COMPRESSOR_H_
+#ifndef NET_QUIC_CORE_CRYPTO_CERT_COMPRESSOR_H_
+#define NET_QUIC_CORE_CRYPTO_CERT_COMPRESSOR_H_
#include <string>
#include <vector>
#include "base/macros.h"
#include "base/strings/string_piece.h"
-#include "net/base/net_export.h"
#include "net/quic/core/crypto/common_cert_set.h"
#include "net/quic/core/crypto/crypto_protocol.h"
+#include "net/quic/platform/api/quic_export.h"
namespace net {
@@ -28,7 +28,7 @@ namespace net {
// 3) Otherwise the certificates are compressed with zlib using a pre-shared
// dictionary that consists of the certificates handled with the above
// methods and a small chunk of common substrings.
-class NET_EXPORT_PRIVATE CertCompressor {
+class QUIC_EXPORT_PRIVATE CertCompressor {
public:
// CompressChain compresses the certificates in |certs| and returns a
// compressed representation. |common_sets| contains the common certificate
@@ -55,4 +55,4 @@ class NET_EXPORT_PRIVATE CertCompressor {
} // namespace net
-#endif // NET_QUIC_CRYPTO_CERT_COMPRESSOR_H_
+#endif // NET_QUIC_CORE_CRYPTO_CERT_COMPRESSOR_H_
diff --git a/chromium/net/quic/core/crypto/cert_compressor_test.cc b/chromium/net/quic/core/crypto/cert_compressor_test.cc
index 631c8326001..11da03395ff 100644
--- a/chromium/net/quic/core/crypto/cert_compressor_test.cc
+++ b/chromium/net/quic/core/crypto/cert_compressor_test.cc
@@ -7,6 +7,7 @@
#include <memory>
#include "net/quic/core/quic_utils.h"
+#include "net/quic/platform/api/quic_text_utils.h"
#include "net/quic/test_tools/crypto_test_utils.h"
#include "testing/gtest/include/gtest/gtest.h"
@@ -20,7 +21,7 @@ TEST(CertCompressor, EmptyChain) {
std::vector<string> chain;
const string compressed = CertCompressor::CompressChain(
chain, StringPiece(), StringPiece(), nullptr);
- EXPECT_EQ("00", QuicUtils::HexEncode(compressed));
+ EXPECT_EQ("00", QuicTextUtils::HexEncode(compressed));
std::vector<string> chain2, cached_certs;
ASSERT_TRUE(CertCompressor::DecompressChain(compressed, cached_certs, nullptr,
@@ -34,7 +35,7 @@ TEST(CertCompressor, Compressed) {
const string compressed = CertCompressor::CompressChain(
chain, StringPiece(), StringPiece(), nullptr);
ASSERT_GE(compressed.size(), 2u);
- EXPECT_EQ("0100", QuicUtils::HexEncode(compressed.substr(0, 2)));
+ EXPECT_EQ("0100", QuicTextUtils::HexEncode(compressed.substr(0, 2)));
std::vector<string> chain2, cached_certs;
ASSERT_TRUE(CertCompressor::DecompressChain(compressed, cached_certs, nullptr,
@@ -55,10 +56,10 @@ TEST(CertCompressor, Common) {
StringPiece(), common_sets.get());
EXPECT_EQ(
"03" /* common */
- "2A00000000000000" /* set hash 42 */
+ "2a00000000000000" /* set hash 42 */
"01000000" /* index 1 */
"00" /* end of list */,
- QuicUtils::HexEncode(compressed));
+ QuicTextUtils::HexEncode(compressed));
std::vector<string> chain2, cached_certs;
ASSERT_TRUE(CertCompressor::DecompressChain(compressed, cached_certs,
@@ -70,14 +71,14 @@ TEST(CertCompressor, Common) {
TEST(CertCompressor, Cached) {
std::vector<string> chain;
chain.push_back("testcert");
- uint64_t hash = QuicUtils::FNV1a_64_Hash(chain[0].data(), chain[0].size());
+ uint64_t hash = QuicUtils::FNV1a_64_Hash(chain[0]);
StringPiece hash_bytes(reinterpret_cast<char*>(&hash), sizeof(hash));
const string compressed =
CertCompressor::CompressChain(chain, StringPiece(), hash_bytes, nullptr);
- EXPECT_EQ("02" /* cached */ + QuicUtils::HexEncode(hash_bytes) +
+ EXPECT_EQ("02" /* cached */ + QuicTextUtils::HexEncode(hash_bytes) +
"00" /* end of list */,
- QuicUtils::HexEncode(compressed));
+ QuicTextUtils::HexEncode(compressed));
std::vector<string> cached_certs, chain2;
cached_certs.push_back(chain[0]);
@@ -91,37 +92,37 @@ TEST(CertCompressor, BadInputs) {
std::vector<string> cached_certs, chain;
EXPECT_FALSE(CertCompressor::DecompressChain(
- QuicUtils::HexEncode("04") /* bad entry type */, cached_certs, nullptr,
- &chain));
+ QuicTextUtils::HexEncode("04") /* bad entry type */, cached_certs,
+ nullptr, &chain));
EXPECT_FALSE(CertCompressor::DecompressChain(
- QuicUtils::HexEncode("01") /* no terminator */, cached_certs, nullptr,
+ QuicTextUtils::HexEncode("01") /* no terminator */, cached_certs, nullptr,
&chain));
EXPECT_FALSE(CertCompressor::DecompressChain(
- QuicUtils::HexEncode("0200") /* hash truncated */, cached_certs, nullptr,
- &chain));
+ QuicTextUtils::HexEncode("0200") /* hash truncated */, cached_certs,
+ nullptr, &chain));
EXPECT_FALSE(CertCompressor::DecompressChain(
- QuicUtils::HexEncode("0300") /* hash and index truncated */, cached_certs,
- nullptr, &chain));
+ QuicTextUtils::HexEncode("0300") /* hash and index truncated */,
+ cached_certs, nullptr, &chain));
/* without a CommonCertSets */
- EXPECT_FALSE(
- CertCompressor::DecompressChain(QuicUtils::HexEncode("03"
- "0000000000000000"
- "00000000"),
- cached_certs, nullptr, &chain));
+ EXPECT_FALSE(CertCompressor::DecompressChain(
+ QuicTextUtils::HexEncode("03"
+ "0000000000000000"
+ "00000000"),
+ cached_certs, nullptr, &chain));
std::unique_ptr<CommonCertSets> common_sets(
CryptoTestUtils::MockCommonCertSets("foo", 42, 1));
/* incorrect hash and index */
- EXPECT_FALSE(
- CertCompressor::DecompressChain(QuicUtils::HexEncode("03"
- "a200000000000000"
- "00000000"),
- cached_certs, nullptr, &chain));
+ EXPECT_FALSE(CertCompressor::DecompressChain(
+ QuicTextUtils::HexEncode("03"
+ "a200000000000000"
+ "00000000"),
+ cached_certs, nullptr, &chain));
}
} // namespace test
diff --git a/chromium/net/quic/core/crypto/chacha20_poly1305_decrypter.h b/chromium/net/quic/core/crypto/chacha20_poly1305_decrypter.h
index 0aa3568af88..d671d68e729 100644
--- a/chromium/net/quic/core/crypto/chacha20_poly1305_decrypter.h
+++ b/chromium/net/quic/core/crypto/chacha20_poly1305_decrypter.h
@@ -2,15 +2,14 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#ifndef NET_QUIC_CRYPTO_CHACHA20_POLY1305_DECRYPTER_H_
-#define NET_QUIC_CRYPTO_CHACHA20_POLY1305_DECRYPTER_H_
+#ifndef NET_QUIC_CORE_CRYPTO_CHACHA20_POLY1305_DECRYPTER_H_
+#define NET_QUIC_CORE_CRYPTO_CHACHA20_POLY1305_DECRYPTER_H_
-#include <stddef.h>
-#include <stdint.h>
+#include <cstdint>
#include "base/macros.h"
-#include "net/base/net_export.h"
#include "net/quic/core/crypto/aead_base_decrypter.h"
+#include "net/quic/platform/api/quic_export.h"
namespace net {
@@ -22,7 +21,7 @@ namespace net {
//
// It uses an authentication tag of 16 bytes (128 bits). There is no
// fixed nonce prefix.
-class NET_EXPORT_PRIVATE ChaCha20Poly1305Decrypter : public AeadBaseDecrypter {
+class QUIC_EXPORT_PRIVATE ChaCha20Poly1305Decrypter : public AeadBaseDecrypter {
public:
enum {
kAuthTagSize = 12,
@@ -40,4 +39,4 @@ class NET_EXPORT_PRIVATE ChaCha20Poly1305Decrypter : public AeadBaseDecrypter {
} // namespace net
-#endif // NET_QUIC_CRYPTO_CHACHA20_POLY1305_DECRYPTER_H_
+#endif // NET_QUIC_CORE_CRYPTO_CHACHA20_POLY1305_DECRYPTER_H_
diff --git a/chromium/net/quic/core/crypto/chacha20_poly1305_decrypter_test.cc b/chromium/net/quic/core/crypto/chacha20_poly1305_decrypter_test.cc
index a0ca47c72b1..6caa52fc40c 100644
--- a/chromium/net/quic/core/crypto/chacha20_poly1305_decrypter_test.cc
+++ b/chromium/net/quic/core/crypto/chacha20_poly1305_decrypter_test.cc
@@ -6,8 +6,8 @@
#include <memory>
-#include "net/quic/core/quic_flags.h"
#include "net/quic/core/quic_utils.h"
+#include "net/quic/platform/api/quic_text_utils.h"
#include "net/quic/test_tools/quic_test_utils.h"
using base::StringPiece;
@@ -129,8 +129,8 @@ QuicData* DecryptWithNonce(ChaCha20Poly1305Decrypter* decrypter,
std::unique_ptr<char[]> output(new char[ciphertext.length()]);
size_t output_length = 0;
const bool success = decrypter->DecryptPacket(
- path_id, packet_number, associated_data, ciphertext, output.get(),
- &output_length, ciphertext.length());
+ QuicVersionMax(), path_id, packet_number, associated_data, ciphertext,
+ output.get(), &output_length, ciphertext.length());
if (!success) {
return nullptr;
}
@@ -143,14 +143,14 @@ TEST(ChaCha20Poly1305DecrypterTest, Decrypt) {
bool has_pt = test_vectors[i].pt;
// Decode the test vector.
- string key = QuicUtils::HexDecode(test_vectors[i].key);
- string iv = QuicUtils::HexDecode(test_vectors[i].iv);
- string fixed = QuicUtils::HexDecode(test_vectors[i].fixed);
- string aad = QuicUtils::HexDecode(test_vectors[i].aad);
- string ct = QuicUtils::HexDecode(test_vectors[i].ct);
+ string key = QuicTextUtils::HexDecode(test_vectors[i].key);
+ string iv = QuicTextUtils::HexDecode(test_vectors[i].iv);
+ string fixed = QuicTextUtils::HexDecode(test_vectors[i].fixed);
+ string aad = QuicTextUtils::HexDecode(test_vectors[i].aad);
+ string ct = QuicTextUtils::HexDecode(test_vectors[i].ct);
string pt;
if (has_pt) {
- pt = QuicUtils::HexDecode(test_vectors[i].pt);
+ pt = QuicTextUtils::HexDecode(test_vectors[i].pt);
}
ChaCha20Poly1305Decrypter decrypter;
diff --git a/chromium/net/quic/core/crypto/chacha20_poly1305_encrypter.h b/chromium/net/quic/core/crypto/chacha20_poly1305_encrypter.h
index 8f3eaa7dc3b..dd4d4a6bbb3 100644
--- a/chromium/net/quic/core/crypto/chacha20_poly1305_encrypter.h
+++ b/chromium/net/quic/core/crypto/chacha20_poly1305_encrypter.h
@@ -2,26 +2,23 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#ifndef NET_QUIC_CRYPTO_CHACHA20_POLY1305_ENCRYPTER_H_
-#define NET_QUIC_CRYPTO_CHACHA20_POLY1305_ENCRYPTER_H_
-
-#include <stddef.h>
+#ifndef NET_QUIC_CORE_CRYPTO_CHACHA20_POLY1305_ENCRYPTER_H_
+#define NET_QUIC_CORE_CRYPTO_CHACHA20_POLY1305_ENCRYPTER_H_
#include "base/macros.h"
-#include "net/base/net_export.h"
#include "net/quic/core/crypto/aead_base_encrypter.h"
+#include "net/quic/platform/api/quic_export.h"
namespace net {
// A ChaCha20Poly1305Encrypter is a QuicEncrypter that implements the
-// AEAD_CHACHA20_POLY1305 algorithm specified in
-// draft-agl-tls-chacha20poly1305-04, except that it truncates the Poly1305
-// authenticator to 12 bytes. Create an instance by calling
-// QuicEncrypter::Create(kCC12).
+// AEAD_CHACHA20_POLY1305 algorithm specified in RFC 7539, except that
+// it truncates the Poly1305 authenticator to 12 bytes. Create an instance
+// by calling QuicEncrypter::Create(kCC12).
//
// It uses an authentication tag of 16 bytes (128 bits). There is no
// fixed nonce prefix.
-class NET_EXPORT_PRIVATE ChaCha20Poly1305Encrypter : public AeadBaseEncrypter {
+class QUIC_EXPORT_PRIVATE ChaCha20Poly1305Encrypter : public AeadBaseEncrypter {
public:
enum {
kAuthTagSize = 12,
@@ -36,4 +33,4 @@ class NET_EXPORT_PRIVATE ChaCha20Poly1305Encrypter : public AeadBaseEncrypter {
} // namespace net
-#endif // NET_QUIC_CRYPTO_CHACHA20_POLY1305_ENCRYPTER_H_
+#endif // NET_QUIC_CORE_CRYPTO_CHACHA20_POLY1305_ENCRYPTER_H_
diff --git a/chromium/net/quic/core/crypto/chacha20_poly1305_encrypter_test.cc b/chromium/net/quic/core/crypto/chacha20_poly1305_encrypter_test.cc
index 863be3111d6..0ec5308728f 100644
--- a/chromium/net/quic/core/crypto/chacha20_poly1305_encrypter_test.cc
+++ b/chromium/net/quic/core/crypto/chacha20_poly1305_encrypter_test.cc
@@ -8,6 +8,7 @@
#include "net/quic/core/crypto/chacha20_poly1305_decrypter.h"
#include "net/quic/core/quic_utils.h"
+#include "net/quic/platform/api/quic_text_utils.h"
#include "net/quic/test_tools/quic_test_utils.h"
using base::StringPiece;
@@ -87,7 +88,7 @@ TEST(ChaCha20Poly1305EncrypterTest, EncryptThenDecrypt) {
ChaCha20Poly1305Encrypter encrypter;
ChaCha20Poly1305Decrypter decrypter;
- string key = QuicUtils::HexDecode(test_vectors[0].key);
+ string key = QuicTextUtils::HexDecode(test_vectors[0].key);
ASSERT_TRUE(encrypter.SetKey(key));
ASSERT_TRUE(decrypter.SetKey(key));
ASSERT_TRUE(encrypter.SetNoncePrefix("abcd"));
@@ -99,25 +100,25 @@ TEST(ChaCha20Poly1305EncrypterTest, EncryptThenDecrypt) {
string plaintext = "plaintext";
char encrypted[1024];
size_t len;
- ASSERT_TRUE(encrypter.EncryptPacket(path_id, packet_number, associated_data,
- plaintext, encrypted, &len,
- arraysize(encrypted)));
+ ASSERT_TRUE(encrypter.EncryptPacket(QuicVersionMax(), path_id, packet_number,
+ associated_data, plaintext, encrypted,
+ &len, arraysize(encrypted)));
StringPiece ciphertext(encrypted, len);
char decrypted[1024];
- ASSERT_TRUE(decrypter.DecryptPacket(path_id, packet_number, associated_data,
- ciphertext, decrypted, &len,
- arraysize(decrypted)));
+ ASSERT_TRUE(decrypter.DecryptPacket(QuicVersionMax(), path_id, packet_number,
+ associated_data, ciphertext, decrypted,
+ &len, arraysize(decrypted)));
}
TEST(ChaCha20Poly1305EncrypterTest, Encrypt) {
for (size_t i = 0; test_vectors[i].key != nullptr; i++) {
// Decode the test vector.
- string key = QuicUtils::HexDecode(test_vectors[i].key);
- string pt = QuicUtils::HexDecode(test_vectors[i].pt);
- string iv = QuicUtils::HexDecode(test_vectors[i].iv);
- string fixed = QuicUtils::HexDecode(test_vectors[i].fixed);
- string aad = QuicUtils::HexDecode(test_vectors[i].aad);
- string ct = QuicUtils::HexDecode(test_vectors[i].ct);
+ string key = QuicTextUtils::HexDecode(test_vectors[i].key);
+ string pt = QuicTextUtils::HexDecode(test_vectors[i].pt);
+ string iv = QuicTextUtils::HexDecode(test_vectors[i].iv);
+ string fixed = QuicTextUtils::HexDecode(test_vectors[i].fixed);
+ string aad = QuicTextUtils::HexDecode(test_vectors[i].aad);
+ string ct = QuicTextUtils::HexDecode(test_vectors[i].ct);
ChaCha20Poly1305Encrypter encrypter;
ASSERT_TRUE(encrypter.SetKey(key));
diff --git a/chromium/net/quic/core/crypto/channel_id.cc b/chromium/net/quic/core/crypto/channel_id.cc
index abc0ae5bfaa..63701805adb 100644
--- a/chromium/net/quic/core/crypto/channel_id.cc
+++ b/chromium/net/quic/core/crypto/channel_id.cc
@@ -4,10 +4,10 @@
#include "net/quic/core/crypto/channel_id.h"
-#include "crypto/openssl_util.h"
+#include <cstdint>
+
#include "third_party/boringssl/src/include/openssl/bn.h"
#include "third_party/boringssl/src/include/openssl/ec.h"
-#include "third_party/boringssl/src/include/openssl/ec_key.h"
#include "third_party/boringssl/src/include/openssl/ecdsa.h"
#include "third_party/boringssl/src/include/openssl/nid.h"
#include "third_party/boringssl/src/include/openssl/sha.h"
@@ -39,7 +39,7 @@ bool ChannelIDVerifier::VerifyRaw(StringPiece key,
bssl::UniquePtr<EC_GROUP> p256(
EC_GROUP_new_by_curve_name(NID_X9_62_prime256v1));
- if (!p256) {
+ if (p256.get() == nullptr) {
return false;
}
diff --git a/chromium/net/quic/core/crypto/channel_id.h b/chromium/net/quic/core/crypto/channel_id.h
index 571f7410c90..3d41e538cc2 100644
--- a/chromium/net/quic/core/crypto/channel_id.h
+++ b/chromium/net/quic/core/crypto/channel_id.h
@@ -2,22 +2,22 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#ifndef NET_QUIC_CRYPTO_CHANNEL_ID_H_
-#define NET_QUIC_CRYPTO_CHANNEL_ID_H_
+#ifndef NET_QUIC_CORE_CRYPTO_CHANNEL_ID_H_
+#define NET_QUIC_CORE_CRYPTO_CHANNEL_ID_H_
#include <memory>
#include <string>
#include "base/macros.h"
#include "base/strings/string_piece.h"
-#include "net/base/net_export.h"
#include "net/quic/core/quic_types.h"
+#include "net/quic/platform/api/quic_export.h"
namespace net {
// ChannelIDKey is an interface that supports signing with and serializing a
// ChannelID key.
-class NET_EXPORT_PRIVATE ChannelIDKey {
+class QUIC_EXPORT_PRIVATE ChannelIDKey {
public:
virtual ~ChannelIDKey() {}
@@ -45,7 +45,7 @@ class ChannelIDSourceCallback {
// ChannelIDSource is an abstract interface by which a QUIC client can obtain
// a ChannelIDKey for a given hostname.
-class NET_EXPORT_PRIVATE ChannelIDSource {
+class QUIC_EXPORT_PRIVATE ChannelIDSource {
public:
virtual ~ChannelIDSource() {}
@@ -64,7 +64,7 @@ class NET_EXPORT_PRIVATE ChannelIDSource {
};
// ChannelIDVerifier verifies ChannelID signatures.
-class NET_EXPORT_PRIVATE ChannelIDVerifier {
+class QUIC_EXPORT_PRIVATE ChannelIDVerifier {
public:
// kContextStr is prepended to the data to be signed in order to ensure that
// a ChannelID signature cannot be used in a different context. (The
@@ -96,4 +96,4 @@ class NET_EXPORT_PRIVATE ChannelIDVerifier {
} // namespace net
-#endif // NET_QUIC_CRYPTO_CHANNEL_ID_H_
+#endif // NET_QUIC_CORE_CRYPTO_CHANNEL_ID_H_
diff --git a/chromium/net/quic/core/crypto/channel_id_test.cc b/chromium/net/quic/core/crypto/channel_id_test.cc
index 2b364d460b4..0309e65cb3a 100644
--- a/chromium/net/quic/core/crypto/channel_id_test.cc
+++ b/chromium/net/quic/core/crypto/channel_id_test.cc
@@ -7,7 +7,6 @@
#include <memory>
#include "net/quic/test_tools/crypto_test_utils.h"
-#include "net/quic/test_tools/quic_test_utils.h"
#include "testing/gtest/include/gtest/gtest.h"
using base::StringPiece;
@@ -202,36 +201,83 @@ const TestVector test_vector[] = {
},
{nullptr}};
+// Returns true if |ch| is a lowercase hexadecimal digit.
+bool IsHexDigit(char ch) {
+ return ('0' <= ch && ch <= '9') || ('a' <= ch && ch <= 'f');
+}
+
+// Converts a lowercase hexadecimal digit to its integer value.
+int HexDigitToInt(char ch) {
+ if ('0' <= ch && ch <= '9') {
+ return ch - '0';
+ }
+ return ch - 'a' + 10;
+}
+
+// |in| is a string consisting of lowercase hexadecimal digits, where
+// every two digits represent one byte. |out| is a buffer of size |max_len|.
+// Converts |in| to bytes and stores the bytes in the |out| buffer. The
+// number of bytes converted is returned in |*out_len|. Returns true on
+// success, false on failure.
+bool DecodeHexString(const char* in,
+ char* out,
+ size_t* out_len,
+ size_t max_len) {
+ if (!in) {
+ *out_len = static_cast<size_t>(-1);
+ return true;
+ }
+ *out_len = 0;
+ while (*in != '\0') {
+ if (!IsHexDigit(*in) || !IsHexDigit(*(in + 1))) {
+ return false;
+ }
+ if (*out_len >= max_len) {
+ return false;
+ }
+ out[*out_len] = HexDigitToInt(*in) * 16 + HexDigitToInt(*(in + 1));
+ (*out_len)++;
+ in += 2;
+ }
+ return true;
+}
+
} // namespace
// A known answer test for ChannelIDVerifier.
TEST(ChannelIDTest, VerifyKnownAnswerTest) {
- string msg;
- string qx;
- string qy;
- string r;
- string s;
+ char msg[1024];
+ size_t msg_len;
+ char key[64];
+ size_t qx_len;
+ size_t qy_len;
+ char signature[64];
+ size_t r_len;
+ size_t s_len;
for (size_t i = 0; test_vector[i].msg != nullptr; i++) {
SCOPED_TRACE(i);
// Decode the test vector.
- ASSERT_TRUE(DecodeHexString(test_vector[i].msg, &msg));
- ASSERT_TRUE(DecodeHexString(test_vector[i].qx, &qx));
- ASSERT_TRUE(DecodeHexString(test_vector[i].qy, &qy));
- ASSERT_TRUE(DecodeHexString(test_vector[i].r, &r));
- ASSERT_TRUE(DecodeHexString(test_vector[i].s, &s));
-
- string key = qx + qy;
- string signature = r + s;
+ ASSERT_TRUE(
+ DecodeHexString(test_vector[i].msg, msg, &msg_len, sizeof(msg)));
+ ASSERT_TRUE(DecodeHexString(test_vector[i].qx, key, &qx_len, sizeof(key)));
+ ASSERT_TRUE(DecodeHexString(test_vector[i].qy, key + qx_len, &qy_len,
+ sizeof(key) - qx_len));
+ ASSERT_TRUE(DecodeHexString(test_vector[i].r, signature, &r_len,
+ sizeof(signature)));
+ ASSERT_TRUE(DecodeHexString(test_vector[i].s, signature + r_len, &s_len,
+ sizeof(signature) - r_len));
// The test vector's lengths should look sane.
- EXPECT_EQ(32u, qx.size());
- EXPECT_EQ(32u, qy.size());
- EXPECT_EQ(32u, r.size());
- EXPECT_EQ(32u, s.size());
+ EXPECT_EQ(sizeof(key) / 2, qx_len);
+ EXPECT_EQ(sizeof(key) / 2, qy_len);
+ EXPECT_EQ(sizeof(signature) / 2, r_len);
+ EXPECT_EQ(sizeof(signature) / 2, s_len);
EXPECT_EQ(test_vector[i].result,
- ChannelIDVerifier::VerifyRaw(key, msg, signature, false));
+ ChannelIDVerifier::VerifyRaw(
+ StringPiece(key, sizeof(key)), StringPiece(msg, msg_len),
+ StringPiece(signature, sizeof(signature)), false));
}
}
diff --git a/chromium/net/quic/core/crypto/common_cert_set.cc b/chromium/net/quic/core/crypto/common_cert_set.cc
index 5b68b63a5fe..25bde99fc20 100644
--- a/chromium/net/quic/core/crypto/common_cert_set.cc
+++ b/chromium/net/quic/core/crypto/common_cert_set.cc
@@ -6,7 +6,6 @@
#include <cstddef>
-#include "base/logging.h"
#include "base/macros.h"
#include "base/memory/singleton.h"
#include "net/quic/core/quic_utils.h"
diff --git a/chromium/net/quic/core/crypto/common_cert_set.h b/chromium/net/quic/core/crypto/common_cert_set.h
index 9ff622bd221..08264c7acb6 100644
--- a/chromium/net/quic/core/crypto/common_cert_set.h
+++ b/chromium/net/quic/core/crypto/common_cert_set.h
@@ -2,21 +2,21 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#ifndef NET_QUIC_CRYPTO_COMMON_CERT_SET_H_
-#define NET_QUIC_CRYPTO_COMMON_CERT_SET_H_
+#ifndef NET_QUIC_CORE_CRYPTO_COMMON_CERT_SET_H_
+#define NET_QUIC_CORE_CRYPTO_COMMON_CERT_SET_H_
#include <cstdint>
#include "base/compiler_specific.h"
#include "base/strings/string_piece.h"
-#include "net/base/net_export.h"
#include "net/quic/core/crypto/crypto_protocol.h"
+#include "net/quic/platform/api/quic_export.h"
namespace net {
// CommonCertSets is an interface to an object that contains a number of common
// certificate sets and can match against them.
-class NET_EXPORT_PRIVATE CommonCertSets {
+class QUIC_EXPORT_PRIVATE CommonCertSets {
public:
virtual ~CommonCertSets();
@@ -45,4 +45,4 @@ class NET_EXPORT_PRIVATE CommonCertSets {
} // namespace net
-#endif // NET_QUIC_CRYPTO_COMMON_CERT_SET_H_
+#endif // NET_QUIC_CORE_CRYPTO_COMMON_CERT_SET_H_
diff --git a/chromium/net/quic/core/crypto/common_cert_set_test.cc b/chromium/net/quic/core/crypto/common_cert_set_test.cc
index 3eea6eebbe7..b355da218d4 100644
--- a/chromium/net/quic/core/crypto/common_cert_set_test.cc
+++ b/chromium/net/quic/core/crypto/common_cert_set_test.cc
@@ -4,7 +4,7 @@
#include "net/quic/core/crypto/common_cert_set.h"
-#include <stdint.h>
+#include <cstdint>
#include "testing/gtest/include/gtest/gtest.h"
diff --git a/chromium/net/quic/core/crypto/crypto_framer.cc b/chromium/net/quic/core/crypto/crypto_framer.cc
index c2a83d61191..56d9bf8dba2 100644
--- a/chromium/net/quic/core/crypto/crypto_framer.cc
+++ b/chromium/net/quic/core/crypto/crypto_framer.cc
@@ -4,12 +4,11 @@
#include "net/quic/core/crypto/crypto_framer.h"
-#include <memory>
-
-#include "base/strings/stringprintf.h"
#include "net/quic/core/crypto/crypto_protocol.h"
#include "net/quic/core/quic_data_reader.h"
#include "net/quic/core/quic_data_writer.h"
+#include "net/quic/core/quic_packets.h"
+#include "net/quic/platform/api/quic_str_cat.h"
using base::StringPiece;
@@ -17,7 +16,7 @@ namespace net {
namespace {
-const size_t kQuicTagSize = sizeof(uint32_t);
+const size_t kQuicTagSize = sizeof(QuicTag);
const size_t kCryptoEndOffsetSize = sizeof(uint32_t);
const size_t kNumEntriesSize = sizeof(uint16_t);
@@ -34,7 +33,7 @@ class OneShotVisitor : public CryptoFramerVisitorInterface {
bool error() const { return error_; }
- CryptoHandshakeMessage* release() { return out_.release(); }
+ std::unique_ptr<CryptoHandshakeMessage> release() { return std::move(out_); }
private:
std::unique_ptr<CryptoHandshakeMessage> out_;
@@ -51,7 +50,8 @@ CryptoFramer::CryptoFramer()
CryptoFramer::~CryptoFramer() {}
// static
-CryptoHandshakeMessage* CryptoFramer::ParseMessage(StringPiece in) {
+std::unique_ptr<CryptoHandshakeMessage> CryptoFramer::ParseMessage(
+ StringPiece in) {
OneShotVisitor visitor;
CryptoFramer framer;
@@ -211,7 +211,7 @@ QuicErrorCode CryptoFramer::Process(StringPiece input) {
}
reader.ReadUInt16(&num_entries_);
if (num_entries_ > kMaxEntries) {
- error_detail_ = base::StringPrintf("%u entries", num_entries_);
+ error_detail_ = QuicStrCat(num_entries_, " entries");
return QUIC_CRYPTO_TOO_MANY_ENTRIES;
}
uint16_t padding;
@@ -232,10 +232,10 @@ QuicErrorCode CryptoFramer::Process(StringPiece input) {
reader.ReadUInt32(&tag);
if (i > 0 && tag <= tags_and_lengths_[i - 1].first) {
if (tag == tags_and_lengths_[i - 1].first) {
- error_detail_ = base::StringPrintf("Duplicate tag:%u", tag);
+ error_detail_ = QuicStrCat("Duplicate tag:", tag);
return QUIC_CRYPTO_DUPLICATE_TAG;
}
- error_detail_ = base::StringPrintf("Tag %u out of order", tag);
+ error_detail_ = QuicStrCat("Tag ", tag, " out of order");
return QUIC_CRYPTO_TAGS_OUT_OF_ORDER;
}
@@ -243,8 +243,8 @@ QuicErrorCode CryptoFramer::Process(StringPiece input) {
reader.ReadUInt32(&end_offset);
if (end_offset < last_end_offset) {
- error_detail_ = base::StringPrintf("End offset: %u vs %u", end_offset,
- last_end_offset);
+ error_detail_ =
+ QuicStrCat("End offset: ", end_offset, " vs ", last_end_offset);
return QUIC_CRYPTO_TAGS_OUT_OF_ORDER;
}
tags_and_lengths_.push_back(std::make_pair(
diff --git a/chromium/net/quic/core/crypto/crypto_framer.h b/chromium/net/quic/core/crypto/crypto_framer.h
index c581a625e4f..a070119186c 100644
--- a/chromium/net/quic/core/crypto/crypto_framer.h
+++ b/chromium/net/quic/core/crypto/crypto_framer.h
@@ -2,29 +2,27 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#ifndef NET_QUIC_CRYPTO_CRYPTO_FRAMER_H_
-#define NET_QUIC_CRYPTO_CRYPTO_FRAMER_H_
-
-#include <stddef.h>
-#include <stdint.h>
+#ifndef NET_QUIC_CORE_CRYPTO_CRYPTO_FRAMER_H_
+#define NET_QUIC_CORE_CRYPTO_CRYPTO_FRAMER_H_
+#include <cstddef>
+#include <cstdint>
+#include <memory>
#include <utility>
#include <vector>
-#include "base/logging.h"
#include "base/strings/string_piece.h"
-#include "net/base/net_export.h"
#include "net/quic/core/crypto/crypto_handshake_message.h"
-#include "net/quic/core/quic_protocol.h"
+#include "net/quic/core/quic_packets.h"
+#include "net/quic/platform/api/quic_export.h"
namespace net {
class CryptoFramer;
class QuicData;
-class QuicDataReader;
class QuicDataWriter;
-class NET_EXPORT_PRIVATE CryptoFramerVisitorInterface {
+class QUIC_EXPORT_PRIVATE CryptoFramerVisitorInterface {
public:
virtual ~CryptoFramerVisitorInterface() {}
@@ -37,7 +35,7 @@ class NET_EXPORT_PRIVATE CryptoFramerVisitorInterface {
// A class for framing the crypto messages that are exchanged in a QUIC
// session.
-class NET_EXPORT_PRIVATE CryptoFramer {
+class QUIC_EXPORT_PRIVATE CryptoFramer {
public:
CryptoFramer();
@@ -46,7 +44,8 @@ class NET_EXPORT_PRIVATE CryptoFramer {
// ParseMessage parses exactly one message from the given StringPiece. If
// there is an error, the message is truncated, or the message has trailing
// garbage then nullptr will be returned.
- static CryptoHandshakeMessage* ParseMessage(base::StringPiece in);
+ static std::unique_ptr<CryptoHandshakeMessage> ParseMessage(
+ base::StringPiece in);
// Set callbacks to be called from the framer. A visitor must be set, or
// else the framer will crash. It is acceptable for the visitor to do
@@ -115,4 +114,4 @@ class NET_EXPORT_PRIVATE CryptoFramer {
} // namespace net
-#endif // NET_QUIC_CRYPTO_CRYPTO_FRAMER_H_
+#endif // NET_QUIC_CORE_CRYPTO_CRYPTO_FRAMER_H_
diff --git a/chromium/net/quic/core/crypto/crypto_framer_test.cc b/chromium/net/quic/core/crypto/crypto_framer_test.cc
index ae695d34077..5e045a45532 100644
--- a/chromium/net/quic/core/crypto/crypto_framer_test.cc
+++ b/chromium/net/quic/core/crypto/crypto_framer_test.cc
@@ -8,10 +8,10 @@
#include <memory>
#include <vector>
-#include "base/logging.h"
#include "net/quic/core/crypto/crypto_handshake.h"
#include "net/quic/core/crypto/crypto_protocol.h"
-#include "net/quic/core/quic_protocol.h"
+#include "net/quic/core/quic_packets.h"
+#include "net/quic/platform/api/quic_logging.h"
#include "net/quic/test_tools/crypto_test_utils.h"
#include "net/quic/test_tools/quic_test_utils.h"
@@ -35,7 +35,7 @@ class TestCryptoVisitor : public CryptoFramerVisitorInterface {
TestCryptoVisitor() : error_count_(0) {}
void OnError(CryptoFramer* framer) override {
- DLOG(ERROR) << "CryptoFramer Error: " << framer->error();
+ QUIC_DLOG(ERROR) << "CryptoFramer Error: " << framer->error();
++error_count_;
}
diff --git a/chromium/net/quic/core/crypto/crypto_handshake.h b/chromium/net/quic/core/crypto/crypto_handshake.h
index 48bee663df8..b646c58e693 100644
--- a/chromium/net/quic/core/crypto/crypto_handshake.h
+++ b/chromium/net/quic/core/crypto/crypto_handshake.h
@@ -2,18 +2,16 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#ifndef NET_QUIC_CRYPTO_CRYPTO_HANDSHAKE_H_
-#define NET_QUIC_CRYPTO_CRYPTO_HANDSHAKE_H_
-
-#include <stdint.h>
+#ifndef NET_QUIC_CORE_CRYPTO_CRYPTO_HANDSHAKE_H_
+#define NET_QUIC_CORE_CRYPTO_CRYPTO_HANDSHAKE_H_
#include <memory>
#include <string>
#include <vector>
#include "base/macros.h"
-#include "net/base/net_export.h"
-#include "net/quic/core/quic_protocol.h"
+#include "net/quic/core/quic_packets.h"
+#include "net/quic/platform/api/quic_export.h"
namespace net {
@@ -91,7 +89,7 @@ enum HandshakeFailureReason {
static_assert(MAX_FAILURE_REASON <= 32, "failure reason out of sync");
// A CrypterPair contains the encrypter and decrypter for an encryption level.
-struct NET_EXPORT_PRIVATE CrypterPair {
+struct QUIC_EXPORT_PRIVATE CrypterPair {
CrypterPair();
~CrypterPair();
std::unique_ptr<QuicEncrypter> encrypter;
@@ -99,8 +97,8 @@ struct NET_EXPORT_PRIVATE CrypterPair {
};
// Parameters negotiated by the crypto handshake.
-struct NET_EXPORT_PRIVATE QuicCryptoNegotiatedParameters
- : public base::RefCounted<QuicCryptoNegotiatedParameters> {
+struct QUIC_EXPORT_PRIVATE QuicCryptoNegotiatedParameters
+ : public QuicReferenceCounted {
// Initializes the members to 0 or empty values.
QuicCryptoNegotiatedParameters();
@@ -150,13 +148,12 @@ struct NET_EXPORT_PRIVATE QuicCryptoNegotiatedParameters
// by sending CSCT tag with an empty value in client hello.
bool sct_supported_by_client;
- private:
- friend class base::RefCounted<QuicCryptoNegotiatedParameters>;
- virtual ~QuicCryptoNegotiatedParameters();
+ protected:
+ ~QuicCryptoNegotiatedParameters() override;
};
// QuicCryptoConfig contains common configuration between clients and servers.
-class NET_EXPORT_PRIVATE QuicCryptoConfig {
+class QUIC_EXPORT_PRIVATE QuicCryptoConfig {
public:
// kInitialLabel is a constant that is used when deriving the initial
// (non-forward secure) keys for the connection in order to tie the resulting
@@ -193,4 +190,4 @@ class NET_EXPORT_PRIVATE QuicCryptoConfig {
} // namespace net
-#endif // NET_QUIC_CRYPTO_CRYPTO_HANDSHAKE_H_
+#endif // NET_QUIC_CORE_CRYPTO_CRYPTO_HANDSHAKE_H_
diff --git a/chromium/net/quic/core/crypto/crypto_handshake_message.cc b/chromium/net/quic/core/crypto/crypto_handshake_message.cc
index 530d2f8011d..fcaf59b5f6f 100644
--- a/chromium/net/quic/core/crypto/crypto_handshake_message.cc
+++ b/chromium/net/quic/core/crypto/crypto_handshake_message.cc
@@ -7,18 +7,18 @@
#include <memory>
#include "base/stl_util.h"
-#include "base/strings/string_number_conversions.h"
#include "base/strings/stringprintf.h"
#include "net/quic/core/crypto/crypto_framer.h"
#include "net/quic/core/crypto/crypto_protocol.h"
#include "net/quic/core/crypto/crypto_utils.h"
#include "net/quic/core/quic_socket_address_coder.h"
#include "net/quic/core/quic_utils.h"
+#include "net/quic/platform/api/quic_text_utils.h"
+using base::ContainsKey;
using base::StringPiece;
using base::StringPrintf;
using std::string;
-using std::vector;
namespace net {
@@ -112,7 +112,7 @@ bool CryptoHandshakeMessage::GetStringPiece(QuicTag tag,
}
bool CryptoHandshakeMessage::HasStringPiece(QuicTag tag) const {
- return base::ContainsKey(tag_value_map_, tag);
+ return ContainsKey(tag_value_map_, tag);
}
QuicErrorCode CryptoHandshakeMessage::GetNthValue24(QuicTag tag,
@@ -212,11 +212,11 @@ QuicErrorCode CryptoHandshakeMessage::GetPOD(QuicTag tag,
}
string CryptoHandshakeMessage::DebugStringInternal(size_t indent) const {
- string ret = string(2 * indent, ' ') + QuicUtils::TagToString(tag_) + "<\n";
+ string ret = string(2 * indent, ' ') + QuicTagToString(tag_) + "<\n";
++indent;
for (QuicTagValueMap::const_iterator it = tag_value_map_.begin();
it != tag_value_map_.end(); ++it) {
- ret += string(2 * indent, ' ') + QuicUtils::TagToString(it->first) + ": ";
+ ret += string(2 * indent, ' ') + QuicTagToString(it->first) + ": ";
bool done = false;
switch (it->first) {
@@ -234,7 +234,7 @@ string CryptoHandshakeMessage::DebugStringInternal(size_t indent) const {
if (it->second.size() == 4) {
uint32_t value;
memcpy(&value, it->second.data(), sizeof(value));
- ret += base::UintToString(value);
+ ret += QuicTextUtils::Uint64ToString(value);
done = true;
}
break;
@@ -243,7 +243,7 @@ string CryptoHandshakeMessage::DebugStringInternal(size_t indent) const {
if (it->second.size() == 8) {
uint64_t value;
memcpy(&value, it->second.data(), sizeof(value));
- ret += base::Uint64ToString(value);
+ ret += QuicTextUtils::Uint64ToString(value);
done = true;
}
break;
@@ -261,7 +261,7 @@ string CryptoHandshakeMessage::DebugStringInternal(size_t indent) const {
if (j > 0) {
ret += ",";
}
- ret += "'" + QuicUtils::TagToString(tag) + "'";
+ ret += "'" + QuicTagToString(tag) + "'";
}
done = true;
}
@@ -286,7 +286,7 @@ string CryptoHandshakeMessage::DebugStringInternal(size_t indent) const {
if (!it->second.empty()) {
QuicSocketAddressCoder decoder;
if (decoder.Decode(it->second.data(), it->second.size())) {
- ret += IPAddressToStringWithPort(decoder.ip(), decoder.port());
+ ret += QuicSocketAddress(decoder.ip(), decoder.port()).ToString();
done = true;
}
}
@@ -319,7 +319,7 @@ string CryptoHandshakeMessage::DebugStringInternal(size_t indent) const {
if (!done) {
// If there's no specific format for this tag, or the value is invalid,
// then just use hex.
- ret += "0x" + QuicUtils::HexEncode(it->second);
+ ret += "0x" + QuicTextUtils::HexEncode(it->second);
}
ret += "\n";
}
diff --git a/chromium/net/quic/core/crypto/crypto_handshake_message.h b/chromium/net/quic/core/crypto/crypto_handshake_message.h
index 81bce9f0979..f1e7b995e69 100644
--- a/chromium/net/quic/core/crypto/crypto_handshake_message.h
+++ b/chromium/net/quic/core/crypto/crypto_handshake_message.h
@@ -2,26 +2,24 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#ifndef NET_QUIC_CRYPTO_CRYPTO_HANDSHAKE_MESSAGE_H_
-#define NET_QUIC_CRYPTO_CRYPTO_HANDSHAKE_MESSAGE_H_
-
-#include <stddef.h>
-#include <stdint.h>
+#ifndef NET_QUIC_CORE_CRYPTO_CRYPTO_HANDSHAKE_MESSAGE_H_
+#define NET_QUIC_CORE_CRYPTO_CRYPTO_HANDSHAKE_MESSAGE_H_
+#include <cstddef>
#include <cstdint>
#include <memory>
#include <string>
#include <vector>
#include "base/strings/string_piece.h"
-#include "net/base/net_export.h"
-#include "net/quic/core/quic_protocol.h"
+#include "net/quic/core/quic_packets.h"
+#include "net/quic/platform/api/quic_export.h"
namespace net {
// An intermediate format of a handshake message that's convenient for a
// CryptoFramer to serialize from or parse into.
-class NET_EXPORT_PRIVATE CryptoHandshakeMessage {
+class QUIC_EXPORT_PRIVATE CryptoHandshakeMessage {
public:
CryptoHandshakeMessage();
CryptoHandshakeMessage(const CryptoHandshakeMessage& other);
@@ -138,4 +136,4 @@ class NET_EXPORT_PRIVATE CryptoHandshakeMessage {
} // namespace net
-#endif // NET_QUIC_CRYPTO_CRYPTO_HANDSHAKE_MESSAGE_H_
+#endif // NET_QUIC_CORE_CRYPTO_CRYPTO_HANDSHAKE_MESSAGE_H_
diff --git a/chromium/net/quic/core/crypto/crypto_handshake_message_test.cc b/chromium/net/quic/core/crypto/crypto_handshake_message_test.cc
index 7032a23969d..088cd37e6a0 100644
--- a/chromium/net/quic/core/crypto/crypto_handshake_message_test.cc
+++ b/chromium/net/quic/core/crypto/crypto_handshake_message_test.cc
@@ -6,7 +6,7 @@
#include "net/quic/core/crypto/crypto_handshake.h"
#include "net/quic/core/crypto/crypto_protocol.h"
-#include "net/test/gtest_util.h"
+#include "testing/gtest/include/gtest/gtest.h"
namespace net {
namespace test {
diff --git a/chromium/net/quic/core/crypto/crypto_protocol.h b/chromium/net/quic/core/crypto/crypto_protocol.h
index 2d3a6b8b18c..e426832d543 100644
--- a/chromium/net/quic/core/crypto/crypto_protocol.h
+++ b/chromium/net/quic/core/crypto/crypto_protocol.h
@@ -2,15 +2,13 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#ifndef NET_QUIC_CRYPTO_CRYPTO_PROTOCOL_H_
-#define NET_QUIC_CRYPTO_CRYPTO_PROTOCOL_H_
-
-#include <stddef.h>
-#include <stdint.h>
+#ifndef NET_QUIC_CORE_CRYPTO_CRYPTO_PROTOCOL_H_
+#define NET_QUIC_CORE_CRYPTO_CRYPTO_PROTOCOL_H_
+#include <cstddef>
#include <string>
-#include "net/quic/core/quic_protocol.h"
+#include "net/quic/core/quic_tag.h"
// Version and Crypto tags are written to the wire with a big-endian
// representation of the name of the tag. For example
@@ -44,7 +42,6 @@ const QuicTag kP256 = TAG('P', '2', '5', '6'); // ECDH, Curve P-256
const QuicTag kC255 = TAG('C', '2', '5', '5'); // ECDH, Curve25519
// AEAD algorithms
-const QuicTag kNULL = TAG('N', 'U', 'L', 'N'); // null algorithm
const QuicTag kAESG = TAG('A', 'E', 'S', 'G'); // AES128 + GCM-12
const QuicTag kCC20 = TAG('C', 'C', '2', '0'); // ChaCha20 + Poly1305 RFC7539
@@ -69,6 +66,18 @@ const QuicTag kIFW7 = TAG('I', 'F', 'W', '7'); // Set initial size
// of stream flow control
// receive window to
// 128KB. (2^7 KB).
+const QuicTag kIFW8 = TAG('I', 'F', 'W', '8'); // Set initial size
+ // of stream flow control
+ // receive window to
+ // 256KB. (2^8 KB).
+const QuicTag kIFW9 = TAG('I', 'F', 'W', '9'); // Set initial size
+ // of stream flow control
+ // receive window to
+ // 512KB. (2^9 KB).
+const QuicTag kIFWA = TAG('I', 'F', 'W', 'a'); // Set initial size
+ // of stream flow control
+ // receive window to
+ // 1MB. (2^0xa KB).
const QuicTag kTBBR = TAG('T', 'B', 'B', 'R'); // Reduced Buffer Bloat TCP
const QuicTag kRENO = TAG('R', 'E', 'N', 'O'); // Reno Congestion Control
const QuicTag kBYTE = TAG('B', 'Y', 'T', 'E'); // TCP cubic or reno in bytes
@@ -107,6 +116,13 @@ const QuicTag kCONH = TAG('C', 'O', 'N', 'H'); // Conservative Handshake
// Retransmissions.
const QuicTag kLFAK = TAG('L', 'F', 'A', 'K'); // Don't invoke FACK on the
// first ack.
+// TODO(fayang): Remove this connection option in QUIC_VERSION_37, in which
+// MAX_HEADER_LIST_SIZE settings frame should be supported.
+const QuicTag kSMHL = TAG('S', 'M', 'H', 'L'); // Support MAX_HEADER_LIST_SIZE
+ // settings frame.
+const QuicTag kCCVX = TAG('C', 'C', 'V', 'X'); // Fix Cubic convex bug.
+const QuicTag kCBQT = TAG('C', 'B', 'Q', 'T'); // Fix CubicBytes quantization.
+const QuicTag kBLMX = TAG('B', 'L', 'M', 'X'); // Fix Cubic BetaLastMax bug.
// Optional support of truncated Connection IDs. If sent by a peer, the value
// is the minimum number of bytes allowed for the connection ID sent to the
@@ -152,6 +168,7 @@ const QuicTag kKEXS = TAG('K', 'E', 'X', 'S'); // Key exchange methods
const QuicTag kAEAD = TAG('A', 'E', 'A', 'D'); // Authenticated
// encryption algorithms
const QuicTag kCOPT = TAG('C', 'O', 'P', 'T'); // Connection options
+const QuicTag kCLOP = TAG('C', 'L', 'O', 'P'); // Client connection options
const QuicTag kICSL = TAG('I', 'C', 'S', 'L'); // Idle network timeout
const QuicTag kSCLS = TAG('S', 'C', 'L', 'S'); // Silently close on timeout
const QuicTag kMSPC = TAG('M', 'S', 'P', 'C'); // Max streams per connection.
@@ -252,4 +269,4 @@ const size_t kClientHelloMinimumSize = 1024;
} // namespace net
-#endif // NET_QUIC_CRYPTO_CRYPTO_PROTOCOL_H_
+#endif // NET_QUIC_CORE_CRYPTO_CRYPTO_PROTOCOL_H_
diff --git a/chromium/net/quic/core/crypto/crypto_secret_boxer.cc b/chromium/net/quic/core/crypto/crypto_secret_boxer.cc
index 37f48b5e312..15d0720e95c 100644
--- a/chromium/net/quic/core/crypto/crypto_secret_boxer.cc
+++ b/chromium/net/quic/core/crypto/crypto_secret_boxer.cc
@@ -16,7 +16,6 @@
using base::StringPiece;
using std::string;
-using std::vector;
namespace net {
@@ -45,20 +44,20 @@ size_t CryptoSecretBoxer::GetKeySize() {
return kKeySize;
}
-void CryptoSecretBoxer::SetKeys(const vector<string>& keys) {
+void CryptoSecretBoxer::SetKeys(const std::vector<string>& keys) {
DCHECK(!keys.empty());
- vector<string> copy = keys;
+ std::vector<string> copy = keys;
for (const string& key : keys) {
DCHECK_EQ(kKeySize, key.size());
}
- base::AutoLock l(lock_);
+ QuicWriterMutexLock l(&lock_);
keys_.swap(copy);
}
string CryptoSecretBoxer::Box(QuicRandom* rand, StringPiece plaintext) const {
std::unique_ptr<Aes128Gcm12Encrypter> encrypter(new Aes128Gcm12Encrypter());
{
- base::AutoLock l(lock_);
+ QuicReaderMutexLock l(&lock_);
DCHECK_EQ(kKeySize, keys_[0].size());
if (!encrypter->SetKey(keys_[0])) {
DLOG(DFATAL) << "CryptoSecretBoxer's encrypter->SetKey failed.";
@@ -105,14 +104,15 @@ bool CryptoSecretBoxer::Unbox(StringPiece ciphertext,
size_t plaintext_length = 0;
bool ok = false;
{
- base::AutoLock l(lock_);
+ QuicReaderMutexLock l(&lock_);
for (const string& key : keys_) {
if (decrypter->SetKey(key)) {
decrypter->SetNoncePrefix(nonce_prefix);
- if (decrypter->DecryptPacket(
- /*path_id=*/0u, packet_number,
- /*associated data=*/StringPiece(), ciphertext, plaintext,
- &plaintext_length, kMaxPacketSize)) {
+ if (decrypter->DecryptPacket(QUIC_VERSION_36,
+ /*path_id=*/0u, packet_number,
+ /*associated data=*/StringPiece(),
+ ciphertext, plaintext, &plaintext_length,
+ kMaxPacketSize)) {
ok = true;
break;
}
diff --git a/chromium/net/quic/core/crypto/crypto_secret_boxer.h b/chromium/net/quic/core/crypto/crypto_secret_boxer.h
index 3bc92846bc1..93e6f90fc12 100644
--- a/chromium/net/quic/core/crypto/crypto_secret_boxer.h
+++ b/chromium/net/quic/core/crypto/crypto_secret_boxer.h
@@ -2,18 +2,17 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#ifndef NET_QUIC_CRYPTO_CRYPTO_SECRET_BOXER_H_
-#define NET_QUIC_CRYPTO_CRYPTO_SECRET_BOXER_H_
-
-#include <stddef.h>
+#ifndef NET_QUIC_CORE_CRYPTO_CRYPTO_SECRET_BOXER_H_
+#define NET_QUIC_CORE_CRYPTO_CRYPTO_SECRET_BOXER_H_
+#include <cstddef>
#include <string>
#include <vector>
#include "base/macros.h"
#include "base/strings/string_piece.h"
-#include "base/synchronization/lock.h"
-#include "net/base/net_export.h"
+#include "net/quic/platform/api/quic_export.h"
+#include "net/quic/platform/api/quic_mutex.h"
namespace net {
@@ -22,7 +21,7 @@ class QuicRandom;
// CryptoSecretBoxer encrypts small chunks of plaintext (called 'boxing') and
// then, later, can authenticate+decrypt the resulting boxes. This object is
// thread-safe.
-class NET_EXPORT_PRIVATE CryptoSecretBoxer {
+class QUIC_EXPORT_PRIVATE CryptoSecretBoxer {
public:
CryptoSecretBoxer();
~CryptoSecretBoxer();
@@ -30,6 +29,7 @@ class NET_EXPORT_PRIVATE CryptoSecretBoxer {
// GetKeySize returns the number of bytes in a key.
static size_t GetKeySize();
+ // SetKeys sets a list of encryption keys. The first key in the list will be
// used by |Box|, but all supplied keys will be tried by |Unbox|, to handle
// key skew across the fleet. This must be called before |Box| or |Unbox|.
// Keys must be |GetKeySize()| bytes long.
@@ -38,7 +38,7 @@ class NET_EXPORT_PRIVATE CryptoSecretBoxer {
// Box encrypts |plaintext| using a random nonce generated from |rand| and
// returns the resulting ciphertext. Since an authenticator and nonce are
// included, the result will be slightly larger than |plaintext|. The first
- // key in the std::vector supplied to |SetKeys| will be used.
+ // key in the vector supplied to |SetKeys| will be used.
std::string Box(QuicRandom* rand, base::StringPiece plaintext) const;
// Unbox takes the result of a previous call to |Box| in |ciphertext| and
@@ -51,13 +51,12 @@ class NET_EXPORT_PRIVATE CryptoSecretBoxer {
base::StringPiece* out) const;
private:
- mutable base::Lock lock_;
- // GUARDED_BY(lock_).mutable Mutex lock_;
- std::vector<std::string> keys_;
+ mutable QuicMutex lock_;
+ std::vector<std::string> keys_ GUARDED_BY(lock_);
DISALLOW_COPY_AND_ASSIGN(CryptoSecretBoxer);
};
} // namespace net
-#endif // NET_QUIC_CRYPTO_CRYPTO_SECRET_BOXER_H_
+#endif // NET_QUIC_CORE_CRYPTO_CRYPTO_SECRET_BOXER_H_
diff --git a/chromium/net/quic/core/crypto/crypto_secret_boxer_test.cc b/chromium/net/quic/core/crypto/crypto_secret_boxer_test.cc
index c7712f40b65..1e8c1d156cd 100644
--- a/chromium/net/quic/core/crypto/crypto_secret_boxer_test.cc
+++ b/chromium/net/quic/core/crypto/crypto_secret_boxer_test.cc
@@ -4,8 +4,6 @@
#include "net/quic/core/crypto/crypto_secret_boxer.h"
-#include <memory>
-
#include "net/quic/core/crypto/quic_random.h"
#include "testing/gtest/include/gtest/gtest.h"
diff --git a/chromium/net/quic/core/crypto/crypto_server_config_protobuf.h b/chromium/net/quic/core/crypto/crypto_server_config_protobuf.h
index bd5e6413eb9..82dafd84e43 100644
--- a/chromium/net/quic/core/crypto/crypto_server_config_protobuf.h
+++ b/chromium/net/quic/core/crypto/crypto_server_config_protobuf.h
@@ -2,11 +2,11 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#ifndef NET_QUIC_CRYPTO_CRYPTO_SERVER_CONFIG_PROTOBUF_H_
-#define NET_QUIC_CRYPTO_CRYPTO_SERVER_CONFIG_PROTOBUF_H_
+#ifndef NET_QUIC_CORE_CRYPTO_CRYPTO_SERVER_CONFIG_PROTOBUF_H_
+#define NET_QUIC_CORE_CRYPTO_CRYPTO_SERVER_CONFIG_PROTOBUF_H_
-#include <stddef.h>
-#include <stdint.h>
+#include <cstddef>
+#include <cstdint>
#include <memory>
#include <string>
@@ -16,20 +16,20 @@
#include "base/macros.h"
#include "base/memory/ptr_util.h"
#include "base/strings/string_piece.h"
-#include "net/base/net_export.h"
#include "net/quic/core/crypto/crypto_protocol.h"
+#include "net/quic/platform/api/quic_export.h"
namespace net {
// QuicServerConfigProtobuf contains QUIC server config block and the private
// keys needed to prove ownership.
// TODO(rch): sync with server more rationally.
-class NET_EXPORT_PRIVATE QuicServerConfigProtobuf {
+class QUIC_EXPORT_PRIVATE QuicServerConfigProtobuf {
public:
// PrivateKey contains a QUIC tag of a key exchange algorithm and a
// serialised private key for that algorithm. The format of the serialised
// private key is specific to the algorithm in question.
- class NET_EXPORT_PRIVATE PrivateKey {
+ class QUIC_EXPORT_PRIVATE PrivateKey {
public:
QuicTag tag() const { return tag_; }
void set_tag(QuicTag tag) { tag_ = tag; }
@@ -113,4 +113,4 @@ class NET_EXPORT_PRIVATE QuicServerConfigProtobuf {
} // namespace net
-#endif // NET_QUIC_CRYPTO_CRYPTO_SERVER_CONFIG_PROTOBUF_H_
+#endif // NET_QUIC_CORE_CRYPTO_CRYPTO_SERVER_CONFIG_PROTOBUF_H_
diff --git a/chromium/net/quic/core/crypto/crypto_server_test.cc b/chromium/net/quic/core/crypto/crypto_server_test.cc
index 51d15b29d00..941e2fedd0b 100644
--- a/chromium/net/quic/core/crypto/crypto_server_test.cc
+++ b/chromium/net/quic/core/crypto/crypto_server_test.cc
@@ -8,7 +8,6 @@
#include <ostream>
#include <vector>
-#include "base/strings/string_number_conversions.h"
#include "crypto/secure_hash.h"
#include "net/quic/core/crypto/cert_compressor.h"
#include "net/quic/core/crypto/common_cert_set.h"
@@ -21,8 +20,10 @@
#include "net/quic/core/quic_flags.h"
#include "net/quic/core/quic_socket_address_coder.h"
#include "net/quic/core/quic_utils.h"
+#include "net/quic/platform/api/quic_text_utils.h"
#include "net/quic/test_tools/crypto_test_utils.h"
#include "net/quic/test_tools/delayed_verify_strike_register_client.h"
+#include "net/quic/test_tools/failing_proof_source.h"
#include "net/quic/test_tools/mock_clock.h"
#include "net/quic/test_tools/mock_random.h"
#include "net/quic/test_tools/quic_crypto_server_config_peer.h"
@@ -30,8 +31,6 @@
#include "testing/gtest/include/gtest/gtest.h"
using base::StringPiece;
-using std::endl;
-using std::ostream;
using std::string;
namespace net {
@@ -47,7 +46,7 @@ class DummyProofVerifierCallback : public ProofVerifierCallback {
void Run(bool ok,
const std::string& error_details,
std::unique_ptr<ProofVerifyDetails>* details) override {
- // Do nothing
+ DCHECK(false);
}
};
@@ -63,7 +62,7 @@ struct TestParams {
use_stateless_rejects(use_stateless_rejects),
supported_versions(std::move(supported_versions)) {}
- friend ostream& operator<<(ostream& os, const TestParams& p) {
+ friend std::ostream& operator<<(std::ostream& os, const TestParams& p) {
os << " enable_stateless_rejects: " << p.enable_stateless_rejects
<< std::endl;
os << " use_stateless_rejects: " << p.use_stateless_rejects << std::endl;
@@ -105,24 +104,24 @@ class CryptoServerTest : public ::testing::TestWithParam<TestParams> {
public:
CryptoServerTest()
: rand_(QuicRandom::GetInstance()),
- client_address_(Loopback4(), 1234),
+ client_address_(QuicIpAddress::Loopback4(), 1234),
config_(QuicCryptoServerConfig::TESTING,
rand_,
CryptoTestUtils::ProofSourceForTesting()),
+ peer_(&config_),
compressed_certs_cache_(
QuicCompressedCertsCache::kQuicCompressedCertsCacheSize),
params_(new QuicCryptoNegotiatedParameters),
- crypto_proof_(new QuicCryptoProof),
+ signed_config_(new QuicSignedServerConfig),
chlo_packet_size_(kDefaultMaxPacketSize) {
supported_versions_ = GetParam().supported_versions;
config_.set_enable_serving_sct(true);
client_version_ = supported_versions_.front();
client_version_string_ =
- QuicUtils::TagToString(QuicVersionToQuicTag(client_version_));
+ QuicTagToString(QuicVersionToQuicTag(client_version_));
- FLAGS_quic_require_handshake_confirmation_pre33 = false;
- FLAGS_enable_quic_stateless_reject_support =
+ FLAGS_quic_reloadable_flag_enable_quic_stateless_reject_support =
GetParam().enable_stateless_rejects;
use_stateless_rejects_ = GetParam().use_stateless_rejects;
}
@@ -146,8 +145,9 @@ class CryptoServerTest : public ::testing::TestWithParam<TestParams> {
char public_value[32];
memset(public_value, 42, sizeof(public_value));
- nonce_hex_ = "#" + QuicUtils::HexEncode(GenerateNonce());
- pub_hex_ = "#" + QuicUtils::HexEncode(public_value, sizeof(public_value));
+ nonce_hex_ = "#" + QuicTextUtils::HexEncode(GenerateNonce());
+ pub_hex_ =
+ "#" + QuicTextUtils::HexEncode(public_value, sizeof(public_value));
// clang-format off
CryptoHandshakeMessage client_hello = CryptoTestUtils::Message(
@@ -173,18 +173,19 @@ class CryptoServerTest : public ::testing::TestWithParam<TestParams> {
StringPiece srct;
ASSERT_TRUE(out_.GetStringPiece(kSourceAddressTokenTag, &srct));
- srct_hex_ = "#" + QuicUtils::HexEncode(srct);
+ srct_hex_ = "#" + QuicTextUtils::HexEncode(srct);
StringPiece scfg;
ASSERT_TRUE(out_.GetStringPiece(kSCFG, &scfg));
- server_config_.reset(CryptoFramer::ParseMessage(scfg));
+ server_config_ = CryptoFramer::ParseMessage(scfg);
StringPiece scid;
ASSERT_TRUE(server_config_->GetStringPiece(kSCID, &scid));
- scid_hex_ = "#" + QuicUtils::HexEncode(scid);
+ scid_hex_ = "#" + QuicTextUtils::HexEncode(scid);
- crypto_proof_ = scoped_refptr<QuicCryptoProof>(new QuicCryptoProof());
- DCHECK(crypto_proof_->chain.get() == nullptr);
+ signed_config_ = QuicReferenceCountedPointer<QuicSignedServerConfig>(
+ new QuicSignedServerConfig());
+ DCHECK(signed_config_->chain.get() == nullptr);
}
// Helper used to accept the result of ValidateClientHello and pass
@@ -202,17 +203,8 @@ class CryptoServerTest : public ::testing::TestWithParam<TestParams> {
*called_ = false;
}
- void Run(scoped_refptr<Result> result,
+ void Run(QuicReferenceCountedPointer<Result> result,
std::unique_ptr<ProofSource::Details> /* details */) override {
- {
- // Ensure that the strike register client lock is not held.
- QuicCryptoServerConfigPeer peer(&test_->config_);
- base::Lock* m = peer.GetStrikeRegisterClientLock();
- // In Chromium, we will dead lock if the lock is held by the current
- // thread. Chromium doesn't have AssertNotHeld API call.
- // m->AssertNotHeld();
- base::AutoLock lock(*m);
- }
ASSERT_FALSE(*called_);
test_->ProcessValidationResult(std::move(result), should_succeed_,
error_substr_);
@@ -239,16 +231,16 @@ class CryptoServerTest : public ::testing::TestWithParam<TestParams> {
ASSERT_TRUE(server_hello.GetStringPiece(kCADR, &address));
QuicSocketAddressCoder decoder;
ASSERT_TRUE(decoder.Decode(address.data(), address.size()));
- EXPECT_EQ(client_address_.address(), decoder.ip());
+ EXPECT_EQ(client_address_.host(), decoder.ip());
EXPECT_EQ(client_address_.port(), decoder.port());
}
void ShouldSucceed(const CryptoHandshakeMessage& message) {
bool called = false;
- IPAddress server_ip;
+ QuicSocketAddress server_address;
config_.ValidateClientHello(
- message, client_address_.address(), server_ip,
- supported_versions_.front(), &clock_, crypto_proof_,
+ message, client_address_.host(), server_address,
+ supported_versions_.front(), &clock_, signed_config_,
std::unique_ptr<ValidateCallback>(
new ValidateCallback(this, true, "", &called)));
EXPECT_TRUE(called);
@@ -264,21 +256,22 @@ class CryptoServerTest : public ::testing::TestWithParam<TestParams> {
void ShouldFailMentioning(const char* error_substr,
const CryptoHandshakeMessage& message,
bool* called) {
- IPAddress server_ip;
+ QuicSocketAddress server_address;
config_.ValidateClientHello(
- message, client_address_.address(), server_ip,
- supported_versions_.front(), &clock_, crypto_proof_,
+ message, client_address_.host(), server_address,
+ supported_versions_.front(), &clock_, signed_config_,
std::unique_ptr<ValidateCallback>(
new ValidateCallback(this, false, error_substr, called)));
}
class ProcessCallback : public ProcessClientHelloResultCallback {
public:
- ProcessCallback(scoped_refptr<ValidateCallback::Result> result,
- bool should_succeed,
- const char* error_substr,
- bool* called,
- CryptoHandshakeMessage* out)
+ ProcessCallback(
+ QuicReferenceCountedPointer<ValidateCallback::Result> result,
+ bool should_succeed,
+ const char* error_substr,
+ bool* called,
+ CryptoHandshakeMessage* out)
: result_(std::move(result)),
should_succeed_(should_succeed),
error_substr_(error_substr),
@@ -294,12 +287,12 @@ class CryptoServerTest : public ::testing::TestWithParam<TestParams> {
std::unique_ptr<DiversificationNonce> diversification_nonce,
std::unique_ptr<ProofSource::Details> proof_source_details) override {
if (should_succeed_) {
- ASSERT_EQ(error, QUIC_NO_ERROR) << "Message failed with error "
- << error_details << ": "
- << result_->client_hello.DebugString();
+ ASSERT_EQ(error, QUIC_NO_ERROR)
+ << "Message failed with error " << error_details << ": "
+ << result_->client_hello.DebugString();
} else {
- ASSERT_NE(error, QUIC_NO_ERROR) << "Message didn't fail: "
- << result_->client_hello.DebugString();
+ ASSERT_NE(error, QUIC_NO_ERROR)
+ << "Message didn't fail: " << result_->client_hello.DebugString();
EXPECT_TRUE(error_details.find(error_substr_) != string::npos)
<< error_substr_ << " not in " << error_details;
@@ -311,25 +304,26 @@ class CryptoServerTest : public ::testing::TestWithParam<TestParams> {
}
private:
- const scoped_refptr<ValidateCallback::Result> result_;
+ const QuicReferenceCountedPointer<ValidateCallback::Result> result_;
const bool should_succeed_;
const char* const error_substr_;
bool* called_;
CryptoHandshakeMessage* out_;
};
- void ProcessValidationResult(scoped_refptr<ValidateCallback::Result> result,
- bool should_succeed,
- const char* error_substr) {
- IPAddress server_ip;
+ void ProcessValidationResult(
+ QuicReferenceCountedPointer<ValidateCallback::Result> result,
+ bool should_succeed,
+ const char* error_substr) {
+ QuicSocketAddress server_address;
QuicConnectionId server_designated_connection_id =
rand_for_id_generation_.RandUint64();
bool called;
config_.ProcessClientHello(
- result, /*reject_only=*/false, /*connection_id=*/1, server_ip,
+ result, /*reject_only=*/false, /*connection_id=*/1, server_address,
client_address_, supported_versions_.front(), supported_versions_,
use_stateless_rejects_, server_designated_connection_id, &clock_, rand_,
- &compressed_certs_cache_, params_, crypto_proof_,
+ &compressed_certs_cache_, params_, signed_config_,
/*total_framing_overhead=*/50, chlo_packet_size_,
std::unique_ptr<ProcessCallback>(new ProcessCallback(
result, should_succeed, error_substr, &called, &out_)));
@@ -380,9 +374,9 @@ class CryptoServerTest : public ::testing::TestWithParam<TestParams> {
void CheckRejectTag() {
if (RejectsAreStateless()) {
- ASSERT_EQ(kSREJ, out_.tag()) << QuicUtils::TagToString(out_.tag());
+ ASSERT_EQ(kSREJ, out_.tag()) << QuicTagToString(out_.tag());
} else {
- ASSERT_EQ(kREJ, out_.tag()) << QuicUtils::TagToString(out_.tag());
+ ASSERT_EQ(kREJ, out_.tag()) << QuicTagToString(out_.tag());
}
}
@@ -393,8 +387,8 @@ class CryptoServerTest : public ::testing::TestWithParam<TestParams> {
string XlctHexString() {
uint64_t xlct = CryptoTestUtils::LeafCertHashForTesting();
- return "#" +
- QuicUtils::HexEncode(reinterpret_cast<char*>(&xlct), sizeof(xlct));
+ return "#" + QuicTextUtils::HexEncode(reinterpret_cast<char*>(&xlct),
+ sizeof(xlct));
}
protected:
@@ -402,15 +396,16 @@ class CryptoServerTest : public ::testing::TestWithParam<TestParams> {
QuicRandom* const rand_;
MockRandom rand_for_id_generation_;
MockClock clock_;
- IPEndPoint client_address_;
+ QuicSocketAddress client_address_;
QuicVersionVector supported_versions_;
QuicVersion client_version_;
string client_version_string_;
QuicCryptoServerConfig config_;
+ QuicCryptoServerConfigPeer peer_;
QuicCompressedCertsCache compressed_certs_cache_;
QuicCryptoServerConfig::ConfigOptions config_options_;
- scoped_refptr<QuicCryptoNegotiatedParameters> params_;
- scoped_refptr<QuicCryptoProof> crypto_proof_;
+ QuicReferenceCountedPointer<QuicCryptoNegotiatedParameters> params_;
+ QuicReferenceCountedPointer<QuicSignedServerConfig> signed_config_;
CryptoHandshakeMessage out_;
uint8_t orbit_[kOrbitSize];
bool use_stateless_rejects_;
@@ -717,7 +712,7 @@ TEST_P(CryptoServerTest, DowngradeAttack) {
// Set the client's preferred version to a supported version that
// is not the "current" version (supported_versions_.front()).
string bad_version =
- QuicUtils::TagToString(QuicVersionToQuicTag(supported_versions_.back()));
+ QuicTagToString(QuicVersionToQuicTag(supported_versions_.back()));
// clang-format off
CryptoHandshakeMessage msg = CryptoTestUtils::Message(
@@ -826,16 +821,9 @@ TEST_P(CryptoServerTest, CorruptMultipleTags) {
ShouldSucceed(msg);
CheckRejectTag();
- if (client_version_ <= QUIC_VERSION_32) {
- const HandshakeFailureReason kRejectReasons[] = {
- SOURCE_ADDRESS_TOKEN_DECRYPTION_FAILURE, CLIENT_NONCE_INVALID_FAILURE,
- SERVER_NONCE_DECRYPTION_FAILURE};
- CheckRejectReasons(kRejectReasons, arraysize(kRejectReasons));
- } else {
- const HandshakeFailureReason kRejectReasons[] = {
- SOURCE_ADDRESS_TOKEN_DECRYPTION_FAILURE, CLIENT_NONCE_INVALID_FAILURE};
- CheckRejectReasons(kRejectReasons, arraysize(kRejectReasons));
- };
+ const HandshakeFailureReason kRejectReasons[] = {
+ SOURCE_ADDRESS_TOKEN_DECRYPTION_FAILURE, CLIENT_NONCE_INVALID_FAILURE};
+ CheckRejectReasons(kRejectReasons, arraysize(kRejectReasons));
}
TEST_P(CryptoServerTest, NoServerNonce) {
@@ -860,21 +848,14 @@ TEST_P(CryptoServerTest, NoServerNonce) {
ShouldSucceed(msg);
- if (client_version_ <= QUIC_VERSION_32) {
- CheckRejectTag();
- const HandshakeFailureReason kRejectReasons[] = {
- SERVER_NONCE_REQUIRED_FAILURE};
- CheckRejectReasons(kRejectReasons, arraysize(kRejectReasons));
- } else {
- // Even without a server nonce, this ClientHello should be accepted in
- // version 33.
- ASSERT_EQ(kSHLO, out_.tag());
- CheckServerHello(out_);
- }
+ // Even without a server nonce, this ClientHello should be accepted in
+ // version 33.
+ ASSERT_EQ(kSHLO, out_.tag());
+ CheckServerHello(out_);
}
TEST_P(CryptoServerTest, ProofForSuppliedServerConfig) {
- client_address_ = IPEndPoint(Loopback6(), 1234);
+ client_address_ = QuicSocketAddress(QuicIpAddress::Loopback6(), 1234);
// clang-format off
CryptoHandshakeMessage msg = CryptoTestUtils::Message(
"CHLO",
@@ -885,6 +866,7 @@ TEST_P(CryptoServerTest, ProofForSuppliedServerConfig) {
"#004b5453", srct_hex_.c_str(),
"PUBS", pub_hex_.c_str(),
"NONC", nonce_hex_.c_str(),
+ "NONP", "123456789012345678901234567890",
"VER\0", client_version_string_.c_str(),
"XLCT", XlctHexString().c_str(),
"$padding", static_cast<int>(kClientHelloMinimumSize),
@@ -975,7 +957,6 @@ TEST_P(CryptoServerTest, ValidXlct) {
"#004b5453", srct_hex_.c_str(),
"PUBS", pub_hex_.c_str(),
"NONC", nonce_hex_.c_str(),
- "NONP", "123456789012345678901234567890",
"VER\0", client_version_string_.c_str(),
"XLCT", XlctHexString().c_str(),
"$padding", static_cast<int>(kClientHelloMinimumSize),
@@ -1018,6 +999,28 @@ TEST_P(CryptoServerTest, NonceInSHLO) {
EXPECT_TRUE(out_.GetStringPiece(kServerNonceTag, &nonce));
}
+TEST_P(CryptoServerTest, ProofSourceFailure) {
+ // Install a ProofSource which will unconditionally fail
+ peer_.ResetProofSource(std::unique_ptr<ProofSource>(new FailingProofSource));
+
+ // clang-format off
+ CryptoHandshakeMessage msg = CryptoTestUtils::Message(
+ "CHLO",
+ "AEAD", "AESG",
+ "KEXS", "C255",
+ "SCID", scid_hex_.c_str(),
+ "PUBS", pub_hex_.c_str(),
+ "NONC", nonce_hex_.c_str(),
+ "PDMD", "X509",
+ "VER\0", client_version_string_.c_str(),
+ "$padding", static_cast<int>(kClientHelloMinimumSize),
+ nullptr);
+ // clang-format on
+
+ // Just ensure that we don't crash as occurred in b/33916924.
+ ShouldFailMentioning("", msg);
+}
+
TEST(CryptoServerConfigGenerationTest, Determinism) {
// Test that using a deterministic PRNG causes the server-config to be
// deterministic.
@@ -1120,7 +1123,7 @@ class CryptoServerTestOldVersion : public CryptoServerTest {
void SetUp() override {
client_version_ = supported_versions_.back();
client_version_string_ =
- QuicUtils::TagToString(QuicVersionToQuicTag(client_version_));
+ QuicTagToString(QuicVersionToQuicTag(client_version_));
CryptoServerTest::SetUp();
}
};
@@ -1174,117 +1177,5 @@ TEST_P(CryptoServerTestOldVersion, XlctNotRequired) {
EXPECT_EQ(kSHLO, out_.tag());
}
-class AsyncStrikeServerVerificationTest : public CryptoServerTest {
- protected:
- AsyncStrikeServerVerificationTest() {}
-
- void SetUp() override {
- const string kOrbit = "12345678";
- config_options_.orbit = kOrbit;
- strike_register_client_ = new DelayedVerifyStrikeRegisterClient(
- 10000, // strike_register_max_entries
- static_cast<uint32_t>(clock_.WallNow().ToUNIXSeconds()),
- 60, // strike_register_window_secs
- reinterpret_cast<const uint8_t*>(kOrbit.c_str()),
- StrikeRegister::NO_STARTUP_PERIOD_NEEDED);
- config_.SetStrikeRegisterClient(strike_register_client_);
- ASSERT_NO_FATAL_FAILURE(CryptoServerTest::SetUp());
- strike_register_client_->StartDelayingVerification();
- }
-
- DelayedVerifyStrikeRegisterClient* strike_register_client_;
-};
-
-TEST_P(AsyncStrikeServerVerificationTest, AsyncReplayProtection) {
- // This tests async validation with a strike register works.
- // clang-format off
- CryptoHandshakeMessage msg = CryptoTestUtils::Message(
- "CHLO",
- "PDMD", "X509",
- "AEAD", "AESG",
- "KEXS", "C255",
- "SCID", scid_hex_.c_str(),
- "#004b5453", srct_hex_.c_str(),
- "PUBS", pub_hex_.c_str(),
- "NONC", nonce_hex_.c_str(),
- "VER\0", client_version_string_.c_str(),
- "$padding", static_cast<int>(kClientHelloMinimumSize),
- nullptr);
- // clang-format on
-
- // Clear the message tag.
- out_.set_tag(0);
-
- bool called = false;
- IPAddress server_ip;
- config_.ValidateClientHello(
- msg, client_address_.address(), server_ip, client_version_, &clock_,
- crypto_proof_, std::unique_ptr<ValidateCallback>(
- new ValidateCallback(this, true, "", &called)));
- // The verification request was queued.
- ASSERT_FALSE(called);
- EXPECT_EQ(0u, out_.tag());
- EXPECT_EQ(1, strike_register_client_->PendingVerifications());
-
- // Continue processing the verification request.
- strike_register_client_->RunPendingVerifications();
- ASSERT_TRUE(called);
- EXPECT_EQ(0, strike_register_client_->PendingVerifications());
- // The message should be accepted now.
- EXPECT_EQ(kSHLO, out_.tag());
-
- // Rejected if replayed.
- config_.ValidateClientHello(
- msg, client_address_.address(), server_ip, client_version_, &clock_,
- crypto_proof_, std::unique_ptr<ValidateCallback>(
- new ValidateCallback(this, true, "", &called)));
- // The verification request was queued.
- ASSERT_FALSE(called);
- EXPECT_EQ(1, strike_register_client_->PendingVerifications());
-
- strike_register_client_->RunPendingVerifications();
- ASSERT_TRUE(called);
- EXPECT_EQ(0, strike_register_client_->PendingVerifications());
- // The message should be rejected now.
- CheckRejectTag();
-}
-
-TEST_P(AsyncStrikeServerVerificationTest, RequireHandshakeCofirmationPre33) {
- FLAGS_quic_require_handshake_confirmation = false;
- FLAGS_quic_require_handshake_confirmation_pre33 = true;
- // clang-format off
- CryptoHandshakeMessage msg = CryptoTestUtils::Message(
- "CHLO",
- "PDMD", "X509",
- "AEAD", "AESG",
- "KEXS", "C255",
- "SNI", "foobar1.example.com",
- "SCID", scid_hex_.c_str(),
- "#004b5453", srct_hex_.c_str(),
- "PUBS", pub_hex_.c_str(),
- "NONC", nonce_hex_.c_str(),
- "VER\0", client_version_string_.c_str(),
- "XLCT", XlctHexString().c_str(),
- "$padding", static_cast<int>(kClientHelloMinimumSize),
- nullptr);
- // clang-format on
-
- ShouldSucceed(msg);
-
- if (client_version_ <= QUIC_VERSION_32) {
- // clang-format off
- const HandshakeFailureReason kRejectReasons[] = {
- SERVER_NONCE_REQUIRED_FAILURE
- };
- // clang-format on
- CheckRejectReasons(kRejectReasons, arraysize(kRejectReasons));
- EXPECT_EQ(0, strike_register_client_->PendingVerifications());
- } else {
- // version 33.
- ASSERT_EQ(kSHLO, out_.tag());
- CheckServerHello(out_);
- }
-}
-
} // namespace test
} // namespace net
diff --git a/chromium/net/quic/core/crypto/crypto_utils.cc b/chromium/net/quic/core/crypto/crypto_utils.cc
index 64c15522105..15f4a99f1f1 100644
--- a/chromium/net/quic/core/crypto/crypto_utils.cc
+++ b/chromium/net/quic/core/crypto/crypto_utils.cc
@@ -14,13 +14,13 @@
#include "net/quic/core/crypto/quic_decrypter.h"
#include "net/quic/core/crypto/quic_encrypter.h"
#include "net/quic/core/crypto/quic_random.h"
-#include "net/quic/core/quic_bug_tracker.h"
#include "net/quic/core/quic_time.h"
#include "net/quic/core/quic_utils.h"
+#include "net/quic/platform/api/quic_bug_tracker.h"
+#include "net/quic/platform/api/quic_logging.h"
#include "url/url_canon.h"
using base::StringPiece;
-using std::numeric_limits;
using std::string;
namespace net {
@@ -186,13 +186,13 @@ bool CryptoUtils::ExportKeyingMaterial(StringPiece subkey_secret,
string* result) {
for (size_t i = 0; i < label.length(); i++) {
if (label[i] == '\0') {
- LOG(ERROR) << "ExportKeyingMaterial label may not contain NULs";
+ QUIC_LOG(ERROR) << "ExportKeyingMaterial label may not contain NULs";
return false;
}
}
// Create HKDF info input: null-terminated label + length-prefixed context
if (context.length() >= std::numeric_limits<uint32_t>::max()) {
- LOG(ERROR) << "Context value longer than 2^32";
+ QUIC_LOG(ERROR) << "Context value longer than 2^32";
return false;
}
uint32_t context_length = static_cast<uint32_t>(context.length());
@@ -208,8 +208,8 @@ bool CryptoUtils::ExportKeyingMaterial(StringPiece subkey_secret,
}
// static
-uint64_t CryptoUtils::ComputeLeafCertHash(const std::string& cert) {
- return QuicUtils::FNV1a_64_Hash(cert.data(), cert.size());
+uint64_t CryptoUtils::ComputeLeafCertHash(StringPiece cert) {
+ return QuicUtils::FNV1a_64_Hash(cert);
}
QuicErrorCode CryptoUtils::ValidateServerHello(
diff --git a/chromium/net/quic/core/crypto/crypto_utils.h b/chromium/net/quic/core/crypto/crypto_utils.h
index 60a4f0634bb..ee0825f3acb 100644
--- a/chromium/net/quic/core/crypto/crypto_utils.h
+++ b/chromium/net/quic/core/crypto/crypto_utils.h
@@ -4,30 +4,27 @@
//
// Some helpers for quic crypto
-#ifndef NET_QUIC_CRYPTO_CRYPTO_UTILS_H_
-#define NET_QUIC_CRYPTO_CRYPTO_UTILS_H_
-
-#include <stddef.h>
-#include <stdint.h>
+#ifndef NET_QUIC_CORE_CRYPTO_CRYPTO_UTILS_H_
+#define NET_QUIC_CORE_CRYPTO_CRYPTO_UTILS_H_
+#include <cstddef>
+#include <cstdint>
#include <string>
#include "base/macros.h"
#include "base/strings/string_piece.h"
-#include "net/base/net_export.h"
#include "net/quic/core/crypto/crypto_handshake.h"
#include "net/quic/core/crypto/crypto_handshake_message.h"
#include "net/quic/core/crypto/crypto_protocol.h"
-#include "net/quic/core/quic_protocol.h"
+#include "net/quic/core/quic_packets.h"
#include "net/quic/core/quic_time.h"
+#include "net/quic/platform/api/quic_export.h"
namespace net {
-class QuicTime;
class QuicRandom;
-struct QuicCryptoNegotiatedParameters;
-class NET_EXPORT_PRIVATE CryptoUtils {
+class QUIC_EXPORT_PRIVATE CryptoUtils {
public:
// Diversification is a utility class that's used to act like a union type.
// Values can be created by calling the functions like |NoDiversification|,
@@ -129,7 +126,7 @@ class NET_EXPORT_PRIVATE CryptoUtils {
// Computes the FNV-1a hash of the provided DER-encoded cert for use in the
// XLCT tag.
- static uint64_t ComputeLeafCertHash(const std::string& cert);
+ static uint64_t ComputeLeafCertHash(base::StringPiece cert);
// Validates that |server_hello| is actually an SHLO message and that it is
// not part of a downgrade attack.
@@ -167,4 +164,4 @@ class NET_EXPORT_PRIVATE CryptoUtils {
} // namespace net
-#endif // NET_QUIC_CRYPTO_CRYPTO_UTILS_H_
+#endif // NET_QUIC_CORE_CRYPTO_CRYPTO_UTILS_H_
diff --git a/chromium/net/quic/core/crypto/crypto_utils_test.cc b/chromium/net/quic/core/crypto/crypto_utils_test.cc
index 34035233799..0d5bea0da76 100644
--- a/chromium/net/quic/core/crypto/crypto_utils_test.cc
+++ b/chromium/net/quic/core/crypto/crypto_utils_test.cc
@@ -4,6 +4,8 @@
#include "net/quic/core/crypto/crypto_utils.h"
+#include "net/quic/core/quic_utils.h"
+#include "net/quic/platform/api/quic_text_utils.h"
#include "net/quic/test_tools/quic_test_utils.h"
#include "testing/gtest/include/gtest/gtest.h"
@@ -18,9 +20,8 @@ TEST(CryptoUtilsTest, IsValidSNI) {
EXPECT_FALSE(CryptoUtils::IsValidSNI("192.168.0.1"));
// SNI without any dot.
EXPECT_FALSE(CryptoUtils::IsValidSNI("somedomain"));
- // Invalid RFC2396 hostname
- // TODO(rtenneti): Support RFC2396 hostname.
- // EXPECT_FALSE(CryptoUtils::IsValidSNI("some_domain.com"));
+ // Invalid by RFC2396 but unfortunately domains of this form exist.
+ EXPECT_TRUE(CryptoUtils::IsValidSNI("some_domain.com"));
// An empty string must be invalid otherwise the QUIC client will try sending
// it.
EXPECT_FALSE(CryptoUtils::IsValidSNI(""));
@@ -93,14 +94,15 @@ TEST(CryptoUtilsTest, TestExportKeyingMaterial) {
for (size_t i = 0; i < arraysize(test_vector); i++) {
// Decode the test vector.
- string subkey_secret = QuicUtils::HexDecode(test_vector[i].subkey_secret);
- string label = QuicUtils::HexDecode(test_vector[i].label);
- string context = QuicUtils::HexDecode(test_vector[i].context);
+ string subkey_secret =
+ QuicTextUtils::HexDecode(test_vector[i].subkey_secret);
+ string label = QuicTextUtils::HexDecode(test_vector[i].label);
+ string context = QuicTextUtils::HexDecode(test_vector[i].context);
size_t result_len = test_vector[i].result_len;
bool expect_ok = test_vector[i].expected != nullptr;
string expected;
if (expect_ok) {
- expected = QuicUtils::HexDecode(test_vector[i].expected);
+ expected = QuicTextUtils::HexDecode(test_vector[i].expected);
}
string result;
diff --git a/chromium/net/quic/core/crypto/curve25519_key_exchange.cc b/chromium/net/quic/core/crypto/curve25519_key_exchange.cc
index 7bb7e30569f..99e62cbfe19 100644
--- a/chromium/net/quic/core/crypto/curve25519_key_exchange.cc
+++ b/chromium/net/quic/core/crypto/curve25519_key_exchange.cc
@@ -4,9 +4,10 @@
#include "net/quic/core/crypto/curve25519_key_exchange.h"
-#include "base/logging.h"
-#include "crypto/curve25519.h"
+#include <cstdint>
+
#include "net/quic/core/crypto/quic_random.h"
+#include "third_party/boringssl/src/include/openssl/curve25519.h"
using base::StringPiece;
using std::string;
@@ -20,35 +21,29 @@ Curve25519KeyExchange::~Curve25519KeyExchange() {}
// static
Curve25519KeyExchange* Curve25519KeyExchange::New(StringPiece private_key) {
Curve25519KeyExchange* ka;
- // We don't want to #include the NaCl headers in the public header file, so
- // we use literals for the sizes of private_key_ and public_key_. Here we
- // assert that those values are equal to the values from the NaCl header.
- static_assert(sizeof(ka->private_key_) == crypto::curve25519::kScalarBytes,
+ // We don't want to #include the BoringSSL headers in the public header file,
+ // so we use literals for the sizes of private_key_ and public_key_. Here we
+ // assert that those values are equal to the values from the BoringSSL
+ // header.
+ static_assert(sizeof(ka->private_key_) == X25519_PRIVATE_KEY_LEN,
"header out of sync");
- static_assert(sizeof(ka->public_key_) == crypto::curve25519::kBytes,
+ static_assert(sizeof(ka->public_key_) == X25519_PUBLIC_VALUE_LEN,
"header out of sync");
- if (private_key.size() != crypto::curve25519::kScalarBytes) {
+ if (private_key.size() != X25519_PRIVATE_KEY_LEN) {
return nullptr;
}
ka = new Curve25519KeyExchange();
- memcpy(ka->private_key_, private_key.data(),
- crypto::curve25519::kScalarBytes);
- crypto::curve25519::ScalarBaseMult(ka->private_key_, ka->public_key_);
+ memcpy(ka->private_key_, private_key.data(), X25519_PRIVATE_KEY_LEN);
+ X25519_public_from_private(ka->public_key_, ka->private_key_);
return ka;
}
// static
string Curve25519KeyExchange::NewPrivateKey(QuicRandom* rand) {
- uint8_t private_key[crypto::curve25519::kScalarBytes];
+ uint8_t private_key[X25519_PRIVATE_KEY_LEN];
rand->RandBytes(private_key, sizeof(private_key));
-
- // This makes |private_key| a valid scalar, as specified on
- // http://cr.yp.to/ecdh.html
- private_key[0] &= 248;
- private_key[31] &= 127;
- private_key[31] |= 64;
return string(reinterpret_cast<char*>(private_key), sizeof(private_key));
}
@@ -59,18 +54,17 @@ KeyExchange* Curve25519KeyExchange::NewKeyPair(QuicRandom* rand) const {
bool Curve25519KeyExchange::CalculateSharedKey(StringPiece peer_public_value,
string* out_result) const {
- if (peer_public_value.size() != crypto::curve25519::kBytes) {
+ if (peer_public_value.size() != X25519_PUBLIC_VALUE_LEN) {
return false;
}
- uint8_t result[crypto::curve25519::kBytes];
- if (!crypto::curve25519::ScalarMult(
- private_key_,
- reinterpret_cast<const uint8_t*>(peer_public_value.data()), result)) {
+ uint8_t result[X25519_PUBLIC_VALUE_LEN];
+ if (!X25519(result, private_key_,
+ reinterpret_cast<const uint8_t*>(peer_public_value.data()))) {
return false;
}
- out_result->assign(reinterpret_cast<char*>(result), sizeof(result));
+ out_result->assign(reinterpret_cast<char*>(result), sizeof(result));
return true;
}
diff --git a/chromium/net/quic/core/crypto/curve25519_key_exchange.h b/chromium/net/quic/core/crypto/curve25519_key_exchange.h
index 6f1bfe45db0..0515e8d7d4e 100644
--- a/chromium/net/quic/core/crypto/curve25519_key_exchange.h
+++ b/chromium/net/quic/core/crypto/curve25519_key_exchange.h
@@ -2,17 +2,16 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#ifndef NET_QUIC_CRYPTO_CURVE25519_KEY_EXCHANGE_H_
-#define NET_QUIC_CRYPTO_CURVE25519_KEY_EXCHANGE_H_
-
-#include <stdint.h>
+#ifndef NET_QUIC_CORE_CRYPTO_CURVE25519_KEY_EXCHANGE_H_
+#define NET_QUIC_CORE_CRYPTO_CURVE25519_KEY_EXCHANGE_H_
+#include <cstdint>
#include <string>
#include "base/compiler_specific.h"
#include "base/strings/string_piece.h"
-#include "net/base/net_export.h"
#include "net/quic/core/crypto/key_exchange.h"
+#include "net/quic/platform/api/quic_export.h"
namespace net {
@@ -20,7 +19,7 @@ class QuicRandom;
// Curve25519KeyExchange implements a KeyExchange using elliptic-curve
// Diffie-Hellman on curve25519. See http://cr.yp.to/ecdh.html
-class NET_EXPORT_PRIVATE Curve25519KeyExchange : public KeyExchange {
+class QUIC_EXPORT_PRIVATE Curve25519KeyExchange : public KeyExchange {
public:
~Curve25519KeyExchange() override;
@@ -48,4 +47,4 @@ class NET_EXPORT_PRIVATE Curve25519KeyExchange : public KeyExchange {
} // namespace net
-#endif // NET_QUIC_CRYPTO_CURVE25519_KEY_EXCHANGE_H_
+#endif // NET_QUIC_CORE_CRYPTO_CURVE25519_KEY_EXCHANGE_H_
diff --git a/chromium/net/quic/core/crypto/curve25519_key_exchange_test.cc b/chromium/net/quic/core/crypto/curve25519_key_exchange_test.cc
index dcd33527c1b..8dad0886a13 100644
--- a/chromium/net/quic/core/crypto/curve25519_key_exchange_test.cc
+++ b/chromium/net/quic/core/crypto/curve25519_key_exchange_test.cc
@@ -6,7 +6,6 @@
#include <memory>
-#include "base/strings/string_piece.h"
#include "net/quic/core/crypto/quic_random.h"
#include "testing/gtest/include/gtest/gtest.h"
diff --git a/chromium/net/quic/core/crypto/ephemeral_key_source.h b/chromium/net/quic/core/crypto/ephemeral_key_source.h
index e99b687ed98..f05fa28e9c6 100644
--- a/chromium/net/quic/core/crypto/ephemeral_key_source.h
+++ b/chromium/net/quic/core/crypto/ephemeral_key_source.h
@@ -2,14 +2,14 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#ifndef NET_QUIC_CRYPTO_EPHEMERAL_KEY_SOURCE_H_
-#define NET_QUIC_CRYPTO_EPHEMERAL_KEY_SOURCE_H_
+#ifndef NET_QUIC_CORE_CRYPTO_EPHEMERAL_KEY_SOURCE_H_
+#define NET_QUIC_CORE_CRYPTO_EPHEMERAL_KEY_SOURCE_H_
#include <string>
#include "base/strings/string_piece.h"
-#include "net/base/net_export.h"
#include "net/quic/core/quic_time.h"
+#include "net/quic/platform/api/quic_export.h"
namespace net {
@@ -20,7 +20,7 @@ class QuicRandom;
// for several connections in a short space of time. Since the implementation
// of this may involve locking or thread-local data, this interface abstracts
// that away.
-class NET_EXPORT_PRIVATE EphemeralKeySource {
+class QUIC_EXPORT_PRIVATE EphemeralKeySource {
public:
virtual ~EphemeralKeySource() {}
@@ -39,4 +39,4 @@ class NET_EXPORT_PRIVATE EphemeralKeySource {
} // namespace net
-#endif // NET_QUIC_CRYPTO_EPHEMERAL_KEY_SOURCE_H_
+#endif // NET_QUIC_CORE_CRYPTO_EPHEMERAL_KEY_SOURCE_H_
diff --git a/chromium/net/quic/core/crypto/key_exchange.h b/chromium/net/quic/core/crypto/key_exchange.h
index 7e4c6f0889b..69da86e92fd 100644
--- a/chromium/net/quic/core/crypto/key_exchange.h
+++ b/chromium/net/quic/core/crypto/key_exchange.h
@@ -2,14 +2,14 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#ifndef NET_QUIC_CRYPTO_KEY_EXCHANGE_H_
-#define NET_QUIC_CRYPTO_KEY_EXCHANGE_H_
+#ifndef NET_QUIC_CORE_CRYPTO_KEY_EXCHANGE_H_
+#define NET_QUIC_CORE_CRYPTO_KEY_EXCHANGE_H_
#include <string>
#include "base/strings/string_piece.h"
-#include "net/base/net_export.h"
#include "net/quic/core/crypto/crypto_protocol.h"
+#include "net/quic/platform/api/quic_export.h"
namespace net {
@@ -17,7 +17,7 @@ class QuicRandom;
// KeyExchange is an abstract class that provides an interface to a
// key-exchange primitive.
-class NET_EXPORT_PRIVATE KeyExchange {
+class QUIC_EXPORT_PRIVATE KeyExchange {
public:
virtual ~KeyExchange() {}
@@ -44,4 +44,4 @@ class NET_EXPORT_PRIVATE KeyExchange {
} // namespace net
-#endif // NET_QUIC_CRYPTO_KEY_EXCHANGE_H_
+#endif // NET_QUIC_CORE_CRYPTO_KEY_EXCHANGE_H_
diff --git a/chromium/net/quic/core/crypto/local_strike_register_client.cc b/chromium/net/quic/core/crypto/local_strike_register_client.cc
index bd70e0b320f..1327818aaaf 100644
--- a/chromium/net/quic/core/crypto/local_strike_register_client.cc
+++ b/chromium/net/quic/core/crypto/local_strike_register_client.cc
@@ -24,7 +24,7 @@ LocalStrikeRegisterClient::LocalStrikeRegisterClient(
startup) {}
bool LocalStrikeRegisterClient::IsKnownOrbit(StringPiece orbit) const {
- base::AutoLock lock(m_);
+ QuicWriterMutexLock lock(&m_);
if (orbit.length() != kOrbitSize) {
return false;
}
@@ -39,7 +39,7 @@ void LocalStrikeRegisterClient::VerifyNonceIsValidAndUnique(
if (nonce.length() != kNonceSize) {
nonce_error = NONCE_INVALID_FAILURE;
} else {
- base::AutoLock lock(m_);
+ QuicWriterMutexLock lock(&m_);
nonce_error =
strike_register_.Insert(reinterpret_cast<const uint8_t*>(nonce.data()),
static_cast<uint32_t>(now.ToUNIXSeconds()));
diff --git a/chromium/net/quic/core/crypto/local_strike_register_client.h b/chromium/net/quic/core/crypto/local_strike_register_client.h
index f1d043c599e..2679bc2f66d 100644
--- a/chromium/net/quic/core/crypto/local_strike_register_client.h
+++ b/chromium/net/quic/core/crypto/local_strike_register_client.h
@@ -2,24 +2,24 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#ifndef NET_QUIC_CRYPTO_LOCAL_STRIKE_REGISTER_CLIENT_H_
-#define NET_QUIC_CRYPTO_LOCAL_STRIKE_REGISTER_CLIENT_H_
+#ifndef NET_QUIC_CORE_CRYPTO_LOCAL_STRIKE_REGISTER_CLIENT_H_
+#define NET_QUIC_CORE_CRYPTO_LOCAL_STRIKE_REGISTER_CLIENT_H_
-#include <stdint.h>
+#include <cstdint>
#include "base/macros.h"
#include "base/strings/string_piece.h"
-#include "base/synchronization/lock.h"
-#include "net/base/net_export.h"
#include "net/quic/core/crypto/strike_register.h"
#include "net/quic/core/crypto/strike_register_client.h"
#include "net/quic/core/quic_time.h"
+#include "net/quic/platform/api/quic_export.h"
+#include "net/quic/platform/api/quic_mutex.h"
namespace net {
// StrikeRegisterClient implementation that wraps a local in-memory
// strike register.
-class NET_EXPORT_PRIVATE LocalStrikeRegisterClient
+class QUIC_EXPORT_PRIVATE LocalStrikeRegisterClient
: public StrikeRegisterClient {
public:
LocalStrikeRegisterClient(unsigned max_entries,
@@ -34,12 +34,12 @@ class NET_EXPORT_PRIVATE LocalStrikeRegisterClient
ResultCallback* cb) override;
private:
- mutable base::Lock m_;
- StrikeRegister strike_register_;
+ mutable QuicMutex m_;
+ StrikeRegister strike_register_ GUARDED_BY(m_);
DISALLOW_COPY_AND_ASSIGN(LocalStrikeRegisterClient);
};
} // namespace net
-#endif // NET_QUIC_CRYPTO_LOCAL_STRIKE_REGISTER_CLIENT_H_
+#endif // NET_QUIC_CORE_CRYPTO_LOCAL_STRIKE_REGISTER_CLIENT_H_
diff --git a/chromium/net/quic/core/crypto/local_strike_register_client_test.cc b/chromium/net/quic/core/crypto/local_strike_register_client_test.cc
index e28e627ed44..684f9bd106e 100644
--- a/chromium/net/quic/core/crypto/local_strike_register_client_test.cc
+++ b/chromium/net/quic/core/crypto/local_strike_register_client_test.cc
@@ -11,6 +11,7 @@
#include "base/sys_byteorder.h"
#include "net/quic/core/crypto/crypto_protocol.h"
#include "net/quic/core/quic_time.h"
+#include "net/quic/platform/api/quic_str_cat.h"
#include "testing/gtest/include/gtest/gtest.h"
using base::StringPiece;
@@ -81,10 +82,11 @@ TEST_F(LocalStrikeRegisterClientTest, CheckOrbit) {
TEST_F(LocalStrikeRegisterClientTest, IncorrectNonceLength) {
string valid_nonce;
- uint32_t norder = htonl(kCurrentTimeExternalSecs);
+ uint32_t norder = base::HostToNet32(kCurrentTimeExternalSecs);
valid_nonce.assign(reinterpret_cast<const char*>(&norder), sizeof(norder));
- valid_nonce.append(string(reinterpret_cast<const char*>(kOrbit), kOrbitSize));
- valid_nonce.append(string(20, '\x17')); // 20 'random' bytes.
+ valid_nonce = QuicStrCat(
+ valid_nonce, string(reinterpret_cast<const char*>(kOrbit), kOrbitSize),
+ string(20, '\x17')); // 20 'random' bytes.
{
// Validation fails if you remove a byte from the nonce.
@@ -105,8 +107,7 @@ TEST_F(LocalStrikeRegisterClientTest, IncorrectNonceLength) {
bool called = false;
bool is_valid = false;
InsertStatus nonce_error = NONCE_UNKNOWN_FAILURE;
- string long_nonce(valid_nonce);
- long_nonce.append("a");
+ string long_nonce = QuicStrCat(valid_nonce, "a");
strike_register_->VerifyNonceIsValidAndUnique(
long_nonce, QuicWallTime::FromUNIXSeconds(kCurrentTimeExternalSecs),
new RecordResultCallback(&called, &is_valid, &nonce_error));
diff --git a/chromium/net/quic/core/crypto/null_decrypter.cc b/chromium/net/quic/core/crypto/null_decrypter.cc
index dabbff59b46..dbc6db97480 100644
--- a/chromium/net/quic/core/crypto/null_decrypter.cc
+++ b/chromium/net/quic/core/crypto/null_decrypter.cc
@@ -4,18 +4,20 @@
#include "net/quic/core/crypto/null_decrypter.h"
-#include <stdint.h>
+#include <cstdint>
-#include "net/quic/core/quic_bug_tracker.h"
+#include "net/base/int128.h"
#include "net/quic/core/quic_data_reader.h"
#include "net/quic/core/quic_utils.h"
+#include "net/quic/platform/api/quic_bug_tracker.h"
using base::StringPiece;
using std::string;
namespace net {
-NullDecrypter::NullDecrypter() {}
+NullDecrypter::NullDecrypter(Perspective perspective)
+ : perspective_(perspective) {}
bool NullDecrypter::SetKey(StringPiece key) {
return key.empty();
@@ -35,7 +37,8 @@ bool NullDecrypter::SetDiversificationNonce(const DiversificationNonce& nonce) {
return true;
}
-bool NullDecrypter::DecryptPacket(QuicPathId /*path_id*/,
+bool NullDecrypter::DecryptPacket(QuicVersion version,
+ QuicPathId /*path_id*/,
QuicPacketNumber /*packet_number*/,
StringPiece associated_data,
StringPiece ciphertext,
@@ -54,7 +57,7 @@ bool NullDecrypter::DecryptPacket(QuicPathId /*path_id*/,
QUIC_BUG << "Output buffer must be larger than the plaintext.";
return false;
}
- if (hash != ComputeHash(associated_data, plaintext)) {
+ if (hash != ComputeHash(version, associated_data, plaintext)) {
return false;
}
// Copy the plaintext to output.
@@ -85,17 +88,27 @@ bool NullDecrypter::ReadHash(QuicDataReader* reader, uint128* hash) {
if (!reader->ReadUInt64(&lo) || !reader->ReadUInt32(&hi)) {
return false;
}
- *hash = hi;
- *hash <<= 64;
- *hash += lo;
+ *hash = MakeUint128(hi, lo);
return true;
}
-uint128 NullDecrypter::ComputeHash(const StringPiece data1,
+uint128 NullDecrypter::ComputeHash(QuicVersion version,
+ const StringPiece data1,
const StringPiece data2) const {
- uint128 correct_hash = QuicUtils::FNV1a_128_Hash_Two(
- data1.data(), data1.length(), data2.data(), data2.length());
- uint128 mask(UINT64_C(0x0), UINT64_C(0xffffffff));
+ uint128 correct_hash;
+ if (version > QUIC_VERSION_36) {
+ if (perspective_ == Perspective::IS_CLIENT) {
+ // Peer is a server.
+ correct_hash = QuicUtils::FNV1a_128_Hash_Three(data1, data2, "Server");
+
+ } else {
+ // Peer is a client.
+ correct_hash = QuicUtils::FNV1a_128_Hash_Three(data1, data2, "Client");
+ }
+ } else {
+ correct_hash = QuicUtils::FNV1a_128_Hash_Two(data1, data2);
+ }
+ uint128 mask = MakeUint128(UINT64_C(0x0), UINT64_C(0xffffffff));
mask <<= 96;
correct_hash &= ~mask;
return correct_hash;
diff --git a/chromium/net/quic/core/crypto/null_decrypter.h b/chromium/net/quic/core/crypto/null_decrypter.h
index 0e5a2202ad9..3f6aecb5e66 100644
--- a/chromium/net/quic/core/crypto/null_decrypter.h
+++ b/chromium/net/quic/core/crypto/null_decrypter.h
@@ -2,16 +2,18 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#ifndef NET_QUIC_CRYPTO_NULL_DECRYPTER_H_
-#define NET_QUIC_CRYPTO_NULL_DECRYPTER_H_
+#ifndef NET_QUIC_CORE_CRYPTO_NULL_DECRYPTER_H_
+#define NET_QUIC_CORE_CRYPTO_NULL_DECRYPTER_H_
-#include <stddef.h>
-#include <stdint.h>
+#include <cstddef>
+#include <cstdint>
#include "base/compiler_specific.h"
#include "base/macros.h"
-#include "net/base/net_export.h"
+#include "net/base/int128.h"
#include "net/quic/core/crypto/quic_decrypter.h"
+#include "net/quic/core/quic_types.h"
+#include "net/quic/platform/api/quic_export.h"
namespace net {
@@ -20,9 +22,9 @@ class QuicDataReader;
// A NullDecrypter is a QuicDecrypter used before a crypto negotiation
// has occurred. It does not actually decrypt the payload, but does
// verify a hash (fnv128) over both the payload and associated data.
-class NET_EXPORT_PRIVATE NullDecrypter : public QuicDecrypter {
+class QUIC_EXPORT_PRIVATE NullDecrypter : public QuicDecrypter {
public:
- NullDecrypter();
+ explicit NullDecrypter(Perspective perspective);
~NullDecrypter() override {}
// QuicDecrypter implementation
@@ -30,7 +32,8 @@ class NET_EXPORT_PRIVATE NullDecrypter : public QuicDecrypter {
bool SetNoncePrefix(base::StringPiece nonce_prefix) override;
bool SetPreliminaryKey(base::StringPiece key) override;
bool SetDiversificationNonce(const DiversificationNonce& nonce) override;
- bool DecryptPacket(QuicPathId path_id,
+ bool DecryptPacket(QuicVersion version,
+ QuicPathId path_id,
QuicPacketNumber packet_number,
base::StringPiece associated_data,
base::StringPiece ciphertext,
@@ -45,11 +48,15 @@ class NET_EXPORT_PRIVATE NullDecrypter : public QuicDecrypter {
private:
bool ReadHash(QuicDataReader* reader, uint128* hash);
- uint128 ComputeHash(base::StringPiece data1, base::StringPiece data2) const;
+ uint128 ComputeHash(QuicVersion version,
+ base::StringPiece data1,
+ base::StringPiece data2) const;
+
+ Perspective perspective_;
DISALLOW_COPY_AND_ASSIGN(NullDecrypter);
};
} // namespace net
-#endif // NET_QUIC_CRYPTO_NULL_DECRYPTER_H_
+#endif // NET_QUIC_CORE_CRYPTO_NULL_DECRYPTER_H_
diff --git a/chromium/net/quic/core/crypto/null_decrypter_test.cc b/chromium/net/quic/core/crypto/null_decrypter_test.cc
index d615f344602..56d20c2ccb6 100644
--- a/chromium/net/quic/core/crypto/null_decrypter_test.cc
+++ b/chromium/net/quic/core/crypto/null_decrypter_test.cc
@@ -12,7 +12,64 @@ namespace test {
class NullDecrypterTest : public ::testing::TestWithParam<bool> {};
-TEST_F(NullDecrypterTest, Decrypt) {
+TEST_F(NullDecrypterTest, DecryptClient) {
+ unsigned char expected[] = {
+ // fnv hash
+ 0x97, 0xdc, 0x27, 0x2f, 0x18, 0xa8, 0x56, 0x73, 0xdf, 0x8d, 0x1d, 0xd0,
+ // payload
+ 'g', 'o', 'o', 'd', 'b', 'y', 'e', '!',
+ };
+ const char* data = reinterpret_cast<const char*>(expected);
+ size_t len = arraysize(expected);
+ NullDecrypter decrypter(Perspective::IS_SERVER);
+ char buffer[256];
+ size_t length = 0;
+ ASSERT_TRUE(decrypter.DecryptPacket(QUIC_VERSION_37, kDefaultPathId, 0,
+ "hello world!", StringPiece(data, len),
+ buffer, &length, 256));
+ EXPECT_LT(0u, length);
+ EXPECT_EQ("goodbye!", StringPiece(buffer, length));
+}
+
+TEST_F(NullDecrypterTest, DecryptServer) {
+ unsigned char expected[] = {
+ // fnv hash
+ 0x63, 0x5e, 0x08, 0x03, 0x32, 0x80, 0x8f, 0x73, 0xdf, 0x8d, 0x1d, 0x1a,
+ // payload
+ 'g', 'o', 'o', 'd', 'b', 'y', 'e', '!',
+ };
+ const char* data = reinterpret_cast<const char*>(expected);
+ size_t len = arraysize(expected);
+ NullDecrypter decrypter(Perspective::IS_CLIENT);
+ char buffer[256];
+ size_t length = 0;
+ ASSERT_TRUE(decrypter.DecryptPacket(QUIC_VERSION_37, kDefaultPathId, 0,
+ "hello world!", StringPiece(data, len),
+ buffer, &length, 256));
+ EXPECT_LT(0u, length);
+ EXPECT_EQ("goodbye!", StringPiece(buffer, length));
+}
+
+TEST_F(NullDecrypterTest, DecryptClientPre37) {
+ unsigned char expected[] = {
+ // fnv hash
+ 0xa0, 0x6f, 0x44, 0x8a, 0x44, 0xf8, 0x18, 0x3b, 0x47, 0x91, 0xb2, 0x13,
+ // payload
+ 'g', 'o', 'o', 'd', 'b', 'y', 'e', '!',
+ };
+ const char* data = reinterpret_cast<const char*>(expected);
+ size_t len = arraysize(expected);
+ NullDecrypter decrypter(Perspective::IS_CLIENT);
+ char buffer[256];
+ size_t length = 0;
+ ASSERT_TRUE(decrypter.DecryptPacket(QUIC_VERSION_36, kDefaultPathId, 0,
+ "hello world!", StringPiece(data, len),
+ buffer, &length, 256));
+ EXPECT_LT(0u, length);
+ EXPECT_EQ("goodbye!", StringPiece(buffer, length));
+}
+
+TEST_F(NullDecrypterTest, DecryptServerPre37) {
unsigned char expected[] = {
// fnv hash
0xa0, 0x6f, 0x44, 0x8a, 0x44, 0xf8, 0x18, 0x3b, 0x47, 0x91, 0xb2, 0x13,
@@ -21,12 +78,12 @@ TEST_F(NullDecrypterTest, Decrypt) {
};
const char* data = reinterpret_cast<const char*>(expected);
size_t len = arraysize(expected);
- NullDecrypter decrypter;
+ NullDecrypter decrypter(Perspective::IS_SERVER);
char buffer[256];
size_t length = 0;
- ASSERT_TRUE(decrypter.DecryptPacket(kDefaultPathId, 0, "hello world!",
- StringPiece(data, len), buffer, &length,
- 256));
+ ASSERT_TRUE(decrypter.DecryptPacket(QUIC_VERSION_36, kDefaultPathId, 0,
+ "hello world!", StringPiece(data, len),
+ buffer, &length, 256));
EXPECT_LT(0u, length);
EXPECT_EQ("goodbye!", StringPiece(buffer, length));
}
@@ -40,12 +97,12 @@ TEST_F(NullDecrypterTest, BadHash) {
};
const char* data = reinterpret_cast<const char*>(expected);
size_t len = arraysize(expected);
- NullDecrypter decrypter;
+ NullDecrypter decrypter(Perspective::IS_CLIENT);
char buffer[256];
size_t length = 0;
- ASSERT_FALSE(decrypter.DecryptPacket(kDefaultPathId, 0, "hello world!",
- StringPiece(data, len), buffer, &length,
- 256));
+ ASSERT_FALSE(decrypter.DecryptPacket(QUIC_VERSION_35, kDefaultPathId, 0,
+ "hello world!", StringPiece(data, len),
+ buffer, &length, 256));
}
TEST_F(NullDecrypterTest, ShortInput) {
@@ -55,12 +112,12 @@ TEST_F(NullDecrypterTest, ShortInput) {
};
const char* data = reinterpret_cast<const char*>(expected);
size_t len = arraysize(expected);
- NullDecrypter decrypter;
+ NullDecrypter decrypter(Perspective::IS_CLIENT);
char buffer[256];
size_t length = 0;
- ASSERT_FALSE(decrypter.DecryptPacket(kDefaultPathId, 0, "hello world!",
- StringPiece(data, len), buffer, &length,
- 256));
+ ASSERT_FALSE(decrypter.DecryptPacket(QUIC_VERSION_35, kDefaultPathId, 0,
+ "hello world!", StringPiece(data, len),
+ buffer, &length, 256));
}
} // namespace test
diff --git a/chromium/net/quic/core/crypto/null_encrypter.cc b/chromium/net/quic/core/crypto/null_encrypter.cc
index 6fbe53fa784..986563bd852 100644
--- a/chromium/net/quic/core/crypto/null_encrypter.cc
+++ b/chromium/net/quic/core/crypto/null_encrypter.cc
@@ -14,7 +14,8 @@ namespace net {
const size_t kHashSizeShort = 12; // size of uint128 serialized short
-NullEncrypter::NullEncrypter() {}
+NullEncrypter::NullEncrypter(Perspective perspective)
+ : perspective_(perspective) {}
bool NullEncrypter::SetKey(StringPiece key) {
return key.empty();
@@ -24,7 +25,8 @@ bool NullEncrypter::SetNoncePrefix(StringPiece nonce_prefix) {
return nonce_prefix.empty();
}
-bool NullEncrypter::EncryptPacket(QuicPathId /*path_id*/,
+bool NullEncrypter::EncryptPacket(QuicVersion version,
+ QuicPathId /*path_id*/,
QuicPacketNumber /*packet_number*/,
StringPiece associated_data,
StringPiece plaintext,
@@ -35,9 +37,18 @@ bool NullEncrypter::EncryptPacket(QuicPathId /*path_id*/,
if (max_output_length < len) {
return false;
}
- uint128 hash = QuicUtils::FNV1a_128_Hash_Two(
- associated_data.data(), associated_data.size(), plaintext.data(),
- plaintext.size());
+ uint128 hash;
+ if (version > QUIC_VERSION_36) {
+ if (perspective_ == Perspective::IS_SERVER) {
+ hash =
+ QuicUtils::FNV1a_128_Hash_Three(associated_data, plaintext, "Server");
+ } else {
+ hash =
+ QuicUtils::FNV1a_128_Hash_Three(associated_data, plaintext, "Client");
+ }
+ } else {
+ hash = QuicUtils::FNV1a_128_Hash_Two(associated_data, plaintext);
+ }
// TODO(ianswett): memmove required for in place encryption. Placing the
// hash at the end would allow use of memcpy, doing nothing for in place.
memmove(output + GetHashLength(), plaintext.data(), plaintext.length());
diff --git a/chromium/net/quic/core/crypto/null_encrypter.h b/chromium/net/quic/core/crypto/null_encrypter.h
index 5ea31eb67cf..96b1bb72562 100644
--- a/chromium/net/quic/core/crypto/null_encrypter.h
+++ b/chromium/net/quic/core/crypto/null_encrypter.h
@@ -2,30 +2,32 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#ifndef NET_QUIC_CRYPTO_NULL_ENCRYPTER_H_
-#define NET_QUIC_CRYPTO_NULL_ENCRYPTER_H_
+#ifndef NET_QUIC_CORE_CRYPTO_NULL_ENCRYPTER_H_
+#define NET_QUIC_CORE_CRYPTO_NULL_ENCRYPTER_H_
-#include <stddef.h>
+#include <cstddef>
#include "base/compiler_specific.h"
#include "base/macros.h"
-#include "net/base/net_export.h"
#include "net/quic/core/crypto/quic_encrypter.h"
+#include "net/quic/core/quic_types.h"
+#include "net/quic/platform/api/quic_export.h"
namespace net {
// A NullEncrypter is a QuicEncrypter used before a crypto negotiation
// has occurred. It does not actually encrypt the payload, but does
// generate a MAC (fnv128) over both the payload and associated data.
-class NET_EXPORT_PRIVATE NullEncrypter : public QuicEncrypter {
+class QUIC_EXPORT_PRIVATE NullEncrypter : public QuicEncrypter {
public:
- NullEncrypter();
+ explicit NullEncrypter(Perspective perspective);
~NullEncrypter() override {}
// QuicEncrypter implementation
bool SetKey(base::StringPiece key) override;
bool SetNoncePrefix(base::StringPiece nonce_prefix) override;
- bool EncryptPacket(QuicPathId path_id,
+ bool EncryptPacket(QuicVersion version,
+ QuicPathId path_id,
QuicPacketNumber packet_number,
base::StringPiece associated_data,
base::StringPiece plaintext,
@@ -42,9 +44,11 @@ class NET_EXPORT_PRIVATE NullEncrypter : public QuicEncrypter {
private:
size_t GetHashLength() const;
+ Perspective perspective_;
+
DISALLOW_COPY_AND_ASSIGN(NullEncrypter);
};
} // namespace net
-#endif // NET_QUIC_CRYPTO_NULL_ENCRYPTER_H_
+#endif // NET_QUIC_CORE_CRYPTO_NULL_ENCRYPTER_H_
diff --git a/chromium/net/quic/core/crypto/null_encrypter_test.cc b/chromium/net/quic/core/crypto/null_encrypter_test.cc
index 8987807c66b..e0296e4915b 100644
--- a/chromium/net/quic/core/crypto/null_encrypter_test.cc
+++ b/chromium/net/quic/core/crypto/null_encrypter_test.cc
@@ -12,33 +12,87 @@ namespace test {
class NullEncrypterTest : public ::testing::TestWithParam<bool> {};
-TEST_F(NullEncrypterTest, Encrypt) {
+TEST_F(NullEncrypterTest, EncryptClient) {
+ unsigned char expected[] = {
+ // fnv hash
+ 0x97, 0xdc, 0x27, 0x2f, 0x18, 0xa8, 0x56, 0x73, 0xdf, 0x8d, 0x1d, 0xd0,
+ // payload
+ 'g', 'o', 'o', 'd', 'b', 'y', 'e', '!',
+ };
+ char encrypted[256];
+ size_t encrypted_len = 0;
+ NullEncrypter encrypter(Perspective::IS_CLIENT);
+ ASSERT_TRUE(encrypter.EncryptPacket(QUIC_VERSION_37, kDefaultPathId, 0,
+ "hello world!", "goodbye!", encrypted,
+ &encrypted_len, 256));
+ test::CompareCharArraysWithHexError(
+ "encrypted data", encrypted, encrypted_len,
+ reinterpret_cast<const char*>(expected), arraysize(expected));
+}
+
+TEST_F(NullEncrypterTest, EncryptServer) {
+ unsigned char expected[] = {
+ // fnv hash
+ 0x63, 0x5e, 0x08, 0x03, 0x32, 0x80, 0x8f, 0x73, 0xdf, 0x8d, 0x1d, 0x1a,
+ // payload
+ 'g', 'o', 'o', 'd', 'b', 'y', 'e', '!',
+ };
+ char encrypted[256];
+ size_t encrypted_len = 0;
+ NullEncrypter encrypter(Perspective::IS_SERVER);
+ ASSERT_TRUE(encrypter.EncryptPacket(QUIC_VERSION_37, kDefaultPathId, 0,
+ "hello world!", "goodbye!", encrypted,
+ &encrypted_len, 256));
+ test::CompareCharArraysWithHexError(
+ "encrypted data", encrypted, encrypted_len,
+ reinterpret_cast<const char*>(expected), arraysize(expected));
+}
+
+TEST_F(NullEncrypterTest, EncryptClientPre37) {
+ unsigned char expected[] = {
+ // fnv hash
+ 0xa0, 0x6f, 0x44, 0x8a, 0x44, 0xf8, 0x18, 0x3b, 0x47, 0x91, 0xb2, 0x13,
+ // payload
+ 'g', 'o', 'o', 'd', 'b', 'y', 'e', '!',
+ };
+ char encrypted[256];
+ size_t encrypted_len = 0;
+ NullEncrypter encrypter(Perspective::IS_CLIENT);
+ ASSERT_TRUE(encrypter.EncryptPacket(QUIC_VERSION_36, kDefaultPathId, 0,
+ "hello world!", "goodbye!", encrypted,
+ &encrypted_len, 256));
+ test::CompareCharArraysWithHexError(
+ "encrypted data", encrypted, encrypted_len,
+ reinterpret_cast<const char*>(expected), arraysize(expected));
+}
+
+TEST_F(NullEncrypterTest, EncryptServerPre37) {
unsigned char expected[] = {
// fnv hash
0xa0, 0x6f, 0x44, 0x8a, 0x44, 0xf8, 0x18, 0x3b, 0x47, 0x91, 0xb2, 0x13,
// payload
'g', 'o', 'o', 'd', 'b', 'y', 'e', '!',
};
- NullEncrypter encrypter;
char encrypted[256];
size_t encrypted_len = 0;
- ASSERT_TRUE(encrypter.EncryptPacket(kDefaultPathId, 0, "hello world!",
- "goodbye!", encrypted, &encrypted_len,
- 256));
+ NullEncrypter encrypter(Perspective::IS_SERVER);
+ ASSERT_TRUE(encrypter.EncryptPacket(QUIC_VERSION_36, kDefaultPathId, 0,
+ "hello world!", "goodbye!", encrypted,
+ &encrypted_len, 256));
test::CompareCharArraysWithHexError(
"encrypted data", encrypted, encrypted_len,
reinterpret_cast<const char*>(expected), arraysize(expected));
}
TEST_F(NullEncrypterTest, GetMaxPlaintextSize) {
- NullEncrypter encrypter;
+ NullEncrypter encrypter(Perspective::IS_CLIENT);
EXPECT_EQ(1000u, encrypter.GetMaxPlaintextSize(1012));
EXPECT_EQ(100u, encrypter.GetMaxPlaintextSize(112));
EXPECT_EQ(10u, encrypter.GetMaxPlaintextSize(22));
}
TEST_F(NullEncrypterTest, GetCiphertextSize) {
- NullEncrypter encrypter;
+ NullEncrypter encrypter(Perspective::IS_CLIENT);
EXPECT_EQ(1012u, encrypter.GetCiphertextSize(1000));
EXPECT_EQ(112u, encrypter.GetCiphertextSize(100));
EXPECT_EQ(22u, encrypter.GetCiphertextSize(10));
diff --git a/chromium/net/quic/core/crypto/p256_key_exchange.cc b/chromium/net/quic/core/crypto/p256_key_exchange.cc
index bfef92476c8..1e4d956ed99 100644
--- a/chromium/net/quic/core/crypto/p256_key_exchange.cc
+++ b/chromium/net/quic/core/crypto/p256_key_exchange.cc
@@ -4,11 +4,15 @@
#include "net/quic/core/crypto/p256_key_exchange.h"
+#include <cstdint>
+#include <memory>
+#include <string>
#include <utility>
-#include "base/logging.h"
+#include "net/quic/platform/api/quic_logging.h"
#include "third_party/boringssl/src/include/openssl/ec.h"
#include "third_party/boringssl/src/include/openssl/ecdh.h"
+#include "third_party/boringssl/src/include/openssl/err.h"
#include "third_party/boringssl/src/include/openssl/evp.h"
using base::StringPiece;
@@ -27,7 +31,7 @@ P256KeyExchange::~P256KeyExchange() {}
// static
P256KeyExchange* P256KeyExchange::New(StringPiece key) {
if (key.empty()) {
- DVLOG(1) << "Private key is empty";
+ QUIC_DLOG(INFO) << "Private key is empty";
return nullptr;
}
@@ -35,7 +39,7 @@ P256KeyExchange* P256KeyExchange::New(StringPiece key) {
bssl::UniquePtr<EC_KEY> private_key(
d2i_ECPrivateKey(nullptr, &keyp, key.size()));
if (!private_key.get() || !EC_KEY_check_key(private_key.get())) {
- DVLOG(1) << "Private key is invalid.";
+ QUIC_DLOG(INFO) << "Private key is invalid.";
return nullptr;
}
@@ -44,7 +48,7 @@ P256KeyExchange* P256KeyExchange::New(StringPiece key) {
EC_KEY_get0_public_key(private_key.get()),
POINT_CONVERSION_UNCOMPRESSED, public_key,
sizeof(public_key), nullptr) != sizeof(public_key)) {
- DVLOG(1) << "Can't get public key.";
+ QUIC_DLOG(INFO) << "Can't get public key.";
return nullptr;
}
@@ -55,19 +59,19 @@ P256KeyExchange* P256KeyExchange::New(StringPiece key) {
string P256KeyExchange::NewPrivateKey() {
bssl::UniquePtr<EC_KEY> key(EC_KEY_new_by_curve_name(NID_X9_62_prime256v1));
if (!key.get() || !EC_KEY_generate_key(key.get())) {
- DVLOG(1) << "Can't generate a new private key.";
+ QUIC_DLOG(INFO) << "Can't generate a new private key.";
return string();
}
int key_len = i2d_ECPrivateKey(key.get(), nullptr);
if (key_len <= 0) {
- DVLOG(1) << "Can't convert private key to string";
+ QUIC_DLOG(INFO) << "Can't convert private key to string";
return string();
}
std::unique_ptr<uint8_t[]> private_key(new uint8_t[key_len]);
uint8_t* keyp = private_key.get();
if (!i2d_ECPrivateKey(key.get(), &keyp)) {
- DVLOG(1) << "Can't convert private key to string.";
+ QUIC_DLOG(INFO) << "Can't convert private key to string.";
return string();
}
return string(reinterpret_cast<char*>(private_key.get()), key_len);
@@ -82,26 +86,26 @@ KeyExchange* P256KeyExchange::NewKeyPair(QuicRandom* /*rand*/) const {
bool P256KeyExchange::CalculateSharedKey(StringPiece peer_public_value,
string* out_result) const {
if (peer_public_value.size() != kUncompressedP256PointBytes) {
- DVLOG(1) << "Peer public value is invalid";
+ QUIC_DLOG(INFO) << "Peer public value is invalid";
return false;
}
bssl::UniquePtr<EC_POINT> point(
EC_POINT_new(EC_KEY_get0_group(private_key_.get())));
- if (!point ||
+ if (!point.get() ||
!EC_POINT_oct2point(/* also test if point is on curve */
EC_KEY_get0_group(private_key_.get()), point.get(),
reinterpret_cast<const uint8_t*>(
peer_public_value.data()),
peer_public_value.size(), nullptr)) {
- DVLOG(1) << "Can't convert peer public value to curve point.";
+ QUIC_DLOG(INFO) << "Can't convert peer public value to curve point.";
return false;
}
uint8_t result[kP256FieldBytes];
if (ECDH_compute_key(result, sizeof(result), point.get(), private_key_.get(),
nullptr) != sizeof(result)) {
- DVLOG(1) << "Can't compute ECDH shared key.";
+ QUIC_DLOG(INFO) << "Can't compute ECDH shared key.";
return false;
}
diff --git a/chromium/net/quic/core/crypto/p256_key_exchange.h b/chromium/net/quic/core/crypto/p256_key_exchange.h
index 059cd2084e5..60c64fa9e6a 100644
--- a/chromium/net/quic/core/crypto/p256_key_exchange.h
+++ b/chromium/net/quic/core/crypto/p256_key_exchange.h
@@ -2,26 +2,23 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#ifndef NET_QUIC_CRYPTO_P256_KEY_EXCHANGE_H_
-#define NET_QUIC_CRYPTO_P256_KEY_EXCHANGE_H_
+#ifndef NET_QUIC_CORE_CRYPTO_P256_KEY_EXCHANGE_H_
+#define NET_QUIC_CORE_CRYPTO_P256_KEY_EXCHANGE_H_
-#include <stdint.h>
-
-#include <memory>
+#include <cstdint>
#include <string>
#include "base/macros.h"
#include "base/strings/string_piece.h"
-#include "crypto/openssl_util.h"
-#include "net/base/net_export.h"
#include "net/quic/core/crypto/key_exchange.h"
+#include "net/quic/platform/api/quic_export.h"
#include "third_party/boringssl/src/include/openssl/base.h"
namespace net {
// P256KeyExchange implements a KeyExchange using elliptic-curve
// Diffie-Hellman on NIST P-256.
-class NET_EXPORT_PRIVATE P256KeyExchange : public KeyExchange {
+class QUIC_EXPORT_PRIVATE P256KeyExchange : public KeyExchange {
public:
~P256KeyExchange() override;
@@ -66,4 +63,5 @@ class NET_EXPORT_PRIVATE P256KeyExchange : public KeyExchange {
};
} // namespace net
-#endif // NET_QUIC_CRYPTO_P256_KEY_EXCHANGE_H_
+
+#endif // NET_QUIC_CORE_CRYPTO_P256_KEY_EXCHANGE_H_
diff --git a/chromium/net/quic/core/crypto/p256_key_exchange_test.cc b/chromium/net/quic/core/crypto/p256_key_exchange_test.cc
index 7f6812288f1..564382cbd50 100644
--- a/chromium/net/quic/core/crypto/p256_key_exchange_test.cc
+++ b/chromium/net/quic/core/crypto/p256_key_exchange_test.cc
@@ -6,7 +6,6 @@
#include <memory>
-#include "base/logging.h"
#include "testing/gtest/include/gtest/gtest.h"
using std::string;
diff --git a/chromium/net/quic/core/crypto/proof_source.cc b/chromium/net/quic/core/crypto/proof_source.cc
index 9a72345f090..7b7f38be57e 100644
--- a/chromium/net/quic/core/crypto/proof_source.cc
+++ b/chromium/net/quic/core/crypto/proof_source.cc
@@ -4,10 +4,11 @@
#include "net/quic/core/crypto/proof_source.h"
+using std::string;
+
namespace net {
-ProofSource::Chain::Chain(const std::vector<std::string>& certs)
- : certs(certs) {}
+ProofSource::Chain::Chain(const std::vector<string>& certs) : certs(certs) {}
ProofSource::Chain::~Chain() {}
diff --git a/chromium/net/quic/core/crypto/proof_source.h b/chromium/net/quic/core/crypto/proof_source.h
index 281da105496..8fd184f65d2 100644
--- a/chromium/net/quic/core/crypto/proof_source.h
+++ b/chromium/net/quic/core/crypto/proof_source.h
@@ -2,37 +2,36 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#ifndef NET_QUIC_CRYPTO_PROOF_SOURCE_H_
-#define NET_QUIC_CRYPTO_PROOF_SOURCE_H_
+#ifndef NET_QUIC_CORE_CRYPTO_PROOF_SOURCE_H_
+#define NET_QUIC_CORE_CRYPTO_PROOF_SOURCE_H_
#include <memory>
#include <string>
#include <vector>
-#include "base/memory/ref_counted.h"
-#include "net/base/net_export.h"
-#include "net/quic/core/quic_protocol.h"
+#include "net/quic/core/crypto/quic_crypto_proof.h"
+#include "net/quic/core/quic_packets.h"
+#include "net/quic/platform/api/quic_export.h"
+#include "net/quic/platform/api/quic_reference_counted.h"
+#include "net/quic/platform/api/quic_socket_address.h"
namespace net {
-class IPAddress;
-
// ProofSource is an interface by which a QUIC server can obtain certificate
// chains and signatures that prove its identity.
-class NET_EXPORT_PRIVATE ProofSource {
+class QUIC_EXPORT_PRIVATE ProofSource {
public:
- // Chain is a reference-counted wrapper for a std::vector of std::stringified
+ // Chain is a reference-counted wrapper for a vector of stringified
// certificates.
- struct NET_EXPORT_PRIVATE Chain : public base::RefCounted<Chain> {
+ struct QUIC_EXPORT_PRIVATE Chain : public QuicReferenceCounted {
explicit Chain(const std::vector<std::string>& certs);
const std::vector<std::string> certs;
- private:
- friend class base::RefCounted<Chain>;
-
- virtual ~Chain();
+ protected:
+ ~Chain() override;
+ private:
DISALLOW_COPY_AND_ASSIGN(Chain);
};
@@ -65,9 +64,8 @@ class NET_EXPORT_PRIVATE ProofSource {
// any, gathered during the operation of GetProof. If no stats are
// available, this will be nullptr.
virtual void Run(bool ok,
- const scoped_refptr<Chain>& chain,
- const std::string& signature,
- const std::string& leaf_cert_sct,
+ const QuicReferenceCountedPointer<Chain>& chain,
+ const QuicCryptoProof& proof,
std::unique_ptr<Details> details) = 0;
private:
@@ -104,21 +102,20 @@ class NET_EXPORT_PRIVATE ProofSource {
// cert.
//
// This function may be called concurrently.
- virtual bool GetProof(const IPAddress& server_ip,
+ virtual bool GetProof(const QuicSocketAddress& server_address,
const std::string& hostname,
const std::string& server_config,
QuicVersion quic_version,
base::StringPiece chlo_hash,
const QuicTagVector& connection_options,
- scoped_refptr<Chain>* out_chain,
- std::string* out_signature,
- std::string* out_leaf_cert_sct) = 0;
+ QuicReferenceCountedPointer<Chain>* out_chain,
+ QuicCryptoProof* out_proof) = 0;
// Async version of GetProof with identical semantics, except that the results
// are delivered to |callback|. Callers should expect that |callback| might
// be invoked synchronously. The ProofSource takes ownership of |callback| in
// any case.
- virtual void GetProof(const IPAddress& server_ip,
+ virtual void GetProof(const QuicSocketAddress& server_address,
const std::string& hostname,
const std::string& server_config,
QuicVersion quic_version,
@@ -129,4 +126,4 @@ class NET_EXPORT_PRIVATE ProofSource {
} // namespace net
-#endif // NET_QUIC_CRYPTO_PROOF_SOURCE_H_
+#endif // NET_QUIC_CORE_CRYPTO_PROOF_SOURCE_H_
diff --git a/chromium/net/quic/core/crypto/proof_verifier.h b/chromium/net/quic/core/crypto/proof_verifier.h
index c87b5c8ccfe..fdde1598e3a 100644
--- a/chromium/net/quic/core/crypto/proof_verifier.h
+++ b/chromium/net/quic/core/crypto/proof_verifier.h
@@ -2,23 +2,23 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#ifndef NET_QUIC_CRYPTO_PROOF_VERIFIER_H_
-#define NET_QUIC_CRYPTO_PROOF_VERIFIER_H_
+#ifndef NET_QUIC_CORE_CRYPTO_PROOF_VERIFIER_H_
+#define NET_QUIC_CORE_CRYPTO_PROOF_VERIFIER_H_
#include <memory>
#include <string>
#include <vector>
-#include "net/base/net_export.h"
-#include "net/quic/core/quic_protocol.h"
+#include "net/quic/core/quic_packets.h"
#include "net/quic/core/quic_types.h"
+#include "net/quic/platform/api/quic_export.h"
namespace net {
// ProofVerifyDetails is an abstract class that acts as a container for any
// implementation specific details that a ProofVerifier wishes to return. These
// details are saved in the CachedState for the origin in question.
-class NET_EXPORT_PRIVATE ProofVerifyDetails {
+class QUIC_EXPORT_PRIVATE ProofVerifyDetails {
public:
virtual ~ProofVerifyDetails() {}
@@ -29,14 +29,14 @@ class NET_EXPORT_PRIVATE ProofVerifyDetails {
// ProofVerifyContext is an abstract class that acts as a container for any
// implementation specific context that a ProofVerifier needs.
-class NET_EXPORT_PRIVATE ProofVerifyContext {
+class QUIC_EXPORT_PRIVATE ProofVerifyContext {
public:
virtual ~ProofVerifyContext() {}
};
// ProofVerifierCallback provides a generic mechanism for a ProofVerifier to
// call back after an asynchronous verification.
-class NET_EXPORT_PRIVATE ProofVerifierCallback {
+class QUIC_EXPORT_PRIVATE ProofVerifierCallback {
public:
virtual ~ProofVerifierCallback() {}
@@ -53,7 +53,7 @@ class NET_EXPORT_PRIVATE ProofVerifierCallback {
// A ProofVerifier checks the signature on a server config, and the certificate
// chain that backs the public key.
-class NET_EXPORT_PRIVATE ProofVerifier {
+class QUIC_EXPORT_PRIVATE ProofVerifier {
public:
virtual ~ProofVerifier() {}
@@ -110,4 +110,4 @@ class NET_EXPORT_PRIVATE ProofVerifier {
} // namespace net
-#endif // NET_QUIC_CRYPTO_PROOF_VERIFIER_H_
+#endif // NET_QUIC_CORE_CRYPTO_PROOF_VERIFIER_H_
diff --git a/chromium/net/quic/core/crypto/quic_compressed_certs_cache.cc b/chromium/net/quic/core/crypto/quic_compressed_certs_cache.cc
index a18f021fa8f..c9ba5301beb 100644
--- a/chromium/net/quic/core/crypto/quic_compressed_certs_cache.cc
+++ b/chromium/net/quic/core/crypto/quic_compressed_certs_cache.cc
@@ -18,10 +18,11 @@ inline void hash_combine(uint64_t* seed, const uint64_t& val) {
} // namespace
-QuicCompressedCertsCache::UncompressedCerts::UncompressedCerts() {}
+QuicCompressedCertsCache::UncompressedCerts::UncompressedCerts()
+ : chain(nullptr) {}
QuicCompressedCertsCache::UncompressedCerts::UncompressedCerts(
- const scoped_refptr<ProofSource::Chain>& chain,
+ const QuicReferenceCountedPointer<ProofSource::Chain>& chain,
const string* client_common_set_hashes,
const string* client_cached_cert_hashes)
: chain(chain),
@@ -67,7 +68,7 @@ QuicCompressedCertsCache::~QuicCompressedCertsCache() {
}
const string* QuicCompressedCertsCache::GetCompressedCert(
- const scoped_refptr<ProofSource::Chain>& chain,
+ const QuicReferenceCountedPointer<ProofSource::Chain>& chain,
const string& client_common_set_hashes,
const string& client_cached_cert_hashes) {
UncompressedCerts uncompressed_certs(chain, &client_common_set_hashes,
@@ -75,19 +76,16 @@ const string* QuicCompressedCertsCache::GetCompressedCert(
uint64_t key = ComputeUncompressedCertsHash(uncompressed_certs);
- auto cached_it = certs_cache_.Get(key);
-
- if (cached_it != certs_cache_.end()) {
- const CachedCerts& cached_value = cached_it->second;
- if (cached_value.MatchesUncompressedCerts(uncompressed_certs)) {
- return cached_value.compressed_cert();
- }
+ CachedCerts* cached_value = certs_cache_.Lookup(key);
+ if (cached_value != nullptr &&
+ cached_value->MatchesUncompressedCerts(uncompressed_certs)) {
+ return cached_value->compressed_cert();
}
return nullptr;
}
void QuicCompressedCertsCache::Insert(
- const scoped_refptr<ProofSource::Chain>& chain,
+ const QuicReferenceCountedPointer<ProofSource::Chain>& chain,
const string& client_common_set_hashes,
const string& client_cached_cert_hashes,
const string& compressed_cert) {
@@ -97,15 +95,17 @@ void QuicCompressedCertsCache::Insert(
uint64_t key = ComputeUncompressedCertsHash(uncompressed_certs);
// Insert one unit to the cache.
- certs_cache_.Put(key, CachedCerts(uncompressed_certs, compressed_cert));
+ std::unique_ptr<CachedCerts> cached_certs(
+ new CachedCerts(uncompressed_certs, compressed_cert));
+ certs_cache_.Insert(key, std::move(cached_certs));
}
size_t QuicCompressedCertsCache::MaxSize() {
- return certs_cache_.max_size();
+ return certs_cache_.MaxSize();
}
size_t QuicCompressedCertsCache::Size() {
- return certs_cache_.size();
+ return certs_cache_.Size();
}
uint64_t QuicCompressedCertsCache::ComputeUncompressedCertsHash(
diff --git a/chromium/net/quic/core/crypto/quic_compressed_certs_cache.h b/chromium/net/quic/core/crypto/quic_compressed_certs_cache.h
index 84989f77052..ce480e35859 100644
--- a/chromium/net/quic/core/crypto/quic_compressed_certs_cache.h
+++ b/chromium/net/quic/core/crypto/quic_compressed_certs_cache.h
@@ -2,21 +2,20 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#ifndef NET_QUIC_CRYPTO_QUIC_COMPRESSED_CERTS_CACHE_H_
-#define NET_QUIC_CRYPTO_QUIC_COMPRESSED_CERTS_CACHE_H_
+#ifndef NET_QUIC_CORE_CRYPTO_QUIC_COMPRESSED_CERTS_CACHE_H_
+#define NET_QUIC_CORE_CRYPTO_QUIC_COMPRESSED_CERTS_CACHE_H_
#include <string>
#include <vector>
-#include "base/containers/mru_cache.h"
-#include "base/memory/ref_counted.h"
-#include "net/base/net_export.h"
#include "net/quic/core/crypto/proof_source.h"
+#include "net/quic/platform/api/quic_export.h"
+#include "net/quic/platform/api/quic_lru_cache.h"
namespace net {
// QuicCompressedCertsCache is a cache to track most recently compressed certs.
-class NET_EXPORT_PRIVATE QuicCompressedCertsCache {
+class QUIC_EXPORT_PRIVATE QuicCompressedCertsCache {
public:
explicit QuicCompressedCertsCache(int64_t max_num_certs);
~QuicCompressedCertsCache();
@@ -26,7 +25,7 @@ class NET_EXPORT_PRIVATE QuicCompressedCertsCache {
// Otherwise, return nullptr.
// Returned pointer might become invalid on the next call to Insert().
const std::string* GetCompressedCert(
- const scoped_refptr<ProofSource::Chain>& chain,
+ const QuicReferenceCountedPointer<ProofSource::Chain>& chain,
const std::string& client_common_set_hashes,
const std::string& client_cached_cert_hashes);
@@ -35,7 +34,7 @@ class NET_EXPORT_PRIVATE QuicCompressedCertsCache {
// client_cached_cert_hashes, compressed_cert| tuple to the cache.
// If the insertion causes the cache to become overfull, entries will
// be deleted in an LRU order to make room.
- void Insert(const scoped_refptr<ProofSource::Chain>& chain,
+ void Insert(const QuicReferenceCountedPointer<ProofSource::Chain>& chain,
const std::string& client_common_set_hashes,
const std::string& client_cached_cert_hashes,
const std::string& compressed_cert);
@@ -55,12 +54,13 @@ class NET_EXPORT_PRIVATE QuicCompressedCertsCache {
// to identify uncompressed representation of certs.
struct UncompressedCerts {
UncompressedCerts();
- UncompressedCerts(const scoped_refptr<ProofSource::Chain>& chain,
- const std::string* client_common_set_hashes,
- const std::string* client_cached_cert_hashes);
+ UncompressedCerts(
+ const QuicReferenceCountedPointer<ProofSource::Chain>& chain,
+ const std::string* client_common_set_hashes,
+ const std::string* client_cached_cert_hashes);
~UncompressedCerts();
- const scoped_refptr<ProofSource::Chain> chain;
+ const QuicReferenceCountedPointer<ProofSource::Chain> chain;
const std::string* client_common_set_hashes;
const std::string* client_cached_cert_hashes;
};
@@ -74,7 +74,6 @@ class NET_EXPORT_PRIVATE QuicCompressedCertsCache {
CachedCerts(const UncompressedCerts& uncompressed_certs,
const std::string& compressed_cert);
CachedCerts(const CachedCerts& other);
-
~CachedCerts();
// Returns true if the |uncompressed_certs| matches uncompressed
@@ -86,7 +85,7 @@ class NET_EXPORT_PRIVATE QuicCompressedCertsCache {
private:
// Uncompressed certs data.
- scoped_refptr<ProofSource::Chain> chain_;
+ QuicReferenceCountedPointer<ProofSource::Chain> chain_;
const std::string client_common_set_hashes_;
const std::string client_cached_cert_hashes_;
@@ -101,9 +100,9 @@ class NET_EXPORT_PRIVATE QuicCompressedCertsCache {
// Key is a unit64_t hash for UncompressedCerts. Stored associated value is
// CachedCerts which has both original uncompressed certs data and the
// compressed representation of the certs.
- base::MRUCache<uint64_t, CachedCerts> certs_cache_;
+ QuicLRUCache<uint64_t, CachedCerts> certs_cache_;
};
} // namespace net
-#endif // NET_QUIC_CRYPTO_QUIC_COMPRESSED_CERTS_CACHE_H_
+#endif // NET_QUIC_CORE_CRYPTO_QUIC_COMPRESSED_CERTS_CACHE_H_
diff --git a/chromium/net/quic/core/crypto/quic_compressed_certs_cache_test.cc b/chromium/net/quic/core/crypto/quic_compressed_certs_cache_test.cc
index 1ac853a550e..4abfca0a0c4 100644
--- a/chromium/net/quic/core/crypto/quic_compressed_certs_cache_test.cc
+++ b/chromium/net/quic/core/crypto/quic_compressed_certs_cache_test.cc
@@ -4,13 +4,13 @@
#include "net/quic/core/crypto/quic_compressed_certs_cache.h"
-#include "base/logging.h"
#include "base/macros.h"
-#include "base/strings/string_number_conversions.h"
#include "net/quic/core/crypto/cert_compressor.h"
+#include "net/quic/platform/api/quic_text_utils.h"
#include "net/quic/test_tools/crypto_test_utils.h"
#include "testing/gtest/include/gtest/gtest.h"
+using base::IntToString;
using std::string;
namespace net {
@@ -30,7 +30,8 @@ class QuicCompressedCertsCacheTest : public testing::Test {
TEST_F(QuicCompressedCertsCacheTest, CacheHit) {
std::vector<string> certs = {"leaf cert", "intermediate cert", "root cert"};
- scoped_refptr<ProofSource::Chain> chain(new ProofSource::Chain(certs));
+ QuicReferenceCountedPointer<ProofSource::Chain> chain(
+ new ProofSource::Chain(certs));
string common_certs = "common certs";
string cached_certs = "cached certs";
string compressed = "compressed cert";
@@ -45,18 +46,25 @@ TEST_F(QuicCompressedCertsCacheTest, CacheHit) {
TEST_F(QuicCompressedCertsCacheTest, CacheMiss) {
std::vector<string> certs = {"leaf cert", "intermediate cert", "root cert"};
- scoped_refptr<ProofSource::Chain> chain(new ProofSource::Chain(certs));
+ QuicReferenceCountedPointer<ProofSource::Chain> chain(
+ new ProofSource::Chain(certs));
+
string common_certs = "common certs";
string cached_certs = "cached certs";
string compressed = "compressed cert";
certs_cache_.Insert(chain, common_certs, cached_certs, compressed);
- EXPECT_EQ(nullptr, certs_cache_.GetCompressedCert(
- chain, "mismatched common certs", cached_certs));
- EXPECT_EQ(nullptr, certs_cache_.GetCompressedCert(chain, common_certs,
- "mismatched cached certs"));
- scoped_refptr<ProofSource::Chain> chain2(new ProofSource::Chain(certs));
+ EXPECT_EQ(nullptr,
+ certs_cache_.GetCompressedCert(chain, "mismatched common certs",
+ cached_certs));
+ EXPECT_EQ(nullptr,
+ certs_cache_.GetCompressedCert(chain, common_certs,
+ "mismatched cached certs"));
+
+ // A different chain though with equivalent certs should get a cache miss.
+ QuicReferenceCountedPointer<ProofSource::Chain> chain2(
+ new ProofSource::Chain(certs));
EXPECT_EQ(nullptr,
certs_cache_.GetCompressedCert(chain2, common_certs, cached_certs));
}
@@ -65,7 +73,8 @@ TEST_F(QuicCompressedCertsCacheTest, CacheMissDueToEviction) {
// Test cache returns a miss when a queried uncompressed certs was cached but
// then evicted.
std::vector<string> certs = {"leaf cert", "intermediate cert", "root cert"};
- scoped_refptr<ProofSource::Chain> chain(new ProofSource::Chain(certs));
+ QuicReferenceCountedPointer<ProofSource::Chain> chain(
+ new ProofSource::Chain(certs));
string common_certs = "common certs";
string cached_certs = "cached certs";
@@ -77,7 +86,8 @@ TEST_F(QuicCompressedCertsCacheTest, CacheMissDueToEviction) {
for (unsigned int i = 0;
i < QuicCompressedCertsCache::kQuicCompressedCertsCacheSize; i++) {
EXPECT_EQ(certs_cache_.Size(), i + 1);
- certs_cache_.Insert(chain, base::IntToString(i), "", base::IntToString(i));
+ certs_cache_.Insert(chain, QuicTextUtils::Uint64ToString(i), "",
+ QuicTextUtils::Uint64ToString(i));
}
EXPECT_EQ(certs_cache_.MaxSize(), certs_cache_.Size());
diff --git a/chromium/net/quic/core/crypto/quic_crypto_client_config.cc b/chromium/net/quic/core/crypto/quic_crypto_client_config.cc
index fa8dfade2dd..28c936a6efa 100644
--- a/chromium/net/quic/core/crypto/quic_crypto_client_config.cc
+++ b/chromium/net/quic/core/crypto/quic_crypto_client_config.cc
@@ -7,10 +7,8 @@
#include <algorithm>
#include <memory>
-#include "base/memory/ptr_util.h"
#include "base/metrics/histogram_macros.h"
#include "base/stl_util.h"
-#include "base/strings/string_util.h"
#include "net/quic/core/crypto/cert_compressor.h"
#include "net/quic/core/crypto/chacha20_poly1305_encrypter.h"
#include "net/quic/core/crypto/channel_id.h"
@@ -23,11 +21,13 @@
#include "net/quic/core/crypto/proof_verifier.h"
#include "net/quic/core/crypto/quic_encrypter.h"
#include "net/quic/core/crypto/quic_random.h"
-#include "net/quic/core/quic_bug_tracker.h"
-#include "net/quic/core/quic_flags.h"
-#include "net/quic/core/quic_time.h"
#include "net/quic/core/quic_utils.h"
+#include "net/quic/platform/api/quic_bug_tracker.h"
+#include "net/quic/platform/api/quic_logging.h"
+#include "net/quic/platform/api/quic_ptr_util.h"
+#include "net/quic/platform/api/quic_text_utils.h"
+using base::ContainsKey;
using base::StringPiece;
using std::string;
@@ -113,7 +113,7 @@ QuicCryptoClientConfig::CachedState::GetServerConfig() const {
}
if (!scfg_.get()) {
- scfg_.reset(CryptoFramer::ParseMessage(server_config_));
+ scfg_ = CryptoFramer::ParseMessage(server_config_);
DCHECK(scfg_.get());
}
return scfg_.get();
@@ -151,7 +151,7 @@ QuicCryptoClientConfig::CachedState::SetServerConfig(StringPiece server_config,
const CryptoHandshakeMessage* new_scfg;
if (!matches_existing) {
- new_scfg_storage.reset(CryptoFramer::ParseMessage(server_config));
+ new_scfg_storage = CryptoFramer::ParseMessage(server_config);
new_scfg = new_scfg_storage.get();
} else {
new_scfg = GetServerConfig();
@@ -181,7 +181,7 @@ QuicCryptoClientConfig::CachedState::SetServerConfig(StringPiece server_config,
if (!matches_existing) {
server_config_ = server_config.as_string();
SetProofInvalid();
- scfg_.reset(new_scfg_storage.release());
+ scfg_ = std::move(new_scfg_storage);
}
return SERVER_CONFIG_VALID;
}
@@ -276,7 +276,7 @@ bool QuicCryptoClientConfig::CachedState::Initialize(
SetServerConfig(server_config, now, expiration_time, &error_details);
RecordDiskCacheServerConfigState(state);
if (state != SERVER_CONFIG_VALID) {
- DVLOG(1) << "SetServerConfig failed with " << error_details;
+ QUIC_DVLOG(1) << "SetServerConfig failed with " << error_details;
return false;
}
@@ -398,7 +398,7 @@ QuicCryptoClientConfig::CachedState* QuicCryptoClientConfig::LookupOrCreate(
}
CachedState* cached = new CachedState;
- cached_states_.insert(std::make_pair(server_id, base::WrapUnique(cached)));
+ cached_states_.insert(std::make_pair(server_id, QuicWrapUnique(cached)));
bool cache_populated = PopulateFromCanonicalConfig(server_id, cached);
UMA_HISTOGRAM_BOOLEAN(
"Net.QuicCryptoClientConfig.PopulatedFromCanonicalConfig",
@@ -419,7 +419,7 @@ void QuicCryptoClientConfig::FillInchoateClientHello(
const CachedState* cached,
QuicRandom* rand,
bool demand_x509_proof,
- scoped_refptr<QuicCryptoNegotiatedParameters> out_params,
+ QuicReferenceCountedPointer<QuicCryptoNegotiatedParameters> out_params,
CryptoHandshakeMessage* out) const {
out->set_tag(kCHLO);
// TODO(rch): Remove this when we remove:
@@ -478,7 +478,7 @@ void QuicCryptoClientConfig::FillInchoateClientHello(
hashes.reserve(certs.size());
for (std::vector<string>::const_iterator i = certs.begin();
i != certs.end(); ++i) {
- hashes.push_back(QuicUtils::FNV1a_64_Hash(i->data(), i->size()));
+ hashes.push_back(QuicUtils::FNV1a_64_Hash(*i));
}
out->SetVector(kCCRT, hashes);
}
@@ -487,13 +487,12 @@ void QuicCryptoClientConfig::FillInchoateClientHello(
QuicErrorCode QuicCryptoClientConfig::FillClientHello(
const QuicServerId& server_id,
QuicConnectionId connection_id,
- const QuicVersion actual_version,
const QuicVersion preferred_version,
const CachedState* cached,
QuicWallTime now,
QuicRandom* rand,
const ChannelIDKey* channel_id_key,
- scoped_refptr<QuicCryptoNegotiatedParameters> out_params,
+ QuicReferenceCountedPointer<QuicCryptoNegotiatedParameters> out_params,
CryptoHandshakeMessage* out,
string* error_details) const {
DCHECK(error_details != nullptr);
@@ -535,13 +534,10 @@ QuicErrorCode QuicCryptoClientConfig::FillClientHello(
// Key exchange: the client does more work than the server, so favor the
// client's preference.
size_t key_exchange_index;
- if (!QuicUtils::FindMutualTag(aead, their_aeads, num_their_aeads,
- QuicUtils::LOCAL_PRIORITY, &out_params->aead,
- nullptr) ||
- !QuicUtils::FindMutualTag(
- kexs, their_key_exchanges, num_their_key_exchanges,
- QuicUtils::LOCAL_PRIORITY, &out_params->key_exchange,
- &key_exchange_index)) {
+ if (!FindMutualQuicTag(aead, their_aeads, num_their_aeads, &out_params->aead,
+ nullptr) ||
+ !FindMutualQuicTag(kexs, their_key_exchanges, num_their_key_exchanges,
+ &out_params->key_exchange, &key_exchange_index)) {
*error_details = "Unsupported AEAD or KEXS";
return QUIC_CRYPTO_NO_SUPPORT;
}
@@ -556,10 +552,8 @@ QuicErrorCode QuicCryptoClientConfig::FillClientHello(
case QUIC_CRYPTO_MESSAGE_PARAMETER_NOT_FOUND:
break;
case QUIC_NO_ERROR:
- if (QuicUtils::FindMutualTag(tb_key_params, their_tbkps,
- num_their_tbkps, QuicUtils::LOCAL_PRIORITY,
- &out_params->token_binding_key_param,
- nullptr)) {
+ if (FindMutualQuicTag(tb_key_params, their_tbkps, num_their_tbkps,
+ &out_params->token_binding_key_param, nullptr)) {
out->SetVector(kTBKP,
QuicTagVector{out_params->token_binding_key_param});
}
@@ -664,9 +658,10 @@ QuicErrorCode QuicCryptoClientConfig::FillClientHello(
std::unique_ptr<char[]> output(new char[encrypted_len]);
size_t output_size = 0;
if (!crypters.encrypter->EncryptPacket(
- kDefaultPathId /* path id */, 0 /* packet number */,
- StringPiece() /* associated data */, cetv_plaintext.AsStringPiece(),
- output.get(), &output_size, encrypted_len)) {
+ preferred_version, kDefaultPathId /* path id */,
+ 0 /* packet number */, StringPiece() /* associated data */,
+ cetv_plaintext.AsStringPiece(), output.get(), &output_size,
+ encrypted_len)) {
*error_details = "Packet encryption failed";
return QUIC_ENCRYPTION_FAILURE;
}
@@ -702,17 +697,11 @@ QuicErrorCode QuicCryptoClientConfig::FillClientHello(
string* subkey_secret = &out_params->initial_subkey_secret;
- // Only perform key diversification for QUIC versions 33 and later.
- // TODO(rch): remove the |actual_version| argument to this method when
- // QUIC_VERSION_32 is removed.
- CryptoUtils::Diversification diversification =
- actual_version > QUIC_VERSION_32 ? CryptoUtils::Diversification::Pending()
- : CryptoUtils::Diversification::Never();
- if (!CryptoUtils::DeriveKeys(out_params->initial_premaster_secret,
- out_params->aead, out_params->client_nonce,
- out_params->server_nonce, hkdf_input,
- Perspective::IS_CLIENT, diversification,
- &out_params->initial_crypters, subkey_secret)) {
+ if (!CryptoUtils::DeriveKeys(
+ out_params->initial_premaster_secret, out_params->aead,
+ out_params->client_nonce, out_params->server_nonce, hkdf_input,
+ Perspective::IS_CLIENT, CryptoUtils::Diversification::Pending(),
+ &out_params->initial_crypters, subkey_secret)) {
*error_details = "Symmetric key setup failed";
return QUIC_CRYPTO_SYMMETRIC_KEY_SETUP_FAILED;
}
@@ -798,7 +787,7 @@ QuicErrorCode QuicCryptoClientConfig::ProcessRejection(
const QuicVersion version,
StringPiece chlo_hash,
CachedState* cached,
- scoped_refptr<QuicCryptoNegotiatedParameters> out_params,
+ QuicReferenceCountedPointer<QuicCryptoNegotiatedParameters> out_params,
string* error_details) {
DCHECK(error_details != nullptr);
@@ -841,7 +830,7 @@ QuicErrorCode QuicCryptoClientConfig::ProcessServerHello(
QuicVersion version,
const QuicVersionVector& negotiated_versions,
CachedState* cached,
- scoped_refptr<QuicCryptoNegotiatedParameters> out_params,
+ QuicReferenceCountedPointer<QuicCryptoNegotiatedParameters> out_params,
string* error_details) {
DCHECK(error_details != nullptr);
@@ -904,7 +893,7 @@ QuicErrorCode QuicCryptoClientConfig::ProcessServerConfigUpdate(
const QuicVersion version,
StringPiece chlo_hash,
CachedState* cached,
- scoped_refptr<QuicCryptoNegotiatedParameters> out_params,
+ QuicReferenceCountedPointer<QuicCryptoNegotiatedParameters> out_params,
string* error_details) {
DCHECK(error_details != nullptr);
@@ -963,8 +952,8 @@ bool QuicCryptoClientConfig::PopulateFromCanonicalConfig(
DCHECK(server_state->IsEmpty());
size_t i = 0;
for (; i < canonical_suffixes_.size(); ++i) {
- if (base::EndsWith(server_id.host(), canonical_suffixes_[i],
- base::CompareCase::INSENSITIVE_ASCII)) {
+ if (QuicTextUtils::EndsWithIgnoreCase(server_id.host(),
+ canonical_suffixes_[i])) {
break;
}
}
@@ -974,7 +963,7 @@ bool QuicCryptoClientConfig::PopulateFromCanonicalConfig(
QuicServerId suffix_server_id(canonical_suffixes_[i], server_id.port(),
server_id.privacy_mode());
- if (!base::ContainsKey(canonical_server_map_, suffix_server_id)) {
+ if (!ContainsKey(canonical_server_map_, suffix_server_id)) {
// This is the first host we've seen which matches the suffix, so make it
// canonical.
canonical_server_map_[suffix_server_id] = server_id;
diff --git a/chromium/net/quic/core/crypto/quic_crypto_client_config.h b/chromium/net/quic/core/crypto/quic_crypto_client_config.h
index b92f9258060..551307b96cd 100644
--- a/chromium/net/quic/core/crypto/quic_crypto_client_config.h
+++ b/chromium/net/quic/core/crypto/quic_crypto_client_config.h
@@ -2,11 +2,10 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#ifndef NET_QUIC_CRYPTO_QUIC_CRYPTO_CLIENT_CONFIG_H_
-#define NET_QUIC_CRYPTO_QUIC_CRYPTO_CLIENT_CONFIG_H_
-
-#include <stdint.h>
+#ifndef NET_QUIC_CORE_CRYPTO_QUIC_CRYPTO_CLIENT_CONFIG_H_
+#define NET_QUIC_CORE_CRYPTO_QUIC_CRYPTO_CLIENT_CONFIG_H_
+#include <cstdint>
#include <map>
#include <memory>
#include <queue>
@@ -15,10 +14,11 @@
#include "base/macros.h"
#include "base/strings/string_piece.h"
-#include "net/base/net_export.h"
#include "net/quic/core/crypto/crypto_handshake.h"
-#include "net/quic/core/quic_protocol.h"
+#include "net/quic/core/quic_packets.h"
#include "net/quic/core/quic_server_id.h"
+#include "net/quic/platform/api/quic_export.h"
+#include "net/quic/platform/api/quic_reference_counted.h"
namespace net {
@@ -32,12 +32,12 @@ class QuicRandom;
// QuicCryptoClientConfig contains crypto-related configuration settings for a
// client. Note that this object isn't thread-safe. It's designed to be used on
// a single thread at a time.
-class NET_EXPORT_PRIVATE QuicCryptoClientConfig : public QuicCryptoConfig {
+class QUIC_EXPORT_PRIVATE QuicCryptoClientConfig : public QuicCryptoConfig {
public:
// A CachedState contains the information that the client needs in order to
// perform a 0-RTT handshake with a server. This information can be reused
// over several connections to the same server.
- class NET_EXPORT_PRIVATE CachedState {
+ class QUIC_EXPORT_PRIVATE CachedState {
public:
// Enum to track if the server config is valid or not. If it is not valid,
// it specifies why it is invalid.
@@ -84,7 +84,7 @@ class NET_EXPORT_PRIVATE QuicCryptoClientConfig : public QuicCryptoConfig {
// InvalidateServerConfig clears the cached server config (if any).
void InvalidateServerConfig();
- // SetProof stores a certificate chain and signature.
+ // SetProof stores a cert chain, cert signed timestamp and signature.
void SetProof(const std::vector<std::string>& certs,
base::StringPiece cert_sct,
base::StringPiece chlo_hash,
@@ -201,6 +201,8 @@ class NET_EXPORT_PRIVATE QuicCryptoClientConfig : public QuicCryptoConfig {
// Used to filter server ids for partial config deletion.
class ServerIdFilter {
public:
+ virtual ~ServerIdFilter() {}
+
// Returns true if |server_id| matches the filter.
virtual bool Matches(const QuicServerId& server_id) const = 0;
};
@@ -232,7 +234,7 @@ class NET_EXPORT_PRIVATE QuicCryptoClientConfig : public QuicCryptoConfig {
const CachedState* cached,
QuicRandom* rand,
bool demand_x509_proof,
- scoped_refptr<QuicCryptoNegotiatedParameters> out_params,
+ QuicReferenceCountedPointer<QuicCryptoNegotiatedParameters> out_params,
CryptoHandshakeMessage* out) const;
// FillClientHello sets |out| to be a CHLO message based on the configuration
@@ -252,13 +254,12 @@ class NET_EXPORT_PRIVATE QuicCryptoClientConfig : public QuicCryptoConfig {
QuicErrorCode FillClientHello(
const QuicServerId& server_id,
QuicConnectionId connection_id,
- const QuicVersion actual_version,
const QuicVersion preferred_version,
const CachedState* cached,
QuicWallTime now,
QuicRandom* rand,
const ChannelIDKey* channel_id_key,
- scoped_refptr<QuicCryptoNegotiatedParameters> out_params,
+ QuicReferenceCountedPointer<QuicCryptoNegotiatedParameters> out_params,
CryptoHandshakeMessage* out,
std::string* error_details) const;
@@ -274,7 +275,7 @@ class NET_EXPORT_PRIVATE QuicCryptoClientConfig : public QuicCryptoConfig {
QuicVersion version,
base::StringPiece chlo_hash,
CachedState* cached,
- scoped_refptr<QuicCryptoNegotiatedParameters> out_params,
+ QuicReferenceCountedPointer<QuicCryptoNegotiatedParameters> out_params,
std::string* error_details);
// ProcessServerHello processes the message in |server_hello|, updates the
@@ -292,7 +293,7 @@ class NET_EXPORT_PRIVATE QuicCryptoClientConfig : public QuicCryptoConfig {
QuicVersion version,
const QuicVersionVector& negotiated_versions,
CachedState* cached,
- scoped_refptr<QuicCryptoNegotiatedParameters> out_params,
+ QuicReferenceCountedPointer<QuicCryptoNegotiatedParameters> out_params,
std::string* error_details);
// Processes the message in |server_update|, updating the cached source
@@ -306,7 +307,7 @@ class NET_EXPORT_PRIVATE QuicCryptoClientConfig : public QuicCryptoConfig {
const QuicVersion version,
base::StringPiece chlo_hash,
CachedState* cached,
- scoped_refptr<QuicCryptoNegotiatedParameters> out_params,
+ QuicReferenceCountedPointer<QuicCryptoNegotiatedParameters> out_params,
std::string* error_details);
ProofVerifier* proof_verifier() const;
@@ -391,4 +392,4 @@ class NET_EXPORT_PRIVATE QuicCryptoClientConfig : public QuicCryptoConfig {
} // namespace net
-#endif // NET_QUIC_CRYPTO_QUIC_CRYPTO_CLIENT_CONFIG_H_
+#endif // NET_QUIC_CORE_CRYPTO_QUIC_CRYPTO_CLIENT_CONFIG_H_
diff --git a/chromium/net/quic/core/crypto/quic_crypto_client_config_test.cc b/chromium/net/quic/core/crypto/quic_crypto_client_config_test.cc
index cd8f332aba1..5d15437143f 100644
--- a/chromium/net/quic/core/crypto/quic_crypto_client_config_test.cc
+++ b/chromium/net/quic/core/crypto/quic_crypto_client_config_test.cc
@@ -6,7 +6,6 @@
#include "net/quic/core/crypto/proof_verifier.h"
#include "net/quic/core/quic_server_id.h"
-#include "net/quic/core/quic_time.h"
#include "net/quic/test_tools/crypto_test_utils.h"
#include "net/quic/test_tools/mock_random.h"
#include "net/quic/test_tools/quic_test_utils.h"
@@ -170,7 +169,7 @@ TEST(QuicCryptoClientConfigTest, CachedState_InitializeFrom) {
TEST(QuicCryptoClientConfigTest, InchoateChlo) {
QuicCryptoClientConfig::CachedState state;
QuicCryptoClientConfig config(CryptoTestUtils::ProofVerifierForTesting());
- scoped_refptr<QuicCryptoNegotiatedParameters> params(
+ QuicReferenceCountedPointer<QuicCryptoNegotiatedParameters> params(
new QuicCryptoNegotiatedParameters);
CryptoHandshakeMessage msg;
QuicServerId server_id("www.google.com", 443, PRIVACY_MODE_DISABLED);
@@ -197,7 +196,7 @@ TEST(QuicCryptoClientConfigTest, PreferAesGcm) {
TEST(QuicCryptoClientConfigTest, InchoateChloSecure) {
QuicCryptoClientConfig::CachedState state;
QuicCryptoClientConfig config(CryptoTestUtils::ProofVerifierForTesting());
- scoped_refptr<QuicCryptoNegotiatedParameters> params(
+ QuicReferenceCountedPointer<QuicCryptoNegotiatedParameters> params(
new QuicCryptoNegotiatedParameters);
CryptoHandshakeMessage msg;
QuicServerId server_id("www.google.com", 443, PRIVACY_MODE_DISABLED);
@@ -226,7 +225,7 @@ TEST(QuicCryptoClientConfigTest, InchoateChloSecureWithSCIDNoEXPY) {
&details);
QuicCryptoClientConfig config(CryptoTestUtils::ProofVerifierForTesting());
- scoped_refptr<QuicCryptoNegotiatedParameters> params(
+ QuicReferenceCountedPointer<QuicCryptoNegotiatedParameters> params(
new QuicCryptoNegotiatedParameters);
CryptoHandshakeMessage msg;
QuicServerId server_id("www.google.com", 443, PRIVACY_MODE_DISABLED);
@@ -252,7 +251,7 @@ TEST(QuicCryptoClientConfigTest, InchoateChloSecureWithSCID) {
QuicWallTime::FromUNIXSeconds(0), &details);
QuicCryptoClientConfig config(CryptoTestUtils::ProofVerifierForTesting());
- scoped_refptr<QuicCryptoNegotiatedParameters> params(
+ QuicReferenceCountedPointer<QuicCryptoNegotiatedParameters> params(
new QuicCryptoNegotiatedParameters);
CryptoHandshakeMessage msg;
QuicServerId server_id("www.google.com", 443, PRIVACY_MODE_DISABLED);
@@ -268,15 +267,15 @@ TEST(QuicCryptoClientConfigTest, InchoateChloSecureWithSCID) {
TEST(QuicCryptoClientConfigTest, FillClientHello) {
QuicCryptoClientConfig::CachedState state;
QuicCryptoClientConfig config(CryptoTestUtils::ProofVerifierForTesting());
- scoped_refptr<QuicCryptoNegotiatedParameters> params(
+ QuicReferenceCountedPointer<QuicCryptoNegotiatedParameters> params(
new QuicCryptoNegotiatedParameters);
QuicConnectionId kConnectionId = 1234;
string error_details;
MockRandom rand;
CryptoHandshakeMessage chlo;
QuicServerId server_id("www.google.com", 443, PRIVACY_MODE_DISABLED);
- config.FillClientHello(server_id, kConnectionId, QuicVersionMax(),
- QuicVersionMax(), &state, QuicWallTime::Zero(), &rand,
+ config.FillClientHello(server_id, kConnectionId, QuicVersionMax(), &state,
+ QuicWallTime::Zero(), &rand,
nullptr, // channel_id_key
params, &chlo, &error_details);
@@ -302,7 +301,7 @@ TEST(QuicCryptoClientConfigTest, ProcessServerDowngradeAttack) {
msg.SetVector(kVER, supported_version_tags);
QuicCryptoClientConfig::CachedState cached;
- scoped_refptr<QuicCryptoNegotiatedParameters> out_params(
+ QuicReferenceCountedPointer<QuicCryptoNegotiatedParameters> out_params(
new QuicCryptoNegotiatedParameters);
string error;
QuicCryptoClientConfig config(CryptoTestUtils::ProofVerifierForTesting());
@@ -466,7 +465,7 @@ TEST(QuicCryptoClientConfigTest, ProcessReject) {
// Now process the rejection.
QuicCryptoClientConfig::CachedState cached;
- scoped_refptr<QuicCryptoNegotiatedParameters> out_params(
+ QuicReferenceCountedPointer<QuicCryptoNegotiatedParameters> out_params(
new QuicCryptoNegotiatedParameters);
string error;
QuicCryptoClientConfig config(CryptoTestUtils::ProofVerifierForTesting());
@@ -487,7 +486,7 @@ TEST(QuicCryptoClientConfigTest, ProcessRejectWithLongTTL) {
// Now process the rejection.
QuicCryptoClientConfig::CachedState cached;
- scoped_refptr<QuicCryptoNegotiatedParameters> out_params(
+ QuicReferenceCountedPointer<QuicCryptoNegotiatedParameters> out_params(
new QuicCryptoNegotiatedParameters);
string error;
QuicCryptoClientConfig config(CryptoTestUtils::ProofVerifierForTesting());
@@ -514,7 +513,7 @@ TEST(QuicCryptoClientConfigTest, ProcessStatelessReject) {
// Now process the rejection.
QuicCryptoClientConfig::CachedState cached;
- scoped_refptr<QuicCryptoNegotiatedParameters> out_params(
+ QuicReferenceCountedPointer<QuicCryptoNegotiatedParameters> out_params(
new QuicCryptoNegotiatedParameters);
string error;
QuicCryptoClientConfig config(CryptoTestUtils::ProofVerifierForTesting());
@@ -535,7 +534,7 @@ TEST(QuicCryptoClientConfigTest, BadlyFormattedStatelessReject) {
// Now process the rejection.
QuicCryptoClientConfig::CachedState cached;
- scoped_refptr<QuicCryptoNegotiatedParameters> out_params(
+ QuicReferenceCountedPointer<QuicCryptoNegotiatedParameters> out_params(
new QuicCryptoNegotiatedParameters);
string error;
QuicCryptoClientConfig config(CryptoTestUtils::ProofVerifierForTesting());
@@ -561,7 +560,7 @@ TEST(QuicCryptoClientConfigTest, ServerNonceinSHLO) {
QuicCryptoClientConfig config(CryptoTestUtils::ProofVerifierForTesting());
QuicCryptoClientConfig::CachedState cached;
- scoped_refptr<QuicCryptoNegotiatedParameters> out_params(
+ QuicReferenceCountedPointer<QuicCryptoNegotiatedParameters> out_params(
new QuicCryptoNegotiatedParameters);
string error_details;
EXPECT_EQ(QUIC_INVALID_CRYPTO_MESSAGE_PARAMETER,
diff --git a/chromium/net/quic/core/crypto/quic_crypto_proof.cc b/chromium/net/quic/core/crypto/quic_crypto_proof.cc
new file mode 100644
index 00000000000..4ee15b7ea55
--- /dev/null
+++ b/chromium/net/quic/core/crypto/quic_crypto_proof.cc
@@ -0,0 +1,11 @@
+// Copyright 2016 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.
+
+#include "net/quic/core/crypto/quic_crypto_proof.h"
+
+namespace net {
+
+QuicCryptoProof::QuicCryptoProof() : send_expect_ct_header(false) {}
+
+} // namespace net
diff --git a/chromium/net/quic/core/crypto/quic_crypto_proof.h b/chromium/net/quic/core/crypto/quic_crypto_proof.h
new file mode 100644
index 00000000000..f701aa7da34
--- /dev/null
+++ b/chromium/net/quic/core/crypto/quic_crypto_proof.h
@@ -0,0 +1,29 @@
+// Copyright 2016 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.
+
+#ifndef NET_QUIC_CORE_CRYPTO_QUIC_CRYPTO_PROOF_H_
+#define NET_QUIC_CORE_CRYPTO_QUIC_CRYPTO_PROOF_H_
+
+#include <string>
+
+#include "net/quic/platform/api/quic_export.h"
+
+namespace net {
+
+// Contains the crypto-related data provided by ProofSource
+struct QUIC_EXPORT_PRIVATE QuicCryptoProof {
+ QuicCryptoProof();
+
+ // Signature generated by ProofSource
+ std::string signature;
+ // SCTList (RFC6962) to be sent to the client, if it supports receiving it.
+ std::string leaf_cert_scts;
+ // Should the Expect-CT header be sent on the connection where the
+ // certificate is used.
+ bool send_expect_ct_header;
+};
+
+} // namespace net
+
+#endif // NET_QUIC_CORE_CRYPTO_QUIC_CRYPTO_PROOF_H_
diff --git a/chromium/net/quic/core/crypto/quic_crypto_server_config.cc b/chromium/net/quic/core/crypto/quic_crypto_server_config.cc
index dcc925f3920..171e4b510b9 100644
--- a/chromium/net/quic/core/crypto/quic_crypto_server_config.cc
+++ b/chromium/net/quic/core/crypto/quic_crypto_server_config.cc
@@ -10,10 +10,8 @@
#include <memory>
#include "base/macros.h"
-#include "base/memory/ref_counted.h"
#include "crypto/hkdf.h"
#include "crypto/secure_hash.h"
-#include "net/base/ip_address.h"
#include "net/quic/core/crypto/aes_128_gcm_12_decrypter.h"
#include "net/quic/core/crypto/aes_128_gcm_12_encrypter.h"
#include "net/quic/core/crypto/cert_compressor.h"
@@ -26,28 +24,25 @@
#include "net/quic/core/crypto/curve25519_key_exchange.h"
#include "net/quic/core/crypto/ephemeral_key_source.h"
#include "net/quic/core/crypto/key_exchange.h"
-#include "net/quic/core/crypto/local_strike_register_client.h"
#include "net/quic/core/crypto/p256_key_exchange.h"
#include "net/quic/core/crypto/proof_source.h"
#include "net/quic/core/crypto/quic_decrypter.h"
#include "net/quic/core/crypto/quic_encrypter.h"
#include "net/quic/core/crypto/quic_random.h"
-#include "net/quic/core/crypto/strike_register.h"
-#include "net/quic/core/crypto/strike_register_client.h"
#include "net/quic/core/proto/source_address_token.pb.h"
-#include "net/quic/core/quic_bug_tracker.h"
-#include "net/quic/core/quic_clock.h"
#include "net/quic/core/quic_flags.h"
-#include "net/quic/core/quic_protocol.h"
+#include "net/quic/core/quic_packets.h"
#include "net/quic/core/quic_socket_address_coder.h"
#include "net/quic/core/quic_utils.h"
+#include "net/quic/platform/api/quic_bug_tracker.h"
+#include "net/quic/platform/api/quic_clock.h"
+#include "net/quic/platform/api/quic_logging.h"
+#include "net/quic/platform/api/quic_reference_counted.h"
+#include "net/quic/platform/api/quic_text_utils.h"
using base::StringPiece;
using crypto::SecureHash;
-using std::map;
-using std::sort;
using std::string;
-using std::vector;
namespace net {
@@ -69,13 +64,6 @@ string DeriveSourceAddressTokenKey(StringPiece source_address_token_secret) {
return hkdf.server_write_key().as_string();
}
-IPAddress DualstackIPAddress(const IPAddress& ip) {
- if (ip.IsIPv4()) {
- return ConvertIPv4ToIPv4MappedIPv6(ip);
- }
- return ip;
-}
-
} // namespace
class ValidateClientHelloHelper {
@@ -83,7 +71,8 @@ class ValidateClientHelloHelper {
// Note: stores a pointer to a unique_ptr, and std::moves the unique_ptr when
// ValidationComplete is called.
ValidateClientHelloHelper(
- scoped_refptr<ValidateClientHelloResultCallback::Result> result,
+ QuicReferenceCountedPointer<ValidateClientHelloResultCallback::Result>
+ result,
std::unique_ptr<ValidateClientHelloResultCallback>* done_cb)
: result_(std::move(result)), done_cb_(done_cb) {}
@@ -108,75 +97,17 @@ class ValidateClientHelloHelper {
}
private:
- scoped_refptr<ValidateClientHelloResultCallback::Result> result_;
+ QuicReferenceCountedPointer<ValidateClientHelloResultCallback::Result>
+ result_;
std::unique_ptr<ValidateClientHelloResultCallback>* done_cb_;
DISALLOW_COPY_AND_ASSIGN(ValidateClientHelloHelper);
};
-class VerifyNonceIsValidAndUniqueCallback
- : public StrikeRegisterClient::ResultCallback {
- public:
- VerifyNonceIsValidAndUniqueCallback(
- scoped_refptr<ValidateClientHelloResultCallback::Result> result,
- std::unique_ptr<ProofSource::Details> proof_source_details,
- std::unique_ptr<ValidateClientHelloResultCallback> done_cb)
- : result_(std::move(result)),
- proof_source_details_(std::move(proof_source_details)),
- done_cb_(std::move(done_cb)) {}
-
- protected:
- void RunImpl(bool nonce_is_valid_and_unique,
- InsertStatus nonce_error) override {
- DVLOG(1) << "Using client nonce, unique: " << nonce_is_valid_and_unique
- << " nonce_error: " << nonce_error;
- if (!nonce_is_valid_and_unique) {
- HandshakeFailureReason client_nonce_error;
- switch (nonce_error) {
- case NONCE_INVALID_FAILURE:
- client_nonce_error = CLIENT_NONCE_INVALID_FAILURE;
- break;
- case NONCE_NOT_UNIQUE_FAILURE:
- client_nonce_error = CLIENT_NONCE_NOT_UNIQUE_FAILURE;
- break;
- case NONCE_INVALID_ORBIT_FAILURE:
- client_nonce_error = CLIENT_NONCE_INVALID_ORBIT_FAILURE;
- break;
- case NONCE_INVALID_TIME_FAILURE:
- client_nonce_error = CLIENT_NONCE_INVALID_TIME_FAILURE;
- break;
- case STRIKE_REGISTER_TIMEOUT:
- client_nonce_error = CLIENT_NONCE_STRIKE_REGISTER_TIMEOUT;
- break;
- case STRIKE_REGISTER_FAILURE:
- client_nonce_error = CLIENT_NONCE_STRIKE_REGISTER_FAILURE;
- break;
- case NONCE_UNKNOWN_FAILURE:
- client_nonce_error = CLIENT_NONCE_UNKNOWN_FAILURE;
- break;
- case NONCE_OK:
- default:
- QUIC_BUG << "Unexpected client nonce error: " << nonce_error;
- client_nonce_error = CLIENT_NONCE_UNKNOWN_FAILURE;
- break;
- }
- result_->info.reject_reasons.push_back(client_nonce_error);
- }
- done_cb_->Run(result_, std::move(proof_source_details_));
- }
-
- private:
- scoped_refptr<ValidateClientHelloResultCallback::Result> result_;
- std::unique_ptr<ProofSource::Details> proof_source_details_;
- std::unique_ptr<ValidateClientHelloResultCallback> done_cb_;
-
- DISALLOW_COPY_AND_ASSIGN(VerifyNonceIsValidAndUniqueCallback);
-};
-
// static
const char QuicCryptoServerConfig::TESTING[] = "secret string for testing";
-ClientHelloInfo::ClientHelloInfo(const IPAddress& in_client_ip,
+ClientHelloInfo::ClientHelloInfo(const QuicIpAddress& in_client_ip,
QuicWallTime in_now)
: client_ip(in_client_ip), now(in_now), valid_source_address_token(false) {}
@@ -190,7 +121,7 @@ PrimaryConfigChangedCallback::~PrimaryConfigChangedCallback() {}
ValidateClientHelloResultCallback::Result::Result(
const CryptoHandshakeMessage& in_client_hello,
- IPAddress in_client_ip,
+ QuicIpAddress in_client_ip,
QuicWallTime in_now)
: client_hello(in_client_hello),
info(in_client_ip, in_now),
@@ -225,15 +156,9 @@ QuicCryptoServerConfig::QuicCryptoServerConfig(
configs_lock_(),
primary_config_(nullptr),
next_config_promotion_time_(QuicWallTime::Zero()),
- server_nonce_strike_register_lock_(),
proof_source_(std::move(proof_source)),
- strike_register_no_startup_period_(false),
- strike_register_max_entries_(1 << 10),
- strike_register_window_secs_(600),
source_address_token_future_secs_(3600),
source_address_token_lifetime_secs_(86400),
- server_nonce_strike_register_max_entries_(1 << 10),
- server_nonce_strike_register_window_secs_(120),
enable_serving_sct_(false),
rejection_observer_(nullptr) {
DCHECK(proof_source_.get());
@@ -251,9 +176,7 @@ QuicCryptoServerConfig::QuicCryptoServerConfig(
{string(reinterpret_cast<char*>(key_bytes.get()), key_size)});
}
-QuicCryptoServerConfig::~QuicCryptoServerConfig() {
- primary_config_ = nullptr;
-}
+QuicCryptoServerConfig::~QuicCryptoServerConfig() {}
// static
std::unique_ptr<QuicServerConfigProtobuf>
@@ -378,29 +301,30 @@ CryptoHandshakeMessage* QuicCryptoServerConfig::AddConfig(
CryptoFramer::ParseMessage(protobuf->config()));
if (!msg.get()) {
- LOG(WARNING) << "Failed to parse server config message";
+ QUIC_LOG(WARNING) << "Failed to parse server config message";
return nullptr;
}
- scoped_refptr<Config> config(ParseConfigProtobuf(protobuf));
+ QuicReferenceCountedPointer<Config> config(ParseConfigProtobuf(protobuf));
if (!config.get()) {
- LOG(WARNING) << "Failed to parse server config message";
+ QUIC_LOG(WARNING) << "Failed to parse server config message";
return nullptr;
}
{
- base::AutoLock locked(configs_lock_);
+ QuicWriterMutexLock locked(&configs_lock_);
if (configs_.find(config->id) != configs_.end()) {
- LOG(WARNING) << "Failed to add config because another with the same "
- "server config id already exists: "
- << QuicUtils::HexEncode(config->id);
+ QUIC_LOG(WARNING) << "Failed to add config because another with the same "
+ "server config id already exists: "
+ << QuicTextUtils::HexEncode(config->id);
return nullptr;
}
configs_[config->id] = config;
SelectNewPrimaryConfig(now);
DCHECK(primary_config_.get());
- DCHECK_EQ(configs_.find(primary_config_->id)->second, primary_config_);
+ DCHECK_EQ(configs_.find(primary_config_->id)->second.get(),
+ primary_config_.get());
}
return msg.release();
@@ -414,14 +338,14 @@ CryptoHandshakeMessage* QuicCryptoServerConfig::AddDefaultConfig(
}
bool QuicCryptoServerConfig::SetConfigs(
- const vector<std::unique_ptr<QuicServerConfigProtobuf>>& protobufs,
+ const std::vector<std::unique_ptr<QuicServerConfigProtobuf>>& protobufs,
const QuicWallTime now) {
- vector<scoped_refptr<Config>> parsed_configs;
+ std::vector<QuicReferenceCountedPointer<Config>> parsed_configs;
bool ok = true;
for (auto& protobuf : protobufs) {
- scoped_refptr<Config> config(ParseConfigProtobuf(protobuf));
- if (!config.get()) {
+ QuicReferenceCountedPointer<Config> config(ParseConfigProtobuf(protobuf));
+ if (!config) {
ok = false;
break;
}
@@ -430,44 +354,49 @@ bool QuicCryptoServerConfig::SetConfigs(
}
if (parsed_configs.empty()) {
- LOG(WARNING) << "New config list is empty.";
+ QUIC_LOG(WARNING) << "New config list is empty.";
ok = false;
}
if (!ok) {
- LOG(WARNING) << "Rejecting QUIC configs because of above errors";
+ QUIC_LOG(WARNING) << "Rejecting QUIC configs because of above errors";
} else {
- VLOG(1) << "Updating configs:";
+ QUIC_LOG(INFO) << "Updating configs:";
- base::AutoLock locked(configs_lock_);
+ QuicWriterMutexLock locked(&configs_lock_);
ConfigMap new_configs;
- for (vector<scoped_refptr<Config>>::const_iterator i =
+ for (std::vector<QuicReferenceCountedPointer<Config>>::const_iterator i =
parsed_configs.begin();
i != parsed_configs.end(); ++i) {
- scoped_refptr<Config> config = *i;
+ QuicReferenceCountedPointer<Config> config = *i;
ConfigMap::iterator it = configs_.find(config->id);
if (it != configs_.end()) {
- VLOG(1) << "Keeping scid: " << QuicUtils::HexEncode(config->id)
- << " orbit: "
- << QuicUtils::HexEncode(
- reinterpret_cast<const char*>(config->orbit), kOrbitSize)
- << " new primary_time " << config->primary_time.ToUNIXSeconds()
- << " old primary_time "
- << it->second->primary_time.ToUNIXSeconds() << " new priority "
- << config->priority << " old priority " << it->second->priority;
+ QUIC_LOG(INFO) << "Keeping scid: "
+ << QuicTextUtils::HexEncode(config->id) << " orbit: "
+ << QuicTextUtils::HexEncode(
+ reinterpret_cast<const char*>(config->orbit),
+ kOrbitSize)
+ << " new primary_time "
+ << config->primary_time.ToUNIXSeconds()
+ << " old primary_time "
+ << it->second->primary_time.ToUNIXSeconds()
+ << " new priority " << config->priority
+ << " old priority " << it->second->priority;
// Update primary_time and priority.
it->second->primary_time = config->primary_time;
it->second->priority = config->priority;
new_configs.insert(*it);
} else {
- VLOG(1) << "Adding scid: " << QuicUtils::HexEncode(config->id)
- << " orbit: "
- << QuicUtils::HexEncode(
- reinterpret_cast<const char*>(config->orbit), kOrbitSize)
- << " primary_time " << config->primary_time.ToUNIXSeconds()
- << " priority " << config->priority;
+ QUIC_LOG(INFO) << "Adding scid: "
+ << QuicTextUtils::HexEncode(config->id) << " orbit: "
+ << QuicTextUtils::HexEncode(
+ reinterpret_cast<const char*>(config->orbit),
+ kOrbitSize)
+ << " primary_time "
+ << config->primary_time.ToUNIXSeconds() << " priority "
+ << config->priority;
new_configs.insert(std::make_pair(config->id, config));
}
}
@@ -475,19 +404,20 @@ bool QuicCryptoServerConfig::SetConfigs(
configs_.swap(new_configs);
SelectNewPrimaryConfig(now);
DCHECK(primary_config_.get());
- DCHECK_EQ(configs_.find(primary_config_->id)->second, primary_config_);
+ DCHECK_EQ(configs_.find(primary_config_->id)->second.get(),
+ primary_config_.get());
}
return ok;
}
void QuicCryptoServerConfig::SetSourceAddressTokenKeys(
- const vector<string>& keys) {
+ const std::vector<string>& keys) {
source_address_token_boxer_.SetKeys(keys);
}
-void QuicCryptoServerConfig::GetConfigIds(vector<string>* scids) const {
- base::AutoLock locked(configs_lock_);
+void QuicCryptoServerConfig::GetConfigIds(std::vector<string>* scids) const {
+ QuicReaderMutexLock locked(&configs_lock_);
for (ConfigMap::const_iterator it = configs_.begin(); it != configs_.end();
++it) {
scids->push_back(it->first);
@@ -496,25 +426,25 @@ void QuicCryptoServerConfig::GetConfigIds(vector<string>* scids) const {
void QuicCryptoServerConfig::ValidateClientHello(
const CryptoHandshakeMessage& client_hello,
- const IPAddress& client_ip,
- const IPAddress& server_ip,
+ const QuicIpAddress& client_ip,
+ const QuicSocketAddress& server_address,
QuicVersion version,
const QuicClock* clock,
- scoped_refptr<QuicCryptoProof> crypto_proof,
+ QuicReferenceCountedPointer<QuicSignedServerConfig> signed_config,
std::unique_ptr<ValidateClientHelloResultCallback> done_cb) const {
const QuicWallTime now(clock->WallNow());
- scoped_refptr<ValidateClientHelloResultCallback::Result> result(
+ QuicReferenceCountedPointer<ValidateClientHelloResultCallback::Result> result(
new ValidateClientHelloResultCallback::Result(client_hello, client_ip,
now));
StringPiece requested_scid;
client_hello.GetStringPiece(kSCID, &requested_scid);
- scoped_refptr<Config> requested_config;
- scoped_refptr<Config> primary_config;
+ QuicReferenceCountedPointer<Config> requested_config;
+ QuicReferenceCountedPointer<Config> primary_config;
{
- base::AutoLock locked(configs_lock_);
+ QuicReaderMutexLock locked(&configs_lock_);
if (!primary_config_.get()) {
result->error_code = QUIC_CRYPTO_INTERNAL_ERROR;
@@ -522,24 +452,30 @@ void QuicCryptoServerConfig::ValidateClientHello(
} else {
if (!next_config_promotion_time_.IsZero() &&
next_config_promotion_time_.IsAfter(now)) {
+ configs_lock_.ReaderUnlock();
+ configs_lock_.WriterLock();
SelectNewPrimaryConfig(now);
DCHECK(primary_config_.get());
- DCHECK_EQ(configs_.find(primary_config_->id)->second, primary_config_);
+ DCHECK_EQ(configs_.find(primary_config_->id)->second.get(),
+ primary_config_.get());
+ configs_lock_.WriterUnlock();
+ configs_lock_.ReaderLock();
}
}
requested_config = GetConfigWithScid(requested_scid);
primary_config = primary_config_;
- crypto_proof->config = primary_config_;
+ signed_config->config = primary_config_;
}
if (result->error_code == QUIC_NO_ERROR) {
// QUIC requires a new proof for each CHLO so clear any existing proof.
- crypto_proof->chain = nullptr;
- crypto_proof->signature = "";
- crypto_proof->cert_sct = "";
- EvaluateClientHello(server_ip, version, requested_config, primary_config,
- crypto_proof, result, std::move(done_cb));
+ signed_config->chain = nullptr;
+ signed_config->proof.signature = "";
+ signed_config->proof.leaf_cert_scts = "";
+ EvaluateClientHello(server_address, version, requested_config,
+ primary_config, signed_config, result,
+ std::move(done_cb));
} else {
done_cb->Run(result, /* details = */ nullptr);
}
@@ -584,11 +520,11 @@ class QuicCryptoServerConfig::ProcessClientHelloCallback
public:
ProcessClientHelloCallback(
const QuicCryptoServerConfig* config,
- scoped_refptr<ValidateClientHelloResultCallback::Result>
+ QuicReferenceCountedPointer<ValidateClientHelloResultCallback::Result>
validate_chlo_result,
bool reject_only,
QuicConnectionId connection_id,
- const IPEndPoint& client_address,
+ const QuicSocketAddress& client_address,
QuicVersion version,
const QuicVersionVector& supported_versions,
bool use_stateless_rejects,
@@ -596,12 +532,14 @@ class QuicCryptoServerConfig::ProcessClientHelloCallback
const QuicClock* clock,
QuicRandom* rand,
QuicCompressedCertsCache* compressed_certs_cache,
- scoped_refptr<QuicCryptoNegotiatedParameters> params,
- scoped_refptr<QuicCryptoProof> crypto_proof,
+ QuicReferenceCountedPointer<QuicCryptoNegotiatedParameters> params,
+ QuicReferenceCountedPointer<QuicSignedServerConfig> signed_config,
QuicByteCount total_framing_overhead,
QuicByteCount chlo_packet_size,
- const scoped_refptr<QuicCryptoServerConfig::Config>& requested_config,
- const scoped_refptr<QuicCryptoServerConfig::Config>& primary_config,
+ const QuicReferenceCountedPointer<QuicCryptoServerConfig::Config>&
+ requested_config,
+ const QuicReferenceCountedPointer<QuicCryptoServerConfig::Config>&
+ primary_config,
std::unique_ptr<ProcessClientHelloResultCallback> done_cb)
: config_(config),
validate_chlo_result_(std::move(validate_chlo_result)),
@@ -616,7 +554,7 @@ class QuicCryptoServerConfig::ProcessClientHelloCallback
rand_(rand),
compressed_certs_cache_(compressed_certs_cache),
params_(params),
- crypto_proof_(crypto_proof),
+ signed_config_(signed_config),
total_framing_overhead_(total_framing_overhead),
chlo_packet_size_(chlo_packet_size),
requested_config_(requested_config),
@@ -624,31 +562,29 @@ class QuicCryptoServerConfig::ProcessClientHelloCallback
done_cb_(std::move(done_cb)) {}
void Run(bool ok,
- const scoped_refptr<ProofSource::Chain>& chain,
- const string& signature,
- const string& leaf_cert_sct,
+ const QuicReferenceCountedPointer<ProofSource::Chain>& chain,
+ const QuicCryptoProof& proof,
std::unique_ptr<ProofSource::Details> details) override {
if (ok) {
- crypto_proof_->chain = chain;
- crypto_proof_->signature = signature;
- crypto_proof_->cert_sct = leaf_cert_sct;
+ signed_config_->chain = chain;
+ signed_config_->proof = proof;
}
config_->ProcessClientHelloAfterGetProof(
!ok, std::move(details), *validate_chlo_result_, reject_only_,
connection_id_, client_address_, version_, supported_versions_,
use_stateless_rejects_, server_designated_connection_id_, clock_, rand_,
- compressed_certs_cache_, params_, crypto_proof_,
+ compressed_certs_cache_, params_, signed_config_,
total_framing_overhead_, chlo_packet_size_, requested_config_,
primary_config_, std::move(done_cb_));
}
private:
const QuicCryptoServerConfig* config_;
- const scoped_refptr<ValidateClientHelloResultCallback::Result>
+ const QuicReferenceCountedPointer<ValidateClientHelloResultCallback::Result>
validate_chlo_result_;
const bool reject_only_;
const QuicConnectionId connection_id_;
- const IPEndPoint client_address_;
+ const QuicSocketAddress client_address_;
const QuicVersion version_;
const QuicVersionVector supported_versions_;
const bool use_stateless_rejects_;
@@ -656,22 +592,24 @@ class QuicCryptoServerConfig::ProcessClientHelloCallback
const QuicClock* const clock_;
QuicRandom* const rand_;
QuicCompressedCertsCache* compressed_certs_cache_;
- scoped_refptr<QuicCryptoNegotiatedParameters> params_;
- scoped_refptr<QuicCryptoProof> crypto_proof_;
+ QuicReferenceCountedPointer<QuicCryptoNegotiatedParameters> params_;
+ QuicReferenceCountedPointer<QuicSignedServerConfig> signed_config_;
const QuicByteCount total_framing_overhead_;
const QuicByteCount chlo_packet_size_;
- const scoped_refptr<QuicCryptoServerConfig::Config> requested_config_;
- const scoped_refptr<QuicCryptoServerConfig::Config> primary_config_;
+ const QuicReferenceCountedPointer<QuicCryptoServerConfig::Config>
+ requested_config_;
+ const QuicReferenceCountedPointer<QuicCryptoServerConfig::Config>
+ primary_config_;
std::unique_ptr<ProcessClientHelloResultCallback> done_cb_;
};
void QuicCryptoServerConfig::ProcessClientHello(
- scoped_refptr<ValidateClientHelloResultCallback::Result>
+ QuicReferenceCountedPointer<ValidateClientHelloResultCallback::Result>
validate_chlo_result,
bool reject_only,
QuicConnectionId connection_id,
- const IPAddress& server_ip,
- const IPEndPoint& client_address,
+ const QuicSocketAddress& server_address,
+ const QuicSocketAddress& client_address,
QuicVersion version,
const QuicVersionVector& supported_versions,
bool use_stateless_rejects,
@@ -679,8 +617,8 @@ void QuicCryptoServerConfig::ProcessClientHello(
const QuicClock* clock,
QuicRandom* rand,
QuicCompressedCertsCache* compressed_certs_cache,
- scoped_refptr<QuicCryptoNegotiatedParameters> params,
- scoped_refptr<QuicCryptoProof> crypto_proof,
+ QuicReferenceCountedPointer<QuicCryptoNegotiatedParameters> params,
+ QuicReferenceCountedPointer<QuicSignedServerConfig> signed_config,
QuicByteCount total_framing_overhead,
QuicByteCount chlo_packet_size,
std::unique_ptr<ProcessClientHelloResultCallback> done_cb) const {
@@ -704,25 +642,30 @@ void QuicCryptoServerConfig::ProcessClientHello(
client_hello.GetStringPiece(kSCID, &requested_scid);
const QuicWallTime now(clock->WallNow());
- scoped_refptr<Config> requested_config;
- scoped_refptr<Config> primary_config;
+ QuicReferenceCountedPointer<Config> requested_config;
+ QuicReferenceCountedPointer<Config> primary_config;
bool no_primary_config = false;
{
- base::AutoLock locked(configs_lock_);
+ QuicReaderMutexLock locked(&configs_lock_);
if (!primary_config_) {
no_primary_config = true;
} else {
if (!next_config_promotion_time_.IsZero() &&
next_config_promotion_time_.IsAfter(now)) {
+ configs_lock_.ReaderUnlock();
+ configs_lock_.WriterLock();
SelectNewPrimaryConfig(now);
DCHECK(primary_config_.get());
- DCHECK_EQ(configs_.find(primary_config_->id)->second, primary_config_);
+ DCHECK_EQ(configs_.find(primary_config_->id)->second.get(),
+ primary_config_.get());
+ configs_lock_.WriterUnlock();
+ configs_lock_.ReaderLock();
}
// Use the config that the client requested in order to do key-agreement.
// Otherwise give it a copy of |primary_config_| to use.
- primary_config = crypto_proof->config;
+ primary_config = signed_config->config;
requested_config = GetConfigWithScid(requested_scid);
}
}
@@ -746,36 +689,38 @@ void QuicCryptoServerConfig::ProcessClientHello(
CryptoUtils::HashHandshakeMessage(client_hello, &chlo_hash);
// No need to get a new proof if one was already generated.
- if (!crypto_proof->chain) {
+ if (!signed_config->chain) {
const QuicTag* tag_ptr;
size_t num_tags;
QuicTagVector connection_options;
if (client_hello.GetTaglist(kCOPT, &tag_ptr, &num_tags) == QUIC_NO_ERROR) {
connection_options.assign(tag_ptr, tag_ptr + num_tags);
}
- if (FLAGS_enable_async_get_proof) {
+ if (FLAGS_quic_reloadable_flag_enable_async_get_proof) {
std::unique_ptr<ProcessClientHelloCallback> cb(
new ProcessClientHelloCallback(
this, validate_chlo_result, reject_only, connection_id,
client_address, version, supported_versions,
use_stateless_rejects, server_designated_connection_id, clock,
- rand, compressed_certs_cache, params, crypto_proof,
+ rand, compressed_certs_cache, params, signed_config,
total_framing_overhead, chlo_packet_size, requested_config,
primary_config, std::move(done_cb)));
- proof_source_->GetProof(server_ip, info.sni.as_string(),
+ proof_source_->GetProof(server_address, info.sni.as_string(),
primary_config->serialized, version, chlo_hash,
connection_options, std::move(cb));
helper.DetachCallback();
return;
}
- if (!proof_source_->GetProof(
- server_ip, info.sni.as_string(), primary_config->serialized,
- version, chlo_hash, connection_options, &crypto_proof->chain,
- &crypto_proof->signature, &crypto_proof->cert_sct)) {
+ QuicCryptoProof proof;
+ if (!proof_source_->GetProof(server_address, info.sni.as_string(),
+ primary_config->serialized, version, chlo_hash,
+ connection_options, &signed_config->chain,
+ &proof)) {
helper.Fail(QUIC_HANDSHAKE_FAILED, "Missing or invalid crypto proof.");
return;
}
+ signed_config->proof = proof;
}
helper.DetachCallback();
@@ -784,7 +729,7 @@ void QuicCryptoServerConfig::ProcessClientHello(
*validate_chlo_result, reject_only, connection_id, client_address,
version, supported_versions, use_stateless_rejects,
server_designated_connection_id, clock, rand, compressed_certs_cache,
- params, crypto_proof, total_framing_overhead, chlo_packet_size,
+ params, signed_config, total_framing_overhead, chlo_packet_size,
requested_config, primary_config, std::move(done_cb));
}
@@ -794,7 +739,7 @@ void QuicCryptoServerConfig::ProcessClientHelloAfterGetProof(
const ValidateClientHelloResultCallback::Result& validate_chlo_result,
bool reject_only,
QuicConnectionId connection_id,
- const IPEndPoint& client_address,
+ const QuicSocketAddress& client_address,
QuicVersion version,
const QuicVersionVector& supported_versions,
bool use_stateless_rejects,
@@ -802,12 +747,12 @@ void QuicCryptoServerConfig::ProcessClientHelloAfterGetProof(
const QuicClock* clock,
QuicRandom* rand,
QuicCompressedCertsCache* compressed_certs_cache,
- scoped_refptr<QuicCryptoNegotiatedParameters> params,
- scoped_refptr<QuicCryptoProof> crypto_proof,
+ QuicReferenceCountedPointer<QuicCryptoNegotiatedParameters> params,
+ QuicReferenceCountedPointer<QuicSignedServerConfig> signed_config,
QuicByteCount total_framing_overhead,
QuicByteCount chlo_packet_size,
- const scoped_refptr<Config>& requested_config,
- const scoped_refptr<Config>& primary_config,
+ const QuicReferenceCountedPointer<Config>& requested_config,
+ const QuicReferenceCountedPointer<Config>& primary_config,
std::unique_ptr<ProcessClientHelloResultCallback> done_cb) const {
ProcessClientHelloHelper helper(&done_cb);
@@ -833,10 +778,9 @@ void QuicCryptoServerConfig::ProcessClientHelloAfterGetProof(
BuildRejection(version, clock->WallNow(), *primary_config, client_hello,
info, validate_chlo_result.cached_network_params,
use_stateless_rejects, server_designated_connection_id, rand,
- compressed_certs_cache, params, *crypto_proof,
+ compressed_certs_cache, params, *signed_config,
total_framing_overhead, chlo_packet_size, out.get());
- if (FLAGS_quic_export_rej_for_all_rejects &&
- rejection_observer_ != nullptr) {
+ if (rejection_observer_ != nullptr) {
rejection_observer_->OnRejectionBuilt(info.reject_reasons, out.get());
}
helper.Succeed(std::move(out), std::move(out_diversification_nonce),
@@ -864,13 +808,11 @@ void QuicCryptoServerConfig::ProcessClientHelloAfterGetProof(
}
size_t key_exchange_index;
- if (!QuicUtils::FindMutualTag(requested_config->aead, their_aeads,
- num_their_aeads, QuicUtils::LOCAL_PRIORITY,
- &params->aead, nullptr) ||
- !QuicUtils::FindMutualTag(requested_config->kexs, their_key_exchanges,
- num_their_key_exchanges,
- QuicUtils::LOCAL_PRIORITY,
- &params->key_exchange, &key_exchange_index)) {
+ if (!FindMutualQuicTag(requested_config->aead, their_aeads, num_their_aeads,
+ &params->aead, nullptr) ||
+ !FindMutualQuicTag(requested_config->kexs, their_key_exchanges,
+ num_their_key_exchanges, &params->key_exchange,
+ &key_exchange_index)) {
helper.Fail(QUIC_CRYPTO_NO_SUPPORT, "Unsupported AEAD or KEXS");
return;
}
@@ -882,10 +824,9 @@ void QuicCryptoServerConfig::ProcessClientHelloAfterGetProof(
case QUIC_CRYPTO_MESSAGE_PARAMETER_NOT_FOUND:
break;
case QUIC_NO_ERROR:
- if (QuicUtils::FindMutualTag(
- requested_config->tb_key_params, their_tbkps, num_their_tbkps,
- QuicUtils::LOCAL_PRIORITY, &params->token_binding_key_param,
- nullptr)) {
+ if (FindMutualQuicTag(requested_config->tb_key_params, their_tbkps,
+ num_their_tbkps, &params->token_binding_key_param,
+ nullptr)) {
break;
}
default:
@@ -926,11 +867,11 @@ void QuicCryptoServerConfig::ProcessClientHelloAfterGetProof(
client_hello_serialized.length());
hkdf_suffix.append(requested_config->serialized);
DCHECK(proof_source_.get());
- if (crypto_proof->chain->certs.empty()) {
+ if (signed_config->chain->certs.empty()) {
helper.Fail(QUIC_CRYPTO_INTERNAL_ERROR, "Failed to get certs");
return;
}
- hkdf_suffix.append(crypto_proof->chain->certs.at(0));
+ hkdf_suffix.append(signed_config->chain->certs.at(0));
StringPiece cetv_ciphertext;
if (requested_config->channel_id_enabled &&
@@ -964,7 +905,7 @@ void QuicCryptoServerConfig::ProcessClientHelloAfterGetProof(
char plaintext[kMaxPacketSize];
size_t plaintext_length = 0;
const bool success = crypters.decrypter->DecryptPacket(
- kDefaultPathId, 0 /* packet number */,
+ QUIC_VERSION_35, kDefaultPathId, 0 /* packet number */,
StringPiece() /* associated data */, cetv_ciphertext, plaintext,
&plaintext_length, kMaxPacketSize);
if (!success) {
@@ -998,15 +939,10 @@ void QuicCryptoServerConfig::ProcessClientHelloAfterGetProof(
hkdf_input.append(QuicCryptoConfig::kInitialLabel, label_len);
hkdf_input.append(hkdf_suffix);
+ rand->RandBytes(out_diversification_nonce->data(),
+ out_diversification_nonce->size());
CryptoUtils::Diversification diversification =
- CryptoUtils::Diversification::Never();
- if (version > QUIC_VERSION_32) {
- rand->RandBytes(out_diversification_nonce->data(),
- out_diversification_nonce->size());
- diversification =
- CryptoUtils::Diversification::Now(out_diversification_nonce.get());
- }
-
+ CryptoUtils::Diversification::Now(out_diversification_nonce.get());
if (!CryptoUtils::DeriveKeys(params->initial_premaster_secret, params->aead,
info.client_nonce, info.server_nonce, hkdf_input,
Perspective::IS_SERVER, diversification,
@@ -1068,8 +1004,8 @@ void QuicCryptoServerConfig::ProcessClientHelloAfterGetProof(
out->SetVector(kVER, supported_version_tags);
out->SetStringPiece(
kSourceAddressTokenTag,
- NewSourceAddressToken(*requested_config.get(), info.source_address_tokens,
- client_address.address(), rand, info.now, nullptr));
+ NewSourceAddressToken(*requested_config, info.source_address_tokens,
+ client_address.host(), rand, info.now, nullptr));
QuicSocketAddressCoder address_coder(client_address);
out->SetStringPiece(kCADR, address_coder.Encode());
out->SetStringPiece(kPUBS, forward_secure_public_value);
@@ -1078,30 +1014,28 @@ void QuicCryptoServerConfig::ProcessClientHelloAfterGetProof(
std::move(proof_source_details));
}
-scoped_refptr<QuicCryptoServerConfig::Config>
+QuicReferenceCountedPointer<QuicCryptoServerConfig::Config>
QuicCryptoServerConfig::GetConfigWithScid(StringPiece requested_scid) const {
- // In Chromium, we will dead lock if the lock is held by the current thread.
- // Chromium doesn't have AssertReaderHeld API call.
- // configs_lock_.AssertReaderHeld();
+ configs_lock_.AssertReaderHeld();
if (!requested_scid.empty()) {
ConfigMap::const_iterator it = configs_.find(requested_scid.as_string());
if (it != configs_.end()) {
// We'll use the config that the client requested in order to do
// key-agreement.
- return scoped_refptr<Config>(it->second);
+ return QuicReferenceCountedPointer<Config>(it->second);
}
}
- return scoped_refptr<Config>();
+ return QuicReferenceCountedPointer<Config>();
}
// ConfigPrimaryTimeLessThan is a comparator that implements "less than" for
// Config's based on their primary_time.
// static
bool QuicCryptoServerConfig::ConfigPrimaryTimeLessThan(
- const scoped_refptr<Config>& a,
- const scoped_refptr<Config>& b) {
+ const QuicReferenceCountedPointer<Config>& a,
+ const QuicReferenceCountedPointer<Config>& b) {
if (a->primary_time.IsBefore(b->primary_time) ||
b->primary_time.IsBefore(a->primary_time)) {
// Primary times differ.
@@ -1117,7 +1051,7 @@ bool QuicCryptoServerConfig::ConfigPrimaryTimeLessThan(
void QuicCryptoServerConfig::SelectNewPrimaryConfig(
const QuicWallTime now) const {
- vector<scoped_refptr<Config>> configs;
+ std::vector<QuicReferenceCountedPointer<Config>> configs;
configs.reserve(configs_.size());
for (ConfigMap::const_iterator it = configs_.begin(); it != configs_.end();
@@ -1127,7 +1061,7 @@ void QuicCryptoServerConfig::SelectNewPrimaryConfig(
}
if (configs.empty()) {
- if (primary_config_.get()) {
+ if (primary_config_ != nullptr) {
QUIC_BUG << "No valid QUIC server config. Keeping the current config.";
} else {
QUIC_BUG << "No valid QUIC server config.";
@@ -1137,13 +1071,13 @@ void QuicCryptoServerConfig::SelectNewPrimaryConfig(
std::sort(configs.begin(), configs.end(), ConfigPrimaryTimeLessThan);
- Config* best_candidate = configs[0].get();
+ QuicReferenceCountedPointer<Config> best_candidate = configs[0];
for (size_t i = 0; i < configs.size(); ++i) {
- const scoped_refptr<Config> config(configs[i]);
+ const QuicReferenceCountedPointer<Config> config(configs[i]);
if (!config->primary_time.IsAfter(now)) {
if (config->primary_time.IsAfter(best_candidate->primary_time)) {
- best_candidate = config.get();
+ best_candidate = config;
}
continue;
}
@@ -1151,7 +1085,7 @@ void QuicCryptoServerConfig::SelectNewPrimaryConfig(
// This is the first config with a primary_time in the future. Thus the
// previous Config should be the primary and this one should determine the
// next_config_promotion_time_.
- scoped_refptr<Config> new_primary(best_candidate);
+ QuicReferenceCountedPointer<Config> new_primary = best_candidate;
if (i == 0) {
// We need the primary_time of the next config.
if (configs.size() > 1) {
@@ -1163,15 +1097,15 @@ void QuicCryptoServerConfig::SelectNewPrimaryConfig(
next_config_promotion_time_ = config->primary_time;
}
- if (primary_config_.get()) {
+ if (primary_config_) {
primary_config_->is_primary = false;
}
primary_config_ = new_primary;
new_primary->is_primary = true;
- DVLOG(1) << "New primary config. orbit: "
- << QuicUtils::HexEncode(
- reinterpret_cast<const char*>(primary_config_->orbit),
- kOrbitSize);
+ QUIC_DLOG(INFO) << "New primary config. orbit: "
+ << QuicTextUtils::HexEncode(reinterpret_cast<const char*>(
+ primary_config_->orbit),
+ kOrbitSize);
if (primary_config_changed_cb_.get() != nullptr) {
primary_config_changed_cb_->Run(primary_config_->id);
}
@@ -1181,17 +1115,17 @@ void QuicCryptoServerConfig::SelectNewPrimaryConfig(
// All config's primary times are in the past. We should make the most recent
// and highest priority candidate primary.
- scoped_refptr<Config> new_primary(best_candidate);
- if (primary_config_.get()) {
+ QuicReferenceCountedPointer<Config> new_primary = best_candidate;
+ if (primary_config_) {
primary_config_->is_primary = false;
}
primary_config_ = new_primary;
new_primary->is_primary = true;
- DVLOG(1) << "New primary config. orbit: "
- << QuicUtils::HexEncode(
- reinterpret_cast<const char*>(primary_config_->orbit),
- kOrbitSize)
- << " scid: " << QuicUtils::HexEncode(primary_config_->id);
+ QUIC_DLOG(INFO) << "New primary config. orbit: "
+ << QuicTextUtils::HexEncode(
+ reinterpret_cast<const char*>(primary_config_->orbit),
+ kOrbitSize)
+ << " scid: " << QuicTextUtils::HexEncode(primary_config_->id);
next_config_promotion_time_ = QuicWallTime::Zero();
if (primary_config_changed_cb_.get() != nullptr) {
primary_config_changed_cb_->Run(primary_config_->id);
@@ -1204,12 +1138,14 @@ class QuicCryptoServerConfig::EvaluateClientHelloCallback
EvaluateClientHelloCallback(
const QuicCryptoServerConfig& config,
bool found_error,
- const IPAddress& server_ip,
+ const QuicIpAddress& server_ip,
QuicVersion version,
- scoped_refptr<QuicCryptoServerConfig::Config> requested_config,
- scoped_refptr<QuicCryptoServerConfig::Config> primary_config,
- scoped_refptr<QuicCryptoProof> crypto_proof,
- scoped_refptr<ValidateClientHelloResultCallback::Result>
+ QuicReferenceCountedPointer<QuicCryptoServerConfig::Config>
+ requested_config,
+ QuicReferenceCountedPointer<QuicCryptoServerConfig::Config>
+ primary_config,
+ QuicReferenceCountedPointer<QuicSignedServerConfig> signed_config,
+ QuicReferenceCountedPointer<ValidateClientHelloResultCallback::Result>
client_hello_state,
std::unique_ptr<ValidateClientHelloResultCallback> done_cb)
: config_(config),
@@ -1218,45 +1154,47 @@ class QuicCryptoServerConfig::EvaluateClientHelloCallback
version_(version),
requested_config_(std::move(requested_config)),
primary_config_(std::move(primary_config)),
- crypto_proof_(crypto_proof),
+ signed_config_(signed_config),
client_hello_state_(std::move(client_hello_state)),
done_cb_(std::move(done_cb)) {}
void Run(bool ok,
- const scoped_refptr<ProofSource::Chain>& chain,
- const string& signature,
- const string& leaf_cert_sct,
+ const QuicReferenceCountedPointer<ProofSource::Chain>& chain,
+ const QuicCryptoProof& proof,
std::unique_ptr<ProofSource::Details> details) override {
if (ok) {
- crypto_proof_->chain = chain;
- crypto_proof_->signature = signature;
- crypto_proof_->cert_sct = leaf_cert_sct;
+ signed_config_->chain = chain;
+ signed_config_->proof = proof;
}
config_.EvaluateClientHelloAfterGetProof(
found_error_, server_ip_, version_, requested_config_, primary_config_,
- crypto_proof_, std::move(details), !ok, client_hello_state_,
+ signed_config_, std::move(details), !ok, client_hello_state_,
std::move(done_cb_));
}
private:
const QuicCryptoServerConfig& config_;
const bool found_error_;
- const IPAddress& server_ip_;
+ const QuicIpAddress& server_ip_;
const QuicVersion version_;
- const scoped_refptr<QuicCryptoServerConfig::Config> requested_config_;
- const scoped_refptr<QuicCryptoServerConfig::Config> primary_config_;
- scoped_refptr<QuicCryptoProof> crypto_proof_;
- scoped_refptr<ValidateClientHelloResultCallback::Result> client_hello_state_;
+ const QuicReferenceCountedPointer<QuicCryptoServerConfig::Config>
+ requested_config_;
+ const QuicReferenceCountedPointer<QuicCryptoServerConfig::Config>
+ primary_config_;
+ QuicReferenceCountedPointer<QuicSignedServerConfig> signed_config_;
+ QuicReferenceCountedPointer<ValidateClientHelloResultCallback::Result>
+ client_hello_state_;
std::unique_ptr<ValidateClientHelloResultCallback> done_cb_;
};
void QuicCryptoServerConfig::EvaluateClientHello(
- const IPAddress& server_ip,
+ const QuicSocketAddress& server_address,
QuicVersion version,
- scoped_refptr<Config> requested_config,
- scoped_refptr<Config> primary_config,
- scoped_refptr<QuicCryptoProof> crypto_proof,
- scoped_refptr<ValidateClientHelloResultCallback::Result> client_hello_state,
+ QuicReferenceCountedPointer<Config> requested_config,
+ QuicReferenceCountedPointer<Config> primary_config,
+ QuicReferenceCountedPointer<QuicSignedServerConfig> signed_config,
+ QuicReferenceCountedPointer<ValidateClientHelloResultCallback::Result>
+ client_hello_state,
std::unique_ptr<ValidateClientHelloResultCallback> done_cb) const {
ValidateClientHelloHelper helper(client_hello_state, &done_cb);
@@ -1281,7 +1219,8 @@ void QuicCryptoServerConfig::EvaluateClientHello(
HandshakeFailureReason source_address_token_error = MAX_FAILURE_REASON;
StringPiece srct;
if (client_hello.GetStringPiece(kSourceAddressTokenTag, &srct)) {
- Config& config = requested_config ? *requested_config : *primary_config;
+ Config& config =
+ requested_config != nullptr ? *requested_config : *primary_config;
source_address_token_error =
ParseSourceAddressToken(config, srct, &info->source_address_tokens);
@@ -1327,23 +1266,23 @@ void QuicCryptoServerConfig::EvaluateClientHello(
string chlo_hash;
CryptoUtils::HashHandshakeMessage(client_hello, &chlo_hash);
bool need_proof = true;
- need_proof = !crypto_proof->chain;
+ need_proof = !signed_config->chain;
const QuicTag* tag_ptr;
size_t num_tags;
QuicTagVector connection_options;
if (client_hello.GetTaglist(kCOPT, &tag_ptr, &num_tags) == QUIC_NO_ERROR) {
connection_options.assign(tag_ptr, tag_ptr + num_tags);
}
- if (FLAGS_enable_async_get_proof) {
+ if (FLAGS_quic_reloadable_flag_enable_async_get_proof) {
if (need_proof) {
// Make an async call to GetProof and setup the callback to trampoline
// back into EvaluateClientHelloAfterGetProof
std::unique_ptr<EvaluateClientHelloCallback> cb(
new EvaluateClientHelloCallback(
- *this, found_error, server_ip, version, requested_config,
- primary_config, crypto_proof, client_hello_state,
- std::move(done_cb)));
- proof_source_->GetProof(server_ip, info->sni.as_string(),
+ *this, found_error, server_address.host(), version,
+ requested_config, primary_config, signed_config,
+ client_hello_state, std::move(done_cb)));
+ proof_source_->GetProof(server_address, info->sni.as_string(),
serialized_config, version, chlo_hash,
connection_options, std::move(cb));
helper.DetachCallback();
@@ -1352,142 +1291,80 @@ void QuicCryptoServerConfig::EvaluateClientHello(
}
// No need to get a new proof if one was already generated.
- if (need_proof &&
- !proof_source_->GetProof(
- server_ip, info->sni.as_string(), serialized_config, version,
- chlo_hash, connection_options, &crypto_proof->chain,
- &crypto_proof->signature, &crypto_proof->cert_sct)) {
- get_proof_failed = true;
+ if (need_proof) {
+ QuicCryptoProof proof;
+
+ if (proof_source_->GetProof(
+ server_address, info->sni.as_string(), serialized_config, version,
+ chlo_hash, connection_options, &signed_config->chain, &proof)) {
+ signed_config->proof = proof;
+ } else {
+ get_proof_failed = true;
+ }
}
// Details are null because the synchronous version of GetProof does not
// return any stats. Eventually the synchronous codepath will be eliminated.
EvaluateClientHelloAfterGetProof(
- found_error, server_ip, version, requested_config, primary_config,
- crypto_proof, nullptr /* proof_source_details */, get_proof_failed,
- client_hello_state, std::move(done_cb));
+ found_error, server_address.host(), version, requested_config,
+ primary_config, signed_config, nullptr /* proof_source_details */,
+ get_proof_failed, client_hello_state, std::move(done_cb));
helper.DetachCallback();
}
void QuicCryptoServerConfig::EvaluateClientHelloAfterGetProof(
bool found_error,
- const IPAddress& server_ip,
+ const QuicIpAddress& server_ip,
QuicVersion version,
- scoped_refptr<Config> requested_config,
- scoped_refptr<Config> primary_config,
- scoped_refptr<QuicCryptoProof> crypto_proof,
+ QuicReferenceCountedPointer<Config> requested_config,
+ QuicReferenceCountedPointer<Config> primary_config,
+ QuicReferenceCountedPointer<QuicSignedServerConfig> signed_config,
std::unique_ptr<ProofSource::Details> proof_source_details,
bool get_proof_failed,
- scoped_refptr<ValidateClientHelloResultCallback::Result> client_hello_state,
+ QuicReferenceCountedPointer<ValidateClientHelloResultCallback::Result>
+ client_hello_state,
std::unique_ptr<ValidateClientHelloResultCallback> done_cb) const {
ValidateClientHelloHelper helper(client_hello_state, &done_cb);
const CryptoHandshakeMessage& client_hello = client_hello_state->client_hello;
ClientHelloInfo* info = &(client_hello_state->info);
if (get_proof_failed) {
- found_error = true;
info->reject_reasons.push_back(SERVER_CONFIG_UNKNOWN_CONFIG_FAILURE);
}
- if (!ValidateExpectedLeafCertificate(client_hello, *crypto_proof)) {
- found_error = true;
+ if (signed_config->chain != nullptr &&
+ !ValidateExpectedLeafCertificate(client_hello,
+ signed_config->chain->certs)) {
info->reject_reasons.push_back(INVALID_EXPECTED_LEAF_CERTIFICATE);
}
if (info->client_nonce.size() != kNonceSize) {
info->reject_reasons.push_back(CLIENT_NONCE_INVALID_FAILURE);
// Invalid client nonce.
- LOG(ERROR) << "Invalid client nonce: " << client_hello.DebugString();
- DVLOG(1) << "Invalid client nonce.";
- found_error = true;
+ QUIC_LOG_FIRST_N(ERROR, 2) << "Invalid client nonce: "
+ << client_hello.DebugString();
+ QUIC_DLOG(INFO) << "Invalid client nonce.";
}
// Server nonce is optional, and used for key derivation if present.
client_hello.GetStringPiece(kServerNonceTag, &info->server_nonce);
- if (version > QUIC_VERSION_32) {
- DVLOG(1) << "No 0-RTT replay protection in QUIC_VERSION_33 and higher.";
- // If the server nonce is empty and we're requiring handshake confirmation
- // for DoS reasons then we must reject the CHLO.
- if (FLAGS_quic_require_handshake_confirmation &&
- info->server_nonce.empty()) {
- info->reject_reasons.push_back(SERVER_NONCE_REQUIRED_FAILURE);
- }
- helper.ValidationComplete(QUIC_NO_ERROR, "",
- std::move(proof_source_details));
- return;
- }
-
- if (!replay_protection_) {
- DVLOG(1) << "No replay protection.";
- helper.ValidationComplete(QUIC_NO_ERROR, "",
- std::move(proof_source_details));
- return;
- }
-
- if (!info->server_nonce.empty()) {
- // If the server nonce is present, use it to establish uniqueness.
- HandshakeFailureReason server_nonce_error =
- ValidateServerNonce(info->server_nonce, info->now);
- bool is_unique = server_nonce_error == HANDSHAKE_OK;
- if (!is_unique) {
- info->reject_reasons.push_back(server_nonce_error);
- }
- DVLOG(1) << "Using server nonce, unique: " << is_unique;
- helper.ValidationComplete(QUIC_NO_ERROR, "",
- std::move(proof_source_details));
- return;
- }
- // If we hit this block, the server nonce was empty. If we're requiring
- // handshake confirmation for DoS reasons and there's no server nonce present,
- // reject the CHLO.
- if (FLAGS_quic_require_handshake_confirmation ||
- FLAGS_quic_require_handshake_confirmation_pre33) {
- info->reject_reasons.push_back(SERVER_NONCE_REQUIRED_FAILURE);
- helper.ValidationComplete(QUIC_NO_ERROR, "",
- std::move(proof_source_details));
- return;
- }
-
- // We want to contact strike register only if there are no errors because it
- // is a RPC call and is expensive.
- if (found_error) {
- helper.ValidationComplete(QUIC_NO_ERROR, "",
- std::move(proof_source_details));
- return;
- }
-
- // Use the client nonce to establish uniqueness.
- StrikeRegisterClient* strike_register_client;
- {
- base::AutoLock locked(strike_register_client_lock_);
- strike_register_client = strike_register_client_.get();
- }
-
- if (!strike_register_client) {
- // Either a valid server nonces or a strike register is required.
- // Since neither are present, reject the handshake which will send a
- // server nonce to the client.
+ QUIC_DVLOG(1) << "No 0-RTT replay protection in QUIC_VERSION_33 and higher.";
+ // If the server nonce is empty and we're requiring handshake confirmation
+ // for DoS reasons then we must reject the CHLO.
+ if (FLAGS_quic_reloadable_flag_quic_require_handshake_confirmation &&
+ info->server_nonce.empty()) {
info->reject_reasons.push_back(SERVER_NONCE_REQUIRED_FAILURE);
- helper.ValidationComplete(QUIC_NO_ERROR, "",
- std::move(proof_source_details));
- return;
}
-
- strike_register_client->VerifyNonceIsValidAndUnique(
- info->client_nonce, info->now,
- new VerifyNonceIsValidAndUniqueCallback(client_hello_state,
- std::move(proof_source_details),
- std::move(done_cb)));
- helper.DetachCallback();
+ helper.ValidationComplete(QUIC_NO_ERROR, "", std::move(proof_source_details));
}
bool QuicCryptoServerConfig::BuildServerConfigUpdateMessage(
QuicVersion version,
StringPiece chlo_hash,
const SourceAddressTokens& previous_source_address_tokens,
- const IPAddress& server_ip,
- const IPAddress& client_ip,
+ const QuicSocketAddress& server_address,
+ const QuicIpAddress& client_ip,
const QuicClock* clock,
QuicRandom* rand,
QuicCompressedCertsCache* compressed_certs_cache,
@@ -1500,7 +1377,7 @@ bool QuicCryptoServerConfig::BuildServerConfigUpdateMessage(
QuicWallTime expiry_time = QuicWallTime::Zero();
const CommonCertSets* common_cert_sets;
{
- base::AutoLock locked(configs_lock_);
+ QuicReaderMutexLock locked(&configs_lock_);
serialized = primary_config_->serialized;
common_cert_sets = primary_config_->common_cert_sets;
expiry_time = primary_config_->expiry_time;
@@ -1515,13 +1392,11 @@ bool QuicCryptoServerConfig::BuildServerConfigUpdateMessage(
out->SetValue(kSTTL,
expiry_time.AbsoluteDifference(clock->WallNow()).ToSeconds());
- scoped_refptr<ProofSource::Chain> chain;
- string signature;
- string cert_sct;
- if (!proof_source_->GetProof(server_ip, params.sni, serialized, version,
- chlo_hash, connection_options, &chain,
- &signature, &cert_sct)) {
- DVLOG(1) << "Server: failed to get proof.";
+ QuicReferenceCountedPointer<ProofSource::Chain> chain;
+ QuicCryptoProof proof;
+ if (!proof_source_->GetProof(server_address, params.sni, serialized, version,
+ chlo_hash, connection_options, &chain, &proof)) {
+ QUIC_DVLOG(1) << "Server: failed to get proof.";
return false;
}
@@ -1530,13 +1405,14 @@ bool QuicCryptoServerConfig::BuildServerConfigUpdateMessage(
params.client_cached_cert_hashes, common_cert_sets);
out->SetStringPiece(kCertificateTag, compressed);
- out->SetStringPiece(kPROF, signature);
+ out->SetStringPiece(kPROF, proof.signature);
if (params.sct_supported_by_client && enable_serving_sct_) {
- if (cert_sct.empty()) {
- DLOG(WARNING) << "SCT is expected but it is empty. sni: " << params.sni
- << " server_ip: " << server_ip.ToString();
+ if (proof.leaf_cert_scts.empty()) {
+ QUIC_LOG_EVERY_N_SEC(WARNING, 60)
+ << "SCT is expected but it is empty. sni: " << params.sni
+ << " server_address: " << server_address.ToString();
} else {
- out->SetStringPiece(kCertificateSCTTag, cert_sct);
+ out->SetStringPiece(kCertificateSCTTag, proof.leaf_cert_scts);
}
}
return true;
@@ -1546,8 +1422,8 @@ void QuicCryptoServerConfig::BuildServerConfigUpdateMessage(
QuicVersion version,
StringPiece chlo_hash,
const SourceAddressTokens& previous_source_address_tokens,
- const IPAddress& server_ip,
- const IPAddress& client_ip,
+ const QuicSocketAddress& server_address,
+ const QuicIpAddress& client_ip,
const QuicClock* clock,
QuicRandom* rand,
QuicCompressedCertsCache* compressed_certs_cache,
@@ -1559,7 +1435,7 @@ void QuicCryptoServerConfig::BuildServerConfigUpdateMessage(
string source_address_token;
const CommonCertSets* common_cert_sets;
{
- base::AutoLock locked(configs_lock_);
+ QuicReaderMutexLock locked(&configs_lock_);
serialized = primary_config_->serialized;
common_cert_sets = primary_config_->common_cert_sets;
source_address_token = NewSourceAddressToken(
@@ -1583,8 +1459,9 @@ void QuicCryptoServerConfig::BuildServerConfigUpdateMessage(
// and so should not have much impact on the experiments associated with that
// tag (plus it would be a chore to plumb information about the tag down to
// here).
- proof_source_->GetProof(server_ip, params.sni, serialized, version, chlo_hash,
- connection_options, std::move(proof_source_cb));
+ proof_source_->GetProof(server_address, params.sni, serialized, version,
+ chlo_hash, connection_options,
+ std::move(proof_source_cb));
}
QuicCryptoServerConfig::BuildServerConfigUpdateMessageProofSourceCallback::
@@ -1611,15 +1488,15 @@ QuicCryptoServerConfig::BuildServerConfigUpdateMessageProofSourceCallback::
void QuicCryptoServerConfig::BuildServerConfigUpdateMessageProofSourceCallback::
Run(bool ok,
- const scoped_refptr<ProofSource::Chain>& chain,
- const string& signature,
- const string& leaf_cert_sct,
+ const QuicReferenceCountedPointer<ProofSource::Chain>& chain,
+ const QuicCryptoProof& proof,
std::unique_ptr<ProofSource::Details> details) {
config_->FinishBuildServerConfigUpdateMessage(
version_, compressed_certs_cache_, common_cert_sets_,
client_common_set_hashes_, client_cached_cert_hashes_,
- sct_supported_by_client_, ok, chain, signature, leaf_cert_sct,
- std::move(details), std::move(message_), std::move(cb_));
+ sct_supported_by_client_, ok, chain, proof.signature,
+ proof.leaf_cert_scts, std::move(details), std::move(message_),
+ std::move(cb_));
}
void QuicCryptoServerConfig::FinishBuildServerConfigUpdateMessage(
@@ -1630,7 +1507,7 @@ void QuicCryptoServerConfig::FinishBuildServerConfigUpdateMessage(
const string& client_cached_cert_hashes,
bool sct_supported_by_client,
bool ok,
- const scoped_refptr<ProofSource::Chain>& chain,
+ const QuicReferenceCountedPointer<ProofSource::Chain>& chain,
const string& signature,
const string& leaf_cert_sct,
std::unique_ptr<ProofSource::Details> details,
@@ -1649,7 +1526,7 @@ void QuicCryptoServerConfig::FinishBuildServerConfigUpdateMessage(
message.SetStringPiece(kPROF, signature);
if (sct_supported_by_client && enable_serving_sct_) {
if (leaf_cert_sct.empty()) {
- DLOG(WARNING) << "SCT is expected but it is empty.";
+ QUIC_LOG_EVERY_N_SEC(WARNING, 60) << "SCT is expected but it is empty.";
} else {
message.SetStringPiece(kCertificateSCTTag, leaf_cert_sct);
}
@@ -1669,15 +1546,16 @@ void QuicCryptoServerConfig::BuildRejection(
QuicConnectionId server_designated_connection_id,
QuicRandom* rand,
QuicCompressedCertsCache* compressed_certs_cache,
- scoped_refptr<QuicCryptoNegotiatedParameters> params,
- const QuicCryptoProof& crypto_proof,
+ QuicReferenceCountedPointer<QuicCryptoNegotiatedParameters> params,
+ const QuicSignedServerConfig& signed_config,
QuicByteCount total_framing_overhead,
QuicByteCount chlo_packet_size,
CryptoHandshakeMessage* out) const {
- if (FLAGS_enable_quic_stateless_reject_support && use_stateless_rejects) {
- DVLOG(1) << "QUIC Crypto server config returning stateless reject "
- << "with server-designated connection ID "
- << server_designated_connection_id;
+ if (FLAGS_quic_reloadable_flag_enable_quic_stateless_reject_support &&
+ use_stateless_rejects) {
+ QUIC_DVLOG(1) << "QUIC Crypto server config returning stateless reject "
+ << "with server-designated connection ID "
+ << server_designated_connection_id;
out->set_tag(kSREJ);
out->SetValue(kRCID, server_designated_connection_id);
} else {
@@ -1714,7 +1592,7 @@ void QuicCryptoServerConfig::BuildRejection(
}
const string compressed =
- CompressChain(compressed_certs_cache, crypto_proof.chain,
+ CompressChain(compressed_certs_cache, signed_config.chain,
params->client_common_set_hashes,
params->client_cached_cert_hashes, config.common_cert_sets);
@@ -1737,31 +1615,32 @@ void QuicCryptoServerConfig::BuildRejection(
"overhead calculation may underflow");
bool should_return_sct =
params->sct_supported_by_client && enable_serving_sct_;
- const size_t sct_size = should_return_sct ? crypto_proof.cert_sct.size() : 0;
+ const string& cert_sct = signed_config.proof.leaf_cert_scts;
+ const size_t sct_size = should_return_sct ? cert_sct.size() : 0;
const size_t total_size =
- crypto_proof.signature.size() + compressed.size() + sct_size;
+ signed_config.proof.signature.size() + compressed.size() + sct_size;
if (info.valid_source_address_token || total_size < max_unverified_size) {
out->SetStringPiece(kCertificateTag, compressed);
- out->SetStringPiece(kPROF, crypto_proof.signature);
+ out->SetStringPiece(kPROF, signed_config.proof.signature);
if (should_return_sct) {
- if (crypto_proof.cert_sct.empty()) {
- DLOG(WARNING) << "SCT is expected but it is empty.";
+ if (cert_sct.empty()) {
+ QUIC_LOG_EVERY_N_SEC(WARNING, 60) << "SCT is expected but it is empty.";
} else {
- out->SetStringPiece(kCertificateSCTTag, crypto_proof.cert_sct);
+ out->SetStringPiece(kCertificateSCTTag, cert_sct);
}
}
} else {
- DLOG(WARNING) << "Sending inchoate REJ for hostname: " << info.sni
- << " signature: " << crypto_proof.signature.size()
- << " cert: " << compressed.size() << " sct:" << sct_size
- << " total: " << total_size
- << " max: " << max_unverified_size;
+ QUIC_LOG_EVERY_N_SEC(WARNING, 60)
+ << "Sending inchoate REJ for hostname: " << info.sni
+ << " signature: " << signed_config.proof.signature.size()
+ << " cert: " << compressed.size() << " sct:" << sct_size
+ << " total: " << total_size << " max: " << max_unverified_size;
}
}
string QuicCryptoServerConfig::CompressChain(
QuicCompressedCertsCache* compressed_certs_cache,
- const scoped_refptr<ProofSource::Chain>& chain,
+ const QuicReferenceCountedPointer<ProofSource::Chain>& chain,
const string& client_common_set_hashes,
const string& client_cached_cert_hashes,
const CommonCertSets* common_sets) {
@@ -1783,19 +1662,19 @@ string QuicCryptoServerConfig::CompressChain(
return compressed;
}
-scoped_refptr<QuicCryptoServerConfig::Config>
+QuicReferenceCountedPointer<QuicCryptoServerConfig::Config>
QuicCryptoServerConfig::ParseConfigProtobuf(
const std::unique_ptr<QuicServerConfigProtobuf>& protobuf) {
std::unique_ptr<CryptoHandshakeMessage> msg(
CryptoFramer::ParseMessage(protobuf->config()));
if (msg->tag() != kSCFG) {
- LOG(WARNING) << "Server config message has tag " << msg->tag()
- << " expected " << kSCFG;
+ QUIC_LOG(WARNING) << "Server config message has tag " << msg->tag()
+ << " expected " << kSCFG;
return nullptr;
}
- scoped_refptr<Config> config(new Config);
+ QuicReferenceCountedPointer<Config> config(new Config);
config->serialized = protobuf->config();
config->source_address_token_boxer = &source_address_token_boxer_;
@@ -1808,7 +1687,7 @@ QuicCryptoServerConfig::ParseConfigProtobuf(
StringPiece scid;
if (!msg->GetStringPiece(kSCID, &scid)) {
- LOG(WARNING) << "Server config message is missing SCID";
+ QUIC_LOG(WARNING) << "Server config message is missing SCID";
return nullptr;
}
config->id = scid.as_string();
@@ -1816,15 +1695,15 @@ QuicCryptoServerConfig::ParseConfigProtobuf(
const QuicTag* aead_tags;
size_t aead_len;
if (msg->GetTaglist(kAEAD, &aead_tags, &aead_len) != QUIC_NO_ERROR) {
- LOG(WARNING) << "Server config message is missing AEAD";
+ QUIC_LOG(WARNING) << "Server config message is missing AEAD";
return nullptr;
}
- config->aead = vector<QuicTag>(aead_tags, aead_tags + aead_len);
+ config->aead = std::vector<QuicTag>(aead_tags, aead_tags + aead_len);
const QuicTag* kexs_tags;
size_t kexs_len;
if (msg->GetTaglist(kKEXS, &kexs_tags, &kexs_len) != QUIC_NO_ERROR) {
- LOG(WARNING) << "Server config message is missing KEXS";
+ QUIC_LOG(WARNING) << "Server config message is missing KEXS";
return nullptr;
}
@@ -1834,47 +1713,30 @@ QuicCryptoServerConfig::ParseConfigProtobuf(
if ((err = msg->GetTaglist(kTBKP, &tbkp_tags, &tbkp_len)) !=
QUIC_CRYPTO_MESSAGE_PARAMETER_NOT_FOUND &&
err != QUIC_NO_ERROR) {
- LOG(WARNING) << "Server config message is missing or has invalid TBKP";
+ QUIC_LOG(WARNING) << "Server config message is missing or has invalid TBKP";
return nullptr;
}
- config->tb_key_params = vector<QuicTag>(tbkp_tags, tbkp_tags + tbkp_len);
+ config->tb_key_params = std::vector<QuicTag>(tbkp_tags, tbkp_tags + tbkp_len);
StringPiece orbit;
if (!msg->GetStringPiece(kORBT, &orbit)) {
- LOG(WARNING) << "Server config message is missing ORBT";
+ QUIC_LOG(WARNING) << "Server config message is missing ORBT";
return nullptr;
}
if (orbit.size() != kOrbitSize) {
- LOG(WARNING) << "Orbit value in server config is the wrong length."
- " Got "
- << orbit.size() << " want " << kOrbitSize;
+ QUIC_LOG(WARNING) << "Orbit value in server config is the wrong length."
+ " Got "
+ << orbit.size() << " want " << kOrbitSize;
return nullptr;
}
- static_assert(sizeof(config->orbit) == kOrbitSize,
- "orbit has incorrect size");
+ static_assert(sizeof(config->orbit) == kOrbitSize, "incorrect orbit size");
memcpy(config->orbit, orbit.data(), sizeof(config->orbit));
- {
- StrikeRegisterClient* strike_register_client;
- {
- base::AutoLock locked(strike_register_client_lock_);
- strike_register_client = strike_register_client_.get();
- }
-
- if (strike_register_client != nullptr &&
- !strike_register_client->IsKnownOrbit(orbit)) {
- LOG(WARNING)
- << "Rejecting server config with orbit that the strike register "
- "client doesn't know about.";
- return nullptr;
- }
- }
-
if (kexs_len != protobuf->key_size()) {
- LOG(WARNING) << "Server config has " << kexs_len
- << " key exchange methods configured, but "
- << protobuf->key_size() << " private keys";
+ QUIC_LOG(WARNING) << "Server config has " << kexs_len
+ << " key exchange methods configured, but "
+ << protobuf->key_size() << " private keys";
return nullptr;
}
@@ -1905,9 +1767,9 @@ QuicCryptoServerConfig::ParseConfigProtobuf(
}
if (private_key.empty()) {
- LOG(WARNING) << "Server config contains key exchange method without "
- "corresponding private key: "
- << tag;
+ QUIC_LOG(WARNING) << "Server config contains key exchange method without "
+ "corresponding private key: "
+ << tag;
return nullptr;
}
@@ -1916,29 +1778,30 @@ QuicCryptoServerConfig::ParseConfigProtobuf(
case kC255:
ka.reset(Curve25519KeyExchange::New(private_key));
if (!ka.get()) {
- LOG(WARNING) << "Server config contained an invalid curve25519"
- " private key.";
+ QUIC_LOG(WARNING) << "Server config contained an invalid curve25519"
+ " private key.";
return nullptr;
}
break;
case kP256:
ka.reset(P256KeyExchange::New(private_key));
if (!ka.get()) {
- LOG(WARNING) << "Server config contained an invalid P-256"
- " private key.";
+ QUIC_LOG(WARNING) << "Server config contained an invalid P-256"
+ " private key.";
return nullptr;
}
break;
default:
- LOG(WARNING) << "Server config message contains unknown key exchange "
- "method: "
- << tag;
+ QUIC_LOG(WARNING)
+ << "Server config message contains unknown key exchange "
+ "method: "
+ << tag;
return nullptr;
}
for (const auto& key_exchange : config->key_exchanges) {
if (key_exchange->tag() == tag) {
- LOG(WARNING) << "Duplicate key exchange in config: " << tag;
+ QUIC_LOG(WARNING) << "Duplicate key exchange in config: " << tag;
return nullptr;
}
}
@@ -1948,7 +1811,7 @@ QuicCryptoServerConfig::ParseConfigProtobuf(
uint64_t expiry_seconds;
if (msg->GetUint64(kEXPY, &expiry_seconds) != QUIC_NO_ERROR) {
- LOG(WARNING) << "Server config message is missing EXPY";
+ QUIC_LOG(WARNING) << "Server config message is missing EXPY";
return nullptr;
}
config->expiry_time = QuicWallTime::FromUNIXSeconds(expiry_seconds);
@@ -1961,13 +1824,6 @@ void QuicCryptoServerConfig::SetEphemeralKeySource(
ephemeral_key_source_.reset(ephemeral_key_source);
}
-void QuicCryptoServerConfig::SetStrikeRegisterClient(
- StrikeRegisterClient* strike_register_client) {
- base::AutoLock locker(strike_register_client_lock_);
- DCHECK(!strike_register_client_.get());
- strike_register_client_.reset(strike_register_client);
-}
-
void QuicCryptoServerConfig::set_replay_protection(bool on) {
replay_protection_ = on;
}
@@ -1976,26 +1832,6 @@ void QuicCryptoServerConfig::set_chlo_multiplier(size_t multiplier) {
chlo_multiplier_ = multiplier;
}
-void QuicCryptoServerConfig::set_strike_register_no_startup_period() {
- base::AutoLock locker(strike_register_client_lock_);
- DCHECK(!strike_register_client_.get());
- strike_register_no_startup_period_ = true;
-}
-
-void QuicCryptoServerConfig::set_strike_register_max_entries(
- uint32_t max_entries) {
- base::AutoLock locker(strike_register_client_lock_);
- DCHECK(!strike_register_client_.get());
- strike_register_max_entries_ = max_entries;
-}
-
-void QuicCryptoServerConfig::set_strike_register_window_secs(
- uint32_t window_secs) {
- base::AutoLock locker(strike_register_client_lock_);
- DCHECK(!strike_register_client_.get());
- strike_register_window_secs_ = window_secs;
-}
-
void QuicCryptoServerConfig::set_source_address_token_future_secs(
uint32_t future_secs) {
source_address_token_future_secs_ = future_secs;
@@ -2006,38 +1842,26 @@ void QuicCryptoServerConfig::set_source_address_token_lifetime_secs(
source_address_token_lifetime_secs_ = lifetime_secs;
}
-void QuicCryptoServerConfig::set_server_nonce_strike_register_max_entries(
- uint32_t max_entries) {
- DCHECK(!server_nonce_strike_register_.get());
- server_nonce_strike_register_max_entries_ = max_entries;
-}
-
-void QuicCryptoServerConfig::set_server_nonce_strike_register_window_secs(
- uint32_t window_secs) {
- DCHECK(!server_nonce_strike_register_.get());
- server_nonce_strike_register_window_secs_ = window_secs;
-}
-
void QuicCryptoServerConfig::set_enable_serving_sct(bool enable_serving_sct) {
enable_serving_sct_ = enable_serving_sct;
}
void QuicCryptoServerConfig::AcquirePrimaryConfigChangedCb(
std::unique_ptr<PrimaryConfigChangedCallback> cb) {
- base::AutoLock locked(configs_lock_);
+ QuicWriterMutexLock locked(&configs_lock_);
primary_config_changed_cb_ = std::move(cb);
}
string QuicCryptoServerConfig::NewSourceAddressToken(
const Config& config,
const SourceAddressTokens& previous_tokens,
- const IPAddress& ip,
+ const QuicIpAddress& ip,
QuicRandom* rand,
QuicWallTime now,
const CachedNetworkParameters* cached_network_params) const {
SourceAddressTokens source_address_tokens;
SourceAddressToken* source_address_token = source_address_tokens.add_tokens();
- source_address_token->set_ip(IPAddressToPackedString(DualstackIPAddress(ip)));
+ source_address_token->set_ip(ip.DualStacked().ToPackedString());
source_address_token->set_timestamp(now.ToUNIXSeconds());
if (cached_network_params != nullptr) {
*(source_address_token->mutable_cached_network_parameters()) =
@@ -2067,7 +1891,7 @@ string QuicCryptoServerConfig::NewSourceAddressToken(
}
int QuicCryptoServerConfig::NumberOfConfigs() const {
- base::AutoLock locked(configs_lock_);
+ QuicReaderMutexLock locked(&configs_lock_);
return configs_.size();
}
@@ -2085,12 +1909,11 @@ HandshakeFailureReason QuicCryptoServerConfig::ParseSourceAddressToken(
// Some clients might still be using the old source token format so
// attempt to parse that format.
// TODO(rch): remove this code once the new format is ubiquitous.
- SourceAddressToken source_address_token;
- if (!source_address_token.ParseFromArray(plaintext.data(),
- plaintext.size())) {
+ SourceAddressToken token;
+ if (!token.ParseFromArray(plaintext.data(), plaintext.size())) {
return SOURCE_ADDRESS_TOKEN_PARSE_FAILURE;
}
- *tokens->add_tokens() = source_address_token;
+ *tokens->add_tokens() = token;
}
return HANDSHAKE_OK;
@@ -2098,7 +1921,7 @@ HandshakeFailureReason QuicCryptoServerConfig::ParseSourceAddressToken(
HandshakeFailureReason QuicCryptoServerConfig::ValidateSourceAddressTokens(
const SourceAddressTokens& source_address_tokens,
- const IPAddress& ip,
+ const QuicIpAddress& ip,
QuicWallTime now,
CachedNetworkParameters* cached_network_params) const {
HandshakeFailureReason reason =
@@ -2117,10 +1940,9 @@ HandshakeFailureReason QuicCryptoServerConfig::ValidateSourceAddressTokens(
HandshakeFailureReason QuicCryptoServerConfig::ValidateSingleSourceAddressToken(
const SourceAddressToken& source_address_token,
- const IPAddress& ip,
+ const QuicIpAddress& ip,
QuicWallTime now) const {
- if (source_address_token.ip() !=
- IPAddressToPackedString(DualstackIPAddress(ip))) {
+ if (source_address_token.ip() != ip.DualStacked().ToPackedString()) {
// It's for a different IP address.
return SOURCE_ADDRESS_TOKEN_DIFFERENT_IP_ADDRESS_FAILURE;
}
@@ -2172,70 +1994,10 @@ string QuicCryptoServerConfig::NewServerNonce(QuicRandom* rand,
StringPiece(reinterpret_cast<char*>(server_nonce), sizeof(server_nonce)));
}
-HandshakeFailureReason QuicCryptoServerConfig::ValidateServerNonce(
- StringPiece token,
- QuicWallTime now) const {
- string storage;
- StringPiece plaintext;
- if (!server_nonce_boxer_.Unbox(token, &storage, &plaintext)) {
- return SERVER_NONCE_DECRYPTION_FAILURE;
- }
-
- // plaintext contains:
- // uint32_t timestamp
- // uint8_t[20] random bytes
-
- if (plaintext.size() != kServerNoncePlaintextSize) {
- // This should never happen because the value decrypted correctly.
- QUIC_BUG << "Seemingly valid server nonce had incorrect length.";
- return SERVER_NONCE_INVALID_FAILURE;
- }
-
- uint8_t server_nonce[32];
- memcpy(server_nonce, plaintext.data(), 4);
- memcpy(server_nonce + 4, server_nonce_orbit_, sizeof(server_nonce_orbit_));
- memcpy(server_nonce + 4 + sizeof(server_nonce_orbit_), plaintext.data() + 4,
- 20);
- static_assert(4 + sizeof(server_nonce_orbit_) + 20 == sizeof(server_nonce),
- "bad nonce buffer length");
-
- InsertStatus nonce_error;
- {
- base::AutoLock auto_lock(server_nonce_strike_register_lock_);
- if (server_nonce_strike_register_.get() == nullptr) {
- server_nonce_strike_register_.reset(new StrikeRegister(
- server_nonce_strike_register_max_entries_,
- static_cast<uint32_t>(now.ToUNIXSeconds()),
- server_nonce_strike_register_window_secs_, server_nonce_orbit_,
- StrikeRegister::NO_STARTUP_PERIOD_NEEDED));
- }
- nonce_error = server_nonce_strike_register_->Insert(
- server_nonce, static_cast<uint32_t>(now.ToUNIXSeconds()));
- }
-
- switch (nonce_error) {
- case NONCE_OK:
- return HANDSHAKE_OK;
- case NONCE_INVALID_FAILURE:
- case NONCE_INVALID_ORBIT_FAILURE:
- return SERVER_NONCE_INVALID_FAILURE;
- case NONCE_NOT_UNIQUE_FAILURE:
- return SERVER_NONCE_NOT_UNIQUE_FAILURE;
- case NONCE_INVALID_TIME_FAILURE:
- return SERVER_NONCE_INVALID_TIME_FAILURE;
- case NONCE_UNKNOWN_FAILURE:
- case STRIKE_REGISTER_TIMEOUT:
- case STRIKE_REGISTER_FAILURE:
- default:
- QUIC_BUG << "Unexpected server nonce error: " << nonce_error;
- return SERVER_NONCE_NOT_UNIQUE_FAILURE;
- }
-}
-
bool QuicCryptoServerConfig::ValidateExpectedLeafCertificate(
const CryptoHandshakeMessage& client_hello,
- const QuicCryptoProof& crypto_proof) const {
- if (crypto_proof.chain->certs.empty()) {
+ const std::vector<string>& certs) const {
+ if (certs.empty()) {
return false;
}
@@ -2243,8 +2005,7 @@ bool QuicCryptoServerConfig::ValidateExpectedLeafCertificate(
if (client_hello.GetUint64(kXLCT, &hash_from_client) != QUIC_NO_ERROR) {
return false;
}
- return CryptoUtils::ComputeLeafCertHash(crypto_proof.chain->certs.at(0)) ==
- hash_from_client;
+ return CryptoUtils::ComputeLeafCertHash(certs.at(0)) == hash_from_client;
}
bool QuicCryptoServerConfig::ClientDemandsX509Proof(
@@ -2274,10 +2035,9 @@ QuicCryptoServerConfig::Config::Config()
priority(0),
source_address_token_boxer(nullptr) {}
-QuicCryptoServerConfig::Config::~Config() {
-}
+QuicCryptoServerConfig::Config::~Config() {}
-QuicCryptoProof::QuicCryptoProof() {}
-QuicCryptoProof::~QuicCryptoProof() {}
+QuicSignedServerConfig::QuicSignedServerConfig() {}
+QuicSignedServerConfig::~QuicSignedServerConfig() {}
} // namespace net
diff --git a/chromium/net/quic/core/crypto/quic_crypto_server_config.h b/chromium/net/quic/core/crypto/quic_crypto_server_config.h
index afd4afe871f..42e9e2ed342 100644
--- a/chromium/net/quic/core/crypto/quic_crypto_server_config.h
+++ b/chromium/net/quic/core/crypto/quic_crypto_server_config.h
@@ -2,33 +2,32 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#ifndef NET_QUIC_CRYPTO_QUIC_CRYPTO_SERVER_CONFIG_H_
-#define NET_QUIC_CRYPTO_QUIC_CRYPTO_SERVER_CONFIG_H_
-
-#include <stddef.h>
-#include <stdint.h>
+#ifndef NET_QUIC_CORE_CRYPTO_QUIC_CRYPTO_SERVER_CONFIG_H_
+#define NET_QUIC_CORE_CRYPTO_QUIC_CRYPTO_SERVER_CONFIG_H_
+#include <cstddef>
+#include <cstdint>
#include <map>
#include <memory>
#include <string>
#include <vector>
#include "base/macros.h"
-#include "base/memory/ref_counted.h"
#include "base/strings/string_piece.h"
-#include "base/synchronization/lock.h"
-#include "net/base/ip_address.h"
-#include "net/base/ip_endpoint.h"
-#include "net/base/net_export.h"
#include "net/quic/core/crypto/crypto_handshake.h"
#include "net/quic/core/crypto/crypto_handshake_message.h"
#include "net/quic/core/crypto/crypto_protocol.h"
#include "net/quic/core/crypto/crypto_secret_boxer.h"
#include "net/quic/core/crypto/proof_source.h"
#include "net/quic/core/crypto/quic_compressed_certs_cache.h"
+#include "net/quic/core/crypto/quic_crypto_proof.h"
#include "net/quic/core/proto/cached_network_parameters.pb.h"
#include "net/quic/core/proto/source_address_token.pb.h"
#include "net/quic/core/quic_time.h"
+#include "net/quic/platform/api/quic_export.h"
+#include "net/quic/platform/api/quic_mutex.h"
+#include "net/quic/platform/api/quic_reference_counted.h"
+#include "net/quic/platform/api/quic_socket_address.h"
namespace net {
@@ -37,23 +36,19 @@ class EphemeralKeySource;
class KeyExchange;
class ProofSource;
class QuicClock;
-class QuicDecrypter;
-class QuicEncrypter;
class QuicRandom;
class QuicServerConfigProtobuf;
-class StrikeRegister;
-class StrikeRegisterClient;
-struct QuicCryptoProof;
+struct QuicSignedServerConfig;
// ClientHelloInfo contains information about a client hello message that is
// only kept for as long as it's being processed.
struct ClientHelloInfo {
- ClientHelloInfo(const IPAddress& in_client_ip, QuicWallTime in_now);
+ ClientHelloInfo(const QuicIpAddress& in_client_ip, QuicWallTime in_now);
ClientHelloInfo(const ClientHelloInfo& other);
~ClientHelloInfo();
// Inputs to EvaluateClientHello.
- const IPAddress client_ip;
+ const QuicIpAddress client_ip;
const QuicWallTime now;
// Outputs from EvaluateClientHello.
@@ -85,13 +80,13 @@ class PrimaryConfigChangedCallback {
};
// Callback used to accept the result of the |client_hello| validation step.
-class NET_EXPORT_PRIVATE ValidateClientHelloResultCallback {
+class QUIC_EXPORT_PRIVATE ValidateClientHelloResultCallback {
public:
// Opaque token that holds information about the client_hello and
// its validity. Can be interpreted by calling ProcessClientHello.
- struct NET_EXPORT_PRIVATE Result : public base::RefCountedThreadSafe<Result> {
+ struct QUIC_EXPORT_PRIVATE Result : public QuicReferenceCounted {
Result(const CryptoHandshakeMessage& in_client_hello,
- IPAddress in_client_ip,
+ QuicIpAddress in_client_ip,
QuicWallTime in_now);
CryptoHandshakeMessage client_hello;
@@ -102,22 +97,21 @@ class NET_EXPORT_PRIVATE ValidateClientHelloResultCallback {
// Populated if the CHLO STK contained a CachedNetworkParameters proto.
CachedNetworkParameters cached_network_params;
- private:
- friend class base::RefCountedThreadSafe<Result>;
- ~Result();
+ protected:
+ ~Result() override;
};
ValidateClientHelloResultCallback();
- virtual void Run(scoped_refptr<Result> result,
- std::unique_ptr<ProofSource::Details> details) = 0;
virtual ~ValidateClientHelloResultCallback();
+ virtual void Run(QuicReferenceCountedPointer<Result> result,
+ std::unique_ptr<ProofSource::Details> details) = 0;
private:
DISALLOW_COPY_AND_ASSIGN(ValidateClientHelloResultCallback);
};
// Callback used to accept the result of the ProcessClientHello method.
-class NET_EXPORT_PRIVATE ProcessClientHelloResultCallback {
+class QUIC_EXPORT_PRIVATE ProcessClientHelloResultCallback {
public:
ProcessClientHelloResultCallback();
virtual ~ProcessClientHelloResultCallback();
@@ -162,10 +156,10 @@ class RejectionObserver {
// order to support clients resuming with a previous configuration.
// TODO(agl): when adding configurations at runtime is added, this object will
// need to consider locking.
-class NET_EXPORT_PRIVATE QuicCryptoServerConfig {
+class QUIC_EXPORT_PRIVATE QuicCryptoServerConfig {
public:
// ConfigOptions contains options for generating server configs.
- struct NET_EXPORT_PRIVATE ConfigOptions {
+ struct QUIC_EXPORT_PRIVATE ConfigOptions {
ConfigOptions();
ConfigOptions(const ConfigOptions& other);
~ConfigOptions();
@@ -263,8 +257,8 @@ class NET_EXPORT_PRIVATE QuicCryptoServerConfig {
// client_hello: the incoming client hello message.
// client_ip: the IP address of the client, which is used to generate and
// validate source-address tokens.
- // server_ip: the IP address of the server. The IP address may be used for
- // certificate selection.
+ // server_address: the IP address and port of the server. The IP address and
+ // port may be used for certificate selection.
// version: protocol version used for this connection.
// clock: used to validate client nonces and ephemeral keys.
// crypto_proof: in/out parameter to which will be written the crypto proof
@@ -277,11 +271,11 @@ class NET_EXPORT_PRIVATE QuicCryptoServerConfig {
// completion of an asynchronous operation.
void ValidateClientHello(
const CryptoHandshakeMessage& client_hello,
- const IPAddress& client_ip,
- const IPAddress& server_ip,
+ const QuicIpAddress& client_ip,
+ const QuicSocketAddress& server_address,
QuicVersion version,
const QuicClock* clock,
- scoped_refptr<QuicCryptoProof> crypto_proof,
+ QuicReferenceCountedPointer<QuicSignedServerConfig> crypto_proof,
std::unique_ptr<ValidateClientHelloResultCallback> done_cb) const;
// ProcessClientHello processes |client_hello| and decides whether to accept
@@ -314,12 +308,12 @@ class NET_EXPORT_PRIVATE QuicCryptoServerConfig {
// chlo_packet_size: the size, in bytes, of the CHLO packet
// done_cb: the callback invoked on completion
void ProcessClientHello(
- scoped_refptr<ValidateClientHelloResultCallback::Result>
+ QuicReferenceCountedPointer<ValidateClientHelloResultCallback::Result>
validate_chlo_result,
bool reject_only,
QuicConnectionId connection_id,
- const IPAddress& server_ip,
- const IPEndPoint& client_address,
+ const QuicSocketAddress& server_address,
+ const QuicSocketAddress& client_address,
QuicVersion version,
const QuicVersionVector& supported_versions,
bool use_stateless_rejects,
@@ -327,8 +321,8 @@ class NET_EXPORT_PRIVATE QuicCryptoServerConfig {
const QuicClock* clock,
QuicRandom* rand,
QuicCompressedCertsCache* compressed_certs_cache,
- scoped_refptr<QuicCryptoNegotiatedParameters> params,
- scoped_refptr<QuicCryptoProof> crypto_proof,
+ QuicReferenceCountedPointer<QuicCryptoNegotiatedParameters> params,
+ QuicReferenceCountedPointer<QuicSignedServerConfig> crypto_proof,
QuicByteCount total_framing_overhead,
QuicByteCount chlo_packet_size,
std::unique_ptr<ProcessClientHelloResultCallback> done_cb) const;
@@ -340,13 +334,14 @@ class NET_EXPORT_PRIVATE QuicCryptoServerConfig {
//
// |cached_network_params| is optional, and can be nullptr.
//
- // TODO(gredner): remove this when --FLAGS_enable_async_get_proof is removed.
+ // TODO(gredner): remove this when
+ // FLAGS_quic_reloadable_flag_enable_async_get_proof is removed.
bool BuildServerConfigUpdateMessage(
QuicVersion version,
base::StringPiece chlo_hash,
const SourceAddressTokens& previous_source_address_tokens,
- const IPAddress& server_ip,
- const IPAddress& client_ip,
+ const QuicSocketAddress& server_address,
+ const QuicIpAddress& client_ip,
const QuicClock* clock,
QuicRandom* rand,
QuicCompressedCertsCache* compressed_certs_cache,
@@ -369,8 +364,8 @@ class NET_EXPORT_PRIVATE QuicCryptoServerConfig {
QuicVersion version,
base::StringPiece chlo_hash,
const SourceAddressTokens& previous_source_address_tokens,
- const IPAddress& server_ip,
- const IPAddress& client_ip,
+ const QuicSocketAddress& server_address,
+ const QuicIpAddress& client_ip,
const QuicClock* clock,
QuicRandom* rand,
QuicCompressedCertsCache* compressed_certs_cache,
@@ -385,11 +380,6 @@ class NET_EXPORT_PRIVATE QuicCryptoServerConfig {
// per-connection.
void SetEphemeralKeySource(EphemeralKeySource* ephemeral_key_source);
- // Install an externally created StrikeRegisterClient for use to
- // interact with the strike register. This object takes ownership
- // of the |strike_register_client|.
- void SetStrikeRegisterClient(StrikeRegisterClient* strike_register_client);
-
// set_replay_protection controls whether replay protection is enabled. If
// replay protection is disabled then no strike registers are needed and
// frontends can share an orbit value without a shared strike-register.
@@ -402,21 +392,6 @@ class NET_EXPORT_PRIVATE QuicCryptoServerConfig {
// valid source-address token.
void set_chlo_multiplier(size_t multiplier);
- // set_strike_register_no_startup_period configures the strike register to
- // not have a startup period.
- void set_strike_register_no_startup_period();
-
- // set_strike_register_max_entries sets the maximum number of entries that
- // the internal strike register will hold. If the strike register fills up
- // then the oldest entries (by the client's clock) will be dropped.
- void set_strike_register_max_entries(uint32_t max_entries);
-
- // set_strike_register_window_secs sets the number of seconds around the
- // current time that the strike register will attempt to be authoritative
- // for. Setting a larger value allows for greater client clock-skew, but
- // means that the quiescent startup period must be longer.
- void set_strike_register_window_secs(uint32_t window_secs);
-
// set_source_address_token_future_secs sets the number of seconds into the
// future that source-address tokens will be accepted from. Since
// source-address tokens are authenticated, this should only happen if
@@ -427,21 +402,6 @@ class NET_EXPORT_PRIVATE QuicCryptoServerConfig {
// source-address token will be valid for.
void set_source_address_token_lifetime_secs(uint32_t lifetime_secs);
- // set_server_nonce_strike_register_max_entries sets the number of entries in
- // the server-nonce strike-register. This is used to record that server nonce
- // values have been used. If the number of entries is too small then clients
- // which are depending on server nonces may fail to handshake because their
- // nonce has expired in the amount of time it took to go from the server to
- // the client and back.
- void set_server_nonce_strike_register_max_entries(uint32_t max_entries);
-
- // set_server_nonce_strike_register_window_secs sets the number of seconds
- // around the current time that the server-nonce strike-register will accept
- // nonces from. Setting a larger value allows for clients to delay follow-up
- // client hellos for longer and still use server nonces as proofs of
- // uniqueness.
- void set_server_nonce_strike_register_window_secs(uint32_t window_secs);
-
// set_enable_serving_sct enables or disables serving signed cert timestamp
// (RFC6962) in server hello.
void set_enable_serving_sct(bool enable_serving_sct);
@@ -461,12 +421,12 @@ class NET_EXPORT_PRIVATE QuicCryptoServerConfig {
private:
friend class test::QuicCryptoServerConfigPeer;
- friend struct QuicCryptoProof;
+ friend struct QuicSignedServerConfig;
// Config represents a server config: a collection of preferences and
// Diffie-Hellman public values.
- class NET_EXPORT_PRIVATE Config : public QuicCryptoConfig,
- public base::RefCounted<Config> {
+ class QUIC_EXPORT_PRIVATE Config : public QuicCryptoConfig,
+ public QuicReferenceCounted {
public:
Config();
@@ -522,23 +482,24 @@ class NET_EXPORT_PRIVATE QuicCryptoServerConfig {
std::unique_ptr<CryptoSecretBoxer> source_address_token_boxer_storage;
private:
- friend class base::RefCounted<Config>;
-
- virtual ~Config();
+ ~Config() override;
DISALLOW_COPY_AND_ASSIGN(Config);
};
- typedef std::map<ServerConfigID, scoped_refptr<Config>> ConfigMap;
+ typedef std::map<ServerConfigID, QuicReferenceCountedPointer<Config>>
+ ConfigMap;
// Get a ref to the config with a given server config id.
- scoped_refptr<Config> GetConfigWithScid(
- base::StringPiece requested_scid) const;
+ QuicReferenceCountedPointer<Config> GetConfigWithScid(
+ base::StringPiece requested_scid) const
+ SHARED_LOCKS_REQUIRED(configs_lock_);
// ConfigPrimaryTimeLessThan returns true if a->primary_time <
// b->primary_time.
- static bool ConfigPrimaryTimeLessThan(const scoped_refptr<Config>& a,
- const scoped_refptr<Config>& b);
+ static bool ConfigPrimaryTimeLessThan(
+ const QuicReferenceCountedPointer<Config>& a,
+ const QuicReferenceCountedPointer<Config>& b);
// SelectNewPrimaryConfig reevaluates the primary config based on the
// "primary_time" deadlines contained in each.
@@ -548,12 +509,12 @@ class NET_EXPORT_PRIVATE QuicCryptoServerConfig {
// whether it can be shown to be fresh (i.e. not a replay). The results are
// written to |info|.
void EvaluateClientHello(
- const IPAddress& server_ip,
+ const QuicSocketAddress& server_address,
QuicVersion version,
- scoped_refptr<Config> requested_config,
- scoped_refptr<Config> primary_config,
- scoped_refptr<QuicCryptoProof> crypto_proof,
- scoped_refptr<ValidateClientHelloResultCallback::Result>
+ QuicReferenceCountedPointer<Config> requested_config,
+ QuicReferenceCountedPointer<Config> primary_config,
+ QuicReferenceCountedPointer<QuicSignedServerConfig> crypto_proof,
+ QuicReferenceCountedPointer<ValidateClientHelloResultCallback::Result>
client_hello_state,
std::unique_ptr<ValidateClientHelloResultCallback> done_cb) const;
@@ -569,14 +530,14 @@ class NET_EXPORT_PRIVATE QuicCryptoServerConfig {
// set to false.
void EvaluateClientHelloAfterGetProof(
bool found_error,
- const IPAddress& server_ip,
+ const QuicIpAddress& server_ip,
QuicVersion version,
- scoped_refptr<Config> requested_config,
- scoped_refptr<Config> primary_config,
- scoped_refptr<QuicCryptoProof> crypto_proof,
+ QuicReferenceCountedPointer<Config> requested_config,
+ QuicReferenceCountedPointer<Config> primary_config,
+ QuicReferenceCountedPointer<QuicSignedServerConfig> crypto_proof,
std::unique_ptr<ProofSource::Details> proof_source_details,
bool get_proof_failed,
- scoped_refptr<ValidateClientHelloResultCallback::Result>
+ QuicReferenceCountedPointer<ValidateClientHelloResultCallback::Result>
client_hello_state,
std::unique_ptr<ValidateClientHelloResultCallback> done_cb) const;
@@ -592,7 +553,7 @@ class NET_EXPORT_PRIVATE QuicCryptoServerConfig {
const ValidateClientHelloResultCallback::Result& validate_chlo_result,
bool reject_only,
QuicConnectionId connection_id,
- const IPEndPoint& client_address,
+ const QuicSocketAddress& client_address,
QuicVersion version,
const QuicVersionVector& supported_versions,
bool use_stateless_rejects,
@@ -600,30 +561,31 @@ class NET_EXPORT_PRIVATE QuicCryptoServerConfig {
const QuicClock* clock,
QuicRandom* rand,
QuicCompressedCertsCache* compressed_certs_cache,
- scoped_refptr<QuicCryptoNegotiatedParameters> params,
- scoped_refptr<QuicCryptoProof> crypto_proof,
+ QuicReferenceCountedPointer<QuicCryptoNegotiatedParameters> params,
+ QuicReferenceCountedPointer<QuicSignedServerConfig> crypto_proof,
QuicByteCount total_framing_overhead,
QuicByteCount chlo_packet_size,
- const scoped_refptr<Config>& requested_config,
- const scoped_refptr<Config>& primary_config,
+ const QuicReferenceCountedPointer<Config>& requested_config,
+ const QuicReferenceCountedPointer<Config>& primary_config,
std::unique_ptr<ProcessClientHelloResultCallback> done_cb) const;
// BuildRejection sets |out| to be a REJ message in reply to |client_hello|.
- void BuildRejection(QuicVersion version,
- QuicWallTime now,
- const Config& config,
- const CryptoHandshakeMessage& client_hello,
- const ClientHelloInfo& info,
- const CachedNetworkParameters& cached_network_params,
- bool use_stateless_rejects,
- QuicConnectionId server_designated_connection_id,
- QuicRandom* rand,
- QuicCompressedCertsCache* compressed_certs_cache,
- scoped_refptr<QuicCryptoNegotiatedParameters> params,
- const QuicCryptoProof& crypto_proof,
- QuicByteCount total_framing_overhead,
- QuicByteCount chlo_packet_size,
- CryptoHandshakeMessage* out) const;
+ void BuildRejection(
+ QuicVersion version,
+ QuicWallTime now,
+ const Config& config,
+ const CryptoHandshakeMessage& client_hello,
+ const ClientHelloInfo& info,
+ const CachedNetworkParameters& cached_network_params,
+ bool use_stateless_rejects,
+ QuicConnectionId server_designated_connection_id,
+ QuicRandom* rand,
+ QuicCompressedCertsCache* compressed_certs_cache,
+ QuicReferenceCountedPointer<QuicCryptoNegotiatedParameters> params,
+ const QuicSignedServerConfig& crypto_proof,
+ QuicByteCount total_framing_overhead,
+ QuicByteCount chlo_packet_size,
+ CryptoHandshakeMessage* out) const;
// CompressChain compresses the certificates in |chain->certs| and returns a
// compressed representation. |common_sets| contains the common certificate
@@ -632,15 +594,15 @@ class NET_EXPORT_PRIVATE QuicCryptoServerConfig {
// 64-bit, FNV-1a hashes of certificates that the peer already possesses.
static std::string CompressChain(
QuicCompressedCertsCache* compressed_certs_cache,
- const scoped_refptr<ProofSource::Chain>& chain,
+ const QuicReferenceCountedPointer<ProofSource::Chain>& chain,
const std::string& client_common_set_hashes,
const std::string& client_cached_cert_hashes,
const CommonCertSets* common_sets);
// ParseConfigProtobuf parses the given config protobuf and returns a
- // scoped_refptr<Config> if successful. The caller adopts the reference to the
- // Config. On error, ParseConfigProtobuf returns nullptr.
- scoped_refptr<Config> ParseConfigProtobuf(
+ // QuicReferenceCountedPointer<Config> if successful. The caller adopts the
+ // reference to the Config. On error, ParseConfigProtobuf returns nullptr.
+ QuicReferenceCountedPointer<Config> ParseConfigProtobuf(
const std::unique_ptr<QuicServerConfigProtobuf>& protobuf);
// NewSourceAddressToken returns a fresh source address token for the given
@@ -648,7 +610,7 @@ class NET_EXPORT_PRIVATE QuicCryptoServerConfig {
std::string NewSourceAddressToken(
const Config& config,
const SourceAddressTokens& previous_tokens,
- const IPAddress& ip,
+ const QuicIpAddress& ip,
QuicRandom* rand,
QuicWallTime now,
const CachedNetworkParameters* cached_network_params) const;
@@ -669,7 +631,7 @@ class NET_EXPORT_PRIVATE QuicCryptoServerConfig {
// token contains a CachedNetworkParameters proto.
HandshakeFailureReason ValidateSourceAddressTokens(
const SourceAddressTokens& tokens,
- const IPAddress& ip,
+ const QuicIpAddress& ip,
QuicWallTime now,
CachedNetworkParameters* cached_network_params) const;
@@ -679,7 +641,7 @@ class NET_EXPORT_PRIVATE QuicCryptoServerConfig {
// for failure.
HandshakeFailureReason ValidateSingleSourceAddressToken(
const SourceAddressToken& token,
- const IPAddress& ip,
+ const QuicIpAddress& ip,
QuicWallTime now) const;
// Returns HANDSHAKE_OK if the source address token in |token| is a timely
@@ -692,24 +654,14 @@ class NET_EXPORT_PRIVATE QuicCryptoServerConfig {
// NewServerNonce generates and encrypts a random nonce.
std::string NewServerNonce(QuicRandom* rand, QuicWallTime now) const;
- // ValidateServerNonce decrypts |token| and verifies that it hasn't been
- // previously used and is recent enough that it is plausible that it was part
- // of a very recently provided rejection ("recent" will be on the order of
- // 10-30 seconds). If so, it records that it has been used and returns
- // HANDSHAKE_OK. Otherwise it returns the reason for failure.
- HandshakeFailureReason ValidateServerNonce(
- base::StringPiece echoed_server_nonce,
- QuicWallTime now) const;
-
// ValidateExpectedLeafCertificate checks the |client_hello| to see if it has
// an XLCT tag, and if so, verifies that its value matches the hash of the
- // server's leaf certificate. The certs field of |crypto_proof| is used to
- // compare against the XLCT value. This method returns true if the XLCT tag
- // is not present, or if the XLCT tag is present and valid. It returns false
- // otherwise.
+ // server's leaf certificate. |certs| is used to compare against the XLCT
+ // value. This method returns true if the XLCT tag is not present, or if the
+ // XLCT tag is present and valid. It returns false otherwise.
bool ValidateExpectedLeafCertificate(
const CryptoHandshakeMessage& client_hello,
- const QuicCryptoProof& crypto_proof) const;
+ const std::vector<std::string>& certs) const;
// Returns true if the PDMD field from the client hello demands an X509
// certificate.
@@ -737,9 +689,8 @@ class NET_EXPORT_PRIVATE QuicCryptoServerConfig {
std::unique_ptr<BuildServerConfigUpdateMessageResultCallback> cb);
void Run(bool ok,
- const scoped_refptr<ProofSource::Chain>& chain,
- const std::string& signature,
- const std::string& leaf_cert_sct,
+ const QuicReferenceCountedPointer<ProofSource::Chain>& chain,
+ const QuicCryptoProof& proof,
std::unique_ptr<ProofSource::Details> details) override;
private:
@@ -765,7 +716,7 @@ class NET_EXPORT_PRIVATE QuicCryptoServerConfig {
const std::string& client_cached_cert_hashes,
bool sct_supported_by_client,
bool ok,
- const scoped_refptr<ProofSource::Chain>& chain,
+ const QuicReferenceCountedPointer<ProofSource::Chain>& chain,
const std::string& signature,
const std::string& leaf_cert_sct,
std::unique_ptr<ProofSource::Details> details,
@@ -785,24 +736,20 @@ class NET_EXPORT_PRIVATE QuicCryptoServerConfig {
// 1) configs_.empty() <-> primary_config_ == nullptr
// 2) primary_config_ != nullptr -> primary_config_->is_primary
// 3) ∀ c∈configs_, c->is_primary <-> c == primary_config_
- mutable base::Lock configs_lock_;
+ mutable QuicMutex configs_lock_;
// configs_ contains all active server configs. It's expected that there are
// about half-a-dozen configs active at any one time.
- ConfigMap configs_;
+ ConfigMap configs_ GUARDED_BY(configs_lock_);
// primary_config_ points to a Config (which is also in |configs_|) which is
// the primary config - i.e. the one that we'll give out to new clients.
- mutable scoped_refptr<Config> primary_config_;
+ mutable QuicReferenceCountedPointer<Config> primary_config_
+ GUARDED_BY(configs_lock_);
// next_config_promotion_time_ contains the nearest, future time when an
// active config will be promoted to primary.
- mutable QuicWallTime next_config_promotion_time_;
+ mutable QuicWallTime next_config_promotion_time_ GUARDED_BY(configs_lock_);
// Callback to invoke when the primary config changes.
- std::unique_ptr<PrimaryConfigChangedCallback> primary_config_changed_cb_;
-
- // Protects access to the pointer held by strike_register_client_.
- mutable base::Lock strike_register_client_lock_;
- // strike_register_ contains a data structure that keeps track of previously
- // observed client nonces in order to prevent replay attacks.
- mutable std::unique_ptr<StrikeRegisterClient> strike_register_client_;
+ std::unique_ptr<PrimaryConfigChangedCallback> primary_config_changed_cb_
+ GUARDED_BY(configs_lock_);
// Used to protect the source-address tokens that are given to clients.
CryptoSecretBoxer source_address_token_boxer_;
@@ -816,12 +763,6 @@ class NET_EXPORT_PRIVATE QuicCryptoServerConfig {
// cookies).
uint8_t server_nonce_orbit_[8];
- mutable base::Lock server_nonce_strike_register_lock_;
- // server_nonce_strike_register_ contains a data structure that keeps track of
- // previously observed server nonces from this server, in order to prevent
- // replay attacks.
- mutable std::unique_ptr<StrikeRegister> server_nonce_strike_register_;
-
// proof_source_ contains an object that can provide certificate chains and
// signatures.
std::unique_ptr<ProofSource> proof_source_;
@@ -832,13 +773,8 @@ class NET_EXPORT_PRIVATE QuicCryptoServerConfig {
// These fields store configuration values. See the comments for their
// respective setter functions.
- bool strike_register_no_startup_period_;
- uint32_t strike_register_max_entries_;
- uint32_t strike_register_window_secs_;
uint32_t source_address_token_future_secs_;
uint32_t source_address_token_lifetime_secs_;
- uint32_t server_nonce_strike_register_max_entries_;
- uint32_t server_nonce_strike_register_window_secs_;
// Enable serving SCT or not.
bool enable_serving_sct_;
@@ -849,23 +785,21 @@ class NET_EXPORT_PRIVATE QuicCryptoServerConfig {
DISALLOW_COPY_AND_ASSIGN(QuicCryptoServerConfig);
};
-struct NET_EXPORT_PRIVATE QuicCryptoProof
- : public base::RefCounted<QuicCryptoProof> {
- QuicCryptoProof();
+struct QUIC_EXPORT_PRIVATE QuicSignedServerConfig
+ : public QuicReferenceCounted {
+ QuicSignedServerConfig();
- std::string signature;
- scoped_refptr<ProofSource::Chain> chain;
- std::string cert_sct;
+ QuicCryptoProof proof;
+ QuicReferenceCountedPointer<ProofSource::Chain> chain;
// The server config that is used for this proof (and the rest of the
// request).
- scoped_refptr<QuicCryptoServerConfig::Config> config;
+ QuicReferenceCountedPointer<QuicCryptoServerConfig::Config> config;
std::string primary_scid;
- private:
- friend class base::RefCounted<QuicCryptoProof>;
- virtual ~QuicCryptoProof();
+ protected:
+ ~QuicSignedServerConfig() override;
};
} // namespace net
-#endif // NET_QUIC_CRYPTO_QUIC_CRYPTO_SERVER_CONFIG_H_
+#endif // NET_QUIC_CORE_CRYPTO_QUIC_CRYPTO_SERVER_CONFIG_H_
diff --git a/chromium/net/quic/core/crypto/quic_crypto_server_config_test.cc b/chromium/net/quic/core/crypto/quic_crypto_server_config_test.cc
index 48763647761..da7f858c4c3 100644
--- a/chromium/net/quic/core/crypto/quic_crypto_server_config_test.cc
+++ b/chromium/net/quic/core/crypto/quic_crypto_server_config_test.cc
@@ -8,63 +8,25 @@
#include <memory>
-#include "net/quic/core/crypto/aes_128_gcm_12_encrypter.h"
#include "net/quic/core/crypto/cert_compressor.h"
#include "net/quic/core/crypto/chacha20_poly1305_encrypter.h"
#include "net/quic/core/crypto/crypto_handshake_message.h"
#include "net/quic/core/crypto/crypto_secret_boxer.h"
#include "net/quic/core/crypto/crypto_server_config_protobuf.h"
#include "net/quic/core/crypto/quic_random.h"
-#include "net/quic/core/crypto/strike_register_client.h"
-#include "net/quic/core/quic_flags.h"
#include "net/quic/core/quic_time.h"
+#include "net/quic/platform/api/quic_socket_address.h"
#include "net/quic/test_tools/crypto_test_utils.h"
#include "net/quic/test_tools/mock_clock.h"
#include "net/quic/test_tools/quic_crypto_server_config_peer.h"
-#include "net/quic/test_tools/quic_test_utils.h"
-#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
using base::StringPiece;
-using std::map;
-using std::pair;
using std::string;
-using std::vector;
namespace net {
namespace test {
-class TestStrikeRegisterClient : public StrikeRegisterClient {
- public:
- explicit TestStrikeRegisterClient(QuicCryptoServerConfig* config)
- : config_(config), is_known_orbit_called_(false) {}
-
- bool IsKnownOrbit(StringPiece orbit) const override {
- // Ensure that the strike register client lock is not held.
- QuicCryptoServerConfigPeer peer(config_);
- base::Lock* m = peer.GetStrikeRegisterClientLock();
- // In Chromium, we will dead lock if the lock is held by the current thread.
- // Chromium doesn't have AssertNotHeld API call.
- // m->AssertNotHeld();
- base::AutoLock lock(*m);
-
- is_known_orbit_called_ = true;
- return true;
- }
-
- void VerifyNonceIsValidAndUnique(StringPiece nonce,
- QuicWallTime now,
- ResultCallback* cb) override {
- LOG(FATAL) << "Not implemented";
- }
-
- bool is_known_orbit_called() { return is_known_orbit_called_; }
-
- private:
- QuicCryptoServerConfig* config_;
- mutable bool is_known_orbit_called_;
-};
-
TEST(QuicCryptoServerConfigTest, ServerConfig) {
QuicRandom* rand = QuicRandom::GetInstance();
QuicCryptoServerConfig server(QuicCryptoServerConfig::TESTING, rand,
@@ -79,27 +41,11 @@ TEST(QuicCryptoServerConfigTest, ServerConfig) {
const QuicTag* aead_tags;
size_t aead_len;
ASSERT_EQ(QUIC_NO_ERROR, message->GetTaglist(kAEAD, &aead_tags, &aead_len));
- vector<QuicTag> aead(aead_tags, aead_tags + aead_len);
+ std::vector<QuicTag> aead(aead_tags, aead_tags + aead_len);
EXPECT_THAT(aead, ::testing::Contains(kAESG));
EXPECT_LE(1u, aead.size());
}
-TEST(QuicCryptoServerConfigTest, GetOrbitIsCalledWithoutTheStrikeRegisterLock) {
- QuicRandom* rand = QuicRandom::GetInstance();
- QuicCryptoServerConfig server(QuicCryptoServerConfig::TESTING, rand,
- CryptoTestUtils::ProofSourceForTesting());
- MockClock clock;
-
- TestStrikeRegisterClient* strike_register =
- new TestStrikeRegisterClient(&server);
- server.SetStrikeRegisterClient(strike_register);
-
- QuicCryptoServerConfig::ConfigOptions options;
- std::unique_ptr<CryptoHandshakeMessage> message(
- server.AddDefaultConfig(rand, &clock, options));
- EXPECT_TRUE(strike_register->is_known_orbit_called());
-}
-
TEST(QuicCryptoServerConfigTest, CompressCerts) {
QuicCompressedCertsCache compressed_certs_cache(
QuicCompressedCertsCache::kQuicCompressedCertsCacheSize);
@@ -109,8 +55,9 @@ TEST(QuicCryptoServerConfigTest, CompressCerts) {
CryptoTestUtils::ProofSourceForTesting());
QuicCryptoServerConfigPeer peer(&server);
- vector<string> certs = {"testcert"};
- scoped_refptr<ProofSource::Chain> chain(new ProofSource::Chain(certs));
+ std::vector<string> certs = {"testcert"};
+ QuicReferenceCountedPointer<ProofSource::Chain> chain(
+ new ProofSource::Chain(certs));
string compressed = QuicCryptoServerConfigPeer::CompressChain(
&compressed_certs_cache, chain, "", "", nullptr);
@@ -128,8 +75,9 @@ TEST(QuicCryptoServerConfigTest, CompressSameCertsTwice) {
QuicCryptoServerConfigPeer peer(&server);
// Compress the certs for the first time.
- vector<string> certs = {"testcert"};
- scoped_refptr<ProofSource::Chain> chain(new ProofSource::Chain(certs));
+ std::vector<string> certs = {"testcert"};
+ QuicReferenceCountedPointer<ProofSource::Chain> chain(
+ new ProofSource::Chain(certs));
string common_certs = "";
string cached_certs = "";
@@ -155,8 +103,9 @@ TEST(QuicCryptoServerConfigTest, CompressDifferentCerts) {
CryptoTestUtils::ProofSourceForTesting());
QuicCryptoServerConfigPeer peer(&server);
- vector<string> certs = {"testcert"};
- scoped_refptr<ProofSource::Chain> chain(new ProofSource::Chain(certs));
+ std::vector<string> certs = {"testcert"};
+ QuicReferenceCountedPointer<ProofSource::Chain> chain(
+ new ProofSource::Chain(certs));
string common_certs = "";
string cached_certs = "";
@@ -165,7 +114,8 @@ TEST(QuicCryptoServerConfigTest, CompressDifferentCerts) {
EXPECT_EQ(compressed_certs_cache.Size(), 1u);
// Compress a similar certs which only differs in the chain.
- scoped_refptr<ProofSource::Chain> chain2(new ProofSource::Chain(certs));
+ QuicReferenceCountedPointer<ProofSource::Chain> chain2(
+ new ProofSource::Chain(certs));
string compressed2 = QuicCryptoServerConfigPeer::CompressChain(
&compressed_certs_cache, chain2, common_certs, cached_certs, nullptr);
@@ -186,9 +136,9 @@ TEST(QuicCryptoServerConfigTest, CompressDifferentCerts) {
class SourceAddressTokenTest : public ::testing::Test {
public:
SourceAddressTokenTest()
- : ip4_(Loopback4()),
- ip4_dual_(ConvertIPv4ToIPv4MappedIPv6(ip4_)),
- ip6_(Loopback6()),
+ : ip4_(QuicIpAddress::Loopback4()),
+ ip4_dual_(ip4_.DualStacked()),
+ ip6_(QuicIpAddress::Loopback6()),
original_time_(QuicWallTime::Zero()),
rand_(QuicRandom::GetInstance()),
server_(QuicCryptoServerConfig::TESTING,
@@ -203,19 +153,19 @@ class SourceAddressTokenTest : public ::testing::Test {
rand_, &clock_, QuicCryptoServerConfig::ConfigOptions()));
}
- string NewSourceAddressToken(string config_id, const IPAddress& ip) {
+ string NewSourceAddressToken(string config_id, const QuicIpAddress& ip) {
return NewSourceAddressToken(config_id, ip, nullptr);
}
string NewSourceAddressToken(string config_id,
- const IPAddress& ip,
+ const QuicIpAddress& ip,
const SourceAddressTokens& previous_tokens) {
return peer_.NewSourceAddressToken(config_id, previous_tokens, ip, rand_,
clock_.WallNow(), nullptr);
}
string NewSourceAddressToken(string config_id,
- const IPAddress& ip,
+ const QuicIpAddress& ip,
CachedNetworkParameters* cached_network_params) {
SourceAddressTokens previous_tokens;
return peer_.NewSourceAddressToken(config_id, previous_tokens, ip, rand_,
@@ -224,14 +174,14 @@ class SourceAddressTokenTest : public ::testing::Test {
HandshakeFailureReason ValidateSourceAddressTokens(string config_id,
StringPiece srct,
- const IPAddress& ip) {
+ const QuicIpAddress& ip) {
return ValidateSourceAddressTokens(config_id, srct, ip, nullptr);
}
HandshakeFailureReason ValidateSourceAddressTokens(
string config_id,
StringPiece srct,
- const IPAddress& ip,
+ const QuicIpAddress& ip,
CachedNetworkParameters* cached_network_params) {
return peer_.ValidateSourceAddressTokens(
config_id, srct, ip, clock_.WallNow(), cached_network_params);
@@ -240,9 +190,9 @@ class SourceAddressTokenTest : public ::testing::Test {
const string kPrimary = "<primary>";
const string kOverride = "Config with custom source address token key";
- IPAddress ip4_;
- IPAddress ip4_dual_;
- IPAddress ip6_;
+ QuicIpAddress ip4_;
+ QuicIpAddress ip4_dual_;
+ QuicIpAddress ip6_;
MockClock clock_;
QuicWallTime original_time_;
@@ -256,7 +206,7 @@ class SourceAddressTokenTest : public ::testing::Test {
// Test basic behavior of source address tokens including being specific
// to a single IP address and server config.
-TEST_F(SourceAddressTokenTest, NewSourceAddressToken) {
+TEST_F(SourceAddressTokenTest, SourceAddressToken) {
// Primary config generates configs that validate successfully.
const string token4 = NewSourceAddressToken(kPrimary, ip4_);
const string token4d = NewSourceAddressToken(kPrimary, ip4_dual_);
@@ -274,7 +224,7 @@ TEST_F(SourceAddressTokenTest, NewSourceAddressToken) {
ASSERT_EQ(HANDSHAKE_OK, ValidateSourceAddressTokens(kPrimary, token6, ip6_));
}
-TEST_F(SourceAddressTokenTest, NewSourceAddressTokenExpiration) {
+TEST_F(SourceAddressTokenTest, SourceAddressTokenExpiration) {
const string token = NewSourceAddressToken(kPrimary, ip4_);
// Validation fails if the token is from the future.
@@ -288,7 +238,7 @@ TEST_F(SourceAddressTokenTest, NewSourceAddressTokenExpiration) {
ValidateSourceAddressTokens(kPrimary, token, ip4_));
}
-TEST_F(SourceAddressTokenTest, NewSourceAddressTokenWithNetworkParams) {
+TEST_F(SourceAddressTokenTest, SourceAddressTokenWithNetworkParams) {
// Make sure that if the source address token contains CachedNetworkParameters
// that this gets written to ValidateSourceAddressToken output argument.
CachedNetworkParameters cached_network_params_input;
@@ -312,11 +262,7 @@ TEST_F(SourceAddressTokenTest, SourceAddressTokenMultipleAddresses) {
// Now create a token which is usable for both addresses.
SourceAddressToken previous_token;
- IPAddress ip_address = ip6_;
- if (ip6_.IsIPv4()) {
- ip_address = ConvertIPv4ToIPv4MappedIPv6(ip_address);
- }
- previous_token.set_ip(IPAddressToPackedString(ip_address));
+ previous_token.set_ip(ip6_.DualStacked().ToPackedString());
previous_token.set_timestamp(now.ToUNIXSeconds());
SourceAddressTokens previous_tokens;
(*previous_tokens.add_tokens()) = previous_token;
@@ -329,36 +275,6 @@ TEST_F(SourceAddressTokenTest, SourceAddressTokenMultipleAddresses) {
ValidateSourceAddressTokens(kPrimary, token4or6, ip6_));
}
-TEST(QuicCryptoServerConfigTest, ValidateServerNonce) {
- QuicRandom* rand = QuicRandom::GetInstance();
- QuicCryptoServerConfig server(QuicCryptoServerConfig::TESTING, rand,
- CryptoTestUtils::ProofSourceForTesting());
- QuicCryptoServerConfigPeer peer(&server);
-
- StringPiece message("hello world");
- const size_t key_size = CryptoSecretBoxer::GetKeySize();
- std::unique_ptr<uint8_t[]> key(new uint8_t[key_size]);
- memset(key.get(), 0x11, key_size);
-
- CryptoSecretBoxer boxer;
- boxer.SetKeys({string(reinterpret_cast<char*>(key.get()), key_size)});
- const string box = boxer.Box(rand, message);
- MockClock clock;
- QuicWallTime now = clock.WallNow();
- const QuicWallTime original_time = now;
- EXPECT_EQ(SERVER_NONCE_DECRYPTION_FAILURE,
- peer.ValidateServerNonce(box, now));
-
- string server_nonce = peer.NewServerNonce(rand, now);
- EXPECT_EQ(HANDSHAKE_OK, peer.ValidateServerNonce(server_nonce, now));
- EXPECT_EQ(SERVER_NONCE_NOT_UNIQUE_FAILURE,
- peer.ValidateServerNonce(server_nonce, now));
-
- now = original_time.Add(QuicTime::Delta::FromSeconds(1000 * 7));
- server_nonce = peer.NewServerNonce(rand, now);
- EXPECT_EQ(HANDSHAKE_OK, peer.ValidateServerNonce(server_nonce, now));
-}
-
class CryptoServerConfigsTest : public ::testing::Test {
public:
CryptoServerConfigsTest()
@@ -398,7 +314,7 @@ class CryptoServerConfigsTest : public ::testing::Test {
bool has_invalid = false;
bool is_empty = true;
- vector<std::unique_ptr<QuicServerConfigProtobuf>> protobufs;
+ std::vector<std::unique_ptr<QuicServerConfigProtobuf>> protobufs;
bool first = true;
for (;;) {
const char* server_config_id;
diff --git a/chromium/net/quic/core/crypto/quic_decrypter.cc b/chromium/net/quic/core/crypto/quic_decrypter.cc
index 5d8f3d32945..f7719144bcf 100644
--- a/chromium/net/quic/core/crypto/quic_decrypter.cc
+++ b/chromium/net/quic/core/crypto/quic_decrypter.cc
@@ -9,6 +9,7 @@
#include "net/quic/core/crypto/chacha20_poly1305_decrypter.h"
#include "net/quic/core/crypto/crypto_protocol.h"
#include "net/quic/core/crypto/null_decrypter.h"
+#include "net/quic/platform/api/quic_logging.h"
using base::StringPiece;
using std::string;
@@ -22,10 +23,8 @@ QuicDecrypter* QuicDecrypter::Create(QuicTag algorithm) {
return new Aes128Gcm12Decrypter();
case kCC20:
return new ChaCha20Poly1305Decrypter();
- case kNULL:
- return new NullDecrypter();
default:
- LOG(FATAL) << "Unsupported algorithm: " << algorithm;
+ QUIC_LOG(FATAL) << "Unsupported algorithm: " << algorithm;
return nullptr;
}
}
diff --git a/chromium/net/quic/core/crypto/quic_decrypter.h b/chromium/net/quic/core/crypto/quic_decrypter.h
index 0a5eea3d388..824cf929f3e 100644
--- a/chromium/net/quic/core/crypto/quic_decrypter.h
+++ b/chromium/net/quic/core/crypto/quic_decrypter.h
@@ -2,18 +2,18 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#ifndef NET_QUIC_CRYPTO_QUIC_DECRYPTER_H_
-#define NET_QUIC_CRYPTO_QUIC_DECRYPTER_H_
+#ifndef NET_QUIC_CORE_CRYPTO_QUIC_DECRYPTER_H_
+#define NET_QUIC_CORE_CRYPTO_QUIC_DECRYPTER_H_
-#include <stddef.h>
-#include <stdint.h>
+#include <cstddef>
+#include <cstdint>
-#include "net/base/net_export.h"
-#include "net/quic/core/quic_protocol.h"
+#include "net/quic/core/quic_packets.h"
+#include "net/quic/platform/api/quic_export.h"
namespace net {
-class NET_EXPORT_PRIVATE QuicDecrypter {
+class QUIC_EXPORT_PRIVATE QuicDecrypter {
public:
virtual ~QuicDecrypter() {}
@@ -66,7 +66,8 @@ class NET_EXPORT_PRIVATE QuicDecrypter {
// to form the nonce.
// TODO(wtc): add a way for DecryptPacket to report decryption failure due
// to non-authentic inputs, as opposed to other reasons for failure.
- virtual bool DecryptPacket(QuicPathId path_id,
+ virtual bool DecryptPacket(QuicVersion version,
+ QuicPathId path_id,
QuicPacketNumber packet_number,
base::StringPiece associated_data,
base::StringPiece ciphertext,
@@ -95,4 +96,4 @@ class NET_EXPORT_PRIVATE QuicDecrypter {
} // namespace net
-#endif // NET_QUIC_CRYPTO_QUIC_DECRYPTER_H_
+#endif // NET_QUIC_CORE_CRYPTO_QUIC_DECRYPTER_H_
diff --git a/chromium/net/quic/core/crypto/quic_encrypter.cc b/chromium/net/quic/core/crypto/quic_encrypter.cc
index 2c19078d2a9..377720b9db9 100644
--- a/chromium/net/quic/core/crypto/quic_encrypter.cc
+++ b/chromium/net/quic/core/crypto/quic_encrypter.cc
@@ -8,6 +8,7 @@
#include "net/quic/core/crypto/chacha20_poly1305_encrypter.h"
#include "net/quic/core/crypto/crypto_protocol.h"
#include "net/quic/core/crypto/null_encrypter.h"
+#include "net/quic/platform/api/quic_logging.h"
namespace net {
@@ -18,10 +19,8 @@ QuicEncrypter* QuicEncrypter::Create(QuicTag algorithm) {
return new Aes128Gcm12Encrypter();
case kCC20:
return new ChaCha20Poly1305Encrypter();
- case kNULL:
- return new NullEncrypter();
default:
- LOG(FATAL) << "Unsupported algorithm: " << algorithm;
+ QUIC_LOG(FATAL) << "Unsupported algorithm: " << algorithm;
return nullptr;
}
}
diff --git a/chromium/net/quic/core/crypto/quic_encrypter.h b/chromium/net/quic/core/crypto/quic_encrypter.h
index fefd7773edb..67398672495 100644
--- a/chromium/net/quic/core/crypto/quic_encrypter.h
+++ b/chromium/net/quic/core/crypto/quic_encrypter.h
@@ -2,17 +2,17 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#ifndef NET_QUIC_CRYPTO_QUIC_ENCRYPTER_H_
-#define NET_QUIC_CRYPTO_QUIC_ENCRYPTER_H_
+#ifndef NET_QUIC_CORE_CRYPTO_QUIC_ENCRYPTER_H_
+#define NET_QUIC_CORE_CRYPTO_QUIC_ENCRYPTER_H_
-#include <stddef.h>
+#include <cstddef>
-#include "net/base/net_export.h"
-#include "net/quic/core/quic_protocol.h"
+#include "net/quic/core/quic_packets.h"
+#include "net/quic/platform/api/quic_export.h"
namespace net {
-class NET_EXPORT_PRIVATE QuicEncrypter {
+class QUIC_EXPORT_PRIVATE QuicEncrypter {
public:
virtual ~QuicEncrypter() {}
@@ -48,7 +48,8 @@ class NET_EXPORT_PRIVATE QuicEncrypter {
// SetNoncePrefix() to form the nonce. |output| must not overlap with
// |associated_data|. If |output| overlaps with |plaintext| then
// |plaintext| must be <= |output|.
- virtual bool EncryptPacket(QuicPathId path_id,
+ virtual bool EncryptPacket(QuicVersion version,
+ QuicPathId path_id,
QuicPacketNumber packet_number,
base::StringPiece associated_data,
base::StringPiece plaintext,
@@ -82,4 +83,4 @@ class NET_EXPORT_PRIVATE QuicEncrypter {
} // namespace net
-#endif // NET_QUIC_CRYPTO_QUIC_ENCRYPTER_H_
+#endif // NET_QUIC_CORE_CRYPTO_QUIC_ENCRYPTER_H_
diff --git a/chromium/net/quic/core/crypto/quic_random.cc b/chromium/net/quic/core/crypto/quic_random.cc
index 35d1bdd326c..ac54517bff1 100644
--- a/chromium/net/quic/core/crypto/quic_random.cc
+++ b/chromium/net/quic/core/crypto/quic_random.cc
@@ -4,11 +4,10 @@
#include "net/quic/core/crypto/quic_random.h"
-#include "base/logging.h"
#include "base/macros.h"
#include "base/memory/singleton.h"
#include "crypto/random.h"
-#include "net/quic/core/quic_bug_tracker.h"
+#include "net/quic/platform/api/quic_bug_tracker.h"
namespace net {
diff --git a/chromium/net/quic/core/crypto/quic_random.h b/chromium/net/quic/core/crypto/quic_random.h
index e723241bd4f..65a632e8575 100644
--- a/chromium/net/quic/core/crypto/quic_random.h
+++ b/chromium/net/quic/core/crypto/quic_random.h
@@ -2,18 +2,18 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#ifndef NET_QUIC_CRYPTO_QUIC_RANDOM_H_
-#define NET_QUIC_CRYPTO_QUIC_RANDOM_H_
+#ifndef NET_QUIC_CORE_CRYPTO_QUIC_RANDOM_H_
+#define NET_QUIC_CORE_CRYPTO_QUIC_RANDOM_H_
-#include <stddef.h>
-#include <stdint.h>
+#include <cstddef>
+#include <cstdint>
-#include "net/base/net_export.h"
+#include "net/quic/platform/api/quic_export.h"
namespace net {
// The interface for a random number generator.
-class NET_EXPORT_PRIVATE QuicRandom {
+class QUIC_EXPORT_PRIVATE QuicRandom {
public:
virtual ~QuicRandom() {}
@@ -35,4 +35,4 @@ class NET_EXPORT_PRIVATE QuicRandom {
} // namespace net
-#endif // NET_QUIC_CRYPTO_QUIC_RANDOM_H_
+#endif // NET_QUIC_CORE_CRYPTO_QUIC_RANDOM_H_
diff --git a/chromium/net/quic/core/crypto/scoped_evp_aead_ctx.h b/chromium/net/quic/core/crypto/scoped_evp_aead_ctx.h
index afb5861414c..0716ea98c7f 100644
--- a/chromium/net/quic/core/crypto/scoped_evp_aead_ctx.h
+++ b/chromium/net/quic/core/crypto/scoped_evp_aead_ctx.h
@@ -2,8 +2,8 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#ifndef NET_QUIC_CRYPTO_SCOPED_EVP_AEAD_CTX_H_
-#define NET_QUIC_CRYPTO_SCOPED_EVP_AEAD_CTX_H_
+#ifndef NET_QUIC_CORE_CRYPTO_SCOPED_EVP_AEAD_CTX_H_
+#define NET_QUIC_CORE_CRYPTO_SCOPED_EVP_AEAD_CTX_H_
#include "base/macros.h"
#include "third_party/boringssl/src/include/openssl/evp.h"
@@ -27,4 +27,4 @@ class ScopedEVPAEADCtx {
} // namespace net
-#endif // NET_QUIC_CRYPTO_SCOPED_EVP_AEAD_CTX_H_
+#endif // NET_QUIC_CORE_CRYPTO_SCOPED_EVP_AEAD_CTX_H_
diff --git a/chromium/net/quic/core/crypto/strike_register.cc b/chromium/net/quic/core/crypto/strike_register.cc
index a673346db16..b5c4e937a17 100644
--- a/chromium/net/quic/core/crypto/strike_register.cc
+++ b/chromium/net/quic/core/crypto/strike_register.cc
@@ -7,7 +7,7 @@
#include <algorithm>
#include <limits>
-#include "base/logging.h"
+#include "net/quic/platform/api/quic_logging.h"
namespace net {
diff --git a/chromium/net/quic/core/crypto/strike_register.h b/chromium/net/quic/core/crypto/strike_register.h
index 9d7431bfd05..d12ebc27c3f 100644
--- a/chromium/net/quic/core/crypto/strike_register.h
+++ b/chromium/net/quic/core/crypto/strike_register.h
@@ -2,18 +2,17 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#ifndef NET_QUIC_CRYPTO_STRIKE_REGISTER_H_
-#define NET_QUIC_CRYPTO_STRIKE_REGISTER_H_
-
-#include <stdint.h>
+#ifndef NET_QUIC_CORE_CRYPTO_STRIKE_REGISTER_H_
+#define NET_QUIC_CORE_CRYPTO_STRIKE_REGISTER_H_
+#include <cstdint>
#include <memory>
#include <set>
#include <utility>
#include <vector>
#include "base/macros.h"
-#include "net/base/net_export.h"
+#include "net/quic/platform/api/quic_export.h"
namespace net {
@@ -71,7 +70,7 @@ enum InsertStatus {
// before the creation time given to the constructor. (See
// |ExternalTimeToInternal|) This avoids having to worry about overflow since
// we assume that no process will run for 130 years.
-class NET_EXPORT_PRIVATE StrikeRegister {
+class QUIC_EXPORT_PRIVATE StrikeRegister {
public:
enum StartupType {
// DENY_REQUESTS_AT_STARTUP is the typical mode for a strike register.
@@ -220,4 +219,4 @@ class NET_EXPORT_PRIVATE StrikeRegister {
} // namespace net
-#endif // NET_QUIC_CRYPTO_STRIKE_REGISTER_H_
+#endif // NET_QUIC_CORE_CRYPTO_STRIKE_REGISTER_H_
diff --git a/chromium/net/quic/core/crypto/strike_register_client.h b/chromium/net/quic/core/crypto/strike_register_client.h
index 2126d6fc4be..c8cc409b53f 100644
--- a/chromium/net/quic/core/crypto/strike_register_client.h
+++ b/chromium/net/quic/core/crypto/strike_register_client.h
@@ -2,26 +2,26 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#ifndef NET_QUIC_CRYPTO_STRIKE_REGISTER_CLIENT_H_
-#define NET_QUIC_CRYPTO_STRIKE_REGISTER_CLIENT_H_
+#ifndef NET_QUIC_CORE_CRYPTO_STRIKE_REGISTER_CLIENT_H_
+#define NET_QUIC_CORE_CRYPTO_STRIKE_REGISTER_CLIENT_H_
#include <string>
#include "base/macros.h"
#include "base/strings/string_piece.h"
-#include "net/base/net_export.h"
#include "net/quic/core/crypto/strike_register.h"
#include "net/quic/core/quic_time.h"
+#include "net/quic/platform/api/quic_export.h"
namespace net {
// Interface implemented by clients that talk to strike registers
// implemented as local or remote services.
-class NET_EXPORT_PRIVATE StrikeRegisterClient {
+class QUIC_EXPORT_PRIVATE StrikeRegisterClient {
public:
// Single use callback that will be invoked once the validation
// operation is complete.
- class NET_EXPORT_PRIVATE ResultCallback {
+ class QUIC_EXPORT_PRIVATE ResultCallback {
public:
ResultCallback() {}
virtual ~ResultCallback() {}
@@ -57,4 +57,4 @@ class NET_EXPORT_PRIVATE StrikeRegisterClient {
} // namespace net
-#endif // NET_QUIC_CRYPTO_STRIKE_REGISTER_CLIENT_H_
+#endif // NET_QUIC_CORE_CRYPTO_STRIKE_REGISTER_CLIENT_H_
diff --git a/chromium/net/quic/core/crypto/strike_register_test.cc b/chromium/net/quic/core/crypto/strike_register_test.cc
index 07d1f2085ef..b056a9e0de7 100644
--- a/chromium/net/quic/core/crypto/strike_register_test.cc
+++ b/chromium/net/quic/core/crypto/strike_register_test.cc
@@ -16,9 +16,6 @@ namespace net {
namespace {
-using std::min;
-using std::pair;
-using std::set;
using std::string;
const uint8_t kOrbit[8] = {1, 2, 3, 4, 5, 6, 7, 8};
@@ -250,7 +247,7 @@ class SlowStrikeRegister {
if (horizon_ > current_time) {
return 0;
}
- return 1 + min(current_time - horizon_, window_secs_);
+ return 1 + std::min(current_time - horizon_, window_secs_);
}
private:
diff --git a/chromium/net/quic/core/frames/quic_ack_frame.cc b/chromium/net/quic/core/frames/quic_ack_frame.cc
new file mode 100644
index 00000000000..0f7464a9e26
--- /dev/null
+++ b/chromium/net/quic/core/frames/quic_ack_frame.cc
@@ -0,0 +1,161 @@
+// Copyright (c) 2016 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.
+
+#include "net/quic/core/frames/quic_ack_frame.h"
+
+#include "net/quic/core/quic_constants.h"
+
+namespace net {
+
+bool IsAwaitingPacket(const QuicAckFrame& ack_frame,
+ QuicPacketNumber packet_number,
+ QuicPacketNumber peer_least_packet_awaiting_ack) {
+ return packet_number >= peer_least_packet_awaiting_ack &&
+ !ack_frame.packets.Contains(packet_number);
+}
+
+QuicAckFrame::QuicAckFrame()
+ : largest_observed(0),
+ ack_delay_time(QuicTime::Delta::Infinite()),
+ path_id(kDefaultPathId) {}
+
+QuicAckFrame::QuicAckFrame(const QuicAckFrame& other) = default;
+
+QuicAckFrame::~QuicAckFrame() {}
+
+std::ostream& operator<<(std::ostream& os, const QuicAckFrame& ack_frame) {
+ os << "{ largest_observed: " << ack_frame.largest_observed
+ << ", ack_delay_time: " << ack_frame.ack_delay_time.ToMicroseconds()
+ << ", packets: [ " << ack_frame.packets << " ]"
+ << ", received_packets: [ ";
+ for (const std::pair<QuicPacketNumber, QuicTime>& p :
+ ack_frame.received_packet_times) {
+ os << p.first << " at " << p.second.ToDebuggingValue() << " ";
+ }
+ os << " ] }\n";
+ return os;
+}
+
+PacketNumberQueue::PacketNumberQueue() = default;
+PacketNumberQueue::PacketNumberQueue(const PacketNumberQueue& other) = default;
+PacketNumberQueue::PacketNumberQueue(PacketNumberQueue&& other) = default;
+PacketNumberQueue::~PacketNumberQueue() {}
+
+PacketNumberQueue& PacketNumberQueue::operator=(
+ const PacketNumberQueue& other) = default;
+PacketNumberQueue& PacketNumberQueue::operator=(PacketNumberQueue&& other) =
+ default;
+
+void PacketNumberQueue::Add(QuicPacketNumber packet_number) {
+ packet_number_intervals_.Add(packet_number, packet_number + 1);
+}
+
+void PacketNumberQueue::Add(QuicPacketNumber lower, QuicPacketNumber higher) {
+ packet_number_intervals_.Add(lower, higher);
+}
+
+void PacketNumberQueue::Remove(QuicPacketNumber packet_number) {
+ packet_number_intervals_.Difference(packet_number, packet_number + 1);
+}
+
+void PacketNumberQueue::Remove(QuicPacketNumber lower,
+ QuicPacketNumber higher) {
+ packet_number_intervals_.Difference(lower, higher);
+}
+
+bool PacketNumberQueue::RemoveUpTo(QuicPacketNumber higher) {
+ if (Empty()) {
+ return false;
+ }
+ const QuicPacketNumber old_min = Min();
+ packet_number_intervals_.Difference(0, higher);
+ return Empty() || old_min != Min();
+}
+
+void PacketNumberQueue::Complement() {
+ if (Empty()) {
+ return;
+ }
+ packet_number_intervals_.Complement(Min(), Max() + 1);
+}
+
+bool PacketNumberQueue::Contains(QuicPacketNumber packet_number) const {
+ return packet_number_intervals_.Contains(packet_number);
+}
+
+bool PacketNumberQueue::Empty() const {
+ return packet_number_intervals_.Empty();
+}
+
+QuicPacketNumber PacketNumberQueue::Min() const {
+ DCHECK(!Empty());
+ return packet_number_intervals_.begin()->min();
+}
+
+QuicPacketNumber PacketNumberQueue::Max() const {
+ DCHECK(!Empty());
+ return packet_number_intervals_.rbegin()->max() - 1;
+}
+
+size_t PacketNumberQueue::NumPacketsSlow() const {
+ size_t num_packets = 0;
+ for (const auto& interval : packet_number_intervals_) {
+ num_packets += interval.Length();
+ }
+ return num_packets;
+}
+
+size_t PacketNumberQueue::NumIntervals() const {
+ return packet_number_intervals_.Size();
+}
+
+QuicPacketNumber PacketNumberQueue::LastIntervalLength() const {
+ DCHECK(!Empty());
+ return packet_number_intervals_.rbegin()->Length();
+}
+
+PacketNumberQueue::const_iterator PacketNumberQueue::lower_bound(
+ QuicPacketNumber packet_number) const {
+ // lower_bound returns the first interval that contains |packet_number| or the
+ // first interval after |packet_number|.
+ auto itr = packet_number_intervals_.Find(packet_number);
+ if (itr != packet_number_intervals_.end()) {
+ return itr;
+ }
+ for (itr = packet_number_intervals_.begin();
+ itr != packet_number_intervals_.end(); ++itr) {
+ if (packet_number < itr->min()) {
+ return itr;
+ }
+ }
+ return packet_number_intervals_.end();
+}
+
+PacketNumberQueue::const_iterator PacketNumberQueue::begin() const {
+ return packet_number_intervals_.begin();
+}
+
+PacketNumberQueue::const_iterator PacketNumberQueue::end() const {
+ return packet_number_intervals_.end();
+}
+
+PacketNumberQueue::const_reverse_iterator PacketNumberQueue::rbegin() const {
+ return packet_number_intervals_.rbegin();
+}
+
+PacketNumberQueue::const_reverse_iterator PacketNumberQueue::rend() const {
+ return packet_number_intervals_.rend();
+}
+
+std::ostream& operator<<(std::ostream& os, const PacketNumberQueue& q) {
+ for (const Interval<QuicPacketNumber>& interval : q) {
+ for (QuicPacketNumber packet_number = interval.min();
+ packet_number < interval.max(); ++packet_number) {
+ os << packet_number << " ";
+ }
+ }
+ return os;
+}
+
+} // namespace net
diff --git a/chromium/net/quic/core/frames/quic_ack_frame.h b/chromium/net/quic/core/frames/quic_ack_frame.h
new file mode 100644
index 00000000000..9e76aee8dc7
--- /dev/null
+++ b/chromium/net/quic/core/frames/quic_ack_frame.h
@@ -0,0 +1,133 @@
+// Copyright (c) 2016 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.
+
+#ifndef NET_QUIC_CORE_FRAMES_QUIC_ACK_FRAME_H_
+#define NET_QUIC_CORE_FRAMES_QUIC_ACK_FRAME_H_
+
+#include <ostream>
+#include <string>
+
+#include "base/strings/string_piece.h"
+#include "net/quic/core/interval_set.h"
+#include "net/quic/core/quic_types.h"
+#include "net/quic/platform/api/quic_export.h"
+
+namespace net {
+
+// A sequence of packet numbers where each number is unique. Intended to be used
+// in a sliding window fashion, where smaller old packet numbers are removed and
+// larger new packet numbers are added, with the occasional random access.
+class QUIC_EXPORT_PRIVATE PacketNumberQueue {
+ public:
+ using const_iterator = IntervalSet<QuicPacketNumber>::const_iterator;
+ using const_reverse_iterator =
+ IntervalSet<QuicPacketNumber>::const_reverse_iterator;
+
+ PacketNumberQueue();
+ PacketNumberQueue(const PacketNumberQueue& other);
+ PacketNumberQueue(PacketNumberQueue&& other);
+ ~PacketNumberQueue();
+
+ PacketNumberQueue& operator=(const PacketNumberQueue& other);
+ PacketNumberQueue& operator=(PacketNumberQueue&& other);
+
+ // Adds |packet_number| to the set of packets in the queue.
+ void Add(QuicPacketNumber packet_number);
+
+ // Adds packets between [lower, higher) to the set of packets in the queue. It
+ // is undefined behavior to call this with |higher| < |lower|.
+ void Add(QuicPacketNumber lower, QuicPacketNumber higher);
+
+ // Removes |packet_number| from the set of packets in the queue.
+ void Remove(QuicPacketNumber packet_number);
+
+ // Removes packets numbers between [lower, higher) to the set of packets in
+ // the queue. It is undefined behavior to call this with |higher| < |lower|.
+ void Remove(QuicPacketNumber lower, QuicPacketNumber higher);
+
+ // Removes packets with values less than |higher| from the set of packets in
+ // the queue. Returns true if packets were removed.
+ bool RemoveUpTo(QuicPacketNumber higher);
+
+ // Mutates packet number set so that it contains only those packet numbers
+ // from minimum to maximum packet number not currently in the set. Do nothing
+ // if packet number set is empty.
+ void Complement();
+
+ // Returns true if the queue contains |packet_number|.
+ bool Contains(QuicPacketNumber packet_number) const;
+
+ // Returns true if the queue is empty.
+ bool Empty() const;
+
+ // Returns the minimum packet number stored in the queue. It is undefined
+ // behavior to call this if the queue is empty.
+ QuicPacketNumber Min() const;
+
+ // Returns the maximum packet number stored in the queue. It is undefined
+ // behavior to call this if the queue is empty.
+ QuicPacketNumber Max() const;
+
+ // Returns the number of unique packets stored in the queue. Inefficient; only
+ // exposed for testing.
+ size_t NumPacketsSlow() const;
+
+ // Returns the number of disjoint packet number intervals contained in the
+ // queue.
+ size_t NumIntervals() const;
+
+ // Returns the length of last interval.
+ QuicPacketNumber LastIntervalLength() const;
+
+ // Returns iterators over the packet number intervals.
+ const_iterator begin() const;
+ const_iterator end() const;
+ const_reverse_iterator rbegin() const;
+ const_reverse_iterator rend() const;
+ const_iterator lower_bound(QuicPacketNumber packet_number) const;
+
+ friend QUIC_EXPORT_PRIVATE std::ostream& operator<<(
+ std::ostream& os,
+ const PacketNumberQueue& q);
+
+ private:
+ IntervalSet<QuicPacketNumber> packet_number_intervals_;
+};
+
+struct QUIC_EXPORT_PRIVATE QuicAckFrame {
+ QuicAckFrame();
+ QuicAckFrame(const QuicAckFrame& other);
+ ~QuicAckFrame();
+
+ friend QUIC_EXPORT_PRIVATE std::ostream& operator<<(std::ostream& os,
+ const QuicAckFrame& s);
+
+ // The highest packet number we've observed from the peer.
+ QuicPacketNumber largest_observed;
+
+ // Time elapsed since largest_observed was received until this Ack frame was
+ // sent.
+ QuicTime::Delta ack_delay_time;
+
+ // Vector of <packet_number, time> for when packets arrived.
+ PacketTimeVector received_packet_times;
+
+ // Set of packets.
+ PacketNumberQueue packets;
+
+ // Path which this ack belongs to.
+ QuicPathId path_id;
+};
+
+// True if the packet number is greater than largest_observed or is listed
+// as missing.
+// Always returns false for packet numbers less than least_unacked.
+QUIC_EXPORT_PRIVATE bool IsAwaitingPacket(
+ const QuicAckFrame& ack_frame,
+ QuicPacketNumber packet_number,
+ QuicPacketNumber peer_least_packet_awaiting_ack);
+
+} // namespace net
+
+#endif // NET_QUIC_CORE_FRAMES_QUIC_ACK_FRAME_H_
diff --git a/chromium/net/quic/core/frames/quic_blocked_frame.cc b/chromium/net/quic/core/frames/quic_blocked_frame.cc
new file mode 100644
index 00000000000..3a1046c928b
--- /dev/null
+++ b/chromium/net/quic/core/frames/quic_blocked_frame.cc
@@ -0,0 +1,18 @@
+// Copyright (c) 2016 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.
+
+#include "net/quic/core/frames/quic_blocked_frame.h"
+
+namespace net {
+
+QuicBlockedFrame::QuicBlockedFrame(QuicStreamId stream_id)
+ : stream_id(stream_id) {}
+
+std::ostream& operator<<(std::ostream& os,
+ const QuicBlockedFrame& blocked_frame) {
+ os << "{ stream_id: " << blocked_frame.stream_id << " }\n";
+ return os;
+}
+
+} // namespace net
diff --git a/chromium/net/quic/core/frames/quic_blocked_frame.h b/chromium/net/quic/core/frames/quic_blocked_frame.h
new file mode 100644
index 00000000000..9409d7adf47
--- /dev/null
+++ b/chromium/net/quic/core/frames/quic_blocked_frame.h
@@ -0,0 +1,34 @@
+// Copyright (c) 2016 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.
+
+#ifndef NET_QUIC_CORE_FRAMES_QUIC_BLOCKED_FRAME_H_
+#define NET_QUIC_CORE_FRAMES_QUIC_BLOCKED_FRAME_H_
+
+#include <ostream>
+
+#include "net/quic/core/quic_types.h"
+#include "net/quic/platform/api/quic_export.h"
+
+namespace net {
+
+// The BLOCKED frame is used to indicate to the remote endpoint that this
+// endpoint believes itself to be flow-control blocked but otherwise ready to
+// send data. The BLOCKED frame is purely advisory and optional.
+// Based on SPDY's BLOCKED frame (undocumented as of 2014-01-28).
+struct QUIC_EXPORT_PRIVATE QuicBlockedFrame {
+ QuicBlockedFrame() {}
+ explicit QuicBlockedFrame(QuicStreamId stream_id);
+
+ friend QUIC_EXPORT_PRIVATE std::ostream& operator<<(
+ std::ostream& os,
+ const QuicBlockedFrame& b);
+
+ // The stream this frame applies to. 0 is a special case meaning the overall
+ // connection rather than a specific stream.
+ QuicStreamId stream_id;
+};
+
+} // namespace net
+
+#endif // NET_QUIC_CORE_FRAMES_QUIC_BLOCKED_FRAME_H_
diff --git a/chromium/net/quic/core/frames/quic_connection_close_frame.cc b/chromium/net/quic/core/frames/quic_connection_close_frame.cc
new file mode 100644
index 00000000000..4aef61dbc15
--- /dev/null
+++ b/chromium/net/quic/core/frames/quic_connection_close_frame.cc
@@ -0,0 +1,20 @@
+// Copyright (c) 2016 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.
+
+#include "net/quic/core/frames/quic_connection_close_frame.h"
+
+namespace net {
+
+QuicConnectionCloseFrame::QuicConnectionCloseFrame()
+ : error_code(QUIC_NO_ERROR) {}
+
+std::ostream& operator<<(
+ std::ostream& os,
+ const QuicConnectionCloseFrame& connection_close_frame) {
+ os << "{ error_code: " << connection_close_frame.error_code
+ << ", error_details: '" << connection_close_frame.error_details << "' }\n";
+ return os;
+}
+
+} // namespace net
diff --git a/chromium/net/quic/core/frames/quic_connection_close_frame.h b/chromium/net/quic/core/frames/quic_connection_close_frame.h
new file mode 100644
index 00000000000..59db52d9822
--- /dev/null
+++ b/chromium/net/quic/core/frames/quic_connection_close_frame.h
@@ -0,0 +1,29 @@
+// Copyright (c) 2016 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.
+
+#ifndef NET_QUIC_CORE_FRAMES_QUIC_CONNECTION_CLOSE_FRAME_H_
+#define NET_QUIC_CORE_FRAMES_QUIC_CONNECTION_CLOSE_FRAME_H_
+
+#include <ostream>
+#include <string>
+
+#include "net/quic/core/quic_error_codes.h"
+#include "net/quic/platform/api/quic_export.h"
+
+namespace net {
+
+struct QUIC_EXPORT_PRIVATE QuicConnectionCloseFrame {
+ QuicConnectionCloseFrame();
+
+ friend QUIC_EXPORT_PRIVATE std::ostream& operator<<(
+ std::ostream& os,
+ const QuicConnectionCloseFrame& c);
+
+ QuicErrorCode error_code;
+ std::string error_details;
+};
+
+} // namespace net
+
+#endif // NET_QUIC_CORE_FRAMES_QUIC_CONNECTION_CLOSE_FRAME_H_
diff --git a/chromium/net/quic/core/frames/quic_frame.cc b/chromium/net/quic/core/frames/quic_frame.cc
new file mode 100644
index 00000000000..840bb6ecb4a
--- /dev/null
+++ b/chromium/net/quic/core/frames/quic_frame.cc
@@ -0,0 +1,163 @@
+// Copyright (c) 2016 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.
+
+#include "net/quic/core/frames/quic_frame.h"
+#include "net/quic/platform/api/quic_logging.h"
+
+using base::StringPiece;
+using std::string;
+
+namespace net {
+
+QuicFrame::QuicFrame() {}
+
+QuicFrame::QuicFrame(QuicPaddingFrame padding_frame)
+ : type(PADDING_FRAME), padding_frame(padding_frame) {}
+
+QuicFrame::QuicFrame(QuicStreamFrame* stream_frame)
+ : type(STREAM_FRAME), stream_frame(stream_frame) {}
+
+QuicFrame::QuicFrame(QuicAckFrame* frame) : type(ACK_FRAME), ack_frame(frame) {}
+
+QuicFrame::QuicFrame(QuicMtuDiscoveryFrame frame)
+ : type(MTU_DISCOVERY_FRAME), mtu_discovery_frame(frame) {}
+
+QuicFrame::QuicFrame(QuicStopWaitingFrame* frame)
+ : type(STOP_WAITING_FRAME), stop_waiting_frame(frame) {}
+
+QuicFrame::QuicFrame(QuicPingFrame frame)
+ : type(PING_FRAME), ping_frame(frame) {}
+
+QuicFrame::QuicFrame(QuicRstStreamFrame* frame)
+ : type(RST_STREAM_FRAME), rst_stream_frame(frame) {}
+
+QuicFrame::QuicFrame(QuicConnectionCloseFrame* frame)
+ : type(CONNECTION_CLOSE_FRAME), connection_close_frame(frame) {}
+
+QuicFrame::QuicFrame(QuicGoAwayFrame* frame)
+ : type(GOAWAY_FRAME), goaway_frame(frame) {}
+
+QuicFrame::QuicFrame(QuicWindowUpdateFrame* frame)
+ : type(WINDOW_UPDATE_FRAME), window_update_frame(frame) {}
+
+QuicFrame::QuicFrame(QuicBlockedFrame* frame)
+ : type(BLOCKED_FRAME), blocked_frame(frame) {}
+
+QuicFrame::QuicFrame(QuicPathCloseFrame* frame)
+ : type(PATH_CLOSE_FRAME), path_close_frame(frame) {}
+
+void DeleteFrames(QuicFrames* frames) {
+ for (QuicFrame& frame : *frames) {
+ switch (frame.type) {
+ // Frames smaller than a pointer are inlined, so don't need to be deleted.
+ case PADDING_FRAME:
+ case MTU_DISCOVERY_FRAME:
+ case PING_FRAME:
+ break;
+ case STREAM_FRAME:
+ delete frame.stream_frame;
+ break;
+ case ACK_FRAME:
+ delete frame.ack_frame;
+ break;
+ case STOP_WAITING_FRAME:
+ delete frame.stop_waiting_frame;
+ break;
+ case RST_STREAM_FRAME:
+ delete frame.rst_stream_frame;
+ break;
+ case CONNECTION_CLOSE_FRAME:
+ delete frame.connection_close_frame;
+ break;
+ case GOAWAY_FRAME:
+ delete frame.goaway_frame;
+ break;
+ case BLOCKED_FRAME:
+ delete frame.blocked_frame;
+ break;
+ case WINDOW_UPDATE_FRAME:
+ delete frame.window_update_frame;
+ break;
+ case PATH_CLOSE_FRAME:
+ delete frame.path_close_frame;
+ break;
+ case NUM_FRAME_TYPES:
+ DCHECK(false) << "Cannot delete type: " << frame.type;
+ }
+ }
+ frames->clear();
+}
+
+void RemoveFramesForStream(QuicFrames* frames, QuicStreamId stream_id) {
+ QuicFrames::iterator it = frames->begin();
+ while (it != frames->end()) {
+ if (it->type != STREAM_FRAME || it->stream_frame->stream_id != stream_id) {
+ ++it;
+ continue;
+ }
+ delete it->stream_frame;
+ it = frames->erase(it);
+ }
+}
+
+std::ostream& operator<<(std::ostream& os, const QuicFrame& frame) {
+ switch (frame.type) {
+ case PADDING_FRAME: {
+ os << "type { PADDING_FRAME } " << frame.padding_frame;
+ break;
+ }
+ case RST_STREAM_FRAME: {
+ os << "type { RST_STREAM_FRAME } " << *(frame.rst_stream_frame);
+ break;
+ }
+ case CONNECTION_CLOSE_FRAME: {
+ os << "type { CONNECTION_CLOSE_FRAME } "
+ << *(frame.connection_close_frame);
+ break;
+ }
+ case GOAWAY_FRAME: {
+ os << "type { GOAWAY_FRAME } " << *(frame.goaway_frame);
+ break;
+ }
+ case WINDOW_UPDATE_FRAME: {
+ os << "type { WINDOW_UPDATE_FRAME } " << *(frame.window_update_frame);
+ break;
+ }
+ case BLOCKED_FRAME: {
+ os << "type { BLOCKED_FRAME } " << *(frame.blocked_frame);
+ break;
+ }
+ case STREAM_FRAME: {
+ os << "type { STREAM_FRAME } " << *(frame.stream_frame);
+ break;
+ }
+ case ACK_FRAME: {
+ os << "type { ACK_FRAME } " << *(frame.ack_frame);
+ break;
+ }
+ case STOP_WAITING_FRAME: {
+ os << "type { STOP_WAITING_FRAME } " << *(frame.stop_waiting_frame);
+ break;
+ }
+ case PING_FRAME: {
+ os << "type { PING_FRAME } ";
+ break;
+ }
+ case MTU_DISCOVERY_FRAME: {
+ os << "type { MTU_DISCOVERY_FRAME } ";
+ break;
+ }
+ case PATH_CLOSE_FRAME: {
+ os << "type { PATH_CLOSE_FRAME } " << *(frame.path_close_frame);
+ break;
+ }
+ default: {
+ QUIC_LOG(ERROR) << "Unknown frame type: " << frame.type;
+ break;
+ }
+ }
+ return os;
+}
+
+} // namespace net
diff --git a/chromium/net/quic/core/frames/quic_frame.h b/chromium/net/quic/core/frames/quic_frame.h
new file mode 100644
index 00000000000..3ebe1cfc3de
--- /dev/null
+++ b/chromium/net/quic/core/frames/quic_frame.h
@@ -0,0 +1,82 @@
+// Copyright (c) 2016 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.
+
+#ifndef NET_QUIC_CORE_FRAMES_QUIC_FRAME_H_
+#define NET_QUIC_CORE_FRAMES_QUIC_FRAME_H_
+
+#include <ostream>
+#include <vector>
+
+#include "net/quic/core/frames/quic_ack_frame.h"
+#include "net/quic/core/frames/quic_blocked_frame.h"
+#include "net/quic/core/frames/quic_connection_close_frame.h"
+#include "net/quic/core/frames/quic_frame.h"
+#include "net/quic/core/frames/quic_goaway_frame.h"
+#include "net/quic/core/frames/quic_mtu_discovery_frame.h"
+#include "net/quic/core/frames/quic_padding_frame.h"
+#include "net/quic/core/frames/quic_path_close_frame.h"
+#include "net/quic/core/frames/quic_ping_frame.h"
+#include "net/quic/core/frames/quic_rst_stream_frame.h"
+#include "net/quic/core/frames/quic_stop_waiting_frame.h"
+#include "net/quic/core/frames/quic_stream_frame.h"
+#include "net/quic/core/frames/quic_window_update_frame.h"
+#include "net/quic/core/quic_types.h"
+#include "net/quic/platform/api/quic_export.h"
+
+namespace net {
+
+struct QUIC_EXPORT_PRIVATE QuicFrame {
+ QuicFrame();
+ explicit QuicFrame(QuicPaddingFrame padding_frame);
+ explicit QuicFrame(QuicMtuDiscoveryFrame frame);
+ explicit QuicFrame(QuicPingFrame frame);
+
+ explicit QuicFrame(QuicStreamFrame* stream_frame);
+ explicit QuicFrame(QuicAckFrame* frame);
+ explicit QuicFrame(QuicRstStreamFrame* frame);
+ explicit QuicFrame(QuicConnectionCloseFrame* frame);
+ explicit QuicFrame(QuicStopWaitingFrame* frame);
+ explicit QuicFrame(QuicGoAwayFrame* frame);
+ explicit QuicFrame(QuicWindowUpdateFrame* frame);
+ explicit QuicFrame(QuicBlockedFrame* frame);
+ explicit QuicFrame(QuicPathCloseFrame* frame);
+
+ QUIC_EXPORT_PRIVATE friend std::ostream& operator<<(std::ostream& os,
+ const QuicFrame& frame);
+
+ QuicFrameType type;
+ union {
+ // Frames smaller than a pointer are inline.
+ QuicPaddingFrame padding_frame;
+ QuicMtuDiscoveryFrame mtu_discovery_frame;
+ QuicPingFrame ping_frame;
+
+ // Frames larger than a pointer.
+ QuicStreamFrame* stream_frame;
+ QuicAckFrame* ack_frame;
+ QuicStopWaitingFrame* stop_waiting_frame;
+ QuicRstStreamFrame* rst_stream_frame;
+ QuicConnectionCloseFrame* connection_close_frame;
+ QuicGoAwayFrame* goaway_frame;
+ QuicWindowUpdateFrame* window_update_frame;
+ QuicBlockedFrame* blocked_frame;
+ QuicPathCloseFrame* path_close_frame;
+ };
+};
+// QuicFrameType consumes 8 bytes with padding.
+static_assert(sizeof(QuicFrame) <= 16,
+ "Frames larger than 8 bytes should be referenced by pointer.");
+
+typedef std::vector<QuicFrame> QuicFrames;
+
+// Deletes all the sub-frames contained in |frames|.
+QUIC_EXPORT_PRIVATE void DeleteFrames(QuicFrames* frames);
+
+// Deletes all the QuicStreamFrames for the specified |stream_id|.
+QUIC_EXPORT_PRIVATE void RemoveFramesForStream(QuicFrames* frames,
+ QuicStreamId stream_id);
+
+} // namespace net
+
+#endif // NET_QUIC_CORE_FRAMES_QUIC_FRAME_H_
diff --git a/chromium/net/quic/core/frames/quic_frames_test.cc b/chromium/net/quic/core/frames/quic_frames_test.cc
new file mode 100644
index 00000000000..11f083ec16d
--- /dev/null
+++ b/chromium/net/quic/core/frames/quic_frames_test.cc
@@ -0,0 +1,285 @@
+// Copyright (c) 2016 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.
+
+#include "net/quic/core/frames/quic_ack_frame.h"
+#include "net/quic/core/frames/quic_blocked_frame.h"
+#include "net/quic/core/frames/quic_connection_close_frame.h"
+#include "net/quic/core/frames/quic_frame.h"
+#include "net/quic/core/frames/quic_goaway_frame.h"
+#include "net/quic/core/frames/quic_mtu_discovery_frame.h"
+#include "net/quic/core/frames/quic_padding_frame.h"
+#include "net/quic/core/frames/quic_path_close_frame.h"
+#include "net/quic/core/frames/quic_ping_frame.h"
+#include "net/quic/core/frames/quic_rst_stream_frame.h"
+#include "net/quic/core/frames/quic_stop_waiting_frame.h"
+#include "net/quic/core/frames/quic_stream_frame.h"
+#include "net/quic/core/frames/quic_window_update_frame.h"
+#include "testing/gmock/include/gmock/gmock.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace net {
+namespace test {
+namespace {
+
+using testing::_;
+
+TEST(QuicFramesTest, AckFrameToString) {
+ QuicAckFrame frame;
+ frame.largest_observed = 2;
+ frame.ack_delay_time = QuicTime::Delta::FromMicroseconds(3);
+ frame.packets.Add(4);
+ frame.packets.Add(5);
+ frame.received_packet_times = {
+ {6, QuicTime::Zero() + QuicTime::Delta::FromMicroseconds(7)}};
+ std::ostringstream stream;
+ stream << frame;
+ EXPECT_EQ(
+ "{ largest_observed: 2, ack_delay_time: 3, "
+ "packets: [ 4 5 ], received_packets: [ 6 at 7 ] }\n",
+ stream.str());
+}
+
+TEST(QuicFramesTest, PaddingFrameToString) {
+ QuicPaddingFrame frame;
+ frame.num_padding_bytes = 1;
+ std::ostringstream stream;
+ stream << frame;
+ EXPECT_EQ("{ num_padding_bytes: 1 }\n", stream.str());
+}
+
+TEST(QuicFramesTest, RstStreamFrameToString) {
+ QuicRstStreamFrame frame;
+ frame.stream_id = 1;
+ frame.error_code = QUIC_STREAM_CANCELLED;
+ std::ostringstream stream;
+ stream << frame;
+ EXPECT_EQ("{ stream_id: 1, error_code: 6 }\n", stream.str());
+}
+
+TEST(QuicFramesTest, ConnectionCloseFrameToString) {
+ QuicConnectionCloseFrame frame;
+ frame.error_code = QUIC_NETWORK_IDLE_TIMEOUT;
+ frame.error_details = "No recent network activity.";
+ std::ostringstream stream;
+ stream << frame;
+ EXPECT_EQ(
+ "{ error_code: 25, error_details: 'No recent network activity.' }\n",
+ stream.str());
+}
+
+TEST(QuicFramesTest, GoAwayFrameToString) {
+ QuicGoAwayFrame frame;
+ frame.error_code = QUIC_NETWORK_IDLE_TIMEOUT;
+ frame.last_good_stream_id = 2;
+ frame.reason_phrase = "Reason";
+ std::ostringstream stream;
+ stream << frame;
+ EXPECT_EQ(
+ "{ error_code: 25, last_good_stream_id: 2, reason_phrase: 'Reason' }\n",
+ stream.str());
+}
+
+TEST(QuicFramesTest, WindowUpdateFrameToString) {
+ QuicWindowUpdateFrame frame;
+ std::ostringstream stream;
+ frame.stream_id = 1;
+ frame.byte_offset = 2;
+ stream << frame;
+ EXPECT_EQ("{ stream_id: 1, byte_offset: 2 }\n", stream.str());
+}
+
+TEST(QuicFramesTest, BlockedFrameToString) {
+ QuicBlockedFrame frame;
+ frame.stream_id = 1;
+ std::ostringstream stream;
+ stream << frame;
+ EXPECT_EQ("{ stream_id: 1 }\n", stream.str());
+}
+
+TEST(QuicFramesTest, StreamFrameToString) {
+ QuicStreamFrame frame;
+ frame.stream_id = 1;
+ frame.fin = false;
+ frame.offset = 2;
+ frame.data_length = 3;
+ std::ostringstream stream;
+ stream << frame;
+ EXPECT_EQ("{ stream_id: 1, fin: 0, offset: 2, length: 3 }\n", stream.str());
+}
+
+TEST(QuicFramesTest, StopWaitingFrameToString) {
+ QuicStopWaitingFrame frame;
+ frame.least_unacked = 2;
+ std::ostringstream stream;
+ stream << frame;
+ EXPECT_EQ("{ least_unacked: 2 }\n", stream.str());
+}
+
+TEST(QuicFramesTest, PathCloseFrameToString) {
+ QuicPathCloseFrame frame;
+ frame.path_id = 1;
+ std::ostringstream stream;
+ stream << frame;
+ EXPECT_EQ("{ path_id: 1 }\n", stream.str());
+}
+
+TEST(QuicFramesTest, IsAwaitingPacket) {
+ QuicAckFrame ack_frame1;
+ ack_frame1.largest_observed = 10u;
+ ack_frame1.packets.Add(1, 11);
+ EXPECT_TRUE(IsAwaitingPacket(ack_frame1, 11u, 0u));
+ EXPECT_FALSE(IsAwaitingPacket(ack_frame1, 1u, 0u));
+
+ ack_frame1.packets.Remove(10);
+ EXPECT_TRUE(IsAwaitingPacket(ack_frame1, 10u, 0u));
+
+ QuicAckFrame ack_frame2;
+ ack_frame2.largest_observed = 100u;
+ ack_frame2.packets.Add(21, 100);
+ EXPECT_FALSE(IsAwaitingPacket(ack_frame2, 11u, 20u));
+ EXPECT_FALSE(IsAwaitingPacket(ack_frame2, 80u, 20u));
+ EXPECT_TRUE(IsAwaitingPacket(ack_frame2, 101u, 20u));
+
+ ack_frame2.packets.Remove(50);
+ EXPECT_TRUE(IsAwaitingPacket(ack_frame2, 50u, 20u));
+}
+
+// Tests that a queue contains the expected data after calls to Add().
+TEST(PacketNumberQueueTest, AddRange) {
+ PacketNumberQueue queue;
+ queue.Add(1, 51);
+ queue.Add(53);
+
+ EXPECT_FALSE(queue.Contains(0));
+ for (int i = 1; i < 51; ++i) {
+ EXPECT_TRUE(queue.Contains(i));
+ }
+ EXPECT_FALSE(queue.Contains(51));
+ EXPECT_FALSE(queue.Contains(52));
+ EXPECT_TRUE(queue.Contains(53));
+ EXPECT_FALSE(queue.Contains(54));
+ EXPECT_EQ(51u, queue.NumPacketsSlow());
+ EXPECT_EQ(1u, queue.Min());
+ EXPECT_EQ(53u, queue.Max());
+
+ queue.Add(70);
+ EXPECT_EQ(70u, queue.Max());
+}
+
+// Tests that a queue contains the expected data after calls to Remove().
+TEST(PacketNumberQueueTest, Removal) {
+ PacketNumberQueue queue;
+ queue.Add(0, 100);
+
+ EXPECT_TRUE(queue.RemoveUpTo(51));
+ EXPECT_FALSE(queue.RemoveUpTo(51));
+ queue.Remove(53);
+
+ EXPECT_FALSE(queue.Contains(0));
+ for (int i = 1; i < 51; ++i) {
+ EXPECT_FALSE(queue.Contains(i));
+ }
+ EXPECT_TRUE(queue.Contains(51));
+ EXPECT_TRUE(queue.Contains(52));
+ EXPECT_FALSE(queue.Contains(53));
+ EXPECT_TRUE(queue.Contains(54));
+ EXPECT_EQ(48u, queue.NumPacketsSlow());
+ EXPECT_EQ(51u, queue.Min());
+ EXPECT_EQ(99u, queue.Max());
+
+ queue.Remove(51);
+ EXPECT_EQ(52u, queue.Min());
+ queue.Remove(99);
+ EXPECT_EQ(98u, queue.Max());
+}
+
+// Tests that a queue is empty when all of its elements are removed.
+TEST(PacketNumberQueueTest, Empty) {
+ PacketNumberQueue queue;
+ EXPECT_TRUE(queue.Empty());
+ EXPECT_EQ(0u, queue.NumPacketsSlow());
+
+ queue.Add(1, 100);
+ EXPECT_TRUE(queue.RemoveUpTo(100));
+ EXPECT_TRUE(queue.Empty());
+ EXPECT_EQ(0u, queue.NumPacketsSlow());
+}
+
+// Tests that logging the state of a PacketNumberQueue does not crash.
+TEST(PacketNumberQueueTest, LogDoesNotCrash) {
+ std::ostringstream oss;
+ PacketNumberQueue queue;
+ oss << queue;
+
+ queue.Add(1);
+ queue.Add(50, 100);
+ oss << queue;
+}
+
+// Tests that the iterators returned from a packet queue iterate over the queue.
+TEST(PacketNumberQueueTest, Iterators) {
+ PacketNumberQueue queue;
+ queue.Add(1, 100);
+
+ const std::vector<Interval<QuicPacketNumber>> actual_intervals(queue.begin(),
+ queue.end());
+
+ std::vector<Interval<QuicPacketNumber>> expected_intervals;
+ expected_intervals.push_back(Interval<QuicPacketNumber>(1, 100));
+
+ EXPECT_EQ(expected_intervals, actual_intervals);
+}
+
+TEST(PacketNumberQueueTest, LowerBoundEquals) {
+ PacketNumberQueue queue;
+ queue.Add(1, 100);
+
+ PacketNumberQueue::const_iterator it = queue.lower_bound(10);
+ ASSERT_NE(queue.end(), it);
+ EXPECT_TRUE(it->Contains(10u));
+
+ it = queue.lower_bound(101);
+ EXPECT_TRUE(queue.end() == it);
+}
+
+TEST(PacketNumberQueueTest, LowerBoundGreater) {
+ PacketNumberQueue queue;
+ queue.Add(15, 25);
+ queue.Add(50, 100);
+
+ PacketNumberQueue::const_iterator it = queue.lower_bound(10);
+ ASSERT_NE(queue.end(), it);
+ EXPECT_EQ(15u, it->min());
+ EXPECT_EQ(25u, it->max());
+}
+
+TEST(PacketNumberQueueTest, IntervalLengthAndRemoveInterval) {
+ PacketNumberQueue queue;
+ queue.Add(1, 10);
+ queue.Add(20, 30);
+ queue.Add(40, 50);
+ EXPECT_EQ(3u, queue.NumIntervals());
+ EXPECT_EQ(10u, queue.LastIntervalLength());
+ queue.Remove(9, 21);
+ EXPECT_EQ(3u, queue.NumIntervals());
+ EXPECT_FALSE(queue.Contains(9));
+ EXPECT_FALSE(queue.Contains(20));
+}
+
+TEST(PacketNumberQueueTest, Complement) {
+ PacketNumberQueue queue;
+ queue.Add(1, 10);
+ queue.Add(12, 20);
+ queue.Add(22, 30);
+ queue.Complement();
+ EXPECT_EQ(2u, queue.NumIntervals());
+ EXPECT_TRUE(queue.Contains(10));
+ EXPECT_TRUE(queue.Contains(11));
+ EXPECT_TRUE(queue.Contains(20));
+ EXPECT_TRUE(queue.Contains(21));
+}
+
+} // namespace
+} // namespace test
+} // namespace net
diff --git a/chromium/net/quic/core/frames/quic_goaway_frame.cc b/chromium/net/quic/core/frames/quic_goaway_frame.cc
new file mode 100644
index 00000000000..2405fbae47e
--- /dev/null
+++ b/chromium/net/quic/core/frames/quic_goaway_frame.cc
@@ -0,0 +1,29 @@
+// Copyright (c) 2016 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.
+
+#include "net/quic/core/frames/quic_goaway_frame.h"
+
+using std::string;
+
+namespace net {
+
+QuicGoAwayFrame::QuicGoAwayFrame()
+ : error_code(QUIC_NO_ERROR), last_good_stream_id(0) {}
+
+QuicGoAwayFrame::QuicGoAwayFrame(QuicErrorCode error_code,
+ QuicStreamId last_good_stream_id,
+ const string& reason)
+ : error_code(error_code),
+ last_good_stream_id(last_good_stream_id),
+ reason_phrase(reason) {}
+
+std::ostream& operator<<(std::ostream& os,
+ const QuicGoAwayFrame& goaway_frame) {
+ os << "{ error_code: " << goaway_frame.error_code
+ << ", last_good_stream_id: " << goaway_frame.last_good_stream_id
+ << ", reason_phrase: '" << goaway_frame.reason_phrase << "' }\n";
+ return os;
+}
+
+} // namespace net
diff --git a/chromium/net/quic/core/frames/quic_goaway_frame.h b/chromium/net/quic/core/frames/quic_goaway_frame.h
new file mode 100644
index 00000000000..5eafcffef22
--- /dev/null
+++ b/chromium/net/quic/core/frames/quic_goaway_frame.h
@@ -0,0 +1,33 @@
+// Copyright (c) 2016 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.
+
+#ifndef NET_QUIC_CORE_FRAMES_QUIC_GOAWAY_FRAME_H_
+#define NET_QUIC_CORE_FRAMES_QUIC_GOAWAY_FRAME_H_
+
+#include <ostream>
+#include <string>
+
+#include "net/quic/core/quic_error_codes.h"
+#include "net/quic/core/quic_types.h"
+#include "net/quic/platform/api/quic_export.h"
+
+namespace net {
+
+struct QUIC_EXPORT_PRIVATE QuicGoAwayFrame {
+ QuicGoAwayFrame();
+ QuicGoAwayFrame(QuicErrorCode error_code,
+ QuicStreamId last_good_stream_id,
+ const std::string& reason);
+
+ friend QUIC_EXPORT_PRIVATE std::ostream& operator<<(std::ostream& os,
+ const QuicGoAwayFrame& g);
+
+ QuicErrorCode error_code;
+ QuicStreamId last_good_stream_id;
+ std::string reason_phrase;
+};
+
+} // namespace net
+
+#endif // NET_QUIC_CORE_FRAMES_QUIC_GOAWAY_FRAME_H_
diff --git a/chromium/net/quic/core/frames/quic_mtu_discovery_frame.h b/chromium/net/quic/core/frames/quic_mtu_discovery_frame.h
new file mode 100644
index 00000000000..d0f33df91e7
--- /dev/null
+++ b/chromium/net/quic/core/frames/quic_mtu_discovery_frame.h
@@ -0,0 +1,18 @@
+// Copyright (c) 2016 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.
+
+#ifndef NET_QUIC_CORE_FRAMES_QUIC_MTU_DISCOVERY_FRAME_H_
+#define NET_QUIC_CORE_FRAMES_QUIC_MTU_DISCOVERY_FRAME_H_
+
+#include "net/quic/platform/api/quic_export.h"
+
+namespace net {
+
+// A path MTU discovery frame contains no payload and is serialized as a ping
+// frame.
+struct QUIC_EXPORT_PRIVATE QuicMtuDiscoveryFrame {};
+
+} // namespace net
+
+#endif // NET_QUIC_CORE_FRAMES_QUIC_MTU_DISCOVERY_FRAME_H_
diff --git a/chromium/net/quic/core/frames/quic_padding_frame.cc b/chromium/net/quic/core/frames/quic_padding_frame.cc
new file mode 100644
index 00000000000..99bc46862ea
--- /dev/null
+++ b/chromium/net/quic/core/frames/quic_padding_frame.cc
@@ -0,0 +1,17 @@
+// Copyright (c) 2016 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.
+
+#include "net/quic/core/frames/quic_padding_frame.h"
+
+using std::string;
+
+namespace net {
+
+std::ostream& operator<<(std::ostream& os,
+ const QuicPaddingFrame& padding_frame) {
+ os << "{ num_padding_bytes: " << padding_frame.num_padding_bytes << " }\n";
+ return os;
+}
+
+} // namespace net
diff --git a/chromium/net/quic/core/frames/quic_padding_frame.h b/chromium/net/quic/core/frames/quic_padding_frame.h
new file mode 100644
index 00000000000..93fb990c451
--- /dev/null
+++ b/chromium/net/quic/core/frames/quic_padding_frame.h
@@ -0,0 +1,32 @@
+// Copyright (c) 2016 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.
+
+#ifndef NET_QUIC_CORE_FRAMES_QUIC_PADDING_FRAME_H_
+#define NET_QUIC_CORE_FRAMES_QUIC_PADDING_FRAME_H_
+
+#include <cstdint>
+#include <ostream>
+
+#include "net/quic/platform/api/quic_export.h"
+
+namespace net {
+
+// A padding frame contains no payload.
+struct QUIC_EXPORT_PRIVATE QuicPaddingFrame {
+ QuicPaddingFrame() : num_padding_bytes(-1) {}
+ explicit QuicPaddingFrame(int num_padding_bytes)
+ : num_padding_bytes(num_padding_bytes) {}
+
+ friend QUIC_EXPORT_PRIVATE std::ostream& operator<<(
+ std::ostream& os,
+ const QuicPaddingFrame& s);
+
+ // -1: full padding to the end of a max-sized packet
+ // otherwise: only pad up to num_padding_bytes bytes
+ int num_padding_bytes;
+};
+
+} // namespace net
+
+#endif // NET_QUIC_CORE_FRAMES_QUIC_PADDING_FRAME_H_
diff --git a/chromium/net/quic/core/frames/quic_path_close_frame.cc b/chromium/net/quic/core/frames/quic_path_close_frame.cc
new file mode 100644
index 00000000000..f2b751aca02
--- /dev/null
+++ b/chromium/net/quic/core/frames/quic_path_close_frame.cc
@@ -0,0 +1,17 @@
+// Copyright (c) 2016 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.
+
+#include "net/quic/core/frames/quic_path_close_frame.h"
+
+namespace net {
+
+QuicPathCloseFrame::QuicPathCloseFrame(QuicPathId path_id) : path_id(path_id) {}
+
+std::ostream& operator<<(std::ostream& os,
+ const QuicPathCloseFrame& path_close_frame) {
+ os << "{ path_id: " << static_cast<int>(path_close_frame.path_id) << " }\n";
+ return os;
+}
+
+} // namespace net
diff --git a/chromium/net/quic/core/frames/quic_path_close_frame.h b/chromium/net/quic/core/frames/quic_path_close_frame.h
new file mode 100644
index 00000000000..55982a9c746
--- /dev/null
+++ b/chromium/net/quic/core/frames/quic_path_close_frame.h
@@ -0,0 +1,34 @@
+// Copyright (c) 2016 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.
+
+#ifndef NET_QUIC_CORE_FRAMES_QUIC_PATH_CLOSE_FRAME_H_
+#define NET_QUIC_CORE_FRAMES_QUIC_PATH_CLOSE_FRAME_H_
+
+#include <ostream>
+
+#include "net/quic/core/quic_types.h"
+#include "net/quic/platform/api/quic_export.h"
+
+namespace net {
+
+// The PATH_CLOSE frame is used to explicitly close a path. Both endpoints can
+// send a PATH_CLOSE frame to initiate a path termination. A path is considered
+// to be closed either a PATH_CLOSE frame is sent or received. An endpoint drops
+// receive side of a closed path, and packets with retransmittable frames on a
+// closed path are marked as retransmissions which will be transmitted on other
+// paths.
+struct QUIC_EXPORT_PRIVATE QuicPathCloseFrame {
+ QuicPathCloseFrame() {}
+ explicit QuicPathCloseFrame(QuicPathId path_id);
+
+ friend QUIC_EXPORT_PRIVATE std::ostream& operator<<(
+ std::ostream& os,
+ const QuicPathCloseFrame& p);
+
+ QuicPathId path_id;
+};
+
+} // namespace net
+
+#endif // NET_QUIC_CORE_FRAMES_QUIC_PATH_CLOSE_FRAME_H_
diff --git a/chromium/net/quic/core/frames/quic_ping_frame.h b/chromium/net/quic/core/frames/quic_ping_frame.h
new file mode 100644
index 00000000000..df1e88e50a4
--- /dev/null
+++ b/chromium/net/quic/core/frames/quic_ping_frame.h
@@ -0,0 +1,18 @@
+// Copyright (c) 2016 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.
+
+#ifndef NET_QUIC_CORE_FRAMES_QUIC_PING_FRAME_H_
+#define NET_QUIC_CORE_FRAMES_QUIC_PING_FRAME_H_
+
+#include "net/quic/platform/api/quic_export.h"
+
+namespace net {
+
+// A ping frame contains no payload, though it is retransmittable,
+// and ACK'd just like other normal frames.
+struct QUIC_EXPORT_PRIVATE QuicPingFrame {};
+
+} // namespace net
+
+#endif // NET_QUIC_CORE_FRAMES_QUIC_PING_FRAME_H_
diff --git a/chromium/net/quic/core/frames/quic_rst_stream_frame.cc b/chromium/net/quic/core/frames/quic_rst_stream_frame.cc
new file mode 100644
index 00000000000..7b2afa7c278
--- /dev/null
+++ b/chromium/net/quic/core/frames/quic_rst_stream_frame.cc
@@ -0,0 +1,26 @@
+// Copyright (c) 2016 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.
+
+#include "net/quic/core/frames/quic_rst_stream_frame.h"
+
+namespace net {
+
+QuicRstStreamFrame::QuicRstStreamFrame()
+ : stream_id(0), error_code(QUIC_STREAM_NO_ERROR), byte_offset(0) {}
+
+QuicRstStreamFrame::QuicRstStreamFrame(QuicStreamId stream_id,
+ QuicRstStreamErrorCode error_code,
+ QuicStreamOffset bytes_written)
+ : stream_id(stream_id),
+ error_code(error_code),
+ byte_offset(bytes_written) {}
+
+std::ostream& operator<<(std::ostream& os,
+ const QuicRstStreamFrame& rst_frame) {
+ os << "{ stream_id: " << rst_frame.stream_id
+ << ", error_code: " << rst_frame.error_code << " }\n";
+ return os;
+}
+
+} // namespace net
diff --git a/chromium/net/quic/core/frames/quic_rst_stream_frame.h b/chromium/net/quic/core/frames/quic_rst_stream_frame.h
new file mode 100644
index 00000000000..896c66c3fc4
--- /dev/null
+++ b/chromium/net/quic/core/frames/quic_rst_stream_frame.h
@@ -0,0 +1,38 @@
+// Copyright (c) 2016 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.
+
+#ifndef NET_QUIC_CORE_FRAMES_QUIC_RST_STREAM_FRAME_H_
+#define NET_QUIC_CORE_FRAMES_QUIC_RST_STREAM_FRAME_H_
+
+#include <ostream>
+
+#include "net/quic/core/quic_error_codes.h"
+#include "net/quic/core/quic_types.h"
+#include "net/quic/platform/api/quic_export.h"
+
+namespace net {
+
+struct QUIC_EXPORT_PRIVATE QuicRstStreamFrame {
+ QuicRstStreamFrame();
+ QuicRstStreamFrame(QuicStreamId stream_id,
+ QuicRstStreamErrorCode error_code,
+ QuicStreamOffset bytes_written);
+
+ friend QUIC_EXPORT_PRIVATE std::ostream& operator<<(
+ std::ostream& os,
+ const QuicRstStreamFrame& r);
+
+ QuicStreamId stream_id;
+ QuicRstStreamErrorCode error_code;
+
+ // Used to update flow control windows. On termination of a stream, both
+ // endpoints must inform the peer of the number of bytes they have sent on
+ // that stream. This can be done through normal termination (data packet with
+ // FIN) or through a RST.
+ QuicStreamOffset byte_offset;
+};
+
+} // namespace net
+
+#endif // NET_QUIC_CORE_FRAMES_QUIC_RST_STREAM_FRAME_H_
diff --git a/chromium/net/quic/core/frames/quic_stop_waiting_frame.cc b/chromium/net/quic/core/frames/quic_stop_waiting_frame.cc
new file mode 100644
index 00000000000..b051beb0d6a
--- /dev/null
+++ b/chromium/net/quic/core/frames/quic_stop_waiting_frame.cc
@@ -0,0 +1,22 @@
+// Copyright (c) 2016 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.
+
+#include "net/quic/core/frames/quic_stop_waiting_frame.h"
+
+#include "net/quic/core/quic_constants.h"
+
+namespace net {
+
+QuicStopWaitingFrame::QuicStopWaitingFrame()
+ : path_id(kDefaultPathId), least_unacked(0) {}
+
+QuicStopWaitingFrame::~QuicStopWaitingFrame() {}
+
+std::ostream& operator<<(std::ostream& os,
+ const QuicStopWaitingFrame& sent_info) {
+ os << "{ least_unacked: " << sent_info.least_unacked << " }\n";
+ return os;
+}
+
+} // namespace net
diff --git a/chromium/net/quic/core/frames/quic_stop_waiting_frame.h b/chromium/net/quic/core/frames/quic_stop_waiting_frame.h
new file mode 100644
index 00000000000..1c02a7768c3
--- /dev/null
+++ b/chromium/net/quic/core/frames/quic_stop_waiting_frame.h
@@ -0,0 +1,31 @@
+// Copyright (c) 2016 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.
+
+#ifndef NET_QUIC_CORE_FRAMES_QUIC_STOP_WAITING_FRAME_H_
+#define NET_QUIC_CORE_FRAMES_QUIC_STOP_WAITING_FRAME_H_
+
+#include <ostream>
+
+#include "net/quic/core/quic_types.h"
+#include "net/quic/platform/api/quic_export.h"
+
+namespace net {
+
+struct QUIC_EXPORT_PRIVATE QuicStopWaitingFrame {
+ QuicStopWaitingFrame();
+ ~QuicStopWaitingFrame();
+
+ friend QUIC_EXPORT_PRIVATE std::ostream& operator<<(
+ std::ostream& os,
+ const QuicStopWaitingFrame& s);
+
+ // Path which this stop waiting frame belongs to.
+ QuicPathId path_id;
+ // The lowest packet we've sent which is unacked, and we expect an ack for.
+ QuicPacketNumber least_unacked;
+};
+
+} // namespace net
+
+#endif // NET_QUIC_CORE_FRAMES_QUIC_STOP_WAITING_FRAME_H_
diff --git a/chromium/net/quic/core/frames/quic_stream_frame.cc b/chromium/net/quic/core/frames/quic_stream_frame.cc
new file mode 100644
index 00000000000..58ec40e5153
--- /dev/null
+++ b/chromium/net/quic/core/frames/quic_stream_frame.cc
@@ -0,0 +1,82 @@
+// Copyright (c) 2016 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.
+
+#include "net/quic/core/frames/quic_stream_frame.h"
+
+#include "net/quic/platform/api/quic_logging.h"
+
+using base::StringPiece;
+
+namespace net {
+
+void StreamBufferDeleter::operator()(char* buffer) const {
+ if (allocator_ != nullptr && buffer != nullptr) {
+ allocator_->Delete(buffer);
+ }
+}
+
+UniqueStreamBuffer NewStreamBuffer(QuicBufferAllocator* allocator,
+ size_t size) {
+ return UniqueStreamBuffer(allocator->New(size),
+ StreamBufferDeleter(allocator));
+}
+
+QuicStreamFrame::QuicStreamFrame()
+ : QuicStreamFrame(0, false, 0, nullptr, 0, nullptr) {}
+
+QuicStreamFrame::QuicStreamFrame(QuicStreamId stream_id,
+ bool fin,
+ QuicStreamOffset offset,
+ StringPiece data)
+ : QuicStreamFrame(stream_id,
+ fin,
+ offset,
+ data.data(),
+ data.length(),
+ nullptr) {}
+
+QuicStreamFrame::QuicStreamFrame(QuicStreamId stream_id,
+ bool fin,
+ QuicStreamOffset offset,
+ QuicPacketLength data_length,
+ UniqueStreamBuffer buffer)
+ : QuicStreamFrame(stream_id,
+ fin,
+ offset,
+ nullptr,
+ data_length,
+ std::move(buffer)) {
+ DCHECK(this->buffer != nullptr);
+ DCHECK_EQ(data_buffer, this->buffer.get());
+}
+
+QuicStreamFrame::QuicStreamFrame(QuicStreamId stream_id,
+ bool fin,
+ QuicStreamOffset offset,
+ const char* data_buffer,
+ QuicPacketLength data_length,
+ UniqueStreamBuffer buffer)
+ : stream_id(stream_id),
+ fin(fin),
+ data_length(data_length),
+ data_buffer(data_buffer),
+ offset(offset),
+ buffer(std::move(buffer)) {
+ if (this->buffer != nullptr) {
+ DCHECK(data_buffer == nullptr);
+ this->data_buffer = this->buffer.get();
+ }
+}
+
+QuicStreamFrame::~QuicStreamFrame() {}
+
+std::ostream& operator<<(std::ostream& os,
+ const QuicStreamFrame& stream_frame) {
+ os << "{ stream_id: " << stream_frame.stream_id
+ << ", fin: " << stream_frame.fin << ", offset: " << stream_frame.offset
+ << ", length: " << stream_frame.data_length << " }\n";
+ return os;
+}
+
+} // namespace net
diff --git a/chromium/net/quic/core/frames/quic_stream_frame.h b/chromium/net/quic/core/frames/quic_stream_frame.h
new file mode 100644
index 00000000000..99f285630a7
--- /dev/null
+++ b/chromium/net/quic/core/frames/quic_stream_frame.h
@@ -0,0 +1,81 @@
+// Copyright (c) 2016 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.
+
+#ifndef NET_QUIC_CORE_FRAMES_QUIC_STREAM_FRAME_H_
+#define NET_QUIC_CORE_FRAMES_QUIC_STREAM_FRAME_H_
+
+#include <memory>
+#include <ostream>
+
+#include "base/strings/string_piece.h"
+#include "net/quic/core/quic_buffer_allocator.h"
+#include "net/quic/core/quic_types.h"
+#include "net/quic/platform/api/quic_export.h"
+
+namespace net {
+
+// Deleter for stream buffers. Copyable to support platforms where the deleter
+// of a unique_ptr must be copyable. Otherwise it would be nice for this to be
+// move-only.
+class QUIC_EXPORT_PRIVATE StreamBufferDeleter {
+ public:
+ StreamBufferDeleter() : allocator_(nullptr) {}
+ explicit StreamBufferDeleter(QuicBufferAllocator* allocator)
+ : allocator_(allocator) {}
+
+ // Deletes |buffer| using |allocator_|.
+ void operator()(char* buffer) const;
+
+ private:
+ // Not owned; must be valid so long as the buffer stored in the unique_ptr
+ // that owns |this| is valid.
+ QuicBufferAllocator* allocator_;
+};
+
+using UniqueStreamBuffer = std::unique_ptr<char[], StreamBufferDeleter>;
+
+// Allocates memory of size |size| using |allocator| for a QUIC stream buffer.
+QUIC_EXPORT_PRIVATE UniqueStreamBuffer
+NewStreamBuffer(QuicBufferAllocator* allocator, size_t size);
+
+struct QUIC_EXPORT_PRIVATE QuicStreamFrame {
+ QuicStreamFrame();
+ QuicStreamFrame(QuicStreamId stream_id,
+ bool fin,
+ QuicStreamOffset offset,
+ base::StringPiece data);
+ QuicStreamFrame(QuicStreamId stream_id,
+ bool fin,
+ QuicStreamOffset offset,
+ QuicPacketLength data_length,
+ UniqueStreamBuffer buffer);
+ ~QuicStreamFrame();
+
+ friend QUIC_EXPORT_PRIVATE std::ostream& operator<<(std::ostream& os,
+ const QuicStreamFrame& s);
+
+ QuicStreamId stream_id;
+ bool fin;
+ QuicPacketLength data_length;
+ const char* data_buffer;
+ QuicStreamOffset offset; // Location of this data in the stream.
+ // nullptr when the QuicStreamFrame is received, and non-null when sent.
+ UniqueStreamBuffer buffer;
+
+ private:
+ QuicStreamFrame(QuicStreamId stream_id,
+ bool fin,
+ QuicStreamOffset offset,
+ const char* data_buffer,
+ QuicPacketLength data_length,
+ UniqueStreamBuffer buffer);
+
+ DISALLOW_COPY_AND_ASSIGN(QuicStreamFrame);
+};
+static_assert(sizeof(QuicStreamFrame) <= 64,
+ "Keep the QuicStreamFrame size to a cacheline.");
+
+} // namespace net
+
+#endif // NET_QUIC_CORE_FRAMES_QUIC_STREAM_FRAME_H_
diff --git a/chromium/net/quic/core/frames/quic_window_update_frame.cc b/chromium/net/quic/core/frames/quic_window_update_frame.cc
new file mode 100644
index 00000000000..e2fe00b7a26
--- /dev/null
+++ b/chromium/net/quic/core/frames/quic_window_update_frame.cc
@@ -0,0 +1,20 @@
+// Copyright (c) 2016 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.
+
+#include "net/quic/core/frames/quic_window_update_frame.h"
+
+namespace net {
+
+QuicWindowUpdateFrame::QuicWindowUpdateFrame(QuicStreamId stream_id,
+ QuicStreamOffset byte_offset)
+ : stream_id(stream_id), byte_offset(byte_offset) {}
+
+std::ostream& operator<<(std::ostream& os,
+ const QuicWindowUpdateFrame& window_update_frame) {
+ os << "{ stream_id: " << window_update_frame.stream_id
+ << ", byte_offset: " << window_update_frame.byte_offset << " }\n";
+ return os;
+}
+
+} // namespace net
diff --git a/chromium/net/quic/core/frames/quic_window_update_frame.h b/chromium/net/quic/core/frames/quic_window_update_frame.h
new file mode 100644
index 00000000000..0edf79ab0ff
--- /dev/null
+++ b/chromium/net/quic/core/frames/quic_window_update_frame.h
@@ -0,0 +1,39 @@
+// Copyright (c) 2016 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.
+
+#ifndef NET_QUIC_CORE_FRAMES_QUIC_WINDOW_UPDATE_FRAME_H_
+#define NET_QUIC_CORE_FRAMES_QUIC_WINDOW_UPDATE_FRAME_H_
+
+#include <ostream>
+
+#include "net/quic/core/quic_types.h"
+#include "net/quic/platform/api/quic_export.h"
+
+namespace net {
+
+// Flow control updates per-stream and at the connection levoel.
+// Based on SPDY's WINDOW_UPDATE frame, but uses an absolute byte offset rather
+// than a window delta.
+// TODO(rjshade): A possible future optimization is to make stream_id and
+// byte_offset variable length, similar to stream frames.
+struct QUIC_EXPORT_PRIVATE QuicWindowUpdateFrame {
+ QuicWindowUpdateFrame() {}
+ QuicWindowUpdateFrame(QuicStreamId stream_id, QuicStreamOffset byte_offset);
+
+ friend QUIC_EXPORT_PRIVATE std::ostream& operator<<(
+ std::ostream& os,
+ const QuicWindowUpdateFrame& w);
+
+ // The stream this frame applies to. 0 is a special case meaning the overall
+ // connection rather than a specific stream.
+ QuicStreamId stream_id;
+
+ // Byte offset in the stream or connection. The receiver of this frame must
+ // not send data which would result in this offset being exceeded.
+ QuicStreamOffset byte_offset;
+};
+
+} // namespace net
+
+#endif // NET_QUIC_CORE_FRAMES_QUIC_WINDOW_UPDATE_FRAME_H_
diff --git a/chromium/net/quic/core/interval.h b/chromium/net/quic/core/interval.h
index d29694e598b..eaae9c98b58 100644
--- a/chromium/net/quic/core/interval.h
+++ b/chromium/net/quic/core/interval.h
@@ -57,8 +57,8 @@
// EXPECT_TRUE(r1.Empty()); // Now r1 is empty.
// EXPECT_FALSE(r1.Contains(r1.min())); // e.g. doesn't contain its own min.
-#ifndef NET_QUIC_INTERVAL_H_
-#define NET_QUIC_INTERVAL_H_
+#ifndef NET_QUIC_CORE_INTERVAL_H_
+#define NET_QUIC_CORE_INTERVAL_H_
#include <stddef.h>
@@ -299,4 +299,4 @@ bool Interval<T>::Difference(const Interval& i,
} // namespace net
-#endif // NET_QUIC_INTERVAL_H_
+#endif // NET_QUIC_CORE_INTERVAL_H_
diff --git a/chromium/net/quic/core/interval_set.h b/chromium/net/quic/core/interval_set.h
index 9bb763a4e91..ac0695c5f19 100644
--- a/chromium/net/quic/core/interval_set.h
+++ b/chromium/net/quic/core/interval_set.h
@@ -49,12 +49,13 @@
// EXPECT_EQ(1, intervals.Size());
// EXPECT_TRUE(intervals.Contains(Interval<int>(20, 40)));
-#ifndef NET_QUIC_INTERVAL_SET_H_
-#define NET_QUIC_INTERVAL_SET_H_
+#ifndef NET_QUIC_CORE_INTERVAL_SET_H_
+#define NET_QUIC_CORE_INTERVAL_SET_H_
#include <stddef.h>
#include <algorithm>
+#include <ostream>
#include <set>
#include <string>
#include <utility>
@@ -854,4 +855,4 @@ inline bool IntervalSet<T>::IntervalComparator::operator()(
} // namespace net
-#endif // NET_QUIC_INTERVAL_SET_H_
+#endif // NET_QUIC_CORE_INTERVAL_SET_H_
diff --git a/chromium/net/quic/core/interval_set_test.cc b/chromium/net/quic/core/interval_set_test.cc
index cbcda2a325e..9fcdddb289a 100644
--- a/chromium/net/quic/core/interval_set_test.cc
+++ b/chromium/net/quic/core/interval_set_test.cc
@@ -6,16 +6,13 @@
#include <stdarg.h>
-#include <iostream>
#include <iterator>
#include <limits>
#include "net/test/gtest_util.h"
#include "testing/gtest/include/gtest/gtest.h"
-using std::pair;
using std::string;
-using std::vector;
namespace net {
namespace test {
@@ -87,7 +84,7 @@ TEST_F(IntervalSetTest, IsDisjoint) {
// Returns true iff <is> contains <count> intervals whose successive
// endpoints match the sequence of args in <ap>:
static bool VA_Check(const IntervalSet<int>& is, size_t count, va_list ap) {
- vector<Interval<int>> intervals;
+ std::vector<Interval<int>> intervals;
is.Get(&intervals);
if (count != intervals.size()) {
LOG(ERROR) << "Expected " << count << " intervals, got " << intervals.size()
@@ -204,14 +201,14 @@ TEST_F(IntervalSetTest, IntervalSetBasic) {
// Test Get() (using an output iterator), begin()/end(), and rbegin()/rend()
// to iterate over intervals.
{
- vector<Interval<int>> expected;
+ std::vector<Interval<int>> expected;
iset.Get(&expected);
- vector<Interval<int>> actual1;
+ std::vector<Interval<int>> actual1;
iset.Get(back_inserter(actual1));
ASSERT_EQ(expected.size(), actual1.size());
- vector<Interval<int>> actual2;
+ std::vector<Interval<int>> actual2;
std::copy(iset.begin(), iset.end(), back_inserter(actual2));
ASSERT_EQ(expected.size(), actual2.size());
@@ -225,7 +222,7 @@ TEST_F(IntervalSetTest, IntervalSetBasic) {
// Ensure that the rbegin()/rend() iterators correctly yield the intervals
// in reverse order.
- EXPECT_THAT(vector<Interval<int>>(iset.rbegin(), iset.rend()),
+ EXPECT_THAT(std::vector<Interval<int>>(iset.rbegin(), iset.rend()),
ElementsAreArray(expected.rbegin(), expected.rend()));
}
@@ -587,7 +584,7 @@ TEST_F(IntervalSetTest, IntervalSetDifference) {
}
TEST_F(IntervalSetTest, IntervalSetDifferenceSingleBounds) {
- vector<Interval<int>> ivals;
+ std::vector<Interval<int>> ivals;
other.Get(&ivals);
for (size_t i = 0; i < ivals.size(); ++i) {
is.Difference(ivals[i].min(), ivals[i].max());
@@ -597,7 +594,7 @@ TEST_F(IntervalSetTest, IntervalSetDifferenceSingleBounds) {
}
TEST_F(IntervalSetTest, IntervalSetDifferenceSingleInterval) {
- vector<Interval<int>> ivals;
+ std::vector<Interval<int>> ivals;
other.Get(&ivals);
for (size_t i = 0; i < ivals.size(); ++i) {
is.Difference(ivals[i]);
diff --git a/chromium/net/quic/core/interval_test.cc b/chromium/net/quic/core/interval_test.cc
index 2e52c5b8c21..da8643aae1f 100644
--- a/chromium/net/quic/core/interval_test.cc
+++ b/chromium/net/quic/core/interval_test.cc
@@ -15,9 +15,7 @@
#include "net/test/gtest_util.h"
#include "testing/gtest/include/gtest/gtest.h"
-using std::pair;
using std::string;
-using std::vector;
namespace net {
namespace test {
@@ -271,7 +269,7 @@ TEST_F(IntervalTest, IntervalOfTypeWithNoOperatorMinus) {
// Interval<T> should work even if T does not support operator-(). We just
// can't call Interval<T>::Length() for such types.
const Interval<string> d1("a", "b");
- const Interval<pair<int, int>> d2({1, 2}, {4, 3});
+ const Interval<std::pair<int, int>> d2({1, 2}, {4, 3});
EXPECT_EQ("a", d1.min());
EXPECT_EQ("b", d1.max());
EXPECT_EQ(std::make_pair(1, 2), d2.min());
diff --git a/chromium/net/quic/core/quic_ack_listener_interface.cc b/chromium/net/quic/core/quic_ack_listener_interface.cc
new file mode 100644
index 00000000000..f0bd0be2ea5
--- /dev/null
+++ b/chromium/net/quic/core/quic_ack_listener_interface.cc
@@ -0,0 +1,21 @@
+// Copyright (c) 2016 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.
+
+#include "net/quic/core/quic_ack_listener_interface.h"
+
+namespace net {
+
+QuicAckListenerInterface::~QuicAckListenerInterface() {}
+
+AckListenerWrapper::AckListenerWrapper(
+ QuicReferenceCountedPointer<QuicAckListenerInterface> ack_listener,
+ QuicPacketLength data_length)
+ : ack_listener(std::move(ack_listener)), length(data_length) {}
+
+AckListenerWrapper::AckListenerWrapper(const AckListenerWrapper& other) =
+ default;
+
+AckListenerWrapper::~AckListenerWrapper() {}
+
+} // namespace net
diff --git a/chromium/net/quic/core/quic_ack_listener_interface.h b/chromium/net/quic/core/quic_ack_listener_interface.h
new file mode 100644
index 00000000000..6082ff3edb2
--- /dev/null
+++ b/chromium/net/quic/core/quic_ack_listener_interface.h
@@ -0,0 +1,48 @@
+// Copyright (c) 2016 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.
+
+#ifndef NET_QUIC_CORE_QUIC_ACK_LISTENER_INTERFACE_H_
+#define NET_QUIC_CORE_QUIC_ACK_LISTENER_INTERFACE_H_
+
+#include "net/quic/core/quic_time.h"
+#include "net/quic/core/quic_types.h"
+#include "net/quic/platform/api/quic_export.h"
+#include "net/quic/platform/api/quic_reference_counted.h"
+
+namespace net {
+
+// Pure virtual class to listen for packet acknowledgements.
+class QUIC_EXPORT_PRIVATE QuicAckListenerInterface
+ : public QuicReferenceCounted {
+ public:
+ QuicAckListenerInterface() {}
+
+ // Called when a packet is acked. Called once per packet.
+ // |acked_bytes| is the number of data bytes acked.
+ virtual void OnPacketAcked(int acked_bytes,
+ QuicTime::Delta ack_delay_time) = 0;
+
+ // Called when a packet is retransmitted. Called once per packet.
+ // |retransmitted_bytes| is the number of data bytes retransmitted.
+ virtual void OnPacketRetransmitted(int retransmitted_bytes) = 0;
+
+ protected:
+ // Delegates are ref counted.
+ ~QuicAckListenerInterface() override;
+};
+
+struct QUIC_EXPORT_PRIVATE AckListenerWrapper {
+ AckListenerWrapper(
+ QuicReferenceCountedPointer<QuicAckListenerInterface> ack_listener,
+ QuicPacketLength data_length);
+ AckListenerWrapper(const AckListenerWrapper& other);
+ ~AckListenerWrapper();
+
+ QuicReferenceCountedPointer<QuicAckListenerInterface> ack_listener;
+ QuicPacketLength length;
+};
+
+} // namespace net
+
+#endif // NET_QUIC_CORE_QUIC_ACK_LISTENER_INTERFACE_H_
diff --git a/chromium/net/quic/core/quic_alarm.cc b/chromium/net/quic/core/quic_alarm.cc
index 985be648f66..8150eb85ad1 100644
--- a/chromium/net/quic/core/quic_alarm.cc
+++ b/chromium/net/quic/core/quic_alarm.cc
@@ -4,9 +4,6 @@
#include "net/quic/core/quic_alarm.h"
-#include "base/logging.h"
-#include "net/quic/core/quic_flags.h"
-
namespace net {
QuicAlarm::QuicAlarm(QuicArenaScopedPtr<Delegate> delegate)
diff --git a/chromium/net/quic/core/quic_alarm.h b/chromium/net/quic/core/quic_alarm.h
index 7ad8af427be..bfb803ad98d 100644
--- a/chromium/net/quic/core/quic_alarm.h
+++ b/chromium/net/quic/core/quic_alarm.h
@@ -2,15 +2,13 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#ifndef NET_QUIC_QUIC_ALARM_H_
-#define NET_QUIC_QUIC_ALARM_H_
-
-#include <memory>
+#ifndef NET_QUIC_CORE_QUIC_ALARM_H_
+#define NET_QUIC_CORE_QUIC_ALARM_H_
#include "base/macros.h"
-#include "net/base/net_export.h"
#include "net/quic/core/quic_arena_scoped_ptr.h"
#include "net/quic/core/quic_time.h"
+#include "net/quic/platform/api/quic_export.h"
namespace net {
@@ -19,9 +17,9 @@ namespace net {
// An alarm may be cancelled, in which case it may or may not be
// removed from the underlying scheduling system, but in either case
// the task will not be executed.
-class NET_EXPORT_PRIVATE QuicAlarm {
+class QUIC_EXPORT_PRIVATE QuicAlarm {
public:
- class NET_EXPORT_PRIVATE Delegate {
+ class QUIC_EXPORT_PRIVATE Delegate {
public:
virtual ~Delegate() {}
@@ -86,4 +84,4 @@ class NET_EXPORT_PRIVATE QuicAlarm {
} // namespace net
-#endif // NET_QUIC_QUIC_ALARM_H_
+#endif // NET_QUIC_CORE_QUIC_ALARM_H_
diff --git a/chromium/net/quic/core/quic_alarm_factory.h b/chromium/net/quic/core/quic_alarm_factory.h
index 77e6ab7fb42..48126222a68 100644
--- a/chromium/net/quic/core/quic_alarm_factory.h
+++ b/chromium/net/quic/core/quic_alarm_factory.h
@@ -2,12 +2,12 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#ifndef NET_QUIC_QUIC_ALARM_FACTORY_H_
-#define NET_QUIC_QUIC_ALARM_FACTORY_H_
+#ifndef NET_QUIC_CORE_QUIC_ALARM_FACTORY_H_
+#define NET_QUIC_CORE_QUIC_ALARM_FACTORY_H_
-#include "net/base/net_export.h"
#include "net/quic/core/quic_alarm.h"
#include "net/quic/core/quic_one_block_arena.h"
+#include "net/quic/platform/api/quic_export.h"
namespace net {
@@ -16,7 +16,7 @@ namespace net {
using QuicConnectionArena = QuicOneBlockArena<1024>;
// Creates platform-specific alarms used throughout QUIC.
-class NET_EXPORT_PRIVATE QuicAlarmFactory {
+class QUIC_EXPORT_PRIVATE QuicAlarmFactory {
public:
virtual ~QuicAlarmFactory() {}
@@ -37,4 +37,4 @@ class NET_EXPORT_PRIVATE QuicAlarmFactory {
} // namespace net
-#endif // NET_QUIC_QUIC_ALARM_FACTORY_H_
+#endif // NET_QUIC_CORE_QUIC_ALARM_FACTORY_H_
diff --git a/chromium/net/quic/core/quic_alarm_test.cc b/chromium/net/quic/core/quic_alarm_test.cc
index a0cafd66a46..cb6aeac464c 100644
--- a/chromium/net/quic/core/quic_alarm_test.cc
+++ b/chromium/net/quic/core/quic_alarm_test.cc
@@ -4,7 +4,6 @@
#include "net/quic/core/quic_alarm.h"
-#include "base/logging.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
diff --git a/chromium/net/quic/core/quic_arena_scoped_ptr.h b/chromium/net/quic/core/quic_arena_scoped_ptr.h
index d9ca24282bf..14273b1590a 100644
--- a/chromium/net/quic/core/quic_arena_scoped_ptr.h
+++ b/chromium/net/quic/core/quic_arena_scoped_ptr.h
@@ -8,14 +8,14 @@
// type has a non-trivial destructor, the arena must outlive the
// QuicArenaScopedPtr. Does not support array overloads.
-#ifndef NET_QUIC_QUIC_ARENA_SCOPED_PTR_H_
-#define NET_QUIC_QUIC_ARENA_SCOPED_PTR_H_
+#ifndef NET_QUIC_CORE_QUIC_ARENA_SCOPED_PTR_H_
+#define NET_QUIC_CORE_QUIC_ARENA_SCOPED_PTR_H_
#include <cstdint> // for uintptr_t
-#include "base/logging.h"
#include "base/macros.h"
-#include "net/quic/core/quic_utils.h"
+#include "net/quic/platform/api/quic_aligned.h"
+#include "net/quic/platform/api/quic_logging.h"
namespace net {
@@ -117,8 +117,7 @@ bool operator!=(const QuicArenaScopedPtr<T>& left, std::nullptr_t) {
}
template <typename T>
-QuicArenaScopedPtr<T>::QuicArenaScopedPtr()
- : value_(nullptr) {}
+QuicArenaScopedPtr<T>::QuicArenaScopedPtr() : value_(nullptr) {}
template <typename T>
QuicArenaScopedPtr<T>::QuicArenaScopedPtr(T* value)
@@ -207,4 +206,4 @@ QuicArenaScopedPtr<T>::QuicArenaScopedPtr(void* value, ConstructFrom from_arena)
} // namespace net
-#endif // NET_QUIC_QUIC_ARENA_SCOPED_PTR_H_
+#endif // NET_QUIC_CORE_QUIC_ARENA_SCOPED_PTR_H_
diff --git a/chromium/net/quic/core/quic_arena_scoped_ptr_test.cc b/chromium/net/quic/core/quic_arena_scoped_ptr_test.cc
index 9c4a0a2501f..7c59e479489 100644
--- a/chromium/net/quic/core/quic_arena_scoped_ptr_test.cc
+++ b/chromium/net/quic/core/quic_arena_scoped_ptr_test.cc
@@ -1,6 +1,7 @@
// Copyright (c) 2016 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.
+
#include "net/quic/core/quic_arena_scoped_ptr.h"
#include "net/quic/core/quic_one_block_arena.h"
diff --git a/chromium/net/quic/core/quic_bandwidth.cc b/chromium/net/quic/core/quic_bandwidth.cc
index 9ba96f3817e..3dce6de237c 100644
--- a/chromium/net/quic/core/quic_bandwidth.cc
+++ b/chromium/net/quic/core/quic_bandwidth.cc
@@ -4,16 +4,14 @@
#include "net/quic/core/quic_bandwidth.h"
-#include <stdint.h>
-
+#include <cinttypes>
#include <limits>
-#include "base/format_macros.h"
-#include "base/logging.h"
#include "base/strings/stringprintf.h"
-#include "net/quic/core/quic_bug_tracker.h"
+#include "net/quic/core/quic_constants.h"
#include "net/quic/core/quic_time.h"
#include "net/quic/core/quic_types.h"
+#include "net/quic/platform/api/quic_bug_tracker.h"
using base::StringPrintf;
diff --git a/chromium/net/quic/core/quic_bandwidth.h b/chromium/net/quic/core/quic_bandwidth.h
index 20d32be8b5d..4e11d5f88aa 100644
--- a/chromium/net/quic/core/quic_bandwidth.h
+++ b/chromium/net/quic/core/quic_bandwidth.h
@@ -4,24 +4,21 @@
//
// QuicBandwidth represents a bandwidth, stored in bits per second resolution.
-#ifndef NET_QUIC_QUIC_BANDWIDTH_H_
-#define NET_QUIC_QUIC_BANDWIDTH_H_
-
-#include <stdint.h>
+#ifndef NET_QUIC_CORE_QUIC_BANDWIDTH_H_
+#define NET_QUIC_CORE_QUIC_BANDWIDTH_H_
#include <cmath>
+#include <cstdint>
#include <ostream>
#include "base/compiler_specific.h"
-#include "net/base/net_export.h"
#include "net/quic/core/quic_time.h"
+#include "net/quic/core/quic_types.h"
+#include "net/quic/platform/api/quic_export.h"
namespace net {
-typedef uint64_t QuicByteCount;
-typedef uint64_t QuicPacketCount;
-
-class NET_EXPORT_PRIVATE QuicBandwidth {
+class QUIC_EXPORT_PRIVATE QuicBandwidth {
public:
// Creates a new QuicBandwidth with an internal value of 0.
static QuicBandwidth Zero();
@@ -121,4 +118,4 @@ inline std::ostream& operator<<(std::ostream& output,
}
} // namespace net
-#endif // NET_QUIC_QUIC_BANDWIDTH_H_
+#endif // NET_QUIC_CORE_QUIC_BANDWIDTH_H_
diff --git a/chromium/net/quic/core/quic_bandwidth_test.cc b/chromium/net/quic/core/quic_bandwidth_test.cc
index d249768eb8a..17b46e24fcd 100644
--- a/chromium/net/quic/core/quic_bandwidth_test.cc
+++ b/chromium/net/quic/core/quic_bandwidth_test.cc
@@ -3,6 +3,7 @@
// found in the LICENSE file.
#include "net/quic/core/quic_bandwidth.h"
+#include "net/quic/core/quic_time.h"
#include "testing/gtest/include/gtest/gtest.h"
namespace net {
@@ -72,10 +73,10 @@ TEST_F(QuicBandwidthTest, Scale) {
}
TEST_F(QuicBandwidthTest, BytesPerPeriod) {
- EXPECT_EQ(2000u, QuicBandwidth::FromKBytesPerSecond(2000)
- .ToBytesPerPeriod(QuicTime::Delta::FromMilliseconds(1)));
- EXPECT_EQ(2u, QuicBandwidth::FromKBytesPerSecond(2000)
- .ToKBytesPerPeriod(QuicTime::Delta::FromMilliseconds(1)));
+ EXPECT_EQ(2000u, QuicBandwidth::FromKBytesPerSecond(2000).ToBytesPerPeriod(
+ QuicTime::Delta::FromMilliseconds(1)));
+ EXPECT_EQ(2u, QuicBandwidth::FromKBytesPerSecond(2000).ToKBytesPerPeriod(
+ QuicTime::Delta::FromMilliseconds(1)));
EXPECT_EQ(200000u, QuicBandwidth::FromKBytesPerSecond(2000).ToBytesPerPeriod(
QuicTime::Delta::FromMilliseconds(100)));
EXPECT_EQ(200u, QuicBandwidth::FromKBytesPerSecond(2000).ToKBytesPerPeriod(
diff --git a/chromium/net/quic/core/quic_blocked_writer_interface.h b/chromium/net/quic/core/quic_blocked_writer_interface.h
index a3a2622a599..ea6bd474e70 100644
--- a/chromium/net/quic/core/quic_blocked_writer_interface.h
+++ b/chromium/net/quic/core/quic_blocked_writer_interface.h
@@ -6,16 +6,16 @@
// the underlying UDP socket is available for writing (not write blocked
// anymore).
-#ifndef NET_QUIC_QUIC_BLOCKED_WRITER_INTERFACE_H_
-#define NET_QUIC_QUIC_BLOCKED_WRITER_INTERFACE_H_
+#ifndef NET_QUIC_CORE_QUIC_BLOCKED_WRITER_INTERFACE_H_
+#define NET_QUIC_CORE_QUIC_BLOCKED_WRITER_INTERFACE_H_
-#include <stddef.h>
+#include <cstddef>
-#include "net/base/net_export.h"
+#include "net/quic/platform/api/quic_export.h"
namespace net {
-class NET_EXPORT_PRIVATE QuicBlockedWriterInterface {
+class QUIC_EXPORT_PRIVATE QuicBlockedWriterInterface {
public:
virtual ~QuicBlockedWriterInterface() {}
@@ -35,4 +35,4 @@ struct QuicBlockedWriterInterfacePtrHash {
} // namespace net
-#endif // NET_QUIC_QUIC_BLOCKED_WRITER_INTERFACE_H_
+#endif // NET_QUIC_CORE_QUIC_BLOCKED_WRITER_INTERFACE_H_
diff --git a/chromium/net/quic/core/quic_buffer_allocator.cc b/chromium/net/quic/core/quic_buffer_allocator.cc
new file mode 100644
index 00000000000..0dca11ab137
--- /dev/null
+++ b/chromium/net/quic/core/quic_buffer_allocator.cc
@@ -0,0 +1,11 @@
+// Copyright (c) 2012 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.
+
+#include "net/quic/core/quic_buffer_allocator.h"
+
+namespace net {
+
+QuicBufferAllocator::~QuicBufferAllocator() = default;
+
+} // namespace net
diff --git a/chromium/net/quic/core/quic_buffer_allocator.h b/chromium/net/quic/core/quic_buffer_allocator.h
new file mode 100644
index 00000000000..24f27e7b9a5
--- /dev/null
+++ b/chromium/net/quic/core/quic_buffer_allocator.h
@@ -0,0 +1,37 @@
+// Copyright (c) 2012 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.
+
+#ifndef NET_QUIC_CORE_QUIC_BUFFER_ALLOCATOR_H_
+#define NET_QUIC_CORE_QUIC_BUFFER_ALLOCATOR_H_
+
+#include <stddef.h>
+
+#include "net/quic/platform/api/quic_export.h"
+
+namespace net {
+
+// Abstract base class for classes which allocate and delete buffers.
+class QUIC_EXPORT_PRIVATE QuicBufferAllocator {
+ public:
+ virtual ~QuicBufferAllocator();
+
+ // Returns or allocates a new buffer of |size|. Never returns null.
+ virtual char* New(size_t size) = 0;
+
+ // Returns or allocates a new buffer of |size| if |flag_enable| is true.
+ // Otherwise, returns a buffer that is compatible with this class directly
+ // with operator new. Never returns null.
+ virtual char* New(size_t size, bool flag_enable) = 0;
+
+ // Releases a buffer.
+ virtual void Delete(char* buffer) = 0;
+
+ // Marks the allocator as being idle. Serves as a hint to notify the allocator
+ // that it should release any resources it's still holding on to.
+ virtual void MarkAllocatorIdle() {}
+};
+
+} // namespace net
+
+#endif // NET_QUIC_CORE_QUIC_BUFFER_ALLOCATOR_H_
diff --git a/chromium/net/quic/core/quic_buffered_packet_store.cc b/chromium/net/quic/core/quic_buffered_packet_store.cc
index 494d0982e6e..f51b8c836d7 100644
--- a/chromium/net/quic/core/quic_buffered_packet_store.cc
+++ b/chromium/net/quic/core/quic_buffered_packet_store.cc
@@ -4,16 +4,17 @@
#include "net/quic/core/quic_buffered_packet_store.h"
-#include <list>
-
#include "base/stl_util.h"
-#include "net/quic/core/quic_bug_tracker.h"
+#include "net/quic/core/quic_flags.h"
+#include "net/quic/platform/api/quic_bug_tracker.h"
+
+using base::ContainsKey;
namespace net {
typedef QuicBufferedPacketStore::BufferedPacket BufferedPacket;
-typedef QuicBufferedPacketStore::EnqueuePacketResult EnqueuePacketResult;
typedef QuicBufferedPacketStore::BufferedPacketList BufferedPacketList;
+typedef QuicBufferedPacketStore::EnqueuePacketResult EnqueuePacketResult;
// Max number of connections this store can keep track.
static const size_t kDefaultMaxConnectionsInStore = 100;
@@ -42,8 +43,8 @@ class ConnectionExpireAlarm : public QuicAlarm::Delegate {
} // namespace
BufferedPacket::BufferedPacket(std::unique_ptr<QuicReceivedPacket> packet,
- IPEndPoint server_address,
- IPEndPoint client_address)
+ QuicSocketAddress server_address,
+ QuicSocketAddress client_address)
: packet(std::move(packet)),
server_address(server_address),
client_address(client_address) {}
@@ -79,23 +80,24 @@ QuicBufferedPacketStore::~QuicBufferedPacketStore() {}
EnqueuePacketResult QuicBufferedPacketStore::EnqueuePacket(
QuicConnectionId connection_id,
const QuicReceivedPacket& packet,
- IPEndPoint server_address,
- IPEndPoint client_address,
+ QuicSocketAddress server_address,
+ QuicSocketAddress client_address,
bool is_chlo) {
- QUIC_BUG_IF(is_chlo &&
- base::ContainsKey(connections_with_chlo_, connection_id))
+ QUIC_BUG_IF(!FLAGS_quic_allow_chlo_buffering)
+ << "Shouldn't buffer packets if disabled via flag.";
+ QUIC_BUG_IF(is_chlo && ContainsKey(connections_with_chlo_, connection_id))
<< "Shouldn't buffer duplicated CHLO on connection " << connection_id;
- if (!base::ContainsKey(undecryptable_packets_, connection_id) &&
+ if (!ContainsKey(undecryptable_packets_, connection_id) &&
ShouldBufferPacket(is_chlo)) {
// Drop the packet if the upper limit of undecryptable packets has been
// reached or the whole capacity of the store has been reached.
return TOO_MANY_CONNECTIONS;
- } else if (!base::ContainsKey(undecryptable_packets_, connection_id)) {
+ } else if (!ContainsKey(undecryptable_packets_, connection_id)) {
undecryptable_packets_.emplace(
std::make_pair(connection_id, BufferedPacketList()));
}
- CHECK(base::ContainsKey(undecryptable_packets_, connection_id));
+ CHECK(ContainsKey(undecryptable_packets_, connection_id));
BufferedPacketList& queue =
undecryptable_packets_.find(connection_id)->second;
@@ -103,7 +105,7 @@ EnqueuePacketResult QuicBufferedPacketStore::EnqueuePacket(
// If current packet is not CHLO, it might not be buffered because store
// only buffers certain number of undecryptable packets per connection.
size_t num_non_chlo_packets =
- base::ContainsKey(connections_with_chlo_, connection_id)
+ ContainsKey(connections_with_chlo_, connection_id)
? (queue.buffered_packets.size() - 1)
: queue.buffered_packets.size();
if (num_non_chlo_packets >= kDefaultMaxUndecryptablePackets) {
@@ -136,7 +138,7 @@ EnqueuePacketResult QuicBufferedPacketStore::EnqueuePacket(
bool QuicBufferedPacketStore::HasBufferedPackets(
QuicConnectionId connection_id) const {
- return base::ContainsKey(undecryptable_packets_, connection_id);
+ return ContainsKey(undecryptable_packets_, connection_id);
}
bool QuicBufferedPacketStore::HasChlosBuffered() const {
@@ -168,7 +170,7 @@ void QuicBufferedPacketStore::OnExpirationTimeout() {
}
QuicConnectionId connection_id = entry.first;
visitor_->OnExpiredPackets(connection_id, std::move(entry.second));
- undecryptable_packets_.erase(undecryptable_packets_.begin());
+ undecryptable_packets_.pop_front();
connections_with_chlo_.erase(connection_id);
}
if (!undecryptable_packets_.empty()) {
@@ -193,7 +195,7 @@ bool QuicBufferedPacketStore::ShouldBufferPacket(bool is_chlo) {
size_t num_connections_without_chlo =
undecryptable_packets_.size() - connections_with_chlo_.size();
bool reach_non_chlo_limit =
- FLAGS_quic_limit_num_new_sessions_per_epoll_loop &&
+ FLAGS_quic_reloadable_flag_quic_limit_num_new_sessions_per_epoll_loop &&
num_connections_without_chlo >= kMaxConnectionsWithoutCHLO;
return is_store_full || reach_non_chlo_limit;
@@ -207,7 +209,7 @@ QuicBufferedPacketStore::DeliverPacketsForNextConnection(
return std::list<BufferedPacket>();
}
*connection_id = connections_with_chlo_.front().first;
- connections_with_chlo_.erase(connections_with_chlo_.begin());
+ connections_with_chlo_.pop_front();
std::list<BufferedPacket> packets = DeliverPackets(*connection_id);
DCHECK(!packets.empty()) << "Try to deliver connectons without CHLO";
@@ -216,7 +218,7 @@ QuicBufferedPacketStore::DeliverPacketsForNextConnection(
bool QuicBufferedPacketStore::HasChloForConnection(
QuicConnectionId connection_id) {
- return base::ContainsKey(connections_with_chlo_, connection_id);
+ return ContainsKey(connections_with_chlo_, connection_id);
}
} // namespace net
diff --git a/chromium/net/quic/core/quic_buffered_packet_store.h b/chromium/net/quic/core/quic_buffered_packet_store.h
index fe8293ee429..1319a8ef086 100644
--- a/chromium/net/quic/core/quic_buffered_packet_store.h
+++ b/chromium/net/quic/core/quic_buffered_packet_store.h
@@ -2,17 +2,19 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#ifndef NET_QUIC_QUIC_BUFFERED_PACKET_STORE_H_
-#define NET_QUIC_QUIC_BUFFERED_PACKET_STORE_H_
+#ifndef NET_QUIC_CORE_QUIC_BUFFERED_PACKET_STORE_H_
+#define NET_QUIC_CORE_QUIC_BUFFERED_PACKET_STORE_H_
+
+#include <list>
-#include "net/base/ip_address.h"
#include "net/base/linked_hash_map.h"
-#include "net/base/net_export.h"
#include "net/quic/core/quic_alarm.h"
#include "net/quic/core/quic_alarm_factory.h"
-#include "net/quic/core/quic_clock.h"
-#include "net/quic/core/quic_protocol.h"
+#include "net/quic/core/quic_packets.h"
#include "net/quic/core/quic_time.h"
+#include "net/quic/platform/api/quic_clock.h"
+#include "net/quic/platform/api/quic_export.h"
+#include "net/quic/platform/api/quic_socket_address.h"
namespace net {
@@ -29,7 +31,7 @@ class QuicBufferedPacketStorePeer;
// of connections: connections with CHLO buffered and those without CHLO. The
// latter has its own upper limit along with the max number of connections this
// store can hold. The former pool can grow till this store is full.
-class NET_EXPORT_PRIVATE QuicBufferedPacketStore {
+class QUIC_EXPORT_PRIVATE QuicBufferedPacketStore {
public:
enum EnqueuePacketResult {
SUCCESS = 0,
@@ -38,10 +40,10 @@ class NET_EXPORT_PRIVATE QuicBufferedPacketStore {
};
// A packets with client/server address.
- struct NET_EXPORT_PRIVATE BufferedPacket {
+ struct QUIC_EXPORT_PRIVATE BufferedPacket {
BufferedPacket(std::unique_ptr<QuicReceivedPacket> packet,
- IPEndPoint server_address,
- IPEndPoint client_address);
+ QuicSocketAddress server_address,
+ QuicSocketAddress client_address);
BufferedPacket(BufferedPacket&& other);
BufferedPacket& operator=(BufferedPacket&& other);
@@ -49,12 +51,12 @@ class NET_EXPORT_PRIVATE QuicBufferedPacketStore {
~BufferedPacket();
std::unique_ptr<QuicReceivedPacket> packet;
- IPEndPoint server_address;
- IPEndPoint client_address;
+ QuicSocketAddress server_address;
+ QuicSocketAddress client_address;
};
// A queue of BufferedPackets for a connection.
- struct NET_EXPORT_PRIVATE BufferedPacketList {
+ struct QUIC_EXPORT_PRIVATE BufferedPacketList {
BufferedPacketList();
BufferedPacketList(BufferedPacketList&& other);
@@ -69,7 +71,7 @@ class NET_EXPORT_PRIVATE QuicBufferedPacketStore {
typedef linked_hash_map<QuicConnectionId, BufferedPacketList>
BufferedPacketMap;
- class NET_EXPORT_PRIVATE VisitorInterface {
+ class QUIC_EXPORT_PRIVATE VisitorInterface {
public:
virtual ~VisitorInterface() {}
@@ -91,8 +93,8 @@ class NET_EXPORT_PRIVATE QuicBufferedPacketStore {
// Adds a copy of packet into packet queue for given connection.
EnqueuePacketResult EnqueuePacket(QuicConnectionId connection_id,
const QuicReceivedPacket& packet,
- IPEndPoint server_address,
- IPEndPoint client_address,
+ QuicSocketAddress server_address,
+ QuicSocketAddress client_address,
bool is_chlo);
// Returns true if there are any packets buffered for |connection_id|.
@@ -115,9 +117,9 @@ class NET_EXPORT_PRIVATE QuicBufferedPacketStore {
// Delivers buffered packets for next connection with CHLO to open.
// Return connection id for next connection in |connection_id|
// and all buffered packets including CHLO.
- // The returned std::list should at least has one packet(CHLO) if
+ // The returned list should at least has one packet(CHLO) if
// store does have any connection to open. If no connection in the store has
- // received CHLO yet, empty std::list will be returned.
+ // received CHLO yet, empty list will be returned.
std::list<BufferedPacket> DeliverPacketsForNextConnection(
QuicConnectionId* connection_id);
@@ -158,4 +160,4 @@ class NET_EXPORT_PRIVATE QuicBufferedPacketStore {
} // namespace net
-#endif // NET_QUIC_QUIC_BUFFERED_PACKET_STORE_H_
+#endif // NET_QUIC_CORE_QUIC_BUFFERED_PACKET_STORE_H_
diff --git a/chromium/net/quic/core/quic_buffered_packet_store_test.cc b/chromium/net/quic/core/quic_buffered_packet_store_test.cc
index 5801bccd630..312f0bf3a36 100644
--- a/chromium/net/quic/core/quic_buffered_packet_store_test.cc
+++ b/chromium/net/quic/core/quic_buffered_packet_store_test.cc
@@ -8,6 +8,7 @@
#include <string>
#include "base/stl_util.h"
+#include "net/quic/core/quic_flags.h"
#include "net/quic/test_tools/mock_clock.h"
#include "net/quic/test_tools/quic_buffered_packet_store_peer.h"
#include "net/quic/test_tools/quic_test_utils.h"
@@ -51,8 +52,8 @@ class QuicBufferedPacketStoreTest : public ::testing::Test {
public:
QuicBufferedPacketStoreTest()
: store_(&visitor_, &clock_, &alarm_factory_),
- server_address_(Loopback6(), 65535),
- client_address_(Loopback6(), 65535),
+ server_address_(QuicIpAddress::Any6(), 65535),
+ client_address_(QuicIpAddress::Any6(), 65535),
packet_content_("some encrypted content"),
packet_time_(QuicTime::Zero() + QuicTime::Delta::FromMicroseconds(42)),
packet_(packet_content_.data(), packet_content_.size(), packet_time_) {}
@@ -63,8 +64,8 @@ class QuicBufferedPacketStoreTest : public ::testing::Test {
MockClock clock_;
MockAlarmFactory alarm_factory_;
QuicBufferedPacketStore store_;
- IPEndPoint server_address_;
- IPEndPoint client_address_;
+ QuicSocketAddress server_address_;
+ QuicSocketAddress client_address_;
string packet_content_;
QuicTime packet_time_;
QuicReceivedPacket packet_;
@@ -88,7 +89,7 @@ TEST_F(QuicBufferedPacketStoreTest, SimpleEnqueueAndDeliverPacket) {
}
TEST_F(QuicBufferedPacketStoreTest, DifferentPacketAddressOnOneConnection) {
- IPEndPoint addr_with_new_port(Loopback4(), 256);
+ QuicSocketAddress addr_with_new_port(QuicIpAddress::Any4(), 256);
QuicConnectionId connection_id = 1;
store_.EnqueuePacket(connection_id, packet_, server_address_, client_address_,
false);
@@ -126,7 +127,7 @@ TEST_F(QuicBufferedPacketStoreTest,
// buffered.
size_t num_packets = kDefaultMaxUndecryptablePackets + 1;
QuicConnectionId connection_id = 1;
- if (FLAGS_quic_limit_num_new_sessions_per_epoll_loop) {
+ if (FLAGS_quic_reloadable_flag_quic_limit_num_new_sessions_per_epoll_loop) {
// Arrived CHLO packet shouldn't affect how many non-CHLO pacekts store can
// keep.
EXPECT_EQ(QuicBufferedPacketStore::SUCCESS,
@@ -146,16 +147,19 @@ TEST_F(QuicBufferedPacketStoreTest,
// Only first |kDefaultMaxUndecryptablePackets| non-CHLO packets and CHLO are
// buffered.
- EXPECT_EQ(kDefaultMaxUndecryptablePackets +
- (FLAGS_quic_limit_num_new_sessions_per_epoll_loop ? 1 : 0),
- store_.DeliverPackets(connection_id).size());
+ EXPECT_EQ(
+ kDefaultMaxUndecryptablePackets +
+ (FLAGS_quic_reloadable_flag_quic_limit_num_new_sessions_per_epoll_loop
+ ? 1
+ : 0),
+ store_.DeliverPackets(connection_id).size());
}
TEST_F(QuicBufferedPacketStoreTest, ReachNonChloConnectionUpperLimit) {
// Tests that store can only keep early arrived packets for limited number of
// connections.
const size_t kNumConnections =
- (FLAGS_quic_limit_num_new_sessions_per_epoll_loop
+ (FLAGS_quic_reloadable_flag_quic_limit_num_new_sessions_per_epoll_loop
? kMaxConnectionsWithoutCHLO
: kDefaultMaxConnectionsInStore) +
1;
@@ -163,9 +167,10 @@ TEST_F(QuicBufferedPacketStoreTest, ReachNonChloConnectionUpperLimit) {
++connection_id) {
EnqueuePacketResult result = store_.EnqueuePacket(
connection_id, packet_, server_address_, client_address_, false);
- if (connection_id <= (FLAGS_quic_limit_num_new_sessions_per_epoll_loop
- ? kMaxConnectionsWithoutCHLO
- : kDefaultMaxConnectionsInStore)) {
+ if (connection_id <=
+ (FLAGS_quic_reloadable_flag_quic_limit_num_new_sessions_per_epoll_loop
+ ? kMaxConnectionsWithoutCHLO
+ : kDefaultMaxConnectionsInStore)) {
EXPECT_EQ(EnqueuePacketResult::SUCCESS, result);
} else {
EXPECT_EQ(EnqueuePacketResult::TOO_MANY_CONNECTIONS, result);
@@ -175,9 +180,10 @@ TEST_F(QuicBufferedPacketStoreTest, ReachNonChloConnectionUpperLimit) {
for (size_t connection_id = 1; connection_id <= kNumConnections;
++connection_id) {
std::list<BufferedPacket> queue = store_.DeliverPackets(connection_id);
- if (connection_id <= (FLAGS_quic_limit_num_new_sessions_per_epoll_loop
- ? kMaxConnectionsWithoutCHLO
- : kDefaultMaxConnectionsInStore)) {
+ if (connection_id <=
+ (FLAGS_quic_reloadable_flag_quic_limit_num_new_sessions_per_epoll_loop
+ ? kMaxConnectionsWithoutCHLO
+ : kDefaultMaxConnectionsInStore)) {
EXPECT_EQ(1u, queue.size());
} else {
EXPECT_EQ(0u, queue.size());
@@ -187,7 +193,7 @@ TEST_F(QuicBufferedPacketStoreTest, ReachNonChloConnectionUpperLimit) {
TEST_F(QuicBufferedPacketStoreTest,
FullStoreFailToBufferDataPacketOnNewConnection) {
- FLAGS_quic_limit_num_new_sessions_per_epoll_loop = true;
+ FLAGS_quic_reloadable_flag_quic_limit_num_new_sessions_per_epoll_loop = true;
// Send enough CHLOs so that store gets full before number of connections
// without CHLO reaches its upper limit.
size_t num_chlos =
@@ -213,7 +219,7 @@ TEST_F(QuicBufferedPacketStoreTest,
}
TEST_F(QuicBufferedPacketStoreTest, EnqueueChloOnTooManyDifferentConnections) {
- FLAGS_quic_limit_num_new_sessions_per_epoll_loop = true;
+ FLAGS_quic_reloadable_flag_quic_limit_num_new_sessions_per_epoll_loop = true;
// Buffer data packets on different connections upto limit.
for (QuicConnectionId conn_id = 1; conn_id <= kMaxConnectionsWithoutCHLO;
++conn_id) {
@@ -266,7 +272,7 @@ TEST_F(QuicBufferedPacketStoreTest, EnqueueChloOnTooManyDifferentConnections) {
}
TEST_F(QuicBufferedPacketStoreTest, PacketQueueExpiredBeforeDelivery1) {
- FLAGS_quic_limit_num_new_sessions_per_epoll_loop = false;
+ FLAGS_quic_reloadable_flag_quic_limit_num_new_sessions_per_epoll_loop = false;
QuicConnectionId connection_id = 1;
store_.EnqueuePacket(connection_id, packet_, server_address_, client_address_,
false);
@@ -275,7 +281,7 @@ TEST_F(QuicBufferedPacketStoreTest, PacketQueueExpiredBeforeDelivery1) {
QuicConnectionId connection_id2 = 2;
// Use different client address to differetiate packets from different
// connections.
- IPEndPoint another_client_address(Loopback4(), 255);
+ QuicSocketAddress another_client_address(QuicIpAddress::Any4(), 255);
store_.EnqueuePacket(connection_id2, packet_, server_address_,
another_client_address, false);
// Advance clock to the time when connection 1 expires.
@@ -318,11 +324,11 @@ TEST_F(QuicBufferedPacketStoreTest, PacketQueueExpiredBeforeDelivery1) {
// Tests that store expires long-staying connections appropriately for
// connections both with and without CHLOs.
TEST_F(QuicBufferedPacketStoreTest, PacketQueueExpiredBeforeDelivery2) {
- FLAGS_quic_limit_num_new_sessions_per_epoll_loop = true;
+ FLAGS_quic_reloadable_flag_quic_limit_num_new_sessions_per_epoll_loop = true;
QuicConnectionId connection_id = 1;
store_.EnqueuePacket(connection_id, packet_, server_address_, client_address_,
false);
- if (FLAGS_quic_limit_num_new_sessions_per_epoll_loop) {
+ if (FLAGS_quic_reloadable_flag_quic_limit_num_new_sessions_per_epoll_loop) {
EXPECT_EQ(EnqueuePacketResult::SUCCESS,
store_.EnqueuePacket(connection_id, packet_, server_address_,
client_address_, true));
@@ -337,7 +343,7 @@ TEST_F(QuicBufferedPacketStoreTest, PacketQueueExpiredBeforeDelivery2) {
QuicConnectionId connection_id3 = 3;
// Use different client address to differetiate packets from different
// connections.
- IPEndPoint another_client_address(Any4(), 255);
+ QuicSocketAddress another_client_address(QuicIpAddress::Any4(), 255);
store_.EnqueuePacket(connection_id3, packet_, server_address_,
another_client_address, true);
diff --git a/chromium/net/quic/core/quic_bug_tracker.h b/chromium/net/quic/core/quic_bug_tracker.h
deleted file mode 100644
index 280a537d0e7..00000000000
--- a/chromium/net/quic/core/quic_bug_tracker.h
+++ /dev/null
@@ -1,13 +0,0 @@
-// Copyright (c) 2016 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.
-#ifndef NET_QUIC_QUIC_BUG_TRACKER_H_
-#define NET_QUIC_QUIC_BUG_TRACKER_H_
-
-// For external QUIC, QUIC_BUG should be #defined to LOG(DFATAL) and
-// QUIC_BUG_IF(condition) to LOG_IF(DFATAL, condition) as client-side log rate
-// limiting is less important and chrome doesn't LOG_FIRST_N anyway.
-#define QUIC_BUG LOG(DFATAL)
-#define QUIC_BUG_IF(condition) LOG_IF(DFATAL, condition)
-
-#endif // NET_QUIC_QUIC_BUG_TRACKER_H_
diff --git a/chromium/net/quic/core/quic_client_promised_info.cc b/chromium/net/quic/core/quic_client_promised_info.cc
index 1648a2bc9d6..a08ff456065 100644
--- a/chromium/net/quic/core/quic_client_promised_info.cc
+++ b/chromium/net/quic/core/quic_client_promised_info.cc
@@ -4,8 +4,8 @@
#include "net/quic/core/quic_client_promised_info.h"
-#include "base/logging.h"
#include "net/quic/core/spdy_utils.h"
+#include "net/quic/platform/api/quic_logging.h"
using net::SpdyHeaderBlock;
using net::kPushPromiseTimeoutSecs;
@@ -24,13 +24,9 @@ QuicClientPromisedInfo::QuicClientPromisedInfo(QuicClientSessionBase* session,
QuicClientPromisedInfo::~QuicClientPromisedInfo() {}
void QuicClientPromisedInfo::CleanupAlarm::OnAlarm() {
- DVLOG(1) << "self GC alarm for stream " << promised_->id_;
+ QUIC_DVLOG(1) << "self GC alarm for stream " << promised_->id_;
promised_->session()->OnPushStreamTimedOut(promised_->id_);
- if (FLAGS_quic_send_push_stream_timed_out_error) {
- promised_->Reset(QUIC_PUSH_STREAM_TIMED_OUT);
- } else {
- promised_->Reset(QUIC_STREAM_CANCELLED);
- }
+ promised_->Reset(QUIC_PUSH_STREAM_TIMED_OUT);
}
void QuicClientPromisedInfo::Init() {
@@ -47,13 +43,14 @@ void QuicClientPromisedInfo::OnPromiseHeaders(const SpdyHeaderBlock& headers) {
SpdyHeaderBlock::const_iterator it = headers.find(":method");
DCHECK(it != headers.end());
if (!(it->second == "GET" || it->second == "HEAD")) {
- DVLOG(1) << "Promise for stream " << id_ << " has invalid method "
- << it->second;
+ QUIC_DVLOG(1) << "Promise for stream " << id_ << " has invalid method "
+ << it->second;
Reset(QUIC_INVALID_PROMISE_METHOD);
return;
}
if (!SpdyUtils::UrlIsValid(headers)) {
- DVLOG(1) << "Promise for stream " << id_ << " has invalid URL " << url_;
+ QUIC_DVLOG(1) << "Promise for stream " << id_ << " has invalid URL "
+ << url_;
Reset(QUIC_INVALID_PROMISE_URL);
return;
}
diff --git a/chromium/net/quic/core/quic_client_promised_info.h b/chromium/net/quic/core/quic_client_promised_info.h
index 1ae274e53e2..0f4bd8dcdf6 100644
--- a/chromium/net/quic/core/quic_client_promised_info.h
+++ b/chromium/net/quic/core/quic_client_promised_info.h
@@ -2,25 +2,23 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#ifndef NET_QUIC_QUIC_CLIENT_PROMISED_INFO_H_
-#define NET_QUIC_QUIC_CLIENT_PROMISED_INFO_H_
+#ifndef NET_QUIC_CORE_QUIC_CLIENT_PROMISED_INFO_H_
+#define NET_QUIC_CORE_QUIC_CLIENT_PROMISED_INFO_H_
-#include <sys/types.h>
#include <string>
+#include <sys/types.h>
-#include "net/base/net_export.h"
#include "net/quic/core/quic_alarm.h"
#include "net/quic/core/quic_client_push_promise_index.h"
#include "net/quic/core/quic_client_session_base.h"
-#include "net/quic/core/quic_protocol.h"
+#include "net/quic/core/quic_packets.h"
#include "net/quic/core/quic_spdy_stream.h"
+#include "net/quic/platform/api/quic_export.h"
#include "net/spdy/spdy_framer.h"
namespace net {
class QuicClientSessionBase;
-class QuicDataToResend;
-class QuicConnectionHelperInterface;
namespace test {
class QuicClientPromisedInfoPeer;
@@ -30,7 +28,7 @@ class QuicClientPromisedInfoPeer;
// stream from the time a PUSH_PROMISE is received until rendezvous
// between the promised response and the corresponding client request
// is complete.
-class NET_EXPORT_PRIVATE QuicClientPromisedInfo
+class QUIC_EXPORT_PRIVATE QuicClientPromisedInfo
: public QuicClientPushPromiseIndex::TryHandle {
public:
// Interface to QuicSpdyClientStream
@@ -113,4 +111,4 @@ class NET_EXPORT_PRIVATE QuicClientPromisedInfo
} // namespace net
-#endif // NET_QUIC_QUIC_CLIENT_PROMISED_INFO_H_
+#endif // NET_QUIC_CORE_QUIC_CLIENT_PROMISED_INFO_H_
diff --git a/chromium/net/quic/core/quic_client_promised_info_test.cc b/chromium/net/quic/core/quic_client_promised_info_test.cc
index 3eee2670d3c..4535720f7a9 100644
--- a/chromium/net/quic/core/quic_client_promised_info_test.cc
+++ b/chromium/net/quic/core/quic_client_promised_info_test.cc
@@ -8,6 +8,8 @@
#include "base/macros.h"
#include "net/quic/core/spdy_utils.h"
+#include "net/quic/platform/api/quic_logging.h"
+#include "net/quic/platform/api/quic_socket_address.h"
#include "net/quic/test_tools/crypto_test_utils.h"
#include "net/quic/test_tools/quic_client_promised_info_peer.h"
#include "net/test/gtest_util.h"
@@ -81,7 +83,7 @@ class QuicClientPromisedInfoTest : public ::testing::Test {
class StreamVisitor : public QuicSpdyClientStream::Visitor {
void OnClose(QuicSpdyStream* stream) override {
- DVLOG(1) << "stream " << stream->id();
+ QUIC_DVLOG(1) << "stream " << stream->id();
}
};
@@ -123,13 +125,8 @@ TEST_F(QuicClientPromisedInfoTest, PushPromiseCleanupAlarm) {
ASSERT_NE(promised, nullptr);
// Fire the alarm that will cancel the promised stream.
- if (FLAGS_quic_send_push_stream_timed_out_error) {
- EXPECT_CALL(*connection_,
- SendRstStream(promise_id_, QUIC_PUSH_STREAM_TIMED_OUT, 0));
- } else {
- EXPECT_CALL(*connection_,
- SendRstStream(promise_id_, QUIC_STREAM_CANCELLED, 0));
- }
+ EXPECT_CALL(*connection_,
+ SendRstStream(promise_id_, QUIC_PUSH_STREAM_TIMED_OUT, 0));
alarm_factory_.FireAlarm(QuicClientPromisedInfoPeer::GetAlarm(promised));
// Verify that the promise is gone after the alarm fires.
diff --git a/chromium/net/quic/core/quic_client_push_promise_index.h b/chromium/net/quic/core/quic_client_push_promise_index.h
index 2049aac843d..38dc1fc8218 100644
--- a/chromium/net/quic/core/quic_client_push_promise_index.h
+++ b/chromium/net/quic/core/quic_client_push_promise_index.h
@@ -2,14 +2,14 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#ifndef NET_QUIC_QUIC_CLIENT_PUSH_PROMISE_INDEX_H_
-#define NET_QUIC_QUIC_CLIENT_PUSH_PROMISE_INDEX_H_
+#ifndef NET_QUIC_CORE_QUIC_CLIENT_PUSH_PROMISE_INDEX_H_
+#define NET_QUIC_CORE_QUIC_CLIENT_PUSH_PROMISE_INDEX_H_
#include <string>
-#include "net/base/net_export.h"
#include "net/quic/core/quic_client_session_base.h"
#include "net/quic/core/quic_types.h"
+#include "net/quic/platform/api/quic_export.h"
namespace net {
@@ -19,11 +19,11 @@ namespace net {
// same browser users profile), since cross-origin pushes are allowed
// (subject to authority constraints).
-class NET_EXPORT_PRIVATE QuicClientPushPromiseIndex {
+class QUIC_EXPORT_PRIVATE QuicClientPushPromiseIndex {
public:
// Delegate is used to complete the rendezvous that began with
// |Try()|.
- class NET_EXPORT_PRIVATE Delegate {
+ class QUIC_EXPORT_PRIVATE Delegate {
public:
virtual ~Delegate() {}
@@ -47,7 +47,7 @@ class NET_EXPORT_PRIVATE QuicClientPushPromiseIndex {
virtual void OnRendezvousResult(QuicSpdyStream* stream) = 0;
};
- class NET_EXPORT_PRIVATE TryHandle {
+ class QUIC_EXPORT_PRIVATE TryHandle {
public:
// Cancel the request.
virtual void Cancel() = 0;
@@ -96,4 +96,4 @@ class NET_EXPORT_PRIVATE QuicClientPushPromiseIndex {
} // namespace net
-#endif // NET_QUIC_QUIC_CLIENT_PUSH_PROMISE_INDEX_H_
+#endif // NET_QUIC_CORE_QUIC_CLIENT_PUSH_PROMISE_INDEX_H_
diff --git a/chromium/net/quic/core/quic_client_session_base.cc b/chromium/net/quic/core/quic_client_session_base.cc
index ff61a9d0a46..a3533721ed7 100644
--- a/chromium/net/quic/core/quic_client_session_base.cc
+++ b/chromium/net/quic/core/quic_client_session_base.cc
@@ -7,6 +7,7 @@
#include "net/quic/core/quic_client_promised_info.h"
#include "net/quic/core/quic_flags.h"
#include "net/quic/core/spdy_utils.h"
+#include "net/quic/platform/api/quic_logging.h"
using base::StringPiece;
using std::string;
@@ -24,7 +25,7 @@ QuicClientSessionBase::QuicClientSessionBase(
QuicClientSessionBase::~QuicClientSessionBase() {
// all promised streams for this session
for (auto& it : promised_by_id_) {
- DVLOG(1) << "erase stream " << it.first << " url " << it.second->url();
+ QUIC_DVLOG(1) << "erase stream " << it.first << " url " << it.second->url();
push_promise_index_->promised_by_url()->erase(it.second->url());
}
delete connection();
@@ -35,7 +36,7 @@ void QuicClientSessionBase::OnConfigNegotiated() {
}
void QuicClientSessionBase::OnCryptoHandshakeEvent(CryptoHandshakeEvent event) {
- QuicSession::OnCryptoHandshakeEvent(event);
+ QuicSpdySession::OnCryptoHandshakeEvent(event);
}
void QuicClientSessionBase::OnInitialHeadersComplete(
@@ -86,13 +87,13 @@ bool QuicClientSessionBase::HandlePromised(QuicStreamId /* associated_id */,
if (IsClosedStream(id)) {
// There was a RST on the data stream already, perhaps
// QUIC_REFUSED_STREAM?
- DVLOG(1) << "Promise ignored for stream " << id
- << " that is already closed";
+ QUIC_DVLOG(1) << "Promise ignored for stream " << id
+ << " that is already closed";
return false;
}
if (push_promise_index_->promised_by_url()->size() >= get_max_promises()) {
- DVLOG(1) << "Too many promises, rejecting promise for stream " << id;
+ QUIC_DVLOG(1) << "Too many promises, rejecting promise for stream " << id;
ResetPromised(id, QUIC_REFUSED_STREAM);
return false;
}
@@ -100,8 +101,8 @@ bool QuicClientSessionBase::HandlePromised(QuicStreamId /* associated_id */,
const string url = SpdyUtils::GetUrlFromHeaderBlock(headers);
QuicClientPromisedInfo* old_promised = GetPromisedByUrl(url);
if (old_promised) {
- DVLOG(1) << "Promise for stream " << id << " is duplicate URL " << url
- << " of previous promise for stream " << old_promised->id();
+ QUIC_DVLOG(1) << "Promise for stream " << id << " is duplicate URL " << url
+ << " of previous promise for stream " << old_promised->id();
ResetPromised(id, QUIC_DUPLICATE_PROMISE_URL);
return false;
}
@@ -116,7 +117,7 @@ bool QuicClientSessionBase::HandlePromised(QuicStreamId /* associated_id */,
QuicClientPromisedInfo* promised = new QuicClientPromisedInfo(this, id, url);
std::unique_ptr<QuicClientPromisedInfo> promised_owner(promised);
promised->Init();
- DVLOG(1) << "stream " << id << " emplace url " << url;
+ QUIC_DVLOG(1) << "stream " << id << " emplace url " << url;
(*push_promise_index_->promised_by_url())[url] = promised;
promised_by_id_[id] = std::move(promised_owner);
promised->OnPromiseHeaders(headers);
@@ -166,9 +167,6 @@ void QuicClientSessionBase::ResetPromised(QuicStreamId id,
SendRstStream(id, error_code, 0);
if (!IsOpenStream(id)) {
MaybeIncreaseLargestPeerStreamId(id);
- if (!FLAGS_quic_bugfix_reset_promised) {
- InsertLocallyClosedStreamsHighestOffset(id, 0);
- }
}
}
diff --git a/chromium/net/quic/core/quic_client_session_base.h b/chromium/net/quic/core/quic_client_session_base.h
index 32d1ba860c4..76aa43744b6 100644
--- a/chromium/net/quic/core/quic_client_session_base.h
+++ b/chromium/net/quic/core/quic_client_session_base.h
@@ -2,15 +2,15 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#ifndef NET_QUIC_QUIC_CLIENT_SESSION_BASE_H_
-#define NET_QUIC_QUIC_CLIENT_SESSION_BASE_H_
+#ifndef NET_QUIC_CORE_QUIC_CLIENT_SESSION_BASE_H_
+#define NET_QUIC_CORE_QUIC_CLIENT_SESSION_BASE_H_
#include <string>
#include "base/macros.h"
-#include "net/base/net_export.h"
#include "net/quic/core/quic_crypto_client_stream.h"
#include "net/quic/core/quic_spdy_session.h"
+#include "net/quic/platform/api/quic_export.h"
namespace net {
@@ -32,7 +32,7 @@ using QuicPromisedByUrlMap =
const int64_t kPushPromiseTimeoutSecs = 60;
// Base class for all client-specific QuicSession subclasses.
-class NET_EXPORT_PRIVATE QuicClientSessionBase
+class QUIC_EXPORT_PRIVATE QuicClientSessionBase
: public QuicSpdySession,
public QuicCryptoClientStream::ProofHandler {
public:
@@ -135,4 +135,4 @@ class NET_EXPORT_PRIVATE QuicClientSessionBase
} // namespace net
-#endif // NET_QUIC_QUIC_CLIENT_SESSION_BASE_H_
+#endif // NET_QUIC_CORE_QUIC_CLIENT_SESSION_BASE_H_
diff --git a/chromium/net/quic/core/quic_config.cc b/chromium/net/quic/core/quic_config.cc
index 5a3bccbd90d..b654a93831a 100644
--- a/chromium/net/quic/core/quic_config.cc
+++ b/chromium/net/quic/core/quic_config.cc
@@ -6,14 +6,14 @@
#include <algorithm>
-#include "base/logging.h"
#include "net/quic/core/crypto/crypto_handshake_message.h"
#include "net/quic/core/crypto/crypto_protocol.h"
-#include "net/quic/core/quic_bug_tracker.h"
+#include "net/quic/core/quic_flags.h"
#include "net/quic/core/quic_socket_address_coder.h"
#include "net/quic/core/quic_utils.h"
+#include "net/quic/platform/api/quic_bug_tracker.h"
+#include "net/quic/platform/api/quic_logging.h"
-using std::min;
using std::string;
namespace net {
@@ -32,7 +32,7 @@ QuicErrorCode ReadUint32(const CryptoHandshakeMessage& msg,
switch (error) {
case QUIC_CRYPTO_MESSAGE_PARAMETER_NOT_FOUND:
if (presence == PRESENCE_REQUIRED) {
- *error_details = "Missing " + QuicUtils::TagToString(tag);
+ *error_details = "Missing " + QuicTagToString(tag);
break;
}
error = QUIC_NO_ERROR;
@@ -41,7 +41,7 @@ QuicErrorCode ReadUint32(const CryptoHandshakeMessage& msg,
case QUIC_NO_ERROR:
break;
default:
- *error_details = "Bad " + QuicUtils::TagToString(tag);
+ *error_details = "Bad " + QuicTagToString(tag);
break;
}
return error;
@@ -104,98 +104,12 @@ QuicErrorCode QuicNegotiableUint32::ProcessPeerHello(
return error;
}
if (hello_type == SERVER && value > max_value_) {
- *error_details =
- "Invalid value received for " + QuicUtils::TagToString(tag_);
+ *error_details = "Invalid value received for " + QuicTagToString(tag_);
return QUIC_INVALID_NEGOTIATED_VALUE;
}
set_negotiated(true);
- negotiated_value_ = min(value, max_value_);
- return QUIC_NO_ERROR;
-}
-
-QuicNegotiableTag::QuicNegotiableTag(QuicTag tag, QuicConfigPresence presence)
- : QuicNegotiableValue(tag, presence),
- negotiated_tag_(0),
- default_value_(0) {}
-
-QuicNegotiableTag::~QuicNegotiableTag() {}
-
-void QuicNegotiableTag::set(const QuicTagVector& possible,
- QuicTag default_value) {
- DCHECK(ContainsQuicTag(possible, default_value));
- possible_values_ = possible;
- default_value_ = default_value;
-}
-
-void QuicNegotiableTag::ToHandshakeMessage(CryptoHandshakeMessage* out) const {
- if (negotiated()) {
- // Because of the way we serialize and parse handshake messages we can
- // serialize this as value and still parse it as a vector.
- out->SetValue(tag_, negotiated_tag_);
- } else {
- out->SetVector(tag_, possible_values_);
- }
-}
-
-QuicErrorCode QuicNegotiableTag::ReadVector(const CryptoHandshakeMessage& msg,
- const QuicTag** out,
- size_t* out_length,
- string* error_details) const {
- DCHECK(error_details != nullptr);
- QuicErrorCode error = msg.GetTaglist(tag_, out, out_length);
- switch (error) {
- case QUIC_CRYPTO_MESSAGE_PARAMETER_NOT_FOUND:
- if (presence_ == PRESENCE_REQUIRED) {
- *error_details = "Missing " + QuicUtils::TagToString(tag_);
- break;
- }
- error = QUIC_NO_ERROR;
- *out_length = 1;
- *out = &default_value_;
-
- case QUIC_NO_ERROR:
- break;
- default:
- *error_details = "Bad " + QuicUtils::TagToString(tag_);
- break;
- }
- return error;
-}
-
-QuicErrorCode QuicNegotiableTag::ProcessPeerHello(
- const CryptoHandshakeMessage& peer_hello,
- HelloType hello_type,
- string* error_details) {
- DCHECK(!negotiated());
- DCHECK(error_details != nullptr);
- const QuicTag* received_tags;
- size_t received_tags_length;
- QuicErrorCode error = ReadVector(peer_hello, &received_tags,
- &received_tags_length, error_details);
- if (error != QUIC_NO_ERROR) {
- return error;
- }
-
- if (hello_type == SERVER) {
- if (received_tags_length != 1 ||
- !ContainsQuicTag(possible_values_, *received_tags)) {
- *error_details = "Invalid " + QuicUtils::TagToString(tag_);
- return QUIC_INVALID_NEGOTIATED_VALUE;
- }
- negotiated_tag_ = *received_tags;
- } else {
- QuicTag negotiated_tag;
- if (!QuicUtils::FindMutualTag(
- possible_values_, received_tags, received_tags_length,
- QuicUtils::LOCAL_PRIORITY, &negotiated_tag, nullptr)) {
- *error_details = "Unsupported " + QuicUtils::TagToString(tag_);
- return QUIC_CRYPTO_MESSAGE_PARAMETER_NO_OVERLAP;
- }
- negotiated_tag_ = negotiated_tag;
- }
-
- set_negotiated(true);
+ negotiated_value_ = std::min(value, max_value_);
return QUIC_NO_ERROR;
}
@@ -211,7 +125,7 @@ bool QuicFixedUint32::HasSendValue() const {
uint32_t QuicFixedUint32::GetSendValue() const {
QUIC_BUG_IF(!has_send_value_) << "No send value to get for tag:"
- << QuicUtils::TagToString(tag_);
+ << QuicTagToString(tag_);
return send_value_;
}
@@ -226,7 +140,7 @@ bool QuicFixedUint32::HasReceivedValue() const {
uint32_t QuicFixedUint32::GetReceivedValue() const {
QUIC_BUG_IF(!has_receive_value_) << "No receive value to get for tag:"
- << QuicUtils::TagToString(tag_);
+ << QuicTagToString(tag_);
return receive_value_;
}
@@ -252,13 +166,13 @@ QuicErrorCode QuicFixedUint32::ProcessPeerHello(
if (presence_ == PRESENCE_OPTIONAL) {
return QUIC_NO_ERROR;
}
- *error_details = "Missing " + QuicUtils::TagToString(tag_);
+ *error_details = "Missing " + QuicTagToString(tag_);
break;
case QUIC_NO_ERROR:
has_receive_value_ = true;
break;
default:
- *error_details = "Bad " + QuicUtils::TagToString(tag_);
+ *error_details = "Bad " + QuicTagToString(tag_);
break;
}
return error;
@@ -281,7 +195,7 @@ bool QuicFixedTagVector::HasSendValues() const {
QuicTagVector QuicFixedTagVector::GetSendValues() const {
QUIC_BUG_IF(!has_send_values_) << "No send values to get for tag:"
- << QuicUtils::TagToString(tag_);
+ << QuicTagToString(tag_);
return send_values_;
}
@@ -296,7 +210,7 @@ bool QuicFixedTagVector::HasReceivedValues() const {
QuicTagVector QuicFixedTagVector::GetReceivedValues() const {
QUIC_BUG_IF(!has_receive_values_) << "No receive value to get for tag:"
- << QuicUtils::TagToString(tag_);
+ << QuicTagToString(tag_);
return receive_values_;
}
@@ -325,61 +239,61 @@ QuicErrorCode QuicFixedTagVector::ProcessPeerHello(
if (presence_ == PRESENCE_OPTIONAL) {
return QUIC_NO_ERROR;
}
- *error_details = "Missing " + QuicUtils::TagToString(tag_);
+ *error_details = "Missing " + QuicTagToString(tag_);
break;
case QUIC_NO_ERROR:
- DVLOG(1) << "Received Connection Option tags from receiver.";
+ QUIC_DVLOG(1) << "Received Connection Option tags from receiver.";
has_receive_values_ = true;
for (size_t i = 0; i < received_tags_length; ++i) {
receive_values_.push_back(received_tags[i]);
}
break;
default:
- *error_details = "Bad " + QuicUtils::TagToString(tag_);
+ *error_details = "Bad " + QuicTagToString(tag_);
break;
}
return error;
}
-QuicFixedIPEndPoint::QuicFixedIPEndPoint(QuicTag tag,
- QuicConfigPresence presence)
+QuicFixedSocketAddress::QuicFixedSocketAddress(QuicTag tag,
+ QuicConfigPresence presence)
: QuicConfigValue(tag, presence),
has_send_value_(false),
has_receive_value_(false) {}
-QuicFixedIPEndPoint::~QuicFixedIPEndPoint() {}
+QuicFixedSocketAddress::~QuicFixedSocketAddress() {}
-bool QuicFixedIPEndPoint::HasSendValue() const {
+bool QuicFixedSocketAddress::HasSendValue() const {
return has_send_value_;
}
-const IPEndPoint& QuicFixedIPEndPoint::GetSendValue() const {
+const QuicSocketAddress& QuicFixedSocketAddress::GetSendValue() const {
QUIC_BUG_IF(!has_send_value_) << "No send value to get for tag:"
- << QuicUtils::TagToString(tag_);
+ << QuicTagToString(tag_);
return send_value_;
}
-void QuicFixedIPEndPoint::SetSendValue(const IPEndPoint& value) {
+void QuicFixedSocketAddress::SetSendValue(const QuicSocketAddress& value) {
has_send_value_ = true;
send_value_ = value;
}
-bool QuicFixedIPEndPoint::HasReceivedValue() const {
+bool QuicFixedSocketAddress::HasReceivedValue() const {
return has_receive_value_;
}
-const IPEndPoint& QuicFixedIPEndPoint::GetReceivedValue() const {
+const QuicSocketAddress& QuicFixedSocketAddress::GetReceivedValue() const {
QUIC_BUG_IF(!has_receive_value_) << "No receive value to get for tag:"
- << QuicUtils::TagToString(tag_);
+ << QuicTagToString(tag_);
return receive_value_;
}
-void QuicFixedIPEndPoint::SetReceivedValue(const IPEndPoint& value) {
+void QuicFixedSocketAddress::SetReceivedValue(const QuicSocketAddress& value) {
has_receive_value_ = true;
receive_value_ = value;
}
-void QuicFixedIPEndPoint::ToHandshakeMessage(
+void QuicFixedSocketAddress::ToHandshakeMessage(
CryptoHandshakeMessage* out) const {
if (has_send_value_) {
QuicSocketAddressCoder address_coder(send_value_);
@@ -387,20 +301,21 @@ void QuicFixedIPEndPoint::ToHandshakeMessage(
}
}
-QuicErrorCode QuicFixedIPEndPoint::ProcessPeerHello(
+QuicErrorCode QuicFixedSocketAddress::ProcessPeerHello(
const CryptoHandshakeMessage& peer_hello,
HelloType hello_type,
string* error_details) {
base::StringPiece address;
if (!peer_hello.GetStringPiece(tag_, &address)) {
if (presence_ == PRESENCE_REQUIRED) {
- *error_details = "Missing " + QuicUtils::TagToString(tag_);
+ *error_details = "Missing " + QuicTagToString(tag_);
return QUIC_CRYPTO_MESSAGE_PARAMETER_NOT_FOUND;
}
} else {
QuicSocketAddressCoder address_coder;
if (address_coder.Decode(address.data(), address.length())) {
- SetReceivedValue(IPEndPoint(address_coder.ip(), address_coder.port()));
+ SetReceivedValue(
+ QuicSocketAddress(address_coder.ip(), address_coder.port()));
}
}
return QUIC_NO_ERROR;
@@ -411,6 +326,7 @@ QuicConfig::QuicConfig()
max_idle_time_before_crypto_handshake_(QuicTime::Delta::Zero()),
max_undecryptable_packets_(0),
connection_options_(kCOPT, PRESENCE_OPTIONAL),
+ client_connection_options_(kCLOP, PRESENCE_OPTIONAL),
idle_network_timeout_seconds_(kICSL, PRESENCE_REQUIRED),
silent_close_(kSCLS, PRESENCE_OPTIONAL),
max_streams_per_connection_(kMSPC, PRESENCE_OPTIONAL),
@@ -423,7 +339,8 @@ QuicConfig::QuicConfig()
multipath_enabled_(kMPTH, PRESENCE_OPTIONAL),
connection_migration_disabled_(kNCMR, PRESENCE_OPTIONAL),
alternate_server_address_(kASAD, PRESENCE_OPTIONAL),
- force_hol_blocking_(kFHL2, PRESENCE_OPTIONAL) {
+ force_hol_blocking_(kFHL2, PRESENCE_OPTIONAL),
+ support_max_header_list_size_(kSMHL, PRESENCE_OPTIONAL) {
SetDefaults();
}
@@ -477,6 +394,23 @@ bool QuicConfig::HasClientSentConnectionOption(QuicTag tag,
return false;
}
+void QuicConfig::SetClientConnectionOptions(
+ const QuicTagVector& client_connection_options) {
+ client_connection_options_.SetSendValues(client_connection_options);
+}
+
+bool QuicConfig::HasClientRequestedIndependentOption(
+ QuicTag tag,
+ Perspective perspective) const {
+ if (perspective == Perspective::IS_SERVER) {
+ return (HasReceivedConnectionOptions() &&
+ ContainsQuicTag(ReceivedConnectionOptions(), tag));
+ }
+
+ return (client_connection_options_.HasSendValues() &&
+ ContainsQuicTag(client_connection_options_.GetSendValues(), tag));
+}
+
void QuicConfig::SetIdleNetworkTimeout(
QuicTime::Delta max_idle_network_timeout,
QuicTime::Delta default_idle_network_timeout) {
@@ -637,7 +571,7 @@ bool QuicConfig::DisableConnectionMigration() const {
}
void QuicConfig::SetAlternateServerAddressToSend(
- const IPEndPoint& alternate_server_address) {
+ const QuicSocketAddress& alternate_server_address) {
alternate_server_address_.SetSendValue(alternate_server_address);
}
@@ -645,7 +579,7 @@ bool QuicConfig::HasReceivedAlternateServerAddress() const {
return alternate_server_address_.HasReceivedValue();
}
-const IPEndPoint& QuicConfig::ReceivedAlternateServerAddress() const {
+const QuicSocketAddress& QuicConfig::ReceivedAlternateServerAddress() const {
return alternate_server_address_.GetReceivedValue();
}
@@ -661,6 +595,14 @@ bool QuicConfig::ForceHolBlocking(Perspective perspective) const {
}
}
+void QuicConfig::SetSupportMaxHeaderListSize() {
+ support_max_header_list_size_.SetSendValue(1);
+}
+
+bool QuicConfig::SupportMaxHeaderListSize() const {
+ return support_max_header_list_size_.HasReceivedValue();
+}
+
bool QuicConfig::negotiated() const {
// TODO(ianswett): Add the negotiated parameters once and iterate over all
// of them in negotiated, ToHandshakeMessage, ProcessClientHello, and
@@ -684,6 +626,9 @@ void QuicConfig::SetDefaults() {
SetInitialStreamFlowControlWindowToSend(kMinimumFlowControlSendWindow);
SetInitialSessionFlowControlWindowToSend(kMinimumFlowControlSendWindow);
+ if (FLAGS_quic_reloadable_flag_quic_send_max_header_list_size) {
+ SetSupportMaxHeaderListSize();
+ }
}
void QuicConfig::ToHandshakeMessage(CryptoHandshakeMessage* out) const {
@@ -700,6 +645,7 @@ void QuicConfig::ToHandshakeMessage(CryptoHandshakeMessage* out) const {
connection_options_.ToHandshakeMessage(out);
alternate_server_address_.ToHandshakeMessage(out);
force_hol_blocking_.ToHandshakeMessage(out);
+ support_max_header_list_size_.ToHandshakeMessage(out);
}
QuicErrorCode QuicConfig::ProcessPeerHello(
@@ -761,6 +707,10 @@ QuicErrorCode QuicConfig::ProcessPeerHello(
error = force_hol_blocking_.ProcessPeerHello(peer_hello, hello_type,
error_details);
}
+ if (error == QUIC_NO_ERROR) {
+ error = support_max_header_list_size_.ProcessPeerHello(
+ peer_hello, hello_type, error_details);
+ }
return error;
}
diff --git a/chromium/net/quic/core/quic_config.h b/chromium/net/quic/core/quic_config.h
index 4f7907465ce..e2388108936 100644
--- a/chromium/net/quic/core/quic_config.h
+++ b/chromium/net/quic/core/quic_config.h
@@ -2,17 +2,17 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#ifndef NET_QUIC_QUIC_CONFIG_H_
-#define NET_QUIC_QUIC_CONFIG_H_
+#ifndef NET_QUIC_CORE_QUIC_CONFIG_H_
+#define NET_QUIC_CORE_QUIC_CONFIG_H_
#include <stddef.h>
#include <stdint.h>
#include <string>
-#include "net/base/net_export.h"
-#include "net/quic/core/quic_protocol.h"
+#include "net/quic/core/quic_packets.h"
#include "net/quic/core/quic_time.h"
+#include "net/quic/platform/api/quic_export.h"
namespace net {
@@ -41,7 +41,7 @@ enum HelloType {
// An abstract base class that stores a value that can be sent in CHLO/SHLO
// message. These values can be OPTIONAL or REQUIRED, depending on |presence_|.
-class NET_EXPORT_PRIVATE QuicConfigValue {
+class QUIC_EXPORT_PRIVATE QuicConfigValue {
public:
QuicConfigValue(QuicTag tag, QuicConfigPresence presence);
virtual ~QuicConfigValue();
@@ -61,7 +61,7 @@ class NET_EXPORT_PRIVATE QuicConfigValue {
const QuicConfigPresence presence_;
};
-class NET_EXPORT_PRIVATE QuicNegotiableValue : public QuicConfigValue {
+class QUIC_EXPORT_PRIVATE QuicNegotiableValue : public QuicConfigValue {
public:
QuicNegotiableValue(QuicTag tag, QuicConfigPresence presence);
~QuicNegotiableValue() override;
@@ -75,7 +75,7 @@ class NET_EXPORT_PRIVATE QuicNegotiableValue : public QuicConfigValue {
bool negotiated_;
};
-class NET_EXPORT_PRIVATE QuicNegotiableUint32 : public QuicNegotiableValue {
+class QUIC_EXPORT_PRIVATE QuicNegotiableUint32 : public QuicNegotiableValue {
// TODO(fayang): some negotiated values use uint32 as bool (e.g., silent
// close). Consider adding a QuicNegotiableBool type.
public:
@@ -114,44 +114,8 @@ class NET_EXPORT_PRIVATE QuicNegotiableUint32 : public QuicNegotiableValue {
uint32_t negotiated_value_;
};
-class NET_EXPORT_PRIVATE QuicNegotiableTag : public QuicNegotiableValue {
- public:
- QuicNegotiableTag(QuicTag name, QuicConfigPresence presence);
- ~QuicNegotiableTag() override;
-
- // Sets the possible values that |negotiated_tag_| can take after negotiation
- // and the default value that |negotiated_tag_| takes if OPTIONAL and *HLO
- // msg doesn't contain tag |name_|.
- void set(const QuicTagVector& possible_values, QuicTag default_value);
-
- // Serialises |name_| and vector (either possible or negotiated) to |out|. If
- // |negotiated_| is true then |negotiated_tag_| is serialised, otherwise
- // |possible_values_| is serialised.
- void ToHandshakeMessage(CryptoHandshakeMessage* out) const override;
-
- // Selects the tag common to both tags in |client_hello| for |name_| and
- // |possible_values_| with preference to tag in |possible_values_|. The
- // selected tag is set as |negotiated_tag_|.
- QuicErrorCode ProcessPeerHello(const CryptoHandshakeMessage& peer_hello,
- HelloType hello_type,
- std::string* error_details) override;
-
- private:
- // Reads the vector corresponding to |name_| from |msg| into |out|. If the
- // |name_| is absent in |msg| and |presence_| is set to OPTIONAL |out| is set
- // to |possible_values_|.
- QuicErrorCode ReadVector(const CryptoHandshakeMessage& msg,
- const QuicTag** out,
- size_t* out_length,
- std::string* error_details) const;
-
- QuicTag negotiated_tag_;
- QuicTagVector possible_values_;
- QuicTag default_value_;
-};
-
// Stores uint32_t from CHLO or SHLO messages that are not negotiated.
-class NET_EXPORT_PRIVATE QuicFixedUint32 : public QuicConfigValue {
+class QUIC_EXPORT_PRIVATE QuicFixedUint32 : public QuicConfigValue {
public:
QuicFixedUint32(QuicTag name, QuicConfigPresence presence);
~QuicFixedUint32() override;
@@ -184,7 +148,7 @@ class NET_EXPORT_PRIVATE QuicFixedUint32 : public QuicConfigValue {
};
// Stores tag from CHLO or SHLO messages that are not negotiated.
-class NET_EXPORT_PRIVATE QuicFixedTagVector : public QuicConfigValue {
+class QUIC_EXPORT_PRIVATE QuicFixedTagVector : public QuicConfigValue {
public:
QuicFixedTagVector(QuicTag name, QuicConfigPresence presence);
QuicFixedTagVector(const QuicFixedTagVector& other);
@@ -219,23 +183,23 @@ class NET_EXPORT_PRIVATE QuicFixedTagVector : public QuicConfigValue {
bool has_receive_values_;
};
-// Stores IPEndPoint from CHLO or SHLO messages that are not negotiated.
-class NET_EXPORT_PRIVATE QuicFixedIPEndPoint : public QuicConfigValue {
+// Stores QuicSocketAddress from CHLO or SHLO messages that are not negotiated.
+class QUIC_EXPORT_PRIVATE QuicFixedSocketAddress : public QuicConfigValue {
public:
- QuicFixedIPEndPoint(QuicTag tag, QuicConfigPresence presence);
- ~QuicFixedIPEndPoint() override;
+ QuicFixedSocketAddress(QuicTag tag, QuicConfigPresence presence);
+ ~QuicFixedSocketAddress() override;
bool HasSendValue() const;
- const IPEndPoint& GetSendValue() const;
+ const QuicSocketAddress& GetSendValue() const;
- void SetSendValue(const IPEndPoint& value);
+ void SetSendValue(const QuicSocketAddress& value);
bool HasReceivedValue() const;
- const IPEndPoint& GetReceivedValue() const;
+ const QuicSocketAddress& GetReceivedValue() const;
- void SetReceivedValue(const IPEndPoint& value);
+ void SetReceivedValue(const QuicSocketAddress& value);
void ToHandshakeMessage(CryptoHandshakeMessage* out) const override;
@@ -244,15 +208,15 @@ class NET_EXPORT_PRIVATE QuicFixedIPEndPoint : public QuicConfigValue {
std::string* error_details) override;
private:
- IPEndPoint send_value_;
+ QuicSocketAddress send_value_;
bool has_send_value_;
- IPEndPoint receive_value_;
+ QuicSocketAddress receive_value_;
bool has_receive_value_;
};
// QuicConfig contains non-crypto configuration options that are negotiated in
// the crypto handshake.
-class NET_EXPORT_PRIVATE QuicConfig {
+class QUIC_EXPORT_PRIVATE QuicConfig {
public:
QuicConfig();
QuicConfig(const QuicConfig& other);
@@ -277,9 +241,19 @@ class NET_EXPORT_PRIVATE QuicConfig {
// Returns true if the client is sending or the server has received a
// connection option.
+ // TODO(ianswett): Rename to HasClientRequestedSharedOption
bool HasClientSentConnectionOption(QuicTag tag,
Perspective perspective) const;
+ void SetClientConnectionOptions(
+ const QuicTagVector& client_connection_options);
+
+ // Returns true if the client has requested the specified connection option.
+ // Checks the client connection options if the |perspective| is client and
+ // connection options if the |perspective| is the server.
+ bool HasClientRequestedIndependentOption(QuicTag tag,
+ Perspective perspective) const;
+
void SetIdleNetworkTimeout(QuicTime::Delta max_idle_network_timeout,
QuicTime::Delta default_idle_network_timeout);
@@ -387,16 +361,20 @@ class NET_EXPORT_PRIVATE QuicConfig {
bool DisableConnectionMigration() const;
void SetAlternateServerAddressToSend(
- const IPEndPoint& alternate_server_address);
+ const QuicSocketAddress& alternate_server_address);
bool HasReceivedAlternateServerAddress() const;
- const IPEndPoint& ReceivedAlternateServerAddress() const;
+ const QuicSocketAddress& ReceivedAlternateServerAddress() const;
void SetForceHolBlocking();
bool ForceHolBlocking(Perspective perspective) const;
+ void SetSupportMaxHeaderListSize();
+
+ bool SupportMaxHeaderListSize() const;
+
bool negotiated() const;
// ToHandshakeMessage serialises the settings in this object as a series of
@@ -423,8 +401,11 @@ class NET_EXPORT_PRIVATE QuicConfig {
// Maximum number of undecryptable packets stored before CHLO/SHLO.
size_t max_undecryptable_packets_;
- // Connection options.
+ // Connection options which affect the server side. May also affect the
+ // client side in cases when identical behavior is desirable.
QuicFixedTagVector connection_options_;
+ // Connection options which only affect the client side.
+ QuicFixedTagVector client_connection_options_;
// Idle network timeout in seconds.
QuicNegotiableUint32 idle_network_timeout_seconds_;
// Whether to use silent close. Defaults to 0 (false) and is otherwise true.
@@ -455,12 +436,15 @@ class NET_EXPORT_PRIVATE QuicConfig {
QuicFixedUint32 connection_migration_disabled_;
// An alternate server address the client could connect to.
- QuicFixedIPEndPoint alternate_server_address_;
+ QuicFixedSocketAddress alternate_server_address_;
// Force HOL blocking for measurement purposes.
QuicFixedUint32 force_hol_blocking_;
+
+ // Whether support HTTP/2 SETTINGS_MAX_HEADER_LIST_SIZE SETTINGS frame.
+ QuicFixedUint32 support_max_header_list_size_;
};
} // namespace net
-#endif // NET_QUIC_QUIC_CONFIG_H_
+#endif // NET_QUIC_CORE_QUIC_CONFIG_H_
diff --git a/chromium/net/quic/core/quic_config_test.cc b/chromium/net/quic/core/quic_config_test.cc
index 0125dab6962..9cf0f334df8 100644
--- a/chromium/net/quic/core/quic_config_test.cc
+++ b/chromium/net/quic/core/quic_config_test.cc
@@ -7,7 +7,7 @@
#include "net/quic/core/crypto/crypto_handshake_message.h"
#include "net/quic/core/crypto/crypto_protocol.h"
#include "net/quic/core/quic_flags.h"
-#include "net/quic/core/quic_protocol.h"
+#include "net/quic/core/quic_packets.h"
#include "net/quic/core/quic_time.h"
#include "net/quic/core/quic_utils.h"
#include "net/quic/test_tools/quic_config_peer.h"
@@ -114,7 +114,9 @@ TEST_F(QuicConfigTest, ProcessClientHello) {
}
TEST_F(QuicConfigTest, ProcessServerHello) {
- const IPEndPoint kTestServerAddress(IPAddress(127, 0, 3, 1), 1234);
+ QuicIpAddress host;
+ host.FromString("127.0.3.1");
+ const QuicSocketAddress kTestServerAddress = QuicSocketAddress(host, 1234);
QuicConfig server_config;
QuicTagVector cgst;
cgst.push_back(kQBIC);
@@ -250,6 +252,56 @@ TEST_F(QuicConfigTest, HasClientSentConnectionOption) {
config_.HasClientSentConnectionOption(kTBBR, Perspective::IS_SERVER));
}
+TEST_F(QuicConfigTest, DontSendClientConnectionOptions) {
+ QuicConfig client_config;
+ QuicTagVector copt;
+ copt.push_back(kTBBR);
+ client_config.SetClientConnectionOptions(copt);
+
+ CryptoHandshakeMessage msg;
+ client_config.ToHandshakeMessage(&msg);
+
+ string error_details;
+ const QuicErrorCode error =
+ config_.ProcessPeerHello(msg, CLIENT, &error_details);
+ EXPECT_EQ(QUIC_NO_ERROR, error);
+ EXPECT_TRUE(config_.negotiated());
+
+ EXPECT_FALSE(config_.HasReceivedConnectionOptions());
+}
+
+TEST_F(QuicConfigTest, HasClientRequestedIndependentOption) {
+ QuicConfig client_config;
+ QuicTagVector client_opt;
+ client_opt.push_back(kRENO);
+ QuicTagVector copt;
+ copt.push_back(kTBBR);
+ client_config.SetClientConnectionOptions(client_opt);
+ client_config.SetConnectionOptionsToSend(copt);
+ EXPECT_TRUE(client_config.HasClientSentConnectionOption(
+ kTBBR, Perspective::IS_CLIENT));
+ EXPECT_TRUE(client_config.HasClientRequestedIndependentOption(
+ kRENO, Perspective::IS_CLIENT));
+ EXPECT_FALSE(client_config.HasClientRequestedIndependentOption(
+ kTBBR, Perspective::IS_CLIENT));
+
+ CryptoHandshakeMessage msg;
+ client_config.ToHandshakeMessage(&msg);
+
+ string error_details;
+ const QuicErrorCode error =
+ config_.ProcessPeerHello(msg, CLIENT, &error_details);
+ EXPECT_EQ(QUIC_NO_ERROR, error);
+ EXPECT_TRUE(config_.negotiated());
+
+ EXPECT_TRUE(config_.HasReceivedConnectionOptions());
+ EXPECT_EQ(1u, config_.ReceivedConnectionOptions().size());
+ EXPECT_FALSE(config_.HasClientRequestedIndependentOption(
+ kRENO, Perspective::IS_SERVER));
+ EXPECT_TRUE(config_.HasClientRequestedIndependentOption(
+ kTBBR, Perspective::IS_SERVER));
+}
+
} // namespace
} // namespace test
} // namespace net
diff --git a/chromium/net/quic/core/quic_connection.cc b/chromium/net/quic/core/quic_connection.cc
index fdb17f8339d..708dc2608a5 100644
--- a/chromium/net/quic/core/quic_connection.cc
+++ b/chromium/net/quic/core/quic_connection.cc
@@ -15,13 +15,9 @@
#include <utility>
#include "base/format_macros.h"
-#include "base/logging.h"
#include "base/macros.h"
-#include "base/memory/ref_counted.h"
#include "base/metrics/histogram_macros.h"
#include "base/stl_util.h"
-#include "base/strings/string_number_conversions.h"
-#include "base/strings/stringprintf.h"
#include "net/base/address_family.h"
#include "net/base/ip_address.h"
#include "net/base/net_errors.h"
@@ -30,23 +26,18 @@
#include "net/quic/core/crypto/quic_encrypter.h"
#include "net/quic/core/proto/cached_network_parameters.pb.h"
#include "net/quic/core/quic_bandwidth.h"
-#include "net/quic/core/quic_bug_tracker.h"
#include "net/quic/core/quic_config.h"
#include "net/quic/core/quic_flags.h"
#include "net/quic/core/quic_packet_generator.h"
-#include "net/quic/core/quic_sent_packet_manager.h"
+#include "net/quic/core/quic_pending_retransmission.h"
#include "net/quic/core/quic_utils.h"
+#include "net/quic/platform/api/quic_bug_tracker.h"
+#include "net/quic/platform/api/quic_logging.h"
+#include "net/quic/platform/api/quic_str_cat.h"
+#include "net/quic/platform/api/quic_text_utils.h"
using base::StringPiece;
-using base::StringPrintf;
-using std::list;
-using std::make_pair;
-using std::max;
-using std::min;
-using std::numeric_limits;
-using std::set;
using std::string;
-using std::vector;
namespace net {
@@ -84,11 +75,6 @@ bool Near(QuicPacketNumber a, QuicPacketNumber b) {
return delta <= kMaxPacketGap;
}
-bool IsInitializedIPEndPoint(const IPEndPoint& address) {
- return net::GetAddressFamily(address.address()) !=
- net::ADDRESS_FAMILY_UNSPECIFIED;
-}
-
// An alarm that is scheduled to send an ack if a timeout occurs.
class AckAlarmDelegate : public QuicAlarm::Delegate {
public:
@@ -183,7 +169,7 @@ class MtuDiscoveryAlarmDelegate : public QuicAlarm::Delegate {
(perspective_ == Perspective::IS_SERVER ? "Server: " : "Client: ")
QuicConnection::QuicConnection(QuicConnectionId connection_id,
- IPEndPoint address,
+ QuicSocketAddress address,
QuicConnectionHelperInterface* helper,
QuicAlarmFactory* alarm_factory,
QuicPacketWriter* writer,
@@ -256,7 +242,6 @@ QuicConnection::QuicConnection(QuicConnectionId connection_id,
debug_visitor_(nullptr),
packet_generator_(connection_id_,
&framer_,
- random_generator_,
helper->GetBufferAllocator(),
this),
idle_network_timeout_(QuicTime::Delta::Infinite()),
@@ -265,14 +250,7 @@ QuicConnection::QuicConnection(QuicConnectionId connection_id,
time_of_last_sent_new_packet_(clock_->ApproximateNow()),
last_send_for_timeout_(clock_->ApproximateNow()),
packet_number_of_last_sent_packet_(0),
- sent_packet_manager_(new QuicSentPacketManager(
- perspective,
- kDefaultPathId,
- clock_,
- &stats_,
- FLAGS_quic_default_enable_cubic_bytes ? kCubicBytes : kCubic,
- kNack,
- /*delegate=*/nullptr)),
+ sent_packet_manager_(perspective, clock_, &stats_, kCubicBytes, kNack),
version_negotiation_state_(START_NEGOTIATION),
perspective_(perspective),
connected_(true),
@@ -286,27 +264,21 @@ QuicConnection::QuicConnection(QuicConnectionId connection_id,
goaway_received_(false),
multipath_enabled_(false),
write_error_occured_(false) {
- DVLOG(1) << ENDPOINT
- << "Created connection with connection_id: " << connection_id;
+ QUIC_DLOG(INFO) << ENDPOINT
+ << "Created connection with connection_id: " << connection_id;
framer_.set_visitor(this);
- framer_.set_received_entropy_calculator(&received_packet_manager_);
- if (!FLAGS_quic_receive_packet_once_decrypted) {
+ if (!FLAGS_quic_reloadable_flag_quic_receive_packet_once_decrypted) {
last_stop_waiting_frame_.least_unacked = 0;
}
stats_.connection_creation_time = clock_->ApproximateNow();
- if (FLAGS_quic_enable_multipath) {
- sent_packet_manager_.reset(new QuicMultipathSentPacketManager(
- sent_packet_manager_.release(), this));
- }
// TODO(ianswett): Supply the NetworkChangeVisitor as a constructor argument
// and make it required non-null, because it's always used.
- sent_packet_manager_->SetNetworkChangeVisitor(this);
+ sent_packet_manager_.SetNetworkChangeVisitor(this);
// Allow the packet writer to potentially reduce the packet size to a value
// even smaller than kDefaultMaxPacketSize.
SetMaxPacketLength(perspective_ == Perspective::IS_SERVER
? kDefaultServerMaxPacketSize
: kDefaultMaxPacketSize);
- received_packet_manager_.SetVersion(version());
}
QuicConnection::~QuicConnection() {
@@ -322,7 +294,7 @@ void QuicConnection::ClearQueuedPackets() {
// Delete the buffer before calling ClearSerializedPacket, which sets
// encrypted_buffer to nullptr.
delete[] it->encrypted_buffer;
- QuicUtils::ClearSerializedPacket(&(*it));
+ ClearSerializedPacket(&(*it));
}
queued_packets_.clear();
}
@@ -336,7 +308,8 @@ void QuicConnection::SetFromConfig(const QuicConfig& config) {
idle_timeout_connection_close_behavior_ =
ConnectionCloseBehavior::SILENT_CLOSE;
}
- if (FLAGS_quic_enable_multipath && config.MultipathEnabled()) {
+ if (FLAGS_quic_reloadable_flag_quic_enable_multipath &&
+ config.MultipathEnabled()) {
multipath_enabled_ = true;
}
} else {
@@ -344,7 +317,7 @@ void QuicConnection::SetFromConfig(const QuicConfig& config) {
config.max_idle_time_before_crypto_handshake());
}
- sent_packet_manager_->SetFromConfig(config);
+ sent_packet_manager_.SetFromConfig(config);
if (config.HasReceivedBytesForConnectionId() &&
can_truncate_connection_ids_) {
packet_generator_.SetConnectionIdLength(
@@ -377,7 +350,7 @@ void QuicConnection::SetFromConfig(const QuicConfig& config) {
}
if (config.HasClientSentConnectionOption(k5RTO, perspective_)) {
if (perspective_ == Perspective::IS_CLIENT ||
- !FLAGS_quic_only_5rto_client_side) {
+ !FLAGS_quic_reloadable_flag_quic_only_5rto_client_side) {
close_connection_after_five_rtos_ = true;
}
}
@@ -400,16 +373,16 @@ void QuicConnection::OnReceiveConnectionState(
void QuicConnection::ResumeConnectionState(
const CachedNetworkParameters& cached_network_params,
bool max_bandwidth_resumption) {
- sent_packet_manager_->ResumeConnectionState(cached_network_params,
- max_bandwidth_resumption);
+ sent_packet_manager_.ResumeConnectionState(cached_network_params,
+ max_bandwidth_resumption);
}
void QuicConnection::SetMaxPacingRate(QuicBandwidth max_pacing_rate) {
- sent_packet_manager_->SetMaxPacingRate(max_pacing_rate);
+ sent_packet_manager_.SetMaxPacingRate(max_pacing_rate);
}
void QuicConnection::SetNumOpenStreams(size_t num_streams) {
- sent_packet_manager_->SetNumOpenStreams(num_streams);
+ sent_packet_manager_.SetNumOpenStreams(num_streams);
}
bool QuicConnection::SelectMutualVersion(
@@ -452,14 +425,14 @@ void QuicConnection::OnPublicResetPacket(const QuicPublicResetPacket& packet) {
debug_visitor_->OnPublicResetPacket(packet);
}
const string error_details = "Received public reset.";
- DVLOG(1) << ENDPOINT << error_details;
+ QUIC_DLOG(INFO) << ENDPOINT << error_details;
TearDownLocalConnectionState(QUIC_PUBLIC_RESET, error_details,
ConnectionCloseSource::FROM_PEER);
}
bool QuicConnection::OnProtocolVersionMismatch(QuicVersion received_version) {
- DVLOG(1) << ENDPOINT << "Received packet with mismatched version "
- << received_version;
+ QUIC_DLOG(INFO) << ENDPOINT << "Received packet with mismatched version "
+ << received_version;
// TODO(satyamshekhar): Implement no server state in this mode.
if (perspective_ == Perspective::IS_CLIENT) {
const string error_details = "Protocol version mismatch.";
@@ -500,12 +473,11 @@ bool QuicConnection::OnProtocolVersionMismatch(QuicVersion received_version) {
}
version_negotiation_state_ = NEGOTIATED_VERSION;
- received_packet_manager_.SetVersion(received_version);
visitor_->OnSuccessfulVersionNegotiation(received_version);
if (debug_visitor_ != nullptr) {
debug_visitor_->OnSuccessfulVersionNegotiation(received_version);
}
- DVLOG(1) << ENDPOINT << "version negotiated " << received_version;
+ QUIC_DLOG(INFO) << ENDPOINT << "version negotiated " << received_version;
// Store the new version.
framer_.set_version(received_version);
@@ -543,7 +515,7 @@ void QuicConnection::OnVersionNegotiationPacket(
const string error_details =
"Server already supports client's version and should have accepted the "
"connection.";
- DLOG(WARNING) << error_details;
+ QUIC_DLOG(WARNING) << error_details;
TearDownLocalConnectionState(QUIC_INVALID_VERSION_NEGOTIATION_PACKET,
error_details,
ConnectionCloseSource::FROM_SELF);
@@ -553,17 +525,16 @@ void QuicConnection::OnVersionNegotiationPacket(
if (!SelectMutualVersion(packet.versions)) {
CloseConnection(
QUIC_INVALID_VERSION,
- "No common version found. Supported versions: {" +
- QuicVersionVectorToString(framer_.supported_versions()) +
- "}, peer supported versions: {" +
- QuicVersionVectorToString(packet.versions) + "}",
+ QuicStrCat("No common version found. Supported versions: {",
+ QuicVersionVectorToString(framer_.supported_versions()),
+ "}, peer supported versions: {",
+ QuicVersionVectorToString(packet.versions), "}"),
ConnectionCloseBehavior::SEND_CONNECTION_CLOSE_PACKET);
return;
}
- DVLOG(1) << ENDPOINT
- << "Negotiated version: " << QuicVersionToString(version());
- received_packet_manager_.SetVersion(version());
+ QUIC_DLOG(INFO) << ENDPOINT
+ << "Negotiated version: " << QuicVersionToString(version());
server_supported_versions_ = packet.versions;
version_negotiation_state_ = NEGOTIATION_IN_PROGRESS;
RetransmitUnackedPackets(ALL_UNACKED_RETRANSMISSION);
@@ -576,8 +547,9 @@ bool QuicConnection::OnUnauthenticatedPublicHeader(
}
++stats_.packets_dropped;
- DVLOG(1) << ENDPOINT << "Ignoring packet from unexpected ConnectionId: "
- << header.connection_id << " instead of " << connection_id_;
+ QUIC_DLOG(INFO) << ENDPOINT
+ << "Ignoring packet from unexpected ConnectionId: "
+ << header.connection_id << " instead of " << connection_id_;
if (debug_visitor_ != nullptr) {
debug_visitor_->OnIncorrectConnectionId(header.connection_id);
}
@@ -612,8 +584,8 @@ bool QuicConnection::OnUnauthenticatedHeader(const QuicPacketHeader& header) {
// If this packet has already been seen, or the sender has told us that it
// will not be retransmitted, then stop processing the packet.
if (!received_packet_manager_.IsAwaitingPacket(header.packet_number)) {
- DVLOG(1) << ENDPOINT << "Packet " << header.packet_number
- << " no longer being waited for. Discarding.";
+ QUIC_DLOG(INFO) << ENDPOINT << "Packet " << header.packet_number
+ << " no longer being waited for. Discarding.";
if (debug_visitor_ != nullptr) {
debug_visitor_->OnDuplicatePacket(header.packet_number);
}
@@ -632,7 +604,7 @@ void QuicConnection::OnDecryptedPacket(EncryptionLevel level) {
// confirmed.
if (level == ENCRYPTION_FORWARD_SECURE &&
perspective_ == Perspective::IS_SERVER) {
- sent_packet_manager_->SetHandshakeConfirmed();
+ sent_packet_manager_.SetHandshakeConfirmed();
}
}
@@ -657,13 +629,13 @@ bool QuicConnection::OnPacketHeader(const QuicPacketHeader& header) {
if (active_peer_migration_type_ == NO_CHANGE &&
peer_migration_type != NO_CHANGE &&
header.packet_number > received_packet_manager_.GetLargestObserved()) {
- StartPeerMigration(header.path_id, peer_migration_type);
+ StartPeerMigration(peer_migration_type);
}
--stats_.packets_dropped;
- DVLOG(1) << ENDPOINT << "Received packet header: " << header;
+ QUIC_DVLOG(1) << ENDPOINT << "Received packet header: " << header;
last_header_ = header;
- if (FLAGS_quic_receive_packet_once_decrypted) {
+ if (FLAGS_quic_reloadable_flag_quic_receive_packet_once_decrypted) {
// An ack will be sent if a missing retransmittable packet was received;
was_last_packet_missing_ =
received_packet_manager_.IsMissing(last_header_.packet_number);
@@ -714,10 +686,10 @@ bool QuicConnection::OnAckFrame(const QuicAckFrame& incoming_ack) {
if (debug_visitor_ != nullptr) {
debug_visitor_->OnAckFrame(incoming_ack);
}
- DVLOG(1) << ENDPOINT << "OnAckFrame: " << incoming_ack;
+ QUIC_DVLOG(1) << ENDPOINT << "OnAckFrame: " << incoming_ack;
if (last_header_.packet_number <= largest_seen_packet_with_ack_) {
- DVLOG(1) << ENDPOINT << "Received an old ack frame: ignoring";
+ QUIC_DLOG(INFO) << ENDPOINT << "Received an old ack frame: ignoring";
return true;
}
@@ -732,9 +704,6 @@ bool QuicConnection::OnAckFrame(const QuicAckFrame& incoming_ack) {
send_alarm_->Cancel();
}
ProcessAckFrame(incoming_ack);
- if (incoming_ack.is_truncated) {
- should_last_packet_instigate_acks_ = true;
- }
// If the incoming ack's packets set expresses missing packets: peer is still
// waiting for a packet lower than a packet that we are no longer planning to
// send.
@@ -742,7 +711,7 @@ bool QuicConnection::OnAckFrame(const QuicAckFrame& incoming_ack) {
// acking packets which we never care about.
// Send an ack to raise the high water mark.
if (!incoming_ack.packets.Empty() &&
- GetLeastUnacked(incoming_ack.path_id) > incoming_ack.packets.Min()) {
+ GetLeastUnacked() > incoming_ack.packets.Min()) {
++stop_waiting_count_;
} else {
stop_waiting_count_ = 0;
@@ -753,14 +722,8 @@ bool QuicConnection::OnAckFrame(const QuicAckFrame& incoming_ack) {
void QuicConnection::ProcessAckFrame(const QuicAckFrame& incoming_ack) {
largest_seen_packet_with_ack_ = last_header_.packet_number;
- sent_packet_manager_->OnIncomingAck(incoming_ack,
- time_of_last_received_packet_);
- if (version() <= QUIC_VERSION_33) {
- sent_entropy_manager_.ClearEntropyBefore(
- sent_packet_manager_->GetLeastPacketAwaitedByPeer(
- incoming_ack.path_id) -
- 1);
- }
+ sent_packet_manager_.OnIncomingAck(incoming_ack,
+ time_of_last_received_packet_);
// Always reset the retransmission alarm when an ack comes in, since we now
// have a better estimate of the current rtt than when it was set.
SetRetransmissionAlarm();
@@ -776,7 +739,8 @@ bool QuicConnection::OnStopWaitingFrame(const QuicStopWaitingFrame& frame) {
DCHECK(connected_);
if (last_header_.packet_number <= largest_seen_packet_with_stop_waiting_) {
- DVLOG(1) << ENDPOINT << "Received an old stop waiting frame: ignoring";
+ QUIC_DLOG(INFO) << ENDPOINT
+ << "Received an old stop waiting frame: ignoring";
return true;
}
@@ -791,7 +755,7 @@ bool QuicConnection::OnStopWaitingFrame(const QuicStopWaitingFrame& frame) {
debug_visitor_->OnStopWaitingFrame(frame);
}
- if (FLAGS_quic_receive_packet_once_decrypted) {
+ if (FLAGS_quic_reloadable_flag_quic_receive_packet_once_decrypted) {
ProcessStopWaitingFrame(frame);
} else {
last_stop_waiting_frame_ = frame;
@@ -818,64 +782,33 @@ bool QuicConnection::OnPingFrame(const QuicPingFrame& frame) {
const char* QuicConnection::ValidateAckFrame(const QuicAckFrame& incoming_ack) {
if (incoming_ack.largest_observed > packet_generator_.packet_number()) {
- DLOG(WARNING) << ENDPOINT << "Peer's observed unsent packet:"
- << incoming_ack.largest_observed << " vs "
- << packet_generator_.packet_number();
+ QUIC_DLOG(WARNING) << ENDPOINT << "Peer's observed unsent packet:"
+ << incoming_ack.largest_observed << " vs "
+ << packet_generator_.packet_number();
// We got an error for data we have not sent. Error out.
return "Largest observed too high.";
}
if (incoming_ack.largest_observed <
- sent_packet_manager_->GetLargestObserved(incoming_ack.path_id)) {
- VLOG(1) << ENDPOINT << "Peer's largest_observed packet decreased:"
- << incoming_ack.largest_observed << " vs "
- << sent_packet_manager_->GetLargestObserved(incoming_ack.path_id)
- << " packet_number:" << last_header_.packet_number
- << " largest seen with ack:" << largest_seen_packet_with_ack_
- << " connection_id: " << connection_id_;
+ sent_packet_manager_.GetLargestObserved()) {
+ QUIC_LOG(INFO) << ENDPOINT << "Peer's largest_observed packet decreased:"
+ << incoming_ack.largest_observed << " vs "
+ << sent_packet_manager_.GetLargestObserved()
+ << " packet_number:" << last_header_.packet_number
+ << " largest seen with ack:" << largest_seen_packet_with_ack_
+ << " connection_id: " << connection_id_;
// A new ack has a diminished largest_observed value. Error out.
// If this was an old packet, we wouldn't even have checked.
return "Largest observed too low.";
}
- if (version() <= QUIC_VERSION_33) {
- if (!incoming_ack.packets.Empty() &&
- incoming_ack.packets.Max() > incoming_ack.largest_observed) {
- LOG(WARNING) << ENDPOINT
- << "Peer sent missing packet: " << incoming_ack.packets.Max()
- << " which is greater than largest observed: "
- << incoming_ack.largest_observed;
- return "Missing packet higher than largest observed.";
- }
-
- if (!incoming_ack.packets.Empty() &&
- incoming_ack.packets.Min() <
- sent_packet_manager_->GetLeastPacketAwaitedByPeer(
- incoming_ack.path_id)) {
- LOG(WARNING) << ENDPOINT
- << "Peer sent missing packet: " << incoming_ack.packets.Min()
- << " which is smaller than least_packet_awaited_by_peer_: "
- << sent_packet_manager_->GetLeastPacketAwaitedByPeer(
- incoming_ack.path_id);
- return "Missing packet smaller than least awaited.";
- }
- if (!sent_entropy_manager_.IsValidEntropy(incoming_ack.largest_observed,
- incoming_ack.packets,
- incoming_ack.entropy_hash)) {
- DLOG(WARNING) << ENDPOINT << "Peer sent invalid entropy."
- << " largest_observed:" << incoming_ack.largest_observed
- << " last_received:" << last_header_.packet_number;
- return "Invalid entropy.";
- }
- } else {
- if (!incoming_ack.packets.Empty() &&
- incoming_ack.packets.Max() != incoming_ack.largest_observed) {
- QUIC_BUG << ENDPOINT
- << "Peer last received packet: " << incoming_ack.packets.Max()
- << " which is not equal to largest observed: "
- << incoming_ack.largest_observed;
- return "Last received packet not equal to largest observed.";
- }
+ if (!incoming_ack.packets.Empty() &&
+ incoming_ack.packets.Max() != incoming_ack.largest_observed) {
+ QUIC_BUG << ENDPOINT
+ << "Peer last received packet: " << incoming_ack.packets.Max()
+ << " which is not equal to largest observed: "
+ << incoming_ack.largest_observed;
+ return "Last received packet not equal to largest observed.";
}
return nullptr;
@@ -885,18 +818,19 @@ const char* QuicConnection::ValidateStopWaitingFrame(
const QuicStopWaitingFrame& stop_waiting) {
if (stop_waiting.least_unacked <
received_packet_manager_.peer_least_packet_awaiting_ack()) {
- DLOG(ERROR) << ENDPOINT << "Peer's sent low least_unacked: "
- << stop_waiting.least_unacked << " vs "
- << received_packet_manager_.peer_least_packet_awaiting_ack();
+ QUIC_DLOG(ERROR)
+ << ENDPOINT
+ << "Peer's sent low least_unacked: " << stop_waiting.least_unacked
+ << " vs " << received_packet_manager_.peer_least_packet_awaiting_ack();
// We never process old ack frames, so this number should only increase.
return "Least unacked too small.";
}
if (stop_waiting.least_unacked > last_header_.packet_number) {
- DLOG(ERROR) << ENDPOINT
- << "Peer sent least_unacked:" << stop_waiting.least_unacked
- << " greater than the enclosing packet number:"
- << last_header_.packet_number;
+ QUIC_DLOG(ERROR) << ENDPOINT
+ << "Peer sent least_unacked:" << stop_waiting.least_unacked
+ << " greater than the enclosing packet number:"
+ << last_header_.packet_number;
return "Least unacked too large.";
}
@@ -908,10 +842,10 @@ bool QuicConnection::OnRstStreamFrame(const QuicRstStreamFrame& frame) {
if (debug_visitor_ != nullptr) {
debug_visitor_->OnRstStreamFrame(frame);
}
- DVLOG(1) << ENDPOINT
- << "RST_STREAM_FRAME received for stream: " << frame.stream_id
- << " with error: "
- << QuicUtils::StreamErrorToString(frame.error_code);
+ QUIC_DLOG(INFO) << ENDPOINT
+ << "RST_STREAM_FRAME received for stream: " << frame.stream_id
+ << " with error: "
+ << QuicRstStreamErrorCodeToString(frame.error_code);
visitor_->OnRstStream(frame);
visitor_->PostProcessAfterData();
should_last_packet_instigate_acks_ = true;
@@ -924,14 +858,14 @@ bool QuicConnection::OnConnectionCloseFrame(
if (debug_visitor_ != nullptr) {
debug_visitor_->OnConnectionCloseFrame(frame);
}
- DVLOG(1) << ENDPOINT
- << "Received ConnectionClose for connection: " << connection_id()
- << ", with error: " << QuicUtils::ErrorToString(frame.error_code)
- << " (" << frame.error_details << ")";
+ QUIC_DLOG(INFO) << ENDPOINT << "Received ConnectionClose for connection: "
+ << connection_id()
+ << ", with error: " << QuicErrorCodeToString(frame.error_code)
+ << " (" << frame.error_details << ")";
if (frame.error_code == QUIC_BAD_MULTIPATH_FLAG) {
- LOG(ERROR) << " quic_version: " << version()
- << " last_received_header: " << last_header_
- << " encryption_level: " << encryption_level_;
+ QUIC_LOG_FIRST_N(ERROR, 10) << "Unexpected QUIC_BAD_MULTIPATH_FLAG error."
+ << " last_received_header: " << last_header_
+ << " encryption_level: " << encryption_level_;
}
TearDownLocalConnectionState(frame.error_code, frame.error_details,
ConnectionCloseSource::FROM_PEER);
@@ -943,10 +877,10 @@ bool QuicConnection::OnGoAwayFrame(const QuicGoAwayFrame& frame) {
if (debug_visitor_ != nullptr) {
debug_visitor_->OnGoAwayFrame(frame);
}
- DVLOG(1) << ENDPOINT << "GOAWAY_FRAME received with last good stream: "
- << frame.last_good_stream_id
- << " and error: " << QuicUtils::ErrorToString(frame.error_code)
- << " and reason: " << frame.reason_phrase;
+ QUIC_DLOG(INFO) << ENDPOINT << "GOAWAY_FRAME received with last good stream: "
+ << frame.last_good_stream_id
+ << " and error: " << QuicErrorCodeToString(frame.error_code)
+ << " and reason: " << frame.reason_phrase;
goaway_received_ = true;
visitor_->OnGoAway(frame);
@@ -960,9 +894,9 @@ bool QuicConnection::OnWindowUpdateFrame(const QuicWindowUpdateFrame& frame) {
if (debug_visitor_ != nullptr) {
debug_visitor_->OnWindowUpdateFrame(frame);
}
- DVLOG(1) << ENDPOINT
- << "WINDOW_UPDATE_FRAME received for stream: " << frame.stream_id
- << " with byte offset: " << frame.byte_offset;
+ QUIC_DLOG(INFO) << ENDPOINT << "WINDOW_UPDATE_FRAME received for stream: "
+ << frame.stream_id
+ << " with byte offset: " << frame.byte_offset;
visitor_->OnWindowUpdateFrame(frame);
visitor_->PostProcessAfterData();
should_last_packet_instigate_acks_ = true;
@@ -974,8 +908,8 @@ bool QuicConnection::OnBlockedFrame(const QuicBlockedFrame& frame) {
if (debug_visitor_ != nullptr) {
debug_visitor_->OnBlockedFrame(frame);
}
- DVLOG(1) << ENDPOINT
- << "BLOCKED_FRAME received for stream: " << frame.stream_id;
+ QUIC_DLOG(INFO) << ENDPOINT
+ << "BLOCKED_FRAME received for stream: " << frame.stream_id;
visitor_->OnBlockedFrame(frame);
visitor_->PostProcessAfterData();
stats_.blocked_frames_received++;
@@ -988,8 +922,8 @@ bool QuicConnection::OnPathCloseFrame(const QuicPathCloseFrame& frame) {
if (debug_visitor_ != nullptr) {
debug_visitor_->OnPathCloseFrame(frame);
}
- DVLOG(1) << ENDPOINT
- << "PATH_CLOSE_FRAME received for path: " << frame.path_id;
+ QUIC_DLOG(INFO) << ENDPOINT
+ << "PATH_CLOSE_FRAME received for path: " << frame.path_id;
OnPathClosed(frame.path_id);
return connected_;
}
@@ -1001,10 +935,10 @@ void QuicConnection::OnPacketComplete() {
return;
}
- DVLOG(1) << ENDPOINT << "Got packet " << last_header_.packet_number << " for "
- << last_header_.public_header.connection_id;
+ QUIC_DVLOG(1) << ENDPOINT << "Got packet " << last_header_.packet_number
+ << " for " << last_header_.public_header.connection_id;
- if (FLAGS_quic_receive_packet_once_decrypted) {
+ if (FLAGS_quic_reloadable_flag_quic_receive_packet_once_decrypted) {
// An ack will be sent if a missing retransmittable packet was received;
const bool was_missing =
should_last_packet_instigate_acks_ && was_last_packet_missing_;
@@ -1039,7 +973,6 @@ void QuicConnection::OnPacketComplete() {
}
ClearLastFrames();
- MaybeCloseIfTooManyOutstandingPackets();
}
void QuicConnection::MaybeQueueAck(bool was_missing) {
@@ -1071,7 +1004,7 @@ void QuicConnection::MaybeQueueAck(bool was_missing) {
} else if (!ack_alarm_->IsSet()) {
// Wait the minimum of a quarter min_rtt and the delayed ack time.
QuicTime::Delta ack_delay = std::min(
- DelayedAckTime(), sent_packet_manager_->GetRttStats()->min_rtt() *
+ DelayedAckTime(), sent_packet_manager_.GetRttStats()->min_rtt() *
ack_decimation_delay_);
ack_alarm_->Set(clock_->ApproximateNow() + ack_delay);
}
@@ -1091,7 +1024,7 @@ void QuicConnection::MaybeQueueAck(bool was_missing) {
// Wait the minimum of an eighth min_rtt and the existing ack time.
QuicTime ack_time =
clock_->ApproximateNow() +
- 0.125 * sent_packet_manager_->GetRttStats()->min_rtt();
+ 0.125 * sent_packet_manager_.GetRttStats()->min_rtt();
if (!ack_alarm_->IsSet() || ack_alarm_->deadline() > ack_time) {
ack_alarm_->Update(ack_time, QuicTime::Delta::Zero());
}
@@ -1108,50 +1041,22 @@ void QuicConnection::MaybeQueueAck(bool was_missing) {
void QuicConnection::ClearLastFrames() {
should_last_packet_instigate_acks_ = false;
- if (!FLAGS_quic_receive_packet_once_decrypted) {
+ if (!FLAGS_quic_reloadable_flag_quic_receive_packet_once_decrypted) {
last_stop_waiting_frame_.least_unacked = 0;
}
}
-void QuicConnection::MaybeCloseIfTooManyOutstandingPackets() {
- if (version() > QUIC_VERSION_33) {
- return;
- }
- // This occurs if we don't discard old packets we've sent fast enough.
- // It's possible largest observed is less than least unacked.
- if (sent_packet_manager_->GetLargestObserved(last_header_.path_id) >
- (sent_packet_manager_->GetLeastUnacked(last_header_.path_id) +
- kMaxTrackedPackets)) {
- CloseConnection(
- QUIC_TOO_MANY_OUTSTANDING_SENT_PACKETS,
- StringPrintf("More than %" PRIu64 " outstanding.", kMaxTrackedPackets),
- ConnectionCloseBehavior::SEND_CONNECTION_CLOSE_PACKET);
- }
- // This occurs if there are received packet gaps and the peer does not raise
- // the least unacked fast enough.
- if (received_packet_manager_.NumTrackedPackets() > kMaxTrackedPackets) {
- CloseConnection(
- QUIC_TOO_MANY_OUTSTANDING_RECEIVED_PACKETS,
- StringPrintf("More than %" PRIu64 " outstanding.", kMaxTrackedPackets),
- ConnectionCloseBehavior::SEND_CONNECTION_CLOSE_PACKET);
- }
-}
-
const QuicFrame QuicConnection::GetUpdatedAckFrame() {
return received_packet_manager_.GetUpdatedAckFrame(clock_->ApproximateNow());
}
void QuicConnection::PopulateStopWaitingFrame(
QuicStopWaitingFrame* stop_waiting) {
- stop_waiting->least_unacked = GetLeastUnacked(stop_waiting->path_id);
- if (version() <= QUIC_VERSION_33) {
- stop_waiting->entropy_hash = sent_entropy_manager_.GetCumulativeEntropy(
- stop_waiting->least_unacked - 1);
- }
+ stop_waiting->least_unacked = GetLeastUnacked();
}
-QuicPacketNumber QuicConnection::GetLeastUnacked(QuicPathId path_id) const {
- return sent_packet_manager_->GetLeastUnacked(path_id);
+QuicPacketNumber QuicConnection::GetLeastUnacked() const {
+ return sent_packet_manager_.GetLeastUnacked();
}
void QuicConnection::MaybeSendInResponseToPacket() {
@@ -1173,14 +1078,15 @@ void QuicConnection::SendVersionNegotiationPacket() {
visitor_->OnWriteBlocked();
return;
}
- DVLOG(1) << ENDPOINT << "Sending version negotiation packet: {"
- << QuicVersionVectorToString(framer_.supported_versions()) << "}";
+ QUIC_DLOG(INFO) << ENDPOINT << "Sending version negotiation packet: {"
+ << QuicVersionVectorToString(framer_.supported_versions())
+ << "}";
std::unique_ptr<QuicEncryptedPacket> version_packet(
packet_generator_.SerializeVersionNegotiationPacket(
framer_.supported_versions()));
WriteResult result = writer_->WritePacket(
- version_packet->data(), version_packet->length(),
- self_address().address(), peer_address(), per_packet_options_);
+ version_packet->data(), version_packet->length(), self_address().host(),
+ peer_address(), per_packet_options_);
if (result.status == WRITE_STATUS_ERROR) {
OnWriteError(result.error_code);
@@ -1202,7 +1108,7 @@ QuicConsumedData QuicConnection::SendStreamData(
QuicIOVector iov,
QuicStreamOffset offset,
bool fin,
- QuicAckListenerInterface* listener) {
+ QuicReferenceCountedPointer<QuicAckListenerInterface> ack_listener) {
if (!fin && iov.total_length == 0) {
QUIC_BUG << "Attempt to send empty stream frame";
return QuicConsumedData(0, false);
@@ -1221,9 +1127,10 @@ QuicConsumedData QuicConnection::SendStreamData(
iov.total_length > kMaxPacketSize) {
// Use the fast path to send full data packets.
return packet_generator_.ConsumeDataFastPath(id, iov, offset, fin,
- listener);
+ std::move(ack_listener));
}
- return packet_generator_.ConsumeData(id, iov, offset, fin, listener);
+ return packet_generator_.ConsumeData(id, iov, offset, fin,
+ std::move(ack_listener));
}
void QuicConnection::SendRstStream(QuicStreamId id,
@@ -1240,7 +1147,7 @@ void QuicConnection::SendRstStream(QuicStreamId id,
return;
}
- sent_packet_manager_->CancelRetransmissionsForStream(id);
+ sent_packet_manager_.CancelRetransmissionsForStream(id);
// Remove all queued packets which only contain data for the reset stream.
QueuedPacketList::iterator packet_iterator = queued_packets_.begin();
while (packet_iterator != queued_packets_.end()) {
@@ -1250,13 +1157,13 @@ void QuicConnection::SendRstStream(QuicStreamId id,
++packet_iterator;
continue;
}
- QuicUtils::RemoveFramesForStream(retransmittable_frames, id);
+ RemoveFramesForStream(retransmittable_frames, id);
if (!retransmittable_frames->empty()) {
++packet_iterator;
continue;
}
delete[] packet_iterator->encrypted_buffer;
- QuicUtils::ClearSerializedPacket(&(*packet_iterator));
+ ClearSerializedPacket(&(*packet_iterator));
packet_iterator = queued_packets_.erase(packet_iterator);
}
}
@@ -1284,7 +1191,7 @@ void QuicConnection::SendPathClose(QuicPathId path_id) {
}
const QuicConnectionStats& QuicConnection::GetStats() {
- const RttStats* rtt_stats = sent_packet_manager_->GetRttStats();
+ const RttStats* rtt_stats = sent_packet_manager_.GetRttStats();
// Update rtt and estimated bandwidth.
QuicTime::Delta min_rtt = rtt_stats->min_rtt();
@@ -1301,14 +1208,14 @@ const QuicConnectionStats& QuicConnection::GetStats() {
}
stats_.srtt_us = srtt.ToMicroseconds();
- stats_.estimated_bandwidth = sent_packet_manager_->BandwidthEstimate();
+ stats_.estimated_bandwidth = sent_packet_manager_.BandwidthEstimate();
stats_.max_packet_size = packet_generator_.GetCurrentMaxPacketLength();
stats_.max_received_packet_size = largest_received_packet_size_;
return stats_;
}
-void QuicConnection::ProcessUdpPacket(const IPEndPoint& self_address,
- const IPEndPoint& peer_address,
+void QuicConnection::ProcessUdpPacket(const QuicSocketAddress& self_address,
+ const QuicSocketAddress& peer_address,
const QuicReceivedPacket& packet) {
if (!connected_) {
return;
@@ -1321,10 +1228,10 @@ void QuicConnection::ProcessUdpPacket(const IPEndPoint& self_address,
last_packet_destination_address_ = self_address;
last_packet_source_address_ = peer_address;
- if (!IsInitializedIPEndPoint(self_address_)) {
+ if (!self_address_.IsInitialized()) {
self_address_ = last_packet_destination_address_;
}
- if (!IsInitializedIPEndPoint(peer_address_)) {
+ if (!peer_address_.IsInitialized()) {
peer_address_ = last_packet_source_address_;
}
@@ -1332,7 +1239,7 @@ void QuicConnection::ProcessUdpPacket(const IPEndPoint& self_address,
++stats_.packets_received;
// Ensure the time coming from the packet reader is within a minute of now.
- if (FLAGS_quic_allow_large_send_deltas &&
+ if (FLAGS_quic_reloadable_flag_quic_allow_large_send_deltas &&
std::abs((packet.receipt_time() - clock_->ApproximateNow()).ToSeconds()) >
60) {
QUIC_BUG << "Packet receipt time:"
@@ -1341,8 +1248,8 @@ void QuicConnection::ProcessUdpPacket(const IPEndPoint& self_address,
<< clock_->ApproximateNow().ToDebuggingValue();
}
time_of_last_received_packet_ = packet.receipt_time();
- DVLOG(1) << ENDPOINT << "time of last received packet: "
- << time_of_last_received_packet_.ToDebuggingValue();
+ QUIC_DVLOG(1) << ENDPOINT << "time of last received packet: "
+ << time_of_last_received_packet_.ToDebuggingValue();
ScopedRetransmissionScheduler alarm_delayer(this);
if (!framer_.ProcessPacket(packet)) {
@@ -1356,17 +1263,18 @@ void QuicConnection::ProcessUdpPacket(const IPEndPoint& self_address,
debug_visitor_->OnUndecryptablePacket();
}
}
- DVLOG(1) << ENDPOINT << "Unable to process packet. Last packet processed: "
- << last_header_.packet_number;
+ QUIC_DVLOG(1) << ENDPOINT
+ << "Unable to process packet. Last packet processed: "
+ << last_header_.packet_number;
current_packet_data_ = nullptr;
return;
}
++stats_.packets_processed;
if (active_peer_migration_type_ != NO_CHANGE &&
- sent_packet_manager_->GetLargestObserved(last_header_.path_id) >
+ sent_packet_manager_.GetLargestObserved() >
highest_packet_sent_before_peer_migration_) {
- OnPeerMigrationValidated(last_header_.path_id);
+ OnPeerMigrationValidated();
}
MaybeProcessUndecryptablePackets();
MaybeSendInResponseToPacket();
@@ -1419,23 +1327,13 @@ void QuicConnection::WriteAndBundleAcksIfNotBlocked() {
}
bool QuicConnection::ProcessValidatedPacket(const QuicPacketHeader& header) {
- if (perspective_ == Perspective::IS_SERVER &&
- IsInitializedIPEndPoint(self_address_) &&
- IsInitializedIPEndPoint(last_packet_destination_address_) &&
- (!(self_address_ == last_packet_destination_address_))) {
+ if (perspective_ == Perspective::IS_SERVER && self_address_.IsInitialized() &&
+ last_packet_destination_address_.IsInitialized() &&
+ self_address_ != last_packet_destination_address_) {
// Allow change between pure IPv4 and equivalent mapped IPv4 address.
- IPAddress self_ip = self_address_.address();
- if (self_ip.IsIPv4MappedIPv6()) {
- self_ip = ConvertIPv4MappedIPv6ToIPv4(self_ip);
- }
- IPAddress last_packet_destination_ip =
- last_packet_destination_address_.address();
- if (last_packet_destination_ip.IsIPv4MappedIPv6()) {
- last_packet_destination_ip =
- ConvertIPv4MappedIPv6ToIPv4(last_packet_destination_ip);
- }
if (self_address_.port() != last_packet_destination_address_.port() ||
- self_ip != last_packet_destination_ip) {
+ self_address_.host().Normalized() !=
+ last_packet_destination_address_.host().Normalized()) {
CloseConnection(QUIC_ERROR_MIGRATING_ADDRESS,
"Self address migration is not supported at the server.",
ConnectionCloseBehavior::SEND_CONNECTION_CLOSE_PACKET);
@@ -1445,8 +1343,8 @@ bool QuicConnection::ProcessValidatedPacket(const QuicPacketHeader& header) {
}
if (!Near(header.packet_number, last_header_.packet_number)) {
- DVLOG(1) << ENDPOINT << "Packet " << header.packet_number
- << " out of bounds. Discarding";
+ QUIC_DLOG(INFO) << ENDPOINT << "Packet " << header.packet_number
+ << " out of bounds. Discarding";
CloseConnection(QUIC_INVALID_PACKET_HEADER, "packet number out of bounds.",
ConnectionCloseBehavior::SEND_CONNECTION_CLOSE_PACKET);
return false;
@@ -1469,10 +1367,9 @@ bool QuicConnection::ProcessValidatedPacket(const QuicPacketHeader& header) {
// Packets should have the version flag till version negotiation is
// done.
string error_details =
- StringPrintf("%s Packet %" PRIu64
- " without version flag before version negotiated.",
- ENDPOINT, header.packet_number);
- DLOG(WARNING) << error_details;
+ QuicStrCat(ENDPOINT, "Packet ", header.packet_number,
+ " without version flag before version negotiated.");
+ QUIC_DLOG(WARNING) << error_details;
CloseConnection(QUIC_INVALID_VERSION, error_details,
ConnectionCloseBehavior::SEND_CONNECTION_CLOSE_PACKET);
return false;
@@ -1480,7 +1377,6 @@ bool QuicConnection::ProcessValidatedPacket(const QuicPacketHeader& header) {
DCHECK_EQ(1u, header.public_header.versions.size());
DCHECK_EQ(header.public_header.versions[0], version());
version_negotiation_state_ = NEGOTIATED_VERSION;
- received_packet_manager_.SetVersion(version());
visitor_->OnSuccessfulVersionNegotiation(version());
if (debug_visitor_ != nullptr) {
debug_visitor_->OnSuccessfulVersionNegotiation(version());
@@ -1492,7 +1388,6 @@ bool QuicConnection::ProcessValidatedPacket(const QuicPacketHeader& header) {
// it should stop sending version since the version negotiation is done.
packet_generator_.StopSendingVersion();
version_negotiation_state_ = NEGOTIATED_VERSION;
- received_packet_manager_.SetVersion(version());
visitor_->OnSuccessfulVersionNegotiation(version());
if (debug_visitor_ != nullptr) {
debug_visitor_->OnSuccessfulVersionNegotiation(version());
@@ -1525,7 +1420,7 @@ void QuicConnection::WriteQueuedPackets() {
while (packet_iterator != queued_packets_.end() &&
WritePacket(&(*packet_iterator))) {
delete[] packet_iterator->encrypted_buffer;
- QuicUtils::ClearSerializedPacket(&(*packet_iterator));
+ ClearSerializedPacket(&(*packet_iterator));
packet_iterator = queued_packets_.erase(packet_iterator);
}
}
@@ -1533,9 +1428,9 @@ void QuicConnection::WriteQueuedPackets() {
void QuicConnection::WritePendingRetransmissions() {
// Keep writing as long as there's a pending retransmission which can be
// written.
- while (sent_packet_manager_->HasPendingRetransmissions()) {
- const PendingRetransmission pending =
- sent_packet_manager_->NextPendingRetransmission();
+ while (sent_packet_manager_.HasPendingRetransmissions()) {
+ const QuicPendingRetransmission pending =
+ sent_packet_manager_.NextPendingRetransmission();
if (!CanWrite(HAS_RETRANSMITTABLE_DATA)) {
break;
}
@@ -1554,13 +1449,13 @@ void QuicConnection::WritePendingRetransmissions() {
void QuicConnection::RetransmitUnackedPackets(
TransmissionType retransmission_type) {
- sent_packet_manager_->RetransmitUnackedPackets(retransmission_type);
+ sent_packet_manager_.RetransmitUnackedPackets(retransmission_type);
WriteIfNotBlocked();
}
void QuicConnection::NeuterUnencryptedPackets() {
- sent_packet_manager_->NeuterUnencryptedPackets();
+ sent_packet_manager_.NeuterUnencryptedPackets();
// This may have changed the retransmission timer, so re-arm it.
SetRetransmissionAlarm();
}
@@ -1596,33 +1491,27 @@ bool QuicConnection::CanWrite(HasRetransmittableData retransmittable) {
return false;
}
- // TODO(fayang): If delay is not infinite, the next packet will be created and
- // sent on path_id.
- QuicPathId path_id = kInvalidPathId;
QuicTime now = clock_->Now();
- QuicTime::Delta delay = sent_packet_manager_->TimeUntilSend(now, &path_id);
+ QuicTime::Delta delay = sent_packet_manager_.TimeUntilSend(now);
if (delay.IsInfinite()) {
- DCHECK_EQ(kInvalidPathId, path_id);
send_alarm_->Cancel();
return false;
}
- DCHECK_NE(kInvalidPathId, path_id);
// If the scheduler requires a delay, then we can not send this packet now.
if (!delay.IsZero()) {
send_alarm_->Update(now + delay, QuicTime::Delta::FromMilliseconds(1));
- DVLOG(1) << ENDPOINT << "Delaying sending " << delay.ToMilliseconds()
- << "ms";
+ QUIC_DVLOG(1) << ENDPOINT << "Delaying sending " << delay.ToMilliseconds()
+ << "ms";
return false;
}
return true;
}
bool QuicConnection::WritePacket(SerializedPacket* packet) {
- if (packet->packet_number <
- sent_packet_manager_->GetLargestSentPacket(packet->path_id)) {
- QUIC_BUG << "Attempt to write packet:" << packet->packet_number << " after:"
- << sent_packet_manager_->GetLargestSentPacket(packet->path_id);
+ if (packet->packet_number < sent_packet_manager_.GetLargestSentPacket()) {
+ QUIC_BUG << "Attempt to write packet:" << packet->packet_number
+ << " after:" << sent_packet_manager_.GetLargestSentPacket();
CloseConnection(QUIC_INTERNAL_ERROR, "Packet written out of order.",
ConnectionCloseBehavior::SEND_CONNECTION_CLOSE_PACKET);
return true;
@@ -1653,7 +1542,7 @@ bool QuicConnection::WritePacket(SerializedPacket* packet) {
new std::vector<std::unique_ptr<QuicEncryptedPacket>>);
}
// Copy the buffer so it's owned in the future.
- char* buffer_copy = QuicUtils::CopyBuffer(*packet);
+ char* buffer_copy = CopyBuffer(*packet);
termination_packets_->push_back(std::unique_ptr<QuicEncryptedPacket>(
new QuicEncryptedPacket(buffer_copy, encrypted_length, true)));
// This assures we won't try to write *forced* packets when blocked.
@@ -1666,23 +1555,23 @@ bool QuicConnection::WritePacket(SerializedPacket* packet) {
DCHECK_LE(encrypted_length, kMaxPacketSize);
DCHECK_LE(encrypted_length, packet_generator_.GetCurrentMaxPacketLength());
- DVLOG(1) << ENDPOINT << "Sending packet " << packet_number << " : "
- << (IsRetransmittable(*packet) == HAS_RETRANSMITTABLE_DATA
- ? "data bearing "
- : " ack only ")
- << ", encryption level: "
- << QuicUtils::EncryptionLevelToString(packet->encryption_level)
- << ", encrypted length:" << encrypted_length;
- DVLOG(2) << ENDPOINT << "packet(" << packet_number << "): " << std::endl
- << QuicUtils::HexDump(
- StringPiece(packet->encrypted_buffer, encrypted_length));
+ QUIC_DVLOG(1) << ENDPOINT << "Sending packet " << packet_number << " : "
+ << (IsRetransmittable(*packet) == HAS_RETRANSMITTABLE_DATA
+ ? "data bearing "
+ : " ack only ")
+ << ", encryption level: "
+ << QuicUtils::EncryptionLevelToString(packet->encryption_level)
+ << ", encrypted length:" << encrypted_length;
+ QUIC_DVLOG(2) << ENDPOINT << "packet(" << packet_number << "): " << std::endl
+ << QuicTextUtils::HexDump(
+ StringPiece(packet->encrypted_buffer, encrypted_length));
// Measure the RTT from before the write begins to avoid underestimating the
// min_rtt_, especially in cases where the thread blocks or gets swapped out
// during the WritePacket below.
QuicTime packet_send_time = clock_->Now();
WriteResult result = writer_->WritePacket(
- packet->encrypted_buffer, encrypted_length, self_address().address(),
+ packet->encrypted_buffer, encrypted_length, self_address().host(),
peer_address(), per_packet_options_);
if (result.error_code == ERR_IO_PENDING) {
DCHECK_EQ(WRITE_STATUS_BLOCKED, result.status);
@@ -1699,30 +1588,26 @@ bool QuicConnection::WritePacket(SerializedPacket* packet) {
}
}
- if (FLAGS_quic_only_track_sent_packets) {
- // In some cases, an MTU probe can cause EMSGSIZE. This indicates that the
- // MTU discovery is permanently unsuccessful.
- if (result.status == WRITE_STATUS_ERROR &&
- result.error_code == kMessageTooBigErrorCode &&
- packet->retransmittable_frames.empty() &&
- packet->encrypted_length > long_term_mtu_) {
- mtu_discovery_target_ = 0;
- mtu_discovery_alarm_->Cancel();
- // The write failed, but the writer is not blocked, so return true.
- return true;
- }
+ // In some cases, an MTU probe can cause EMSGSIZE. This indicates that the
+ // MTU discovery is permanently unsuccessful.
+ if (result.status == WRITE_STATUS_ERROR &&
+ result.error_code == kMessageTooBigErrorCode &&
+ packet->retransmittable_frames.empty() &&
+ packet->encrypted_length > long_term_mtu_) {
+ mtu_discovery_target_ = 0;
+ mtu_discovery_alarm_->Cancel();
+ // The write failed, but the writer is not blocked, so return true.
+ return true;
+ }
- if (result.status == WRITE_STATUS_ERROR) {
- OnWriteError(result.error_code);
- DLOG(ERROR) << ENDPOINT << "failed writing " << encrypted_length
- << " from host "
- << (self_address().address().empty()
- ? " empty address "
- : self_address().ToStringWithoutPort())
- << " to address " << peer_address().ToString()
- << " with error code " << result.error_code;
- return false;
- }
+ if (result.status == WRITE_STATUS_ERROR) {
+ OnWriteError(result.error_code);
+ QUIC_LOG_FIRST_N(ERROR, 10)
+ << ENDPOINT << "failed writing " << encrypted_length
+ << " bytes from host " << self_address().host().ToString()
+ << " to address " << peer_address().ToString() << " with error code "
+ << result.error_code;
+ return false;
}
if (result.status != WRITE_STATUS_ERROR && debug_visitor_ != nullptr) {
@@ -1744,12 +1629,12 @@ bool QuicConnection::WritePacket(SerializedPacket* packet) {
}
SetPingAlarm();
MaybeSetMtuAlarm();
- DVLOG(1) << ENDPOINT << "time we began writing last sent packet: "
- << packet_send_time.ToDebuggingValue();
+ QUIC_DVLOG(1) << ENDPOINT << "time we began writing last sent packet: "
+ << packet_send_time.ToDebuggingValue();
- bool reset_retransmission_alarm = sent_packet_manager_->OnPacketSent(
- packet, packet->original_path_id, packet->original_packet_number,
- packet_send_time, packet->transmission_type, IsRetransmittable(*packet));
+ bool reset_retransmission_alarm = sent_packet_manager_.OnPacketSent(
+ packet, packet->original_packet_number, packet_send_time,
+ packet->transmission_type, IsRetransmittable(*packet));
if (reset_retransmission_alarm || !retransmission_alarm_->IsSet()) {
SetRetransmissionAlarm();
@@ -1758,8 +1643,8 @@ bool QuicConnection::WritePacket(SerializedPacket* packet) {
// The packet number length must be updated after OnPacketSent, because it
// may change the packet number length in packet.
packet_generator_.UpdateSequenceNumberLength(
- sent_packet_manager_->GetLeastUnacked(packet->path_id),
- sent_packet_manager_->EstimateMaxPacketsInFlight(max_packet_length()));
+ sent_packet_manager_.GetLeastUnacked(),
+ sent_packet_manager_.EstimateMaxPacketsInFlight(max_packet_length()));
stats_.bytes_sent += result.bytes_written;
++stats_.packets_sent;
@@ -1768,37 +1653,13 @@ bool QuicConnection::WritePacket(SerializedPacket* packet) {
++stats_.packets_retransmitted;
}
- if (!FLAGS_quic_only_track_sent_packets) {
- // In some cases, an MTU probe can cause EMSGSIZE. This indicates that the
- // MTU discovery is permanently unsuccessful.
- if (result.status == WRITE_STATUS_ERROR &&
- result.error_code == kMessageTooBigErrorCode &&
- packet->retransmittable_frames.empty() &&
- packet->encrypted_length > long_term_mtu_) {
- mtu_discovery_target_ = 0;
- mtu_discovery_alarm_->Cancel();
- return true;
- }
-
- if (result.status == WRITE_STATUS_ERROR) {
- OnWriteError(result.error_code);
- DLOG(ERROR) << ENDPOINT << "failed writing " << encrypted_length
- << " from host "
- << (self_address().address().empty()
- ? " empty address "
- : self_address().ToStringWithoutPort())
- << " to address " << peer_address().ToString()
- << " with error code " << result.error_code;
- return false;
- }
- }
-
return true;
}
bool QuicConnection::ShouldDiscardPacket(const SerializedPacket& packet) {
if (!connected_) {
- DVLOG(1) << ENDPOINT << "Not sending packet as connection is disconnected.";
+ QUIC_DLOG(INFO) << ENDPOINT
+ << "Not sending packet as connection is disconnected.";
return true;
}
@@ -1807,8 +1668,9 @@ bool QuicConnection::ShouldDiscardPacket(const SerializedPacket& packet) {
packet.encryption_level == ENCRYPTION_NONE) {
// Drop packets that are NULL encrypted since the peer won't accept them
// anymore.
- DVLOG(1) << ENDPOINT << "Dropping NULL encrypted packet: " << packet_number
- << " since the connection is forward secure.";
+ QUIC_DLOG(INFO) << ENDPOINT
+ << "Dropping NULL encrypted packet: " << packet_number
+ << " since the connection is forward secure.";
return true;
}
@@ -1822,10 +1684,9 @@ void QuicConnection::OnWriteError(int error_code) {
}
write_error_occured_ = true;
- const string error_details = "Write failed with error: " +
- base::IntToString(error_code) + " (" +
- ErrorToString(error_code) + ")";
- DVLOG(1) << ENDPOINT << error_details;
+ const string error_details = QuicStrCat(
+ "Write failed with error: ", error_code, " (", strerror(error_code), ")");
+ QUIC_LOG_FIRST_N(ERROR, 2) << ENDPOINT << error_details;
// We can't send an error as the socket is presumably borked.
switch (error_code) {
case kMessageTooBigErrorCode:
@@ -1869,10 +1730,10 @@ void QuicConnection::OnCongestionChange() {
visitor_->OnCongestionWindowChange(clock_->ApproximateNow());
// Uses the connection's smoothed RTT. If zero, uses initial_rtt.
- QuicTime::Delta rtt = sent_packet_manager_->GetRttStats()->smoothed_rtt();
+ QuicTime::Delta rtt = sent_packet_manager_.GetRttStats()->smoothed_rtt();
if (rtt.IsZero()) {
rtt = QuicTime::Delta::FromMicroseconds(
- sent_packet_manager_->GetRttStats()->initial_rtt_us());
+ sent_packet_manager_.GetRttStats()->initial_rtt_us());
}
if (debug_visitor_)
@@ -1890,7 +1751,7 @@ void QuicConnection::OnPathMtuIncreased(QuicPacketLength packet_size) {
}
void QuicConnection::OnHandshakeComplete() {
- sent_packet_manager_->SetHandshakeConfirmed();
+ sent_packet_manager_.SetHandshakeConfirmed();
// The client should immediately ack the SHLO to confirm the handshake is
// complete with the server.
if (perspective_ == Perspective::IS_CLIENT && !ack_queued_ &&
@@ -1905,20 +1766,16 @@ void QuicConnection::SendOrQueuePacket(SerializedPacket* packet) {
QUIC_BUG << "packet.encrypted_buffer == nullptr in to SendOrQueuePacket";
return;
}
- if (version() <= QUIC_VERSION_33) {
- sent_entropy_manager_.RecordPacketEntropyHash(packet->packet_number,
- packet->entropy_hash);
- }
// If there are already queued packets, queue this one immediately to ensure
// it's written in sequence number order.
if (!queued_packets_.empty() || !WritePacket(packet)) {
// Take ownership of the underlying encrypted packet.
- packet->encrypted_buffer = QuicUtils::CopyBuffer(*packet);
+ packet->encrypted_buffer = CopyBuffer(*packet);
queued_packets_.push_back(*packet);
packet->retransmittable_frames.clear();
}
- QuicUtils::ClearSerializedPacket(packet);
+ ClearSerializedPacket(packet);
}
void QuicConnection::OnPingTimeout() {
@@ -1949,17 +1806,17 @@ void QuicConnection::SendAck() {
}
void QuicConnection::OnRetransmissionTimeout() {
- DCHECK(sent_packet_manager_->HasUnackedPackets());
+ DCHECK(sent_packet_manager_.HasUnackedPackets());
if (close_connection_after_five_rtos_ &&
- sent_packet_manager_->GetConsecutiveRtoCount() >= 4) {
+ sent_packet_manager_.GetConsecutiveRtoCount() >= 4) {
// Close on the 5th consecutive RTO, so after 4 previous RTOs have occurred.
CloseConnection(QUIC_TOO_MANY_RTOS, "5 consecutive retransmission timeouts",
ConnectionCloseBehavior::SEND_CONNECTION_CLOSE_PACKET);
return;
}
- sent_packet_manager_->OnRetransmissionTimeout();
+ sent_packet_manager_.OnRetransmissionTimeout();
WriteIfNotBlocked();
// A write failure can result in the connection being closed, don't attempt to
@@ -1970,7 +1827,7 @@ void QuicConnection::OnRetransmissionTimeout() {
// In the TLP case, the SentPacketManager gives the connection the opportunity
// to send new data before retransmitting.
- if (sent_packet_manager_->MaybeRetransmitTailLossProbe()) {
+ if (sent_packet_manager_.MaybeRetransmitTailLossProbe()) {
// Send the pending retransmission now that it's been queued.
WriteIfNotBlocked();
}
@@ -2021,7 +1878,7 @@ const QuicDecrypter* QuicConnection::alternative_decrypter() const {
void QuicConnection::QueueUndecryptablePacket(
const QuicEncryptedPacket& packet) {
- DVLOG(1) << ENDPOINT << "Queueing undecryptable packet.";
+ QUIC_DVLOG(1) << ENDPOINT << "Queueing undecryptable packet.";
undecryptable_packets_.push_back(packet.Clone());
}
@@ -2031,14 +1888,14 @@ void QuicConnection::MaybeProcessUndecryptablePackets() {
}
while (connected_ && !undecryptable_packets_.empty()) {
- DVLOG(1) << ENDPOINT << "Attempting to process undecryptable packet";
+ QUIC_DVLOG(1) << ENDPOINT << "Attempting to process undecryptable packet";
QuicEncryptedPacket* packet = undecryptable_packets_.front().get();
if (!framer_.ProcessPacket(*packet) &&
framer_.error() == QUIC_DECRYPTION_FAILURE) {
- DVLOG(1) << ENDPOINT << "Unable to process undecryptable packet...";
+ QUIC_DVLOG(1) << ENDPOINT << "Unable to process undecryptable packet...";
break;
}
- DVLOG(1) << ENDPOINT << "Processed undecryptable packet!";
+ QUIC_DVLOG(1) << ENDPOINT << "Processed undecryptable packet!";
++stats_.packets_processed;
undecryptable_packets_.pop_front();
}
@@ -2065,13 +1922,13 @@ void QuicConnection::CloseConnection(
ConnectionCloseBehavior connection_close_behavior) {
DCHECK(!error_details.empty());
if (!connected_) {
- DVLOG(1) << "Connection is already closed.";
+ QUIC_DLOG(INFO) << "Connection is already closed.";
return;
}
- DVLOG(1) << ENDPOINT << "Closing connection: " << connection_id()
- << ", with error: " << QuicUtils::ErrorToString(error) << " ("
- << error << "), and details: " << error_details;
+ QUIC_DLOG(INFO) << ENDPOINT << "Closing connection: " << connection_id()
+ << ", with error: " << QuicErrorCodeToString(error) << " ("
+ << error << "), and details: " << error_details;
if (connection_close_behavior ==
ConnectionCloseBehavior::SEND_CONNECTION_CLOSE_PACKET) {
@@ -2082,14 +1939,19 @@ void QuicConnection::CloseConnection(
SendConnectionClosePacket(error, error_details, NO_ACK);
}
- TearDownLocalConnectionState(error, error_details,
- ConnectionCloseSource::FROM_SELF);
+ ConnectionCloseSource source = ConnectionCloseSource::FROM_SELF;
+ if (perspective_ == Perspective::IS_CLIENT &&
+ error == QUIC_CRYPTO_HANDSHAKE_STATELESS_REJECT) {
+ // Regard stateless rejected connection as closed by server.
+ source = ConnectionCloseSource::FROM_PEER;
+ }
+ TearDownLocalConnectionState(error, error_details, source);
}
void QuicConnection::SendConnectionClosePacket(QuicErrorCode error,
const string& details,
AckBundling ack_mode) {
- DVLOG(1) << ENDPOINT << "Sending connection close packet.";
+ QUIC_DLOG(INFO) << ENDPOINT << "Sending connection close packet.";
ClearQueuedPackets();
ScopedPacketBundler ack_bundler(this, ack_mode);
QuicConnectionCloseFrame* frame = new QuicConnectionCloseFrame();
@@ -2104,7 +1966,7 @@ void QuicConnection::TearDownLocalConnectionState(
const string& error_details,
ConnectionCloseSource source) {
if (!connected_) {
- DVLOG(1) << "Connection is already closed.";
+ QUIC_DLOG(INFO) << "Connection is already closed.";
return;
}
connected_ = false;
@@ -2126,6 +1988,8 @@ void QuicConnection::TearDownLocalConnectionState(
}
void QuicConnection::CancelAllAlarms() {
+ QUIC_DVLOG(1) << "Cancelling all QuicConnection alarms.";
+
ack_alarm_->Cancel();
ping_alarm_->Cancel();
resume_writes_alarm_->Cancel();
@@ -2143,8 +2007,8 @@ void QuicConnection::SendGoAway(QuicErrorCode error,
}
goaway_sent_ = true;
- DVLOG(1) << ENDPOINT << "Going away with error "
- << QuicUtils::ErrorToString(error) << " (" << error << ")";
+ QUIC_DLOG(INFO) << ENDPOINT << "Going away with error "
+ << QuicErrorCodeToString(error) << " (" << error << ")";
// Opportunistically bundle an ack with this outgoing packet.
ScopedPacketBundler ack_bundler(this, SEND_ACK_IF_PENDING);
@@ -2207,21 +2071,21 @@ void QuicConnection::SetNetworkTimeouts(QuicTime::Delta handshake_timeout,
void QuicConnection::CheckForTimeout() {
QuicTime now = clock_->ApproximateNow();
QuicTime time_of_last_packet =
- max(time_of_last_received_packet_, last_send_for_timeout_);
+ std::max(time_of_last_received_packet_, last_send_for_timeout_);
// |delta| can be < 0 as |now| is approximate time but |time_of_last_packet|
// is accurate time. However, this should not change the behavior of
// timeout handling.
QuicTime::Delta idle_duration = now - time_of_last_packet;
- DVLOG(1) << ENDPOINT << "last packet "
- << time_of_last_packet.ToDebuggingValue()
- << " now:" << now.ToDebuggingValue()
- << " idle_duration:" << idle_duration.ToMicroseconds()
- << " idle_network_timeout: "
- << idle_network_timeout_.ToMicroseconds();
+ QUIC_DVLOG(1) << ENDPOINT << "last packet "
+ << time_of_last_packet.ToDebuggingValue()
+ << " now:" << now.ToDebuggingValue()
+ << " idle_duration:" << idle_duration.ToMicroseconds()
+ << " idle_network_timeout: "
+ << idle_network_timeout_.ToMicroseconds();
if (idle_duration >= idle_network_timeout_) {
const string error_details = "No recent network activity.";
- DVLOG(1) << ENDPOINT << error_details;
+ QUIC_DVLOG(1) << ENDPOINT << error_details;
CloseConnection(QUIC_NETWORK_IDLE_TIMEOUT, error_details,
idle_timeout_connection_close_behavior_);
return;
@@ -2229,12 +2093,13 @@ void QuicConnection::CheckForTimeout() {
if (!handshake_timeout_.IsInfinite()) {
QuicTime::Delta connected_duration = now - stats_.connection_creation_time;
- DVLOG(1) << ENDPOINT
- << "connection time: " << connected_duration.ToMicroseconds()
- << " handshake timeout: " << handshake_timeout_.ToMicroseconds();
+ QUIC_DVLOG(1) << ENDPOINT
+ << "connection time: " << connected_duration.ToMicroseconds()
+ << " handshake timeout: "
+ << handshake_timeout_.ToMicroseconds();
if (connected_duration >= handshake_timeout_) {
const string error_details = "Handshake timeout expired.";
- DVLOG(1) << ENDPOINT << error_details;
+ QUIC_DVLOG(1) << ENDPOINT << error_details;
CloseConnection(QUIC_HANDSHAKE_TIMEOUT, error_details,
ConnectionCloseBehavior::SEND_CONNECTION_CLOSE_PACKET);
return;
@@ -2246,14 +2111,14 @@ void QuicConnection::CheckForTimeout() {
void QuicConnection::SetTimeoutAlarm() {
QuicTime time_of_last_packet =
- max(time_of_last_received_packet_, time_of_last_sent_new_packet_);
+ std::max(time_of_last_received_packet_, time_of_last_sent_new_packet_);
time_of_last_packet =
- max(time_of_last_received_packet_, last_send_for_timeout_);
+ std::max(time_of_last_received_packet_, last_send_for_timeout_);
QuicTime deadline = time_of_last_packet + idle_network_timeout_;
if (!handshake_timeout_.IsInfinite()) {
- deadline =
- min(deadline, stats_.connection_creation_time + handshake_timeout_);
+ deadline = std::min(deadline,
+ stats_.connection_creation_time + handshake_timeout_);
}
timeout_alarm_->Update(deadline, QuicTime::Delta::Zero());
@@ -2278,7 +2143,7 @@ void QuicConnection::SetRetransmissionAlarm() {
pending_retransmission_alarm_ = true;
return;
}
- QuicTime retransmission_time = sent_packet_manager_->GetRetransmissionTime();
+ QuicTime retransmission_time = sent_packet_manager_.GetRetransmissionTime();
retransmission_alarm_->Update(retransmission_time,
QuicTime::Delta::FromMilliseconds(1));
}
@@ -2318,11 +2183,11 @@ QuicConnection::ScopedPacketBundler::ScopedPacketBundler(
// Move generator into batch mode. If caller wants us to include an ack,
// check the delayed-ack timer to see if there's ack info to be sent.
if (!already_in_batch_mode_) {
- DVLOG(2) << "Entering Batch Mode.";
+ QUIC_DVLOG(2) << "Entering Batch Mode.";
connection_->packet_generator_.StartBatchOperations();
}
if (ShouldSendAck(ack_mode)) {
- DVLOG(1) << "Bundling ack with outgoing packet.";
+ QUIC_DVLOG(1) << "Bundling ack with outgoing packet.";
DCHECK(ack_mode == SEND_ACK || connection_->ack_frame_updated() ||
connection_->stop_waiting_count_ > 1);
connection_->SendAck();
@@ -2353,7 +2218,7 @@ QuicConnection::ScopedPacketBundler::~ScopedPacketBundler() {
}
// If we changed the generator's batch state, restore original batch state.
if (!already_in_batch_mode_) {
- DVLOG(2) << "Leaving Batch Mode.";
+ QUIC_DVLOG(2) << "Leaving Batch Mode.";
connection_->packet_generator_.FinishBatchOperations();
// Once all transmissions are done, check if there is any outstanding data
@@ -2434,7 +2299,7 @@ void QuicConnection::SetMtuDiscoveryTarget(QuicByteCount target) {
QuicByteCount QuicConnection::GetLimitedMaxPacketSize(
QuicByteCount suggested_max_packet_size) {
- if (peer_address_.address().empty()) {
+ if (!peer_address_.IsInitialized()) {
QUIC_BUG << "Attempted to use a connection without a valid peer address";
return suggested_max_packet_size;
}
@@ -2476,13 +2341,13 @@ void QuicConnection::DiscoverMtu() {
packet_number_of_last_sent_packet_ + packets_between_mtu_probes_ + 1;
++mtu_probe_count_;
- DVLOG(2) << "Sending a path MTU discovery packet #" << mtu_probe_count_;
+ QUIC_DVLOG(2) << "Sending a path MTU discovery packet #" << mtu_probe_count_;
SendMtuDiscoveryPacket(mtu_discovery_target_);
DCHECK(!mtu_discovery_alarm_->IsSet());
}
-void QuicConnection::OnPeerMigrationValidated(QuicPathId path_id) {
+void QuicConnection::OnPeerMigrationValidated() {
if (active_peer_migration_type_ == NO_CHANGE) {
QUIC_BUG << "No migration underway.";
return;
@@ -2496,7 +2361,6 @@ void QuicConnection::OnPeerMigrationValidated(QuicPathId path_id) {
// migration. This should happen even if a migration is underway, since the
// most recent migration is the one that we should pay attention to.
void QuicConnection::StartPeerMigration(
- QuicPathId path_id,
PeerAddressChangeType peer_migration_type) {
// TODO(fayang): Currently, all peer address change type are allowed. Need to
// add a method ShouldAllowPeerAddressChange(PeerAddressChangeType type) to
@@ -2506,10 +2370,10 @@ void QuicConnection::StartPeerMigration(
QUIC_BUG << "Migration underway or no new migration started.";
return;
}
- DVLOG(1) << ENDPOINT << "Peer's ip:port changed from "
- << peer_address_.ToString() << " to "
- << last_packet_source_address_.ToString()
- << ", migrating connection.";
+ QUIC_DLOG(INFO) << ENDPOINT << "Peer's ip:port changed from "
+ << peer_address_.ToString() << " to "
+ << last_packet_source_address_.ToString()
+ << ", migrating connection.";
highest_packet_sent_before_peer_migration_ =
packet_number_of_last_sent_packet_;
@@ -2519,7 +2383,7 @@ void QuicConnection::StartPeerMigration(
// TODO(jri): Move these calls to OnPeerMigrationValidated. Rename
// OnConnectionMigration methods to OnPeerMigration.
visitor_->OnConnectionMigration(peer_migration_type);
- sent_packet_manager_->OnConnectionMigration(path_id, peer_migration_type);
+ sent_packet_manager_.OnConnectionMigration(peer_migration_type);
}
void QuicConnection::OnPathClosed(QuicPathId path_id) {
@@ -2578,14 +2442,14 @@ bool QuicConnection::MaybeConsiderAsMemoryCorruption(
// of (likely, tail) latency, then consider such a mechanism.
const QuicTime::Delta QuicConnection::DelayedAckTime() {
return QuicTime::Delta::FromMilliseconds(
- min(kMaxDelayedAckTimeMs, kMinRetransmissionTimeMs / 2));
+ std::min(kMaxDelayedAckTimeMs, kMinRetransmissionTimeMs / 2));
}
void QuicConnection::CheckIfApplicationLimited() {
if (queued_packets_.empty() &&
- !sent_packet_manager_->HasPendingRetransmissions() &&
+ !sent_packet_manager_.HasPendingRetransmissions() &&
!visitor_->WillingAndAbleToWrite()) {
- sent_packet_manager_->OnApplicationLimited();
+ sent_packet_manager_.OnApplicationLimited();
}
}
diff --git a/chromium/net/quic/core/quic_connection.h b/chromium/net/quic/core/quic_connection.h
index 456eec5fe60..b5d34f5b081 100644
--- a/chromium/net/quic/core/quic_connection.h
+++ b/chromium/net/quic/core/quic_connection.h
@@ -13,8 +13,8 @@
//
// Note: this class is not thread-safe.
-#ifndef NET_QUIC_QUIC_CONNECTION_H_
-#define NET_QUIC_QUIC_CONNECTION_H_
+#ifndef NET_QUIC_CORE_QUIC_CONNECTION_H_
+#define NET_QUIC_CORE_QUIC_CONNECTION_H_
#include <stddef.h>
#include <stdint.h>
@@ -27,29 +27,25 @@
#include <string>
#include <vector>
-#include "base/logging.h"
#include "base/macros.h"
#include "base/strings/string_piece.h"
-#include "net/base/ip_address.h"
-#include "net/base/ip_endpoint.h"
-#include "net/base/net_export.h"
#include "net/quic/core/crypto/quic_decrypter.h"
#include "net/quic/core/quic_alarm.h"
#include "net/quic/core/quic_alarm_factory.h"
#include "net/quic/core/quic_blocked_writer_interface.h"
#include "net/quic/core/quic_connection_stats.h"
#include "net/quic/core/quic_framer.h"
-#include "net/quic/core/quic_multipath_sent_packet_manager.h"
#include "net/quic/core/quic_one_block_arena.h"
#include "net/quic/core/quic_packet_creator.h"
#include "net/quic/core/quic_packet_generator.h"
#include "net/quic/core/quic_packet_writer.h"
-#include "net/quic/core/quic_protocol.h"
+#include "net/quic/core/quic_packets.h"
#include "net/quic/core/quic_received_packet_manager.h"
-#include "net/quic/core/quic_sent_entropy_manager.h"
-#include "net/quic/core/quic_sent_packet_manager_interface.h"
+#include "net/quic/core/quic_sent_packet_manager.h"
#include "net/quic/core/quic_time.h"
#include "net/quic/core/quic_types.h"
+#include "net/quic/platform/api/quic_export.h"
+#include "net/quic/platform/api/quic_socket_address.h"
namespace net {
@@ -95,7 +91,7 @@ static_assert(kMtuDiscoveryTargetPacketSizeHigh > kDefaultMaxPacketSize,
// Class that receives callbacks from the connection when frames are received
// and when other interesting events happen.
-class NET_EXPORT_PRIVATE QuicConnectionVisitorInterface {
+class QUIC_EXPORT_PRIVATE QuicConnectionVisitorInterface {
public:
virtual ~QuicConnectionVisitorInterface() {}
@@ -163,8 +159,8 @@ class NET_EXPORT_PRIVATE QuicConnectionVisitorInterface {
// Interface which gets callbacks from the QuicConnection at interesting
// points. Implementations must not mutate the state of the connection
// as a result of these callbacks.
-class NET_EXPORT_PRIVATE QuicConnectionDebugVisitor
- : public QuicSentPacketManagerInterface::DebugDelegate {
+class QUIC_EXPORT_PRIVATE QuicConnectionDebugVisitor
+ : public QuicSentPacketManager::DebugDelegate {
public:
~QuicConnectionDebugVisitor() override {}
@@ -180,8 +176,8 @@ class NET_EXPORT_PRIVATE QuicConnectionDebugVisitor
// Called when a packet has been received, but before it is
// validated or parsed.
- virtual void OnPacketReceived(const IPEndPoint& self_address,
- const IPEndPoint& peer_address,
+ virtual void OnPacketReceived(const QuicSocketAddress& self_address,
+ const QuicSocketAddress& peer_address,
const QuicEncryptedPacket& packet) {}
// Called when the unauthenticated portion of the header has been parsed.
@@ -273,7 +269,7 @@ class NET_EXPORT_PRIVATE QuicConnectionDebugVisitor
// ordinarily be on the heap. Instead, store them inline in an arena.
using QuicConnectionArena = QuicOneBlockArena<1024>;
-class NET_EXPORT_PRIVATE QuicConnectionHelperInterface {
+class QUIC_EXPORT_PRIVATE QuicConnectionHelperInterface {
public:
virtual ~QuicConnectionHelperInterface() {}
@@ -287,11 +283,11 @@ class NET_EXPORT_PRIVATE QuicConnectionHelperInterface {
virtual QuicBufferAllocator* GetBufferAllocator() = 0;
};
-class NET_EXPORT_PRIVATE QuicConnection
+class QUIC_EXPORT_PRIVATE QuicConnection
: public QuicFramerVisitorInterface,
public QuicBlockedWriterInterface,
public QuicPacketGenerator::DelegateInterface,
- public QuicSentPacketManagerInterface::NetworkChangeVisitor {
+ public QuicSentPacketManager::NetworkChangeVisitor {
public:
enum AckBundling {
// Send an ack if it's already queued in the connection.
@@ -310,7 +306,7 @@ class NET_EXPORT_PRIVATE QuicConnection
// |writer| to write packets. |owns_writer| specifies whether the connection
// takes ownership of |writer|. |helper| must outlive this connection.
QuicConnection(QuicConnectionId connection_id,
- IPEndPoint address,
+ QuicSocketAddress address,
QuicConnectionHelperInterface* helper,
QuicAlarmFactory* alarm_factory,
QuicPacketWriter* writer,
@@ -349,11 +345,12 @@ class NET_EXPORT_PRIVATE QuicConnection
// If |listener| is provided, then it will be informed once ACKs have been
// received for all the packets written in this call.
// The |listener| is not owned by the QuicConnection and must outlive it.
- virtual QuicConsumedData SendStreamData(QuicStreamId id,
- QuicIOVector iov,
- QuicStreamOffset offset,
- bool fin,
- QuicAckListenerInterface* listener);
+ virtual QuicConsumedData SendStreamData(
+ QuicStreamId id,
+ QuicIOVector iov,
+ QuicStreamOffset offset,
+ bool fin,
+ QuicReferenceCountedPointer<QuicAckListenerInterface> ack_listener);
// Send a RST_STREAM frame to the peer.
virtual void SendRstStream(QuicStreamId id,
@@ -389,8 +386,8 @@ class NET_EXPORT_PRIVATE QuicConnection
// the peer.
// In a client, the packet may be "stray" and have a different connection ID
// than that of this connection.
- virtual void ProcessUdpPacket(const IPEndPoint& self_address,
- const IPEndPoint& peer_address,
+ virtual void ProcessUdpPacket(const QuicSocketAddress& self_address,
+ const QuicSocketAddress& peer_address,
const QuicReceivedPacket& packet);
// QuicBlockedWriterInterface
@@ -420,7 +417,7 @@ class NET_EXPORT_PRIVATE QuicConnection
}
// Set self address.
- void SetSelfAddress(IPEndPoint address) { self_address_ = address; }
+ void SetSelfAddress(QuicSocketAddress address) { self_address_ = address; }
// The version of the protocol this connection is using.
QuicVersion version() const { return framer_.version(); }
@@ -485,7 +482,7 @@ class NET_EXPORT_PRIVATE QuicConnection
}
void set_debug_visitor(QuicConnectionDebugVisitor* debug_visitor) {
debug_visitor_ = debug_visitor;
- sent_packet_manager_->SetDebugDelegate(debug_visitor);
+ sent_packet_manager_.SetDebugDelegate(debug_visitor);
}
void set_ping_timeout(QuicTime::Delta ping_timeout) {
ping_timeout_ = ping_timeout;
@@ -495,8 +492,8 @@ class NET_EXPORT_PRIVATE QuicConnection
void set_creator_debug_delegate(QuicPacketCreator::DebugDelegate* visitor) {
packet_generator_.set_debug_delegate(visitor);
}
- const IPEndPoint& self_address() const { return self_address_; }
- const IPEndPoint& peer_address() const { return peer_address_; }
+ const QuicSocketAddress& self_address() const { return self_address_; }
+ const QuicSocketAddress& peer_address() const { return peer_address_; }
QuicConnectionId connection_id() const { return connection_id_; }
const QuicClock* clock() const { return clock_; }
QuicRandom* random_generator() const { return random_generator_; }
@@ -606,8 +603,8 @@ class NET_EXPORT_PRIVATE QuicConnection
}
// Returns the underlying sent packet manager.
- const QuicSentPacketManagerInterface& sent_packet_manager() const {
- return *sent_packet_manager_;
+ const QuicSentPacketManager& sent_packet_manager() const {
+ return sent_packet_manager_;
}
bool CanWrite(HasRetransmittableData retransmittable);
@@ -618,7 +615,7 @@ class NET_EXPORT_PRIVATE QuicConnection
// as densely as possible into packets. In addition, this bundler
// can be configured to ensure that an ACK frame is included in the
// first packet created, if there's new ack information to be sent.
- class NET_EXPORT_PRIVATE ScopedPacketBundler {
+ class QUIC_EXPORT_PRIVATE ScopedPacketBundler {
public:
// In addition to all outgoing frames being bundled when the
// bundler is in scope, setting |include_ack| to true ensures that
@@ -637,7 +634,7 @@ class NET_EXPORT_PRIVATE QuicConnection
// Delays setting the retransmission alarm until the scope is exited.
// When nested, only the outermost scheduler will set the alarm, and inner
// ones have no effect.
- class NET_EXPORT_PRIVATE ScopedRetransmissionScheduler {
+ class QUIC_EXPORT_PRIVATE ScopedRetransmissionScheduler {
public:
explicit ScopedRetransmissionScheduler(QuicConnection* connection);
~ScopedRetransmissionScheduler();
@@ -693,7 +690,7 @@ class NET_EXPORT_PRIVATE QuicConnection
EncryptionLevel encryption_level() const { return encryption_level_; }
- const IPEndPoint& last_packet_source_address() const {
+ const QuicSocketAddress& last_packet_source_address() const {
return last_packet_source_address_;
}
@@ -705,13 +702,12 @@ class NET_EXPORT_PRIVATE QuicConnection
// cannot be written immediately.
virtual void SendOrQueuePacket(SerializedPacket* packet);
- // Called after a packet is received from a new peer address on existing
- // |path_id| and is decrypted. Starts validation of peer's address change.
- virtual void StartPeerMigration(QuicPathId path_id,
- PeerAddressChangeType peer_migration_type);
+ // Called after a packet is received from a new peer address and is decrypted.
+ // Starts validation of peer's address change.
+ virtual void StartPeerMigration(PeerAddressChangeType peer_migration_type);
- // Called when a peer address migration is validated on |path_id|.
- virtual void OnPeerMigrationValidated(QuicPathId path_id);
+ // Called when a peer address migration is validated.
+ virtual void OnPeerMigrationValidated();
// Selects and updates the version of the protocol being used by selecting a
// version from |available_versions| which is also supported. Returns true if
@@ -744,6 +740,9 @@ class NET_EXPORT_PRIVATE QuicConnection
const std::string& details,
AckBundling ack_mode);
+ // Returns true if the packet should be discarded and not sent.
+ virtual bool ShouldDiscardPacket(const SerializedPacket& packet);
+
private:
friend class test::QuicConnectionPeer;
friend class test::PacketSavingConnection;
@@ -784,10 +783,6 @@ class NET_EXPORT_PRIVATE QuicConnection
// Deletes and clears any queued packets.
void ClearQueuedPackets();
- // Closes the connection if the sent or received packet manager are tracking
- // too many outstanding packets.
- void MaybeCloseIfTooManyOutstandingPackets();
-
// Writes as many queued packets as possible. The connection must not be
// blocked when this is called.
void WriteQueuedPackets();
@@ -795,9 +790,6 @@ class NET_EXPORT_PRIVATE QuicConnection
// Writes as many pending retransmissions as possible.
void WritePendingRetransmissions();
- // Returns true if the packet should be discarded and not sent.
- bool ShouldDiscardPacket(const SerializedPacket& packet);
-
// Queues |packet| in the hopes that it can be decrypted in the
// future, when a new key is installed.
void QueueUndecryptablePacket(const QuicEncryptedPacket& packet);
@@ -817,9 +809,9 @@ class NET_EXPORT_PRIVATE QuicConnection
// the most recently received packet was formerly missing.
void MaybeQueueAck(bool was_missing);
- // Gets the least unacked packet number of |path_id|, which is the next packet
- // number to be sent if there are no outstanding packets.
- QuicPacketNumber GetLeastUnacked(QuicPathId path_id) const;
+ // Gets the least unacked packet number, which is the next packet number to be
+ // sent if there are no outstanding packets.
+ QuicPacketNumber GetLeastUnacked() const;
// Sets the timeout alarm to the appropriate value, if any.
void SetTimeoutAlarm();
@@ -882,8 +874,8 @@ class NET_EXPORT_PRIVATE QuicConnection
const QuicConnectionId connection_id_;
// Address on the last successfully processed packet received from the
// client.
- IPEndPoint self_address_;
- IPEndPoint peer_address_;
+ QuicSocketAddress self_address_;
+ QuicSocketAddress peer_address_;
// Records change type when the peer initiates migration to a new peer
// address. Reset to NO_CHANGE after peer migration is validated.
@@ -902,7 +894,8 @@ class NET_EXPORT_PRIVATE QuicConnection
EncryptionLevel last_decrypted_packet_level_;
QuicPacketHeader last_header_;
// TODO(ianswett): Remove last_stop_waiting_frame_ once
- // FLAGS_quic_receive_packet_once_decrypted is deprecated.
+ // FLAGS_quic_reloadable_flag_quic_receive_packet_once_decrypted is
+ // deprecated.
QuicStopWaitingFrame last_stop_waiting_frame_;
bool should_last_packet_instigate_acks_;
// Whether the most recent packet was missing before it was received.
@@ -953,7 +946,6 @@ class NET_EXPORT_PRIVATE QuicConnection
bool close_connection_after_five_rtos_;
QuicReceivedPacketManager received_packet_manager_;
- QuicSentEntropyManager sent_entropy_manager_;
// Indicates whether an ack should be sent the next time we try to write.
bool ack_queued_;
@@ -1039,9 +1031,22 @@ class NET_EXPORT_PRIVATE QuicConnection
// Sent packet manager which tracks the status of packets sent by this
// connection and contains the send and receive algorithms to determine when
// to send packets.
- std::unique_ptr<QuicSentPacketManagerInterface> sent_packet_manager_;
+ QuicSentPacketManager sent_packet_manager_;
// The state of connection in version negotiation finite state machine.
+ enum QuicVersionNegotiationState {
+ START_NEGOTIATION = 0,
+ // Server-side this implies we've sent a version negotiation packet and are
+ // waiting on the client to select a compatible version. Client-side this
+ // implies we've gotten a version negotiation packet, are retransmitting the
+ // initial packets with a supported version and are waiting for our first
+ // packet from the server.
+ NEGOTIATION_IN_PROGRESS,
+ // This indicates this endpoint has received a packet from the peer with a
+ // version this endpoint supports. Version negotiation is complete, and the
+ // version number will no longer be sent with future packets.
+ NEGOTIATED_VERSION
+ };
QuicVersionNegotiationState version_negotiation_state_;
// Tracks if the connection was created by the server or the client.
@@ -1052,10 +1057,10 @@ class NET_EXPORT_PRIVATE QuicConnection
bool connected_;
// Destination address of the last received packet.
- IPEndPoint last_packet_destination_address_;
+ QuicSocketAddress last_packet_destination_address_;
// Source address of the last received packet.
- IPEndPoint last_packet_source_address_;
+ QuicSocketAddress last_packet_source_address_;
// Set to false if the connection should not send truncated connection IDs to
// the peer, even if the peer supports it.
@@ -1106,4 +1111,4 @@ class NET_EXPORT_PRIVATE QuicConnection
} // namespace net
-#endif // NET_QUIC_QUIC_CONNECTION_H_
+#endif // NET_QUIC_CORE_QUIC_CONNECTION_H_
diff --git a/chromium/net/quic/core/quic_connection_close_delegate_interface.h b/chromium/net/quic/core/quic_connection_close_delegate_interface.h
new file mode 100644
index 00000000000..1544874c485
--- /dev/null
+++ b/chromium/net/quic/core/quic_connection_close_delegate_interface.h
@@ -0,0 +1,27 @@
+// Copyright (c) 2016 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.
+
+#ifndef NET_QUIC_CORE_QUIC_CONNECTION_CLOSE_DELEGATE_INTERFACE_H_
+#define NET_QUIC_CORE_QUIC_CONNECTION_CLOSE_DELEGATE_INTERFACE_H_
+
+#include "net/quic/core/quic_error_codes.h"
+#include "net/quic/core/quic_types.h"
+#include "net/quic/platform/api/quic_export.h"
+
+namespace net {
+
+// Pure virtual class to close connection on unrecoverable errors.
+class QUIC_EXPORT_PRIVATE QuicConnectionCloseDelegateInterface {
+ public:
+ virtual ~QuicConnectionCloseDelegateInterface() {}
+
+ // Called when an unrecoverable error is encountered.
+ virtual void OnUnrecoverableError(QuicErrorCode error,
+ const std::string& error_details,
+ ConnectionCloseSource source) = 0;
+};
+
+} // namespace net
+
+#endif // NET_QUIC_CORE_QUIC_CONNECTION_CLOSE_DELEGATE_INTERFACE_H_
diff --git a/chromium/net/quic/core/quic_connection_stats.cc b/chromium/net/quic/core/quic_connection_stats.cc
index 7d50bf8f567..759c4620159 100644
--- a/chromium/net/quic/core/quic_connection_stats.cc
+++ b/chromium/net/quic/core/quic_connection_stats.cc
@@ -4,8 +4,6 @@
#include "net/quic/core/quic_connection_stats.h"
-using std::ostream;
-
namespace net {
QuicConnectionStats::QuicConnectionStats()
@@ -48,4 +46,44 @@ QuicConnectionStats::QuicConnectionStats(const QuicConnectionStats& other) =
QuicConnectionStats::~QuicConnectionStats() {}
+std::ostream& operator<<(std::ostream& os, const QuicConnectionStats& s) {
+ os << "{ bytes_sent: " << s.bytes_sent;
+ os << " packets_sent: " << s.packets_sent;
+ os << " stream_bytes_sent: " << s.stream_bytes_sent;
+ os << " packets_discarded: " << s.packets_discarded;
+ os << " bytes_received: " << s.bytes_received;
+ os << " packets_received: " << s.packets_received;
+ os << " packets_processed: " << s.packets_processed;
+ os << " stream_bytes_received: " << s.stream_bytes_received;
+ os << " bytes_retransmitted: " << s.bytes_retransmitted;
+ os << " packets_retransmitted: " << s.packets_retransmitted;
+ os << " bytes_spuriously_retransmitted: " << s.bytes_spuriously_retransmitted;
+ os << " packets_spuriously_retransmitted: "
+ << s.packets_spuriously_retransmitted;
+ os << " packets_lost: " << s.packets_lost;
+ os << " slowstart_packets_sent: " << s.slowstart_packets_sent;
+ os << " slowstart_packets_lost: " << s.slowstart_packets_lost;
+ os << " slowstart_bytes_lost: " << s.slowstart_bytes_lost;
+ os << " packets_dropped: " << s.packets_dropped;
+ os << " crypto_retransmit_count: " << s.crypto_retransmit_count;
+ os << " loss_timeout_count: " << s.loss_timeout_count;
+ os << " tlp_count: " << s.tlp_count;
+ os << " rto_count: " << s.rto_count;
+ os << " min_rtt_us: " << s.min_rtt_us;
+ os << " srtt_us: " << s.srtt_us;
+ os << " max_packet_size: " << s.max_packet_size;
+ os << " max_received_packet_size: " << s.max_received_packet_size;
+ os << " estimated_bandwidth: " << s.estimated_bandwidth;
+ os << " packets_reordered: " << s.packets_reordered;
+ os << " max_sequence_reordering: " << s.max_sequence_reordering;
+ os << " max_time_reordering_us: " << s.max_time_reordering_us;
+ os << " tcp_loss_events: " << s.tcp_loss_events;
+ os << " connection_creation_time: "
+ << s.connection_creation_time.ToDebuggingValue();
+ os << " blocked_frames_received: " << s.blocked_frames_received;
+ os << " blocked_frames_sent: " << s.blocked_frames_sent << " }";
+
+ return os;
+}
+
} // namespace net
diff --git a/chromium/net/quic/core/quic_connection_stats.h b/chromium/net/quic/core/quic_connection_stats.h
index e125f2910fa..57f7c789431 100644
--- a/chromium/net/quic/core/quic_connection_stats.h
+++ b/chromium/net/quic/core/quic_connection_stats.h
@@ -2,27 +2,27 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#ifndef NET_QUIC_QUIC_CONNECTION_STATS_H_
-#define NET_QUIC_QUIC_CONNECTION_STATS_H_
+#ifndef NET_QUIC_CORE_QUIC_CONNECTION_STATS_H_
+#define NET_QUIC_CORE_QUIC_CONNECTION_STATS_H_
#include <stddef.h>
#include <stdint.h>
#include <ostream>
-#include "net/base/net_export.h"
#include "net/quic/core/quic_bandwidth.h"
-#include "net/quic/core/quic_protocol.h"
+#include "net/quic/core/quic_packets.h"
#include "net/quic/core/quic_time.h"
+#include "net/quic/platform/api/quic_export.h"
namespace net {
// Structure to hold stats for a QuicConnection.
-struct NET_EXPORT_PRIVATE QuicConnectionStats {
+struct QUIC_EXPORT_PRIVATE QuicConnectionStats {
QuicConnectionStats();
QuicConnectionStats(const QuicConnectionStats& other);
~QuicConnectionStats();
- NET_EXPORT_PRIVATE friend std::ostream& operator<<(
+ QUIC_EXPORT_PRIVATE friend std::ostream& operator<<(
std::ostream& os,
const QuicConnectionStats& s);
@@ -93,4 +93,4 @@ struct NET_EXPORT_PRIVATE QuicConnectionStats {
} // namespace net
-#endif // NET_QUIC_QUIC_CONNECTION_STATS_H_
+#endif // NET_QUIC_CORE_QUIC_CONNECTION_STATS_H_
diff --git a/chromium/net/quic/core/quic_connection_test.cc b/chromium/net/quic/core/quic_connection_test.cc
index 8f4e599046a..5b351b39bb5 100644
--- a/chromium/net/quic/core/quic_connection_test.cc
+++ b/chromium/net/quic/core/quic_connection_test.cc
@@ -12,7 +12,6 @@
#include "base/bind.h"
#include "base/macros.h"
#include "base/stl_util.h"
-#include "net/base/ip_address.h"
#include "net/base/net_errors.h"
#include "net/quic/core/congestion_control/loss_detection_interface.h"
#include "net/quic/core/congestion_control/send_algorithm_interface.h"
@@ -20,9 +19,12 @@
#include "net/quic/core/crypto/quic_decrypter.h"
#include "net/quic/core/crypto/quic_encrypter.h"
#include "net/quic/core/quic_flags.h"
-#include "net/quic/core/quic_protocol.h"
+#include "net/quic/core/quic_packets.h"
#include "net/quic/core/quic_simple_buffer_allocator.h"
#include "net/quic/core/quic_utils.h"
+#include "net/quic/platform/api/quic_logging.h"
+#include "net/quic/platform/api/quic_reference_counted.h"
+#include "net/quic/platform/api/quic_str_cat.h"
#include "net/quic/test_tools/mock_clock.h"
#include "net/quic/test_tools/mock_random.h"
#include "net/quic/test_tools/quic_config_peer.h"
@@ -38,13 +40,9 @@
#include "testing/gtest/include/gtest/gtest.h"
using base::StringPiece;
-using std::map;
-using std::ostream;
using std::string;
-using std::vector;
using testing::AnyNumber;
using testing::AtLeast;
-using testing::Contains;
using testing::DoAll;
using testing::InSequence;
using testing::InvokeWithoutArgs;
@@ -64,15 +62,16 @@ const char data1[] = "foo";
const char data2[] = "bar";
const bool kFin = true;
-const bool kEntropyFlag = true;
const bool kHasStopWaiting = true;
-const QuicPacketEntropyHash kTestEntropyHash = 76;
-
const int kDefaultRetransmissionTimeMs = 500;
-const IPEndPoint kPeerAddress = IPEndPoint(Loopback6(), /*port=*/12345);
-const IPEndPoint kSelfAddress = IPEndPoint(Loopback6(), /*port=*/443);
+const QuicSocketAddress kPeerAddress =
+ QuicSocketAddress(QuicIpAddress::Loopback6(),
+ /*port=*/12345);
+const QuicSocketAddress kSelfAddress =
+ QuicSocketAddress(QuicIpAddress::Loopback6(),
+ /*port=*/443);
Perspective InvertPerspective(Perspective perspective) {
return perspective == Perspective::IS_CLIENT ? Perspective::IS_SERVER
@@ -91,7 +90,8 @@ class TaggingEncrypter : public QuicEncrypter {
bool SetNoncePrefix(StringPiece nonce_prefix) override { return true; }
- bool EncryptPacket(QuicPathId path_id,
+ bool EncryptPacket(QuicVersion /*version*/,
+ QuicPathId path_id,
QuicPacketNumber packet_number,
StringPiece associated_data,
StringPiece plaintext,
@@ -155,7 +155,8 @@ class TaggingDecrypter : public QuicDecrypter {
return true;
}
- bool DecryptPacket(QuicPathId path_id,
+ bool DecryptPacket(QuicVersion /*version*/,
+ QuicPathId path_id,
QuicPacketNumber packet_number,
StringPiece associated_data,
StringPiece ciphertext,
@@ -274,7 +275,7 @@ class TestPacketWriter : public QuicPacketWriter {
public:
TestPacketWriter(QuicVersion version, MockClock* clock)
: version_(version),
- framer_(SupportedVersions(version_)),
+ framer_(SupportedVersions(version_), Perspective::IS_SERVER),
last_packet_size_(0),
write_blocked_(false),
write_should_fail_(false),
@@ -293,8 +294,8 @@ class TestPacketWriter : public QuicPacketWriter {
// QuicPacketWriter interface
WriteResult WritePacket(const char* buffer,
size_t buf_len,
- const IPAddress& self_address,
- const IPEndPoint& peer_address,
+ const QuicIpAddress& self_address,
+ const QuicSocketAddress& peer_address,
PerPacketOptions* options) override {
QuicEncryptedPacket packet(buffer, buf_len);
++packets_write_attempts_;
@@ -350,7 +351,7 @@ class TestPacketWriter : public QuicPacketWriter {
void SetShouldWriteFail() { write_should_fail_ = true; }
QuicByteCount GetMaxPacketSize(
- const IPEndPoint& /*peer_address*/) const override {
+ const QuicSocketAddress& /*peer_address*/) const override {
return max_packet_size_;
}
@@ -369,27 +370,27 @@ class TestPacketWriter : public QuicPacketWriter {
size_t frame_count() const { return framer_.num_frames(); }
- const vector<QuicAckFrame>& ack_frames() const {
+ const std::vector<QuicAckFrame>& ack_frames() const {
return framer_.ack_frames();
}
- const vector<QuicStopWaitingFrame>& stop_waiting_frames() const {
+ const std::vector<QuicStopWaitingFrame>& stop_waiting_frames() const {
return framer_.stop_waiting_frames();
}
- const vector<QuicConnectionCloseFrame>& connection_close_frames() const {
+ const std::vector<QuicConnectionCloseFrame>& connection_close_frames() const {
return framer_.connection_close_frames();
}
- const vector<QuicRstStreamFrame>& rst_stream_frames() const {
+ const std::vector<QuicRstStreamFrame>& rst_stream_frames() const {
return framer_.rst_stream_frames();
}
- const vector<std::unique_ptr<QuicStreamFrame>>& stream_frames() const {
+ const std::vector<std::unique_ptr<QuicStreamFrame>>& stream_frames() const {
return framer_.stream_frames();
}
- const vector<QuicPingFrame>& ping_frames() const {
+ const std::vector<QuicPingFrame>& ping_frames() const {
return framer_.ping_frames();
}
@@ -461,7 +462,7 @@ class TestPacketWriter : public QuicPacketWriter {
class TestConnection : public QuicConnection {
public:
TestConnection(QuicConnectionId connection_id,
- IPEndPoint address,
+ QuicSocketAddress address,
TestConnectionHelper* helper,
TestAlarmFactory* alarm_factory,
TestPacketWriter* writer,
@@ -476,26 +477,23 @@ class TestConnection : public QuicConnection {
perspective,
SupportedVersions(version)) {
writer->set_perspective(perspective);
- SetEncrypter(ENCRYPTION_FORWARD_SECURE, new NullEncrypter());
+ SetEncrypter(ENCRYPTION_FORWARD_SECURE, new NullEncrypter(perspective));
}
void SendAck() { QuicConnectionPeer::SendAck(this); }
- void SetSendAlgorithm(QuicPathId path_id,
- SendAlgorithmInterface* send_algorithm) {
- QuicConnectionPeer::SetSendAlgorithm(this, path_id, send_algorithm);
+ void SetSendAlgorithm(SendAlgorithmInterface* send_algorithm) {
+ QuicConnectionPeer::SetSendAlgorithm(this, send_algorithm);
}
- void SetLossAlgorithm(QuicPathId path_id,
- LossDetectionInterface* loss_algorithm) {
- QuicConnectionPeer::SetLossAlgorithm(this, path_id, loss_algorithm);
+ void SetLossAlgorithm(LossDetectionInterface* loss_algorithm) {
+ QuicConnectionPeer::SetLossAlgorithm(this, loss_algorithm);
}
void SendPacket(EncryptionLevel level,
QuicPathId path_id,
QuicPacketNumber packet_number,
QuicPacket* packet,
- QuicPacketEntropyHash entropy_hash,
HasRetransmittableData retransmittable,
bool has_ack,
bool has_pending_frames) {
@@ -507,7 +505,7 @@ class TestConnection : public QuicConnection {
delete packet;
SerializedPacket serialized_packet(
kDefaultPathId, packet_number, PACKET_6BYTE_PACKET_NUMBER, buffer,
- encrypted_length, entropy_hash, has_ack, has_pending_frames);
+ encrypted_length, has_ack, has_pending_frames);
if (retransmittable == HAS_RETRANSMITTABLE_DATA) {
serialized_packet.retransmittable_frames.push_back(
QuicFrame(new QuicStreamFrame()));
@@ -520,13 +518,14 @@ class TestConnection : public QuicConnection {
StringPiece data,
QuicStreamOffset offset,
bool fin,
- QuicAckListenerInterface* listener) {
+ QuicReferenceCountedPointer<QuicAckListenerInterface> ack_listener) {
if (id != kCryptoStreamId && this->encryption_level() == ENCRYPTION_NONE) {
this->SetDefaultEncryptionLevel(ENCRYPTION_FORWARD_SECURE);
}
struct iovec iov;
QuicIOVector data_iov(MakeIOVector(data, &iov));
- return QuicConnection::SendStreamData(id, data_iov, offset, fin, listener);
+ return QuicConnection::SendStreamData(id, data_iov, offset, fin,
+ std::move(ack_listener));
}
QuicConsumedData SendStreamData3() {
@@ -622,15 +621,14 @@ class TestConnection : public QuicConnection {
QuicConnectionPeer::GetMtuDiscoveryAlarm(this));
}
- void SetMaxTailLossProbes(QuicPathId path_id, size_t max_tail_loss_probes) {
+ void SetMaxTailLossProbes(size_t max_tail_loss_probes) {
QuicSentPacketManagerPeer::SetMaxTailLossProbes(
- QuicConnectionPeer::GetSentPacketManager(this, path_id),
- max_tail_loss_probes);
+ QuicConnectionPeer::GetSentPacketManager(this), max_tail_loss_probes);
}
- QuicByteCount GetBytesInFlight(QuicPathId path_id) {
+ QuicByteCount GetBytesInFlight() {
return QuicSentPacketManagerPeer::GetBytesInFlight(
- QuicConnectionPeer::GetSentPacketManager(this, path_id));
+ QuicConnectionPeer::GetSentPacketManager(this));
}
using QuicConnection::SelectMutualVersion;
@@ -651,7 +649,7 @@ struct TestParams {
TestParams(QuicVersion version, AckResponse ack_response)
: version(version), ack_response(ack_response) {}
- friend ostream& operator<<(ostream& os, const TestParams& p) {
+ friend std::ostream& operator<<(std::ostream& os, const TestParams& p) {
os << "{ client_version: " << QuicVersionToString(p.version)
<< " ack_response: "
<< (p.ack_response == AckResponse::kDefer ? "defer" : "immediate")
@@ -664,8 +662,8 @@ struct TestParams {
};
// Constructs various test permutations.
-vector<TestParams> GetTestParams() {
- vector<TestParams> params;
+std::vector<TestParams> GetTestParams() {
+ std::vector<TestParams> params;
QuicVersionVector all_supported_versions = AllSupportedVersions();
for (size_t i = 0; i < all_supported_versions.size(); ++i) {
for (AckResponse ack_response :
@@ -692,7 +690,6 @@ class QuicConnectionTest : public ::testing::TestWithParam<TestParams> {
Perspective::IS_SERVER),
peer_creator_(connection_id_,
&peer_framer_,
- &random_generator_,
&buffer_allocator_,
/*delegate=*/nullptr),
writer_(new TestPacketWriter(version(), &clock_)),
@@ -705,8 +702,7 @@ class QuicConnectionTest : public ::testing::TestWithParam<TestParams> {
version()),
creator_(QuicConnectionPeer::GetPacketCreator(&connection_)),
generator_(QuicConnectionPeer::GetPacketGenerator(&connection_)),
- manager_(QuicConnectionPeer::GetSentPacketManager(&connection_,
- kDefaultPathId)),
+ manager_(QuicConnectionPeer::GetSentPacketManager(&connection_)),
frame1_(1, false, 0, StringPiece(data1)),
frame2_(1, false, 3, StringPiece(data2)),
packet_number_length_(PACKET_6BYTE_PACKET_NUMBER),
@@ -714,10 +710,8 @@ class QuicConnectionTest : public ::testing::TestWithParam<TestParams> {
connection_.set_defer_send_in_response_to_packets(GetParam().ack_response ==
AckResponse::kDefer);
connection_.set_visitor(&visitor_);
- connection_.SetSendAlgorithm(kDefaultPathId, send_algorithm_);
- connection_.SetLossAlgorithm(kDefaultPathId, loss_algorithm_.get());
- framer_.set_received_entropy_calculator(&entropy_calculator_);
- peer_framer_.set_received_entropy_calculator(&peer_entropy_calculator_);
+ connection_.SetSendAlgorithm(send_algorithm_);
+ connection_.SetLossAlgorithm(loss_algorithm_.get());
EXPECT_CALL(*send_algorithm_, TimeUntilSend(_, _))
.WillRepeatedly(Return(QuicTime::Delta::Zero()));
EXPECT_CALL(*send_algorithm_, OnPacketSent(_, _, _, _, _))
@@ -774,20 +768,19 @@ class QuicConnectionTest : public ::testing::TestWithParam<TestParams> {
void ProcessPacket(QuicPathId path_id, QuicPacketNumber number) {
EXPECT_CALL(visitor_, OnStreamFrame(_)).Times(1);
- ProcessDataPacket(path_id, number, !kEntropyFlag);
+ ProcessDataPacket(path_id, number);
if (connection_.GetSendAlarm()->IsSet()) {
connection_.GetSendAlarm()->Fire();
}
}
- QuicPacketEntropyHash ProcessFramePacket(QuicFrame frame) {
- return ProcessFramePacketWithAddresses(frame, kSelfAddress, kPeerAddress);
+ void ProcessFramePacket(QuicFrame frame) {
+ ProcessFramePacketWithAddresses(frame, kSelfAddress, kPeerAddress);
}
- QuicPacketEntropyHash ProcessFramePacketWithAddresses(
- QuicFrame frame,
- IPEndPoint self_address,
- IPEndPoint peer_address) {
+ void ProcessFramePacketWithAddresses(QuicFrame frame,
+ QuicSocketAddress self_address,
+ QuicSocketAddress peer_address) {
QuicFrames frames;
frames.push_back(QuicFrame(frame));
QuicPacketCreatorPeer::SetSendVersionInPacket(
@@ -804,7 +797,6 @@ class QuicConnectionTest : public ::testing::TestWithParam<TestParams> {
if (connection_.GetSendAlarm()->IsSet()) {
connection_.GetSendAlarm()->Fire();
}
- return serialized_packet.entropy_hash;
}
// Bypassing the packet creator is unrealistic, but allows us to process
@@ -832,10 +824,10 @@ class QuicConnectionTest : public ::testing::TestWithParam<TestParams> {
QuicReceivedPacket(encrypted_buffer, encrypted_length, clock_.Now()));
}
- QuicPacketEntropyHash ProcessFramePacketAtLevel(QuicPathId path_id,
- QuicPacketNumber number,
- QuicFrame frame,
- EncryptionLevel level) {
+ size_t ProcessFramePacketAtLevel(QuicPathId path_id,
+ QuicPacketNumber number,
+ QuicFrame frame,
+ EncryptionLevel level) {
QuicPacketHeader header;
header.public_header.connection_id = connection_id_;
header.public_header.packet_number_length = packet_number_length_;
@@ -853,25 +845,21 @@ class QuicConnectionTest : public ::testing::TestWithParam<TestParams> {
connection_.ProcessUdpPacket(
kSelfAddress, kPeerAddress,
QuicReceivedPacket(buffer, encrypted_length, QuicTime::Zero(), false));
- return base::checked_cast<QuicPacketEntropyHash>(encrypted_length);
+ return encrypted_length;
}
- size_t ProcessDataPacket(QuicPathId path_id,
- QuicPacketNumber number,
- bool entropy_flag) {
- return ProcessDataPacketAtLevel(path_id, number, entropy_flag, false,
- ENCRYPTION_NONE);
+ size_t ProcessDataPacket(QuicPathId path_id, QuicPacketNumber number) {
+ return ProcessDataPacketAtLevel(path_id, number, false, ENCRYPTION_NONE);
}
size_t ProcessDataPacketAtLevel(QuicPathId path_id,
QuicPacketNumber number,
- bool entropy_flag,
bool has_stop_waiting,
EncryptionLevel level) {
std::unique_ptr<QuicPacket> packet(
- ConstructDataPacket(path_id, number, entropy_flag, has_stop_waiting));
+ ConstructDataPacket(path_id, number, has_stop_waiting));
char buffer[kMaxPacketSize];
- size_t encrypted_length = framer_.EncryptPayload(
+ size_t encrypted_length = peer_framer_.EncryptPayload(
level, path_id, number, *packet, buffer, kMaxPacketSize);
connection_.ProcessUdpPacket(
kSelfAddress, kPeerAddress,
@@ -885,7 +873,7 @@ class QuicConnectionTest : public ::testing::TestWithParam<TestParams> {
void ProcessClosePacket(QuicPathId path_id, QuicPacketNumber number) {
std::unique_ptr<QuicPacket> packet(ConstructClosePacket(number));
char buffer[kMaxPacketSize];
- size_t encrypted_length = framer_.EncryptPayload(
+ size_t encrypted_length = peer_framer_.EncryptPayload(
ENCRYPTION_NONE, path_id, number, *packet, buffer, kMaxPacketSize);
connection_.ProcessUdpPacket(
kSelfAddress, kPeerAddress,
@@ -921,29 +909,28 @@ class QuicConnectionTest : public ::testing::TestWithParam<TestParams> {
ProcessFramePacket(QuicFrame(frame));
}
- QuicPacketEntropyHash ProcessAckPacket(QuicAckFrame* frame) {
- return ProcessFramePacket(QuicFrame(frame));
+ void ProcessAckPacket(QuicAckFrame* frame) {
+ ProcessFramePacket(QuicFrame(frame));
}
- QuicPacketEntropyHash ProcessStopWaitingPacket(QuicStopWaitingFrame* frame) {
- return ProcessFramePacket(QuicFrame(frame));
+ void ProcessStopWaitingPacket(QuicStopWaitingFrame* frame) {
+ ProcessFramePacket(QuicFrame(frame));
}
- QuicPacketEntropyHash ProcessStopWaitingPacketAtLevel(
- QuicPathId path_id,
- QuicPacketNumber number,
- QuicStopWaitingFrame* frame,
- EncryptionLevel level) {
+ size_t ProcessStopWaitingPacketAtLevel(QuicPathId path_id,
+ QuicPacketNumber number,
+ QuicStopWaitingFrame* frame,
+ EncryptionLevel level) {
return ProcessFramePacketAtLevel(path_id, number, QuicFrame(frame),
ENCRYPTION_INITIAL);
}
- QuicPacketEntropyHash ProcessGoAwayPacket(QuicGoAwayFrame* frame) {
- return ProcessFramePacket(QuicFrame(frame));
+ void ProcessGoAwayPacket(QuicGoAwayFrame* frame) {
+ ProcessFramePacket(QuicFrame(frame));
}
- QuicPacketEntropyHash ProcessPathClosePacket(QuicPathCloseFrame* frame) {
- return ProcessFramePacket(QuicFrame(frame));
+ void ProcessPathClosePacket(QuicPathCloseFrame* frame) {
+ ProcessFramePacket(QuicFrame(frame));
}
bool IsMissing(QuicPacketNumber number) {
@@ -958,14 +945,12 @@ class QuicConnectionTest : public ::testing::TestWithParam<TestParams> {
QuicPacket* ConstructDataPacket(QuicPathId path_id,
QuicPacketNumber number,
- bool entropy_flag,
bool has_stop_waiting) {
QuicPacketHeader header;
header.public_header.connection_id = connection_id_;
header.public_header.packet_number_length = packet_number_length_;
header.public_header.connection_id_length = connection_id_length_;
header.public_header.multipath_flag = path_id != kDefaultPathId;
- header.entropy_flag = entropy_flag;
header.path_id = path_id;
header.packet_number = number;
@@ -1001,16 +986,8 @@ class QuicConnectionTest : public ::testing::TestWithParam<TestParams> {
// Initialize a frame acknowledging all packets up to largest_observed.
const QuicAckFrame InitAckFrame(QuicPacketNumber largest_observed) {
QuicAckFrame frame(MakeAckFrame(largest_observed));
- if (GetParam().version <= QUIC_VERSION_33) {
- if (largest_observed > 0) {
- frame.entropy_hash = QuicConnectionPeer::GetSentEntropyHash(
- &connection_, largest_observed);
- }
- } else {
- frame.missing = false;
- if (largest_observed > 0) {
- frame.packets.Add(1, largest_observed + 1);
- }
+ if (largest_observed > 0) {
+ frame.packets.Add(1, largest_observed + 1);
}
return frame;
}
@@ -1024,26 +1001,13 @@ class QuicConnectionTest : public ::testing::TestWithParam<TestParams> {
// Explicitly nack a packet.
void NackPacket(QuicPacketNumber missing, QuicAckFrame* frame) {
- if (frame->missing) {
- frame->packets.Add(missing);
- frame->entropy_hash ^=
- QuicConnectionPeer::PacketEntropy(&connection_, missing);
- } else {
- frame->packets.Remove(missing);
- }
+ frame->packets.Remove(missing);
}
// Undo nacking a packet within the frame.
void AckPacket(QuicPacketNumber arrived, QuicAckFrame* frame) {
- if (frame->missing) {
- EXPECT_TRUE(frame->packets.Contains(arrived));
- frame->packets.Remove(arrived);
- frame->entropy_hash ^=
- QuicConnectionPeer::PacketEntropy(&connection_, arrived);
- } else {
- EXPECT_FALSE(frame->packets.Contains(arrived));
- frame->packets.Add(arrived);
- }
+ EXPECT_FALSE(frame->packets.Contains(arrived));
+ frame->packets.Add(arrived);
}
void TriggerConnectionClose() {
@@ -1052,7 +1016,7 @@ class QuicConnectionTest : public ::testing::TestWithParam<TestParams> {
ConnectionCloseSource::FROM_SELF));
// Call ProcessDataPacket rather than ProcessPacket, as we should not get a
// packet call to the visitor.
- ProcessDataPacket(kDefaultPathId, 6000, !kEntropyFlag);
+ ProcessDataPacket(kDefaultPathId, 6000);
EXPECT_FALSE(QuicConnectionPeer::GetConnectionClosePacket(&connection_) ==
nullptr);
}
@@ -1090,8 +1054,6 @@ class QuicConnectionTest : public ::testing::TestWithParam<TestParams> {
QuicConnectionId connection_id_;
QuicFramer framer_;
- MockEntropyCalculator entropy_calculator_;
- MockEntropyCalculator peer_entropy_calculator_;
MockSendAlgorithm* send_algorithm_;
std::unique_ptr<MockLossAlgorithm> loss_algorithm_;
@@ -1136,7 +1098,9 @@ TEST_P(QuicConnectionTest, SelfAddressChangeAtClient) {
ProcessFramePacketWithAddresses(QuicFrame(&stream_frame), kSelfAddress,
kPeerAddress);
// Cause change in self_address.
- IPEndPoint self_address(IPAddress(1, 1, 1, 1), 123);
+ QuicIpAddress host;
+ host.FromString("1.1.1.1");
+ QuicSocketAddress self_address(host, 123);
EXPECT_CALL(visitor_, OnStreamFrame(_));
ProcessFramePacketWithAddresses(QuicFrame(&stream_frame), self_address,
kPeerAddress);
@@ -1157,7 +1121,9 @@ TEST_P(QuicConnectionTest, SelfAddressChangeAtServer) {
ProcessFramePacketWithAddresses(QuicFrame(&stream_frame), kSelfAddress,
kPeerAddress);
// Cause change in self_address.
- IPEndPoint self_address(IPAddress(1, 1, 1, 1), 123);
+ QuicIpAddress host;
+ host.FromString("1.1.1.1");
+ QuicSocketAddress self_address(host, 123);
EXPECT_CALL(visitor_, OnConnectionClosed(QUIC_ERROR_MIGRATING_ADDRESS, _, _));
ProcessFramePacketWithAddresses(QuicFrame(&stream_frame), self_address,
kPeerAddress);
@@ -1175,12 +1141,16 @@ TEST_P(QuicConnectionTest, AllowSelfAddressChangeToMappedIpv4AddressAtServer) {
QuicStreamFrame stream_frame(1u, false, 0u, StringPiece());
EXPECT_CALL(visitor_, OnStreamFrame(_)).Times(3);
- IPEndPoint self_address1(IPAddress(1, 1, 1, 1), 443);
+ QuicIpAddress host;
+ host.FromString("1.1.1.1");
+ QuicSocketAddress self_address1(host, 443);
ProcessFramePacketWithAddresses(QuicFrame(&stream_frame), self_address1,
kPeerAddress);
// Cause self_address change to mapped Ipv4 address.
- IPEndPoint self_address2(ConvertIPv4ToIPv4MappedIPv6(self_address1.address()),
- 443);
+ QuicIpAddress host2;
+ host2.FromString(
+ QuicStrCat("::ffff:", connection_.self_address().host().ToString()));
+ QuicSocketAddress self_address2(host2, connection_.self_address().port());
ProcessFramePacketWithAddresses(QuicFrame(&stream_frame), self_address2,
kPeerAddress);
EXPECT_TRUE(connection_.connected());
@@ -1195,13 +1165,14 @@ TEST_P(QuicConnectionTest, ClientAddressChangeAndPacketReordered) {
set_perspective(Perspective::IS_SERVER);
QuicPacketCreatorPeer::SetSendVersionInPacket(creator_, false);
// Clear peer address.
- QuicConnectionPeer::SetPeerAddress(&connection_, IPEndPoint());
+ QuicConnectionPeer::SetPeerAddress(&connection_, QuicSocketAddress());
QuicPacketCreatorPeer::SetPacketNumber(&peer_creator_, 5);
QuicStreamFrame stream_frame(1u, false, 0u, StringPiece());
EXPECT_CALL(visitor_, OnStreamFrame(_)).Times(AnyNumber());
- const IPEndPoint kNewPeerAddress = IPEndPoint(Loopback6(),
- /*port=*/23456);
+ const QuicSocketAddress kNewPeerAddress =
+ QuicSocketAddress(QuicIpAddress::Loopback6(),
+ /*port=*/23456);
ProcessFramePacketWithAddresses(QuicFrame(&stream_frame), kSelfAddress,
kNewPeerAddress);
@@ -1245,7 +1216,7 @@ TEST_P(QuicConnectionTest, IncreaseServerMaxPacketSize) {
frames.push_back(QuicFrame(padding));
std::unique_ptr<QuicPacket> packet(ConstructPacket(header, frames));
char buffer[kMaxPacketSize];
- size_t encrypted_length = framer_.EncryptPayload(
+ size_t encrypted_length = peer_framer_.EncryptPayload(
ENCRYPTION_NONE, kDefaultPathId, 12, *packet, buffer, kMaxPacketSize);
EXPECT_EQ(kMaxPacketSize, encrypted_length);
@@ -1279,7 +1250,7 @@ TEST_P(QuicConnectionTest, IncreaseServerMaxPacketSizeWhileWriterLimited) {
frames.push_back(QuicFrame(padding));
std::unique_ptr<QuicPacket> packet(ConstructPacket(header, frames));
char buffer[kMaxPacketSize];
- size_t encrypted_length = framer_.EncryptPayload(
+ size_t encrypted_length = peer_framer_.EncryptPayload(
ENCRYPTION_NONE, kDefaultPathId, 12, *packet, buffer, kMaxPacketSize);
EXPECT_EQ(kMaxPacketSize, encrypted_length);
@@ -1321,27 +1292,15 @@ TEST_P(QuicConnectionTest, PacketsInOrder) {
ProcessPacket(kDefaultPathId, 1);
EXPECT_EQ(1u, outgoing_ack()->largest_observed);
- if (outgoing_ack()->missing) {
- EXPECT_TRUE(outgoing_ack()->packets.Empty());
- } else {
- EXPECT_EQ(1u, outgoing_ack()->packets.NumIntervals());
- }
+ EXPECT_EQ(1u, outgoing_ack()->packets.NumIntervals());
ProcessPacket(kDefaultPathId, 2);
EXPECT_EQ(2u, outgoing_ack()->largest_observed);
- if (outgoing_ack()->missing) {
- EXPECT_TRUE(outgoing_ack()->packets.Empty());
- } else {
- EXPECT_EQ(1u, outgoing_ack()->packets.NumIntervals());
- }
+ EXPECT_EQ(1u, outgoing_ack()->packets.NumIntervals());
ProcessPacket(kDefaultPathId, 3);
EXPECT_EQ(3u, outgoing_ack()->largest_observed);
- if (outgoing_ack()->missing) {
- EXPECT_TRUE(outgoing_ack()->packets.Empty());
- } else {
- EXPECT_EQ(1u, outgoing_ack()->packets.NumIntervals());
- }
+ EXPECT_EQ(1u, outgoing_ack()->packets.NumIntervals());
}
TEST_P(QuicConnectionTest, PacketsOutOfOrder) {
@@ -1373,7 +1332,7 @@ TEST_P(QuicConnectionTest, DuplicatePacket) {
// Send packet 3 again, but do not set the expectation that
// the visitor OnStreamFrame() will be called.
- ProcessDataPacket(kDefaultPathId, 3, !kEntropyFlag);
+ ProcessDataPacket(kDefaultPathId, 3);
EXPECT_EQ(3u, outgoing_ack()->largest_observed);
EXPECT_TRUE(IsMissing(2));
EXPECT_TRUE(IsMissing(1));
@@ -1414,7 +1373,7 @@ TEST_P(QuicConnectionTest, RejectPacketTooFarOut) {
ConnectionCloseSource::FROM_SELF));
// Call ProcessDataPacket rather than ProcessPacket, as we should not get a
// packet call to the visitor.
- ProcessDataPacket(kDefaultPathId, 6000, !kEntropyFlag);
+ ProcessDataPacket(kDefaultPathId, 6000);
EXPECT_FALSE(QuicConnectionPeer::GetConnectionClosePacket(&connection_) ==
nullptr);
}
@@ -1425,66 +1384,16 @@ TEST_P(QuicConnectionTest, RejectUnencryptedStreamData) {
EXPECT_CALL(visitor_, OnSuccessfulVersionNegotiation(_));
EXPECT_CALL(visitor_, OnConnectionClosed(QUIC_UNENCRYPTED_STREAM_DATA, _,
ConnectionCloseSource::FROM_SELF));
- EXPECT_QUIC_BUG(ProcessDataPacket(kDefaultPathId, 1, !kEntropyFlag), "");
+ EXPECT_QUIC_BUG(ProcessDataPacket(kDefaultPathId, 1), "");
EXPECT_FALSE(QuicConnectionPeer::GetConnectionClosePacket(&connection_) ==
nullptr);
- const vector<QuicConnectionCloseFrame>& connection_close_frames =
+ const std::vector<QuicConnectionCloseFrame>& connection_close_frames =
writer_->connection_close_frames();
EXPECT_EQ(1u, connection_close_frames.size());
EXPECT_EQ(QUIC_UNENCRYPTED_STREAM_DATA,
connection_close_frames[0].error_code);
}
-TEST_P(QuicConnectionTest, TruncatedAck) {
- if (GetParam().version > QUIC_VERSION_33) {
- return;
- }
- EXPECT_CALL(visitor_, OnSuccessfulVersionNegotiation(_));
- QuicPacketNumber num_packets = 256 * 2 + 1;
- for (QuicPacketNumber i = 0; i < num_packets; ++i) {
- SendStreamDataToPeer(3, "foo", i * 3, !kFin, nullptr);
- }
-
- QuicAckFrame frame = InitAckFrame(num_packets);
- // Create an ack with 256 nacks, none adjacent to one another.
- for (QuicPacketNumber i = 1; i <= 256; ++i) {
- NackPacket(i * 2, &frame);
- }
- EXPECT_CALL(*loss_algorithm_, DetectLosses(_, _, _, _, _));
- EXPECT_CALL(peer_entropy_calculator_, EntropyHash(511))
- .WillOnce(Return(static_cast<QuicPacketEntropyHash>(0)));
- EXPECT_CALL(*send_algorithm_, OnCongestionEvent(true, _, _, _, _));
- ProcessAckPacket(&frame);
-
- // A truncated ack will not have the true largest observed.
- EXPECT_GT(num_packets, manager_->GetLargestObserved(frame.path_id));
-
- AckPacket(192, &frame);
-
- // Removing one missing packet allows us to ack 192 and one more range, but
- // 192 has already been declared lost, so it doesn't register as an ack.
- EXPECT_CALL(*loss_algorithm_, DetectLosses(_, _, _, _, _));
- EXPECT_CALL(*send_algorithm_, OnCongestionEvent(true, _, _, _, _));
- ProcessAckPacket(&frame);
- EXPECT_EQ(num_packets, manager_->GetLargestObserved(frame.path_id));
-}
-
-TEST_P(QuicConnectionTest, AckReceiptCausesAckSendBadEntropy) {
- EXPECT_CALL(visitor_, OnSuccessfulVersionNegotiation(_));
-
- ProcessPacket(kDefaultPathId, 1);
- // Delay sending, then queue up an ack.
- QuicConnectionPeer::SendAck(&connection_);
-
- // Process an ack with a least unacked of the received ack.
- // This causes an ack to be sent when TimeUntilSend returns 0.
- EXPECT_CALL(*send_algorithm_, TimeUntilSend(_, _))
- .WillRepeatedly(testing::Return(QuicTime::Delta::Zero()));
- // Skip a packet and then record an ack.
- QuicAckFrame frame = InitAckFrame(0);
- ProcessAckPacket(3, &frame);
-}
-
TEST_P(QuicConnectionTest, OutOfOrderReceiptCausesAckSend) {
EXPECT_CALL(visitor_, OnSuccessfulVersionNegotiation(_));
@@ -1640,13 +1549,6 @@ TEST_P(QuicConnectionTest, TooManySentPackets) {
// Ack packet 1, which leaves more than the limit outstanding.
EXPECT_CALL(*send_algorithm_, OnCongestionEvent(true, _, _, _, _));
- if (GetParam().version <= QUIC_VERSION_33) {
- EXPECT_CALL(visitor_,
- OnConnectionClosed(QUIC_TOO_MANY_OUTSTANDING_SENT_PACKETS, _,
- ConnectionCloseSource::FROM_SELF));
- // We're receive buffer limited, so the connection won't try to write more.
- EXPECT_CALL(visitor_, OnCanWrite()).Times(0);
- }
// Nack the first packet and ack the rest, leaving a huge gap.
QuicAckFrame frame1 = InitAckFrame(num_packets);
@@ -1656,11 +1558,6 @@ TEST_P(QuicConnectionTest, TooManySentPackets) {
TEST_P(QuicConnectionTest, TooManyReceivedPackets) {
EXPECT_CALL(visitor_, OnSuccessfulVersionNegotiation(_));
- if (GetParam().version <= QUIC_VERSION_33) {
- EXPECT_CALL(visitor_,
- OnConnectionClosed(QUIC_TOO_MANY_OUTSTANDING_RECEIVED_PACKETS,
- _, ConnectionCloseSource::FROM_SELF));
- }
// Miss 99 of every 100 packets for 5500 packets.
for (QuicPacketNumber i = 1; i < kMaxTrackedPackets + 500; i += 100) {
ProcessPacket(kDefaultPathId, i);
@@ -1858,7 +1755,7 @@ TEST_P(QuicConnectionTest, FramePackingAckResponse) {
EXPECT_CALL(visitor_, OnSuccessfulVersionNegotiation(_));
// Process a data packet to queue up a pending ack.
EXPECT_CALL(visitor_, OnStreamFrame(_)).Times(1);
- ProcessDataPacket(kDefaultPathId, 1, kEntropyFlag);
+ ProcessDataPacket(kDefaultPathId, 1);
EXPECT_CALL(visitor_, OnCanWrite())
.WillOnce(DoAll(IgnoreResult(InvokeWithoutArgs(
@@ -2146,7 +2043,7 @@ TEST_P(QuicConnectionTest, DoNotRetransmitForResetStreamOnRTO) {
// Ensure that if the only data in flight is non-retransmittable, the
// retransmission alarm is not set.
TEST_P(QuicConnectionTest, CancelRetransmissionAlarmAfterResetStream) {
- FLAGS_quic_more_conservative_retransmission_alarm = true;
+ FLAGS_quic_reloadable_flag_quic_more_conservative_retransmission_alarm = true;
QuicStreamId stream_id = 2;
QuicPacketNumber last_data_packet;
SendStreamDataToPeer(stream_id, "foo", 0, !kFin, &last_data_packet);
@@ -2172,7 +2069,7 @@ TEST_P(QuicConnectionTest, CancelRetransmissionAlarmAfterResetStream) {
}
TEST_P(QuicConnectionTest, RetransmitForQuicRstStreamNoErrorOnRTO) {
- connection_.SetMaxTailLossProbes(kDefaultPathId, 0);
+ connection_.SetMaxTailLossProbes(0);
QuicStreamId stream_id = 2;
QuicPacketNumber last_packet;
@@ -2315,7 +2212,7 @@ TEST_P(QuicConnectionTest, RetransmitNackedLargestObserved) {
}
TEST_P(QuicConnectionTest, QueueAfterTwoRTOs) {
- connection_.SetMaxTailLossProbes(kDefaultPathId, 0);
+ connection_.SetMaxTailLossProbes(0);
for (int i = 0; i < 10; ++i) {
EXPECT_CALL(*send_algorithm_, OnPacketSent(_, _, _, _, _)).Times(1);
@@ -2391,8 +2288,9 @@ TEST_P(QuicConnectionTest, RetransmitWriteBlockedAckedOriginalThenSent) {
writer_->SetWritable();
connection_.OnCanWrite();
// There is now a pending packet, but with no retransmittable frames.
- EXPECT_EQ(FLAGS_quic_more_conservative_retransmission_alarm,
- !connection_.GetRetransmissionAlarm()->IsSet());
+ EXPECT_EQ(
+ FLAGS_quic_reloadable_flag_quic_more_conservative_retransmission_alarm,
+ !connection_.GetRetransmissionAlarm()->IsSet());
EXPECT_FALSE(QuicConnectionPeer::HasRetransmittableFrames(&connection_,
ack.path_id, 2));
}
@@ -2532,7 +2430,7 @@ TEST_P(QuicConnectionTest, DontLatchUnackedPacket) {
}
TEST_P(QuicConnectionTest, TLP) {
- connection_.SetMaxTailLossProbes(kDefaultPathId, 1);
+ connection_.SetMaxTailLossProbes(1);
SendStreamDataToPeer(3, "foo", 0, !kFin, nullptr);
EXPECT_EQ(1u, stop_waiting()->least_unacked);
@@ -2552,7 +2450,7 @@ TEST_P(QuicConnectionTest, TLP) {
}
TEST_P(QuicConnectionTest, RTO) {
- connection_.SetMaxTailLossProbes(kDefaultPathId, 0);
+ connection_.SetMaxTailLossProbes(0);
QuicTime default_retransmission_time =
clock_.ApproximateNow() + DefaultRetransmissionTime();
@@ -2679,11 +2577,11 @@ TEST_P(QuicConnectionTest, BufferNonDecryptablePackets) {
use_tagging_decrypter();
const uint8_t tag = 0x07;
- framer_.SetEncrypter(ENCRYPTION_INITIAL, new TaggingEncrypter(tag));
+ peer_framer_.SetEncrypter(ENCRYPTION_INITIAL, new TaggingEncrypter(tag));
// Process an encrypted packet which can not yet be decrypted which should
// result in the packet being buffered.
- ProcessDataPacketAtLevel(kDefaultPathId, 1, kEntropyFlag, !kHasStopWaiting,
+ ProcessDataPacketAtLevel(kDefaultPathId, 1, !kHasStopWaiting,
ENCRYPTION_INITIAL);
// Transition to the new encryption state and process another encrypted packet
@@ -2692,13 +2590,13 @@ TEST_P(QuicConnectionTest, BufferNonDecryptablePackets) {
connection_.SetDefaultEncryptionLevel(ENCRYPTION_INITIAL);
connection_.SetEncrypter(ENCRYPTION_INITIAL, new TaggingEncrypter(tag));
EXPECT_CALL(visitor_, OnStreamFrame(_)).Times(2);
- ProcessDataPacketAtLevel(kDefaultPathId, 2, kEntropyFlag, !kHasStopWaiting,
+ ProcessDataPacketAtLevel(kDefaultPathId, 2, !kHasStopWaiting,
ENCRYPTION_INITIAL);
// Finally, process a third packet and note that we do not reprocess the
// buffered packet.
EXPECT_CALL(visitor_, OnStreamFrame(_)).Times(1);
- ProcessDataPacketAtLevel(kDefaultPathId, 3, kEntropyFlag, !kHasStopWaiting,
+ ProcessDataPacketAtLevel(kDefaultPathId, 3, !kHasStopWaiting,
ENCRYPTION_INITIAL);
}
@@ -2712,12 +2610,12 @@ TEST_P(QuicConnectionTest, Buffer100NonDecryptablePackets) {
use_tagging_decrypter();
const uint8_t tag = 0x07;
- framer_.SetEncrypter(ENCRYPTION_INITIAL, new TaggingEncrypter(tag));
+ peer_framer_.SetEncrypter(ENCRYPTION_INITIAL, new TaggingEncrypter(tag));
// Process an encrypted packet which can not yet be decrypted which should
// result in the packet being buffered.
for (QuicPacketNumber i = 1; i <= 100; ++i) {
- ProcessDataPacketAtLevel(kDefaultPathId, i, kEntropyFlag, !kHasStopWaiting,
+ ProcessDataPacketAtLevel(kDefaultPathId, i, !kHasStopWaiting,
ENCRYPTION_INITIAL);
}
@@ -2727,18 +2625,18 @@ TEST_P(QuicConnectionTest, Buffer100NonDecryptablePackets) {
connection_.SetDefaultEncryptionLevel(ENCRYPTION_INITIAL);
connection_.SetEncrypter(ENCRYPTION_INITIAL, new TaggingEncrypter(tag));
EXPECT_CALL(visitor_, OnStreamFrame(_)).Times(101);
- ProcessDataPacketAtLevel(kDefaultPathId, 101, kEntropyFlag, !kHasStopWaiting,
+ ProcessDataPacketAtLevel(kDefaultPathId, 101, !kHasStopWaiting,
ENCRYPTION_INITIAL);
// Finally, process a third packet and note that we do not reprocess the
// buffered packet.
EXPECT_CALL(visitor_, OnStreamFrame(_)).Times(1);
- ProcessDataPacketAtLevel(kDefaultPathId, 102, kEntropyFlag, !kHasStopWaiting,
+ ProcessDataPacketAtLevel(kDefaultPathId, 102, !kHasStopWaiting,
ENCRYPTION_INITIAL);
}
TEST_P(QuicConnectionTest, TestRetransmitOrder) {
- connection_.SetMaxTailLossProbes(kDefaultPathId, 0);
+ connection_.SetMaxTailLossProbes(0);
QuicByteCount first_packet_size;
EXPECT_CALL(*send_algorithm_, OnPacketSent(_, _, _, _, _))
@@ -2783,7 +2681,7 @@ TEST_P(QuicConnectionTest, SetRTOAfterWritingToSocket) {
}
TEST_P(QuicConnectionTest, DelayRTOWithAckReceipt) {
- connection_.SetMaxTailLossProbes(kDefaultPathId, 0);
+ connection_.SetMaxTailLossProbes(0);
EXPECT_CALL(visitor_, OnSuccessfulVersionNegotiation(_));
EXPECT_CALL(*send_algorithm_, OnPacketSent(_, _, _, _, _)).Times(2);
@@ -2826,7 +2724,7 @@ TEST_P(QuicConnectionTest, DelayRTOWithAckReceipt) {
}
TEST_P(QuicConnectionTest, TestQueued) {
- connection_.SetMaxTailLossProbes(kDefaultPathId, 0);
+ connection_.SetMaxTailLossProbes(0);
EXPECT_EQ(0u, connection_.NumQueuedPackets());
BlockOnNextWrite();
@@ -3083,7 +2981,7 @@ TEST_P(QuicConnectionTest, MtuDiscoveryEnabled) {
EXPECT_CALL(*send_algorithm_, OnCongestionEvent(true, _, _, _, _));
ProcessAckPacket(&probe_ack);
EXPECT_EQ(kMtuDiscoveryTargetPacketSizeHigh, connection_.max_packet_length());
- EXPECT_EQ(0u, connection_.GetBytesInFlight(kDefaultPathId));
+ EXPECT_EQ(0u, connection_.GetBytesInFlight());
// Send more packets, and ensure that none of them sets the alarm.
for (QuicPacketCount i = 0; i < 4 * kPacketsBetweenMtuProbesBase; i++) {
@@ -3118,7 +3016,7 @@ TEST_P(QuicConnectionTest, MtuDiscoveryFailed) {
// get caught as well.
const QuicPacketCount number_of_packets =
packets_between_probes_base * (1 << (kMtuDiscoveryAttempts + 1));
- vector<QuicPacketNumber> mtu_discovery_packets;
+ std::vector<QuicPacketNumber> mtu_discovery_packets;
// Called by the first ack.
EXPECT_CALL(visitor_, OnSuccessfulVersionNegotiation(_));
// Called on many acks.
@@ -3200,7 +3098,7 @@ TEST_P(QuicConnectionTest, MtuDiscoveryWriterLimited) {
EXPECT_CALL(*send_algorithm_, OnCongestionEvent(true, _, _, _, _));
ProcessAckPacket(&probe_ack);
EXPECT_EQ(mtu_limit, connection_.max_packet_length());
- EXPECT_EQ(0u, connection_.GetBytesInFlight(kDefaultPathId));
+ EXPECT_EQ(0u, connection_.GetBytesInFlight());
// Send more packets, and ensure that none of them sets the alarm.
for (QuicPacketCount i = 0; i < 4 * kPacketsBetweenMtuProbesBase; i++) {
@@ -3341,7 +3239,7 @@ TEST_P(QuicConnectionTest, TimeoutAfterRetransmission) {
QuicTime::Delta::FromSeconds(kInitialIdleTimeoutSecs - 1);
QuicTime default_timeout = clock_.Now() + initial_idle_timeout;
- connection_.SetMaxTailLossProbes(kDefaultPathId, 0);
+ connection_.SetMaxTailLossProbes(0);
const QuicTime default_retransmission_time =
start_time + DefaultRetransmissionTime();
@@ -3561,7 +3459,7 @@ TEST_P(QuicConnectionTest, TimeoutAfterReceiveNotSendWhenUnacked) {
ConnectionCloseSource::FROM_SELF));
EXPECT_CALL(*send_algorithm_, OnPacketSent(_, _, _, _, _)).Times(AnyNumber());
for (int i = 0; i < 100 && connection_.connected(); ++i) {
- VLOG(1) << "sending data packet";
+ QUIC_LOG(INFO) << "sending data packet";
connection_.SendStreamDataWithString(kClientDataStreamId1, "foo", 0, !kFin,
nullptr);
connection_.GetTimeoutAlarm()->Fire();
@@ -3572,7 +3470,7 @@ TEST_P(QuicConnectionTest, TimeoutAfterReceiveNotSendWhenUnacked) {
}
TEST_P(QuicConnectionTest, TimeoutAfter5ClientRTOs) {
- connection_.SetMaxTailLossProbes(kDefaultPathId, 2);
+ connection_.SetMaxTailLossProbes(2);
EXPECT_TRUE(connection_.connected());
EXPECT_CALL(*send_algorithm_, SetFromConfig(_, _));
QuicConfig config;
@@ -3605,9 +3503,9 @@ TEST_P(QuicConnectionTest, TimeoutAfter5ClientRTOs) {
}
TEST_P(QuicConnectionTest, TimeoutAfter5ServerRTOs) {
- FLAGS_quic_only_5rto_client_side = true;
- connection_.SetMaxTailLossProbes(kDefaultPathId, 2);
- QuicConnectionPeer::SetPerspective(&connection_, Perspective::IS_SERVER);
+ FLAGS_quic_reloadable_flag_quic_only_5rto_client_side = true;
+ connection_.SetMaxTailLossProbes(2);
+ set_perspective(Perspective::IS_SERVER);
QuicFramerPeer::SetPerspective(QuicConnectionPeer::GetFramer(&connection_),
Perspective::IS_SERVER);
creator_->StopSendingVersion();
@@ -3642,12 +3540,10 @@ TEST_P(QuicConnectionTest, TimeoutAfter5ServerRTOs) {
TEST_P(QuicConnectionTest, SendScheduler) {
// Test that if we send a packet without delay, it is not queued.
- QuicPacket* packet =
- ConstructDataPacket(kDefaultPathId, 1, !kEntropyFlag, !kHasStopWaiting);
+ QuicPacket* packet = ConstructDataPacket(kDefaultPathId, 1, !kHasStopWaiting);
EXPECT_CALL(*send_algorithm_, OnPacketSent(_, _, _, _, _));
connection_.SendPacket(ENCRYPTION_NONE, kDefaultPathId, 1, packet,
- kTestEntropyHash, HAS_RETRANSMITTABLE_DATA, false,
- false);
+ HAS_RETRANSMITTABLE_DATA, false, false);
EXPECT_EQ(0u, connection_.NumQueuedPackets());
}
@@ -3655,22 +3551,18 @@ TEST_P(QuicConnectionTest, FailToSendFirstPacket) {
// Test that the connection does not crash when it fails to send the first
// packet at which point self_address_ might be uninitialized.
EXPECT_CALL(visitor_, OnConnectionClosed(_, _, _)).Times(1);
- QuicPacket* packet =
- ConstructDataPacket(kDefaultPathId, 1, !kEntropyFlag, !kHasStopWaiting);
+ QuicPacket* packet = ConstructDataPacket(kDefaultPathId, 1, !kHasStopWaiting);
writer_->SetShouldWriteFail();
connection_.SendPacket(ENCRYPTION_NONE, kDefaultPathId, 1, packet,
- kTestEntropyHash, HAS_RETRANSMITTABLE_DATA, false,
- false);
+ HAS_RETRANSMITTABLE_DATA, false, false);
}
TEST_P(QuicConnectionTest, SendSchedulerEAGAIN) {
- QuicPacket* packet =
- ConstructDataPacket(kDefaultPathId, 1, !kEntropyFlag, !kHasStopWaiting);
+ QuicPacket* packet = ConstructDataPacket(kDefaultPathId, 1, !kHasStopWaiting);
BlockOnNextWrite();
EXPECT_CALL(*send_algorithm_, OnPacketSent(_, _, 1, _, _)).Times(0);
connection_.SendPacket(ENCRYPTION_NONE, kDefaultPathId, 1, packet,
- kTestEntropyHash, HAS_RETRANSMITTABLE_DATA, false,
- false);
+ HAS_RETRANSMITTABLE_DATA, false, false);
EXPECT_EQ(1u, connection_.NumQueuedPackets());
}
@@ -3749,14 +3641,14 @@ TEST_P(QuicConnectionTest, SendDelayedAck) {
EXPECT_FALSE(connection_.GetAckAlarm()->IsSet());
const uint8_t tag = 0x07;
connection_.SetDecrypter(ENCRYPTION_INITIAL, new StrictTaggingDecrypter(tag));
- framer_.SetEncrypter(ENCRYPTION_INITIAL, new TaggingEncrypter(tag));
+ peer_framer_.SetEncrypter(ENCRYPTION_INITIAL, new TaggingEncrypter(tag));
// Process a packet from the non-crypto stream.
frame1_.stream_id = 3;
// The same as ProcessPacket(1) except that ENCRYPTION_INITIAL is used
// instead of ENCRYPTION_NONE.
EXPECT_CALL(visitor_, OnStreamFrame(_)).Times(1);
- ProcessDataPacketAtLevel(kDefaultPathId, 1, !kEntropyFlag, !kHasStopWaiting,
+ ProcessDataPacketAtLevel(kDefaultPathId, 1, !kHasStopWaiting,
ENCRYPTION_INITIAL);
// Check if delayed ack timer is running for the expected interval.
@@ -3786,7 +3678,7 @@ TEST_P(QuicConnectionTest, SendDelayedAckDecimation) {
EXPECT_FALSE(connection_.GetAckAlarm()->IsSet());
const uint8_t tag = 0x07;
connection_.SetDecrypter(ENCRYPTION_INITIAL, new StrictTaggingDecrypter(tag));
- framer_.SetEncrypter(ENCRYPTION_INITIAL, new TaggingEncrypter(tag));
+ peer_framer_.SetEncrypter(ENCRYPTION_INITIAL, new TaggingEncrypter(tag));
// Process a packet from the non-crypto stream.
frame1_.stream_id = 3;
@@ -3794,14 +3686,14 @@ TEST_P(QuicConnectionTest, SendDelayedAckDecimation) {
QuicPacketNumber kFirstDecimatedPacket = 101;
for (unsigned int i = 0; i < kFirstDecimatedPacket - 1; ++i) {
EXPECT_CALL(visitor_, OnStreamFrame(_)).Times(1);
- ProcessDataPacketAtLevel(kDefaultPathId, 1 + i, !kEntropyFlag,
- !kHasStopWaiting, ENCRYPTION_INITIAL);
+ ProcessDataPacketAtLevel(kDefaultPathId, 1 + i, !kHasStopWaiting,
+ ENCRYPTION_INITIAL);
}
EXPECT_FALSE(connection_.GetAckAlarm()->IsSet());
// The same as ProcessPacket(1) except that ENCRYPTION_INITIAL is used
// instead of ENCRYPTION_NONE.
EXPECT_CALL(visitor_, OnStreamFrame(_)).Times(1);
- ProcessDataPacketAtLevel(kDefaultPathId, kFirstDecimatedPacket, !kEntropyFlag,
+ ProcessDataPacketAtLevel(kDefaultPathId, kFirstDecimatedPacket,
!kHasStopWaiting, ENCRYPTION_INITIAL);
// Check if delayed ack timer is running for the expected interval.
@@ -3813,8 +3705,7 @@ TEST_P(QuicConnectionTest, SendDelayedAckDecimation) {
EXPECT_TRUE(connection_.GetAckAlarm()->IsSet());
EXPECT_CALL(visitor_, OnStreamFrame(_)).Times(1);
ProcessDataPacketAtLevel(kDefaultPathId, kFirstDecimatedPacket + 1 + i,
- !kEntropyFlag, !kHasStopWaiting,
- ENCRYPTION_INITIAL);
+ !kHasStopWaiting, ENCRYPTION_INITIAL);
}
// Check that ack is sent and that delayed ack alarm is reset.
EXPECT_EQ(2u, writer_->frame_count());
@@ -3839,7 +3730,7 @@ TEST_P(QuicConnectionTest, SendDelayedAckDecimationEighthRtt) {
EXPECT_FALSE(connection_.GetAckAlarm()->IsSet());
const uint8_t tag = 0x07;
connection_.SetDecrypter(ENCRYPTION_INITIAL, new StrictTaggingDecrypter(tag));
- framer_.SetEncrypter(ENCRYPTION_INITIAL, new TaggingEncrypter(tag));
+ peer_framer_.SetEncrypter(ENCRYPTION_INITIAL, new TaggingEncrypter(tag));
// Process a packet from the non-crypto stream.
frame1_.stream_id = 3;
@@ -3847,14 +3738,14 @@ TEST_P(QuicConnectionTest, SendDelayedAckDecimationEighthRtt) {
QuicPacketNumber kFirstDecimatedPacket = 101;
for (unsigned int i = 0; i < kFirstDecimatedPacket - 1; ++i) {
EXPECT_CALL(visitor_, OnStreamFrame(_)).Times(1);
- ProcessDataPacketAtLevel(kDefaultPathId, 1 + i, !kEntropyFlag,
- !kHasStopWaiting, ENCRYPTION_INITIAL);
+ ProcessDataPacketAtLevel(kDefaultPathId, 1 + i, !kHasStopWaiting,
+ ENCRYPTION_INITIAL);
}
EXPECT_FALSE(connection_.GetAckAlarm()->IsSet());
// The same as ProcessPacket(1) except that ENCRYPTION_INITIAL is used
// instead of ENCRYPTION_NONE.
EXPECT_CALL(visitor_, OnStreamFrame(_)).Times(1);
- ProcessDataPacketAtLevel(kDefaultPathId, kFirstDecimatedPacket, !kEntropyFlag,
+ ProcessDataPacketAtLevel(kDefaultPathId, kFirstDecimatedPacket,
!kHasStopWaiting, ENCRYPTION_INITIAL);
// Check if delayed ack timer is running for the expected interval.
@@ -3866,8 +3757,7 @@ TEST_P(QuicConnectionTest, SendDelayedAckDecimationEighthRtt) {
EXPECT_TRUE(connection_.GetAckAlarm()->IsSet());
EXPECT_CALL(visitor_, OnStreamFrame(_)).Times(1);
ProcessDataPacketAtLevel(kDefaultPathId, kFirstDecimatedPacket + 1 + i,
- !kEntropyFlag, !kHasStopWaiting,
- ENCRYPTION_INITIAL);
+ !kHasStopWaiting, ENCRYPTION_INITIAL);
}
// Check that ack is sent and that delayed ack alarm is reset.
EXPECT_EQ(2u, writer_->frame_count());
@@ -3892,7 +3782,7 @@ TEST_P(QuicConnectionTest, SendDelayedAckDecimationWithReordering) {
EXPECT_FALSE(connection_.GetAckAlarm()->IsSet());
const uint8_t tag = 0x07;
connection_.SetDecrypter(ENCRYPTION_INITIAL, new StrictTaggingDecrypter(tag));
- framer_.SetEncrypter(ENCRYPTION_INITIAL, new TaggingEncrypter(tag));
+ peer_framer_.SetEncrypter(ENCRYPTION_INITIAL, new TaggingEncrypter(tag));
// Process a packet from the non-crypto stream.
frame1_.stream_id = 3;
@@ -3900,14 +3790,14 @@ TEST_P(QuicConnectionTest, SendDelayedAckDecimationWithReordering) {
QuicPacketNumber kFirstDecimatedPacket = 101;
for (unsigned int i = 0; i < kFirstDecimatedPacket - 1; ++i) {
EXPECT_CALL(visitor_, OnStreamFrame(_)).Times(1);
- ProcessDataPacketAtLevel(kDefaultPathId, 1 + i, !kEntropyFlag,
- !kHasStopWaiting, ENCRYPTION_INITIAL);
+ ProcessDataPacketAtLevel(kDefaultPathId, 1 + i, !kHasStopWaiting,
+ ENCRYPTION_INITIAL);
}
EXPECT_FALSE(connection_.GetAckAlarm()->IsSet());
// The same as ProcessPacket(1) except that ENCRYPTION_INITIAL is used
// instead of ENCRYPTION_NONE.
EXPECT_CALL(visitor_, OnStreamFrame(_)).Times(1);
- ProcessDataPacketAtLevel(kDefaultPathId, kFirstDecimatedPacket, !kEntropyFlag,
+ ProcessDataPacketAtLevel(kDefaultPathId, kFirstDecimatedPacket,
!kHasStopWaiting, ENCRYPTION_INITIAL);
// Check if delayed ack timer is running for the expected interval.
@@ -3917,7 +3807,7 @@ TEST_P(QuicConnectionTest, SendDelayedAckDecimationWithReordering) {
// Process packet 10 first and ensure the alarm is one eighth min_rtt.
EXPECT_CALL(visitor_, OnStreamFrame(_)).Times(1);
ProcessDataPacketAtLevel(kDefaultPathId, kFirstDecimatedPacket + 9,
- !kEntropyFlag, !kHasStopWaiting, ENCRYPTION_INITIAL);
+ !kHasStopWaiting, ENCRYPTION_INITIAL);
ack_time = clock_.ApproximateNow() + QuicTime::Delta::FromMilliseconds(5);
EXPECT_TRUE(connection_.GetAckAlarm()->IsSet());
EXPECT_EQ(ack_time, connection_.GetAckAlarm()->deadline());
@@ -3927,8 +3817,7 @@ TEST_P(QuicConnectionTest, SendDelayedAckDecimationWithReordering) {
EXPECT_TRUE(connection_.GetAckAlarm()->IsSet());
EXPECT_CALL(visitor_, OnStreamFrame(_)).Times(1);
ProcessDataPacketAtLevel(kDefaultPathId, kFirstDecimatedPacket + 1 + i,
- !kEntropyFlag, !kHasStopWaiting,
- ENCRYPTION_INITIAL);
+ !kHasStopWaiting, ENCRYPTION_INITIAL);
}
// Check that ack is sent and that delayed ack alarm is reset.
EXPECT_EQ(2u, writer_->frame_count());
@@ -3953,7 +3842,7 @@ TEST_P(QuicConnectionTest, SendDelayedAckDecimationWithLargeReordering) {
EXPECT_FALSE(connection_.GetAckAlarm()->IsSet());
const uint8_t tag = 0x07;
connection_.SetDecrypter(ENCRYPTION_INITIAL, new StrictTaggingDecrypter(tag));
- framer_.SetEncrypter(ENCRYPTION_INITIAL, new TaggingEncrypter(tag));
+ peer_framer_.SetEncrypter(ENCRYPTION_INITIAL, new TaggingEncrypter(tag));
// Process a packet from the non-crypto stream.
frame1_.stream_id = 3;
@@ -3961,14 +3850,14 @@ TEST_P(QuicConnectionTest, SendDelayedAckDecimationWithLargeReordering) {
QuicPacketNumber kFirstDecimatedPacket = 101;
for (unsigned int i = 0; i < kFirstDecimatedPacket - 1; ++i) {
EXPECT_CALL(visitor_, OnStreamFrame(_)).Times(1);
- ProcessDataPacketAtLevel(kDefaultPathId, 1 + i, !kEntropyFlag,
- !kHasStopWaiting, ENCRYPTION_INITIAL);
+ ProcessDataPacketAtLevel(kDefaultPathId, 1 + i, !kHasStopWaiting,
+ ENCRYPTION_INITIAL);
}
EXPECT_FALSE(connection_.GetAckAlarm()->IsSet());
// The same as ProcessPacket(1) except that ENCRYPTION_INITIAL is used
// instead of ENCRYPTION_NONE.
EXPECT_CALL(visitor_, OnStreamFrame(_)).Times(1);
- ProcessDataPacketAtLevel(kDefaultPathId, kFirstDecimatedPacket, !kEntropyFlag,
+ ProcessDataPacketAtLevel(kDefaultPathId, kFirstDecimatedPacket,
!kHasStopWaiting, ENCRYPTION_INITIAL);
// Check if delayed ack timer is running for the expected interval.
@@ -3978,7 +3867,7 @@ TEST_P(QuicConnectionTest, SendDelayedAckDecimationWithLargeReordering) {
// Process packet 10 first and ensure the alarm is one eighth min_rtt.
EXPECT_CALL(visitor_, OnStreamFrame(_)).Times(1);
ProcessDataPacketAtLevel(kDefaultPathId, kFirstDecimatedPacket + 19,
- !kEntropyFlag, !kHasStopWaiting, ENCRYPTION_INITIAL);
+ !kHasStopWaiting, ENCRYPTION_INITIAL);
ack_time = clock_.ApproximateNow() + QuicTime::Delta::FromMilliseconds(5);
EXPECT_TRUE(connection_.GetAckAlarm()->IsSet());
EXPECT_EQ(ack_time, connection_.GetAckAlarm()->deadline());
@@ -3988,8 +3877,7 @@ TEST_P(QuicConnectionTest, SendDelayedAckDecimationWithLargeReordering) {
EXPECT_TRUE(connection_.GetAckAlarm()->IsSet());
EXPECT_CALL(visitor_, OnStreamFrame(_)).Times(1);
ProcessDataPacketAtLevel(kDefaultPathId, kFirstDecimatedPacket + 1 + i,
- !kEntropyFlag, !kHasStopWaiting,
- ENCRYPTION_INITIAL);
+ !kHasStopWaiting, ENCRYPTION_INITIAL);
}
// Check that ack is sent and that delayed ack alarm is reset.
EXPECT_EQ(2u, writer_->frame_count());
@@ -4002,7 +3890,7 @@ TEST_P(QuicConnectionTest, SendDelayedAckDecimationWithLargeReordering) {
EXPECT_FALSE(connection_.GetAckAlarm()->IsSet());
EXPECT_CALL(visitor_, OnStreamFrame(_)).Times(1);
ProcessDataPacketAtLevel(kDefaultPathId, kFirstDecimatedPacket + 10,
- !kEntropyFlag, !kHasStopWaiting, ENCRYPTION_INITIAL);
+ !kHasStopWaiting, ENCRYPTION_INITIAL);
// Check that ack is sent and that delayed ack alarm is reset.
EXPECT_EQ(2u, writer_->frame_count());
EXPECT_FALSE(writer_->stop_waiting_frames().empty());
@@ -4027,7 +3915,7 @@ TEST_P(QuicConnectionTest, SendDelayedAckDecimationWithReorderingEighthRtt) {
EXPECT_FALSE(connection_.GetAckAlarm()->IsSet());
const uint8_t tag = 0x07;
connection_.SetDecrypter(ENCRYPTION_INITIAL, new StrictTaggingDecrypter(tag));
- framer_.SetEncrypter(ENCRYPTION_INITIAL, new TaggingEncrypter(tag));
+ peer_framer_.SetEncrypter(ENCRYPTION_INITIAL, new TaggingEncrypter(tag));
// Process a packet from the non-crypto stream.
frame1_.stream_id = 3;
@@ -4035,14 +3923,14 @@ TEST_P(QuicConnectionTest, SendDelayedAckDecimationWithReorderingEighthRtt) {
QuicPacketNumber kFirstDecimatedPacket = 101;
for (unsigned int i = 0; i < kFirstDecimatedPacket - 1; ++i) {
EXPECT_CALL(visitor_, OnStreamFrame(_)).Times(1);
- ProcessDataPacketAtLevel(kDefaultPathId, 1 + i, !kEntropyFlag,
- !kHasStopWaiting, ENCRYPTION_INITIAL);
+ ProcessDataPacketAtLevel(kDefaultPathId, 1 + i, !kHasStopWaiting,
+ ENCRYPTION_INITIAL);
}
EXPECT_FALSE(connection_.GetAckAlarm()->IsSet());
// The same as ProcessPacket(1) except that ENCRYPTION_INITIAL is used
// instead of ENCRYPTION_NONE.
EXPECT_CALL(visitor_, OnStreamFrame(_)).Times(1);
- ProcessDataPacketAtLevel(kDefaultPathId, kFirstDecimatedPacket, !kEntropyFlag,
+ ProcessDataPacketAtLevel(kDefaultPathId, kFirstDecimatedPacket,
!kHasStopWaiting, ENCRYPTION_INITIAL);
// Check if delayed ack timer is running for the expected interval.
@@ -4052,7 +3940,7 @@ TEST_P(QuicConnectionTest, SendDelayedAckDecimationWithReorderingEighthRtt) {
// Process packet 10 first and ensure the alarm is one eighth min_rtt.
EXPECT_CALL(visitor_, OnStreamFrame(_)).Times(1);
ProcessDataPacketAtLevel(kDefaultPathId, kFirstDecimatedPacket + 9,
- !kEntropyFlag, !kHasStopWaiting, ENCRYPTION_INITIAL);
+ !kHasStopWaiting, ENCRYPTION_INITIAL);
ack_time = clock_.ApproximateNow() + QuicTime::Delta::FromMilliseconds(5);
EXPECT_TRUE(connection_.GetAckAlarm()->IsSet());
EXPECT_EQ(ack_time, connection_.GetAckAlarm()->deadline());
@@ -4062,8 +3950,7 @@ TEST_P(QuicConnectionTest, SendDelayedAckDecimationWithReorderingEighthRtt) {
EXPECT_TRUE(connection_.GetAckAlarm()->IsSet());
EXPECT_CALL(visitor_, OnStreamFrame(_)).Times(1);
ProcessDataPacketAtLevel(kDefaultPathId, kFirstDecimatedPacket + 1 + i,
- !kEntropyFlag, !kHasStopWaiting,
- ENCRYPTION_INITIAL);
+ !kHasStopWaiting, ENCRYPTION_INITIAL);
}
// Check that ack is sent and that delayed ack alarm is reset.
EXPECT_EQ(2u, writer_->frame_count());
@@ -4090,7 +3977,7 @@ TEST_P(QuicConnectionTest,
EXPECT_FALSE(connection_.GetAckAlarm()->IsSet());
const uint8_t tag = 0x07;
connection_.SetDecrypter(ENCRYPTION_INITIAL, new StrictTaggingDecrypter(tag));
- framer_.SetEncrypter(ENCRYPTION_INITIAL, new TaggingEncrypter(tag));
+ peer_framer_.SetEncrypter(ENCRYPTION_INITIAL, new TaggingEncrypter(tag));
// Process a packet from the non-crypto stream.
frame1_.stream_id = 3;
@@ -4098,14 +3985,14 @@ TEST_P(QuicConnectionTest,
QuicPacketNumber kFirstDecimatedPacket = 101;
for (unsigned int i = 0; i < kFirstDecimatedPacket - 1; ++i) {
EXPECT_CALL(visitor_, OnStreamFrame(_)).Times(1);
- ProcessDataPacketAtLevel(kDefaultPathId, 1 + i, !kEntropyFlag,
- !kHasStopWaiting, ENCRYPTION_INITIAL);
+ ProcessDataPacketAtLevel(kDefaultPathId, 1 + i, !kHasStopWaiting,
+ ENCRYPTION_INITIAL);
}
EXPECT_FALSE(connection_.GetAckAlarm()->IsSet());
// The same as ProcessPacket(1) except that ENCRYPTION_INITIAL is used
// instead of ENCRYPTION_NONE.
EXPECT_CALL(visitor_, OnStreamFrame(_)).Times(1);
- ProcessDataPacketAtLevel(kDefaultPathId, kFirstDecimatedPacket, !kEntropyFlag,
+ ProcessDataPacketAtLevel(kDefaultPathId, kFirstDecimatedPacket,
!kHasStopWaiting, ENCRYPTION_INITIAL);
// Check if delayed ack timer is running for the expected interval.
@@ -4115,7 +4002,7 @@ TEST_P(QuicConnectionTest,
// Process packet 10 first and ensure the alarm is one eighth min_rtt.
EXPECT_CALL(visitor_, OnStreamFrame(_)).Times(1);
ProcessDataPacketAtLevel(kDefaultPathId, kFirstDecimatedPacket + 19,
- !kEntropyFlag, !kHasStopWaiting, ENCRYPTION_INITIAL);
+ !kHasStopWaiting, ENCRYPTION_INITIAL);
ack_time = clock_.ApproximateNow() + QuicTime::Delta::FromMilliseconds(5);
EXPECT_TRUE(connection_.GetAckAlarm()->IsSet());
EXPECT_EQ(ack_time, connection_.GetAckAlarm()->deadline());
@@ -4125,8 +4012,7 @@ TEST_P(QuicConnectionTest,
EXPECT_TRUE(connection_.GetAckAlarm()->IsSet());
EXPECT_CALL(visitor_, OnStreamFrame(_)).Times(1);
ProcessDataPacketAtLevel(kDefaultPathId, kFirstDecimatedPacket + 1 + i,
- !kEntropyFlag, !kHasStopWaiting,
- ENCRYPTION_INITIAL);
+ !kHasStopWaiting, ENCRYPTION_INITIAL);
}
// Check that ack is sent and that delayed ack alarm is reset.
EXPECT_EQ(2u, writer_->frame_count());
@@ -4139,7 +4025,7 @@ TEST_P(QuicConnectionTest,
EXPECT_FALSE(connection_.GetAckAlarm()->IsSet());
EXPECT_CALL(visitor_, OnStreamFrame(_)).Times(1);
ProcessDataPacketAtLevel(kDefaultPathId, kFirstDecimatedPacket + 10,
- !kEntropyFlag, !kHasStopWaiting, ENCRYPTION_INITIAL);
+ !kHasStopWaiting, ENCRYPTION_INITIAL);
// Check that ack is sent and that delayed ack alarm is reset.
EXPECT_EQ(2u, writer_->frame_count());
EXPECT_FALSE(writer_->stop_waiting_frames().empty());
@@ -4264,7 +4150,7 @@ TEST_P(QuicConnectionTest, BundleAckForSecondCHLO) {
}
TEST_P(QuicConnectionTest, BundleAckForSecondCHLOTwoPacketReject) {
- FLAGS_quic_receive_packet_once_decrypted = true;
+ FLAGS_quic_reloadable_flag_quic_receive_packet_once_decrypted = true;
EXPECT_CALL(visitor_, OnSuccessfulVersionNegotiation(_));
EXPECT_FALSE(connection_.GetAckAlarm()->IsSet());
@@ -4276,7 +4162,7 @@ TEST_P(QuicConnectionTest, BundleAckForSecondCHLOTwoPacketReject) {
EXPECT_CALL(visitor_, OnStreamFrame(_))
.WillOnce(IgnoreResult(InvokeWithoutArgs(
&connection_, &TestConnection::SendCryptoStreamData)));
- ProcessDataPacket(kDefaultPathId, 2, kEntropyFlag);
+ ProcessDataPacket(kDefaultPathId, 2);
}
// Check that ack is sent and that delayed ack alarm is reset.
EXPECT_EQ(3u, writer_->frame_count());
@@ -4355,12 +4241,10 @@ TEST_P(QuicConnectionTest, SendWhenDisconnected) {
ConnectionCloseBehavior::SILENT_CLOSE);
EXPECT_FALSE(connection_.connected());
EXPECT_FALSE(connection_.CanWriteStreamData());
- QuicPacket* packet =
- ConstructDataPacket(kDefaultPathId, 1, !kEntropyFlag, !kHasStopWaiting);
+ QuicPacket* packet = ConstructDataPacket(kDefaultPathId, 1, !kHasStopWaiting);
EXPECT_CALL(*send_algorithm_, OnPacketSent(_, _, 1, _, _)).Times(0);
connection_.SendPacket(ENCRYPTION_NONE, kDefaultPathId, 1, packet,
- kTestEntropyHash, HAS_RETRANSMITTABLE_DATA, false,
- false);
+ HAS_RETRANSMITTABLE_DATA, false, false);
}
TEST_P(QuicConnectionTest, PublicReset) {
@@ -4432,100 +4316,7 @@ TEST_P(QuicConnectionTest, MissingPacketsBeforeLeastUnacked) {
EXPECT_CALL(visitor_, OnSuccessfulVersionNegotiation(_));
QuicStopWaitingFrame frame = InitStopWaitingFrame(4);
ProcessStopWaitingPacket(&frame);
- if (outgoing_ack()->missing) {
- EXPECT_TRUE(outgoing_ack()->packets.Empty());
- } else {
- EXPECT_FALSE(outgoing_ack()->packets.Empty());
- }
-}
-
-TEST_P(QuicConnectionTest, ReceivedEntropyHashCalculation) {
- if (GetParam().version > QUIC_VERSION_33) {
- return;
- }
- EXPECT_CALL(visitor_, OnStreamFrame(_)).Times(AtLeast(1));
- EXPECT_CALL(visitor_, OnSuccessfulVersionNegotiation(_));
- ProcessDataPacket(kDefaultPathId, 1, kEntropyFlag);
- ProcessDataPacket(kDefaultPathId, 4, kEntropyFlag);
- ProcessDataPacket(kDefaultPathId, 3, !kEntropyFlag);
- ProcessDataPacket(kDefaultPathId, 7, kEntropyFlag);
- EXPECT_EQ(146u, outgoing_ack()->entropy_hash);
-}
-
-TEST_P(QuicConnectionTest, UpdateEntropyForReceivedPackets) {
- if (GetParam().version > QUIC_VERSION_33) {
- return;
- }
- EXPECT_CALL(visitor_, OnStreamFrame(_)).Times(AtLeast(1));
- EXPECT_CALL(visitor_, OnSuccessfulVersionNegotiation(_));
- ProcessDataPacket(kDefaultPathId, 1, kEntropyFlag);
- ProcessDataPacket(kDefaultPathId, 5, kEntropyFlag);
- ProcessDataPacket(kDefaultPathId, 4, !kEntropyFlag);
- EXPECT_EQ(34u, outgoing_ack()->entropy_hash);
- // Make 4th packet my least unacked, and update entropy for 2, 3 packets.
- QuicPacketCreatorPeer::SetPacketNumber(&peer_creator_, 5);
- QuicPacketEntropyHash six_packet_entropy_hash = 0;
- QuicPacketEntropyHash random_entropy_hash = 129u;
- QuicStopWaitingFrame frame = InitStopWaitingFrame(4);
- frame.entropy_hash = random_entropy_hash;
- if (ProcessStopWaitingPacket(&frame)) {
- six_packet_entropy_hash = 1 << 6;
- }
-
- EXPECT_EQ((random_entropy_hash + (1 << 5) + six_packet_entropy_hash),
- outgoing_ack()->entropy_hash);
-}
-
-TEST_P(QuicConnectionTest, UpdateEntropyHashUptoCurrentPacket) {
- if (GetParam().version > QUIC_VERSION_33) {
- return;
- }
- EXPECT_CALL(visitor_, OnStreamFrame(_)).Times(AtLeast(1));
- EXPECT_CALL(visitor_, OnSuccessfulVersionNegotiation(_));
- ProcessDataPacket(kDefaultPathId, 1, kEntropyFlag);
- ProcessDataPacket(kDefaultPathId, 5, !kEntropyFlag);
- ProcessDataPacket(kDefaultPathId, 22, kEntropyFlag);
- EXPECT_EQ(66u, outgoing_ack()->entropy_hash);
- QuicPacketCreatorPeer::SetPacketNumber(&peer_creator_, 22);
- QuicPacketEntropyHash random_entropy_hash = 85u;
- // Current packet is the least unacked packet.
- QuicPacketEntropyHash ack_entropy_hash;
- QuicStopWaitingFrame frame = InitStopWaitingFrame(23);
- frame.entropy_hash = random_entropy_hash;
- ack_entropy_hash = ProcessStopWaitingPacket(&frame);
- EXPECT_EQ((random_entropy_hash + ack_entropy_hash),
- outgoing_ack()->entropy_hash);
- ProcessDataPacket(kDefaultPathId, 25, kEntropyFlag);
- EXPECT_EQ((random_entropy_hash + ack_entropy_hash + (1 << (25 % 8))),
- outgoing_ack()->entropy_hash);
-}
-
-TEST_P(QuicConnectionTest, EntropyCalculationForTruncatedAck) {
- if (GetParam().version > QUIC_VERSION_33) {
- return;
- }
- EXPECT_CALL(visitor_, OnStreamFrame(_)).Times(AtLeast(1));
- EXPECT_CALL(visitor_, OnSuccessfulVersionNegotiation(_));
- QuicPacketEntropyHash entropy[51];
- entropy[0] = 0;
- for (int i = 1; i < 51; ++i) {
- bool should_send = i % 10 != 1;
- bool entropy_flag = (i & (i - 1)) != 0;
- if (!should_send) {
- entropy[i] = entropy[i - 1];
- continue;
- }
- if (entropy_flag) {
- entropy[i] = entropy[i - 1] ^ (1 << (i % 8));
- } else {
- entropy[i] = entropy[i - 1];
- }
- ProcessDataPacket(kDefaultPathId, i, entropy_flag);
- }
- for (int i = 1; i < 50; ++i) {
- EXPECT_EQ(entropy[i],
- QuicConnectionPeer::ReceivedEntropyHash(&connection_, i));
- }
+ EXPECT_FALSE(outgoing_ack()->packets.Empty());
}
TEST_P(QuicConnectionTest, ServerSendsVersionNegotiationPacket) {
@@ -4641,8 +4432,8 @@ TEST_P(QuicConnectionTest, ClientHandlesVersionNegotiation) {
// Send a version negotiation packet.
std::unique_ptr<QuicEncryptedPacket> encrypted(
- framer_.BuildVersionNegotiationPacket(connection_id_,
- AllSupportedVersions()));
+ peer_framer_.BuildVersionNegotiationPacket(connection_id_,
+ AllSupportedVersions()));
std::unique_ptr<QuicReceivedPacket> received(
ConstructReceivedPacket(*encrypted, QuicTime::Zero()));
connection_.ProcessUdpPacket(kSelfAddress, kPeerAddress, *received);
@@ -4658,7 +4449,7 @@ TEST_P(QuicConnectionTest, ClientHandlesVersionNegotiation) {
frames.push_back(QuicFrame(&frame1_));
std::unique_ptr<QuicPacket> packet(ConstructPacket(header, frames));
char buffer[kMaxPacketSize];
- size_t encrypted_length = framer_.EncryptPayload(
+ size_t encrypted_length = peer_framer_.EncryptPayload(
ENCRYPTION_NONE, kDefaultPathId, 12, *packet, buffer, kMaxPacketSize);
ASSERT_NE(0u, encrypted_length);
EXPECT_CALL(visitor_, OnStreamFrame(_)).Times(1);
@@ -4685,7 +4476,7 @@ TEST_P(QuicConnectionTest, BadVersionNegotiation) {
}
TEST_P(QuicConnectionTest, CheckSendStats) {
- connection_.SetMaxTailLossProbes(kDefaultPathId, 0);
+ connection_.SetMaxTailLossProbes(0);
EXPECT_CALL(*send_algorithm_, OnPacketSent(_, _, _, _, _));
connection_.SendStreamDataWithString(3, "first", 0, !kFin, nullptr);
@@ -4747,7 +4538,7 @@ TEST_P(QuicConnectionTest, ProcessFramesIfPacketClosedConnection) {
std::unique_ptr<QuicPacket> packet(ConstructPacket(header, frames));
EXPECT_TRUE(nullptr != packet.get());
char buffer[kMaxPacketSize];
- size_t encrypted_length = framer_.EncryptPayload(
+ size_t encrypted_length = peer_framer_.EncryptPayload(
ENCRYPTION_NONE, kDefaultPathId, 1, *packet, buffer, kMaxPacketSize);
EXPECT_CALL(visitor_, OnConnectionClosed(QUIC_PEER_GOING_AWAY, _,
@@ -4823,11 +4614,11 @@ TEST_P(QuicConnectionTest, AckNotifierTriggerCallback) {
EXPECT_CALL(visitor_, OnSuccessfulVersionNegotiation(_));
// Create a listener which we expect to be called.
- scoped_refptr<MockAckListener> listener(new MockAckListener);
+ QuicReferenceCountedPointer<MockAckListener> listener(new MockAckListener);
EXPECT_CALL(*listener, OnPacketAcked(_, _)).Times(1);
// Send some data, which will register the listener to be notified.
- connection_.SendStreamDataWithString(1, "foo", 0, !kFin, listener.get());
+ connection_.SendStreamDataWithString(1, "foo", 0, !kFin, listener);
// Process an ACK from the server which should trigger the callback.
EXPECT_CALL(*send_algorithm_, OnCongestionEvent(true, _, _, _, _));
@@ -4839,12 +4630,12 @@ TEST_P(QuicConnectionTest, AckNotifierFailToTriggerCallback) {
EXPECT_CALL(visitor_, OnSuccessfulVersionNegotiation(_));
// Create a listener which we don't expect to be called.
- scoped_refptr<MockAckListener> listener(new MockAckListener);
+ QuicReferenceCountedPointer<MockAckListener> listener(new MockAckListener);
EXPECT_CALL(*listener, OnPacketAcked(_, _)).Times(0);
// Send some data, which will register the listener to be notified. This will
// not be ACKed and so the listener should never be called.
- connection_.SendStreamDataWithString(1, "foo", 0, !kFin, listener.get());
+ connection_.SendStreamDataWithString(1, "foo", 0, !kFin, listener);
// Send some other data which we will ACK.
connection_.SendStreamDataWithString(1, "foo", 0, !kFin, nullptr);
@@ -4866,13 +4657,13 @@ TEST_P(QuicConnectionTest, AckNotifierCallbackAfterRetransmission) {
EXPECT_CALL(visitor_, OnSuccessfulVersionNegotiation(_));
// Create a listener which we expect to be called.
- scoped_refptr<MockAckListener> listener(new MockAckListener);
+ QuicReferenceCountedPointer<MockAckListener> listener(new MockAckListener);
EXPECT_CALL(*listener, OnPacketRetransmitted(3)).Times(1);
EXPECT_CALL(*listener, OnPacketAcked(3, _)).Times(1);
// Send four packets, and register to be notified on ACK of packet 2.
connection_.SendStreamDataWithString(3, "foo", 0, !kFin, nullptr);
- connection_.SendStreamDataWithString(3, "bar", 0, !kFin, listener.get());
+ connection_.SendStreamDataWithString(3, "bar", 0, !kFin, listener);
connection_.SendStreamDataWithString(3, "baz", 0, !kFin, nullptr);
connection_.SendStreamDataWithString(3, "qux", 0, !kFin, nullptr);
@@ -4899,14 +4690,15 @@ TEST_P(QuicConnectionTest, AckNotifierCallbackAfterRetransmission) {
// out and was retransmitted, even though the retransmission has a
// different packet number.
TEST_P(QuicConnectionTest, AckNotifierCallbackForAckAfterRTO) {
- connection_.SetMaxTailLossProbes(kDefaultPathId, 0);
+ connection_.SetMaxTailLossProbes(0);
// Create a listener which we expect to be called.
- scoped_refptr<MockAckListener> listener(new StrictMock<MockAckListener>);
+ QuicReferenceCountedPointer<MockAckListener> listener(
+ new StrictMock<MockAckListener>);
QuicTime default_retransmission_time =
clock_.ApproximateNow() + DefaultRetransmissionTime();
- connection_.SendStreamDataWithString(3, "foo", 0, !kFin, listener.get());
+ connection_.SendStreamDataWithString(3, "foo", 0, !kFin, listener);
EXPECT_EQ(1u, stop_waiting()->least_unacked);
EXPECT_EQ(1u, writer_->header().packet_number);
@@ -4939,11 +4731,12 @@ TEST_P(QuicConnectionTest, AckNotifierCallbackForAckAfterRTO) {
// packet number.
TEST_P(QuicConnectionTest, AckNotifierCallbackForAckOfNackedPacket) {
// Create a listener which we expect to be called.
- scoped_refptr<MockAckListener> listener(new StrictMock<MockAckListener>);
+ QuicReferenceCountedPointer<MockAckListener> listener(
+ new StrictMock<MockAckListener>());
// Send four packets, and register to be notified on ACK of packet 2.
connection_.SendStreamDataWithString(3, "foo", 0, !kFin, nullptr);
- connection_.SendStreamDataWithString(3, "bar", 0, !kFin, listener.get());
+ connection_.SendStreamDataWithString(3, "bar", 0, !kFin, listener);
connection_.SendStreamDataWithString(3, "baz", 0, !kFin, nullptr);
connection_.SendStreamDataWithString(3, "qux", 0, !kFin, nullptr);
@@ -4988,7 +4781,7 @@ TEST_P(QuicConnectionTest, OnPacketHeaderDebugVisitor) {
TEST_P(QuicConnectionTest, Pacing) {
// static_cast here does not work if using multipath_sent_packet_manager.
- FLAGS_quic_enable_multipath = false;
+ FLAGS_quic_reloadable_flag_quic_enable_multipath = false;
TestConnection server(connection_id_, kSelfAddress, helper_.get(),
alarm_factory_.get(), writer_.get(),
Perspective::IS_SERVER, version());
@@ -5036,9 +4829,9 @@ TEST_P(QuicConnectionTest, NoDataNoFin) {
// Make sure that a call to SendStreamWithData, with no data and no FIN, does
// not result in a QuicAckNotifier being used-after-free (fail under ASAN).
// Regression test for b/18594622
- scoped_refptr<MockAckListener> listener(new MockAckListener);
+ QuicReferenceCountedPointer<MockAckListener> listener(new MockAckListener);
EXPECT_QUIC_BUG(
- connection_.SendStreamDataWithString(3, "", 0, !kFin, listener.get()),
+ connection_.SendStreamDataWithString(3, "", 0, !kFin, listener),
"Attempt to send empty stream frame");
}
@@ -5122,7 +4915,7 @@ TEST_P(QuicConnectionTest, SendingUnencryptedStreamDataFails) {
TEST_P(QuicConnectionTest, EnableMultipathNegotiation) {
// Test multipath negotiation during crypto handshake. Multipath is enabled
// when both endpoints enable multipath.
- FLAGS_quic_enable_multipath = true;
+ FLAGS_quic_reloadable_flag_quic_enable_multipath = true;
EXPECT_TRUE(connection_.connected());
EXPECT_FALSE(QuicConnectionPeer::IsMultipathEnabled(&connection_));
EXPECT_CALL(*send_algorithm_, SetFromConfig(_, _));
@@ -5174,10 +4967,10 @@ TEST_P(QuicConnectionTest, OnPathDegrading) {
EXPECT_CALL(*send_algorithm_, OnPacketSent(_, _, _, _, _))
.WillOnce(DoAll(SaveArg<3>(&packet_size), Return(true)));
connection_.SendStreamDataWithString(3, "packet", 0, !kFin, nullptr);
- size_t num_timeouts = kMinTimeoutsBeforePathDegrading +
- QuicSentPacketManagerPeer::GetMaxTailLossProbes(
- QuicConnectionPeer::GetSentPacketManager(
- &connection_, kDefaultPathId));
+ size_t num_timeouts =
+ kMinTimeoutsBeforePathDegrading +
+ QuicSentPacketManagerPeer::GetMaxTailLossProbes(
+ QuicConnectionPeer::GetSentPacketManager(&connection_));
for (size_t i = 1; i < num_timeouts; ++i) {
clock_.AdvanceTime(QuicTime::Delta::FromSeconds(10 * i));
EXPECT_CALL(*send_algorithm_, OnPacketSent(_, _, _, packet_size, _));
@@ -5243,11 +5036,6 @@ TEST_P(QuicConnectionTest, ClientReceivesRejOnNonCryptoStream) {
TEST_P(QuicConnectionTest, CloseConnectionOnPacketTooLarge) {
SimulateNextPacketTooLarge();
- if (!FLAGS_quic_only_track_sent_packets) {
- // Although the data packet cannot be written, the send packet manager is
- // informed.
- EXPECT_CALL(*send_algorithm_, OnPacketSent(_, _, _, _, _)).Times(2);
- }
// A connection close packet is sent
EXPECT_CALL(visitor_, OnConnectionClosed(QUIC_PACKET_WRITE_ERROR, _,
ConnectionCloseSource::FROM_SELF))
@@ -5259,9 +5047,6 @@ TEST_P(QuicConnectionTest, AlwaysGetPacketTooLarge) {
// Test even we always get packet too large, we do not infinitely try to send
// close packet.
AlwaysGetPacketTooLarge();
- if (!FLAGS_quic_only_track_sent_packets) {
- EXPECT_CALL(*send_algorithm_, OnPacketSent(_, _, _, _, _)).Times(2);
- }
EXPECT_CALL(visitor_, OnConnectionClosed(QUIC_PACKET_WRITE_ERROR, _,
ConnectionCloseSource::FROM_SELF))
.Times(1);
@@ -5325,6 +5110,17 @@ TEST_P(QuicConnectionTest, DonotForceSendingAckOnPacketTooLarge) {
EXPECT_TRUE(writer_->ack_frames().empty());
}
+TEST_P(QuicConnectionTest, CloseConnectionForStatelessReject) {
+ string error_details("stateless reject");
+ EXPECT_CALL(visitor_, OnConnectionClosed(
+ QUIC_CRYPTO_HANDSHAKE_STATELESS_REJECT,
+ error_details, ConnectionCloseSource::FROM_PEER));
+ connection_.set_perspective(Perspective::IS_CLIENT);
+ connection_.CloseConnection(QUIC_CRYPTO_HANDSHAKE_STATELESS_REJECT,
+ error_details,
+ ConnectionCloseBehavior::SILENT_CLOSE);
+}
+
} // namespace
} // namespace test
} // namespace net
diff --git a/chromium/net/quic/core/quic_constants.cc b/chromium/net/quic/core/quic_constants.cc
new file mode 100644
index 00000000000..381e8bfcae2
--- /dev/null
+++ b/chromium/net/quic/core/quic_constants.cc
@@ -0,0 +1,11 @@
+// Copyright (c) 2016 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.
+
+#include "net/quic/core/quic_constants.h"
+
+namespace net {
+
+const char* const kFinalOffsetHeaderKey = ":final-offset";
+
+} // namespace net
diff --git a/chromium/net/quic/core/quic_constants.h b/chromium/net/quic/core/quic_constants.h
new file mode 100644
index 00000000000..9783db0691e
--- /dev/null
+++ b/chromium/net/quic/core/quic_constants.h
@@ -0,0 +1,189 @@
+// Copyright (c) 2012 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.
+
+#ifndef NET_QUIC_CORE_QUIC_CONSTANTS_H_
+#define NET_QUIC_CORE_QUIC_CONSTANTS_H_
+
+#include <stddef.h>
+
+#include <cstdint>
+#include <limits>
+
+#include "base/macros.h"
+#include "net/quic/core/quic_types.h"
+#include "net/quic/platform/api/quic_export.h"
+
+// Definitions of constant values used throughout the QUIC code.
+
+namespace net {
+
+// Simple time constants.
+const uint64_t kNumSecondsPerMinute = 60;
+const uint64_t kNumSecondsPerHour = kNumSecondsPerMinute * 60;
+const uint64_t kNumSecondsPerWeek = kNumSecondsPerHour * 24 * 7;
+const uint64_t kNumMicrosPerMilli = 1000;
+const uint64_t kNumMicrosPerSecond = 1000 * 1000;
+
+// Default initial maximum size in bytes of a QUIC packet.
+const QuicByteCount kDefaultMaxPacketSize = 1350;
+const QuicByteCount kDefaultServerMaxPacketSize = 1000;
+// The maximum packet size of any QUIC packet, based on ethernet's max size,
+// minus the IP and UDP headers. IPv6 has a 40 byte header, UDP adds an
+// additional 8 bytes. This is a total overhead of 48 bytes. Ethernet's
+// max packet size is 1500 bytes, 1500 - 48 = 1452.
+const QuicByteCount kMaxPacketSize = 1452;
+// Default maximum packet size used in the Linux TCP implementation.
+// Used in QUIC for congestion window computations in bytes.
+const QuicByteCount kDefaultTCPMSS = 1460;
+
+// We match SPDY's use of 32 (since we'd compete with SPDY).
+const QuicPacketCount kInitialCongestionWindow = 32;
+
+// Minimum size of initial flow control window, for both stream and session.
+const uint32_t kMinimumFlowControlSendWindow = 16 * 1024; // 16 KB
+
+// Maximum flow control receive window limits for connection and stream.
+const QuicByteCount kStreamReceiveWindowLimit = 16 * 1024 * 1024; // 16 MB
+const QuicByteCount kSessionReceiveWindowLimit = 24 * 1024 * 1024; // 24 MB
+
+// Default limit on the size of uncompressed headers.
+const QuicByteCount kDefaultMaxUncompressedHeaderSize = 16 * 1024; // 16 KB
+
+// Minimum size of the CWND, in packets, when doing bandwidth resumption.
+const QuicPacketCount kMinCongestionWindowForBandwidthResumption = 10;
+
+// Maximum number of tracked packets.
+const QuicPacketCount kMaxTrackedPackets = 10000;
+
+// Default size of the socket receive buffer in bytes.
+const QuicByteCount kDefaultSocketReceiveBuffer = 1024 * 1024;
+
+// Don't allow a client to suggest an RTT shorter than 10ms.
+const uint32_t kMinInitialRoundTripTimeUs = 10 * kNumMicrosPerMilli;
+
+// Don't allow a client to suggest an RTT longer than 15 seconds.
+const uint32_t kMaxInitialRoundTripTimeUs = 15 * kNumMicrosPerSecond;
+
+// Maximum number of open streams per connection.
+const size_t kDefaultMaxStreamsPerConnection = 100;
+
+// Number of bytes reserved for public flags in the packet header.
+const size_t kPublicFlagsSize = 1;
+// Number of bytes reserved for version number in the packet header.
+const size_t kQuicVersionSize = 4;
+// Number of bytes reserved for path id in the packet header.
+const size_t kQuicPathIdSize = 1;
+// Number of bytes reserved for private flags in the packet header.
+const size_t kPrivateFlagsSize = 1;
+
+// Signifies that the QuicPacket will contain version of the protocol.
+const bool kIncludeVersion = true;
+// Signifies that the QuicPacket will contain path id.
+const bool kIncludePathId = true;
+// Signifies that the QuicPacket will include a diversification nonce.
+const bool kIncludeDiversificationNonce = true;
+
+// Stream ID is reserved to denote an invalid ID.
+const QuicStreamId kInvalidStreamId = 0;
+
+// Reserved ID for the crypto stream.
+const QuicStreamId kCryptoStreamId = 1;
+
+// Reserved ID for the headers stream.
+const QuicStreamId kHeadersStreamId = 3;
+
+// Header key used to identify final offset on data stream when sending HTTP/2
+// trailing headers over QUIC.
+QUIC_EXPORT_PRIVATE extern const char* const kFinalOffsetHeaderKey;
+
+// Maximum delayed ack time, in ms.
+const int64_t kMaxDelayedAckTimeMs = 25;
+
+// Minimum tail loss probe time in ms.
+static const int64_t kMinTailLossProbeTimeoutMs = 10;
+
+// The timeout before the handshake succeeds.
+const int64_t kInitialIdleTimeoutSecs = 5;
+// The default idle timeout.
+const int64_t kDefaultIdleTimeoutSecs = 30;
+// The maximum idle timeout that can be negotiated.
+const int64_t kMaximumIdleTimeoutSecs = 60 * 10; // 10 minutes.
+// The default timeout for a connection until the crypto handshake succeeds.
+const int64_t kMaxTimeForCryptoHandshakeSecs = 10; // 10 secs.
+
+// Default limit on the number of undecryptable packets the connection buffers
+// before the CHLO/SHLO arrive.
+const size_t kDefaultMaxUndecryptablePackets = 10;
+
+// Default ping timeout.
+const int64_t kPingTimeoutSecs = 15; // 15 secs.
+
+// Minimum number of RTTs between Server Config Updates (SCUP) sent to client.
+const int kMinIntervalBetweenServerConfigUpdatesRTTs = 10;
+
+// Minimum time between Server Config Updates (SCUP) sent to client.
+const int kMinIntervalBetweenServerConfigUpdatesMs = 1000;
+
+// Minimum number of packets between Server Config Updates (SCUP).
+const int kMinPacketsBetweenServerConfigUpdates = 100;
+
+// The number of open streams that a server will accept is set to be slightly
+// larger than the negotiated limit. Immediately closing the connection if the
+// client opens slightly too many streams is not ideal: the client may have sent
+// a FIN that was lost, and simultaneously opened a new stream. The number of
+// streams a server accepts is a fixed increment over the negotiated limit, or a
+// percentage increase, whichever is larger.
+const float kMaxStreamsMultiplier = 1.1f;
+const int kMaxStreamsMinimumIncrement = 10;
+
+// Available streams are ones with IDs less than the highest stream that has
+// been opened which have neither been opened or reset. The limit on the number
+// of available streams is 10 times the limit on the number of open streams.
+const int kMaxAvailableStreamsMultiplier = 10;
+
+// Track the number of promises that are not yet claimed by a
+// corresponding get. This must be smaller than
+// kMaxAvailableStreamsMultiplier, because RST on a promised stream my
+// create available streams entries.
+const int kMaxPromisedStreamsMultiplier = kMaxAvailableStreamsMultiplier - 1;
+
+// TCP RFC calls for 1 second RTO however Linux differs from this default and
+// define the minimum RTO to 200ms, we will use the same until we have data to
+// support a higher or lower value.
+static const int64_t kMinRetransmissionTimeMs = 200;
+
+// We define an unsigned 16-bit floating point value, inspired by IEEE floats
+// (http://en.wikipedia.org/wiki/Half_precision_floating-point_format),
+// with 5-bit exponent (bias 1), 11-bit mantissa (effective 12 with hidden
+// bit) and denormals, but without signs, transfinites or fractions. Wire format
+// 16 bits (little-endian byte order) are split into exponent (high 5) and
+// mantissa (low 11) and decoded as:
+// uint64_t value;
+// if (exponent == 0) value = mantissa;
+// else value = (mantissa | 1 << 11) << (exponent - 1)
+const int kUFloat16ExponentBits = 5;
+const int kUFloat16MaxExponent = (1 << kUFloat16ExponentBits) - 2; // 30
+const int kUFloat16MantissaBits = 16 - kUFloat16ExponentBits; // 11
+const int kUFloat16MantissaEffectiveBits = kUFloat16MantissaBits + 1; // 12
+const uint64_t kUFloat16MaxValue = // 0x3FFC0000000
+ ((UINT64_C(1) << kUFloat16MantissaEffectiveBits) - 1)
+ << kUFloat16MaxExponent;
+
+// Default path ID.
+const QuicPathId kDefaultPathId = 0;
+// Invalid path ID.
+const QuicPathId kInvalidPathId = 0xff;
+
+// kDiversificationNonceSize is the size, in bytes, of the nonce that a server
+// may set in the packet header to ensure that its INITIAL keys are not
+// duplicated.
+const size_t kDiversificationNonceSize = 32;
+
+// The largest gap in packets we'll accept without closing the connection.
+// This will likely have to be tuned.
+const QuicPacketNumber kMaxPacketGap = 5000;
+
+} // namespace net
+
+#endif // NET_QUIC_CORE_QUIC_CONSTANTS_H_
diff --git a/chromium/net/quic/core/quic_crypto_client_stream.cc b/chromium/net/quic/core/quic_crypto_client_stream.cc
index e2c4070fe80..e6d86638359 100644
--- a/chromium/net/quic/core/quic_crypto_client_stream.cc
+++ b/chromium/net/quic/core/quic_crypto_client_stream.cc
@@ -9,20 +9,22 @@
#include "base/metrics/histogram_macros.h"
#include "base/metrics/sparse_histogram.h"
-#include "base/strings/stringprintf.h"
#include "net/quic/core/crypto/crypto_protocol.h"
#include "net/quic/core/crypto/crypto_utils.h"
#include "net/quic/core/crypto/null_encrypter.h"
#include "net/quic/core/quic_flags.h"
-#include "net/quic/core/quic_protocol.h"
+#include "net/quic/core/quic_packets.h"
#include "net/quic/core/quic_session.h"
#include "net/quic/core/quic_utils.h"
+#include "net/quic/platform/api/quic_logging.h"
+#include "net/quic/platform/api/quic_str_cat.h"
using std::string;
-using std::vector;
namespace net {
+const int QuicCryptoClientStream::kMaxClientHellos;
+
QuicCryptoClientStreamBase::QuicCryptoClientStreamBase(QuicSession* session)
: QuicCryptoStream(session) {}
@@ -39,7 +41,7 @@ void QuicCryptoClientStream::ChannelIDSourceCallbackImpl::Run(
return;
}
- stream_->channel_id_key_.reset(channel_id_key->release());
+ stream_->channel_id_key_ = std::move(*channel_id_key);
stream_->channel_id_source_callback_run_ = true;
stream_->channel_id_source_callback_ = nullptr;
stream_->DoHandshakeLoop(nullptr);
@@ -69,7 +71,7 @@ void QuicCryptoClientStream::ProofVerifierCallbackImpl::Run(
stream_->verify_ok_ = ok;
stream_->verify_error_details_ = error_details;
- stream_->verify_details_.reset(details->release());
+ stream_->verify_details_ = std::move(*details);
stream_->proof_verify_callback_ = nullptr;
stream_->DoHandshakeLoop(nullptr);
@@ -171,7 +173,7 @@ void QuicCryptoClientStream::HandleServerConfigUpdateMessage(
crypto_config_->LookupOrCreate(server_id_);
QuicErrorCode error = crypto_config_->ProcessServerConfigUpdate(
server_config_update, session()->connection()->clock()->WallNow(),
- session()->connection()->version(), cached->chlo_hash(), cached,
+ session()->connection()->version(), chlo_hash_, cached,
crypto_negotiated_params_, &error_details);
if (error != QUIC_NO_ERROR) {
@@ -278,7 +280,7 @@ void QuicCryptoClientStream::DoSendCHLO(
if (num_client_hellos_ > kMaxClientHellos) {
CloseConnectionWithDetails(
QUIC_CRYPTO_TOO_MANY_REJECTS,
- base::StringPrintf("More than %u rejects", kMaxClientHellos).c_str());
+ QuicStrCat("More than ", kMaxClientHellos, " rejects"));
return;
}
num_client_hellos_++;
@@ -304,14 +306,14 @@ void QuicCryptoClientStream::DoSendCHLO(
const QuicByteCount max_packet_size =
session()->connection()->max_packet_length();
if (max_packet_size <= kFramingOverhead) {
- DLOG(DFATAL) << "max_packet_length (" << max_packet_size
- << ") has no room for framing overhead.";
+ QUIC_DLOG(DFATAL) << "max_packet_length (" << max_packet_size
+ << ") has no room for framing overhead.";
CloseConnectionWithDetails(QUIC_INTERNAL_ERROR,
"max_packet_size too smalll");
return;
}
if (kClientHelloMinimumSize > max_packet_size - kFramingOverhead) {
- DLOG(DFATAL) << "Client hello won't fit in a single packet.";
+ QUIC_DLOG(DFATAL) << "Client hello won't fit in a single packet.";
CloseConnectionWithDetails(QUIC_INTERNAL_ERROR, "CHLO too large");
return;
}
@@ -327,7 +329,7 @@ void QuicCryptoClientStream::DoSendCHLO(
// If the server nonce is empty, copy over the server nonce from a previous
// SREJ, if there is one.
- if (FLAGS_enable_quic_stateless_reject_support &&
+ if (FLAGS_quic_reloadable_flag_enable_quic_stateless_reject_support &&
crypto_negotiated_params_->server_nonce.empty() &&
cached->has_server_nonce()) {
crypto_negotiated_params_->server_nonce = cached->GetNextServerNonce();
@@ -337,7 +339,6 @@ void QuicCryptoClientStream::DoSendCHLO(
string error_details;
QuicErrorCode error = crypto_config_->FillClientHello(
server_id_, session()->connection()->connection_id(),
- session()->connection()->version(),
session()->connection()->supported_versions().front(), cached,
session()->connection()->clock()->WallNow(),
session()->connection()->random_generator(), channel_id_key_.get(),
@@ -465,7 +466,7 @@ QuicAsyncStatus QuicCryptoClientStream::DoVerifyProof(
switch (status) {
case QUIC_PENDING:
proof_verify_callback_ = proof_verify_callback;
- DVLOG(1) << "Doing VerifyProof";
+ QUIC_DVLOG(1) << "Doing VerifyProof";
break;
case QUIC_FAILURE:
break;
@@ -532,7 +533,7 @@ QuicAsyncStatus QuicCryptoClientStream::DoGetChannelID(
switch (status) {
case QUIC_PENDING:
channel_id_source_callback_ = channel_id_source_callback;
- DVLOG(1) << "Looking up channel ID";
+ QUIC_DVLOG(1) << "Looking up channel ID";
break;
case QUIC_FAILURE:
next_state_ = STATE_NONE;
diff --git a/chromium/net/quic/core/quic_crypto_client_stream.h b/chromium/net/quic/core/quic_crypto_client_stream.h
index 94e3fdae44d..cc937f09393 100644
--- a/chromium/net/quic/core/quic_crypto_client_stream.h
+++ b/chromium/net/quic/core/quic_crypto_client_stream.h
@@ -2,21 +2,21 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#ifndef NET_QUIC_QUIC_CRYPTO_CLIENT_STREAM_H_
-#define NET_QUIC_QUIC_CRYPTO_CLIENT_STREAM_H_
+#ifndef NET_QUIC_CORE_QUIC_CRYPTO_CLIENT_STREAM_H_
+#define NET_QUIC_CORE_QUIC_CRYPTO_CLIENT_STREAM_H_
#include <cstdint>
#include <memory>
#include <string>
#include "base/macros.h"
-#include "net/base/net_export.h"
#include "net/quic/core/crypto/channel_id.h"
#include "net/quic/core/crypto/proof_verifier.h"
#include "net/quic/core/crypto/quic_crypto_client_config.h"
#include "net/quic/core/quic_config.h"
#include "net/quic/core/quic_crypto_stream.h"
#include "net/quic/core/quic_server_id.h"
+#include "net/quic/platform/api/quic_export.h"
namespace net {
@@ -25,7 +25,7 @@ class CryptoTestUtils;
class QuicChromiumClientSessionPeer;
} // namespace test
-class NET_EXPORT_PRIVATE QuicCryptoClientStreamBase : public QuicCryptoStream {
+class QUIC_EXPORT_PRIVATE QuicCryptoClientStreamBase : public QuicCryptoStream {
public:
explicit QuicCryptoClientStreamBase(QuicSession* session);
@@ -45,7 +45,7 @@ class NET_EXPORT_PRIVATE QuicCryptoClientStreamBase : public QuicCryptoStream {
virtual int num_scup_messages_received() const = 0;
};
-class NET_EXPORT_PRIVATE QuicCryptoClientStream
+class QUIC_EXPORT_PRIVATE QuicCryptoClientStream
: public QuicCryptoClientStreamBase {
public:
// kMaxClientHellos is the maximum number of times that we'll send a client
@@ -58,7 +58,7 @@ class NET_EXPORT_PRIVATE QuicCryptoClientStream
// ProofHandler is an interface that handles callbacks from the crypto
// stream when the client has proof verification details of the server.
- class NET_EXPORT_PRIVATE ProofHandler {
+ class QUIC_EXPORT_PRIVATE ProofHandler {
public:
virtual ~ProofHandler() {}
@@ -99,6 +99,8 @@ class NET_EXPORT_PRIVATE QuicCryptoClientStream
// ChannelIDSource operated asynchronously. Intended for testing.
bool WasChannelIDSourceCallbackRun() const;
+ std::string chlo_hash() const { return chlo_hash_; }
+
private:
// ChannelIDSourceCallbackImpl is passed as the callback method to
// GetChannelIDKey. The ChannelIDSource calls this class with the result of
@@ -274,4 +276,4 @@ class NET_EXPORT_PRIVATE QuicCryptoClientStream
} // namespace net
-#endif // NET_QUIC_QUIC_CRYPTO_CLIENT_STREAM_H_
+#endif // NET_QUIC_CORE_QUIC_CRYPTO_CLIENT_STREAM_H_
diff --git a/chromium/net/quic/core/quic_crypto_client_stream_test.cc b/chromium/net/quic/core/quic_crypto_client_stream_test.cc
index b6bbf6424b6..bbc2f37217a 100644
--- a/chromium/net/quic/core/quic_crypto_client_stream_test.cc
+++ b/chromium/net/quic/core/quic_crypto_client_stream_test.cc
@@ -10,7 +10,7 @@
#include "net/quic/core/crypto/quic_decrypter.h"
#include "net/quic/core/crypto/quic_encrypter.h"
#include "net/quic/core/quic_flags.h"
-#include "net/quic/core/quic_protocol.h"
+#include "net/quic/core/quic_packets.h"
#include "net/quic/core/quic_server_id.h"
#include "net/quic/core/quic_utils.h"
#include "net/quic/test_tools/crypto_test_utils.h"
@@ -227,10 +227,48 @@ TEST_F(QuicCryptoClientStreamTest, ServerConfigUpdate) {
const string& cached_scfg = state->server_config();
test::CompareCharArraysWithHexError(
"scfg", cached_scfg.data(), cached_scfg.length(),
- QuicUtils::AsChars(scfg), arraysize(scfg));
+ reinterpret_cast<char*>(scfg), arraysize(scfg));
+
QuicStreamSequencer* sequencer = QuicStreamPeer::sequencer(stream());
- EXPECT_NE(FLAGS_quic_release_crypto_stream_buffer,
- QuicStreamSequencerPeer::IsUnderlyingBufferAllocated(sequencer));
+ EXPECT_NE(
+ FLAGS_quic_reloadable_flag_quic_release_crypto_stream_buffer &&
+ FLAGS_quic_reloadable_flag_quic_reduce_sequencer_buffer_memory_life_time, // NOLINT
+ QuicStreamSequencerPeer::IsUnderlyingBufferAllocated(sequencer));
+}
+
+TEST_F(QuicCryptoClientStreamTest, ServerConfigUpdateWithCert) {
+ // Test that the crypto client stream can receive and use server config
+ // updates with certificates after the connection has been established.
+ CompleteCryptoHandshake();
+
+ // Build a server config update message with certificates
+ QuicCryptoServerConfig crypto_config(
+ QuicCryptoServerConfig::TESTING, QuicRandom::GetInstance(),
+ CryptoTestUtils::ProofSourceForTesting());
+ CryptoTestUtils::FakeServerOptions options;
+ CryptoTestUtils::SetupCryptoServerConfigForTest(
+ connection_->clock(), QuicRandom::GetInstance(), &crypto_config, options);
+ SourceAddressTokens tokens;
+ QuicCompressedCertsCache cache(1);
+ CachedNetworkParameters network_params;
+ CryptoHandshakeMessage server_config_update;
+ EXPECT_TRUE(crypto_config.BuildServerConfigUpdateMessage(
+ session_->connection()->version(), stream()->chlo_hash(), tokens,
+ QuicSocketAddress(QuicIpAddress::Loopback6(), 1234),
+ QuicIpAddress::Loopback6(), connection_->clock(),
+ QuicRandom::GetInstance(), &cache, stream()->crypto_negotiated_params(),
+ &network_params, QuicTagVector(), &server_config_update));
+
+ std::unique_ptr<QuicData> data(
+ CryptoFramer::ConstructHandshakeMessage(server_config_update));
+ stream()->OnStreamFrame(QuicStreamFrame(kCryptoStreamId, /*fin=*/false,
+ /*offset=*/0, data->AsStringPiece()));
+
+ // Recreate connection with the new config and verify a 0-RTT attempt.
+ CreateConnection();
+
+ stream()->CryptoConnect();
+ EXPECT_TRUE(session_->IsEncryptionEstablished());
}
TEST_F(QuicCryptoClientStreamTest, ServerConfigUpdateBeforeHandshake) {
@@ -339,7 +377,7 @@ class QuicCryptoClientStreamStatelessTest : public ::testing::Test {
CryptoTestUtils::SetupCryptoServerConfigForTest(
server_connection_->clock(), server_connection_->random_generator(),
&server_crypto_config_, options);
- FLAGS_enable_quic_stateless_reject_support = true;
+ FLAGS_quic_reloadable_flag_enable_quic_stateless_reject_support = true;
}
QuicFlagSaver flags_; // Save/restore all QUIC flag values.
@@ -361,7 +399,7 @@ class QuicCryptoClientStreamStatelessTest : public ::testing::Test {
};
TEST_F(QuicCryptoClientStreamStatelessTest, StatelessReject) {
- FLAGS_enable_quic_stateless_reject_support = true;
+ FLAGS_quic_reloadable_flag_enable_quic_stateless_reject_support = true;
QuicCryptoClientConfig::CachedState* client_state =
client_crypto_config_.LookupOrCreate(server_id_);
diff --git a/chromium/net/quic/core/quic_crypto_server_stream.cc b/chromium/net/quic/core/quic_crypto_server_stream.cc
index 87f00962fb9..e08827bdd79 100644
--- a/chromium/net/quic/core/quic_crypto_server_stream.cc
+++ b/chromium/net/quic/core/quic_crypto_server_stream.cc
@@ -6,7 +6,6 @@
#include <memory>
-#include "base/base64.h"
#include "crypto/secure_hash.h"
#include "net/quic/core/crypto/crypto_protocol.h"
#include "net/quic/core/crypto/crypto_utils.h"
@@ -15,8 +14,10 @@
#include "net/quic/core/proto/cached_network_parameters.pb.h"
#include "net/quic/core/quic_config.h"
#include "net/quic/core/quic_flags.h"
-#include "net/quic/core/quic_protocol.h"
+#include "net/quic/core/quic_packets.h"
#include "net/quic/core/quic_session.h"
+#include "net/quic/platform/api/quic_logging.h"
+#include "net/quic/platform/api/quic_text_utils.h"
using base::StringPiece;
using std::string;
@@ -28,7 +29,8 @@ class QuicCryptoServerStream::ProcessClientHelloCallback
public:
ProcessClientHelloCallback(
QuicCryptoServerStream* stream,
- const scoped_refptr<ValidateClientHelloResultCallback::Result>& result)
+ const QuicReferenceCountedPointer<
+ ValidateClientHelloResultCallback::Result>& result)
: stream_(stream), result_(result) {}
void Run(QuicErrorCode error,
@@ -57,7 +59,8 @@ class QuicCryptoServerStream::ProcessClientHelloCallback
private:
QuicCryptoServerStream* stream_;
- scoped_refptr<ValidateClientHelloResultCallback::Result> result_;
+ QuicReferenceCountedPointer<ValidateClientHelloResultCallback::Result>
+ result_;
};
QuicCryptoServerStreamBase::QuicCryptoServerStreamBase(QuicSession* session)
@@ -92,7 +95,7 @@ QuicCryptoServerStream::QuicCryptoServerStream(
: QuicCryptoServerStreamBase(session),
crypto_config_(crypto_config),
compressed_certs_cache_(compressed_certs_cache),
- crypto_proof_(new QuicCryptoProof),
+ signed_config_(new QuicSignedServerConfig),
validate_client_hello_cb_(nullptr),
helper_(helper),
num_handshake_messages_(0),
@@ -161,13 +164,14 @@ void QuicCryptoServerStream::OnHandshakeMessage(
std::unique_ptr<ValidateCallback> cb(new ValidateCallback(this));
validate_client_hello_cb_ = cb.get();
crypto_config_->ValidateClientHello(
- message, session()->connection()->peer_address().address(),
- session()->connection()->self_address().address(), version(),
- session()->connection()->clock(), crypto_proof_, std::move(cb));
+ message, session()->connection()->peer_address().host(),
+ session()->connection()->self_address(), version(),
+ session()->connection()->clock(), signed_config_, std::move(cb));
}
void QuicCryptoServerStream::FinishProcessingHandshakeMessage(
- scoped_refptr<ValidateClientHelloResultCallback::Result> result,
+ QuicReferenceCountedPointer<ValidateClientHelloResultCallback::Result>
+ result,
std::unique_ptr<ProofSource::Details> details) {
const CryptoHandshakeMessage& message = result->client_hello;
@@ -214,9 +218,9 @@ void QuicCryptoServerStream::
DCHECK(use_stateless_rejects_if_peer_supported_);
DCHECK(peer_supports_stateless_rejects_);
DCHECK(!handshake_confirmed());
- DVLOG(1) << "Closing connection "
- << session()->connection()->connection_id()
- << " because of a stateless reject.";
+ QUIC_DLOG(INFO) << "Closing connection "
+ << session()->connection()->connection_id()
+ << " because of a stateless reject.";
session()->connection()->CloseConnection(
QUIC_CRYPTO_HANDSHAKE_STATELESS_REJECT, "stateless reject",
ConnectionCloseBehavior::SILENT_CLOSE);
@@ -255,9 +259,7 @@ void QuicCryptoServerStream::
session()->connection()->SetDecrypter(
ENCRYPTION_INITIAL,
crypto_negotiated_params_->initial_crypters.decrypter.release());
- if (version() > QUIC_VERSION_32) {
- session()->connection()->SetDiversificationNonce(*diversification_nonce);
- }
+ session()->connection()->SetDiversificationNonce(*diversification_nonce);
SendHandshakeMessage(*reply);
@@ -282,9 +284,9 @@ void QuicCryptoServerStream::SendServerConfigUpdate(
return;
}
- if (FLAGS_enable_async_get_proof) {
+ if (FLAGS_quic_reloadable_flag_enable_async_get_proof) {
if (send_server_config_update_cb_ != nullptr) {
- DVLOG(1)
+ QUIC_DVLOG(1)
<< "Skipped server config update since one is already in progress";
return;
}
@@ -296,8 +298,8 @@ void QuicCryptoServerStream::SendServerConfigUpdate(
crypto_config_->BuildServerConfigUpdateMessage(
session()->connection()->version(), chlo_hash_,
previous_source_address_tokens_,
- session()->connection()->self_address().address(),
- session()->connection()->peer_address().address(),
+ session()->connection()->self_address(),
+ session()->connection()->peer_address().host(),
session()->connection()->clock(),
session()->connection()->random_generator(), compressed_certs_cache_,
*crypto_negotiated_params_, cached_network_params,
@@ -312,8 +314,8 @@ void QuicCryptoServerStream::SendServerConfigUpdate(
if (!crypto_config_->BuildServerConfigUpdateMessage(
session()->connection()->version(), chlo_hash_,
previous_source_address_tokens_,
- session()->connection()->self_address().address(),
- session()->connection()->peer_address().address(),
+ session()->connection()->self_address(),
+ session()->connection()->peer_address().host(),
session()->connection()->clock(),
session()->connection()->random_generator(), compressed_certs_cache_,
*crypto_negotiated_params_, cached_network_params,
@@ -321,12 +323,12 @@ void QuicCryptoServerStream::SendServerConfigUpdate(
? session()->config()->ReceivedConnectionOptions()
: QuicTagVector()),
&server_config_update_message)) {
- DVLOG(1) << "Server: Failed to build server config update (SCUP)!";
+ QUIC_DVLOG(1) << "Server: Failed to build server config update (SCUP)!";
return;
}
- DVLOG(1) << "Server: Sending server config update: "
- << server_config_update_message.DebugString();
+ QUIC_DVLOG(1) << "Server: Sending server config update: "
+ << server_config_update_message.DebugString();
const QuicData& data = server_config_update_message.GetSerialized();
WriteOrBufferData(StringPiece(data.data(), data.length()), false, nullptr);
@@ -359,21 +361,18 @@ void QuicCryptoServerStream::FinishSendServerConfigUpdate(
send_server_config_update_cb_ = nullptr;
if (!ok) {
- DVLOG(1) << "Server: Failed to build server config update (SCUP)!";
+ QUIC_DVLOG(1) << "Server: Failed to build server config update (SCUP)!";
return;
}
- DVLOG(1) << "Server: Sending server config update: " << message.DebugString();
+ QUIC_DVLOG(1) << "Server: Sending server config update: "
+ << message.DebugString();
const QuicData& data = message.GetSerialized();
WriteOrBufferData(StringPiece(data.data(), data.length()), false, nullptr);
++num_server_config_update_messages_sent_;
}
-void QuicCryptoServerStream::OnServerHelloAcked() {
- session()->connection()->OnHandshakeComplete();
-}
-
uint8_t QuicCryptoServerStream::NumHandshakeMessages() const {
return num_handshake_messages_;
}
@@ -424,24 +423,13 @@ bool QuicCryptoServerStream::GetBase64SHA256ClientChannelID(
uint8_t digest[32];
hash->Finish(digest, sizeof(digest));
- base::Base64Encode(
- string(reinterpret_cast<const char*>(digest), sizeof(digest)), output);
- // Remove padding.
- size_t len = output->size();
- if (len >= 2) {
- if ((*output)[len - 1] == '=') {
- len--;
- if ((*output)[len - 1] == '=') {
- len--;
- }
- output->resize(len);
- }
- }
+ QuicTextUtils::Base64Encode(digest, arraysize(digest), output);
return true;
}
void QuicCryptoServerStream::ProcessClientHello(
- scoped_refptr<ValidateClientHelloResultCallback::Result> result,
+ QuicReferenceCountedPointer<ValidateClientHelloResultCallback::Result>
+ result,
std::unique_ptr<ProofSource::Details> proof_source_details,
std::unique_ptr<ProcessClientHelloResultCallback> done_cb) {
const CryptoHandshakeMessage& message = result->client_hello;
@@ -471,11 +459,11 @@ void QuicCryptoServerStream::ProcessClientHello(
GenerateConnectionIdForReject(use_stateless_rejects_in_crypto_config);
crypto_config_->ProcessClientHello(
result, /*reject_only=*/false, connection->connection_id(),
- connection->self_address().address(), connection->peer_address(),
- version(), connection->supported_versions(),
- use_stateless_rejects_in_crypto_config, server_designated_connection_id,
- connection->clock(), connection->random_generator(),
- compressed_certs_cache_, crypto_negotiated_params_, crypto_proof_,
+ connection->self_address(), connection->peer_address(), version(),
+ connection->supported_versions(), use_stateless_rejects_in_crypto_config,
+ server_designated_connection_id, connection->clock(),
+ connection->random_generator(), compressed_certs_cache_,
+ crypto_negotiated_params_, signed_config_,
QuicCryptoStream::CryptoMessageFramingOverhead(version()),
chlo_packet_size_, std::move(done_cb));
}
@@ -491,7 +479,7 @@ void QuicCryptoServerStream::ValidateCallback::Cancel() {
}
void QuicCryptoServerStream::ValidateCallback::Run(
- scoped_refptr<Result> result,
+ QuicReferenceCountedPointer<Result> result,
std::unique_ptr<ProofSource::Details> details) {
if (parent_ != nullptr) {
parent_->FinishProcessingHandshakeMessage(std::move(result),
diff --git a/chromium/net/quic/core/quic_crypto_server_stream.h b/chromium/net/quic/core/quic_crypto_server_stream.h
index aadc4aebd91..721a2763a22 100644
--- a/chromium/net/quic/core/quic_crypto_server_stream.h
+++ b/chromium/net/quic/core/quic_crypto_server_stream.h
@@ -2,21 +2,21 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#ifndef NET_QUIC_QUIC_CRYPTO_SERVER_STREAM_H_
-#define NET_QUIC_QUIC_CRYPTO_SERVER_STREAM_H_
+#ifndef NET_QUIC_CORE_QUIC_CRYPTO_SERVER_STREAM_H_
+#define NET_QUIC_CORE_QUIC_CRYPTO_SERVER_STREAM_H_
#include <cstdint>
#include <memory>
#include <string>
#include "base/macros.h"
-#include "net/base/net_export.h"
#include "net/quic/core/crypto/crypto_handshake.h"
#include "net/quic/core/crypto/quic_compressed_certs_cache.h"
#include "net/quic/core/crypto/quic_crypto_server_config.h"
#include "net/quic/core/proto/source_address_token.pb.h"
#include "net/quic/core/quic_config.h"
#include "net/quic/core/quic_crypto_stream.h"
+#include "net/quic/platform/api/quic_export.h"
namespace net {
@@ -24,7 +24,6 @@ class CachedNetworkParameters;
class CryptoHandshakeMessage;
class QuicCryptoServerConfig;
class QuicCryptoServerStreamBase;
-class QuicServerSessionBase;
namespace test {
class CryptoTestUtils;
@@ -33,7 +32,7 @@ class QuicCryptoServerStreamPeer;
// TODO(alyssar) see what can be moved out of QuicCryptoServerStream with
// various code and test refactoring.
-class NET_EXPORT_PRIVATE QuicCryptoServerStreamBase : public QuicCryptoStream {
+class QUIC_EXPORT_PRIVATE QuicCryptoServerStreamBase : public QuicCryptoStream {
public:
explicit QuicCryptoServerStreamBase(QuicSession* session);
@@ -54,10 +53,6 @@ class NET_EXPORT_PRIVATE QuicCryptoServerStreamBase : public QuicCryptoStream {
virtual void SendServerConfigUpdate(
const CachedNetworkParameters* cached_network_params) = 0;
- // Called by the ServerHello AckNotifier once the SHLO has been ACKed by the
- // client.
- virtual void OnServerHelloAcked() = 0;
-
// These are all accessors and setters to their respective counters.
virtual uint8_t NumHandshakeMessages() const = 0;
virtual uint8_t NumHandshakeMessagesWithServerNonces() const = 0;
@@ -75,7 +70,7 @@ class NET_EXPORT_PRIVATE QuicCryptoServerStreamBase : public QuicCryptoStream {
const CryptoHandshakeMessage& message);
};
-class NET_EXPORT_PRIVATE QuicCryptoServerStream
+class QUIC_EXPORT_PRIVATE QuicCryptoServerStream
: public QuicCryptoServerStreamBase {
public:
class Helper {
@@ -91,7 +86,7 @@ class NET_EXPORT_PRIVATE QuicCryptoServerStream
// acceptable according to the visitor's policy. Otherwise, returns false
// and populates |error_details|.
virtual bool CanAcceptClientHello(const CryptoHandshakeMessage& message,
- const IPEndPoint& self_address,
+ const QuicSocketAddress& self_address,
std::string* error_details) const = 0;
};
@@ -112,7 +107,6 @@ class NET_EXPORT_PRIVATE QuicCryptoServerStream
bool GetBase64SHA256ClientChannelID(std::string* output) const override;
void SendServerConfigUpdate(
const CachedNetworkParameters* cached_network_params) override;
- void OnServerHelloAcked() override;
uint8_t NumHandshakeMessages() const override;
uint8_t NumHandshakeMessagesWithServerNonces() const override;
int NumServerConfigUpdateMessagesSent() const override;
@@ -124,9 +118,19 @@ class NET_EXPORT_PRIVATE QuicCryptoServerStream
void SetPreviousCachedNetworkParams(
CachedNetworkParameters cached_network_params) override;
+ // NOTE: Indicating that the Expect-CT header should be sent here presents
+ // a layering violation to some extent. The Expect-CT header only applies to
+ // HTTP connections, while this class can be used for non-HTTP applications.
+ // However, it is exposed here because that is the only place where the
+ // configuration for the certificate used in the connection is accessible.
+ bool ShouldSendExpectCTHeader() const {
+ return signed_config_->proof.send_expect_ct_header;
+ }
+
protected:
virtual void ProcessClientHello(
- scoped_refptr<ValidateClientHelloResultCallback::Result> result,
+ QuicReferenceCountedPointer<ValidateClientHelloResultCallback::Result>
+ result,
std::unique_ptr<ProofSource::Details> proof_source_details,
std::unique_ptr<ProcessClientHelloResultCallback> done_cb);
@@ -145,7 +149,7 @@ class NET_EXPORT_PRIVATE QuicCryptoServerStream
void Cancel();
// From ValidateClientHelloResultCallback
- void Run(scoped_refptr<Result> result,
+ void Run(QuicReferenceCountedPointer<Result> result,
std::unique_ptr<ProofSource::Details> details) override;
private:
@@ -176,7 +180,8 @@ class NET_EXPORT_PRIVATE QuicCryptoServerStream
// the client hello is complete. Finishes processing of the client
// hello message and handles handshake success/failure.
void FinishProcessingHandshakeMessage(
- scoped_refptr<ValidateClientHelloResultCallback::Result> result,
+ QuicReferenceCountedPointer<ValidateClientHelloResultCallback::Result>
+ result,
std::unique_ptr<ProofSource::Details> details);
class ProcessClientHelloCallback;
@@ -212,7 +217,7 @@ class NET_EXPORT_PRIVATE QuicCryptoServerStream
// Server's certificate chain and signature of the server config, as provided
// by ProofSource::GetProof.
- scoped_refptr<QuicCryptoProof> crypto_proof_;
+ QuicReferenceCountedPointer<QuicSignedServerConfig> signed_config_;
// Hash of the last received CHLO message which can be used for generating
// server config update messages.
@@ -276,4 +281,4 @@ class NET_EXPORT_PRIVATE QuicCryptoServerStream
} // namespace net
-#endif // NET_QUIC_QUIC_CRYPTO_SERVER_STREAM_H_
+#endif // NET_QUIC_CORE_QUIC_CRYPTO_SERVER_STREAM_H_
diff --git a/chromium/net/quic/core/quic_crypto_server_stream_test.cc b/chromium/net/quic/core/quic_crypto_server_stream_test.cc
index 27c9abcb2cd..bba6bda2fda 100644
--- a/chromium/net/quic/core/quic_crypto_server_stream_test.cc
+++ b/chromium/net/quic/core/quic_crypto_server_stream_test.cc
@@ -8,7 +8,6 @@
#include <memory>
#include <vector>
-#include "base/memory/ptr_util.h"
#include "net/quic/core/crypto/aes_128_gcm_12_encrypter.h"
#include "net/quic/core/crypto/crypto_framer.h"
#include "net/quic/core/crypto/crypto_handshake.h"
@@ -20,10 +19,13 @@
#include "net/quic/core/crypto/quic_random.h"
#include "net/quic/core/quic_crypto_client_stream.h"
#include "net/quic/core/quic_flags.h"
-#include "net/quic/core/quic_protocol.h"
+#include "net/quic/core/quic_packets.h"
#include "net/quic/core/quic_session.h"
+#include "net/quic/platform/api/quic_logging.h"
+#include "net/quic/platform/api/quic_ptr_util.h"
+#include "net/quic/platform/api/quic_socket_address.h"
#include "net/quic/test_tools/crypto_test_utils.h"
-#include "net/quic/test_tools/delayed_verify_strike_register_client.h"
+#include "net/quic/test_tools/failing_proof_source.h"
#include "net/quic/test_tools/quic_crypto_server_config_peer.h"
#include "net/quic/test_tools/quic_test_utils.h"
#include "testing/gmock/include/gmock/gmock.h"
@@ -67,26 +69,10 @@ class QuicCryptoServerStreamTest : public ::testing::TestWithParam<bool> {
QuicCompressedCertsCache::kQuicCompressedCertsCacheSize),
server_id_(kServerHostname, kServerPort, PRIVACY_MODE_DISABLED),
client_crypto_config_(CryptoTestUtils::ProofVerifierForTesting()) {
- FLAGS_enable_quic_stateless_reject_support = false;
- server_crypto_config_.set_strike_register_no_startup_period();
+ FLAGS_quic_reloadable_flag_enable_quic_stateless_reject_support = false;
}
- void Initialize() {
- InitializeServer();
-
- if (AsyncStrikeRegisterVerification()) {
- QuicCryptoServerConfigPeer peer(&server_crypto_config_);
- strike_register_client_ = new DelayedVerifyStrikeRegisterClient(
- 10000, // strike_register_max_entries
- static_cast<uint32_t>(
- server_connection_->clock()->WallNow().ToUNIXSeconds()),
- 60, // strike_register_window_secs
- peer.GetPrimaryConfig()->orbit,
- StrikeRegister::NO_STARTUP_PERIOD_NEEDED);
- strike_register_client_->StartDelayingVerification();
- server_crypto_config_.SetStrikeRegisterClient(strike_register_client_);
- }
- }
+ void Initialize() { InitializeServer(); }
~QuicCryptoServerStreamTest() override {
// Ensure that anything that might reference |helpers_| is destroyed before
@@ -101,8 +87,8 @@ class QuicCryptoServerStreamTest : public ::testing::TestWithParam<bool> {
// called multiple times.
void InitializeServer() {
TestQuicSpdyServerSession* server_session = nullptr;
- helpers_.push_back(base::MakeUnique<MockQuicConnectionHelper>());
- alarm_factories_.push_back(base::MakeUnique<MockAlarmFactory>());
+ helpers_.push_back(QuicMakeUnique<MockQuicConnectionHelper>());
+ alarm_factories_.push_back(QuicMakeUnique<MockAlarmFactory>());
CreateServerSessionForTest(
server_id_, QuicTime::Delta::FromSeconds(100000), supported_versions_,
helpers_.back().get(), alarm_factories_.back().get(),
@@ -129,8 +115,8 @@ class QuicCryptoServerStreamTest : public ::testing::TestWithParam<bool> {
// testing. May be called multiple times.
void InitializeFakeClient(bool supports_stateless_rejects) {
TestQuicSpdyClientSession* client_session = nullptr;
- helpers_.push_back(base::MakeUnique<MockQuicConnectionHelper>());
- alarm_factories_.push_back(base::MakeUnique<MockAlarmFactory>());
+ helpers_.push_back(QuicMakeUnique<MockQuicConnectionHelper>());
+ alarm_factories_.push_back(QuicMakeUnique<MockAlarmFactory>());
CreateClientSessionForTest(
server_id_, supports_stateless_rejects,
QuicTime::Delta::FromSeconds(100000), supported_versions_,
@@ -140,13 +126,6 @@ class QuicCryptoServerStreamTest : public ::testing::TestWithParam<bool> {
client_session_.reset(client_session);
}
- bool AsyncStrikeRegisterVerification() {
- if (server_connection_->version() > QUIC_VERSION_32) {
- return false;
- }
- return GetParam();
- }
-
void ConstructHandshakeMessage() {
CryptoFramer framer;
message_data_.reset(framer.ConstructHandshakeMessage(message_));
@@ -196,7 +175,6 @@ class QuicCryptoServerStreamTest : public ::testing::TestWithParam<bool> {
CryptoHandshakeMessage message_;
std::unique_ptr<QuicData> message_data_;
CryptoTestUtils::FakeClientOptions client_options_;
- DelayedVerifyStrikeRegisterClient* strike_register_client_;
// Which QUIC versions the client and server support.
QuicVersionVector supported_versions_ = AllSupportedVersions();
@@ -249,7 +227,7 @@ TEST_P(QuicCryptoServerStreamTest, ForwardSecureAfterCHLO) {
}
TEST_P(QuicCryptoServerStreamTest, StatelessRejectAfterCHLO) {
- FLAGS_enable_quic_stateless_reject_support = true;
+ FLAGS_quic_reloadable_flag_enable_quic_stateless_reject_support = true;
Initialize();
@@ -283,7 +261,7 @@ TEST_P(QuicCryptoServerStreamTest, StatelessRejectAfterCHLO) {
}
TEST_P(QuicCryptoServerStreamTest, ConnectedAfterStatelessHandshake) {
- FLAGS_enable_quic_stateless_reject_support = true;
+ FLAGS_quic_reloadable_flag_enable_quic_stateless_reject_support = true;
Initialize();
@@ -314,7 +292,6 @@ TEST_P(QuicCryptoServerStreamTest, ConnectedAfterStatelessHandshake) {
InitializeServer();
InitializeFakeClient(/* supports_stateless_rejects= */ true);
-
// In the stateless case, the second handshake contains a server-nonce, so the
// AsyncStrikeRegisterVerification() case will still succeed (unlike a 0-RTT
// handshake).
@@ -328,7 +305,7 @@ TEST_P(QuicCryptoServerStreamTest, ConnectedAfterStatelessHandshake) {
}
TEST_P(QuicCryptoServerStreamTest, NoStatelessRejectIfNoClientSupport) {
- FLAGS_enable_quic_stateless_reject_support = true;
+ FLAGS_quic_reloadable_flag_enable_quic_stateless_reject_support = true;
Initialize();
@@ -359,45 +336,14 @@ TEST_P(QuicCryptoServerStreamTest, ZeroRTT) {
AdvanceHandshakeWithFakeClient();
// Now do another handshake, hopefully in 0-RTT.
- DVLOG(1) << "Resetting for 0-RTT handshake attempt";
+ QUIC_LOG(INFO) << "Resetting for 0-RTT handshake attempt";
InitializeFakeClient(/* supports_stateless_rejects= */ false);
InitializeServer();
client_stream()->CryptoConnect();
- if (AsyncStrikeRegisterVerification()) {
- EXPECT_FALSE(client_stream()->handshake_confirmed());
- EXPECT_FALSE(server_stream()->handshake_confirmed());
-
- // Advance the handshake. Expect that the server will be stuck waiting for
- // client nonce verification to complete.
- std::pair<size_t, size_t> messages_moved =
- CryptoTestUtils::AdvanceHandshake(client_connection_, client_stream(),
- 0, server_connection_,
- server_stream(), 0);
- EXPECT_EQ(1u, messages_moved.first);
- EXPECT_EQ(0u, messages_moved.second);
- EXPECT_EQ(1, strike_register_client_->PendingVerifications());
- EXPECT_FALSE(client_stream()->handshake_confirmed());
- EXPECT_FALSE(server_stream()->handshake_confirmed());
-
- // The server handshake completes once the nonce verification completes.
- strike_register_client_->RunPendingVerifications();
- EXPECT_FALSE(client_stream()->handshake_confirmed());
- EXPECT_TRUE(server_stream()->handshake_confirmed());
-
- messages_moved = CryptoTestUtils::AdvanceHandshake(
- client_connection_, client_stream(), messages_moved.first,
- server_connection_, server_stream(), messages_moved.second);
- EXPECT_EQ(1u, messages_moved.first);
- EXPECT_EQ(1u, messages_moved.second);
- EXPECT_TRUE(client_stream()->handshake_confirmed());
- EXPECT_TRUE(server_stream()->handshake_confirmed());
- } else {
- CryptoTestUtils::CommunicateHandshakeMessages(
- client_connection_, client_stream(), server_connection_,
- server_stream());
- }
+ CryptoTestUtils::CommunicateHandshakeMessages(
+ client_connection_, client_stream(), server_connection_, server_stream());
EXPECT_EQ(1, client_stream()->num_sent_client_hellos());
}
@@ -472,6 +418,12 @@ TEST_P(QuicCryptoServerStreamTest, OnlySendSCUPAfterHandshakeComplete) {
}
TEST_P(QuicCryptoServerStreamTest, SendSCUPAfterHandshakeComplete) {
+ // Do not send MAX_HEADER_LIST_SIZE SETTING frame.
+ // TODO(fayang): This SETTING frame cannot be decrypted and
+ // CryptoTestUtils::MovePackets stops processing parsing following packets.
+ // Actually, crypto stream test should use QuicSession instead of
+ // QuicSpdySession (b/32366134).
+ FLAGS_quic_reloadable_flag_quic_send_max_header_list_size = false;
Initialize();
InitializeFakeClient(/* supports_stateless_rejects= */ false);
@@ -533,74 +485,6 @@ TEST_P(QuicCryptoServerStreamTest, NoTokenBindingWithoutClientSupport) {
EXPECT_TRUE(server_stream()->handshake_confirmed());
}
-TEST_P(QuicCryptoServerStreamTest, CancelRPCBeforeVerificationCompletes) {
- FLAGS_quic_require_handshake_confirmation_pre33 = false;
- // Tests that the client can close the connection while the remote strike
- // register verification RPC is still pending.
-
- // Set version to QUIC_VERSION_32 as QUIC_VERSION_33 and later don't support
- // asynchronous strike register RPCs.
- supported_versions_ = {QUIC_VERSION_32};
- Initialize();
- if (!AsyncStrikeRegisterVerification()) {
- return;
- }
- InitializeFakeClient(/* supports_stateless_rejects= */ false);
-
- // Do a first handshake in order to prime the client config with the server's
- // information.
- AdvanceHandshakeWithFakeClient();
-
- // Now start another handshake, this time the server will attempt to verify
- // the client's nonce with the strike registers.
- InitializeFakeClient(/* supports_stateless_rejects= */ false);
- InitializeServer();
- client_stream()->CryptoConnect();
- EXPECT_FALSE(client_stream()->handshake_confirmed());
- EXPECT_FALSE(server_stream()->handshake_confirmed());
-
- // Advance the handshake. Expect that the server will be stuck waiting for
- // client nonce verification to complete.
- CryptoTestUtils::AdvanceHandshake(client_connection_, client_stream(), 0,
- server_connection_, server_stream(), 0);
- EXPECT_EQ(1, strike_register_client_->PendingVerifications());
- EXPECT_FALSE(client_stream()->handshake_confirmed());
- EXPECT_FALSE(server_stream()->handshake_confirmed());
-
- // While waiting for the asynchronous verification to complete, the client
- // decides to close the connection.
- server_session_->connection()->CloseConnection(
- QUIC_NO_ERROR, "", ConnectionCloseBehavior::SILENT_CLOSE);
-
- // The outstanding nonce verification RPC now completes.
- strike_register_client_->RunPendingVerifications();
-}
-
-class FailingProofSource : public ProofSource {
- public:
- bool GetProof(const IPAddress& server_ip,
- const string& hostname,
- const string& server_config,
- QuicVersion quic_version,
- StringPiece chlo_hash,
- const QuicTagVector& connection_options,
- scoped_refptr<ProofSource::Chain>* out_chain,
- string* out_signature,
- string* out_leaf_cert_sct) override {
- return false;
- }
-
- void GetProof(const IPAddress& server_ip,
- const string& hostname,
- const string& server_config,
- QuicVersion quic_version,
- StringPiece chlo_hash,
- const QuicTagVector& connection_options,
- std::unique_ptr<Callback> callback) override {
- callback->Run(false, nullptr, "", "", nullptr);
- }
-};
-
class QuicCryptoServerStreamTestWithFailingProofSource
: public QuicCryptoServerStreamTest {
public:
diff --git a/chromium/net/quic/core/quic_crypto_stream.cc b/chromium/net/quic/core/quic_crypto_stream.cc
index 66209fd6c8b..814b2683a0c 100644
--- a/chromium/net/quic/core/quic_crypto_stream.cc
+++ b/chromium/net/quic/core/quic_crypto_stream.cc
@@ -13,6 +13,7 @@
#include "net/quic/core/quic_flags.h"
#include "net/quic/core/quic_session.h"
#include "net/quic/core/quic_utils.h"
+#include "net/quic/platform/api/quic_logging.h"
using std::string;
using base::StringPiece;
@@ -48,13 +49,13 @@ QuicByteCount QuicCryptoStream::CryptoMessageFramingOverhead(
}
void QuicCryptoStream::OnError(CryptoFramer* framer) {
- DLOG(WARNING) << "Error processing crypto data: "
- << QuicUtils::ErrorToString(framer->error());
+ QUIC_DLOG(WARNING) << "Error processing crypto data: "
+ << QuicErrorCodeToString(framer->error());
}
void QuicCryptoStream::OnHandshakeMessage(
const CryptoHandshakeMessage& message) {
- DVLOG(1) << ENDPOINT << "Received " << message.DebugString();
+ QUIC_DVLOG(1) << ENDPOINT << "Received " << message.DebugString();
session()->OnCryptoHandshakeMessageReceived(message);
}
@@ -73,7 +74,7 @@ void QuicCryptoStream::OnDataAvailable() {
}
sequencer()->MarkConsumed(iov.iov_len);
if (handshake_confirmed_ && crypto_framer_.InputBytesRemaining() == 0 &&
- FLAGS_quic_release_crypto_stream_buffer) {
+ FLAGS_quic_reloadable_flag_quic_release_crypto_stream_buffer) {
// If the handshake is complete and the current message has been fully
// processed then no more handshake messages are likely to arrive soon
// so release the memory in the stream sequencer.
@@ -84,7 +85,7 @@ void QuicCryptoStream::OnDataAvailable() {
void QuicCryptoStream::SendHandshakeMessage(
const CryptoHandshakeMessage& message) {
- DVLOG(1) << ENDPOINT << "Sending " << message.DebugString();
+ QUIC_DVLOG(1) << ENDPOINT << "Sending " << message.DebugString();
session()->connection()->NeuterUnencryptedPackets();
session()->OnCryptoHandshakeMessageSent(message);
const QuicData& data = message.GetSerialized();
@@ -96,8 +97,8 @@ bool QuicCryptoStream::ExportKeyingMaterial(StringPiece label,
size_t result_len,
string* result) const {
if (!handshake_confirmed()) {
- DLOG(ERROR) << "ExportKeyingMaterial was called before forward-secure"
- << "encryption was established.";
+ QUIC_DLOG(ERROR) << "ExportKeyingMaterial was called before forward-secure"
+ << "encryption was established.";
return false;
}
return CryptoUtils::ExportKeyingMaterial(
diff --git a/chromium/net/quic/core/quic_crypto_stream.h b/chromium/net/quic/core/quic_crypto_stream.h
index 185165a9be1..05aa23c5933 100644
--- a/chromium/net/quic/core/quic_crypto_stream.h
+++ b/chromium/net/quic/core/quic_crypto_stream.h
@@ -2,18 +2,18 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#ifndef NET_QUIC_QUIC_CRYPTO_STREAM_H_
-#define NET_QUIC_QUIC_CRYPTO_STREAM_H_
+#ifndef NET_QUIC_CORE_QUIC_CRYPTO_STREAM_H_
+#define NET_QUIC_CORE_QUIC_CRYPTO_STREAM_H_
#include <stddef.h>
#include "base/macros.h"
-#include "net/base/net_export.h"
#include "net/quic/core/crypto/crypto_framer.h"
#include "net/quic/core/crypto/crypto_utils.h"
#include "net/quic/core/quic_config.h"
-#include "net/quic/core/quic_protocol.h"
+#include "net/quic/core/quic_packets.h"
#include "net/quic/core/quic_stream.h"
+#include "net/quic/platform/api/quic_export.h"
namespace net {
@@ -30,7 +30,7 @@ class QuicSession;
//
// For more details:
// https://docs.google.com/document/d/1g5nIXAIkN_Y-7XJW5K45IblHd_L2f5LTaDUDwvZ5L6g/edit?usp=sharing
-class NET_EXPORT_PRIVATE QuicCryptoStream
+class QUIC_EXPORT_PRIVATE QuicCryptoStream
: public QuicStream,
public CryptoFramerVisitorInterface {
public:
@@ -81,7 +81,8 @@ class NET_EXPORT_PRIVATE QuicCryptoStream
bool encryption_established_;
bool handshake_confirmed_;
- scoped_refptr<QuicCryptoNegotiatedParameters> crypto_negotiated_params_;
+ QuicReferenceCountedPointer<QuicCryptoNegotiatedParameters>
+ crypto_negotiated_params_;
private:
CryptoFramer crypto_framer_;
@@ -91,4 +92,4 @@ class NET_EXPORT_PRIVATE QuicCryptoStream
} // namespace net
-#endif // NET_QUIC_QUIC_CRYPTO_STREAM_H_
+#endif // NET_QUIC_CORE_QUIC_CRYPTO_STREAM_H_
diff --git a/chromium/net/quic/core/quic_crypto_stream_test.cc b/chromium/net/quic/core/quic_crypto_stream_test.cc
index 3fdf56531ea..5ef4aa965b1 100644
--- a/chromium/net/quic/core/quic_crypto_stream_test.cc
+++ b/chromium/net/quic/core/quic_crypto_stream_test.cc
@@ -12,6 +12,7 @@
#include "base/macros.h"
#include "net/quic/core/crypto/crypto_handshake.h"
#include "net/quic/core/crypto/crypto_protocol.h"
+#include "net/quic/platform/api/quic_socket_address.h"
#include "net/quic/test_tools/crypto_test_utils.h"
#include "net/quic/test_tools/quic_stream_peer.h"
#include "net/quic/test_tools/quic_test_utils.h"
diff --git a/chromium/net/quic/core/quic_data_reader.cc b/chromium/net/quic/core/quic_data_reader.cc
index 72185cdeb41..855c71ab73b 100644
--- a/chromium/net/quic/core/quic_data_reader.cc
+++ b/chromium/net/quic/core/quic_data_reader.cc
@@ -5,7 +5,7 @@
#include "net/quic/core/quic_data_reader.h"
#include "net/base/int128.h"
-#include "net/quic/core/quic_protocol.h"
+#include "net/quic/core/quic_packets.h"
using base::StringPiece;
@@ -78,7 +78,7 @@ bool QuicDataReader::ReadStringPiece(StringPiece* result, size_t size) {
}
// Set result.
- result->set(data_ + pos_, size);
+ *result = StringPiece(data_ + pos_, size);
// Iterate.
pos_ += size;
diff --git a/chromium/net/quic/core/quic_data_reader.h b/chromium/net/quic/core/quic_data_reader.h
index 970e5b208f3..b1d8444e6f0 100644
--- a/chromium/net/quic/core/quic_data_reader.h
+++ b/chromium/net/quic/core/quic_data_reader.h
@@ -2,18 +2,16 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#ifndef NET_QUIC_QUIC_DATA_READER_H_
-#define NET_QUIC_QUIC_DATA_READER_H_
-
-#include <stddef.h>
-#include <stdint.h>
+#ifndef NET_QUIC_CORE_QUIC_DATA_READER_H_
+#define NET_QUIC_CORE_QUIC_DATA_READER_H_
#include <cstddef>
+#include <cstdint>
#include "base/macros.h"
#include "base/strings/string_piece.h"
#include "net/base/int128.h"
-#include "net/base/net_export.h"
+#include "net/quic/platform/api/quic_export.h"
namespace net {
@@ -31,7 +29,7 @@ namespace net {
// trusted and it is up to the caller to throw away the failed instance and
// handle the error as appropriate. None of the Read*() methods should ever be
// called after failure, as they will also fail immediately.
-class NET_EXPORT_PRIVATE QuicDataReader {
+class QUIC_EXPORT_PRIVATE QuicDataReader {
public:
// Caller must provide an underlying buffer to work on.
QuicDataReader(const char* data, const size_t len);
@@ -125,4 +123,4 @@ class NET_EXPORT_PRIVATE QuicDataReader {
} // namespace net
-#endif // NET_QUIC_QUIC_DATA_READER_H_
+#endif // NET_QUIC_CORE_QUIC_DATA_READER_H_
diff --git a/chromium/net/quic/core/quic_data_writer.cc b/chromium/net/quic/core/quic_data_writer.cc
index 69835533308..f890eb2393c 100644
--- a/chromium/net/quic/core/quic_data_writer.cc
+++ b/chromium/net/quic/core/quic_data_writer.cc
@@ -4,7 +4,6 @@
#include "net/quic/core/quic_data_writer.h"
-#include <stdint.h>
#include <algorithm>
#include <limits>
diff --git a/chromium/net/quic/core/quic_data_writer.h b/chromium/net/quic/core/quic_data_writer.h
index 8dcc74a0e9f..d1d511a3379 100644
--- a/chromium/net/quic/core/quic_data_writer.h
+++ b/chromium/net/quic/core/quic_data_writer.h
@@ -2,21 +2,18 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#ifndef NET_QUIC_QUIC_DATA_WRITER_H_
-#define NET_QUIC_QUIC_DATA_WRITER_H_
-
-#include <stddef.h>
-#include <stdint.h>
+#ifndef NET_QUIC_CORE_QUIC_DATA_WRITER_H_
+#define NET_QUIC_CORE_QUIC_DATA_WRITER_H_
#include <cstddef>
+#include <cstdint>
#include <string>
-#include "base/logging.h"
#include "base/macros.h"
#include "base/strings/string_piece.h"
#include "net/base/int128.h"
-#include "net/base/net_export.h"
-#include "net/quic/core/quic_protocol.h"
+#include "net/quic/core/quic_packets.h"
+#include "net/quic/platform/api/quic_export.h"
namespace net {
@@ -25,7 +22,7 @@ namespace net {
// The QuicDataWriter supports appending primitive values (int, string, etc)
// to a frame instance. The internal memory buffer is exposed as the "data"
// of the QuicDataWriter.
-class NET_EXPORT_PRIVATE QuicDataWriter {
+class QUIC_EXPORT_PRIVATE QuicDataWriter {
public:
// Creates a QuicDataWriter where |buffer| is not owned.
QuicDataWriter(size_t size, char* buffer);
@@ -73,4 +70,4 @@ class NET_EXPORT_PRIVATE QuicDataWriter {
} // namespace net
-#endif // NET_QUIC_QUIC_DATA_WRITER_H_
+#endif // NET_QUIC_CORE_QUIC_DATA_WRITER_H_
diff --git a/chromium/net/quic/core/quic_data_writer_test.cc b/chromium/net/quic/core/quic_data_writer_test.cc
index bb3cfaf5e14..fcd1a577e6e 100644
--- a/chromium/net/quic/core/quic_data_writer_test.cc
+++ b/chromium/net/quic/core/quic_data_writer_test.cc
@@ -4,12 +4,9 @@
#include "net/quic/core/quic_data_writer.h"
-#include <stdint.h>
-
-#include <memory>
+#include <cstdint>
#include "net/quic/core/quic_data_reader.h"
-#include "net/test/gtest_util.h"
#include "testing/gtest/include/gtest/gtest.h"
namespace net {
diff --git a/chromium/net/quic/core/quic_error_codes.cc b/chromium/net/quic/core/quic_error_codes.cc
new file mode 100644
index 00000000000..fa360963b69
--- /dev/null
+++ b/chromium/net/quic/core/quic_error_codes.cc
@@ -0,0 +1,144 @@
+// Copyright (c) 2012 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.
+
+#include "net/quic/core/quic_error_codes.h"
+
+namespace net {
+
+#define RETURN_STRING_LITERAL(x) \
+ case x: \
+ return #x;
+
+const char* QuicRstStreamErrorCodeToString(QuicRstStreamErrorCode error) {
+ switch (error) {
+ RETURN_STRING_LITERAL(QUIC_STREAM_NO_ERROR);
+ RETURN_STRING_LITERAL(QUIC_STREAM_CONNECTION_ERROR);
+ RETURN_STRING_LITERAL(QUIC_ERROR_PROCESSING_STREAM);
+ RETURN_STRING_LITERAL(QUIC_MULTIPLE_TERMINATION_OFFSETS);
+ RETURN_STRING_LITERAL(QUIC_BAD_APPLICATION_PAYLOAD);
+ RETURN_STRING_LITERAL(QUIC_STREAM_PEER_GOING_AWAY);
+ RETURN_STRING_LITERAL(QUIC_STREAM_CANCELLED);
+ RETURN_STRING_LITERAL(QUIC_RST_ACKNOWLEDGEMENT);
+ RETURN_STRING_LITERAL(QUIC_REFUSED_STREAM);
+ RETURN_STRING_LITERAL(QUIC_STREAM_LAST_ERROR);
+ RETURN_STRING_LITERAL(QUIC_INVALID_PROMISE_URL);
+ RETURN_STRING_LITERAL(QUIC_UNAUTHORIZED_PROMISE_URL);
+ RETURN_STRING_LITERAL(QUIC_DUPLICATE_PROMISE_URL);
+ RETURN_STRING_LITERAL(QUIC_PROMISE_VARY_MISMATCH);
+ RETURN_STRING_LITERAL(QUIC_INVALID_PROMISE_METHOD);
+ RETURN_STRING_LITERAL(QUIC_PUSH_STREAM_TIMED_OUT);
+ RETURN_STRING_LITERAL(QUIC_HEADERS_TOO_LARGE);
+ }
+ // Return a default value so that we return this when |error| doesn't match
+ // any of the QuicRstStreamErrorCodes. This can happen when the RstStream
+ // frame sent by the peer (attacker) has invalid error code.
+ return "INVALID_RST_STREAM_ERROR_CODE";
+}
+
+const char* QuicErrorCodeToString(QuicErrorCode error) {
+ switch (error) {
+ RETURN_STRING_LITERAL(QUIC_NO_ERROR);
+ RETURN_STRING_LITERAL(QUIC_INTERNAL_ERROR);
+ RETURN_STRING_LITERAL(QUIC_STREAM_DATA_AFTER_TERMINATION);
+ RETURN_STRING_LITERAL(QUIC_INVALID_PACKET_HEADER);
+ RETURN_STRING_LITERAL(QUIC_INVALID_FRAME_DATA);
+ RETURN_STRING_LITERAL(QUIC_MISSING_PAYLOAD);
+ RETURN_STRING_LITERAL(QUIC_INVALID_FEC_DATA);
+ RETURN_STRING_LITERAL(QUIC_INVALID_STREAM_DATA);
+ RETURN_STRING_LITERAL(QUIC_OVERLAPPING_STREAM_DATA);
+ RETURN_STRING_LITERAL(QUIC_UNENCRYPTED_STREAM_DATA);
+ RETURN_STRING_LITERAL(QUIC_INVALID_RST_STREAM_DATA);
+ RETURN_STRING_LITERAL(QUIC_INVALID_CONNECTION_CLOSE_DATA);
+ RETURN_STRING_LITERAL(QUIC_INVALID_GOAWAY_DATA);
+ RETURN_STRING_LITERAL(QUIC_INVALID_WINDOW_UPDATE_DATA);
+ RETURN_STRING_LITERAL(QUIC_INVALID_BLOCKED_DATA);
+ RETURN_STRING_LITERAL(QUIC_INVALID_STOP_WAITING_DATA);
+ RETURN_STRING_LITERAL(QUIC_INVALID_PATH_CLOSE_DATA);
+ RETURN_STRING_LITERAL(QUIC_INVALID_ACK_DATA);
+ RETURN_STRING_LITERAL(QUIC_INVALID_VERSION_NEGOTIATION_PACKET);
+ RETURN_STRING_LITERAL(QUIC_INVALID_PUBLIC_RST_PACKET);
+ RETURN_STRING_LITERAL(QUIC_DECRYPTION_FAILURE);
+ RETURN_STRING_LITERAL(QUIC_ENCRYPTION_FAILURE);
+ RETURN_STRING_LITERAL(QUIC_PACKET_TOO_LARGE);
+ RETURN_STRING_LITERAL(QUIC_PEER_GOING_AWAY);
+ RETURN_STRING_LITERAL(QUIC_HANDSHAKE_FAILED);
+ RETURN_STRING_LITERAL(QUIC_CRYPTO_TAGS_OUT_OF_ORDER);
+ RETURN_STRING_LITERAL(QUIC_CRYPTO_TOO_MANY_ENTRIES);
+ RETURN_STRING_LITERAL(QUIC_CRYPTO_TOO_MANY_REJECTS);
+ RETURN_STRING_LITERAL(QUIC_CRYPTO_INVALID_VALUE_LENGTH)
+ RETURN_STRING_LITERAL(QUIC_CRYPTO_MESSAGE_AFTER_HANDSHAKE_COMPLETE);
+ RETURN_STRING_LITERAL(QUIC_CRYPTO_INTERNAL_ERROR);
+ RETURN_STRING_LITERAL(QUIC_CRYPTO_VERSION_NOT_SUPPORTED);
+ RETURN_STRING_LITERAL(QUIC_CRYPTO_HANDSHAKE_STATELESS_REJECT);
+ RETURN_STRING_LITERAL(QUIC_CRYPTO_NO_SUPPORT);
+ RETURN_STRING_LITERAL(QUIC_INVALID_CRYPTO_MESSAGE_TYPE);
+ RETURN_STRING_LITERAL(QUIC_INVALID_CRYPTO_MESSAGE_PARAMETER);
+ RETURN_STRING_LITERAL(QUIC_CRYPTO_MESSAGE_PARAMETER_NOT_FOUND);
+ RETURN_STRING_LITERAL(QUIC_CRYPTO_MESSAGE_PARAMETER_NO_OVERLAP);
+ RETURN_STRING_LITERAL(QUIC_CRYPTO_MESSAGE_INDEX_NOT_FOUND);
+ RETURN_STRING_LITERAL(QUIC_UNSUPPORTED_PROOF_DEMAND);
+ RETURN_STRING_LITERAL(QUIC_INVALID_STREAM_ID);
+ RETURN_STRING_LITERAL(QUIC_INVALID_PRIORITY);
+ RETURN_STRING_LITERAL(QUIC_TOO_MANY_OPEN_STREAMS);
+ RETURN_STRING_LITERAL(QUIC_PUBLIC_RESET);
+ RETURN_STRING_LITERAL(QUIC_INVALID_VERSION);
+ RETURN_STRING_LITERAL(QUIC_INVALID_HEADER_ID);
+ RETURN_STRING_LITERAL(QUIC_INVALID_NEGOTIATED_VALUE);
+ RETURN_STRING_LITERAL(QUIC_DECOMPRESSION_FAILURE);
+ RETURN_STRING_LITERAL(QUIC_NETWORK_IDLE_TIMEOUT);
+ RETURN_STRING_LITERAL(QUIC_HANDSHAKE_TIMEOUT);
+ RETURN_STRING_LITERAL(QUIC_ERROR_MIGRATING_ADDRESS);
+ RETURN_STRING_LITERAL(QUIC_ERROR_MIGRATING_PORT);
+ RETURN_STRING_LITERAL(QUIC_PACKET_WRITE_ERROR);
+ RETURN_STRING_LITERAL(QUIC_PACKET_READ_ERROR);
+ RETURN_STRING_LITERAL(QUIC_EMPTY_STREAM_FRAME_NO_FIN);
+ RETURN_STRING_LITERAL(QUIC_INVALID_HEADERS_STREAM_DATA);
+ RETURN_STRING_LITERAL(QUIC_FLOW_CONTROL_RECEIVED_TOO_MUCH_DATA);
+ RETURN_STRING_LITERAL(QUIC_FLOW_CONTROL_SENT_TOO_MUCH_DATA);
+ RETURN_STRING_LITERAL(QUIC_FLOW_CONTROL_INVALID_WINDOW);
+ RETURN_STRING_LITERAL(QUIC_CONNECTION_IP_POOLED);
+ RETURN_STRING_LITERAL(QUIC_PROOF_INVALID);
+ RETURN_STRING_LITERAL(QUIC_CRYPTO_DUPLICATE_TAG);
+ RETURN_STRING_LITERAL(QUIC_CRYPTO_ENCRYPTION_LEVEL_INCORRECT);
+ RETURN_STRING_LITERAL(QUIC_CRYPTO_SERVER_CONFIG_EXPIRED);
+ RETURN_STRING_LITERAL(QUIC_INVALID_CHANNEL_ID_SIGNATURE);
+ RETURN_STRING_LITERAL(QUIC_CRYPTO_SYMMETRIC_KEY_SETUP_FAILED);
+ RETURN_STRING_LITERAL(QUIC_CRYPTO_MESSAGE_WHILE_VALIDATING_CLIENT_HELLO);
+ RETURN_STRING_LITERAL(QUIC_CRYPTO_UPDATE_BEFORE_HANDSHAKE_COMPLETE);
+ RETURN_STRING_LITERAL(QUIC_VERSION_NEGOTIATION_MISMATCH);
+ RETURN_STRING_LITERAL(QUIC_TOO_MANY_OUTSTANDING_SENT_PACKETS);
+ RETURN_STRING_LITERAL(QUIC_TOO_MANY_OUTSTANDING_RECEIVED_PACKETS);
+ RETURN_STRING_LITERAL(QUIC_CONNECTION_CANCELLED);
+ RETURN_STRING_LITERAL(QUIC_BAD_PACKET_LOSS_RATE);
+ RETURN_STRING_LITERAL(QUIC_PUBLIC_RESETS_POST_HANDSHAKE);
+ RETURN_STRING_LITERAL(QUIC_TIMEOUTS_WITH_OPEN_STREAMS);
+ RETURN_STRING_LITERAL(QUIC_FAILED_TO_SERIALIZE_PACKET);
+ RETURN_STRING_LITERAL(QUIC_TOO_MANY_AVAILABLE_STREAMS);
+ RETURN_STRING_LITERAL(QUIC_UNENCRYPTED_FEC_DATA);
+ RETURN_STRING_LITERAL(QUIC_BAD_MULTIPATH_FLAG);
+ RETURN_STRING_LITERAL(QUIC_IP_ADDRESS_CHANGED);
+ RETURN_STRING_LITERAL(QUIC_CONNECTION_MIGRATION_NO_MIGRATABLE_STREAMS);
+ RETURN_STRING_LITERAL(QUIC_CONNECTION_MIGRATION_TOO_MANY_CHANGES);
+ RETURN_STRING_LITERAL(QUIC_CONNECTION_MIGRATION_NO_NEW_NETWORK);
+ RETURN_STRING_LITERAL(QUIC_CONNECTION_MIGRATION_NON_MIGRATABLE_STREAM);
+ RETURN_STRING_LITERAL(QUIC_TOO_MANY_RTOS);
+ RETURN_STRING_LITERAL(QUIC_ATTEMPT_TO_SEND_UNENCRYPTED_STREAM_DATA);
+ RETURN_STRING_LITERAL(QUIC_MAYBE_CORRUPTED_MEMORY);
+ RETURN_STRING_LITERAL(QUIC_CRYPTO_CHLO_TOO_LARGE);
+ RETURN_STRING_LITERAL(QUIC_MULTIPATH_PATH_DOES_NOT_EXIST);
+ RETURN_STRING_LITERAL(QUIC_MULTIPATH_PATH_NOT_ACTIVE);
+ RETURN_STRING_LITERAL(QUIC_TOO_MANY_FRAME_GAPS);
+ RETURN_STRING_LITERAL(QUIC_STREAM_SEQUENCER_INVALID_STATE);
+ RETURN_STRING_LITERAL(QUIC_TOO_MANY_SESSIONS_ON_SERVER);
+ RETURN_STRING_LITERAL(QUIC_LAST_ERROR);
+ // Intentionally have no default case, so we'll break the build
+ // if we add errors and don't put them here.
+ }
+ // Return a default value so that we return this when |error| doesn't match
+ // any of the QuicErrorCodes. This can happen when the ConnectionClose
+ // frame sent by the peer (attacker) has invalid error code.
+ return "INVALID_ERROR_CODE";
+}
+
+} // namespace net
diff --git a/chromium/net/quic/core/quic_error_codes.h b/chromium/net/quic/core/quic_error_codes.h
new file mode 100644
index 00000000000..7e341f186db
--- /dev/null
+++ b/chromium/net/quic/core/quic_error_codes.h
@@ -0,0 +1,293 @@
+// Copyright (c) 2012 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.
+
+#ifndef NET_QUIC_CORE_QUIC_ERROR_CODES_H_
+#define NET_QUIC_CORE_QUIC_ERROR_CODES_H_
+
+#include <cstdint>
+#include <limits>
+
+#include "net/quic/platform/api/quic_export.h"
+
+namespace net {
+
+enum QuicRstStreamErrorCode {
+ // Complete response has been sent, sending a RST to ask the other endpoint
+ // to stop sending request data without discarding the response.
+ QUIC_STREAM_NO_ERROR = 0,
+
+ // There was some error which halted stream processing.
+ QUIC_ERROR_PROCESSING_STREAM,
+ // We got two fin or reset offsets which did not match.
+ QUIC_MULTIPLE_TERMINATION_OFFSETS,
+ // We got bad payload and can not respond to it at the protocol level.
+ QUIC_BAD_APPLICATION_PAYLOAD,
+ // Stream closed due to connection error. No reset frame is sent when this
+ // happens.
+ QUIC_STREAM_CONNECTION_ERROR,
+ // GoAway frame sent. No more stream can be created.
+ QUIC_STREAM_PEER_GOING_AWAY,
+ // The stream has been cancelled.
+ QUIC_STREAM_CANCELLED,
+ // Closing stream locally, sending a RST to allow for proper flow control
+ // accounting. Sent in response to a RST from the peer.
+ QUIC_RST_ACKNOWLEDGEMENT,
+ // Receiver refused to create the stream (because its limit on open streams
+ // has been reached). The sender should retry the request later (using
+ // another stream).
+ QUIC_REFUSED_STREAM,
+ // Invalid URL in PUSH_PROMISE request header.
+ QUIC_INVALID_PROMISE_URL,
+ // Server is not authoritative for this URL.
+ QUIC_UNAUTHORIZED_PROMISE_URL,
+ // Can't have more than one active PUSH_PROMISE per URL.
+ QUIC_DUPLICATE_PROMISE_URL,
+ // Vary check failed.
+ QUIC_PROMISE_VARY_MISMATCH,
+ // Only GET and HEAD methods allowed.
+ QUIC_INVALID_PROMISE_METHOD,
+ // The push stream is unclaimed and timed out.
+ QUIC_PUSH_STREAM_TIMED_OUT,
+ // Received headers were too large.
+ QUIC_HEADERS_TOO_LARGE,
+ // No error. Used as bound while iterating.
+ QUIC_STREAM_LAST_ERROR,
+};
+// QuicRstStreamErrorCode is encoded as a single octet on-the-wire.
+static_assert(static_cast<int>(QUIC_STREAM_LAST_ERROR) <=
+ std::numeric_limits<uint8_t>::max(),
+ "QuicRstStreamErrorCode exceeds single octet");
+
+// These values must remain stable as they are uploaded to UMA histograms.
+// To add a new error code, use the current value of QUIC_LAST_ERROR and
+// increment QUIC_LAST_ERROR.
+enum QuicErrorCode {
+ QUIC_NO_ERROR = 0,
+
+ // Connection has reached an invalid state.
+ QUIC_INTERNAL_ERROR = 1,
+ // There were data frames after the a fin or reset.
+ QUIC_STREAM_DATA_AFTER_TERMINATION = 2,
+ // Control frame is malformed.
+ QUIC_INVALID_PACKET_HEADER = 3,
+ // Frame data is malformed.
+ QUIC_INVALID_FRAME_DATA = 4,
+ // The packet contained no payload.
+ QUIC_MISSING_PAYLOAD = 48,
+ // FEC data is malformed.
+ QUIC_INVALID_FEC_DATA = 5,
+ // STREAM frame data is malformed.
+ QUIC_INVALID_STREAM_DATA = 46,
+ // STREAM frame data overlaps with buffered data.
+ QUIC_OVERLAPPING_STREAM_DATA = 87,
+ // Received STREAM frame data is not encrypted.
+ QUIC_UNENCRYPTED_STREAM_DATA = 61,
+ // Attempt to send unencrypted STREAM frame.
+ QUIC_ATTEMPT_TO_SEND_UNENCRYPTED_STREAM_DATA = 88,
+ // Received a frame which is likely the result of memory corruption.
+ QUIC_MAYBE_CORRUPTED_MEMORY = 89,
+ // FEC frame data is not encrypted.
+ QUIC_UNENCRYPTED_FEC_DATA = 77,
+ // RST_STREAM frame data is malformed.
+ QUIC_INVALID_RST_STREAM_DATA = 6,
+ // CONNECTION_CLOSE frame data is malformed.
+ QUIC_INVALID_CONNECTION_CLOSE_DATA = 7,
+ // GOAWAY frame data is malformed.
+ QUIC_INVALID_GOAWAY_DATA = 8,
+ // WINDOW_UPDATE frame data is malformed.
+ QUIC_INVALID_WINDOW_UPDATE_DATA = 57,
+ // BLOCKED frame data is malformed.
+ QUIC_INVALID_BLOCKED_DATA = 58,
+ // STOP_WAITING frame data is malformed.
+ QUIC_INVALID_STOP_WAITING_DATA = 60,
+ // PATH_CLOSE frame data is malformed.
+ QUIC_INVALID_PATH_CLOSE_DATA = 78,
+ // ACK frame data is malformed.
+ QUIC_INVALID_ACK_DATA = 9,
+
+ // Version negotiation packet is malformed.
+ QUIC_INVALID_VERSION_NEGOTIATION_PACKET = 10,
+ // Public RST packet is malformed.
+ QUIC_INVALID_PUBLIC_RST_PACKET = 11,
+ // There was an error decrypting.
+ QUIC_DECRYPTION_FAILURE = 12,
+ // There was an error encrypting.
+ QUIC_ENCRYPTION_FAILURE = 13,
+ // The packet exceeded kMaxPacketSize.
+ QUIC_PACKET_TOO_LARGE = 14,
+ // The peer is going away. May be a client or server.
+ QUIC_PEER_GOING_AWAY = 16,
+ // A stream ID was invalid.
+ QUIC_INVALID_STREAM_ID = 17,
+ // A priority was invalid.
+ QUIC_INVALID_PRIORITY = 49,
+ // Too many streams already open.
+ QUIC_TOO_MANY_OPEN_STREAMS = 18,
+ // The peer created too many available streams.
+ QUIC_TOO_MANY_AVAILABLE_STREAMS = 76,
+ // Received public reset for this connection.
+ QUIC_PUBLIC_RESET = 19,
+ // Invalid protocol version.
+ QUIC_INVALID_VERSION = 20,
+
+ // The Header ID for a stream was too far from the previous.
+ QUIC_INVALID_HEADER_ID = 22,
+ // Negotiable parameter received during handshake had invalid value.
+ QUIC_INVALID_NEGOTIATED_VALUE = 23,
+ // There was an error decompressing data.
+ QUIC_DECOMPRESSION_FAILURE = 24,
+ // The connection timed out due to no network activity.
+ QUIC_NETWORK_IDLE_TIMEOUT = 25,
+ // The connection timed out waiting for the handshake to complete.
+ QUIC_HANDSHAKE_TIMEOUT = 67,
+ // There was an error encountered migrating addresses.
+ QUIC_ERROR_MIGRATING_ADDRESS = 26,
+ // There was an error encountered migrating port only.
+ QUIC_ERROR_MIGRATING_PORT = 86,
+ // There was an error while writing to the socket.
+ QUIC_PACKET_WRITE_ERROR = 27,
+ // There was an error while reading from the socket.
+ QUIC_PACKET_READ_ERROR = 51,
+ // We received a STREAM_FRAME with no data and no fin flag set.
+ QUIC_EMPTY_STREAM_FRAME_NO_FIN = 50,
+ // We received invalid data on the headers stream.
+ QUIC_INVALID_HEADERS_STREAM_DATA = 56,
+ // The peer received too much data, violating flow control.
+ QUIC_FLOW_CONTROL_RECEIVED_TOO_MUCH_DATA = 59,
+ // The peer sent too much data, violating flow control.
+ QUIC_FLOW_CONTROL_SENT_TOO_MUCH_DATA = 63,
+ // The peer received an invalid flow control window.
+ QUIC_FLOW_CONTROL_INVALID_WINDOW = 64,
+ // The connection has been IP pooled into an existing connection.
+ QUIC_CONNECTION_IP_POOLED = 62,
+ // The connection has too many outstanding sent packets.
+ QUIC_TOO_MANY_OUTSTANDING_SENT_PACKETS = 68,
+ // The connection has too many outstanding received packets.
+ QUIC_TOO_MANY_OUTSTANDING_RECEIVED_PACKETS = 69,
+ // The quic connection has been cancelled.
+ QUIC_CONNECTION_CANCELLED = 70,
+ // Disabled QUIC because of high packet loss rate.
+ QUIC_BAD_PACKET_LOSS_RATE = 71,
+ // Disabled QUIC because of too many PUBLIC_RESETs post handshake.
+ QUIC_PUBLIC_RESETS_POST_HANDSHAKE = 73,
+ // Disabled QUIC because of too many timeouts with streams open.
+ QUIC_TIMEOUTS_WITH_OPEN_STREAMS = 74,
+ // Closed because we failed to serialize a packet.
+ QUIC_FAILED_TO_SERIALIZE_PACKET = 75,
+ // QUIC timed out after too many RTOs.
+ QUIC_TOO_MANY_RTOS = 85,
+
+ // Crypto errors.
+
+ // Handshake failed.
+ QUIC_HANDSHAKE_FAILED = 28,
+ // Handshake message contained out of order tags.
+ QUIC_CRYPTO_TAGS_OUT_OF_ORDER = 29,
+ // Handshake message contained too many entries.
+ QUIC_CRYPTO_TOO_MANY_ENTRIES = 30,
+ // Handshake message contained an invalid value length.
+ QUIC_CRYPTO_INVALID_VALUE_LENGTH = 31,
+ // A crypto message was received after the handshake was complete.
+ QUIC_CRYPTO_MESSAGE_AFTER_HANDSHAKE_COMPLETE = 32,
+ // A crypto message was received with an illegal message tag.
+ QUIC_INVALID_CRYPTO_MESSAGE_TYPE = 33,
+ // A crypto message was received with an illegal parameter.
+ QUIC_INVALID_CRYPTO_MESSAGE_PARAMETER = 34,
+ // An invalid channel id signature was supplied.
+ QUIC_INVALID_CHANNEL_ID_SIGNATURE = 52,
+ // A crypto message was received with a mandatory parameter missing.
+ QUIC_CRYPTO_MESSAGE_PARAMETER_NOT_FOUND = 35,
+ // A crypto message was received with a parameter that has no overlap
+ // with the local parameter.
+ QUIC_CRYPTO_MESSAGE_PARAMETER_NO_OVERLAP = 36,
+ // A crypto message was received that contained a parameter with too few
+ // values.
+ QUIC_CRYPTO_MESSAGE_INDEX_NOT_FOUND = 37,
+ // A demand for an unsupport proof type was received.
+ QUIC_UNSUPPORTED_PROOF_DEMAND = 94,
+ // An internal error occurred in crypto processing.
+ QUIC_CRYPTO_INTERNAL_ERROR = 38,
+ // A crypto handshake message specified an unsupported version.
+ QUIC_CRYPTO_VERSION_NOT_SUPPORTED = 39,
+ // A crypto handshake message resulted in a stateless reject.
+ QUIC_CRYPTO_HANDSHAKE_STATELESS_REJECT = 72,
+ // There was no intersection between the crypto primitives supported by the
+ // peer and ourselves.
+ QUIC_CRYPTO_NO_SUPPORT = 40,
+ // The server rejected our client hello messages too many times.
+ QUIC_CRYPTO_TOO_MANY_REJECTS = 41,
+ // The client rejected the server's certificate chain or signature.
+ QUIC_PROOF_INVALID = 42,
+ // A crypto message was received with a duplicate tag.
+ QUIC_CRYPTO_DUPLICATE_TAG = 43,
+ // A crypto message was received with the wrong encryption level (i.e. it
+ // should have been encrypted but was not.)
+ QUIC_CRYPTO_ENCRYPTION_LEVEL_INCORRECT = 44,
+ // The server config for a server has expired.
+ QUIC_CRYPTO_SERVER_CONFIG_EXPIRED = 45,
+ // We failed to setup the symmetric keys for a connection.
+ QUIC_CRYPTO_SYMMETRIC_KEY_SETUP_FAILED = 53,
+ // A handshake message arrived, but we are still validating the
+ // previous handshake message.
+ QUIC_CRYPTO_MESSAGE_WHILE_VALIDATING_CLIENT_HELLO = 54,
+ // A server config update arrived before the handshake is complete.
+ QUIC_CRYPTO_UPDATE_BEFORE_HANDSHAKE_COMPLETE = 65,
+ // CHLO cannot fit in one packet.
+ QUIC_CRYPTO_CHLO_TOO_LARGE = 90,
+ // This connection involved a version negotiation which appears to have been
+ // tampered with.
+ QUIC_VERSION_NEGOTIATION_MISMATCH = 55,
+
+ // Multipath errors.
+ // Multipath is not enabled, but a packet with multipath flag on is received.
+ QUIC_BAD_MULTIPATH_FLAG = 79,
+ // A path is supposed to exist but does not.
+ QUIC_MULTIPATH_PATH_DOES_NOT_EXIST = 91,
+ // A path is supposed to be active but is not.
+ QUIC_MULTIPATH_PATH_NOT_ACTIVE = 92,
+
+ // IP address changed causing connection close.
+ QUIC_IP_ADDRESS_CHANGED = 80,
+
+ // Connection migration errors.
+ // Network changed, but connection had no migratable streams.
+ QUIC_CONNECTION_MIGRATION_NO_MIGRATABLE_STREAMS = 81,
+ // Connection changed networks too many times.
+ QUIC_CONNECTION_MIGRATION_TOO_MANY_CHANGES = 82,
+ // Connection migration was attempted, but there was no new network to
+ // migrate to.
+ QUIC_CONNECTION_MIGRATION_NO_NEW_NETWORK = 83,
+ // Network changed, but connection had one or more non-migratable streams.
+ QUIC_CONNECTION_MIGRATION_NON_MIGRATABLE_STREAM = 84,
+
+ // Stream frames arrived too discontiguously so that stream sequencer buffer
+ // maintains too many gaps.
+ QUIC_TOO_MANY_FRAME_GAPS = 93,
+
+ // Sequencer buffer get into weird state where continuing read/write will lead
+ // to crash.
+ QUIC_STREAM_SEQUENCER_INVALID_STATE = 95,
+
+ // Connection closed because of server hits max number of sessions allowed.
+ // TODO(fayang): Add monitoring for QUIC_TOO_MANY_SESSIONS_ON_SERVER.
+ QUIC_TOO_MANY_SESSIONS_ON_SERVER = 96,
+
+ // No error. Used as bound while iterating.
+ QUIC_LAST_ERROR = 97,
+};
+// QuicErrorCodes is encoded as a single octet on-the-wire.
+static_assert(static_cast<int>(QUIC_LAST_ERROR) <=
+ std::numeric_limits<uint8_t>::max(),
+ "QuicErrorCode exceeds single octet");
+
+// Returns the name of the QuicRstStreamErrorCode as a char*
+QUIC_EXPORT_PRIVATE const char* QuicRstStreamErrorCodeToString(
+ QuicRstStreamErrorCode error);
+
+// Returns the name of the QuicErrorCode as a char*
+QUIC_EXPORT_PRIVATE const char* QuicErrorCodeToString(QuicErrorCode error);
+
+} // namespace net
+
+#endif // NET_QUIC_CORE_QUIC_ERROR_CODES_H_
diff --git a/chromium/net/quic/core/quic_error_codes_test.cc b/chromium/net/quic/core/quic_error_codes_test.cc
new file mode 100644
index 00000000000..0694fefdf83
--- /dev/null
+++ b/chromium/net/quic/core/quic_error_codes_test.cc
@@ -0,0 +1,25 @@
+// Copyright (c) 2013 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.
+
+#include "net/quic/core/quic_error_codes.h"
+
+#include "testing/gmock/include/gmock/gmock.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace net {
+namespace test {
+namespace {
+
+TEST(QuicUtilsTest, QuicRstStreamErrorCodeToString) {
+ EXPECT_STREQ("QUIC_BAD_APPLICATION_PAYLOAD",
+ QuicRstStreamErrorCodeToString(QUIC_BAD_APPLICATION_PAYLOAD));
+}
+
+TEST(QuicUtilsTest, QuicErrorCodeToString) {
+ EXPECT_STREQ("QUIC_NO_ERROR", QuicErrorCodeToString(QUIC_NO_ERROR));
+}
+
+} // namespace
+} // namespace test
+} // namespace net
diff --git a/chromium/net/quic/core/quic_flags.h b/chromium/net/quic/core/quic_flags.h
index 70c9d2e9ad2..a1a5ff36c0d 100644
--- a/chromium/net/quic/core/quic_flags.h
+++ b/chromium/net/quic/core/quic_flags.h
@@ -2,15 +2,59 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#ifndef NET_QUIC_QUIC_FLAGS_H_
-#define NET_QUIC_QUIC_FLAGS_H_
+#ifndef NET_QUIC_CORE_QUIC_FLAGS_H_
+#define NET_QUIC_CORE_QUIC_FLAGS_H_
-#include <stdint.h>
+#include <cstdint>
+#include <string>
-#include "net/base/net_export.h"
+#include "net/quic/platform/api/quic_export.h"
-#define QUIC_FLAG(type, flag, value) NET_EXPORT_PRIVATE extern type flag;
+#define QUIC_FLAG(type, flag, value) QUIC_EXPORT_PRIVATE extern type flag;
#include "net/quic/core/quic_flags_list.h"
#undef QUIC_FLAG
-#endif // NET_QUIC_QUIC_FLAGS_H_
+// API compatibility with new-style flags.
+namespace base {
+
+inline bool GetFlag(bool flag) {
+ return flag;
+}
+inline int32_t GetFlag(int32_t flag) {
+ return flag;
+}
+inline int64_t GetFlag(int64_t flag) {
+ return flag;
+}
+inline uint64_t GetFlag(uint64_t flag) {
+ return flag;
+}
+inline double GetFlag(double flag) {
+ return flag;
+}
+inline std::string GetFlag(const std::string& flag) {
+ return flag;
+}
+
+inline void SetFlag(bool* f, bool v) {
+ *f = v;
+}
+inline void SetFlag(int32_t* f, int32_t v) {
+ *f = v;
+}
+inline void SetFlag(int64_t* f, int64_t v) {
+ *f = v;
+}
+inline void SetFlag(uint64_t* f, uint64_t v) {
+ *f = v;
+}
+inline void SetFlag(double* f, double v) {
+ *f = v;
+}
+inline void SetFlag(std::string* f, const std::string& v) {
+ *f = v;
+}
+
+} // namespace base
+
+#endif // NET_QUIC_CORE_QUIC_FLAGS_H_
diff --git a/chromium/net/quic/core/quic_flags_list.h b/chromium/net/quic/core/quic_flags_list.h
index 85bd48d220d..3941adc596d 100644
--- a/chromium/net/quic/core/quic_flags_list.h
+++ b/chromium/net/quic/core/quic_flags_list.h
@@ -9,7 +9,7 @@
// If true, QUIC BBR congestion control may be enabled via Finch and/or via QUIC
// connection options.
-QUIC_FLAG(bool, FLAGS_quic_allow_new_bbr, true)
+QUIC_FLAG(bool, FLAGS_quic_reloadable_flag_quic_allow_new_bbr, true)
// Time period for which a given connection_id should live in the time-wait
// state.
@@ -27,138 +27,192 @@ QUIC_FLAG(int64_t, FLAGS_quic_time_wait_list_seconds, 200)
QUIC_FLAG(int64_t, FLAGS_quic_time_wait_list_max_connections, 600000)
// Enables server-side support for QUIC stateless rejects.
-QUIC_FLAG(bool, FLAGS_enable_quic_stateless_reject_support, true)
+QUIC_FLAG(bool,
+ FLAGS_quic_reloadable_flag_enable_quic_stateless_reject_support,
+ true)
// This flag is not in use, just to keep consistency for shared code.
-QUIC_FLAG(bool, FLAGS_quic_always_log_bugs_for_tests, true)
+QUIC_FLAG(bool, FLAGS_quic_reloadable_flag_quic_always_log_bugs_for_tests, true)
// If true, multipath is enabled for the connection.
-QUIC_FLAG(bool, FLAGS_quic_enable_multipath, false)
+QUIC_FLAG(bool, FLAGS_quic_reloadable_flag_quic_enable_multipath, false)
// If true, require handshake confirmation for QUIC connections, functionally
// disabling 0-rtt handshakes.
// TODO(rtenneti): Enable this flag after CryptoServerTest's are fixed.
-QUIC_FLAG(bool, FLAGS_quic_require_handshake_confirmation, false)
+QUIC_FLAG(bool,
+ FLAGS_quic_reloadable_flag_quic_require_handshake_confirmation,
+ false)
// If true, disable pacing in QUIC.
QUIC_FLAG(bool, FLAGS_quic_disable_pacing_for_perf_tests, false)
// If true, QUIC public reset packets will have the \"pre-v33\" public header
// flags.
-QUIC_FLAG(bool, FLAGS_quic_use_old_public_reset_packets, true)
+QUIC_FLAG(bool,
+ FLAGS_quic_reloadable_flag_quic_use_old_public_reset_packets,
+ true)
// If true, QUIC will use cheap stateless rejects without creating a full
// connection.
-QUIC_FLAG(bool, FLAGS_quic_use_cheap_stateless_rejects, true)
+QUIC_FLAG(bool,
+ FLAGS_quic_reloadable_flag_quic_use_cheap_stateless_rejects,
+ true)
// If true, QUIC respect HTTP2 SETTINGS frame rather than always close the
// connection.
-QUIC_FLAG(bool, FLAGS_quic_respect_http2_settings_frame, true)
-
-// If true, enables QUIC_VERSION_35.
-QUIC_FLAG(bool, FLAGS_quic_enable_version_35, true)
+QUIC_FLAG(bool,
+ FLAGS_quic_reloadable_flag_quic_respect_http2_settings_frame,
+ true)
// If true, re-enables QUIC_VERSION_36.
-QUIC_FLAG(bool, FLAGS_quic_enable_version_36_v2, true)
+QUIC_FLAG(bool, FLAGS_quic_reloadable_flag_quic_enable_version_36_v3, true)
// If true, use async codepaths to invoke ProofSource::GetProof.
-QUIC_FLAG(bool, FLAGS_enable_async_get_proof, false)
-
-// If true, requires handshake confirmations for all QUIC handshakes with
-// versions less than 33.
-QUIC_FLAG(bool, FLAGS_quic_require_handshake_confirmation_pre33, false)
+QUIC_FLAG(bool, FLAGS_quic_reloadable_flag_enable_async_get_proof, false)
// If true, only open limited number of quic sessions per epoll event. Leave the
// rest to next event.
-QUIC_FLAG(bool, FLAGS_quic_limit_num_new_sessions_per_epoll_loop, true)
-
-// If true, disables QUIC version less than 34.
-QUIC_FLAG(bool, FLAGS_quic_disable_pre_34, true)
+QUIC_FLAG(bool,
+ FLAGS_quic_reloadable_flag_quic_limit_num_new_sessions_per_epoll_loop,
+ true)
// Only close the connection on the 5th RTO client side when the 5RTO option
// is enabled.
-QUIC_FLAG(bool, FLAGS_quic_only_5rto_client_side, true)
+QUIC_FLAG(bool, FLAGS_quic_reloadable_flag_quic_only_5rto_client_side, false)
// If true, QUIC server push will enabled by default.
-QUIC_FLAG(bool, FLAGS_quic_enable_server_push_by_default, true)
-
-// Only inform the QuicSentPacketManager of packets that were sent,
-// not those that we tried to send.
-QUIC_FLAG(bool, FLAGS_quic_only_track_sent_packets, true)
-
-// As the Linux kernel does, limit QUIC's Cubic congestion control to
-// only increase the CWND 1 packet for every two packets acked.
-QUIC_FLAG(bool, FLAGS_quic_limit_cubic_cwnd_increase, true)
-
-// If true, export reject reasons for all rejects, i.e., rejects,
-// stateless rejects and cheap stateless rejects.
-QUIC_FLAG(bool, FLAGS_quic_export_rej_for_all_rejects, true)
+QUIC_FLAG(bool,
+ FLAGS_quic_reloadable_flag_quic_enable_server_push_by_default,
+ true)
// Allow large send deltas to be used as RTT samples.
-QUIC_FLAG(bool, FLAGS_quic_allow_large_send_deltas, true)
+QUIC_FLAG(bool, FLAGS_quic_reloadable_flag_quic_allow_large_send_deltas, true)
// Engage early retransmit anytime the largest acked is greater than
// or equal to the largest retransmittable packet.
-QUIC_FLAG(bool, FLAGS_quic_largest_sent_retransmittable, true)
+QUIC_FLAG(bool,
+ FLAGS_quic_reloadable_flag_quic_largest_sent_retransmittable,
+ true)
// If true, release QuicCryptoStream\'s read buffer when stream are less
// frequently used.
-QUIC_FLAG(bool, FLAGS_quic_release_crypto_stream_buffer, false)
+QUIC_FLAG(bool,
+ FLAGS_quic_reloadable_flag_quic_release_crypto_stream_buffer,
+ true)
// Use a more conservative backoff of 2x instead of 1.5x for handshake
// retransmissions, as well as a larger minimum.
-QUIC_FLAG(bool, FLAGS_quic_conservative_handshake_retransmits, true)
+QUIC_FLAG(bool,
+ FLAGS_quic_reloadable_flag_quic_conservative_handshake_retransmits,
+ false)
// If true, buffer packets while parsing public headers instead of parsing down
// if CHLO is already buffered.
-QUIC_FLAG(bool, FLAGS_quic_buffer_packets_after_chlo, false)
+QUIC_FLAG(bool,
+ FLAGS_quic_reloadable_flag_quic_buffer_packets_after_chlo,
+ false)
// Previously QUIC didn't register a packet as received until it was fully
// processed, but now that flow control is implemented, it can be received once
// decrypted.
-QUIC_FLAG(bool, FLAGS_quic_receive_packet_once_decrypted, false)
+QUIC_FLAG(bool,
+ FLAGS_quic_reloadable_flag_quic_receive_packet_once_decrypted,
+ false)
// If true, enable the Lazy FACK style loss detection in QUIC.
-QUIC_FLAG(bool, FLAGS_quic_enable_lazy_fack, true)
+QUIC_FLAG(bool, FLAGS_quic_reloadable_flag_quic_enable_lazy_fack, false)
// If true, do not override a connection in global map if exists. Only create
// QUIC session if it is successfully inserted to the global map. Toss the
// packet if insertion fails.
-QUIC_FLAG(bool, FLAGS_quic_create_session_after_insertion, false)
+QUIC_FLAG(bool,
+ FLAGS_quic_reloadable_flag_quic_create_session_after_insertion,
+ false)
// If true, rejected packet number is removed from public reset packet.
-QUIC_FLAG(bool, FLAGS_quic_remove_packet_number_from_public_reset, false)
-
-// If true, will send QUIC_PUSH_STREAM_TIMED_OUT when push stream is unclaimed
-// and times out.
-QUIC_FLAG(bool, FLAGS_quic_send_push_stream_timed_out_error, true)
-
-// If true, enable bugfix for FHOL experiment (fin-only
-// WritevStreamData).
-QUIC_FLAG(bool, FLAGS_quic_bugfix_fhol_writev_fin_only_v2, true)
+QUIC_FLAG(
+ bool,
+ FLAGS_quic_reloadable_flag_quic_remove_packet_number_from_public_reset,
+ false)
// If true, v33 QUIC client uses 1 bit to specify 8-byte connection id in
// public flag.
-QUIC_FLAG(bool, FLAGS_quic_remove_v33_hacks2, false)
+QUIC_FLAG(bool, FLAGS_quic_reloadable_flag_quic_remove_v33_hacks2, false)
// If true, limits QUIC uncompressed headers to 16K.
-QUIC_FLAG(bool, FLAGS_quic_limit_uncompressed_headers, false)
+QUIC_FLAG(bool,
+ FLAGS_quic_reloadable_flag_quic_limit_uncompressed_headers,
+ false)
// If true, release headers stream\'s sequencer buffer when there is no active
// stream.
-QUIC_FLAG(bool, FLAGS_quic_headers_stream_release_sequencer_buffer, false)
-
-// Default enable QUIC's Cubic in bytes implementation instead of
-// Cubic in packets.
-QUIC_FLAG(bool, FLAGS_quic_default_enable_cubic_bytes, true)
-
-// If enabled, fix double call of
-// InsertLocallyClosedStreamsHighestOffset in ResetPromised.
-QUIC_FLAG(bool, FLAGS_quic_bugfix_reset_promised, true)
+QUIC_FLAG(
+ bool,
+ FLAGS_quic_reloadable_flag_quic_headers_stream_release_sequencer_buffer,
+ true)
// Set the retransmission alarm only when there are unacked
// retransmittable packets.
-QUIC_FLAG(bool, FLAGS_quic_more_conservative_retransmission_alarm, true)
+QUIC_FLAG(
+ bool,
+ FLAGS_quic_reloadable_flag_quic_more_conservative_retransmission_alarm,
+ true)
// Enable QUIC force HOL blocking experiment.
-QUIC_FLAG(bool, FLAGS_quic_enable_force_hol_blocking, true)
+QUIC_FLAG(bool, FLAGS_quic_reloadable_flag_quic_enable_force_hol_blocking, true)
+
+// If true, allows packets to be buffered in anticipation of a future CHLO, and
+// allow CHLO packets to be buffered until next iteration of the event loop.
+QUIC_FLAG(bool, FLAGS_quic_allow_chlo_buffering, true)
+
+// If true, fix version manager bug, in which version flag does not really
+// help.
+QUIC_FLAG(bool, FLAGS_quic_reloadable_flag_quic_fix_version_manager, false)
+
+// Add a new client connection options field to QuicOptions which is only used
+// to configure client side features, such as congestion control.
+QUIC_FLAG(bool, FLAGS_quic_reloadable_flag_quic_client_connection_options, true)
+
+// If true, fix some casts that were causing off-by-one errors in QUIC's cubic
+// "convex" increases.
+QUIC_FLAG(bool, FLAGS_quic_reloadable_flag_quic_fix_cubic_convex_mode, false)
+
+// Ensure that BBR startup pacing rate does not drop below the initial one.
+QUIC_FLAG(bool, FLAGS_quic_reloadable_flag_quic_bbr_faster_startup, true)
+
+// If true, GFE sends SETTINGS_MAX_HEADER_LIST_SIZE to the client at the
+// beginning of a connection.
+QUIC_FLAG(bool, FLAGS_quic_reloadable_flag_quic_send_max_header_list_size, true)
+
+// If true, fix quantization of CubicBytes while performing convex increases.
+QUIC_FLAG(bool,
+ FLAGS_quic_reloadable_flag_quic_fix_cubic_bytes_quantization,
+ false)
+
+// If true, QUIC cubic code will use the event time when adjusting CWND after an
+// ACK instead of the clock\'s current approximate time.
+QUIC_FLAG(bool, FLAGS_quic_reloadable_flag_quic_use_event_time, false)
+
+// If true, lazy allocate and early release memeory used in
+// QuicStreamSequencerBuffer to buffer incoming data.
+QUIC_FLAG(
+ bool,
+ FLAGS_quic_reloadable_flag_quic_reduce_sequencer_buffer_memory_life_time,
+ true)
+
+// If true, Makes GFE respect the connection options for initial flow control
+// window larger than 32 KB.
+QUIC_FLAG(bool, FLAGS_quic_reloadable_flag_quic_large_ifw_options, false)
+
+// If true, fix Cubic\'s use of kBetaLastMax for n-connection emulation.
+QUIC_FLAG(bool, FLAGS_quic_reloadable_flag_quic_fix_beta_last_max, false)
+
+// If true, enable QUIC v37.
+QUIC_FLAG(bool, FLAGS_quic_reloadable_flag_quic_enable_version_37, false)
+
+// If true, disables QUIC v34.
+QUIC_FLAG(bool, FLAGS_quic_reloadable_flag_quic_disable_version_34, false)
+
+// Allow quic to properly support proxying 100 Continue responses.
+QUIC_FLAG(bool, FLAGS_quic_restart_flag_quic_supports_100_continue, false)
diff --git a/chromium/net/quic/core/quic_flow_controller.cc b/chromium/net/quic/core/quic_flow_controller.cc
index 3c556f3488f..976c0ff1d92 100644
--- a/chromium/net/quic/core/quic_flow_controller.cc
+++ b/chromium/net/quic/core/quic_flow_controller.cc
@@ -4,11 +4,13 @@
#include "net/quic/core/quic_flow_controller.h"
-#include "base/strings/stringprintf.h"
-#include "net/quic/core/quic_bug_tracker.h"
+#include <cstdint>
+
#include "net/quic/core/quic_connection.h"
-#include "net/quic/core/quic_flags.h"
-#include "net/quic/core/quic_protocol.h"
+#include "net/quic/core/quic_packets.h"
+#include "net/quic/platform/api/quic_bug_tracker.h"
+#include "net/quic/platform/api/quic_logging.h"
+#include "net/quic/platform/api/quic_str_cat.h"
namespace net {
@@ -36,18 +38,21 @@ QuicFlowController::QuicFlowController(QuicConnection* connection,
receive_window_size_limit_ = (id_ == kConnectionLevelId)
? kSessionReceiveWindowLimit
: kStreamReceiveWindowLimit;
-
- DVLOG(1) << ENDPOINT << "Created flow controller for stream " << id_
- << ", setting initial receive window offset to: "
- << receive_window_offset_
- << ", max receive window to: " << receive_window_size_
- << ", max receive window limit to: " << receive_window_size_limit_
- << ", setting send window offset to: " << send_window_offset_;
+ DCHECK_LE(receive_window_size_, receive_window_size_limit_);
+
+ QUIC_DVLOG(1) << ENDPOINT << "Created flow controller for stream " << id_
+ << ", setting initial receive window offset to: "
+ << receive_window_offset_
+ << ", max receive window to: " << receive_window_size_
+ << ", max receive window limit to: "
+ << receive_window_size_limit_
+ << ", setting send window offset to: " << send_window_offset_;
}
void QuicFlowController::AddBytesConsumed(QuicByteCount bytes_consumed) {
bytes_consumed_ += bytes_consumed;
- DVLOG(1) << ENDPOINT << "Stream " << id_ << " consumed: " << bytes_consumed_;
+ QUIC_DVLOG(1) << ENDPOINT << "Stream " << id_
+ << " consumed: " << bytes_consumed_;
MaybeSendWindowUpdate();
}
@@ -59,9 +64,9 @@ bool QuicFlowController::UpdateHighestReceivedOffset(
return false;
}
- DVLOG(1) << ENDPOINT << "Stream " << id_
- << " highest byte offset increased from: "
- << highest_received_byte_offset_ << " to " << new_offset;
+ QUIC_DVLOG(1) << ENDPOINT << "Stream " << id_
+ << " highest byte offset increased from: "
+ << highest_received_byte_offset_ << " to " << new_offset;
highest_received_byte_offset_ = new_offset;
return true;
}
@@ -76,25 +81,22 @@ void QuicFlowController::AddBytesSent(QuicByteCount bytes_sent) {
// This is an error on our side, close the connection as soon as possible.
connection_->CloseConnection(
QUIC_FLOW_CONTROL_SENT_TOO_MUCH_DATA,
- base::StringPrintf(
- "%llu bytes over send window offset",
- static_cast<unsigned long long>(send_window_offset_ -
- (bytes_sent_ + bytes_sent)))
- .c_str(),
+ QuicStrCat(send_window_offset_ - (bytes_sent_ + bytes_sent),
+ "bytes over send window offset"),
ConnectionCloseBehavior::SEND_CONNECTION_CLOSE_PACKET);
return;
}
bytes_sent_ += bytes_sent;
- DVLOG(1) << ENDPOINT << "Stream " << id_ << " sent: " << bytes_sent_;
+ QUIC_DVLOG(1) << ENDPOINT << "Stream " << id_ << " sent: " << bytes_sent_;
}
bool QuicFlowController::FlowControlViolation() {
if (highest_received_byte_offset_ > receive_window_offset_) {
- DVLOG(1) << ENDPOINT << "Flow control violation on stream " << id_
- << ", receive window offset: " << receive_window_offset_
- << ", highest received byte offset: "
- << highest_received_byte_offset_;
+ QUIC_DLOG(INFO) << ENDPOINT << "Flow control violation on stream " << id_
+ << ", receive window offset: " << receive_window_offset_
+ << ", highest received byte offset: "
+ << highest_received_byte_offset_;
return true;
}
return false;
@@ -114,7 +116,7 @@ void QuicFlowController::MaybeIncreaseMaxWindowSize() {
QuicTime prev = prev_window_update_time_;
prev_window_update_time_ = now;
if (!prev.IsInitialized()) {
- DVLOG(1) << ENDPOINT << "first window update for stream " << id_;
+ QUIC_DVLOG(1) << ENDPOINT << "first window update for stream " << id_;
return;
}
@@ -126,7 +128,7 @@ void QuicFlowController::MaybeIncreaseMaxWindowSize() {
QuicTime::Delta rtt =
connection_->sent_packet_manager().GetRttStats()->smoothed_rtt();
if (rtt.IsZero()) {
- DVLOG(1) << ENDPOINT << "rtt zero for stream " << id_;
+ QUIC_DVLOG(1) << ENDPOINT << "rtt zero for stream " << id_;
return;
}
@@ -146,16 +148,16 @@ void QuicFlowController::MaybeIncreaseMaxWindowSize() {
std::min(receive_window_size_, receive_window_size_limit_);
if (receive_window_size_ > old_window) {
- DVLOG(1) << ENDPOINT << "New max window increase for stream " << id_
- << " after " << since_last.ToMicroseconds() << " us, and RTT is "
- << rtt.ToMicroseconds()
- << "us. max wndw: " << receive_window_size_;
+ QUIC_DVLOG(1) << ENDPOINT << "New max window increase for stream " << id_
+ << " after " << since_last.ToMicroseconds()
+ << " us, and RTT is " << rtt.ToMicroseconds()
+ << "us. max wndw: " << receive_window_size_;
} else {
// TODO(ckrasic) - add a varz to track this (?).
- DVLOG(1) << ENDPOINT << "Max window at limit for stream " << id_
- << " after " << since_last.ToMicroseconds() << " us, and RTT is "
- << rtt.ToMicroseconds()
- << "us. Limit size: " << receive_window_size_;
+ QUIC_LOG_FIRST_N(INFO, 1) << ENDPOINT << "Max window at limit for stream "
+ << id_ << " after " << since_last.ToMicroseconds()
+ << " us, and RTT is " << rtt.ToMicroseconds()
+ << "us. Limit size: " << receive_window_size_;
}
}
@@ -172,9 +174,9 @@ void QuicFlowController::MaybeSendWindowUpdate() {
QuicByteCount threshold = WindowUpdateThreshold();
if (available_window >= threshold) {
- DVLOG(1) << ENDPOINT << "Not sending WindowUpdate for stream " << id_
- << ", available window: " << available_window
- << " >= threshold: " << threshold;
+ QUIC_DVLOG(1) << ENDPOINT << "Not sending WindowUpdate for stream " << id_
+ << ", available window: " << available_window
+ << " >= threshold: " << threshold;
return;
}
@@ -183,12 +185,12 @@ void QuicFlowController::MaybeSendWindowUpdate() {
// Update our receive window.
receive_window_offset_ += (receive_window_size_ - available_window);
- DVLOG(1) << ENDPOINT << "Sending WindowUpdate frame for stream " << id_
- << ", consumed bytes: " << bytes_consumed_
- << ", available window: " << available_window
- << ", and threshold: " << threshold
- << ", and receive window size: " << receive_window_size_
- << ". New receive window offset is: " << receive_window_offset_;
+ QUIC_DVLOG(1) << ENDPOINT << "Sending WindowUpdate frame for stream " << id_
+ << ", consumed bytes: " << bytes_consumed_
+ << ", available window: " << available_window
+ << ", and threshold: " << threshold
+ << ", and receive window size: " << receive_window_size_
+ << ". New receive window offset is: " << receive_window_offset_;
// Inform the peer of our new receive window.
connection_->SendWindowUpdate(id_, receive_window_offset_);
@@ -197,10 +199,11 @@ void QuicFlowController::MaybeSendWindowUpdate() {
void QuicFlowController::MaybeSendBlocked() {
if (SendWindowSize() == 0 &&
last_blocked_send_window_offset_ < send_window_offset_) {
- DVLOG(1) << ENDPOINT << "Stream " << id_ << " is flow control blocked. "
- << "Send window: " << SendWindowSize()
- << ", bytes sent: " << bytes_sent_
- << ", send limit: " << send_window_offset_;
+ QUIC_DLOG(INFO) << ENDPOINT << "Stream " << id_
+ << " is flow control blocked. "
+ << "Send window: " << SendWindowSize()
+ << ", bytes sent: " << bytes_sent_
+ << ", send limit: " << send_window_offset_;
// The entire send_window has been consumed, we are now flow control
// blocked.
connection_->SendBlocked(id_);
@@ -218,10 +221,10 @@ bool QuicFlowController::UpdateSendWindowOffset(
return false;
}
- DVLOG(1) << ENDPOINT << "UpdateSendWindowOffset for stream " << id_
- << " with new offset " << new_send_window_offset
- << " current offset: " << send_window_offset_
- << " bytes_sent: " << bytes_sent_;
+ QUIC_DVLOG(1) << ENDPOINT << "UpdateSendWindowOffset for stream " << id_
+ << " with new offset " << new_send_window_offset
+ << " current offset: " << send_window_offset_
+ << " bytes_sent: " << bytes_sent_;
const bool blocked = IsBlocked();
send_window_offset_ = new_send_window_offset;
@@ -240,8 +243,9 @@ uint64_t QuicFlowController::SendWindowSize() const {
}
void QuicFlowController::UpdateReceiveWindowSize(QuicStreamOffset size) {
- DVLOG(1) << ENDPOINT << "UpdateReceiveWindowSize for stream " << id_ << ": "
- << size;
+ DCHECK_LE(size, receive_window_size_limit_);
+ QUIC_DVLOG(1) << ENDPOINT << "UpdateReceiveWindowSize for stream " << id_
+ << ": " << size;
if (receive_window_size_ != receive_window_offset_) {
QUIC_BUG << "receive_window_size_:" << receive_window_size_
<< " != receive_window_offset:" << receive_window_offset_;
diff --git a/chromium/net/quic/core/quic_flow_controller.h b/chromium/net/quic/core/quic_flow_controller.h
index 238b9b49c3b..94225636c28 100644
--- a/chromium/net/quic/core/quic_flow_controller.h
+++ b/chromium/net/quic/core/quic_flow_controller.h
@@ -2,12 +2,12 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#ifndef NET_QUIC_QUIC_FLOW_CONTROLLER_H_
-#define NET_QUIC_QUIC_FLOW_CONTROLLER_H_
+#ifndef NET_QUIC_CORE_QUIC_FLOW_CONTROLLER_H_
+#define NET_QUIC_CORE_QUIC_FLOW_CONTROLLER_H_
#include "base/macros.h"
-#include "net/base/net_export.h"
-#include "net/quic/core/quic_protocol.h"
+#include "net/quic/core/quic_packets.h"
+#include "net/quic/platform/api/quic_export.h"
namespace net {
@@ -23,7 +23,7 @@ const QuicStreamId kConnectionLevelId = 0;
// control. The stream/connection owns a QuicFlowController which keeps track of
// bytes sent/received, can tell the owner if it is flow control blocked, and
// can send WINDOW_UPDATE or BLOCKED frames when needed.
-class NET_EXPORT_PRIVATE QuicFlowController {
+class QUIC_EXPORT_PRIVATE QuicFlowController {
public:
QuicFlowController(QuicConnection* connection,
QuicStreamId id,
@@ -168,4 +168,4 @@ class NET_EXPORT_PRIVATE QuicFlowController {
} // namespace net
-#endif // NET_QUIC_QUIC_FLOW_CONTROLLER_H_
+#endif // NET_QUIC_CORE_QUIC_FLOW_CONTROLLER_H_
diff --git a/chromium/net/quic/core/quic_flow_controller_test.cc b/chromium/net/quic/core/quic_flow_controller_test.cc
index 5b7981f1858..93a07a58175 100644
--- a/chromium/net/quic/core/quic_flow_controller_test.cc
+++ b/chromium/net/quic/core/quic_flow_controller_test.cc
@@ -7,15 +7,12 @@
#include <memory>
#include "base/format_macros.h"
-#include "base/strings/stringprintf.h"
-#include "net/quic/core/quic_flags.h"
-#include "net/quic/core/quic_utils.h"
+#include "net/quic/platform/api/quic_str_cat.h"
#include "net/quic/test_tools/quic_connection_peer.h"
#include "net/quic/test_tools/quic_flow_controller_peer.h"
#include "net/quic/test_tools/quic_sent_packet_manager_peer.h"
#include "net/quic/test_tools/quic_test_utils.h"
-#include "net/test/gtest_util.h"
-#include "testing/gmock/include/gmock/gmock.h"
+#include "testing/gtest/include/gtest/gtest.h"
using testing::_;
@@ -84,8 +81,7 @@ TEST_F(QuicFlowControllerTest, SendingBytes) {
CloseConnection(QUIC_FLOW_CONTROL_SENT_TOO_MUCH_DATA, _, _));
EXPECT_QUIC_BUG(
flow_controller_->AddBytesSent(send_window_ * 10),
- base::StringPrintf("Trying to send an extra %" PRIu64 " bytes",
- send_window_ * 10));
+ QuicStrCat("Trying to send an extra ", send_window_ * 10, " bytes"));
EXPECT_TRUE(flow_controller_->IsBlocked());
EXPECT_EQ(0u, flow_controller_->SendWindowSize());
}
@@ -166,8 +162,8 @@ TEST_F(QuicFlowControllerTest, ReceivingBytesFastIncreasesFlowWindow) {
// Make sure clock is inititialized.
connection_.AdvanceTime(QuicTime::Delta::FromMilliseconds(1));
- QuicSentPacketManagerInterface* manager =
- QuicConnectionPeer::GetSentPacketManager(&connection_, kDefaultPathId);
+ QuicSentPacketManager* manager =
+ QuicConnectionPeer::GetSentPacketManager(&connection_);
RttStats* rtt_stats = const_cast<RttStats*>(manager->GetRttStats());
rtt_stats->UpdateRtt(QuicTime::Delta::FromMilliseconds(kRtt),
@@ -219,8 +215,8 @@ TEST_F(QuicFlowControllerTest, ReceivingBytesFastNoAutoTune) {
// Make sure clock is inititialized.
connection_.AdvanceTime(QuicTime::Delta::FromMilliseconds(1));
- QuicSentPacketManagerInterface* manager =
- QuicConnectionPeer::GetSentPacketManager(&connection_, kDefaultPathId);
+ QuicSentPacketManager* manager =
+ QuicConnectionPeer::GetSentPacketManager(&connection_);
RttStats* rtt_stats = const_cast<RttStats*>(manager->GetRttStats());
rtt_stats->UpdateRtt(QuicTime::Delta::FromMilliseconds(kRtt),
@@ -272,8 +268,8 @@ TEST_F(QuicFlowControllerTest, ReceivingBytesNormalStableFlowWindow) {
// Make sure clock is inititialized.
connection_.AdvanceTime(QuicTime::Delta::FromMilliseconds(1));
- QuicSentPacketManagerInterface* manager =
- QuicConnectionPeer::GetSentPacketManager(&connection_, kDefaultPathId);
+ QuicSentPacketManager* manager =
+ QuicConnectionPeer::GetSentPacketManager(&connection_);
RttStats* rtt_stats = const_cast<RttStats*>(manager->GetRttStats());
rtt_stats->UpdateRtt(QuicTime::Delta::FromMilliseconds(kRtt),
QuicTime::Delta::Zero(), QuicTime::Zero());
@@ -327,8 +323,8 @@ TEST_F(QuicFlowControllerTest, ReceivingBytesNormalNoAutoTune) {
// Make sure clock is inititialized.
connection_.AdvanceTime(QuicTime::Delta::FromMilliseconds(1));
- QuicSentPacketManagerInterface* manager =
- QuicConnectionPeer::GetSentPacketManager(&connection_, kDefaultPathId);
+ QuicSentPacketManager* manager =
+ QuicConnectionPeer::GetSentPacketManager(&connection_);
RttStats* rtt_stats = const_cast<RttStats*>(manager->GetRttStats());
rtt_stats->UpdateRtt(QuicTime::Delta::FromMilliseconds(kRtt),
QuicTime::Delta::Zero(), QuicTime::Zero());
diff --git a/chromium/net/quic/core/quic_frame_list.cc b/chromium/net/quic/core/quic_frame_list.cc
deleted file mode 100644
index f4890f14e7e..00000000000
--- a/chromium/net/quic/core/quic_frame_list.cc
+++ /dev/null
@@ -1,254 +0,0 @@
-// Copyright (c) 2015 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.
-
-#include "net/quic/core/quic_frame_list.h"
-
-#include <algorithm>
-
-#include "base/logging.h"
-
-using std::list;
-using std::string;
-
-namespace net {
-
-QuicFrameList::FrameData::FrameData(QuicStreamOffset offset,
- string segment,
- const QuicTime timestamp)
- : offset(offset), segment(segment), timestamp(timestamp) {}
-
-QuicFrameList::QuicFrameList() {}
-
-QuicFrameList::~QuicFrameList() {
- Clear();
-}
-
-void QuicFrameList::Clear() {
- frame_list_.clear();
- num_bytes_buffered_ = 0;
-}
-
-bool QuicFrameList::Empty() const {
- return frame_list_.empty();
-}
-
-QuicErrorCode QuicFrameList::OnStreamData(QuicStreamOffset offset,
- base::StringPiece data,
- QuicTime timestamp,
- size_t* const bytes_buffered) {
- *bytes_buffered = 0;
- const size_t data_len = data.size();
- auto insertion_point = FindInsertionPoint(offset, data_len);
- if (IsDuplicate(offset, data_len, insertion_point)) {
- return QUIC_NO_ERROR;
- }
-
- if (FrameOverlapsBufferedData(offset, data_len, insertion_point)) {
- return QUIC_INVALID_STREAM_DATA;
- }
-
- DVLOG(1) << "Buffering stream data at offset " << offset;
- // Inserting an empty string and then copying to avoid the extra copy.
- insertion_point =
- frame_list_.insert(insertion_point, FrameData(offset, "", timestamp));
- data.CopyToString(&insertion_point->segment);
- *bytes_buffered = data_len;
- num_bytes_buffered_ += data_len;
- return QUIC_NO_ERROR;
-}
-
-// Finds the place the frame should be inserted. If an identical frame is
-// present, stops on the identical frame.
-list<QuicFrameList::FrameData>::iterator QuicFrameList::FindInsertionPoint(
- QuicStreamOffset offset,
- size_t len) {
- if (frame_list_.empty()) {
- return frame_list_.begin();
- }
- // If it's after all buffered_frames, return the end.
- if (offset >=
- (frame_list_.rbegin()->offset + frame_list_.rbegin()->segment.length())) {
- return frame_list_.end();
- }
- auto iter = frame_list_.begin();
- // Only advance the iterator if the data begins after the already received
- // frame. If the new frame overlaps with an existing frame, the iterator will
- // still point to the frame it overlaps with.
- while (iter != frame_list_.end() &&
- offset >= iter->offset + iter->segment.length()) {
- ++iter;
- }
- return iter;
-}
-
-// Returns true if |frame| contains data which overlaps buffered data
-// (indicating an invalid stream frame has been received).
-bool QuicFrameList::FrameOverlapsBufferedData(
- QuicStreamOffset offset,
- size_t data_len,
- list<FrameData>::const_iterator insertion_point) const {
- if (frame_list_.empty() || insertion_point == frame_list_.end()) {
- return false;
- }
- // If there is a buffered frame with a higher starting offset, then check to
- // see if the new frame overlaps the beginning of the higher frame.
- if (offset < insertion_point->offset &&
- offset + data_len > insertion_point->offset) {
- DVLOG(1) << "New frame overlaps next frame: " << offset << " + " << data_len
- << " > " << insertion_point->offset;
- return true;
- }
- // If there is a buffered frame with a lower starting offset, then check to
- // see if the buffered frame runs into the new frame.
- if (offset >= insertion_point->offset &&
- offset < insertion_point->offset + insertion_point->segment.length()) {
- DVLOG(1) << "Preceeding frame overlaps new frame: "
- << insertion_point->offset << " + "
- << insertion_point->segment.length() << " > " << offset;
- return true;
- }
-
- return false;
-}
-
-// Returns true if the sequencer has received this frame before.
-bool QuicFrameList::IsDuplicate(
- QuicStreamOffset offset,
- size_t data_len,
- list<FrameData>::const_iterator insertion_point) const {
- // A frame is duplicate if the frame offset is smaller than the bytes consumed
- // or identical to an already received frame.
- return offset < total_bytes_read_ || (insertion_point != frame_list_.end() &&
- offset == insertion_point->offset);
-}
-
-int QuicFrameList::GetReadableRegions(struct iovec* iov, int iov_len) const {
- list<FrameData>::const_iterator it = frame_list_.begin();
- int index = 0;
- QuicStreamOffset offset = total_bytes_read_;
- while (it != frame_list_.end() && index < iov_len) {
- if (it->offset != offset) {
- return index;
- }
-
- iov[index].iov_base =
- static_cast<void*>(const_cast<char*>(it->segment.data()));
- iov[index].iov_len = it->segment.size();
- offset += it->segment.size();
-
- ++index;
- ++it;
- }
- return index;
-}
-
-bool QuicFrameList::GetReadableRegion(iovec* iov, QuicTime* timestamp) const {
- list<FrameData>::const_iterator it = frame_list_.begin();
- if (it == frame_list_.end() || it->offset != total_bytes_read_) {
- return false;
- }
- iov->iov_base = static_cast<void*>(const_cast<char*>(it->segment.data()));
- iov->iov_len = it->segment.size();
- *timestamp = it->timestamp;
- return true;
-}
-
-bool QuicFrameList::MarkConsumed(size_t bytes_used) {
- size_t end_offset = total_bytes_read_ + bytes_used;
- while (!frame_list_.empty() && end_offset != total_bytes_read_) {
- list<FrameData>::iterator it = frame_list_.begin();
- if (it->offset != total_bytes_read_) {
- return false;
- }
-
- if (it->offset + it->segment.length() <= end_offset) {
- total_bytes_read_ += it->segment.length();
- num_bytes_buffered_ -= it->segment.length();
- // This chunk is entirely consumed.
- frame_list_.erase(it);
- continue;
- }
-
- // Partially consume this frame.
- size_t delta = end_offset - it->offset;
- total_bytes_read_ += delta;
- num_bytes_buffered_ -= delta;
- string new_data = it->segment.substr(delta);
- const QuicTime timestamp = it->timestamp;
- frame_list_.erase(it);
- frame_list_.push_front(FrameData(total_bytes_read_, new_data, timestamp));
- break;
- }
- return true;
-}
-
-size_t QuicFrameList::Readv(const struct iovec* iov, size_t iov_len) {
- list<FrameData>::iterator it = frame_list_.begin();
- size_t iov_index = 0;
- size_t iov_offset = 0;
- size_t frame_offset = 0;
- QuicStreamOffset initial_bytes_consumed = total_bytes_read_;
-
- while (iov_index < iov_len && it != frame_list_.end() &&
- it->offset == total_bytes_read_) {
- int bytes_to_read = std::min(iov[iov_index].iov_len - iov_offset,
- it->segment.size() - frame_offset);
-
- char* iov_ptr = static_cast<char*>(iov[iov_index].iov_base) + iov_offset;
- memcpy(iov_ptr, it->segment.data() + frame_offset, bytes_to_read);
- frame_offset += bytes_to_read;
- iov_offset += bytes_to_read;
-
- if (iov[iov_index].iov_len == iov_offset) {
- // We've filled this buffer.
- iov_offset = 0;
- ++iov_index;
- }
- if (it->segment.size() == frame_offset) {
- // We've copied this whole frame
- total_bytes_read_ += it->segment.size();
- num_bytes_buffered_ -= it->segment.size();
- frame_list_.erase(it);
- it = frame_list_.begin();
- frame_offset = 0;
- }
- }
- // Done copying. If there is a partial frame, update it.
- if (frame_offset != 0) {
- frame_list_.push_front(FrameData(it->offset + frame_offset,
- it->segment.substr(frame_offset),
- it->timestamp));
- frame_list_.erase(it);
- total_bytes_read_ += frame_offset;
- num_bytes_buffered_ -= frame_offset;
- }
- return total_bytes_read_ - initial_bytes_consumed;
-}
-
-size_t QuicFrameList::FlushBufferedFrames() {
- QuicStreamOffset initial_bytes_consumed = total_bytes_read_;
- if (!frame_list_.empty()) {
- // Consume all of the bytes up to the last byte yet seen, including the
- // ones that haven't arrived yet.
- auto it = frame_list_.back();
- total_bytes_read_ = it.offset + it.segment.length();
- frame_list_.clear();
- }
- return total_bytes_read_ - initial_bytes_consumed;
-}
-
-bool QuicFrameList::HasBytesToRead() const {
- return !frame_list_.empty() &&
- frame_list_.begin()->offset == total_bytes_read_;
-}
-
-QuicStreamOffset QuicFrameList::BytesConsumed() const {
- return total_bytes_read_;
-}
-
-size_t QuicFrameList::BytesBuffered() const {
- return num_bytes_buffered_;
-}
-
-} // namespace net
diff --git a/chromium/net/quic/core/quic_frame_list.h b/chromium/net/quic/core/quic_frame_list.h
deleted file mode 100644
index 2e95455d2d7..00000000000
--- a/chromium/net/quic/core/quic_frame_list.h
+++ /dev/null
@@ -1,82 +0,0 @@
-// Copyright (c) 2015 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.
-
-#ifndef NET_QUIC_QUIC_FRAME_LIST_H_
-#define NET_QUIC_QUIC_FRAME_LIST_H_
-
-#include <stddef.h>
-#include <list>
-#include <string>
-
-#include "base/strings/string_piece.h"
-#include "net/base/net_export.h"
-#include "net/quic/core/quic_protocol.h"
-#include "net/quic/core/quic_stream_sequencer_buffer_interface.h"
-
-namespace net {
-
-namespace test {
-class QuicStreamSequencerPeer;
-}
-
-class NET_EXPORT_PRIVATE QuicFrameList
- : public QuicStreamSequencerBufferInterface {
- public:
- // A contiguous segment received by a QUIC stream.
- struct FrameData {
- FrameData(QuicStreamOffset offset,
- std::string segment,
- const QuicTime timestamp);
-
- const QuicStreamOffset offset;
- std::string segment;
- const QuicTime timestamp;
- };
-
- QuicFrameList();
-
- ~QuicFrameList() override;
-
- // QuicStreamSequencerBufferInterface implementation
- void Clear() override;
- bool Empty() const override;
- QuicErrorCode OnStreamData(QuicStreamOffset offset,
- base::StringPiece data,
- QuicTime timestamp,
- size_t* bytes_buffered) override;
- size_t Readv(const struct iovec* iov, size_t iov_len) override;
- int GetReadableRegions(struct iovec* iov, int iov_len) const override;
- bool GetReadableRegion(iovec* iov, QuicTime* timestamp) const override;
- bool MarkConsumed(size_t bytes_used) override;
- size_t FlushBufferedFrames() override;
- bool HasBytesToRead() const override;
- QuicStreamOffset BytesConsumed() const override;
- size_t BytesBuffered() const override;
-
- private:
- friend class test::QuicStreamSequencerPeer;
-
- std::list<FrameData>::iterator FindInsertionPoint(QuicStreamOffset offset,
- size_t len);
-
- bool FrameOverlapsBufferedData(
- QuicStreamOffset offset,
- size_t data_len,
- std::list<FrameData>::const_iterator insertion_point) const;
-
- bool IsDuplicate(QuicStreamOffset offset,
- size_t data_len,
- std::list<FrameData>::const_iterator insertion_point) const;
-
- std::list<FrameData> frame_list_;
-
- // Number of bytes in buffer.
- size_t num_bytes_buffered_ = 0;
-
- QuicStreamOffset total_bytes_read_ = 0;
-};
-
-} // namespace net
-
-#endif // NET_QUIC_QUIC_FRAME_LIST_H_
diff --git a/chromium/net/quic/core/quic_framer.cc b/chromium/net/quic/core/quic_framer.cc
index c1988023897..99c23b97d57 100644
--- a/chromium/net/quic/core/quic_framer.cc
+++ b/chromium/net/quic/core/quic_framer.cc
@@ -6,28 +6,28 @@
#include <cstdint>
#include <memory>
-#include <vector>
#include "base/compiler_specific.h"
-#include "base/logging.h"
-#include "base/memory/ptr_util.h"
#include "base/stl_util.h"
#include "net/quic/core/crypto/crypto_framer.h"
#include "net/quic/core/crypto/crypto_handshake_message.h"
#include "net/quic/core/crypto/crypto_protocol.h"
+#include "net/quic/core/crypto/null_decrypter.h"
+#include "net/quic/core/crypto/null_encrypter.h"
#include "net/quic/core/crypto/quic_decrypter.h"
#include "net/quic/core/crypto/quic_encrypter.h"
-#include "net/quic/core/quic_bug_tracker.h"
#include "net/quic/core/quic_data_reader.h"
#include "net/quic/core/quic_data_writer.h"
#include "net/quic/core/quic_flags.h"
#include "net/quic/core/quic_socket_address_coder.h"
#include "net/quic/core/quic_utils.h"
+#include "net/quic/platform/api/quic_aligned.h"
+#include "net/quic/platform/api/quic_bug_tracker.h"
+#include "net/quic/platform/api/quic_logging.h"
+#include "net/quic/platform/api/quic_ptr_util.h"
using base::ContainsKey;
using base::StringPiece;
-using std::max;
-using std::min;
using std::string;
#define PREDICT_FALSE(x) (x)
@@ -35,6 +35,9 @@ namespace net {
namespace {
+#define ENDPOINT \
+ (perspective_ == Perspective::IS_SERVER ? "Server: " : "Client: ")
+
// Mask to select the lowest 48 bits of a packet number.
const QuicPacketNumber k6ByteSequenceNumberMask = UINT64_C(0x0000FFFFFFFFFFFF);
const QuicPacketNumber k4ByteSequenceNumberMask = UINT64_C(0x00000000FFFFFFFF);
@@ -91,12 +94,6 @@ const uint8_t kQuicStreamFinMask = 0x01;
// packet number size shift used in AckFrames.
const uint8_t kQuicSequenceNumberLengthShift = 2;
-// Acks may be truncated.
-const uint8_t kQuicAckTruncatedShift = 1;
-const uint8_t kQuicAckTruncatedMask = 0x01;
-
-// Acks may not have any nacks.
-const uint8_t kQuicHasNacksMask = 0x01;
// Acks may have only one ack block.
const uint8_t kQuicHasMultipleAckBlocksMask = 0x01;
const uint8_t kQuicHasMultipleAckBlocksShift = 1;
@@ -138,7 +135,6 @@ QuicFramer::QuicFramer(const QuicVersionVector& supported_versions,
QuicTime creation_time,
Perspective perspective)
: visitor_(nullptr),
- entropy_calculator_(nullptr),
error_(QUIC_NO_ERROR),
last_packet_number_(0),
largest_packet_number_(0),
@@ -154,8 +150,8 @@ QuicFramer::QuicFramer(const QuicVersionVector& supported_versions,
last_timestamp_(QuicTime::Delta::Zero()) {
DCHECK(!supported_versions.empty());
quic_version_ = supported_versions_[0];
- decrypter_.reset(QuicDecrypter::Create(kNULL));
- encrypter_[ENCRYPTION_NONE].reset(QuicEncrypter::Create(kNULL));
+ decrypter_ = QuicMakeUnique<NullDecrypter>(perspective);
+ encrypter_[ENCRYPTION_NONE] = QuicMakeUnique<NullEncrypter>(perspective);
}
QuicFramer::~QuicFramer() {}
@@ -175,9 +171,6 @@ size_t QuicFramer::GetMinAckFrameSize(
QuicPacketNumberLength largest_observed_length) {
size_t min_size = kQuicFrameTypeSize + largest_observed_length +
kQuicDeltaTimeLargestObservedSize;
- if (version <= QUIC_VERSION_33) {
- return min_size + kQuicEntropyHashSize;
- }
return min_size + kQuicNumTimestampsSize;
}
@@ -186,9 +179,6 @@ size_t QuicFramer::GetStopWaitingFrameSize(
QuicVersion version,
QuicPacketNumberLength packet_number_length) {
size_t min_size = kQuicFrameTypeSize + packet_number_length;
- if (version <= QUIC_VERSION_33) {
- return min_size + kQuicEntropyHashSize;
- }
return min_size;
}
@@ -318,39 +308,20 @@ size_t QuicFramer::GetSerializedFrameLength(
if (can_truncate) {
// Truncate the frame so the packet will not exceed kMaxPacketSize.
// Note that we may not use every byte of the writer in this case.
- DVLOG(1) << "Truncating large frame, free bytes: " << free_bytes;
+ QUIC_DLOG(INFO) << ENDPOINT
+ << "Truncating large frame, free bytes: " << free_bytes;
return free_bytes;
}
return 0;
}
-QuicFramer::AckFrameInfo::AckFrameInfo() : max_delta(0) {}
+QuicFramer::AckFrameInfo::AckFrameInfo()
+ : max_block_length(0), first_block_length(0), num_ack_blocks(0) {}
QuicFramer::AckFrameInfo::AckFrameInfo(const AckFrameInfo& other) = default;
QuicFramer::AckFrameInfo::~AckFrameInfo() {}
-QuicFramer::AckBlock::AckBlock(uint8_t gap, QuicPacketNumber length)
- : gap(gap), length(length) {}
-
-QuicFramer::AckBlock::AckBlock(const AckBlock& other) = default;
-
-QuicFramer::AckBlock::~AckBlock() {}
-
-QuicFramer::NewAckFrameInfo::NewAckFrameInfo()
- : max_block_length(0), first_block_length(0), num_ack_blocks(0) {}
-
-QuicFramer::NewAckFrameInfo::NewAckFrameInfo(const NewAckFrameInfo& other) =
- default;
-
-QuicFramer::NewAckFrameInfo::~NewAckFrameInfo() {}
-
-// static
-QuicPacketEntropyHash QuicFramer::GetPacketEntropyHash(
- const QuicPacketHeader& header) {
- return header.entropy_flag << (header.packet_number % 8);
-}
-
size_t QuicFramer::BuildDataPacket(const QuicPacketHeader& header,
const QuicFrames& frames,
char* buffer,
@@ -382,18 +353,9 @@ size_t QuicFramer::BuildDataPacket(const QuicPacketHeader& header,
}
break;
case ACK_FRAME:
- if (quic_version_ <= QUIC_VERSION_33) {
- if (!AppendAckFrameAndTypeByte(header, *frame.ack_frame, &writer)) {
- QUIC_BUG << "AppendAckFrameAndTypeByte failed"
- << " header: " << header
- << " ack_fame: " << *frame.ack_frame;
- return 0;
- }
- } else {
- if (!AppendNewAckFrameAndTypeByte(*frame.ack_frame, &writer)) {
- QUIC_BUG << "AppendNewAckFrameAndTypeByte failed";
- return 0;
- }
+ if (!AppendAckFrameAndTypeByte(*frame.ack_frame, &writer)) {
+ QUIC_BUG << "AppendAckFrameAndTypeByte failed";
+ return 0;
}
break;
case STOP_WAITING_FRAME:
@@ -464,10 +426,11 @@ std::unique_ptr<QuicEncryptedPacket> QuicFramer::BuildPublicResetPacket(
CryptoHandshakeMessage reset;
reset.set_tag(kPRST);
reset.SetValue(kRNON, packet.nonce_proof);
- if (!FLAGS_quic_remove_packet_number_from_public_reset) {
+ if (!FLAGS_quic_reloadable_flag_quic_remove_packet_number_from_public_reset) {
reset.SetValue(kRSEQ, packet.rejected_packet_number);
}
- if (!packet.client_address.address().empty()) {
+ if (packet.client_address.host().address_family() !=
+ IpAddressFamily::IP_UNSPEC) {
// packet.client_address is non-empty.
QuicSocketAddressCoder address_coder(packet.client_address);
string serialized_address = address_coder.Encode();
@@ -485,7 +448,7 @@ std::unique_ptr<QuicEncryptedPacket> QuicFramer::BuildPublicResetPacket(
uint8_t flags = static_cast<uint8_t>(PACKET_PUBLIC_FLAGS_RST |
PACKET_PUBLIC_FLAGS_8BYTE_CONNECTION_ID);
- if (FLAGS_quic_use_old_public_reset_packets) {
+ if (FLAGS_quic_reloadable_flag_quic_use_old_public_reset_packets) {
// TODO(rch): Remove this QUIC_VERSION_32 is retired.
flags |= static_cast<uint8_t>(PACKET_PUBLIC_FLAGS_8BYTE_CONNECTION_ID_OLD);
}
@@ -501,7 +464,7 @@ std::unique_ptr<QuicEncryptedPacket> QuicFramer::BuildPublicResetPacket(
return nullptr;
}
- return base::MakeUnique<QuicEncryptedPacket>(buffer.release(), len, true);
+ return QuicMakeUnique<QuicEncryptedPacket>(buffer.release(), len, true);
}
// static
@@ -531,7 +494,7 @@ std::unique_ptr<QuicEncryptedPacket> QuicFramer::BuildVersionNegotiationPacket(
}
}
- return base::MakeUnique<QuicEncryptedPacket>(buffer.release(), len, true);
+ return QuicMakeUnique<QuicEncryptedPacket>(buffer.release(), len, true);
}
bool QuicFramer::ProcessPacket(const QuicEncryptedPacket& packet) {
@@ -542,7 +505,9 @@ bool QuicFramer::ProcessPacket(const QuicEncryptedPacket& packet) {
// First parse the public header.
QuicPacketPublicHeader public_header;
if (!ProcessPublicHeader(&reader, &public_header)) {
- DVLOG(1) << "Unable to process public header.";
+ DCHECK_NE("", detailed_error_);
+ QUIC_DVLOG(1) << ENDPOINT << "Unable to process public header. Error: "
+ << detailed_error_;
DCHECK_NE("", detailed_error_);
return RaiseError(QUIC_INVALID_PACKET_HEADER);
}
@@ -567,10 +532,7 @@ bool QuicFramer::ProcessPacket(const QuicEncryptedPacket& packet) {
} else if (packet.length() <= kMaxPacketSize) {
// The optimized decryption algorithm implementations run faster when
// operating on aligned memory.
- //
- // TODO(rtenneti): Change the default 64 alignas value (used the default
- // value from CACHELINE_SIZE).
- ALIGNAS(64) char buffer[kMaxPacketSize];
+ QUIC_CACHELINE_ALIGNED char buffer[kMaxPacketSize];
rv = ProcessDataPacket(&reader, public_header, packet, buffer,
kMaxPacketSize);
} else {
@@ -609,7 +571,11 @@ bool QuicFramer::ProcessDataPacket(QuicDataReader* encrypted_reader,
size_t buffer_length) {
QuicPacketHeader header(public_header);
if (!ProcessUnauthenticatedHeader(encrypted_reader, &header)) {
- DVLOG(1) << "Unable to process packet header. Stopping parsing.";
+ DCHECK_NE("", detailed_error_);
+ QUIC_DVLOG(1)
+ << ENDPOINT
+ << "Unable to process packet header. Stopping parsing. Error: "
+ << detailed_error_;
return false;
}
@@ -621,12 +587,6 @@ bool QuicFramer::ProcessDataPacket(QuicDataReader* encrypted_reader,
}
QuicDataReader reader(decrypted_buffer, decrypted_length);
- if (quic_version_ <= QUIC_VERSION_33) {
- if (!ProcessAuthenticatedHeader(&reader, &header)) {
- DVLOG(1) << "Unable to process packet header. Stopping parsing.";
- return false;
- }
- }
// Set the last packet number after we have decrypted the packet
// so we are confident is not attacker controlled.
@@ -646,7 +606,9 @@ bool QuicFramer::ProcessDataPacket(QuicDataReader* encrypted_reader,
// Handle the payload.
if (!ProcessFrameData(&reader, header)) {
DCHECK_NE(QUIC_NO_ERROR, error_); // ProcessFrameData sets the error.
- DLOG(WARNING) << "Unable to process frame data.";
+ DCHECK_NE("", detailed_error_);
+ QUIC_DLOG(WARNING) << ENDPOINT << "Unable to process frame data. Error: "
+ << detailed_error_;
return false;
}
@@ -681,7 +643,7 @@ bool QuicFramer::ProcessPublicResetPacket(
QuicSocketAddressCoder address_coder;
if (address_coder.Decode(address.data(), address.length())) {
packet.client_address =
- IPEndPoint(address_coder.ip(), address_coder.port());
+ QuicSocketAddress(address_coder.ip(), address_coder.port());
}
}
@@ -691,7 +653,7 @@ bool QuicFramer::ProcessPublicResetPacket(
bool QuicFramer::AppendPacketHeader(const QuicPacketHeader& header,
QuicDataWriter* writer) {
- DVLOG(1) << "Appending header: " << header;
+ QUIC_DVLOG(1) << ENDPOINT << "Appending header: " << header;
uint8_t public_flags = 0;
if (header.public_header.reset_flag) {
public_flags |= PACKET_PUBLIC_FLAGS_RST;
@@ -720,14 +682,9 @@ bool QuicFramer::AppendPacketHeader(const QuicPacketHeader& header,
}
break;
case PACKET_8BYTE_CONNECTION_ID:
- if (quic_version_ > QUIC_VERSION_32) {
- public_flags |= PACKET_PUBLIC_FLAGS_8BYTE_CONNECTION_ID;
- if (!FLAGS_quic_remove_v33_hacks2 &&
- perspective_ == Perspective::IS_CLIENT) {
- public_flags |= PACKET_PUBLIC_FLAGS_8BYTE_CONNECTION_ID_OLD;
- }
-
- } else {
+ public_flags |= PACKET_PUBLIC_FLAGS_8BYTE_CONNECTION_ID;
+ if (!FLAGS_quic_reloadable_flag_quic_remove_v33_hacks2 &&
+ perspective_ == Perspective::IS_CLIENT) {
public_flags |= PACKET_PUBLIC_FLAGS_8BYTE_CONNECTION_ID_OLD;
}
if (!writer->WriteUInt8(public_flags) ||
@@ -742,8 +699,8 @@ bool QuicFramer::AppendPacketHeader(const QuicPacketHeader& header,
DCHECK_EQ(Perspective::IS_CLIENT, perspective_);
QuicTag tag = QuicVersionToQuicTag(quic_version_);
writer->WriteUInt32(tag);
- DVLOG(1) << "version = " << quic_version_ << ", tag = '"
- << QuicUtils::TagToString(tag) << "'";
+ QUIC_DVLOG(1) << ENDPOINT << "version = " << quic_version_ << ", tag = '"
+ << QuicTagToString(tag) << "'";
}
if (header.public_header.multipath_flag &&
@@ -761,17 +718,6 @@ bool QuicFramer::AppendPacketHeader(const QuicPacketHeader& header,
header.packet_number, writer)) {
return false;
}
- if (quic_version_ > QUIC_VERSION_33) {
- return true;
- }
-
- uint8_t private_flags = 0;
- if (header.entropy_flag) {
- private_flags |= PACKET_PRIVATE_FLAGS_ENTROPY;
- }
- if (!writer->WriteUInt8(private_flags)) {
- return false;
- }
return true;
}
@@ -830,7 +776,8 @@ void QuicFramer::SetLastPacketNumber(const QuicPacketHeader& header) {
last_path_id_ = header.path_id;
}
last_packet_number_ = header.packet_number;
- largest_packet_number_ = max(header.packet_number, largest_packet_number_);
+ largest_packet_number_ =
+ std::max(header.packet_number, largest_packet_number_);
}
void QuicFramer::OnPathClosed(QuicPathId path_id) {
@@ -926,12 +873,8 @@ bool QuicFramer::ProcessPublicHeader(QuicDataReader* reader,
}
// A nonce should only be present in packets from the server to the client,
- // which are neither version negotiation nor public reset packets
- // and only for versions after QUIC_VERSION_32. Earlier versions will
- // set this bit when indicating an 8-byte connection ID, which should
- // not be interpreted as indicating a nonce is present.
- if (quic_version_ > QUIC_VERSION_32 &&
- public_flags & PACKET_PUBLIC_FLAGS_NONCE &&
+ // which are neither version negotiation nor public reset packets.
+ if (public_flags & PACKET_PUBLIC_FLAGS_NONCE &&
!(public_flags & PACKET_PUBLIC_FLAGS_VERSION) &&
!(public_flags & PACKET_PUBLIC_FLAGS_RST) &&
// The nonce flag from a client is ignored and is assumed to be an older
@@ -985,38 +928,7 @@ uint8_t QuicFramer::GetSequenceNumberFlags(
// static
QuicFramer::AckFrameInfo QuicFramer::GetAckFrameInfo(
const QuicAckFrame& frame) {
- AckFrameInfo ack_info;
- if (frame.packets.Empty()) {
- return ack_info;
- }
- DCHECK_GE(frame.largest_observed, frame.packets.Max());
- QuicPacketNumber last_largest_missing = 0;
- for (const Interval<QuicPacketNumber>& interval : frame.packets) {
- for (QuicPacketNumber interval_start = interval.min();
- interval_start < interval.max();
- interval_start += (1ull + std::numeric_limits<uint8_t>::max())) {
- uint8_t cur_range_length =
- interval.max() - interval_start > std::numeric_limits<uint8_t>::max()
- ? std::numeric_limits<uint8_t>::max()
- : (interval.max() - interval_start) - 1;
- ack_info.nack_ranges[interval_start] = cur_range_length;
- }
- ack_info.max_delta =
- max(ack_info.max_delta, last_largest_missing == 0
- ? QuicPacketNumber{0}
- : (interval.min() - last_largest_missing));
- last_largest_missing = interval.max() - 1;
- }
- // Include the range to the largest observed.
- ack_info.max_delta =
- max(ack_info.max_delta, frame.largest_observed - last_largest_missing);
- return ack_info;
-}
-
-// static
-QuicFramer::NewAckFrameInfo QuicFramer::GetNewAckFrameInfo(
- const QuicAckFrame& frame) {
- NewAckFrameInfo new_ack_info;
+ AckFrameInfo new_ack_info;
if (frame.packets.Empty()) {
return new_ack_info;
}
@@ -1039,7 +951,7 @@ QuicFramer::NewAckFrameInfo QuicFramer::GetNewAckFrameInfo(
(total_gap + std::numeric_limits<uint8_t>::max() - 1) /
std::numeric_limits<uint8_t>::max();
new_ack_info.max_block_length =
- max(new_ack_info.max_block_length, interval.Length());
+ std::max(new_ack_info.max_block_length, interval.Length());
}
return new_ack_info;
}
@@ -1057,6 +969,7 @@ bool QuicFramer::ProcessUnauthenticatedHeader(QuicDataReader* encrypted_reader,
if (header->public_header.multipath_flag &&
!IsValidPath(header->path_id, &base_packet_number)) {
// Stop processing because path is closed.
+ set_detailed_error("Path is closed.");
return false;
}
@@ -1073,29 +986,13 @@ bool QuicFramer::ProcessUnauthenticatedHeader(QuicDataReader* encrypted_reader,
}
if (!visitor_->OnUnauthenticatedHeader(*header)) {
+ set_detailed_error(
+ "Visitor asked to stop processing of unauthenticated header.");
return false;
}
return true;
}
-bool QuicFramer::ProcessAuthenticatedHeader(QuicDataReader* reader,
- QuicPacketHeader* header) {
- uint8_t private_flags;
- if (!reader->ReadBytes(&private_flags, 1)) {
- set_detailed_error("Unable to read private flags.");
- return RaiseError(QUIC_INVALID_PACKET_HEADER);
- }
-
- if (private_flags > PACKET_PRIVATE_FLAGS_MAX) {
- set_detailed_error("Illegal private flags value.");
- return RaiseError(QUIC_INVALID_PACKET_HEADER);
- }
-
- header->entropy_flag = (private_flags & PACKET_PRIVATE_FLAGS_ENTROPY) != 0;
- header->entropy_hash = GetPacketEntropyHash(*header);
- return true;
-}
-
bool QuicFramer::ProcessPathId(QuicDataReader* reader, QuicPathId* path_id) {
if (!reader->ReadBytes(path_id, 1)) {
return false;
@@ -1142,7 +1039,8 @@ bool QuicFramer::ProcessFrameData(QuicDataReader* reader,
return RaiseError(QUIC_INVALID_STREAM_DATA);
}
if (!visitor_->OnStreamFrame(frame)) {
- DVLOG(1) << "Visitor asked to stop further processing.";
+ QUIC_DVLOG(1) << ENDPOINT
+ << "Visitor asked to stop further processing.";
// Returning true since there was no parsing error.
return true;
}
@@ -1152,17 +1050,12 @@ bool QuicFramer::ProcessFrameData(QuicDataReader* reader,
// Ack Frame
if (frame_type & kQuicFrameTypeAckMask) {
QuicAckFrame frame;
- if (quic_version_ <= QUIC_VERSION_33) {
- if (!ProcessAckFrame(reader, frame_type, &frame)) {
- return RaiseError(QUIC_INVALID_ACK_DATA);
- }
- } else {
- if (!ProcessNewAckFrame(reader, frame_type, &frame)) {
- return RaiseError(QUIC_INVALID_ACK_DATA);
- }
+ if (!ProcessAckFrame(reader, frame_type, &frame)) {
+ return RaiseError(QUIC_INVALID_ACK_DATA);
}
if (!visitor_->OnAckFrame(frame)) {
- DVLOG(1) << "Visitor asked to stop further processing.";
+ QUIC_DVLOG(1) << ENDPOINT
+ << "Visitor asked to stop further processing.";
// Returning true since there was no parsing error.
return true;
}
@@ -1172,7 +1065,8 @@ bool QuicFramer::ProcessFrameData(QuicDataReader* reader,
// This was a special frame type that did not match any
// of the known ones. Error.
set_detailed_error("Illegal frame type.");
- DLOG(WARNING) << "Illegal frame type: " << static_cast<int>(frame_type);
+ QUIC_DLOG(WARNING) << ENDPOINT << "Illegal frame type: "
+ << static_cast<int>(frame_type);
return RaiseError(QUIC_INVALID_FRAME_DATA);
}
@@ -1180,7 +1074,7 @@ bool QuicFramer::ProcessFrameData(QuicDataReader* reader,
case PADDING_FRAME: {
QuicPaddingFrame frame(reader->BytesRemaining());
if (!visitor_->OnPaddingFrame(frame)) {
- DVLOG(1) << "Visitor asked to stop further processing.";
+ QUIC_DVLOG(1) << "Visitor asked to stop further processing.";
}
// We're done with the packet.
return true;
@@ -1192,7 +1086,7 @@ bool QuicFramer::ProcessFrameData(QuicDataReader* reader,
return RaiseError(QUIC_INVALID_RST_STREAM_DATA);
}
if (!visitor_->OnRstStreamFrame(frame)) {
- DVLOG(1) << "Visitor asked to stop further processing.";
+ QUIC_DVLOG(1) << "Visitor asked to stop further processing.";
// Returning true since there was no parsing error.
return true;
}
@@ -1206,7 +1100,8 @@ bool QuicFramer::ProcessFrameData(QuicDataReader* reader,
}
if (!visitor_->OnConnectionCloseFrame(frame)) {
- DVLOG(1) << "Visitor asked to stop further processing.";
+ QUIC_DVLOG(1) << ENDPOINT
+ << "Visitor asked to stop further processing.";
// Returning true since there was no parsing error.
return true;
}
@@ -1219,7 +1114,8 @@ bool QuicFramer::ProcessFrameData(QuicDataReader* reader,
return RaiseError(QUIC_INVALID_GOAWAY_DATA);
}
if (!visitor_->OnGoAwayFrame(goaway_frame)) {
- DVLOG(1) << "Visitor asked to stop further processing.";
+ QUIC_DVLOG(1) << ENDPOINT
+ << "Visitor asked to stop further processing.";
// Returning true since there was no parsing error.
return true;
}
@@ -1232,7 +1128,8 @@ bool QuicFramer::ProcessFrameData(QuicDataReader* reader,
return RaiseError(QUIC_INVALID_WINDOW_UPDATE_DATA);
}
if (!visitor_->OnWindowUpdateFrame(window_update_frame)) {
- DVLOG(1) << "Visitor asked to stop further processing.";
+ QUIC_DVLOG(1) << ENDPOINT
+ << "Visitor asked to stop further processing.";
// Returning true since there was no parsing error.
return true;
}
@@ -1245,7 +1142,8 @@ bool QuicFramer::ProcessFrameData(QuicDataReader* reader,
return RaiseError(QUIC_INVALID_BLOCKED_DATA);
}
if (!visitor_->OnBlockedFrame(blocked_frame)) {
- DVLOG(1) << "Visitor asked to stop further processing.";
+ QUIC_DVLOG(1) << ENDPOINT
+ << "Visitor asked to stop further processing.";
// Returning true since there was no parsing error.
return true;
}
@@ -1258,7 +1156,8 @@ bool QuicFramer::ProcessFrameData(QuicDataReader* reader,
return RaiseError(QUIC_INVALID_STOP_WAITING_DATA);
}
if (!visitor_->OnStopWaitingFrame(stop_waiting_frame)) {
- DVLOG(1) << "Visitor asked to stop further processing.";
+ QUIC_DVLOG(1) << ENDPOINT
+ << "Visitor asked to stop further processing.";
// Returning true since there was no parsing error.
return true;
}
@@ -1268,7 +1167,8 @@ bool QuicFramer::ProcessFrameData(QuicDataReader* reader,
// Ping has no payload.
QuicPingFrame ping_frame;
if (!visitor_->OnPingFrame(ping_frame)) {
- DVLOG(1) << "Visitor asked to stop further processing.";
+ QUIC_DVLOG(1) << ENDPOINT
+ << "Visitor asked to stop further processing.";
// Returning true since there was no parsing error.
return true;
}
@@ -1280,7 +1180,8 @@ bool QuicFramer::ProcessFrameData(QuicDataReader* reader,
return RaiseError(QUIC_INVALID_PATH_CLOSE_DATA);
}
if (!visitor_->OnPathCloseFrame(path_close_frame)) {
- DVLOG(1) << "Visitor asked to stop further processing.";
+ QUIC_DVLOG(1) << ENDPOINT
+ << "Visitor asked to stop further processing.";
// Returning true since there was no parsing error.
return true;
}
@@ -1289,7 +1190,8 @@ bool QuicFramer::ProcessFrameData(QuicDataReader* reader,
default:
set_detailed_error("Illegal frame type.");
- DLOG(WARNING) << "Illegal frame type: " << static_cast<int>(frame_type);
+ QUIC_DLOG(WARNING) << ENDPOINT << "Illegal frame type: "
+ << static_cast<int>(frame_type);
return RaiseError(QUIC_INVALID_FRAME_DATA);
}
}
@@ -1355,83 +1257,6 @@ bool QuicFramer::ProcessStreamFrame(QuicDataReader* reader,
bool QuicFramer::ProcessAckFrame(QuicDataReader* reader,
uint8_t frame_type,
QuicAckFrame* ack_frame) {
- // Determine the three lengths from the frame type: largest observed length,
- // missing packet number length, and missing range length.
- const QuicPacketNumberLength missing_packet_number_length =
- ReadSequenceNumberLength(frame_type);
- frame_type >>= kQuicSequenceNumberLengthShift;
- const QuicPacketNumberLength largest_observed_packet_number_length =
- ReadSequenceNumberLength(frame_type);
- frame_type >>= kQuicSequenceNumberLengthShift;
- ack_frame->is_truncated = frame_type & kQuicAckTruncatedMask;
- frame_type >>= kQuicAckTruncatedShift;
- bool has_nacks = frame_type & kQuicHasNacksMask;
-
- if (!reader->ReadBytes(&ack_frame->entropy_hash, 1)) {
- set_detailed_error("Unable to read entropy hash for received packets.");
- return false;
- }
-
- if (!reader->ReadBytes(&ack_frame->largest_observed,
- largest_observed_packet_number_length)) {
- set_detailed_error("Unable to read largest observed.");
- return false;
- }
-
- uint64_t ack_delay_time_us;
- if (!reader->ReadUFloat16(&ack_delay_time_us)) {
- set_detailed_error("Unable to read ack delay time.");
- return false;
- }
-
- if (ack_delay_time_us == kUFloat16MaxValue) {
- ack_frame->ack_delay_time = QuicTime::Delta::Infinite();
- } else {
- ack_frame->ack_delay_time =
- QuicTime::Delta::FromMicroseconds(ack_delay_time_us);
- }
-
- if (!ProcessTimestampsInAckFrame(reader, ack_frame)) {
- return false;
- }
-
- if (!has_nacks) {
- return true;
- }
-
- uint8_t num_missing_ranges;
- if (!reader->ReadBytes(&num_missing_ranges, 1)) {
- set_detailed_error("Unable to read num missing packet ranges.");
- return false;
- }
-
- QuicPacketNumber last_packet_number = ack_frame->largest_observed;
- for (size_t i = 0; i < num_missing_ranges; ++i) {
- QuicPacketNumber missing_delta = 0;
- if (!reader->ReadBytes(&missing_delta, missing_packet_number_length)) {
- set_detailed_error("Unable to read missing packet number delta.");
- return false;
- }
- last_packet_number -= missing_delta;
- QuicPacketNumber range_length = 0;
- if (!reader->ReadBytes(&range_length, PACKET_1BYTE_PACKET_NUMBER)) {
- set_detailed_error("Unable to read missing packet number range.");
- return false;
- }
- ack_frame->packets.Add(last_packet_number - range_length,
- last_packet_number + 1);
- // Subtract an extra 1 to ensure ranges are represented efficiently and
- // can't overlap by 1 packet number. This allows a missing_delta of 0
- // to represent an adjacent nack range.
- last_packet_number -= (range_length + 1);
- }
-
- return true;
-}
-
-bool QuicFramer::ProcessNewAckFrame(QuicDataReader* reader,
- uint8_t frame_type,
- QuicAckFrame* ack_frame) {
// Determine the two lengths from the frame type: largest acked length,
// ack block length.
const QuicPacketNumberLength ack_block_length =
@@ -1442,7 +1267,6 @@ bool QuicFramer::ProcessNewAckFrame(QuicDataReader* reader,
frame_type >>= kQuicSequenceNumberLengthShift;
frame_type >>= kQuicHasMultipleAckBlocksShift;
bool has_ack_blocks = frame_type & kQuicHasMultipleAckBlocksMask;
- ack_frame->missing = false;
if (!reader->ReadBytes(&ack_frame->largest_observed, largest_acked_length)) {
set_detailed_error("Unable to read largest acked.");
@@ -1508,9 +1332,6 @@ bool QuicFramer::ProcessNewAckFrame(QuicDataReader* reader,
bool QuicFramer::ProcessTimestampsInAckFrame(QuicDataReader* reader,
QuicAckFrame* ack_frame) {
- if (ack_frame->is_truncated) {
- return true;
- }
uint8_t num_received_packets;
if (!reader->ReadBytes(&num_received_packets, 1)) {
set_detailed_error("Unable to read num received packets.");
@@ -1569,13 +1390,6 @@ bool QuicFramer::ProcessTimestampsInAckFrame(QuicDataReader* reader,
bool QuicFramer::ProcessStopWaitingFrame(QuicDataReader* reader,
const QuicPacketHeader& header,
QuicStopWaitingFrame* stop_waiting) {
- if (quic_version_ <= QUIC_VERSION_33) {
- if (!reader->ReadBytes(&stop_waiting->entropy_hash, 1)) {
- set_detailed_error("Unable to read entropy hash for sent packets.");
- return false;
- }
- }
-
QuicPacketNumber least_unacked_delta = 0;
if (!reader->ReadBytes(&least_unacked_delta,
header.public_header.packet_number_length)) {
@@ -1761,7 +1575,7 @@ size_t QuicFramer::EncryptInPlace(EncryptionLevel level,
char* buffer) {
size_t output_length = 0;
if (!encrypter_[level]->EncryptPacket(
- path_id, packet_number,
+ quic_version_, path_id, packet_number,
StringPiece(buffer, ad_len), // Associated data
StringPiece(buffer + ad_len, total_len - ad_len), // Plaintext
buffer + ad_len, // Destination buffer
@@ -1788,10 +1602,10 @@ size_t QuicFramer::EncryptPayload(EncryptionLevel level,
memmove(buffer, associated_data.data(), ad_len);
// Encrypt the plaintext into the buffer.
size_t output_length = 0;
- if (!encrypter_[level]->EncryptPacket(path_id, packet_number, associated_data,
- packet.Plaintext(quic_version_),
- buffer + ad_len, &output_length,
- buffer_len - ad_len)) {
+ if (!encrypter_[level]->EncryptPacket(
+ quic_version_, path_id, packet_number, associated_data,
+ packet.Plaintext(quic_version_), buffer + ad_len, &output_length,
+ buffer_len - ad_len)) {
RaiseError(QUIC_ENCRYPTION_FAILURE);
return 0;
}
@@ -1831,8 +1645,8 @@ bool QuicFramer::DecryptPayload(QuicDataReader* encrypted_reader,
header.public_header.packet_number_length);
bool success = decrypter_->DecryptPacket(
- header.path_id, header.packet_number, associated_data, encrypted,
- decrypted_buffer, decrypted_length, buffer_length);
+ quic_version_, header.path_id, header.packet_number, associated_data,
+ encrypted, decrypted_buffer, decrypted_length, buffer_length);
if (success) {
visitor_->OnDecryptedPacket(decrypter_level_);
} else if (alternative_decrypter_.get() != nullptr) {
@@ -1843,8 +1657,7 @@ bool QuicFramer::DecryptPayload(QuicDataReader* encrypted_reader,
}
bool try_alternative_decryption = true;
if (alternative_decrypter_level_ == ENCRYPTION_INITIAL) {
- if (perspective_ == Perspective::IS_CLIENT &&
- quic_version_ > QUIC_VERSION_32) {
+ if (perspective_ == Perspective::IS_CLIENT) {
if (header.public_header.nonce == nullptr) {
// Can not use INITIAL decryption without a diversification nonce.
try_alternative_decryption = false;
@@ -1856,15 +1669,15 @@ bool QuicFramer::DecryptPayload(QuicDataReader* encrypted_reader,
if (try_alternative_decryption) {
success = alternative_decrypter_->DecryptPacket(
- header.path_id, header.packet_number, associated_data, encrypted,
- decrypted_buffer, decrypted_length, buffer_length);
+ quic_version_, header.path_id, header.packet_number, associated_data,
+ encrypted, decrypted_buffer, decrypted_length, buffer_length);
}
if (success) {
visitor_->OnDecryptedPacket(alternative_decrypter_level_);
if (alternative_decrypter_latch_) {
// Switch to the alternative decrypter and latch so that we cannot
// switch back.
- decrypter_.reset(alternative_decrypter_.release());
+ decrypter_ = std::move(alternative_decrypter_);
decrypter_level_ = alternative_decrypter_level_;
alternative_decrypter_level_ = ENCRYPTION_NONE;
} else {
@@ -1878,8 +1691,8 @@ bool QuicFramer::DecryptPayload(QuicDataReader* encrypted_reader,
}
if (!success) {
- DVLOG(1) << "DecryptPacket failed for packet_number:"
- << header.packet_number;
+ QUIC_DVLOG(1) << ENDPOINT << "DecryptPacket failed for packet_number:"
+ << header.packet_number;
return false;
}
@@ -1898,32 +1711,8 @@ size_t QuicFramer::GetAckFrameSize(
const QuicAckFrame& ack,
QuicPacketNumberLength packet_number_length) {
size_t ack_size = 0;
- if (quic_version_ <= QUIC_VERSION_33) {
- AckFrameInfo ack_info = GetAckFrameInfo(ack);
- QuicPacketNumberLength largest_observed_length =
- GetMinSequenceNumberLength(ack.largest_observed);
- QuicPacketNumberLength missing_packet_number_length =
- GetMinSequenceNumberLength(ack_info.max_delta);
-
- ack_size = GetMinAckFrameSize(quic_version_, largest_observed_length);
- if (!ack_info.nack_ranges.empty()) {
- ack_size += kNumberOfNackRangesSize;
- ack_size += min(ack_info.nack_ranges.size(), kMaxNackRanges) *
- (missing_packet_number_length + PACKET_1BYTE_PACKET_NUMBER);
- }
-
- // In version 23, if the ack will be truncated due to too many nack ranges,
- // then do not include the number of timestamps (1 byte).
- if (ack_info.nack_ranges.size() <= kMaxNackRanges) {
- // 1 byte for the number of timestamps.
- ack_size += 1;
- ack_size += GetAckFrameTimeStampSize(ack);
- }
-
- return ack_size;
- }
- NewAckFrameInfo ack_info = GetNewAckFrameInfo(ack);
+ AckFrameInfo ack_info = GetAckFrameInfo(ack);
QuicPacketNumberLength largest_acked_length =
GetMinSequenceNumberLength(ack.largest_observed);
QuicPacketNumberLength ack_block_length =
@@ -1934,7 +1723,7 @@ size_t QuicFramer::GetAckFrameSize(
ack_size += ack_block_length;
if (ack_info.num_ack_blocks != 0) {
ack_size += kNumberOfAckBlocksSize;
- ack_size += min(ack_info.num_ack_blocks, kMaxAckBlocks) *
+ ack_size += std::min(ack_info.num_ack_blocks, kMaxAckBlocks) *
(ack_block_length + PACKET_1BYTE_PACKET_NUMBER);
}
@@ -2101,144 +1890,9 @@ void QuicFramer::set_version(const QuicVersion version) {
quic_version_ = version;
}
-bool QuicFramer::AppendAckFrameAndTypeByte(const QuicPacketHeader& header,
- const QuicAckFrame& frame,
+bool QuicFramer::AppendAckFrameAndTypeByte(const QuicAckFrame& frame,
QuicDataWriter* writer) {
- AckFrameInfo ack_info = GetAckFrameInfo(frame);
- QuicPacketNumber ack_largest_observed = frame.largest_observed;
- QuicPacketNumberLength largest_observed_length =
- GetMinSequenceNumberLength(ack_largest_observed);
- QuicPacketNumberLength missing_packet_number_length =
- GetMinSequenceNumberLength(ack_info.max_delta);
- // Determine whether we need to truncate ranges.
- size_t available_range_bytes =
- writer->capacity() - writer->length() - kNumberOfNackRangesSize -
- GetMinAckFrameSize(quic_version_, largest_observed_length);
- size_t max_num_ranges =
- available_range_bytes /
- (missing_packet_number_length + PACKET_1BYTE_PACKET_NUMBER);
- max_num_ranges = min(kMaxNackRanges, max_num_ranges);
- bool truncated = ack_info.nack_ranges.size() > max_num_ranges;
- DVLOG_IF(1, truncated) << "Truncating ack from "
- << ack_info.nack_ranges.size() << " ranges to "
- << max_num_ranges;
- // Write out the type byte by setting the low order bits and doing shifts
- // to make room for the next bit flags to be set.
- // Whether there are any nacks.
- uint8_t type_byte = ack_info.nack_ranges.empty() ? 0 : kQuicHasNacksMask;
-
- // truncating bit.
- type_byte <<= kQuicAckTruncatedShift;
- type_byte |= truncated ? kQuicAckTruncatedMask : 0;
-
- // Largest observed packet number length.
- type_byte <<= kQuicSequenceNumberLengthShift;
- type_byte |= GetSequenceNumberFlags(largest_observed_length);
-
- // Missing packet number length.
- type_byte <<= kQuicSequenceNumberLengthShift;
- type_byte |= GetSequenceNumberFlags(missing_packet_number_length);
-
- type_byte |= kQuicFrameTypeAckMask;
-
- if (!writer->WriteUInt8(type_byte)) {
- QUIC_BUG << "type byte failed";
- return false;
- }
-
- QuicPacketEntropyHash ack_entropy_hash = frame.entropy_hash;
- NackRangeMap::reverse_iterator ack_iter = ack_info.nack_ranges.rbegin();
- if (truncated) {
- // Skip the nack ranges which the truncated ack won't include and set
- // a correct largest observed for the truncated ack.
- for (size_t i = 1; i < (ack_info.nack_ranges.size() - max_num_ranges);
- ++i) {
- ++ack_iter;
- }
- // If the last range is followed by acks, include them.
- // If the last range is followed by another range, specify the end of the
- // range as the largest_observed.
- ack_largest_observed = ack_iter->first - 1;
- // Also update the entropy so it matches the largest observed.
- ack_entropy_hash = entropy_calculator_->EntropyHash(ack_largest_observed);
- ++ack_iter;
- }
-
- if (!writer->WriteUInt8(ack_entropy_hash)) {
- QUIC_BUG << "hash failed.";
- return false;
- }
-
- if (!AppendPacketSequenceNumber(largest_observed_length, ack_largest_observed,
- writer)) {
- QUIC_BUG << "AppendPacketSequenceNumber failed. "
- << "largest_observed_length: " << largest_observed_length
- << " ack_largest_observed: " << ack_largest_observed;
- return false;
- }
-
- uint64_t ack_delay_time_us = kUFloat16MaxValue;
- if (!frame.ack_delay_time.IsInfinite()) {
- DCHECK_LE(0u, frame.ack_delay_time.ToMicroseconds());
- ack_delay_time_us = frame.ack_delay_time.ToMicroseconds();
- }
-
- if (!writer->WriteUFloat16(ack_delay_time_us)) {
- QUIC_BUG << "ack delay time failed.";
- return false;
- }
-
- // Timestamp goes at the end of the required fields.
- if (!truncated) {
- if (!AppendTimestampToAckFrame(frame, writer)) {
- QUIC_BUG << "AppendTimestampToAckFrame failed";
- return false;
- }
- }
-
- if (ack_info.nack_ranges.empty()) {
- return true;
- }
-
- const uint8_t num_missing_ranges =
- static_cast<uint8_t>(min(ack_info.nack_ranges.size(), max_num_ranges));
- if (!writer->WriteBytes(&num_missing_ranges, 1)) {
- QUIC_BUG << "num_missing_ranges failed: "
- << static_cast<uint32_t>(num_missing_ranges);
- return false;
- }
-
- int num_ranges_written = 0;
- QuicPacketNumber last_sequence_written = ack_largest_observed;
- for (; ack_iter != ack_info.nack_ranges.rend(); ++ack_iter) {
- // Calculate the delta to the last number in the range.
- QuicPacketNumber missing_delta =
- last_sequence_written - (ack_iter->first + ack_iter->second);
- if (!AppendPacketSequenceNumber(missing_packet_number_length, missing_delta,
- writer)) {
- QUIC_BUG << "AppendPacketSequenceNumber failed: "
- << "missing_packet_number_length: "
- << missing_packet_number_length << " missing_delta "
- << missing_delta;
- return false;
- }
- if (!AppendPacketSequenceNumber(PACKET_1BYTE_PACKET_NUMBER,
- ack_iter->second, writer)) {
- QUIC_BUG << "AppendPacketSequenceNumber failed";
- return false;
- }
- // Subtract 1 so a missing_delta of 0 means an adjacent range.
- last_sequence_written = ack_iter->first - 1;
- ++num_ranges_written;
- }
- DCHECK_EQ(num_missing_ranges, num_ranges_written);
-
- return true;
-}
-
-bool QuicFramer::AppendNewAckFrameAndTypeByte(const QuicAckFrame& frame,
- QuicDataWriter* writer) {
- const NewAckFrameInfo new_ack_info = GetNewAckFrameInfo(frame);
+ const AckFrameInfo new_ack_info = GetAckFrameInfo(frame);
QuicPacketNumber largest_acked = frame.largest_observed;
QuicPacketNumberLength largest_acked_length =
GetMinSequenceNumberLength(largest_acked);
@@ -2292,7 +1946,8 @@ bool QuicFramer::AppendNewAckFrameAndTypeByte(const QuicAckFrame& frame,
(ack_block_length + PACKET_1BYTE_PACKET_NUMBER);
// Number of ack blocks.
- size_t num_ack_blocks = min(new_ack_info.num_ack_blocks, max_num_ack_blocks);
+ size_t num_ack_blocks =
+ std::min(new_ack_info.num_ack_blocks, max_num_ack_blocks);
if (num_ack_blocks > std::numeric_limits<uint8_t>::max()) {
num_ack_blocks = std::numeric_limits<uint8_t>::max();
}
@@ -2332,7 +1987,7 @@ bool QuicFramer::AppendNewAckFrameAndTypeByte(const QuicAckFrame& frame,
const size_t num_encoded_gaps =
(total_gap + std::numeric_limits<uint8_t>::max() - 1) /
std::numeric_limits<uint8_t>::max();
- DCHECK_GT(num_encoded_gaps, 0u);
+ DCHECK_LE(0u, num_encoded_gaps);
// Append empty ACK blocks because the gap is longer than a single gap.
for (size_t i = 1;
@@ -2457,12 +2112,6 @@ bool QuicFramer::AppendStopWaitingFrame(const QuicPacketHeader& header,
header.packet_number - frame.least_unacked;
const QuicPacketNumber length_shift =
header.public_header.packet_number_length * 8;
- if (quic_version_ <= QUIC_VERSION_33) {
- if (!writer->WriteUInt8(frame.entropy_hash)) {
- QUIC_BUG << " hash failed";
- return false;
- }
- }
if (least_unacked_delta >> length_shift > 0) {
QUIC_BUG << "packet_number_length "
@@ -2560,8 +2209,8 @@ bool QuicFramer::AppendPathCloseFrame(const QuicPathCloseFrame& frame,
}
bool QuicFramer::RaiseError(QuicErrorCode error) {
- DVLOG(1) << "Error: " << QuicUtils::ErrorToString(error)
- << " detail: " << detailed_error_;
+ QUIC_DLOG(INFO) << ENDPOINT << "Error: " << QuicErrorCodeToString(error)
+ << " detail: " << detailed_error_;
set_error(error);
visitor_->OnError(this);
return false;
diff --git a/chromium/net/quic/core/quic_framer.h b/chromium/net/quic/core/quic_framer.h
index 1f160f7c3c1..a40b211690f 100644
--- a/chromium/net/quic/core/quic_framer.h
+++ b/chromium/net/quic/core/quic_framer.h
@@ -2,23 +2,20 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#ifndef NET_QUIC_QUIC_FRAMER_H_
-#define NET_QUIC_QUIC_FRAMER_H_
-
-#include <stddef.h>
-#include <stdint.h>
+#ifndef NET_QUIC_CORE_QUIC_FRAMER_H_
+#define NET_QUIC_CORE_QUIC_FRAMER_H_
+#include <cstddef>
+#include <cstdint>
#include <memory>
#include <string>
#include <unordered_map>
#include <unordered_set>
-#include <vector>
-#include "base/logging.h"
#include "base/macros.h"
#include "base/strings/string_piece.h"
-#include "net/base/net_export.h"
-#include "net/quic/core/quic_protocol.h"
+#include "net/quic/core/quic_packets.h"
+#include "net/quic/platform/api/quic_export.h"
namespace net {
@@ -46,8 +43,6 @@ const size_t kQuicMaxStreamOffsetSize = 8;
// Number of bytes reserved to store payload length in stream frame.
const size_t kQuicStreamPayloadLengthSize = 2;
-// Size in bytes of the entropy hash sent in ack frames.
-const size_t kQuicEntropyHashSize = 1;
// Size in bytes reserved for the delta time of the largest observed
// packet number in ack frames.
const size_t kQuicDeltaTimeLargestObservedSize = 2;
@@ -64,7 +59,7 @@ const size_t kMaxAckBlocks = (1 << (kNumberOfAckBlocksSize * 8)) - 1;
// This class receives callbacks from the framer when packets
// are processed.
-class NET_EXPORT_PRIVATE QuicFramerVisitorInterface {
+class QUIC_EXPORT_PRIVATE QuicFramerVisitorInterface {
public:
virtual ~QuicFramerVisitorInterface() {}
@@ -148,24 +143,9 @@ class NET_EXPORT_PRIVATE QuicFramerVisitorInterface {
virtual void OnPacketComplete() = 0;
};
-// This class calculates the received entropy of the ack packet being
-// framed, should it get truncated.
-class NET_EXPORT_PRIVATE QuicReceivedEntropyHashCalculatorInterface {
- public:
- virtual ~QuicReceivedEntropyHashCalculatorInterface() {}
-
- // When an ack frame gets truncated while being framed the received
- // entropy of the ack frame needs to be calculated since the some of the
- // missing packets are not added and the largest observed might be lowered.
- // This should return the received entropy hash of the packets received up to
- // and including |packet_number|.
- virtual QuicPacketEntropyHash EntropyHash(
- QuicPacketNumber packet_number) const = 0;
-};
-
// Class for parsing and constructing QUIC packets. It has a
// QuicFramerVisitorInterface that is called when packets are parsed.
-class NET_EXPORT_PRIVATE QuicFramer {
+class QUIC_EXPORT_PRIVATE QuicFramer {
public:
// Constructs a new framer that installs a kNULL QuicEncrypter and
// QuicDecrypter for level ENCRYPTION_NONE. |supported_versions| specifies the
@@ -200,15 +180,6 @@ class NET_EXPORT_PRIVATE QuicFramer {
quic_version_ = version;
}
- // Set entropy calculator to be called from the framer when it needs the
- // entropy of a truncated ack frame. An entropy calculator must be set or else
- // the framer will likely crash. If this is called multiple times, only the
- // last calculator will be used.
- void set_received_entropy_calculator(
- QuicReceivedEntropyHashCalculatorInterface* entropy_calculator) {
- entropy_calculator_ = entropy_calculator;
- }
-
QuicErrorCode error() const { return error_; }
// Pass a UDP packet into the framer for parsing.
@@ -363,9 +334,6 @@ class NET_EXPORT_PRIVATE QuicFramer {
Perspective perspective() const { return perspective_; }
- static QuicPacketEntropyHash GetPacketEntropyHash(
- const QuicPacketHeader& header);
-
// Called when a PATH_CLOSED frame has been sent/received on |path_id|.
void OnPathClosed(QuicPathId path_id);
@@ -381,28 +349,6 @@ class NET_EXPORT_PRIVATE QuicFramer {
AckFrameInfo(const AckFrameInfo& other);
~AckFrameInfo();
- // The maximum delta between ranges.
- QuicPacketNumber max_delta;
- // Nack ranges starting with start packet numbers and lengths.
- NackRangeMap nack_ranges;
- };
-
- struct AckBlock {
- AckBlock(uint8_t gap, QuicPacketNumber length);
- AckBlock(const AckBlock& other);
- ~AckBlock();
-
- // Gap to the next ack block.
- uint8_t gap;
- // Length of this ack block.
- QuicPacketNumber length;
- };
-
- struct NewAckFrameInfo {
- NewAckFrameInfo();
- NewAckFrameInfo(const NewAckFrameInfo& other);
- ~NewAckFrameInfo();
-
// The maximum ack block length.
QuicPacketNumber max_block_length;
// Length of first ack block.
@@ -431,11 +377,6 @@ class NET_EXPORT_PRIVATE QuicFramer {
bool ProcessUnauthenticatedHeader(QuicDataReader* encrypted_reader,
QuicPacketHeader* header);
- // Processes the authenticated portion of the header into |header| from
- // the current QuicDataReader. Returns true on success, false on failure.
- bool ProcessAuthenticatedHeader(QuicDataReader* reader,
- QuicPacketHeader* header);
-
bool ProcessPathId(QuicDataReader* reader, QuicPathId* path_id);
bool ProcessPacketSequenceNumber(QuicDataReader* reader,
QuicPacketNumberLength packet_number_length,
@@ -448,9 +389,6 @@ class NET_EXPORT_PRIVATE QuicFramer {
bool ProcessAckFrame(QuicDataReader* reader,
uint8_t frame_type,
QuicAckFrame* frame);
- bool ProcessNewAckFrame(QuicDataReader* reader,
- uint8_t frame_type,
- QuicAckFrame* frame);
bool ProcessTimestampsInAckFrame(QuicDataReader* reader, QuicAckFrame* frame);
bool ProcessStopWaitingFrame(QuicDataReader* reader,
const QuicPacketHeader& public_header,
@@ -495,12 +433,12 @@ class NET_EXPORT_PRIVATE QuicFramer {
// Computes the wire size in bytes of time stamps in |ack|.
size_t GetAckFrameTimeStampSize(const QuicAckFrame& ack);
- // Computes the wire size in bytes of the |ack| frame, assuming no truncation.
+ // Computes the wire size in bytes of the |ack| frame.
size_t GetAckFrameSize(const QuicAckFrame& ack,
QuicPacketNumberLength packet_number_length);
// Computes the wire size in bytes of the |ack| frame.
- size_t GetNewAckFrameSize(const QuicAckFrame& ack);
+ size_t GetAckFrameSize(const QuicAckFrame& ack);
// Computes the wire size in bytes of the payload of |frame|.
size_t ComputeFrameLength(const QuicFrame& frame,
@@ -524,16 +462,11 @@ class NET_EXPORT_PRIVATE QuicFramer {
static AckFrameInfo GetAckFrameInfo(const QuicAckFrame& frame);
- static NewAckFrameInfo GetNewAckFrameInfo(const QuicAckFrame& frame);
-
// The Append* methods attempt to write the provided header or frame using the
// |writer|, and return true if successful.
- bool AppendAckFrameAndTypeByte(const QuicPacketHeader& header,
- const QuicAckFrame& frame,
+ bool AppendAckFrameAndTypeByte(const QuicAckFrame& frame,
QuicDataWriter* builder);
- bool AppendNewAckFrameAndTypeByte(const QuicAckFrame& frame,
- QuicDataWriter* builder);
bool AppendTimestampToAckFrame(const QuicAckFrame& frame,
QuicDataWriter* builder);
bool AppendStopWaitingFrame(const QuicPacketHeader& header,
@@ -559,7 +492,6 @@ class NET_EXPORT_PRIVATE QuicFramer {
std::string detailed_error_;
QuicFramerVisitorInterface* visitor_;
- QuicReceivedEntropyHashCalculatorInterface* entropy_calculator_;
QuicErrorCode error_;
// Set of closed paths. A path is considered as closed if a PATH_CLOSED frame
// has been sent/received.
@@ -619,4 +551,4 @@ class NET_EXPORT_PRIVATE QuicFramer {
} // namespace net
-#endif // NET_QUIC_QUIC_FRAMER_H_
+#endif // NET_QUIC_CORE_QUIC_FRAMER_H_
diff --git a/chromium/net/quic/core/quic_framer_test.cc b/chromium/net/quic/core/quic_framer_test.cc
index 47b3c53b06d..645c2c6d9db 100644
--- a/chromium/net/quic/core/quic_framer_test.cc
+++ b/chromium/net/quic/core/quic_framer_test.cc
@@ -4,32 +4,28 @@
#include "net/quic/core/quic_framer.h"
-#include <string.h>
-
#include <algorithm>
+#include <cstdint>
#include <map>
#include <memory>
#include <string>
#include <vector>
-#include "base/logging.h"
-#include "base/memory/ptr_util.h"
#include "net/quic/core/crypto/null_decrypter.h"
+#include "net/quic/core/crypto/null_encrypter.h"
#include "net/quic/core/crypto/quic_decrypter.h"
#include "net/quic/core/crypto/quic_encrypter.h"
-#include "net/quic/core/quic_protocol.h"
+#include "net/quic/core/quic_flags.h"
+#include "net/quic/core/quic_packets.h"
#include "net/quic/core/quic_utils.h"
+#include "net/quic/platform/api/quic_logging.h"
+#include "net/quic/platform/api/quic_ptr_util.h"
#include "net/quic/test_tools/quic_framer_peer.h"
#include "net/quic/test_tools/quic_test_utils.h"
-#include "net/test/gtest_util.h"
+#include "testing/gtest/include/gtest/gtest.h"
using base::StringPiece;
-using std::make_pair;
-using std::map;
-using std::numeric_limits;
-using std::pair;
using std::string;
-using std::vector;
using testing::Return;
using testing::Truly;
using testing::_;
@@ -45,9 +41,7 @@ const QuicPacketNumber kMask = kEpoch - 1;
const QuicConnectionId kConnectionId = UINT64_C(0xFEDCBA9876543210);
const QuicPathId kPathId = 0x42;
const QuicPacketNumber kPacketNumber = UINT64_C(0x123456789ABC);
-const QuicPacketNumber kLargestObserved = UINT64_C(0x0123456789ABF);
const QuicPacketNumber kSmallLargestObserved = UINT16_C(0x1234);
-const QuicPacketNumber kMissingPacket = UINT64_C(0x0123456789ABE);
const QuicPacketNumber kSmallMissingPacket = UINT16_C(0x1233);
const QuicPacketNumber kLeastUnacked = UINT64_C(0x0123456789AA0);
const QuicStreamId kStreamId = UINT64_C(0x01020304);
@@ -118,13 +112,15 @@ class TestEncrypter : public QuicEncrypter {
~TestEncrypter() override {}
bool SetKey(StringPiece key) override { return true; }
bool SetNoncePrefix(StringPiece nonce_prefix) override { return true; }
- bool EncryptPacket(QuicPathId path_id,
+ bool EncryptPacket(QuicVersion version,
+ QuicPathId path_id,
QuicPacketNumber packet_number,
StringPiece associated_data,
StringPiece plaintext,
char* output,
size_t* output_length,
size_t max_output_length) override {
+ version_ = version;
path_id_ = path_id;
packet_number_ = packet_number;
associated_data_ = associated_data.as_string();
@@ -143,6 +139,9 @@ class TestEncrypter : public QuicEncrypter {
}
StringPiece GetKey() const override { return StringPiece(); }
StringPiece GetNoncePrefix() const override { return StringPiece(); }
+
+ QuicVersion version_;
+ Perspective perspective_;
QuicPathId path_id_;
QuicPacketNumber packet_number_;
string associated_data_;
@@ -161,13 +160,15 @@ class TestDecrypter : public QuicDecrypter {
bool SetDiversificationNonce(const DiversificationNonce& key) override {
return true;
}
- bool DecryptPacket(QuicPathId path_id,
+ bool DecryptPacket(QuicVersion version,
+ QuicPathId path_id,
QuicPacketNumber packet_number,
StringPiece associated_data,
StringPiece ciphertext,
char* output,
size_t* output_length,
size_t max_output_length) override {
+ version_ = version;
path_id_ = path_id;
packet_number_ = packet_number;
associated_data_ = associated_data.as_string();
@@ -181,6 +182,8 @@ class TestDecrypter : public QuicDecrypter {
const char* cipher_name() const override { return "Test"; }
// Use a distinct value starting with 0xFFFFFF, which is never used by TLS.
uint32_t cipher_id() const override { return 0xFFFFFFF2; }
+ QuicVersion version_;
+ Perspective perspective_;
QuicPathId path_id_;
QuicPacketNumber packet_number_;
string associated_data_;
@@ -201,8 +204,8 @@ class TestQuicVisitor : public QuicFramerVisitorInterface {
~TestQuicVisitor() override {}
void OnError(QuicFramer* f) override {
- DVLOG(1) << "QuicFramer Error: " << QuicUtils::ErrorToString(f->error())
- << " (" << f->error() << ")";
+ QUIC_DLOG(INFO) << "QuicFramer Error: " << QuicErrorCodeToString(f->error())
+ << " (" << f->error() << ")";
++error_count_;
}
@@ -218,7 +221,7 @@ class TestQuicVisitor : public QuicFramerVisitorInterface {
}
bool OnProtocolVersionMismatch(QuicVersion version) override {
- DVLOG(1) << "QuicFramer Version Mismatch, version: " << version;
+ QUIC_DLOG(INFO) << "QuicFramer Version Mismatch, version: " << version;
++version_mismatch_;
return true;
}
@@ -244,36 +247,33 @@ class TestQuicVisitor : public QuicFramerVisitorInterface {
bool OnStreamFrame(const QuicStreamFrame& frame) override {
++frame_count_;
// Save a copy of the data so it is valid after the packet is processed.
- string* string_data = new string();
- StringPiece(frame.data_buffer, frame.data_length)
- .AppendToString(string_data);
- stream_data_.push_back(base::WrapUnique(string_data));
- stream_frames_.push_back(base::MakeUnique<QuicStreamFrame>(
+ string* string_data = new string(frame.data_buffer, frame.data_length);
+ stream_data_.push_back(QuicWrapUnique(string_data));
+ stream_frames_.push_back(QuicMakeUnique<QuicStreamFrame>(
frame.stream_id, frame.fin, frame.offset, *string_data));
return true;
}
bool OnAckFrame(const QuicAckFrame& frame) override {
++frame_count_;
- ack_frames_.push_back(base::MakeUnique<QuicAckFrame>(frame));
+ ack_frames_.push_back(QuicMakeUnique<QuicAckFrame>(frame));
return true;
}
bool OnStopWaitingFrame(const QuicStopWaitingFrame& frame) override {
++frame_count_;
- stop_waiting_frames_.push_back(
- base::MakeUnique<QuicStopWaitingFrame>(frame));
+ stop_waiting_frames_.push_back(QuicMakeUnique<QuicStopWaitingFrame>(frame));
return true;
}
bool OnPaddingFrame(const QuicPaddingFrame& frame) override {
- padding_frames_.push_back(base::MakeUnique<QuicPaddingFrame>(frame));
+ padding_frames_.push_back(QuicMakeUnique<QuicPaddingFrame>(frame));
return true;
}
bool OnPingFrame(const QuicPingFrame& frame) override {
++frame_count_;
- ping_frames_.push_back(base::MakeUnique<QuicPingFrame>(frame));
+ ping_frames_.push_back(QuicMakeUnique<QuicPingFrame>(frame));
return true;
}
@@ -322,18 +322,18 @@ class TestQuicVisitor : public QuicFramerVisitorInterface {
std::unique_ptr<QuicPacketPublicHeader> public_header_;
std::unique_ptr<QuicPublicResetPacket> public_reset_packet_;
std::unique_ptr<QuicVersionNegotiationPacket> version_negotiation_packet_;
- vector<std::unique_ptr<QuicStreamFrame>> stream_frames_;
- vector<std::unique_ptr<QuicAckFrame>> ack_frames_;
- vector<std::unique_ptr<QuicStopWaitingFrame>> stop_waiting_frames_;
- vector<std::unique_ptr<QuicPaddingFrame>> padding_frames_;
- vector<std::unique_ptr<QuicPingFrame>> ping_frames_;
+ std::vector<std::unique_ptr<QuicStreamFrame>> stream_frames_;
+ std::vector<std::unique_ptr<QuicAckFrame>> ack_frames_;
+ std::vector<std::unique_ptr<QuicStopWaitingFrame>> stop_waiting_frames_;
+ std::vector<std::unique_ptr<QuicPaddingFrame>> padding_frames_;
+ std::vector<std::unique_ptr<QuicPingFrame>> ping_frames_;
QuicRstStreamFrame rst_stream_frame_;
QuicConnectionCloseFrame connection_close_frame_;
QuicGoAwayFrame goaway_frame_;
QuicWindowUpdateFrame window_update_frame_;
QuicBlockedFrame blocked_frame_;
QuicPathCloseFrame path_close_frame_;
- vector<std::unique_ptr<string>> stream_data_;
+ std::vector<std::unique_ptr<string>> stream_data_;
};
class QuicFramerTest : public ::testing::TestWithParam<QuicVersion> {
@@ -348,7 +348,6 @@ class QuicFramerTest : public ::testing::TestWithParam<QuicVersion> {
framer_.SetDecrypter(ENCRYPTION_NONE, decrypter_);
framer_.SetEncrypter(ENCRYPTION_NONE, encrypter_);
framer_.set_visitor(&visitor_);
- framer_.set_received_entropy_calculator(&entropy_calculator_);
}
// Helper function to get unsigned char representation of digit in the
@@ -366,22 +365,24 @@ class QuicFramerTest : public ::testing::TestWithParam<QuicVersion> {
bool CheckEncryption(QuicPathId path_id,
QuicPacketNumber packet_number,
QuicPacket* packet) {
+ EXPECT_EQ(version_, encrypter_->version_);
if (packet_number != encrypter_->packet_number_) {
- LOG(ERROR) << "Encrypted incorrect packet number. expected "
- << packet_number << " actual: " << encrypter_->packet_number_;
+ QUIC_LOG(ERROR) << "Encrypted incorrect packet number. expected "
+ << packet_number
+ << " actual: " << encrypter_->packet_number_;
return false;
}
if (packet->AssociatedData(framer_.version()) !=
encrypter_->associated_data_) {
- LOG(ERROR) << "Encrypted incorrect associated data. expected "
- << packet->AssociatedData(framer_.version())
- << " actual: " << encrypter_->associated_data_;
+ QUIC_LOG(ERROR) << "Encrypted incorrect associated data. expected "
+ << packet->AssociatedData(framer_.version())
+ << " actual: " << encrypter_->associated_data_;
return false;
}
if (packet->Plaintext(framer_.version()) != encrypter_->plaintext_) {
- LOG(ERROR) << "Encrypted incorrect plaintext data. expected "
- << packet->Plaintext(framer_.version())
- << " actual: " << encrypter_->plaintext_;
+ QUIC_LOG(ERROR) << "Encrypted incorrect plaintext data. expected "
+ << packet->Plaintext(framer_.version())
+ << " actual: " << encrypter_->plaintext_;
return false;
}
return true;
@@ -391,23 +392,24 @@ class QuicFramerTest : public ::testing::TestWithParam<QuicVersion> {
bool includes_version,
bool includes_path_id,
bool includes_diversification_nonce) {
+ EXPECT_EQ(version_, decrypter_->version_);
if (visitor_.header_->packet_number != decrypter_->packet_number_) {
- LOG(ERROR) << "Decrypted incorrect packet number. expected "
- << visitor_.header_->packet_number
- << " actual: " << decrypter_->packet_number_;
+ QUIC_LOG(ERROR) << "Decrypted incorrect packet number. expected "
+ << visitor_.header_->packet_number
+ << " actual: " << decrypter_->packet_number_;
return false;
}
if (QuicFramer::GetAssociatedDataFromEncryptedPacket(
framer_.version(), encrypted, PACKET_8BYTE_CONNECTION_ID,
includes_version, includes_path_id, includes_diversification_nonce,
PACKET_6BYTE_PACKET_NUMBER) != decrypter_->associated_data_) {
- LOG(ERROR) << "Decrypted incorrect associated data. expected "
- << QuicFramer::GetAssociatedDataFromEncryptedPacket(
- framer_.version(), encrypted,
- PACKET_8BYTE_CONNECTION_ID, includes_version,
- includes_path_id, includes_diversification_nonce,
- PACKET_6BYTE_PACKET_NUMBER)
- << " actual: " << decrypter_->associated_data_;
+ QUIC_LOG(ERROR) << "Decrypted incorrect associated data. expected "
+ << QuicFramer::GetAssociatedDataFromEncryptedPacket(
+ framer_.version(), encrypted,
+ PACKET_8BYTE_CONNECTION_ID, includes_version,
+ includes_path_id, includes_diversification_nonce,
+ PACKET_6BYTE_PACKET_NUMBER)
+ << " actual: " << decrypter_->associated_data_;
return false;
}
StringPiece ciphertext(
@@ -416,8 +418,8 @@ class QuicFramerTest : public ::testing::TestWithParam<QuicVersion> {
includes_path_id, includes_diversification_nonce,
PACKET_6BYTE_PACKET_NUMBER)));
if (ciphertext != decrypter_->ciphertext_) {
- LOG(ERROR) << "Decrypted incorrect ciphertext data. expected "
- << ciphertext << " actual: " << decrypter_->ciphertext_;
+ QUIC_LOG(ERROR) << "Decrypted incorrect ciphertext data. expected "
+ << ciphertext << " actual: " << decrypter_->ciphertext_;
return false;
}
return true;
@@ -495,7 +497,6 @@ class QuicFramerTest : public ::testing::TestWithParam<QuicVersion> {
QuicTime start_;
QuicFramer framer_;
test::TestQuicVisitor visitor_;
- test::TestEntropyCalculator entropy_calculator_;
};
// Run all framer tests with all supported versions of QUIC.
@@ -582,7 +583,7 @@ TEST_P(QuicFramerTest, CalculatePacketNumberFromWireNearNextEpoch) {
}
TEST_P(QuicFramerTest, CalculatePacketNumberFromWireNearNextMax) {
- const uint64_t max_number = numeric_limits<uint64_t>::max();
+ const uint64_t max_number = std::numeric_limits<uint64_t>::max();
const uint64_t max_epoch = max_number & ~kMask;
// Cases where the last number was close to the end of the range
@@ -651,24 +652,10 @@ TEST_P(QuicFramerTest, PacketHeader) {
0x10, 0x32, 0x54, 0x76, 0x98, 0xBA, 0xDC, 0xFE,
// packet number
0xBC, 0x9A, 0x78, 0x56, 0x34, 0x12,
- // private flags
- 0x00,
- };
- unsigned char packet_34[] = {
- // public flags (8 byte connection_id)
- 0x38,
- // connection_id
- 0x10, 0x32, 0x54, 0x76, 0x98, 0xBA, 0xDC, 0xFE,
- // packet number
- 0xBC, 0x9A, 0x78, 0x56, 0x34, 0x12,
};
// clang-format on
- QuicEncryptedPacket encrypted(
- AsChars(framer_.version() <= QUIC_VERSION_33 ? packet : packet_34),
- framer_.version() <= QUIC_VERSION_33 ? arraysize(packet)
- : arraysize(packet_34),
- false);
+ QuicEncryptedPacket encrypted(AsChars(packet), arraysize(packet), false);
EXPECT_FALSE(framer_.ProcessPacket(encrypted));
EXPECT_EQ(QUIC_MISSING_PAYLOAD, framer_.error());
ASSERT_TRUE(visitor_.header_.get());
@@ -676,8 +663,6 @@ TEST_P(QuicFramerTest, PacketHeader) {
EXPECT_FALSE(visitor_.header_->public_header.multipath_flag);
EXPECT_FALSE(visitor_.header_->public_header.reset_flag);
EXPECT_FALSE(visitor_.header_->public_header.version_flag);
- EXPECT_FALSE(visitor_.header_->entropy_flag);
- EXPECT_EQ(0, visitor_.header_->entropy_hash);
EXPECT_EQ(kPacketNumber, visitor_.header_->packet_number);
// Now test framing boundaries.
@@ -693,19 +678,9 @@ TEST_P(QuicFramerTest, PacketHeader) {
} else if (i < GetPacketNumberOffset(!kIncludeVersion, !kIncludePathId)) {
expected_error = "Unable to read ConnectionId.";
} else {
- if (framer_.version() <= QUIC_VERSION_33) {
- if (i < GetPrivateFlagsOffset(!kIncludeVersion, !kIncludePathId)) {
- expected_error = "Unable to read packet number.";
- } else {
- expected_error = "Unable to read private flags.";
- }
- } else {
- expected_error = "Unable to read packet number.";
- }
+ expected_error = "Unable to read packet number.";
}
- CheckProcessingFails(
- framer_.version() <= QUIC_VERSION_33 ? packet : packet_34, i,
- expected_error, QUIC_INVALID_PACKET_HEADER);
+ CheckProcessingFails(packet, i, expected_error, QUIC_INVALID_PACKET_HEADER);
}
}
@@ -720,24 +695,10 @@ TEST_P(QuicFramerTest, PacketHeaderWith0ByteConnectionId) {
// packet number
0xBC, 0x9A, 0x78, 0x56,
0x34, 0x12,
- // private flags
- 0x00,
- };
- unsigned char packet_34[] = {
- // public flags (0 byte connection_id)
- 0x30,
- // connection_id
- // packet number
- 0xBC, 0x9A, 0x78, 0x56,
- 0x34, 0x12,
};
// clang-format on
- QuicEncryptedPacket encrypted(
- AsChars(framer_.version() <= QUIC_VERSION_33 ? packet : packet_34),
- framer_.version() <= QUIC_VERSION_33 ? arraysize(packet)
- : arraysize(packet_34),
- false);
+ QuicEncryptedPacket encrypted(AsChars(packet), arraysize(packet), false);
EXPECT_FALSE(framer_.ProcessPacket(encrypted));
EXPECT_EQ(QUIC_MISSING_PAYLOAD, framer_.error());
ASSERT_TRUE(visitor_.header_.get());
@@ -745,8 +706,6 @@ TEST_P(QuicFramerTest, PacketHeaderWith0ByteConnectionId) {
EXPECT_FALSE(visitor_.header_->public_header.multipath_flag);
EXPECT_FALSE(visitor_.header_->public_header.reset_flag);
EXPECT_FALSE(visitor_.header_->public_header.version_flag);
- EXPECT_FALSE(visitor_.header_->entropy_flag);
- EXPECT_EQ(0, visitor_.header_->entropy_hash);
EXPECT_EQ(kPacketNumber, visitor_.header_->packet_number);
// Now test framing boundaries.
@@ -763,20 +722,9 @@ TEST_P(QuicFramerTest, PacketHeaderWith0ByteConnectionId) {
!kIncludeVersion, !kIncludePathId)) {
expected_error = "Unable to read ConnectionId.";
} else {
- if (framer_.version() <= QUIC_VERSION_33) {
- if (i < GetPrivateFlagsOffset(PACKET_0BYTE_CONNECTION_ID,
- !kIncludeVersion, !kIncludePathId)) {
- expected_error = "Unable to read packet number.";
- } else {
- expected_error = "Unable to read private flags.";
- }
- } else {
- expected_error = "Unable to read packet number.";
- }
+ expected_error = "Unable to read packet number.";
}
- CheckProcessingFails(
- framer_.version() <= QUIC_VERSION_33 ? packet : packet_34, i,
- expected_error, QUIC_INVALID_PACKET_HEADER);
+ CheckProcessingFails(packet, i, expected_error, QUIC_INVALID_PACKET_HEADER);
}
}
@@ -791,26 +739,10 @@ TEST_P(QuicFramerTest, PacketHeaderWithVersionFlag) {
'Q', '0', GetQuicVersionDigitTens(), GetQuicVersionDigitOnes(),
// packet number
0xBC, 0x9A, 0x78, 0x56, 0x34, 0x12,
- // private flags
- 0x00,
- };
- unsigned char packet_34[] = {
- // public flags (version)
- 0x39,
- // connection_id
- 0x10, 0x32, 0x54, 0x76, 0x98, 0xBA, 0xDC, 0xFE,
- // version tag
- 'Q', '0', GetQuicVersionDigitTens(), GetQuicVersionDigitOnes(),
- // packet number
- 0xBC, 0x9A, 0x78, 0x56, 0x34, 0x12,
};
// clang-format on
- QuicEncryptedPacket encrypted(
- AsChars(framer_.version() <= QUIC_VERSION_33 ? packet : packet_34),
- framer_.version() <= QUIC_VERSION_33 ? arraysize(packet)
- : arraysize(packet_34),
- false);
+ QuicEncryptedPacket encrypted(AsChars(packet), arraysize(packet), false);
EXPECT_FALSE(framer_.ProcessPacket(encrypted));
EXPECT_EQ(QUIC_MISSING_PAYLOAD, framer_.error());
ASSERT_TRUE(visitor_.header_.get());
@@ -819,8 +751,6 @@ TEST_P(QuicFramerTest, PacketHeaderWithVersionFlag) {
EXPECT_FALSE(visitor_.header_->public_header.reset_flag);
EXPECT_TRUE(visitor_.header_->public_header.version_flag);
EXPECT_EQ(GetParam(), visitor_.header_->public_header.versions[0]);
- EXPECT_FALSE(visitor_.header_->entropy_flag);
- EXPECT_EQ(0, visitor_.header_->entropy_hash);
EXPECT_EQ(kPacketNumber, visitor_.header_->packet_number);
// Now test framing boundaries.
@@ -838,19 +768,9 @@ TEST_P(QuicFramerTest, PacketHeaderWithVersionFlag) {
} else if (i < GetPacketNumberOffset(kIncludeVersion, !kIncludePathId)) {
expected_error = "Unable to read protocol version.";
} else {
- if (framer_.version() <= QUIC_VERSION_33) {
- if (i < GetPrivateFlagsOffset(kIncludeVersion, !kIncludePathId)) {
- expected_error = "Unable to read packet number.";
- } else {
- expected_error = "Unable to read private flags.";
- }
- } else {
- expected_error = "Unable to read packet number.";
- }
+ expected_error = "Unable to read packet number.";
}
- CheckProcessingFails(
- framer_.version() <= QUIC_VERSION_33 ? packet : packet_34, i,
- expected_error, QUIC_INVALID_PACKET_HEADER);
+ CheckProcessingFails(packet, i, expected_error, QUIC_INVALID_PACKET_HEADER);
}
}
@@ -865,26 +785,10 @@ TEST_P(QuicFramerTest, PacketHeaderWithMultipathFlag) {
0x42,
// packet number
0xBC, 0x9A, 0x78, 0x56, 0x34, 0x12,
- // private flags
- 0x00,
- };
- unsigned char packet_34[] = {
- // public flags (version)
- 0x78,
- // connection_id
- 0x10, 0x32, 0x54, 0x76, 0x98, 0xBA, 0xDC, 0xFE,
- // path_id
- 0x42,
- // packet number
- 0xBC, 0x9A, 0x78, 0x56, 0x34, 0x12,
};
// clang-format on
- QuicEncryptedPacket encrypted(
- AsChars(framer_.version() <= QUIC_VERSION_33 ? packet : packet_34),
- framer_.version() <= QUIC_VERSION_33 ? arraysize(packet)
- : arraysize(packet_34),
- false);
+ QuicEncryptedPacket encrypted(AsChars(packet), arraysize(packet), false);
EXPECT_FALSE(framer_.ProcessPacket(encrypted));
EXPECT_EQ(QUIC_MISSING_PAYLOAD, framer_.error());
ASSERT_TRUE(visitor_.header_.get());
@@ -894,8 +798,6 @@ TEST_P(QuicFramerTest, PacketHeaderWithMultipathFlag) {
EXPECT_TRUE(visitor_.header_->public_header.multipath_flag);
EXPECT_FALSE(visitor_.header_->public_header.reset_flag);
EXPECT_FALSE(visitor_.header_->public_header.version_flag);
- EXPECT_FALSE(visitor_.header_->entropy_flag);
- EXPECT_EQ(0, visitor_.header_->entropy_hash);
EXPECT_EQ(kPathId, visitor_.header_->path_id);
EXPECT_EQ(kPacketNumber, visitor_.header_->packet_number);
@@ -915,19 +817,9 @@ TEST_P(QuicFramerTest, PacketHeaderWithMultipathFlag) {
} else if (i < GetPacketNumberOffset(!kIncludeVersion, kIncludePathId)) {
expected_error = "Unable to read path id.";
} else {
- if (framer_.version() <= QUIC_VERSION_33) {
- if (i < GetPrivateFlagsOffset(!kIncludeVersion, kIncludePathId)) {
- expected_error = "Unable to read packet number.";
- } else {
- expected_error = "Unable to read private flags.";
- }
- } else {
- expected_error = "Unable to read packet number.";
- }
+ expected_error = "Unable to read packet number.";
}
- CheckProcessingFails(
- framer_.version() <= QUIC_VERSION_33 ? packet : packet_34, i,
- expected_error, QUIC_INVALID_PACKET_HEADER);
+ CheckProcessingFails(packet, i, expected_error, QUIC_INVALID_PACKET_HEADER);
}
}
@@ -944,28 +836,10 @@ TEST_P(QuicFramerTest, PacketHeaderWithBothVersionFlagAndMultipathFlag) {
0x42,
// packet number
0xBC, 0x9A, 0x78, 0x56, 0x34, 0x12,
- // private flags
- 0x00,
- };
- unsigned char packet_34[] = {
- // public flags (version)
- 0x79,
- // connection_id
- 0x10, 0x32, 0x54, 0x76, 0x98, 0xBA, 0xDC, 0xFE,
- // version tag
- 'Q', '0', GetQuicVersionDigitTens(), GetQuicVersionDigitOnes(),
- // path_id
- 0x42,
- // packet number
- 0xBC, 0x9A, 0x78, 0x56, 0x34, 0x12,
};
// clang-format on
- QuicEncryptedPacket encrypted(
- AsChars(framer_.version() <= QUIC_VERSION_33 ? packet : packet_34),
- framer_.version() <= QUIC_VERSION_33 ? arraysize(packet)
- : arraysize(packet_34),
- false);
+ QuicEncryptedPacket encrypted(AsChars(packet), arraysize(packet), false);
EXPECT_FALSE(framer_.ProcessPacket(encrypted));
EXPECT_EQ(QUIC_MISSING_PAYLOAD, framer_.error());
ASSERT_TRUE(visitor_.header_.get());
@@ -976,8 +850,6 @@ TEST_P(QuicFramerTest, PacketHeaderWithBothVersionFlagAndMultipathFlag) {
EXPECT_FALSE(visitor_.header_->public_header.reset_flag);
EXPECT_TRUE(visitor_.header_->public_header.version_flag);
EXPECT_EQ(GetParam(), visitor_.header_->public_header.versions[0]);
- EXPECT_FALSE(visitor_.header_->entropy_flag);
- EXPECT_EQ(0, visitor_.header_->entropy_hash);
EXPECT_EQ(kPathId, visitor_.header_->path_id);
EXPECT_EQ(kPacketNumber, visitor_.header_->packet_number);
@@ -999,19 +871,9 @@ TEST_P(QuicFramerTest, PacketHeaderWithBothVersionFlagAndMultipathFlag) {
} else if (i < GetPacketNumberOffset(kIncludeVersion, kIncludePathId)) {
expected_error = "Unable to read path id.";
} else {
- if (framer_.version() <= QUIC_VERSION_33) {
- if (i < GetPrivateFlagsOffset(kIncludeVersion, kIncludePathId)) {
- expected_error = "Unable to read packet number.";
- } else {
- expected_error = "Unable to read private flags.";
- }
- } else {
- expected_error = "Unable to read packet number.";
- }
+ expected_error = "Unable to read packet number.";
}
- CheckProcessingFails(
- framer_.version() <= QUIC_VERSION_33 ? packet : packet_34, i,
- expected_error, QUIC_INVALID_PACKET_HEADER);
+ CheckProcessingFails(packet, i, expected_error, QUIC_INVALID_PACKET_HEADER);
}
}
@@ -1027,28 +889,12 @@ TEST_P(QuicFramerTest, PacketHeaderWithPathChange) {
0x42,
// packet number
0xBC, 0x9A, 0x78, 0x56, 0x34, 0x12,
- // private flags
- 0x00,
- };
- unsigned char packet1_34[] = {
- // public flags (version)
- 0x78,
- // connection_id
- 0x10, 0x32, 0x54, 0x76, 0x98, 0xBA, 0xDC, 0xFE,
- // path_id
- 0x42,
- // packet number
- 0xBC, 0x9A, 0x78, 0x56, 0x34, 0x12,
};
// clang-format on
EXPECT_EQ(0u, QuicFramerPeer::GetLastPacketNumber(&framer_));
EXPECT_EQ(kInvalidPathId, QuicFramerPeer::GetLastPathId(&framer_));
- QuicEncryptedPacket encrypted1(
- AsChars(framer_.version() <= QUIC_VERSION_33 ? packet1 : packet1_34),
- framer_.version() <= QUIC_VERSION_33 ? arraysize(packet1)
- : arraysize(packet1_34),
- false);
+ QuicEncryptedPacket encrypted1(AsChars(packet1), arraysize(packet1), false);
EXPECT_FALSE(framer_.ProcessPacket(encrypted1));
EXPECT_EQ(QUIC_MISSING_PAYLOAD, framer_.error());
ASSERT_TRUE(visitor_.header_.get());
@@ -1069,26 +915,10 @@ TEST_P(QuicFramerTest, PacketHeaderWithPathChange) {
0x00,
// packet number
0xCC, 0x9A, 0x78, 0x56, 0x34, 0x12,
- // private flags
- 0x00,
- };
- unsigned char packet2_34[] = {
- // public flags (version)
- 0x78,
- // connection_id
- 0x10, 0x32, 0x54, 0x76, 0x98, 0xBA, 0xDC, 0xFE,
- // path_id
- 0x00,
- // packet number
- 0xCC, 0x9A, 0x78, 0x56, 0x34, 0x12,
};
// clang-format on
- QuicEncryptedPacket encrypted2(
- AsChars(framer_.version() <= QUIC_VERSION_33 ? packet2 : packet2_34),
- framer_.version() <= QUIC_VERSION_33 ? arraysize(packet2)
- : arraysize(packet2_34),
- false);
+ QuicEncryptedPacket encrypted2(AsChars(packet2), arraysize(packet2), false);
EXPECT_FALSE(framer_.ProcessPacket(encrypted2));
EXPECT_EQ(QUIC_MISSING_PAYLOAD, framer_.error());
ASSERT_TRUE(visitor_.header_.get());
@@ -1109,26 +939,10 @@ TEST_P(QuicFramerTest, PacketHeaderWithPathChange) {
0x42,
// packet number
0xBD, 0x9A, 0x78, 0x56, 0x34, 0x12,
- // private flags
- 0x00,
- };
- unsigned char packet3_34[] = {
- // public flags (version)
- 0x78,
- // connection_id
- 0x10, 0x32, 0x54, 0x76, 0x98, 0xBA, 0xDC, 0xFE,
- // path_id
- 0x42,
- // packet number
- 0xBD, 0x9A, 0x78, 0x56, 0x34, 0x12,
};
// clang-format on
- QuicEncryptedPacket encrypted3(
- AsChars(framer_.version() <= QUIC_VERSION_33 ? packet3 : packet3_34),
- framer_.version() <= QUIC_VERSION_33 ? arraysize(packet3)
- : arraysize(packet3_34),
- false);
+ QuicEncryptedPacket encrypted3(AsChars(packet3), arraysize(packet3), false);
EXPECT_FALSE(framer_.ProcessPacket(encrypted3));
EXPECT_EQ(QUIC_MISSING_PAYLOAD, framer_.error());
ASSERT_TRUE(visitor_.header_.get());
@@ -1154,26 +968,10 @@ TEST_P(QuicFramerTest, ReceivedPacketOnClosedPath) {
// private flags
0x00,
};
- unsigned char packet_34[] = {
- // public flags (version)
- 0x78,
- // connection_id
- 0x10, 0x32, 0x54, 0x76, 0x98, 0xBA, 0xDC, 0xFE,
- // path_id
- 0x42,
- // packet number
- 0xBC, 0x9A, 0x78, 0x56, 0x34, 0x12,
- // private flags
- 0x00,
- };
// clang-format on
framer_.OnPathClosed(kPathId);
- QuicEncryptedPacket encrypted(
- AsChars(framer_.version() <= QUIC_VERSION_33 ? packet : packet_34),
- framer_.version() <= QUIC_VERSION_33 ? arraysize(packet)
- : arraysize(packet_34),
- false);
+ QuicEncryptedPacket encrypted(AsChars(packet), arraysize(packet), false);
EXPECT_FALSE(framer_.ProcessPacket(encrypted));
EXPECT_EQ(QUIC_NO_ERROR, framer_.error());
EXPECT_EQ(0u, QuicFramerPeer::GetLastPacketNumber(&framer_));
@@ -1191,24 +989,10 @@ TEST_P(QuicFramerTest, PacketHeaderWith4BytePacketNumber) {
0x10, 0x32, 0x54, 0x76, 0x98, 0xBA, 0xDC, 0xFE,
// packet number
0xBC, 0x9A, 0x78, 0x56,
- // private flags
- 0x00,
- };
- unsigned char packet_34[] = {
- // public flags (8 byte connection_id and 4 byte packet number)
- 0x28,
- // connection_id
- 0x10, 0x32, 0x54, 0x76, 0x98, 0xBA, 0xDC, 0xFE,
- // packet number
- 0xBC, 0x9A, 0x78, 0x56,
};
// clang-format on
- QuicEncryptedPacket encrypted(
- AsChars(framer_.version() <= QUIC_VERSION_33 ? packet : packet_34),
- framer_.version() <= QUIC_VERSION_33 ? arraysize(packet)
- : arraysize(packet_34),
- false);
+ QuicEncryptedPacket encrypted(AsChars(packet), arraysize(packet), false);
EXPECT_FALSE(framer_.ProcessPacket(encrypted));
EXPECT_EQ(QUIC_MISSING_PAYLOAD, framer_.error());
ASSERT_TRUE(visitor_.header_.get());
@@ -1216,8 +1000,6 @@ TEST_P(QuicFramerTest, PacketHeaderWith4BytePacketNumber) {
EXPECT_FALSE(visitor_.header_->public_header.multipath_flag);
EXPECT_FALSE(visitor_.header_->public_header.reset_flag);
EXPECT_FALSE(visitor_.header_->public_header.version_flag);
- EXPECT_FALSE(visitor_.header_->entropy_flag);
- EXPECT_EQ(0, visitor_.header_->entropy_hash);
EXPECT_EQ(kPacketNumber, visitor_.header_->packet_number);
// Now test framing boundaries.
@@ -1233,20 +1015,9 @@ TEST_P(QuicFramerTest, PacketHeaderWith4BytePacketNumber) {
} else if (i < GetPacketNumberOffset(!kIncludeVersion, !kIncludePathId)) {
expected_error = "Unable to read ConnectionId.";
} else {
- if (framer_.version() <= QUIC_VERSION_33) {
- if (i < GetPrivateFlagsOffset(!kIncludeVersion, !kIncludePathId,
- PACKET_4BYTE_PACKET_NUMBER)) {
- expected_error = "Unable to read packet number.";
- } else {
- expected_error = "Unable to read private flags.";
- }
- } else {
- expected_error = "Unable to read packet number.";
- }
+ expected_error = "Unable to read packet number.";
}
- CheckProcessingFails(
- framer_.version() <= QUIC_VERSION_33 ? packet : packet_34, i,
- expected_error, QUIC_INVALID_PACKET_HEADER);
+ CheckProcessingFails(packet, i, expected_error, QUIC_INVALID_PACKET_HEADER);
}
}
@@ -1261,24 +1032,10 @@ TEST_P(QuicFramerTest, PacketHeaderWith2BytePacketNumber) {
0x10, 0x32, 0x54, 0x76, 0x98, 0xBA, 0xDC, 0xFE,
// packet number
0xBC, 0x9A,
- // private flags
- 0x00,
- };
- unsigned char packet_34[] = {
- // public flags (8 byte connection_id and 2 byte packet number)
- 0x18,
- // connection_id
- 0x10, 0x32, 0x54, 0x76, 0x98, 0xBA, 0xDC, 0xFE,
- // packet number
- 0xBC, 0x9A,
};
// clang-format on
- QuicEncryptedPacket encrypted(
- AsChars(framer_.version() <= QUIC_VERSION_33 ? packet : packet_34),
- framer_.version() <= QUIC_VERSION_33 ? arraysize(packet)
- : arraysize(packet_34),
- false);
+ QuicEncryptedPacket encrypted(AsChars(packet), arraysize(packet), false);
EXPECT_FALSE(framer_.ProcessPacket(encrypted));
EXPECT_EQ(QUIC_MISSING_PAYLOAD, framer_.error());
ASSERT_TRUE(visitor_.header_.get());
@@ -1288,8 +1045,6 @@ TEST_P(QuicFramerTest, PacketHeaderWith2BytePacketNumber) {
EXPECT_FALSE(visitor_.header_->public_header.version_flag);
EXPECT_EQ(PACKET_2BYTE_PACKET_NUMBER,
visitor_.header_->public_header.packet_number_length);
- EXPECT_FALSE(visitor_.header_->entropy_flag);
- EXPECT_EQ(0, visitor_.header_->entropy_hash);
EXPECT_EQ(kPacketNumber, visitor_.header_->packet_number);
// Now test framing boundaries.
@@ -1305,20 +1060,9 @@ TEST_P(QuicFramerTest, PacketHeaderWith2BytePacketNumber) {
} else if (i < GetPacketNumberOffset(!kIncludeVersion, !kIncludePathId)) {
expected_error = "Unable to read ConnectionId.";
} else {
- if (framer_.version() <= QUIC_VERSION_33) {
- if (i < GetPrivateFlagsOffset(!kIncludeVersion, !kIncludePathId,
- PACKET_2BYTE_PACKET_NUMBER)) {
- expected_error = "Unable to read packet number.";
- } else {
- expected_error = "Unable to read private flags.";
- }
- } else {
- expected_error = "Unable to read packet number.";
- }
+ expected_error = "Unable to read packet number.";
}
- CheckProcessingFails(
- framer_.version() <= QUIC_VERSION_33 ? packet : packet_34, i,
- expected_error, QUIC_INVALID_PACKET_HEADER);
+ CheckProcessingFails(packet, i, expected_error, QUIC_INVALID_PACKET_HEADER);
}
}
@@ -1333,24 +1077,10 @@ TEST_P(QuicFramerTest, PacketHeaderWith1BytePacketNumber) {
0x10, 0x32, 0x54, 0x76, 0x98, 0xBA, 0xDC, 0xFE,
// packet number
0xBC,
- // private flags
- 0x00,
- };
- unsigned char packet_34[] = {
- // public flags (8 byte connection_id and 1 byte packet number)
- 0x08,
- // connection_id
- 0x10, 0x32, 0x54, 0x76, 0x98, 0xBA, 0xDC, 0xFE,
- // packet number
- 0xBC,
};
// clang-format on
- QuicEncryptedPacket encrypted(
- AsChars(framer_.version() <= QUIC_VERSION_33 ? packet : packet_34),
- framer_.version() <= QUIC_VERSION_33 ? arraysize(packet)
- : arraysize(packet_34),
- false);
+ QuicEncryptedPacket encrypted(AsChars(packet), arraysize(packet), false);
EXPECT_FALSE(framer_.ProcessPacket(encrypted));
EXPECT_EQ(QUIC_MISSING_PAYLOAD, framer_.error());
ASSERT_TRUE(visitor_.header_.get());
@@ -1360,8 +1090,6 @@ TEST_P(QuicFramerTest, PacketHeaderWith1BytePacketNumber) {
EXPECT_FALSE(visitor_.header_->public_header.version_flag);
EXPECT_EQ(PACKET_1BYTE_PACKET_NUMBER,
visitor_.header_->public_header.packet_number_length);
- EXPECT_FALSE(visitor_.header_->entropy_flag);
- EXPECT_EQ(0, visitor_.header_->entropy_hash);
EXPECT_EQ(kPacketNumber, visitor_.header_->packet_number);
// Now test framing boundaries.
@@ -1377,20 +1105,9 @@ TEST_P(QuicFramerTest, PacketHeaderWith1BytePacketNumber) {
} else if (i < GetPacketNumberOffset(!kIncludeVersion, !kIncludePathId)) {
expected_error = "Unable to read ConnectionId.";
} else {
- if (framer_.version() <= QUIC_VERSION_33) {
- if (i < GetPrivateFlagsOffset(!kIncludeVersion, !kIncludePathId,
- PACKET_1BYTE_PACKET_NUMBER)) {
- expected_error = "Unable to read packet number.";
- } else {
- expected_error = "Unable to read private flags.";
- }
- } else {
- expected_error = "Unable to read packet number.";
- }
+ expected_error = "Unable to read packet number.";
}
- CheckProcessingFails(
- framer_.version() <= QUIC_VERSION_33 ? packet : packet_34, i,
- expected_error, QUIC_INVALID_PACKET_HEADER);
+ CheckProcessingFails(packet, i, expected_error, QUIC_INVALID_PACKET_HEADER);
}
}
@@ -1401,12 +1118,9 @@ TEST_P(QuicFramerTest, PacketNumberDecreasesThenIncreases) {
header.public_header.connection_id = kConnectionId;
header.public_header.reset_flag = false;
header.public_header.version_flag = false;
- header.entropy_flag = false;
header.packet_number = kPacketNumber - 2;
- QuicPaddingFrame padding_frame;
- QuicFrames frames;
- frames.push_back(QuicFrame(padding_frame));
+ QuicFrames frames = {QuicFrame(QuicPaddingFrame())};
std::unique_ptr<QuicPacket> data(BuildDataPacket(header, frames));
ASSERT_TRUE(data != nullptr);
@@ -1455,36 +1169,6 @@ TEST_P(QuicFramerTest, PacketNumberDecreasesThenIncreases) {
EXPECT_EQ(kPacketNumber - 1, visitor_.header_->packet_number);
}
-TEST_P(QuicFramerTest, InvalidPublicFlag) {
- if (framer_.version() > QUIC_VERSION_33) {
- return;
- }
- // clang-format off
- unsigned char packet[] = {
- // public flags: all flags set but the public reset flag and version flag.
- 0xF8,
- // connection_id
- 0x10, 0x32, 0x54, 0x76, 0x98, 0xBA, 0xDC, 0xFE,
- // packet number
- 0xBC, 0x9A, 0x78, 0x56, 0x34, 0x12,
- // private flags
- 0x00,
-
- // frame type (padding)
- 0x00,
- 0x00, 0x00, 0x00, 0x00
- };
- // clang-format on
-
- CheckProcessingFails(packet, arraysize(packet), "Illegal public flags value.",
- QUIC_INVALID_PACKET_HEADER);
-
- // Now turn off validation.
- framer_.set_validate_flags(false);
- QuicEncryptedPacket encrypted(AsChars(packet), arraysize(packet), false);
- EXPECT_TRUE(framer_.ProcessPacket(encrypted));
-};
-
TEST_P(QuicFramerTest, PacketWithDiversificationNonce) {
// clang-format off
unsigned char packet[] = {
@@ -1499,25 +1183,6 @@ TEST_P(QuicFramerTest, PacketWithDiversificationNonce) {
0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f,
// packet number
0xBC, 0x9A, 0x78, 0x56, 0x34, 0x12,
- // private flags
- 0x00,
-
- // frame type (padding)
- 0x00,
- 0x00, 0x00, 0x00, 0x00
- };
- unsigned char packet_34[] = {
- // public flags: includes nonce flag
- 0x7C,
- // connection_id
- 0x10, 0x32, 0x54, 0x76, 0x98, 0xBA, 0xDC, 0xFE,
- // nonce
- 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
- 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
- 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
- 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f,
- // packet number
- 0xBC, 0x9A, 0x78, 0x56, 0x34, 0x12,
// frame type (padding)
0x00,
@@ -1525,55 +1190,13 @@ TEST_P(QuicFramerTest, PacketWithDiversificationNonce) {
};
// clang-format on
- QuicEncryptedPacket encrypted(
- AsChars(framer_.version() <= QUIC_VERSION_33 ? packet : packet_34),
- framer_.version() <= QUIC_VERSION_33 ? arraysize(packet)
- : arraysize(packet_34),
- false);
+ QuicEncryptedPacket encrypted(AsChars(packet), arraysize(packet), false);
QuicFramerPeer::SetPerspective(&framer_, Perspective::IS_CLIENT);
- if (framer_.version() > QUIC_VERSION_32) {
- EXPECT_TRUE(framer_.ProcessPacket(encrypted));
- ASSERT_TRUE(visitor_.public_header_->nonce != nullptr);
- for (char i = 0; i < 32; ++i) {
- EXPECT_EQ(i, (*visitor_.public_header_->nonce)[static_cast<int>(i)]);
- }
- } else if (framer_.version() < QUIC_VERSION_32) {
- // Packet is successfully parsed by accident.
- EXPECT_TRUE(framer_.ProcessPacket(encrypted));
- ASSERT_TRUE(visitor_.public_header_ != nullptr);
- } else {
- EXPECT_FALSE(framer_.ProcessPacket(encrypted));
- EXPECT_EQ(QUIC_INVALID_PACKET_HEADER, framer_.error());
- EXPECT_EQ("Illegal private flags value.", framer_.detailed_error());
- }
-};
-
-TEST_P(QuicFramerTest, InvalidPublicFlagWithMatchingVersions) {
- if (framer_.version() > QUIC_VERSION_33) {
- return;
+ EXPECT_TRUE(framer_.ProcessPacket(encrypted));
+ ASSERT_TRUE(visitor_.public_header_->nonce != nullptr);
+ for (char i = 0; i < 32; ++i) {
+ EXPECT_EQ(i, (*visitor_.public_header_->nonce)[static_cast<size_t>(i)]);
}
- // clang-format off
- unsigned char packet[] = {
- // public flags (8 byte connection_id and version flag and an unknown flag)
- 0x8D,
- // connection_id
- 0x10, 0x32, 0x54, 0x76,
- 0x98, 0xBA, 0xDC, 0xFE,
- // version tag
- 'Q', '0', GetQuicVersionDigitTens(), GetQuicVersionDigitOnes(),
- // packet number
- 0xBC, 0x9A, 0x78, 0x56,
- 0x34, 0x12,
- // private flags
- 0x00,
-
- // frame type (padding)
- 0x00,
- 0x00, 0x00, 0x00, 0x00
- };
- // clang-format on
- CheckProcessingFails(packet, arraysize(packet), "Illegal public flags value.",
- QUIC_INVALID_PACKET_HEADER);
};
TEST_P(QuicFramerTest, LargePublicFlagWithMismatchedVersions) {
@@ -1589,35 +1212,13 @@ TEST_P(QuicFramerTest, LargePublicFlagWithMismatchedVersions) {
// packet number
0xBC, 0x9A, 0x78, 0x56,
0x34, 0x12,
- // private flags
- 0x00,
-
- // frame type (padding frame)
- 0x00,
- 0x00, 0x00, 0x00, 0x00
- };
- unsigned char packet_34[] = {
- // public flags (8 byte connection_id, version flag and an unknown flag)
- 0x79,
- // connection_id
- 0x10, 0x32, 0x54, 0x76,
- 0x98, 0xBA, 0xDC, 0xFE,
- // version tag
- 'Q', '0', '0', '0',
- // packet number
- 0xBC, 0x9A, 0x78, 0x56,
- 0x34, 0x12,
// frame type (padding frame)
0x00,
0x00, 0x00, 0x00, 0x00
};
// clang-format on
- QuicEncryptedPacket encrypted(
- AsChars(framer_.version() <= QUIC_VERSION_33 ? packet : packet_34),
- framer_.version() <= QUIC_VERSION_33 ? arraysize(packet)
- : arraysize(packet_34),
- false);
+ QuicEncryptedPacket encrypted(AsChars(packet), arraysize(packet), false);
EXPECT_TRUE(framer_.ProcessPacket(encrypted));
EXPECT_EQ(QUIC_NO_ERROR, framer_.error());
ASSERT_TRUE(visitor_.header_.get());
@@ -1625,33 +1226,6 @@ TEST_P(QuicFramerTest, LargePublicFlagWithMismatchedVersions) {
EXPECT_EQ(1, visitor_.version_mismatch_);
};
-TEST_P(QuicFramerTest, InvalidPrivateFlag) {
- if (framer_.version() > QUIC_VERSION_33) {
- return;
- }
- // clang-format off
- unsigned char packet[] = {
- // public flags (8 byte connection_id)
- 0x38,
- // connection_id
- 0x10, 0x32, 0x54, 0x76,
- 0x98, 0xBA, 0xDC, 0xFE,
- // packet number
- 0xBC, 0x9A, 0x78, 0x56,
- 0x34, 0x12,
- // private flags
- 0x10,
-
- // frame type (padding)
- 0x00,
- 0x00, 0x00, 0x00, 0x00
- };
- // clang-format on
- CheckProcessingFails(packet, arraysize(packet),
- "Illegal private flags value.",
- QUIC_INVALID_PACKET_HEADER);
-};
-
TEST_P(QuicFramerTest, PaddingFrame) {
// clang-format off
unsigned char packet[] = {
@@ -1663,35 +1237,6 @@ TEST_P(QuicFramerTest, PaddingFrame) {
// packet number
0xBC, 0x9A, 0x78, 0x56,
0x34, 0x12,
- // private flags
- 0x00,
-
- // frame type (padding frame)
- 0x00,
- // Ignored data (which in this case is a stream frame)
- // frame type (stream frame with fin)
- 0xFF,
- // stream id
- 0x04, 0x03, 0x02, 0x01,
- // offset
- 0x54, 0x76, 0x10, 0x32,
- 0xDC, 0xFE, 0x98, 0xBA,
- // data length
- 0x0c, 0x00,
- // data
- 'h', 'e', 'l', 'l',
- 'o', ' ', 'w', 'o',
- 'r', 'l', 'd', '!',
- };
- unsigned char packet_34[] = {
- // public flags (8 byte connection_id)
- 0x38,
- // connection_id
- 0x10, 0x32, 0x54, 0x76,
- 0x98, 0xBA, 0xDC, 0xFE,
- // packet number
- 0xBC, 0x9A, 0x78, 0x56,
- 0x34, 0x12,
// frame type (padding frame)
0x00,
@@ -1712,11 +1257,7 @@ TEST_P(QuicFramerTest, PaddingFrame) {
};
// clang-format on
- QuicEncryptedPacket encrypted(
- AsChars(framer_.version() <= QUIC_VERSION_33 ? packet : packet_34),
- framer_.version() <= QUIC_VERSION_33 ? arraysize(packet)
- : arraysize(packet_34),
- false);
+ QuicEncryptedPacket encrypted(AsChars(packet), arraysize(packet), false);
EXPECT_TRUE(framer_.ProcessPacket(encrypted));
EXPECT_EQ(QUIC_NO_ERROR, framer_.error());
ASSERT_TRUE(visitor_.header_.get());
@@ -1737,32 +1278,6 @@ TEST_P(QuicFramerTest, PaddingFrame) {
TEST_P(QuicFramerTest, StreamFrame) {
// clang-format off
unsigned char packet[] = {
- // public flags (8 byte connection_id)
- 0x38,
- // connection_id
- 0x10, 0x32, 0x54, 0x76,
- 0x98, 0xBA, 0xDC, 0xFE,
- // packet number
- 0xBC, 0x9A, 0x78, 0x56,
- 0x34, 0x12,
- // private flags
- 0x00,
-
- // frame type (stream frame with fin)
- 0xFF,
- // stream id
- 0x04, 0x03, 0x02, 0x01,
- // offset
- 0x54, 0x76, 0x10, 0x32,
- 0xDC, 0xFE, 0x98, 0xBA,
- // data length
- 0x0c, 0x00,
- // data
- 'h', 'e', 'l', 'l',
- 'o', ' ', 'w', 'o',
- 'r', 'l', 'd', '!',
- };
- unsigned char packet_34[] = {
// public flags (8 byte connection_id)
0x38,
// connection_id
@@ -1788,11 +1303,7 @@ TEST_P(QuicFramerTest, StreamFrame) {
};
// clang-format on
- QuicEncryptedPacket encrypted(
- AsChars(framer_.version() <= QUIC_VERSION_33 ? packet : packet_34),
- framer_.version() <= QUIC_VERSION_33 ? arraysize(packet)
- : arraysize(packet_34),
- false);
+ QuicEncryptedPacket encrypted(AsChars(packet), arraysize(packet), false);
EXPECT_TRUE(framer_.ProcessPacket(encrypted));
EXPECT_EQ(QUIC_NO_ERROR, framer_.error());
@@ -1808,45 +1319,18 @@ TEST_P(QuicFramerTest, StreamFrame) {
CheckStreamFrameData("hello world!", visitor_.stream_frames_[0].get());
// Now test framing boundaries.
- CheckStreamFrameBoundaries(
- framer_.version() <= QUIC_VERSION_33 ? packet : packet_34,
- kQuicMaxStreamIdSize, !kIncludeVersion);
+ CheckStreamFrameBoundaries(packet, kQuicMaxStreamIdSize, !kIncludeVersion);
}
TEST_P(QuicFramerTest, MissingDiversificationNonce) {
QuicFramerPeer::SetPerspective(&framer_, Perspective::IS_CLIENT);
- framer_.SetDecrypter(ENCRYPTION_NONE, new NullDecrypter());
+ framer_.SetDecrypter(ENCRYPTION_NONE,
+ new NullDecrypter(Perspective::IS_CLIENT));
decrypter_ = new test::TestDecrypter();
framer_.SetAlternativeDecrypter(ENCRYPTION_INITIAL, decrypter_, false);
// clang-format off
unsigned char packet[] = {
- // public flags (8 byte connection_id)
- 0x38,
- // connection_id
- 0x10, 0x32, 0x54, 0x76,
- 0x98, 0xBA, 0xDC, 0xFE,
- // packet number
- 0xBC, 0x9A, 0x78, 0x56,
- 0x34, 0x12,
- // private flags
- 0x00,
-
- // frame type (stream frame with fin)
- 0xFF,
- // stream id
- 0x04, 0x03, 0x02, 0x01,
- // offset
- 0x54, 0x76, 0x10, 0x32,
- 0xDC, 0xFE, 0x98, 0xBA,
- // data length
- 0x0c, 0x00,
- // data
- 'h', 'e', 'l', 'l',
- 'o', ' ', 'w', 'o',
- 'r', 'l', 'd', '!',
- };
- unsigned char packet_34[] = {
// public flags (8 byte connection_id)
0x38,
// connection_id
@@ -1872,23 +1356,9 @@ TEST_P(QuicFramerTest, MissingDiversificationNonce) {
};
// clang-format on
- QuicEncryptedPacket encrypted(
- AsChars(framer_.version() <= QUIC_VERSION_33 ? packet : packet_34),
- framer_.version() <= QUIC_VERSION_33 ? arraysize(packet)
- : arraysize(packet_34),
- false);
- if (framer_.version() > QUIC_VERSION_32) {
- EXPECT_FALSE(framer_.ProcessPacket(encrypted));
- EXPECT_EQ(QUIC_DECRYPTION_FAILURE, framer_.error());
-
- } else {
- EXPECT_TRUE(framer_.ProcessPacket(encrypted));
-
- EXPECT_EQ(QUIC_NO_ERROR, framer_.error());
- ASSERT_TRUE(visitor_.header_.get());
- EXPECT_TRUE(CheckDecryption(encrypted, !kIncludeVersion, !kIncludePathId,
- !kIncludeDiversificationNonce));
- }
+ QuicEncryptedPacket encrypted(AsChars(packet), arraysize(packet), false);
+ EXPECT_FALSE(framer_.ProcessPacket(encrypted));
+ EXPECT_EQ(QUIC_DECRYPTION_FAILURE, framer_.error());
}
TEST_P(QuicFramerTest, StreamFrame3ByteStreamId) {
@@ -1902,32 +1372,6 @@ TEST_P(QuicFramerTest, StreamFrame3ByteStreamId) {
// packet number
0xBC, 0x9A, 0x78, 0x56,
0x34, 0x12,
- // private flags
- 0x00,
-
- // frame type (stream frame with fin)
- 0xFE,
- // stream id
- 0x04, 0x03, 0x02,
- // offset
- 0x54, 0x76, 0x10, 0x32,
- 0xDC, 0xFE, 0x98, 0xBA,
- // data length
- 0x0c, 0x00,
- // data
- 'h', 'e', 'l', 'l',
- 'o', ' ', 'w', 'o',
- 'r', 'l', 'd', '!',
- };
- unsigned char packet_34[] = {
- // public flags (8 byte connection_id)
- 0x38,
- // connection_id
- 0x10, 0x32, 0x54, 0x76,
- 0x98, 0xBA, 0xDC, 0xFE,
- // packet number
- 0xBC, 0x9A, 0x78, 0x56,
- 0x34, 0x12,
// frame type (stream frame with fin)
0xFE,
@@ -1945,11 +1389,7 @@ TEST_P(QuicFramerTest, StreamFrame3ByteStreamId) {
};
// clang-format on
- QuicEncryptedPacket encrypted(
- AsChars(framer_.version() <= QUIC_VERSION_33 ? packet : packet_34),
- framer_.version() <= QUIC_VERSION_33 ? arraysize(packet)
- : arraysize(packet_34),
- false);
+ QuicEncryptedPacket encrypted(AsChars(packet), arraysize(packet), false);
EXPECT_TRUE(framer_.ProcessPacket(encrypted));
EXPECT_EQ(QUIC_NO_ERROR, framer_.error());
@@ -1967,9 +1407,7 @@ TEST_P(QuicFramerTest, StreamFrame3ByteStreamId) {
// Now test framing boundaries.
const size_t stream_id_size = 3;
- CheckStreamFrameBoundaries(
- framer_.version() <= QUIC_VERSION_33 ? packet : packet_34, stream_id_size,
- !kIncludeVersion);
+ CheckStreamFrameBoundaries(packet, stream_id_size, !kIncludeVersion);
}
TEST_P(QuicFramerTest, StreamFrame2ByteStreamId) {
@@ -1983,32 +1421,6 @@ TEST_P(QuicFramerTest, StreamFrame2ByteStreamId) {
// packet number
0xBC, 0x9A, 0x78, 0x56,
0x34, 0x12,
- // private flags
- 0x00,
-
- // frame type (stream frame with fin)
- 0xFD,
- // stream id
- 0x04, 0x03,
- // offset
- 0x54, 0x76, 0x10, 0x32,
- 0xDC, 0xFE, 0x98, 0xBA,
- // data length
- 0x0c, 0x00,
- // data
- 'h', 'e', 'l', 'l',
- 'o', ' ', 'w', 'o',
- 'r', 'l', 'd', '!',
- };
- unsigned char packet_34[] = {
- // public flags (8 byte connection_id)
- 0x38,
- // connection_id
- 0x10, 0x32, 0x54, 0x76,
- 0x98, 0xBA, 0xDC, 0xFE,
- // packet number
- 0xBC, 0x9A, 0x78, 0x56,
- 0x34, 0x12,
// frame type (stream frame with fin)
0xFD,
@@ -2026,11 +1438,7 @@ TEST_P(QuicFramerTest, StreamFrame2ByteStreamId) {
};
// clang-format on
- QuicEncryptedPacket encrypted(
- AsChars(framer_.version() <= QUIC_VERSION_33 ? packet : packet_34),
- framer_.version() <= QUIC_VERSION_33 ? arraysize(packet)
- : arraysize(packet_34),
- false);
+ QuicEncryptedPacket encrypted(AsChars(packet), arraysize(packet), false);
EXPECT_TRUE(framer_.ProcessPacket(encrypted));
EXPECT_EQ(QUIC_NO_ERROR, framer_.error());
@@ -2048,9 +1456,7 @@ TEST_P(QuicFramerTest, StreamFrame2ByteStreamId) {
// Now test framing boundaries.
const size_t stream_id_size = 2;
- CheckStreamFrameBoundaries(
- framer_.version() <= QUIC_VERSION_33 ? packet : packet_34, stream_id_size,
- !kIncludeVersion);
+ CheckStreamFrameBoundaries(packet, stream_id_size, !kIncludeVersion);
}
TEST_P(QuicFramerTest, StreamFrame1ByteStreamId) {
@@ -2064,32 +1470,6 @@ TEST_P(QuicFramerTest, StreamFrame1ByteStreamId) {
// packet number
0xBC, 0x9A, 0x78, 0x56,
0x34, 0x12,
- // private flags
- 0x00,
-
- // frame type (stream frame with fin)
- 0xFC,
- // stream id
- 0x04,
- // offset
- 0x54, 0x76, 0x10, 0x32,
- 0xDC, 0xFE, 0x98, 0xBA,
- // data length
- 0x0c, 0x00,
- // data
- 'h', 'e', 'l', 'l',
- 'o', ' ', 'w', 'o',
- 'r', 'l', 'd', '!',
- };
- unsigned char packet_34[] = {
- // public flags (8 byte connection_id)
- 0x38,
- // connection_id
- 0x10, 0x32, 0x54, 0x76,
- 0x98, 0xBA, 0xDC, 0xFE,
- // packet number
- 0xBC, 0x9A, 0x78, 0x56,
- 0x34, 0x12,
// frame type (stream frame with fin)
0xFC,
@@ -2107,11 +1487,7 @@ TEST_P(QuicFramerTest, StreamFrame1ByteStreamId) {
};
// clang-format on
- QuicEncryptedPacket encrypted(
- AsChars(framer_.version() <= QUIC_VERSION_33 ? packet : packet_34),
- framer_.version() <= QUIC_VERSION_33 ? arraysize(packet)
- : arraysize(packet_34),
- false);
+ QuicEncryptedPacket encrypted(AsChars(packet), arraysize(packet), false);
EXPECT_TRUE(framer_.ProcessPacket(encrypted));
EXPECT_EQ(QUIC_NO_ERROR, framer_.error());
@@ -2129,9 +1505,7 @@ TEST_P(QuicFramerTest, StreamFrame1ByteStreamId) {
// Now test framing boundaries.
const size_t stream_id_size = 1;
- CheckStreamFrameBoundaries(
- framer_.version() <= QUIC_VERSION_33 ? packet : packet_34, stream_id_size,
- !kIncludeVersion);
+ CheckStreamFrameBoundaries(packet, stream_id_size, !kIncludeVersion);
}
TEST_P(QuicFramerTest, StreamFrameWithVersion) {
@@ -2147,34 +1521,6 @@ TEST_P(QuicFramerTest, StreamFrameWithVersion) {
// packet number
0xBC, 0x9A, 0x78, 0x56,
0x34, 0x12,
- // private flags
- 0x00,
-
- // frame type (stream frame with fin)
- 0xFF,
- // stream id
- 0x04, 0x03, 0x02, 0x01,
- // offset
- 0x54, 0x76, 0x10, 0x32,
- 0xDC, 0xFE, 0x98, 0xBA,
- // data length
- 0x0c, 0x00,
- // data
- 'h', 'e', 'l', 'l',
- 'o', ' ', 'w', 'o',
- 'r', 'l', 'd', '!',
- };
- unsigned char packet_34[] = {
- // public flags (version, 8 byte connection_id)
- 0x39,
- // connection_id
- 0x10, 0x32, 0x54, 0x76,
- 0x98, 0xBA, 0xDC, 0xFE,
- // version tag
- 'Q', '0', GetQuicVersionDigitTens(), GetQuicVersionDigitOnes(),
- // packet number
- 0xBC, 0x9A, 0x78, 0x56,
- 0x34, 0x12,
// frame type (stream frame with fin)
0xFF,
@@ -2192,11 +1538,7 @@ TEST_P(QuicFramerTest, StreamFrameWithVersion) {
};
// clang-format on
- QuicEncryptedPacket encrypted(
- AsChars(framer_.version() <= QUIC_VERSION_33 ? packet : packet_34),
- framer_.version() <= QUIC_VERSION_33 ? arraysize(packet)
- : arraysize(packet_34),
- false);
+ QuicEncryptedPacket encrypted(AsChars(packet), arraysize(packet), false);
EXPECT_TRUE(framer_.ProcessPacket(encrypted));
EXPECT_EQ(QUIC_NO_ERROR, framer_.error());
@@ -2214,9 +1556,7 @@ TEST_P(QuicFramerTest, StreamFrameWithVersion) {
CheckStreamFrameData("hello world!", visitor_.stream_frames_[0].get());
// Now test framing boundaries.
- CheckStreamFrameBoundaries(
- framer_.version() <= QUIC_VERSION_33 ? packet : packet_34,
- kQuicMaxStreamIdSize, kIncludeVersion);
+ CheckStreamFrameBoundaries(packet, kQuicMaxStreamIdSize, kIncludeVersion);
}
TEST_P(QuicFramerTest, RejectPacket) {
@@ -2224,32 +1564,6 @@ TEST_P(QuicFramerTest, RejectPacket) {
// clang-format off
unsigned char packet[] = {
- // public flags (8 byte connection_id)
- 0x38,
- // connection_id
- 0x10, 0x32, 0x54, 0x76,
- 0x98, 0xBA, 0xDC, 0xFE,
- // packet number
- 0xBC, 0x9A, 0x78, 0x56,
- 0x34, 0x12,
- // private flags
- 0x00,
-
- // frame type (stream frame with fin)
- 0xFF,
- // stream id
- 0x04, 0x03, 0x02, 0x01,
- // offset
- 0x54, 0x76, 0x10, 0x32,
- 0xDC, 0xFE, 0x98, 0xBA,
- // data length
- 0x0c, 0x00,
- // data
- 'h', 'e', 'l', 'l',
- 'o', ' ', 'w', 'o',
- 'r', 'l', 'd', '!',
- };
- unsigned char packet_34[] = {
// public flags (8 byte connection_id)
0x38,
// connection_id
@@ -2275,11 +1589,7 @@ TEST_P(QuicFramerTest, RejectPacket) {
};
// clang-format on
- QuicEncryptedPacket encrypted(
- AsChars(framer_.version() <= QUIC_VERSION_33 ? packet : packet_34),
- framer_.version() <= QUIC_VERSION_33 ? arraysize(packet)
- : arraysize(packet_34),
- false);
+ QuicEncryptedPacket encrypted(AsChars(packet), arraysize(packet), false);
EXPECT_TRUE(framer_.ProcessPacket(encrypted));
EXPECT_EQ(QUIC_NO_ERROR, framer_.error());
@@ -2312,225 +1622,7 @@ TEST_P(QuicFramerTest, RejectPublicHeader) {
ASSERT_FALSE(visitor_.header_.get());
}
-TEST_P(QuicFramerTest, AckFrameTwoTimestampVersion32) {
- // clang-format off
- unsigned char packet[] = {
- // public flags (8 byte connection_id)
- 0x3C,
- // connection_id
- 0x10, 0x32, 0x54, 0x76, 0x98, 0xBA, 0xDC, 0xFE,
- // packet number
- 0xA8, 0x9A, 0x78, 0x56, 0x34, 0x12,
- // private flags (entropy)
- 0x01,
-
- // frame type (ack frame)
- // (has nacks, not truncated, 6 byte largest observed, 1 byte delta)
- 0x6C,
- // entropy hash of all received packets.
- 0xBA,
- // largest observed packet number
- 0xBF, 0x9A, 0x78, 0x56, 0x34, 0x12,
- // Zero delta time.
- 0x00, 0x00,
- // Number of timestamps.
- 0x02,
- // Delta from largest observed.
- 0x01,
- // Delta time.
- 0x10, 0x32, 0x54, 0x76,
- // Delta from largest observed.
- 0x02,
- // Delta time.
- 0x10, 0x32,
- // num missing packets
- 0x01,
- // missing packet delta
- 0x01,
- // 0 more missing packets in range.
- 0x00,
- };
- // clang-format on
-
- if (framer_.version() > QUIC_VERSION_33) {
- return;
- }
-
- QuicEncryptedPacket encrypted(AsChars(packet), arraysize(packet), false);
- EXPECT_TRUE(framer_.ProcessPacket(encrypted));
-
- EXPECT_EQ(QUIC_NO_ERROR, framer_.error());
- ASSERT_TRUE(visitor_.header_.get());
- EXPECT_TRUE(CheckDecryption(encrypted, !kIncludeVersion, !kIncludePathId,
- !kIncludeDiversificationNonce));
-
- EXPECT_EQ(0u, visitor_.stream_frames_.size());
- ASSERT_EQ(1u, visitor_.ack_frames_.size());
- const QuicAckFrame& frame = *visitor_.ack_frames_[0].get();
- EXPECT_EQ(0xBA, frame.entropy_hash);
- EXPECT_EQ(kLargestObserved, frame.largest_observed);
- ASSERT_EQ(1u, frame.packets.NumPacketsSlow());
- ASSERT_EQ(2u, frame.received_packet_times.size());
- EXPECT_EQ(kMissingPacket, frame.packets.Min());
-
- const size_t kReceivedEntropyOffset = kQuicFrameTypeSize;
- const size_t kLargestObservedOffset =
- kReceivedEntropyOffset + kQuicEntropyHashSize;
- const size_t kMissingDeltaTimeOffset =
- kLargestObservedOffset + PACKET_6BYTE_PACKET_NUMBER;
- const size_t kNumTimestampsOffset =
- kMissingDeltaTimeOffset + kQuicDeltaTimeLargestObservedSize;
- const size_t kTimestampDeltaLargestObserved1 =
- kNumTimestampsOffset + kQuicNumTimestampsSize;
- const size_t kTimestampTimeDeltaLargestObserved1 =
- kTimestampDeltaLargestObserved1 + 1;
- const size_t kTimestampDeltaLargestObserved2 =
- kTimestampTimeDeltaLargestObserved1 + 4;
- const size_t kTimestampTimeDeltaLargestObserved2 =
- kTimestampDeltaLargestObserved2 + 1;
- const size_t kNumMissingPacketOffset =
- kTimestampTimeDeltaLargestObserved2 + 2;
- const size_t kMissingPacketsOffset =
- kNumMissingPacketOffset + kNumberOfNackRangesSize;
- // Now test framing boundaries.
- const size_t ack_frame_size = PACKET_1BYTE_PACKET_NUMBER;
- for (size_t i = kQuicFrameTypeSize; i < ack_frame_size; ++i) {
- string expected_error;
- if (i < kLargestObservedOffset) {
- expected_error = "Unable to read entropy hash for received packets.";
- } else if (i < kMissingDeltaTimeOffset) {
- expected_error = "Unable to read largest observed.";
- } else if (i < kNumTimestampsOffset) {
- expected_error = "Unable to read ack delay time.";
- } else if (i < kTimestampDeltaLargestObserved1) {
- expected_error = "Unable to read num received packets.";
- } else if (i < kTimestampTimeDeltaLargestObserved1) {
- expected_error = "Unable to read sequence delta in received packets.";
- } else if (i < kTimestampDeltaLargestObserved2) {
- expected_error = "Unable to read time delta in received packets.";
- } else if (i < kTimestampTimeDeltaLargestObserved2) {
- expected_error = "Unable to read sequence delta in received packets.";
- } else if (i < kNumMissingPacketOffset) {
- expected_error =
- "Unable to read incremental time delta in received packets.";
- } else if (i < kMissingPacketsOffset) {
- expected_error = "Unable to read num missing packet ranges.";
- } else {
- expected_error = "Unable to read missing packet number delta.";
- }
- CheckProcessingFails(
- packet,
- i + GetPacketHeaderSize(framer_.version(), PACKET_8BYTE_CONNECTION_ID,
- !kIncludeVersion, !kIncludePathId,
- !kIncludeDiversificationNonce,
- PACKET_6BYTE_PACKET_NUMBER),
- expected_error, QUIC_INVALID_ACK_DATA);
- }
-}
-
-TEST_P(QuicFramerTest, AckFrameOneTimestampVersion32) {
- // clang-format off
- unsigned char packet[] = {
- // public flags (8 byte connection_id)
- 0x3C,
- // connection_id
- 0x10, 0x32, 0x54, 0x76, 0x98, 0xBA, 0xDC, 0xFE,
- // packet number
- 0xA8, 0x9A, 0x78, 0x56, 0x34, 0x12,
- // private flags (entropy)
- 0x01,
-
- // frame type (ack frame)
- // (has nacks, not truncated, 6 byte largest observed, 1 byte delta)
- 0x6C,
- // entropy hash of all received packets.
- 0xBA,
- // largest observed packet number
- 0xBF, 0x9A, 0x78, 0x56, 0x34, 0x12,
- // Zero delta time.
- 0x00, 0x00,
- // Number of timestamps.
- 0x01,
- // Delta from largest observed.
- 0x01,
- // Delta time.
- 0x10, 0x32, 0x54, 0x76,
- // num missing packets
- 0x01,
- // missing packet delta
- 0x01,
- // 0 more missing packets in range.
- 0x00,
- };
- // clang-format on
-
- if (framer_.version() > QUIC_VERSION_33) {
- return;
- }
-
- QuicEncryptedPacket encrypted(AsChars(packet), arraysize(packet), false);
- EXPECT_TRUE(framer_.ProcessPacket(encrypted));
-
- EXPECT_EQ(QUIC_NO_ERROR, framer_.error());
- ASSERT_TRUE(visitor_.header_.get());
- EXPECT_TRUE(CheckDecryption(encrypted, !kIncludeVersion, !kIncludePathId,
- !kIncludeDiversificationNonce));
-
- EXPECT_EQ(0u, visitor_.stream_frames_.size());
- ASSERT_EQ(1u, visitor_.ack_frames_.size());
- const QuicAckFrame& frame = *visitor_.ack_frames_[0].get();
- EXPECT_EQ(0xBA, frame.entropy_hash);
- EXPECT_EQ(kLargestObserved, frame.largest_observed);
- ASSERT_EQ(1u, frame.packets.NumPacketsSlow());
- ASSERT_EQ(1u, frame.received_packet_times.size());
- EXPECT_EQ(kMissingPacket, frame.packets.Min());
-
- const size_t kReceivedEntropyOffset = kQuicFrameTypeSize;
- const size_t kLargestObservedOffset =
- kReceivedEntropyOffset + kQuicEntropyHashSize;
- const size_t kMissingDeltaTimeOffset =
- kLargestObservedOffset + PACKET_6BYTE_PACKET_NUMBER;
- const size_t kNumTimestampsOffset =
- kMissingDeltaTimeOffset + kQuicDeltaTimeLargestObservedSize;
- const size_t kTimestampDeltaLargestObserved =
- kNumTimestampsOffset + kQuicNumTimestampsSize;
- const size_t kTimestampTimeDeltaLargestObserved =
- kTimestampDeltaLargestObserved + 1;
- const size_t kNumMissingPacketOffset = kTimestampTimeDeltaLargestObserved + 4;
- const size_t kMissingPacketsOffset =
- kNumMissingPacketOffset + kNumberOfNackRangesSize;
- // Now test framing boundaries.
- const size_t ack_frame_size = PACKET_1BYTE_PACKET_NUMBER;
- for (size_t i = kQuicFrameTypeSize; i < ack_frame_size; ++i) {
- string expected_error;
- if (i < kLargestObservedOffset) {
- expected_error = "Unable to read entropy hash for received packets.";
- } else if (i < kMissingDeltaTimeOffset) {
- expected_error = "Unable to read largest observed.";
- } else if (i < kNumTimestampsOffset) {
- expected_error = "Unable to read ack delay time.";
- } else if (i < kTimestampDeltaLargestObserved) {
- expected_error = "Unable to read num received packets.";
- } else if (i < kTimestampTimeDeltaLargestObserved) {
- expected_error = "Unable to read sequence delta in received packets.";
- } else if (i < kNumMissingPacketOffset) {
- expected_error = "Unable to read time delta in received packets.";
- } else if (i < kMissingPacketsOffset) {
- expected_error = "Unable to read num missing packet ranges.";
- } else {
- expected_error = "Unable to read missing packet number delta.";
- }
- CheckProcessingFails(
- packet,
- i + GetPacketHeaderSize(framer_.version(), PACKET_8BYTE_CONNECTION_ID,
- !kIncludeVersion, !kIncludePathId,
- !kIncludeDiversificationNonce,
- PACKET_6BYTE_PACKET_NUMBER),
- expected_error, QUIC_INVALID_ACK_DATA);
- }
-}
-
-TEST_P(QuicFramerTest, NewAckFrameOneAckBlock) {
+TEST_P(QuicFramerTest, AckFrameOneAckBlock) {
// clang-format off
unsigned char packet[] = {
// public flags (8 byte connection_id)
@@ -2554,10 +1646,6 @@ TEST_P(QuicFramerTest, NewAckFrameOneAckBlock) {
};
// clang-format on
- if (framer_.version() <= QUIC_VERSION_33) {
- return;
- }
-
QuicEncryptedPacket encrypted(AsChars(packet), arraysize(packet), false);
EXPECT_TRUE(framer_.ProcessPacket(encrypted));
@@ -2568,9 +1656,8 @@ TEST_P(QuicFramerTest, NewAckFrameOneAckBlock) {
EXPECT_EQ(0u, visitor_.stream_frames_.size());
ASSERT_EQ(1u, visitor_.ack_frames_.size());
- const QuicAckFrame& frame = *visitor_.ack_frames_[0].get();
+ const QuicAckFrame& frame = *visitor_.ack_frames_[0];
EXPECT_EQ(kSmallLargestObserved, frame.largest_observed);
- EXPECT_FALSE(frame.missing);
ASSERT_EQ(4660u, frame.packets.NumPacketsSlow());
const size_t kLargestAckedOffset = kQuicFrameTypeSize;
@@ -2604,7 +1691,7 @@ TEST_P(QuicFramerTest, NewAckFrameOneAckBlock) {
}
}
-TEST_P(QuicFramerTest, NewAckFrameTwoTimeStampsMultipleAckBlocks) {
+TEST_P(QuicFramerTest, AckFrameTwoTimeStampsMultipleAckBlocks) {
// clang-format off
unsigned char packet[] = {
// public flags (8 byte connection_id)
@@ -2654,10 +1741,6 @@ TEST_P(QuicFramerTest, NewAckFrameTwoTimeStampsMultipleAckBlocks) {
};
// clang-format on
- if (framer_.version() <= QUIC_VERSION_33) {
- return;
- }
-
QuicEncryptedPacket encrypted(AsChars(packet), arraysize(packet), false);
EXPECT_TRUE(framer_.ProcessPacket(encrypted));
@@ -2668,9 +1751,8 @@ TEST_P(QuicFramerTest, NewAckFrameTwoTimeStampsMultipleAckBlocks) {
EXPECT_EQ(0u, visitor_.stream_frames_.size());
ASSERT_EQ(1u, visitor_.ack_frames_.size());
- const QuicAckFrame& frame = *visitor_.ack_frames_[0].get();
+ const QuicAckFrame& frame = *visitor_.ack_frames_[0];
EXPECT_EQ(kSmallLargestObserved, frame.largest_observed);
- EXPECT_FALSE(frame.missing);
ASSERT_EQ(4254u, frame.packets.NumPacketsSlow());
const size_t kLargestAckedOffset = kQuicFrameTypeSize;
@@ -2755,233 +1837,7 @@ TEST_P(QuicFramerTest, NewAckFrameTwoTimeStampsMultipleAckBlocks) {
}
}
-TEST_P(QuicFramerTest, AckFrameVersion32) {
- // clang-format off
- unsigned char packet[] = {
- // public flags (8 byte connection_id)
- 0x38,
- // connection_id
- 0x10, 0x32, 0x54, 0x76, 0x98, 0xBA, 0xDC, 0xFE,
- // packet number
- 0xA8, 0x9A, 0x78, 0x56, 0x34, 0x12,
- // private flags (entropy)
- 0x01,
-
- // frame type (ack frame)
- // (has nacks, not truncated, 6 byte largest observed, 1 byte delta)
- 0x6C,
- // entropy hash of all received packets.
- 0xBA,
- // largest observed packet number
- 0xBF, 0x9A, 0x78, 0x56, 0x34, 0x12,
- // Zero delta time.
- 0x00, 0x00,
- // Number of timestamps.
- 0x00,
- // num missing packets
- 0x01,
- // missing packet delta
- 0x01,
- // 0 more missing packets in range.
- 0x00,
- };
- // clang-format on
-
- if (framer_.version() > QUIC_VERSION_33) {
- return;
- }
-
- QuicEncryptedPacket encrypted(AsChars(packet), arraysize(packet), false);
- EXPECT_TRUE(framer_.ProcessPacket(encrypted));
-
- EXPECT_EQ(QUIC_NO_ERROR, framer_.error());
- ASSERT_TRUE(visitor_.header_.get());
- EXPECT_TRUE(CheckDecryption(encrypted, !kIncludeVersion, !kIncludePathId,
- !kIncludeDiversificationNonce));
-
- EXPECT_EQ(0u, visitor_.stream_frames_.size());
- ASSERT_EQ(1u, visitor_.ack_frames_.size());
- const QuicAckFrame& frame = *visitor_.ack_frames_[0].get();
- EXPECT_EQ(0xBA, frame.entropy_hash);
- EXPECT_EQ(kLargestObserved, frame.largest_observed);
- ASSERT_EQ(1u, frame.packets.NumPacketsSlow());
- EXPECT_EQ(kMissingPacket, frame.packets.Min());
-
- const size_t kReceivedEntropyOffset = kQuicFrameTypeSize;
- const size_t kLargestObservedOffset =
- kReceivedEntropyOffset + kQuicEntropyHashSize;
- const size_t kMissingDeltaTimeOffset =
- kLargestObservedOffset + PACKET_6BYTE_PACKET_NUMBER;
- const size_t kNumTimestampsOffset =
- kMissingDeltaTimeOffset + kQuicDeltaTimeLargestObservedSize;
- const size_t kNumMissingPacketOffset =
- kNumTimestampsOffset + kQuicNumTimestampsSize;
- const size_t kMissingPacketsOffset =
- kNumMissingPacketOffset + kNumberOfNackRangesSize;
- // Now test framing boundaries.
- const size_t ack_frame_size = PACKET_1BYTE_PACKET_NUMBER;
- for (size_t i = kQuicFrameTypeSize; i < ack_frame_size; ++i) {
- string expected_error;
- if (i < kLargestObservedOffset) {
- expected_error = "Unable to read entropy hash for received packets.";
- } else if (i < kMissingDeltaTimeOffset) {
- expected_error = "Unable to read largest observed.";
- } else if (i < kNumTimestampsOffset) {
- expected_error = "Unable to read ack delay time.";
- } else if (i < kNumMissingPacketOffset) {
- expected_error = "Unable to read num received packets.";
- } else if (i < kMissingPacketsOffset) {
- expected_error = "Unable to read num missing packet ranges.";
- } else {
- expected_error = "Unable to read missing packet number delta.";
- }
- CheckProcessingFails(
- packet,
- i + GetPacketHeaderSize(framer_.version(), PACKET_8BYTE_CONNECTION_ID,
- !kIncludeVersion, !kIncludePathId,
- !kIncludeDiversificationNonce,
- PACKET_6BYTE_PACKET_NUMBER),
- expected_error, QUIC_INVALID_ACK_DATA);
- }
-}
-
-TEST_P(QuicFramerTest, AckFrame500NacksVersion32) {
- // clang-format off
- unsigned char packet[] = {
- // public flags (8 byte connection_id)
- static_cast<unsigned char>(
- framer_.version() > QUIC_VERSION_32 ? 0x38 : 0x3C),
- // connection_id
- 0x10, 0x32, 0x54, 0x76, 0x98, 0xBA, 0xDC, 0xFE,
- // packet number
- 0xA8, 0x9A, 0x78, 0x56, 0x34, 0x12,
- // private flags (entropy)
- 0x01,
-
- // frame type (ack frame)
- // (has nacks, not truncated, 6 byte largest observed, 1 byte delta)
- 0x6C,
- // entropy hash of all received packets.
- 0xBA,
- // largest observed packet number
- 0xBF, 0x9A, 0x78, 0x56, 0x34, 0x12,
- // Zero delta time.
- 0x00, 0x00,
- // No received packets.
- 0x00,
- // num missing packet ranges
- 0x02,
- // missing packet delta
- 0x01,
- // 243 more missing packets in range.
- // The ranges are listed in this order so the re-constructed packet
- // matches.
- 0xF3,
- // No gap between ranges
- 0x00,
- // 255 more missing packets in range.
- 0xFF,
- };
- // clang-format on
-
- if (framer_.version() > QUIC_VERSION_33) {
- return;
- }
-
- QuicEncryptedPacket encrypted(AsChars(packet), arraysize(packet), false);
- EXPECT_TRUE(framer_.ProcessPacket(encrypted));
-
- EXPECT_EQ(QUIC_NO_ERROR, framer_.error());
- ASSERT_TRUE(visitor_.header_.get());
- EXPECT_TRUE(CheckDecryption(encrypted, !kIncludeVersion, !kIncludePathId,
- !kIncludeDiversificationNonce));
-
- EXPECT_EQ(0u, visitor_.stream_frames_.size());
- ASSERT_EQ(1u, visitor_.ack_frames_.size());
- QuicAckFrame* frame = visitor_.ack_frames_[0].get();
- EXPECT_EQ(0xBA, frame->entropy_hash);
- EXPECT_EQ(kLargestObserved, frame->largest_observed);
- ASSERT_EQ(500u, frame->packets.NumPacketsSlow());
- EXPECT_EQ(kMissingPacket - 499, frame->packets.Min());
- EXPECT_EQ(kMissingPacket, frame->packets.Max());
-
- // Verify that the packet re-serializes identically.
- QuicFrames frames;
- frames.push_back(QuicFrame(frame));
- std::unique_ptr<QuicPacket> data(BuildDataPacket(*visitor_.header_, frames));
- ASSERT_TRUE(data != nullptr);
-
- test::CompareCharArraysWithHexError("constructed packet", data->data(),
- data->length(), AsChars(packet),
- arraysize(packet));
-}
-
-TEST_P(QuicFramerTest, StopWaitingFrame) {
- if (framer_.version() > QUIC_VERSION_33) {
- return;
- }
- // clang-format off
- unsigned char packet[] = {
- // public flags (8 byte connection_id)
- 0x38,
- // connection_id
- 0x10, 0x32, 0x54, 0x76,
- 0x98, 0xBA, 0xDC, 0xFE,
- // packet number
- 0xA8, 0x9A, 0x78, 0x56,
- 0x34, 0x12,
- // private flags (entropy)
- 0x01,
-
- // frame type (ack frame)
- // (has nacks, not truncated, 6 byte largest observed, 1 byte delta)
- 0x06,
- // entropy hash of sent packets till least awaiting - 1.
- 0xAB,
- // least packet number awaiting an ack, delta from packet number.
- 0x08, 0x00, 0x00, 0x00,
- 0x00, 0x00,
- };
- // clang-format on
-
- QuicEncryptedPacket encrypted(AsChars(packet), arraysize(packet), false);
- EXPECT_TRUE(framer_.ProcessPacket(encrypted));
-
- EXPECT_EQ(QUIC_NO_ERROR, framer_.error());
- ASSERT_TRUE(visitor_.header_.get());
- EXPECT_TRUE(CheckDecryption(encrypted, !kIncludeVersion, !kIncludePathId,
- !kIncludeDiversificationNonce));
-
- EXPECT_EQ(0u, visitor_.stream_frames_.size());
- ASSERT_EQ(1u, visitor_.stop_waiting_frames_.size());
- const QuicStopWaitingFrame& frame = *visitor_.stop_waiting_frames_[0].get();
- EXPECT_EQ(0xAB, frame.entropy_hash);
- EXPECT_EQ(kLeastUnacked, frame.least_unacked);
-
- const size_t kSentEntropyOffset = kQuicFrameTypeSize;
- const size_t kLeastUnackedOffset = kSentEntropyOffset + kQuicEntropyHashSize;
- const size_t frame_size = 7;
- for (size_t i = kQuicFrameTypeSize; i < frame_size; ++i) {
- string expected_error;
- if (i < kLeastUnackedOffset) {
- expected_error = "Unable to read entropy hash for sent packets.";
- } else {
- expected_error = "Unable to read least unacked delta.";
- }
- CheckProcessingFails(
- packet,
- i + GetPacketHeaderSize(framer_.version(), PACKET_8BYTE_CONNECTION_ID,
- !kIncludeVersion, !kIncludePathId,
- !kIncludeDiversificationNonce,
- PACKET_6BYTE_PACKET_NUMBER),
- expected_error, QUIC_INVALID_STOP_WAITING_DATA);
- }
-}
-
TEST_P(QuicFramerTest, NewStopWaitingFrame) {
- if (framer_.version() <= QUIC_VERSION_33) {
- return;
- }
// clang-format off
unsigned char packet[] = {
// public flags (8 byte connection_id)
@@ -3010,7 +1866,7 @@ TEST_P(QuicFramerTest, NewStopWaitingFrame) {
EXPECT_EQ(0u, visitor_.stream_frames_.size());
ASSERT_EQ(1u, visitor_.stop_waiting_frames_.size());
- const QuicStopWaitingFrame& frame = *visitor_.stop_waiting_frames_[0].get();
+ const QuicStopWaitingFrame& frame = *visitor_.stop_waiting_frames_[0];
EXPECT_EQ(kLeastUnacked, frame.least_unacked);
const size_t frame_size = 7;
@@ -3038,30 +1894,6 @@ TEST_P(QuicFramerTest, RstStreamFrameQuic) {
// packet number
0xBC, 0x9A, 0x78, 0x56,
0x34, 0x12,
- // private flags
- 0x00,
-
- // frame type (rst stream frame)
- 0x01,
- // stream id
- 0x04, 0x03, 0x02, 0x01,
-
- // sent byte offset
- 0x54, 0x76, 0x10, 0x32,
- 0xDC, 0xFE, 0x98, 0xBA,
-
- // error code
- 0x01, 0x00, 0x00, 0x00,
- };
- unsigned char packet_34[] = {
- // public flags (8 byte connection_id)
- 0x38,
- // connection_id
- 0x10, 0x32, 0x54, 0x76,
- 0x98, 0xBA, 0xDC, 0xFE,
- // packet number
- 0xBC, 0x9A, 0x78, 0x56,
- 0x34, 0x12,
// frame type (rst stream frame)
0x01,
@@ -3077,11 +1909,7 @@ TEST_P(QuicFramerTest, RstStreamFrameQuic) {
};
// clang-format on
- QuicEncryptedPacket encrypted(
- AsChars(framer_.version() <= QUIC_VERSION_33 ? packet : packet_34),
- framer_.version() <= QUIC_VERSION_33 ? arraysize(packet)
- : arraysize(packet_34),
- false);
+ QuicEncryptedPacket encrypted(AsChars(packet), arraysize(packet), false);
EXPECT_TRUE(framer_.ProcessPacket(encrypted));
EXPECT_EQ(QUIC_NO_ERROR, framer_.error());
@@ -3107,7 +1935,7 @@ TEST_P(QuicFramerTest, RstStreamFrameQuic) {
expected_error = "Unable to read rst stream error code.";
}
CheckProcessingFails(
- framer_.version() <= QUIC_VERSION_33 ? packet : packet_34,
+ packet,
i + GetPacketHeaderSize(framer_.version(), PACKET_8BYTE_CONNECTION_ID,
!kIncludeVersion, !kIncludePathId,
!kIncludeDiversificationNonce,
@@ -3127,31 +1955,6 @@ TEST_P(QuicFramerTest, ConnectionCloseFrame) {
// packet number
0xBC, 0x9A, 0x78, 0x56,
0x34, 0x12,
- // private flags
- 0x00,
-
- // frame type (connection close frame)
- 0x02,
- // error code
- 0x11, 0x00, 0x00, 0x00,
-
- // error details length
- 0x0d, 0x00,
- // error details
- 'b', 'e', 'c', 'a',
- 'u', 's', 'e', ' ',
- 'I', ' ', 'c', 'a',
- 'n',
- };
- unsigned char packet_34[] = {
- // public flags (8 byte connection_id)
- 0x38,
- // connection_id
- 0x10, 0x32, 0x54, 0x76,
- 0x98, 0xBA, 0xDC, 0xFE,
- // packet number
- 0xBC, 0x9A, 0x78, 0x56,
- 0x34, 0x12,
// frame type (connection close frame)
0x02,
@@ -3168,11 +1971,7 @@ TEST_P(QuicFramerTest, ConnectionCloseFrame) {
};
// clang-format on
- QuicEncryptedPacket encrypted(
- AsChars(framer_.version() <= QUIC_VERSION_33 ? packet : packet_34),
- framer_.version() <= QUIC_VERSION_33 ? arraysize(packet)
- : arraysize(packet_34),
- false);
+ QuicEncryptedPacket encrypted(AsChars(packet), arraysize(packet), false);
EXPECT_TRUE(framer_.ProcessPacket(encrypted));
EXPECT_EQ(QUIC_NO_ERROR, framer_.error());
@@ -3197,7 +1996,7 @@ TEST_P(QuicFramerTest, ConnectionCloseFrame) {
expected_error = "Unable to read connection close error details.";
}
CheckProcessingFails(
- framer_.version() <= QUIC_VERSION_33 ? packet : packet_34,
+ packet,
i + GetPacketHeaderSize(framer_.version(), PACKET_8BYTE_CONNECTION_ID,
!kIncludeVersion, !kIncludePathId,
!kIncludeDiversificationNonce,
@@ -3217,32 +2016,6 @@ TEST_P(QuicFramerTest, GoAwayFrame) {
// packet number
0xBC, 0x9A, 0x78, 0x56,
0x34, 0x12,
- // private flags
- 0x00,
-
- // frame type (go away frame)
- 0x03,
- // error code
- 0x09, 0x00, 0x00, 0x00,
- // stream id
- 0x04, 0x03, 0x02, 0x01,
- // error details length
- 0x0d, 0x00,
- // error details
- 'b', 'e', 'c', 'a',
- 'u', 's', 'e', ' ',
- 'I', ' ', 'c', 'a',
- 'n',
- };
- unsigned char packet_34[] = {
- // public flags (8 byte connection_id)
- 0x38,
- // connection_id
- 0x10, 0x32, 0x54, 0x76,
- 0x98, 0xBA, 0xDC, 0xFE,
- // packet number
- 0xBC, 0x9A, 0x78, 0x56,
- 0x34, 0x12,
// frame type (go away frame)
0x03,
@@ -3260,11 +2033,7 @@ TEST_P(QuicFramerTest, GoAwayFrame) {
};
// clang-format on
- QuicEncryptedPacket encrypted(
- AsChars(framer_.version() <= QUIC_VERSION_33 ? packet : packet_34),
- framer_.version() <= QUIC_VERSION_33 ? arraysize(packet)
- : arraysize(packet_34),
- false);
+ QuicEncryptedPacket encrypted(AsChars(packet), arraysize(packet), false);
EXPECT_TRUE(framer_.ProcessPacket(encrypted));
EXPECT_EQ(QUIC_NO_ERROR, framer_.error());
@@ -3290,7 +2059,7 @@ TEST_P(QuicFramerTest, GoAwayFrame) {
expected_error = "Unable to read goaway reason.";
}
CheckProcessingFails(
- framer_.version() <= QUIC_VERSION_33 ? packet : packet_34,
+ packet,
i + GetPacketHeaderSize(framer_.version(), PACKET_8BYTE_CONNECTION_ID,
!kIncludeVersion, !kIncludePathId,
!kIncludeDiversificationNonce,
@@ -3310,26 +2079,6 @@ TEST_P(QuicFramerTest, WindowUpdateFrame) {
// packet number
0xBC, 0x9A, 0x78, 0x56,
0x34, 0x12,
- // private flags
- 0x00,
-
- // frame type (window update frame)
- 0x04,
- // stream id
- 0x04, 0x03, 0x02, 0x01,
- // byte offset
- 0x54, 0x76, 0x10, 0x32,
- 0xDC, 0xFE, 0x98, 0xBA,
- };
- unsigned char packet_34[] = {
- // public flags (8 byte connection_id)
- 0x38,
- // connection_id
- 0x10, 0x32, 0x54, 0x76,
- 0x98, 0xBA, 0xDC, 0xFE,
- // packet number
- 0xBC, 0x9A, 0x78, 0x56,
- 0x34, 0x12,
// frame type (window update frame)
0x04,
@@ -3341,12 +2090,7 @@ TEST_P(QuicFramerTest, WindowUpdateFrame) {
};
// clang-format on
- QuicEncryptedPacket encrypted(
- AsChars(framer_.version() <= QUIC_VERSION_33 ? packet : packet_34),
- framer_.version() <= QUIC_VERSION_33 ? arraysize(packet)
- : arraysize(packet_34),
- false);
-
+ QuicEncryptedPacket encrypted(AsChars(packet), arraysize(packet), false);
EXPECT_TRUE(framer_.ProcessPacket(encrypted));
EXPECT_EQ(QUIC_NO_ERROR, framer_.error());
@@ -3367,7 +2111,7 @@ TEST_P(QuicFramerTest, WindowUpdateFrame) {
expected_error = "Unable to read window byte_offset.";
}
CheckProcessingFails(
- framer_.version() <= QUIC_VERSION_33 ? packet : packet_34,
+ packet,
i + GetPacketHeaderSize(framer_.version(), PACKET_8BYTE_CONNECTION_ID,
!kIncludeVersion, !kIncludePathId,
!kIncludeDiversificationNonce,
@@ -3387,23 +2131,6 @@ TEST_P(QuicFramerTest, BlockedFrame) {
// packet number
0xBC, 0x9A, 0x78, 0x56,
0x34, 0x12,
- // private flags
- 0x00,
-
- // frame type (blocked frame)
- 0x05,
- // stream id
- 0x04, 0x03, 0x02, 0x01,
- };
- unsigned char packet_34[] = {
- // public flags (8 byte connection_id)
- 0x38,
- // connection_id
- 0x10, 0x32, 0x54, 0x76,
- 0x98, 0xBA, 0xDC, 0xFE,
- // packet number
- 0xBC, 0x9A, 0x78, 0x56,
- 0x34, 0x12,
// frame type (blocked frame)
0x05,
@@ -3412,12 +2139,7 @@ TEST_P(QuicFramerTest, BlockedFrame) {
};
// clang-format on
- QuicEncryptedPacket encrypted(
- AsChars(framer_.version() <= QUIC_VERSION_33 ? packet : packet_34),
- framer_.version() <= QUIC_VERSION_33 ? arraysize(packet)
- : arraysize(packet_34),
- false);
-
+ QuicEncryptedPacket encrypted(AsChars(packet), arraysize(packet), false);
EXPECT_TRUE(framer_.ProcessPacket(encrypted));
EXPECT_EQ(QUIC_NO_ERROR, framer_.error());
@@ -3432,7 +2154,7 @@ TEST_P(QuicFramerTest, BlockedFrame) {
++i) {
string expected_error = "Unable to read stream_id.";
CheckProcessingFails(
- framer_.version() <= QUIC_VERSION_33 ? packet : packet_34,
+ packet,
i + GetPacketHeaderSize(framer_.version(), PACKET_8BYTE_CONNECTION_ID,
!kIncludeVersion, !kIncludePathId,
!kIncludeDiversificationNonce,
@@ -3452,32 +2174,13 @@ TEST_P(QuicFramerTest, PingFrame) {
// packet number
0xBC, 0x9A, 0x78, 0x56,
0x34, 0x12,
- // private flags
- 0x00,
-
- // frame type (ping frame)
- 0x07,
- };
- unsigned char packet_34[] = {
- // public flags (8 byte connection_id)
- 0x38,
- // connection_id
- 0x10, 0x32, 0x54, 0x76,
- 0x98, 0xBA, 0xDC, 0xFE,
- // packet number
- 0xBC, 0x9A, 0x78, 0x56,
- 0x34, 0x12,
// frame type (ping frame)
0x07,
};
// clang-format on
- QuicEncryptedPacket encrypted(
- AsChars(framer_.version() <= QUIC_VERSION_33 ? packet : packet_34),
- framer_.version() <= QUIC_VERSION_33 ? arraysize(packet)
- : arraysize(packet_34),
- false);
+ QuicEncryptedPacket encrypted(AsChars(packet), arraysize(packet), false);
EXPECT_TRUE(framer_.ProcessPacket(encrypted));
EXPECT_EQ(QUIC_NO_ERROR, framer_.error());
@@ -3501,23 +2204,6 @@ TEST_P(QuicFramerTest, PathCloseFrame) {
0x00,
// packet number
0xBC, 0x9A, 0x78, 0x56, 0x34, 0x12,
- // private flags
- 0x00,
-
- // frame type (path_close_frame)
- 0x08,
- // path id
- 0x42,
- };
- unsigned char packet_34[] = {
- // public flags (version)
- 0x78,
- // connection_id
- 0x10, 0x32, 0x54, 0x76, 0x98, 0xBA, 0xDC, 0xFE,
- // path_id
- 0x00,
- // packet number
- 0xBC, 0x9A, 0x78, 0x56, 0x34, 0x12,
// frame type (path_close_frame)
0x08,
@@ -3526,11 +2212,7 @@ TEST_P(QuicFramerTest, PathCloseFrame) {
};
// clang-format on
- QuicEncryptedPacket encrypted(
- AsChars(framer_.version() <= QUIC_VERSION_33 ? packet : packet_34),
- framer_.version() <= QUIC_VERSION_33 ? arraysize(packet)
- : arraysize(packet_34),
- false);
+ QuicEncryptedPacket encrypted(AsChars(packet), arraysize(packet), false);
EXPECT_TRUE(framer_.ProcessPacket(encrypted));
EXPECT_EQ(QUIC_NO_ERROR, framer_.error());
@@ -3546,7 +2228,7 @@ TEST_P(QuicFramerTest, PathCloseFrame) {
expected_error = "Unable to read path_id.";
}
CheckProcessingFails(
- framer_.version() <= QUIC_VERSION_33 ? packet : packet_34,
+ packet,
i + GetPacketHeaderSize(framer_.version(), PACKET_8BYTE_CONNECTION_ID,
!kIncludeVersion, kIncludePathId,
!kIncludeDiversificationNonce,
@@ -3594,13 +2276,14 @@ TEST_P(QuicFramerTest, PublicResetPacketV33) {
EXPECT_FALSE(visitor_.public_reset_packet_->public_header.version_flag);
EXPECT_EQ(kNonceProof, visitor_.public_reset_packet_->nonce_proof);
EXPECT_EQ(0u, visitor_.public_reset_packet_->rejected_packet_number);
- EXPECT_EQ(ADDRESS_FAMILY_UNSPECIFIED,
- visitor_.public_reset_packet_->client_address.GetFamily());
+ EXPECT_EQ(
+ IpAddressFamily::IP_UNSPEC,
+ visitor_.public_reset_packet_->client_address.host().address_family());
// Now test framing boundaries.
for (size_t i = 0; i < arraysize(packet); ++i) {
string expected_error;
- DVLOG(1) << "iteration: " << i;
+ QUIC_DLOG(INFO) << "iteration: " << i;
if (i < kConnectionIdOffset) {
expected_error = "Unable to read public flags.";
CheckProcessingFails(packet, i, expected_error,
@@ -3658,13 +2341,14 @@ TEST_P(QuicFramerTest, PublicResetPacket) {
EXPECT_FALSE(visitor_.public_reset_packet_->public_header.version_flag);
EXPECT_EQ(kNonceProof, visitor_.public_reset_packet_->nonce_proof);
EXPECT_EQ(0u, visitor_.public_reset_packet_->rejected_packet_number);
- EXPECT_EQ(ADDRESS_FAMILY_UNSPECIFIED,
- visitor_.public_reset_packet_->client_address.GetFamily());
+ EXPECT_EQ(
+ IpAddressFamily::IP_UNSPEC,
+ visitor_.public_reset_packet_->client_address.host().address_family());
// Now test framing boundaries.
for (size_t i = 0; i < arraysize(packet); ++i) {
string expected_error;
- DVLOG(1) << "iteration: " << i;
+ QUIC_DLOG(INFO) << "iteration: " << i;
if (i < kConnectionIdOffset) {
expected_error = "Unable to read public flags.";
CheckProcessingFails(packet, i, expected_error,
@@ -3765,13 +2449,13 @@ TEST_P(QuicFramerTest, PublicResetPacketWithClientAddress) {
EXPECT_EQ(kNonceProof, visitor_.public_reset_packet_->nonce_proof);
EXPECT_EQ(0u, visitor_.public_reset_packet_->rejected_packet_number);
EXPECT_EQ("4.31.198.44",
- visitor_.public_reset_packet_->client_address.address().ToString());
+ visitor_.public_reset_packet_->client_address.host().ToString());
EXPECT_EQ(443, visitor_.public_reset_packet_->client_address.port());
// Now test framing boundaries.
for (size_t i = 0; i < arraysize(packet); ++i) {
string expected_error;
- DVLOG(1) << "iteration: " << i;
+ QUIC_DLOG(INFO) << "iteration: " << i;
if (i < kConnectionIdOffset) {
expected_error = "Unable to read public flags.";
CheckProcessingFails(packet, i, expected_error,
@@ -3869,34 +2553,13 @@ TEST_P(QuicFramerTest, BuildPaddingFramePacket) {
header.public_header.connection_id = kConnectionId;
header.public_header.reset_flag = false;
header.public_header.version_flag = false;
- header.entropy_flag = false;
header.packet_number = kPacketNumber;
- QuicPaddingFrame padding_frame;
-
- QuicFrames frames;
- frames.push_back(QuicFrame(padding_frame));
+ QuicFrames frames = {QuicFrame(QuicPaddingFrame())};
// clang-format off
unsigned char packet[kMaxPacketSize] = {
// public flags (8 byte connection_id)
- static_cast<unsigned char>(
- framer_.version() > QUIC_VERSION_32 ? 0x38 : 0x3C),
- // connection_id
- 0x10, 0x32, 0x54, 0x76,
- 0x98, 0xBA, 0xDC, 0xFE,
- // packet number
- 0xBC, 0x9A, 0x78, 0x56,
- 0x34, 0x12,
- // private flags
- 0x00,
-
- // frame type (padding frame)
- 0x00,
- 0x00, 0x00, 0x00, 0x00
- };
- unsigned char packet_34[kMaxPacketSize] = {
- // public flags (8 byte connection_id)
0x38,
// connection_id
0x10, 0x32, 0x54, 0x76,
@@ -3915,18 +2578,14 @@ TEST_P(QuicFramerTest, BuildPaddingFramePacket) {
framer_.version(), PACKET_8BYTE_CONNECTION_ID, !kIncludeVersion,
!kIncludePathId, !kIncludeDiversificationNonce,
PACKET_6BYTE_PACKET_NUMBER);
- memset((framer_.version() <= QUIC_VERSION_33 ? packet : packet_34) +
- header_size + 1,
- 0x00, kMaxPacketSize - header_size - 1);
+ memset(packet + header_size + 1, 0x00, kMaxPacketSize - header_size - 1);
std::unique_ptr<QuicPacket> data(BuildDataPacket(header, frames));
ASSERT_TRUE(data != nullptr);
- test::CompareCharArraysWithHexError(
- "constructed packet", data->data(), data->length(),
- AsChars(framer_.version() <= QUIC_VERSION_33 ? packet : packet_34),
- framer_.version() <= QUIC_VERSION_33 ? arraysize(packet)
- : arraysize(packet_34));
+ test::CompareCharArraysWithHexError("constructed packet", data->data(),
+ data->length(), AsChars(packet),
+ arraysize(packet));
}
TEST_P(QuicFramerTest, Build4ByteSequenceNumberPaddingFramePacket) {
@@ -3934,34 +2593,14 @@ TEST_P(QuicFramerTest, Build4ByteSequenceNumberPaddingFramePacket) {
header.public_header.connection_id = kConnectionId;
header.public_header.reset_flag = false;
header.public_header.version_flag = false;
- header.entropy_flag = false;
header.public_header.packet_number_length = PACKET_4BYTE_PACKET_NUMBER;
header.packet_number = kPacketNumber;
- QuicPaddingFrame padding_frame;
-
- QuicFrames frames;
- frames.push_back(QuicFrame(padding_frame));
+ QuicFrames frames = {QuicFrame(QuicPaddingFrame())};
// clang-format off
unsigned char packet[kMaxPacketSize] = {
// public flags (8 byte connection_id and 4 byte packet number)
- static_cast<unsigned char>(
- framer_.version() > QUIC_VERSION_32 ? 0x28 : 0x2C),
- // connection_id
- 0x10, 0x32, 0x54, 0x76,
- 0x98, 0xBA, 0xDC, 0xFE,
- // packet number
- 0xBC, 0x9A, 0x78, 0x56,
- // private flags
- 0x00,
-
- // frame type (padding frame)
- 0x00,
- 0x00, 0x00, 0x00, 0x00
- };
- unsigned char packet_34[kMaxPacketSize] = {
- // public flags (8 byte connection_id and 4 byte packet number)
0x28,
// connection_id
0x10, 0x32, 0x54, 0x76,
@@ -3979,18 +2618,14 @@ TEST_P(QuicFramerTest, Build4ByteSequenceNumberPaddingFramePacket) {
framer_.version(), PACKET_8BYTE_CONNECTION_ID, !kIncludeVersion,
!kIncludePathId, !kIncludeDiversificationNonce,
PACKET_4BYTE_PACKET_NUMBER);
- memset((framer_.version() <= QUIC_VERSION_33 ? packet : packet_34) +
- header_size + 1,
- 0x00, kMaxPacketSize - header_size - 1);
+ memset(packet + header_size + 1, 0x00, kMaxPacketSize - header_size - 1);
std::unique_ptr<QuicPacket> data(BuildDataPacket(header, frames));
ASSERT_TRUE(data != nullptr);
- test::CompareCharArraysWithHexError(
- "constructed packet", data->data(), data->length(),
- AsChars(framer_.version() <= QUIC_VERSION_33 ? packet : packet_34),
- framer_.version() <= QUIC_VERSION_33 ? arraysize(packet)
- : arraysize(packet_34));
+ test::CompareCharArraysWithHexError("constructed packet", data->data(),
+ data->length(), AsChars(packet),
+ arraysize(packet));
}
TEST_P(QuicFramerTest, Build2ByteSequenceNumberPaddingFramePacket) {
@@ -3998,34 +2633,14 @@ TEST_P(QuicFramerTest, Build2ByteSequenceNumberPaddingFramePacket) {
header.public_header.connection_id = kConnectionId;
header.public_header.reset_flag = false;
header.public_header.version_flag = false;
- header.entropy_flag = false;
header.public_header.packet_number_length = PACKET_2BYTE_PACKET_NUMBER;
header.packet_number = kPacketNumber;
- QuicPaddingFrame padding_frame;
-
- QuicFrames frames;
- frames.push_back(QuicFrame(padding_frame));
+ QuicFrames frames = {QuicFrame(QuicPaddingFrame())};
// clang-format off
unsigned char packet[kMaxPacketSize] = {
// public flags (8 byte connection_id and 2 byte packet number)
- static_cast<unsigned char>(
- framer_.version() > QUIC_VERSION_32 ? 0x18 : 0x1C),
- // connection_id
- 0x10, 0x32, 0x54, 0x76,
- 0x98, 0xBA, 0xDC, 0xFE,
- // packet number
- 0xBC, 0x9A,
- // private flags
- 0x00,
-
- // frame type (padding frame)
- 0x00,
- 0x00, 0x00, 0x00, 0x00
- };
- unsigned char packet_34[kMaxPacketSize] = {
- // public flags (8 byte connection_id and 2 byte packet number)
0x18,
// connection_id
0x10, 0x32, 0x54, 0x76,
@@ -4043,18 +2658,14 @@ TEST_P(QuicFramerTest, Build2ByteSequenceNumberPaddingFramePacket) {
framer_.version(), PACKET_8BYTE_CONNECTION_ID, !kIncludeVersion,
!kIncludePathId, !kIncludeDiversificationNonce,
PACKET_2BYTE_PACKET_NUMBER);
- memset((framer_.version() <= QUIC_VERSION_33 ? packet : packet_34) +
- header_size + 1,
- 0x00, kMaxPacketSize - header_size - 1);
+ memset(packet + header_size + 1, 0x00, kMaxPacketSize - header_size - 1);
std::unique_ptr<QuicPacket> data(BuildDataPacket(header, frames));
ASSERT_TRUE(data != nullptr);
- test::CompareCharArraysWithHexError(
- "constructed packet", data->data(), data->length(),
- AsChars(framer_.version() <= QUIC_VERSION_33 ? packet : packet_34),
- framer_.version() <= QUIC_VERSION_33 ? arraysize(packet)
- : arraysize(packet_34));
+ test::CompareCharArraysWithHexError("constructed packet", data->data(),
+ data->length(), AsChars(packet),
+ arraysize(packet));
}
TEST_P(QuicFramerTest, Build1ByteSequenceNumberPaddingFramePacket) {
@@ -4062,34 +2673,14 @@ TEST_P(QuicFramerTest, Build1ByteSequenceNumberPaddingFramePacket) {
header.public_header.connection_id = kConnectionId;
header.public_header.reset_flag = false;
header.public_header.version_flag = false;
- header.entropy_flag = false;
header.public_header.packet_number_length = PACKET_1BYTE_PACKET_NUMBER;
header.packet_number = kPacketNumber;
- QuicPaddingFrame padding_frame;
-
- QuicFrames frames;
- frames.push_back(QuicFrame(padding_frame));
+ QuicFrames frames = {QuicFrame(QuicPaddingFrame())};
// clang-format off
unsigned char packet[kMaxPacketSize] = {
// public flags (8 byte connection_id and 1 byte packet number)
- static_cast<unsigned char>(
- framer_.version() > QUIC_VERSION_32 ? 0x08 : 0x0C),
- // connection_id
- 0x10, 0x32, 0x54, 0x76,
- 0x98, 0xBA, 0xDC, 0xFE,
- // packet number
- 0xBC,
- // private flags
- 0x00,
-
- // frame type (padding frame)
- 0x00,
- 0x00, 0x00, 0x00, 0x00
- };
- unsigned char packet_34[kMaxPacketSize] = {
- // public flags (8 byte connection_id and 1 byte packet number)
0x08,
// connection_id
0x10, 0x32, 0x54, 0x76,
@@ -4107,18 +2698,14 @@ TEST_P(QuicFramerTest, Build1ByteSequenceNumberPaddingFramePacket) {
framer_.version(), PACKET_8BYTE_CONNECTION_ID, !kIncludeVersion,
!kIncludePathId, !kIncludeDiversificationNonce,
PACKET_1BYTE_PACKET_NUMBER);
- memset((framer_.version() <= QUIC_VERSION_33 ? packet : packet_34) +
- header_size + 1,
- 0x00, kMaxPacketSize - header_size - 1);
+ memset(packet + header_size + 1, 0x00, kMaxPacketSize - header_size - 1);
std::unique_ptr<QuicPacket> data(BuildDataPacket(header, frames));
ASSERT_TRUE(data != nullptr);
- test::CompareCharArraysWithHexError(
- "constructed packet", data->data(), data->length(),
- AsChars(framer_.version() <= QUIC_VERSION_33 ? packet : packet_34),
- framer_.version() <= QUIC_VERSION_33 ? arraysize(packet)
- : arraysize(packet_34));
+ test::CompareCharArraysWithHexError("constructed packet", data->data(),
+ data->length(), AsChars(packet),
+ arraysize(packet));
}
TEST_P(QuicFramerTest, BuildStreamFramePacket) {
@@ -4126,43 +2713,16 @@ TEST_P(QuicFramerTest, BuildStreamFramePacket) {
header.public_header.connection_id = kConnectionId;
header.public_header.reset_flag = false;
header.public_header.version_flag = false;
- header.entropy_flag = true;
header.packet_number = kPacketNumber;
QuicStreamFrame stream_frame(kStreamId, true, kStreamOffset,
StringPiece("hello world!"));
- QuicFrames frames;
- frames.push_back(QuicFrame(&stream_frame));
+ QuicFrames frames = {QuicFrame(&stream_frame)};
// clang-format off
unsigned char packet[] = {
// public flags (8 byte connection_id)
- static_cast<unsigned char>(
- framer_.version() > QUIC_VERSION_32 ? 0x38 : 0x3C),
- // connection_id
- 0x10, 0x32, 0x54, 0x76,
- 0x98, 0xBA, 0xDC, 0xFE,
- // packet number
- 0xBC, 0x9A, 0x78, 0x56,
- 0x34, 0x12,
- // private flags (entropy)
- 0x01,
-
- // frame type (stream frame with fin and no length)
- 0xDF,
- // stream id
- 0x04, 0x03, 0x02, 0x01,
- // offset
- 0x54, 0x76, 0x10, 0x32,
- 0xDC, 0xFE, 0x98, 0xBA,
- // data
- 'h', 'e', 'l', 'l',
- 'o', ' ', 'w', 'o',
- 'r', 'l', 'd', '!',
- };
- unsigned char packet_34[] = {
- // public flags (8 byte connection_id)
0x38,
// connection_id
0x10, 0x32, 0x54, 0x76,
@@ -4188,11 +2748,9 @@ TEST_P(QuicFramerTest, BuildStreamFramePacket) {
std::unique_ptr<QuicPacket> data(BuildDataPacket(header, frames));
ASSERT_TRUE(data != nullptr);
- test::CompareCharArraysWithHexError(
- "constructed packet", data->data(), data->length(),
- AsChars(framer_.version() <= QUIC_VERSION_33 ? packet : packet_34),
- framer_.version() <= QUIC_VERSION_33 ? arraysize(packet)
- : arraysize(packet_34));
+ test::CompareCharArraysWithHexError("constructed packet", data->data(),
+ data->length(), AsChars(packet),
+ arraysize(packet));
}
TEST_P(QuicFramerTest, BuildStreamFramePacketWithVersionFlag) {
@@ -4200,43 +2758,17 @@ TEST_P(QuicFramerTest, BuildStreamFramePacketWithVersionFlag) {
header.public_header.connection_id = kConnectionId;
header.public_header.reset_flag = false;
header.public_header.version_flag = true;
- header.entropy_flag = true;
header.packet_number = kPacketNumber;
QuicStreamFrame stream_frame(kStreamId, true, kStreamOffset,
StringPiece("hello world!"));
-
- QuicFrames frames;
- frames.push_back(QuicFrame(&stream_frame));
+ QuicFrames frames = {QuicFrame(&stream_frame)};
// clang-format off
unsigned char packet[] = {
// public flags (version, 8 byte connection_id)
static_cast<unsigned char>(
- (FLAGS_quic_remove_v33_hacks2 &&
- framer_.version() > QUIC_VERSION_32) ? 0x39 : 0x3D),
- // connection_id
- 0x10, 0x32, 0x54, 0x76, 0x98, 0xBA, 0xDC, 0xFE,
- // version tag
- 'Q', '0', GetQuicVersionDigitTens(), GetQuicVersionDigitOnes(),
- // packet number
- 0xBC, 0x9A, 0x78, 0x56, 0x34, 0x12,
- // private flags (entropy)
- 0x01,
-
- // frame type (stream frame with fin and no length)
- 0xDF,
- // stream id
- 0x04, 0x03, 0x02, 0x01,
- // offset
- 0x54, 0x76, 0x10, 0x32, 0xDC, 0xFE, 0x98, 0xBA,
- // data
- 'h', 'e', 'l', 'l', 'o', ' ', 'w', 'o', 'r', 'l', 'd', '!',
- };
- unsigned char packet_34[] = {
- // public flags (version, 8 byte connection_id)
- static_cast<unsigned char>(
- FLAGS_quic_remove_v33_hacks2 ? 0x39 : 0x3D),
+ FLAGS_quic_reloadable_flag_quic_remove_v33_hacks2 ? 0x39 : 0x3D),
// connection_id
0x10, 0x32, 0x54, 0x76, 0x98, 0xBA, 0xDC, 0xFE,
// version tag
@@ -4259,11 +2791,9 @@ TEST_P(QuicFramerTest, BuildStreamFramePacketWithVersionFlag) {
std::unique_ptr<QuicPacket> data(BuildDataPacket(header, frames));
ASSERT_TRUE(data != nullptr);
- test::CompareCharArraysWithHexError(
- "constructed packet", data->data(), data->length(),
- AsChars(framer_.version() <= QUIC_VERSION_33 ? packet : packet_34),
- framer_.version() <= QUIC_VERSION_33 ? arraysize(packet)
- : arraysize(packet_34));
+ test::CompareCharArraysWithHexError("constructed packet", data->data(),
+ data->length(), AsChars(packet),
+ arraysize(packet));
}
TEST_P(QuicFramerTest, BuildStreamFramePacketWithMultipathFlag) {
@@ -4272,46 +2802,16 @@ TEST_P(QuicFramerTest, BuildStreamFramePacketWithMultipathFlag) {
header.public_header.multipath_flag = true;
header.public_header.reset_flag = false;
header.public_header.version_flag = false;
- header.entropy_flag = true;
header.path_id = kPathId;
header.packet_number = kPacketNumber;
QuicStreamFrame stream_frame(kStreamId, true, kStreamOffset,
StringPiece("hello world!"));
-
- QuicFrames frames;
- frames.push_back(QuicFrame(&stream_frame));
+ QuicFrames frames = {QuicFrame(&stream_frame)};
// clang-format off
unsigned char packet[] = {
// public flags (8 byte connection_id)
- static_cast<unsigned char>(
- framer_.version() > QUIC_VERSION_32 ? 0x78 : 0x7C),
- // connection_id
- 0x10, 0x32, 0x54, 0x76,
- 0x98, 0xBA, 0xDC, 0xFE,
- // path_id
- 0x42,
- // packet number
- 0xBC, 0x9A, 0x78, 0x56,
- 0x34, 0x12,
- // private flags (entropy)
- 0x01,
-
- // frame type (stream frame with fin and no length)
- 0xDF,
- // stream id
- 0x04, 0x03, 0x02, 0x01,
- // offset
- 0x54, 0x76, 0x10, 0x32,
- 0xDC, 0xFE, 0x98, 0xBA,
- // data
- 'h', 'e', 'l', 'l',
- 'o', ' ', 'w', 'o',
- 'r', 'l', 'd', '!',
- };
- unsigned char packet_34[] = {
- // public flags (8 byte connection_id)
0x78,
// connection_id
0x10, 0x32, 0x54, 0x76,
@@ -4339,11 +2839,9 @@ TEST_P(QuicFramerTest, BuildStreamFramePacketWithMultipathFlag) {
std::unique_ptr<QuicPacket> data(BuildDataPacket(header, frames));
ASSERT_TRUE(data != nullptr);
- test::CompareCharArraysWithHexError(
- "constructed packet", data->data(), data->length(),
- AsChars(framer_.version() <= QUIC_VERSION_33 ? packet : packet_34),
- framer_.version() <= QUIC_VERSION_33 ? arraysize(packet)
- : arraysize(packet_34));
+ test::CompareCharArraysWithHexError("constructed packet", data->data(),
+ data->length(), AsChars(packet),
+ arraysize(packet));
}
TEST_P(QuicFramerTest, BuildStreamFramePacketWithBothVersionAndMultipathFlag) {
@@ -4352,51 +2850,18 @@ TEST_P(QuicFramerTest, BuildStreamFramePacketWithBothVersionAndMultipathFlag) {
header.public_header.multipath_flag = true;
header.public_header.reset_flag = false;
header.public_header.version_flag = true;
- header.entropy_flag = true;
header.path_id = kPathId;
header.packet_number = kPacketNumber;
QuicStreamFrame stream_frame(kStreamId, true, kStreamOffset,
StringPiece("hello world!"));
-
- QuicFrames frames;
- frames.push_back(QuicFrame(&stream_frame));
+ QuicFrames frames = {QuicFrame(&stream_frame)};
// clang-format off
unsigned char packet[] = {
// public flags (8 byte connection_id)
static_cast<unsigned char>(
- (FLAGS_quic_remove_v33_hacks2 &&
- framer_.version() > QUIC_VERSION_32) ? 0x79 : 0x7D),
- // connection_id
- 0x10, 0x32, 0x54, 0x76,
- 0x98, 0xBA, 0xDC, 0xFE,
- // version tag
- 'Q', '0', GetQuicVersionDigitTens(), GetQuicVersionDigitOnes(),
- // path_id
- 0x42,
- // packet number
- 0xBC, 0x9A, 0x78, 0x56,
- 0x34, 0x12,
- // private flags (entropy)
- 0x01,
-
- // frame type (stream frame with fin and no length)
- 0xDF,
- // stream id
- 0x04, 0x03, 0x02, 0x01,
- // offset
- 0x54, 0x76, 0x10, 0x32,
- 0xDC, 0xFE, 0x98, 0xBA,
- // data
- 'h', 'e', 'l', 'l',
- 'o', ' ', 'w', 'o',
- 'r', 'l', 'd', '!',
- };
- unsigned char packet_34[] = {
- // public flags (8 byte connection_id)
- static_cast<unsigned char>(
- FLAGS_quic_remove_v33_hacks2 ? 0x79 : 0x7D),
+ FLAGS_quic_reloadable_flag_quic_remove_v33_hacks2 ? 0x79 : 0x7D),
// connection_id
0x10, 0x32, 0x54, 0x76,
0x98, 0xBA, 0xDC, 0xFE,
@@ -4426,11 +2891,9 @@ TEST_P(QuicFramerTest, BuildStreamFramePacketWithBothVersionAndMultipathFlag) {
std::unique_ptr<QuicPacket> data(BuildDataPacket(header, frames));
ASSERT_TRUE(data != nullptr);
- test::CompareCharArraysWithHexError(
- "constructed packet", data->data(), data->length(),
- AsChars(framer_.version() <= QUIC_VERSION_33 ? packet : packet_34),
- framer_.version() <= QUIC_VERSION_33 ? arraysize(packet)
- : arraysize(packet_34));
+ test::CompareCharArraysWithHexError("constructed packet", data->data(),
+ data->length(), AsChars(packet),
+ arraysize(packet));
}
TEST_P(QuicFramerTest, BuildVersionNegotiationPacket) {
@@ -4454,252 +2917,7 @@ TEST_P(QuicFramerTest, BuildVersionNegotiationPacket) {
arraysize(packet));
}
-TEST_P(QuicFramerTest, BuildAckFramePacket) {
- if (framer_.version() > QUIC_VERSION_33) {
- return;
- }
-
- QuicPacketHeader header;
- header.public_header.connection_id = kConnectionId;
- header.public_header.reset_flag = false;
- header.public_header.version_flag = false;
- header.entropy_flag = true;
- header.packet_number = kPacketNumber;
-
- QuicAckFrame ack_frame;
- ack_frame.entropy_hash = 0x43;
- ack_frame.largest_observed = kLargestObserved;
- ack_frame.ack_delay_time = QuicTime::Delta::Zero();
- ack_frame.packets.Add(kMissingPacket);
-
- QuicFrames frames;
- frames.push_back(QuicFrame(&ack_frame));
-
- // clang-format off
- unsigned char packet[] = {
- // public flags (8 byte connection_id)
- static_cast<unsigned char>(
- framer_.version() > QUIC_VERSION_32 ? 0x38 : 0x3C),
- // connection_id
- 0x10, 0x32, 0x54, 0x76, 0x98, 0xBA, 0xDC, 0xFE,
- // packet number
- 0xBC, 0x9A, 0x78, 0x56, 0x34, 0x12,
- // private flags (entropy)
- 0x01,
-
- // frame type (ack frame)
- // (has nacks, not truncated, 6 byte largest observed, 1 byte delta)
- 0x6C,
- // entropy hash of all received packets.
- 0x43,
- // largest observed packet number
- 0xBF, 0x9A, 0x78, 0x56, 0x34, 0x12,
- // Zero delta time.
- 0x00, 0x00,
- // num received packets.
- 0x00,
- // num missing packet ranges
- 0x01,
- // missing packet delta
- 0x01,
- // 0 more missing packets in range.
- 0x00,
- };
- // clang-format on
-
- std::unique_ptr<QuicPacket> data(BuildDataPacket(header, frames));
- ASSERT_TRUE(data != nullptr);
-
- test::CompareCharArraysWithHexError("constructed packet", data->data(),
- data->length(), AsChars(packet),
- arraysize(packet));
-}
-
-// TODO(jri): Add test for tuncated packets in which the original ack frame had
-// revived packets. (In both the large and small packet cases below).
-
-TEST_P(QuicFramerTest, BuildTruncatedAckFrameLargePacket) {
- if (framer_.version() > QUIC_VERSION_33) {
- return;
- }
-
- QuicPacketHeader header;
- header.public_header.connection_id = kConnectionId;
- header.public_header.reset_flag = false;
- header.public_header.version_flag = false;
- header.entropy_flag = true;
- header.packet_number = kPacketNumber;
-
- QuicAckFrame ack_frame;
- // This entropy hash is different from what shows up in the packet below,
- // since entropy is recomputed by the framer on ack truncation (by
- // TestEntropyCalculator for this test.)
- ack_frame.entropy_hash = 0x43;
- ack_frame.largest_observed = 2 * 300;
- ack_frame.ack_delay_time = QuicTime::Delta::Zero();
- for (size_t i = 1; i < 2 * 300; i += 2) {
- ack_frame.packets.Add(i);
- }
-
- QuicFrames frames;
- frames.push_back(QuicFrame(&ack_frame));
-
- // clang-format off
- unsigned char packet[] = {
- // public flags (8 byte connection_id)
- static_cast<unsigned char>(
- framer_.version() > QUIC_VERSION_32 ? 0x38 : 0x3C),
- // connection_id
- 0x10, 0x32, 0x54, 0x76, 0x98, 0xBA, 0xDC, 0xFE,
- // packet number
- 0xBC, 0x9A, 0x78, 0x56, 0x34, 0x12,
- // private flags (entropy)
- 0x01,
-
- // frame type (ack frame)
- // (has nacks, is truncated, 2 byte largest observed, 1 byte delta)
- 0x74,
- // entropy hash of all received packets, set to 1 by TestEntropyCalculator
- // since ack is truncated.
- 0x01,
- // 2-byte largest observed packet number.
- // Expected to be 510 (0x1FE), since only 255 nack ranges can fit.
- 0xFE, 0x01,
- // Zero delta time.
- 0x00, 0x00,
- // num missing packet ranges (limited to 255 by size of this field).
- 0xFF,
- // {missing packet delta, further missing packets in range}
- // 6 nack ranges x 42 + 3 nack ranges
- 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00,
- 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00,
- 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00,
- 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00,
- 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00,
- 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00,
- 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00,
- 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00,
- 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00,
- 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00,
-
- 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00,
- 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00,
- 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00,
- 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00,
- 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00,
- 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00,
- 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00,
- 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00,
- 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00,
- 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00,
-
- 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00,
- 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00,
- 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00,
- 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00,
- 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00,
- 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00,
- 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00,
- 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00,
- 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00,
- 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00,
-
- 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00,
- 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00,
- 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00,
- 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00,
- 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00,
- 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00,
- 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00,
- 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00,
- 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00,
- 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00,
-
- 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00,
- 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00,
- 0x01, 0x00, 0x01, 0x00, 0x01, 0x00,
- };
- // clang-format on
-
- std::unique_ptr<QuicPacket> data(BuildDataPacket(header, frames));
- ASSERT_TRUE(data != nullptr);
-
- test::CompareCharArraysWithHexError("constructed packet", data->data(),
- data->length(), AsChars(packet),
- arraysize(packet));
-}
-
-TEST_P(QuicFramerTest, BuildTruncatedAckFrameSmallPacket) {
- if (framer_.version() > QUIC_VERSION_33) {
- return;
- }
-
- QuicPacketHeader header;
- header.public_header.connection_id = kConnectionId;
- header.public_header.reset_flag = false;
- header.public_header.version_flag = false;
- header.entropy_flag = true;
- header.packet_number = kPacketNumber;
-
- QuicAckFrame ack_frame;
- // This entropy hash is different from what shows up in the packet below,
- // since entropy is recomputed by the framer on ack truncation (by
- // TestEntropyCalculator for this test.)
- ack_frame.entropy_hash = 0x43;
- ack_frame.largest_observed = 2 * 300;
- ack_frame.ack_delay_time = QuicTime::Delta::Zero();
- for (size_t i = 1; i < 2 * 300; i += 2) {
- ack_frame.packets.Add(i);
- }
-
- QuicFrames frames;
- frames.push_back(QuicFrame(&ack_frame));
-
- // clang-format off
- unsigned char packet[] = {
- // public flags (8 byte connection_id)
- static_cast<unsigned char>(
- framer_.version() > QUIC_VERSION_32 ? 0x38 : 0x3C),
- // connection_id
- 0x10, 0x32, 0x54, 0x76, 0x98, 0xBA, 0xDC, 0xFE,
- // packet number
- 0xBC, 0x9A, 0x78, 0x56, 0x34, 0x12,
- // private flags (entropy)
- 0x01,
-
- // frame type (ack frame)
- // (has nacks, is truncated, 2 byte largest observed, 1 byte delta)
- 0x74,
- // entropy hash of all received packets, set to 1 by TestEntropyCalculator
- // since ack is truncated.
- 0x01,
- // 2-byte largest observed packet number.
- // Expected to be 12 (0x0C), since only 6 nack ranges can fit.
- 0x0C, 0x00,
- // Zero delta time.
- 0x00, 0x00,
- // num missing packet ranges (limited to 6 by packet size of 37).
- 0x06,
- // {missing packet delta, further missing packets in range}
- // 6 nack ranges
- 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00,
- };
- // clang-format on
-
- std::unique_ptr<QuicPacket> data(BuildDataPacket(header, frames, 36u));
- ASSERT_TRUE(data != nullptr);
- // Expect 1 byte unused since at least 2 bytes are needed to fit more nacks.
- EXPECT_EQ(35u, data->length());
- test::CompareCharArraysWithHexError("constructed packet", data->data(),
- data->length(), AsChars(packet),
- arraysize(packet));
-}
-
-TEST_P(QuicFramerTest, BuildNewAckFramePacketOneAckBlock) {
- if (framer_.version() <= QUIC_VERSION_33) {
- return;
- }
-
+TEST_P(QuicFramerTest, BuildAckFramePacketOneAckBlock) {
QuicPacketHeader header;
header.public_header.connection_id = kConnectionId;
header.public_header.reset_flag = false;
@@ -4710,11 +2928,9 @@ TEST_P(QuicFramerTest, BuildNewAckFramePacketOneAckBlock) {
QuicAckFrame ack_frame;
ack_frame.largest_observed = kSmallLargestObserved;
ack_frame.ack_delay_time = QuicTime::Delta::Zero();
- ack_frame.missing = false;
ack_frame.packets.Add(1, kSmallLargestObserved + 1);
- QuicFrames frames;
- frames.push_back(QuicFrame(&ack_frame));
+ QuicFrames frames = {QuicFrame(&ack_frame)};
// clang-format off
unsigned char packet[] = {
@@ -4747,11 +2963,7 @@ TEST_P(QuicFramerTest, BuildNewAckFramePacketOneAckBlock) {
arraysize(packet));
}
-TEST_P(QuicFramerTest, BuildNewAckFramePacketMultipleAckBlocks) {
- if (framer_.version() <= QUIC_VERSION_33) {
- return;
- }
-
+TEST_P(QuicFramerTest, BuildAckFramePacketMultipleAckBlocks) {
QuicPacketHeader header;
header.public_header.connection_id = kConnectionId;
header.public_header.reset_flag = false;
@@ -4762,14 +2974,12 @@ TEST_P(QuicFramerTest, BuildNewAckFramePacketMultipleAckBlocks) {
QuicAckFrame ack_frame;
ack_frame.largest_observed = kSmallLargestObserved;
ack_frame.ack_delay_time = QuicTime::Delta::Zero();
- ack_frame.missing = false;
ack_frame.packets.Add(1, 5);
ack_frame.packets.Add(10, 500);
ack_frame.packets.Add(900, kSmallMissingPacket);
ack_frame.packets.Add(kSmallMissingPacket + 1, kSmallLargestObserved + 1);
- QuicFrames frames;
- frames.push_back(QuicFrame(&ack_frame));
+ QuicFrames frames = {QuicFrame(&ack_frame)};
// clang-format off
unsigned char packet[] = {
@@ -4820,11 +3030,7 @@ TEST_P(QuicFramerTest, BuildNewAckFramePacketMultipleAckBlocks) {
arraysize(packet));
}
-TEST_P(QuicFramerTest, BuildNewAckFramePacketMaxAckBlocks) {
- if (framer_.version() <= QUIC_VERSION_33) {
- return;
- }
-
+TEST_P(QuicFramerTest, BuildAckFramePacketMaxAckBlocks) {
QuicPacketHeader header;
header.public_header.connection_id = kConnectionId;
header.public_header.reset_flag = false;
@@ -4835,15 +3041,13 @@ TEST_P(QuicFramerTest, BuildNewAckFramePacketMaxAckBlocks) {
QuicAckFrame ack_frame;
ack_frame.largest_observed = kSmallLargestObserved;
ack_frame.ack_delay_time = QuicTime::Delta::Zero();
- ack_frame.missing = false;
// 300 ack blocks.
for (size_t i = 2; i < 2 * 300; i += 2) {
ack_frame.packets.Add(i);
}
ack_frame.packets.Add(600, kSmallLargestObserved + 1);
- QuicFrames frames;
- frames.push_back(QuicFrame(&ack_frame));
+ QuicFrames frames = {QuicFrame(&ack_frame)};
// clang-format off
unsigned char packet[] = {
@@ -4947,71 +3151,17 @@ TEST_P(QuicFramerTest, BuildNewAckFramePacketMaxAckBlocks) {
arraysize(packet));
}
-TEST_P(QuicFramerTest, BuildStopWaitingPacket) {
- if (framer_.version() > QUIC_VERSION_33) {
- return;
- }
- QuicPacketHeader header;
- header.public_header.connection_id = kConnectionId;
- header.public_header.reset_flag = false;
- header.public_header.version_flag = false;
- header.entropy_flag = true;
- header.packet_number = kPacketNumber;
-
- QuicStopWaitingFrame stop_waiting_frame;
- stop_waiting_frame.entropy_hash = 0x14;
- stop_waiting_frame.least_unacked = kLeastUnacked;
-
- QuicFrames frames;
- frames.push_back(QuicFrame(&stop_waiting_frame));
-
- // clang-format off
- unsigned char packet[] = {
- // public flags (8 byte connection_id)
- static_cast<unsigned char>(
- framer_.version() > QUIC_VERSION_32 ? 0x38 : 0x3C),
- // connection_id
- 0x10, 0x32, 0x54, 0x76,
- 0x98, 0xBA, 0xDC, 0xFE,
- // packet number
- 0xBC, 0x9A, 0x78, 0x56, 0x34, 0x12,
- // private flags (entropy)
- 0x01,
-
- // frame type (stop waiting frame)
- 0x06,
- // entropy hash of sent packets till least awaiting - 1.
- 0x14,
- // least packet number awaiting an ack, delta from packet number.
- 0x1C, 0x00, 0x00, 0x00,
- 0x00, 0x00,
- };
- // clang-format on
-
- std::unique_ptr<QuicPacket> data(BuildDataPacket(header, frames));
- ASSERT_TRUE(data != nullptr);
-
- test::CompareCharArraysWithHexError("constructed packet", data->data(),
- data->length(), AsChars(packet),
- arraysize(packet));
-}
-
TEST_P(QuicFramerTest, BuildNewStopWaitingPacket) {
- if (framer_.version() <= QUIC_VERSION_33) {
- return;
- }
QuicPacketHeader header;
header.public_header.connection_id = kConnectionId;
header.public_header.reset_flag = false;
header.public_header.version_flag = false;
- header.entropy_flag = false;
header.packet_number = kPacketNumber;
QuicStopWaitingFrame stop_waiting_frame;
stop_waiting_frame.least_unacked = kLeastUnacked;
- QuicFrames frames;
- frames.push_back(QuicFrame(&stop_waiting_frame));
+ QuicFrames frames = {QuicFrame(&stop_waiting_frame)};
// clang-format off
unsigned char packet[] = {
@@ -5044,7 +3194,6 @@ TEST_P(QuicFramerTest, BuildRstFramePacketQuic) {
header.public_header.connection_id = kConnectionId;
header.public_header.reset_flag = false;
header.public_header.version_flag = false;
- header.entropy_flag = false;
header.packet_number = kPacketNumber;
QuicRstStreamFrame rst_frame;
@@ -5055,29 +3204,6 @@ TEST_P(QuicFramerTest, BuildRstFramePacketQuic) {
// clang-format off
unsigned char packet[] = {
// public flags (8 byte connection_id)
- static_cast<unsigned char>(
- framer_.version() > QUIC_VERSION_32 ? 0x38 : 0x3C),
- // connection_id
- 0x10, 0x32, 0x54, 0x76,
- 0x98, 0xBA, 0xDC, 0xFE,
- // packet number
- 0xBC, 0x9A, 0x78, 0x56,
- 0x34, 0x12,
- // private flags
- 0x00,
-
- // frame type (rst stream frame)
- 0x01,
- // stream id
- 0x04, 0x03, 0x02, 0x01,
- // sent byte offset
- 0x01, 0x02, 0x03, 0x04,
- 0x05, 0x06, 0x07, 0x08,
- // error code
- 0x08, 0x07, 0x06, 0x05,
- };
- unsigned char packet_34[] = {
- // public flags (8 byte connection_id)
0x38,
// connection_id
0x10, 0x32, 0x54, 0x76,
@@ -5098,17 +3224,14 @@ TEST_P(QuicFramerTest, BuildRstFramePacketQuic) {
};
// clang-format on
- QuicFrames frames;
- frames.push_back(QuicFrame(&rst_frame));
+ QuicFrames frames = {QuicFrame(&rst_frame)};
std::unique_ptr<QuicPacket> data(BuildDataPacket(header, frames));
ASSERT_TRUE(data != nullptr);
- test::CompareCharArraysWithHexError(
- "constructed packet", data->data(), data->length(),
- AsChars(framer_.version() <= QUIC_VERSION_33 ? packet : packet_34),
- framer_.version() <= QUIC_VERSION_33 ? arraysize(packet)
- : arraysize(packet_34));
+ test::CompareCharArraysWithHexError("constructed packet", data->data(),
+ data->length(), AsChars(packet),
+ arraysize(packet));
}
TEST_P(QuicFramerTest, BuildCloseFramePacket) {
@@ -5116,46 +3239,18 @@ TEST_P(QuicFramerTest, BuildCloseFramePacket) {
header.public_header.connection_id = kConnectionId;
header.public_header.reset_flag = false;
header.public_header.version_flag = false;
- header.entropy_flag = true;
header.packet_number = kPacketNumber;
QuicConnectionCloseFrame close_frame;
close_frame.error_code = static_cast<QuicErrorCode>(0x05060708);
close_frame.error_details = "because I can";
- QuicFrames frames;
- frames.push_back(QuicFrame(&close_frame));
+ QuicFrames frames = {QuicFrame(&close_frame)};
// clang-format off
unsigned char packet[] = {
// public flags (8 byte connection_id)
- static_cast<unsigned char>(
- framer_.version() > QUIC_VERSION_32 ? 0x38 : 0x3C),
- // connection_id
- 0x10, 0x32, 0x54, 0x76,
- 0x98, 0xBA, 0xDC, 0xFE,
- // packet number
- 0xBC, 0x9A, 0x78, 0x56,
- 0x34, 0x12,
- // private flags (entropy)
- 0x01,
-
- // frame type (connection close frame)
- 0x02,
- // error code
- 0x08, 0x07, 0x06, 0x05,
- // error details length
- 0x0d, 0x00,
- // error details
- 'b', 'e', 'c', 'a',
- 'u', 's', 'e', ' ',
- 'I', ' ', 'c', 'a',
- 'n',
- };
- unsigned char packet_34[] = {
- // public flags (8 byte connection_id)
- static_cast<unsigned char>(
- framer_.version() > QUIC_VERSION_32 ? 0x38 : 0x3C),
+ 0x38,
// connection_id
0x10, 0x32, 0x54, 0x76,
0x98, 0xBA, 0xDC, 0xFE,
@@ -5180,11 +3275,9 @@ TEST_P(QuicFramerTest, BuildCloseFramePacket) {
std::unique_ptr<QuicPacket> data(BuildDataPacket(header, frames));
ASSERT_TRUE(data != nullptr);
- test::CompareCharArraysWithHexError(
- "constructed packet", data->data(), data->length(),
- AsChars(framer_.version() <= QUIC_VERSION_33 ? packet : packet_34),
- framer_.version() <= QUIC_VERSION_33 ? arraysize(packet)
- : arraysize(packet_34));
+ test::CompareCharArraysWithHexError("constructed packet", data->data(),
+ data->length(), AsChars(packet),
+ arraysize(packet));
}
TEST_P(QuicFramerTest, BuildGoAwayPacket) {
@@ -5192,7 +3285,6 @@ TEST_P(QuicFramerTest, BuildGoAwayPacket) {
header.public_header.connection_id = kConnectionId;
header.public_header.reset_flag = false;
header.public_header.version_flag = false;
- header.entropy_flag = true;
header.packet_number = kPacketNumber;
QuicGoAwayFrame goaway_frame;
@@ -5200,39 +3292,11 @@ TEST_P(QuicFramerTest, BuildGoAwayPacket) {
goaway_frame.last_good_stream_id = kStreamId;
goaway_frame.reason_phrase = "because I can";
- QuicFrames frames;
- frames.push_back(QuicFrame(&goaway_frame));
+ QuicFrames frames = {QuicFrame(&goaway_frame)};
// clang-format off
unsigned char packet[] = {
// public flags (8 byte connection_id)
- static_cast<unsigned char>(
- framer_.version() > QUIC_VERSION_32 ? 0x38 : 0x3C),
- // connection_id
- 0x10, 0x32, 0x54, 0x76,
- 0x98, 0xBA, 0xDC, 0xFE,
- // packet number
- 0xBC, 0x9A, 0x78, 0x56,
- 0x34, 0x12,
- // private flags(entropy)
- 0x01,
-
- // frame type (go away frame)
- 0x03,
- // error code
- 0x08, 0x07, 0x06, 0x05,
- // stream id
- 0x04, 0x03, 0x02, 0x01,
- // error details length
- 0x0d, 0x00,
- // error details
- 'b', 'e', 'c', 'a',
- 'u', 's', 'e', ' ',
- 'I', ' ', 'c', 'a',
- 'n',
- };
- unsigned char packet_34[] = {
- // public flags (8 byte connection_id)
0x38,
// connection_id
0x10, 0x32, 0x54, 0x76,
@@ -5260,11 +3324,9 @@ TEST_P(QuicFramerTest, BuildGoAwayPacket) {
std::unique_ptr<QuicPacket> data(BuildDataPacket(header, frames));
ASSERT_TRUE(data != nullptr);
- test::CompareCharArraysWithHexError(
- "constructed packet", data->data(), data->length(),
- AsChars(framer_.version() <= QUIC_VERSION_33 ? packet : packet_34),
- framer_.version() <= QUIC_VERSION_33 ? arraysize(packet)
- : arraysize(packet_34));
+ test::CompareCharArraysWithHexError("constructed packet", data->data(),
+ data->length(), AsChars(packet),
+ arraysize(packet));
}
TEST_P(QuicFramerTest, BuildWindowUpdatePacket) {
@@ -5272,40 +3334,17 @@ TEST_P(QuicFramerTest, BuildWindowUpdatePacket) {
header.public_header.connection_id = kConnectionId;
header.public_header.reset_flag = false;
header.public_header.version_flag = false;
- header.entropy_flag = true;
header.packet_number = kPacketNumber;
QuicWindowUpdateFrame window_update_frame;
window_update_frame.stream_id = kStreamId;
window_update_frame.byte_offset = 0x1122334455667788;
- QuicFrames frames;
- frames.push_back(QuicFrame(&window_update_frame));
+ QuicFrames frames = {QuicFrame(&window_update_frame)};
// clang-format off
unsigned char packet[] = {
// public flags (8 byte connection_id)
- static_cast<unsigned char>(
- framer_.version() > QUIC_VERSION_32 ? 0x38 : 0x3C),
- // connection_id
- 0x10, 0x32, 0x54, 0x76,
- 0x98, 0xBA, 0xDC, 0xFE,
- // packet number
- 0xBC, 0x9A, 0x78, 0x56,
- 0x34, 0x12,
- // private flags(entropy)
- 0x01,
-
- // frame type (window update frame)
- 0x04,
- // stream id
- 0x04, 0x03, 0x02, 0x01,
- // byte offset
- 0x88, 0x77, 0x66, 0x55,
- 0x44, 0x33, 0x22, 0x11,
- };
- unsigned char packet_34[] = {
- // public flags (8 byte connection_id)
0x38,
// connection_id
0x10, 0x32, 0x54, 0x76,
@@ -5327,11 +3366,9 @@ TEST_P(QuicFramerTest, BuildWindowUpdatePacket) {
std::unique_ptr<QuicPacket> data(BuildDataPacket(header, frames));
ASSERT_TRUE(data != nullptr);
- test::CompareCharArraysWithHexError(
- "constructed packet", data->data(), data->length(),
- AsChars(framer_.version() <= QUIC_VERSION_33 ? packet : packet_34),
- framer_.version() <= QUIC_VERSION_33 ? arraysize(packet)
- : arraysize(packet_34));
+ test::CompareCharArraysWithHexError("constructed packet", data->data(),
+ data->length(), AsChars(packet),
+ arraysize(packet));
}
TEST_P(QuicFramerTest, BuildBlockedPacket) {
@@ -5339,36 +3376,16 @@ TEST_P(QuicFramerTest, BuildBlockedPacket) {
header.public_header.connection_id = kConnectionId;
header.public_header.reset_flag = false;
header.public_header.version_flag = false;
- header.entropy_flag = true;
header.packet_number = kPacketNumber;
QuicBlockedFrame blocked_frame;
blocked_frame.stream_id = kStreamId;
- QuicFrames frames;
- frames.push_back(QuicFrame(&blocked_frame));
+ QuicFrames frames = {QuicFrame(&blocked_frame)};
// clang-format off
unsigned char packet[] = {
// public flags (8 byte connection_id)
- static_cast<unsigned char>(
- framer_.version() > QUIC_VERSION_32 ? 0x38 : 0x3C),
- // connection_id
- 0x10, 0x32, 0x54, 0x76,
- 0x98, 0xBA, 0xDC, 0xFE,
- // packet number
- 0xBC, 0x9A, 0x78, 0x56,
- 0x34, 0x12,
- // private flags(entropy)
- 0x01,
-
- // frame type (blocked frame)
- 0x05,
- // stream id
- 0x04, 0x03, 0x02, 0x01,
- };
- unsigned char packet_34[] = {
- // public flags (8 byte connection_id)
0x38,
// connection_id
0x10, 0x32, 0x54, 0x76,
@@ -5387,11 +3404,9 @@ TEST_P(QuicFramerTest, BuildBlockedPacket) {
std::unique_ptr<QuicPacket> data(BuildDataPacket(header, frames));
ASSERT_TRUE(data != nullptr);
- test::CompareCharArraysWithHexError(
- "constructed packet", data->data(), data->length(),
- AsChars(framer_.version() <= QUIC_VERSION_33 ? packet : packet_34),
- framer_.version() <= QUIC_VERSION_33 ? arraysize(packet)
- : arraysize(packet_34));
+ test::CompareCharArraysWithHexError("constructed packet", data->data(),
+ data->length(), AsChars(packet),
+ arraysize(packet));
}
TEST_P(QuicFramerTest, BuildPingPacket) {
@@ -5399,35 +3414,14 @@ TEST_P(QuicFramerTest, BuildPingPacket) {
header.public_header.connection_id = kConnectionId;
header.public_header.reset_flag = false;
header.public_header.version_flag = false;
- header.entropy_flag = true;
header.packet_number = kPacketNumber;
- QuicPingFrame ping_frame;
-
- QuicFrames frames;
- frames.push_back(QuicFrame(ping_frame));
+ QuicFrames frames = {QuicFrame(QuicPingFrame())};
// clang-format off
unsigned char packet[] = {
// public flags (8 byte connection_id)
- static_cast<unsigned char>(
- framer_.version() > QUIC_VERSION_32 ? 0x38 : 0x3C),
- // connection_id
- 0x10, 0x32, 0x54, 0x76,
- 0x98, 0xBA, 0xDC, 0xFE,
- // packet number
- 0xBC, 0x9A, 0x78, 0x56,
- 0x34, 0x12,
- // private flags(entropy)
- 0x01,
-
- // frame type (ping frame)
- 0x07,
- };
- unsigned char packet_34[] = {
- // public flags (8 byte connection_id)
- static_cast<unsigned char>(
- framer_.version() > QUIC_VERSION_32 ? 0x38 : 0x3C),
+ 0x38,
// connection_id
0x10, 0x32, 0x54, 0x76,
0x98, 0xBA, 0xDC, 0xFE,
@@ -5443,11 +3437,9 @@ TEST_P(QuicFramerTest, BuildPingPacket) {
std::unique_ptr<QuicPacket> data(BuildDataPacket(header, frames));
ASSERT_TRUE(data != nullptr);
- test::CompareCharArraysWithHexError(
- "constructed packet", data->data(), data->length(),
- AsChars(framer_.version() <= QUIC_VERSION_33 ? packet : packet_34),
- framer_.version() <= QUIC_VERSION_33 ? arraysize(packet)
- : arraysize(packet_34));
+ test::CompareCharArraysWithHexError("constructed packet", data->data(),
+ data->length(), AsChars(packet),
+ arraysize(packet));
}
TEST_P(QuicFramerTest, BuildPathClosePacket) {
@@ -5456,7 +3448,6 @@ TEST_P(QuicFramerTest, BuildPathClosePacket) {
header.public_header.multipath_flag = true;
header.public_header.reset_flag = false;
header.public_header.version_flag = false;
- header.entropy_flag = true;
header.path_id = kDefaultPathId;
header.packet_number = kPacketNumber;
@@ -5468,26 +3459,7 @@ TEST_P(QuicFramerTest, BuildPathClosePacket) {
// clang-format off
unsigned char packet[] = {
// public flags (version)
- static_cast<unsigned char>(
- framer_.version() > QUIC_VERSION_32 ? 0x78 : 0X7C),
- // connection_id
- 0x10, 0x32, 0x54, 0x76, 0x98, 0xBA, 0xDC, 0xFE,
- // path_id
- 0x00,
- // packet number
- 0xBC, 0x9A, 0x78, 0x56, 0x34, 0x12,
- // private flags (entropy)
- 0x01,
-
- // frame type (path_close_frame)
- 0x08,
- // path id
- 0x42,
- };
- unsigned char packet_34[] = {
- // public flags (version)
- static_cast<unsigned char>(
- framer_.version() > QUIC_VERSION_32 ? 0x78 : 0X7C),
+ 0x78,
// connection_id
0x10, 0x32, 0x54, 0x76, 0x98, 0xBA, 0xDC, 0xFE,
// path_id
@@ -5505,11 +3477,9 @@ TEST_P(QuicFramerTest, BuildPathClosePacket) {
std::unique_ptr<QuicPacket> data(BuildDataPacket(header, frames));
ASSERT_TRUE(data != nullptr);
- test::CompareCharArraysWithHexError(
- "constructed packet", data->data(), data->length(),
- AsChars(framer_.version() <= QUIC_VERSION_33 ? packet : packet_34),
- framer_.version() <= QUIC_VERSION_33 ? arraysize(packet)
- : arraysize(packet_34));
+ test::CompareCharArraysWithHexError("constructed packet", data->data(),
+ data->length(), AsChars(packet),
+ arraysize(packet));
}
// Test that the MTU discovery packet is serialized correctly as a PING packet.
@@ -5518,35 +3488,14 @@ TEST_P(QuicFramerTest, BuildMtuDiscoveryPacket) {
header.public_header.connection_id = kConnectionId;
header.public_header.reset_flag = false;
header.public_header.version_flag = false;
- header.entropy_flag = true;
header.packet_number = kPacketNumber;
- QuicMtuDiscoveryFrame mtu_discovery_frame;
-
- QuicFrames frames;
- frames.push_back(QuicFrame(mtu_discovery_frame));
+ QuicFrames frames = {QuicFrame(QuicMtuDiscoveryFrame())};
// clang-format off
unsigned char packet[] = {
// public flags (8 byte connection_id)
- static_cast<unsigned char>(
- framer_.version() > QUIC_VERSION_32 ? 0x38 : 0x3C),
- // connection_id
- 0x10, 0x32, 0x54, 0x76,
- 0x98, 0xBA, 0xDC, 0xFE,
- // packet number
- 0xBC, 0x9A, 0x78, 0x56,
- 0x34, 0x12,
- // private flags(entropy)
- 0x01,
-
- // frame type (ping frame)
- 0x07,
- };
- unsigned char packet_34[] = {
- // public flags (8 byte connection_id)
- static_cast<unsigned char>(
- framer_.version() > QUIC_VERSION_32 ? 0x38 : 0x3C),
+ 0x38,
// connection_id
0x10, 0x32, 0x54, 0x76,
0x98, 0xBA, 0xDC, 0xFE,
@@ -5562,15 +3511,13 @@ TEST_P(QuicFramerTest, BuildMtuDiscoveryPacket) {
std::unique_ptr<QuicPacket> data(BuildDataPacket(header, frames));
ASSERT_TRUE(data != nullptr);
- test::CompareCharArraysWithHexError(
- "constructed packet", data->data(), data->length(),
- AsChars(framer_.version() <= QUIC_VERSION_33 ? packet : packet_34),
- framer_.version() <= QUIC_VERSION_33 ? arraysize(packet)
- : arraysize(packet_34));
+ test::CompareCharArraysWithHexError("constructed packet", data->data(),
+ data->length(), AsChars(packet),
+ arraysize(packet));
}
TEST_P(QuicFramerTest, BuildPublicResetPacketOld) {
- FLAGS_quic_use_old_public_reset_packets = true;
+ FLAGS_quic_reloadable_flag_quic_use_old_public_reset_packets = true;
QuicPublicResetPacket reset_packet;
reset_packet.public_header.connection_id = kConnectionId;
reset_packet.public_header.reset_flag = true;
@@ -5627,7 +3574,7 @@ TEST_P(QuicFramerTest, BuildPublicResetPacketOld) {
std::unique_ptr<QuicEncryptedPacket> data(
framer_.BuildPublicResetPacket(reset_packet));
ASSERT_TRUE(data != nullptr);
- if (FLAGS_quic_remove_packet_number_from_public_reset) {
+ if (FLAGS_quic_reloadable_flag_quic_remove_packet_number_from_public_reset) {
test::CompareCharArraysWithHexError(
"constructed packet", data->data(), data->length(),
AsChars(packet_no_rejected_packet_number),
@@ -5640,7 +3587,7 @@ TEST_P(QuicFramerTest, BuildPublicResetPacketOld) {
}
TEST_P(QuicFramerTest, BuildPublicResetPacket) {
- FLAGS_quic_use_old_public_reset_packets = false;
+ FLAGS_quic_reloadable_flag_quic_use_old_public_reset_packets = false;
QuicPublicResetPacket reset_packet;
reset_packet.public_header.connection_id = kConnectionId;
reset_packet.public_header.reset_flag = true;
@@ -5698,7 +3645,7 @@ TEST_P(QuicFramerTest, BuildPublicResetPacket) {
framer_.BuildPublicResetPacket(reset_packet));
ASSERT_TRUE(data != nullptr);
- if (FLAGS_quic_remove_packet_number_from_public_reset) {
+ if (FLAGS_quic_reloadable_flag_quic_remove_packet_number_from_public_reset) {
test::CompareCharArraysWithHexError(
"constructed packet", data->data(), data->length(),
AsChars(packet_no_rejected_packet_number),
@@ -5711,14 +3658,15 @@ TEST_P(QuicFramerTest, BuildPublicResetPacket) {
}
TEST_P(QuicFramerTest, BuildPublicResetPacketWithClientAddress) {
- FLAGS_quic_use_old_public_reset_packets = false;
+ FLAGS_quic_reloadable_flag_quic_use_old_public_reset_packets = false;
QuicPublicResetPacket reset_packet;
reset_packet.public_header.connection_id = kConnectionId;
reset_packet.public_header.reset_flag = true;
reset_packet.public_header.version_flag = false;
reset_packet.rejected_packet_number = kPacketNumber;
reset_packet.nonce_proof = kNonceProof;
- reset_packet.client_address = IPEndPoint(Loopback4(), 0x1234);
+ reset_packet.client_address =
+ QuicSocketAddress(QuicIpAddress::Loopback4(), 0x1234);
// clang-format off
unsigned char packet[] = {
@@ -5786,7 +3734,7 @@ TEST_P(QuicFramerTest, BuildPublicResetPacketWithClientAddress) {
framer_.BuildPublicResetPacket(reset_packet));
ASSERT_TRUE(data != nullptr);
- if (FLAGS_quic_remove_packet_number_from_public_reset) {
+ if (FLAGS_quic_reloadable_flag_quic_remove_packet_number_from_public_reset) {
test::CompareCharArraysWithHexError(
"constructed packet", data->data(), data->length(),
AsChars(packet_no_rejected_packet_number),
@@ -5803,27 +3751,7 @@ TEST_P(QuicFramerTest, EncryptPacket) {
// clang-format off
unsigned char packet[] = {
// public flags (8 byte connection_id)
- static_cast<unsigned char>(
- framer_.version() > QUIC_VERSION_32 ? 0x38 : 0x3C),
- // connection_id
- 0x10, 0x32, 0x54, 0x76,
- 0x98, 0xBA, 0xDC, 0xFE,
- // packet number
- 0xBC, 0x9A, 0x78, 0x56,
- 0x34, 0x12,
- // private flags
- 0x00,
-
- // redundancy
- 'a', 'b', 'c', 'd',
- 'e', 'f', 'g', 'h',
- 'i', 'j', 'k', 'l',
- 'm', 'n', 'o', 'p',
- };
- unsigned char packet_34[] = {
- // public flags (8 byte connection_id)
- static_cast<unsigned char>(
- framer_.version() > QUIC_VERSION_32 ? 0x38 : 0x3C),
+ 0x38,
// connection_id
0x10, 0x32, 0x54, 0x76,
0x98, 0xBA, 0xDC, 0xFE,
@@ -5840,11 +3768,9 @@ TEST_P(QuicFramerTest, EncryptPacket) {
// clang-format on
std::unique_ptr<QuicPacket> raw(new QuicPacket(
- AsChars(framer_.version() <= QUIC_VERSION_33 ? packet : packet_34),
- framer_.version() <= QUIC_VERSION_33 ? arraysize(packet)
- : arraysize(packet_34),
- false, PACKET_8BYTE_CONNECTION_ID, !kIncludeVersion, !kIncludePathId,
- !kIncludeDiversificationNonce, PACKET_6BYTE_PACKET_NUMBER));
+ AsChars(packet), arraysize(packet), false, PACKET_8BYTE_CONNECTION_ID,
+ !kIncludeVersion, !kIncludePathId, !kIncludeDiversificationNonce,
+ PACKET_6BYTE_PACKET_NUMBER));
char buffer[kMaxPacketSize];
size_t encrypted_length =
framer_.EncryptPayload(ENCRYPTION_NONE, kDefaultPathId, packet_number,
@@ -5868,26 +3794,6 @@ TEST_P(QuicFramerTest, EncryptPacketWithVersionFlag) {
// packet number
0xBC, 0x9A, 0x78, 0x56,
0x34, 0x12,
- // private flags
- 0x00,
-
- // redundancy
- 'a', 'b', 'c', 'd',
- 'e', 'f', 'g', 'h',
- 'i', 'j', 'k', 'l',
- 'm', 'n', 'o', 'p',
- };
- unsigned char packet_34[] = {
- // public flags (version, 8 byte connection_id)
- 0x39,
- // connection_id
- 0x10, 0x32, 0x54, 0x76,
- 0x98, 0xBA, 0xDC, 0xFE,
- // version tag
- 'Q', '.', '1', '0',
- // packet number
- 0xBC, 0x9A, 0x78, 0x56,
- 0x34, 0x12,
// redundancy
'a', 'b', 'c', 'd',
@@ -5898,11 +3804,9 @@ TEST_P(QuicFramerTest, EncryptPacketWithVersionFlag) {
// clang-format on
std::unique_ptr<QuicPacket> raw(new QuicPacket(
- AsChars(framer_.version() <= QUIC_VERSION_33 ? packet : packet_34),
- framer_.version() <= QUIC_VERSION_33 ? arraysize(packet)
- : arraysize(packet_34),
- false, PACKET_8BYTE_CONNECTION_ID, kIncludeVersion, !kIncludePathId,
- !kIncludeDiversificationNonce, PACKET_6BYTE_PACKET_NUMBER));
+ AsChars(packet), arraysize(packet), false, PACKET_8BYTE_CONNECTION_ID,
+ kIncludeVersion, !kIncludePathId, !kIncludeDiversificationNonce,
+ PACKET_6BYTE_PACKET_NUMBER));
char buffer[kMaxPacketSize];
size_t encrypted_length =
framer_.EncryptPayload(ENCRYPTION_NONE, kDefaultPathId, packet_number,
@@ -5926,26 +3830,6 @@ TEST_P(QuicFramerTest, EncryptPacketWithMultipathFlag) {
// packet number
0xBC, 0x9A, 0x78, 0x56,
0x34, 0x12,
- // private flags
- 0x00,
-
- // redundancy
- 'a', 'b', 'c', 'd',
- 'e', 'f', 'g', 'h',
- 'i', 'j', 'k', 'l',
- 'm', 'n', 'o', 'p',
- };
- unsigned char packet_34[] = {
- // public flags (version, 8 byte connection_id)
- 0x78,
- // connection_id
- 0x10, 0x32, 0x54, 0x76,
- 0x98, 0xBA, 0xDC, 0xFE,
- // path_id
- 0x42,
- // packet number
- 0xBC, 0x9A, 0x78, 0x56,
- 0x34, 0x12,
// redundancy
'a', 'b', 'c', 'd',
@@ -5956,11 +3840,9 @@ TEST_P(QuicFramerTest, EncryptPacketWithMultipathFlag) {
// clang-format on
std::unique_ptr<QuicPacket> raw(new QuicPacket(
- AsChars(framer_.version() <= QUIC_VERSION_33 ? packet : packet_34),
- framer_.version() <= QUIC_VERSION_33 ? arraysize(packet)
- : arraysize(packet_34),
- false, PACKET_8BYTE_CONNECTION_ID, !kIncludeVersion, kIncludePathId,
- !kIncludeDiversificationNonce, PACKET_6BYTE_PACKET_NUMBER));
+ AsChars(packet), arraysize(packet), false, PACKET_8BYTE_CONNECTION_ID,
+ !kIncludeVersion, kIncludePathId, !kIncludeDiversificationNonce,
+ PACKET_6BYTE_PACKET_NUMBER));
char buffer[kMaxPacketSize];
size_t encrypted_length = framer_.EncryptPayload(
ENCRYPTION_NONE, kPathId, packet_number, *raw, buffer, kMaxPacketSize);
@@ -5985,28 +3867,6 @@ TEST_P(QuicFramerTest, EncryptPacketWithBothVersionFlagAndMultipathFlag) {
// packet number
0xBC, 0x9A, 0x78, 0x56,
0x34, 0x12,
- // private flags
- 0x00,
-
- // redundancy
- 'a', 'b', 'c', 'd',
- 'e', 'f', 'g', 'h',
- 'i', 'j', 'k', 'l',
- 'm', 'n', 'o', 'p',
- };
- unsigned char packet_34[] = {
- // public flags (version, 8 byte connection_id)
- 0x79,
- // connection_id
- 0x10, 0x32, 0x54, 0x76,
- 0x98, 0xBA, 0xDC, 0xFE,
- // version tag
- 'Q', '.', '1', '0',
- // path_id
- 0x42,
- // packet number
- 0xBC, 0x9A, 0x78, 0x56,
- 0x34, 0x12,
// redundancy
'a', 'b', 'c', 'd',
@@ -6017,11 +3877,9 @@ TEST_P(QuicFramerTest, EncryptPacketWithBothVersionFlagAndMultipathFlag) {
// clang-format on
std::unique_ptr<QuicPacket> raw(new QuicPacket(
- AsChars(framer_.version() <= QUIC_VERSION_33 ? packet : packet_34),
- framer_.version() <= QUIC_VERSION_33 ? arraysize(packet)
- : arraysize(packet_34),
- false, PACKET_8BYTE_CONNECTION_ID, kIncludeVersion, kIncludePathId,
- !kIncludeDiversificationNonce, PACKET_6BYTE_PACKET_NUMBER));
+ AsChars(packet), arraysize(packet), false, PACKET_8BYTE_CONNECTION_ID,
+ kIncludeVersion, kIncludePathId, !kIncludeDiversificationNonce,
+ PACKET_6BYTE_PACKET_NUMBER));
char buffer[kMaxPacketSize];
size_t encrypted_length = framer_.EncryptPayload(
ENCRYPTION_NONE, kPathId, packet_number, *raw, buffer, kMaxPacketSize);
@@ -6035,21 +3893,12 @@ TEST_P(QuicFramerTest, AckTruncationLargePacket) {
header.public_header.connection_id = kConnectionId;
header.public_header.reset_flag = false;
header.public_header.version_flag = false;
- header.entropy_flag = false;
header.packet_number = kPacketNumber;
QuicAckFrame ack_frame;
// Create a packet with just the ack.
- if (framer_.version() <= QUIC_VERSION_33) {
- ack_frame = MakeAckFrameWithNackRanges(300, 0u);
- } else {
- ack_frame = MakeAckFrameWithAckBlocks(300, 0u);
- }
- QuicFrame frame;
- frame.type = ACK_FRAME;
- frame.ack_frame = &ack_frame;
- QuicFrames frames;
- frames.push_back(frame);
+ ack_frame = MakeAckFrameWithAckBlocks(300, 0u);
+ QuicFrames frames = {QuicFrame(&ack_frame)};
// Build an ack packet with truncation due to limit in number of nack ranges.
std::unique_ptr<QuicPacket> raw_ack_packet(BuildDataPacket(header, frames));
@@ -6063,22 +3912,11 @@ TEST_P(QuicFramerTest, AckTruncationLargePacket) {
ASSERT_TRUE(framer_.ProcessPacket(
QuicEncryptedPacket(buffer, encrypted_length, false)));
ASSERT_EQ(1u, visitor_.ack_frames_.size());
- QuicAckFrame& processed_ack_frame = *visitor_.ack_frames_[0].get();
- if (framer_.version() <= QUIC_VERSION_33) {
- EXPECT_TRUE(processed_ack_frame.is_truncated);
- EXPECT_EQ(510u, processed_ack_frame.largest_observed);
- EXPECT_TRUE(processed_ack_frame.missing);
- ASSERT_EQ(255u, processed_ack_frame.packets.NumPacketsSlow());
- EXPECT_EQ(1u, processed_ack_frame.packets.Min());
- EXPECT_EQ(509u, processed_ack_frame.packets.Max());
- } else {
- EXPECT_FALSE(processed_ack_frame.is_truncated);
- EXPECT_FALSE(processed_ack_frame.missing);
- EXPECT_EQ(600u, processed_ack_frame.largest_observed);
- ASSERT_EQ(256u, processed_ack_frame.packets.NumPacketsSlow());
- EXPECT_EQ(90u, processed_ack_frame.packets.Min());
- EXPECT_EQ(600u, processed_ack_frame.packets.Max());
- }
+ QuicAckFrame& processed_ack_frame = *visitor_.ack_frames_[0];
+ EXPECT_EQ(600u, processed_ack_frame.largest_observed);
+ ASSERT_EQ(256u, processed_ack_frame.packets.NumPacketsSlow());
+ EXPECT_EQ(90u, processed_ack_frame.packets.Min());
+ EXPECT_EQ(600u, processed_ack_frame.packets.Max());
}
TEST_P(QuicFramerTest, AckTruncationSmallPacket) {
@@ -6086,21 +3924,12 @@ TEST_P(QuicFramerTest, AckTruncationSmallPacket) {
header.public_header.connection_id = kConnectionId;
header.public_header.reset_flag = false;
header.public_header.version_flag = false;
- header.entropy_flag = false;
header.packet_number = kPacketNumber;
// Create a packet with just the ack.
QuicAckFrame ack_frame;
- if (framer_.version() <= QUIC_VERSION_33) {
- ack_frame = MakeAckFrameWithNackRanges(300, 0u);
- } else {
- ack_frame = MakeAckFrameWithAckBlocks(300, 0u);
- }
- QuicFrame frame;
- frame.type = ACK_FRAME;
- frame.ack_frame = &ack_frame;
- QuicFrames frames;
- frames.push_back(frame);
+ ack_frame = MakeAckFrameWithAckBlocks(300, 0u);
+ QuicFrames frames = {QuicFrame(&ack_frame)};
// Build an ack packet with truncation due to limit in number of nack ranges.
std::unique_ptr<QuicPacket> raw_ack_packet(
@@ -6115,22 +3944,11 @@ TEST_P(QuicFramerTest, AckTruncationSmallPacket) {
ASSERT_TRUE(framer_.ProcessPacket(
QuicEncryptedPacket(buffer, encrypted_length, false)));
ASSERT_EQ(1u, visitor_.ack_frames_.size());
- QuicAckFrame& processed_ack_frame = *visitor_.ack_frames_[0].get();
- if (framer_.version() <= QUIC_VERSION_33) {
- EXPECT_TRUE(processed_ack_frame.is_truncated);
- EXPECT_EQ(476u, processed_ack_frame.largest_observed);
- EXPECT_TRUE(processed_ack_frame.missing);
- ASSERT_EQ(238u, processed_ack_frame.packets.NumPacketsSlow());
- EXPECT_EQ(1u, processed_ack_frame.packets.Min());
- EXPECT_EQ(475u, processed_ack_frame.packets.Max());
- } else {
- EXPECT_FALSE(processed_ack_frame.is_truncated);
- EXPECT_EQ(600u, processed_ack_frame.largest_observed);
- EXPECT_FALSE(processed_ack_frame.missing);
- ASSERT_EQ(239u, processed_ack_frame.packets.NumPacketsSlow());
- EXPECT_EQ(124u, processed_ack_frame.packets.Min());
- EXPECT_EQ(600u, processed_ack_frame.packets.Max());
- }
+ QuicAckFrame& processed_ack_frame = *visitor_.ack_frames_[0];
+ EXPECT_EQ(600u, processed_ack_frame.largest_observed);
+ ASSERT_EQ(239u, processed_ack_frame.packets.NumPacketsSlow());
+ EXPECT_EQ(124u, processed_ack_frame.packets.Min());
+ EXPECT_EQ(600u, processed_ack_frame.packets.Max());
}
TEST_P(QuicFramerTest, CleanTruncation) {
@@ -6138,7 +3956,6 @@ TEST_P(QuicFramerTest, CleanTruncation) {
header.public_header.connection_id = kConnectionId;
header.public_header.reset_flag = false;
header.public_header.version_flag = false;
- header.entropy_flag = true;
header.packet_number = kPacketNumber;
QuicAckFrame ack_frame;
@@ -6146,11 +3963,7 @@ TEST_P(QuicFramerTest, CleanTruncation) {
ack_frame.packets.Add(1, ack_frame.largest_observed);
// Create a packet with just the ack.
- QuicFrame frame;
- frame.type = ACK_FRAME;
- frame.ack_frame = &ack_frame;
- QuicFrames frames;
- frames.push_back(frame);
+ QuicFrames frames = {QuicFrame(&ack_frame)};
std::unique_ptr<QuicPacket> raw_ack_packet(BuildDataPacket(header, frames));
ASSERT_TRUE(raw_ack_packet != nullptr);
@@ -6168,9 +3981,7 @@ TEST_P(QuicFramerTest, CleanTruncation) {
// Test for clean truncation of the ack by comparing the length of the
// original packets to the re-serialized packets.
frames.clear();
- frame.type = ACK_FRAME;
- frame.ack_frame = visitor_.ack_frames_[0].get();
- frames.push_back(frame);
+ frames.push_back(QuicFrame(visitor_.ack_frames_[0].get()));
size_t original_raw_length = raw_ack_packet->length();
raw_ack_packet.reset(BuildDataPacket(header, frames));
@@ -6179,97 +3990,11 @@ TEST_P(QuicFramerTest, CleanTruncation) {
ASSERT_TRUE(raw_ack_packet != nullptr);
}
-TEST_P(QuicFramerTest, EntropyFlagTest) {
- if (framer_.version() > QUIC_VERSION_33) {
- return;
- }
- // clang-format off
- unsigned char packet[] = {
- // public flags (8 byte connection_id)
- static_cast<unsigned char>(
- framer_.version() > QUIC_VERSION_32 ? 0x38 : 0x3C),
- // connection_id
- 0x10, 0x32, 0x54, 0x76,
- 0x98, 0xBA, 0xDC, 0xFE,
- // packet number
- 0xBC, 0x9A, 0x78, 0x56,
- 0x34, 0x12,
- // private flags (Entropy)
- 0x01,
-
- // frame type (stream frame with fin and no length)
- 0xDF,
- // stream id
- 0x04, 0x03, 0x02, 0x01,
- // offset
- 0x54, 0x76, 0x10, 0x32,
- 0xDC, 0xFE, 0x98, 0xBA,
- // data
- 'h', 'e', 'l', 'l',
- 'o', ' ', 'w', 'o',
- 'r', 'l', 'd', '!',
- };
- // clang-format on
-
- QuicEncryptedPacket encrypted(AsChars(packet), arraysize(packet), false);
- EXPECT_TRUE(framer_.ProcessPacket(encrypted));
- EXPECT_EQ(QUIC_NO_ERROR, framer_.error());
- ASSERT_TRUE(visitor_.header_.get());
- EXPECT_TRUE(visitor_.header_->entropy_flag);
- EXPECT_EQ(1 << 4, visitor_.header_->entropy_hash);
-};
-
TEST_P(QuicFramerTest, StopPacketProcessing) {
// clang-format off
unsigned char packet[] = {
// public flags (8 byte connection_id)
- static_cast<unsigned char>(
- framer_.version() > QUIC_VERSION_32 ? 0x38 : 0x3C),
- // connection_id
- 0x10, 0x32, 0x54, 0x76,
- 0x98, 0xBA, 0xDC, 0xFE,
- // packet number
- 0xBC, 0x9A, 0x78, 0x56,
- 0x34, 0x12,
- // Entropy
- 0x01,
-
- // frame type (stream frame with fin)
- 0xFF,
- // stream id
- 0x04, 0x03, 0x02, 0x01,
- // offset
- 0x54, 0x76, 0x10, 0x32,
- 0xDC, 0xFE, 0x98, 0xBA,
- // data length
- 0x0c, 0x00,
- // data
- 'h', 'e', 'l', 'l',
- 'o', ' ', 'w', 'o',
- 'r', 'l', 'd', '!',
-
- // frame type (ack frame)
- 0x40,
- // entropy hash of sent packets till least awaiting - 1.
- 0x14,
- // least packet number awaiting an ack
- 0xA0, 0x9A, 0x78, 0x56,
- 0x34, 0x12,
- // entropy hash of all received packets.
- 0x43,
- // largest observed packet number
- 0xBF, 0x9A, 0x78, 0x56,
- 0x34, 0x12,
- // num missing packets
- 0x01,
- // missing packet
- 0xBE, 0x9A, 0x78, 0x56,
- 0x34, 0x12,
- };
- unsigned char packet_34[] = {
- // public flags (8 byte connection_id)
- static_cast<unsigned char>(
- framer_.version() > QUIC_VERSION_32 ? 0x38 : 0x3C),
+ 0x38,
// connection_id
0x10, 0x32, 0x54, 0x76,
0x98, 0xBA, 0xDC, 0xFE,
@@ -6293,13 +4018,9 @@ TEST_P(QuicFramerTest, StopPacketProcessing) {
// frame type (ack frame)
0x40,
- // entropy hash of sent packets till least awaiting - 1.
- 0x14,
// least packet number awaiting an ack
0xA0, 0x9A, 0x78, 0x56,
0x34, 0x12,
- // entropy hash of all received packets.
- 0x43,
// largest observed packet number
0xBF, 0x9A, 0x78, 0x56,
0x34, 0x12,
@@ -6322,11 +4043,7 @@ TEST_P(QuicFramerTest, StopPacketProcessing) {
EXPECT_CALL(visitor, OnUnauthenticatedHeader(_)).WillOnce(Return(true));
EXPECT_CALL(visitor, OnDecryptedPacket(_));
- QuicEncryptedPacket encrypted(
- AsChars(framer_.version() <= QUIC_VERSION_33 ? packet : packet_34),
- framer_.version() <= QUIC_VERSION_33 ? arraysize(packet)
- : arraysize(packet_34),
- false);
+ QuicEncryptedPacket encrypted(AsChars(packet), arraysize(packet), false);
EXPECT_TRUE(framer_.ProcessPacket(encrypted));
EXPECT_EQ(QUIC_NO_ERROR, framer_.error());
}
@@ -6346,8 +4063,10 @@ static bool ExpectedStreamFrame(const QuicStreamFrame& frame) {
TEST_P(QuicFramerTest, ConstructEncryptedPacket) {
// Since we are using ConstructEncryptedPacket, we have to set the framer's
// crypto to be Null.
- framer_.SetDecrypter(ENCRYPTION_NONE, QuicDecrypter::Create(kNULL));
- framer_.SetEncrypter(ENCRYPTION_NONE, QuicEncrypter::Create(kNULL));
+ framer_.SetDecrypter(ENCRYPTION_NONE,
+ new NullDecrypter(framer_.perspective()));
+ framer_.SetEncrypter(ENCRYPTION_NONE,
+ new NullEncrypter(framer_.perspective()));
QuicVersionVector versions;
versions.push_back(framer_.version());
std::unique_ptr<QuicEncryptedPacket> packet(ConstructEncryptedPacket(
@@ -6380,14 +4099,16 @@ TEST_P(QuicFramerTest, ConstructEncryptedPacket) {
TEST_P(QuicFramerTest, ConstructMisFramedEncryptedPacket) {
// Since we are using ConstructEncryptedPacket, we have to set the framer's
// crypto to be Null.
- framer_.SetDecrypter(ENCRYPTION_NONE, QuicDecrypter::Create(kNULL));
- framer_.SetEncrypter(ENCRYPTION_NONE, QuicEncrypter::Create(kNULL));
+ framer_.SetDecrypter(ENCRYPTION_NONE,
+ new NullDecrypter(framer_.perspective()));
+ framer_.SetEncrypter(ENCRYPTION_NONE,
+ new NullEncrypter(framer_.perspective()));
QuicVersionVector versions;
versions.push_back(framer_.version());
std::unique_ptr<QuicEncryptedPacket> packet(ConstructMisFramedEncryptedPacket(
42, false, false, false, kDefaultPathId, kTestQuicStreamId, kTestString,
PACKET_8BYTE_CONNECTION_ID, PACKET_6BYTE_PACKET_NUMBER, &versions,
- Perspective::IS_SERVER));
+ Perspective::IS_CLIENT));
MockFramerVisitor visitor;
framer_.set_visitor(&visitor);
@@ -6398,11 +4119,7 @@ TEST_P(QuicFramerTest, ConstructMisFramedEncryptedPacket) {
EXPECT_CALL(visitor, OnUnauthenticatedHeader(_))
.Times(1)
.WillOnce(Return(true));
- if (framer_.version() <= QUIC_VERSION_33) {
- EXPECT_CALL(visitor, OnPacketHeader(_)).Times(0);
- } else {
- EXPECT_CALL(visitor, OnPacketHeader(_)).Times(1);
- }
+ EXPECT_CALL(visitor, OnPacketHeader(_)).Times(1);
EXPECT_CALL(visitor, OnDecryptedPacket(_)).Times(1);
EXPECT_CALL(visitor, OnError(_)).Times(1);
EXPECT_CALL(visitor, OnStreamFrame(_)).Times(0);
@@ -6410,11 +4127,7 @@ TEST_P(QuicFramerTest, ConstructMisFramedEncryptedPacket) {
EXPECT_CALL(visitor, OnPacketComplete()).Times(0);
EXPECT_FALSE(framer_.ProcessPacket(*packet));
- if (framer_.version() <= QUIC_VERSION_33) {
- EXPECT_EQ(QUIC_INVALID_PACKET_HEADER, framer_.error());
- } else {
- EXPECT_EQ(QUIC_INVALID_FRAME_DATA, framer_.error());
- }
+ EXPECT_EQ(QUIC_INVALID_FRAME_DATA, framer_.error());
}
// Tests for fuzzing with Dr. Fuzz
diff --git a/chromium/net/quic/core/quic_header_list.cc b/chromium/net/quic/core/quic_header_list.cc
index 871c49a3ce5..77b85395e44 100644
--- a/chromium/net/quic/core/quic_header_list.cc
+++ b/chromium/net/quic/core/quic_header_list.cc
@@ -4,10 +4,10 @@
#include "net/quic/core/quic_header_list.h"
-using std::string;
-
#include "net/quic/core/quic_flags.h"
-#include "net/quic/core/quic_protocol.h"
+#include "net/quic/core/quic_packets.h"
+
+using std::string;
namespace net {
@@ -34,7 +34,7 @@ void QuicHeaderList::OnHeaderBlockStart() {
void QuicHeaderList::OnHeader(base::StringPiece name, base::StringPiece value) {
// Avoid infinte buffering of headers. No longer store headers
// once the current headers are over the limit.
- if (!FLAGS_quic_limit_uncompressed_headers ||
+ if (!FLAGS_quic_reloadable_flag_quic_limit_uncompressed_headers ||
uncompressed_header_bytes_ == 0 || !header_list_.empty()) {
header_list_.emplace_back(name.as_string(), value.as_string());
}
@@ -48,7 +48,7 @@ void QuicHeaderList::OnHeaderBlockEnd(size_t uncompressed_header_bytes,
size_t compressed_header_bytes) {
uncompressed_header_bytes_ = uncompressed_header_bytes;
compressed_header_bytes_ = compressed_header_bytes;
- if (FLAGS_quic_limit_uncompressed_headers &&
+ if (FLAGS_quic_reloadable_flag_quic_limit_uncompressed_headers &&
uncompressed_header_bytes_ > max_uncompressed_header_bytes_) {
Clear();
}
diff --git a/chromium/net/quic/core/quic_header_list.h b/chromium/net/quic/core/quic_header_list.h
index e74275b3c9b..fb20a6ba284 100644
--- a/chromium/net/quic/core/quic_header_list.h
+++ b/chromium/net/quic/core/quic_header_list.h
@@ -2,23 +2,23 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#ifndef NET_QUIC_QUIC_HEADER_LIST_H_
-#define NET_QUIC_QUIC_HEADER_LIST_H_
+#ifndef NET_QUIC_CORE_QUIC_HEADER_LIST_H_
+#define NET_QUIC_CORE_QUIC_HEADER_LIST_H_
#include <algorithm>
#include <deque>
#include <functional>
#include "base/strings/string_piece.h"
-#include "net/base/net_export.h"
-#include "net/quic/core/quic_bug_tracker.h"
+#include "net/quic/platform/api/quic_bug_tracker.h"
+#include "net/quic/platform/api/quic_export.h"
#include "net/spdy/spdy_header_block.h"
#include "net/spdy/spdy_headers_handler_interface.h"
namespace net {
// A simple class that accumulates header pairs
-class NET_EXPORT_PRIVATE QuicHeaderList : public SpdyHeadersHandlerInterface {
+class QUIC_EXPORT_PRIVATE QuicHeaderList : public SpdyHeadersHandlerInterface {
public:
typedef std::deque<std::pair<std::string, std::string>> ListType;
typedef ListType::const_iterator const_iterator;
@@ -36,6 +36,7 @@ class NET_EXPORT_PRIVATE QuicHeaderList : public SpdyHeadersHandlerInterface {
void OnHeaderBlockEnd(size_t uncompressed_header_bytes) override;
void OnHeaderBlockEnd(size_t uncompressed_header_bytes,
size_t compressed_header_bytes) override;
+
void Clear();
const_iterator begin() const { return header_list_.begin(); }
@@ -45,7 +46,6 @@ class NET_EXPORT_PRIVATE QuicHeaderList : public SpdyHeadersHandlerInterface {
size_t uncompressed_header_bytes() const {
return uncompressed_header_bytes_;
}
-
size_t compressed_header_bytes() const { return compressed_header_bytes_; }
void set_max_uncompressed_header_bytes(size_t max_uncompressed_header_bytes) {
@@ -71,4 +71,4 @@ inline bool operator==(const QuicHeaderList& l1, const QuicHeaderList& l2) {
} // namespace net
-#endif // NET_QUIC_QUIC_HEADER_LIST_H_
+#endif // NET_QUIC_CORE_QUIC_HEADER_LIST_H_
diff --git a/chromium/net/quic/core/quic_header_list_test.cc b/chromium/net/quic/core/quic_header_list_test.cc
index 54fa9cb78be..d9b0afd0fe6 100644
--- a/chromium/net/quic/core/quic_header_list_test.cc
+++ b/chromium/net/quic/core/quic_header_list_test.cc
@@ -6,8 +6,7 @@
#include "net/quic/core/quic_flags.h"
#include "net/quic/test_tools/quic_test_utils.h"
-#include "net/test/gtest_util.h"
-#include "testing/gmock/include/gmock/gmock.h"
+#include "testing/gtest/include/gtest/gtest.h"
using std::string;
@@ -25,7 +24,7 @@ TEST(QuicHeaderListTest, OnHeader) {
TEST(QuicHeaderListTest, TooLarge) {
test::QuicFlagSaver flags;
- FLAGS_quic_limit_uncompressed_headers = true;
+ FLAGS_quic_reloadable_flag_quic_limit_uncompressed_headers = true;
QuicHeaderList headers;
string key = "key";
string value(1 << 18, '1');
diff --git a/chromium/net/quic/core/quic_headers_stream.cc b/chromium/net/quic/core/quic_headers_stream.cc
index 1c6f682590f..9f035732844 100644
--- a/chromium/net/quic/core/quic_headers_stream.cc
+++ b/chromium/net/quic/core/quic_headers_stream.cc
@@ -4,507 +4,19 @@
#include "net/quic/core/quic_headers_stream.h"
-#include <algorithm>
-#include <string>
-#include <utility>
-
-#include "base/macros.h"
-#include "base/metrics/histogram_macros.h"
-#include "base/strings/string_number_conversions.h"
-#include "base/strings/stringprintf.h"
-#include "net/quic/core/quic_bug_tracker.h"
#include "net/quic/core/quic_flags.h"
-#include "net/quic/core/quic_header_list.h"
-#include "net/quic/core/quic_server_session_base.h"
#include "net/quic/core/quic_spdy_session.h"
-#include "net/quic/core/quic_time.h"
-#include "net/spdy/spdy_protocol.h"
-
-using base::StringPiece;
-using net::HTTP2;
-using net::SpdyFrameType;
-using std::string;
namespace net {
-namespace {
-
-class HeaderTableDebugVisitor : public HpackHeaderTable::DebugVisitorInterface {
- public:
- HeaderTableDebugVisitor(
- const QuicClock* clock,
- std::unique_ptr<QuicHeadersStream::HpackDebugVisitor> visitor)
- : clock_(clock), headers_stream_hpack_visitor_(std::move(visitor)) {}
-
- int64_t OnNewEntry(const HpackEntry& entry) override {
- DVLOG(1) << entry.GetDebugString();
- return (clock_->ApproximateNow() - QuicTime::Zero()).ToMicroseconds();
- }
-
- void OnUseEntry(const HpackEntry& entry) override {
- const QuicTime::Delta elapsed(
- clock_->ApproximateNow() -
- QuicTime::Delta::FromMicroseconds(entry.time_added()) -
- QuicTime::Zero());
- DVLOG(1) << entry.GetDebugString() << " " << elapsed.ToMilliseconds()
- << " ms";
- headers_stream_hpack_visitor_->OnUseEntry(elapsed);
- }
-
- private:
- const QuicClock* clock_;
- std::unique_ptr<QuicHeadersStream::HpackDebugVisitor>
- headers_stream_hpack_visitor_;
-
- DISALLOW_COPY_AND_ASSIGN(HeaderTableDebugVisitor);
-};
-
-// When forced HOL blocking is enabled, extra bytes in the form of
-// HTTP/2 DATA frame headers are inserted on the way down to the
-// session layer. |ForceAckListener| filters the |OnPacketAcked()|
-// notifications generated by the session layer to not count the extra
-// bytes. Otherwise, code that is using ack listener on streams might
-// consider it an error if more bytes are acked than were written to
-// the stream, it is the case with some internal stats gathering code.
-class ForceHolAckListener : public QuicAckListenerInterface {
- public:
- // |extra_bytes| should be initialized to the size of the HTTP/2
- // DATA frame header inserted when forced HOL blocking is enabled.
- ForceHolAckListener(QuicAckListenerInterface* stream_ack_listener,
- int extra_bytes)
- : stream_ack_listener_(stream_ack_listener), extra_bytes_(extra_bytes) {
- DCHECK_GE(extra_bytes, 0);
- }
-
- void OnPacketAcked(int acked_bytes, QuicTime::Delta ack_delay_time) override {
- if (extra_bytes_ > 0) {
- // Don't count the added HTTP/2 DATA frame header bytes
- int delta = std::min(extra_bytes_, acked_bytes);
- extra_bytes_ -= delta;
- acked_bytes -= delta;
- }
- stream_ack_listener_->OnPacketAcked(acked_bytes, ack_delay_time);
- }
-
- void OnPacketRetransmitted(int retransmitted_bytes) override {
- stream_ack_listener_->OnPacketRetransmitted(retransmitted_bytes);
- }
-
- private:
- ~ForceHolAckListener() override {}
-
- scoped_refptr<QuicAckListenerInterface> stream_ack_listener_;
- int extra_bytes_;
-
- DISALLOW_COPY_AND_ASSIGN(ForceHolAckListener);
-};
-
-} // namespace
-
-QuicHeadersStream::HpackDebugVisitor::HpackDebugVisitor() {}
-
-QuicHeadersStream::HpackDebugVisitor::~HpackDebugVisitor() {}
-
-// A SpdyFramer visitor which passed SYN_STREAM and SYN_REPLY frames to
-// the QuicSpdyStream, and closes the connection if any unexpected frames
-// are received.
-class QuicHeadersStream::SpdyFramerVisitor
- : public SpdyFramerVisitorInterface,
- public SpdyFramerDebugVisitorInterface {
- public:
- explicit SpdyFramerVisitor(QuicHeadersStream* stream) : stream_(stream) {}
-
- // SpdyFramerVisitorInterface implementation
- void OnSynStream(SpdyStreamId stream_id,
- SpdyStreamId associated_stream_id,
- SpdyPriority priority,
- bool fin,
- bool unidirectional) override {
- CloseConnection("SPDY SYN_STREAM frame received.");
- }
-
- void OnSynReply(SpdyStreamId stream_id, bool fin) override {
- CloseConnection("SPDY SYN_REPLY frame received.");
- }
-
- void OnStreamFrameData(SpdyStreamId stream_id,
- const char* data,
- size_t len) override {
- if (stream_->OnStreamFrameData(stream_id, data, len)) {
- return;
- }
- CloseConnection("SPDY DATA frame received.");
- }
-
- void OnStreamEnd(SpdyStreamId stream_id) override {
- // The framer invokes OnStreamEnd after processing a SYN_STREAM
- // or SYN_REPLY frame that had the fin bit set.
- }
-
- void OnStreamPadding(SpdyStreamId stream_id, size_t len) override {
- CloseConnection("SPDY frame padding received.");
- }
-
- SpdyHeadersHandlerInterface* OnHeaderFrameStart(
- SpdyStreamId /* stream_id */) override {
- return &header_list_;
- }
-
- void OnHeaderFrameEnd(SpdyStreamId /* stream_id */,
- bool end_headers) override {
- if (end_headers) {
- if (stream_->IsConnected()) {
- stream_->OnHeaderList(header_list_);
- }
- header_list_.Clear();
- }
- }
-
- void OnError(SpdyFramer* framer) override {
- CloseConnection(base::StringPrintf(
- "SPDY framing error: %s",
- SpdyFramer::ErrorCodeToString(framer->error_code())));
- }
-
- void OnDataFrameHeader(SpdyStreamId stream_id,
- size_t length,
- bool fin) override {
- if (stream_->OnDataFrameHeader(stream_id, length, fin)) {
- return;
- }
- CloseConnection("SPDY DATA frame received.");
- }
-
- void OnRstStream(SpdyStreamId stream_id,
- SpdyRstStreamStatus status) override {
- CloseConnection("SPDY RST_STREAM frame received.");
- }
-
- void OnSetting(SpdySettingsIds id, uint8_t flags, uint32_t value) override {
- if (!FLAGS_quic_respect_http2_settings_frame) {
- CloseConnection("SPDY SETTINGS frame received.");
- return;
- }
- switch (id) {
- case SETTINGS_HEADER_TABLE_SIZE:
- stream_->UpdateHeaderEncoderTableSize(value);
- break;
- case SETTINGS_ENABLE_PUSH:
- if (FLAGS_quic_enable_server_push_by_default &&
- stream_->session()->perspective() == Perspective::IS_SERVER) {
- // See rfc7540, Section 6.5.2.
- if (value > 1) {
- CloseConnection("Invalid value for SETTINGS_ENABLE_PUSH: " +
- base::IntToString(value));
- return;
- }
- stream_->UpdateEnableServerPush(value > 0);
- break;
- } else {
- CloseConnection("Unsupported field of HTTP/2 SETTINGS frame: " +
- base::IntToString(id));
- }
- break;
- // TODO(fayang): Need to support SETTINGS_MAX_HEADER_LIST_SIZE when
- // clients are actually sending it.
- default:
- CloseConnection("Unsupported field of HTTP/2 SETTINGS frame: " +
- base::IntToString(id));
- }
- }
-
- void OnSettingsAck() override {
- if (!FLAGS_quic_respect_http2_settings_frame) {
- CloseConnection("SPDY SETTINGS frame received.");
- }
- }
-
- void OnSettingsEnd() override {
- if (!FLAGS_quic_respect_http2_settings_frame) {
- CloseConnection("SPDY SETTINGS frame received.");
- }
- }
-
- void OnPing(SpdyPingId unique_id, bool is_ack) override {
- CloseConnection("SPDY PING frame received.");
- }
-
- void OnGoAway(SpdyStreamId last_accepted_stream_id,
- SpdyGoAwayStatus status) override {
- CloseConnection("SPDY GOAWAY frame received.");
- }
-
- void OnHeaders(SpdyStreamId stream_id,
- bool has_priority,
- int weight,
- SpdyStreamId parent_stream_id,
- bool exclusive,
- bool fin,
- bool end) override {
- if (!stream_->IsConnected()) {
- return;
- }
-
- // TODO(mpw): avoid down-conversion and plumb SpdyStreamPrecedence through
- // QuicHeadersStream.
- SpdyPriority priority =
- has_priority ? Http2WeightToSpdy3Priority(weight) : 0;
- stream_->OnHeaders(stream_id, has_priority, priority, fin);
- }
-
- void OnWindowUpdate(SpdyStreamId stream_id, int delta_window_size) override {
- CloseConnection("SPDY WINDOW_UPDATE frame received.");
- }
-
- void OnPushPromise(SpdyStreamId stream_id,
- SpdyStreamId promised_stream_id,
- bool end) override {
- if (!stream_->supports_push_promise()) {
- CloseConnection("PUSH_PROMISE not supported.");
- return;
- }
- if (!stream_->IsConnected()) {
- return;
- }
- stream_->OnPushPromise(stream_id, promised_stream_id, end);
- }
-
- void OnContinuation(SpdyStreamId stream_id, bool end) override {}
-
- void OnPriority(SpdyStreamId stream_id,
- SpdyStreamId parent_id,
- int weight,
- bool exclusive) override {
- CloseConnection("SPDY PRIORITY frame received.");
- }
-
- bool OnUnknownFrame(SpdyStreamId stream_id, int frame_type) override {
- CloseConnection("Unknown frame type received.");
- return false;
- }
-
- // SpdyFramerDebugVisitorInterface implementation
- void OnSendCompressedFrame(SpdyStreamId stream_id,
- SpdyFrameType type,
- size_t payload_len,
- size_t frame_len) override {
- if (payload_len == 0) {
- QUIC_BUG << "Zero payload length.";
- return;
- }
- int compression_pct = 100 - (100 * frame_len) / payload_len;
- DVLOG(1) << "Net.QuicHpackCompressionPercentage: " << compression_pct;
- UMA_HISTOGRAM_PERCENTAGE("Net.QuicHpackCompressionPercentage",
- compression_pct);
- }
-
- void OnReceiveCompressedFrame(SpdyStreamId stream_id,
- SpdyFrameType type,
- size_t frame_len) override {
- if (stream_->IsConnected()) {
- stream_->OnCompressedFrameSize(frame_len);
- }
- }
-
- void set_max_uncompressed_header_bytes(
- size_t set_max_uncompressed_header_bytes) {
- header_list_.set_max_uncompressed_header_bytes(
- set_max_uncompressed_header_bytes);
- }
-
- private:
- void CloseConnection(const std::string& details) {
- if (stream_->IsConnected()) {
- stream_->CloseConnectionWithDetails(QUIC_INVALID_HEADERS_STREAM_DATA,
- details);
- }
- }
-
- private:
- QuicHeadersStream* stream_;
- QuicHeaderList header_list_;
-
- DISALLOW_COPY_AND_ASSIGN(SpdyFramerVisitor);
-};
-
QuicHeadersStream::QuicHeadersStream(QuicSpdySession* session)
- : QuicStream(kHeadersStreamId, session),
- spdy_session_(session),
- stream_id_(kInvalidStreamId),
- promised_stream_id_(kInvalidStreamId),
- fin_(false),
- frame_len_(0),
- uncompressed_frame_len_(0),
- supports_push_promise_(session->perspective() == Perspective::IS_CLIENT),
- cur_max_timestamp_(QuicTime::Zero()),
- prev_max_timestamp_(QuicTime::Zero()),
- spdy_framer_(HTTP2),
- spdy_framer_visitor_(new SpdyFramerVisitor(this)) {
- spdy_framer_.set_visitor(spdy_framer_visitor_.get());
- spdy_framer_.set_debug_visitor(spdy_framer_visitor_.get());
+ : QuicStream(kHeadersStreamId, session), spdy_session_(session) {
// The headers stream is exempt from connection level flow control.
DisableConnectionFlowControlForThisStream();
}
QuicHeadersStream::~QuicHeadersStream() {}
-size_t QuicHeadersStream::WriteHeaders(QuicStreamId stream_id,
- SpdyHeaderBlock headers,
- bool fin,
- SpdyPriority priority,
- QuicAckListenerInterface* ack_listener) {
- SpdyHeadersIR headers_frame(stream_id, std::move(headers));
- headers_frame.set_fin(fin);
- if (session()->perspective() == Perspective::IS_CLIENT) {
- headers_frame.set_has_priority(true);
- headers_frame.set_weight(Spdy3PriorityToHttp2Weight(priority));
- }
- SpdySerializedFrame frame(spdy_framer_.SerializeFrame(headers_frame));
- WriteOrBufferData(StringPiece(frame.data(), frame.size()), false,
- ack_listener);
- return frame.size();
-}
-
-size_t QuicHeadersStream::WritePushPromise(QuicStreamId original_stream_id,
- QuicStreamId promised_stream_id,
- SpdyHeaderBlock headers) {
- if (session()->perspective() == Perspective::IS_CLIENT) {
- QUIC_BUG << "Client shouldn't send PUSH_PROMISE";
- return 0;
- }
-
- SpdyPushPromiseIR push_promise(original_stream_id, promised_stream_id,
- std::move(headers));
-
- // PUSH_PROMISE must not be the last frame sent out, at least followed by
- // response headers.
- push_promise.set_fin(false);
-
- SpdySerializedFrame frame(spdy_framer_.SerializeFrame(push_promise));
- WriteOrBufferData(StringPiece(frame.data(), frame.size()), false, nullptr);
- return frame.size();
-}
-
-void QuicHeadersStream::WriteDataFrame(
- QuicStreamId id,
- StringPiece data,
- bool fin,
- QuicAckListenerInterface* ack_notifier_delegate) {
- SpdyDataIR spdy_data(id, data);
- spdy_data.set_fin(fin);
- SpdySerializedFrame frame(spdy_framer_.SerializeFrame(spdy_data));
- scoped_refptr<ForceHolAckListener> ack_listener;
- if (ack_notifier_delegate != nullptr) {
- ack_listener = new ForceHolAckListener(ack_notifier_delegate,
- frame.size() - data.length());
- }
- // Use buffered writes so that coherence of framing is preserved
- // between streams.
- WriteOrBufferData(StringPiece(frame.data(), frame.size()), false,
- ack_listener.get());
-}
-
-QuicConsumedData QuicHeadersStream::WritevStreamData(
- QuicStreamId id,
- QuicIOVector iov,
- QuicStreamOffset offset,
- bool fin,
- QuicAckListenerInterface* ack_notifier_delegate) {
- const size_t max_len = kSpdyInitialFrameSizeLimit -
- SpdyConstants::GetDataFrameMinimumSize(HTTP2);
-
- QuicConsumedData result(0, false);
- size_t total_length = iov.total_length;
-
- if (!FLAGS_quic_bugfix_fhol_writev_fin_only_v2) {
- // Encapsulate the data into HTTP/2 DATA frames. The outer loop
- // handles each element of the source iov, the inner loop handles
- // the possibility of fragmenting eacho of those into multiple DATA
- // frames, as the DATA frames have a max size of 16KB.
- for (int i = 0; i < iov.iov_count; i++) {
- size_t offset = 0;
- const struct iovec* src_iov = &iov.iov[i];
- do {
- size_t len = std::min(std::min(src_iov->iov_len - offset, max_len),
- total_length);
- char* data = static_cast<char*>(src_iov->iov_base) + offset;
- SpdyDataIR spdy_data(id, StringPiece(data, len));
- offset += len;
- // fin handling, only set it for the final HTTP/2 DATA frame.
- bool last_iov = i == iov.iov_count - 1;
- bool last_fragment_within_iov = offset >= src_iov->iov_len;
- bool frame_fin = (last_iov && last_fragment_within_iov) ? fin : false;
- spdy_data.set_fin(frame_fin);
- if (frame_fin) {
- result.fin_consumed = true;
- }
- SpdySerializedFrame frame(spdy_framer_.SerializeFrame(spdy_data));
- DVLOG(1) << "Encapsulating in DATA frame for stream " << id << " len "
- << len << " fin " << spdy_data.fin() << " remaining "
- << src_iov->iov_len - offset;
-
- scoped_refptr<ForceHolAckListener> ack_listener;
- if (ack_notifier_delegate != nullptr) {
- ack_listener = new ForceHolAckListener(ack_notifier_delegate,
- frame.size() - len);
- }
-
- WriteOrBufferData(StringPiece(frame.data(), frame.size()), false,
- ack_listener.get());
- result.bytes_consumed += len;
- total_length -= len;
- if (total_length <= 0) {
- return result;
- }
- } while (offset < src_iov->iov_len);
- }
- } else {
- if (total_length == 0 && fin) {
- WriteDataFrame(id, StringPiece(), true, ack_notifier_delegate);
- result.fin_consumed = true;
- return result;
- }
-
- // Encapsulate the data into HTTP/2 DATA frames. The outer loop
- // handles each element of the source iov, the inner loop handles
- // the possibility of fragmenting each of those into multiple DATA
- // frames, as the DATA frames have a max size of 16KB.
- for (int i = 0; i < iov.iov_count; i++) {
- size_t src_iov_offset = 0;
- const struct iovec* src_iov = &iov.iov[i];
- do {
- if (queued_data_bytes() > 0) {
- // Limit the amount of buffering to the minimum needed to
- // preserve framing.
- return result;
- }
- size_t len = std::min(
- std::min(src_iov->iov_len - src_iov_offset, max_len), total_length);
- char* data = static_cast<char*>(src_iov->iov_base) + src_iov_offset;
- src_iov_offset += len;
- offset += len;
- // fin handling, only set it for the final HTTP/2 DATA frame.
- bool last_iov = i == iov.iov_count - 1;
- bool last_fragment_within_iov = src_iov_offset >= src_iov->iov_len;
- bool frame_fin = (last_iov && last_fragment_within_iov) ? fin : false;
- WriteDataFrame(id, StringPiece(data, len), frame_fin,
- ack_notifier_delegate);
- result.bytes_consumed += len;
- if (frame_fin) {
- result.fin_consumed = true;
- }
- DCHECK_GE(total_length, len);
- total_length -= len;
- if (total_length <= 0) {
- return result;
- }
- } while (src_iov_offset < src_iov->iov_len);
- }
- }
-
- return result;
-}
-
void QuicHeadersStream::OnDataAvailable() {
char buffer[1024];
struct iovec iov;
@@ -516,10 +28,7 @@ void QuicHeadersStream::OnDataAvailable() {
// No more data to read.
break;
}
- DCHECK(timestamp.IsInitialized());
- cur_max_timestamp_ = std::max(timestamp, cur_max_timestamp_);
- if (spdy_framer_.ProcessInput(static_cast<char*>(iov.iov_base),
- iov.iov_len) != iov.iov_len) {
+ if (spdy_session_->ProcessHeaderData(iov, timestamp) != iov.iov_len) {
// Error processing data.
return;
}
@@ -528,151 +37,11 @@ void QuicHeadersStream::OnDataAvailable() {
}
}
-void QuicHeadersStream::set_max_uncompressed_header_bytes(
- size_t set_max_uncompressed_header_bytes) {
- spdy_framer_visitor_->set_max_uncompressed_header_bytes(
- set_max_uncompressed_header_bytes);
-}
-
-void QuicHeadersStream::OnHeaders(SpdyStreamId stream_id,
- bool has_priority,
- SpdyPriority priority,
- bool fin) {
- if (has_priority) {
- if (session()->perspective() == Perspective::IS_CLIENT) {
- CloseConnectionWithDetails(QUIC_INVALID_HEADERS_STREAM_DATA,
- "Server must not send priorities.");
- return;
- }
- spdy_session_->OnStreamHeadersPriority(stream_id, priority);
- } else {
- if (session()->perspective() == Perspective::IS_SERVER) {
- CloseConnectionWithDetails(QUIC_INVALID_HEADERS_STREAM_DATA,
- "Client must send priorities.");
- return;
- }
- }
- DCHECK_EQ(kInvalidStreamId, stream_id_);
- DCHECK_EQ(kInvalidStreamId, promised_stream_id_);
- stream_id_ = stream_id;
- fin_ = fin;
-}
-
-void QuicHeadersStream::OnPushPromise(SpdyStreamId stream_id,
- SpdyStreamId promised_stream_id,
- bool end) {
- DCHECK_EQ(kInvalidStreamId, stream_id_);
- DCHECK_EQ(kInvalidStreamId, promised_stream_id_);
- stream_id_ = stream_id;
- promised_stream_id_ = promised_stream_id;
-}
-
-void QuicHeadersStream::OnHeaderList(const QuicHeaderList& header_list) {
- DVLOG(1) << "Received header list for stream " << stream_id_ << ": "
- << header_list.DebugString();
- if (prev_max_timestamp_ > cur_max_timestamp_) {
- // prev_max_timestamp_ > cur_max_timestamp_ implies that
- // headers from lower numbered streams actually came off the
- // wire after headers for the current stream, hence there was
- // HOL blocking.
- QuicTime::Delta delta = prev_max_timestamp_ - cur_max_timestamp_;
- DVLOG(1) << "stream " << stream_id_
- << ": Net.QuicSession.HeadersHOLBlockedTime "
- << delta.ToMilliseconds();
- spdy_session_->OnHeadersHeadOfLineBlocking(delta);
- }
-
- prev_max_timestamp_ = std::max(prev_max_timestamp_, cur_max_timestamp_);
- cur_max_timestamp_ = QuicTime::Zero();
- if (promised_stream_id_ == kInvalidStreamId) {
- spdy_session_->OnStreamHeaderList(stream_id_, fin_, frame_len_,
- header_list);
- } else {
- spdy_session_->OnPromiseHeaderList(stream_id_, promised_stream_id_,
- frame_len_, header_list);
- }
- // Reset state for the next frame.
- promised_stream_id_ = kInvalidStreamId;
- stream_id_ = kInvalidStreamId;
- fin_ = false;
- frame_len_ = 0;
- uncompressed_frame_len_ = 0;
-}
-
-void QuicHeadersStream::OnCompressedFrameSize(size_t frame_len) {
- frame_len_ += frame_len;
-}
-
-bool QuicHeadersStream::IsConnected() {
- return session()->connection()->connected();
-}
-
-void QuicHeadersStream::DisableHpackDynamicTable() {
- spdy_framer_.UpdateHeaderEncoderTableSize(0);
-}
-
-void QuicHeadersStream::SetHpackEncoderDebugVisitor(
- std::unique_ptr<HpackDebugVisitor> visitor) {
- spdy_framer_.SetEncoderHeaderTableDebugVisitor(
- std::unique_ptr<HeaderTableDebugVisitor>(new HeaderTableDebugVisitor(
- session()->connection()->helper()->GetClock(), std::move(visitor))));
-}
-
-void QuicHeadersStream::SetHpackDecoderDebugVisitor(
- std::unique_ptr<HpackDebugVisitor> visitor) {
- spdy_framer_.SetDecoderHeaderTableDebugVisitor(
- std::unique_ptr<HeaderTableDebugVisitor>(new HeaderTableDebugVisitor(
- session()->connection()->helper()->GetClock(), std::move(visitor))));
-}
-
-void QuicHeadersStream::UpdateHeaderEncoderTableSize(uint32_t value) {
- spdy_framer_.UpdateHeaderEncoderTableSize(value);
-}
-
-void QuicHeadersStream::UpdateEnableServerPush(bool value) {
- spdy_session_->set_server_push_enabled(value);
-}
-
void QuicHeadersStream::MaybeReleaseSequencerBuffer() {
- if (FLAGS_quic_headers_stream_release_sequencer_buffer &&
+ if (FLAGS_quic_reloadable_flag_quic_headers_stream_release_sequencer_buffer &&
spdy_session_->ShouldReleaseHeadersStreamSequencerBuffer()) {
sequencer()->ReleaseBufferIfEmpty();
}
}
-bool QuicHeadersStream::OnDataFrameHeader(QuicStreamId stream_id,
- size_t length,
- bool fin) {
- if (!spdy_session_->force_hol_blocking()) {
- return false;
- }
- if (!IsConnected()) {
- return true;
- }
- DVLOG(1) << "DATA frame header for stream " << stream_id << " length "
- << length << " fin " << fin;
- fin_ = fin;
- frame_len_ = length;
- if (fin && length == 0) {
- OnStreamFrameData(stream_id, "", 0);
- }
- return true;
-}
-
-bool QuicHeadersStream::OnStreamFrameData(QuicStreamId stream_id,
- const char* data,
- size_t len) {
- if (!spdy_session_->force_hol_blocking()) {
- return false;
- }
- if (!IsConnected()) {
- return true;
- }
- frame_len_ -= len;
- // Ignore fin_ while there is more data coming, if frame_len_ > 0.
- spdy_session_->OnStreamFrameData(stream_id, data, len,
- frame_len_ > 0 ? false : fin_);
- return true;
-}
-
} // namespace net
diff --git a/chromium/net/quic/core/quic_headers_stream.h b/chromium/net/quic/core/quic_headers_stream.h
index af79e3d1b43..40684a02047 100644
--- a/chromium/net/quic/core/quic_headers_stream.h
+++ b/chromium/net/quic/core/quic_headers_stream.h
@@ -5,15 +5,14 @@
#ifndef NET_QUIC_CORE_QUIC_HEADERS_STREAM_H_
#define NET_QUIC_CORE_QUIC_HEADERS_STREAM_H_
-#include <stddef.h>
-
+#include <cstddef>
#include <memory>
#include "base/macros.h"
-#include "net/base/net_export.h"
#include "net/quic/core/quic_header_list.h"
-#include "net/quic/core/quic_protocol.h"
+#include "net/quic/core/quic_packets.h"
#include "net/quic/core/quic_stream.h"
+#include "net/quic/platform/api/quic_export.h"
#include "net/spdy/spdy_framer.h"
namespace net {
@@ -24,150 +23,28 @@ namespace test {
class QuicHeadersStreamPeer;
} // namespace test
-// Headers in QUIC are sent as HTTP/2 HEADERS or PUSH_PROMISE frames
-// over a reserved reliable stream with the id 3. Each endpoint
-// (client and server) will allocate an instance of QuicHeadersStream
-// to send and receive headers.
-class NET_EXPORT_PRIVATE QuicHeadersStream : public QuicStream {
+// Headers in QUIC are sent as HTTP/2 HEADERS or PUSH_PROMISE frames over a
+// reserved stream with the id 3. Each endpoint (client and server) will
+// allocate an instance of QuicHeadersStream to send and receive headers.
+class QUIC_EXPORT_PRIVATE QuicHeadersStream : public QuicStream {
public:
- class NET_EXPORT_PRIVATE HpackDebugVisitor {
- public:
- HpackDebugVisitor();
-
- virtual ~HpackDebugVisitor();
-
- // For each HPACK indexed representation processed, |elapsed| is
- // the time since the corresponding entry was added to the dynamic
- // table.
- virtual void OnUseEntry(QuicTime::Delta elapsed) = 0;
-
- private:
- DISALLOW_COPY_AND_ASSIGN(HpackDebugVisitor);
- };
-
explicit QuicHeadersStream(QuicSpdySession* session);
~QuicHeadersStream() override;
- // Writes |headers| for |stream_id| in an HTTP/2 HEADERS frame to the peer.
- // If |fin| is true, the fin flag will be set on the HEADERS frame. Returns
- // the size, in bytes, of the resulting HEADERS frame.
- virtual size_t WriteHeaders(QuicStreamId stream_id,
- SpdyHeaderBlock headers,
- bool fin,
- SpdyPriority priority,
- QuicAckListenerInterface* ack_listener);
-
- // Write |headers| for |promised_stream_id| on |original_stream_id| in a
- // PUSH_PROMISE frame to peer.
- // Return the size, in bytes, of the resulting PUSH_PROMISE frame.
- virtual size_t WritePushPromise(QuicStreamId original_stream_id,
- QuicStreamId promised_stream_id,
- SpdyHeaderBlock headers);
-
- // For forcing HOL blocking. This encapsulates data from other
- // streams into HTTP/2 data frames on the headers stream.
- QuicConsumedData WritevStreamData(
- QuicStreamId id,
- QuicIOVector iov,
- QuicStreamOffset offset,
- bool fin,
- QuicAckListenerInterface* ack_notifier_delegate);
-
// QuicStream implementation
void OnDataAvailable() override;
- bool supports_push_promise() { return supports_push_promise_; }
-
- // Experimental: force HPACK to use static table and huffman coding
- // only. Part of exploring improvements related to headers stream
- // induced HOL blocking in QUIC.
- void DisableHpackDynamicTable();
-
- // Optional, enables instrumentation related to go/quic-hpack.
- void SetHpackEncoderDebugVisitor(std::unique_ptr<HpackDebugVisitor> visitor);
- void SetHpackDecoderDebugVisitor(std::unique_ptr<HpackDebugVisitor> visitor);
-
- // Sets the maximum size of the header compression table spdy_framer_ is
- // willing to use to decode header blocks.
- void UpdateHeaderEncoderTableSize(uint32_t value);
-
- // Called when SETTINGS_ENABLE_PUSH is received, only supported on
- // server side.
- void UpdateEnableServerPush(bool value);
-
// Release underlying buffer if allowed.
void MaybeReleaseSequencerBuffer();
- // Sets how much encoded data the hpack decoder of spdy_framer_ is willing to
- // buffer.
- void set_max_decode_buffer_size_bytes(size_t max_decode_buffer_size_bytes) {
- spdy_framer_.set_max_decode_buffer_size_bytes(max_decode_buffer_size_bytes);
- }
-
- void set_max_uncompressed_header_bytes(
- size_t set_max_uncompressed_header_bytes);
-
private:
friend class test::QuicHeadersStreamPeer;
- class SpdyFramerVisitor;
-
- // The following methods are called by the SimpleVisitor.
-
- // Called when a HEADERS frame has been received.
- void OnHeaders(SpdyStreamId stream_id,
- bool has_priority,
- SpdyPriority priority,
- bool fin);
-
- // Called when a PUSH_PROMISE frame has been received.
- void OnPushPromise(SpdyStreamId stream_id,
- SpdyStreamId promised_stream_id,
- bool end);
-
- // Called when the complete list of headers is available.
- void OnHeaderList(const QuicHeaderList& header_list);
-
- // Called when the size of the compressed frame payload is available.
- void OnCompressedFrameSize(size_t frame_len);
-
- // For force HOL blocking, where stream frames from all streams are
- // plumbed through headers stream as HTTP/2 data frames.
- // The following two return false if force_hol_blocking_ is false.
- bool OnDataFrameHeader(QuicStreamId stream_id, size_t length, bool fin);
- bool OnStreamFrameData(QuicStreamId stream_id, const char* data, size_t len);
- // Helper for |WritevStreamData()|.
- void WriteDataFrame(QuicStreamId stream_id,
- base::StringPiece data,
- bool fin,
- QuicAckListenerInterface* ack_notifier_delegate);
-
// Returns true if the session is still connected.
bool IsConnected();
QuicSpdySession* spdy_session_;
- // Data about the stream whose headers are being processed.
- QuicStreamId stream_id_;
- QuicStreamId promised_stream_id_;
- bool fin_;
- size_t frame_len_;
- size_t uncompressed_frame_len_;
-
- bool supports_push_promise_;
-
- // Timestamps used to measure HOL blocking, these are recorded by
- // the sequencer approximate to the time of arrival off the wire.
- // |cur_max_timestamp_| tracks the most recent arrival time of
- // frames for current (at the headers stream level) processed
- // stream's headers, and |prev_max_timestamp_| tracks the most
- // recent arrival time of lower numbered streams.
- QuicTime cur_max_timestamp_;
- QuicTime prev_max_timestamp_;
-
- SpdyFramer spdy_framer_;
- std::unique_ptr<SpdyFramerVisitor> spdy_framer_visitor_;
-
DISALLOW_COPY_AND_ASSIGN(QuicHeadersStream);
};
diff --git a/chromium/net/quic/core/quic_headers_stream_test.cc b/chromium/net/quic/core/quic_headers_stream_test.cc
index 167dfcefe2c..d4fb9d5c2da 100644
--- a/chromium/net/quic/core/quic_headers_stream_test.cc
+++ b/chromium/net/quic/core/quic_headers_stream_test.cc
@@ -4,14 +4,19 @@
#include "net/quic/core/quic_headers_stream.h"
+#include <cstdint>
+#include <ostream>
#include <string>
+#include <tuple>
+#include <utility>
-#include "base/strings/string_number_conversions.h"
-#include "net/quic/core/quic_bug_tracker.h"
+#include "net/quic/core/quic_flags.h"
#include "net/quic/core/quic_utils.h"
#include "net/quic/core/spdy_utils.h"
+#include "net/quic/platform/api/quic_bug_tracker.h"
+#include "net/quic/platform/api/quic_logging.h"
+#include "net/quic/platform/api/quic_str_cat.h"
#include "net/quic/test_tools/quic_connection_peer.h"
-#include "net/quic/test_tools/quic_headers_stream_peer.h"
#include "net/quic/test_tools/quic_spdy_session_peer.h"
#include "net/quic/test_tools/quic_stream_peer.h"
#include "net/quic/test_tools/quic_test_utils.h"
@@ -23,10 +28,7 @@
#include "testing/gtest/include/gtest/gtest.h"
using base::StringPiece;
-using std::ostream;
using std::string;
-using std::vector;
-using testing::ElementsAre;
using testing::_;
using testing::AtLeast;
using testing::HasSubstr;
@@ -35,24 +37,22 @@ using testing::Invoke;
using testing::Return;
using testing::StrictMock;
using testing::WithArgs;
-using testing::_;
// TODO(bnc): Merge these correctly.
bool FLAGS_use_http2_frame_decoder_adapter;
-bool FLAGS_spdy_use_hpack_decoder2;
bool FLAGS_spdy_framer_use_new_methods4;
namespace net {
namespace test {
-class MockHpackDebugVisitor : public QuicHeadersStream::HpackDebugVisitor {
+class MockQuicHpackDebugVisitor : public QuicHpackDebugVisitor {
public:
- explicit MockHpackDebugVisitor() : HpackDebugVisitor() {}
+ MockQuicHpackDebugVisitor() : QuicHpackDebugVisitor() {}
MOCK_METHOD1(OnUseEntry, void(QuicTime::Delta elapsed));
private:
- DISALLOW_COPY_AND_ASSIGN(MockHpackDebugVisitor);
+ DISALLOW_COPY_AND_ASSIGN(MockQuicHpackDebugVisitor);
};
namespace {
@@ -76,18 +76,10 @@ class MockVisitor : public SpdyFramerVisitorInterface {
bool(SpdyStreamId stream_id,
const char* header_data,
size_t len));
- MOCK_METHOD5(OnSynStream,
- void(SpdyStreamId stream_id,
- SpdyStreamId associated_stream_id,
- SpdyPriority priority,
- bool fin,
- bool unidirectional));
- MOCK_METHOD2(OnSynReply, void(SpdyStreamId stream_id, bool fin));
MOCK_METHOD2(OnRstStream,
void(SpdyStreamId stream_id, SpdyRstStreamStatus status));
MOCK_METHOD1(OnSettings, void(bool clear_persisted));
- MOCK_METHOD3(OnSetting,
- void(SpdySettingsIds id, uint8_t flags, uint32_t value));
+ MOCK_METHOD2(OnSetting, void(SpdySettingsIds id, uint32_t value));
MOCK_METHOD0(OnSettingsAck, void());
MOCK_METHOD0(OnSettingsEnd, void());
MOCK_METHOD2(OnPing, void(SpdyPingId unique_id, bool is_ack));
@@ -148,7 +140,7 @@ enum Http2DecoderChoice {
HTTP2_DECODER_NESTED_SPDY,
HTTP2_DECODER_NEW
};
-ostream& operator<<(ostream& os, Http2DecoderChoice v) {
+std::ostream& operator<<(std::ostream& os, Http2DecoderChoice v) {
switch (v) {
case HTTP2_DECODER_SPDY:
return os << "SPDY";
@@ -160,13 +152,15 @@ ostream& operator<<(ostream& os, Http2DecoderChoice v) {
return os;
}
-enum HpackDecoderChoice { HPACK_DECODER_SPDY, HPACK_DECODER_NEW };
-ostream& operator<<(ostream& os, HpackDecoderChoice v) {
+enum HpackDecoderChoice { HPACK_DECODER_SPDY, HPACK_DECODER2, HPACK_DECODER3 };
+std::ostream& operator<<(std::ostream& os, HpackDecoderChoice v) {
switch (v) {
case HPACK_DECODER_SPDY:
return os << "SPDY";
- case HPACK_DECODER_NEW:
- return os << "NEW";
+ case HPACK_DECODER2:
+ return os << "HPACK_DECODER2";
+ case HPACK_DECODER3:
+ return os << "HPACK_DECODER3";
}
return os;
}
@@ -200,18 +194,22 @@ struct TestParams {
}
switch (hpack_decoder) {
case HPACK_DECODER_SPDY:
- FLAGS_spdy_use_hpack_decoder2 = false;
+ FLAGS_chromium_http2_flag_spdy_use_hpack_decoder2 = false;
+ FLAGS_chromium_http2_flag_spdy_use_hpack_decoder3 = false;
break;
- case HPACK_DECODER_NEW:
- FLAGS_spdy_use_hpack_decoder2 = true;
- // Needs new header methods to be used.
- FLAGS_spdy_framer_use_new_methods4 = true;
+ case HPACK_DECODER2:
+ FLAGS_chromium_http2_flag_spdy_use_hpack_decoder2 = true;
+ FLAGS_chromium_http2_flag_spdy_use_hpack_decoder3 = false;
+ break;
+ case HPACK_DECODER3:
+ FLAGS_chromium_http2_flag_spdy_use_hpack_decoder2 = false;
+ FLAGS_chromium_http2_flag_spdy_use_hpack_decoder3 = true;
break;
}
- VLOG(1) << "TestParams: version: " << QuicVersionToString(version)
- << ", perspective: " << perspective
- << ", http2_decoder: " << http2_decoder
- << ", hpack_decoder: " << hpack_decoder;
+ QUIC_LOG(INFO) << "TestParams: version: " << QuicVersionToString(version)
+ << ", perspective: " << perspective
+ << ", http2_decoder: " << http2_decoder
+ << ", hpack_decoder: " << hpack_decoder;
}
QuicVersion version;
@@ -235,14 +233,15 @@ class QuicHeadersStreamTest : public ::testing::TestWithParam<TestParamsTuple> {
session_(connection_),
headers_stream_(QuicSpdySessionPeer::GetHeadersStream(&session_)),
body_("hello world"),
- hpack_encoder_visitor_(new StrictMock<MockHpackDebugVisitor>),
- hpack_decoder_visitor_(new StrictMock<MockHpackDebugVisitor>),
+ hpack_encoder_visitor_(new StrictMock<MockQuicHpackDebugVisitor>),
+ hpack_decoder_visitor_(new StrictMock<MockQuicHpackDebugVisitor>),
stream_frame_(kHeadersStreamId, /*fin=*/false, /*offset=*/0, ""),
next_promised_stream_id_(2) {
headers_[":version"] = "HTTP/1.1";
headers_[":status"] = "200 Ok";
headers_["content-length"] = "11";
- framer_ = std::unique_ptr<SpdyFramer>(new SpdyFramer(HTTP2));
+ framer_ = std::unique_ptr<SpdyFramer>(
+ new SpdyFramer(SpdyFramer::ENABLE_COMPRESSION));
framer_->set_visitor(&visitor_);
EXPECT_EQ(version(), session_.connection()->version());
EXPECT_TRUE(headers_stream_ != nullptr);
@@ -269,7 +268,8 @@ class QuicHeadersStreamTest : public ::testing::TestWithParam<TestParamsTuple> {
QuicConsumedData SaveIovAndNotifyAckListener(
const QuicIOVector& data,
- QuicAckListenerInterface* ack_listener) {
+ const QuicReferenceCountedPointer<QuicAckListenerInterface>&
+ ack_listener) {
QuicConsumedData result = SaveIov(data);
if (ack_listener) {
ack_listener->OnPacketAcked(result.bytes_consumed,
@@ -314,29 +314,29 @@ class QuicHeadersStreamTest : public ::testing::TestWithParam<TestParamsTuple> {
headers_handler_->OnHeaderBlockEnd(size);
}
- void WriteHeadersAndExpectSynStream(QuicStreamId stream_id,
- bool fin,
- SpdyPriority priority) {
- WriteHeadersAndCheckData(stream_id, fin, priority, SYN_STREAM);
+ void WriteAndExpectRequestHeaders(QuicStreamId stream_id,
+ bool fin,
+ SpdyPriority priority) {
+ WriteHeadersAndCheckData(stream_id, fin, priority, true /*is_request*/);
}
- void WriteHeadersAndExpectSynReply(QuicStreamId stream_id, bool fin) {
- WriteHeadersAndCheckData(stream_id, fin, 0, SYN_REPLY);
+ void WriteAndExpectResponseHeaders(QuicStreamId stream_id, bool fin) {
+ WriteHeadersAndCheckData(stream_id, fin, 0, false /*is_request*/);
}
void WriteHeadersAndCheckData(QuicStreamId stream_id,
bool fin,
SpdyPriority priority,
- SpdyFrameType type) {
+ bool is_request) {
// Write the headers and capture the outgoing data
- EXPECT_CALL(session_, WritevData(headers_stream_, kHeadersStreamId, _, _,
- false, nullptr))
+ EXPECT_CALL(session_,
+ WritevData(headers_stream_, kHeadersStreamId, _, _, false, _))
.WillOnce(WithArgs<2>(Invoke(this, &QuicHeadersStreamTest::SaveIov)));
- headers_stream_->WriteHeaders(stream_id, headers_.Clone(), fin, priority,
- nullptr);
+ QuicSpdySessionPeer::WriteHeadersImpl(
+ &session_, stream_id, headers_.Clone(), fin, priority, nullptr);
// Parse the outgoing data and check that it matches was was written.
- if (type == SYN_STREAM) {
+ if (is_request) {
EXPECT_CALL(visitor_,
OnHeaders(stream_id, kHasPriority,
Spdy3PriorityToHttp2Weight(priority),
@@ -403,8 +403,8 @@ class QuicHeadersStreamTest : public ::testing::TestWithParam<TestParamsTuple> {
string saved_payloads_;
std::unique_ptr<SpdyFramer> framer_;
StrictMock<MockVisitor> visitor_;
- std::unique_ptr<StrictMock<MockHpackDebugVisitor>> hpack_encoder_visitor_;
- std::unique_ptr<StrictMock<MockHpackDebugVisitor>> hpack_decoder_visitor_;
+ std::unique_ptr<StrictMock<MockQuicHpackDebugVisitor>> hpack_encoder_visitor_;
+ std::unique_ptr<StrictMock<MockQuicHpackDebugVisitor>> hpack_decoder_visitor_;
QuicStreamFrame stream_frame_;
QuicStreamId next_promised_stream_id_;
};
@@ -420,7 +420,7 @@ INSTANTIATE_TEST_CASE_P(
::testing::Values(HTTP2_DECODER_SPDY,
HTTP2_DECODER_NESTED_SPDY,
HTTP2_DECODER_NEW),
- ::testing::Values(HPACK_DECODER_SPDY, HPACK_DECODER_NEW)));
+ ::testing::Values(HPACK_DECODER_SPDY, HPACK_DECODER2, HPACK_DECODER3)));
TEST_P(QuicHeadersStreamTest, StreamId) {
EXPECT_EQ(3u, headers_stream_->id());
@@ -431,11 +431,11 @@ TEST_P(QuicHeadersStreamTest, WriteHeaders) {
stream_id < kClientDataStreamId3; stream_id += 2) {
for (bool fin : kFins) {
if (perspective() == Perspective::IS_SERVER) {
- WriteHeadersAndExpectSynReply(stream_id, fin);
+ WriteAndExpectResponseHeaders(stream_id, fin);
} else {
for (SpdyPriority priority = 0; priority < 7; ++priority) {
// TODO(rch): implement priorities correctly.
- WriteHeadersAndExpectSynStream(stream_id, fin, 0);
+ WriteAndExpectRequestHeaders(stream_id, fin, 0);
}
}
}
@@ -448,11 +448,11 @@ TEST_P(QuicHeadersStreamTest, WritePushPromises) {
QuicStreamId promised_stream_id = NextPromisedStreamId();
if (perspective() == Perspective::IS_SERVER) {
// Write the headers and capture the outgoing data
- EXPECT_CALL(session_, WritevData(headers_stream_, kHeadersStreamId, _, _,
- false, nullptr))
+ EXPECT_CALL(session_,
+ WritevData(headers_stream_, kHeadersStreamId, _, _, false, _))
.WillOnce(WithArgs<2>(Invoke(this, &QuicHeadersStreamTest::SaveIov)));
- headers_stream_->WritePushPromise(stream_id, promised_stream_id,
- headers_.Clone());
+ session_.WritePushPromise(stream_id, promised_stream_id,
+ headers_.Clone());
// Parse the outgoing data and check that it matches was was written.
EXPECT_CALL(visitor_,
@@ -467,8 +467,8 @@ TEST_P(QuicHeadersStreamTest, WritePushPromises) {
CheckHeaders();
saved_data_.clear();
} else {
- EXPECT_QUIC_BUG(headers_stream_->WritePushPromise(
- stream_id, promised_stream_id, headers_.Clone()),
+ EXPECT_QUIC_BUG(session_.WritePushPromise(stream_id, promised_stream_id,
+ headers_.Clone()),
"Client shouldn't send PUSH_PROMISE");
}
}
@@ -538,12 +538,12 @@ TEST_P(QuicHeadersStreamTest, ProcessPushPromise) {
}
TEST_P(QuicHeadersStreamTest, ProcessPushPromiseDisabledSetting) {
- FLAGS_quic_respect_http2_settings_frame = true;
- FLAGS_quic_enable_server_push_by_default = true;
+ FLAGS_quic_reloadable_flag_quic_respect_http2_settings_frame = true;
+ FLAGS_quic_reloadable_flag_quic_enable_server_push_by_default = true;
session_.OnConfigNegotiated();
SpdySettingsIR data;
// Respect supported settings frames SETTINGS_ENABLE_PUSH.
- data.AddSetting(SETTINGS_ENABLE_PUSH, true, true, 0);
+ data.AddSetting(SETTINGS_ENABLE_PUSH, 0);
SpdySerializedFrame frame(framer_->SerializeFrame(data));
stream_frame_.data_buffer = frame.data();
stream_frame_.data_length = frame.size();
@@ -551,7 +551,7 @@ TEST_P(QuicHeadersStreamTest, ProcessPushPromiseDisabledSetting) {
EXPECT_CALL(
*connection_,
CloseConnection(QUIC_INVALID_HEADERS_STREAM_DATA,
- "Unsupported field of HTTP/2 SETTINGS frame: 9", _));
+ "Unsupported field of HTTP/2 SETTINGS frame: 2", _));
}
headers_stream_->OnStreamFrame(stream_frame_);
EXPECT_EQ(
@@ -561,7 +561,7 @@ TEST_P(QuicHeadersStreamTest, ProcessPushPromiseDisabledSetting) {
TEST_P(QuicHeadersStreamTest, EmptyHeaderHOLBlockedTime) {
EXPECT_CALL(session_, OnHeadersHeadOfLineBlocking(_)).Times(0);
- testing::InSequence seq;
+ InSequence seq;
bool fin = true;
for (int stream_num = 0; stream_num < 10; stream_num++) {
QuicStreamId stream_id = QuicClientDataStreamId(stream_num);
@@ -615,8 +615,8 @@ TEST_P(QuicHeadersStreamTest, NonEmptyHeaderHOLBlockedTime) {
stream_frames[stream_num].offset = stream_frame_.offset;
stream_frames[stream_num].data_buffer = frames[stream_num].data();
stream_frames[stream_num].data_length = frames[stream_num].size();
- DVLOG(1) << "make frame for stream " << stream_num << " offset "
- << stream_frames[stream_num].offset;
+ QUIC_DVLOG(1) << "make frame for stream " << stream_num << " offset "
+ << stream_frames[stream_num].offset;
stream_frame_.offset += frames[stream_num].size();
EXPECT_CALL(session_, OnStreamHeaderList(stream_id, fin, _, _)).Times(1);
}
@@ -626,15 +626,15 @@ TEST_P(QuicHeadersStreamTest, NonEmptyHeaderHOLBlockedTime) {
EXPECT_CALL(session_, OnHeadersHeadOfLineBlocking(_)).Times(9);
for (int stream_num = 9; stream_num >= 0; --stream_num) {
- DVLOG(1) << "OnStreamFrame for stream " << stream_num << " offset "
- << stream_frames[stream_num].offset;
+ QUIC_DVLOG(1) << "OnStreamFrame for stream " << stream_num << " offset "
+ << stream_frames[stream_num].offset;
headers_stream_->OnStreamFrame(stream_frames[stream_num]);
connection_->AdvanceTime(QuicTime::Delta::FromMilliseconds(1));
}
}
TEST_P(QuicHeadersStreamTest, ProcessLargeRawData) {
- headers_stream_->set_max_uncompressed_header_bytes(256 * 1024);
+ QuicSpdySessionPeer::SetMaxUncompressedHeaderBytes(&session_, 256 * 1024);
// We want to create a frame that is more than the SPDY Framer's max control
// frame size, which is 16K, but less than the HPACK decoders max decode
// buffer size, which is 32K.
@@ -736,9 +736,9 @@ TEST_P(QuicHeadersStreamTest, ProcessSpdyRstStreamFrame) {
}
TEST_P(QuicHeadersStreamTest, ProcessSpdySettingsFrame) {
- FLAGS_quic_respect_http2_settings_frame = false;
+ FLAGS_quic_reloadable_flag_quic_respect_http2_settings_frame = false;
SpdySettingsIR data;
- data.AddSetting(SETTINGS_HEADER_TABLE_SIZE, true, true, 0);
+ data.AddSetting(SETTINGS_HEADER_TABLE_SIZE, 0);
SpdySerializedFrame frame(framer_->SerializeFrame(data));
EXPECT_CALL(*connection_, CloseConnection(QUIC_INVALID_HEADERS_STREAM_DATA,
"SPDY SETTINGS frame received.", _))
@@ -750,63 +750,62 @@ TEST_P(QuicHeadersStreamTest, ProcessSpdySettingsFrame) {
}
TEST_P(QuicHeadersStreamTest, RespectHttp2SettingsFrameSupportedFields) {
- FLAGS_quic_respect_http2_settings_frame = true;
+ FLAGS_quic_reloadable_flag_quic_respect_http2_settings_frame = true;
+ FLAGS_quic_reloadable_flag_quic_send_max_header_list_size = true;
const uint32_t kTestHeaderTableSize = 1000;
SpdySettingsIR data;
- // Respect supported settings frames SETTINGS_HEADER_TABLE_SIZE.
- data.AddSetting(SETTINGS_HEADER_TABLE_SIZE, true, true, kTestHeaderTableSize);
+ // Respect supported settings frames SETTINGS_HEADER_TABLE_SIZE,
+ // SETTINGS_MAX_HEADER_LIST_SIZE.
+ data.AddSetting(SETTINGS_HEADER_TABLE_SIZE, kTestHeaderTableSize);
+ data.AddSetting(SETTINGS_MAX_HEADER_LIST_SIZE, 2000);
SpdySerializedFrame frame(framer_->SerializeFrame(data));
stream_frame_.data_buffer = frame.data();
stream_frame_.data_length = frame.size();
headers_stream_->OnStreamFrame(stream_frame_);
EXPECT_EQ(kTestHeaderTableSize,
- QuicHeadersStreamPeer::GetSpdyFramer(headers_stream_)
+ QuicSpdySessionPeer::GetSpdyFramer(&session_)
.header_encoder_table_size());
}
TEST_P(QuicHeadersStreamTest, RespectHttp2SettingsFrameUnsupportedFields) {
- FLAGS_quic_respect_http2_settings_frame = true;
+ FLAGS_quic_reloadable_flag_quic_respect_http2_settings_frame = true;
+ FLAGS_quic_reloadable_flag_quic_send_max_header_list_size = true;
SpdySettingsIR data;
- // Does not support SETTINGS_MAX_HEADER_LIST_SIZE,
- // SETTINGS_MAX_CONCURRENT_STREAMS, SETTINGS_INITIAL_WINDOW_SIZE,
- // SETTINGS_ENABLE_PUSH and SETTINGS_MAX_FRAME_SIZE.
- data.AddSetting(SETTINGS_MAX_HEADER_LIST_SIZE, true, true, 2000);
- data.AddSetting(SETTINGS_MAX_CONCURRENT_STREAMS, true, true, 100);
- data.AddSetting(SETTINGS_INITIAL_WINDOW_SIZE, true, true, 100);
- data.AddSetting(SETTINGS_ENABLE_PUSH, true, true, 1);
- data.AddSetting(SETTINGS_MAX_FRAME_SIZE, true, true, 1250);
+ // Does not support SETTINGS_MAX_CONCURRENT_STREAMS,
+ // SETTINGS_INITIAL_WINDOW_SIZE, SETTINGS_ENABLE_PUSH and
+ // SETTINGS_MAX_FRAME_SIZE.
+ data.AddSetting(SETTINGS_MAX_CONCURRENT_STREAMS, 100);
+ data.AddSetting(SETTINGS_INITIAL_WINDOW_SIZE, 100);
+ data.AddSetting(SETTINGS_ENABLE_PUSH, 1);
+ data.AddSetting(SETTINGS_MAX_FRAME_SIZE, 1250);
SpdySerializedFrame frame(framer_->SerializeFrame(data));
EXPECT_CALL(
*connection_,
CloseConnection(QUIC_INVALID_HEADERS_STREAM_DATA,
- "Unsupported field of HTTP/2 SETTINGS frame: " +
- base::IntToString(SETTINGS_MAX_HEADER_LIST_SIZE),
+ QuicStrCat("Unsupported field of HTTP/2 SETTINGS frame: ",
+ SETTINGS_MAX_CONCURRENT_STREAMS),
_));
EXPECT_CALL(
*connection_,
CloseConnection(QUIC_INVALID_HEADERS_STREAM_DATA,
- "Unsupported field of HTTP/2 SETTINGS frame: " +
- base::IntToString(SETTINGS_MAX_CONCURRENT_STREAMS),
+ QuicStrCat("Unsupported field of HTTP/2 SETTINGS frame: ",
+ SETTINGS_INITIAL_WINDOW_SIZE),
_));
+ if (!FLAGS_quic_reloadable_flag_quic_enable_server_push_by_default ||
+ session_.perspective() == Perspective::IS_CLIENT) {
+ EXPECT_CALL(*connection_,
+ CloseConnection(
+ QUIC_INVALID_HEADERS_STREAM_DATA,
+ QuicStrCat("Unsupported field of HTTP/2 SETTINGS frame: ",
+ SETTINGS_ENABLE_PUSH),
+ _));
+ }
EXPECT_CALL(
*connection_,
CloseConnection(QUIC_INVALID_HEADERS_STREAM_DATA,
- "Unsupported field of HTTP/2 SETTINGS frame: " +
- base::IntToString(SETTINGS_INITIAL_WINDOW_SIZE),
+ QuicStrCat("Unsupported field of HTTP/2 SETTINGS frame: ",
+ SETTINGS_MAX_FRAME_SIZE),
_));
- if (!FLAGS_quic_enable_server_push_by_default ||
- session_.perspective() == Perspective::IS_CLIENT) {
- EXPECT_CALL(*connection_,
- CloseConnection(QUIC_INVALID_HEADERS_STREAM_DATA,
- "Unsupported field of HTTP/2 SETTINGS frame: " +
- base::IntToString(SETTINGS_ENABLE_PUSH),
- _));
- }
- EXPECT_CALL(*connection_,
- CloseConnection(QUIC_INVALID_HEADERS_STREAM_DATA,
- "Unsupported field of HTTP/2 SETTINGS frame: " +
- base::IntToString(SETTINGS_MAX_FRAME_SIZE),
- _));
stream_frame_.data_buffer = frame.data();
stream_frame_.data_length = frame.size();
headers_stream_->OnStreamFrame(stream_frame_);
@@ -855,13 +854,14 @@ TEST_P(QuicHeadersStreamTest, NoConnectionLevelFlowControl) {
}
TEST_P(QuicHeadersStreamTest, HpackDecoderDebugVisitor) {
- if (FLAGS_use_nested_spdy_framer_decoder)
+ if (test_params_.hpack_decoder == HPACK_DECODER3) {
return;
+ }
- StrictMock<MockHpackDebugVisitor>* hpack_decoder_visitor =
+ StrictMock<MockQuicHpackDebugVisitor>* hpack_decoder_visitor =
hpack_decoder_visitor_.get();
- headers_stream_->SetHpackDecoderDebugVisitor(
- std::move(hpack_decoder_visitor_));
+ QuicSpdySessionPeer::SetHpackDecoderDebugVisitor(
+ &session_, std::move(hpack_decoder_visitor_));
// Create some headers we expect to generate entries in HPACK's
// dynamic table, in addition to content-length.
@@ -869,7 +869,7 @@ TEST_P(QuicHeadersStreamTest, HpackDecoderDebugVisitor) {
headers_["key1"] = string(1 << 2, '.');
headers_["key2"] = string(1 << 3, '.');
{
- testing::InSequence seq;
+ InSequence seq;
// Number of indexed representations generated in headers below.
for (int i = 1; i < 28; i++) {
EXPECT_CALL(*hpack_decoder_visitor,
@@ -910,19 +910,19 @@ TEST_P(QuicHeadersStreamTest, HpackDecoderDebugVisitor) {
}
TEST_P(QuicHeadersStreamTest, HpackEncoderDebugVisitor) {
- StrictMock<MockHpackDebugVisitor>* hpack_encoder_visitor =
+ StrictMock<MockQuicHpackDebugVisitor>* hpack_encoder_visitor =
hpack_encoder_visitor_.get();
- headers_stream_->SetHpackEncoderDebugVisitor(
- std::move(hpack_encoder_visitor_));
+ QuicSpdySessionPeer::SetHpackEncoderDebugVisitor(
+ &session_, std::move(hpack_encoder_visitor_));
if (perspective() == Perspective::IS_SERVER) {
- testing::InSequence seq;
+ InSequence seq;
for (int i = 1; i < 4; i++) {
EXPECT_CALL(*hpack_encoder_visitor,
OnUseEntry(QuicTime::Delta::FromMilliseconds(i)));
}
} else {
- testing::InSequence seq;
+ InSequence seq;
for (int i = 1; i < 28; i++) {
EXPECT_CALL(*hpack_encoder_visitor,
OnUseEntry(QuicTime::Delta::FromMilliseconds(i)));
@@ -932,12 +932,12 @@ TEST_P(QuicHeadersStreamTest, HpackEncoderDebugVisitor) {
stream_id < kClientDataStreamId3; stream_id += 2) {
for (bool fin : {false, true}) {
if (perspective() == Perspective::IS_SERVER) {
- WriteHeadersAndExpectSynReply(stream_id, fin);
+ WriteAndExpectResponseHeaders(stream_id, fin);
connection_->AdvanceTime(QuicTime::Delta::FromMilliseconds(1));
} else {
for (SpdyPriority priority = 0; priority < 7; ++priority) {
// TODO(rch): implement priorities correctly.
- WriteHeadersAndExpectSynStream(stream_id, fin, 0);
+ WriteAndExpectRequestHeaders(stream_id, fin, 0);
connection_->AdvanceTime(QuicTime::Delta::FromMilliseconds(1));
}
}
@@ -949,7 +949,6 @@ TEST_P(QuicHeadersStreamTest, WritevStreamData) {
QuicStreamId id = kClientDataStreamId1;
QuicStreamOffset offset = 0;
struct iovec iov;
- string data;
// This test will issue a write that will require fragmenting into
// multiple HTTP/2 DATA frames.
@@ -958,11 +957,11 @@ TEST_P(QuicHeadersStreamTest, WritevStreamData) {
kSpdyInitialFrameSizeLimit * kMinDataFrames + 1024;
// Set headers stream send window large enough for data written below.
headers_stream_->flow_controller()->UpdateSendWindowOffset(data_len * 2 * 4);
- test::GenerateBody(&data, data_len);
+ string data(data_len, 'a');
for (bool fin : {true, false}) {
for (bool use_ack_listener : {true, false}) {
- scoped_refptr<ForceHolAckListener> ack_listener;
+ QuicReferenceCountedPointer<ForceHolAckListener> ack_listener;
if (use_ack_listener) {
ack_listener = new ForceHolAckListener();
}
@@ -971,8 +970,8 @@ TEST_P(QuicHeadersStreamTest, WritevStreamData) {
.WillRepeatedly(WithArgs<2, 5>(Invoke(
this, &QuicHeadersStreamTest::SaveIovAndNotifyAckListener)));
- QuicConsumedData consumed_data = headers_stream_->WritevStreamData(
- id, MakeIOVector(data, &iov), offset, fin, ack_listener.get());
+ QuicConsumedData consumed_data = session_.WritevStreamData(
+ id, MakeIOVector(data, &iov), offset, fin, ack_listener);
EXPECT_EQ(consumed_data.bytes_consumed, data_len);
EXPECT_EQ(consumed_data.fin_consumed, fin);
@@ -1001,7 +1000,6 @@ TEST_P(QuicHeadersStreamTest, WritevStreamData) {
}
TEST_P(QuicHeadersStreamTest, WritevStreamDataFinOnly) {
- FLAGS_quic_bugfix_fhol_writev_fin_only_v2 = true;
struct iovec iov;
string data;
@@ -1010,7 +1008,7 @@ TEST_P(QuicHeadersStreamTest, WritevStreamDataFinOnly) {
.WillOnce(WithArgs<2, 5>(
Invoke(this, &QuicHeadersStreamTest::SaveIovAndNotifyAckListener)));
- QuicConsumedData consumed_data = headers_stream_->WritevStreamData(
+ QuicConsumedData consumed_data = session_.WritevStreamData(
kClientDataStreamId1, MakeIOVector(data, &iov), 0, true, nullptr);
EXPECT_EQ(consumed_data.bytes_consumed, 0u);
@@ -1018,11 +1016,9 @@ TEST_P(QuicHeadersStreamTest, WritevStreamDataFinOnly) {
}
TEST_P(QuicHeadersStreamTest, WritevStreamDataSendBlocked) {
- FLAGS_quic_bugfix_fhol_writev_fin_only_v2 = true;
QuicStreamId id = kClientDataStreamId1;
QuicStreamOffset offset = 0;
struct iovec iov;
- string data;
// This test will issue a write that will require fragmenting into
// multiple HTTP/2 DATA frames. It will ensure that only 1 frame
@@ -1033,7 +1029,7 @@ TEST_P(QuicHeadersStreamTest, WritevStreamDataSendBlocked) {
const size_t data_len = kSpdyInitialFrameSizeLimit * kMinDataFrames + 1024;
// Set headers stream send window large enough for data written below.
headers_stream_->flow_controller()->UpdateSendWindowOffset(data_len * 2 * 4);
- test::GenerateBody(&data, data_len);
+ string data(data_len, 'a');
bool fin = true;
// So force the underlying |WritevData| to consume only 1 byte.
@@ -1044,19 +1040,18 @@ TEST_P(QuicHeadersStreamTest, WritevStreamDataSendBlocked) {
.WillOnce(
WithArgs<2>(Invoke(this, &QuicHeadersStreamTest::SaveIovShort)));
- QuicConsumedData consumed_data = headers_stream_->WritevStreamData(
+ QuicConsumedData consumed_data = session_.WritevStreamData(
id, MakeIOVector(data, &iov), offset, fin, nullptr);
// bytes_consumed is max HTTP/2 data frame size minus the HTTP/2
// data header size.
EXPECT_EQ(consumed_data.bytes_consumed,
- kSpdyInitialFrameSizeLimit -
- SpdyConstants::GetDataFrameMinimumSize(HTTP2));
+ kSpdyInitialFrameSizeLimit - kDataFrameMinimumSize);
EXPECT_EQ(consumed_data.fin_consumed, false);
// If session already blocked, then bytes_consumed should be zero.
- consumed_data = headers_stream_->WritevStreamData(
- id, MakeIOVector(data, &iov), offset, fin, nullptr);
+ consumed_data = session_.WritevStreamData(id, MakeIOVector(data, &iov),
+ offset, fin, nullptr);
EXPECT_EQ(consumed_data.bytes_consumed, 0u);
EXPECT_EQ(consumed_data.fin_consumed, false);
diff --git a/chromium/net/quic/core/quic_iovector.h b/chromium/net/quic/core/quic_iovector.h
new file mode 100644
index 00000000000..6e893e97e3b
--- /dev/null
+++ b/chromium/net/quic/core/quic_iovector.h
@@ -0,0 +1,28 @@
+// Copyright (c) 2012 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.
+
+#ifndef NET_QUIC_CORE_QUIC_IOVECTOR_H_
+#define NET_QUIC_CORE_QUIC_IOVECTOR_H_
+
+#include <stddef.h>
+
+#include "net/base/iovec.h"
+#include "net/quic/platform/api/quic_export.h"
+
+namespace net {
+
+// Convenience wrapper to wrap an iovec array and the total length, which must
+// be less than or equal to the actual total length of the iovecs.
+struct QUIC_EXPORT_PRIVATE QuicIOVector {
+ QuicIOVector(const struct iovec* iov, int iov_count, size_t total_length)
+ : iov(iov), iov_count(iov_count), total_length(total_length) {}
+
+ const struct iovec* iov;
+ const int iov_count;
+ const size_t total_length;
+};
+
+} // namespace net
+
+#endif // NET_QUIC_CORE_QUIC_IOVECTOR_H_
diff --git a/chromium/net/quic/core/quic_multipath_received_packet_manager.cc b/chromium/net/quic/core/quic_multipath_received_packet_manager.cc
index 7a1b2f37851..3bf497bf810 100644
--- a/chromium/net/quic/core/quic_multipath_received_packet_manager.cc
+++ b/chromium/net/quic/core/quic_multipath_received_packet_manager.cc
@@ -4,16 +4,17 @@
#include "net/quic/core/quic_multipath_received_packet_manager.h"
-#include "base/memory/ptr_util.h"
+#include <cstdint>
-#include "net/quic/core/quic_bug_tracker.h"
+#include "net/quic/platform/api/quic_bug_tracker.h"
+#include "net/quic/platform/api/quic_ptr_util.h"
namespace net {
QuicMultipathReceivedPacketManager::QuicMultipathReceivedPacketManager(
QuicConnectionStats* stats) {
path_managers_[kDefaultPathId] =
- base::MakeUnique<QuicReceivedPacketManager>(stats);
+ QuicMakeUnique<QuicReceivedPacketManager>(stats);
}
QuicMultipathReceivedPacketManager::~QuicMultipathReceivedPacketManager() {}
@@ -27,7 +28,7 @@ void QuicMultipathReceivedPacketManager::OnPathCreated(
return;
}
- path_managers_[path_id] = base::MakeUnique<QuicReceivedPacketManager>(stats);
+ path_managers_[path_id] = QuicMakeUnique<QuicReceivedPacketManager>(stats);
}
void QuicMultipathReceivedPacketManager::OnPathClosed(QuicPathId path_id) {
diff --git a/chromium/net/quic/core/quic_multipath_received_packet_manager.h b/chromium/net/quic/core/quic_multipath_received_packet_manager.h
index d85ace766fe..3f48aaa6453 100644
--- a/chromium/net/quic/core/quic_multipath_received_packet_manager.h
+++ b/chromium/net/quic/core/quic_multipath_received_packet_manager.h
@@ -5,16 +5,16 @@
// A connection level received packet manager which manages multiple per path
// received packet managers.
-#ifndef NET_QUIC_QUIC_MULTIPATH_RECEIVED_PACKET_MANAGER_H_
-#define NET_QUIC_QUIC_MULTIPATH_RECEIVED_PACKET_MANAGER_H_
+#ifndef NET_QUIC_CORE_QUIC_MULTIPATH_RECEIVED_PACKET_MANAGER_H_
+#define NET_QUIC_CORE_QUIC_MULTIPATH_RECEIVED_PACKET_MANAGER_H_
#include <memory>
#include <unordered_map>
#include <vector>
-#include "net/base/net_export.h"
-#include "net/quic/core/quic_protocol.h"
+#include "net/quic/core/quic_packets.h"
#include "net/quic/core/quic_received_packet_manager.h"
+#include "net/quic/platform/api/quic_export.h"
namespace net {
@@ -22,7 +22,7 @@ namespace test {
class QuicMultipathReceivedPacketManagerPeer;
} // namespace test
-class NET_EXPORT_PRIVATE QuicMultipathReceivedPacketManager {
+class QUIC_EXPORT_PRIVATE QuicMultipathReceivedPacketManager {
public:
explicit QuicMultipathReceivedPacketManager(QuicConnectionStats* stats);
~QuicMultipathReceivedPacketManager();
@@ -76,4 +76,4 @@ class NET_EXPORT_PRIVATE QuicMultipathReceivedPacketManager {
} // namespace net
-#endif // NET_QUIC_QUIC_MULTIPATH_RECEIVED_PACKET_MANAGER_H_
+#endif // NET_QUIC_CORE_QUIC_MULTIPATH_RECEIVED_PACKET_MANAGER_H_
diff --git a/chromium/net/quic/core/quic_multipath_received_packet_manager_test.cc b/chromium/net/quic/core/quic_multipath_received_packet_manager_test.cc
index effae4df069..d8e948d5de3 100644
--- a/chromium/net/quic/core/quic_multipath_received_packet_manager_test.cc
+++ b/chromium/net/quic/core/quic_multipath_received_packet_manager_test.cc
@@ -4,11 +4,9 @@
#include "net/quic/core/quic_multipath_received_packet_manager.h"
-#include "base/memory/ptr_util.h"
#include "net/quic/core/quic_connection_stats.h"
-#include "net/quic/core/quic_flags.h"
+#include "net/quic/platform/api/quic_ptr_util.h"
#include "net/quic/test_tools/quic_test_utils.h"
-#include "net/test/gtest_util.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
@@ -47,9 +45,9 @@ class QuicMultipathReceivedPacketManagerTest : public testing::Test {
manager_0_(new MockReceivedPacketManager(&stats_)),
manager_1_(new MockReceivedPacketManager(&stats_)) {
QuicMultipathReceivedPacketManagerPeer::SetPathReceivedPacketManager(
- &multipath_manager_, kDefaultPathId, base::WrapUnique(manager_0_));
+ &multipath_manager_, kDefaultPathId, QuicWrapUnique(manager_0_));
QuicMultipathReceivedPacketManagerPeer::SetPathReceivedPacketManager(
- &multipath_manager_, kPathId1, base::WrapUnique(manager_1_));
+ &multipath_manager_, kPathId1, QuicWrapUnique(manager_1_));
}
QuicConnectionStats stats_;
diff --git a/chromium/net/quic/core/quic_multipath_sent_packet_manager.cc b/chromium/net/quic/core/quic_multipath_sent_packet_manager.cc
deleted file mode 100644
index 5d46ec10f06..00000000000
--- a/chromium/net/quic/core/quic_multipath_sent_packet_manager.cc
+++ /dev/null
@@ -1,524 +0,0 @@
-// Copyright (c) 2012 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.
-
-#include "net/quic/core/quic_multipath_sent_packet_manager.h"
-
-#include <cstdint>
-
-#include "base/strings/string_number_conversions.h"
-#include "net/quic/core/quic_bug_tracker.h"
-
-using std::string;
-using std::max;
-
-namespace net {
-
-QuicMultipathSentPacketManager::QuicMultipathSentPacketManager(
- QuicSentPacketManagerInterface* manager,
- QuicConnectionCloseDelegateInterface* delegate)
- : delegate_(delegate) {
- path_managers_info_.push_back(PathSentPacketManagerInfo(manager, ACTIVE));
-}
-
-QuicMultipathSentPacketManager::~QuicMultipathSentPacketManager() {
- for (PathSentPacketManagerInfo path_manager_info : path_managers_info_) {
- delete path_manager_info.manager;
- }
-}
-
-void QuicMultipathSentPacketManager::SetFromConfig(const QuicConfig& config) {
- for (PathSentPacketManagerInfo path_manager_info : path_managers_info_) {
- if (path_manager_info.manager != nullptr) {
- path_manager_info.manager->SetFromConfig(config);
- }
- }
-}
-
-void QuicMultipathSentPacketManager::ResumeConnectionState(
- const CachedNetworkParameters& cached_network_params,
- bool max_bandwidth_resumption) {
- QuicSentPacketManagerInterface* path_manager =
- MaybeGetSentPacketManagerForActivePath(kDefaultPathId);
- if (path_manager == nullptr) {
- OnUnrecoverablePathError(kDefaultPathId);
- return;
- }
- path_manager->ResumeConnectionState(cached_network_params,
- max_bandwidth_resumption);
-}
-
-void QuicMultipathSentPacketManager::SetNumOpenStreams(size_t num_streams) {
- for (PathSentPacketManagerInfo path_manager_info : path_managers_info_) {
- if (path_manager_info.manager != nullptr) {
- path_manager_info.manager->SetNumOpenStreams(num_streams);
- }
- }
-}
-
-void QuicMultipathSentPacketManager::SetMaxPacingRate(
- QuicBandwidth max_pacing_rate) {
- QuicSentPacketManagerInterface* path_manager =
- MaybeGetSentPacketManagerForActivePath(kDefaultPathId);
- if (path_manager == nullptr) {
- OnUnrecoverablePathError(kDefaultPathId);
- return;
- }
- path_manager->SetMaxPacingRate(max_pacing_rate);
-}
-
-void QuicMultipathSentPacketManager::SetHandshakeConfirmed() {
- QuicSentPacketManagerInterface* path_manager =
- MaybeGetSentPacketManagerForActivePath(kDefaultPathId);
- if (path_manager == nullptr) {
- OnUnrecoverablePathError(kDefaultPathId);
- return;
- }
- path_manager->SetHandshakeConfirmed();
-}
-
-void QuicMultipathSentPacketManager::OnIncomingAck(
- const QuicAckFrame& ack_frame,
- QuicTime ack_receive_time) {
- if (ack_frame.path_id >= path_managers_info_.size() ||
- path_managers_info_[ack_frame.path_id].state != ACTIVE) {
- return;
- }
- path_managers_info_[ack_frame.path_id].manager->OnIncomingAck(
- ack_frame, ack_receive_time);
-}
-
-void QuicMultipathSentPacketManager::RetransmitUnackedPackets(
- TransmissionType retransmission_type) {
- QuicSentPacketManagerInterface* path_manager =
- MaybeGetSentPacketManagerForActivePath(kDefaultPathId);
- if (path_manager == nullptr) {
- OnUnrecoverablePathError(kDefaultPathId);
- return;
- }
- path_manager->RetransmitUnackedPackets(retransmission_type);
-}
-
-bool QuicMultipathSentPacketManager::MaybeRetransmitTailLossProbe() {
- for (PathSentPacketManagerInfo path_manager_info : path_managers_info_) {
- if (path_manager_info.manager != nullptr &&
- path_manager_info.state == ACTIVE) {
- if (path_manager_info.manager->MaybeRetransmitTailLossProbe()) {
- return true;
- }
- }
- }
- return false;
-}
-
-void QuicMultipathSentPacketManager::NeuterUnencryptedPackets() {
- QuicSentPacketManagerInterface* path_manager =
- MaybeGetSentPacketManagerForActivePath(kDefaultPathId);
- if (path_manager == nullptr) {
- OnUnrecoverablePathError(kDefaultPathId);
- return;
- }
- path_manager->NeuterUnencryptedPackets();
-}
-
-bool QuicMultipathSentPacketManager::HasPendingRetransmissions() const {
- // TODO(fayang): Move pending_retransmissions_ from path sent packet manager
- // to multipath sent packet manager.
- QuicSentPacketManagerInterface* path_manager =
- MaybeGetSentPacketManagerForActivePath(kDefaultPathId);
- return path_manager != nullptr && path_manager->HasPendingRetransmissions();
-}
-
-PendingRetransmission
-QuicMultipathSentPacketManager::NextPendingRetransmission() {
- // TODO(fayang): Move pending_retransmissions_ from path sent packet manager
- // to multipath sent packet manager.
- QuicSentPacketManagerInterface* path_manager =
- MaybeGetSentPacketManagerForActivePath(kDefaultPathId);
- if (path_manager == nullptr) {
- OnUnrecoverablePathError(kDefaultPathId);
- QuicFrames retransmittable_frames;
- return PendingRetransmission(kInvalidPathId, 0u, NOT_RETRANSMISSION,
- retransmittable_frames, false, 0,
- ENCRYPTION_NONE, PACKET_1BYTE_PACKET_NUMBER);
- }
- return path_manager->NextPendingRetransmission();
-}
-
-bool QuicMultipathSentPacketManager::HasUnackedPackets() const {
- for (PathSentPacketManagerInfo path_manager_info : path_managers_info_) {
- if (path_manager_info.manager != nullptr &&
- path_manager_info.state == ACTIVE &&
- path_manager_info.manager->HasUnackedPackets()) {
- return true;
- }
- }
- return false;
-}
-
-QuicPacketNumber QuicMultipathSentPacketManager::GetLeastUnacked(
- QuicPathId path_id) const {
- QuicSentPacketManagerInterface* path_manager =
- MaybeGetSentPacketManagerForPath(path_id);
- if (path_manager == nullptr) {
- return 0;
- }
- return path_manager->GetLeastUnacked(path_id);
-}
-
-bool QuicMultipathSentPacketManager::OnPacketSent(
- SerializedPacket* serialized_packet,
- QuicPathId original_path_id,
- QuicPacketNumber original_packet_number,
- QuicTime sent_time,
- TransmissionType transmission_type,
- HasRetransmittableData has_retransmittable_data) {
- QuicSentPacketManagerInterface* path_manager =
- MaybeGetSentPacketManagerForActivePath(serialized_packet->path_id);
- // TODO(fayang): Handle packets retransmitted on different path.
- DCHECK(original_packet_number == 0 ||
- original_path_id == serialized_packet->path_id);
- if (path_manager == nullptr) {
- OnUnrecoverablePathError(serialized_packet->path_id);
- return false;
- }
-
- return path_manager->OnPacketSent(
- serialized_packet, original_path_id, original_packet_number, sent_time,
- transmission_type, has_retransmittable_data);
-}
-
-void QuicMultipathSentPacketManager::OnRetransmissionTimeout() {
- QuicPathId rto_path = DetermineRetransmissionTimeoutPath();
- DCHECK_NE(kInvalidPathId, rto_path);
- QuicSentPacketManagerInterface* path_manager =
- MaybeGetSentPacketManagerForActivePath(rto_path);
- if (path_manager == nullptr) {
- OnUnrecoverablePathError(rto_path);
- return;
- }
- path_manager->OnRetransmissionTimeout();
-}
-
-QuicTime::Delta QuicMultipathSentPacketManager::TimeUntilSend(
- QuicTime now,
- QuicPathId* path_id) {
- QuicTime::Delta delay = QuicTime::Delta::Infinite();
- *path_id = kInvalidPathId;
- for (size_t i = 0; i < path_managers_info_.size(); ++i) {
- if (path_managers_info_[i].manager == nullptr ||
- path_managers_info_[i].state != ACTIVE) {
- continue;
- }
-
- QuicTime::Delta path_delay =
- path_managers_info_[i].manager->TimeUntilSend(now, path_id);
- if (!path_delay.IsInfinite() && path_delay < delay) {
- delay = path_delay;
- *path_id = i;
- }
- }
- DCHECK(*path_id == kInvalidPathId || !delay.IsInfinite());
- return delay;
-}
-
-const QuicTime QuicMultipathSentPacketManager::GetRetransmissionTime() const {
- QuicTime retransmission_time = QuicTime::Zero();
- for (PathSentPacketManagerInfo path_manager_info : path_managers_info_) {
- if (path_manager_info.manager == nullptr ||
- path_manager_info.state != ACTIVE) {
- continue;
- }
- QuicTime path_retransmission_time =
- path_manager_info.manager->GetRetransmissionTime();
- if (!path_retransmission_time.IsInitialized()) {
- continue;
- }
- if (!retransmission_time.IsInitialized() ||
- path_retransmission_time < retransmission_time) {
- retransmission_time = path_retransmission_time;
- }
- }
-
- return retransmission_time;
-}
-
-const RttStats* QuicMultipathSentPacketManager::GetRttStats() const {
- QuicSentPacketManagerInterface* path_manager =
- MaybeGetSentPacketManagerForActivePath(kDefaultPathId);
- if (path_manager == nullptr) {
- return nullptr;
- }
- return path_manager->GetRttStats();
-}
-
-QuicBandwidth QuicMultipathSentPacketManager::BandwidthEstimate() const {
- QuicSentPacketManagerInterface* path_manager =
- MaybeGetSentPacketManagerForActivePath(kDefaultPathId);
- if (path_manager == nullptr) {
- return QuicBandwidth::Zero();
- }
- return path_manager->BandwidthEstimate();
-}
-
-const QuicSustainedBandwidthRecorder*
-QuicMultipathSentPacketManager::SustainedBandwidthRecorder() const {
- QuicSentPacketManagerInterface* path_manager =
- MaybeGetSentPacketManagerForActivePath(kDefaultPathId);
- if (path_manager == nullptr) {
- return nullptr;
- }
- return path_manager->SustainedBandwidthRecorder();
-}
-
-QuicPacketCount QuicMultipathSentPacketManager::GetCongestionWindowInTcpMss()
- const {
- QuicSentPacketManagerInterface* path_manager =
- MaybeGetSentPacketManagerForActivePath(kDefaultPathId);
- if (path_manager == nullptr) {
- return 0;
- }
- return path_manager->GetCongestionWindowInTcpMss();
-}
-
-QuicPacketCount QuicMultipathSentPacketManager::EstimateMaxPacketsInFlight(
- QuicByteCount max_packet_length) const {
- QuicPacketCount max_packets_in_flight = 0;
- for (PathSentPacketManagerInfo path_manager_info : path_managers_info_) {
- if (path_manager_info.manager != nullptr) {
- max_packets_in_flight =
- max(max_packets_in_flight,
- path_manager_info.manager->EstimateMaxPacketsInFlight(
- max_packet_length));
- }
- }
- DCHECK_LT(0u, max_packets_in_flight);
- return max_packets_in_flight;
-}
-
-QuicByteCount QuicMultipathSentPacketManager::GetCongestionWindowInBytes()
- const {
- QuicSentPacketManagerInterface* path_manager =
- MaybeGetSentPacketManagerForActivePath(kDefaultPathId);
- if (path_manager == nullptr) {
- return 0;
- }
- return path_manager->GetCongestionWindowInBytes();
-}
-
-QuicPacketCount QuicMultipathSentPacketManager::GetSlowStartThresholdInTcpMss()
- const {
- QuicSentPacketManagerInterface* path_manager =
- MaybeGetSentPacketManagerForActivePath(kDefaultPathId);
- if (path_manager == nullptr) {
- return 0;
- }
- return path_manager->GetSlowStartThresholdInTcpMss();
-}
-
-string QuicMultipathSentPacketManager::GetDebugState() const {
- string debug_state_by_path;
- for (size_t i = 0; i < path_managers_info_.size(); ++i) {
- if (path_managers_info_[i].manager == nullptr ||
- path_managers_info_[i].state != ACTIVE) {
- continue;
- }
- const string& debug_state = path_managers_info_[i].manager->GetDebugState();
- if (debug_state.empty()) {
- continue;
- }
- debug_state_by_path =
- debug_state_by_path + "[" + base::IntToString(i) + "]:" + debug_state;
- }
- return debug_state_by_path;
-}
-
-void QuicMultipathSentPacketManager::CancelRetransmissionsForStream(
- QuicStreamId stream_id) {
- for (PathSentPacketManagerInfo path_manager_info : path_managers_info_) {
- if (path_manager_info.manager != nullptr) {
- path_manager_info.manager->CancelRetransmissionsForStream(stream_id);
- }
- }
-}
-
-void QuicMultipathSentPacketManager::OnConnectionMigration(
- QuicPathId path_id,
- PeerAddressChangeType type) {
- QuicSentPacketManagerInterface* path_manager =
- MaybeGetSentPacketManagerForActivePath(path_id);
- if (path_manager == nullptr) {
- OnUnrecoverablePathError(path_id);
- return;
- }
- path_manager->OnConnectionMigration(path_id, type);
-}
-
-void QuicMultipathSentPacketManager::SetDebugDelegate(
- DebugDelegate* debug_delegate) {
- for (PathSentPacketManagerInfo path_manager_info : path_managers_info_) {
- if (path_manager_info.manager == nullptr) {
- continue;
- }
- path_manager_info.manager->SetDebugDelegate(debug_delegate);
- }
-}
-
-QuicPacketNumber QuicMultipathSentPacketManager::GetLargestObserved(
- QuicPathId path_id) const {
- QuicSentPacketManagerInterface* path_manager =
- MaybeGetSentPacketManagerForPath(path_id);
- if (path_manager == nullptr) {
- return 0;
- }
- return path_manager->GetLargestObserved(path_id);
-}
-
-QuicPacketNumber QuicMultipathSentPacketManager::GetLargestSentPacket(
- QuicPathId path_id) const {
- QuicSentPacketManagerInterface* path_manager =
- MaybeGetSentPacketManagerForPath(path_id);
- if (path_manager == nullptr) {
- return 0;
- }
- return path_manager->GetLargestSentPacket(path_id);
-}
-
-QuicPacketNumber QuicMultipathSentPacketManager::GetLeastPacketAwaitedByPeer(
- QuicPathId path_id) const {
- QuicSentPacketManagerInterface* path_manager =
- MaybeGetSentPacketManagerForPath(path_id);
- if (path_manager == nullptr) {
- return 0;
- }
- return path_manager->GetLeastPacketAwaitedByPeer(path_id);
-}
-
-void QuicMultipathSentPacketManager::SetNetworkChangeVisitor(
- NetworkChangeVisitor* visitor) {
- for (PathSentPacketManagerInfo path_manager_info : path_managers_info_) {
- if (path_manager_info.manager == nullptr ||
- path_manager_info.state != ACTIVE) {
- continue;
- }
- path_manager_info.manager->SetNetworkChangeVisitor(visitor);
- }
-}
-
-bool QuicMultipathSentPacketManager::InSlowStart() const {
- QuicSentPacketManagerInterface* path_manager =
- MaybeGetSentPacketManagerForActivePath(kDefaultPathId);
- return path_manager != nullptr && path_manager->InSlowStart();
-}
-
-size_t QuicMultipathSentPacketManager::GetConsecutiveRtoCount() const {
- QuicSentPacketManagerInterface* path_manager =
- MaybeGetSentPacketManagerForActivePath(kDefaultPathId);
- if (path_manager == nullptr) {
- return 0;
- }
- return path_manager->GetConsecutiveRtoCount();
-}
-size_t QuicMultipathSentPacketManager::GetConsecutiveTlpCount() const {
- QuicSentPacketManagerInterface* path_manager =
- MaybeGetSentPacketManagerForActivePath(kDefaultPathId);
- if (path_manager == nullptr) {
- return 0;
- }
- return path_manager->GetConsecutiveTlpCount();
-}
-
-QuicMultipathSentPacketManager::PathSentPacketManagerInfo::
- PathSentPacketManagerInfo()
- : manager(nullptr), state(CLOSING) {}
-
-QuicMultipathSentPacketManager::PathSentPacketManagerInfo::
- PathSentPacketManagerInfo(QuicSentPacketManagerInterface* manager,
- PathSentPacketManagerState state)
- : manager(manager), state(state) {}
-
-QuicMultipathSentPacketManager::PathSentPacketManagerInfo::
- PathSentPacketManagerInfo(const PathSentPacketManagerInfo& other) = default;
-
-QuicSentPacketManagerInterface*
-QuicMultipathSentPacketManager::MaybeGetSentPacketManagerForPath(
- QuicPathId path_id) const {
- if (path_id >= path_managers_info_.size() ||
- path_managers_info_[path_id].manager == nullptr) {
- QUIC_BUG << "Sent packet manager of path: (" + base::IntToString(path_id) +
- ") must exist but does not.";
- return nullptr;
- }
-
- return path_managers_info_[path_id].manager;
-}
-
-QuicSentPacketManagerInterface*
-QuicMultipathSentPacketManager::MaybeGetSentPacketManagerForActivePath(
- QuicPathId path_id) const {
- QuicSentPacketManagerInterface* path_manager =
- MaybeGetSentPacketManagerForPath(path_id);
- if (path_manager == nullptr) {
- return nullptr;
- }
- if (path_managers_info_[path_id].state != ACTIVE) {
- QUIC_BUG << "Sent packet manager of path: (" + base::IntToString(path_id) +
- ") must be active but is not.";
- return nullptr;
- }
-
- return path_manager;
-}
-
-QuicPathId QuicMultipathSentPacketManager::DetermineRetransmissionTimeoutPath()
- const {
- QuicTime retransmission_time = QuicTime::Zero();
- QuicPathId rto_path = kInvalidPathId;
- for (size_t i = 0; i < path_managers_info_.size(); ++i) {
- if (path_managers_info_[i].manager == nullptr ||
- path_managers_info_[i].state != ACTIVE) {
- continue;
- }
- QuicTime path_retransmission_time =
- path_managers_info_[i].manager->GetRetransmissionTime();
- if (!path_retransmission_time.IsInitialized()) {
- continue;
- }
- if (!retransmission_time.IsInitialized() ||
- path_retransmission_time < retransmission_time) {
- retransmission_time = path_retransmission_time;
- rto_path = i;
- }
- }
- return rto_path;
-}
-
-void QuicMultipathSentPacketManager::OnUnrecoverablePathError(
- QuicPathId path_id) {
- if (MaybeGetSentPacketManagerForPath(path_id) == nullptr) {
- const string error_details = "Sent packet manager of path: (" +
- base::IntToString(path_id) +
- ") must exist but does not.";
- delegate_->OnUnrecoverableError(QUIC_MULTIPATH_PATH_DOES_NOT_EXIST,
- error_details,
- ConnectionCloseSource::FROM_SELF);
- return;
- }
- const string error_details = "Sent packet manager of path: (" +
- base::IntToString(path_id) +
- ") must be active but is not.";
- delegate_->OnUnrecoverableError(QUIC_MULTIPATH_PATH_NOT_ACTIVE, error_details,
- ConnectionCloseSource::FROM_SELF);
-}
-
-void QuicMultipathSentPacketManager::OnApplicationLimited() {
- for (PathSentPacketManagerInfo& path_manager_info : path_managers_info_) {
- if (path_manager_info.manager == nullptr ||
- path_manager_info.state != ACTIVE) {
- continue;
- }
- path_manager_info.manager->OnApplicationLimited();
- }
-}
-
-} // namespace net
diff --git a/chromium/net/quic/core/quic_multipath_sent_packet_manager.h b/chromium/net/quic/core/quic_multipath_sent_packet_manager.h
deleted file mode 100644
index 75b35ddf237..00000000000
--- a/chromium/net/quic/core/quic_multipath_sent_packet_manager.h
+++ /dev/null
@@ -1,220 +0,0 @@
-// Copyright (c) 2012 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.
-
-#ifndef NET_QUIC_QUIC_MULTIPATH_SENT_PACKET_MANAGER_H_
-#define NET_QUIC_QUIC_MULTIPATH_SENT_PACKET_MANAGER_H_
-
-#include <vector>
-
-#include "net/base/net_export.h"
-#include "net/quic/core/quic_protocol.h"
-#include "net/quic/core/quic_sent_packet_manager.h"
-#include "net/quic/core/quic_sent_packet_manager_interface.h"
-
-namespace net {
-
-namespace test {
-class QuicConnectionPeer;
-class QuicMultipathSentPacketManagerPeer;
-} // namespace test
-
-// A connection level sent packet manager which manages a sent packet manager
-// per path. The main duties of multipath sent packet manager comprise:
-// (1) manages a pending retransmission queue shared among all paths;
-// (2) records mapping of packets transmitted on different paths;
-// (3) consults paths which should timeout on a retransmission timeout.
-// TODO(fayang): Currently above duties are not fully implemented, need to
-// finish them.
-class NET_EXPORT_PRIVATE QuicMultipathSentPacketManager
- : public QuicSentPacketManagerInterface {
- public:
- // Multipath sent packet manager takes ownership of |manager|.
- explicit QuicMultipathSentPacketManager(
- QuicSentPacketManagerInterface* manager,
- QuicConnectionCloseDelegateInterface* delegate);
- ~QuicMultipathSentPacketManager() override;
-
- // Start implementation of QuicSentPacketManagerInterface.
- // Sets all paths from |config|.
- void SetFromConfig(const QuicConfig& config) override;
-
- // Resumes connection state on the default path.
- void ResumeConnectionState(
- const CachedNetworkParameters& cached_network_params,
- bool max_bandwidth_resumption) override;
-
- // Sets number of active streams of all paths.
- void SetNumOpenStreams(size_t num_streams) override;
-
- // Sets max pacing rate of the default path.
- void SetMaxPacingRate(QuicBandwidth max_pacing_rate) override;
-
- void SetHandshakeConfirmed() override;
-
- // Directs |ack_frame| to the appropriate path sent packet manager.
- void OnIncomingAck(const QuicAckFrame& ack_frame,
- QuicTime ack_receive_time) override;
-
- // Requests retransmission of all unacked packets of |retransmission_type| on
- // the default path.
- void RetransmitUnackedPackets(TransmissionType retransmission_type) override;
-
- // Tries to retransmit the oldest pending packet across all paths. The
- // retransmission is sent on the path that has a TLP timer pending.
- bool MaybeRetransmitTailLossProbe() override;
-
- // Removes the retransmittable frames from all unencrypted packets on the
- // default path to ensure they don't get retransmitted.
- void NeuterUnencryptedPackets() override;
-
- // Returns true if there are pending retransmissions.
- bool HasPendingRetransmissions() const override;
-
- // Retrieves the next pending retransmission. Caller must ensure that
- // there are pending retransmissions prior to calling this function.
- PendingRetransmission NextPendingRetransmission() override;
-
- // Returns true if the any path has unacked packets.
- bool HasUnackedPackets() const override;
-
- // Returns the smallest packet number of a serialized packet which has not
- // been acked on |path_id|.
- QuicPacketNumber GetLeastUnacked(QuicPathId path_id) const override;
-
- // Called when a packet has been sent to the peer. If this packet is a
- // retransmission on a different path than the original packet, records the
- // mapping in |transmissions_map_|. Retransmittable frames are transfered from
- // original packet to the sent packet.
- bool OnPacketSent(SerializedPacket* serialized_packet,
- QuicPathId original_path_id,
- QuicPacketNumber original_packet_number,
- QuicTime sent_time,
- TransmissionType transmission_type,
- HasRetransmittableData has_retransmittable_data) override;
-
- // Called when the retransmission timer expires.
- void OnRetransmissionTimeout() override;
-
- // Returns the earliest time the next packet can be sent. Sets |path_id| to be
- // the path on which the next packet should be sent.
- QuicTime::Delta TimeUntilSend(QuicTime now, QuicPathId* path_id) override;
-
- // Returns the earliest retransmission time of all paths.
- const QuicTime GetRetransmissionTime() const override;
-
- // Returns the rtt stats of the default path.
- const RttStats* GetRttStats() const override;
-
- // Returns the estimated bandwidth on default path calculated by the
- // congestion algorithm.
- QuicBandwidth BandwidthEstimate() const override;
-
- // Returns the sustained bandwidth recorder on the default path.
- const QuicSustainedBandwidthRecorder* SustainedBandwidthRecorder()
- const override;
-
- // Returns the size of the current congestion window on default path in number
- // of kDefaultTCPMSS-sized segments.
- QuicPacketCount GetCongestionWindowInTcpMss() const override;
-
- // Determines the number of packets of length |max_packet_length| which fit in
- // the congestion windows for all paths, and returns the max number of packets
- // across all paths.
- QuicPacketCount EstimateMaxPacketsInFlight(
- QuicByteCount max_packet_length) const override;
-
- // Returns the size of the current congestion window size on the default path
- // in bytes.
- QuicByteCount GetCongestionWindowInBytes() const override;
-
- // Returns the size of the slow start congestion window in number of 1460 byte
- // TCP segments on the default path.
- QuicPacketCount GetSlowStartThresholdInTcpMss() const override;
-
- // Returns debugging information about the state of the congestion
- // controller for all paths.
- std::string GetDebugState() const override;
-
- // No longer retransmit data for |stream_id| on all paths and any pending
- // retransmissions in pending_retransmissions_.
- void CancelRetransmissionsForStream(QuicStreamId stream_id) override;
-
- void OnConnectionMigration(QuicPathId path_id,
- PeerAddressChangeType type) override;
-
- // Sets debug delegate for all active paths.
- void SetDebugDelegate(DebugDelegate* debug_delegate) override;
-
- QuicPacketNumber GetLargestObserved(QuicPathId path_id) const override;
-
- QuicPacketNumber GetLargestSentPacket(QuicPathId path_id) const override;
-
- QuicPacketNumber GetLeastPacketAwaitedByPeer(
- QuicPathId path_id) const override;
-
- // Sets network change visitor for all active paths.
- void SetNetworkChangeVisitor(NetworkChangeVisitor* visitor) override;
-
- // Returns true if the default path is in slow start.
- bool InSlowStart() const override;
-
- // These two methods return the consecutive RTO or TLP count of the default
- // path.
- size_t GetConsecutiveRtoCount() const override;
- size_t GetConsecutiveTlpCount() const override;
-
- void OnApplicationLimited() override;
-
- private:
- friend class test::QuicConnectionPeer;
- friend class test::QuicMultipathSentPacketManagerPeer;
-
- // State of per path sent packet manager.
- // TODO(fayang): Need to add a state that path can receive acks but cannot
- // send data.
- enum PathSentPacketManagerState {
- ACTIVE, // We both send packets and receiving acks on this path.
- CLOSING, // We stop sending packets and receiving acks on this path. There
- // are retransmittable frames in the unacked packets map.
- };
-
- // PathSentPacketManagerInfo contains sent packet manager and its state.
- struct NET_EXPORT_PRIVATE PathSentPacketManagerInfo {
- PathSentPacketManagerInfo();
- PathSentPacketManagerInfo(QuicSentPacketManagerInterface* manager,
- PathSentPacketManagerState state);
- PathSentPacketManagerInfo(const PathSentPacketManagerInfo& other);
-
- QuicSentPacketManagerInterface* manager;
- PathSentPacketManagerState state;
- };
-
- // Returns path sent packet manager if it exists for |path_id|, returns
- // nullptr otherwise.
- QuicSentPacketManagerInterface* MaybeGetSentPacketManagerForPath(
- QuicPathId path_id) const;
-
- // Returns path sent packet manager if it exists and |path_id| is ACTIVE,
- // returns nullptr otherwise.
- QuicSentPacketManagerInterface* MaybeGetSentPacketManagerForActivePath(
- QuicPathId path_id) const;
-
- // Returns the path which has the earliest retransmission time.
- QuicPathId DetermineRetransmissionTimeoutPath() const;
-
- // Close the connection on unrecoverable path errors.
- void OnUnrecoverablePathError(QuicPathId path_id);
-
- // Current path sent packet managers info, index is path id.
- std::vector<PathSentPacketManagerInfo> path_managers_info_;
-
- // Does not own this delegate.
- QuicConnectionCloseDelegateInterface* delegate_;
-
- DISALLOW_COPY_AND_ASSIGN(QuicMultipathSentPacketManager);
-};
-
-} // namespace net
-
-#endif // NET_QUIC_QUIC_MULTIPATH_SENT_PACKET_MANAGER_H_
diff --git a/chromium/net/quic/core/quic_multipath_sent_packet_manager_test.cc b/chromium/net/quic/core/quic_multipath_sent_packet_manager_test.cc
deleted file mode 100644
index bcff44da01b..00000000000
--- a/chromium/net/quic/core/quic_multipath_sent_packet_manager_test.cc
+++ /dev/null
@@ -1,356 +0,0 @@
-// Copyright (c) 2012 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.
-
-#include "net/quic/core/quic_multipath_sent_packet_manager.h"
-
-#include "net/quic/core/quic_bug_tracker.h"
-#include "net/quic/test_tools/quic_multipath_sent_packet_manager_peer.h"
-#include "net/quic/test_tools/quic_test_utils.h"
-#include "net/test/gtest_util.h"
-#include "testing/gmock/include/gmock/gmock.h"
-#include "testing/gtest/include/gtest/gtest.h"
-
-using testing::Return;
-using testing::StrictMock;
-using testing::_;
-
-namespace net {
-namespace test {
-
-namespace {
-
-const QuicPathId kTestPathId1 = 1;
-const QuicPathId kTestPathId2 = 2;
-const QuicPathId kTestPathId3 = 3;
-
-class QuicMultipathSentPacketManagerTest : public testing::Test {
- public:
- QuicMultipathSentPacketManagerTest()
- : manager_0_(new StrictMock<MockSentPacketManager>),
- manager_1_(new StrictMock<MockSentPacketManager>),
- manager_2_(new StrictMock<MockSentPacketManager>),
- multipath_manager_(manager_0_, &delegate_) {
- // Paths 0 and 1 are active, and path 2 is closing.
- QuicMultipathSentPacketManagerPeer::AddPathWithActiveState(
- &multipath_manager_, manager_1_);
- QuicMultipathSentPacketManagerPeer::AddPathWithCloseState(
- &multipath_manager_, manager_2_);
- }
-
- ~QuicMultipathSentPacketManagerTest() override {}
-
- MockSentPacketManager* manager_0_;
- MockSentPacketManager* manager_1_;
- MockSentPacketManager* manager_2_;
- QuicMultipathSentPacketManager multipath_manager_;
- MockClock clock_;
- StrictMock<MockConnectionCloseDelegate> delegate_;
-};
-
-TEST_F(QuicMultipathSentPacketManagerTest, SetFromConfig) {
- EXPECT_CALL(*manager_0_, SetFromConfig(_)).Times(1);
- EXPECT_CALL(*manager_1_, SetFromConfig(_)).Times(1);
- EXPECT_CALL(*manager_2_, SetFromConfig(_)).Times(1);
- QuicConfig config;
- multipath_manager_.SetFromConfig(config);
-}
-
-TEST_F(QuicMultipathSentPacketManagerTest, ResumeConnectionState) {
- EXPECT_CALL(*manager_0_, ResumeConnectionState(_, true));
- multipath_manager_.ResumeConnectionState(CachedNetworkParameters(), true);
-}
-
-TEST_F(QuicMultipathSentPacketManagerTest, SetNumOpenStreams) {
- size_t kNumStreams = 10;
- EXPECT_CALL(*manager_0_, SetNumOpenStreams(kNumStreams));
- EXPECT_CALL(*manager_1_, SetNumOpenStreams(kNumStreams));
- EXPECT_CALL(*manager_2_, SetNumOpenStreams(kNumStreams));
- multipath_manager_.SetNumOpenStreams(kNumStreams);
-}
-
-TEST_F(QuicMultipathSentPacketManagerTest, SetMaxPacingRate) {
- QuicBandwidth kBandwidth = QuicBandwidth::FromBitsPerSecond(1000);
- EXPECT_CALL(*manager_0_, SetMaxPacingRate(kBandwidth));
- multipath_manager_.SetMaxPacingRate(kBandwidth);
-}
-
-TEST_F(QuicMultipathSentPacketManagerTest, SetHandshakeConfirmed) {
- EXPECT_CALL(*manager_0_, SetHandshakeConfirmed());
- multipath_manager_.SetHandshakeConfirmed();
-}
-
-TEST_F(QuicMultipathSentPacketManagerTest, OnIncomingAck) {
- QuicAckFrame frame0;
- QuicAckFrame frame1;
- frame1.path_id = kTestPathId1;
- QuicAckFrame frame2;
- frame2.path_id = kTestPathId2;
- QuicAckFrame frame3;
- frame3.path_id = kTestPathId3;
- EXPECT_CALL(*manager_0_, OnIncomingAck(_, QuicTime::Zero()));
- EXPECT_CALL(*manager_1_, OnIncomingAck(_, QuicTime::Zero()));
- EXPECT_CALL(*manager_2_, OnIncomingAck(_, QuicTime::Zero())).Times(0);
- multipath_manager_.OnIncomingAck(frame0, QuicTime::Zero());
- multipath_manager_.OnIncomingAck(frame1, QuicTime::Zero());
- multipath_manager_.OnIncomingAck(frame2, QuicTime::Zero());
- multipath_manager_.OnIncomingAck(frame3, QuicTime::Zero());
-}
-
-TEST_F(QuicMultipathSentPacketManagerTest, RetransmitUnackedPackets) {
- EXPECT_CALL(*manager_0_, RetransmitUnackedPackets(HANDSHAKE_RETRANSMISSION));
- multipath_manager_.RetransmitUnackedPackets(HANDSHAKE_RETRANSMISSION);
-}
-
-TEST_F(QuicMultipathSentPacketManagerTest, MaybeRetransmitTailLossProbe) {
- EXPECT_CALL(*manager_0_, MaybeRetransmitTailLossProbe())
- .WillOnce(Return(false));
- EXPECT_CALL(*manager_1_, MaybeRetransmitTailLossProbe())
- .WillOnce(Return(false));
- EXPECT_FALSE(multipath_manager_.MaybeRetransmitTailLossProbe());
- EXPECT_CALL(*manager_0_, MaybeRetransmitTailLossProbe())
- .WillOnce(Return(false));
- EXPECT_CALL(*manager_1_, MaybeRetransmitTailLossProbe())
- .WillOnce(Return(true));
- EXPECT_TRUE(multipath_manager_.MaybeRetransmitTailLossProbe());
-}
-
-TEST_F(QuicMultipathSentPacketManagerTest, NeuterUnencryptedPackets) {
- EXPECT_CALL(*manager_0_, NeuterUnencryptedPackets());
- multipath_manager_.NeuterUnencryptedPackets();
-}
-
-TEST_F(QuicMultipathSentPacketManagerTest, HasPendingRetransmissions) {
- EXPECT_CALL(*manager_0_, HasPendingRetransmissions()).WillOnce(Return(true));
- EXPECT_TRUE(multipath_manager_.HasPendingRetransmissions());
-}
-
-TEST_F(QuicMultipathSentPacketManagerTest, NextPendingRetransmission) {
- SerializedPacket packet(kDefaultPathId, 1, PACKET_6BYTE_PACKET_NUMBER,
- nullptr, 1250, 0u, false, false);
- PendingRetransmission retransmission(
- packet.path_id, packet.packet_number, LOSS_RETRANSMISSION,
- packet.retransmittable_frames, packet.has_crypto_handshake,
- packet.num_padding_bytes, packet.encryption_level,
- packet.packet_number_length);
- EXPECT_CALL(*manager_0_, NextPendingRetransmission())
- .WillOnce(Return(retransmission));
- multipath_manager_.NextPendingRetransmission();
-}
-
-TEST_F(QuicMultipathSentPacketManagerTest, HasUnackedPackets) {
- EXPECT_CALL(*manager_0_, HasUnackedPackets()).WillOnce(Return(false));
- EXPECT_CALL(*manager_1_, HasUnackedPackets()).WillOnce(Return(false));
- EXPECT_CALL(*manager_2_, HasUnackedPackets()).Times(0);
- EXPECT_FALSE(multipath_manager_.HasUnackedPackets());
- EXPECT_CALL(*manager_0_, HasUnackedPackets()).WillOnce(Return(false));
- EXPECT_CALL(*manager_1_, HasUnackedPackets()).WillOnce(Return(true));
- EXPECT_TRUE(multipath_manager_.HasUnackedPackets());
-}
-
-TEST_F(QuicMultipathSentPacketManagerTest, GetLeastUnacked) {
- EXPECT_CALL(*manager_0_, GetLeastUnacked(kDefaultPathId)).WillOnce(Return(2));
- EXPECT_CALL(*manager_1_, GetLeastUnacked(kTestPathId1)).WillOnce(Return(3));
- EXPECT_CALL(*manager_2_, GetLeastUnacked(kTestPathId2)).WillOnce(Return(4));
- EXPECT_EQ(2u, multipath_manager_.GetLeastUnacked(kDefaultPathId));
- EXPECT_EQ(3u, multipath_manager_.GetLeastUnacked(kTestPathId1));
- EXPECT_EQ(4u, multipath_manager_.GetLeastUnacked(kTestPathId2));
- EXPECT_QUIC_BUG(multipath_manager_.GetLeastUnacked(kTestPathId3), "");
-}
-
-TEST_F(QuicMultipathSentPacketManagerTest, OnPacketSent) {
- SerializedPacket packet0(kDefaultPathId, 1, PACKET_6BYTE_PACKET_NUMBER,
- nullptr, 1250, 0u, false, false);
- SerializedPacket packet1(kTestPathId1, 1, PACKET_6BYTE_PACKET_NUMBER, nullptr,
- 1250, 0u, false, false);
- SerializedPacket packet2(kTestPathId2, 1, PACKET_6BYTE_PACKET_NUMBER, nullptr,
- 1250, 0u, false, false);
- SerializedPacket packet3(kTestPathId3, 1, PACKET_6BYTE_PACKET_NUMBER, nullptr,
- 1250, 0u, false, false);
- EXPECT_CALL(*manager_0_,
- OnPacketSent(&packet0, kInvalidPathId, 0, clock_.Now(),
- NOT_RETRANSMISSION, HAS_RETRANSMITTABLE_DATA));
- multipath_manager_.OnPacketSent(&packet0, kInvalidPathId, 0, clock_.Now(),
- NOT_RETRANSMISSION, HAS_RETRANSMITTABLE_DATA);
- EXPECT_CALL(*manager_1_,
- OnPacketSent(&packet1, kInvalidPathId, 0, clock_.Now(),
- NOT_RETRANSMISSION, HAS_RETRANSMITTABLE_DATA));
- multipath_manager_.OnPacketSent(&packet1, kInvalidPathId, 0, clock_.Now(),
- NOT_RETRANSMISSION, HAS_RETRANSMITTABLE_DATA);
- EXPECT_CALL(*manager_2_, OnPacketSent(_, _, _, _, _, _)).Times(0);
- EXPECT_CALL(delegate_,
- OnUnrecoverableError(QUIC_MULTIPATH_PATH_NOT_ACTIVE, _, _));
- EXPECT_QUIC_BUG(multipath_manager_.OnPacketSent(
- &packet2, kInvalidPathId, 0, clock_.Now(),
- NOT_RETRANSMISSION, HAS_RETRANSMITTABLE_DATA),
- "");
- EXPECT_CALL(delegate_,
- OnUnrecoverableError(QUIC_MULTIPATH_PATH_DOES_NOT_EXIST, _, _));
- EXPECT_QUIC_BUG(multipath_manager_.OnPacketSent(
- &packet3, kInvalidPathId, 0, clock_.Now(),
- NOT_RETRANSMISSION, HAS_RETRANSMITTABLE_DATA),
- "");
-}
-
-TEST_F(QuicMultipathSentPacketManagerTest, OnRetransmissionTimeout) {
- QuicTime time0 = clock_.Now() + QuicTime::Delta::FromMilliseconds(50);
- QuicTime time1 = clock_.Now() + QuicTime::Delta::FromMilliseconds(100);
- EXPECT_CALL(*manager_0_, GetRetransmissionTime()).WillOnce(Return(time0));
- EXPECT_CALL(*manager_1_, GetRetransmissionTime()).WillOnce(Return(time1));
- EXPECT_CALL(*manager_0_, OnRetransmissionTimeout());
- multipath_manager_.OnRetransmissionTimeout();
-}
-
-TEST_F(QuicMultipathSentPacketManagerTest, TimeUntilSend) {
- QuicPathId path_id = kInvalidPathId;
- EXPECT_CALL(*manager_0_, TimeUntilSend(clock_.Now(), &path_id))
- .WillOnce(Return(QuicTime::Delta::FromMilliseconds(200)));
- EXPECT_CALL(*manager_1_, TimeUntilSend(clock_.Now(), &path_id))
- .WillOnce(Return(QuicTime::Delta::FromMilliseconds(100)));
- EXPECT_EQ(QuicTime::Delta::FromMilliseconds(100),
- multipath_manager_.TimeUntilSend(clock_.Now(), &path_id));
- EXPECT_EQ(kTestPathId1, path_id);
-}
-
-TEST_F(QuicMultipathSentPacketManagerTest, GetRetransmissionTime) {
- QuicTime time0 = clock_.Now() + QuicTime::Delta::FromMilliseconds(200);
- QuicTime time1 = clock_.Now() + QuicTime::Delta::FromMilliseconds(100);
- EXPECT_CALL(*manager_0_, GetRetransmissionTime()).WillOnce(Return(time0));
- EXPECT_CALL(*manager_1_, GetRetransmissionTime()).WillOnce(Return(time1));
- EXPECT_EQ(time1, multipath_manager_.GetRetransmissionTime());
-}
-
-TEST_F(QuicMultipathSentPacketManagerTest, GetRttStats) {
- EXPECT_CALL(*manager_0_, GetRttStats());
- multipath_manager_.GetRttStats();
-}
-
-TEST_F(QuicMultipathSentPacketManagerTest, BandwidthEstimate) {
- QuicBandwidth bandwidth = QuicBandwidth::FromKBitsPerSecond(100);
- EXPECT_CALL(*manager_0_, BandwidthEstimate()).WillOnce(Return(bandwidth));
- EXPECT_EQ(bandwidth, multipath_manager_.BandwidthEstimate());
-}
-
-TEST_F(QuicMultipathSentPacketManagerTest, GetCongestionWindowInTcpMss) {
- EXPECT_CALL(*manager_0_, GetCongestionWindowInTcpMss()).WillOnce(Return(100));
- EXPECT_EQ(100u, multipath_manager_.GetCongestionWindowInTcpMss());
-}
-
-TEST_F(QuicMultipathSentPacketManagerTest, EstimateMaxPacketsInFlight) {
- QuicByteCount max_packet_length = 1250;
- EXPECT_CALL(*manager_0_, EstimateMaxPacketsInFlight(max_packet_length))
- .WillOnce(Return(100));
- EXPECT_CALL(*manager_1_, EstimateMaxPacketsInFlight(max_packet_length))
- .WillOnce(Return(200));
- EXPECT_CALL(*manager_2_, EstimateMaxPacketsInFlight(max_packet_length))
- .WillOnce(Return(300));
- EXPECT_EQ(300u,
- multipath_manager_.EstimateMaxPacketsInFlight(max_packet_length));
-}
-
-TEST_F(QuicMultipathSentPacketManagerTest, GetSlowStartThresholdInTcpMss) {
- EXPECT_CALL(*manager_0_, GetSlowStartThresholdInTcpMss())
- .WillOnce(Return(100));
- EXPECT_EQ(100u, multipath_manager_.GetSlowStartThresholdInTcpMss());
-}
-
-TEST_F(QuicMultipathSentPacketManagerTest, CancelRetransmissionsForStream) {
- EXPECT_CALL(*manager_0_, CancelRetransmissionsForStream(1));
- EXPECT_CALL(*manager_1_, CancelRetransmissionsForStream(1));
- EXPECT_CALL(*manager_2_, CancelRetransmissionsForStream(1));
- multipath_manager_.CancelRetransmissionsForStream(1);
-}
-
-TEST_F(QuicMultipathSentPacketManagerTest, OnConnectionMigration) {
- EXPECT_CALL(*manager_0_, OnConnectionMigration(kDefaultPathId, PORT_CHANGE));
- EXPECT_CALL(*manager_2_, OnConnectionMigration(_, _)).Times(0);
- multipath_manager_.OnConnectionMigration(kDefaultPathId, PORT_CHANGE);
- EXPECT_CALL(delegate_,
- OnUnrecoverableError(QUIC_MULTIPATH_PATH_NOT_ACTIVE, _, _));
- EXPECT_QUIC_BUG(
- multipath_manager_.OnConnectionMigration(kTestPathId2, PORT_CHANGE), "");
- EXPECT_CALL(delegate_,
- OnUnrecoverableError(QUIC_MULTIPATH_PATH_DOES_NOT_EXIST, _, _));
- EXPECT_QUIC_BUG(
- multipath_manager_.OnConnectionMigration(kTestPathId3, PORT_CHANGE), "");
-}
-
-TEST_F(QuicMultipathSentPacketManagerTest, SetDebugDelegate) {
- EXPECT_CALL(*manager_0_, SetDebugDelegate(nullptr));
- EXPECT_CALL(*manager_1_, SetDebugDelegate(nullptr));
- EXPECT_CALL(*manager_2_, SetDebugDelegate(nullptr));
- multipath_manager_.SetDebugDelegate(nullptr);
-}
-
-TEST_F(QuicMultipathSentPacketManagerTest, GetLargestObserved) {
- EXPECT_CALL(*manager_0_, GetLargestObserved(kDefaultPathId))
- .WillOnce(Return(10));
- EXPECT_CALL(*manager_1_, GetLargestObserved(kTestPathId1))
- .WillOnce(Return(11));
- EXPECT_CALL(*manager_2_, GetLargestObserved(kTestPathId2))
- .WillOnce(Return(12));
- EXPECT_EQ(10u, multipath_manager_.GetLargestObserved(kDefaultPathId));
- EXPECT_EQ(11u, multipath_manager_.GetLargestObserved(kTestPathId1));
- EXPECT_EQ(12u, multipath_manager_.GetLargestObserved(kTestPathId2));
- EXPECT_QUIC_BUG(multipath_manager_.GetLargestObserved(kTestPathId3), "");
-}
-
-TEST_F(QuicMultipathSentPacketManagerTest, GetLargestSentPacket) {
- EXPECT_CALL(*manager_0_, GetLargestSentPacket(kDefaultPathId))
- .WillOnce(Return(10));
- EXPECT_CALL(*manager_1_, GetLargestSentPacket(kTestPathId1))
- .WillOnce(Return(11));
- EXPECT_CALL(*manager_2_, GetLargestSentPacket(kTestPathId2))
- .WillOnce(Return(12));
- EXPECT_EQ(10u, multipath_manager_.GetLargestSentPacket(kDefaultPathId));
- EXPECT_EQ(11u, multipath_manager_.GetLargestSentPacket(kTestPathId1));
- EXPECT_EQ(12u, multipath_manager_.GetLargestSentPacket(kTestPathId2));
- EXPECT_QUIC_BUG(multipath_manager_.GetLargestSentPacket(kTestPathId3), "");
-}
-
-TEST_F(QuicMultipathSentPacketManagerTest, GetLeastPacketAwaitedByPeer) {
- EXPECT_CALL(*manager_0_, GetLeastPacketAwaitedByPeer(kDefaultPathId))
- .WillOnce(Return(10));
- EXPECT_CALL(*manager_1_, GetLeastPacketAwaitedByPeer(kTestPathId1))
- .WillOnce(Return(11));
- EXPECT_CALL(*manager_2_, GetLeastPacketAwaitedByPeer(kTestPathId2))
- .WillOnce(Return(12));
- EXPECT_EQ(10u,
- multipath_manager_.GetLeastPacketAwaitedByPeer(kDefaultPathId));
- EXPECT_EQ(11u, multipath_manager_.GetLeastPacketAwaitedByPeer(kTestPathId1));
- EXPECT_EQ(12u, multipath_manager_.GetLeastPacketAwaitedByPeer(kTestPathId2));
- EXPECT_QUIC_BUG(multipath_manager_.GetLeastPacketAwaitedByPeer(kTestPathId3),
- "");
-}
-
-TEST_F(QuicMultipathSentPacketManagerTest, SetNetworkChangeVisitor) {
- EXPECT_CALL(*manager_0_, SetNetworkChangeVisitor(nullptr));
- EXPECT_CALL(*manager_1_, SetNetworkChangeVisitor(nullptr));
- multipath_manager_.SetNetworkChangeVisitor(nullptr);
-}
-
-TEST_F(QuicMultipathSentPacketManagerTest, InSlowStart) {
- EXPECT_CALL(*manager_0_, InSlowStart()).WillOnce(Return(true));
- EXPECT_TRUE(multipath_manager_.InSlowStart());
-}
-
-TEST_F(QuicMultipathSentPacketManagerTest, GetConsecutiveRtoCount) {
- EXPECT_CALL(*manager_0_, GetConsecutiveRtoCount()).WillOnce(Return(4));
- EXPECT_EQ(4u, multipath_manager_.GetConsecutiveRtoCount());
-}
-
-TEST_F(QuicMultipathSentPacketManagerTest, GetConsecutiveTlpCount) {
- EXPECT_CALL(*manager_0_, GetConsecutiveTlpCount()).WillOnce(Return(3));
- EXPECT_EQ(3u, multipath_manager_.GetConsecutiveTlpCount());
-}
-
-TEST_F(QuicMultipathSentPacketManagerTest, OnApplicationLimited) {
- EXPECT_CALL(*manager_0_, OnApplicationLimited()).Times(1);
- EXPECT_CALL(*manager_1_, OnApplicationLimited()).Times(1);
- EXPECT_CALL(*manager_2_, OnApplicationLimited()).Times(0);
- multipath_manager_.OnApplicationLimited();
-}
-
-} // namespace
-} // namespace test
-} // namespace net
diff --git a/chromium/net/quic/core/quic_multipath_transmissions_map.h b/chromium/net/quic/core/quic_multipath_transmissions_map.h
index 8802e4d59ee..6b40076ce63 100644
--- a/chromium/net/quic/core/quic_multipath_transmissions_map.h
+++ b/chromium/net/quic/core/quic_multipath_transmissions_map.h
@@ -9,22 +9,22 @@
// gets retransmitted on path 2 with packet 2. (2, 2) will not be inserted
// because this transmission does not "across" path compared to (2, 1).
-#ifndef NET_QUIC_QUIC_MULTIPATH_TRANSMISSIONS_MAP_H_
-#define NET_QUIC_QUIC_MULTIPATH_TRANSMISSIONS_MAP_H_
+#ifndef NET_QUIC_CORE_QUIC_MULTIPATH_TRANSMISSIONS_MAP_H_
+#define NET_QUIC_CORE_QUIC_MULTIPATH_TRANSMISSIONS_MAP_H_
#include <deque>
#include <unordered_map>
#include "base/macros.h"
-#include "net/base/net_export.h"
-#include "net/quic/core/quic_protocol.h"
+#include "net/quic/core/quic_packets.h"
#include "net/quic/core/quic_utils.h"
+#include "net/quic/platform/api/quic_export.h"
namespace net {
typedef std::pair<QuicPathId, QuicPacketNumber> QuicPathIdPacketNumber;
-class NET_EXPORT_PRIVATE QuicMultipathTransmissionsMap {
+class QUIC_EXPORT_PRIVATE QuicMultipathTransmissionsMap {
public:
struct QuicPathIdPacketNumberHash {
size_t operator()(std::pair<QuicPathId, QuicPacketNumber> value) const {
@@ -71,4 +71,4 @@ class NET_EXPORT_PRIVATE QuicMultipathTransmissionsMap {
} // namespace net
-#endif // NET_QUIC_QUIC_MULTIPATH_TRANSMISSIONS_MAP_H_
+#endif // NET_QUIC_CORE_QUIC_MULTIPATH_TRANSMISSIONS_MAP_H_
diff --git a/chromium/net/quic/core/quic_one_block_arena.h b/chromium/net/quic/core/quic_one_block_arena.h
index 37893747ec6..022918b4fe8 100644
--- a/chromium/net/quic/core/quic_one_block_arena.h
+++ b/chromium/net/quic/core/quic_one_block_arena.h
@@ -7,12 +7,14 @@
// if an allocation out of the arena ever fails in debug builds; falls back to
// heap allocation in release builds.
-#ifndef NET_QUIC_QUIC_ONE_BLOCK_ARENA_H_
-#define NET_QUIC_QUIC_ONE_BLOCK_ARENA_H_
+#ifndef NET_QUIC_CORE_QUIC_ONE_BLOCK_ARENA_H_
+#define NET_QUIC_CORE_QUIC_ONE_BLOCK_ARENA_H_
+
+#include <cstdint>
#include "net/quic/core/quic_arena_scoped_ptr.h"
-#include "net/quic/core/quic_flags.h"
-#include "net/quic/core/quic_utils.h"
+#include "net/quic/core/quic_types.h"
+#include "net/quic/platform/api/quic_bug_tracker.h"
#define PREDICT_FALSE(x) x
@@ -59,9 +61,9 @@ QuicArenaScopedPtr<T> QuicOneBlockArena<ArenaSize>::New(Args&&... args) {
static_assert(QUIC_ALIGN_OF(T) > 1,
"Objects added to the arena must be at least 2B aligned.");
if (PREDICT_FALSE(offset_ > ArenaSize - AlignedSize<T>())) {
- LOG(DFATAL) << "Ran out of space in QuicOneBlockArena at " << this
- << ", max size was " << ArenaSize << ", failing request was "
- << AlignedSize<T>() << ", end of arena was " << offset_;
+ QUIC_BUG << "Ran out of space in QuicOneBlockArena at " << this
+ << ", max size was " << ArenaSize << ", failing request was "
+ << AlignedSize<T>() << ", end of arena was " << offset_;
return QuicArenaScopedPtr<T>(new T(std::forward<Args>(args)...));
}
@@ -74,4 +76,4 @@ QuicArenaScopedPtr<T> QuicOneBlockArena<ArenaSize>::New(Args&&... args) {
} // namespace net
-#endif // NET_QUIC_QUIC_ONE_BLOCK_ARENA_H_
+#endif // NET_QUIC_CORE_QUIC_ONE_BLOCK_ARENA_H_
diff --git a/chromium/net/quic/core/quic_one_block_arena_test.cc b/chromium/net/quic/core/quic_one_block_arena_test.cc
index 15ff0c67211..2f060252e30 100644
--- a/chromium/net/quic/core/quic_one_block_arena_test.cc
+++ b/chromium/net/quic/core/quic_one_block_arena_test.cc
@@ -4,11 +4,10 @@
#include "net/quic/core/quic_one_block_arena.h"
+#include <cstdint>
+
#include "net/quic/core/interval_set.h"
-#include "net/quic/core/quic_flags.h"
-#include "net/quic/core/quic_utils.h"
#include "net/quic/test_tools/quic_test_utils.h"
-#include "net/test/gtest_util.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
diff --git a/chromium/net/quic/core/quic_packet_creator.cc b/chromium/net/quic/core/quic_packet_creator.cc
index 2ed4f805d8c..b0c47fd409b 100644
--- a/chromium/net/quic/core/quic_packet_creator.cc
+++ b/chromium/net/quic/core/quic_packet_creator.cc
@@ -5,23 +5,19 @@
#include "net/quic/core/quic_packet_creator.h"
#include <algorithm>
+#include <cstdint>
-#include "base/logging.h"
#include "base/macros.h"
#include "net/quic/core/crypto/crypto_protocol.h"
-#include "net/quic/core/crypto/quic_random.h"
-#include "net/quic/core/quic_bug_tracker.h"
#include "net/quic/core/quic_data_writer.h"
#include "net/quic/core/quic_flags.h"
#include "net/quic/core/quic_utils.h"
+#include "net/quic/platform/api/quic_aligned.h"
+#include "net/quic/platform/api/quic_bug_tracker.h"
+#include "net/quic/platform/api/quic_logging.h"
using base::StringPiece;
-using std::make_pair;
-using std::max;
-using std::min;
-using std::pair;
using std::string;
-using std::vector;
// If true, enforce that QUIC CHLOs fit in one packet.
bool FLAGS_quic_enforce_single_packet_chlo = true;
@@ -30,13 +26,11 @@ namespace net {
QuicPacketCreator::QuicPacketCreator(QuicConnectionId connection_id,
QuicFramer* framer,
- QuicRandom* random_generator,
QuicBufferAllocator* buffer_allocator,
DelegateInterface* delegate)
: delegate_(delegate),
debug_delegate_(nullptr),
framer_(framer),
- random_bool_source_(random_generator),
buffer_allocator_(buffer_allocator),
send_version_in_packet_(framer->perspective() == Perspective::IS_CLIENT),
send_path_id_in_packet_(false),
@@ -51,14 +45,13 @@ QuicPacketCreator::QuicPacketCreator(QuicConnectionId connection_id,
PACKET_1BYTE_PACKET_NUMBER,
nullptr,
0,
- 0,
false,
false) {
SetMaxPacketLength(kDefaultMaxPacketSize);
}
QuicPacketCreator::~QuicPacketCreator() {
- QuicUtils::DeleteFrames(&packet_.retransmittable_frames);
+ DeleteFrames(&packet_.retransmittable_frames);
}
void QuicPacketCreator::SetEncrypter(EncryptionLevel level,
@@ -119,7 +112,7 @@ void QuicPacketCreator::UpdatePacketNumberLength(
DCHECK_LE(least_packet_awaited_by_peer, packet_.packet_number + 1);
const QuicPacketNumber current_delta =
packet_.packet_number + 1 - least_packet_awaited_by_peer;
- const uint64_t delta = max(current_delta, max_packets_in_flight);
+ const uint64_t delta = std::max(current_delta, max_packets_in_flight);
packet_.packet_number_length =
QuicFramer::GetMinSequenceNumberLength(delta * 4);
}
@@ -140,7 +133,7 @@ bool QuicPacketCreator::ConsumeData(QuicStreamId id,
frame->stream_frame->data_length >= sizeof(kCHLO) &&
strncmp(frame->stream_frame->data_buffer,
reinterpret_cast<const char*>(&kCHLO), sizeof(kCHLO)) == 0) {
- DCHECK_EQ(static_cast<size_t>(0), iov_offset);
+ DCHECK_EQ(0u, iov_offset);
if (FLAGS_quic_enforce_single_packet_chlo &&
frame->stream_frame->data_length < iov.iov->iov_len) {
const string error_details = "Client hello won't fit in a single packet.";
@@ -212,7 +205,8 @@ void QuicPacketCreator::CreateStreamFrame(QuicStreamId id,
const size_t data_size = iov.total_length - iov_offset;
size_t min_frame_size = QuicFramer::GetMinStreamFrameSize(
id, offset, /* last_frame_in_packet= */ true);
- size_t bytes_consumed = min<size_t>(BytesFree() - min_frame_size, data_size);
+ size_t bytes_consumed =
+ std::min<size_t>(BytesFree() - min_frame_size, data_size);
bool set_fin = fin && bytes_consumed == data_size; // Last frame.
UniqueStreamBuffer buffer =
@@ -240,7 +234,7 @@ void QuicPacketCreator::CopyToBuffer(QuicIOVector iov,
// Unroll the first iteration that handles iov_offset.
const size_t iov_available = iov.iov[iovnum].iov_len - iov_offset;
- size_t copy_len = min(length, iov_available);
+ size_t copy_len = std::min(length, iov_available);
// Try to prefetch the next iov if there is at least one more after the
// current. Otherwise, it looks like an irregular access that the hardware
@@ -270,13 +264,13 @@ void QuicPacketCreator::CopyToBuffer(QuicIOVector iov,
break;
}
src = static_cast<char*>(iov.iov[iovnum].iov_base);
- copy_len = min(length, iov.iov[iovnum].iov_len);
+ copy_len = std::min(length, iov.iov[iovnum].iov_len);
}
QUIC_BUG_IF(length > 0) << "Failed to copy entire length to buffer.";
}
void QuicPacketCreator::ReserializeAllFrames(
- const PendingRetransmission& retransmission,
+ const QuicPendingRetransmission& retransmission,
char* buffer,
size_t buffer_len) {
DCHECK(queued_frames_.empty());
@@ -307,7 +301,6 @@ void QuicPacketCreator::ReserializeAllFrames(
<< packet_.packet_number_length;
}
SerializePacket(buffer, buffer_len);
- packet_.original_path_id = retransmission.path_id;
packet_.original_packet_number = retransmission.packet_number;
packet_.transmission_type = retransmission.transmission_type;
OnSerializedPacket();
@@ -320,9 +313,7 @@ void QuicPacketCreator::Flush() {
return;
}
- // TODO(rtenneti): Change the default 64 alignas value (used the default
- // value from CACHELINE_SIZE).
- ALIGNAS(64) char seralized_packet_buffer[kMaxPacketSize];
+ QUIC_CACHELINE_ALIGNED char seralized_packet_buffer[kMaxPacketSize];
SerializePacket(seralized_packet_buffer, kMaxPacketSize);
OnSerializedPacket();
}
@@ -339,11 +330,6 @@ void QuicPacketCreator::OnSerializedPacket() {
delegate_->OnSerializedPacket(&packet_);
ClearPacket();
- // Maximum packet size may be only enacted while no packet is currently being
- // constructed, so here we have a good opportunity to actually change it.
- if (CanSetMaxPacketLength()) {
- SetMaxPacketLength(max_packet_length_);
- }
}
void QuicPacketCreator::ClearPacket() {
@@ -366,13 +352,13 @@ void QuicPacketCreator::CreateAndSerializeStreamFrame(
QuicStreamOffset iov_offset,
QuicStreamOffset stream_offset,
bool fin,
- QuicAckListenerInterface* listener,
+ QuicReferenceCountedPointer<QuicAckListenerInterface> ack_listener,
size_t* num_bytes_consumed) {
DCHECK(queued_frames_.empty());
// Write out the packet header
QuicPacketHeader header;
FillPacketHeader(&header);
- ALIGNAS(64) char encrypted_buffer[kMaxPacketSize];
+ QUIC_CACHELINE_ALIGNED char encrypted_buffer[kMaxPacketSize];
QuicDataWriter writer(arraysize(encrypted_buffer), encrypted_buffer);
if (!framer_->AppendPacketHeader(header, &writer)) {
QUIC_BUG << "AppendPacketHeader failed";
@@ -388,7 +374,7 @@ void QuicPacketCreator::CreateAndSerializeStreamFrame(
const size_t available_size =
max_plaintext_size_ - writer.length() - min_frame_size;
const size_t bytes_consumed =
- min<size_t>(available_size, remaining_data_size);
+ std::min<size_t>(available_size, remaining_data_size);
const bool set_fin = fin && (bytes_consumed == remaining_data_size);
UniqueStreamBuffer stream_buffer =
@@ -396,7 +382,7 @@ void QuicPacketCreator::CreateAndSerializeStreamFrame(
CopyToBuffer(iov, iov_offset, bytes_consumed, stream_buffer.get());
std::unique_ptr<QuicStreamFrame> frame(new QuicStreamFrame(
id, set_fin, stream_offset, bytes_consumed, std::move(stream_buffer)));
- DVLOG(1) << "Adding frame: " << *frame;
+ QUIC_DVLOG(1) << "Adding frame: " << *frame;
// TODO(ianswett): AppendTypeByte and AppendStreamFrame could be optimized
// into one method that takes a QuicStreamFrame, if warranted.
@@ -423,11 +409,10 @@ void QuicPacketCreator::CreateAndSerializeStreamFrame(
// unioned with a QuicStreamFrame and a UniqueStreamBuffer.
*num_bytes_consumed = bytes_consumed;
packet_size_ = 0;
- packet_.entropy_hash = QuicFramer::GetPacketEntropyHash(header);
packet_.encrypted_buffer = encrypted_buffer;
packet_.encrypted_length = encrypted_length;
- if (listener != nullptr) {
- packet_.listeners.emplace_back(listener, bytes_consumed);
+ if (ack_listener != nullptr) {
+ packet_.listeners.emplace_back(std::move(ack_listener), bytes_consumed);
}
packet_.retransmittable_frames.push_back(QuicFrame(frame.release()));
OnSerializedPacket();
@@ -452,7 +437,7 @@ size_t QuicPacketCreator::ExpansionOnNewFrame() const {
size_t QuicPacketCreator::BytesFree() {
DCHECK_GE(max_plaintext_size_, PacketSize());
return max_plaintext_size_ -
- min(max_plaintext_size_, PacketSize() + ExpansionOnNewFrame());
+ std::min(max_plaintext_size_, PacketSize() + ExpansionOnNewFrame());
}
size_t QuicPacketCreator::PacketSize() {
@@ -478,10 +463,11 @@ bool QuicPacketCreator::AddPaddedSavedFrame(const QuicFrame& frame) {
return false;
}
-void QuicPacketCreator::AddAckListener(QuicAckListenerInterface* listener,
- QuicPacketLength length) {
+void QuicPacketCreator::AddAckListener(
+ QuicReferenceCountedPointer<QuicAckListenerInterface> ack_listener,
+ QuicPacketLength length) {
DCHECK(!queued_frames_.empty());
- packet_.listeners.emplace_back(listener, length);
+ packet_.listeners.emplace_back(std::move(ack_listener), length);
}
void QuicPacketCreator::SerializePacket(char* encrypted_buffer,
@@ -527,7 +513,6 @@ void QuicPacketCreator::SerializePacket(char* encrypted_buffer,
packet_size_ = 0;
queued_frames_.clear();
- packet_.entropy_hash = QuicFramer::GetPacketEntropyHash(header);
packet_.encrypted_buffer = encrypted_buffer;
packet_.encrypted_length = encrypted_length;
}
@@ -547,7 +532,7 @@ QuicPacketCreator::SerializeVersionNegotiationPacket(
// TODO(jri): Make this a public method of framer?
SerializedPacket QuicPacketCreator::NoPacket() {
return SerializedPacket(kInvalidPathId, 0, PACKET_1BYTE_PACKET_NUMBER,
- nullptr, 0, 0, false, false);
+ nullptr, 0, false, false);
}
void QuicPacketCreator::FillPacketHeader(QuicPacketHeader* header) {
@@ -565,7 +550,6 @@ void QuicPacketCreator::FillPacketHeader(QuicPacketHeader* header) {
header->path_id = packet_.path_id;
header->packet_number = ++packet_.packet_number;
header->public_header.packet_number_length = packet_.packet_number_length;
- header->entropy_flag = random_bool_source_.RandBool();
}
bool QuicPacketCreator::ShouldRetransmit(const QuicFrame& frame) {
@@ -582,7 +566,7 @@ bool QuicPacketCreator::ShouldRetransmit(const QuicFrame& frame) {
bool QuicPacketCreator::AddFrame(const QuicFrame& frame,
bool save_retransmittable_frames) {
- DVLOG(1) << "Adding frame: " << frame;
+ QUIC_DVLOG(1) << "Adding frame: " << frame;
if (frame.type == STREAM_FRAME &&
frame.stream_frame->stream_id != kCryptoStreamId &&
packet_.encryption_level == ENCRYPTION_NONE) {
@@ -677,20 +661,4 @@ bool QuicPacketCreator::IncludeNonceInPublicHeader() {
packet_.encryption_level == ENCRYPTION_INITIAL;
}
-QuicPacketCreator::QuicRandomBoolSource::QuicRandomBoolSource(
- QuicRandom* random)
- : random_(random), bit_bucket_(0), bit_mask_(0) {}
-
-QuicPacketCreator::QuicRandomBoolSource::~QuicRandomBoolSource() {}
-
-bool QuicPacketCreator::QuicRandomBoolSource::RandBool() {
- if (bit_mask_ == 0) {
- bit_bucket_ = random_->RandUint64();
- bit_mask_ = 1;
- }
- bool result = ((bit_bucket_ & bit_mask_) != 0);
- bit_mask_ <<= 1;
- return result;
-}
-
} // namespace net
diff --git a/chromium/net/quic/core/quic_packet_creator.h b/chromium/net/quic/core/quic_packet_creator.h
index c8bf0ae66c0..232b31d79f9 100644
--- a/chromium/net/quic/core/quic_packet_creator.h
+++ b/chromium/net/quic/core/quic_packet_creator.h
@@ -7,11 +7,10 @@
// packets on one path at the same time. Currently, next packet number is
// tracked per-path.
-#ifndef NET_QUIC_QUIC_PACKET_CREATOR_H_
-#define NET_QUIC_QUIC_PACKET_CREATOR_H_
-
-#include <stddef.h>
+#ifndef NET_QUIC_CORE_QUIC_PACKET_CREATOR_H_
+#define NET_QUIC_CORE_QUIC_PACKET_CREATOR_H_
+#include <cstddef>
#include <memory>
#include <string>
#include <unordered_map>
@@ -20,21 +19,22 @@
#include "base/macros.h"
#include "base/strings/string_piece.h"
-#include "net/base/net_export.h"
+#include "net/quic/core/quic_connection_close_delegate_interface.h"
#include "net/quic/core/quic_framer.h"
-#include "net/quic/core/quic_protocol.h"
+#include "net/quic/core/quic_iovector.h"
+#include "net/quic/core/quic_packets.h"
+#include "net/quic/core/quic_pending_retransmission.h"
+#include "net/quic/platform/api/quic_export.h"
namespace net {
namespace test {
class QuicPacketCreatorPeer;
}
-class QuicRandom;
-
-class NET_EXPORT_PRIVATE QuicPacketCreator {
+class QUIC_EXPORT_PRIVATE QuicPacketCreator {
public:
// A delegate interface for further processing serialized packet.
- class NET_EXPORT_PRIVATE DelegateInterface
+ class QUIC_EXPORT_PRIVATE DelegateInterface
: public QuicConnectionCloseDelegateInterface {
public:
~DelegateInterface() override {}
@@ -47,7 +47,7 @@ class NET_EXPORT_PRIVATE QuicPacketCreator {
// Interface which gets callbacks from the QuicPacketCreator at interesting
// points. Implementations must not mutate the state of the creator
// as a result of these callbacks.
- class NET_EXPORT_PRIVATE DebugDelegate {
+ class QUIC_EXPORT_PRIVATE DebugDelegate {
public:
virtual ~DebugDelegate() {}
@@ -55,10 +55,8 @@ class NET_EXPORT_PRIVATE QuicPacketCreator {
virtual void OnFrameAddedToPacket(const QuicFrame& frame) {}
};
- // QuicRandom* required for packet entropy.
QuicPacketCreator(QuicConnectionId connection_id,
QuicFramer* framer,
- QuicRandom* random_generator,
QuicBufferAllocator* buffer_allocator,
DelegateInterface* delegate);
@@ -108,7 +106,7 @@ class NET_EXPORT_PRIVATE QuicPacketCreator {
// Re-serializes frames with the original packet's packet number length.
// Used for retransmitting packets to ensure they aren't too long.
- void ReserializeAllFrames(const PendingRetransmission& retransmission,
+ void ReserializeAllFrames(const QuicPendingRetransmission& retransmission,
char* buffer,
size_t buffer_len);
@@ -120,13 +118,14 @@ class NET_EXPORT_PRIVATE QuicPacketCreator {
// QuicStreamFrame to the returned SerializedPacket. Sets
// |num_bytes_consumed| to the number of bytes consumed to create the
// QuicStreamFrame.
- void CreateAndSerializeStreamFrame(QuicStreamId id,
- const QuicIOVector& iov,
- QuicStreamOffset iov_offset,
- QuicStreamOffset stream_offset,
- bool fin,
- QuicAckListenerInterface* listener,
- size_t* num_bytes_consumed);
+ void CreateAndSerializeStreamFrame(
+ QuicStreamId id,
+ const QuicIOVector& iov,
+ QuicStreamOffset iov_offset,
+ QuicStreamOffset stream_offset,
+ bool fin,
+ QuicReferenceCountedPointer<QuicAckListenerInterface> listener,
+ size_t* num_bytes_consumed);
// Returns true if there are frames pending to be serialized.
bool HasPendingFrames() const;
@@ -160,14 +159,13 @@ class NET_EXPORT_PRIVATE QuicPacketCreator {
// Identical to AddSavedFrame, but allows the frame to be padded.
bool AddPaddedSavedFrame(const QuicFrame& frame);
- // Adds |listener| to the next serialized packet and notifies the
- // std::listener with |length| as the number of acked bytes.
- void AddAckListener(QuicAckListenerInterface* listener,
- QuicPacketLength length);
+ // Adds |listener| to the next serialized packet and notifies the listener
+ // with |length| as the number of acked bytes.
+ void AddAckListener(
+ QuicReferenceCountedPointer<QuicAckListenerInterface> listener,
+ QuicPacketLength length);
// Creates a version negotiation packet which supports |supported_versions|.
- // Also, sets the entropy hash of the serialized packet to a random bool and
- // returns that value as a member of SerializedPacket.
std::unique_ptr<QuicEncryptedPacket> SerializeVersionNegotiationPacket(
const QuicVersionVector& supported_versions);
@@ -223,30 +221,6 @@ class NET_EXPORT_PRIVATE QuicPacketCreator {
private:
friend class test::QuicPacketCreatorPeer;
- // A QuicRandom wrapper that gets a bucket of entropy and distributes it
- // bit-by-bit. Replenishes the bucket as needed. Not thread-safe. Expose this
- // class if single bit randomness is needed elsewhere.
- class QuicRandomBoolSource {
- public:
- // random: Source of entropy. Not owned.
- explicit QuicRandomBoolSource(QuicRandom* random);
-
- ~QuicRandomBoolSource();
-
- // Returns the next random bit from the bucket.
- bool RandBool();
-
- private:
- // Source of entropy.
- QuicRandom* random_;
- // Stored random bits.
- uint64_t bit_bucket_;
- // The next available bit has "1" in the mask. Zero means empty bucket.
- uint64_t bit_mask_;
-
- DISALLOW_COPY_AND_ASSIGN(QuicRandomBoolSource);
- };
-
static bool ShouldRetransmit(const QuicFrame& frame);
// Converts a raw payload to a frame which fits into the current open
@@ -283,8 +257,7 @@ class NET_EXPORT_PRIVATE QuicPacketCreator {
// Serializes all frames which have been added and adds any which should be
// retransmitted to packet_.retransmittable_frames. All frames must fit into
- // a single packet. Sets the entropy hash of the serialized packet to a
- // random bool.
+ // a single packet.
// Fails if |buffer_len| isn't long enough for the encrypted packet.
void SerializePacket(char* encrypted_buffer, size_t buffer_len);
@@ -304,7 +277,6 @@ class NET_EXPORT_PRIVATE QuicPacketCreator {
DebugDelegate* debug_delegate_;
QuicFramer* framer_;
- QuicRandomBoolSource random_bool_source_;
QuicBufferAllocator* const buffer_allocator_;
// Controls whether version should be included while serializing the packet.
@@ -346,4 +318,4 @@ class NET_EXPORT_PRIVATE QuicPacketCreator {
} // namespace net
-#endif // NET_QUIC_QUIC_PACKET_CREATOR_H_
+#endif // NET_QUIC_CORE_QUIC_PACKET_CREATOR_H_
diff --git a/chromium/net/quic/core/quic_packet_creator_test.cc b/chromium/net/quic/core/quic_packet_creator_test.cc
index 6a31455e76f..18159788573 100644
--- a/chromium/net/quic/core/quic_packet_creator_test.cc
+++ b/chromium/net/quic/core/quic_packet_creator_test.cc
@@ -6,6 +6,7 @@
#include <cstdint>
#include <memory>
+#include <ostream>
#include <string>
#include "base/macros.h"
@@ -13,18 +14,17 @@
#include "net/quic/core/crypto/null_encrypter.h"
#include "net/quic/core/crypto/quic_decrypter.h"
#include "net/quic/core/crypto/quic_encrypter.h"
-#include "net/quic/core/quic_flags.h"
+#include "net/quic/core/quic_pending_retransmission.h"
#include "net/quic/core/quic_simple_buffer_allocator.h"
#include "net/quic/core/quic_utils.h"
-#include "net/quic/test_tools/mock_random.h"
+#include "net/quic/platform/api/quic_socket_address.h"
#include "net/quic/test_tools/quic_framer_peer.h"
#include "net/quic/test_tools/quic_packet_creator_peer.h"
#include "net/quic/test_tools/quic_test_utils.h"
-#include "net/test/gtest_util.h"
#include "testing/gmock/include/gmock/gmock.h"
+#include "testing/gtest/include/gtest/gtest.h"
using base::StringPiece;
-using std::ostream;
using std::string;
using testing::DoAll;
using testing::InSequence;
@@ -46,7 +46,7 @@ struct TestParams {
connection_id_length(length),
version_serialization(version_serialization) {}
- friend ostream& operator<<(ostream& os, const TestParams& p) {
+ friend std::ostream& operator<<(std::ostream& os, const TestParams& p) {
os << "{ client_version: " << QuicVersionToString(p.version)
<< " connection id length: " << p.connection_id_length
<< " include version: " << p.version_serialization << " }";
@@ -90,11 +90,11 @@ class MockDelegate : public QuicPacketCreator::DelegateInterface {
class QuicPacketCreatorTest : public ::testing::TestWithParam<TestParams> {
public:
- void ClearSerializedPacket(SerializedPacket* serialized_packet) {
+ void ClearSerializedPacketForTests(SerializedPacket* serialized_packet) {
if (serialized_packet == nullptr) {
return;
}
- QuicUtils::ClearSerializedPacket(serialized_packet);
+ ClearSerializedPacket(serialized_packet);
}
void SaveSerializedPacket(SerializedPacket* serialized_packet) {
@@ -103,8 +103,7 @@ class QuicPacketCreatorTest : public ::testing::TestWithParam<TestParams> {
}
delete[] serialized_packet_.encrypted_buffer;
serialized_packet_ = *serialized_packet;
- serialized_packet_.encrypted_buffer =
- QuicUtils::CopyBuffer(*serialized_packet);
+ serialized_packet_.encrypted_buffer = CopyBuffer(*serialized_packet);
serialized_packet->retransmittable_frames.clear();
}
@@ -126,16 +125,16 @@ class QuicPacketCreatorTest : public ::testing::TestWithParam<TestParams> {
data_("foo"),
creator_(connection_id_,
&client_framer_,
- &mock_random_,
&buffer_allocator_,
&delegate_),
serialized_packet_(creator_.NoPacket()) {
creator_.set_connection_id_length(GetParam().connection_id_length);
- creator_.SetEncrypter(ENCRYPTION_INITIAL, new NullEncrypter());
- creator_.SetEncrypter(ENCRYPTION_FORWARD_SECURE, new NullEncrypter());
+ creator_.SetEncrypter(ENCRYPTION_INITIAL,
+ new NullEncrypter(Perspective::IS_CLIENT));
+ creator_.SetEncrypter(ENCRYPTION_FORWARD_SECURE,
+ new NullEncrypter(Perspective::IS_CLIENT));
client_framer_.set_visitor(&framer_visitor_);
- client_framer_.set_received_entropy_calculator(&entropy_calculator_);
server_framer_.set_visitor(&framer_visitor_);
}
@@ -195,20 +194,19 @@ class QuicPacketCreatorTest : public ::testing::TestWithParam<TestParams> {
true);
}
- QuicIOVector MakeIOVector(StringPiece s) {
- return ::net::MakeIOVector(s, &iov_);
+ QuicIOVector MakeIOVectorFromStringPiece(StringPiece s) {
+ return MakeIOVector(s, &iov_);
}
- PendingRetransmission CreateRetransmission(
+ QuicPendingRetransmission CreateRetransmission(
const QuicFrames& retransmittable_frames,
bool has_crypto_handshake,
int num_padding_bytes,
EncryptionLevel encryption_level,
QuicPacketNumberLength packet_number_length) {
- return PendingRetransmission(1u, 1u, NOT_RETRANSMISSION,
- retransmittable_frames, has_crypto_handshake,
- num_padding_bytes, encryption_level,
- packet_number_length);
+ return QuicPendingRetransmission(
+ 1u, NOT_RETRANSMISSION, retransmittable_frames, has_crypto_handshake,
+ num_padding_bytes, encryption_level, packet_number_length);
}
static const QuicStreamOffset kOffset = 1u;
@@ -223,10 +221,8 @@ class QuicPacketCreatorTest : public ::testing::TestWithParam<TestParams> {
QuicConnectionId connection_id_;
string data_;
struct iovec iov_;
- MockRandom mock_random_;
SimpleBufferAllocator buffer_allocator_;
QuicPacketCreator creator_;
- MockEntropyCalculator entropy_calculator_;
SerializedPacket serialized_packet_;
};
@@ -280,7 +276,7 @@ TEST_P(QuicPacketCreatorTest, ReserializeFramesWithSequenceNumberLength) {
QuicFrames frames;
frames.push_back(QuicFrame(stream_frame));
char buffer[kMaxPacketSize];
- PendingRetransmission retransmission(CreateRetransmission(
+ QuicPendingRetransmission retransmission(CreateRetransmission(
frames, true /* has_crypto_handshake */, -1 /* needs full padding */,
ENCRYPTION_NONE, PACKET_1BYTE_PACKET_NUMBER));
EXPECT_CALL(delegate_, OnSerializedPacket(_))
@@ -315,7 +311,7 @@ TEST_P(QuicPacketCreatorTest, ReserializeCryptoFrameWithForwardSecurity) {
frames.push_back(QuicFrame(stream_frame));
creator_.set_encryption_level(ENCRYPTION_FORWARD_SECURE);
char buffer[kMaxPacketSize];
- PendingRetransmission retransmission(CreateRetransmission(
+ QuicPendingRetransmission retransmission(CreateRetransmission(
frames, true /* has_crypto_handshake */, -1 /* needs full padding */,
ENCRYPTION_NONE,
QuicPacketCreatorPeer::GetPacketNumberLength(&creator_)));
@@ -333,7 +329,7 @@ TEST_P(QuicPacketCreatorTest, ReserializeFrameWithForwardSecurity) {
frames.push_back(QuicFrame(stream_frame));
creator_.set_encryption_level(ENCRYPTION_FORWARD_SECURE);
char buffer[kMaxPacketSize];
- PendingRetransmission retransmission(CreateRetransmission(
+ QuicPendingRetransmission retransmission(CreateRetransmission(
frames, false /* has_crypto_handshake */, 0 /* no padding */,
ENCRYPTION_NONE,
QuicPacketCreatorPeer::GetPacketNumberLength(&creator_)));
@@ -346,13 +342,14 @@ TEST_P(QuicPacketCreatorTest, ReserializeFrameWithForwardSecurity) {
TEST_P(QuicPacketCreatorTest, ReserializeFramesWithFullPadding) {
QuicFrame frame;
- QuicIOVector io_vector(MakeIOVector("fake handshake message data"));
+ QuicIOVector io_vector(
+ MakeIOVectorFromStringPiece("fake handshake message data"));
QuicPacketCreatorPeer::CreateStreamFrame(&creator_, kCryptoStreamId,
io_vector, 0u, 0u, false, &frame);
QuicFrames frames;
frames.push_back(frame);
char buffer[kMaxPacketSize];
- PendingRetransmission retransmission(CreateRetransmission(
+ QuicPendingRetransmission retransmission(CreateRetransmission(
frames, true /* has_crypto_handshake */, -1 /* needs full padding */,
ENCRYPTION_NONE,
QuicPacketCreatorPeer::GetPacketNumberLength(&creator_)));
@@ -365,7 +362,7 @@ TEST_P(QuicPacketCreatorTest, ReserializeFramesWithFullPadding) {
TEST_P(QuicPacketCreatorTest, ReserializeFramesWithSpecifiedPadding) {
QuicFrame frame;
- QuicIOVector io_vector(MakeIOVector("fake message data"));
+ QuicIOVector io_vector(MakeIOVectorFromStringPiece("fake message data"));
QuicPacketCreatorPeer::CreateStreamFrame(&creator_, kCryptoStreamId,
io_vector, 0u, 0u, false, &frame);
@@ -375,7 +372,7 @@ TEST_P(QuicPacketCreatorTest, ReserializeFramesWithSpecifiedPadding) {
QuicFrames frames;
frames.push_back(frame);
char buffer[kMaxPacketSize];
- PendingRetransmission retransmission(CreateRetransmission(
+ QuicPendingRetransmission retransmission(CreateRetransmission(
frames, false /* has_crypto_handshake */,
kNumPaddingBytes1 /* padding bytes */, ENCRYPTION_NONE,
QuicPacketCreatorPeer::GetPacketNumberLength(&creator_)));
@@ -389,7 +386,7 @@ TEST_P(QuicPacketCreatorTest, ReserializeFramesWithSpecifiedPadding) {
QuicFrames frames;
frames.push_back(frame);
char buffer[kMaxPacketSize];
- PendingRetransmission retransmission(CreateRetransmission(
+ QuicPendingRetransmission retransmission(CreateRetransmission(
frames, false /* has_crypto_handshake */,
kNumPaddingBytes2 /* padding bytes */, ENCRYPTION_NONE,
QuicPacketCreatorPeer::GetPacketNumberLength(&creator_)));
@@ -411,13 +408,13 @@ TEST_P(QuicPacketCreatorTest, ReserializeFramesWithFullPacketAndPadding) {
size_t bytes_free = 0 - delta;
QuicFrame frame;
- QuicIOVector io_vector(MakeIOVector(data));
+ QuicIOVector io_vector(MakeIOVectorFromStringPiece(data));
QuicPacketCreatorPeer::CreateStreamFrame(
&creator_, kCryptoStreamId, io_vector, 0, kOffset, false, &frame);
QuicFrames frames;
frames.push_back(frame);
char buffer[kMaxPacketSize];
- PendingRetransmission retransmission(CreateRetransmission(
+ QuicPendingRetransmission retransmission(CreateRetransmission(
frames, true /* has_crypto_handshake */, -1 /* needs full padding */,
ENCRYPTION_NONE,
QuicPacketCreatorPeer::GetPacketNumberLength(&creator_)));
@@ -466,7 +463,7 @@ TEST_P(QuicPacketCreatorTest, SerializeConnectionClose) {
TEST_P(QuicPacketCreatorTest, ConsumeData) {
QuicFrame frame;
- QuicIOVector io_vector(MakeIOVector("test"));
+ QuicIOVector io_vector(MakeIOVectorFromStringPiece("test"));
ASSERT_TRUE(creator_.ConsumeData(kCryptoStreamId, io_vector, 0u, 0u, false,
false, &frame));
ASSERT_TRUE(frame.stream_frame);
@@ -478,7 +475,7 @@ TEST_P(QuicPacketCreatorTest, ConsumeData) {
TEST_P(QuicPacketCreatorTest, ConsumeDataFin) {
QuicFrame frame;
- QuicIOVector io_vector(MakeIOVector("test"));
+ QuicIOVector io_vector(MakeIOVectorFromStringPiece("test"));
ASSERT_TRUE(creator_.ConsumeData(kCryptoStreamId, io_vector, 0u, 10u, true,
false, &frame));
ASSERT_TRUE(frame.stream_frame);
@@ -511,10 +508,10 @@ TEST_P(QuicPacketCreatorTest, CreateAllFreeBytesForStreamFrames) {
creator_.HasRoomForStreamFrame(kClientDataStreamId1, kOffset));
if (should_have_room) {
QuicFrame frame;
- QuicIOVector io_vector(MakeIOVector("testdata"));
+ QuicIOVector io_vector(MakeIOVectorFromStringPiece("testdata"));
EXPECT_CALL(delegate_, OnSerializedPacket(_))
- .WillRepeatedly(
- Invoke(this, &QuicPacketCreatorTest::ClearSerializedPacket));
+ .WillRepeatedly(Invoke(
+ this, &QuicPacketCreatorTest::ClearSerializedPacketForTests));
ASSERT_TRUE(creator_.ConsumeData(kClientDataStreamId1, io_vector, 0u,
kOffset, false, false, &frame));
ASSERT_TRUE(frame.stream_frame);
@@ -536,7 +533,7 @@ TEST_P(QuicPacketCreatorTest, StreamFrameConsumption) {
string data(capacity + delta, 'A');
size_t bytes_free = delta > 0 ? 0 : 0 - delta;
QuicFrame frame;
- QuicIOVector io_vector(MakeIOVector(data));
+ QuicIOVector io_vector(MakeIOVectorFromStringPiece(data));
ASSERT_TRUE(creator_.ConsumeData(kClientDataStreamId1, io_vector, 0u,
kOffset, false, false, &frame));
ASSERT_TRUE(frame.stream_frame);
@@ -566,7 +563,7 @@ TEST_P(QuicPacketCreatorTest, CryptoStreamFramePacketPadding) {
size_t bytes_free = delta > 0 ? 0 : 0 - delta;
QuicFrame frame;
- QuicIOVector io_vector(MakeIOVector(data));
+ QuicIOVector io_vector(MakeIOVectorFromStringPiece(data));
EXPECT_CALL(delegate_, OnSerializedPacket(_))
.WillRepeatedly(
Invoke(this, &QuicPacketCreatorTest::SaveSerializedPacket));
@@ -603,7 +600,7 @@ TEST_P(QuicPacketCreatorTest, NonCryptoStreamFramePacketNonPadding) {
size_t bytes_free = delta > 0 ? 0 : 0 - delta;
QuicFrame frame;
- QuicIOVector io_vector(MakeIOVector(data));
+ QuicIOVector io_vector(MakeIOVectorFromStringPiece(data));
EXPECT_CALL(delegate_, OnSerializedPacket(_))
.WillOnce(Invoke(this, &QuicPacketCreatorTest::SaveSerializedPacket));
ASSERT_TRUE(creator_.ConsumeData(kClientDataStreamId1, io_vector, 0u,
@@ -729,7 +726,7 @@ TEST_P(QuicPacketCreatorTest, ConsumeDataLargerThanOneStreamFrame) {
PACKET_1BYTE_PACKET_NUMBER, &payload_length));
QuicFrame frame;
const string too_long_payload(payload_length * 2, 'a');
- QuicIOVector io_vector(MakeIOVector(too_long_payload));
+ QuicIOVector io_vector(MakeIOVectorFromStringPiece(too_long_payload));
EXPECT_CALL(delegate_, OnSerializedPacket(_))
.WillOnce(Invoke(this, &QuicPacketCreatorTest::SaveSerializedPacket));
ASSERT_TRUE(creator_.ConsumeData(kCryptoStreamId, io_vector, 0u, 0u, true,
@@ -764,7 +761,7 @@ TEST_P(QuicPacketCreatorTest, AddFrameAndFlush) {
EXPECT_TRUE(creator_.HasPendingFrames());
QuicFrame frame;
- QuicIOVector io_vector(MakeIOVector("test"));
+ QuicIOVector io_vector(MakeIOVectorFromStringPiece("test"));
ASSERT_TRUE(creator_.ConsumeData(kCryptoStreamId, io_vector, 0u, 0u, false,
false, &frame));
ASSERT_TRUE(frame.stream_frame);
@@ -807,13 +804,13 @@ TEST_P(QuicPacketCreatorTest, SerializeAndSendStreamFrame) {
}
EXPECT_FALSE(creator_.HasPendingFrames());
- QuicIOVector iov(MakeIOVector("test"));
+ QuicIOVector iov(MakeIOVectorFromStringPiece("test"));
EXPECT_CALL(delegate_, OnSerializedPacket(_))
.WillOnce(Invoke(this, &QuicPacketCreatorTest::SaveSerializedPacket));
size_t num_bytes_consumed;
creator_.CreateAndSerializeStreamFrame(kHeadersStreamId, iov, 0, 0, true,
nullptr, &num_bytes_consumed);
- EXPECT_EQ(static_cast<size_t>(4), num_bytes_consumed);
+ EXPECT_EQ(4u, num_bytes_consumed);
// Ensure the packet is successfully created.
ASSERT_TRUE(serialized_packet_.encrypted_buffer);
@@ -827,117 +824,6 @@ TEST_P(QuicPacketCreatorTest, SerializeAndSendStreamFrame) {
EXPECT_FALSE(creator_.HasPendingFrames());
}
-TEST_P(QuicPacketCreatorTest, SerializeTruncatedAckFrameWithLargePacketSize) {
- creator_.set_encryption_level(ENCRYPTION_FORWARD_SECURE);
- if (!GetParam().version_serialization) {
- creator_.StopSendingVersion();
- }
- creator_.SetMaxPacketLength(kMaxPacketSize);
-
- // Serialized length of ack frame with 2000 nack ranges should be limited by
- // the number of nack ranges that can be fit in an ack frame.
- QuicAckFrame ack_frame = MakeAckFrameWithNackRanges(2000u, 0u);
- size_t frame_len = client_framer_.GetSerializedFrameLength(
- QuicFrame(&ack_frame), creator_.BytesFree(), true, true,
- PACKET_1BYTE_PACKET_NUMBER);
- EXPECT_GT(creator_.BytesFree(), frame_len);
- EXPECT_GT(creator_.max_packet_length(), creator_.PacketSize());
-
- // Add ack frame to creator.
- EXPECT_TRUE(creator_.AddSavedFrame(QuicFrame(&ack_frame)));
- EXPECT_TRUE(creator_.HasPendingFrames());
- EXPECT_GT(creator_.max_packet_length(), creator_.PacketSize());
- EXPECT_LT(0u, creator_.BytesFree());
-
- // Make sure that an additional stream frame can be added to the packet.
- QuicFrame frame;
- QuicIOVector io_vector(MakeIOVector("test"));
- ASSERT_TRUE(
- creator_.ConsumeData(2u, io_vector, 0u, 0u, false, false, &frame));
- ASSERT_TRUE(frame.stream_frame);
- size_t consumed = frame.stream_frame->data_length;
- EXPECT_EQ(4u, consumed);
- EXPECT_TRUE(creator_.HasPendingFrames());
-
- // Ensure the packet is successfully created, and the packet size estimate
- // matches the serialized packet length.
- if (GetParam().version <= QUIC_VERSION_33) {
- EXPECT_CALL(entropy_calculator_, EntropyHash(_))
- .WillOnce(testing::Return(0));
- }
- EXPECT_CALL(delegate_, OnSerializedPacket(_))
- .WillOnce(Invoke(this, &QuicPacketCreatorTest::SaveSerializedPacket));
- size_t est_packet_size = creator_.PacketSize();
- creator_.Flush();
- ASSERT_TRUE(serialized_packet_.encrypted_buffer);
- EXPECT_EQ(est_packet_size, client_framer_.GetMaxPlaintextSize(
- serialized_packet_.encrypted_length));
- DeleteSerializedPacket();
-}
-
-TEST_P(QuicPacketCreatorTest, SerializeTruncatedAckFrameWithSmallPacketSize) {
- if (!GetParam().version_serialization) {
- creator_.StopSendingVersion();
- }
- creator_.SetMaxPacketLength(500u);
-
- const size_t max_plaintext_size =
- client_framer_.GetMaxPlaintextSize(creator_.max_packet_length());
- EXPECT_EQ(max_plaintext_size - creator_.PacketSize(), creator_.BytesFree());
-
- // Serialized length of ack frame with 2000 nack ranges should be limited by
- // the packet size.
- QuicAckFrame ack_frame = MakeAckFrameWithNackRanges(2000u, 0u);
- size_t frame_len = client_framer_.GetSerializedFrameLength(
- QuicFrame(&ack_frame), creator_.BytesFree(), true, true,
- PACKET_1BYTE_PACKET_NUMBER);
- EXPECT_EQ(creator_.BytesFree(), frame_len);
-
- // Add ack frame to creator.
- EXPECT_TRUE(creator_.AddSavedFrame(QuicFrame(&ack_frame)));
- EXPECT_TRUE(creator_.HasPendingFrames());
- EXPECT_EQ(client_framer_.GetMaxPlaintextSize(creator_.max_packet_length()),
- creator_.PacketSize());
- EXPECT_EQ(0u, creator_.BytesFree());
-
- // Ensure the packet is successfully created, and the packet size estimate
- // may not match the serialized packet length.
- if (GetParam().version <= QUIC_VERSION_33) {
- EXPECT_CALL(entropy_calculator_, EntropyHash(_)).WillOnce(Return(0));
- }
- size_t est_packet_size = creator_.PacketSize();
- EXPECT_CALL(delegate_, OnSerializedPacket(_))
- .WillOnce(Invoke(this, &QuicPacketCreatorTest::SaveSerializedPacket));
- creator_.Flush();
- ASSERT_TRUE(serialized_packet_.encrypted_buffer);
- EXPECT_GE(est_packet_size, client_framer_.GetMaxPlaintextSize(
- serialized_packet_.encrypted_length));
- DeleteSerializedPacket();
-}
-
-TEST_P(QuicPacketCreatorTest, EntropyFlag) {
- frames_.push_back(QuicFrame(
- new QuicStreamFrame(kCryptoStreamId, false, 0u, StringPiece())));
-
- for (int i = 0; i < 2; ++i) {
- for (int j = 0; j < 64; ++j) {
- SerializedPacket serialized = SerializeAllFrames(frames_);
- // Verify both BoolSource and hash algorithm.
- bool expected_rand_bool =
- (mock_random_.RandUint64() & (UINT64_C(1) << j)) != 0;
- bool observed_rand_bool =
- (serialized.entropy_hash & (1 << ((j + 1) % 8))) != 0;
- uint8_t rest_of_hash = serialized.entropy_hash & ~(1 << ((j + 1) % 8));
- EXPECT_EQ(expected_rand_bool, observed_rand_bool);
- EXPECT_EQ(0, rest_of_hash);
- }
- // After 64 calls, BoolSource will refresh the bucket - make sure it does.
- mock_random_.ChangeValue();
- }
-
- delete frames_[0].stream_frame;
-}
-
TEST_P(QuicPacketCreatorTest, SetCurrentPath) {
// Current path is the default path.
EXPECT_EQ(kDefaultPathId, QuicPacketCreatorPeer::GetCurrentPath(&creator_));
@@ -946,7 +832,7 @@ TEST_P(QuicPacketCreatorTest, SetCurrentPath) {
QuicPacketCreatorPeer::GetPacketNumberLength(&creator_));
// Add a stream frame to the creator.
QuicFrame frame;
- QuicIOVector io_vector(MakeIOVector("test"));
+ QuicIOVector io_vector(MakeIOVectorFromStringPiece("test"));
ASSERT_TRUE(creator_.ConsumeData(kCryptoStreamId, io_vector, 0u, 0u, false,
false, &frame));
ASSERT_TRUE(frame.stream_frame);
@@ -962,7 +848,7 @@ TEST_P(QuicPacketCreatorTest, SetCurrentPath) {
EXPECT_CALL(delegate_, OnSerializedPacket(_))
.Times(1)
.WillRepeatedly(
- Invoke(this, &QuicPacketCreatorTest::ClearSerializedPacket));
+ Invoke(this, &QuicPacketCreatorTest::ClearSerializedPacketForTests));
creator_.Flush();
EXPECT_FALSE(creator_.HasPendingFrames());
creator_.SetCurrentPath(kPathId1, 1, 0);
@@ -1001,7 +887,7 @@ TEST_P(QuicPacketCreatorTest, SerializePacketOnDifferentPath) {
EXPECT_EQ(0u, creator_.packet_number());
// Add a stream frame to the creator and flush the packet.
QuicFrame frame;
- QuicIOVector io_vector(MakeIOVector("test"));
+ QuicIOVector io_vector(MakeIOVectorFromStringPiece("test"));
ASSERT_TRUE(creator_.ConsumeData(kCryptoStreamId, io_vector, 0u, 0u, false,
false, &frame));
ASSERT_TRUE(frame.stream_frame);
@@ -1059,7 +945,7 @@ TEST_P(QuicPacketCreatorTest, ChloTooLarge) {
message_data.reset(framer.ConstructHandshakeMessage(message));
struct iovec iov;
- QuicIOVector data_iovec(::net::MakeIOVector(
+ QuicIOVector data_iovec(MakeIOVector(
StringPiece(message_data->data(), message_data->length()), &iov));
QuicFrame frame;
EXPECT_CALL(delegate_,
diff --git a/chromium/net/quic/core/quic_packet_generator.cc b/chromium/net/quic/core/quic_packet_generator.cc
index 4c338c89c17..3d86874fc44 100644
--- a/chromium/net/quic/core/quic_packet_generator.cc
+++ b/chromium/net/quic/core/quic_packet_generator.cc
@@ -4,10 +4,11 @@
#include "net/quic/core/quic_packet_generator.h"
-#include "base/logging.h"
-#include "net/quic/core/quic_bug_tracker.h"
-#include "net/quic/core/quic_flags.h"
+#include <cstdint>
+
#include "net/quic/core/quic_utils.h"
+#include "net/quic/platform/api/quic_bug_tracker.h"
+#include "net/quic/platform/api/quic_logging.h"
using base::StringPiece;
@@ -15,21 +16,16 @@ namespace net {
QuicPacketGenerator::QuicPacketGenerator(QuicConnectionId connection_id,
QuicFramer* framer,
- QuicRandom* random_generator,
QuicBufferAllocator* buffer_allocator,
DelegateInterface* delegate)
: delegate_(delegate),
- packet_creator_(connection_id,
- framer,
- random_generator,
- buffer_allocator,
- delegate),
+ packet_creator_(connection_id, framer, buffer_allocator, delegate),
batch_mode_(false),
should_send_ack_(false),
should_send_stop_waiting_(false) {}
QuicPacketGenerator::~QuicPacketGenerator() {
- QuicUtils::DeleteFrames(&queued_control_frames_);
+ DeleteFrames(&queued_control_frames_);
}
void QuicPacketGenerator::SetShouldSendAck(bool also_send_stop_waiting) {
@@ -58,7 +54,7 @@ QuicConsumedData QuicPacketGenerator::ConsumeData(
QuicIOVector iov,
QuicStreamOffset offset,
bool fin,
- QuicAckListenerInterface* listener) {
+ QuicReferenceCountedPointer<QuicAckListenerInterface> ack_listener) {
bool has_handshake = (id == kCryptoStreamId);
QUIC_BUG_IF(has_handshake && fin)
<< "Handshake packets should never send a fin";
@@ -94,8 +90,8 @@ QuicConsumedData QuicPacketGenerator::ConsumeData(
// A stream frame is created and added.
size_t bytes_consumed = frame.stream_frame->data_length;
- if (listener != nullptr) {
- packet_creator_.AddAckListener(listener, bytes_consumed);
+ if (ack_listener != nullptr) {
+ packet_creator_.AddAckListener(ack_listener, bytes_consumed);
}
total_bytes_consumed += bytes_consumed;
fin_consumed = fin && total_bytes_consumed == iov.total_length;
@@ -130,7 +126,7 @@ QuicConsumedData QuicPacketGenerator::ConsumeDataFastPath(
const QuicIOVector& iov,
QuicStreamOffset offset,
bool fin,
- QuicAckListenerInterface* listener) {
+ QuicReferenceCountedPointer<QuicAckListenerInterface> ack_listener) {
DCHECK_NE(id, kCryptoStreamId);
size_t total_bytes_consumed = 0;
while (total_bytes_consumed < iov.total_length &&
@@ -140,7 +136,7 @@ QuicConsumedData QuicPacketGenerator::ConsumeDataFastPath(
size_t bytes_consumed = 0;
packet_creator_.CreateAndSerializeStreamFrame(
id, iov, total_bytes_consumed, offset + total_bytes_consumed, fin,
- listener, &bytes_consumed);
+ ack_listener, &bytes_consumed);
total_bytes_consumed += bytes_consumed;
}
@@ -150,7 +146,7 @@ QuicConsumedData QuicPacketGenerator::ConsumeDataFastPath(
void QuicPacketGenerator::GenerateMtuDiscoveryPacket(
QuicByteCount target_mtu,
- QuicAckListenerInterface* listener) {
+ QuicReferenceCountedPointer<QuicAckListenerInterface> ack_listener) {
// MTU discovery frames must be sent by themselves.
if (!packet_creator_.CanSetMaxPacketLength()) {
QUIC_BUG << "MTU discovery packets should only be sent when no other "
@@ -167,8 +163,8 @@ void QuicPacketGenerator::GenerateMtuDiscoveryPacket(
// Send the probe packet with the new length.
SetMaxPacketLength(target_mtu);
const bool success = packet_creator_.AddPaddedSavedFrame(frame);
- if (listener != nullptr) {
- packet_creator_.AddAckListener(listener, 0);
+ if (ack_listener != nullptr) {
+ packet_creator_.AddAckListener(std::move(ack_listener), 0);
}
packet_creator_.Flush();
// The only reason AddFrame can fail is that the packet is too full to fit in
@@ -204,7 +200,7 @@ void QuicPacketGenerator::SendQueuedFrames(bool flush) {
<< " number of queued_control_frames: "
<< queued_control_frames_.size();
if (!queued_control_frames_.empty()) {
- DVLOG(1) << queued_control_frames_[0];
+ QUIC_LOG(INFO) << queued_control_frames_[0];
}
delegate_->OnUnrecoverableError(QUIC_FAILED_TO_SERIALIZE_PACKET,
"Single frame cannot fit into a packet",
@@ -303,7 +299,7 @@ QuicPacketGenerator::SerializeVersionNegotiationPacket(
}
void QuicPacketGenerator::ReserializeAllFrames(
- const PendingRetransmission& retransmission,
+ const QuicPendingRetransmission& retransmission,
char* buffer,
size_t buffer_len) {
packet_creator_.ReserializeAllFrames(retransmission, buffer, buffer_len);
diff --git a/chromium/net/quic/core/quic_packet_generator.h b/chromium/net/quic/core/quic_packet_generator.h
index d9ee405f492..0ae2e9e4712 100644
--- a/chromium/net/quic/core/quic_packet_generator.h
+++ b/chromium/net/quic/core/quic_packet_generator.h
@@ -37,19 +37,19 @@
// mode is ended via |FinishBatchOperations|, the current packet
// will be serialzied, even if it is not full.
-#ifndef NET_QUIC_QUIC_PACKET_GENERATOR_H_
-#define NET_QUIC_QUIC_PACKET_GENERATOR_H_
-
-#include <stddef.h>
-#include <stdint.h>
+#ifndef NET_QUIC_CORE_QUIC_PACKET_GENERATOR_H_
+#define NET_QUIC_CORE_QUIC_PACKET_GENERATOR_H_
+#include <cstddef>
+#include <cstdint>
#include <list>
#include "base/macros.h"
-#include "net/base/net_export.h"
#include "net/quic/core/quic_packet_creator.h"
+#include "net/quic/core/quic_pending_retransmission.h"
#include "net/quic/core/quic_sent_packet_manager.h"
#include "net/quic/core/quic_types.h"
+#include "net/quic/platform/api/quic_export.h"
namespace net {
@@ -57,9 +57,9 @@ namespace test {
class QuicPacketGeneratorPeer;
} // namespace test
-class NET_EXPORT_PRIVATE QuicPacketGenerator {
+class QUIC_EXPORT_PRIVATE QuicPacketGenerator {
public:
- class NET_EXPORT_PRIVATE DelegateInterface
+ class QUIC_EXPORT_PRIVATE DelegateInterface
: public QuicPacketCreator::DelegateInterface {
public:
~DelegateInterface() override {}
@@ -73,7 +73,6 @@ class NET_EXPORT_PRIVATE QuicPacketGenerator {
QuicPacketGenerator(QuicConnectionId connection_id,
QuicFramer* framer,
- QuicRandom* random_generator,
QuicBufferAllocator* buffer_allocator,
DelegateInterface* delegate);
@@ -93,24 +92,27 @@ class NET_EXPORT_PRIVATE QuicPacketGenerator {
// mode, these packets will also be sent during this call.
// |delegate| (if not nullptr) will be informed once all packets sent as a
// result of this call are ACKed by the peer.
- QuicConsumedData ConsumeData(QuicStreamId id,
- QuicIOVector iov,
- QuicStreamOffset offset,
- bool fin,
- QuicAckListenerInterface* listener);
+ QuicConsumedData ConsumeData(
+ QuicStreamId id,
+ QuicIOVector iov,
+ QuicStreamOffset offset,
+ bool fin,
+ QuicReferenceCountedPointer<QuicAckListenerInterface> ack_listener);
// Sends as many data only packets as allowed by the send algorithm and the
// available iov.
// This path does not support FEC, padding, or bundling pending frames.
- QuicConsumedData ConsumeDataFastPath(QuicStreamId id,
- const QuicIOVector& iov,
- QuicStreamOffset offset,
- bool fin,
- QuicAckListenerInterface* listener);
+ QuicConsumedData ConsumeDataFastPath(
+ QuicStreamId id,
+ const QuicIOVector& iov,
+ QuicStreamOffset offset,
+ bool fin,
+ QuicReferenceCountedPointer<QuicAckListenerInterface> ack_listener);
// Generates an MTU discovery packet of specified size.
- void GenerateMtuDiscoveryPacket(QuicByteCount target_mtu,
- QuicAckListenerInterface* listener);
+ void GenerateMtuDiscoveryPacket(
+ QuicByteCount target_mtu,
+ QuicReferenceCountedPointer<QuicAckListenerInterface> ack_listener);
// Indicates whether batch mode is currently enabled.
bool InBatchMode();
@@ -136,14 +138,12 @@ class NET_EXPORT_PRIVATE QuicPacketGenerator {
void SetDiversificationNonce(const DiversificationNonce& nonce);
// Creates a version negotiation packet which supports |supported_versions|.
- // Also, sets the entropy hash of the serialized packet to a random bool and
- // returns that value as a member of SerializedPacket.
std::unique_ptr<QuicEncryptedPacket> SerializeVersionNegotiationPacket(
const QuicVersionVector& supported_versions);
// Re-serializes frames with the original packet's packet number length.
// Used for retransmitting packets to ensure they aren't too long.
- void ReserializeAllFrames(const PendingRetransmission& retransmission,
+ void ReserializeAllFrames(const QuicPendingRetransmission& retransmission,
char* buffer,
size_t buffer_len);
@@ -219,4 +219,4 @@ class NET_EXPORT_PRIVATE QuicPacketGenerator {
} // namespace net
-#endif // NET_QUIC_QUIC_PACKET_GENERATOR_H_
+#endif // NET_QUIC_CORE_QUIC_PACKET_GENERATOR_H_
diff --git a/chromium/net/quic/core/quic_packet_generator_test.cc b/chromium/net/quic/core/quic_packet_generator_test.cc
index b6d6d043077..4486fc51de1 100644
--- a/chromium/net/quic/core/quic_packet_generator_test.cc
+++ b/chromium/net/quic/core/quic_packet_generator_test.cc
@@ -9,18 +9,18 @@
#include <string>
#include "base/macros.h"
+#include "base/stl_util.h"
#include "net/quic/core/crypto/crypto_protocol.h"
#include "net/quic/core/crypto/null_encrypter.h"
#include "net/quic/core/crypto/quic_decrypter.h"
#include "net/quic/core/crypto/quic_encrypter.h"
-#include "net/quic/core/quic_flags.h"
#include "net/quic/core/quic_simple_buffer_allocator.h"
#include "net/quic/core/quic_utils.h"
+#include "net/quic/platform/api/quic_socket_address.h"
#include "net/quic/test_tools/quic_packet_creator_peer.h"
#include "net/quic/test_tools/quic_packet_generator_peer.h"
#include "net/quic/test_tools/quic_test_utils.h"
#include "net/quic/test_tools/simple_quic_framer.h"
-#include "net/test/gtest_util.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
@@ -106,21 +106,22 @@ class QuicPacketGeneratorTest : public ::testing::Test {
: framer_(AllSupportedVersions(),
QuicTime::Zero(),
Perspective::IS_CLIENT),
- generator_(42, &framer_, &random_, &buffer_allocator_, &delegate_),
+ generator_(42, &framer_, &buffer_allocator_, &delegate_),
creator_(QuicPacketGeneratorPeer::GetPacketCreator(&generator_)) {
- creator_->SetEncrypter(ENCRYPTION_FORWARD_SECURE, new NullEncrypter());
+ creator_->SetEncrypter(ENCRYPTION_FORWARD_SECURE,
+ new NullEncrypter(Perspective::IS_CLIENT));
creator_->set_encryption_level(ENCRYPTION_FORWARD_SECURE);
}
~QuicPacketGeneratorTest() override {
for (SerializedPacket& packet : packets_) {
delete[] packet.encrypted_buffer;
- QuicUtils::ClearSerializedPacket(&packet);
+ ClearSerializedPacket(&packet);
}
}
void SavePacket(SerializedPacket* packet) {
- packet->encrypted_buffer = QuicUtils::CopyBuffer(*packet);
+ packet->encrypted_buffer = CopyBuffer(*packet);
packets_.push_back(*packet);
packet->encrypted_buffer = nullptr;
packet->retransmittable_frames.clear();
@@ -202,12 +203,11 @@ class QuicPacketGeneratorTest : public ::testing::Test {
return QuicIOVector(&iov_, 1, len);
}
- QuicIOVector MakeIOVector(StringPiece s) {
- return ::net::MakeIOVector(s, &iov_);
+ QuicIOVector MakeIOVectorFromStringPiece(StringPiece s) {
+ return MakeIOVector(s, &iov_);
}
QuicFramer framer_;
- MockRandom random_;
SimpleBufferAllocator buffer_allocator_;
StrictMock<MockDelegate> delegate_;
QuicPacketGenerator generator_;
@@ -343,7 +343,7 @@ TEST_F(QuicPacketGeneratorTest, ConsumeData_NotWritable) {
delegate_.SetCanNotWrite();
QuicConsumedData consumed = generator_.ConsumeData(
- kHeadersStreamId, MakeIOVector("foo"), 2, true, nullptr);
+ kHeadersStreamId, MakeIOVectorFromStringPiece("foo"), 2, true, nullptr);
EXPECT_EQ(0u, consumed.bytes_consumed);
EXPECT_FALSE(consumed.fin_consumed);
EXPECT_FALSE(generator_.HasQueuedFrames());
@@ -354,7 +354,7 @@ TEST_F(QuicPacketGeneratorTest, ConsumeData_WritableAndShouldNotFlush) {
generator_.StartBatchOperations();
QuicConsumedData consumed = generator_.ConsumeData(
- kHeadersStreamId, MakeIOVector("foo"), 2, true, nullptr);
+ kHeadersStreamId, MakeIOVectorFromStringPiece("foo"), 2, true, nullptr);
EXPECT_EQ(3u, consumed.bytes_consumed);
EXPECT_TRUE(consumed.fin_consumed);
EXPECT_TRUE(generator_.HasQueuedFrames());
@@ -366,7 +366,7 @@ TEST_F(QuicPacketGeneratorTest, ConsumeData_WritableAndShouldFlush) {
EXPECT_CALL(delegate_, OnSerializedPacket(_))
.WillOnce(Invoke(this, &QuicPacketGeneratorTest::SavePacket));
QuicConsumedData consumed = generator_.ConsumeData(
- kHeadersStreamId, MakeIOVector("foo"), 2, true, nullptr);
+ kHeadersStreamId, MakeIOVectorFromStringPiece("foo"), 2, true, nullptr);
EXPECT_EQ(3u, consumed.bytes_consumed);
EXPECT_TRUE(consumed.fin_consumed);
EXPECT_FALSE(generator_.HasQueuedFrames());
@@ -386,7 +386,7 @@ TEST_F(QuicPacketGeneratorTest, ConsumeData_Handshake) {
EXPECT_CALL(delegate_, OnSerializedPacket(_))
.WillOnce(Invoke(this, &QuicPacketGeneratorTest::SavePacket));
QuicConsumedData consumed = generator_.ConsumeData(
- kCryptoStreamId, MakeIOVector("foo"), 0, false, nullptr);
+ kCryptoStreamId, MakeIOVectorFromStringPiece("foo"), 0, false, nullptr);
EXPECT_EQ(3u, consumed.bytes_consumed);
EXPECT_FALSE(generator_.HasQueuedFrames());
@@ -400,9 +400,10 @@ TEST_F(QuicPacketGeneratorTest, ConsumeData_Handshake) {
}
TEST_F(QuicPacketGeneratorTest, ConsumeData_EmptyData) {
- EXPECT_QUIC_BUG(generator_.ConsumeData(kHeadersStreamId, MakeIOVector(""), 0,
- false, nullptr),
- "Attempt to consume empty data without FIN.");
+ EXPECT_QUIC_BUG(
+ generator_.ConsumeData(kHeadersStreamId, MakeIOVectorFromStringPiece(""),
+ 0, false, nullptr),
+ "Attempt to consume empty data without FIN.");
}
TEST_F(QuicPacketGeneratorTest,
@@ -410,10 +411,10 @@ TEST_F(QuicPacketGeneratorTest,
delegate_.SetCanWriteAnything();
generator_.StartBatchOperations();
- generator_.ConsumeData(kHeadersStreamId, MakeIOVector("foo"), 2, true,
- nullptr);
- QuicConsumedData consumed =
- generator_.ConsumeData(3, MakeIOVector("quux"), 7, false, nullptr);
+ generator_.ConsumeData(kHeadersStreamId, MakeIOVectorFromStringPiece("foo"),
+ 2, true, nullptr);
+ QuicConsumedData consumed = generator_.ConsumeData(
+ 3, MakeIOVectorFromStringPiece("quux"), 7, false, nullptr);
EXPECT_EQ(4u, consumed.bytes_consumed);
EXPECT_FALSE(consumed.fin_consumed);
EXPECT_TRUE(generator_.HasQueuedFrames());
@@ -423,10 +424,10 @@ TEST_F(QuicPacketGeneratorTest, ConsumeData_BatchOperations) {
delegate_.SetCanWriteAnything();
generator_.StartBatchOperations();
- generator_.ConsumeData(kHeadersStreamId, MakeIOVector("foo"), 2, true,
- nullptr);
- QuicConsumedData consumed =
- generator_.ConsumeData(3, MakeIOVector("quux"), 7, false, nullptr);
+ generator_.ConsumeData(kHeadersStreamId, MakeIOVectorFromStringPiece("foo"),
+ 2, true, nullptr);
+ QuicConsumedData consumed = generator_.ConsumeData(
+ 3, MakeIOVectorFromStringPiece("quux"), 7, false, nullptr);
EXPECT_EQ(4u, consumed.bytes_consumed);
EXPECT_FALSE(consumed.fin_consumed);
EXPECT_TRUE(generator_.HasQueuedFrames());
@@ -446,7 +447,7 @@ TEST_F(QuicPacketGeneratorTest, ConsumeData_FramesPreviouslyQueued) {
// Set the packet size be enough for two stream frames with 0 stream offset,
// but not enough for a stream frame of 0 offset and one with non-zero offset.
size_t length =
- NullEncrypter().GetCiphertextSize(0) +
+ NullEncrypter(Perspective::IS_CLIENT).GetCiphertextSize(0) +
GetPacketHeaderSize(
framer_.version(), creator_->connection_id_length(), kIncludeVersion,
!kIncludePathId, !kIncludeDiversificationNonce,
@@ -468,15 +469,15 @@ TEST_F(QuicPacketGeneratorTest, ConsumeData_FramesPreviouslyQueued) {
// Queue enough data to prevent a stream frame with a non-zero offset from
// fitting.
QuicConsumedData consumed = generator_.ConsumeData(
- kHeadersStreamId, MakeIOVector("foo"), 0, false, nullptr);
+ kHeadersStreamId, MakeIOVectorFromStringPiece("foo"), 0, false, nullptr);
EXPECT_EQ(3u, consumed.bytes_consumed);
EXPECT_FALSE(consumed.fin_consumed);
EXPECT_TRUE(generator_.HasQueuedFrames());
// This frame will not fit with the existing frame, causing the queued frame
// to be serialized, and it will be added to a new open packet.
- consumed = generator_.ConsumeData(kHeadersStreamId, MakeIOVector("bar"), 3,
- true, nullptr);
+ consumed = generator_.ConsumeData(
+ kHeadersStreamId, MakeIOVectorFromStringPiece("bar"), 3, true, nullptr);
EXPECT_EQ(3u, consumed.bytes_consumed);
EXPECT_TRUE(consumed.fin_consumed);
EXPECT_TRUE(generator_.HasQueuedFrames());
@@ -524,7 +525,8 @@ TEST_F(QuicPacketGeneratorTest, NotWritableThenBatchOperations) {
.WillOnce(Return(QuicFrame(&ack_frame_)));
// Send some data and a control frame
- generator_.ConsumeData(3, MakeIOVector("quux"), 7, false, nullptr);
+ generator_.ConsumeData(3, MakeIOVectorFromStringPiece("quux"), 7, false,
+ nullptr);
generator_.AddControlFrame(QuicFrame(CreateGoAwayFrame()));
// All five frames will be flushed out in a single packet.
@@ -851,7 +853,7 @@ TEST_F(QuicPacketGeneratorTest, SetCurrentPath) {
generator_.StartBatchOperations();
QuicConsumedData consumed = generator_.ConsumeData(
- kHeadersStreamId, MakeIOVector("foo"), 2, true, nullptr);
+ kHeadersStreamId, MakeIOVectorFromStringPiece("foo"), 2, true, nullptr);
EXPECT_EQ(3u, consumed.bytes_consumed);
EXPECT_TRUE(consumed.fin_consumed);
EXPECT_TRUE(generator_.HasQueuedFrames());
diff --git a/chromium/net/quic/core/quic_packet_writer.h b/chromium/net/quic/core/quic_packet_writer.h
index ea1adf90cc5..5f63a03f5a9 100644
--- a/chromium/net/quic/core/quic_packet_writer.h
+++ b/chromium/net/quic/core/quic_packet_writer.h
@@ -2,21 +2,20 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#ifndef NET_QUIC_QUIC_PACKET_WRITER_H_
-#define NET_QUIC_QUIC_PACKET_WRITER_H_
+#ifndef NET_QUIC_CORE_QUIC_PACKET_WRITER_H_
+#define NET_QUIC_CORE_QUIC_PACKET_WRITER_H_
-#include <stddef.h>
+#include <cstddef>
-#include "net/base/ip_endpoint.h"
-#include "net/base/net_export.h"
-#include "net/quic/core/quic_protocol.h"
+#include "net/quic/core/quic_packets.h"
+#include "net/quic/platform/api/quic_export.h"
+#include "net/quic/platform/api/quic_socket_address.h"
namespace net {
-class IPAddress;
struct WriteResult;
-class NET_EXPORT_PRIVATE PerPacketOptions {
+class QUIC_EXPORT_PRIVATE PerPacketOptions {
public:
PerPacketOptions() = default;
virtual ~PerPacketOptions() {}
@@ -34,7 +33,7 @@ class NET_EXPORT_PRIVATE PerPacketOptions {
// An interface between writers and the entity managing the
// socket (in our case the QuicDispatcher). This allows the Dispatcher to
// control writes, and manage any writers who end up write blocked.
-class NET_EXPORT_PRIVATE QuicPacketWriter {
+class QUIC_EXPORT_PRIVATE QuicPacketWriter {
public:
virtual ~QuicPacketWriter() {}
@@ -46,8 +45,8 @@ class NET_EXPORT_PRIVATE QuicPacketWriter {
// implementation. Options may be ignored, depending on the implementation.
virtual WriteResult WritePacket(const char* buffer,
size_t buf_len,
- const IPAddress& self_address,
- const IPEndPoint& peer_address,
+ const QuicIpAddress& self_address,
+ const QuicSocketAddress& peer_address,
PerPacketOptions* options) = 0;
// Returns true if the writer buffers and subsequently rewrites data
@@ -66,9 +65,9 @@ class NET_EXPORT_PRIVATE QuicPacketWriter {
// writer for the supplied peer address. This size may actually exceed the
// size of a valid QUIC packet.
virtual QuicByteCount GetMaxPacketSize(
- const IPEndPoint& peer_address) const = 0;
+ const QuicSocketAddress& peer_address) const = 0;
};
} // namespace net
-#endif // NET_QUIC_QUIC_PACKET_WRITER_H_
+#endif // NET_QUIC_CORE_QUIC_PACKET_WRITER_H_
diff --git a/chromium/net/quic/core/quic_packets.cc b/chromium/net/quic/core/quic_packets.cc
new file mode 100644
index 00000000000..3d7e24b9f65
--- /dev/null
+++ b/chromium/net/quic/core/quic_packets.cc
@@ -0,0 +1,250 @@
+// Copyright (c) 2012 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.
+
+#include "net/quic/core/quic_packets.h"
+
+#include "net/quic/core/quic_flags.h"
+#include "net/quic/core/quic_utils.h"
+#include "net/quic/core/quic_versions.h"
+#include "net/quic/platform/api/quic_ptr_util.h"
+#include "net/quic/platform/api/quic_str_cat.h"
+#include "net/quic/platform/api/quic_text_utils.h"
+
+using base::StringPiece;
+using std::string;
+
+namespace net {
+
+size_t GetPacketHeaderSize(QuicVersion version,
+ const QuicPacketHeader& header) {
+ return GetPacketHeaderSize(version, header.public_header.connection_id_length,
+ header.public_header.version_flag,
+ header.public_header.multipath_flag,
+ header.public_header.nonce != nullptr,
+ header.public_header.packet_number_length);
+}
+
+size_t GetPacketHeaderSize(QuicVersion version,
+ QuicConnectionIdLength connection_id_length,
+ bool include_version,
+ bool include_path_id,
+ bool include_diversification_nonce,
+ QuicPacketNumberLength packet_number_length) {
+ return kPublicFlagsSize + connection_id_length +
+ (include_version ? kQuicVersionSize : 0) +
+ (include_path_id ? kQuicPathIdSize : 0) + packet_number_length +
+ (include_diversification_nonce ? kDiversificationNonceSize : 0);
+}
+
+size_t GetStartOfEncryptedData(QuicVersion version,
+ const QuicPacketHeader& header) {
+ return GetPacketHeaderSize(version, header);
+}
+
+size_t GetStartOfEncryptedData(QuicVersion version,
+ QuicConnectionIdLength connection_id_length,
+ bool include_version,
+ bool include_path_id,
+ bool include_diversification_nonce,
+ QuicPacketNumberLength packet_number_length) {
+ // Encryption starts before private flags.
+ return GetPacketHeaderSize(version, connection_id_length, include_version,
+ include_path_id, include_diversification_nonce,
+ packet_number_length);
+}
+
+QuicPacketPublicHeader::QuicPacketPublicHeader()
+ : connection_id(0),
+ connection_id_length(PACKET_8BYTE_CONNECTION_ID),
+ multipath_flag(false),
+ reset_flag(false),
+ version_flag(false),
+ packet_number_length(PACKET_6BYTE_PACKET_NUMBER),
+ nonce(nullptr) {}
+
+QuicPacketPublicHeader::QuicPacketPublicHeader(
+ const QuicPacketPublicHeader& other) = default;
+
+QuicPacketPublicHeader::~QuicPacketPublicHeader() {}
+
+QuicPacketHeader::QuicPacketHeader()
+ : packet_number(0), path_id(kDefaultPathId) {}
+
+QuicPacketHeader::QuicPacketHeader(const QuicPacketPublicHeader& header)
+ : public_header(header), packet_number(0), path_id(kDefaultPathId) {}
+
+QuicPacketHeader::QuicPacketHeader(const QuicPacketHeader& other) = default;
+
+QuicPublicResetPacket::QuicPublicResetPacket()
+ : nonce_proof(0), rejected_packet_number(0) {}
+
+QuicPublicResetPacket::QuicPublicResetPacket(
+ const QuicPacketPublicHeader& header)
+ : public_header(header), nonce_proof(0), rejected_packet_number(0) {}
+
+std::ostream& operator<<(std::ostream& os, const QuicPacketHeader& header) {
+ os << "{ connection_id: " << header.public_header.connection_id
+ << ", connection_id_length: " << header.public_header.connection_id_length
+ << ", packet_number_length: " << header.public_header.packet_number_length
+ << ", multipath_flag: " << header.public_header.multipath_flag
+ << ", reset_flag: " << header.public_header.reset_flag
+ << ", version_flag: " << header.public_header.version_flag;
+ if (header.public_header.version_flag) {
+ os << ", version:";
+ for (size_t i = 0; i < header.public_header.versions.size(); ++i) {
+ os << " ";
+ os << QuicVersionToString(header.public_header.versions[i]);
+ }
+ }
+ if (header.public_header.nonce != nullptr) {
+ os << ", diversification_nonce: "
+ << QuicTextUtils::HexEncode(
+ StringPiece(header.public_header.nonce->data(),
+ header.public_header.nonce->size()));
+ }
+ os << ", path_id: " << static_cast<int>(header.path_id)
+ << ", packet_number: " << header.packet_number << " }\n";
+ return os;
+}
+
+QuicData::QuicData(const char* buffer, size_t length)
+ : buffer_(buffer), length_(length), owns_buffer_(false) {}
+
+QuicData::QuicData(const char* buffer, size_t length, bool owns_buffer)
+ : buffer_(buffer), length_(length), owns_buffer_(owns_buffer) {}
+
+QuicData::~QuicData() {
+ if (owns_buffer_) {
+ delete[] const_cast<char*>(buffer_);
+ }
+}
+
+QuicPacket::QuicPacket(char* buffer,
+ size_t length,
+ bool owns_buffer,
+ QuicConnectionIdLength connection_id_length,
+ bool includes_version,
+ bool includes_path_id,
+ bool includes_diversification_nonce,
+ QuicPacketNumberLength packet_number_length)
+ : QuicData(buffer, length, owns_buffer),
+ buffer_(buffer),
+ connection_id_length_(connection_id_length),
+ includes_version_(includes_version),
+ includes_path_id_(includes_path_id),
+ includes_diversification_nonce_(includes_diversification_nonce),
+ packet_number_length_(packet_number_length) {}
+
+QuicEncryptedPacket::QuicEncryptedPacket(const char* buffer, size_t length)
+ : QuicData(buffer, length) {}
+
+QuicEncryptedPacket::QuicEncryptedPacket(const char* buffer,
+ size_t length,
+ bool owns_buffer)
+ : QuicData(buffer, length, owns_buffer) {}
+
+std::unique_ptr<QuicEncryptedPacket> QuicEncryptedPacket::Clone() const {
+ char* buffer = new char[this->length()];
+ memcpy(buffer, this->data(), this->length());
+ return QuicMakeUnique<QuicEncryptedPacket>(buffer, this->length(), true);
+}
+
+std::ostream& operator<<(std::ostream& os, const QuicEncryptedPacket& s) {
+ os << s.length() << "-byte data";
+ return os;
+}
+
+QuicReceivedPacket::QuicReceivedPacket(const char* buffer,
+ size_t length,
+ QuicTime receipt_time)
+ : QuicEncryptedPacket(buffer, length),
+ receipt_time_(receipt_time),
+ ttl_(0) {}
+
+QuicReceivedPacket::QuicReceivedPacket(const char* buffer,
+ size_t length,
+ QuicTime receipt_time,
+ bool owns_buffer)
+ : QuicEncryptedPacket(buffer, length, owns_buffer),
+ receipt_time_(receipt_time),
+ ttl_(0) {}
+
+QuicReceivedPacket::QuicReceivedPacket(const char* buffer,
+ size_t length,
+ QuicTime receipt_time,
+ bool owns_buffer,
+ int ttl,
+ bool ttl_valid)
+ : QuicEncryptedPacket(buffer, length, owns_buffer),
+ receipt_time_(receipt_time),
+ ttl_(ttl_valid ? ttl : -1) {}
+
+std::unique_ptr<QuicReceivedPacket> QuicReceivedPacket::Clone() const {
+ char* buffer = new char[this->length()];
+ memcpy(buffer, this->data(), this->length());
+ return QuicMakeUnique<QuicReceivedPacket>(
+ buffer, this->length(), receipt_time(), true, ttl(), ttl() >= 0);
+}
+
+std::ostream& operator<<(std::ostream& os, const QuicReceivedPacket& s) {
+ os << s.length() << "-byte data";
+ return os;
+}
+
+StringPiece QuicPacket::AssociatedData(QuicVersion version) const {
+ return StringPiece(
+ data(), GetStartOfEncryptedData(version, connection_id_length_,
+ includes_version_, includes_path_id_,
+ includes_diversification_nonce_,
+ packet_number_length_));
+}
+
+StringPiece QuicPacket::Plaintext(QuicVersion version) const {
+ const size_t start_of_encrypted_data = GetStartOfEncryptedData(
+ version, connection_id_length_, includes_version_, includes_path_id_,
+ includes_diversification_nonce_, packet_number_length_);
+ return StringPiece(data() + start_of_encrypted_data,
+ length() - start_of_encrypted_data);
+}
+
+SerializedPacket::SerializedPacket(QuicPathId path_id,
+ QuicPacketNumber packet_number,
+ QuicPacketNumberLength packet_number_length,
+ const char* encrypted_buffer,
+ QuicPacketLength encrypted_length,
+ bool has_ack,
+ bool has_stop_waiting)
+ : encrypted_buffer(encrypted_buffer),
+ encrypted_length(encrypted_length),
+ has_crypto_handshake(NOT_HANDSHAKE),
+ num_padding_bytes(0),
+ path_id(path_id),
+ packet_number(packet_number),
+ packet_number_length(packet_number_length),
+ encryption_level(ENCRYPTION_NONE),
+ has_ack(has_ack),
+ has_stop_waiting(has_stop_waiting),
+ transmission_type(NOT_RETRANSMISSION),
+ original_path_id(kInvalidPathId),
+ original_packet_number(0) {}
+
+SerializedPacket::SerializedPacket(const SerializedPacket& other) = default;
+
+SerializedPacket::~SerializedPacket() {}
+
+void ClearSerializedPacket(SerializedPacket* serialized_packet) {
+ if (!serialized_packet->retransmittable_frames.empty()) {
+ DeleteFrames(&serialized_packet->retransmittable_frames);
+ }
+ serialized_packet->encrypted_buffer = nullptr;
+ serialized_packet->encrypted_length = 0;
+}
+
+char* CopyBuffer(const SerializedPacket& packet) {
+ char* dst_buffer = new char[packet.encrypted_length];
+ memcpy(dst_buffer, packet.encrypted_buffer, packet.encrypted_length);
+ return dst_buffer;
+}
+
+} // namespace net
diff --git a/chromium/net/quic/core/quic_packets.h b/chromium/net/quic/core/quic_packets.h
new file mode 100644
index 00000000000..b620146157c
--- /dev/null
+++ b/chromium/net/quic/core/quic_packets.h
@@ -0,0 +1,262 @@
+// Copyright (c) 2012 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.
+
+#ifndef NET_QUIC_CORE_QUIC_PACKETS_H_
+#define NET_QUIC_CORE_QUIC_PACKETS_H_
+
+#include <cstdint>
+#include <limits>
+#include <list>
+#include <memory>
+#include <ostream>
+#include <string>
+#include <utility>
+#include <vector>
+
+#include "base/macros.h"
+#include "base/strings/string_piece.h"
+#include "net/base/iovec.h"
+#include "net/quic/core/frames/quic_frame.h"
+#include "net/quic/core/quic_ack_listener_interface.h"
+#include "net/quic/core/quic_bandwidth.h"
+#include "net/quic/core/quic_constants.h"
+#include "net/quic/core/quic_error_codes.h"
+#include "net/quic/core/quic_time.h"
+#include "net/quic/core/quic_types.h"
+#include "net/quic/core/quic_versions.h"
+#include "net/quic/platform/api/quic_export.h"
+#include "net/quic/platform/api/quic_socket_address.h"
+
+namespace net {
+
+class QuicPacket;
+struct QuicPacketHeader;
+
+// Size in bytes of the data packet header.
+QUIC_EXPORT_PRIVATE size_t GetPacketHeaderSize(QuicVersion version,
+ const QuicPacketHeader& header);
+
+QUIC_EXPORT_PRIVATE size_t
+GetPacketHeaderSize(QuicVersion version,
+ QuicConnectionIdLength connection_id_length,
+ bool include_version,
+ bool include_path_id,
+ bool include_diversification_nonce,
+ QuicPacketNumberLength packet_number_length);
+
+// Index of the first byte in a QUIC packet of encrypted data.
+QUIC_EXPORT_PRIVATE size_t
+GetStartOfEncryptedData(QuicVersion version, const QuicPacketHeader& header);
+
+QUIC_EXPORT_PRIVATE size_t
+GetStartOfEncryptedData(QuicVersion version,
+ QuicConnectionIdLength connection_id_length,
+ bool include_version,
+ bool include_path_id,
+ bool include_diversification_nonce,
+ QuicPacketNumberLength packet_number_length);
+
+struct QUIC_EXPORT_PRIVATE QuicPacketPublicHeader {
+ QuicPacketPublicHeader();
+ QuicPacketPublicHeader(const QuicPacketPublicHeader& other);
+ ~QuicPacketPublicHeader();
+
+ // Universal header. All QuicPacket headers will have a connection_id and
+ // public flags.
+ QuicConnectionId connection_id;
+ QuicConnectionIdLength connection_id_length;
+ bool multipath_flag;
+ bool reset_flag;
+ bool version_flag;
+ QuicPacketNumberLength packet_number_length;
+ QuicVersionVector versions;
+ // nonce contains an optional, 32-byte nonce value. If not included in the
+ // packet, |nonce| will be empty.
+ DiversificationNonce* nonce;
+};
+
+// Header for Data packets.
+struct QUIC_EXPORT_PRIVATE QuicPacketHeader {
+ QuicPacketHeader();
+ explicit QuicPacketHeader(const QuicPacketPublicHeader& header);
+ QuicPacketHeader(const QuicPacketHeader& other);
+
+ QUIC_EXPORT_PRIVATE friend std::ostream& operator<<(
+ std::ostream& os,
+ const QuicPacketHeader& s);
+
+ QuicPacketPublicHeader public_header;
+ QuicPacketNumber packet_number;
+ QuicPathId path_id;
+};
+
+struct QUIC_EXPORT_PRIVATE QuicPublicResetPacket {
+ QuicPublicResetPacket();
+ explicit QuicPublicResetPacket(const QuicPacketPublicHeader& header);
+
+ QuicPacketPublicHeader public_header;
+ QuicPublicResetNonceProof nonce_proof;
+ // TODO(fayang): remove rejected_packet_number when deprecating
+ // FLAGS_quic_reloadable_flag_quic_remove_packet_number_from_public_reset.
+ QuicPacketNumber rejected_packet_number;
+ QuicSocketAddress client_address;
+};
+
+typedef QuicPacketPublicHeader QuicVersionNegotiationPacket;
+
+class QUIC_EXPORT_PRIVATE QuicData {
+ public:
+ QuicData(const char* buffer, size_t length);
+ QuicData(const char* buffer, size_t length, bool owns_buffer);
+ virtual ~QuicData();
+
+ base::StringPiece AsStringPiece() const {
+ return base::StringPiece(data(), length());
+ }
+
+ const char* data() const { return buffer_; }
+ size_t length() const { return length_; }
+
+ private:
+ const char* buffer_;
+ size_t length_;
+ bool owns_buffer_;
+
+ DISALLOW_COPY_AND_ASSIGN(QuicData);
+};
+
+class QUIC_EXPORT_PRIVATE QuicPacket : public QuicData {
+ public:
+ // TODO(fayang): 4 fields from public header are passed in as arguments.
+ // Consider to add a convenience method which directly accepts the entire
+ // public header.
+ QuicPacket(char* buffer,
+ size_t length,
+ bool owns_buffer,
+ QuicConnectionIdLength connection_id_length,
+ bool includes_version,
+ bool includes_path_id,
+ bool includes_diversification_nonce,
+ QuicPacketNumberLength packet_number_length);
+
+ base::StringPiece AssociatedData(QuicVersion version) const;
+ base::StringPiece Plaintext(QuicVersion version) const;
+
+ char* mutable_data() { return buffer_; }
+
+ private:
+ char* buffer_;
+ const QuicConnectionIdLength connection_id_length_;
+ const bool includes_version_;
+ const bool includes_path_id_;
+ const bool includes_diversification_nonce_;
+ const QuicPacketNumberLength packet_number_length_;
+
+ DISALLOW_COPY_AND_ASSIGN(QuicPacket);
+};
+
+class QUIC_EXPORT_PRIVATE QuicEncryptedPacket : public QuicData {
+ public:
+ QuicEncryptedPacket(const char* buffer, size_t length);
+ QuicEncryptedPacket(const char* buffer, size_t length, bool owns_buffer);
+
+ // Clones the packet into a new packet which owns the buffer.
+ std::unique_ptr<QuicEncryptedPacket> Clone() const;
+
+ // By default, gtest prints the raw bytes of an object. The bool data
+ // member (in the base class QuicData) causes this object to have padding
+ // bytes, which causes the default gtest object printer to read
+ // uninitialize memory. So we need to teach gtest how to print this object.
+ QUIC_EXPORT_PRIVATE friend std::ostream& operator<<(
+ std::ostream& os,
+ const QuicEncryptedPacket& s);
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(QuicEncryptedPacket);
+};
+
+// A received encrypted QUIC packet, with a recorded time of receipt.
+class QUIC_EXPORT_PRIVATE QuicReceivedPacket : public QuicEncryptedPacket {
+ public:
+ QuicReceivedPacket(const char* buffer, size_t length, QuicTime receipt_time);
+ QuicReceivedPacket(const char* buffer,
+ size_t length,
+ QuicTime receipt_time,
+ bool owns_buffer);
+ QuicReceivedPacket(const char* buffer,
+ size_t length,
+ QuicTime receipt_time,
+ bool owns_buffer,
+ int ttl,
+ bool ttl_valid);
+
+ // Clones the packet into a new packet which owns the buffer.
+ std::unique_ptr<QuicReceivedPacket> Clone() const;
+
+ // Returns the time at which the packet was received.
+ QuicTime receipt_time() const { return receipt_time_; }
+
+ // This is the TTL of the packet, assuming ttl_vaild_ is true.
+ int ttl() const { return ttl_; }
+
+ // By default, gtest prints the raw bytes of an object. The bool data
+ // member (in the base class QuicData) causes this object to have padding
+ // bytes, which causes the default gtest object printer to read
+ // uninitialize memory. So we need to teach gtest how to print this object.
+ QUIC_EXPORT_PRIVATE friend std::ostream& operator<<(
+ std::ostream& os,
+ const QuicReceivedPacket& s);
+
+ private:
+ const QuicTime receipt_time_;
+ int ttl_;
+
+ DISALLOW_COPY_AND_ASSIGN(QuicReceivedPacket);
+};
+
+struct QUIC_EXPORT_PRIVATE SerializedPacket {
+ SerializedPacket(QuicPathId path_id,
+ QuicPacketNumber packet_number,
+ QuicPacketNumberLength packet_number_length,
+ const char* encrypted_buffer,
+ QuicPacketLength encrypted_length,
+ bool has_ack,
+ bool has_stop_waiting);
+ SerializedPacket(const SerializedPacket& other);
+ ~SerializedPacket();
+
+ // Not owned.
+ const char* encrypted_buffer;
+ QuicPacketLength encrypted_length;
+ QuicFrames retransmittable_frames;
+ IsHandshake has_crypto_handshake;
+ // -1: full padding to the end of a max-sized packet
+ // 0: no padding
+ // otherwise: only pad up to num_padding_bytes bytes
+ int16_t num_padding_bytes;
+ QuicPathId path_id;
+ QuicPacketNumber packet_number;
+ QuicPacketNumberLength packet_number_length;
+ EncryptionLevel encryption_level;
+ bool has_ack;
+ bool has_stop_waiting;
+ TransmissionType transmission_type;
+ QuicPathId original_path_id;
+ QuicPacketNumber original_packet_number;
+
+ // Optional notifiers which will be informed when this packet has been ACKed.
+ std::list<AckListenerWrapper> listeners;
+};
+
+// Deletes and clears all the frames and the packet from serialized packet.
+QUIC_EXPORT_PRIVATE void ClearSerializedPacket(
+ SerializedPacket* serialized_packet);
+
+// Allocates a new char[] of size |packet.encrypted_length| and copies in
+// |packet.encrypted_buffer|.
+QUIC_EXPORT_PRIVATE char* CopyBuffer(const SerializedPacket& packet);
+
+} // namespace net
+
+#endif // NET_QUIC_CORE_QUIC_PACKETS_H_
diff --git a/chromium/net/quic/core/quic_pending_retransmission.h b/chromium/net/quic/core/quic_pending_retransmission.h
new file mode 100644
index 00000000000..1b6f0cc3a9a
--- /dev/null
+++ b/chromium/net/quic/core/quic_pending_retransmission.h
@@ -0,0 +1,42 @@
+// Copyright (c) 2016 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.
+
+#ifndef NET_QUIC_CORE_QUIC_PENDING_RETRANSMISSION_H_
+#define NET_QUIC_CORE_QUIC_PENDING_RETRANSMISSION_H_
+
+#include "net/quic/core/frames/quic_frame.h"
+#include "net/quic/core/quic_types.h"
+#include "net/quic/platform/api/quic_export.h"
+
+namespace net {
+
+// Struct to store the pending retransmission information.
+struct QUIC_EXPORT_PRIVATE QuicPendingRetransmission {
+ QuicPendingRetransmission(QuicPacketNumber packet_number,
+ TransmissionType transmission_type,
+ const QuicFrames& retransmittable_frames,
+ bool has_crypto_handshake,
+ int num_padding_bytes,
+ EncryptionLevel encryption_level,
+ QuicPacketNumberLength packet_number_length)
+ : packet_number(packet_number),
+ retransmittable_frames(retransmittable_frames),
+ transmission_type(transmission_type),
+ has_crypto_handshake(has_crypto_handshake),
+ num_padding_bytes(num_padding_bytes),
+ encryption_level(encryption_level),
+ packet_number_length(packet_number_length) {}
+
+ QuicPacketNumber packet_number;
+ const QuicFrames& retransmittable_frames;
+ TransmissionType transmission_type;
+ bool has_crypto_handshake;
+ int num_padding_bytes;
+ EncryptionLevel encryption_level;
+ QuicPacketNumberLength packet_number_length;
+};
+
+} // namespace net
+
+#endif // NET_QUIC_CORE_QUIC_PENDING_RETRANSMISSION_H_
diff --git a/chromium/net/quic/core/quic_protocol.cc b/chromium/net/quic/core/quic_protocol.cc
deleted file mode 100644
index 690e5a2c7c2..00000000000
--- a/chromium/net/quic/core/quic_protocol.cc
+++ /dev/null
@@ -1,856 +0,0 @@
-// Copyright (c) 2012 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.
-
-#include "net/quic/core/quic_protocol.h"
-
-#include "base/memory/ptr_util.h"
-#include "base/strings/string_number_conversions.h"
-#include "net/quic/core/quic_flags.h"
-#include "net/quic/core/quic_utils.h"
-
-using base::StringPiece;
-using std::map;
-using std::numeric_limits;
-using std::ostream;
-using std::string;
-
-namespace net {
-
-const char* const kFinalOffsetHeaderKey = ":final-offset";
-
-size_t GetPacketHeaderSize(QuicVersion version,
- const QuicPacketHeader& header) {
- return GetPacketHeaderSize(version, header.public_header.connection_id_length,
- header.public_header.version_flag,
- header.public_header.multipath_flag,
- header.public_header.nonce != nullptr,
- header.public_header.packet_number_length);
-}
-
-size_t GetPacketHeaderSize(QuicVersion version,
- QuicConnectionIdLength connection_id_length,
- bool include_version,
- bool include_path_id,
- bool include_diversification_nonce,
- QuicPacketNumberLength packet_number_length) {
- return kPublicFlagsSize + connection_id_length +
- (include_version ? kQuicVersionSize : 0) +
- (include_path_id ? kQuicPathIdSize : 0) + packet_number_length +
- (include_diversification_nonce ? kDiversificationNonceSize : 0) +
- (version <= QUIC_VERSION_33 ? kPrivateFlagsSize : 0);
-}
-
-size_t GetStartOfEncryptedData(QuicVersion version,
- const QuicPacketHeader& header) {
- return GetPacketHeaderSize(version, header) -
- (version <= QUIC_VERSION_33 ? kPrivateFlagsSize : 0);
-}
-
-size_t GetStartOfEncryptedData(QuicVersion version,
- QuicConnectionIdLength connection_id_length,
- bool include_version,
- bool include_path_id,
- bool include_diversification_nonce,
- QuicPacketNumberLength packet_number_length) {
- // Encryption starts before private flags.
- return GetPacketHeaderSize(version, connection_id_length, include_version,
- include_path_id, include_diversification_nonce,
- packet_number_length) -
- (version <= QUIC_VERSION_33 ? kPrivateFlagsSize : 0);
-}
-
-QuicPacketPublicHeader::QuicPacketPublicHeader()
- : connection_id(0),
- connection_id_length(PACKET_8BYTE_CONNECTION_ID),
- multipath_flag(false),
- reset_flag(false),
- version_flag(false),
- packet_number_length(PACKET_6BYTE_PACKET_NUMBER),
- nonce(nullptr) {}
-
-QuicPacketPublicHeader::QuicPacketPublicHeader(
- const QuicPacketPublicHeader& other) = default;
-
-QuicPacketPublicHeader::~QuicPacketPublicHeader() {}
-
-QuicPacketHeader::QuicPacketHeader()
- : packet_number(0),
- path_id(kDefaultPathId),
- entropy_flag(false),
- entropy_hash(0) {}
-
-QuicPacketHeader::QuicPacketHeader(const QuicPacketPublicHeader& header)
- : public_header(header),
- packet_number(0),
- path_id(kDefaultPathId),
- entropy_flag(false),
- entropy_hash(0) {}
-
-QuicPacketHeader::QuicPacketHeader(const QuicPacketHeader& other) = default;
-
-QuicPublicResetPacket::QuicPublicResetPacket()
- : nonce_proof(0), rejected_packet_number(0) {}
-
-QuicPublicResetPacket::QuicPublicResetPacket(
- const QuicPacketPublicHeader& header)
- : public_header(header), nonce_proof(0), rejected_packet_number(0) {}
-
-QuicBufferAllocator::~QuicBufferAllocator() = default;
-
-void StreamBufferDeleter::operator()(char* buffer) const {
- if (allocator_ != nullptr && buffer != nullptr) {
- allocator_->Delete(buffer);
- }
-}
-
-UniqueStreamBuffer NewStreamBuffer(QuicBufferAllocator* allocator,
- size_t size) {
- return UniqueStreamBuffer(allocator->New(size),
- StreamBufferDeleter(allocator));
-}
-
-QuicStreamFrame::QuicStreamFrame()
- : QuicStreamFrame(0, false, 0, nullptr, 0, nullptr) {}
-
-QuicStreamFrame::QuicStreamFrame(QuicStreamId stream_id,
- bool fin,
- QuicStreamOffset offset,
- StringPiece data)
- : QuicStreamFrame(stream_id,
- fin,
- offset,
- data.data(),
- data.length(),
- nullptr) {}
-
-QuicStreamFrame::QuicStreamFrame(QuicStreamId stream_id,
- bool fin,
- QuicStreamOffset offset,
- QuicPacketLength data_length,
- UniqueStreamBuffer buffer)
- : QuicStreamFrame(stream_id,
- fin,
- offset,
- nullptr,
- data_length,
- std::move(buffer)) {
- DCHECK(this->buffer != nullptr);
- DCHECK_EQ(data_buffer, this->buffer.get());
-}
-
-QuicStreamFrame::QuicStreamFrame(QuicStreamId stream_id,
- bool fin,
- QuicStreamOffset offset,
- const char* data_buffer,
- QuicPacketLength data_length,
- UniqueStreamBuffer buffer)
- : stream_id(stream_id),
- fin(fin),
- data_length(data_length),
- data_buffer(data_buffer),
- offset(offset),
- buffer(std::move(buffer)) {
- if (this->buffer != nullptr) {
- DCHECK(data_buffer == nullptr);
- this->data_buffer = this->buffer.get();
- }
-}
-
-QuicStreamFrame::~QuicStreamFrame() {}
-
-uint32_t MakeQuicTag(char a, char b, char c, char d) {
- return static_cast<uint32_t>(a) | static_cast<uint32_t>(b) << 8 |
- static_cast<uint32_t>(c) << 16 | static_cast<uint32_t>(d) << 24;
-}
-
-bool ContainsQuicTag(const QuicTagVector& tag_vector, QuicTag tag) {
- return std::find(tag_vector.begin(), tag_vector.end(), tag) !=
- tag_vector.end();
-}
-
-QuicVersionVector AllSupportedVersions() {
- QuicVersionVector supported_versions;
- for (size_t i = 0; i < arraysize(kSupportedQuicVersions); ++i) {
- supported_versions.push_back(kSupportedQuicVersions[i]);
- }
- return supported_versions;
-}
-
-QuicVersionVector CurrentSupportedVersions() {
- return FilterSupportedVersions(AllSupportedVersions());
-}
-
-QuicVersionVector FilterSupportedVersions(QuicVersionVector versions) {
- QuicVersionVector filtered_versions(versions.size());
- filtered_versions.clear(); // Guaranteed by spec not to change capacity.
- for (QuicVersion version : versions) {
- if (version < QUIC_VERSION_34) {
- if (!FLAGS_quic_disable_pre_34) {
- filtered_versions.push_back(version);
- }
- } else if (version == QUIC_VERSION_35) {
- if (FLAGS_quic_enable_version_35) {
- filtered_versions.push_back(version);
- }
- } else if (version == QUIC_VERSION_36) {
- if (FLAGS_quic_enable_version_35 && FLAGS_quic_enable_version_36_v2) {
- filtered_versions.push_back(version);
- }
- } else {
- filtered_versions.push_back(version);
- }
- }
- return filtered_versions;
-}
-
-QuicVersionVector VersionOfIndex(const QuicVersionVector& versions, int index) {
- QuicVersionVector version;
- int version_count = versions.size();
- if (index >= 0 && index < version_count) {
- version.push_back(versions[index]);
- } else {
- version.push_back(QUIC_VERSION_UNSUPPORTED);
- }
- return version;
-}
-
-QuicTag QuicVersionToQuicTag(const QuicVersion version) {
- switch (version) {
- case QUIC_VERSION_32:
- return MakeQuicTag('Q', '0', '3', '2');
- case QUIC_VERSION_33:
- return MakeQuicTag('Q', '0', '3', '3');
- case QUIC_VERSION_34:
- return MakeQuicTag('Q', '0', '3', '4');
- case QUIC_VERSION_35:
- return MakeQuicTag('Q', '0', '3', '5');
- case QUIC_VERSION_36:
- return MakeQuicTag('Q', '0', '3', '6');
- default:
- // This shold be an ERROR because we should never attempt to convert an
- // invalid QuicVersion to be written to the wire.
- LOG(ERROR) << "Unsupported QuicVersion: " << version;
- return 0;
- }
-}
-
-QuicVersion QuicTagToQuicVersion(const QuicTag version_tag) {
- for (size_t i = 0; i < arraysize(kSupportedQuicVersions); ++i) {
- if (version_tag == QuicVersionToQuicTag(kSupportedQuicVersions[i])) {
- return kSupportedQuicVersions[i];
- }
- }
- // Reading from the client so this should not be considered an ERROR.
- DVLOG(1) << "Unsupported QuicTag version: "
- << QuicUtils::TagToString(version_tag);
- return QUIC_VERSION_UNSUPPORTED;
-}
-
-#define RETURN_STRING_LITERAL(x) \
- case x: \
- return #x
-
-string QuicVersionToString(const QuicVersion version) {
- switch (version) {
- RETURN_STRING_LITERAL(QUIC_VERSION_32);
- RETURN_STRING_LITERAL(QUIC_VERSION_33);
- RETURN_STRING_LITERAL(QUIC_VERSION_34);
- RETURN_STRING_LITERAL(QUIC_VERSION_35);
- RETURN_STRING_LITERAL(QUIC_VERSION_36);
- default:
- return "QUIC_VERSION_UNSUPPORTED";
- }
-}
-
-string QuicVersionVectorToString(const QuicVersionVector& versions) {
- string result = "";
- for (size_t i = 0; i < versions.size(); ++i) {
- if (i != 0) {
- result.append(",");
- }
- result.append(QuicVersionToString(versions[i]));
- }
- return result;
-}
-
-ostream& operator<<(ostream& os, const Perspective& s) {
- if (s == Perspective::IS_SERVER) {
- os << "IS_SERVER";
- } else {
- os << "IS_CLIENT";
- }
- return os;
-}
-
-ostream& operator<<(ostream& os, const QuicPacketHeader& header) {
- os << "{ connection_id: " << header.public_header.connection_id
- << ", connection_id_length: " << header.public_header.connection_id_length
- << ", packet_number_length: " << header.public_header.packet_number_length
- << ", multipath_flag: " << header.public_header.multipath_flag
- << ", reset_flag: " << header.public_header.reset_flag
- << ", version_flag: " << header.public_header.version_flag;
- if (header.public_header.version_flag) {
- os << ", version:";
- for (size_t i = 0; i < header.public_header.versions.size(); ++i) {
- os << " ";
- os << QuicVersionToString(header.public_header.versions[i]);
- }
- }
- if (header.public_header.nonce != nullptr) {
- os << ", diversification_nonce: "
- << QuicUtils::HexEncode(StringPiece(header.public_header.nonce->data(),
- header.public_header.nonce->size()));
- }
- os << ", entropy_flag: " << header.entropy_flag
- << ", entropy hash: " << static_cast<int>(header.entropy_hash)
- << ", path_id: " << static_cast<int>(header.path_id)
- << ", packet_number: " << header.packet_number << " }\n";
- return os;
-}
-
-bool IsAwaitingPacket(const QuicAckFrame& ack_frame,
- QuicPacketNumber packet_number,
- QuicPacketNumber peer_least_packet_awaiting_ack) {
- if (ack_frame.missing) {
- return packet_number > ack_frame.largest_observed ||
- ack_frame.packets.Contains(packet_number);
- }
- return packet_number >= peer_least_packet_awaiting_ack &&
- !ack_frame.packets.Contains(packet_number);
-}
-
-QuicStopWaitingFrame::QuicStopWaitingFrame()
- : path_id(kDefaultPathId), entropy_hash(0), least_unacked(0) {}
-
-QuicStopWaitingFrame::~QuicStopWaitingFrame() {}
-
-QuicAckFrame::QuicAckFrame()
- : largest_observed(0),
- ack_delay_time(QuicTime::Delta::Infinite()),
- path_id(kDefaultPathId),
- entropy_hash(0),
- is_truncated(false),
- missing(true) {}
-
-QuicAckFrame::QuicAckFrame(const QuicAckFrame& other) = default;
-
-QuicAckFrame::~QuicAckFrame() {}
-
-QuicRstStreamFrame::QuicRstStreamFrame()
- : stream_id(0), error_code(QUIC_STREAM_NO_ERROR), byte_offset(0) {}
-
-QuicRstStreamFrame::QuicRstStreamFrame(QuicStreamId stream_id,
- QuicRstStreamErrorCode error_code,
- QuicStreamOffset bytes_written)
- : stream_id(stream_id),
- error_code(error_code),
- byte_offset(bytes_written) {}
-
-QuicConnectionCloseFrame::QuicConnectionCloseFrame()
- : error_code(QUIC_NO_ERROR) {}
-
-QuicFrame::QuicFrame() {}
-
-QuicFrame::QuicFrame(QuicPaddingFrame padding_frame)
- : type(PADDING_FRAME), padding_frame(padding_frame) {}
-
-QuicFrame::QuicFrame(QuicStreamFrame* stream_frame)
- : type(STREAM_FRAME), stream_frame(stream_frame) {}
-
-QuicFrame::QuicFrame(QuicAckFrame* frame) : type(ACK_FRAME), ack_frame(frame) {}
-
-QuicFrame::QuicFrame(QuicMtuDiscoveryFrame frame)
- : type(MTU_DISCOVERY_FRAME), mtu_discovery_frame(frame) {}
-
-QuicFrame::QuicFrame(QuicStopWaitingFrame* frame)
- : type(STOP_WAITING_FRAME), stop_waiting_frame(frame) {}
-
-QuicFrame::QuicFrame(QuicPingFrame frame)
- : type(PING_FRAME), ping_frame(frame) {}
-
-QuicFrame::QuicFrame(QuicRstStreamFrame* frame)
- : type(RST_STREAM_FRAME), rst_stream_frame(frame) {}
-
-QuicFrame::QuicFrame(QuicConnectionCloseFrame* frame)
- : type(CONNECTION_CLOSE_FRAME), connection_close_frame(frame) {}
-
-QuicFrame::QuicFrame(QuicGoAwayFrame* frame)
- : type(GOAWAY_FRAME), goaway_frame(frame) {}
-
-QuicFrame::QuicFrame(QuicWindowUpdateFrame* frame)
- : type(WINDOW_UPDATE_FRAME), window_update_frame(frame) {}
-
-QuicFrame::QuicFrame(QuicBlockedFrame* frame)
- : type(BLOCKED_FRAME), blocked_frame(frame) {}
-
-QuicFrame::QuicFrame(QuicPathCloseFrame* frame)
- : type(PATH_CLOSE_FRAME), path_close_frame(frame) {}
-
-ostream& operator<<(ostream& os, const QuicStopWaitingFrame& sent_info) {
- os << "{ entropy_hash: " << static_cast<int>(sent_info.entropy_hash)
- << ", least_unacked: " << sent_info.least_unacked << " }\n";
- return os;
-}
-
-PacketNumberQueue::PacketNumberQueue() = default;
-PacketNumberQueue::PacketNumberQueue(const PacketNumberQueue& other) = default;
-// TODO(rtenneti): on windows RValue reference gives errors.
-// PacketNumberQueue::PacketNumberQueue(PacketNumberQueue&& other) = default;
-PacketNumberQueue::~PacketNumberQueue() {}
-
-PacketNumberQueue& PacketNumberQueue::operator=(
- const PacketNumberQueue& other) = default;
-// TODO(rtenneti): on windows RValue reference gives errors.
-// PacketNumberQueue& PacketNumberQueue::operator=(PacketNumberQueue&& other) =
-// default;
-
-void PacketNumberQueue::Add(QuicPacketNumber packet_number) {
- packet_number_intervals_.Add(packet_number, packet_number + 1);
-}
-
-void PacketNumberQueue::Add(QuicPacketNumber lower, QuicPacketNumber higher) {
- packet_number_intervals_.Add(lower, higher);
-}
-
-void PacketNumberQueue::Remove(QuicPacketNumber packet_number) {
- packet_number_intervals_.Difference(packet_number, packet_number + 1);
-}
-
-void PacketNumberQueue::Remove(QuicPacketNumber lower,
- QuicPacketNumber higher) {
- packet_number_intervals_.Difference(lower, higher);
-}
-
-bool PacketNumberQueue::RemoveUpTo(QuicPacketNumber higher) {
- if (Empty()) {
- return false;
- }
- const QuicPacketNumber old_min = Min();
- packet_number_intervals_.Difference(0, higher);
- return Empty() || old_min != Min();
-}
-
-void PacketNumberQueue::Complement() {
- if (Empty()) {
- return;
- }
- packet_number_intervals_.Complement(Min(), Max() + 1);
-}
-
-bool PacketNumberQueue::Contains(QuicPacketNumber packet_number) const {
- return packet_number_intervals_.Contains(packet_number);
-}
-
-bool PacketNumberQueue::Empty() const {
- return packet_number_intervals_.Empty();
-}
-
-QuicPacketNumber PacketNumberQueue::Min() const {
- DCHECK(!Empty());
- return packet_number_intervals_.begin()->min();
-}
-
-QuicPacketNumber PacketNumberQueue::Max() const {
- DCHECK(!Empty());
- return packet_number_intervals_.rbegin()->max() - 1;
-}
-
-size_t PacketNumberQueue::NumPacketsSlow() const {
- size_t num_packets = 0;
- for (const auto& interval : packet_number_intervals_) {
- num_packets += interval.Length();
- }
- return num_packets;
-}
-
-size_t PacketNumberQueue::NumIntervals() const {
- return packet_number_intervals_.Size();
-}
-
-QuicPacketNumber PacketNumberQueue::LastIntervalLength() const {
- DCHECK(!Empty());
- return packet_number_intervals_.rbegin()->Length();
-}
-
-PacketNumberQueue::const_iterator PacketNumberQueue::lower_bound(
- QuicPacketNumber packet_number) const {
- // lower_bound returns the first interval that contains |packet_number| or the
- // first interval after |packet_number|.
- auto itr = packet_number_intervals_.Find(packet_number);
- if (itr != packet_number_intervals_.end()) {
- return itr;
- }
- for (itr = packet_number_intervals_.begin();
- itr != packet_number_intervals_.end(); ++itr) {
- if (packet_number < itr->min()) {
- return itr;
- }
- }
- return packet_number_intervals_.end();
-}
-
-PacketNumberQueue::const_iterator PacketNumberQueue::begin() const {
- return packet_number_intervals_.begin();
-}
-
-PacketNumberQueue::const_iterator PacketNumberQueue::end() const {
- return packet_number_intervals_.end();
-}
-
-PacketNumberQueue::const_reverse_iterator PacketNumberQueue::rbegin() const {
- return packet_number_intervals_.rbegin();
-}
-
-PacketNumberQueue::const_reverse_iterator PacketNumberQueue::rend() const {
- return packet_number_intervals_.rend();
-}
-
-ostream& operator<<(ostream& os, const PacketNumberQueue& q) {
- for (const Interval<QuicPacketNumber>& interval : q) {
- for (QuicPacketNumber packet_number = interval.min();
- packet_number < interval.max(); ++packet_number) {
- os << packet_number << " ";
- }
- }
- return os;
-}
-
-ostream& operator<<(ostream& os, const QuicAckFrame& ack_frame) {
- os << "{ entropy_hash: " << static_cast<int>(ack_frame.entropy_hash)
- << ", largest_observed: " << ack_frame.largest_observed
- << ", ack_delay_time: " << ack_frame.ack_delay_time.ToMicroseconds()
- << ", packets: [ " << ack_frame.packets << " ]"
- << ", is_truncated: " << ack_frame.is_truncated
- << ", received_packets: [ ";
- for (const std::pair<QuicPacketNumber, QuicTime>& p :
- ack_frame.received_packet_times) {
- os << p.first << " at " << p.second.ToDebuggingValue() << " ";
- }
- os << " ] }\n";
- return os;
-}
-
-ostream& operator<<(ostream& os, const QuicFrame& frame) {
- switch (frame.type) {
- case PADDING_FRAME: {
- os << "type { PADDING_FRAME } " << frame.padding_frame;
- break;
- }
- case RST_STREAM_FRAME: {
- os << "type { RST_STREAM_FRAME } " << *(frame.rst_stream_frame);
- break;
- }
- case CONNECTION_CLOSE_FRAME: {
- os << "type { CONNECTION_CLOSE_FRAME } "
- << *(frame.connection_close_frame);
- break;
- }
- case GOAWAY_FRAME: {
- os << "type { GOAWAY_FRAME } " << *(frame.goaway_frame);
- break;
- }
- case WINDOW_UPDATE_FRAME: {
- os << "type { WINDOW_UPDATE_FRAME } " << *(frame.window_update_frame);
- break;
- }
- case BLOCKED_FRAME: {
- os << "type { BLOCKED_FRAME } " << *(frame.blocked_frame);
- break;
- }
- case STREAM_FRAME: {
- os << "type { STREAM_FRAME } " << *(frame.stream_frame);
- break;
- }
- case ACK_FRAME: {
- os << "type { ACK_FRAME } " << *(frame.ack_frame);
- break;
- }
- case STOP_WAITING_FRAME: {
- os << "type { STOP_WAITING_FRAME } " << *(frame.stop_waiting_frame);
- break;
- }
- case PING_FRAME: {
- os << "type { PING_FRAME } ";
- break;
- }
- case MTU_DISCOVERY_FRAME: {
- os << "type { MTU_DISCOVERY_FRAME } ";
- break;
- }
- case PATH_CLOSE_FRAME: {
- os << "type { PATH_CLOSE_FRAME } " << *(frame.path_close_frame);
- break;
- }
- default: {
- LOG(ERROR) << "Unknown frame type: " << frame.type;
- break;
- }
- }
- return os;
-}
-
-ostream& operator<<(ostream& os, const QuicPaddingFrame& padding_frame) {
- os << "{ num_padding_bytes: " << padding_frame.num_padding_bytes << " }\n";
- return os;
-}
-
-ostream& operator<<(ostream& os, const QuicRstStreamFrame& rst_frame) {
- os << "{ stream_id: " << rst_frame.stream_id
- << ", error_code: " << rst_frame.error_code << " }\n";
- return os;
-}
-
-ostream& operator<<(ostream& os,
- const QuicConnectionCloseFrame& connection_close_frame) {
- os << "{ error_code: " << connection_close_frame.error_code
- << ", error_details: '" << connection_close_frame.error_details << "' }\n";
- return os;
-}
-
-ostream& operator<<(ostream& os, const QuicGoAwayFrame& goaway_frame) {
- os << "{ error_code: " << goaway_frame.error_code
- << ", last_good_stream_id: " << goaway_frame.last_good_stream_id
- << ", reason_phrase: '" << goaway_frame.reason_phrase << "' }\n";
- return os;
-}
-
-ostream& operator<<(ostream& os,
- const QuicWindowUpdateFrame& window_update_frame) {
- os << "{ stream_id: " << window_update_frame.stream_id
- << ", byte_offset: " << window_update_frame.byte_offset << " }\n";
- return os;
-}
-
-ostream& operator<<(ostream& os, const QuicBlockedFrame& blocked_frame) {
- os << "{ stream_id: " << blocked_frame.stream_id << " }\n";
- return os;
-}
-
-ostream& operator<<(ostream& os, const QuicPathCloseFrame& path_close_frame) {
- os << "{ path_id: " << static_cast<int>(path_close_frame.path_id) << " }\n";
- return os;
-}
-
-ostream& operator<<(ostream& os, const QuicStreamFrame& stream_frame) {
- os << "{ stream_id: " << stream_frame.stream_id
- << ", fin: " << stream_frame.fin << ", offset: " << stream_frame.offset
- << ", length: " << stream_frame.data_length << " }\n";
- return os;
-}
-
-QuicGoAwayFrame::QuicGoAwayFrame()
- : error_code(QUIC_NO_ERROR), last_good_stream_id(0) {}
-
-QuicGoAwayFrame::QuicGoAwayFrame(QuicErrorCode error_code,
- QuicStreamId last_good_stream_id,
- const string& reason)
- : error_code(error_code),
- last_good_stream_id(last_good_stream_id),
- reason_phrase(reason) {}
-
-QuicData::QuicData(const char* buffer, size_t length)
- : buffer_(buffer), length_(length), owns_buffer_(false) {}
-
-QuicData::QuicData(const char* buffer, size_t length, bool owns_buffer)
- : buffer_(buffer), length_(length), owns_buffer_(owns_buffer) {}
-
-QuicData::~QuicData() {
- if (owns_buffer_) {
- delete[] const_cast<char*>(buffer_);
- }
-}
-
-QuicWindowUpdateFrame::QuicWindowUpdateFrame(QuicStreamId stream_id,
- QuicStreamOffset byte_offset)
- : stream_id(stream_id), byte_offset(byte_offset) {}
-
-QuicBlockedFrame::QuicBlockedFrame(QuicStreamId stream_id)
- : stream_id(stream_id) {}
-
-QuicPathCloseFrame::QuicPathCloseFrame(QuicPathId path_id) : path_id(path_id) {}
-
-QuicPacket::QuicPacket(char* buffer,
- size_t length,
- bool owns_buffer,
- QuicConnectionIdLength connection_id_length,
- bool includes_version,
- bool includes_path_id,
- bool includes_diversification_nonce,
- QuicPacketNumberLength packet_number_length)
- : QuicData(buffer, length, owns_buffer),
- buffer_(buffer),
- connection_id_length_(connection_id_length),
- includes_version_(includes_version),
- includes_path_id_(includes_path_id),
- includes_diversification_nonce_(includes_diversification_nonce),
- packet_number_length_(packet_number_length) {}
-
-QuicEncryptedPacket::QuicEncryptedPacket(const char* buffer, size_t length)
- : QuicData(buffer, length) {}
-
-QuicEncryptedPacket::QuicEncryptedPacket(const char* buffer,
- size_t length,
- bool owns_buffer)
- : QuicData(buffer, length, owns_buffer) {}
-
-std::unique_ptr<QuicEncryptedPacket> QuicEncryptedPacket::Clone() const {
- char* buffer = new char[this->length()];
- memcpy(buffer, this->data(), this->length());
- return base::MakeUnique<QuicEncryptedPacket>(buffer, this->length(), true);
-}
-
-ostream& operator<<(ostream& os, const QuicEncryptedPacket& s) {
- os << s.length() << "-byte data";
- return os;
-}
-
-QuicReceivedPacket::QuicReceivedPacket(const char* buffer,
- size_t length,
- QuicTime receipt_time)
- : QuicEncryptedPacket(buffer, length),
- receipt_time_(receipt_time),
- ttl_(0) {}
-
-QuicReceivedPacket::QuicReceivedPacket(const char* buffer,
- size_t length,
- QuicTime receipt_time,
- bool owns_buffer)
- : QuicEncryptedPacket(buffer, length, owns_buffer),
- receipt_time_(receipt_time),
- ttl_(0) {}
-
-QuicReceivedPacket::QuicReceivedPacket(const char* buffer,
- size_t length,
- QuicTime receipt_time,
- bool owns_buffer,
- int ttl,
- bool ttl_valid)
- : QuicEncryptedPacket(buffer, length, owns_buffer),
- receipt_time_(receipt_time),
- ttl_(ttl_valid ? ttl : -1) {}
-
-std::unique_ptr<QuicReceivedPacket> QuicReceivedPacket::Clone() const {
- char* buffer = new char[this->length()];
- memcpy(buffer, this->data(), this->length());
- return base::MakeUnique<QuicReceivedPacket>(
- buffer, this->length(), receipt_time(), true, ttl(), ttl() >= 0);
-}
-
-ostream& operator<<(ostream& os, const QuicReceivedPacket& s) {
- os << s.length() << "-byte data";
- return os;
-}
-
-StringPiece QuicPacket::AssociatedData(QuicVersion version) const {
- return StringPiece(
- data(), GetStartOfEncryptedData(version, connection_id_length_,
- includes_version_, includes_path_id_,
- includes_diversification_nonce_,
- packet_number_length_));
-}
-
-StringPiece QuicPacket::Plaintext(QuicVersion version) const {
- const size_t start_of_encrypted_data = GetStartOfEncryptedData(
- version, connection_id_length_, includes_version_, includes_path_id_,
- includes_diversification_nonce_, packet_number_length_);
- return StringPiece(data() + start_of_encrypted_data,
- length() - start_of_encrypted_data);
-}
-
-QuicVersionManager::QuicVersionManager(QuicVersionVector supported_versions)
- : disable_pre_34_(FLAGS_quic_disable_pre_34),
- enable_version_35_(FLAGS_quic_enable_version_35),
- enable_version_36_(FLAGS_quic_enable_version_36_v2),
- allowed_supported_versions_(supported_versions),
- filtered_supported_versions_(
- FilterSupportedVersions(supported_versions)) {}
-
-QuicVersionManager::~QuicVersionManager() {}
-
-const QuicVersionVector& QuicVersionManager::GetSupportedVersions() {
- if (disable_pre_34_ != FLAGS_quic_disable_pre_34 ||
- enable_version_35_ != FLAGS_quic_enable_version_35 ||
- enable_version_36_ != FLAGS_quic_enable_version_36_v2) {
- disable_pre_34_ = FLAGS_quic_disable_pre_34;
- enable_version_35_ = FLAGS_quic_enable_version_35;
- enable_version_36_ = FLAGS_quic_enable_version_36_v2;
- filtered_supported_versions_ =
- FilterSupportedVersions(allowed_supported_versions_);
- }
- return filtered_supported_versions_;
-}
-
-AckListenerWrapper::AckListenerWrapper(QuicAckListenerInterface* listener,
- QuicPacketLength data_length)
- : ack_listener(listener), length(data_length) {
- DCHECK(listener != nullptr);
-}
-
-AckListenerWrapper::AckListenerWrapper(const AckListenerWrapper& other) =
- default;
-
-AckListenerWrapper::~AckListenerWrapper() {}
-
-SerializedPacket::SerializedPacket(QuicPathId path_id,
- QuicPacketNumber packet_number,
- QuicPacketNumberLength packet_number_length,
- const char* encrypted_buffer,
- QuicPacketLength encrypted_length,
- QuicPacketEntropyHash entropy_hash,
- bool has_ack,
- bool has_stop_waiting)
- : encrypted_buffer(encrypted_buffer),
- encrypted_length(encrypted_length),
- has_crypto_handshake(NOT_HANDSHAKE),
- num_padding_bytes(0),
- path_id(path_id),
- packet_number(packet_number),
- packet_number_length(packet_number_length),
- encryption_level(ENCRYPTION_NONE),
- entropy_hash(entropy_hash),
- has_ack(has_ack),
- has_stop_waiting(has_stop_waiting),
- transmission_type(NOT_RETRANSMISSION),
- original_path_id(kInvalidPathId),
- original_packet_number(0) {}
-
-SerializedPacket::SerializedPacket(const SerializedPacket& other) = default;
-
-SerializedPacket::~SerializedPacket() {}
-
-TransmissionInfo::TransmissionInfo()
- : encryption_level(ENCRYPTION_NONE),
- packet_number_length(PACKET_1BYTE_PACKET_NUMBER),
- bytes_sent(0),
- sent_time(QuicTime::Zero()),
- transmission_type(NOT_RETRANSMISSION),
- in_flight(false),
- is_unackable(false),
- has_crypto_handshake(false),
- num_padding_bytes(0),
- retransmission(0) {}
-
-TransmissionInfo::TransmissionInfo(EncryptionLevel level,
- QuicPacketNumberLength packet_number_length,
- TransmissionType transmission_type,
- QuicTime sent_time,
- QuicPacketLength bytes_sent,
- bool has_crypto_handshake,
- int num_padding_bytes)
- : encryption_level(level),
- packet_number_length(packet_number_length),
- bytes_sent(bytes_sent),
- sent_time(sent_time),
- transmission_type(transmission_type),
- in_flight(false),
- is_unackable(false),
- has_crypto_handshake(has_crypto_handshake),
- num_padding_bytes(num_padding_bytes),
- retransmission(0) {}
-
-TransmissionInfo::TransmissionInfo(const TransmissionInfo& other) = default;
-
-TransmissionInfo::~TransmissionInfo() {}
-
-} // namespace net
diff --git a/chromium/net/quic/core/quic_protocol.h b/chromium/net/quic/core/quic_protocol.h
deleted file mode 100644
index 624e48b0078..00000000000
--- a/chromium/net/quic/core/quic_protocol.h
+++ /dev/null
@@ -1,1528 +0,0 @@
-// Copyright (c) 2012 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.
-
-#ifndef NET_QUIC_QUIC_PROTOCOL_H_
-#define NET_QUIC_QUIC_PROTOCOL_H_
-
-#include <stddef.h>
-#include <stdint.h>
-
-#include <array>
-#include <limits>
-#include <list>
-#include <map>
-#include <memory>
-#include <ostream>
-#include <set>
-#include <string>
-#include <utility>
-#include <vector>
-
-#include "base/logging.h"
-#include "base/macros.h"
-#include "base/memory/ref_counted.h"
-#include "base/strings/string_piece.h"
-#include "net/base/int128.h"
-#include "net/base/iovec.h"
-#include "net/base/ip_endpoint.h"
-#include "net/base/net_export.h"
-#include "net/quic/core/interval_set.h"
-#include "net/quic/core/quic_bandwidth.h"
-#include "net/quic/core/quic_time.h"
-#include "net/quic/core/quic_types.h"
-
-namespace net {
-
-class QuicPacket;
-struct QuicPacketHeader;
-class QuicAckListenerInterface;
-
-typedef uint64_t QuicConnectionId;
-typedef uint32_t QuicStreamId;
-typedef uint64_t QuicStreamOffset;
-typedef uint64_t QuicPacketNumber;
-typedef uint8_t QuicPathId;
-typedef uint64_t QuicPublicResetNonceProof;
-typedef uint8_t QuicPacketEntropyHash;
-typedef uint32_t QuicHeaderId;
-// QuicTag is the type of a tag in the wire protocol.
-typedef uint32_t QuicTag;
-typedef std::vector<QuicTag> QuicTagVector;
-typedef std::map<QuicTag, std::string> QuicTagValueMap;
-typedef uint16_t QuicPacketLength;
-
-// Default initial maximum size in bytes of a QUIC packet.
-const QuicByteCount kDefaultMaxPacketSize = 1350;
-// Default initial maximum size in bytes of a QUIC packet for servers.
-const QuicByteCount kDefaultServerMaxPacketSize = 1000;
-// The maximum packet size of any QUIC packet, based on ethernet's max size,
-// minus the IP and UDP headers. IPv6 has a 40 byte header, UDP adds an
-// additional 8 bytes. This is a total overhead of 48 bytes. Ethernet's
-// max packet size is 1500 bytes, 1500 - 48 = 1452.
-const QuicByteCount kMaxPacketSize = 1452;
-// Default maximum packet size used in the Linux TCP implementation.
-// Used in QUIC for congestion window computations in bytes.
-const QuicByteCount kDefaultTCPMSS = 1460;
-
-// We match SPDY's use of 32 (since we'd compete with SPDY).
-const QuicPacketCount kInitialCongestionWindow = 32;
-
-// Minimum size of initial flow control window, for both stream and session.
-const uint32_t kMinimumFlowControlSendWindow = 16 * 1024; // 16 KB
-
-// Maximum flow control receive window limits for connection and stream.
-const QuicByteCount kStreamReceiveWindowLimit = 16 * 1024 * 1024; // 16 MB
-const QuicByteCount kSessionReceiveWindowLimit = 24 * 1024 * 1024; // 24 MB
-
-// Default limit on the size of uncompressed headers.
-const QuicByteCount kDefaultMaxUncompressedHeaderSize = 16 * 1024; // 16 KB
-
-// Minimum size of the CWND, in packets, when doing bandwidth resumption.
-const QuicPacketCount kMinCongestionWindowForBandwidthResumption = 10;
-
-// Maximum number of tracked packets.
-const QuicPacketCount kMaxTrackedPackets = 10000;
-
-// Default size of the socket receive buffer in bytes.
-const QuicByteCount kDefaultSocketReceiveBuffer = 1024 * 1024;
-
-// Don't allow a client to suggest an RTT shorter than 10ms.
-const uint32_t kMinInitialRoundTripTimeUs = 10 * kNumMicrosPerMilli;
-
-// Don't allow a client to suggest an RTT longer than 15 seconds.
-const uint32_t kMaxInitialRoundTripTimeUs = 15 * kNumMicrosPerSecond;
-
-// Maximum number of open streams per connection.
-const size_t kDefaultMaxStreamsPerConnection = 100;
-
-// Number of bytes reserved for public flags in the packet header.
-const size_t kPublicFlagsSize = 1;
-// Number of bytes reserved for version number in the packet header.
-const size_t kQuicVersionSize = 4;
-// Number of bytes reserved for path id in the packet header.
-const size_t kQuicPathIdSize = 1;
-// Number of bytes reserved for private flags in the packet header.
-const size_t kPrivateFlagsSize = 1;
-
-// Signifies that the QuicPacket will contain version of the protocol.
-const bool kIncludeVersion = true;
-// Signifies that the QuicPacket will contain path id.
-const bool kIncludePathId = true;
-// Signifies that the QuicPacket will include a diversification nonce.
-const bool kIncludeDiversificationNonce = true;
-
-// Stream ID is reserved to denote an invalid ID.
-const QuicStreamId kInvalidStreamId = 0;
-
-// Reserved ID for the crypto stream.
-const QuicStreamId kCryptoStreamId = 1;
-
-// Reserved ID for the headers stream.
-const QuicStreamId kHeadersStreamId = 3;
-
-// Header key used to identify final offset on data stream when sending HTTP/2
-// trailing headers over QUIC.
-NET_EXPORT_PRIVATE extern const char* const kFinalOffsetHeaderKey;
-
-// Maximum delayed ack time, in ms.
-const int64_t kMaxDelayedAckTimeMs = 25;
-
-// Minimum tail loss probe time in ms.
-static const int64_t kMinTailLossProbeTimeoutMs = 10;
-
-// The timeout before the handshake succeeds.
-const int64_t kInitialIdleTimeoutSecs = 5;
-// The default idle timeout.
-const int64_t kDefaultIdleTimeoutSecs = 30;
-// The maximum idle timeout that can be negotiated.
-const int64_t kMaximumIdleTimeoutSecs = 60 * 10; // 10 minutes.
-// The default timeout for a connection until the crypto handshake succeeds.
-const int64_t kMaxTimeForCryptoHandshakeSecs = 10; // 10 secs.
-
-// Default limit on the number of undecryptable packets the connection buffers
-// before the CHLO/SHLO arrive.
-const size_t kDefaultMaxUndecryptablePackets = 10;
-
-// Default ping timeout.
-const int64_t kPingTimeoutSecs = 15; // 15 secs.
-
-// Minimum number of RTTs between Server Config Updates (SCUP) sent to client.
-const int kMinIntervalBetweenServerConfigUpdatesRTTs = 10;
-
-// Minimum time between Server Config Updates (SCUP) sent to client.
-const int kMinIntervalBetweenServerConfigUpdatesMs = 1000;
-
-// Minimum number of packets between Server Config Updates (SCUP).
-const int kMinPacketsBetweenServerConfigUpdates = 100;
-
-// The number of open streams that a server will accept is set to be slightly
-// larger than the negotiated limit. Immediately closing the connection if the
-// client opens slightly too many streams is not ideal: the client may have sent
-// a FIN that was lost, and simultaneously opened a new stream. The number of
-// streams a server accepts is a fixed increment over the negotiated limit, or a
-// percentage increase, whichever is larger.
-const float kMaxStreamsMultiplier = 1.1f;
-const int kMaxStreamsMinimumIncrement = 10;
-
-// Available streams are ones with IDs less than the highest stream that has
-// been opened which have neither been opened or reset. The limit on the number
-// of available streams is 10 times the limit on the number of open streams.
-const int kMaxAvailableStreamsMultiplier = 10;
-
-// Track the number of promises that are not yet claimed by a
-// corresponding get. This must be smaller than
-// kMaxAvailableStreamsMultiplier, because RST on a promised stream my
-// create available streams entries.
-const int kMaxPromisedStreamsMultiplier = kMaxAvailableStreamsMultiplier - 1;
-
-// TCP RFC calls for 1 second RTO however Linux differs from this default and
-// define the minimum RTO to 200ms, we will use the same until we have data to
-// support a higher or lower value.
-static const int64_t kMinRetransmissionTimeMs = 200;
-
-// We define an unsigned 16-bit floating point value, inspired by IEEE floats
-// (http://en.wikipedia.org/wiki/Half_precision_floating-point_format),
-// with 5-bit exponent (bias 1), 11-bit mantissa (effective 12 with hidden
-// bit) and denormals, but without signs, transfinites or fractions. Wire format
-// 16 bits (little-endian byte order) are split into exponent (high 5) and
-// mantissa (low 11) and decoded as:
-// uint64_t value;
-// if (exponent == 0) value = mantissa;
-// else value = (mantissa | 1 << 11) << (exponent - 1)
-const int kUFloat16ExponentBits = 5;
-const int kUFloat16MaxExponent = (1 << kUFloat16ExponentBits) - 2; // 30
-const int kUFloat16MantissaBits = 16 - kUFloat16ExponentBits; // 11
-const int kUFloat16MantissaEffectiveBits = kUFloat16MantissaBits + 1; // 12
-const uint64_t kUFloat16MaxValue = // 0x3FFC0000000
- ((UINT64_C(1) << kUFloat16MantissaEffectiveBits) - 1)
- << kUFloat16MaxExponent;
-
-// Default path ID.
-const QuicPathId kDefaultPathId = 0;
-// Invalid path ID.
-const QuicPathId kInvalidPathId = 0xff;
-
-// kDiversificationNonceSize is the size, in bytes, of the nonce that a server
-// may set in the packet header to ensure that its INITIAL keys are not
-// duplicated.
-const size_t kDiversificationNonceSize = 32;
-
-// The largest gap in packets we'll accept without closing the connection.
-// This will likely have to be tuned.
-const QuicPacketNumber kMaxPacketGap = 5000;
-
-enum TransmissionType : int8_t {
- NOT_RETRANSMISSION,
- FIRST_TRANSMISSION_TYPE = NOT_RETRANSMISSION,
- HANDSHAKE_RETRANSMISSION, // Retransmits due to handshake timeouts.
- ALL_UNACKED_RETRANSMISSION, // Retransmits all unacked packets.
- ALL_INITIAL_RETRANSMISSION, // Retransmits all initially encrypted packets.
- LOSS_RETRANSMISSION, // Retransmits due to loss detection.
- RTO_RETRANSMISSION, // Retransmits due to retransmit time out.
- TLP_RETRANSMISSION, // Tail loss probes.
- LAST_TRANSMISSION_TYPE = TLP_RETRANSMISSION,
-};
-
-enum HasRetransmittableData : int8_t {
- NO_RETRANSMITTABLE_DATA,
- HAS_RETRANSMITTABLE_DATA,
-};
-
-enum IsHandshake : int8_t { NOT_HANDSHAKE, IS_HANDSHAKE };
-
-enum class Perspective { IS_SERVER, IS_CLIENT };
-
-// Describes whether a ConnectionClose was originated by the peer.
-enum class ConnectionCloseSource { FROM_PEER, FROM_SELF };
-
-// Should a connection be closed silently or not.
-enum class ConnectionCloseBehavior {
- SILENT_CLOSE,
- SEND_CONNECTION_CLOSE_PACKET,
- SEND_CONNECTION_CLOSE_PACKET_WITH_NO_ACK
-};
-
-NET_EXPORT_PRIVATE std::ostream& operator<<(std::ostream& os,
- const Perspective& s);
-enum QuicFrameType {
- // Regular frame types. The values set here cannot change without the
- // introduction of a new QUIC version.
- PADDING_FRAME = 0,
- RST_STREAM_FRAME = 1,
- CONNECTION_CLOSE_FRAME = 2,
- GOAWAY_FRAME = 3,
- WINDOW_UPDATE_FRAME = 4,
- BLOCKED_FRAME = 5,
- STOP_WAITING_FRAME = 6,
- PING_FRAME = 7,
- PATH_CLOSE_FRAME = 8,
-
- // STREAM and ACK frames are special frames. They are encoded differently on
- // the wire and their values do not need to be stable.
- STREAM_FRAME,
- ACK_FRAME,
- // The path MTU discovery frame is encoded as a PING frame on the wire.
- MTU_DISCOVERY_FRAME,
- NUM_FRAME_TYPES
-};
-
-enum QuicConnectionIdLength {
- PACKET_0BYTE_CONNECTION_ID = 0,
- PACKET_8BYTE_CONNECTION_ID = 8
-};
-
-enum QuicPacketNumberLength : int8_t {
- PACKET_1BYTE_PACKET_NUMBER = 1,
- PACKET_2BYTE_PACKET_NUMBER = 2,
- PACKET_4BYTE_PACKET_NUMBER = 4,
- PACKET_6BYTE_PACKET_NUMBER = 6
-};
-
-// Used to indicate a QuicSequenceNumberLength using two flag bits.
-enum QuicPacketNumberLengthFlags {
- PACKET_FLAGS_1BYTE_PACKET = 0, // 00
- PACKET_FLAGS_2BYTE_PACKET = 1, // 01
- PACKET_FLAGS_4BYTE_PACKET = 1 << 1, // 10
- PACKET_FLAGS_6BYTE_PACKET = 1 << 1 | 1, // 11
-};
-
-// The public flags are specified in one byte.
-enum QuicPacketPublicFlags {
- PACKET_PUBLIC_FLAGS_NONE = 0,
-
- // Bit 0: Does the packet header contains version info?
- PACKET_PUBLIC_FLAGS_VERSION = 1 << 0,
-
- // Bit 1: Is this packet a public reset packet?
- PACKET_PUBLIC_FLAGS_RST = 1 << 1,
-
- // Bit 2: indicates the that public header includes a nonce.
- PACKET_PUBLIC_FLAGS_NONCE = 1 << 2,
-
- // Bit 3: indicates whether a ConnectionID is included.
- PACKET_PUBLIC_FLAGS_0BYTE_CONNECTION_ID = 0,
- PACKET_PUBLIC_FLAGS_8BYTE_CONNECTION_ID = 1 << 3,
-
- // QUIC_VERSION_32 and earlier use two bits for an 8 byte
- // connection id.
- PACKET_PUBLIC_FLAGS_8BYTE_CONNECTION_ID_OLD = 1 << 3 | 1 << 2,
-
- // Bits 4 and 5 describe the packet number length as follows:
- // --00----: 1 byte
- // --01----: 2 bytes
- // --10----: 4 bytes
- // --11----: 6 bytes
- PACKET_PUBLIC_FLAGS_1BYTE_PACKET = PACKET_FLAGS_1BYTE_PACKET << 4,
- PACKET_PUBLIC_FLAGS_2BYTE_PACKET = PACKET_FLAGS_2BYTE_PACKET << 4,
- PACKET_PUBLIC_FLAGS_4BYTE_PACKET = PACKET_FLAGS_4BYTE_PACKET << 4,
- PACKET_PUBLIC_FLAGS_6BYTE_PACKET = PACKET_FLAGS_6BYTE_PACKET << 4,
-
- // Bit 6: Does the packet header contain a path id?
- PACKET_PUBLIC_FLAGS_MULTIPATH = 1 << 6,
-
- // Reserved, unimplemented flags:
-
- // Bit 7: indicates the presence of a second flags byte.
- PACKET_PUBLIC_FLAGS_TWO_OR_MORE_BYTES = 1 << 7,
-
- // All bits set (bit 7 is not currently used): 01111111
- PACKET_PUBLIC_FLAGS_MAX = (1 << 7) - 1,
-};
-
-// The private flags are specified in one byte.
-enum QuicPacketPrivateFlags {
- PACKET_PRIVATE_FLAGS_NONE = 0,
-
- // Bit 0: Does this packet contain an entropy bit?
- PACKET_PRIVATE_FLAGS_ENTROPY = 1 << 0,
-
- // (bits 1-7 are not used): 00000001
- PACKET_PRIVATE_FLAGS_MAX = (1 << 1) - 1
-};
-
-// The available versions of QUIC. Guaranteed that the integer value of the enum
-// will match the version number.
-// When adding a new version to this enum you should add it to
-// kSupportedQuicVersions (if appropriate), and also add a new case to the
-// helper methods QuicVersionToQuicTag, QuicTagToQuicVersion, and
-// QuicVersionToString.
-enum QuicVersion {
- // Special case to indicate unknown/unsupported QUIC version.
- QUIC_VERSION_UNSUPPORTED = 0,
-
- QUIC_VERSION_32 = 32, // FEC related fields are removed from wire format.
- QUIC_VERSION_33 = 33, // Adds diversification nonces.
- QUIC_VERSION_34 = 34, // Deprecates entropy, removes private flag from packet
- // header, uses new ack and stop waiting wire format.
- QUIC_VERSION_35 = 35, // Allows endpoints to independently set stream limit.
- QUIC_VERSION_36 = 36, // Add support to force HOL blocking.
-
- // IMPORTANT: if you are adding to this std::list, follow the instructions at
- // http://sites/quic/adding-and-removing-versions
-};
-
-// This vector contains QUIC versions which we currently support.
-// This should be ordered such that the highest supported version is the first
-// element, with subsequent elements in descending order (versions can be
-// skipped as necessary).
-//
-// IMPORTANT: if you are adding to this list, follow the instructions at
-// http://sites/quic/adding-and-removing-versions
-static const QuicVersion kSupportedQuicVersions[] = {
- QUIC_VERSION_36, QUIC_VERSION_35, QUIC_VERSION_34, QUIC_VERSION_33,
- QUIC_VERSION_32};
-
-typedef std::vector<QuicVersion> QuicVersionVector;
-
-// Returns a vector of QUIC versions in kSupportedQuicVersions.
-NET_EXPORT_PRIVATE QuicVersionVector AllSupportedVersions();
-
-// Returns a vector of QUIC versions from kSupportedQuicVersions which exclude
-// any versions which are disabled by flags.
-NET_EXPORT_PRIVATE QuicVersionVector CurrentSupportedVersions();
-
-// Returns a vector of QUIC versions from |versions| which exclude any versions
-// which are disabled by flags.
-NET_EXPORT_PRIVATE QuicVersionVector
-FilterSupportedVersions(QuicVersionVector versions);
-
-// Returns QUIC version of |index| in result of |versions|. Returns
-// QUIC_VERSION_UNSUPPORTED if |index| is out of bounds.
-NET_EXPORT_PRIVATE QuicVersionVector
-VersionOfIndex(const QuicVersionVector& versions, int index);
-
-// QuicTag is written to and read from the wire, but we prefer to use
-// the more readable QuicVersion at other levels.
-// Helper function which translates from a QuicVersion to a QuicTag. Returns 0
-// if QuicVersion is unsupported.
-NET_EXPORT_PRIVATE QuicTag QuicVersionToQuicTag(const QuicVersion version);
-
-// Returns appropriate QuicVersion from a QuicTag.
-// Returns QUIC_VERSION_UNSUPPORTED if version_tag cannot be understood.
-NET_EXPORT_PRIVATE QuicVersion QuicTagToQuicVersion(const QuicTag version_tag);
-
-// Helper function which translates from a QuicVersion to a string.
-// Returns strings corresponding to enum names (e.g. QUIC_VERSION_6).
-NET_EXPORT_PRIVATE std::string QuicVersionToString(const QuicVersion version);
-
-// Returns comma separated list of string representations of QuicVersion enum
-// values in the supplied |versions| vector.
-NET_EXPORT_PRIVATE std::string QuicVersionVectorToString(
- const QuicVersionVector& versions);
-
-// Version and Crypto tags are written to the wire with a big-endian
-// representation of the name of the tag. For example
-// the client hello tag (CHLO) will be written as the
-// following 4 bytes: 'C' 'H' 'L' 'O'. Since it is
-// stored in memory as a little endian uint32_t, we need
-// to reverse the order of the bytes.
-
-// MakeQuicTag returns a value given the four bytes. For example:
-// MakeQuicTag('C', 'H', 'L', 'O');
-NET_EXPORT_PRIVATE QuicTag MakeQuicTag(char a, char b, char c, char d);
-
-// Returns true if the tag vector contains the specified tag.
-NET_EXPORT_PRIVATE bool ContainsQuicTag(const QuicTagVector& tag_vector,
- QuicTag tag);
-
-// Size in bytes of the data packet header.
-NET_EXPORT_PRIVATE size_t GetPacketHeaderSize(QuicVersion version,
- const QuicPacketHeader& header);
-
-NET_EXPORT_PRIVATE size_t
-GetPacketHeaderSize(QuicVersion version,
- QuicConnectionIdLength connection_id_length,
- bool include_version,
- bool include_path_id,
- bool include_diversification_nonce,
- QuicPacketNumberLength packet_number_length);
-
-// Index of the first byte in a QUIC packet of encrypted data.
-NET_EXPORT_PRIVATE size_t
-GetStartOfEncryptedData(QuicVersion version, const QuicPacketHeader& header);
-
-NET_EXPORT_PRIVATE size_t
-GetStartOfEncryptedData(QuicVersion version,
- QuicConnectionIdLength connection_id_length,
- bool include_version,
- bool include_path_id,
- bool include_diversification_nonce,
- QuicPacketNumberLength packet_number_length);
-
-enum QuicRstStreamErrorCode {
- // Complete response has been sent, sending a RST to ask the other endpoint
- // to stop sending request data without discarding the response.
- QUIC_STREAM_NO_ERROR = 0,
-
- // There was some error which halted stream processing.
- QUIC_ERROR_PROCESSING_STREAM,
- // We got two fin or reset offsets which did not match.
- QUIC_MULTIPLE_TERMINATION_OFFSETS,
- // We got bad payload and can not respond to it at the protocol level.
- QUIC_BAD_APPLICATION_PAYLOAD,
- // Stream closed due to connection error. No reset frame is sent when this
- // happens.
- QUIC_STREAM_CONNECTION_ERROR,
- // GoAway frame sent. No more stream can be created.
- QUIC_STREAM_PEER_GOING_AWAY,
- // The stream has been cancelled.
- QUIC_STREAM_CANCELLED,
- // Closing stream locally, sending a RST to allow for proper flow control
- // accounting. Sent in response to a RST from the peer.
- QUIC_RST_ACKNOWLEDGEMENT,
- // Receiver refused to create the stream (because its limit on open streams
- // has been reached). The sender should retry the request later (using
- // another stream).
- QUIC_REFUSED_STREAM,
- // Invalid URL in PUSH_PROMISE request header.
- QUIC_INVALID_PROMISE_URL,
- // Server is not authoritative for this URL.
- QUIC_UNAUTHORIZED_PROMISE_URL,
- // Can't have more than one active PUSH_PROMISE per URL.
- QUIC_DUPLICATE_PROMISE_URL,
- // Vary check failed.
- QUIC_PROMISE_VARY_MISMATCH,
- // Only GET and HEAD methods allowed.
- QUIC_INVALID_PROMISE_METHOD,
- // The push stream is unclaimed and timed out.
- QUIC_PUSH_STREAM_TIMED_OUT,
- // Received headers were too large.
- QUIC_HEADERS_TOO_LARGE,
- // No error. Used as bound while iterating.
- QUIC_STREAM_LAST_ERROR,
-};
-// QUIC error codes are encoded to a single octet on-the-wire.
-static_assert(static_cast<int>(QUIC_STREAM_LAST_ERROR) <=
- std::numeric_limits<uint8_t>::max(),
- "QuicErrorCode exceeds single octet");
-
-// These values must remain stable as they are uploaded to UMA histograms.
-// To add a new error code, use the current value of QUIC_LAST_ERROR and
-// increment QUIC_LAST_ERROR.
-enum QuicErrorCode {
- QUIC_NO_ERROR = 0,
-
- // Connection has reached an invalid state.
- QUIC_INTERNAL_ERROR = 1,
- // There were data frames after the a fin or reset.
- QUIC_STREAM_DATA_AFTER_TERMINATION = 2,
- // Control frame is malformed.
- QUIC_INVALID_PACKET_HEADER = 3,
- // Frame data is malformed.
- QUIC_INVALID_FRAME_DATA = 4,
- // The packet contained no payload.
- QUIC_MISSING_PAYLOAD = 48,
- // FEC data is malformed.
- QUIC_INVALID_FEC_DATA = 5,
- // STREAM frame data is malformed.
- QUIC_INVALID_STREAM_DATA = 46,
- // STREAM frame data overlaps with buffered data.
- QUIC_OVERLAPPING_STREAM_DATA = 87,
- // Received STREAM frame data is not encrypted.
- QUIC_UNENCRYPTED_STREAM_DATA = 61,
- // Attempt to send unencrypted STREAM frame.
- QUIC_ATTEMPT_TO_SEND_UNENCRYPTED_STREAM_DATA = 88,
- // Received a frame which is likely the result of memory corruption.
- QUIC_MAYBE_CORRUPTED_MEMORY = 89,
- // FEC frame data is not encrypted.
- QUIC_UNENCRYPTED_FEC_DATA = 77,
- // RST_STREAM frame data is malformed.
- QUIC_INVALID_RST_STREAM_DATA = 6,
- // CONNECTION_CLOSE frame data is malformed.
- QUIC_INVALID_CONNECTION_CLOSE_DATA = 7,
- // GOAWAY frame data is malformed.
- QUIC_INVALID_GOAWAY_DATA = 8,
- // WINDOW_UPDATE frame data is malformed.
- QUIC_INVALID_WINDOW_UPDATE_DATA = 57,
- // BLOCKED frame data is malformed.
- QUIC_INVALID_BLOCKED_DATA = 58,
- // STOP_WAITING frame data is malformed.
- QUIC_INVALID_STOP_WAITING_DATA = 60,
- // PATH_CLOSE frame data is malformed.
- QUIC_INVALID_PATH_CLOSE_DATA = 78,
- // ACK frame data is malformed.
- QUIC_INVALID_ACK_DATA = 9,
-
- // Version negotiation packet is malformed.
- QUIC_INVALID_VERSION_NEGOTIATION_PACKET = 10,
- // Public RST packet is malformed.
- QUIC_INVALID_PUBLIC_RST_PACKET = 11,
- // There was an error decrypting.
- QUIC_DECRYPTION_FAILURE = 12,
- // There was an error encrypting.
- QUIC_ENCRYPTION_FAILURE = 13,
- // The packet exceeded kMaxPacketSize.
- QUIC_PACKET_TOO_LARGE = 14,
- // The peer is going away. May be a client or server.
- QUIC_PEER_GOING_AWAY = 16,
- // A stream ID was invalid.
- QUIC_INVALID_STREAM_ID = 17,
- // A priority was invalid.
- QUIC_INVALID_PRIORITY = 49,
- // Too many streams already open.
- QUIC_TOO_MANY_OPEN_STREAMS = 18,
- // The peer created too many available streams.
- QUIC_TOO_MANY_AVAILABLE_STREAMS = 76,
- // Received public reset for this connection.
- QUIC_PUBLIC_RESET = 19,
- // Invalid protocol version.
- QUIC_INVALID_VERSION = 20,
-
- // The Header ID for a stream was too far from the previous.
- QUIC_INVALID_HEADER_ID = 22,
- // Negotiable parameter received during handshake had invalid value.
- QUIC_INVALID_NEGOTIATED_VALUE = 23,
- // There was an error decompressing data.
- QUIC_DECOMPRESSION_FAILURE = 24,
- // The connection timed out due to no network activity.
- QUIC_NETWORK_IDLE_TIMEOUT = 25,
- // The connection timed out waiting for the handshake to complete.
- QUIC_HANDSHAKE_TIMEOUT = 67,
- // There was an error encountered migrating addresses.
- QUIC_ERROR_MIGRATING_ADDRESS = 26,
- // There was an error encountered migrating port only.
- QUIC_ERROR_MIGRATING_PORT = 86,
- // There was an error while writing to the socket.
- QUIC_PACKET_WRITE_ERROR = 27,
- // There was an error while reading from the socket.
- QUIC_PACKET_READ_ERROR = 51,
- // We received a STREAM_FRAME with no data and no fin flag set.
- QUIC_EMPTY_STREAM_FRAME_NO_FIN = 50,
- // We received invalid data on the headers stream.
- QUIC_INVALID_HEADERS_STREAM_DATA = 56,
- // The peer received too much data, violating flow control.
- QUIC_FLOW_CONTROL_RECEIVED_TOO_MUCH_DATA = 59,
- // The peer sent too much data, violating flow control.
- QUIC_FLOW_CONTROL_SENT_TOO_MUCH_DATA = 63,
- // The peer received an invalid flow control window.
- QUIC_FLOW_CONTROL_INVALID_WINDOW = 64,
- // The connection has been IP pooled into an existing connection.
- QUIC_CONNECTION_IP_POOLED = 62,
- // The connection has too many outstanding sent packets.
- QUIC_TOO_MANY_OUTSTANDING_SENT_PACKETS = 68,
- // The connection has too many outstanding received packets.
- QUIC_TOO_MANY_OUTSTANDING_RECEIVED_PACKETS = 69,
- // The quic connection has been cancelled.
- QUIC_CONNECTION_CANCELLED = 70,
- // Disabled QUIC because of high packet loss rate.
- QUIC_BAD_PACKET_LOSS_RATE = 71,
- // Disabled QUIC because of too many PUBLIC_RESETs post handshake.
- QUIC_PUBLIC_RESETS_POST_HANDSHAKE = 73,
- // Disabled QUIC because of too many timeouts with streams open.
- QUIC_TIMEOUTS_WITH_OPEN_STREAMS = 74,
- // Closed because we failed to serialize a packet.
- QUIC_FAILED_TO_SERIALIZE_PACKET = 75,
- // QUIC timed out after too many RTOs.
- QUIC_TOO_MANY_RTOS = 85,
-
- // Crypto errors.
-
- // Hanshake failed.
- QUIC_HANDSHAKE_FAILED = 28,
- // Handshake message contained out of order tags.
- QUIC_CRYPTO_TAGS_OUT_OF_ORDER = 29,
- // Handshake message contained too many entries.
- QUIC_CRYPTO_TOO_MANY_ENTRIES = 30,
- // Handshake message contained an invalid value length.
- QUIC_CRYPTO_INVALID_VALUE_LENGTH = 31,
- // A crypto message was received after the handshake was complete.
- QUIC_CRYPTO_MESSAGE_AFTER_HANDSHAKE_COMPLETE = 32,
- // A crypto message was received with an illegal message tag.
- QUIC_INVALID_CRYPTO_MESSAGE_TYPE = 33,
- // A crypto message was received with an illegal parameter.
- QUIC_INVALID_CRYPTO_MESSAGE_PARAMETER = 34,
- // An invalid channel id signature was supplied.
- QUIC_INVALID_CHANNEL_ID_SIGNATURE = 52,
- // A crypto message was received with a mandatory parameter missing.
- QUIC_CRYPTO_MESSAGE_PARAMETER_NOT_FOUND = 35,
- // A crypto message was received with a parameter that has no overlap
- // with the local parameter.
- QUIC_CRYPTO_MESSAGE_PARAMETER_NO_OVERLAP = 36,
- // A crypto message was received that contained a parameter with too few
- // values.
- QUIC_CRYPTO_MESSAGE_INDEX_NOT_FOUND = 37,
- // A demand for an unsupport proof type was received.
- QUIC_UNSUPPORTED_PROOF_DEMAND = 94,
- // An internal error occured in crypto processing.
- QUIC_CRYPTO_INTERNAL_ERROR = 38,
- // A crypto handshake message specified an unsupported version.
- QUIC_CRYPTO_VERSION_NOT_SUPPORTED = 39,
- // A crypto handshake message resulted in a stateless reject.
- QUIC_CRYPTO_HANDSHAKE_STATELESS_REJECT = 72,
- // There was no intersection between the crypto primitives supported by the
- // peer and ourselves.
- QUIC_CRYPTO_NO_SUPPORT = 40,
- // The server rejected our client hello messages too many times.
- QUIC_CRYPTO_TOO_MANY_REJECTS = 41,
- // The client rejected the server's certificate chain or signature.
- QUIC_PROOF_INVALID = 42,
- // A crypto message was received with a duplicate tag.
- QUIC_CRYPTO_DUPLICATE_TAG = 43,
- // A crypto message was received with the wrong encryption level (i.e. it
- // should have been encrypted but was not.)
- QUIC_CRYPTO_ENCRYPTION_LEVEL_INCORRECT = 44,
- // The server config for a server has expired.
- QUIC_CRYPTO_SERVER_CONFIG_EXPIRED = 45,
- // We failed to setup the symmetric keys for a connection.
- QUIC_CRYPTO_SYMMETRIC_KEY_SETUP_FAILED = 53,
- // A handshake message arrived, but we are still validating the
- // previous handshake message.
- QUIC_CRYPTO_MESSAGE_WHILE_VALIDATING_CLIENT_HELLO = 54,
- // A server config update arrived before the handshake is complete.
- QUIC_CRYPTO_UPDATE_BEFORE_HANDSHAKE_COMPLETE = 65,
- // CHLO cannot fit in one packet.
- QUIC_CRYPTO_CHLO_TOO_LARGE = 90,
- // This connection involved a version negotiation which appears to have been
- // tampered with.
- QUIC_VERSION_NEGOTIATION_MISMATCH = 55,
-
- // Multipath errors.
- // Multipath is not enabled, but a packet with multipath flag on is received.
- QUIC_BAD_MULTIPATH_FLAG = 79,
- // A path is supposed to exist but does not.
- QUIC_MULTIPATH_PATH_DOES_NOT_EXIST = 91,
- // A path is supposed to be active but is not.
- QUIC_MULTIPATH_PATH_NOT_ACTIVE = 92,
-
- // IP address changed causing connection close.
- QUIC_IP_ADDRESS_CHANGED = 80,
-
- // Connection migration errors.
- // Network changed, but connection had no migratable streams.
- QUIC_CONNECTION_MIGRATION_NO_MIGRATABLE_STREAMS = 81,
- // Connection changed networks too many times.
- QUIC_CONNECTION_MIGRATION_TOO_MANY_CHANGES = 82,
- // Connection migration was attempted, but there was no new network to
- // migrate to.
- QUIC_CONNECTION_MIGRATION_NO_NEW_NETWORK = 83,
- // Network changed, but connection had one or more non-migratable streams.
- QUIC_CONNECTION_MIGRATION_NON_MIGRATABLE_STREAM = 84,
-
- // Stream frames arrived too discontiguously so that stream sequencer buffer
- // maintains too many gaps.
- QUIC_TOO_MANY_FRAME_GAPS = 93,
-
- // Sequencer buffer get into weird state where continuing read/write will lead
- // to crash.
- QUIC_STREAM_SEQUENCER_INVALID_STATE = 95,
-
- // Connection closed because of server hits max number of sessions allowed.
- // TODO(fayang): Add monitoring for QUIC_TOO_MANY_SESSIONS_ON_SERVER.
- QUIC_TOO_MANY_SESSIONS_ON_SERVER = 96,
-
- // No error. Used as bound while iterating.
- QUIC_LAST_ERROR = 97,
-};
-
-typedef std::array<char, 32> DiversificationNonce;
-
-struct NET_EXPORT_PRIVATE QuicPacketPublicHeader {
- QuicPacketPublicHeader();
- explicit QuicPacketPublicHeader(const QuicPacketPublicHeader& other);
- ~QuicPacketPublicHeader();
-
- // Universal header. All QuicPacket headers will have a connection_id and
- // public flags.
- QuicConnectionId connection_id;
- QuicConnectionIdLength connection_id_length;
- bool multipath_flag;
- bool reset_flag;
- bool version_flag;
- QuicPacketNumberLength packet_number_length;
- QuicVersionVector versions;
- // nonce contains an optional, 32-byte nonce value. If not included in the
- // packet, |nonce| will be empty.
- DiversificationNonce* nonce;
-};
-
-// An integer which cannot be a packet number.
-const QuicPacketNumber kInvalidPacketNumber = 0;
-
-// Header for Data packets.
-struct NET_EXPORT_PRIVATE QuicPacketHeader {
- QuicPacketHeader();
- explicit QuicPacketHeader(const QuicPacketPublicHeader& header);
- QuicPacketHeader(const QuicPacketHeader& other);
-
- NET_EXPORT_PRIVATE friend std::ostream& operator<<(std::ostream& os,
- const QuicPacketHeader& s);
-
- QuicPacketPublicHeader public_header;
- QuicPacketNumber packet_number;
- QuicPathId path_id;
- bool entropy_flag;
- QuicPacketEntropyHash entropy_hash;
-};
-
-struct NET_EXPORT_PRIVATE QuicPublicResetPacket {
- QuicPublicResetPacket();
- explicit QuicPublicResetPacket(const QuicPacketPublicHeader& header);
-
- QuicPacketPublicHeader public_header;
- QuicPublicResetNonceProof nonce_proof;
- // TODO(fayang): remove rejected_packet_number when deprecating
- // FLAGS_quic_remove_packet_number_from_public_reset.
- QuicPacketNumber rejected_packet_number;
- IPEndPoint client_address;
-};
-
-enum QuicVersionNegotiationState {
- START_NEGOTIATION = 0,
- // Server-side this implies we've sent a version negotiation packet and are
- // waiting on the client to select a compatible version. Client-side this
- // implies we've gotten a version negotiation packet, are retransmitting the
- // initial packets with a supported version and are waiting for our first
- // packet from the server.
- NEGOTIATION_IN_PROGRESS,
- // This indicates this endpoint has received a packet from the peer with a
- // version this endpoint supports. Version negotiation is complete, and the
- // version number will no longer be sent with future packets.
- NEGOTIATED_VERSION
-};
-
-typedef QuicPacketPublicHeader QuicVersionNegotiationPacket;
-
-// A padding frame contains no payload.
-struct NET_EXPORT_PRIVATE QuicPaddingFrame {
- QuicPaddingFrame() : num_padding_bytes(-1) {}
- explicit QuicPaddingFrame(int num_padding_bytes)
- : num_padding_bytes(num_padding_bytes) {}
-
- NET_EXPORT_PRIVATE friend std::ostream& operator<<(std::ostream& os,
- const QuicPaddingFrame& s);
-
- // -1: full padding to the end of a max-sized packet
- // otherwise: only pad up to num_padding_bytes bytes
- int num_padding_bytes;
-};
-
-// A ping frame contains no payload, though it is retransmittable,
-// and ACK'd just like other normal frames.
-struct NET_EXPORT_PRIVATE QuicPingFrame {};
-
-// A path MTU discovery frame contains no payload and is serialized as a ping
-// frame.
-struct NET_EXPORT_PRIVATE QuicMtuDiscoveryFrame {};
-
-class NET_EXPORT_PRIVATE QuicBufferAllocator {
- public:
- virtual ~QuicBufferAllocator();
-
- // Returns or allocates a new buffer of |size|. Never returns null.
- virtual char* New(size_t size) = 0;
-
- // Returns or allocates a new buffer of |size| if |flag_enable| is true.
- // Otherwise, returns a buffer that is compatible with this class directly
- // with operator new. Never returns null.
- virtual char* New(size_t size, bool flag_enable) = 0;
-
- // Releases a buffer.
- virtual void Delete(char* buffer) = 0;
-
- // Marks the allocator as being idle. Serves as a hint to notify the allocator
- // that it should release any resources it's still holding on to.
- virtual void MarkAllocatorIdle() {}
-};
-
-// Deleter for stream buffers. Copyable to support platforms where the deleter
-// of a unique_ptr must be copyable. Otherwise it would be nice for this to be
-// move-only.
-class NET_EXPORT_PRIVATE StreamBufferDeleter {
- public:
- StreamBufferDeleter() : allocator_(nullptr) {}
- explicit StreamBufferDeleter(QuicBufferAllocator* allocator)
- : allocator_(allocator) {}
-
- // Deletes |buffer| using |allocator_|.
- void operator()(char* buffer) const;
-
- private:
- // Not owned; must be valid so long as the buffer stored in the unique_ptr
- // that owns |this| is valid.
- QuicBufferAllocator* allocator_;
-};
-
-using UniqueStreamBuffer = std::unique_ptr<char[], StreamBufferDeleter>;
-
-// Allocates memory of size |size| using |allocator| for a QUIC stream buffer.
-NET_EXPORT_PRIVATE UniqueStreamBuffer
-NewStreamBuffer(QuicBufferAllocator* allocator, size_t size);
-
-struct NET_EXPORT_PRIVATE QuicStreamFrame {
- QuicStreamFrame();
- QuicStreamFrame(QuicStreamId stream_id,
- bool fin,
- QuicStreamOffset offset,
- base::StringPiece data);
- QuicStreamFrame(QuicStreamId stream_id,
- bool fin,
- QuicStreamOffset offset,
- QuicPacketLength data_length,
- UniqueStreamBuffer buffer);
- ~QuicStreamFrame();
-
- NET_EXPORT_PRIVATE friend std::ostream& operator<<(std::ostream& os,
- const QuicStreamFrame& s);
-
- QuicStreamId stream_id;
- bool fin;
- QuicPacketLength data_length;
- const char* data_buffer;
- QuicStreamOffset offset; // Location of this data in the stream.
- // nullptr when the QuicStreamFrame is received, and non-null when sent.
- UniqueStreamBuffer buffer;
-
- private:
- QuicStreamFrame(QuicStreamId stream_id,
- bool fin,
- QuicStreamOffset offset,
- const char* data_buffer,
- QuicPacketLength data_length,
- UniqueStreamBuffer buffer);
-
- DISALLOW_COPY_AND_ASSIGN(QuicStreamFrame);
-};
-static_assert(sizeof(QuicStreamFrame) <= 64,
- "Keep the QuicStreamFrame size to a cacheline.");
-
-typedef std::vector<std::pair<QuicPacketNumber, QuicTime>> PacketTimeVector;
-
-struct NET_EXPORT_PRIVATE QuicStopWaitingFrame {
- QuicStopWaitingFrame();
- ~QuicStopWaitingFrame();
-
- NET_EXPORT_PRIVATE friend std::ostream& operator<<(
- std::ostream& os,
- const QuicStopWaitingFrame& s);
- // Path which this stop waiting frame belongs to.
- QuicPathId path_id;
- // Entropy hash of all packets up to, but not including, the least unacked
- // packet.
- QuicPacketEntropyHash entropy_hash;
- // The lowest packet we've sent which is unacked, and we expect an ack for.
- QuicPacketNumber least_unacked;
-};
-
-// A sequence of packet numbers where each number is unique. Intended to be used
-// in a sliding window fashion, where smaller old packet numbers are removed and
-// larger new packet numbers are added, with the occasional random access.
-class NET_EXPORT_PRIVATE PacketNumberQueue {
- public:
- using const_iterator = IntervalSet<QuicPacketNumber>::const_iterator;
- using const_reverse_iterator =
- IntervalSet<QuicPacketNumber>::const_reverse_iterator;
-
- PacketNumberQueue();
- PacketNumberQueue(const PacketNumberQueue& other);
- // TODO(rtenneti): on windows RValue reference gives errors.
- // PacketNumberQueue(PacketNumberQueue&& other);
- ~PacketNumberQueue();
-
- PacketNumberQueue& operator=(const PacketNumberQueue& other);
- // PacketNumberQueue& operator=(PacketNumberQueue&& other);
-
- // Adds |packet_number| to the set of packets in the queue.
- void Add(QuicPacketNumber packet_number);
-
- // Adds packets between [lower, higher) to the set of packets in the queue. It
- // is undefined behavior to call this with |higher| < |lower|.
- void Add(QuicPacketNumber lower, QuicPacketNumber higher);
-
- // Removes |packet_number| from the set of packets in the queue.
- void Remove(QuicPacketNumber packet_number);
-
- // Removes packets numbers between [lower, higher) to the set of packets in
- // the queue. It is undefined behavior to call this with |higher| < |lower|.
- void Remove(QuicPacketNumber lower, QuicPacketNumber higher);
-
- // Removes packets with values less than |higher| from the set of packets in
- // the queue. Returns true if packets were removed.
- bool RemoveUpTo(QuicPacketNumber higher);
-
- // Mutates packet number set so that it contains only those packet numbers
- // from minimum to maximum packet number not currently in the set. Do nothing
- // if packet number set is empty.
- void Complement();
-
- // Returns true if the queue contains |packet_number|.
- bool Contains(QuicPacketNumber packet_number) const;
-
- // Returns true if the queue is empty.
- bool Empty() const;
-
- // Returns the minimum packet number stored in the queue. It is undefined
- // behavior to call this if the queue is empty.
- QuicPacketNumber Min() const;
-
- // Returns the maximum packet number stored in the queue. It is undefined
- // behavior to call this if the queue is empty.
- QuicPacketNumber Max() const;
-
- // Returns the number of unique packets stored in the queue. Inefficient; only
- // exposed for testing.
- size_t NumPacketsSlow() const;
-
- // Returns the number of disjoint packet number intervals contained in the
- // queue.
- size_t NumIntervals() const;
-
- // Returns the length of last interval.
- QuicPacketNumber LastIntervalLength() const;
-
- // Returns iterators over the packet number intervals.
- const_iterator begin() const;
- const_iterator end() const;
- const_reverse_iterator rbegin() const;
- const_reverse_iterator rend() const;
- const_iterator lower_bound(QuicPacketNumber packet_number) const;
-
- NET_EXPORT_PRIVATE friend std::ostream& operator<<(
- std::ostream& os,
- const PacketNumberQueue& q);
-
- private:
- IntervalSet<QuicPacketNumber> packet_number_intervals_;
-};
-
-struct NET_EXPORT_PRIVATE QuicAckFrame {
- QuicAckFrame();
- QuicAckFrame(const QuicAckFrame& other);
- ~QuicAckFrame();
-
- NET_EXPORT_PRIVATE friend std::ostream& operator<<(std::ostream& os,
- const QuicAckFrame& s);
-
- // The highest packet number we've observed from the peer.
- //
- // In general, this should be the largest packet number we've received. In
- // the case of truncated acks, we may have to advertise a lower "upper bound"
- // than largest received, to avoid implicitly acking missing packets that
- // don't fit in the missing packet list due to size limitations. In this
- // case, largest_observed may be a packet which is also in the missing packets
- // list.
- QuicPacketNumber largest_observed;
-
- // Time elapsed since largest_observed was received until this Ack frame was
- // sent.
- QuicTime::Delta ack_delay_time;
-
- // Vector of <packet_number, time> for when packets arrived.
- PacketTimeVector received_packet_times;
-
- // Set of packets.
- PacketNumberQueue packets;
-
- // Path which this ack belongs to.
- QuicPathId path_id;
-
- // Entropy hash of all packets up to largest observed not including missing
- // packets.
- QuicPacketEntropyHash entropy_hash;
-
- // Whether the ack had to be truncated when sent.
- bool is_truncated;
-
- // If true, |packets| express missing packets. Otherwise, |packets| express
- // received packets.
- bool missing;
-};
-
-// True if the packet number is greater than largest_observed or is listed
-// as missing.
-// Always returns false for packet numbers less than least_unacked.
-bool NET_EXPORT_PRIVATE
-IsAwaitingPacket(const QuicAckFrame& ack_frame,
- QuicPacketNumber packet_number,
- QuicPacketNumber peer_least_packet_awaiting_ack);
-
-// Defines for all types of congestion control algorithms that can be used in
-// QUIC. Note that this is separate from the congestion feedback type -
-// some congestion control algorithms may use the same feedback type
-// (Reno and Cubic are the classic example for that).
-enum CongestionControlType {
- kCubic,
- kCubicBytes,
- kReno,
- kRenoBytes,
- kBBR,
-};
-
-enum LossDetectionType {
- kNack, // Used to mimic TCP's loss detection.
- kTime, // Time based loss detection.
- kAdaptiveTime, // Adaptive time based loss detection.
- kLazyFack, // Nack based but with FACK disabled for the first ack.
-};
-
-struct NET_EXPORT_PRIVATE QuicRstStreamFrame {
- QuicRstStreamFrame();
- QuicRstStreamFrame(QuicStreamId stream_id,
- QuicRstStreamErrorCode error_code,
- QuicStreamOffset bytes_written);
-
- NET_EXPORT_PRIVATE friend std::ostream& operator<<(
- std::ostream& os,
- const QuicRstStreamFrame& r);
-
- QuicStreamId stream_id;
- QuicRstStreamErrorCode error_code;
-
- // Used to update flow control windows. On termination of a stream, both
- // endpoints must inform the peer of the number of bytes they have sent on
- // that stream. This can be done through normal termination (data packet with
- // FIN) or through a RST.
- QuicStreamOffset byte_offset;
-};
-
-struct NET_EXPORT_PRIVATE QuicConnectionCloseFrame {
- QuicConnectionCloseFrame();
-
- NET_EXPORT_PRIVATE friend std::ostream& operator<<(
- std::ostream& os,
- const QuicConnectionCloseFrame& c);
-
- QuicErrorCode error_code;
- std::string error_details;
-};
-
-struct NET_EXPORT_PRIVATE QuicGoAwayFrame {
- QuicGoAwayFrame();
- QuicGoAwayFrame(QuicErrorCode error_code,
- QuicStreamId last_good_stream_id,
- const std::string& reason);
-
- NET_EXPORT_PRIVATE friend std::ostream& operator<<(std::ostream& os,
- const QuicGoAwayFrame& g);
-
- QuicErrorCode error_code;
- QuicStreamId last_good_stream_id;
- std::string reason_phrase;
-};
-
-// Flow control updates per-stream and at the connection levoel.
-// Based on SPDY's WINDOW_UPDATE frame, but uses an absolute byte offset rather
-// than a window delta.
-// TODO(rjshade): A possible future optimization is to make stream_id and
-// byte_offset variable length, similar to stream frames.
-struct NET_EXPORT_PRIVATE QuicWindowUpdateFrame {
- QuicWindowUpdateFrame() {}
- QuicWindowUpdateFrame(QuicStreamId stream_id, QuicStreamOffset byte_offset);
-
- NET_EXPORT_PRIVATE friend std::ostream& operator<<(
- std::ostream& os,
- const QuicWindowUpdateFrame& w);
-
- // The stream this frame applies to. 0 is a special case meaning the overall
- // connection rather than a specific stream.
- QuicStreamId stream_id;
-
- // Byte offset in the stream or connection. The receiver of this frame must
- // not send data which would result in this offset being exceeded.
- QuicStreamOffset byte_offset;
-};
-
-// The BLOCKED frame is used to indicate to the remote endpoint that this
-// endpoint believes itself to be flow-control blocked but otherwise ready to
-// send data. The BLOCKED frame is purely advisory and optional.
-// Based on SPDY's BLOCKED frame (undocumented as of 2014-01-28).
-struct NET_EXPORT_PRIVATE QuicBlockedFrame {
- QuicBlockedFrame() {}
- explicit QuicBlockedFrame(QuicStreamId stream_id);
-
- NET_EXPORT_PRIVATE friend std::ostream& operator<<(std::ostream& os,
- const QuicBlockedFrame& b);
-
- // The stream this frame applies to. 0 is a special case meaning the overall
- // connection rather than a specific stream.
- QuicStreamId stream_id;
-};
-
-// The PATH_CLOSE frame is used to explicitly close a path. Both endpoints can
-// send a PATH_CLOSE frame to initiate a path termination. A path is considered
-// to be closed either a PATH_CLOSE frame is sent or received. An endpoint drops
-// receive side of a closed path, and packets with retransmittable frames on a
-// closed path are marked as retransmissions which will be transmitted on other
-// paths.
-struct NET_EXPORT_PRIVATE QuicPathCloseFrame {
- QuicPathCloseFrame() {}
- explicit QuicPathCloseFrame(QuicPathId path_id);
-
- NET_EXPORT_PRIVATE friend std::ostream& operator<<(
- std::ostream& os,
- const QuicPathCloseFrame& p);
-
- QuicPathId path_id;
-};
-
-// EncryptionLevel enumerates the stages of encryption that a QUIC connection
-// progresses through. When retransmitting a packet, the encryption level needs
-// to be specified so that it is retransmitted at a level which the peer can
-// understand.
-enum EncryptionLevel : int8_t {
- ENCRYPTION_NONE = 0,
- ENCRYPTION_INITIAL = 1,
- ENCRYPTION_FORWARD_SECURE = 2,
-
- NUM_ENCRYPTION_LEVELS,
-};
-
-enum PeerAddressChangeType {
- // IP address and port remain unchanged.
- NO_CHANGE,
- // Port changed, but IP address remains unchanged.
- PORT_CHANGE,
- // IPv4 address changed, but within the /24 subnet (port may have changed.)
- IPV4_SUBNET_CHANGE,
- // IPv4 address changed, excluding /24 subnet change (port may have changed.)
- IPV4_TO_IPV4_CHANGE,
- // IP address change from an IPv4 to an IPv6 address (port may have changed.)
- IPV4_TO_IPV6_CHANGE,
- // IP address change from an IPv6 to an IPv4 address (port may have changed.)
- IPV6_TO_IPV4_CHANGE,
- // IP address change from an IPv6 to an IPv6 address (port may have changed.)
- IPV6_TO_IPV6_CHANGE,
-};
-
-struct NET_EXPORT_PRIVATE QuicFrame {
- QuicFrame();
- explicit QuicFrame(QuicPaddingFrame padding_frame);
- explicit QuicFrame(QuicMtuDiscoveryFrame frame);
- explicit QuicFrame(QuicPingFrame frame);
-
- explicit QuicFrame(QuicStreamFrame* stream_frame);
- explicit QuicFrame(QuicAckFrame* frame);
- explicit QuicFrame(QuicRstStreamFrame* frame);
- explicit QuicFrame(QuicConnectionCloseFrame* frame);
- explicit QuicFrame(QuicStopWaitingFrame* frame);
- explicit QuicFrame(QuicGoAwayFrame* frame);
- explicit QuicFrame(QuicWindowUpdateFrame* frame);
- explicit QuicFrame(QuicBlockedFrame* frame);
- explicit QuicFrame(QuicPathCloseFrame* frame);
-
- NET_EXPORT_PRIVATE friend std::ostream& operator<<(std::ostream& os,
- const QuicFrame& frame);
-
- QuicFrameType type;
- union {
- // Frames smaller than a pointer are inline.
- QuicPaddingFrame padding_frame;
- QuicMtuDiscoveryFrame mtu_discovery_frame;
- QuicPingFrame ping_frame;
-
- // Frames larger than a pointer.
- QuicStreamFrame* stream_frame;
- QuicAckFrame* ack_frame;
- QuicStopWaitingFrame* stop_waiting_frame;
- QuicRstStreamFrame* rst_stream_frame;
- QuicConnectionCloseFrame* connection_close_frame;
- QuicGoAwayFrame* goaway_frame;
- QuicWindowUpdateFrame* window_update_frame;
- QuicBlockedFrame* blocked_frame;
- QuicPathCloseFrame* path_close_frame;
- };
-};
-// QuicFrameType consumes 8 bytes with padding.
-static_assert(sizeof(QuicFrame) <= 16,
- "Frames larger than 8 bytes should be referenced by pointer.");
-
-typedef std::vector<QuicFrame> QuicFrames;
-
-class NET_EXPORT_PRIVATE QuicData {
- public:
- QuicData(const char* buffer, size_t length);
- QuicData(const char* buffer, size_t length, bool owns_buffer);
- virtual ~QuicData();
-
- base::StringPiece AsStringPiece() const {
- return base::StringPiece(data(), length());
- }
-
- const char* data() const { return buffer_; }
- size_t length() const { return length_; }
- bool owns_buffer() const { return owns_buffer_; }
-
- private:
- const char* buffer_;
- size_t length_;
- bool owns_buffer_;
-
- DISALLOW_COPY_AND_ASSIGN(QuicData);
-};
-
-class NET_EXPORT_PRIVATE QuicPacket : public QuicData {
- public:
- // TODO(fayang): 4 fields from public header are passed in as arguments.
- // Consider to add a convenience method which directly accepts the entire
- // public header.
- QuicPacket(char* buffer,
- size_t length,
- bool owns_buffer,
- QuicConnectionIdLength connection_id_length,
- bool includes_version,
- bool includes_path_id,
- bool includes_diversification_nonce,
- QuicPacketNumberLength packet_number_length);
-
- base::StringPiece AssociatedData(QuicVersion version) const;
- base::StringPiece Plaintext(QuicVersion version) const;
-
- char* mutable_data() { return buffer_; }
-
- private:
- char* buffer_;
- const QuicConnectionIdLength connection_id_length_;
- const bool includes_version_;
- const bool includes_path_id_;
- const bool includes_diversification_nonce_;
- const QuicPacketNumberLength packet_number_length_;
-
- DISALLOW_COPY_AND_ASSIGN(QuicPacket);
-};
-
-class NET_EXPORT_PRIVATE QuicEncryptedPacket : public QuicData {
- public:
- QuicEncryptedPacket(const char* buffer, size_t length);
- QuicEncryptedPacket(const char* buffer, size_t length, bool owns_buffer);
-
- // Clones the packet into a new packet which owns the buffer.
- std::unique_ptr<QuicEncryptedPacket> Clone() const;
-
- // By default, gtest prints the raw bytes of an object. The bool data
- // member (in the base class QuicData) causes this object to have padding
- // bytes, which causes the default gtest object printer to read
- // uninitialize memory. So we need to teach gtest how to print this object.
- NET_EXPORT_PRIVATE friend std::ostream& operator<<(
- std::ostream& os,
- const QuicEncryptedPacket& s);
-
- private:
- DISALLOW_COPY_AND_ASSIGN(QuicEncryptedPacket);
-};
-
-// A received encrypted QUIC packet, with a recorded time of receipt.
-class NET_EXPORT_PRIVATE QuicReceivedPacket : public QuicEncryptedPacket {
- public:
- QuicReceivedPacket(const char* buffer, size_t length, QuicTime receipt_time);
- QuicReceivedPacket(const char* buffer,
- size_t length,
- QuicTime receipt_time,
- bool owns_buffer);
- QuicReceivedPacket(const char* buffer,
- size_t length,
- QuicTime receipt_time,
- bool owns_buffer,
- int ttl,
- bool ttl_valid);
-
- // Clones the packet into a new packet which owns the buffer.
- std::unique_ptr<QuicReceivedPacket> Clone() const;
-
- // Returns the time at which the packet was received.
- QuicTime receipt_time() const { return receipt_time_; }
-
- // This is the TTL of the packet, assuming ttl_vaild_ is true.
- int ttl() const { return ttl_; }
-
- // By default, gtest prints the raw bytes of an object. The bool data
- // member (in the base class QuicData) causes this object to have padding
- // bytes, which causes the default gtest object printer to read
- // uninitialize memory. So we need to teach gtest how to print this object.
- NET_EXPORT_PRIVATE friend std::ostream& operator<<(
- std::ostream& os,
- const QuicReceivedPacket& s);
-
- private:
- const QuicTime receipt_time_;
- int ttl_;
-
- DISALLOW_COPY_AND_ASSIGN(QuicReceivedPacket);
-};
-
-// Pure virtual class to listen for packet acknowledgements.
-class NET_EXPORT_PRIVATE QuicAckListenerInterface
- : public base::RefCounted<QuicAckListenerInterface> {
- public:
- QuicAckListenerInterface() {}
-
- // Called when a packet is acked. Called once per packet.
- // |acked_bytes| is the number of data bytes acked.
- virtual void OnPacketAcked(int acked_bytes,
- QuicTime::Delta ack_delay_time) = 0;
-
- // Called when a packet is retransmitted. Called once per packet.
- // |retransmitted_bytes| is the number of data bytes retransmitted.
- virtual void OnPacketRetransmitted(int retransmitted_bytes) = 0;
-
- protected:
- friend class base::RefCounted<QuicAckListenerInterface>;
-
- // Delegates are ref counted.
- virtual ~QuicAckListenerInterface() {}
-};
-
-// Pure virtual class to close connection on unrecoverable errors.
-class NET_EXPORT_PRIVATE QuicConnectionCloseDelegateInterface {
- public:
- virtual ~QuicConnectionCloseDelegateInterface() {}
-
- // Called when an unrecoverable error is encountered.
- virtual void OnUnrecoverableError(QuicErrorCode error,
- const std::string& error_details,
- ConnectionCloseSource source) = 0;
-};
-
-// Used to generate filtered supported versions based on flags.
-class NET_EXPORT_PRIVATE QuicVersionManager {
- public:
- explicit QuicVersionManager(QuicVersionVector supported_versions);
- ~QuicVersionManager();
-
- // Returns supported versions based on flags.
- const QuicVersionVector& GetSupportedVersions();
-
- private:
- // FLAGS_quic_disable_pre_34
- bool disable_pre_34_;
- // FLAGS_quic_enable_version_35
- bool enable_version_35_;
- // FLAGS_quic_enable_version_36_v2
- bool enable_version_36_;
- // The list of versions that may be supported.
- QuicVersionVector allowed_supported_versions_;
- // This vector contains QUIC versions which are currently supported based
- // on flags.
- QuicVersionVector filtered_supported_versions_;
-};
-
-struct NET_EXPORT_PRIVATE AckListenerWrapper {
- AckListenerWrapper(QuicAckListenerInterface* listener,
- QuicPacketLength data_length);
- AckListenerWrapper(const AckListenerWrapper& other);
- ~AckListenerWrapper();
-
- scoped_refptr<QuicAckListenerInterface> ack_listener;
- QuicPacketLength length;
-};
-
-struct NET_EXPORT_PRIVATE SerializedPacket {
- SerializedPacket(QuicPathId path_id,
- QuicPacketNumber packet_number,
- QuicPacketNumberLength packet_number_length,
- const char* encrypted_buffer,
- QuicPacketLength encrypted_length,
- QuicPacketEntropyHash entropy_hash,
- bool has_ack,
- bool has_stop_waiting);
- SerializedPacket(const SerializedPacket& other);
- ~SerializedPacket();
-
- // Not owned.
- const char* encrypted_buffer;
- QuicPacketLength encrypted_length;
- QuicFrames retransmittable_frames;
- IsHandshake has_crypto_handshake;
- // -1: full padding to the end of a max-sized packet
- // 0: no padding
- // otherwise: only pad up to num_padding_bytes bytes
- int16_t num_padding_bytes;
- QuicPathId path_id;
- QuicPacketNumber packet_number;
- QuicPacketNumberLength packet_number_length;
- EncryptionLevel encryption_level;
- QuicPacketEntropyHash entropy_hash;
- bool has_ack;
- bool has_stop_waiting;
- TransmissionType transmission_type;
- QuicPathId original_path_id;
- QuicPacketNumber original_packet_number;
-
- // Optional notifiers which will be informed when this packet has been ACKed.
- std::list<AckListenerWrapper> listeners;
-};
-
-struct NET_EXPORT_PRIVATE TransmissionInfo {
- // Used by STL when assigning into a map.
- TransmissionInfo();
-
- // Constructs a Transmission with a new all_transmissions set
- // containing |packet_number|.
- TransmissionInfo(EncryptionLevel level,
- QuicPacketNumberLength packet_number_length,
- TransmissionType transmission_type,
- QuicTime sent_time,
- QuicPacketLength bytes_sent,
- bool has_crypto_handshake,
- int num_padding_bytes);
-
- TransmissionInfo(const TransmissionInfo& other);
-
- ~TransmissionInfo();
-
- QuicFrames retransmittable_frames;
- EncryptionLevel encryption_level;
- QuicPacketNumberLength packet_number_length;
- QuicPacketLength bytes_sent;
- QuicTime sent_time;
- // Reason why this packet was transmitted.
- TransmissionType transmission_type;
- // In flight packets have not been abandoned or lost.
- bool in_flight;
- // True if the packet can never be acked, so it can be removed. Occurs when
- // a packet is never sent, after it is acknowledged once, or if it's a crypto
- // packet we never expect to receive an ack for.
- bool is_unackable;
- // True if the packet contains stream data from the crypto stream.
- bool has_crypto_handshake;
- // Non-zero if the packet needs padding if it's retransmitted.
- int16_t num_padding_bytes;
- // Stores the packet number of the next retransmission of this packet.
- // Zero if the packet has not been retransmitted.
- QuicPacketNumber retransmission;
- // Non-empty if there is a std::listener for this packet.
- std::list<AckListenerWrapper> ack_listeners;
-};
-
-// Struct to store the pending retransmission information.
-struct PendingRetransmission {
- PendingRetransmission(QuicPathId path_id,
- QuicPacketNumber packet_number,
- TransmissionType transmission_type,
- const QuicFrames& retransmittable_frames,
- bool has_crypto_handshake,
- int num_padding_bytes,
- EncryptionLevel encryption_level,
- QuicPacketNumberLength packet_number_length)
- : packet_number(packet_number),
- retransmittable_frames(retransmittable_frames),
- transmission_type(transmission_type),
- path_id(path_id),
- has_crypto_handshake(has_crypto_handshake),
- num_padding_bytes(num_padding_bytes),
- encryption_level(encryption_level),
- packet_number_length(packet_number_length) {}
-
- QuicPacketNumber packet_number;
- const QuicFrames& retransmittable_frames;
- TransmissionType transmission_type;
- QuicPathId path_id;
- bool has_crypto_handshake;
- int num_padding_bytes;
- EncryptionLevel encryption_level;
- QuicPacketNumberLength packet_number_length;
-};
-
-// Convenience wrapper to wrap an iovec array and the total length, which must
-// be less than or equal to the actual total length of the iovecs.
-struct NET_EXPORT_PRIVATE QuicIOVector {
- QuicIOVector(const struct iovec* iov, int iov_count, size_t total_length)
- : iov(iov), iov_count(iov_count), total_length(total_length) {}
-
- const struct iovec* iov;
- const int iov_count;
- const size_t total_length;
-};
-
-} // namespace net
-
-#endif // NET_QUIC_QUIC_PROTOCOL_H_
diff --git a/chromium/net/quic/core/quic_protocol_test.cc b/chromium/net/quic/core/quic_protocol_test.cc
deleted file mode 100644
index 49d2434ac9a..00000000000
--- a/chromium/net/quic/core/quic_protocol_test.cc
+++ /dev/null
@@ -1,517 +0,0 @@
-// Copyright (c) 2012 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.
-
-#include "net/quic/core/quic_protocol.h"
-
-#include <sstream>
-
-#include "base/stl_util.h"
-#include "net/quic/core/quic_flags.h"
-#include "net/quic/core/quic_utils.h"
-#include "net/quic/test_tools/quic_test_utils.h"
-#include "testing/gtest/include/gtest/gtest.h"
-
-namespace net {
-namespace test {
-namespace {
-
-TEST(QuicProtocolTest, MakeQuicTag) {
- QuicTag tag = MakeQuicTag('A', 'B', 'C', 'D');
- char bytes[4];
- memcpy(bytes, &tag, 4);
- EXPECT_EQ('A', bytes[0]);
- EXPECT_EQ('B', bytes[1]);
- EXPECT_EQ('C', bytes[2]);
- EXPECT_EQ('D', bytes[3]);
-}
-
-TEST(QuicProtocolTest, IsAawaitingPacket) {
- QuicAckFrame ack_frame;
- ack_frame.largest_observed = 10u;
- EXPECT_TRUE(IsAwaitingPacket(ack_frame, 11u, 0u));
- EXPECT_FALSE(IsAwaitingPacket(ack_frame, 1u, 0u));
-
- ack_frame.packets.Add(10);
- EXPECT_TRUE(IsAwaitingPacket(ack_frame, 10u, 0u));
-
- QuicAckFrame ack_frame1;
- ack_frame1.missing = false;
- ack_frame1.largest_observed = 10u;
- ack_frame1.packets.Add(1, 11);
- EXPECT_TRUE(IsAwaitingPacket(ack_frame1, 11u, 0u));
- EXPECT_FALSE(IsAwaitingPacket(ack_frame1, 1u, 0u));
-
- ack_frame1.packets.Remove(10);
- EXPECT_TRUE(IsAwaitingPacket(ack_frame1, 10u, 0u));
-
- QuicAckFrame ack_frame2;
- ack_frame2.missing = false;
- ack_frame2.largest_observed = 100u;
- ack_frame2.packets.Add(21, 100);
- EXPECT_FALSE(IsAwaitingPacket(ack_frame2, 11u, 20u));
- EXPECT_FALSE(IsAwaitingPacket(ack_frame2, 80u, 20u));
- EXPECT_TRUE(IsAwaitingPacket(ack_frame2, 101u, 20u));
-
- ack_frame2.packets.Remove(50);
- EXPECT_TRUE(IsAwaitingPacket(ack_frame2, 50u, 20u));
-}
-
-TEST(QuicProtocolTest, QuicVersionToQuicTag) {
-// If you add a new version to the QuicVersion enum you will need to add a new
-// case to QuicVersionToQuicTag, otherwise this test will fail.
-
-// TODO(rtenneti): Enable checking of Log(ERROR) messages.
-#if 0
- // Any logs would indicate an unsupported version which we don't expect.
- ScopedMockLog log(kDoNotCaptureLogsYet);
- EXPECT_CALL(log, Log(_, _, _)).Times(0);
- log.StartCapturingLogs();
-#endif
-
- // Explicitly test a specific version.
- EXPECT_EQ(MakeQuicTag('Q', '0', '3', '2'),
- QuicVersionToQuicTag(QUIC_VERSION_32));
-
- // Loop over all supported versions and make sure that we never hit the
- // default case (i.e. all supported versions should be successfully converted
- // to valid QuicTags).
- for (size_t i = 0; i < arraysize(kSupportedQuicVersions); ++i) {
- QuicVersion version = kSupportedQuicVersions[i];
- EXPECT_LT(0u, QuicVersionToQuicTag(version));
- }
-}
-
-TEST(QuicProtocolTest, QuicVersionToQuicTagUnsupported) {
-// TODO(rtenneti): Enable checking of Log(ERROR) messages.
-#if 0
- // TODO(rjshade): Change to DFATAL once we actually support multiple versions,
- // and QuicConnectionTest::SendVersionNegotiationPacket can be changed to use
- // mis-matched versions rather than relying on QUIC_VERSION_UNSUPPORTED.
- ScopedMockLog log(kDoNotCaptureLogsYet);
- EXPECT_CALL(log, Log(base_logging::ERROR, _, "Unsupported QuicVersion: 0"))
- .Times(1);
- log.StartCapturingLogs();
-#endif
-
- EXPECT_EQ(0u, QuicVersionToQuicTag(QUIC_VERSION_UNSUPPORTED));
-}
-
-TEST(QuicProtocolTest, QuicTagToQuicVersion) {
-// If you add a new version to the QuicVersion enum you will need to add a new
-// case to QuicTagToQuicVersion, otherwise this test will fail.
-
-// TODO(rtenneti): Enable checking of Log(ERROR) messages.
-#if 0
- // Any logs would indicate an unsupported version which we don't expect.
- ScopedMockLog log(kDoNotCaptureLogsYet);
- EXPECT_CALL(log, Log(_, _, _)).Times(0);
- log.StartCapturingLogs();
-#endif
-
- // Explicitly test specific versions.
- EXPECT_EQ(QUIC_VERSION_32,
- QuicTagToQuicVersion(MakeQuicTag('Q', '0', '3', '2')));
-
- for (size_t i = 0; i < arraysize(kSupportedQuicVersions); ++i) {
- QuicVersion version = kSupportedQuicVersions[i];
-
- // Get the tag from the version (we can loop over QuicVersions easily).
- QuicTag tag = QuicVersionToQuicTag(version);
- EXPECT_LT(0u, tag);
-
- // Now try converting back.
- QuicVersion tag_to_quic_version = QuicTagToQuicVersion(tag);
- EXPECT_EQ(version, tag_to_quic_version);
- EXPECT_NE(QUIC_VERSION_UNSUPPORTED, tag_to_quic_version);
- }
-}
-
-TEST(QuicProtocolTest, QuicTagToQuicVersionUnsupported) {
-// TODO(rtenneti): Enable checking of Log(ERROR) messages.
-#if 0
- ScopedMockLog log(kDoNotCaptureLogsYet);
-#ifndef NDEBUG
- EXPECT_CALL(log,
- Log(base_logging::INFO, _, "Unsupported QuicTag version: FAKE"))
- .Times(1);
-#endif
- log.StartCapturingLogs();
-#endif
-
- EXPECT_EQ(QUIC_VERSION_UNSUPPORTED,
- QuicTagToQuicVersion(MakeQuicTag('F', 'A', 'K', 'E')));
-}
-
-TEST(QuicProtocolTest, QuicVersionToString) {
- EXPECT_EQ("QUIC_VERSION_32", QuicVersionToString(QUIC_VERSION_32));
- EXPECT_EQ("QUIC_VERSION_UNSUPPORTED",
- QuicVersionToString(QUIC_VERSION_UNSUPPORTED));
-
- QuicVersion single_version[] = {QUIC_VERSION_32};
- QuicVersionVector versions_vector;
- for (size_t i = 0; i < arraysize(single_version); ++i) {
- versions_vector.push_back(single_version[i]);
- }
- EXPECT_EQ("QUIC_VERSION_32", QuicVersionVectorToString(versions_vector));
-
- QuicVersion multiple_versions[] = {QUIC_VERSION_UNSUPPORTED, QUIC_VERSION_32};
- versions_vector.clear();
- for (size_t i = 0; i < arraysize(multiple_versions); ++i) {
- versions_vector.push_back(multiple_versions[i]);
- }
- EXPECT_EQ("QUIC_VERSION_UNSUPPORTED,QUIC_VERSION_32",
- QuicVersionVectorToString(versions_vector));
-
- // Make sure that all supported versions are present in QuicVersionToString.
- for (size_t i = 0; i < arraysize(kSupportedQuicVersions); ++i) {
- QuicVersion version = kSupportedQuicVersions[i];
- EXPECT_NE("QUIC_VERSION_UNSUPPORTED", QuicVersionToString(version));
- }
-}
-
-TEST(QuicProtocolTest, AckFrameToString) {
- QuicAckFrame frame;
- frame.entropy_hash = 1;
- frame.largest_observed = 2;
- frame.ack_delay_time = QuicTime::Delta::FromMicroseconds(3);
- frame.packets.Add(4);
- frame.packets.Add(5);
- frame.received_packet_times = {
- {6, QuicTime::Zero() + QuicTime::Delta::FromMicroseconds(7)}};
- std::ostringstream stream;
- stream << frame;
- EXPECT_EQ(
- "{ entropy_hash: 1, largest_observed: 2, ack_delay_time: 3, "
- "packets: [ 4 5 ], is_truncated: 0, received_packets: [ 6 at 7 ] }\n",
- stream.str());
-}
-
-TEST(QuicProtocolTest, PaddingFrameToString) {
- QuicPaddingFrame frame;
- frame.num_padding_bytes = 1;
- std::ostringstream stream;
- stream << frame;
- EXPECT_EQ("{ num_padding_bytes: 1 }\n", stream.str());
-}
-
-TEST(QuicProtocolTest, RstStreamFrameToString) {
- QuicRstStreamFrame frame;
- frame.stream_id = 1;
- frame.error_code = QUIC_STREAM_CANCELLED;
- std::ostringstream stream;
- stream << frame;
- EXPECT_EQ("{ stream_id: 1, error_code: 6 }\n", stream.str());
-}
-
-TEST(QuicProtocolTest, ConnectionCloseFrameToString) {
- QuicConnectionCloseFrame frame;
- frame.error_code = QUIC_NETWORK_IDLE_TIMEOUT;
- frame.error_details = "No recent network activity.";
- std::ostringstream stream;
- stream << frame;
- EXPECT_EQ(
- "{ error_code: 25, error_details: 'No recent network activity.' }\n",
- stream.str());
-}
-
-TEST(QuicProtocolTest, GoAwayFrameToString) {
- QuicGoAwayFrame frame;
- frame.error_code = QUIC_NETWORK_IDLE_TIMEOUT;
- frame.last_good_stream_id = 2;
- frame.reason_phrase = "Reason";
- std::ostringstream stream;
- stream << frame;
- EXPECT_EQ(
- "{ error_code: 25, last_good_stream_id: 2, reason_phrase: 'Reason' }\n",
- stream.str());
-}
-
-TEST(QuicProtocolTest, WindowUpdateFrameToString) {
- QuicWindowUpdateFrame frame;
- std::ostringstream stream;
- frame.stream_id = 1;
- frame.byte_offset = 2;
- stream << frame;
- EXPECT_EQ("{ stream_id: 1, byte_offset: 2 }\n", stream.str());
-}
-
-TEST(QuicProtocolTest, BlockedFrameToString) {
- QuicBlockedFrame frame;
- frame.stream_id = 1;
- std::ostringstream stream;
- stream << frame;
- EXPECT_EQ("{ stream_id: 1 }\n", stream.str());
-}
-
-TEST(QuicProtocolTest, StreamFrameToString) {
- QuicStreamFrame frame;
- frame.stream_id = 1;
- frame.fin = false;
- frame.offset = 2;
- frame.data_length = 3;
- std::ostringstream stream;
- stream << frame;
- EXPECT_EQ("{ stream_id: 1, fin: 0, offset: 2, length: 3 }\n", stream.str());
-}
-
-TEST(QuicProtocolTest, StopWaitingFrameToString) {
- QuicStopWaitingFrame frame;
- frame.entropy_hash = 1;
- frame.least_unacked = 2;
- std::ostringstream stream;
- stream << frame;
- EXPECT_EQ("{ entropy_hash: 1, least_unacked: 2 }\n", stream.str());
-}
-
-TEST(QuicProtocolTest, PathCloseFrameToString) {
- QuicPathCloseFrame frame;
- frame.path_id = 1;
- std::ostringstream stream;
- stream << frame;
- EXPECT_EQ("{ path_id: 1 }\n", stream.str());
-}
-
-TEST(QuicProtocolTest, FilterSupportedVersions) {
- QuicFlagSaver flags;
- QuicVersionVector all_versions = {QUIC_VERSION_32, QUIC_VERSION_33,
- QUIC_VERSION_34, QUIC_VERSION_35,
- QUIC_VERSION_36};
-
- FLAGS_quic_disable_pre_34 = true;
- FLAGS_quic_enable_version_35 = false;
- FLAGS_quic_enable_version_36_v2 = false;
-
- QuicVersionVector filtered_versions = FilterSupportedVersions(all_versions);
- ASSERT_EQ(1u, filtered_versions.size());
- EXPECT_EQ(QUIC_VERSION_34, filtered_versions[0]);
-}
-
-TEST(QuicProtocolTest, FilterSupportedVersionsAllVersions) {
- QuicFlagSaver flags;
- QuicVersionVector all_versions = {QUIC_VERSION_32, QUIC_VERSION_33,
- QUIC_VERSION_34, QUIC_VERSION_35,
- QUIC_VERSION_36};
-
- FLAGS_quic_disable_pre_34 = false;
- FLAGS_quic_enable_version_35 = true;
- FLAGS_quic_enable_version_36_v2 = true;
-
- QuicVersionVector filtered_versions = FilterSupportedVersions(all_versions);
- ASSERT_EQ(all_versions, filtered_versions);
-}
-
-TEST(QuicProtocolTest, FilterSupportedVersionsNo36) {
- QuicFlagSaver flags;
- QuicVersionVector all_versions = {QUIC_VERSION_32, QUIC_VERSION_33,
- QUIC_VERSION_34, QUIC_VERSION_35,
- QUIC_VERSION_36};
-
- FLAGS_quic_disable_pre_34 = false;
- FLAGS_quic_enable_version_35 = true;
- FLAGS_quic_enable_version_36_v2 = false;
-
- all_versions.pop_back(); // Remove 36
-
- ASSERT_EQ(all_versions, FilterSupportedVersions(all_versions));
-}
-
-TEST(QuicProtocolTest, FilterSupportedVersionsNo35) {
- QuicFlagSaver flags;
- QuicVersionVector all_versions = {QUIC_VERSION_32, QUIC_VERSION_33,
- QUIC_VERSION_34, QUIC_VERSION_35,
- QUIC_VERSION_36};
-
- FLAGS_quic_disable_pre_34 = false;
- FLAGS_quic_enable_version_35 = true;
- FLAGS_quic_enable_version_36_v2 = true;
-
- all_versions.pop_back(); // Remove 36
- all_versions.pop_back(); // Remove 35
-
- ASSERT_EQ(all_versions, FilterSupportedVersions(all_versions));
-}
-
-TEST(QuicProtocolTest, FilterSupportedVersionsNoPre34) {
- QuicFlagSaver flags;
- QuicVersionVector all_versions = {QUIC_VERSION_32, QUIC_VERSION_33,
- QUIC_VERSION_34, QUIC_VERSION_35,
- QUIC_VERSION_36};
-
- FLAGS_quic_disable_pre_34 = true;
- FLAGS_quic_enable_version_35 = true;
- FLAGS_quic_enable_version_36_v2 = true;
-
- all_versions.erase(all_versions.begin()); // Remove 32
- all_versions.erase(all_versions.begin()); // Remove 33
-
- ASSERT_EQ(all_versions, FilterSupportedVersions(all_versions));
-}
-
-TEST(QuicProtocolTest, QuicVersionManager) {
- QuicFlagSaver flags;
- FLAGS_quic_enable_version_35 = false;
- FLAGS_quic_enable_version_36_v2 = false;
- QuicVersionManager manager(AllSupportedVersions());
- EXPECT_EQ(FilterSupportedVersions(AllSupportedVersions()),
- manager.GetSupportedVersions());
- FLAGS_quic_enable_version_35 = true;
- FLAGS_quic_enable_version_36_v2 = true;
- EXPECT_EQ(FilterSupportedVersions(AllSupportedVersions()),
- manager.GetSupportedVersions());
- EXPECT_EQ(QUIC_VERSION_36, manager.GetSupportedVersions()[0]);
- EXPECT_EQ(QUIC_VERSION_35, manager.GetSupportedVersions()[1]);
-}
-
-TEST(QuicProtocolTest, LookUpVersionByIndex) {
- QuicVersionVector all_versions = {QUIC_VERSION_32, QUIC_VERSION_33,
- QUIC_VERSION_34, QUIC_VERSION_35,
- QUIC_VERSION_36};
- int version_count = all_versions.size();
- for (int i = -5; i <= version_count + 1; ++i) {
- if (i >= 0 && i < version_count) {
- EXPECT_EQ(all_versions[i], VersionOfIndex(all_versions, i)[0]);
- } else {
- EXPECT_EQ(QUIC_VERSION_UNSUPPORTED, VersionOfIndex(all_versions, i)[0]);
- }
- }
-}
-
-// Tests that a queue contains the expected data after calls to Add().
-TEST(PacketNumberQueueTest, AddRange) {
- PacketNumberQueue queue;
- queue.Add(1, 51);
- queue.Add(53);
-
- EXPECT_FALSE(queue.Contains(0));
- for (int i = 1; i < 51; ++i) {
- EXPECT_TRUE(queue.Contains(i));
- }
- EXPECT_FALSE(queue.Contains(51));
- EXPECT_FALSE(queue.Contains(52));
- EXPECT_TRUE(queue.Contains(53));
- EXPECT_FALSE(queue.Contains(54));
- EXPECT_EQ(51u, queue.NumPacketsSlow());
- EXPECT_EQ(1u, queue.Min());
- EXPECT_EQ(53u, queue.Max());
-
- queue.Add(70);
- EXPECT_EQ(70u, queue.Max());
-}
-
-// Tests that a queue contains the expected data after calls to Remove().
-TEST(PacketNumberQueueTest, Removal) {
- PacketNumberQueue queue;
- queue.Add(0, 100);
-
- EXPECT_TRUE(queue.RemoveUpTo(51));
- EXPECT_FALSE(queue.RemoveUpTo(51));
- queue.Remove(53);
-
- EXPECT_FALSE(queue.Contains(0));
- for (int i = 1; i < 51; ++i) {
- EXPECT_FALSE(queue.Contains(i));
- }
- EXPECT_TRUE(queue.Contains(51));
- EXPECT_TRUE(queue.Contains(52));
- EXPECT_FALSE(queue.Contains(53));
- EXPECT_TRUE(queue.Contains(54));
- EXPECT_EQ(48u, queue.NumPacketsSlow());
- EXPECT_EQ(51u, queue.Min());
- EXPECT_EQ(99u, queue.Max());
-
- queue.Remove(51);
- EXPECT_EQ(52u, queue.Min());
- queue.Remove(99);
- EXPECT_EQ(98u, queue.Max());
-}
-
-// Tests that a queue is empty when all of its elements are removed.
-TEST(PacketNumberQueueTest, Empty) {
- PacketNumberQueue queue;
- EXPECT_TRUE(queue.Empty());
- EXPECT_EQ(0u, queue.NumPacketsSlow());
-
- queue.Add(1, 100);
- EXPECT_TRUE(queue.RemoveUpTo(100));
- EXPECT_TRUE(queue.Empty());
- EXPECT_EQ(0u, queue.NumPacketsSlow());
-}
-
-// Tests that logging the state of a PacketNumberQueue does not crash.
-TEST(PacketNumberQueueTest, LogDoesNotCrash) {
- std::ostringstream oss;
- PacketNumberQueue queue;
- oss << queue;
-
- queue.Add(1);
- queue.Add(50, 100);
- oss << queue;
-}
-
-// Tests that the iterators returned from a packet queue iterate over the queue.
-TEST(PacketNumberQueueTest, Iterators) {
- PacketNumberQueue queue;
- queue.Add(1, 100);
-
- const std::vector<Interval<QuicPacketNumber>> actual_intervals(queue.begin(),
- queue.end());
-
- std::vector<Interval<QuicPacketNumber>> expected_intervals;
- expected_intervals.push_back(Interval<QuicPacketNumber>(1, 100));
-
- EXPECT_EQ(expected_intervals, actual_intervals);
-}
-
-TEST(PacketNumberQueueTest, LowerBoundEquals) {
- PacketNumberQueue queue;
- queue.Add(1, 100);
-
- PacketNumberQueue::const_iterator it = queue.lower_bound(10);
- ASSERT_NE(queue.end(), it);
- EXPECT_TRUE(it->Contains(10u));
-
- it = queue.lower_bound(101);
- EXPECT_TRUE(queue.end() == it);
-}
-
-TEST(PacketNumberQueueTest, LowerBoundGreater) {
- PacketNumberQueue queue;
- queue.Add(15, 25);
- queue.Add(50, 100);
-
- PacketNumberQueue::const_iterator it = queue.lower_bound(10);
- ASSERT_NE(queue.end(), it);
- EXPECT_EQ(15u, it->min());
- EXPECT_EQ(25u, it->max());
-}
-
-TEST(PacketNumberQueueTest, IntervalLengthAndRemoveInterval) {
- PacketNumberQueue queue;
- queue.Add(1, 10);
- queue.Add(20, 30);
- queue.Add(40, 50);
- EXPECT_EQ(3u, queue.NumIntervals());
- EXPECT_EQ(10u, queue.LastIntervalLength());
- queue.Remove(9, 21);
- EXPECT_EQ(3u, queue.NumIntervals());
- EXPECT_FALSE(queue.Contains(9));
- EXPECT_FALSE(queue.Contains(20));
-}
-
-TEST(PacketNumberQueueTest, Complement) {
- PacketNumberQueue queue;
- queue.Add(1, 10);
- queue.Add(12, 20);
- queue.Add(22, 30);
- queue.Complement();
- EXPECT_EQ(2u, queue.NumIntervals());
- EXPECT_TRUE(queue.Contains(10));
- EXPECT_TRUE(queue.Contains(11));
- EXPECT_TRUE(queue.Contains(20));
- EXPECT_TRUE(queue.Contains(21));
-}
-
-} // namespace
-} // namespace test
-} // namespace net
diff --git a/chromium/net/quic/core/quic_received_packet_manager.cc b/chromium/net/quic/core/quic_received_packet_manager.cc
index fdb41fc41d6..1f2734d6036 100644
--- a/chromium/net/quic/core/quic_received_packet_manager.cc
+++ b/chromium/net/quic/core/quic_received_packet_manager.cc
@@ -7,17 +7,11 @@
#include <limits>
#include <utility>
-#include "base/logging.h"
#include "base/stl_util.h"
-#include "base/strings/stringprintf.h"
#include "net/base/linked_hash_map.h"
#include "net/quic/core/crypto/crypto_protocol.h"
-#include "net/quic/core/quic_bug_tracker.h"
#include "net/quic/core/quic_connection_stats.h"
-#include "net/quic/core/quic_flags.h"
-
-using std::max;
-using std::min;
+#include "net/quic/platform/api/quic_bug_tracker.h"
namespace net {
@@ -31,111 +25,12 @@ namespace {
const size_t kMaxPacketsAfterNewMissing = 4;
}
-QuicReceivedPacketManager::EntropyTracker::EntropyTracker()
- : packets_entropy_hash_(0), first_gap_(1), largest_observed_(0) {}
-
-QuicReceivedPacketManager::EntropyTracker::~EntropyTracker() {}
-
-QuicPacketEntropyHash QuicReceivedPacketManager::EntropyTracker::EntropyHash(
- QuicPacketNumber packet_number) const {
- DCHECK_LE(packet_number, largest_observed_);
- if (packet_number == largest_observed_) {
- return packets_entropy_hash_;
- }
-
- DCHECK_GE(packet_number, first_gap_);
- DCHECK_EQ(first_gap_ + packets_entropy_.size() - 1, largest_observed_);
- QuicPacketEntropyHash hash = packets_entropy_hash_;
- ReceivedEntropyHashes::const_reverse_iterator it = packets_entropy_.rbegin();
- for (QuicPacketNumber i = 0; i < (largest_observed_ - packet_number);
- ++i, ++it) {
- hash ^= it->first;
- }
- return hash;
-}
-
-void QuicReceivedPacketManager::EntropyTracker::RecordPacketEntropyHash(
- QuicPacketNumber packet_number,
- QuicPacketEntropyHash entropy_hash) {
- if (packet_number < first_gap_) {
- DVLOG(1) << "Ignoring received packet entropy for packet_number:"
- << packet_number
- << " less than largest_peer_packet_number:" << first_gap_;
- return;
- }
- // RecordPacketEntropyHash is only intended to be called once per packet.
- DCHECK(packet_number > largest_observed_ ||
- !packets_entropy_[packet_number - first_gap_].second);
-
- packets_entropy_hash_ ^= entropy_hash;
-
- // Optimize the typical case of no gaps.
- if (packet_number == largest_observed_ + 1 && packets_entropy_.empty()) {
- ++first_gap_;
- largest_observed_ = packet_number;
- return;
- }
- if (packet_number > largest_observed_) {
- for (QuicPacketNumber i = 0; i < (packet_number - largest_observed_ - 1);
- ++i) {
- packets_entropy_.push_back(std::make_pair(0, false));
- }
- packets_entropy_.push_back(std::make_pair(entropy_hash, true));
- largest_observed_ = packet_number;
- } else {
- packets_entropy_[packet_number - first_gap_] =
- std::make_pair(entropy_hash, true);
- AdvanceFirstGapAndGarbageCollectEntropyMap();
- }
-
- DVLOG(2) << "setting cumulative received entropy hash to: "
- << static_cast<int>(packets_entropy_hash_)
- << " updated with packet number " << packet_number
- << " entropy hash: " << static_cast<int>(entropy_hash);
-}
-
-void QuicReceivedPacketManager::EntropyTracker::SetCumulativeEntropyUpTo(
- QuicPacketNumber packet_number,
- QuicPacketEntropyHash entropy_hash) {
- DCHECK_LE(packet_number, largest_observed_);
- if (packet_number < first_gap_) {
- DVLOG(1) << "Ignoring set entropy at:" << packet_number
- << " less than first_gap_:" << first_gap_;
- return;
- }
- while (first_gap_ < packet_number) {
- ++first_gap_;
- if (!packets_entropy_.empty()) {
- packets_entropy_.pop_front();
- }
- }
- // Compute the current entropy by XORing in all entropies received including
- // and since packet_number.
- packets_entropy_hash_ = entropy_hash;
- for (ReceivedEntropyHashes::const_iterator it = packets_entropy_.begin();
- it != packets_entropy_.end(); ++it) {
- packets_entropy_hash_ ^= it->first;
- }
-
- // Garbage collect entries from the beginning of the map.
- AdvanceFirstGapAndGarbageCollectEntropyMap();
-}
-
-void QuicReceivedPacketManager::EntropyTracker::
- AdvanceFirstGapAndGarbageCollectEntropyMap() {
- while (!packets_entropy_.empty() && packets_entropy_.front().second) {
- ++first_gap_;
- packets_entropy_.pop_front();
- }
-}
-
QuicReceivedPacketManager::QuicReceivedPacketManager(QuicConnectionStats* stats)
: peer_least_packet_awaiting_ack_(0),
ack_frame_updated_(false),
time_largest_observed_(QuicTime::Zero()),
stats_(stats) {
ack_frame_.largest_observed = 0;
- ack_frame_.entropy_hash = 0;
}
QuicReceivedPacketManager::~QuicReceivedPacketManager() {}
@@ -149,51 +44,29 @@ void QuicReceivedPacketManager::RecordPacketReceived(
ack_frame_.received_packet_times.clear();
}
ack_frame_updated_ = true;
- if (ack_frame_.missing) {
- // Adds the range of packet numbers from max(largest observed + 1, least
- // awaiting ack) up to packet_number not including packet_number.
- ack_frame_.packets.Add(
- max(ack_frame_.largest_observed + 1, peer_least_packet_awaiting_ack_),
- packet_number);
- } else {
- ack_frame_.packets.Add(header.packet_number);
- }
+ ack_frame_.packets.Add(header.packet_number);
if (ack_frame_.largest_observed > packet_number) {
- if (ack_frame_.missing) {
- // We've gotten one of the out of order packets - remove it from our
- // "missing packets" list.
- DVLOG(1) << "Removing " << packet_number << " from missing list";
- ack_frame_.packets.Remove(packet_number);
- }
-
// Record how out of order stats.
++stats_->packets_reordered;
stats_->max_sequence_reordering =
- max(stats_->max_sequence_reordering,
- ack_frame_.largest_observed - packet_number);
+ std::max(stats_->max_sequence_reordering,
+ ack_frame_.largest_observed - packet_number);
int64_t reordering_time_us =
(receipt_time - time_largest_observed_).ToMicroseconds();
stats_->max_time_reordering_us =
- max(stats_->max_time_reordering_us, reordering_time_us);
+ std::max(stats_->max_time_reordering_us, reordering_time_us);
}
if (packet_number > ack_frame_.largest_observed) {
ack_frame_.largest_observed = packet_number;
time_largest_observed_ = receipt_time;
}
- if (ack_frame_.missing) {
- entropy_tracker_.RecordPacketEntropyHash(packet_number,
- header.entropy_hash);
- }
ack_frame_.received_packet_times.push_back(
std::make_pair(packet_number, receipt_time));
}
bool QuicReceivedPacketManager::IsMissing(QuicPacketNumber packet_number) {
- if (ack_frame_.missing) {
- return ack_frame_.packets.Contains(packet_number);
- }
return packet_number < ack_frame_.largest_observed &&
!ack_frame_.packets.Contains(packet_number);
}
@@ -204,26 +77,9 @@ bool QuicReceivedPacketManager::IsAwaitingPacket(
peer_least_packet_awaiting_ack_);
}
-namespace {
-struct isTooLarge {
- explicit isTooLarge(QuicPacketNumber n) : largest_observed_(n) {}
- QuicPacketNumber largest_observed_;
-
- // Return true if the packet in p is too different from largest_observed_
- // to express.
- bool operator()(const std::pair<QuicPacketNumber, QuicTime>& p) const {
- return largest_observed_ - p.first >= std::numeric_limits<uint8_t>::max();
- }
-};
-} // namespace
-
const QuicFrame QuicReceivedPacketManager::GetUpdatedAckFrame(
QuicTime approximate_now) {
ack_frame_updated_ = false;
- if (ack_frame_.missing) {
- ack_frame_.entropy_hash = EntropyHash(ack_frame_.largest_observed);
- }
-
if (time_largest_observed_ == QuicTime::Zero()) {
// We have received no packets.
ack_frame_.ack_delay_time = QuicTime::Delta::Infinite();
@@ -249,11 +105,6 @@ const QuicFrame QuicReceivedPacketManager::GetUpdatedAckFrame(
return QuicFrame(&ack_frame_);
}
-QuicPacketEntropyHash QuicReceivedPacketManager::EntropyHash(
- QuicPacketNumber packet_number) const {
- return entropy_tracker_.EntropyHash(packet_number);
-}
-
bool QuicReceivedPacketManager::DontWaitForPacketsBefore(
QuicPacketNumber least_unacked) {
peer_least_packet_awaiting_ack_ = least_unacked;
@@ -267,13 +118,6 @@ void QuicReceivedPacketManager::UpdatePacketInformationSentByPeer(
if (stop_waiting.least_unacked > peer_least_packet_awaiting_ack_) {
bool packets_updated = DontWaitForPacketsBefore(stop_waiting.least_unacked);
if (packets_updated) {
- if (ack_frame_.missing) {
- DVLOG(1) << "Updating entropy hashed since we missed packets";
- // There were some missing packets that we won't ever get now.
- // Recalculate the received entropy hash.
- entropy_tracker_.SetCumulativeEntropyUpTo(stop_waiting.least_unacked,
- stop_waiting.entropy_hash);
- }
// Ack frame gets updated because packets set is updated because of stop
// waiting frame.
ack_frame_updated_ = true;
@@ -284,35 +128,17 @@ void QuicReceivedPacketManager::UpdatePacketInformationSentByPeer(
}
bool QuicReceivedPacketManager::HasMissingPackets() const {
- if (ack_frame_.missing) {
- return !ack_frame_.packets.Empty();
- }
-
return ack_frame_.packets.NumIntervals() > 1 ||
(!ack_frame_.packets.Empty() &&
ack_frame_.packets.Min() >
- max(QuicPacketNumber(1), peer_least_packet_awaiting_ack_));
+ std::max(QuicPacketNumber(1), peer_least_packet_awaiting_ack_));
}
bool QuicReceivedPacketManager::HasNewMissingPackets() const {
- if (ack_frame_.missing) {
- return !ack_frame_.packets.Empty() &&
- (ack_frame_.largest_observed - ack_frame_.packets.Max()) <=
- kMaxPacketsAfterNewMissing;
- }
-
return HasMissingPackets() &&
ack_frame_.packets.LastIntervalLength() <= kMaxPacketsAfterNewMissing;
}
-size_t QuicReceivedPacketManager::NumTrackedPackets() const {
- return entropy_tracker_.size();
-}
-
-void QuicReceivedPacketManager::SetVersion(QuicVersion version) {
- ack_frame_.missing = version <= QUIC_VERSION_33;
-}
-
bool QuicReceivedPacketManager::ack_frame_updated() const {
return ack_frame_updated_;
}
diff --git a/chromium/net/quic/core/quic_received_packet_manager.h b/chromium/net/quic/core/quic_received_packet_manager.h
index 16759ade20b..140a825f9e0 100644
--- a/chromium/net/quic/core/quic_received_packet_manager.h
+++ b/chromium/net/quic/core/quic_received_packet_manager.h
@@ -1,106 +1,30 @@
// Copyright 2013 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.
-//
-// Manages the packet entropy calculation for both sent and received packets
-// for a connection.
-#ifndef NET_QUIC_QUIC_RECEIVED_PACKET_MANAGER_H_
-#define NET_QUIC_QUIC_RECEIVED_PACKET_MANAGER_H_
-
-#include <stddef.h>
-
-#include <deque>
+#ifndef NET_QUIC_CORE_QUIC_RECEIVED_PACKET_MANAGER_H_
+#define NET_QUIC_CORE_QUIC_RECEIVED_PACKET_MANAGER_H_
#include "base/macros.h"
-#include "net/base/net_export.h"
#include "net/quic/core/quic_config.h"
#include "net/quic/core/quic_framer.h"
-#include "net/quic/core/quic_protocol.h"
+#include "net/quic/core/quic_packets.h"
+#include "net/quic/platform/api/quic_export.h"
namespace net {
namespace test {
-class EntropyTrackerPeer;
class QuicConnectionPeer;
class QuicReceivedPacketManagerPeer;
} // namespace test
struct QuicConnectionStats;
-// Records all received packets by a connection and tracks their entropy.
-// Also calculates the correct entropy for the framer when it truncates an ack
-// frame being serialized.
-class NET_EXPORT_PRIVATE QuicReceivedPacketManager
- : public QuicReceivedEntropyHashCalculatorInterface {
+// Records all received packets by a connection.
+class QUIC_EXPORT_PRIVATE QuicReceivedPacketManager {
public:
- class NET_EXPORT_PRIVATE EntropyTracker {
- public:
- EntropyTracker();
- ~EntropyTracker();
-
- // Compute the XOR of the entropy of all received packets up to
- // and including packet_number.
- // Requires that either:
- // packet_number == largest_observed_
- // or:
- // packet_number > first_gap_ &&
- // packet_number < largest_observed_ &&
- // packet_number in packets_entropy_
- QuicPacketEntropyHash EntropyHash(QuicPacketNumber packet_number) const;
-
- // Record the received entropy hash against |packet_number|.
- // Performs garbage collection to advance first_gap_ if
- // packet_number == first_gap_.
- void RecordPacketEntropyHash(QuicPacketNumber packet_number,
- QuicPacketEntropyHash entropy_hash);
-
- // Sets the entropy hash up to but not including a packet number based
- // on the hash provided by a StopWaiting frame. Clears older packet
- // entropy entries and performs garbage collection up to the first gap.
- void SetCumulativeEntropyUpTo(QuicPacketNumber packet_number,
- QuicPacketEntropyHash entropy_hash);
-
- size_t size() const { return packets_entropy_.size(); }
-
- private:
- friend class test::EntropyTrackerPeer;
-
- // A deque indexed by packet number storing the packet's hash and whether
- // a hash was recorded for that packet number.
- typedef std::deque<std::pair<QuicPacketEntropyHash, bool>>
- ReceivedEntropyHashes;
-
- // Recomputes first_gap_ and removes packets_entropy_ entries that are no
- // longer needed to compute EntropyHash.
- void AdvanceFirstGapAndGarbageCollectEntropyMap();
-
- // Map of received packet numbers to their corresponding entropy.
- // Stores an entry for every received packet whose packet_number is larger
- // than first_gap_. Packets without the entropy bit set have an entropy
- // value of 0.
- ReceivedEntropyHashes packets_entropy_;
-
- // Cumulative hash of entropy of all received packets.
- QuicPacketEntropyHash packets_entropy_hash_;
-
- // packet number of the first packet that we do not know the entropy of.
- // If there are no gaps in the received packet sequence,
- // packets_entropy_ will be empty and first_gap_ will be equal to
- // 'largest_observed_ + 1' since that's the first packet for which
- // entropy is unknown. If there are gaps, packets_entropy_ will
- // contain entries for all received packets with packet_number >
- // first_gap_.
- QuicPacketNumber first_gap_;
-
- // packet number of the largest observed packet.
- QuicPacketNumber largest_observed_;
-
- DISALLOW_COPY_AND_ASSIGN(EntropyTracker);
- };
-
explicit QuicReceivedPacketManager(QuicConnectionStats* stats);
- ~QuicReceivedPacketManager() override;
+ virtual ~QuicReceivedPacketManager();
// Updates the internal state concerning which packets have been received.
// header: the packet header.
@@ -119,12 +43,6 @@ class NET_EXPORT_PRIVATE QuicReceivedPacketManager
// another packet is received, or it will change.
const QuicFrame GetUpdatedAckFrame(QuicTime approximate_now);
- // QuicReceivedEntropyHashCalculatorInterface
- // Called by QuicFramer, when the outgoing ack gets truncated, to recalculate
- // the received entropy hash for the truncated ack frame.
- QuicPacketEntropyHash EntropyHash(
- QuicPacketNumber packet_number) const override;
-
// Updates internal state based on |stop_waiting|.
virtual void UpdatePacketInformationSentByPeer(
const QuicStopWaitingFrame& stop_waiting);
@@ -136,12 +54,6 @@ class NET_EXPORT_PRIVATE QuicReceivedPacketManager
// packets of the largest observed.
virtual bool HasNewMissingPackets() const;
- // Returns the number of packets being tracked in the EntropyTracker.
- size_t NumTrackedPackets() const;
-
- // Sets the mode of packets set of ack_frame_ based on |version|.
- void SetVersion(QuicVersion version);
-
QuicPacketNumber peer_least_packet_awaiting_ack() {
return peer_least_packet_awaiting_ack_;
}
@@ -163,9 +75,6 @@ class NET_EXPORT_PRIVATE QuicReceivedPacketManager
// |least_unacked| unacked, false otherwise.
bool DontWaitForPacketsBefore(QuicPacketNumber least_unacked);
- // Tracks entropy hashes of received packets.
- EntropyTracker entropy_tracker_;
-
// Least packet number of the the packet sent by the peer for which it
// hasn't received an ack.
QuicPacketNumber peer_least_packet_awaiting_ack_;
@@ -189,4 +98,4 @@ class NET_EXPORT_PRIVATE QuicReceivedPacketManager
} // namespace net
-#endif // NET_QUIC_QUIC_RECEIVED_PACKET_MANAGER_H_
+#endif // NET_QUIC_CORE_QUIC_RECEIVED_PACKET_MANAGER_H_
diff --git a/chromium/net/quic/core/quic_received_packet_manager_test.cc b/chromium/net/quic/core/quic_received_packet_manager_test.cc
index 65f0a84890e..6a2e02011b6 100644
--- a/chromium/net/quic/core/quic_received_packet_manager_test.cc
+++ b/chromium/net/quic/core/quic_received_packet_manager_test.cc
@@ -5,184 +5,17 @@
#include "net/quic/core/quic_received_packet_manager.h"
#include <algorithm>
+#include <ostream>
#include <vector>
#include "net/quic/core/quic_connection_stats.h"
-#include "net/quic/core/quic_flags.h"
#include "net/quic/test_tools/quic_received_packet_manager_peer.h"
-#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
namespace net {
namespace test {
-
-class EntropyTrackerPeer {
- public:
- static QuicPacketNumber first_gap(
- const QuicReceivedPacketManager::EntropyTracker& tracker) {
- return tracker.first_gap_;
- }
- static QuicPacketNumber largest_observed(
- const QuicReceivedPacketManager::EntropyTracker& tracker) {
- return tracker.largest_observed_;
- }
- static int packets_entropy_size(
- const QuicReceivedPacketManager::EntropyTracker& tracker) {
- return tracker.packets_entropy_.size();
- }
- static bool IsTrackingPacket(
- const QuicReceivedPacketManager::EntropyTracker& tracker,
- QuicPacketNumber packet_number) {
- return packet_number >= tracker.first_gap_ &&
- packet_number <
- (tracker.first_gap_ + tracker.packets_entropy_.size()) &&
- tracker.packets_entropy_[packet_number - tracker.first_gap_].second;
- }
-};
-
namespace {
-// Entropy of individual packets is not tracked if there are no gaps.
-TEST(EntropyTrackerTest, NoGaps) {
- QuicReceivedPacketManager::EntropyTracker tracker;
-
- tracker.RecordPacketEntropyHash(1, 23);
- tracker.RecordPacketEntropyHash(2, 42);
-
- EXPECT_EQ(23 ^ 42, tracker.EntropyHash(2));
- EXPECT_EQ(3u, EntropyTrackerPeer::first_gap(tracker));
-
- EXPECT_EQ(2u, EntropyTrackerPeer::largest_observed(tracker));
- EXPECT_EQ(0, EntropyTrackerPeer::packets_entropy_size(tracker));
- EXPECT_FALSE(EntropyTrackerPeer::IsTrackingPacket(tracker, 1));
- EXPECT_FALSE(EntropyTrackerPeer::IsTrackingPacket(tracker, 2));
-}
-
-// Entropy of individual packets is tracked as long as there are gaps.
-// Filling the first gap results in entropy getting garbage collected.
-TEST(EntropyTrackerTest, FillGaps) {
- QuicReceivedPacketManager::EntropyTracker tracker;
-
- tracker.RecordPacketEntropyHash(2, 5);
- tracker.RecordPacketEntropyHash(5, 17);
- tracker.RecordPacketEntropyHash(6, 23);
- tracker.RecordPacketEntropyHash(9, 42);
-
- EXPECT_EQ(1u, EntropyTrackerPeer::first_gap(tracker));
- EXPECT_EQ(9u, EntropyTrackerPeer::largest_observed(tracker));
- EXPECT_EQ(9, EntropyTrackerPeer::packets_entropy_size(tracker));
-
- EXPECT_EQ(5, tracker.EntropyHash(2));
- EXPECT_EQ(5 ^ 17, tracker.EntropyHash(5));
- EXPECT_EQ(5 ^ 17 ^ 23, tracker.EntropyHash(6));
- EXPECT_EQ(5 ^ 17 ^ 23 ^ 42, tracker.EntropyHash(9));
-
- EXPECT_FALSE(EntropyTrackerPeer::IsTrackingPacket(tracker, 1));
- EXPECT_TRUE(EntropyTrackerPeer::IsTrackingPacket(tracker, 2));
- EXPECT_TRUE(EntropyTrackerPeer::IsTrackingPacket(tracker, 5));
- EXPECT_TRUE(EntropyTrackerPeer::IsTrackingPacket(tracker, 6));
- EXPECT_TRUE(EntropyTrackerPeer::IsTrackingPacket(tracker, 9));
-
- // Fill the gap at 1.
- tracker.RecordPacketEntropyHash(1, 2);
-
- EXPECT_EQ(3u, EntropyTrackerPeer::first_gap(tracker));
- EXPECT_EQ(9u, EntropyTrackerPeer::largest_observed(tracker));
- EXPECT_EQ(7, EntropyTrackerPeer::packets_entropy_size(tracker));
-
- EXPECT_EQ(2 ^ 5 ^ 17, tracker.EntropyHash(5));
- EXPECT_EQ(2 ^ 5 ^ 17 ^ 23, tracker.EntropyHash(6));
- EXPECT_EQ(2 ^ 5 ^ 17 ^ 23 ^ 42, tracker.EntropyHash(9));
-
- EXPECT_FALSE(EntropyTrackerPeer::IsTrackingPacket(tracker, 1));
- EXPECT_FALSE(EntropyTrackerPeer::IsTrackingPacket(tracker, 2));
- EXPECT_TRUE(EntropyTrackerPeer::IsTrackingPacket(tracker, 5));
- EXPECT_TRUE(EntropyTrackerPeer::IsTrackingPacket(tracker, 6));
- EXPECT_TRUE(EntropyTrackerPeer::IsTrackingPacket(tracker, 9));
-
- // Fill the gap at 4.
- tracker.RecordPacketEntropyHash(4, 2);
-
- EXPECT_EQ(3u, EntropyTrackerPeer::first_gap(tracker));
- EXPECT_EQ(9u, EntropyTrackerPeer::largest_observed(tracker));
- EXPECT_EQ(7, EntropyTrackerPeer::packets_entropy_size(tracker));
-
- EXPECT_EQ(5, tracker.EntropyHash(4));
- EXPECT_EQ(5 ^ 17, tracker.EntropyHash(5));
- EXPECT_EQ(5 ^ 17 ^ 23, tracker.EntropyHash(6));
- EXPECT_EQ(5 ^ 17 ^ 23 ^ 42, tracker.EntropyHash(9));
-
- EXPECT_FALSE(EntropyTrackerPeer::IsTrackingPacket(tracker, 3));
- EXPECT_TRUE(EntropyTrackerPeer::IsTrackingPacket(tracker, 4));
- EXPECT_TRUE(EntropyTrackerPeer::IsTrackingPacket(tracker, 5));
- EXPECT_TRUE(EntropyTrackerPeer::IsTrackingPacket(tracker, 6));
- EXPECT_TRUE(EntropyTrackerPeer::IsTrackingPacket(tracker, 9));
-
- // Fill the gap at 3. Entropy for packets 3 to 6 are forgotten.
- tracker.RecordPacketEntropyHash(3, 2);
-
- EXPECT_EQ(7u, EntropyTrackerPeer::first_gap(tracker));
- EXPECT_EQ(9u, EntropyTrackerPeer::largest_observed(tracker));
- EXPECT_EQ(3, EntropyTrackerPeer::packets_entropy_size(tracker));
-
- EXPECT_EQ(2 ^ 5 ^ 17 ^ 23 ^ 42, tracker.EntropyHash(9));
-
- EXPECT_FALSE(EntropyTrackerPeer::IsTrackingPacket(tracker, 3));
- EXPECT_FALSE(EntropyTrackerPeer::IsTrackingPacket(tracker, 4));
- EXPECT_FALSE(EntropyTrackerPeer::IsTrackingPacket(tracker, 5));
- EXPECT_FALSE(EntropyTrackerPeer::IsTrackingPacket(tracker, 6));
- EXPECT_TRUE(EntropyTrackerPeer::IsTrackingPacket(tracker, 9));
-
- // Fill in the rest.
- tracker.RecordPacketEntropyHash(7, 2);
- tracker.RecordPacketEntropyHash(8, 2);
-
- EXPECT_EQ(10u, EntropyTrackerPeer::first_gap(tracker));
- EXPECT_EQ(9u, EntropyTrackerPeer::largest_observed(tracker));
- EXPECT_EQ(0, EntropyTrackerPeer::packets_entropy_size(tracker));
-
- EXPECT_EQ(2 ^ 5 ^ 17 ^ 23 ^ 42, tracker.EntropyHash(9));
-}
-
-TEST(EntropyTrackerTest, SetCumulativeEntropyUpTo) {
- QuicReceivedPacketManager::EntropyTracker tracker;
-
- tracker.RecordPacketEntropyHash(2, 5);
- tracker.RecordPacketEntropyHash(5, 17);
- tracker.RecordPacketEntropyHash(6, 23);
- tracker.RecordPacketEntropyHash(9, 42);
-
- EXPECT_EQ(1u, EntropyTrackerPeer::first_gap(tracker));
- EXPECT_EQ(9u, EntropyTrackerPeer::largest_observed(tracker));
- EXPECT_EQ(9, EntropyTrackerPeer::packets_entropy_size(tracker));
-
- // Inform the tracker about value of the hash at a gap.
- tracker.SetCumulativeEntropyUpTo(3, 7);
- EXPECT_EQ(3u, EntropyTrackerPeer::first_gap(tracker));
- EXPECT_EQ(9u, EntropyTrackerPeer::largest_observed(tracker));
- EXPECT_EQ(7, EntropyTrackerPeer::packets_entropy_size(tracker));
-
- EXPECT_EQ(7 ^ 17, tracker.EntropyHash(5));
- EXPECT_EQ(7 ^ 17 ^ 23, tracker.EntropyHash(6));
- EXPECT_EQ(7 ^ 17 ^ 23 ^ 42, tracker.EntropyHash(9));
-
- // Inform the tracker about value of the hash at a known location.
- tracker.SetCumulativeEntropyUpTo(6, 1);
- EXPECT_EQ(7u, EntropyTrackerPeer::first_gap(tracker));
- EXPECT_EQ(9u, EntropyTrackerPeer::largest_observed(tracker));
- EXPECT_EQ(3, EntropyTrackerPeer::packets_entropy_size(tracker));
-
- EXPECT_EQ(1 ^ 23 ^ 42, tracker.EntropyHash(9));
-
- // Inform the tracker about value of the hash at the last location.
- tracker.SetCumulativeEntropyUpTo(9, 21);
- EXPECT_EQ(10u, EntropyTrackerPeer::first_gap(tracker));
- EXPECT_EQ(9u, EntropyTrackerPeer::largest_observed(tracker));
- EXPECT_EQ(0, EntropyTrackerPeer::packets_entropy_size(tracker));
-
- EXPECT_EQ(42 ^ 21, tracker.EntropyHash(9));
-}
-
struct TestParams {
explicit TestParams(QuicVersion version) : version(version) {}
@@ -206,21 +39,16 @@ std::vector<TestParams> GetTestParams() {
class QuicReceivedPacketManagerTest
: public ::testing::TestWithParam<TestParams> {
protected:
- QuicReceivedPacketManagerTest() : received_manager_(&stats_) {
- received_manager_.SetVersion(GetParam().version);
- }
+ QuicReceivedPacketManagerTest() : received_manager_(&stats_) {}
- void RecordPacketReceipt(QuicPacketNumber packet_number,
- QuicPacketEntropyHash entropy_hash) {
- RecordPacketReceipt(packet_number, entropy_hash, QuicTime::Zero());
+ void RecordPacketReceipt(QuicPacketNumber packet_number) {
+ RecordPacketReceipt(packet_number, QuicTime::Zero());
}
void RecordPacketReceipt(QuicPacketNumber packet_number,
- QuicPacketEntropyHash entropy_hash,
QuicTime receipt_time) {
QuicPacketHeader header;
header.packet_number = packet_number;
- header.entropy_hash = entropy_hash;
received_manager_.RecordPacketReceived(header, receipt_time);
}
@@ -232,96 +60,6 @@ INSTANTIATE_TEST_CASE_P(QuicReceivedPacketManagerTest,
QuicReceivedPacketManagerTest,
::testing::ValuesIn(GetTestParams()));
-TEST_P(QuicReceivedPacketManagerTest, ReceivedPacketEntropyHash) {
- if (GetParam().version > QUIC_VERSION_33) {
- return;
- }
- std::vector<std::pair<QuicPacketNumber, QuicPacketEntropyHash>> entropies;
- entropies.push_back(std::make_pair(1, 12));
- entropies.push_back(std::make_pair(7, 1));
- entropies.push_back(std::make_pair(2, 33));
- entropies.push_back(std::make_pair(5, 3));
- entropies.push_back(std::make_pair(8, 34));
-
- for (size_t i = 0; i < entropies.size(); ++i) {
- RecordPacketReceipt(entropies[i].first, entropies[i].second);
- }
-
- std::sort(entropies.begin(), entropies.end());
-
- QuicPacketEntropyHash hash = 0;
- size_t index = 0;
- for (size_t i = 1; i <= (*entropies.rbegin()).first; ++i) {
- if (entropies[index].first == i) {
- hash ^= entropies[index].second;
- ++index;
- }
- if (i < 3)
- continue;
- EXPECT_EQ(hash, received_manager_.EntropyHash(i));
- }
- // Reorder by 5 when 2 is received after 7.
- EXPECT_EQ(5u, stats_.max_sequence_reordering);
- EXPECT_EQ(0, stats_.max_time_reordering_us);
- EXPECT_EQ(2u, stats_.packets_reordered);
-}
-
-TEST_P(QuicReceivedPacketManagerTest, EntropyHashBelowLeastObserved) {
- if (GetParam().version > QUIC_VERSION_33) {
- return;
- }
- EXPECT_EQ(0, received_manager_.EntropyHash(0));
- RecordPacketReceipt(4, 5);
- EXPECT_EQ(0, received_manager_.EntropyHash(3));
-}
-
-TEST_P(QuicReceivedPacketManagerTest, EntropyHashAboveLargestObserved) {
- if (GetParam().version > QUIC_VERSION_33) {
- return;
- }
- EXPECT_EQ(0, received_manager_.EntropyHash(0));
- RecordPacketReceipt(4, 5);
- EXPECT_EQ(0, received_manager_.EntropyHash(3));
-}
-
-TEST_P(QuicReceivedPacketManagerTest, SetCumulativeEntropyUpTo) {
- if (GetParam().version > QUIC_VERSION_33) {
- return;
- }
- std::vector<std::pair<QuicPacketNumber, QuicPacketEntropyHash>> entropies;
- entropies.push_back(std::make_pair(1, 12));
- entropies.push_back(std::make_pair(2, 1));
- entropies.push_back(std::make_pair(3, 33));
- entropies.push_back(std::make_pair(4, 3));
- entropies.push_back(std::make_pair(6, 34));
- entropies.push_back(std::make_pair(7, 29));
-
- QuicPacketEntropyHash entropy_hash = 0;
- for (size_t i = 0; i < entropies.size(); ++i) {
- RecordPacketReceipt(entropies[i].first, entropies[i].second);
- entropy_hash ^= entropies[i].second;
- }
- EXPECT_EQ(entropy_hash, received_manager_.EntropyHash(7));
-
- // Now set the entropy hash up to 5 to be 100.
- entropy_hash ^= 100;
- for (size_t i = 0; i < 4; ++i) {
- entropy_hash ^= entropies[i].second;
- }
- QuicReceivedPacketManagerPeer::SetCumulativeEntropyUpTo(&received_manager_, 5,
- 100);
- EXPECT_EQ(entropy_hash, received_manager_.EntropyHash(7));
-
- QuicReceivedPacketManagerPeer::SetCumulativeEntropyUpTo(&received_manager_, 1,
- 50);
- EXPECT_EQ(entropy_hash, received_manager_.EntropyHash(7));
-
- // No reordering.
- EXPECT_EQ(0u, stats_.max_sequence_reordering);
- EXPECT_EQ(0, stats_.max_time_reordering_us);
- EXPECT_EQ(0u, stats_.packets_reordered);
-}
-
TEST_P(QuicReceivedPacketManagerTest, DontWaitForPacketsBefore) {
QuicPacketHeader header;
header.packet_number = 2u;
@@ -377,10 +115,10 @@ TEST_P(QuicReceivedPacketManagerTest, GetUpdatedAckFrame) {
TEST_P(QuicReceivedPacketManagerTest, UpdateReceivedConnectionStats) {
EXPECT_FALSE(received_manager_.ack_frame_updated());
- RecordPacketReceipt(1, 0);
+ RecordPacketReceipt(1);
EXPECT_TRUE(received_manager_.ack_frame_updated());
- RecordPacketReceipt(6, 0);
- RecordPacketReceipt(2, 0,
+ RecordPacketReceipt(6);
+ RecordPacketReceipt(2,
QuicTime::Zero() + QuicTime::Delta::FromMilliseconds(1));
EXPECT_EQ(4u, stats_.max_sequence_reordering);
diff --git a/chromium/net/quic/core/quic_sent_entropy_manager.cc b/chromium/net/quic/core/quic_sent_entropy_manager.cc
deleted file mode 100644
index f10e5bc7673..00000000000
--- a/chromium/net/quic/core/quic_sent_entropy_manager.cc
+++ /dev/null
@@ -1,113 +0,0 @@
-// Copyright 2013 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.
-
-#include "net/quic/core/quic_sent_entropy_manager.h"
-
-#include "base/logging.h"
-#include "net/base/linked_hash_map.h"
-#include "net/quic/core/quic_flags.h"
-
-using std::make_pair;
-using std::max;
-using std::min;
-
-namespace net {
-
-QuicSentEntropyManager::QuicSentEntropyManager() : map_offset_(1) {}
-
-QuicSentEntropyManager::~QuicSentEntropyManager() {}
-
-QuicPacketEntropyHash QuicSentEntropyManager::GetPacketEntropy(
- QuicPacketNumber packet_number) const {
- return packets_entropy_[packet_number - map_offset_];
-}
-
-QuicPacketNumber QuicSentEntropyManager::GetLargestPacketWithEntropy() const {
- return map_offset_ + packets_entropy_.size() - 1;
-}
-
-QuicPacketNumber QuicSentEntropyManager::GetSmallestPacketWithEntropy() const {
- return map_offset_;
-}
-
-void QuicSentEntropyManager::UpdateCumulativeEntropy(
- QuicPacketNumber packet_number,
- CumulativeEntropy* cumulative) const {
- while (cumulative->packet_number < packet_number) {
- ++cumulative->packet_number;
- cumulative->entropy ^= GetPacketEntropy(cumulative->packet_number);
- }
-}
-
-void QuicSentEntropyManager::RecordPacketEntropyHash(
- QuicPacketNumber packet_number,
- QuicPacketEntropyHash entropy_hash) {
- if (!packets_entropy_.empty()) {
- // Ensure packets always are recorded in order.
- // Every packet's entropy is recorded, even if it's not sent, so there
- // are not packet number gaps.
- DCHECK_EQ(GetLargestPacketWithEntropy() + 1, packet_number);
- }
- packets_entropy_.push_back(entropy_hash);
- DVLOG(2) << "Recorded packet number " << packet_number
- << " with entropy hash: " << static_cast<int>(entropy_hash);
-}
-
-QuicPacketEntropyHash QuicSentEntropyManager::GetCumulativeEntropy(
- QuicPacketNumber packet_number) {
- DCHECK_LE(last_cumulative_entropy_.packet_number, packet_number);
- DCHECK_GE(GetLargestPacketWithEntropy(), packet_number);
- // First the entropy for largest_observed packet number should be updated.
- UpdateCumulativeEntropy(packet_number, &last_cumulative_entropy_);
- return last_cumulative_entropy_.entropy;
-}
-
-bool QuicSentEntropyManager::IsValidEntropy(
- QuicPacketNumber largest_observed,
- const PacketNumberQueue& missing_packets,
- QuicPacketEntropyHash entropy_hash) {
- DCHECK_GE(largest_observed, last_valid_entropy_.packet_number);
- // Ensure the largest and smallest packet numbers are in range.
- if (largest_observed > GetLargestPacketWithEntropy()) {
- return false;
- }
- if (!missing_packets.Empty() &&
- missing_packets.Min() < GetSmallestPacketWithEntropy()) {
- return false;
- }
- // First the entropy for largest_observed packet number should be updated.
- UpdateCumulativeEntropy(largest_observed, &last_valid_entropy_);
-
- // Now XOR out all the missing entropies.
- QuicPacketEntropyHash expected_entropy_hash = last_valid_entropy_.entropy;
- for (const Interval<QuicPacketNumber>& interval : missing_packets) {
- for (QuicPacketNumber packet_number = interval.min();
- packet_number < interval.max(); ++packet_number) {
- expected_entropy_hash ^= GetPacketEntropy(packet_number);
- }
- }
- DLOG_IF(WARNING, entropy_hash != expected_entropy_hash)
- << "Invalid entropy hash: " << static_cast<int>(entropy_hash)
- << " expected entropy hash: " << static_cast<int>(expected_entropy_hash);
- return entropy_hash == expected_entropy_hash;
-}
-
-void QuicSentEntropyManager::ClearEntropyBefore(
- QuicPacketNumber packet_number) {
- // Don't discard entropy before updating the cumulative entropy used to
- // calculate EntropyHash and IsValidEntropy.
- if (last_cumulative_entropy_.packet_number < packet_number) {
- UpdateCumulativeEntropy(packet_number, &last_cumulative_entropy_);
- }
- if (last_valid_entropy_.packet_number < packet_number) {
- UpdateCumulativeEntropy(packet_number, &last_valid_entropy_);
- }
- while (map_offset_ < packet_number) {
- packets_entropy_.pop_front();
- ++map_offset_;
- }
- DVLOG(2) << "Cleared entropy before: " << packet_number;
-}
-
-} // namespace net
diff --git a/chromium/net/quic/core/quic_sent_entropy_manager.h b/chromium/net/quic/core/quic_sent_entropy_manager.h
deleted file mode 100644
index 59733a028e9..00000000000
--- a/chromium/net/quic/core/quic_sent_entropy_manager.h
+++ /dev/null
@@ -1,89 +0,0 @@
-// Copyright 2013 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.
-//
-// Manages the packet entropy calculation for both sent and received packets
-// for a connection.
-
-#ifndef NET_QUIC_QUIC_SENT_ENTROPY_MANAGER_H_
-#define NET_QUIC_QUIC_SENT_ENTROPY_MANAGER_H_
-
-#include <deque>
-
-#include "base/macros.h"
-#include "net/base/linked_hash_map.h"
-#include "net/base/net_export.h"
-#include "net/quic/core/quic_framer.h"
-#include "net/quic/core/quic_protocol.h"
-
-namespace net {
-
-namespace test {
-class QuicConnectionPeer;
-} // namespace test
-
-// Records all sent packets by a connection to track the cumulative entropy of
-// sent packets. It is used by the connection to validate an ack
-// frame sent by the peer as a preventive measure against the optimistic ack
-// attack.
-class NET_EXPORT_PRIVATE QuicSentEntropyManager {
- public:
- QuicSentEntropyManager();
- virtual ~QuicSentEntropyManager();
-
- // Record |entropy_hash| for sent packet corresponding to |packet_number|.
- void RecordPacketEntropyHash(QuicPacketNumber packet_number,
- QuicPacketEntropyHash entropy_hash);
-
- // Retrieves the cumulative entropy up to |packet_number|.
- // Must always be called with a monotonically increasing |packet_number|.
- QuicPacketEntropyHash GetCumulativeEntropy(QuicPacketNumber packet_number);
-
- // Returns true if |entropy_hash| matches the expected sent entropy hash
- // up to |largest_observed| removing packet numbers from |missing_packets|.
- // Must always be called with a monotonically increasing |largest_observed|.
- bool IsValidEntropy(QuicPacketNumber largest_observed,
- const PacketNumberQueue& missing_packets,
- QuicPacketEntropyHash entropy_hash);
-
- // Removes unnecessary entries before |packet_number|.
- void ClearEntropyBefore(QuicPacketNumber packet_number);
-
- private:
- friend class test::QuicConnectionPeer;
-
- typedef std::deque<QuicPacketEntropyHash> SentEntropyMap;
-
- struct CumulativeEntropy {
- CumulativeEntropy() : packet_number(0), entropy(0) {}
-
- QuicPacketNumber packet_number;
- QuicPacketEntropyHash entropy;
- };
-
- // Convenience methods to get the largest and smallest packets with entropies.
- QuicPacketNumber GetLargestPacketWithEntropy() const;
- QuicPacketNumber GetSmallestPacketWithEntropy() const;
- // Convenience method to get the entropy hash for |packet_number|.
- QuicPacketEntropyHash GetPacketEntropy(QuicPacketNumber packet_number) const;
-
- // Update the cumulative entropy to |packet_number|.
- void UpdateCumulativeEntropy(QuicPacketNumber packet_number,
- CumulativeEntropy* cumulative) const;
-
- // Maps packet numbers to the sent entropy hash for the packet number.
- SentEntropyMap packets_entropy_;
- QuicPacketNumber map_offset_;
-
- // Cache the cumulative entropy for IsValidEntropy.
- CumulativeEntropy last_valid_entropy_;
-
- // Cache the cumulative entropy for the packet number used by EntropyHash.
- CumulativeEntropy last_cumulative_entropy_;
-
- DISALLOW_COPY_AND_ASSIGN(QuicSentEntropyManager);
-};
-
-} // namespace net
-
-#endif // NET_QUIC_QUIC_SENT_ENTROPY_MANAGER_H_
diff --git a/chromium/net/quic/core/quic_sent_entropy_manager_test.cc b/chromium/net/quic/core/quic_sent_entropy_manager_test.cc
deleted file mode 100644
index 1f30ab0f558..00000000000
--- a/chromium/net/quic/core/quic_sent_entropy_manager_test.cc
+++ /dev/null
@@ -1,96 +0,0 @@
-// Copyright 2013 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.
-
-#include "net/quic/core/quic_sent_entropy_manager.h"
-
-#include <algorithm>
-#include <vector>
-
-#include "testing/gmock/include/gmock/gmock.h"
-#include "testing/gtest/include/gtest/gtest.h"
-
-using std::make_pair;
-using std::pair;
-
-namespace net {
-namespace test {
-namespace {
-
-class QuicSentEntropyManagerTest : public ::testing::Test {
- protected:
- QuicSentEntropyManager entropy_manager_;
-};
-
-TEST_F(QuicSentEntropyManagerTest, SentEntropyHash) {
- EXPECT_EQ(0, entropy_manager_.GetCumulativeEntropy(0));
-
- QuicPacketEntropyHash entropies[4] = {12, 1, 33, 3};
- for (size_t i = 0; i < arraysize(entropies); ++i) {
- entropy_manager_.RecordPacketEntropyHash(i + 1, entropies[i]);
- }
-
- QuicPacketEntropyHash hash = 0;
- for (size_t i = 0; i < arraysize(entropies); ++i) {
- hash ^= entropies[i];
- EXPECT_EQ(hash, entropy_manager_.GetCumulativeEntropy(i + 1));
- }
-}
-
-TEST_F(QuicSentEntropyManagerTest, IsValidEntropy) {
- QuicPacketEntropyHash entropies[10] = {12, 1, 33, 3, 32,
- 100, 28, 42, 22, 255};
- for (size_t i = 0; i < arraysize(entropies); ++i) {
- entropy_manager_.RecordPacketEntropyHash(i + 1, entropies[i]);
- }
-
- PacketNumberQueue missing_packets;
- missing_packets.Add(1);
- missing_packets.Add(4);
- missing_packets.Add(7, 9);
-
- QuicPacketEntropyHash entropy_hash = 0;
- for (size_t i = 0; i < arraysize(entropies); ++i) {
- if (!missing_packets.Contains(i + 1)) {
- entropy_hash ^= entropies[i];
- }
- }
-
- EXPECT_TRUE(
- entropy_manager_.IsValidEntropy(10, missing_packets, entropy_hash));
-}
-
-TEST_F(QuicSentEntropyManagerTest, ClearEntropiesBefore) {
- QuicPacketEntropyHash entropies[10] = {12, 1, 33, 3, 32,
- 100, 28, 42, 22, 255};
-
- for (size_t i = 0; i < arraysize(entropies); ++i) {
- entropy_manager_.RecordPacketEntropyHash(i + 1, entropies[i]);
- }
-
- // Discard the first 5 entropies and ensure IsValidEntropy and EntropyHash
- // still return correct results.
- entropy_manager_.ClearEntropyBefore(5);
-
- PacketNumberQueue missing_packets;
- missing_packets.Add(7, 9);
-
- QuicPacketEntropyHash entropy_hash = 0;
- for (size_t i = 0; i < arraysize(entropies); ++i) {
- if (!missing_packets.Contains(i + 1)) {
- entropy_hash ^= entropies[i];
- }
- }
- EXPECT_TRUE(
- entropy_manager_.IsValidEntropy(10, missing_packets, entropy_hash));
-
- entropy_hash = 0;
- for (size_t i = 0; i < arraysize(entropies); ++i) {
- entropy_hash ^= entropies[i];
- }
- EXPECT_EQ(entropy_hash, entropy_manager_.GetCumulativeEntropy(10));
-}
-
-} // namespace
-} // namespace test
-} // namespace net
diff --git a/chromium/net/quic/core/quic_sent_packet_manager.cc b/chromium/net/quic/core/quic_sent_packet_manager.cc
index 965a96f9179..21646fbd25f 100644
--- a/chromium/net/quic/core/quic_sent_packet_manager.cc
+++ b/chromium/net/quic/core/quic_sent_packet_manager.cc
@@ -7,20 +7,17 @@
#include <algorithm>
#include <string>
-#include "base/logging.h"
#include "base/stl_util.h"
#include "net/quic/chromium/quic_utils_chromium.h"
#include "net/quic/core/congestion_control/general_loss_algorithm.h"
#include "net/quic/core/congestion_control/pacing_sender.h"
#include "net/quic/core/crypto/crypto_protocol.h"
#include "net/quic/core/proto/cached_network_parameters.pb.h"
-#include "net/quic/core/quic_bug_tracker.h"
#include "net/quic/core/quic_connection_stats.h"
#include "net/quic/core/quic_flags.h"
-
-using std::max;
-using std::min;
-using std::pair;
+#include "net/quic/core/quic_pending_retransmission.h"
+#include "net/quic/platform/api/quic_bug_tracker.h"
+#include "net/quic/platform/api/quic_logging.h"
namespace net {
@@ -45,7 +42,7 @@ static const int64_t kConservativeMinHandshakeTimeoutMs = kMaxDelayedAckTimeMs;
// per draft RFC draft-dukkipati-tcpm-tcp-loss-probe.
static const size_t kDefaultMaxTailLossProbes = 2;
-bool HasCryptoHandshake(const TransmissionInfo& transmission_info) {
+bool HasCryptoHandshake(const QuicTransmissionInfo& transmission_info) {
DCHECK(!transmission_info.has_crypto_handshake ||
!transmission_info.retransmittable_frames.empty());
return transmission_info.has_crypto_handshake;
@@ -58,25 +55,20 @@ bool HasCryptoHandshake(const TransmissionInfo& transmission_info) {
QuicSentPacketManager::QuicSentPacketManager(
Perspective perspective,
- QuicPathId path_id,
const QuicClock* clock,
QuicConnectionStats* stats,
CongestionControlType congestion_control_type,
- LossDetectionType loss_type,
- MultipathDelegateInterface* delegate)
+ LossDetectionType loss_type)
: unacked_packets_(),
perspective_(perspective),
- path_id_(path_id),
clock_(clock),
stats_(stats),
- delegate_(delegate),
debug_delegate_(nullptr),
network_change_visitor_(nullptr),
initial_congestion_window_(kInitialCongestionWindow),
loss_algorithm_(&general_loss_algorithm_),
general_loss_algorithm_(loss_type),
n_connection_simulation_(false),
- receive_buffer_bytes_(kDefaultSocketReceiveBuffer),
least_packet_awaited_by_peer_(1),
first_rto_transmission_(0),
consecutive_rto_count_(0),
@@ -101,33 +93,50 @@ void QuicSentPacketManager::SetFromConfig(const QuicConfig& config) {
if (config.HasReceivedInitialRoundTripTimeUs() &&
config.ReceivedInitialRoundTripTimeUs() > 0) {
rtt_stats_.set_initial_rtt_us(
- max(kMinInitialRoundTripTimeUs,
- min(kMaxInitialRoundTripTimeUs,
- config.ReceivedInitialRoundTripTimeUs())));
+ std::max(kMinInitialRoundTripTimeUs,
+ std::min(kMaxInitialRoundTripTimeUs,
+ config.ReceivedInitialRoundTripTimeUs())));
} else if (config.HasInitialRoundTripTimeUsToSend() &&
config.GetInitialRoundTripTimeUsToSend() > 0) {
rtt_stats_.set_initial_rtt_us(
- max(kMinInitialRoundTripTimeUs,
- min(kMaxInitialRoundTripTimeUs,
- config.GetInitialRoundTripTimeUsToSend())));
- }
- if (FLAGS_quic_allow_new_bbr && config.HasReceivedConnectionOptions() &&
- ContainsQuicTag(config.ReceivedConnectionOptions(), kTBBR)) {
- SetSendAlgorithm(kBBR);
- }
- if (config.HasReceivedConnectionOptions() &&
- ContainsQuicTag(config.ReceivedConnectionOptions(), kRENO)) {
- if (ContainsQuicTag(config.ReceivedConnectionOptions(), kBYTE)) {
- SetSendAlgorithm(kRenoBytes);
- } else {
- SetSendAlgorithm(kReno);
+ std::max(kMinInitialRoundTripTimeUs,
+ std::min(kMaxInitialRoundTripTimeUs,
+ config.GetInitialRoundTripTimeUsToSend())));
+ }
+ // Configure congestion control.
+ const bool enable_client_connection_options =
+ FLAGS_quic_reloadable_flag_quic_client_connection_options;
+ if (enable_client_connection_options) {
+ if (FLAGS_quic_reloadable_flag_quic_allow_new_bbr &&
+ config.HasClientRequestedIndependentOption(kTBBR, perspective_)) {
+ SetSendAlgorithm(kBBR);
}
- } else if (config.HasReceivedConnectionOptions() &&
- ContainsQuicTag(config.ReceivedConnectionOptions(), kBYTE)) {
- if (FLAGS_quic_default_enable_cubic_bytes) {
+ if (config.HasClientRequestedIndependentOption(kRENO, perspective_)) {
+ if (config.HasClientRequestedIndependentOption(kBYTE, perspective_)) {
+ SetSendAlgorithm(kRenoBytes);
+ } else {
+ SetSendAlgorithm(kReno);
+ }
+ } else if (config.HasClientRequestedIndependentOption(kBYTE,
+ perspective_)) {
+ SetSendAlgorithm(kCubic);
+ }
+ } else {
+ if (FLAGS_quic_reloadable_flag_quic_allow_new_bbr &&
+ config.HasReceivedConnectionOptions() &&
+ ContainsQuicTag(config.ReceivedConnectionOptions(), kTBBR)) {
+ SetSendAlgorithm(kBBR);
+ }
+ if (config.HasReceivedConnectionOptions() &&
+ ContainsQuicTag(config.ReceivedConnectionOptions(), kRENO)) {
+ if (ContainsQuicTag(config.ReceivedConnectionOptions(), kBYTE)) {
+ SetSendAlgorithm(kRenoBytes);
+ } else {
+ SetSendAlgorithm(kReno);
+ }
+ } else if (config.HasReceivedConnectionOptions() &&
+ ContainsQuicTag(config.ReceivedConnectionOptions(), kBYTE)) {
SetSendAlgorithm(kCubic);
- } else {
- SetSendAlgorithm(kCubicBytes);
}
}
using_pacing_ = !FLAGS_quic_disable_pacing_for_perf_tests;
@@ -147,22 +156,37 @@ void QuicSentPacketManager::SetFromConfig(const QuicConfig& config) {
if (config.HasClientSentConnectionOption(kNRTO, perspective_)) {
use_new_rto_ = true;
}
- if (config.HasReceivedConnectionOptions() &&
- ContainsQuicTag(config.ReceivedConnectionOptions(), kTIME)) {
- general_loss_algorithm_.SetLossDetectionType(kTime);
- }
- if (config.HasReceivedConnectionOptions() &&
- ContainsQuicTag(config.ReceivedConnectionOptions(), kATIM)) {
- general_loss_algorithm_.SetLossDetectionType(kAdaptiveTime);
- }
- if (FLAGS_quic_enable_lazy_fack && config.HasReceivedConnectionOptions() &&
- ContainsQuicTag(config.ReceivedConnectionOptions(), kLFAK)) {
- general_loss_algorithm_.SetLossDetectionType(kLazyFack);
+ // Configure loss detection.
+ if (enable_client_connection_options) {
+ if (config.HasClientRequestedIndependentOption(kTIME, perspective_)) {
+ general_loss_algorithm_.SetLossDetectionType(kTime);
+ }
+ if (config.HasClientRequestedIndependentOption(kATIM, perspective_)) {
+ general_loss_algorithm_.SetLossDetectionType(kAdaptiveTime);
+ }
+ if (FLAGS_quic_reloadable_flag_quic_enable_lazy_fack &&
+ config.HasClientRequestedIndependentOption(kLFAK, perspective_)) {
+ general_loss_algorithm_.SetLossDetectionType(kLazyFack);
+ }
+ } else {
+ if (config.HasReceivedConnectionOptions() &&
+ ContainsQuicTag(config.ReceivedConnectionOptions(), kTIME)) {
+ general_loss_algorithm_.SetLossDetectionType(kTime);
+ }
+ if (config.HasReceivedConnectionOptions() &&
+ ContainsQuicTag(config.ReceivedConnectionOptions(), kATIM)) {
+ general_loss_algorithm_.SetLossDetectionType(kAdaptiveTime);
+ }
+ if (FLAGS_quic_reloadable_flag_quic_enable_lazy_fack &&
+ config.HasReceivedConnectionOptions() &&
+ ContainsQuicTag(config.ReceivedConnectionOptions(), kLFAK)) {
+ general_loss_algorithm_.SetLossDetectionType(kLazyFack);
+ }
}
if (config.HasClientSentConnectionOption(kUNDO, perspective_)) {
undo_pending_retransmits_ = true;
}
- if (FLAGS_quic_conservative_handshake_retransmits &&
+ if (FLAGS_quic_reloadable_flag_quic_conservative_handshake_retransmits &&
config.HasClientSentConnectionOption(kCONH, perspective_)) {
conservative_handshake_retransmits_ = true;
}
@@ -180,8 +204,8 @@ void QuicSentPacketManager::ResumeConnectionState(
uint32_t initial_rtt_us =
kNumMicrosPerMilli * cached_network_params.min_rtt_ms();
rtt_stats_.set_initial_rtt_us(
- max(kMinInitialRoundTripTimeUs,
- min(kMaxInitialRoundTripTimeUs, initial_rtt_us)));
+ std::max(kMinInitialRoundTripTimeUs,
+ std::min(kMaxInitialRoundTripTimeUs, initial_rtt_us)));
}
send_algorithm_->ResumeConnectionState(cached_network_params,
max_bandwidth_resumption);
@@ -191,7 +215,7 @@ void QuicSentPacketManager::SetNumOpenStreams(size_t num_streams) {
if (n_connection_simulation_) {
// Ensure the number of connections is between 1 and 5.
send_algorithm_->SetNumEmulatedConnections(
- min<size_t>(5, max<size_t>(1, num_streams)));
+ std::min<size_t>(5, std::max<size_t>(1, num_streams)));
}
}
@@ -262,7 +286,7 @@ void QuicSentPacketManager::OnIncomingAck(const QuicAckFrame& ack_frame,
if (debug_delegate_ != nullptr) {
debug_delegate_->OnIncomingAck(ack_frame, ack_receive_time,
unacked_packets_.largest_observed(),
- rtt_updated, GetLeastUnacked(path_id_));
+ rtt_updated, GetLeastUnacked());
}
}
@@ -309,13 +333,12 @@ void QuicSentPacketManager::HandleAckForSentPackets(
break;
}
- if ((ack_frame.missing && ack_frame.packets.Contains(packet_number)) ||
- (!ack_frame.missing && !ack_frame.packets.Contains(packet_number))) {
+ if (!ack_frame.packets.Contains(packet_number)) {
// Packet is still missing.
continue;
}
// Packet was acked, so remove it from our unacked packet list.
- DVLOG(1) << ENDPOINT << "Got an ack for packet " << packet_number;
+ QUIC_DVLOG(1) << ENDPOINT << "Got an ack for packet " << packet_number;
// If data is associated with the most recent transmission of this
// packet, then inform the caller.
if (it->in_flight) {
@@ -353,11 +376,7 @@ void QuicSentPacketManager::NeuterUnencryptedPackets() {
// or otherwise. Unencrypted packets are neutered and abandoned, to ensure
// they are not retransmitted or considered lost from a congestion control
// perspective.
- if (delegate_ != nullptr) {
- delegate_->OnUnencryptedPacketsNeutered(path_id_, packet_number);
- } else {
- pending_retransmissions_.erase(packet_number);
- }
+ pending_retransmissions_.erase(packet_number);
unacked_packets_.RemoveFromInFlight(packet_number);
unacked_packets_.RemoveRetransmittability(packet_number);
}
@@ -367,7 +386,7 @@ void QuicSentPacketManager::NeuterUnencryptedPackets() {
void QuicSentPacketManager::MarkForRetransmission(
QuicPacketNumber packet_number,
TransmissionType transmission_type) {
- const TransmissionInfo& transmission_info =
+ const QuicTransmissionInfo& transmission_info =
unacked_packets_.GetTransmissionInfo(packet_number);
QUIC_BUG_IF(transmission_info.retransmittable_frames.empty());
// Both TLP and the new RTO leave the packets in flight and let the loss
@@ -376,10 +395,6 @@ void QuicSentPacketManager::MarkForRetransmission(
transmission_type != RTO_RETRANSMISSION) {
unacked_packets_.RemoveFromInFlight(packet_number);
}
- if (delegate_ != nullptr) {
- delegate_->OnRetransmissionMarked(path_id_, packet_number,
- transmission_type);
- } else {
// TODO(ianswett): Currently the RTO can fire while there are pending NACK
// retransmissions for the same data, which is not ideal.
if (base::ContainsKey(pending_retransmissions_, packet_number)) {
@@ -387,11 +402,10 @@ void QuicSentPacketManager::MarkForRetransmission(
}
pending_retransmissions_[packet_number] = transmission_type;
- }
}
void QuicSentPacketManager::RecordOneSpuriousRetransmission(
- const TransmissionInfo& info) {
+ const QuicTransmissionInfo& info) {
stats_->bytes_spuriously_retransmitted += info.bytes_sent;
++stats_->packets_spuriously_retransmitted;
if (debug_delegate_ != nullptr) {
@@ -401,11 +415,11 @@ void QuicSentPacketManager::RecordOneSpuriousRetransmission(
}
void QuicSentPacketManager::RecordSpuriousRetransmissions(
- const TransmissionInfo& info,
+ const QuicTransmissionInfo& info,
QuicPacketNumber acked_packet_number) {
QuicPacketNumber retransmission = info.retransmission;
while (retransmission != 0) {
- const TransmissionInfo& retransmit_info =
+ const QuicTransmissionInfo& retransmit_info =
unacked_packets_.GetTransmissionInfo(retransmission);
retransmission = retransmit_info.retransmission;
RecordOneSpuriousRetransmission(retransmit_info);
@@ -422,7 +436,7 @@ bool QuicSentPacketManager::HasPendingRetransmissions() const {
return !pending_retransmissions_.empty();
}
-PendingRetransmission QuicSentPacketManager::NextPendingRetransmission() {
+QuicPendingRetransmission QuicSentPacketManager::NextPendingRetransmission() {
QUIC_BUG_IF(pending_retransmissions_.empty())
<< "Unexpected call to PendingRetransmissions() with empty pending "
<< "retransmission list. Corrupted memory usage imminent.";
@@ -440,21 +454,21 @@ PendingRetransmission QuicSentPacketManager::NextPendingRetransmission() {
}
}
DCHECK(unacked_packets_.IsUnacked(packet_number)) << packet_number;
- const TransmissionInfo& transmission_info =
+ const QuicTransmissionInfo& transmission_info =
unacked_packets_.GetTransmissionInfo(packet_number);
DCHECK(!transmission_info.retransmittable_frames.empty());
- return PendingRetransmission(path_id_, packet_number, transmission_type,
- transmission_info.retransmittable_frames,
- transmission_info.has_crypto_handshake,
- transmission_info.num_padding_bytes,
- transmission_info.encryption_level,
- transmission_info.packet_number_length);
+ return QuicPendingRetransmission(packet_number, transmission_type,
+ transmission_info.retransmittable_frames,
+ transmission_info.has_crypto_handshake,
+ transmission_info.num_padding_bytes,
+ transmission_info.encryption_level,
+ transmission_info.packet_number_length);
}
QuicPacketNumber QuicSentPacketManager::GetNewestRetransmission(
QuicPacketNumber packet_number,
- const TransmissionInfo& transmission_info) const {
+ const QuicTransmissionInfo& transmission_info) const {
QuicPacketNumber retransmission = transmission_info.retransmission;
while (retransmission != 0) {
packet_number = retransmission;
@@ -464,41 +478,13 @@ QuicPacketNumber QuicSentPacketManager::GetNewestRetransmission(
return packet_number;
}
-void QuicSentPacketManager::MarkPacketNotRetransmittable(
- QuicPacketNumber packet_number,
- QuicTime::Delta ack_delay_time) {
- if (!unacked_packets_.IsUnacked(packet_number)) {
- return;
- }
-
- const TransmissionInfo& transmission_info =
- unacked_packets_.GetTransmissionInfo(packet_number);
- QuicPacketNumber newest_transmission =
- GetNewestRetransmission(packet_number, transmission_info);
- // We do not need to retransmit this packet anymore.
- if (delegate_ != nullptr) {
- delegate_->OnPacketMarkedNotRetransmittable(path_id_, newest_transmission,
- ack_delay_time);
- } else {
- pending_retransmissions_.erase(newest_transmission);
- }
-
- unacked_packets_.NotifyAndClearListeners(newest_transmission, ack_delay_time);
- unacked_packets_.RemoveRetransmittability(packet_number);
-}
-
void QuicSentPacketManager::MarkPacketHandled(QuicPacketNumber packet_number,
- TransmissionInfo* info,
+ QuicTransmissionInfo* info,
QuicTime::Delta ack_delay_time) {
QuicPacketNumber newest_transmission =
GetNewestRetransmission(packet_number, *info);
// Remove the most recent packet, if it is pending retransmission.
- if (delegate_ != nullptr) {
- delegate_->OnPacketMarkedHandled(path_id_, newest_transmission,
- ack_delay_time);
- } else {
- pending_retransmissions_.erase(newest_transmission);
- }
+ pending_retransmissions_.erase(newest_transmission);
// The AckListener needs to be notified about the most recent
// transmission, since that's the one only one it tracks.
@@ -515,7 +501,7 @@ void QuicSentPacketManager::MarkPacketHandled(QuicPacketNumber packet_number,
// transmission of a crypto packet is in flight at once.
// TODO(ianswett): Instead of handling all crypto packets special,
// only handle nullptr encrypted packets in a special way.
- const TransmissionInfo& newest_transmission_info =
+ const QuicTransmissionInfo& newest_transmission_info =
unacked_packets_.GetTransmissionInfo(newest_transmission);
if (HasCryptoHandshake(newest_transmission_info)) {
unacked_packets_.RemoveFromInFlight(newest_transmission);
@@ -536,13 +522,12 @@ bool QuicSentPacketManager::HasUnackedPackets() const {
return unacked_packets_.HasUnackedPackets();
}
-QuicPacketNumber QuicSentPacketManager::GetLeastUnacked(QuicPathId) const {
+QuicPacketNumber QuicSentPacketManager::GetLeastUnacked() const {
return unacked_packets_.GetLeastUnacked();
}
bool QuicSentPacketManager::OnPacketSent(
SerializedPacket* serialized_packet,
- QuicPathId /*original_path_id*/,
QuicPacketNumber original_packet_number,
QuicTime sent_time,
TransmissionType transmission_type,
@@ -553,7 +538,7 @@ bool QuicSentPacketManager::OnPacketSent(
QUIC_BUG_IF(serialized_packet->encrypted_length == 0)
<< "Cannot send empty packets.";
- if (delegate_ == nullptr && original_packet_number != 0) {
+ if (original_packet_number != 0) {
pending_retransmissions_.erase(original_packet_number);
}
@@ -652,7 +637,7 @@ bool QuicSentPacketManager::MaybeRetransmitTailLossProbe() {
MarkForRetransmission(packet_number, TLP_RETRANSMISSION);
return true;
}
- DLOG(ERROR)
+ QUIC_DLOG(ERROR)
<< "No retransmittable packets, so RetransmitOldestPacket failed.";
return false;
}
@@ -746,7 +731,7 @@ bool QuicSentPacketManager::MaybeUpdateRTT(const QuicAckFrame& ack_frame,
}
// We calculate the RTT based on the highest ACKed packet number, the lower
// packet numbers will include the ACK aggregation delay.
- const TransmissionInfo& transmission_info =
+ const QuicTransmissionInfo& transmission_info =
unacked_packets_.GetTransmissionInfo(ack_frame.largest_observed);
// Ensure the packet has a valid sent time.
if (transmission_info.sent_time == QuicTime::Zero()) {
@@ -757,15 +742,15 @@ bool QuicSentPacketManager::MaybeUpdateRTT(const QuicAckFrame& ack_frame,
QuicTime::Delta send_delta = ack_receive_time - transmission_info.sent_time;
const int kMaxSendDeltaSeconds = 30;
- if (!FLAGS_quic_allow_large_send_deltas &&
+ if (!FLAGS_quic_reloadable_flag_quic_allow_large_send_deltas &&
send_delta.ToSeconds() > kMaxSendDeltaSeconds) {
// send_delta can be very high if local clock is changed mid-connection.
- LOG(WARNING) << "Excessive send delta: " << send_delta.ToSeconds()
- << ", setting to: " << kMaxSendDeltaSeconds
- << " largest_observed:" << ack_frame.largest_observed
- << " ack_receive_time:" << ack_receive_time.ToDebuggingValue()
- << " sent_time:"
- << transmission_info.sent_time.ToDebuggingValue();
+ QUIC_LOG_FIRST_N(WARNING, 10)
+ << "Excessive send delta: " << send_delta.ToSeconds()
+ << ", setting to: " << kMaxSendDeltaSeconds
+ << " largest_observed:" << ack_frame.largest_observed
+ << " ack_receive_time:" << ack_receive_time.ToDebuggingValue()
+ << " sent_time:" << transmission_info.sent_time.ToDebuggingValue();
return false;
}
rtt_stats_.UpdateRtt(send_delta, ack_frame.ack_delay_time, ack_receive_time);
@@ -773,8 +758,7 @@ bool QuicSentPacketManager::MaybeUpdateRTT(const QuicAckFrame& ack_frame,
return true;
}
-QuicTime::Delta QuicSentPacketManager::TimeUntilSend(QuicTime now,
- QuicPathId* path_id) {
+QuicTime::Delta QuicSentPacketManager::TimeUntilSend(QuicTime now) {
QuicTime::Delta delay = QuicTime::Delta::Infinite();
// The TLP logic is entirely contained within QuicSentPacketManager, so the
// send algorithm does not need to be consulted.
@@ -787,9 +771,6 @@ QuicTime::Delta QuicSentPacketManager::TimeUntilSend(QuicTime now,
delay =
send_algorithm_->TimeUntilSend(now, unacked_packets_.bytes_in_flight());
}
- if (!delay.IsInfinite()) {
- *path_id = path_id_;
- }
return delay;
}
@@ -800,7 +781,7 @@ const QuicTime QuicSentPacketManager::GetRetransmissionTime() const {
pending_timer_transmission_count_ > 0) {
return QuicTime::Zero();
}
- if (FLAGS_quic_more_conservative_retransmission_alarm &&
+ if (FLAGS_quic_reloadable_flag_quic_more_conservative_retransmission_alarm &&
!unacked_packets_.HasUnackedRetransmittableFrames()) {
return QuicTime::Zero();
}
@@ -842,11 +823,11 @@ const QuicTime::Delta QuicSentPacketManager::GetCryptoRetransmissionDelay()
srtt = QuicTime::Delta::FromMicroseconds(rtt_stats_.initial_rtt_us());
}
if (conservative_handshake_retransmits_) {
- delay_ms = max(kConservativeMinHandshakeTimeoutMs,
- static_cast<int64_t>(2 * srtt.ToMilliseconds()));
+ delay_ms = std::max(kConservativeMinHandshakeTimeoutMs,
+ static_cast<int64_t>(2 * srtt.ToMilliseconds()));
} else {
- delay_ms = max(kMinHandshakeTimeoutMs,
- static_cast<int64_t>(1.5 * srtt.ToMilliseconds()));
+ delay_ms = std::max(kMinHandshakeTimeoutMs,
+ static_cast<int64_t>(1.5 * srtt.ToMilliseconds()));
}
return QuicTime::Delta::FromMilliseconds(
delay_ms << consecutive_crypto_retransmission_count_);
@@ -859,16 +840,17 @@ const QuicTime::Delta QuicSentPacketManager::GetTailLossProbeDelay() const {
}
if (enable_half_rtt_tail_loss_probe_ && consecutive_tlp_count_ == 0u) {
return QuicTime::Delta::FromMilliseconds(
- max(kMinTailLossProbeTimeoutMs,
- static_cast<int64_t>(0.5 * srtt.ToMilliseconds())));
+ std::max(kMinTailLossProbeTimeoutMs,
+ static_cast<int64_t>(0.5 * srtt.ToMilliseconds())));
}
if (!unacked_packets_.HasMultipleInFlightPackets()) {
- return std::max(2 * srtt, 1.5 * srtt + QuicTime::Delta::FromMilliseconds(
- kMinRetransmissionTimeMs / 2));
+ return std::max(2 * srtt,
+ 1.5 * srtt + QuicTime::Delta::FromMilliseconds(
+ kMinRetransmissionTimeMs / 2));
}
return QuicTime::Delta::FromMilliseconds(
- max(kMinTailLossProbeTimeoutMs,
- static_cast<int64_t>(2 * srtt.ToMilliseconds())));
+ std::max(kMinTailLossProbeTimeoutMs,
+ static_cast<int64_t>(2 * srtt.ToMilliseconds())));
}
const QuicTime::Delta QuicSentPacketManager::GetRetransmissionDelay() const {
@@ -889,7 +871,7 @@ const QuicTime::Delta QuicSentPacketManager::GetRetransmissionDelay() const {
// Calculate exponential back off.
retransmission_delay =
retransmission_delay *
- (1 << min<size_t>(consecutive_rto_count_, kMaxRetransmissions));
+ (1 << std::min<size_t>(consecutive_rto_count_, kMaxRetransmissions));
if (retransmission_delay.ToMilliseconds() > kMaxRetransmissionTimeMs) {
return QuicTime::Delta::FromMilliseconds(kMaxRetransmissionTimeMs);
@@ -936,9 +918,6 @@ std::string QuicSentPacketManager::GetDebugState() const {
void QuicSentPacketManager::CancelRetransmissionsForStream(
QuicStreamId stream_id) {
unacked_packets_.CancelRetransmissionsForStream(stream_id);
- if (delegate_ != nullptr) {
- return;
- }
PendingRetransmissionMap::iterator it = pending_retransmissions_.begin();
while (it != pending_retransmissions_.end()) {
if (unacked_packets_.HasRetransmittableFrames(it->first)) {
@@ -962,8 +941,7 @@ void QuicSentPacketManager::SetSendAlgorithm(
pacing_sender_.set_sender(send_algorithm);
}
-void QuicSentPacketManager::OnConnectionMigration(QuicPathId,
- PeerAddressChangeType type) {
+void QuicSentPacketManager::OnConnectionMigration(PeerAddressChangeType type) {
if (type == PORT_CHANGE || type == IPV4_SUBNET_CHANGE) {
// Rtt and cwnd do not need to be reset when the peer address change is
// considered to be caused by NATs.
@@ -979,17 +957,16 @@ void QuicSentPacketManager::SetDebugDelegate(DebugDelegate* debug_delegate) {
debug_delegate_ = debug_delegate;
}
-QuicPacketNumber QuicSentPacketManager::GetLargestObserved(QuicPathId) const {
+QuicPacketNumber QuicSentPacketManager::GetLargestObserved() const {
return unacked_packets_.largest_observed();
}
-QuicPacketNumber QuicSentPacketManager::GetLargestSentPacket(QuicPathId) const {
+QuicPacketNumber QuicSentPacketManager::GetLargestSentPacket() const {
return unacked_packets_.largest_sent_packet();
}
// Remove this method when deprecating QUIC_VERSION_33.
-QuicPacketNumber QuicSentPacketManager::GetLeastPacketAwaitedByPeer(
- QuicPathId) const {
+QuicPacketNumber QuicSentPacketManager::GetLeastPacketAwaitedByPeer() const {
return least_packet_awaited_by_peer_;
}
@@ -1012,17 +989,12 @@ size_t QuicSentPacketManager::GetConsecutiveTlpCount() const {
return consecutive_tlp_count_;
}
-TransmissionInfo* QuicSentPacketManager::GetMutableTransmissionInfo(
- QuicPacketNumber packet_number) {
- return unacked_packets_.GetMutableTransmissionInfo(packet_number);
-}
-
-void QuicSentPacketManager::RemoveObsoletePackets() {
- unacked_packets_.RemoveObsoletePackets();
-}
-
void QuicSentPacketManager::OnApplicationLimited() {
send_algorithm_->OnApplicationLimited(unacked_packets_.bytes_in_flight());
}
+const SendAlgorithmInterface* QuicSentPacketManager::GetSendAlgorithm() const {
+ return send_algorithm_.get();
+}
+
} // namespace net
diff --git a/chromium/net/quic/core/quic_sent_packet_manager.h b/chromium/net/quic/core/quic_sent_packet_manager.h
index 4da97b0a2ab..7ed8b90949a 100644
--- a/chromium/net/quic/core/quic_sent_packet_manager.h
+++ b/chromium/net/quic/core/quic_sent_packet_manager.h
@@ -2,8 +2,8 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#ifndef NET_QUIC_QUIC_SENT_PACKET_MANAGER_H_
-#define NET_QUIC_QUIC_SENT_PACKET_MANAGER_H_
+#ifndef NET_QUIC_CORE_QUIC_SENT_PACKET_MANAGER_H_
+#define NET_QUIC_CORE_QUIC_SENT_PACKET_MANAGER_H_
#include <stddef.h>
@@ -15,15 +15,16 @@
#include "base/macros.h"
#include "net/base/linked_hash_map.h"
-#include "net/base/net_export.h"
#include "net/quic/core/congestion_control/general_loss_algorithm.h"
#include "net/quic/core/congestion_control/loss_detection_interface.h"
#include "net/quic/core/congestion_control/pacing_sender.h"
#include "net/quic/core/congestion_control/rtt_stats.h"
#include "net/quic/core/congestion_control/send_algorithm_interface.h"
-#include "net/quic/core/quic_protocol.h"
-#include "net/quic/core/quic_sent_packet_manager_interface.h"
+#include "net/quic/core/quic_packets.h"
+#include "net/quic/core/quic_pending_retransmission.h"
+#include "net/quic/core/quic_sustained_bandwidth_recorder.h"
#include "net/quic/core/quic_unacked_packet_map.h"
+#include "net/quic/platform/api/quic_export.h"
namespace net {
@@ -41,60 +42,73 @@ struct QuicConnectionStats;
// retransmittable data associated with each packet. If a packet is
// retransmitted, it will keep track of each version of a packet so that if a
// previous transmission is acked, the data will not be retransmitted.
-class NET_EXPORT_PRIVATE QuicSentPacketManager
- : public QuicSentPacketManagerInterface {
+class QUIC_EXPORT_PRIVATE QuicSentPacketManager {
public:
- // A delegate interface which manages pending retransmissions.
- class MultipathDelegateInterface {
+ // Interface which gets callbacks from the QuicSentPacketManager at
+ // interesting points. Implementations must not mutate the state of
+ // the packet manager or connection as a result of these callbacks.
+ class QUIC_EXPORT_PRIVATE DebugDelegate {
public:
- virtual ~MultipathDelegateInterface() {}
-
- // Called when unencrypted |packet_number| is requested to be neutered.
- virtual void OnUnencryptedPacketsNeutered(
- QuicPathId path_id,
- QuicPacketNumber packet_number) = 0;
- // Called when |packet_number| is requested to be retransmitted.
- virtual void OnRetransmissionMarked(QuicPathId path_id,
- QuicPacketNumber packet_number,
- TransmissionType transmission_type) = 0;
- // Called when |packet_number| is marked as not retransmittable.
- virtual void OnPacketMarkedNotRetransmittable(
- QuicPathId path_id,
- QuicPacketNumber packet_number,
- QuicTime::Delta delta_largest_observed) = 0;
- // Called when any transmission of |packet_number| is handled.
- virtual void OnPacketMarkedHandled(
- QuicPathId path_id,
- QuicPacketNumber packet_number,
- QuicTime::Delta delta_largest_observed) = 0;
+ virtual ~DebugDelegate() {}
+
+ // Called when a spurious retransmission is detected.
+ virtual void OnSpuriousPacketRetransmission(
+ TransmissionType transmission_type,
+ QuicByteCount byte_size) {}
+
+ virtual void OnIncomingAck(const QuicAckFrame& ack_frame,
+ QuicTime ack_receive_time,
+ QuicPacketNumber largest_observed,
+ bool rtt_updated,
+ QuicPacketNumber least_unacked_sent_packet) {}
+
+ virtual void OnPacketLoss(QuicPacketNumber lost_packet_number,
+ TransmissionType transmission_type,
+ QuicTime detection_time) {}
+ };
+
+ // Interface which gets callbacks from the QuicSentPacketManager when
+ // network-related state changes. Implementations must not mutate the
+ // state of the packet manager as a result of these callbacks.
+ class QUIC_EXPORT_PRIVATE NetworkChangeVisitor {
+ public:
+ virtual ~NetworkChangeVisitor() {}
+
+ // Called when congestion window or RTT may have changed.
+ virtual void OnCongestionChange() = 0;
+
+ // Called with the path may be degrading. Note that the path may only be
+ // temporarily degrading.
+ // TODO(jri): With multipath, this method should probably have a path_id
+ // parameter, and should maybe result in the path being marked as inactive.
+ virtual void OnPathDegrading() = 0;
+
+ // Called when the Path MTU may have increased.
+ virtual void OnPathMtuIncreased(QuicPacketLength packet_size) = 0;
};
QuicSentPacketManager(Perspective perspective,
- QuicPathId path_id,
const QuicClock* clock,
QuicConnectionStats* stats,
CongestionControlType congestion_control_type,
- LossDetectionType loss_type,
- MultipathDelegateInterface* delegate);
- ~QuicSentPacketManager() override;
+ LossDetectionType loss_type);
+ virtual ~QuicSentPacketManager();
- // Start implementation of QuicSentPacketManagerInterface.
- void SetFromConfig(const QuicConfig& config) override;
+ virtual void SetFromConfig(const QuicConfig& config);
// Pass the CachedNetworkParameters to the send algorithm.
void ResumeConnectionState(
const CachedNetworkParameters& cached_network_params,
- bool max_bandwidth_resumption) override;
+ bool max_bandwidth_resumption);
- void SetNumOpenStreams(size_t num_streams) override;
+ void SetNumOpenStreams(size_t num_streams);
- void SetMaxPacingRate(QuicBandwidth max_pacing_rate) override;
+ void SetMaxPacingRate(QuicBandwidth max_pacing_rate);
- void SetHandshakeConfirmed() override;
+ void SetHandshakeConfirmed();
// Processes the incoming ack.
- void OnIncomingAck(const QuicAckFrame& ack_frame,
- QuicTime ack_receive_time) override;
+ void OnIncomingAck(const QuicAckFrame& ack_frame, QuicTime ack_receive_time);
// Requests retransmission of all unacked packets of |retransmission_type|.
// The behavior of this method depends on the value of |retransmission_type|:
@@ -104,109 +118,109 @@ class NET_EXPORT_PRIVATE QuicSentPacketManager
// ALL_INITIAL_RETRANSMISSION - Only initially encrypted packets will be
// retransmitted. This can happen, for example, when a CHLO has been rejected
// and the previously encrypted data needs to be encrypted with a new key.
- void RetransmitUnackedPackets(TransmissionType retransmission_type) override;
+ void RetransmitUnackedPackets(TransmissionType retransmission_type);
// Retransmits the oldest pending packet there is still a tail loss probe
// pending. Invoked after OnRetransmissionTimeout.
- bool MaybeRetransmitTailLossProbe() override;
+ bool MaybeRetransmitTailLossProbe();
// Removes the retransmittable frames from all unencrypted packets to ensure
// they don't get retransmitted.
- void NeuterUnencryptedPackets() override;
+ void NeuterUnencryptedPackets();
// Returns true if there are pending retransmissions.
// Not const because retransmissions may be cancelled before returning.
- bool HasPendingRetransmissions() const override;
+ bool HasPendingRetransmissions() const;
// Retrieves the next pending retransmission. You must ensure that
// there are pending retransmissions prior to calling this function.
- PendingRetransmission NextPendingRetransmission() override;
+ QuicPendingRetransmission NextPendingRetransmission();
- bool HasUnackedPackets() const override;
+ bool HasUnackedPackets() const;
// Returns the smallest packet number of a serialized packet which has not
// been acked by the peer.
- QuicPacketNumber GetLeastUnacked(QuicPathId) const override;
+ QuicPacketNumber GetLeastUnacked() const;
// Called when we have sent bytes to the peer. This informs the manager both
// the number of bytes sent and if they were retransmitted. Returns true if
// the sender should reset the retransmission timer.
bool OnPacketSent(SerializedPacket* serialized_packet,
- QuicPathId /*original_path_id*/,
QuicPacketNumber original_packet_number,
QuicTime sent_time,
TransmissionType transmission_type,
- HasRetransmittableData has_retransmittable_data) override;
+ HasRetransmittableData has_retransmittable_data);
// Called when the retransmission timer expires.
- void OnRetransmissionTimeout() override;
+ void OnRetransmissionTimeout();
// Calculate the time until we can send the next packet to the wire.
// Note 1: When kUnknownWaitTime is returned, there is no need to poll
// TimeUntilSend again until we receive an OnIncomingAckFrame event.
// Note 2: Send algorithms may or may not use |retransmit| in their
// calculations.
- QuicTime::Delta TimeUntilSend(QuicTime now, QuicPathId* path_id) override;
+ QuicTime::Delta TimeUntilSend(QuicTime now);
// Returns the current delay for the retransmission timer, which may send
// either a tail loss probe or do a full RTO. Returns QuicTime::Zero() if
// there are no retransmittable packets.
- const QuicTime GetRetransmissionTime() const override;
+ const QuicTime GetRetransmissionTime() const;
- const RttStats* GetRttStats() const override;
+ const RttStats* GetRttStats() const;
// Returns the estimated bandwidth calculated by the congestion algorithm.
- QuicBandwidth BandwidthEstimate() const override;
+ QuicBandwidth BandwidthEstimate() const;
- const QuicSustainedBandwidthRecorder* SustainedBandwidthRecorder()
- const override;
+ const QuicSustainedBandwidthRecorder* SustainedBandwidthRecorder() const;
// Returns the size of the current congestion window in number of
// kDefaultTCPMSS-sized segments. Note, this is not the *available* window.
// Some send algorithms may not use a congestion window and will return 0.
- QuicPacketCount GetCongestionWindowInTcpMss() const override;
+ QuicPacketCount GetCongestionWindowInTcpMss() const;
// Returns the number of packets of length |max_packet_length| which fit in
// the current congestion window. More packets may end up in flight if the
// congestion window has been recently reduced, of if non-full packets are
// sent.
QuicPacketCount EstimateMaxPacketsInFlight(
- QuicByteCount max_packet_length) const override;
+ QuicByteCount max_packet_length) const;
// Returns the size of the current congestion window size in bytes.
- QuicByteCount GetCongestionWindowInBytes() const override;
+ QuicByteCount GetCongestionWindowInBytes() const;
// Returns the size of the slow start congestion window in nume of 1460 byte
// TCP segments, aka ssthresh. Some send algorithms do not define a slow
// start threshold and will return 0.
- QuicPacketCount GetSlowStartThresholdInTcpMss() const override;
+ QuicPacketCount GetSlowStartThresholdInTcpMss() const;
// Returns debugging information about the state of the congestion controller.
- std::string GetDebugState() const override;
+ std::string GetDebugState() const;
// No longer retransmit data for |stream_id|.
- void CancelRetransmissionsForStream(QuicStreamId stream_id) override;
+ void CancelRetransmissionsForStream(QuicStreamId stream_id);
// Called when peer address changes and the connection migrates.
- void OnConnectionMigration(QuicPathId, PeerAddressChangeType type) override;
+ void OnConnectionMigration(PeerAddressChangeType type);
+
+ void SetDebugDelegate(DebugDelegate* debug_delegate);
- void SetDebugDelegate(DebugDelegate* debug_delegate) override;
+ QuicPacketNumber GetLargestObserved() const;
- QuicPacketNumber GetLargestObserved(QuicPathId) const override;
+ QuicPacketNumber GetLargestSentPacket() const;
- QuicPacketNumber GetLargestSentPacket(QuicPathId) const override;
+ QuicPacketNumber GetLeastPacketAwaitedByPeer() const;
- QuicPacketNumber GetLeastPacketAwaitedByPeer(QuicPathId) const override;
+ void SetNetworkChangeVisitor(NetworkChangeVisitor* visitor);
- void SetNetworkChangeVisitor(NetworkChangeVisitor* visitor) override;
+ bool InSlowStart() const;
- bool InSlowStart() const override;
+ size_t GetConsecutiveRtoCount() const;
- size_t GetConsecutiveRtoCount() const override;
+ size_t GetConsecutiveTlpCount() const;
- size_t GetConsecutiveTlpCount() const override;
+ void OnApplicationLimited();
- void OnApplicationLimited() override;
+ const SendAlgorithmInterface* GetSendAlgorithm() const;
private:
friend class test::QuicConnectionPeer;
@@ -257,7 +271,7 @@ class NET_EXPORT_PRIVATE QuicSentPacketManager
// Returns the newest transmission associated with a packet.
QuicPacketNumber GetNewestRetransmission(
QuicPacketNumber packet_number,
- const TransmissionInfo& transmission_info) const;
+ const QuicTransmissionInfo& transmission_info) const;
// Update the RTT if the ack is for the largest acked packet number.
// Returns true if the rtt was updated.
@@ -277,21 +291,10 @@ class NET_EXPORT_PRIVATE QuicSentPacketManager
QuicByteCount prior_in_flight,
QuicTime event_time);
- // Called when frames of |packet_number| has been received but the packet
- // itself has not been received by the peer. Currently, this method is not
- // used.
- // TODO(fayang): Update the comment when multipath sent packet manager is
- // landed.
- // The packet needs no longer to be retransmitted, but the packet remains
- // pending if it is and the congestion control does not consider the packet
- // acked.
- void MarkPacketNotRetransmittable(QuicPacketNumber packet_number,
- QuicTime::Delta ack_delay_time);
-
// Removes the retransmittability and in flight properties from the packet at
// |info| due to receipt by the peer.
void MarkPacketHandled(QuicPacketNumber packet_number,
- TransmissionInfo* info,
+ QuicTransmissionInfo* info,
QuicTime::Delta ack_delay_time);
// Request that |packet_number| be retransmitted after the other pending
@@ -300,25 +303,17 @@ class NET_EXPORT_PRIVATE QuicSentPacketManager
void MarkForRetransmission(QuicPacketNumber packet_number,
TransmissionType transmission_type);
- // Notify observers that packet with TransmissionInfo |info| is a spurious
+ // Notify observers that packet with QuicTransmissionInfo |info| is a spurious
// retransmission. It is caller's responsibility to guarantee the packet with
- // TransmissionInfo |info| is a spurious retransmission before calling this
- // function.
- void RecordOneSpuriousRetransmission(const TransmissionInfo& info);
+ // QuicTransmissionInfo |info| is a spurious retransmission before calling
+ // this function.
+ void RecordOneSpuriousRetransmission(const QuicTransmissionInfo& info);
- // Notify observers about spurious retransmits of packet with TransmissionInfo
- // |info|.
- void RecordSpuriousRetransmissions(const TransmissionInfo& info,
+ // Notify observers about spurious retransmits of packet with
+ // QuicTransmissionInfo |info|.
+ void RecordSpuriousRetransmissions(const QuicTransmissionInfo& info,
QuicPacketNumber acked_packet_number);
- // Returns mutable TransmissionInfo associated with |packet_number|, which
- // must be unacked.
- TransmissionInfo* GetMutableTransmissionInfo(QuicPacketNumber packet_number);
-
- // Remove any packets no longer needed for retransmission, congestion, or
- // RTT measurement purposes.
- void RemoveObsoletePackets();
-
// Sets the send algorithm to the given congestion control type and points the
// pacing sender at |send_algorithm_|. Can be called any number of times.
void SetSendAlgorithm(CongestionControlType congestion_control_type);
@@ -344,14 +339,9 @@ class NET_EXPORT_PRIVATE QuicSentPacketManager
// Tracks if the connection was created by the server or the client.
Perspective perspective_;
- QuicPathId path_id_;
-
const QuicClock* clock_;
QuicConnectionStats* stats_;
- // Pending retransmissions are managed by delegate_ if it is not null.
- MultipathDelegateInterface* delegate_; // Not owned.
-
DebugDelegate* debug_delegate_;
NetworkChangeVisitor* network_change_visitor_;
const QuicPacketCount initial_congestion_window_;
@@ -362,9 +352,6 @@ class NET_EXPORT_PRIVATE QuicSentPacketManager
GeneralLossAlgorithm general_loss_algorithm_;
bool n_connection_simulation_;
- // Receiver side buffer in bytes.
- QuicByteCount receive_buffer_bytes_;
-
// Least packet number which the peer is still waiting for.
QuicPacketNumber least_packet_awaited_by_peer_;
@@ -420,4 +407,4 @@ class NET_EXPORT_PRIVATE QuicSentPacketManager
} // namespace net
-#endif // NET_QUIC_QUIC_SENT_PACKET_MANAGER_H_
+#endif // NET_QUIC_CORE_QUIC_SENT_PACKET_MANAGER_H_
diff --git a/chromium/net/quic/core/quic_sent_packet_manager_interface.h b/chromium/net/quic/core/quic_sent_packet_manager_interface.h
deleted file mode 100644
index 498f5cdc026..00000000000
--- a/chromium/net/quic/core/quic_sent_packet_manager_interface.h
+++ /dev/null
@@ -1,195 +0,0 @@
-// Copyright 2016 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.
-
-#ifndef NET_QUIC_QUIC_SENT_PACKET_MANAGER_INTERFACE_H_
-#define NET_QUIC_QUIC_SENT_PACKET_MANAGER_INTERFACE_H_
-
-#include "base/macros.h"
-#include "net/base/net_export.h"
-#include "net/quic/core/quic_protocol.h"
-#include "net/quic/core/quic_sustained_bandwidth_recorder.h"
-
-namespace net {
-
-class QuicConfig;
-class RttStats;
-
-class NET_EXPORT_PRIVATE QuicSentPacketManagerInterface {
- public:
- // Interface which gets callbacks from the QuicSentPacketManager at
- // interesting points. Implementations must not mutate the state of
- // the packet manager or connection as a result of these callbacks.
- class NET_EXPORT_PRIVATE DebugDelegate {
- public:
- virtual ~DebugDelegate() {}
-
- // Called when a spurious retransmission is detected.
- virtual void OnSpuriousPacketRetransmission(
- TransmissionType transmission_type,
- QuicByteCount byte_size) {}
-
- virtual void OnIncomingAck(const QuicAckFrame& ack_frame,
- QuicTime ack_receive_time,
- QuicPacketNumber largest_observed,
- bool rtt_updated,
- QuicPacketNumber least_unacked_sent_packet) {}
-
- virtual void OnPacketLoss(QuicPacketNumber lost_packet_number,
- TransmissionType transmission_type,
- QuicTime detection_time) {}
- };
-
- // Interface which gets callbacks from the QuicSentPacketManager when
- // network-related state changes. Implementations must not mutate the
- // state of the packet manager as a result of these callbacks.
- class NET_EXPORT_PRIVATE NetworkChangeVisitor {
- public:
- virtual ~NetworkChangeVisitor() {}
-
- // Called when congestion window or RTT may have changed.
- virtual void OnCongestionChange() = 0;
-
- // Called with the path may be degrading. Note that the path may only be
- // temporarily degrading.
- // TODO(jri): With multipath, this method should probably have a path_id
- // parameter, and should maybe result in the path being marked as inactive.
- virtual void OnPathDegrading() = 0;
-
- // Called when the Path MTU may have increased.
- virtual void OnPathMtuIncreased(QuicPacketLength packet_size) = 0;
- };
-
- virtual ~QuicSentPacketManagerInterface() {}
-
- virtual void SetFromConfig(const QuicConfig& config) = 0;
-
- // Resumes connection state on the default path.
- virtual void ResumeConnectionState(
- const CachedNetworkParameters& cached_network_params,
- bool max_bandwidth_resumption) = 0;
-
- // Sets number of active streams of all paths.
- virtual void SetNumOpenStreams(size_t num_streams) = 0;
-
- // Sets max pacing rate of the default path.
- virtual void SetMaxPacingRate(QuicBandwidth max_pacing_rate) = 0;
-
- // Indicates the handshake has completed, so no handshake packets need to be
- // retransmitted.
- virtual void SetHandshakeConfirmed() = 0;
-
- virtual void OnIncomingAck(const QuicAckFrame& ack_frame,
- QuicTime ack_receive_time) = 0;
-
- // Requests retransmission of all unacked packets of |retransmission_type| on
- // the default path.
- virtual void RetransmitUnackedPackets(
- TransmissionType retransmission_type) = 0;
-
- // Retransmits the oldest pending packet on the path (on which retransmission
- // alarm fires) if there is still a tail loss probe pending. Invoked after
- // OnRetransmissionTimeout.
- virtual bool MaybeRetransmitTailLossProbe() = 0;
-
- // Removes the retransmittable frames from all unencrypted packets on the
- // default path to ensure they don't get retransmitted.
- virtual void NeuterUnencryptedPackets() = 0;
-
- virtual bool HasPendingRetransmissions() const = 0;
-
- virtual PendingRetransmission NextPendingRetransmission() = 0;
-
- // Returns true if the default path has unacked packets.
- virtual bool HasUnackedPackets() const = 0;
-
- virtual QuicPacketNumber GetLeastUnacked(QuicPathId path_id) const = 0;
-
- virtual bool OnPacketSent(
- SerializedPacket* serialized_packet,
- QuicPathId original_path_id,
- QuicPacketNumber original_packet_number,
- QuicTime sent_time,
- TransmissionType transmission_type,
- HasRetransmittableData has_retransmittable_data) = 0;
-
- virtual void OnRetransmissionTimeout() = 0;
-
- // Returns the earliest time we can send the next packet. Sets |path_id| to be
- // the path on which the next packet will be sent.
- virtual QuicTime::Delta TimeUntilSend(QuicTime now, QuicPathId* path_id) = 0;
-
- // Returns the earliest retransmission time of all paths.
- // TODO(fayang): This method should not be const becasue the return value
- // depends upon the time it is invoked.
- virtual const QuicTime GetRetransmissionTime() const = 0;
-
- // Returns the rtt stats of the default path.
- virtual const RttStats* GetRttStats() const = 0;
-
- // Returns the estimated bandwidth on default path calculated by the
- // congestion algorithm.
- virtual QuicBandwidth BandwidthEstimate() const = 0;
-
- // Returns the sustained bandwidth recorder on the default path.
- virtual const QuicSustainedBandwidthRecorder* SustainedBandwidthRecorder()
- const = 0;
-
- // Returns the size of the current congestion window on default path in number
- // of kDefaultTCPMSS-sized segments.
- virtual QuicPacketCount GetCongestionWindowInTcpMss() const = 0;
-
- // Determines the number of packets of length |max_packet_length| which fit in
- // the congestion windows for all paths, and returns the max number of packets
- // across all paths.
- virtual QuicPacketCount EstimateMaxPacketsInFlight(
- QuicByteCount max_packet_length) const = 0;
-
- // Returns the size of the current congestion window size on the default path
- // in bytes.
- virtual QuicByteCount GetCongestionWindowInBytes() const = 0;
-
- // Returns the size of the slow start congestion window in number of 1460 byte
- // TCP segments on the default path.
- virtual QuicPacketCount GetSlowStartThresholdInTcpMss() const = 0;
-
- // Returns debugging information about the current state of the
- // congestion controller.
- virtual std::string GetDebugState() const = 0;
-
- // No longer retransmit data for |stream_id| on all paths.
- virtual void CancelRetransmissionsForStream(QuicStreamId stream_id) = 0;
-
- // Called when peer address changes and the connection migrates on |path_id|.
- // TODO(fayang): Name of this method is confusing in multipath world because
- // this migration is path level. Need to rename this as OnPeerMigration.
- virtual void OnConnectionMigration(QuicPathId path_id,
- PeerAddressChangeType type) = 0;
-
- virtual void SetDebugDelegate(DebugDelegate* debug_delegate) = 0;
-
- virtual QuicPacketNumber GetLargestObserved(QuicPathId path_id) const = 0;
-
- virtual QuicPacketNumber GetLargestSentPacket(QuicPathId path_id) const = 0;
-
- virtual QuicPacketNumber GetLeastPacketAwaitedByPeer(
- QuicPathId path_id) const = 0;
-
- virtual void SetNetworkChangeVisitor(NetworkChangeVisitor* visitor) = 0;
-
- // Returns true if the default path is in slow start.
- virtual bool InSlowStart() const = 0;
-
- // These two methods return the consecutive RTO or TLP count of the default
- // path.
- virtual size_t GetConsecutiveRtoCount() const = 0;
- virtual size_t GetConsecutiveTlpCount() const = 0;
-
- // Signals to the congestion controller that the connection has no outstanding
- // data to send.
- virtual void OnApplicationLimited() = 0;
-};
-
-} // namespace net
-
-#endif // NET_QUIC_QUIC_SENT_PACKET_MANAGER_INTERFACE_H_
diff --git a/chromium/net/quic/core/quic_sent_packet_manager_test.cc b/chromium/net/quic/core/quic_sent_packet_manager_test.cc
index de79cb66116..b0f4c347c0b 100644
--- a/chromium/net/quic/core/quic_sent_packet_manager_test.cc
+++ b/chromium/net/quic/core/quic_sent_packet_manager_test.cc
@@ -6,15 +6,14 @@
#include <memory>
-#include "base/memory/ptr_util.h"
#include "net/quic/core/quic_flags.h"
+#include "net/quic/platform/api/quic_ptr_util.h"
#include "net/quic/test_tools/quic_config_peer.h"
#include "net/quic/test_tools/quic_sent_packet_manager_peer.h"
#include "net/quic/test_tools/quic_test_utils.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
-using std::vector;
using testing::AnyNumber;
using testing::ElementsAre;
using testing::IsEmpty;
@@ -45,7 +44,7 @@ MATCHER(KeyEq, "") {
return std::tr1::get<0>(arg).first == std::tr1::get<1>(arg);
}
-class MockDebugDelegate : public QuicSentPacketManagerInterface::DebugDelegate {
+class MockDebugDelegate : public QuicSentPacketManager::DebugDelegate {
public:
MOCK_METHOD2(OnSpuriousPacketRetransmission,
void(TransmissionType transmission_type,
@@ -56,36 +55,10 @@ class MockDebugDelegate : public QuicSentPacketManagerInterface::DebugDelegate {
QuicTime detection_time));
};
-// Run tests with different ack frame packets set mode.
-struct TestParams {
- explicit TestParams(bool missing) : missing(missing) {}
-
- friend std::ostream& operator<<(std::ostream& os, const TestParams& p) {
- os << "{ ack frame packets set mode: " << p.missing << " }";
- return os;
- }
-
- bool missing;
-};
-
-vector<TestParams> GetTestParams() {
- vector<TestParams> params;
- for (bool missing : {true, false}) {
- params.push_back(TestParams(missing));
- }
- return params;
-}
-
-class QuicSentPacketManagerTest : public ::testing::TestWithParam<TestParams> {
+class QuicSentPacketManagerTest : public ::testing::Test {
protected:
QuicSentPacketManagerTest()
- : manager_(Perspective::IS_SERVER,
- kDefaultPathId,
- &clock_,
- &stats_,
- FLAGS_quic_default_enable_cubic_bytes ? kCubicBytes : kCubic,
- kNack,
- /*delegate=*/nullptr),
+ : manager_(Perspective::IS_SERVER, &clock_, &stats_, kCubicBytes, kNack),
send_algorithm_(new StrictMock<MockSendAlgorithm>),
network_change_visitor_(new StrictMock<MockNetworkChangeVisitor>) {
QuicSentPacketManagerPeer::SetSendAlgorithm(&manager_, send_algorithm_);
@@ -120,7 +93,7 @@ class QuicSentPacketManagerTest : public ::testing::TestWithParam<TestParams> {
}
EXPECT_TRUE(manager_.HasUnackedPackets());
- EXPECT_EQ(packets[0], manager_.GetLeastUnacked(kDefaultPathId));
+ EXPECT_EQ(packets[0], manager_.GetLeastUnacked());
for (size_t i = 0; i < num_packets; ++i) {
EXPECT_TRUE(QuicSentPacketManagerPeer::IsUnacked(&manager_, packets[i]))
<< packets[i];
@@ -169,11 +142,11 @@ class QuicSentPacketManagerTest : public ::testing::TestWithParam<TestParams> {
size_t num_packets_acked,
QuicPacketNumber* packets_lost,
size_t num_packets_lost) {
- vector<QuicPacketNumber> ack_vector;
+ std::vector<QuicPacketNumber> ack_vector;
for (size_t i = 0; i < num_packets_acked; ++i) {
ack_vector.push_back(packets_acked[i]);
}
- vector<QuicPacketNumber> lost_vector;
+ std::vector<QuicPacketNumber> lost_vector;
for (size_t i = 0; i < num_packets_lost; ++i) {
lost_vector.push_back(packets_lost[i]);
}
@@ -195,9 +168,9 @@ class QuicSentPacketManagerTest : public ::testing::TestWithParam<TestParams> {
QuicPacketNumber new_packet_number,
TransmissionType transmission_type) {
QuicSentPacketManagerPeer::MarkForRetransmission(
- &manager_, kDefaultPathId, old_packet_number, transmission_type);
+ &manager_, old_packet_number, transmission_type);
EXPECT_TRUE(manager_.HasPendingRetransmissions());
- PendingRetransmission next_retransmission =
+ QuicPendingRetransmission next_retransmission =
manager_.NextPendingRetransmission();
EXPECT_EQ(old_packet_number, next_retransmission.packet_number);
EXPECT_EQ(transmission_type, next_retransmission.transmission_type);
@@ -207,11 +180,10 @@ class QuicSentPacketManagerTest : public ::testing::TestWithParam<TestParams> {
kDefaultLength, HAS_RETRANSMITTABLE_DATA))
.WillOnce(Return(true));
SerializedPacket packet(CreatePacket(new_packet_number, false));
- manager_.OnPacketSent(&packet, packet.path_id, old_packet_number,
- clock_.Now(), transmission_type,
- HAS_RETRANSMITTABLE_DATA);
- EXPECT_TRUE(QuicSentPacketManagerPeer::IsRetransmission(
- &manager_, packet.path_id, new_packet_number));
+ manager_.OnPacketSent(&packet, old_packet_number, clock_.Now(),
+ transmission_type, HAS_RETRANSMITTABLE_DATA);
+ EXPECT_TRUE(QuicSentPacketManagerPeer::IsRetransmission(&manager_,
+ new_packet_number));
}
SerializedPacket CreateDataPacket(QuicPacketNumber packet_number) {
@@ -222,7 +194,7 @@ class QuicSentPacketManagerTest : public ::testing::TestWithParam<TestParams> {
bool retransmittable) {
SerializedPacket packet(kDefaultPathId, packet_number,
PACKET_6BYTE_PACKET_NUMBER, nullptr, kDefaultLength,
- 0u, false, false);
+ false, false);
if (retransmittable) {
packet.retransmittable_frames.push_back(
QuicFrame(new QuicStreamFrame(kStreamId, false, 0, StringPiece())));
@@ -236,8 +208,8 @@ class QuicSentPacketManagerTest : public ::testing::TestWithParam<TestParams> {
.Times(1)
.WillOnce(Return(true));
SerializedPacket packet(CreateDataPacket(packet_number));
- manager_.OnPacketSent(&packet, kInvalidPathId, 0, clock_.Now(),
- NOT_RETRANSMISSION, HAS_RETRANSMITTABLE_DATA);
+ manager_.OnPacketSent(&packet, 0, clock_.Now(), NOT_RETRANSMISSION,
+ HAS_RETRANSMITTABLE_DATA);
}
void SendCryptoPacket(QuicPacketNumber packet_number) {
@@ -250,8 +222,8 @@ class QuicSentPacketManagerTest : public ::testing::TestWithParam<TestParams> {
packet.retransmittable_frames.push_back(
QuicFrame(new QuicStreamFrame(1, false, 0, StringPiece())));
packet.has_crypto_handshake = IS_HANDSHAKE;
- manager_.OnPacketSent(&packet, kInvalidPathId, 0, clock_.Now(),
- NOT_RETRANSMISSION, HAS_RETRANSMITTABLE_DATA);
+ manager_.OnPacketSent(&packet, 0, clock_.Now(), NOT_RETRANSMISSION,
+ HAS_RETRANSMITTABLE_DATA);
}
void SendAckPacket(QuicPacketNumber packet_number) {
@@ -261,8 +233,8 @@ class QuicSentPacketManagerTest : public ::testing::TestWithParam<TestParams> {
.Times(1)
.WillOnce(Return(false));
SerializedPacket packet(CreatePacket(packet_number, false));
- manager_.OnPacketSent(&packet, kInvalidPathId, 0, clock_.Now(),
- NOT_RETRANSMISSION, NO_RETRANSMITTABLE_DATA);
+ manager_.OnPacketSent(&packet, 0, clock_.Now(), NOT_RETRANSMISSION,
+ NO_RETRANSMITTABLE_DATA);
}
// Based on QuicConnection's WritePendingRetransmissions.
@@ -273,21 +245,18 @@ class QuicSentPacketManagerTest : public ::testing::TestWithParam<TestParams> {
HAS_RETRANSMITTABLE_DATA))
.Times(1)
.WillOnce(Return(true));
- const PendingRetransmission pending = manager_.NextPendingRetransmission();
+ const QuicPendingRetransmission pending =
+ manager_.NextPendingRetransmission();
SerializedPacket packet(CreatePacket(retransmission_packet_number, false));
- manager_.OnPacketSent(&packet, pending.path_id, pending.packet_number,
- clock_.Now(), pending.transmission_type,
- HAS_RETRANSMITTABLE_DATA);
+ manager_.OnPacketSent(&packet, pending.packet_number, clock_.Now(),
+ pending.transmission_type, HAS_RETRANSMITTABLE_DATA);
}
// Initialize a frame acknowledging all packets up to largest_observed.
const QuicAckFrame InitAckFrame(QuicPacketNumber largest_observed) {
QuicAckFrame frame(MakeAckFrame(largest_observed));
- frame.missing = GetParam().missing;
- if (!GetParam().missing) {
- if (largest_observed > 0) {
- frame.packets.Add(1, largest_observed + 1);
- }
+ if (largest_observed > 0) {
+ frame.packets.Add(1, largest_observed + 1);
}
return frame;
}
@@ -296,11 +265,7 @@ class QuicSentPacketManagerTest : public ::testing::TestWithParam<TestParams> {
void NackPackets(QuicPacketNumber lower,
QuicPacketNumber higher,
QuicAckFrame* frame) {
- if (frame->missing) {
- frame->packets.Add(lower, higher);
- } else {
- frame->packets.Remove(lower, higher);
- }
+ frame->packets.Remove(lower, higher);
}
QuicFlagSaver flags_; // Save/restore all QUIC flag values.
@@ -311,11 +276,7 @@ class QuicSentPacketManagerTest : public ::testing::TestWithParam<TestParams> {
std::unique_ptr<MockNetworkChangeVisitor> network_change_visitor_;
};
-INSTANTIATE_TEST_CASE_P(QuicSentPacketManagerTest,
- QuicSentPacketManagerTest,
- ::testing::ValuesIn(GetTestParams()));
-
-TEST_P(QuicSentPacketManagerTest, IsUnacked) {
+TEST_F(QuicSentPacketManagerTest, IsUnacked) {
VerifyUnackedPackets(nullptr, 0);
SendDataPacket(1);
@@ -325,19 +286,18 @@ TEST_P(QuicSentPacketManagerTest, IsUnacked) {
VerifyRetransmittablePackets(retransmittable, arraysize(retransmittable));
}
-TEST_P(QuicSentPacketManagerTest, IsUnAckedRetransmit) {
+TEST_F(QuicSentPacketManagerTest, IsUnAckedRetransmit) {
SendDataPacket(1);
RetransmitAndSendPacket(1, 2);
- EXPECT_TRUE(QuicSentPacketManagerPeer::IsRetransmission(&manager_,
- kDefaultPathId, 2));
+ EXPECT_TRUE(QuicSentPacketManagerPeer::IsRetransmission(&manager_, 2));
QuicPacketNumber unacked[] = {1, 2};
VerifyUnackedPackets(unacked, arraysize(unacked));
QuicPacketNumber retransmittable[] = {2};
VerifyRetransmittablePackets(retransmittable, arraysize(retransmittable));
}
-TEST_P(QuicSentPacketManagerTest, RetransmitThenAck) {
+TEST_F(QuicSentPacketManagerTest, RetransmitThenAck) {
SendDataPacket(1);
RetransmitAndSendPacket(1, 2);
@@ -354,9 +314,9 @@ TEST_P(QuicSentPacketManagerTest, RetransmitThenAck) {
VerifyRetransmittablePackets(nullptr, 0);
}
-TEST_P(QuicSentPacketManagerTest, RetransmitThenAckBeforeSend) {
+TEST_F(QuicSentPacketManagerTest, RetransmitThenAckBeforeSend) {
SendDataPacket(1);
- QuicSentPacketManagerPeer::MarkForRetransmission(&manager_, kDefaultPathId, 1,
+ QuicSentPacketManagerPeer::MarkForRetransmission(&manager_, 1,
TLP_RETRANSMISSION);
EXPECT_TRUE(manager_.HasPendingRetransmissions());
@@ -374,9 +334,9 @@ TEST_P(QuicSentPacketManagerTest, RetransmitThenAckBeforeSend) {
EXPECT_EQ(0u, stats_.packets_spuriously_retransmitted);
}
-TEST_P(QuicSentPacketManagerTest, RetransmitThenStopRetransmittingBeforeSend) {
+TEST_F(QuicSentPacketManagerTest, RetransmitThenStopRetransmittingBeforeSend) {
SendDataPacket(1);
- QuicSentPacketManagerPeer::MarkForRetransmission(&manager_, kDefaultPathId, 1,
+ QuicSentPacketManagerPeer::MarkForRetransmission(&manager_, 1,
TLP_RETRANSMISSION);
EXPECT_TRUE(manager_.HasPendingRetransmissions());
@@ -391,7 +351,7 @@ TEST_P(QuicSentPacketManagerTest, RetransmitThenStopRetransmittingBeforeSend) {
EXPECT_EQ(0u, stats_.packets_spuriously_retransmitted);
}
-TEST_P(QuicSentPacketManagerTest, RetransmitThenAckPrevious) {
+TEST_F(QuicSentPacketManagerTest, RetransmitThenAckPrevious) {
SendDataPacket(1);
RetransmitAndSendPacket(1, 2);
QuicTime::Delta rtt = QuicTime::Delta::FromMilliseconds(15);
@@ -411,7 +371,7 @@ TEST_P(QuicSentPacketManagerTest, RetransmitThenAckPrevious) {
EXPECT_EQ(1u, stats_.packets_spuriously_retransmitted);
}
-TEST_P(QuicSentPacketManagerTest, RetransmitThenAckPreviousThenNackRetransmit) {
+TEST_F(QuicSentPacketManagerTest, RetransmitThenAckPreviousThenNackRetransmit) {
SendDataPacket(1);
RetransmitAndSendPacket(1, 2);
QuicTime::Delta rtt = QuicTime::Delta::FromMilliseconds(15);
@@ -453,7 +413,7 @@ TEST_P(QuicSentPacketManagerTest, RetransmitThenAckPreviousThenNackRetransmit) {
EXPECT_EQ(QuicTime::Zero(), manager_.GetRetransmissionTime());
}
-TEST_P(QuicSentPacketManagerTest,
+TEST_F(QuicSentPacketManagerTest,
DISABLED_RetransmitTwiceThenAckPreviousBeforeSend) {
SendDataPacket(1);
RetransmitAndSendPacket(1, 2);
@@ -483,7 +443,7 @@ TEST_P(QuicSentPacketManagerTest,
EXPECT_EQ(QuicTime::Zero(), manager_.GetRetransmissionTime());
}
-TEST_P(QuicSentPacketManagerTest, RetransmitTwiceThenAckFirst) {
+TEST_F(QuicSentPacketManagerTest, RetransmitTwiceThenAckFirst) {
StrictMock<MockDebugDelegate> debug_delegate;
EXPECT_CALL(debug_delegate, OnSpuriousPacketRetransmission(TLP_RETRANSMISSION,
kDefaultLength))
@@ -531,8 +491,8 @@ TEST_P(QuicSentPacketManagerTest, RetransmitTwiceThenAckFirst) {
EXPECT_EQ(2u, stats_.packets_spuriously_retransmitted);
}
-TEST_P(QuicSentPacketManagerTest, AckOriginalTransmission) {
- auto loss_algorithm = base::MakeUnique<MockLossAlgorithm>();
+TEST_F(QuicSentPacketManagerTest, AckOriginalTransmission) {
+ auto loss_algorithm = QuicMakeUnique<MockLossAlgorithm>();
QuicSentPacketManagerPeer::SetLossAlgorithm(&manager_, loss_algorithm.get());
SendDataPacket(1);
@@ -566,16 +526,16 @@ TEST_P(QuicSentPacketManagerTest, AckOriginalTransmission) {
}
}
-TEST_P(QuicSentPacketManagerTest, GetLeastUnacked) {
- EXPECT_EQ(1u, manager_.GetLeastUnacked(kDefaultPathId));
+TEST_F(QuicSentPacketManagerTest, GetLeastUnacked) {
+ EXPECT_EQ(1u, manager_.GetLeastUnacked());
}
-TEST_P(QuicSentPacketManagerTest, GetLeastUnackedUnacked) {
+TEST_F(QuicSentPacketManagerTest, GetLeastUnackedUnacked) {
SendDataPacket(1);
- EXPECT_EQ(1u, manager_.GetLeastUnacked(kDefaultPathId));
+ EXPECT_EQ(1u, manager_.GetLeastUnacked());
}
-TEST_P(QuicSentPacketManagerTest, AckAckAndUpdateRtt) {
+TEST_F(QuicSentPacketManagerTest, AckAckAndUpdateRtt) {
SendDataPacket(1);
SendAckPacket(2);
@@ -594,7 +554,7 @@ TEST_P(QuicSentPacketManagerTest, AckAckAndUpdateRtt) {
manager_.OnIncomingAck(ack_frame, clock_.Now());
}
-TEST_P(QuicSentPacketManagerTest, Rtt) {
+TEST_F(QuicSentPacketManagerTest, Rtt) {
QuicPacketNumber packet_number = 1;
QuicTime::Delta expected_rtt = QuicTime::Delta::FromMilliseconds(15);
SendDataPacket(packet_number);
@@ -607,7 +567,7 @@ TEST_P(QuicSentPacketManagerTest, Rtt) {
EXPECT_EQ(expected_rtt, manager_.GetRttStats()->latest_rtt());
}
-TEST_P(QuicSentPacketManagerTest, RttWithInvalidDelta) {
+TEST_F(QuicSentPacketManagerTest, RttWithInvalidDelta) {
// Expect that the RTT is equal to the local time elapsed, since the
// ack_delay_time is larger than the local time elapsed
// and is hence invalid.
@@ -623,7 +583,7 @@ TEST_P(QuicSentPacketManagerTest, RttWithInvalidDelta) {
EXPECT_EQ(expected_rtt, manager_.GetRttStats()->latest_rtt());
}
-TEST_P(QuicSentPacketManagerTest, RttWithInfiniteDelta) {
+TEST_F(QuicSentPacketManagerTest, RttWithInfiniteDelta) {
// Expect that the RTT is equal to the local time elapsed, since the
// ack_delay_time is infinite, and is hence invalid.
QuicPacketNumber packet_number = 1;
@@ -638,7 +598,7 @@ TEST_P(QuicSentPacketManagerTest, RttWithInfiniteDelta) {
EXPECT_EQ(expected_rtt, manager_.GetRttStats()->latest_rtt());
}
-TEST_P(QuicSentPacketManagerTest, RttZeroDelta) {
+TEST_F(QuicSentPacketManagerTest, RttZeroDelta) {
// Expect that the RTT is the time between send and receive since the
// ack_delay_time is zero.
QuicPacketNumber packet_number = 1;
@@ -653,18 +613,16 @@ TEST_P(QuicSentPacketManagerTest, RttZeroDelta) {
EXPECT_EQ(expected_rtt, manager_.GetRttStats()->latest_rtt());
}
-TEST_P(QuicSentPacketManagerTest, TailLossProbeTimeout) {
+TEST_F(QuicSentPacketManagerTest, TailLossProbeTimeout) {
QuicSentPacketManagerPeer::SetMaxTailLossProbes(&manager_, 2);
// Send 1 packet.
QuicPacketNumber packet_number = 1;
SendDataPacket(packet_number);
- QuicPathId path_id = kInvalidPathId;
// The first tail loss probe retransmits 1 packet.
manager_.OnRetransmissionTimeout();
- EXPECT_EQ(QuicTime::Delta::Zero(),
- manager_.TimeUntilSend(clock_.Now(), &path_id));
+ EXPECT_EQ(QuicTime::Delta::Zero(), manager_.TimeUntilSend(clock_.Now()));
EXPECT_FALSE(manager_.HasPendingRetransmissions());
manager_.MaybeRetransmitTailLossProbe();
EXPECT_TRUE(manager_.HasPendingRetransmissions());
@@ -673,16 +631,14 @@ TEST_P(QuicSentPacketManagerTest, TailLossProbeTimeout) {
// The second tail loss probe retransmits 1 packet.
manager_.OnRetransmissionTimeout();
- EXPECT_EQ(QuicTime::Delta::Zero(),
- manager_.TimeUntilSend(clock_.Now(), &path_id));
+ EXPECT_EQ(QuicTime::Delta::Zero(), manager_.TimeUntilSend(clock_.Now()));
EXPECT_FALSE(manager_.HasPendingRetransmissions());
manager_.MaybeRetransmitTailLossProbe();
EXPECT_TRUE(manager_.HasPendingRetransmissions());
RetransmitNextPacket(3);
EXPECT_CALL(*send_algorithm_, TimeUntilSend(_, _))
.WillOnce(Return(QuicTime::Delta::Infinite()));
- EXPECT_EQ(QuicTime::Delta::Infinite(),
- manager_.TimeUntilSend(clock_.Now(), &path_id));
+ EXPECT_EQ(QuicTime::Delta::Infinite(), manager_.TimeUntilSend(clock_.Now()));
EXPECT_FALSE(manager_.HasPendingRetransmissions());
// Ack the third and ensure the first two are still pending.
@@ -710,7 +666,7 @@ TEST_P(QuicSentPacketManagerTest, TailLossProbeTimeout) {
EXPECT_EQ(0u, stats_.rto_count);
}
-TEST_P(QuicSentPacketManagerTest, TailLossProbeThenRTO) {
+TEST_F(QuicSentPacketManagerTest, TailLossProbeThenRTO) {
QuicSentPacketManagerPeer::SetMaxTailLossProbes(&manager_, 2);
// Send 100 packets.
@@ -724,32 +680,27 @@ TEST_P(QuicSentPacketManagerTest, TailLossProbeThenRTO) {
// The first tail loss probe retransmits 1 packet.
manager_.OnRetransmissionTimeout();
- QuicPathId path_id = kInvalidPathId;
- EXPECT_EQ(QuicTime::Delta::Zero(),
- manager_.TimeUntilSend(clock_.Now(), &path_id));
+ EXPECT_EQ(QuicTime::Delta::Zero(), manager_.TimeUntilSend(clock_.Now()));
EXPECT_FALSE(manager_.HasPendingRetransmissions());
manager_.MaybeRetransmitTailLossProbe();
EXPECT_TRUE(manager_.HasPendingRetransmissions());
RetransmitNextPacket(101);
EXPECT_CALL(*send_algorithm_, TimeUntilSend(_, _))
.WillOnce(Return(QuicTime::Delta::Infinite()));
- EXPECT_EQ(QuicTime::Delta::Infinite(),
- manager_.TimeUntilSend(clock_.Now(), &path_id));
+ EXPECT_EQ(QuicTime::Delta::Infinite(), manager_.TimeUntilSend(clock_.Now()));
EXPECT_FALSE(manager_.HasPendingRetransmissions());
clock_.AdvanceTime(manager_.GetRetransmissionTime() - clock_.Now());
// The second tail loss probe retransmits 1 packet.
manager_.OnRetransmissionTimeout();
- EXPECT_EQ(QuicTime::Delta::Zero(),
- manager_.TimeUntilSend(clock_.Now(), &path_id));
+ EXPECT_EQ(QuicTime::Delta::Zero(), manager_.TimeUntilSend(clock_.Now()));
EXPECT_FALSE(manager_.HasPendingRetransmissions());
EXPECT_TRUE(manager_.MaybeRetransmitTailLossProbe());
EXPECT_TRUE(manager_.HasPendingRetransmissions());
RetransmitNextPacket(102);
EXPECT_CALL(*send_algorithm_, TimeUntilSend(_, _))
.WillOnce(Return(QuicTime::Delta::Infinite()));
- EXPECT_EQ(QuicTime::Delta::Infinite(),
- manager_.TimeUntilSend(clock_.Now(), &path_id));
+ EXPECT_EQ(QuicTime::Delta::Infinite(), manager_.TimeUntilSend(clock_.Now()));
// Ensure the RTO is set based on the correct packet.
rto_packet_time = clock_.Now();
@@ -780,7 +731,7 @@ TEST_P(QuicSentPacketManagerTest, TailLossProbeThenRTO) {
EXPECT_EQ(0u, QuicSentPacketManagerPeer::GetBytesInFlight(&manager_));
}
-TEST_P(QuicSentPacketManagerTest, CryptoHandshakeTimeout) {
+TEST_F(QuicSentPacketManagerTest, CryptoHandshakeTimeout) {
// Send 2 crypto packets and 3 data packets.
const size_t kNumSentCryptoPackets = 2;
for (size_t i = 1; i <= kNumSentCryptoPackets; ++i) {
@@ -793,10 +744,8 @@ TEST_P(QuicSentPacketManagerTest, CryptoHandshakeTimeout) {
EXPECT_TRUE(QuicSentPacketManagerPeer::HasUnackedCryptoPackets(&manager_));
// The first retransmits 2 packets.
- QuicPathId path_id = kInvalidPathId;
manager_.OnRetransmissionTimeout();
- EXPECT_EQ(QuicTime::Delta::Zero(),
- manager_.TimeUntilSend(clock_.Now(), &path_id));
+ EXPECT_EQ(QuicTime::Delta::Zero(), manager_.TimeUntilSend(clock_.Now()));
RetransmitNextPacket(6);
RetransmitNextPacket(7);
EXPECT_FALSE(manager_.HasPendingRetransmissions());
@@ -804,8 +753,7 @@ TEST_P(QuicSentPacketManagerTest, CryptoHandshakeTimeout) {
// The second retransmits 2 packets.
manager_.OnRetransmissionTimeout();
- EXPECT_EQ(QuicTime::Delta::Zero(),
- manager_.TimeUntilSend(clock_.Now(), &path_id));
+ EXPECT_EQ(QuicTime::Delta::Zero(), manager_.TimeUntilSend(clock_.Now()));
RetransmitNextPacket(8);
RetransmitNextPacket(9);
EXPECT_FALSE(manager_.HasPendingRetransmissions());
@@ -823,7 +771,7 @@ TEST_P(QuicSentPacketManagerTest, CryptoHandshakeTimeout) {
EXPECT_FALSE(QuicSentPacketManagerPeer::HasUnackedCryptoPackets(&manager_));
}
-TEST_P(QuicSentPacketManagerTest, CryptoHandshakeTimeoutVersionNegotiation) {
+TEST_F(QuicSentPacketManagerTest, CryptoHandshakeTimeoutVersionNegotiation) {
// Send 2 crypto packets and 3 data packets.
const size_t kNumSentCryptoPackets = 2;
for (size_t i = 1; i <= kNumSentCryptoPackets; ++i) {
@@ -860,7 +808,7 @@ TEST_P(QuicSentPacketManagerTest, CryptoHandshakeTimeoutVersionNegotiation) {
RetransmitNextPacket(12);
EXPECT_FALSE(manager_.HasPendingRetransmissions());
- EXPECT_EQ(1u, manager_.GetLeastUnacked(kDefaultPathId));
+ EXPECT_EQ(1u, manager_.GetLeastUnacked());
// Least unacked isn't raised until an ack is received, so ack the
// crypto packets.
QuicPacketNumber acked[] = {8, 9};
@@ -870,10 +818,10 @@ TEST_P(QuicSentPacketManagerTest, CryptoHandshakeTimeoutVersionNegotiation) {
NackPackets(i, i + 1, &ack_frame);
}
manager_.OnIncomingAck(ack_frame, clock_.ApproximateNow());
- EXPECT_EQ(10u, manager_.GetLeastUnacked(kDefaultPathId));
+ EXPECT_EQ(10u, manager_.GetLeastUnacked());
}
-TEST_P(QuicSentPacketManagerTest, CryptoHandshakeSpuriousRetransmission) {
+TEST_F(QuicSentPacketManagerTest, CryptoHandshakeSpuriousRetransmission) {
// Send 1 crypto packet.
SendCryptoPacket(1);
EXPECT_TRUE(QuicSentPacketManagerPeer::HasUnackedCryptoPackets(&manager_));
@@ -898,7 +846,7 @@ TEST_P(QuicSentPacketManagerTest, CryptoHandshakeSpuriousRetransmission) {
VerifyUnackedPackets(unacked, arraysize(unacked));
}
-TEST_P(QuicSentPacketManagerTest, CryptoHandshakeTimeoutUnsentDataPacket) {
+TEST_F(QuicSentPacketManagerTest, CryptoHandshakeTimeoutUnsentDataPacket) {
// Send 2 crypto packets and 1 data packet.
const size_t kNumSentCryptoPackets = 2;
for (size_t i = 1; i <= kNumSentCryptoPackets; ++i) {
@@ -915,7 +863,7 @@ TEST_P(QuicSentPacketManagerTest, CryptoHandshakeTimeoutUnsentDataPacket) {
EXPECT_TRUE(QuicSentPacketManagerPeer::HasUnackedCryptoPackets(&manager_));
}
-TEST_P(QuicSentPacketManagerTest,
+TEST_F(QuicSentPacketManagerTest,
CryptoHandshakeRetransmissionThenRetransmitAll) {
// Send 1 crypto packet.
SendCryptoPacket(1);
@@ -935,7 +883,7 @@ TEST_P(QuicSentPacketManagerTest,
EXPECT_FALSE(QuicSentPacketManagerPeer::HasPendingPackets(&manager_));
}
-TEST_P(QuicSentPacketManagerTest,
+TEST_F(QuicSentPacketManagerTest,
CryptoHandshakeRetransmissionThenNeuterAndAck) {
// Send 1 crypto packet.
SendCryptoPacket(1);
@@ -971,7 +919,7 @@ TEST_P(QuicSentPacketManagerTest,
VerifyRetransmittablePackets(nullptr, 0);
}
-TEST_P(QuicSentPacketManagerTest, RetransmissionTimeout) {
+TEST_F(QuicSentPacketManagerTest, RetransmissionTimeout) {
StrictMock<MockDebugDelegate> debug_delegate;
manager_.SetDebugDelegate(&debug_delegate);
@@ -1008,7 +956,7 @@ TEST_P(QuicSentPacketManagerTest, RetransmissionTimeout) {
manager_.OnIncomingAck(ack_frame, clock_.Now());
}
-TEST_P(QuicSentPacketManagerTest, NewRetransmissionTimeout) {
+TEST_F(QuicSentPacketManagerTest, NewRetransmissionTimeout) {
QuicConfig client_config;
QuicTagVector options;
options.push_back(kNRTO);
@@ -1050,7 +998,7 @@ TEST_P(QuicSentPacketManagerTest, NewRetransmissionTimeout) {
manager_.OnIncomingAck(ack_frame, clock_.Now());
}
-TEST_P(QuicSentPacketManagerTest, TwoRetransmissionTimeoutsAckSecond) {
+TEST_F(QuicSentPacketManagerTest, TwoRetransmissionTimeoutsAckSecond) {
// Send 1 packet.
SendDataPacket(1);
@@ -1083,7 +1031,7 @@ TEST_P(QuicSentPacketManagerTest, TwoRetransmissionTimeoutsAckSecond) {
QuicSentPacketManagerPeer::GetBytesInFlight(&manager_));
}
-TEST_P(QuicSentPacketManagerTest, TwoRetransmissionTimeoutsAckFirst) {
+TEST_F(QuicSentPacketManagerTest, TwoRetransmissionTimeoutsAckFirst) {
// Send 1 packet.
SendDataPacket(1);
@@ -1116,7 +1064,7 @@ TEST_P(QuicSentPacketManagerTest, TwoRetransmissionTimeoutsAckFirst) {
QuicSentPacketManagerPeer::GetBytesInFlight(&manager_));
}
-TEST_P(QuicSentPacketManagerTest, OnPathDegrading) {
+TEST_F(QuicSentPacketManagerTest, OnPathDegrading) {
SendDataPacket(1);
for (size_t i = 1; i < kMinTimeoutsBeforePathDegrading; ++i) {
manager_.OnRetransmissionTimeout();
@@ -1128,11 +1076,11 @@ TEST_P(QuicSentPacketManagerTest, OnPathDegrading) {
manager_.OnRetransmissionTimeout();
}
-TEST_P(QuicSentPacketManagerTest, GetTransmissionTime) {
+TEST_F(QuicSentPacketManagerTest, GetTransmissionTime) {
EXPECT_EQ(QuicTime::Zero(), manager_.GetRetransmissionTime());
}
-TEST_P(QuicSentPacketManagerTest, GetTransmissionTimeCryptoHandshake) {
+TEST_F(QuicSentPacketManagerTest, GetTransmissionTimeCryptoHandshake) {
SendCryptoPacket(1);
// Check the min.
@@ -1159,9 +1107,9 @@ TEST_P(QuicSentPacketManagerTest, GetTransmissionTimeCryptoHandshake) {
EXPECT_EQ(expected_time, manager_.GetRetransmissionTime());
}
-TEST_P(QuicSentPacketManagerTest,
+TEST_F(QuicSentPacketManagerTest,
GetConservativeTransmissionTimeCryptoHandshake) {
- FLAGS_quic_conservative_handshake_retransmits = true;
+ FLAGS_quic_reloadable_flag_quic_conservative_handshake_retransmits = true;
QuicConfig config;
QuicTagVector options;
options.push_back(kCONH);
@@ -1201,7 +1149,7 @@ TEST_P(QuicSentPacketManagerTest,
EXPECT_EQ(expected_time, manager_.GetRetransmissionTime());
}
-TEST_P(QuicSentPacketManagerTest, GetTransmissionTimeTailLossProbe) {
+TEST_F(QuicSentPacketManagerTest, GetTransmissionTimeTailLossProbe) {
QuicSentPacketManagerPeer::SetMaxTailLossProbes(&manager_, 2);
SendDataPacket(1);
SendDataPacket(2);
@@ -1223,24 +1171,21 @@ TEST_P(QuicSentPacketManagerTest, GetTransmissionTimeTailLossProbe) {
// Retransmit the packet by invoking the retransmission timeout.
clock_.AdvanceTime(expected_tlp_delay);
manager_.OnRetransmissionTimeout();
- QuicPathId path_id = kInvalidPathId;
- EXPECT_EQ(QuicTime::Delta::Zero(),
- manager_.TimeUntilSend(clock_.Now(), &path_id));
+ EXPECT_EQ(QuicTime::Delta::Zero(), manager_.TimeUntilSend(clock_.Now()));
EXPECT_FALSE(manager_.HasPendingRetransmissions());
EXPECT_TRUE(manager_.MaybeRetransmitTailLossProbe());
EXPECT_TRUE(manager_.HasPendingRetransmissions());
RetransmitNextPacket(3);
EXPECT_CALL(*send_algorithm_, TimeUntilSend(_, _))
.WillOnce(Return(QuicTime::Delta::Infinite()));
- EXPECT_EQ(QuicTime::Delta::Infinite(),
- manager_.TimeUntilSend(clock_.Now(), &path_id));
+ EXPECT_EQ(QuicTime::Delta::Infinite(), manager_.TimeUntilSend(clock_.Now()));
EXPECT_FALSE(manager_.HasPendingRetransmissions());
expected_time = clock_.Now() + expected_tlp_delay;
EXPECT_EQ(expected_time, manager_.GetRetransmissionTime());
}
-TEST_P(QuicSentPacketManagerTest, GetTransmissionTimeSpuriousRTO) {
+TEST_F(QuicSentPacketManagerTest, GetTransmissionTimeSpuriousRTO) {
RttStats* rtt_stats = const_cast<RttStats*>(manager_.GetRttStats());
rtt_stats->UpdateRtt(QuicTime::Delta::FromMilliseconds(100),
QuicTime::Delta::Zero(), QuicTime::Zero());
@@ -1294,7 +1239,7 @@ TEST_P(QuicSentPacketManagerTest, GetTransmissionTimeSpuriousRTO) {
EXPECT_EQ(expected_time, manager_.GetRetransmissionTime());
}
-TEST_P(QuicSentPacketManagerTest, GetTransmissionDelayMin) {
+TEST_F(QuicSentPacketManagerTest, GetTransmissionDelayMin) {
SendDataPacket(1);
// Provide a 1ms RTT sample.
const_cast<RttStats*>(manager_.GetRttStats())
@@ -1314,7 +1259,7 @@ TEST_P(QuicSentPacketManagerTest, GetTransmissionDelayMin) {
}
}
-TEST_P(QuicSentPacketManagerTest, GetTransmissionDelayMax) {
+TEST_F(QuicSentPacketManagerTest, GetTransmissionDelayMax) {
SendDataPacket(1);
// Provide a 60s RTT sample.
const_cast<RttStats*>(manager_.GetRttStats())
@@ -1325,7 +1270,7 @@ TEST_P(QuicSentPacketManagerTest, GetTransmissionDelayMax) {
QuicSentPacketManagerPeer::GetRetransmissionDelay(&manager_));
}
-TEST_P(QuicSentPacketManagerTest, GetTransmissionDelayExponentialBackoff) {
+TEST_F(QuicSentPacketManagerTest, GetTransmissionDelayExponentialBackoff) {
SendDataPacket(1);
QuicTime::Delta delay = QuicTime::Delta::FromMilliseconds(500);
@@ -1374,8 +1319,8 @@ TEST_F(QuicSentPacketManagerTest, RetransmissionDelay) {
1);
}
-TEST_P(QuicSentPacketManagerTest, GetLossDelay) {
- auto loss_algorithm = base::MakeUnique<MockLossAlgorithm>();
+TEST_F(QuicSentPacketManagerTest, GetLossDelay) {
+ auto loss_algorithm = QuicMakeUnique<MockLossAlgorithm>();
QuicSentPacketManagerPeer::SetLossAlgorithm(&manager_, loss_algorithm.get());
EXPECT_CALL(*loss_algorithm, GetLossTimeout())
@@ -1402,7 +1347,7 @@ TEST_P(QuicSentPacketManagerTest, GetLossDelay) {
manager_.OnRetransmissionTimeout();
}
-TEST_P(QuicSentPacketManagerTest, NegotiateTimeLossDetectionFromOptions) {
+TEST_F(QuicSentPacketManagerTest, NegotiateTimeLossDetectionFromOptions) {
EXPECT_EQ(kNack, QuicSentPacketManagerPeer::GetLossAlgorithm(&manager_)
->GetLossDetectionType());
@@ -1418,8 +1363,8 @@ TEST_P(QuicSentPacketManagerTest, NegotiateTimeLossDetectionFromOptions) {
->GetLossDetectionType());
}
-TEST_P(QuicSentPacketManagerTest, NegotiateCongestionControlFromOptions) {
- FLAGS_quic_allow_new_bbr = true;
+TEST_F(QuicSentPacketManagerTest, NegotiateCongestionControlFromOptions) {
+ FLAGS_quic_reloadable_flag_quic_allow_new_bbr = true;
QuicConfig config;
QuicTagVector options;
@@ -1443,13 +1388,8 @@ TEST_P(QuicSentPacketManagerTest, NegotiateCongestionControlFromOptions) {
QuicConfigPeer::SetReceivedConnectionOptions(&config, options);
EXPECT_CALL(*network_change_visitor_, OnCongestionChange());
manager_.SetFromConfig(config);
- if (FLAGS_quic_default_enable_cubic_bytes) {
- EXPECT_EQ(kCubic, QuicSentPacketManagerPeer::GetSendAlgorithm(manager_)
- ->GetCongestionControlType());
- } else {
- EXPECT_EQ(kCubicBytes, QuicSentPacketManagerPeer::GetSendAlgorithm(manager_)
- ->GetCongestionControlType());
- }
+ EXPECT_EQ(kCubic, QuicSentPacketManagerPeer::GetSendAlgorithm(manager_)
+ ->GetCongestionControlType());
options.clear();
options.push_back(kRENO);
@@ -1461,7 +1401,56 @@ TEST_P(QuicSentPacketManagerTest, NegotiateCongestionControlFromOptions) {
->GetCongestionControlType());
}
-TEST_P(QuicSentPacketManagerTest, NegotiateNumConnectionsFromOptions) {
+TEST_F(QuicSentPacketManagerTest, NegotiateClientCongestionControlFromOptions) {
+ FLAGS_quic_reloadable_flag_quic_allow_new_bbr = true;
+ FLAGS_quic_reloadable_flag_quic_client_connection_options = true;
+ QuicConfig config;
+ QuicTagVector options;
+
+ // No change if the server receives client options.
+ const SendAlgorithmInterface* mock_sender =
+ QuicSentPacketManagerPeer::GetSendAlgorithm(manager_);
+ options.push_back(kRENO);
+ config.SetClientConnectionOptions(options);
+ EXPECT_CALL(*send_algorithm_, SetFromConfig(_, _));
+ EXPECT_CALL(*network_change_visitor_, OnCongestionChange());
+ manager_.SetFromConfig(config);
+ EXPECT_EQ(mock_sender, QuicSentPacketManagerPeer::GetSendAlgorithm(manager_));
+
+ // Change the congestion control on the client with client options.
+ QuicSentPacketManagerPeer::SetPerspective(&manager_, Perspective::IS_CLIENT);
+ EXPECT_CALL(*network_change_visitor_, OnCongestionChange());
+ manager_.SetFromConfig(config);
+ EXPECT_EQ(kReno, QuicSentPacketManagerPeer::GetSendAlgorithm(manager_)
+ ->GetCongestionControlType());
+
+ options.clear();
+ options.push_back(kTBBR);
+ config.SetClientConnectionOptions(options);
+ EXPECT_CALL(*network_change_visitor_, OnCongestionChange());
+ manager_.SetFromConfig(config);
+ EXPECT_EQ(kBBR, QuicSentPacketManagerPeer::GetSendAlgorithm(manager_)
+ ->GetCongestionControlType());
+
+ options.clear();
+ options.push_back(kBYTE);
+ config.SetClientConnectionOptions(options);
+ EXPECT_CALL(*network_change_visitor_, OnCongestionChange());
+ manager_.SetFromConfig(config);
+ EXPECT_EQ(kCubic, QuicSentPacketManagerPeer::GetSendAlgorithm(manager_)
+ ->GetCongestionControlType());
+
+ options.clear();
+ options.push_back(kRENO);
+ options.push_back(kBYTE);
+ config.SetClientConnectionOptions(options);
+ EXPECT_CALL(*network_change_visitor_, OnCongestionChange());
+ manager_.SetFromConfig(config);
+ EXPECT_EQ(kRenoBytes, QuicSentPacketManagerPeer::GetSendAlgorithm(manager_)
+ ->GetCongestionControlType());
+}
+
+TEST_F(QuicSentPacketManagerTest, NegotiateNumConnectionsFromOptions) {
QuicConfig config;
QuicTagVector options;
@@ -1481,7 +1470,7 @@ TEST_P(QuicSentPacketManagerTest, NegotiateNumConnectionsFromOptions) {
manager_.SetFromConfig(client_config);
}
-TEST_P(QuicSentPacketManagerTest, NegotiateNConnectionFromOptions) {
+TEST_F(QuicSentPacketManagerTest, NegotiateNConnectionFromOptions) {
// By default, changing the number of open streams does nothing.
manager_.SetNumOpenStreams(5);
@@ -1498,7 +1487,7 @@ TEST_P(QuicSentPacketManagerTest, NegotiateNConnectionFromOptions) {
manager_.SetNumOpenStreams(5);
}
-TEST_P(QuicSentPacketManagerTest, NegotiateNoTLPFromOptionsAtServer) {
+TEST_F(QuicSentPacketManagerTest, NegotiateNoTLPFromOptionsAtServer) {
QuicConfig config;
QuicTagVector options;
@@ -1510,7 +1499,7 @@ TEST_P(QuicSentPacketManagerTest, NegotiateNoTLPFromOptionsAtServer) {
EXPECT_EQ(0u, QuicSentPacketManagerPeer::GetMaxTailLossProbes(&manager_));
}
-TEST_P(QuicSentPacketManagerTest, NegotiateNoTLPFromOptionsAtClient) {
+TEST_F(QuicSentPacketManagerTest, NegotiateNoTLPFromOptionsAtClient) {
QuicConfig client_config;
QuicTagVector options;
@@ -1523,7 +1512,7 @@ TEST_P(QuicSentPacketManagerTest, NegotiateNoTLPFromOptionsAtClient) {
EXPECT_EQ(0u, QuicSentPacketManagerPeer::GetMaxTailLossProbes(&manager_));
}
-TEST_P(QuicSentPacketManagerTest, NegotiateTLPRttFromOptionsAtServer) {
+TEST_F(QuicSentPacketManagerTest, NegotiateTLPRttFromOptionsAtServer) {
QuicConfig config;
QuicTagVector options;
@@ -1536,7 +1525,7 @@ TEST_P(QuicSentPacketManagerTest, NegotiateTLPRttFromOptionsAtServer) {
QuicSentPacketManagerPeer::GetEnableHalfRttTailLossProbe(&manager_));
}
-TEST_P(QuicSentPacketManagerTest, NegotiateTLPRttFromOptionsAtClient) {
+TEST_F(QuicSentPacketManagerTest, NegotiateTLPRttFromOptionsAtClient) {
QuicConfig client_config;
QuicTagVector options;
@@ -1550,7 +1539,7 @@ TEST_P(QuicSentPacketManagerTest, NegotiateTLPRttFromOptionsAtClient) {
QuicSentPacketManagerPeer::GetEnableHalfRttTailLossProbe(&manager_));
}
-TEST_P(QuicSentPacketManagerTest, NegotiateNewRTOFromOptionsAtServer) {
+TEST_F(QuicSentPacketManagerTest, NegotiateNewRTOFromOptionsAtServer) {
EXPECT_FALSE(QuicSentPacketManagerPeer::GetUseNewRto(&manager_));
QuicConfig config;
QuicTagVector options;
@@ -1563,7 +1552,7 @@ TEST_P(QuicSentPacketManagerTest, NegotiateNewRTOFromOptionsAtServer) {
EXPECT_TRUE(QuicSentPacketManagerPeer::GetUseNewRto(&manager_));
}
-TEST_P(QuicSentPacketManagerTest, NegotiateNewRTOFromOptionsAtClient) {
+TEST_F(QuicSentPacketManagerTest, NegotiateNewRTOFromOptionsAtClient) {
EXPECT_FALSE(QuicSentPacketManagerPeer::GetUseNewRto(&manager_));
QuicConfig client_config;
QuicTagVector options;
@@ -1577,7 +1566,7 @@ TEST_P(QuicSentPacketManagerTest, NegotiateNewRTOFromOptionsAtClient) {
EXPECT_TRUE(QuicSentPacketManagerPeer::GetUseNewRto(&manager_));
}
-TEST_P(QuicSentPacketManagerTest, NegotiateUndoFromOptionsAtServer) {
+TEST_F(QuicSentPacketManagerTest, NegotiateUndoFromOptionsAtServer) {
EXPECT_FALSE(QuicSentPacketManagerPeer::GetUndoRetransmits(&manager_));
QuicConfig config;
QuicTagVector options;
@@ -1600,7 +1589,7 @@ TEST_P(QuicSentPacketManagerTest, NegotiateUndoFromOptionsAtServer) {
for (size_t i = 1; i <= kNumSentPackets; ++i) {
SendDataPacket(i);
}
- auto loss_algorithm = base::MakeUnique<MockLossAlgorithm>();
+ auto loss_algorithm = QuicMakeUnique<MockLossAlgorithm>();
QuicSentPacketManagerPeer::SetLossAlgorithm(&manager_, loss_algorithm.get());
EXPECT_CALL(*send_algorithm_, OnCongestionEvent(true, _, _, _, _));
EXPECT_CALL(*network_change_visitor_, OnCongestionChange());
@@ -1628,7 +1617,7 @@ TEST_P(QuicSentPacketManagerTest, NegotiateUndoFromOptionsAtServer) {
EXPECT_EQ(3u * kDefaultLength, BytesInFlight());
}
-TEST_P(QuicSentPacketManagerTest, NegotiateUndoFromOptionsAtClient) {
+TEST_F(QuicSentPacketManagerTest, NegotiateUndoFromOptionsAtClient) {
EXPECT_FALSE(QuicSentPacketManagerPeer::GetUndoRetransmits(&manager_));
QuicConfig client_config;
QuicTagVector options;
@@ -1642,7 +1631,7 @@ TEST_P(QuicSentPacketManagerTest, NegotiateUndoFromOptionsAtClient) {
EXPECT_TRUE(QuicSentPacketManagerPeer::GetUndoRetransmits(&manager_));
}
-TEST_P(QuicSentPacketManagerTest, UseInitialRoundTripTimeToSend) {
+TEST_F(QuicSentPacketManagerTest, UseInitialRoundTripTimeToSend) {
uint32_t initial_rtt_us = 325000;
EXPECT_NE(initial_rtt_us,
manager_.GetRttStats()->smoothed_rtt().ToMicroseconds());
@@ -1657,7 +1646,7 @@ TEST_P(QuicSentPacketManagerTest, UseInitialRoundTripTimeToSend) {
EXPECT_EQ(initial_rtt_us, manager_.GetRttStats()->initial_rtt_us());
}
-TEST_P(QuicSentPacketManagerTest, ResumeConnectionState) {
+TEST_F(QuicSentPacketManagerTest, ResumeConnectionState) {
// The sent packet manager should use the RTT from CachedNetworkParameters if
// it is provided.
const int kRttMs = 1234;
@@ -1670,7 +1659,7 @@ TEST_P(QuicSentPacketManagerTest, ResumeConnectionState) {
static_cast<uint64_t>(manager_.GetRttStats()->initial_rtt_us()));
}
-TEST_P(QuicSentPacketManagerTest, ConnectionMigrationUnspecifiedChange) {
+TEST_F(QuicSentPacketManagerTest, ConnectionMigrationUnspecifiedChange) {
RttStats* rtt_stats = const_cast<RttStats*>(manager_.GetRttStats());
int64_t default_init_rtt = rtt_stats->initial_rtt_us();
rtt_stats->set_initial_rtt_us(default_init_rtt * 2);
@@ -1682,14 +1671,14 @@ TEST_P(QuicSentPacketManagerTest, ConnectionMigrationUnspecifiedChange) {
EXPECT_EQ(2u, manager_.GetConsecutiveTlpCount());
EXPECT_CALL(*send_algorithm_, OnConnectionMigration());
- manager_.OnConnectionMigration(kDefaultPathId, IPV4_TO_IPV4_CHANGE);
+ manager_.OnConnectionMigration(IPV4_TO_IPV4_CHANGE);
EXPECT_EQ(default_init_rtt, rtt_stats->initial_rtt_us());
EXPECT_EQ(0u, manager_.GetConsecutiveRtoCount());
EXPECT_EQ(0u, manager_.GetConsecutiveTlpCount());
}
-TEST_P(QuicSentPacketManagerTest, ConnectionMigrationIPSubnetChange) {
+TEST_F(QuicSentPacketManagerTest, ConnectionMigrationIPSubnetChange) {
RttStats* rtt_stats = const_cast<RttStats*>(manager_.GetRttStats());
int64_t default_init_rtt = rtt_stats->initial_rtt_us();
rtt_stats->set_initial_rtt_us(default_init_rtt * 2);
@@ -1700,14 +1689,14 @@ TEST_P(QuicSentPacketManagerTest, ConnectionMigrationIPSubnetChange) {
QuicSentPacketManagerPeer::SetConsecutiveTlpCount(&manager_, 2);
EXPECT_EQ(2u, manager_.GetConsecutiveTlpCount());
- manager_.OnConnectionMigration(kDefaultPathId, IPV4_SUBNET_CHANGE);
+ manager_.OnConnectionMigration(IPV4_SUBNET_CHANGE);
EXPECT_EQ(2 * default_init_rtt, rtt_stats->initial_rtt_us());
EXPECT_EQ(1u, manager_.GetConsecutiveRtoCount());
EXPECT_EQ(2u, manager_.GetConsecutiveTlpCount());
}
-TEST_P(QuicSentPacketManagerTest, ConnectionMigrationPortChange) {
+TEST_F(QuicSentPacketManagerTest, ConnectionMigrationPortChange) {
RttStats* rtt_stats = const_cast<RttStats*>(manager_.GetRttStats());
int64_t default_init_rtt = rtt_stats->initial_rtt_us();
rtt_stats->set_initial_rtt_us(default_init_rtt * 2);
@@ -1718,21 +1707,21 @@ TEST_P(QuicSentPacketManagerTest, ConnectionMigrationPortChange) {
QuicSentPacketManagerPeer::SetConsecutiveTlpCount(&manager_, 2);
EXPECT_EQ(2u, manager_.GetConsecutiveTlpCount());
- manager_.OnConnectionMigration(kDefaultPathId, PORT_CHANGE);
+ manager_.OnConnectionMigration(PORT_CHANGE);
EXPECT_EQ(2 * default_init_rtt, rtt_stats->initial_rtt_us());
EXPECT_EQ(1u, manager_.GetConsecutiveRtoCount());
EXPECT_EQ(2u, manager_.GetConsecutiveTlpCount());
}
-TEST_P(QuicSentPacketManagerTest, PathMtuIncreased) {
+TEST_F(QuicSentPacketManagerTest, PathMtuIncreased) {
EXPECT_CALL(*send_algorithm_, OnPacketSent(_, BytesInFlight(), 1, _, _))
.Times(1)
.WillOnce(Return(true));
SerializedPacket packet(kDefaultPathId, 1, PACKET_6BYTE_PACKET_NUMBER,
- nullptr, kDefaultLength + 100, 0u, false, false);
- manager_.OnPacketSent(&packet, kInvalidPathId, 0, clock_.Now(),
- NOT_RETRANSMISSION, HAS_RETRANSMITTABLE_DATA);
+ nullptr, kDefaultLength + 100, false, false);
+ manager_.OnPacketSent(&packet, 0, clock_.Now(), NOT_RETRANSMISSION,
+ HAS_RETRANSMITTABLE_DATA);
// Ack the large packet and expect the path MTU to increase.
ExpectAck(1);
diff --git a/chromium/net/quic/core/quic_server_id.cc b/chromium/net/quic/core/quic_server_id.cc
index ecc8d0e40fd..280530a97d5 100644
--- a/chromium/net/quic/core/quic_server_id.cc
+++ b/chromium/net/quic/core/quic_server_id.cc
@@ -6,9 +6,9 @@
#include <tuple>
-#include "base/logging.h"
#include "net/base/host_port_pair.h"
#include "net/base/port_util.h"
+#include "net/quic/platform/api/quic_str_cat.h"
#include "url/gurl.h"
using std::string;
@@ -52,8 +52,8 @@ QuicServerId QuicServerId::FromString(const std::string& str) {
}
string QuicServerId::ToString() const {
- return "https://" + host_port_pair_.ToString() +
- (privacy_mode_ == PRIVACY_MODE_ENABLED ? "/private" : "");
+ return QuicStrCat("https://", host_port_pair_.ToString(),
+ (privacy_mode_ == PRIVACY_MODE_ENABLED ? "/private" : ""));
}
} // namespace net
diff --git a/chromium/net/quic/core/quic_server_id.h b/chromium/net/quic/core/quic_server_id.h
index 97dbebbb49a..906529d1c51 100644
--- a/chromium/net/quic/core/quic_server_id.h
+++ b/chromium/net/quic/core/quic_server_id.h
@@ -2,22 +2,22 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#ifndef NET_QUIC_QUIC_SERVER_ID_H_
-#define NET_QUIC_QUIC_SERVER_ID_H_
+#ifndef NET_QUIC_CORE_QUIC_SERVER_ID_H_
+#define NET_QUIC_CORE_QUIC_SERVER_ID_H_
#include <stdint.h>
#include <string>
#include "net/base/host_port_pair.h"
-#include "net/base/net_export.h"
#include "net/base/privacy_mode.h"
+#include "net/quic/platform/api/quic_export.h"
namespace net {
// The id used to identify sessions. Includes the hostname, port, scheme and
// privacy_mode.
-class NET_EXPORT_PRIVATE QuicServerId {
+class QUIC_EXPORT_PRIVATE QuicServerId {
public:
QuicServerId();
QuicServerId(const HostPortPair& host_port_pair, PrivacyMode privacy_mode);
@@ -55,4 +55,4 @@ class NET_EXPORT_PRIVATE QuicServerId {
} // namespace net
-#endif // NET_QUIC_QUIC_SERVER_ID_H_
+#endif // NET_QUIC_CORE_QUIC_SERVER_ID_H_
diff --git a/chromium/net/quic/core/quic_server_session_base.cc b/chromium/net/quic/core/quic_server_session_base.cc
index 38004e0f728..d4275440c6d 100644
--- a/chromium/net/quic/core/quic_server_session_base.cc
+++ b/chromium/net/quic/core/quic_server_session_base.cc
@@ -4,13 +4,13 @@
#include "net/quic/core/quic_server_session_base.h"
-#include "base/logging.h"
#include "net/quic/core/proto/cached_network_parameters.pb.h"
-#include "net/quic/core/quic_bug_tracker.h"
#include "net/quic/core/quic_connection.h"
#include "net/quic/core/quic_flags.h"
#include "net/quic/core/quic_spdy_session.h"
#include "net/quic/core/quic_stream.h"
+#include "net/quic/platform/api/quic_bug_tracker.h"
+#include "net/quic/platform/api/quic_logging.h"
using std::string;
@@ -55,7 +55,7 @@ void QuicServerSessionBase::OnConfigNegotiated() {
bandwidth_resumption_enabled_ =
last_bandwidth_resumption || max_bandwidth_resumption;
- if (!FLAGS_quic_enable_server_push_by_default ||
+ if (!FLAGS_quic_reloadable_flag_quic_enable_server_push_by_default ||
connection()->version() < QUIC_VERSION_35) {
set_server_push_enabled(
ContainsQuicTag(config()->ReceivedConnectionOptions(), kSPSH));
@@ -74,7 +74,7 @@ void QuicServerSessionBase::OnConfigNegotiated() {
if (bandwidth_resumption_enabled_) {
// Only do bandwidth resumption if estimate is recent enough.
- const int64_t seconds_since_estimate =
+ const uint64_t seconds_since_estimate =
connection()->clock()->WallNow().ToUNIXSeconds() -
cached_network_params->timestamp();
if (seconds_since_estimate <= kNumSecondsPerHour) {
@@ -107,7 +107,7 @@ void QuicServerSessionBase::OnCongestionWindowChange(QuicTime now) {
// If not enough time has passed since the last time we sent an update to the
// client, or not enough packets have been sent, then return early.
- const QuicSentPacketManagerInterface& sent_packet_manager =
+ const QuicSentPacketManager& sent_packet_manager =
connection()->sent_packet_manager();
int64_t srtt_ms =
sent_packet_manager.GetRttStats()->smoothed_rtt().ToMilliseconds();
@@ -148,8 +148,8 @@ void QuicServerSessionBase::OnCongestionWindowChange(QuicTime now) {
}
bandwidth_estimate_sent_to_client_ = new_bandwidth_estimate;
- DVLOG(1) << "Server: sending new bandwidth estimate (KBytes/s): "
- << bandwidth_estimate_sent_to_client_.ToKBytesPerSecond();
+ QUIC_DVLOG(1) << "Server: sending new bandwidth estimate (KBytes/s): "
+ << bandwidth_estimate_sent_to_client_.ToKBytesPerSecond();
// Include max bandwidth in the update.
QuicBandwidth max_bandwidth_estimate =
@@ -200,7 +200,7 @@ bool QuicServerSessionBase::ShouldCreateIncomingDynamicStream(QuicStreamId id) {
}
if (id % 2 == 0) {
- DVLOG(1) << "Invalid incoming even stream_id:" << id;
+ QUIC_DLOG(INFO) << "Invalid incoming even stream_id:" << id;
connection()->CloseConnection(
QUIC_INVALID_STREAM_ID, "Client created even numbered stream",
ConnectionCloseBehavior::SEND_CONNECTION_CLOSE_PACKET);
diff --git a/chromium/net/quic/core/quic_server_session_base.h b/chromium/net/quic/core/quic_server_session_base.h
index 19b6b1e894d..5ad9a848e02 100644
--- a/chromium/net/quic/core/quic_server_session_base.h
+++ b/chromium/net/quic/core/quic_server_session_base.h
@@ -4,8 +4,8 @@
//
// A server specific QuicSession subclass.
-#ifndef NET_QUIC_QUIC_SERVER_SESSION_BASE_H_
-#define NET_QUIC_QUIC_SERVER_SESSION_BASE_H_
+#ifndef NET_QUIC_CORE_QUIC_SERVER_SESSION_BASE_H_
+#define NET_QUIC_CORE_QUIC_SERVER_SESSION_BASE_H_
#include <stdint.h>
@@ -16,26 +16,24 @@
#include <vector>
#include "base/macros.h"
-#include "net/base/net_export.h"
#include "net/quic/core/crypto/quic_compressed_certs_cache.h"
#include "net/quic/core/quic_crypto_server_stream.h"
-#include "net/quic/core/quic_protocol.h"
+#include "net/quic/core/quic_packets.h"
#include "net/quic/core/quic_spdy_session.h"
+#include "net/quic/platform/api/quic_export.h"
namespace net {
-class QuicBlockedWriterInterface;
class QuicConfig;
class QuicConnection;
class QuicCryptoServerConfig;
-class QuicStream;
namespace test {
class QuicServerSessionBasePeer;
class QuicSimpleServerSessionPeer;
} // namespace test
-class NET_EXPORT_PRIVATE QuicServerSessionBase : public QuicSpdySession {
+class QUIC_EXPORT_PRIVATE QuicServerSessionBase : public QuicSpdySession {
public:
// Does not take ownership of |connection|. |crypto_config| must outlive the
// session. |helper| must outlive any created crypto streams.
@@ -137,4 +135,4 @@ class NET_EXPORT_PRIVATE QuicServerSessionBase : public QuicSpdySession {
} // namespace net
-#endif // NET_QUIC_QUIC_SERVER_SESSION_BASE_H_
+#endif // NET_QUIC_CORE_QUIC_SERVER_SESSION_BASE_H_
diff --git a/chromium/net/quic/core/quic_server_session_base_test.cc b/chromium/net/quic/core/quic_server_session_base_test.cc
index 22aee56e749..5baad162205 100644
--- a/chromium/net/quic/core/quic_server_session_base_test.cc
+++ b/chromium/net/quic/core/quic_server_session_base_test.cc
@@ -8,13 +8,14 @@
#include <memory>
#include "base/macros.h"
-#include "base/memory/ptr_util.h"
#include "net/quic/core/crypto/quic_crypto_server_config.h"
#include "net/quic/core/crypto/quic_random.h"
#include "net/quic/core/proto/cached_network_parameters.pb.h"
#include "net/quic/core/quic_connection.h"
#include "net/quic/core/quic_crypto_server_stream.h"
#include "net/quic/core/quic_utils.h"
+#include "net/quic/platform/api/quic_ptr_util.h"
+#include "net/quic/platform/api/quic_socket_address.h"
#include "net/quic/test_tools/crypto_test_utils.h"
#include "net/quic/test_tools/fake_proof_source.h"
#include "net/quic/test_tools/quic_config_peer.h"
@@ -34,22 +35,6 @@
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
-using net::test::CryptoTestUtils;
-using net::test::MockQuicConnection;
-using net::test::MockQuicConnectionHelper;
-using net::test::QuicConfigPeer;
-using net::test::QuicConnectionPeer;
-using net::test::QuicSpdyStreamPeer;
-using net::test::QuicSentPacketManagerPeer;
-using net::test::QuicSessionPeer;
-using net::test::QuicSpdySessionPeer;
-using net::test::QuicSustainedBandwidthRecorderPeer;
-using net::test::SupportedVersions;
-using net::test::kClientDataStreamId1;
-using net::test::kClientDataStreamId2;
-using net::test::kClientDataStreamId3;
-using net::test::kInitialSessionFlowControlWindowForTest;
-using net::test::kInitialStreamFlowControlWindowForTest;
using std::string;
using testing::StrictMock;
using testing::_;
@@ -82,13 +67,15 @@ class TestServerSession : public QuicServerSessionBase {
QuicSession::Visitor* visitor,
QuicCryptoServerStream::Helper* helper,
const QuicCryptoServerConfig* crypto_config,
- QuicCompressedCertsCache* compressed_certs_cache)
+ QuicCompressedCertsCache* compressed_certs_cache,
+ QuicHttpResponseCache* response_cache)
: QuicServerSessionBase(config,
connection,
visitor,
helper,
crypto_config,
- compressed_certs_cache) {}
+ compressed_certs_cache),
+ response_cache_(response_cache) {}
~TestServerSession() override { delete connection(); };
@@ -97,8 +84,9 @@ class TestServerSession : public QuicServerSessionBase {
if (!ShouldCreateIncomingDynamicStream(id)) {
return nullptr;
}
- QuicSpdyStream* stream = new QuicSimpleServerStream(id, this);
- ActivateStream(base::WrapUnique(stream));
+ QuicSpdyStream* stream =
+ new QuicSimpleServerStream(id, this, response_cache_);
+ ActivateStream(QuicWrapUnique(stream));
return stream;
}
@@ -107,10 +95,10 @@ class TestServerSession : public QuicServerSessionBase {
return nullptr;
}
- QuicSpdyStream* stream =
- new QuicSimpleServerStream(GetNextOutgoingStreamId(), this);
+ QuicSpdyStream* stream = new QuicSimpleServerStream(
+ GetNextOutgoingStreamId(), this, response_cache_);
stream->SetPriority(priority);
- ActivateStream(base::WrapUnique(stream));
+ ActivateStream(QuicWrapUnique(stream));
return stream;
}
@@ -119,8 +107,12 @@ class TestServerSession : public QuicServerSessionBase {
QuicCompressedCertsCache* compressed_certs_cache) override {
return new QuicCryptoServerStream(
crypto_config, compressed_certs_cache,
- FLAGS_enable_quic_stateless_reject_support, this, stream_helper());
+ FLAGS_quic_reloadable_flag_enable_quic_stateless_reject_support, this,
+ stream_helper());
}
+
+ private:
+ QuicHttpResponseCache* response_cache_; // Owned by QuicServerSessionBaseTest
};
const size_t kMaxStreamsForTest = 10;
@@ -148,9 +140,9 @@ class QuicServerSessionBaseTest : public ::testing::TestWithParam<QuicVersion> {
connection_ = new StrictMock<MockQuicConnection>(
&helper_, &alarm_factory_, Perspective::IS_SERVER,
SupportedVersions(GetParam()));
- session_.reset(new TestServerSession(config_, connection_, &owner_,
- &stream_helper_, &crypto_config_,
- &compressed_certs_cache_));
+ session_.reset(new TestServerSession(
+ config_, connection_, &owner_, &stream_helper_, &crypto_config_,
+ &compressed_certs_cache_, &response_cache_));
MockClock clock;
handshake_message_.reset(crypto_config_.AddDefaultConfig(
QuicRandom::GetInstance(), &clock,
@@ -167,6 +159,7 @@ class QuicServerSessionBaseTest : public ::testing::TestWithParam<QuicVersion> {
QuicConfig config_;
QuicCryptoServerConfig crypto_config_;
QuicCompressedCertsCache compressed_certs_cache_;
+ QuicHttpResponseCache response_cache_;
std::unique_ptr<TestServerSession> session_;
std::unique_ptr<CryptoHandshakeMessage> handshake_message_;
QuicConnectionVisitorInterface* visitor_;
@@ -193,7 +186,7 @@ INSTANTIATE_TEST_CASE_P(Tests,
QuicServerSessionBaseTest,
::testing::ValuesIn(AllSupportedVersions()));
TEST_P(QuicServerSessionBaseTest, ServerPushDisabledByDefault) {
- FLAGS_quic_enable_server_push_by_default = true;
+ FLAGS_quic_reloadable_flag_quic_enable_server_push_by_default = true;
// Without the client explicitly sending kSPSH, server push will be disabled
// at the server, until version 35 when it is enabled by default.
EXPECT_FALSE(
@@ -356,10 +349,10 @@ TEST_P(QuicServerSessionBaseTest, MaxAvailableStreams) {
}
// TODO(ckrasic): remove this when
-// FLAGS_quic_enable_server_push_by_default is
+// FLAGS_quic_reloadable_flag_quic_enable_server_push_by_default is
// deprecated.
TEST_P(QuicServerSessionBaseTest, EnableServerPushThroughConnectionOption) {
- FLAGS_quic_enable_server_push_by_default = false;
+ FLAGS_quic_reloadable_flag_quic_enable_server_push_by_default = false;
// Assume server received server push connection option.
QuicTagVector copt;
copt.push_back(kSPSH);
@@ -390,11 +383,12 @@ class MockQuicCryptoServerStream : public QuicCryptoServerStream {
QuicCompressedCertsCache* compressed_certs_cache,
QuicServerSessionBase* session,
QuicCryptoServerStream::Helper* helper)
- : QuicCryptoServerStream(crypto_config,
- compressed_certs_cache,
- FLAGS_enable_quic_stateless_reject_support,
- session,
- helper) {}
+ : QuicCryptoServerStream(
+ crypto_config,
+ compressed_certs_cache,
+ FLAGS_quic_reloadable_flag_enable_quic_stateless_reject_support,
+ session,
+ helper) {}
~MockQuicCryptoServerStream() override {}
MOCK_METHOD1(SendServerConfigUpdate,
@@ -437,8 +431,7 @@ TEST_P(QuicServerSessionBaseTest, BandwidthEstimates) {
// Set some initial bandwidth values.
QuicSentPacketManager* sent_packet_manager =
- QuicConnectionPeer::GetSentPacketManager(session_->connection(),
- kDefaultPathId);
+ QuicConnectionPeer::GetSentPacketManager(session_->connection());
QuicSustainedBandwidthRecorder& bandwidth_recorder =
QuicSentPacketManagerPeer::GetBandwidthRecorder(sent_packet_manager);
// Seed an rtt measurement equal to the initial default rtt.
@@ -606,10 +599,10 @@ INSTANTIATE_TEST_CASE_P(StreamMemberLifetimeTests,
// ProofSource::GetProof. Delay the completion of the operation until after the
// stream has been destroyed, and verify that there are no memory bugs.
TEST_P(StreamMemberLifetimeTest, Basic) {
- FLAGS_enable_async_get_proof = true;
- FLAGS_enable_quic_stateless_reject_support = true;
- FLAGS_quic_use_cheap_stateless_rejects = true;
- FLAGS_quic_create_session_after_insertion = true;
+ FLAGS_quic_reloadable_flag_enable_async_get_proof = true;
+ FLAGS_quic_reloadable_flag_enable_quic_stateless_reject_support = true;
+ FLAGS_quic_reloadable_flag_quic_use_cheap_stateless_rejects = true;
+ FLAGS_quic_reloadable_flag_quic_create_session_after_insertion = true;
const QuicClock* clock = helper_.GetClock();
QuicVersion version = AllSupportedVersions().front();
diff --git a/chromium/net/quic/core/quic_session.cc b/chromium/net/quic/core/quic_session.cc
index c3c668884c6..0845816fac4 100644
--- a/chromium/net/quic/core/quic_session.cc
+++ b/chromium/net/quic/core/quic_session.cc
@@ -4,22 +4,17 @@
#include "net/quic/core/quic_session.h"
-#include "base/memory/ptr_util.h"
#include "base/stl_util.h"
-#include "base/strings/string_number_conversions.h"
-#include "base/strings/stringprintf.h"
#include "net/quic/core/crypto/proof_verifier.h"
-#include "net/quic/core/quic_bug_tracker.h"
#include "net/quic/core/quic_connection.h"
#include "net/quic/core/quic_flags.h"
#include "net/quic/core/quic_flow_controller.h"
+#include "net/quic/platform/api/quic_bug_tracker.h"
+#include "net/quic/platform/api/quic_logging.h"
+#include "net/quic/platform/api/quic_str_cat.h"
-using base::IntToString;
using base::StringPiece;
-using std::make_pair;
-using std::max;
using std::string;
-using net::SpdyPriority;
namespace net {
@@ -58,13 +53,13 @@ void QuicSession::Initialize() {
}
QuicSession::~QuicSession() {
- DLOG_IF(WARNING, num_locally_closed_incoming_streams_highest_offset() >
- max_open_incoming_streams_)
+ QUIC_LOG_IF(WARNING, num_locally_closed_incoming_streams_highest_offset() >
+ max_open_incoming_streams_)
<< "Surprisingly high number of locally closed peer initiated streams"
"still waiting for final byte offset: "
<< num_locally_closed_incoming_streams_highest_offset();
- DLOG_IF(WARNING, GetNumLocallyClosedOutgoingStreamsHighestOffset() >
- max_open_outgoing_streams_)
+ QUIC_LOG_IF(WARNING, GetNumLocallyClosedOutgoingStreamsHighestOffset() >
+ max_open_outgoing_streams_)
<< "Surprisingly high number of locally closed self initiated streams"
"still waiting for final byte offset: "
<< GetNumLocallyClosedOutgoingStreamsHighestOffset();
@@ -151,9 +146,10 @@ void QuicSession::OnWindowUpdateFrame(const QuicWindowUpdateFrame& frame) {
if (stream_id == kConnectionLevelId) {
// This is a window update that applies to the connection, rather than an
// individual stream.
- DVLOG(1) << ENDPOINT << "Received connection level flow control window "
- "update with byte offset: "
- << frame.byte_offset;
+ QUIC_DLOG(INFO) << ENDPOINT
+ << "Received connection level flow control window "
+ "update with byte offset: "
+ << frame.byte_offset;
flow_controller_.UpdateSendWindowOffset(frame.byte_offset);
return;
}
@@ -167,8 +163,8 @@ void QuicSession::OnBlockedFrame(const QuicBlockedFrame& frame) {
// TODO(rjshade): Compare our flow control receive windows for specified
// streams: if we have a large window then maybe something
// had gone wrong with the flow control accounting.
- DVLOG(1) << ENDPOINT
- << "Received BLOCKED frame with stream id: " << frame.stream_id;
+ QUIC_DLOG(INFO) << ENDPOINT << "Received BLOCKED frame with stream id: "
+ << frame.stream_id;
}
bool QuicSession::CheckStreamNotBusyLooping(QuicStream* stream,
@@ -182,17 +178,18 @@ bool QuicSession::CheckStreamNotBusyLooping(QuicStream* stream,
previous_bytes_written == stream->stream_bytes_written() &&
previous_fin_sent == stream->fin_sent()) {
stream->set_busy_counter(stream->busy_counter() + 1);
- DVLOG(1) << "Suspected busy loop on stream id " << stream->id()
- << " stream_bytes_written " << stream->stream_bytes_written()
- << " fin " << stream->fin_sent() << " count "
- << stream->busy_counter();
+ QUIC_DVLOG(1) << "Suspected busy loop on stream id " << stream->id()
+ << " stream_bytes_written " << stream->stream_bytes_written()
+ << " fin " << stream->fin_sent() << " count "
+ << stream->busy_counter();
// Wait a few iterations before firing, the exact count is
// arbitrary, more than a few to cover a few test-only false
// positives.
if (stream->busy_counter() > 20) {
- LOG(ERROR) << "Detected busy loop on stream id " << stream->id()
- << " stream_bytes_written " << stream->stream_bytes_written()
- << " fin " << stream->fin_sent();
+ QUIC_LOG(ERROR) << "Detected busy loop on stream id " << stream->id()
+ << " stream_bytes_written "
+ << stream->stream_bytes_written() << " fin "
+ << stream->fin_sent();
return false;
}
} else {
@@ -245,8 +242,8 @@ void QuicSession::OnCanWrite() {
// list.
uint64_t previous_bytes_written = stream->stream_bytes_written();
bool previous_fin_sent = stream->fin_sent();
- DVLOG(1) << "stream " << stream->id() << " bytes_written "
- << previous_bytes_written << " fin " << previous_fin_sent;
+ QUIC_DVLOG(1) << "stream " << stream->id() << " bytes_written "
+ << previous_bytes_written << " fin " << previous_fin_sent;
stream->OnCanWrite();
DCHECK(CheckStreamNotBusyLooping(stream, previous_bytes_written,
previous_fin_sent));
@@ -274,8 +271,8 @@ bool QuicSession::HasOpenDynamicStreams() const {
locally_closed_streams_highest_offset_.size()) > 0;
}
-void QuicSession::ProcessUdpPacket(const IPEndPoint& self_address,
- const IPEndPoint& peer_address,
+void QuicSession::ProcessUdpPacket(const QuicSocketAddress& self_address,
+ const QuicSocketAddress& peer_address,
const QuicReceivedPacket& packet) {
connection_->ProcessUdpPacket(self_address, peer_address, packet);
}
@@ -286,7 +283,7 @@ QuicConsumedData QuicSession::WritevData(
QuicIOVector iov,
QuicStreamOffset offset,
bool fin,
- QuicAckListenerInterface* ack_notifier_delegate) {
+ QuicReferenceCountedPointer<QuicAckListenerInterface> ack_listener) {
// This check is an attempt to deal with potential memory corruption
// in which |id| ends up set to 1 (the crypto stream id). If this happen
// it might end up resulting in unencrypted stream data being sent.
@@ -305,8 +302,8 @@ QuicConsumedData QuicSession::WritevData(
// up write blocked until OnCanWrite is next called.
return QuicConsumedData(0, false);
}
- QuicConsumedData data =
- connection_->SendStreamData(id, iov, offset, fin, ack_notifier_delegate);
+ QuicConsumedData data = connection_->SendStreamData(id, iov, offset, fin,
+ std::move(ack_listener));
write_blocked_streams_.UpdateBytesForStream(id, data.bytes_consumed);
return data;
}
@@ -348,14 +345,14 @@ void QuicSession::InsertLocallyClosedStreamsHighestOffset(
}
void QuicSession::CloseStreamInner(QuicStreamId stream_id, bool locally_reset) {
- DVLOG(1) << ENDPOINT << "Closing stream " << stream_id;
+ QUIC_DLOG(INFO) << ENDPOINT << "Closing stream " << stream_id;
DynamicStreamMap::iterator it = dynamic_stream_map_.find(stream_id);
if (it == dynamic_stream_map_.end()) {
// When CloseStreamInner has been called recursively (via
// QuicStream::OnClose), the stream will already have been deleted
// from stream_map_, so return immediately.
- DVLOG(1) << ENDPOINT << "Stream is already closed: " << stream_id;
+ QUIC_DLOG(INFO) << ENDPOINT << "Stream is already closed: " << stream_id;
return;
}
QuicStream* stream = it->second.get();
@@ -400,8 +397,8 @@ void QuicSession::UpdateFlowControlOnFinalReceivedByteOffset(
return;
}
- DVLOG(1) << ENDPOINT << "Received final byte offset " << final_byte_offset
- << " for stream " << stream_id;
+ QUIC_DVLOG(1) << ENDPOINT << "Received final byte offset "
+ << final_byte_offset << " for stream " << stream_id;
QuicByteCount offset_diff = final_byte_offset - it->second;
if (flow_controller_.UpdateHighestReceivedOffset(
flow_controller_.highest_received_byte_offset() + offset_diff)) {
@@ -442,6 +439,28 @@ void QuicSession::OnConfigNegotiated() {
max_streams = config_.MaxStreamsPerConnection();
}
set_max_open_outgoing_streams(max_streams);
+ if (FLAGS_quic_reloadable_flag_quic_large_ifw_options &&
+ perspective() == Perspective::IS_SERVER) {
+ if (config_.HasReceivedConnectionOptions()) {
+ // The following variations change the initial receive flow control
+ // window sizes.
+ if (ContainsQuicTag(config_.ReceivedConnectionOptions(), kIFW6)) {
+ AdjustInitialFlowControlWindows(64 * 1024);
+ }
+ if (ContainsQuicTag(config_.ReceivedConnectionOptions(), kIFW7)) {
+ AdjustInitialFlowControlWindows(128 * 1024);
+ }
+ if (ContainsQuicTag(config_.ReceivedConnectionOptions(), kIFW8)) {
+ AdjustInitialFlowControlWindows(256 * 1024);
+ }
+ if (ContainsQuicTag(config_.ReceivedConnectionOptions(), kIFW9)) {
+ AdjustInitialFlowControlWindows(512 * 1024);
+ }
+ if (ContainsQuicTag(config_.ReceivedConnectionOptions(), kIFWA)) {
+ AdjustInitialFlowControlWindows(1024 * 1024);
+ }
+ }
+ }
if (version <= QUIC_VERSION_34) {
// A small number of additional incoming streams beyond the limit should be
@@ -450,16 +469,16 @@ void QuicSession::OnConfigNegotiated() {
// Use a minimum number of additional streams, or a percentage increase,
// whichever is larger.
uint32_t max_incoming_streams =
- max(max_streams + kMaxStreamsMinimumIncrement,
- static_cast<uint32_t>(max_streams * kMaxStreamsMultiplier));
+ std::max(max_streams + kMaxStreamsMinimumIncrement,
+ static_cast<uint32_t>(max_streams * kMaxStreamsMultiplier));
set_max_open_incoming_streams(max_incoming_streams);
} else {
uint32_t max_incoming_streams_to_send =
config_.GetMaxIncomingDynamicStreamsToSend();
uint32_t max_incoming_streams =
- max(max_incoming_streams_to_send + kMaxStreamsMinimumIncrement,
- static_cast<uint32_t>(max_incoming_streams_to_send *
- kMaxStreamsMultiplier));
+ std::max(max_incoming_streams_to_send + kMaxStreamsMinimumIncrement,
+ static_cast<uint32_t>(max_incoming_streams_to_send *
+ kMaxStreamsMultiplier));
set_max_open_incoming_streams(max_incoming_streams);
}
@@ -475,6 +494,31 @@ void QuicSession::OnConfigNegotiated() {
}
}
+void QuicSession::AdjustInitialFlowControlWindows(size_t stream_window) {
+ const float session_window_multiplier =
+ config_.GetInitialStreamFlowControlWindowToSend()
+ ? static_cast<float>(
+ config_.GetInitialSessionFlowControlWindowToSend()) /
+ config_.GetInitialStreamFlowControlWindowToSend()
+ : 1.5;
+
+ QUIC_DVLOG(1) << ENDPOINT << "Set stream receive window to " << stream_window;
+ config_.SetInitialStreamFlowControlWindowToSend(stream_window);
+
+ size_t session_window = session_window_multiplier * stream_window;
+ QUIC_DVLOG(1) << ENDPOINT << "Set session receive window to "
+ << session_window;
+ config_.SetInitialSessionFlowControlWindowToSend(session_window);
+ flow_controller_.UpdateReceiveWindowSize(session_window);
+ // Inform all existing streams about the new window.
+ for (auto const& kv : static_stream_map_) {
+ kv.second->flow_controller()->UpdateReceiveWindowSize(stream_window);
+ }
+ for (auto const& kv : dynamic_stream_map_) {
+ kv.second->flow_controller()->UpdateReceiveWindowSize(stream_window);
+ }
+}
+
void QuicSession::HandleFrameOnNonexistentOutgoingStream(
QuicStreamId stream_id) {
DCHECK(!IsClosedStream(stream_id));
@@ -500,9 +544,9 @@ void QuicSession::HandleRstOnValidNonexistentStream(
void QuicSession::OnNewStreamFlowControlWindow(QuicStreamOffset new_window) {
if (new_window < kMinimumFlowControlSendWindow) {
- LOG(ERROR) << "Peer sent us an invalid stream flow control send window: "
- << new_window
- << ", below default: " << kMinimumFlowControlSendWindow;
+ QUIC_LOG_FIRST_N(ERROR, 1)
+ << "Peer sent us an invalid stream flow control send window: "
+ << new_window << ", below default: " << kMinimumFlowControlSendWindow;
if (connection_->connected()) {
connection_->CloseConnection(
QUIC_FLOW_CONTROL_INVALID_WINDOW, "New stream window too low",
@@ -522,9 +566,9 @@ void QuicSession::OnNewStreamFlowControlWindow(QuicStreamOffset new_window) {
void QuicSession::OnNewSessionFlowControlWindow(QuicStreamOffset new_window) {
if (new_window < kMinimumFlowControlSendWindow) {
- LOG(ERROR) << "Peer sent us an invalid session flow control send window: "
- << new_window
- << ", below default: " << kMinimumFlowControlSendWindow;
+ QUIC_LOG_FIRST_N(ERROR, 1)
+ << "Peer sent us an invalid session flow control send window: "
+ << new_window << ", below default: " << kMinimumFlowControlSendWindow;
if (connection_->connected()) {
connection_->CloseConnection(
QUIC_FLOW_CONTROL_INVALID_WINDOW, "New connection window too low",
@@ -562,7 +606,7 @@ void QuicSession::OnCryptoHandshakeEvent(CryptoHandshakeEvent event) {
break;
default:
- LOG(ERROR) << ENDPOINT << "Got unknown handshake event: " << event;
+ QUIC_LOG(ERROR) << ENDPOINT << "Got unknown handshake event: " << event;
}
}
@@ -578,8 +622,8 @@ QuicConfig* QuicSession::config() {
void QuicSession::ActivateStream(std::unique_ptr<QuicStream> stream) {
QuicStreamId stream_id = stream->id();
- DVLOG(1) << ENDPOINT << "num_streams: " << dynamic_stream_map_.size()
- << ". activating " << stream_id;
+ QUIC_DLOG(INFO) << ENDPOINT << "num_streams: " << dynamic_stream_map_.size()
+ << ". activating " << stream_id;
DCHECK(!base::ContainsKey(dynamic_stream_map_, stream_id));
DCHECK(!base::ContainsKey(static_stream_map_, stream_id));
dynamic_stream_map_[stream_id] = std::move(stream);
@@ -628,16 +672,16 @@ bool QuicSession::MaybeIncreaseLargestPeerStreamId(
size_t new_num_available_streams =
GetNumAvailableStreams() + additional_available_streams;
if (new_num_available_streams > MaxAvailableStreams()) {
- DVLOG(1) << ENDPOINT
- << "Failed to create a new incoming stream with id:" << stream_id
- << ". There are already " << GetNumAvailableStreams()
- << " streams available, which would become "
- << new_num_available_streams << ", which exceeds the limit "
- << MaxAvailableStreams() << ".";
- string details = IntToString(new_num_available_streams) + " above " +
- IntToString(MaxAvailableStreams());
+ QUIC_DLOG(INFO) << ENDPOINT
+ << "Failed to create a new incoming stream with id:"
+ << stream_id << ". There are already "
+ << GetNumAvailableStreams()
+ << " streams available, which would become "
+ << new_num_available_streams << ", which exceeds the limit "
+ << MaxAvailableStreams() << ".";
connection()->CloseConnection(
- QUIC_TOO_MANY_AVAILABLE_STREAMS, details.c_str(),
+ QUIC_TOO_MANY_AVAILABLE_STREAMS,
+ QuicStrCat(new_num_available_streams, " above ", MaxAvailableStreams()),
ConnectionCloseBehavior::SEND_CONNECTION_CLOSE_PACKET);
return false;
}
@@ -694,16 +738,16 @@ QuicStream* QuicSession::GetOrCreateDynamicStream(
void QuicSession::set_max_open_incoming_streams(
size_t max_open_incoming_streams) {
- DVLOG(1) << "Setting max_open_incoming_streams_ to "
- << max_open_incoming_streams;
+ QUIC_DVLOG(1) << "Setting max_open_incoming_streams_ to "
+ << max_open_incoming_streams;
max_open_incoming_streams_ = max_open_incoming_streams;
- DVLOG(1) << "MaxAvailableStreams() became " << MaxAvailableStreams();
+ QUIC_DVLOG(1) << "MaxAvailableStreams() became " << MaxAvailableStreams();
}
void QuicSession::set_max_open_outgoing_streams(
size_t max_open_outgoing_streams) {
- DVLOG(1) << "Setting max_open_outgoing_streams_ to "
- << max_open_outgoing_streams;
+ QUIC_DVLOG(1) << "Setting max_open_outgoing_streams_ to "
+ << max_open_outgoing_streams;
max_open_outgoing_streams_ = max_open_outgoing_streams;
}
diff --git a/chromium/net/quic/core/quic_session.h b/chromium/net/quic/core/quic_session.h
index f25b50f7f5e..7397b7195d8 100644
--- a/chromium/net/quic/core/quic_session.h
+++ b/chromium/net/quic/core/quic_session.h
@@ -4,8 +4,8 @@
//
// A QuicSession, which demuxes a single connection to individual streams.
-#ifndef NET_QUIC_QUIC_SESSION_H_
-#define NET_QUIC_QUIC_SESSION_H_
+#ifndef NET_QUIC_CORE_QUIC_SESSION_H_
+#define NET_QUIC_CORE_QUIC_SESSION_H_
#include <stddef.h>
@@ -20,14 +20,13 @@
#include "base/containers/small_map.h"
#include "base/macros.h"
#include "base/strings/string_piece.h"
-#include "net/base/ip_endpoint.h"
-#include "net/base/net_export.h"
#include "net/quic/core/quic_connection.h"
#include "net/quic/core/quic_crypto_stream.h"
#include "net/quic/core/quic_packet_creator.h"
-#include "net/quic/core/quic_protocol.h"
+#include "net/quic/core/quic_packets.h"
#include "net/quic/core/quic_stream.h"
#include "net/quic/core/quic_write_blocked_list.h"
+#include "net/quic/platform/api/quic_export.h"
namespace net {
@@ -39,7 +38,7 @@ namespace test {
class QuicSessionPeer;
} // namespace test
-class NET_EXPORT_PRIVATE QuicSession : public QuicConnectionVisitorInterface {
+class QUIC_EXPORT_PRIVATE QuicSession : public QuicConnectionVisitorInterface {
public:
// An interface from the session to the entity owning the session.
// This lets the session notify its owner (the Dispatcher) when the connection
@@ -106,8 +105,8 @@ class NET_EXPORT_PRIVATE QuicSession : public QuicConnectionVisitorInterface {
void OnPathDegrading() override;
// Called on every incoming packet. Passes |packet| through to |connection_|.
- virtual void ProcessUdpPacket(const IPEndPoint& self_address,
- const IPEndPoint& peer_address,
+ virtual void ProcessUdpPacket(const QuicSocketAddress& self_address,
+ const QuicSocketAddress& peer_address,
const QuicReceivedPacket& packet);
// Called by streams when they want to write data to the peer.
@@ -123,7 +122,7 @@ class NET_EXPORT_PRIVATE QuicSession : public QuicConnectionVisitorInterface {
QuicIOVector iov,
QuicStreamOffset offset,
bool fin,
- QuicAckListenerInterface* ack_notifier_delegate);
+ QuicReferenceCountedPointer<QuicAckListenerInterface> ack_listener);
// Called by streams when they want to close the stream in both directions.
virtual void SendRstStream(QuicStreamId id,
@@ -177,26 +176,28 @@ class NET_EXPORT_PRIVATE QuicSession : public QuicConnectionVisitorInterface {
QuicConnection* connection() { return connection_; }
const QuicConnection* connection() const { return connection_; }
size_t num_active_requests() const { return dynamic_stream_map_.size(); }
- const IPEndPoint& peer_address() const { return connection_->peer_address(); }
+ const QuicSocketAddress& peer_address() const {
+ return connection_->peer_address();
+ }
QuicConnectionId connection_id() const {
return connection_->connection_id();
}
// Returns the number of currently open streams, excluding the reserved
// headers and crypto streams, and never counting unfinished streams.
- virtual size_t GetNumActiveStreams() const;
+ size_t GetNumActiveStreams() const;
// Returns the number of currently open peer initiated streams, excluding the
// reserved headers and crypto streams.
- virtual size_t GetNumOpenIncomingStreams() const;
+ size_t GetNumOpenIncomingStreams() const;
// Returns the number of currently open self initiated streams, excluding the
// reserved headers and crypto streams.
- virtual size_t GetNumOpenOutgoingStreams() const;
+ size_t GetNumOpenOutgoingStreams() const;
// Returns the number of "available" streams, the stream ids less than
// largest_peer_created_stream_id_ that have not yet been opened.
- virtual size_t GetNumAvailableStreams() const;
+ size_t GetNumAvailableStreams() const;
// Add the stream to the session's write-blocked list because it is blocked by
// connection-level flow control but not by its own stream-level flow control.
@@ -354,10 +355,6 @@ class NET_EXPORT_PRIVATE QuicSession : public QuicConnectionVisitorInterface {
virtual void HandleRstOnValidNonexistentStream(
const QuicRstStreamFrame& frame);
- Visitor* visitor() { return visitor_; }
-
- const Visitor* visitor() const { return visitor_; }
-
private:
friend class test::QuicSessionPeer;
@@ -375,6 +372,10 @@ class NET_EXPORT_PRIVATE QuicSession : public QuicConnectionVisitorInterface {
uint64_t previous_bytes_written,
bool previous_fin_sent);
+ // Called in OnConfigNegotiated for Finch trials to measure performance of
+ // starting with larger flow control receive windows.
+ void AdjustInitialFlowControlWindows(size_t stream_window);
+
// Keep track of highest received byte offset of locally closed streams, while
// waiting for a definitive final highest offset from the peer.
std::map<QuicStreamId, QuicStreamOffset>
@@ -444,4 +445,4 @@ class NET_EXPORT_PRIVATE QuicSession : public QuicConnectionVisitorInterface {
} // namespace net
-#endif // NET_QUIC_QUIC_SESSION_H_
+#endif // NET_QUIC_CORE_QUIC_SESSION_H_
diff --git a/chromium/net/quic/core/quic_session_test.cc b/chromium/net/quic/core/quic_session_test.cc
index 17bd3d0c4bb..f2deba15b63 100644
--- a/chromium/net/quic/core/quic_session_test.cc
+++ b/chromium/net/quic/core/quic_session_test.cc
@@ -7,22 +7,21 @@
#include <set>
#include <utility>
-#include "base/memory/ptr_util.h"
#include "base/rand_util.h"
#include "base/stl_util.h"
-#include "base/strings/string_number_conversions.h"
#include "build/build_config.h"
#include "net/quic/core/crypto/crypto_protocol.h"
#include "net/quic/core/crypto/null_encrypter.h"
#include "net/quic/core/quic_crypto_stream.h"
#include "net/quic/core/quic_flags.h"
-#include "net/quic/core/quic_protocol.h"
+#include "net/quic/core/quic_packets.h"
#include "net/quic/core/quic_stream.h"
#include "net/quic/core/quic_utils.h"
+#include "net/quic/platform/api/quic_ptr_util.h"
+#include "net/quic/platform/api/quic_str_cat.h"
#include "net/quic/test_tools/quic_config_peer.h"
#include "net/quic/test_tools/quic_connection_peer.h"
#include "net/quic/test_tools/quic_flow_controller_peer.h"
-#include "net/quic/test_tools/quic_headers_stream_peer.h"
#include "net/quic/test_tools/quic_session_peer.h"
#include "net/quic/test_tools/quic_spdy_session_peer.h"
#include "net/quic/test_tools/quic_spdy_stream_peer.h"
@@ -69,6 +68,8 @@ class TestCryptoStream : public QuicCryptoStream {
session()->config()->ProcessPeerHello(msg, CLIENT, &error_details);
EXPECT_EQ(QUIC_NO_ERROR, error);
session()->OnConfigNegotiated();
+ session()->connection()->SetDefaultEncryptionLevel(
+ ENCRYPTION_FORWARD_SECURE);
session()->OnCryptoHandshakeEvent(QuicSession::HANDSHAKE_CONFIRMED);
}
@@ -117,8 +118,9 @@ class TestSession : public QuicSpdySession {
crypto_stream_(this),
writev_consumes_all_data_(false) {
Initialize();
- this->connection()->SetEncrypter(ENCRYPTION_FORWARD_SECURE,
- new NullEncrypter());
+ this->connection()->SetEncrypter(
+ ENCRYPTION_FORWARD_SECURE,
+ new NullEncrypter(connection->perspective()));
}
~TestSession() override { delete connection(); }
@@ -128,7 +130,7 @@ class TestSession : public QuicSpdySession {
TestStream* CreateOutgoingDynamicStream(SpdyPriority priority) override {
TestStream* stream = new TestStream(GetNextOutgoingStreamId(), this);
stream->SetPriority(priority);
- ActivateStream(base::WrapUnique(stream));
+ ActivateStream(QuicWrapUnique(stream));
return stream;
}
@@ -141,7 +143,7 @@ class TestSession : public QuicSpdySession {
return nullptr;
} else {
TestStream* stream = new TestStream(id, this);
- ActivateStream(base::WrapUnique(stream));
+ ActivateStream(QuicWrapUnique(stream));
return stream;
}
}
@@ -166,11 +168,12 @@ class TestSession : public QuicSpdySession {
QuicIOVector data,
QuicStreamOffset offset,
bool fin,
- QuicAckListenerInterface* ack_notifier_delegate) override {
+ QuicReferenceCountedPointer<QuicAckListenerInterface> ack_listener)
+ override {
QuicConsumedData consumed(data.total_length, fin);
if (!writev_consumes_all_data_) {
consumed = QuicSession::WritevData(stream, id, data, offset, fin,
- ack_notifier_delegate);
+ std::move(ack_listener));
}
stream->set_stream_bytes_written(stream->stream_bytes_written() +
consumed.bytes_consumed);
@@ -294,7 +297,8 @@ INSTANTIATE_TEST_CASE_P(Tests,
::testing::ValuesIn(AllSupportedVersions()));
TEST_P(QuicSessionTestServer, PeerAddress) {
- EXPECT_EQ(IPEndPoint(Loopback4(), kTestPort), session_.peer_address());
+ EXPECT_EQ(QuicSocketAddress(QuicIpAddress::Loopback4(), kTestPort),
+ session_.peer_address());
}
TEST_P(QuicSessionTestServer, IsCryptoHandshakeConfirmed) {
@@ -515,12 +519,17 @@ TEST_P(QuicSessionTestServer, TestBatchedWrites) {
TEST_P(QuicSessionTestServer, OnCanWriteBundlesStreams) {
// Encryption needs to be established before data can be sent.
CryptoHandshakeMessage msg;
+ MockPacketWriter* writer = static_cast<MockPacketWriter*>(
+ QuicConnectionPeer::GetWriter(session_.connection()));
+ if (FLAGS_quic_reloadable_flag_quic_send_max_header_list_size) {
+ EXPECT_CALL(*writer, WritePacket(_, _, _, _, _))
+ .WillOnce(Return(WriteResult(WRITE_STATUS_OK, 0)));
+ }
session_.GetCryptoStream()->OnHandshakeMessage(msg);
// Drive congestion control manually.
MockSendAlgorithm* send_algorithm = new StrictMock<MockSendAlgorithm>;
- QuicConnectionPeer::SetSendAlgorithm(session_.connection(), kDefaultPathId,
- send_algorithm);
+ QuicConnectionPeer::SetSendAlgorithm(session_.connection(), send_algorithm);
TestStream* stream2 = session_.CreateOutgoingDynamicStream(kDefaultPriority);
TestStream* stream4 = session_.CreateOutgoingDynamicStream(kDefaultPriority);
@@ -550,8 +559,6 @@ TEST_P(QuicSessionTestServer, OnCanWriteBundlesStreams) {
// Expect that we only send one packet, the writes from different streams
// should be bundled together.
- MockPacketWriter* writer = static_cast<MockPacketWriter*>(
- QuicConnectionPeer::GetWriter(session_.connection()));
EXPECT_CALL(*writer, WritePacket(_, _, _, _, _))
.WillOnce(Return(WriteResult(WRITE_STATUS_OK, 0)));
EXPECT_CALL(*send_algorithm, OnPacketSent(_, _, _, _, _));
@@ -566,8 +573,7 @@ TEST_P(QuicSessionTestServer, OnCanWriteCongestionControlBlocks) {
// Drive congestion control manually.
MockSendAlgorithm* send_algorithm = new StrictMock<MockSendAlgorithm>;
- QuicConnectionPeer::SetSendAlgorithm(session_.connection(), kDefaultPathId,
- send_algorithm);
+ QuicConnectionPeer::SetSendAlgorithm(session_.connection(), send_algorithm);
TestStream* stream2 = session_.CreateOutgoingDynamicStream(kDefaultPriority);
TestStream* stream4 = session_.CreateOutgoingDynamicStream(kDefaultPriority);
@@ -620,8 +626,7 @@ TEST_P(QuicSessionTestServer, OnCanWriteWriterBlocks) {
// Drive congestion control manually in order to ensure that
// application-limited signaling is handled correctly.
MockSendAlgorithm* send_algorithm = new StrictMock<MockSendAlgorithm>;
- QuicConnectionPeer::SetSendAlgorithm(session_.connection(), kDefaultPathId,
- send_algorithm);
+ QuicConnectionPeer::SetSendAlgorithm(session_.connection(), send_algorithm);
EXPECT_CALL(*send_algorithm, TimeUntilSend(_, _))
.WillRepeatedly(Return(QuicTime::Delta::Zero()));
@@ -726,8 +731,7 @@ TEST_P(QuicSessionTestServer, OnCanWriteLimitsNumWritesIfFlowControlBlocked) {
// Drive congestion control manually in order to ensure that
// application-limited signaling is handled correctly.
MockSendAlgorithm* send_algorithm = new StrictMock<MockSendAlgorithm>;
- QuicConnectionPeer::SetSendAlgorithm(session_.connection(), kDefaultPathId,
- send_algorithm);
+ QuicConnectionPeer::SetSendAlgorithm(session_.connection(), send_algorithm);
EXPECT_CALL(*send_algorithm, TimeUntilSend(_, _))
.WillRepeatedly(Return(QuicTime::Delta::Zero()));
@@ -912,15 +916,14 @@ TEST_P(QuicSessionTestServer,
while (!headers_stream->flow_controller()->IsBlocked() && stream_id < 2000) {
EXPECT_FALSE(session_.IsConnectionFlowControlBlocked());
EXPECT_FALSE(session_.IsStreamFlowControlBlocked());
- headers["header"] = base::Uint64ToString(base::RandUint64()) +
- base::Uint64ToString(base::RandUint64()) +
- base::Uint64ToString(base::RandUint64());
- headers_stream->WriteHeaders(stream_id, headers.Clone(), true, 0, nullptr);
+ headers["header"] = QuicStrCat("", base::RandUint64(), base::RandUint64(),
+ base::RandUint64());
+ session_.WriteHeaders(stream_id, headers.Clone(), true, 0, nullptr);
stream_id += 2;
}
// Write once more to ensure that the headers stream has buffered data. The
// random headers may have exactly filled the flow control window.
- headers_stream->WriteHeaders(stream_id, std::move(headers), true, 0, nullptr);
+ session_.WriteHeaders(stream_id, std::move(headers), true, 0, nullptr);
EXPECT_TRUE(headers_stream->HasBufferedData());
EXPECT_TRUE(headers_stream->flow_controller()->IsBlocked());
@@ -1089,6 +1092,18 @@ TEST_P(QuicSessionTestServer, InvalidSessionFlowControlWindowInHandshake) {
session_.OnConfigNegotiated();
}
+// Test negotiation of custom server initial flow control window.
+TEST_P(QuicSessionTestServer, CustomFlowControlWindow) {
+ FLAGS_quic_reloadable_flag_quic_large_ifw_options = true;
+ QuicTagVector copt;
+ copt.push_back(kIFW7);
+ QuicConfigPeer::SetReceivedConnectionOptions(session_.config(), copt);
+
+ session_.OnConfigNegotiated();
+ EXPECT_EQ(192 * 1024u, QuicFlowControllerPeer::ReceiveWindowSize(
+ session_.flow_controller()));
+}
+
TEST_P(QuicSessionTestServer, FlowControlWithInvalidFinalOffset) {
// Test that if we receive a stream RST with a highest byte offset that
// violates flow control, that we close the connection.
@@ -1283,9 +1298,9 @@ TEST_P(QuicSessionTestClient, EnableDHDTThroughConnectionOption) {
copt.push_back(kDHDT);
QuicConfigPeer::SetConnectionOptionsToSend(session_.config(), copt);
session_.OnConfigNegotiated();
- EXPECT_EQ(QuicHeadersStreamPeer::GetSpdyFramer(session_.headers_stream())
- .header_encoder_table_size(),
- 0UL);
+ EXPECT_EQ(
+ QuicSpdySessionPeer::GetSpdyFramer(&session_).header_encoder_table_size(),
+ 0UL);
}
TEST_P(QuicSessionTestClient, EnableFHOLThroughConfigOption) {
diff --git a/chromium/net/quic/core/quic_simple_buffer_allocator.h b/chromium/net/quic/core/quic_simple_buffer_allocator.h
index a980d03979f..03d8e0e5fe0 100644
--- a/chromium/net/quic/core/quic_simple_buffer_allocator.h
+++ b/chromium/net/quic/core/quic_simple_buffer_allocator.h
@@ -2,15 +2,15 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#ifndef NET_QUIC_SIMPLE_BUFFER_ALLOCATOR_H_
-#define NET_QUIC_SIMPLE_BUFFER_ALLOCATOR_H_
+#ifndef NET_QUIC_CORE_QUIC_SIMPLE_BUFFER_ALLOCATOR_H_
+#define NET_QUIC_CORE_QUIC_SIMPLE_BUFFER_ALLOCATOR_H_
-#include "net/base/net_export.h"
-#include "net/quic/core/quic_protocol.h"
+#include "net/quic/core/quic_buffer_allocator.h"
+#include "net/quic/platform/api/quic_export.h"
namespace net {
-class NET_EXPORT_PRIVATE SimpleBufferAllocator : public QuicBufferAllocator {
+class QUIC_EXPORT_PRIVATE SimpleBufferAllocator : public QuicBufferAllocator {
public:
char* New(size_t size) override;
char* New(size_t size, bool flag_enable) override;
@@ -19,4 +19,4 @@ class NET_EXPORT_PRIVATE SimpleBufferAllocator : public QuicBufferAllocator {
} // namespace net
-#endif // NET_QUIC_SIMPLE_BUFFER_ALLOCATOR_H_
+#endif // NET_QUIC_CORE_QUIC_SIMPLE_BUFFER_ALLOCATOR_H_
diff --git a/chromium/net/quic/core/quic_simple_buffer_allocator_test.cc b/chromium/net/quic/core/quic_simple_buffer_allocator_test.cc
index d999162378b..69cfad9d1fb 100644
--- a/chromium/net/quic/core/quic_simple_buffer_allocator_test.cc
+++ b/chromium/net/quic/core/quic_simple_buffer_allocator_test.cc
@@ -4,7 +4,7 @@
#include "net/quic/core/quic_simple_buffer_allocator.h"
-#include "net/quic/core/quic_protocol.h"
+#include "net/quic/core/quic_packets.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
diff --git a/chromium/net/quic/core/quic_socket_address_coder.cc b/chromium/net/quic/core/quic_socket_address_coder.cc
index 9d9a043e3b1..ae1dd6d673f 100644
--- a/chromium/net/quic/core/quic_socket_address_coder.cc
+++ b/chromium/net/quic/core/quic_socket_address_coder.cc
@@ -4,7 +4,6 @@
#include "net/quic/core/quic_socket_address_coder.h"
-#include "net/base/ip_address.h"
#include "net/base/sys_addrinfo.h"
using std::string;
@@ -22,7 +21,7 @@ const uint16_t kIPv6 = 10;
QuicSocketAddressCoder::QuicSocketAddressCoder() {}
-QuicSocketAddressCoder::QuicSocketAddressCoder(const IPEndPoint& address)
+QuicSocketAddressCoder::QuicSocketAddressCoder(const QuicSocketAddress& address)
: address_(address) {}
QuicSocketAddressCoder::~QuicSocketAddressCoder() {}
@@ -30,11 +29,11 @@ QuicSocketAddressCoder::~QuicSocketAddressCoder() {}
string QuicSocketAddressCoder::Encode() const {
string serialized;
uint16_t address_family;
- switch (address_.GetSockAddrFamily()) {
- case AF_INET:
+ switch (address_.host().address_family()) {
+ case IpAddressFamily::IP_V4:
address_family = kIPv4;
break;
- case AF_INET6:
+ case IpAddressFamily::IP_V6:
address_family = kIPv6;
break;
default:
@@ -42,7 +41,7 @@ string QuicSocketAddressCoder::Encode() const {
}
serialized.append(reinterpret_cast<const char*>(&address_family),
sizeof(address_family));
- serialized.append(IPAddressToPackedString(address_.address()));
+ serialized.append(address_.host().ToPackedString());
uint16_t port = address_.port();
serialized.append(reinterpret_cast<const char*>(&port), sizeof(port));
return serialized;
@@ -82,7 +81,9 @@ bool QuicSocketAddressCoder::Decode(const char* data, size_t length) {
}
memcpy(&port, data, length);
- address_ = IPEndPoint(IPAddress(ip), port);
+ QuicIpAddress ip_address;
+ ip_address.FromPackedString(reinterpret_cast<const char*>(&ip[0]), ip_length);
+ address_ = QuicSocketAddress(ip_address, port);
return true;
}
diff --git a/chromium/net/quic/core/quic_socket_address_coder.h b/chromium/net/quic/core/quic_socket_address_coder.h
index e6f8bf6a08b..1038c288d25 100644
--- a/chromium/net/quic/core/quic_socket_address_coder.h
+++ b/chromium/net/quic/core/quic_socket_address_coder.h
@@ -2,8 +2,8 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#ifndef NET_QUIC_QUIC_SOCKET_ADDRESS_CODER_H_
-#define NET_QUIC_QUIC_SOCKET_ADDRESS_CODER_H_
+#ifndef NET_QUIC_CORE_QUIC_SOCKET_ADDRESS_CODER_H_
+#define NET_QUIC_CORE_QUIC_SOCKET_ADDRESS_CODER_H_
#include <stddef.h>
#include <stdint.h>
@@ -11,36 +11,34 @@
#include <string>
#include "base/macros.h"
-#include "net/base/ip_endpoint.h"
-#include "net/base/net_export.h"
+#include "net/quic/platform/api/quic_export.h"
+#include "net/quic/platform/api/quic_socket_address.h"
namespace net {
-class IPAddress;
-
// Serializes and parses a socket address (IP address and port), to be used in
// the kCADR tag in the ServerHello handshake message and the Public Reset
// packet.
-class NET_EXPORT_PRIVATE QuicSocketAddressCoder {
+class QUIC_EXPORT_PRIVATE QuicSocketAddressCoder {
public:
QuicSocketAddressCoder();
- explicit QuicSocketAddressCoder(const IPEndPoint& address);
+ explicit QuicSocketAddressCoder(const QuicSocketAddress& address);
~QuicSocketAddressCoder();
std::string Encode() const;
bool Decode(const char* data, size_t length);
- const IPAddress& ip() const { return address_.address(); }
+ QuicIpAddress ip() const { return address_.host(); }
uint16_t port() const { return address_.port(); }
private:
- IPEndPoint address_;
+ QuicSocketAddress address_;
DISALLOW_COPY_AND_ASSIGN(QuicSocketAddressCoder);
};
} // namespace net
-#endif // NET_QUIC_QUIC_SOCKET_ADDRESS_CODER_H_
+#endif // NET_QUIC_CORE_QUIC_SOCKET_ADDRESS_CODER_H_
diff --git a/chromium/net/quic/core/quic_socket_address_coder_test.cc b/chromium/net/quic/core/quic_socket_address_coder_test.cc
index 7befddc22f9..703cc430e04 100644
--- a/chromium/net/quic/core/quic_socket_address_coder_test.cc
+++ b/chromium/net/quic/core/quic_socket_address_coder_test.cc
@@ -13,18 +13,18 @@ namespace net {
namespace test {
TEST(QuicSocketAddressCoderTest, EncodeIPv4) {
- IPAddress ip;
- ASSERT_TRUE(ip.AssignFromIPLiteral("4.31.198.44"));
- QuicSocketAddressCoder coder(IPEndPoint(ip, 0x1234));
+ QuicIpAddress ip;
+ ip.FromString("4.31.198.44");
+ QuicSocketAddressCoder coder(QuicSocketAddress(ip, 0x1234));
string serialized = coder.Encode();
string expected("\x02\x00\x04\x1f\xc6\x2c\x34\x12", 8);
EXPECT_EQ(expected, serialized);
}
TEST(QuicSocketAddressCoderTest, EncodeIPv6) {
- IPAddress ip;
- ASSERT_TRUE(ip.AssignFromIPLiteral("2001:700:300:1800::f"));
- QuicSocketAddressCoder coder(IPEndPoint(ip, 0x5678));
+ QuicIpAddress ip;
+ ip.FromString("2001:700:300:1800::f");
+ QuicSocketAddressCoder coder(QuicSocketAddress(ip, 0x5678));
string serialized = coder.Encode();
string expected(
"\x0a\x00"
@@ -39,9 +39,9 @@ TEST(QuicSocketAddressCoderTest, DecodeIPv4) {
string serialized("\x02\x00\x04\x1f\xc6\x2c\x34\x12", 8);
QuicSocketAddressCoder coder;
ASSERT_TRUE(coder.Decode(serialized.data(), serialized.length()));
- EXPECT_EQ(AF_INET, ConvertAddressFamily(GetAddressFamily(coder.ip())));
+ EXPECT_EQ(IpAddressFamily::IP_V4, coder.ip().address_family());
string expected_addr("\x04\x1f\xc6\x2c", 4);
- EXPECT_EQ(expected_addr, IPAddressToPackedString(coder.ip()));
+ EXPECT_EQ(expected_addr, coder.ip().ToPackedString());
EXPECT_EQ(0x1234, coder.port());
}
@@ -54,12 +54,12 @@ TEST(QuicSocketAddressCoderTest, DecodeIPv6) {
20);
QuicSocketAddressCoder coder;
ASSERT_TRUE(coder.Decode(serialized.data(), serialized.length()));
- EXPECT_EQ(AF_INET6, ConvertAddressFamily(GetAddressFamily(coder.ip())));
+ EXPECT_EQ(IpAddressFamily::IP_V6, coder.ip().address_family());
string expected_addr(
"\x20\x01\x07\x00\x03\x00\x18\x00"
"\x00\x00\x00\x00\x00\x00\x00\x0f",
16);
- EXPECT_EQ(expected_addr, IPAddressToPackedString(coder.ip()));
+ EXPECT_EQ(expected_addr, coder.ip().ToPackedString());
EXPECT_EQ(0x5678, coder.port());
}
@@ -110,9 +110,9 @@ TEST(QuicSocketAddressCoderTest, EncodeAndDecode) {
};
for (size_t i = 0; i < arraysize(test_case); i++) {
- IPAddress ip;
- ASSERT_TRUE(ip.AssignFromIPLiteral(test_case[i].ip_literal));
- QuicSocketAddressCoder encoder(IPEndPoint(ip, test_case[i].port));
+ QuicIpAddress ip;
+ ASSERT_TRUE(ip.FromString(test_case[i].ip_literal));
+ QuicSocketAddressCoder encoder(QuicSocketAddress(ip, test_case[i].port));
string serialized = encoder.Encode();
QuicSocketAddressCoder decoder;
diff --git a/chromium/net/quic/core/quic_spdy_session.cc b/chromium/net/quic/core/quic_spdy_session.cc
index b2bb42ffca2..279646b95e6 100644
--- a/chromium/net/quic/core/quic_spdy_session.cc
+++ b/chromium/net/quic/core/quic_spdy_session.cc
@@ -6,20 +6,326 @@
#include <utility>
-#include "net/quic/core/quic_bug_tracker.h"
+#include "net/quic/core/quic_flags.h"
#include "net/quic/core/quic_headers_stream.h"
+#include "net/quic/platform/api/quic_bug_tracker.h"
+#include "net/quic/platform/api/quic_logging.h"
+#include "net/quic/platform/api/quic_str_cat.h"
using base::StringPiece;
using std::string;
namespace net {
+namespace {
+
+class HeaderTableDebugVisitor
+ : public HpackHeaderTable::DebugVisitorInterface {
+ public:
+ HeaderTableDebugVisitor(const QuicClock* clock,
+ std::unique_ptr<QuicHpackDebugVisitor> visitor)
+ : clock_(clock), headers_stream_hpack_visitor_(std::move(visitor)) {}
+
+ int64_t OnNewEntry(const HpackEntry& entry) override {
+ QUIC_DVLOG(1) << entry.GetDebugString();
+ return (clock_->ApproximateNow() - QuicTime::Zero()).ToMicroseconds();
+ }
+
+ void OnUseEntry(const HpackEntry& entry) override {
+ const QuicTime::Delta elapsed(
+ clock_->ApproximateNow() -
+ QuicTime::Delta::FromMicroseconds(entry.time_added()) -
+ QuicTime::Zero());
+ QUIC_DVLOG(1) << entry.GetDebugString() << " " << elapsed.ToMilliseconds()
+ << " ms";
+ headers_stream_hpack_visitor_->OnUseEntry(elapsed);
+ }
+
+ private:
+ const QuicClock* clock_;
+ std::unique_ptr<QuicHpackDebugVisitor> headers_stream_hpack_visitor_;
+
+ DISALLOW_COPY_AND_ASSIGN(HeaderTableDebugVisitor);
+};
+
+// When forced HOL blocking is enabled, extra bytes in the form of
+// HTTP/2 DATA frame headers are inserted on the way down to the
+// session layer. |ForceAckListener| filters the |OnPacketAcked()|
+// notifications generated by the session layer to not count the extra
+// bytes. Otherwise, code that is using ack listener on streams might
+// consider it an error if more bytes are acked than were written to
+// the stream, it is the case with some internal stats gathering code.
+class ForceHolAckListener : public QuicAckListenerInterface {
+ public:
+ // |extra_bytes| should be initialized to the size of the HTTP/2
+ // DATA frame header inserted when forced HOL blocking is enabled.
+ ForceHolAckListener(
+ QuicReferenceCountedPointer<QuicAckListenerInterface> stream_ack_listener,
+ int extra_bytes)
+ : stream_ack_listener_(std::move(stream_ack_listener)),
+ extra_bytes_(extra_bytes) {
+ DCHECK_GE(extra_bytes, 0);
+ }
+
+ void OnPacketAcked(int acked_bytes, QuicTime::Delta ack_delay_time) override {
+ if (extra_bytes_ > 0) {
+ // Don't count the added HTTP/2 DATA frame header bytes
+ int delta = std::min(extra_bytes_, acked_bytes);
+ extra_bytes_ -= delta;
+ acked_bytes -= delta;
+ }
+ stream_ack_listener_->OnPacketAcked(acked_bytes, ack_delay_time);
+ }
+
+ void OnPacketRetransmitted(int retransmitted_bytes) override {
+ stream_ack_listener_->OnPacketRetransmitted(retransmitted_bytes);
+ }
+
+ protected:
+ ~ForceHolAckListener() override {}
+
+ private:
+ QuicReferenceCountedPointer<QuicAckListenerInterface> stream_ack_listener_;
+ int extra_bytes_;
+
+ DISALLOW_COPY_AND_ASSIGN(ForceHolAckListener);
+};
+
+} // namespace
+
+// A SpdyFramerVisitor that passes HEADERS frames to the QuicSpdyStream, and
+// closes the connection if any unexpected frames are received.
+class QuicSpdySession::SpdyFramerVisitor
+ : public SpdyFramerVisitorInterface,
+ public SpdyFramerDebugVisitorInterface {
+ public:
+ explicit SpdyFramerVisitor(QuicSpdySession* session) : session_(session) {}
+
+ SpdyHeadersHandlerInterface* OnHeaderFrameStart(
+ SpdyStreamId /* stream_id */) override {
+ return &header_list_;
+ }
+
+ void OnHeaderFrameEnd(SpdyStreamId /* stream_id */,
+ bool end_headers) override {
+ if (end_headers) {
+ if (session_->IsConnected()) {
+ session_->OnHeaderList(header_list_);
+ }
+ header_list_.Clear();
+ }
+ }
+
+ void OnStreamFrameData(SpdyStreamId stream_id,
+ const char* data,
+ size_t len) override {
+ if (session_->OnStreamFrameData(stream_id, data, len)) {
+ return;
+ }
+ CloseConnection("SPDY DATA frame received.");
+ }
+
+ void OnStreamEnd(SpdyStreamId stream_id) override {
+ // The framer invokes OnStreamEnd after processing a frame that had the fin
+ // bit set.
+ }
+
+ void OnStreamPadding(SpdyStreamId stream_id, size_t len) override {
+ CloseConnection("SPDY frame padding received.");
+ }
+
+ void OnError(SpdyFramer* framer) override {
+ CloseConnection(
+ QuicStrCat("SPDY framing error: ",
+ SpdyFramer::ErrorCodeToString(framer->error_code())));
+ }
+
+ void OnDataFrameHeader(SpdyStreamId stream_id,
+ size_t length,
+ bool fin) override {
+ if (session_->OnDataFrameHeader(stream_id, length, fin)) {
+ return;
+ }
+ CloseConnection("SPDY DATA frame received.");
+ }
+
+ void OnRstStream(SpdyStreamId stream_id,
+ SpdyRstStreamStatus status) override {
+ CloseConnection("SPDY RST_STREAM frame received.");
+ }
+
+ void OnSetting(SpdySettingsIds id, uint32_t value) override {
+ if (!FLAGS_quic_reloadable_flag_quic_respect_http2_settings_frame) {
+ CloseConnection("SPDY SETTINGS frame received.");
+ return;
+ }
+ switch (id) {
+ case SETTINGS_HEADER_TABLE_SIZE:
+ session_->UpdateHeaderEncoderTableSize(value);
+ break;
+ case SETTINGS_ENABLE_PUSH:
+ if (FLAGS_quic_reloadable_flag_quic_enable_server_push_by_default &&
+ session_->perspective() == Perspective::IS_SERVER) {
+ // See rfc7540, Section 6.5.2.
+ if (value > 1) {
+ CloseConnection(
+ QuicStrCat("Invalid value for SETTINGS_ENABLE_PUSH: ", value));
+ return;
+ }
+ session_->UpdateEnableServerPush(value > 0);
+ break;
+ } else {
+ CloseConnection(
+ QuicStrCat("Unsupported field of HTTP/2 SETTINGS frame: ", id));
+ }
+ break;
+ // TODO(fayang): Need to support SETTINGS_MAX_HEADER_LIST_SIZE when
+ // clients are actually sending it.
+ case SETTINGS_MAX_HEADER_LIST_SIZE:
+ if (FLAGS_quic_reloadable_flag_quic_send_max_header_list_size) {
+ break;
+ }
+ default:
+ CloseConnection(
+ QuicStrCat("Unsupported field of HTTP/2 SETTINGS frame: ", id));
+ }
+ }
+
+ void OnSettingsAck() override {
+ if (!FLAGS_quic_reloadable_flag_quic_respect_http2_settings_frame) {
+ CloseConnection("SPDY SETTINGS frame received.");
+ }
+ }
+
+ void OnSettingsEnd() override {
+ if (!FLAGS_quic_reloadable_flag_quic_respect_http2_settings_frame) {
+ CloseConnection("SPDY SETTINGS frame received.");
+ }
+ }
+
+ void OnPing(SpdyPingId unique_id, bool is_ack) override {
+ CloseConnection("SPDY PING frame received.");
+ }
+
+ void OnGoAway(SpdyStreamId last_accepted_stream_id,
+ SpdyGoAwayStatus status) override {
+ CloseConnection("SPDY GOAWAY frame received.");
+ }
+
+ void OnHeaders(SpdyStreamId stream_id,
+ bool has_priority,
+ int weight,
+ SpdyStreamId /*parent_stream_id*/,
+ bool /*exclusive*/,
+ bool fin,
+ bool end) override {
+ if (!session_->IsConnected()) {
+ return;
+ }
+
+ // TODO(mpw): avoid down-conversion and plumb SpdyStreamPrecedence through
+ // QuicHeadersStream.
+ SpdyPriority priority =
+ has_priority ? Http2WeightToSpdy3Priority(weight) : 0;
+ session_->OnHeaders(stream_id, has_priority, priority, fin);
+ }
+
+ void OnWindowUpdate(SpdyStreamId stream_id, int delta_window_size) override {
+ CloseConnection("SPDY WINDOW_UPDATE frame received.");
+ }
+
+ void OnPushPromise(SpdyStreamId stream_id,
+ SpdyStreamId promised_stream_id,
+ bool end) override {
+ if (!session_->supports_push_promise()) {
+ CloseConnection("PUSH_PROMISE not supported.");
+ return;
+ }
+ if (!session_->IsConnected()) {
+ return;
+ }
+ session_->OnPushPromise(stream_id, promised_stream_id, end);
+ }
+
+ void OnContinuation(SpdyStreamId stream_id, bool end) override {}
+
+ void OnPriority(SpdyStreamId stream_id,
+ SpdyStreamId parent_id,
+ int weight,
+ bool exclusive) override {
+ CloseConnection("SPDY PRIORITY frame received.");
+ }
+
+ bool OnUnknownFrame(SpdyStreamId stream_id, int frame_type) override {
+ CloseConnection("Unknown frame type received.");
+ return false;
+ }
+
+ // SpdyFramerDebugVisitorInterface implementation
+ void OnSendCompressedFrame(SpdyStreamId stream_id,
+ SpdyFrameType type,
+ size_t payload_len,
+ size_t frame_len) override {
+ if (payload_len == 0) {
+ QUIC_BUG << "Zero payload length.";
+ return;
+ }
+ int compression_pct = 100 - (100 * frame_len) / payload_len;
+ QUIC_DVLOG(1) << "Net.QuicHpackCompressionPercentage: " << compression_pct;
+ }
+
+ void OnReceiveCompressedFrame(SpdyStreamId stream_id,
+ SpdyFrameType type,
+ size_t frame_len) override {
+ if (session_->IsConnected()) {
+ session_->OnCompressedFrameSize(frame_len);
+ }
+ }
+
+ void set_max_uncompressed_header_bytes(
+ size_t set_max_uncompressed_header_bytes) {
+ header_list_.set_max_uncompressed_header_bytes(
+ set_max_uncompressed_header_bytes);
+ }
+
+ private:
+ void CloseConnection(const string& details) {
+ if (session_->IsConnected()) {
+ session_->CloseConnectionWithDetails(QUIC_INVALID_HEADERS_STREAM_DATA,
+ details);
+ }
+ }
+
+ private:
+ QuicSpdySession* session_;
+ QuicHeaderList header_list_;
+
+ DISALLOW_COPY_AND_ASSIGN(SpdyFramerVisitor);
+};
+
+QuicHpackDebugVisitor::QuicHpackDebugVisitor() {}
+
+QuicHpackDebugVisitor::~QuicHpackDebugVisitor() {}
+
QuicSpdySession::QuicSpdySession(QuicConnection* connection,
QuicSession::Visitor* visitor,
const QuicConfig& config)
: QuicSession(connection, visitor, config),
force_hol_blocking_(false),
- server_push_enabled_(false) {}
+ server_push_enabled_(false),
+ stream_id_(kInvalidStreamId),
+ promised_stream_id_(kInvalidStreamId),
+ fin_(false),
+ frame_len_(0),
+ uncompressed_frame_len_(0),
+ supports_push_promise_(perspective() == Perspective::IS_CLIENT),
+ cur_max_timestamp_(QuicTime::Zero()),
+ prev_max_timestamp_(QuicTime::Zero()),
+ spdy_framer_(SpdyFramer::ENABLE_COMPRESSION),
+ spdy_framer_visitor_(new SpdyFramerVisitor(this)) {
+ spdy_framer_.set_visitor(spdy_framer_visitor_.get());
+ spdy_framer_.set_debug_visitor(spdy_framer_visitor_.get());
+}
QuicSpdySession::~QuicSpdySession() {
// Set the streams' session pointers in closed and dynamic stream lists
@@ -69,14 +375,147 @@ void QuicSpdySession::OnStreamHeaderList(QuicStreamId stream_id,
stream->OnStreamHeaderList(fin, frame_len, header_list);
}
+size_t QuicSpdySession::ProcessHeaderData(const struct iovec& iov,
+ QuicTime timestamp) {
+ DCHECK(timestamp.IsInitialized());
+ UpdateCurMaxTimeStamp(timestamp);
+ return spdy_framer_.ProcessInput(static_cast<char*>(iov.iov_base),
+ iov.iov_len);
+}
+
size_t QuicSpdySession::WriteHeaders(
QuicStreamId id,
SpdyHeaderBlock headers,
bool fin,
SpdyPriority priority,
- QuicAckListenerInterface* ack_notifier_delegate) {
- return headers_stream_->WriteHeaders(id, std::move(headers), fin, priority,
- ack_notifier_delegate);
+ QuicReferenceCountedPointer<QuicAckListenerInterface>
+ ack_notifier_delegate) {
+ return WriteHeadersImpl(id, std::move(headers), fin, priority,
+ std::move(ack_notifier_delegate));
+}
+
+size_t QuicSpdySession::WriteHeadersImpl(
+ QuicStreamId id,
+ SpdyHeaderBlock headers,
+ bool fin,
+ SpdyPriority priority,
+ QuicReferenceCountedPointer<QuicAckListenerInterface>
+ ack_notifier_delegate) {
+ SpdyHeadersIR headers_frame(id, std::move(headers));
+ headers_frame.set_fin(fin);
+ if (perspective() == Perspective::IS_CLIENT) {
+ headers_frame.set_has_priority(true);
+ headers_frame.set_weight(Spdy3PriorityToHttp2Weight(priority));
+ }
+ SpdySerializedFrame frame(spdy_framer_.SerializeFrame(headers_frame));
+ headers_stream_->WriteOrBufferData(StringPiece(frame.data(), frame.size()),
+ false, std::move(ack_notifier_delegate));
+ return frame.size();
+}
+
+size_t QuicSpdySession::WritePushPromise(QuicStreamId original_stream_id,
+ QuicStreamId promised_stream_id,
+ SpdyHeaderBlock headers) {
+ if (perspective() == Perspective::IS_CLIENT) {
+ QUIC_BUG << "Client shouldn't send PUSH_PROMISE";
+ return 0;
+ }
+
+ SpdyPushPromiseIR push_promise(original_stream_id, promised_stream_id,
+ std::move(headers));
+ // PUSH_PROMISE must not be the last frame sent out, at least followed by
+ // response headers.
+ push_promise.set_fin(false);
+
+ SpdySerializedFrame frame(spdy_framer_.SerializeFrame(push_promise));
+ headers_stream_->WriteOrBufferData(StringPiece(frame.data(), frame.size()),
+ false, nullptr);
+ return frame.size();
+}
+
+void QuicSpdySession::WriteDataFrame(
+ QuicStreamId id,
+ StringPiece data,
+ bool fin,
+ QuicReferenceCountedPointer<QuicAckListenerInterface> ack_listener) {
+ SpdyDataIR spdy_data(id, data);
+ spdy_data.set_fin(fin);
+ SpdySerializedFrame frame(spdy_framer_.SerializeFrame(spdy_data));
+ QuicReferenceCountedPointer<ForceHolAckListener> force_hol_ack_listener;
+ if (ack_listener != nullptr) {
+ force_hol_ack_listener = new ForceHolAckListener(
+ std::move(ack_listener), frame.size() - data.length());
+ }
+ // Use buffered writes so that coherence of framing is preserved
+ // between streams.
+ headers_stream_->WriteOrBufferData(StringPiece(frame.data(), frame.size()),
+ false, std::move(force_hol_ack_listener));
+}
+
+QuicConsumedData QuicSpdySession::WritevStreamData(
+ QuicStreamId id,
+ QuicIOVector iov,
+ QuicStreamOffset offset,
+ bool fin,
+ QuicReferenceCountedPointer<QuicAckListenerInterface> ack_listener) {
+ const size_t max_len =
+ kSpdyInitialFrameSizeLimit - kDataFrameMinimumSize;
+
+ QuicConsumedData result(0, false);
+ size_t total_length = iov.total_length;
+
+ if (total_length == 0 && fin) {
+ WriteDataFrame(id, StringPiece(), true, std::move(ack_listener));
+ result.fin_consumed = true;
+ return result;
+ }
+
+ // Encapsulate the data into HTTP/2 DATA frames. The outer loop
+ // handles each element of the source iov, the inner loop handles
+ // the possibility of fragmenting each of those into multiple DATA
+ // frames, as the DATA frames have a max size of 16KB.
+ for (int i = 0; i < iov.iov_count; i++) {
+ size_t src_iov_offset = 0;
+ const struct iovec* src_iov = &iov.iov[i];
+ do {
+ if (headers_stream_->queued_data_bytes() > 0) {
+ // Limit the amount of buffering to the minimum needed to
+ // preserve framing.
+ return result;
+ }
+ size_t len = std::min(
+ std::min(src_iov->iov_len - src_iov_offset, max_len), total_length);
+ char* data = static_cast<char*>(src_iov->iov_base) + src_iov_offset;
+ src_iov_offset += len;
+ offset += len;
+ // fin handling, only set it for the final HTTP/2 DATA frame.
+ bool last_iov = i == iov.iov_count - 1;
+ bool last_fragment_within_iov = src_iov_offset >= src_iov->iov_len;
+ bool frame_fin = (last_iov && last_fragment_within_iov) ? fin : false;
+ WriteDataFrame(id, StringPiece(data, len), frame_fin, ack_listener);
+ result.bytes_consumed += len;
+ if (frame_fin) {
+ result.fin_consumed = true;
+ }
+ DCHECK_GE(total_length, len);
+ total_length -= len;
+ if (total_length <= 0) {
+ return result;
+ }
+ } while (src_iov_offset < src_iov->iov_len);
+ }
+
+ return result;
+}
+
+size_t QuicSpdySession::SendMaxHeaderListSize(size_t value) {
+ SpdySettingsIR settings_frame;
+ settings_frame.AddSetting(SETTINGS_MAX_HEADER_LIST_SIZE, value);
+
+ SpdySerializedFrame frame(spdy_framer_.SerializeFrame(settings_frame));
+ headers_stream_->WriteOrBufferData(StringPiece(frame.data(), frame.size()),
+ false, nullptr);
+ return frame.size();
}
void QuicSpdySession::OnHeadersHeadOfLineBlocking(QuicTime::Delta delta) {
@@ -102,6 +541,14 @@ QuicSpdyStream* QuicSpdySession::GetSpdyDataStream(
return static_cast<QuicSpdyStream*>(GetOrCreateDynamicStream(stream_id));
}
+void QuicSpdySession::OnCryptoHandshakeEvent(CryptoHandshakeEvent event) {
+ QuicSession::OnCryptoHandshakeEvent(event);
+ if (FLAGS_quic_reloadable_flag_quic_send_max_header_list_size &&
+ event == HANDSHAKE_CONFIRMED && config()->SupportMaxHeaderListSize()) {
+ SendMaxHeaderListSize(kDefaultMaxUncompressedHeaderSize);
+ }
+}
+
void QuicSpdySession::OnPromiseHeaderList(QuicStreamId stream_id,
QuicStreamId promised_stream_id,
size_t frame_len,
@@ -115,34 +562,26 @@ void QuicSpdySession::OnPromiseHeaderList(QuicStreamId stream_id,
void QuicSpdySession::OnConfigNegotiated() {
QuicSession::OnConfigNegotiated();
if (config()->HasClientSentConnectionOption(kDHDT, perspective())) {
- headers_stream_->DisableHpackDynamicTable();
+ DisableHpackDynamicTable();
}
const QuicVersion version = connection()->version();
- if (FLAGS_quic_enable_force_hol_blocking && version > QUIC_VERSION_35 &&
- config()->ForceHolBlocking(perspective())) {
+ if (FLAGS_quic_reloadable_flag_quic_enable_force_hol_blocking &&
+ version > QUIC_VERSION_35 && config()->ForceHolBlocking(perspective())) {
force_hol_blocking_ = true;
- if (!FLAGS_quic_bugfix_fhol_writev_fin_only_v2) {
- // Autotuning makes sure that the headers stream flow control does
- // not get in the way, and normal stream and connection level flow
- // control are active anyway. This is really only for the client
- // side (and mainly there just in tests and toys), where
- // autotuning and/or large buffers are not enabled by default.
- headers_stream_->flow_controller()->set_auto_tune_receive_window(true);
- } else {
- // Since all streams are tunneled through the headers stream, it
- // is important that headers stream never flow control blocks.
- // Otherwise, busy-loop behaviour can ensue where data streams
- // data try repeatedly to write data not realizing that the
- // tunnel through the headers stream is blocked.
- headers_stream_->flow_controller()->UpdateReceiveWindowSize(
- kStreamReceiveWindowLimit);
- headers_stream_->flow_controller()->UpdateSendWindowOffset(
- kStreamReceiveWindowLimit);
- }
+ // Since all streams are tunneled through the headers stream, it
+ // is important that headers stream never flow control blocks.
+ // Otherwise, busy-loop behaviour can ensue where data streams
+ // data try repeatedly to write data not realizing that the
+ // tunnel through the headers stream is blocked.
+ headers_stream_->flow_controller()->UpdateReceiveWindowSize(
+ kStreamReceiveWindowLimit);
+ headers_stream_->flow_controller()->UpdateSendWindowOffset(
+ kStreamReceiveWindowLimit);
}
if (version > QUIC_VERSION_34) {
- server_push_enabled_ = FLAGS_quic_enable_server_push_by_default;
+ server_push_enabled_ =
+ FLAGS_quic_reloadable_flag_quic_enable_server_push_by_default;
}
}
@@ -157,8 +596,8 @@ void QuicSpdySession::OnStreamFrameData(QuicStreamId stream_id,
const QuicStreamOffset offset =
stream->flow_controller()->highest_received_byte_offset();
const QuicStreamFrame frame(stream_id, fin, offset, StringPiece(data, len));
- DVLOG(1) << "De-encapsulating DATA frame for stream " << stream_id
- << " offset " << offset << " len " << len << " fin " << fin;
+ QUIC_DVLOG(1) << "De-encapsulating DATA frame for stream " << stream_id
+ << " offset " << offset << " len " << len << " fin " << fin;
OnStreamFrame(frame);
}
@@ -166,4 +605,143 @@ bool QuicSpdySession::ShouldReleaseHeadersStreamSequencerBuffer() {
return false;
}
+void QuicSpdySession::OnHeaders(SpdyStreamId stream_id,
+ bool has_priority,
+ SpdyPriority priority,
+ bool fin) {
+ if (has_priority) {
+ if (perspective() == Perspective::IS_CLIENT) {
+ CloseConnectionWithDetails(QUIC_INVALID_HEADERS_STREAM_DATA,
+ "Server must not send priorities.");
+ return;
+ }
+ OnStreamHeadersPriority(stream_id, priority);
+ } else {
+ if (perspective() == Perspective::IS_SERVER) {
+ CloseConnectionWithDetails(QUIC_INVALID_HEADERS_STREAM_DATA,
+ "Client must send priorities.");
+ return;
+ }
+ }
+ DCHECK_EQ(kInvalidStreamId, stream_id_);
+ DCHECK_EQ(kInvalidStreamId, promised_stream_id_);
+ stream_id_ = stream_id;
+ fin_ = fin;
+}
+
+void QuicSpdySession::OnPushPromise(SpdyStreamId stream_id,
+ SpdyStreamId promised_stream_id,
+ bool end) {
+ DCHECK_EQ(kInvalidStreamId, stream_id_);
+ DCHECK_EQ(kInvalidStreamId, promised_stream_id_);
+ stream_id_ = stream_id;
+ promised_stream_id_ = promised_stream_id;
+}
+
+void QuicSpdySession::OnHeaderList(const QuicHeaderList& header_list) {
+ QUIC_DVLOG(1) << "Received header list for stream " << stream_id_ << ": "
+ << header_list.DebugString();
+ if (prev_max_timestamp_ > cur_max_timestamp_) {
+ // prev_max_timestamp_ > cur_max_timestamp_ implies that
+ // headers from lower numbered streams actually came off the
+ // wire after headers for the current stream, hence there was
+ // HOL blocking.
+ QuicTime::Delta delta = prev_max_timestamp_ - cur_max_timestamp_;
+ QUIC_DLOG(INFO) << "stream " << stream_id_
+ << ": Net.QuicSession.HeadersHOLBlockedTime "
+ << delta.ToMilliseconds();
+ OnHeadersHeadOfLineBlocking(delta);
+ }
+ prev_max_timestamp_ = std::max(prev_max_timestamp_, cur_max_timestamp_);
+ cur_max_timestamp_ = QuicTime::Zero();
+ if (promised_stream_id_ == kInvalidStreamId) {
+ OnStreamHeaderList(stream_id_, fin_, frame_len_, header_list);
+ } else {
+ OnPromiseHeaderList(stream_id_, promised_stream_id_, frame_len_,
+ header_list);
+ }
+ // Reset state for the next frame.
+ promised_stream_id_ = kInvalidStreamId;
+ stream_id_ = kInvalidStreamId;
+ fin_ = false;
+ frame_len_ = 0;
+ uncompressed_frame_len_ = 0;
+}
+
+void QuicSpdySession::OnCompressedFrameSize(size_t frame_len) {
+ frame_len_ += frame_len;
+}
+
+void QuicSpdySession::DisableHpackDynamicTable() {
+ spdy_framer_.UpdateHeaderEncoderTableSize(0);
+}
+
+void QuicSpdySession::SetHpackEncoderDebugVisitor(
+ std::unique_ptr<QuicHpackDebugVisitor> visitor) {
+ spdy_framer_.SetEncoderHeaderTableDebugVisitor(
+ std::unique_ptr<HeaderTableDebugVisitor>(new HeaderTableDebugVisitor(
+ connection()->helper()->GetClock(), std::move(visitor))));
+}
+
+void QuicSpdySession::SetHpackDecoderDebugVisitor(
+ std::unique_ptr<QuicHpackDebugVisitor> visitor) {
+ spdy_framer_.SetDecoderHeaderTableDebugVisitor(
+ std::unique_ptr<HeaderTableDebugVisitor>(new HeaderTableDebugVisitor(
+ connection()->helper()->GetClock(), std::move(visitor))));
+}
+
+void QuicSpdySession::UpdateHeaderEncoderTableSize(uint32_t value) {
+ spdy_framer_.UpdateHeaderEncoderTableSize(value);
+}
+
+void QuicSpdySession::UpdateEnableServerPush(bool value) {
+ set_server_push_enabled(value);
+}
+
+bool QuicSpdySession::OnDataFrameHeader(QuicStreamId stream_id,
+ size_t length,
+ bool fin) {
+ if (!force_hol_blocking()) {
+ return false;
+ }
+ if (!IsConnected()) {
+ return true;
+ }
+ QUIC_DVLOG(1) << "DATA frame header for stream " << stream_id << " length "
+ << length << " fin " << fin;
+ fin_ = fin;
+ frame_len_ = length;
+ if (fin && length == 0) {
+ OnStreamFrameData(stream_id, "", 0);
+ }
+ return true;
+}
+
+bool QuicSpdySession::OnStreamFrameData(QuicStreamId stream_id,
+ const char* data,
+ size_t len) {
+ if (!force_hol_blocking()) {
+ return false;
+ }
+ if (!IsConnected()) {
+ return true;
+ }
+ frame_len_ -= len;
+ // Ignore fin_ while there is more data coming, if frame_len_ > 0.
+ OnStreamFrameData(stream_id, data, len, frame_len_ > 0 ? false : fin_);
+ return true;
+}
+
+void QuicSpdySession::set_max_uncompressed_header_bytes(
+ size_t set_max_uncompressed_header_bytes) {
+ spdy_framer_visitor_->set_max_uncompressed_header_bytes(
+ set_max_uncompressed_header_bytes);
+}
+
+void QuicSpdySession::CloseConnectionWithDetails(QuicErrorCode error,
+ const string& details) {
+ connection()->CloseConnection(
+ error, details, ConnectionCloseBehavior::SEND_CONNECTION_CLOSE_PACKET);
+}
+
} // namespace net
diff --git a/chromium/net/quic/core/quic_spdy_session.h b/chromium/net/quic/core/quic_spdy_session.h
index 670142ebffa..d0066b59ebe 100644
--- a/chromium/net/quic/core/quic_spdy_session.h
+++ b/chromium/net/quic/core/quic_spdy_session.h
@@ -2,19 +2,19 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#ifndef NET_QUIC_QUIC_SPDY_SESSION_H_
-#define NET_QUIC_QUIC_SPDY_SESSION_H_
+#ifndef NET_QUIC_CORE_QUIC_SPDY_SESSION_H_
+#define NET_QUIC_CORE_QUIC_SPDY_SESSION_H_
#include <stddef.h>
#include <memory>
#include "base/macros.h"
-#include "net/base/net_export.h"
#include "net/quic/core/quic_header_list.h"
#include "net/quic/core/quic_headers_stream.h"
#include "net/quic/core/quic_session.h"
#include "net/quic/core/quic_spdy_stream.h"
+#include "net/quic/platform/api/quic_export.h"
namespace net {
@@ -22,8 +22,28 @@ namespace test {
class QuicSpdySessionPeer;
} // namespace test
+// QuicHpackDebugVisitor gathers data used for understanding HPACK HoL
+// dynamics. Specifically, it is to help predict the compression
+// penalty of avoiding HoL by chagning how the dynamic table is used.
+// In chromium, the concrete instance populates an UMA
+// histogram with the data.
+class QUIC_EXPORT_PRIVATE QuicHpackDebugVisitor {
+ public:
+ QuicHpackDebugVisitor();
+
+ virtual ~QuicHpackDebugVisitor();
+
+ // For each HPACK indexed representation processed, |elapsed| is
+ // the time since the corresponding entry was added to the dynamic
+ // table.
+ virtual void OnUseEntry(QuicTime::Delta elapsed) = 0;
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(QuicHpackDebugVisitor);
+};
+
// A QUIC session with a headers stream.
-class NET_EXPORT_PRIVATE QuicSpdySession : public QuicSession {
+class QUIC_EXPORT_PRIVATE QuicSpdySession : public QuicSession {
public:
// Does not take ownership of |connection| or |visitor|.
QuicSpdySession(QuicConnection* connection,
@@ -56,15 +76,38 @@ class NET_EXPORT_PRIVATE QuicSpdySession : public QuicSession {
size_t frame_len,
const QuicHeaderList& header_list);
+ // Sends contents of |iov| to spdy_framer_, returns number of bytes processd.
+ size_t ProcessHeaderData(const struct iovec& iov, QuicTime timestamp);
+
// Writes |headers| for the stream |id| to the dedicated headers stream.
// If |fin| is true, then no more data will be sent for the stream |id|.
// If provided, |ack_notifier_delegate| will be registered to be notified when
// we have seen ACKs for all packets resulting from this call.
- virtual size_t WriteHeaders(QuicStreamId id,
- SpdyHeaderBlock headers,
- bool fin,
- SpdyPriority priority,
- QuicAckListenerInterface* ack_notifier_delegate);
+ virtual size_t WriteHeaders(
+ QuicStreamId id,
+ SpdyHeaderBlock headers,
+ bool fin,
+ SpdyPriority priority,
+ QuicReferenceCountedPointer<QuicAckListenerInterface> ack_listener);
+
+ // Write |headers| for |promised_stream_id| on |original_stream_id| in a
+ // PUSH_PROMISE frame to peer.
+ // Return the size, in bytes, of the resulting PUSH_PROMISE frame.
+ virtual size_t WritePushPromise(QuicStreamId original_stream_id,
+ QuicStreamId promised_stream_id,
+ SpdyHeaderBlock headers);
+
+ // For forcing HOL blocking. This encapsulates data from other
+ // streams into HTTP/2 data frames on the headers stream.
+ QuicConsumedData WritevStreamData(
+ QuicStreamId id,
+ QuicIOVector iov,
+ QuicStreamOffset offset,
+ bool fin,
+ QuicReferenceCountedPointer<QuicAckListenerInterface> ack_listener);
+
+ // Sends SETTINGS_MAX_HEADER_LIST_SIZE SETTINGS frame.
+ size_t SendMaxHeaderListSize(size_t value);
QuicHeadersStream* headers_stream() { return headers_stream_.get(); }
@@ -93,6 +136,10 @@ class NET_EXPORT_PRIVATE QuicSpdySession : public QuicSession {
bool server_push_enabled() const { return server_push_enabled_; }
+ void UpdateCurMaxTimeStamp(QuicTime timestamp) {
+ cur_max_timestamp_ = std::max(timestamp, cur_max_timestamp_);
+ }
+
// Called by |QuicHeadersStream::UpdateEnableServerPush()| with
// value from SETTINGS_ENABLE_PUSH.
void set_server_push_enabled(bool enable) { server_push_enabled_ = enable; }
@@ -101,6 +148,17 @@ class NET_EXPORT_PRIVATE QuicSpdySession : public QuicSession {
// aggressively.
virtual bool ShouldReleaseHeadersStreamSequencerBuffer();
+ SpdyFramer* spdy_framer() { return &spdy_framer_; }
+
+ void CloseConnectionWithDetails(QuicErrorCode error,
+ const std::string& details);
+
+ // Sets how much encoded data the hpack decoder of spdy_framer_ is willing to
+ // buffer.
+ void set_max_decode_buffer_size_bytes(size_t max_decode_buffer_size_bytes) {
+ spdy_framer_.set_max_decode_buffer_size_bytes(max_decode_buffer_size_bytes);
+ }
+
protected:
// Override CreateIncomingDynamicStream() and CreateOutgoingDynamicStream()
// with QuicSpdyStream return type to make sure that all data streams are
@@ -117,9 +175,81 @@ class NET_EXPORT_PRIVATE QuicSpdySession : public QuicSession {
// If an outgoing stream can be created, return true.
virtual bool ShouldCreateOutgoingDynamicStream() = 0;
+ void OnCryptoHandshakeEvent(CryptoHandshakeEvent event) override;
+
+ bool supports_push_promise() { return supports_push_promise_; }
+
+ // Experimental: force HPACK to use static table and huffman coding
+ // only. Part of exploring improvements related to headers stream
+ // induced HOL blocking in QUIC.
+ void DisableHpackDynamicTable();
+
+ // Optional, enables instrumentation related to go/quic-hpack.
+ void SetHpackEncoderDebugVisitor(
+ std::unique_ptr<QuicHpackDebugVisitor> visitor);
+ void SetHpackDecoderDebugVisitor(
+ std::unique_ptr<QuicHpackDebugVisitor> visitor);
+
+ // Sets the maximum size of the header compression table spdy_framer_ is
+ // willing to use to decode header blocks.
+ void UpdateHeaderEncoderTableSize(uint32_t value);
+
+ // Called when SETTINGS_ENABLE_PUSH is received, only supported on
+ // server side.
+ void UpdateEnableServerPush(bool value);
+
+ void set_max_uncompressed_header_bytes(
+ size_t set_max_uncompressed_header_bytes);
+
+ bool IsConnected() { return connection()->connected(); }
+
private:
friend class test::QuicSpdySessionPeer;
+ class SpdyFramerVisitor;
+
+ // The following methods are called by the SimpleVisitor.
+
+ // Called when a HEADERS frame has been received.
+ void OnHeaders(SpdyStreamId stream_id,
+ bool has_priority,
+ SpdyPriority priority,
+ bool fin);
+
+ // Called when a PUSH_PROMISE frame has been received.
+ void OnPushPromise(SpdyStreamId stream_id,
+ SpdyStreamId promised_stream_id,
+ bool end);
+
+ // Called when the complete list of headers is available.
+ void OnHeaderList(const QuicHeaderList& header_list);
+
+ // Called when the size of the compressed frame payload is available.
+ void OnCompressedFrameSize(size_t frame_len);
+
+ // For force HOL blocking, where stream frames from all streams are
+ // plumbed through headers stream as HTTP/2 data frames.
+ // The following two return false if force_hol_blocking_ is false.
+ bool OnDataFrameHeader(QuicStreamId stream_id, size_t length, bool fin);
+ bool OnStreamFrameData(QuicStreamId stream_id, const char* data, size_t len);
+
+ // Helper for |WritevStreamData()|.
+ void WriteDataFrame(
+ QuicStreamId stream_id,
+ base::StringPiece data,
+ bool fin,
+ QuicReferenceCountedPointer<QuicAckListenerInterface> ack_listener);
+
+ // This was formerly QuicHeadersStream::WriteHeaders. Needs to be
+ // separate from QuicSpdySession::WriteHeaders because tests call
+ // this but mock the latter.
+ size_t WriteHeadersImpl(
+ QuicStreamId id,
+ SpdyHeaderBlock headers,
+ bool fin,
+ SpdyPriority priority,
+ QuicReferenceCountedPointer<QuicAckListenerInterface> ack_listener);
+
std::unique_ptr<QuicHeadersStream> headers_stream_;
// If set, redirect all data through the headers stream in order to
@@ -131,9 +261,30 @@ class NET_EXPORT_PRIVATE QuicSpdySession : public QuicSession {
// headers will be pushed.
bool server_push_enabled_;
+ // Data about the stream whose headers are being processed.
+ QuicStreamId stream_id_;
+ QuicStreamId promised_stream_id_;
+ bool fin_;
+ size_t frame_len_;
+ size_t uncompressed_frame_len_;
+
+ bool supports_push_promise_;
+
+ // Timestamps used to measure HOL blocking, these are recorded by
+ // the sequencer approximate to the time of arrival off the wire.
+ // |cur_max_timestamp_| tracks the most recent arrival time of
+ // frames for current (at the headers stream level) processed
+ // stream's headers, and |prev_max_timestamp_| tracks the most
+ // recent arrival time of lower numbered streams.
+ QuicTime cur_max_timestamp_;
+ QuicTime prev_max_timestamp_;
+
+ SpdyFramer spdy_framer_;
+ std::unique_ptr<SpdyFramerVisitor> spdy_framer_visitor_;
+
DISALLOW_COPY_AND_ASSIGN(QuicSpdySession);
};
} // namespace net
-#endif // NET_QUIC_QUIC_SPDY_SESSION_H_
+#endif // NET_QUIC_CORE_QUIC_SPDY_SESSION_H_
diff --git a/chromium/net/quic/core/quic_spdy_stream.cc b/chromium/net/quic/core/quic_spdy_stream.cc
index bb8b172e55b..3fb5e236adb 100644
--- a/chromium/net/quic/core/quic_spdy_stream.cc
+++ b/chromium/net/quic/core/quic_spdy_stream.cc
@@ -6,17 +6,17 @@
#include <utility>
-#include "base/logging.h"
-#include "base/strings/string_number_conversions.h"
-#include "net/quic/core/quic_bug_tracker.h"
+#include "net/base/parse_number.h"
#include "net/quic/core/quic_spdy_session.h"
#include "net/quic/core/quic_utils.h"
#include "net/quic/core/quic_write_blocked_list.h"
#include "net/quic/core/spdy_utils.h"
+#include "net/quic/platform/api/quic_bug_tracker.h"
+#include "net/quic/platform/api/quic_logging.h"
+#include "net/quic/platform/api/quic_text_utils.h"
using base::IntToString;
using base::StringPiece;
-using std::min;
using std::string;
namespace net {
@@ -47,24 +47,12 @@ QuicSpdyStream::~QuicSpdyStream() {
}
}
-void QuicSpdyStream::CloseWriteSide() {
- if (!fin_received() && !rst_received() && sequencer()->ignore_read_data() &&
- !rst_sent()) {
- DCHECK(fin_sent());
- // Tell the peer to stop sending further data.
- DVLOG(1) << ENDPOINT << "Send QUIC_STREAM_NO_ERROR on stream " << id();
- Reset(QUIC_STREAM_NO_ERROR);
- }
-
- QuicStream::CloseWriteSide();
-}
-
void QuicSpdyStream::StopReading() {
if (!fin_received() && !rst_received() && write_side_closed() &&
!rst_sent()) {
DCHECK(fin_sent());
// Tell the peer to stop sending further data.
- DVLOG(1) << ENDPOINT << "Send QUIC_STREAM_NO_ERROR on stream " << id();
+ QUIC_DVLOG(1) << ENDPOINT << "Send QUIC_STREAM_NO_ERROR on stream " << id();
Reset(QUIC_STREAM_NO_ERROR);
}
QuicStream::StopReading();
@@ -73,9 +61,9 @@ void QuicSpdyStream::StopReading() {
size_t QuicSpdyStream::WriteHeaders(
SpdyHeaderBlock header_block,
bool fin,
- QuicAckListenerInterface* ack_notifier_delegate) {
+ QuicReferenceCountedPointer<QuicAckListenerInterface> ack_listener) {
size_t bytes_written = spdy_session_->WriteHeaders(
- id(), std::move(header_block), fin, priority_, ack_notifier_delegate);
+ id(), std::move(header_block), fin, priority_, std::move(ack_listener));
if (fin) {
// TODO(rch): Add test to ensure fin_sent_ is set whenever a fin is sent.
set_fin_sent(true);
@@ -87,13 +75,13 @@ size_t QuicSpdyStream::WriteHeaders(
void QuicSpdyStream::WriteOrBufferBody(
const string& data,
bool fin,
- QuicAckListenerInterface* ack_notifier_delegate) {
- WriteOrBufferData(data, fin, ack_notifier_delegate);
+ QuicReferenceCountedPointer<QuicAckListenerInterface> ack_listener) {
+ WriteOrBufferData(data, fin, std::move(ack_listener));
}
size_t QuicSpdyStream::WriteTrailers(
SpdyHeaderBlock trailer_block,
- QuicAckListenerInterface* ack_notifier_delegate) {
+ QuicReferenceCountedPointer<QuicAckListenerInterface> ack_listener) {
if (fin_sent()) {
QUIC_BUG << "Trailers cannot be sent after a FIN.";
return 0;
@@ -101,17 +89,18 @@ size_t QuicSpdyStream::WriteTrailers(
// The header block must contain the final offset for this stream, as the
// trailers may be processed out of order at the peer.
- DVLOG(1) << "Inserting trailer: (" << kFinalOffsetHeaderKey << ", "
- << stream_bytes_written() + queued_data_bytes() << ")";
- trailer_block.insert(std::make_pair(
- kFinalOffsetHeaderKey,
- IntToString(stream_bytes_written() + queued_data_bytes())));
+ QUIC_DLOG(INFO) << "Inserting trailer: (" << kFinalOffsetHeaderKey << ", "
+ << stream_bytes_written() + queued_data_bytes() << ")";
+ trailer_block.insert(
+ std::make_pair(kFinalOffsetHeaderKey,
+ QuicTextUtils::Uint64ToString(stream_bytes_written() +
+ queued_data_bytes())));
// Write the trailing headers with a FIN, and close stream for writing:
// trailers are the last thing to be sent on a stream.
const bool kFin = true;
size_t bytes_written = spdy_session_->WriteHeaders(
- id(), std::move(trailer_block), kFin, priority_, ack_notifier_delegate);
+ id(), std::move(trailer_block), kFin, priority_, std::move(ack_listener));
set_fin_sent(kFin);
// Trailers are the last thing to be sent on a stream, but if there is still
@@ -180,7 +169,8 @@ void QuicSpdyStream::OnStreamHeaderList(bool fin,
// be reset.
// TODO(rch): Use an explicit "headers too large" signal. An empty header list
// might be acceptable if it corresponds to a trailing header frame.
- if (FLAGS_quic_limit_uncompressed_headers && header_list.empty()) {
+ if (FLAGS_quic_reloadable_flag_quic_limit_uncompressed_headers &&
+ header_list.empty()) {
OnHeadersTooLarge();
if (IsDoneReading()) {
return;
@@ -229,14 +219,14 @@ void QuicSpdyStream::OnTrailingHeadersComplete(
const QuicHeaderList& header_list) {
DCHECK(!trailers_decompressed_);
if (fin_received()) {
- DLOG(ERROR) << "Received Trailers after FIN, on stream: " << id();
+ QUIC_DLOG(ERROR) << "Received Trailers after FIN, on stream: " << id();
session()->connection()->CloseConnection(
QUIC_INVALID_HEADERS_STREAM_DATA, "Trailers after fin",
ConnectionCloseBehavior::SEND_CONNECTION_CLOSE_PACKET);
return;
}
if (!fin) {
- DLOG(ERROR) << "Trailers must have FIN set, on stream: " << id();
+ QUIC_DLOG(ERROR) << "Trailers must have FIN set, on stream: " << id();
session()->connection()->CloseConnection(
QUIC_INVALID_HEADERS_STREAM_DATA, "Fin missing from trailers",
ConnectionCloseBehavior::SEND_CONNECTION_CLOSE_PACKET);
@@ -246,7 +236,7 @@ void QuicSpdyStream::OnTrailingHeadersComplete(
size_t final_byte_offset = 0;
if (!SpdyUtils::CopyAndValidateTrailers(header_list, &final_byte_offset,
&received_trailers_)) {
- DLOG(ERROR) << "Trailers are malformed: " << id();
+ QUIC_DLOG(ERROR) << "Trailers are malformed: " << id();
session()->connection()->CloseConnection(
QUIC_INVALID_HEADERS_STREAM_DATA, "Trailers are malformed",
ConnectionCloseBehavior::SEND_CONNECTION_CLOSE_PACKET);
@@ -261,7 +251,7 @@ void QuicSpdyStream::OnStreamReset(const QuicRstStreamFrame& frame) {
QuicStream::OnStreamReset(frame);
return;
}
- DVLOG(1) << "Received QUIC_STREAM_NO_ERROR, not discarding response";
+ QUIC_DVLOG(1) << "Received QUIC_STREAM_NO_ERROR, not discarding response";
set_rst_received(true);
MaybeIncreaseHighestReceivedOffset(frame.byte_offset);
set_stream_error(frame.error_code);
@@ -303,15 +293,19 @@ bool QuicSpdyStream::ParseHeaderStatusCode(const SpdyHeaderBlock& header,
if (status.size() != 3) {
return false;
}
- // First character must be an integer in range [1,5].
- if (status[0] < '1' || status[0] > '5') {
+
+ unsigned int result;
+ if (!ParseUint32(status, &result, nullptr)) {
return false;
}
- // The remaining two characters must be integers.
- if (!isdigit(status[1]) || !isdigit(status[2])) {
+
+ // Valid status codes are only in the range [100, 599].
+ if (result < 100 || result >= 600) {
return false;
}
- return StringToInt(status, status_code);
+
+ *status_code = static_cast<int>(result);
+ return true;
}
bool QuicSpdyStream::FinishedReadingTrailers() const {
@@ -338,13 +332,13 @@ QuicConsumedData QuicSpdyStream::WritevDataInner(
QuicIOVector iov,
QuicStreamOffset offset,
bool fin,
- QuicAckListenerInterface* ack_notifier_delegate) {
+ QuicReferenceCountedPointer<QuicAckListenerInterface> ack_listener) {
if (spdy_session_->headers_stream() != nullptr &&
spdy_session_->force_hol_blocking()) {
- return spdy_session_->headers_stream()->WritevStreamData(
- id(), iov, offset, fin, ack_notifier_delegate);
+ return spdy_session_->WritevStreamData(id(), iov, offset, fin,
+ std::move(ack_listener));
}
- return QuicStream::WritevDataInner(iov, offset, fin, ack_notifier_delegate);
+ return QuicStream::WritevDataInner(iov, offset, fin, std::move(ack_listener));
}
} // namespace net
diff --git a/chromium/net/quic/core/quic_spdy_stream.h b/chromium/net/quic/core/quic_spdy_stream.h
index 21dab6c017c..d470e800169 100644
--- a/chromium/net/quic/core/quic_spdy_stream.h
+++ b/chromium/net/quic/core/quic_spdy_stream.h
@@ -6,8 +6,8 @@
// In each direction, the data on such a stream first contains compressed
// headers then body data.
-#ifndef NET_QUIC_QUIC_SPDY_STREAM_H_
-#define NET_QUIC_QUIC_SPDY_STREAM_H_
+#ifndef NET_QUIC_CORE_QUIC_SPDY_STREAM_H_
+#define NET_QUIC_CORE_QUIC_SPDY_STREAM_H_
#include <stddef.h>
#include <sys/types.h>
@@ -18,13 +18,13 @@
#include "base/macros.h"
#include "base/strings/string_piece.h"
#include "net/base/iovec.h"
-#include "net/base/ip_endpoint.h"
-#include "net/base/net_export.h"
#include "net/quic/core/quic_flags.h"
#include "net/quic/core/quic_header_list.h"
-#include "net/quic/core/quic_protocol.h"
+#include "net/quic/core/quic_packets.h"
#include "net/quic/core/quic_stream.h"
#include "net/quic/core/quic_stream_sequencer.h"
+#include "net/quic/platform/api/quic_export.h"
+#include "net/quic/platform/api/quic_socket_address.h"
#include "net/spdy/spdy_framer.h"
namespace net {
@@ -43,10 +43,10 @@ class QuicSpdySession;
const SpdyPriority kDefaultPriority = 3;
// A QUIC stream that can send and receive HTTP2 (SPDY) headers.
-class NET_EXPORT_PRIVATE QuicSpdyStream : public QuicStream {
+class QUIC_EXPORT_PRIVATE QuicSpdyStream : public QuicStream {
public:
// Visitor receives callbacks from the stream.
- class NET_EXPORT_PRIVATE Visitor {
+ class QUIC_EXPORT_PRIVATE Visitor {
public:
Visitor() {}
@@ -67,9 +67,6 @@ class NET_EXPORT_PRIVATE QuicSpdyStream : public QuicStream {
QuicSpdyStream(QuicStreamId id, QuicSpdySession* spdy_session);
~QuicSpdyStream() override;
- // Override the base class to send QUIC_STREAM_NO_ERROR to the peer
- // when the stream has not received all the data.
- void CloseWriteSide() override;
void StopReading() override;
// QuicStream implementation
@@ -105,19 +102,22 @@ class NET_EXPORT_PRIVATE QuicSpdyStream : public QuicStream {
// Writes the headers contained in |header_block| to the dedicated
// headers stream.
- virtual size_t WriteHeaders(SpdyHeaderBlock header_block,
- bool fin,
- QuicAckListenerInterface* ack_notifier_delegate);
+ virtual size_t WriteHeaders(
+ SpdyHeaderBlock header_block,
+ bool fin,
+ QuicReferenceCountedPointer<QuicAckListenerInterface> ack_listener);
// Sends |data| to the peer, or buffers if it can't be sent immediately.
- void WriteOrBufferBody(const std::string& data,
- bool fin,
- QuicAckListenerInterface* ack_notifier_delegate);
+ void WriteOrBufferBody(
+ const std::string& data,
+ bool fin,
+ QuicReferenceCountedPointer<QuicAckListenerInterface> ack_listener);
// Writes the trailers contained in |trailer_block| to the dedicated
// headers stream. Trailers will always have the FIN set.
- virtual size_t WriteTrailers(SpdyHeaderBlock trailer_block,
- QuicAckListenerInterface* ack_notifier_delegate);
+ virtual size_t WriteTrailers(
+ SpdyHeaderBlock trailer_block,
+ QuicReferenceCountedPointer<QuicAckListenerInterface> ack_listener);
// Marks the trailers as consumed. This applies to the case where this object
// receives headers and trailers as QuicHeaderLists via calls to
@@ -183,6 +183,8 @@ class NET_EXPORT_PRIVATE QuicSpdyStream : public QuicStream {
bool allow_bidirectional_data() const { return allow_bidirectional_data_; }
+ using QuicStream::CloseWriteSide;
+
protected:
virtual void OnInitialHeadersComplete(bool fin,
size_t frame_len,
@@ -199,7 +201,10 @@ class NET_EXPORT_PRIVATE QuicSpdyStream : public QuicStream {
QuicIOVector iov,
QuicStreamOffset offset,
bool fin,
- QuicAckListenerInterface* ack_notifier_delegate) override;
+ QuicReferenceCountedPointer<QuicAckListenerInterface> ack_listener)
+ override;
+
+ void set_headers_decompressed(bool val) { headers_decompressed_ = val; }
private:
friend class test::QuicSpdyStreamPeer;
@@ -233,4 +238,4 @@ class NET_EXPORT_PRIVATE QuicSpdyStream : public QuicStream {
} // namespace net
-#endif // NET_QUIC_QUIC_SPDY_STREAM_H_
+#endif // NET_QUIC_CORE_QUIC_SPDY_STREAM_H_
diff --git a/chromium/net/quic/core/quic_spdy_stream_test.cc b/chromium/net/quic/core/quic_spdy_stream_test.cc
index f91f88abd04..0e45dea119a 100644
--- a/chromium/net/quic/core/quic_spdy_stream_test.cc
+++ b/chromium/net/quic/core/quic_spdy_stream_test.cc
@@ -7,12 +7,12 @@
#include <memory>
#include <utility>
-#include "base/memory/ptr_util.h"
-#include "base/strings/string_number_conversions.h"
#include "net/quic/core/quic_connection.h"
#include "net/quic/core/quic_utils.h"
#include "net/quic/core/quic_write_blocked_list.h"
#include "net/quic/core/spdy_utils.h"
+#include "net/quic/platform/api/quic_ptr_util.h"
+#include "net/quic/platform/api/quic_text_utils.h"
#include "net/quic/test_tools/quic_flow_controller_peer.h"
#include "net/quic/test_tools/quic_session_peer.h"
#include "net/quic/test_tools/quic_stream_peer.h"
@@ -21,7 +21,6 @@
#include "testing/gmock/include/gmock/gmock.h"
using base::StringPiece;
-using std::min;
using std::string;
using testing::AnyNumber;
using testing::Invoke;
@@ -104,10 +103,10 @@ class QuicSpdyStreamTest : public ::testing::TestWithParam<QuicVersion> {
session_.reset(new testing::StrictMock<MockQuicSpdySession>(connection_));
stream_ = new TestStream(kClientDataStreamId1, session_.get(),
stream_should_process_data);
- session_->ActivateStream(base::WrapUnique(stream_));
+ session_->ActivateStream(QuicWrapUnique(stream_));
stream2_ = new TestStream(kClientDataStreamId2, session_.get(),
stream_should_process_data);
- session_->ActivateStream(base::WrapUnique(stream2_));
+ session_->ActivateStream(QuicWrapUnique(stream2_));
}
QuicHeaderList ProcessHeaders(bool fin, const SpdyHeaderBlock& headers) {
@@ -145,7 +144,7 @@ TEST_P(QuicSpdyStreamTest, ProcessHeaderList) {
}
TEST_P(QuicSpdyStreamTest, ProcessTooLargeHeaderList) {
- FLAGS_quic_limit_uncompressed_headers = true;
+ FLAGS_quic_reloadable_flag_quic_limit_uncompressed_headers = true;
Initialize(kShouldProcessData);
QuicHeaderList headers;
@@ -180,11 +179,19 @@ TEST_P(QuicSpdyStreamTest, ParseHeaderStatusCode) {
Initialize(kShouldProcessData);
int status_code = 0;
- // Valid status code.
+ // Valid status codes.
headers_[":status"] = "404";
EXPECT_TRUE(stream_->ParseHeaderStatusCode(headers_, &status_code));
EXPECT_EQ(404, status_code);
+ headers_[":status"] = "100";
+ EXPECT_TRUE(stream_->ParseHeaderStatusCode(headers_, &status_code));
+ EXPECT_EQ(100, status_code);
+
+ headers_[":status"] = "599";
+ EXPECT_TRUE(stream_->ParseHeaderStatusCode(headers_, &status_code));
+ EXPECT_EQ(599, status_code);
+
// Invalid status codes.
headers_[":status"] = "010";
EXPECT_FALSE(stream_->ParseHeaderStatusCode(headers_, &status_code));
@@ -204,6 +211,12 @@ TEST_P(QuicSpdyStreamTest, ParseHeaderStatusCode) {
headers_[":status"] = "+20";
EXPECT_FALSE(stream_->ParseHeaderStatusCode(headers_, &status_code));
+ headers_[":status"] = "-10";
+ EXPECT_FALSE(stream_->ParseHeaderStatusCode(headers_, &status_code));
+
+ headers_[":status"] = "-100";
+ EXPECT_FALSE(stream_->ParseHeaderStatusCode(headers_, &status_code));
+
// Leading or trailing spaces are also invalid.
headers_[":status"] = " 200";
EXPECT_FALSE(stream_->ParseHeaderStatusCode(headers_, &status_code));
@@ -255,7 +268,7 @@ TEST_P(QuicSpdyStreamTest, ProcessHeadersAndBodyFragments) {
for (size_t offset = 0; offset < body.size(); offset += fragment_size) {
size_t remaining_data = body.size() - offset;
StringPiece fragment(body.data() + offset,
- min(fragment_size, remaining_data));
+ std::min(fragment_size, remaining_data));
QuicStreamFrame frame(kClientDataStreamId1, false, offset,
StringPiece(fragment));
stream_->OnStreamFrame(frame);
@@ -388,9 +401,8 @@ TEST_P(QuicSpdyStreamTest, StreamFlowControlBlocked) {
// Try to send more data than the flow control limit allows.
string headers = SpdyUtils::SerializeUncompressedHeaders(headers_);
- string body;
const uint64_t kOverflow = 15;
- GenerateBody(&body, kWindow + kOverflow);
+ string body(kWindow + kOverflow, 'a');
EXPECT_CALL(*connection_, SendBlocked(kClientDataStreamId1));
EXPECT_CALL(*session_, WritevData(_, _, _, _, _, _))
@@ -427,8 +439,8 @@ TEST_P(QuicSpdyStreamTest, StreamFlowControlNoWindowUpdateIfNotConsumed) {
stream_->flow_controller()));
// Stream receives enough data to fill a fraction of the receive window.
- string body;
- GenerateBody(&body, kWindow / 3);
+ string body(kWindow / 3, 'a');
+ auto headers = AsHeaderList(headers_);
ProcessHeaders(false, headers_);
QuicStreamFrame frame1(kClientDataStreamId1, false, 0, StringPiece(body));
@@ -463,8 +475,7 @@ TEST_P(QuicSpdyStreamTest, StreamFlowControlWindowUpdate) {
stream_->flow_controller()));
// Stream receives enough data to fill a fraction of the receive window.
- string body;
- GenerateBody(&body, kWindow / 3);
+ string body(kWindow / 3, 'a');
ProcessHeaders(false, headers_);
stream_->ConsumeHeaderList();
@@ -521,8 +532,7 @@ TEST_P(QuicSpdyStreamTest, ConnectionFlowControlWindowUpdate) {
// Each stream gets a quarter window of data. This should not trigger a
// WINDOW_UPDATE for either stream, nor for the connection.
- string body;
- GenerateBody(&body, kWindow / 4);
+ string body(kWindow / 4, 'a');
QuicStreamFrame frame1(kClientDataStreamId1, false, 0, StringPiece(body));
stream_->OnStreamFrame(frame1);
QuicStreamFrame frame2(kClientDataStreamId2, false, 0, StringPiece(body));
@@ -534,9 +544,10 @@ TEST_P(QuicSpdyStreamTest, ConnectionFlowControlWindowUpdate) {
EXPECT_CALL(*connection_, SendWindowUpdate(kClientDataStreamId1, _)).Times(0);
EXPECT_CALL(*connection_, SendWindowUpdate(kClientDataStreamId2, _)).Times(0);
EXPECT_CALL(*connection_,
- SendWindowUpdate(0, QuicFlowControllerPeer::ReceiveWindowOffset(
- session_->flow_controller()) +
- 1 + kWindow / 2));
+ SendWindowUpdate(0,
+ QuicFlowControllerPeer::ReceiveWindowOffset(
+ session_->flow_controller()) +
+ 1 + kWindow / 2));
QuicStreamFrame frame3(kClientDataStreamId1, false, (kWindow / 4),
StringPiece("a"));
stream_->OnStreamFrame(frame3);
@@ -558,8 +569,7 @@ TEST_P(QuicSpdyStreamTest, StreamFlowControlViolation) {
ProcessHeaders(false, headers_);
// Receive data to overflow the window, violating flow control.
- string body;
- GenerateBody(&body, kWindow + 1);
+ string body(kWindow + 1, 'a');
QuicStreamFrame frame(kClientDataStreamId1, false, 0, StringPiece(body));
EXPECT_CALL(*connection_,
CloseConnection(QUIC_FLOW_CONTROL_RECEIVED_TOO_MUCH_DATA, _, _));
@@ -596,8 +606,7 @@ TEST_P(QuicSpdyStreamTest, ConnectionFlowControlViolation) {
ProcessHeaders(false, headers_);
// Send enough data to overflow the connection level flow control window.
- string body;
- GenerateBody(&body, kConnectionWindow + 1);
+ string body(kConnectionWindow + 1, 'a');
EXPECT_LT(body.size(), kStreamWindow);
QuicStreamFrame frame(kClientDataStreamId1, false, 0, StringPiece(body));
@@ -768,7 +777,8 @@ TEST_P(QuicSpdyStreamTest, ReceivingTrailersWithOffset) {
trailers_block["key1"] = "value1";
trailers_block["key2"] = "value2";
trailers_block["key3"] = "value3";
- trailers_block[kFinalOffsetHeaderKey] = base::IntToString(body.size());
+ trailers_block[kFinalOffsetHeaderKey] =
+ QuicTextUtils::Uint64ToString(body.size());
QuicHeaderList trailers = ProcessHeaders(true, trailers_block);
@@ -850,7 +860,8 @@ TEST_P(QuicSpdyStreamTest, WritingTrailersFinalOffset) {
SpdyHeaderBlock trailers;
trailers["trailer key"] = "trailer value";
SpdyHeaderBlock trailers_with_offset(trailers.Clone());
- trailers_with_offset[kFinalOffsetHeaderKey] = base::Uint64ToString(kBodySize);
+ trailers_with_offset[kFinalOffsetHeaderKey] =
+ QuicTextUtils::Uint64ToString(kBodySize);
EXPECT_CALL(*session_, WriteHeadersMock(_, _, true, _, _));
stream_->WriteTrailers(std::move(trailers), nullptr);
EXPECT_EQ(trailers_with_offset, session_->GetWriteHeaders());
diff --git a/chromium/net/quic/core/quic_stream.cc b/chromium/net/quic/core/quic_stream.cc
index 3ab6736c469..04bfec23a54 100644
--- a/chromium/net/quic/core/quic_stream.cc
+++ b/chromium/net/quic/core/quic_stream.cc
@@ -4,15 +4,14 @@
#include "net/quic/core/quic_stream.h"
-#include "base/logging.h"
-#include "net/quic/core/quic_bug_tracker.h"
#include "net/quic/core/quic_flags.h"
#include "net/quic/core/quic_flow_controller.h"
#include "net/quic/core/quic_session.h"
#include "net/quic/core/quic_write_blocked_list.h"
+#include "net/quic/platform/api/quic_bug_tracker.h"
+#include "net/quic/platform/api/quic_logging.h"
using base::StringPiece;
-using std::min;
using std::string;
namespace net {
@@ -42,9 +41,12 @@ size_t GetReceivedFlowControlWindow(QuicSession* session) {
} // namespace
-QuicStream::PendingData::PendingData(string data_in,
- QuicAckListenerInterface* ack_listener_in)
- : data(std::move(data_in)), offset(0), ack_listener(ack_listener_in) {}
+QuicStream::PendingData::PendingData(
+ string data_in,
+ QuicReferenceCountedPointer<QuicAckListenerInterface> ack_listener)
+ : data(std::move(data_in)),
+ offset(0),
+ ack_listener(std::move(ack_listener)) {}
QuicStream::PendingData::~PendingData() {}
@@ -94,8 +96,9 @@ void QuicStream::OnStreamFrame(const QuicStreamFrame& frame) {
}
if (read_side_closed_) {
- DVLOG(1) << ENDPOINT << "Stream " << frame.stream_id
- << " is closed for reading. Ignoring newly received stream data.";
+ QUIC_DLOG(INFO)
+ << ENDPOINT << "Stream " << frame.stream_id
+ << " is closed for reading. Ignoring newly received stream data.";
// The subclass does not want to read data: blackhole the data.
return;
}
@@ -177,9 +180,10 @@ void QuicStream::CloseConnectionWithDetails(QuicErrorCode error,
error, details, ConnectionCloseBehavior::SEND_CONNECTION_CLOSE_PACKET);
}
-void QuicStream::WriteOrBufferData(StringPiece data,
- bool fin,
- QuicAckListenerInterface* ack_listener) {
+void QuicStream::WriteOrBufferData(
+ StringPiece data,
+ bool fin,
+ QuicReferenceCountedPointer<QuicAckListenerInterface> ack_listener) {
if (data.empty() && !fin) {
QUIC_BUG << "data.empty() && !fin";
return;
@@ -190,7 +194,8 @@ void QuicStream::WriteOrBufferData(StringPiece data,
return;
}
if (write_side_closed_) {
- DLOG(ERROR) << ENDPOINT << "Attempt to write when the write side is closed";
+ QUIC_DLOG(ERROR) << ENDPOINT
+ << "Attempt to write when the write side is closed";
return;
}
@@ -216,7 +221,8 @@ void QuicStream::OnCanWrite() {
bool fin = false;
while (!queued_data_.empty()) {
PendingData* pending_data = &queued_data_.front();
- QuicAckListenerInterface* ack_listener = pending_data->ack_listener.get();
+ QuicReferenceCountedPointer<QuicAckListenerInterface> ack_listener =
+ pending_data->ack_listener;
if (queued_data_.size() == 1 && fin_buffered_) {
fin = true;
}
@@ -266,9 +272,10 @@ QuicConsumedData QuicStream::WritevData(
const struct iovec* iov,
int iov_count,
bool fin,
- QuicAckListenerInterface* ack_listener) {
+ QuicReferenceCountedPointer<QuicAckListenerInterface> ack_listener) {
if (write_side_closed_) {
- DLOG(ERROR) << ENDPOINT << "Attempt to write when the write side is closed";
+ QUIC_DLOG(ERROR) << ENDPOINT
+ << "Attempt to write when the write side is closed";
return QuicConsumedData(0, false);
}
@@ -287,7 +294,7 @@ QuicConsumedData QuicStream::WritevData(
QuicByteCount send_window = flow_controller_.SendWindowSize();
if (stream_contributes_to_connection_flow_control_) {
send_window =
- min(send_window, connection_flow_controller_->SendWindowSize());
+ std::min(send_window, connection_flow_controller_->SendWindowSize());
}
if (session_->ShouldYield(id())) {
@@ -307,13 +314,13 @@ QuicConsumedData QuicStream::WritevData(
// Writing more data would be a violation of flow control.
write_length = static_cast<size_t>(send_window);
- DVLOG(1) << "stream " << id() << " shortens write length to "
- << write_length << " due to flow control";
+ QUIC_DVLOG(1) << "stream " << id() << " shortens write length to "
+ << write_length << " due to flow control";
}
QuicConsumedData consumed_data =
WritevDataInner(QuicIOVector(iov, iov_count, write_length),
- stream_bytes_written_, fin, ack_listener);
+ stream_bytes_written_, fin, std::move(ack_listener));
stream_bytes_written_ += consumed_data.bytes_consumed;
AddBytesSent(consumed_data.bytes_consumed);
@@ -347,22 +354,22 @@ QuicConsumedData QuicStream::WritevDataInner(
QuicIOVector iov,
QuicStreamOffset offset,
bool fin,
- QuicAckListenerInterface* ack_notifier_delegate) {
+ QuicReferenceCountedPointer<QuicAckListenerInterface> ack_listener) {
return session()->WritevData(this, id(), iov, offset, fin,
- ack_notifier_delegate);
+ std::move(ack_listener));
}
void QuicStream::CloseReadSide() {
if (read_side_closed_) {
return;
}
- DVLOG(1) << ENDPOINT << "Done reading from stream " << id();
+ QUIC_DLOG(INFO) << ENDPOINT << "Done reading from stream " << id();
read_side_closed_ = true;
sequencer_.ReleaseBuffer();
if (write_side_closed_) {
- DVLOG(1) << ENDPOINT << "Closing stream: " << id();
+ QUIC_DLOG(INFO) << ENDPOINT << "Closing stream: " << id();
session_->CloseStream(id());
}
}
@@ -371,11 +378,11 @@ void QuicStream::CloseWriteSide() {
if (write_side_closed_) {
return;
}
- DVLOG(1) << ENDPOINT << "Done writing to stream " << id();
+ QUIC_DLOG(INFO) << ENDPOINT << "Done writing to stream " << id();
write_side_closed_ = true;
if (read_side_closed_) {
- DVLOG(1) << ENDPOINT << "Closing stream: " << id();
+ QUIC_DLOG(INFO) << ENDPOINT << "Closing stream: " << id();
session_->CloseStream(id());
}
}
@@ -389,11 +396,11 @@ QuicVersion QuicStream::version() const {
}
void QuicStream::StopReading() {
- DVLOG(1) << ENDPOINT << "Stop reading from stream " << id();
+ QUIC_DLOG(INFO) << ENDPOINT << "Stop reading from stream " << id();
sequencer_.StopReading();
}
-const IPEndPoint& QuicStream::PeerAddressOfLatestPacket() const {
+const QuicSocketAddress& QuicStream::PeerAddressOfLatestPacket() const {
return session_->connection()->last_packet_source_address();
}
@@ -405,7 +412,7 @@ void QuicStream::OnClose() {
// For flow control accounting, tell the peer how many bytes have been
// written on this stream before termination. Done here if needed, using a
// RST_STREAM frame.
- DVLOG(1) << ENDPOINT << "Sending RST_STREAM in OnClose: " << id();
+ QUIC_DLOG(INFO) << ENDPOINT << "Sending RST_STREAM in OnClose: " << id();
session_->SendRstStream(id(), QUIC_RST_ACKNOWLEDGEMENT,
stream_bytes_written_);
rst_sent_ = true;
diff --git a/chromium/net/quic/core/quic_stream.h b/chromium/net/quic/core/quic_stream.h
index a18df0556ba..5e5cfb0ccb1 100644
--- a/chromium/net/quic/core/quic_stream.h
+++ b/chromium/net/quic/core/quic_stream.h
@@ -25,14 +25,15 @@
#include <string>
#include "base/macros.h"
-#include "base/memory/ref_counted.h"
#include "base/strings/string_piece.h"
#include "net/base/iovec.h"
-#include "net/base/net_export.h"
#include "net/quic/core/quic_flow_controller.h"
-#include "net/quic/core/quic_protocol.h"
+#include "net/quic/core/quic_iovector.h"
+#include "net/quic/core/quic_packets.h"
#include "net/quic/core/quic_stream_sequencer.h"
#include "net/quic/core/quic_types.h"
+#include "net/quic/platform/api/quic_export.h"
+#include "net/quic/platform/api/quic_reference_counted.h"
namespace net {
@@ -42,7 +43,7 @@ class QuicStreamPeer;
class QuicSession;
-class NET_EXPORT_PRIVATE QuicStream {
+class QUIC_EXPORT_PRIVATE QuicStream {
public:
QuicStream(QuicStreamId id, QuicSession* session);
@@ -176,26 +177,28 @@ class NET_EXPORT_PRIVATE QuicStream {
virtual void StopReading();
// Get peer IP of the lastest packet which connection is dealing/delt with.
- virtual const IPEndPoint& PeerAddressOfLatestPacket() const;
+ virtual const QuicSocketAddress& PeerAddressOfLatestPacket() const;
- protected:
// Sends as much of 'data' to the connection as the connection will consume,
// and then buffers any remaining data in queued_data_.
// If fin is true: if it is immediately passed on to the session,
// write_side_closed() becomes true, otherwise fin_buffered_ becomes true.
- void WriteOrBufferData(base::StringPiece data,
- bool fin,
- QuicAckListenerInterface* ack_listener);
+ void WriteOrBufferData(
+ base::StringPiece data,
+ bool fin,
+ QuicReferenceCountedPointer<QuicAckListenerInterface> ack_listener);
+ protected:
// Sends as many bytes in the first |count| buffers of |iov| to the connection
// as the connection will consume.
// If |ack_listener| is provided, then it will be notified once all
// the ACKs for this write have been received.
// Returns the number of bytes consumed by the connection.
- QuicConsumedData WritevData(const struct iovec* iov,
- int iov_count,
- bool fin,
- QuicAckListenerInterface* ack_listener);
+ QuicConsumedData WritevData(
+ const struct iovec* iov,
+ int iov_count,
+ bool fin,
+ QuicReferenceCountedPointer<QuicAckListenerInterface> ack_listener);
// Allows override of the session level writev, for the force HOL
// blocking experiment.
@@ -203,7 +206,7 @@ class NET_EXPORT_PRIVATE QuicStream {
QuicIOVector iov,
QuicStreamOffset offset,
bool fin,
- QuicAckListenerInterface* ack_notifier_delegate);
+ QuicReferenceCountedPointer<QuicAckListenerInterface> ack_listener);
// Close the write side of the socket. Further writes will fail.
// Can be called by the subclass or internally.
@@ -234,7 +237,9 @@ class NET_EXPORT_PRIVATE QuicStream {
bool read_side_closed() const { return read_side_closed_; }
struct PendingData {
- PendingData(std::string data_in, QuicAckListenerInterface* ack_listener_in);
+ PendingData(
+ std::string data_in,
+ QuicReferenceCountedPointer<QuicAckListenerInterface> ack_listener);
~PendingData();
// Pending data to be written.
@@ -243,7 +248,7 @@ class NET_EXPORT_PRIVATE QuicStream {
size_t offset;
// AckListener that should be notified when the pending data is acked.
// Can be nullptr.
- scoped_refptr<QuicAckListenerInterface> ack_listener;
+ QuicReferenceCountedPointer<QuicAckListenerInterface> ack_listener;
};
// Calls MaybeSendBlocked on the stream's flow controller and the connection
diff --git a/chromium/net/quic/core/quic_stream_sequencer.cc b/chromium/net/quic/core/quic_stream_sequencer.cc
index c0ab7028f13..941a670e1d5 100644
--- a/chromium/net/quic/core/quic_stream_sequencer.cc
+++ b/chromium/net/quic/core/quic_stream_sequencer.cc
@@ -10,21 +10,17 @@
#include <utility>
#include "base/format_macros.h"
-#include "base/logging.h"
-#include "base/strings/string_number_conversions.h"
-#include "base/strings/stringprintf.h"
-#include "net/quic/core/quic_bug_tracker.h"
-#include "net/quic/core/quic_clock.h"
#include "net/quic/core/quic_flags.h"
-#include "net/quic/core/quic_protocol.h"
+#include "net/quic/core/quic_packets.h"
#include "net/quic/core/quic_stream.h"
#include "net/quic/core/quic_stream_sequencer_buffer.h"
#include "net/quic/core/quic_utils.h"
+#include "net/quic/platform/api/quic_bug_tracker.h"
+#include "net/quic/platform/api/quic_clock.h"
+#include "net/quic/platform/api/quic_logging.h"
+#include "net/quic/platform/api/quic_str_cat.h"
-using base::IntToString;
using base::StringPiece;
-using base::StringPrintf;
-using std::min;
using std::string;
namespace net {
@@ -59,12 +55,12 @@ void QuicStreamSequencer::OnStreamFrame(const QuicStreamFrame& frame) {
byte_offset, StringPiece(frame.data_buffer, frame.data_length),
clock_->ApproximateNow(), &bytes_written, &error_details);
if (result != QUIC_NO_ERROR) {
- string details = "Stream" + base::Uint64ToString(stream_->id()) + ": " +
- QuicUtils::ErrorToString(result) + ": " + error_details +
- "\nPeer Address: " +
- stream_->PeerAddressOfLatestPacket().ToString();
- DLOG(WARNING) << QuicUtils::ErrorToString(result);
- DLOG(WARNING) << details;
+ string details = QuicStrCat(
+ "Stream ", stream_->id(), ": ", QuicErrorCodeToString(result), ": ",
+ error_details, "\nPeer Address: ",
+ stream_->PeerAddressOfLatestPacket().ToString());
+ QUIC_LOG_FIRST_N(WARNING, 50) << QuicErrorCodeToString(result);
+ QUIC_LOG_FIRST_N(WARNING, 50) << details;
stream_->CloseConnectionWithDetails(result, details);
return;
}
@@ -108,9 +104,9 @@ bool QuicStreamSequencer::MaybeCloseStream() {
return false;
}
- DVLOG(1) << "Passing up termination, as we've processed "
- << buffered_frames_.BytesConsumed() << " of " << close_offset_
- << " bytes.";
+ QUIC_DVLOG(1) << "Passing up termination, as we've processed "
+ << buffered_frames_.BytesConsumed() << " of " << close_offset_
+ << " bytes.";
// This will cause the stream to consume the FIN.
// Technically it's an error if |num_bytes_consumed| isn't exactly
// equal to |close_offset|, but error handling seems silly at this point.
@@ -143,8 +139,7 @@ int QuicStreamSequencer::Readv(const struct iovec* iov, size_t iov_len) {
QuicErrorCode read_error =
buffered_frames_.Readv(iov, iov_len, &bytes_read, &error_details);
if (read_error != QUIC_NO_ERROR) {
- string details = StringPrintf("Stream %" PRIu32 ": %s", stream_->id(),
- error_details.c_str());
+ string details = QuicStrCat("Stream ", stream_->id(), ": ", error_details);
stream_->CloseConnectionWithDetails(read_error, details);
return static_cast<int>(bytes_read);
}
@@ -206,9 +201,9 @@ void QuicStreamSequencer::ReleaseBufferIfEmpty() {
void QuicStreamSequencer::FlushBufferedFrames() {
DCHECK(ignore_read_data_);
size_t bytes_flushed = buffered_frames_.FlushBufferedFrames();
- DVLOG(1) << "Flushing buffered data at offset "
- << buffered_frames_.BytesConsumed() << " length " << bytes_flushed
- << " for stream " << stream_->id();
+ QUIC_DVLOG(1) << "Flushing buffered data at offset "
+ << buffered_frames_.BytesConsumed() << " length "
+ << bytes_flushed << " for stream " << stream_->id();
stream_->AddBytesConsumed(bytes_flushed);
MaybeCloseStream();
}
@@ -223,13 +218,13 @@ QuicStreamOffset QuicStreamSequencer::NumBytesConsumed() const {
const string QuicStreamSequencer::DebugString() const {
// clang-format off
- return "QuicStreamSequencer:"
- "\n bytes buffered: " + IntToString(NumBytesBuffered()) +
- "\n bytes consumed: " + IntToString( NumBytesConsumed()) +
- "\n has bytes to read: " + (HasBytesToRead() ? "true" : "false") +
- "\n frames received: " + IntToString(num_frames_received()) +
- "\n close offset bytes: " + IntToString( close_offset_) +
- "\n is closed: " + (IsClosed() ? "true" : "false");
+ return QuicStrCat("QuicStreamSequencer:",
+ "\n bytes buffered: ", NumBytesBuffered(),
+ "\n bytes consumed: ", NumBytesConsumed(),
+ "\n has bytes to read: ", HasBytesToRead() ? "true" : "false",
+ "\n frames received: ", num_frames_received(),
+ "\n close offset bytes: ", close_offset_,
+ "\n is closed: ", IsClosed() ? "true" : "false");
// clang-format on
}
diff --git a/chromium/net/quic/core/quic_stream_sequencer.h b/chromium/net/quic/core/quic_stream_sequencer.h
index caede890168..e19da1b3724 100644
--- a/chromium/net/quic/core/quic_stream_sequencer.h
+++ b/chromium/net/quic/core/quic_stream_sequencer.h
@@ -2,17 +2,17 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#ifndef NET_QUIC_QUIC_STREAM_SEQUENCER_H_
-#define NET_QUIC_QUIC_STREAM_SEQUENCER_H_
+#ifndef NET_QUIC_CORE_QUIC_STREAM_SEQUENCER_H_
+#define NET_QUIC_CORE_QUIC_STREAM_SEQUENCER_H_
#include <stddef.h>
#include <map>
#include "base/macros.h"
-#include "net/base/net_export.h"
-#include "net/quic/core/quic_protocol.h"
+#include "net/quic/core/quic_packets.h"
#include "net/quic/core/quic_stream_sequencer_buffer.h"
+#include "net/quic/platform/api/quic_export.h"
namespace net {
@@ -21,12 +21,11 @@ class QuicStreamSequencerPeer;
} // namespace test
class QuicClock;
-class QuicSession;
class QuicStream;
// Buffers frames until we have something which can be passed
// up to the next layer.
-class NET_EXPORT_PRIVATE QuicStreamSequencer {
+class QUIC_EXPORT_PRIVATE QuicStreamSequencer {
public:
QuicStreamSequencer(QuicStream* quic_stream, const QuicClock* clock);
virtual ~QuicStreamSequencer();
@@ -148,4 +147,4 @@ class NET_EXPORT_PRIVATE QuicStreamSequencer {
} // namespace net
-#endif // NET_QUIC_QUIC_STREAM_SEQUENCER_H_
+#endif // NET_QUIC_CORE_QUIC_STREAM_SEQUENCER_H_
diff --git a/chromium/net/quic/core/quic_stream_sequencer_buffer.cc b/chromium/net/quic/core/quic_stream_sequencer_buffer.cc
index e6bd9110390..4e9aaf1c4be 100644
--- a/chromium/net/quic/core/quic_stream_sequencer_buffer.cc
+++ b/chromium/net/quic/core/quic_stream_sequencer_buffer.cc
@@ -5,14 +5,11 @@
#include "net/quic/core/quic_stream_sequencer_buffer.h"
#include "base/format_macros.h"
-#include "base/logging.h"
-#include "base/strings/string_number_conversions.h"
-#include "base/strings/stringprintf.h"
-#include "net/quic/core/quic_bug_tracker.h"
#include "net/quic/core/quic_flags.h"
+#include "net/quic/platform/api/quic_bug_tracker.h"
+#include "net/quic/platform/api/quic_logging.h"
+#include "net/quic/platform/api/quic_str_cat.h"
-using base::StringPrintf;
-using std::min;
using std::string;
namespace net {
@@ -25,15 +22,6 @@ const size_t kMaxNumGapsAllowed = 2 * kMaxPacketGap;
} // namespace
-namespace {
-
-string RangeDebugString(QuicStreamOffset start, QuicStreamOffset end) {
- return std::string("[") + base::Uint64ToString(start) + ", " +
- base::Uint64ToString(end) + ") ";
-}
-
-} // namespace
-
QuicStreamSequencerBuffer::Gap::Gap(QuicStreamOffset begin_offset,
QuicStreamOffset end_offset)
: begin_offset(begin_offset), end_offset(end_offset) {}
@@ -50,16 +38,25 @@ QuicStreamSequencerBuffer::QuicStreamSequencerBuffer(size_t max_capacity_bytes)
blocks_count_(
ceil(static_cast<double>(max_capacity_bytes) / kBlockSizeBytes)),
total_bytes_read_(0),
- blocks_(nullptr) {
+ reduce_sequencer_buffer_memory_life_time_(
+ FLAGS_quic_reloadable_flag_quic_reduce_sequencer_buffer_memory_life_time), // NOLINT
+ blocks_(reduce_sequencer_buffer_memory_life_time_
+ ? nullptr
+ : new BufferBlock*[blocks_count_]()),
+ destruction_indicator_(123456) {
+ CHECK_GT(blocks_count_, 1u)
+ << "blocks_count_ = " << blocks_count_
+ << ", max_buffer_capacity_bytes_ = " << max_buffer_capacity_bytes_;
Clear();
}
QuicStreamSequencerBuffer::~QuicStreamSequencerBuffer() {
Clear();
+ destruction_indicator_ = 654321;
}
void QuicStreamSequencerBuffer::Clear() {
- if (blocks_ != nullptr) {
+ if (!reduce_sequencer_buffer_memory_life_time_ || blocks_ != nullptr) {
for (size_t i = 0; i < blocks_count_; ++i) {
if (blocks_[i] != nullptr) {
RetireBlock(i);
@@ -82,7 +79,7 @@ bool QuicStreamSequencerBuffer::RetireBlock(size_t idx) {
}
delete blocks_[idx];
blocks_[idx] = nullptr;
- DVLOG(1) << "Retired block with index: " << idx;
+ QUIC_DVLOG(1) << "Retired block with index: " << idx;
return true;
}
@@ -92,6 +89,7 @@ QuicErrorCode QuicStreamSequencerBuffer::OnStreamData(
QuicTime timestamp,
size_t* const bytes_buffered,
std::string* error_details) {
+ CHECK_EQ(destruction_indicator_, 123456) << "This object has been destructed";
*bytes_buffered = 0;
QuicStreamOffset offset = starting_offset;
size_t size = data.size();
@@ -115,30 +113,30 @@ QuicErrorCode QuicStreamSequencerBuffer::OnStreamData(
// and allow the caller of this method to handle the result.
if (offset < current_gap->begin_offset &&
offset + size <= current_gap->begin_offset) {
- DVLOG(1) << "Duplicated data at offset: " << offset << " length: " << size;
+ QUIC_DVLOG(1) << "Duplicated data at offset: " << offset
+ << " length: " << size;
return QUIC_NO_ERROR;
}
if (offset < current_gap->begin_offset &&
offset + size > current_gap->begin_offset) {
// Beginning of new data overlaps data before current gap.
+ string prefix(data.data(), data.length() < 128 ? data.length() : 128);
*error_details =
- string("Beginning of received data overlaps with buffered data.\n") +
- "New frame range " + RangeDebugString(offset, offset + size) +
- " with first 128 bytes: " +
- string(data.data(), data.length() < 128 ? data.length() : 128) +
- "\nCurrently received frames: " + ReceivedFramesDebugString() +
- "\nCurrent gaps: " + GapsDebugString();
+ QuicStrCat("Beginning of received data overlaps with buffered data.\n",
+ "New frame range [", offset, ", ", offset + size,
+ ") with first 128 bytes: ", prefix, "\n",
+ "Currently received frames: ", GapsDebugString(), "\n",
+ "Current gaps: ", ReceivedFramesDebugString());
return QUIC_OVERLAPPING_STREAM_DATA;
}
if (offset + size > current_gap->end_offset) {
// End of new data overlaps with data after current gap.
- *error_details =
- string("End of received data overlaps with buffered data.\n") +
- "New frame range " + RangeDebugString(offset, offset + size) +
- " with first 128 bytes: " +
- string(data.data(), data.length() < 128 ? data.length() : 128) +
- "\nCurrently received frames: " + ReceivedFramesDebugString() +
- "\nCurrent gaps: " + GapsDebugString();
+ string prefix(data.data(), data.length() < 128 ? data.length() : 128);
+ *error_details = QuicStrCat(
+ "End of received data overlaps with buffered data.\nNew frame range [",
+ offset, ", ", offset + size, ") with first 128 bytes: ", prefix, "\n",
+ "Currently received frames: ", ReceivedFramesDebugString(), "\n",
+ "Current gaps: ", GapsDebugString());
return QUIC_OVERLAPPING_STREAM_DATA;
}
@@ -177,7 +175,7 @@ QuicErrorCode QuicStreamSequencerBuffer::OnStreamData(
bytes_avail = total_bytes_read_ + max_buffer_capacity_bytes_ - offset;
}
- if (blocks_ == nullptr) {
+ if (reduce_sequencer_buffer_memory_life_time_ && blocks_ == nullptr) {
blocks_.reset(new BufferBlock*[blocks_count_]());
for (size_t i = 0; i < blocks_count_; ++i) {
blocks_[i] = nullptr;
@@ -185,11 +183,11 @@ QuicErrorCode QuicStreamSequencerBuffer::OnStreamData(
}
if (write_block_num >= blocks_count_) {
- *error_details = StringPrintf(
+ *error_details = QuicStrCat(
"QuicStreamSequencerBuffer error: OnStreamData() exceed array bounds."
- "write offset = %" PRIu64 " write_block_num = %" PRIuS
- " blocks_count_ = %" PRIuS,
- offset, write_block_num, blocks_count_);
+ "write offset = ",
+ offset, " write_block_num = ", write_block_num,
+ " blocks_count_ = ", blocks_count_);
return QUIC_STREAM_SEQUENCER_INVALID_STATE;
}
if (blocks_ == nullptr) {
@@ -203,23 +201,20 @@ QuicErrorCode QuicStreamSequencerBuffer::OnStreamData(
blocks_[write_block_num] = new BufferBlock();
}
- const size_t bytes_to_copy = min<size_t>(bytes_avail, source_remaining);
+ const size_t bytes_to_copy =
+ std::min<size_t>(bytes_avail, source_remaining);
char* dest = blocks_[write_block_num]->buffer + write_block_offset;
- DVLOG(1) << "Write at offset: " << offset << " length: " << bytes_to_copy;
+ QUIC_DVLOG(1) << "Write at offset: " << offset
+ << " length: " << bytes_to_copy;
if (dest == nullptr || source == nullptr) {
- *error_details = StringPrintf(
+ *error_details = QuicStrCat(
"QuicStreamSequencerBuffer error: OnStreamData()"
- " dest == nullptr: %s"
- " source == nullptr: %s"
- " Writing at offset %" PRIu64
- " Gaps: %s"
- " Remaining frames: %s"
- " total_bytes_read_ = %" PRIu64,
- (dest == nullptr ? "true" : "false"),
- (source == nullptr ? "true" : "false"), offset,
- GapsDebugString().c_str(), ReceivedFramesDebugString().c_str(),
- total_bytes_read_);
+ " dest == nullptr: ",
+ (dest == nullptr), " source == nullptr: ", (source == nullptr),
+ " Writing at offset ", offset, " Gaps: ", GapsDebugString(),
+ " Remaining frames: ", ReceivedFramesDebugString(),
+ " total_bytes_read_ = ", total_bytes_read_);
return QUIC_STREAM_SEQUENCER_INVALID_STATE;
}
memcpy(dest, source, bytes_to_copy);
@@ -273,26 +268,31 @@ QuicErrorCode QuicStreamSequencerBuffer::Readv(const iovec* dest_iov,
size_t dest_count,
size_t* bytes_read,
string* error_details) {
+ CHECK_EQ(destruction_indicator_, 123456) << "This object has been destructed";
+
*bytes_read = 0;
for (size_t i = 0; i < dest_count && ReadableBytes() > 0; ++i) {
char* dest = reinterpret_cast<char*>(dest_iov[i].iov_base);
+ CHECK_NE(dest, nullptr);
size_t dest_remaining = dest_iov[i].iov_len;
while (dest_remaining > 0 && ReadableBytes() > 0) {
size_t block_idx = NextBlockToRead();
size_t start_offset_in_block = ReadOffset();
size_t block_capacity = GetBlockCapacity(block_idx);
- size_t bytes_available_in_block =
- min<size_t>(ReadableBytes(), block_capacity - start_offset_in_block);
+ size_t bytes_available_in_block = std::min<size_t>(
+ ReadableBytes(), block_capacity - start_offset_in_block);
size_t bytes_to_copy =
- min<size_t>(bytes_available_in_block, dest_remaining);
+ std::min<size_t>(bytes_available_in_block, dest_remaining);
DCHECK_GT(bytes_to_copy, 0UL);
if (blocks_[block_idx] == nullptr || dest == nullptr) {
- *error_details = StringPrintf(
+ *error_details = QuicStrCat(
"QuicStreamSequencerBuffer error:"
- " Readv() dest == nullptr: %s"
- " blocks_[%" PRIuS "] == nullptr: %s",
- (dest == nullptr ? "true" : "false"), block_idx,
- (blocks_[block_idx] == nullptr ? "true" : "false"));
+ " Readv() dest == nullptr: ",
+ (dest == nullptr), " blocks_[", block_idx,
+ "] == nullptr: ", (blocks_[block_idx] == nullptr),
+ " Gaps: ", GapsDebugString(),
+ " Remaining frames: ", ReceivedFramesDebugString(),
+ " total_bytes_read_ = ", total_bytes_read_);
return QUIC_STREAM_SEQUENCER_INVALID_STATE;
}
memcpy(dest, blocks_[block_idx]->buffer + start_offset_in_block,
@@ -310,11 +310,11 @@ QuicErrorCode QuicStreamSequencerBuffer::Readv(const iovec* dest_iov,
if (bytes_to_copy == bytes_available_in_block) {
bool retire_successfully = RetireBlockIfEmpty(block_idx);
if (!retire_successfully) {
- *error_details = StringPrintf(
- "QuicStreamSequencerBuffer error: fail to retire block %" PRIuS
- " as the block is already released + total_bytes_read_ = %" PRIu64
- " Gaps: %s",
- block_idx, total_bytes_read_, GapsDebugString().c_str());
+ *error_details = QuicStrCat(
+ "QuicStreamSequencerBuffer error: fail to retire block ",
+ block_idx,
+ " as the block is already released, total_bytes_read_ = ",
+ total_bytes_read_, " Gaps: ", GapsDebugString());
return QUIC_STREAM_SEQUENCER_INVALID_STATE;
}
}
@@ -329,6 +329,8 @@ QuicErrorCode QuicStreamSequencerBuffer::Readv(const iovec* dest_iov,
int QuicStreamSequencerBuffer::GetReadableRegions(struct iovec* iov,
int iov_count) const {
+ CHECK_EQ(destruction_indicator_, 123456) << "This object has been destructed";
+
DCHECK(iov != nullptr);
DCHECK_GT(iov_count, 0);
@@ -348,15 +350,15 @@ int QuicStreamSequencerBuffer::GetReadableRegions(struct iovec* iov,
if (start_block_idx == end_block_idx && ReadOffset() <= end_block_offset) {
iov[0].iov_base = blocks_[start_block_idx]->buffer + ReadOffset();
iov[0].iov_len = ReadableBytes();
- DVLOG(1) << "Got only a single block with index: " << start_block_idx;
+ QUIC_DVLOG(1) << "Got only a single block with index: " << start_block_idx;
return 1;
}
// Get first block
iov[0].iov_base = blocks_[start_block_idx]->buffer + ReadOffset();
iov[0].iov_len = GetBlockCapacity(start_block_idx) - ReadOffset();
- DVLOG(1) << "Got first block " << start_block_idx << " with len "
- << iov[0].iov_len;
+ QUIC_DVLOG(1) << "Got first block " << start_block_idx << " with len "
+ << iov[0].iov_len;
DCHECK_GT(readable_offset_end + 1, total_bytes_read_ + iov[0].iov_len)
<< "there should be more available data";
@@ -369,7 +371,7 @@ int QuicStreamSequencerBuffer::GetReadableRegions(struct iovec* iov,
DCHECK_NE(static_cast<BufferBlock*>(nullptr), blocks_[block_idx]);
iov[iov_used].iov_base = blocks_[block_idx]->buffer;
iov[iov_used].iov_len = GetBlockCapacity(block_idx);
- DVLOG(1) << "Got block with index: " << block_idx;
+ QUIC_DVLOG(1) << "Got block with index: " << block_idx;
++iov_used;
block_idx = (start_block_idx + iov_used) % blocks_count_;
}
@@ -379,7 +381,7 @@ int QuicStreamSequencerBuffer::GetReadableRegions(struct iovec* iov,
DCHECK_NE(static_cast<BufferBlock*>(nullptr), blocks_[block_idx]);
iov[iov_used].iov_base = blocks_[end_block_idx]->buffer;
iov[iov_used].iov_len = end_block_offset + 1;
- DVLOG(1) << "Got last block with index: " << end_block_idx;
+ QUIC_DVLOG(1) << "Got last block with index: " << end_block_idx;
++iov_used;
}
return iov_used;
@@ -387,6 +389,8 @@ int QuicStreamSequencerBuffer::GetReadableRegions(struct iovec* iov,
bool QuicStreamSequencerBuffer::GetReadableRegion(iovec* iov,
QuicTime* timestamp) const {
+ CHECK_EQ(destruction_indicator_, 123456) << "This object has been destructed";
+
if (ReadableBytes() == 0) {
iov[0].iov_base = nullptr;
iov[0].iov_len = 0;
@@ -395,29 +399,29 @@ bool QuicStreamSequencerBuffer::GetReadableRegion(iovec* iov,
size_t start_block_idx = NextBlockToRead();
iov->iov_base = blocks_[start_block_idx]->buffer + ReadOffset();
- size_t readable_bytes_in_block = min<size_t>(
+ size_t readable_bytes_in_block = std::min<size_t>(
GetBlockCapacity(start_block_idx) - ReadOffset(), ReadableBytes());
size_t region_len = 0;
auto iter = frame_arrival_time_map_.begin();
*timestamp = iter->second.timestamp;
- DVLOG(1) << "Readable bytes in block: " << readable_bytes_in_block;
+ QUIC_DVLOG(1) << "Readable bytes in block: " << readable_bytes_in_block;
for (; iter != frame_arrival_time_map_.end() &&
region_len + iter->second.length <= readable_bytes_in_block;
++iter) {
if (iter->second.timestamp != *timestamp) {
// If reaches a frame arrive at another timestamp, stop expanding current
// region.
- DVLOG(1) << "Meet frame with different timestamp.";
+ QUIC_DVLOG(1) << "Meet frame with different timestamp.";
break;
}
region_len += iter->second.length;
- DVLOG(1) << "Added bytes to region: " << iter->second.length;
+ QUIC_DVLOG(1) << "Added bytes to region: " << iter->second.length;
}
if (iter == frame_arrival_time_map_.end() ||
iter->second.timestamp == *timestamp) {
// If encountered the end of readable bytes before reaching a different
// timestamp.
- DVLOG(1) << "Got all readable bytes in first block.";
+ QUIC_DVLOG(1) << "Got all readable bytes in first block.";
region_len = readable_bytes_in_block;
}
iov->iov_len = region_len;
@@ -425,6 +429,8 @@ bool QuicStreamSequencerBuffer::GetReadableRegion(iovec* iov,
}
bool QuicStreamSequencerBuffer::MarkConsumed(size_t bytes_used) {
+ CHECK_EQ(destruction_indicator_, 123456) << "This object has been destructed";
+
if (bytes_used > ReadableBytes()) {
return false;
}
@@ -432,9 +438,9 @@ bool QuicStreamSequencerBuffer::MarkConsumed(size_t bytes_used) {
while (bytes_to_consume > 0) {
size_t block_idx = NextBlockToRead();
size_t offset_in_block = ReadOffset();
- size_t bytes_available = min<size_t>(
+ size_t bytes_available = std::min<size_t>(
ReadableBytes(), GetBlockCapacity(block_idx) - offset_in_block);
- size_t bytes_read = min<size_t>(bytes_to_consume, bytes_available);
+ size_t bytes_read = std::min<size_t>(bytes_to_consume, bytes_available);
total_bytes_read_ += bytes_read;
num_bytes_buffered_ -= bytes_read;
bytes_to_consume -= bytes_read;
@@ -458,6 +464,10 @@ size_t QuicStreamSequencerBuffer::FlushBufferedFrames() {
}
void QuicStreamSequencerBuffer::ReleaseWholeBuffer() {
+ if (!reduce_sequencer_buffer_memory_life_time_) {
+ // Don't release buffer if flag is off.
+ return;
+ }
Clear();
blocks_.reset(nullptr);
}
@@ -550,16 +560,16 @@ void QuicStreamSequencerBuffer::UpdateFrameArrivalMap(QuicStreamOffset offset) {
while (iter != next_frame) {
auto erased = *iter;
iter = frame_arrival_time_map_.erase(iter);
- DVLOG(1) << "Removed FrameInfo with offset: " << erased.first
- << " and length: " << erased.second.length;
+ QUIC_DVLOG(1) << "Removed FrameInfo with offset: " << erased.first
+ << " and length: " << erased.second.length;
if (erased.first + erased.second.length > offset) {
// If last frame is partially read out, update this FrameInfo and insert
// it back.
auto updated = std::make_pair(
offset, FrameInfo(erased.first + erased.second.length - offset,
erased.second.timestamp));
- DVLOG(1) << "Inserted FrameInfo with offset: " << updated.first
- << " and length: " << updated.second.length;
+ QUIC_DVLOG(1) << "Inserted FrameInfo with offset: " << updated.first
+ << " and length: " << updated.second.length;
frame_arrival_time_map_.insert(updated);
}
}
@@ -570,7 +580,8 @@ string QuicStreamSequencerBuffer::GapsDebugString() {
for (const Gap& gap : gaps_) {
QuicStreamOffset current_gap_begin = gap.begin_offset;
QuicStreamOffset current_gap_end = gap.end_offset;
- current_gaps_string += RangeDebugString(current_gap_begin, current_gap_end);
+ current_gaps_string.append(
+ QuicStrCat("[", current_gap_begin, ", ", current_gap_end, ") "));
}
return current_gaps_string;
}
@@ -581,9 +592,9 @@ string QuicStreamSequencerBuffer::ReceivedFramesDebugString() {
QuicStreamOffset current_frame_begin_offset = it.first;
QuicStreamOffset current_frame_end_offset =
it.second.length + current_frame_begin_offset;
- current_frames_string = string(StringPrintf(
- "%s[%" PRIu64 ", %" PRIu64 ") ", current_frames_string.c_str(),
- current_frame_begin_offset, current_frame_end_offset));
+ current_frames_string.append(QuicStrCat(
+ "[", current_frame_begin_offset, ", ", current_frame_end_offset,
+ ") receiving time ", it.second.timestamp.ToDebuggingValue()));
}
return current_frames_string;
}
diff --git a/chromium/net/quic/core/quic_stream_sequencer_buffer.h b/chromium/net/quic/core/quic_stream_sequencer_buffer.h
index 9549d1fbd64..22d2bebea1b 100644
--- a/chromium/net/quic/core/quic_stream_sequencer_buffer.h
+++ b/chromium/net/quic/core/quic_stream_sequencer_buffer.h
@@ -2,8 +2,8 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#ifndef NET_QUIC_QUIC_STREAM_SEQUENCER_BUFFER_H_
-#define NET_QUIC_QUIC_STREAM_SEQUENCER_BUFFER_H_
+#ifndef NET_QUIC_CORE_QUIC_STREAM_SEQUENCER_BUFFER_H_
+#define NET_QUIC_CORE_QUIC_STREAM_SEQUENCER_BUFFER_H_
// QuicStreamSequencerBuffer implements QuicStreamSequencerBufferInterface.
// It is a circular stream buffer with random write and
@@ -67,8 +67,8 @@
#include <memory>
#include "base/macros.h"
-#include "net/base/net_export.h"
-#include "net/quic/core/quic_protocol.h"
+#include "net/quic/core/quic_packets.h"
+#include "net/quic/platform/api/quic_export.h"
namespace net {
@@ -76,18 +76,18 @@ namespace test {
class QuicStreamSequencerBufferPeer;
} // namespace test
-class NET_EXPORT_PRIVATE QuicStreamSequencerBuffer {
+class QUIC_EXPORT_PRIVATE QuicStreamSequencerBuffer {
public:
// A Gap indicates a missing chunk of bytes between
// [begin_offset, end_offset) in the stream
- struct NET_EXPORT_PRIVATE Gap {
+ struct QUIC_EXPORT_PRIVATE Gap {
Gap(QuicStreamOffset begin_offset, QuicStreamOffset end_offset);
QuicStreamOffset begin_offset;
QuicStreamOffset end_offset;
};
// A FrameInfo stores the length of a frame and the time it arrived.
- struct NET_EXPORT_PRIVATE FrameInfo {
+ struct QUIC_EXPORT_PRIVATE FrameInfo {
FrameInfo();
FrameInfo(size_t length, QuicTime timestamp);
@@ -168,6 +168,10 @@ class NET_EXPORT_PRIVATE QuicStreamSequencerBuffer {
// Count how many bytes are in buffer at this moment.
size_t BytesBuffered() const;
+ bool reduce_sequencer_buffer_memory_life_time() const {
+ return reduce_sequencer_buffer_memory_life_time_;
+ }
+
private:
friend class test::QuicStreamSequencerBufferPeer;
@@ -237,6 +241,10 @@ class NET_EXPORT_PRIVATE QuicStreamSequencerBuffer {
// Contains Gaps which represents currently missing data.
std::list<Gap> gaps_;
+ // If true, allocate buffer memory upon the first frame arrival and release
+ // the memory when stream is read closed.
+ bool reduce_sequencer_buffer_memory_life_time_;
+
// An ordered, variable-length list of blocks, with the length limited
// such that the number of blocks never exceeds blocks_count_.
// Each list entry can hold up to kBlockSizeBytes bytes.
@@ -248,8 +256,13 @@ class NET_EXPORT_PRIVATE QuicStreamSequencerBuffer {
// Stores all the buffered frames' start offset, length and arrival time.
std::map<QuicStreamOffset, FrameInfo> frame_arrival_time_map_;
+ // For debugging use after free, assigned to 123456 in constructor and 654321
+ // in destructor. As long as it's not 123456, this means either use after free
+ // or memory corruption.
+ int32_t destruction_indicator_;
+
DISALLOW_COPY_AND_ASSIGN(QuicStreamSequencerBuffer);
};
} // namespace net
-#endif // NET_QUIC_QUIC_STREAM_SEQUENCER_BUFFER_H_
+#endif // NET_QUIC_CORE_QUIC_STREAM_SEQUENCER_BUFFER_H_
diff --git a/chromium/net/quic/core/quic_stream_sequencer_buffer_interface.h b/chromium/net/quic/core/quic_stream_sequencer_buffer_interface.h
deleted file mode 100644
index 96b6bb929d2..00000000000
--- a/chromium/net/quic/core/quic_stream_sequencer_buffer_interface.h
+++ /dev/null
@@ -1,77 +0,0 @@
-// Copyright (c) 2012 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.
-
-#ifndef NET_QUIC_QUIC_STREAM_SEQUENCER_BUFFER_INTERFACE_H_
-#define NET_QUIC_QUIC_STREAM_SEQUENCER_BUFFER_INTERFACE_H_
-
-#include <stddef.h>
-
-#include "net/base/net_export.h"
-#include "net/quic/core/quic_protocol.h"
-
-namespace net {
-
-// The QuicStreamSequencer uses an implementation of this interface to store
-// received data.
-class NET_EXPORT_PRIVATE QuicStreamSequencerBufferInterface {
- public:
- virtual ~QuicStreamSequencerBufferInterface() {}
-
- // Free the space used to buffer data.
- virtual void Clear() = 0;
-
- // Returns true if there is nothing to read in this buffer.
- virtual bool Empty() const = 0;
-
- // Called to buffer new data received for this stream. If the data was
- // successfully buffered, returns QUIC_NO_ERROR and stores the number of
- // bytes buffered in |bytes_buffered|. Returns an error otherwise.
- // |timestamp| is the time the data arrived.
- virtual QuicErrorCode OnStreamData(QuicStreamOffset offset,
- base::StringPiece data,
- QuicTime timestamp,
- size_t* bytes_buffered) = 0;
-
- // Reads from this buffer into given iovec array, up to number of iov_len
- // iovec objects and returns the number of bytes read.
- virtual size_t Readv(const struct iovec* iov, size_t iov_len) = 0;
-
- // Returns the readable region of valid data in iovec format. The readable
- // region is the buffer region where there is valid data not yet read by
- // client.
- // Returns the number of iovec entries in |iov| which were populated.
- // If the region is empty, one iovec entry with 0 length
- // is returned, and the function returns 0. If there are more readable
- // regions than iov_size, the function only processes the first
- // iov_size of them.
- virtual int GetReadableRegions(struct iovec* iov, int iov_len) const = 0;
-
- // Fills in one iovec with data which all arrived at the same time from the
- // next readable region.
- // Populates |timestamp| with the time that this data arrived.
- // Returns false if there is no readable region available.
- virtual bool GetReadableRegion(iovec* iov, QuicTime* timestamp) const = 0;
-
- // Called after GetReadableRegions() to free up |bytes_used| space if these
- // bytes are processed.
- // Pre-requisite: bytes_used <= available bytes to read.
- virtual bool MarkConsumed(size_t bytes_used) = 0;
-
- // Deletes and records as consumed any buffered data and clear the buffer.
- // (To be called only after sequencer's StopReading has been called.)
- virtual size_t FlushBufferedFrames() = 0;
-
- // Whether there are bytes can be read out.
- virtual bool HasBytesToRead() const = 0;
-
- // Count how many bytes have been consumed (read out of buffer).
- virtual QuicStreamOffset BytesConsumed() const = 0;
-
- // Count how many bytes are in buffer at this moment.
- virtual size_t BytesBuffered() const = 0;
-};
-
-} // namespace net
-
-#endif // NET_QUIC_QUIC_STREAM_SEQUENCER_BUFFER_INTERFACE_H_
diff --git a/chromium/net/quic/core/quic_stream_sequencer_buffer_test.cc b/chromium/net/quic/core/quic_stream_sequencer_buffer_test.cc
index bc3025d42ac..25de41f6b99 100644
--- a/chromium/net/quic/core/quic_stream_sequencer_buffer_test.cc
+++ b/chromium/net/quic/core/quic_stream_sequencer_buffer_test.cc
@@ -9,9 +9,9 @@
#include <string>
#include <utility>
-#include "base/logging.h"
#include "base/macros.h"
-#include "base/rand_util.h"
+#include "net/quic/platform/api/quic_logging.h"
+#include "net/quic/platform/api/quic_str_cat.h"
#include "net/quic/test_tools/mock_clock.h"
#include "net/quic/test_tools/quic_stream_sequencer_buffer_peer.h"
#include "net/quic/test_tools/quic_test_utils.h"
@@ -20,7 +20,6 @@
#include "testing/gmock_mutant.h"
#include "testing/gtest/include/gtest/gtest.h"
-using std::min;
using std::string;
namespace net {
@@ -111,7 +110,9 @@ TEST_F(QuicStreamSequencerBufferTest, OnStreamData0length) {
}
TEST_F(QuicStreamSequencerBufferTest, OnStreamDataWithinBlock) {
- EXPECT_FALSE(helper_->IsBufferAllocated());
+ if (FLAGS_quic_reloadable_flag_quic_reduce_sequencer_buffer_memory_life_time) { // NOLINT
+ EXPECT_FALSE(helper_->IsBufferAllocated());
+ }
string source(1024, 'a');
size_t written;
clock_.AdvanceTime(QuicTime::Delta::FromSeconds(1));
@@ -137,16 +138,16 @@ TEST_F(QuicStreamSequencerBufferTest, OnStreamDataWithinBlock) {
TEST_F(QuicStreamSequencerBufferTest, OnStreamDataInvalidSource) {
// Pass in an invalid source, expects to return error.
StringPiece source;
- source.set(nullptr, 1024);
+ source = StringPiece(nullptr, 1024);
size_t written;
clock_.AdvanceTime(QuicTime::Delta::FromSeconds(1));
QuicTime t = clock_.ApproximateNow();
EXPECT_EQ(QUIC_STREAM_SEQUENCER_INVALID_STATE,
buffer_->OnStreamData(800, source, t, &written, &error_details_));
- EXPECT_EQ(
- 0u, error_details_.find("QuicStreamSequencerBuffer error: OnStreamData()"
- " dest == nullptr: false"
- " source == nullptr: true"));
+ EXPECT_EQ(0u, error_details_.find(QuicStrCat(
+ "QuicStreamSequencerBuffer error: OnStreamData() "
+ "dest == nullptr: ",
+ false, " source == nullptr: ", true)));
}
TEST_F(QuicStreamSequencerBufferTest, OnStreamDataWithOverlap) {
@@ -322,7 +323,7 @@ TEST_F(QuicStreamSequencerBufferTest, Readv100Bytes) {
iovec iovecs[3]{iovec{dest, 40}, iovec{dest + 40, 40}, iovec{dest + 80, 40}};
size_t read;
EXPECT_EQ(QUIC_NO_ERROR, buffer_->Readv(iovecs, 3, &read, &error_details_));
- LOG(ERROR) << error_details_;
+ QUIC_LOG(ERROR) << error_details_;
EXPECT_EQ(100u, read);
EXPECT_EQ(100u, buffer_->BytesConsumed());
EXPECT_EQ(source, string(dest, read));
@@ -332,26 +333,6 @@ TEST_F(QuicStreamSequencerBufferTest, Readv100Bytes) {
EXPECT_TRUE(helper_->CheckBufferInvariants());
}
-TEST_F(QuicStreamSequencerBufferTest, ReadvError) {
- string source = string(100, 'b');
- clock_.AdvanceTime(QuicTime::Delta::FromSeconds(1));
- QuicTime t1 = clock_.ApproximateNow();
- // Write something into [0, 100).
- size_t written;
- buffer_->OnStreamData(0, source, t1, &written, &error_details_);
- EXPECT_TRUE(helper_->GetBlock(0) != nullptr);
- EXPECT_TRUE(buffer_->HasBytesToRead());
- // Read into a iovec array with total capacity of 120 bytes.
- iovec iov{nullptr, 120};
- size_t read;
- EXPECT_EQ(QUIC_STREAM_SEQUENCER_INVALID_STATE,
- buffer_->Readv(&iov, 1, &read, &error_details_));
- EXPECT_EQ(0u,
- error_details_.find(
- "QuicStreamSequencerBuffer error: Readv() dest == nullptr: true"
- " blocks_[0] == nullptr: false"));
-}
-
TEST_F(QuicStreamSequencerBufferTest, ReadvAcrossBlocks) {
string source(kBlockSizeBytes + 50, 'a');
// Write 1st block to full and extand 50 bytes to next block.
@@ -490,6 +471,10 @@ TEST_F(QuicStreamSequencerBufferTest, GetReadableRegionsEmpty) {
TEST_F(QuicStreamSequencerBufferTest, ReleaseWholeBuffer) {
// Tests that buffer is not deallocated unless ReleaseWholeBuffer() is called.
+ if (!FLAGS_quic_reloadable_flag_quic_reduce_sequencer_buffer_memory_life_time) { // NOLINT
+ // Won't release buffer when flag is off.
+ return;
+ }
string source(100, 'b');
clock_.AdvanceTime(QuicTime::Delta::FromSeconds(1));
@@ -835,8 +820,8 @@ class QuicStreamSequencerBufferRandomIOTest
bytes_to_buffer_ = 2 * max_capacity_bytes_;
Initialize();
- uint32_t seed = base::RandInt(0, std::numeric_limits<int32_t>::max());
- LOG(INFO) << "RandomWriteAndProcessInPlace test seed is " << seed;
+ uint64_t seed = QuicRandom::GetInstance()->RandUint64();
+ QUIC_LOG(INFO) << "**** The current seed is " << seed << " ****";
rng_.set_seed(seed);
}
@@ -852,8 +837,8 @@ class QuicStreamSequencerBufferRandomIOTest
size_t start_chopping_offset = 0;
size_t iterations = 0;
while (start_chopping_offset < bytes_to_buffer_) {
- size_t max_chunk = min<size_t>(max_chunk_size_bytes_,
- bytes_to_buffer_ - start_chopping_offset);
+ size_t max_chunk = std::min<size_t>(
+ max_chunk_size_bytes_, bytes_to_buffer_ - start_chopping_offset);
size_t chunk_size = rng_.RandUint64() % max_chunk + 1;
chopped_stream[iterations] =
OffsetSizePair(start_chopping_offset, chunk_size);
@@ -867,8 +852,8 @@ class QuicStreamSequencerBufferRandomIOTest
// out-of-order array of OffsetSizePairs.
for (int i = chunk_num - 1; i >= 0; --i) {
size_t random_idx = rng_.RandUint64() % (i + 1);
- DVLOG(1) << "chunk offset " << chopped_stream[random_idx].first
- << " size " << chopped_stream[random_idx].second;
+ QUIC_DVLOG(1) << "chunk offset " << chopped_stream[random_idx].first
+ << " size " << chopped_stream[random_idx].second;
shuffled_buf_.push_front(chopped_stream[random_idx]);
chopped_stream[random_idx] = chopped_stream[i];
}
@@ -899,9 +884,10 @@ class QuicStreamSequencerBufferRandomIOTest
shuffled_buf_.push_back(chunk);
shuffled_buf_.pop_front();
}
- DVLOG(1) << " write at offset: " << offset
- << " len to write: " << num_to_write << " write result: " << result
- << " left over: " << shuffled_buf_.size();
+ QUIC_DVLOG(1) << " write at offset: " << offset
+ << " len to write: " << num_to_write
+ << " write result: " << result
+ << " left over: " << shuffled_buf_.size();
}
protected:
@@ -930,7 +916,7 @@ TEST_F(QuicStreamSequencerBufferRandomIOTest, RandomWriteAndReadv) {
iterations <= 2 * bytes_to_buffer_) {
uint8_t next_action =
shuffled_buf_.empty() ? uint8_t{1} : rng_.RandUint64() % 2;
- DVLOG(1) << "iteration: " << iterations;
+ QUIC_DVLOG(1) << "iteration: " << iterations;
switch (next_action) {
case 0: { // write
WriteNextChunkToBuffer();
@@ -953,9 +939,9 @@ TEST_F(QuicStreamSequencerBufferRandomIOTest, RandomWriteAndReadv) {
buffer_->Readv(dest_iov, kNumReads, &actually_read,
&error_details_));
ASSERT_LE(actually_read, num_to_read);
- DVLOG(1) << " read from offset: " << total_bytes_read_
- << " size: " << num_to_read
- << " actual read: " << actually_read;
+ QUIC_DVLOG(1) << " read from offset: " << total_bytes_read_
+ << " size: " << num_to_read
+ << " actual read: " << actually_read;
for (size_t i = 0; i < actually_read; ++i) {
char ch = (i + total_bytes_read_) % 256;
ASSERT_EQ(ch, GetCharFromIOVecs(i, dest_iov, kNumReads))
@@ -991,7 +977,7 @@ TEST_F(QuicStreamSequencerBufferRandomIOTest, RandomWriteAndConsumeInPlace) {
iterations <= 2 * bytes_to_buffer_) {
uint8_t next_action =
shuffled_buf_.empty() ? uint8_t{1} : rng_.RandUint64() % 2;
- DVLOG(1) << "iteration: " << iterations;
+ QUIC_DVLOG(1) << "iteration: " << iterations;
switch (next_action) {
case 0: { // write
WriteNextChunkToBuffer();
@@ -1013,7 +999,7 @@ TEST_F(QuicStreamSequencerBufferRandomIOTest, RandomWriteAndConsumeInPlace) {
size_t bytes_to_process = rng_.RandUint64() % (avail_bytes + 1);
size_t bytes_processed = 0;
for (size_t i = 0; i < actually_num_read; ++i) {
- size_t bytes_in_block = min<size_t>(
+ size_t bytes_in_block = std::min<size_t>(
bytes_to_process - bytes_processed, dest_iov[i].iov_len);
if (bytes_in_block == 0) {
break;
@@ -1031,10 +1017,11 @@ TEST_F(QuicStreamSequencerBufferRandomIOTest, RandomWriteAndConsumeInPlace) {
buffer_->MarkConsumed(bytes_processed);
- DVLOG(1) << "iteration " << iterations << ": try to get " << num_read
- << " readable regions, actually get " << actually_num_read
- << " from offset: " << total_bytes_read_
- << "\nprocesse bytes: " << bytes_processed;
+ QUIC_DVLOG(1) << "iteration " << iterations << ": try to get "
+ << num_read << " readable regions, actually get "
+ << actually_num_read
+ << " from offset: " << total_bytes_read_
+ << "\nprocesse bytes: " << bytes_processed;
total_bytes_read_ += bytes_processed;
ASSERT_EQ(total_bytes_read_, buffer_->BytesConsumed());
ASSERT_TRUE(helper_->CheckBufferInvariants());
diff --git a/chromium/net/quic/core/quic_stream_sequencer_test.cc b/chromium/net/quic/core/quic_stream_sequencer_test.cc
index e71963a5f2a..0e04007bb0e 100644
--- a/chromium/net/quic/core/quic_stream_sequencer_test.cc
+++ b/chromium/net/quic/core/quic_stream_sequencer_test.cc
@@ -10,12 +10,11 @@
#include <utility>
#include <vector>
-#include "base/logging.h"
-#include "base/rand_util.h"
#include "net/base/ip_endpoint.h"
#include "net/quic/core/quic_flags.h"
#include "net/quic/core/quic_stream.h"
#include "net/quic/core/quic_utils.h"
+#include "net/quic/platform/api/quic_logging.h"
#include "net/quic/test_tools/mock_clock.h"
#include "net/quic/test_tools/quic_stream_sequencer_peer.h"
#include "net/quic/test_tools/quic_test_utils.h"
@@ -25,7 +24,6 @@
#include "testing/gtest/include/gtest/gtest.h"
using base::StringPiece;
-using std::min;
using std::string;
using testing::_;
using testing::AnyNumber;
@@ -49,12 +47,13 @@ class MockStream : public QuicStream {
MOCK_METHOD0(OnCanWrite, void());
virtual bool IsFlowControlEnabled() const { return true; }
- const IPEndPoint& PeerAddressOfLatestPacket() const override {
+ const QuicSocketAddress& PeerAddressOfLatestPacket() const override {
return peer_address_;
}
protected:
- IPEndPoint peer_address_ = IPEndPoint(net::test::Any4(), 65535);
+ QuicSocketAddress peer_address_ =
+ QuicSocketAddress(QuicIpAddress::Any4(), 65535);
};
namespace {
@@ -117,13 +116,13 @@ class QuicStreamSequencerTest : public ::testing::Test {
bool VerifyIovec(const iovec& iovec, StringPiece expected) {
if (iovec.iov_len != expected.length()) {
- LOG(ERROR) << "Invalid length: " << iovec.iov_len << " vs "
- << expected.length();
+ QUIC_LOG(ERROR) << "Invalid length: " << iovec.iov_len << " vs "
+ << expected.length();
return false;
}
if (memcmp(iovec.iov_base, expected.data(), expected.length()) != 0) {
- LOG(ERROR) << "Invalid data: " << static_cast<char*>(iovec.iov_base)
- << " vs " << expected;
+ QUIC_LOG(ERROR) << "Invalid data: " << static_cast<char*>(iovec.iov_base)
+ << " vs " << expected;
return false;
}
return true;
@@ -393,16 +392,22 @@ class QuicSequencerRandomTest : public QuicStreamSequencerTest {
int payload_size = arraysize(kPayload) - 1;
int remaining_payload = payload_size;
while (remaining_payload != 0) {
- int size = min(OneToN(6), remaining_payload);
+ int size = std::min(OneToN(6), remaining_payload);
int index = payload_size - remaining_payload;
list_.push_back(std::make_pair(index, string(kPayload + index, size)));
remaining_payload -= size;
}
}
- QuicSequencerRandomTest() { CreateFrames(); }
+ QuicSequencerRandomTest() {
+ uint64_t seed = QuicRandom::GetInstance()->RandUint64();
+ VLOG(1) << "**** The current seed is " << seed << " ****";
+ random_.set_seed(seed);
- int OneToN(int n) { return base::RandInt(1, n); }
+ CreateFrames();
+ }
+
+ int OneToN(int n) { return random_.RandUint64() % n + 1; }
void ReadAvailableData() {
// Read all available data
@@ -418,6 +423,7 @@ class QuicSequencerRandomTest : public QuicStreamSequencerTest {
string output_;
// Data which peek at using GetReadableRegion if we back up.
string peeked_;
+ SimpleRandom random_;
FrameList list_;
};
@@ -432,7 +438,7 @@ TEST_F(QuicSequencerRandomTest, RandomFramesNoDroppingNoBackup) {
while (!list_.empty()) {
int index = OneToN(list_.size()) - 1;
- LOG(ERROR) << "Sending index " << index << " " << list_[index].second;
+ QUIC_LOG(ERROR) << "Sending index " << index << " " << list_[index].second;
OnFrame(list_[index].first, list_[index].second.data());
list_.erase(list_.begin() + index);
@@ -453,7 +459,7 @@ TEST_F(QuicSequencerRandomTest, RandomFramesNoDroppingBackup) {
EXPECT_CALL(stream_, OnDataAvailable()).Times(AnyNumber());
while (output_.size() != arraysize(kPayload) - 1) {
- if (!list_.empty() && (base::RandUint64() % 2 == 0)) { // Send data
+ if (!list_.empty() && OneToN(2) == 1) { // Send data
int index = OneToN(list_.size()) - 1;
OnFrame(list_[index].first, list_[index].second.data());
list_.erase(list_.begin() + index);
@@ -471,7 +477,8 @@ TEST_F(QuicSequencerRandomTest, RandomFramesNoDroppingBackup) {
}
int total_bytes_to_peek = arraysize(buffer);
for (int i = 0; i < iovs_peeked; ++i) {
- int bytes_to_peek = min<int>(peek_iov[i].iov_len, total_bytes_to_peek);
+ int bytes_to_peek =
+ std::min<int>(peek_iov[i].iov_len, total_bytes_to_peek);
peeked_.append(static_cast<char*>(peek_iov[i].iov_base), bytes_to_peek);
total_bytes_to_peek -= bytes_to_peek;
if (total_bytes_to_peek == 0) {
@@ -658,31 +665,16 @@ TEST_F(QuicStreamSequencerTest, OutOfOrderTimestamps) {
EXPECT_EQ(0u, sequencer_->NumBytesBuffered());
}
-// TODO(danzh): Figure out the way to implement this test case without the use
-// of unsupported StringPiece constructor.
-#if 0
TEST_F(QuicStreamSequencerTest, OnStreamFrameWithNullSource) {
// Pass in a frame with data pointing to null address, expect to close
// connection with error.
- StringPiece source(nullptr, 5u);
+ StringPiece source;
+ source.set(nullptr, 5u);
QuicStreamFrame frame(kClientDataStreamId1, false, 1, source);
EXPECT_CALL(stream_, CloseConnectionWithDetails(
QUIC_STREAM_SEQUENCER_INVALID_STATE, _));
sequencer_->OnStreamFrame(frame);
}
-#endif
-
-TEST_F(QuicStreamSequencerTest, ReadvError) {
- EXPECT_CALL(stream_, OnDataAvailable());
- string source(100, 'a');
- OnFrame(0u, source.data());
- EXPECT_EQ(source.length(), sequencer_->NumBytesBuffered());
- // Pass in a null iovec, expect to tear down connection.
- EXPECT_CALL(stream_, CloseConnectionWithDetails(
- QUIC_STREAM_SEQUENCER_INVALID_STATE, _));
- iovec iov{nullptr, 512};
- sequencer_->Readv(&iov, 1u);
-}
} // namespace
} // namespace test
diff --git a/chromium/net/quic/core/quic_stream_test.cc b/chromium/net/quic/core/quic_stream_test.cc
index fbfc3beb36d..99cc0532536 100644
--- a/chromium/net/quic/core/quic_stream_test.cc
+++ b/chromium/net/quic/core/quic_stream_test.cc
@@ -6,12 +6,13 @@
#include <memory>
-#include "base/memory/ptr_util.h"
#include "net/quic/core/quic_connection.h"
#include "net/quic/core/quic_flags.h"
#include "net/quic/core/quic_utils.h"
#include "net/quic/core/quic_write_blocked_list.h"
#include "net/quic/core/spdy_utils.h"
+#include "net/quic/platform/api/quic_logging.h"
+#include "net/quic/platform/api/quic_ptr_util.h"
#include "net/quic/test_tools/quic_config_peer.h"
#include "net/quic/test_tools/quic_connection_peer.h"
#include "net/quic/test_tools/quic_flow_controller_peer.h"
@@ -23,7 +24,6 @@
#include "testing/gmock_mutant.h"
using base::StringPiece;
-using std::min;
using std::string;
using testing::AnyNumber;
using testing::AtLeast;
@@ -55,7 +55,7 @@ class TestStream : public QuicStream {
uint32_t ProcessRawData(const char* data, uint32_t data_len) {
EXPECT_NE(0u, data_len);
- DVLOG(1) << "ProcessData data_len: " << data_len;
+ QUIC_DVLOG(1) << "ProcessData data_len: " << data_len;
data_ += string(data, data_len);
return should_process_data_ ? data_len : 0;
}
@@ -117,7 +117,7 @@ class QuicStreamTest : public ::testing::TestWithParam<bool> {
stream_ = new TestStream(kTestStreamId, session_.get(),
stream_should_process_data);
// session_ now owns stream_.
- session_->ActivateStream(base::WrapUnique(stream_));
+ session_->ActivateStream(QuicWrapUnique(stream_));
// Ignore resetting when session_ is terminated.
EXPECT_CALL(*session_, SendRstStream(kTestStreamId, _, _))
.Times(AnyNumber());
@@ -144,7 +144,8 @@ class QuicStreamTest : public ::testing::TestWithParam<bool> {
QuicIOVector /*iov*/,
QuicStreamOffset /*offset*/,
bool /*fin*/,
- QuicAckListenerInterface* /*ack_notifier_delegate*/) {
+ const QuicReferenceCountedPointer<
+ QuicAckListenerInterface>& /*ack_listener*/) {
session_->CloseStream(id);
return QuicConsumedData(1, false);
}
@@ -387,15 +388,17 @@ TEST_F(QuicStreamTest, StreamFlowControlMultipleWindowUpdates) {
// TODO(ianswett): It's not clear this method is still needed now that
// ProxyAckNotifierDelegate has been removed.
-void SaveAckListener(scoped_refptr<QuicAckListenerInterface>* listener_out,
- QuicAckListenerInterface* listener) {
- *listener_out = (listener);
+void SaveAckListener(
+ QuicReferenceCountedPointer<QuicAckListenerInterface>* ack_listener_out,
+ QuicReferenceCountedPointer<QuicAckListenerInterface> ack_listener) {
+ *ack_listener_out = std::move(ack_listener);
}
TEST_F(QuicStreamTest, WriteOrBufferDataWithQuicAckNotifier) {
Initialize(kShouldProcessData);
- scoped_refptr<MockAckListener> delegate(new StrictMock<MockAckListener>);
+ QuicReferenceCountedPointer<MockAckListener> mock_ack_listener(
+ new StrictMock<MockAckListener>);
const int kDataSize = 16 * 1024;
const string kData(kDataSize, 'a');
@@ -408,28 +411,28 @@ TEST_F(QuicStreamTest, WriteOrBufferDataWithQuicAckNotifier) {
stream_->flow_controller()->UpdateSendWindowOffset(kDataSize + 1);
session_->flow_controller()->UpdateSendWindowOffset(kDataSize + 1);
- scoped_refptr<QuicAckListenerInterface> ack_listener;
+ QuicReferenceCountedPointer<QuicAckListenerInterface> ack_listener;
EXPECT_CALL(*session_, WritevData(_, kTestStreamId, _, _, _, _))
.WillOnce(DoAll(
WithArgs<5>(Invoke(CreateFunctor(SaveAckListener, &ack_listener))),
Return(QuicConsumedData(kFirstWriteSize, false))));
- stream_->WriteOrBufferData(kData, false, delegate.get());
+ stream_->WriteOrBufferData(kData, false, mock_ack_listener);
EXPECT_TRUE(HasWriteBlockedStreams());
EXPECT_CALL(*session_,
- WritevData(stream_, kTestStreamId, _, _, _, ack_listener.get()))
+ WritevData(stream_, kTestStreamId, _, _, _, ack_listener))
.WillOnce(Return(QuicConsumedData(kSecondWriteSize, false)));
stream_->OnCanWrite();
// No ack expected for an empty write.
EXPECT_CALL(*session_,
- WritevData(stream_, kTestStreamId, _, _, _, ack_listener.get()))
+ WritevData(stream_, kTestStreamId, _, _, _, ack_listener))
.WillOnce(Return(QuicConsumedData(0, false)));
stream_->OnCanWrite();
EXPECT_CALL(*session_,
- WritevData(stream_, kTestStreamId, _, _, _, ack_listener.get()))
+ WritevData(stream_, kTestStreamId, _, _, _, ack_listener))
.WillOnce(Return(QuicConsumedData(kLastWriteSize, false)));
stream_->OnCanWrite();
}
@@ -439,7 +442,8 @@ TEST_F(QuicStreamTest, WriteOrBufferDataWithQuicAckNotifier) {
TEST_F(QuicStreamTest, WriteOrBufferDataAckNotificationBeforeFlush) {
Initialize(kShouldProcessData);
- scoped_refptr<MockAckListener> ack_listener(new StrictMock<MockAckListener>);
+ QuicReferenceCountedPointer<MockAckListener> mock_ack_listener(
+ new StrictMock<MockAckListener>);
const int kDataSize = 16 * 1024;
const string kData(kDataSize, 'a');
@@ -450,18 +454,18 @@ TEST_F(QuicStreamTest, WriteOrBufferDataAckNotificationBeforeFlush) {
stream_->flow_controller()->UpdateSendWindowOffset(kDataSize + 1);
session_->flow_controller()->UpdateSendWindowOffset(kDataSize + 1);
- scoped_refptr<QuicAckListenerInterface> proxy_delegate;
+ QuicReferenceCountedPointer<QuicAckListenerInterface> ack_listener;
EXPECT_CALL(*session_, WritevData(stream_, kTestStreamId, _, _, _, _))
.WillOnce(DoAll(
- WithArgs<5>(Invoke(CreateFunctor(SaveAckListener, &proxy_delegate))),
+ WithArgs<5>(Invoke(CreateFunctor(SaveAckListener, &ack_listener))),
Return(QuicConsumedData(kInitialWriteSize, false))));
- stream_->WriteOrBufferData(kData, false, ack_listener.get());
+ stream_->WriteOrBufferData(kData, false, mock_ack_listener);
EXPECT_TRUE(HasWriteBlockedStreams());
EXPECT_CALL(*session_, WritevData(stream_, kTestStreamId, _, _, _, _))
.WillOnce(DoAll(
- WithArgs<5>(Invoke(CreateFunctor(SaveAckListener, &proxy_delegate))),
+ WithArgs<5>(Invoke(CreateFunctor(SaveAckListener, &ack_listener))),
Return(QuicConsumedData(kDataSize - kInitialWriteSize, false))));
stream_->OnCanWrite();
}
@@ -470,15 +474,16 @@ TEST_F(QuicStreamTest, WriteOrBufferDataAckNotificationBeforeFlush) {
TEST_F(QuicStreamTest, WriteAndBufferDataWithAckNotiferNoBuffer) {
Initialize(kShouldProcessData);
- scoped_refptr<MockAckListener> delegate(new StrictMock<MockAckListener>);
+ QuicReferenceCountedPointer<MockAckListener> mock_ack_listener(
+ new StrictMock<MockAckListener>);
- scoped_refptr<QuicAckListenerInterface> proxy_delegate;
+ QuicReferenceCountedPointer<QuicAckListenerInterface> ack_listener;
EXPECT_CALL(*session_, WritevData(stream_, kTestStreamId, _, _, _, _))
.WillOnce(DoAll(
- WithArgs<5>(Invoke(CreateFunctor(SaveAckListener, &proxy_delegate))),
+ WithArgs<5>(Invoke(CreateFunctor(SaveAckListener, &ack_listener))),
Return(QuicConsumedData(kDataLen, true))));
- stream_->WriteOrBufferData(kData1, true, delegate.get());
+ stream_->WriteOrBufferData(kData1, true, mock_ack_listener);
EXPECT_FALSE(HasWriteBlockedStreams());
}
@@ -486,18 +491,19 @@ TEST_F(QuicStreamTest, WriteAndBufferDataWithAckNotiferNoBuffer) {
TEST_F(QuicStreamTest, BufferOnWriteAndBufferDataWithAckNotifer) {
Initialize(kShouldProcessData);
- scoped_refptr<MockAckListener> delegate(new StrictMock<MockAckListener>);
+ QuicReferenceCountedPointer<MockAckListener> mock_ack_listener(
+ new StrictMock<MockAckListener>);
- scoped_refptr<QuicAckListenerInterface> proxy_delegate;
+ QuicReferenceCountedPointer<QuicAckListenerInterface> ack_listener;
EXPECT_CALL(*session_, WritevData(stream_, kTestStreamId, _, _, _, _))
.WillOnce(Return(QuicConsumedData(0, false)));
- stream_->WriteOrBufferData(kData1, true, delegate.get());
+ stream_->WriteOrBufferData(kData1, true, mock_ack_listener);
EXPECT_TRUE(HasWriteBlockedStreams());
EXPECT_CALL(*session_, WritevData(stream_, kTestStreamId, _, _, _, _))
.WillOnce(DoAll(
- WithArgs<5>(Invoke(CreateFunctor(SaveAckListener, &proxy_delegate))),
+ WithArgs<5>(Invoke(CreateFunctor(SaveAckListener, &ack_listener))),
Return(QuicConsumedData(kDataLen, true))));
stream_->OnCanWrite();
}
@@ -507,20 +513,21 @@ TEST_F(QuicStreamTest, BufferOnWriteAndBufferDataWithAckNotifer) {
TEST_F(QuicStreamTest, WriteAndBufferDataWithAckNotiferOnlyFinRemains) {
Initialize(kShouldProcessData);
- scoped_refptr<MockAckListener> delegate(new StrictMock<MockAckListener>);
+ QuicReferenceCountedPointer<MockAckListener> mock_ack_listener(
+ new StrictMock<MockAckListener>);
- scoped_refptr<QuicAckListenerInterface> proxy_delegate;
+ QuicReferenceCountedPointer<QuicAckListenerInterface> ack_listener;
EXPECT_CALL(*session_, WritevData(stream_, kTestStreamId, _, _, _, _))
.WillOnce(DoAll(
- WithArgs<5>(Invoke(CreateFunctor(SaveAckListener, &proxy_delegate))),
+ WithArgs<5>(Invoke(CreateFunctor(SaveAckListener, &ack_listener))),
Return(QuicConsumedData(kDataLen, false))));
- stream_->WriteOrBufferData(kData1, true, delegate.get());
+ stream_->WriteOrBufferData(kData1, true, mock_ack_listener);
EXPECT_TRUE(HasWriteBlockedStreams());
EXPECT_CALL(*session_, WritevData(stream_, kTestStreamId, _, _, _, _))
.WillOnce(DoAll(
- WithArgs<5>(Invoke(CreateFunctor(SaveAckListener, &proxy_delegate))),
+ WithArgs<5>(Invoke(CreateFunctor(SaveAckListener, &ack_listener))),
Return(QuicConsumedData(0, true))));
stream_->OnCanWrite();
}
diff --git a/chromium/net/quic/core/quic_sustained_bandwidth_recorder.cc b/chromium/net/quic/core/quic_sustained_bandwidth_recorder.cc
index 37068283781..d4324e28351 100644
--- a/chromium/net/quic/core/quic_sustained_bandwidth_recorder.cc
+++ b/chromium/net/quic/core/quic_sustained_bandwidth_recorder.cc
@@ -4,9 +4,9 @@
#include "net/quic/core/quic_sustained_bandwidth_recorder.h"
-#include "base/logging.h"
#include "net/quic/core/quic_bandwidth.h"
#include "net/quic/core/quic_time.h"
+#include "net/quic/platform/api/quic_logging.h"
namespace net {
@@ -27,7 +27,8 @@ void QuicSustainedBandwidthRecorder::RecordEstimate(bool in_recovery,
QuicTime::Delta srtt) {
if (in_recovery) {
is_recording_ = false;
- DVLOG(1) << "Stopped recording at: " << estimate_time.ToDebuggingValue();
+ QUIC_DVLOG(1) << "Stopped recording at: "
+ << estimate_time.ToDebuggingValue();
return;
}
@@ -35,7 +36,7 @@ void QuicSustainedBandwidthRecorder::RecordEstimate(bool in_recovery,
// This is the first estimate of a new recording period.
start_time_ = estimate_time;
is_recording_ = true;
- DVLOG(1) << "Started recording at: " << start_time_.ToDebuggingValue();
+ QUIC_DVLOG(1) << "Started recording at: " << start_time_.ToDebuggingValue();
return;
}
@@ -45,16 +46,16 @@ void QuicSustainedBandwidthRecorder::RecordEstimate(bool in_recovery,
has_estimate_ = true;
bandwidth_estimate_recorded_during_slow_start_ = in_slow_start;
bandwidth_estimate_ = bandwidth;
- DVLOG(1) << "New sustained bandwidth estimate (KBytes/s): "
- << bandwidth_estimate_.ToKBytesPerSecond();
+ QUIC_DVLOG(1) << "New sustained bandwidth estimate (KBytes/s): "
+ << bandwidth_estimate_.ToKBytesPerSecond();
}
// Check for an increase in max bandwidth.
if (bandwidth > max_bandwidth_estimate_) {
max_bandwidth_estimate_ = bandwidth;
max_bandwidth_timestamp_ = wall_time.ToUNIXSeconds();
- DVLOG(1) << "New max bandwidth estimate (KBytes/s): "
- << max_bandwidth_estimate_.ToKBytesPerSecond();
+ QUIC_DVLOG(1) << "New max bandwidth estimate (KBytes/s): "
+ << max_bandwidth_estimate_.ToKBytesPerSecond();
}
}
diff --git a/chromium/net/quic/core/quic_sustained_bandwidth_recorder.h b/chromium/net/quic/core/quic_sustained_bandwidth_recorder.h
index be5afef228f..63bf4587fec 100644
--- a/chromium/net/quic/core/quic_sustained_bandwidth_recorder.h
+++ b/chromium/net/quic/core/quic_sustained_bandwidth_recorder.h
@@ -2,16 +2,16 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#ifndef NET_QUIC_QUIC_SUSTAINED_BANDWIDTH_RECORDER_H_
-#define NET_QUIC_QUIC_SUSTAINED_BANDWIDTH_RECORDER_H_
+#ifndef NET_QUIC_CORE_QUIC_SUSTAINED_BANDWIDTH_RECORDER_H_
+#define NET_QUIC_CORE_QUIC_SUSTAINED_BANDWIDTH_RECORDER_H_
#include <stdint.h>
-#include "base/logging.h"
#include "base/macros.h"
-#include "net/base/net_export.h"
#include "net/quic/core/quic_bandwidth.h"
#include "net/quic/core/quic_time.h"
+#include "net/quic/platform/api/quic_export.h"
+#include "net/quic/platform/api/quic_logging.h"
namespace net {
@@ -23,7 +23,7 @@ class QuicSustainedBandwidthRecorderPeer;
// to the client in a server config update message. A sustained bandwidth
// estimate is only marked as valid if the QuicSustainedBandwidthRecorder has
// been given uninterrupted reliable estimates over a certain period of time.
-class NET_EXPORT_PRIVATE QuicSustainedBandwidthRecorder {
+class QUIC_EXPORT_PRIVATE QuicSustainedBandwidthRecorder {
public:
QuicSustainedBandwidthRecorder();
@@ -91,4 +91,4 @@ class NET_EXPORT_PRIVATE QuicSustainedBandwidthRecorder {
} // namespace net
-#endif // NET_QUIC_QUIC_SUSTAINED_BANDWIDTH_RECORDER_H_
+#endif // NET_QUIC_CORE_QUIC_SUSTAINED_BANDWIDTH_RECORDER_H_
diff --git a/chromium/net/quic/core/quic_tag.cc b/chromium/net/quic/core/quic_tag.cc
new file mode 100644
index 00000000000..1bb93351a77
--- /dev/null
+++ b/chromium/net/quic/core/quic_tag.cc
@@ -0,0 +1,72 @@
+// Copyright (c) 2016 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.
+
+#include "net/quic/core/quic_tag.h"
+
+#include <algorithm>
+
+#include "base/macros.h"
+#include "net/quic/platform/api/quic_text_utils.h"
+
+namespace net {
+
+bool FindMutualQuicTag(const QuicTagVector& our_tags_vector,
+ const QuicTag* their_tags,
+ size_t num_their_tags,
+ QuicTag* out_result,
+ size_t* out_index) {
+ if (our_tags_vector.empty()) {
+ return false;
+ }
+ const size_t num_our_tags = our_tags_vector.size();
+ for (size_t i = 0; i < num_our_tags; i++) {
+ for (size_t j = 0; j < num_their_tags; j++) {
+ if (our_tags_vector[i] == their_tags[j]) {
+ *out_result = our_tags_vector[i];
+ if (out_index != nullptr) {
+ *out_index = j;
+ }
+ return true;
+ }
+ }
+ }
+
+ return false;
+}
+
+std::string QuicTagToString(QuicTag tag) {
+ char chars[sizeof tag];
+ bool ascii = true;
+ const QuicTag orig_tag = tag;
+
+ for (size_t i = 0; i < arraysize(chars); i++) {
+ chars[i] = static_cast<char>(tag);
+ if ((chars[i] == 0 || chars[i] == '\xff') && i == arraysize(chars) - 1) {
+ chars[i] = ' ';
+ }
+ if (!isprint(static_cast<unsigned char>(chars[i]))) {
+ ascii = false;
+ break;
+ }
+ tag >>= 8;
+ }
+
+ if (ascii) {
+ return std::string(chars, sizeof(chars));
+ }
+
+ return QuicTextUtils::Uint64ToString(orig_tag);
+}
+
+uint32_t MakeQuicTag(char a, char b, char c, char d) {
+ return static_cast<uint32_t>(a) | static_cast<uint32_t>(b) << 8 |
+ static_cast<uint32_t>(c) << 16 | static_cast<uint32_t>(d) << 24;
+}
+
+bool ContainsQuicTag(const QuicTagVector& tag_vector, QuicTag tag) {
+ return std::find(tag_vector.begin(), tag_vector.end(), tag) !=
+ tag_vector.end();
+}
+
+} // namespace net
diff --git a/chromium/net/quic/core/quic_tag.h b/chromium/net/quic/core/quic_tag.h
new file mode 100644
index 00000000000..c2803cdd58e
--- /dev/null
+++ b/chromium/net/quic/core/quic_tag.h
@@ -0,0 +1,54 @@
+// Copyright (c) 2016 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.
+
+#ifndef NET_QUIC_CORE_QUIC_TAG_H_
+#define NET_QUIC_CORE_QUIC_TAG_H_
+
+#include <map>
+#include <string>
+#include <vector>
+
+#include "net/quic/platform/api/quic_export.h"
+
+namespace net {
+
+// A QuicTag is a 32-bit used as identifiers in the QUIC handshake. The use of
+// a uint32_t seeks to provide a balance between the tyranny of magic number
+// registries and the verbosity of std::strings. As far as the wire protocol is
+// concerned, these are opaque, 32-bit values.
+//
+// Tags will often be referred to by their ASCII equivalent, e.g. EXMP. This is
+// just a mnemonic for the value 0x504d5845 (little-endian version of the ASCII
+// std::string E X M P).
+typedef uint32_t QuicTag;
+typedef std::map<QuicTag, std::string> QuicTagValueMap;
+typedef std::vector<QuicTag> QuicTagVector;
+
+// MakeQuicTag returns a value given the four bytes. For example:
+// MakeQuicTag('C', 'H', 'L', 'O');
+QUIC_EXPORT_PRIVATE QuicTag MakeQuicTag(char a, char b, char c, char d);
+
+// Returns true if |tag_vector| contains |tag|.
+QUIC_EXPORT_PRIVATE bool ContainsQuicTag(const QuicTagVector& tag_vector,
+ QuicTag tag);
+
+// Sets |out_result| to the first tag in |our_tags| that is also in |their_tags|
+// and returns true. If there is no intersection it returns false.
+//
+// If |out_index| is non-nullptr and a match is found then the index of that
+// match in |their_tags| is written to |out_index|.
+QUIC_EXPORT_PRIVATE bool FindMutualQuicTag(const QuicTagVector& our_tags,
+ const QuicTag* their_tags,
+ size_t num_their_tags,
+ QuicTag* out_result,
+ size_t* out_index);
+
+// A utility function that converts a tag to a string. It will try to maintain
+// the human friendly name if possible (i.e. kABCD -> "ABCD"), or will just
+// treat it as a number if not.
+QUIC_EXPORT_PRIVATE std::string QuicTagToString(QuicTag tag);
+
+} // namespace net
+
+#endif // NET_QUIC_CORE_QUIC_TAG_H_
diff --git a/chromium/net/quic/core/quic_tag_test.cc b/chromium/net/quic/core/quic_tag_test.cc
new file mode 100644
index 00000000000..92a51d7b185
--- /dev/null
+++ b/chromium/net/quic/core/quic_tag_test.cc
@@ -0,0 +1,37 @@
+// Copyright (c) 2016 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.
+
+#include "net/quic/core/quic_tag.h"
+
+#include "net/quic/core/crypto/crypto_protocol.h"
+#include "testing/gmock/include/gmock/gmock.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace net {
+namespace test {
+namespace {
+
+TEST(QuicTagTest, TagToString) {
+ EXPECT_EQ("SCFG", QuicTagToString(kSCFG));
+ EXPECT_EQ("SNO ", QuicTagToString(kServerNonceTag));
+ EXPECT_EQ("CRT ", QuicTagToString(kCertificateTag));
+ EXPECT_EQ("CHLO", QuicTagToString(MakeQuicTag('C', 'H', 'L', 'O')));
+ // A tag that contains a non-printing character will be printed as a decimal
+ // number.
+ EXPECT_EQ("525092931", QuicTagToString(MakeQuicTag('C', 'H', 'L', '\x1f')));
+}
+
+TEST(QuicTagTest, MakeQuicTag) {
+ QuicTag tag = MakeQuicTag('A', 'B', 'C', 'D');
+ char bytes[4];
+ memcpy(bytes, &tag, 4);
+ EXPECT_EQ('A', bytes[0]);
+ EXPECT_EQ('B', bytes[1]);
+ EXPECT_EQ('C', bytes[2]);
+ EXPECT_EQ('D', bytes[3]);
+}
+
+} // namespace
+} // namespace test
+} // namespace net
diff --git a/chromium/net/quic/core/quic_time.cc b/chromium/net/quic/core/quic_time.cc
index c9e72ce57de..d1cfbafcdcb 100644
--- a/chromium/net/quic/core/quic_time.cc
+++ b/chromium/net/quic/core/quic_time.cc
@@ -8,14 +8,14 @@
#include <cstdlib>
#include <limits>
-#include "base/logging.h"
#include "base/strings/stringprintf.h"
using base::StringPrintf;
+using std::string;
namespace net {
-std::string QuicTime::Delta::ToDebugValue() const {
+string QuicTime::Delta::ToDebugValue() const {
const int64_t one_ms = 1000;
const int64_t one_s = 1000 * one_ms;
diff --git a/chromium/net/quic/core/quic_time.h b/chromium/net/quic/core/quic_time.h
index 06aa8827cb2..ee883bfcfe0 100644
--- a/chromium/net/quic/core/quic_time.h
+++ b/chromium/net/quic/core/quic_time.h
@@ -8,8 +8,8 @@
//
// This implementation wraps the classes base::TimeTicks and base::TimeDelta.
-#ifndef NET_QUIC_QUIC_TIME_H_
-#define NET_QUIC_QUIC_TIME_H_
+#ifndef NET_QUIC_CORE_QUIC_TIME_H_
+#define NET_QUIC_CORE_QUIC_TIME_H_
#include <stdint.h>
@@ -18,27 +18,20 @@
#include "base/compiler_specific.h"
#include "base/time/time.h"
-#include "net/base/net_export.h"
+#include "net/quic/platform/api/quic_export.h"
#define QUICTIME_CONSTEXPR inline
namespace net {
-static const int kNumSecondsPerMinute = 60;
-static const int kNumSecondsPerHour = kNumSecondsPerMinute * 60;
-static const uint64_t kNumSecondsPerWeek = kNumSecondsPerHour * 24 * 7;
-static const uint64_t kNumMicrosPerSecond = base::Time::kMicrosecondsPerSecond;
-static const uint64_t kNumMicrosPerMilli =
- base::Time::kMicrosecondsPerMillisecond;
-
// A QuicTime is a purely relative time. QuicTime values from different clocks
// cannot be compared to each other. If you need an absolute time, see
// QuicWallTime, below.
-class NET_EXPORT_PRIVATE QuicTime {
+class QUIC_EXPORT_PRIVATE QuicTime {
public:
// A QuicTime::Delta represents the signed difference between two points in
// time, stored in microsecond resolution.
- class NET_EXPORT_PRIVATE Delta {
+ class QUIC_EXPORT_PRIVATE Delta {
public:
explicit Delta(base::TimeDelta delta);
@@ -145,7 +138,7 @@ class NET_EXPORT_PRIVATE QuicTime {
// A QuicWallTime represents an absolute time that is globally consistent. In
// practice, clock-skew means that comparing values from different machines
// requires some flexibility.
-class NET_EXPORT_PRIVATE QuicWallTime {
+class QUIC_EXPORT_PRIVATE QuicWallTime {
public:
// FromUNIXSeconds constructs a QuicWallTime from a count of the seconds
// since the UNIX epoch.
@@ -278,4 +271,4 @@ inline std::ostream& operator<<(std::ostream& output,
}
} // namespace net
-#endif // NET_QUIC_QUIC_TIME_H_
+#endif // NET_QUIC_CORE_QUIC_TIME_H_
diff --git a/chromium/net/quic/core/quic_transmission_info.cc b/chromium/net/quic/core/quic_transmission_info.cc
new file mode 100644
index 00000000000..96cbfd2407d
--- /dev/null
+++ b/chromium/net/quic/core/quic_transmission_info.cc
@@ -0,0 +1,45 @@
+// Copyright (c) 2016 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.
+
+#include "net/quic/core/quic_transmission_info.h"
+
+namespace net {
+
+QuicTransmissionInfo::QuicTransmissionInfo()
+ : encryption_level(ENCRYPTION_NONE),
+ packet_number_length(PACKET_1BYTE_PACKET_NUMBER),
+ bytes_sent(0),
+ sent_time(QuicTime::Zero()),
+ transmission_type(NOT_RETRANSMISSION),
+ in_flight(false),
+ is_unackable(false),
+ has_crypto_handshake(false),
+ num_padding_bytes(0),
+ retransmission(0) {}
+
+QuicTransmissionInfo::QuicTransmissionInfo(
+ EncryptionLevel level,
+ QuicPacketNumberLength packet_number_length,
+ TransmissionType transmission_type,
+ QuicTime sent_time,
+ QuicPacketLength bytes_sent,
+ bool has_crypto_handshake,
+ int num_padding_bytes)
+ : encryption_level(level),
+ packet_number_length(packet_number_length),
+ bytes_sent(bytes_sent),
+ sent_time(sent_time),
+ transmission_type(transmission_type),
+ in_flight(false),
+ is_unackable(false),
+ has_crypto_handshake(has_crypto_handshake),
+ num_padding_bytes(num_padding_bytes),
+ retransmission(0) {}
+
+QuicTransmissionInfo::QuicTransmissionInfo(const QuicTransmissionInfo& other) =
+ default;
+
+QuicTransmissionInfo::~QuicTransmissionInfo() {}
+
+} // namespace net
diff --git a/chromium/net/quic/core/quic_transmission_info.h b/chromium/net/quic/core/quic_transmission_info.h
new file mode 100644
index 00000000000..cce790e461b
--- /dev/null
+++ b/chromium/net/quic/core/quic_transmission_info.h
@@ -0,0 +1,62 @@
+// Copyright (c) 2016 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.
+
+#ifndef NET_QUIC_CORE_QUIC_TRANSMISSION_INFO_H_
+#define NET_QUIC_CORE_QUIC_TRANSMISSION_INFO_H_
+
+#include <list>
+
+#include "net/quic/core/frames/quic_frame.h"
+#include "net/quic/core/quic_ack_listener_interface.h"
+#include "net/quic/core/quic_types.h"
+#include "net/quic/platform/api/quic_export.h"
+
+namespace net {
+
+// Stores details of a single sent packet.
+struct QUIC_EXPORT_PRIVATE QuicTransmissionInfo {
+ // Used by STL when assigning into a map.
+ QuicTransmissionInfo();
+
+ // Constructs a Transmission with a new all_transmissions set
+ // containing |packet_number|.
+ QuicTransmissionInfo(EncryptionLevel level,
+ QuicPacketNumberLength packet_number_length,
+ TransmissionType transmission_type,
+ QuicTime sent_time,
+ QuicPacketLength bytes_sent,
+ bool has_crypto_handshake,
+ int num_padding_bytes);
+
+ QuicTransmissionInfo(const QuicTransmissionInfo& other);
+
+ ~QuicTransmissionInfo();
+
+ QuicFrames retransmittable_frames;
+ EncryptionLevel encryption_level;
+ QuicPacketNumberLength packet_number_length;
+ QuicPacketLength bytes_sent;
+ QuicTime sent_time;
+ // Reason why this packet was transmitted.
+ TransmissionType transmission_type;
+ // In flight packets have not been abandoned or lost.
+ bool in_flight;
+ // True if the packet can never be acked, so it can be removed. Occurs when
+ // a packet is never sent, after it is acknowledged once, or if it's a crypto
+ // packet we never expect to receive an ack for.
+ bool is_unackable;
+ // True if the packet contains stream data from the crypto stream.
+ bool has_crypto_handshake;
+ // Non-zero if the packet needs padding if it's retransmitted.
+ int16_t num_padding_bytes;
+ // Stores the packet number of the next retransmission of this packet.
+ // Zero if the packet has not been retransmitted.
+ QuicPacketNumber retransmission;
+ // Non-empty if there is a listener for this packet.
+ std::list<AckListenerWrapper> ack_listeners;
+};
+
+} // namespace net
+
+#endif // NET_QUIC_CORE_QUIC_TRANSMISSION_INFO_H_
diff --git a/chromium/net/quic/core/quic_types.cc b/chromium/net/quic/core/quic_types.cc
index 49260ba4ef3..4167c944eab 100644
--- a/chromium/net/quic/core/quic_types.cc
+++ b/chromium/net/quic/core/quic_types.cc
@@ -4,19 +4,26 @@
#include "net/quic/core/quic_types.h"
-using std::ostream;
-
namespace net {
QuicConsumedData::QuicConsumedData(size_t bytes_consumed, bool fin_consumed)
: bytes_consumed(bytes_consumed), fin_consumed(fin_consumed) {}
-ostream& operator<<(ostream& os, const QuicConsumedData& s) {
+std::ostream& operator<<(std::ostream& os, const QuicConsumedData& s) {
os << "bytes_consumed: " << s.bytes_consumed
<< " fin_consumed: " << s.fin_consumed;
return os;
}
+std::ostream& operator<<(std::ostream& os, const Perspective& s) {
+ if (s == Perspective::IS_SERVER) {
+ os << "IS_SERVER";
+ } else {
+ os << "IS_CLIENT";
+ }
+ return os;
+}
+
WriteResult::WriteResult() : status(WRITE_STATUS_ERROR), bytes_written(0) {}
WriteResult::WriteResult(WriteStatus status, int bytes_written_or_error_code)
diff --git a/chromium/net/quic/core/quic_types.h b/chromium/net/quic/core/quic_types.h
index 4f24e95f62d..30fefd2137e 100644
--- a/chromium/net/quic/core/quic_types.h
+++ b/chromium/net/quic/core/quic_types.h
@@ -2,31 +2,44 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#ifndef NET_QUIC_QUIC_TYPES_H_
-#define NET_QUIC_QUIC_TYPES_H_
-
-// This header defines some basic types that don't depend on quic_protocol.h,
-// so that classes not directly related to the protocol wire format can avoid
-// including quic_protocol.h.
-
-#include <stddef.h>
+#ifndef NET_QUIC_CORE_QUIC_TYPES_H_
+#define NET_QUIC_CORE_QUIC_TYPES_H_
+#include <array>
+#include <cstddef>
+#include <map>
#include <ostream>
+#include <vector>
-#include "net/base/net_export.h"
+#include "net/quic/core/quic_time.h"
+#include "net/quic/platform/api/quic_export.h"
namespace net {
+typedef uint8_t QuicPathId;
+typedef uint16_t QuicPacketLength;
+typedef uint32_t QuicHeaderId;
+typedef uint32_t QuicStreamId;
+typedef uint64_t QuicByteCount;
+typedef uint64_t QuicConnectionId;
+typedef uint64_t QuicPacketCount;
+typedef uint64_t QuicPacketNumber;
+typedef uint64_t QuicPublicResetNonceProof;
+typedef uint64_t QuicStreamOffset;
+typedef std::array<char, 32> DiversificationNonce;
+typedef std::vector<std::pair<QuicPacketNumber, QuicTime>> PacketTimeVector;
+
// A struct for functions which consume data payloads and fins.
-struct NET_EXPORT_PRIVATE QuicConsumedData {
+struct QUIC_EXPORT_PRIVATE QuicConsumedData {
QuicConsumedData(size_t bytes_consumed, bool fin_consumed);
// By default, gtest prints the raw bytes of an object. The bool data
// member causes this object to have padding bytes, which causes the
// default gtest object printer to read uninitialize memory. So we need
// to teach gtest how to print this object.
- NET_EXPORT_PRIVATE friend std::ostream& operator<<(std::ostream& os,
- const QuicConsumedData& s);
+ QUIC_EXPORT_PRIVATE friend std::ostream& operator<<(
+ std::ostream& os,
+ const QuicConsumedData& s);
// How many bytes were consumed.
size_t bytes_consumed;
@@ -54,7 +67,7 @@ enum WriteStatus {
// A struct used to return the result of write calls including either the number
// of bytes written or the error code, depending upon the status.
-struct NET_EXPORT_PRIVATE WriteResult {
+struct QUIC_EXPORT_PRIVATE WriteResult {
WriteResult(WriteStatus status, int bytes_written_or_error_code);
WriteResult();
@@ -65,6 +78,183 @@ struct NET_EXPORT_PRIVATE WriteResult {
};
};
+enum TransmissionType : int8_t {
+ NOT_RETRANSMISSION,
+ FIRST_TRANSMISSION_TYPE = NOT_RETRANSMISSION,
+ HANDSHAKE_RETRANSMISSION, // Retransmits due to handshake timeouts.
+ ALL_UNACKED_RETRANSMISSION, // Retransmits all unacked packets.
+ ALL_INITIAL_RETRANSMISSION, // Retransmits all initially encrypted packets.
+ LOSS_RETRANSMISSION, // Retransmits due to loss detection.
+ RTO_RETRANSMISSION, // Retransmits due to retransmit time out.
+ TLP_RETRANSMISSION, // Tail loss probes.
+ LAST_TRANSMISSION_TYPE = TLP_RETRANSMISSION,
+};
+
+enum HasRetransmittableData : int8_t {
+ NO_RETRANSMITTABLE_DATA,
+ HAS_RETRANSMITTABLE_DATA,
+};
+
+enum IsHandshake : int8_t { NOT_HANDSHAKE, IS_HANDSHAKE };
+
+enum class Perspective { IS_SERVER, IS_CLIENT };
+QUIC_EXPORT_PRIVATE std::ostream& operator<<(std::ostream& os,
+ const Perspective& s);
+
+// Describes whether a ConnectionClose was originated by the peer.
+enum class ConnectionCloseSource { FROM_PEER, FROM_SELF };
+
+// Should a connection be closed silently or not.
+enum class ConnectionCloseBehavior {
+ SILENT_CLOSE,
+ SEND_CONNECTION_CLOSE_PACKET,
+ SEND_CONNECTION_CLOSE_PACKET_WITH_NO_ACK
+};
+
+enum QuicFrameType {
+ // Regular frame types. The values set here cannot change without the
+ // introduction of a new QUIC version.
+ PADDING_FRAME = 0,
+ RST_STREAM_FRAME = 1,
+ CONNECTION_CLOSE_FRAME = 2,
+ GOAWAY_FRAME = 3,
+ WINDOW_UPDATE_FRAME = 4,
+ BLOCKED_FRAME = 5,
+ STOP_WAITING_FRAME = 6,
+ PING_FRAME = 7,
+ PATH_CLOSE_FRAME = 8,
+
+ // STREAM and ACK frames are special frames. They are encoded differently on
+ // the wire and their values do not need to be stable.
+ STREAM_FRAME,
+ ACK_FRAME,
+ // The path MTU discovery frame is encoded as a PING frame on the wire.
+ MTU_DISCOVERY_FRAME,
+ NUM_FRAME_TYPES
+};
+
+enum QuicConnectionIdLength {
+ PACKET_0BYTE_CONNECTION_ID = 0,
+ PACKET_8BYTE_CONNECTION_ID = 8
+};
+
+enum QuicPacketNumberLength : int8_t {
+ PACKET_1BYTE_PACKET_NUMBER = 1,
+ PACKET_2BYTE_PACKET_NUMBER = 2,
+ PACKET_4BYTE_PACKET_NUMBER = 4,
+ PACKET_6BYTE_PACKET_NUMBER = 6
+};
+
+// Used to indicate a QuicSequenceNumberLength using two flag bits.
+enum QuicPacketNumberLengthFlags {
+ PACKET_FLAGS_1BYTE_PACKET = 0, // 00
+ PACKET_FLAGS_2BYTE_PACKET = 1, // 01
+ PACKET_FLAGS_4BYTE_PACKET = 1 << 1, // 10
+ PACKET_FLAGS_6BYTE_PACKET = 1 << 1 | 1, // 11
+};
+
+// The public flags are specified in one byte.
+enum QuicPacketPublicFlags {
+ PACKET_PUBLIC_FLAGS_NONE = 0,
+
+ // Bit 0: Does the packet header contains version info?
+ PACKET_PUBLIC_FLAGS_VERSION = 1 << 0,
+
+ // Bit 1: Is this packet a public reset packet?
+ PACKET_PUBLIC_FLAGS_RST = 1 << 1,
+
+ // Bit 2: indicates the that public header includes a nonce.
+ PACKET_PUBLIC_FLAGS_NONCE = 1 << 2,
+
+ // Bit 3: indicates whether a ConnectionID is included.
+ PACKET_PUBLIC_FLAGS_0BYTE_CONNECTION_ID = 0,
+ PACKET_PUBLIC_FLAGS_8BYTE_CONNECTION_ID = 1 << 3,
+
+ // QUIC_VERSION_32 and earlier use two bits for an 8 byte
+ // connection id.
+ PACKET_PUBLIC_FLAGS_8BYTE_CONNECTION_ID_OLD = 1 << 3 | 1 << 2,
+
+ // Bits 4 and 5 describe the packet number length as follows:
+ // --00----: 1 byte
+ // --01----: 2 bytes
+ // --10----: 4 bytes
+ // --11----: 6 bytes
+ PACKET_PUBLIC_FLAGS_1BYTE_PACKET = PACKET_FLAGS_1BYTE_PACKET << 4,
+ PACKET_PUBLIC_FLAGS_2BYTE_PACKET = PACKET_FLAGS_2BYTE_PACKET << 4,
+ PACKET_PUBLIC_FLAGS_4BYTE_PACKET = PACKET_FLAGS_4BYTE_PACKET << 4,
+ PACKET_PUBLIC_FLAGS_6BYTE_PACKET = PACKET_FLAGS_6BYTE_PACKET << 4,
+
+ // Bit 6: Does the packet header contain a path id?
+ PACKET_PUBLIC_FLAGS_MULTIPATH = 1 << 6,
+
+ // Reserved, unimplemented flags:
+
+ // Bit 7: indicates the presence of a second flags byte.
+ PACKET_PUBLIC_FLAGS_TWO_OR_MORE_BYTES = 1 << 7,
+
+ // All bits set (bit 7 is not currently used): 01111111
+ PACKET_PUBLIC_FLAGS_MAX = (1 << 7) - 1,
+};
+
+// The private flags are specified in one byte.
+enum QuicPacketPrivateFlags {
+ PACKET_PRIVATE_FLAGS_NONE = 0,
+
+ // Bit 0: Does this packet contain an entropy bit?
+ PACKET_PRIVATE_FLAGS_ENTROPY = 1 << 0,
+
+ // (bits 1-7 are not used): 00000001
+ PACKET_PRIVATE_FLAGS_MAX = (1 << 1) - 1
+};
+
+// Defines for all types of congestion control algorithms that can be used in
+// QUIC. Note that this is separate from the congestion feedback type -
+// some congestion control algorithms may use the same feedback type
+// (Reno and Cubic are the classic example for that).
+enum CongestionControlType {
+ kCubic,
+ kCubicBytes,
+ kReno,
+ kRenoBytes,
+ kBBR,
+};
+
+enum LossDetectionType {
+ kNack, // Used to mimic TCP's loss detection.
+ kTime, // Time based loss detection.
+ kAdaptiveTime, // Adaptive time based loss detection.
+ kLazyFack, // Nack based but with FACK disabled for the first ack.
+};
+
+// EncryptionLevel enumerates the stages of encryption that a QUIC connection
+// progresses through. When retransmitting a packet, the encryption level needs
+// to be specified so that it is retransmitted at a level which the peer can
+// understand.
+enum EncryptionLevel : int8_t {
+ ENCRYPTION_NONE = 0,
+ ENCRYPTION_INITIAL = 1,
+ ENCRYPTION_FORWARD_SECURE = 2,
+
+ NUM_ENCRYPTION_LEVELS,
+};
+
+enum PeerAddressChangeType {
+ // IP address and port remain unchanged.
+ NO_CHANGE,
+ // Port changed, but IP address remains unchanged.
+ PORT_CHANGE,
+ // IPv4 address changed, but within the /24 subnet (port may have changed.)
+ IPV4_SUBNET_CHANGE,
+ // IPv4 address changed, excluding /24 subnet change (port may have changed.)
+ IPV4_TO_IPV4_CHANGE,
+ // IP address change from an IPv4 to an IPv6 address (port may have changed.)
+ IPV4_TO_IPV6_CHANGE,
+ // IP address change from an IPv6 to an IPv4 address (port may have changed.)
+ IPV6_TO_IPV4_CHANGE,
+ // IP address change from an IPv6 to an IPv6 address (port may have changed.)
+ IPV6_TO_IPV6_CHANGE,
+};
+
} // namespace net
-#endif // NET_QUIC_QUIC_TYPES_H_
+#endif // NET_QUIC_CORE_QUIC_TYPES_H_
diff --git a/chromium/net/quic/core/quic_unacked_packet_map.cc b/chromium/net/quic/core/quic_unacked_packet_map.cc
index adc4a653fa3..d5456392bde 100644
--- a/chromium/net/quic/core/quic_unacked_packet_map.cc
+++ b/chromium/net/quic/core/quic_unacked_packet_map.cc
@@ -4,15 +4,10 @@
#include "net/quic/core/quic_unacked_packet_map.h"
-#include "base/logging.h"
#include "base/stl_util.h"
-#include "net/quic/chromium/quic_utils_chromium.h"
-#include "net/quic/core/quic_bug_tracker.h"
#include "net/quic/core/quic_connection_stats.h"
-#include "net/quic/core/quic_flags.h"
#include "net/quic/core/quic_utils.h"
-
-using std::max;
+#include "net/quic/platform/api/quic_bug_tracker.h"
namespace net {
@@ -25,10 +20,8 @@ QuicUnackedPacketMap::QuicUnackedPacketMap()
pending_crypto_packet_count_(0) {}
QuicUnackedPacketMap::~QuicUnackedPacketMap() {
- QuicPacketNumber index = least_unacked_;
- for (UnackedPacketMap::iterator it = unacked_packets_.begin();
- it != unacked_packets_.end(); ++it, ++index) {
- QuicUtils::DeleteFrames(&it->retransmittable_frames);
+ for (QuicTransmissionInfo& transmission_info : unacked_packets_) {
+ DeleteFrames(&(transmission_info.retransmittable_frames));
}
}
@@ -42,15 +35,15 @@ void QuicUnackedPacketMap::AddSentPacket(SerializedPacket* packet,
QUIC_BUG_IF(largest_sent_packet_ >= packet_number) << packet_number;
DCHECK_GE(packet_number, least_unacked_ + unacked_packets_.size());
while (least_unacked_ + unacked_packets_.size() < packet_number) {
- unacked_packets_.push_back(TransmissionInfo());
+ unacked_packets_.push_back(QuicTransmissionInfo());
unacked_packets_.back().is_unackable = true;
}
const bool has_crypto_handshake =
packet->has_crypto_handshake == IS_HANDSHAKE;
- TransmissionInfo info(packet->encryption_level, packet->packet_number_length,
- transmission_type, sent_time, bytes_sent,
- has_crypto_handshake, packet->num_padding_bytes);
+ QuicTransmissionInfo info(
+ packet->encryption_level, packet->packet_number_length, transmission_type,
+ sent_time, bytes_sent, has_crypto_handshake, packet->num_padding_bytes);
if (old_packet_number > 0) {
TransferRetransmissionInfo(old_packet_number, packet_number,
transmission_type, &info);
@@ -91,7 +84,7 @@ void QuicUnackedPacketMap::TransferRetransmissionInfo(
QuicPacketNumber old_packet_number,
QuicPacketNumber new_packet_number,
TransmissionType transmission_type,
- TransmissionInfo* info) {
+ QuicTransmissionInfo* info) {
if (old_packet_number < least_unacked_) {
// This can happen when a retransmission packet is queued because of write
// blocked socket, and the original packet gets acked before the
@@ -99,14 +92,14 @@ void QuicUnackedPacketMap::TransferRetransmissionInfo(
return;
}
if (old_packet_number > largest_sent_packet_) {
- QUIC_BUG << "Old TransmissionInfo never existed for :" << old_packet_number
- << " largest_sent:" << largest_sent_packet_;
+ QUIC_BUG << "Old QuicTransmissionInfo never existed for :"
+ << old_packet_number << " largest_sent:" << largest_sent_packet_;
return;
}
DCHECK_GE(new_packet_number, least_unacked_ + unacked_packets_.size());
DCHECK_NE(NOT_RETRANSMISSION, transmission_type);
- TransmissionInfo* transmission_info =
+ QuicTransmissionInfo* transmission_info =
&unacked_packets_.at(old_packet_number - least_unacked_);
QuicFrames* frames = &transmission_info->retransmittable_frames;
for (AckListenerWrapper& wrapper : transmission_info->ack_listeners) {
@@ -145,34 +138,32 @@ bool QuicUnackedPacketMap::HasRetransmittableFrames(
.retransmittable_frames.empty();
}
-void QuicUnackedPacketMap::RemoveRetransmittability(TransmissionInfo* info) {
+void QuicUnackedPacketMap::RemoveRetransmittability(
+ QuicTransmissionInfo* info) {
while (info->retransmission != 0) {
const QuicPacketNumber retransmission = info->retransmission;
info->retransmission = 0;
info = &unacked_packets_[retransmission - least_unacked_];
}
- MaybeRemoveRetransmittableFrames(info);
+
+ if (info->has_crypto_handshake) {
+ DCHECK(!info->retransmittable_frames.empty());
+ DCHECK_LT(0u, pending_crypto_packet_count_);
+ --pending_crypto_packet_count_;
+ info->has_crypto_handshake = false;
+ }
+ DeleteFrames(&info->retransmittable_frames);
}
void QuicUnackedPacketMap::RemoveRetransmittability(
QuicPacketNumber packet_number) {
DCHECK_GE(packet_number, least_unacked_);
DCHECK_LT(packet_number, least_unacked_ + unacked_packets_.size());
- TransmissionInfo* info = &unacked_packets_[packet_number - least_unacked_];
+ QuicTransmissionInfo* info =
+ &unacked_packets_[packet_number - least_unacked_];
RemoveRetransmittability(info);
}
-void QuicUnackedPacketMap::MaybeRemoveRetransmittableFrames(
- TransmissionInfo* transmission_info) {
- if (transmission_info->has_crypto_handshake) {
- DCHECK(!transmission_info->retransmittable_frames.empty());
- DCHECK_LT(0u, pending_crypto_packet_count_);
- --pending_crypto_packet_count_;
- transmission_info->has_crypto_handshake = false;
- }
- QuicUtils::DeleteFrames(&transmission_info->retransmittable_frames);
-}
-
void QuicUnackedPacketMap::IncreaseLargestObserved(
QuicPacketNumber largest_observed) {
DCHECK_LE(largest_observed_, largest_observed);
@@ -181,20 +172,20 @@ void QuicUnackedPacketMap::IncreaseLargestObserved(
bool QuicUnackedPacketMap::IsPacketUsefulForMeasuringRtt(
QuicPacketNumber packet_number,
- const TransmissionInfo& info) const {
+ const QuicTransmissionInfo& info) const {
// Packet can be used for RTT measurement if it may yet be acked as the
// largest observed packet by the receiver.
return !info.is_unackable && packet_number > largest_observed_;
}
bool QuicUnackedPacketMap::IsPacketUsefulForCongestionControl(
- const TransmissionInfo& info) const {
+ const QuicTransmissionInfo& info) const {
// Packet contributes to congestion control if it is considered inflight.
return info.in_flight;
}
bool QuicUnackedPacketMap::IsPacketUsefulForRetransmittableData(
- const TransmissionInfo& info) const {
+ const QuicTransmissionInfo& info) const {
// Packet may have retransmittable frames, or the data may have been
// retransmitted with a new packet number.
return !info.retransmittable_frames.empty() ||
@@ -202,8 +193,9 @@ bool QuicUnackedPacketMap::IsPacketUsefulForRetransmittableData(
info.retransmission > largest_observed_;
}
-bool QuicUnackedPacketMap::IsPacketUseless(QuicPacketNumber packet_number,
- const TransmissionInfo& info) const {
+bool QuicUnackedPacketMap::IsPacketUseless(
+ QuicPacketNumber packet_number,
+ const QuicTransmissionInfo& info) const {
return !IsPacketUsefulForMeasuringRtt(packet_number, info) &&
!IsPacketUsefulForCongestionControl(info) &&
!IsPacketUsefulForRetransmittableData(info);
@@ -232,11 +224,12 @@ void QuicUnackedPacketMap::NotifyAndClearListeners(
QuicTime::Delta ack_delay_time) {
DCHECK_GE(packet_number, least_unacked_);
DCHECK_LT(packet_number, least_unacked_ + unacked_packets_.size());
- TransmissionInfo* info = &unacked_packets_[packet_number - least_unacked_];
+ QuicTransmissionInfo* info =
+ &unacked_packets_[packet_number - least_unacked_];
NotifyAndClearListeners(&info->ack_listeners, ack_delay_time);
}
-void QuicUnackedPacketMap::RemoveFromInFlight(TransmissionInfo* info) {
+void QuicUnackedPacketMap::RemoveFromInFlight(QuicTransmissionInfo* info) {
if (info->in_flight) {
QUIC_BUG_IF(bytes_in_flight_ < info->bytes_sent);
bytes_in_flight_ -= info->bytes_sent;
@@ -247,14 +240,16 @@ void QuicUnackedPacketMap::RemoveFromInFlight(TransmissionInfo* info) {
void QuicUnackedPacketMap::RemoveFromInFlight(QuicPacketNumber packet_number) {
DCHECK_GE(packet_number, least_unacked_);
DCHECK_LT(packet_number, least_unacked_ + unacked_packets_.size());
- TransmissionInfo* info = &unacked_packets_[packet_number - least_unacked_];
+ QuicTransmissionInfo* info =
+ &unacked_packets_[packet_number - least_unacked_];
RemoveFromInFlight(info);
}
void QuicUnackedPacketMap::RestoreToInFlight(QuicPacketNumber packet_number) {
DCHECK_GE(packet_number, least_unacked_);
DCHECK_LT(packet_number, least_unacked_ + unacked_packets_.size());
- TransmissionInfo* info = &unacked_packets_[packet_number - least_unacked_];
+ QuicTransmissionInfo* info =
+ &unacked_packets_[packet_number - least_unacked_];
DCHECK(!info->is_unackable);
bytes_in_flight_ += info->bytes_sent;
info->in_flight = true;
@@ -269,7 +264,7 @@ void QuicUnackedPacketMap::CancelRetransmissionsForStream(
if (frames->empty()) {
continue;
}
- QuicUtils::RemoveFramesForStream(frames, stream_id);
+ RemoveFramesForStream(frames, stream_id);
if (frames->empty()) {
RemoveRetransmittability(packet_number);
}
@@ -284,12 +279,12 @@ bool QuicUnackedPacketMap::HasInFlightPackets() const {
return bytes_in_flight_ > 0;
}
-const TransmissionInfo& QuicUnackedPacketMap::GetTransmissionInfo(
+const QuicTransmissionInfo& QuicUnackedPacketMap::GetTransmissionInfo(
QuicPacketNumber packet_number) const {
return unacked_packets_[packet_number - least_unacked_];
}
-TransmissionInfo* QuicUnackedPacketMap::GetMutableTransmissionInfo(
+QuicTransmissionInfo* QuicUnackedPacketMap::GetMutableTransmissionInfo(
QuicPacketNumber packet_number) {
return &unacked_packets_[packet_number - least_unacked_];
}
diff --git a/chromium/net/quic/core/quic_unacked_packet_map.h b/chromium/net/quic/core/quic_unacked_packet_map.h
index 47352b3fbe3..1901f49e322 100644
--- a/chromium/net/quic/core/quic_unacked_packet_map.h
+++ b/chromium/net/quic/core/quic_unacked_packet_map.h
@@ -2,26 +2,24 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#ifndef NET_QUIC_QUIC_UNACKED_PACKET_MAP_H_
-#define NET_QUIC_QUIC_UNACKED_PACKET_MAP_H_
-
-#include <stddef.h>
+#ifndef NET_QUIC_CORE_QUIC_UNACKED_PACKET_MAP_H_
+#define NET_QUIC_CORE_QUIC_UNACKED_PACKET_MAP_H_
+#include <cstddef>
#include <deque>
#include "base/macros.h"
-#include "net/base/net_export.h"
-#include "net/quic/core/quic_protocol.h"
+#include "net/quic/core/quic_packets.h"
+#include "net/quic/core/quic_transmission_info.h"
+#include "net/quic/platform/api/quic_export.h"
namespace net {
-class AckNotifierManager;
-
// Class which tracks unacked packets for three purposes:
// 1) Track retransmittable data, including multiple transmissions of frames.
// 2) Track packets and bytes in flight for congestion control.
// 3) Track sent time of packets to provide RTT measurements from acks.
-class NET_EXPORT_PRIVATE QuicUnackedPacketMap {
+class QUIC_EXPORT_PRIVATE QuicUnackedPacketMap {
public:
QuicUnackedPacketMap();
~QuicUnackedPacketMap();
@@ -33,7 +31,7 @@ class NET_EXPORT_PRIVATE QuicUnackedPacketMap {
// |old_packet_number| is the packet number of the previous transmission,
// or 0 if there was none.
// Any AckNotifierWrappers in |serialized_packet| are swapped from the
- // serialized packet into the TransmissionInfo.
+ // serialized packet into the QuicTransmissionInfo.
void AddSentPacket(SerializedPacket* serialized_packet,
QuicPacketNumber old_packet_number,
TransmissionType transmission_type,
@@ -53,7 +51,7 @@ class NET_EXPORT_PRIVATE QuicUnackedPacketMap {
QuicTime::Delta delta_largest_observed);
// Marks |info| as no longer in flight.
- void RemoveFromInFlight(TransmissionInfo* info);
+ void RemoveFromInFlight(QuicTransmissionInfo* info);
// Marks |packet_number| as no longer in flight.
void RemoveFromInFlight(QuicPacketNumber packet_number);
@@ -96,7 +94,7 @@ class NET_EXPORT_PRIVATE QuicUnackedPacketMap {
// been acked by the peer. If there are no unacked packets, returns 0.
QuicPacketNumber GetLeastUnacked() const;
- typedef std::deque<TransmissionInfo> UnackedPacketMap;
+ typedef std::deque<QuicTransmissionInfo> UnackedPacketMap;
typedef UnackedPacketMap::const_iterator const_iterator;
typedef UnackedPacketMap::iterator iterator;
@@ -109,14 +107,15 @@ class NET_EXPORT_PRIVATE QuicUnackedPacketMap {
// Returns true if there are unacked packets that are in flight.
bool HasInFlightPackets() const;
- // Returns the TransmissionInfo associated with |packet_number|, which
+ // Returns the QuicTransmissionInfo associated with |packet_number|, which
// must be unacked.
- const TransmissionInfo& GetTransmissionInfo(
+ const QuicTransmissionInfo& GetTransmissionInfo(
QuicPacketNumber packet_number) const;
- // Returns mutable TransmissionInfo associated with |packet_number|, which
+ // Returns mutable QuicTransmissionInfo associated with |packet_number|, which
// must be unacked.
- TransmissionInfo* GetMutableTransmissionInfo(QuicPacketNumber packet_number);
+ QuicTransmissionInfo* GetMutableTransmissionInfo(
+ QuicPacketNumber packet_number);
// Returns the time that the last unacked packet was sent.
QuicTime GetLastPacketSentTime() const;
@@ -133,9 +132,9 @@ class NET_EXPORT_PRIVATE QuicUnackedPacketMap {
// Removes any retransmittable frames from this transmission or an associated
// transmission. It removes now useless transmissions, and disconnects any
// other packets from other transmissions.
- void RemoveRetransmittability(TransmissionInfo* info);
+ void RemoveRetransmittability(QuicTransmissionInfo* info);
- // Looks up the TransmissionInfo by |packet_number| and calls
+ // Looks up the QuicTransmissionInfo by |packet_number| and calls
// RemoveRetransmittability.
void RemoveRetransmittability(QuicPacketNumber packet_number);
@@ -155,24 +154,24 @@ class NET_EXPORT_PRIVATE QuicUnackedPacketMap {
void TransferRetransmissionInfo(QuicPacketNumber old_packet_number,
QuicPacketNumber new_packet_number,
TransmissionType transmission_type,
- TransmissionInfo* info);
-
- void MaybeRemoveRetransmittableFrames(TransmissionInfo* transmission_info);
+ QuicTransmissionInfo* info);
// Returns true if packet may be useful for an RTT measurement.
bool IsPacketUsefulForMeasuringRtt(QuicPacketNumber packet_number,
- const TransmissionInfo& info) const;
+ const QuicTransmissionInfo& info) const;
// Returns true if packet may be useful for congestion control purposes.
- bool IsPacketUsefulForCongestionControl(const TransmissionInfo& info) const;
+ bool IsPacketUsefulForCongestionControl(
+ const QuicTransmissionInfo& info) const;
// Returns true if packet may be associated with retransmittable data
// directly or through retransmissions.
- bool IsPacketUsefulForRetransmittableData(const TransmissionInfo& info) const;
+ bool IsPacketUsefulForRetransmittableData(
+ const QuicTransmissionInfo& info) const;
// Returns true if the packet no longer has a purpose in the map.
bool IsPacketUseless(QuicPacketNumber packet_number,
- const TransmissionInfo& info) const;
+ const QuicTransmissionInfo& info) const;
QuicPacketNumber largest_sent_packet_;
// The largest sent packet we expect to receive an ack for.
@@ -200,4 +199,4 @@ class NET_EXPORT_PRIVATE QuicUnackedPacketMap {
} // namespace net
-#endif // NET_QUIC_QUIC_UNACKED_PACKET_MAP_H_
+#endif // NET_QUIC_CORE_QUIC_UNACKED_PACKET_MAP_H_
diff --git a/chromium/net/quic/core/quic_unacked_packet_map_test.cc b/chromium/net/quic/core/quic_unacked_packet_map_test.cc
index 2198606af41..443cae68807 100644
--- a/chromium/net/quic/core/quic_unacked_packet_map_test.cc
+++ b/chromium/net/quic/core/quic_unacked_packet_map_test.cc
@@ -4,14 +4,9 @@
#include "net/quic/core/quic_unacked_packet_map.h"
-#include "net/quic/core/quic_flags.h"
-#include "net/quic/core/quic_utils.h"
#include "net/quic/test_tools/quic_test_utils.h"
#include "testing/gtest/include/gtest/gtest.h"
-using std::min;
-using std::vector;
-
namespace net {
namespace test {
namespace {
@@ -37,7 +32,7 @@ class QuicUnackedPacketMapTest : public ::testing::Test {
QuicStreamId stream_id) {
SerializedPacket packet(kDefaultPathId, packet_number,
PACKET_1BYTE_PACKET_NUMBER, nullptr, kDefaultLength,
- 0, false, false);
+ false, false);
QuicStreamFrame* frame = new QuicStreamFrame();
frame->stream_id = stream_id;
packet.retransmittable_frames.push_back(QuicFrame(frame));
@@ -48,7 +43,7 @@ class QuicUnackedPacketMapTest : public ::testing::Test {
QuicPacketNumber packet_number) {
return SerializedPacket(kDefaultPathId, packet_number,
PACKET_1BYTE_PACKET_NUMBER, nullptr, kDefaultLength,
- 0, false, false);
+ false, false);
}
void VerifyInFlightPackets(QuicPacketNumber* packets, size_t num_packets) {
diff --git a/chromium/net/quic/core/quic_utils.cc b/chromium/net/quic/core/quic_utils.cc
index 9bf9c5d11ad..cf516126e85 100644
--- a/chromium/net/quic/core/quic_utils.cc
+++ b/chromium/net/quic/core/quic_utils.cc
@@ -12,12 +12,8 @@
#include "base/containers/adapters.h"
#include "base/logging.h"
-#include "base/strings/string_number_conversions.h"
-#include "base/strings/string_split.h"
-#include "base/strings/stringprintf.h"
-#include "net/base/ip_address.h"
+#include "net/quic/core/quic_constants.h"
#include "net/quic/core/quic_flags.h"
-#include "net/quic/core/quic_write_blocked_list.h"
using base::StringPiece;
using std::string;
@@ -35,7 +31,7 @@ namespace {
#endif
#ifdef QUIC_UTIL_HAS_UINT128
-uint128 IncrementalHashFast(uint128 uhash, const char* data, size_t len) {
+uint128 IncrementalHashFast(uint128 uhash, StringPiece data) {
// This code ends up faster than the naive implementation for 2 reasons:
// 1. uint128 from base/int128.h is sufficiently complicated that the compiler
// cannot transform the multiplication by kPrime into a shift-multiply-add;
@@ -47,53 +43,50 @@ uint128 IncrementalHashFast(uint128 uhash, const char* data, size_t len) {
(static_cast<__uint128_t>(16777216) << 64) + 315;
__uint128_t xhash = (static_cast<__uint128_t>(Uint128High64(uhash)) << 64) +
Uint128Low64(uhash);
- const uint8_t* octets = reinterpret_cast<const uint8_t*>(data);
- for (size_t i = 0; i < len; ++i) {
+ const uint8_t* octets = reinterpret_cast<const uint8_t*>(data.data());
+ for (size_t i = 0; i < data.length(); ++i) {
xhash = (xhash ^ octets[i]) * kPrime;
}
- return uint128(static_cast<uint64_t>(xhash >> 64),
- static_cast<uint64_t>(xhash & UINT64_C(0xFFFFFFFFFFFFFFFF)));
+ return MakeUint128(
+ static_cast<uint64_t>(xhash >> 64),
+ static_cast<uint64_t>(xhash & UINT64_C(0xFFFFFFFFFFFFFFFF)));
}
#endif
#ifndef QUIC_UTIL_HAS_UINT128
// Slow implementation of IncrementalHash. In practice, only used by Chromium.
-uint128 IncrementalHashSlow(uint128 hash, const char* data, size_t len) {
+uint128 IncrementalHashSlow(uint128 hash, StringPiece data) {
// kPrime = 309485009821345068724781371
- static const uint128 kPrime(16777216, 315);
- const uint8_t* octets = reinterpret_cast<const uint8_t*>(data);
- for (size_t i = 0; i < len; ++i) {
- hash = hash ^ uint128(0, octets[i]);
+ static const uint128 kPrime = MakeUint128(16777216, 315);
+ const uint8_t* octets = reinterpret_cast<const uint8_t*>(data.data());
+ for (size_t i = 0; i < data.length(); ++i) {
+ hash = hash ^ MakeUint128(0, octets[i]);
hash = hash * kPrime;
}
return hash;
}
#endif
-uint128 IncrementalHash(uint128 hash, const char* data, size_t len) {
+uint128 IncrementalHash(uint128 hash, StringPiece data) {
#ifdef QUIC_UTIL_HAS_UINT128
- return IncrementalHashFast(hash, data, len);
+ return IncrementalHashFast(hash, data);
#else
- return IncrementalHashSlow(hash, data, len);
+ return IncrementalHashSlow(hash, data);
#endif
}
-bool IsInitializedIPEndPoint(const IPEndPoint& address) {
- return address.address().IsValid();
-}
-
} // namespace
// static
-uint64_t QuicUtils::FNV1a_64_Hash(const char* data, int len) {
+uint64_t QuicUtils::FNV1a_64_Hash(StringPiece data) {
static const uint64_t kOffset = UINT64_C(14695981039346656037);
static const uint64_t kPrime = UINT64_C(1099511628211);
- const uint8_t* octets = reinterpret_cast<const uint8_t*>(data);
+ const uint8_t* octets = reinterpret_cast<const uint8_t*>(data.data());
uint64_t hash = kOffset;
- for (int i = 0; i < len; ++i) {
+ for (size_t i = 0; i < data.length(); ++i) {
hash = hash ^ octets[i];
hash = hash * kPrime;
}
@@ -102,73 +95,35 @@ uint64_t QuicUtils::FNV1a_64_Hash(const char* data, int len) {
}
// static
-uint128 QuicUtils::FNV1a_128_Hash(const char* data, int len) {
- return FNV1a_128_Hash_Two(data, len, nullptr, 0);
+uint128 QuicUtils::FNV1a_128_Hash(StringPiece data) {
+ return FNV1a_128_Hash_Three(data, StringPiece(), StringPiece());
+}
+
+// static
+uint128 QuicUtils::FNV1a_128_Hash_Two(StringPiece data1, StringPiece data2) {
+ return FNV1a_128_Hash_Three(data1, data2, StringPiece());
}
// static
-uint128 QuicUtils::FNV1a_128_Hash_Two(const char* data1,
- int len1,
- const char* data2,
- int len2) {
+uint128 QuicUtils::FNV1a_128_Hash_Three(StringPiece data1,
+ StringPiece data2,
+ StringPiece data3) {
// The two constants are defined as part of the hash algorithm.
// see http://www.isthe.com/chongo/tech/comp/fnv/
// kOffset = 144066263297769815596495629667062367629
- const uint128 kOffset(UINT64_C(7809847782465536322),
- UINT64_C(7113472399480571277));
+ const uint128 kOffset =
+ MakeUint128(UINT64_C(7809847782465536322), UINT64_C(7113472399480571277));
- uint128 hash = IncrementalHash(kOffset, data1, len1);
- if (data2 == nullptr) {
+ uint128 hash = IncrementalHash(kOffset, data1);
+ if (data2.empty()) {
return hash;
}
- return IncrementalHash(hash, data2, len2);
-}
-// static
-bool QuicUtils::FindMutualTag(const QuicTagVector& our_tags_vector,
- const QuicTag* their_tags,
- size_t num_their_tags,
- Priority priority,
- QuicTag* out_result,
- size_t* out_index) {
- if (our_tags_vector.empty()) {
- return false;
- }
- const size_t num_our_tags = our_tags_vector.size();
- const QuicTag* our_tags = &our_tags_vector[0];
-
- size_t num_priority_tags, num_inferior_tags;
- const QuicTag* priority_tags;
- const QuicTag* inferior_tags;
- if (priority == LOCAL_PRIORITY) {
- num_priority_tags = num_our_tags;
- priority_tags = our_tags;
- num_inferior_tags = num_their_tags;
- inferior_tags = their_tags;
- } else {
- num_priority_tags = num_their_tags;
- priority_tags = their_tags;
- num_inferior_tags = num_our_tags;
- inferior_tags = our_tags;
- }
-
- for (size_t i = 0; i < num_priority_tags; i++) {
- for (size_t j = 0; j < num_inferior_tags; j++) {
- if (priority_tags[i] == inferior_tags[j]) {
- *out_result = priority_tags[i];
- if (out_index) {
- if (priority == LOCAL_PRIORITY) {
- *out_index = j;
- } else {
- *out_index = i;
- }
- }
- return true;
- }
- }
+ hash = IncrementalHash(hash, data2);
+ if (data3.empty()) {
+ return hash;
}
-
- return false;
+ return IncrementalHash(hash, data3);
}
// static
@@ -185,139 +140,6 @@ void QuicUtils::SerializeUint128Short(uint128 v, uint8_t* out) {
return #x;
// static
-const char* QuicUtils::StreamErrorToString(QuicRstStreamErrorCode error) {
- switch (error) {
- RETURN_STRING_LITERAL(QUIC_STREAM_NO_ERROR);
- RETURN_STRING_LITERAL(QUIC_STREAM_CONNECTION_ERROR);
- RETURN_STRING_LITERAL(QUIC_ERROR_PROCESSING_STREAM);
- RETURN_STRING_LITERAL(QUIC_MULTIPLE_TERMINATION_OFFSETS);
- RETURN_STRING_LITERAL(QUIC_BAD_APPLICATION_PAYLOAD);
- RETURN_STRING_LITERAL(QUIC_STREAM_PEER_GOING_AWAY);
- RETURN_STRING_LITERAL(QUIC_STREAM_CANCELLED);
- RETURN_STRING_LITERAL(QUIC_RST_ACKNOWLEDGEMENT);
- RETURN_STRING_LITERAL(QUIC_REFUSED_STREAM);
- RETURN_STRING_LITERAL(QUIC_STREAM_LAST_ERROR);
- RETURN_STRING_LITERAL(QUIC_INVALID_PROMISE_URL);
- RETURN_STRING_LITERAL(QUIC_UNAUTHORIZED_PROMISE_URL);
- RETURN_STRING_LITERAL(QUIC_DUPLICATE_PROMISE_URL);
- RETURN_STRING_LITERAL(QUIC_PROMISE_VARY_MISMATCH);
- RETURN_STRING_LITERAL(QUIC_INVALID_PROMISE_METHOD);
- RETURN_STRING_LITERAL(QUIC_PUSH_STREAM_TIMED_OUT);
- RETURN_STRING_LITERAL(QUIC_HEADERS_TOO_LARGE);
- }
- // Return a default value so that we return this when |error| doesn't match
- // any of the QuicRstStreamErrorCodes. This can happen when the RstStream
- // frame sent by the peer (attacker) has invalid error code.
- return "INVALID_RST_STREAM_ERROR_CODE";
-}
-
-// static
-const char* QuicUtils::ErrorToString(QuicErrorCode error) {
- switch (error) {
- RETURN_STRING_LITERAL(QUIC_NO_ERROR);
- RETURN_STRING_LITERAL(QUIC_INTERNAL_ERROR);
- RETURN_STRING_LITERAL(QUIC_STREAM_DATA_AFTER_TERMINATION);
- RETURN_STRING_LITERAL(QUIC_INVALID_PACKET_HEADER);
- RETURN_STRING_LITERAL(QUIC_INVALID_FRAME_DATA);
- RETURN_STRING_LITERAL(QUIC_MISSING_PAYLOAD);
- RETURN_STRING_LITERAL(QUIC_INVALID_FEC_DATA);
- RETURN_STRING_LITERAL(QUIC_INVALID_STREAM_DATA);
- RETURN_STRING_LITERAL(QUIC_OVERLAPPING_STREAM_DATA);
- RETURN_STRING_LITERAL(QUIC_UNENCRYPTED_STREAM_DATA);
- RETURN_STRING_LITERAL(QUIC_INVALID_RST_STREAM_DATA);
- RETURN_STRING_LITERAL(QUIC_INVALID_CONNECTION_CLOSE_DATA);
- RETURN_STRING_LITERAL(QUIC_INVALID_GOAWAY_DATA);
- RETURN_STRING_LITERAL(QUIC_INVALID_WINDOW_UPDATE_DATA);
- RETURN_STRING_LITERAL(QUIC_INVALID_BLOCKED_DATA);
- RETURN_STRING_LITERAL(QUIC_INVALID_STOP_WAITING_DATA);
- RETURN_STRING_LITERAL(QUIC_INVALID_PATH_CLOSE_DATA);
- RETURN_STRING_LITERAL(QUIC_INVALID_ACK_DATA);
- RETURN_STRING_LITERAL(QUIC_INVALID_VERSION_NEGOTIATION_PACKET);
- RETURN_STRING_LITERAL(QUIC_INVALID_PUBLIC_RST_PACKET);
- RETURN_STRING_LITERAL(QUIC_DECRYPTION_FAILURE);
- RETURN_STRING_LITERAL(QUIC_ENCRYPTION_FAILURE);
- RETURN_STRING_LITERAL(QUIC_PACKET_TOO_LARGE);
- RETURN_STRING_LITERAL(QUIC_PEER_GOING_AWAY);
- RETURN_STRING_LITERAL(QUIC_HANDSHAKE_FAILED);
- RETURN_STRING_LITERAL(QUIC_CRYPTO_TAGS_OUT_OF_ORDER);
- RETURN_STRING_LITERAL(QUIC_CRYPTO_TOO_MANY_ENTRIES);
- RETURN_STRING_LITERAL(QUIC_CRYPTO_TOO_MANY_REJECTS);
- RETURN_STRING_LITERAL(QUIC_CRYPTO_INVALID_VALUE_LENGTH)
- RETURN_STRING_LITERAL(QUIC_CRYPTO_MESSAGE_AFTER_HANDSHAKE_COMPLETE);
- RETURN_STRING_LITERAL(QUIC_CRYPTO_INTERNAL_ERROR);
- RETURN_STRING_LITERAL(QUIC_CRYPTO_VERSION_NOT_SUPPORTED);
- RETURN_STRING_LITERAL(QUIC_CRYPTO_HANDSHAKE_STATELESS_REJECT);
- RETURN_STRING_LITERAL(QUIC_CRYPTO_NO_SUPPORT);
- RETURN_STRING_LITERAL(QUIC_INVALID_CRYPTO_MESSAGE_TYPE);
- RETURN_STRING_LITERAL(QUIC_INVALID_CRYPTO_MESSAGE_PARAMETER);
- RETURN_STRING_LITERAL(QUIC_CRYPTO_MESSAGE_PARAMETER_NOT_FOUND);
- RETURN_STRING_LITERAL(QUIC_CRYPTO_MESSAGE_PARAMETER_NO_OVERLAP);
- RETURN_STRING_LITERAL(QUIC_CRYPTO_MESSAGE_INDEX_NOT_FOUND);
- RETURN_STRING_LITERAL(QUIC_UNSUPPORTED_PROOF_DEMAND);
- RETURN_STRING_LITERAL(QUIC_INVALID_STREAM_ID);
- RETURN_STRING_LITERAL(QUIC_INVALID_PRIORITY);
- RETURN_STRING_LITERAL(QUIC_TOO_MANY_OPEN_STREAMS);
- RETURN_STRING_LITERAL(QUIC_PUBLIC_RESET);
- RETURN_STRING_LITERAL(QUIC_INVALID_VERSION);
- RETURN_STRING_LITERAL(QUIC_INVALID_HEADER_ID);
- RETURN_STRING_LITERAL(QUIC_INVALID_NEGOTIATED_VALUE);
- RETURN_STRING_LITERAL(QUIC_DECOMPRESSION_FAILURE);
- RETURN_STRING_LITERAL(QUIC_NETWORK_IDLE_TIMEOUT);
- RETURN_STRING_LITERAL(QUIC_HANDSHAKE_TIMEOUT);
- RETURN_STRING_LITERAL(QUIC_ERROR_MIGRATING_ADDRESS);
- RETURN_STRING_LITERAL(QUIC_ERROR_MIGRATING_PORT);
- RETURN_STRING_LITERAL(QUIC_PACKET_WRITE_ERROR);
- RETURN_STRING_LITERAL(QUIC_PACKET_READ_ERROR);
- RETURN_STRING_LITERAL(QUIC_EMPTY_STREAM_FRAME_NO_FIN);
- RETURN_STRING_LITERAL(QUIC_INVALID_HEADERS_STREAM_DATA);
- RETURN_STRING_LITERAL(QUIC_FLOW_CONTROL_RECEIVED_TOO_MUCH_DATA);
- RETURN_STRING_LITERAL(QUIC_FLOW_CONTROL_SENT_TOO_MUCH_DATA);
- RETURN_STRING_LITERAL(QUIC_FLOW_CONTROL_INVALID_WINDOW);
- RETURN_STRING_LITERAL(QUIC_CONNECTION_IP_POOLED);
- RETURN_STRING_LITERAL(QUIC_PROOF_INVALID);
- RETURN_STRING_LITERAL(QUIC_CRYPTO_DUPLICATE_TAG);
- RETURN_STRING_LITERAL(QUIC_CRYPTO_ENCRYPTION_LEVEL_INCORRECT);
- RETURN_STRING_LITERAL(QUIC_CRYPTO_SERVER_CONFIG_EXPIRED);
- RETURN_STRING_LITERAL(QUIC_INVALID_CHANNEL_ID_SIGNATURE);
- RETURN_STRING_LITERAL(QUIC_CRYPTO_SYMMETRIC_KEY_SETUP_FAILED);
- RETURN_STRING_LITERAL(QUIC_CRYPTO_MESSAGE_WHILE_VALIDATING_CLIENT_HELLO);
- RETURN_STRING_LITERAL(QUIC_CRYPTO_UPDATE_BEFORE_HANDSHAKE_COMPLETE);
- RETURN_STRING_LITERAL(QUIC_VERSION_NEGOTIATION_MISMATCH);
- RETURN_STRING_LITERAL(QUIC_TOO_MANY_OUTSTANDING_SENT_PACKETS);
- RETURN_STRING_LITERAL(QUIC_TOO_MANY_OUTSTANDING_RECEIVED_PACKETS);
- RETURN_STRING_LITERAL(QUIC_CONNECTION_CANCELLED);
- RETURN_STRING_LITERAL(QUIC_BAD_PACKET_LOSS_RATE);
- RETURN_STRING_LITERAL(QUIC_PUBLIC_RESETS_POST_HANDSHAKE);
- RETURN_STRING_LITERAL(QUIC_TIMEOUTS_WITH_OPEN_STREAMS);
- RETURN_STRING_LITERAL(QUIC_FAILED_TO_SERIALIZE_PACKET);
- RETURN_STRING_LITERAL(QUIC_TOO_MANY_AVAILABLE_STREAMS);
- RETURN_STRING_LITERAL(QUIC_UNENCRYPTED_FEC_DATA);
- RETURN_STRING_LITERAL(QUIC_BAD_MULTIPATH_FLAG);
- RETURN_STRING_LITERAL(QUIC_IP_ADDRESS_CHANGED);
- RETURN_STRING_LITERAL(QUIC_CONNECTION_MIGRATION_NO_MIGRATABLE_STREAMS);
- RETURN_STRING_LITERAL(QUIC_CONNECTION_MIGRATION_TOO_MANY_CHANGES);
- RETURN_STRING_LITERAL(QUIC_CONNECTION_MIGRATION_NO_NEW_NETWORK);
- RETURN_STRING_LITERAL(QUIC_CONNECTION_MIGRATION_NON_MIGRATABLE_STREAM);
- RETURN_STRING_LITERAL(QUIC_TOO_MANY_RTOS);
- RETURN_STRING_LITERAL(QUIC_ATTEMPT_TO_SEND_UNENCRYPTED_STREAM_DATA);
- RETURN_STRING_LITERAL(QUIC_MAYBE_CORRUPTED_MEMORY);
- RETURN_STRING_LITERAL(QUIC_CRYPTO_CHLO_TOO_LARGE);
- RETURN_STRING_LITERAL(QUIC_MULTIPATH_PATH_DOES_NOT_EXIST);
- RETURN_STRING_LITERAL(QUIC_MULTIPATH_PATH_NOT_ACTIVE);
- RETURN_STRING_LITERAL(QUIC_TOO_MANY_FRAME_GAPS);
- RETURN_STRING_LITERAL(QUIC_STREAM_SEQUENCER_INVALID_STATE);
- RETURN_STRING_LITERAL(QUIC_TOO_MANY_SESSIONS_ON_SERVER);
- RETURN_STRING_LITERAL(QUIC_LAST_ERROR);
- // Intentionally have no default case, so we'll break the build
- // if we add errors and don't put them here.
- }
- // Return a default value so that we return this when |error| doesn't match
- // any of the QuicErrorCodes. This can happen when the ConnectionClose
- // frame sent by the peer (attacker) has invalid error code.
- return "INVALID_ERROR_CODE";
-}
-
-// static
const char* QuicUtils::EncryptionLevelToString(EncryptionLevel level) {
switch (level) {
RETURN_STRING_LITERAL(ENCRYPTION_NONE);
@@ -342,50 +164,6 @@ const char* QuicUtils::TransmissionTypeToString(TransmissionType type) {
return "INVALID_TRANSMISSION_TYPE";
}
-// static
-string QuicUtils::TagToString(QuicTag tag) {
- char chars[sizeof tag];
- bool ascii = true;
- const QuicTag orig_tag = tag;
-
- for (size_t i = 0; i < arraysize(chars); i++) {
- chars[i] = static_cast<char>(tag);
- if ((chars[i] == 0 || chars[i] == '\xff') && i == arraysize(chars) - 1) {
- chars[i] = ' ';
- }
- if (!isprint(static_cast<unsigned char>(chars[i]))) {
- ascii = false;
- break;
- }
- tag >>= 8;
- }
-
- if (ascii) {
- return string(chars, sizeof(chars));
- }
-
- return base::UintToString(orig_tag);
-}
-
-// static
-QuicTagVector QuicUtils::ParseQuicConnectionOptions(
- const std::string& connection_options) {
- QuicTagVector options;
- // Tokens are expected to be no more than 4 characters long, but we
- // handle overflow gracefully.
- for (const base::StringPiece& token :
- base::SplitStringPiece(connection_options, ",", base::TRIM_WHITESPACE,
- base::SPLIT_WANT_ALL)) {
- uint32_t option = 0;
- for (char token_char : base::Reversed(token)) {
- option <<= 8;
- option |= static_cast<unsigned char>(token_char);
- }
- options.push_back(option);
- }
- return options;
-}
-
string QuicUtils::PeerAddressChangeTypeToString(PeerAddressChangeType type) {
switch (type) {
RETURN_STRING_LITERAL(NO_CHANGE);
@@ -400,72 +178,6 @@ string QuicUtils::PeerAddressChangeTypeToString(PeerAddressChangeType type) {
}
// static
-void QuicUtils::DeleteFrames(QuicFrames* frames) {
- for (QuicFrame& frame : *frames) {
- switch (frame.type) {
- // Frames smaller than a pointer are inlined, so don't need to be deleted.
- case PADDING_FRAME:
- case MTU_DISCOVERY_FRAME:
- case PING_FRAME:
- break;
- case STREAM_FRAME:
- delete frame.stream_frame;
- break;
- case ACK_FRAME:
- delete frame.ack_frame;
- break;
- case STOP_WAITING_FRAME:
- delete frame.stop_waiting_frame;
- break;
- case RST_STREAM_FRAME:
- delete frame.rst_stream_frame;
- break;
- case CONNECTION_CLOSE_FRAME:
- delete frame.connection_close_frame;
- break;
- case GOAWAY_FRAME:
- delete frame.goaway_frame;
- break;
- case BLOCKED_FRAME:
- delete frame.blocked_frame;
- break;
- case WINDOW_UPDATE_FRAME:
- delete frame.window_update_frame;
- break;
- case PATH_CLOSE_FRAME:
- delete frame.path_close_frame;
- break;
- case NUM_FRAME_TYPES:
- DCHECK(false) << "Cannot delete type: " << frame.type;
- }
- }
- frames->clear();
-}
-
-// static
-void QuicUtils::RemoveFramesForStream(QuicFrames* frames,
- QuicStreamId stream_id) {
- QuicFrames::iterator it = frames->begin();
- while (it != frames->end()) {
- if (it->type != STREAM_FRAME || it->stream_frame->stream_id != stream_id) {
- ++it;
- continue;
- }
- delete it->stream_frame;
- it = frames->erase(it);
- }
-}
-
-// static
-void QuicUtils::ClearSerializedPacket(SerializedPacket* serialized_packet) {
- if (!serialized_packet->retransmittable_frames.empty()) {
- DeleteFrames(&serialized_packet->retransmittable_frames);
- }
- serialized_packet->encrypted_buffer = nullptr;
- serialized_packet->encrypted_length = 0;
-}
-
-// static
uint64_t QuicUtils::PackPathIdAndPacketNumber(QuicPathId path_id,
QuicPacketNumber packet_number) {
// Setting the nonce below relies on QuicPathId and QuicPacketNumber being
@@ -481,27 +193,20 @@ uint64_t QuicUtils::PackPathIdAndPacketNumber(QuicPathId path_id,
}
// static
-char* QuicUtils::CopyBuffer(const SerializedPacket& packet) {
- char* dst_buffer = new char[packet.encrypted_length];
- memcpy(dst_buffer, packet.encrypted_buffer, packet.encrypted_length);
- return dst_buffer;
-}
-
-// static
PeerAddressChangeType QuicUtils::DetermineAddressChangeType(
- const IPEndPoint& old_address,
- const IPEndPoint& new_address) {
- if (!IsInitializedIPEndPoint(old_address) ||
- !IsInitializedIPEndPoint(new_address) || old_address == new_address) {
+ const QuicSocketAddress& old_address,
+ const QuicSocketAddress& new_address) {
+ if (!old_address.IsInitialized() || !new_address.IsInitialized() ||
+ old_address == new_address) {
return NO_CHANGE;
}
- if (old_address.address() == new_address.address()) {
+ if (old_address.host() == new_address.host()) {
return PORT_CHANGE;
}
- bool old_ip_is_ipv4 = old_address.address().IsIPv4();
- bool migrating_ip_is_ipv4 = new_address.address().IsIPv4();
+ bool old_ip_is_ipv4 = old_address.host().IsIPv4() ? true : false;
+ bool migrating_ip_is_ipv4 = new_address.host().IsIPv4() ? true : false;
if (old_ip_is_ipv4 && !migrating_ip_is_ipv4) {
return IPV4_TO_IPV6_CHANGE;
}
@@ -510,8 +215,8 @@ PeerAddressChangeType QuicUtils::DetermineAddressChangeType(
return migrating_ip_is_ipv4 ? IPV6_TO_IPV4_CHANGE : IPV6_TO_IPV6_CHANGE;
}
- if (IPAddressMatchesPrefix(old_address.address(), new_address.address(),
- 24)) {
+ const int kSubnetMaskLength = 24;
+ if (old_address.host().InSameSubnet(new_address.host(), kSubnetMaskLength)) {
// Subnet part does not change (here, we use /24), which is considered to be
// caused by NATs.
return IPV4_SUBNET_CHANGE;
@@ -520,60 +225,4 @@ PeerAddressChangeType QuicUtils::DetermineAddressChangeType(
return IPV4_TO_IPV4_CHANGE;
}
-string QuicUtils::HexEncode(const char* data, size_t length) {
- return HexEncode(StringPiece(data, length));
-}
-
-string QuicUtils::HexEncode(StringPiece data) {
- return ::base::HexEncode(data.data(), data.size());
-}
-
-string QuicUtils::HexDecode(const char* data, size_t length) {
- return HexDecode(StringPiece(data, length));
-}
-
-string QuicUtils::HexDecode(StringPiece data) {
- if (data.empty())
- return "";
- std::vector<uint8_t> v;
- if (!base::HexStringToBytes(data.as_string(), &v))
- return "";
- string out;
- if (!v.empty())
- out.assign(reinterpret_cast<const char*>(&v[0]), v.size());
- return out;
-}
-
-string QuicUtils::HexDump(StringPiece binary_input) {
- int offset = 0;
- const int kBytesPerLine = 16; // Max bytes dumped per line
- const char* buf = binary_input.data();
- int bytes_remaining = binary_input.size();
- string s; // our output
- const char* p = buf;
- while (bytes_remaining > 0) {
- const int line_bytes = std::min(bytes_remaining, kBytesPerLine);
- base::StringAppendF(&s, "0x%04x: ", offset); // Do the line header
- for (int i = 0; i < kBytesPerLine; ++i) {
- if (i < line_bytes) {
- base::StringAppendF(&s, "%02x", static_cast<unsigned char>(p[i]));
- } else {
- s += " "; // two-space filler instead of two-space hex digits
- }
- if (i % 2)
- s += ' ';
- }
- s += ' ';
- for (int i = 0; i < line_bytes; ++i) { // Do the ASCII dump
- s += (p[i] > 32 && p[i] < 127) ? p[i] : '.';
- }
-
- bytes_remaining -= line_bytes;
- offset += line_bytes;
- p += line_bytes;
- s += '\n';
- }
- return s;
-}
-
} // namespace net
diff --git a/chromium/net/quic/core/quic_utils.h b/chromium/net/quic/core/quic_utils.h
index 66b338ab751..c32e8657dde 100644
--- a/chromium/net/quic/core/quic_utils.h
+++ b/chromium/net/quic/core/quic_utils.h
@@ -1,160 +1,74 @@
// Copyright (c) 2012 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.
-//
-// Some helpers for quic.
#ifndef NET_QUIC_CORE_QUIC_UTILS_H_
#define NET_QUIC_CORE_QUIC_UTILS_H_
-#include <stddef.h>
-#include <stdint.h>
-
+#include <cstddef>
+#include <cstdint>
#include <string>
#include "base/macros.h"
#include "base/strings/string_piece.h"
#include "net/base/int128.h"
-#include "net/base/net_export.h"
-#include "net/quic/core/quic_protocol.h"
-
-#ifdef _MSC_VER
-// MSVC 2013 and prior don't have alignof or aligned(); they have __alignof and
-// a __declspec instead.
-#define QUIC_ALIGN_OF __alignof
-#define QUIC_ALIGNED(X) __declspec(align(X))
-#else
-#define QUIC_ALIGN_OF alignof
-#define QUIC_ALIGNED(X) __attribute__((aligned(X)))
-#endif // _MSC_VER
+#include "net/quic/core/quic_error_codes.h"
+#include "net/quic/core/quic_types.h"
+#include "net/quic/platform/api/quic_export.h"
+#include "net/quic/platform/api/quic_socket_address.h"
namespace net {
-class NET_EXPORT_PRIVATE QuicUtils {
+class QUIC_EXPORT_PRIVATE QuicUtils {
public:
- enum Priority {
- LOCAL_PRIORITY,
- PEER_PRIORITY,
- };
-
// Returns the 64 bit FNV1a hash of the data. See
// http://www.isthe.com/chongo/tech/comp/fnv/index.html#FNV-param
- static uint64_t FNV1a_64_Hash(const char* data, int len);
+ static uint64_t FNV1a_64_Hash(base::StringPiece data);
- // returns the 128 bit FNV1a hash of the data. See
+ // Returns the 128 bit FNV1a hash of the data. See
// http://www.isthe.com/chongo/tech/comp/fnv/index.html#FNV-param
- static uint128 FNV1a_128_Hash(const char* data1, int len1);
+ static uint128 FNV1a_128_Hash(base::StringPiece data);
- // returns the 128 bit FNV1a hash of the two sequences of data. See
+ // Returns the 128 bit FNV1a hash of the two sequences of data. See
// http://www.isthe.com/chongo/tech/comp/fnv/index.html#FNV-param
- static uint128 FNV1a_128_Hash_Two(const char* data1,
- int len1,
- const char* data2,
- int len2);
-
- // FindMutualTag sets |out_result| to the first tag in the priority list that
- // is also in the other list and returns true. If there is no intersection it
- // returns false.
- //
- // Which list has priority is determined by |priority|.
- //
- // If |out_index| is non-nullptr and a match is found then the index of that
- // match in |their_tags| is written to |out_index|.
- static bool FindMutualTag(const QuicTagVector& our_tags,
- const QuicTag* their_tags,
- size_t num_their_tags,
- Priority priority,
- QuicTag* out_result,
- size_t* out_index);
+ static uint128 FNV1a_128_Hash_Two(base::StringPiece data1,
+ base::StringPiece data2);
+
+ // Returns the 128 bit FNV1a hash of the three sequences of data. See
+ // http://www.isthe.com/chongo/tech/comp/fnv/index.html#FNV-param
+ static uint128 FNV1a_128_Hash_Three(base::StringPiece data1,
+ base::StringPiece data2,
+ base::StringPiece data3);
// SerializeUint128 writes the first 96 bits of |v| in little-endian form
// to |out|.
static void SerializeUint128Short(uint128 v, uint8_t* out);
- // Returns the name of the QuicRstStreamErrorCode as a char*
- static const char* StreamErrorToString(QuicRstStreamErrorCode error);
-
- // Returns the name of the QuicErrorCode as a char*
- static const char* ErrorToString(QuicErrorCode error);
-
// Returns the level of encryption as a char*
static const char* EncryptionLevelToString(EncryptionLevel level);
// Returns TransmissionType as a char*
static const char* TransmissionTypeToString(TransmissionType type);
- // TagToString is a utility function for pretty-printing handshake messages
- // that converts a tag to a string. It will try to maintain the human friendly
- // name if possible (i.e. kABCD -> "ABCD"), or will just treat it as a number
- // if not.
- static std::string TagToString(QuicTag tag);
-
- // Returns the list of QUIC tags represented by the comma separated
- // string in |connection_options|.
- static QuicTagVector ParseQuicConnectionOptions(
- const std::string& connection_options);
-
// Returns PeerAddressChangeType as a std::string.
static std::string PeerAddressChangeTypeToString(PeerAddressChangeType type);
- static char* AsChars(unsigned char* data) {
- return reinterpret_cast<char*>(data);
- }
-
- // Deletes all the sub-frames contained in |frames|.
- static void DeleteFrames(QuicFrames* frames);
-
- // Deletes all the QuicStreamFrames for the specified |stream_id|.
- static void RemoveFramesForStream(QuicFrames* frames, QuicStreamId stream_id);
-
- // Deletes and clears all the frames and the packet from serialized packet.
- static void ClearSerializedPacket(SerializedPacket* serialized_packet);
-
// Returns a packed representation of |path_id| and |packet_number| in which
// the highest byte is set to |path_id| and the lower 7 bytes are the lower
// 7 bytes of |packet_number|.
static uint64_t PackPathIdAndPacketNumber(QuicPathId path_id,
QuicPacketNumber packet_number);
- // Allocates a new char[] of size |packet.encrypted_length| and copies in
- // |packet.encrypted_buffer|.
- static char* CopyBuffer(const SerializedPacket& packet);
-
// Determines and returns change type of address change from |old_address| to
// |new_address|.
static PeerAddressChangeType DetermineAddressChangeType(
- const IPEndPoint& old_address,
- const IPEndPoint& new_address);
-
- // This converts 'num' bytes of binary to a 2*'num'-character hexadecimal
- // representation. Return value: 2*'num' characters of ascii std::string.
- static std::string HexEncode(const char* data, size_t length);
- static std::string HexEncode(base::StringPiece data);
-
- // This converts 2*'num' hexadecimal characters to 'num' binary data.
- // Return value: 'num' bytes of binary data (via the 'to' argument).
- static std::string HexDecode(const char* data, size_t length);
- static std::string HexDecode(base::StringPiece data);
-
- // Returns a std::string containing hex and ASCII representations of |binary|,
- // side-by-side in the style of hexdump. Non-printable characters will be
- // printed as '.' in the ASCII output.
- // "0x0000: 4865 6c6c 6f2c 2051 5549 4321 0102 0304 Hello,.QUIC!...."
- static std::string HexDump(base::StringPiece binary_data);
+ const QuicSocketAddress& old_address,
+ const QuicSocketAddress& new_address);
private:
DISALLOW_COPY_AND_ASSIGN(QuicUtils);
};
-// Utility function that returns an QuicIOVector object wrapped around |str|.
-// |str|'s data is stored in |iov|.
-inline QuicIOVector MakeIOVector(base::StringPiece str, struct iovec* iov) {
- iov->iov_base = const_cast<char*>(str.data());
- iov->iov_len = static_cast<size_t>(str.size());
- QuicIOVector quic_iov(iov, 1, str.size());
- return quic_iov;
-}
-
} // namespace net
#endif // NET_QUIC_CORE_QUIC_UTILS_H_
diff --git a/chromium/net/quic/core/quic_utils_test.cc b/chromium/net/quic/core/quic_utils_test.cc
index ca3df9bfbb8..6d0be398b07 100644
--- a/chromium/net/quic/core/quic_utils_test.cc
+++ b/chromium/net/quic/core/quic_utils_test.cc
@@ -5,7 +5,6 @@
#include "net/quic/core/quic_utils.h"
#include "net/quic/core/crypto/crypto_protocol.h"
-#include "net/quic/core/quic_flags.h"
#include "testing/gtest/include/gtest/gtest.h"
using base::StringPiece;
@@ -15,94 +14,61 @@ namespace net {
namespace test {
namespace {
-TEST(QuicUtilsTest, StreamErrorToString) {
- EXPECT_STREQ("QUIC_BAD_APPLICATION_PAYLOAD",
- QuicUtils::StreamErrorToString(QUIC_BAD_APPLICATION_PAYLOAD));
-}
-
-TEST(QuicUtilsTest, ErrorToString) {
- EXPECT_STREQ("QUIC_NO_ERROR", QuicUtils::ErrorToString(QUIC_NO_ERROR));
-}
-
-TEST(QuicUtilsTest, TagToString) {
- EXPECT_EQ("SCFG", QuicUtils::TagToString(kSCFG));
- EXPECT_EQ("SNO ", QuicUtils::TagToString(kServerNonceTag));
- EXPECT_EQ("CRT ", QuicUtils::TagToString(kCertificateTag));
- EXPECT_EQ("CHLO", QuicUtils::TagToString(MakeQuicTag('C', 'H', 'L', 'O')));
- // A tag that contains a non-printing character will be printed as a decimal
- // number.
- EXPECT_EQ("525092931",
- QuicUtils::TagToString(MakeQuicTag('C', 'H', 'L', '\x1f')));
-}
-
-TEST(QuicUtilsTest, ParseQuicConnectionOptions) {
- QuicTagVector empty_options = QuicUtils::ParseQuicConnectionOptions("");
- EXPECT_EQ(0ul, empty_options.size());
-
- QuicTagVector parsed_options =
- QuicUtils::ParseQuicConnectionOptions("TIMER,TBBR,REJ");
- QuicTagVector expected_options;
- expected_options.push_back(kTIME);
- expected_options.push_back(kTBBR);
- expected_options.push_back(kREJ);
- EXPECT_EQ(expected_options, parsed_options);
-}
-
TEST(QuicUtilsTest, DetermineAddressChangeType) {
const string kIPv4String1 = "1.2.3.4";
const string kIPv4String2 = "1.2.3.5";
const string kIPv4String3 = "1.1.3.5";
const string kIPv6String1 = "2001:700:300:1800::f";
const string kIPv6String2 = "2001:700:300:1800:1:1:1:f";
- IPEndPoint old_address;
- IPEndPoint new_address;
- IPAddress address;
+ QuicSocketAddress old_address;
+ QuicSocketAddress new_address;
+ QuicIpAddress address;
EXPECT_EQ(NO_CHANGE,
QuicUtils::DetermineAddressChangeType(old_address, new_address));
- ASSERT_TRUE(address.AssignFromIPLiteral(kIPv4String1));
- old_address = IPEndPoint(address, 1234);
+ ASSERT_TRUE(address.FromString(kIPv4String1));
+ old_address = QuicSocketAddress(address, 1234);
EXPECT_EQ(NO_CHANGE,
QuicUtils::DetermineAddressChangeType(old_address, new_address));
- new_address = IPEndPoint(address, 1234);
+ new_address = QuicSocketAddress(address, 1234);
EXPECT_EQ(NO_CHANGE,
QuicUtils::DetermineAddressChangeType(old_address, new_address));
- new_address = IPEndPoint(address, 5678);
+ new_address = QuicSocketAddress(address, 5678);
EXPECT_EQ(PORT_CHANGE,
QuicUtils::DetermineAddressChangeType(old_address, new_address));
- ASSERT_TRUE(address.AssignFromIPLiteral(kIPv6String1));
- old_address = IPEndPoint(address, 1234);
- new_address = IPEndPoint(address, 5678);
+ ASSERT_TRUE(address.FromString(kIPv6String1));
+ old_address = QuicSocketAddress(address, 1234);
+ new_address = QuicSocketAddress(address, 5678);
EXPECT_EQ(PORT_CHANGE,
QuicUtils::DetermineAddressChangeType(old_address, new_address));
- ASSERT_TRUE(address.AssignFromIPLiteral(kIPv4String1));
- old_address = IPEndPoint(address, 1234);
- ASSERT_TRUE(address.AssignFromIPLiteral(kIPv6String1));
- new_address = IPEndPoint(address, 1234);
+ ASSERT_TRUE(address.FromString(kIPv4String1));
+ old_address = QuicSocketAddress(address, 1234);
+ ASSERT_TRUE(address.FromString(kIPv6String1));
+ new_address = QuicSocketAddress(address, 1234);
EXPECT_EQ(IPV4_TO_IPV6_CHANGE,
QuicUtils::DetermineAddressChangeType(old_address, new_address));
- old_address = IPEndPoint(address, 1234);
- ASSERT_TRUE(address.AssignFromIPLiteral(kIPv4String1));
- new_address = IPEndPoint(address, 1234);
+ old_address = QuicSocketAddress(address, 1234);
+ ASSERT_TRUE(address.FromString(kIPv4String1));
+ new_address = QuicSocketAddress(address, 1234);
EXPECT_EQ(IPV6_TO_IPV4_CHANGE,
QuicUtils::DetermineAddressChangeType(old_address, new_address));
- ASSERT_TRUE(address.AssignFromIPLiteral(kIPv6String2));
- new_address = IPEndPoint(address, 1234);
+ ASSERT_TRUE(address.FromString(kIPv6String2));
+ new_address = QuicSocketAddress(address, 1234);
EXPECT_EQ(IPV6_TO_IPV6_CHANGE,
QuicUtils::DetermineAddressChangeType(old_address, new_address));
- ASSERT_TRUE(address.AssignFromIPLiteral(kIPv4String1));
- old_address = IPEndPoint(address, 1234);
- ASSERT_TRUE(address.AssignFromIPLiteral(kIPv4String2));
- new_address = IPEndPoint(address, 1234);
+ ASSERT_TRUE(address.FromString(kIPv4String1));
+ old_address = QuicSocketAddress(address, 1234);
+ ASSERT_TRUE(address.FromString(kIPv4String2));
+ new_address = QuicSocketAddress(address, 1234);
EXPECT_EQ(IPV4_SUBNET_CHANGE,
QuicUtils::DetermineAddressChangeType(old_address, new_address));
- ASSERT_TRUE(address.AssignFromIPLiteral(kIPv4String3));
- new_address = IPEndPoint(address, 1234);
+ ASSERT_TRUE(address.FromString(kIPv4String3));
+ new_address = QuicSocketAddress(address, 1234);
EXPECT_EQ(IPV4_TO_IPV4_CHANGE,
QuicUtils::DetermineAddressChangeType(old_address, new_address));
}
@@ -112,12 +78,12 @@ uint128 IncrementalHashReference(const void* data, size_t len) {
// see http://www.isthe.com/chongo/tech/comp/fnv/
// hash = 144066263297769815596495629667062367629
uint128 hash =
- uint128(UINT64_C(7809847782465536322), UINT64_C(7113472399480571277));
+ MakeUint128(UINT64_C(7809847782465536322), UINT64_C(7113472399480571277));
// kPrime = 309485009821345068724781371
- const uint128 kPrime(16777216, 315);
+ const uint128 kPrime = MakeUint128(16777216, 315);
const uint8_t* octets = reinterpret_cast<const uint8_t*>(data);
for (size_t i = 0; i < len; ++i) {
- hash = hash ^ uint128(0, octets[i]);
+ hash = hash ^ MakeUint128(0, octets[i]);
hash = hash * kPrime;
}
return hash;
@@ -129,29 +95,8 @@ TEST(QuicUtilsHashTest, ReferenceTest) {
data[i] = i % 255;
}
EXPECT_EQ(IncrementalHashReference(data.data(), data.size()),
- QuicUtils::FNV1a_128_Hash(
- reinterpret_cast<const char*>(data.data()), data.size()));
-}
-
-TEST(QuicUtilsTest, HexDump) {
- // Verify output of the HexDump method is as expected.
- char packet[] = {
- 0x48, 0x65, 0x6c, 0x6c, 0x6f, 0x2c, 0x20, 0x51, 0x55, 0x49, 0x43, 0x21,
- 0x20, 0x54, 0x68, 0x69, 0x73, 0x20, 0x73, 0x74, 0x72, 0x69, 0x6e, 0x67,
- 0x20, 0x73, 0x68, 0x6f, 0x75, 0x6c, 0x64, 0x20, 0x62, 0x65, 0x20, 0x6c,
- 0x6f, 0x6e, 0x67, 0x20, 0x65, 0x6e, 0x6f, 0x75, 0x67, 0x68, 0x20, 0x74,
- 0x6f, 0x20, 0x73, 0x70, 0x61, 0x6e, 0x20, 0x6d, 0x75, 0x6c, 0x74, 0x69,
- 0x70, 0x6c, 0x65, 0x20, 0x6c, 0x69, 0x6e, 0x65, 0x73, 0x20, 0x6f, 0x66,
- 0x20, 0x6f, 0x75, 0x74, 0x70, 0x75, 0x74, 0x2e, 0x01, 0x02, 0x03, 0x00,
- };
- EXPECT_EQ(
- QuicUtils::HexDump(packet),
- "0x0000: 4865 6c6c 6f2c 2051 5549 4321 2054 6869 Hello,.QUIC!.Thi\n"
- "0x0010: 7320 7374 7269 6e67 2073 686f 756c 6420 s.string.should.\n"
- "0x0020: 6265 206c 6f6e 6720 656e 6f75 6768 2074 be.long.enough.t\n"
- "0x0030: 6f20 7370 616e 206d 756c 7469 706c 6520 o.span.multiple.\n"
- "0x0040: 6c69 6e65 7320 6f66 206f 7574 7075 742e lines.of.output.\n"
- "0x0050: 0102 03 ...\n");
+ QuicUtils::FNV1a_128_Hash(StringPiece(
+ reinterpret_cast<const char*>(data.data()), data.size())));
}
} // namespace
diff --git a/chromium/net/quic/core/quic_version_manager.cc b/chromium/net/quic/core/quic_version_manager.cc
new file mode 100644
index 00000000000..f266f0d098b
--- /dev/null
+++ b/chromium/net/quic/core/quic_version_manager.cc
@@ -0,0 +1,45 @@
+// Copyright (c) 2016 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.
+
+#include "net/quic/core/quic_version_manager.h"
+
+#include "net/quic/core/quic_flags.h"
+#include "net/quic/core/quic_versions.h"
+
+namespace net {
+
+QuicVersionManager::QuicVersionManager(QuicVersionVector supported_versions)
+ : enable_version_37_(FLAGS_quic_reloadable_flag_quic_enable_version_37),
+ enable_version_36_(FLAGS_quic_reloadable_flag_quic_enable_version_36_v3),
+ disable_version_34_(FLAGS_quic_reloadable_flag_quic_disable_version_34),
+ allowed_supported_versions_(supported_versions),
+ filtered_supported_versions_(
+ FilterSupportedVersions(supported_versions)) {}
+
+QuicVersionManager::~QuicVersionManager() {}
+
+const QuicVersionVector& QuicVersionManager::GetSupportedVersions() {
+ MaybeRefilterSupportedVersions();
+ return filtered_supported_versions_;
+}
+
+void QuicVersionManager::MaybeRefilterSupportedVersions() {
+ if (enable_version_37_ != FLAGS_quic_reloadable_flag_quic_enable_version_37 ||
+ enable_version_36_ !=
+ FLAGS_quic_reloadable_flag_quic_enable_version_36_v3 ||
+ disable_version_34_ !=
+ FLAGS_quic_reloadable_flag_quic_disable_version_34) {
+ enable_version_37_ = FLAGS_quic_reloadable_flag_quic_enable_version_37;
+ enable_version_36_ = FLAGS_quic_reloadable_flag_quic_enable_version_36_v3;
+ disable_version_34_ = FLAGS_quic_reloadable_flag_quic_disable_version_34;
+ RefilterSupportedVersions();
+ }
+}
+
+void QuicVersionManager::RefilterSupportedVersions() {
+ filtered_supported_versions_ =
+ FilterSupportedVersions(allowed_supported_versions_);
+}
+
+} // namespace net
diff --git a/chromium/net/quic/core/quic_version_manager.h b/chromium/net/quic/core/quic_version_manager.h
new file mode 100644
index 00000000000..89b8c79694d
--- /dev/null
+++ b/chromium/net/quic/core/quic_version_manager.h
@@ -0,0 +1,49 @@
+// Copyright (c) 2016 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.
+
+#ifndef NET_QUIC_CORE_QUIC_VERSION_MANAGER_H_
+#define NET_QUIC_CORE_QUIC_VERSION_MANAGER_H_
+
+#include "net/quic/core/quic_versions.h"
+#include "net/quic/platform/api/quic_export.h"
+
+namespace net {
+
+// Used to generate filtered supported versions based on flags.
+class QUIC_EXPORT_PRIVATE QuicVersionManager {
+ public:
+ explicit QuicVersionManager(QuicVersionVector supported_versions);
+ virtual ~QuicVersionManager();
+
+ // Returns currently supported QUIC versions.
+ const QuicVersionVector& GetSupportedVersions();
+
+ protected:
+ // Maybe refilter filtered_supported_versions_ based on flags.
+ void MaybeRefilterSupportedVersions();
+
+ // Refilters filtered_supported_versions_.
+ virtual void RefilterSupportedVersions();
+
+ const QuicVersionVector& filtered_supported_versions() const {
+ return filtered_supported_versions_;
+ }
+
+ private:
+ // FLAGS_quic_reloadable_flag_quic_enable_version_37
+ bool enable_version_37_;
+ // FLAGS_quic_reloadable_flag_quic_enable_version_36_v3
+ bool enable_version_36_;
+ // FLAGS_quic_reloadable_flag_quic_disable_version_34
+ bool disable_version_34_;
+ // The list of versions that may be supported.
+ QuicVersionVector allowed_supported_versions_;
+ // This vector contains QUIC versions which are currently supported based on
+ // flags.
+ QuicVersionVector filtered_supported_versions_;
+};
+
+} // namespace net
+
+#endif // NET_QUIC_CORE_QUIC_VERSION_MANAGER_H_
diff --git a/chromium/net/quic/core/quic_version_manager_test.cc b/chromium/net/quic/core/quic_version_manager_test.cc
new file mode 100644
index 00000000000..52ec489ae9c
--- /dev/null
+++ b/chromium/net/quic/core/quic_version_manager_test.cc
@@ -0,0 +1,54 @@
+// Copyright (c) 2016 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.
+
+#include "net/quic/core/quic_version_manager.h"
+
+#include "net/quic/core/quic_flags.h"
+#include "net/quic/core/quic_versions.h"
+#include "net/quic/test_tools/quic_test_utils.h"
+#include "testing/gmock/include/gmock/gmock.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace net {
+namespace test {
+namespace {
+
+TEST(QuicVersionManagerTest, QuicVersionManager) {
+ QuicFlagSaver flags;
+ FLAGS_quic_reloadable_flag_quic_enable_version_36_v3 = false;
+ FLAGS_quic_reloadable_flag_quic_enable_version_37 = false;
+ FLAGS_quic_reloadable_flag_quic_disable_version_34 = false;
+ QuicVersionManager manager(AllSupportedVersions());
+ EXPECT_EQ(FilterSupportedVersions(AllSupportedVersions()),
+ manager.GetSupportedVersions());
+
+ FLAGS_quic_reloadable_flag_quic_enable_version_36_v3 = true;
+ EXPECT_EQ(FilterSupportedVersions(AllSupportedVersions()),
+ manager.GetSupportedVersions());
+ ASSERT_EQ(3u, manager.GetSupportedVersions().size());
+ EXPECT_EQ(QUIC_VERSION_36, manager.GetSupportedVersions()[0]);
+ EXPECT_EQ(QUIC_VERSION_35, manager.GetSupportedVersions()[1]);
+ EXPECT_EQ(QUIC_VERSION_34, manager.GetSupportedVersions()[2]);
+
+ FLAGS_quic_reloadable_flag_quic_enable_version_37 = true;
+ EXPECT_EQ(FilterSupportedVersions(AllSupportedVersions()),
+ manager.GetSupportedVersions());
+ ASSERT_EQ(4u, manager.GetSupportedVersions().size());
+ EXPECT_EQ(QUIC_VERSION_37, manager.GetSupportedVersions()[0]);
+ EXPECT_EQ(QUIC_VERSION_36, manager.GetSupportedVersions()[1]);
+ EXPECT_EQ(QUIC_VERSION_35, manager.GetSupportedVersions()[2]);
+ EXPECT_EQ(QUIC_VERSION_34, manager.GetSupportedVersions()[3]);
+
+ FLAGS_quic_reloadable_flag_quic_disable_version_34 = true;
+ EXPECT_EQ(FilterSupportedVersions(AllSupportedVersions()),
+ manager.GetSupportedVersions());
+ ASSERT_EQ(3u, manager.GetSupportedVersions().size());
+ EXPECT_EQ(QUIC_VERSION_37, manager.GetSupportedVersions()[0]);
+ EXPECT_EQ(QUIC_VERSION_36, manager.GetSupportedVersions()[1]);
+ EXPECT_EQ(QUIC_VERSION_35, manager.GetSupportedVersions()[2]);
+}
+
+} // namespace
+} // namespace test
+} // namespace net
diff --git a/chromium/net/quic/core/quic_versions.cc b/chromium/net/quic/core/quic_versions.cc
new file mode 100644
index 00000000000..0eb2b6d5c4b
--- /dev/null
+++ b/chromium/net/quic/core/quic_versions.cc
@@ -0,0 +1,123 @@
+// Copyright (c) 2012 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.
+
+#include "net/quic/core/quic_versions.h"
+
+#include "base/memory/ptr_util.h"
+#include "base/strings/string_piece.h"
+#include "net/quic/core/quic_error_codes.h"
+#include "net/quic/core/quic_flags.h"
+#include "net/quic/core/quic_tag.h"
+#include "net/quic/core/quic_types.h"
+#include "net/quic/platform/api/quic_logging.h"
+
+using base::StringPiece;
+using std::string;
+
+namespace net {
+
+QuicVersionVector AllSupportedVersions() {
+ QuicVersionVector supported_versions;
+ for (size_t i = 0; i < arraysize(kSupportedQuicVersions); ++i) {
+ supported_versions.push_back(kSupportedQuicVersions[i]);
+ }
+ return supported_versions;
+}
+
+QuicVersionVector CurrentSupportedVersions() {
+ return FilterSupportedVersions(AllSupportedVersions());
+}
+
+QuicVersionVector FilterSupportedVersions(QuicVersionVector versions) {
+ QuicVersionVector filtered_versions(versions.size());
+ filtered_versions.clear(); // Guaranteed by spec not to change capacity.
+ for (QuicVersion version : versions) {
+ if (version == QUIC_VERSION_37) {
+ if (FLAGS_quic_reloadable_flag_quic_enable_version_37 &&
+ FLAGS_quic_reloadable_flag_quic_enable_version_36_v3) {
+ filtered_versions.push_back(version);
+ }
+ } else if (version == QUIC_VERSION_36) {
+ if (FLAGS_quic_reloadable_flag_quic_enable_version_36_v3) {
+ filtered_versions.push_back(version);
+ }
+ } else if (version == QUIC_VERSION_34) {
+ if (!FLAGS_quic_reloadable_flag_quic_disable_version_34) {
+ filtered_versions.push_back(version);
+ }
+ } else {
+ filtered_versions.push_back(version);
+ }
+ }
+ return filtered_versions;
+}
+
+QuicVersionVector VersionOfIndex(const QuicVersionVector& versions, int index) {
+ QuicVersionVector version;
+ int version_count = versions.size();
+ if (index >= 0 && index < version_count) {
+ version.push_back(versions[index]);
+ } else {
+ version.push_back(QUIC_VERSION_UNSUPPORTED);
+ }
+ return version;
+}
+
+QuicTag QuicVersionToQuicTag(const QuicVersion version) {
+ switch (version) {
+ case QUIC_VERSION_34:
+ return MakeQuicTag('Q', '0', '3', '4');
+ case QUIC_VERSION_35:
+ return MakeQuicTag('Q', '0', '3', '5');
+ case QUIC_VERSION_36:
+ return MakeQuicTag('Q', '0', '3', '6');
+ case QUIC_VERSION_37:
+ return MakeQuicTag('Q', '0', '3', '7');
+ default:
+ // This shold be an ERROR because we should never attempt to convert an
+ // invalid QuicVersion to be written to the wire.
+ QUIC_LOG(ERROR) << "Unsupported QuicVersion: " << version;
+ return 0;
+ }
+}
+
+QuicVersion QuicTagToQuicVersion(const QuicTag version_tag) {
+ for (size_t i = 0; i < arraysize(kSupportedQuicVersions); ++i) {
+ if (version_tag == QuicVersionToQuicTag(kSupportedQuicVersions[i])) {
+ return kSupportedQuicVersions[i];
+ }
+ }
+ // Reading from the client so this should not be considered an ERROR.
+ QUIC_DLOG(INFO) << "Unsupported QuicTag version: "
+ << QuicTagToString(version_tag);
+ return QUIC_VERSION_UNSUPPORTED;
+}
+
+#define RETURN_STRING_LITERAL(x) \
+ case x: \
+ return #x
+
+string QuicVersionToString(const QuicVersion version) {
+ switch (version) {
+ RETURN_STRING_LITERAL(QUIC_VERSION_34);
+ RETURN_STRING_LITERAL(QUIC_VERSION_35);
+ RETURN_STRING_LITERAL(QUIC_VERSION_36);
+ RETURN_STRING_LITERAL(QUIC_VERSION_37);
+ default:
+ return "QUIC_VERSION_UNSUPPORTED";
+ }
+}
+
+string QuicVersionVectorToString(const QuicVersionVector& versions) {
+ string result = "";
+ for (size_t i = 0; i < versions.size(); ++i) {
+ if (i != 0) {
+ result.append(",");
+ }
+ result.append(QuicVersionToString(versions[i]));
+ }
+ return result;
+}
+
+} // namespace net
diff --git a/chromium/net/quic/core/quic_versions.h b/chromium/net/quic/core/quic_versions.h
new file mode 100644
index 00000000000..0ce3902ddfb
--- /dev/null
+++ b/chromium/net/quic/core/quic_versions.h
@@ -0,0 +1,87 @@
+// Copyright (c) 2012 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.
+
+#ifndef NET_QUIC_CORE_QUIC_VERSIONS_H_
+#define NET_QUIC_CORE_QUIC_VERSIONS_H_
+
+#include <string>
+#include <vector>
+
+#include "net/quic/core/quic_tag.h"
+#include "net/quic/core/quic_types.h"
+#include "net/quic/platform/api/quic_export.h"
+
+namespace net {
+
+// The available versions of QUIC. Guaranteed that the integer value of the enum
+// will match the version number.
+// When adding a new version to this enum you should add it to
+// kSupportedQuicVersions (if appropriate), and also add a new case to the
+// helper methods QuicVersionToQuicTag, QuicTagToQuicVersion, and
+// QuicVersionToString.
+enum QuicVersion {
+ // Special case to indicate unknown/unsupported QUIC version.
+ QUIC_VERSION_UNSUPPORTED = 0,
+
+ QUIC_VERSION_34 = 34, // Deprecates entropy, removes private flag from packet
+ // header, uses new ack and stop waiting wire format.
+ QUIC_VERSION_35 = 35, // Allows endpoints to independently set stream limit.
+ QUIC_VERSION_36 = 36, // Add support to force HOL blocking.
+ QUIC_VERSION_37 = 37, // Add perspective into null encryption.
+
+ // IMPORTANT: if you are adding to this list, follow the instructions at
+ // http://sites/quic/adding-and-removing-versions
+};
+
+// This vector contains QUIC versions which we currently support.
+// This should be ordered such that the highest supported version is the first
+// element, with subsequent elements in descending order (versions can be
+// skipped as necessary).
+//
+// IMPORTANT: if you are adding to this list, follow the instructions at
+// http://sites/quic/adding-and-removing-versions
+static const QuicVersion kSupportedQuicVersions[] = {
+ QUIC_VERSION_37, QUIC_VERSION_36, QUIC_VERSION_35, QUIC_VERSION_34};
+
+typedef std::vector<QuicVersion> QuicVersionVector;
+
+// Returns a vector of QUIC versions in kSupportedQuicVersions.
+QUIC_EXPORT_PRIVATE QuicVersionVector AllSupportedVersions();
+
+// Returns a vector of QUIC versions from kSupportedQuicVersions which exclude
+// any versions which are disabled by flags.
+QUIC_EXPORT_PRIVATE QuicVersionVector CurrentSupportedVersions();
+
+// Returns a vector of QUIC versions from |versions| which exclude any versions
+// which are disabled by flags.
+QUIC_EXPORT_PRIVATE QuicVersionVector
+FilterSupportedVersions(QuicVersionVector versions);
+
+// Returns QUIC version of |index| in result of |versions|. Returns
+// QUIC_VERSION_UNSUPPORTED if |index| is out of bounds.
+QUIC_EXPORT_PRIVATE QuicVersionVector
+VersionOfIndex(const QuicVersionVector& versions, int index);
+
+// QuicTag is written to and read from the wire, but we prefer to use
+// the more readable QuicVersion at other levels.
+// Helper function which translates from a QuicVersion to a QuicTag. Returns 0
+// if QuicVersion is unsupported.
+QUIC_EXPORT_PRIVATE QuicTag QuicVersionToQuicTag(const QuicVersion version);
+
+// Returns appropriate QuicVersion from a QuicTag.
+// Returns QUIC_VERSION_UNSUPPORTED if version_tag cannot be understood.
+QUIC_EXPORT_PRIVATE QuicVersion QuicTagToQuicVersion(const QuicTag version_tag);
+
+// Helper function which translates from a QuicVersion to a string.
+// Returns strings corresponding to enum names (e.g. QUIC_VERSION_6).
+QUIC_EXPORT_PRIVATE std::string QuicVersionToString(const QuicVersion version);
+
+// Returns comma separated list of string representations of QuicVersion enum
+// values in the supplied |versions| vector.
+QUIC_EXPORT_PRIVATE std::string QuicVersionVectorToString(
+ const QuicVersionVector& versions);
+
+} // namespace net
+
+#endif // NET_QUIC_CORE_QUIC_VERSIONS_H_
diff --git a/chromium/net/quic/core/quic_versions_test.cc b/chromium/net/quic/core/quic_versions_test.cc
new file mode 100644
index 00000000000..cb2df3175cf
--- /dev/null
+++ b/chromium/net/quic/core/quic_versions_test.cc
@@ -0,0 +1,201 @@
+// Copyright (c) 2012 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.
+
+#include "net/quic/core/quic_versions.h"
+
+#include "net/quic/core/quic_flags.h"
+#include "net/quic/test_tools/quic_test_utils.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace net {
+namespace test {
+namespace {
+
+TEST(QuicVersionsTest, QuicVersionToQuicTag) {
+// If you add a new version to the QuicVersion enum you will need to add a new
+// case to QuicVersionToQuicTag, otherwise this test will fail.
+
+// TODO(rtenneti): Enable checking of Log(ERROR) messages.
+#if 0
+ // Any logs would indicate an unsupported version which we don't expect.
+ ScopedMockLog log(kDoNotCaptureLogsYet);
+ EXPECT_CALL(log, Log(_, _, _)).Times(0);
+ log.StartCapturingLogs();
+#endif
+
+ // Explicitly test a specific version.
+ EXPECT_EQ(MakeQuicTag('Q', '0', '3', '4'),
+ QuicVersionToQuicTag(QUIC_VERSION_34));
+
+ // Loop over all supported versions and make sure that we never hit the
+ // default case (i.e. all supported versions should be successfully converted
+ // to valid QuicTags).
+ for (size_t i = 0; i < arraysize(kSupportedQuicVersions); ++i) {
+ QuicVersion version = kSupportedQuicVersions[i];
+ EXPECT_LT(0u, QuicVersionToQuicTag(version));
+ }
+}
+
+TEST(QuicVersionsTest, QuicVersionToQuicTagUnsupported) {
+// TODO(rtenneti): Enable checking of Log(ERROR) messages.
+#if 0
+ // TODO(rjshade): Change to DFATAL once we actually support multiple versions,
+ // and QuicConnectionTest::SendVersionNegotiationPacket can be changed to use
+ // mis-matched versions rather than relying on QUIC_VERSION_UNSUPPORTED.
+ ScopedMockLog log(kDoNotCaptureLogsYet);
+ EXPECT_CALL(log, Log(base_logging::ERROR, _, "Unsupported QuicVersion: 0"))
+ .Times(1);
+ log.StartCapturingLogs();
+#endif
+
+ EXPECT_EQ(0u, QuicVersionToQuicTag(QUIC_VERSION_UNSUPPORTED));
+}
+
+TEST(QuicVersionsTest, QuicTagToQuicVersion) {
+// If you add a new version to the QuicVersion enum you will need to add a new
+// case to QuicTagToQuicVersion, otherwise this test will fail.
+
+// TODO(rtenneti): Enable checking of Log(ERROR) messages.
+#if 0
+ // Any logs would indicate an unsupported version which we don't expect.
+ ScopedMockLog log(kDoNotCaptureLogsYet);
+ EXPECT_CALL(log, Log(_, _, _)).Times(0);
+ log.StartCapturingLogs();
+#endif
+
+ // Explicitly test specific versions.
+ EXPECT_EQ(QUIC_VERSION_34,
+ QuicTagToQuicVersion(MakeQuicTag('Q', '0', '3', '4')));
+
+ for (size_t i = 0; i < arraysize(kSupportedQuicVersions); ++i) {
+ QuicVersion version = kSupportedQuicVersions[i];
+
+ // Get the tag from the version (we can loop over QuicVersions easily).
+ QuicTag tag = QuicVersionToQuicTag(version);
+ EXPECT_LT(0u, tag);
+
+ // Now try converting back.
+ QuicVersion tag_to_quic_version = QuicTagToQuicVersion(tag);
+ EXPECT_EQ(version, tag_to_quic_version);
+ EXPECT_NE(QUIC_VERSION_UNSUPPORTED, tag_to_quic_version);
+ }
+}
+
+TEST(QuicVersionsTest, QuicTagToQuicVersionUnsupported) {
+// TODO(rtenneti): Enable checking of Log(ERROR) messages.
+#if 0
+ ScopedMockLog log(kDoNotCaptureLogsYet);
+#ifndef NDEBUG
+ EXPECT_CALL(log,
+ Log(base_logging::INFO, _, "Unsupported QuicTag version: FAKE"))
+ .Times(1);
+#endif
+ log.StartCapturingLogs();
+#endif
+
+ EXPECT_EQ(QUIC_VERSION_UNSUPPORTED,
+ QuicTagToQuicVersion(MakeQuicTag('F', 'A', 'K', 'E')));
+}
+
+TEST(QuicVersionsTest, QuicVersionToString) {
+ EXPECT_EQ("QUIC_VERSION_34", QuicVersionToString(QUIC_VERSION_34));
+ EXPECT_EQ("QUIC_VERSION_UNSUPPORTED",
+ QuicVersionToString(QUIC_VERSION_UNSUPPORTED));
+
+ QuicVersion single_version[] = {QUIC_VERSION_34};
+ QuicVersionVector versions_vector;
+ for (size_t i = 0; i < arraysize(single_version); ++i) {
+ versions_vector.push_back(single_version[i]);
+ }
+ EXPECT_EQ("QUIC_VERSION_34", QuicVersionVectorToString(versions_vector));
+
+ QuicVersion multiple_versions[] = {QUIC_VERSION_UNSUPPORTED, QUIC_VERSION_34};
+ versions_vector.clear();
+ for (size_t i = 0; i < arraysize(multiple_versions); ++i) {
+ versions_vector.push_back(multiple_versions[i]);
+ }
+ EXPECT_EQ("QUIC_VERSION_UNSUPPORTED,QUIC_VERSION_34",
+ QuicVersionVectorToString(versions_vector));
+
+ // Make sure that all supported versions are present in QuicVersionToString.
+ for (size_t i = 0; i < arraysize(kSupportedQuicVersions); ++i) {
+ QuicVersion version = kSupportedQuicVersions[i];
+ EXPECT_NE("QUIC_VERSION_UNSUPPORTED", QuicVersionToString(version));
+ }
+}
+
+TEST(QuicVersionsTest, FilterSupportedVersionsNo34) {
+ QuicFlagSaver flags;
+ QuicVersionVector all_versions = {QUIC_VERSION_34, QUIC_VERSION_35,
+ QUIC_VERSION_36, QUIC_VERSION_37};
+
+ FLAGS_quic_reloadable_flag_quic_disable_version_34 = true;
+ FLAGS_quic_reloadable_flag_quic_enable_version_36_v3 = false;
+ FLAGS_quic_reloadable_flag_quic_enable_version_37 = false;
+
+ QuicVersionVector filtered_versions = FilterSupportedVersions(all_versions);
+ ASSERT_EQ(1u, filtered_versions.size());
+ EXPECT_EQ(QUIC_VERSION_35, filtered_versions[0]);
+}
+
+TEST(QuicVersionsTest, FilterSupportedVersionsNo36) {
+ QuicFlagSaver flags;
+ QuicVersionVector all_versions = {QUIC_VERSION_34, QUIC_VERSION_35,
+ QUIC_VERSION_36, QUIC_VERSION_37};
+
+ FLAGS_quic_reloadable_flag_quic_disable_version_34 = false;
+ FLAGS_quic_reloadable_flag_quic_enable_version_36_v3 = false;
+ FLAGS_quic_reloadable_flag_quic_enable_version_37 = false;
+
+ QuicVersionVector filtered_versions = FilterSupportedVersions(all_versions);
+ ASSERT_EQ(2u, filtered_versions.size());
+ EXPECT_EQ(QUIC_VERSION_34, filtered_versions[0]);
+ EXPECT_EQ(QUIC_VERSION_35, filtered_versions[1]);
+}
+
+TEST(QuicVersionsTest, FilterSupportedVersionsNo37) {
+ QuicFlagSaver flags;
+ QuicVersionVector all_versions = {QUIC_VERSION_34, QUIC_VERSION_35,
+ QUIC_VERSION_36, QUIC_VERSION_37};
+
+ FLAGS_quic_reloadable_flag_quic_disable_version_34 = false;
+ FLAGS_quic_reloadable_flag_quic_enable_version_36_v3 = true;
+ FLAGS_quic_reloadable_flag_quic_enable_version_37 = false;
+
+ QuicVersionVector filtered_versions = FilterSupportedVersions(all_versions);
+ ASSERT_EQ(3u, filtered_versions.size());
+ EXPECT_EQ(QUIC_VERSION_34, filtered_versions[0]);
+ EXPECT_EQ(QUIC_VERSION_35, filtered_versions[1]);
+ EXPECT_EQ(QUIC_VERSION_36, filtered_versions[2]);
+}
+
+TEST(QuicVersionsTest, FilterSupportedVersionsAllVersions) {
+ QuicFlagSaver flags;
+ QuicVersionVector all_versions = {QUIC_VERSION_34, QUIC_VERSION_35,
+ QUIC_VERSION_36, QUIC_VERSION_37};
+
+ FLAGS_quic_reloadable_flag_quic_disable_version_34 = false;
+ FLAGS_quic_reloadable_flag_quic_enable_version_36_v3 = true;
+ FLAGS_quic_reloadable_flag_quic_enable_version_37 = true;
+
+ QuicVersionVector filtered_versions = FilterSupportedVersions(all_versions);
+ ASSERT_EQ(all_versions, filtered_versions);
+}
+
+TEST(QuicVersionsTest, LookUpVersionByIndex) {
+ QuicVersionVector all_versions = {QUIC_VERSION_34, QUIC_VERSION_35,
+ QUIC_VERSION_36, QUIC_VERSION_37};
+ int version_count = all_versions.size();
+ for (int i = -5; i <= version_count + 1; ++i) {
+ if (i >= 0 && i < version_count) {
+ EXPECT_EQ(all_versions[i], VersionOfIndex(all_versions, i)[0]);
+ } else {
+ EXPECT_EQ(QUIC_VERSION_UNSUPPORTED, VersionOfIndex(all_versions, i)[0]);
+ }
+ }
+}
+
+} // namespace
+} // namespace test
+} // namespace net
diff --git a/chromium/net/quic/core/quic_write_blocked_list.h b/chromium/net/quic/core/quic_write_blocked_list.h
index c7b6d446ac6..f26491d6cf5 100644
--- a/chromium/net/quic/core/quic_write_blocked_list.h
+++ b/chromium/net/quic/core/quic_write_blocked_list.h
@@ -2,18 +2,15 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
//
-#ifndef NET_QUIC_QUIC_WRITE_BLOCKED_LIST_H_
-#define NET_QUIC_QUIC_WRITE_BLOCKED_LIST_H_
+#ifndef NET_QUIC_CORE_QUIC_WRITE_BLOCKED_LIST_H_
+#define NET_QUIC_CORE_QUIC_WRITE_BLOCKED_LIST_H_
-#include <stddef.h>
-#include <stdint.h>
-
-#include <set>
+#include <cstddef>
+#include <cstdint>
#include "base/macros.h"
-#include "net/base/net_export.h"
-#include "net/quic/core/quic_flags.h"
-#include "net/quic/core/quic_protocol.h"
+#include "net/quic/core/quic_packets.h"
+#include "net/quic/platform/api/quic_export.h"
#include "net/spdy/priority_write_scheduler.h"
namespace net {
@@ -21,7 +18,7 @@ namespace net {
// Keeps tracks of the QUIC streams that have data to write, sorted by
// priority. QUIC stream priority order is:
// Crypto stream > Headers stream > Data streams by requested priority.
-class NET_EXPORT_PRIVATE QuicWriteBlockedList {
+class QUIC_EXPORT_PRIVATE QuicWriteBlockedList {
private:
typedef PriorityWriteScheduler<QuicStreamId> QuicPriorityWriteScheduler;
@@ -123,9 +120,9 @@ class NET_EXPORT_PRIVATE QuicWriteBlockedList {
}
}
- // Pushes a stream to the back of the list for its priority level *unless*
- // it is latched for doing batched writes in which case it goes to the front
- // of the list for its priority level.
+ // Pushes a stream to the back of the list for its priority level *unless* it
+ // is latched for doing batched writes in which case it goes to the front of
+ // the list for its priority level.
// Headers and crypto streams are special cased to always resume first.
void AddStream(QuicStreamId stream_id) {
if (stream_id == kCryptoStreamId) {
@@ -173,4 +170,4 @@ class NET_EXPORT_PRIVATE QuicWriteBlockedList {
} // namespace net
-#endif // NET_QUIC_QUIC_WRITE_BLOCKED_LIST_H_
+#endif // NET_QUIC_CORE_QUIC_WRITE_BLOCKED_LIST_H_
diff --git a/chromium/net/quic/core/spdy_utils.cc b/chromium/net/quic/core/spdy_utils.cc
index 222001368ff..11ca27585b5 100644
--- a/chromium/net/quic/core/spdy_utils.cc
+++ b/chromium/net/quic/core/spdy_utils.cc
@@ -8,10 +8,8 @@
#include <vector>
#include "base/stl_util.h"
-#include "base/strings/string_number_conversions.h"
-#include "base/strings/string_split.h"
-#include "base/strings/string_util.h"
-#include "base/strings/stringprintf.h"
+#include "net/quic/platform/api/quic_logging.h"
+#include "net/quic/platform/api/quic_text_utils.h"
#include "net/spdy/spdy_flags.h"
#include "net/spdy/spdy_frame_builder.h"
#include "net/spdy/spdy_framer.h"
@@ -21,17 +19,14 @@
using base::StringPiece;
using base::ContainsKey;
using std::string;
-using std::vector;
namespace net {
// static
string SpdyUtils::SerializeUncompressedHeaders(const SpdyHeaderBlock& headers) {
- SpdyMajorVersion spdy_version = HTTP2;
-
- size_t length = SpdyFramer::GetSerializedLength(spdy_version, &headers);
- SpdyFrameBuilder builder(length, spdy_version);
- SpdyFramer framer(spdy_version);
+ size_t length = SpdyFramer::GetSerializedLength(&headers);
+ SpdyFrameBuilder builder(length);
+ SpdyFramer framer(SpdyFramer::DISABLE_COMPRESSION);
framer.SerializeHeaderBlockWithoutCompression(&builder, headers);
SpdySerializedFrame block(builder.take());
return string(block.data(), length);
@@ -42,7 +37,7 @@ bool SpdyUtils::ParseHeaders(const char* data,
uint32_t data_len,
int64_t* content_length,
SpdyHeaderBlock* headers) {
- SpdyFramer framer(HTTP2);
+ SpdyFramer framer(SpdyFramer::ENABLE_COMPRESSION);
if (!framer.ParseHeaderBlockInBuffer(data, data_len, headers) ||
headers->empty()) {
return false; // Headers were invalid.
@@ -64,13 +59,13 @@ bool SpdyUtils::ExtractContentLengthFromHeaders(int64_t* content_length,
} else {
// Check whether multiple values are consistent.
StringPiece content_length_header = it->second;
- std::vector<string> values =
- base::SplitString(content_length_header, base::StringPiece("\0", 1),
- base::TRIM_WHITESPACE, base::SPLIT_WANT_ALL);
- for (const string& value : values) {
+ std::vector<StringPiece> values =
+ QuicTextUtils::Split(content_length_header, '\0');
+ for (const StringPiece& value : values) {
int64_t new_value;
if (!base::StringToInt64(value, &new_value) || new_value < 0) {
- DLOG(ERROR) << "Content length was either unparseable or negative.";
+ QUIC_DLOG(ERROR)
+ << "Content length was either unparseable or negative.";
return false;
}
if (*content_length < 0) {
@@ -78,9 +73,10 @@ bool SpdyUtils::ExtractContentLengthFromHeaders(int64_t* content_length,
continue;
}
if (new_value != *content_length) {
- DLOG(ERROR) << "Parsed content length " << new_value << " is "
- << "inconsistent with previously detected content length "
- << *content_length;
+ QUIC_DLOG(ERROR)
+ << "Parsed content length " << new_value << " is "
+ << "inconsistent with previously detected content length "
+ << *content_length;
return false;
}
}
@@ -93,10 +89,10 @@ bool SpdyUtils::ParseTrailers(const char* data,
uint32_t data_len,
size_t* final_byte_offset,
SpdyHeaderBlock* trailers) {
- SpdyFramer framer(HTTP2);
+ SpdyFramer framer(SpdyFramer::ENABLE_COMPRESSION);
if (!framer.ParseHeaderBlockInBuffer(data, data_len, trailers) ||
trailers->empty()) {
- DVLOG(1) << "Request Trailers are invalid.";
+ QUIC_DVLOG(1) << "Request Trailers are invalid.";
return false; // Trailers were invalid.
}
@@ -105,7 +101,8 @@ bool SpdyUtils::ParseTrailers(const char* data,
auto it = trailers->find(kFinalOffsetHeaderKey);
if (it == trailers->end() ||
!base::StringToSizeT(it->second, final_byte_offset)) {
- DVLOG(1) << "Required key '" << kFinalOffsetHeaderKey << "' not present";
+ QUIC_DVLOG(1) << "Required key '" << kFinalOffsetHeaderKey
+ << "' not present";
return false;
}
// The final offset header is no longer needed.
@@ -113,18 +110,18 @@ bool SpdyUtils::ParseTrailers(const char* data,
// Trailers must not have empty keys, and must not contain pseudo headers.
for (const auto& trailer : *trailers) {
- base::StringPiece key = trailer.first;
- base::StringPiece value = trailer.second;
- if (base::StartsWith(key, ":", base::CompareCase::INSENSITIVE_ASCII)) {
- DVLOG(1) << "Trailers must not contain pseudo-header: '" << key << "','"
- << value << "'.";
+ StringPiece key = trailer.first;
+ StringPiece value = trailer.second;
+ if (QuicTextUtils::StartsWith(key, ":")) {
+ QUIC_DVLOG(1) << "Trailers must not contain pseudo-header: '" << key
+ << "','" << value << "'.";
return false;
}
// TODO(rjshade): Check for other forbidden keys, following the HTTP/2 spec.
}
- DVLOG(1) << "Successfully parsed Trailers.";
+ QUIC_DVLOG(1) << "Successfully parsed Trailers.";
return true;
}
@@ -134,13 +131,13 @@ bool SpdyUtils::CopyAndValidateHeaders(const QuicHeaderList& header_list,
for (const auto& p : header_list) {
const string& name = p.first;
if (name.empty()) {
- DVLOG(1) << "Header name must not be empty.";
+ QUIC_DVLOG(1) << "Header name must not be empty.";
return false;
}
- if (std::any_of(name.begin(), name.end(), base::IsAsciiUpper<char>)) {
- DVLOG(1) << "Malformed header: Header name " << name
- << " contains upper-case characters.";
+ if (QuicTextUtils::ContainsUpperCase(name)) {
+ QUIC_DLOG(ERROR) << "Malformed header: Header name " << name
+ << " contains upper-case characters.";
return false;
}
@@ -152,7 +149,7 @@ bool SpdyUtils::CopyAndValidateHeaders(const QuicHeaderList& header_list,
return false;
}
- DVLOG(1) << "Successfully parsed headers: " << headers->DebugString();
+ QUIC_DVLOG(1) << "Successfully parsed headers: " << headers->DebugString();
return true;
}
@@ -174,19 +171,20 @@ bool SpdyUtils::CopyAndValidateTrailers(const QuicHeaderList& header_list,
}
if (name.empty() || name[0] == ':') {
- DVLOG(1) << "Trailers must not be empty, and must not contain pseudo-"
- << "headers. Found: '" << name << "'";
+ QUIC_DVLOG(1)
+ << "Trailers must not be empty, and must not contain pseudo-"
+ << "headers. Found: '" << name << "'";
return false;
}
- if (std::any_of(name.begin(), name.end(), base::IsAsciiUpper<char>)) {
- DVLOG(1) << "Malformed header: Header name " << name
- << " contains upper-case characters.";
+ if (QuicTextUtils::ContainsUpperCase(name)) {
+ QUIC_DLOG(INFO) << "Malformed header: Header name " << name
+ << " contains upper-case characters.";
return false;
}
if (trailers->find(name) != trailers->end()) {
- DVLOG(1) << "Duplicate header '" << name << "' found in trailers.";
+ QUIC_DLOG(INFO) << "Duplicate header '" << name << "' found in trailers.";
return false;
}
@@ -194,13 +192,14 @@ bool SpdyUtils::CopyAndValidateTrailers(const QuicHeaderList& header_list,
}
if (!found_final_byte_offset) {
- DVLOG(1) << "Required key '" << kFinalOffsetHeaderKey << "' not present";
+ QUIC_DVLOG(1) << "Required key '" << kFinalOffsetHeaderKey
+ << "' not present";
return false;
}
// TODO(rjshade): Check for other forbidden keys, following the HTTP/2 spec.
- DVLOG(1) << "Successfully parsed Trailers: " << trailers->DebugString();
+ QUIC_DVLOG(1) << "Successfully parsed Trailers: " << trailers->DebugString();
return true;
}
diff --git a/chromium/net/quic/core/spdy_utils.h b/chromium/net/quic/core/spdy_utils.h
index f69b4474d19..752bd77150a 100644
--- a/chromium/net/quic/core/spdy_utils.h
+++ b/chromium/net/quic/core/spdy_utils.h
@@ -2,30 +2,28 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#ifndef NET_QUIC_SPDY_UTILS_H_
-#define NET_QUIC_SPDY_UTILS_H_
+#ifndef NET_QUIC_CORE_SPDY_UTILS_H_
+#define NET_QUIC_CORE_SPDY_UTILS_H_
-#include <stddef.h>
-#include <stdint.h>
-
-#include <map>
+#include <cstddef>
+#include <cstdint>
#include <string>
#include "base/macros.h"
-#include "net/base/net_export.h"
#include "net/quic/core/quic_header_list.h"
-#include "net/quic/core/quic_protocol.h"
+#include "net/quic/core/quic_packets.h"
+#include "net/quic/platform/api/quic_export.h"
#include "net/spdy/spdy_framer.h"
namespace net {
-class NET_EXPORT_PRIVATE SpdyUtils {
+class QUIC_EXPORT_PRIVATE SpdyUtils {
public:
static std::string SerializeUncompressedHeaders(
const SpdyHeaderBlock& headers);
- // Parses |data| as a std::string containing serialized HTTP/2 HEADERS frame,
- // populating |headers| with the key->value std:pairs found.
+ // Parses |data| as a string containing serialized HTTP/2 HEADERS frame,
+ // populating |headers| with the key->value pairs found.
// |content_length| will be populated with the value of the content-length
// header if one or more are present.
// Returns true on success, false if parsing fails, or invalid keys are found.
@@ -40,8 +38,8 @@ class NET_EXPORT_PRIVATE SpdyUtils {
static bool ExtractContentLengthFromHeaders(int64_t* content_length,
SpdyHeaderBlock* headers);
- // Parses |data| as a std::string containing serialized HTTP/2 HEADERS frame,
- // populating |trailers| with the key->value std:pairs found.
+ // Parses |data| as a string containing serialized HTTP/2 HEADERS frame,
+ // populating |trailers| with the key->value pairs found.
// The final offset header will be excluded from |trailers|, and instead the
// value will be copied to |final_byte_offset|.
// Returns true on success, false if parsing fails, or invalid keys are found.
@@ -64,14 +62,14 @@ class NET_EXPORT_PRIVATE SpdyUtils {
// Returns URL composed from scheme, authority, and path header
// values, or empty string if any of those fields are missing.
- static std::string GetUrlFromHeaderBlock(const net::SpdyHeaderBlock& headers);
+ static std::string GetUrlFromHeaderBlock(const SpdyHeaderBlock& headers);
- // Returns hostname, or empty std::string if missing.
+ // Returns hostname, or empty string if missing.
static std::string GetHostNameFromHeaderBlock(const SpdyHeaderBlock& headers);
// Returns true if result of |GetUrlFromHeaderBlock()| is non-empty
// and is a well-formed URL.
- static bool UrlIsValid(const net::SpdyHeaderBlock& headers);
+ static bool UrlIsValid(const SpdyHeaderBlock& headers);
// Populates the fields of |headers| to make a GET request of |url|,
// which must be fully-qualified.
@@ -84,4 +82,4 @@ class NET_EXPORT_PRIVATE SpdyUtils {
} // namespace net
-#endif // NET_QUIC_SPDY_UTILS_H_
+#endif // NET_QUIC_CORE_SPDY_UTILS_H_
diff --git a/chromium/net/quic/core/spdy_utils_test.cc b/chromium/net/quic/core/spdy_utils_test.cc
index c07f9dee58f..75823c3de37 100644
--- a/chromium/net/quic/core/spdy_utils_test.cc
+++ b/chromium/net/quic/core/spdy_utils_test.cc
@@ -4,9 +4,10 @@
#include "net/quic/core/spdy_utils.h"
#include "base/macros.h"
-#include "base/strings/string_number_conversions.h"
#include "base/strings/string_piece.h"
+#include "net/quic/platform/api/quic_text_utils.h"
#include "net/test/gtest_util.h"
+#include "testing/gtest/include/gtest/gtest.h"
using base::StringPiece;
using std::string;
@@ -26,7 +27,8 @@ TEST(SpdyUtilsTest, SerializeAndParseHeaders) {
input_headers[":pseudo2"] = "pseudo value2";
input_headers["key1"] = "value1";
const int64_t kContentLength = 1234;
- input_headers["content-length"] = base::Int64ToString(kContentLength);
+ input_headers["content-length"] =
+ QuicTextUtils::Uint64ToString(kContentLength);
input_headers["key2"] = "value2";
// Serialize the header block.
@@ -55,7 +57,8 @@ TEST(SpdyUtilsTest, SerializeAndParseHeadersLargeContentLength) {
input_headers[":pseudo2"] = "pseudo value2";
input_headers["key1"] = "value1";
const int64_t kContentLength = 12345678900;
- input_headers["content-length"] = base::Int64ToString(kContentLength);
+ input_headers["content-length"] =
+ QuicTextUtils::Uint64ToString(kContentLength);
input_headers["key2"] = "value2";
// Serialize the header block.
@@ -80,7 +83,8 @@ TEST(SpdyUtilsTest, SerializeAndParseValidTrailers) {
// result is the same as the trailers that the test started with.
SpdyHeaderBlock input_trailers;
const size_t kFinalOffset = 5678;
- input_trailers[kFinalOffsetHeaderKey] = base::IntToString(kFinalOffset);
+ input_trailers[kFinalOffsetHeaderKey] =
+ QuicTextUtils::Uint64ToString(kFinalOffset);
input_trailers["key1"] = "value1";
input_trailers["key2"] = "value2";
diff --git a/chromium/net/quic/platform/README.md b/chromium/net/quic/platform/README.md
new file mode 100644
index 00000000000..6538de108cf
--- /dev/null
+++ b/chromium/net/quic/platform/README.md
@@ -0,0 +1,12 @@
+# QUIC platform
+
+This platform/ directory exists in order to allow QUIC code to be built on
+numerous platforms. It contains two subdirectories:
+
+- api/ contains platform independent class definitions for fundamental data
+ structures (e.g., IPAddress, SocketAddress, etc.).
+- impl/ contains platform specific implementations of these data structures.
+ The content of files in impl/ will vary depending on the platform.
+
+Code in the parent quic/ directory should not depend on any platform specific
+code, other than that found in impl/.
diff --git a/chromium/net/quic/platform/api/quic_aligned.h b/chromium/net/quic/platform/api/quic_aligned.h
new file mode 100644
index 00000000000..7e5d9357a67
--- /dev/null
+++ b/chromium/net/quic/platform/api/quic_aligned.h
@@ -0,0 +1,14 @@
+// Copyright 2016 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.
+
+#ifndef NET_QUIC_PLATFORM_API_QUIC_ALIGNED_H_
+#define NET_QUIC_PLATFORM_API_QUIC_ALIGNED_H_
+
+#include "net/quic/platform/impl/quic_aligned_impl.h"
+
+#define QUIC_ALIGN_OF QUIC_ALIGN_OF_IMPL
+#define QUIC_ALIGNED(X) QUIC_ALIGNED_IMPL(X)
+#define QUIC_CACHELINE_ALIGNED QUIC_CACHELINE_ALIGNED_IMPL
+
+#endif // NET_QUIC_PLATFORM_API_QUIC_ALIGNED_H_
diff --git a/chromium/net/quic/platform/api/quic_bug_tracker.h b/chromium/net/quic/platform/api/quic_bug_tracker.h
new file mode 100644
index 00000000000..1db197003c3
--- /dev/null
+++ b/chromium/net/quic/platform/api/quic_bug_tracker.h
@@ -0,0 +1,12 @@
+// Copyright (c) 2016 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.
+#ifndef NET_QUIC_PLATFORM_API_QUIC_BUG_TRACKER_H_
+#define NET_QUIC_PLATFORM_API_QUIC_BUG_TRACKER_H_
+
+#include "net/quic/platform/impl/quic_bug_tracker_impl.h"
+
+#define QUIC_BUG QUIC_BUG_IMPL
+#define QUIC_BUG_IF QUIC_BUG_IF_IMPL
+
+#endif // NET_QUIC_PLATFORM_API_QUIC_BUG_TRACKER_H_ \ No newline at end of file
diff --git a/chromium/net/quic/core/quic_clock.cc b/chromium/net/quic/platform/api/quic_clock.cc
index 9eb4f71760e..4c52c3e022f 100644
--- a/chromium/net/quic/core/quic_clock.cc
+++ b/chromium/net/quic/platform/api/quic_clock.cc
@@ -2,9 +2,7 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#include "net/quic/core/quic_clock.h"
-
-#include "base/time/time.h"
+#include "net/quic/platform/api/quic_clock.h"
namespace net {
@@ -12,21 +10,6 @@ QuicClock::QuicClock() {}
QuicClock::~QuicClock() {}
-QuicTime QuicClock::ApproximateNow() const {
- // At the moment, Chrome does not have a distinct notion of ApproximateNow().
- // We should consider implementing this using MessageLoop::recent_time_.
- return Now();
-}
-
-QuicTime QuicClock::Now() const {
- return QuicTime(base::TimeTicks::Now());
-}
-
-QuicWallTime QuicClock::WallNow() const {
- return QuicWallTime::FromUNIXMicroseconds(base::Time::Now().ToJavaTime() *
- 1000);
-}
-
QuicTime QuicClock::ConvertWallTimeToQuicTime(
const QuicWallTime& walltime) const {
// ..........................
diff --git a/chromium/net/quic/core/quic_clock.h b/chromium/net/quic/platform/api/quic_clock.h
index 7c6878b063a..e95e0bc8a1b 100644
--- a/chromium/net/quic/core/quic_clock.h
+++ b/chromium/net/quic/platform/api/quic_clock.h
@@ -2,43 +2,39 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#ifndef NET_QUIC_QUIC_CLOCK_H_
-#define NET_QUIC_QUIC_CLOCK_H_
+#ifndef NET_QUIC_PLATFORM_API_QUIC_CLOCK_H_
+#define NET_QUIC_PLATFORM_API_QUIC_CLOCK_H_
-#include "base/macros.h"
-#include "net/base/net_export.h"
#include "net/quic/core/quic_time.h"
+#include "net/quic/platform/api/quic_export.h"
namespace net {
-typedef double WallTime;
-
-// Clock to efficiently retrieve an approximately accurate time from an
-// EpollServer.
-class NET_EXPORT_PRIVATE QuicClock {
+// Interface for retreiving the current time.
+class QUIC_EXPORT_PRIVATE QuicClock {
public:
QuicClock();
virtual ~QuicClock();
+ QuicClock(const QuicClock&) = delete;
+ QuicClock& operator=(const QuicClock&) = delete;
+
// Returns the approximate current time as a QuicTime object.
- virtual QuicTime ApproximateNow() const;
+ virtual QuicTime ApproximateNow() const = 0;
// Returns the current time as a QuicTime object.
// Note: this use significant resources please use only if needed.
- virtual QuicTime Now() const;
+ virtual QuicTime Now() const = 0;
// WallNow returns the current wall-time - a time that is consistent across
// different clocks.
- virtual QuicWallTime WallNow() const;
+ virtual QuicWallTime WallNow() const = 0;
// Converts |walltime| to a QuicTime relative to this clock's epoch.
virtual QuicTime ConvertWallTimeToQuicTime(
const QuicWallTime& walltime) const;
-
- private:
- DISALLOW_COPY_AND_ASSIGN(QuicClock);
};
} // namespace net
-#endif // NET_QUIC_QUIC_CLOCK_H_
+#endif // NET_QUIC_PLATFORM_API_QUIC_CLOCK_H_
diff --git a/chromium/net/quic/platform/api/quic_export.h b/chromium/net/quic/platform/api/quic_export.h
new file mode 100644
index 00000000000..2939b01e20d
--- /dev/null
+++ b/chromium/net/quic/platform/api/quic_export.h
@@ -0,0 +1,10 @@
+// Copyright 2016 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.
+
+#ifndef NET_QUIC_PLATFORM_API_QUIC_EXPORT_H_
+#define NET_QUIC_PLATFORM_API_QUIC_EXPORT_H_
+
+#include "net/quic/platform/impl/quic_export_impl.h"
+
+#endif // NET_QUIC_PLATFORM_API_QUIC_EXPORT_H_
diff --git a/chromium/net/quic/platform/api/quic_ip_address.cc b/chromium/net/quic/platform/api/quic_ip_address.cc
new file mode 100644
index 00000000000..146904018d5
--- /dev/null
+++ b/chromium/net/quic/platform/api/quic_ip_address.cc
@@ -0,0 +1,86 @@
+// Copyright (c) 2016 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.
+
+#include "net/quic/platform/api/quic_ip_address.h"
+
+using std::string;
+
+namespace net {
+
+QuicIpAddress QuicIpAddress::Loopback4() {
+ return QuicIpAddress(QuicIpAddressImpl::Loopback4());
+}
+
+QuicIpAddress QuicIpAddress::Loopback6() {
+ return QuicIpAddress(QuicIpAddressImpl::Loopback6());
+}
+
+QuicIpAddress QuicIpAddress::Any4() {
+ return QuicIpAddress(QuicIpAddressImpl::Any4());
+}
+
+QuicIpAddress QuicIpAddress::Any6() {
+ return QuicIpAddress(QuicIpAddressImpl::Any6());
+}
+
+QuicIpAddress::QuicIpAddress(const QuicIpAddressImpl& impl) : impl_(impl) {}
+
+bool operator==(QuicIpAddress lhs, QuicIpAddress rhs) {
+ return lhs.impl_ == rhs.impl_;
+}
+
+bool operator!=(QuicIpAddress lhs, QuicIpAddress rhs) {
+ return !(lhs == rhs);
+}
+
+bool QuicIpAddress::IsInitialized() const {
+ return impl_.IsInitialized();
+}
+
+IpAddressFamily QuicIpAddress::address_family() const {
+ return impl_.address_family();
+}
+
+int QuicIpAddress::AddressFamilyToInt() const {
+ return impl_.AddressFamilyToInt();
+}
+
+std::string QuicIpAddress::ToPackedString() const {
+ return impl_.ToPackedString();
+}
+
+std::string QuicIpAddress::ToString() const {
+ return impl_.ToString();
+}
+
+QuicIpAddress QuicIpAddress::Normalized() const {
+ return QuicIpAddress(impl_.Normalized());
+}
+
+QuicIpAddress QuicIpAddress::DualStacked() const {
+ return QuicIpAddress(impl_.DualStacked());
+}
+
+bool QuicIpAddress::FromPackedString(const char* data, size_t length) {
+ return impl_.FromPackedString(data, length);
+}
+
+bool QuicIpAddress::FromString(string str) {
+ return impl_.FromString(str);
+}
+
+bool QuicIpAddress::IsIPv4() const {
+ return impl_.IsIPv4();
+}
+
+bool QuicIpAddress::IsIPv6() const {
+ return impl_.IsIPv6();
+}
+
+bool QuicIpAddress::InSameSubnet(const QuicIpAddress& other,
+ int subnet_length) {
+ return impl_.InSameSubnet(other.impl(), subnet_length);
+}
+
+} // namespace net
diff --git a/chromium/net/quic/platform/api/quic_ip_address.h b/chromium/net/quic/platform/api/quic_ip_address.h
new file mode 100644
index 00000000000..9b10e8efe90
--- /dev/null
+++ b/chromium/net/quic/platform/api/quic_ip_address.h
@@ -0,0 +1,67 @@
+// Copyright (c) 2016 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.
+
+#ifndef NET_QUIC_PLATFORM_API_QUIC_IP_ADDRESS_H_
+#define NET_QUIC_PLATFORM_API_QUIC_IP_ADDRESS_H_
+
+#include <string>
+
+#include "net/quic/platform/api/quic_export.h"
+#include "net/quic/platform/impl/quic_ip_address_impl.h"
+
+namespace net {
+
+class QUIC_EXPORT_PRIVATE QuicIpAddress {
+ // A class representing an IPv4 or IPv6 address in QUIC. The actual
+ // implementation (platform dependent) of an IP address is in
+ // QuicIpAddressImpl.
+ public:
+ static QuicIpAddress Loopback4();
+ static QuicIpAddress Loopback6();
+ static QuicIpAddress Any4();
+ static QuicIpAddress Any6();
+
+ QuicIpAddress() = default;
+ QuicIpAddress(const QuicIpAddress& other) = default;
+ explicit QuicIpAddress(const QuicIpAddressImpl& impl);
+ QuicIpAddress& operator=(const QuicIpAddress& other) = default;
+ QuicIpAddress& operator=(QuicIpAddress&& other) = default;
+ QUIC_EXPORT_PRIVATE friend bool operator==(QuicIpAddress lhs,
+ QuicIpAddress rhs);
+ QUIC_EXPORT_PRIVATE friend bool operator!=(QuicIpAddress lhs,
+ QuicIpAddress rhs);
+
+ bool IsInitialized() const;
+ IpAddressFamily address_family() const;
+ int AddressFamilyToInt() const;
+ // Returns the address as a sequence of bytes in network-byte-order. IPv4 will
+ // be 6 bytes. IPv6 will be 18 bytes.
+ std::string ToPackedString() const;
+ // Returns std::string representation of the address.
+ std::string ToString() const;
+ // Normalizes the address representation with respect to IPv4 addresses, i.e,
+ // mapped IPv4 addresses ("::ffff:X.Y.Z.Q") are converted to pure IPv4
+ // addresses. All other IPv4, IPv6, and empty values are left unchanged.
+ QuicIpAddress Normalized() const;
+ // Returns an address suitable for use in IPv6-aware contexts. This is the
+ // opposite of NormalizeIPAddress() above. IPv4 addresses are converted into
+ // their IPv4-mapped address equivalents (e.g. 192.0.2.1 becomes
+ // ::ffff:192.0.2.1). IPv6 addresses are a noop (they are returned
+ // unchanged).
+ QuicIpAddress DualStacked() const;
+ bool FromPackedString(const char* data, size_t length);
+ bool FromString(std::string str);
+ bool IsIPv4() const;
+ bool IsIPv6() const;
+ bool InSameSubnet(const QuicIpAddress& other, int subnet_length);
+
+ const QuicIpAddressImpl& impl() const { return impl_; }
+
+ private:
+ QuicIpAddressImpl impl_;
+};
+
+} // namespace net
+
+#endif // NET_QUIC_PLATFORM_API_QUIC_IP_ADDRESS_H_
diff --git a/chromium/net/quic/platform/api/quic_ip_address_family.h b/chromium/net/quic/platform/api/quic_ip_address_family.h
new file mode 100644
index 00000000000..d8b4a65a69d
--- /dev/null
+++ b/chromium/net/quic/platform/api/quic_ip_address_family.h
@@ -0,0 +1,20 @@
+// Copyright (c) 2016 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.
+
+#ifndef NET_QUIC_PLATFORM_API_QUIC_IP_ADDRESS_FAMILY_H_
+#define NET_QUIC_PLATFORM_API_QUIC_IP_ADDRESS_FAMILY_H_
+
+namespace net {
+
+// IP address family type used in QUIC. This hides platform dependant IP address
+// family types.
+enum class IpAddressFamily {
+ IP_V4,
+ IP_V6,
+ IP_UNSPEC,
+};
+
+} // namespace net
+
+#endif // NET_QUIC_PLATFORM_API_QUIC_IP_ADDRESS_FAMILY_H_
diff --git a/chromium/net/quic/platform/api/quic_logging.h b/chromium/net/quic/platform/api/quic_logging.h
new file mode 100644
index 00000000000..5f840202802
--- /dev/null
+++ b/chromium/net/quic/platform/api/quic_logging.h
@@ -0,0 +1,23 @@
+// Copyright (c) 2017 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.
+
+#ifndef NET_QUIC_PLATFORM_API_QUIC_LOGGING_H_
+#define NET_QUIC_PLATFORM_API_QUIC_LOGGING_H_
+
+#include "net/quic/platform/impl/quic_logging_impl.h"
+
+// Please note following QUIC_LOG are platform dependent:
+// INFO severity can be degraded (to VLOG(1) or DVLOG(1)).
+// Some platforms may not support QUIC_LOG_FIRST_N or QUIC_LOG_EVERY_N_SEC, and
+// they would simply be translated to LOG.
+
+#define QUIC_DVLOG(verbose_level) QUIC_DVLOG_IMPL(verbose_level)
+#define QUIC_DLOG(severity) QUIC_DLOG_IMPL(severity)
+#define QUIC_LOG(severity) QUIC_LOG_IMPL(severity)
+#define QUIC_LOG_FIRST_N(severity, n) QUIC_LOG_FIRST_N_IMPL(severity, n)
+#define QUIC_LOG_EVERY_N_SEC(severity, seconds) \
+ QUIC_LOG_EVERY_N_SEC_IMPL(severity, seconds)
+#define QUIC_LOG_IF(severity, condition) QUIC_LOG_IF_IMPL(severity, condition)
+
+#endif // NET_QUIC_PLATFORM_API_QUIC_LOGGING_H_
diff --git a/chromium/net/quic/platform/api/quic_lru_cache.h b/chromium/net/quic/platform/api/quic_lru_cache.h
new file mode 100644
index 00000000000..b7a0623309c
--- /dev/null
+++ b/chromium/net/quic/platform/api/quic_lru_cache.h
@@ -0,0 +1,52 @@
+// Copyright (c) 2016 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.
+
+#ifndef NET_QUIC_PLATFORM_API_QUIC_LRU_CACHE_H_
+#define NET_QUIC_PLATFORM_API_QUIC_LRU_CACHE_H_
+
+#include <memory>
+
+#include "net/quic/platform/impl/quic_lru_cache_impl.h"
+
+namespace net {
+
+// A LRU cache that maps from type Key to Value* in QUIC.
+// This cache CANNOT be shared by multiple threads (even with locks) because
+// Value* returned by Lookup() can be invalid if the entry is evicted by other
+// threads.
+template <class K, class V>
+class QuicLRUCache {
+ public:
+ explicit QuicLRUCache(int64_t total_units) : impl_(total_units) {}
+
+ // Inserts one unit of |key|, |value| pair to the cache. Cache takes ownership
+ // of inserted |value|.
+ void Insert(const K& key, std::unique_ptr<V> value) {
+ impl_.Insert(key, std::move(value));
+ }
+
+ // If cache contains an entry for |key|, return a pointer to it. This returned
+ // value is guaranteed to be valid until Insert or Clear.
+ // Else return nullptr.
+ V* Lookup(const K& key) { return impl_.Lookup(key); }
+
+ // Removes all entries from the cache. This method MUST be called before
+ // destruction.
+ void Clear() { impl_.Clear(); }
+
+ // Returns maximum size of the cache.
+ int64_t MaxSize() const { return impl_.MaxSize(); }
+
+ // Returns current size of the cache.
+ int64_t Size() const { return impl_.Size(); }
+
+ private:
+ QuicLRUCacheImpl<K, V> impl_;
+
+ DISALLOW_COPY_AND_ASSIGN(QuicLRUCache);
+};
+
+} // namespace net
+
+#endif // NET_QUIC_PLATFORM_API_QUIC_LRU_CACHE_H_
diff --git a/chromium/net/quic/platform/api/quic_lru_cache_test.cc b/chromium/net/quic/platform/api/quic_lru_cache_test.cc
new file mode 100644
index 00000000000..77b6bacc43b
--- /dev/null
+++ b/chromium/net/quic/platform/api/quic_lru_cache_test.cc
@@ -0,0 +1,76 @@
+// Copyright (c) 2016 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.
+
+#include "net/quic/platform/api/quic_lru_cache.h"
+
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace net {
+namespace test {
+namespace {
+
+struct CachedItem {
+ explicit CachedItem(uint32_t new_value) : value(new_value) {}
+
+ uint32_t value;
+};
+
+TEST(QuicLRUCacheTest, InsertAndLookup) {
+ QuicLRUCache<int, CachedItem> cache(5);
+ EXPECT_EQ(nullptr, cache.Lookup(1));
+ EXPECT_EQ(0u, cache.Size());
+ EXPECT_EQ(5u, cache.MaxSize());
+
+ // Check that item 1 was properly inserted.
+ std::unique_ptr<CachedItem> item1(new CachedItem(11));
+ cache.Insert(1, std::move(item1));
+ EXPECT_EQ(1u, cache.Size());
+ EXPECT_EQ(11u, cache.Lookup(1)->value);
+
+ // Check that item 2 overrides item 1.
+ std::unique_ptr<CachedItem> item2(new CachedItem(12));
+ cache.Insert(1, std::move(item2));
+ EXPECT_EQ(1u, cache.Size());
+ EXPECT_EQ(12u, cache.Lookup(1)->value);
+
+ std::unique_ptr<CachedItem> item3(new CachedItem(13));
+ cache.Insert(3, std::move(item3));
+ EXPECT_EQ(2u, cache.Size());
+ EXPECT_EQ(13u, cache.Lookup(3)->value);
+
+ // No memory leakage.
+ cache.Clear();
+ EXPECT_EQ(0u, cache.Size());
+}
+
+TEST(QuicLRUCacheTest, Eviction) {
+ QuicLRUCache<int, CachedItem> cache(3);
+
+ for (size_t i = 1; i <= 4; ++i) {
+ std::unique_ptr<CachedItem> item(new CachedItem(10 + i));
+ cache.Insert(i, std::move(item));
+ }
+
+ EXPECT_EQ(3u, cache.Size());
+ EXPECT_EQ(3u, cache.MaxSize());
+
+ // Make sure item 1 is evicted.
+ EXPECT_EQ(nullptr, cache.Lookup(1));
+ EXPECT_EQ(14u, cache.Lookup(4)->value);
+
+ EXPECT_EQ(12u, cache.Lookup(2)->value);
+ std::unique_ptr<CachedItem> item5(new CachedItem(15));
+ cache.Insert(5, std::move(item5));
+ // Make sure item 3 is evicted.
+ EXPECT_EQ(nullptr, cache.Lookup(3));
+ EXPECT_EQ(15u, cache.Lookup(5)->value);
+
+ // No memory leakage.
+ cache.Clear();
+ EXPECT_EQ(0u, cache.Size());
+}
+
+} // namespace
+} // namespace test
+} // namespace net
diff --git a/chromium/net/quic/platform/api/quic_mutex.cc b/chromium/net/quic/platform/api/quic_mutex.cc
new file mode 100644
index 00000000000..f0c8f0997ae
--- /dev/null
+++ b/chromium/net/quic/platform/api/quic_mutex.cc
@@ -0,0 +1,45 @@
+// Copyright (c) 2016 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.
+
+#include "net/quic/platform/api/quic_mutex.h"
+
+namespace net {
+
+void QuicMutex::WriterLock() {
+ impl_.WriterLock();
+}
+
+void QuicMutex::WriterUnlock() {
+ impl_.WriterUnlock();
+}
+
+void QuicMutex::ReaderLock() {
+ impl_.ReaderLock();
+}
+
+void QuicMutex::ReaderUnlock() {
+ impl_.ReaderUnlock();
+}
+
+void QuicMutex::AssertReaderHeld() const {
+ impl_.AssertReaderHeld();
+}
+
+QuicReaderMutexLock::QuicReaderMutexLock(QuicMutex* lock) : lock_(lock) {
+ lock->ReaderLock();
+}
+
+QuicReaderMutexLock::~QuicReaderMutexLock() {
+ lock_->ReaderUnlock();
+}
+
+QuicWriterMutexLock::QuicWriterMutexLock(QuicMutex* lock) : lock_(lock) {
+ lock->WriterLock();
+}
+
+QuicWriterMutexLock::~QuicWriterMutexLock() {
+ lock_->WriterUnlock();
+}
+
+} // namespace net
diff --git a/chromium/net/quic/platform/api/quic_mutex.h b/chromium/net/quic/platform/api/quic_mutex.h
new file mode 100644
index 00000000000..cc51f304881
--- /dev/null
+++ b/chromium/net/quic/platform/api/quic_mutex.h
@@ -0,0 +1,70 @@
+// Copyright (c) 2016 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.
+
+#ifndef NET_QUIC_PLATFORM_API_QUIC_MUTEX_H_
+#define NET_QUIC_PLATFORM_API_QUIC_MUTEX_H_
+
+#include "net/quic/platform/impl/quic_mutex_impl.h"
+
+namespace net {
+
+// A class representing a non-reentrant mutex in QUIC.
+class QUIC_EXPORT_PRIVATE LOCKABLE QuicMutex {
+ public:
+ QuicMutex() = default;
+
+ // Block until this Mutex is free, then acquire it exclusively.
+ void WriterLock() EXCLUSIVE_LOCK_FUNCTION();
+
+ // Release this Mutex. Caller must hold it exclusively.
+ void WriterUnlock() UNLOCK_FUNCTION();
+
+ // Block until this Mutex is free or shared, then acquire a share of it.
+ void ReaderLock() SHARED_LOCK_FUNCTION();
+
+ // Release this Mutex. Caller could hold it in shared mode.
+ void ReaderUnlock() UNLOCK_FUNCTION();
+
+ // Returns immediately if current thread holds the Mutex in at least shared
+ // mode. Otherwise, may report an error (typically by crashing with a
+ // diagnostic), or may return immediately.
+ void AssertReaderHeld() const ASSERT_SHARED_LOCK();
+
+ private:
+ QuicLockImpl impl_;
+
+ DISALLOW_COPY_AND_ASSIGN(QuicMutex);
+};
+
+// A helper class that acquires the given QuicMutex shared lock while the
+// QuicReaderMutexLock is in scope.
+class QUIC_EXPORT_PRIVATE SCOPED_LOCKABLE QuicReaderMutexLock {
+ public:
+ explicit QuicReaderMutexLock(QuicMutex* lock) SHARED_LOCK_FUNCTION(lock);
+
+ ~QuicReaderMutexLock() UNLOCK_FUNCTION();
+
+ private:
+ QuicMutex* const lock_;
+
+ DISALLOW_COPY_AND_ASSIGN(QuicReaderMutexLock);
+};
+
+// A helper class that acquires the given QuicMutex exclusive lock while the
+// QuicWriterMutexLock is in scope.
+class QUIC_EXPORT_PRIVATE SCOPED_LOCKABLE QuicWriterMutexLock {
+ public:
+ explicit QuicWriterMutexLock(QuicMutex* lock) EXCLUSIVE_LOCK_FUNCTION(lock);
+
+ ~QuicWriterMutexLock() UNLOCK_FUNCTION();
+
+ private:
+ QuicMutex* const lock_;
+
+ DISALLOW_COPY_AND_ASSIGN(QuicWriterMutexLock);
+};
+
+} // namespace net
+
+#endif // NET_QUIC_PLATFORM_API_QUIC_MUTEX_H_
diff --git a/chromium/net/quic/platform/api/quic_ptr_util.h b/chromium/net/quic/platform/api/quic_ptr_util.h
new file mode 100644
index 00000000000..b5a472e1eec
--- /dev/null
+++ b/chromium/net/quic/platform/api/quic_ptr_util.h
@@ -0,0 +1,23 @@
+// Copyright (c) 2017 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.
+#ifndef NET_QUIC_PLATFORM_API_QUIC_PTR_UTIL_H_
+#define NET_QUIC_PLATFORM_API_QUIC_PTR_UTIL_H_
+
+#include "net/quic/platform/impl/quic_ptr_util_impl.h"
+
+namespace net {
+
+template <typename T, typename... Args>
+std::unique_ptr<T> QuicMakeUnique(Args&&... args) {
+ return std::move(QuicMakeUniqueImpl<T>(std::forward<Args>(args)...));
+}
+
+template <typename T>
+std::unique_ptr<T> QuicWrapUnique(T* ptr) {
+ return std::move(QuicWrapUniqueImpl<T>(ptr));
+}
+
+} // namespace net
+
+#endif // NET_QUIC_PLATFORM_API_QUIC_PTR_UTIL_H_
diff --git a/chromium/net/quic/platform/api/quic_reference_counted.h b/chromium/net/quic/platform/api/quic_reference_counted.h
new file mode 100644
index 00000000000..296fe483e1a
--- /dev/null
+++ b/chromium/net/quic/platform/api/quic_reference_counted.h
@@ -0,0 +1,161 @@
+// Copyright (c) 2016 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.
+
+#ifndef NET_QUIC_PLATFORM_API_QUIC_REFERENCE_COUNTED_H_
+#define NET_QUIC_PLATFORM_API_QUIC_REFERENCE_COUNTED_H_
+
+#include "net/quic/platform/impl/quic_reference_counted_impl.h"
+
+namespace net {
+
+// Base class for explicitly reference-counted objects in QUIC.
+class QUIC_EXPORT_PRIVATE QuicReferenceCounted
+ : public QuicReferenceCountedImpl {
+ public:
+ QuicReferenceCounted() {}
+
+ protected:
+ ~QuicReferenceCounted() override {}
+};
+
+// A class representing a reference counted pointer in QUIC.
+//
+// Construct or initialize QuicReferenceCountedPointer from raw pointer. Here
+// raw pointer MUST be a newly created object. Reference count of a newly
+// created object is undefined, but that will be 1 after being added to
+// QuicReferenceCountedPointer.
+// QuicReferenceCountedPointer is used as a local variable.
+// QuicReferenceCountedPointer<T> r_ptr(new T());
+// or, equivalently:
+// QuicReferenceCountedPointer<T> r_ptr;
+// T* p = new T();
+// r_ptr = T;
+//
+// QuicReferenceCountedPointer is used as a member variable:
+// MyClass::MyClass() : r_ptr(new T()) {}
+//
+// This is WRONG, since *p is not guaranteed to be newly created:
+// MyClass::MyClass(T* p) : r_ptr(p) {}
+//
+// Given an existing QuicReferenceCountedPointer, create a duplicate that has
+// its own reference on the object:
+// QuicReferenceCountedPointer<T> r_ptr_b(r_ptr_a);
+// or, equivalently:
+// QuicReferenceCountedPointer<T> r_ptr_b = r_ptr_a;
+//
+// Given an existing QuicReferenceCountedPointer, create a
+// QuicReferenceCountedPointer that adopts the reference:
+// QuicReferenceCountedPointer<T> r_ptr_b(std::move(r_ptr_a));
+// or, equivalently:
+// QuicReferenceCountedPointer<T> r_ptr_b = std::move(r_ptr_a);
+
+template <class T>
+class QuicReferenceCountedPointer {
+ public:
+ QuicReferenceCountedPointer() = default;
+
+ // Constructor from raw pointer |p|. This guarantees the reference count of *p
+ // is 1. This should only be used when a new object is created, calling this
+ // on an already existent object is undefined behavior.
+ explicit QuicReferenceCountedPointer(T* p) : impl_(p) {}
+
+ // Allows implicit conversion from nullptr.
+ QuicReferenceCountedPointer(std::nullptr_t) : impl_(nullptr) {} // NOLINT
+
+ // Copy and copy conversion constructors. It does not take the reference away
+ // from |other| and they each end up with their own reference.
+ template <typename U>
+ QuicReferenceCountedPointer( // NOLINT
+ const QuicReferenceCountedPointer<U>& other)
+ : impl_(other.impl()) {}
+ QuicReferenceCountedPointer(const QuicReferenceCountedPointer& other)
+ : impl_(other.impl()) {}
+
+ // Move constructors. After move, It adopts the reference from |other|.
+ template <typename U>
+ QuicReferenceCountedPointer(QuicReferenceCountedPointer<U>&& other) // NOLINT
+ : impl_(std::move(other.impl())) {}
+ QuicReferenceCountedPointer(QuicReferenceCountedPointer&& other)
+ : impl_(std::move(other.impl())) {}
+
+ ~QuicReferenceCountedPointer() = default;
+
+ // Copy assignments.
+ QuicReferenceCountedPointer& operator=(
+ const QuicReferenceCountedPointer& other) {
+ impl_ = other.impl();
+ return *this;
+ }
+ template <typename U>
+ QuicReferenceCountedPointer<T>& operator=(
+ const QuicReferenceCountedPointer<U>& other) {
+ impl_ = other.impl();
+ return *this;
+ }
+
+ // Move assignments.
+ QuicReferenceCountedPointer& operator=(QuicReferenceCountedPointer&& other) {
+ impl_ = std::move(other.impl());
+ return *this;
+ }
+ template <typename U>
+ QuicReferenceCountedPointer<T>& operator=(
+ QuicReferenceCountedPointer<U>&& other) {
+ impl_ = std::move(other.impl());
+ return *this;
+ }
+
+ // Accessors for the referenced object.
+ // operator* and operator-> will assert() if there is no current object.
+ T& operator*() const { return *impl_; }
+ T* operator->() const { return impl_.get(); }
+
+ explicit operator bool() const { return static_cast<bool>(impl_); }
+
+ // Assignment operator on raw pointer. Drops a reference to current pointee,
+ // if any and replaces it with |p|. This garantee the reference count of *p is
+ // 1. This should only be used when a new object is created, calling this
+ // on a already existent object is undefined behavior.
+ QuicReferenceCountedPointer<T>& operator=(T* p) {
+ impl_ = p;
+ return *this;
+ }
+
+ // Returns the raw pointer with no change in reference.
+ T* get() const { return impl_.get(); }
+
+ QuicReferenceCountedPointerImpl<T>& impl() { return impl_; }
+ const QuicReferenceCountedPointerImpl<T>& impl() const { return impl_; }
+
+ // Comparisons against same type.
+ friend bool operator==(const QuicReferenceCountedPointer& a,
+ const QuicReferenceCountedPointer& b) {
+ return a.get() == b.get();
+ }
+ friend bool operator!=(const QuicReferenceCountedPointer& a,
+ const QuicReferenceCountedPointer& b) {
+ return a.get() != b.get();
+ }
+
+ // Comparisons against nullptr.
+ friend bool operator==(const QuicReferenceCountedPointer& a, std::nullptr_t) {
+ return a.get() == nullptr;
+ }
+ friend bool operator==(std::nullptr_t, const QuicReferenceCountedPointer& b) {
+ return nullptr == b.get();
+ }
+ friend bool operator!=(const QuicReferenceCountedPointer& a, std::nullptr_t) {
+ return a.get() != nullptr;
+ }
+ friend bool operator!=(std::nullptr_t, const QuicReferenceCountedPointer& b) {
+ return nullptr != b.get();
+ }
+
+ private:
+ QuicReferenceCountedPointerImpl<T> impl_;
+};
+
+} // namespace net
+
+#endif // NET_QUIC_PLATFORM_API_QUIC_REFERENCE_COUNTED_H_
diff --git a/chromium/net/quic/platform/api/quic_reference_counted_test.cc b/chromium/net/quic/platform/api/quic_reference_counted_test.cc
new file mode 100644
index 00000000000..8f46094b6fe
--- /dev/null
+++ b/chromium/net/quic/platform/api/quic_reference_counted_test.cc
@@ -0,0 +1,173 @@
+// Copyright (c) 2016 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.
+
+#include "net/quic/platform/api/quic_reference_counted.h"
+
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace net {
+namespace test {
+namespace {
+
+class Base : public QuicReferenceCounted {
+ public:
+ explicit Base(bool* destroyed) : destroyed_(destroyed) {
+ *destroyed_ = false;
+ }
+
+ bool destroyed() const { return *destroyed_; }
+
+ protected:
+ ~Base() override { *destroyed_ = true; }
+
+ private:
+ bool* destroyed_;
+};
+
+class Derived : public Base {
+ public:
+ explicit Derived(bool* destroyed) : Base(destroyed) {}
+
+ private:
+ ~Derived() override {}
+};
+
+TEST(QuicReferenceCountedTest, DefaultConstructor) {
+ QuicReferenceCountedPointer<Base> a;
+ EXPECT_EQ(nullptr, a);
+ EXPECT_EQ(nullptr, a.get());
+ EXPECT_FALSE(a);
+}
+
+TEST(QuicReferenceCountedTest, ConstructFromRawPointer) {
+ bool destroyed = false;
+ {
+ QuicReferenceCountedPointer<Base> a(new Base(&destroyed));
+ EXPECT_FALSE(destroyed);
+ }
+ EXPECT_TRUE(destroyed);
+}
+
+TEST(QuicReferenceCountedTest, RawPointerAssignment) {
+ bool destroyed = false;
+ {
+ QuicReferenceCountedPointer<Base> a;
+ Base* rct = new Base(&destroyed);
+ a = rct;
+ EXPECT_FALSE(destroyed);
+ }
+ EXPECT_TRUE(destroyed);
+}
+
+TEST(QuicReferenceCountedTest, PointerCopy) {
+ bool destroyed = false;
+ {
+ QuicReferenceCountedPointer<Base> a(new Base(&destroyed));
+ {
+ QuicReferenceCountedPointer<Base> b(a);
+ EXPECT_EQ(a, b);
+ EXPECT_FALSE(destroyed);
+ }
+ EXPECT_FALSE(destroyed);
+ }
+ EXPECT_TRUE(destroyed);
+}
+
+TEST(QuicReferenceCountedTest, PointerCopyAssignment) {
+ bool destroyed = false;
+ {
+ QuicReferenceCountedPointer<Base> a(new Base(&destroyed));
+ {
+ QuicReferenceCountedPointer<Base> b = a;
+ EXPECT_EQ(a, b);
+ EXPECT_FALSE(destroyed);
+ }
+ EXPECT_FALSE(destroyed);
+ }
+ EXPECT_TRUE(destroyed);
+}
+
+TEST(QuicReferenceCountedTest, PointerCopyFromOtherType) {
+ bool destroyed = false;
+ {
+ QuicReferenceCountedPointer<Derived> a(new Derived(&destroyed));
+ {
+ QuicReferenceCountedPointer<Base> b(a);
+ EXPECT_EQ(a.get(), b.get());
+ EXPECT_FALSE(destroyed);
+ }
+ EXPECT_FALSE(destroyed);
+ }
+ EXPECT_TRUE(destroyed);
+}
+
+TEST(QuicReferenceCountedTest, PointerCopyAssignmentFromOtherType) {
+ bool destroyed = false;
+ {
+ QuicReferenceCountedPointer<Derived> a(new Derived(&destroyed));
+ {
+ QuicReferenceCountedPointer<Base> b = a;
+ EXPECT_EQ(a.get(), b.get());
+ EXPECT_FALSE(destroyed);
+ }
+ EXPECT_FALSE(destroyed);
+ }
+ EXPECT_TRUE(destroyed);
+}
+
+TEST(QuicReferenceCountedTest, PointerMove) {
+ bool destroyed = false;
+ QuicReferenceCountedPointer<Base> a(new Derived(&destroyed));
+ EXPECT_FALSE(destroyed);
+ QuicReferenceCountedPointer<Base> b(std::move(a));
+ EXPECT_FALSE(destroyed);
+ EXPECT_NE(nullptr, b);
+ EXPECT_EQ(nullptr, a); // NOLINT
+
+ b = nullptr;
+ EXPECT_TRUE(destroyed);
+}
+
+TEST(QuicReferenceCountedTest, PointerMoveAssignment) {
+ bool destroyed = false;
+ QuicReferenceCountedPointer<Base> a(new Derived(&destroyed));
+ EXPECT_FALSE(destroyed);
+ QuicReferenceCountedPointer<Base> b = std::move(a);
+ EXPECT_FALSE(destroyed);
+ EXPECT_NE(nullptr, b);
+ EXPECT_EQ(nullptr, a); // NOLINT
+
+ b = nullptr;
+ EXPECT_TRUE(destroyed);
+}
+
+TEST(QuicReferenceCountedTest, PointerMoveFromOtherType) {
+ bool destroyed = false;
+ QuicReferenceCountedPointer<Derived> a(new Derived(&destroyed));
+ EXPECT_FALSE(destroyed);
+ QuicReferenceCountedPointer<Base> b(std::move(a));
+ EXPECT_FALSE(destroyed);
+ EXPECT_NE(nullptr, b);
+ EXPECT_EQ(nullptr, a); // NOLINT
+
+ b = nullptr;
+ EXPECT_TRUE(destroyed);
+}
+
+TEST(QuicReferenceCountedTest, PointerMoveAssignmentFromOtherType) {
+ bool destroyed = false;
+ QuicReferenceCountedPointer<Derived> a(new Derived(&destroyed));
+ EXPECT_FALSE(destroyed);
+ QuicReferenceCountedPointer<Base> b = std::move(a);
+ EXPECT_FALSE(destroyed);
+ EXPECT_NE(nullptr, b);
+ EXPECT_EQ(nullptr, a); // NOLINT
+
+ b = nullptr;
+ EXPECT_TRUE(destroyed);
+}
+
+} // namespace
+} // namespace test
+} // namespace net
diff --git a/chromium/net/quic/platform/api/quic_socket_address.cc b/chromium/net/quic/platform/api/quic_socket_address.cc
new file mode 100644
index 00000000000..43ffa343e74
--- /dev/null
+++ b/chromium/net/quic/platform/api/quic_socket_address.cc
@@ -0,0 +1,59 @@
+// Copyright (c) 2016 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.
+
+#include "net/quic/platform/api/quic_socket_address.h"
+
+using std::string;
+
+namespace net {
+
+QuicSocketAddress::QuicSocketAddress(QuicIpAddress address, uint16_t port)
+ : impl_(address.impl(), port) {}
+
+QuicSocketAddress::QuicSocketAddress(const struct sockaddr_storage& saddr)
+ : impl_(saddr) {}
+
+QuicSocketAddress::QuicSocketAddress(const struct sockaddr& saddr)
+ : impl_(saddr) {}
+
+QuicSocketAddress::QuicSocketAddress(const QuicSocketAddressImpl& impl)
+ : impl_(impl) {}
+
+bool operator==(QuicSocketAddress lhs, QuicSocketAddress rhs) {
+ return lhs.impl_ == rhs.impl_;
+}
+
+bool operator!=(QuicSocketAddress lhs, QuicSocketAddress rhs) {
+ return lhs.impl_ != rhs.impl_;
+}
+
+bool QuicSocketAddress::IsInitialized() const {
+ return impl_.IsInitialized();
+}
+
+string QuicSocketAddress::ToString() const {
+ return impl_.ToString();
+}
+
+int QuicSocketAddress::FromSocket(int fd) {
+ return impl_.FromSocket(fd);
+}
+
+QuicSocketAddress QuicSocketAddress::Normalized() const {
+ return QuicSocketAddress(impl_.Normalized());
+}
+
+QuicIpAddress QuicSocketAddress::host() const {
+ return QuicIpAddress(impl_.host());
+}
+
+uint16_t QuicSocketAddress::port() const {
+ return impl_.port();
+}
+
+sockaddr_storage QuicSocketAddress::generic_address() const {
+ return impl_.generic_address();
+}
+
+} // namespace net
diff --git a/chromium/net/quic/platform/api/quic_socket_address.h b/chromium/net/quic/platform/api/quic_socket_address.h
new file mode 100644
index 00000000000..7d8bcdef1cb
--- /dev/null
+++ b/chromium/net/quic/platform/api/quic_socket_address.h
@@ -0,0 +1,48 @@
+// Copyright (c) 2016 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.
+
+#ifndef NET_QUIC_PLATFORM_API_QUIC_SOCKET_ADDRESS_H_
+#define NET_QUIC_PLATFORM_API_QUIC_SOCKET_ADDRESS_H_
+
+#include "net/quic/platform/api/quic_export.h"
+#include "net/quic/platform/api/quic_ip_address.h"
+#include "net/quic/platform/impl/quic_socket_address_impl.h"
+
+namespace net {
+
+class QUIC_EXPORT_PRIVATE QuicSocketAddress {
+ // A class representing a socket endpoint address (i.e., IP address plus a
+ // port) in QUIC. The actual implementation (platform dependent) of a socket
+ // address is in QuicSocketAddressImpl.
+ public:
+ QuicSocketAddress() = default;
+ QuicSocketAddress(QuicIpAddress address, uint16_t port);
+ explicit QuicSocketAddress(const struct sockaddr_storage& saddr);
+ explicit QuicSocketAddress(const struct sockaddr& saddr);
+ explicit QuicSocketAddress(const QuicSocketAddressImpl& impl);
+ QuicSocketAddress(const QuicSocketAddress& other) = default;
+ QuicSocketAddress& operator=(const QuicSocketAddress& other) = default;
+ QuicSocketAddress& operator=(QuicSocketAddress&& other) = default;
+ QUIC_EXPORT_PRIVATE friend bool operator==(QuicSocketAddress lhs,
+ QuicSocketAddress rhs);
+ QUIC_EXPORT_PRIVATE friend bool operator!=(QuicSocketAddress lhs,
+ QuicSocketAddress rhs);
+
+ bool IsInitialized() const;
+ std::string ToString() const;
+ int FromSocket(int fd);
+ QuicSocketAddress Normalized() const;
+
+ QuicIpAddress host() const;
+ uint16_t port() const;
+ sockaddr_storage generic_address() const;
+ const QuicSocketAddressImpl& impl() const { return impl_; }
+
+ private:
+ QuicSocketAddressImpl impl_;
+};
+
+} // namespace net
+
+#endif // NET_QUIC_PLATFORM_API_QUIC_SOCKET_ADDRESS_H_
diff --git a/chromium/net/quic/platform/api/quic_str_cat.h b/chromium/net/quic/platform/api/quic_str_cat.h
new file mode 100644
index 00000000000..cfbc67d6e77
--- /dev/null
+++ b/chromium/net/quic/platform/api/quic_str_cat.h
@@ -0,0 +1,19 @@
+// Copyright (c) 2016 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.
+
+#ifndef NET_QUIC_PLATFORM_API_QUIC_STR_CAT_H_
+#define NET_QUIC_PLATFORM_API_QUIC_STR_CAT_H_
+
+#include "net/quic/platform/impl/quic_str_cat_impl.h"
+
+namespace net {
+
+template <typename... Args>
+inline std::string QuicStrCat(const Args&... args) {
+ return std::move(QuicStrCatImpl(std::forward<const Args&>(args)...));
+}
+
+} // namespace net
+
+#endif // NET_QUIC_PLATFORM_API_QUIC_STR_CAT_H_
diff --git a/chromium/net/quic/platform/api/quic_str_cat_test.cc b/chromium/net/quic/platform/api/quic_str_cat_test.cc
new file mode 100644
index 00000000000..3064346952d
--- /dev/null
+++ b/chromium/net/quic/platform/api/quic_str_cat_test.cc
@@ -0,0 +1,167 @@
+// Copyright (c) 2016 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.
+
+#include "net/quic/platform/api/quic_str_cat.h"
+
+#include "base/strings/string_piece.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+using base::StringPiece;
+using std::string;
+
+namespace net {
+namespace test {
+namespace {
+
+TEST(QuicStrCatTest, Ints) {
+ const int16_t s = -1;
+ const uint16_t us = 2;
+ const int i = -3;
+ const uint32_t ui = 4;
+ const int64_t l = -5;
+ const uint64_t ul = 6;
+ const ptrdiff_t ptrdiff = -7;
+ const size_t size = 8;
+ const intptr_t intptr = -9;
+ const uintptr_t uintptr = 10;
+ string answer;
+ answer = QuicStrCat(s, us);
+ EXPECT_EQ(answer, "-12");
+ answer = QuicStrCat(i, ui);
+ EXPECT_EQ(answer, "-34");
+ answer = QuicStrCat(l, ul);
+ EXPECT_EQ(answer, "-56");
+ answer = QuicStrCat(ptrdiff, size);
+ EXPECT_EQ(answer, "-78");
+ answer = QuicStrCat(size, intptr);
+ EXPECT_EQ(answer, "8-9");
+ answer = QuicStrCat(uintptr, 0);
+ EXPECT_EQ(answer, "100");
+}
+
+TEST(QuicStrCatTest, Basics) {
+ string result;
+
+ string strs[] = {"Hello", "Cruel", "World"};
+
+ StringPiece pieces[] = {"Hello", "Cruel", "World"};
+
+ const char* c_strs[] = {"Hello", "Cruel", "World"};
+
+ int32_t i32s[] = {'H', 'C', 'W'};
+ uint64_t ui64s[] = {12345678910LL, 10987654321LL};
+
+ result = QuicStrCat(false, true, 2, 3);
+ EXPECT_EQ(result, "0123");
+
+ result = QuicStrCat(-1);
+ EXPECT_EQ(result, "-1");
+
+ result = QuicStrCat(0.5);
+ EXPECT_EQ(result, "0.5");
+
+ result = QuicStrCat(strs[1], pieces[2]);
+ EXPECT_EQ(result, "CruelWorld");
+
+ result = QuicStrCat(strs[0], ", ", pieces[2]);
+ EXPECT_EQ(result, "Hello, World");
+
+ result = QuicStrCat(strs[0], ", ", strs[1], " ", strs[2], "!");
+ EXPECT_EQ(result, "Hello, Cruel World!");
+
+ result = QuicStrCat(pieces[0], ", ", pieces[1], " ", pieces[2]);
+ EXPECT_EQ(result, "Hello, Cruel World");
+
+ result = QuicStrCat(c_strs[0], ", ", c_strs[1], " ", c_strs[2]);
+ EXPECT_EQ(result, "Hello, Cruel World");
+
+ result = QuicStrCat("ASCII ", i32s[0], ", ", i32s[1], " ", i32s[2], "!");
+ EXPECT_EQ(result, "ASCII 72, 67 87!");
+
+ result = QuicStrCat(ui64s[0], ", ", ui64s[1], "!");
+ EXPECT_EQ(result, "12345678910, 10987654321!");
+
+ string one = "1";
+ result = QuicStrCat("And a ", one.size(), " and a ", &result[2] - &result[0],
+ " and a ", one, " 2 3 4", "!");
+ EXPECT_EQ(result, "And a 1 and a 2 and a 1 2 3 4!");
+
+ result =
+ QuicStrCat("To output a char by ASCII/numeric value, use +: ", '!' + 0);
+ EXPECT_EQ(result, "To output a char by ASCII/numeric value, use +: 33");
+
+ float f = 10000.5;
+ result = QuicStrCat("Ten K and a half is ", f);
+ EXPECT_EQ(result, "Ten K and a half is 10000.5");
+
+ double d = 99999.9;
+ result = QuicStrCat("This double number is ", d);
+ EXPECT_EQ(result, "This double number is 99999.9");
+
+ result =
+ QuicStrCat(1, 22, 333, 4444, 55555, 666666, 7777777, 88888888, 999999999);
+ EXPECT_EQ(result, "122333444455555666666777777788888888999999999");
+}
+
+TEST(QuicStrCatTest, MaxArgs) {
+ string result;
+ // Test 10 up to 26 arguments, the current maximum
+ result = QuicStrCat(1, 2, 3, 4, 5, 6, 7, 8, 9, "a");
+ EXPECT_EQ(result, "123456789a");
+ result = QuicStrCat(1, 2, 3, 4, 5, 6, 7, 8, 9, "a", "b");
+ EXPECT_EQ(result, "123456789ab");
+ result = QuicStrCat(1, 2, 3, 4, 5, 6, 7, 8, 9, "a", "b", "c");
+ EXPECT_EQ(result, "123456789abc");
+ result = QuicStrCat(1, 2, 3, 4, 5, 6, 7, 8, 9, "a", "b", "c", "d");
+ EXPECT_EQ(result, "123456789abcd");
+ result = QuicStrCat(1, 2, 3, 4, 5, 6, 7, 8, 9, "a", "b", "c", "d", "e");
+ EXPECT_EQ(result, "123456789abcde");
+ result = QuicStrCat(1, 2, 3, 4, 5, 6, 7, 8, 9, "a", "b", "c", "d", "e", "f");
+ EXPECT_EQ(result, "123456789abcdef");
+ result =
+ QuicStrCat(1, 2, 3, 4, 5, 6, 7, 8, 9, "a", "b", "c", "d", "e", "f", "g");
+ EXPECT_EQ(result, "123456789abcdefg");
+ result = QuicStrCat(1, 2, 3, 4, 5, 6, 7, 8, 9, "a", "b", "c", "d", "e", "f",
+ "g", "h");
+ EXPECT_EQ(result, "123456789abcdefgh");
+ result = QuicStrCat(1, 2, 3, 4, 5, 6, 7, 8, 9, "a", "b", "c", "d", "e", "f",
+ "g", "h", "i");
+ EXPECT_EQ(result, "123456789abcdefghi");
+ result = QuicStrCat(1, 2, 3, 4, 5, 6, 7, 8, 9, "a", "b", "c", "d", "e", "f",
+ "g", "h", "i", "j");
+ EXPECT_EQ(result, "123456789abcdefghij");
+ result = QuicStrCat(1, 2, 3, 4, 5, 6, 7, 8, 9, "a", "b", "c", "d", "e", "f",
+ "g", "h", "i", "j", "k");
+ EXPECT_EQ(result, "123456789abcdefghijk");
+ result = QuicStrCat(1, 2, 3, 4, 5, 6, 7, 8, 9, "a", "b", "c", "d", "e", "f",
+ "g", "h", "i", "j", "k", "l");
+ EXPECT_EQ(result, "123456789abcdefghijkl");
+ result = QuicStrCat(1, 2, 3, 4, 5, 6, 7, 8, 9, "a", "b", "c", "d", "e", "f",
+ "g", "h", "i", "j", "k", "l", "m");
+ EXPECT_EQ(result, "123456789abcdefghijklm");
+ result = QuicStrCat(1, 2, 3, 4, 5, 6, 7, 8, 9, "a", "b", "c", "d", "e", "f",
+ "g", "h", "i", "j", "k", "l", "m", "n");
+ EXPECT_EQ(result, "123456789abcdefghijklmn");
+ result = QuicStrCat(1, 2, 3, 4, 5, 6, 7, 8, 9, "a", "b", "c", "d", "e", "f",
+ "g", "h", "i", "j", "k", "l", "m", "n", "o");
+ EXPECT_EQ(result, "123456789abcdefghijklmno");
+ result = QuicStrCat(1, 2, 3, 4, 5, 6, 7, 8, 9, "a", "b", "c", "d", "e", "f",
+ "g", "h", "i", "j", "k", "l", "m", "n", "o", "p");
+ EXPECT_EQ(result, "123456789abcdefghijklmnop");
+ result = QuicStrCat(1, 2, 3, 4, 5, 6, 7, 8, 9, "a", "b", "c", "d", "e", "f",
+ "g", "h", "i", "j", "k", "l", "m", "n", "o", "p", "q");
+ EXPECT_EQ(result, "123456789abcdefghijklmnopq");
+ // No limit thanks to C++11's variadic templates
+ result = QuicStrCat(
+ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, "a", "b", "c", "d", "e", "f", "g", "h",
+ "i", "j", "k", "l", "m", "n", "o", "p", "q", "r", "s", "t", "u", "v", "w",
+ "x", "y", "z", "A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K", "L",
+ "M", "N", "O", "P", "Q", "R", "S", "T", "U", "V", "W", "X", "Y", "Z");
+ EXPECT_EQ(result,
+ "12345678910abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ");
+}
+
+} // namespace
+} // namespace test
+} // namespace net
diff --git a/chromium/net/quic/platform/api/quic_text_utils.h b/chromium/net/quic/platform/api/quic_text_utils.h
new file mode 100644
index 00000000000..7eabe73ea4a
--- /dev/null
+++ b/chromium/net/quic/platform/api/quic_text_utils.h
@@ -0,0 +1,98 @@
+// Copyright 2016 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.
+
+#ifndef NET_QUIC_PLATFORM_API_QUIC_TEXT_UTILS_H_
+#define NET_QUIC_PLATFORM_API_QUIC_TEXT_UTILS_H_
+
+#include "base/strings/string_piece.h"
+#include "net/quic/platform/impl/quic_text_utils_impl.h"
+
+namespace net {
+
+// Various utilities for manipulating text.
+class QuicTextUtils {
+ public:
+ // Returns true if |data| starts with |prefix|, case sensitively.
+ static bool StartsWith(base::StringPiece data, base::StringPiece prefix) {
+ return QuicTextUtilsImpl::StartsWith(data, prefix);
+ }
+
+ // Returns true if |data| ends with |suffix|, case insensitively.
+ static bool EndsWithIgnoreCase(base::StringPiece data,
+ base::StringPiece suffix) {
+ return QuicTextUtilsImpl::EndsWithIgnoreCase(data, suffix);
+ }
+
+ // Returns a new string in which |data| has been converted to lower case.
+ static std::string ToLower(base::StringPiece data) {
+ return QuicTextUtilsImpl::ToLower(data);
+ }
+
+ // Removes leading and trailing whitespace from |data|.
+ static void RemoveLeadingAndTrailingWhitespace(base::StringPiece* data) {
+ QuicTextUtilsImpl::RemoveLeadingAndTrailingWhitespace(data);
+ }
+
+ // Returns true if |in| represents a valid uint64, and stores that value in
+ // |out|.
+ static bool StringToUint64(base::StringPiece in, uint64_t* out) {
+ return QuicTextUtilsImpl::StringToUint64(in, out);
+ }
+
+ // Returns a new string representing |in|.
+ static std::string Uint64ToString(uint64_t in) {
+ return QuicTextUtilsImpl::Uint64ToString(in);
+ }
+
+ // This converts |length| bytes of binary to a 2*|length|-character
+ // hexadecimal representation.
+ // Return value: 2*|length| characters of ASCII string.
+ static std::string HexEncode(const char* data, size_t length) {
+ return HexEncode(base::StringPiece(data, length));
+ }
+
+ // This converts |data.length()| bytes of binary to a
+ // 2*|data.length()|-character hexadecimal representation.
+ // Return value: 2*|data.length()| characters of ASCII string.
+ static std::string HexEncode(base::StringPiece data) {
+ return QuicTextUtilsImpl::HexEncode(data);
+ }
+
+ // Converts |data| from a hexadecimal ASCII string to a binary string
+ // that is |data.length()/2| bytes long.
+ static std::string HexDecode(base::StringPiece data) {
+ return QuicTextUtilsImpl::HexDecode(data);
+ }
+
+ // Base64 encodes with no padding |data_len| bytes of |data| into |output|.
+ static void Base64Encode(const uint8_t* data,
+ size_t data_len,
+ std::string* output) {
+ return QuicTextUtilsImpl::Base64Encode(data, data_len, output);
+ }
+
+ // Returns a string containing hex and ASCII representations of |binary|,
+ // side-by-side in the style of hexdump. Non-printable characters will be
+ // printed as '.' in the ASCII output.
+ // For example, given the input "Hello, QUIC!\01\02\03\04", returns:
+ // "0x0000: 4865 6c6c 6f2c 2051 5549 4321 0102 0304 Hello,.QUIC!...."
+ static std::string HexDump(base::StringPiece binary_data) {
+ return QuicTextUtilsImpl::HexDump(binary_data);
+ }
+
+ // Returns true if |data| contains any uppercase characters.
+ static bool ContainsUpperCase(base::StringPiece data) {
+ return QuicTextUtilsImpl::ContainsUpperCase(data);
+ }
+
+ // Splits |data| into a vector of pieces delimited by |delim|.
+ static std::vector<base::StringPiece> Split(base::StringPiece data,
+ char delim) {
+ return QuicTextUtilsImpl::Split(data, delim);
+ }
+};
+
+} // namespace net
+
+#endif // NET_QUIC_PLATFORM_API_QUIC_TEXT_UTILS_H_
diff --git a/chromium/net/quic/platform/api/quic_text_utils_test.cc b/chromium/net/quic/platform/api/quic_text_utils_test.cc
new file mode 100644
index 00000000000..49efeb16182
--- /dev/null
+++ b/chromium/net/quic/platform/api/quic_text_utils_test.cc
@@ -0,0 +1,140 @@
+// Copyright 2016 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.
+
+#include "net/quic/platform/api/quic_text_utils.h"
+
+#include <string>
+
+#include "base/strings/string_piece.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+using base::StringPiece;
+using std::string;
+
+namespace net {
+namespace test {
+
+TEST(QuicTextUtilsText, StartsWith) {
+ EXPECT_TRUE(QuicTextUtils::StartsWith("hello world", "hello"));
+ EXPECT_TRUE(QuicTextUtils::StartsWith("hello world", "hello world"));
+ EXPECT_TRUE(QuicTextUtils::StartsWith("hello world", ""));
+ EXPECT_FALSE(QuicTextUtils::StartsWith("hello world", "Hello"));
+ EXPECT_FALSE(QuicTextUtils::StartsWith("hello world", "world"));
+ EXPECT_FALSE(QuicTextUtils::StartsWith("hello world", "bar"));
+}
+
+TEST(QuicTextUtilsText, EndsWithIgnoreCase) {
+ EXPECT_TRUE(QuicTextUtils::EndsWithIgnoreCase("hello world", "world"));
+ EXPECT_TRUE(QuicTextUtils::EndsWithIgnoreCase("hello world", "hello world"));
+ EXPECT_TRUE(QuicTextUtils::EndsWithIgnoreCase("hello world", ""));
+ EXPECT_TRUE(QuicTextUtils::EndsWithIgnoreCase("hello world", "WORLD"));
+ EXPECT_FALSE(QuicTextUtils::EndsWithIgnoreCase("hello world", "hello"));
+}
+
+TEST(QuicTextUtilsText, ToLower) {
+ EXPECT_EQ("lower", QuicTextUtils::ToLower("LOWER"));
+ EXPECT_EQ("lower", QuicTextUtils::ToLower("lower"));
+ EXPECT_EQ("lower", QuicTextUtils::ToLower("lOwEr"));
+ EXPECT_EQ("123", QuicTextUtils::ToLower("123"));
+ EXPECT_EQ("", QuicTextUtils::ToLower(""));
+}
+
+TEST(QuicTextUtilsText, RemoveLeadingAndTrailingWhitespace) {
+ string input;
+
+ for (auto input : {"text", " text", " text", "text ", "text ", " text ",
+ " text ", "\r\n\ttext", "text\n\r\t"}) {
+ StringPiece piece(input);
+ QuicTextUtils::RemoveLeadingAndTrailingWhitespace(&piece);
+ EXPECT_EQ("text", piece);
+ }
+}
+
+TEST(QuicTextUtilsText, StringToUint64) {
+ uint64_t val = 0;
+ EXPECT_TRUE(QuicTextUtils::StringToUint64("123", &val));
+ EXPECT_EQ(123u, val);
+ EXPECT_TRUE(QuicTextUtils::StringToUint64("1234", &val));
+ EXPECT_EQ(1234u, val);
+ EXPECT_FALSE(QuicTextUtils::StringToUint64("", &val));
+ EXPECT_FALSE(QuicTextUtils::StringToUint64("-123", &val));
+ EXPECT_FALSE(QuicTextUtils::StringToUint64("-123.0", &val));
+}
+
+TEST(QuicTextUtilsText, Uint64ToString) {
+ EXPECT_EQ("123", QuicTextUtils::Uint64ToString(123));
+ EXPECT_EQ("1234", QuicTextUtils::Uint64ToString(1234));
+}
+
+TEST(QuicTextUtilsText, HexEncode) {
+ EXPECT_EQ("48656c6c6f", QuicTextUtils::HexEncode("Hello", 5));
+ EXPECT_EQ("48656c6c6f", QuicTextUtils::HexEncode("Hello World", 5));
+ EXPECT_EQ("48656c6c6f", QuicTextUtils::HexEncode("Hello"));
+ EXPECT_EQ("0102779cfa", QuicTextUtils::HexEncode("\x01\x02\x77\x9c\xfa"));
+}
+
+TEST(QuicTextUtilsText, HexDecode) {
+ EXPECT_EQ("Hello", QuicTextUtils::HexDecode("48656c6c6f"));
+ EXPECT_EQ("", QuicTextUtils::HexDecode(""));
+ EXPECT_EQ("\x01\x02\x77\x9c\xfa", QuicTextUtils::HexDecode("0102779cfa"));
+}
+
+TEST(QuicTextUtilsText, HexDump) {
+ // Verify output of the HexDump method is as expected.
+ char packet[] = {
+ 0x48, 0x65, 0x6c, 0x6c, 0x6f, 0x2c, 0x20, 0x51, 0x55, 0x49, 0x43, 0x21,
+ 0x20, 0x54, 0x68, 0x69, 0x73, 0x20, 0x73, 0x74, 0x72, 0x69, 0x6e, 0x67,
+ 0x20, 0x73, 0x68, 0x6f, 0x75, 0x6c, 0x64, 0x20, 0x62, 0x65, 0x20, 0x6c,
+ 0x6f, 0x6e, 0x67, 0x20, 0x65, 0x6e, 0x6f, 0x75, 0x67, 0x68, 0x20, 0x74,
+ 0x6f, 0x20, 0x73, 0x70, 0x61, 0x6e, 0x20, 0x6d, 0x75, 0x6c, 0x74, 0x69,
+ 0x70, 0x6c, 0x65, 0x20, 0x6c, 0x69, 0x6e, 0x65, 0x73, 0x20, 0x6f, 0x66,
+ 0x20, 0x6f, 0x75, 0x74, 0x70, 0x75, 0x74, 0x2e, 0x01, 0x02, 0x03, 0x00,
+ };
+ EXPECT_EQ(
+ QuicTextUtils::HexDump(packet),
+ "0x0000: 4865 6c6c 6f2c 2051 5549 4321 2054 6869 Hello,.QUIC!.Thi\n"
+ "0x0010: 7320 7374 7269 6e67 2073 686f 756c 6420 s.string.should.\n"
+ "0x0020: 6265 206c 6f6e 6720 656e 6f75 6768 2074 be.long.enough.t\n"
+ "0x0030: 6f20 7370 616e 206d 756c 7469 706c 6520 o.span.multiple.\n"
+ "0x0040: 6c69 6e65 7320 6f66 206f 7574 7075 742e lines.of.output.\n"
+ "0x0050: 0102 03 ...\n");
+}
+
+TEST(QuicTextUtilsText, Base64Encode) {
+ string output;
+ string input = "Hello";
+ QuicTextUtils::Base64Encode(reinterpret_cast<const uint8_t*>(input.data()),
+ input.length(), &output);
+ EXPECT_EQ("SGVsbG8", output);
+
+ input =
+ "Hello, QUIC! This string should be long enough to span"
+ "multiple lines of output\n";
+ QuicTextUtils::Base64Encode(reinterpret_cast<const uint8_t*>(input.data()),
+ input.length(), &output);
+ EXPECT_EQ(
+ "SGVsbG8sIFFVSUMhIFRoaXMgc3RyaW5nIHNob3VsZCBiZSBsb25n"
+ "IGVub3VnaCB0byBzcGFubXVsdGlwbGUgbGluZXMgb2Ygb3V0cHV0Cg",
+ output);
+}
+
+TEST(QuicTextUtilsText, ContainsUpperCase) {
+ EXPECT_FALSE(QuicTextUtils::ContainsUpperCase("abc"));
+ EXPECT_FALSE(QuicTextUtils::ContainsUpperCase(""));
+ EXPECT_FALSE(QuicTextUtils::ContainsUpperCase("123"));
+ EXPECT_TRUE(QuicTextUtils::ContainsUpperCase("ABC"));
+ EXPECT_TRUE(QuicTextUtils::ContainsUpperCase("aBc"));
+}
+
+TEST(QuicTextUtilsText, Split) {
+ EXPECT_EQ(std::vector<StringPiece>({"a", "b", "c"}),
+ QuicTextUtils::Split("a,b,c", ','));
+ EXPECT_EQ(std::vector<StringPiece>({"a", "b", "c"}),
+ QuicTextUtils::Split("a:b:c", ':'));
+ EXPECT_EQ(std::vector<StringPiece>({"a:b:c"}),
+ QuicTextUtils::Split("a:b:c", ','));
+}
+
+} // namespace test
+} // namespace net
diff --git a/chromium/net/quic/platform/impl/quic_aligned_impl.h b/chromium/net/quic/platform/impl/quic_aligned_impl.h
new file mode 100644
index 00000000000..eec157cb483
--- /dev/null
+++ b/chromium/net/quic/platform/impl/quic_aligned_impl.h
@@ -0,0 +1,22 @@
+// Copyright 2016 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.
+
+#ifndef NET_QUIC_PLATFORM_IMPL_QUIC_ALIGNED_IMPL_H_
+#define NET_QUIC_PLATFORM_IMPL_QUIC_ALIGNED_IMPL_H_
+
+#ifdef _MSC_VER
+// MSVC 2013 and prior don't have alignof or aligned(); they have __alignof and
+// a __declspec instead.
+#define QUIC_ALIGN_OF_IMPL __alignof
+#define QUIC_ALIGNED_IMPL(X) __declspec(align(X))
+#else
+#define QUIC_ALIGN_OF_IMPL alignof
+#define QUIC_ALIGNED_IMPL(X) __attribute__((aligned(X)))
+#endif // _MSC_VER
+
+// TODO(rtenneti): Change the default 64 alignas value (used the default
+// value from CACHELINE_SIZE).
+#define QUIC_CACHELINE_ALIGNED_IMPL ALIGNAS(64)
+
+#endif // NET_QUIC_PLATFORM_IMPL_QUIC_ALIGNED_IMPL_H_
diff --git a/chromium/net/quic/platform/impl/quic_bug_tracker_impl.h b/chromium/net/quic/platform/impl/quic_bug_tracker_impl.h
new file mode 100644
index 00000000000..16675042718
--- /dev/null
+++ b/chromium/net/quic/platform/impl/quic_bug_tracker_impl.h
@@ -0,0 +1,15 @@
+// Copyright (c) 2016 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.
+#ifndef NET_QUIC_PLATFORM_IMPL_QUIC_BUG_TRACKER_IMPL_H_
+#define NET_QUIC_PLATFORM_IMPL_QUIC_BUG_TRACKER_IMPL_H_
+
+#include "net/quic/platform/api/quic_logging.h"
+
+// For external QUIC, QUIC_BUG should be #defined to QUIC_LOG(DFATAL) and
+// QUIC_BUG_IF(condition) to QUIC LOG_IF(DFATAL, condition) as client-side log
+// rate limiting is less important and chrome doesn't QUIC_LOG_FIRST_N anyway.
+#define QUIC_BUG_IMPL QUIC_LOG(DFATAL)
+#define QUIC_BUG_IF_IMPL(condition) QUIC_LOG_IF(DFATAL, condition)
+
+#endif // NET_QUIC_PLATFORM_IMPL_QUIC_BUG_TRACKER_IMPL_H_
diff --git a/chromium/net/quic/platform/impl/quic_chromium_clock.cc b/chromium/net/quic/platform/impl/quic_chromium_clock.cc
new file mode 100644
index 00000000000..9493adae3d7
--- /dev/null
+++ b/chromium/net/quic/platform/impl/quic_chromium_clock.cc
@@ -0,0 +1,30 @@
+// Copyright (c) 2012 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.
+
+#include "net/quic/platform/impl/quic_chromium_clock.h"
+
+#include "base/time/time.h"
+
+namespace net {
+
+QuicChromiumClock::QuicChromiumClock() {}
+
+QuicChromiumClock::~QuicChromiumClock() {}
+
+QuicTime QuicChromiumClock::ApproximateNow() const {
+ // At the moment, Chrome does not have a distinct notion of ApproximateNow().
+ // We should consider implementing this using MessageLoop::recent_time_.
+ return Now();
+}
+
+QuicTime QuicChromiumClock::Now() const {
+ return QuicTime(base::TimeTicks::Now());
+}
+
+QuicWallTime QuicChromiumClock::WallNow() const {
+ return QuicWallTime::FromUNIXMicroseconds(base::Time::Now().ToJavaTime() *
+ 1000);
+}
+
+} // namespace net
diff --git a/chromium/net/quic/platform/impl/quic_chromium_clock.h b/chromium/net/quic/platform/impl/quic_chromium_clock.h
new file mode 100644
index 00000000000..33c7eab79b1
--- /dev/null
+++ b/chromium/net/quic/platform/impl/quic_chromium_clock.h
@@ -0,0 +1,32 @@
+// Copyright (c) 2012 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.
+
+#ifndef NET_QUIC_PLATFORM_IMPL_QUIC_CHROMIUM_CLOCK_H_
+#define NET_QUIC_PLATFORM_IMPL_QUIC_CHROMIUM_CLOCK_H_
+
+#include "base/time/time.h"
+#include "net/quic/platform/api/quic_clock.h"
+#include "net/quic/platform/api/quic_export.h"
+
+namespace net {
+
+// Clock to efficiently retrieve an approximately accurate time from an
+// EpollServer.
+class QUIC_EXPORT_PRIVATE QuicChromiumClock : public QuicClock {
+ public:
+ QuicChromiumClock();
+ ~QuicChromiumClock() override;
+
+ // QuicClock implementation:
+ QuicTime ApproximateNow() const override;
+ QuicTime Now() const override;
+ QuicWallTime WallNow() const override;
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(QuicChromiumClock);
+};
+
+} // namespace net
+
+#endif // NET_QUIC_PLATFORM_IMPL_QUIC_CHROMIUM_CLOCK_H_
diff --git a/chromium/net/quic/core/quic_clock_test.cc b/chromium/net/quic/platform/impl/quic_chromium_clock_test.cc
index f9d1f634e32..562a1565517 100644
--- a/chromium/net/quic/core/quic_clock_test.cc
+++ b/chromium/net/quic/platform/impl/quic_chromium_clock_test.cc
@@ -2,15 +2,15 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#include "net/quic/core/quic_clock.h"
+#include "net/quic/platform/impl/quic_chromium_clock.h"
#include "testing/gtest/include/gtest/gtest.h"
namespace net {
namespace test {
-TEST(QuicClockTest, Now) {
- QuicClock clock;
+TEST(QuicChromiumClockTest, Now) {
+ QuicChromiumClock clock;
QuicTime start(base::TimeTicks::Now());
QuicTime now = clock.ApproximateNow();
@@ -20,8 +20,8 @@ TEST(QuicClockTest, Now) {
EXPECT_LE(now, end);
}
-TEST(QuicClockTest, WallNow) {
- QuicClock clock;
+TEST(QuicChromiumClockTest, WallNow) {
+ QuicChromiumClock clock;
base::Time start = base::Time::Now();
QuicWallTime now = clock.WallNow();
diff --git a/chromium/net/quic/platform/impl/quic_export_impl.h b/chromium/net/quic/platform/impl/quic_export_impl.h
new file mode 100644
index 00000000000..cbf2ea475ed
--- /dev/null
+++ b/chromium/net/quic/platform/impl/quic_export_impl.h
@@ -0,0 +1,13 @@
+// Copyright 2016 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.
+
+#ifndef NET_QUIC_PLATFORM_IMPL_QUIC_EXPORT_IMPL_H_
+#define NET_QUIC_PLATFORM_IMPL_QUIC_EXPORT_IMPL_H_
+
+#include "net/base/net_export.h"
+
+#define QUIC_EXPORT NET_EXPORT
+#define QUIC_EXPORT_PRIVATE NET_EXPORT_PRIVATE
+
+#endif // NET_QUIC_PLATFORM_IMPL_QUIC_EXPORT_IMPL_H_
diff --git a/chromium/net/quic/platform/impl/quic_ip_address_impl.cc b/chromium/net/quic/platform/impl/quic_ip_address_impl.cc
new file mode 100644
index 00000000000..e0c58f14ec8
--- /dev/null
+++ b/chromium/net/quic/platform/impl/quic_ip_address_impl.cc
@@ -0,0 +1,133 @@
+// Copyright (c) 2016 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.
+
+#include "net/quic/platform/impl/quic_ip_address_impl.h"
+
+#include "net/base/address_family.h"
+#include "net/quic/platform/api/quic_bug_tracker.h"
+
+#if defined(OS_WIN)
+#include <winsock2.h>
+#include <ws2bth.h>
+#elif defined(OS_POSIX)
+#include <netinet/in.h>
+#endif
+
+using std::string;
+
+namespace net {
+
+QuicIpAddressImpl QuicIpAddressImpl::Loopback4() {
+ return QuicIpAddressImpl(IPAddress::IPv4Localhost());
+}
+
+QuicIpAddressImpl QuicIpAddressImpl::Loopback6() {
+ return QuicIpAddressImpl(IPAddress::IPv6Localhost());
+}
+
+QuicIpAddressImpl QuicIpAddressImpl::Any4() {
+ return QuicIpAddressImpl(IPAddress::IPv4AllZeros());
+}
+
+QuicIpAddressImpl QuicIpAddressImpl::Any6() {
+ return QuicIpAddressImpl(IPAddress::IPv6AllZeros());
+}
+
+QuicIpAddressImpl::QuicIpAddressImpl(const IPAddress& addr)
+ : ip_address_(addr) {}
+
+bool operator==(QuicIpAddressImpl lhs, QuicIpAddressImpl rhs) {
+ return lhs.ip_address_ == rhs.ip_address_;
+}
+
+bool operator!=(QuicIpAddressImpl lhs, QuicIpAddressImpl rhs) {
+ return !(lhs == rhs);
+}
+
+bool QuicIpAddressImpl::IsInitialized() const {
+ return net::GetAddressFamily(ip_address_) != net::ADDRESS_FAMILY_UNSPECIFIED;
+}
+
+IpAddressFamily QuicIpAddressImpl::address_family() const {
+ switch (net::GetAddressFamily(ip_address_)) {
+ case net::ADDRESS_FAMILY_IPV4:
+ return IpAddressFamily::IP_V4;
+ case net::ADDRESS_FAMILY_IPV6:
+ return IpAddressFamily::IP_V6;
+ case net::ADDRESS_FAMILY_UNSPECIFIED:
+ break;
+ default:
+ QUIC_BUG << "Invalid address family "
+ << net::GetAddressFamily(ip_address_);
+ }
+ return IpAddressFamily::IP_UNSPEC;
+}
+
+int QuicIpAddressImpl::AddressFamilyToInt() const {
+ switch (ip_address_.size()) {
+ case IPAddress::kIPv4AddressSize:
+ return AF_INET;
+ case IPAddress::kIPv6AddressSize:
+ return AF_INET6;
+ default:
+ NOTREACHED() << "Bad IP address";
+ return AF_UNSPEC;
+ }
+}
+
+string QuicIpAddressImpl::ToPackedString() const {
+ return IPAddressToPackedString(ip_address_);
+}
+
+string QuicIpAddressImpl::ToString() const {
+ if (!IsInitialized()) {
+ return "Uninitialized address";
+ }
+ return ip_address_.ToString();
+}
+
+QuicIpAddressImpl QuicIpAddressImpl::Normalized() const {
+ if (ip_address_.IsIPv4MappedIPv6()) {
+ return QuicIpAddressImpl(ConvertIPv4MappedIPv6ToIPv4(ip_address_));
+ }
+ return QuicIpAddressImpl(ip_address_);
+}
+
+QuicIpAddressImpl QuicIpAddressImpl::DualStacked() const {
+ if (ip_address_.IsIPv4()) {
+ return QuicIpAddressImpl(ConvertIPv4ToIPv4MappedIPv6(ip_address_));
+ }
+ return QuicIpAddressImpl(ip_address_);
+}
+
+bool QuicIpAddressImpl::FromPackedString(const char* data, size_t length) {
+ if (length != IPAddress::kIPv4AddressSize &&
+ length != IPAddress::kIPv6AddressSize) {
+ QUIC_BUG << "Invalid packed IP address of length " << length;
+ return false;
+ }
+ std::vector<uint8_t> ip(length);
+ memcpy(&ip[0], data, length);
+ ip_address_ = IPAddress(ip);
+ return true;
+}
+
+bool QuicIpAddressImpl::FromString(string str) {
+ return ip_address_.AssignFromIPLiteral(str);
+}
+
+bool QuicIpAddressImpl::IsIPv4() const {
+ return ip_address_.IsIPv4();
+}
+
+bool QuicIpAddressImpl::IsIPv6() const {
+ return ip_address_.IsIPv6();
+}
+
+bool QuicIpAddressImpl::InSameSubnet(const QuicIpAddressImpl& other,
+ int subnet_length) {
+ return IPAddressMatchesPrefix(ip_address_, other.ip_address(), subnet_length);
+}
+
+} // namespace net
diff --git a/chromium/net/quic/platform/impl/quic_ip_address_impl.h b/chromium/net/quic/platform/impl/quic_ip_address_impl.h
new file mode 100644
index 00000000000..c2b0d895afa
--- /dev/null
+++ b/chromium/net/quic/platform/impl/quic_ip_address_impl.h
@@ -0,0 +1,52 @@
+// Copyright (c) 2016 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.
+
+#ifndef NET_QUIC_PLATFORM_IMPL_QUIC_IP_ADDRESS_IMPL_H_
+#define NET_QUIC_PLATFORM_IMPL_QUIC_IP_ADDRESS_IMPL_H_
+
+#include <string>
+
+#include "net/base/ip_address.h"
+#include "net/quic/platform/api/quic_export.h"
+#include "net/quic/platform/api/quic_ip_address_family.h"
+
+namespace net {
+
+class QUIC_EXPORT_PRIVATE QuicIpAddressImpl {
+ public:
+ static QuicIpAddressImpl Loopback4();
+ static QuicIpAddressImpl Loopback6();
+ static QuicIpAddressImpl Any4();
+ static QuicIpAddressImpl Any6();
+
+ QuicIpAddressImpl() = default;
+ QuicIpAddressImpl(const QuicIpAddressImpl& other) = default;
+ explicit QuicIpAddressImpl(const IPAddress& addr);
+ QuicIpAddressImpl& operator=(const QuicIpAddressImpl& other) = default;
+ QuicIpAddressImpl& operator=(QuicIpAddressImpl&& other) = default;
+ friend bool operator==(QuicIpAddressImpl lhs, QuicIpAddressImpl rhs);
+ friend bool operator!=(QuicIpAddressImpl lhs, QuicIpAddressImpl rhs);
+
+ bool IsInitialized() const;
+ IpAddressFamily address_family() const;
+ int AddressFamilyToInt() const;
+ std::string ToPackedString() const;
+ std::string ToString() const;
+ QuicIpAddressImpl Normalized() const;
+ QuicIpAddressImpl DualStacked() const;
+ bool FromPackedString(const char* data, size_t length);
+ bool FromString(std::string str);
+ bool IsIPv4() const;
+ bool IsIPv6() const;
+
+ bool InSameSubnet(const QuicIpAddressImpl& other, int subnet_length);
+ const IPAddress& ip_address() const { return ip_address_; }
+
+ private:
+ IPAddress ip_address_;
+};
+
+} // namespace net
+
+#endif // NET_QUIC_PLATFORM_IMPL_QUIC_IP_ADDRESS_IMPL_H_
diff --git a/chromium/net/quic/platform/impl/quic_logging_impl.h b/chromium/net/quic/platform/impl/quic_logging_impl.h
new file mode 100644
index 00000000000..000b20b95e1
--- /dev/null
+++ b/chromium/net/quic/platform/impl/quic_logging_impl.h
@@ -0,0 +1,47 @@
+// Copyright (c) 2017 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.
+
+#ifndef NET_QUIC_PLATFORM_IMPL_QUIC_LOGGING_IMPL_H_
+#define NET_QUIC_PLATFORM_IMPL_QUIC_LOGGING_IMPL_H_
+
+#include "base/logging.h"
+
+#define QUIC_LOG_IMPL(severity) QUIC_CHROMIUM_LOG_##severity
+#define QUIC_LOG_EVERY_N_SEC_IMPL(severity, seconds) QUIC_LOG_IMPL(severity)
+#define QUIC_LOG_FIRST_N_IMPL(severity, n) QUIC_LOG_IMPL(severity)
+#define QUIC_DLOG_IMPL(severity) QUIC_CHROMIUM_DLOG_##severity
+#define QUIC_LOG_IF_IMPL(severity, condition) \
+ QUIC_CHROMIUM_LOG_IF_##severity(condition)
+
+#define QUIC_CHROMIUM_LOG_INFO VLOG(1)
+#define QUIC_CHROMIUM_LOG_WARNING DLOG(WARNING)
+#define QUIC_CHROMIUM_LOG_ERROR DLOG(ERROR)
+#define QUIC_CHROMIUM_LOG_FATAL LOG(FATAL)
+#define QUIC_CHROMIUM_LOG_DFATAL LOG(DFATAL)
+
+#define QUIC_CHROMIUM_DLOG_INFO DVLOG(1)
+#define QUIC_CHROMIUM_DLOG_WARNING DLOG(WARNING)
+#define QUIC_CHROMIUM_DLOG_ERROR DLOG(ERROR)
+#define QUIC_CHROMIUM_DLOG_FATAL DLOG(FATAL)
+#define QUIC_CHROMIUM_DLOG_DFATAL DLOG(DFATAL)
+
+#define QUIC_CHROMIUM_LOG_IF_INFO(condition) VLOG_IF(1, condition)
+#define QUIC_CHROMIUM_LOG_IF_WARNING(condition) DLOG_IF(WARNING, condition)
+#define QUIC_CHROMIUM_LOG_IF_ERROR(condition) DLOG_IF(ERROR, condition)
+#define QUIC_CHROMIUM_LOG_IF_FATAL(condition) LOG_IF(FATAL, condition)
+#define QUIC_CHROMIUM_LOG_IF_DFATAL(condition) LOG_IF(DFATAL, condition)
+
+#define QUIC_DVLOG_IMPL(verbose_level) DVLOG(verbose_level)
+
+#if defined(OS_WIN)
+// wingdi.h defines ERROR to be 0. When we call QUIC_DLOG(ERROR), it gets
+// substituted with 0, and it expands to QUIC_CHROMIUM_DLOG_0. To allow us to
+// keep using this syntax, we define this macro to do the same thing as
+// QUIC_CHROMIUM_DLOG_ERROR.
+#define QUIC_CHROMIUM_LOG_0 QUIC_CHROMIUM_LOG_ERROR
+#define QUIC_CHROMIUM_DLOG_0 QUIC_CHROMIUM_DLOG_ERROR
+#define QUIC_CHROMIUM_LOG_IF_0 QUIC_CHROMIUM_LOG_IF_ERROR
+#endif
+
+#endif // NET_QUIC_PLATFORM_IMPL_QUIC_LOGGING_IMPL_H_
diff --git a/chromium/net/quic/platform/impl/quic_lru_cache_impl.h b/chromium/net/quic/platform/impl/quic_lru_cache_impl.h
new file mode 100644
index 00000000000..18f337196d0
--- /dev/null
+++ b/chromium/net/quic/platform/impl/quic_lru_cache_impl.h
@@ -0,0 +1,50 @@
+// Copyright (c) 2016 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.
+
+#ifndef NET_QUIC_PLATFORM_IMPL_QUIC_LRU_CACHE_IMPL_H_
+#define NET_QUIC_PLATFORM_IMPL_QUIC_LRU_CACHE_IMPL_H_
+
+#include "base/containers/mru_cache.h"
+
+namespace net {
+
+template <class K, class V>
+class QuicLRUCacheImpl {
+ public:
+ explicit QuicLRUCacheImpl(int64_t total_units) : mru_cache_(total_units) {}
+
+ // Inserts one unit of |key|, |value| pair to the cache.
+ void Insert(const K& key, std::unique_ptr<V> value) {
+ mru_cache_.Put(key, std::move(value));
+ }
+
+ // If cache contains an entry for |key|, return a pointer to it. This returned
+ // value is guaranteed to be valid until Insert or Clear.
+ // Else return nullptr.
+ V* Lookup(const K& key) {
+ auto cached_it = mru_cache_.Get(key);
+ if (cached_it != mru_cache_.end()) {
+ return cached_it->second.get();
+ }
+ return nullptr;
+ }
+
+ // Removes all entries from the cache.
+ void Clear() { mru_cache_.Clear(); }
+
+ // Returns maximum size of the cache.
+ int64_t MaxSize() const { return mru_cache_.max_size(); }
+
+ // Returns current size of the cache.
+ int64_t Size() const { return mru_cache_.size(); }
+
+ private:
+ base::MRUCache<K, std::unique_ptr<V>> mru_cache_;
+
+ DISALLOW_COPY_AND_ASSIGN(QuicLRUCacheImpl);
+};
+
+} // namespace net
+
+#endif // NET_QUIC_PLATFORM_IMPL_QUIC_LRU_CACHE_IMPL_H_
diff --git a/chromium/net/quic/platform/impl/quic_mutex_impl.cc b/chromium/net/quic/platform/impl/quic_mutex_impl.cc
new file mode 100644
index 00000000000..95e46c1947f
--- /dev/null
+++ b/chromium/net/quic/platform/impl/quic_mutex_impl.cc
@@ -0,0 +1,25 @@
+// Copyright (c) 2016 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.
+
+#include "net/quic/platform/impl/quic_mutex_impl.h"
+
+namespace net {
+
+void QuicLockImpl::WriterLock() {
+ lock_.Acquire();
+}
+
+void QuicLockImpl::WriterUnlock() {
+ lock_.Release();
+}
+
+void QuicLockImpl::ReaderLock() {
+ lock_.Acquire();
+}
+
+void QuicLockImpl::ReaderUnlock() {
+ lock_.Release();
+}
+
+} // namespace net
diff --git a/chromium/net/quic/platform/impl/quic_mutex_impl.h b/chromium/net/quic/platform/impl/quic_mutex_impl.h
new file mode 100644
index 00000000000..8053514eab5
--- /dev/null
+++ b/chromium/net/quic/platform/impl/quic_mutex_impl.h
@@ -0,0 +1,73 @@
+// Copyright (c) 2016 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.
+
+#ifndef NET_QUIC_PLATFORM_IMPL_QUIC_MUTEX_IMPL_H_
+#define NET_QUIC_PLATFORM_IMPL_QUIC_MUTEX_IMPL_H_
+
+#include "base/synchronization/lock.h"
+#include "net/quic/platform/api/quic_export.h"
+
+#ifndef EXCLUSIVE_LOCK_FUNCTION
+#define EXCLUSIVE_LOCK_FUNCTION(...)
+#endif
+
+#ifndef UNLOCK_FUNCTION
+#define UNLOCK_FUNCTION(...)
+#endif
+
+#ifndef SHARED_LOCK_FUNCTION
+#define SHARED_LOCK_FUNCTION(...)
+#endif
+
+#ifndef ASSERT_SHARED_LOCK
+#define ASSERT_SHARED_LOCK(...)
+#endif
+
+#ifndef LOCKABLE
+#define LOCKABLE
+#endif
+
+#ifndef SCOPED_LOCKABLE
+#define SCOPED_LOCKABLE
+#endif
+
+#ifndef GUARDED_BY
+#define GUARDED_BY(x)
+#endif
+
+#ifndef SHARED_LOCKS_REQUIRED
+#define SHARED_LOCKS_REQUIRED(...)
+#endif
+
+namespace net {
+
+// A class wrapping a non-reentrant mutex.
+class QUIC_EXPORT_PRIVATE QuicLockImpl {
+ public:
+ QuicLockImpl() = default;
+
+ // Block until lock_ is free, then acquire it exclusively.
+ void WriterLock() EXCLUSIVE_LOCK_FUNCTION();
+
+ // Release lock_. Caller must hold it exclusively.
+ void WriterUnlock() UNLOCK_FUNCTION();
+
+ // Block until lock_ is free or shared, then acquire a share of it.
+ void ReaderLock() SHARED_LOCK_FUNCTION();
+
+ // Release lock_. Caller could hold it in shared mode.
+ void ReaderUnlock() UNLOCK_FUNCTION();
+
+ // Not implemented.
+ void AssertReaderHeld() const ASSERT_SHARED_LOCK() {}
+
+ private:
+ base::Lock lock_;
+
+ DISALLOW_COPY_AND_ASSIGN(QuicLockImpl);
+};
+
+} // namespace net
+
+#endif // NET_QUIC_PLATFORM_IMPL_QUIC_MUTEX_IMPL_H_
diff --git a/chromium/net/quic/platform/impl/quic_ptr_util_impl.h b/chromium/net/quic/platform/impl/quic_ptr_util_impl.h
new file mode 100644
index 00000000000..b41ea4ec961
--- /dev/null
+++ b/chromium/net/quic/platform/impl/quic_ptr_util_impl.h
@@ -0,0 +1,23 @@
+// Copyright (c) 2017 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.
+#ifndef NET_QUIC_PLATFORM_IMPL_QUIC_PTR_UTIL_IMPL_H_
+#define NET_QUIC_PLATFORM_IMPL_QUIC_PTR_UTIL_IMPL_H_
+
+#include "base/memory/ptr_util.h"
+
+namespace net {
+
+template <typename T, typename... Args>
+std::unique_ptr<T> QuicMakeUniqueImpl(Args&&... args) {
+ return std::move(base::MakeUnique<T>(std::forward<Args>(args)...));
+}
+
+template <typename T>
+std::unique_ptr<T> QuicWrapUniqueImpl(T* ptr) {
+ return std::move(base::WrapUnique<T>(ptr));
+}
+
+} // namespace net
+
+#endif // NET_QUIC_PLATFORM_IMPL_QUIC_PTR_UTIL_IMPL_H_
diff --git a/chromium/net/quic/platform/impl/quic_reference_counted_impl.h b/chromium/net/quic/platform/impl/quic_reference_counted_impl.h
new file mode 100644
index 00000000000..0edd3c6309c
--- /dev/null
+++ b/chromium/net/quic/platform/impl/quic_reference_counted_impl.h
@@ -0,0 +1,114 @@
+// Copyright (c) 2016 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.
+
+#ifndef NET_QUIC_PLATFORM_IMPL_QUIC_REFERENCE_COUNTED_IMPL_H_
+#define NET_QUIC_PLATFORM_IMPL_QUIC_REFERENCE_COUNTED_IMPL_H_
+
+#include "base/memory/ref_counted.h"
+#include "net/quic/platform/api/quic_export.h"
+
+namespace net {
+
+class QUIC_EXPORT_PRIVATE QuicReferenceCountedImpl
+ : public base::RefCountedThreadSafe<QuicReferenceCountedImpl> {
+ public:
+ QuicReferenceCountedImpl() {}
+
+ protected:
+ virtual ~QuicReferenceCountedImpl() {}
+
+ private:
+ friend class base::RefCountedThreadSafe<QuicReferenceCountedImpl>;
+};
+
+template <class T>
+class QuicReferenceCountedPointerImpl {
+ public:
+ QuicReferenceCountedPointerImpl() = default;
+
+ // Constructor from raw pointer |p|. This guarantees the reference count of *p
+ // is 1. This should be only called when a new object is created, calling this
+ // on an already existent object does not increase its reference count.
+ explicit QuicReferenceCountedPointerImpl(T* p) : refptr_(p) {}
+
+ // Allows implicit conversion from nullptr.
+ QuicReferenceCountedPointerImpl(std::nullptr_t) // NOLINT
+ : refptr_(nullptr) {}
+
+ // Copy and copy conversion constructors. It does not take the reference away
+ // from |other| and they each end up with their own reference.
+ template <typename U>
+ QuicReferenceCountedPointerImpl( // NOLINT
+ const QuicReferenceCountedPointerImpl<U>& other)
+ : refptr_(other.refptr()) {}
+ QuicReferenceCountedPointerImpl(const QuicReferenceCountedPointerImpl& other)
+ : refptr_(other.refptr()) {}
+
+ // Move constructors. After move, It adopts the reference from |other|.
+ template <typename U>
+ QuicReferenceCountedPointerImpl( // NOLINT
+ QuicReferenceCountedPointerImpl<U>&& other)
+ : refptr_(std::move(other.refptr())) {}
+ QuicReferenceCountedPointerImpl(QuicReferenceCountedPointerImpl&& other)
+ : refptr_(std::move(other.refptr())) {}
+
+ ~QuicReferenceCountedPointerImpl() = default;
+
+ // Copy assignments.
+ QuicReferenceCountedPointerImpl& operator=(
+ const QuicReferenceCountedPointerImpl& other) {
+ refptr_ = other.refptr();
+ return *this;
+ }
+ template <typename U>
+ QuicReferenceCountedPointerImpl<T>& operator=(
+ const QuicReferenceCountedPointerImpl<U>& other) {
+ refptr_ = other.refptr();
+ return *this;
+ }
+
+ // Move assignments.
+ QuicReferenceCountedPointerImpl& operator=(
+ QuicReferenceCountedPointerImpl&& other) {
+ refptr_ = std::move(other.refptr());
+ return *this;
+ }
+ template <typename U>
+ QuicReferenceCountedPointerImpl<T>& operator=(
+ QuicReferenceCountedPointerImpl<U>&& other) {
+ refptr_ = std::move(other.refptr());
+ return *this;
+ }
+
+ explicit operator bool() const { return static_cast<bool>(refptr_); }
+
+ // Assignment operator on raw pointer. Drops a reference to current pointee,
+ // if any and replaces it with |p|. This garantee the reference count of *p is
+ // 1. This should only be used when a new object is created, calling this
+ // on a already existent object does not increase its reference count.
+ QuicReferenceCountedPointerImpl<T>& operator=(T* p) {
+ refptr_ = p;
+ return *this;
+ }
+ // Returns the raw pointer with no change in reference.
+ T* get() const { return refptr_.get(); }
+
+ // Accessors for the referenced object.
+ // operator* and operator-> will assert() if there is no current object.
+ T& operator*() const { return *refptr_; }
+ T* operator->() const {
+ assert(refptr_ != nullptr);
+ return refptr_.get();
+ }
+
+ scoped_refptr<T>& refptr() { return refptr_; }
+ const scoped_refptr<T>& refptr() const { return refptr_; }
+
+ private:
+ scoped_refptr<T> refptr_;
+};
+
+} // namespace net
+
+#endif // NET_QUIC_PLATFORM_IMPL_QUIC_REFERENCE_COUNTED_IMPL_H_
diff --git a/chromium/net/quic/platform/impl/quic_socket_address_impl.cc b/chromium/net/quic/platform/impl/quic_socket_address_impl.cc
new file mode 100644
index 00000000000..ae76f21aa03
--- /dev/null
+++ b/chromium/net/quic/platform/impl/quic_socket_address_impl.cc
@@ -0,0 +1,91 @@
+// Copyright (c) 2016 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.
+
+#include "net/quic/platform/impl/quic_socket_address_impl.h"
+
+#include "net/base/sockaddr_storage.h"
+#include "net/quic/platform/api/quic_bug_tracker.h"
+
+using std::string;
+
+namespace net {
+
+QuicSocketAddressImpl::QuicSocketAddressImpl(IPEndPoint address)
+ : socket_address_(address) {}
+
+QuicSocketAddressImpl::QuicSocketAddressImpl(QuicIpAddressImpl address,
+ uint16_t port)
+ : socket_address_(address.ip_address(), port) {}
+
+QuicSocketAddressImpl::QuicSocketAddressImpl(
+ const struct sockaddr_storage& saddr) {
+ if (saddr.ss_family == AF_INET) {
+ CHECK(socket_address_.FromSockAddr(
+ reinterpret_cast<const sockaddr*>(&saddr), sizeof(struct sockaddr_in)));
+ } else if (saddr.ss_family == AF_INET6) {
+ CHECK(
+ socket_address_.FromSockAddr(reinterpret_cast<const sockaddr*>(&saddr),
+ sizeof(struct sockaddr_in6)));
+ }
+}
+
+QuicSocketAddressImpl::QuicSocketAddressImpl(const struct sockaddr& saddr) {
+ QUIC_BUG << "QuicSocketAddressImpl(const struct sockaddr& saddr) is not "
+ "implemented.";
+}
+
+bool operator==(QuicSocketAddressImpl lhs, QuicSocketAddressImpl rhs) {
+ return lhs.socket_address_ == rhs.socket_address_;
+}
+
+bool operator!=(QuicSocketAddressImpl lhs, QuicSocketAddressImpl rhs) {
+ return lhs.socket_address_.address() != rhs.socket_address_.address() ||
+ lhs.socket_address_.port() != rhs.socket_address_.port();
+}
+
+bool QuicSocketAddressImpl::IsInitialized() const {
+ return net::GetAddressFamily(socket_address_.address()) !=
+ net::ADDRESS_FAMILY_UNSPECIFIED;
+ ;
+}
+
+string QuicSocketAddressImpl::ToString() const {
+ if (!IsInitialized()) {
+ return "Uninitialized address";
+ }
+ return socket_address_.ToString();
+}
+
+int QuicSocketAddressImpl::FromSocket(int fd) {
+ SockaddrStorage storage;
+ if (getsockname(fd, storage.addr, &storage.addr_len) != 0 ||
+ !socket_address_.FromSockAddr(storage.addr, storage.addr_len)) {
+ return 1;
+ }
+
+ return 0;
+}
+
+QuicSocketAddressImpl QuicSocketAddressImpl::Normalized() const {
+ QUIC_BUG << "QuicSocketAddressImpl::Normalized() is not implemented.";
+ return QuicSocketAddressImpl();
+}
+
+QuicIpAddressImpl QuicSocketAddressImpl::host() const {
+ return QuicIpAddressImpl(socket_address_.address());
+}
+
+uint16_t QuicSocketAddressImpl::port() const {
+ return socket_address_.port();
+}
+
+sockaddr_storage QuicSocketAddressImpl::generic_address() const {
+ sockaddr_storage raw_address;
+ socklen_t address_len = sizeof(raw_address);
+ CHECK(socket_address_.ToSockAddr(
+ reinterpret_cast<struct sockaddr*>(&raw_address), &address_len));
+ return raw_address;
+}
+
+} // namespace net
diff --git a/chromium/net/quic/platform/impl/quic_socket_address_impl.h b/chromium/net/quic/platform/impl/quic_socket_address_impl.h
new file mode 100644
index 00000000000..e5648f236e6
--- /dev/null
+++ b/chromium/net/quic/platform/impl/quic_socket_address_impl.h
@@ -0,0 +1,45 @@
+// Copyright (c) 2016 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.
+
+#ifndef NET_QUIC_PLATFORM_IMPL_QUIC_SOCKET_ADDRESS_IMPL_H_
+#define NET_QUIC_PLATFORM_IMPL_QUIC_SOCKET_ADDRESS_IMPL_H_
+
+#include "net/base/ip_endpoint.h"
+#include "net/quic/platform/api/quic_export.h"
+#include "net/quic/platform/impl/quic_ip_address_impl.h"
+
+namespace net {
+
+class QUIC_EXPORT_PRIVATE QuicSocketAddressImpl {
+ public:
+ QuicSocketAddressImpl() = default;
+ explicit QuicSocketAddressImpl(IPEndPoint addr);
+ QuicSocketAddressImpl(QuicIpAddressImpl address, uint16_t port);
+ explicit QuicSocketAddressImpl(const struct sockaddr_storage& saddr);
+ explicit QuicSocketAddressImpl(const struct sockaddr& saddr);
+ QuicSocketAddressImpl(const QuicSocketAddressImpl& other) = default;
+ QuicSocketAddressImpl& operator=(const QuicSocketAddressImpl& other) =
+ default;
+ QuicSocketAddressImpl& operator=(QuicSocketAddressImpl&& other) = default;
+ friend bool operator==(QuicSocketAddressImpl lhs, QuicSocketAddressImpl rhs);
+ friend bool operator!=(QuicSocketAddressImpl lhs, QuicSocketAddressImpl rhs);
+
+ bool IsInitialized() const;
+ std::string ToString() const;
+ int FromSocket(int fd);
+ QuicSocketAddressImpl Normalized() const;
+
+ QuicIpAddressImpl host() const;
+ uint16_t port() const;
+
+ sockaddr_storage generic_address() const;
+ const IPEndPoint& socket_address() const { return socket_address_; }
+
+ private:
+ IPEndPoint socket_address_;
+};
+
+} // namespace net
+
+#endif // NET_QUIC_PLATFORM_IMPL_QUIC_SOCKET_ADDRESS_IMPL_H_
diff --git a/chromium/net/quic/platform/impl/quic_str_cat_impl.h b/chromium/net/quic/platform/impl/quic_str_cat_impl.h
new file mode 100644
index 00000000000..1989e8df5d5
--- /dev/null
+++ b/chromium/net/quic/platform/impl/quic_str_cat_impl.h
@@ -0,0 +1,23 @@
+// Copyright (c) 2016 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.
+
+#ifndef NET_QUIC_PLATFORM_IMPL_QUIC_STR_CAT_IMPL_H_
+#define NET_QUIC_PLATFORM_IMPL_QUIC_STR_CAT_IMPL_H_
+
+#include <sstream>
+#include <string>
+
+namespace net {
+
+template <typename... Args>
+inline std::string QuicStrCatImpl(const Args&... args) {
+ std::ostringstream oss;
+ int dummy[] = {1, (oss << args, 0)...};
+ static_cast<void>(dummy);
+ return oss.str();
+}
+
+} // namespace net
+
+#endif // NET_QUIC_PLATFORM_IMPL_QUIC_STR_CAT_IMPL_H_
diff --git a/chromium/net/quic/platform/impl/quic_text_utils_impl.h b/chromium/net/quic/platform/impl/quic_text_utils_impl.h
new file mode 100644
index 00000000000..a3cce167695
--- /dev/null
+++ b/chromium/net/quic/platform/impl/quic_text_utils_impl.h
@@ -0,0 +1,146 @@
+// Copyright 2016 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.
+
+#ifndef NET_QUIC_PLATFORM_IMPL_QUIC_TEXT_UTILS_IMPL_H_
+#define NET_QUIC_PLATFORM_IMPL_QUIC_TEXT_UTILS_IMPL_H_
+
+#include <algorithm>
+
+#include "base/base64.h"
+#include "base/strings/string_number_conversions.h"
+#include "base/strings/string_piece.h"
+#include "base/strings/string_split.h"
+#include "base/strings/string_util.h"
+#include "base/strings/stringprintf.h"
+
+namespace net {
+
+// google3 implementation of QuicTextUtils.
+class QuicTextUtilsImpl {
+ public:
+ // Returns true of |data| starts with |prefix|, case sensitively.
+ static bool StartsWith(base::StringPiece data, base::StringPiece prefix) {
+ return base::StartsWith(data, prefix, base::CompareCase::SENSITIVE);
+ }
+
+ // Returns true of |data| ends with |suffix|, case insensitively.
+ static bool EndsWithIgnoreCase(base::StringPiece data,
+ base::StringPiece suffix) {
+ return base::EndsWith(data, suffix, base::CompareCase::INSENSITIVE_ASCII);
+ }
+
+ // Returns a new std::string in which |data| has been converted to lower case.
+ static std::string ToLower(base::StringPiece data) {
+ return base::ToLowerASCII(data);
+ }
+
+ // Remove leading and trailing whitespace from |data|.
+ static void RemoveLeadingAndTrailingWhitespace(base::StringPiece* data) {
+ *data = base::TrimWhitespaceASCII(*data, base::TRIM_ALL);
+ }
+
+ // Returns true if |in| represents a valid uint64, and stores that value in
+ // |out|.
+ static bool StringToUint64(base::StringPiece in, uint64_t* out) {
+ return base::StringToUint64(in, out);
+ }
+
+ // Returns a new std::string representing |in|.
+ static std::string Uint64ToString(uint64_t in) {
+ return base::Uint64ToString(in);
+ }
+
+ // This converts |length| bytes of binary to a 2*|length|-character
+ // hexadecimal representation.
+ // Return value: 2*|length| characters of ASCII std::string.
+ static std::string HexEncode(base::StringPiece data) {
+ return base::ToLowerASCII(::base::HexEncode(data.data(), data.size()));
+ }
+
+ // Converts |data| from a hexadecimal ASCII string to a binary string
+ // that is |data.length()/2| bytes long.
+ static std::string HexDecode(base::StringPiece data) {
+ if (data.empty())
+ return "";
+ std::vector<uint8_t> v;
+ if (!base::HexStringToBytes(data.as_string(), &v))
+ return "";
+ std::string out;
+ if (!v.empty())
+ out.assign(reinterpret_cast<const char*>(&v[0]), v.size());
+ return out;
+ }
+
+ // Base64 encodes with no padding |data_len| bytes of |data| into |output|.
+ static void Base64Encode(const uint8_t* data,
+ size_t data_len,
+ std::string* output) {
+ base::Base64Encode(
+ std::string(reinterpret_cast<const char*>(data), data_len), output);
+ // Remove padding.
+ size_t len = output->size();
+ if (len >= 2) {
+ if ((*output)[len - 1] == '=') {
+ len--;
+ if ((*output)[len - 1] == '=') {
+ len--;
+ }
+ output->resize(len);
+ }
+ }
+ }
+
+ // Returns a std::string containing hex and ASCII representations of |binary|,
+ // side-by-side in the style of hexdump. Non-printable characters will be
+ // printed as '.' in the ASCII output.
+ // For example, given the input "Hello, QUIC!\01\02\03\04", returns:
+ // "0x0000: 4865 6c6c 6f2c 2051 5549 4321 0102 0304 Hello,.QUIC!...."
+ static std::string HexDump(base::StringPiece binary_input) {
+ int offset = 0;
+ const int kBytesPerLine = 16; // Max bytes dumped per line
+ const char* buf = binary_input.data();
+ int bytes_remaining = binary_input.size();
+ std::string s; // our output
+ const char* p = buf;
+ while (bytes_remaining > 0) {
+ const int line_bytes = std::min(bytes_remaining, kBytesPerLine);
+ base::StringAppendF(&s, "0x%04x: ", offset); // Do the line header
+ for (int i = 0; i < kBytesPerLine; ++i) {
+ if (i < line_bytes) {
+ base::StringAppendF(&s, "%02x", static_cast<unsigned char>(p[i]));
+ } else {
+ s += " "; // two-space filler instead of two-space hex digits
+ }
+ if (i % 2)
+ s += ' ';
+ }
+ s += ' ';
+ for (int i = 0; i < line_bytes; ++i) { // Do the ASCII dump
+ s += (p[i] > 32 && p[i] < 127) ? p[i] : '.';
+ }
+
+ bytes_remaining -= line_bytes;
+ offset += line_bytes;
+ p += line_bytes;
+ s += '\n';
+ }
+ return s;
+ }
+
+ // Returns true if |data| contains any uppercase characters.
+ static bool ContainsUpperCase(base::StringPiece data) {
+ return std::any_of(data.begin(), data.end(), base::IsAsciiUpper<char>);
+ }
+
+ // Splits |data| into a vector of pieces delimited by |delim|.
+ static std::vector<base::StringPiece> Split(base::StringPiece data,
+ char delim) {
+ return base::SplitStringPiece(data, base::StringPiece(&delim, 1),
+ base::TRIM_WHITESPACE, base::SPLIT_WANT_ALL);
+ }
+};
+
+} // namespace net
+
+#endif // NET_QUIC_PLATFORM_IMPL_QUIC_TEXT_UTILS_IMPL_H_
diff --git a/chromium/net/quic/quartc/quartc_alarm_factory.h b/chromium/net/quic/quartc/quartc_alarm_factory.h
index 49005d92bc8..12fd8169590 100644
--- a/chromium/net/quic/quartc/quartc_alarm_factory.h
+++ b/chromium/net/quic/quartc/quartc_alarm_factory.h
@@ -7,9 +7,9 @@
#include <utility>
-#include "net/base/net_export.h"
#include "net/quic/core/quic_alarm_factory.h"
-#include "net/quic/core/quic_clock.h"
+#include "net/quic/platform/api/quic_clock.h"
+#include "net/quic/platform/api/quic_export.h"
namespace base {
class TaskRunner;
@@ -20,7 +20,7 @@ namespace net {
// Creates Chromium-based QuartcAlarms used throughout QUIC. The alarm posts
// messages to the Chromium message queue for tasks such as retransmission.
// Used for the tests inside Chromium.
-class NET_EXPORT_PRIVATE QuartcAlarmFactory : public QuicAlarmFactory {
+class QUIC_EXPORT_PRIVATE QuartcAlarmFactory : public QuicAlarmFactory {
public:
QuartcAlarmFactory(base::TaskRunner* task_runner, const QuicClock* clock);
~QuartcAlarmFactory() override;
diff --git a/chromium/net/quic/quartc/quartc_factory.cc b/chromium/net/quic/quartc/quartc_factory.cc
index bcf81465edf..6a90bd614b5 100644
--- a/chromium/net/quic/quartc/quartc_factory.cc
+++ b/chromium/net/quic/quartc/quartc_factory.cc
@@ -118,7 +118,8 @@ std::unique_ptr<QuicConnection> QuartcFactory::CreateQuicConnection(
QuicConnectionId dummy_id = 0;
IPEndPoint dummy_address(IPAddress(0, 0, 0, 0), 0 /*Port*/);
return std::unique_ptr<QuicConnection>(new QuicConnection(
- dummy_id, dummy_address, this, /*QuicConnectionHelperInterface*/
+ dummy_id, QuicSocketAddress(QuicSocketAddressImpl(dummy_address)),
+ this, /*QuicConnectionHelperInterface*/
this /*QuicAlarmFactory*/, writer.release(), true /*own the writer*/,
perspective, AllSupportedVersions()));
}
diff --git a/chromium/net/quic/quartc/quartc_factory.h b/chromium/net/quic/quartc/quartc_factory.h
index d91441f1d76..28fd42a5ce5 100644
--- a/chromium/net/quic/quartc/quartc_factory.h
+++ b/chromium/net/quic/quartc/quartc_factory.h
@@ -7,11 +7,11 @@
#include "base/at_exit.h"
#include "base/message_loop/message_loop.h"
-#include "net/base/net_export.h"
#include "net/quic/core/quic_alarm_factory.h"
-#include "net/quic/core/quic_clock.h"
#include "net/quic/core/quic_connection.h"
#include "net/quic/core/quic_simple_buffer_allocator.h"
+#include "net/quic/platform/api/quic_export.h"
+#include "net/quic/platform/impl/quic_chromium_clock.h"
#include "net/quic/quartc/quartc_alarm_factory.h"
#include "net/quic/quartc/quartc_factory_interface.h"
#include "net/quic/quartc/quartc_packet_writer.h"
@@ -23,9 +23,9 @@ namespace net {
// QuartcSessionInterface. Implements the QuicAlarmFactory to create alarms
// using the QuartcTaskRunner. Implements the QuicConnectionHelperInterface used
// by the QuicConnections. Only one QuartcFactory is expected to be created.
-class NET_EXPORT_PRIVATE QuartcFactory : public QuartcFactoryInterface,
- public QuicAlarmFactory,
- public QuicConnectionHelperInterface {
+class QUIC_EXPORT_PRIVATE QuartcFactory : public QuartcFactoryInterface,
+ public QuicAlarmFactory,
+ public QuicConnectionHelperInterface {
public:
QuartcFactory(const QuartcFactoryConfig& factory_config);
~QuartcFactory() override;
@@ -56,7 +56,7 @@ class NET_EXPORT_PRIVATE QuartcFactory : public QuartcFactoryInterface,
// Used to implement QuicAlarmFactory..
std::unique_ptr<QuartcTaskRunnerInterface> task_runner_;
// Used to implement the QuicConnectionHelperInterface.
- QuicClock clock_;
+ QuicChromiumClock clock_;
SimpleBufferAllocator buffer_allocator_;
// An AtExitManager owned by the QuartcFactory to manage the lifetime of
// Singletons.
diff --git a/chromium/net/quic/quartc/quartc_factory_interface.h b/chromium/net/quic/quartc/quartc_factory_interface.h
index 900ea70b74a..fe9c2bd77fd 100644
--- a/chromium/net/quic/quartc/quartc_factory_interface.h
+++ b/chromium/net/quic/quartc/quartc_factory_interface.h
@@ -10,14 +10,14 @@
#include <memory>
-#include "net/base/net_export.h"
+#include "net/quic/platform/api/quic_export.h"
#include "net/quic/quartc/quartc_session_interface.h"
#include "net/quic/quartc/quartc_task_runner_interface.h"
namespace net {
// Used to create instances for Quartc objects such as QuartcSession.
-class NET_EXPORT_PRIVATE QuartcFactoryInterface {
+class QUIC_EXPORT_PRIVATE QuartcFactoryInterface {
public:
virtual ~QuartcFactoryInterface() {}
@@ -55,7 +55,7 @@ struct QuartcFactoryConfig {
};
// Creates a new instance of QuartcFactoryInterface.
-NET_EXPORT_PRIVATE std::unique_ptr<QuartcFactoryInterface> CreateQuartcFactory(
+QUIC_EXPORT_PRIVATE std::unique_ptr<QuartcFactoryInterface> CreateQuartcFactory(
const QuartcFactoryConfig& factory_config);
} // namespace net
diff --git a/chromium/net/quic/quartc/quartc_packet_writer.cc b/chromium/net/quic/quartc/quartc_packet_writer.cc
index bfe8aa93124..9ad7bdf8fae 100644
--- a/chromium/net/quic/quartc/quartc_packet_writer.cc
+++ b/chromium/net/quic/quartc/quartc_packet_writer.cc
@@ -13,11 +13,12 @@ QuartcPacketWriter::QuartcPacketWriter(
QuicByteCount max_packet_size)
: packet_transport_(packet_transport), max_packet_size_(max_packet_size) {}
-WriteResult QuartcPacketWriter::WritePacket(const char* buffer,
- size_t buf_len,
- const IPAddress& self_address,
- const IPEndPoint& peer_address,
- PerPacketOptions* options) {
+WriteResult QuartcPacketWriter::WritePacket(
+ const char* buffer,
+ size_t buf_len,
+ const QuicIpAddress& self_address,
+ const QuicSocketAddress& peer_address,
+ PerPacketOptions* options) {
DCHECK(packet_transport_);
int bytes_written = packet_transport_->Write(buffer, buf_len);
if (bytes_written <= 0) {
@@ -36,7 +37,7 @@ bool QuartcPacketWriter::IsWriteBlocked() const {
}
QuicByteCount QuartcPacketWriter::GetMaxPacketSize(
- const IPEndPoint& peer_address) const {
+ const QuicSocketAddress& peer_address) const {
return max_packet_size_;
}
diff --git a/chromium/net/quic/quartc/quartc_packet_writer.h b/chromium/net/quic/quartc/quartc_packet_writer.h
index d65d5d830c5..2c4b07f434c 100644
--- a/chromium/net/quic/quartc/quartc_packet_writer.h
+++ b/chromium/net/quic/quartc/quartc_packet_writer.h
@@ -5,8 +5,8 @@
#ifndef NET_QUIC_QUARTC_QUARTC_PACKET_WRITER_H_
#define NET_QUIC_QUARTC_QUARTC_PACKET_WRITER_H_
-#include "net/base/net_export.h"
#include "net/quic/core/quic_packet_writer.h"
+#include "net/quic/platform/api/quic_export.h"
#include "net/quic/quartc/quartc_session_interface.h"
namespace net {
@@ -14,7 +14,7 @@ namespace net {
// Implements a QuicPacketWriter using a
// QuartcSessionInterface::PacketTransport, which allows a QuicConnection to
// use(for example), a WebRTC IceTransport.
-class NET_EXPORT_PRIVATE QuartcPacketWriter : public QuicPacketWriter {
+class QUIC_EXPORT_PRIVATE QuartcPacketWriter : public QuicPacketWriter {
public:
QuartcPacketWriter(QuartcSessionInterface::PacketTransport* packet_transport,
QuicByteCount max_packet_size);
@@ -24,8 +24,8 @@ class NET_EXPORT_PRIVATE QuartcPacketWriter : public QuicPacketWriter {
// to the QuartcSessionInterface::PacketTransport.
WriteResult WritePacket(const char* buffer,
size_t buf_len,
- const IPAddress& self_address,
- const IPEndPoint& peer_address,
+ const QuicIpAddress& self_address,
+ const QuicSocketAddress& peer_address,
PerPacketOptions* options) override;
// This is always set to false so that QuicConnection buffers unsent packets.
@@ -39,7 +39,8 @@ class NET_EXPORT_PRIVATE QuartcPacketWriter : public QuicPacketWriter {
// Maximum size of the QUIC packet which can be written. Users such as WebRTC
// can set the value through the QuartcFactoryConfig without updating the QUIC
// code.
- QuicByteCount GetMaxPacketSize(const IPEndPoint& peer_address) const override;
+ QuicByteCount GetMaxPacketSize(
+ const QuicSocketAddress& peer_address) const override;
// This method is not used because the network layer in WebRTC will determine
// the writing states.
diff --git a/chromium/net/quic/quartc/quartc_session.cc b/chromium/net/quic/quartc/quartc_session.cc
index b89dc077349..e31f72bb0df 100644
--- a/chromium/net/quic/quartc/quartc_session.cc
+++ b/chromium/net/quic/quartc/quartc_session.cc
@@ -28,24 +28,24 @@ class DummyProofSource : public net::ProofSource {
~DummyProofSource() override {}
// ProofSource override.
- bool GetProof(const net::IPAddress& server_ip,
- const std::string& hostname,
- const std::string& server_config,
- net::QuicVersion quic_version,
- base::StringPiece chlo_hash,
- const net::QuicTagVector& connection_options,
- scoped_refptr<net::ProofSource::Chain>* out_chain,
- std::string* out_signature,
- std::string* out_leaf_cert_sct) override {
+ bool GetProof(
+ const net::QuicSocketAddress& server_addr,
+ const std::string& hostname,
+ const std::string& server_config,
+ net::QuicVersion quic_version,
+ base::StringPiece chlo_hash,
+ const net::QuicTagVector& connection_options,
+ net::QuicReferenceCountedPointer<net::ProofSource::Chain>* out_chain,
+ net::QuicCryptoProof* proof) override {
std::vector<std::string> certs;
certs.push_back("Dummy cert");
*out_chain = new ProofSource::Chain(certs);
- *out_signature = "Dummy signature";
- *out_leaf_cert_sct = "Dummy timestamp";
+ proof->signature = "Dummy signature";
+ proof->leaf_cert_scts = "Dummy timestamp";
return true;
}
- void GetProof(const net::IPAddress& server_ip,
+ void GetProof(const net::QuicSocketAddress& server_addr,
const std::string& hostname,
const std::string& server_config,
net::QuicVersion quic_version,
@@ -100,7 +100,7 @@ QuicConnectionId QuartcCryptoServerStreamHelper::GenerateConnectionIdForReject(
bool QuartcCryptoServerStreamHelper::CanAcceptClientHello(
const CryptoHandshakeMessage& message,
- const IPEndPoint& self_address,
+ const QuicSocketAddress& self_address,
std::string* error_details) const {
return true;
}
diff --git a/chromium/net/quic/quartc/quartc_session.h b/chromium/net/quic/quartc/quartc_session.h
index 0b84b6aba2f..2b3fa4bd175 100644
--- a/chromium/net/quic/quartc/quartc_session.h
+++ b/chromium/net/quic/quartc/quartc_session.h
@@ -5,11 +5,12 @@
#ifndef NET_QUIC_QUARTC_QUARTC_SESSION_H_
#define NET_QUIC_QUARTC_QUARTC_SESSION_H_
-#include "net/base/net_export.h"
#include "net/quic/core/quic_crypto_client_stream.h"
#include "net/quic/core/quic_crypto_server_stream.h"
#include "net/quic/core/quic_crypto_stream.h"
#include "net/quic/core/quic_session.h"
+#include "net/quic/platform/api/quic_export.h"
+#include "net/quic/platform/impl/quic_chromium_clock.h"
#include "net/quic/quartc/quartc_session_interface.h"
#include "net/quic/quartc/quartc_stream.h"
@@ -22,11 +23,11 @@ class QuartcCryptoServerStreamHelper : public QuicCryptoServerStream::Helper {
QuicConnectionId connection_id) const override;
bool CanAcceptClientHello(const CryptoHandshakeMessage& message,
- const IPEndPoint& self_address,
+ const QuicSocketAddress& self_address,
std::string* error_details) const override;
};
-class NET_EXPORT_PRIVATE QuartcSession
+class QUIC_EXPORT_PRIVATE QuartcSession
: public QuicSession,
public QuartcSessionInterface,
public QuicCryptoClientStream::ProofHandler {
@@ -97,7 +98,7 @@ class NET_EXPORT_PRIVATE QuartcSession
// For crypto handshake.
std::unique_ptr<QuicCryptoStream> crypto_stream_;
// For recording packet receipt time
- QuicClock clock_;
+ QuicChromiumClock clock_;
const std::string unique_remote_server_id_;
Perspective perspective_;
// Take the ownership of the QuicConnection.
diff --git a/chromium/net/quic/quartc/quartc_session_interface.h b/chromium/net/quic/quartc/quartc_session_interface.h
index f1513cef43f..82314875f20 100644
--- a/chromium/net/quic/quartc/quartc_session_interface.h
+++ b/chromium/net/quic/quartc/quartc_session_interface.h
@@ -9,7 +9,7 @@
#include <stdint.h>
#include <string>
-#include "net/base/net_export.h"
+#include "net/quic/platform/api/quic_export.h"
#include "net/quic/quartc/quartc_stream_interface.h"
namespace net {
@@ -17,7 +17,7 @@ namespace net {
// Given a PacketTransport, provides a way to send and receive separate streams
// of reliable, in-order, encrypted data. For example, this can build on top of
// a WebRTC IceTransport for sending and receiving data over QUIC.
-class NET_EXPORT_PRIVATE QuartcSessionInterface {
+class QUIC_EXPORT_PRIVATE QuartcSessionInterface {
public:
virtual ~QuartcSessionInterface() {}
diff --git a/chromium/net/quic/quartc/quartc_session_test.cc b/chromium/net/quic/quartc/quartc_session_test.cc
index b4ddc88e314..dd8db243eda 100644
--- a/chromium/net/quic/quartc/quartc_session_test.cc
+++ b/chromium/net/quic/quartc/quartc_session_test.cc
@@ -18,6 +18,7 @@
#include "net/quic/core/quic_crypto_client_stream.h"
#include "net/quic/core/quic_crypto_server_stream.h"
#include "net/quic/core/quic_simple_buffer_allocator.h"
+#include "net/quic/platform/impl/quic_chromium_clock.h"
#include "net/quic/quartc/quartc_alarm_factory.h"
#include "net/quic/quartc/quartc_packet_writer.h"
#include "testing/gtest/include/gtest/gtest.h"
@@ -51,26 +52,25 @@ class FakeProofSource : public net::ProofSource {
explicit FakeProofSource(bool success) : success_(success) {}
// ProofSource override.
- bool GetProof(const IPAddress& server_ip,
+ bool GetProof(const QuicSocketAddress& server_ip,
const std::string& hostname,
const std::string& server_config,
net::QuicVersion quic_version,
base::StringPiece chlo_hash,
const net::QuicTagVector& connection_options,
- scoped_refptr<net::ProofSource::Chain>* out_certs,
- std::string* out_signature,
- std::string* out_leaf_cert_sct) override {
+ QuicReferenceCountedPointer<net::ProofSource::Chain>* out_certs,
+ net::QuicCryptoProof* proof) override {
if (success_) {
std::vector<std::string> certs;
certs.push_back("Required to establish handshake");
*out_certs = new ProofSource::Chain(certs);
- *out_signature = "Signature";
- *out_leaf_cert_sct = "Time";
+ proof->signature = "Signature";
+ proof->leaf_cert_scts = "Time";
}
return success_;
}
- void GetProof(const net::IPAddress& server_ip,
+ void GetProof(const QuicSocketAddress& server_ip,
const std::string& hostname,
const std::string& server_config,
net::QuicVersion quic_version,
@@ -354,12 +354,13 @@ class QuartcSessionTest : public ::testing::Test,
QuartcPacketWriter* writer = perspective == Perspective::IS_CLIENT
? client_writer_.get()
: server_writer_.get();
- IPAddress ip(0, 0, 0, 0);
+ QuicIpAddress ip;
+ ip.FromString("0.0.0.0");
bool owns_writer = false;
alarm_factory_.reset(new QuartcAlarmFactory(
base::ThreadTaskRunnerHandle::Get().get(), GetClock()));
return std::unique_ptr<QuicConnection>(new QuicConnection(
- 0, IPEndPoint(ip, 0), this /*QuicConnectionHelperInterface*/,
+ 0, QuicSocketAddress(ip, 0), this /*QuicConnectionHelperInterface*/,
alarm_factory_.get(), writer, owns_writer, perspective,
AllSupportedVersions()));
}
@@ -448,7 +449,7 @@ class QuartcSessionTest : public ::testing::Test,
protected:
std::unique_ptr<QuicAlarmFactory> alarm_factory_;
SimpleBufferAllocator buffer_allocator_;
- QuicClock clock_;
+ QuicChromiumClock clock_;
std::unique_ptr<FakeTransportChannel> client_channel_;
std::unique_ptr<FakeTransportChannel> server_channel_;
diff --git a/chromium/net/quic/quartc/quartc_stream.h b/chromium/net/quic/quartc/quartc_stream.h
index fc091b9e6b1..95c185bbff9 100644
--- a/chromium/net/quic/quartc/quartc_stream.h
+++ b/chromium/net/quic/quartc/quartc_stream.h
@@ -7,13 +7,14 @@
#include "net/quic/core/quic_session.h"
#include "net/quic/core/quic_stream.h"
+#include "net/quic/platform/api/quic_export.h"
#include "net/quic/quartc/quartc_stream_interface.h"
namespace net {
// Implements a QuartcStreamInterface using a QuicStream.
-class NET_EXPORT_PRIVATE QuartcStream : public QuicStream,
- public QuartcStreamInterface {
+class QUIC_EXPORT_PRIVATE QuartcStream : public QuicStream,
+ public QuartcStreamInterface {
public:
QuartcStream(QuicStreamId id, QuicSession* session);
@@ -47,4 +48,4 @@ class NET_EXPORT_PRIVATE QuartcStream : public QuicStream,
} // namespace net
-#endif // NET_QUIC_QUARTC_STREAM_H_
+#endif // NET_QUIC_QUARTC_QUARTC_STREAM_H_
diff --git a/chromium/net/quic/quartc/quartc_stream_interface.h b/chromium/net/quic/quartc/quartc_stream_interface.h
index 2de1afd308e..831abb5432a 100644
--- a/chromium/net/quic/quartc/quartc_stream_interface.h
+++ b/chromium/net/quic/quartc/quartc_stream_interface.h
@@ -8,7 +8,7 @@
#include <stddef.h>
#include <stdint.h>
-#include "net/base/net_export.h"
+#include "net/quic/platform/api/quic_export.h"
namespace net {
@@ -16,7 +16,7 @@ namespace net {
// in-order. To send/receive data out of order, use separate streams. To
// send/receive unreliably, close a stream after reliability is no longer
// needed.
-class NET_EXPORT_PRIVATE QuartcStreamInterface {
+class QUIC_EXPORT_PRIVATE QuartcStreamInterface {
public:
virtual ~QuartcStreamInterface() {}
diff --git a/chromium/net/quic/quartc/quartc_stream_test.cc b/chromium/net/quic/quartc/quartc_stream_test.cc
index d138705afd4..c074be8afdc 100644
--- a/chromium/net/quic/quartc/quartc_stream_test.cc
+++ b/chromium/net/quic/quartc/quartc_stream_test.cc
@@ -8,6 +8,7 @@
#include "net/quic/core/crypto/quic_random.h"
#include "net/quic/core/quic_session.h"
#include "net/quic/core/quic_simple_buffer_allocator.h"
+#include "net/quic/platform/impl/quic_chromium_clock.h"
#include "net/quic/quartc/quartc_alarm_factory.h"
#include "net/quic/quartc/quartc_stream_interface.h"
#include "testing/gtest/include/gtest/gtest.h"
@@ -37,7 +38,8 @@ class MockQuicSession : public QuicSession {
QuicIOVector iovector,
QuicStreamOffset offset,
bool fin,
- QuicAckListenerInterface* ack_notifier_delegate) override {
+ QuicReferenceCountedPointer<
+ QuicAckListenerInterface> /*ack_notifier_delegate*/) override {
if (!writable_) {
return QuicConsumedData(0, false);
}
@@ -92,8 +94,8 @@ class DummyPacketWriter : public QuicPacketWriter {
// QuicPacketWriter overrides.
WriteResult WritePacket(const char* buffer,
size_t buf_len,
- const IPAddress& self_address,
- const IPEndPoint& peer_address,
+ const QuicIpAddress& self_address,
+ const QuicSocketAddress& peer_address,
PerPacketOptions* options) override {
return WriteResult(WRITE_STATUS_ERROR, 0);
}
@@ -105,7 +107,7 @@ class DummyPacketWriter : public QuicPacketWriter {
void SetWritable() override {}
QuicByteCount GetMaxPacketSize(
- const IPEndPoint& peer_address) const override {
+ const QuicSocketAddress& peer_address) const override {
return 0;
}
};
@@ -149,13 +151,14 @@ class QuartcStreamTest : public ::testing::Test,
void CreateReliableQuicStream() {
// Arbitrary values for QuicConnection.
Perspective perspective = Perspective::IS_SERVER;
- IPAddress ip(0, 0, 0, 0);
+ QuicIpAddress ip;
+ ip.FromString("0.0.0.0");
bool owns_writer = true;
alarm_factory_.reset(new QuartcAlarmFactory(
base::ThreadTaskRunnerHandle::Get().get(), GetClock()));
connection_.reset(new QuicConnection(
- 0, IPEndPoint(ip, 0), this /*QuicConnectionHelperInterface*/,
+ 0, QuicSocketAddress(ip, 0), this /*QuicConnectionHelperInterface*/,
alarm_factory_.get(), new DummyPacketWriter(), owns_writer, perspective,
AllSupportedVersions()));
@@ -192,7 +195,7 @@ class QuartcStreamTest : public ::testing::Test,
std::unique_ptr<QuicConnection> connection_;
// Used to implement the QuicConnectionHelperInterface.
SimpleBufferAllocator buffer_allocator_;
- QuicClock clock_;
+ QuicChromiumClock clock_;
};
// Write an entire string.
diff --git a/chromium/net/quic/quartc/quartc_task_runner_interface.h b/chromium/net/quic/quartc/quartc_task_runner_interface.h
index 00917b74b41..da9cd0b3273 100644
--- a/chromium/net/quic/quartc/quartc_task_runner_interface.h
+++ b/chromium/net/quic/quartc/quartc_task_runner_interface.h
@@ -2,8 +2,8 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#ifndef NET_QUIC_QUARTC_QUARTC_TASKRUNNER_INTERFACE_H_
-#define NET_QUIC_QUARTC_QUARTC_TASKRUNNER_INTERFACE_H_
+#ifndef NET_QUIC_QUARTC_QUARTC_TASK_RUNNER_INTERFACE_H_
+#define NET_QUIC_QUARTC_QUARTC_TASK_RUNNER_INTERFACE_H_
#include <stdint.h>
@@ -48,4 +48,4 @@ class QuartcTaskRunnerInterface {
} // namespace net
-#endif // NET_QUIC_QUARTC_QUARTC_TASKRUNNER_INTERFACE_H_
+#endif // NET_QUIC_QUARTC_QUARTC_TASK_RUNNER_INTERFACE_H_
diff --git a/chromium/net/quic/test_tools/crypto_test_utils.cc b/chromium/net/quic/test_tools/crypto_test_utils.cc
index adb68bd22ae..f210e26b821 100644
--- a/chromium/net/quic/test_tools/crypto_test_utils.cc
+++ b/chromium/net/quic/test_tools/crypto_test_utils.cc
@@ -6,7 +6,6 @@
#include <memory>
-#include "base/strings/string_util.h"
#include "crypto/openssl_util.h"
#include "crypto/secure_hash.h"
#include "net/quic/core/crypto/channel_id.h"
@@ -17,12 +16,15 @@
#include "net/quic/core/crypto/quic_decrypter.h"
#include "net/quic/core/crypto/quic_encrypter.h"
#include "net/quic/core/crypto/quic_random.h"
-#include "net/quic/core/quic_clock.h"
#include "net/quic/core/quic_crypto_client_stream.h"
#include "net/quic/core/quic_crypto_server_stream.h"
#include "net/quic/core/quic_crypto_stream.h"
#include "net/quic/core/quic_server_id.h"
#include "net/quic/core/quic_utils.h"
+#include "net/quic/platform/api/quic_clock.h"
+#include "net/quic/platform/api/quic_logging.h"
+#include "net/quic/platform/api/quic_socket_address.h"
+#include "net/quic/platform/api/quic_text_utils.h"
#include "net/quic/test_tools/quic_connection_peer.h"
#include "net/quic/test_tools/quic_framer_peer.h"
#include "net/quic/test_tools/quic_test_utils.h"
@@ -35,7 +37,6 @@
#include "third_party/boringssl/src/include/openssl/sha.h"
using base::StringPiece;
-using std::make_pair;
using std::string;
namespace net {
@@ -274,18 +275,19 @@ namespace {
// CHLO.
class FullChloGenerator {
public:
- FullChloGenerator(QuicCryptoServerConfig* crypto_config,
- IPAddress server_ip,
- IPEndPoint client_addr,
- const QuicClock* clock,
- scoped_refptr<QuicCryptoProof> proof,
- QuicCompressedCertsCache* compressed_certs_cache,
- CryptoHandshakeMessage* out)
+ FullChloGenerator(
+ QuicCryptoServerConfig* crypto_config,
+ QuicSocketAddress server_addr,
+ QuicSocketAddress client_addr,
+ const QuicClock* clock,
+ QuicReferenceCountedPointer<QuicSignedServerConfig> signed_config,
+ QuicCompressedCertsCache* compressed_certs_cache,
+ CryptoHandshakeMessage* out)
: crypto_config_(crypto_config),
- server_ip_(server_ip),
+ server_addr_(server_addr),
client_addr_(client_addr),
clock_(clock),
- proof_(proof),
+ signed_config_(signed_config),
compressed_certs_cache_(compressed_certs_cache),
out_(out),
params_(new QuicCryptoNegotiatedParameters) {}
@@ -294,7 +296,8 @@ class FullChloGenerator {
public:
explicit ValidateClientHelloCallback(FullChloGenerator* generator)
: generator_(generator) {}
- void Run(scoped_refptr<ValidateClientHelloResultCallback::Result> result,
+ void Run(QuicReferenceCountedPointer<
+ ValidateClientHelloResultCallback::Result> result,
std::unique_ptr<ProofSource::Details> /* details */) override {
generator_->ValidateClientHelloDone(std::move(result));
}
@@ -311,14 +314,15 @@ class FullChloGenerator {
private:
void ValidateClientHelloDone(
- scoped_refptr<ValidateClientHelloResultCallback::Result> result) {
+ QuicReferenceCountedPointer<ValidateClientHelloResultCallback::Result>
+ result) {
result_ = result;
crypto_config_->ProcessClientHello(
- result_, /*reject_only=*/false, /*connection_id=*/1, server_ip_,
+ result_, /*reject_only=*/false, /*connection_id=*/1, server_addr_,
client_addr_, AllSupportedVersions().front(), AllSupportedVersions(),
/*use_stateless_rejects=*/true, /*server_designated_connection_id=*/0,
clock_, QuicRandom::GetInstance(), compressed_certs_cache_, params_,
- proof_, /*total_framing_overhead=*/50, kDefaultMaxPacketSize,
+ signed_config_, /*total_framing_overhead=*/50, kDefaultMaxPacketSize,
GetProcessClientHelloCallback());
}
@@ -370,15 +374,16 @@ class FullChloGenerator {
protected:
QuicCryptoServerConfig* crypto_config_;
- IPAddress server_ip_;
- IPEndPoint client_addr_;
+ QuicSocketAddress server_addr_;
+ QuicSocketAddress client_addr_;
const QuicClock* clock_;
- scoped_refptr<QuicCryptoProof> proof_;
+ QuicReferenceCountedPointer<QuicSignedServerConfig> signed_config_;
QuicCompressedCertsCache* compressed_certs_cache_;
CryptoHandshakeMessage* out_;
- scoped_refptr<QuicCryptoNegotiatedParameters> params_;
- scoped_refptr<ValidateClientHelloResultCallback::Result> result_;
+ QuicReferenceCountedPointer<QuicCryptoNegotiatedParameters> params_;
+ QuicReferenceCountedPointer<ValidateClientHelloResultCallback::Result>
+ result_;
};
} // namespace
@@ -509,9 +514,9 @@ void CryptoTestUtils::CommunicateHandshakeMessagesAndRunCallbacks(
size_t client_i = 0, server_i = 0;
while (!client->handshake_confirmed()) {
ASSERT_GT(client_conn->encrypted_packets_.size(), client_i);
- VLOG(1) << "Processing "
- << client_conn->encrypted_packets_.size() - client_i
- << " packets client->server";
+ QUIC_LOG(INFO) << "Processing "
+ << client_conn->encrypted_packets_.size() - client_i
+ << " packets client->server";
MovePackets(client_conn, &client_i, server, server_conn,
Perspective::IS_SERVER);
if (callback_source) {
@@ -519,9 +524,9 @@ void CryptoTestUtils::CommunicateHandshakeMessagesAndRunCallbacks(
}
ASSERT_GT(server_conn->encrypted_packets_.size(), server_i);
- VLOG(1) << "Processing "
- << server_conn->encrypted_packets_.size() - server_i
- << " packets server->client";
+ QUIC_LOG(INFO) << "Processing "
+ << server_conn->encrypted_packets_.size() - server_i
+ << " packets server->client";
MovePackets(server_conn, &server_i, client, client_conn,
Perspective::IS_CLIENT);
if (callback_source) {
@@ -538,15 +543,17 @@ std::pair<size_t, size_t> CryptoTestUtils::AdvanceHandshake(
PacketSavingConnection* server_conn,
QuicCryptoStream* server,
size_t server_i) {
- VLOG(1) << "Processing " << client_conn->encrypted_packets_.size() - client_i
- << " packets client->server";
+ QUIC_LOG(INFO) << "Processing "
+ << client_conn->encrypted_packets_.size() - client_i
+ << " packets client->server";
MovePackets(client_conn, &client_i, server, server_conn,
Perspective::IS_SERVER);
- VLOG(1) << "Processing " << server_conn->encrypted_packets_.size() - server_i
- << " packets server->client";
+ QUIC_LOG(INFO) << "Processing "
+ << server_conn->encrypted_packets_.size() - server_i
+ << " packets server->client";
if (server_conn->encrypted_packets_.size() - server_i == 2) {
- VLOG(1) << "here";
+ QUIC_LOG(INFO) << "here";
}
MovePackets(server_conn, &server_i, client, client_conn,
Perspective::IS_CLIENT);
@@ -565,21 +572,20 @@ string CryptoTestUtils::GetValueForTag(const CryptoHandshakeMessage& message,
}
uint64_t CryptoTestUtils::LeafCertHashForTesting() {
- scoped_refptr<ProofSource::Chain> chain;
- IPAddress server_ip;
- string sig;
- string cert_sct;
+ QuicReferenceCountedPointer<ProofSource::Chain> chain;
+ QuicSocketAddress server_address;
+ QuicCryptoProof proof;
std::unique_ptr<ProofSource> proof_source(
CryptoTestUtils::ProofSourceForTesting());
- if (!proof_source->GetProof(server_ip, "", "", AllSupportedVersions().front(),
- "", QuicTagVector(), &chain, &sig, &cert_sct) ||
+ if (!proof_source->GetProof(server_address, "", "",
+ AllSupportedVersions().front(), "",
+ QuicTagVector(), &chain, &proof) ||
chain->certs.empty()) {
DCHECK(false) << "Proof generation failed";
return 0;
}
- return QuicUtils::FNV1a_64_Hash(chain->certs.at(0).c_str(),
- chain->certs.at(0).length());
+ return QuicUtils::FNV1a_64_Hash(chain->certs.at(0));
}
class MockCommonCertSets : public CommonCertSets {
@@ -960,7 +966,7 @@ CryptoHandshakeMessage CryptoTestUtils::GenerateDefaultInchoateCHLO(
"PUBS", CryptoTestUtils::GenerateClientPublicValuesHex().c_str(),
"NONC", CryptoTestUtils::GenerateClientNonceHex(clock,
crypto_config).c_str(),
- "VER\0", QuicUtils::TagToString(
+ "VER\0", QuicTagToString(
QuicVersionToQuicTag(version)).c_str(),
"$padding", static_cast<int>(kClientHelloMinimumSize),
nullptr);
@@ -989,31 +995,31 @@ string CryptoTestUtils::GenerateClientNonceHex(
StringPiece(reinterpret_cast<const char*>(orbit.data()),
sizeof(orbit.size())),
&nonce);
- return ("#" + net::QuicUtils::HexEncode(nonce));
+ return ("#" + QuicTextUtils::HexEncode(nonce));
}
string CryptoTestUtils::GenerateClientPublicValuesHex() {
char public_value[32];
memset(public_value, 42, sizeof(public_value));
- return ("#" + net::QuicUtils::HexEncode(public_value, sizeof(public_value)));
+ return ("#" + QuicTextUtils::HexEncode(public_value, sizeof(public_value)));
}
// static
void CryptoTestUtils::GenerateFullCHLO(
const CryptoHandshakeMessage& inchoate_chlo,
QuicCryptoServerConfig* crypto_config,
- IPAddress server_ip,
- IPEndPoint client_addr,
+ QuicSocketAddress server_addr,
+ QuicSocketAddress client_addr,
QuicVersion version,
const QuicClock* clock,
- scoped_refptr<QuicCryptoProof> proof,
+ QuicReferenceCountedPointer<QuicSignedServerConfig> proof,
QuicCompressedCertsCache* compressed_certs_cache,
CryptoHandshakeMessage* out) {
// Pass a inchoate CHLO.
- FullChloGenerator generator(crypto_config, server_ip, client_addr, clock,
+ FullChloGenerator generator(crypto_config, server_addr, client_addr, clock,
proof, compressed_certs_cache, out);
crypto_config->ValidateClientHello(
- inchoate_chlo, client_addr.address(), server_ip, version, clock, proof,
+ inchoate_chlo, client_addr.host(), server_addr, version, clock, proof,
generator.GetValidateClientHelloCallback());
}
diff --git a/chromium/net/quic/test_tools/crypto_test_utils.h b/chromium/net/quic/test_tools/crypto_test_utils.h
index d1468dc38a6..8c3565d1447 100644
--- a/chromium/net/quic/test_tools/crypto_test_utils.h
+++ b/chromium/net/quic/test_tools/crypto_test_utils.h
@@ -5,19 +5,17 @@
#ifndef NET_QUIC_TEST_TOOLS_CRYPTO_TEST_UTILS_H_
#define NET_QUIC_TEST_TOOLS_CRYPTO_TEST_UTILS_H_
-#include <stdarg.h>
-#include <stddef.h>
-#include <stdint.h>
-
+#include <cstdarg>
+#include <cstddef>
+#include <cstdint>
#include <utility>
#include <vector>
-#include "base/logging.h"
#include "base/macros.h"
#include "base/strings/string_piece.h"
#include "net/quic/core/crypto/crypto_framer.h"
#include "net/quic/core/quic_framer.h"
-#include "net/quic/core/quic_protocol.h"
+#include "net/quic/core/quic_packets.h"
#include "net/quic/test_tools/quic_test_utils.h"
namespace net {
@@ -144,11 +142,14 @@ class CryptoTestUtils {
// Returns a new |ProofSource| that serves up test certificates.
static std::unique_ptr<ProofSource> ProofSourceForTesting();
- // Returns a |ProofVerifier| that uses the QUIC testing root CA.
- static std::unique_ptr<ProofVerifier> ProofVerifierForTesting();
+ // Identical to |ProofSourceForTesting|, with the addition of setting
+ // the |emit_expect_ct_header| field on the test certificates
+ // to be the value of |send_expect_ct_header|.
+ static std::unique_ptr<ProofSource> ProofSourceForTesting(
+ bool send_expect_ct_header);
- // Returns a real ProofVerifier (not a fake proof verifier) for testing.
- static std::unique_ptr<ProofVerifier> RealProofVerifierForTesting();
+ // Returns a new |ProofVerifier| that uses the QUIC testing root CA.
+ static std::unique_ptr<ProofVerifier> ProofVerifierForTesting();
// Returns a hash of the leaf test certificate.
static uint64_t LeafCertHashForTesting();
@@ -204,7 +205,7 @@ class CryptoTestUtils {
PacketSavingConnection* dest_conn,
Perspective dest_perspective);
- // Return an inchoate CHLO with some basic tag value std:pairs.
+ // Return an inchoate CHLO with some basic tag value pairs.
static CryptoHandshakeMessage GenerateDefaultInchoateCHLO(
const QuicClock* clock,
QuicVersion version,
@@ -212,15 +213,16 @@ class CryptoTestUtils {
// Takes a inchoate CHLO, returns a full CHLO in |out| which can pass
// |crypto_config|'s validation.
- static void GenerateFullCHLO(const CryptoHandshakeMessage& inchoate_chlo,
- QuicCryptoServerConfig* crypto_config,
- IPAddress server_ip,
- IPEndPoint client_addr,
- QuicVersion version,
- const QuicClock* clock,
- scoped_refptr<QuicCryptoProof> proof,
- QuicCompressedCertsCache* compressed_certs_cache,
- CryptoHandshakeMessage* out);
+ static void GenerateFullCHLO(
+ const CryptoHandshakeMessage& inchoate_chlo,
+ QuicCryptoServerConfig* crypto_config,
+ QuicSocketAddress server_addr,
+ QuicSocketAddress client_addr,
+ QuicVersion version,
+ const QuicClock* clock,
+ QuicReferenceCountedPointer<QuicSignedServerConfig> signed_config,
+ QuicCompressedCertsCache* compressed_certs_cache,
+ CryptoHandshakeMessage* out);
private:
static void CompareClientAndServerKeys(QuicCryptoClientStream* client,
diff --git a/chromium/net/quic/test_tools/crypto_test_utils_test.cc b/chromium/net/quic/test_tools/crypto_test_utils_test.cc
index d79b4601a8f..85069446e41 100644
--- a/chromium/net/quic/test_tools/crypto_test_utils_test.cc
+++ b/chromium/net/quic/test_tools/crypto_test_utils_test.cc
@@ -6,6 +6,7 @@
#include "net/quic/core/crypto/crypto_server_config_protobuf.h"
#include "net/quic/core/quic_utils.h"
+#include "net/quic/platform/api/quic_text_utils.h"
#include "net/quic/test_tools/mock_clock.h"
#include "net/test/gtest_util.h"
#include "testing/gmock/include/gmock/gmock.h"
@@ -18,17 +19,18 @@ namespace test {
class ShloVerifier {
public:
- ShloVerifier(QuicCryptoServerConfig* crypto_config,
- IPAddress server_ip,
- IPEndPoint client_addr,
- const QuicClock* clock,
- scoped_refptr<QuicCryptoProof> proof,
- QuicCompressedCertsCache* compressed_certs_cache)
+ ShloVerifier(
+ QuicCryptoServerConfig* crypto_config,
+ QuicSocketAddress server_addr,
+ QuicSocketAddress client_addr,
+ const QuicClock* clock,
+ QuicReferenceCountedPointer<QuicSignedServerConfig> signed_config,
+ QuicCompressedCertsCache* compressed_certs_cache)
: crypto_config_(crypto_config),
- server_ip_(server_ip),
+ server_addr_(server_addr),
client_addr_(client_addr),
clock_(clock),
- proof_(proof),
+ signed_config_(signed_config),
compressed_certs_cache_(compressed_certs_cache),
params_(new QuicCryptoNegotiatedParameters) {}
@@ -36,7 +38,8 @@ class ShloVerifier {
public:
explicit ValidateClientHelloCallback(ShloVerifier* shlo_verifier)
: shlo_verifier_(shlo_verifier) {}
- void Run(scoped_refptr<ValidateClientHelloResultCallback::Result> result,
+ void Run(QuicReferenceCountedPointer<
+ ValidateClientHelloResultCallback::Result> result,
std::unique_ptr<ProofSource::Details> /* details */) override {
shlo_verifier_->ValidateClientHelloDone(result);
}
@@ -53,14 +56,15 @@ class ShloVerifier {
private:
void ValidateClientHelloDone(
- const scoped_refptr<ValidateClientHelloResultCallback::Result>& result) {
+ const QuicReferenceCountedPointer<
+ ValidateClientHelloResultCallback::Result>& result) {
result_ = result;
crypto_config_->ProcessClientHello(
- result_, /*reject_only=*/false, /*connection_id=*/1, server_ip_,
+ result_, /*reject_only=*/false, /*connection_id=*/1, server_addr_,
client_addr_, AllSupportedVersions().front(), AllSupportedVersions(),
/*use_stateless_rejects=*/true, /*server_designated_connection_id=*/0,
clock_, QuicRandom::GetInstance(), compressed_certs_cache_, params_,
- proof_, /*total_framing_overhead=*/50, kDefaultMaxPacketSize,
+ signed_config_, /*total_framing_overhead=*/50, kDefaultMaxPacketSize,
GetProcessClientHelloCallback());
}
@@ -88,19 +92,20 @@ class ShloVerifier {
void ProcessClientHelloDone(std::unique_ptr<CryptoHandshakeMessage> message) {
// Verify output is a SHLO.
- EXPECT_EQ(message->tag(), kSHLO) << "Fail to pass validation. Get "
- << message->DebugString();
+ EXPECT_EQ(message->tag(), kSHLO)
+ << "Fail to pass validation. Get " << message->DebugString();
}
QuicCryptoServerConfig* crypto_config_;
- IPAddress server_ip_;
- IPEndPoint client_addr_;
+ QuicSocketAddress server_addr_;
+ QuicSocketAddress client_addr_;
const QuicClock* clock_;
- scoped_refptr<QuicCryptoProof> proof_;
+ QuicReferenceCountedPointer<QuicSignedServerConfig> signed_config_;
QuicCompressedCertsCache* compressed_certs_cache_;
- scoped_refptr<QuicCryptoNegotiatedParameters> params_;
- scoped_refptr<ValidateClientHelloResultCallback::Result> result_;
+ QuicReferenceCountedPointer<QuicCryptoNegotiatedParameters> params_;
+ QuicReferenceCountedPointer<ValidateClientHelloResultCallback::Result>
+ result_;
};
TEST(CryptoTestUtilsTest, TestGenerateFullCHLO) {
@@ -108,9 +113,10 @@ TEST(CryptoTestUtilsTest, TestGenerateFullCHLO) {
QuicCryptoServerConfig crypto_config(
QuicCryptoServerConfig::TESTING, QuicRandom::GetInstance(),
CryptoTestUtils::ProofSourceForTesting());
- IPAddress server_ip;
- IPEndPoint client_addr(IPAddress::IPv4Localhost(), 1);
- scoped_refptr<QuicCryptoProof> proof(new QuicCryptoProof);
+ QuicSocketAddress server_addr;
+ QuicSocketAddress client_addr(QuicIpAddress::Loopback4(), 1);
+ QuicReferenceCountedPointer<QuicSignedServerConfig> signed_config(
+ new QuicSignedServerConfig);
QuicCompressedCertsCache compressed_certs_cache(
QuicCompressedCertsCache::kQuicCompressedCertsCacheSize);
CryptoHandshakeMessage full_chlo;
@@ -134,12 +140,12 @@ TEST(CryptoTestUtilsTest, TestGenerateFullCHLO) {
StringPiece(reinterpret_cast<const char*>(orbit.data()),
sizeof(orbit.size())),
&nonce);
- string nonce_hex = "#" + QuicUtils::HexEncode(nonce);
+ string nonce_hex = "#" + QuicTextUtils::HexEncode(nonce);
char public_value[32];
memset(public_value, 42, sizeof(public_value));
string pub_hex =
- "#" + QuicUtils::HexEncode(public_value, sizeof(public_value));
+ "#" + QuicTextUtils::HexEncode(public_value, sizeof(public_value));
QuicVersion version(AllSupportedVersions().front());
// clang-format off
@@ -151,20 +157,20 @@ TEST(CryptoTestUtilsTest, TestGenerateFullCHLO) {
"COPT", "SREJ",
"PUBS", pub_hex.c_str(),
"NONC", nonce_hex.c_str(),
- "VER\0", QuicUtils::TagToString(QuicVersionToQuicTag(version)).c_str(),
+ "VER\0", QuicTagToString(QuicVersionToQuicTag(version)).c_str(),
"$padding", static_cast<int>(kClientHelloMinimumSize),
nullptr);
// clang-format on
- CryptoTestUtils::GenerateFullCHLO(inchoate_chlo, &crypto_config, server_ip,
- client_addr, version, &clock, proof,
+ CryptoTestUtils::GenerateFullCHLO(inchoate_chlo, &crypto_config, server_addr,
+ client_addr, version, &clock, signed_config,
&compressed_certs_cache, &full_chlo);
// Verify that full_chlo can pass crypto_config's verification.
- ShloVerifier shlo_verifier(&crypto_config, server_ip, client_addr, &clock,
- proof, &compressed_certs_cache);
+ ShloVerifier shlo_verifier(&crypto_config, server_addr, client_addr, &clock,
+ signed_config, &compressed_certs_cache);
crypto_config.ValidateClientHello(
- full_chlo, client_addr.address(), server_ip, version, &clock, proof,
- shlo_verifier.GetValidateClientHelloCallback());
+ full_chlo, client_addr.host(), server_addr, version, &clock,
+ signed_config, shlo_verifier.GetValidateClientHelloCallback());
}
} // namespace test
diff --git a/chromium/net/quic/test_tools/failing_proof_source.cc b/chromium/net/quic/test_tools/failing_proof_source.cc
new file mode 100644
index 00000000000..53b69e19c85
--- /dev/null
+++ b/chromium/net/quic/test_tools/failing_proof_source.cc
@@ -0,0 +1,33 @@
+// Copyright (c) 2017 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.
+
+#include "net/quic/test_tools/failing_proof_source.h"
+
+namespace net {
+namespace test {
+
+bool FailingProofSource::GetProof(
+ const QuicSocketAddress& server_address,
+ const std::string& hostname,
+ const std::string& server_config,
+ QuicVersion quic_version,
+ base::StringPiece chlo_hash,
+ const QuicTagVector& connection_options,
+ QuicReferenceCountedPointer<ProofSource::Chain>* out_chain,
+ QuicCryptoProof* out_proof) {
+ return false;
+}
+
+void FailingProofSource::GetProof(const QuicSocketAddress& server_address,
+ const std::string& hostname,
+ const std::string& server_config,
+ QuicVersion quic_version,
+ base::StringPiece chlo_hash,
+ const QuicTagVector& connection_options,
+ std::unique_ptr<Callback> callback) {
+ callback->Run(false, nullptr, QuicCryptoProof(), nullptr);
+}
+
+} // namespace test
+} // namespace net
diff --git a/chromium/net/quic/test_tools/failing_proof_source.h b/chromium/net/quic/test_tools/failing_proof_source.h
new file mode 100644
index 00000000000..67aa44e0a89
--- /dev/null
+++ b/chromium/net/quic/test_tools/failing_proof_source.h
@@ -0,0 +1,36 @@
+// Copyright (c) 2017 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.
+
+#ifndef NET_QUIC_TEST_TOOLS_FAILING_PROOF_SOURCE_H_
+#define NET_QUIC_TEST_TOOLS_FAILING_PROOF_SOURCE_H_
+
+#include "net/quic/core/crypto/proof_source.h"
+
+namespace net {
+namespace test {
+
+class FailingProofSource : public ProofSource {
+ public:
+ bool GetProof(const QuicSocketAddress& server_address,
+ const std::string& hostname,
+ const std::string& server_config,
+ QuicVersion quic_version,
+ base::StringPiece chlo_hash,
+ const QuicTagVector& connection_options,
+ QuicReferenceCountedPointer<ProofSource::Chain>* out_chain,
+ QuicCryptoProof* out_proof) override;
+
+ void GetProof(const QuicSocketAddress& server_address,
+ const std::string& hostname,
+ const std::string& server_config,
+ QuicVersion quic_version,
+ base::StringPiece chlo_hash,
+ const QuicTagVector& connection_options,
+ std::unique_ptr<Callback> callback) override;
+};
+
+} // namespace test
+} // namespace net
+
+#endif // NET_QUIC_TEST_TOOLS_FAILING_PROOF_SOURCE_H_
diff --git a/chromium/net/quic/test_tools/fake_proof_source.cc b/chromium/net/quic/test_tools/fake_proof_source.cc
index b40af64a96a..e4360195b83 100644
--- a/chromium/net/quic/test_tools/fake_proof_source.cc
+++ b/chromium/net/quic/test_tools/fake_proof_source.cc
@@ -2,6 +2,7 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
+#include "net/quic/platform/api/quic_logging.h"
#include "net/quic/test_tools/fake_proof_source.h"
#include "net/quic/test_tools/crypto_test_utils.h"
@@ -15,14 +16,14 @@ FakeProofSource::FakeProofSource()
FakeProofSource::~FakeProofSource() {}
-FakeProofSource::Params::Params(const IPAddress& server_ip,
+FakeProofSource::Params::Params(const QuicSocketAddress& server_addr,
std::string hostname,
std::string server_config,
QuicVersion quic_version,
std::string chlo_hash,
const QuicTagVector& connection_options,
std::unique_ptr<ProofSource::Callback> callback)
- : server_ip(server_ip),
+ : server_address(server_addr),
hostname(hostname),
server_config(server_config),
quic_version(quic_version),
@@ -41,23 +42,23 @@ void FakeProofSource::Activate() {
active_ = true;
}
-bool FakeProofSource::GetProof(const IPAddress& server_ip,
- const string& hostname,
- const string& server_config,
- QuicVersion quic_version,
- StringPiece chlo_hash,
- const QuicTagVector& connection_options,
- scoped_refptr<ProofSource::Chain>* out_chain,
- string* out_signature,
- string* out_leaf_cert_sct) {
- LOG(WARNING) << "Synchronous GetProof called";
- return delegate_->GetProof(server_ip, hostname, server_config, quic_version,
- chlo_hash, connection_options, out_chain,
- out_signature, out_leaf_cert_sct);
+bool FakeProofSource::GetProof(
+ const QuicSocketAddress& server_address,
+ const string& hostname,
+ const string& server_config,
+ QuicVersion quic_version,
+ StringPiece chlo_hash,
+ const QuicTagVector& connection_options,
+ QuicReferenceCountedPointer<ProofSource::Chain>* out_chain,
+ QuicCryptoProof* out_proof) {
+ QUIC_LOG(WARNING) << "Synchronous GetProof called";
+ return delegate_->GetProof(server_address, hostname, server_config,
+ quic_version, chlo_hash, connection_options,
+ out_chain, out_proof);
}
void FakeProofSource::GetProof(
- const IPAddress& server_ip,
+ const QuicSocketAddress& server_address,
const string& hostname,
const string& server_config,
QuicVersion quic_version,
@@ -65,21 +66,19 @@ void FakeProofSource::GetProof(
const QuicTagVector& connection_options,
std::unique_ptr<ProofSource::Callback> callback) {
if (!active_) {
- scoped_refptr<Chain> chain;
- string signature;
- string leaf_cert_sct;
+ QuicReferenceCountedPointer<Chain> chain;
+ QuicCryptoProof proof;
const bool ok =
- GetProof(server_ip, hostname, server_config, quic_version, chlo_hash,
- connection_options, &chain, &signature, &leaf_cert_sct);
- callback->Run(ok, chain, signature, leaf_cert_sct,
- /* details = */ nullptr);
+ GetProof(server_address, hostname, server_config, quic_version,
+ chlo_hash, connection_options, &chain, &proof);
+ callback->Run(ok, chain, proof, /* details = */ nullptr);
return;
}
- LOG(WARNING) << "Asynchronous GetProof called";
- params_.push_back(Params{server_ip, hostname, server_config, quic_version,
- chlo_hash.as_string(), connection_options,
- std::move(callback)});
+ QUIC_LOG(WARNING) << "Asynchronous GetProof called";
+ params_.push_back(Params{server_address, hostname, server_config,
+ quic_version, chlo_hash.as_string(),
+ connection_options, std::move(callback)});
}
int FakeProofSource::NumPendingCallbacks() const {
@@ -91,16 +90,14 @@ void FakeProofSource::InvokePendingCallback(int n) {
const Params& params = params_[n];
- scoped_refptr<ProofSource::Chain> chain;
- string signature;
- string leaf_cert_sct;
+ QuicReferenceCountedPointer<ProofSource::Chain> chain;
+ QuicCryptoProof proof;
const bool ok = delegate_->GetProof(
- params.server_ip, params.hostname, params.server_config,
+ params.server_address, params.hostname, params.server_config,
params.quic_version, params.chlo_hash, params.connection_options, &chain,
- &signature, &leaf_cert_sct);
+ &proof);
- params.callback->Run(ok, chain, signature, leaf_cert_sct,
- /* details = */ nullptr);
+ params.callback->Run(ok, chain, proof, /* details = */ nullptr);
auto it = params_.begin() + n;
params_.erase(it);
}
diff --git a/chromium/net/quic/test_tools/fake_proof_source.h b/chromium/net/quic/test_tools/fake_proof_source.h
index 421c29b9373..776466d6645 100644
--- a/chromium/net/quic/test_tools/fake_proof_source.h
+++ b/chromium/net/quic/test_tools/fake_proof_source.h
@@ -30,16 +30,15 @@ class FakeProofSource : public ProofSource {
void Activate();
// ProofSource interface
- bool GetProof(const IPAddress& server_ip,
+ bool GetProof(const QuicSocketAddress& server_address,
const std::string& hostname,
const std::string& server_config,
QuicVersion quic_version,
base::StringPiece chlo_hash,
const QuicTagVector& connection_options,
- scoped_refptr<ProofSource::Chain>* out_chain,
- std::string* out_signature,
- std::string* out_leaf_cert_sct) override;
- void GetProof(const IPAddress& server_ip,
+ QuicReferenceCountedPointer<ProofSource::Chain>* out_chain,
+ QuicCryptoProof* out_proof) override;
+ void GetProof(const QuicSocketAddress& server_address,
const std::string& hostname,
const std::string& server_config,
QuicVersion quic_version,
@@ -59,7 +58,7 @@ class FakeProofSource : public ProofSource {
bool active_ = false;
struct Params {
- Params(const IPAddress& server_ip,
+ Params(const QuicSocketAddress& server_addr,
std::string hostname,
std::string server_config,
QuicVersion quic_version,
@@ -70,7 +69,7 @@ class FakeProofSource : public ProofSource {
Params(Params&& other);
Params& operator=(Params&& other);
- IPAddress server_ip;
+ QuicSocketAddress server_address;
std::string hostname;
std::string server_config;
QuicVersion quic_version;
diff --git a/chromium/net/quic/test_tools/mock_clock.h b/chromium/net/quic/test_tools/mock_clock.h
index 01a48bf2fa0..5bcdf0b9ce2 100644
--- a/chromium/net/quic/test_tools/mock_clock.h
+++ b/chromium/net/quic/test_tools/mock_clock.h
@@ -9,7 +9,7 @@
#include "base/logging.h"
#include "base/macros.h"
#include "base/time/time.h"
-#include "net/quic/core/quic_clock.h"
+#include "net/quic/platform/api/quic_clock.h"
namespace net {
@@ -18,14 +18,15 @@ class MockClock : public QuicClock {
MockClock();
~MockClock() override;
- void AdvanceTime(QuicTime::Delta delta);
-
+ // QuicClock implementation:
QuicTime Now() const override;
-
QuicTime ApproximateNow() const override;
-
QuicWallTime WallNow() const override;
+ // Advances the current time by |delta|, which may be negative.
+ void AdvanceTime(QuicTime::Delta delta);
+
+ // Returns the current time in ticks.
base::TimeTicks NowInTicks() const;
private:
diff --git a/chromium/net/quic/test_tools/mock_crypto_client_stream.cc b/chromium/net/quic/test_tools/mock_crypto_client_stream.cc
index 1453a5bdd26..25ba8684ce5 100644
--- a/chromium/net/quic/test_tools/mock_crypto_client_stream.cc
+++ b/chromium/net/quic/test_tools/mock_crypto_client_stream.cc
@@ -4,6 +4,8 @@
#include "net/quic/test_tools/mock_crypto_client_stream.h"
+#include "net/quic/core/crypto/null_decrypter.h"
+#include "net/quic/core/crypto/null_encrypter.h"
#include "net/quic/core/crypto/quic_decrypter.h"
#include "net/quic/core/crypto/quic_encrypter.h"
#include "net/quic/core/quic_client_session_base.h"
@@ -64,10 +66,10 @@ void MockCryptoClientStream::CryptoConnect() {
reinterpret_cast<QuicClientSessionBase*>(session())
->OnProofVerifyDetailsAvailable(*proof_verify_details_);
}
- session()->connection()->SetDecrypter(ENCRYPTION_INITIAL,
- QuicDecrypter::Create(kNULL));
- session()->connection()->SetEncrypter(ENCRYPTION_INITIAL,
- QuicEncrypter::Create(kNULL));
+ session()->connection()->SetDecrypter(
+ ENCRYPTION_INITIAL, new NullDecrypter(Perspective::IS_CLIENT));
+ session()->connection()->SetEncrypter(
+ ENCRYPTION_INITIAL, new NullEncrypter(Perspective::IS_CLIENT));
session()->connection()->SetDefaultEncryptionLevel(ENCRYPTION_INITIAL);
session()->OnCryptoHandshakeEvent(
QuicSession::ENCRYPTION_FIRST_ESTABLISHED);
@@ -84,10 +86,10 @@ void MockCryptoClientStream::CryptoConnect() {
->OnProofVerifyDetailsAvailable(*proof_verify_details_);
}
SetConfigNegotiated();
- session()->connection()->SetDecrypter(ENCRYPTION_FORWARD_SECURE,
- QuicDecrypter::Create(kNULL));
- session()->connection()->SetEncrypter(ENCRYPTION_FORWARD_SECURE,
- QuicEncrypter::Create(kNULL));
+ session()->connection()->SetDecrypter(
+ ENCRYPTION_FORWARD_SECURE, new NullDecrypter(Perspective::IS_CLIENT));
+ session()->connection()->SetEncrypter(
+ ENCRYPTION_FORWARD_SECURE, new NullEncrypter(Perspective::IS_CLIENT));
session()->connection()->SetDefaultEncryptionLevel(
ENCRYPTION_FORWARD_SECURE);
session()->OnCryptoHandshakeEvent(QuicSession::HANDSHAKE_CONFIRMED);
@@ -108,6 +110,12 @@ void MockCryptoClientStream::SendOnCryptoHandshakeEvent(
if (event == QuicSession::HANDSHAKE_CONFIRMED) {
handshake_confirmed_ = true;
SetConfigNegotiated();
+ session()->connection()->SetDecrypter(
+ ENCRYPTION_FORWARD_SECURE, new NullDecrypter(Perspective::IS_CLIENT));
+ session()->connection()->SetEncrypter(
+ ENCRYPTION_FORWARD_SECURE, new NullEncrypter(Perspective::IS_CLIENT));
+ session()->connection()->SetDefaultEncryptionLevel(
+ ENCRYPTION_FORWARD_SECURE);
}
session()->OnCryptoHandshakeEvent(event);
}
diff --git a/chromium/net/quic/test_tools/mock_quic_client_promised_info.h b/chromium/net/quic/test_tools/mock_quic_client_promised_info.h
index 98643d7c0aa..4137b564daa 100644
--- a/chromium/net/quic/test_tools/mock_quic_client_promised_info.h
+++ b/chromium/net/quic/test_tools/mock_quic_client_promised_info.h
@@ -9,7 +9,7 @@
#include "base/macros.h"
#include "net/quic/core/quic_client_promised_info.h"
-#include "net/quic/core/quic_protocol.h"
+#include "net/quic/core/quic_packets.h"
#include "testing/gmock/include/gmock/gmock.h"
namespace net {
diff --git a/chromium/net/quic/test_tools/mock_quic_dispatcher.cc b/chromium/net/quic/test_tools/mock_quic_dispatcher.cc
index a8add6553c0..e074e5555c7 100644
--- a/chromium/net/quic/test_tools/mock_quic_dispatcher.cc
+++ b/chromium/net/quic/test_tools/mock_quic_dispatcher.cc
@@ -15,13 +15,15 @@ MockQuicDispatcher::MockQuicDispatcher(
QuicVersionManager* version_manager,
std::unique_ptr<QuicConnectionHelperInterface> helper,
std::unique_ptr<QuicCryptoServerStream::Helper> session_helper,
- std::unique_ptr<QuicAlarmFactory> alarm_factory)
+ std::unique_ptr<QuicAlarmFactory> alarm_factory,
+ QuicHttpResponseCache* response_cache)
: QuicSimpleDispatcher(config,
crypto_config,
version_manager,
std::move(helper),
std::move(session_helper),
- std::move(alarm_factory)) {}
+ std::move(alarm_factory),
+ response_cache) {}
MockQuicDispatcher::~MockQuicDispatcher() {}
diff --git a/chromium/net/quic/test_tools/mock_quic_dispatcher.h b/chromium/net/quic/test_tools/mock_quic_dispatcher.h
index e4c41a64962..a07dd80ae30 100644
--- a/chromium/net/quic/test_tools/mock_quic_dispatcher.h
+++ b/chromium/net/quic/test_tools/mock_quic_dispatcher.h
@@ -6,10 +6,9 @@
#define NET_QUIC_TEST_TOOLS_MOCK_QUIC_DISPATCHER_H_
#include "base/macros.h"
-#include "net/base/ip_endpoint.h"
#include "net/quic/core/crypto/quic_crypto_server_config.h"
#include "net/quic/core/quic_config.h"
-#include "net/quic/core/quic_protocol.h"
+#include "net/quic/core/quic_packets.h"
#include "net/tools/quic/quic_simple_dispatcher.h"
#include "testing/gmock/include/gmock/gmock.h"
@@ -24,13 +23,14 @@ class MockQuicDispatcher : public QuicSimpleDispatcher {
QuicVersionManager* version_manager,
std::unique_ptr<QuicConnectionHelperInterface> helper,
std::unique_ptr<QuicCryptoServerStream::Helper> session_helper,
- std::unique_ptr<QuicAlarmFactory> alarm_factory);
+ std::unique_ptr<QuicAlarmFactory> alarm_factory,
+ QuicHttpResponseCache* response_cache);
~MockQuicDispatcher() override;
MOCK_METHOD3(ProcessPacket,
- void(const IPEndPoint& server_address,
- const IPEndPoint& client_address,
+ void(const QuicSocketAddress& server_address,
+ const QuicSocketAddress& client_address,
const QuicReceivedPacket& packet));
private:
diff --git a/chromium/net/quic/test_tools/mock_quic_spdy_client_stream.h b/chromium/net/quic/test_tools/mock_quic_spdy_client_stream.h
index bfe225d1685..5522cb65465 100644
--- a/chromium/net/quic/test_tools/mock_quic_spdy_client_stream.h
+++ b/chromium/net/quic/test_tools/mock_quic_spdy_client_stream.h
@@ -7,7 +7,7 @@
#include "base/macros.h"
#include "net/quic/core/quic_header_list.h"
-#include "net/quic/core/quic_protocol.h"
+#include "net/quic/core/quic_packets.h"
#include "net/tools/quic/quic_spdy_client_stream.h"
#include "testing/gmock/include/gmock/gmock.h"
// #include "testing/gtest/include/gtest/gtest.h"
diff --git a/chromium/net/quic/test_tools/quic_buffered_packet_store_peer.h b/chromium/net/quic/test_tools/quic_buffered_packet_store_peer.h
index efa4b03459e..0951d6ad6ac 100644
--- a/chromium/net/quic/test_tools/quic_buffered_packet_store_peer.h
+++ b/chromium/net/quic/test_tools/quic_buffered_packet_store_peer.h
@@ -8,7 +8,7 @@
#include <memory>
#include "net/quic/core/quic_alarm.h"
-#include "net/quic/core/quic_clock.h"
+#include "net/quic/platform/api/quic_clock.h"
namespace net {
diff --git a/chromium/net/quic/test_tools/quic_config_peer.cc b/chromium/net/quic/test_tools/quic_config_peer.cc
index d9144172b6a..45cf42500ee 100644
--- a/chromium/net/quic/test_tools/quic_config_peer.cc
+++ b/chromium/net/quic/test_tools/quic_config_peer.cc
@@ -71,7 +71,7 @@ void QuicConfigPeer::SetReceivedForceHolBlocking(QuicConfig* config) {
// static
void QuicConfigPeer::SetReceivedAlternateServerAddress(QuicConfig* config,
- IPEndPoint addr) {
+ QuicSocketAddress addr) {
config->alternate_server_address_.SetReceivedValue(addr);
}
diff --git a/chromium/net/quic/test_tools/quic_config_peer.h b/chromium/net/quic/test_tools/quic_config_peer.h
index 0742f3529d9..20c8f08d933 100644
--- a/chromium/net/quic/test_tools/quic_config_peer.h
+++ b/chromium/net/quic/test_tools/quic_config_peer.h
@@ -9,7 +9,7 @@
#include "base/macros.h"
#include "net/quic/core/quic_config.h"
-#include "net/quic/core/quic_protocol.h"
+#include "net/quic/core/quic_packets.h"
namespace net {
@@ -44,7 +44,7 @@ class QuicConfigPeer {
static void SetReceivedForceHolBlocking(QuicConfig* config);
static void SetReceivedAlternateServerAddress(QuicConfig* config,
- IPEndPoint addr);
+ QuicSocketAddress addr);
private:
DISALLOW_COPY_AND_ASSIGN(QuicConfigPeer);
diff --git a/chromium/net/quic/test_tools/quic_connection_peer.cc b/chromium/net/quic/test_tools/quic_connection_peer.cc
index 24118ddcf18..11e34198cc9 100644
--- a/chromium/net/quic/test_tools/quic_connection_peer.cc
+++ b/chromium/net/quic/test_tools/quic_connection_peer.cc
@@ -6,7 +6,7 @@
#include "base/stl_util.h"
#include "net/quic/core/congestion_control/send_algorithm_interface.h"
-#include "net/quic/core/quic_multipath_sent_packet_manager.h"
+#include "net/quic/core/quic_flags.h"
#include "net/quic/core/quic_packet_writer.h"
#include "net/quic/core/quic_received_packet_manager.h"
#include "net/quic/test_tools/quic_framer_peer.h"
@@ -24,17 +24,15 @@ void QuicConnectionPeer::SendAck(QuicConnection* connection) {
// static
void QuicConnectionPeer::SetSendAlgorithm(
QuicConnection* connection,
- QuicPathId path_id,
SendAlgorithmInterface* send_algorithm) {
- GetSentPacketManager(connection, path_id)->SetSendAlgorithm(send_algorithm);
+ GetSentPacketManager(connection)->SetSendAlgorithm(send_algorithm);
}
// static
void QuicConnectionPeer::SetLossAlgorithm(
QuicConnection* connection,
- QuicPathId path_id,
LossDetectionInterface* loss_algorithm) {
- GetSentPacketManager(connection, path_id)->loss_algorithm_ = loss_algorithm;
+ GetSentPacketManager(connection)->loss_algorithm_ = loss_algorithm;
}
// static
@@ -71,16 +69,8 @@ QuicPacketGenerator* QuicConnectionPeer::GetPacketGenerator(
// static
QuicSentPacketManager* QuicConnectionPeer::GetSentPacketManager(
- QuicConnection* connection,
- QuicPathId path_id) {
- if (FLAGS_quic_enable_multipath) {
- return static_cast<QuicSentPacketManager*>(
- static_cast<QuicMultipathSentPacketManager*>(
- connection->sent_packet_manager_.get())
- ->MaybeGetSentPacketManagerForPath(path_id));
- }
- return static_cast<QuicSentPacketManager*>(
- connection->sent_packet_manager_.get());
+ QuicConnection* connection) {
+ return &connection->sent_packet_manager_;
}
// static
@@ -90,38 +80,6 @@ QuicTime::Delta QuicConnectionPeer::GetNetworkTimeout(
}
// static
-QuicSentEntropyManager* QuicConnectionPeer::GetSentEntropyManager(
- QuicConnection* connection) {
- return &connection->sent_entropy_manager_;
-}
-
-// static
-// TODO(ianswett): Create a GetSentEntropyHash which accepts an AckFrame.
-QuicPacketEntropyHash QuicConnectionPeer::GetSentEntropyHash(
- QuicConnection* connection,
- QuicPacketNumber packet_number) {
- QuicSentEntropyManager::CumulativeEntropy last_entropy_copy =
- connection->sent_entropy_manager_.last_cumulative_entropy_;
- connection->sent_entropy_manager_.UpdateCumulativeEntropy(packet_number,
- &last_entropy_copy);
- return last_entropy_copy.entropy;
-}
-
-// static
-QuicPacketEntropyHash QuicConnectionPeer::PacketEntropy(
- QuicConnection* connection,
- QuicPacketNumber packet_number) {
- return connection->sent_entropy_manager_.GetPacketEntropy(packet_number);
-}
-
-// static
-QuicPacketEntropyHash QuicConnectionPeer::ReceivedEntropyHash(
- QuicConnection* connection,
- QuicPacketNumber packet_number) {
- return connection->received_packet_manager_.EntropyHash(packet_number);
-}
-
-// static
void QuicConnectionPeer::SetPerspective(QuicConnection* connection,
Perspective perspective) {
connection->perspective_ = perspective;
@@ -130,13 +88,13 @@ void QuicConnectionPeer::SetPerspective(QuicConnection* connection,
// static
void QuicConnectionPeer::SetSelfAddress(QuicConnection* connection,
- const IPEndPoint& self_address) {
+ const QuicSocketAddress& self_address) {
connection->self_address_ = self_address;
}
// static
void QuicConnectionPeer::SetPeerAddress(QuicConnection* connection,
- const IPEndPoint& peer_address) {
+ const QuicSocketAddress& peer_address) {
connection->peer_address_ = peer_address;
}
@@ -305,7 +263,7 @@ bool QuicConnectionPeer::HasRetransmittableFrames(
QuicPathId path_id,
QuicPacketNumber packet_number) {
return QuicSentPacketManagerPeer::HasRetransmittableFrames(
- GetSentPacketManager(connection, path_id), packet_number);
+ GetSentPacketManager(connection), packet_number);
}
} // namespace test
diff --git a/chromium/net/quic/test_tools/quic_connection_peer.h b/chromium/net/quic/test_tools/quic_connection_peer.h
index dc35c9e9fac..0a5c529b140 100644
--- a/chromium/net/quic/test_tools/quic_connection_peer.h
+++ b/chromium/net/quic/test_tools/quic_connection_peer.h
@@ -9,11 +9,11 @@
#include "net/base/ip_endpoint.h"
#include "net/quic/core/quic_connection.h"
#include "net/quic/core/quic_connection_stats.h"
-#include "net/quic/core/quic_protocol.h"
+#include "net/quic/core/quic_packets.h"
+#include "net/quic/platform/api/quic_socket_address.h"
namespace net {
-struct QuicAckFrame;
struct QuicPacketHeader;
class QuicAlarm;
class QuicConnectionHelperInterface;
@@ -23,8 +23,6 @@ class QuicFramer;
class QuicPacketCreator;
class QuicPacketGenerator;
class QuicPacketWriter;
-class QuicReceivedPacketManager;
-class QuicSentEntropyManager;
class QuicSentPacketManager;
class SendAlgorithmInterface;
@@ -35,14 +33,10 @@ class QuicConnectionPeer {
public:
static void SendAck(QuicConnection* connection);
- // Sets send algorithm of |path_id|.
static void SetSendAlgorithm(QuicConnection* connection,
- QuicPathId path_id,
SendAlgorithmInterface* send_algorithm);
- // Sets loss algorithm of |path_id|.
static void SetLossAlgorithm(QuicConnection* connection,
- QuicPathId path_id,
LossDetectionInterface* loss_algorithm);
static const QuicFrame GetUpdatedAckFrame(QuicConnection* connection);
@@ -56,34 +50,19 @@ class QuicConnectionPeer {
static QuicPacketGenerator* GetPacketGenerator(QuicConnection* connection);
- // Returns sent packet manager of |path_id|.
- static QuicSentPacketManager* GetSentPacketManager(QuicConnection* connection,
- QuicPathId path_id);
-
- static QuicTime::Delta GetNetworkTimeout(QuicConnection* connection);
-
- static QuicSentEntropyManager* GetSentEntropyManager(
+ static QuicSentPacketManager* GetSentPacketManager(
QuicConnection* connection);
- static QuicPacketEntropyHash GetSentEntropyHash(
- QuicConnection* connection,
- QuicPacketNumber packet_number);
-
- static QuicPacketEntropyHash PacketEntropy(QuicConnection* connection,
- QuicPacketNumber packet_number);
-
- static QuicPacketEntropyHash ReceivedEntropyHash(
- QuicConnection* connection,
- QuicPacketNumber packet_number);
+ static QuicTime::Delta GetNetworkTimeout(QuicConnection* connection);
static void SetPerspective(QuicConnection* connection,
Perspective perspective);
static void SetSelfAddress(QuicConnection* connection,
- const IPEndPoint& self_address);
+ const QuicSocketAddress& self_address);
static void SetPeerAddress(QuicConnection* connection,
- const IPEndPoint& peer_address);
+ const QuicSocketAddress& peer_address);
static bool IsSilentCloseEnabled(QuicConnection* connection);
diff --git a/chromium/net/quic/test_tools/quic_crypto_server_config_peer.cc b/chromium/net/quic/test_tools/quic_crypto_server_config_peer.cc
index ade944e7828..d9a47f7747b 100644
--- a/chromium/net/quic/test_tools/quic_crypto_server_config_peer.cc
+++ b/chromium/net/quic/test_tools/quic_crypto_server_config_peer.cc
@@ -20,18 +20,18 @@ ProofSource* QuicCryptoServerConfigPeer::GetProofSource() {
return server_config_->proof_source_.get();
}
-scoped_refptr<QuicCryptoServerConfig::Config>
+QuicReferenceCountedPointer<QuicCryptoServerConfig::Config>
QuicCryptoServerConfigPeer::GetPrimaryConfig() {
- base::AutoLock locked(server_config_->configs_lock_);
- return scoped_refptr<QuicCryptoServerConfig::Config>(
+ QuicReaderMutexLock locked(&server_config_->configs_lock_);
+ return QuicReferenceCountedPointer<QuicCryptoServerConfig::Config>(
server_config_->primary_config_);
}
-scoped_refptr<QuicCryptoServerConfig::Config>
+QuicReferenceCountedPointer<QuicCryptoServerConfig::Config>
QuicCryptoServerConfigPeer::GetConfig(string config_id) {
- base::AutoLock locked(server_config_->configs_lock_);
+ QuicReaderMutexLock locked(&server_config_->configs_lock_);
if (config_id == "<primary>") {
- return scoped_refptr<QuicCryptoServerConfig::Config>(
+ return QuicReferenceCountedPointer<QuicCryptoServerConfig::Config>(
server_config_->primary_config_);
} else {
return server_config_->GetConfigWithScid(config_id);
@@ -42,10 +42,15 @@ ProofSource* QuicCryptoServerConfigPeer::GetProofSource() const {
return server_config_->proof_source_.get();
}
+void QuicCryptoServerConfigPeer::ResetProofSource(
+ std::unique_ptr<ProofSource> proof_source) {
+ server_config_->proof_source_ = std::move(proof_source);
+}
+
string QuicCryptoServerConfigPeer::NewSourceAddressToken(
string config_id,
SourceAddressTokens previous_tokens,
- const IPAddress& ip,
+ const QuicIpAddress& ip,
QuicRandom* rand,
QuicWallTime now,
CachedNetworkParameters* cached_network_params) {
@@ -57,7 +62,7 @@ string QuicCryptoServerConfigPeer::NewSourceAddressToken(
HandshakeFailureReason QuicCryptoServerConfigPeer::ValidateSourceAddressTokens(
string config_id,
StringPiece srct,
- const IPAddress& ip,
+ const QuicIpAddress& ip,
QuicWallTime now,
CachedNetworkParameters* cached_network_params) {
SourceAddressTokens tokens;
@@ -74,7 +79,7 @@ HandshakeFailureReason QuicCryptoServerConfigPeer::ValidateSourceAddressTokens(
HandshakeFailureReason
QuicCryptoServerConfigPeer::ValidateSingleSourceAddressToken(
StringPiece token,
- const IPAddress& ip,
+ const QuicIpAddress& ip,
QuicWallTime now) {
SourceAddressTokens tokens;
HandshakeFailureReason parse_status = server_config_->ParseSourceAddressToken(
@@ -92,16 +97,6 @@ string QuicCryptoServerConfigPeer::NewServerNonce(QuicRandom* rand,
return server_config_->NewServerNonce(rand, now);
}
-HandshakeFailureReason QuicCryptoServerConfigPeer::ValidateServerNonce(
- StringPiece token,
- QuicWallTime now) {
- return server_config_->ValidateServerNonce(token, now);
-}
-
-base::Lock* QuicCryptoServerConfigPeer::GetStrikeRegisterClientLock() {
- return &server_config_->strike_register_client_lock_;
-}
-
void QuicCryptoServerConfigPeer::CheckConfigs(const char* server_config_id1,
...) {
va_list ap;
@@ -130,12 +125,13 @@ void QuicCryptoServerConfigPeer::CheckConfigs(const char* server_config_id1,
va_end(ap);
- base::AutoLock locked(server_config_->configs_lock_);
+ QuicReaderMutexLock locked(&server_config_->configs_lock_);
ASSERT_EQ(expected.size(), server_config_->configs_.size()) << ConfigsDebug();
- for (const std::pair<const ServerConfigID,
- scoped_refptr<QuicCryptoServerConfig::Config>>& i :
+ for (const std::pair<
+ const ServerConfigID,
+ QuicReferenceCountedPointer<QuicCryptoServerConfig::Config>>& i :
server_config_->configs_) {
bool found = false;
for (std::pair<ServerConfigID, bool>& j : expected) {
@@ -162,7 +158,8 @@ string QuicCryptoServerConfigPeer::ConfigsDebug() {
string s;
for (const auto& i : server_config_->configs_) {
- const scoped_refptr<QuicCryptoServerConfig::Config> config = i.second;
+ const QuicReferenceCountedPointer<QuicCryptoServerConfig::Config> config =
+ i.second;
if (config->is_primary) {
s += "(primary) ";
} else {
@@ -176,14 +173,14 @@ string QuicCryptoServerConfigPeer::ConfigsDebug() {
}
void QuicCryptoServerConfigPeer::SelectNewPrimaryConfig(int seconds) {
- base::AutoLock locked(server_config_->configs_lock_);
+ QuicWriterMutexLock locked(&server_config_->configs_lock_);
server_config_->SelectNewPrimaryConfig(
QuicWallTime::FromUNIXSeconds(seconds));
}
string QuicCryptoServerConfigPeer::CompressChain(
QuicCompressedCertsCache* compressed_certs_cache,
- const scoped_refptr<ProofSource::Chain>& chain,
+ const QuicReferenceCountedPointer<ProofSource::Chain>& chain,
const string& client_common_set_hashes,
const string& client_cached_cert_hashes,
const CommonCertSets* common_sets) {
@@ -200,15 +197,5 @@ uint32_t QuicCryptoServerConfigPeer::source_address_token_lifetime_secs() {
return server_config_->source_address_token_lifetime_secs_;
}
-uint32_t
-QuicCryptoServerConfigPeer::server_nonce_strike_register_max_entries() {
- return server_config_->server_nonce_strike_register_max_entries_;
-}
-
-uint32_t
-QuicCryptoServerConfigPeer::server_nonce_strike_register_window_secs() {
- return server_config_->server_nonce_strike_register_window_secs_;
-}
-
} // namespace test
} // namespace net
diff --git a/chromium/net/quic/test_tools/quic_crypto_server_config_peer.h b/chromium/net/quic/test_tools/quic_crypto_server_config_peer.h
index 6f5794de977..310be87bf26 100644
--- a/chromium/net/quic/test_tools/quic_crypto_server_config_peer.h
+++ b/chromium/net/quic/test_tools/quic_crypto_server_config_peer.h
@@ -13,28 +13,31 @@ namespace test {
// Peer for accessing otherwise private members of a QuicCryptoServerConfig.
class QuicCryptoServerConfigPeer {
public:
- explicit QuicCryptoServerConfigPeer(
- const QuicCryptoServerConfig* server_config)
+ explicit QuicCryptoServerConfigPeer(QuicCryptoServerConfig* server_config)
: server_config_(server_config) {}
// Returns the proof source.
ProofSource* GetProofSource();
// Returns the primary config.
- scoped_refptr<QuicCryptoServerConfig::Config> GetPrimaryConfig();
+ QuicReferenceCountedPointer<QuicCryptoServerConfig::Config>
+ GetPrimaryConfig();
// Returns the config associated with |config_id|.
- scoped_refptr<QuicCryptoServerConfig::Config> GetConfig(
+ QuicReferenceCountedPointer<QuicCryptoServerConfig::Config> GetConfig(
std::string config_id);
// Returns a pointer to the ProofSource object.
ProofSource* GetProofSource() const;
+ // Reset the proof_source_ member.
+ void ResetProofSource(std::unique_ptr<ProofSource> proof_source);
+
// Generates a new valid source address token.
std::string NewSourceAddressToken(
std::string config_id,
SourceAddressTokens previous_tokens,
- const IPAddress& ip,
+ const QuicIpAddress& ip,
QuicRandom* rand,
QuicWallTime now,
CachedNetworkParameters* cached_network_params);
@@ -43,30 +46,22 @@ class QuicCryptoServerConfigPeer {
HandshakeFailureReason ValidateSourceAddressTokens(
std::string config_id,
base::StringPiece tokens,
- const IPAddress& ip,
+ const QuicIpAddress& ip,
QuicWallTime now,
CachedNetworkParameters* cached_network_params);
// Attempts to validate the single source address token in |token|.
HandshakeFailureReason ValidateSingleSourceAddressToken(
base::StringPiece token,
- const IPAddress& ip,
+ const QuicIpAddress& ip,
QuicWallTime now);
// Returns a new server nonce.
std::string NewServerNonce(QuicRandom* rand, QuicWallTime now) const;
- // Check if |nonce| is valid |now|.
- HandshakeFailureReason ValidateServerNonce(base::StringPiece nonce,
- QuicWallTime now);
-
- // Returns the mutex needed to access the strike register client.
- base::Lock* GetStrikeRegisterClientLock();
-
// CheckConfigs compares the state of the Configs in |server_config_| to the
// description given as arguments. The arguments are given as
- // nullptr-terminated std:pairs. The first of each std:pair is the server
- // config ID of
+ // nullptr-terminated pairs. The first of each pair is the server config ID of
// a Config. The second is a boolean describing whether the config is the
// primary. For example:
// CheckConfigs(nullptr); // checks that no Configs are loaded.
@@ -80,8 +75,7 @@ class QuicCryptoServerConfigPeer {
// nullptr);
void CheckConfigs(const char* server_config_id1, ...);
- // ConfigsDebug returns a std::string that contains debugging information
- // about
+ // ConfigsDebug returns a string that contains debugging information about
// the set of Configs loaded in |server_config_| and their status.
std::string ConfigsDebug();
@@ -89,7 +83,7 @@ class QuicCryptoServerConfigPeer {
static std::string CompressChain(
QuicCompressedCertsCache* compressed_certs_cache,
- const scoped_refptr<ProofSource::Chain>& chain,
+ const QuicReferenceCountedPointer<ProofSource::Chain>& chain,
const std::string& client_common_set_hashes,
const std::string& client_cached_cert_hashes,
const CommonCertSets* common_sets);
@@ -98,12 +92,8 @@ class QuicCryptoServerConfigPeer {
uint32_t source_address_token_lifetime_secs();
- uint32_t server_nonce_strike_register_max_entries();
-
- uint32_t server_nonce_strike_register_window_secs();
-
private:
- const QuicCryptoServerConfig* server_config_;
+ QuicCryptoServerConfig* server_config_;
};
} // namespace test
diff --git a/chromium/net/quic/test_tools/quic_flow_controller_peer.cc b/chromium/net/quic/test_tools/quic_flow_controller_peer.cc
index 5fc7d4295fc..73f20a27c1d 100644
--- a/chromium/net/quic/test_tools/quic_flow_controller_peer.cc
+++ b/chromium/net/quic/test_tools/quic_flow_controller_peer.cc
@@ -7,7 +7,7 @@
#include <list>
#include "net/quic/core/quic_flow_controller.h"
-#include "net/quic/core/quic_protocol.h"
+#include "net/quic/core/quic_packets.h"
namespace net {
namespace test {
diff --git a/chromium/net/quic/test_tools/quic_flow_controller_peer.h b/chromium/net/quic/test_tools/quic_flow_controller_peer.h
index 7788980c6a8..cc42cde9ba4 100644
--- a/chromium/net/quic/test_tools/quic_flow_controller_peer.h
+++ b/chromium/net/quic/test_tools/quic_flow_controller_peer.h
@@ -6,7 +6,7 @@
#define NET_QUIC_TEST_TOOLS_QUIC_FLOW_CONTROLLER_PEER_H_
#include "base/macros.h"
-#include "net/quic/core/quic_protocol.h"
+#include "net/quic/core/quic_packets.h"
namespace net {
diff --git a/chromium/net/quic/test_tools/quic_framer_peer.cc b/chromium/net/quic/test_tools/quic_framer_peer.cc
index f884e7bf6a7..9c873f7a21a 100644
--- a/chromium/net/quic/test_tools/quic_framer_peer.cc
+++ b/chromium/net/quic/test_tools/quic_framer_peer.cc
@@ -6,7 +6,7 @@
#include "base/stl_util.h"
#include "net/quic/core/quic_framer.h"
-#include "net/quic/core/quic_protocol.h"
+#include "net/quic/core/quic_packets.h"
namespace net {
namespace test {
diff --git a/chromium/net/quic/test_tools/quic_framer_peer.h b/chromium/net/quic/test_tools/quic_framer_peer.h
index 3ab38304ff6..7b8b17947a0 100644
--- a/chromium/net/quic/test_tools/quic_framer_peer.h
+++ b/chromium/net/quic/test_tools/quic_framer_peer.h
@@ -8,7 +8,7 @@
#include "base/macros.h"
#include "net/quic/core/crypto/quic_encrypter.h"
#include "net/quic/core/quic_framer.h"
-#include "net/quic/core/quic_protocol.h"
+#include "net/quic/core/quic_packets.h"
namespace net {
diff --git a/chromium/net/quic/test_tools/quic_headers_stream_peer.cc b/chromium/net/quic/test_tools/quic_headers_stream_peer.cc
deleted file mode 100644
index 1e8e65bf0f3..00000000000
--- a/chromium/net/quic/test_tools/quic_headers_stream_peer.cc
+++ /dev/null
@@ -1,19 +0,0 @@
-// Copyright 2016 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.
-
-#include "net/quic/test_tools/quic_headers_stream_peer.h"
-
-#include "net/quic/core/quic_headers_stream.h"
-
-namespace net {
-namespace test {
-
-// static
-const SpdyFramer& QuicHeadersStreamPeer::GetSpdyFramer(
- QuicHeadersStream* stream) {
- return stream->spdy_framer_;
-}
-
-} // namespace test
-} // namespace net
diff --git a/chromium/net/quic/test_tools/quic_headers_stream_peer.h b/chromium/net/quic/test_tools/quic_headers_stream_peer.h
deleted file mode 100644
index 998f3e970c1..00000000000
--- a/chromium/net/quic/test_tools/quic_headers_stream_peer.h
+++ /dev/null
@@ -1,28 +0,0 @@
-// Copyright 2016 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.
-
-#ifndef NET_QUIC_TEST_TOOLS_QUIC_HEADERS_STREAM_PEER_H_
-#define NET_QUIC_TEST_TOOLS_QUIC_HEADERS_STREAM_PEER_H_
-
-#include "net/spdy/spdy_framer.h"
-
-namespace net {
-
-class QuicHeadersStream;
-
-namespace test {
-
-class QuicHeadersStreamPeer {
- public:
- static const SpdyFramer& GetSpdyFramer(QuicHeadersStream* stream);
-
- private:
- DISALLOW_COPY_AND_ASSIGN(QuicHeadersStreamPeer);
-};
-
-} // namespace test
-
-} // namespace net
-
-#endif // NET_QUIC_TEST_TOOLS_QUIC_HEADERS_STREAM_PEER_H_
diff --git a/chromium/net/quic/test_tools/quic_multipath_sent_packet_manager_peer.cc b/chromium/net/quic/test_tools/quic_multipath_sent_packet_manager_peer.cc
deleted file mode 100644
index 5115cc4b43a..00000000000
--- a/chromium/net/quic/test_tools/quic_multipath_sent_packet_manager_peer.cc
+++ /dev/null
@@ -1,29 +0,0 @@
-// Copyright (c) 2012 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.
-
-#include "net/quic/test_tools/quic_multipath_sent_packet_manager_peer.h"
-
-namespace net {
-namespace test {
-
-// static
-void QuicMultipathSentPacketManagerPeer::AddPathWithCloseState(
- QuicMultipathSentPacketManager* multipath_manager,
- QuicSentPacketManagerInterface* manager) {
- multipath_manager->path_managers_info_.push_back(
- QuicMultipathSentPacketManager::PathSentPacketManagerInfo(
- manager, QuicMultipathSentPacketManager::CLOSING));
-}
-
-// static
-void QuicMultipathSentPacketManagerPeer::AddPathWithActiveState(
- QuicMultipathSentPacketManager* multipath_manager,
- QuicSentPacketManagerInterface* manager) {
- multipath_manager->path_managers_info_.push_back(
- QuicMultipathSentPacketManager::PathSentPacketManagerInfo(
- manager, QuicMultipathSentPacketManager::ACTIVE));
-}
-
-} // namespace test
-} // namespace net
diff --git a/chromium/net/quic/test_tools/quic_multipath_sent_packet_manager_peer.h b/chromium/net/quic/test_tools/quic_multipath_sent_packet_manager_peer.h
deleted file mode 100644
index 21477452e22..00000000000
--- a/chromium/net/quic/test_tools/quic_multipath_sent_packet_manager_peer.h
+++ /dev/null
@@ -1,31 +0,0 @@
-// Copyright (c) 2012 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.
-
-#ifndef NET_QUIC_TEST_TOOLS_QUIC_MULTIPATH_SENT_PACKET_MANAGER_PEER_H_
-#define NET_QUIC_TEST_TOOLS_QUIC_MULTIPATH_SENT_PACKET_MANAGER_PEER_H_
-
-#include "base/macros.h"
-#include "net/quic/core/quic_multipath_sent_packet_manager.h"
-#include "net/quic/test_tools/quic_sent_packet_manager_peer.h"
-
-namespace net {
-namespace test {
-
-class QuicMultipathSentPacketManagerPeer {
- public:
- // Add a path |manager| with close state.
- static void AddPathWithCloseState(
- QuicMultipathSentPacketManager* multipath_manager,
- QuicSentPacketManagerInterface* manager);
-
- // Add a path |manager| with active state.
- static void AddPathWithActiveState(
- QuicMultipathSentPacketManager* multipath_manager,
- QuicSentPacketManagerInterface* manager);
-};
-
-} // namespace test
-} // namespace net
-
-#endif // NET_QUIC_TEST_TOOLS_QUIC_MULTIPATH_SENT_PACKET_MANAGER_PEER_H_
diff --git a/chromium/net/quic/test_tools/quic_packet_creator_peer.h b/chromium/net/quic/test_tools/quic_packet_creator_peer.h
index 645d1a80b2c..1cdb91b5dbc 100644
--- a/chromium/net/quic/test_tools/quic_packet_creator_peer.h
+++ b/chromium/net/quic/test_tools/quic_packet_creator_peer.h
@@ -8,7 +8,8 @@
#include <stddef.h>
#include "base/macros.h"
-#include "net/quic/core/quic_protocol.h"
+#include "net/quic/core/quic_iovector.h"
+#include "net/quic/core/quic_packets.h"
namespace net {
class QuicPacketCreator;
diff --git a/chromium/net/quic/test_tools/quic_packet_generator_peer.h b/chromium/net/quic/test_tools/quic_packet_generator_peer.h
index 2aaa263b9bf..7d0becda64a 100644
--- a/chromium/net/quic/test_tools/quic_packet_generator_peer.h
+++ b/chromium/net/quic/test_tools/quic_packet_generator_peer.h
@@ -6,7 +6,7 @@
#define NET_QUIC_TEST_TOOLS_QUIC_PACKET_GENERATOR_PEER_H_
#include "base/macros.h"
-#include "net/quic/core/quic_protocol.h"
+#include "net/quic/core/quic_packets.h"
namespace net {
diff --git a/chromium/net/quic/test_tools/quic_received_packet_manager_peer.cc b/chromium/net/quic/test_tools/quic_received_packet_manager_peer.cc
index c990cc3ac09..1e0ee002c4d 100644
--- a/chromium/net/quic/test_tools/quic_received_packet_manager_peer.cc
+++ b/chromium/net/quic/test_tools/quic_received_packet_manager_peer.cc
@@ -4,22 +4,13 @@
#include "net/quic/test_tools/quic_received_packet_manager_peer.h"
-#include "net/quic/core/quic_protocol.h"
+#include "net/quic/core/quic_packets.h"
#include "net/quic/core/quic_received_packet_manager.h"
namespace net {
namespace test {
// static
-void QuicReceivedPacketManagerPeer::SetCumulativeEntropyUpTo(
- QuicReceivedPacketManager* received_packet_manager,
- QuicPacketNumber peer_least_unacked,
- QuicPacketEntropyHash entropy_hash) {
- received_packet_manager->entropy_tracker_.SetCumulativeEntropyUpTo(
- peer_least_unacked, entropy_hash);
-}
-
-// static
bool QuicReceivedPacketManagerPeer::DontWaitForPacketsBefore(
QuicReceivedPacketManager* received_packet_manager,
QuicPacketNumber least_unacked) {
diff --git a/chromium/net/quic/test_tools/quic_received_packet_manager_peer.h b/chromium/net/quic/test_tools/quic_received_packet_manager_peer.h
index 90dfd3a1d6f..43a9d2049c2 100644
--- a/chromium/net/quic/test_tools/quic_received_packet_manager_peer.h
+++ b/chromium/net/quic/test_tools/quic_received_packet_manager_peer.h
@@ -6,7 +6,7 @@
#define NET_QUIC_TEST_TOOLS_QUIC_RECEIVED_PACKET_MANAGER_PEER_H_
#include "base/macros.h"
-#include "net/quic/core/quic_protocol.h"
+#include "net/quic/core/quic_packets.h"
namespace net {
@@ -16,11 +16,6 @@ namespace test {
class QuicReceivedPacketManagerPeer {
public:
- static void SetCumulativeEntropyUpTo(
- QuicReceivedPacketManager* received_packet_manager,
- QuicPacketNumber peer_least_unacked,
- QuicPacketEntropyHash entropy_hash);
-
static bool DontWaitForPacketsBefore(
QuicReceivedPacketManager* received_packet_manager,
QuicPacketNumber least_unacked);
diff --git a/chromium/net/quic/test_tools/quic_sent_packet_manager_peer.cc b/chromium/net/quic/test_tools/quic_sent_packet_manager_peer.cc
index 1b617e59b34..d3039726ddd 100644
--- a/chromium/net/quic/test_tools/quic_sent_packet_manager_peer.cc
+++ b/chromium/net/quic/test_tools/quic_sent_packet_manager_peer.cc
@@ -8,7 +8,7 @@
#include "net/quic/core/congestion_control/loss_detection_interface.h"
#include "net/quic/core/congestion_control/send_algorithm_interface.h"
#include "net/quic/core/quic_flags.h"
-#include "net/quic/core/quic_protocol.h"
+#include "net/quic/core/quic_packets.h"
#include "net/quic/core/quic_sent_packet_manager.h"
namespace net {
@@ -46,12 +46,6 @@ bool QuicSentPacketManagerPeer::GetUndoRetransmits(
}
// static
-QuicByteCount QuicSentPacketManagerPeer::GetReceiveWindow(
- QuicSentPacketManager* sent_packet_manager) {
- return sent_packet_manager->receive_buffer_bytes_;
-}
-
-// static
void QuicSentPacketManagerPeer::SetPerspective(
QuicSentPacketManager* sent_packet_manager,
Perspective perspective) {
@@ -104,7 +98,6 @@ QuicTime QuicSentPacketManagerPeer::GetSentTime(
// static
bool QuicSentPacketManagerPeer::IsRetransmission(
QuicSentPacketManager* sent_packet_manager,
- QuicPathId path_id,
QuicPacketNumber packet_number) {
DCHECK(HasRetransmittableFrames(sent_packet_manager, packet_number));
if (!HasRetransmittableFrames(sent_packet_manager, packet_number)) {
@@ -121,7 +114,6 @@ bool QuicSentPacketManagerPeer::IsRetransmission(
// static
void QuicSentPacketManagerPeer::MarkForRetransmission(
QuicSentPacketManager* sent_packet_manager,
- QuicPathId path_id,
QuicPacketNumber packet_number,
TransmissionType transmission_type) {
sent_packet_manager->MarkForRetransmission(packet_number, transmission_type);
@@ -160,7 +152,7 @@ QuicByteCount QuicSentPacketManagerPeer::GetBytesInFlight(
}
// static
-QuicSentPacketManagerInterface::NetworkChangeVisitor*
+QuicSentPacketManager::NetworkChangeVisitor*
QuicSentPacketManagerPeer::GetNetworkChangeVisitor(
const QuicSentPacketManager* sent_packet_manager) {
return sent_packet_manager->network_change_visitor_;
diff --git a/chromium/net/quic/test_tools/quic_sent_packet_manager_peer.h b/chromium/net/quic/test_tools/quic_sent_packet_manager_peer.h
index c9eedc2c21d..0ffbafc25ab 100644
--- a/chromium/net/quic/test_tools/quic_sent_packet_manager_peer.h
+++ b/chromium/net/quic/test_tools/quic_sent_packet_manager_peer.h
@@ -8,7 +8,7 @@
#include <stddef.h>
#include "base/macros.h"
-#include "net/quic/core/quic_protocol.h"
+#include "net/quic/core/quic_packets.h"
#include "net/quic/core/quic_sent_packet_manager.h"
namespace net {
@@ -32,9 +32,6 @@ class QuicSentPacketManagerPeer {
static bool GetUndoRetransmits(QuicSentPacketManager* sent_packet_manager);
- static QuicByteCount GetReceiveWindow(
- QuicSentPacketManager* sent_packet_manager);
-
static void SetPerspective(QuicSentPacketManager* sent_packet_manager,
Perspective perspective);
@@ -56,14 +53,11 @@ class QuicSentPacketManagerPeer {
static QuicTime GetSentTime(const QuicSentPacketManager* sent_packet_manager,
QuicPacketNumber packet_number);
- // Returns true if |packet_number| of |path_id| is a retransmission of a
- // packet.
+ // Returns true if |packet_number| is a retransmission of a packet.
static bool IsRetransmission(QuicSentPacketManager* sent_packet_manager,
- QuicPathId path_id,
QuicPacketNumber packet_number);
static void MarkForRetransmission(QuicSentPacketManager* sent_packet_manager,
- QuicPathId path_id,
QuicPacketNumber packet_number,
TransmissionType transmission_type);
@@ -79,8 +73,8 @@ class QuicSentPacketManagerPeer {
static QuicByteCount GetBytesInFlight(
const QuicSentPacketManager* sent_packet_manager);
- static QuicSentPacketManagerInterface::NetworkChangeVisitor*
- GetNetworkChangeVisitor(const QuicSentPacketManager* sent_packet_manager);
+ static QuicSentPacketManager::NetworkChangeVisitor* GetNetworkChangeVisitor(
+ const QuicSentPacketManager* sent_packet_manager);
static void SetConsecutiveRtoCount(QuicSentPacketManager* sent_packet_manager,
size_t count);
diff --git a/chromium/net/quic/test_tools/quic_session_peer.h b/chromium/net/quic/test_tools/quic_session_peer.h
index 59245fe72d7..8874c7ac961 100644
--- a/chromium/net/quic/test_tools/quic_session_peer.h
+++ b/chromium/net/quic/test_tools/quic_session_peer.h
@@ -11,16 +11,14 @@
#include <memory>
#include "base/macros.h"
-#include "net/quic/core/quic_protocol.h"
+#include "net/quic/core/quic_packets.h"
#include "net/quic/core/quic_session.h"
#include "net/quic/core/quic_write_blocked_list.h"
namespace net {
class QuicCryptoStream;
-class QuicHeadersStream;
class QuicSession;
-class QuicSpdyStream;
class QuicStream;
namespace test {
diff --git a/chromium/net/quic/test_tools/quic_spdy_session_peer.cc b/chromium/net/quic/test_tools/quic_spdy_session_peer.cc
index ad760e62906..37b76e1dc4f 100644
--- a/chromium/net/quic/test_tools/quic_spdy_session_peer.cc
+++ b/chromium/net/quic/test_tools/quic_spdy_session_peer.cc
@@ -28,5 +28,41 @@ void QuicSpdySessionPeer::SetForceHolBlocking(QuicSpdySession* session,
session->force_hol_blocking_ = value;
}
+// static
+const SpdyFramer& QuicSpdySessionPeer::GetSpdyFramer(
+ QuicSpdySession* session) {
+ return session->spdy_framer_;
+}
+
+void QuicSpdySessionPeer::SetHpackEncoderDebugVisitor(
+ QuicSpdySession* session,
+ std::unique_ptr<QuicHpackDebugVisitor> visitor) {
+ session->SetHpackEncoderDebugVisitor(std::move(visitor));
+}
+
+void QuicSpdySessionPeer::SetHpackDecoderDebugVisitor(
+ QuicSpdySession* session,
+ std::unique_ptr<QuicHpackDebugVisitor> visitor) {
+ session->SetHpackDecoderDebugVisitor(std::move(visitor));
+}
+
+void QuicSpdySessionPeer::SetMaxUncompressedHeaderBytes(
+ QuicSpdySession* session,
+ size_t set_max_uncompressed_header_bytes) {
+ session->set_max_uncompressed_header_bytes(set_max_uncompressed_header_bytes);
+}
+
+// static
+size_t QuicSpdySessionPeer::WriteHeadersImpl(
+ QuicSpdySession* session,
+ QuicStreamId id,
+ SpdyHeaderBlock headers,
+ bool fin,
+ SpdyPriority priority,
+ QuicReferenceCountedPointer<QuicAckListenerInterface> ack_listener) {
+ return session->WriteHeadersImpl(id, std::move(headers), fin, priority,
+ std::move(ack_listener));
+}
+
} // namespace test
} // namespace net
diff --git a/chromium/net/quic/test_tools/quic_spdy_session_peer.h b/chromium/net/quic/test_tools/quic_spdy_session_peer.h
index 9cb9cfd554b..f06d579f346 100644
--- a/chromium/net/quic/test_tools/quic_spdy_session_peer.h
+++ b/chromium/net/quic/test_tools/quic_spdy_session_peer.h
@@ -6,13 +6,15 @@
#define NET_QUIC_TEST_TOOLS_QUIC_SPDY_SESSION_PEER_H_
#include "base/macros.h"
-#include "net/quic/core/quic_protocol.h"
+#include "net/quic/core/quic_packets.h"
#include "net/quic/core/quic_write_blocked_list.h"
+#include "net/spdy/spdy_framer.h"
namespace net {
class QuicHeadersStream;
class QuicSpdySession;
+class QuicHpackDebugVisitor;
namespace test {
@@ -22,6 +24,23 @@ class QuicSpdySessionPeer {
static void SetHeadersStream(QuicSpdySession* session,
QuicHeadersStream* headers_stream);
static void SetForceHolBlocking(QuicSpdySession* session, bool value);
+ static const SpdyFramer& GetSpdyFramer(QuicSpdySession* session);
+ static void SetHpackEncoderDebugVisitor(
+ QuicSpdySession* session,
+ std::unique_ptr<QuicHpackDebugVisitor> visitor);
+ static void SetHpackDecoderDebugVisitor(
+ QuicSpdySession* session,
+ std::unique_ptr<QuicHpackDebugVisitor> visitor);
+ static void SetMaxUncompressedHeaderBytes(
+ QuicSpdySession* session,
+ size_t set_max_uncompressed_header_bytes);
+ static size_t WriteHeadersImpl(
+ QuicSpdySession* session,
+ QuicStreamId id,
+ SpdyHeaderBlock headers,
+ bool fin,
+ SpdyPriority priority,
+ QuicReferenceCountedPointer<QuicAckListenerInterface> ack_listener);
private:
DISALLOW_COPY_AND_ASSIGN(QuicSpdySessionPeer);
diff --git a/chromium/net/quic/test_tools/quic_stream_factory_peer.cc b/chromium/net/quic/test_tools/quic_stream_factory_peer.cc
index 94dd59bd0ae..03dbff80981 100644
--- a/chromium/net/quic/test_tools/quic_stream_factory_peer.cc
+++ b/chromium/net/quic/test_tools/quic_stream_factory_peer.cc
@@ -12,12 +12,11 @@
#include "net/quic/chromium/quic_http_stream.h"
#include "net/quic/chromium/quic_stream_factory.h"
#include "net/quic/core/crypto/quic_crypto_client_config.h"
-#include "net/quic/core/quic_clock.h"
+#include "net/quic/platform/impl/quic_chromium_clock.h"
#include "net/test/cert_test_util.h"
#include "net/test/test_data_directory.h"
using std::string;
-using std::vector;
namespace net {
namespace test {
@@ -169,7 +168,7 @@ void QuicStreamFactoryPeer::CacheDummyServerConfig(
string source_address_token("test_source_address_token");
string signature("test_signature");
- vector<string> certs;
+ std::vector<string> certs;
// Load a certificate that is valid for *.example.org
scoped_refptr<X509Certificate> cert(
ImportCertFromFile(GetTestCertsDirectory(), "wildcard.pem"));
@@ -181,7 +180,7 @@ void QuicStreamFactoryPeer::CacheDummyServerConfig(
QuicCryptoClientConfig* crypto_config = &factory->crypto_config_;
QuicCryptoClientConfig::CachedState* cached =
crypto_config->LookupOrCreate(quic_server_id);
- QuicClock clock;
+ QuicChromiumClock clock;
cached->Initialize(server_config, source_address_token, certs, "", "",
signature, clock.WallNow(), QuicWallTime::Zero());
DCHECK(!cached->certs().empty());
diff --git a/chromium/net/quic/test_tools/quic_stream_factory_peer.h b/chromium/net/quic/test_tools/quic_stream_factory_peer.h
index 38916b11aaf..eeb1dc0907f 100644
--- a/chromium/net/quic/test_tools/quic_stream_factory_peer.h
+++ b/chromium/net/quic/test_tools/quic_stream_factory_peer.h
@@ -12,7 +12,7 @@
#include "base/task_runner.h"
#include "net/base/host_port_pair.h"
#include "net/base/privacy_mode.h"
-#include "net/quic/core/quic_protocol.h"
+#include "net/quic/core/quic_packets.h"
#include "net/quic/core/quic_server_id.h"
#include "net/quic/core/quic_time.h"
diff --git a/chromium/net/quic/test_tools/quic_stream_peer.cc b/chromium/net/quic/test_tools/quic_stream_peer.cc
index 6b65a87389c..b35ec1a1273 100644
--- a/chromium/net/quic/test_tools/quic_stream_peer.cc
+++ b/chromium/net/quic/test_tools/quic_stream_peer.cc
@@ -88,8 +88,8 @@ void QuicStreamPeer::WriteOrBufferData(
QuicStream* stream,
StringPiece data,
bool fin,
- QuicAckListenerInterface* ack_notifier_delegate) {
- stream->WriteOrBufferData(data, fin, ack_notifier_delegate);
+ QuicReferenceCountedPointer<QuicAckListenerInterface> ack_listener) {
+ stream->WriteOrBufferData(data, fin, std::move(ack_listener));
}
// static
diff --git a/chromium/net/quic/test_tools/quic_stream_peer.h b/chromium/net/quic/test_tools/quic_stream_peer.h
index e39ac4bca03..3d9b4f439e0 100644
--- a/chromium/net/quic/test_tools/quic_stream_peer.h
+++ b/chromium/net/quic/test_tools/quic_stream_peer.h
@@ -9,7 +9,7 @@
#include "base/macros.h"
#include "base/strings/string_piece.h"
-#include "net/quic/core/quic_protocol.h"
+#include "net/quic/core/quic_packets.h"
#include "net/quic/core/quic_stream_sequencer.h"
namespace net {
@@ -42,7 +42,7 @@ class QuicStreamPeer {
QuicStream* stream,
base::StringPiece data,
bool fin,
- QuicAckListenerInterface* ack_notifier_delegate);
+ QuicReferenceCountedPointer<QuicAckListenerInterface> ack_listener);
static net::QuicStreamSequencer* sequencer(QuicStream* stream);
diff --git a/chromium/net/quic/test_tools/quic_stream_sequencer_buffer_peer.cc b/chromium/net/quic/test_tools/quic_stream_sequencer_buffer_peer.cc
index a493ed8f6f0..e7f38b20689 100644
--- a/chromium/net/quic/test_tools/quic_stream_sequencer_buffer_peer.cc
+++ b/chromium/net/quic/test_tools/quic_stream_sequencer_buffer_peer.cc
@@ -5,6 +5,7 @@
#include "net/quic/test_tools/quic_stream_sequencer_buffer_peer.h"
#include "net/quic/core/quic_flags.h"
+#include "net/quic/platform/api/quic_logging.h"
#include "net/test/gtest_util.h"
typedef net::QuicStreamSequencerBuffer::BufferBlock BufferBlock;
@@ -41,7 +42,8 @@ bool QuicStreamSequencerBufferPeer::CheckEmptyInvariants() {
}
bool QuicStreamSequencerBufferPeer::IsBlockArrayEmpty() {
- if (buffer_->blocks_ == nullptr) {
+ if (FLAGS_quic_reloadable_flag_quic_reduce_sequencer_buffer_memory_life_time && // NOLINT
+ buffer_->blocks_ == nullptr) {
return true;
}
@@ -66,29 +68,29 @@ bool QuicStreamSequencerBufferPeer::CheckBufferInvariants() {
bool capacity_sane = data_span <= buffer_->max_buffer_capacity_bytes_ &&
data_span >= buffer_->num_bytes_buffered_;
if (!capacity_sane) {
- LOG(ERROR) << "data span is larger than capacity.";
- LOG(ERROR) << "total read: " << buffer_->total_bytes_read_
- << " last byte: " << buffer_->gaps_.back().begin_offset;
+ QUIC_LOG(ERROR) << "data span is larger than capacity.";
+ QUIC_LOG(ERROR) << "total read: " << buffer_->total_bytes_read_
+ << " last byte: " << buffer_->gaps_.back().begin_offset;
}
bool total_read_sane =
buffer_->gaps_.front().begin_offset >= buffer_->total_bytes_read_;
if (!total_read_sane) {
- LOG(ERROR) << "read across 1st gap.";
+ QUIC_LOG(ERROR) << "read across 1st gap.";
}
bool read_offset_sane = buffer_->ReadOffset() < kBlockSizeBytes;
if (!capacity_sane) {
- LOG(ERROR) << "read offset go beyond 1st block";
+ QUIC_LOG(ERROR) << "read offset go beyond 1st block";
}
bool block_match_capacity = (buffer_->max_buffer_capacity_bytes_ <=
buffer_->blocks_count_ * kBlockSizeBytes) &&
(buffer_->max_buffer_capacity_bytes_ >
(buffer_->blocks_count_ - 1) * kBlockSizeBytes);
if (!capacity_sane) {
- LOG(ERROR) << "block number not match capcaity.";
+ QUIC_LOG(ERROR) << "block number not match capcaity.";
}
bool block_retired_when_empty = CheckEmptyInvariants();
if (!block_retired_when_empty) {
- LOG(ERROR) << "block is not retired after use.";
+ QUIC_LOG(ERROR) << "block is not retired after use.";
}
return capacity_sane && total_read_sane && read_offset_sane &&
block_match_capacity && block_retired_when_empty;
diff --git a/chromium/net/quic/test_tools/quic_stream_sequencer_peer.cc b/chromium/net/quic/test_tools/quic_stream_sequencer_peer.cc
index d78543b0465..29c8741afa3 100644
--- a/chromium/net/quic/test_tools/quic_stream_sequencer_peer.cc
+++ b/chromium/net/quic/test_tools/quic_stream_sequencer_peer.cc
@@ -7,7 +7,6 @@
#include "net/quic/core/quic_stream_sequencer.h"
#include "net/quic/test_tools/quic_stream_sequencer_buffer_peer.h"
-using std::map;
using std::string;
namespace net {
diff --git a/chromium/net/quic/test_tools/quic_stream_sequencer_peer.h b/chromium/net/quic/test_tools/quic_stream_sequencer_peer.h
index aa8773cb8b5..cc63e71155c 100644
--- a/chromium/net/quic/test_tools/quic_stream_sequencer_peer.h
+++ b/chromium/net/quic/test_tools/quic_stream_sequencer_peer.h
@@ -8,7 +8,7 @@
#include <stddef.h>
#include "base/macros.h"
-#include "net/quic/core/quic_protocol.h"
+#include "net/quic/core/quic_packets.h"
namespace net {
diff --git a/chromium/net/quic/test_tools/quic_sustained_bandwidth_recorder_peer.cc b/chromium/net/quic/test_tools/quic_sustained_bandwidth_recorder_peer.cc
index 6a70fa9310a..ad64391007b 100644
--- a/chromium/net/quic/test_tools/quic_sustained_bandwidth_recorder_peer.cc
+++ b/chromium/net/quic/test_tools/quic_sustained_bandwidth_recorder_peer.cc
@@ -4,7 +4,7 @@
#include "net/quic/test_tools/quic_sustained_bandwidth_recorder_peer.h"
-#include "net/quic/core/quic_protocol.h"
+#include "net/quic/core/quic_packets.h"
#include "net/quic/core/quic_sustained_bandwidth_recorder.h"
namespace net {
diff --git a/chromium/net/quic/test_tools/quic_sustained_bandwidth_recorder_peer.h b/chromium/net/quic/test_tools/quic_sustained_bandwidth_recorder_peer.h
index 4a0669a6405..5dbb4e383ed 100644
--- a/chromium/net/quic/test_tools/quic_sustained_bandwidth_recorder_peer.h
+++ b/chromium/net/quic/test_tools/quic_sustained_bandwidth_recorder_peer.h
@@ -8,7 +8,7 @@
#include <stdint.h>
#include "base/macros.h"
-#include "net/quic/core/quic_protocol.h"
+#include "net/quic/core/quic_packets.h"
namespace net {
diff --git a/chromium/net/quic/test_tools/quic_test_utils.cc b/chromium/net/quic/test_tools/quic_test_utils.cc
index c97fe1f7696..eb070011e63 100644
--- a/chromium/net/quic/test_tools/quic_test_utils.cc
+++ b/chromium/net/quic/test_tools/quic_test_utils.cc
@@ -6,9 +6,6 @@
#include <memory>
-#include "base/memory/ptr_util.h"
-#include "base/sha1.h"
-#include "base/strings/string_number_conversions.h"
#include "net/quic/core/crypto/crypto_framer.h"
#include "net/quic/core/crypto/crypto_handshake.h"
#include "net/quic/core/crypto/crypto_utils.h"
@@ -19,14 +16,15 @@
#include "net/quic/core/quic_framer.h"
#include "net/quic/core/quic_packet_creator.h"
#include "net/quic/core/quic_utils.h"
+#include "net/quic/platform/api/quic_logging.h"
+#include "net/quic/platform/api/quic_ptr_util.h"
#include "net/quic/test_tools/crypto_test_utils.h"
#include "net/quic/test_tools/quic_connection_peer.h"
#include "net/spdy/spdy_frame_builder.h"
#include "net/tools/quic/quic_per_connection_packet_writer.h"
+#include "third_party/boringssl/src/include/openssl/sha.h"
using base::StringPiece;
-using std::max;
-using std::min;
using std::string;
using testing::Invoke;
using testing::_;
@@ -38,24 +36,12 @@ namespace test {
QuicAckFrame MakeAckFrame(QuicPacketNumber largest_observed) {
QuicAckFrame ack;
ack.largest_observed = largest_observed;
- ack.entropy_hash = 0;
- return ack;
-}
-
-QuicAckFrame MakeAckFrameWithNackRanges(size_t num_nack_ranges,
- QuicPacketNumber least_unacked) {
- QuicAckFrame ack = MakeAckFrame(2 * num_nack_ranges + least_unacked);
- // Add enough missing packets to get num_nack_ranges nack ranges.
- for (QuicPacketNumber i = 1; i < 2 * num_nack_ranges; i += 2) {
- ack.packets.Add(least_unacked + i);
- }
return ack;
}
QuicAckFrame MakeAckFrameWithAckBlocks(size_t num_ack_blocks,
QuicPacketNumber least_unacked) {
QuicAckFrame ack = MakeAckFrame(2 * num_ack_blocks + least_unacked);
- ack.missing = false;
// Add enough received packets to get num_ack_blocks ack blocks.
for (QuicPacketNumber i = 2; i < 2 * num_ack_blocks + 1; i += 2) {
ack.packets.Add(least_unacked + i);
@@ -98,25 +84,32 @@ QuicPacket* BuildUnsizedDataPacket(QuicFramer* framer,
}
QuicFlagSaver::QuicFlagSaver() {
-#define QUIC_FLAG(type, flag, value) \
- CHECK_EQ(value, flag) << "Flag set to an expected value. A prior test is " \
- "likely setting a flag " \
- << "without using a QuicFlagSaver";
+#define QUIC_FLAG(type, flag, value) \
+ CHECK_EQ(value, base::GetFlag(flag)) \
+ << "Flag set to an unexpected value. A prior test is likely " \
+ << "setting a flag without using a QuicFlagSaver";
#include "net/quic/core/quic_flags_list.h"
#undef QUIC_FLAG
}
QuicFlagSaver::~QuicFlagSaver() {
-#define QUIC_FLAG(type, flag, value) flag = value;
+#define QUIC_FLAG(type, flag, value) base::SetFlag(&flag, value);
#include "net/quic/core/quic_flags_list.h"
#undef QUIC_FLAG
}
+string Sha1Hash(StringPiece data) {
+ char buffer[SHA_DIGEST_LENGTH];
+ SHA1(reinterpret_cast<const uint8_t*>(data.data()), data.size(),
+ reinterpret_cast<uint8_t*>(buffer));
+ return string(buffer, arraysize(buffer));
+}
+
uint64_t SimpleRandom::RandUint64() {
- unsigned char hash[base::kSHA1Length];
- base::SHA1HashBytes(reinterpret_cast<unsigned char*>(&seed_), sizeof(seed_),
- hash);
- memcpy(&seed_, hash, sizeof(seed_));
+ string hash =
+ Sha1Hash(StringPiece(reinterpret_cast<char*>(&seed_), sizeof(seed_)));
+ DCHECK_EQ(static_cast<size_t>(SHA_DIGEST_LENGTH), hash.length());
+ memcpy(&seed_, hash.data(), sizeof(seed_));
return seed_;
}
@@ -278,13 +271,13 @@ MockQuicConnection::MockQuicConnection(MockQuicConnectionHelper* helper,
MockAlarmFactory* alarm_factory,
Perspective perspective)
: MockQuicConnection(kTestConnectionId,
- IPEndPoint(TestPeerIPAddress(), kTestPort),
+ QuicSocketAddress(TestPeerIPAddress(), kTestPort),
helper,
alarm_factory,
perspective,
AllSupportedVersions()) {}
-MockQuicConnection::MockQuicConnection(IPEndPoint address,
+MockQuicConnection::MockQuicConnection(QuicSocketAddress address,
MockQuicConnectionHelper* helper,
MockAlarmFactory* alarm_factory,
Perspective perspective)
@@ -300,7 +293,7 @@ MockQuicConnection::MockQuicConnection(QuicConnectionId connection_id,
MockAlarmFactory* alarm_factory,
Perspective perspective)
: MockQuicConnection(connection_id,
- IPEndPoint(TestPeerIPAddress(), kTestPort),
+ QuicSocketAddress(TestPeerIPAddress(), kTestPort),
helper,
alarm_factory,
perspective,
@@ -312,7 +305,7 @@ MockQuicConnection::MockQuicConnection(
Perspective perspective,
const QuicVersionVector& supported_versions)
: MockQuicConnection(kTestConnectionId,
- IPEndPoint(TestPeerIPAddress(), kTestPort),
+ QuicSocketAddress(TestPeerIPAddress(), kTestPort),
helper,
alarm_factory,
perspective,
@@ -320,7 +313,7 @@ MockQuicConnection::MockQuicConnection(
MockQuicConnection::MockQuicConnection(
QuicConnectionId connection_id,
- IPEndPoint address,
+ QuicSocketAddress address,
MockQuicConnectionHelper* helper,
MockAlarmFactory* alarm_factory,
Perspective perspective,
@@ -362,13 +355,13 @@ PacketSavingConnection::PacketSavingConnection(
PacketSavingConnection::~PacketSavingConnection() {}
void PacketSavingConnection::SendOrQueuePacket(SerializedPacket* packet) {
- encrypted_packets_.push_back(base::MakeUnique<QuicEncryptedPacket>(
- QuicUtils::CopyBuffer(*packet), packet->encrypted_length, true));
+ encrypted_packets_.push_back(QuicMakeUnique<QuicEncryptedPacket>(
+ CopyBuffer(*packet), packet->encrypted_length, true));
// Transfer ownership of the packet to the SentPacketManager and the
// ack notifier to the AckNotifierManager.
- sent_packet_manager_->OnPacketSent(packet, kInvalidPathId, 0,
- QuicTime::Zero(), NOT_RETRANSMISSION,
- HAS_RETRANSMITTABLE_DATA);
+ sent_packet_manager_.OnPacketSent(packet, 0, QuicTime::Zero(),
+ NOT_RETRANSMISSION,
+ HAS_RETRANSMITTABLE_DATA);
}
MockQuicSession::MockQuicSession(QuicConnection* connection)
@@ -390,7 +383,8 @@ QuicConsumedData MockQuicSession::ConsumeAllData(
const QuicIOVector& data,
QuicStreamOffset /*offset*/,
bool fin,
- QuicAckListenerInterface* /*ack_notifier_delegate*/) {
+ const QuicReferenceCountedPointer<
+ QuicAckListenerInterface>& /*ack_listener*/) {
return QuicConsumedData(data.total_length, fin);
}
@@ -433,9 +427,10 @@ QuicCryptoServerStreamBase*
TestQuicSpdyServerSession::CreateQuicCryptoServerStream(
const QuicCryptoServerConfig* crypto_config,
QuicCompressedCertsCache* compressed_certs_cache) {
- return new QuicCryptoServerStream(crypto_config, compressed_certs_cache,
- FLAGS_enable_quic_stateless_reject_support,
- this, &helper_);
+ return new QuicCryptoServerStream(
+ crypto_config, compressed_certs_cache,
+ FLAGS_quic_reloadable_flag_enable_quic_stateless_reject_support, this,
+ &helper_);
}
QuicCryptoServerStream* TestQuicSpdyServerSession::GetCryptoStream() {
@@ -450,7 +445,7 @@ bool TestPushPromiseDelegate::CheckVary(
const SpdyHeaderBlock& client_request,
const SpdyHeaderBlock& promise_request,
const SpdyHeaderBlock& promise_response) {
- DVLOG(1) << "match " << match_;
+ QUIC_DVLOG(1) << "match " << match_;
return match_;
}
@@ -515,9 +510,9 @@ string HexDumpWithMarks(const char* data,
const int kSizeLimit = 1024;
if (length > kSizeLimit || mark_length > kSizeLimit) {
- LOG(ERROR) << "Only dumping first " << kSizeLimit << " bytes.";
- length = min(length, kSizeLimit);
- mark_length = min(mark_length, kSizeLimit);
+ QUIC_LOG(ERROR) << "Only dumping first " << kSizeLimit << " bytes.";
+ length = std::min(length, kSizeLimit);
+ mark_length = std::min(mark_length, kSizeLimit);
}
string hex;
@@ -548,8 +543,8 @@ string HexDumpWithMarks(const char* data,
} // namespace
-IPAddress TestPeerIPAddress() {
- return Loopback4();
+QuicIpAddress TestPeerIPAddress() {
+ return QuicIpAddress::Loopback4();
}
QuicVersion QuicVersionMax() {
@@ -572,14 +567,6 @@ IPAddress Any4() {
return IPAddress::IPv4AllZeros();
}
-void GenerateBody(string* body, int length) {
- body->clear();
- body->reserve(length);
- for (int i = 0; i < length; ++i) {
- body->append(1, static_cast<char>(32 + i % (126 - 32)));
- }
-}
-
QuicEncryptedPacket* ConstructEncryptedPacket(QuicConnectionId connection_id,
bool version_flag,
bool multipath_flag,
@@ -645,8 +632,6 @@ QuicEncryptedPacket* ConstructEncryptedPacket(
header.public_header.packet_number_length = packet_number_length;
header.path_id = path_id;
header.packet_number = packet_number;
- header.entropy_flag = false;
- header.entropy_hash = 0;
QuicStreamFrame stream_frame(1, false, 0, StringPiece(data));
QuicFrame frame(&stream_frame);
QuicFrames frames;
@@ -695,8 +680,6 @@ QuicEncryptedPacket* ConstructMisFramedEncryptedPacket(
header.public_header.packet_number_length = packet_number_length;
header.path_id = path_id;
header.packet_number = packet_number;
- header.entropy_flag = false;
- header.entropy_hash = 0;
QuicStreamFrame stream_frame(1, false, 0, StringPiece(data));
QuicFrame frame(&stream_frame);
QuicFrames frames;
@@ -708,20 +691,11 @@ QuicEncryptedPacket* ConstructMisFramedEncryptedPacket(
BuildUnsizedDataPacket(&framer, header, frames));
EXPECT_TRUE(packet != nullptr);
- if (framer.version() <= QUIC_VERSION_33) {
- // Now set the packet's private flags byte to 0xFF, which is an invalid
- // value.
- reinterpret_cast<unsigned char*>(
- packet->mutable_data())[GetStartOfEncryptedData(
- framer.version(), connection_id_length, version_flag, multipath_flag,
- false /* no diversification nonce */, packet_number_length)] = 0xFF;
- } else {
- // Now set the frame type to 0x1F, which is an invalid frame type.
- reinterpret_cast<unsigned char*>(
- packet->mutable_data())[GetStartOfEncryptedData(
- framer.version(), connection_id_length, version_flag, multipath_flag,
- false /* no diversification nonce */, packet_number_length)] = 0x1F;
- }
+ // Now set the frame type to 0x1F, which is an invalid frame type.
+ reinterpret_cast<unsigned char*>(
+ packet->mutable_data())[GetStartOfEncryptedData(
+ framer.version(), connection_id_length, version_flag, multipath_flag,
+ false /* no diversification nonce */, packet_number_length)] = 0x1F;
char* buffer = new char[kMaxPacketSize];
size_t encrypted_length = framer.EncryptPayload(
@@ -736,8 +710,8 @@ void CompareCharArraysWithHexError(const string& description,
const char* expected,
const int expected_len) {
EXPECT_EQ(actual_len, expected_len);
- const int min_len = min(actual_len, expected_len);
- const int max_len = max(actual_len, expected_len);
+ const int min_len = std::min(actual_len, expected_len);
+ const int max_len = std::max(actual_len, expected_len);
std::unique_ptr<bool[]> marks(new bool[max_len]);
bool identical = (actual_len == expected_len);
for (int i = 0; i < min_len; ++i) {
@@ -761,18 +735,6 @@ void CompareCharArraysWithHexError(const string& description,
<< HexDumpWithMarks(actual, actual_len, marks.get(), max_len);
}
-bool DecodeHexString(const base::StringPiece& hex, std::string* bytes) {
- bytes->clear();
- if (hex.empty())
- return true;
- std::vector<uint8_t> v;
- if (!base::HexStringToBytes(hex.as_string(), &v))
- return false;
- if (!v.empty())
- bytes->assign(reinterpret_cast<const char*>(&v[0]), v.size());
- return true;
-}
-
static QuicPacket* ConstructPacketFromHandshakeMessage(
QuicConnectionId connection_id,
const CryptoHandshakeMessage& message,
@@ -788,8 +750,6 @@ static QuicPacket* ConstructPacketFromHandshakeMessage(
header.public_header.reset_flag = false;
header.public_header.version_flag = should_include_version;
header.packet_number = 1;
- header.entropy_flag = false;
- header.entropy_hash = 0;
QuicStreamFrame stream_frame(kCryptoStreamId, false, 0,
data->AsStringPiece());
@@ -816,13 +776,14 @@ size_t GetPacketLengthForOneStream(QuicVersion version,
size_t* payload_length) {
*payload_length = 1;
const size_t stream_length =
- NullEncrypter().GetCiphertextSize(*payload_length) +
+ NullEncrypter(Perspective::IS_CLIENT).GetCiphertextSize(*payload_length) +
QuicPacketCreator::StreamFramePacketOverhead(
version, PACKET_8BYTE_CONNECTION_ID, include_version, include_path_id,
include_diversification_nonce, packet_number_length, 0u);
const size_t ack_length =
- NullEncrypter().GetCiphertextSize(
- QuicFramer::GetMinAckFrameSize(version, PACKET_1BYTE_PACKET_NUMBER)) +
+ NullEncrypter(Perspective::IS_CLIENT)
+ .GetCiphertextSize(QuicFramer::GetMinAckFrameSize(
+ version, PACKET_1BYTE_PACKET_NUMBER)) +
GetPacketHeaderSize(version, connection_id_length, include_version,
include_path_id, include_diversification_nonce,
packet_number_length);
@@ -830,25 +791,13 @@ size_t GetPacketLengthForOneStream(QuicVersion version,
*payload_length = 1 + ack_length - stream_length;
}
- return NullEncrypter().GetCiphertextSize(*payload_length) +
+ return NullEncrypter(Perspective::IS_CLIENT)
+ .GetCiphertextSize(*payload_length) +
QuicPacketCreator::StreamFramePacketOverhead(
version, connection_id_length, include_version, include_path_id,
include_diversification_nonce, packet_number_length, 0u);
}
-TestEntropyCalculator::TestEntropyCalculator() {}
-
-TestEntropyCalculator::~TestEntropyCalculator() {}
-
-QuicPacketEntropyHash TestEntropyCalculator::EntropyHash(
- QuicPacketNumber packet_number) const {
- return 1u;
-}
-
-MockEntropyCalculator::MockEntropyCalculator() {}
-
-MockEntropyCalculator::~MockEntropyCalculator() {}
-
QuicConfig DefaultQuicConfig() {
QuicConfig config;
config.SetInitialStreamFlowControlWindowToSend(
@@ -881,10 +830,6 @@ MockReceivedPacketManager::MockReceivedPacketManager(QuicConnectionStats* stats)
MockReceivedPacketManager::~MockReceivedPacketManager() {}
-MockSentPacketManager::MockSentPacketManager() {}
-
-MockSentPacketManager::~MockSentPacketManager() {}
-
MockConnectionCloseDelegate::MockConnectionCloseDelegate() {}
MockConnectionCloseDelegate::~MockConnectionCloseDelegate() {}
diff --git a/chromium/net/quic/test_tools/quic_test_utils.h b/chromium/net/quic/test_tools/quic_test_utils.h
index f0773530f92..2f01fc0a821 100644
--- a/chromium/net/quic/test_tools/quic_test_utils.h
+++ b/chromium/net/quic/test_tools/quic_test_utils.h
@@ -23,15 +23,18 @@
#include "net/quic/core/congestion_control/send_algorithm_interface.h"
#include "net/quic/core/quic_client_push_promise_index.h"
#include "net/quic/core/quic_connection.h"
+#include "net/quic/core/quic_connection_close_delegate_interface.h"
#include "net/quic/core/quic_framer.h"
-#include "net/quic/core/quic_protocol.h"
-#include "net/quic/core/quic_sent_packet_manager_interface.h"
+#include "net/quic/core/quic_iovector.h"
+#include "net/quic/core/quic_packets.h"
+#include "net/quic/core/quic_sent_packet_manager.h"
#include "net/quic/core/quic_server_session_base.h"
#include "net/quic/core/quic_session.h"
#include "net/quic/core/quic_simple_buffer_allocator.h"
#include "net/quic/test_tools/mock_clock.h"
#include "net/quic/test_tools/mock_random.h"
#include "net/spdy/spdy_framer.h"
+#include "net/test/gtest_util.h"
#include "net/tools/quic/quic_dispatcher.h"
#include "net/tools/quic/quic_per_connection_packet_writer.h"
#include "net/tools/quic/test_tools/mock_quic_server_session_visitor.h"
@@ -62,7 +65,7 @@ static const QuicStreamId kClientDataStreamId3 = 9;
static const QuicStreamId kServerDataStreamId1 = 4;
// Returns the test peer IP address.
-IPAddress TestPeerIPAddress();
+QuicIpAddress TestPeerIPAddress();
// Upper limit on versions we support.
QuicVersion QuicVersionMax();
@@ -79,8 +82,6 @@ IPAddress Loopback6();
// Returns an address for 0.0.0.0.
IPAddress Any4();
-void GenerateBody(std::string* body, int length);
-
// Create an encrypted packet for testing.
// If versions == nullptr, uses &AllSupportedVersions().
// Note that the packet is encrypted with NullEncrypter, so to decrypt the
@@ -167,8 +168,6 @@ void CompareCharArraysWithHexError(const std::string& description,
const char* expected,
const int expected_len);
-bool DecodeHexString(const StringPiece& hex, std::string* bytes);
-
// Returns the length of a QuicPacket that is capable of holding either a
// stream frame or a minimal ack frame. Sets |*payload_length| to the number
// of bytes of stream data that will fit in such a packet.
@@ -189,15 +188,10 @@ QuicConfig DefaultQuicConfigStatelessRejects();
// Returns a version vector consisting of |version|.
QuicVersionVector SupportedVersions(QuicVersion version);
-// Testing convenience method to construct a QuicAckFrame with entropy_hash set
-// to 0 and largest_observed from peer set to |largest_observed|.
+// Testing convenience method to construct a QuicAckFrame with largest_observed
+// from peer set to |largest_observed|.
QuicAckFrame MakeAckFrame(QuicPacketNumber largest_observed);
-// Testing convenience method to construct a QuicAckFrame with |num_nack_ranges|
-// nack ranges of width 1 packet, starting from |least_unacked|.
-QuicAckFrame MakeAckFrameWithNackRanges(size_t num_nack_ranges,
- QuicPacketNumber least_unacked);
-
// Testing convenience method to construct a QuicAckFrame with |num_ack_blocks|
// ack blocks of width 1 packet, starting from |least_unacked| + 2.
QuicAckFrame MakeAckFrameWithAckBlocks(size_t num_ack_blocks,
@@ -223,6 +217,9 @@ class QuicFlagSaver {
~QuicFlagSaver();
};
+// Compute SHA-1 hash of the supplied std::string.
+std::string Sha1Hash(base::StringPiece data);
+
// Simple random number generator used to compute random numbers suitable
// for pseudo-randomly dropping packets in tests. It works by computing
// the sha1 hash of the current seed, and using the first 64 bits as
@@ -395,7 +392,7 @@ class MockQuicConnection : public QuicConnection {
Perspective perspective);
// Uses a ConnectionId of 42.
- MockQuicConnection(IPEndPoint address,
+ MockQuicConnection(QuicSocketAddress address,
MockQuicConnectionHelper* helper,
MockAlarmFactory* alarm_factory,
Perspective perspective);
@@ -413,7 +410,7 @@ class MockQuicConnection : public QuicConnection {
const QuicVersionVector& supported_versions);
MockQuicConnection(QuicConnectionId connection_id,
- IPEndPoint address,
+ QuicSocketAddress address,
MockQuicConnectionHelper* helper,
MockAlarmFactory* alarm_factory,
Perspective perspective,
@@ -427,8 +424,8 @@ class MockQuicConnection : public QuicConnection {
void AdvanceTime(QuicTime::Delta delta);
MOCK_METHOD3(ProcessUdpPacket,
- void(const IPEndPoint& self_address,
- const IPEndPoint& peer_address,
+ void(const QuicSocketAddress& self_address,
+ const QuicSocketAddress& peer_address,
const QuicReceivedPacket& packet));
MOCK_METHOD1(SendConnectionClose, void(QuicErrorCode error));
MOCK_METHOD3(CloseConnection,
@@ -462,8 +459,8 @@ class MockQuicConnection : public QuicConnection {
QuicConnection::OnError(framer);
}
- void ReallyProcessUdpPacket(const IPEndPoint& self_address,
- const IPEndPoint& peer_address,
+ void ReallyProcessUdpPacket(const QuicSocketAddress& self_address,
+ const QuicSocketAddress& peer_address,
const QuicReceivedPacket& packet) {
QuicConnection::ProcessUdpPacket(self_address, peer_address, packet);
}
@@ -517,13 +514,14 @@ class MockQuicSession : public QuicSession {
MOCK_METHOD1(CreateOutgoingDynamicStream, QuicStream*(SpdyPriority priority));
MOCK_METHOD1(ShouldCreateIncomingDynamicStream, bool(QuicStreamId id));
MOCK_METHOD0(ShouldCreateOutgoingDynamicStream, bool());
- MOCK_METHOD6(WritevData,
- QuicConsumedData(QuicStream* stream,
- QuicStreamId id,
- QuicIOVector data,
- QuicStreamOffset offset,
- bool fin,
- QuicAckListenerInterface*));
+ MOCK_METHOD6(
+ WritevData,
+ QuicConsumedData(QuicStream* stream,
+ QuicStreamId id,
+ QuicIOVector data,
+ QuicStreamOffset offset,
+ bool fin,
+ QuicReferenceCountedPointer<QuicAckListenerInterface>));
MOCK_METHOD3(SendRstStream,
void(QuicStreamId stream_id,
@@ -548,7 +546,8 @@ class MockQuicSession : public QuicSession {
const QuicIOVector& data,
QuicStreamOffset offset,
bool fin,
- QuicAckListenerInterface* ack_notifier_delegate);
+ const QuicReferenceCountedPointer<QuicAckListenerInterface>&
+ ack_listener);
private:
std::unique_ptr<QuicCryptoStream> crypto_stream_;
@@ -575,13 +574,15 @@ class MockQuicSpdySession : public QuicSpdySession {
QuicSpdyStream*(SpdyPriority priority));
MOCK_METHOD1(ShouldCreateIncomingDynamicStream, bool(QuicStreamId id));
MOCK_METHOD0(ShouldCreateOutgoingDynamicStream, bool());
- MOCK_METHOD6(WritevData,
- QuicConsumedData(QuicStream* stream,
- QuicStreamId id,
- QuicIOVector data,
- QuicStreamOffset offset,
- bool fin,
- QuicAckListenerInterface*));
+ MOCK_METHOD6(
+ WritevData,
+ QuicConsumedData(
+ QuicStream* stream,
+ QuicStreamId id,
+ QuicIOVector data,
+ QuicStreamOffset offset,
+ bool fin,
+ QuicReferenceCountedPointer<QuicAckListenerInterface> ack_listener));
MOCK_METHOD3(SendRstStream,
void(QuicStreamId stream_id,
@@ -613,22 +614,23 @@ class MockQuicSpdySession : public QuicSpdySession {
const QuicHeaderList& header_list));
// Methods taking non-copyable types like SpdyHeaderBlock by value cannot be
// mocked directly.
- size_t WriteHeaders(
- QuicStreamId id,
- SpdyHeaderBlock headers,
- bool fin,
- SpdyPriority priority,
- QuicAckListenerInterface* ack_notifier_delegate) override {
- write_headers_ = std::move(headers);
- return WriteHeadersMock(id, write_headers_, fin, priority,
- ack_notifier_delegate);
- }
- MOCK_METHOD5(WriteHeadersMock,
- size_t(QuicStreamId id,
- const SpdyHeaderBlock& headers,
+ size_t WriteHeaders(QuicStreamId id,
+ SpdyHeaderBlock headers,
bool fin,
SpdyPriority priority,
- QuicAckListenerInterface* ack_notifier_delegate));
+ QuicReferenceCountedPointer<QuicAckListenerInterface>
+ ack_listener) override {
+ write_headers_ = std::move(headers);
+ return WriteHeadersMock(id, write_headers_, fin, priority, ack_listener);
+ }
+ MOCK_METHOD5(
+ WriteHeadersMock,
+ size_t(QuicStreamId id,
+ const SpdyHeaderBlock& headers,
+ bool fin,
+ SpdyPriority priority,
+ const QuicReferenceCountedPointer<QuicAckListenerInterface>&
+ ack_listener));
MOCK_METHOD1(OnHeadersHeadOfLineBlocking, void(QuicTime::Delta delta));
MOCK_METHOD4(
OnStreamFrameData,
@@ -729,14 +731,14 @@ class MockPacketWriter : public QuicPacketWriter {
MOCK_METHOD5(WritePacket,
WriteResult(const char* buffer,
size_t buf_len,
- const IPAddress& self_address,
- const IPEndPoint& peer_address,
+ const QuicIpAddress& self_address,
+ const QuicSocketAddress& peer_address,
PerPacketOptions* options));
MOCK_CONST_METHOD0(IsWriteBlockedDataBuffered, bool());
MOCK_CONST_METHOD0(IsWriteBlocked, bool());
MOCK_METHOD0(SetWritable, void());
MOCK_CONST_METHOD1(GetMaxPacketSize,
- QuicByteCount(const IPEndPoint& peer_address));
+ QuicByteCount(const QuicSocketAddress& peer_address));
private:
DISALLOW_COPY_AND_ASSIGN(MockPacketWriter);
@@ -811,31 +813,6 @@ class MockLossAlgorithm : public LossDetectionInterface {
DISALLOW_COPY_AND_ASSIGN(MockLossAlgorithm);
};
-class TestEntropyCalculator
- : public QuicReceivedEntropyHashCalculatorInterface {
- public:
- TestEntropyCalculator();
- ~TestEntropyCalculator() override;
-
- QuicPacketEntropyHash EntropyHash(
- QuicPacketNumber packet_number) const override;
-
- private:
- DISALLOW_COPY_AND_ASSIGN(TestEntropyCalculator);
-};
-
-class MockEntropyCalculator : public TestEntropyCalculator {
- public:
- MockEntropyCalculator();
- ~MockEntropyCalculator() override;
-
- MOCK_CONST_METHOD1(EntropyHash,
- QuicPacketEntropyHash(QuicPacketNumber packet_number));
-
- private:
- DISALLOW_COPY_AND_ASSIGN(MockEntropyCalculator);
-};
-
class MockAckListener : public QuicAckListenerInterface {
public:
MockAckListener();
@@ -854,7 +831,7 @@ class MockAckListener : public QuicAckListenerInterface {
};
class MockNetworkChangeVisitor
- : public QuicSentPacketManagerInterface::NetworkChangeVisitor {
+ : public QuicSentPacketManager::NetworkChangeVisitor {
public:
MockNetworkChangeVisitor();
~MockNetworkChangeVisitor() override;
@@ -884,8 +861,8 @@ class MockQuicConnectionDebugVisitor : public QuicConnectionDebugVisitor {
MOCK_METHOD0(OnPingSent, void());
MOCK_METHOD3(OnPacketReceived,
- void(const IPEndPoint&,
- const IPEndPoint&,
+ void(const QuicSocketAddress&,
+ const QuicSocketAddress&,
const QuicEncryptedPacket&));
MOCK_METHOD1(OnIncorrectConnectionId, void(QuicConnectionId));
@@ -927,59 +904,6 @@ class MockReceivedPacketManager : public QuicReceivedPacketManager {
MOCK_CONST_METHOD0(ack_frame_updated, bool(void));
};
-class MockSentPacketManager : public QuicSentPacketManagerInterface {
- public:
- MockSentPacketManager();
- ~MockSentPacketManager() override;
-
- MOCK_METHOD1(SetFromConfig, void(const QuicConfig&));
- MOCK_METHOD2(ResumeConnectionState,
- void(const CachedNetworkParameters&, bool));
- MOCK_METHOD1(SetNumOpenStreams, void(size_t));
- MOCK_METHOD1(SetMaxPacingRate, void(QuicBandwidth));
- MOCK_METHOD0(SetHandshakeConfirmed, void(void));
- MOCK_METHOD2(OnIncomingAck, void(const QuicAckFrame&, QuicTime));
- MOCK_METHOD1(RetransmitUnackedPackets, void(TransmissionType));
- MOCK_METHOD0(MaybeRetransmitTailLossProbe, bool(void));
- MOCK_METHOD0(NeuterUnencryptedPackets, void(void));
- MOCK_CONST_METHOD0(HasPendingRetransmissions, bool(void));
- MOCK_METHOD0(NextPendingRetransmission, PendingRetransmission(void));
- MOCK_CONST_METHOD0(HasUnackedPackets, bool(void));
- MOCK_CONST_METHOD1(GetLeastUnacked, QuicPacketNumber(QuicPathId));
- MOCK_METHOD6(OnPacketSent,
- bool(SerializedPacket*,
- QuicPathId,
- QuicPacketNumber,
- QuicTime,
- TransmissionType,
- HasRetransmittableData));
- MOCK_METHOD0(OnRetransmissionTimeout, void(void));
- MOCK_METHOD2(TimeUntilSend, QuicTime::Delta(QuicTime, QuicPathId*));
- MOCK_CONST_METHOD0(GetRetransmissionTime, const QuicTime(void));
- MOCK_CONST_METHOD0(GetRttStats, const RttStats*(void));
- MOCK_CONST_METHOD0(BandwidthEstimate, QuicBandwidth(void));
- MOCK_CONST_METHOD0(SustainedBandwidthRecorder,
- const QuicSustainedBandwidthRecorder*(void));
- MOCK_CONST_METHOD0(GetCongestionWindowInTcpMss, QuicPacketCount(void));
- MOCK_CONST_METHOD1(EstimateMaxPacketsInFlight,
- QuicPacketCount(QuicByteCount));
- MOCK_CONST_METHOD0(GetCongestionWindowInBytes, QuicByteCount(void));
- MOCK_CONST_METHOD0(GetSlowStartThresholdInTcpMss, QuicPacketCount(void));
- MOCK_CONST_METHOD0(GetDebugState, std::string());
- MOCK_METHOD1(CancelRetransmissionsForStream, void(QuicStreamId));
- MOCK_METHOD2(OnConnectionMigration, void(QuicPathId, PeerAddressChangeType));
- MOCK_CONST_METHOD0(IsHandshakeConfirmed, bool(void));
- MOCK_METHOD1(SetDebugDelegate, void(DebugDelegate*));
- MOCK_CONST_METHOD1(GetLargestObserved, QuicPacketNumber(QuicPathId));
- MOCK_CONST_METHOD1(GetLargestSentPacket, QuicPacketNumber(QuicPathId));
- MOCK_CONST_METHOD1(GetLeastPacketAwaitedByPeer, QuicPacketNumber(QuicPathId));
- MOCK_METHOD1(SetNetworkChangeVisitor, void(NetworkChangeVisitor*));
- MOCK_CONST_METHOD0(InSlowStart, bool(void));
- MOCK_CONST_METHOD0(GetConsecutiveRtoCount, size_t(void));
- MOCK_CONST_METHOD0(GetConsecutiveTlpCount, size_t(void));
- MOCK_METHOD0(OnApplicationLimited, void(void));
-};
-
class MockConnectionCloseDelegate
: public QuicConnectionCloseDelegateInterface {
public:
@@ -1077,6 +1001,15 @@ QuicHeaderList AsHeaderList(const T& container) {
return l;
}
+// Utility function that returns an QuicIOVector object wrapped around |str|.
+// // |str|'s data is stored in |iov|.
+inline QuicIOVector MakeIOVector(base::StringPiece str, struct iovec* iov) {
+ iov->iov_base = const_cast<char*>(str.data());
+ iov->iov_len = static_cast<size_t>(str.size());
+ QuicIOVector quic_iov(iov, 1, str.size());
+ return quic_iov;
+}
+
} // namespace test
} // namespace net
diff --git a/chromium/net/quic/test_tools/quic_test_utils_test.cc b/chromium/net/quic/test_tools/quic_test_utils_test.cc
index 6d4fb2766a6..d522c8f53e5 100644
--- a/chromium/net/quic/test_tools/quic_test_utils_test.cc
+++ b/chromium/net/quic/test_tools/quic_test_utils_test.cc
@@ -37,5 +37,13 @@ TEST(QuicTestUtilsTest, QuicBandwidth) {
"");
}
+// Ensure that SimpleRandom does not change its output for a fixed seed.
+TEST(QuicTestUtilsTest, SimpleRandomStability) {
+ SimpleRandom rng;
+ rng.set_seed(UINT64_C(0x1234567800010001));
+ EXPECT_EQ(UINT64_C(14865409841904857791), rng.RandUint64());
+ EXPECT_EQ(UINT64_C(12139094019410129741), rng.RandUint64());
+}
+
} // namespace test
} // namespace net
diff --git a/chromium/net/quic/test_tools/simple_quic_framer.cc b/chromium/net/quic/test_tools/simple_quic_framer.cc
index 6ffb1211ada..8ba739253fd 100644
--- a/chromium/net/quic/test_tools/simple_quic_framer.cc
+++ b/chromium/net/quic/test_tools/simple_quic_framer.cc
@@ -7,13 +7,12 @@
#include <memory>
#include "base/macros.h"
-#include "base/memory/ptr_util.h"
#include "net/quic/core/crypto/quic_decrypter.h"
#include "net/quic/core/crypto/quic_encrypter.h"
+#include "net/quic/platform/api/quic_ptr_util.h"
using base::StringPiece;
using std::string;
-using std::vector;
namespace net {
namespace test {
@@ -53,12 +52,10 @@ class SimpleFramerVisitor : public QuicFramerVisitorInterface {
bool OnStreamFrame(const QuicStreamFrame& frame) override {
// Save a copy of the data so it is valid after the packet is processed.
- string* string_data = new string();
- StringPiece(frame.data_buffer, frame.data_length)
- .AppendToString(string_data);
- stream_data_.push_back(base::WrapUnique(string_data));
+ string* string_data = new string(frame.data_buffer, frame.data_length);
+ stream_data_.push_back(QuicWrapUnique(string_data));
// TODO(ianswett): A pointer isn't necessary with emplace_back.
- stream_frames_.push_back(base::MakeUnique<QuicStreamFrame>(
+ stream_frames_.push_back(QuicMakeUnique<QuicStreamFrame>(
frame.stream_id, frame.fin, frame.offset, StringPiece(*string_data)));
return true;
}
@@ -116,23 +113,23 @@ class SimpleFramerVisitor : public QuicFramerVisitorInterface {
void OnPacketComplete() override {}
const QuicPacketHeader& header() const { return header_; }
- const vector<QuicAckFrame>& ack_frames() const { return ack_frames_; }
- const vector<QuicConnectionCloseFrame>& connection_close_frames() const {
+ const std::vector<QuicAckFrame>& ack_frames() const { return ack_frames_; }
+ const std::vector<QuicConnectionCloseFrame>& connection_close_frames() const {
return connection_close_frames_;
}
- const vector<QuicGoAwayFrame>& goaway_frames() const {
+ const std::vector<QuicGoAwayFrame>& goaway_frames() const {
return goaway_frames_;
}
- const vector<QuicRstStreamFrame>& rst_stream_frames() const {
+ const std::vector<QuicRstStreamFrame>& rst_stream_frames() const {
return rst_stream_frames_;
}
- const vector<std::unique_ptr<QuicStreamFrame>>& stream_frames() const {
+ const std::vector<std::unique_ptr<QuicStreamFrame>>& stream_frames() const {
return stream_frames_;
}
- const vector<QuicStopWaitingFrame>& stop_waiting_frames() const {
+ const std::vector<QuicStopWaitingFrame>& stop_waiting_frames() const {
return stop_waiting_frames_;
}
- const vector<QuicPingFrame>& ping_frames() const { return ping_frames_; }
+ const std::vector<QuicPingFrame>& ping_frames() const { return ping_frames_; }
const QuicVersionNegotiationPacket* version_negotiation_packet() const {
return version_negotiation_packet_.get();
}
@@ -143,18 +140,18 @@ class SimpleFramerVisitor : public QuicFramerVisitorInterface {
QuicPacketHeader header_;
std::unique_ptr<QuicVersionNegotiationPacket> version_negotiation_packet_;
std::unique_ptr<QuicPublicResetPacket> public_reset_packet_;
- vector<QuicAckFrame> ack_frames_;
- vector<QuicStopWaitingFrame> stop_waiting_frames_;
- vector<QuicPaddingFrame> padding_frames_;
- vector<QuicPingFrame> ping_frames_;
- vector<std::unique_ptr<QuicStreamFrame>> stream_frames_;
- vector<QuicRstStreamFrame> rst_stream_frames_;
- vector<QuicGoAwayFrame> goaway_frames_;
- vector<QuicConnectionCloseFrame> connection_close_frames_;
- vector<QuicWindowUpdateFrame> window_update_frames_;
- vector<QuicBlockedFrame> blocked_frames_;
- vector<QuicPathCloseFrame> path_close_frames_;
- vector<std::unique_ptr<string>> stream_data_;
+ std::vector<QuicAckFrame> ack_frames_;
+ std::vector<QuicStopWaitingFrame> stop_waiting_frames_;
+ std::vector<QuicPaddingFrame> padding_frames_;
+ std::vector<QuicPingFrame> ping_frames_;
+ std::vector<std::unique_ptr<QuicStreamFrame>> stream_frames_;
+ std::vector<QuicRstStreamFrame> rst_stream_frames_;
+ std::vector<QuicGoAwayFrame> goaway_frames_;
+ std::vector<QuicConnectionCloseFrame> connection_close_frames_;
+ std::vector<QuicWindowUpdateFrame> window_update_frames_;
+ std::vector<QuicBlockedFrame> blocked_frames_;
+ std::vector<QuicPathCloseFrame> path_close_frames_;
+ std::vector<std::unique_ptr<string>> stream_data_;
DISALLOW_COPY_AND_ASSIGN(SimpleFramerVisitor);
};
@@ -203,33 +200,34 @@ size_t SimpleQuicFramer::num_frames() const {
connection_close_frames().size();
}
-const vector<QuicAckFrame>& SimpleQuicFramer::ack_frames() const {
+const std::vector<QuicAckFrame>& SimpleQuicFramer::ack_frames() const {
return visitor_->ack_frames();
}
-const vector<QuicStopWaitingFrame>& SimpleQuicFramer::stop_waiting_frames()
+const std::vector<QuicStopWaitingFrame>& SimpleQuicFramer::stop_waiting_frames()
const {
return visitor_->stop_waiting_frames();
}
-const vector<QuicPingFrame>& SimpleQuicFramer::ping_frames() const {
+const std::vector<QuicPingFrame>& SimpleQuicFramer::ping_frames() const {
return visitor_->ping_frames();
}
-const vector<std::unique_ptr<QuicStreamFrame>>&
+const std::vector<std::unique_ptr<QuicStreamFrame>>&
SimpleQuicFramer::stream_frames() const {
return visitor_->stream_frames();
}
-const vector<QuicRstStreamFrame>& SimpleQuicFramer::rst_stream_frames() const {
+const std::vector<QuicRstStreamFrame>& SimpleQuicFramer::rst_stream_frames()
+ const {
return visitor_->rst_stream_frames();
}
-const vector<QuicGoAwayFrame>& SimpleQuicFramer::goaway_frames() const {
+const std::vector<QuicGoAwayFrame>& SimpleQuicFramer::goaway_frames() const {
return visitor_->goaway_frames();
}
-const vector<QuicConnectionCloseFrame>&
+const std::vector<QuicConnectionCloseFrame>&
SimpleQuicFramer::connection_close_frames() const {
return visitor_->connection_close_frames();
}
diff --git a/chromium/net/quic/test_tools/simple_quic_framer.h b/chromium/net/quic/test_tools/simple_quic_framer.h
index 4db6e3be283..d019f2903e6 100644
--- a/chromium/net/quic/test_tools/simple_quic_framer.h
+++ b/chromium/net/quic/test_tools/simple_quic_framer.h
@@ -13,15 +13,11 @@
#include "base/macros.h"
#include "base/strings/string_piece.h"
#include "net/quic/core/quic_framer.h"
-#include "net/quic/core/quic_protocol.h"
+#include "net/quic/core/quic_packets.h"
namespace net {
struct QuicAckFrame;
-class QuicConnection;
-class QuicConnectionVisitorInterface;
-class QuicPacketCreator;
-class SendAlgorithmInterface;
namespace test {
diff --git a/chromium/net/quic/test_tools/simulator/README.md b/chromium/net/quic/test_tools/simulator/README.md
index 02ffa0a1c37..b53470afce5 100644
--- a/chromium/net/quic/test_tools/simulator/README.md
+++ b/chromium/net/quic/test_tools/simulator/README.md
@@ -30,7 +30,7 @@ class LogClock : public Actor {
~LogClock() override {}
void Act() override {
- VLOG(1) << "The current time is " << clock_->Now().ToDebuggingValue();
+ QUIC_LOG(INFO) << "The current time is " << clock_->Now().ToDebuggingValue();
Schedule(clock_->Now() + QuicTime::Delta::FromMilliseconds(100));
}
};
diff --git a/chromium/net/quic/test_tools/simulator/actor.cc b/chromium/net/quic/test_tools/simulator/actor.cc
index 0fdf26fc99d..2aa8391a2ef 100644
--- a/chromium/net/quic/test_tools/simulator/actor.cc
+++ b/chromium/net/quic/test_tools/simulator/actor.cc
@@ -5,10 +5,12 @@
#include "net/quic/test_tools/simulator/actor.h"
#include "net/quic/test_tools/simulator/simulator.h"
+using std::string;
+
namespace net {
namespace simulator {
-Actor::Actor(Simulator* simulator, std::string name)
+Actor::Actor(Simulator* simulator, string name)
: simulator_(simulator),
clock_(simulator->GetClock()),
name_(std::move(name)) {
diff --git a/chromium/net/quic/test_tools/simulator/actor.h b/chromium/net/quic/test_tools/simulator/actor.h
index f74b712bb23..853b491db5c 100644
--- a/chromium/net/quic/test_tools/simulator/actor.h
+++ b/chromium/net/quic/test_tools/simulator/actor.h
@@ -7,14 +7,13 @@
#include <string>
-#include "net/quic/core/quic_clock.h"
#include "net/quic/core/quic_time.h"
+#include "net/quic/platform/api/quic_clock.h"
namespace net {
namespace simulator {
class Simulator;
-struct ScheduledActor;
// Actor is the base class for all participants of the simulation which can
// schedule events to be triggered at the specified time. Every actor has a
diff --git a/chromium/net/quic/test_tools/simulator/alarm_factory.cc b/chromium/net/quic/test_tools/simulator/alarm_factory.cc
index 7c895570d7f..43eb54d020d 100644
--- a/chromium/net/quic/test_tools/simulator/alarm_factory.cc
+++ b/chromium/net/quic/test_tools/simulator/alarm_factory.cc
@@ -7,6 +7,7 @@
#include "net/quic/test_tools/simulator/alarm_factory.h"
using base::StringPrintf;
+using std::string;
namespace net {
namespace simulator {
@@ -16,7 +17,7 @@ namespace simulator {
class Alarm : public QuicAlarm {
public:
Alarm(Simulator* simulator,
- std::string name,
+ string name,
QuicArenaScopedPtr<QuicAlarm::Delegate> delegate)
: QuicAlarm(std::move(delegate)), adapter_(simulator, name, this) {}
~Alarm() override {}
@@ -34,7 +35,7 @@ class Alarm : public QuicAlarm {
// interfaces.
class Adapter : public Actor {
public:
- Adapter(Simulator* simulator, std::string name, Alarm* parent)
+ Adapter(Simulator* simulator, string name, Alarm* parent)
: Actor(simulator, name), parent_(parent) {}
~Adapter() override {}
@@ -52,12 +53,12 @@ class Alarm : public QuicAlarm {
Adapter adapter_;
};
-AlarmFactory::AlarmFactory(Simulator* simulator, std::string name)
+AlarmFactory::AlarmFactory(Simulator* simulator, string name)
: simulator_(simulator), name_(std::move(name)), counter_(0) {}
AlarmFactory::~AlarmFactory() {}
-std::string AlarmFactory::GetNewAlarmName() {
+string AlarmFactory::GetNewAlarmName() {
++counter_;
return StringPrintf("%s (alarm %i)", name_.c_str(), counter_);
}
diff --git a/chromium/net/quic/test_tools/simulator/link.cc b/chromium/net/quic/test_tools/simulator/link.cc
index 6104ee58cbc..2ce999e39e4 100644
--- a/chromium/net/quic/test_tools/simulator/link.cc
+++ b/chromium/net/quic/test_tools/simulator/link.cc
@@ -2,11 +2,13 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#include "base/strings/stringprintf.h"
#include "net/quic/test_tools/simulator/link.h"
+
+#include "base/strings/stringprintf.h"
#include "net/quic/test_tools/simulator/simulator.h"
using base::StringPrintf;
+using std::string;
namespace net {
namespace simulator {
@@ -15,7 +17,7 @@ namespace simulator {
const uint64_t kMaxRandomDelayUs = 10;
OneWayLink::OneWayLink(Simulator* simulator,
- std::string name,
+ string name,
UnconstrainedPortInterface* sink,
QuicBandwidth bandwidth,
QuicTime::Delta propagation_delay)
@@ -84,7 +86,7 @@ QuicTime::Delta OneWayLink::GetRandomDelay(QuicTime::Delta transfer_time) {
}
SymmetricLink::SymmetricLink(Simulator* simulator,
- std::string name,
+ string name,
UnconstrainedPortInterface* sink_a,
UnconstrainedPortInterface* sink_b,
QuicBandwidth bandwidth,
diff --git a/chromium/net/quic/test_tools/simulator/packet_filter.cc b/chromium/net/quic/test_tools/simulator/packet_filter.cc
new file mode 100644
index 00000000000..e6f97f08ef0
--- /dev/null
+++ b/chromium/net/quic/test_tools/simulator/packet_filter.cc
@@ -0,0 +1,40 @@
+// Copyright (c) 2016 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.
+
+#include "net/quic/test_tools/simulator/packet_filter.h"
+
+using std::string;
+
+namespace net {
+namespace simulator {
+
+PacketFilter::PacketFilter(Simulator* simulator, string name, Endpoint* input)
+ : Endpoint(simulator, name), input_(input) {
+ input_->SetTxPort(this);
+}
+
+PacketFilter::~PacketFilter() {}
+
+void PacketFilter::AcceptPacket(std::unique_ptr<Packet> packet) {
+ if (FilterPacket(*packet)) {
+ output_tx_port_->AcceptPacket(std::move(packet));
+ }
+}
+
+QuicTime::Delta PacketFilter::TimeUntilAvailable() {
+ return output_tx_port_->TimeUntilAvailable();
+}
+
+void PacketFilter::Act() {}
+
+UnconstrainedPortInterface* PacketFilter::GetRxPort() {
+ return input_->GetRxPort();
+}
+
+void PacketFilter::SetTxPort(ConstrainedPortInterface* port) {
+ output_tx_port_ = port;
+}
+
+} // namespace simulator
+} // namespace net
diff --git a/chromium/net/quic/test_tools/simulator/packet_filter.h b/chromium/net/quic/test_tools/simulator/packet_filter.h
new file mode 100644
index 00000000000..f8caa2f0bea
--- /dev/null
+++ b/chromium/net/quic/test_tools/simulator/packet_filter.h
@@ -0,0 +1,77 @@
+// Copyright (c) 2016 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.
+
+#ifndef NET_QUIC_TEST_TOOLS_SIMULATOR_PACKET_FILTER_H_
+#define NET_QUIC_TEST_TOOLS_SIMULATOR_PACKET_FILTER_H_
+
+#include "net/quic/test_tools/simulator/port.h"
+
+namespace net {
+namespace simulator {
+
+// Packet filter allows subclasses to filter out the packets that enter the
+// input port and exit the output port. Packets in the other direction are
+// always passed through.
+//
+// The filter wraps around the input endpoint, and exposes the resulting
+// filtered endpoint via the output() method. For example, if initially there
+// are two endpoints, A and B, connected via a symmetric link:
+//
+// QuicEndpoint endpoint_a;
+// QuicEndpoint endpoint_b;
+//
+// [...]
+//
+// SymmetricLink a_b_link(&endpoint_a, &endpoint_b, ...);
+//
+// and the goal is to filter the traffic from A to B, then the new invocation
+// would be as follows:
+//
+// PacketFilter filter(&simulator, "A-to-B packet filter", endpoint_a);
+// SymmetricLink a_b_link(&filter, &endpoint_b, ...);
+//
+// Note that the filter drops the packet instanteneously, without it ever
+// reaching the output wire. This means that in a direct endpoint-to-endpoint
+// scenario, whenever the packet is dropped, the link would become immediately
+// available for the next packet.
+class PacketFilter : public Endpoint, public ConstrainedPortInterface {
+ public:
+ // Initialize the filter by wrapping around |input|. Does not take the
+ // ownership of |input|.
+ PacketFilter(Simulator* simulator, std::string name, Endpoint* input);
+ ~PacketFilter() override;
+
+ Endpoint* input() { return input_; }
+
+ // Implementation of ConstrainedPortInterface.
+ void AcceptPacket(std::unique_ptr<Packet> packet) override;
+ QuicTime::Delta TimeUntilAvailable() override;
+
+ // Implementation of Endpoint interface methods.
+ UnconstrainedPortInterface* GetRxPort() override;
+ void SetTxPort(ConstrainedPortInterface* port) override;
+
+ // Implementation of Actor interface methods.
+ void Act() override;
+
+ protected:
+ // Returns true if the packet should be passed through, and false if it should
+ // be dropped. The function is called once per packet, in the order that the
+ // packets arrive, so it is safe for the function to alter the internal state
+ // of the filter.
+ virtual bool FilterPacket(const Packet& packet) = 0;
+
+ private:
+ // The port onto which the filtered packets are egressed.
+ ConstrainedPortInterface* output_tx_port_;
+
+ // The original network endpoint wrapped by the class.
+ Endpoint* input_;
+
+ DISALLOW_COPY_AND_ASSIGN(PacketFilter);
+};
+
+} // namespace simulator
+} // namespace net
+#endif // NET_QUIC_TEST_TOOLS_SIMULATOR_PACKET_FILTER_H_
diff --git a/chromium/net/quic/test_tools/simulator/port.cc b/chromium/net/quic/test_tools/simulator/port.cc
index 11e4edae8ee..2ae0b9aab08 100644
--- a/chromium/net/quic/test_tools/simulator/port.cc
+++ b/chromium/net/quic/test_tools/simulator/port.cc
@@ -4,6 +4,8 @@
#include "net/quic/test_tools/simulator/port.h"
+using std::string;
+
namespace net {
namespace simulator {
@@ -14,7 +16,7 @@ Packet::~Packet() {}
Packet::Packet(const Packet& packet) = default;
-Endpoint::Endpoint(Simulator* simulator, std::string name)
+Endpoint::Endpoint(Simulator* simulator, string name)
: Actor(simulator, name) {}
} // namespace simulator
diff --git a/chromium/net/quic/test_tools/simulator/port.h b/chromium/net/quic/test_tools/simulator/port.h
index 62c47f2b0bd..5975f87304b 100644
--- a/chromium/net/quic/test_tools/simulator/port.h
+++ b/chromium/net/quic/test_tools/simulator/port.h
@@ -8,7 +8,7 @@
#include <string>
#include <utility>
-#include "net/quic/core/quic_protocol.h"
+#include "net/quic/core/quic_packets.h"
#include "net/quic/test_tools/simulator/actor.h"
namespace net {
diff --git a/chromium/net/quic/test_tools/simulator/queue.cc b/chromium/net/quic/test_tools/simulator/queue.cc
index 05704430b78..12073f8e0a8 100644
--- a/chromium/net/quic/test_tools/simulator/queue.cc
+++ b/chromium/net/quic/test_tools/simulator/queue.cc
@@ -2,18 +2,22 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
+#include "net/quic/platform/api/quic_logging.h"
#include "net/quic/test_tools/simulator/queue.h"
+using std::string;
+
namespace net {
namespace simulator {
Queue::ListenerInterface::~ListenerInterface() {}
-Queue::Queue(Simulator* simulator, std::string name, QuicByteCount capacity)
+Queue::Queue(Simulator* simulator, string name, QuicByteCount capacity)
: Actor(simulator, name),
capacity_(capacity),
bytes_queued_(0),
listener_(nullptr) {}
+
Queue::~Queue() {}
void Queue::set_tx_port(ConstrainedPortInterface* port) {
@@ -22,11 +26,11 @@ void Queue::set_tx_port(ConstrainedPortInterface* port) {
void Queue::AcceptPacket(std::unique_ptr<Packet> packet) {
if (packet->size + bytes_queued_ > capacity_) {
- DVLOG(1) << "Queue [" << name() << "] has received a packet from ["
- << packet->source << "] to [" << packet->destination
- << "] which is over capacity. Dropping it.";
- DVLOG(1) << "Queue size: " << bytes_queued_ << " out of " << capacity_
- << ". Packet size: " << packet->size;
+ QUIC_DVLOG(1) << "Queue [" << name() << "] has received a packet from ["
+ << packet->source << "] to [" << packet->destination
+ << "] which is over capacity. Dropping it.";
+ QUIC_DVLOG(1) << "Queue size: " << bytes_queued_ << " out of " << capacity_
+ << ". Packet size: " << packet->size;
return;
}
diff --git a/chromium/net/quic/test_tools/simulator/quic_endpoint.cc b/chromium/net/quic/test_tools/simulator/quic_endpoint.cc
index bcd3e0a2023..7adb701bae8 100644
--- a/chromium/net/quic/test_tools/simulator/quic_endpoint.cc
+++ b/chromium/net/quic/test_tools/simulator/quic_endpoint.cc
@@ -4,14 +4,16 @@
#include "net/quic/test_tools/simulator/quic_endpoint.h"
-#include "base/memory/ptr_util.h"
#include "base/sha1.h"
#include "base/strings/stringprintf.h"
#include "net/quic/core/crypto/crypto_handshake_message.h"
#include "net/quic/core/crypto/crypto_protocol.h"
+#include "net/quic/platform/api/quic_ptr_util.h"
+#include "net/quic/test_tools/quic_test_utils.h"
#include "net/quic/test_tools/simulator/simulator.h"
using base::StringPrintf;
+using std::string;
namespace net {
namespace simulator {
@@ -21,8 +23,8 @@ const QuicByteCount kWriteChunkSize = 128 * 1024;
const char kStreamDataContents = 'Q';
// Takes a SHA-1 hash of the name and converts it into five 32-bit integers.
-static std::vector<uint32_t> HashNameIntoFive32BitIntegers(std::string name) {
- const std::string hash = base::SHA1HashString(name);
+static std::vector<uint32_t> HashNameIntoFive32BitIntegers(string name) {
+ const string hash = test::Sha1Hash(name);
std::vector<uint32_t> output;
uint32_t current_number = 0;
@@ -37,25 +39,25 @@ static std::vector<uint32_t> HashNameIntoFive32BitIntegers(std::string name) {
return output;
}
-IPEndPoint GetAddressFromName(std::string name) {
+QuicSocketAddress GetAddressFromName(string name) {
const std::vector<uint32_t> hash = HashNameIntoFive32BitIntegers(name);
// Generate a random port between 1025 and 65535.
const uint16_t port = 1025 + hash[0] % (65535 - 1025 + 1);
// Generate a random 10.x.x.x address, where x is between 1 and 254.
- std::vector<uint8_t> ip_address;
- ip_address.push_back(10);
- for (size_t i = 1; i <= 4; i++) {
- ip_address.push_back(1 + hash[i] % 254);
+ string ip_address{"\xa\0\0\0", 4};
+ for (size_t i = 1; i < 4; i++) {
+ ip_address[i] = 1 + hash[i] % 254;
}
-
- return IPEndPoint(IPAddress(ip_address), port);
+ QuicIpAddress host;
+ host.FromPackedString(ip_address.c_str(), ip_address.length());
+ return QuicSocketAddress(host, port);
}
QuicEndpoint::QuicEndpoint(Simulator* simulator,
- std::string name,
- std::string peer_name,
+ string name,
+ string peer_name,
Perspective perspective,
QuicConnectionId connection_id)
: Endpoint(simulator, name),
@@ -81,8 +83,10 @@ QuicEndpoint::QuicEndpoint(Simulator* simulator,
connection_.SetSelfAddress(GetAddressFromName(name));
connection_.set_visitor(this);
- connection_.SetEncrypter(ENCRYPTION_FORWARD_SECURE, new NullEncrypter());
- connection_.SetDecrypter(ENCRYPTION_FORWARD_SECURE, new NullDecrypter());
+ connection_.SetEncrypter(ENCRYPTION_FORWARD_SECURE,
+ new NullEncrypter(perspective));
+ connection_.SetDecrypter(ENCRYPTION_FORWARD_SECURE,
+ new NullDecrypter(perspective));
connection_.SetDefaultEncryptionLevel(ENCRYPTION_FORWARD_SECURE);
// Configure the connection as if it received a handshake. This is important
@@ -168,11 +172,12 @@ QuicEndpoint::Writer::Writer(QuicEndpoint* endpoint)
QuicEndpoint::Writer::~Writer() {}
-WriteResult QuicEndpoint::Writer::WritePacket(const char* buffer,
- size_t buf_len,
- const IPAddress& self_address,
- const IPEndPoint& peer_address,
- PerPacketOptions* options) {
+WriteResult QuicEndpoint::Writer::WritePacket(
+ const char* buffer,
+ size_t buf_len,
+ const QuicIpAddress& self_address,
+ const QuicSocketAddress& peer_address,
+ PerPacketOptions* options) {
DCHECK(!IsWriteBlocked());
DCHECK(options == nullptr);
DCHECK(buf_len <= kMaxPacketSize);
@@ -185,12 +190,12 @@ WriteResult QuicEndpoint::Writer::WritePacket(const char* buffer,
return WriteResult(WRITE_STATUS_BLOCKED, 0);
}
- auto packet = base::MakeUnique<Packet>();
+ auto packet = QuicMakeUnique<Packet>();
packet->source = endpoint_->name();
packet->destination = endpoint_->peer_name_;
packet->tx_timestamp = endpoint_->clock_->Now();
- packet->contents = std::string(buffer, buf_len);
+ packet->contents = string(buffer, buf_len);
packet->size = buf_len;
endpoint_->nic_tx_queue_.AcceptPacket(std::move(packet));
@@ -208,7 +213,7 @@ void QuicEndpoint::Writer::SetWritable() {
is_blocked_ = false;
}
QuicByteCount QuicEndpoint::Writer::GetMaxPacketSize(
- const IPEndPoint& /*peer_address*/) const {
+ const QuicSocketAddress& /*peer_address*/) const {
return kMaxPacketSize;
}
@@ -241,7 +246,7 @@ void QuicEndpoint::WriteStreamData() {
}
QuicEndpointMultiplexer::QuicEndpointMultiplexer(
- std::string name,
+ string name,
std::initializer_list<QuicEndpoint*> endpoints)
: Endpoint((*endpoints.begin())->simulator(), name) {
for (QuicEndpoint* endpoint : endpoints) {
diff --git a/chromium/net/quic/test_tools/simulator/quic_endpoint.h b/chromium/net/quic/test_tools/simulator/quic_endpoint.h
index d6a64d72ee7..6f4f30d039a 100644
--- a/chromium/net/quic/test_tools/simulator/quic_endpoint.h
+++ b/chromium/net/quic/test_tools/simulator/quic_endpoint.h
@@ -8,7 +8,7 @@
#include "net/quic/core/crypto/null_decrypter.h"
#include "net/quic/core/crypto/null_encrypter.h"
#include "net/quic/core/quic_connection.h"
-#include "net/quic/core/quic_protocol.h"
+#include "net/quic/core/quic_packets.h"
#include "net/quic/test_tools/simulator/link.h"
#include "net/quic/test_tools/simulator/queue.h"
#include "net/tools/quic/quic_default_packet_writer.h"
@@ -22,7 +22,7 @@ const QuicByteCount kTxQueueSize = 1000;
// Generate a random local network host-port tuple based on the name of the
// endpoint.
-IPEndPoint GetAddressFromName(std::string name);
+QuicSocketAddress GetAddressFromName(std::string name);
// A QUIC connection endpoint. Wraps around QuicConnection. In order to
// initiate a transfer, the caller has to call AddBytesToTransfer(). The data
@@ -100,14 +100,14 @@ class QuicEndpoint : public Endpoint,
WriteResult WritePacket(const char* buffer,
size_t buf_len,
- const IPAddress& self_address,
- const IPEndPoint& peer_address,
+ const QuicIpAddress& self_address,
+ const QuicSocketAddress& peer_address,
PerPacketOptions* options) override;
bool IsWriteBlockedDataBuffered() const override;
bool IsWriteBlocked() const override;
void SetWritable() override;
QuicByteCount GetMaxPacketSize(
- const IPEndPoint& peer_address) const override;
+ const QuicSocketAddress& peer_address) const override;
private:
QuicEndpoint* endpoint_;
diff --git a/chromium/net/quic/test_tools/simulator/quic_endpoint_test.cc b/chromium/net/quic/test_tools/simulator/quic_endpoint_test.cc
index 5213727b234..9962b55a5f6 100644
--- a/chromium/net/quic/test_tools/simulator/quic_endpoint_test.cc
+++ b/chromium/net/quic/test_tools/simulator/quic_endpoint_test.cc
@@ -4,13 +4,13 @@
#include "net/quic/test_tools/simulator/quic_endpoint.h"
-#include "base/memory/ptr_util.h"
+#include "net/quic/platform/api/quic_ptr_util.h"
#include "net/quic/test_tools/quic_connection_peer.h"
#include "net/quic/test_tools/quic_test_utils.h"
#include "net/quic/test_tools/simulator/simulator.h"
#include "net/quic/test_tools/simulator/switch.h"
-#include "net/test/gtest_util.h"
+#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
using ::testing::_;
@@ -38,8 +38,8 @@ class QuicEndpointTest : public ::testing::Test {
Switch switch_;
std::unique_ptr<SymmetricLink> Link(Endpoint* a, Endpoint* b) {
- return base::MakeUnique<SymmetricLink>(a, b, kDefaultBandwidth,
- kDefaultPropagationDelay);
+ return QuicMakeUnique<SymmetricLink>(a, b, kDefaultBandwidth,
+ kDefaultPropagationDelay);
}
};
@@ -98,8 +98,7 @@ TEST_F(QuicEndpointTest, WriteBlocked) {
EXPECT_CALL(*sender, GetCongestionWindow())
.WillRepeatedly(
Return(kMaxPacketSize * kDefaultMaxCongestionWindowPackets));
- test::QuicConnectionPeer::SetSendAlgorithm(endpoint_a.connection(),
- kDefaultPathId, sender);
+ test::QuicConnectionPeer::SetSendAlgorithm(endpoint_a.connection(), sender);
// First transmit a small, packet-size chunk of data.
QuicByteCount bytes_to_transfer = 3 * 1024 * 1024;
@@ -147,17 +146,17 @@ TEST_F(QuicEndpointTest, TwoWayTransmission) {
TEST_F(QuicEndpointTest, Competition) {
simulator_.set_enable_random_delays(true);
- auto endpoint_a = base::MakeUnique<QuicEndpoint>(
+ auto endpoint_a = QuicMakeUnique<QuicEndpoint>(
&simulator_, "Endpoint A", "Endpoint D (A)", Perspective::IS_CLIENT, 42);
- auto endpoint_b = base::MakeUnique<QuicEndpoint>(
+ auto endpoint_b = QuicMakeUnique<QuicEndpoint>(
&simulator_, "Endpoint B", "Endpoint D (B)", Perspective::IS_CLIENT, 43);
- auto endpoint_c = base::MakeUnique<QuicEndpoint>(
+ auto endpoint_c = QuicMakeUnique<QuicEndpoint>(
&simulator_, "Endpoint C", "Endpoint D (C)", Perspective::IS_CLIENT, 44);
- auto endpoint_d_a = base::MakeUnique<QuicEndpoint>(
+ auto endpoint_d_a = QuicMakeUnique<QuicEndpoint>(
&simulator_, "Endpoint D (A)", "Endpoint A", Perspective::IS_SERVER, 42);
- auto endpoint_d_b = base::MakeUnique<QuicEndpoint>(
+ auto endpoint_d_b = QuicMakeUnique<QuicEndpoint>(
&simulator_, "Endpoint D (B)", "Endpoint B", Perspective::IS_SERVER, 43);
- auto endpoint_d_c = base::MakeUnique<QuicEndpoint>(
+ auto endpoint_d_c = QuicMakeUnique<QuicEndpoint>(
&simulator_, "Endpoint D (C)", "Endpoint C", Perspective::IS_SERVER, 44);
QuicEndpointMultiplexer endpoint_d(
"Endpoint D",
diff --git a/chromium/net/quic/test_tools/simulator/simulator.cc b/chromium/net/quic/test_tools/simulator/simulator.cc
index 951ebbaea33..055a7fd767f 100644
--- a/chromium/net/quic/test_tools/simulator/simulator.cc
+++ b/chromium/net/quic/test_tools/simulator/simulator.cc
@@ -2,8 +2,8 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#include "base/memory/ptr_util.h"
#include "net/quic/core/crypto/quic_random.h"
+#include "net/quic/platform/api/quic_logging.h"
#include "net/quic/test_tools/simulator/simulator.h"
namespace net {
@@ -127,8 +127,8 @@ void Simulator::HandleNextScheduledActor() {
const auto current_event_it = schedule_.begin();
QuicTime event_time = current_event_it->first;
Actor* actor = current_event_it->second;
- DVLOG(3) << "At t = " << event_time.ToDebuggingValue() << ", calling "
- << actor->name();
+ QUIC_DVLOG(3) << "At t = " << event_time.ToDebuggingValue() << ", calling "
+ << actor->name();
Unschedule(actor);
diff --git a/chromium/net/quic/test_tools/simulator/simulator.h b/chromium/net/quic/test_tools/simulator/simulator.h
index 7b3743bd168..62cc17b2429 100644
--- a/chromium/net/quic/test_tools/simulator/simulator.h
+++ b/chromium/net/quic/test_tools/simulator/simulator.h
@@ -9,9 +9,9 @@
#include <unordered_map>
#include <unordered_set>
-#include "net/quic/core/quic_bug_tracker.h"
#include "net/quic/core/quic_connection.h"
#include "net/quic/core/quic_simple_buffer_allocator.h"
+#include "net/quic/platform/api/quic_bug_tracker.h"
#include "net/quic/test_tools/simulator/actor.h"
#include "net/quic/test_tools/simulator/alarm_factory.h"
diff --git a/chromium/net/quic/test_tools/simulator/simulator_test.cc b/chromium/net/quic/test_tools/simulator/simulator_test.cc
index 4c85beada50..235d64c5f55 100644
--- a/chromium/net/quic/test_tools/simulator/simulator_test.cc
+++ b/chromium/net/quic/test_tools/simulator/simulator_test.cc
@@ -4,24 +4,30 @@
#include "net/quic/test_tools/simulator/simulator.h"
-#include "base/memory/ptr_util.h"
+#include "net/quic/platform/api/quic_logging.h"
+#include "net/quic/platform/api/quic_ptr_util.h"
#include "net/quic/test_tools/quic_test_utils.h"
#include "net/quic/test_tools/simulator/alarm_factory.h"
#include "net/quic/test_tools/simulator/link.h"
+#include "net/quic/test_tools/simulator/packet_filter.h"
#include "net/quic/test_tools/simulator/queue.h"
#include "net/quic/test_tools/simulator/switch.h"
#include "net/quic/test_tools/simulator/traffic_policer.h"
-
-#include "net/test/gtest_util.h"
+#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
+using std::string;
+using testing::_;
+using testing::Return;
+using testing::StrictMock;
+
namespace net {
namespace simulator {
// A simple counter that increments its value by 1 every specified period.
class Counter : public Actor {
public:
- Counter(Simulator* simulator, std::string name, QuicTime::Delta period)
+ Counter(Simulator* simulator, string name, QuicTime::Delta period)
: Actor(simulator, name), value_(-1), period_(period) {
Schedule(clock_->Now());
}
@@ -31,8 +37,8 @@ class Counter : public Actor {
void Act() override {
++value_;
- DVLOG(1) << name_ << " has value " << value_ << " at time "
- << clock_->Now().ToDebuggingValue();
+ QUIC_DVLOG(1) << name_ << " has value " << value_ << " at time "
+ << clock_->Now().ToDebuggingValue();
Schedule(clock_->Now() + period_);
}
@@ -79,7 +85,7 @@ class CounterPort : public UnconstrainedPortInterface {
per_destination_packet_counter_.clear();
}
- QuicPacketCount CountPacketsForDestination(std::string destination) const {
+ QuicPacketCount CountPacketsForDestination(string destination) const {
auto result_it = per_destination_packet_counter_.find(destination);
if (result_it == per_destination_packet_counter_.cend()) {
return 0;
@@ -91,8 +97,7 @@ class CounterPort : public UnconstrainedPortInterface {
QuicByteCount bytes_;
QuicPacketCount packets_;
- std::unordered_map<std::string, QuicPacketCount>
- per_destination_packet_counter_;
+ std::unordered_map<string, QuicPacketCount> per_destination_packet_counter_;
};
// Sends the packet to the specified destination at the uplink rate. Provides a
@@ -100,9 +105,9 @@ class CounterPort : public UnconstrainedPortInterface {
class LinkSaturator : public Endpoint {
public:
LinkSaturator(Simulator* simulator,
- std::string name,
+ string name,
QuicByteCount packet_size,
- std::string destination)
+ string destination)
: Endpoint(simulator, name),
packet_size_(packet_size),
destination_(std::move(destination)),
@@ -113,7 +118,7 @@ class LinkSaturator : public Endpoint {
void Act() override {
if (tx_port_->TimeUntilAvailable().IsZero()) {
- auto packet = base::MakeUnique<Packet>();
+ auto packet = QuicMakeUnique<Packet>();
packet->source = name_;
packet->destination = destination_;
packet->tx_timestamp = clock_->Now();
@@ -146,7 +151,7 @@ class LinkSaturator : public Endpoint {
private:
QuicByteCount packet_size_;
- std::string destination_;
+ string destination_;
ConstrainedPortInterface* tx_port_;
CounterPort rx_port_;
@@ -245,7 +250,7 @@ TEST(SimulatorTest, Queue) {
EXPECT_EQ(0u, queue.packets_queued());
EXPECT_EQ(0u, acceptor.packets()->size());
- auto first_packet = base::MakeUnique<Packet>();
+ auto first_packet = QuicMakeUnique<Packet>();
first_packet->size = 600;
queue.AcceptPacket(std::move(first_packet));
EXPECT_EQ(600u, queue.bytes_queued());
@@ -253,14 +258,14 @@ TEST(SimulatorTest, Queue) {
EXPECT_EQ(0u, acceptor.packets()->size());
// The second packet does not fit and is dropped.
- auto second_packet = base::MakeUnique<Packet>();
+ auto second_packet = QuicMakeUnique<Packet>();
second_packet->size = 500;
queue.AcceptPacket(std::move(second_packet));
EXPECT_EQ(600u, queue.bytes_queued());
EXPECT_EQ(1u, queue.packets_queued());
EXPECT_EQ(0u, acceptor.packets()->size());
- auto third_packet = base::MakeUnique<Packet>();
+ auto third_packet = QuicMakeUnique<Packet>();
third_packet->size = 400;
queue.AcceptPacket(std::move(third_packet));
EXPECT_EQ(1000u, queue.bytes_queued());
@@ -420,7 +425,7 @@ TEST(SimulatorTest, SwitchedNetwork) {
class AlarmToggler : public Actor {
public:
AlarmToggler(Simulator* simulator,
- std::string name,
+ string name,
QuicAlarm* alarm,
QuicTime::Delta interval)
: Actor(simulator, name),
@@ -564,6 +569,52 @@ TEST(SimulatorTest, RunFor) {
EXPECT_EQ(33, counter.get_value());
}
+class MockPacketFilter : public PacketFilter {
+ public:
+ MockPacketFilter(Simulator* simulator, string name, Endpoint* endpoint)
+ : PacketFilter(simulator, name, endpoint) {}
+ MOCK_METHOD1(FilterPacket, bool(const Packet&));
+};
+
+// Set up two trivial packet filters, one allowing any packets, and one dropping
+// all of them.
+TEST(SimulatorTest, PacketFilter) {
+ const QuicBandwidth bandwidth =
+ QuicBandwidth::FromBytesPerSecond(1024 * 1024);
+ const QuicTime::Delta base_propagation_delay =
+ QuicTime::Delta::FromMilliseconds(5);
+
+ Simulator simulator;
+ LinkSaturator saturator_a(&simulator, "Saturator A", 1000, "Saturator B");
+ LinkSaturator saturator_b(&simulator, "Saturator B", 1000, "Saturator A");
+
+ // Attach packets to the switch to create a delay between the point at which
+ // the packet is generated and the point at which it is filtered. Note that
+ // if the saturators were connected directly, the link would be always
+ // available for the endpoint which has all of its packets dropped, resulting
+ // in saturator looping infinitely.
+ Switch network_switch(&simulator, "Switch", 8,
+ bandwidth * base_propagation_delay * 10);
+ StrictMock<MockPacketFilter> a_to_b_filter(&simulator, "A -> B filter",
+ network_switch.port(1));
+ StrictMock<MockPacketFilter> b_to_a_filter(&simulator, "B -> A filter",
+ network_switch.port(2));
+ SymmetricLink link_a(&a_to_b_filter, &saturator_b, bandwidth,
+ base_propagation_delay);
+ SymmetricLink link_b(&b_to_a_filter, &saturator_a, bandwidth,
+ base_propagation_delay);
+
+ // Allow packets from A to B, but not from B to A.
+ EXPECT_CALL(a_to_b_filter, FilterPacket(_)).WillRepeatedly(Return(true));
+ EXPECT_CALL(b_to_a_filter, FilterPacket(_)).WillRepeatedly(Return(false));
+
+ // Run the simulation for a while, and expect that only B will receive any
+ // packets.
+ simulator.RunFor(QuicTime::Delta::FromSeconds(10));
+ EXPECT_GE(saturator_b.counter()->packets(), 1u);
+ EXPECT_EQ(saturator_a.counter()->packets(), 0u);
+}
+
// Set up a traffic policer in one direction that throttles at 25% of link
// bandwidth, and put two link saturators at each endpoint.
TEST(SimulatorTest, TrafficPolicer) {
@@ -587,8 +638,7 @@ TEST(SimulatorTest, TrafficPolicer) {
SymmetricLink link1(&saturator1, network_switch.port(1), bandwidth,
base_propagation_delay);
- SymmetricLink link2(&saturator2, policer.output(), bandwidth,
- base_propagation_delay);
+ SymmetricLink link2(&saturator2, &policer, bandwidth, base_propagation_delay);
// Ensure the initial burst passes without being dropped at all.
bool simulator_result = simulator.RunUntilOrTimeout(
@@ -646,8 +696,7 @@ TEST(SimulatorTest, TrafficPolicerBurst) {
SymmetricLink link1(&saturator1, network_switch.port(1), bandwidth,
base_propagation_delay);
- SymmetricLink link2(&saturator2, policer.output(), bandwidth,
- base_propagation_delay);
+ SymmetricLink link2(&saturator2, &policer, bandwidth, base_propagation_delay);
// Ensure at least one packet is sent on each side.
bool simulator_result = simulator.RunUntilOrTimeout(
diff --git a/chromium/net/quic/test_tools/simulator/switch.cc b/chromium/net/quic/test_tools/simulator/switch.cc
index 6490274cb9a..85c9e3b31c2 100644
--- a/chromium/net/quic/test_tools/simulator/switch.cc
+++ b/chromium/net/quic/test_tools/simulator/switch.cc
@@ -4,30 +4,32 @@
#include <cinttypes>
-#include "base/memory/ptr_util.h"
+#include "base/format_macros.h"
#include "base/strings/stringprintf.h"
+#include "net/quic/platform/api/quic_ptr_util.h"
#include "net/quic/test_tools/simulator/switch.h"
using base::StringPrintf;
+using std::string;
namespace net {
namespace simulator {
Switch::Switch(Simulator* simulator,
- std::string name,
+ string name,
SwitchPortNumber port_count,
QuicByteCount queue_capacity) {
for (size_t port_number = 1; port_number <= port_count; port_number++) {
- ports_.emplace_back(
- simulator, StringPrintf("%s (port %zu)", name.c_str(), port_number),
- this, port_number, queue_capacity);
+ ports_.emplace_back(simulator, StringPrintf("%s (port %" PRIuS ")",
+ name.c_str(), port_number),
+ this, port_number, queue_capacity);
}
}
Switch::~Switch() {}
Switch::Port::Port(Simulator* simulator,
- std::string name,
+ string name,
Switch* parent,
SwitchPortNumber port_number,
QuicByteCount queue_capacity)
@@ -79,7 +81,7 @@ void Switch::DispatchPacket(SwitchPortNumber port_number,
if (!egress_port.connected()) {
continue;
}
- egress_port.EnqueuePacket(base::MakeUnique<Packet>(*packet));
+ egress_port.EnqueuePacket(QuicMakeUnique<Packet>(*packet));
}
}
diff --git a/chromium/net/quic/test_tools/simulator/traffic_policer.cc b/chromium/net/quic/test_tools/simulator/traffic_policer.cc
index 84ea4db0f24..5570119f445 100644
--- a/chromium/net/quic/test_tools/simulator/traffic_policer.cc
+++ b/chromium/net/quic/test_tools/simulator/traffic_policer.cc
@@ -6,29 +6,25 @@
#include <algorithm>
+using std::string;
+
namespace net {
namespace simulator {
TrafficPolicer::TrafficPolicer(Simulator* simulator,
- std::string name,
+ string name,
QuicByteCount initial_bucket_size,
QuicByteCount max_bucket_size,
QuicBandwidth target_bandwidth,
Endpoint* input)
- : Actor(simulator, name),
+ : PacketFilter(simulator, name, input),
initial_bucket_size_(initial_bucket_size),
max_bucket_size_(max_bucket_size),
target_bandwidth_(target_bandwidth),
- last_refill_time_(clock_->Now()),
- input_(input),
- output_(this) {
- input_->SetTxPort(this);
-}
+ last_refill_time_(clock_->Now()) {}
TrafficPolicer::~TrafficPolicer() {}
-void TrafficPolicer::Act() {}
-
void TrafficPolicer::Refill() {
QuicTime::Delta time_passed = clock_->Now() - last_refill_time_;
QuicByteCount refill_size = time_passed * target_bandwidth_;
@@ -40,47 +36,27 @@ void TrafficPolicer::Refill() {
last_refill_time_ = clock_->Now();
}
-void TrafficPolicer::AcceptPacket(std::unique_ptr<Packet> packet) {
+bool TrafficPolicer::FilterPacket(const Packet& packet) {
// Refill existing buckets.
Refill();
// Create a new bucket if one does not exist.
- if (token_buckets_.count(packet->destination) == 0) {
+ if (token_buckets_.count(packet.destination) == 0) {
token_buckets_.insert(
- std::make_pair(packet->destination, initial_bucket_size_));
+ std::make_pair(packet.destination, initial_bucket_size_));
}
- auto bucket = token_buckets_.find(packet->destination);
+ auto bucket = token_buckets_.find(packet.destination);
DCHECK(bucket != token_buckets_.end());
// Silently drop the packet on the floor if out of tokens
- if (bucket->second < packet->size) {
- return;
+ if (bucket->second < packet.size) {
+ return false;
}
- bucket->second -= packet->size;
- output_tx_port_->AcceptPacket(std::move(packet));
-}
-
-QuicTime::Delta TrafficPolicer::TimeUntilAvailable() {
- return output_tx_port_->TimeUntilAvailable();
-}
-
-TrafficPolicer::Output::Output(TrafficPolicer* policer)
- : Endpoint(policer->simulator(), policer->name() + " (output port)"),
- policer_(policer) {}
-
-TrafficPolicer::Output::~Output() {}
-
-UnconstrainedPortInterface* TrafficPolicer::Output::GetRxPort() {
- return policer_->input_->GetRxPort();
+ bucket->second -= packet.size;
+ return true;
}
-void TrafficPolicer::Output::SetTxPort(ConstrainedPortInterface* port) {
- policer_->output_tx_port_ = port;
-}
-
-void TrafficPolicer::Output::Act() {}
-
} // namespace simulator
} // namespace net
diff --git a/chromium/net/quic/test_tools/simulator/traffic_policer.h b/chromium/net/quic/test_tools/simulator/traffic_policer.h
index caa585594ce..3a218ae0a1a 100644
--- a/chromium/net/quic/test_tools/simulator/traffic_policer.h
+++ b/chromium/net/quic/test_tools/simulator/traffic_policer.h
@@ -7,6 +7,7 @@
#include <unordered_map>
+#include "net/quic/test_tools/simulator/packet_filter.h"
#include "net/quic/test_tools/simulator/port.h"
namespace net {
@@ -16,8 +17,8 @@ namespace simulator {
// passing through. It wraps around an input port and exposes an output port.
// Only the traffic from input to the output is policed, so in case when
// bidirectional policing is desired, two policers have to be used. The flows
-// are hashed by the source only.
-class TrafficPolicer : public Actor, public ConstrainedPortInterface {
+// are hashed by the destination only.
+class TrafficPolicer : public PacketFilter {
public:
TrafficPolicer(Simulator* simulator,
std::string name,
@@ -27,28 +28,10 @@ class TrafficPolicer : public Actor, public ConstrainedPortInterface {
Endpoint* input);
~TrafficPolicer() override;
- Endpoint* input() { return input_; }
- Endpoint* output() { return &output_; }
-
- void AcceptPacket(std::unique_ptr<Packet> packet) override;
- QuicTime::Delta TimeUntilAvailable() override;
-
- void Act() override;
+ protected:
+ bool FilterPacket(const Packet& packet) override;
private:
- class Output : public Endpoint {
- public:
- explicit Output(TrafficPolicer* policer);
- ~Output() override;
-
- UnconstrainedPortInterface* GetRxPort() override;
- void SetTxPort(ConstrainedPortInterface* port) override;
- void Act() override;
-
- private:
- TrafficPolicer* policer_;
- };
-
// Refill the token buckets with all the tokens that have been granted since
// |last_refill_time_|.
void Refill();
@@ -60,11 +43,6 @@ class TrafficPolicer : public Actor, public ConstrainedPortInterface {
// The time at which the token buckets were last refilled.
QuicTime last_refill_time_;
- ConstrainedPortInterface* output_tx_port_;
-
- Endpoint* input_;
- Output output_;
-
// Maps each destination to the number of tokens it has left.
std::unordered_map<std::string, QuicByteCount> token_buckets_;
diff --git a/chromium/net/server/http_server.cc b/chromium/net/server/http_server.cc
index cf79aed9745..7300a38f8c1 100644
--- a/chromium/net/server/http_server.cc
+++ b/chromium/net/server/http_server.cc
@@ -14,7 +14,6 @@
#include "base/single_thread_task_runner.h"
#include "base/strings/string_number_conversions.h"
#include "base/strings/string_util.h"
-#include "base/strings/stringprintf.h"
#include "base/sys_byteorder.h"
#include "base/threading/thread_task_runner_handle.h"
#include "build/build_config.h"
@@ -368,7 +367,7 @@ const int parser_state[MAX_STATES][MAX_INPUTS] = {
// Convert an input character to the parser's input token.
int charToInput(char ch) {
- switch(ch) {
+ switch (ch) {
case ' ':
case '\t':
return INPUT_LWS;
diff --git a/chromium/net/server/http_server.h b/chromium/net/server/http_server.h
index c8ba46a5e8f..dda1a5c7c04 100644
--- a/chromium/net/server/http_server.h
+++ b/chromium/net/server/http_server.h
@@ -24,7 +24,6 @@ class HttpServerResponseInfo;
class IPEndPoint;
class ServerSocket;
class StreamSocket;
-class WebSocket;
class HttpServer {
public:
diff --git a/chromium/net/server/http_server_unittest.cc b/chromium/net/server/http_server_unittest.cc
index 87c2784da62..9b6dee1bea9 100644
--- a/chromium/net/server/http_server_unittest.cc
+++ b/chromium/net/server/http_server_unittest.cc
@@ -248,7 +248,7 @@ class HttpServerTest : public testing::Test,
}
void HandleAcceptResult(std::unique_ptr<StreamSocket> socket) {
- server_->accepted_socket_.reset(socket.release());
+ server_->accepted_socket_ = std::move(socket);
server_->HandleAcceptResult(OK);
}
@@ -548,7 +548,7 @@ class MockStreamSocket : public StreamSocket {
void SetSubresourceSpeculation() override {}
void SetOmniboxSpeculation() override {}
bool WasEverUsed() const override { return true; }
- bool WasNpnNegotiated() const override { return false; }
+ bool WasAlpnNegotiated() const override { return false; }
NextProto GetNegotiatedProtocol() const override { return kProtoUnknown; }
bool GetSSLInfo(SSLInfo* ssl_info) override { return false; }
void GetConnectionAttempts(ConnectionAttempts* out) const override {
diff --git a/chromium/net/server/web_socket_encoder.cc b/chromium/net/server/web_socket_encoder.cc
index 693de733b69..114eb36d578 100644
--- a/chromium/net/server/web_socket_encoder.cc
+++ b/chromium/net/server/web_socket_encoder.cc
@@ -11,7 +11,6 @@
#include "base/logging.h"
#include "base/memory/ptr_util.h"
#include "base/strings/string_number_conversions.h"
-#include "base/strings/stringprintf.h"
#include "net/base/io_buffer.h"
#include "net/websockets/websocket_deflate_parameters.h"
#include "net/websockets/websocket_extension.h"
@@ -97,9 +96,9 @@ WebSocket::ParseResult DecodeFrameHybi17(const base::StringPiece& frame,
uint64_t payload_length64 = second_byte & kPayloadLengthMask;
if (payload_length64 > kMaxSingleBytePayloadLength) {
int extended_payload_length_size;
- if (payload_length64 == kTwoBytePayloadLengthField)
+ if (payload_length64 == kTwoBytePayloadLengthField) {
extended_payload_length_size = 2;
- else {
+ } else {
DCHECK(payload_length64 == kEightBytePayloadLengthField);
extended_payload_length_size = 8;
}
diff --git a/chromium/net/socket/client_socket_handle.cc b/chromium/net/socket/client_socket_handle.cc
index f171552e4c2..983efa7c83c 100644
--- a/chromium/net/socket/client_socket_handle.cc
+++ b/chromium/net/socket/client_socket_handle.cc
@@ -12,6 +12,7 @@
#include "base/logging.h"
#include "base/trace_event/trace_event.h"
#include "net/base/net_errors.h"
+#include "net/base/trace_constants.h"
#include "net/log/net_log_event_type.h"
#include "net/socket/client_socket_pool.h"
@@ -66,8 +67,6 @@ void ClientSocketHandle::ResetInternal(bool cancel) {
RemoveHigherLayeredPool(higher_pool_);
pool_ = NULL;
idle_time_ = base::TimeDelta();
- init_time_ = base::TimeTicks();
- setup_time_ = base::TimeDelta();
connect_timing_ = LoadTimingInfo::ConnectTiming();
pool_id_ = -1;
}
@@ -134,12 +133,17 @@ bool ClientSocketHandle::GetLoadTimingInfo(
return true;
}
+void ClientSocketHandle::DumpMemoryStats(
+ StreamSocket::SocketMemoryStats* stats) const {
+ socket_->DumpMemoryStats(stats);
+}
+
void ClientSocketHandle::SetSocket(std::unique_ptr<StreamSocket> s) {
socket_ = std::move(s);
}
void ClientSocketHandle::OnIOComplete(int result) {
- TRACE_EVENT0("net", "ClientSocketHandle::OnIOComplete");
+ TRACE_EVENT0(kNetTracingCategory, "ClientSocketHandle::OnIOComplete");
CompletionCallback callback = user_callback_;
user_callback_.Reset();
HandleInitCompletion(result);
@@ -161,7 +165,6 @@ void ClientSocketHandle::HandleInitCompletion(int result) {
}
is_initialized_ = true;
CHECK_NE(-1, pool_id_) << "Pool should have set |pool_id_| to a valid value.";
- setup_time_ = base::TimeTicks::Now() - init_time_;
// Broadcast that the socket has been acquired.
// TODO(eroman): This logging is not complete, in particular set_socket() and
diff --git a/chromium/net/socket/client_socket_handle.h b/chromium/net/socket/client_socket_handle.h
index cf9e8d022ee..7c1788267ee 100644
--- a/chromium/net/socket/client_socket_handle.h
+++ b/chromium/net/socket/client_socket_handle.h
@@ -114,12 +114,6 @@ class NET_EXPORT ClientSocketHandle {
// Returns true when Init() has completed successfully.
bool is_initialized() const { return is_initialized_; }
- // Returns the time tick when Init() was called.
- base::TimeTicks init_time() const { return init_time_; }
-
- // Returns the time between Init() and when is_initialized() becomes true.
- base::TimeDelta setup_time() const { return setup_time_; }
-
// Sets the portion of LoadTimingInfo related to connection establishment, and
// the socket id. |is_reused| is needed because the handle may not have full
// reuse information. |load_timing_info| must have all default values when
@@ -128,6 +122,11 @@ class NET_EXPORT ClientSocketHandle {
bool GetLoadTimingInfo(bool is_reused,
LoadTimingInfo* load_timing_info) const;
+ // Dumps memory allocation stats into |stats|. |stats| can be assumed as being
+ // default initialized upon entry. Implementation overrides fields in
+ // |stats|.
+ void DumpMemoryStats(StreamSocket::SocketMemoryStats* stats) const;
+
// Used by ClientSocketPool to initialize the ClientSocketHandle.
//
// SetSocket() may also be used if this handle is used as simply for
@@ -217,8 +216,6 @@ class NET_EXPORT ClientSocketHandle {
HttpResponseInfo ssl_error_response_info_;
std::unique_ptr<ClientSocketHandle> pending_http_proxy_connection_;
std::vector<ConnectionAttempt> connection_attempts_;
- base::TimeTicks init_time_;
- base::TimeDelta setup_time_;
NetLogSource requesting_source_;
@@ -245,7 +242,6 @@ int ClientSocketHandle::Init(
ResetErrorState();
pool_ = pool;
group_name_ = group_name;
- init_time_ = base::TimeTicks::Now();
int rv = pool_->RequestSocket(group_name, &socket_params, priority,
respect_limits, this, callback_, net_log);
if (rv == ERR_IO_PENDING) {
diff --git a/chromium/net/socket/client_socket_pool_base.cc b/chromium/net/socket/client_socket_pool_base.cc
index 4e88c745acf..c5427ccf7a6 100644
--- a/chromium/net/socket/client_socket_pool_base.cc
+++ b/chromium/net/socket/client_socket_pool_base.cc
@@ -14,11 +14,15 @@
#include "base/metrics/histogram_macros.h"
#include "base/single_thread_task_runner.h"
#include "base/strings/string_util.h"
+#include "base/strings/stringprintf.h"
#include "base/threading/thread_task_runner_handle.h"
#include "base/time/time.h"
+#include "base/trace_event/memory_allocator_dump.h"
+#include "base/trace_event/process_memory_dump.h"
#include "base/trace_event/trace_event.h"
#include "base/values.h"
#include "net/base/net_errors.h"
+#include "net/base/trace_constants.h"
#include "net/log/net_log.h"
#include "net/log/net_log_event_type.h"
#include "net/log/net_log_source.h"
@@ -33,6 +37,45 @@ namespace {
// after a certain timeout has passed without receiving an ACK.
bool g_connect_backup_jobs_enabled = true;
+// Tracks why the IdleSocket is removed from the group's |idle_sockets_|.
+// This enum is used to back an UMA histogram, and should therefore be
+// treated as append-only.
+enum IdleSocketFate {
+ // (1) When an attempt is made to reuse the socket:
+
+ // Reusing an idle socket that is previously used.
+ IDLE_SOCKET_FATE_REUSE_REUSED = 0,
+ // Reusing an idle socket that is not previously used.
+ IDLE_SOCKET_FATE_REUSE_UNUSED = 1,
+ // Reusing an idle socket and found it unusable.
+ IDLE_SOCKET_FATE_REUSE_UNUSABLE = 2,
+
+ // (2) When releasing the socket to the pool, found it unusable:
+ IDLE_SOCKET_FATE_RELEASE_UNUSABLE = 3,
+
+ // (3) Socket is cleaned up in CleanupIdleSockets():
+
+ // Cleaning up the idle socket is forced.
+ IDLE_SOCKET_FATE_CLEAN_UP_FORCED = 4,
+ // Cleaning up a timed-out, reused idle socket.
+ IDLE_SOCKET_FATE_CLEAN_UP_TIMED_OUT_REUSED = 5,
+ // Cleaning up a timed-out, unused idle socket.
+ IDLE_SOCKET_FATE_CLEAN_UP_TIMED_OUT_UNUSED = 6,
+ // Cleaning up an unusable idle socket.
+ IDLE_SOCKET_FATE_CLEAN_UP_UNUSABLE = 7,
+
+ // (4) Socket is closed usually when per-origin socket limit is reached:
+ IDLE_SOCKET_FATE_CLOSE_ONE = 8,
+
+ // Max value.
+ IDLE_SOCKET_FATE_MAX = 9
+};
+
+void RecordIdleSocketFate(IdleSocketFate fate) {
+ UMA_HISTOGRAM_ENUMERATION("Net.Socket.IdleSocketFate", fate,
+ IDLE_SOCKET_FATE_MAX);
+}
+
} // namespace
ConnectJob::ConnectJob(const std::string& group_name,
@@ -89,7 +132,7 @@ void ConnectJob::SetSocket(std::unique_ptr<StreamSocket> socket) {
}
void ConnectJob::NotifyDelegateOfCompletion(int rv) {
- TRACE_EVENT0("net", "ConnectJob::NotifyDelegateOfCompletion");
+ TRACE_EVENT0(kNetTracingCategory, "ConnectJob::NotifyDelegateOfCompletion");
// The delegate will own |this|.
Delegate* delegate = delegate_;
delegate_ = NULL;
@@ -455,8 +498,12 @@ bool ClientSocketPoolBaseHelper::AssignIdleSocketToRequest(
// the |idle_socket_it| will be set to the newest used idle socket.
for (std::list<IdleSocket>::iterator it = idle_sockets->begin();
it != idle_sockets->end();) {
+ // Check whether socket is usable. Note that it's unlikely that the socket
+ // is not usuable because this function is always invoked after a
+ // reusability check, but in theory socket can be closed asynchronously.
if (!it->IsUsable()) {
DecrementIdleCount();
+ RecordIdleSocketFate(IDLE_SOCKET_FATE_REUSE_UNUSABLE);
delete it->socket;
it = idle_sockets->erase(it);
continue;
@@ -490,6 +537,9 @@ bool ClientSocketPoolBaseHelper::AssignIdleSocketToRequest(
ClientSocketHandle::REUSED_IDLE :
ClientSocketHandle::UNUSED_IDLE;
+ RecordIdleSocketFate(idle_socket.socket->WasEverUsed()
+ ? IDLE_SOCKET_FATE_REUSE_REUSED
+ : IDLE_SOCKET_FATE_REUSE_UNUSED);
// If this socket took multiple attempts to obtain, don't report those
// every time it's reused, just to the first user.
if (idle_socket.socket->WasEverUsed())
@@ -651,21 +701,55 @@ ClientSocketPoolBaseHelper::GetInfoAsValue(const std::string& name,
return dict;
}
+void ClientSocketPoolBaseHelper::DumpMemoryStats(
+ base::trace_event::ProcessMemoryDump* pmd,
+ const std::string& parent_dump_absolute_name) const {
+ size_t socket_count = 0;
+ size_t total_size = 0;
+ size_t buffer_size = 0;
+ size_t cert_count = 0;
+ size_t serialized_cert_size = 0;
+ for (const auto& kv : group_map_) {
+ for (const auto& socket : kv.second->idle_sockets()) {
+ StreamSocket::SocketMemoryStats stats;
+ socket.socket->DumpMemoryStats(&stats);
+ total_size += stats.total_size;
+ buffer_size += stats.buffer_size;
+ cert_count += stats.cert_count;
+ serialized_cert_size += stats.serialized_cert_size;
+ ++socket_count;
+ }
+ }
+ // Only create a MemoryAllocatorDump if there is at least one idle socket
+ if (socket_count > 0) {
+ base::trace_event::MemoryAllocatorDump* socket_pool_dump =
+ pmd->CreateAllocatorDump(base::StringPrintf(
+ "%s/socket_pool", parent_dump_absolute_name.c_str()));
+ socket_pool_dump->AddScalar(
+ base::trace_event::MemoryAllocatorDump::kNameSize,
+ base::trace_event::MemoryAllocatorDump::kUnitsBytes, total_size);
+ socket_pool_dump->AddScalar(
+ base::trace_event::MemoryAllocatorDump::kNameObjectCount,
+ base::trace_event::MemoryAllocatorDump::kUnitsObjects, socket_count);
+ socket_pool_dump->AddScalar(
+ "buffer_size", base::trace_event::MemoryAllocatorDump::kUnitsBytes,
+ buffer_size);
+ socket_pool_dump->AddScalar(
+ "cert_count", base::trace_event::MemoryAllocatorDump::kUnitsObjects,
+ cert_count);
+ socket_pool_dump->AddScalar(
+ "serialized_cert_size",
+ base::trace_event::MemoryAllocatorDump::kUnitsBytes,
+ serialized_cert_size);
+ }
+}
+
bool ClientSocketPoolBaseHelper::IdleSocket::IsUsable() const {
if (socket->WasEverUsed())
return socket->IsConnectedAndIdle();
return socket->IsConnected();
}
-bool ClientSocketPoolBaseHelper::IdleSocket::ShouldCleanup(
- base::TimeTicks now,
- base::TimeDelta timeout) const {
- bool timed_out = (now - start_time) >= timeout;
- if (timed_out)
- return true;
- return !IsUsable();
-}
-
void ClientSocketPoolBaseHelper::CleanupIdleSockets(bool force) {
if (idle_socket_count_ == 0)
return;
@@ -678,17 +762,30 @@ void ClientSocketPoolBaseHelper::CleanupIdleSockets(bool force) {
while (i != group_map_.end()) {
Group* group = i->second;
- std::list<IdleSocket>::iterator j = group->mutable_idle_sockets()->begin();
- while (j != group->idle_sockets().end()) {
- base::TimeDelta timeout =
- j->socket->WasEverUsed() ?
- used_idle_socket_timeout_ : unused_idle_socket_timeout_;
- if (force || j->ShouldCleanup(now, timeout)) {
- delete j->socket;
- j = group->mutable_idle_sockets()->erase(j);
+ auto idle_socket_it = group->mutable_idle_sockets()->begin();
+ while (idle_socket_it != group->idle_sockets().end()) {
+ base::TimeDelta timeout = idle_socket_it->socket->WasEverUsed()
+ ? used_idle_socket_timeout_
+ : unused_idle_socket_timeout_;
+ bool timed_out = (now - idle_socket_it->start_time) >= timeout;
+ bool should_clean_up = force || timed_out || !idle_socket_it->IsUsable();
+ if (should_clean_up) {
+ if (force) {
+ RecordIdleSocketFate(IDLE_SOCKET_FATE_CLEAN_UP_FORCED);
+ } else if (timed_out) {
+ RecordIdleSocketFate(
+ idle_socket_it->socket->WasEverUsed()
+ ? IDLE_SOCKET_FATE_CLEAN_UP_TIMED_OUT_REUSED
+ : IDLE_SOCKET_FATE_CLEAN_UP_TIMED_OUT_UNUSED);
+ } else {
+ DCHECK(!idle_socket_it->IsUsable());
+ RecordIdleSocketFate(IDLE_SOCKET_FATE_CLEAN_UP_UNUSABLE);
+ }
+ delete idle_socket_it->socket;
+ idle_socket_it = group->mutable_idle_sockets()->erase(idle_socket_it);
DecrementIdleCount();
} else {
- ++j;
+ ++idle_socket_it;
}
}
@@ -770,6 +867,7 @@ void ClientSocketPoolBaseHelper::ReleaseSocket(
OnAvailableSocketSlot(group_name, group);
} else {
socket.reset();
+ RecordIdleSocketFate(IDLE_SOCKET_FATE_RELEASE_UNUSABLE);
}
CheckForStalledSocketGroups();
@@ -1090,6 +1188,7 @@ bool ClientSocketPoolBaseHelper::CloseOneIdleSocketExceptInGroup(
if (!idle_sockets->empty()) {
delete idle_sockets->front().socket;
idle_sockets->pop_front();
+ RecordIdleSocketFate(IDLE_SOCKET_FATE_CLOSE_ONE);
DecrementIdleCount();
if (group->IsEmpty())
RemoveGroup(i);
diff --git a/chromium/net/socket/client_socket_pool_base.h b/chromium/net/socket/client_socket_pool_base.h
index 024e9bf13a6..f221f8e330c 100644
--- a/chromium/net/socket/client_socket_pool_base.h
+++ b/chromium/net/socket/client_socket_pool_base.h
@@ -56,6 +56,9 @@
namespace base {
class DictionaryValue;
+namespace trace_event {
+class ProcessMemoryDump;
+}
}
namespace net {
@@ -338,6 +341,11 @@ class NET_EXPORT_PRIVATE ClientSocketPoolBaseHelper
const std::string& name,
const std::string& type) const;
+ // Dumps memory allocation stats. |parent_dump_absolute_name| is the name
+ // used by the parent MemoryAllocatorDump in the memory dump hierarchy.
+ void DumpMemoryStats(base::trace_event::ProcessMemoryDump* pmd,
+ const std::string& parent_dump_absolute_name) const;
+
base::TimeDelta ConnectionTimeout() const {
return connect_job_factory_->ConnectionTimeout();
}
@@ -368,11 +376,6 @@ class NET_EXPORT_PRIVATE ClientSocketPoolBaseHelper
// SETTINGS frame.
bool IsUsable() const;
- // An idle socket should be removed if it can't be reused, or has been idle
- // for too long. |now| is the current time value (TimeTicks::Now()).
- // |timeout| is the length of time to wait before timing out an idle socket.
- bool ShouldCleanup(base::TimeTicks now, base::TimeDelta timeout) const;
-
StreamSocket* socket;
base::TimeTicks start_time;
};
@@ -798,6 +801,11 @@ class ClientSocketPoolBase {
return helper_.GetLoadState(group_name, handle);
}
+ void DumpMemoryStats(base::trace_event::ProcessMemoryDump* pmd,
+ const std::string& parent_dump_absolute_name) const {
+ return helper_.DumpMemoryStats(pmd, parent_dump_absolute_name);
+ }
+
virtual void OnConnectJobComplete(int result, ConnectJob* job) {
return helper_.OnConnectJobComplete(result, job);
}
diff --git a/chromium/net/socket/client_socket_pool_base_unittest.cc b/chromium/net/socket/client_socket_pool_base_unittest.cc
index 2fd8d9bb436..7b9bffa3a52 100644
--- a/chromium/net/socket/client_socket_pool_base_unittest.cc
+++ b/chromium/net/socket/client_socket_pool_base_unittest.cc
@@ -22,6 +22,7 @@
#include "base/single_thread_task_runner.h"
#include "base/strings/string_number_conversions.h"
#include "base/strings/stringprintf.h"
+#include "base/test/histogram_tester.h"
#include "base/threading/platform_thread.h"
#include "base/threading/thread_task_runner_handle.h"
#include "base/values.h"
@@ -61,6 +62,7 @@ namespace {
const int kDefaultMaxSockets = 4;
const int kDefaultMaxSocketsPerGroup = 2;
+const char kIdleSocketFateHistogram[] = "Net.Socket.IdleSocketFate";
// Make sure |handle| sets load times correctly when it has been assigned a
// reused socket.
@@ -183,7 +185,7 @@ class MockClientSocket : public StreamSocket {
void SetSubresourceSpeculation() override {}
void SetOmniboxSpeculation() override {}
bool WasEverUsed() const override { return was_used_to_convey_data_; }
- bool WasNpnNegotiated() const override { return false; }
+ bool WasAlpnNegotiated() const override { return false; }
NextProto GetNegotiatedProtocol() const override { return kProtoUnknown; }
bool GetSSLInfo(SSLInfo* ssl_info) override { return false; }
void GetConnectionAttempts(ConnectionAttempts* out) const override {
@@ -288,7 +290,8 @@ class TestConnectJob : public ConnectJob {
request.priority(),
request.respect_limits(),
delegate,
- NetLogWithSource::Make(net_log, NetLogSourceType::CONNECT_JOB)),
+ NetLogWithSource::Make(net_log,
+ NetLogSourceType::TRANSPORT_CONNECT_JOB)),
job_type_(job_type),
client_socket_factory_(client_socket_factory),
load_state_(LOAD_STATE_IDLE),
@@ -868,6 +871,7 @@ TEST_F(ClientSocketPoolBaseTest, InitConnectionFailure) {
}
TEST_F(ClientSocketPoolBaseTest, TotalLimit) {
+ base::HistogramTester histograms;
CreatePool(kDefaultMaxSockets, kDefaultMaxSocketsPerGroup);
// TODO(eroman): Check that the NetLog contains this event.
@@ -887,6 +891,10 @@ TEST_F(ClientSocketPoolBaseTest, TotalLimit) {
ReleaseAllConnections(ClientSocketPoolTest::NO_KEEP_ALIVE);
+ EXPECT_THAT(histograms.GetAllSamples(kIdleSocketFateHistogram),
+ testing::ElementsAre(
+ base::Bucket(/*IDLE_SOCKET_FATE_RELEASE_UNUSABLE=*/3, 7)));
+
EXPECT_EQ(static_cast<int>(requests_size()),
client_socket_factory_.allocation_count());
EXPECT_EQ(requests_size() - kDefaultMaxSockets, completion_count());
@@ -904,6 +912,7 @@ TEST_F(ClientSocketPoolBaseTest, TotalLimit) {
}
TEST_F(ClientSocketPoolBaseTest, TotalLimitReachedNewGroup) {
+ base::HistogramTester histograms;
CreatePool(kDefaultMaxSockets, kDefaultMaxSocketsPerGroup);
// TODO(eroman): Check that the NetLog contains this event.
@@ -922,6 +931,9 @@ TEST_F(ClientSocketPoolBaseTest, TotalLimitReachedNewGroup) {
EXPECT_THAT(StartRequest("c", DEFAULT_PRIORITY), IsError(ERR_IO_PENDING));
ReleaseAllConnections(ClientSocketPoolTest::NO_KEEP_ALIVE);
+ EXPECT_THAT(histograms.GetAllSamples(kIdleSocketFateHistogram),
+ testing::ElementsAre(
+ base::Bucket(/*IDLE_SOCKET_FATE_RELEASE_UNUSABLE=*/3, 5)));
EXPECT_EQ(static_cast<int>(requests_size()),
client_socket_factory_.allocation_count());
@@ -938,6 +950,7 @@ TEST_F(ClientSocketPoolBaseTest, TotalLimitReachedNewGroup) {
}
TEST_F(ClientSocketPoolBaseTest, TotalLimitRespectsPriority) {
+ base::HistogramTester histograms;
CreatePool(kDefaultMaxSockets, kDefaultMaxSocketsPerGroup);
EXPECT_THAT(StartRequest("b", LOWEST), IsOk());
@@ -953,6 +966,9 @@ TEST_F(ClientSocketPoolBaseTest, TotalLimitRespectsPriority) {
EXPECT_THAT(StartRequest("b", HIGHEST), IsError(ERR_IO_PENDING));
ReleaseAllConnections(ClientSocketPoolTest::NO_KEEP_ALIVE);
+ EXPECT_THAT(histograms.GetAllSamples(kIdleSocketFateHistogram),
+ testing::ElementsAre(
+ base::Bucket(/*IDLE_SOCKET_FATE_RELEASE_UNUSABLE=*/3, 7)));
EXPECT_EQ(requests_size() - kDefaultMaxSockets, completion_count());
@@ -973,6 +989,7 @@ TEST_F(ClientSocketPoolBaseTest, TotalLimitRespectsPriority) {
}
TEST_F(ClientSocketPoolBaseTest, TotalLimitRespectsGroupLimit) {
+ base::HistogramTester histograms;
CreatePool(kDefaultMaxSockets, kDefaultMaxSocketsPerGroup);
EXPECT_THAT(StartRequest("a", LOWEST), IsOk());
@@ -988,6 +1005,9 @@ TEST_F(ClientSocketPoolBaseTest, TotalLimitRespectsGroupLimit) {
EXPECT_THAT(StartRequest("b", HIGHEST), IsError(ERR_IO_PENDING));
ReleaseAllConnections(ClientSocketPoolTest::NO_KEEP_ALIVE);
+ EXPECT_THAT(histograms.GetAllSamples(kIdleSocketFateHistogram),
+ testing::ElementsAre(
+ base::Bucket(/*IDLE_SOCKET_FATE_RELEASE_UNUSABLE=*/3, 7)));
EXPECT_EQ(static_cast<int>(requests_size()),
client_socket_factory_.allocation_count());
@@ -1013,6 +1033,7 @@ TEST_F(ClientSocketPoolBaseTest, TotalLimitRespectsGroupLimit) {
// Make sure that we count connecting sockets against the total limit.
TEST_F(ClientSocketPoolBaseTest, TotalLimitCountsConnectingSockets) {
+ base::HistogramTester histograms;
CreatePool(kDefaultMaxSockets, kDefaultMaxSocketsPerGroup);
EXPECT_THAT(StartRequest("a", DEFAULT_PRIORITY), IsOk());
@@ -1035,6 +1056,9 @@ TEST_F(ClientSocketPoolBaseTest, TotalLimitCountsConnectingSockets) {
EXPECT_THAT(StartRequest("e", DEFAULT_PRIORITY), IsError(ERR_IO_PENDING));
ReleaseAllConnections(ClientSocketPoolTest::NO_KEEP_ALIVE);
+ EXPECT_THAT(histograms.GetAllSamples(kIdleSocketFateHistogram),
+ testing::ElementsAre(
+ base::Bucket(/*IDLE_SOCKET_FATE_RELEASE_UNUSABLE=*/3, 5)));
EXPECT_EQ(static_cast<int>(requests_size()),
client_socket_factory_.allocation_count());
@@ -1050,6 +1074,7 @@ TEST_F(ClientSocketPoolBaseTest, TotalLimitCountsConnectingSockets) {
}
TEST_F(ClientSocketPoolBaseTest, CorrectlyCountStalledGroups) {
+ base::HistogramTester histograms;
CreatePool(kDefaultMaxSockets, kDefaultMaxSockets);
connect_job_factory_->set_job_type(TestConnectJob::kMockJob);
@@ -1068,12 +1093,21 @@ TEST_F(ClientSocketPoolBaseTest, CorrectlyCountStalledGroups) {
EXPECT_EQ(kDefaultMaxSockets, client_socket_factory_.allocation_count());
EXPECT_TRUE(ReleaseOneConnection(ClientSocketPoolTest::KEEP_ALIVE));
+ EXPECT_THAT(
+ histograms.GetAllSamples(kIdleSocketFateHistogram),
+ testing::ElementsAre(base::Bucket(/*IDLE_SOCKET_FATE_CLOSE_ONE=*/8, 1)));
EXPECT_EQ(kDefaultMaxSockets + 1, client_socket_factory_.allocation_count());
EXPECT_TRUE(ReleaseOneConnection(ClientSocketPoolTest::KEEP_ALIVE));
+ EXPECT_THAT(
+ histograms.GetAllSamples(kIdleSocketFateHistogram),
+ testing::ElementsAre(base::Bucket(/*IDLE_SOCKET_FATE_CLOSE_ONE=*/8, 2)));
EXPECT_EQ(kDefaultMaxSockets + 2, client_socket_factory_.allocation_count());
EXPECT_TRUE(ReleaseOneConnection(ClientSocketPoolTest::KEEP_ALIVE));
EXPECT_TRUE(ReleaseOneConnection(ClientSocketPoolTest::KEEP_ALIVE));
EXPECT_EQ(kDefaultMaxSockets + 2, client_socket_factory_.allocation_count());
+ EXPECT_THAT(
+ histograms.GetAllSamples(kIdleSocketFateHistogram),
+ testing::ElementsAre(base::Bucket(/*IDLE_SOCKET_FATE_CLOSE_ONE=*/8, 2)));
}
TEST_F(ClientSocketPoolBaseTest, StallAndThenCancelAndTriggerAvailableSocket) {
@@ -1235,6 +1269,7 @@ TEST_F(ClientSocketPoolBaseTest, WaitForStalledSocketAtSocketLimit) {
// Regression test for http://crbug.com/40952.
TEST_F(ClientSocketPoolBaseTest, CloseIdleSocketAtSocketLimitDeleteGroup) {
+ base::HistogramTester histograms;
CreatePool(kDefaultMaxSockets, kDefaultMaxSocketsPerGroup);
pool_->EnableConnectBackupJobs();
connect_job_factory_->set_job_type(TestConnectJob::kMockJob);
@@ -1265,11 +1300,15 @@ TEST_F(ClientSocketPoolBaseTest, CloseIdleSocketAtSocketLimitDeleteGroup) {
ClientSocketPool::RespectLimits::ENABLED,
callback.callback(), pool_.get(), NetLogWithSource()));
+ EXPECT_THAT(histograms.GetAllSamples(kIdleSocketFateHistogram),
+ testing::ElementsAre(
+ base::Bucket(/*IDLE_SOCKET_FATE_REUSE_UNUSED=*/1, 1)));
EXPECT_EQ(kDefaultMaxSockets, client_socket_factory_.allocation_count());
EXPECT_EQ(kDefaultMaxSockets - 1, pool_->IdleSocketCount());
}
TEST_F(ClientSocketPoolBaseTest, PendingRequests) {
+ base::HistogramTester histograms;
CreatePool(kDefaultMaxSockets, kDefaultMaxSocketsPerGroup);
EXPECT_THAT(StartRequest("a", DEFAULT_PRIORITY), IsOk());
@@ -1282,6 +1321,10 @@ TEST_F(ClientSocketPoolBaseTest, PendingRequests) {
EXPECT_THAT(StartRequest("a", LOWEST), IsError(ERR_IO_PENDING));
ReleaseAllConnections(ClientSocketPoolTest::KEEP_ALIVE);
+ // 2 sockets reused for last 6 requests.
+ EXPECT_THAT(histograms.GetAllSamples(kIdleSocketFateHistogram),
+ testing::ElementsAre(
+ base::Bucket(/*IDLE_SOCKET_FATE_REUSE_UNUSED=*/1, 6)));
EXPECT_EQ(kDefaultMaxSocketsPerGroup,
client_socket_factory_.allocation_count());
@@ -1302,6 +1345,7 @@ TEST_F(ClientSocketPoolBaseTest, PendingRequests) {
}
TEST_F(ClientSocketPoolBaseTest, PendingRequests_NoKeepAlive) {
+ base::HistogramTester histograms;
CreatePool(kDefaultMaxSockets, kDefaultMaxSocketsPerGroup);
EXPECT_THAT(StartRequest("a", DEFAULT_PRIORITY), IsOk());
@@ -1317,6 +1361,9 @@ TEST_F(ClientSocketPoolBaseTest, PendingRequests_NoKeepAlive) {
for (size_t i = kDefaultMaxSocketsPerGroup; i < requests_size(); ++i)
EXPECT_THAT(request(i)->WaitForResult(), IsOk());
+ EXPECT_THAT(histograms.GetAllSamples(kIdleSocketFateHistogram),
+ testing::ElementsAre(
+ base::Bucket(/*IDLE_SOCKET_FATE_RELEASE_UNUSABE=*/3, 7)));
EXPECT_EQ(static_cast<int>(requests_size()),
client_socket_factory_.allocation_count());
EXPECT_EQ(requests_size() - kDefaultMaxSocketsPerGroup,
@@ -1366,6 +1413,7 @@ TEST_F(ClientSocketPoolBaseTest, ConnectCancelConnect) {
}
TEST_F(ClientSocketPoolBaseTest, CancelRequest) {
+ base::HistogramTester histograms;
CreatePool(kDefaultMaxSockets, kDefaultMaxSocketsPerGroup);
EXPECT_THAT(StartRequest("a", DEFAULT_PRIORITY), IsOk());
@@ -1382,6 +1430,10 @@ TEST_F(ClientSocketPoolBaseTest, CancelRequest) {
(*requests())[index_to_cancel]->handle()->Reset();
ReleaseAllConnections(ClientSocketPoolTest::KEEP_ALIVE);
+ // 2 sockets reused for 4 requests.
+ EXPECT_THAT(histograms.GetAllSamples(kIdleSocketFateHistogram),
+ testing::ElementsAre(
+ base::Bucket(/*IDLE_SOCKET_FATE_REUSE_UNUSED=*/1, 4)));
EXPECT_EQ(kDefaultMaxSocketsPerGroup,
client_socket_factory_.allocation_count());
@@ -1550,8 +1602,55 @@ TEST_F(ClientSocketPoolBaseTest, CancelActiveRequestThenRequestSocket) {
EXPECT_EQ(2, client_socket_factory_.allocation_count());
}
+TEST_F(ClientSocketPoolBaseTest, CloseIdleSocketsForced) {
+ base::HistogramTester histograms;
+ CreatePool(kDefaultMaxSockets, kDefaultMaxSocketsPerGroup);
+ ClientSocketHandle handle;
+ TestCompletionCallback callback;
+ BoundTestNetLog log;
+ int rv = handle.Init("a", params_, LOWEST,
+ ClientSocketPool::RespectLimits::ENABLED,
+ callback.callback(), pool_.get(), log.bound());
+ EXPECT_THAT(rv, IsOk());
+ handle.Reset();
+ EXPECT_EQ(1, pool_->IdleSocketCount());
+ pool_->CloseIdleSockets();
+ EXPECT_THAT(histograms.GetAllSamples(kIdleSocketFateHistogram),
+ testing::ElementsAre(
+ base::Bucket(/*IDLE_SOCKET_FATE_CLEAN_UP_FORCED=*/4, 1)));
+}
+
+TEST_F(ClientSocketPoolBaseTest, CleanUpUnusableIdleSockets) {
+ base::HistogramTester histograms;
+ CreatePool(kDefaultMaxSockets, kDefaultMaxSocketsPerGroup);
+ ClientSocketHandle handle;
+ TestCompletionCallback callback;
+ BoundTestNetLog log;
+ int rv = handle.Init("a", params_, LOWEST,
+ ClientSocketPool::RespectLimits::ENABLED,
+ callback.callback(), pool_.get(), log.bound());
+ EXPECT_THAT(rv, IsOk());
+ StreamSocket* socket = handle.socket();
+ handle.Reset();
+ EXPECT_EQ(1, pool_->IdleSocketCount());
+
+ // Disconnect socket now to make the socket unusable.
+ socket->Disconnect();
+ ClientSocketHandle handle2;
+ rv = handle2.Init("a", params_, LOWEST,
+ ClientSocketPool::RespectLimits::ENABLED,
+ callback.callback(), pool_.get(), log.bound());
+ EXPECT_THAT(rv, IsOk());
+ EXPECT_FALSE(handle2.is_reused());
+
+ EXPECT_THAT(histograms.GetAllSamples(kIdleSocketFateHistogram),
+ testing::ElementsAre(
+ base::Bucket(/*IDLE_SOCKET_FATE_CLEAN_UP_UNUSABLE=*/7, 1)));
+}
+
// Regression test for http://crbug.com/17985.
TEST_F(ClientSocketPoolBaseTest, GroupWithPendingRequestsIsNotEmpty) {
+ base::HistogramTester histograms;
const int kMaxSockets = 3;
const int kMaxSocketsPerGroup = 2;
CreatePool(kMaxSockets, kMaxSocketsPerGroup);
@@ -1576,7 +1675,14 @@ TEST_F(ClientSocketPoolBaseTest, GroupWithPendingRequestsIsNotEmpty) {
// second release will unblock a request for "c", becaue it is the next
// high priority socket.
EXPECT_TRUE(ReleaseOneConnection(ClientSocketPoolTest::KEEP_ALIVE));
+ EXPECT_THAT(histograms.GetAllSamples(kIdleSocketFateHistogram),
+ testing::ElementsAre(
+ base::Bucket(/*IDLE_SOCKET_FATE_REUSE_UNUSED=*/1, 1)));
EXPECT_TRUE(ReleaseOneConnection(ClientSocketPoolTest::KEEP_ALIVE));
+ EXPECT_THAT(
+ histograms.GetAllSamples(kIdleSocketFateHistogram),
+ testing::ElementsAre(base::Bucket(/*IDLE_SOCKET_FATE_REUSE_UNUSED=*/1, 1),
+ base::Bucket(/*IDLE_SOCKET_FATE_CLOSE_ONE=*/8, 1)));
// Closing idle sockets should not get us into trouble, but in the bug
// we were hitting a CHECK here.
@@ -1585,6 +1691,10 @@ TEST_F(ClientSocketPoolBaseTest, GroupWithPendingRequestsIsNotEmpty) {
// Run the released socket wakeups.
base::RunLoop().RunUntilIdle();
+ EXPECT_THAT(
+ histograms.GetAllSamples(kIdleSocketFateHistogram),
+ testing::ElementsAre(base::Bucket(/*IDLE_SOCKET_FATE_REUSE_UNUSED=*/1, 1),
+ base::Bucket(/*IDLE_SOCKET_FATE_CLOSE_ONE=*/8, 1)));
}
TEST_F(ClientSocketPoolBaseTest, BasicAsynchronous) {
@@ -2066,6 +2176,7 @@ TEST_F(ClientSocketPoolBaseTest, AdditionalErrorStateAsynchronous) {
// Make sure we can reuse sockets.
TEST_F(ClientSocketPoolBaseTest, CleanupTimedOutIdleSocketsReuse) {
+ base::HistogramTester histograms;
CreatePoolWithIdleTimeouts(
kDefaultMaxSockets, kDefaultMaxSocketsPerGroup,
base::TimeDelta(), // Time out unused sockets immediately.
@@ -2103,6 +2214,9 @@ TEST_F(ClientSocketPoolBaseTest, CleanupTimedOutIdleSocketsReuse) {
ASSERT_TRUE(pool_->HasGroup("a"));
EXPECT_EQ(0, pool_->IdleSocketCountInGroup("a"));
EXPECT_EQ(1, pool_->NumActiveSocketsInGroup("a"));
+ EXPECT_THAT(histograms.GetAllSamples(kIdleSocketFateHistogram),
+ testing::ElementsAre(
+ base::Bucket(/*IDLE_SOCKET_FATE_REUSE_REUSED=*/0, 1)));
TestNetLogEntry::List entries;
log.GetEntries(&entries);
@@ -2120,6 +2234,7 @@ TEST_F(ClientSocketPoolBaseTest, CleanupTimedOutIdleSocketsReuse) {
#endif
// Make sure we cleanup old unused sockets.
TEST_F(ClientSocketPoolBaseTest, MAYBE_CleanupTimedOutIdleSocketsNoReuse) {
+ base::HistogramTester histograms;
CreatePoolWithIdleTimeouts(
kDefaultMaxSockets, kDefaultMaxSocketsPerGroup,
base::TimeDelta(), // Time out unused sockets immediately
@@ -2177,6 +2292,12 @@ TEST_F(ClientSocketPoolBaseTest, MAYBE_CleanupTimedOutIdleSocketsNoReuse) {
ASSERT_THAT(callback3.WaitForResult(), IsOk());
EXPECT_FALSE(handle.is_reused());
+ EXPECT_THAT(
+ histograms.GetAllSamples(kIdleSocketFateHistogram),
+ testing::ElementsAre(
+ base::Bucket(/*IDLE_SOCKET_FATE_CLEAN_UP_TIMED_OUT_REUSED=*/5, 1),
+ base::Bucket(/*IDLE_SOCKET_FATE_CLEAN_UP_TIMED_OUT_UNUSED=*/6, 1)));
+
// Make sure the idle socket is closed.
ASSERT_TRUE(pool_->HasGroup("a"));
EXPECT_EQ(0, pool_->IdleSocketCountInGroup("a"));
@@ -2311,6 +2432,7 @@ TEST_F(ClientSocketPoolBaseTest, SocketLimitReleasingSockets) {
TEST_F(ClientSocketPoolBaseTest,
ReleasingDisconnectedSocketsMaintainsPriorityOrder) {
+ base::HistogramTester histograms;
CreatePool(kDefaultMaxSockets, kDefaultMaxSocketsPerGroup);
connect_job_factory_->set_job_type(TestConnectJob::kMockPendingJob);
@@ -2327,10 +2449,16 @@ TEST_F(ClientSocketPoolBaseTest,
// Releases one connection.
EXPECT_TRUE(ReleaseOneConnection(ClientSocketPoolTest::NO_KEEP_ALIVE));
EXPECT_THAT((*requests())[2]->WaitForResult(), IsOk());
+ EXPECT_THAT(histograms.GetAllSamples(kIdleSocketFateHistogram),
+ testing::ElementsAre(
+ base::Bucket(/*IDLE_SOCKET_FATE_RELEASE_UNUSABLE=*/3, 1)));
EXPECT_TRUE(ReleaseOneConnection(ClientSocketPoolTest::NO_KEEP_ALIVE));
EXPECT_THAT((*requests())[3]->WaitForResult(), IsOk());
EXPECT_EQ(4u, completion_count());
+ EXPECT_THAT(histograms.GetAllSamples(kIdleSocketFateHistogram),
+ testing::ElementsAre(
+ base::Bucket(/*IDLE_SOCKET_FATE_RELEASE_UNUSABLE=*/3, 2)));
EXPECT_EQ(1, GetOrderOfRequest(1));
EXPECT_EQ(2, GetOrderOfRequest(2));
@@ -3532,6 +3660,7 @@ TEST_F(ClientSocketPoolBaseTest, FailToCloseIdleSocketsNotHeldByLayeredPool) {
}
TEST_F(ClientSocketPoolBaseTest, ForciblyCloseIdleSocketsHeldByLayeredPool) {
+ base::HistogramTester histograms;
CreatePool(kDefaultMaxSockets, kDefaultMaxSocketsPerGroup);
connect_job_factory_->set_job_type(TestConnectJob::kMockJob);
@@ -3541,6 +3670,9 @@ TEST_F(ClientSocketPoolBaseTest, ForciblyCloseIdleSocketsHeldByLayeredPool) {
.WillOnce(Invoke(&mock_layered_pool,
&MockLayeredPool::ReleaseOneConnection));
EXPECT_TRUE(pool_->CloseOneIdleConnectionInHigherLayeredPool());
+ EXPECT_THAT(histograms.GetAllSamples(kIdleSocketFateHistogram),
+ testing::ElementsAre(
+ base::Bucket(/*IDLE_SOCKET_FATE_RELEASE_UNUSABLE=*/3, 1)));
}
// Tests the basic case of closing an idle socket in a higher layered pool when
diff --git a/chromium/net/socket/client_socket_pool_manager.cc b/chromium/net/socket/client_socket_pool_manager.cc
index 8482dc2b166..f0b4b6f96c8 100644
--- a/chromium/net/socket/client_socket_pool_manager.cc
+++ b/chromium/net/socket/client_socket_pool_manager.cc
@@ -4,8 +4,6 @@
#include "net/socket/client_socket_pool_manager.h"
-#include <string>
-
#include "base/logging.h"
#include "base/strings/stringprintf.h"
#include "net/base/load_flags.h"
diff --git a/chromium/net/socket/client_socket_pool_manager.h b/chromium/net/socket/client_socket_pool_manager.h
index 6f1d4078a35..9c0dae87c9c 100644
--- a/chromium/net/socket/client_socket_pool_manager.h
+++ b/chromium/net/socket/client_socket_pool_manager.h
@@ -9,15 +9,18 @@
#ifndef NET_SOCKET_CLIENT_SOCKET_POOL_MANAGER_H_
#define NET_SOCKET_CLIENT_SOCKET_POOL_MANAGER_H_
+#include <string>
+
#include "net/base/completion_callback.h"
#include "net/base/net_export.h"
#include "net/base/request_priority.h"
#include "net/http/http_network_session.h"
-class GURL;
-
namespace base {
class Value;
+namespace trace_event {
+class ProcessMemoryDump;
+}
}
namespace net {
@@ -85,6 +88,12 @@ class NET_EXPORT_PRIVATE ClientSocketPoolManager {
const HostPortPair& proxy_server) = 0;
// Creates a Value summary of the state of the socket pools.
virtual std::unique_ptr<base::Value> SocketPoolInfoToValue() const = 0;
+
+ // Dumps memory allocation stats. |parent_dump_absolute_name| is the name
+ // used by the parent MemoryAllocatorDump in the memory dump hierarchy.
+ virtual void DumpMemoryStats(
+ base::trace_event::ProcessMemoryDump* pmd,
+ const std::string& parent_dump_absolute_name) const = 0;
};
// A helper method that uses the passed in proxy information to initialize a
diff --git a/chromium/net/socket/client_socket_pool_manager_impl.cc b/chromium/net/socket/client_socket_pool_manager_impl.cc
index 5135248e4f8..26348cbb7af 100644
--- a/chromium/net/socket/client_socket_pool_manager_impl.cc
+++ b/chromium/net/socket/client_socket_pool_manager_impl.cc
@@ -360,4 +360,10 @@ void ClientSocketPoolManagerImpl::OnCertDBChanged(const X509Certificate* cert) {
FlushSocketPoolsWithError(ERR_NETWORK_CHANGED);
}
+void ClientSocketPoolManagerImpl::DumpMemoryStats(
+ base::trace_event::ProcessMemoryDump* pmd,
+ const std::string& parent_dump_absolute_name) const {
+ return ssl_socket_pool_->DumpMemoryStats(pmd, parent_dump_absolute_name);
+}
+
} // namespace net
diff --git a/chromium/net/socket/client_socket_pool_manager_impl.h b/chromium/net/socket/client_socket_pool_manager_impl.h
index c378ed91356..f2f4e7ec08f 100644
--- a/chromium/net/socket/client_socket_pool_manager_impl.h
+++ b/chromium/net/socket/client_socket_pool_manager_impl.h
@@ -7,6 +7,7 @@
#include <map>
#include <memory>
+#include <string>
#include <type_traits>
#include "base/compiler_specific.h"
@@ -17,6 +18,12 @@
#include "net/http/http_network_session.h"
#include "net/socket/client_socket_pool_manager.h"
+namespace base {
+namespace trace_event {
+class ProcessMemoryDump;
+}
+}
+
namespace net {
class CertVerifier;
@@ -74,6 +81,10 @@ class ClientSocketPoolManagerImpl : public base::NonThreadSafe,
// CertDatabase::Observer methods:
void OnCertDBChanged(const X509Certificate* cert) override;
+ void DumpMemoryStats(
+ base::trace_event::ProcessMemoryDump* pmd,
+ const std::string& parent_dump_absolute_name) const override;
+
private:
using TransportSocketPoolMap =
std::map<HostPortPair, std::unique_ptr<TransportClientSocketPool>>;
diff --git a/chromium/net/socket/fuzzed_socket.cc b/chromium/net/socket/fuzzed_socket.cc
index d0b11cf68b7..6c1a75cf46e 100644
--- a/chromium/net/socket/fuzzed_socket.cc
+++ b/chromium/net/socket/fuzzed_socket.cc
@@ -58,19 +58,14 @@ int FuzzedSocket::Read(IOBuffer* buf,
} else {
// Otherwise, use |data_provider_|.
sync = data_provider_->ConsumeBool();
- result = data_provider_->ConsumeUint8();
- if (result > buf_len)
- result = buf_len;
+ std::string data = data_provider_->ConsumeRandomLengthString(buf_len);
+ result = data.size();
if (result > 0) {
- std::string data = data_provider_->ConsumeBytes(result);
- result = data.size();
std::copy(data.data(), data.data() + result, buf->data());
- }
-
- if (result == 0) {
- net_error_ = ConsumeReadWriteErrorFromData();
- result = net_error_;
+ } else {
+ result = ConsumeReadWriteErrorFromData();
+ net_error_ = result;
if (!sync)
error_pending_ = true;
}
@@ -221,7 +216,7 @@ bool FuzzedSocket::WasEverUsed() const {
void FuzzedSocket::EnableTCPFastOpenIfSupported() {}
-bool FuzzedSocket::WasNpnNegotiated() const {
+bool FuzzedSocket::WasAlpnNegotiated() const {
return false;
}
@@ -279,6 +274,7 @@ void FuzzedSocket::OnConnectComplete(const CompletionCallback& callback,
connect_pending_ = false;
if (result < 0)
error_pending_ = false;
+ net_error_ = result;
callback.Run(result);
}
diff --git a/chromium/net/socket/fuzzed_socket.h b/chromium/net/socket/fuzzed_socket.h
index 491b339e382..2da0b03cb5d 100644
--- a/chromium/net/socket/fuzzed_socket.h
+++ b/chromium/net/socket/fuzzed_socket.h
@@ -79,7 +79,7 @@ class FuzzedSocket : public StreamSocket {
void SetOmniboxSpeculation() override;
bool WasEverUsed() const override;
void EnableTCPFastOpenIfSupported() override;
- bool WasNpnNegotiated() const override;
+ bool WasAlpnNegotiated() const override;
NextProto GetNegotiatedProtocol() const override;
bool GetSSLInfo(SSLInfo* ssl_info) override;
void GetConnectionAttempts(ConnectionAttempts* out) const override;
diff --git a/chromium/net/socket/fuzzed_socket_factory.cc b/chromium/net/socket/fuzzed_socket_factory.cc
index 0385bb2eadf..4e60a00651e 100644
--- a/chromium/net/socket/fuzzed_socket_factory.cc
+++ b/chromium/net/socket/fuzzed_socket_factory.cc
@@ -73,7 +73,7 @@ class FailingSSLClientSocket : public SSLClientSocket {
void EnableTCPFastOpenIfSupported() override {}
- bool WasNpnNegotiated() const override { return false; }
+ bool WasAlpnNegotiated() const override { return false; }
NextProto GetNegotiatedProtocol() const override { return kProtoUnknown; }
diff --git a/chromium/net/socket/mock_client_socket_pool_manager.cc b/chromium/net/socket/mock_client_socket_pool_manager.cc
index 3f33b64533b..3c80ac64bb7 100644
--- a/chromium/net/socket/mock_client_socket_pool_manager.cc
+++ b/chromium/net/socket/mock_client_socket_pool_manager.cc
@@ -93,4 +93,8 @@ MockClientSocketPoolManager::SocketPoolInfoToValue() const {
return std::unique_ptr<base::Value>(nullptr);
}
+void MockClientSocketPoolManager::DumpMemoryStats(
+ base::trace_event::ProcessMemoryDump* pmd,
+ const std::string& parent_dump_absolute_name) const {}
+
} // namespace net
diff --git a/chromium/net/socket/mock_client_socket_pool_manager.h b/chromium/net/socket/mock_client_socket_pool_manager.h
index 379065a8321..18004377abb 100644
--- a/chromium/net/socket/mock_client_socket_pool_manager.h
+++ b/chromium/net/socket/mock_client_socket_pool_manager.h
@@ -5,6 +5,8 @@
#ifndef NET_SOCKET_MOCK_CLIENT_SOCKET_POOL_MANAGER_H_
#define NET_SOCKET_MOCK_CLIENT_SOCKET_POOL_MANAGER_H_
+#include <string>
+
#include "base/macros.h"
#include "net/socket/client_socket_pool_manager.h"
#include "net/socket/client_socket_pool_manager_impl.h"
@@ -39,6 +41,9 @@ class MockClientSocketPoolManager : public ClientSocketPoolManager {
SSLClientSocketPool* GetSocketPoolForSSLWithProxy(
const HostPortPair& proxy_server) override;
std::unique_ptr<base::Value> SocketPoolInfoToValue() const override;
+ void DumpMemoryStats(
+ base::trace_event::ProcessMemoryDump* pmd,
+ const std::string& parent_dump_absolute_name) const override;
private:
using TransportSocketPoolMap =
diff --git a/chromium/net/socket/next_proto.cc b/chromium/net/socket/next_proto.cc
index 7ec7c1d68d0..b637f978d5f 100644
--- a/chromium/net/socket/next_proto.cc
+++ b/chromium/net/socket/next_proto.cc
@@ -9,11 +9,7 @@ namespace net {
NextProto NextProtoFromString(base::StringPiece proto_string) {
if (proto_string == "http1.1" || proto_string == "http/1.1")
return kProtoHTTP11;
- // "npn-h2" and "npn-spdy/3.1" are accepted here so that persisted
- // settings with the old string can be loaded from disk.
- // TODO(bnc): Remove around 2016 December.
- if (proto_string == "h2" || proto_string == "npn-h2" ||
- proto_string == "npn-spdy/3.1") {
+ if (proto_string == "h2") {
return kProtoHTTP2;
}
if (proto_string == "quic")
diff --git a/chromium/net/socket/sequenced_socket_data_unittest.cc b/chromium/net/socket/sequenced_socket_data_unittest.cc
index ea77f0a3e00..b35d1fb9133 100644
--- a/chromium/net/socket/sequenced_socket_data_unittest.cc
+++ b/chromium/net/socket/sequenced_socket_data_unittest.cc
@@ -914,6 +914,9 @@ TEST_F(SequencedSocketDataTest, InterleavedAsyncOperations) {
ASSERT_EQ(kLen1, read_callback_.WaitForResult());
AssertReadBufferEquals(kMsg1, kLen1);
+ // Run posted OnWriteComplete().
+ base::RunLoop().RunUntilIdle();
+
ASSERT_TRUE(write_callback_.have_result());
ASSERT_EQ(kLen2, write_callback_.WaitForResult());
diff --git a/chromium/net/socket/socket_bio_adapter.cc b/chromium/net/socket/socket_bio_adapter.cc
index 1241bae6f90..0d75e68ec85 100644
--- a/chromium/net/socket/socket_bio_adapter.cc
+++ b/chromium/net/socket/socket_bio_adapter.cc
@@ -53,6 +53,16 @@ bool SocketBIOAdapter::HasPendingReadData() {
return read_result_ > 0;
}
+size_t SocketBIOAdapter::GetAllocationSize() const {
+ size_t buffer_size = 0;
+ if (read_buffer_)
+ buffer_size += read_buffer_capacity_;
+
+ if (write_buffer_)
+ buffer_size += write_buffer_capacity_;
+ return buffer_size;
+}
+
int SocketBIOAdapter::BIORead(char* out, int len) {
if (len <= 0)
return len;
diff --git a/chromium/net/socket/socket_bio_adapter.h b/chromium/net/socket/socket_bio_adapter.h
index d718721683a..235917a0891 100644
--- a/chromium/net/socket/socket_bio_adapter.h
+++ b/chromium/net/socket/socket_bio_adapter.h
@@ -78,6 +78,9 @@ class NET_EXPORT_PRIVATE SocketBIOAdapter {
// but not yet consumed by the BIO.
bool HasPendingReadData();
+ // Returns the allocation size estimate in bytes.
+ size_t GetAllocationSize() const;
+
private:
int BIORead(char* out, int len);
void HandleSocketReadResult(int result);
diff --git a/chromium/net/socket/socket_posix.cc b/chromium/net/socket/socket_posix.cc
index a86bf855b32..09d9baec87e 100644
--- a/chromium/net/socket/socket_posix.cc
+++ b/chromium/net/socket/socket_posix.cc
@@ -19,6 +19,7 @@
#include "net/base/ip_endpoint.h"
#include "net/base/net_errors.h"
#include "net/base/sockaddr_storage.h"
+#include "net/base/trace_constants.h"
namespace net {
@@ -369,7 +370,8 @@ void SocketPosix::DetachFromThread() {
}
void SocketPosix::OnFileCanReadWithoutBlocking(int fd) {
- TRACE_EVENT0("net", "SocketPosix::OnFileCanReadWithoutBlocking");
+ TRACE_EVENT0(kNetTracingCategory,
+ "SocketPosix::OnFileCanReadWithoutBlocking");
DCHECK(!accept_callback_.is_null() || !read_callback_.is_null());
if (!accept_callback_.is_null()) {
AcceptCompleted();
diff --git a/chromium/net/socket/socket_posix.h b/chromium/net/socket/socket_posix.h
index e308f1b26ec..bf4b7e53d9b 100644
--- a/chromium/net/socket/socket_posix.h
+++ b/chromium/net/socket/socket_posix.h
@@ -19,7 +19,6 @@
namespace net {
class IOBuffer;
-class IPEndPoint;
struct SockaddrStorage;
// Socket class to provide asynchronous read/write operations on top of the
diff --git a/chromium/net/socket/socket_test_util.cc b/chromium/net/socket/socket_test_util.cc
index ef21477adc6..aeea26ad7a9 100644
--- a/chromium/net/socket/socket_test_util.cc
+++ b/chromium/net/socket/socket_test_util.cc
@@ -808,7 +808,7 @@ const NetLogWithSource& MockClientSocket::NetLog() const {
return net_log_;
}
-bool MockClientSocket::WasNpnNegotiated() const {
+bool MockClientSocket::WasAlpnNegotiated() const {
return false;
}
@@ -1206,7 +1206,7 @@ int MockSSLClientSocket::GetPeerAddress(IPEndPoint* address) const {
return transport_->socket()->GetPeerAddress(address);
}
-bool MockSSLClientSocket::WasNpnNegotiated() const {
+bool MockSSLClientSocket::WasAlpnNegotiated() const {
return data_->next_proto != kProtoUnknown;
}
diff --git a/chromium/net/socket/socket_test_util.h b/chromium/net/socket/socket_test_util.h
index 4496a97d889..fec7819d0e9 100644
--- a/chromium/net/socket/socket_test_util.h
+++ b/chromium/net/socket/socket_test_util.h
@@ -575,7 +575,7 @@ class MockClientSocket : public SSLClientSocket {
const NetLogWithSource& NetLog() const override;
void SetSubresourceSpeculation() override {}
void SetOmniboxSpeculation() override {}
- bool WasNpnNegotiated() const override;
+ bool WasAlpnNegotiated() const override;
NextProto GetNegotiatedProtocol() const override;
void GetConnectionAttempts(ConnectionAttempts* out) const override;
void ClearConnectionAttempts() override {}
@@ -701,7 +701,7 @@ class MockSSLClientSocket : public MockClientSocket, public AsyncSocket {
bool IsConnectedAndIdle() const override;
bool WasEverUsed() const override;
int GetPeerAddress(IPEndPoint* address) const override;
- bool WasNpnNegotiated() const override;
+ bool WasAlpnNegotiated() const override;
NextProto GetNegotiatedProtocol() const override;
bool GetSSLInfo(SSLInfo* ssl_info) override;
diff --git a/chromium/net/socket/socks5_client_socket.cc b/chromium/net/socket/socks5_client_socket.cc
index 9259296fa92..19cdfddbe0c 100644
--- a/chromium/net/socket/socks5_client_socket.cc
+++ b/chromium/net/socket/socks5_client_socket.cc
@@ -114,9 +114,9 @@ bool SOCKS5ClientSocket::WasEverUsed() const {
return was_ever_used_;
}
-bool SOCKS5ClientSocket::WasNpnNegotiated() const {
+bool SOCKS5ClientSocket::WasAlpnNegotiated() const {
if (transport_.get() && transport_->socket()) {
- return transport_->socket()->WasNpnNegotiated();
+ return transport_->socket()->WasAlpnNegotiated();
}
NOTREACHED();
return false;
diff --git a/chromium/net/socket/socks5_client_socket.h b/chromium/net/socket/socks5_client_socket.h
index 268fbfbd05a..afef312d001 100644
--- a/chromium/net/socket/socks5_client_socket.h
+++ b/chromium/net/socket/socks5_client_socket.h
@@ -53,7 +53,7 @@ class NET_EXPORT_PRIVATE SOCKS5ClientSocket : public StreamSocket {
void SetSubresourceSpeculation() override;
void SetOmniboxSpeculation() override;
bool WasEverUsed() const override;
- bool WasNpnNegotiated() const override;
+ bool WasAlpnNegotiated() const override;
NextProto GetNegotiatedProtocol() const override;
bool GetSSLInfo(SSLInfo* ssl_info) override;
void GetConnectionAttempts(ConnectionAttempts* out) const override;
diff --git a/chromium/net/socket/socks_client_socket.cc b/chromium/net/socket/socks_client_socket.cc
index 8cbd379ef7b..027d18ab7c1 100644
--- a/chromium/net/socket/socks_client_socket.cc
+++ b/chromium/net/socket/socks_client_socket.cc
@@ -143,9 +143,9 @@ bool SOCKSClientSocket::WasEverUsed() const {
return was_ever_used_;
}
-bool SOCKSClientSocket::WasNpnNegotiated() const {
+bool SOCKSClientSocket::WasAlpnNegotiated() const {
if (transport_.get() && transport_->socket()) {
- return transport_->socket()->WasNpnNegotiated();
+ return transport_->socket()->WasAlpnNegotiated();
}
NOTREACHED();
return false;
diff --git a/chromium/net/socket/socks_client_socket.h b/chromium/net/socket/socks_client_socket.h
index 0f6d189cc43..c2999ffa17b 100644
--- a/chromium/net/socket/socks_client_socket.h
+++ b/chromium/net/socket/socks_client_socket.h
@@ -50,7 +50,7 @@ class NET_EXPORT_PRIVATE SOCKSClientSocket : public StreamSocket {
void SetSubresourceSpeculation() override;
void SetOmniboxSpeculation() override;
bool WasEverUsed() const override;
- bool WasNpnNegotiated() const override;
+ bool WasAlpnNegotiated() const override;
NextProto GetNegotiatedProtocol() const override;
bool GetSSLInfo(SSLInfo* ssl_info) override;
void GetConnectionAttempts(ConnectionAttempts* out) const override;
diff --git a/chromium/net/socket/socks_client_socket_pool.cc b/chromium/net/socket/socks_client_socket_pool.cc
index 0e2464d7944..8db91d5467f 100644
--- a/chromium/net/socket/socks_client_socket_pool.cc
+++ b/chromium/net/socket/socks_client_socket_pool.cc
@@ -55,7 +55,7 @@ SOCKSConnectJob::SOCKSConnectJob(
priority,
respect_limits,
delegate,
- NetLogWithSource::Make(net_log, NetLogSourceType::CONNECT_JOB)),
+ NetLogWithSource::Make(net_log, NetLogSourceType::SOCKS_CONNECT_JOB)),
socks_params_(socks_params),
transport_pool_(transport_pool),
resolver_(host_resolver),
diff --git a/chromium/net/socket/ssl_client_socket.cc b/chromium/net/socket/ssl_client_socket.cc
index 7c91d2fb761..2ace6e7669b 100644
--- a/chromium/net/socket/ssl_client_socket.cc
+++ b/chromium/net/socket/ssl_client_socket.cc
@@ -4,7 +4,6 @@
#include "net/socket/ssl_client_socket.h"
-#include "base/feature_list.h"
#include "base/metrics/histogram_macros.h"
#include "base/metrics/sparse_histogram.h"
#include "base/strings/string_util.h"
@@ -17,13 +16,6 @@
namespace net {
-namespace {
-#if !defined(OS_NACL)
-const base::Feature kPostQuantumExperiment{"SSLPostQuantumExperiment",
- base::FEATURE_DISABLED_BY_DEFAULT};
-#endif
-} // namespace
-
SSLClientSocket::SSLClientSocket()
: signed_cert_timestamps_received_(false),
stapled_ocsp_response_received_(false) {}
@@ -47,15 +39,6 @@ bool SSLClientSocket::IgnoreCertError(int error, int load_flags) {
}
// static
-bool SSLClientSocket::IsPostQuantumExperimentEnabled() {
-#if !defined(OS_NACL)
- return base::FeatureList::IsEnabled(kPostQuantumExperiment);
-#else
- return false;
-#endif
-}
-
-// static
std::vector<uint8_t> SSLClientSocket::SerializeNextProtos(
const NextProtoVector& next_protos) {
std::vector<uint8_t> wire_protos;
diff --git a/chromium/net/socket/ssl_client_socket.h b/chromium/net/socket/ssl_client_socket.h
index f523e26f264..89ac601c344 100644
--- a/chromium/net/socket/ssl_client_socket.h
+++ b/chromium/net/socket/ssl_client_socket.h
@@ -8,6 +8,7 @@
#include <stdint.h>
#include <string>
+#include <vector>
#include "base/gtest_prod_util.h"
#include "base/strings/string_piece.h"
@@ -35,10 +36,7 @@ class CertVerifier;
class ChannelIDService;
class CTVerifier;
class SSLCertRequestInfo;
-struct SSLConfig;
-class SSLInfo;
class TransportSecurityState;
-class X509Certificate;
// This struct groups together several fields which are used by various
// classes related to SSLClientSocket.
@@ -118,11 +116,6 @@ class NET_EXPORT SSLClientSocket : public SSLSocket {
// establishing the connection (or NULL if no channel ID was used).
virtual crypto::ECPrivateKey* GetChannelIDKey() const = 0;
- // Returns true if the CECPQ1 (experimental post-quantum) experiment is
- // enabled. This should be removed after the experiment is ended, around
- // 2017-18.
- static bool IsPostQuantumExperimentEnabled();
-
protected:
void set_signed_cert_timestamps_received(
bool signed_cert_timestamps_received) {
diff --git a/chromium/net/socket/ssl_client_socket_impl.cc b/chromium/net/socket/ssl_client_socket_impl.cc
index d20d81e2d12..4be80d76f56 100644
--- a/chromium/net/socket/ssl_client_socket_impl.cc
+++ b/chromium/net/socket/ssl_client_socket_impl.cc
@@ -7,6 +7,7 @@
#include <errno.h>
#include <string.h>
+#include <algorithm>
#include <utility>
#include "base/bind.h"
@@ -21,14 +22,17 @@
#include "base/profiler/scoped_tracker.h"
#include "base/strings/string_number_conversions.h"
#include "base/strings/string_piece.h"
+#include "base/strings/stringprintf.h"
#include "base/synchronization/lock.h"
#include "base/threading/thread_local.h"
+#include "base/trace_event/process_memory_dump.h"
#include "base/trace_event/trace_event.h"
#include "base/values.h"
#include "crypto/ec_private_key.h"
#include "crypto/openssl_util.h"
#include "net/base/ip_address.h"
#include "net/base/net_errors.h"
+#include "net/base/trace_constants.h"
#include "net/cert/cert_verifier.h"
#include "net/cert/ct_ev_whitelist.h"
#include "net/cert/ct_policy_enforcer.h"
@@ -169,10 +173,7 @@ std::unique_ptr<base::Value> NetLogChannelIDLookupCompleteCallback(
dict->SetInteger("net_error", result);
std::string raw_key;
if (result == OK && key && key->ExportRawPublicKey(&raw_key)) {
- std::string key_to_log = "redacted";
- if (capture_mode.include_cookies_and_credentials()) {
- key_to_log = base::HexEncode(raw_key.data(), raw_key.length());
- }
+ std::string key_to_log = base::HexEncode(raw_key.data(), raw_key.length());
dict->SetString("key", key_to_log);
}
return std::move(dict);
@@ -232,12 +233,16 @@ bool AreLegacyECDSACiphersEnabled() {
}
#endif
+const base::Feature kShortRecordHeaderFeature{
+ "SSLShortRecordHeader", base::FEATURE_DISABLED_BY_DEFAULT};
+
} // namespace
class SSLClientSocketImpl::SSLContext {
public:
static SSLContext* GetInstance() {
- return base::Singleton<SSLContext>::get();
+ return base::Singleton<SSLContext,
+ base::LeakySingletonTraits<SSLContext>>::get();
}
SSL_CTX* ssl_ctx() { return ssl_ctx_.get(); }
SSLClientSessionCache* session_cache() { return &session_cache_; }
@@ -287,6 +292,10 @@ class SSLClientSocketImpl::SSLContext {
SSL_CTX_set_grease_enabled(ssl_ctx_.get(), 1);
+ if (base::FeatureList::IsEnabled(kShortRecordHeaderFeature)) {
+ SSL_CTX_set_short_header_enabled(ssl_ctx_.get(), 1);
+ }
+
if (!SSL_CTX_add_client_custom_ext(ssl_ctx_.get(), kTbExtNum,
&TokenBindingAddCallback,
&TokenBindingFreeCallback, nullptr,
@@ -556,9 +565,36 @@ void SSLClientSocketImpl::SetSSLKeyLogFile(
void SSLClientSocketImpl::GetSSLCertRequestInfo(
SSLCertRequestInfo* cert_request_info) {
+ if (!ssl_) {
+ NOTREACHED();
+ return;
+ }
+
cert_request_info->host_and_port = host_and_port_;
- cert_request_info->cert_authorities = cert_authorities_;
- cert_request_info->cert_key_types = cert_key_types_;
+
+ cert_request_info->cert_authorities.clear();
+ STACK_OF(X509_NAME)* authorities = SSL_get_client_CA_list(ssl_.get());
+ for (size_t i = 0; i < sk_X509_NAME_num(authorities); i++) {
+ X509_NAME* ca_name = sk_X509_NAME_value(authorities, i);
+ uint8_t* str = nullptr;
+ int length = i2d_X509_NAME(ca_name, &str);
+ if (length > 0) {
+ cert_request_info->cert_authorities.push_back(std::string(
+ reinterpret_cast<const char*>(str), static_cast<size_t>(length)));
+ } else {
+ NOTREACHED(); // Error serializing |ca_name|.
+ }
+ OPENSSL_free(str);
+ }
+
+ cert_request_info->cert_key_types.clear();
+ const uint8_t* client_cert_types;
+ size_t num_client_cert_types =
+ SSL_get0_certificate_types(ssl_.get(), &client_cert_types);
+ for (size_t i = 0; i < num_client_cert_types; i++) {
+ cert_request_info->cert_key_types.push_back(
+ static_cast<SSLClientCertType>(client_cert_types[i]));
+ }
}
ChannelIDService* SSLClientSocketImpl::GetChannelIDService() const {
@@ -742,7 +778,7 @@ bool SSLClientSocketImpl::WasEverUsed() const {
return was_ever_used_;
}
-bool SSLClientSocketImpl::WasNpnNegotiated() const {
+bool SSLClientSocketImpl::WasAlpnNegotiated() const {
return negotiated_protocol_ != kProtoUnknown;
}
@@ -784,9 +820,6 @@ bool SSLClientSocketImpl::GetSSLInfo(SSLInfo* ssl_info) {
SSLConnectionStatusSetVersion(GetNetSSLVersion(ssl_.get()),
&ssl_info->connection_status);
- if (!SSL_get_secure_renegotiation_support(ssl_.get()))
- ssl_info->connection_status |= SSL_CONNECTION_NO_RENEGOTIATION_EXTENSION;
-
ssl_info->handshake_type = SSL_session_reused(ssl_.get())
? SSLInfo::HANDSHAKE_RESUME
: SSLInfo::HANDSHAKE_FULL;
@@ -802,6 +835,28 @@ int64_t SSLClientSocketImpl::GetTotalReceivedBytes() const {
return transport_->socket()->GetTotalReceivedBytes();
}
+void SSLClientSocketImpl::DumpMemoryStats(SocketMemoryStats* stats) const {
+ if (transport_adapter_)
+ stats->buffer_size = transport_adapter_->GetAllocationSize();
+ if (server_cert_chain_) {
+ for (size_t i = 0; i < server_cert_chain_->size(); ++i) {
+ X509* cert = server_cert_chain_->Get(i);
+ // This measures the lower bound of the serialized certificate. It doesn't
+ // measure the actual memory used, which is 4x this amount (see
+ // crbug.com/671420 for more details).
+ stats->serialized_cert_size += i2d_X509(cert, nullptr);
+ }
+ stats->cert_count = server_cert_chain_->size();
+ }
+ stats->total_size = stats->buffer_size + stats->serialized_cert_size;
+}
+
+// static
+void SSLClientSocketImpl::DumpSSLClientSessionMemoryStats(
+ base::trace_event::ProcessMemoryDump* pmd) {
+ SSLContext::GetInstance()->session_cache()->DumpMemoryStats(pmd);
+}
+
int SSLClientSocketImpl::Read(IOBuffer* buf,
int buf_len,
const CompletionCallback& callback) {
@@ -891,8 +946,8 @@ int SSLClientSocketImpl::Init() {
return ERR_UNEXPECTED;
}
- bssl::UniquePtr<SSL_SESSION> session =
- context->session_cache()->Lookup(GetSessionCacheKey());
+ bssl::UniquePtr<SSL_SESSION> session = context->session_cache()->Lookup(
+ GetSessionCacheKey(), &ssl_session_cache_lookup_count_);
if (session)
SSL_set_session(ssl_.get(), session.get());
@@ -937,27 +992,6 @@ int SSLClientSocketImpl::Init() {
SSL_set_mode(ssl_.get(), mode.set_mask);
SSL_clear_mode(ssl_.get(), mode.clear_mask);
- std::string command;
- if (SSLClientSocket::IsPostQuantumExperimentEnabled()) {
- // These are experimental, non-standard ciphersuites. They are part of an
- // experiment in post-quantum cryptography. They're not intended to
- // represent a de-facto standard, and will be removed from BoringSSL in
- // ~2018.
- if (EVP_has_aes_hardware()) {
- command.append(
- "CECPQ1-RSA-AES256-GCM-SHA384:"
- "CECPQ1-ECDSA-AES256-GCM-SHA384:");
- }
- command.append(
- "CECPQ1-RSA-CHACHA20-POLY1305-SHA256:"
- "CECPQ1-ECDSA-CHACHA20-POLY1305-SHA256:");
- if (!EVP_has_aes_hardware()) {
- command.append(
- "CECPQ1-RSA-AES256-GCM-SHA384:"
- "CECPQ1-ECDSA-AES256-GCM-SHA384:");
- }
- }
-
// Use BoringSSL defaults, but disable HMAC-SHA256 and HMAC-SHA384 ciphers
// (note that SHA256 and SHA384 only select legacy CBC ciphers). Also disable
// DHE_RSA_WITH_AES_256_GCM_SHA384. Historically, AES_256_GCM was not
@@ -966,7 +1000,8 @@ int SSLClientSocketImpl::Init() {
//
// TODO(davidben): Remove the DHE_RSA_WITH_AES_256_GCM_SHA384 exclusion when
// the DHEEnabled administrative policy expires.
- command.append("ALL:!SHA256:!SHA384:!DHE-RSA-AES256-GCM-SHA384:!aPSK:!RC4");
+ std::string command(
+ "ALL:!SHA256:!SHA384:!DHE-RSA-AES256-GCM-SHA384:!aPSK:!RC4");
if (ssl_config_.require_ecdhe)
command.append(":!kRSA:!kDHE");
@@ -1113,6 +1148,19 @@ int SSLClientSocketImpl::DoHandshakeComplete(int result) {
if (result < 0)
return result;
+ SSLContext::GetInstance()->session_cache()->ResetLookupCount(
+ GetSessionCacheKey());
+ // If we got a session from the session cache, log how many concurrent
+ // handshakes that session was used in before we finished our handshake. This
+ // is only recorded if the session from the cache was actually used, and only
+ // if the ALPN protocol is h2 (under the assumption that TLS 1.3 servers will
+ // be speaking h2). See https://crbug.com/631988.
+ if (ssl_session_cache_lookup_count_ && negotiated_protocol_ == kProtoHTTP2 &&
+ SSL_session_reused(ssl_.get())) {
+ UMA_HISTOGRAM_EXACT_LINEAR("Net.SSLSessionConcurrentLookupCount",
+ ssl_session_cache_lookup_count_, 20);
+ }
+
// DHE is offered on the deprecated cipher fallback and then rejected
// afterwards. This is to aid in diagnosing connection failures because a
// server requires DHE ciphers.
@@ -1146,11 +1194,6 @@ int SSLClientSocketImpl::DoHandshakeComplete(int result) {
const uint8_t* ocsp_response_raw;
size_t ocsp_response_len;
SSL_get0_ocsp_response(ssl_.get(), &ocsp_response_raw, &ocsp_response_len);
- std::string ocsp_response;
- if (ocsp_response_len > 0) {
- ocsp_response_.assign(reinterpret_cast<const char*>(ocsp_response_raw),
- ocsp_response_len);
- }
set_stapled_ocsp_response_received(ocsp_response_len != 0);
UMA_HISTOGRAM_BOOLEAN("Net.OCSPResponseStapled", ocsp_response_len != 0);
@@ -1232,10 +1275,16 @@ int SSLClientSocketImpl::DoVerifyCert(int result) {
start_cert_verification_time_ = base::TimeTicks::Now();
+ const uint8_t* ocsp_response_raw;
+ size_t ocsp_response_len;
+ SSL_get0_ocsp_response(ssl_.get(), &ocsp_response_raw, &ocsp_response_len);
+ base::StringPiece ocsp_response(
+ reinterpret_cast<const char*>(ocsp_response_raw), ocsp_response_len);
+
return cert_verifier_->Verify(
CertVerifier::RequestParams(server_cert_, host_and_port_.host(),
ssl_config_.GetCertVerifyFlags(),
- ocsp_response_, CertificateList()),
+ ocsp_response.as_string(), CertificateList()),
// TODO(davidben): Route the CRLSet through SSLConfig so
// SSLClientSocket doesn't depend on SSLConfigService.
SSLConfigService::GetCRLSet().get(), &server_cert_verify_result_,
@@ -1293,8 +1342,15 @@ int SSLClientSocketImpl::DoVerifyCertComplete(int result) {
SSLInfo ssl_info;
bool ok = GetSSLInfo(&ssl_info);
DCHECK(ok);
+
+ const uint8_t* ocsp_response_raw;
+ size_t ocsp_response_len;
+ SSL_get0_ocsp_response(ssl_.get(), &ocsp_response_raw, &ocsp_response_len);
+ base::StringPiece ocsp_response(
+ reinterpret_cast<const char*>(ocsp_response_raw), ocsp_response_len);
+
transport_security_state_->CheckExpectStaple(host_and_port_, ssl_info,
- ocsp_response_);
+ ocsp_response);
}
completed_connect_ = true;
@@ -1330,7 +1386,7 @@ void SSLClientSocketImpl::OnHandshakeIOComplete(int result) {
}
int SSLClientSocketImpl::DoHandshakeLoop(int last_io_result) {
- TRACE_EVENT0("net", "SSLClientSocketImpl::DoHandshakeLoop");
+ TRACE_EVENT0(kNetTracingCategory, "SSLClientSocketImpl::DoHandshakeLoop");
int rv = last_io_result;
do {
// Default to STATE_NONE for next state.
@@ -1531,15 +1587,20 @@ int SSLClientSocketImpl::VerifyCT() {
const uint8_t* sct_list_raw;
size_t sct_list_len;
SSL_get0_signed_cert_timestamp_list(ssl_.get(), &sct_list_raw, &sct_list_len);
- std::string sct_list;
- if (sct_list_len > 0)
- sct_list.assign(reinterpret_cast<const char*>(sct_list_raw), sct_list_len);
+ base::StringPiece sct_list(reinterpret_cast<const char*>(sct_list_raw),
+ sct_list_len);
+
+ const uint8_t* ocsp_response_raw;
+ size_t ocsp_response_len;
+ SSL_get0_ocsp_response(ssl_.get(), &ocsp_response_raw, &ocsp_response_len);
+ base::StringPiece ocsp_response(
+ reinterpret_cast<const char*>(ocsp_response_raw), ocsp_response_len);
// Note that this is a completely synchronous operation: The CT Log Verifier
// gets all the data it needs for SCT verification and does not do any
// external communication.
cert_transparency_verifier_->Verify(
- server_cert_verify_result_.verified_cert.get(), ocsp_response_, sct_list,
+ server_cert_verify_result_.verified_cert.get(), ocsp_response, sct_list,
&ct_verify_result_.scts, net_log_);
ct_verify_result_.ct_policies_applied = true;
@@ -1603,26 +1664,8 @@ int SSLClientSocketImpl::ClientCertRequestCallback(SSL* ssl) {
#else // !defined(OS_IOS)
if (!ssl_config_.send_client_cert) {
// First pass: we know that a client certificate is needed, but we do not
- // have one at hand.
- STACK_OF(X509_NAME)* authorities = SSL_get_client_CA_list(ssl);
- for (size_t i = 0; i < sk_X509_NAME_num(authorities); i++) {
- X509_NAME* ca_name = (X509_NAME*)sk_X509_NAME_value(authorities, i);
- unsigned char* str = NULL;
- int length = i2d_X509_NAME(ca_name, &str);
- cert_authorities_.push_back(std::string(
- reinterpret_cast<const char*>(str), static_cast<size_t>(length)));
- OPENSSL_free(str);
- }
-
- const unsigned char* client_cert_types;
- size_t num_client_cert_types =
- SSL_get0_certificate_types(ssl, &client_cert_types);
- for (size_t i = 0; i < num_client_cert_types; i++) {
- cert_key_types_.push_back(
- static_cast<SSLClientCertType>(client_cert_types[i]));
- }
-
- // Suspends handshake. SSL_get_error will return SSL_ERROR_WANT_X509_LOOKUP.
+ // have one at hand. Suspend the handshake. SSL_get_error will return
+ // SSL_ERROR_WANT_X509_LOOKUP.
return -1;
}
diff --git a/chromium/net/socket/ssl_client_socket_impl.h b/chromium/net/socket/ssl_client_socket_impl.h
index de677ba3713..86505ab2f4a 100644
--- a/chromium/net/socket/ssl_client_socket_impl.h
+++ b/chromium/net/socket/ssl_client_socket_impl.h
@@ -37,6 +37,9 @@
namespace base {
class FilePath;
class SequencedTaskRunner;
+namespace trace_event {
+class ProcessMemoryDump;
+}
}
namespace crypto {
@@ -107,13 +110,18 @@ class SSLClientSocketImpl : public SSLClientSocket,
void SetSubresourceSpeculation() override;
void SetOmniboxSpeculation() override;
bool WasEverUsed() const override;
- bool WasNpnNegotiated() const override;
+ bool WasAlpnNegotiated() const override;
NextProto GetNegotiatedProtocol() const override;
bool GetSSLInfo(SSLInfo* ssl_info) override;
void GetConnectionAttempts(ConnectionAttempts* out) const override;
void ClearConnectionAttempts() override {}
void AddConnectionAttempts(const ConnectionAttempts& attempts) override {}
int64_t GetTotalReceivedBytes() const override;
+ void DumpMemoryStats(SocketMemoryStats* stats) const override;
+
+ // Dumps memory allocation stats. |pmd| is the browser process memory dump.
+ static void DumpSSLClientSessionMemoryStats(
+ base::trace_event::ProcessMemoryDump* pmd);
// Socket implementation.
int Read(IOBuffer* buf,
@@ -267,20 +275,12 @@ class SSLClientSocketImpl : public SSLClientSocket,
std::unique_ptr<PeerCertificateChain> server_cert_chain_;
scoped_refptr<X509Certificate> server_cert_;
CertVerifyResult server_cert_verify_result_;
- std::string ocsp_response_;
bool completed_connect_;
// Set when Read() or Write() successfully reads or writes data to or from the
// network.
bool was_ever_used_;
- // List of DER-encoded X.509 DistinguishedName of certificate authorities
- // allowed by the server.
- std::vector<std::string> cert_authorities_;
- // List of SSLClientCertType values for client certificates allowed by the
- // server.
- std::vector<SSLClientCertType> cert_key_types_;
-
CertVerifier* const cert_verifier_;
std::unique_ptr<CertVerifier::Request> cert_verifier_request_;
base::TimeTicks start_cert_verification_time_;
@@ -306,6 +306,7 @@ class SSLClientSocketImpl : public SSLClientSocket,
// session cache. i.e. sessions created with one value will not attempt to
// resume on the socket with a different value.
const std::string ssl_session_cache_shard_;
+ int ssl_session_cache_lookup_count_;
enum State {
STATE_NONE,
diff --git a/chromium/net/socket/ssl_client_socket_pool.cc b/chromium/net/socket/ssl_client_socket_pool.cc
index b6cb5cd2ab9..d98f6b00542 100644
--- a/chromium/net/socket/ssl_client_socket_pool.cc
+++ b/chromium/net/socket/ssl_client_socket_pool.cc
@@ -16,6 +16,7 @@
#include "base/values.h"
#include "net/base/host_port_pair.h"
#include "net/base/net_errors.h"
+#include "net/base/trace_constants.h"
#include "net/http/http_proxy_client_socket.h"
#include "net/http/http_proxy_client_socket_pool.h"
#include "net/log/net_log_source_type.h"
@@ -114,7 +115,7 @@ SSLConnectJob::SSLConnectJob(const std::string& group_name,
priority,
respect_limits,
delegate,
- NetLogWithSource::Make(net_log, NetLogSourceType::CONNECT_JOB)),
+ NetLogWithSource::Make(net_log, NetLogSourceType::SSL_CONNECT_JOB)),
params_(params),
transport_pool_(transport_pool),
socks_pool_(socks_pool),
@@ -176,7 +177,7 @@ void SSLConnectJob::OnIOComplete(int result) {
}
int SSLConnectJob::DoLoop(int result) {
- TRACE_EVENT0("net", "SSLConnectJob::DoLoop");
+ TRACE_EVENT0(kNetTracingCategory, "SSLConnectJob::DoLoop");
DCHECK_NE(next_state_, STATE_NONE);
int rv = result;
@@ -294,7 +295,7 @@ int SSLConnectJob::DoTunnelConnectComplete(int result) {
}
int SSLConnectJob::DoSSLConnect() {
- TRACE_EVENT0("net", "SSLConnectJob::DoSSLConnect");
+ TRACE_EVENT0(kNetTracingCategory, "SSLConnectJob::DoSSLConnect");
// TODO(pkasting): Remove ScopedTracker below once crbug.com/462815 is fixed.
tracked_objects::ScopedTracker tracking_profile(
FROM_HERE_WITH_EXPLICIT_FUNCTION("462815 SSLConnectJob::DoSSLConnect"));
@@ -376,9 +377,6 @@ int SSLConnectJob::DoSSLConnectComplete(int result) {
SSLConnectionStatusToCipherSuite(ssl_info.connection_status);
UMA_HISTOGRAM_SPARSE_SLOWLY("Net.SSL_CipherSuite", cipher_suite);
- const SSL_CIPHER* cipher = SSL_get_cipher_by_value(cipher_suite);
- bool is_cecpq1 = cipher && SSL_CIPHER_is_CECPQ1(cipher);
-
if (ssl_info.key_exchange_group != 0) {
UMA_HISTOGRAM_SPARSE_SLOWLY("Net.SSL_KeyExchange.ECDHE",
ssl_info.key_exchange_group);
@@ -422,27 +420,6 @@ int SSLConnectJob::DoSSLConnectComplete(int result) {
base::TimeDelta::FromMilliseconds(1),
base::TimeDelta::FromMinutes(1),
100);
-
- // These are hosts that we expect to always offer CECPQ1. Connections
- // to them, whether or not this browser is in the experiment group, form
- // the basis of our comparisons.
- bool cecpq1_expected_to_be_offered =
- ssl_info.is_issued_by_known_root &&
- (host == "play.google.com" || host == "checkout.google.com" ||
- host == "wallet.google.com");
- if (cecpq1_expected_to_be_offered) {
- UMA_HISTOGRAM_CUSTOM_TIMES(
- "Net.SSL_Connection_Latency_PostQuantumSupported_Full_Handshake",
- connect_duration, base::TimeDelta::FromMilliseconds(1),
- base::TimeDelta::FromMinutes(1), 100);
- if (SSLClientSocket::IsPostQuantumExperimentEnabled()) {
- // But don't trust that these hosts offer CECPQ1: make sure. If
- // we're doing everything right on the server side, |is_cecpq1|
- // should always be true if we get here, modulo MITM.
- UMA_HISTOGRAM_BOOLEAN("Net.SSL_Connection_PostQuantum_Negotiated",
- is_cecpq1);
- }
- }
}
}
}
@@ -637,6 +614,12 @@ LoadState SSLClientSocketPool::GetLoadState(
return base_.GetLoadState(group_name, handle);
}
+void SSLClientSocketPool::DumpMemoryStats(
+ base::trace_event::ProcessMemoryDump* pmd,
+ const std::string& parent_dump_absolute_name) const {
+ base_.DumpMemoryStats(pmd, parent_dump_absolute_name);
+}
+
std::unique_ptr<base::DictionaryValue> SSLClientSocketPool::GetInfoAsValue(
const std::string& name,
const std::string& type,
diff --git a/chromium/net/socket/ssl_client_socket_pool.h b/chromium/net/socket/ssl_client_socket_pool.h
index e7b7e8c9259..c02fe98150f 100644
--- a/chromium/net/socket/ssl_client_socket_pool.h
+++ b/chromium/net/socket/ssl_client_socket_pool.h
@@ -233,6 +233,11 @@ class NET_EXPORT_PRIVATE SSLClientSocketPool
LoadState GetLoadState(const std::string& group_name,
const ClientSocketHandle* handle) const override;
+ // Dumps memory allocation stats. |parent_dump_absolute_name| is the name
+ // used by the parent MemoryAllocatorDump in the memory dump hierarchy.
+ void DumpMemoryStats(base::trace_event::ProcessMemoryDump* pmd,
+ const std::string& parent_dump_absolute_name) const;
+
std::unique_ptr<base::DictionaryValue> GetInfoAsValue(
const std::string& name,
const std::string& type,
diff --git a/chromium/net/socket/ssl_client_socket_pool_unittest.cc b/chromium/net/socket/ssl_client_socket_pool_unittest.cc
index 3a8537f1421..26c722fae41 100644
--- a/chromium/net/socket/ssl_client_socket_pool_unittest.cc
+++ b/chromium/net/socket/ssl_client_socket_pool_unittest.cc
@@ -408,7 +408,7 @@ TEST_F(SSLClientSocketPoolTest, DirectWithNPN) {
EXPECT_TRUE(handle.socket());
TestLoadTimingInfo(handle);
SSLClientSocket* ssl_socket = static_cast<SSLClientSocket*>(handle.socket());
- EXPECT_TRUE(ssl_socket->WasNpnNegotiated());
+ EXPECT_TRUE(ssl_socket->WasAlpnNegotiated());
}
TEST_F(SSLClientSocketPoolTest, DirectNoSPDY) {
@@ -463,7 +463,7 @@ TEST_F(SSLClientSocketPoolTest, DirectGotSPDY) {
TestLoadTimingInfo(handle);
SSLClientSocket* ssl_socket = static_cast<SSLClientSocket*>(handle.socket());
- EXPECT_TRUE(ssl_socket->WasNpnNegotiated());
+ EXPECT_TRUE(ssl_socket->WasAlpnNegotiated());
EXPECT_EQ(kProtoHTTP2, ssl_socket->GetNegotiatedProtocol());
}
@@ -493,7 +493,7 @@ TEST_F(SSLClientSocketPoolTest, DirectGotBonusSPDY) {
TestLoadTimingInfo(handle);
SSLClientSocket* ssl_socket = static_cast<SSLClientSocket*>(handle.socket());
- EXPECT_TRUE(ssl_socket->WasNpnNegotiated());
+ EXPECT_TRUE(ssl_socket->WasAlpnNegotiated());
EXPECT_EQ(kProtoHTTP2, ssl_socket->GetNegotiatedProtocol());
}
diff --git a/chromium/net/socket/ssl_client_socket_unittest.cc b/chromium/net/socket/ssl_client_socket_unittest.cc
index d451d31c2e9..58c7fa811de 100644
--- a/chromium/net/socket/ssl_client_socket_unittest.cc
+++ b/chromium/net/socket/ssl_client_socket_unittest.cc
@@ -18,6 +18,7 @@
#include "base/single_thread_task_runner.h"
#include "base/threading/thread_task_runner_handle.h"
#include "base/time/time.h"
+#include "base/values.h"
#include "net/base/address_list.h"
#include "net/base/io_buffer.h"
#include "net/base/net_errors.h"
@@ -26,6 +27,7 @@
#include "net/cert/ct_policy_enforcer.h"
#include "net/cert/ct_policy_status.h"
#include "net/cert/ct_verifier.h"
+#include "net/cert/do_nothing_ct_verifier.h"
#include "net/cert/mock_cert_verifier.h"
#include "net/cert/signed_certificate_timestamp_and_status.h"
#include "net/cert/test_root_certs.h"
@@ -42,6 +44,7 @@
#include "net/socket/client_socket_factory.h"
#include "net/socket/client_socket_handle.h"
#include "net/socket/socket_test_util.h"
+#include "net/socket/stream_socket.h"
#include "net/socket/tcp_client_socket.h"
#include "net/ssl/channel_id_service.h"
#include "net/ssl/default_channel_id_store.h"
@@ -109,8 +112,8 @@ class WrappedStreamSocket : public StreamSocket {
}
void SetOmniboxSpeculation() override { transport_->SetOmniboxSpeculation(); }
bool WasEverUsed() const override { return transport_->WasEverUsed(); }
- bool WasNpnNegotiated() const override {
- return transport_->WasNpnNegotiated();
+ bool WasAlpnNegotiated() const override {
+ return transport_->WasAlpnNegotiated();
}
NextProto GetNegotiatedProtocol() const override {
return transport_->GetNegotiatedProtocol();
@@ -702,11 +705,11 @@ class AsyncFailingChannelIDStore : public ChannelIDStore {
class MockCTVerifier : public CTVerifier {
public:
MOCK_METHOD5(Verify,
- int(X509Certificate*,
- const std::string&,
- const std::string&,
- SignedCertificateTimestampAndStatusList*,
- const NetLogWithSource&));
+ void(X509Certificate*,
+ base::StringPiece,
+ base::StringPiece,
+ SignedCertificateTimestampAndStatusList*,
+ const NetLogWithSource&));
MOCK_METHOD1(SetObserver, void(CTVerifier::Observer*));
};
@@ -736,7 +739,7 @@ class SSLClientSocketTest : public PlatformTest {
: socket_factory_(ClientSocketFactory::GetDefaultFactory()),
cert_verifier_(new MockCertVerifier),
transport_security_state_(new TransportSecurityState),
- ct_verifier_(new MockCTVerifier),
+ ct_verifier_(new DoNothingCTVerifier),
ct_policy_enforcer_(new MockCTPolicyEnforcer) {
cert_verifier_->set_default_result(OK);
context_.cert_verifier = cert_verifier_.get();
@@ -744,8 +747,6 @@ class SSLClientSocketTest : public PlatformTest {
context_.cert_transparency_verifier = ct_verifier_.get();
context_.ct_policy_enforcer = ct_policy_enforcer_.get();
- EXPECT_CALL(*ct_verifier_, Verify(_, _, _, _, _))
- .WillRepeatedly(Return(OK));
EXPECT_CALL(*ct_policy_enforcer_, DoesConformToCertPolicy(_, _, _))
.WillRepeatedly(
Return(ct::CertPolicyCompliance::CERT_POLICY_COMPLIES_VIA_SCTS));
@@ -843,7 +844,7 @@ class SSLClientSocketTest : public PlatformTest {
ClientSocketFactory* socket_factory_;
std::unique_ptr<MockCertVerifier> cert_verifier_;
std::unique_ptr<TransportSecurityState> transport_security_state_;
- std::unique_ptr<MockCTVerifier> ct_verifier_;
+ std::unique_ptr<DoNothingCTVerifier> ct_verifier_;
std::unique_ptr<MockCTPolicyEnforcer> ct_policy_enforcer_;
SSLClientSocketContext context_;
std::unique_ptr<SSLClientSocket> sock_;
@@ -2298,9 +2299,11 @@ TEST_F(SSLClientSocketCertRequestInfoTest, CertKeyTypes) {
}
TEST_F(SSLClientSocketTest, ConnectSignedCertTimestampsEnabledTLSExtension) {
- SpawnedTestServer::SSLOptions ssl_options;
- ssl_options.signed_cert_timestamps_tls_ext = "test";
+ // Encoding of SCT List containing 'test'.
+ base::StringPiece sct_ext("\x00\x06\x00\x04test", 8);
+ SpawnedTestServer::SSLOptions ssl_options;
+ ssl_options.signed_cert_timestamps_tls_ext = sct_ext.as_string();
ASSERT_TRUE(StartTestServer(ssl_options));
SSLConfig ssl_config;
@@ -2309,9 +2312,11 @@ TEST_F(SSLClientSocketTest, ConnectSignedCertTimestampsEnabledTLSExtension) {
MockCTVerifier ct_verifier;
SetCTVerifier(&ct_verifier);
- // Check that the SCT list is extracted as expected.
- EXPECT_CALL(ct_verifier, Verify(_, "", "test", _, _)).WillRepeatedly(
- Return(ERR_CT_NO_SCTS_VERIFIED_OK));
+ // Check that the SCT list is extracted from the TLS extension as expected,
+ // while also simulating that it was an unparsable response.
+ SignedCertificateTimestampAndStatusList sct_list;
+ EXPECT_CALL(ct_verifier, Verify(_, _, sct_ext, _, _))
+ .WillOnce(testing::SetArgPointee<3>(sct_list));
int rv;
ASSERT_TRUE(CreateAndConnectSSLClientSocket(ssl_config, &rv));
@@ -2320,27 +2325,6 @@ TEST_F(SSLClientSocketTest, ConnectSignedCertTimestampsEnabledTLSExtension) {
EXPECT_TRUE(sock_->signed_cert_timestamps_received_);
}
-// Test that when an EV certificate is received, but no CT verifier
-// or certificate policy enforcer are defined, then the EV status
-// of the certificate is maintained.
-TEST_F(SSLClientSocketTest, EVCertStatusMaintainedNoCTVerifier) {
- SpawnedTestServer::SSLOptions ssl_options;
- ASSERT_TRUE(StartTestServer(ssl_options));
-
- SSLConfig ssl_config;
- AddServerCertStatusToSSLConfig(CERT_STATUS_IS_EV, &ssl_config);
-
- // No verifier to skip CT and policy checks.
- int rv;
- ASSERT_TRUE(CreateAndConnectSSLClientSocket(ssl_config, &rv));
- EXPECT_THAT(rv, IsOk());
-
- SSLInfo result;
- ASSERT_TRUE(sock_->GetSSLInfo(&result));
-
- EXPECT_TRUE(result.cert_status & CERT_STATUS_IS_EV);
-}
-
// Test that when a CT verifier and a CTPolicyEnforcer are defined, and
// the EV certificate used conforms to the CT/EV policy, its EV status
// is maintained.
@@ -2351,12 +2335,6 @@ TEST_F(SSLClientSocketTest, EVCertStatusMaintainedForCompliantCert) {
SSLConfig ssl_config;
AddServerCertStatusToSSLConfig(CERT_STATUS_IS_EV, &ssl_config);
- // To activate the CT/EV policy enforcement non-null CTVerifier and
- // CTPolicyEnforcer are needed.
- MockCTVerifier ct_verifier;
- SetCTVerifier(&ct_verifier);
- EXPECT_CALL(ct_verifier, Verify(_, "", "", _, _)).WillRepeatedly(Return(OK));
-
// Emulate compliance of the certificate to the policy.
MockCTPolicyEnforcer policy_enforcer;
SetCTPolicyEnforcer(&policy_enforcer);
@@ -2387,12 +2365,6 @@ TEST_F(SSLClientSocketTest, EVCertStatusRemovedForNonCompliantCert) {
SSLConfig ssl_config;
AddServerCertStatusToSSLConfig(CERT_STATUS_IS_EV, &ssl_config);
- // To activate the CT/EV policy enforcement non-null CTVerifier and
- // CTPolicyEnforcer are needed.
- MockCTVerifier ct_verifier;
- SetCTVerifier(&ct_verifier);
- EXPECT_CALL(ct_verifier, Verify(_, "", "", _, _)).WillRepeatedly(Return(OK));
-
// Emulate non-compliance of the certificate to the policy.
MockCTPolicyEnforcer policy_enforcer;
SetCTPolicyEnforcer(&policy_enforcer);
@@ -2414,20 +2386,6 @@ TEST_F(SSLClientSocketTest, EVCertStatusRemovedForNonCompliantCert) {
EXPECT_TRUE(result.cert_status & CERT_STATUS_CT_COMPLIANCE_FAILED);
}
-namespace {
-
-bool IsValidOCSPResponse(const base::StringPiece& input) {
- der::Parser parser((der::Input(input)));
- der::Parser sequence;
- return parser.ReadSequence(&sequence) && !parser.HasMore() &&
- sequence.SkipTag(der::kEnumerated) &&
- sequence.SkipTag(der::kTagContextSpecific | der::kTagConstructed |
- 0) &&
- !sequence.HasMore();
-}
-
-} // namespace
-
// Test that enabling Signed Certificate Timestamps enables OCSP stapling.
TEST_F(SSLClientSocketTest, ConnectSignedCertTimestampsEnabledOCSP) {
SpawnedTestServer::SSLOptions ssl_options;
@@ -2444,18 +2402,6 @@ TEST_F(SSLClientSocketTest, ConnectSignedCertTimestampsEnabledOCSP) {
// is able to process the OCSP status itself.
ssl_config.signed_cert_timestamps_enabled = true;
- MockCTVerifier ct_verifier;
- SetCTVerifier(&ct_verifier);
-
- // Check that the OCSP response is extracted and well-formed. It should be the
- // DER encoding of an OCSPResponse (RFC 2560), so check that it consists of a
- // SEQUENCE of an ENUMERATED type and an element tagged with [0] EXPLICIT. In
- // particular, it should not include the overall two-byte length prefix from
- // TLS.
- EXPECT_CALL(ct_verifier,
- Verify(_, Truly(IsValidOCSPResponse), "", _, _)).WillRepeatedly(
- Return(ERR_CT_NO_SCTS_VERIFIED_OK));
-
int rv;
ASSERT_TRUE(CreateAndConnectSSLClientSocket(ssl_config, &rv));
EXPECT_THAT(rv, IsOk());
@@ -3672,4 +3618,33 @@ TEST_F(SSLClientSocketTest, AccessDeniedClientCerts) {
EXPECT_THAT(rv, IsError(ERR_BAD_SSL_CLIENT_AUTH_CERT));
}
+// Basic test for dumping memory stats.
+TEST_F(SSLClientSocketTest, DumpMemoryStats) {
+ ASSERT_TRUE(StartTestServer(SpawnedTestServer::SSLOptions()));
+
+ int rv;
+ ASSERT_TRUE(CreateAndConnectSSLClientSocket(SSLConfig(), &rv));
+ EXPECT_THAT(rv, IsOk());
+ StreamSocket::SocketMemoryStats stats;
+ sock_->DumpMemoryStats(&stats);
+ EXPECT_EQ(0u, stats.buffer_size);
+ EXPECT_EQ(1u, stats.cert_count);
+ EXPECT_LT(0u, stats.serialized_cert_size);
+ EXPECT_EQ(stats.serialized_cert_size, stats.total_size);
+
+ // Read the response without writing a request, so the read will be pending.
+ TestCompletionCallback read_callback;
+ scoped_refptr<IOBuffer> buf(new IOBuffer(4096));
+ rv = sock_->Read(buf.get(), 4096, read_callback.callback());
+ EXPECT_EQ(ERR_IO_PENDING, rv);
+
+ // Dump memory again and check that |buffer_size| contain the read buffer.
+ StreamSocket::SocketMemoryStats stats2;
+ sock_->DumpMemoryStats(&stats2);
+ EXPECT_EQ(17 * 1024u, stats2.buffer_size);
+ EXPECT_EQ(1u, stats2.cert_count);
+ EXPECT_LT(0u, stats2.serialized_cert_size);
+ EXPECT_LT(17 * 1024u, stats2.total_size);
+}
+
} // namespace net
diff --git a/chromium/net/socket/ssl_server_socket_impl.cc b/chromium/net/socket/ssl_server_socket_impl.cc
index 3e3f79b2003..4337aa10531 100644
--- a/chromium/net/socket/ssl_server_socket_impl.cc
+++ b/chromium/net/socket/ssl_server_socket_impl.cc
@@ -94,7 +94,7 @@ class SSLServerSocketImpl : public SSLServerSocket,
void SetSubresourceSpeculation() override;
void SetOmniboxSpeculation() override;
bool WasEverUsed() const override;
- bool WasNpnNegotiated() const override;
+ bool WasAlpnNegotiated() const override;
NextProto GetNegotiatedProtocol() const override;
bool GetSSLInfo(SSLInfo* ssl_info) override;
void GetConnectionAttempts(ConnectionAttempts* out) const override;
@@ -328,13 +328,13 @@ bool SSLServerSocketImpl::WasEverUsed() const {
return transport_socket_->WasEverUsed();
}
-bool SSLServerSocketImpl::WasNpnNegotiated() const {
+bool SSLServerSocketImpl::WasAlpnNegotiated() const {
NOTIMPLEMENTED();
return false;
}
NextProto SSLServerSocketImpl::GetNegotiatedProtocol() const {
- // NPN is not supported by this class.
+ // ALPN is not supported by this class.
return kProtoUnknown;
}
@@ -355,9 +355,6 @@ bool SSLServerSocketImpl::GetSSLInfo(SSLInfo* ssl_info) {
SSLConnectionStatusSetVersion(GetNetSSLVersion(ssl_.get()),
&ssl_info->connection_status);
- if (!SSL_get_secure_renegotiation_support(ssl_.get()))
- ssl_info->connection_status |= SSL_CONNECTION_NO_RENEGOTIATION_EXTENSION;
-
ssl_info->handshake_type = SSL_session_reused(ssl_.get())
? SSLInfo::HANDSHAKE_RESUME
: SSLInfo::HANDSHAKE_FULL;
diff --git a/chromium/net/socket/ssl_server_socket_impl.h b/chromium/net/socket/ssl_server_socket_impl.h
index d2061982122..7e262da6133 100644
--- a/chromium/net/socket/ssl_server_socket_impl.h
+++ b/chromium/net/socket/ssl_server_socket_impl.h
@@ -18,8 +18,6 @@
namespace net {
-class SSLInfo;
-
class SSLServerContextImpl : public SSLServerContext {
public:
SSLServerContextImpl(X509Certificate* certificate,
diff --git a/chromium/net/socket/ssl_server_socket_unittest.cc b/chromium/net/socket/ssl_server_socket_unittest.cc
index fe9953da02a..d99008c2642 100644
--- a/chromium/net/socket/ssl_server_socket_unittest.cc
+++ b/chromium/net/socket/ssl_server_socket_unittest.cc
@@ -45,7 +45,7 @@
#include "net/cert/cert_status_flags.h"
#include "net/cert/ct_policy_enforcer.h"
#include "net/cert/ct_policy_status.h"
-#include "net/cert/ct_verifier.h"
+#include "net/cert/do_nothing_ct_verifier.h"
#include "net/cert/mock_cert_verifier.h"
#include "net/cert/mock_client_cert_verifier.h"
#include "net/cert/signed_certificate_timestamp_and_status.h"
@@ -86,22 +86,6 @@ const char kWrongClientCertFileName[] = "client_2.pem";
const char kWrongClientPrivateKeyFileName[] = "client_2.pk8";
const char kClientCertCAFileName[] = "client_1_ca.pem";
-class MockCTVerifier : public CTVerifier {
- public:
- MockCTVerifier() = default;
- ~MockCTVerifier() override = default;
-
- int Verify(X509Certificate* cert,
- const std::string& stapled_ocsp_response,
- const std::string& sct_list_from_tls_extension,
- SignedCertificateTimestampAndStatusList* output_scts,
- const NetLogWithSource& net_log) override {
- return net::OK;
- }
-
- void SetObserver(Observer* observer) override {}
-};
-
class MockCTPolicyEnforcer : public CTPolicyEnforcer {
public:
MockCTPolicyEnforcer() = default;
@@ -298,7 +282,7 @@ class FakeSocket : public StreamSocket {
bool WasEverUsed() const override { return true; }
- bool WasNpnNegotiated() const override { return false; }
+ bool WasAlpnNegotiated() const override { return false; }
NextProto GetNegotiatedProtocol() const override { return kProtoUnknown; }
@@ -374,7 +358,7 @@ class SSLServerSocketTest : public PlatformTest {
cert_verifier_(new MockCertVerifier()),
client_cert_verifier_(new MockClientCertVerifier()),
transport_security_state_(new TransportSecurityState),
- ct_verifier_(new MockCTVerifier),
+ ct_verifier_(new DoNothingCTVerifier),
ct_policy_enforcer_(new MockCTPolicyEnforcer) {}
void SetUp() override {
@@ -509,7 +493,7 @@ class SSLServerSocketTest : public PlatformTest {
std::unique_ptr<MockCertVerifier> cert_verifier_;
std::unique_ptr<MockClientCertVerifier> client_cert_verifier_;
std::unique_ptr<TransportSecurityState> transport_security_state_;
- std::unique_ptr<MockCTVerifier> ct_verifier_;
+ std::unique_ptr<DoNothingCTVerifier> ct_verifier_;
std::unique_ptr<MockCTPolicyEnforcer> ct_policy_enforcer_;
std::unique_ptr<SSLServerContext> server_context_;
std::unique_ptr<crypto::RSAPrivateKey> server_private_key_;
diff --git a/chromium/net/socket/stream_socket.cc b/chromium/net/socket/stream_socket.cc
index 650f388f692..d435fc3ae57 100644
--- a/chromium/net/socket/stream_socket.cc
+++ b/chromium/net/socket/stream_socket.cc
@@ -98,4 +98,9 @@ void StreamSocket::UseHistory::EmitPreconnectionHistograms() const {
UMA_HISTOGRAM_ENUMERATION("Net.PreconnectUtilization2", result, 9);
}
+StreamSocket::SocketMemoryStats::SocketMemoryStats()
+ : total_size(0), buffer_size(0), cert_count(0), serialized_cert_size(0) {}
+
+StreamSocket::SocketMemoryStats::~SocketMemoryStats() {}
+
} // namespace net
diff --git a/chromium/net/socket/stream_socket.h b/chromium/net/socket/stream_socket.h
index 4ed735af04f..fe2f0a6951a 100644
--- a/chromium/net/socket/stream_socket.h
+++ b/chromium/net/socket/stream_socket.h
@@ -15,13 +15,31 @@
namespace net {
-class AddressList;
class IPEndPoint;
class NetLogWithSource;
class SSLInfo;
class NET_EXPORT_PRIVATE StreamSocket : public Socket {
public:
+ // This is used in DumpMemoryStats() to track the estimate of memory usage of
+ // a socket.
+ struct NET_EXPORT_PRIVATE SocketMemoryStats {
+ public:
+ SocketMemoryStats();
+ ~SocketMemoryStats();
+ // Estimated total memory usage of this socket in bytes.
+ size_t total_size;
+ // Size of all buffers used by this socket in bytes.
+ size_t buffer_size;
+ // Number of certs used by this socket.
+ size_t cert_count;
+ // Total size of certs used by this socket in bytes.
+ size_t serialized_cert_size;
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(SocketMemoryStats);
+ };
+
~StreamSocket() override {}
// Called to establish a connection. Returns OK if the connection could be
@@ -84,11 +102,11 @@ class NET_EXPORT_PRIVATE StreamSocket : public Socket {
// Enables use of TCP FastOpen for the underlying transport socket.
virtual void EnableTCPFastOpenIfSupported() {}
- // Returns true if NPN was negotiated during the connection of this socket.
- virtual bool WasNpnNegotiated() const = 0;
+ // Returns true if ALPN was negotiated during the connection of this socket.
+ virtual bool WasAlpnNegotiated() const = 0;
- // Returns the protocol negotiated via NPN for this socket, or
- // kProtoUnknown will be returned if NPN is not applicable.
+ // Returns the protocol negotiated via ALPN for this socket, or
+ // kProtoUnknown will be returned if ALPN is not applicable.
virtual NextProto GetNegotiatedProtocol() const = 0;
// Gets the SSL connection information of the socket. Returns false if
@@ -111,6 +129,11 @@ class NET_EXPORT_PRIVATE StreamSocket : public Socket {
// Disconnect() is called.
virtual int64_t GetTotalReceivedBytes() const = 0;
+ // Dumps memory allocation stats into |stats|. |stats| can be assumed as being
+ // default initialized upon entry. Implementations should override fields in
+ // |stats|. Default implementation does nothing.
+ virtual void DumpMemoryStats(SocketMemoryStats* stats) const {}
+
protected:
// The following class is only used to gather statistics about the history of
// a socket. It is only instantiated and used in basic sockets, such as
diff --git a/chromium/net/socket/tcp_client_socket.cc b/chromium/net/socket/tcp_client_socket.cc
index f8f61229529..01ce316ee14 100644
--- a/chromium/net/socket/tcp_client_socket.cc
+++ b/chromium/net/socket/tcp_client_socket.cc
@@ -257,7 +257,7 @@ void TCPClientSocket::EnableTCPFastOpenIfSupported() {
socket_->EnableTCPFastOpenIfSupported();
}
-bool TCPClientSocket::WasNpnNegotiated() const {
+bool TCPClientSocket::WasAlpnNegotiated() const {
return false;
}
diff --git a/chromium/net/socket/tcp_client_socket.h b/chromium/net/socket/tcp_client_socket.h
index 295e8b68113..65a51837103 100644
--- a/chromium/net/socket/tcp_client_socket.h
+++ b/chromium/net/socket/tcp_client_socket.h
@@ -58,7 +58,7 @@ class NET_EXPORT TCPClientSocket : public StreamSocket {
void SetOmniboxSpeculation() override;
bool WasEverUsed() const override;
void EnableTCPFastOpenIfSupported() override;
- bool WasNpnNegotiated() const override;
+ bool WasAlpnNegotiated() const override;
NextProto GetNegotiatedProtocol() const override;
bool GetSSLInfo(SSLInfo* ssl_info) override;
diff --git a/chromium/net/socket/tcp_socket_posix.cc b/chromium/net/socket/tcp_socket_posix.cc
index 2707b29dd4f..51f0818e4b6 100644
--- a/chromium/net/socket/tcp_socket_posix.cc
+++ b/chromium/net/socket/tcp_socket_posix.cc
@@ -16,7 +16,7 @@
#include "base/posix/eintr_wrapper.h"
#include "base/task_runner_util.h"
#include "base/threading/worker_pool.h"
-#include "base/time/default_tick_clock.h"
+#include "base/time/time.h"
#include "net/base/address_list.h"
#include "net/base/io_buffer.h"
#include "net/base/ip_endpoint.h"
@@ -145,8 +145,6 @@ TCPSocketPosix::TCPSocketPosix(
NetLog* net_log,
const NetLogSource& source)
: socket_performance_watcher_(std::move(socket_performance_watcher)),
- tick_clock_(new base::DefaultTickClock()),
- rtt_notifications_minimum_interval_(base::TimeDelta::FromSeconds(1)),
use_tcp_fastopen_(false),
tcp_fastopen_write_attempted_(false),
tcp_fastopen_connected_(false),
@@ -484,11 +482,6 @@ void TCPSocketPosix::EndLoggingMultipleConnectAttempts(int net_error) {
}
}
-void TCPSocketPosix::SetTickClockForTesting(
- std::unique_ptr<base::TickClock> tick_clock) {
- tick_clock_ = std::move(tick_clock);
-}
-
void TCPSocketPosix::AcceptCompleted(
std::unique_ptr<TCPSocketPosix>* tcp_socket,
IPEndPoint* address,
@@ -529,7 +522,7 @@ int TCPSocketPosix::BuildTcpSocketPosix(
tcp_socket->reset(
new TCPSocketPosix(nullptr, net_log_.net_log(), net_log_.source()));
- (*tcp_socket)->socket_.reset(accept_socket_.release());
+ (*tcp_socket)->socket_ = std::move(accept_socket_);
return OK;
}
@@ -724,13 +717,6 @@ int TCPSocketPosix::TcpFastOpenWrite(IOBuffer* buf,
void TCPSocketPosix::NotifySocketPerformanceWatcher() {
#if defined(TCP_INFO)
- const base::TimeTicks now_ticks = tick_clock_->NowTicks();
- // Do not notify |socket_performance_watcher_| if the last notification was
- // recent than |rtt_notifications_minimum_interval_| ago. This helps in
- // reducing the overall overhead of the tcp_info syscalls.
- if (now_ticks - last_rtt_notification_ < rtt_notifications_minimum_interval_)
- return;
-
// Check if |socket_performance_watcher_| is interested in receiving a RTT
// update notification.
if (!socket_performance_watcher_ ||
@@ -752,7 +738,6 @@ void TCPSocketPosix::NotifySocketPerformanceWatcher() {
socket_performance_watcher_->OnUpdatedRTTAvailable(
base::TimeDelta::FromMicroseconds(info.tcpi_rtt));
- last_rtt_notification_ = now_ticks;
#endif // defined(TCP_INFO)
}
diff --git a/chromium/net/socket/tcp_socket_posix.h b/chromium/net/socket/tcp_socket_posix.h
index fda90fcfd95..93b8261a1f4 100644
--- a/chromium/net/socket/tcp_socket_posix.h
+++ b/chromium/net/socket/tcp_socket_posix.h
@@ -12,7 +12,6 @@
#include "base/callback.h"
#include "base/compiler_specific.h"
#include "base/macros.h"
-#include "base/time/time.h"
#include "net/base/address_family.h"
#include "net/base/completion_callback.h"
#include "net/base/net_export.h"
@@ -20,7 +19,7 @@
#include "net/socket/socket_performance_watcher.h"
namespace base {
-class TickClock;
+class TimeDelta;
}
namespace net {
@@ -108,8 +107,6 @@ class NET_EXPORT TCPSocketPosix {
void StartLoggingMultipleConnectAttempts(const AddressList& addresses);
void EndLoggingMultipleConnectAttempts(int net_error);
- void SetTickClockForTesting(std::unique_ptr<base::TickClock> tick_clock);
-
const NetLogWithSource& net_log() const { return net_log_; }
private:
@@ -224,16 +221,6 @@ class NET_EXPORT TCPSocketPosix {
// |socket_performance_watcher_|. May be nullptr.
std::unique_ptr<SocketPerformanceWatcher> socket_performance_watcher_;
- std::unique_ptr<base::TickClock> tick_clock_;
-
- // Minimum interval betweeen consecutive notifications to
- // |socket_performance_watcher_|.
- const base::TimeDelta rtt_notifications_minimum_interval_;
-
- // Time when the |socket_performance_watcher_| was last notified of updated
- // RTT.
- base::TimeTicks last_rtt_notification_;
-
// Enables experimental TCP FastOpen option.
bool use_tcp_fastopen_;
diff --git a/chromium/net/socket/tcp_socket_unittest.cc b/chromium/net/socket/tcp_socket_unittest.cc
index b783e94b601..d9da13c660c 100644
--- a/chromium/net/socket/tcp_socket_unittest.cc
+++ b/chromium/net/socket/tcp_socket_unittest.cc
@@ -12,7 +12,6 @@
#include <vector>
#include "base/memory/ref_counted.h"
-#include "base/test/simple_test_tick_clock.h"
#include "base/time/time.h"
#include "net/base/address_list.h"
#include "net/base/io_buffer.h"
@@ -116,27 +115,20 @@ class TCPSocketTest : public PlatformTest {
#if defined(TCP_INFO) || defined(OS_LINUX)
// Tests that notifications to Socket Performance Watcher (SPW) are delivered
- // correctly. |advance_ticks| is the duration by which the clock is advanced
- // before a message is read. |should_notify_updated_rtt| is true if the SPW
- // is interested in receiving RTT notifications. |num_messages| is the number
- // of messages that are written/read by the sockets.
- // |expect_connection_changed_count| is the expected number of connection
- // change notifications received by the SPW. |expect_rtt_notification_count|
- // is the expected number of RTT notifications received by the SPW.
- // This test works by writing |num_messages| to the socket. A different
- // socket (with a SPW attached to it) reads the messages.
- void TestSPWNotifications(const base::TimeDelta& advance_ticks,
- bool should_notify_updated_rtt,
+ // correctly. |should_notify_updated_rtt| is true if the SPW is interested in
+ // receiving RTT notifications. |num_messages| is the number of messages that
+ // are written/read by the sockets. |expect_connection_changed_count| is the
+ // expected number of connection change notifications received by the SPW.
+ // |expect_rtt_notification_count| is the expected number of RTT
+ // notifications received by the SPW. This test works by writing
+ // |num_messages| to the socket. A different socket (with a SPW attached to
+ // it) reads the messages.
+ void TestSPWNotifications(bool should_notify_updated_rtt,
size_t num_messages,
size_t expect_connection_changed_count,
size_t expect_rtt_notification_count) {
ASSERT_NO_FATAL_FAILURE(SetUpListenIPv4());
- std::unique_ptr<base::SimpleTestTickClock> tick_clock(
- new base::SimpleTestTickClock());
- base::SimpleTestTickClock* tick_clock_ptr = tick_clock.get();
- tick_clock_ptr->SetNowTicks(base::TimeTicks::Now());
-
TestCompletionCallback connect_callback;
std::unique_ptr<TestSocketPerformanceWatcher> watcher(
@@ -144,7 +136,6 @@ class TCPSocketTest : public PlatformTest {
TestSocketPerformanceWatcher* watcher_ptr = watcher.get();
TCPSocket connecting_socket(std::move(watcher), NULL, NetLogSource());
- connecting_socket.SetTickClockForTesting(std::move(tick_clock));
int result = connecting_socket.Open(ADDRESS_FAMILY_IPV4);
ASSERT_THAT(result, IsOk());
@@ -165,8 +156,6 @@ class TCPSocketTest : public PlatformTest {
ASSERT_THAT(connect_callback.WaitForResult(), IsOk());
for (size_t i = 0; i < num_messages; ++i) {
- tick_clock_ptr->Advance(advance_ticks);
-
// Use a 1 byte message so that the watcher is notified at most once per
// message.
const std::string message("t");
@@ -396,22 +385,13 @@ TEST_F(TCPSocketTest, ReadWrite) {
// If SocketPerformanceWatcher::ShouldNotifyUpdatedRTT always returns false,
// then the wtatcher should not receive any notifications.
TEST_F(TCPSocketTest, SPWNotInterested) {
- TestSPWNotifications(base::TimeDelta::FromSeconds(0), false, 2u, 0u, 0u);
-}
-
-// One notification should be received when the socket connects. No additional
-// notifications should be received when the message is read because the clock
-// is not advanced.
-TEST_F(TCPSocketTest, SPWNoAdvance) {
- TestSPWNotifications(base::TimeDelta::FromSeconds(0), true, 2u, 0u, 1u);
+ TestSPWNotifications(false, 2u, 0u, 0u);
}
// One notification should be received when the socket connects. One
-// additional notification should be received for each message read since this
-// test advances clock by 2 seconds (which is longer than the minimum interval
-// between consecutive notifications) before every read.
-TEST_F(TCPSocketTest, SPWAdvance) {
- TestSPWNotifications(base::TimeDelta::FromSeconds(2), true, 2u, 0u, 3u);
+// additional notification should be received for each message read.
+TEST_F(TCPSocketTest, SPWNoAdvance) {
+ TestSPWNotifications(true, 2u, 0u, 3u);
}
#endif // defined(TCP_INFO) || defined(OS_LINUX)
diff --git a/chromium/net/socket/tcp_socket_win.cc b/chromium/net/socket/tcp_socket_win.cc
index d879a5ee95e..6bb5895eff1 100644
--- a/chromium/net/socket/tcp_socket_win.cc
+++ b/chromium/net/socket/tcp_socket_win.cc
@@ -40,7 +40,8 @@ const int kTCPKeepAliveSeconds = 45;
int SetSocketReceiveBufferSize(SOCKET socket, int32_t size) {
int rv = setsockopt(socket, SOL_SOCKET, SO_RCVBUF,
reinterpret_cast<const char*>(&size), sizeof(size));
- int net_error = (rv == 0) ? OK : MapSystemError(WSAGetLastError());
+ int os_error = WSAGetLastError();
+ int net_error = (rv == 0) ? OK : MapSystemError(os_error);
DCHECK(!rv) << "Could not set socket receive buffer size: " << net_error;
return net_error;
}
@@ -48,7 +49,8 @@ int SetSocketReceiveBufferSize(SOCKET socket, int32_t size) {
int SetSocketSendBufferSize(SOCKET socket, int32_t size) {
int rv = setsockopt(socket, SOL_SOCKET, SO_SNDBUF,
reinterpret_cast<const char*>(&size), sizeof(size));
- int net_error = (rv == 0) ? OK : MapSystemError(WSAGetLastError());
+ int os_error = WSAGetLastError();
+ int net_error = (rv == 0) ? OK : MapSystemError(os_error);
DCHECK(!rv) << "Could not set socket send buffer size: " << net_error;
return net_error;
}
@@ -67,8 +69,9 @@ bool SetTCPKeepAlive(SOCKET socket, BOOL enable, int delay_secs) {
int rv = WSAIoctl(socket, SIO_KEEPALIVE_VALS, &keepalive_vals,
sizeof(keepalive_vals), NULL, 0,
&bytes_returned, NULL, NULL);
+ int os_error = WSAGetLastError();
DCHECK(!rv) << "Could not enable TCP Keep-Alive for socket: " << socket
- << " [error: " << WSAGetLastError() << "].";
+ << " [error: " << os_error << "].";
// Disregard any failure in disabling nagle or enabling TCP Keep-Alive.
return rv == 0;
@@ -98,6 +101,13 @@ int MapConnectError(int os_error) {
}
}
+bool SetNonBlockingAndGetError(int fd, int* os_error) {
+ bool ret = base::SetNonBlocking(fd);
+ *os_error = WSAGetLastError();
+
+ return ret;
+}
+
} // namespace
//-----------------------------------------------------------------------------
@@ -276,13 +286,14 @@ int TCPSocketWin::Open(AddressFamily family) {
socket_ = CreatePlatformSocket(ConvertAddressFamily(family), SOCK_STREAM,
IPPROTO_TCP);
+ int os_error = WSAGetLastError();
if (socket_ == INVALID_SOCKET) {
PLOG(ERROR) << "CreatePlatformSocket() returned an error";
- return MapSystemError(WSAGetLastError());
+ return MapSystemError(os_error);
}
- if (!base::SetNonBlocking(socket_)) {
- int result = MapSystemError(WSAGetLastError());
+ if (!SetNonBlockingAndGetError(socket_, &os_error)) {
+ int result = MapSystemError(os_error);
Close();
return result;
}
@@ -298,8 +309,9 @@ int TCPSocketWin::AdoptConnectedSocket(SOCKET socket,
socket_ = socket;
- if (!base::SetNonBlocking(socket_)) {
- int result = MapSystemError(WSAGetLastError());
+ int os_error;
+ if (!SetNonBlockingAndGetError(socket_, &os_error)) {
+ int result = MapSystemError(os_error);
Close();
return result;
}
@@ -316,8 +328,9 @@ int TCPSocketWin::AdoptListenSocket(SOCKET socket) {
socket_ = socket;
- if (!base::SetNonBlocking(socket_)) {
- int result = MapSystemError(WSAGetLastError());
+ int os_error;
+ if (!SetNonBlockingAndGetError(socket_, &os_error)) {
+ int result = MapSystemError(os_error);
Close();
return result;
}
@@ -337,9 +350,10 @@ int TCPSocketWin::Bind(const IPEndPoint& address) {
return ERR_ADDRESS_INVALID;
int result = bind(socket_, storage.addr, storage.addr_len);
+ int os_error = WSAGetLastError();
if (result < 0) {
PLOG(ERROR) << "bind() returned an error";
- return MapSystemError(WSAGetLastError());
+ return MapSystemError(os_error);
}
return OK;
@@ -352,15 +366,17 @@ int TCPSocketWin::Listen(int backlog) {
DCHECK_EQ(accept_event_, WSA_INVALID_EVENT);
accept_event_ = WSACreateEvent();
+ int os_error = WSAGetLastError();
if (accept_event_ == WSA_INVALID_EVENT) {
PLOG(ERROR) << "WSACreateEvent()";
- return MapSystemError(WSAGetLastError());
+ return MapSystemError(os_error);
}
int result = listen(socket_, backlog);
+ os_error = WSAGetLastError();
if (result < 0) {
PLOG(ERROR) << "listen() returned an error";
- return MapSystemError(WSAGetLastError());
+ return MapSystemError(os_error);
}
return OK;
@@ -438,9 +454,10 @@ bool TCPSocketWin::IsConnected() const {
// Check if connection is alive.
char c;
int rv = recv(socket_, &c, 1, MSG_PEEK);
+ int os_error = WSAGetLastError();
if (rv == 0)
return false;
- if (rv == SOCKET_ERROR && WSAGetLastError() != WSAEWOULDBLOCK)
+ if (rv == SOCKET_ERROR && os_error != WSAEWOULDBLOCK)
return false;
return true;
@@ -459,9 +476,10 @@ bool TCPSocketWin::IsConnectedAndIdle() const {
// unexpectedly.
char c;
int rv = recv(socket_, &c, 1, MSG_PEEK);
+ int os_error = WSAGetLastError();
if (rv >= 0)
return false;
- if (WSAGetLastError() != WSAEWOULDBLOCK)
+ if (os_error != WSAEWOULDBLOCK)
return false;
return true;
@@ -498,6 +516,7 @@ int TCPSocketWin::Write(IOBuffer* buf,
DWORD num;
int rv = WSASend(socket_, &write_buffer, 1, &num, 0,
&core_->write_overlapped_, NULL);
+ int os_error = WSAGetLastError();
if (rv == 0) {
if (ResetEventIfSignaled(core_->write_overlapped_.hEvent)) {
rv = static_cast<int>(num);
@@ -514,7 +533,6 @@ int TCPSocketWin::Write(IOBuffer* buf,
return rv;
}
} else {
- int os_error = WSAGetLastError();
if (os_error != WSA_IO_PENDING) {
int net_error = MapSystemError(os_error);
net_log_.AddEvent(NetLogEventType::SOCKET_WRITE_ERROR,
@@ -535,8 +553,10 @@ int TCPSocketWin::GetLocalAddress(IPEndPoint* address) const {
DCHECK(address);
SockaddrStorage storage;
- if (getsockname(socket_, storage.addr, &storage.addr_len))
- return MapSystemError(WSAGetLastError());
+ if (getsockname(socket_, storage.addr, &storage.addr_len)) {
+ int os_error = WSAGetLastError();
+ return MapSystemError(os_error);
+ }
if (!address->FromSockAddr(storage.addr, storage.addr_len))
return ERR_ADDRESS_INVALID;
@@ -689,8 +709,9 @@ int TCPSocketWin::AcceptInternal(std::unique_ptr<TCPSocketWin>* socket,
IPEndPoint* address) {
SockaddrStorage storage;
int new_socket = accept(socket_, storage.addr, &storage.addr_len);
+ int os_error = WSAGetLastError();
if (new_socket < 0) {
- int net_error = MapSystemError(WSAGetLastError());
+ int net_error = MapSystemError(os_error);
if (net_error != ERR_IO_PENDING)
net_log_.EndEventWithNetErrorCode(NetLogEventType::TCP_ACCEPT, net_error);
return net_error;
@@ -763,11 +784,13 @@ int TCPSocketWin::DoConnect() {
return ERR_ADDRESS_INVALID;
int result;
+ int os_error;
{
// TODO(ricea): Remove ScopedTracker below once crbug.com/436634 is fixed.
tracked_objects::ScopedTracker tracking_profile(
FROM_HERE_WITH_EXPLICIT_FUNCTION("436634 connect()"));
result = connect(socket_, storage.addr, storage.addr_len);
+ os_error = WSAGetLastError();
}
if (!result) {
@@ -786,7 +809,6 @@ int TCPSocketWin::DoConnect() {
if (ResetEventIfSignaled(core_->read_overlapped_.hEvent))
return OK;
} else {
- int os_error = WSAGetLastError();
if (os_error != WSAEWOULDBLOCK) {
LOG(ERROR) << "connect failed: " << os_error;
connect_os_error_ = os_error;
@@ -834,9 +856,9 @@ void TCPSocketWin::LogConnectEnd(int net_error) {
socklen_t addrlen = sizeof(source_address);
int rv = getsockname(
socket_, reinterpret_cast<struct sockaddr*>(&source_address), &addrlen);
+ int os_error = WSAGetLastError();
if (rv != 0) {
- LOG(ERROR) << "getsockname() [rv: " << rv
- << "] error: " << WSAGetLastError();
+ LOG(ERROR) << "getsockname() [rv: " << rv << "] error: " << os_error;
NOTREACHED();
net_log_.EndEventWithNetErrorCode(NetLogEventType::TCP_CONNECT, rv);
return;
@@ -857,8 +879,8 @@ int TCPSocketWin::DoRead(IOBuffer* buf, int buf_len,
core_->non_blocking_reads_initialized_ = true;
}
int rv = recv(socket_, buf->data(), buf_len, 0);
+ int os_error = WSAGetLastError();
if (rv == SOCKET_ERROR) {
- int os_error = WSAGetLastError();
if (os_error != WSAEWOULDBLOCK) {
int net_error = MapSystemError(os_error);
net_log_.AddEvent(NetLogEventType::SOCKET_READ_ERROR,
@@ -887,6 +909,7 @@ void TCPSocketWin::DidCompleteConnect() {
WSANETWORKEVENTS events;
int rv;
+ int os_error = 0;
{
// TODO(pkasting): Remove ScopedTracker below once crbug.com/462784 is
// fixed.
@@ -894,11 +917,10 @@ void TCPSocketWin::DidCompleteConnect() {
FROM_HERE_WITH_EXPLICIT_FUNCTION(
"462784 TCPSocketWin::DidCompleteConnect -> WSAEnumNetworkEvents"));
rv = WSAEnumNetworkEvents(socket_, core_->read_overlapped_.hEvent, &events);
+ os_error = WSAGetLastError();
}
- int os_error = 0;
if (rv == SOCKET_ERROR) {
NOTREACHED();
- os_error = WSAGetLastError();
result = MapSystemError(os_error);
} else if (events.lNetworkEvents & FD_CONNECT) {
os_error = events.iErrorCode[FD_CONNECT_BIT];
@@ -927,11 +949,11 @@ void TCPSocketWin::DidCompleteWrite() {
DWORD num_bytes, flags;
BOOL ok = WSAGetOverlappedResult(socket_, &core_->write_overlapped_,
&num_bytes, FALSE, &flags);
+ int os_error = WSAGetLastError();
WSAResetEvent(core_->write_overlapped_.hEvent);
waiting_write_ = false;
int rv;
if (!ok) {
- int os_error = WSAGetLastError();
rv = MapSystemError(os_error);
net_log_.AddEvent(NetLogEventType::SOCKET_WRITE_ERROR,
CreateNetLogSocketErrorCallback(rv, os_error));
@@ -965,8 +987,9 @@ void TCPSocketWin::DidSignalRead() {
WSANETWORKEVENTS network_events;
int rv = WSAEnumNetworkEvents(socket_, core_->read_overlapped_.hEvent,
&network_events);
+ os_error = WSAGetLastError();
+
if (rv == SOCKET_ERROR) {
- os_error = WSAGetLastError();
rv = MapSystemError(os_error);
} else if (network_events.lNetworkEvents) {
// TODO(pkasting): Remove ScopedTracker below once crbug.com/462778 is
diff --git a/chromium/net/socket/transport_client_socket_pool.cc b/chromium/net/socket/transport_client_socket_pool.cc
index dbcd7c44c57..3cbbd611732 100644
--- a/chromium/net/socket/transport_client_socket_pool.cc
+++ b/chromium/net/socket/transport_client_socket_pool.cc
@@ -19,6 +19,7 @@
#include "base/values.h"
#include "net/base/ip_endpoint.h"
#include "net/base/net_errors.h"
+#include "net/base/trace_constants.h"
#include "net/log/net_log.h"
#include "net/log/net_log_event_type.h"
#include "net/log/net_log_source_type.h"
@@ -101,7 +102,8 @@ TransportConnectJob::TransportConnectJob(
priority,
respect_limits,
delegate,
- NetLogWithSource::Make(net_log, NetLogSourceType::CONNECT_JOB)),
+ NetLogWithSource::Make(net_log,
+ NetLogSourceType::TRANSPORT_CONNECT_JOB)),
params_(params),
resolver_(host_resolver),
client_socket_factory_(client_socket_factory),
@@ -267,7 +269,8 @@ int TransportConnectJob::DoResolveHost() {
}
int TransportConnectJob::DoResolveHostComplete(int result) {
- TRACE_EVENT0("net", "TransportConnectJob::DoResolveHostComplete");
+ TRACE_EVENT0(kNetTracingCategory,
+ "TransportConnectJob::DoResolveHostComplete");
connect_timing_.dns_end = base::TimeTicks::Now();
// Overwrite connection start time, since for connections that do not go
// through proxies, |connect_start| should not include dns lookup time.
diff --git a/chromium/net/socket/transport_client_socket_pool_test_util.cc b/chromium/net/socket/transport_client_socket_pool_test_util.cc
index 7f50efbf497..46d352c6e3c 100644
--- a/chromium/net/socket/transport_client_socket_pool_test_util.cc
+++ b/chromium/net/socket/transport_client_socket_pool_test_util.cc
@@ -73,7 +73,7 @@ class MockConnectClientSocket : public StreamSocket {
void SetOmniboxSpeculation() override {}
bool WasEverUsed() const override { return false; }
void EnableTCPFastOpenIfSupported() override {}
- bool WasNpnNegotiated() const override { return false; }
+ bool WasAlpnNegotiated() const override { return false; }
NextProto GetNegotiatedProtocol() const override { return kProtoUnknown; }
bool GetSSLInfo(SSLInfo* ssl_info) override { return false; }
void GetConnectionAttempts(ConnectionAttempts* out) const override {
@@ -135,7 +135,7 @@ class MockFailingClientSocket : public StreamSocket {
void SetOmniboxSpeculation() override {}
bool WasEverUsed() const override { return false; }
void EnableTCPFastOpenIfSupported() override {}
- bool WasNpnNegotiated() const override { return false; }
+ bool WasAlpnNegotiated() const override { return false; }
NextProto GetNegotiatedProtocol() const override { return kProtoUnknown; }
bool GetSSLInfo(SSLInfo* ssl_info) override { return false; }
void GetConnectionAttempts(ConnectionAttempts* out) const override {
@@ -261,7 +261,7 @@ class MockTriggerableClientSocket : public StreamSocket {
void SetOmniboxSpeculation() override {}
bool WasEverUsed() const override { return false; }
void EnableTCPFastOpenIfSupported() override {}
- bool WasNpnNegotiated() const override { return false; }
+ bool WasAlpnNegotiated() const override { return false; }
NextProto GetNegotiatedProtocol() const override { return kProtoUnknown; }
bool GetSSLInfo(SSLInfo* ssl_info) override { return false; }
void GetConnectionAttempts(ConnectionAttempts* out) const override {
diff --git a/chromium/net/socket/udp_socket_posix.cc b/chromium/net/socket/udp_socket_posix.cc
index 8b8c227ebc8..395541e0f8c 100644
--- a/chromium/net/socket/udp_socket_posix.cc
+++ b/chromium/net/socket/udp_socket_posix.cc
@@ -27,6 +27,7 @@
#include "net/base/net_errors.h"
#include "net/base/network_activity_monitor.h"
#include "net/base/sockaddr_storage.h"
+#include "net/base/trace_constants.h"
#include "net/log/net_log.h"
#include "net/log/net_log_event_type.h"
#include "net/log/net_log_source.h"
@@ -244,7 +245,7 @@ int UDPSocketPosix::GetPeerAddress(IPEndPoint* address) const {
std::unique_ptr<IPEndPoint> address(new IPEndPoint());
if (!address->FromSockAddr(storage.addr, storage.addr_len))
return ERR_ADDRESS_INVALID;
- remote_address_.reset(address.release());
+ remote_address_ = std::move(address);
}
*address = *remote_address_;
@@ -264,7 +265,7 @@ int UDPSocketPosix::GetLocalAddress(IPEndPoint* address) const {
std::unique_ptr<IPEndPoint> address(new IPEndPoint());
if (!address->FromSockAddr(storage.addr, storage.addr_len))
return ERR_ADDRESS_INVALID;
- local_address_.reset(address.release());
+ local_address_ = std::move(address);
net_log_.AddEvent(
NetLogEventType::UDP_LOCAL_ADDRESS,
CreateNetLogUDPConnectCallback(local_address_.get(), bound_network_));
@@ -574,7 +575,7 @@ int UDPSocketPosix::SetBroadcast(bool broadcast) {
}
void UDPSocketPosix::ReadWatcher::OnFileCanReadWithoutBlocking(int) {
- TRACE_EVENT0("net",
+ TRACE_EVENT0(kNetTracingCategory,
"UDPSocketPosix::ReadWatcher::OnFileCanReadWithoutBlocking");
if (!socket_->read_callback_.is_null())
socket_->DidCompleteRead();
diff --git a/chromium/net/socket/udp_socket_win.cc b/chromium/net/socket/udp_socket_win.cc
index 1d7aa187ed1..1b78e75d2a0 100644
--- a/chromium/net/socket/udp_socket_win.cc
+++ b/chromium/net/socket/udp_socket_win.cc
@@ -336,7 +336,7 @@ int UDPSocketWin::GetPeerAddress(IPEndPoint* address) const {
std::unique_ptr<IPEndPoint> remote_address(new IPEndPoint());
if (!remote_address->FromSockAddr(storage.addr, storage.addr_len))
return ERR_ADDRESS_INVALID;
- remote_address_.reset(remote_address.release());
+ remote_address_ = std::move(remote_address);
}
*address = *remote_address_;
@@ -357,7 +357,7 @@ int UDPSocketWin::GetLocalAddress(IPEndPoint* address) const {
std::unique_ptr<IPEndPoint> local_address(new IPEndPoint());
if (!local_address->FromSockAddr(storage.addr, storage.addr_len))
return ERR_ADDRESS_INVALID;
- local_address_.reset(local_address.release());
+ local_address_ = std::move(local_address);
net_log_.AddEvent(NetLogEventType::UDP_LOCAL_ADDRESS,
CreateNetLogUDPConnectCallback(
local_address_.get(),
diff --git a/chromium/net/socket/unix_domain_client_socket_posix.cc b/chromium/net/socket/unix_domain_client_socket_posix.cc
index 3615f2cbf69..037b0728dbc 100644
--- a/chromium/net/socket/unix_domain_client_socket_posix.cc
+++ b/chromium/net/socket/unix_domain_client_socket_posix.cc
@@ -132,7 +132,7 @@ bool UnixDomainClientSocket::WasEverUsed() const {
return true; // We don't care.
}
-bool UnixDomainClientSocket::WasNpnNegotiated() const {
+bool UnixDomainClientSocket::WasAlpnNegotiated() const {
return false;
}
diff --git a/chromium/net/socket/unix_domain_client_socket_posix.h b/chromium/net/socket/unix_domain_client_socket_posix.h
index b5af84546f3..47fb4fe2e8d 100644
--- a/chromium/net/socket/unix_domain_client_socket_posix.h
+++ b/chromium/net/socket/unix_domain_client_socket_posix.h
@@ -52,7 +52,7 @@ class NET_EXPORT UnixDomainClientSocket : public StreamSocket {
void SetSubresourceSpeculation() override;
void SetOmniboxSpeculation() override;
bool WasEverUsed() const override;
- bool WasNpnNegotiated() const override;
+ bool WasAlpnNegotiated() const override;
NextProto GetNegotiatedProtocol() const override;
bool GetSSLInfo(SSLInfo* ssl_info) override;
void GetConnectionAttempts(ConnectionAttempts* out) const override;
diff --git a/chromium/net/socket/websocket_endpoint_lock_manager_unittest.cc b/chromium/net/socket/websocket_endpoint_lock_manager_unittest.cc
index 7a79247d726..5668859be28 100644
--- a/chromium/net/socket/websocket_endpoint_lock_manager_unittest.cc
+++ b/chromium/net/socket/websocket_endpoint_lock_manager_unittest.cc
@@ -54,7 +54,7 @@ class FakeStreamSocket : public StreamSocket {
bool WasEverUsed() const override { return false; }
- bool WasNpnNegotiated() const override { return false; }
+ bool WasAlpnNegotiated() const override { return false; }
NextProto GetNegotiatedProtocol() const override { return kProtoUnknown; }
diff --git a/chromium/net/socket/websocket_transport_client_socket_pool.cc b/chromium/net/socket/websocket_transport_client_socket_pool.cc
index 987723c2032..0239226da99 100644
--- a/chromium/net/socket/websocket_transport_client_socket_pool.cc
+++ b/chromium/net/socket/websocket_transport_client_socket_pool.cc
@@ -18,6 +18,7 @@
#include "base/trace_event/trace_event.h"
#include "base/values.h"
#include "net/base/net_errors.h"
+#include "net/base/trace_constants.h"
#include "net/log/net_log_event_type.h"
#include "net/log/net_log_source.h"
#include "net/log/net_log_source_type.h"
@@ -41,13 +42,14 @@ WebSocketTransportConnectJob::WebSocketTransportConnectJob(
Delegate* delegate,
NetLog* pool_net_log,
const NetLogWithSource& request_net_log)
- : ConnectJob(
- group_name,
- timeout_duration,
- priority,
- respect_limits,
- delegate,
- NetLogWithSource::Make(pool_net_log, NetLogSourceType::CONNECT_JOB)),
+ : ConnectJob(group_name,
+ timeout_duration,
+ priority,
+ respect_limits,
+ delegate,
+ NetLogWithSource::Make(
+ pool_net_log,
+ NetLogSourceType::WEB_SOCKET_TRANSPORT_CONNECT_JOB)),
params_(params),
resolver_(host_resolver),
client_socket_factory_(client_socket_factory),
@@ -123,7 +125,8 @@ int WebSocketTransportConnectJob::DoResolveHost() {
}
int WebSocketTransportConnectJob::DoResolveHostComplete(int result) {
- TRACE_EVENT0("net", "WebSocketTransportConnectJob::DoResolveHostComplete");
+ TRACE_EVENT0(kNetTracingCategory,
+ "WebSocketTransportConnectJob::DoResolveHostComplete");
connect_timing_.dns_end = base::TimeTicks::Now();
// Overwrite connection start time, since for connections that do not go
// through proxies, |connect_start| should not include dns lookup time.
diff --git a/chromium/net/spdy/bidirectional_stream_spdy_impl.cc b/chromium/net/spdy/bidirectional_stream_spdy_impl.cc
index 3f755c15a87..07f240db5e4 100644
--- a/chromium/net/spdy/bidirectional_stream_spdy_impl.cc
+++ b/chromium/net/spdy/bidirectional_stream_spdy_impl.cc
@@ -9,6 +9,7 @@
#include "base/bind.h"
#include "base/location.h"
#include "base/logging.h"
+#include "base/threading/thread_task_runner_handle.h"
#include "base/time/time.h"
#include "base/timer/timer.h"
#include "net/http/bidirectional_stream_request_info.h"
@@ -210,7 +211,7 @@ bool BidirectionalStreamSpdyImpl::GetLoadTimingInfo(
return stream_->GetLoadTimingInfo(load_timing_info);
}
-void BidirectionalStreamSpdyImpl::OnRequestHeadersSent() {
+void BidirectionalStreamSpdyImpl::OnHeadersSent() {
DCHECK(stream_);
negotiated_protocol_ = kProtoHTTP2;
@@ -218,14 +219,12 @@ void BidirectionalStreamSpdyImpl::OnRequestHeadersSent() {
delegate_->OnStreamReady(/*request_headers_sent=*/true);
}
-SpdyResponseHeadersStatus BidirectionalStreamSpdyImpl::OnResponseHeadersUpdated(
+void BidirectionalStreamSpdyImpl::OnHeadersReceived(
const SpdyHeaderBlock& response_headers) {
DCHECK(stream_);
if (delegate_)
delegate_->OnHeadersReceived(response_headers);
-
- return RESPONSE_HEADERS_ARE_COMPLETE;
}
void BidirectionalStreamSpdyImpl::OnDataReceived(
@@ -317,7 +316,7 @@ void BidirectionalStreamSpdyImpl::OnStreamInitialized(int rv) {
stream_->SetDelegate(this);
rv = SendRequestHeadersHelper();
if (rv == OK) {
- OnRequestHeadersSent();
+ OnHeadersSent();
return;
} else if (rv == ERR_IO_PENDING) {
return;
diff --git a/chromium/net/spdy/bidirectional_stream_spdy_impl.h b/chromium/net/spdy/bidirectional_stream_spdy_impl.h
index 1e3f6e7a0b9..b5398b35274 100644
--- a/chromium/net/spdy/bidirectional_stream_spdy_impl.h
+++ b/chromium/net/spdy/bidirectional_stream_spdy_impl.h
@@ -61,9 +61,8 @@ class NET_EXPORT_PRIVATE BidirectionalStreamSpdyImpl
bool GetLoadTimingInfo(LoadTimingInfo* load_timing_info) const override;
// SpdyStream::Delegate implementation:
- void OnRequestHeadersSent() override;
- SpdyResponseHeadersStatus OnResponseHeadersUpdated(
- const SpdyHeaderBlock& response_headers) override;
+ void OnHeadersSent() override;
+ void OnHeadersReceived(const SpdyHeaderBlock& response_headers) override;
void OnDataReceived(std::unique_ptr<SpdyBuffer> buffer) override;
void OnDataSent() override;
void OnTrailers(const SpdyHeaderBlock& trailers) override;
diff --git a/chromium/net/spdy/buffered_spdy_framer.cc b/chromium/net/spdy/buffered_spdy_framer.cc
index 4a1e8469104..19facaeb64b 100644
--- a/chromium/net/spdy/buffered_spdy_framer.cc
+++ b/chromium/net/spdy/buffered_spdy_framer.cc
@@ -20,7 +20,7 @@ size_t kGoAwayDebugDataMaxSize = 1024;
} // namespace
BufferedSpdyFramer::BufferedSpdyFramer()
- : spdy_framer_(HTTP2),
+ : spdy_framer_(SpdyFramer::ENABLE_COMPRESSION),
visitor_(NULL),
header_buffer_valid_(false),
header_stream_id_(SpdyFramer::kInvalidStream),
@@ -45,14 +45,6 @@ void BufferedSpdyFramer::OnError(SpdyFramer* spdy_framer) {
visitor_->OnError(spdy_framer->error_code());
}
-void BufferedSpdyFramer::OnSynStream(SpdyStreamId stream_id,
- SpdyStreamId associated_stream_id,
- SpdyPriority priority,
- bool fin,
- bool unidirectional) {
- NOTREACHED();
-}
-
void BufferedSpdyFramer::OnHeaders(SpdyStreamId stream_id,
bool has_priority,
int weight,
@@ -76,11 +68,6 @@ void BufferedSpdyFramer::OnHeaders(SpdyStreamId stream_id,
InitHeaderStreaming(stream_id);
}
-void BufferedSpdyFramer::OnSynReply(SpdyStreamId stream_id,
- bool fin) {
- NOTREACHED();
-}
-
void BufferedSpdyFramer::OnDataFrameHeader(SpdyStreamId stream_id,
size_t length,
bool fin) {
@@ -118,12 +105,6 @@ void BufferedSpdyFramer::OnHeaderFrameEnd(SpdyStreamId stream_id,
}
DCHECK(control_frame_fields_.get());
switch (control_frame_fields_->type) {
- case SYN_STREAM:
- NOTREACHED();
- break;
- case SYN_REPLY:
- NOTREACHED();
- break;
case HEADERS:
visitor_->OnHeaders(
control_frame_fields_->stream_id, control_frame_fields_->has_priority,
@@ -149,10 +130,8 @@ void BufferedSpdyFramer::OnSettings(bool clear_persisted) {
visitor_->OnSettings();
}
-void BufferedSpdyFramer::OnSetting(SpdySettingsIds id,
- uint8_t flags,
- uint32_t value) {
- visitor_->OnSetting(id, flags, value);
+void BufferedSpdyFramer::OnSetting(SpdySettingsIds id, uint32_t value) {
+ visitor_->OnSetting(id, value);
}
void BufferedSpdyFramer::OnSettingsAck() {
@@ -270,14 +249,9 @@ SpdySerializedFrame* BufferedSpdyFramer::CreateRstStream(
SpdySerializedFrame* BufferedSpdyFramer::CreateSettings(
const SettingsMap& values) const {
SpdySettingsIR settings_ir;
- for (SettingsMap::const_iterator it = values.begin();
- it != values.end();
+ for (SettingsMap::const_iterator it = values.begin(); it != values.end();
++it) {
- settings_ir.AddSetting(
- it->first,
- (it->second.first & SETTINGS_FLAG_PLEASE_PERSIST) != 0,
- (it->second.first & SETTINGS_FLAG_PERSISTED) != 0,
- it->second.second);
+ settings_ir.AddSetting(it->first, it->second);
}
return new SpdySerializedFrame(spdy_framer_.SerializeSettings(settings_ir));
}
@@ -345,6 +319,17 @@ SpdySerializedFrame* BufferedSpdyFramer::CreatePushPromise(
spdy_framer_.SerializePushPromise(push_promise_ir));
}
+// TODO(jgraettinger): Eliminate uses of this method (prefer
+// SpdyPriorityIR).
+SpdySerializedFrame* BufferedSpdyFramer::CreatePriority(
+ SpdyStreamId stream_id,
+ SpdyStreamId dependency_id,
+ int weight,
+ bool exclusive) const {
+ SpdyPriorityIR priority_ir(stream_id, dependency_id, weight, exclusive);
+ return new SpdySerializedFrame(spdy_framer_.SerializePriority(priority_ir));
+}
+
SpdyPriority BufferedSpdyFramer::GetHighestPriority() const {
return spdy_framer_.GetHighestPriority();
}
diff --git a/chromium/net/spdy/buffered_spdy_framer.h b/chromium/net/spdy/buffered_spdy_framer.h
index fa523f186ac..7412f589682 100644
--- a/chromium/net/spdy/buffered_spdy_framer.h
+++ b/chromium/net/spdy/buffered_spdy_framer.h
@@ -28,7 +28,7 @@ class NET_EXPORT_PRIVATE BufferedSpdyFramerVisitorInterface {
// Called if an error is detected in the SpdySerializedFrame protocol.
virtual void OnError(SpdyFramer::SpdyError error_code) = 0;
- // Called if an error is detected in a SPDY stream.
+ // Called if an error is detected in a HTTP2 stream.
virtual void OnStreamError(SpdyStreamId stream_id,
const std::string& description) = 0;
@@ -49,8 +49,7 @@ class NET_EXPORT_PRIVATE BufferedSpdyFramerVisitorInterface {
// Called when data is received.
// |stream_id| The stream receiving data.
// |data| A buffer containing the data received.
- // |len| The length of the data buffer (at most 2^24 - 1 for SPDY/3,
- // but 2^16 - 1 - 8 for HTTP2).
+ // |len| The length of the data buffer (at most 2^16 - 1 - 8).
virtual void OnStreamFrameData(SpdyStreamId stream_id,
const char* data,
size_t len) = 0;
@@ -69,7 +68,7 @@ class NET_EXPORT_PRIVATE BufferedSpdyFramerVisitorInterface {
// Called when an individual setting within a SETTINGS frame has been parsed
// and validated.
- virtual void OnSetting(SpdySettingsIds id, uint8_t flags, uint32_t value) = 0;
+ virtual void OnSetting(SpdySettingsIds id, uint32_t value) = 0;
// Called when a SETTINGS frame is received with the ACK flag set.
virtual void OnSettingsAck() {}
@@ -136,12 +135,6 @@ class NET_EXPORT_PRIVATE BufferedSpdyFramer
// SpdyFramerVisitorInterface
void OnError(SpdyFramer* spdy_framer) override;
- void OnSynStream(SpdyStreamId stream_id,
- SpdyStreamId associated_stream_id,
- SpdyPriority priority,
- bool fin,
- bool unidirectional) override;
- void OnSynReply(SpdyStreamId stream_id, bool fin) override;
void OnHeaders(SpdyStreamId stream_id,
bool has_priority,
int weight,
@@ -158,7 +151,7 @@ class NET_EXPORT_PRIVATE BufferedSpdyFramer
SpdyStreamId stream_id) override;
void OnHeaderFrameEnd(SpdyStreamId stream_id, bool end_headers) override;
void OnSettings(bool clear_persisted) override;
- void OnSetting(SpdySettingsIds id, uint8_t flags, uint32_t value) override;
+ void OnSetting(SpdySettingsIds id, uint32_t value) override;
void OnSettingsAck() override;
void OnSettingsEnd() override;
void OnPing(SpdyPingId unique_id, bool is_ack) override;
@@ -208,6 +201,10 @@ class NET_EXPORT_PRIVATE BufferedSpdyFramer
SpdySerializedFrame* CreatePushPromise(SpdyStreamId stream_id,
SpdyStreamId promised_stream_id,
SpdyHeaderBlock headers);
+ SpdySerializedFrame* CreatePriority(SpdyStreamId stream_id,
+ SpdyStreamId dependency_id,
+ int weight,
+ bool exclusive) const;
// Serialize a frame of unknown type.
SpdySerializedFrame SerializeFrame(const SpdyFrameIR& frame) {
@@ -224,10 +221,6 @@ class NET_EXPORT_PRIVATE BufferedSpdyFramer
return spdy_framer_.GetFrameHeaderSize();
}
- size_t GetSynStreamMinimumSize() const {
- return spdy_framer_.GetSynStreamMinimumSize();
- }
-
size_t GetFrameMinimumSize() const {
return spdy_framer_.GetFrameMinimumSize();
}
diff --git a/chromium/net/spdy/buffered_spdy_framer_unittest.cc b/chromium/net/spdy/buffered_spdy_framer_unittest.cc
index cc373163ec3..a5bf1c1f46f 100644
--- a/chromium/net/spdy/buffered_spdy_framer_unittest.cc
+++ b/chromium/net/spdy/buffered_spdy_framer_unittest.cc
@@ -4,6 +4,7 @@
#include "net/spdy/buffered_spdy_framer.h"
+#include <algorithm>
#include <utility>
#include "base/logging.h"
@@ -16,7 +17,7 @@ namespace {
class TestBufferedSpdyVisitor : public BufferedSpdyFramerVisitorInterface {
public:
- explicit TestBufferedSpdyVisitor()
+ TestBufferedSpdyVisitor()
: buffered_spdy_framer_(),
error_count_(0),
setting_count_(0),
@@ -74,7 +75,7 @@ class TestBufferedSpdyVisitor : public BufferedSpdyFramerVisitorInterface {
void OnSettings() override {}
- void OnSetting(SpdySettingsIds id, uint8_t flags, uint32_t value) override {
+ void OnSetting(SpdySettingsIds id, uint32_t value) override {
setting_count_++;
}
@@ -179,10 +180,10 @@ class TestBufferedSpdyVisitor : public BufferedSpdyFramerVisitorInterface {
class BufferedSpdyFramerTest : public PlatformTest {};
TEST_F(BufferedSpdyFramerTest, OnSetting) {
- SpdyFramer framer(HTTP2);
+ SpdyFramer framer(SpdyFramer::ENABLE_COMPRESSION);
SpdySettingsIR settings_ir;
- settings_ir.AddSetting(SETTINGS_INITIAL_WINDOW_SIZE, false, false, 2);
- settings_ir.AddSetting(SETTINGS_MAX_CONCURRENT_STREAMS, false, false, 3);
+ settings_ir.AddSetting(SETTINGS_INITIAL_WINDOW_SIZE, 2);
+ settings_ir.AddSetting(SETTINGS_MAX_CONCURRENT_STREAMS, 3);
SpdySerializedFrame control_frame(framer.SerializeSettings(settings_ir));
TestBufferedSpdyVisitor visitor;
diff --git a/chromium/net/spdy/hpack/hpack_constants.cc b/chromium/net/spdy/hpack/hpack_constants.cc
index b9db0ef2d6c..1a2a267e193 100644
--- a/chromium/net/spdy/hpack/hpack_constants.cc
+++ b/chromium/net/spdy/hpack/hpack_constants.cc
@@ -25,7 +25,7 @@ struct SharedHpackHuffmanTable {
std::unique_ptr<HpackHuffmanTable> mutable_table(new HpackHuffmanTable());
CHECK(mutable_table->Initialize(&code[0], code.size()));
CHECK(mutable_table->IsInitialized());
- table.reset(mutable_table.release());
+ table = std::move(mutable_table);
}
static SharedHpackHuffmanTable* GetInstance() {
@@ -44,7 +44,7 @@ struct SharedHpackStaticTable {
std::unique_ptr<HpackStaticTable> mutable_table(new HpackStaticTable());
mutable_table->Initialize(&static_table[0], static_table.size());
CHECK(mutable_table->IsInitialized());
- table.reset(mutable_table.release());
+ table = std::move(mutable_table);
}
static SharedHpackStaticTable* GetInstance() {
diff --git a/chromium/net/spdy/hpack/hpack_constants.h b/chromium/net/spdy/hpack/hpack_constants.h
index 8718ffe0629..fdfb0d1278e 100644
--- a/chromium/net/spdy/hpack/hpack_constants.h
+++ b/chromium/net/spdy/hpack/hpack_constants.h
@@ -2,8 +2,8 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#ifndef NET_SPDY_HPACK_CONSTANTS_H_
-#define NET_SPDY_HPACK_CONSTANTS_H_
+#ifndef NET_SPDY_HPACK_HPACK_CONSTANTS_H_
+#define NET_SPDY_HPACK_HPACK_CONSTANTS_H_
#include <stddef.h>
#include <stdint.h>
@@ -90,4 +90,4 @@ const char kPseudoHeaderPrefix = ':';
} // namespace net
-#endif // NET_SPDY_HPACK_CONSTANTS_H_
+#endif // NET_SPDY_HPACK_HPACK_CONSTANTS_H_
diff --git a/chromium/net/spdy/hpack/hpack_decoder2.cc b/chromium/net/spdy/hpack/hpack_decoder2.cc
new file mode 100644
index 00000000000..03b1c2ef229
--- /dev/null
+++ b/chromium/net/spdy/hpack/hpack_decoder2.cc
@@ -0,0 +1,330 @@
+// Copyright 2016 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.
+
+#include "net/spdy/hpack/hpack_decoder2.h"
+
+#include <list>
+#include <utility>
+
+#include "base/logging.h"
+#include "base/strings/string_piece.h"
+#include "net/http2/decoder/decode_buffer.h"
+#include "net/http2/decoder/decode_status.h"
+#include "net/spdy/hpack/hpack_entry.h"
+
+using base::StringPiece;
+
+namespace net {
+
+HpackDecoder2::HpackDecoder2() : hpack_block_decoder_(this) {
+ Reset();
+}
+
+HpackDecoder2::~HpackDecoder2() {}
+
+void HpackDecoder2::Reset() {
+ DVLOG(2) << "HpackDecoder2::Reset";
+ handler_ = nullptr;
+
+ hpack_block_decoder_.Reset();
+ hpack_block_decoder_.set_listener(this);
+
+ total_hpack_bytes_ = 0;
+ total_header_bytes_ = 0;
+ size_update_count_ = 0;
+ header_seen_ = false;
+ in_progress_ = false;
+ error_detected_ = false;
+ header_block_started_ = false;
+
+ name_.Reset();
+ value_.Reset();
+}
+
+void HpackDecoder2::SetErrorDetected() {
+ if (!error_detected_) {
+ DVLOG(2) << "HpackDecoder2::SetErrorDetected";
+ hpack_block_decoder_.set_listener(&no_op_listener_);
+ error_detected_ = true;
+ }
+}
+
+void HpackDecoder2::ApplyHeaderTableSizeSetting(size_t size_setting) {
+ DVLOG(2) << "HpackDecoder2::ApplyHeaderTableSizeSetting";
+ header_table_.SetSettingsHeaderTableSize(size_setting);
+}
+
+// If a SpdyHeadersHandlerInterface is provided, the decoder will emit
+// headers to it rather than accumulating them in a SpdyHeaderBlock.
+void HpackDecoder2::HandleControlFrameHeadersStart(
+ SpdyHeadersHandlerInterface* handler) {
+ DVLOG(2) << "HpackDecoder2::HandleControlFrameHeadersStart";
+ DCHECK(!header_block_started_);
+ handler_ = handler;
+}
+
+// Called as HPACK block fragments arrive. Returns false
+// if an error occurred while decoding the block.
+bool HpackDecoder2::HandleControlFrameHeadersData(const char* headers_data,
+ size_t headers_data_length) {
+ DVLOG(2) << "HpackDecoder2::HandleControlFrameHeadersData: len="
+ << headers_data_length;
+ if (!header_block_started_) {
+ DCHECK_EQ(total_hpack_bytes_, 0u);
+ // Clear the SpdyHeaderBlock here rather than in Reset so that it is NOT
+ // cleared in HandleControlFrameHeadersComplete, which would be before it
+ // could be used.
+ decoded_block_.clear();
+ header_block_started_ = true;
+ if (handler_ != nullptr) {
+ handler_->OnHeaderBlockStart();
+ }
+ }
+
+ // Sometimes we get a call with headers_data==nullptr and
+ // headers_data_length==0, in which case we need to avoid creating
+ // a DecodeBuffer, which would otherwise complain.
+ if (headers_data_length > 0) {
+ DCHECK_NE(headers_data, nullptr);
+ total_hpack_bytes_ += headers_data_length;
+ DecodeBuffer db(headers_data, headers_data_length);
+ DecodeStatus status = hpack_block_decoder_.Decode(&db);
+ switch (status) {
+ case DecodeStatus::kDecodeDone:
+ // We've completed the decoding of headers_data, and it ended at the
+ // boundary between two HPACK block entries, so name_ and value_ are
+ // currently reset.
+ DCHECK_EQ(0u, db.Remaining());
+ in_progress_ = false;
+ break;
+
+ case DecodeStatus::kDecodeInProgress:
+ DCHECK_EQ(0u, db.Remaining());
+ in_progress_ = true;
+ if (!error_detected_) {
+ name_.BufferStringIfUnbuffered();
+ value_.BufferStringIfUnbuffered();
+ EnforceMaxDecodeBufferSize();
+ }
+ break;
+
+ case DecodeStatus::kDecodeError:
+ SetErrorDetected();
+ break;
+ }
+ }
+ return !error_detected_;
+}
+
+// Called after a HPACK block has been completely delivered via
+// HandleControlFrameHeadersData(). Returns false if an error occurred.
+// |compressed_len| if non-null will be set to the size of the encoded
+// buffered block that was accumulated in HandleControlFrameHeadersData(),
+// to support subsequent calculation of compression percentage.
+// Discards the handler supplied at the start of decoding the block.
+// TODO(jamessynge): Determine if compressed_len is needed; it is used to
+// produce UUMA stat Net.SpdyHpackDecompressionPercentage, but only for
+// SPDY3, not HTTP2.
+bool HpackDecoder2::HandleControlFrameHeadersComplete(size_t* compressed_len) {
+ DVLOG(2) << "HpackDecoder2::HandleControlFrameHeadersComplete";
+ if (error_detected_ || in_progress_) {
+ DVLOG(2) << "error_detected_=" << error_detected_
+ << ", in_progress_=" << in_progress_;
+ return false;
+ }
+ if (compressed_len != nullptr) {
+ *compressed_len = total_hpack_bytes_;
+ }
+ if (handler_ != nullptr) {
+ handler_->OnHeaderBlockEnd(total_header_bytes_);
+ }
+ Reset();
+ return true;
+}
+
+const SpdyHeaderBlock& HpackDecoder2::decoded_block() const {
+ return decoded_block_;
+}
+
+void HpackDecoder2::SetHeaderTableDebugVisitor(
+ std::unique_ptr<HpackHeaderTable::DebugVisitorInterface> visitor) {
+ DVLOG(2) << "HpackDecoder2::SetHeaderTableDebugVisitor";
+ header_table_.set_debug_visitor(std::move(visitor));
+}
+
+void HpackDecoder2::set_max_decode_buffer_size_bytes(
+ size_t max_decode_buffer_size_bytes) {
+ DVLOG(2) << "HpackDecoder2::set_max_decode_buffer_size_bytes";
+ max_decode_buffer_size_bytes_ = max_decode_buffer_size_bytes;
+}
+
+void HpackDecoder2::OnIndexedHeader(size_t index) {
+ DVLOG(2) << "HpackDecoder2::OnIndexedHeader: index=" << index;
+ DCHECK(!error_detected_);
+ const HpackEntry* entry = header_table_.GetByIndex(index);
+ if (entry == nullptr) {
+ SetErrorDetected();
+ return;
+ }
+ HandleHeaderRepresentation(entry->name(), entry->value());
+}
+
+void HpackDecoder2::OnStartLiteralHeader(HpackEntryType entry_type,
+ size_t maybe_name_index) {
+ DVLOG(2) << "HpackDecoder2::OnStartLiteralHeader: entry_type=" << entry_type
+ << ", maybe_name_index=" << maybe_name_index;
+ DCHECK(!error_detected_);
+ entry_type_ = entry_type;
+ if (maybe_name_index > 0) {
+ const HpackEntry* entry = header_table_.GetByIndex(maybe_name_index);
+ if (entry == nullptr) {
+ SetErrorDetected();
+ return;
+ } else {
+ // Non-static entries could be evicted, leaving us with a dangling
+ // pointer, so we preemptively copy. This could be avoided if
+ // TryAddEntry would copy the strings prior to performing eviction.
+ name_.Set(entry->name(), entry->IsStatic());
+ name_.BufferStringIfUnbuffered();
+ }
+ }
+}
+
+void HpackDecoder2::OnNameStart(bool huffman_encoded, size_t len) {
+ DVLOG(2) << "HpackDecoder2::OnNameStart: huffman_encoded="
+ << (huffman_encoded ? "true" : "false") << ", len=" << len;
+ if (len > max_decode_buffer_size_bytes_) {
+ DVLOG(1) << "Name length (" << len << ") is longer than permitted ("
+ << max_decode_buffer_size_bytes_ << ")";
+ SetErrorDetected();
+ return;
+ }
+ name_.OnStart(huffman_encoded, len);
+}
+
+void HpackDecoder2::OnNameData(const char* data, size_t len) {
+ DVLOG(2) << "HpackDecoder2::OnNameData: len=" << len
+ << "\n data: " << StringPiece(data, len);
+ if (error_detected_) {
+ return;
+ }
+ if (!name_.OnData(data, len)) {
+ SetErrorDetected();
+ }
+}
+
+void HpackDecoder2::OnNameEnd() {
+ DVLOG(2) << "HpackDecoder2::OnNameEnd";
+ if (error_detected_) {
+ return;
+ }
+ if (!name_.OnEnd()) {
+ SetErrorDetected();
+ }
+}
+
+void HpackDecoder2::OnValueStart(bool huffman_encoded, size_t len) {
+ DVLOG(2) << "HpackDecoder2::OnValueStart: huffman_encoded="
+ << (huffman_encoded ? "true" : "false") << ", len=" << len;
+ if (len > max_decode_buffer_size_bytes_) {
+ DVLOG(1) << "Value length (" << len << ") is longer than permitted ("
+ << max_decode_buffer_size_bytes_ << ")";
+ SetErrorDetected();
+ return;
+ }
+ value_.OnStart(huffman_encoded, len);
+}
+
+void HpackDecoder2::OnValueData(const char* data, size_t len) {
+ DVLOG(2) << "HpackDecoder2::OnValueData: len=" << len
+ << "\n data: " << StringPiece(data, len);
+ if (error_detected_) {
+ return;
+ }
+ if (!value_.OnData(data, len)) {
+ SetErrorDetected();
+ }
+}
+
+void HpackDecoder2::OnValueEnd() {
+ DVLOG(2) << "HpackDecoder2::OnValueEnd";
+ if (error_detected_) {
+ return;
+ }
+ if (!value_.OnEnd()) {
+ SetErrorDetected();
+ return;
+ }
+ if (EnforceMaxDecodeBufferSize()) {
+ // All is well.
+ HandleHeaderRepresentation(name_.str(), value_.str());
+ if (entry_type_ == HpackEntryType::kIndexedLiteralHeader) {
+ header_table_.TryAddEntry(name_.str(), value_.str());
+ }
+ name_.Reset();
+ value_.Reset();
+ }
+}
+
+void HpackDecoder2::OnDynamicTableSizeUpdate(size_t size) {
+ DVLOG(2) << "HpackDecoder2::OnDynamicTableSizeUpdate: size=" << size;
+ if (error_detected_) {
+ return;
+ }
+ if (size > header_table_.settings_size_bound()) {
+ DVLOG(1) << "Dynamic Table Size Update with too large a size: " << size
+ << " > " << header_table_.settings_size_bound();
+ SetErrorDetected();
+ return;
+ }
+ if (header_seen_) {
+ DVLOG(1) << "Dynamic Table Size Update seen after a Header";
+ SetErrorDetected();
+ return;
+ }
+ ++size_update_count_;
+ if (size_update_count_ > 2) {
+ DVLOG(1) << "Too many (" << size_update_count_
+ << ") Dynamic Table Size Updates";
+ SetErrorDetected();
+ return;
+ }
+ header_table_.SetMaxSize(size);
+ return;
+}
+
+bool HpackDecoder2::EnforceMaxDecodeBufferSize() {
+ if (!error_detected_) {
+ size_t buffered_length = name_.BufferedLength() + value_.BufferedLength();
+ DVLOG(2) << "buffered_length=" << buffered_length
+ << "; max=" << max_decode_buffer_size_bytes_;
+ if (buffered_length > max_decode_buffer_size_bytes_) {
+ DVLOG(1) << "Header length (" << buffered_length
+ << ") is longer than permitted ("
+ << max_decode_buffer_size_bytes_ << ")";
+ SetErrorDetected();
+ }
+ }
+ return !error_detected_;
+}
+
+void HpackDecoder2::HandleHeaderRepresentation(StringPiece name,
+ StringPiece value) {
+ DVLOG(2) << "HpackDecoder2::HandleHeaderRepresentation:\n name: " << name
+ << "\n value: " << value;
+ total_header_bytes_ += name.size() + value.size();
+ header_seen_ = true;
+ if (handler_ == nullptr) {
+ DVLOG(3) << "HpackDecoder2::HandleHeaderRepresentation "
+ << "adding to decoded_block";
+ decoded_block_.AppendValueOrAddHeader(name, value);
+ } else {
+ DVLOG(3) << "HpackDecoder2::HandleHeaderRepresentation "
+ << "passing to handler";
+ DCHECK(decoded_block_.empty());
+ handler_->OnHeader(name, value);
+ }
+}
+
+} // namespace net
diff --git a/chromium/net/spdy/hpack/hpack_decoder2.h b/chromium/net/spdy/hpack/hpack_decoder2.h
new file mode 100644
index 00000000000..6dd207c0aad
--- /dev/null
+++ b/chromium/net/spdy/hpack/hpack_decoder2.h
@@ -0,0 +1,146 @@
+// Copyright 2016 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.
+
+#ifndef NET_SPDY_HPACK_HPACK_DECODER2_H_
+#define NET_SPDY_HPACK_HPACK_DECODER2_H_
+
+// HpackDecoder2
+
+// An HpackDecoder decodes header sets as outlined in
+// http://tools.ietf.org/html/rfc7541. This implementation uses the
+// new HpackBlockDecoder in //net/http2/hpack/
+
+#include <stddef.h>
+
+#include <memory>
+#include <string>
+
+#include "base/macros.h"
+#include "base/strings/string_piece.h"
+#include "net/base/net_export.h"
+#include "net/http2/hpack/decoder/hpack_block_decoder.h"
+#include "net/http2/hpack/decoder/hpack_decoder_string_buffer.h"
+#include "net/http2/hpack/decoder/hpack_entry_decoder_listener.h"
+#include "net/http2/hpack/http2_hpack_constants.h"
+#include "net/http2/hpack/huffman/http2_hpack_huffman_decoder.h"
+#include "net/spdy/hpack/hpack_constants.h"
+#include "net/spdy/hpack/hpack_decoder_interface.h"
+#include "net/spdy/hpack/hpack_header_table.h"
+#include "net/spdy/spdy_header_block.h"
+#include "net/spdy/spdy_headers_handler_interface.h"
+
+namespace net {
+namespace test {
+class HpackDecoder2Peer;
+} // namespace test
+
+class NET_EXPORT_PRIVATE HpackDecoder2 : public HpackDecoderInterface,
+ HpackEntryDecoderListener {
+ public:
+ friend test::HpackDecoder2Peer;
+ HpackDecoder2();
+ ~HpackDecoder2() override;
+
+ // Override the interface methods:
+
+ void ApplyHeaderTableSizeSetting(size_t size_setting) override;
+ void HandleControlFrameHeadersStart(
+ SpdyHeadersHandlerInterface* handler) override;
+ bool HandleControlFrameHeadersData(const char* headers_data,
+ size_t headers_data_length) override;
+ bool HandleControlFrameHeadersComplete(size_t* compressed_len) override;
+ const SpdyHeaderBlock& decoded_block() const override;
+ void SetHeaderTableDebugVisitor(
+ std::unique_ptr<HpackHeaderTable::DebugVisitorInterface> visitor)
+ override;
+ void set_max_decode_buffer_size_bytes(
+ size_t max_decode_buffer_size_bytes) override;
+
+ protected:
+ // Override the HpackEntryDecoderListener methods:
+
+ void OnIndexedHeader(size_t index) override;
+ void OnStartLiteralHeader(HpackEntryType entry_type,
+ size_t maybe_name_index) override;
+ void OnNameStart(bool huffman_encoded, size_t len) override;
+ void OnNameData(const char* data, size_t len) override;
+ void OnNameEnd() override;
+ void OnValueStart(bool huffman_encoded, size_t len) override;
+ void OnValueData(const char* data, size_t len) override;
+ void OnValueEnd() override;
+ void OnDynamicTableSizeUpdate(size_t size) override;
+
+ private:
+ // Called when a complete header entry has been decoded, with the name and
+ // value of the entry. If check_header_order_ is true, confirms that
+ // pseudo-headers don't appear after normal headers, else it treats the
+ // headers as malformed, as per sections 8.1.2.3. of the HTTP2 specification.
+ // Calls handler_->OnHeader() if there is a handler, else adds the header
+ // to decoded_block_.
+ void HandleHeaderRepresentation(base::StringPiece name,
+ base::StringPiece value);
+
+ // Reset state in preparation for decoding a new HPACK block. Does not reset
+ // the dynamic table.
+ void Reset();
+
+ // Called when an error is detected while decoding. Replaces the listener
+ // in the HpackBlockDecoder with the no-op listener.
+ void SetErrorDetected();
+
+ // Enforce the limit on the maximum size of strings that can be buffered.
+ // It happens that this test is made after the strings have been buffered,
+ // but that isn't a problem because we don't pass enormous buffers into
+ // HandleControlFrameHeadersData.
+ bool EnforceMaxDecodeBufferSize();
+
+ HpackHeaderTable header_table_;
+ SpdyHeaderBlock decoded_block_;
+
+ // Scratch space for storing decoded literals.
+ HpackDecoderStringBuffer name_, value_;
+
+ // If non-NULL, handles decoded headers.
+ SpdyHeadersHandlerInterface* handler_;
+
+ HpackEntryDecoderNoOpListener no_op_listener_;
+
+ // Total bytes that have been received as input (i.e. HPACK encoded).
+ size_t total_hpack_bytes_;
+
+ // Total bytes of the name and value strings in the current HPACK block.
+ size_t total_header_bytes_;
+
+ // How much encoded data this decoder is willing to buffer.
+ size_t max_decode_buffer_size_bytes_ = 32 * 1024; // 32 KB
+
+ HpackBlockDecoder hpack_block_decoder_;
+
+ // Count of Dynamic Table Size Updates seen in the current HPACK block.
+ uint32_t size_update_count_;
+
+ // The type of the current header entry (with literals) that is being decoded.
+ HpackEntryType entry_type_;
+
+ // Has a header been seen in the current HPACK block?
+ bool header_seen_;
+
+ // Did the HpackBlockDecoder stop in the middle of an entry?
+ bool in_progress_;
+
+ // Has an error been detected while decoding the HPACK block?
+ bool error_detected_;
+
+ // Flag to keep track of having seen the header block start. Needed at the
+ // moment because HandleControlFrameHeadersStart won't be called if a handler
+ // is not being provided by the caller.
+ // TODO(jamessynge): Consider collapsing several of these bools into a single
+ // enum representing the state of the decoding process.
+ bool header_block_started_;
+
+ DISALLOW_COPY_AND_ASSIGN(HpackDecoder2);
+};
+
+} // namespace net
+#endif // NET_SPDY_HPACK_HPACK_DECODER2_H_
diff --git a/chromium/net/spdy/hpack/hpack_decoder2_test.cc b/chromium/net/spdy/hpack/hpack_decoder2_test.cc
new file mode 100644
index 00000000000..8c70051e2c1
--- /dev/null
+++ b/chromium/net/spdy/hpack/hpack_decoder2_test.cc
@@ -0,0 +1,959 @@
+// Copyright 2016 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.
+
+#include "net/spdy/hpack/hpack_decoder2.h"
+
+// Tests of HpackDecoder2.
+
+#include <string>
+#include <tuple>
+#include <utility>
+#include <vector>
+
+#include "base/logging.h"
+#include "base/strings/string_piece.h"
+#include "net/http2/hpack/tools/hpack_block_builder.h"
+#include "net/http2/tools/http2_random.h"
+#include "net/spdy/hpack/hpack_encoder.h"
+#include "net/spdy/hpack/hpack_entry.h"
+#include "net/spdy/hpack/hpack_huffman_table.h"
+#include "net/spdy/hpack/hpack_output_stream.h"
+#include "net/spdy/spdy_test_utils.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+using base::StringPiece;
+using std::string;
+
+namespace net {
+namespace test {
+
+class HpackDecoder2Peer {
+ public:
+ explicit HpackDecoder2Peer(HpackDecoder2* decoder) : decoder_(decoder) {}
+
+ void HandleHeaderRepresentation(StringPiece name, StringPiece value) {
+ decoder_->HandleHeaderRepresentation(name, value);
+ }
+ HpackHeaderTable* header_table() { return &decoder_->header_table_; }
+
+ private:
+ HpackDecoder2* decoder_;
+};
+
+namespace {
+
+using testing::ElementsAre;
+using testing::Pair;
+
+// Is HandleControlFrameHeadersStart to be called, and with what value?
+enum StartChoice { START_WITH_HANDLER, START_WITHOUT_HANDLER, NO_START };
+
+class HpackDecoder2Test
+ : public ::testing::TestWithParam<std::tuple<StartChoice, bool>> {
+ protected:
+ HpackDecoder2Test() : decoder_(), decoder_peer_(&decoder_) {}
+
+ void SetUp() override {
+ std::tie(start_choice_, randomly_split_input_buffer_) = GetParam();
+ }
+
+ void HandleControlFrameHeadersStart() {
+ switch (start_choice_) {
+ case START_WITH_HANDLER:
+ decoder_.HandleControlFrameHeadersStart(&handler_);
+ break;
+ case START_WITHOUT_HANDLER:
+ decoder_.HandleControlFrameHeadersStart(nullptr);
+ break;
+ case NO_START:
+ break;
+ }
+ }
+
+ bool HandleControlFrameHeadersData(StringPiece str) {
+ return decoder_.HandleControlFrameHeadersData(str.data(), str.size());
+ }
+
+ bool HandleControlFrameHeadersComplete(size_t* size) {
+ return decoder_.HandleControlFrameHeadersComplete(size);
+ }
+
+ bool DecodeHeaderBlock(StringPiece str) {
+ // Don't call this again if HandleControlFrameHeadersData failed previously.
+ EXPECT_FALSE(decode_has_failed_);
+ HandleControlFrameHeadersStart();
+ if (randomly_split_input_buffer_) {
+ do {
+ // Decode some fragment of the remaining bytes.
+ size_t bytes = str.length();
+ if (!str.empty()) {
+ bytes = (random_.Rand8() % str.length()) + 1;
+ }
+ EXPECT_LE(bytes, str.length());
+ if (!HandleControlFrameHeadersData(str.substr(0, bytes))) {
+ decode_has_failed_ = true;
+ return false;
+ }
+ str.remove_prefix(bytes);
+ } while (!str.empty());
+ } else if (!HandleControlFrameHeadersData(str)) {
+ decode_has_failed_ = true;
+ return false;
+ }
+ if (!HandleControlFrameHeadersComplete(nullptr)) {
+ decode_has_failed_ = true;
+ return false;
+ }
+ return true;
+ }
+
+ const SpdyHeaderBlock& decoded_block() const {
+ if (start_choice_ == START_WITH_HANDLER) {
+ return handler_.decoded_block();
+ } else {
+ return decoder_.decoded_block();
+ }
+ }
+
+ const SpdyHeaderBlock& DecodeBlockExpectingSuccess(StringPiece str) {
+ EXPECT_TRUE(DecodeHeaderBlock(str));
+ return decoded_block();
+ }
+
+ void expectEntry(size_t index,
+ size_t size,
+ const string& name,
+ const string& value) {
+ const HpackEntry* entry = decoder_peer_.header_table()->GetByIndex(index);
+ EXPECT_EQ(name, entry->name()) << "index " << index;
+ EXPECT_EQ(value, entry->value());
+ EXPECT_EQ(size, entry->Size());
+ EXPECT_EQ(index, decoder_peer_.header_table()->IndexOf(entry));
+ }
+
+ SpdyHeaderBlock MakeHeaderBlock(
+ const std::vector<std::pair<string, string>>& headers) {
+ SpdyHeaderBlock result;
+ for (const auto& kv : headers) {
+ result.AppendValueOrAddHeader(kv.first, kv.second);
+ }
+ return result;
+ }
+
+ Http2Random random_;
+ HpackDecoder2 decoder_;
+ test::HpackDecoder2Peer decoder_peer_;
+ TestHeadersHandler handler_;
+ StartChoice start_choice_;
+ bool randomly_split_input_buffer_;
+ bool decode_has_failed_ = false;
+};
+
+INSTANTIATE_TEST_CASE_P(
+ StartChoiceAndRandomlySplitChoice,
+ HpackDecoder2Test,
+ ::testing::Combine(
+ ::testing::Values(START_WITH_HANDLER, START_WITHOUT_HANDLER, NO_START),
+ ::testing::Bool()));
+
+TEST_P(HpackDecoder2Test, AddHeaderDataWithHandleControlFrameHeadersData) {
+ // The hpack decode buffer size is limited in size. This test verifies that
+ // adding encoded data under that limit is accepted, and data that exceeds the
+ // limit is rejected.
+ HandleControlFrameHeadersStart();
+ const size_t kMaxBufferSizeBytes = 50;
+ const string a_value = string(49, 'x');
+ decoder_.set_max_decode_buffer_size_bytes(kMaxBufferSizeBytes);
+ {
+ HpackBlockBuilder hbb;
+ hbb.AppendLiteralNameAndValue(HpackEntryType::kNeverIndexedLiteralHeader,
+ false, "a", false, a_value);
+ const auto& s = hbb.buffer();
+ EXPECT_TRUE(decoder_.HandleControlFrameHeadersData(s.data(), s.size()));
+ }
+ {
+ HpackBlockBuilder hbb;
+ hbb.AppendLiteralNameAndValue(HpackEntryType::kNeverIndexedLiteralHeader,
+ false, "b", false, string(51, 'x'));
+ const auto& s = hbb.buffer();
+ EXPECT_FALSE(decoder_.HandleControlFrameHeadersData(s.data(), s.size()));
+ }
+
+ SpdyHeaderBlock expected_block = MakeHeaderBlock({{"a", a_value}});
+ EXPECT_EQ(expected_block, decoded_block());
+}
+
+TEST_P(HpackDecoder2Test, NameTooLong) {
+ // Verify that a name longer than the allowed size generates an error.
+ const size_t kMaxBufferSizeBytes = 50;
+ const string name = string(2 * kMaxBufferSizeBytes, 'x');
+ const string value = "abc";
+
+ decoder_.set_max_decode_buffer_size_bytes(kMaxBufferSizeBytes);
+
+ HpackBlockBuilder hbb;
+ hbb.AppendLiteralNameAndValue(HpackEntryType::kNeverIndexedLiteralHeader,
+ false, name, false, value);
+
+ const size_t fragment_size = (3 * kMaxBufferSizeBytes) / 2;
+ const string fragment = hbb.buffer().substr(0, fragment_size);
+
+ HandleControlFrameHeadersStart();
+ EXPECT_FALSE(HandleControlFrameHeadersData(fragment));
+}
+
+TEST_P(HpackDecoder2Test, HeaderTooLongToBuffer) {
+ // Verify that a header longer than the allowed size generates an error if
+ // it isn't all in one input buffer.
+ const string name = "some-key";
+ const string value = "some-value";
+ const size_t kMaxBufferSizeBytes = name.size() + value.size() - 2;
+ decoder_.set_max_decode_buffer_size_bytes(kMaxBufferSizeBytes);
+
+ HpackBlockBuilder hbb;
+ hbb.AppendLiteralNameAndValue(HpackEntryType::kNeverIndexedLiteralHeader,
+ false, name, false, value);
+ const size_t fragment_size = hbb.size() - 1;
+ const string fragment = hbb.buffer().substr(0, fragment_size);
+
+ HandleControlFrameHeadersStart();
+ EXPECT_FALSE(HandleControlFrameHeadersData(fragment));
+}
+
+// Decode with incomplete data in buffer.
+TEST_P(HpackDecoder2Test, DecodeWithIncompleteData) {
+ HandleControlFrameHeadersStart();
+
+ // No need to wait for more data.
+ EXPECT_TRUE(HandleControlFrameHeadersData("\x82\x85\x82"));
+ std::vector<std::pair<string, string>> expected_headers = {
+ {":method", "GET"}, {":path", "/index.html"}, {":method", "GET"}};
+
+ SpdyHeaderBlock expected_block1 = MakeHeaderBlock(expected_headers);
+ EXPECT_EQ(expected_block1, decoded_block());
+
+ // Full and partial headers, won't add partial to the headers.
+ EXPECT_TRUE(
+ HandleControlFrameHeadersData("\x40\x03goo"
+ "\x03gar\xbe\x40\x04spam"));
+ expected_headers.push_back({"goo", "gar"});
+ expected_headers.push_back({"goo", "gar"});
+
+ SpdyHeaderBlock expected_block2 = MakeHeaderBlock(expected_headers);
+ EXPECT_EQ(expected_block2, decoded_block());
+
+ // Add the needed data.
+ EXPECT_TRUE(HandleControlFrameHeadersData("\x04gggs"));
+
+ size_t size = 0;
+ EXPECT_TRUE(HandleControlFrameHeadersComplete(&size));
+ EXPECT_EQ(24u, size);
+
+ expected_headers.push_back({"spam", "gggs"});
+
+ SpdyHeaderBlock expected_block3 = MakeHeaderBlock(expected_headers);
+ EXPECT_EQ(expected_block3, decoded_block());
+}
+
+TEST_P(HpackDecoder2Test, HandleHeaderRepresentation) {
+ // Make sure the decoder is properly initialized.
+ HandleControlFrameHeadersStart();
+ HandleControlFrameHeadersData("");
+
+ // All cookie crumbs are joined.
+ decoder_peer_.HandleHeaderRepresentation("cookie", " part 1");
+ decoder_peer_.HandleHeaderRepresentation("cookie", "part 2 ");
+ decoder_peer_.HandleHeaderRepresentation("cookie", "part3");
+
+ // Already-delimited headers are passed through.
+ decoder_peer_.HandleHeaderRepresentation("passed-through",
+ string("foo\0baz", 7));
+
+ // Other headers are joined on \0. Case matters.
+ decoder_peer_.HandleHeaderRepresentation("joined", "not joined");
+ decoder_peer_.HandleHeaderRepresentation("joineD", "value 1");
+ decoder_peer_.HandleHeaderRepresentation("joineD", "value 2");
+
+ // Empty headers remain empty.
+ decoder_peer_.HandleHeaderRepresentation("empty", "");
+
+ // Joined empty headers work as expected.
+ decoder_peer_.HandleHeaderRepresentation("empty-joined", "");
+ decoder_peer_.HandleHeaderRepresentation("empty-joined", "foo");
+ decoder_peer_.HandleHeaderRepresentation("empty-joined", "");
+ decoder_peer_.HandleHeaderRepresentation("empty-joined", "");
+
+ // Non-contiguous cookie crumb.
+ decoder_peer_.HandleHeaderRepresentation("cookie", " fin!");
+
+ // Finish and emit all headers.
+ decoder_.HandleControlFrameHeadersComplete(nullptr);
+
+ // Resulting decoded headers are in the same order as the inputs.
+ EXPECT_THAT(decoded_block(),
+ ElementsAre(Pair("cookie", " part 1; part 2 ; part3; fin!"),
+ Pair("passed-through", StringPiece("foo\0baz", 7)),
+ Pair("joined", "not joined"),
+ Pair("joineD", StringPiece("value 1\0value 2", 15)),
+ Pair("empty", ""),
+ Pair("empty-joined", StringPiece("\0foo\0\0", 6))));
+}
+
+// Decoding indexed static table field should work.
+TEST_P(HpackDecoder2Test, IndexedHeaderStatic) {
+ // Reference static table entries #2 and #5.
+ const SpdyHeaderBlock& header_set1 = DecodeBlockExpectingSuccess("\x82\x85");
+ SpdyHeaderBlock expected_header_set1;
+ expected_header_set1[":method"] = "GET";
+ expected_header_set1[":path"] = "/index.html";
+ EXPECT_EQ(expected_header_set1, header_set1);
+
+ // Reference static table entry #2.
+ const SpdyHeaderBlock& header_set2 = DecodeBlockExpectingSuccess("\x82");
+ SpdyHeaderBlock expected_header_set2;
+ expected_header_set2[":method"] = "GET";
+ EXPECT_EQ(expected_header_set2, header_set2);
+}
+
+TEST_P(HpackDecoder2Test, IndexedHeaderDynamic) {
+ // First header block: add an entry to header table.
+ const SpdyHeaderBlock& header_set1 = DecodeBlockExpectingSuccess(
+ "\x40\x03"
+ "foo"
+ "\x03"
+ "bar");
+ SpdyHeaderBlock expected_header_set1;
+ expected_header_set1["foo"] = "bar";
+ EXPECT_EQ(expected_header_set1, header_set1);
+
+ // Second header block: add another entry to header table.
+ const SpdyHeaderBlock& header_set2 = DecodeBlockExpectingSuccess(
+ "\xbe\x40\x04"
+ "spam"
+ "\x04"
+ "eggs");
+ SpdyHeaderBlock expected_header_set2;
+ expected_header_set2["foo"] = "bar";
+ expected_header_set2["spam"] = "eggs";
+ EXPECT_EQ(expected_header_set2, header_set2);
+
+ // Third header block: refer to most recently added entry.
+ const SpdyHeaderBlock& header_set3 = DecodeBlockExpectingSuccess("\xbe");
+ SpdyHeaderBlock expected_header_set3;
+ expected_header_set3["spam"] = "eggs";
+ EXPECT_EQ(expected_header_set3, header_set3);
+}
+
+// Test a too-large indexed header.
+TEST_P(HpackDecoder2Test, InvalidIndexedHeader) {
+ // High-bit set, and a prefix of one more than the number of static entries.
+ EXPECT_FALSE(DecodeHeaderBlock("\xbe"));
+}
+
+TEST_P(HpackDecoder2Test, ContextUpdateMaximumSize) {
+ EXPECT_EQ(kDefaultHeaderTableSizeSetting,
+ decoder_peer_.header_table()->max_size());
+ string input;
+ {
+ // Maximum-size update with size 126. Succeeds.
+ HpackOutputStream output_stream;
+ output_stream.AppendPrefix(kHeaderTableSizeUpdateOpcode);
+ output_stream.AppendUint32(126);
+
+ output_stream.TakeString(&input);
+ EXPECT_TRUE(DecodeHeaderBlock(StringPiece(input)));
+ EXPECT_EQ(126u, decoder_peer_.header_table()->max_size());
+ }
+ {
+ // Maximum-size update with kDefaultHeaderTableSizeSetting. Succeeds.
+ HpackOutputStream output_stream;
+ output_stream.AppendPrefix(kHeaderTableSizeUpdateOpcode);
+ output_stream.AppendUint32(kDefaultHeaderTableSizeSetting);
+
+ output_stream.TakeString(&input);
+ EXPECT_TRUE(DecodeHeaderBlock(StringPiece(input)));
+ EXPECT_EQ(kDefaultHeaderTableSizeSetting,
+ decoder_peer_.header_table()->max_size());
+ }
+ {
+ // Maximum-size update with kDefaultHeaderTableSizeSetting + 1. Fails.
+ HpackOutputStream output_stream;
+ output_stream.AppendPrefix(kHeaderTableSizeUpdateOpcode);
+ output_stream.AppendUint32(kDefaultHeaderTableSizeSetting + 1);
+
+ output_stream.TakeString(&input);
+ EXPECT_FALSE(DecodeHeaderBlock(StringPiece(input)));
+ EXPECT_EQ(kDefaultHeaderTableSizeSetting,
+ decoder_peer_.header_table()->max_size());
+ }
+}
+
+// Two HeaderTableSizeUpdates may appear at the beginning of the block
+TEST_P(HpackDecoder2Test, TwoTableSizeUpdates) {
+ string input;
+ {
+ // Should accept two table size updates, update to second one
+ HpackOutputStream output_stream;
+ output_stream.AppendPrefix(kHeaderTableSizeUpdateOpcode);
+ output_stream.AppendUint32(0);
+ output_stream.AppendPrefix(kHeaderTableSizeUpdateOpcode);
+ output_stream.AppendUint32(122);
+
+ output_stream.TakeString(&input);
+ EXPECT_TRUE(DecodeHeaderBlock(StringPiece(input)));
+ EXPECT_EQ(122u, decoder_peer_.header_table()->max_size());
+ }
+}
+
+// Three HeaderTableSizeUpdates should result in an error
+TEST_P(HpackDecoder2Test, ThreeTableSizeUpdatesError) {
+ string input;
+ {
+ // Should reject three table size updates, update to second one
+ HpackOutputStream output_stream;
+ output_stream.AppendPrefix(kHeaderTableSizeUpdateOpcode);
+ output_stream.AppendUint32(5);
+ output_stream.AppendPrefix(kHeaderTableSizeUpdateOpcode);
+ output_stream.AppendUint32(10);
+ output_stream.AppendPrefix(kHeaderTableSizeUpdateOpcode);
+ output_stream.AppendUint32(15);
+
+ output_stream.TakeString(&input);
+
+ EXPECT_FALSE(DecodeHeaderBlock(StringPiece(input)));
+ EXPECT_EQ(10u, decoder_peer_.header_table()->max_size());
+ }
+}
+
+// HeaderTableSizeUpdates may only appear at the beginning of the block
+// Any other updates should result in an error
+TEST_P(HpackDecoder2Test, TableSizeUpdateSecondError) {
+ string input;
+ {
+ // Should reject a table size update appearing after a different entry
+ // The table size should remain as the default
+ HpackOutputStream output_stream;
+ output_stream.AppendBytes("\x82\x85");
+ output_stream.AppendPrefix(kHeaderTableSizeUpdateOpcode);
+ output_stream.AppendUint32(123);
+
+ output_stream.TakeString(&input);
+
+ EXPECT_FALSE(DecodeHeaderBlock(StringPiece(input)));
+ EXPECT_EQ(kDefaultHeaderTableSizeSetting,
+ decoder_peer_.header_table()->max_size());
+ }
+}
+
+// HeaderTableSizeUpdates may only appear at the beginning of the block
+// Any other updates should result in an error
+TEST_P(HpackDecoder2Test, TableSizeUpdateFirstThirdError) {
+ string input;
+ {
+ // Should reject the second table size update
+ // if a different entry appears after the first update
+ // The table size should update to the first but not the second
+ HpackOutputStream output_stream;
+ output_stream.AppendPrefix(kHeaderTableSizeUpdateOpcode);
+ output_stream.AppendUint32(60);
+ output_stream.AppendBytes("\x82\x85");
+ output_stream.AppendPrefix(kHeaderTableSizeUpdateOpcode);
+ output_stream.AppendUint32(125);
+
+ output_stream.TakeString(&input);
+
+ EXPECT_FALSE(DecodeHeaderBlock(StringPiece(input)));
+ EXPECT_EQ(60u, decoder_peer_.header_table()->max_size());
+ }
+}
+
+// Decoding two valid encoded literal headers with no indexing should
+// work.
+TEST_P(HpackDecoder2Test, LiteralHeaderNoIndexing) {
+ // First header with indexed name, second header with string literal
+ // name.
+ const char input[] = "\x04\x0c/sample/path\x00\x06:path2\x0e/sample/path/2";
+ const SpdyHeaderBlock& header_set =
+ DecodeBlockExpectingSuccess(StringPiece(input, arraysize(input) - 1));
+
+ SpdyHeaderBlock expected_header_set;
+ expected_header_set[":path"] = "/sample/path";
+ expected_header_set[":path2"] = "/sample/path/2";
+ EXPECT_EQ(expected_header_set, header_set);
+}
+
+// Decoding two valid encoded literal headers with incremental
+// indexing and string literal names should work.
+TEST_P(HpackDecoder2Test, LiteralHeaderIncrementalIndexing) {
+ const char input[] = "\x44\x0c/sample/path\x40\x06:path2\x0e/sample/path/2";
+ const SpdyHeaderBlock& header_set =
+ DecodeBlockExpectingSuccess(StringPiece(input, arraysize(input) - 1));
+
+ SpdyHeaderBlock expected_header_set;
+ expected_header_set[":path"] = "/sample/path";
+ expected_header_set[":path2"] = "/sample/path/2";
+ EXPECT_EQ(expected_header_set, header_set);
+}
+
+TEST_P(HpackDecoder2Test, LiteralHeaderWithIndexingInvalidNameIndex) {
+ decoder_.ApplyHeaderTableSizeSetting(0);
+
+ // Name is the last static index. Works.
+ EXPECT_TRUE(DecodeHeaderBlock(StringPiece("\x7d\x03ooo")));
+ // Name is one beyond the last static index. Fails.
+ EXPECT_FALSE(DecodeHeaderBlock(StringPiece("\x7e\x03ooo")));
+}
+
+TEST_P(HpackDecoder2Test, LiteralHeaderNoIndexingInvalidNameIndex) {
+ // Name is the last static index. Works.
+ EXPECT_TRUE(DecodeHeaderBlock(StringPiece("\x0f\x2e\x03ooo")));
+ // Name is one beyond the last static index. Fails.
+ EXPECT_FALSE(DecodeHeaderBlock(StringPiece("\x0f\x2f\x03ooo")));
+}
+
+TEST_P(HpackDecoder2Test, LiteralHeaderNeverIndexedInvalidNameIndex) {
+ // Name is the last static index. Works.
+ EXPECT_TRUE(DecodeHeaderBlock(StringPiece("\x1f\x2e\x03ooo")));
+ // Name is one beyond the last static index. Fails.
+ EXPECT_FALSE(DecodeHeaderBlock(StringPiece("\x1f\x2f\x03ooo")));
+}
+
+TEST_P(HpackDecoder2Test, TruncatedIndex) {
+ // Indexed Header, varint for index requires multiple bytes,
+ // but only one provided.
+ EXPECT_FALSE(DecodeHeaderBlock(StringPiece("\xff", 1)));
+}
+
+TEST_P(HpackDecoder2Test, TruncatedHuffmanLiteral) {
+ // Literal value, Huffman encoded, but with the last byte missing (i.e.
+ // drop the final ff shown below).
+ //
+ // 41 | == Literal indexed ==
+ // | Indexed name (idx = 1)
+ // | :authority
+ // 8c | Literal value (len = 12)
+ // | Huffman encoded:
+ // f1e3 c2e5 f23a 6ba0 ab90 f4ff | .....:k.....
+ // | Decoded:
+ // | www.example.com
+ // | -> :authority: www.example.com
+
+ string first = a2b_hex("418cf1e3c2e5f23a6ba0ab90f4ff");
+ EXPECT_TRUE(DecodeHeaderBlock(first));
+ first = a2b_hex("418cf1e3c2e5f23a6ba0ab90f4");
+ EXPECT_FALSE(DecodeHeaderBlock(first));
+}
+
+TEST_P(HpackDecoder2Test, HuffmanEOSError) {
+ // Literal value, Huffman encoded, but with an additional ff byte at the end
+ // of the string, i.e. an EOS that is longer than permitted.
+ //
+ // 41 | == Literal indexed ==
+ // | Indexed name (idx = 1)
+ // | :authority
+ // 8d | Literal value (len = 13)
+ // | Huffman encoded:
+ // f1e3 c2e5 f23a 6ba0 ab90 f4ff | .....:k.....
+ // | Decoded:
+ // | www.example.com
+ // | -> :authority: www.example.com
+
+ string first = a2b_hex("418cf1e3c2e5f23a6ba0ab90f4ff");
+ EXPECT_TRUE(DecodeHeaderBlock(first));
+ first = a2b_hex("418df1e3c2e5f23a6ba0ab90f4ffff");
+ EXPECT_FALSE(DecodeHeaderBlock(first));
+}
+
+// Round-tripping the header set from RFC 7541 C.3.1 should work.
+// http://httpwg.org/specs/rfc7541.html#rfc.section.C.3.1
+TEST_P(HpackDecoder2Test, BasicC31) {
+ HpackEncoder encoder(ObtainHpackHuffmanTable());
+
+ SpdyHeaderBlock expected_header_set;
+ expected_header_set[":method"] = "GET";
+ expected_header_set[":scheme"] = "http";
+ expected_header_set[":path"] = "/";
+ expected_header_set[":authority"] = "www.example.com";
+
+ string encoded_header_set;
+ EXPECT_TRUE(
+ encoder.EncodeHeaderSet(expected_header_set, &encoded_header_set));
+
+ EXPECT_TRUE(DecodeHeaderBlock(encoded_header_set));
+ EXPECT_EQ(expected_header_set, decoded_block());
+}
+
+// RFC 7541, Section C.4: Request Examples with Huffman Coding
+// http://httpwg.org/specs/rfc7541.html#rfc.section.C.4
+TEST_P(HpackDecoder2Test, SectionC4RequestHuffmanExamples) {
+ // TODO(jamessynge): Use net/http2/hpack/tools/hpack_example.h to parse the
+ // example directly, instead of having it as a comment.
+ // 82 | == Indexed - Add ==
+ // | idx = 2
+ // | -> :method: GET
+ // 86 | == Indexed - Add ==
+ // | idx = 6
+ // | -> :scheme: http
+ // 84 | == Indexed - Add ==
+ // | idx = 4
+ // | -> :path: /
+ // 41 | == Literal indexed ==
+ // | Indexed name (idx = 1)
+ // | :authority
+ // 8c | Literal value (len = 12)
+ // | Huffman encoded:
+ // f1e3 c2e5 f23a 6ba0 ab90 f4ff | .....:k.....
+ // | Decoded:
+ // | www.example.com
+ // | -> :authority: www.example.com
+ string first = a2b_hex("828684418cf1e3c2e5f23a6ba0ab90f4ff");
+ const SpdyHeaderBlock& first_header_set = DecodeBlockExpectingSuccess(first);
+
+ EXPECT_THAT(first_header_set,
+ ElementsAre(
+ // clang-format off
+ Pair(":method", "GET"),
+ Pair(":scheme", "http"),
+ Pair(":path", "/"),
+ Pair(":authority", "www.example.com")));
+ // clang-format on
+
+ expectEntry(62, 57, ":authority", "www.example.com");
+ EXPECT_EQ(57u, decoder_peer_.header_table()->size());
+
+ // 82 | == Indexed - Add ==
+ // | idx = 2
+ // | -> :method: GET
+ // 86 | == Indexed - Add ==
+ // | idx = 6
+ // | -> :scheme: http
+ // 84 | == Indexed - Add ==
+ // | idx = 4
+ // | -> :path: /
+ // be | == Indexed - Add ==
+ // | idx = 62
+ // | -> :authority: www.example.com
+ // 58 | == Literal indexed ==
+ // | Indexed name (idx = 24)
+ // | cache-control
+ // 86 | Literal value (len = 8)
+ // | Huffman encoded:
+ // a8eb 1064 9cbf | ...d..
+ // | Decoded:
+ // | no-cache
+ // | -> cache-control: no-cache
+
+ string second = a2b_hex("828684be5886a8eb10649cbf");
+ const SpdyHeaderBlock& second_header_set =
+ DecodeBlockExpectingSuccess(second);
+
+ EXPECT_THAT(second_header_set,
+ ElementsAre(
+ // clang-format off
+ Pair(":method", "GET"),
+ Pair(":scheme", "http"),
+ Pair(":path", "/"),
+ Pair(":authority", "www.example.com"),
+ Pair("cache-control", "no-cache")));
+ // clang-format on
+
+ expectEntry(62, 53, "cache-control", "no-cache");
+ expectEntry(63, 57, ":authority", "www.example.com");
+ EXPECT_EQ(110u, decoder_peer_.header_table()->size());
+
+ // 82 | == Indexed - Add ==
+ // | idx = 2
+ // | -> :method: GET
+ // 87 | == Indexed - Add ==
+ // | idx = 7
+ // | -> :scheme: https
+ // 85 | == Indexed - Add ==
+ // | idx = 5
+ // | -> :path: /index.html
+ // bf | == Indexed - Add ==
+ // | idx = 63
+ // | -> :authority: www.example.com
+ // 40 | == Literal indexed ==
+ // 88 | Literal name (len = 10)
+ // | Huffman encoded:
+ // 25a8 49e9 5ba9 7d7f | %.I.[.}.
+ // | Decoded:
+ // | custom-key
+ // 89 | Literal value (len = 12)
+ // | Huffman encoded:
+ // 25a8 49e9 5bb8 e8b4 bf | %.I.[....
+ // | Decoded:
+ // | custom-value
+ // | -> custom-key: custom-value
+ string third = a2b_hex("828785bf408825a849e95ba97d7f8925a849e95bb8e8b4bf");
+ const SpdyHeaderBlock& third_header_set = DecodeBlockExpectingSuccess(third);
+
+ EXPECT_THAT(
+ third_header_set,
+ ElementsAre(
+ // clang-format off
+ Pair(":method", "GET"),
+ Pair(":scheme", "https"),
+ Pair(":path", "/index.html"),
+ Pair(":authority", "www.example.com"),
+ Pair("custom-key", "custom-value")));
+ // clang-format on
+
+ expectEntry(62, 54, "custom-key", "custom-value");
+ expectEntry(63, 53, "cache-control", "no-cache");
+ expectEntry(64, 57, ":authority", "www.example.com");
+ EXPECT_EQ(164u, decoder_peer_.header_table()->size());
+}
+
+// RFC 7541, Section C.6: Response Examples with Huffman Coding
+// http://httpwg.org/specs/rfc7541.html#rfc.section.C.6
+TEST_P(HpackDecoder2Test, SectionC6ResponseHuffmanExamples) {
+ decoder_.ApplyHeaderTableSizeSetting(256);
+
+ // 48 | == Literal indexed ==
+ // | Indexed name (idx = 8)
+ // | :status
+ // 82 | Literal value (len = 3)
+ // | Huffman encoded:
+ // 6402 | d.
+ // | Decoded:
+ // | 302
+ // | -> :status: 302
+ // 58 | == Literal indexed ==
+ // | Indexed name (idx = 24)
+ // | cache-control
+ // 85 | Literal value (len = 7)
+ // | Huffman encoded:
+ // aec3 771a 4b | ..w.K
+ // | Decoded:
+ // | private
+ // | -> cache-control: private
+ // 61 | == Literal indexed ==
+ // | Indexed name (idx = 33)
+ // | date
+ // 96 | Literal value (len = 29)
+ // | Huffman encoded:
+ // d07a be94 1054 d444 a820 0595 040b 8166 | .z...T.D. .....f
+ // e082 a62d 1bff | ...-..
+ // | Decoded:
+ // | Mon, 21 Oct 2013 20:13:21
+ // | GMT
+ // | -> date: Mon, 21 Oct 2013
+ // | 20:13:21 GMT
+ // 6e | == Literal indexed ==
+ // | Indexed name (idx = 46)
+ // | location
+ // 91 | Literal value (len = 23)
+ // | Huffman encoded:
+ // 9d29 ad17 1863 c78f 0b97 c8e9 ae82 ae43 | .)...c.........C
+ // d3 | .
+ // | Decoded:
+ // | https://www.example.com
+ // | -> location: https://www.e
+ // | xample.com
+
+ string first = a2b_hex(
+ "488264025885aec3771a4b6196d07abe"
+ "941054d444a8200595040b8166e082a6"
+ "2d1bff6e919d29ad171863c78f0b97c8"
+ "e9ae82ae43d3");
+ const SpdyHeaderBlock& first_header_set = DecodeBlockExpectingSuccess(first);
+
+ EXPECT_THAT(first_header_set,
+ ElementsAre(
+ // clang-format off
+ Pair(":status", "302"),
+ Pair("cache-control", "private"),
+ Pair("date", "Mon, 21 Oct 2013 20:13:21 GMT"),
+ Pair("location", "https://www.example.com")));
+ // clang-format on
+
+ expectEntry(62, 63, "location", "https://www.example.com");
+ expectEntry(63, 65, "date", "Mon, 21 Oct 2013 20:13:21 GMT");
+ expectEntry(64, 52, "cache-control", "private");
+ expectEntry(65, 42, ":status", "302");
+ EXPECT_EQ(222u, decoder_peer_.header_table()->size());
+
+ // 48 | == Literal indexed ==
+ // | Indexed name (idx = 8)
+ // | :status
+ // 83 | Literal value (len = 3)
+ // | Huffman encoded:
+ // 640e ff | d..
+ // | Decoded:
+ // | 307
+ // | - evict: :status: 302
+ // | -> :status: 307
+ // c1 | == Indexed - Add ==
+ // | idx = 65
+ // | -> cache-control: private
+ // c0 | == Indexed - Add ==
+ // | idx = 64
+ // | -> date: Mon, 21 Oct 2013
+ // | 20:13:21 GMT
+ // bf | == Indexed - Add ==
+ // | idx = 63
+ // | -> location:
+ // | https://www.example.com
+ string second = a2b_hex("4883640effc1c0bf");
+ const SpdyHeaderBlock& second_header_set =
+ DecodeBlockExpectingSuccess(second);
+
+ EXPECT_THAT(second_header_set,
+ ElementsAre(
+ // clang-format off
+ Pair(":status", "307"),
+ Pair("cache-control", "private"),
+ Pair("date", "Mon, 21 Oct 2013 20:13:21 GMT"),
+ Pair("location", "https://www.example.com")));
+ // clang-format on
+
+ expectEntry(62, 42, ":status", "307");
+ expectEntry(63, 63, "location", "https://www.example.com");
+ expectEntry(64, 65, "date", "Mon, 21 Oct 2013 20:13:21 GMT");
+ expectEntry(65, 52, "cache-control", "private");
+ EXPECT_EQ(222u, decoder_peer_.header_table()->size());
+
+ // 88 | == Indexed - Add ==
+ // | idx = 8
+ // | -> :status: 200
+ // c1 | == Indexed - Add ==
+ // | idx = 65
+ // | -> cache-control: private
+ // 61 | == Literal indexed ==
+ // | Indexed name (idx = 33)
+ // | date
+ // 96 | Literal value (len = 22)
+ // | Huffman encoded:
+ // d07a be94 1054 d444 a820 0595 040b 8166 | .z...T.D. .....f
+ // e084 a62d 1bff | ...-..
+ // | Decoded:
+ // | Mon, 21 Oct 2013 20:13:22
+ // | GMT
+ // | - evict: cache-control:
+ // | private
+ // | -> date: Mon, 21 Oct 2013
+ // | 20:13:22 GMT
+ // c0 | == Indexed - Add ==
+ // | idx = 64
+ // | -> location:
+ // | https://www.example.com
+ // 5a | == Literal indexed ==
+ // | Indexed name (idx = 26)
+ // | content-encoding
+ // 83 | Literal value (len = 3)
+ // | Huffman encoded:
+ // 9bd9 ab | ...
+ // | Decoded:
+ // | gzip
+ // | - evict: date: Mon, 21 Oct
+ // | 2013 20:13:21 GMT
+ // | -> content-encoding: gzip
+ // 77 | == Literal indexed ==
+ // | Indexed name (idx = 55)
+ // | set-cookie
+ // ad | Literal value (len = 45)
+ // | Huffman encoded:
+ // 94e7 821d d7f2 e6c7 b335 dfdf cd5b 3960 | .........5...[9`
+ // d5af 2708 7f36 72c1 ab27 0fb5 291f 9587 | ..'..6r..'..)...
+ // 3160 65c0 03ed 4ee5 b106 3d50 07 | 1`e...N...=P.
+ // | Decoded:
+ // | foo=ASDJKHQKBZXOQWEOPIUAXQ
+ // | WEOIU; max-age=3600; versi
+ // | on=1
+ // | - evict: location:
+ // | https://www.example.com
+ // | - evict: :status: 307
+ // | -> set-cookie: foo=ASDJKHQ
+ // | KBZXOQWEOPIUAXQWEOIU;
+ // | max-age=3600; version=1
+ string third = a2b_hex(
+ "88c16196d07abe941054d444a8200595"
+ "040b8166e084a62d1bffc05a839bd9ab"
+ "77ad94e7821dd7f2e6c7b335dfdfcd5b"
+ "3960d5af27087f3672c1ab270fb5291f"
+ "9587316065c003ed4ee5b1063d5007");
+ const SpdyHeaderBlock& third_header_set = DecodeBlockExpectingSuccess(third);
+
+ EXPECT_THAT(third_header_set,
+ ElementsAre(
+ // clang-format off
+ Pair(":status", "200"),
+ Pair("cache-control", "private"),
+ Pair("date", "Mon, 21 Oct 2013 20:13:22 GMT"),
+ Pair("location", "https://www.example.com"),
+ Pair("content-encoding", "gzip"),
+ Pair("set-cookie", "foo=ASDJKHQKBZXOQWEOPIUAXQWEOIU;"
+ " max-age=3600; version=1")));
+ // clang-format on
+
+ expectEntry(62, 98, "set-cookie",
+ "foo=ASDJKHQKBZXOQWEOPIUAXQWEOIU;"
+ " max-age=3600; version=1");
+ expectEntry(63, 52, "content-encoding", "gzip");
+ expectEntry(64, 65, "date", "Mon, 21 Oct 2013 20:13:22 GMT");
+ EXPECT_EQ(215u, decoder_peer_.header_table()->size());
+}
+
+// Regression test: Found that entries with dynamic indexed names and literal
+// values caused "use after free" MSAN failures if the name was evicted as it
+// was being re-used.
+TEST_P(HpackDecoder2Test, ReuseNameOfEvictedEntry) {
+ // Each entry is measured as 32 bytes plus the sum of the lengths of the name
+ // and the value. Set the size big enough for at most one entry, and a fairly
+ // small one at that (31 ASCII characters).
+ decoder_.ApplyHeaderTableSizeSetting(63);
+
+ HpackBlockBuilder hbb;
+
+ const StringPiece name("some-name");
+ const StringPiece value1("some-value");
+ const StringPiece value2("another-value");
+ const StringPiece value3("yet-another-value");
+
+ // Add an entry that will become the first in the dynamic table, entry 62.
+ hbb.AppendLiteralNameAndValue(HpackEntryType::kIndexedLiteralHeader, false,
+ name, false, value1);
+
+ // Confirm that entry has been added by re-using it.
+ hbb.AppendIndexedHeader(62);
+
+ // Add another entry referring to the name of the first. This will evict the
+ // first.
+ hbb.AppendNameIndexAndLiteralValue(HpackEntryType::kIndexedLiteralHeader, 62,
+ false, value2);
+
+ // Confirm that entry has been added by re-using it.
+ hbb.AppendIndexedHeader(62);
+
+ // Add another entry referring to the name of the second. This will evict the
+ // second.
+ hbb.AppendNameIndexAndLiteralValue(HpackEntryType::kIndexedLiteralHeader, 62,
+ false, value3);
+
+ // Confirm that entry has been added by re-using it.
+ hbb.AppendIndexedHeader(62);
+
+ EXPECT_TRUE(DecodeHeaderBlock(hbb.buffer()));
+
+ SpdyHeaderBlock expected_header_set;
+ expected_header_set.AppendValueOrAddHeader(name, value1);
+ expected_header_set.AppendValueOrAddHeader(name, value1);
+ expected_header_set.AppendValueOrAddHeader(name, value2);
+ expected_header_set.AppendValueOrAddHeader(name, value2);
+ expected_header_set.AppendValueOrAddHeader(name, value3);
+ expected_header_set.AppendValueOrAddHeader(name, value3);
+
+ // SpdyHeaderBlock stores these 6 strings as '\0' separated values.
+ // Make sure that is what happened.
+ string joined_values = expected_header_set[name].as_string();
+ EXPECT_EQ(joined_values.size(),
+ 2 * value1.size() + 2 * value2.size() + 2 * value3.size() + 5);
+
+ EXPECT_EQ(expected_header_set, decoded_block());
+}
+
+} // namespace
+} // namespace test
+} // namespace net
diff --git a/chromium/net/spdy/hpack/hpack_decoder3.cc b/chromium/net/spdy/hpack/hpack_decoder3.cc
new file mode 100644
index 00000000000..d2dcbeb407a
--- /dev/null
+++ b/chromium/net/spdy/hpack/hpack_decoder3.cc
@@ -0,0 +1,151 @@
+// Copyright 2017 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.
+
+#include "net/spdy/hpack/hpack_decoder3.h"
+
+#include "base/logging.h"
+#include "net/http2/decoder/decode_buffer.h"
+#include "net/http2/decoder/decode_status.h"
+
+using base::StringPiece;
+
+namespace net {
+namespace {
+const size_t kMaxDecodeBufferSizeBytes = 32 * 1024; // 32 KB
+} // namespace
+
+HpackDecoder3::HpackDecoder3()
+ : hpack_decoder_(&listener_adapter_, kMaxDecodeBufferSizeBytes),
+ max_decode_buffer_size_bytes_(kMaxDecodeBufferSizeBytes),
+ header_block_started_(false) {}
+
+HpackDecoder3::~HpackDecoder3() {}
+
+void HpackDecoder3::ApplyHeaderTableSizeSetting(size_t size_setting) {
+ DVLOG(2) << "HpackDecoder3::ApplyHeaderTableSizeSetting";
+ hpack_decoder_.ApplyHeaderTableSizeSetting(size_setting);
+}
+
+void HpackDecoder3::HandleControlFrameHeadersStart(
+ SpdyHeadersHandlerInterface* handler) {
+ DVLOG(2) << "HpackDecoder3::HandleControlFrameHeadersStart";
+ DCHECK(!header_block_started_);
+ listener_adapter_.set_handler(handler);
+}
+
+bool HpackDecoder3::HandleControlFrameHeadersData(const char* headers_data,
+ size_t headers_data_length) {
+ DVLOG(2) << "HpackDecoder3::HandleControlFrameHeadersData: len="
+ << headers_data_length;
+ if (!header_block_started_) {
+ // Initialize the decoding process here rather than in
+ // HandleControlFrameHeadersStart because that method is not always called.
+ total_hpack_bytes_ = 0;
+ header_block_started_ = true;
+ if (!hpack_decoder_.StartDecodingBlock()) {
+ header_block_started_ = false;
+ return false;
+ }
+ }
+
+ // Sometimes we get a call with headers_data==nullptr and
+ // headers_data_length==0, in which case we need to avoid creating
+ // a DecodeBuffer, which would otherwise complain.
+ if (headers_data_length > 0) {
+ DCHECK_NE(headers_data, nullptr);
+ if (headers_data_length > max_decode_buffer_size_bytes_) {
+ DVLOG(1) << "max_decode_buffer_size_bytes_ < headers_data_length: "
+ << max_decode_buffer_size_bytes_ << " < " << headers_data_length;
+ return false;
+ }
+ total_hpack_bytes_ += headers_data_length;
+ DecodeBuffer db(headers_data, headers_data_length);
+ bool ok = hpack_decoder_.DecodeFragment(&db);
+ DCHECK(!ok || db.Empty()) << "Remaining=" << db.Remaining();
+ return ok;
+ }
+ return true;
+}
+
+// TODO(jamessynge): Determine if compressed_len is needed; it is used to
+// produce UUMA stat Net.SpdyHpackDecompressionPercentage, but only for
+// SPDY3, not HTTP2.
+bool HpackDecoder3::HandleControlFrameHeadersComplete(size_t* compressed_len) {
+ DVLOG(2) << "HpackDecoder3::HandleControlFrameHeadersComplete";
+ if (compressed_len != nullptr) {
+ *compressed_len = total_hpack_bytes_;
+ }
+ if (!hpack_decoder_.EndDecodingBlock()) {
+ DVLOG(3) << "EndDecodingBlock returned false";
+ return false;
+ }
+ header_block_started_ = false;
+ return true;
+}
+
+const SpdyHeaderBlock& HpackDecoder3::decoded_block() const {
+ return listener_adapter_.decoded_block();
+}
+
+void HpackDecoder3::SetHeaderTableDebugVisitor(
+ std::unique_ptr<HpackHeaderTable::DebugVisitorInterface> visitor) {
+ DVLOG(2) << "HpackDecoder3::SetHeaderTableDebugVisitor";
+ // Dropping on the floor for now. Not sure yet if needed at all.
+}
+
+void HpackDecoder3::set_max_decode_buffer_size_bytes(
+ size_t max_decode_buffer_size_bytes) {
+ DVLOG(2) << "HpackDecoder3::set_max_decode_buffer_size_bytes";
+ max_decode_buffer_size_bytes_ = max_decode_buffer_size_bytes;
+ hpack_decoder_.set_max_string_size_bytes(max_decode_buffer_size_bytes);
+}
+
+HpackDecoder3::ListenerAdapter::ListenerAdapter() : handler_(nullptr) {}
+HpackDecoder3::ListenerAdapter::~ListenerAdapter() {}
+
+void HpackDecoder3::ListenerAdapter::set_handler(
+ SpdyHeadersHandlerInterface* handler) {
+ handler_ = handler;
+}
+
+void HpackDecoder3::ListenerAdapter::OnHeaderListStart() {
+ DVLOG(2) << "HpackDecoder3::ListenerAdapter::OnHeaderListStart";
+ total_uncompressed_bytes_ = 0;
+ decoded_block_.clear();
+ if (handler_ != nullptr) {
+ handler_->OnHeaderBlockStart();
+ }
+}
+
+void HpackDecoder3::ListenerAdapter::OnHeader(HpackEntryType entry_type,
+ const HpackString& name,
+ const HpackString& value) {
+ DVLOG(2) << "HpackDecoder3::ListenerAdapter::OnHeader:\n name: " << name
+ << "\n value: " << value;
+ total_uncompressed_bytes_ += name.size() + value.size();
+ if (handler_ == nullptr) {
+ DVLOG(3) << "Adding to decoded_block";
+ decoded_block_.AppendValueOrAddHeader(name, value);
+ } else {
+ DVLOG(3) << "Passing to handler";
+ handler_->OnHeader(name, value);
+ }
+}
+
+void HpackDecoder3::ListenerAdapter::OnHeaderListEnd() {
+ DVLOG(2) << "HpackDecoder3::ListenerAdapter::OnHeaderListEnd";
+ // We don't clear the SpdyHeaderBlock here to allow access to it until the
+ // next HPACK block is decoded.
+ if (handler_ != nullptr) {
+ handler_->OnHeaderBlockEnd(total_uncompressed_bytes_);
+ handler_ = nullptr;
+ }
+}
+
+void HpackDecoder3::ListenerAdapter::OnHeaderErrorDetected(
+ StringPiece error_message) {
+ VLOG(1) << error_message;
+}
+
+} // namespace net
diff --git a/chromium/net/spdy/hpack/hpack_decoder3.h b/chromium/net/spdy/hpack/hpack_decoder3.h
new file mode 100644
index 00000000000..6203dfd322b
--- /dev/null
+++ b/chromium/net/spdy/hpack/hpack_decoder3.h
@@ -0,0 +1,112 @@
+// Copyright 2017 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.
+
+#ifndef NET_SPDY_HPACK_HPACK_DECODER3_H_
+#define NET_SPDY_HPACK_HPACK_DECODER3_H_
+
+// HpackDecoder3 implements HpackDecoderInterface, using Http2HpackDecoder to
+// decode HPACK blocks into HTTP/2 header lists as outlined in
+// http://tools.ietf.org/html/rfc7541.
+
+#include <stddef.h>
+
+#include <memory>
+
+#include "base/macros.h"
+#include "base/strings/string_piece.h"
+#include "net/base/net_export.h"
+#include "net/http2/hpack/decoder/hpack_decoder_listener.h"
+#include "net/http2/hpack/decoder/http2_hpack_decoder.h"
+#include "net/http2/hpack/hpack_string.h"
+#include "net/http2/hpack/http2_hpack_constants.h"
+#include "net/spdy/hpack/hpack_decoder_interface.h"
+#include "net/spdy/hpack/hpack_header_table.h"
+#include "net/spdy/spdy_header_block.h"
+#include "net/spdy/spdy_headers_handler_interface.h"
+
+namespace net {
+namespace test {
+class HpackDecoder3Peer;
+} // namespace test
+
+class NET_EXPORT_PRIVATE HpackDecoder3 : public HpackDecoderInterface {
+ public:
+ friend test::HpackDecoder3Peer;
+ HpackDecoder3();
+ ~HpackDecoder3() override;
+
+ // Override the HpackDecoderInterface methods:
+
+ void ApplyHeaderTableSizeSetting(size_t size_setting) override;
+ void HandleControlFrameHeadersStart(
+ SpdyHeadersHandlerInterface* handler) override;
+ bool HandleControlFrameHeadersData(const char* headers_data,
+ size_t headers_data_length) override;
+ bool HandleControlFrameHeadersComplete(size_t* compressed_len) override;
+ const SpdyHeaderBlock& decoded_block() const override;
+ void SetHeaderTableDebugVisitor(
+ std::unique_ptr<HpackHeaderTable::DebugVisitorInterface> visitor)
+ override;
+ void set_max_decode_buffer_size_bytes(
+ size_t max_decode_buffer_size_bytes) override;
+
+ private:
+ class NET_EXPORT_PRIVATE ListenerAdapter : public HpackDecoderListener {
+ public:
+ ListenerAdapter();
+ ~ListenerAdapter() override;
+
+ // If a SpdyHeadersHandlerInterface is provided, the decoder will emit
+ // headers to it rather than accumulating them in a SpdyHeaderBlock.
+ // Does not take ownership of the handler, but does use the pointer until
+ // the current HPACK block is completely decoded.
+ void set_handler(SpdyHeadersHandlerInterface* handler);
+ const SpdyHeaderBlock& decoded_block() const { return decoded_block_; }
+
+ // Override the HpackDecoderListener methods:
+
+ void OnHeaderListStart() override;
+ void OnHeader(HpackEntryType entry_type,
+ const HpackString& name,
+ const HpackString& value) override;
+ void OnHeaderListEnd() override;
+ void OnHeaderErrorDetected(base::StringPiece error_message) override;
+
+ private:
+ // If the caller doesn't provide a handler, the header list is stored in
+ // this SpdyHeaderBlock.
+ SpdyHeaderBlock decoded_block_;
+
+ // If non-NULL, handles decoded headers. Not owned.
+ SpdyHeadersHandlerInterface* handler_;
+
+ // Total bytes of the name and value strings in the current HPACK block.
+ size_t total_uncompressed_bytes_;
+ };
+
+ // Converts calls to HpackDecoderListener into calls to
+ // SpdyHeadersHandlerInterface.
+ ListenerAdapter listener_adapter_;
+
+ // The actual decoder.
+ Http2HpackDecoder hpack_decoder_;
+
+ // Total bytes that have been received as input (i.e. HPACK encoded)
+ // in the current HPACK block.
+ size_t total_hpack_bytes_;
+
+ // How much encoded data this decoder is willing to buffer.
+ size_t max_decode_buffer_size_bytes_;
+
+ // Flag to keep track of having seen the header block start. Needed at the
+ // moment because HandleControlFrameHeadersStart won't be called if a handler
+ // is not being provided by the caller.
+ bool header_block_started_;
+
+ DISALLOW_COPY_AND_ASSIGN(HpackDecoder3);
+};
+
+} // namespace net
+
+#endif // NET_SPDY_HPACK_HPACK_DECODER3_H_
diff --git a/chromium/net/spdy/hpack/hpack_decoder3_test.cc b/chromium/net/spdy/hpack/hpack_decoder3_test.cc
new file mode 100644
index 00000000000..3f71724a4ff
--- /dev/null
+++ b/chromium/net/spdy/hpack/hpack_decoder3_test.cc
@@ -0,0 +1,1012 @@
+// Copyright 2017 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.
+
+#include "net/spdy/hpack/hpack_decoder3.h"
+
+// Tests of HpackDecoder3.
+
+#include <stdint.h>
+
+#include <string>
+#include <tuple>
+#include <utility>
+#include <vector>
+
+#include "base/logging.h"
+#include "base/strings/string_number_conversions.h"
+#include "net/http2/hpack/decoder/hpack_decoder_state.h"
+#include "net/http2/hpack/decoder/hpack_decoder_tables.h"
+#include "net/http2/hpack/tools/hpack_block_builder.h"
+#include "net/http2/tools/http2_random.h"
+#include "net/spdy/hpack/hpack_constants.h"
+#include "net/spdy/hpack/hpack_encoder.h"
+#include "net/spdy/hpack/hpack_huffman_table.h"
+#include "net/spdy/hpack/hpack_output_stream.h"
+#include "net/spdy/spdy_test_utils.h"
+#include "testing/gmock/include/gmock/gmock.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+using base::StringPiece;
+using std::string;
+using ::testing::ElementsAre;
+using ::testing::Pair;
+
+namespace net {
+namespace test {
+
+class HpackDecoderStatePeer {
+ public:
+ static HpackDecoderTables* GetDecoderTables(HpackDecoderState* state) {
+ return &state->decoder_tables_;
+ }
+};
+
+class Http2HpackDecoderPeer {
+ public:
+ static HpackDecoderState* GetDecoderState(Http2HpackDecoder* decoder) {
+ return &decoder->decoder_state_;
+ }
+ static HpackDecoderTables* GetDecoderTables(Http2HpackDecoder* decoder) {
+ return HpackDecoderStatePeer::GetDecoderTables(GetDecoderState(decoder));
+ }
+};
+
+class HpackDecoder3Peer {
+ public:
+ explicit HpackDecoder3Peer(HpackDecoder3* decoder) : decoder_(decoder) {}
+
+ void HandleHeaderRepresentation(StringPiece name, StringPiece value) {
+ decoder_->listener_adapter_.OnHeader(HpackEntryType::kIndexedLiteralHeader,
+ HpackString(name), HpackString(value));
+ }
+
+ HpackDecoderTables* GetDecoderTables() {
+ return Http2HpackDecoderPeer::GetDecoderTables(&decoder_->hpack_decoder_);
+ }
+
+ const HpackStringPair* GetTableEntry(uint32_t index) {
+ return GetDecoderTables()->Lookup(index);
+ }
+
+ size_t current_header_table_size() {
+ return GetDecoderTables()->current_header_table_size();
+ }
+
+ size_t header_table_size_limit() {
+ return GetDecoderTables()->header_table_size_limit();
+ }
+
+ void set_header_table_size_limit(size_t size) {
+ return GetDecoderTables()->DynamicTableSizeUpdate(size);
+ }
+
+ private:
+ HpackDecoder3* decoder_;
+};
+
+namespace {
+
+// Is HandleControlFrameHeadersStart to be called, and with what value?
+enum StartChoice { START_WITH_HANDLER, START_WITHOUT_HANDLER, NO_START };
+
+class HpackDecoder3Test
+ : public ::testing::TestWithParam<std::tuple<StartChoice, bool>> {
+ protected:
+ HpackDecoder3Test() : decoder_(), decoder_peer_(&decoder_) {}
+
+ void SetUp() override {
+ std::tie(start_choice_, randomly_split_input_buffer_) = GetParam();
+ }
+
+ void HandleControlFrameHeadersStart() {
+ switch (start_choice_) {
+ case START_WITH_HANDLER:
+ decoder_.HandleControlFrameHeadersStart(&handler_);
+ break;
+ case START_WITHOUT_HANDLER:
+ decoder_.HandleControlFrameHeadersStart(nullptr);
+ break;
+ case NO_START:
+ break;
+ }
+ }
+
+ bool HandleControlFrameHeadersData(StringPiece str) {
+ VLOG(3) << "HandleControlFrameHeadersData:\n"
+ << base::HexEncode(str.data(), str.size());
+ return decoder_.HandleControlFrameHeadersData(str.data(), str.size());
+ }
+
+ bool HandleControlFrameHeadersComplete(size_t* size) {
+ return decoder_.HandleControlFrameHeadersComplete(size);
+ }
+
+ bool DecodeHeaderBlock(StringPiece str) {
+ // Don't call this again if HandleControlFrameHeadersData failed previously.
+ EXPECT_FALSE(decode_has_failed_);
+ HandleControlFrameHeadersStart();
+ if (randomly_split_input_buffer_) {
+ do {
+ // Decode some fragment of the remaining bytes.
+ size_t bytes = str.length();
+ if (!str.empty()) {
+ bytes = (random_.Rand8() % str.length()) + 1;
+ }
+ EXPECT_LE(bytes, str.length());
+ if (!HandleControlFrameHeadersData(str.substr(0, bytes))) {
+ decode_has_failed_ = true;
+ return false;
+ }
+ str.remove_prefix(bytes);
+ } while (!str.empty());
+ } else if (!HandleControlFrameHeadersData(str)) {
+ decode_has_failed_ = true;
+ return false;
+ }
+ if (!HandleControlFrameHeadersComplete(nullptr)) {
+ decode_has_failed_ = true;
+ return false;
+ }
+ return true;
+ }
+
+ bool EncodeAndDecodeDynamicTableSizeUpdates(size_t first, size_t second) {
+ HpackBlockBuilder hbb;
+ hbb.AppendDynamicTableSizeUpdate(first);
+ if (second != first) {
+ hbb.AppendDynamicTableSizeUpdate(second);
+ }
+ return DecodeHeaderBlock(hbb.buffer());
+ }
+
+ const SpdyHeaderBlock& decoded_block() const {
+ if (start_choice_ == START_WITH_HANDLER) {
+ return handler_.decoded_block();
+ } else {
+ return decoder_.decoded_block();
+ }
+ }
+
+ const SpdyHeaderBlock& DecodeBlockExpectingSuccess(StringPiece str) {
+ EXPECT_TRUE(DecodeHeaderBlock(str));
+ return decoded_block();
+ }
+
+ void expectEntry(size_t index,
+ size_t size,
+ const string& name,
+ const string& value) {
+ const HpackStringPair* entry = decoder_peer_.GetTableEntry(index);
+ EXPECT_EQ(name, entry->name) << "index " << index;
+ EXPECT_EQ(value, entry->value);
+ EXPECT_EQ(size, entry->size());
+ }
+
+ SpdyHeaderBlock MakeHeaderBlock(
+ const std::vector<std::pair<string, string>>& headers) {
+ SpdyHeaderBlock result;
+ for (const auto& kv : headers) {
+ result.AppendValueOrAddHeader(kv.first, kv.second);
+ }
+ return result;
+ }
+
+ Http2Random random_;
+ HpackHuffmanTable huffman_table_;
+ HpackDecoder3 decoder_;
+ test::HpackDecoder3Peer decoder_peer_;
+ TestHeadersHandler handler_;
+ StartChoice start_choice_;
+ bool randomly_split_input_buffer_;
+ bool decode_has_failed_ = false;
+};
+
+INSTANTIATE_TEST_CASE_P(
+ StartChoiceAndRandomlySplitChoice,
+ HpackDecoder3Test,
+ ::testing::Combine(
+ ::testing::Values(START_WITH_HANDLER, START_WITHOUT_HANDLER, NO_START),
+ ::testing::Bool()));
+
+TEST_P(HpackDecoder3Test, AddHeaderDataWithHandleControlFrameHeadersData) {
+ // The hpack decode buffer size is limited in size. This test verifies that
+ // adding encoded data under that limit is accepted, and data that exceeds the
+ // limit is rejected.
+ HandleControlFrameHeadersStart();
+ const size_t kMaxBufferSizeBytes = 50;
+ const string a_value = string(49, 'x');
+ decoder_.set_max_decode_buffer_size_bytes(kMaxBufferSizeBytes);
+ HpackBlockBuilder hbb;
+ hbb.AppendLiteralNameAndValue(HpackEntryType::kNeverIndexedLiteralHeader,
+ false, "a", false, a_value);
+ const string& s = hbb.buffer();
+ EXPECT_GT(s.size(), kMaxBufferSizeBytes);
+
+ // Any one in input buffer must not exceed kMaxBufferSizeBytes.
+ EXPECT_TRUE(HandleControlFrameHeadersData(s.substr(0, s.size() / 2)));
+ EXPECT_TRUE(HandleControlFrameHeadersData(s.substr(s.size() / 2)));
+
+ EXPECT_FALSE(HandleControlFrameHeadersData(s));
+ SpdyHeaderBlock expected_block = MakeHeaderBlock({{"a", a_value}});
+ EXPECT_EQ(expected_block, decoded_block());
+}
+
+TEST_P(HpackDecoder3Test, NameTooLong) {
+ // Verify that a name longer than the allowed size generates an error.
+ const size_t kMaxBufferSizeBytes = 50;
+ const string name = string(2 * kMaxBufferSizeBytes, 'x');
+ const string value = "abc";
+
+ decoder_.set_max_decode_buffer_size_bytes(kMaxBufferSizeBytes);
+
+ HpackBlockBuilder hbb;
+ hbb.AppendLiteralNameAndValue(HpackEntryType::kNeverIndexedLiteralHeader,
+ false, name, false, value);
+
+ const size_t fragment_size = (3 * kMaxBufferSizeBytes) / 2;
+ const string fragment = hbb.buffer().substr(0, fragment_size);
+
+ HandleControlFrameHeadersStart();
+ EXPECT_FALSE(HandleControlFrameHeadersData(fragment));
+}
+
+TEST_P(HpackDecoder3Test, HeaderTooLongToBuffer) {
+ // Verify that a header longer than the allowed size generates an error if
+ // it isn't all in one input buffer.
+ const string name = "some-key";
+ const string value = "some-value";
+ const size_t kMaxBufferSizeBytes = name.size() + value.size() - 2;
+ decoder_.set_max_decode_buffer_size_bytes(kMaxBufferSizeBytes);
+
+ HpackBlockBuilder hbb;
+ hbb.AppendLiteralNameAndValue(HpackEntryType::kNeverIndexedLiteralHeader,
+ false, name, false, value);
+ const size_t fragment_size = hbb.size() - 1;
+ const string fragment = hbb.buffer().substr(0, fragment_size);
+
+ HandleControlFrameHeadersStart();
+ EXPECT_FALSE(HandleControlFrameHeadersData(fragment));
+}
+
+// Decode with incomplete data in buffer.
+TEST_P(HpackDecoder3Test, DecodeWithIncompleteData) {
+ HandleControlFrameHeadersStart();
+
+ // No need to wait for more data.
+ EXPECT_TRUE(HandleControlFrameHeadersData("\x82\x85\x82"));
+ std::vector<std::pair<string, string>> expected_headers = {
+ {":method", "GET"}, {":path", "/index.html"}, {":method", "GET"}};
+
+ SpdyHeaderBlock expected_block1 = MakeHeaderBlock(expected_headers);
+ EXPECT_EQ(expected_block1, decoded_block());
+
+ // Full and partial headers, won't add partial to the headers.
+ EXPECT_TRUE(
+ HandleControlFrameHeadersData("\x40\x03goo"
+ "\x03gar\xbe\x40\x04spam"));
+ expected_headers.push_back({"goo", "gar"});
+ expected_headers.push_back({"goo", "gar"});
+
+ SpdyHeaderBlock expected_block2 = MakeHeaderBlock(expected_headers);
+ EXPECT_EQ(expected_block2, decoded_block());
+
+ // Add the needed data.
+ EXPECT_TRUE(HandleControlFrameHeadersData("\x04gggs"));
+
+ size_t size = 0;
+ EXPECT_TRUE(HandleControlFrameHeadersComplete(&size));
+ EXPECT_EQ(24u, size);
+
+ expected_headers.push_back({"spam", "gggs"});
+
+ SpdyHeaderBlock expected_block3 = MakeHeaderBlock(expected_headers);
+ EXPECT_EQ(expected_block3, decoded_block());
+}
+
+TEST_P(HpackDecoder3Test, HandleHeaderRepresentation) {
+ // Make sure the decoder is properly initialized.
+ HandleControlFrameHeadersStart();
+ HandleControlFrameHeadersData("");
+
+ // All cookie crumbs are joined.
+ decoder_peer_.HandleHeaderRepresentation("cookie", " part 1");
+ decoder_peer_.HandleHeaderRepresentation("cookie", "part 2 ");
+ decoder_peer_.HandleHeaderRepresentation("cookie", "part3");
+
+ // Already-delimited headers are passed through.
+ decoder_peer_.HandleHeaderRepresentation("passed-through",
+ string("foo\0baz", 7));
+
+ // Other headers are joined on \0. Case matters.
+ decoder_peer_.HandleHeaderRepresentation("joined", "not joined");
+ decoder_peer_.HandleHeaderRepresentation("joineD", "value 1");
+ decoder_peer_.HandleHeaderRepresentation("joineD", "value 2");
+
+ // Empty headers remain empty.
+ decoder_peer_.HandleHeaderRepresentation("empty", "");
+
+ // Joined empty headers work as expected.
+ decoder_peer_.HandleHeaderRepresentation("empty-joined", "");
+ decoder_peer_.HandleHeaderRepresentation("empty-joined", "foo");
+ decoder_peer_.HandleHeaderRepresentation("empty-joined", "");
+ decoder_peer_.HandleHeaderRepresentation("empty-joined", "");
+
+ // Non-contiguous cookie crumb.
+ decoder_peer_.HandleHeaderRepresentation("cookie", " fin!");
+
+ // Finish and emit all headers.
+ decoder_.HandleControlFrameHeadersComplete(nullptr);
+
+ // Resulting decoded headers are in the same order as the inputs.
+ EXPECT_THAT(decoded_block(),
+ ElementsAre(Pair("cookie", " part 1; part 2 ; part3; fin!"),
+ Pair("passed-through", StringPiece("foo\0baz", 7)),
+ Pair("joined", "not joined"),
+ Pair("joineD", StringPiece("value 1\0value 2", 15)),
+ Pair("empty", ""),
+ Pair("empty-joined", StringPiece("\0foo\0\0", 6))));
+}
+
+// Decoding indexed static table field should work.
+TEST_P(HpackDecoder3Test, IndexedHeaderStatic) {
+ // Reference static table entries #2 and #5.
+ const SpdyHeaderBlock& header_set1 = DecodeBlockExpectingSuccess("\x82\x85");
+ SpdyHeaderBlock expected_header_set1;
+ expected_header_set1[":method"] = "GET";
+ expected_header_set1[":path"] = "/index.html";
+ EXPECT_EQ(expected_header_set1, header_set1);
+
+ // Reference static table entry #2.
+ const SpdyHeaderBlock& header_set2 = DecodeBlockExpectingSuccess("\x82");
+ SpdyHeaderBlock expected_header_set2;
+ expected_header_set2[":method"] = "GET";
+ EXPECT_EQ(expected_header_set2, header_set2);
+}
+
+TEST_P(HpackDecoder3Test, IndexedHeaderDynamic) {
+ // First header block: add an entry to header table.
+ const SpdyHeaderBlock& header_set1 = DecodeBlockExpectingSuccess(
+ "\x40\x03"
+ "foo"
+ "\x03"
+ "bar");
+ SpdyHeaderBlock expected_header_set1;
+ expected_header_set1["foo"] = "bar";
+ EXPECT_EQ(expected_header_set1, header_set1);
+
+ // Second header block: add another entry to header table.
+ const SpdyHeaderBlock& header_set2 = DecodeBlockExpectingSuccess(
+ "\xbe\x40\x04"
+ "spam"
+ "\x04"
+ "eggs");
+ SpdyHeaderBlock expected_header_set2;
+ expected_header_set2["foo"] = "bar";
+ expected_header_set2["spam"] = "eggs";
+ EXPECT_EQ(expected_header_set2, header_set2);
+
+ // Third header block: refer to most recently added entry.
+ const SpdyHeaderBlock& header_set3 = DecodeBlockExpectingSuccess("\xbe");
+ SpdyHeaderBlock expected_header_set3;
+ expected_header_set3["spam"] = "eggs";
+ EXPECT_EQ(expected_header_set3, header_set3);
+}
+
+// Test a too-large indexed header.
+TEST_P(HpackDecoder3Test, InvalidIndexedHeader) {
+ // High-bit set, and a prefix of one more than the number of static entries.
+ EXPECT_FALSE(DecodeHeaderBlock("\xbe"));
+}
+
+TEST_P(HpackDecoder3Test, ContextUpdateMaximumSize) {
+ EXPECT_EQ(kDefaultHeaderTableSizeSetting,
+ decoder_peer_.header_table_size_limit());
+ string input;
+ {
+ // Maximum-size update with size 126. Succeeds.
+ HpackOutputStream output_stream;
+ output_stream.AppendPrefix(kHeaderTableSizeUpdateOpcode);
+ output_stream.AppendUint32(126);
+
+ output_stream.TakeString(&input);
+ EXPECT_TRUE(DecodeHeaderBlock(StringPiece(input)));
+ EXPECT_EQ(126u, decoder_peer_.header_table_size_limit());
+ }
+ {
+ // Maximum-size update with kDefaultHeaderTableSizeSetting. Succeeds.
+ HpackOutputStream output_stream;
+ output_stream.AppendPrefix(kHeaderTableSizeUpdateOpcode);
+ output_stream.AppendUint32(kDefaultHeaderTableSizeSetting);
+
+ output_stream.TakeString(&input);
+ EXPECT_TRUE(DecodeHeaderBlock(StringPiece(input)));
+ EXPECT_EQ(kDefaultHeaderTableSizeSetting,
+ decoder_peer_.header_table_size_limit());
+ }
+ {
+ // Maximum-size update with kDefaultHeaderTableSizeSetting + 1. Fails.
+ HpackOutputStream output_stream;
+ output_stream.AppendPrefix(kHeaderTableSizeUpdateOpcode);
+ output_stream.AppendUint32(kDefaultHeaderTableSizeSetting + 1);
+
+ output_stream.TakeString(&input);
+ EXPECT_FALSE(DecodeHeaderBlock(StringPiece(input)));
+ EXPECT_EQ(kDefaultHeaderTableSizeSetting,
+ decoder_peer_.header_table_size_limit());
+ }
+}
+
+// Two HeaderTableSizeUpdates may appear at the beginning of the block
+TEST_P(HpackDecoder3Test, TwoTableSizeUpdates) {
+ string input;
+ {
+ // Should accept two table size updates, update to second one
+ HpackOutputStream output_stream;
+ output_stream.AppendPrefix(kHeaderTableSizeUpdateOpcode);
+ output_stream.AppendUint32(0);
+ output_stream.AppendPrefix(kHeaderTableSizeUpdateOpcode);
+ output_stream.AppendUint32(122);
+
+ output_stream.TakeString(&input);
+ EXPECT_TRUE(DecodeHeaderBlock(StringPiece(input)));
+ EXPECT_EQ(122u, decoder_peer_.header_table_size_limit());
+ }
+}
+
+// Three HeaderTableSizeUpdates should result in an error
+TEST_P(HpackDecoder3Test, ThreeTableSizeUpdatesError) {
+ string input;
+ {
+ // Should reject three table size updates, update to second one
+ HpackOutputStream output_stream;
+ output_stream.AppendPrefix(kHeaderTableSizeUpdateOpcode);
+ output_stream.AppendUint32(5);
+ output_stream.AppendPrefix(kHeaderTableSizeUpdateOpcode);
+ output_stream.AppendUint32(10);
+ output_stream.AppendPrefix(kHeaderTableSizeUpdateOpcode);
+ output_stream.AppendUint32(15);
+
+ output_stream.TakeString(&input);
+
+ EXPECT_FALSE(DecodeHeaderBlock(StringPiece(input)));
+ EXPECT_EQ(10u, decoder_peer_.header_table_size_limit());
+ }
+}
+
+// HeaderTableSizeUpdates may only appear at the beginning of the block
+// Any other updates should result in an error
+TEST_P(HpackDecoder3Test, TableSizeUpdateSecondError) {
+ string input;
+ {
+ // Should reject a table size update appearing after a different entry
+ // The table size should remain as the default
+ HpackOutputStream output_stream;
+ output_stream.AppendBytes("\x82\x85");
+ output_stream.AppendPrefix(kHeaderTableSizeUpdateOpcode);
+ output_stream.AppendUint32(123);
+
+ output_stream.TakeString(&input);
+
+ EXPECT_FALSE(DecodeHeaderBlock(StringPiece(input)));
+ EXPECT_EQ(kDefaultHeaderTableSizeSetting,
+ decoder_peer_.header_table_size_limit());
+ }
+}
+
+// HeaderTableSizeUpdates may only appear at the beginning of the block
+// Any other updates should result in an error
+TEST_P(HpackDecoder3Test, TableSizeUpdateFirstThirdError) {
+ string input;
+ {
+ // Should reject the second table size update
+ // if a different entry appears after the first update
+ // The table size should update to the first but not the second
+ HpackOutputStream output_stream;
+ output_stream.AppendPrefix(kHeaderTableSizeUpdateOpcode);
+ output_stream.AppendUint32(60);
+ output_stream.AppendBytes("\x82\x85");
+ output_stream.AppendPrefix(kHeaderTableSizeUpdateOpcode);
+ output_stream.AppendUint32(125);
+
+ output_stream.TakeString(&input);
+
+ EXPECT_FALSE(DecodeHeaderBlock(StringPiece(input)));
+ EXPECT_EQ(60u, decoder_peer_.header_table_size_limit());
+ }
+}
+
+// Decoding two valid encoded literal headers with no indexing should
+// work.
+TEST_P(HpackDecoder3Test, LiteralHeaderNoIndexing) {
+ // First header with indexed name, second header with string literal
+ // name.
+ const char input[] = "\x04\x0c/sample/path\x00\x06:path2\x0e/sample/path/2";
+ const SpdyHeaderBlock& header_set =
+ DecodeBlockExpectingSuccess(StringPiece(input, arraysize(input) - 1));
+
+ SpdyHeaderBlock expected_header_set;
+ expected_header_set[":path"] = "/sample/path";
+ expected_header_set[":path2"] = "/sample/path/2";
+ EXPECT_EQ(expected_header_set, header_set);
+}
+
+// Decoding two valid encoded literal headers with incremental
+// indexing and string literal names should work.
+TEST_P(HpackDecoder3Test, LiteralHeaderIncrementalIndexing) {
+ const char input[] = "\x44\x0c/sample/path\x40\x06:path2\x0e/sample/path/2";
+ const SpdyHeaderBlock& header_set =
+ DecodeBlockExpectingSuccess(StringPiece(input, arraysize(input) - 1));
+
+ SpdyHeaderBlock expected_header_set;
+ expected_header_set[":path"] = "/sample/path";
+ expected_header_set[":path2"] = "/sample/path/2";
+ EXPECT_EQ(expected_header_set, header_set);
+}
+
+TEST_P(HpackDecoder3Test, LiteralHeaderWithIndexingInvalidNameIndex) {
+ decoder_.ApplyHeaderTableSizeSetting(0);
+ EXPECT_TRUE(EncodeAndDecodeDynamicTableSizeUpdates(0, 0));
+
+ // Name is the last static index. Works.
+ EXPECT_TRUE(DecodeHeaderBlock(StringPiece("\x7d\x03ooo")));
+ // Name is one beyond the last static index. Fails.
+ EXPECT_FALSE(DecodeHeaderBlock(StringPiece("\x7e\x03ooo")));
+}
+
+TEST_P(HpackDecoder3Test, LiteralHeaderNoIndexingInvalidNameIndex) {
+ // Name is the last static index. Works.
+ EXPECT_TRUE(DecodeHeaderBlock(StringPiece("\x0f\x2e\x03ooo")));
+ // Name is one beyond the last static index. Fails.
+ EXPECT_FALSE(DecodeHeaderBlock(StringPiece("\x0f\x2f\x03ooo")));
+}
+
+TEST_P(HpackDecoder3Test, LiteralHeaderNeverIndexedInvalidNameIndex) {
+ // Name is the last static index. Works.
+ EXPECT_TRUE(DecodeHeaderBlock(StringPiece("\x1f\x2e\x03ooo")));
+ // Name is one beyond the last static index. Fails.
+ EXPECT_FALSE(DecodeHeaderBlock(StringPiece("\x1f\x2f\x03ooo")));
+}
+
+TEST_P(HpackDecoder3Test, TruncatedIndex) {
+ // Indexed Header, varint for index requires multiple bytes,
+ // but only one provided.
+ EXPECT_FALSE(DecodeHeaderBlock(StringPiece("\xff", 1)));
+}
+
+TEST_P(HpackDecoder3Test, TruncatedHuffmanLiteral) {
+ // Literal value, Huffman encoded, but with the last byte missing (i.e.
+ // drop the final ff shown below).
+ //
+ // 41 | == Literal indexed ==
+ // | Indexed name (idx = 1)
+ // | :authority
+ // 8c | Literal value (len = 12)
+ // | Huffman encoded:
+ // f1e3 c2e5 f23a 6ba0 ab90 f4ff | .....:k.....
+ // | Decoded:
+ // | www.example.com
+ // | -> :authority: www.example.com
+
+ string first = a2b_hex("418cf1e3c2e5f23a6ba0ab90f4ff");
+ EXPECT_TRUE(DecodeHeaderBlock(first));
+ first = a2b_hex("418cf1e3c2e5f23a6ba0ab90f4");
+ EXPECT_FALSE(DecodeHeaderBlock(first));
+}
+
+TEST_P(HpackDecoder3Test, HuffmanEOSError) {
+ // Literal value, Huffman encoded, but with an additional ff byte at the end
+ // of the string, i.e. an EOS that is longer than permitted.
+ //
+ // 41 | == Literal indexed ==
+ // | Indexed name (idx = 1)
+ // | :authority
+ // 8d | Literal value (len = 13)
+ // | Huffman encoded:
+ // f1e3 c2e5 f23a 6ba0 ab90 f4ff | .....:k.....
+ // | Decoded:
+ // | www.example.com
+ // | -> :authority: www.example.com
+
+ string first = a2b_hex("418cf1e3c2e5f23a6ba0ab90f4ff");
+ EXPECT_TRUE(DecodeHeaderBlock(first));
+ first = a2b_hex("418df1e3c2e5f23a6ba0ab90f4ffff");
+ EXPECT_FALSE(DecodeHeaderBlock(first));
+}
+
+// Round-tripping the header set from RFC 7541 C.3.1 should work.
+// http://httpwg.org/specs/rfc7541.html#rfc.section.C.3.1
+TEST_P(HpackDecoder3Test, BasicC31) {
+ HpackEncoder encoder(ObtainHpackHuffmanTable());
+
+ SpdyHeaderBlock expected_header_set;
+ expected_header_set[":method"] = "GET";
+ expected_header_set[":scheme"] = "http";
+ expected_header_set[":path"] = "/";
+ expected_header_set[":authority"] = "www.example.com";
+
+ string encoded_header_set;
+ EXPECT_TRUE(
+ encoder.EncodeHeaderSet(expected_header_set, &encoded_header_set));
+
+ EXPECT_TRUE(DecodeHeaderBlock(encoded_header_set));
+ EXPECT_EQ(expected_header_set, decoded_block());
+}
+
+// RFC 7541, Section C.4: Request Examples with Huffman Coding
+// http://httpwg.org/specs/rfc7541.html#rfc.section.C.4
+TEST_P(HpackDecoder3Test, SectionC4RequestHuffmanExamples) {
+ // TODO(jamessynge): Use net/http2/hpack/tools/hpack_example.h to parse the
+ // example directly, instead of having it as a comment.
+ // 82 | == Indexed - Add ==
+ // | idx = 2
+ // | -> :method: GET
+ // 86 | == Indexed - Add ==
+ // | idx = 6
+ // | -> :scheme: http
+ // 84 | == Indexed - Add ==
+ // | idx = 4
+ // | -> :path: /
+ // 41 | == Literal indexed ==
+ // | Indexed name (idx = 1)
+ // | :authority
+ // 8c | Literal value (len = 12)
+ // | Huffman encoded:
+ // f1e3 c2e5 f23a 6ba0 ab90 f4ff | .....:k.....
+ // | Decoded:
+ // | www.example.com
+ // | -> :authority: www.example.com
+ string first = a2b_hex("828684418cf1e3c2e5f23a6ba0ab90f4ff");
+ const SpdyHeaderBlock& first_header_set = DecodeBlockExpectingSuccess(first);
+
+ EXPECT_THAT(first_header_set,
+ ElementsAre(
+ // clang-format off
+ Pair(":method", "GET"),
+ Pair(":scheme", "http"),
+ Pair(":path", "/"),
+ Pair(":authority", "www.example.com")));
+ // clang-format on
+
+ expectEntry(62, 57, ":authority", "www.example.com");
+ EXPECT_EQ(57u, decoder_peer_.current_header_table_size());
+
+ // 82 | == Indexed - Add ==
+ // | idx = 2
+ // | -> :method: GET
+ // 86 | == Indexed - Add ==
+ // | idx = 6
+ // | -> :scheme: http
+ // 84 | == Indexed - Add ==
+ // | idx = 4
+ // | -> :path: /
+ // be | == Indexed - Add ==
+ // | idx = 62
+ // | -> :authority: www.example.com
+ // 58 | == Literal indexed ==
+ // | Indexed name (idx = 24)
+ // | cache-control
+ // 86 | Literal value (len = 8)
+ // | Huffman encoded:
+ // a8eb 1064 9cbf | ...d..
+ // | Decoded:
+ // | no-cache
+ // | -> cache-control: no-cache
+
+ string second = a2b_hex("828684be5886a8eb10649cbf");
+ const SpdyHeaderBlock& second_header_set =
+ DecodeBlockExpectingSuccess(second);
+
+ EXPECT_THAT(second_header_set,
+ ElementsAre(
+ // clang-format off
+ Pair(":method", "GET"),
+ Pair(":scheme", "http"),
+ Pair(":path", "/"),
+ Pair(":authority", "www.example.com"),
+ Pair("cache-control", "no-cache")));
+ // clang-format on
+
+ expectEntry(62, 53, "cache-control", "no-cache");
+ expectEntry(63, 57, ":authority", "www.example.com");
+ EXPECT_EQ(110u, decoder_peer_.current_header_table_size());
+
+ // 82 | == Indexed - Add ==
+ // | idx = 2
+ // | -> :method: GET
+ // 87 | == Indexed - Add ==
+ // | idx = 7
+ // | -> :scheme: https
+ // 85 | == Indexed - Add ==
+ // | idx = 5
+ // | -> :path: /index.html
+ // bf | == Indexed - Add ==
+ // | idx = 63
+ // | -> :authority: www.example.com
+ // 40 | == Literal indexed ==
+ // 88 | Literal name (len = 10)
+ // | Huffman encoded:
+ // 25a8 49e9 5ba9 7d7f | %.I.[.}.
+ // | Decoded:
+ // | custom-key
+ // 89 | Literal value (len = 12)
+ // | Huffman encoded:
+ // 25a8 49e9 5bb8 e8b4 bf | %.I.[....
+ // | Decoded:
+ // | custom-value
+ // | -> custom-key: custom-value
+ string third = a2b_hex("828785bf408825a849e95ba97d7f8925a849e95bb8e8b4bf");
+ const SpdyHeaderBlock& third_header_set = DecodeBlockExpectingSuccess(third);
+
+ EXPECT_THAT(
+ third_header_set,
+ ElementsAre(
+ // clang-format off
+ Pair(":method", "GET"),
+ Pair(":scheme", "https"),
+ Pair(":path", "/index.html"),
+ Pair(":authority", "www.example.com"),
+ Pair("custom-key", "custom-value")));
+ // clang-format on
+
+ expectEntry(62, 54, "custom-key", "custom-value");
+ expectEntry(63, 53, "cache-control", "no-cache");
+ expectEntry(64, 57, ":authority", "www.example.com");
+ EXPECT_EQ(164u, decoder_peer_.current_header_table_size());
+}
+
+// RFC 7541, Section C.6: Response Examples with Huffman Coding
+// http://httpwg.org/specs/rfc7541.html#rfc.section.C.6
+TEST_P(HpackDecoder3Test, SectionC6ResponseHuffmanExamples) {
+ // The example is based on a maximum dynamic table size of 256,
+ // which allows for testing dynamic table evictions.
+ decoder_peer_.set_header_table_size_limit(256);
+
+ // 48 | == Literal indexed ==
+ // | Indexed name (idx = 8)
+ // | :status
+ // 82 | Literal value (len = 3)
+ // | Huffman encoded:
+ // 6402 | d.
+ // | Decoded:
+ // | 302
+ // | -> :status: 302
+ // 58 | == Literal indexed ==
+ // | Indexed name (idx = 24)
+ // | cache-control
+ // 85 | Literal value (len = 7)
+ // | Huffman encoded:
+ // aec3 771a 4b | ..w.K
+ // | Decoded:
+ // | private
+ // | -> cache-control: private
+ // 61 | == Literal indexed ==
+ // | Indexed name (idx = 33)
+ // | date
+ // 96 | Literal value (len = 29)
+ // | Huffman encoded:
+ // d07a be94 1054 d444 a820 0595 040b 8166 | .z...T.D. .....f
+ // e082 a62d 1bff | ...-..
+ // | Decoded:
+ // | Mon, 21 Oct 2013 20:13:21
+ // | GMT
+ // | -> date: Mon, 21 Oct 2013
+ // | 20:13:21 GMT
+ // 6e | == Literal indexed ==
+ // | Indexed name (idx = 46)
+ // | location
+ // 91 | Literal value (len = 23)
+ // | Huffman encoded:
+ // 9d29 ad17 1863 c78f 0b97 c8e9 ae82 ae43 | .)...c.........C
+ // d3 | .
+ // | Decoded:
+ // | https://www.example.com
+ // | -> location: https://www.e
+ // | xample.com
+
+ string first = a2b_hex(
+ "488264025885aec3771a4b6196d07abe"
+ "941054d444a8200595040b8166e082a6"
+ "2d1bff6e919d29ad171863c78f0b97c8"
+ "e9ae82ae43d3");
+ const SpdyHeaderBlock& first_header_set = DecodeBlockExpectingSuccess(first);
+
+ EXPECT_THAT(first_header_set,
+ ElementsAre(
+ // clang-format off
+ Pair(":status", "302"),
+ Pair("cache-control", "private"),
+ Pair("date", "Mon, 21 Oct 2013 20:13:21 GMT"),
+ Pair("location", "https://www.example.com")));
+ // clang-format on
+
+ expectEntry(62, 63, "location", "https://www.example.com");
+ expectEntry(63, 65, "date", "Mon, 21 Oct 2013 20:13:21 GMT");
+ expectEntry(64, 52, "cache-control", "private");
+ expectEntry(65, 42, ":status", "302");
+ EXPECT_EQ(222u, decoder_peer_.current_header_table_size());
+
+ // 48 | == Literal indexed ==
+ // | Indexed name (idx = 8)
+ // | :status
+ // 83 | Literal value (len = 3)
+ // | Huffman encoded:
+ // 640e ff | d..
+ // | Decoded:
+ // | 307
+ // | - evict: :status: 302
+ // | -> :status: 307
+ // c1 | == Indexed - Add ==
+ // | idx = 65
+ // | -> cache-control: private
+ // c0 | == Indexed - Add ==
+ // | idx = 64
+ // | -> date: Mon, 21 Oct 2013
+ // | 20:13:21 GMT
+ // bf | == Indexed - Add ==
+ // | idx = 63
+ // | -> location:
+ // | https://www.example.com
+ string second = a2b_hex("4883640effc1c0bf");
+ const SpdyHeaderBlock& second_header_set =
+ DecodeBlockExpectingSuccess(second);
+
+ EXPECT_THAT(second_header_set,
+ ElementsAre(
+ // clang-format off
+ Pair(":status", "307"),
+ Pair("cache-control", "private"),
+ Pair("date", "Mon, 21 Oct 2013 20:13:21 GMT"),
+ Pair("location", "https://www.example.com")));
+ // clang-format on
+
+ expectEntry(62, 42, ":status", "307");
+ expectEntry(63, 63, "location", "https://www.example.com");
+ expectEntry(64, 65, "date", "Mon, 21 Oct 2013 20:13:21 GMT");
+ expectEntry(65, 52, "cache-control", "private");
+ EXPECT_EQ(222u, decoder_peer_.current_header_table_size());
+
+ // 88 | == Indexed - Add ==
+ // | idx = 8
+ // | -> :status: 200
+ // c1 | == Indexed - Add ==
+ // | idx = 65
+ // | -> cache-control: private
+ // 61 | == Literal indexed ==
+ // | Indexed name (idx = 33)
+ // | date
+ // 96 | Literal value (len = 22)
+ // | Huffman encoded:
+ // d07a be94 1054 d444 a820 0595 040b 8166 | .z...T.D. .....f
+ // e084 a62d 1bff | ...-..
+ // | Decoded:
+ // | Mon, 21 Oct 2013 20:13:22
+ // | GMT
+ // | - evict: cache-control:
+ // | private
+ // | -> date: Mon, 21 Oct 2013
+ // | 20:13:22 GMT
+ // c0 | == Indexed - Add ==
+ // | idx = 64
+ // | -> location:
+ // | https://www.example.com
+ // 5a | == Literal indexed ==
+ // | Indexed name (idx = 26)
+ // | content-encoding
+ // 83 | Literal value (len = 3)
+ // | Huffman encoded:
+ // 9bd9 ab | ...
+ // | Decoded:
+ // | gzip
+ // | - evict: date: Mon, 21 Oct
+ // | 2013 20:13:21 GMT
+ // | -> content-encoding: gzip
+ // 77 | == Literal indexed ==
+ // | Indexed name (idx = 55)
+ // | set-cookie
+ // ad | Literal value (len = 45)
+ // | Huffman encoded:
+ // 94e7 821d d7f2 e6c7 b335 dfdf cd5b 3960 | .........5...[9`
+ // d5af 2708 7f36 72c1 ab27 0fb5 291f 9587 | ..'..6r..'..)...
+ // 3160 65c0 03ed 4ee5 b106 3d50 07 | 1`e...N...=P.
+ // | Decoded:
+ // | foo=ASDJKHQKBZXOQWEOPIUAXQ
+ // | WEOIU; max-age=3600; versi
+ // | on=1
+ // | - evict: location:
+ // | https://www.example.com
+ // | - evict: :status: 307
+ // | -> set-cookie: foo=ASDJKHQ
+ // | KBZXOQWEOPIUAXQWEOIU;
+ // | max-age=3600; version=1
+ string third = a2b_hex(
+ "88c16196d07abe941054d444a8200595"
+ "040b8166e084a62d1bffc05a839bd9ab"
+ "77ad94e7821dd7f2e6c7b335dfdfcd5b"
+ "3960d5af27087f3672c1ab270fb5291f"
+ "9587316065c003ed4ee5b1063d5007");
+ const SpdyHeaderBlock& third_header_set = DecodeBlockExpectingSuccess(third);
+
+ EXPECT_THAT(third_header_set,
+ ElementsAre(
+ // clang-format off
+ Pair(":status", "200"),
+ Pair("cache-control", "private"),
+ Pair("date", "Mon, 21 Oct 2013 20:13:22 GMT"),
+ Pair("location", "https://www.example.com"),
+ Pair("content-encoding", "gzip"),
+ Pair("set-cookie", "foo=ASDJKHQKBZXOQWEOPIUAXQWEOIU;"
+ " max-age=3600; version=1")));
+ // clang-format on
+
+ expectEntry(62, 98, "set-cookie",
+ "foo=ASDJKHQKBZXOQWEOPIUAXQWEOIU;"
+ " max-age=3600; version=1");
+ expectEntry(63, 52, "content-encoding", "gzip");
+ expectEntry(64, 65, "date", "Mon, 21 Oct 2013 20:13:22 GMT");
+ EXPECT_EQ(215u, decoder_peer_.current_header_table_size());
+}
+
+// Regression test: Found that entries with dynamic indexed names and literal
+// values caused "use after free" MSAN failures if the name was evicted as it
+// was being re-used.
+TEST_P(HpackDecoder3Test, ReuseNameOfEvictedEntry) {
+ // Each entry is measured as 32 bytes plus the sum of the lengths of the name
+ // and the value. Set the size big enough for at most one entry, and a fairly
+ // small one at that (31 ASCII characters).
+ decoder_.ApplyHeaderTableSizeSetting(63);
+
+ HpackBlockBuilder hbb;
+ hbb.AppendDynamicTableSizeUpdate(0);
+ hbb.AppendDynamicTableSizeUpdate(63);
+
+ const StringPiece name("some-name");
+ const StringPiece value1("some-value");
+ const StringPiece value2("another-value");
+ const StringPiece value3("yet-another-value");
+
+ // Add an entry that will become the first in the dynamic table, entry 62.
+ hbb.AppendLiteralNameAndValue(HpackEntryType::kIndexedLiteralHeader, false,
+ name, false, value1);
+
+ // Confirm that entry has been added by re-using it.
+ hbb.AppendIndexedHeader(62);
+
+ // Add another entry referring to the name of the first. This will evict the
+ // first.
+ hbb.AppendNameIndexAndLiteralValue(HpackEntryType::kIndexedLiteralHeader, 62,
+ false, value2);
+
+ // Confirm that entry has been added by re-using it.
+ hbb.AppendIndexedHeader(62);
+
+ // Add another entry referring to the name of the second. This will evict the
+ // second.
+ hbb.AppendNameIndexAndLiteralValue(HpackEntryType::kIndexedLiteralHeader, 62,
+ false, value3);
+
+ // Confirm that entry has been added by re-using it.
+ hbb.AppendIndexedHeader(62);
+
+ EXPECT_TRUE(DecodeHeaderBlock(hbb.buffer()));
+
+ SpdyHeaderBlock expected_header_set;
+ expected_header_set.AppendValueOrAddHeader(name, value1);
+ expected_header_set.AppendValueOrAddHeader(name, value1);
+ expected_header_set.AppendValueOrAddHeader(name, value2);
+ expected_header_set.AppendValueOrAddHeader(name, value2);
+ expected_header_set.AppendValueOrAddHeader(name, value3);
+ expected_header_set.AppendValueOrAddHeader(name, value3);
+
+ // SpdyHeaderBlock stores these 6 strings as '\0' separated values.
+ // Make sure that is what happened.
+ string joined_values = expected_header_set[name].as_string();
+ EXPECT_EQ(joined_values.size(),
+ 2 * value1.size() + 2 * value2.size() + 2 * value3.size() + 5);
+
+ EXPECT_EQ(expected_header_set, decoded_block());
+}
+
+} // namespace
+} // namespace test
+} // namespace net
diff --git a/chromium/net/spdy/hpack/hpack_decoder_interface.h b/chromium/net/spdy/hpack/hpack_decoder_interface.h
index dfc6f82caaf..1103e3198fb 100644
--- a/chromium/net/spdy/hpack/hpack_decoder_interface.h
+++ b/chromium/net/spdy/hpack/hpack_decoder_interface.h
@@ -28,11 +28,13 @@ class NET_EXPORT_PRIVATE HpackDecoderInterface {
// If a SpdyHeadersHandlerInterface is provided, the decoder will emit
// headers to it rather than accumulating them in a SpdyHeaderBlock.
+ // Does not take ownership of the handler, but does use the pointer until
+ // the current HPACK block is completely decoded.
virtual void HandleControlFrameHeadersStart(
SpdyHeadersHandlerInterface* handler) = 0;
// Called as HPACK block fragments arrive. Returns false if an error occurred
- // while decoding the block.
+ // while decoding the block. Does not take ownership of headers_data.
virtual bool HandleControlFrameHeadersData(const char* headers_data,
size_t headers_data_length) = 0;
@@ -44,7 +46,7 @@ class NET_EXPORT_PRIVATE HpackDecoderInterface {
// Discards the handler supplied at the start of decoding the block.
// TODO(jamessynge): Determine if compressed_len is needed; it is used to
// produce UUMA stat Net.SpdyHpackDecompressionPercentage, but only for
- // SPDY3, not HTTP2.
+ // deprecated SPDY3.
virtual bool HandleControlFrameHeadersComplete(size_t* compressed_len) = 0;
// Accessor for the most recently decoded headers block. Valid until the next
@@ -57,6 +59,11 @@ class NET_EXPORT_PRIVATE HpackDecoderInterface {
std::unique_ptr<HpackHeaderTable::DebugVisitorInterface> visitor) = 0;
// Set how much encoded data this decoder is willing to buffer.
+ // TODO(jamessynge): Resolve definition of this value, as it is currently
+ // too tied to a single implementation. We probably want to limit one or more
+ // of these: individual name or value strings, header entries, the entire
+ // header list, or the HPACK block; we probably shouldn't care about the size
+ // of individual transport buffers.
virtual void set_max_decode_buffer_size_bytes(
size_t max_decode_buffer_size_bytes) = 0;
};
diff --git a/chromium/net/spdy/hpack/hpack_decoder_test.cc b/chromium/net/spdy/hpack/hpack_decoder_test.cc
index b6bbcbe2740..5a26633a762 100644
--- a/chromium/net/spdy/hpack/hpack_decoder_test.cc
+++ b/chromium/net/spdy/hpack/hpack_decoder_test.cc
@@ -351,9 +351,6 @@ TEST_P(HpackDecoderTest, InvalidIndexedHeader) {
EXPECT_FALSE(DecodeHeaderBlock(StringPiece("\xbe", 1)));
}
-// Test that a header block with a pseudo-header field following a regular one
-// is treated as malformed. (HTTP2 draft-14 8.1.2.1., HPACK draft-09 3.1.)
-
TEST_P(HpackDecoderTest, ContextUpdateMaximumSize) {
EXPECT_EQ(kDefaultHeaderTableSizeSetting,
decoder_peer_.header_table()->max_size());
@@ -546,8 +543,9 @@ TEST_P(HpackDecoderTest, StringLiteralIncomplete) {
EXPECT_EQ(21u, input_stream.ParsedBytes());
}
-// Round-tripping the header set from E.2.1 should work.
-TEST_P(HpackDecoderTest, BasicE21) {
+// Round-tripping the header set from RFC 7541 C.3.1 should work.
+// http://httpwg.org/specs/rfc7541.html#rfc.section.C.3.1
+TEST_P(HpackDecoderTest, BasicC31) {
HpackEncoder encoder(ObtainHpackHuffmanTable());
SpdyHeaderBlock expected_header_set;
@@ -564,7 +562,9 @@ TEST_P(HpackDecoderTest, BasicE21) {
EXPECT_EQ(expected_header_set, decoded_block());
}
-TEST_P(HpackDecoderTest, SectionD4RequestHuffmanExamples) {
+// RFC 7541, Section C.4: Request Examples with Huffman Coding
+// http://httpwg.org/specs/rfc7541.html#rfc.section.C.4
+TEST_P(HpackDecoderTest, SectionC4RequestHuffmanExamples) {
// 82 | == Indexed - Add ==
// | idx = 2
// | -> :method: GET
@@ -671,7 +671,9 @@ TEST_P(HpackDecoderTest, SectionD4RequestHuffmanExamples) {
EXPECT_EQ(164u, decoder_peer_.header_table()->size());
}
-TEST_P(HpackDecoderTest, SectionD6ResponseHuffmanExamples) {
+// RFC 7541, Section C.6: Response Examples with Huffman Coding
+// http://httpwg.org/specs/rfc7541.html#rfc.section.C.6
+TEST_P(HpackDecoderTest, SectionC6ResponseHuffmanExamples) {
decoder_.ApplyHeaderTableSizeSetting(256);
// 48 | == Literal indexed ==
diff --git a/chromium/net/spdy/hpack/hpack_encoder.cc b/chromium/net/spdy/hpack/hpack_encoder.cc
index 7362bb1acc6..0ec5e8f67d4 100644
--- a/chromium/net/spdy/hpack/hpack_encoder.cc
+++ b/chromium/net/spdy/hpack/hpack_encoder.cc
@@ -82,7 +82,7 @@ HpackEncoder::HpackEncoder(const HpackHuffmanTable& table)
min_table_size_setting_received_(std::numeric_limits<size_t>::max()),
listener_(NoOpListener),
should_index_(DefaultPolicy),
- allow_huffman_compression_(true),
+ enable_compression_(true),
should_emit_table_size_(false) {}
HpackEncoder::~HpackEncoder() {}
@@ -120,21 +120,6 @@ bool HpackEncoder::EncodeHeaderSet(const SpdyHeaderBlock& header_set,
return true;
}
-bool HpackEncoder::EncodeHeaderSetWithoutCompression(
- const SpdyHeaderBlock& header_set,
- string* output) {
- allow_huffman_compression_ = false;
- MaybeEmitTableSize();
- for (const auto& header : header_set) {
- listener_(header.first, header.second);
- // Note that cookies are not crumbled in this case.
- EmitNonIndexedLiteral(header);
- }
- allow_huffman_compression_ = true;
- output_stream_.TakeString(output);
- return true;
-}
-
void HpackEncoder::ApplyHeaderTableSizeSetting(size_t size_setting) {
if (size_setting == header_table_.settings_size_bound()) {
return;
@@ -153,12 +138,16 @@ void HpackEncoder::EncodeRepresentations(RepresentationIterator* iter,
while (iter->HasNext()) {
const auto header = iter->Next();
listener_(header.first, header.second);
- const HpackEntry* entry =
- header_table_.GetByNameAndValue(header.first, header.second);
- if (entry != nullptr) {
- EmitIndex(entry);
- } else if (should_index_(header.first, header.second)) {
- EmitIndexedLiteral(header);
+ if (enable_compression_) {
+ const HpackEntry* entry =
+ header_table_.GetByNameAndValue(header.first, header.second);
+ if (entry != nullptr) {
+ EmitIndex(entry);
+ } else if (should_index_(header.first, header.second)) {
+ EmitIndexedLiteral(header);
+ } else {
+ EmitNonIndexedLiteral(header);
+ }
} else {
EmitNonIndexedLiteral(header);
}
@@ -168,17 +157,22 @@ void HpackEncoder::EncodeRepresentations(RepresentationIterator* iter,
}
void HpackEncoder::EmitIndex(const HpackEntry* entry) {
+ DVLOG(2) << "Emitting index " << header_table_.IndexOf(entry);
output_stream_.AppendPrefix(kIndexedOpcode);
output_stream_.AppendUint32(header_table_.IndexOf(entry));
}
void HpackEncoder::EmitIndexedLiteral(const Representation& representation) {
+ DVLOG(2) << "Emitting indexed literal: (" << representation.first << ", "
+ << representation.second << ")";
output_stream_.AppendPrefix(kLiteralIncrementalIndexOpcode);
EmitLiteral(representation);
header_table_.TryAddEntry(representation.first, representation.second);
}
void HpackEncoder::EmitNonIndexedLiteral(const Representation& representation) {
+ DVLOG(2) << "Emitting nonindexed literal: (" << representation.first << ", "
+ << representation.second << ")";
output_stream_.AppendPrefix(kLiteralNoIndexOpcode);
output_stream_.AppendUint32(0);
EmitString(representation.first);
@@ -198,13 +192,14 @@ void HpackEncoder::EmitLiteral(const Representation& representation) {
void HpackEncoder::EmitString(StringPiece str) {
size_t encoded_size =
- (!allow_huffman_compression_ ? str.size()
- : huffman_table_.EncodedSize(str));
+ enable_compression_ ? huffman_table_.EncodedSize(str) : str.size();
if (encoded_size < str.size()) {
+ DVLOG(2) << "Emitted Huffman-encoded string of length " << encoded_size;
output_stream_.AppendPrefix(kStringLiteralHuffmanEncoded);
output_stream_.AppendUint32(encoded_size);
huffman_table_.EncodeString(str, &output_stream_);
} else {
+ DVLOG(2) << "Emitted literal string of length " << str.size();
output_stream_.AppendPrefix(kStringLiteralIdentityEncoded);
output_stream_.AppendUint32(str.size());
output_stream_.AppendBytes(str);
@@ -286,9 +281,7 @@ void HpackEncoder::GatherRepresentation(const Representation& header_field,
// Iteratively encodes a SpdyHeaderBlock.
class HpackEncoder::Encoderator : public ProgressiveEncoder {
public:
- Encoderator(const SpdyHeaderBlock& header_set,
- HpackEncoder* encoder,
- bool use_compression);
+ Encoderator(const SpdyHeaderBlock& header_set, HpackEncoder* encoder);
// Encoderator is neither copyable nor movable.
Encoderator(const Encoderator&) = delete;
@@ -307,29 +300,27 @@ class HpackEncoder::Encoderator : public ProgressiveEncoder {
Representations pseudo_headers_;
Representations regular_headers_;
bool has_next_;
- bool use_compression_;
};
HpackEncoder::Encoderator::Encoderator(const SpdyHeaderBlock& header_set,
- HpackEncoder* encoder,
- bool use_compression)
- : encoder_(encoder), has_next_(true), use_compression_(use_compression) {
+ HpackEncoder* encoder)
+ : encoder_(encoder), has_next_(true) {
// Separate header set into pseudo-headers and regular headers.
+ const bool use_compression = encoder_->enable_compression_;
bool found_cookie = false;
for (const auto& header : header_set) {
if (!found_cookie && header.first == "cookie") {
// Note that there can only be one "cookie" header, because header_set
// is a map.
found_cookie = true;
- use_compression_ ? CookieToCrumbs(header, &regular_headers_)
- : GatherRepresentation(header, &regular_headers_);
+ CookieToCrumbs(header, &regular_headers_);
} else if (!header.first.empty() &&
header.first[0] == kPseudoHeaderPrefix) {
- use_compression_ ? DecomposeRepresentation(header, &pseudo_headers_)
- : GatherRepresentation(header, &pseudo_headers_);
+ use_compression ? DecomposeRepresentation(header, &pseudo_headers_)
+ : GatherRepresentation(header, &pseudo_headers_);
} else {
- use_compression_ ? DecomposeRepresentation(header, &regular_headers_)
- : GatherRepresentation(header, &regular_headers_);
+ use_compression ? DecomposeRepresentation(header, &regular_headers_)
+ : GatherRepresentation(header, &regular_headers_);
}
}
header_it_ = base::MakeUnique<RepresentationIterator>(pseudo_headers_,
@@ -341,13 +332,14 @@ HpackEncoder::Encoderator::Encoderator(const SpdyHeaderBlock& header_set,
void HpackEncoder::Encoderator::Next(size_t max_encoded_bytes, string* output) {
SPDY_BUG_IF(!has_next_)
<< "Encoderator::Next called with nothing left to encode.";
+ const bool use_compression = encoder_->enable_compression_;
// Encode up to max_encoded_bytes of headers.
while (header_it_->HasNext() &&
encoder_->output_stream_.size() <= max_encoded_bytes) {
const Representation header = header_it_->Next();
encoder_->listener_(header.first, header.second);
- if (use_compression_) {
+ if (use_compression) {
const HpackEntry* entry = encoder_->header_table_.GetByNameAndValue(
header.first, header.second);
if (entry != nullptr) {
@@ -358,9 +350,7 @@ void HpackEncoder::Encoderator::Next(size_t max_encoded_bytes, string* output) {
encoder_->EmitNonIndexedLiteral(header);
}
} else {
- encoder_->allow_huffman_compression_ = false;
encoder_->EmitNonIndexedLiteral(header);
- encoder_->allow_huffman_compression_ = true;
}
}
@@ -369,9 +359,8 @@ void HpackEncoder::Encoderator::Next(size_t max_encoded_bytes, string* output) {
}
std::unique_ptr<HpackEncoder::ProgressiveEncoder> HpackEncoder::EncodeHeaderSet(
- const SpdyHeaderBlock& header_set,
- bool use_compression) {
- return base::MakeUnique<Encoderator>(header_set, this, use_compression);
+ const SpdyHeaderBlock& header_set) {
+ return base::MakeUnique<Encoderator>(header_set, this);
}
} // namespace net
diff --git a/chromium/net/spdy/hpack/hpack_encoder.h b/chromium/net/spdy/hpack/hpack_encoder.h
index b2778afedbe..f2d95e3257b 100644
--- a/chromium/net/spdy/hpack/hpack_encoder.h
+++ b/chromium/net/spdy/hpack/hpack_encoder.h
@@ -60,12 +60,6 @@ class NET_EXPORT_PRIVATE HpackEncoder {
// whether or not the encoding was successful.
bool EncodeHeaderSet(const SpdyHeaderBlock& header_set, std::string* output);
- // Encodes the given header set into the given string. Only non-indexed
- // literal representations are emitted, bypassing the header table. Huffman
- // coding is also not used. Returns whether the encoding was successful.
- bool EncodeHeaderSetWithoutCompression(const SpdyHeaderBlock& header_set,
- std::string* output);
-
class NET_EXPORT_PRIVATE ProgressiveEncoder {
public:
virtual ~ProgressiveEncoder() {}
@@ -81,8 +75,7 @@ class NET_EXPORT_PRIVATE HpackEncoder {
// Returns a ProgressiveEncoder which must be outlived by both the given
// SpdyHeaderBlock and this object.
std::unique_ptr<ProgressiveEncoder> EncodeHeaderSet(
- const SpdyHeaderBlock& header_set,
- bool use_compression);
+ const SpdyHeaderBlock& header_set);
// Called upon a change to SETTINGS_HEADER_TABLE_SIZE. Specifically, this
// is to be called after receiving (and sending an acknowledgement for) a
@@ -106,6 +99,8 @@ class NET_EXPORT_PRIVATE HpackEncoder {
header_table_.set_debug_visitor(std::move(visitor));
}
+ void DisableCompression() { enable_compression_ = false; }
+
private:
friend class test::HpackEncoderPeer;
@@ -149,7 +144,7 @@ class NET_EXPORT_PRIVATE HpackEncoder {
size_t min_table_size_setting_received_;
HeaderListener listener_;
IndexingPolicy should_index_;
- bool allow_huffman_compression_;
+ bool enable_compression_;
bool should_emit_table_size_;
DISALLOW_COPY_AND_ASSIGN(HpackEncoder);
diff --git a/chromium/net/spdy/hpack/hpack_encoder_test.cc b/chromium/net/spdy/hpack/hpack_encoder_test.cc
index fd4861c4935..c1db5b4c19a 100644
--- a/chromium/net/spdy/hpack/hpack_encoder_test.cc
+++ b/chromium/net/spdy/hpack/hpack_encoder_test.cc
@@ -9,6 +9,7 @@
#include "base/rand_util.h"
#include "net/base/arena.h"
+#include "net/spdy/hpack/hpack_huffman_table.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
@@ -41,10 +42,11 @@ class HpackEncoderPeer {
explicit HpackEncoderPeer(HpackEncoder* encoder) : encoder_(encoder) {}
+ bool compression_enabled() const { return encoder_->enable_compression_; }
HpackHeaderTable* table() { return &encoder_->header_table_; }
HpackHeaderTablePeer table_peer() { return HpackHeaderTablePeer(table()); }
- void set_allow_huffman_compression(bool allow) {
- encoder_->allow_huffman_compression_ = allow;
+ const HpackHuffmanTable& huffman_table() const {
+ return encoder_->huffman_table_;
}
void EmitString(StringPiece str) { encoder_->EmitString(str); }
void TakeString(string* out) { encoder_->output_stream_.TakeString(out); }
@@ -75,23 +77,19 @@ class HpackEncoderPeer {
static bool EncodeHeaderSet(HpackEncoder* encoder,
const SpdyHeaderBlock& header_set,
string* output,
- bool use_compression,
bool use_incremental) {
if (use_incremental) {
- return EncodeIncremental(encoder, header_set, output, use_compression);
+ return EncodeIncremental(encoder, header_set, output);
} else {
- return use_compression ? encoder->EncodeHeaderSet(header_set, output)
- : encoder->EncodeHeaderSetWithoutCompression(
- header_set, output);
+ return encoder->EncodeHeaderSet(header_set, output);
}
}
static bool EncodeIncremental(HpackEncoder* encoder,
const SpdyHeaderBlock& header_set,
- string* output,
- bool use_compression) {
+ string* output) {
std::unique_ptr<HpackEncoder::ProgressiveEncoder> encoderator =
- encoder->EncodeHeaderSet(header_set, use_compression);
+ encoder->EncodeHeaderSet(header_set);
string output_buffer;
encoderator->Next(base::RandInt(0, 15), &output_buffer);
while (encoderator->HasNext()) {
@@ -137,9 +135,6 @@ class HpackEncoderTest : public ::testing::TestWithParam<bool> {
// No further insertions may occur without evictions.
peer_.table()->SetMaxSize(peer_.table()->size());
-
- // Disable Huffman coding by default. Most tests don't care about it.
- peer_.set_allow_huffman_compression(false);
}
void SaveHeaders(StringPiece name, StringPiece value) {
@@ -157,29 +152,34 @@ class HpackEncoderTest : public ::testing::TestWithParam<bool> {
void ExpectIndexedLiteral(const HpackEntry* key_entry, StringPiece value) {
expected_.AppendPrefix(kLiteralIncrementalIndexOpcode);
expected_.AppendUint32(IndexOf(key_entry));
- expected_.AppendPrefix(kStringLiteralIdentityEncoded);
- expected_.AppendUint32(value.size());
- expected_.AppendBytes(value);
+ ExpectString(&expected_, value);
}
void ExpectIndexedLiteral(StringPiece name, StringPiece value) {
expected_.AppendPrefix(kLiteralIncrementalIndexOpcode);
expected_.AppendUint32(0);
- expected_.AppendPrefix(kStringLiteralIdentityEncoded);
- expected_.AppendUint32(name.size());
- expected_.AppendBytes(name);
- expected_.AppendPrefix(kStringLiteralIdentityEncoded);
- expected_.AppendUint32(value.size());
- expected_.AppendBytes(value);
+ ExpectString(&expected_, name);
+ ExpectString(&expected_, value);
}
void ExpectNonIndexedLiteral(StringPiece name, StringPiece value) {
expected_.AppendPrefix(kLiteralNoIndexOpcode);
expected_.AppendUint32(0);
- expected_.AppendPrefix(kStringLiteralIdentityEncoded);
- expected_.AppendUint32(name.size());
- expected_.AppendBytes(name);
- expected_.AppendPrefix(kStringLiteralIdentityEncoded);
- expected_.AppendUint32(value.size());
- expected_.AppendBytes(value);
+ ExpectString(&expected_, name);
+ ExpectString(&expected_, value);
+ }
+ void ExpectString(HpackOutputStream* stream, StringPiece str) {
+ const HpackHuffmanTable& huffman_table = peer_.huffman_table();
+ size_t encoded_size = peer_.compression_enabled()
+ ? huffman_table.EncodedSize(str)
+ : str.size();
+ if (encoded_size < str.size()) {
+ expected_.AppendPrefix(kStringLiteralHuffmanEncoded);
+ expected_.AppendUint32(encoded_size);
+ huffman_table.EncodeString(str, stream);
+ } else {
+ expected_.AppendPrefix(kStringLiteralIdentityEncoded);
+ expected_.AppendUint32(str.size());
+ expected_.AppendBytes(str);
+ }
}
void ExpectHeaderTableSizeUpdate(uint32_t size) {
expected_.AppendPrefix(kHeaderTableSizeUpdateOpcode);
@@ -189,15 +189,7 @@ class HpackEncoderTest : public ::testing::TestWithParam<bool> {
string expected_out, actual_out;
expected_.TakeString(&expected_out);
EXPECT_TRUE(test::HpackEncoderPeer::EncodeHeaderSet(
- &encoder_, header_set, &actual_out, true, use_incremental_));
- EXPECT_EQ(expected_out, actual_out);
- }
- void CompareWithExpectedEncodingWithoutCompression(
- const SpdyHeaderBlock& header_set) {
- string expected_out, actual_out;
- expected_.TakeString(&expected_out);
- EXPECT_TRUE(test::HpackEncoderPeer::EncodeHeaderSet(
- &encoder_, header_set, &actual_out, false, use_incremental_));
+ &encoder_, header_set, &actual_out, use_incremental_));
EXPECT_EQ(expected_out, actual_out);
}
size_t IndexOf(const HpackEntry* entry) {
@@ -317,8 +309,6 @@ TEST_P(HpackEncoderTest, CookieHeaderIsCrumbled) {
}
TEST_P(HpackEncoderTest, StringsDynamicallySelectHuffmanCoding) {
- peer_.set_allow_huffman_compression(true);
-
// Compactable string. Uses Huffman coding.
peer_.EmitString("feedbeef");
expected_.AppendPrefix(kStringLiteralHuffmanEncoded);
@@ -341,12 +331,11 @@ TEST_P(HpackEncoderTest, EncodingWithoutCompression) {
encoder_.SetHeaderListener([this](StringPiece name, StringPiece value) {
this->SaveHeaders(name, value);
});
-
- // Implementation should internally disable.
- peer_.set_allow_huffman_compression(true);
+ encoder_.DisableCompression();
ExpectNonIndexedLiteral(":path", "/index.html");
- ExpectNonIndexedLiteral("cookie", "foo=bar; baz=bing");
+ ExpectNonIndexedLiteral("cookie", "foo=bar");
+ ExpectNonIndexedLiteral("cookie", "baz=bing");
ExpectNonIndexedLiteral("hello", "goodbye");
SpdyHeaderBlock headers;
@@ -354,12 +343,12 @@ TEST_P(HpackEncoderTest, EncodingWithoutCompression) {
headers["cookie"] = "foo=bar; baz=bing";
headers["hello"] = "goodbye";
- CompareWithExpectedEncodingWithoutCompression(headers);
+ CompareWithExpectedEncoding(headers);
- EXPECT_THAT(headers_observed_,
- ElementsAre(Pair(":path", "/index.html"),
- Pair("cookie", "foo=bar; baz=bing"),
- Pair("hello", "goodbye")));
+ EXPECT_THAT(
+ headers_observed_,
+ ElementsAre(Pair(":path", "/index.html"), Pair("cookie", "foo=bar"),
+ Pair("cookie", "baz=bing"), Pair("hello", "goodbye")));
}
TEST_P(HpackEncoderTest, MultipleEncodingPasses) {
diff --git a/chromium/net/spdy/hpack/hpack_entry.cc b/chromium/net/spdy/hpack/hpack_entry.cc
index 50bb7184279..9a4707915e1 100644
--- a/chromium/net/spdy/hpack/hpack_entry.cc
+++ b/chromium/net/spdy/hpack/hpack_entry.cc
@@ -37,8 +37,8 @@ HpackEntry::HpackEntry(const HpackEntry& other)
} else {
name_ = other.name_;
value_ = other.value_;
- name_ref_.set(name_.data(), name_.size());
- value_ref_.set(value_.data(), value_.size());
+ name_ref_ = StringPiece(name_.data(), name_.size());
+ value_ref_ = StringPiece(value_.data(), value_.size());
}
}
@@ -52,8 +52,8 @@ HpackEntry& HpackEntry::operator=(const HpackEntry& other) {
}
name_ = other.name_;
value_ = other.value_;
- name_ref_.set(name_.data(), name_.size());
- value_ref_.set(value_.data(), value_.size());
+ name_ref_ = StringPiece(name_.data(), name_.size());
+ value_ref_ = StringPiece(value_.data(), value_.size());
return *this;
}
diff --git a/chromium/net/spdy/hpack/hpack_entry.h b/chromium/net/spdy/hpack/hpack_entry.h
index de3f9fe95aa..12d3f068e9d 100644
--- a/chromium/net/spdy/hpack/hpack_entry.h
+++ b/chromium/net/spdy/hpack/hpack_entry.h
@@ -2,8 +2,8 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#ifndef NET_SPDY_HPACK_ENTRY_H_
-#define NET_SPDY_HPACK_ENTRY_H_
+#ifndef NET_SPDY_HPACK_HPACK_ENTRY_H_
+#define NET_SPDY_HPACK_HPACK_ENTRY_H_
#include <stddef.h>
@@ -104,4 +104,4 @@ class NET_EXPORT_PRIVATE HpackEntry {
} // namespace net
-#endif // NET_SPDY_HPACK_ENTRY_H_
+#endif // NET_SPDY_HPACK_HPACK_ENTRY_H_
diff --git a/chromium/net/spdy/hpack/hpack_header_table.h b/chromium/net/spdy/hpack/hpack_header_table.h
index 3fb8036a9e5..ca0318a8107 100644
--- a/chromium/net/spdy/hpack/hpack_header_table.h
+++ b/chromium/net/spdy/hpack/hpack_header_table.h
@@ -2,8 +2,8 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#ifndef NET_SPDY_HPACK_HEADER_TABLE_H_
-#define NET_SPDY_HPACK_HEADER_TABLE_H_
+#ifndef NET_SPDY_HPACK_HPACK_HEADER_TABLE_H_
+#define NET_SPDY_HPACK_HPACK_HEADER_TABLE_H_
#include <cstddef>
#include <deque>
@@ -173,4 +173,4 @@ class NET_EXPORT_PRIVATE HpackHeaderTable {
} // namespace net
-#endif // NET_SPDY_HPACK_HEADER_TABLE_H_
+#endif // NET_SPDY_HPACK_HPACK_HEADER_TABLE_H_
diff --git a/chromium/net/spdy/hpack/hpack_huffman_decoder.cc b/chromium/net/spdy/hpack/hpack_huffman_decoder.cc
index f305a664e07..dcb512cb76a 100644
--- a/chromium/net/spdy/hpack/hpack_huffman_decoder.cc
+++ b/chromium/net/spdy/hpack/hpack_huffman_decoder.cc
@@ -158,7 +158,7 @@ const uint8_t kCanonicalToSymbol[] = {
};
// clang-format on
-#if !defined(NDEBUG) || defined(DCHECK_ALWAYS_ON)
+#if DCHECK_IS_ON()
// Only used in DLOG.
bool IsEOSPrefix(HuffmanWord bits, HuffmanCodeLength bits_available) {
@@ -171,7 +171,7 @@ bool IsEOSPrefix(HuffmanWord bits, HuffmanCodeLength bits_available) {
return bits == expected;
}
-#endif // NDEBUG && !defined(DCHECK_ALWAYS_ON)
+#endif // DCHECK_IS_ON()
} // namespace
diff --git a/chromium/net/spdy/hpack/hpack_huffman_table.h b/chromium/net/spdy/hpack/hpack_huffman_table.h
index c02e175e81b..96c39504dbd 100644
--- a/chromium/net/spdy/hpack/hpack_huffman_table.h
+++ b/chromium/net/spdy/hpack/hpack_huffman_table.h
@@ -2,8 +2,8 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#ifndef NET_SPDY_HPACK_HUFFMAN_TABLE_H_
-#define NET_SPDY_HPACK_HUFFMAN_TABLE_H_
+#ifndef NET_SPDY_HPACK_HPACK_HUFFMAN_TABLE_H_
+#define NET_SPDY_HPACK_HPACK_HUFFMAN_TABLE_H_
#include <stdint.h>
@@ -129,4 +129,4 @@ class NET_EXPORT_PRIVATE HpackHuffmanTable {
} // namespace net
-#endif // NET_SPDY_HPACK_HUFFMAN_TABLE_H_
+#endif // NET_SPDY_HPACK_HPACK_HUFFMAN_TABLE_H_
diff --git a/chromium/net/spdy/hpack/hpack_input_stream.h b/chromium/net/spdy/hpack/hpack_input_stream.h
index af26c94e062..95791bb84cc 100644
--- a/chromium/net/spdy/hpack/hpack_input_stream.h
+++ b/chromium/net/spdy/hpack/hpack_input_stream.h
@@ -2,8 +2,8 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#ifndef NET_SPDY_HPACK_INPUT_STREAM_H_
-#define NET_SPDY_HPACK_INPUT_STREAM_H_
+#ifndef NET_SPDY_HPACK_HPACK_INPUT_STREAM_H_
+#define NET_SPDY_HPACK_HPACK_INPUT_STREAM_H_
#include <stddef.h>
#include <stdint.h>
@@ -110,4 +110,4 @@ class NET_EXPORT_PRIVATE HpackInputStream {
} // namespace net
-#endif // NET_SPDY_HPACK_INPUT_STREAM_H_
+#endif // NET_SPDY_HPACK_HPACK_INPUT_STREAM_H_
diff --git a/chromium/net/spdy/hpack/hpack_output_stream.h b/chromium/net/spdy/hpack/hpack_output_stream.h
index 4451a88def2..41dfd7d4f4f 100644
--- a/chromium/net/spdy/hpack/hpack_output_stream.h
+++ b/chromium/net/spdy/hpack/hpack_output_stream.h
@@ -2,8 +2,8 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#ifndef NET_SPDY_HPACK_OUTPUT_STREAM_H_
-#define NET_SPDY_HPACK_OUTPUT_STREAM_H_
+#ifndef NET_SPDY_HPACK_HPACK_OUTPUT_STREAM_H_
+#define NET_SPDY_HPACK_HPACK_OUTPUT_STREAM_H_
#include <stddef.h>
#include <stdint.h>
@@ -72,4 +72,4 @@ class NET_EXPORT_PRIVATE HpackOutputStream {
} // namespace net
-#endif // NET_SPDY_HPACK_OUTPUT_STREAM_H_
+#endif // NET_SPDY_HPACK_HPACK_OUTPUT_STREAM_H_
diff --git a/chromium/net/spdy/hpack/hpack_static_table.h b/chromium/net/spdy/hpack/hpack_static_table.h
index ad22097408c..923913487a7 100644
--- a/chromium/net/spdy/hpack/hpack_static_table.h
+++ b/chromium/net/spdy/hpack/hpack_static_table.h
@@ -2,8 +2,8 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#ifndef NET_SPDY_HPACK_STATIC_TABLE_H_
-#define NET_SPDY_HPACK_STATIC_TABLE_H_
+#ifndef NET_SPDY_HPACK_HPACK_STATIC_TABLE_H_
+#define NET_SPDY_HPACK_HPACK_STATIC_TABLE_H_
#include <stddef.h>
@@ -50,4 +50,4 @@ class NET_EXPORT_PRIVATE HpackStaticTable {
} // namespace net
-#endif // NET_SPDY_HPACK_STATIC_TABLE_H_
+#endif // NET_SPDY_HPACK_HPACK_STATIC_TABLE_H_
diff --git a/chromium/net/spdy/http2_frame_decoder_adapter.cc b/chromium/net/spdy/http2_frame_decoder_adapter.cc
new file mode 100644
index 00000000000..7a78386ba38
--- /dev/null
+++ b/chromium/net/spdy/http2_frame_decoder_adapter.cc
@@ -0,0 +1,975 @@
+// Copyright 2016 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.
+
+#include "net/spdy/http2_frame_decoder_adapter.h"
+
+// Logging policy: If an error in the input is detected, VLOG(n) is used so that
+// the option exists to debug the situation. Otherwise, this code mostly uses
+// DVLOG so that the logging does not slow down production code when things are
+// working OK.
+
+#include <stddef.h>
+
+#include <cstring>
+#include <string>
+#include <utility>
+
+#include "base/logging.h"
+#include "base/optional.h"
+#include "base/strings/string_piece.h"
+#include "base/sys_byteorder.h"
+#include "net/http2/decoder/decode_buffer.h"
+#include "net/http2/decoder/decode_status.h"
+#include "net/http2/decoder/http2_frame_decoder.h"
+#include "net/http2/decoder/http2_frame_decoder_listener.h"
+#include "net/http2/http2_constants.h"
+#include "net/http2/http2_structures.h"
+#include "net/spdy/hpack/hpack_decoder_interface.h"
+#include "net/spdy/hpack/hpack_header_table.h"
+#include "net/spdy/spdy_alt_svc_wire_format.h"
+#include "net/spdy/spdy_bug_tracker.h"
+#include "net/spdy/spdy_frame_builder.h"
+#include "net/spdy/spdy_header_block.h"
+#include "net/spdy/spdy_headers_handler_interface.h"
+#include "net/spdy/spdy_protocol.h"
+
+using std::string;
+
+namespace net {
+
+namespace {
+
+const bool kHasPriorityFields = true;
+const bool kNotHasPriorityFields = false;
+
+const Http2FrameType kFrameTypeBlocked = Http2FrameType(11);
+
+bool IsPaddable(Http2FrameType type) {
+ return type == Http2FrameType::DATA || type == Http2FrameType::HEADERS ||
+ type == Http2FrameType::PUSH_PROMISE;
+}
+
+SpdyFrameType ToSpdyFrameType(Http2FrameType type) {
+ return ParseFrameType(static_cast<int>(type));
+}
+
+uint64_t ToSpdyPingId(const Http2PingFields& ping) {
+ uint64_t v;
+ std::memcpy(&v, ping.opaque_data, Http2PingFields::EncodedSize());
+ return base::NetToHost64(v);
+}
+
+// Overwrites the fields of the header with invalid values, for the purpose
+// of identifying reading of unset fields. Only takes effect for debug builds.
+// In Address Sanatizer builds, it also marks the fields as un-readable.
+void CorruptFrameHeader(Http2FrameHeader* header) {
+#ifndef NDEBUG
+ // Beyond a valid payload length, which is 2^24 - 1.
+ header->payload_length = 0x1010dead;
+ // An unsupported frame type.
+ header->type = Http2FrameType(0x80);
+ DCHECK(!IsSupportedHttp2FrameType(header->type));
+ // Frame flag bits that aren't used by any supported frame type.
+ header->flags = Http2FrameFlag(0xd2);
+ // A stream id with the reserved high-bit (R in the RFC) set.
+ // 2129510127 when the high-bit is cleared.
+ header->stream_id = 0xfeedbeef;
+#endif
+}
+
+class Http2DecoderAdapter : public SpdyFramerDecoderAdapter,
+ public Http2FrameDecoderListener {
+ typedef SpdyFramer::SpdyState SpdyState;
+ typedef SpdyFramer::SpdyError SpdyError;
+
+ public:
+ explicit Http2DecoderAdapter(SpdyFramer* outer_framer)
+ : SpdyFramerDecoderAdapter(), outer_framer_(outer_framer) {
+ DVLOG(1) << "Http2DecoderAdapter ctor, outer_framer=" << outer_framer;
+ ResetInternal();
+ }
+ ~Http2DecoderAdapter() override {}
+
+ // ===========================================================================
+ // Implementations of the pure virtual methods from SpdyFramerDecoderAdapter;
+ // the other virtual methods of SpdyFramerDecoderAdapter have satsifactory
+ // default implementations.
+
+ // Passes the call on to the HPACK decoder.
+ void SetDecoderHeaderTableDebugVisitor(
+ std::unique_ptr<HpackHeaderTable::DebugVisitorInterface> visitor)
+ override {
+ GetHpackDecoder()->SetHeaderTableDebugVisitor(std::move(visitor));
+ }
+
+ size_t ProcessInput(const char* data, size_t len) override {
+ size_t limit = outer_framer_->recv_frame_size_limit();
+ frame_decoder_->set_maximum_payload_size(limit);
+
+ size_t total_processed = 0;
+ while (len > 0 && spdy_state_ != SpdyFramer::SPDY_ERROR) {
+ // Process one at a time so that we update the adapter's internal
+ // state appropriately.
+ const size_t processed = ProcessInputFrame(data, len);
+
+ // We had some data, and weren't in an error state, so should have
+ // processed/consumed at least one byte of it, even if we then ended up
+ // in an error state.
+ DCHECK(processed > 0) << "processed=" << processed
+ << " spdy_state_=" << spdy_state_
+ << " spdy_error_=" << spdy_error_;
+
+ data += processed;
+ len -= processed;
+ total_processed += processed;
+ if (process_single_input_frame() || processed == 0) {
+ break;
+ }
+ }
+ return total_processed;
+ }
+
+ void Reset() override { ResetInternal(); }
+
+ SpdyState state() const override { return spdy_state_; }
+
+ SpdyError error_code() const override { return spdy_error_; }
+
+ bool probable_http_response() const override {
+ return latched_probable_http_response_;
+ }
+
+ // ===========================================================================
+ // Implementations of the methods declared by Http2FrameDecoderListener.
+
+ // Called once the common frame header has been decoded for any frame.
+ // This function is largely based on SpdyFramer::ValidateFrameHeader
+ // and some parts of SpdyFramer::ProcessCommonHeader.
+ bool OnFrameHeader(const Http2FrameHeader& header) override {
+ DVLOG(1) << "OnFrameHeader: " << header;
+ decoded_frame_header_ = true;
+ if (!latched_probable_http_response_) {
+ latched_probable_http_response_ = header.IsProbableHttpResponse();
+ }
+ if (!IsSupportedHttp2FrameType(header.type) &&
+ header.type != kFrameTypeBlocked) {
+ // In HTTP2 we ignore unknown frame types for extensibility, as long as
+ // the rest of the control frame header is valid.
+ // We rely on the visitor to check validity of stream_id.
+ bool valid_stream = visitor()->OnUnknownFrame(
+ header.stream_id, static_cast<int>(header.type));
+ if (has_expected_frame_type_ && header.type != expected_frame_type_) {
+ // Report an unexpected frame error and close the connection if we
+ // expect a known frame type (probably CONTINUATION) and receive an
+ // unknown frame.
+ VLOG(1) << "The framer was expecting to receive a "
+ << expected_frame_type_
+ << " frame, but instead received an unknown frame of type "
+ << header.type;
+ SetSpdyErrorAndNotify(SpdyError::SPDY_UNEXPECTED_FRAME);
+ return false;
+ } else if (!valid_stream) {
+ // Report an invalid frame error if the stream_id is not valid.
+ VLOG(1) << "Unknown control frame type " << header.type
+ << " received on invalid stream " << header.stream_id;
+ SetSpdyErrorAndNotify(SpdyError::SPDY_INVALID_CONTROL_FRAME);
+ return false;
+ } else {
+ DVLOG(1) << "Ignoring unknown frame type " << header.type;
+ return true;
+ }
+ }
+
+ SpdyFrameType frame_type = ToSpdyFrameType(header.type);
+ if (!IsValidHTTP2FrameStreamId(header.stream_id, frame_type)) {
+ VLOG(1) << "The framer received an invalid streamID of "
+ << header.stream_id << " for a frame of type " << header.type;
+ SetSpdyErrorAndNotify(SpdyError::SPDY_INVALID_STREAM_ID);
+ return false;
+ }
+
+ if (has_expected_frame_type_ && header.type != expected_frame_type_) {
+ VLOG(1) << "Expected frame type " << expected_frame_type_ << ", not "
+ << header.type;
+ SetSpdyErrorAndNotify(SpdyError::SPDY_UNEXPECTED_FRAME);
+ return false;
+ }
+
+ if (!has_expected_frame_type_ &&
+ header.type == Http2FrameType::CONTINUATION) {
+ VLOG(1) << "Got CONTINUATION frame when not expected.";
+ SetSpdyErrorAndNotify(SpdyError::SPDY_UNEXPECTED_FRAME);
+ return false;
+ }
+
+ if (header.type == Http2FrameType::DATA) {
+ // For some reason SpdyFramer still rejects invalid DATA frame flags.
+ uint8_t valid_flags =
+ Http2FrameFlag::FLAG_PADDED | Http2FrameFlag::FLAG_END_STREAM;
+ if (header.HasAnyFlags(~valid_flags)) {
+ SetSpdyErrorAndNotify(SpdyError::SPDY_INVALID_DATA_FRAME_FLAGS);
+ return false;
+ }
+ }
+
+ return true;
+ }
+
+ void OnDataStart(const Http2FrameHeader& header) override {
+ DVLOG(1) << "OnDataStart: " << header;
+
+ if (IsOkToStartFrame(header) && HasRequiredStreamId(header)) {
+ frame_header_ = header;
+ has_frame_header_ = true;
+ visitor()->OnDataFrameHeader(header.stream_id, header.payload_length,
+ header.IsEndStream());
+ }
+ }
+
+ void OnDataPayload(const char* data, size_t len) override {
+ DVLOG(1) << "OnDataPayload: len=" << len;
+ DCHECK(has_frame_header_);
+ DCHECK_EQ(frame_header_.type, Http2FrameType::DATA);
+ visitor()->OnStreamFrameData(frame_header().stream_id, data, len);
+ }
+
+ void OnDataEnd() override {
+ DVLOG(1) << "OnDataEnd";
+ DCHECK(has_frame_header_);
+ DCHECK_EQ(frame_header_.type, Http2FrameType::DATA);
+ if (frame_header().IsEndStream()) {
+ visitor()->OnStreamEnd(frame_header().stream_id);
+ }
+ opt_pad_length_.reset();
+ }
+
+ void OnHeadersStart(const Http2FrameHeader& header) override {
+ DVLOG(1) << "OnHeadersStart: " << header;
+ if (IsOkToStartFrame(header) && HasRequiredStreamId(header)) {
+ frame_header_ = header;
+ has_frame_header_ = true;
+ if (header.HasPriority()) {
+ // Once we've got the priority fields, then we can report the arrival
+ // of this HEADERS frame.
+ on_headers_called_ = false;
+ return;
+ }
+ on_headers_called_ = true;
+ ReportReceiveCompressedFrame(header);
+ visitor()->OnHeaders(header.stream_id, kNotHasPriorityFields,
+ 0, // priority
+ 0, // parent_stream_id
+ false, // exclusive
+ header.IsEndStream(), header.IsEndHeaders());
+ CommonStartHpackBlock();
+ }
+ }
+
+ void OnHeadersPriority(const Http2PriorityFields& priority) override {
+ DVLOG(1) << "OnHeadersPriority: " << priority;
+ DCHECK(has_frame_header_);
+ DCHECK_EQ(frame_type(), Http2FrameType::HEADERS) << frame_header_;
+ DCHECK(frame_header_.HasPriority());
+ DCHECK(!on_headers_called_);
+ on_headers_called_ = true;
+ ReportReceiveCompressedFrame(frame_header_);
+ visitor()->OnHeaders(frame_header_.stream_id, kHasPriorityFields,
+ priority.weight, priority.stream_dependency,
+ priority.is_exclusive, frame_header_.IsEndStream(),
+ frame_header_.IsEndHeaders());
+ CommonStartHpackBlock();
+ }
+
+ void OnHpackFragment(const char* data, size_t len) override {
+ DVLOG(1) << "OnHpackFragment: len=" << len;
+ on_hpack_fragment_called_ = true;
+ if (!GetHpackDecoder()->HandleControlFrameHeadersData(data, len)) {
+ SetSpdyErrorAndNotify(SpdyError::SPDY_DECOMPRESS_FAILURE);
+ return;
+ }
+ }
+
+ void OnHeadersEnd() override {
+ DVLOG(1) << "OnHeadersEnd";
+ CommonHpackFragmentEnd();
+ opt_pad_length_.reset();
+ }
+
+ void OnPriorityFrame(const Http2FrameHeader& header,
+ const Http2PriorityFields& priority) override {
+ DVLOG(1) << "OnPriorityFrame: " << header << "; priority: " << priority;
+ if (IsOkToStartFrame(header) && HasRequiredStreamId(header)) {
+ visitor()->OnPriority(header.stream_id, priority.stream_dependency,
+ priority.weight, priority.is_exclusive);
+ }
+ }
+
+ void OnContinuationStart(const Http2FrameHeader& header) override {
+ DVLOG(1) << "OnContinuationStart: " << header;
+ if (IsOkToStartFrame(header) && HasRequiredStreamId(header)) {
+ DCHECK(has_hpack_first_frame_header_);
+ if (header.stream_id != hpack_first_frame_header_.stream_id) {
+ SetSpdyErrorAndNotify(SpdyError::SPDY_UNEXPECTED_FRAME);
+ return;
+ }
+ frame_header_ = header;
+ has_frame_header_ = true;
+ ReportReceiveCompressedFrame(header);
+ visitor()->OnContinuation(header.stream_id, header.IsEndHeaders());
+ }
+ }
+
+ void OnContinuationEnd() override {
+ DVLOG(1) << "OnContinuationEnd";
+ CommonHpackFragmentEnd();
+ }
+
+ void OnPadLength(size_t trailing_length) override {
+ DVLOG(1) << "OnPadLength: " << trailing_length;
+ opt_pad_length_ = trailing_length;
+ if (frame_header_.type == Http2FrameType::DATA) {
+ visitor()->OnStreamPadding(stream_id(), 1);
+ } else if (frame_header_.type == Http2FrameType::HEADERS) {
+ CHECK_LT(trailing_length, 256u);
+ }
+ }
+
+ void OnPadding(const char* padding, size_t skipped_length) override {
+ DVLOG(1) << "OnPadding: " << skipped_length;
+ if (frame_header_.type == Http2FrameType::DATA) {
+ visitor()->OnStreamPadding(stream_id(), skipped_length);
+ } else {
+ MaybeAnnounceEmptyFirstHpackFragment();
+ }
+ }
+
+ void OnRstStream(const Http2FrameHeader& header,
+ Http2ErrorCode error_code) override {
+ DVLOG(1) << "OnRstStream: " << header << "; code=" << error_code;
+ if (IsOkToStartFrame(header) && HasRequiredStreamId(header)) {
+ // Treat unrecognized error codes as INTERNAL_ERROR as
+ // recommended by the HTTP/2 spec.
+ if (!IsSupportedHttp2ErrorCode(error_code)) {
+ error_code = Http2ErrorCode::INTERNAL_ERROR;
+ }
+ SpdyRstStreamStatus status = RST_STREAM_INTERNAL_ERROR;
+ uint32_t status_raw = static_cast<int>(error_code);
+ if (IsValidRstStreamStatus(status_raw)) {
+ status = ParseRstStreamStatus(status_raw);
+ }
+ visitor()->OnRstStream(header.stream_id, status);
+ }
+ }
+
+ void OnSettingsStart(const Http2FrameHeader& header) override {
+ DVLOG(1) << "OnSettingsStart: " << header;
+ if (IsOkToStartFrame(header) && HasRequiredStreamIdZero(header)) {
+ frame_header_ = header;
+ has_frame_header_ = true;
+ visitor()->OnSettings(0);
+ }
+ }
+
+ void OnSetting(const Http2SettingFields& setting_fields) override {
+ DVLOG(1) << "OnSetting: " << setting_fields;
+ SpdySettingsIds setting_id;
+ if (!ParseSettingsId(static_cast<int>(setting_fields.parameter),
+ &setting_id)) {
+ DVLOG(1) << "Ignoring invalid setting id: " << setting_fields;
+ return;
+ }
+ visitor()->OnSetting(setting_id, setting_fields.value);
+ }
+
+ void OnSettingsEnd() override {
+ DVLOG(1) << "OnSettingsEnd";
+ visitor()->OnSettingsEnd();
+ }
+
+ void OnSettingsAck(const Http2FrameHeader& header) override {
+ DVLOG(1) << "OnSettingsAck: " << header;
+ if (IsOkToStartFrame(header) && HasRequiredStreamIdZero(header)) {
+ visitor()->OnSettingsAck();
+ }
+ }
+
+ void OnPushPromiseStart(const Http2FrameHeader& header,
+ const Http2PushPromiseFields& promise,
+ size_t total_padding_length) override {
+ DVLOG(1) << "OnPushPromiseStart: " << header << "; promise: " << promise
+ << "; total_padding_length: " << total_padding_length;
+ if (IsOkToStartFrame(header) && HasRequiredStreamId(header)) {
+ if (promise.promised_stream_id == 0) {
+ SetSpdyErrorAndNotify(SpdyError::SPDY_INVALID_CONTROL_FRAME);
+ return;
+ }
+ frame_header_ = header;
+ has_frame_header_ = true;
+ ReportReceiveCompressedFrame(header);
+ visitor()->OnPushPromise(header.stream_id, promise.promised_stream_id,
+ header.IsEndHeaders());
+ CommonStartHpackBlock();
+ }
+ }
+
+ void OnPushPromiseEnd() override {
+ DVLOG(1) << "OnPushPromiseEnd";
+ CommonHpackFragmentEnd();
+ opt_pad_length_.reset();
+ }
+
+ void OnPing(const Http2FrameHeader& header,
+ const Http2PingFields& ping) override {
+ DVLOG(1) << "OnPing: " << header << "; ping: " << ping;
+ if (IsOkToStartFrame(header) && HasRequiredStreamIdZero(header)) {
+ visitor()->OnPing(ToSpdyPingId(ping), false);
+ }
+ }
+
+ void OnPingAck(const Http2FrameHeader& header,
+ const Http2PingFields& ping) override {
+ DVLOG(1) << "OnPingAck: " << header << "; ping: " << ping;
+ if (IsOkToStartFrame(header) && HasRequiredStreamIdZero(header)) {
+ visitor()->OnPing(ToSpdyPingId(ping), true);
+ }
+ }
+
+ void OnGoAwayStart(const Http2FrameHeader& header,
+ const Http2GoAwayFields& goaway) override {
+ DVLOG(1) << "OnGoAwayStart: " << header << "; goaway: " << goaway;
+ if (IsOkToStartFrame(header) && HasRequiredStreamIdZero(header)) {
+ frame_header_ = header;
+ has_frame_header_ = true;
+ uint32_t status_raw = static_cast<int>(goaway.error_code);
+ SpdyGoAwayStatus status;
+ if (IsValidGoAwayStatus(status_raw)) {
+ status = ParseGoAwayStatus(status_raw);
+ } else {
+ // Treat unrecognized status codes as INTERNAL_ERROR as
+ // recommended by the HTTP/2 spec.
+ status = SpdyGoAwayStatus::GOAWAY_INTERNAL_ERROR;
+ }
+ visitor()->OnGoAway(goaway.last_stream_id, status);
+ }
+ }
+
+ void OnGoAwayOpaqueData(const char* data, size_t len) override {
+ DVLOG(1) << "OnGoAwayOpaqueData: len=" << len;
+ visitor()->OnGoAwayFrameData(data, len);
+ }
+
+ void OnGoAwayEnd() override {
+ DVLOG(1) << "OnGoAwayEnd";
+ visitor()->OnGoAwayFrameData(nullptr, 0);
+ }
+
+ void OnWindowUpdate(const Http2FrameHeader& header,
+ uint32_t increment) override {
+ DVLOG(1) << "OnWindowUpdate: " << header << "; increment=" << increment;
+ if (IsOkToStartFrame(header)) {
+ visitor()->OnWindowUpdate(header.stream_id, increment);
+ }
+ }
+
+ void OnAltSvcStart(const Http2FrameHeader& header,
+ size_t origin_length,
+ size_t value_length) override {
+ DVLOG(1) << "OnAltSvcStart: " << header
+ << "; origin_length: " << origin_length
+ << "; value_length: " << value_length;
+ if (IsOkToStartFrame(header) && HasRequiredStreamId(header)) {
+ frame_header_ = header;
+ has_frame_header_ = true;
+ alt_svc_origin_.clear();
+ alt_svc_value_.clear();
+ }
+ }
+
+ void OnAltSvcOriginData(const char* data, size_t len) override {
+ DVLOG(1) << "OnAltSvcOriginData: len=" << len;
+ alt_svc_origin_.append(data, len);
+ }
+
+ // Called when decoding the Alt-Svc-Field-Value of an ALTSVC;
+ // the field is uninterpreted.
+ void OnAltSvcValueData(const char* data, size_t len) override {
+ DVLOG(1) << "OnAltSvcValueData: len=" << len;
+ alt_svc_value_.append(data, len);
+ }
+
+ void OnAltSvcEnd() override {
+ DVLOG(1) << "OnAltSvcEnd: origin.size(): " << alt_svc_origin_.size()
+ << "; value.size(): " << alt_svc_value_.size();
+ SpdyAltSvcWireFormat::AlternativeServiceVector altsvc_vector;
+ if (!SpdyAltSvcWireFormat::ParseHeaderFieldValue(alt_svc_value_,
+ &altsvc_vector)) {
+ DLOG(ERROR) << "SpdyAltSvcWireFormat::ParseHeaderFieldValue failed.";
+ SetSpdyErrorAndNotify(SpdyError::SPDY_INVALID_CONTROL_FRAME);
+ return;
+ }
+ visitor()->OnAltSvc(frame_header_.stream_id, alt_svc_origin_,
+ altsvc_vector);
+ // We assume that ALTSVC frames are rare, so get rid of the storage.
+ alt_svc_origin_.clear();
+ alt_svc_origin_.shrink_to_fit();
+ alt_svc_value_.clear();
+ alt_svc_value_.shrink_to_fit();
+ }
+
+ // Except for BLOCKED frames, all other unknown frames are
+ // effectively dropped.
+ void OnUnknownStart(const Http2FrameHeader& header) override {
+ DVLOG(1) << "OnUnknownStart: " << header;
+ if (IsOkToStartFrame(header)) {
+ if (header.type == kFrameTypeBlocked) {
+ visitor()->OnBlocked(header.stream_id);
+ }
+ }
+ }
+
+ void OnUnknownPayload(const char* data, size_t len) override {
+ DVLOG(1) << "OnUnknownPayload: len=" << len;
+ }
+
+ void OnUnknownEnd() override { DVLOG(1) << "OnUnknownEnd"; }
+
+ void OnPaddingTooLong(const Http2FrameHeader& header,
+ size_t missing_length) override {
+ DVLOG(1) << "OnPaddingTooLong: " << header
+ << "; missing_length: " << missing_length;
+ if (header.type == Http2FrameType::DATA) {
+ if (header.payload_length == 0) {
+ DCHECK_EQ(1u, missing_length);
+ SetSpdyErrorAndNotify(SpdyError::SPDY_INVALID_DATA_FRAME_FLAGS);
+ return;
+ }
+ visitor()->OnStreamPadding(header.stream_id, 1);
+ }
+ SetSpdyErrorAndNotify(SpdyError::SPDY_INVALID_PADDING);
+ }
+
+ void OnFrameSizeError(const Http2FrameHeader& header) override {
+ DVLOG(1) << "OnFrameSizeError: " << header;
+ size_t recv_limit = outer_framer_->recv_frame_size_limit();
+ if (header.payload_length > recv_limit) {
+ SetSpdyErrorAndNotify(SpdyError::SPDY_OVERSIZED_PAYLOAD);
+ return;
+ }
+ if (header.type != Http2FrameType::DATA &&
+ header.payload_length > recv_limit) {
+ SetSpdyErrorAndNotify(SpdyError::SPDY_CONTROL_PAYLOAD_TOO_LARGE);
+ return;
+ }
+ switch (header.type) {
+ case Http2FrameType::GOAWAY:
+ case Http2FrameType::ALTSVC:
+ SetSpdyErrorAndNotify(SpdyError::SPDY_INVALID_CONTROL_FRAME);
+ break;
+ default:
+ SetSpdyErrorAndNotify(SpdyError::SPDY_INVALID_CONTROL_FRAME_SIZE);
+ }
+ }
+
+ private:
+ // Decodes the input up to the next frame boundary (i.e. at most one frame),
+ // stopping early if an error is detected.
+ size_t ProcessInputFrame(const char* data, size_t len) {
+ DCHECK_NE(spdy_state_, SpdyState::SPDY_ERROR);
+ DecodeBuffer db(data, len);
+ DecodeStatus status = frame_decoder_->DecodeFrame(&db);
+ if (spdy_state_ != SpdyFramer::SPDY_ERROR) {
+ DetermineSpdyState(status);
+ } else {
+ VLOG(1) << "ProcessInputFrame spdy_error_="
+ << SpdyFramer::ErrorCodeToString(spdy_error_);
+ if (spdy_error_ == SpdyError::SPDY_INVALID_PADDING && has_frame_header_ &&
+ frame_type() != Http2FrameType::DATA) {
+ // spdy_framer_test checks that all of the available frame payload
+ // has been consumed, so do that.
+ size_t total = remaining_total_payload();
+ if (total <= frame_header().payload_length) {
+ size_t avail = db.MinLengthRemaining(total);
+ VLOG(1) << "Skipping past " << avail << " bytes, of " << total
+ << " total remaining in the frame's payload.";
+ db.AdvanceCursor(avail);
+ } else {
+ SPDY_BUG << "Total remaining (" << total
+ << ") should not be greater than the payload length; "
+ << frame_header();
+ }
+ }
+ }
+ return db.Offset();
+ }
+
+ // After decoding, determine the next SpdyState. Only called if the current
+ // state is NOT SpdyState::SPDY_ERROR (i.e. if none of the callback methods
+ // detected an error condition), because otherwise we assume that the callback
+ // method has set spdy_error_ appropriately.
+ void DetermineSpdyState(DecodeStatus status) {
+ DCHECK_EQ(spdy_error_, SpdyFramer::SPDY_NO_ERROR);
+ DCHECK(!HasError()) << spdy_error_;
+ switch (status) {
+ case DecodeStatus::kDecodeDone:
+ DVLOG(1) << "ProcessInputFrame -> DecodeStatus::kDecodeDone";
+ ResetBetweenFrames();
+ break;
+ case DecodeStatus::kDecodeInProgress:
+ DVLOG(1) << "ProcessInputFrame -> DecodeStatus::kDecodeInProgress";
+ if (decoded_frame_header_) {
+ if (IsDiscardingPayload()) {
+ set_spdy_state(SpdyState::SPDY_IGNORE_REMAINING_PAYLOAD);
+ } else if (has_frame_header_ &&
+ frame_type() == Http2FrameType::DATA) {
+ if (IsReadingPaddingLength()) {
+ set_spdy_state(SpdyState::SPDY_READ_DATA_FRAME_PADDING_LENGTH);
+ } else if (IsSkippingPadding()) {
+ set_spdy_state(SpdyState::SPDY_CONSUME_PADDING);
+ } else {
+ set_spdy_state(SpdyState::SPDY_FORWARD_STREAM_FRAME);
+ }
+ } else {
+ set_spdy_state(SpdyState::SPDY_CONTROL_FRAME_PAYLOAD);
+ }
+ } else {
+ set_spdy_state(SpdyState::SPDY_READING_COMMON_HEADER);
+ }
+ break;
+ case DecodeStatus::kDecodeError:
+ VLOG(1) << "ProcessInputFrame -> DecodeStatus::kDecodeError";
+ if (IsDiscardingPayload()) {
+ if (remaining_total_payload() == 0) {
+ // Push the Http2FrameDecoder out of state kDiscardPayload now
+ // since doing so requires no input.
+ DecodeBuffer tmp("", 0);
+ DecodeStatus status = frame_decoder_->DecodeFrame(&tmp);
+ if (status != DecodeStatus::kDecodeDone) {
+ SPDY_BUG << "Expected to be done decoding the frame, not "
+ << status;
+ SetSpdyErrorAndNotify(SpdyFramer::SPDY_INTERNAL_FRAMER_ERROR);
+ } else if (spdy_error_ != SpdyFramer::SPDY_NO_ERROR) {
+ SPDY_BUG << "Expected to have no error, not "
+ << SpdyFramer::ErrorCodeToString(spdy_error_);
+ } else {
+ ResetBetweenFrames();
+ }
+ } else {
+ set_spdy_state(SpdyState::SPDY_IGNORE_REMAINING_PAYLOAD);
+ }
+ } else {
+ SetSpdyErrorAndNotify(SpdyFramer::SPDY_INVALID_CONTROL_FRAME);
+ }
+ break;
+ }
+ }
+
+ void ResetBetweenFrames() {
+ CorruptFrameHeader(&frame_header_);
+ decoded_frame_header_ = false;
+ has_frame_header_ = false;
+ set_spdy_state(SpdyState::SPDY_READY_FOR_FRAME);
+ }
+
+ // ResetInternal is called from the constructor, and during tests, but not
+ // otherwise (i.e. not between every frame).
+ void ResetInternal() {
+ set_spdy_state(SpdyState::SPDY_READY_FOR_FRAME);
+ spdy_error_ = SpdyError::SPDY_NO_ERROR;
+
+ decoded_frame_header_ = false;
+ has_frame_header_ = false;
+ on_headers_called_ = false;
+ on_hpack_fragment_called_ = false;
+ latched_probable_http_response_ = false;
+ has_expected_frame_type_ = false;
+
+ CorruptFrameHeader(&frame_header_);
+ CorruptFrameHeader(&hpack_first_frame_header_);
+
+ frame_decoder_.reset(new Http2FrameDecoder(this));
+ }
+
+ void set_spdy_state(SpdyState v) {
+ DVLOG(2) << "set_spdy_state(" << SpdyFramer::StateToString(v) << ")";
+ spdy_state_ = v;
+ }
+
+ void SetSpdyErrorAndNotify(SpdyError error) {
+ if (HasError()) {
+ DCHECK_EQ(spdy_state_, SpdyState::SPDY_ERROR);
+ } else {
+ VLOG(2) << "SetSpdyErrorAndNotify("
+ << SpdyFramer::ErrorCodeToString(error) << ")";
+ DCHECK_NE(error, SpdyError::SPDY_NO_ERROR);
+ spdy_error_ = error;
+ set_spdy_state(SpdyState::SPDY_ERROR);
+ frame_decoder_->set_listener(&no_op_listener_);
+ visitor()->OnError(outer_framer_);
+ }
+ }
+
+ bool HasError() const {
+ if (spdy_state_ == SpdyState::SPDY_ERROR) {
+ DCHECK_NE(error_code(), SpdyError::SPDY_NO_ERROR);
+ return true;
+ } else {
+ DCHECK_EQ(error_code(), SpdyError::SPDY_NO_ERROR);
+ return false;
+ }
+ }
+
+ const Http2FrameHeader& frame_header() const {
+ DCHECK(has_frame_header_);
+ return frame_header_;
+ }
+
+ uint32_t stream_id() const { return frame_header().stream_id; }
+
+ Http2FrameType frame_type() const { return frame_header().type; }
+
+ size_t remaining_total_payload() const {
+ DCHECK(has_frame_header_);
+ size_t remaining = frame_decoder_->remaining_payload();
+ if (IsPaddable(frame_type()) && frame_header_.IsPadded()) {
+ remaining += frame_decoder_->remaining_padding();
+ }
+ return remaining;
+ }
+
+ bool IsReadingPaddingLength() {
+ bool result = frame_header_.IsPadded() && !opt_pad_length_;
+ DVLOG(2) << "Http2DecoderAdapter::IsReadingPaddingLength: " << result;
+ return result;
+ }
+ bool IsSkippingPadding() {
+ bool result = frame_header_.IsPadded() && opt_pad_length_ &&
+ frame_decoder_->remaining_payload() == 0 &&
+ frame_decoder_->remaining_padding() > 0;
+ DVLOG(2) << "Http2DecoderAdapter::IsSkippingPadding: " << result;
+ return result;
+ }
+ bool IsDiscardingPayload() {
+ bool result =
+ decoded_frame_header_ && frame_decoder_->IsDiscardingPayload();
+ DVLOG(2) << "Http2DecoderAdapter::IsDiscardingPayload: " << result;
+ return result;
+ }
+ // Called from OnXyz or OnXyzStart methods to decide whether it is OK to
+ // handle the callback.
+ bool IsOkToStartFrame(const Http2FrameHeader& header) {
+ DVLOG(3) << "IsOkToStartFrame";
+ if (HasError()) {
+ VLOG(2) << "HasError()";
+ return false;
+ }
+ DCHECK(!has_frame_header_);
+ if (has_expected_frame_type_ && header.type != expected_frame_type_) {
+ VLOG(1) << "Expected frame type " << expected_frame_type_ << ", not "
+ << header.type;
+ SetSpdyErrorAndNotify(SpdyError::SPDY_UNEXPECTED_FRAME);
+ return false;
+ }
+
+ return true;
+ }
+
+ bool HasRequiredStreamId(uint32_t stream_id) {
+ DVLOG(3) << "HasRequiredStreamId: " << stream_id;
+ if (HasError()) {
+ VLOG(2) << "HasError()";
+ return false;
+ }
+ if (stream_id != 0) {
+ return true;
+ }
+ VLOG(1) << "Stream Id is required, but zero provided";
+ SetSpdyErrorAndNotify(SpdyError::SPDY_INVALID_STREAM_ID);
+ return false;
+ }
+
+ bool HasRequiredStreamId(const Http2FrameHeader& header) {
+ return HasRequiredStreamId(header.stream_id);
+ }
+
+ bool HasRequiredStreamIdZero(uint32_t stream_id) {
+ DVLOG(3) << "HasRequiredStreamIdZero: " << stream_id;
+ if (HasError()) {
+ VLOG(2) << "HasError()";
+ return false;
+ }
+ if (stream_id == 0) {
+ return true;
+ }
+ VLOG(1) << "Stream Id was not zero, as required: " << stream_id;
+ SetSpdyErrorAndNotify(SpdyError::SPDY_INVALID_STREAM_ID);
+ return false;
+ }
+
+ bool HasRequiredStreamIdZero(const Http2FrameHeader& header) {
+ return HasRequiredStreamIdZero(header.stream_id);
+ }
+
+ void ReportReceiveCompressedFrame(const Http2FrameHeader& header) {
+ if (debug_visitor() != nullptr) {
+ size_t total = header.payload_length + Http2FrameHeader::EncodedSize();
+ debug_visitor()->OnReceiveCompressedFrame(
+ header.stream_id, ToSpdyFrameType(header.type), total);
+ }
+ }
+
+ HpackDecoderInterface* GetHpackDecoder() {
+ if (hpack_decoder_ == nullptr) {
+ hpack_decoder_ = outer_framer_->GetHpackDecoderForAdapter();
+ }
+ return hpack_decoder_;
+ }
+
+ void CommonStartHpackBlock() {
+ DVLOG(1) << "CommonStartHpackBlock";
+ DCHECK(!has_hpack_first_frame_header_);
+ if (!frame_header_.IsEndHeaders()) {
+ hpack_first_frame_header_ = frame_header_;
+ has_hpack_first_frame_header_ = true;
+ } else {
+ CorruptFrameHeader(&hpack_first_frame_header_);
+ }
+ on_hpack_fragment_called_ = false;
+ SpdyHeadersHandlerInterface* handler =
+ visitor()->OnHeaderFrameStart(stream_id());
+ if (handler == nullptr) {
+ SPDY_BUG << "visitor_->OnHeaderFrameStart returned nullptr";
+ SetSpdyErrorAndNotify(SpdyError::SPDY_INTERNAL_FRAMER_ERROR);
+ return;
+ }
+ GetHpackDecoder()->HandleControlFrameHeadersStart(handler);
+ }
+
+ // SpdyFramer calls HandleControlFrameHeadersData even if there are zero
+ // fragment bytes in the first frame, so do the same.
+ void MaybeAnnounceEmptyFirstHpackFragment() {
+ if (!on_hpack_fragment_called_) {
+ OnHpackFragment(nullptr, 0);
+ DCHECK(on_hpack_fragment_called_);
+ }
+ }
+
+ void CommonHpackFragmentEnd() {
+ DVLOG(1) << "CommonHpackFragmentEnd: stream_id=" << stream_id();
+ if (HasError()) {
+ VLOG(1) << "HasError(), returning";
+ return;
+ }
+ DCHECK(has_frame_header_);
+ MaybeAnnounceEmptyFirstHpackFragment();
+ if (frame_header_.IsEndHeaders()) {
+ DCHECK_EQ(has_hpack_first_frame_header_,
+ frame_type() == Http2FrameType::CONTINUATION)
+ << frame_header();
+ has_expected_frame_type_ = false;
+ if (GetHpackDecoder()->HandleControlFrameHeadersComplete(nullptr)) {
+ visitor()->OnHeaderFrameEnd(stream_id(), true);
+ } else {
+ SetSpdyErrorAndNotify(SpdyError::SPDY_DECOMPRESS_FAILURE);
+ return;
+ }
+ const Http2FrameHeader& first =
+ frame_type() == Http2FrameType::CONTINUATION
+ ? hpack_first_frame_header_
+ : frame_header_;
+ if (first.type == Http2FrameType::HEADERS && first.IsEndStream()) {
+ visitor()->OnStreamEnd(first.stream_id);
+ }
+ hpack_decoder_ = nullptr;
+ has_hpack_first_frame_header_ = false;
+ CorruptFrameHeader(&hpack_first_frame_header_);
+ } else {
+ DCHECK(has_hpack_first_frame_header_);
+ has_expected_frame_type_ = true;
+ expected_frame_type_ = Http2FrameType::CONTINUATION;
+ }
+ }
+
+ // The SpdyFramer that created this Http2FrameDecoderAdapter.
+ SpdyFramer* const outer_framer_;
+
+ // The HPACK decoder that we're using for the HPACK block that is currently
+ // being decoded. Cleared at the end of the block. Owned by the SpdyFramer.
+ HpackDecoderInterface* hpack_decoder_ = nullptr;
+
+ // The HTTP/2 frame decoder. Accessed via a unique_ptr to allow replacement
+ // (e.g. in tests) when Reset() is called.
+ std::unique_ptr<Http2FrameDecoder> frame_decoder_;
+
+ // The most recently decoded frame header; invalid after we reached the end
+ // of that frame.
+ Http2FrameHeader frame_header_;
+
+ // If decoding an HPACK block that is split across multiple frames, this holds
+ // the frame header of the HEADERS or PUSH_PROMISE that started the block.
+ Http2FrameHeader hpack_first_frame_header_;
+
+ // Amount of trailing padding. Currently used just as an indicator of whether
+ // OnPadLength has been called.
+ base::Optional<size_t> opt_pad_length_;
+
+ // Temporary buffers for the AltSvc fields.
+ string alt_svc_origin_;
+ string alt_svc_value_;
+
+ // Listener used if we transition to an error state; the listener ignores all
+ // the callbacks.
+ Http2FrameDecoderNoOpListener no_op_listener_;
+
+ // Next frame type expected. Currently only used for CONTINUATION frames,
+ // but could be used for detecting whether the first frame is a SETTINGS
+ // frame.
+ // TODO(jamessyng): Provide means to indicate that decoder should require
+ // SETTINGS frame as the first frame.
+ Http2FrameType expected_frame_type_;
+
+ // Attempt to duplicate the SpdyState and SpdyError values that SpdyFramer
+ // sets. Values determined by getting tests to pass.
+ SpdyState spdy_state_;
+ SpdyError spdy_error_;
+
+ // Has OnFrameHeader been called?
+ bool decoded_frame_header_ = false;
+
+ // Have we recorded an Http2FrameHeader for the current frame?
+ // We only do so if the decoder will make multiple callbacks for
+ // the frame; for example, for PING frames we don't make record
+ // the frame header, but for ALTSVC we do.
+ bool has_frame_header_ = false;
+
+ // Have we recorded an Http2FrameHeader for the current HPACK block?
+ // True only for multi-frame HPACK blocks.
+ bool has_hpack_first_frame_header_ = false;
+
+ // Has OnHeaders() already been called for current HEADERS block? Only
+ // meaningful between OnHeadersStart and OnHeadersPriority.
+ bool on_headers_called_;
+
+ // Has OnHpackFragment() already been called for current HPACK block?
+ // SpdyFramer will pass an empty buffer to the HPACK decoder if a HEADERS
+ // or PUSH_PROMISE has no HPACK data in it (e.g. a HEADERS frame with only
+ // padding). Detect that condition and replicate the behavior using this
+ // field.
+ bool on_hpack_fragment_called_;
+
+ // Have we seen a frame header that appears to be an HTTP/1 response?
+ bool latched_probable_http_response_ = false;
+
+ // Is expected_frame_type_ set?
+ bool has_expected_frame_type_ = false;
+};
+
+} // namespace
+
+std::unique_ptr<SpdyFramerDecoderAdapter> CreateHttp2FrameDecoderAdapter(
+ SpdyFramer* outer_framer) {
+ return std::unique_ptr<SpdyFramerDecoderAdapter>(
+ new Http2DecoderAdapter(outer_framer));
+}
+
+} // namespace net
diff --git a/chromium/net/spdy/http2_frame_decoder_adapter.h b/chromium/net/spdy/http2_frame_decoder_adapter.h
new file mode 100644
index 00000000000..bd1e19be92d
--- /dev/null
+++ b/chromium/net/spdy/http2_frame_decoder_adapter.h
@@ -0,0 +1,24 @@
+// Copyright 2016 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.
+
+#ifndef NET_SPDY_HTTP2_FRAME_DECODER_ADAPTER_H_
+#define NET_SPDY_HTTP2_FRAME_DECODER_ADAPTER_H_
+
+// Provides a SpdyFramerDecoderAdapter that uses Http2FrameDecoder for decoding
+// HTTP/2 frames. The adapter does not directly decode HPACK, but instead calls
+// SpdyFramer::GetHpackDecoderForAdapter() to get the decoder to be used.
+
+#include <memory>
+
+#include "net/spdy/spdy_framer.h"
+#include "net/spdy/spdy_framer_decoder_adapter.h"
+
+namespace net {
+
+std::unique_ptr<SpdyFramerDecoderAdapter> CreateHttp2FrameDecoderAdapter(
+ SpdyFramer* outer_framer);
+
+} // namespace net
+
+#endif // NET_SPDY_HTTP2_FRAME_DECODER_ADAPTER_H_
diff --git a/chromium/net/spdy/http2_priority_dependencies.cc b/chromium/net/spdy/http2_priority_dependencies.cc
index a09ef1d08ae..9cbfba07c15 100644
--- a/chromium/net/spdy/http2_priority_dependencies.cc
+++ b/chromium/net/spdy/http2_priority_dependencies.cc
@@ -10,7 +10,7 @@ Http2PriorityDependencies::Http2PriorityDependencies() {}
Http2PriorityDependencies::~Http2PriorityDependencies() {}
-void Http2PriorityDependencies::OnStreamSynSent(
+void Http2PriorityDependencies::OnStreamCreation(
SpdyStreamId id,
SpdyPriority priority,
SpdyStreamId* dependent_stream_id,
@@ -20,28 +20,137 @@ void Http2PriorityDependencies::OnStreamSynSent(
*dependent_stream_id = 0ul;
*exclusive = true;
- // Find the next highest entry in total order.
+ // Dependent on the lowest-priority stream that has a priority >= |priority|.
+ IdList::iterator parent;
+ if (PriorityLowerBound(priority, &parent)) {
+ *dependent_stream_id = parent->first;
+ }
+
+ id_priority_lists_[priority].push_back(std::make_pair(id, priority));
+ IdList::iterator it = id_priority_lists_[priority].end();
+ --it;
+ entry_by_stream_id_[id] = it;
+}
+
+bool Http2PriorityDependencies::PriorityLowerBound(SpdyPriority priority,
+ IdList::iterator* bound) {
for (int i = priority; i >= kV3HighestPriority; --i) {
if (!id_priority_lists_[i].empty()) {
- *dependent_stream_id = id_priority_lists_[i].back().first;
- break;
+ *bound = id_priority_lists_[i].end();
+ --(*bound);
+ return true;
}
}
+ return false;
+}
- id_priority_lists_[priority].push_back(std::make_pair(id, priority));
- IdList::iterator it = id_priority_lists_[priority].end();
+bool Http2PriorityDependencies::ParentOfStream(SpdyStreamId id,
+ IdList::iterator* parent) {
+ EntryMap::iterator entry = entry_by_stream_id_.find(id);
+ DCHECK(entry != entry_by_stream_id_.end());
+
+ SpdyPriority priority = entry->second->second;
+ IdList::iterator curr = entry->second;
+ if (curr != id_priority_lists_[priority].begin()) {
+ *parent = curr;
+ --(*parent);
+ return true;
+ }
+
+ // |id| is at the head of its priority list, so its parent is the last
+ // entry of the next-highest priority band.
+ if (priority == kV3HighestPriority) {
+ return false;
+ }
+ return PriorityLowerBound(priority - 1, parent);
+}
+
+bool Http2PriorityDependencies::ChildOfStream(SpdyStreamId id,
+ IdList::iterator* child) {
+ EntryMap::iterator entry = entry_by_stream_id_.find(id);
+ DCHECK(entry != entry_by_stream_id_.end());
+
+ SpdyPriority priority = entry->second->second;
+ *child = entry->second;
+ ++(*child);
+ if (*child != id_priority_lists_[priority].end()) {
+ return true;
+ }
+
+ // |id| is at the end of its priority list, so its child is the stream
+ // at the front of the next-lowest priority band.
+ for (int i = priority + 1; i <= kV3LowestPriority; ++i) {
+ if (!id_priority_lists_[i].empty()) {
+ *child = id_priority_lists_[i].begin();
+ return true;
+ }
+ }
+
+ return false;
+}
+
+std::vector<Http2PriorityDependencies::DependencyUpdate>
+Http2PriorityDependencies::OnStreamUpdate(SpdyStreamId id,
+ SpdyPriority new_priority) {
+ std::vector<DependencyUpdate> result;
+ result.reserve(2);
+
+ EntryMap::iterator curr_entry = entry_by_stream_id_.find(id);
+ SpdyPriority old_priority = curr_entry->second->second;
+ if (old_priority == new_priority) {
+ return result;
+ }
+
+ IdList::iterator old_parent;
+ bool old_has_parent = ParentOfStream(id, &old_parent);
+
+ IdList::iterator new_parent;
+ bool new_has_parent = PriorityLowerBound(new_priority, &new_parent);
+
+ // If we move |id| from MEDIUM to LOW, where HIGH = {other_id}, MEDIUM = {id},
+ // and LOW = {}, then PriorityLowerBound(new_priority) is |id|. In this corner
+ // case, |id| does not change parents.
+ if (new_has_parent && new_parent->first == id) {
+ new_has_parent = old_has_parent;
+ new_parent = old_parent;
+ }
+
+ // If the parent has changed, we generate dependency updates.
+ if ((old_has_parent != new_has_parent) ||
+ (old_has_parent && old_parent->first != new_parent->first)) {
+ // If |id| has a child, then that child moves to be dependent on
+ // |old_parent|.
+ IdList::iterator old_child;
+ if (ChildOfStream(id, &old_child)) {
+ if (old_has_parent) {
+ result.push_back({old_child->first, old_parent->first, true});
+ } else {
+ result.push_back({old_child->first, 0, true});
+ }
+ }
+
+ // |id| moves to be dependent on |new_parent|.
+ if (new_has_parent) {
+ result.push_back({id, new_parent->first, true});
+ } else {
+ result.push_back({id, 0, true});
+ }
+ }
+
+ // Move to the new priority.
+ EntryMap::iterator old = entry_by_stream_id_.find(id);
+ id_priority_lists_[old->second->second].erase(old->second);
+ id_priority_lists_[new_priority].push_back(std::make_pair(id, new_priority));
+ IdList::iterator it = id_priority_lists_[new_priority].end();
--it;
entry_by_stream_id_[id] = it;
+
+ return result;
}
void Http2PriorityDependencies::OnStreamDestruction(SpdyStreamId id) {
EntryMap::iterator emit = entry_by_stream_id_.find(id);
-
- // This routine may be called without a matching call to
- // OnStreamSynSent above, in the case of server push. In that case,
- // it's a no-op.
- if (emit == entry_by_stream_id_.end())
- return;
+ DCHECK(emit != entry_by_stream_id_.end());
IdList::iterator it = emit->second;
id_priority_lists_[it->second].erase(it);
diff --git a/chromium/net/spdy/http2_priority_dependencies.h b/chromium/net/spdy/http2_priority_dependencies.h
index fbf099c55aa..d356a79586a 100644
--- a/chromium/net/spdy/http2_priority_dependencies.h
+++ b/chromium/net/spdy/http2_priority_dependencies.h
@@ -2,8 +2,8 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#ifndef NET_HTTP2_PRIORITY_DEPENDENCIES_H_
-#define NET_HTTP2_PRIORITY_DEPENDENCIES_H_
+#ifndef NET_SPDY_HTTP2_PRIORITY_DEPENDENCIES_H_
+#define NET_SPDY_HTTP2_PRIORITY_DEPENDENCIES_H_
#include <list>
#include <map>
@@ -21,21 +21,32 @@ class NET_EXPORT_PRIVATE Http2PriorityDependencies {
Http2PriorityDependencies();
~Http2PriorityDependencies();
- // Called when a stream SYN is sent to the server. Note that in the
- // case of server push, a stream may be created without this routine
- // being called. In such cases, the client ignores the stream's priority
- // (as the server is effectively overriding the client's notions of
- // priority anyway).
+ // Called when a stream is created. This is used for both client-initiated
+ // and server-initiated (pushed) streams.
// On return, |*dependent_stream_id| is set to the stream id that
// this stream should be made dependent on, and |*exclusive| set to
// whether that dependency should be exclusive.
- void OnStreamSynSent(SpdyStreamId id,
- SpdyPriority priority,
- SpdyStreamId* dependent_stream_id,
- bool* exclusive);
+ void OnStreamCreation(SpdyStreamId id,
+ SpdyPriority priority,
+ SpdyStreamId* dependent_stream_id,
+ bool* exclusive);
+ // Called when a stream is destroyed.
void OnStreamDestruction(SpdyStreamId id);
+ struct DependencyUpdate {
+ SpdyStreamId id;
+ SpdyStreamId dependent_stream_id;
+ bool exclusive;
+ };
+
+ // Called when a stream's priority has changed. Returns a list of
+ // dependency updates that should be sent to the server to describe
+ // the requested priority change. The updates should be sent in the
+ // given order.
+ std::vector<DependencyUpdate> OnStreamUpdate(SpdyStreamId id,
+ SpdyPriority new_priority);
+
private:
// The requirements for the internal data structure for this class are:
// a) Constant time insertion of entries at the end of the list,
@@ -54,8 +65,23 @@ class NET_EXPORT_PRIVATE Http2PriorityDependencies {
// Iterators to list elements remain valid until those particular elements
// are erased.
EntryMap entry_by_stream_id_;
+
+ // Finds the lowest-priority stream that has a priority >= |priority|.
+ // Returns false if there are no such streams.
+ // Otherwise, returns true and sets |*bound|.
+ bool PriorityLowerBound(SpdyPriority priority, IdList::iterator* bound);
+
+ // Finds the stream just above |id| in the total order.
+ // Returns false if there are no streams with a higher priority.
+ // Otherwise, returns true and sets |*parent|.
+ bool ParentOfStream(SpdyStreamId id, IdList::iterator* parent);
+
+ // Finds the stream just below |id| in the total order.
+ // Returns false if there are no streams with a lower priority.
+ // Otherwise, returns true and sets |*child|.
+ bool ChildOfStream(SpdyStreamId id, IdList::iterator* child);
};
} // namespace net
-#endif // NET_HTTP2_PRIORITY_DEPENDENCIES_H_
+#endif // NET_SPDY_HTTP2_PRIORITY_DEPENDENCIES_H_
diff --git a/chromium/net/spdy/http2_priority_dependencies_unittest.cc b/chromium/net/spdy/http2_priority_dependencies_unittest.cc
index 05c482bbfc5..73d1f7d7f74 100644
--- a/chromium/net/spdy/http2_priority_dependencies_unittest.cc
+++ b/chromium/net/spdy/http2_priority_dependencies_unittest.cc
@@ -4,16 +4,42 @@
#include "net/spdy/http2_priority_dependencies.h"
+#include <algorithm>
+
+#include "testing/gmock/include/gmock/gmock.h"
#include "testing/platform_test.h"
+using ::testing::ContainerEq;
+
namespace net {
+bool operator==(const Http2PriorityDependencies::DependencyUpdate& a,
+ const Http2PriorityDependencies::DependencyUpdate& b) {
+ return a.id == b.id && a.dependent_stream_id == b.dependent_stream_id &&
+ a.exclusive == b.exclusive;
+}
+
+std::ostream& operator<<(
+ std::ostream& os,
+ const std::vector<Http2PriorityDependencies::DependencyUpdate>& v) {
+ for (auto e : v) {
+ os << "{" << e.id << "," << e.dependent_stream_id << ","
+ << (e.exclusive ? "true" : "false") << "}";
+ }
+ return os;
+}
+
class HttpPriorityDependencyTest : public PlatformTest {
public:
HttpPriorityDependencyTest() : next_id_(0u) {}
// Fixed priority values to use for testing.
- enum { HIGHEST = 0, MEDIUM = 2, LOW = 4, LOWEST = 5 };
+ enum {
+ HIGHEST = kV3HighestPriority,
+ MEDIUM = HIGHEST + 1,
+ LOW = MEDIUM + 1,
+ LOWEST = kV3LowestPriority,
+ };
SpdyStreamId GetId() { return ++next_id_; }
@@ -22,25 +48,48 @@ class HttpPriorityDependencyTest : public PlatformTest {
SpdyStreamId expected_dependent_id) {
SpdyStreamId dependent_id = 999u;
bool exclusive = false;
- dependency_state.OnStreamSynSent(new_id, priority, &dependent_id,
- &exclusive);
- EXPECT_EQ(expected_dependent_id, dependent_id);
- EXPECT_TRUE(exclusive);
+ dependency_state_.OnStreamCreation(new_id, priority, &dependent_id,
+ &exclusive);
+ if (expected_dependent_id != dependent_id || !exclusive) {
+ ADD_FAILURE() << "OnStreamCreation(" << new_id << ", " << int(priority)
+ << ")\n"
+ << " Got: (" << dependent_id << ", " << exclusive << ")\n"
+ << " Want: (" << expected_dependent_id << ", true)\n";
+ }
+ }
+
+ struct ExpectedDependencyUpdate {
+ SpdyStreamId id;
+ SpdyStreamId parent_id;
+ };
+
+ void TestStreamUpdate(SpdyStreamId id,
+ SpdyPriority new_priority,
+ std::vector<ExpectedDependencyUpdate> expected) {
+ auto value = dependency_state_.OnStreamUpdate(id, new_priority);
+ std::vector<Http2PriorityDependencies::DependencyUpdate> expected_value;
+ for (auto e : expected) {
+ expected_value.push_back({e.id, e.parent_id, true /* exclusive */});
+ }
+ if (value != expected_value) {
+ ADD_FAILURE() << "OnStreamUpdate(" << id << ", " << int(new_priority)
+ << ")\n"
+ << " Value: " << value << "\n"
+ << " Expected: " << expected_value << "\n";
+ }
}
void OnStreamDestruction(SpdyStreamId id) {
- dependency_state.OnStreamDestruction(id);
+ dependency_state_.OnStreamDestruction(id);
}
private:
SpdyStreamId next_id_;
- Http2PriorityDependencies dependency_state;
+ Http2PriorityDependencies dependency_state_;
};
// Confirm dependencies correct for entries at the same priority.
TEST_F(HttpPriorityDependencyTest, SamePriority) {
- Http2PriorityDependencies dependency_state;
-
const SpdyStreamId first_id = GetId();
const SpdyStreamId second_id = GetId();
const SpdyStreamId third_id = GetId();
@@ -52,8 +101,6 @@ TEST_F(HttpPriorityDependencyTest, SamePriority) {
// Confirm dependencies correct for entries at different priorities, increasing.
TEST_F(HttpPriorityDependencyTest, DifferentPriorityIncreasing) {
- Http2PriorityDependencies dependency_state;
-
const SpdyStreamId first_id = GetId();
const SpdyStreamId second_id = GetId();
const SpdyStreamId third_id = GetId();
@@ -65,8 +112,6 @@ TEST_F(HttpPriorityDependencyTest, DifferentPriorityIncreasing) {
// Confirm dependencies correct for entries at different priorities, increasing.
TEST_F(HttpPriorityDependencyTest, DifferentPriorityDecreasing) {
- Http2PriorityDependencies dependency_state;
-
const SpdyStreamId first_id = GetId();
const SpdyStreamId second_id = GetId();
const SpdyStreamId third_id = GetId();
@@ -79,8 +124,6 @@ TEST_F(HttpPriorityDependencyTest, DifferentPriorityDecreasing) {
// Confirm dependencies correct if requests are completed between before
// next creation.
TEST_F(HttpPriorityDependencyTest, CompletionBeforeIssue) {
- Http2PriorityDependencies dependency_state;
-
const SpdyStreamId first_id = GetId();
const SpdyStreamId second_id = GetId();
const SpdyStreamId third_id = GetId();
@@ -95,8 +138,6 @@ TEST_F(HttpPriorityDependencyTest, CompletionBeforeIssue) {
// Confirm dependencies correct if some requests are completed between before
// next creation.
TEST_F(HttpPriorityDependencyTest, SomeCompletions) {
- Http2PriorityDependencies dependency_state;
-
const SpdyStreamId first_id = GetId();
const SpdyStreamId second_id = GetId();
const SpdyStreamId third_id = GetId();
@@ -109,8 +150,6 @@ TEST_F(HttpPriorityDependencyTest, SomeCompletions) {
// A more complex example parallel to a simple web page.
TEST_F(HttpPriorityDependencyTest, Complex) {
- Http2PriorityDependencies dependency_state;
-
const SpdyStreamId first_id = GetId();
const SpdyStreamId second_id = GetId();
const SpdyStreamId third_id = GetId();
@@ -141,4 +180,81 @@ TEST_F(HttpPriorityDependencyTest, Complex) {
TestStreamCreation(tenth_id, HIGHEST, 0u);
}
+// Confirm dependencies correct after updates with just one stream.
+// All updates are no-ops.
+TEST_F(HttpPriorityDependencyTest, UpdateSingleStream) {
+ const SpdyStreamId id = GetId();
+
+ TestStreamCreation(id, HIGHEST, 0);
+
+ std::vector<ExpectedDependencyUpdate> empty;
+ TestStreamUpdate(id, HIGHEST, empty);
+ TestStreamUpdate(id, MEDIUM, empty);
+ TestStreamUpdate(id, LOWEST, empty);
+ TestStreamUpdate(id, HIGHEST, empty);
+}
+
+// Confirm dependencies correct after updates with three streams.
+TEST_F(HttpPriorityDependencyTest, UpdateThreeStreams) {
+ const SpdyStreamId first_id = GetId();
+ const SpdyStreamId second_id = GetId();
+ const SpdyStreamId third_id = GetId();
+
+ TestStreamCreation(first_id, HIGHEST, 0);
+ TestStreamCreation(second_id, MEDIUM, first_id);
+ TestStreamCreation(third_id, LOWEST, second_id);
+
+ std::vector<ExpectedDependencyUpdate> empty;
+
+ // no-op: still at top.
+ TestStreamUpdate(first_id, HIGHEST, empty);
+
+ // no-op: still below first.
+ TestStreamUpdate(second_id, MEDIUM, empty);
+
+ // no-op: still below second.
+ TestStreamUpdate(third_id, LOWEST, empty);
+
+ // second moves to top, first moves below second.
+ TestStreamUpdate(first_id, MEDIUM, {{second_id, 0}, {first_id, second_id}});
+
+ // third moves to top.
+ TestStreamUpdate(third_id, HIGHEST, {{third_id, 0}});
+
+ // third moves to bottom.
+ TestStreamUpdate(third_id, LOWEST, {{second_id, 0}, {third_id, first_id}});
+
+ // first moves to top.
+ TestStreamUpdate(first_id, HIGHEST, {{third_id, second_id}, {first_id, 0}});
+}
+
+// A more complex example parallel to a simple web page with pushed responses.
+TEST_F(HttpPriorityDependencyTest, UpdateComplex) {
+ const SpdyStreamId first_id = GetId();
+ const SpdyStreamId second_id = GetId(); // pushed
+ const SpdyStreamId third_id = GetId(); // pushed
+ const SpdyStreamId fourth_id = GetId();
+ const SpdyStreamId fifth_id = GetId();
+ const SpdyStreamId sixth_id = GetId();
+ const SpdyStreamId seventh_id = GetId();
+
+ TestStreamCreation(first_id, HIGHEST, 0u);
+ TestStreamCreation(second_id, LOWEST, first_id);
+ TestStreamCreation(third_id, LOWEST, second_id);
+ TestStreamCreation(fourth_id, HIGHEST, first_id);
+ TestStreamCreation(fifth_id, MEDIUM, fourth_id);
+ TestStreamCreation(sixth_id, MEDIUM, fifth_id);
+ TestStreamCreation(seventh_id, LOW, sixth_id);
+
+ // second matches a HIGHEST priority response.
+ // 3 moves under 7
+ // 2 moves under 4
+ TestStreamUpdate(second_id, HIGHEST,
+ {{third_id, seventh_id}, {second_id, fourth_id}});
+
+ // third matches a MEDIUM priority response.
+ // 3 moves under 6
+ TestStreamUpdate(third_id, MEDIUM, {{third_id, sixth_id}});
+}
+
} // namespace net
diff --git a/chromium/net/spdy/http2_write_scheduler.h b/chromium/net/spdy/http2_write_scheduler.h
index 3622b0e0a59..741169edb50 100644
--- a/chromium/net/spdy/http2_write_scheduler.h
+++ b/chromium/net/spdy/http2_write_scheduler.h
@@ -24,6 +24,7 @@
#include "base/logging.h"
#include "base/macros.h"
#include "base/memory/ptr_util.h"
+#include "base/stl_util.h"
#include "net/spdy/spdy_bug_tracker.h"
#include "net/spdy/spdy_protocol.h"
#include "net/spdy/write_scheduler.h"
diff --git a/chromium/net/spdy/mock_spdy_framer_visitor.h b/chromium/net/spdy/mock_spdy_framer_visitor.h
index 408b83203e3..4f48ed0de35 100644
--- a/chromium/net/spdy/mock_spdy_framer_visitor.h
+++ b/chromium/net/spdy/mock_spdy_framer_visitor.h
@@ -34,17 +34,10 @@ class MockSpdyFramerVisitor : public SpdyFramerVisitorInterface {
MOCK_METHOD1(OnHeaderFrameStart,
SpdyHeadersHandlerInterface*(SpdyStreamId stream_id));
MOCK_METHOD2(OnHeaderFrameEnd, void(SpdyStreamId stream_id, bool end));
- MOCK_METHOD5(OnSynStream, void(SpdyStreamId stream_id,
- SpdyStreamId associated_stream_id,
- SpdyPriority priority,
- bool fin,
- bool unidirectional));
- MOCK_METHOD2(OnSynReply, void(SpdyStreamId stream_id, bool fin));
MOCK_METHOD2(OnRstStream, void(SpdyStreamId stream_id,
SpdyRstStreamStatus status));
MOCK_METHOD1(OnSettings, void(bool clear_persisted));
- MOCK_METHOD3(OnSetting,
- void(SpdySettingsIds id, uint8_t flags, uint32_t value));
+ MOCK_METHOD2(OnSetting, void(SpdySettingsIds id, uint32_t value));
MOCK_METHOD2(OnPing, void(SpdyPingId unique_id, bool is_ack));
MOCK_METHOD0(OnSettingsEnd, void());
MOCK_METHOD2(OnGoAway, void(SpdyStreamId last_accepted_stream_id,
diff --git a/chromium/net/spdy/multiplexed_http_stream.cc b/chromium/net/spdy/multiplexed_http_stream.cc
new file mode 100644
index 00000000000..ad5a723ab48
--- /dev/null
+++ b/chromium/net/spdy/multiplexed_http_stream.cc
@@ -0,0 +1,59 @@
+// Copyright 2016 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.
+
+#include "net/spdy/multiplexed_http_stream.h"
+
+#include "base/logging.h"
+
+namespace net {
+
+MultiplexedHttpStream::MultiplexedHttpStream(MultiplexedSessionHandle session)
+ : session_(session) {}
+
+MultiplexedHttpStream::~MultiplexedHttpStream() {}
+
+bool MultiplexedHttpStream::GetRemoteEndpoint(IPEndPoint* endpoint) {
+ return session_.GetRemoteEndpoint(endpoint);
+}
+
+void MultiplexedHttpStream::GetSSLInfo(SSLInfo* ssl_info) {
+ session_.GetSSLInfo(ssl_info);
+}
+
+void MultiplexedHttpStream::SaveSSLInfo() {
+ session_.SaveSSLInfo();
+}
+
+void MultiplexedHttpStream::GetSSLCertRequestInfo(
+ SSLCertRequestInfo* cert_request_info) {
+ // A multiplexed stream cannot request client certificates. Client
+ // authentication may only occur during the initial SSL handshake.
+ NOTREACHED();
+}
+
+Error MultiplexedHttpStream::GetTokenBindingSignature(
+ crypto::ECPrivateKey* key,
+ TokenBindingType tb_type,
+ std::vector<uint8_t>* out) {
+ return session_.GetTokenBindingSignature(key, tb_type, out);
+}
+
+void MultiplexedHttpStream::Drain(HttpNetworkSession* session) {
+ NOTREACHED();
+ Close(false);
+ delete this;
+}
+
+HttpStream* MultiplexedHttpStream::RenewStreamForAuth() {
+ return nullptr;
+}
+
+void MultiplexedHttpStream::SetConnectionReused() {}
+
+bool MultiplexedHttpStream::CanReuseConnection() const {
+ // Multiplexed streams aren't considered reusable.
+ return false;
+}
+
+} // namespace net
diff --git a/chromium/net/spdy/multiplexed_http_stream.h b/chromium/net/spdy/multiplexed_http_stream.h
new file mode 100644
index 00000000000..1fe4a2a5eb5
--- /dev/null
+++ b/chromium/net/spdy/multiplexed_http_stream.h
@@ -0,0 +1,39 @@
+// Copyright 2016 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.
+
+#ifndef NET_SPDY_MULTIPLEXED_HTTP_STREAM_H_
+#define NET_SPDY_MULTIPLEXED_HTTP_STREAM_H_
+
+#include "net/http/http_stream.h"
+#include "net/spdy/multiplexed_session.h"
+
+namespace net {
+
+// Base class for SPDY and QUIC HttpStream subclasses.
+class NET_EXPORT_PRIVATE MultiplexedHttpStream : public HttpStream {
+ public:
+ explicit MultiplexedHttpStream(MultiplexedSessionHandle session);
+ ~MultiplexedHttpStream() override;
+
+ bool GetRemoteEndpoint(IPEndPoint* endpoint) override;
+ void GetSSLInfo(SSLInfo* ssl_info) override;
+ void GetSSLCertRequestInfo(SSLCertRequestInfo* cert_request_info) override;
+ Error GetTokenBindingSignature(crypto::ECPrivateKey* key,
+ TokenBindingType tb_type,
+ std::vector<uint8_t>* out) override;
+ void Drain(HttpNetworkSession* session) override;
+ HttpStream* RenewStreamForAuth() override;
+ void SetConnectionReused() override;
+ bool CanReuseConnection() const override;
+
+ // Caches SSL info from the underlying session.
+ void SaveSSLInfo();
+
+ private:
+ MultiplexedSessionHandle session_;
+};
+
+} // namespace net
+
+#endif // NET_SPDY_MULTIPLEXED_HTTP_STREAM_H_
diff --git a/chromium/net/spdy/multiplexed_session.cc b/chromium/net/spdy/multiplexed_session.cc
new file mode 100644
index 00000000000..2fc70546531
--- /dev/null
+++ b/chromium/net/spdy/multiplexed_session.cc
@@ -0,0 +1,51 @@
+// Copyright 2016 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.
+
+#include "net/spdy/multiplexed_session.h"
+
+namespace net {
+
+MultiplexedSessionHandle::MultiplexedSessionHandle(
+ base::WeakPtr<MultiplexedSession> session)
+ : session_(session) {
+ SaveSSLInfo();
+}
+
+MultiplexedSessionHandle::MultiplexedSessionHandle(
+ const MultiplexedSessionHandle& other) = default;
+
+MultiplexedSessionHandle::MultiplexedSessionHandle(
+ MultiplexedSessionHandle&& other) = default;
+
+MultiplexedSessionHandle::~MultiplexedSessionHandle() {}
+
+bool MultiplexedSessionHandle::GetRemoteEndpoint(IPEndPoint* endpoint) {
+ if (!session_)
+ return false;
+
+ return session_->GetRemoteEndpoint(endpoint);
+}
+
+bool MultiplexedSessionHandle::GetSSLInfo(SSLInfo* ssl_info) const {
+ if (!has_ssl_info_)
+ return false;
+
+ *ssl_info = ssl_info_;
+ return true;
+}
+
+void MultiplexedSessionHandle::SaveSSLInfo() {
+ has_ssl_info_ = session_->GetSSLInfo(&ssl_info_);
+}
+
+Error MultiplexedSessionHandle::GetTokenBindingSignature(
+ crypto::ECPrivateKey* key,
+ TokenBindingType tb_type,
+ std::vector<uint8_t>* out) {
+ if (!session_)
+ return ERR_CONNECTION_CLOSED;
+ return session_->GetTokenBindingSignature(key, tb_type, out);
+}
+
+} // namespace net
diff --git a/chromium/net/spdy/multiplexed_session.h b/chromium/net/spdy/multiplexed_session.h
new file mode 100644
index 00000000000..ce37a477e87
--- /dev/null
+++ b/chromium/net/spdy/multiplexed_session.h
@@ -0,0 +1,78 @@
+// Copyright 2016 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.
+
+#ifndef NET_SPDY_MULTIPLEXED_SESSION_H_
+#define NET_SPDY_MULTIPLEXED_SESSION_H_
+
+#include <vector>
+
+#include "net/base/ip_endpoint.h"
+#include "net/base/net_errors.h"
+#include "net/http/http_stream.h"
+#include "net/ssl/ssl_info.h"
+#include "net/ssl/token_binding.h"
+
+namespace crypto {
+class ECPrivateKey;
+} // namespace crypto
+
+namespace net {
+
+// Base class for SPDY and QUIC sessions.
+class NET_EXPORT_PRIVATE MultiplexedSession {
+ public:
+ virtual ~MultiplexedSession() {}
+
+ // Fills SSL info in |ssl_info| and returns true when SSL is in use.
+ virtual bool GetSSLInfo(SSLInfo* ssl_info) const = 0;
+
+ // Gets the remote endpoint of the socket that the HTTP stream is using, if
+ // any. Returns true and fills in |endpoint| if it is available; returns false
+ // and does not modify |endpoint| if it is unavailable.
+ virtual bool GetRemoteEndpoint(IPEndPoint* endpoint) = 0;
+
+ // Generates the signature used in Token Binding using key |*key| and for a
+ // Token Binding of type |tb_type|, putting the signature in |*out|. Returns a
+ // net error code.
+ virtual Error GetTokenBindingSignature(crypto::ECPrivateKey* key,
+ TokenBindingType tb_type,
+ std::vector<uint8_t>* out) = 0;
+};
+
+// A handle to a multiplexed session which will be valid even after the
+// underlying session is deleted.
+class NET_EXPORT_PRIVATE MultiplexedSessionHandle {
+ public:
+ explicit MultiplexedSessionHandle(base::WeakPtr<MultiplexedSession> session);
+ MultiplexedSessionHandle(const MultiplexedSessionHandle& other);
+ MultiplexedSessionHandle(MultiplexedSessionHandle&& other);
+ ~MultiplexedSessionHandle();
+
+ // Gets the remote endpoint of the socket that the HTTP stream is using, if
+ // any. Returns true and fills in |endpoint| if it is available; returns false
+ // and does not modify |endpoint| if it is unavailable.
+ bool GetRemoteEndpoint(IPEndPoint* endpoint);
+
+ // Fills SSL info in |ssl_info| and returns true when SSL is in use.
+ bool GetSSLInfo(SSLInfo* ssl_info) const;
+
+ // Caches SSL info from the underlying session.
+ void SaveSSLInfo();
+
+ // Generates the signature used in Token Binding using key |*key| and for a
+ // Token Binding of type |tb_type|, putting the signature in |*out|. Returns a
+ // net error code.
+ Error GetTokenBindingSignature(crypto::ECPrivateKey* key,
+ TokenBindingType tb_type,
+ std::vector<uint8_t>* out);
+
+ private:
+ base::WeakPtr<MultiplexedSession> session_;
+ SSLInfo ssl_info_;
+ bool has_ssl_info_;
+};
+
+} // namespace net
+
+#endif // NET_SPDY_MULTIPLEXED_SESSION_H_
diff --git a/chromium/net/spdy/server_push_delegate.h b/chromium/net/spdy/server_push_delegate.h
index 52e52946243..7e9c3db84ed 100644
--- a/chromium/net/spdy/server_push_delegate.h
+++ b/chromium/net/spdy/server_push_delegate.h
@@ -34,4 +34,4 @@ class NET_EXPORT_PRIVATE ServerPushDelegate {
} // namespace net
-#endif // NET_SPDY_PUSH_DELEGATE_H_
+#endif // NET_SPDY_SERVER_PUSH_DELEGATE_H_
diff --git a/chromium/net/spdy/spdy_alt_svc_wire_format.cc b/chromium/net/spdy/spdy_alt_svc_wire_format.cc
index e94b4fa7195..df4e84dded5 100644
--- a/chromium/net/spdy/spdy_alt_svc_wire_format.cc
+++ b/chromium/net/spdy/spdy_alt_svc_wire_format.cc
@@ -9,6 +9,7 @@
#include <string>
#include "base/logging.h"
+#include "base/strings/string_util.h"
#include "base/strings/stringprintf.h"
namespace net {
@@ -22,7 +23,8 @@ bool ParsePositiveIntegerImpl(StringPiece::const_iterator c,
StringPiece::const_iterator end,
T* value) {
*value = 0;
- for (; c != end && isdigit(*c); ++c) {
+ // TODO(mmenke): This really should be using methods in parse_number.h.
+ for (; c != end && '0' <= *c && *c <= '9'; ++c) {
if (*value > std::numeric_limits<T>::max() / 10) {
return false;
}
@@ -277,22 +279,20 @@ bool SpdyAltSvcWireFormat::PercentDecode(StringPiece::const_iterator c,
}
DCHECK_EQ('%', *c);
++c;
- if (c == end || !isxdigit(*c)) {
+ if (c == end || !base::IsHexDigit(*c)) {
return false;
}
- char decoded = tolower(*c);
- // '0' is 0, 'a' is 10.
- decoded += isdigit(*c) ? (0 - '0') : (10 - 'a');
// Network byte order is big-endian.
- decoded <<= 4;
+ int decoded = base::HexDigitToInt(*c) << 4;
+
++c;
- if (c == end || !isxdigit(*c)) {
+ if (c == end || !base::IsHexDigit(*c)) {
return false;
}
- decoded += tolower(*c);
- // '0' is 0, 'a' is 10.
- decoded += isdigit(*c) ? (0 - '0') : (10 - 'a');
- output->push_back(decoded);
+ // Network byte order is big-endian.
+ decoded += base::HexDigitToInt(*c);
+
+ output->push_back(static_cast<char>(decoded));
}
return true;
}
diff --git a/chromium/net/spdy/spdy_deframer_visitor.cc b/chromium/net/spdy/spdy_deframer_visitor.cc
index 5b8535bd343..15ff32c5866 100644
--- a/chromium/net/spdy/spdy_deframer_visitor.cc
+++ b/chromium/net/spdy/spdy_deframer_visitor.cc
@@ -169,7 +169,7 @@ class SpdyTestDeframerImpl : public SpdyTestDeframer,
bool end) override;
void OnRstStream(SpdyStreamId stream_id, SpdyRstStreamStatus status) override;
bool OnRstStreamFrameData(const char* rst_stream_data, size_t len) override;
- void OnSetting(SpdySettingsIds id, uint8_t flags, uint32_t value) override;
+ void OnSetting(SpdySettingsIds id, uint32_t value) override;
void OnSettings(bool clear_persisted) override;
void OnSettingsAck() override;
void OnSettingsEnd() override;
@@ -178,12 +178,6 @@ class SpdyTestDeframerImpl : public SpdyTestDeframer,
size_t len) override;
void OnStreamEnd(SpdyStreamId stream_id) override;
void OnStreamPadding(SpdyStreamId stream_id, size_t len) override;
- void OnSynReply(SpdyStreamId stream_id, bool fin) override;
- void OnSynStream(SpdyStreamId stream_id,
- SpdyStreamId associated_stream_id,
- SpdyPriority priority,
- bool fin,
- bool unidirectional) override;
bool OnUnknownFrame(SpdyStreamId stream_id, int frame_type) override;
void OnWindowUpdate(SpdyStreamId stream_id, int delta_window_size) override;
@@ -642,16 +636,13 @@ bool SpdyTestDeframerImpl::OnRstStreamFrameData(const char* rst_stream_data,
// Called for an individual setting. There is no negotiation, the sender is
// stating the value that the sender is using.
-void SpdyTestDeframerImpl::OnSetting(SpdySettingsIds id,
- uint8_t flags,
- uint32_t value) {
- DVLOG(1) << "OnSetting id: " << id << std::hex << " flags: " << flags
- << " value: " << value;
+void SpdyTestDeframerImpl::OnSetting(SpdySettingsIds id, uint32_t value) {
+ DVLOG(1) << "OnSetting id: " << id << std::hex << " value: " << value;
CHECK_EQ(frame_type_, SETTINGS) << " frame_type_="
<< Http2FrameTypeToString(frame_type_);
CHECK(settings_);
settings_->push_back(std::make_pair(id, value));
- settings_ir_->AddSetting(id, true, true, value);
+ settings_ir_->AddSetting(id, value);
}
// Called at the start of a SETTINGS frame with setting entries, but not the
@@ -734,32 +725,6 @@ void SpdyTestDeframerImpl::OnStreamPadding(SpdyStreamId stream_id, size_t len) {
CHECK_LE(padding_len_, 256u) << "len=" << len;
}
-// Obsolete.
-void SpdyTestDeframerImpl::OnSynStream(SpdyStreamId stream_id,
- SpdyStreamId associated_stream_id,
- SpdyPriority priority,
- bool fin,
- bool unidirectional) {
- DVLOG(1) << "OnSynStream stream_id: " << stream_id;
- CHECK_EQ(frame_type_, UNSET) << " frame_type_="
- << Http2FrameTypeToString(frame_type_);
- frame_type_ = UNKNOWN;
- stream_id_ = stream_id;
- fin_ = fin;
- LOG(DFATAL) << "SYN_STREAM is not a valid HTTP/2 frame type.";
-}
-
-// Obsolete.
-void SpdyTestDeframerImpl::OnSynReply(SpdyStreamId stream_id, bool fin) {
- DVLOG(1) << "OnSynReply stream_id: " << stream_id;
- CHECK_EQ(frame_type_, UNSET) << " frame_type_="
- << Http2FrameTypeToString(frame_type_);
- frame_type_ = UNKNOWN;
- stream_id_ = stream_id;
- fin_ = fin;
- LOG(DFATAL) << "SYN_REPLY is not a valid HTTP/2 frame type.";
-}
-
// WINDOW_UPDATE is supposed to be hop-by-hop, according to the spec.
// stream_id is 0 if the update applies to the connection, else stream_id
// will be the id of a stream previously seen, which maybe half or fully
diff --git a/chromium/net/spdy/spdy_deframer_visitor_test.cc b/chromium/net/spdy/spdy_deframer_visitor_test.cc
index 9e947986864..f2dc4c74b81 100644
--- a/chromium/net/spdy/spdy_deframer_visitor_test.cc
+++ b/chromium/net/spdy/spdy_deframer_visitor_test.cc
@@ -31,7 +31,9 @@ namespace {
class SpdyDeframerVisitorTest : public ::testing::Test {
protected:
- SpdyDeframerVisitorTest() : encoder_(HTTP2), decoder_(HTTP2) {
+ SpdyDeframerVisitorTest()
+ : encoder_(SpdyFramer::ENABLE_COMPRESSION),
+ decoder_(SpdyFramer::ENABLE_COMPRESSION) {
decoder_.set_process_single_input_frame(true);
auto collector = MakeUnique<DeframerCallbackCollector>(&collected_frames_);
auto log_and_collect =
@@ -226,7 +228,7 @@ TEST_F(SpdyDeframerVisitorTest, SettingsFrame) {
ASSERT_NE(cf0.frame_ir, nullptr);
SpdySettingsIR expected_ir;
- expected_ir.AddSetting(SETTINGS_INITIAL_WINDOW_SIZE, true, true, 255);
+ expected_ir.AddSetting(SETTINGS_INITIAL_WINDOW_SIZE, 255);
EXPECT_TRUE(cf0.VerifyHasFrame(expected_ir));
SettingVector expected_settings;
@@ -239,7 +241,7 @@ TEST_F(SpdyDeframerVisitorTest, SettingsFrame) {
expected_settings.push_back({SETTINGS_INITIAL_WINDOW_SIZE, 65536});
EXPECT_FALSE(cf0.VerifyHasSettings(expected_settings));
- expected_ir.AddSetting(SETTINGS_INITIAL_WINDOW_SIZE, true, true, 65536);
+ expected_ir.AddSetting(SETTINGS_INITIAL_WINDOW_SIZE, 65536);
EXPECT_FALSE(cf0.VerifyHasFrame(expected_ir));
SpdySettingsIR unexpected_ir;
diff --git a/chromium/net/spdy/spdy_flags.cc b/chromium/net/spdy/spdy_flags.cc
index 3bfa05274db..1f342d8916a 100644
--- a/chromium/net/spdy/spdy_flags.cc
+++ b/chromium/net/spdy/spdy_flags.cc
@@ -9,10 +9,22 @@ namespace net {
// Log compressed size of HTTP/2 requests.
bool FLAGS_chromium_http2_flag_log_compressed_size = true;
+// If true, remove use of SpdyFrameBuilder::OverwriteLength().
+bool FLAGS_chromium_http2_flag_remove_rewritelength = true;
+
+// Use //net/http2/hpack/decoder as HPACK entry decoder.
+bool FLAGS_chromium_http2_flag_spdy_use_hpack_decoder2 = false;
+
+// Use //net/http2/hpack/decoder as complete HPACK decoder.
+bool FLAGS_chromium_http2_flag_spdy_use_hpack_decoder3 = false;
+
// If true, increase HPACK table size up to optimal size kOptTableSize if
// clients allow it.
bool FLAGS_chromium_reloadable_flag_increase_hpack_table_size = false;
+// Use Http2FrameDecoderAdapter.
+bool FLAGS_use_http2_frame_decoder_adapter = false;
+
// Use NestedSpdyFramerDecoder.
bool FLAGS_use_nested_spdy_framer_decoder = false;
diff --git a/chromium/net/spdy/spdy_flags.h b/chromium/net/spdy/spdy_flags.h
index cf0db837712..d448594b7b9 100644
--- a/chromium/net/spdy/spdy_flags.h
+++ b/chromium/net/spdy/spdy_flags.h
@@ -10,8 +10,14 @@
namespace net {
NET_EXPORT_PRIVATE extern bool FLAGS_chromium_http2_flag_log_compressed_size;
+NET_EXPORT_PRIVATE extern bool FLAGS_chromium_http2_flag_remove_rewritelength;
+NET_EXPORT_PRIVATE extern bool
+ FLAGS_chromium_http2_flag_spdy_use_hpack_decoder2;
+NET_EXPORT_PRIVATE extern bool
+ FLAGS_chromium_http2_flag_spdy_use_hpack_decoder3;
NET_EXPORT_PRIVATE extern bool
FLAGS_chromium_reloadable_flag_increase_hpack_table_size;
+NET_EXPORT_PRIVATE extern bool FLAGS_use_http2_frame_decoder_adapter;
NET_EXPORT_PRIVATE extern bool FLAGS_use_nested_spdy_framer_decoder;
} // namespace net
diff --git a/chromium/net/spdy/spdy_frame_builder.cc b/chromium/net/spdy/spdy_frame_builder.cc
index d6918b7c7d1..39f0c29606e 100644
--- a/chromium/net/spdy/spdy_frame_builder.cc
+++ b/chromium/net/spdy/spdy_frame_builder.cc
@@ -13,33 +13,8 @@
namespace net {
-namespace {
-
-// A special structure for the 8 bit flags and 24 bit length fields.
-union FlagsAndLength {
- uint8_t flags[4]; // 8 bits
- uint32_t length; // 24 bits
-};
-
-// Creates a FlagsAndLength.
-FlagsAndLength CreateFlagsAndLength(uint8_t flags, size_t length) {
- DCHECK_EQ(0u, length & ~static_cast<size_t>(kLengthMask));
- FlagsAndLength flags_length;
- flags_length.length = base::HostToNet32(static_cast<uint32_t>(length));
- DCHECK_EQ(0, flags & ~kControlFlagsMask);
- flags_length.flags[0] = flags;
- return flags_length;
-}
-
-} // namespace
-
-SpdyFrameBuilder::SpdyFrameBuilder(size_t size, SpdyMajorVersion version)
- : buffer_(new char[size]),
- capacity_(size),
- length_(0),
- offset_(0),
- version_(version) {
-}
+SpdyFrameBuilder::SpdyFrameBuilder(size_t size)
+ : buffer_(new char[size]), capacity_(size), length_(0), offset_(0) {}
SpdyFrameBuilder::~SpdyFrameBuilder() {
}
@@ -60,57 +35,16 @@ bool SpdyFrameBuilder::Seek(size_t length) {
return true;
}
-bool SpdyFrameBuilder::WriteControlFrameHeader(const SpdyFramer& framer,
- SpdyFrameType type,
- uint8_t flags) {
- DCHECK_EQ(SPDY3, version_);
- DCHECK(SpdyConstants::IsValidFrameType(
- version_, SpdyConstants::SerializeFrameType(version_, type)));
- bool success = true;
- FlagsAndLength flags_length =
- CreateFlagsAndLength(flags, capacity_ - framer.GetFrameHeaderSize());
- success &= WriteUInt16(kControlFlagMask | kSpdy3Version);
- success &= WriteUInt16(
- SpdyConstants::SerializeFrameType(framer.protocol_version(), type));
- success &= WriteBytes(&flags_length, sizeof(flags_length));
- DCHECK_EQ(framer.GetFrameHeaderSize(), length());
- return success;
-}
-
-bool SpdyFrameBuilder::WriteDataFrameHeader(const SpdyFramer& framer,
- SpdyStreamId stream_id,
- uint8_t flags) {
- if (version_ == HTTP2) {
- return BeginNewFrame(framer, DATA, flags, stream_id);
- }
- DCHECK_EQ(0u, stream_id & ~kStreamIdMask);
- bool success = true;
- success &= WriteUInt32(stream_id);
- size_t length_field = capacity_ - framer.GetDataFrameMinimumSize();
- DCHECK_EQ(0u, length_field & ~static_cast<size_t>(kLengthMask));
- FlagsAndLength flags_length;
- flags_length.length = base::HostToNet32(static_cast<uint32_t>(length_field));
- DCHECK_EQ(0, flags & ~kDataFlagsMask);
- flags_length.flags[0] = flags;
- success &= WriteBytes(&flags_length, sizeof(flags_length));
- DCHECK_EQ(framer.GetDataFrameMinimumSize(), length());
- return success;
-}
-
bool SpdyFrameBuilder::BeginNewFrame(const SpdyFramer& framer,
SpdyFrameType type,
uint8_t flags,
SpdyStreamId stream_id) {
- DCHECK(SpdyConstants::IsValidFrameType(
- version_, SpdyConstants::SerializeFrameType(version_, type)));
+ DCHECK(IsValidFrameType(SerializeFrameType(type)));
DCHECK_EQ(0u, stream_id & ~kStreamIdMask);
- DCHECK_EQ(HTTP2, framer.protocol_version());
bool success = true;
- size_t frame_header_length =
- SpdyConstants::GetFrameHeaderSize(framer.protocol_version());
if (length_ > 0) {
// Update length field for previous frame.
- OverwriteLength(framer, length_ - frame_header_length);
+ OverwriteLength(framer, length_ - kFrameHeaderSize);
SPDY_BUG_IF(framer.GetFrameMaximumSize() < length_)
<< "Frame length " << length_
<< " is longer than the maximum allowed length.";
@@ -123,8 +57,31 @@ bool SpdyFrameBuilder::BeginNewFrame(const SpdyFramer& framer,
// the length will get overwritten when we begin the next frame.
// Don't check for length limits here because this may be larger than the
// actual frame length.
- success &= WriteUInt24(capacity_ - offset_ - frame_header_length);
- success &= WriteUInt8(SpdyConstants::SerializeFrameType(version_, type));
+ success &= WriteUInt24(capacity_ - offset_ - kFrameHeaderSize);
+ success &= WriteUInt8(SerializeFrameType(type));
+ success &= WriteUInt8(flags);
+ success &= WriteUInt32(stream_id);
+ DCHECK_EQ(framer.GetDataFrameMinimumSize(), length_);
+ return success;
+}
+
+bool SpdyFrameBuilder::BeginNewFrame(const SpdyFramer& framer,
+ SpdyFrameType type,
+ uint8_t flags,
+ SpdyStreamId stream_id,
+ size_t length) {
+ DCHECK(IsValidFrameType(SerializeFrameType(type)));
+ DCHECK_EQ(0u, stream_id & ~kStreamIdMask);
+ bool success = true;
+ SPDY_BUG_IF(framer.GetFrameMaximumSize() < length_)
+ << "Frame length " << length_
+ << " is longer than the maximum allowed length.";
+
+ offset_ += length_;
+ length_ = 0;
+
+ success &= WriteUInt24(length);
+ success &= WriteUInt8(SerializeFrameType(type));
success &= WriteUInt8(flags);
success &= WriteUInt32(stream_id);
DCHECK_EQ(framer.GetDataFrameMinimumSize(), length_);
@@ -169,35 +126,18 @@ bool SpdyFrameBuilder::RewriteLength(const SpdyFramer& framer) {
bool SpdyFrameBuilder::OverwriteLength(const SpdyFramer& framer,
size_t length) {
- if (version_ == SPDY3) {
- DCHECK_GE(framer.GetFrameMaximumSize() - framer.GetFrameMinimumSize(),
- length);
- } else {
- DCHECK_GE(framer.GetFrameMaximumSize(), length);
- }
+ DCHECK_GE(framer.GetFrameMaximumSize(), length);
bool success = false;
const size_t old_length = length_;
- if (version_ == SPDY3) {
- FlagsAndLength flags_length = CreateFlagsAndLength(
- 0, // We're not writing over the flags value anyway.
- length);
-
- // Write into the correct location by temporarily faking the offset.
- length_ = 5; // Offset at which the length field occurs.
- success = WriteBytes(reinterpret_cast<char*>(&flags_length) + 1,
- sizeof(flags_length) - 1);
- } else {
- length_ = 0;
- success = WriteUInt24(length);
- }
+ length_ = 0;
+ success = WriteUInt24(length);
length_ = old_length;
return success;
}
bool SpdyFrameBuilder::OverwriteFlags(const SpdyFramer& framer, uint8_t flags) {
- DCHECK_EQ(HTTP2, framer.protocol_version());
bool success = false;
const size_t old_length = length_;
// Flags are the fifth octet in the frame prefix.
diff --git a/chromium/net/spdy/spdy_frame_builder.h b/chromium/net/spdy/spdy_frame_builder.h
index ab21e0a0d87..b48ef20261d 100644
--- a/chromium/net/spdy/spdy_frame_builder.h
+++ b/chromium/net/spdy/spdy_frame_builder.h
@@ -31,7 +31,7 @@ class SpdyFramer;
class NET_EXPORT_PRIVATE SpdyFrameBuilder {
public:
// Initializes a SpdyFrameBuilder with a buffer of given size
- SpdyFrameBuilder(size_t size, SpdyMajorVersion version);
+ explicit SpdyFrameBuilder(size_t size);
~SpdyFrameBuilder();
@@ -51,36 +51,26 @@ class NET_EXPORT_PRIVATE SpdyFrameBuilder {
// GetWriteableBuffer() above.
bool Seek(size_t length);
- // Populates this frame with a SPDY control frame header using
- // version-specific information from the |framer| and length information from
- // |capacity_|. The given type must be a control frame type.
- // Used only for SPDY3.
- bool WriteControlFrameHeader(const SpdyFramer& framer,
- SpdyFrameType type,
- uint8_t flags);
-
- // Populates this frame with a SPDY data frame header using version-specific
- // information from the |framer| and length information from capacity_.
- bool WriteDataFrameHeader(const SpdyFramer& framer,
- SpdyStreamId stream_id,
- uint8_t flags);
-
- // Populates this frame with a HTTP2 frame prefix using version-specific
- // information from the |framer| and length information from |capacity_|. The
- // given type must be a control frame type.
- // Used only for HTTP2.
+ // Populates this frame with a HTTP2 frame prefix using length information
+ // from |capacity_|. The given type must be a control frame type.
bool BeginNewFrame(const SpdyFramer& framer,
SpdyFrameType type,
uint8_t flags,
SpdyStreamId stream_id);
+ // Populates this frame with a HTTP2 frame prefix with length information.
+ // The given type must be a control frame type.
+ bool BeginNewFrame(const SpdyFramer& framer,
+ SpdyFrameType type,
+ uint8_t flags,
+ SpdyStreamId stream_id,
+ size_t length);
+
// Takes the buffer from the SpdyFrameBuilder.
SpdySerializedFrame take() {
- if (version_ == HTTP2) {
- SPDY_BUG_IF(SpdyConstants::GetMaxFrameSizeLimit(version_) < length_)
- << "Frame length " << length_
- << " is longer than the maximum possible allowed length.";
- }
+ SPDY_BUG_IF(kMaxFrameSizeLimit < length_)
+ << "Frame length " << length_
+ << " is longer than the maximum possible allowed length.";
SpdySerializedFrame rv(buffer_.release(), length(), true);
capacity_ = 0;
length_ = 0;
@@ -131,7 +121,6 @@ class NET_EXPORT_PRIVATE SpdyFrameBuilder {
// Update (in-place) the flags field in the frame being built to reflect the
// given flags value.
- // Used only for SPDY versions >=4.
bool OverwriteFlags(const SpdyFramer& framer, uint8_t flags);
private:
@@ -143,8 +132,6 @@ class NET_EXPORT_PRIVATE SpdyFrameBuilder {
size_t capacity_; // Allocation size of payload, set by constructor.
size_t length_; // Length of the latest frame in the buffer.
size_t offset_; // Position at which the latest frame begins.
-
- const SpdyMajorVersion version_;
};
} // namespace net
diff --git a/chromium/net/spdy/spdy_frame_builder_test.cc b/chromium/net/spdy/spdy_frame_builder_test.cc
index b27abf9e551..624a534c089 100644
--- a/chromium/net/spdy/spdy_frame_builder_test.cc
+++ b/chromium/net/spdy/spdy_frame_builder_test.cc
@@ -10,46 +10,28 @@
namespace net {
-class SpdyFrameBuilderTest : public ::testing::TestWithParam<SpdyMajorVersion> {
- protected:
- void SetUp() override { spdy_version_ = GetParam(); }
-
- // Major version of SPDY protocol to be used.
- SpdyMajorVersion spdy_version_;
-};
-
-// All tests are run with SPDY/3 and HTTP/2.
-INSTANTIATE_TEST_CASE_P(SpdyFrameBuilderTests,
- SpdyFrameBuilderTest,
- ::testing::Values(SPDY3, HTTP2));
-
-TEST_P(SpdyFrameBuilderTest, GetWritableBuffer) {
- const size_t builder_size = 10;
- SpdyFrameBuilder builder(builder_size, spdy_version_);
- char* writable_buffer = builder.GetWritableBuffer(builder_size);
- memset(writable_buffer, ~1, builder_size);
- EXPECT_TRUE(builder.Seek(builder_size));
+TEST(SpdyFrameBuilderTest, GetWritableBuffer) {
+ const size_t kBuilderSize = 10;
+ SpdyFrameBuilder builder(kBuilderSize);
+ char* writable_buffer = builder.GetWritableBuffer(kBuilderSize);
+ memset(writable_buffer, ~1, kBuilderSize);
+ EXPECT_TRUE(builder.Seek(kBuilderSize));
SpdySerializedFrame frame(builder.take());
- char expected[builder_size];
- memset(expected, ~1, builder_size);
- EXPECT_EQ(base::StringPiece(expected, builder_size),
- base::StringPiece(frame.data(), builder_size));
+ char expected[kBuilderSize];
+ memset(expected, ~1, kBuilderSize);
+ EXPECT_EQ(base::StringPiece(expected, kBuilderSize),
+ base::StringPiece(frame.data(), kBuilderSize));
}
-TEST_P(SpdyFrameBuilderTest, RewriteLength) {
+TEST(SpdyFrameBuilderTest, RewriteLength) {
// Create an empty SETTINGS frame both via framer and manually via builder.
// The one created via builder is initially given the incorrect length, but
// then is corrected via RewriteLength().
- SpdyFramer framer(spdy_version_);
+ SpdyFramer framer(SpdyFramer::ENABLE_COMPRESSION);
SpdySettingsIR settings_ir;
SpdySerializedFrame expected(framer.SerializeSettings(settings_ir));
- SpdyFrameBuilder builder(expected.size() + 1, spdy_version_);
- if (spdy_version_ == SPDY3) {
- builder.WriteControlFrameHeader(framer, SETTINGS, 0);
- builder.WriteUInt32(0); // Write the number of settings.
- } else {
- builder.BeginNewFrame(framer, SETTINGS, 0, 0);
- }
+ SpdyFrameBuilder builder(expected.size() + 1);
+ builder.BeginNewFrame(framer, SETTINGS, 0, 0);
EXPECT_TRUE(builder.GetWritableBuffer(1) != NULL);
builder.RewriteLength(framer);
SpdySerializedFrame built(builder.take());
@@ -57,21 +39,17 @@ TEST_P(SpdyFrameBuilderTest, RewriteLength) {
base::StringPiece(built.data(), expected.size()));
}
-TEST_P(SpdyFrameBuilderTest, OverwriteFlags) {
+TEST(SpdyFrameBuilderTest, OverwriteFlags) {
// Create a HEADERS frame both via framer and manually via builder with
// different flags set, then make them match using OverwriteFlags().
- SpdyFramer framer(spdy_version_);
- if (spdy_version_ == SPDY3) {
- return;
- }
+ SpdyFramer framer(SpdyFramer::ENABLE_COMPRESSION);
SpdyHeadersIR headers_ir(1);
SpdySerializedFrame expected(framer.SerializeHeaders(headers_ir));
- SpdyFrameBuilder builder(expected.size(), spdy_version_);
+ SpdyFrameBuilder builder(expected.size());
builder.BeginNewFrame(framer, HEADERS, 0, 1);
builder.OverwriteFlags(framer, HEADERS_FLAG_END_HEADERS);
SpdySerializedFrame built(builder.take());
EXPECT_EQ(base::StringPiece(expected.data(), expected.size()),
base::StringPiece(built.data(), built.size()));
}
-
} // namespace net
diff --git a/chromium/net/spdy/spdy_frame_reader.cc b/chromium/net/spdy/spdy_frame_reader.cc
index 4727caaa2ec..7e9ded5321c 100644
--- a/chromium/net/spdy/spdy_frame_reader.cc
+++ b/chromium/net/spdy/spdy_frame_reader.cc
@@ -10,6 +10,8 @@
namespace net {
+using base::StringPiece;
+
SpdyFrameReader::SpdyFrameReader(const char* data, const size_t len)
: data_(data),
len_(len),
@@ -115,7 +117,7 @@ bool SpdyFrameReader::ReadUInt24(uint32_t* result) {
return true;
}
-bool SpdyFrameReader::ReadStringPiece16(base::StringPiece* result) {
+bool SpdyFrameReader::ReadStringPiece16(StringPiece* result) {
// Read resultant length.
uint16_t result_len;
if (!ReadUInt16(&result_len)) {
@@ -130,7 +132,7 @@ bool SpdyFrameReader::ReadStringPiece16(base::StringPiece* result) {
}
// Set result.
- result->set(data_ + ofs_, result_len);
+ *result = StringPiece(data_ + ofs_, result_len);
// Iterate.
ofs_ += result_len;
@@ -138,7 +140,7 @@ bool SpdyFrameReader::ReadStringPiece16(base::StringPiece* result) {
return true;
}
-bool SpdyFrameReader::ReadStringPiece32(base::StringPiece* result) {
+bool SpdyFrameReader::ReadStringPiece32(StringPiece* result) {
// Read resultant length.
uint32_t result_len;
if (!ReadUInt32(&result_len)) {
@@ -153,7 +155,7 @@ bool SpdyFrameReader::ReadStringPiece32(base::StringPiece* result) {
}
// Set result.
- result->set(data_ + ofs_, result_len);
+ *result = StringPiece(data_ + ofs_, result_len);
// Iterate.
ofs_ += result_len;
diff --git a/chromium/net/spdy/spdy_framer.cc b/chromium/net/spdy/spdy_framer.cc
index c6f0e3f3b19..db0628098de 100644
--- a/chromium/net/spdy/spdy_framer.cc
+++ b/chromium/net/spdy/spdy_framer.cc
@@ -23,6 +23,10 @@
#include "base/strings/string_util.h"
#include "net/quic/core/quic_flags.h"
#include "net/spdy/hpack/hpack_constants.h"
+#include "net/spdy/hpack/hpack_decoder.h"
+#include "net/spdy/hpack/hpack_decoder2.h"
+#include "net/spdy/hpack/hpack_decoder3.h"
+#include "net/spdy/http2_frame_decoder_adapter.h"
#include "net/spdy/spdy_bitmasks.h"
#include "net/spdy/spdy_bug_tracker.h"
#include "net/spdy/spdy_flags.h"
@@ -30,7 +34,6 @@
#include "net/spdy/spdy_frame_reader.h"
#include "net/spdy/spdy_framer_decoder_adapter.h"
#include "net/spdy/spdy_headers_block_parser.h"
-#include "third_party/zlib/zlib.h"
using base::StringPiece;
using std::hex;
@@ -41,37 +44,6 @@ namespace net {
namespace {
-// Compute the id of our dictionary so that we know we're using the
-// right one when asked for it.
-uLong CalculateDictionaryId(const char* dictionary,
- const size_t dictionary_size) {
- uLong initial_value = adler32(0L, Z_NULL, 0);
- return adler32(initial_value,
- reinterpret_cast<const Bytef*>(dictionary),
- dictionary_size);
-}
-
-#if !defined(USE_SYSTEM_ZLIB)
-// Check to see if the name and value of a cookie are both empty.
-bool IsCookieEmpty(const base::StringPiece& cookie) {
- if (cookie.size() == 0) {
- return true;
- }
- size_t pos = cookie.find('=');
- if (pos == base::StringPiece::npos) {
- return false;
- }
- // Ignore leading whitespaces of cookie value.
- size_t value_start = pos + 1;
- for (; value_start < cookie.size(); value_start++) {
- if (!(cookie[value_start] == ' ' || cookie[value_start] == '\t')) {
- break;
- }
- }
- return (pos == 0) && ((cookie.size() - value_start) == 0);
-}
-#endif // !defined(USE_SYSTEM_ZLIB)
-
// Pack parent stream ID and exclusive flag into the format used by HTTP/2
// headers and priority frames.
uint32_t PackStreamDependencyValues(bool exclusive,
@@ -98,24 +70,22 @@ void UnpackStreamDependencyValues(uint32_t packed,
std::unique_ptr<SpdyFramerDecoderAdapter> DecoderAdapterFactory(
SpdyFramer* outer) {
if (FLAGS_use_nested_spdy_framer_decoder) {
+ if (FLAGS_use_http2_frame_decoder_adapter) {
+ SPDY_BUG << "Two SpdyFramerDecoderAdapter are enabled!";
+ }
DVLOG(1) << "Creating NestedSpdyFramerDecoder.";
return CreateNestedSpdyFramerDecoder(outer);
}
- return nullptr;
-}
-struct DictionaryIds {
- DictionaryIds()
- : v3_dictionary_id(
- CalculateDictionaryId(kV3Dictionary, kV3DictionarySize)) {}
- const uLong v3_dictionary_id;
-};
+ if (FLAGS_use_http2_frame_decoder_adapter) {
+ DVLOG(1) << "Creating Http2FrameDecoderAdapter.";
+ return CreateHttp2FrameDecoderAdapter(outer);
+ }
-// Adler ID for the SPDY header compressor dictionaries. Note that they are
-// initialized lazily to avoid static initializers.
-base::LazyInstance<DictionaryIds>::Leaky g_dictionary_ids;
+ return nullptr;
+}
-// Used to indicate no flags in a SPDY flags field.
+// Used to indicate no flags in a HTTP2 flags field.
const uint8_t kNoFlags = 0;
// Wire sizes of priority payloads.
@@ -135,8 +105,7 @@ const size_t SpdyFramer::kHeaderDataChunkMaxSize = 1024;
const size_t SpdyFramer::kMaxControlFrameSize = (1 << 14) - 1;
const size_t SpdyFramer::kMaxDataPayloadSendSize = 1 << 14;
// The size of the control frame buffer. Must be >= the minimum size of the
-// largest control frame, which is SYN_STREAM. See GetSynStreamMinimumSize() for
-// calculation details.
+// largest control frame.
const size_t SpdyFramer::kControlFrameBufferSize = 19;
#ifdef DEBUG_SPDY_STATE_CHANGES
@@ -160,21 +129,6 @@ const size_t SpdyFramer::kControlFrameBufferSize = 19;
} while (false)
#endif
-SettingsFlagsAndId SettingsFlagsAndId::FromWireFormat(SpdyMajorVersion version,
- uint32_t wire) {
- return SettingsFlagsAndId(base::NetToHost32(wire) >> 24,
- base::NetToHost32(wire) & 0x00ffffff);
-}
-
-SettingsFlagsAndId::SettingsFlagsAndId(uint8_t flags, uint32_t id)
- : flags_(flags), id_(id & 0x00ffffff) {
- SPDY_BUG_IF(id > (1u << 24)) << "SPDY setting ID too large: " << id;
-}
-
-uint32_t SettingsFlagsAndId::GetWireFormat(SpdyMajorVersion version) const {
- return base::HostToNet32(id_ & 0x00ffffff) | base::HostToNet32(flags_ << 24);
-}
-
bool SpdyFramerVisitorInterface::OnGoAwayFrameData(const char* goaway_data,
size_t len) {
return true;
@@ -186,20 +140,16 @@ bool SpdyFramerVisitorInterface::OnRstStreamFrameData(
return true;
}
-SpdyFramer::SpdyFramer(SpdyMajorVersion version,
- SpdyFramer::DecoderAdapterFactoryFn adapter_factory)
+SpdyFramer::SpdyFramer(SpdyFramer::DecoderAdapterFactoryFn adapter_factory,
+ CompressionOption option)
: current_frame_buffer_(kControlFrameBufferSize),
expect_continuation_(0),
visitor_(NULL),
debug_visitor_(NULL),
header_handler_(nullptr),
- display_protocol_("SPDY"),
- protocol_version_(version),
- enable_compression_(true),
- syn_frame_processed_(false),
+ compression_option_(option),
probable_http_response_(false),
end_stream_when_done_(false) {
- DCHECK(protocol_version_ == SPDY3 || protocol_version_ == HTTP2);
// TODO(bnc): The way kMaxControlFrameSize is currently interpreted, it
// includes the frame header, whereas kSpdyInitialFrameSizeLimit does not.
// Therefore this assertion is unnecessarily strict.
@@ -207,21 +157,16 @@ SpdyFramer::SpdyFramer(SpdyMajorVersion version,
"Our send limit should be at most our receive limit");
Reset();
- if (version == HTTP2 && adapter_factory != nullptr) {
+ if (adapter_factory != nullptr) {
decoder_adapter_ = adapter_factory(this);
}
+ skip_rewritelength_ = FLAGS_chromium_http2_flag_remove_rewritelength;
}
-SpdyFramer::SpdyFramer(SpdyMajorVersion version)
- : SpdyFramer(version, &DecoderAdapterFactory) {}
+SpdyFramer::SpdyFramer(CompressionOption option)
+ : SpdyFramer(&DecoderAdapterFactory, option) {}
SpdyFramer::~SpdyFramer() {
- if (header_compressor_.get()) {
- deflateEnd(header_compressor_.get());
- }
- if (header_decompressor_.get()) {
- inflateEnd(header_decompressor_.get());
- }
}
void SpdyFramer::Reset() {
@@ -287,77 +232,32 @@ SpdyFramer::SpdyState SpdyFramer::state() const {
}
size_t SpdyFramer::GetDataFrameMinimumSize() const {
- return SpdyConstants::GetDataFrameMinimumSize(protocol_version_);
+ return kDataFrameMinimumSize;
}
// Size, in bytes, of the control frame header.
size_t SpdyFramer::GetFrameHeaderSize() const {
- return SpdyConstants::GetFrameHeaderSize(protocol_version_);
-}
-
-size_t SpdyFramer::GetSynStreamMinimumSize() const {
- // Size, in bytes, of a SYN_STREAM frame not including the variable-length
- // header block.
- if (protocol_version_ == SPDY3) {
- // Calculated as:
- // control frame header + 2 * 4 (stream IDs) + 1 (priority)
- // + 1 (unused)
- return GetFrameHeaderSize() + 10;
- } else {
- return GetFrameHeaderSize() + kPriorityDependencyPayloadSize +
- kPriorityWeightPayloadSize;
- }
-}
-
-size_t SpdyFramer::GetSynReplyMinimumSize() const {
- // Size, in bytes, of a SYN_REPLY frame not including the variable-length
- // header block.
- size_t size = GetFrameHeaderSize();
- if (protocol_version_ == SPDY3) {
- // Calculated as:
- // control frame header + 4 (stream IDs)
- size += 4;
- }
-
- return size;
+ return kFrameHeaderSize;
}
-// TODO(jamessynge): Rename this to GetRstStreamSize as the frame is fixed size.
-size_t SpdyFramer::GetRstStreamMinimumSize() const {
+size_t SpdyFramer::GetRstStreamSize() const {
// Size, in bytes, of a RST_STREAM frame.
- if (protocol_version_ == SPDY3) {
- // Calculated as:
- // control frame header + 4 (stream id) + 4 (status code)
- return GetFrameHeaderSize() + 8;
- } else {
- // Calculated as:
- // frame prefix + 4 (status code)
- return GetFrameHeaderSize() + 4;
- }
+ // Calculated as:
+ // frame prefix + 4 (status code)
+ return GetFrameHeaderSize() + 4;
}
size_t SpdyFramer::GetSettingsMinimumSize() const {
// Size, in bytes, of a SETTINGS frame not including the IDs and values
- // from the variable-length value block. Calculated as:
- // control frame header + 4 (number of ID/value pairs)
- if (protocol_version_ == SPDY3) {
- return GetFrameHeaderSize() + 4;
- } else {
- return GetFrameHeaderSize();
- }
+ // from the variable-length value block.
+ return GetFrameHeaderSize();
}
size_t SpdyFramer::GetPingSize() const {
// Size, in bytes, of this PING frame.
- if (protocol_version_ == SPDY3) {
- // Calculated as:
- // control frame header + 4 (id)
- return GetFrameHeaderSize() + 4;
- } else {
- // Calculated as:
- // control frame header + 8 (id)
- return GetFrameHeaderSize() + 8;
- }
+ // Calculated as:
+ // control frame header + 8 (id)
+ return GetFrameHeaderSize() + 8;
}
size_t SpdyFramer::GetGoAwayMinimumSize() const {
@@ -369,38 +269,23 @@ size_t SpdyFramer::GetGoAwayMinimumSize() const {
size_t SpdyFramer::GetHeadersMinimumSize() const {
// Size, in bytes, of a HEADERS frame not including the variable-length
// header block.
- size_t size = GetFrameHeaderSize();
- if (protocol_version_ == SPDY3) {
- // Calculated as:
- // control frame header + 4 (stream IDs)
- size += 4;
- }
-
- return size;
+ return GetFrameHeaderSize();
}
size_t SpdyFramer::GetWindowUpdateSize() const {
// Size, in bytes, of a WINDOW_UPDATE frame.
- if (protocol_version_ == SPDY3) {
- // Calculated as:
- // control frame header + 4 (stream id) + 4 (delta)
- return GetFrameHeaderSize() + 8;
- } else {
- // Calculated as:
- // frame prefix + 4 (delta)
- return GetFrameHeaderSize() + 4;
- }
+ // Calculated as:
+ // frame prefix + 4 (delta)
+ return GetFrameHeaderSize() + 4;
}
size_t SpdyFramer::GetBlockedSize() const {
- DCHECK_EQ(HTTP2, protocol_version_);
// Size, in bytes, of a BLOCKED frame.
// The BLOCKED frame has no payload beyond the control frame header.
return GetFrameHeaderSize();
}
size_t SpdyFramer::GetPushPromiseMinimumSize() const {
- DCHECK_EQ(HTTP2, protocol_version_);
// Size, in bytes, of a PUSH_PROMISE frame, sans the embedded header block.
// Calculated as frame prefix + 4 (promised stream id)
return GetFrameHeaderSize() + 4;
@@ -432,21 +317,12 @@ size_t SpdyFramer::GetFrameMinimumSize() const {
}
size_t SpdyFramer::GetFrameMaximumSize() const {
- if (protocol_version_ == HTTP2) {
- return send_frame_size_limit_ +
- SpdyConstants::GetFrameHeaderSize(protocol_version_);
- } else {
- return SpdyConstants::GetMaxFrameSizeLimit(protocol_version_);
- }
+ return send_frame_size_limit_ + kFrameHeaderSize;
}
size_t SpdyFramer::GetDataFrameMaximumPayload() const {
- if (protocol_version_ == HTTP2) {
- return std::min(kMaxDataPayloadSendSize,
- GetFrameMaximumSize() - GetDataFrameMinimumSize());
- } else {
- return GetFrameMaximumSize() - GetDataFrameMinimumSize();
- }
+ return std::min(kMaxDataPayloadSendSize,
+ GetFrameMaximumSize() - GetDataFrameMinimumSize());
}
const char* SpdyFramer::StateToString(int state) {
@@ -542,24 +418,22 @@ const char* SpdyFramer::StatusCodeToString(int status_code) {
return "NO_ERROR";
case RST_STREAM_PROTOCOL_ERROR:
return "PROTOCOL_ERROR";
- case RST_STREAM_INVALID_STREAM:
- return "INVALID_STREAM";
- case RST_STREAM_REFUSED_STREAM:
- return "REFUSED_STREAM";
- case RST_STREAM_UNSUPPORTED_VERSION:
- return "UNSUPPORTED_VERSION";
- case RST_STREAM_CANCEL:
- return "CANCEL";
case RST_STREAM_INTERNAL_ERROR:
return "INTERNAL_ERROR";
case RST_STREAM_FLOW_CONTROL_ERROR:
return "FLOW_CONTROL_ERROR";
- case RST_STREAM_STREAM_IN_USE:
- return "STREAM_IN_USE";
- case RST_STREAM_STREAM_ALREADY_CLOSED:
- return "STREAM_ALREADY_CLOSED";
- case RST_STREAM_FRAME_TOO_LARGE:
- return "FRAME_TOO_LARGE";
+ case RST_STREAM_SETTINGS_TIMEOUT:
+ return "SETTINGS_TIMEOUT";
+ case RST_STREAM_STREAM_CLOSED:
+ return "STREAM_CLOSED";
+ case RST_STREAM_FRAME_SIZE_ERROR:
+ return "FRAME_SIZE_ERROR";
+ case RST_STREAM_REFUSED_STREAM:
+ return "REFUSED_STREAM";
+ case RST_STREAM_CANCEL:
+ return "CANCEL";
+ case RST_STREAM_COMPRESSION_ERROR:
+ return "COMPRESSION_ERROR";
case RST_STREAM_CONNECT_ERROR:
return "CONNECT_ERROR";
case RST_STREAM_ENHANCE_YOUR_CALM:
@@ -576,10 +450,6 @@ const char* SpdyFramer::FrameTypeToString(SpdyFrameType type) {
switch (type) {
case DATA:
return "DATA";
- case SYN_STREAM:
- return "SYN_STREAM";
- case SYN_REPLY:
- return "SYN_REPLY";
case RST_STREAM:
return "RST_STREAM";
case SETTINGS:
@@ -644,7 +514,7 @@ size_t SpdyFramer::ProcessInput(const char* data, size_t len) {
case SPDY_CONTROL_FRAME_BEFORE_HEADER_BLOCK: {
// Control frames that contain header blocks
- // (SYN_STREAM, SYN_REPLY, HEADERS, PUSH_PROMISE, CONTINUATION)
+ // (HEADERS, PUSH_PROMISE, CONTINUATION)
// take a special path through the state machine - they
// will go:
// 1. SPDY_CONTROL_FRAME_BEFORE_HEADER_BLOCK
@@ -670,8 +540,7 @@ size_t SpdyFramer::ProcessInput(const char* data, size_t len) {
}
case SPDY_CONTROL_FRAME_HEADER_BLOCK: {
- int bytes_read = ProcessControlFrameHeaderBlock(
- data, len, protocol_version_ == HTTP2);
+ int bytes_read = ProcessControlFrameHeaderBlock(data, len);
len -= bytes_read;
data += bytes_read;
break;
@@ -734,8 +603,7 @@ size_t SpdyFramer::ProcessInput(const char* data, size_t len) {
}
default:
- SPDY_BUG << "Invalid value for " << display_protocol_
- << " framer state: " << state_;
+ SPDY_BUG << "Invalid value for framer state: " << state_;
// This ensures that we don't infinite-loop if state_ gets an
// invalid value somehow, such as due to a SpdyFramer getting deleted
// from a callback it calls.
@@ -780,72 +648,57 @@ void SpdyFramer::SpdySettingsScratch::Reset() {
SpdyFrameType SpdyFramer::ValidateFrameHeader(bool is_control_frame,
int frame_type_field,
size_t payload_length_field) {
- if (!SpdyConstants::IsValidFrameType(protocol_version_, frame_type_field)) {
- if (protocol_version_ == SPDY3) {
- if (is_control_frame) {
- DLOG(WARNING) << "Invalid control frame type " << frame_type_field
- << " (protocol version: " << protocol_version_ << ")";
- set_error(SPDY_INVALID_CONTROL_FRAME);
- } else {
- // Else it's a SPDY3 data frame which we don't validate further here
- }
+ if (!IsValidFrameType(frame_type_field)) {
+ // We ignore unknown frame types for extensibility, as long as
+ // the rest of the control frame header is valid.
+ // We rely on the visitor to check validity of current_frame_stream_id_.
+ bool valid_stream =
+ visitor_->OnUnknownFrame(current_frame_stream_id_, frame_type_field);
+ if (expect_continuation_) {
+ // Report an unexpected frame error and close the connection
+ // if we expect a continuation and receive an unknown frame.
+ DLOG(ERROR) << "The framer was expecting to receive a CONTINUATION "
+ << "frame, but instead received an unknown frame of type "
+ << frame_type_field;
+ set_error(SPDY_UNEXPECTED_FRAME);
+ } else if (!valid_stream) {
+ // Report an invalid frame error and close the stream if the
+ // stream_id is not valid.
+ DLOG(WARNING) << "Unknown control frame type " << frame_type_field
+ << " received on invalid stream "
+ << current_frame_stream_id_;
+ set_error(SPDY_INVALID_CONTROL_FRAME);
} else {
- // In HTTP2 we ignore unknown frame types for extensibility, as long as
- // the rest of the control frame header is valid.
- // We rely on the visitor to check validity of current_frame_stream_id_.
- bool valid_stream =
- visitor_->OnUnknownFrame(current_frame_stream_id_, frame_type_field);
- if (expect_continuation_) {
- // Report an unexpected frame error and close the connection
- // if we expect a continuation and receive an unknown frame.
- DLOG(ERROR) << "The framer was expecting to receive a CONTINUATION "
- << "frame, but instead received an unknown frame of type "
- << frame_type_field;
- set_error(SPDY_UNEXPECTED_FRAME);
- } else if (!valid_stream) {
- // Report an invalid frame error and close the stream if the
- // stream_id is not valid.
- DLOG(WARNING) << "Unknown control frame type " << frame_type_field
- << " received on invalid stream "
- << current_frame_stream_id_;
- set_error(SPDY_INVALID_CONTROL_FRAME);
- } else {
- DVLOG(1) << "Ignoring unknown frame type.";
- CHANGE_STATE(SPDY_IGNORE_REMAINING_PAYLOAD);
- }
+ DVLOG(1) << "Ignoring unknown frame type.";
+ CHANGE_STATE(SPDY_IGNORE_REMAINING_PAYLOAD);
}
return DATA;
}
- SpdyFrameType frame_type =
- SpdyConstants::ParseFrameType(protocol_version_, frame_type_field);
+ SpdyFrameType frame_type = ParseFrameType(frame_type_field);
- if (protocol_version_ == HTTP2) {
- if (!SpdyConstants::IsValidHTTP2FrameStreamId(current_frame_stream_id_,
- frame_type)) {
- DLOG(ERROR) << "The framer received an invalid streamID of "
- << current_frame_stream_id_ << " for a frame of type "
- << FrameTypeToString(frame_type);
- set_error(SPDY_INVALID_STREAM_ID);
- return frame_type;
- }
+ if (!IsValidHTTP2FrameStreamId(current_frame_stream_id_, frame_type)) {
+ DLOG(ERROR) << "The framer received an invalid streamID of "
+ << current_frame_stream_id_ << " for a frame of type "
+ << FrameTypeToString(frame_type);
+ set_error(SPDY_INVALID_STREAM_ID);
+ return frame_type;
+ }
- // Ensure that we see a CONTINUATION frame iff we expect to.
- if ((frame_type == CONTINUATION) != (expect_continuation_ != 0)) {
- if (expect_continuation_ != 0) {
- DLOG(ERROR) << "The framer was expecting to receive a CONTINUATION "
- << "frame, but instead received a frame of type "
- << FrameTypeToString(frame_type);
- } else {
- DLOG(ERROR) << "The framer received an unexpected CONTINUATION frame.";
- }
- set_error(SPDY_UNEXPECTED_FRAME);
- return frame_type;
+ // Ensure that we see a CONTINUATION frame iff we expect to.
+ if ((frame_type == CONTINUATION) != (expect_continuation_ != 0)) {
+ if (expect_continuation_ != 0) {
+ DLOG(ERROR) << "The framer was expecting to receive a CONTINUATION "
+ << "frame, but instead received a frame of type "
+ << FrameTypeToString(frame_type);
+ } else {
+ DLOG(ERROR) << "The framer received an unexpected CONTINUATION frame.";
}
+ set_error(SPDY_UNEXPECTED_FRAME);
+ return frame_type;
}
- if (protocol_version_ == HTTP2 &&
- payload_length_field > recv_frame_size_limit_) {
+ if (payload_length_field > recv_frame_size_limit_) {
set_error(SPDY_OVERSIZED_PAYLOAD);
}
@@ -874,85 +727,43 @@ size_t SpdyFramer::ProcessCommonHeader(const char* data, size_t len) {
current_frame_buffer_.len());
bool is_control_frame = false;
- int control_frame_type_field =
- SpdyConstants::DataFrameType(protocol_version_);
+ int control_frame_type_field = kDataFrameType;
// ProcessControlFrameHeader() will set current_frame_type_ to the
// correct value if this is a valid control frame.
current_frame_type_ = DATA;
- if (protocol_version_ == SPDY3) {
- uint16_t version = 0;
- bool successful_read = reader.ReadUInt16(&version);
- DCHECK(successful_read);
- is_control_frame = (version & kControlFlagMask) != 0;
- if (is_control_frame) {
- version &= ~kControlFlagMask;
- if (version != kSpdy3Version) {
- // Version does not match the version the framer was initialized with.
- DVLOG(1) << "Unsupported SPDY version " << version << " (expected "
- << kSpdy3Version << ")";
- set_error(SPDY_UNSUPPORTED_VERSION);
- return 0;
- }
- uint16_t control_frame_type_field_uint16;
- successful_read = reader.ReadUInt16(&control_frame_type_field_uint16);
- control_frame_type_field = control_frame_type_field_uint16;
- } else {
- reader.Rewind();
- successful_read = reader.ReadUInt31(&current_frame_stream_id_);
- }
- DCHECK(successful_read);
-
- successful_read = reader.ReadUInt8(&current_frame_flags_);
- DCHECK(successful_read);
+ uint32_t length_field = 0;
+ bool successful_read = reader.ReadUInt24(&length_field);
+ DCHECK(successful_read);
- uint32_t length_field = 0;
- successful_read = reader.ReadUInt24(&length_field);
- DCHECK(successful_read);
- remaining_data_length_ = length_field;
- current_frame_length_ = remaining_data_length_ + reader.GetBytesConsumed();
- } else {
- uint32_t length_field = 0;
- bool successful_read = reader.ReadUInt24(&length_field);
- DCHECK(successful_read);
-
- uint8_t control_frame_type_field_uint8;
- successful_read = reader.ReadUInt8(&control_frame_type_field_uint8);
- DCHECK(successful_read);
- // We check control_frame_type_field's validity in
- // ProcessControlFrameHeader().
- control_frame_type_field = control_frame_type_field_uint8;
- is_control_frame =
- control_frame_type_field !=
- SpdyConstants::SerializeFrameType(protocol_version_, DATA);
+ uint8_t control_frame_type_field_uint8;
+ successful_read = reader.ReadUInt8(&control_frame_type_field_uint8);
+ DCHECK(successful_read);
+ // We check control_frame_type_field's validity in
+ // ProcessControlFrameHeader().
+ control_frame_type_field = control_frame_type_field_uint8;
+ is_control_frame = control_frame_type_field != kDataFrameType;
- current_frame_length_ = length_field + GetFrameHeaderSize();
+ current_frame_length_ = length_field + GetFrameHeaderSize();
- successful_read = reader.ReadUInt8(&current_frame_flags_);
- DCHECK(successful_read);
+ successful_read = reader.ReadUInt8(&current_frame_flags_);
+ DCHECK(successful_read);
- successful_read = reader.ReadUInt31(&current_frame_stream_id_);
- DCHECK(successful_read);
+ successful_read = reader.ReadUInt31(&current_frame_stream_id_);
+ DCHECK(successful_read);
- remaining_data_length_ = current_frame_length_ - reader.GetBytesConsumed();
- }
+ remaining_data_length_ = current_frame_length_ - reader.GetBytesConsumed();
DCHECK_EQ(GetFrameHeaderSize(), reader.GetBytesConsumed());
DCHECK_EQ(current_frame_length_,
remaining_data_length_ + reader.GetBytesConsumed());
// This is just a sanity check for help debugging early frame errors.
- if (remaining_data_length_ > 1000000u) {
- // The strncmp for 5 is safe because we only hit this point if we
- // have kMinCommonHeader (8) bytes
- if (!syn_frame_processed_ &&
- strncmp(current_frame_buffer_.data(), "HTTP/", 5) == 0) {
- LOG(WARNING) << "Unexpected HTTP response to " << display_protocol_
- << " request";
- probable_http_response_ = true;
- } else {
- LOG(WARNING) << "Unexpectedly large frame. " << display_protocol_
- << " session is likely corrupt.";
- }
+ // The strncmp for 5 is safe because we only hit this point if we
+ // have kMinCommonHeader (8) bytes
+ if (remaining_data_length_ > 1000000u &&
+ strncmp(current_frame_buffer_.data(), "HTTP/", 5) == 0) {
+ LOG(WARNING) << "Unexpected HTTP response to HTTP2 request";
+ probable_http_response_ = true;
}
// If we're here, then we have the common header all received.
@@ -967,12 +778,7 @@ size_t SpdyFramer::ProcessCommonHeader(const char* data, size_t len) {
}
if (!is_control_frame) {
- uint8_t valid_data_flags = 0;
- if (protocol_version_ == SPDY3) {
- valid_data_flags = DATA_FLAG_FIN;
- } else {
- valid_data_flags = DATA_FLAG_FIN | DATA_FLAG_PADDED;
- }
+ uint8_t valid_data_flags = DATA_FLAG_FIN | DATA_FLAG_PADDED;
if (current_frame_flags_ & ~valid_data_flags) {
set_error(SPDY_INVALID_DATA_FRAME_FLAGS);
@@ -1003,23 +809,8 @@ void SpdyFramer::ProcessControlFrameHeader(int control_frame_type_field) {
// Do some sanity checking on the control frame sizes and flags.
switch (current_frame_type_) {
- case SYN_STREAM:
- if (current_frame_length_ < GetSynStreamMinimumSize()) {
- set_error(SPDY_INVALID_CONTROL_FRAME);
- } else if (current_frame_flags_ &
- ~(CONTROL_FLAG_FIN | CONTROL_FLAG_UNIDIRECTIONAL)) {
- set_error(SPDY_INVALID_CONTROL_FRAME_FLAGS);
- }
- break;
- case SYN_REPLY:
- if (current_frame_length_ < GetSynReplyMinimumSize()) {
- set_error(SPDY_INVALID_CONTROL_FRAME);
- } else if (current_frame_flags_ & ~CONTROL_FLAG_FIN) {
- set_error(SPDY_INVALID_CONTROL_FRAME_FLAGS);
- }
- break;
case RST_STREAM:
- if (current_frame_length_ != GetRstStreamMinimumSize()) {
+ if (current_frame_length_ != GetRstStreamSize()) {
set_error(SPDY_INVALID_CONTROL_FRAME_SIZE);
} else if (current_frame_flags_ != 0) {
VLOG(1) << "Undefined frame flags for RST_STREAM frame: " << hex
@@ -1030,26 +821,17 @@ void SpdyFramer::ProcessControlFrameHeader(int control_frame_type_field) {
case SETTINGS:
{
// Make sure that we have an integral number of 8-byte key/value pairs,
- // plus a 4-byte length field in SPDY3 and below.
- size_t values_prefix_size = (protocol_version_ == SPDY3 ? 4 : 0);
// Size of each key/value pair in bytes.
- size_t setting_size = SpdyConstants::GetSettingSize(protocol_version_);
+ int setting_size = 6;
if (current_frame_length_ < GetSettingsMinimumSize() ||
- (current_frame_length_ - GetFrameHeaderSize()) % setting_size !=
- values_prefix_size) {
+ (current_frame_length_ - GetFrameHeaderSize()) % setting_size != 0) {
DLOG(WARNING) << "Invalid length for SETTINGS frame: "
<< current_frame_length_;
set_error(SPDY_INVALID_CONTROL_FRAME_SIZE);
- } else if (protocol_version_ == SPDY3 &&
- current_frame_flags_ &
- ~SETTINGS_FLAG_CLEAR_PREVIOUSLY_PERSISTED_SETTINGS) {
- set_error(SPDY_INVALID_CONTROL_FRAME_FLAGS);
- } else if (protocol_version_ == HTTP2 &&
- current_frame_flags_ & SETTINGS_FLAG_ACK &&
+ } else if (current_frame_flags_ & SETTINGS_FLAG_ACK &&
current_frame_length_ > GetSettingsMinimumSize()) {
set_error(SPDY_INVALID_CONTROL_FRAME_SIZE);
- } else if (protocol_version_ == HTTP2 &&
- current_frame_flags_ & ~SETTINGS_FLAG_ACK) {
+ } else if (current_frame_flags_ & ~SETTINGS_FLAG_ACK) {
VLOG(1) << "Undefined frame flags for SETTINGS frame: " << hex
<< static_cast<int>(current_frame_flags_);
current_frame_flags_ &= SETTINGS_FLAG_ACK;
@@ -1060,12 +842,7 @@ void SpdyFramer::ProcessControlFrameHeader(int control_frame_type_field) {
if (current_frame_length_ != GetPingSize()) {
set_error(SPDY_INVALID_CONTROL_FRAME_SIZE);
} else {
- if (protocol_version_ == SPDY3 && current_frame_flags_ != 0) {
- VLOG(1) << "Undefined frame flags for PING frame: " << hex
- << static_cast<int>(current_frame_flags_);
- current_frame_flags_ = 0;
- } else if (protocol_version_ == HTTP2 &&
- current_frame_flags_ & ~PING_FLAG_ACK) {
+ if (current_frame_flags_ & ~PING_FLAG_ACK) {
VLOG(1) << "Undefined frame flags for PING frame: " << hex
<< static_cast<int>(current_frame_flags_);
current_frame_flags_ &= PING_FLAG_ACK;
@@ -1074,14 +851,10 @@ void SpdyFramer::ProcessControlFrameHeader(int control_frame_type_field) {
break;
case GOAWAY:
{
- // For SPDY/3, there are only mandatory fields and the header has a
- // fixed length. For HTTP/2, optional opaque data may be appended to the
- // GOAWAY frame, thus there is only a minimal length restriction.
- if ((protocol_version_ == SPDY3 &&
- current_frame_length_ != GetGoAwayMinimumSize()) ||
- (protocol_version_ == HTTP2 &&
- current_frame_length_ < GetGoAwayMinimumSize())) {
- set_error(SPDY_INVALID_CONTROL_FRAME);
+ // For HTTP/2, optional opaque data may be appended to the
+ // GOAWAY frame, thus there is only a minimal length restriction.
+ if (current_frame_length_ < GetGoAwayMinimumSize()) {
+ set_error(SPDY_INVALID_CONTROL_FRAME);
} else if (current_frame_flags_ != 0) {
VLOG(1) << "Undefined frame flags for GOAWAY frame: " << hex
<< static_cast<int>(current_frame_flags_);
@@ -1092,23 +865,16 @@ void SpdyFramer::ProcessControlFrameHeader(int control_frame_type_field) {
case HEADERS:
{
size_t min_size = GetHeadersMinimumSize();
- if (protocol_version_ == HTTP2 &&
- (current_frame_flags_ & HEADERS_FLAG_PRIORITY)) {
+ if (current_frame_flags_ & HEADERS_FLAG_PRIORITY) {
min_size += 4;
}
if (current_frame_length_ < min_size) {
// TODO(mlavan): check here for HEADERS with no payload?
// (not allowed in HTTP2)
set_error(SPDY_INVALID_CONTROL_FRAME);
- } else if (protocol_version_ == SPDY3 &&
- current_frame_flags_ & ~CONTROL_FLAG_FIN) {
- VLOG(1) << "Undefined frame flags for HEADERS frame: " << hex
- << static_cast<int>(current_frame_flags_);
- current_frame_flags_ &= CONTROL_FLAG_FIN;
- } else if (protocol_version_ == HTTP2 &&
- current_frame_flags_ &
- ~(CONTROL_FLAG_FIN | HEADERS_FLAG_PRIORITY |
- HEADERS_FLAG_END_HEADERS | HEADERS_FLAG_PADDED)) {
+ } else if (current_frame_flags_ &
+ ~(CONTROL_FLAG_FIN | HEADERS_FLAG_PRIORITY |
+ HEADERS_FLAG_END_HEADERS | HEADERS_FLAG_PADDED)) {
VLOG(1) << "Undefined frame flags for HEADERS frame: " << hex
<< static_cast<int>(current_frame_flags_);
current_frame_flags_ &=
@@ -1127,8 +893,7 @@ void SpdyFramer::ProcessControlFrameHeader(int control_frame_type_field) {
}
break;
case BLOCKED:
- if (protocol_version_ == SPDY3 ||
- current_frame_length_ != GetBlockedSize()) {
+ if (current_frame_length_ != GetBlockedSize()) {
set_error(SPDY_INVALID_CONTROL_FRAME);
} else if (current_frame_flags_ != 0) {
VLOG(1) << "Undefined frame flags for BLOCKED frame: " << hex
@@ -1139,14 +904,8 @@ void SpdyFramer::ProcessControlFrameHeader(int control_frame_type_field) {
case PUSH_PROMISE:
if (current_frame_length_ < GetPushPromiseMinimumSize()) {
set_error(SPDY_INVALID_CONTROL_FRAME);
- } else if (protocol_version_ == SPDY3 && current_frame_flags_ != 0) {
- VLOG(1) << "Undefined frame flags for PUSH_PROMISE frame: " << hex
- << static_cast<int>(current_frame_flags_);
- current_frame_flags_ = 0;
- } else if (protocol_version_ == HTTP2 &&
- current_frame_flags_ &
- ~(PUSH_PROMISE_FLAG_END_PUSH_PROMISE |
- HEADERS_FLAG_PADDED)) {
+ } else if (current_frame_flags_ &
+ ~(PUSH_PROMISE_FLAG_END_PUSH_PROMISE | HEADERS_FLAG_PADDED)) {
VLOG(1) << "Undefined frame flags for PUSH_PROMISE frame: " << hex
<< static_cast<int>(current_frame_flags_);
current_frame_flags_ &=
@@ -1154,8 +913,7 @@ void SpdyFramer::ProcessControlFrameHeader(int control_frame_type_field) {
}
break;
case CONTINUATION:
- if (protocol_version_ == SPDY3 ||
- current_frame_length_ < GetContinuationMinimumSize()) {
+ if (current_frame_length_ < GetContinuationMinimumSize()) {
set_error(SPDY_INVALID_CONTROL_FRAME);
} else if (current_frame_flags_ & ~HEADERS_FLAG_END_HEADERS) {
VLOG(1) << "Undefined frame flags for CONTINUATION frame: " << hex
@@ -1173,8 +931,7 @@ void SpdyFramer::ProcessControlFrameHeader(int control_frame_type_field) {
}
break;
case PRIORITY:
- if (protocol_version_ == SPDY3 ||
- current_frame_length_ != GetPrioritySize()) {
+ if (current_frame_length_ != GetPrioritySize()) {
set_error(SPDY_INVALID_CONTROL_FRAME_SIZE);
} else if (current_frame_flags_ != 0) {
VLOG(1) << "Undefined frame flags for PRIORITY frame: " << hex
@@ -1183,8 +940,7 @@ void SpdyFramer::ProcessControlFrameHeader(int control_frame_type_field) {
}
break;
default:
- LOG(WARNING) << "Valid " << display_protocol_
- << " control frame with unhandled type: "
+ LOG(WARNING) << "Valid control frame with unhandled type: "
<< current_frame_type_;
// This branch should be unreachable because of the frame type bounds
// check above. However, we DLOG(FATAL) here in an effort to painfully
@@ -1199,17 +955,6 @@ void SpdyFramer::ProcessControlFrameHeader(int control_frame_type_field) {
return;
}
- if (protocol_version_ == SPDY3 &&
- current_frame_length_ >
- kSpdyInitialFrameSizeLimit +
- SpdyConstants::GetFrameHeaderSize(protocol_version_)) {
- DLOG(WARNING) << "Received control frame of type " << current_frame_type_
- << " with way too big of a payload: "
- << current_frame_length_;
- set_error(SPDY_CONTROL_PAYLOAD_TOO_LARGE);
- return;
- }
-
if (current_frame_type_ == GOAWAY) {
CHANGE_STATE(SPDY_GOAWAY_FRAME_PAYLOAD);
return;
@@ -1227,34 +972,22 @@ void SpdyFramer::ProcessControlFrameHeader(int control_frame_type_field) {
// Determine the frame size without variable-length data.
int32_t frame_size_without_variable_data;
switch (current_frame_type_) {
- case SYN_STREAM:
- syn_frame_processed_ = true;
- frame_size_without_variable_data = GetSynStreamMinimumSize();
- break;
- case SYN_REPLY:
- syn_frame_processed_ = true;
- frame_size_without_variable_data = GetSynReplyMinimumSize();
- break;
case SETTINGS:
frame_size_without_variable_data = GetSettingsMinimumSize();
break;
case HEADERS:
frame_size_without_variable_data = GetHeadersMinimumSize();
- if (protocol_version_ == HTTP2) {
- if (current_frame_flags_ & HEADERS_FLAG_PADDED) {
- frame_size_without_variable_data += kPadLengthFieldSize;
- }
- if (current_frame_flags_ & HEADERS_FLAG_PRIORITY) {
+ if (current_frame_flags_ & HEADERS_FLAG_PADDED) {
+ frame_size_without_variable_data += kPadLengthFieldSize;
+ }
+ if (current_frame_flags_ & HEADERS_FLAG_PRIORITY) {
frame_size_without_variable_data +=
- kPriorityDependencyPayloadSize +
- kPriorityWeightPayloadSize;
- }
+ kPriorityDependencyPayloadSize + kPriorityWeightPayloadSize;
}
break;
case PUSH_PROMISE:
frame_size_without_variable_data = GetPushPromiseMinimumSize();
- if (protocol_version_ == HTTP2 &&
- current_frame_flags_ & PUSH_PROMISE_FLAG_PADDED) {
+ if (current_frame_flags_ & PUSH_PROMISE_FLAG_PADDED) {
frame_size_without_variable_data += kPadLengthFieldSize;
}
break;
@@ -1271,8 +1004,7 @@ void SpdyFramer::ProcessControlFrameHeader(int control_frame_type_field) {
// We should already be in an error state. Double-check.
DCHECK_EQ(SPDY_ERROR, state_);
if (state_ != SPDY_ERROR) {
- SPDY_BUG << display_protocol_
- << " control frame buffer too small for fixed-length frame.";
+ SPDY_BUG << "Control frame buffer too small for fixed-length frame.";
set_error(SPDY_CONTROL_PAYLOAD_TOO_LARGE);
}
return;
@@ -1310,7 +1042,6 @@ size_t SpdyFramer::UpdateCurrentFrameBuffer(const char** data, size_t* len,
}
size_t SpdyFramer::GetSerializedLength(
- const SpdyMajorVersion spdy_version,
const SpdyHeaderBlock* headers) {
const size_t num_name_value_pairs_size = sizeof(uint32_t);
const size_t length_of_name_size = num_name_value_pairs_size;
@@ -1326,179 +1057,6 @@ size_t SpdyFramer::GetSerializedLength(
return total_length;
}
-// TODO(phajdan.jr): Clean up after we no longer need
-// to workaround http://crbug.com/139744.
-#if !defined(USE_SYSTEM_ZLIB)
-
-// These constants are used by zlib to differentiate between normal data and
-// cookie data. Cookie data is handled specially by zlib when compressing.
-enum ZDataClass {
- // kZStandardData is compressed normally, save that it will never match
- // against any other class of data in the window.
- kZStandardData = Z_CLASS_STANDARD,
- // kZCookieData is compressed in its own Huffman blocks and only matches in
- // its entirety and only against other kZCookieData blocks. Any matches must
- // be preceeded by a kZStandardData byte, or a semicolon to prevent matching
- // a suffix. It's assumed that kZCookieData ends in a semicolon to prevent
- // prefix matches.
- kZCookieData = Z_CLASS_COOKIE,
- // kZHuffmanOnlyData is only Huffman compressed - no matches are performed
- // against the window.
- kZHuffmanOnlyData = Z_CLASS_HUFFMAN_ONLY,
-};
-
-// WriteZ writes |data| to the deflate context |out|. WriteZ will flush as
-// needed when switching between classes of data.
-static void WriteZ(const base::StringPiece& data,
- ZDataClass clas,
- z_stream* out) {
- int rv;
-
- // If we are switching from standard to non-standard data then we need to end
- // the current Huffman context to avoid it leaking between them.
- if (out->clas == kZStandardData &&
- clas != kZStandardData) {
- out->avail_in = 0;
- rv = deflate(out, Z_PARTIAL_FLUSH);
- DCHECK_EQ(Z_OK, rv);
- DCHECK_EQ(0u, out->avail_in);
- DCHECK_LT(0u, out->avail_out);
- }
-
- out->next_in = reinterpret_cast<Bytef*>(const_cast<char*>(data.data()));
- out->avail_in = data.size();
- out->clas = clas;
- if (clas == kZStandardData) {
- rv = deflate(out, Z_NO_FLUSH);
- } else {
- rv = deflate(out, Z_PARTIAL_FLUSH);
- }
- if (!data.empty()) {
- // If we didn't provide any data then zlib will return Z_BUF_ERROR.
- DCHECK_EQ(Z_OK, rv);
- }
- DCHECK_EQ(0u, out->avail_in);
- DCHECK_LT(0u, out->avail_out);
-}
-
-// WriteLengthZ writes |n| as a |length|-byte, big-endian number to |out|.
-static void WriteLengthZ(size_t n,
- unsigned length,
- ZDataClass clas,
- z_stream* out) {
- char buf[4];
- DCHECK_LE(length, sizeof(buf));
- for (unsigned i = 1; i <= length; i++) {
- buf[length - i] = static_cast<char>(n);
- n >>= 8;
- }
- WriteZ(base::StringPiece(buf, length), clas, out);
-}
-
-// WriteHeaderBlockToZ serialises |headers| to the deflate context |z| in a
-// manner that resists the length of the compressed data from compromising
-// cookie data.
-void SpdyFramer::WriteHeaderBlockToZ(const SpdyHeaderBlock* headers,
- z_stream* z) const {
- const size_t length_length = 4;
- WriteLengthZ(headers->size(), length_length, kZStandardData, z);
-
- SpdyHeaderBlock::const_iterator it;
- for (it = headers->begin(); it != headers->end(); ++it) {
- WriteLengthZ(it->first.size(), length_length, kZStandardData, z);
-
- std::string lowercase_key = base::ToLowerASCII(it->first);
- WriteZ(lowercase_key, kZStandardData, z);
-
- if (lowercase_key == "cookie") {
- // We require the cookie values (save for the last) to end with a
- // semicolon and (save for the first) to start with a space. This is
- // typically the format that we are given them in but we reserialize them
- // to be sure.
-
- std::vector<base::StringPiece> cookie_values;
- size_t cookie_length = 0;
- base::StringPiece cookie_data(it->second);
-
- for (;;) {
- while (!cookie_data.empty() &&
- (cookie_data[0] == ' ' || cookie_data[0] == '\t')) {
- cookie_data.remove_prefix(1);
- }
- if (cookie_data.empty())
- break;
-
- size_t i;
- for (i = 0; i < cookie_data.size(); i++) {
- if (cookie_data[i] == ';')
- break;
- }
- if (i < cookie_data.size()) {
- if (!IsCookieEmpty(cookie_data.substr(0, i))) {
- cookie_values.push_back(cookie_data.substr(0, i));
- cookie_length += i + 2 /* semicolon and space */;
- }
- cookie_data.remove_prefix(i + 1);
- } else {
- if (!IsCookieEmpty(cookie_data)) {
- cookie_values.push_back(cookie_data);
- cookie_length += cookie_data.size();
- } else if (cookie_length > 2) {
- cookie_length -= 2 /* compensate for previously added length */;
- }
- cookie_data.remove_prefix(i);
- }
- }
-
- WriteLengthZ(cookie_length, length_length, kZStandardData, z);
- for (size_t i = 0; i < cookie_values.size(); i++) {
- std::string cookie;
- // Since zlib will only back-reference complete cookies, a cookie that
- // is currently last (and so doesn't have a trailing semicolon) won't
- // match if it's later in a non-final position. The same is true of
- // the first cookie.
- if (i == 0 && cookie_values.size() == 1) {
- cookie = cookie_values[i].as_string();
- } else if (i == 0) {
- cookie = cookie_values[i].as_string() + ";";
- } else if (i < cookie_values.size() - 1) {
- cookie = " " + cookie_values[i].as_string() + ";";
- } else {
- cookie = " " + cookie_values[i].as_string();
- }
- WriteZ(cookie, kZCookieData, z);
- }
- } else if (lowercase_key == "accept" ||
- lowercase_key == "accept-charset" ||
- lowercase_key == "accept-encoding" ||
- lowercase_key == "accept-language" ||
- lowercase_key == "host" ||
- lowercase_key == "version" ||
- lowercase_key == "method" ||
- lowercase_key == "scheme" ||
- lowercase_key == ":host" ||
- lowercase_key == ":version" ||
- lowercase_key == ":method" ||
- lowercase_key == ":scheme" ||
- lowercase_key == "user-agent") {
- WriteLengthZ(it->second.size(), length_length, kZStandardData, z);
- WriteZ(it->second, kZStandardData, z);
- } else {
- // Non-whitelisted headers are Huffman compressed in their own block, but
- // don't match against the window.
- WriteLengthZ(it->second.size(), length_length, kZStandardData, z);
- WriteZ(it->second, kZHuffmanOnlyData, z);
- }
- }
-
- z->avail_in = 0;
- int rv = deflate(z, Z_SYNC_FLUSH);
- DCHECK_EQ(Z_OK, rv);
- z->clas = kZStandardData;
-}
-
-#endif // !defined(USE_SYSTEM_ZLIB)
-
size_t SpdyFramer::ProcessControlFrameBeforeHeaderBlock(const char* data,
size_t len) {
DCHECK_EQ(SPDY_CONTROL_FRAME_BEFORE_HEADER_BLOCK, state_);
@@ -1517,67 +1075,19 @@ size_t SpdyFramer::ProcessControlFrameBeforeHeaderBlock(const char* data,
reader.Seek(GetFrameHeaderSize()); // Seek past frame header.
switch (current_frame_type_) {
- case SYN_STREAM:
- {
- DCHECK_EQ(SPDY3, protocol_version_);
- bool successful_read = true;
- successful_read = reader.ReadUInt31(&current_frame_stream_id_);
- DCHECK(successful_read);
- if (current_frame_stream_id_ == 0) {
- set_error(SPDY_INVALID_CONTROL_FRAME);
- return original_len - len;
- }
-
- SpdyStreamId associated_to_stream_id = kInvalidStream;
- successful_read = reader.ReadUInt31(&associated_to_stream_id);
- DCHECK(successful_read);
-
- SpdyPriority priority = 0;
- successful_read = reader.ReadUInt8(&priority);
- DCHECK(successful_read);
- priority = priority >> 5;
-
- // Seek past unused byte.
- reader.Seek(1);
-
- DCHECK(reader.IsDoneReading());
- if (debug_visitor_) {
- debug_visitor_->OnReceiveCompressedFrame(
- current_frame_stream_id_,
- current_frame_type_,
- current_frame_length_);
- }
- visitor_->OnSynStream(
- current_frame_stream_id_,
- associated_to_stream_id,
- priority,
- (current_frame_flags_ & CONTROL_FLAG_FIN) != 0,
- (current_frame_flags_ & CONTROL_FLAG_UNIDIRECTIONAL) != 0);
- }
- break;
- case SYN_REPLY:
- DCHECK_EQ(SPDY3, protocol_version_);
- /* FALLTHROUGH */
case HEADERS:
- // SYN_REPLY and HEADERS are the same, save for the visitor call.
{
bool successful_read = true;
- if (protocol_version_ == SPDY3) {
- successful_read = reader.ReadUInt31(&current_frame_stream_id_);
- DCHECK(successful_read);
- }
if (current_frame_stream_id_ == 0) {
set_error(SPDY_INVALID_CONTROL_FRAME);
return original_len - len;
}
- if (protocol_version_ == HTTP2 &&
- !(current_frame_flags_ & HEADERS_FLAG_END_HEADERS) &&
+ if (!(current_frame_flags_ & HEADERS_FLAG_END_HEADERS) &&
current_frame_type_ == HEADERS) {
expect_continuation_ = current_frame_stream_id_;
end_stream_when_done_ = current_frame_flags_ & CONTROL_FLAG_FIN;
}
- if (protocol_version_ == HTTP2 &&
- current_frame_flags_ & HEADERS_FLAG_PADDED) {
+ if (current_frame_flags_ & HEADERS_FLAG_PADDED) {
uint8_t pad_payload_len = 0;
DCHECK_EQ(remaining_padding_payload_length_, 0u);
successful_read = reader.ReadUInt8(&pad_payload_len);
@@ -1589,7 +1099,7 @@ size_t SpdyFramer::ProcessControlFrameBeforeHeaderBlock(const char* data,
int weight = 0;
uint32_t parent_stream_id = 0;
bool exclusive = false;
- if (protocol_version_ == HTTP2 && has_priority) {
+ if (has_priority) {
uint32_t stream_dependency;
successful_read = reader.ReadUInt32(&stream_dependency);
DCHECK(successful_read);
@@ -1606,35 +1116,26 @@ size_t SpdyFramer::ProcessControlFrameBeforeHeaderBlock(const char* data,
}
DCHECK(reader.IsDoneReading());
if (debug_visitor_) {
- debug_visitor_->OnReceiveCompressedFrame(
- current_frame_stream_id_,
- current_frame_type_,
- current_frame_length_);
- }
- if (current_frame_type_ == SYN_REPLY) {
- visitor_->OnSynReply(
- current_frame_stream_id_,
- (current_frame_flags_ & CONTROL_FLAG_FIN) != 0);
- } else {
- visitor_->OnHeaders(
- current_frame_stream_id_,
- (current_frame_flags_ & HEADERS_FLAG_PRIORITY) != 0, weight,
- parent_stream_id, exclusive,
- (current_frame_flags_ & CONTROL_FLAG_FIN) != 0,
- expect_continuation_ == 0);
+ debug_visitor_->OnReceiveCompressedFrame(current_frame_stream_id_,
+ current_frame_type_,
+ current_frame_length_);
}
+ visitor_->OnHeaders(
+ current_frame_stream_id_,
+ (current_frame_flags_ & HEADERS_FLAG_PRIORITY) != 0, weight,
+ parent_stream_id, exclusive,
+ (current_frame_flags_ & CONTROL_FLAG_FIN) != 0,
+ expect_continuation_ == 0);
}
break;
case PUSH_PROMISE:
{
- DCHECK_EQ(HTTP2, protocol_version_);
if (current_frame_stream_id_ == 0) {
set_error(SPDY_INVALID_CONTROL_FRAME);
return original_len - len;
}
bool successful_read = true;
- if (protocol_version_ == HTTP2 &&
- current_frame_flags_ & PUSH_PROMISE_FLAG_PADDED) {
+ if (current_frame_flags_ & PUSH_PROMISE_FLAG_PADDED) {
DCHECK_EQ(remaining_padding_payload_length_, 0u);
uint8_t pad_payload_len = 0;
successful_read = reader.ReadUInt8(&pad_payload_len);
@@ -1707,12 +1208,7 @@ size_t SpdyFramer::ProcessControlFrameBeforeHeaderBlock(const char* data,
set_error(SPDY_INTERNAL_FRAMER_ERROR);
return original_len - len;
}
- if (protocol_version() == SPDY3) {
- header_parser_.reset(
- new SpdyHeadersBlockParser(protocol_version(), header_handler_));
- } else {
- GetHpackDecoder()->HandleControlFrameHeadersStart(header_handler_);
- }
+ GetHpackDecoder()->HandleControlFrameHeadersStart(header_handler_);
}
CHANGE_STATE(SPDY_CONTROL_FRAME_HEADER_BLOCK);
}
@@ -1721,18 +1217,13 @@ size_t SpdyFramer::ProcessControlFrameBeforeHeaderBlock(const char* data,
// Does not buffer the control payload. Instead, either passes directly to the
// visitor or decompresses and then passes directly to the visitor, via
-// IncrementallyDeliverControlFrameHeaderData() or
-// IncrementallyDecompressControlFrameHeaderData() respectively.
+// IncrementallyDeliverControlFrameHeaderData()
size_t SpdyFramer::ProcessControlFrameHeaderBlock(const char* data,
- size_t data_len,
- bool is_hpack_header_block) {
+ size_t data_len) {
DCHECK_EQ(SPDY_CONTROL_FRAME_HEADER_BLOCK, state_);
bool processed_successfully = true;
- if (current_frame_type_ != SYN_STREAM &&
- current_frame_type_ != SYN_REPLY &&
- current_frame_type_ != HEADERS &&
- current_frame_type_ != PUSH_PROMISE &&
+ if (current_frame_type_ != HEADERS && current_frame_type_ != PUSH_PROMISE &&
current_frame_type_ != CONTINUATION) {
SPDY_BUG << "Unhandled frame type in ProcessControlFrameHeaderBlock.";
}
@@ -1744,21 +1235,10 @@ size_t SpdyFramer::ProcessControlFrameHeaderBlock(const char* data,
size_t process_bytes = std::min(
data_len, remaining_data_length_ - remaining_padding_payload_length_);
- if (is_hpack_header_block) {
- if (!GetHpackDecoder()->HandleControlFrameHeadersData(data,
- process_bytes)) {
- // TODO(jgraettinger): Finer-grained HPACK error codes.
- set_error(SPDY_DECOMPRESS_FAILURE);
- processed_successfully = false;
- }
- } else if (process_bytes > 0) {
- if (protocol_version_ == SPDY3 && enable_compression_) {
- processed_successfully = IncrementallyDecompressControlFrameHeaderData(
- current_frame_stream_id_, data, process_bytes);
- } else {
- processed_successfully = IncrementallyDeliverControlFrameHeaderData(
- current_frame_stream_id_, data, process_bytes);
- }
+ if (!GetHpackDecoder()->HandleControlFrameHeadersData(data, process_bytes)) {
+ // TODO(jgraettinger): Finer-grained HPACK error codes.
+ set_error(SPDY_DECOMPRESS_FAILURE);
+ processed_successfully = false;
}
remaining_data_length_ -= process_bytes;
@@ -1766,23 +1246,16 @@ size_t SpdyFramer::ProcessControlFrameHeaderBlock(const char* data,
if (remaining_data_length_ == remaining_padding_payload_length_ &&
processed_successfully) {
if (expect_continuation_ == 0) {
- if (is_hpack_header_block) {
- size_t compressed_len = 0;
- if (GetHpackDecoder()->HandleControlFrameHeadersComplete(
- &compressed_len)) {
- visitor_->OnHeaderFrameEnd(current_frame_stream_id_, true);
- if (state_ == SPDY_ERROR) {
- return data_len;
- }
- } else {
- set_error(SPDY_DECOMPRESS_FAILURE);
- processed_successfully = false;
- }
- } else {
+ size_t compressed_len = 0;
+ if (GetHpackDecoder()->HandleControlFrameHeadersComplete(
+ &compressed_len)) {
visitor_->OnHeaderFrameEnd(current_frame_stream_id_, true);
if (state_ == SPDY_ERROR) {
return data_len;
}
+ } else {
+ set_error(SPDY_DECOMPRESS_FAILURE);
+ processed_successfully = false;
}
}
if (processed_successfully) {
@@ -1811,8 +1284,7 @@ size_t SpdyFramer::ProcessSettingsFrameHeader(const char* data, size_t len) {
remaining_data_length_ -= bytes_read;
}
if (remaining_control_header_ == 0) {
- if (protocol_version_ == HTTP2 &&
- current_frame_flags_ & SETTINGS_FLAG_ACK) {
+ if (current_frame_flags_ & SETTINGS_FLAG_ACK) {
visitor_->OnSettingsAck();
CHANGE_STATE(SPDY_FRAME_COMPLETE);
} else {
@@ -1831,7 +1303,7 @@ size_t SpdyFramer::ProcessSettingsFramePayload(const char* data,
size_t unprocessed_bytes = std::min(data_len, remaining_data_length_);
size_t processed_bytes = 0;
- size_t setting_size = SpdyConstants::GetSettingSize(protocol_version_);
+ size_t setting_size = 6;
// Loop over our incoming data.
while (unprocessed_bytes > 0) {
@@ -1877,60 +1349,22 @@ size_t SpdyFramer::ProcessSettingsFramePayload(const char* data,
}
bool SpdyFramer::ProcessSetting(const char* data) {
- int id_field;
- SpdySettingsIds id;
- uint8_t flags = 0;
- uint32_t value;
-
// Extract fields.
// Maintain behavior of old SPDY 2 bug with byte ordering of flags/id.
- if (protocol_version_ == SPDY3) {
- const uint32_t id_and_flags_wire =
- *(reinterpret_cast<const uint32_t*>(data));
- SettingsFlagsAndId id_and_flags = SettingsFlagsAndId::FromWireFormat(
- protocol_version_, id_and_flags_wire);
- id_field = id_and_flags.id();
- flags = id_and_flags.flags();
- value = base::NetToHost32(*(reinterpret_cast<const uint32_t*>(data + 4)));
- } else {
- id_field = base::NetToHost16(*(reinterpret_cast<const uint16_t*>(data)));
- value = base::NetToHost32(*(reinterpret_cast<const uint32_t*>(data + 2)));
- }
+ int id_field = base::NetToHost16(*(reinterpret_cast<const uint16_t*>(data)));
+ int32_t value =
+ base::NetToHost32(*(reinterpret_cast<const uint32_t*>(data + 2)));
// Validate id.
- if (!SpdyConstants::IsValidSettingId(protocol_version_, id_field)) {
+ SpdySettingsIds setting_id;
+ if (!ParseSettingsId(id_field, &setting_id)) {
DLOG(WARNING) << "Unknown SETTINGS ID: " << id_field;
- if (protocol_version_ == SPDY3) {
- return false;
- } else {
- // In HTTP2 we ignore unknown settings for extensibility.
- return true;
- }
- }
- id = SpdyConstants::ParseSettingId(protocol_version_, id_field);
-
- if (protocol_version_ == SPDY3) {
- // Detect duplicates.
- if (id <= settings_scratch_.last_setting_id) {
- DLOG(WARNING) << "Duplicate entry or invalid ordering for id " << id
- << " in " << display_protocol_ << " SETTINGS frame "
- << "(last setting id was "
- << settings_scratch_.last_setting_id << ").";
- return false;
- }
- settings_scratch_.last_setting_id = id;
-
- // Validate flags.
- uint8_t kFlagsMask = SETTINGS_FLAG_PLEASE_PERSIST | SETTINGS_FLAG_PERSISTED;
- if ((flags & ~(kFlagsMask)) != 0) {
- DLOG(WARNING) << "Unknown SETTINGS flags provided for id " << id << ": "
- << flags;
- return false;
- }
+ // Ignore unknown settings for extensibility.
+ return true;
}
// Validation succeeded. Pass on to visitor.
- visitor_->OnSetting(id, flags, value);
+ visitor_->OnSetting(setting_id, value);
return true;
}
@@ -1948,16 +1382,9 @@ size_t SpdyFramer::ProcessControlFramePayload(const char* data, size_t len) {
switch (current_frame_type_) {
case PING: {
SpdyPingId id = 0;
- bool is_ack = protocol_version_ == HTTP2 &&
- (current_frame_flags_ & PING_FLAG_ACK);
+ bool is_ack = current_frame_flags_ & PING_FLAG_ACK;
bool successful_read = true;
- if (protocol_version_ == SPDY3) {
- uint32_t id32 = 0;
- successful_read = reader.ReadUInt32(&id32);
- id = id32;
- } else {
- successful_read = reader.ReadUInt64(&id);
- }
+ successful_read = reader.ReadUInt64(&id);
DCHECK(successful_read);
DCHECK(reader.IsDoneReading());
visitor_->OnPing(id, is_ack);
@@ -1966,10 +1393,6 @@ size_t SpdyFramer::ProcessControlFramePayload(const char* data, size_t len) {
case WINDOW_UPDATE: {
uint32_t delta_window_size = 0;
bool successful_read = true;
- if (protocol_version_ == SPDY3) {
- successful_read = reader.ReadUInt31(&current_frame_stream_id_);
- DCHECK(successful_read);
- }
successful_read = reader.ReadUInt32(&delta_window_size);
DCHECK(successful_read);
DCHECK(reader.IsDoneReading());
@@ -1978,13 +1401,11 @@ size_t SpdyFramer::ProcessControlFramePayload(const char* data, size_t len) {
}
break;
case BLOCKED: {
- DCHECK_EQ(HTTP2, protocol_version_);
DCHECK(reader.IsDoneReading());
visitor_->OnBlocked(current_frame_stream_id_);
}
break;
case PRIORITY: {
- DCHECK_EQ(HTTP2, protocol_version_);
uint32_t stream_dependency;
uint32_t parent_stream_id;
bool exclusive;
@@ -2042,19 +1463,16 @@ size_t SpdyFramer::ProcessGoAwayFramePayload(const char* data, size_t len) {
DCHECK(successful_read);
// Parse status code.
- SpdyGoAwayStatus status = GOAWAY_OK;
- uint32_t status_raw = GOAWAY_OK;
+ SpdyGoAwayStatus status = GOAWAY_NO_ERROR;
+ uint32_t status_raw = GOAWAY_NO_ERROR;
successful_read = reader.ReadUInt32(&status_raw);
DCHECK(successful_read);
- if (SpdyConstants::IsValidGoAwayStatus(protocol_version_, status_raw)) {
- status =
- SpdyConstants::ParseGoAwayStatus(protocol_version_, status_raw);
+ if (IsValidGoAwayStatus(status_raw)) {
+ status = ParseGoAwayStatus(status_raw);
} else {
- if (protocol_version_ == HTTP2) {
- // Treat unrecognized status codes as INTERNAL_ERROR as
- // recommended by the HTTP/2 spec.
- status = GOAWAY_INTERNAL_ERROR;
- }
+ // Treat unrecognized status codes as INTERNAL_ERROR as
+ // recommended by the HTTP/2 spec.
+ status = GOAWAY_INTERNAL_ERROR;
}
// Finished parsing the GOAWAY header, call frame handler.
visitor_->OnGoAway(current_frame_stream_id_, status);
@@ -2089,7 +1507,7 @@ size_t SpdyFramer::ProcessRstStreamFramePayload(const char* data, size_t len) {
// Check if we had already read enough bytes to parse the fixed-length portion
// of the RST_STREAM frame.
- const size_t header_size = GetRstStreamMinimumSize();
+ const size_t header_size = GetRstStreamSize();
size_t unread_header_bytes = header_size - current_frame_buffer_.len();
bool already_parsed_header = (unread_header_bytes == 0);
if (!already_parsed_header) {
@@ -2102,25 +1520,17 @@ size_t SpdyFramer::ProcessRstStreamFramePayload(const char* data, size_t len) {
SpdyFrameReader reader(current_frame_buffer_.data(),
current_frame_buffer_.len());
reader.Seek(GetFrameHeaderSize()); // Seek past frame header.
- if (protocol_version_ == SPDY3) {
- bool successful_read = reader.ReadUInt31(&current_frame_stream_id_);
- DCHECK(successful_read);
- }
SpdyRstStreamStatus status = RST_STREAM_NO_ERROR;
uint32_t status_raw = status;
bool successful_read = reader.ReadUInt32(&status_raw);
DCHECK(successful_read);
- if (SpdyConstants::IsValidRstStreamStatus(protocol_version_,
- status_raw)) {
- status =
- SpdyConstants::ParseRstStreamStatus(protocol_version_, status_raw);
+ if (IsValidRstStreamStatus(status_raw)) {
+ status = ParseRstStreamStatus(status_raw);
} else {
- if (protocol_version_ == HTTP2) {
- // Treat unrecognized status codes as INTERNAL_ERROR as
- // recommended by the HTTP/2 spec.
- status = RST_STREAM_INTERNAL_ERROR;
- }
+ // Treat unrecognized status codes as INTERNAL_ERROR as
+ // recommended by the HTTP/2 spec.
+ status = RST_STREAM_INTERNAL_ERROR;
}
// Finished parsing the RST_STREAM header, call frame handler.
visitor_->OnRstStream(current_frame_stream_id_, status);
@@ -2229,8 +1639,6 @@ size_t SpdyFramer::ProcessFramePadding(const char* data, size_t len) {
DCHECK_EQ(remaining_padding_payload_length_, remaining_data_length_);
size_t amount_to_discard = std::min(remaining_padding_payload_length_, len);
if (current_frame_type_ == DATA && amount_to_discard > 0) {
- SPDY_BUG_IF(protocol_version_ == SPDY3)
- << "Padding invalid for SPDY version " << protocol_version_;
visitor_->OnStreamPadding(current_frame_stream_id_, amount_to_discard);
}
data += amount_to_discard;
@@ -2316,7 +1724,7 @@ bool SpdyFramer::ParseHeaderBlockInBuffer(const char* header_data,
const char* begin = temp.data();
const char* end = begin;
std::advance(end, temp.size());
- if (protocol_version_ == HTTP2 && std::any_of(begin, end, isupper)) {
+ if (std::any_of(begin, end, isupper)) {
DVLOG(1) << "Malformed header: Header name " << temp
<< " contains upper-case characters.";
return false;
@@ -2359,8 +1767,8 @@ SpdyFramer::SpdyHeaderFrameIterator::SpdyHeaderFrameIterator(
debug_total_size_(0),
is_first_frame_(true),
has_next_frame_(true) {
- encoder_ = framer_->GetHpackEncoder()->EncodeHeaderSet(
- headers_ir_->header_block(), framer_->enable_compression_);
+ encoder_ =
+ framer_->GetHpackEncoder()->EncodeHeaderSet(headers_ir_->header_block());
}
SpdyFramer::SpdyHeaderFrameIterator::~SpdyHeaderFrameIterator() {}
@@ -2383,11 +1791,12 @@ SpdySerializedFrame SpdyFramer::SpdyHeaderFrameIterator::NextFrame() {
debug_total_size_ += size_without_block;
debug_total_size_ += encoding->size();
if (!has_next_frame_) {
+ // TODO(birenroy) are these (here and below) still necessary?
// HTTP2 uses HPACK for header compression. However, continue to
// use GetSerializedLength() for an apples-to-apples comparision of
// compression performance between HPACK and SPDY w/ deflate.
size_t debug_payload_len =
- framer_->GetSerializedLength(HTTP2, &headers_ir_->header_block());
+ framer_->GetSerializedLength(&headers_ir_->header_block());
framer_->debug_visitor_->OnSendCompressedFrame(headers_ir_->stream_id(),
HEADERS, debug_payload_len,
debug_total_size_);
@@ -2412,36 +1821,27 @@ SpdySerializedFrame SpdyFramer::SerializeData(const SpdyDataIR& data_ir) const {
flags = DATA_FLAG_FIN;
}
- if (protocol_version_ == SPDY3) {
- const size_t size = GetDataFrameMinimumSize() + data_ir.data_len();
- SpdyFrameBuilder builder(size, protocol_version_);
- builder.WriteDataFrameHeader(*this, data_ir.stream_id(), flags);
- builder.WriteBytes(data_ir.data(), data_ir.data_len());
- DCHECK_EQ(size, builder.length());
- return builder.take();
- } else {
- int num_padding_fields = 0;
- if (data_ir.padded()) {
- flags |= DATA_FLAG_PADDED;
- ++num_padding_fields;
- }
+ int num_padding_fields = 0;
+ if (data_ir.padded()) {
+ flags |= DATA_FLAG_PADDED;
+ ++num_padding_fields;
+ }
- const size_t size_with_padding = num_padding_fields + data_ir.data_len() +
- data_ir.padding_payload_len() +
- GetDataFrameMinimumSize();
- SpdyFrameBuilder builder(size_with_padding, protocol_version_);
- builder.WriteDataFrameHeader(*this, data_ir.stream_id(), flags);
- if (data_ir.padded()) {
- builder.WriteUInt8(data_ir.padding_payload_len() & 0xff);
- }
- builder.WriteBytes(data_ir.data(), data_ir.data_len());
- if (data_ir.padding_payload_len() > 0) {
- string padding(data_ir.padding_payload_len(), 0);
- builder.WriteBytes(padding.data(), padding.length());
- }
- DCHECK_EQ(size_with_padding, builder.length());
- return builder.take();
+ const size_t size_with_padding = num_padding_fields + data_ir.data_len() +
+ data_ir.padding_payload_len() +
+ GetDataFrameMinimumSize();
+ SpdyFrameBuilder builder(size_with_padding);
+ builder.BeginNewFrame(*this, DATA, flags, data_ir.stream_id());
+ if (data_ir.padded()) {
+ builder.WriteUInt8(data_ir.padding_payload_len() & 0xff);
+ }
+ builder.WriteBytes(data_ir.data(), data_ir.data_len());
+ if (data_ir.padding_payload_len() > 0) {
+ string padding(data_ir.padding_payload_len(), 0);
+ builder.WriteBytes(padding.data(), padding.length());
}
+ DCHECK_EQ(size_with_padding, builder.length());
+ return builder.take();
}
SpdySerializedFrame SpdyFramer::SerializeDataFrameHeaderWithPaddingLengthField(
@@ -2453,122 +1853,40 @@ SpdySerializedFrame SpdyFramer::SerializeDataFrameHeaderWithPaddingLengthField(
size_t frame_size = GetDataFrameMinimumSize();
size_t num_padding_fields = 0;
- if (protocol_version_ == HTTP2) {
- if (data_ir.padded()) {
- flags |= DATA_FLAG_PADDED;
- ++num_padding_fields;
- }
+ if (data_ir.padded()) {
+ flags |= DATA_FLAG_PADDED;
+ ++num_padding_fields;
frame_size += num_padding_fields;
}
- SpdyFrameBuilder builder(frame_size, protocol_version_);
- builder.WriteDataFrameHeader(*this, data_ir.stream_id(), flags);
- if (protocol_version_ == HTTP2) {
+ SpdyFrameBuilder builder(frame_size);
+ if (!skip_rewritelength_) {
+ builder.BeginNewFrame(*this, DATA, flags, data_ir.stream_id());
if (data_ir.padded()) {
builder.WriteUInt8(data_ir.padding_payload_len() & 0xff);
}
builder.OverwriteLength(*this, num_padding_fields + data_ir.data_len() +
data_ir.padding_payload_len());
} else {
- builder.OverwriteLength(*this, data_ir.data_len());
+ builder.BeginNewFrame(*this, DATA, flags, data_ir.stream_id(),
+ num_padding_fields + data_ir.data_len() +
+ data_ir.padding_payload_len());
+ if (data_ir.padded()) {
+ builder.WriteUInt8(data_ir.padding_payload_len() & 0xff);
+ }
}
DCHECK_EQ(frame_size, builder.length());
return builder.take();
}
-SpdySerializedFrame SpdyFramer::SerializeSynStream(
- const SpdySynStreamIR& syn_stream) {
- DCHECK_EQ(SPDY3, protocol_version_);
- uint8_t flags = 0;
- if (syn_stream.fin()) {
- flags |= CONTROL_FLAG_FIN;
- }
- if (syn_stream.unidirectional()) {
- flags |= CONTROL_FLAG_UNIDIRECTIONAL;
- }
-
- // Sanitize priority.
- uint8_t priority = syn_stream.priority();
- if (priority > GetLowestPriority()) {
- SPDY_BUG << "Priority out-of-bounds.";
- priority = GetLowestPriority();
- }
-
- // The size of this frame, including variable-length header block.
- size_t size = GetSynStreamMinimumSize() +
- GetSerializedLength(syn_stream.header_block());
-
- SpdyFrameBuilder builder(size, protocol_version_);
- builder.WriteControlFrameHeader(*this, SYN_STREAM, flags);
- builder.WriteUInt32(syn_stream.stream_id());
- builder.WriteUInt32(syn_stream.associated_to_stream_id());
- builder.WriteUInt8(priority << 5);
- builder.WriteUInt8(0); // Unused byte.
- DCHECK_EQ(GetSynStreamMinimumSize(), builder.length());
- SerializeHeaderBlock(&builder, syn_stream);
-
- if (debug_visitor_) {
- const size_t payload_len =
- GetSerializedLength(protocol_version_, &(syn_stream.header_block()));
- debug_visitor_->OnSendCompressedFrame(syn_stream.stream_id(),
- SYN_STREAM,
- payload_len,
- builder.length());
- }
-
- return builder.take();
-}
-
-SpdySerializedFrame SpdyFramer::SerializeSynReply(
- const SpdySynReplyIR& syn_reply) {
- DCHECK_EQ(SPDY3, protocol_version_);
- uint8_t flags = 0;
- if (syn_reply.fin()) {
- flags |= CONTROL_FLAG_FIN;
- }
-
- // The size of this frame, including variable-length header block.
- const size_t size =
- GetSynReplyMinimumSize() + GetSerializedLength(syn_reply.header_block());
-
- SpdyFrameBuilder builder(size, protocol_version_);
- builder.WriteControlFrameHeader(*this, SYN_REPLY, flags);
- builder.WriteUInt32(syn_reply.stream_id());
- DCHECK_EQ(GetSynReplyMinimumSize(), builder.length());
- SerializeHeaderBlock(&builder, syn_reply);
-
- if (debug_visitor_) {
- const size_t payload_len =
- GetSerializedLength(protocol_version_, &(syn_reply.header_block()));
- debug_visitor_->OnSendCompressedFrame(syn_reply.stream_id(),
- SYN_REPLY,
- payload_len,
- builder.length());
- }
-
- return builder.take();
-}
-
SpdySerializedFrame SpdyFramer::SerializeRstStream(
const SpdyRstStreamIR& rst_stream) const {
- // TODO(jgraettinger): For now, Chromium will support parsing RST_STREAM
- // payloads, but will not emit them. This is used for draft HTTP/2,
- // which doesn't currently include RST_STREAM payloads. GFE flags have been
- // commented but left in place to simplify future patching.
- // Compute the output buffer size, taking opaque data into account.
- size_t expected_length = GetRstStreamMinimumSize();
- SpdyFrameBuilder builder(expected_length, protocol_version_);
-
- // Serialize the RST_STREAM frame.
- if (protocol_version_ == SPDY3) {
- builder.WriteControlFrameHeader(*this, RST_STREAM, 0);
- builder.WriteUInt32(rst_stream.stream_id());
- } else {
- builder.BeginNewFrame(*this, RST_STREAM, 0, rst_stream.stream_id());
- }
+ size_t expected_length = GetRstStreamSize();
+ SpdyFrameBuilder builder(expected_length);
+
+ builder.BeginNewFrame(*this, RST_STREAM, 0, rst_stream.stream_id());
- builder.WriteUInt32(SpdyConstants::SerializeRstStreamStatus(
- protocol_version_, rst_stream.status()));
+ builder.WriteUInt32(SerializeRstStreamStatus(rst_stream.status()));
DCHECK_EQ(expected_length, builder.length());
return builder.take();
@@ -2578,77 +1896,43 @@ SpdySerializedFrame SpdyFramer::SerializeSettings(
const SpdySettingsIR& settings) const {
uint8_t flags = 0;
- if (protocol_version_ == SPDY3) {
- if (settings.clear_settings()) {
- flags |= SETTINGS_FLAG_CLEAR_PREVIOUSLY_PERSISTED_SETTINGS;
- }
- } else {
- if (settings.is_ack()) {
- flags |= SETTINGS_FLAG_ACK;
- }
+ if (settings.is_ack()) {
+ flags |= SETTINGS_FLAG_ACK;
}
- const SpdySettingsIR::ValueMap* values = &(settings.values());
+ const SettingsMap* values = &(settings.values());
- size_t setting_size = SpdyConstants::GetSettingSize(protocol_version_);
+ int setting_size = 6;
// Size, in bytes, of this SETTINGS frame.
const size_t size = GetSettingsMinimumSize() +
(values->size() * setting_size);
- SpdyFrameBuilder builder(size, protocol_version_);
- if (protocol_version_ == SPDY3) {
- builder.WriteControlFrameHeader(*this, SETTINGS, flags);
- } else {
- builder.BeginNewFrame(*this, SETTINGS, flags, 0);
- }
+ SpdyFrameBuilder builder(size);
+ builder.BeginNewFrame(*this, SETTINGS, flags, 0);
// If this is an ACK, payload should be empty.
- if (protocol_version_ == HTTP2 && settings.is_ack()) {
+ if (settings.is_ack()) {
return builder.take();
}
- if (protocol_version_ == SPDY3) {
- builder.WriteUInt32(values->size());
- }
DCHECK_EQ(GetSettingsMinimumSize(), builder.length());
- for (SpdySettingsIR::ValueMap::const_iterator it = values->begin();
- it != values->end();
+ for (SettingsMap::const_iterator it = values->begin(); it != values->end();
++it) {
- int setting_id =
- SpdyConstants::SerializeSettingId(protocol_version_, it->first);
+ int setting_id = it->first;
DCHECK_GE(setting_id, 0);
- if (protocol_version_ == SPDY3) {
- uint8_t setting_flags = 0;
- if (it->second.persist_value) {
- setting_flags |= SETTINGS_FLAG_PLEASE_PERSIST;
- }
- if (it->second.persisted) {
- setting_flags |= SETTINGS_FLAG_PERSISTED;
- }
- SettingsFlagsAndId flags_and_id(setting_flags, setting_id);
- uint32_t id_and_flags_wire =
- flags_and_id.GetWireFormat(protocol_version_);
- builder.WriteBytes(&id_and_flags_wire, 4);
- } else {
- builder.WriteUInt16(static_cast<uint16_t>(setting_id));
- }
- builder.WriteUInt32(it->second.value);
+ builder.WriteUInt16(static_cast<uint16_t>(setting_id));
+ builder.WriteUInt32(it->second);
}
DCHECK_EQ(size, builder.length());
return builder.take();
}
SpdySerializedFrame SpdyFramer::SerializePing(const SpdyPingIR& ping) const {
- SpdyFrameBuilder builder(GetPingSize(), protocol_version_);
- if (protocol_version_ == SPDY3) {
- builder.WriteControlFrameHeader(*this, PING, kNoFlags);
- builder.WriteUInt32(static_cast<uint32_t>(ping.id()));
- } else {
- uint8_t flags = 0;
- if (ping.is_ack()) {
- flags |= PING_FLAG_ACK;
- }
- builder.BeginNewFrame(*this, PING, flags, 0);
- builder.WriteUInt64(ping.id());
+ SpdyFrameBuilder builder(GetPingSize());
+ uint8_t flags = 0;
+ if (ping.is_ack()) {
+ flags |= PING_FLAG_ACK;
}
+ builder.BeginNewFrame(*this, PING, flags, 0);
+ builder.WriteUInt64(ping.id());
DCHECK_EQ(GetPingSize(), builder.length());
return builder.take();
}
@@ -2657,27 +1941,20 @@ SpdySerializedFrame SpdyFramer::SerializeGoAway(
const SpdyGoAwayIR& goaway) const {
// Compute the output buffer size, take opaque data into account.
size_t expected_length = GetGoAwayMinimumSize();
- if (protocol_version_ == HTTP2) {
- expected_length += goaway.description().size();
- }
- SpdyFrameBuilder builder(expected_length, protocol_version_);
+ expected_length += goaway.description().size();
+ SpdyFrameBuilder builder(expected_length);
// Serialize the GOAWAY frame.
- if (protocol_version_ == SPDY3) {
- builder.WriteControlFrameHeader(*this, GOAWAY, kNoFlags);
- } else {
- builder.BeginNewFrame(*this, GOAWAY, 0, 0);
- }
+ builder.BeginNewFrame(*this, GOAWAY, 0, 0);
- // GOAWAY frames specify the last good stream id for all SPDY versions.
+ // GOAWAY frames specify the last good stream id.
builder.WriteUInt32(goaway.last_good_stream_id());
// GOAWAY frames also specify the error status code.
- builder.WriteUInt32(
- SpdyConstants::SerializeGoAwayStatus(protocol_version_, goaway.status()));
+ builder.WriteUInt32(SerializeGoAwayStatus(goaway.status()));
- // In HTTP2, GOAWAY frames may also specify opaque data.
- if ((protocol_version_ == HTTP2) && (goaway.description().size() > 0)) {
+ // GOAWAY frames may also specify opaque data.
+ if (!goaway.description().empty()) {
builder.WriteBytes(goaway.description().data(),
goaway.description().size());
}
@@ -2691,22 +1968,20 @@ SpdySerializedFrame SpdyFramer::SerializeHeaders(const SpdyHeadersIR& headers) {
if (headers.fin()) {
flags |= CONTROL_FLAG_FIN;
}
- if (protocol_version_ == HTTP2) {
- // This will get overwritten if we overflow into a CONTINUATION frame.
- flags |= HEADERS_FLAG_END_HEADERS;
- if (headers.has_priority()) {
- flags |= HEADERS_FLAG_PRIORITY;
- }
- if (headers.padded()) {
- flags |= HEADERS_FLAG_PADDED;
- }
+ // This will get overwritten if we overflow into a CONTINUATION frame.
+ flags |= HEADERS_FLAG_END_HEADERS;
+ if (headers.has_priority()) {
+ flags |= HEADERS_FLAG_PRIORITY;
+ }
+ if (headers.padded()) {
+ flags |= HEADERS_FLAG_PADDED;
}
// The size of this frame, including padding (if there is any) and
// variable-length header block.
size_t size = GetHeadersMinimumSize();
- if (protocol_version_ == HTTP2 && headers.padded()) {
+ if (headers.padded()) {
size += kPadLengthFieldSize;
size += headers.padding_payload_len();
}
@@ -2718,63 +1993,59 @@ SpdySerializedFrame SpdyFramer::SerializeHeaders(const SpdyHeadersIR& headers) {
}
string hpack_encoding;
- if (protocol_version_ == SPDY3) {
- size += GetSerializedLength(headers.header_block());
- } else {
- if (enable_compression_) {
- GetHpackEncoder()->EncodeHeaderSet(headers.header_block(),
- &hpack_encoding);
- } else {
- GetHpackEncoder()->EncodeHeaderSetWithoutCompression(
- headers.header_block(), &hpack_encoding);
- }
- size += hpack_encoding.size();
- if (size > kMaxControlFrameSize) {
- size += GetNumberRequiredContinuationFrames(size) *
- GetContinuationMinimumSize();
- flags &= ~HEADERS_FLAG_END_HEADERS;
- }
+ GetHpackEncoder()->EncodeHeaderSet(headers.header_block(), &hpack_encoding);
+ size += hpack_encoding.size();
+ if (size > kMaxControlFrameSize) {
+ size += GetNumberRequiredContinuationFrames(size) *
+ GetContinuationMinimumSize();
+ flags &= ~HEADERS_FLAG_END_HEADERS;
}
- SpdyFrameBuilder builder(size, protocol_version_);
- if (protocol_version_ == SPDY3) {
- builder.WriteControlFrameHeader(*this, HEADERS, flags);
- builder.WriteUInt32(headers.stream_id());
- } else {
- builder.BeginNewFrame(*this,
- HEADERS,
- flags,
- headers.stream_id());
- }
- DCHECK_EQ(GetHeadersMinimumSize(), builder.length());
+ SpdyFrameBuilder builder(size);
- if (protocol_version_ == SPDY3) {
- SerializeHeaderBlock(&builder, headers);
+ if (!skip_rewritelength_) {
+ builder.BeginNewFrame(*this, HEADERS, flags, headers.stream_id());
} else {
- int padding_payload_len = 0;
+ // Compute frame length field.
+ size_t length_field = 0;
if (headers.padded()) {
- builder.WriteUInt8(headers.padding_payload_len());
- padding_payload_len = headers.padding_payload_len();
+ length_field += 1; // Padding length field.
}
if (headers.has_priority()) {
- builder.WriteUInt32(PackStreamDependencyValues(
- headers.exclusive(), headers.parent_stream_id()));
- // Per RFC 7540 section 6.3, serialized weight value is actual value - 1.
- builder.WriteUInt8(weight - 1);
+ length_field += 4; // Dependency field.
+ length_field += 1; // Weight field.
}
- WritePayloadWithContinuation(&builder,
- hpack_encoding,
- headers.stream_id(),
- HEADERS,
- padding_payload_len);
+ length_field += headers.padding_payload_len();
+ length_field += hpack_encoding.size();
+ // If the HEADERS frame with payload would exceed the max frame size, then
+ // WritePayloadWithContinuation() will serialize CONTINUATION frames as
+ // necessary.
+ length_field =
+ std::min(length_field, kMaxControlFrameSize - GetFrameHeaderSize());
+ builder.BeginNewFrame(*this, HEADERS, flags, headers.stream_id(),
+ length_field);
+ }
+ DCHECK_EQ(GetHeadersMinimumSize(), builder.length());
+
+ int padding_payload_len = 0;
+ if (headers.padded()) {
+ builder.WriteUInt8(headers.padding_payload_len());
+ padding_payload_len = headers.padding_payload_len();
+ }
+ if (headers.has_priority()) {
+ builder.WriteUInt32(PackStreamDependencyValues(headers.exclusive(),
+ headers.parent_stream_id()));
+ // Per RFC 7540 section 6.3, serialized weight value is actual value - 1.
+ builder.WriteUInt8(weight - 1);
}
+ WritePayloadWithContinuation(&builder, hpack_encoding, headers.stream_id(),
+ HEADERS, padding_payload_len);
if (debug_visitor_) {
// HTTP2 uses HPACK for header compression. However, continue to
// use GetSerializedLength() for an apples-to-apples comparision of
// compression performance between HPACK and SPDY w/ deflate.
- const size_t payload_len =
- GetSerializedLength(protocol_version_, &(headers.header_block()));
+ const size_t payload_len = GetSerializedLength(&(headers.header_block()));
debug_visitor_->OnSendCompressedFrame(headers.stream_id(),
HEADERS,
payload_len,
@@ -2786,16 +2057,9 @@ SpdySerializedFrame SpdyFramer::SerializeHeaders(const SpdyHeadersIR& headers) {
SpdySerializedFrame SpdyFramer::SerializeWindowUpdate(
const SpdyWindowUpdateIR& window_update) const {
- SpdyFrameBuilder builder(GetWindowUpdateSize(), protocol_version_);
- if (protocol_version_ == SPDY3) {
- builder.WriteControlFrameHeader(*this, WINDOW_UPDATE, kNoFlags);
- builder.WriteUInt32(window_update.stream_id());
- } else {
- builder.BeginNewFrame(*this,
- WINDOW_UPDATE,
- kNoFlags,
- window_update.stream_id());
- }
+ SpdyFrameBuilder builder(GetWindowUpdateSize());
+ builder.BeginNewFrame(*this, WINDOW_UPDATE, kNoFlags,
+ window_update.stream_id());
builder.WriteUInt32(window_update.delta());
DCHECK_EQ(GetWindowUpdateSize(), builder.length());
return builder.take();
@@ -2803,15 +2067,13 @@ SpdySerializedFrame SpdyFramer::SerializeWindowUpdate(
SpdySerializedFrame SpdyFramer::SerializeBlocked(
const SpdyBlockedIR& blocked) const {
- DCHECK_EQ(HTTP2, protocol_version_);
- SpdyFrameBuilder builder(GetBlockedSize(), protocol_version_);
+ SpdyFrameBuilder builder(GetBlockedSize());
builder.BeginNewFrame(*this, BLOCKED, kNoFlags, blocked.stream_id());
return builder.take();
}
SpdySerializedFrame SpdyFramer::SerializePushPromise(
const SpdyPushPromiseIR& push_promise) {
- DCHECK_EQ(HTTP2, protocol_version_);
uint8_t flags = 0;
// This will get overwritten if we overflow into a CONTINUATION frame.
flags |= PUSH_PROMISE_FLAG_END_PUSH_PROMISE;
@@ -2825,13 +2087,8 @@ SpdySerializedFrame SpdyFramer::SerializePushPromise(
}
string hpack_encoding;
- if (enable_compression_) {
- GetHpackEncoder()->EncodeHeaderSet(push_promise.header_block(),
- &hpack_encoding);
- } else {
- GetHpackEncoder()->EncodeHeaderSetWithoutCompression(
- push_promise.header_block(), &hpack_encoding);
- }
+ GetHpackEncoder()->EncodeHeaderSet(push_promise.header_block(),
+ &hpack_encoding);
size += hpack_encoding.size();
if (size > kMaxControlFrameSize) {
size += GetNumberRequiredContinuationFrames(size) *
@@ -2839,11 +2096,14 @@ SpdySerializedFrame SpdyFramer::SerializePushPromise(
flags &= ~PUSH_PROMISE_FLAG_END_PUSH_PROMISE;
}
- SpdyFrameBuilder builder(size, protocol_version_);
- builder.BeginNewFrame(*this,
- PUSH_PROMISE,
- flags,
- push_promise.stream_id());
+ SpdyFrameBuilder builder(size);
+ if (!skip_rewritelength_) {
+ builder.BeginNewFrame(*this, PUSH_PROMISE, flags, push_promise.stream_id());
+ } else {
+ size_t length = std::min(size, kMaxControlFrameSize) - GetFrameHeaderSize();
+ builder.BeginNewFrame(*this, PUSH_PROMISE, flags, push_promise.stream_id(),
+ length);
+ }
int padding_payload_len = 0;
if (push_promise.padded()) {
builder.WriteUInt8(push_promise.padding_payload_len());
@@ -2868,7 +2128,7 @@ SpdySerializedFrame SpdyFramer::SerializePushPromise(
// use GetSerializedLength() for an apples-to-apples comparision of
// compression performance between HPACK and SPDY w/ deflate.
const size_t payload_len =
- GetSerializedLength(protocol_version_, &(push_promise.header_block()));
+ GetSerializedLength(&(push_promise.header_block()));
debug_visitor_->OnSendCompressedFrame(push_promise.stream_id(),
PUSH_PROMISE,
payload_len,
@@ -2881,10 +2141,8 @@ SpdySerializedFrame SpdyFramer::SerializePushPromise(
SpdySerializedFrame SpdyFramer::SerializeHeadersGivenEncoding(
const SpdyHeadersIR& headers,
const string& encoding) const {
- DCHECK_EQ(HTTP2, protocol_version_);
-
size_t frame_size = GetHeaderFrameSizeSansBlock(headers) + encoding.size();
- SpdyFrameBuilder builder(frame_size, protocol_version_);
+ SpdyFrameBuilder builder(frame_size);
builder.BeginNewFrame(*this, HEADERS, SerializeHeaderFrameFlags(headers),
headers.stream_id());
DCHECK_EQ(GetFrameHeaderSize(), builder.length());
@@ -2912,11 +2170,9 @@ SpdySerializedFrame SpdyFramer::SerializeHeadersGivenEncoding(
SpdySerializedFrame SpdyFramer::SerializeContinuation(
const SpdyContinuationIR& continuation) const {
- DCHECK_EQ(HTTP2, protocol_version_);
-
const string& encoding = continuation.encoding();
size_t frame_size = GetContinuationMinimumSize() + encoding.size();
- SpdyFrameBuilder builder(frame_size, protocol_version_);
+ SpdyFrameBuilder builder(frame_size);
uint8_t flags = continuation.end_headers() ? HEADERS_FLAG_END_HEADERS : 0;
builder.BeginNewFrame(*this, CONTINUATION, flags, continuation.stream_id());
DCHECK_EQ(GetFrameHeaderSize(), builder.length());
@@ -2926,15 +2182,13 @@ SpdySerializedFrame SpdyFramer::SerializeContinuation(
}
SpdySerializedFrame SpdyFramer::SerializeAltSvc(const SpdyAltSvcIR& altsvc_ir) {
- DCHECK_EQ(HTTP2, protocol_version_);
-
size_t size = GetAltSvcMinimumSize();
size += altsvc_ir.origin().length();
string value = SpdyAltSvcWireFormat::SerializeHeaderFieldValue(
altsvc_ir.altsvc_vector());
size += value.length();
- SpdyFrameBuilder builder(size, protocol_version_);
+ SpdyFrameBuilder builder(size);
builder.BeginNewFrame(*this, ALTSVC, kNoFlags, altsvc_ir.stream_id());
builder.WriteUInt16(altsvc_ir.origin().length());
@@ -2946,10 +2200,9 @@ SpdySerializedFrame SpdyFramer::SerializeAltSvc(const SpdyAltSvcIR& altsvc_ir) {
SpdySerializedFrame SpdyFramer::SerializePriority(
const SpdyPriorityIR& priority) const {
- DCHECK_EQ(HTTP2, protocol_version_);
size_t size = GetPrioritySize();
- SpdyFrameBuilder builder(size, protocol_version_);
+ SpdyFrameBuilder builder(size);
builder.BeginNewFrame(*this, PRIORITY, kNoFlags, priority.stream_id());
builder.WriteUInt32(PackStreamDependencyValues(priority.exclusive(),
@@ -2973,12 +2226,6 @@ class FrameSerializationVisitor : public SpdyFrameVisitor {
void VisitData(const SpdyDataIR& data) override {
frame_ = framer_->SerializeData(data);
}
- void VisitSynStream(const SpdySynStreamIR& syn_stream) override {
- frame_ = framer_->SerializeSynStream(syn_stream);
- }
- void VisitSynReply(const SpdySynReplyIR& syn_reply) override {
- frame_ = framer_->SerializeSynReply(syn_reply);
- }
void VisitRstStream(const SpdyRstStreamIR& rst_stream) override {
frame_ = framer_->SerializeRstStream(rst_stream);
}
@@ -3018,6 +2265,89 @@ class FrameSerializationVisitor : public SpdyFrameVisitor {
SpdySerializedFrame frame_;
};
+// TODO(diannahu): Use also in frame serialization.
+class FlagsSerializationVisitor : public SpdyFrameVisitor {
+ public:
+ void VisitData(const SpdyDataIR& data) override {
+ flags_ = DATA_FLAG_NONE;
+ if (data.fin()) {
+ flags_ |= DATA_FLAG_FIN;
+ }
+ if (data.padded()) {
+ flags_ |= DATA_FLAG_PADDED;
+ }
+ }
+
+ void VisitRstStream(const SpdyRstStreamIR& rst_stream) override {
+ flags_ = kNoFlags;
+ }
+
+ void VisitSettings(const SpdySettingsIR& settings) override {
+ flags_ = kNoFlags;
+ if (settings.is_ack()) {
+ flags_ |= SETTINGS_FLAG_ACK;
+ }
+ }
+
+ void VisitPing(const SpdyPingIR& ping) override {
+ flags_ = kNoFlags;
+ if (ping.is_ack()) {
+ flags_ |= PING_FLAG_ACK;
+ }
+ }
+
+ void VisitGoAway(const SpdyGoAwayIR& goaway) override { flags_ = kNoFlags; }
+
+ // TODO(diannahu): The END_HEADERS flag is incorrect for HEADERS that require
+ // CONTINUATION frames.
+ void VisitHeaders(const SpdyHeadersIR& headers) override {
+ flags_ = HEADERS_FLAG_END_HEADERS;
+ if (headers.fin()) {
+ flags_ |= CONTROL_FLAG_FIN;
+ }
+ if (headers.padded()) {
+ flags_ |= HEADERS_FLAG_PADDED;
+ }
+ if (headers.has_priority()) {
+ flags_ |= HEADERS_FLAG_PRIORITY;
+ }
+ }
+
+ void VisitWindowUpdate(const SpdyWindowUpdateIR& window_update) override {
+ flags_ = kNoFlags;
+ }
+
+ void VisitBlocked(const SpdyBlockedIR& blocked) override {
+ flags_ = kNoFlags;
+ }
+
+ // TODO(diannahu): The END_PUSH_PROMISE flag is incorrect for PUSH_PROMISEs
+ // that require CONTINUATION frames.
+ void VisitPushPromise(const SpdyPushPromiseIR& push_promise) override {
+ flags_ = PUSH_PROMISE_FLAG_END_PUSH_PROMISE;
+ if (push_promise.padded()) {
+ flags_ |= PUSH_PROMISE_FLAG_PADDED;
+ }
+ }
+
+ // TODO(diannahu): The END_HEADERS flag is incorrect for CONTINUATIONs that
+ // require CONTINUATION frames.
+ void VisitContinuation(const SpdyContinuationIR& continuation) override {
+ flags_ = HEADERS_FLAG_END_HEADERS;
+ }
+
+ void VisitAltSvc(const SpdyAltSvcIR& altsvc) override { flags_ = kNoFlags; }
+
+ void VisitPriority(const SpdyPriorityIR& priority) override {
+ flags_ = kNoFlags;
+ }
+
+ uint8_t flags() const { return flags_; }
+
+ private:
+ uint8_t flags_ = kNoFlags;
+};
+
} // namespace
SpdySerializedFrame SpdyFramer::SerializeFrame(const SpdyFrameIR& frame) {
@@ -3026,20 +2356,13 @@ SpdySerializedFrame SpdyFramer::SerializeFrame(const SpdyFrameIR& frame) {
return visitor.ReleaseSerializedFrame();
}
-size_t SpdyFramer::GetSerializedLength(const SpdyHeaderBlock& headers) {
- const size_t uncompressed_length =
- GetSerializedLength(protocol_version_, &headers);
- if (!enable_compression_) {
- return uncompressed_length;
- }
- z_stream* compressor = GetHeaderCompressor();
- // Since we'll be performing lots of flushes when compressing the data,
- // zlib's lower bounds may be insufficient.
- return 2 * deflateBound(compressor, uncompressed_length);
+uint8_t SpdyFramer::GetSerializedFlags(const SpdyFrameIR& frame) {
+ FlagsSerializationVisitor visitor;
+ frame.Visit(&visitor);
+ return visitor.flags();
}
size_t SpdyFramer::GetNumberRequiredContinuationFrames(size_t size) {
- DCHECK_EQ(HTTP2, protocol_version_);
DCHECK_GT(size, kMaxControlFrameSize);
size_t overflow = size - kMaxControlFrameSize;
size_t payload_size = kMaxControlFrameSize - GetContinuationMinimumSize();
@@ -3110,7 +2433,7 @@ void SpdyFramer::WritePayloadWithContinuation(SpdyFrameBuilder* builder,
string padding = string(padding_payload_len, 0);
builder->WriteBytes(padding.data(), padding.length());
}
- if (bytes_remaining > 0) {
+ if (bytes_remaining > 0 && !skip_rewritelength_) {
builder->OverwriteLength(*this,
kMaxControlFrameSize - GetFrameHeaderSize());
}
@@ -3123,7 +2446,12 @@ void SpdyFramer::WritePayloadWithContinuation(SpdyFrameBuilder* builder,
if (bytes_remaining == bytes_to_write) {
flags |= end_flag;
}
- builder->BeginNewFrame(*this, CONTINUATION, flags, stream_id);
+ if (!skip_rewritelength_) {
+ builder->BeginNewFrame(*this, CONTINUATION, flags, stream_id);
+ } else {
+ builder->BeginNewFrame(*this, CONTINUATION, flags, stream_id,
+ bytes_to_write);
+ }
// Write payload fragment.
builder->WriteBytes(
&hpack_encoding[hpack_encoding.size() - bytes_remaining],
@@ -3132,155 +2460,29 @@ void SpdyFramer::WritePayloadWithContinuation(SpdyFrameBuilder* builder,
}
}
-// The following compression setting are based on Brian Olson's analysis. See
-// https://groups.google.com/group/spdy-dev/browse_thread/thread/dfaf498542fac792
-// for more details.
-#if defined(USE_SYSTEM_ZLIB)
-// System zlib is not expected to have workaround for http://crbug.com/139744,
-// so disable compression in that case.
-// TODO(phajdan.jr): Remove the special case when it's no longer necessary.
-static const int kCompressorLevel = 0;
-#else // !defined(USE_SYSTEM_ZLIB)
-static const int kCompressorLevel = 9;
-#endif // !defined(USE_SYSTEM_ZLIB)
-static const int kCompressorWindowSizeInBits = 11;
-static const int kCompressorMemLevel = 1;
-
-z_stream* SpdyFramer::GetHeaderCompressor() {
- if (header_compressor_.get()) {
- return header_compressor_.get(); // Already initialized.
- }
-
- header_compressor_.reset(new z_stream);
- memset(header_compressor_.get(), 0, sizeof(z_stream));
-
- int success = deflateInit2(header_compressor_.get(),
- kCompressorLevel,
- Z_DEFLATED,
- kCompressorWindowSizeInBits,
- kCompressorMemLevel,
- Z_DEFAULT_STRATEGY);
- if (success == Z_OK) {
- const char* dictionary = kV3Dictionary;
- const int dictionary_size = kV3DictionarySize;
- success = deflateSetDictionary(header_compressor_.get(),
- reinterpret_cast<const Bytef*>(dictionary),
- dictionary_size);
- }
- if (success != Z_OK) {
- LOG(WARNING) << "deflateSetDictionary failure: " << success;
- header_compressor_.reset(NULL);
- return NULL;
- }
- return header_compressor_.get();
-}
-
-z_stream* SpdyFramer::GetHeaderDecompressor() {
- if (header_decompressor_.get()) {
- return header_decompressor_.get(); // Already initialized.
- }
-
- header_decompressor_.reset(new z_stream);
- memset(header_decompressor_.get(), 0, sizeof(z_stream));
-
- int success = inflateInit(header_decompressor_.get());
- if (success != Z_OK) {
- LOG(WARNING) << "inflateInit failure: " << success;
- header_decompressor_.reset(NULL);
- return NULL;
- }
- return header_decompressor_.get();
-}
-
HpackEncoder* SpdyFramer::GetHpackEncoder() {
- DCHECK_EQ(HTTP2, protocol_version_);
if (hpack_encoder_.get() == nullptr) {
hpack_encoder_.reset(new HpackEncoder(ObtainHpackHuffmanTable()));
+ if (!compression_enabled()) {
+ hpack_encoder_->DisableCompression();
+ }
}
return hpack_encoder_.get();
}
HpackDecoderInterface* SpdyFramer::GetHpackDecoder() {
- DCHECK_EQ(HTTP2, protocol_version_);
if (hpack_decoder_.get() == nullptr) {
- hpack_decoder_.reset(new HpackDecoder());
- }
- return hpack_decoder_.get();
-}
-
-// Incrementally decompress the control frame's header block, feeding the
-// result to the visitor in chunks. Continue this until the visitor
-// indicates that it cannot process any more data, or (more commonly) we
-// run out of data to deliver.
-bool SpdyFramer::IncrementallyDecompressControlFrameHeaderData(
- SpdyStreamId stream_id,
- const char* data,
- size_t len) {
- // Get a decompressor or set error.
- z_stream* decomp = GetHeaderDecompressor();
- if (decomp == NULL) {
- SPDY_BUG << "Couldn't get decompressor for handling compressed headers.";
- set_error(SPDY_DECOMPRESS_FAILURE);
- return false;
- }
-
- bool processed_successfully = true;
- char buffer[kHeaderDataChunkMaxSize];
-
- decomp->next_in = reinterpret_cast<Bytef*>(const_cast<char*>(data));
- decomp->avail_in = len;
- // If we get a SYN_STREAM/SYN_REPLY/HEADERS frame with stream ID zero, we
- // signal an error back in ProcessControlFrameBeforeHeaderBlock. So if we've
- // reached this method successfully, stream_id should be nonzero.
- DCHECK_LT(0u, stream_id);
- while (decomp->avail_in > 0 && processed_successfully) {
- decomp->next_out = reinterpret_cast<Bytef*>(buffer);
- decomp->avail_out = arraysize(buffer);
-
- int rv = inflate(decomp, Z_SYNC_FLUSH);
- if (rv == Z_NEED_DICT) {
- const char* dictionary = kV3Dictionary;
- const int dictionary_size = kV3DictionarySize;
- const DictionaryIds& ids = g_dictionary_ids.Get();
- const uLong dictionary_id = ids.v3_dictionary_id;
- // Need to try again with the right dictionary.
- if (decomp->adler == dictionary_id) {
- rv = inflateSetDictionary(decomp,
- reinterpret_cast<const Bytef*>(dictionary),
- dictionary_size);
- if (rv == Z_OK) {
- rv = inflate(decomp, Z_SYNC_FLUSH);
- }
- }
- }
-
- // Inflate will generate a Z_BUF_ERROR if it runs out of input
- // without producing any output. The input is consumed and
- // buffered internally by zlib so we can detect this condition by
- // checking if avail_in is 0 after the call to inflate.
- bool input_exhausted = ((rv == Z_BUF_ERROR) && (decomp->avail_in == 0));
- if ((rv == Z_OK) || input_exhausted) {
- size_t decompressed_len = arraysize(buffer) - decomp->avail_out;
- if (decompressed_len > 0) {
- processed_successfully = header_parser_->HandleControlFrameHeadersData(
- stream_id, buffer, decompressed_len);
- if (header_parser_->get_error() ==
- SpdyHeadersBlockParser::NEED_MORE_DATA) {
- processed_successfully = true;
- }
- }
- if (!processed_successfully) {
- // Assume that the problem was the header block was too large for the
- // visitor.
- set_error(SPDY_CONTROL_PAYLOAD_TOO_LARGE);
- }
+ if (FLAGS_chromium_http2_flag_spdy_use_hpack_decoder3) {
+ SPDY_BUG_IF(FLAGS_chromium_http2_flag_spdy_use_hpack_decoder2)
+ << "Both alternate decoders are enabled.";
+ hpack_decoder_.reset(new HpackDecoder3());
+ } else if (FLAGS_chromium_http2_flag_spdy_use_hpack_decoder2) {
+ hpack_decoder_.reset(new HpackDecoder2());
} else {
- DLOG(WARNING) << "inflate failure: " << rv << " " << len;
- set_error(SPDY_DECOMPRESS_FAILURE);
- processed_successfully = false;
+ hpack_decoder_.reset(new HpackDecoder());
}
}
- return processed_successfully;
+ return hpack_decoder_.get();
}
bool SpdyFramer::IncrementallyDeliverControlFrameHeaderData(
@@ -3347,62 +2549,4 @@ void SpdyFramer::SerializeHeaderBlockWithoutCompression(
}
}
-void SpdyFramer::SerializeHeaderBlock(SpdyFrameBuilder* builder,
- const SpdyFrameWithHeaderBlockIR& frame) {
- if (!enable_compression_) {
- return SerializeHeaderBlockWithoutCompression(builder,
- frame.header_block());
- }
-
- // First build an uncompressed version to be fed into the compressor.
- const size_t uncompressed_len =
- GetSerializedLength(protocol_version_, &(frame.header_block()));
- SpdyFrameBuilder uncompressed_builder(uncompressed_len, protocol_version_);
- SerializeHeaderBlockWithoutCompression(&uncompressed_builder,
- frame.header_block());
- SpdySerializedFrame uncompressed_payload(uncompressed_builder.take());
-
- z_stream* compressor = GetHeaderCompressor();
- if (!compressor) {
- SPDY_BUG << "Could not obtain compressor.";
- return;
- }
- // Create an output frame.
- // Since we'll be performing lots of flushes when compressing the data,
- // zlib's lower bounds may be insufficient.
- //
- // TODO(akalin): Avoid the duplicate calculation with
- // GetSerializedLength(const SpdyHeaderBlock&).
- const int compressed_max_size =
- 2 * deflateBound(compressor, uncompressed_len);
-
- // TODO(phajdan.jr): Clean up after we no longer need
- // to workaround http://crbug.com/139744.
-#if defined(USE_SYSTEM_ZLIB)
- compressor->next_in = reinterpret_cast<Bytef*>(uncompressed_payload.data());
- compressor->avail_in = uncompressed_len;
-#endif // defined(USE_SYSTEM_ZLIB)
- compressor->next_out = reinterpret_cast<Bytef*>(
- builder->GetWritableBuffer(compressed_max_size));
- compressor->avail_out = compressed_max_size;
-
- // TODO(phajdan.jr): Clean up after we no longer need
- // to workaround http://crbug.com/139744.
-#if defined(USE_SYSTEM_ZLIB)
- int rv = deflate(compressor, Z_SYNC_FLUSH);
- if (rv != Z_OK) { // How can we know that it compressed everything?
- // This shouldn't happen, right?
- LOG(WARNING) << "deflate failure: " << rv;
- // TODO(akalin): Upstream this return.
- return;
- }
-#else
- WriteHeaderBlockToZ(&frame.header_block(), compressor);
-#endif // defined(USE_SYSTEM_ZLIB)
-
- int compressed_size = compressed_max_size - compressor->avail_out;
- builder->Seek(compressed_size);
- builder->RewriteLength(*this);
-}
-
} // namespace net
diff --git a/chromium/net/spdy/spdy_framer.h b/chromium/net/spdy/spdy_framer.h
index bebfccacc09..b686746feff 100644
--- a/chromium/net/spdy/spdy_framer.h
+++ b/chromium/net/spdy/spdy_framer.h
@@ -16,7 +16,6 @@
#include "base/strings/string_piece.h"
#include "base/sys_byteorder.h"
#include "net/base/net_export.h"
-#include "net/spdy/hpack/hpack_decoder.h"
#include "net/spdy/hpack/hpack_decoder_interface.h"
#include "net/spdy/hpack/hpack_encoder.h"
#include "net/spdy/spdy_alt_svc_wire_format.h"
@@ -26,8 +25,6 @@
#include "net/spdy/spdy_headers_handler_interface.h"
#include "net/spdy/spdy_protocol.h"
-typedef struct z_stream_s z_stream; // Forward declaration for zlib.
-
namespace net {
class HttpProxyClientSocketPoolTest;
@@ -50,41 +47,22 @@ class SpdyFramerPeer;
} // namespace test
-// A datastructure for holding the ID and flag fields for SETTINGS.
-// Conveniently handles converstion to/from wire format.
-class NET_EXPORT_PRIVATE SettingsFlagsAndId {
- public:
- static SettingsFlagsAndId FromWireFormat(SpdyMajorVersion version,
- uint32_t wire);
-
- SettingsFlagsAndId() : flags_(0), id_(0) {}
-
- // TODO(hkhalil): restrict to enums instead of free-form ints.
- SettingsFlagsAndId(uint8_t flags, uint32_t id);
-
- uint32_t GetWireFormat(SpdyMajorVersion version) const;
-
- uint32_t id() const { return id_; }
- uint8_t flags() const { return flags_; }
-
- private:
- uint8_t flags_;
- uint32_t id_;
-};
-
-// SettingsMap has unique (flags, value) pair for given SpdySettingsIds ID.
-typedef std::pair<SpdySettingsFlags, uint32_t> SettingsFlagsAndValue;
-typedef std::map<SpdySettingsIds, SettingsFlagsAndValue> SettingsMap;
-
// SpdyFramerVisitorInterface is a set of callbacks for the SpdyFramer.
// Implement this interface to receive event callbacks as frames are
// decoded from the framer.
//
-// Control frames that contain SPDY header blocks (SYN_STREAM, SYN_REPLY,
-// HEADER, and PUSH_PROMISE) are processed in fashion that allows the
-// decompressed header block to be delivered in chunks to the visitor.
+// Control frames that contain HTTP2 header blocks (HEADER, and PUSH_PROMISE)
+// are processed in fashion that allows the decompressed header block to be
+// delivered in chunks to the visitor.
// The following steps are followed:
-// 1. OnSynStream, OnSynReply, OnHeaders, or OnPushPromise is called.
+// 1. OnHeaders, or OnPushPromise is called.
+// 2. OnHeaderFrameStart is called; visitor is expected to return an instance
+// of SpdyHeadersHandlerInterface that will receive the header key-value
+// pairs.
+// 3. OnHeaderFrameEnd is called, indicating that the full header block has
+// been delivered for the control frame.
+// During step 2, if the visitor is not interested in accepting the header data,
+// it should return a no-op implementation of SpdyHeadersHandlerInterface.
class NET_EXPORT_PRIVATE SpdyFramerVisitorInterface {
public:
virtual ~SpdyFramerVisitorInterface() {}
@@ -137,18 +115,6 @@ class NET_EXPORT_PRIVATE SpdyFramerVisitorInterface {
// frames.
virtual void OnHeaderFrameEnd(SpdyStreamId stream_id, bool end_headers) = 0;
- // Called when a SYN_STREAM frame is received.
- // Note that header block data is not included. See OnHeaderFrameStart().
- virtual void OnSynStream(SpdyStreamId stream_id,
- SpdyStreamId associated_stream_id,
- SpdyPriority priority,
- bool fin,
- bool unidirectional) = 0;
-
- // Called when a SYN_REPLY frame is received.
- // Note that header block data is not included. See OnHeaderFrameStart().
- virtual void OnSynReply(SpdyStreamId stream_id, bool fin) = 0;
-
// Called when a RST_STREAM frame has been parsed.
virtual void OnRstStream(SpdyStreamId stream_id,
SpdyRstStreamStatus status) = 0;
@@ -159,7 +125,7 @@ class NET_EXPORT_PRIVATE SpdyFramerVisitorInterface {
// Called when a complete setting within a SETTINGS frame has been parsed and
// validated.
- virtual void OnSetting(SpdySettingsIds id, uint8_t flags, uint32_t value) = 0;
+ virtual void OnSetting(SpdySettingsIds id, uint32_t value) = 0;
// Called when a SETTINGS frame is received with the ACK flag set.
virtual void OnSettingsAck() {}
@@ -178,14 +144,13 @@ class NET_EXPORT_PRIVATE SpdyFramerVisitorInterface {
// Note that header block data is not included. See OnHeaderFrameStart().
// |stream_id| The stream receiving the header.
// |has_priority| Whether or not the headers frame included a priority value,
- // and, if protocol version == HTTP2, stream dependency info.
+ // and stream dependency info.
// |weight| If |has_priority| is true, then weight (in the range [1, 256])
// for the receiving stream, otherwise 0.
- // |parent_stream_id| If |has_priority| is true and protocol
- // version == HTTP2, the parent stream of the receiving stream, else 0.
- // |exclusive| If |has_priority| is true and protocol
- // version == HTTP2, the exclusivity of dependence on the parent stream,
- // else false.
+ // |parent_stream_id| If |has_priority| is true the parent stream of the
+ // receiving stream, else 0.
+ // |exclusive| If |has_priority| is true the exclusivity of dependence on the
+ // parent stream, else false.
// |fin| Whether FIN flag is set in frame headers.
// |end| False if HEADERs frame is to be followed by a CONTINUATION frame,
// or true if not.
@@ -262,7 +227,7 @@ class NET_EXPORT_PRIVATE SpdyFramerVisitorInterface {
// order to extract debug/internal information about the SpdyFramer as it
// operates.
//
-// Most SPDY implementations need not bother with this interface at all.
+// Most HTTP2 implementations need not bother with this interface at all.
class NET_EXPORT_PRIVATE SpdyFramerDebugVisitorInterface {
public:
virtual ~SpdyFramerDebugVisitorInterface() {}
@@ -286,9 +251,7 @@ class NET_EXPORT_PRIVATE SpdyFramerDebugVisitorInterface {
class NET_EXPORT_PRIVATE SpdyFramer {
public:
- // SPDY states.
- // TODO(mbelshe): Can we move these into the implementation
- // and avoid exposing through the header. (Needed for test)
+ // HTTP2 states.
enum SpdyState {
SPDY_ERROR,
SPDY_READY_FOR_FRAME, // Framer is ready for reading the next frame.
@@ -331,6 +294,11 @@ class NET_EXPORT_PRIVATE SpdyFramer {
LAST_ERROR, // Must be the last entry in the enum.
};
+ enum CompressionOption {
+ ENABLE_COMPRESSION,
+ DISABLE_COMPRESSION,
+ };
+
// Typedef for a function used to create SpdyFramerDecoderAdapter's.
// Defined in support of evaluating an alternate HTTP/2 decoder.
typedef std::unique_ptr<SpdyFramerDecoderAdapter> (*DecoderAdapterFactoryFn)(
@@ -348,18 +316,17 @@ class NET_EXPORT_PRIVATE SpdyFramer {
const SpdyHeaderBlock& header_block) const;
// Retrieve serialized length of SpdyHeaderBlock.
- // TODO(hkhalil): Remove, or move to quic code.
- static size_t GetSerializedLength(
- const SpdyMajorVersion spdy_version,
- const SpdyHeaderBlock* headers);
+ static size_t GetSerializedLength(const SpdyHeaderBlock* headers);
- // Create a new Framer, provided a SPDY version.
- explicit SpdyFramer(SpdyMajorVersion version);
+ // Gets the serialized flags for the given |frame|.
+ static uint8_t GetSerializedFlags(const SpdyFrameIR& frame);
+
+ explicit SpdyFramer(CompressionOption option);
// Used recursively from the above constructor in order to support
// instantiating a SpdyFramerDecoderAdapter selected via flags or some other
// means.
- SpdyFramer(SpdyMajorVersion version, DecoderAdapterFactoryFn adapter_factory);
+ SpdyFramer(DecoderAdapterFactoryFn adapter_factory, CompressionOption option);
virtual ~SpdyFramer();
@@ -395,9 +362,8 @@ class NET_EXPORT_PRIVATE SpdyFramer {
SpdyState state() const;
bool HasError() const { return state() == SPDY_ERROR; }
- // Given a buffer containing a decompressed header block in SPDY
- // serialized format, parse out a SpdyHeaderBlock, putting the results
- // in the given header block.
+ // Given a buffer containing a serialized header block parse out a
+ // SpdyHeaderBlock, putting the results in the given header block.
// Returns true if successfully parsed, false otherwise.
bool ParseHeaderBlockInBuffer(const char* header_data,
size_t header_length,
@@ -437,12 +403,6 @@ class NET_EXPORT_PRIVATE SpdyFramer {
SpdySerializedFrame SerializeDataFrameHeaderWithPaddingLengthField(
const SpdyDataIR& data) const;
- // Serializes a SYN_STREAM frame.
- SpdySerializedFrame SerializeSynStream(const SpdySynStreamIR& syn_stream);
-
- // Serialize a SYN_REPLY frame.
- SpdySerializedFrame SerializeSynReply(const SpdySynReplyIR& syn_reply);
-
SpdySerializedFrame SerializeRstStream(
const SpdyRstStreamIR& rst_stream) const;
@@ -461,11 +421,11 @@ class NET_EXPORT_PRIVATE SpdyFramer {
SpdySerializedFrame SerializeGoAway(const SpdyGoAwayIR& goaway) const;
// Serializes a HEADERS frame. The HEADERS frame is used
- // for sending additional headers outside of a SYN_STREAM/SYN_REPLY.
+ // for sending headers.
SpdySerializedFrame SerializeHeaders(const SpdyHeadersIR& headers);
// Serializes a WINDOW_UPDATE frame. The WINDOW_UPDATE
- // frame is used to implement per stream flow control in SPDY.
+ // frame is used to implement per stream flow control.
SpdySerializedFrame SerializeWindowUpdate(
const SpdyWindowUpdateIR& window_update) const;
@@ -498,53 +458,19 @@ class NET_EXPORT_PRIVATE SpdyFramer {
// Serialize a frame of unknown type.
SpdySerializedFrame SerializeFrame(const SpdyFrameIR& frame);
- // NOTES about frame compression.
- // We want spdy to compress headers across the entire session. As long as
- // the session is over TCP, frames are sent serially. The client & server
- // can each compress frames in the same order and then compress them in that
- // order, and the remote can do the reverse. However, we ultimately want
- // the creation of frames to be less sensitive to order so that they can be
- // placed over a UDP based protocol and yet still benefit from some
- // compression. We don't know of any good compression protocol which does
- // not build its state in a serial (stream based) manner.... For now, we're
- // using zlib anyway.
-
- // For ease of testing and experimentation we can tweak compression on/off.
- bool enable_compression() const { return enable_compression_; }
- void set_enable_compression(bool value) {
- enable_compression_ = value;
+ // Returns whether this SpdyFramer will compress header blocks using HPACK.
+ bool compression_enabled() const {
+ return compression_option_ == ENABLE_COMPRESSION;
}
void SetHpackIndexingPolicy(HpackEncoder::IndexingPolicy policy) {
GetHpackEncoder()->SetIndexingPolicy(std::move(policy));
}
- // Used only in log messages.
- void set_display_protocol(const std::string& protocol) {
- display_protocol_ = protocol;
- }
-
- void set_max_decode_buffer_size_bytes(size_t max_decode_buffer_size_bytes) {
- GetHpackDecoder()->set_max_decode_buffer_size_bytes(
- max_decode_buffer_size_bytes);
- }
-
- size_t send_frame_size_limit() const { return send_frame_size_limit_; }
-
- void set_send_frame_size_limit(size_t send_frame_size_limit) {
- send_frame_size_limit_ = send_frame_size_limit;
- }
-
- void set_recv_frame_size_limit(size_t recv_frame_size_limit) {
- recv_frame_size_limit_ = recv_frame_size_limit;
- }
-
// Returns the (minimum) size of frames (sans variable-length portions).
size_t GetDataFrameMinimumSize() const;
size_t GetFrameHeaderSize() const;
- size_t GetSynStreamMinimumSize() const;
- size_t GetSynReplyMinimumSize() const;
- size_t GetRstStreamMinimumSize() const;
+ size_t GetRstStreamSize() const;
size_t GetSettingsMinimumSize() const;
size_t GetPingSize() const;
size_t GetGoAwayMinimumSize() const;
@@ -571,8 +497,6 @@ class NET_EXPORT_PRIVATE SpdyFramer {
static const char* StatusCodeToString(int status_code);
static const char* FrameTypeToString(SpdyFrameType type);
- SpdyMajorVersion protocol_version() const { return protocol_version_; }
-
// Did the most recent frame header appear to be an HTTP/1.x (or earlier)
// response (i.e. start with "HTTP/")?
bool probable_http_response() const;
@@ -581,14 +505,6 @@ class NET_EXPORT_PRIVATE SpdyFramer {
SpdyPriority GetHighestPriority() const { return kV3HighestPriority; }
- // Deliver the given control frame's compressed headers block to the visitor
- // in decompressed form, in chunks. Returns true if the visitor has
- // accepted all of the chunks.
- bool IncrementallyDecompressControlFrameHeaderData(
- SpdyStreamId stream_id,
- const char* data,
- size_t len);
-
// Updates the maximum size of the header encoder compression table.
void UpdateHeaderEncoderTableSize(uint32_t value);
@@ -598,12 +514,33 @@ class NET_EXPORT_PRIVATE SpdyFramer {
// Returns the maximum size of the header encoder compression table.
size_t header_encoder_table_size() const;
+ void set_max_decode_buffer_size_bytes(size_t max_decode_buffer_size_bytes) {
+ GetHpackDecoder()->set_max_decode_buffer_size_bytes(
+ max_decode_buffer_size_bytes);
+ }
+
+ size_t send_frame_size_limit() const { return send_frame_size_limit_; }
+ void set_send_frame_size_limit(size_t send_frame_size_limit) {
+ send_frame_size_limit_ = send_frame_size_limit;
+ }
+
+ size_t recv_frame_size_limit() const { return recv_frame_size_limit_; }
+ void set_recv_frame_size_limit(size_t recv_frame_size_limit) {
+ recv_frame_size_limit_ = recv_frame_size_limit;
+ }
+
void SetDecoderHeaderTableDebugVisitor(
std::unique_ptr<HpackHeaderTable::DebugVisitorInterface> visitor);
void SetEncoderHeaderTableDebugVisitor(
std::unique_ptr<HpackHeaderTable::DebugVisitorInterface> visitor);
+ // For use in SpdyFramerDecoderAdapter implementations; returns a HPACK
+ // decoder to be used.
+ HpackDecoderInterface* GetHpackDecoderForAdapter() {
+ return GetHpackDecoder();
+ }
+
protected:
friend class BufferedSpdyFramer;
friend class HttpNetworkLayer; // This is temporary for the server.
@@ -657,9 +594,7 @@ class NET_EXPORT_PRIVATE SpdyFramer {
// HPACK data is re-encoded as SPDY3 and re-entrantly delivered through
// |ProcessControlFrameHeaderBlock()|. |is_hpack_header_block| controls
// whether data is treated as HPACK- vs SPDY3-encoded.
- size_t ProcessControlFrameHeaderBlock(const char* data,
- size_t len,
- bool is_hpack_header_block);
+ size_t ProcessControlFrameHeaderBlock(const char* data, size_t len);
size_t ProcessDataFramePaddingLength(const char* data, size_t len);
size_t ProcessFramePadding(const char* data, size_t len);
size_t ProcessDataFramePayload(const char* data, size_t len);
@@ -673,7 +608,7 @@ class NET_EXPORT_PRIVATE SpdyFramer {
// Validates the frame header against the current protocol, e.g.
// Frame type must be known, must specify a non-zero stream id.
//
- // is_control_frame : the control bit for SPDY3
+ // is_control_frame : the control bit
// frame_type_field : the unparsed frame type octet(s)
// payload_length_field: the stated length in octets of the frame payload
//
@@ -689,14 +624,6 @@ class NET_EXPORT_PRIVATE SpdyFramer {
// Always passed exactly 1 setting's worth of data.
bool ProcessSetting(const char* data);
- // Retrieve serialized length of SpdyHeaderBlock. If compression is enabled, a
- // maximum estimate is returned.
- size_t GetSerializedLength(const SpdyHeaderBlock& headers);
-
- // Get (and lazily initialize) the ZLib state.
- z_stream* GetHeaderCompressor();
- z_stream* GetHeaderDecompressor();
-
// Get (and lazily initialize) the HPACK state.
HpackEncoder* GetHpackEncoder();
HpackDecoderInterface* GetHpackDecoder();
@@ -725,13 +652,6 @@ class NET_EXPORT_PRIVATE SpdyFramer {
size_t UpdateCurrentFrameBuffer(const char** data, size_t* len,
size_t max_bytes);
- void WriteHeaderBlockToZ(const SpdyHeaderBlock* headers,
- z_stream* out) const;
-
- // Compresses automatically according to enable_compression_.
- void SerializeHeaderBlock(SpdyFrameBuilder* builder,
- const SpdyFrameWithHeaderBlockIR& frame);
-
// Serializes a HEADERS frame from the given SpdyHeadersIR and encoded header
// block. Does not need or use the SpdyHeaderBlock inside SpdyHeadersIR.
SpdySerializedFrame SerializeHeadersGivenEncoding(
@@ -750,7 +670,7 @@ class NET_EXPORT_PRIVATE SpdyFramer {
// The size of the control frame buffer.
// Since this is only used for control frame headers, the maximum control
- // frame header size (SYN_STREAM) is sufficient; all remaining control
+ // frame header size is sufficient; all remaining control
// frame data is streamed to the visitor.
static const size_t kControlFrameBufferSize;
@@ -812,10 +732,6 @@ class NET_EXPORT_PRIVATE SpdyFramer {
std::unique_ptr<CharBuffer> altsvc_scratch_;
- // SPDY header compressors.
- std::unique_ptr<z_stream> header_compressor_;
- std::unique_ptr<z_stream> header_decompressor_;
-
std::unique_ptr<HpackEncoder> hpack_encoder_;
std::unique_ptr<HpackDecoderInterface> hpack_decoder_;
@@ -825,33 +741,19 @@ class NET_EXPORT_PRIVATE SpdyFramer {
std::unique_ptr<SpdyHeadersBlockParser> header_parser_;
SpdyHeadersHandlerInterface* header_handler_;
- std::string display_protocol_;
-
// Optional decoder to use instead of this instance.
std::unique_ptr<SpdyFramerDecoderAdapter> decoder_adapter_;
- // The protocol version to be spoken/understood by this framer.
- const SpdyMajorVersion protocol_version_;
-
// The flags field of the frame currently being read.
uint8_t current_frame_flags_;
- // Determines whether HPACK or gzip compression is used.
- bool enable_compression_;
+ // Determines whether HPACK compression is used.
+ const CompressionOption compression_option_;
- // Tracks if we've ever gotten far enough in framing to see a control frame of
- // type SYN_STREAM or SYN_REPLY.
- //
- // If we ever get something which looks like a data frame before we've had a
- // SYN, we explicitly check to see if it looks like we got an HTTP response
- // to a SPDY request. This boolean lets us do that.
- bool syn_frame_processed_;
-
- // If we ever get a data frame before a SYN frame, we check to see if it
- // starts with HTTP. If it does, we likely have an HTTP response. This
- // isn't guaranteed though: we could have gotten a settings frame and then
- // corrupt data that just looks like HTTP, but deterministic checking requires
- // a lot more state.
+ // On the first read, we check to see if the data starts with HTTP.
+ // If it does, we likely have an HTTP response. This isn't guaranteed
+ // though: we could have gotten a settings frame and then corrupt data that
+ // just looks like HTTP, but deterministic checking requires a lot more state.
bool probable_http_response_;
// If a HEADERS frame is followed by a CONTINUATION frame, the FIN/END_STREAM
@@ -863,6 +765,9 @@ class NET_EXPORT_PRIVATE SpdyFramer {
// If true, then ProcessInput returns after processing a full frame,
// rather than reading all available input.
bool process_single_input_frame_ = false;
+
+ // Latched value of FLAGS_chromium_http2_flag_remove_rewritelength.
+ bool skip_rewritelength_ = false;
};
} // namespace net
diff --git a/chromium/net/spdy/spdy_framer_decoder_adapter.cc b/chromium/net/spdy/spdy_framer_decoder_adapter.cc
index 4a81839a1c6..3e7a7fefca2 100644
--- a/chromium/net/spdy/spdy_framer_decoder_adapter.cc
+++ b/chromium/net/spdy/spdy_framer_decoder_adapter.cc
@@ -48,6 +48,13 @@ void SpdyFramerVisitorAdapter::OnError(SpdyFramer* framer) {
visitor_->OnError(framer_);
}
+void SpdyFramerVisitorAdapter::OnCommonHeader(SpdyStreamId stream_id,
+ size_t length,
+ uint8_t type,
+ uint8_t flags) {
+ visitor_->OnCommonHeader(stream_id, length, type, flags);
+}
+
void SpdyFramerVisitorAdapter::OnDataFrameHeader(SpdyStreamId stream_id,
size_t length,
bool fin) {
@@ -79,28 +86,14 @@ void SpdyFramerVisitorAdapter::OnHeaderFrameEnd(SpdyStreamId stream_id,
visitor_->OnHeaderFrameEnd(stream_id, end_headers);
}
-void SpdyFramerVisitorAdapter::OnSynStream(SpdyStreamId stream_id,
- SpdyStreamId associated_stream_id,
- SpdyPriority priority,
- bool fin,
- bool unidirectional) {
- visitor_->OnSynStream(stream_id, associated_stream_id, priority, fin,
- unidirectional);
-}
-
-void SpdyFramerVisitorAdapter::OnSynReply(SpdyStreamId stream_id, bool fin) {
- visitor_->OnSynReply(stream_id, fin);
-}
-
void SpdyFramerVisitorAdapter::OnRstStream(SpdyStreamId stream_id,
SpdyRstStreamStatus status) {
visitor_->OnRstStream(stream_id, status);
}
void SpdyFramerVisitorAdapter::OnSetting(SpdySettingsIds id,
- uint8_t flags,
uint32_t value) {
- visitor_->OnSetting(id, flags, value);
+ visitor_->OnSetting(id, value);
}
void SpdyFramerVisitorAdapter::OnPing(SpdyPingId unique_id, bool is_ack) {
@@ -190,7 +183,10 @@ class NestedSpdyFramerDecoder : public SpdyFramerDecoderAdapter {
public:
explicit NestedSpdyFramerDecoder(SpdyFramer* outer)
- : framer_(HTTP2, nullptr), outer_(outer) {
+ : framer_(nullptr,
+ outer->compression_enabled() ? SpdyFramer::ENABLE_COMPRESSION
+ : SpdyFramer::DISABLE_COMPRESSION),
+ outer_(outer) {
DVLOG(1) << PRETTY_THIS;
}
~NestedSpdyFramerDecoder() override { DVLOG(1) << PRETTY_THIS; }
diff --git a/chromium/net/spdy/spdy_framer_decoder_adapter.h b/chromium/net/spdy/spdy_framer_decoder_adapter.h
index d2df45bda9d..59a33d09ab6 100644
--- a/chromium/net/spdy/spdy_framer_decoder_adapter.h
+++ b/chromium/net/spdy/spdy_framer_decoder_adapter.h
@@ -54,9 +54,10 @@ class SpdyFramerDecoderAdapter {
return process_single_input_frame_;
}
- // Decode the |len| bytes of encoded HTTP/2 starting at |*data|. Returns the
- // number of bytes consumed. It is safe to pass more bytes in than may be
- // consumed.
+ // Decode the |len| bytes of encoded HTTP/2 starting at |*data|. Returns
+ // the number of bytes consumed. It is safe to pass more bytes in than
+ // may be consumed. Should process (or otherwise buffer) as much as
+ // available, unless process_single_input_frame is true.
virtual size_t ProcessInput(const char* data, size_t len) = 0;
// Reset the decoder (used just for tests at this time).
@@ -68,9 +69,9 @@ class SpdyFramerDecoderAdapter {
// Current error code (NO_ERROR if state != ERROR).
virtual SpdyFramer::SpdyError error_code() const = 0;
- // Did the most recently decoded frame header appear to be the start of an
- // HTTP/1.1 (or earlier) response? Used to detect if a backend/server that
- // we sent a request to, responded with an HTTP/1.1 response?
+ // Has any frame header looked like the start of an HTTP/1.1 (or earlier)
+ // response? Used to detect if a backend/server that we sent a request to
+ // has responded with an HTTP/1.1 (or earlier) response.
virtual bool probable_http_response() const = 0;
private:
@@ -99,6 +100,10 @@ class SpdyFramerVisitorAdapter : public SpdyFramerVisitorInterface {
// The visitor needs the original SpdyFramer, not the SpdyFramerDecoderAdapter
// instance.
void OnError(SpdyFramer* framer) override;
+ void OnCommonHeader(SpdyStreamId stream_id,
+ size_t length,
+ uint8_t type,
+ uint8_t flags) override;
void OnDataFrameHeader(SpdyStreamId stream_id,
size_t length,
bool fin) override;
@@ -110,14 +115,8 @@ class SpdyFramerVisitorAdapter : public SpdyFramerVisitorInterface {
SpdyHeadersHandlerInterface* OnHeaderFrameStart(
SpdyStreamId stream_id) override;
void OnHeaderFrameEnd(SpdyStreamId stream_id, bool end_headers) override;
- void OnSynStream(SpdyStreamId stream_id,
- SpdyStreamId associated_stream_id,
- SpdyPriority priority,
- bool fin,
- bool unidirectional) override;
- void OnSynReply(SpdyStreamId stream_id, bool fin) override;
void OnRstStream(SpdyStreamId stream_id, SpdyRstStreamStatus status) override;
- void OnSetting(SpdySettingsIds id, uint8_t flags, uint32_t value) override;
+ void OnSetting(SpdySettingsIds id, uint32_t value) override;
void OnPing(SpdyPingId unique_id, bool is_ack) override;
void OnSettings(bool clear_persisted) override;
void OnSettingsAck() override;
diff --git a/chromium/net/spdy/spdy_framer_test.cc b/chromium/net/spdy/spdy_framer_test.cc
index 7166290325a..e3b3fff96b1 100644
--- a/chromium/net/spdy/spdy_framer_test.cc
+++ b/chromium/net/spdy/spdy_framer_test.cc
@@ -11,6 +11,7 @@
#include <limits>
#include <memory>
#include <string>
+#include <tuple>
#include <vector>
#include "base/compiler_specific.h"
@@ -27,6 +28,7 @@
#include "net/spdy/spdy_protocol.h"
#include "net/spdy/spdy_test_utils.h"
#include "testing/gmock/include/gmock/gmock.h"
+#include "testing/gtest/include/gtest/gtest.h"
#include "testing/platform_test.h"
using base::StringPiece;
@@ -67,8 +69,7 @@ class SpdyFramerTestUtil {
CHECK_EQ(frame.size(), framer->ProcessInput(frame.data(), frame.size()));
CHECK_EQ(SpdyFramer::SPDY_READY_FOR_FRAME, framer->state());
framer->set_visitor(nullptr);
- SpdyFramer serializer(framer->protocol_version());
- serializer.set_enable_compression(false);
+ SpdyFramer serializer(SpdyFramer::DISABLE_COMPRESSION);
return serializer.SerializeFrame(visitor.GetFrame());
}
@@ -98,25 +99,6 @@ class SpdyFramerTestUtil {
}
}
- void OnSynStream(SpdyStreamId stream_id,
- SpdyStreamId associated_stream_id,
- SpdyPriority priority,
- bool fin,
- bool unidirectional) override {
- SpdySynStreamIR* syn_stream = new SpdySynStreamIR(stream_id);
- syn_stream->set_associated_to_stream_id(associated_stream_id);
- syn_stream->set_priority(priority);
- syn_stream->set_fin(fin);
- syn_stream->set_unidirectional(unidirectional);
- frame_.reset(syn_stream);
- }
-
- void OnSynReply(SpdyStreamId stream_id, bool fin) override {
- SpdyHeadersIR* headers = new SpdyHeadersIR(stream_id);
- headers->set_fin(fin);
- frame_.reset(headers);
- }
-
void OnHeaders(SpdyStreamId stream_id,
bool has_priority,
int weight,
@@ -169,9 +151,7 @@ class SpdyFramerTestUtil {
SpdyRstStreamStatus status) override {
LOG(FATAL);
}
- void OnSetting(SpdySettingsIds id, uint8_t flags, uint32_t value) override {
- LOG(FATAL);
- }
+ void OnSetting(SpdySettingsIds id, uint32_t value) override { LOG(FATAL); }
void OnPing(SpdyPingId unique_id, bool is_ack) override { LOG(FATAL); }
void OnSettingsEnd() override { LOG(FATAL); }
void OnGoAway(SpdyStreamId last_accepted_stream_id,
@@ -266,21 +246,18 @@ class SpdyFramerPeer {
const SpdyHeadersIR& headers) {
SpdySerializedFrame serialized_headers_old_version =
framer->SerializeHeaders(headers);
- if (framer->protocol_version() == HTTP2) {
- framer->hpack_encoder_.reset(nullptr);
- auto saved_debug_visitor = framer->debug_visitor_;
- framer->debug_visitor_ = nullptr;
-
- std::vector<SpdySerializedFrame> frame_list;
- SpdyFramer::SpdyHeaderFrameIterator it(framer,
- CloneSpdyHeadersIR(headers));
- while (it.HasNextFrame()) {
- frame_list.push_back(it.NextFrame());
- }
- framer->debug_visitor_ = saved_debug_visitor;
-
- EXPECT_THAT(serialized_headers_old_version, IsFrameUnionOf(&frame_list));
+ framer->hpack_encoder_.reset(nullptr);
+ auto saved_debug_visitor = framer->debug_visitor_;
+ framer->debug_visitor_ = nullptr;
+
+ std::vector<SpdySerializedFrame> frame_list;
+ SpdyFramer::SpdyHeaderFrameIterator it(framer, CloneSpdyHeadersIR(headers));
+ while (it.HasNextFrame()) {
+ frame_list.push_back(it.NextFrame());
}
+ framer->debug_visitor_ = saved_debug_visitor;
+
+ EXPECT_THAT(serialized_headers_old_version, IsFrameUnionOf(&frame_list));
return serialized_headers_old_version;
}
};
@@ -292,12 +269,9 @@ class TestSpdyVisitor : public SpdyFramerVisitorInterface,
// are too long can spill over into CONTINUATION frames.
static const size_t kDefaultHeaderBufferSize = 16 * 1024 * 1024;
- explicit TestSpdyVisitor(SpdyMajorVersion version)
- : framer_(version),
- use_compression_(false),
+ explicit TestSpdyVisitor(SpdyFramer::CompressionOption option)
+ : framer_(option),
error_count_(0),
- syn_frame_count_(0),
- syn_reply_frame_count_(0),
headers_frame_count_(0),
push_promise_frame_count_(0),
goaway_count_(0),
@@ -384,37 +358,6 @@ class TestSpdyVisitor : public SpdyFramerVisitorInterface,
}
}
- void OnSynStream(SpdyStreamId stream_id,
- SpdyStreamId associated_stream_id,
- SpdyPriority priority,
- bool fin,
- bool unidirectional) override {
- VLOG(1) << "OnSynStream(" << stream_id << ", " << associated_stream_id
- << ", " << priority << ", " << (fin ? 1 : 0) << ", "
- << (unidirectional ? 1 : 0) << ")";
- ++syn_frame_count_;
- if (framer_.protocol_version() == SPDY3) {
- InitHeaderStreaming(SYN_STREAM, stream_id);
- } else {
- InitHeaderStreaming(HEADERS, stream_id);
- }
- if (fin) {
- ++fin_flag_count_;
- }
- }
-
- void OnSynReply(SpdyStreamId stream_id, bool fin) override {
- ++syn_reply_frame_count_;
- if (framer_.protocol_version() == SPDY3) {
- InitHeaderStreaming(SYN_REPLY, stream_id);
- } else {
- InitHeaderStreaming(HEADERS, stream_id);
- }
- if (fin) {
- ++fin_flag_count_;
- }
- }
-
void OnRstStream(SpdyStreamId stream_id,
SpdyRstStreamStatus status) override {
VLOG(1) << "OnRstStream(" << stream_id << ", " << status << ")";
@@ -428,23 +371,19 @@ class TestSpdyVisitor : public SpdyFramerVisitorInterface,
return true;
}
- void OnSetting(SpdySettingsIds id, uint8_t flags, uint32_t value) override {
- VLOG(1) << "OnSetting(" << id << ", " << std::hex << flags << ", " << value
- << ")";
+ void OnSetting(SpdySettingsIds id, uint32_t value) override {
+ VLOG(1) << "OnSetting(" << id << ", " << std::hex << ", " << value << ")";
++setting_count_;
}
void OnSettingsAck() override {
VLOG(1) << "OnSettingsAck";
- DCHECK_EQ(HTTP2, framer_.protocol_version());
++settings_ack_received_;
}
void OnSettingsEnd() override {
VLOG(1) << "OnSettingsEnd";
- if (framer_.protocol_version() == HTTP2) {
- ++settings_ack_sent_;
- }
+ ++settings_ack_sent_;
}
void OnPing(SpdyPingId unique_id, bool is_ack) override {
@@ -551,7 +490,6 @@ class TestSpdyVisitor : public SpdyFramerVisitorInterface,
// Convenience function which runs a framer simulation with particular input.
void SimulateInFramer(const unsigned char* input, size_t size) {
- framer_.set_enable_compression(use_compression_);
framer_.set_visitor(this);
size_t input_remaining = size;
const char* input_ptr = reinterpret_cast<const char*>(input);
@@ -571,10 +509,7 @@ class TestSpdyVisitor : public SpdyFramerVisitorInterface,
void InitHeaderStreaming(SpdyFrameType header_control_type,
SpdyStreamId stream_id) {
- if (!SpdyConstants::IsValidFrameType(
- framer_.protocol_version(),
- SpdyConstants::SerializeFrameType(framer_.protocol_version(),
- header_control_type))) {
+ if (!IsValidFrameType(SerializeFrameType(header_control_type))) {
DLOG(FATAL) << "Attempted to init header streaming with "
<< "invalid control frame type: " << header_control_type;
}
@@ -609,12 +544,9 @@ class TestSpdyVisitor : public SpdyFramerVisitorInterface,
}
SpdyFramer framer_;
- bool use_compression_;
// Counters from the visitor callbacks.
int error_count_;
- int syn_frame_count_;
- int syn_reply_frame_count_;
int headers_frame_count_;
int push_promise_frame_count_;
int goaway_count_;
@@ -657,47 +589,61 @@ class TestSpdyVisitor : public SpdyFramerVisitorInterface,
bool header_exclusive_;
};
-// Retrieves serialized headers from a HEADERS or SYN_STREAM frame.
+// Retrieves serialized headers from a HEADERS frame.
StringPiece GetSerializedHeaders(const SpdySerializedFrame& frame,
const SpdyFramer& framer) {
SpdyFrameReader reader(frame.data(), frame.size());
- if (framer.protocol_version() == SPDY3) {
- reader.Seek(2); // Seek past the frame length.
- } else {
- reader.Seek(3); // Seek past the frame length.
- }
- SpdyFrameType frame_type;
- if (framer.protocol_version() == SPDY3) {
- uint16_t serialized_type;
- reader.ReadUInt16(&serialized_type);
- frame_type = SpdyConstants::ParseFrameType(framer.protocol_version(),
- serialized_type);
- DCHECK(frame_type == HEADERS || frame_type == SYN_STREAM) << frame_type;
- } else {
- uint8_t serialized_type;
- reader.ReadUInt8(&serialized_type);
- frame_type = SpdyConstants::ParseFrameType(framer.protocol_version(),
- serialized_type);
- DCHECK_EQ(HEADERS, frame_type);
- uint8_t flags;
- reader.ReadUInt8(&flags);
- if (flags & HEADERS_FLAG_PRIORITY) {
- frame_type = SYN_STREAM;
- }
- }
+ reader.Seek(3); // Seek past the frame length.
- if (frame_type == SYN_STREAM) {
- return StringPiece(frame.data() + framer.GetSynStreamMinimumSize(),
- frame.size() - framer.GetSynStreamMinimumSize());
- } else {
- return StringPiece(frame.data() + framer.GetHeadersMinimumSize(),
- frame.size() - framer.GetHeadersMinimumSize());
- }
+ uint8_t serialized_type;
+ reader.ReadUInt8(&serialized_type);
+
+ SpdyFrameType type = ParseFrameType(serialized_type);
+ DCHECK_EQ(HEADERS, type);
+ uint8_t flags;
+ reader.ReadUInt8(&flags);
+
+ return StringPiece(frame.data() + framer.GetHeadersMinimumSize(),
+ frame.size() - framer.GetHeadersMinimumSize());
}
-class SpdyFramerTest : public ::testing::TestWithParam<SpdyMajorVersion> {
+enum DecoderChoice { DECODER_SELF, DECODER_NESTED, DECODER_HTTP2 };
+enum HpackChoice { HPACK_DECODER_1, HPACK_DECODER_2, HPACK_DECODER_3 };
+
+class SpdyFramerTest
+ : public ::testing::TestWithParam<std::tuple<DecoderChoice, HpackChoice>> {
protected:
- void SetUp() override { spdy_version_ = GetParam(); }
+ void SetUp() override {
+ auto param = GetParam();
+ switch (std::get<0>(param)) {
+ case DECODER_SELF:
+ FLAGS_use_nested_spdy_framer_decoder = false;
+ FLAGS_use_http2_frame_decoder_adapter = false;
+ break;
+ case DECODER_NESTED:
+ FLAGS_use_nested_spdy_framer_decoder = true;
+ FLAGS_use_http2_frame_decoder_adapter = false;
+ break;
+ case DECODER_HTTP2:
+ FLAGS_use_nested_spdy_framer_decoder = false;
+ FLAGS_use_http2_frame_decoder_adapter = true;
+ break;
+ }
+ switch (std::get<1>(param)) {
+ case HPACK_DECODER_1:
+ FLAGS_chromium_http2_flag_spdy_use_hpack_decoder2 = false;
+ FLAGS_chromium_http2_flag_spdy_use_hpack_decoder3 = false;
+ break;
+ case HPACK_DECODER_2:
+ FLAGS_chromium_http2_flag_spdy_use_hpack_decoder2 = true;
+ FLAGS_chromium_http2_flag_spdy_use_hpack_decoder3 = false;
+ break;
+ case HPACK_DECODER_3:
+ FLAGS_chromium_http2_flag_spdy_use_hpack_decoder2 = false;
+ FLAGS_chromium_http2_flag_spdy_use_hpack_decoder3 = true;
+ break;
+ }
+ }
void CompareFrame(const string& description,
const SpdySerializedFrame& actual_frame,
@@ -719,48 +665,18 @@ class SpdyFramerTest : public ::testing::TestWithParam<SpdyMajorVersion> {
reinterpret_cast<const unsigned char*>(actual_frame.data()),
actual_frame.size());
}
-
- bool IsSpdy3() { return spdy_version_ == SPDY3; }
- bool IsHttp2() { return spdy_version_ == HTTP2; }
-
- // Version of SPDY protocol to be used.
- SpdyMajorVersion spdy_version_;
};
-// All tests are run with SPDY/3 and HTTP/2.
-INSTANTIATE_TEST_CASE_P(SpdyFramerTests,
- SpdyFramerTest,
- ::testing::Values(SPDY3, HTTP2));
-
-// Test that we ignore cookie where both name and value are empty.
-TEST_P(SpdyFramerTest, HeaderBlockWithEmptyCookie) {
- if (!IsSpdy3()) {
- // Not implemented for hpack.
- return;
- }
-
- SpdyFramer framer(spdy_version_);
- framer.set_enable_compression(true);
- SpdyHeadersIR headers(1);
- headers.SetHeader("cookie",
- "=; key=value; ; = ; foo; bar=; ; = ; k2=v2 ; =");
- SpdySerializedFrame frame(SpdyFramerPeer::SerializeHeaders(&framer, headers));
-
- TestSpdyVisitor visitor(spdy_version_);
- visitor.use_compression_ = true;
- visitor.SimulateInFramer(reinterpret_cast<unsigned char*>(frame.data()),
- frame.size());
-
- EXPECT_EQ(0, visitor.zero_length_control_frame_header_data_count_);
- EXPECT_NE(headers.header_block(), visitor.headers_);
- EXPECT_EQ(1u, visitor.headers_.size());
- EXPECT_EQ("key=value; foo; bar=; k2=v2 ", visitor.headers_["cookie"]);
-}
+INSTANTIATE_TEST_CASE_P(
+ SpdyFramerTests,
+ SpdyFramerTest,
+ ::testing::Combine(
+ ::testing::Values(DECODER_SELF, DECODER_NESTED, DECODER_HTTP2),
+ ::testing::Values(HPACK_DECODER_1, HPACK_DECODER_2, HPACK_DECODER_3)));
// Test that we can encode and decode a SpdyHeaderBlock in serialized form.
TEST_P(SpdyFramerTest, HeaderBlockInBuffer) {
- SpdyFramer framer(spdy_version_);
- framer.set_enable_compression(false);
+ SpdyFramer framer(SpdyFramer::DISABLE_COMPRESSION);
// Encode the header block into a Headers frame.
SpdyHeadersIR headers(1);
@@ -769,8 +685,7 @@ TEST_P(SpdyFramerTest, HeaderBlockInBuffer) {
headers.SetHeader("cookie", "key1=value1; key2=value2");
SpdySerializedFrame frame(SpdyFramerPeer::SerializeHeaders(&framer, headers));
- TestSpdyVisitor visitor(spdy_version_);
- visitor.use_compression_ = false;
+ TestSpdyVisitor visitor(SpdyFramer::DISABLE_COMPRESSION);
visitor.SimulateInFramer(reinterpret_cast<unsigned char*>(frame.data()),
frame.size());
@@ -780,8 +695,7 @@ TEST_P(SpdyFramerTest, HeaderBlockInBuffer) {
// Test that if there's not a full frame, we fail to parse it.
TEST_P(SpdyFramerTest, UndersizedHeaderBlockInBuffer) {
- SpdyFramer framer(spdy_version_);
- framer.set_enable_compression(false);
+ SpdyFramer framer(SpdyFramer::DISABLE_COMPRESSION);
// Encode the header block into a Headers frame.
SpdyHeadersIR headers(1);
@@ -789,8 +703,7 @@ TEST_P(SpdyFramerTest, UndersizedHeaderBlockInBuffer) {
headers.SetHeader("gamma", "charlie");
SpdySerializedFrame frame(SpdyFramerPeer::SerializeHeaders(&framer, headers));
- TestSpdyVisitor visitor(spdy_version_);
- visitor.use_compression_ = false;
+ TestSpdyVisitor visitor(SpdyFramer::DISABLE_COMPRESSION);
visitor.SimulateInFramer(reinterpret_cast<unsigned char*>(frame.data()),
frame.size() - 2);
@@ -798,52 +711,19 @@ TEST_P(SpdyFramerTest, UndersizedHeaderBlockInBuffer) {
EXPECT_EQ(0u, visitor.headers_.size());
}
-// Test that we make all header field names (keys) lower case on encoding.
-TEST_P(SpdyFramerTest, HeaderBlockToLowerCase) {
- // The HPACK encoding path does not lowercase field names.
- if (IsHttp2()) {
- return;
- }
-
- SpdyFramer framer(spdy_version_);
- framer.set_enable_compression(true);
-
- // Encode the header block into a Headers frame.
- SpdyHeadersIR headers_ir(1);
- headers_ir.SetHeader("aLpha", "beta");
- headers_ir.SetHeader("GAMMA", "charlie");
- headers_ir.SetHeader("foo", "Bar"); // Upper case values are okay.
- SpdySerializedFrame frame(
- SpdyFramerPeer::SerializeHeaders(&framer, headers_ir));
- TestSpdyVisitor visitor(spdy_version_);
- visitor.use_compression_ = true;
- visitor.SimulateInFramer(reinterpret_cast<unsigned char*>(frame.data()),
- frame.size());
- EXPECT_EQ(1, visitor.headers_frame_count_);
- EXPECT_EQ(headers_ir.header_block().size(), visitor.headers_.size());
- EXPECT_EQ("beta", visitor.headers_["alpha"]);
- EXPECT_EQ("charlie", visitor.headers_["gamma"]);
- EXPECT_EQ("Bar", visitor.headers_["foo"]);
-}
-
// Test that we treat incoming upper-case or mixed-case header values as
-// malformed for HTTP2.
+// malformed.
TEST_P(SpdyFramerTest, RejectUpperCaseHeaderBlockValue) {
- if (!IsHttp2()) {
- return;
- }
-
- SpdyFramer framer(spdy_version_);
- framer.set_enable_compression(false);
+ SpdyFramer framer(SpdyFramer::DISABLE_COMPRESSION);
- SpdyFrameBuilder frame(1024, spdy_version_);
+ SpdyFrameBuilder frame(1024);
frame.BeginNewFrame(framer, HEADERS, 0, 1);
frame.WriteUInt32(1);
frame.WriteStringPiece32("Name1");
frame.WriteStringPiece32("value1");
frame.RewriteLength(framer);
- SpdyFrameBuilder frame2(1024, spdy_version_);
+ SpdyFrameBuilder frame2(1024);
frame2.BeginNewFrame(framer, HEADERS, 0, 1);
frame2.WriteUInt32(2);
frame2.WriteStringPiece32("name1");
@@ -868,12 +748,7 @@ TEST_P(SpdyFramerTest, RejectUpperCaseHeaderBlockValue) {
// Test that we can encode and decode stream dependency values in a header
// frame.
TEST_P(SpdyFramerTest, HeaderStreamDependencyValues) {
- if (!IsHttp2()) {
- return;
- }
-
- SpdyFramer framer(spdy_version_);
- framer.set_enable_compression(false);
+ SpdyFramer framer(SpdyFramer::DISABLE_COMPRESSION);
const SpdyStreamId parent_stream_id_test_array[] = {0, 3};
for (SpdyStreamId parent_stream_id : parent_stream_id_test_array) {
@@ -886,8 +761,7 @@ TEST_P(SpdyFramerTest, HeaderStreamDependencyValues) {
SpdySerializedFrame frame(
SpdyFramerPeer::SerializeHeaders(&framer, headers));
- TestSpdyVisitor visitor(spdy_version_);
- visitor.use_compression_ = false;
+ TestSpdyVisitor visitor(SpdyFramer::DISABLE_COMPRESSION);
visitor.SimulateInFramer(reinterpret_cast<unsigned char*>(frame.data()),
frame.size());
@@ -901,12 +775,8 @@ TEST_P(SpdyFramerTest, HeaderStreamDependencyValues) {
// Test that if we receive a frame with payload length field at the
// advertised max size, we do not set an error in ProcessInput.
TEST_P(SpdyFramerTest, AcceptMaxFrameSizeSetting) {
- if (!IsHttp2()) {
- return;
- }
-
testing::StrictMock<test::MockSpdyFramerVisitor> visitor;
- SpdyFramer framer(spdy_version_);
+ SpdyFramer framer(SpdyFramer::ENABLE_COMPRESSION);
framer.set_visitor(&visitor);
// DATA frame with maximum allowed payload length.
@@ -930,12 +800,8 @@ TEST_P(SpdyFramerTest, AcceptMaxFrameSizeSetting) {
// Test that if we receive a frame with payload length larger than the
// advertised max size, we set an error of SPDY_INVALID_CONTROL_FRAME_SIZE.
TEST_P(SpdyFramerTest, ExceedMaxFrameSizeSetting) {
- if (!IsHttp2()) {
- return;
- }
-
testing::StrictMock<test::MockSpdyFramerVisitor> visitor;
- SpdyFramer framer(spdy_version_);
+ SpdyFramer framer(SpdyFramer::ENABLE_COMPRESSION);
framer.set_visitor(&visitor);
// DATA frame with too large payload length.
@@ -960,12 +826,8 @@ TEST_P(SpdyFramerTest, ExceedMaxFrameSizeSetting) {
// Test that if we receive a DATA frame with padding length larger than the
// payload length, we set an error of SPDY_INVALID_PADDING
TEST_P(SpdyFramerTest, OversizedDataPaddingError) {
- if (!IsHttp2()) {
- return;
- }
-
testing::StrictMock<test::MockSpdyFramerVisitor> visitor;
- SpdyFramer framer(spdy_version_);
+ SpdyFramer framer(SpdyFramer::ENABLE_COMPRESSION);
framer.set_visitor(&visitor);
// DATA frame with invalid padding length.
@@ -999,12 +861,8 @@ TEST_P(SpdyFramerTest, OversizedDataPaddingError) {
// Test that if we receive a DATA frame with padding length not larger than the
// payload length, we do not set an error of SPDY_INVALID_PADDING
TEST_P(SpdyFramerTest, CorrectlySizedDataPaddingNoError) {
- if (!IsHttp2()) {
- return;
- }
-
testing::StrictMock<test::MockSpdyFramerVisitor> visitor;
- SpdyFramer framer(spdy_version_);
+ SpdyFramer framer(SpdyFramer::ENABLE_COMPRESSION);
framer.set_visitor(&visitor);
// DATA frame with valid Padding length
@@ -1038,12 +896,8 @@ TEST_P(SpdyFramerTest, CorrectlySizedDataPaddingNoError) {
// Test that if we receive a HEADERS frame with padding length larger than the
// payload length, we set an error of SPDY_INVALID_PADDING
TEST_P(SpdyFramerTest, OversizedHeadersPaddingError) {
- if (!IsHttp2()) {
- return;
- }
-
testing::StrictMock<test::MockSpdyFramerVisitor> visitor;
- SpdyFramer framer(spdy_version_);
+ SpdyFramer framer(SpdyFramer::ENABLE_COMPRESSION);
framer.set_visitor(&visitor);
// HEADERS frame with invalid padding length.
@@ -1074,12 +928,8 @@ TEST_P(SpdyFramerTest, OversizedHeadersPaddingError) {
// Test that if we receive a HEADERS frame with padding length not larger
// than the payload length, we do not set an error of SPDY_INVALID_PADDING
TEST_P(SpdyFramerTest, CorrectlySizedHeadersPaddingNoError) {
- if (!IsHttp2()) {
- return;
- }
-
testing::StrictMock<test::MockSpdyFramerVisitor> visitor;
- SpdyFramer framer(spdy_version_);
+ SpdyFramer framer(SpdyFramer::ENABLE_COMPRESSION);
framer.set_visitor(&visitor);
// HEADERS frame with invalid Padding length
@@ -1102,38 +952,11 @@ TEST_P(SpdyFramerTest, CorrectlySizedHeadersPaddingNoError) {
<< SpdyFramer::ErrorCodeToString(framer.error_code());
}
-// Test that if we receive a SYN_REPLY with stream ID zero, we signal an error
-// (but don't crash).
-TEST_P(SpdyFramerTest, SynReplyWithStreamIdZero) {
- if (!IsSpdy3()) {
- return;
- }
-
- testing::StrictMock<test::MockSpdyFramerVisitor> visitor;
- SpdyFramer framer(spdy_version_);
- framer.set_visitor(&visitor);
-
- SpdySynReplyIR syn_reply(0);
- syn_reply.SetHeader("alpha", "beta");
- SpdySerializedFrame frame(framer.SerializeSynReply(syn_reply));
-
- // We shouldn't have to read the whole frame before we signal an error.
- EXPECT_CALL(visitor, OnError(testing::Eq(&framer)));
- EXPECT_GT(frame.size(), framer.ProcessInput(frame.data(), frame.size()));
- EXPECT_TRUE(framer.HasError());
- EXPECT_EQ(SpdyFramer::SPDY_INVALID_CONTROL_FRAME, framer.error_code())
- << SpdyFramer::ErrorCodeToString(framer.error_code());
-}
-
// Test that if we receive a DATA with stream ID zero, we signal an error
// (but don't crash).
TEST_P(SpdyFramerTest, DataWithStreamIdZero) {
- if (!IsHttp2()) {
- return;
- }
-
testing::StrictMock<test::MockSpdyFramerVisitor> visitor;
- SpdyFramer framer(spdy_version_);
+ SpdyFramer framer(SpdyFramer::ENABLE_COMPRESSION);
framer.set_visitor(&visitor);
const char bytes[] = "hello";
@@ -1152,7 +975,7 @@ TEST_P(SpdyFramerTest, DataWithStreamIdZero) {
// (but don't crash).
TEST_P(SpdyFramerTest, HeadersWithStreamIdZero) {
testing::StrictMock<test::MockSpdyFramerVisitor> visitor;
- SpdyFramer framer(spdy_version_);
+ SpdyFramer framer(SpdyFramer::ENABLE_COMPRESSION);
framer.set_visitor(&visitor);
SpdyHeadersIR headers(0);
@@ -1163,24 +986,15 @@ TEST_P(SpdyFramerTest, HeadersWithStreamIdZero) {
EXPECT_CALL(visitor, OnError(testing::Eq(&framer)));
EXPECT_GT(frame.size(), framer.ProcessInput(frame.data(), frame.size()));
EXPECT_TRUE(framer.HasError());
- if (IsHttp2()) {
- EXPECT_EQ(SpdyFramer::SPDY_INVALID_STREAM_ID, framer.error_code())
- << SpdyFramer::ErrorCodeToString(framer.error_code());
- } else {
- EXPECT_EQ(SpdyFramer::SPDY_INVALID_CONTROL_FRAME, framer.error_code())
- << SpdyFramer::ErrorCodeToString(framer.error_code());
- }
+ EXPECT_EQ(SpdyFramer::SPDY_INVALID_STREAM_ID, framer.error_code())
+ << SpdyFramer::ErrorCodeToString(framer.error_code());
}
// Test that if we receive a PRIORITY with stream ID zero, we signal an error
// (but don't crash).
TEST_P(SpdyFramerTest, PriorityWithStreamIdZero) {
- if (!IsHttp2()) {
- return;
- }
-
testing::StrictMock<test::MockSpdyFramerVisitor> visitor;
- SpdyFramer framer(spdy_version_);
+ SpdyFramer framer(SpdyFramer::ENABLE_COMPRESSION);
framer.set_visitor(&visitor);
SpdyPriorityIR priority_ir(0, 1, 16, true);
@@ -1197,12 +1011,8 @@ TEST_P(SpdyFramerTest, PriorityWithStreamIdZero) {
// Test that if we receive a RST_STREAM with stream ID zero, we signal an error
// (but don't crash).
TEST_P(SpdyFramerTest, RstStreamWithStreamIdZero) {
- if (!IsHttp2()) {
- return;
- }
-
testing::StrictMock<test::MockSpdyFramerVisitor> visitor;
- SpdyFramer framer(spdy_version_);
+ SpdyFramer framer(SpdyFramer::ENABLE_COMPRESSION);
framer.set_visitor(&visitor);
SpdyRstStreamIR rst_stream_ir(0, RST_STREAM_PROTOCOL_ERROR);
@@ -1219,12 +1029,8 @@ TEST_P(SpdyFramerTest, RstStreamWithStreamIdZero) {
// Test that if we receive a SETTINGS with stream ID other than zero,
// we signal an error (but don't crash).
TEST_P(SpdyFramerTest, SettingsWithStreamIdNotZero) {
- if (!IsHttp2()) {
- return;
- }
-
testing::StrictMock<test::MockSpdyFramerVisitor> visitor;
- SpdyFramer framer(spdy_version_);
+ SpdyFramer framer(SpdyFramer::ENABLE_COMPRESSION);
framer.set_visitor(&visitor);
// Settings frame with invalid StreamID of 0x01
@@ -1250,12 +1056,8 @@ TEST_P(SpdyFramerTest, SettingsWithStreamIdNotZero) {
// Test that if we receive a GOAWAY with stream ID other than zero,
// we signal an error (but don't crash).
TEST_P(SpdyFramerTest, GoawayWithStreamIdNotZero) {
- if (!IsHttp2()) {
- return;
- }
-
testing::StrictMock<test::MockSpdyFramerVisitor> visitor;
- SpdyFramer framer(spdy_version_);
+ SpdyFramer framer(SpdyFramer::ENABLE_COMPRESSION);
framer.set_visitor(&visitor);
// GOAWAY frame with invalid StreamID of 0x01
@@ -1282,12 +1084,8 @@ TEST_P(SpdyFramerTest, GoawayWithStreamIdNotZero) {
// Test that if we receive a CONTINUATION with stream ID zero, we signal an
// SPDY_INVALID_STREAM_ID.
TEST_P(SpdyFramerTest, ContinuationWithStreamIdZero) {
- if (!IsHttp2()) {
- return;
- }
-
testing::StrictMock<test::MockSpdyFramerVisitor> visitor;
- SpdyFramer framer(spdy_version_);
+ SpdyFramer framer(SpdyFramer::ENABLE_COMPRESSION);
framer.set_visitor(&visitor);
SpdyContinuationIR continuation(0);
@@ -1308,12 +1106,8 @@ TEST_P(SpdyFramerTest, ContinuationWithStreamIdZero) {
// Test that if we receive a PUSH_PROMISE with stream ID zero, we signal an
// SPDY_INVALID_STREAM_ID.
TEST_P(SpdyFramerTest, PushPromiseWithStreamIdZero) {
- if (!IsHttp2()) {
- return;
- }
-
testing::StrictMock<test::MockSpdyFramerVisitor> visitor;
- SpdyFramer framer(spdy_version_);
+ SpdyFramer framer(SpdyFramer::ENABLE_COMPRESSION);
framer.set_visitor(&visitor);
SpdyPushPromiseIR push_promise(0, 4);
@@ -1331,45 +1125,26 @@ TEST_P(SpdyFramerTest, PushPromiseWithStreamIdZero) {
// Test that if we receive a PUSH_PROMISE with promised stream ID zero, we
// signal SPDY_INVALID_STREAM_ID.
TEST_P(SpdyFramerTest, PushPromiseWithPromisedStreamIdZero) {
- if (!IsHttp2()) {
- return;
- }
-
testing::StrictMock<test::MockSpdyFramerVisitor> visitor;
- SpdyFramer framer(spdy_version_);
+ SpdyFramer framer(SpdyFramer::ENABLE_COMPRESSION);
framer.set_visitor(&visitor);
SpdyPushPromiseIR push_promise(3, 0);
push_promise.SetHeader("alpha", "beta");
SpdySerializedFrame frame(framer.SerializePushPromise(push_promise));
- // We shouldn't have to read the whole frame before we signal an error.
EXPECT_CALL(visitor, OnError(testing::Eq(&framer)));
- EXPECT_GT(frame.size(), framer.ProcessInput(frame.data(), frame.size()));
+ framer.ProcessInput(frame.data(), frame.size());
EXPECT_TRUE(framer.HasError());
EXPECT_EQ(SpdyFramer::SPDY_INVALID_CONTROL_FRAME, framer.error_code())
<< SpdyFramer::ErrorCodeToString(framer.error_code());
}
TEST_P(SpdyFramerTest, DuplicateHeader) {
- if (!IsSpdy3()) {
- // TODO(jgraettinger): Punting on this because we haven't determined
- // whether duplicate HPACK headers other than Cookie are an error.
- // If they are, this will need to be updated to use HpackOutputStream.
- return;
- }
- SpdyFramer framer(spdy_version_);
+ SpdyFramer framer(SpdyFramer::DISABLE_COMPRESSION);
// Frame builder with plentiful buffer size.
- SpdyFrameBuilder frame(1024, spdy_version_);
- if (spdy_version_ <= SPDY3) {
- frame.WriteControlFrameHeader(framer, SYN_STREAM, CONTROL_FLAG_NONE);
- frame.WriteUInt32(3); // stream_id
- frame.WriteUInt32(0); // associated stream id
- frame.WriteUInt16(0); // Priority.
- } else {
- frame.BeginNewFrame(framer, HEADERS, HEADERS_FLAG_PRIORITY, 3);
- frame.WriteUInt32(framer.GetHighestPriority());
- }
+ SpdyFrameBuilder frame(1024);
+ frame.BeginNewFrame(framer, HEADERS, 0, 3);
frame.WriteUInt32(2); // Number of headers.
frame.WriteStringPiece32("name");
@@ -1380,7 +1155,6 @@ TEST_P(SpdyFramerTest, DuplicateHeader) {
frame.RewriteLength(framer);
SpdyHeaderBlock new_headers;
- framer.set_enable_compression(false);
SpdySerializedFrame control_frame(frame.take());
StringPiece serialized_headers = GetSerializedHeaders(control_frame, framer);
// This should fail because duplicate headers are verboten by the spec.
@@ -1389,43 +1163,29 @@ TEST_P(SpdyFramerTest, DuplicateHeader) {
}
TEST_P(SpdyFramerTest, MultiValueHeader) {
- SpdyFramer framer(spdy_version_);
+ SpdyFramer framer(SpdyFramer::DISABLE_COMPRESSION);
// Frame builder with plentiful buffer size.
- SpdyFrameBuilder frame(1024, spdy_version_);
- if (IsSpdy3()) {
- frame.WriteControlFrameHeader(framer, SYN_STREAM, CONTROL_FLAG_NONE);
- frame.WriteUInt32(3); // stream_id
- frame.WriteUInt32(0); // associated stream id
- frame.WriteUInt16(0); // Priority.
- } else {
- frame.BeginNewFrame(framer, HEADERS,
- HEADERS_FLAG_PRIORITY | HEADERS_FLAG_END_HEADERS, 3);
- frame.WriteUInt32(0); // Priority exclusivity and dependent stream.
- frame.WriteUInt8(255); // Priority weight.
- }
+ SpdyFrameBuilder frame(1024);
+ frame.BeginNewFrame(framer, HEADERS,
+ HEADERS_FLAG_PRIORITY | HEADERS_FLAG_END_HEADERS, 3);
+ frame.WriteUInt32(0); // Priority exclusivity and dependent stream.
+ frame.WriteUInt8(255); // Priority weight.
string value("value1\0value2", 13);
- if (IsSpdy3()) {
- frame.WriteUInt32(1); // Number of headers.
- frame.WriteStringPiece32("name");
- frame.WriteStringPiece32(value);
- } else {
- // TODO(jgraettinger): If this pattern appears again, move to test class.
- SpdyHeaderBlock header_set;
- header_set["name"] = value;
- string buffer;
- HpackEncoder encoder(ObtainHpackHuffmanTable());
- encoder.EncodeHeaderSetWithoutCompression(header_set, &buffer);
- frame.WriteBytes(&buffer[0], buffer.size());
- }
+ // TODO(jgraettinger): If this pattern appears again, move to test class.
+ SpdyHeaderBlock header_set;
+ header_set["name"] = value;
+ string buffer;
+ HpackEncoder encoder(ObtainHpackHuffmanTable());
+ encoder.DisableCompression();
+ encoder.EncodeHeaderSet(header_set, &buffer);
+ frame.WriteBytes(&buffer[0], buffer.size());
// write the length
frame.RewriteLength(framer);
- framer.set_enable_compression(false);
SpdySerializedFrame control_frame(frame.take());
- TestSpdyVisitor visitor(spdy_version_);
- visitor.use_compression_ = false;
+ TestSpdyVisitor visitor(SpdyFramer::DISABLE_COMPRESSION);
visitor.SimulateInFramer(
reinterpret_cast<unsigned char*>(control_frame.data()),
control_frame.size());
@@ -1434,74 +1194,6 @@ TEST_P(SpdyFramerTest, MultiValueHeader) {
testing::ElementsAre(testing::Pair("name", StringPiece(value))));
}
-TEST_P(SpdyFramerTest, BasicCompression) {
- if (!IsSpdy3()) {
- // Deflate compression doesn't apply to HPACK.
- return;
- }
-
- std::unique_ptr<TestSpdyVisitor> visitor(new TestSpdyVisitor(spdy_version_));
- SpdyFramer framer(spdy_version_);
- framer.set_debug_visitor(visitor.get());
- SpdySynStreamIR syn_stream(1);
- syn_stream.set_priority(1);
- syn_stream.SetHeader("server", "SpdyServer 1.0");
- syn_stream.SetHeader("date", "Mon 12 Jan 2009 12:12:12 PST");
- syn_stream.SetHeader("status", "200");
- syn_stream.SetHeader("version", "HTTP/1.1");
- syn_stream.SetHeader("content-type", "text/html");
- syn_stream.SetHeader("content-length", "12");
- SpdySerializedFrame frame1(framer.SerializeSynStream(syn_stream));
- size_t uncompressed_size1 = visitor->last_payload_len_;
- size_t compressed_size1 =
- visitor->last_frame_len_ - framer.GetSynStreamMinimumSize();
- EXPECT_EQ(165u, uncompressed_size1);
-#if defined(USE_SYSTEM_ZLIB)
- EXPECT_EQ(181u, compressed_size1);
-#else // !defined(USE_SYSTEM_ZLIB)
- EXPECT_EQ(116u, compressed_size1);
-#endif // !defined(USE_SYSTEM_ZLIB)
- SpdySerializedFrame frame2(framer.SerializeSynStream(syn_stream));
- size_t uncompressed_size2 = visitor->last_payload_len_;
- size_t compressed_size2 =
- visitor->last_frame_len_ - framer.GetSynStreamMinimumSize();
-
- // Expect the second frame to be more compact than the first.
- EXPECT_LE(frame2.size(), frame1.size());
-
- // Decompress the first frame
- SpdySerializedFrame frame3(
- SpdyFramerTestUtil::DecompressFrame(&framer, frame1));
-
- // Decompress the second frame
- visitor.reset(new TestSpdyVisitor(spdy_version_));
- framer.set_debug_visitor(visitor.get());
- SpdySerializedFrame frame4(
- SpdyFramerTestUtil::DecompressFrame(&framer, frame2));
- size_t uncompressed_size4 = frame4.size() - framer.GetSynStreamMinimumSize();
- size_t compressed_size4 =
- visitor->last_frame_len_ - framer.GetSynStreamMinimumSize();
- EXPECT_EQ(165u, uncompressed_size4);
-#if defined(USE_SYSTEM_ZLIB)
- EXPECT_EQ(175u, compressed_size4);
-#else // !defined(USE_SYSTEM_ZLIB)
- EXPECT_EQ(98u, compressed_size4);
-#endif // !defined(USE_SYSTEM_ZLIB)
-
- EXPECT_EQ(uncompressed_size1, uncompressed_size2);
- EXPECT_EQ(uncompressed_size1, uncompressed_size4);
- EXPECT_EQ(compressed_size2, compressed_size4);
-
- // Expect frames 3 & 4 to be the same.
- CompareFrames("Uncompressed SYN_STREAM", frame3, frame4);
-
- // Expect frames 3 to be the same as a uncompressed frame created
- // from scratch.
- framer.set_enable_compression(false);
- SpdySerializedFrame uncompressed_frame(framer.SerializeSynStream(syn_stream));
- CompareFrames("Uncompressed SYN_STREAM", frame3, uncompressed_frame);
-}
-
TEST_P(SpdyFramerTest, CompressEmptyHeaders) {
// See crbug.com/172383
SpdyHeadersIR headers(1);
@@ -1513,76 +1205,13 @@ TEST_P(SpdyFramerTest, CompressEmptyHeaders) {
headers.SetHeader("content-length", "12");
headers.SetHeader("x-empty-header", "");
- SpdyFramer framer(spdy_version_);
- framer.set_enable_compression(true);
+ SpdyFramer framer(SpdyFramer::ENABLE_COMPRESSION);
SpdySerializedFrame frame1(
SpdyFramerPeer::SerializeHeaders(&framer, headers));
}
TEST_P(SpdyFramerTest, Basic) {
- // clang-format off
- const unsigned char kV3Input[] = {
- 0x80, 0x03, 0x00, 0x01, // SYN Stream #1
- 0x00, 0x00, 0x00, 0x1a,
- 0x00, 0x00, 0x00, 0x01,
- 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x01, 0x00, 0x00,
- 0x00, 0x02, 'h', 'h',
- 0x00, 0x00, 0x00, 0x02,
- 'v', 'v',
-
- 0x80, 0x03, 0x00, 0x08, // HEADERS on Stream #1
- 0x00, 0x00, 0x00, 0x20,
- 0x00, 0x00, 0x00, 0x01,
- 0x00, 0x00, 0x00, 0x02,
- 0x00, 0x00, 0x00, 0x02,
- 'h', '2',
- 0x00, 0x00, 0x00, 0x02,
- 'v', '2', 0x00, 0x00,
- 0x00, 0x02, 'h', '3',
- 0x00, 0x00, 0x00, 0x02,
- 'v', '3',
-
- 0x00, 0x00, 0x00, 0x01, // DATA on Stream #1
- 0x00, 0x00, 0x00, 0x0c,
- 0xde, 0xad, 0xbe, 0xef,
- 0xde, 0xad, 0xbe, 0xef,
- 0xde, 0xad, 0xbe, 0xef,
-
- 0x80, 0x03, 0x00, 0x01, // SYN Stream #3
- 0x00, 0x00, 0x00, 0x0e,
- 0x00, 0x00, 0x00, 0x03,
- 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00,
-
- 0x00, 0x00, 0x00, 0x03, // DATA on Stream #3
- 0x00, 0x00, 0x00, 0x08,
- 0xde, 0xad, 0xbe, 0xef,
- 0xde, 0xad, 0xbe, 0xef,
-
- 0x00, 0x00, 0x00, 0x01, // DATA on Stream #1
- 0x00, 0x00, 0x00, 0x04,
- 0xde, 0xad, 0xbe, 0xef,
-
- 0x80, 0x03, 0x00, 0x03, // RST_STREAM on Stream #1
- 0x00, 0x00, 0x00, 0x08,
- 0x00, 0x00, 0x00, 0x01,
- 0x00, 0x00, 0x00, 0x05, // RST_STREAM_CANCEL
-
- 0x00, 0x00, 0x00, 0x03, // DATA on Stream #3
- 0x00, 0x00, 0x00, 0x00,
-
- 0x80, 0x03, 0x00, 0x03, // RST_STREAM on Stream #3
- 0x00, 0x00, 0x00, 0x08,
- 0x00, 0x00, 0x00, 0x03,
- 0x00, 0x00, 0x00, 0x05, // RST_STREAM_CANCEL
- };
- // clang-format on
-
- // SYN_STREAM doesn't exist in HTTP/2, so instead we send
- // HEADERS frames with PRIORITY and END_HEADERS set.
+ // Send HEADERS frames with PRIORITY and END_HEADERS set.
// frame-format off
const unsigned char kH2Input[] = {
0x00, 0x00, 0x05, // Length: 5
@@ -1645,27 +1274,15 @@ TEST_P(SpdyFramerTest, Basic) {
};
// frame-format on
- TestSpdyVisitor visitor(spdy_version_);
- if (IsSpdy3()) {
- visitor.SimulateInFramer(kV3Input, sizeof(kV3Input));
- } else {
- visitor.SimulateInFramer(kH2Input, sizeof(kH2Input));
- }
+ TestSpdyVisitor visitor(SpdyFramer::DISABLE_COMPRESSION);
+ visitor.SimulateInFramer(kH2Input, sizeof(kH2Input));
- EXPECT_EQ(0, visitor.syn_reply_frame_count_);
EXPECT_EQ(24, visitor.data_bytes_);
EXPECT_EQ(0, visitor.error_count_);
EXPECT_EQ(2, visitor.fin_frame_count_);
- if (IsSpdy3()) {
- EXPECT_EQ(1, visitor.headers_frame_count_);
- EXPECT_EQ(2, visitor.syn_frame_count_);
- EXPECT_TRUE(visitor.fin_opaque_data_.empty());
- } else {
- EXPECT_EQ(3, visitor.headers_frame_count_);
- EXPECT_EQ(0, visitor.syn_frame_count_);
- EXPECT_TRUE(visitor.fin_opaque_data_.empty());
- }
+ EXPECT_EQ(3, visitor.headers_frame_count_);
+ EXPECT_TRUE(visitor.fin_opaque_data_.empty());
EXPECT_EQ(0, visitor.fin_flag_count_);
EXPECT_EQ(0, visitor.end_of_stream_count_);
@@ -1675,40 +1292,7 @@ TEST_P(SpdyFramerTest, Basic) {
// Test that the FIN flag on a data frame signifies EOF.
TEST_P(SpdyFramerTest, FinOnDataFrame) {
- // clang-format off
- const unsigned char kV3Input[] = {
- 0x80, 0x03, 0x00, 0x01, // SYN Stream #1
- 0x00, 0x00, 0x00, 0x1a,
- 0x00, 0x00, 0x00, 0x01,
- 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x01, 0x00, 0x00,
- 0x00, 0x02, 'h', 'h',
- 0x00, 0x00, 0x00, 0x02,
- 'v', 'v',
-
- 0x80, 0x03, 0x00, 0x02, // SYN REPLY Stream #1
- 0x00, 0x00, 0x00, 0x14,
- 0x00, 0x00, 0x00, 0x01,
- 0x00, 0x00, 0x00, 0x01,
- 0x00, 0x00, 0x00, 0x02,
- 'a', 'a', 0x00, 0x00,
- 0x00, 0x02, 'b', 'b',
-
- 0x00, 0x00, 0x00, 0x01, // DATA on Stream #1
- 0x00, 0x00, 0x00, 0x0c,
- 0xde, 0xad, 0xbe, 0xef,
- 0xde, 0xad, 0xbe, 0xef,
- 0xde, 0xad, 0xbe, 0xef,
-
- 0x00, 0x00, 0x00, 0x01, // DATA on Stream #1, with EOF
- 0x01, 0x00, 0x00, 0x04,
- 0xde, 0xad, 0xbe, 0xef,
- };
- // clang-format on
-
- // SYN_STREAM and SYN_REPLY don't exist in HTTP2, so instead we send
- // HEADERS frames with PRIORITY(SYN_STREAM only) and END_HEADERS set.
+ // Send HEADERS frames with END_HEADERS set.
// frame-format off
const unsigned char kH2Input[] = {
0x00, 0x00, 0x05, // Length: 5
@@ -1740,23 +1324,11 @@ TEST_P(SpdyFramerTest, FinOnDataFrame) {
};
// frame-format on
- TestSpdyVisitor visitor(spdy_version_);
- if (IsSpdy3()) {
- visitor.SimulateInFramer(kV3Input, sizeof(kV3Input));
- } else {
- visitor.SimulateInFramer(kH2Input, sizeof(kH2Input));
- }
+ TestSpdyVisitor visitor(SpdyFramer::DISABLE_COMPRESSION);
+ visitor.SimulateInFramer(kH2Input, sizeof(kH2Input));
EXPECT_EQ(0, visitor.error_count_);
- if (IsSpdy3()) {
- EXPECT_EQ(1, visitor.syn_frame_count_);
- EXPECT_EQ(1, visitor.syn_reply_frame_count_);
- EXPECT_EQ(0, visitor.headers_frame_count_);
- } else {
- EXPECT_EQ(0, visitor.syn_frame_count_);
- EXPECT_EQ(0, visitor.syn_reply_frame_count_);
- EXPECT_EQ(2, visitor.headers_frame_count_);
- }
+ EXPECT_EQ(2, visitor.headers_frame_count_);
EXPECT_EQ(16, visitor.data_bytes_);
EXPECT_EQ(0, visitor.fin_frame_count_);
EXPECT_EQ(0, visitor.fin_flag_count_);
@@ -1764,32 +1336,8 @@ TEST_P(SpdyFramerTest, FinOnDataFrame) {
EXPECT_EQ(2, visitor.data_frame_count_);
}
-// Test that the FIN flag on a SYN reply frame signifies EOF.
-TEST_P(SpdyFramerTest, FinOnSynReplyFrame) {
- // clang-format off
- const unsigned char kV3Input[] = {
- 0x80, 0x03, 0x00, // SYN Stream #1
- 0x01, 0x00, 0x00, 0x00,
- 0x1a, 0x00, 0x00, 0x00,
- 0x01, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x01, 0x00,
- 0x00, 0x00, 0x02, 'h',
- 'h', 0x00, 0x00, 0x00,
- 0x02, 'v', 'v',
-
- 0x80, 0x03, 0x00, 0x02, // SYN REPLY Stream #1
- 0x01, 0x00, 0x00, 0x14,
- 0x00, 0x00, 0x00, 0x01,
- 0x00, 0x00, 0x00, 0x01,
- 0x00, 0x00, 0x00, 0x02,
- 'a', 'a', 0x00, 0x00,
- 0x00, 0x02, 'b', 'b',
- };
- // clang-format on
-
- // SYN_STREAM and SYN_REPLY don't exist in HTTP2, so instead we send
- // HEADERS frames with PRIORITY(SYN_STREAM only) and END_HEADERS set.
+TEST_P(SpdyFramerTest, FinOnHeadersFrame) {
+ // Send HEADERS frames with END_HEADERS set.
// frame-format off
const unsigned char kH2Input[] = {
0x00, 0x00, 0x05, // Length: 5
@@ -1807,23 +1355,11 @@ TEST_P(SpdyFramerTest, FinOnSynReplyFrame) {
};
// frame-format on
- TestSpdyVisitor visitor(spdy_version_);
- if (IsSpdy3()) {
- visitor.SimulateInFramer(kV3Input, sizeof(kV3Input));
- } else {
- visitor.SimulateInFramer(kH2Input, sizeof(kH2Input));
- }
+ TestSpdyVisitor visitor(SpdyFramer::DISABLE_COMPRESSION);
+ visitor.SimulateInFramer(kH2Input, sizeof(kH2Input));
EXPECT_EQ(0, visitor.error_count_);
- if (IsSpdy3()) {
- EXPECT_EQ(1, visitor.syn_frame_count_);
- EXPECT_EQ(1, visitor.syn_reply_frame_count_);
- EXPECT_EQ(0, visitor.headers_frame_count_);
- } else {
- EXPECT_EQ(0, visitor.syn_frame_count_);
- EXPECT_EQ(0, visitor.syn_reply_frame_count_);
- EXPECT_EQ(2, visitor.headers_frame_count_);
- }
+ EXPECT_EQ(2, visitor.headers_frame_count_);
EXPECT_EQ(0, visitor.data_bytes_);
EXPECT_EQ(0, visitor.fin_frame_count_);
EXPECT_EQ(1, visitor.fin_flag_count_);
@@ -1831,69 +1367,10 @@ TEST_P(SpdyFramerTest, FinOnSynReplyFrame) {
EXPECT_EQ(0, visitor.data_frame_count_);
}
-TEST_P(SpdyFramerTest, HeaderCompression) {
- if (!IsSpdy3()) {
- // Deflate compression doesn't apply to HPACK.
- return;
- }
-
- SpdyFramer send_framer(spdy_version_);
- SpdyFramer recv_framer(spdy_version_);
-
- send_framer.set_enable_compression(true);
- recv_framer.set_enable_compression(true);
-
- const char kHeader1[] = "header1";
- const char kHeader2[] = "header2";
- const char kHeader3[] = "header3";
- const char kValue1[] = "value1";
- const char kValue2[] = "value2";
- const char kValue3[] = "value3";
-
- // SYN_STREAM #1
- SpdyHeaderBlock block;
- block[kHeader1] = kValue1;
- block[kHeader2] = kValue2;
- SpdySynStreamIR syn_ir_1(1, block.Clone());
- SpdySerializedFrame syn_frame_1(send_framer.SerializeFrame(syn_ir_1));
-
- // SYN_STREAM #2
- block[kHeader3] = kValue3;
- SpdySynStreamIR syn_stream(3, std::move(block));
- SpdySerializedFrame syn_frame_2(send_framer.SerializeSynStream(syn_stream));
-
- // Decompress SYN_STREAM #1
- SpdySerializedFrame decompressed(
- SpdyFramerTestUtil::DecompressFrame(&recv_framer, syn_frame_1));
- StringPiece serialized_headers =
- GetSerializedHeaders(decompressed, send_framer);
- SpdyHeaderBlock decompressed_headers;
- EXPECT_TRUE(recv_framer.ParseHeaderBlockInBuffer(serialized_headers.data(),
- serialized_headers.size(),
- &decompressed_headers));
- EXPECT_EQ(2u, decompressed_headers.size());
- EXPECT_EQ(kValue1, decompressed_headers[kHeader1]);
- EXPECT_EQ(kValue2, decompressed_headers[kHeader2]);
-
- // Decompress SYN_STREAM #2
- decompressed = SpdyFramerTestUtil::DecompressFrame(&recv_framer, syn_frame_2);
- serialized_headers = GetSerializedHeaders(decompressed, send_framer);
- decompressed_headers.clear();
- EXPECT_TRUE(recv_framer.ParseHeaderBlockInBuffer(serialized_headers.data(),
- serialized_headers.size(),
- &decompressed_headers));
- EXPECT_EQ(3u, decompressed_headers.size());
- EXPECT_EQ(kValue1, decompressed_headers[kHeader1]);
- EXPECT_EQ(kValue2, decompressed_headers[kHeader2]);
- EXPECT_EQ(kValue3, decompressed_headers[kHeader3]);
-}
-
// Verify we can decompress the stream even if handed over to the
// framer 1 byte at a time.
TEST_P(SpdyFramerTest, UnclosedStreamDataCompressorsOneByteAtATime) {
- SpdyFramer framer(spdy_version_);
-
- framer.set_enable_compression(true);
+ SpdyFramer framer(SpdyFramer::ENABLE_COMPRESSION);
const char kHeader1[] = "header1";
const char kHeader2[] = "header2";
@@ -1912,8 +1389,7 @@ TEST_P(SpdyFramerTest, UnclosedStreamDataCompressorsOneByteAtATime) {
SpdySerializedFrame send_frame(framer.SerializeData(data_ir));
// Run the inputs through the framer.
- TestSpdyVisitor visitor(spdy_version_);
- visitor.use_compression_ = true;
+ TestSpdyVisitor visitor(SpdyFramer::ENABLE_COMPRESSION);
const unsigned char* data;
data = reinterpret_cast<const unsigned char*>(headers_frame.data());
for (size_t idx = 0; idx < headers_frame.size(); ++idx) {
@@ -1927,8 +1403,6 @@ TEST_P(SpdyFramerTest, UnclosedStreamDataCompressorsOneByteAtATime) {
}
EXPECT_EQ(0, visitor.error_count_);
- EXPECT_EQ(0, visitor.syn_frame_count_);
- EXPECT_EQ(0, visitor.syn_reply_frame_count_);
EXPECT_EQ(1, visitor.headers_frame_count_);
EXPECT_EQ(arraysize(bytes), static_cast<unsigned>(visitor.data_bytes_));
EXPECT_EQ(0, visitor.fin_frame_count_);
@@ -1938,19 +1412,11 @@ TEST_P(SpdyFramerTest, UnclosedStreamDataCompressorsOneByteAtATime) {
}
TEST_P(SpdyFramerTest, WindowUpdateFrame) {
- SpdyFramer framer(spdy_version_);
+ SpdyFramer framer(SpdyFramer::ENABLE_COMPRESSION);
SpdySerializedFrame frame(
framer.SerializeWindowUpdate(SpdyWindowUpdateIR(1, 0x12345678)));
const char kDescription[] = "WINDOW_UPDATE frame, stream 1, delta 0x12345678";
- // clang-format off
- const unsigned char kV3FrameData[] = {
- 0x80, 0x03, 0x00, 0x09,
- 0x00, 0x00, 0x00, 0x08,
- 0x00, 0x00, 0x00, 0x01,
- 0x12, 0x34, 0x56, 0x78
- };
- // clang-format on
const unsigned char kH2FrameData[] = {
0x00, 0x00, 0x04, // Length: 4
0x08, // Type: WINDOW_UPDATE
@@ -1959,26 +1425,14 @@ TEST_P(SpdyFramerTest, WindowUpdateFrame) {
0x12, 0x34, 0x56, 0x78, // Increment: 305419896
};
- if (IsSpdy3()) {
- CompareFrame(kDescription, frame, kV3FrameData, arraysize(kV3FrameData));
- } else {
- CompareFrame(kDescription, frame, kH2FrameData, arraysize(kH2FrameData));
- }
+ CompareFrame(kDescription, frame, kH2FrameData, arraysize(kH2FrameData));
}
TEST_P(SpdyFramerTest, CreateDataFrame) {
- SpdyFramer framer(spdy_version_);
+ SpdyFramer framer(SpdyFramer::ENABLE_COMPRESSION);
{
const char kDescription[] = "'hello' data frame, no FIN";
- // clang-format off
- const unsigned char kV3FrameData[] = {
- 0x00, 0x00, 0x00, 0x01,
- 0x00, 0x00, 0x00, 0x05,
- 'h', 'e', 'l', 'l',
- 'o'
- };
- // clang-format on
// frame-format off
const unsigned char kH2FrameData[] = {
0x00, 0x00, 0x05, // Length: 5
@@ -1993,11 +1447,7 @@ TEST_P(SpdyFramerTest, CreateDataFrame) {
SpdyDataIR data_ir(1, bytes);
SpdySerializedFrame frame(framer.SerializeData(data_ir));
- if (IsSpdy3()) {
- CompareFrame(kDescription, frame, kV3FrameData, arraysize(kV3FrameData));
- } else {
- CompareFrame(kDescription, frame, kH2FrameData, arraysize(kH2FrameData));
- }
+ CompareFrame(kDescription, frame, kH2FrameData, arraysize(kH2FrameData));
SpdyDataIR data_header_ir(1);
data_header_ir.SetDataShallow(bytes);
@@ -2005,28 +1455,19 @@ TEST_P(SpdyFramerTest, CreateDataFrame) {
framer.SerializeDataFrameHeaderWithPaddingLengthField(data_header_ir);
CompareCharArraysWithHexError(
kDescription, reinterpret_cast<const unsigned char*>(frame.data()),
- framer.GetDataFrameMinimumSize(),
- IsSpdy3() ? kV3FrameData : kH2FrameData,
+ framer.GetDataFrameMinimumSize(), kH2FrameData,
framer.GetDataFrameMinimumSize());
}
{
const char kDescription[] = "'hello' data frame with more padding, no FIN";
- // clang-format off
- const unsigned char kV3FrameData[] = {
- 0x00, 0x00, 0x00, 0x01,
- 0x00, 0x00, 0x00, 0x05,
- 'h', 'e', 'l', 'l',
- 'o'
- };
- // frame-format off
const unsigned char kH2FrameData[] = {
0x00, 0x00, 0xfd, // Length: 253
0x00, // Type: DATA
0x08, // Flags: PADDED
0x00, 0x00, 0x00, 0x01, // Stream: 1
0xf7, // PadLen: 247 trailing bytes
- 'h', 'e', 'l', 'l', // Payload
+ 'h', 'e', 'l', 'l', // Payload
'o', //
// Padding of 247 0x00(s).
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
@@ -2060,30 +1501,17 @@ TEST_P(SpdyFramerTest, CreateDataFrame) {
// bytes.
data_ir.set_padding_len(248);
SpdySerializedFrame frame(framer.SerializeData(data_ir));
- if (IsSpdy3()) {
- CompareFrame(kDescription, frame, kV3FrameData, arraysize(kV3FrameData));
- } else {
- CompareFrame(kDescription, frame, kH2FrameData, arraysize(kH2FrameData));
- }
+ CompareFrame(kDescription, frame, kH2FrameData, arraysize(kH2FrameData));
frame = framer.SerializeDataFrameHeaderWithPaddingLengthField(data_ir);
CompareCharArraysWithHexError(
kDescription, reinterpret_cast<const unsigned char*>(frame.data()),
- framer.GetDataFrameMinimumSize(),
- IsSpdy3() ? kV3FrameData : kH2FrameData,
+ framer.GetDataFrameMinimumSize(), kH2FrameData,
framer.GetDataFrameMinimumSize());
}
{
const char kDescription[] = "'hello' data frame with few padding, no FIN";
- // clang-format off
- const unsigned char kV3FrameData[] = {
- 0x00, 0x00, 0x00, 0x01,
- 0x00, 0x00, 0x00, 0x05,
- 'h', 'e', 'l', 'l',
- 'o'
- };
- // clang-format on
// frame-format off
const unsigned char kH2FrameData[] = {
0x00, 0x00, 0x0d, // Length: 13
@@ -2103,25 +1531,12 @@ TEST_P(SpdyFramerTest, CreateDataFrame) {
// 7 zeros and the pad length field make the overall padding to be 8 bytes.
data_ir.set_padding_len(8);
SpdySerializedFrame frame(framer.SerializeData(data_ir));
- if (IsSpdy3()) {
- CompareFrame(kDescription, frame, kV3FrameData, arraysize(kV3FrameData));
- } else {
- CompareFrame(kDescription, frame, kH2FrameData, arraysize(kH2FrameData));
- }
+ CompareFrame(kDescription, frame, kH2FrameData, arraysize(kH2FrameData));
}
{
const char kDescription[] =
"'hello' data frame with 1 byte padding, no FIN";
- // clang-format off
- const unsigned char kV3FrameData[] = {
- 0x00, 0x00, 0x00, 0x01,
- 0x00, 0x00, 0x00, 0x05,
- 'h', 'e', 'l', 'l',
- 'o'
- };
- // clang-format on
-
// frame-format off
const unsigned char kH2FrameData[] = {
0x00, 0x00, 0x06, // Length: 6
@@ -2140,29 +1555,17 @@ TEST_P(SpdyFramerTest, CreateDataFrame) {
// payload is needed.
data_ir.set_padding_len(1);
SpdySerializedFrame frame(framer.SerializeData(data_ir));
- if (IsSpdy3()) {
- CompareFrame(kDescription, frame, kV3FrameData, arraysize(kV3FrameData));
- } else {
- CompareFrame(kDescription, frame, kH2FrameData, arraysize(kH2FrameData));
- }
+ CompareFrame(kDescription, frame, kH2FrameData, arraysize(kH2FrameData));
frame = framer.SerializeDataFrameHeaderWithPaddingLengthField(data_ir);
CompareCharArraysWithHexError(
kDescription, reinterpret_cast<const unsigned char*>(frame.data()),
- framer.GetDataFrameMinimumSize(),
- IsSpdy3() ? kV3FrameData : kH2FrameData,
+ framer.GetDataFrameMinimumSize(), kH2FrameData,
framer.GetDataFrameMinimumSize());
}
{
const char kDescription[] = "Data frame with negative data byte, no FIN";
- // clang-format off
- const unsigned char kV3FrameData[] = {
- 0x00, 0x00, 0x00, 0x01,
- 0x00, 0x00, 0x00, 0x01,
- 0xff
- };
- // clang-format on
const unsigned char kH2FrameData[] = {
0x00, 0x00, 0x01, // Length: 1
0x00, // Type: DATA
@@ -2172,23 +1575,11 @@ TEST_P(SpdyFramerTest, CreateDataFrame) {
};
SpdyDataIR data_ir(1, "\xff");
SpdySerializedFrame frame(framer.SerializeData(data_ir));
- if (IsSpdy3()) {
- CompareFrame(kDescription, frame, kV3FrameData, arraysize(kV3FrameData));
- } else {
- CompareFrame(kDescription, frame, kH2FrameData, arraysize(kH2FrameData));
- }
+ CompareFrame(kDescription, frame, kH2FrameData, arraysize(kH2FrameData));
}
{
const char kDescription[] = "'hello' data frame, with FIN";
- // clang-format off
- const unsigned char kV3FrameData[] = {
- 0x00, 0x00, 0x00, 0x01,
- 0x01, 0x00, 0x00, 0x05,
- 'h', 'e', 'l', 'l',
- 'o'
- };
- // clang-format on
const unsigned char kH2FrameData[] = {
0x00, 0x00, 0x05, // Length: 5
0x00, // Type: DATA
@@ -2200,21 +1591,11 @@ TEST_P(SpdyFramerTest, CreateDataFrame) {
SpdyDataIR data_ir(1, "hello");
data_ir.set_fin(true);
SpdySerializedFrame frame(framer.SerializeData(data_ir));
- if (IsSpdy3()) {
- CompareFrame(kDescription, frame, kV3FrameData, arraysize(kV3FrameData));
- } else {
- CompareFrame(kDescription, frame, kH2FrameData, arraysize(kH2FrameData));
- }
+ CompareFrame(kDescription, frame, kH2FrameData, arraysize(kH2FrameData));
}
{
const char kDescription[] = "Empty data frame";
- // clang-format off
- const unsigned char kV3FrameData[] = {
- 0x00, 0x00, 0x00, 0x01,
- 0x00, 0x00, 0x00, 0x00,
- };
- // clang-format on
const unsigned char kH2FrameData[] = {
0x00, 0x00, 0x00, // Length: 0
0x00, // Type: DATA
@@ -2223,30 +1604,17 @@ TEST_P(SpdyFramerTest, CreateDataFrame) {
};
SpdyDataIR data_ir(1, "");
SpdySerializedFrame frame(framer.SerializeData(data_ir));
- if (IsSpdy3()) {
- CompareFrame(kDescription, frame, kV3FrameData, arraysize(kV3FrameData));
- } else {
- CompareFrame(kDescription, frame, kH2FrameData, arraysize(kH2FrameData));
- }
+ CompareFrame(kDescription, frame, kH2FrameData, arraysize(kH2FrameData));
frame = framer.SerializeDataFrameHeaderWithPaddingLengthField(data_ir);
CompareCharArraysWithHexError(
kDescription, reinterpret_cast<const unsigned char*>(frame.data()),
- framer.GetDataFrameMinimumSize(),
- IsSpdy3() ? kV3FrameData : kH2FrameData,
+ framer.GetDataFrameMinimumSize(), kH2FrameData,
framer.GetDataFrameMinimumSize());
}
{
const char kDescription[] = "Data frame with max stream ID";
- // clang-format off
- const unsigned char kV3FrameData[] = {
- 0x7f, 0xff, 0xff, 0xff,
- 0x01, 0x00, 0x00, 0x05,
- 'h', 'e', 'l', 'l',
- 'o'
- };
- // clang-format on
const unsigned char kH2FrameData[] = {
0x00, 0x00, 0x05, // Length: 5
0x00, // Type: DATA
@@ -2258,403 +1626,15 @@ TEST_P(SpdyFramerTest, CreateDataFrame) {
SpdyDataIR data_ir(0x7fffffff, "hello");
data_ir.set_fin(true);
SpdySerializedFrame frame(framer.SerializeData(data_ir));
- if (IsSpdy3()) {
- CompareFrame(kDescription, frame, kV3FrameData, arraysize(kV3FrameData));
- } else {
- CompareFrame(kDescription, frame, kH2FrameData, arraysize(kH2FrameData));
- }
- }
-
- if (!IsHttp2()) {
- // This test does not apply to HTTP/2 because the max frame size is smaller
- // than 4MB.
- const char kDescription[] = "Large data frame";
- const int kDataSize = 4 * 1024 * 1024; // 4 MB
- const string kData(kDataSize, 'A');
- // clang-format off
- const unsigned char kFrameHeader[] = {
- 0x00, 0x00, 0x00, 0x01,
- 0x01, 0x40, 0x00, 0x00,
- };
- // clang-format on
-
- const int kFrameSize = arraysize(kFrameHeader) + kDataSize;
- std::unique_ptr<unsigned char[]> expected_frame_data(
- new unsigned char[kFrameSize]);
- memcpy(expected_frame_data.get(), kFrameHeader, arraysize(kFrameHeader));
- memset(expected_frame_data.get() + arraysize(kFrameHeader), 'A', kDataSize);
-
- SpdyDataIR data_ir(1, kData);
- data_ir.set_fin(true);
- SpdySerializedFrame frame(framer.SerializeData(data_ir));
- CompareFrame(kDescription, frame, expected_frame_data.get(), kFrameSize);
- }
-}
-
-TEST_P(SpdyFramerTest, CreateSynStreamUncompressed) {
- if (!IsSpdy3()) {
- return;
- }
-
- SpdyFramer framer(spdy_version_);
- framer.set_enable_compression(false);
-
- {
- const char kDescription[] = "SYN_STREAM frame, lowest pri, no FIN";
-
- // clang-format off
- const unsigned char kV3FrameData[] = {
- 0x80, 0x03, 0x00, 0x01,
- 0x00, 0x00, 0x00, 0x2a,
- 0x00, 0x00, 0x00, 0x01,
- 0x00, 0x00, 0x00, 0x00,
- 0xE0, 0x00, 0x00, 0x00,
- 0x00, 0x02, 0x00, 0x00,
- 0x00, 0x03, 'b', 'a',
- 'r', 0x00, 0x00, 0x00,
- 0x03, 'f', 'o', 'o',
- 0x00, 0x00, 0x00, 0x03,
- 'f', 'o', 'o', 0x00,
- 0x00, 0x00, 0x03, 'b',
- 'a', 'r'
- };
- // clang-format on
- SpdySynStreamIR syn_stream(1);
- syn_stream.set_priority(framer.GetLowestPriority());
- syn_stream.SetHeader("bar", "foo");
- syn_stream.SetHeader("foo", "bar");
- SpdySerializedFrame frame(framer.SerializeSynStream(syn_stream));
- if (IsSpdy3()) {
- CompareFrame(kDescription, frame, kV3FrameData, arraysize(kV3FrameData));
- } else {
- LOG(FATAL) << "Unsupported version in test.";
- }
- }
-
- {
- const char kDescription[] =
- "SYN_STREAM frame with a 0-length header name, highest pri, FIN, "
- "max stream ID";
-
- // clang-format off
- const unsigned char kV3FrameData[] = {
- 0x80, 0x03, 0x00, 0x01,
- 0x01, 0x00, 0x00, 0x27,
- 0x7f, 0xff, 0xff, 0xff,
- 0x7f, 0xff, 0xff, 0xff,
- 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x02, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x03, 'f', 'o',
- 'o', 0x00, 0x00, 0x00,
- 0x03, 'f', 'o', 'o',
- 0x00, 0x00, 0x00, 0x03,
- 'b', 'a', 'r'
- };
- // clang-format on
- SpdySynStreamIR syn_stream(0x7fffffff);
- syn_stream.set_associated_to_stream_id(0x7fffffff);
- syn_stream.set_priority(framer.GetHighestPriority());
- syn_stream.set_fin(true);
- syn_stream.SetHeader("", "foo");
- syn_stream.SetHeader("foo", "bar");
- SpdySerializedFrame frame(framer.SerializeSynStream(syn_stream));
- if (IsSpdy3()) {
- CompareFrame(kDescription, frame, kV3FrameData, arraysize(kV3FrameData));
- } else {
- LOG(FATAL) << "Unsupported version in test.";
- }
- }
-
- {
- const char kDescription[] =
- "SYN_STREAM frame with a 0-length header val, high pri, FIN, "
- "max stream ID";
-
- // clang-format off
- const unsigned char kV3FrameData[] = {
- 0x80, 0x03, 0x00, 0x01,
- 0x01, 0x00, 0x00, 0x27,
- 0x7f, 0xff, 0xff, 0xff,
- 0x7f, 0xff, 0xff, 0xff,
- 0x20, 0x00, 0x00, 0x00,
- 0x00, 0x02, 0x00, 0x00,
- 0x00, 0x03, 'b', 'a',
- 'r', 0x00, 0x00, 0x00,
- 0x03, 'f', 'o', 'o',
- 0x00, 0x00, 0x00, 0x03,
- 'f', 'o', 'o', 0x00,
- 0x00, 0x00, 0x00
- };
- // clang-format on
- SpdySynStreamIR syn_stream(0x7fffffff);
- syn_stream.set_associated_to_stream_id(0x7fffffff);
- syn_stream.set_priority(1);
- syn_stream.set_fin(true);
- syn_stream.SetHeader("bar", "foo");
- syn_stream.SetHeader("foo", "");
- SpdySerializedFrame frame(framer.SerializeSynStream(syn_stream));
- if (IsSpdy3()) {
- CompareFrame(kDescription, frame, kV3FrameData, arraysize(kV3FrameData));
- } else {
- LOG(FATAL) << "Unsupported version in test.";
- }
- }
-}
-
-// TODO(phajdan.jr): Clean up after we no longer need
-// to workaround http://crbug.com/139744.
-#if !defined(USE_SYSTEM_ZLIB)
-TEST_P(SpdyFramerTest, CreateSynStreamCompressed) {
- if (!IsSpdy3()) {
- return;
- }
-
- SpdyFramer framer(spdy_version_);
- framer.set_enable_compression(true);
-
- {
- const char kDescription[] = "SYN_STREAM frame, low pri, no FIN";
-
- // clang-format off
- const unsigned char kV3FrameData[] = {
- 0x80, 0x03, 0x00, 0x01,
- 0x00, 0x00, 0x00, 0x36,
- 0x00, 0x00, 0x00, 0x01,
- 0x00, 0x00, 0x00, 0x00,
- 0x80, 0x00, 0x38, 0xEA,
- 0xE3, 0xC6, 0xA7, 0xC2,
- 0x02, 0xE5, 0x0E, 0x50,
- 0xC2, 0x4B, 0x4A, 0x04,
- 0xE5, 0x0B, 0x66, 0x80,
- 0x00, 0x4A, 0xCB, 0xCF,
- 0x07, 0x08, 0x20, 0x10,
- 0x95, 0x96, 0x9F, 0x0F,
- 0xA2, 0x00, 0x02, 0x28,
- 0x29, 0xB1, 0x08, 0x20,
- 0x00, 0x00, 0x00, 0x00,
- 0xFF, 0xFF,
- };
- const unsigned char kV3SIMDFrameData[] = {
- 0x80, 0x03, 0x00, 0x01,
- 0x00, 0x00, 0x00, 0x31,
- 0x00, 0x00, 0x00, 0x01,
- 0x00, 0x00, 0x00, 0x00,
- 0x80, 0x00, 0x38, 0xea,
- 0xe3, 0xc6, 0xa7, 0xc2,
- 0x02, 0xe5, 0x0e, 0x50,
- 0xc2, 0x4b, 0x4a, 0x04,
- 0xe5, 0x0b, 0x66, 0x80,
- 0x00, 0x4a, 0xcb, 0xcf,
- 0x07, 0x08, 0x20, 0x24,
- 0x0a, 0x20, 0x80, 0x92,
- 0x12, 0x8b, 0x00, 0x02,
- 0x00, 0x00, 0x00, 0xff,
- 0xff,
- };
- // clang-format on
-
- SpdySynStreamIR syn_stream(1);
- syn_stream.set_priority(4);
- syn_stream.SetHeader("bar", "foo");
- syn_stream.SetHeader("foo", "bar");
- SpdySerializedFrame frame(framer.SerializeSynStream(syn_stream));
- const unsigned char* frame_data =
- reinterpret_cast<const unsigned char*>(frame.data());
- if (IsSpdy3()) {
- if (memcmp(frame_data, kV3SIMDFrameData,
- std::min(arraysize(kV3SIMDFrameData), frame.size())) != 0) {
- CompareCharArraysWithHexError(kDescription, frame_data, frame.size(),
- kV3FrameData, arraysize(kV3FrameData));
- }
- } else {
- LOG(FATAL) << "Unsupported version in test.";
- }
- }
-}
-#endif // !defined(USE_SYSTEM_ZLIB)
-
-TEST_P(SpdyFramerTest, CreateSynReplyUncompressed) {
- if (!IsSpdy3()) {
- return;
- }
-
- SpdyFramer framer(spdy_version_);
- framer.set_enable_compression(false);
-
- {
- const char kDescription[] = "SYN_REPLY frame, no FIN";
-
- // clang-format off
- const unsigned char kV3FrameData[] = {
- 0x80, 0x03, 0x00, 0x02,
- 0x00, 0x00, 0x00, 0x24,
- 0x00, 0x00, 0x00, 0x01,
- 0x00, 0x00, 0x00, 0x02,
- 0x00, 0x00, 0x00, 0x03,
- 'b', 'a', 'r', 0x00,
- 0x00, 0x00, 0x03, 'f',
- 'o', 'o', 0x00, 0x00,
- 0x00, 0x03, 'f', 'o',
- 'o', 0x00, 0x00, 0x00,
- 0x03, 'b', 'a', 'r'
- };
- // clang-format on
- SpdySynReplyIR syn_reply(1);
- syn_reply.SetHeader("bar", "foo");
- syn_reply.SetHeader("foo", "bar");
- SpdySerializedFrame frame(framer.SerializeSynReply(syn_reply));
- if (IsSpdy3()) {
- CompareFrame(kDescription, frame, kV3FrameData, arraysize(kV3FrameData));
- } else {
- LOG(FATAL) << "Unsupported version in test.";
- }
- }
-
- {
- const char kDescription[] =
- "SYN_REPLY frame with a 0-length header name, FIN, max stream ID";
-
- // clang-format off
- const unsigned char kV3FrameData[] = {
- 0x80, 0x03, 0x00, 0x02,
- 0x01, 0x00, 0x00, 0x21,
- 0x7f, 0xff, 0xff, 0xff,
- 0x00, 0x00, 0x00, 0x02,
- 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x03,
- 'f', 'o', 'o', 0x00,
- 0x00, 0x00, 0x03, 'f',
- 'o', 'o', 0x00, 0x00,
- 0x00, 0x03, 'b', 'a',
- 'r'
- };
- // clang-format on
- SpdySynReplyIR syn_reply(0x7fffffff);
- syn_reply.set_fin(true);
- syn_reply.SetHeader("", "foo");
- syn_reply.SetHeader("foo", "bar");
- SpdySerializedFrame frame(framer.SerializeSynReply(syn_reply));
- if (IsSpdy3()) {
- CompareFrame(kDescription, frame, kV3FrameData, arraysize(kV3FrameData));
- } else {
- LOG(FATAL) << "Unsupported version in test.";
- }
- }
-
- {
- const char kDescription[] =
- "SYN_REPLY frame with a 0-length header val, FIN, max stream ID";
-
- // clang-format off
- const unsigned char kV3FrameData[] = {
- 0x80, 0x03, 0x00, 0x02,
- 0x01, 0x00, 0x00, 0x21,
- 0x7f, 0xff, 0xff, 0xff,
- 0x00, 0x00, 0x00, 0x02,
- 0x00, 0x00, 0x00, 0x03,
- 'b', 'a', 'r', 0x00,
- 0x00, 0x00, 0x03, 'f',
- 'o', 'o', 0x00, 0x00,
- 0x00, 0x03, 'f', 'o',
- 'o', 0x00, 0x00, 0x00,
- 0x00
- };
- // clang-format on
- SpdySynReplyIR syn_reply(0x7fffffff);
- syn_reply.set_fin(true);
- syn_reply.SetHeader("bar", "foo");
- syn_reply.SetHeader("foo", "");
- SpdySerializedFrame frame(framer.SerializeSynReply(syn_reply));
- if (IsSpdy3()) {
- CompareFrame(kDescription, frame, kV3FrameData, arraysize(kV3FrameData));
- } else {
- LOG(FATAL) << "Unsupported version in test.";
- }
- }
-}
-
-// TODO(phajdan.jr): Clean up after we no longer need
-// to workaround http://crbug.com/139744.
-#if !defined(USE_SYSTEM_ZLIB)
-TEST_P(SpdyFramerTest, CreateSynReplyCompressed) {
- if (!IsSpdy3()) {
- return;
- }
-
- SpdyFramer framer(spdy_version_);
- framer.set_enable_compression(true);
-
- {
- const char kDescription[] = "SYN_REPLY frame, no FIN";
-
- // clang-format off
- const unsigned char kV3FrameData[] = {
- 0x80, 0x03, 0x00, 0x02,
- 0x00, 0x00, 0x00, 0x30,
- 0x00, 0x00, 0x00, 0x01,
- 0x38, 0xea, 0xe3, 0xc6,
- 0xa7, 0xc2, 0x02, 0xe5,
- 0x0e, 0x50, 0xc2, 0x4b,
- 0x4a, 0x04, 0xe5, 0x0b,
- 0x66, 0x80, 0x00, 0x4a,
- 0xcb, 0xcf, 0x07, 0x08,
- 0x20, 0x10, 0x95, 0x96,
- 0x9f, 0x0f, 0xa2, 0x00,
- 0x02, 0x28, 0x29, 0xb1,
- 0x08, 0x20, 0x00, 0x00,
- 0x00, 0x00, 0xff, 0xff,
- };
-
- const unsigned char kV3SIMDFrameData[] = {
- 0x80, 0x03, 0x00, 0x02,
- 0x00, 0x00, 0x00, 0x2b,
- 0x00, 0x00, 0x00, 0x01,
- 0x38, 0xea, 0xe3, 0xc6,
- 0xa7, 0xc2, 0x02, 0xe5,
- 0x0e, 0x50, 0xc2, 0x4b,
- 0x4a, 0x04, 0xe5, 0x0b,
- 0x66, 0x80, 0x00, 0x4a,
- 0xcb, 0xcf, 0x07, 0x08,
- 0x20, 0x24, 0x0a, 0x20,
- 0x80, 0x92, 0x12, 0x8b,
- 0x00, 0x02, 0x00, 0x00,
- 0x00, 0xff, 0xff,
- };
- // clang-format on
-
- SpdySynReplyIR syn_reply(1);
- syn_reply.SetHeader("bar", "foo");
- syn_reply.SetHeader("foo", "bar");
- SpdySerializedFrame frame(framer.SerializeSynReply(syn_reply));
- const unsigned char* frame_data =
- reinterpret_cast<const unsigned char*>(frame.data());
- if (IsSpdy3()) {
- if (memcmp(frame_data, kV3SIMDFrameData,
- std::min(arraysize(kV3SIMDFrameData), frame.size())) != 0) {
- CompareCharArraysWithHexError(kDescription, frame_data, frame.size(),
- kV3FrameData, arraysize(kV3FrameData));
- }
- } else {
- LOG(FATAL) << "Unsupported version in test.";
- }
+ CompareFrame(kDescription, frame, kH2FrameData, arraysize(kH2FrameData));
}
}
-#endif // !defined(USE_SYSTEM_ZLIB)
TEST_P(SpdyFramerTest, CreateRstStream) {
- SpdyFramer framer(spdy_version_);
+ SpdyFramer framer(SpdyFramer::ENABLE_COMPRESSION);
{
const char kDescription[] = "RST_STREAM frame";
- // clang-format off
- const unsigned char kV3FrameData[] = {
- 0x80, 0x03, 0x00, 0x03,
- 0x00, 0x00, 0x00, 0x08,
- 0x00, 0x00, 0x00, 0x01,
- 0x00, 0x00, 0x00, 0x01,
- };
- // clang-format on
const unsigned char kH2FrameData[] = {
0x00, 0x00, 0x04, // Length: 4
0x03, // Type: RST_STREAM
@@ -2664,23 +1644,11 @@ TEST_P(SpdyFramerTest, CreateRstStream) {
};
SpdyRstStreamIR rst_stream(1, RST_STREAM_PROTOCOL_ERROR);
SpdySerializedFrame frame(framer.SerializeRstStream(rst_stream));
- if (IsSpdy3()) {
- CompareFrame(kDescription, frame, kV3FrameData, arraysize(kV3FrameData));
- } else {
- CompareFrame(kDescription, frame, kH2FrameData, arraysize(kH2FrameData));
- }
+ CompareFrame(kDescription, frame, kH2FrameData, arraysize(kH2FrameData));
}
{
const char kDescription[] = "RST_STREAM frame with max stream ID";
- // clang-format off
- const unsigned char kV3FrameData[] = {
- 0x80, 0x03, 0x00, 0x03,
- 0x00, 0x00, 0x00, 0x08,
- 0x7f, 0xff, 0xff, 0xff,
- 0x00, 0x00, 0x00, 0x01,
- };
- // clang-format on
const unsigned char kH2FrameData[] = {
0x00, 0x00, 0x04, // Length: 4
0x03, // Type: RST_STREAM
@@ -2690,23 +1658,11 @@ TEST_P(SpdyFramerTest, CreateRstStream) {
};
SpdyRstStreamIR rst_stream(0x7FFFFFFF, RST_STREAM_PROTOCOL_ERROR);
SpdySerializedFrame frame(framer.SerializeRstStream(rst_stream));
- if (IsSpdy3()) {
- CompareFrame(kDescription, frame, kV3FrameData, arraysize(kV3FrameData));
- } else {
- CompareFrame(kDescription, frame, kH2FrameData, arraysize(kH2FrameData));
- }
+ CompareFrame(kDescription, frame, kH2FrameData, arraysize(kH2FrameData));
}
{
const char kDescription[] = "RST_STREAM frame with max status code";
- // clang-format off
- const unsigned char kV3FrameData[] = {
- 0x80, 0x03, 0x00, 0x03,
- 0x00, 0x00, 0x00, 0x08,
- 0x7f, 0xff, 0xff, 0xff,
- 0x00, 0x00, 0x00, 0x06,
- };
- // clang-format on
const unsigned char kH2FrameData[] = {
0x00, 0x00, 0x04, // Length: 4
0x03, // Type: RST_STREAM
@@ -2716,29 +1672,16 @@ TEST_P(SpdyFramerTest, CreateRstStream) {
};
SpdyRstStreamIR rst_stream(0x7FFFFFFF, RST_STREAM_INTERNAL_ERROR);
SpdySerializedFrame frame(framer.SerializeRstStream(rst_stream));
- if (IsSpdy3()) {
- CompareFrame(kDescription, frame, kV3FrameData, arraysize(kV3FrameData));
- } else {
- CompareFrame(kDescription, frame, kH2FrameData, arraysize(kH2FrameData));
- }
+ CompareFrame(kDescription, frame, kH2FrameData, arraysize(kH2FrameData));
}
}
TEST_P(SpdyFramerTest, CreateSettings) {
- SpdyFramer framer(spdy_version_);
+ SpdyFramer framer(SpdyFramer::ENABLE_COMPRESSION);
{
const char kDescription[] = "Network byte order SETTINGS frame";
- // clang-format off
- const unsigned char kV3FrameData[] = {
- 0x80, 0x03, 0x00, 0x04,
- 0x00, 0x00, 0x00, 0x0c,
- 0x00, 0x00, 0x00, 0x01,
- 0x01, 0x00, 0x00, 0x07,
- 0x0a, 0x0b, 0x0c, 0x0d,
- };
- // clang-format on
const unsigned char kH2FrameData[] = {
0x00, 0x00, 0x06, // Length: 6
0x04, // Type: SETTINGS
@@ -2751,37 +1694,15 @@ TEST_P(SpdyFramerTest, CreateSettings) {
uint32_t kValue = 0x0a0b0c0d;
SpdySettingsIR settings_ir;
- SpdySettingsFlags kFlags = static_cast<SpdySettingsFlags>(0x01);
SpdySettingsIds kId = SETTINGS_INITIAL_WINDOW_SIZE;
- settings_ir.AddSetting(kId, kFlags & SETTINGS_FLAG_PLEASE_PERSIST,
- kFlags & SETTINGS_FLAG_PERSISTED, kValue);
+ settings_ir.AddSetting(kId, kValue);
SpdySerializedFrame frame(framer.SerializeSettings(settings_ir));
- if (IsSpdy3()) {
- CompareFrame(kDescription, frame, kV3FrameData, arraysize(kV3FrameData));
- } else {
- CompareFrame(kDescription, frame, kH2FrameData, arraysize(kH2FrameData));
- }
+ CompareFrame(kDescription, frame, kH2FrameData, arraysize(kH2FrameData));
}
{
const char kDescription[] = "Basic SETTINGS frame";
-
- // clang-format off
- const unsigned char kV3FrameData[] = {
- 0x80, 0x03, 0x00, 0x04,
- 0x00, 0x00, 0x00, 0x24,
- 0x00, 0x00, 0x00, 0x04,
- 0x00, 0x00, 0x00, 0x01, // 1st Setting
- 0x00, 0x00, 0x00, 0x05,
- 0x00, 0x00, 0x00, 0x02, // 2nd Setting
- 0x00, 0x00, 0x00, 0x06,
- 0x00, 0x00, 0x00, 0x03, // 3rd Setting
- 0x00, 0x00, 0x00, 0x07,
- 0x00, 0x00, 0x00, 0x04, // 4th Setting
- 0x00, 0x00, 0x00, 0x08,
- };
- // clang-format on
// These end up seemingly out of order because of the way that our internal
// ordering for settings_ir works. HTTP2 has no requirement on ordering on
// the wire.
@@ -2790,52 +1711,29 @@ TEST_P(SpdyFramerTest, CreateSettings) {
0x04, // Type: SETTINGS
0x00, // Flags: none
0x00, 0x00, 0x00, 0x00, // Stream: 0
- 0x00, 0x03, // Param: MAX_CONCURRENT_STREAMS
- 0x00, 0x00, 0x00, 0x07, // Value: 7
- 0x00, 0x04, // Param: INITIAL_WINDOW_SIZE
- 0x00, 0x00, 0x00, 0x08, // Value: 8
0x00, 0x01, // Param: HEADER_TABLE_SIZE
0x00, 0x00, 0x00, 0x05, // Value: 5
0x00, 0x02, // Param: ENABLE_PUSH
0x00, 0x00, 0x00, 0x06, // Value: 6
+ 0x00, 0x03, // Param: MAX_CONCURRENT_STREAMS
+ 0x00, 0x00, 0x00, 0x07, // Value: 7
+ 0x00, 0x04, // Param: INITIAL_WINDOW_SIZE
+ 0x00, 0x00, 0x00, 0x08, // Value: 8
};
SpdySettingsIR settings_ir;
- settings_ir.AddSetting(SpdyConstants::ParseSettingId(spdy_version_, 1),
- false, // persist
- false, // persisted
- 5);
- settings_ir.AddSetting(SpdyConstants::ParseSettingId(spdy_version_, 2),
- false, // persist
- false, // persisted
- 6);
- settings_ir.AddSetting(SpdyConstants::ParseSettingId(spdy_version_, 3),
- false, // persist
- false, // persisted
- 7);
- settings_ir.AddSetting(SpdyConstants::ParseSettingId(spdy_version_, 4),
- false, // persist
- false, // persisted
- 8);
+ settings_ir.AddSetting(SETTINGS_HEADER_TABLE_SIZE, 5);
+ settings_ir.AddSetting(SETTINGS_ENABLE_PUSH, 6);
+ settings_ir.AddSetting(SETTINGS_MAX_CONCURRENT_STREAMS, 7);
+ settings_ir.AddSetting(SETTINGS_INITIAL_WINDOW_SIZE, 8);
SpdySerializedFrame frame(framer.SerializeSettings(settings_ir));
- if (IsSpdy3()) {
- CompareFrame(kDescription, frame, kV3FrameData, arraysize(kV3FrameData));
- } else {
- CompareFrame(kDescription, frame, kH2FrameData, arraysize(kH2FrameData));
- }
+ CompareFrame(kDescription, frame, kH2FrameData, arraysize(kH2FrameData));
}
{
const char kDescription[] = "Empty SETTINGS frame";
- // clang-format off
- const unsigned char kV3FrameData[] = {
- 0x80, 0x03, 0x00, 0x04,
- 0x00, 0x00, 0x00, 0x04,
- 0x00, 0x00, 0x00, 0x00,
- };
- // clang-format on
const unsigned char kH2FrameData[] = {
0x00, 0x00, 0x00, // Length: 0
0x04, // Type: SETTINGS
@@ -2844,26 +1742,15 @@ TEST_P(SpdyFramerTest, CreateSettings) {
};
SpdySettingsIR settings_ir;
SpdySerializedFrame frame(framer.SerializeSettings(settings_ir));
- if (IsSpdy3()) {
- CompareFrame(kDescription, frame, kV3FrameData, arraysize(kV3FrameData));
- } else {
- CompareFrame(kDescription, frame, kH2FrameData, arraysize(kH2FrameData));
- }
+ CompareFrame(kDescription, frame, kH2FrameData, arraysize(kH2FrameData));
}
}
TEST_P(SpdyFramerTest, CreatePingFrame) {
- SpdyFramer framer(spdy_version_);
+ SpdyFramer framer(SpdyFramer::ENABLE_COMPRESSION);
{
const char kDescription[] = "PING frame";
- // clang-format off
- const unsigned char kV3FrameData[] = {
- 0x80, 0x03, 0x00, 0x06,
- 0x00, 0x00, 0x00, 0x04,
- 0x12, 0x34, 0x56, 0x78,
- };
- // clang-format on
const unsigned char kH2FrameData[] = {
0x00, 0x00, 0x08, // Length: 8
0x06, // Type: PING
@@ -2881,39 +1768,26 @@ TEST_P(SpdyFramerTest, CreatePingFrame) {
0x9a, 0xbc, 0xde, 0xff, // Data
};
SpdySerializedFrame frame;
- if (IsSpdy3()) {
- frame = framer.SerializePing(SpdyPingIR(0x12345678ull));
- CompareFrame(kDescription, frame, kV3FrameData, arraysize(kV3FrameData));
- } else {
- const SpdyPingId kPingId = 0x123456789abcdeffULL;
- SpdyPingIR ping_ir(kPingId);
- // Tests SpdyPingIR when the ping is not an ack.
- ASSERT_FALSE(ping_ir.is_ack());
- frame = framer.SerializePing(ping_ir);
- CompareFrame(kDescription, frame, kH2FrameData, arraysize(kH2FrameData));
-
- // Tests SpdyPingIR when the ping is an ack.
- ping_ir.set_is_ack(true);
- frame = framer.SerializePing(ping_ir);
- CompareFrame(kDescription, frame, kH2FrameDataWithAck,
- arraysize(kH2FrameDataWithAck));
- }
+ const SpdyPingId kPingId = 0x123456789abcdeffULL;
+ SpdyPingIR ping_ir(kPingId);
+ // Tests SpdyPingIR when the ping is not an ack.
+ ASSERT_FALSE(ping_ir.is_ack());
+ frame = framer.SerializePing(ping_ir);
+ CompareFrame(kDescription, frame, kH2FrameData, arraysize(kH2FrameData));
+
+ // Tests SpdyPingIR when the ping is an ack.
+ ping_ir.set_is_ack(true);
+ frame = framer.SerializePing(ping_ir);
+ CompareFrame(kDescription, frame, kH2FrameDataWithAck,
+ arraysize(kH2FrameDataWithAck));
}
}
TEST_P(SpdyFramerTest, CreateGoAway) {
- SpdyFramer framer(spdy_version_);
+ SpdyFramer framer(SpdyFramer::ENABLE_COMPRESSION);
{
const char kDescription[] = "GOAWAY frame";
- // clang-format off
- const unsigned char kV3FrameData[] = {
- 0x80, 0x03, 0x00, 0x07,
- 0x00, 0x00, 0x00, 0x08,
- 0x00, 0x00, 0x00, 0x00, // Stream Id
- 0x00, 0x00, 0x00, 0x00, // Status
- };
- // clang-format on
const unsigned char kH2FrameData[] = {
0x00, 0x00, 0x0a, // Length: 10
0x07, // Type: GOAWAY
@@ -2923,25 +1797,13 @@ TEST_P(SpdyFramerTest, CreateGoAway) {
0x00, 0x00, 0x00, 0x00, // Error: NO_ERROR
0x47, 0x41, // Description
};
- SpdyGoAwayIR goaway_ir(0, GOAWAY_OK, "GA");
+ SpdyGoAwayIR goaway_ir(0, GOAWAY_NO_ERROR, "GA");
SpdySerializedFrame frame(framer.SerializeGoAway(goaway_ir));
- if (IsSpdy3()) {
- CompareFrame(kDescription, frame, kV3FrameData, arraysize(kV3FrameData));
- } else {
- CompareFrame(kDescription, frame, kH2FrameData, arraysize(kH2FrameData));
- }
+ CompareFrame(kDescription, frame, kH2FrameData, arraysize(kH2FrameData));
}
{
const char kDescription[] = "GOAWAY frame with max stream ID, status";
- // clang-format off
- const unsigned char kV3FrameData[] = {
- 0x80, 0x03, 0x00, 0x07,
- 0x00, 0x00, 0x00, 0x08,
- 0x7f, 0xff, 0xff, 0xff, // Stream Id
- 0x00, 0x00, 0x00, 0x01, // Status: PROTOCOL_ERROR.
- };
- // clang-format on
const unsigned char kH2FrameData[] = {
0x00, 0x00, 0x0a, // Length: 10
0x07, // Type: GOAWAY
@@ -2953,36 +1815,15 @@ TEST_P(SpdyFramerTest, CreateGoAway) {
};
SpdyGoAwayIR goaway_ir(0x7FFFFFFF, GOAWAY_INTERNAL_ERROR, "GA");
SpdySerializedFrame frame(framer.SerializeGoAway(goaway_ir));
- if (IsSpdy3()) {
- CompareFrame(kDescription, frame, kV3FrameData, arraysize(kV3FrameData));
- } else {
- CompareFrame(kDescription, frame, kH2FrameData, arraysize(kH2FrameData));
- }
+ CompareFrame(kDescription, frame, kH2FrameData, arraysize(kH2FrameData));
}
}
TEST_P(SpdyFramerTest, CreateHeadersUncompressed) {
- SpdyFramer framer(spdy_version_);
- framer.set_enable_compression(false);
+ SpdyFramer framer(SpdyFramer::DISABLE_COMPRESSION);
{
const char kDescription[] = "HEADERS frame, no FIN";
-
- // clang-format off
- const unsigned char kV3FrameData[] = {
- 0x80, 0x03, 0x00, 0x08,
- 0x00, 0x00, 0x00, 0x24,
- 0x00, 0x00, 0x00, 0x01,
- 0x00, 0x00, 0x00, 0x02,
- 0x00, 0x00, 0x00, 0x03,
- 'b', 'a', 'r', 0x00,
- 0x00, 0x00, 0x03, 'f',
- 'o', 'o', 0x00, 0x00,
- 0x00, 0x03, 'f', 'o',
- 'o', 0x00, 0x00, 0x00,
- 0x03, 'b', 'a', 'r'
- };
- // clang-format on
// frame-format off
const unsigned char kH2FrameData[] = {
0x00, 0x00, 0x12, // Length: 18
@@ -3009,32 +1850,12 @@ TEST_P(SpdyFramerTest, CreateHeadersUncompressed) {
headers.SetHeader("foo", "bar");
SpdySerializedFrame frame(
SpdyFramerPeer::SerializeHeaders(&framer, headers));
- if (IsSpdy3()) {
- CompareFrame(kDescription, frame, kV3FrameData, arraysize(kV3FrameData));
- } else {
- CompareFrame(kDescription, frame, kH2FrameData, arraysize(kH2FrameData));
- }
+ CompareFrame(kDescription, frame, kH2FrameData, arraysize(kH2FrameData));
}
{
const char kDescription[] =
"HEADERS frame with a 0-length header name, FIN, max stream ID";
-
- // clang-format off
- const unsigned char kV3FrameData[] = {
- 0x80, 0x03, 0x00, 0x08,
- 0x01, 0x00, 0x00, 0x21,
- 0x7f, 0xff, 0xff, 0xff,
- 0x00, 0x00, 0x00, 0x02,
- 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x03,
- 'f', 'o', 'o', 0x00,
- 0x00, 0x00, 0x03, 'f',
- 'o', 'o', 0x00, 0x00,
- 0x00, 0x03, 'b', 'a',
- 'r'
- };
- // clang-format on
// frame-format off
const unsigned char kH2FrameData[] = {
0x00, 0x00, 0x0f, // Length: 15
@@ -3060,32 +1881,12 @@ TEST_P(SpdyFramerTest, CreateHeadersUncompressed) {
headers.SetHeader("foo", "bar");
SpdySerializedFrame frame(
SpdyFramerPeer::SerializeHeaders(&framer, headers));
- if (IsSpdy3()) {
- CompareFrame(kDescription, frame, kV3FrameData, arraysize(kV3FrameData));
- } else {
- CompareFrame(kDescription, frame, kH2FrameData, arraysize(kH2FrameData));
- }
+ CompareFrame(kDescription, frame, kH2FrameData, arraysize(kH2FrameData));
}
{
const char kDescription[] =
"HEADERS frame with a 0-length header val, FIN, max stream ID";
-
- // clang-format off
- const unsigned char kV3FrameData[] = {
- 0x80, 0x03, 0x00, 0x08,
- 0x01, 0x00, 0x00, 0x21,
- 0x7f, 0xff, 0xff, 0xff,
- 0x00, 0x00, 0x00, 0x02,
- 0x00, 0x00, 0x00, 0x03,
- 'b', 'a', 'r', 0x00,
- 0x00, 0x00, 0x03, 'f',
- 'o', 'o', 0x00, 0x00,
- 0x00, 0x03, 'f', 'o',
- 'o', 0x00, 0x00, 0x00,
- 0x00
- };
- // clang-format on
// frame-format off
const unsigned char kH2FrameData[] = {
0x00, 0x00, 0x0f, // Length: 15
@@ -3111,11 +1912,7 @@ TEST_P(SpdyFramerTest, CreateHeadersUncompressed) {
headers_ir.SetHeader("foo", "");
SpdySerializedFrame frame(
SpdyFramerPeer::SerializeHeaders(&framer, headers_ir));
- if (IsSpdy3()) {
- CompareFrame(kDescription, frame, kV3FrameData, arraysize(kV3FrameData));
- } else {
- CompareFrame(kDescription, frame, kH2FrameData, arraysize(kH2FrameData));
- }
+ CompareFrame(kDescription, frame, kH2FrameData, arraysize(kH2FrameData));
}
{
@@ -3151,11 +1948,7 @@ TEST_P(SpdyFramerTest, CreateHeadersUncompressed) {
headers_ir.SetHeader("foo", "");
SpdySerializedFrame frame(
SpdyFramerPeer::SerializeHeaders(&framer, headers_ir));
- if (IsSpdy3()) {
- // HEADERS with priority not supported.
- } else {
- CompareFrame(kDescription, frame, kH2FrameData, arraysize(kH2FrameData));
- }
+ CompareFrame(kDescription, frame, kH2FrameData, arraysize(kH2FrameData));
}
{
@@ -3194,11 +1987,7 @@ TEST_P(SpdyFramerTest, CreateHeadersUncompressed) {
headers_ir.SetHeader("foo", "");
SpdySerializedFrame frame(
SpdyFramerPeer::SerializeHeaders(&framer, headers_ir));
- if (IsSpdy3()) {
- // HEADERS with priority not supported.
- } else {
- CompareFrame(kDescription, frame, kV4FrameData, arraysize(kV4FrameData));
- }
+ CompareFrame(kDescription, frame, kV4FrameData, arraysize(kV4FrameData));
}
{
@@ -3237,11 +2026,7 @@ TEST_P(SpdyFramerTest, CreateHeadersUncompressed) {
headers_ir.SetHeader("foo", "");
SpdySerializedFrame frame(
SpdyFramerPeer::SerializeHeaders(&framer, headers_ir));
- if (IsSpdy3()) {
- // HEADERS with priority not supported.
- } else {
- CompareFrame(kDescription, frame, kV4FrameData, arraysize(kV4FrameData));
- }
+ CompareFrame(kDescription, frame, kV4FrameData, arraysize(kV4FrameData));
}
{
@@ -3278,11 +2063,7 @@ TEST_P(SpdyFramerTest, CreateHeadersUncompressed) {
headers_ir.set_padding_len(6);
SpdySerializedFrame frame(
SpdyFramerPeer::SerializeHeaders(&framer, headers_ir));
- if (IsSpdy3()) {
- // Padding is not supported.
- } else {
- CompareFrame(kDescription, frame, kH2FrameData, arraysize(kH2FrameData));
- }
+ CompareFrame(kDescription, frame, kH2FrameData, arraysize(kH2FrameData));
}
}
@@ -3290,79 +2071,24 @@ TEST_P(SpdyFramerTest, CreateHeadersUncompressed) {
// to workaround http://crbug.com/139744.
#if !defined(USE_SYSTEM_ZLIB)
TEST_P(SpdyFramerTest, CreateHeadersCompressed) {
- SpdyFramer framer(spdy_version_);
- framer.set_enable_compression(true);
+ SpdyFramer framer(SpdyFramer::ENABLE_COMPRESSION);
{
- const char kDescription[] = "HEADERS frame, no FIN";
-
- // clang-format off
- const unsigned char kV3FrameData[] = {
- 0x80, 0x03, 0x00, 0x08,
- 0x00, 0x00, 0x00, 0x30,
- 0x00, 0x00, 0x00, 0x01,
- 0x38, 0xea, 0xe3, 0xc6,
- 0xa7, 0xc2, 0x02, 0xe5,
- 0x0e, 0x50, 0xc2, 0x4b,
- 0x4a, 0x04, 0xe5, 0x0b,
- 0x66, 0x80, 0x00, 0x4a,
- 0xcb, 0xcf, 0x07, 0x08,
- 0x20, 0x10, 0x95, 0x96,
- 0x9f, 0x0f, 0xa2, 0x00,
- 0x02, 0x28, 0x29, 0xb1,
- 0x08, 0x20, 0x00, 0x00,
- 0x00, 0x00, 0xff, 0xff,
- };
- const unsigned char kV3SIMDFrameData[] = {
- 0x80, 0x03, 0x00, 0x08,
- 0x00, 0x00, 0x00, 0x2b,
- 0x00, 0x00, 0x00, 0x01,
- 0x38, 0xea, 0xe3, 0xc6,
- 0xa7, 0xc2, 0x02, 0xe5,
- 0x0e, 0x50, 0xc2, 0x4b,
- 0x4a, 0x04, 0xe5, 0x0b,
- 0x66, 0x80, 0x00, 0x4a,
- 0xcb, 0xcf, 0x07, 0x08,
- 0x20, 0x24, 0x0a, 0x20,
- 0x80, 0x92, 0x12, 0x8b,
- 0x00, 0x02, 0x00, 0x00,
- 0x00, 0xff, 0xff,
- };
- // clang-format on
-
SpdyHeadersIR headers_ir(1);
headers_ir.SetHeader("bar", "foo");
headers_ir.SetHeader("foo", "bar");
SpdySerializedFrame frame(
SpdyFramerPeer::SerializeHeaders(&framer, headers_ir));
- const unsigned char* frame_data =
- reinterpret_cast<const unsigned char*>(frame.data());
- if (IsSpdy3()) {
- if (memcmp(frame_data, kV3SIMDFrameData,
- std::min(arraysize(kV3SIMDFrameData), frame.size())) != 0) {
- CompareCharArraysWithHexError(kDescription, frame_data, frame.size(),
- kV3FrameData, arraysize(kV3FrameData));
- }
- } else {
- // Deflate compression doesn't apply to HPACK.
- }
+ // Deflate compression doesn't apply to HPACK.
}
}
#endif // !defined(USE_SYSTEM_ZLIB)
TEST_P(SpdyFramerTest, CreateWindowUpdate) {
- SpdyFramer framer(spdy_version_);
+ SpdyFramer framer(SpdyFramer::ENABLE_COMPRESSION);
{
const char kDescription[] = "WINDOW_UPDATE frame";
- // clang-format off
- const unsigned char kV3FrameData[] = {
- 0x80, 0x03, 0x00, 0x09,
- 0x00, 0x00, 0x00, 0x08,
- 0x00, 0x00, 0x00, 0x01,
- 0x00, 0x00, 0x00, 0x01,
- };
- // clang-format on
const unsigned char kH2FrameData[] = {
0x00, 0x00, 0x04, // Length: 4
0x08, // Type: WINDOW_UPDATE
@@ -3372,23 +2098,11 @@ TEST_P(SpdyFramerTest, CreateWindowUpdate) {
};
SpdySerializedFrame frame(
framer.SerializeWindowUpdate(SpdyWindowUpdateIR(1, 1)));
- if (IsSpdy3()) {
- CompareFrame(kDescription, frame, kV3FrameData, arraysize(kV3FrameData));
- } else {
- CompareFrame(kDescription, frame, kH2FrameData, arraysize(kH2FrameData));
- }
+ CompareFrame(kDescription, frame, kH2FrameData, arraysize(kH2FrameData));
}
{
const char kDescription[] = "WINDOW_UPDATE frame with max stream ID";
- // clang-format off
- const unsigned char kV3FrameData[] = {
- 0x80, 0x03, 0x00, 0x09,
- 0x00, 0x00, 0x00, 0x08,
- 0x7f, 0xff, 0xff, 0xff,
- 0x00, 0x00, 0x00, 0x01,
- };
- // clang-format on
const unsigned char kH2FrameData[] = {
0x00, 0x00, 0x04, // Length: 4
0x08, // Type: WINDOW_UPDATE
@@ -3398,23 +2112,11 @@ TEST_P(SpdyFramerTest, CreateWindowUpdate) {
};
SpdySerializedFrame frame(
framer.SerializeWindowUpdate(SpdyWindowUpdateIR(0x7FFFFFFF, 1)));
- if (IsSpdy3()) {
- CompareFrame(kDescription, frame, kV3FrameData, arraysize(kV3FrameData));
- } else {
- CompareFrame(kDescription, frame, kH2FrameData, arraysize(kH2FrameData));
- }
+ CompareFrame(kDescription, frame, kH2FrameData, arraysize(kH2FrameData));
}
{
const char kDescription[] = "WINDOW_UPDATE frame with max window delta";
- // clang-format off
- const unsigned char kV3FrameData[] = {
- 0x80, 0x03, 0x00, 0x09,
- 0x00, 0x00, 0x00, 0x08,
- 0x00, 0x00, 0x00, 0x01,
- 0x7f, 0xff, 0xff, 0xff,
- };
- // clang-format on
const unsigned char kH2FrameData[] = {
0x00, 0x00, 0x04, // Length: 4
0x08, // Type: WINDOW_UPDATE
@@ -3424,24 +2126,15 @@ TEST_P(SpdyFramerTest, CreateWindowUpdate) {
};
SpdySerializedFrame frame(
framer.SerializeWindowUpdate(SpdyWindowUpdateIR(1, 0x7FFFFFFF)));
- if (IsSpdy3()) {
- CompareFrame(kDescription, frame, kV3FrameData, arraysize(kV3FrameData));
- } else {
- CompareFrame(kDescription, frame, kH2FrameData, arraysize(kH2FrameData));
- }
+ CompareFrame(kDescription, frame, kH2FrameData, arraysize(kH2FrameData));
}
}
TEST_P(SpdyFramerTest, SerializeBlocked) {
- if (!IsHttp2()) {
- return;
- }
-
- SpdyFramer framer(spdy_version_);
+ SpdyFramer framer(SpdyFramer::ENABLE_COMPRESSION);
const char kDescription[] = "BLOCKED frame";
- const unsigned char kType = static_cast<unsigned char>(
- SpdyConstants::SerializeFrameType(spdy_version_, BLOCKED));
+ const char kType = static_cast<unsigned char>(SerializeFrameType(BLOCKED));
const unsigned char kFrameData[] = {
0x00, 0x00, 0x00, // Length: 0
kType, // Type: BLOCKED
@@ -3454,11 +2147,7 @@ TEST_P(SpdyFramerTest, SerializeBlocked) {
}
TEST_P(SpdyFramerTest, CreateBlocked) {
- if (!IsHttp2()) {
- return;
- }
-
- SpdyFramer framer(spdy_version_);
+ SpdyFramer framer(SpdyFramer::ENABLE_COMPRESSION);
const char kDescription[] = "BLOCKED frame";
const SpdyStreamId kStreamId = 3;
@@ -3472,14 +2161,9 @@ TEST_P(SpdyFramerTest, CreateBlocked) {
}
TEST_P(SpdyFramerTest, CreatePushPromiseUncompressed) {
- if (!IsHttp2()) {
- return;
- }
-
{
// Test framing PUSH_PROMISE without padding.
- SpdyFramer framer(spdy_version_);
- framer.set_enable_compression(false);
+ SpdyFramer framer(SpdyFramer::DISABLE_COMPRESSION);
const char kDescription[] = "PUSH_PROMISE frame without padding";
// frame-format off
@@ -3513,8 +2197,7 @@ TEST_P(SpdyFramerTest, CreatePushPromiseUncompressed) {
{
// Test framing PUSH_PROMISE with one byte of padding.
- SpdyFramer framer(spdy_version_);
- framer.set_enable_compression(false);
+ SpdyFramer framer(SpdyFramer::DISABLE_COMPRESSION);
const char kDescription[] = "PUSH_PROMISE frame with one byte of padding";
// frame-format off
@@ -3550,8 +2233,7 @@ TEST_P(SpdyFramerTest, CreatePushPromiseUncompressed) {
{
// Test framing PUSH_PROMISE with 177 bytes of padding.
- SpdyFramer framer(spdy_version_);
- framer.set_enable_compression(false);
+ SpdyFramer framer(SpdyFramer::DISABLE_COMPRESSION);
const char kDescription[] = "PUSH_PROMISE frame with 177 bytes of padding";
// frame-format off
@@ -3608,11 +2290,7 @@ TEST_P(SpdyFramerTest, CreatePushPromiseUncompressed) {
// Regression test for https://crbug.com/464748.
TEST_P(SpdyFramerTest, GetNumberRequiredContinuationFrames) {
- if (!IsHttp2()) {
- return;
- }
-
- SpdyFramer framer(spdy_version_);
+ SpdyFramer framer(SpdyFramer::ENABLE_COMPRESSION);
EXPECT_EQ(1u, SpdyFramerPeer::GetNumberRequiredContinuationFrames(
&framer, 16383 + 16374));
EXPECT_EQ(2u, SpdyFramerPeer::GetNumberRequiredContinuationFrames(
@@ -3624,12 +2302,7 @@ TEST_P(SpdyFramerTest, GetNumberRequiredContinuationFrames) {
}
TEST_P(SpdyFramerTest, CreateContinuationUncompressed) {
- if (!IsHttp2()) {
- return;
- }
-
- SpdyFramer framer(spdy_version_);
- framer.set_enable_compression(false);
+ SpdyFramer framer(SpdyFramer::DISABLE_COMPRESSION);
const char kDescription[] = "CONTINUATION frame";
// frame-format off
@@ -3658,7 +2331,8 @@ TEST_P(SpdyFramerTest, CreateContinuationUncompressed) {
header_block["foo"] = "bar";
auto buffer = base::MakeUnique<string>();
HpackEncoder encoder(ObtainHpackHuffmanTable());
- encoder.EncodeHeaderSetWithoutCompression(header_block, buffer.get());
+ encoder.DisableCompression();
+ encoder.EncodeHeaderSet(header_block, buffer.get());
SpdyContinuationIR continuation(42);
continuation.take_encoding(std::move(buffer));
@@ -3671,12 +2345,8 @@ TEST_P(SpdyFramerTest, CreateContinuationUncompressed) {
// Test that if we send an unexpected CONTINUATION
// we signal an error (but don't crash).
TEST_P(SpdyFramerTest, SendUnexpectedContinuation) {
- if (!IsHttp2()) {
- return;
- }
-
testing::StrictMock<test::MockSpdyFramerVisitor> visitor;
- SpdyFramer framer(spdy_version_);
+ SpdyFramer framer(SpdyFramer::ENABLE_COMPRESSION);
framer.set_visitor(&visitor);
// frame-format off
@@ -3711,16 +2381,11 @@ TEST_P(SpdyFramerTest, SendUnexpectedContinuation) {
}
TEST_P(SpdyFramerTest, CreatePushPromiseThenContinuationUncompressed) {
- if (!IsHttp2()) {
- return;
- }
-
{
// Test framing in a case such that a PUSH_PROMISE frame, with one byte of
// padding, cannot hold all the data payload, which is overflowed to the
// consecutive CONTINUATION frame.
- SpdyFramer framer(spdy_version_);
- framer.set_enable_compression(false);
+ SpdyFramer framer(SpdyFramer::DISABLE_COMPRESSION);
const char kDescription[] =
"PUSH_PROMISE and CONTINUATION frames with one byte of padding";
@@ -3816,15 +2481,10 @@ TEST_P(SpdyFramerTest, CreatePushPromiseThenContinuationUncompressed) {
}
TEST_P(SpdyFramerTest, CreateAltSvc) {
- if (!IsHttp2()) {
- return;
- }
-
- SpdyFramer framer(spdy_version_);
+ SpdyFramer framer(SpdyFramer::ENABLE_COMPRESSION);
const char kDescription[] = "ALTSVC frame";
- const char kType = static_cast<unsigned char>(
- SpdyConstants::SerializeFrameType(spdy_version_, ALTSVC));
+ const char kType = static_cast<unsigned char>(SerializeFrameType(ALTSVC));
const unsigned char kFrameData[] = {
0x00, 0x00, 0x49, kType, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x06, 'o',
'r', 'i', 'g', 'i', 'n', 'p', 'i', 'd', '1', '=', '"', 'h',
@@ -3845,11 +2505,7 @@ TEST_P(SpdyFramerTest, CreateAltSvc) {
}
TEST_P(SpdyFramerTest, CreatePriority) {
- if (!IsHttp2()) {
- return;
- }
-
- SpdyFramer framer(spdy_version_);
+ SpdyFramer framer(SpdyFramer::ENABLE_COMPRESSION);
const char kDescription[] = "PRIORITY frame";
const unsigned char kFrameData[] = {
@@ -3871,55 +2527,14 @@ TEST_P(SpdyFramerTest, CreatePriority) {
CompareFrame(kDescription, frame, kFrameData, arraysize(kFrameData));
}
-TEST_P(SpdyFramerTest, ReadCompressedSynStreamHeaderBlock) {
- if (!IsSpdy3()) {
- return;
- }
-
- SpdyFramer framer(spdy_version_);
- SpdySynStreamIR syn_stream(1);
- syn_stream.set_priority(1);
- syn_stream.SetHeader("aa", "vv");
- syn_stream.SetHeader("bb", "ww");
- SpdySerializedFrame control_frame(framer.SerializeSynStream(syn_stream));
- TestSpdyVisitor visitor(spdy_version_);
- visitor.use_compression_ = true;
- visitor.SimulateInFramer(
- reinterpret_cast<unsigned char*>(control_frame.data()),
- control_frame.size());
- EXPECT_EQ(1, visitor.syn_frame_count_);
- EXPECT_EQ(syn_stream.header_block(), visitor.headers_);
-}
-
-TEST_P(SpdyFramerTest, ReadCompressedSynReplyHeaderBlock) {
- if (!IsSpdy3()) {
- return;
- }
-
- SpdyFramer framer(spdy_version_);
- SpdySynReplyIR syn_reply(1);
- syn_reply.SetHeader("alpha", "beta");
- syn_reply.SetHeader("gamma", "delta");
- SpdySerializedFrame control_frame(framer.SerializeSynReply(syn_reply));
- TestSpdyVisitor visitor(spdy_version_);
- visitor.use_compression_ = true;
- visitor.SimulateInFramer(
- reinterpret_cast<unsigned char*>(control_frame.data()),
- control_frame.size());
- EXPECT_EQ(1, visitor.syn_reply_frame_count_);
- EXPECT_EQ(0, visitor.headers_frame_count_);
- EXPECT_EQ(syn_reply.header_block(), visitor.headers_);
-}
-
TEST_P(SpdyFramerTest, ReadCompressedHeadersHeaderBlock) {
- SpdyFramer framer(spdy_version_);
+ SpdyFramer framer(SpdyFramer::ENABLE_COMPRESSION);
SpdyHeadersIR headers_ir(1);
headers_ir.SetHeader("alpha", "beta");
headers_ir.SetHeader("gamma", "delta");
SpdySerializedFrame control_frame(
SpdyFramerPeer::SerializeHeaders(&framer, headers_ir));
- TestSpdyVisitor visitor(spdy_version_);
- visitor.use_compression_ = true;
+ TestSpdyVisitor visitor(SpdyFramer::ENABLE_COMPRESSION);
visitor.SimulateInFramer(
reinterpret_cast<unsigned char*>(control_frame.data()),
control_frame.size());
@@ -3931,15 +2546,14 @@ TEST_P(SpdyFramerTest, ReadCompressedHeadersHeaderBlock) {
}
TEST_P(SpdyFramerTest, ReadCompressedHeadersHeaderBlockWithHalfClose) {
- SpdyFramer framer(spdy_version_);
+ SpdyFramer framer(SpdyFramer::ENABLE_COMPRESSION);
SpdyHeadersIR headers_ir(1);
headers_ir.set_fin(true);
headers_ir.SetHeader("alpha", "beta");
headers_ir.SetHeader("gamma", "delta");
SpdySerializedFrame control_frame(
SpdyFramerPeer::SerializeHeaders(&framer, headers_ir));
- TestSpdyVisitor visitor(spdy_version_);
- visitor.use_compression_ = true;
+ TestSpdyVisitor visitor(SpdyFramer::ENABLE_COMPRESSION);
visitor.SimulateInFramer(
reinterpret_cast<unsigned char*>(control_frame.data()),
control_frame.size());
@@ -3950,93 +2564,8 @@ TEST_P(SpdyFramerTest, ReadCompressedHeadersHeaderBlockWithHalfClose) {
EXPECT_EQ(headers_ir.header_block(), visitor.headers_);
}
-TEST_P(SpdyFramerTest, ControlFrameAtMaxSizeLimit) {
- if (!IsSpdy3()) {
- // TODO(jgraettinger): This test setup doesn't work with HPACK.
- return;
- }
-
- // First find the size of the header value in order to just reach the control
- // frame max size.
- SpdyFramer framer(spdy_version_);
- framer.set_enable_compression(false);
- SpdySynStreamIR syn_stream(1);
- syn_stream.set_priority(1);
- syn_stream.SetHeader("aa", "");
- SpdySerializedFrame control_frame(framer.SerializeSynStream(syn_stream));
- const size_t kBigValueSize =
- TestSpdyVisitor::sent_control_frame_max_size() - control_frame.size();
-
- // Create a frame at exactly that size.
- string big_value(kBigValueSize, 'x');
- syn_stream.SetHeader("aa", big_value);
- control_frame = framer.SerializeSynStream(syn_stream);
- EXPECT_EQ(TestSpdyVisitor::sent_control_frame_max_size(),
- control_frame.size());
-
- TestSpdyVisitor visitor(spdy_version_);
- visitor.SimulateInFramer(
- reinterpret_cast<unsigned char*>(control_frame.data()),
- control_frame.size());
- EXPECT_TRUE(visitor.header_buffer_valid_);
- EXPECT_EQ(0, visitor.error_count_);
- EXPECT_EQ(1, visitor.syn_frame_count_);
- EXPECT_EQ(0, visitor.zero_length_control_frame_header_data_count_);
- EXPECT_EQ(0, visitor.end_of_stream_count_);
-}
-
-TEST_P(SpdyFramerTest, ControlFrameTooLarge) {
- if (!IsSpdy3()) {
- // TODO(jgraettinger): This test setup doesn't work with HPACK.
- return;
- }
-
- // First find the size of the header value in order to just reach the control
- // frame max size.
- SpdyFramer framer(spdy_version_);
- framer.set_enable_compression(false);
- SpdySynStreamIR syn_stream(1);
- syn_stream.SetHeader("aa", "");
- syn_stream.set_priority(1);
- SpdySerializedFrame control_frame(framer.SerializeSynStream(syn_stream));
- const size_t kBigValueSize =
- TestSpdyVisitor::received_control_frame_max_size() +
- SpdyConstants::GetFrameHeaderSize(spdy_version_) - control_frame.size() +
- 1;
-
- // Create a frame at exatly that size.
- string big_value(kBigValueSize, 'x');
- syn_stream.SetHeader("aa", big_value);
- if (IsSpdy3()) {
- control_frame = framer.SerializeSynStream(syn_stream);
- } else {
- EXPECT_SPDY_BUG({ control_frame = framer.SerializeSynStream(syn_stream); },
- "Serializing frame over-capacity.");
- }
- EXPECT_EQ(TestSpdyVisitor::received_control_frame_max_size() +
- SpdyConstants::GetFrameHeaderSize(spdy_version_) + 1,
- control_frame.size());
-
- TestSpdyVisitor visitor(spdy_version_);
- visitor.SimulateInFramer(
- reinterpret_cast<unsigned char*>(control_frame.data()),
- control_frame.size());
- EXPECT_FALSE(visitor.header_buffer_valid_);
- EXPECT_EQ(1, visitor.error_count_);
- EXPECT_EQ(SpdyFramer::SPDY_CONTROL_PAYLOAD_TOO_LARGE,
- visitor.framer_.error_code())
- << SpdyFramer::ErrorCodeToString(visitor.framer_.error_code());
- EXPECT_EQ(0, visitor.syn_frame_count_);
- EXPECT_EQ(0u, visitor.header_buffer_length_);
-}
-
TEST_P(SpdyFramerTest, TooLargeHeadersFrameUsesContinuation) {
- if (!IsHttp2()) {
- return;
- }
-
- SpdyFramer framer(spdy_version_);
- framer.set_enable_compression(false);
+ SpdyFramer framer(SpdyFramer::DISABLE_COMPRESSION);
SpdyHeadersIR headers(1);
headers.set_padding_len(256);
@@ -4050,7 +2579,7 @@ TEST_P(SpdyFramerTest, TooLargeHeadersFrameUsesContinuation) {
EXPECT_GT(control_frame.size(),
TestSpdyVisitor::sent_control_frame_max_size());
- TestSpdyVisitor visitor(spdy_version_);
+ TestSpdyVisitor visitor(SpdyFramer::DISABLE_COMPRESSION);
visitor.SimulateInFramer(
reinterpret_cast<unsigned char*>(control_frame.data()),
control_frame.size());
@@ -4062,12 +2591,7 @@ TEST_P(SpdyFramerTest, TooLargeHeadersFrameUsesContinuation) {
}
TEST_P(SpdyFramerTest, MultipleContinuationFramesWithIterator) {
- if (!IsHttp2()) {
- return;
- }
-
- SpdyFramer framer(spdy_version_);
- framer.set_enable_compression(false);
+ SpdyFramer framer(SpdyFramer::DISABLE_COMPRESSION);
auto headers = base::MakeUnique<SpdyHeadersIR>(1);
headers->set_padding_len(256);
@@ -4086,7 +2610,7 @@ TEST_P(SpdyFramerTest, MultipleContinuationFramesWithIterator) {
EXPECT_EQ(headers_frame.size(),
TestSpdyVisitor::sent_control_frame_max_size());
- TestSpdyVisitor visitor(spdy_version_);
+ TestSpdyVisitor visitor(SpdyFramer::DISABLE_COMPRESSION);
visitor.SimulateInFramer(
reinterpret_cast<unsigned char*>(headers_frame.data()),
headers_frame.size());
@@ -4128,12 +2652,7 @@ TEST_P(SpdyFramerTest, MultipleContinuationFramesWithIterator) {
}
TEST_P(SpdyFramerTest, TooLargePushPromiseFrameUsesContinuation) {
- if (!IsHttp2()) {
- return;
- }
-
- SpdyFramer framer(spdy_version_);
- framer.set_enable_compression(false);
+ SpdyFramer framer(SpdyFramer::DISABLE_COMPRESSION);
SpdyPushPromiseIR push_promise(1, 2);
push_promise.set_padding_len(256);
@@ -4146,7 +2665,7 @@ TEST_P(SpdyFramerTest, TooLargePushPromiseFrameUsesContinuation) {
EXPECT_GT(control_frame.size(),
TestSpdyVisitor::sent_control_frame_max_size());
- TestSpdyVisitor visitor(spdy_version_);
+ TestSpdyVisitor visitor(SpdyFramer::DISABLE_COMPRESSION);
visitor.SimulateInFramer(
reinterpret_cast<unsigned char*>(control_frame.data()),
control_frame.size());
@@ -4166,15 +2685,14 @@ TEST_P(SpdyFramerTest, ControlFrameMuchTooLarge) {
TestSpdyVisitor::header_data_chunk_max_size() * kHeaderBufferChunks;
const size_t kBigValueSize = kHeaderBufferSize * 2;
string big_value(kBigValueSize, 'x');
- SpdyFramer framer(spdy_version_);
+ SpdyFramer framer(SpdyFramer::ENABLE_COMPRESSION);
SpdyHeadersIR headers(1);
headers.set_fin(true);
headers.SetHeader("aa", big_value);
SpdySerializedFrame control_frame(
SpdyFramerPeer::SerializeHeaders(&framer, headers));
- TestSpdyVisitor visitor(spdy_version_);
+ TestSpdyVisitor visitor(SpdyFramer::ENABLE_COMPRESSION);
visitor.set_header_buffer_size(kHeaderBufferSize);
- visitor.use_compression_ = true;
visitor.SimulateInFramer(
reinterpret_cast<unsigned char*>(control_frame.data()),
control_frame.size());
@@ -4184,50 +2702,18 @@ TEST_P(SpdyFramerTest, ControlFrameMuchTooLarge) {
EXPECT_EQ(1, visitor.end_of_stream_count_);
}
-TEST_P(SpdyFramerTest, DecompressCorruptHeaderBlock) {
- if (!IsSpdy3()) {
- // Deflate compression doesn't apply to HPACK.
- return;
- }
-
- SpdyFramer framer(spdy_version_);
- framer.set_enable_compression(false);
- // Construct a SYN_STREAM control frame without compressing the header block,
- // and have the framer try to decompress it. This will cause the framer to
- // deal with a decompression error.
- SpdySynStreamIR syn_stream(1);
- syn_stream.set_priority(1);
- syn_stream.SetHeader("aa", "alpha beta gamma delta");
- SpdySerializedFrame control_frame(framer.SerializeSynStream(syn_stream));
- TestSpdyVisitor visitor(spdy_version_);
- visitor.use_compression_ = true;
- visitor.SimulateInFramer(
- reinterpret_cast<unsigned char*>(control_frame.data()),
- control_frame.size());
- EXPECT_EQ(1, visitor.error_count_);
- EXPECT_EQ(SpdyFramer::SPDY_DECOMPRESS_FAILURE, visitor.framer_.error_code())
- << SpdyFramer::ErrorCodeToString(visitor.framer_.error_code());
- EXPECT_EQ(0u, visitor.header_buffer_length_);
-}
-
TEST_P(SpdyFramerTest, ControlFrameSizesAreValidated) {
- SpdyFramer framer(spdy_version_);
+ SpdyFramer framer(SpdyFramer::ENABLE_COMPRESSION);
// Create a GoAway frame that has a few extra bytes at the end.
// We create enough overhead to overflow the framer's control frame buffer.
ASSERT_LE(SpdyFramerPeer::ControlFrameBufferSize(), 250u);
const size_t length = SpdyFramerPeer::ControlFrameBufferSize() + 1;
- const unsigned char kV3FrameData[] = {
- 0x80, 0x03, 0x00, 0x07,
- 0x00, 0x00, 0x00, static_cast<unsigned char>(length),
- 0x00, 0x00, 0x00, 0x00, // Stream ID
- 0x00, 0x00, 0x00, 0x00, // Status
- };
// HTTP/2 GOAWAY frames are only bound by a minimal length, since they may
// carry opaque data. Verify that minimal length is tested.
- ASSERT_GT(framer.GetGoAwayMinimumSize(), framer.GetFrameHeaderSize());
+ ASSERT_GT(framer.GetGoAwayMinimumSize(), kFrameHeaderSize);
const size_t less_than_min_length =
- framer.GetGoAwayMinimumSize() - framer.GetFrameHeaderSize() - 1;
+ framer.GetGoAwayMinimumSize() - kFrameHeaderSize - 1;
ASSERT_LE(less_than_min_length, std::numeric_limits<unsigned char>::max());
const unsigned char kH2Len = static_cast<unsigned char>(less_than_min_length);
const unsigned char kH2FrameData[] = {
@@ -4238,17 +2724,11 @@ TEST_P(SpdyFramerTest, ControlFrameSizesAreValidated) {
0x00, 0x00, 0x00, 0x00, // Last: 0
0x00, 0x00, 0x00, // Truncated Status Field
};
- const size_t pad_length =
- length + framer.GetFrameHeaderSize() -
- (IsSpdy3() ? sizeof(kV3FrameData) : sizeof(kH2FrameData));
+ const size_t pad_length = length + kFrameHeaderSize - sizeof(kH2FrameData);
string pad(pad_length, 'A');
- TestSpdyVisitor visitor(spdy_version_);
+ TestSpdyVisitor visitor(SpdyFramer::DISABLE_COMPRESSION);
- if (IsSpdy3()) {
- visitor.SimulateInFramer(kV3FrameData, sizeof(kV3FrameData));
- } else {
- visitor.SimulateInFramer(kH2FrameData, sizeof(kH2FrameData));
- }
+ visitor.SimulateInFramer(kH2FrameData, sizeof(kH2FrameData));
visitor.SimulateInFramer(reinterpret_cast<const unsigned char*>(pad.c_str()),
pad.length());
@@ -4260,38 +2740,33 @@ TEST_P(SpdyFramerTest, ControlFrameSizesAreValidated) {
}
TEST_P(SpdyFramerTest, ReadZeroLenSettingsFrame) {
- SpdyFramer framer(spdy_version_);
+ SpdyFramer framer(SpdyFramer::ENABLE_COMPRESSION);
SpdySettingsIR settings_ir;
SpdySerializedFrame control_frame(framer.SerializeSettings(settings_ir));
- SetFrameLength(&control_frame, 0, spdy_version_);
- TestSpdyVisitor visitor(spdy_version_);
- visitor.use_compression_ = false;
+ SetFrameLength(&control_frame, 0);
+ TestSpdyVisitor visitor(SpdyFramer::DISABLE_COMPRESSION);
visitor.SimulateInFramer(
reinterpret_cast<unsigned char*>(control_frame.data()),
framer.GetFrameHeaderSize());
- if (IsSpdy3()) {
- // Should generate an error, since zero-len settings frames are unsupported.
- EXPECT_EQ(1, visitor.error_count_);
- } else {
- // Zero-len settings frames are permitted as of HTTP/2.
- EXPECT_EQ(0, visitor.error_count_);
- }
+ // Zero-len settings frames are permitted as of HTTP/2.
+ EXPECT_EQ(0, visitor.error_count_);
}
// Tests handling of SETTINGS frames with invalid length.
TEST_P(SpdyFramerTest, ReadBogusLenSettingsFrame) {
- SpdyFramer framer(spdy_version_);
+ SpdyFramer framer(SpdyFramer::ENABLE_COMPRESSION);
SpdySettingsIR settings_ir;
- // Add a setting to pad the frame so that we don't get a buffer overflow when
- // calling SimulateInFramer() below.
- settings_ir.AddSetting(SETTINGS_INITIAL_WINDOW_SIZE, false, false,
- 0x00000002);
+ // Add settings to more than fill the frame so that we don't get a buffer
+ // overflow when calling SimulateInFramer() below. These settings must be
+ // distinct parameters because SpdySettingsIR has a map for settings, and will
+ // collapse multiple copies of the same parameter.
+ settings_ir.AddSetting(SETTINGS_INITIAL_WINDOW_SIZE, 0x00000002);
+ settings_ir.AddSetting(SETTINGS_MAX_CONCURRENT_STREAMS, 0x00000002);
SpdySerializedFrame control_frame(framer.SerializeSettings(settings_ir));
- const size_t kNewLength = 14;
- SetFrameLength(&control_frame, kNewLength, spdy_version_);
- TestSpdyVisitor visitor(spdy_version_);
- visitor.use_compression_ = false;
+ const size_t kNewLength = 8;
+ SetFrameLength(&control_frame, kNewLength);
+ TestSpdyVisitor visitor(SpdyFramer::DISABLE_COMPRESSION);
visitor.SimulateInFramer(
reinterpret_cast<unsigned char*>(control_frame.data()),
framer.GetFrameHeaderSize() + kNewLength);
@@ -4305,25 +2780,15 @@ TEST_P(SpdyFramerTest, ReadBogusLenSettingsFrame) {
// Tests handling of SETTINGS frames larger than the frame buffer size.
TEST_P(SpdyFramerTest, ReadLargeSettingsFrame) {
- SpdyFramer framer(spdy_version_);
+ SpdyFramer framer(SpdyFramer::ENABLE_COMPRESSION);
SpdySettingsIR settings_ir;
- settings_ir.AddSetting(SpdyConstants::ParseSettingId(spdy_version_, 1),
- false, // persist
- false, // persisted
- 5);
- settings_ir.AddSetting(SpdyConstants::ParseSettingId(spdy_version_, 2),
- false, // persist
- false, // persisted
- 6);
- settings_ir.AddSetting(SpdyConstants::ParseSettingId(spdy_version_, 3),
- false, // persist
- false, // persisted
- 7);
+ settings_ir.AddSetting(SETTINGS_HEADER_TABLE_SIZE, 5);
+ settings_ir.AddSetting(SETTINGS_ENABLE_PUSH, 6);
+ settings_ir.AddSetting(SETTINGS_MAX_CONCURRENT_STREAMS, 7);
SpdySerializedFrame control_frame(framer.SerializeSettings(settings_ir));
EXPECT_LT(SpdyFramerPeer::ControlFrameBufferSize(), control_frame.size());
- TestSpdyVisitor visitor(spdy_version_);
- visitor.use_compression_ = false;
+ TestSpdyVisitor visitor(SpdyFramer::DISABLE_COMPRESSION);
// Read all at once.
visitor.SimulateInFramer(
@@ -4331,9 +2796,7 @@ TEST_P(SpdyFramerTest, ReadLargeSettingsFrame) {
control_frame.size());
EXPECT_EQ(0, visitor.error_count_);
EXPECT_EQ(3, visitor.setting_count_);
- if (IsHttp2()) {
- EXPECT_EQ(1, visitor.settings_ack_sent_);
- }
+ EXPECT_EQ(1, visitor.settings_ack_sent_);
// Read data in small chunks.
size_t framed_data = 0;
@@ -4349,28 +2812,13 @@ TEST_P(SpdyFramerTest, ReadLargeSettingsFrame) {
}
EXPECT_EQ(0, visitor.error_count_);
EXPECT_EQ(3 * 2, visitor.setting_count_);
- if (IsHttp2()) {
- EXPECT_EQ(2, visitor.settings_ack_sent_);
- }
+ EXPECT_EQ(2, visitor.settings_ack_sent_);
}
// Tests handling of SETTINGS frame with duplicate entries.
TEST_P(SpdyFramerTest, ReadDuplicateSettings) {
- SpdyFramer framer(spdy_version_);
-
- // clang-format off
- const unsigned char kV3FrameData[] = {
- 0x80, 0x03, 0x00, 0x04,
- 0x00, 0x00, 0x00, 0x1C,
- 0x00, 0x00, 0x00, 0x03,
- 0x00, 0x00, 0x00, 0x01, // 1st Setting
- 0x00, 0x00, 0x00, 0x02,
- 0x00, 0x00, 0x00, 0x01, // 2nd (duplicate) Setting
- 0x00, 0x00, 0x00, 0x03,
- 0x00, 0x00, 0x00, 0x03, // 3rd (unprocessed) Setting
- 0x00, 0x00, 0x00, 0x03,
- };
- // clang-format on
+ SpdyFramer framer(SpdyFramer::ENABLE_COMPRESSION);
+
const unsigned char kH2FrameData[] = {
0x00, 0x00, 0x12, // Length: 18
0x04, // Type: SETTINGS
@@ -4384,39 +2832,19 @@ TEST_P(SpdyFramerTest, ReadDuplicateSettings) {
0x00, 0x00, 0x00, 0x03, // Value: 3
};
- TestSpdyVisitor visitor(spdy_version_);
- visitor.use_compression_ = false;
- if (IsSpdy3()) {
- visitor.SimulateInFramer(kV3FrameData, sizeof(kV3FrameData));
- } else {
- visitor.SimulateInFramer(kH2FrameData, sizeof(kH2FrameData));
- }
+ TestSpdyVisitor visitor(SpdyFramer::DISABLE_COMPRESSION);
+ visitor.SimulateInFramer(kH2FrameData, sizeof(kH2FrameData));
- if (IsSpdy3()) {
- EXPECT_EQ(1, visitor.setting_count_);
- EXPECT_EQ(1, visitor.error_count_);
- } else {
- // In HTTP/2, duplicate settings are allowed;
- // each setting replaces the previous value for that setting.
- EXPECT_EQ(3, visitor.setting_count_);
- EXPECT_EQ(0, visitor.error_count_);
- EXPECT_EQ(1, visitor.settings_ack_sent_);
- }
+ // In HTTP/2, duplicate settings are allowed;
+ // each setting replaces the previous value for that setting.
+ EXPECT_EQ(3, visitor.setting_count_);
+ EXPECT_EQ(0, visitor.error_count_);
+ EXPECT_EQ(1, visitor.settings_ack_sent_);
}
// Tests handling of SETTINGS frame with a setting we don't recognize.
TEST_P(SpdyFramerTest, ReadUnknownSettingsId) {
- SpdyFramer framer(spdy_version_);
-
- // clang-format off
- const unsigned char kV3FrameData[] = {
- 0x80, 0x03, 0x00, 0x04,
- 0x00, 0x00, 0x00, 0x1C,
- 0x00, 0x00, 0x00, 0x01,
- 0x00, 0x00, 0x00, 0x10, // 1st Setting
- 0x00, 0x00, 0x00, 0x02,
- };
- // clang-format on
+ SpdyFramer framer(SpdyFramer::ENABLE_COMPRESSION);
const unsigned char kH2FrameData[] = {
0x00, 0x00, 0x06, // Length: 6
0x04, // Type: SETTINGS
@@ -4426,41 +2854,17 @@ TEST_P(SpdyFramerTest, ReadUnknownSettingsId) {
0x00, 0x00, 0x00, 0x02, // Value: 2
};
- TestSpdyVisitor visitor(spdy_version_);
- visitor.use_compression_ = false;
- if (IsSpdy3()) {
- visitor.SimulateInFramer(kV3FrameData, sizeof(kV3FrameData));
- } else {
- visitor.SimulateInFramer(kH2FrameData, sizeof(kH2FrameData));
- }
+ TestSpdyVisitor visitor(SpdyFramer::DISABLE_COMPRESSION);
+ visitor.SimulateInFramer(kH2FrameData, sizeof(kH2FrameData));
- if (IsSpdy3()) {
- EXPECT_EQ(0, visitor.setting_count_);
- EXPECT_EQ(1, visitor.error_count_);
- } else {
- // In HTTP/2, we ignore unknown settings because of extensions.
- EXPECT_EQ(0, visitor.setting_count_);
- EXPECT_EQ(0, visitor.error_count_);
- }
+ // In HTTP/2, we ignore unknown settings because of extensions.
+ EXPECT_EQ(0, visitor.setting_count_);
+ EXPECT_EQ(0, visitor.error_count_);
}
// Tests handling of SETTINGS frame with entries out of order.
TEST_P(SpdyFramerTest, ReadOutOfOrderSettings) {
- SpdyFramer framer(spdy_version_);
-
- // clang-format off
- const unsigned char kV3FrameData[] = {
- 0x80, 0x03, 0x00, 0x04,
- 0x00, 0x00, 0x00, 0x1C,
- 0x00, 0x00, 0x00, 0x03,
- 0x00, 0x00, 0x00, 0x02, // 1st Setting
- 0x00, 0x00, 0x00, 0x02,
- 0x00, 0x00, 0x00, 0x01, // 2nd (out of order) Setting
- 0x00, 0x00, 0x00, 0x03,
- 0x00, 0x00, 0x01, 0x03, // 3rd (unprocessed) Setting
- 0x00, 0x00, 0x00, 0x03,
- };
- // clang-format on
+ SpdyFramer framer(SpdyFramer::ENABLE_COMPRESSION);
const unsigned char kH2FrameData[] = {
0x00, 0x00, 0x12, // Length: 18
0x04, // Type: SETTINGS
@@ -4474,30 +2878,16 @@ TEST_P(SpdyFramerTest, ReadOutOfOrderSettings) {
0x00, 0x00, 0x00, 0x03, // Value: 3
};
- TestSpdyVisitor visitor(spdy_version_);
- visitor.use_compression_ = false;
- if (IsSpdy3()) {
- visitor.SimulateInFramer(kV3FrameData, sizeof(kV3FrameData));
- } else {
- visitor.SimulateInFramer(kH2FrameData, sizeof(kH2FrameData));
- }
+ TestSpdyVisitor visitor(SpdyFramer::DISABLE_COMPRESSION);
+ visitor.SimulateInFramer(kH2FrameData, sizeof(kH2FrameData));
- if (IsSpdy3()) {
- EXPECT_EQ(1, visitor.setting_count_);
- EXPECT_EQ(1, visitor.error_count_);
- } else {
- // In HTTP/2, settings are allowed in any order.
- EXPECT_EQ(3, visitor.setting_count_);
- EXPECT_EQ(0, visitor.error_count_);
- }
+ // In HTTP/2, settings are allowed in any order.
+ EXPECT_EQ(3, visitor.setting_count_);
+ EXPECT_EQ(0, visitor.error_count_);
}
TEST_P(SpdyFramerTest, ProcessSettingsAckFrame) {
- if (!IsHttp2()) {
- return;
- }
-
- SpdyFramer framer(spdy_version_);
+ SpdyFramer framer(SpdyFramer::ENABLE_COMPRESSION);
const unsigned char kFrameData[] = {
0x00, 0x00, 0x00, // Length: 0
@@ -4506,8 +2896,7 @@ TEST_P(SpdyFramerTest, ProcessSettingsAckFrame) {
0x00, 0x00, 0x00, 0x00, // Stream: 0
};
- TestSpdyVisitor visitor(spdy_version_);
- visitor.use_compression_ = false;
+ TestSpdyVisitor visitor(SpdyFramer::DISABLE_COMPRESSION);
visitor.SimulateInFramer(kFrameData, sizeof(kFrameData));
EXPECT_EQ(0, visitor.error_count_);
@@ -4516,15 +2905,11 @@ TEST_P(SpdyFramerTest, ProcessSettingsAckFrame) {
}
TEST_P(SpdyFramerTest, ProcessDataFrameWithPadding) {
- if (!IsHttp2()) {
- return;
- }
-
const int kPaddingLen = 119;
const char data_payload[] = "hello";
testing::StrictMock<test::MockSpdyFramerVisitor> visitor;
- SpdyFramer framer(spdy_version_);
+ SpdyFramer framer(SpdyFramer::ENABLE_COMPRESSION);
framer.set_visitor(&visitor);
SpdyDataIR data_ir(1, data_payload);
@@ -4578,10 +2963,10 @@ TEST_P(SpdyFramerTest, ProcessDataFrameWithPadding) {
}
TEST_P(SpdyFramerTest, ReadWindowUpdate) {
- SpdyFramer framer(spdy_version_);
+ SpdyFramer framer(SpdyFramer::ENABLE_COMPRESSION);
SpdySerializedFrame control_frame(
framer.SerializeWindowUpdate(SpdyWindowUpdateIR(1, 2)));
- TestSpdyVisitor visitor(spdy_version_);
+ TestSpdyVisitor visitor(SpdyFramer::DISABLE_COMPRESSION);
visitor.SimulateInFramer(
reinterpret_cast<unsigned char*>(control_frame.data()),
control_frame.size());
@@ -4590,17 +2975,12 @@ TEST_P(SpdyFramerTest, ReadWindowUpdate) {
}
TEST_P(SpdyFramerTest, ReadCompressedPushPromise) {
- if (!IsHttp2()) {
- return;
- }
-
- SpdyFramer framer(spdy_version_);
+ SpdyFramer framer(SpdyFramer::ENABLE_COMPRESSION);
SpdyPushPromiseIR push_promise(42, 57);
push_promise.SetHeader("foo", "bar");
push_promise.SetHeader("bar", "foofoo");
SpdySerializedFrame frame(framer.SerializePushPromise(push_promise));
- TestSpdyVisitor visitor(spdy_version_);
- visitor.use_compression_ = true;
+ TestSpdyVisitor visitor(SpdyFramer::ENABLE_COMPRESSION);
visitor.SimulateInFramer(reinterpret_cast<unsigned char*>(frame.data()),
frame.size());
EXPECT_EQ(42u, visitor.last_push_promise_stream_);
@@ -4609,10 +2989,6 @@ TEST_P(SpdyFramerTest, ReadCompressedPushPromise) {
}
TEST_P(SpdyFramerTest, ReadHeadersWithContinuation) {
- if (!IsHttp2()) {
- return;
- }
-
// frame-format off
const unsigned char kInput[] = {
0x00, 0x00, 0x14, // Length: 20
@@ -4654,8 +3030,7 @@ TEST_P(SpdyFramerTest, ReadHeadersWithContinuation) {
};
// frame-format on
- SpdyFramer framer(spdy_version_);
- TestSpdyVisitor visitor(spdy_version_);
+ TestSpdyVisitor visitor(SpdyFramer::DISABLE_COMPRESSION);
visitor.SimulateInFramer(kInput, sizeof(kInput));
EXPECT_EQ(0, visitor.error_count_);
@@ -4671,9 +3046,6 @@ TEST_P(SpdyFramerTest, ReadHeadersWithContinuation) {
}
TEST_P(SpdyFramerTest, ReadHeadersWithContinuationAndFin) {
- if (!IsHttp2()) {
- return;
- }
// frame-format off
const unsigned char kInput[] = {
0x00, 0x00, 0x10, // Length: 20
@@ -4713,8 +3085,8 @@ TEST_P(SpdyFramerTest, ReadHeadersWithContinuationAndFin) {
};
// frame-format on
- SpdyFramer framer(spdy_version_);
- TestSpdyVisitor visitor(spdy_version_);
+ SpdyFramer framer(SpdyFramer::ENABLE_COMPRESSION);
+ TestSpdyVisitor visitor(SpdyFramer::DISABLE_COMPRESSION);
visitor.SimulateInFramer(kInput, sizeof(kInput));
EXPECT_EQ(0, visitor.error_count_);
@@ -4731,10 +3103,6 @@ TEST_P(SpdyFramerTest, ReadHeadersWithContinuationAndFin) {
}
TEST_P(SpdyFramerTest, ReadPushPromiseWithContinuation) {
- if (!IsHttp2()) {
- return;
- }
-
// frame-format off
const unsigned char kInput[] = {
0x00, 0x00, 0x17, 0x05, // PUSH_PROMISE
@@ -4765,8 +3133,8 @@ TEST_P(SpdyFramerTest, ReadPushPromiseWithContinuation) {
};
// frame-format on
- SpdyFramer framer(spdy_version_);
- TestSpdyVisitor visitor(spdy_version_);
+ SpdyFramer framer(SpdyFramer::ENABLE_COMPRESSION);
+ TestSpdyVisitor visitor(SpdyFramer::DISABLE_COMPRESSION);
visitor.SimulateInFramer(kInput, sizeof(kInput));
EXPECT_EQ(0, visitor.error_count_);
@@ -4785,10 +3153,6 @@ TEST_P(SpdyFramerTest, ReadPushPromiseWithContinuation) {
// Receiving an unknown frame when a continuation is expected should
// result in a SPDY_UNEXPECTED_FRAME error
TEST_P(SpdyFramerTest, ReceiveUnknownMidContinuation) {
- if (!IsHttp2()) {
- return;
- }
-
const unsigned char kInput[] = {
0x00, 0x00, 0x10, // Length: 16
0x01, // Type: HEADERS
@@ -4810,8 +3174,8 @@ TEST_P(SpdyFramerTest, ReceiveUnknownMidContinuation) {
0x67, 0x00, 0x06, 0x63, //
};
- SpdyFramer framer(spdy_version_);
- TestSpdyVisitor visitor(spdy_version_);
+ SpdyFramer framer(SpdyFramer::ENABLE_COMPRESSION);
+ TestSpdyVisitor visitor(SpdyFramer::DISABLE_COMPRESSION);
// Assume the unknown frame is allowed
visitor.on_unknown_frame_result_ = true;
framer.set_visitor(&visitor);
@@ -4826,10 +3190,6 @@ TEST_P(SpdyFramerTest, ReceiveUnknownMidContinuation) {
}
TEST_P(SpdyFramerTest, ReceiveContinuationOnWrongStream) {
- if (!IsHttp2()) {
- return;
- }
-
const unsigned char kInput[] = {
0x00, 0x00, 0x10, // Length: 16
0x01, // Type: HEADERS
@@ -4851,8 +3211,8 @@ TEST_P(SpdyFramerTest, ReceiveContinuationOnWrongStream) {
0x67, 0x00, 0x06, 0x63, //
};
- SpdyFramer framer(spdy_version_);
- TestSpdyVisitor visitor(spdy_version_);
+ SpdyFramer framer(SpdyFramer::ENABLE_COMPRESSION);
+ TestSpdyVisitor visitor(SpdyFramer::DISABLE_COMPRESSION);
framer.set_visitor(&visitor);
visitor.SimulateInFramer(kInput, sizeof(kInput));
@@ -4865,10 +3225,6 @@ TEST_P(SpdyFramerTest, ReceiveContinuationOnWrongStream) {
}
TEST_P(SpdyFramerTest, ReadContinuationOutOfOrder) {
- if (!IsHttp2()) {
- return;
- }
-
const unsigned char kInput[] = {
0x00, 0x00, 0x18, // Length: 24
0x09, // Type: CONTINUATION
@@ -4880,8 +3236,8 @@ TEST_P(SpdyFramerTest, ReadContinuationOutOfOrder) {
0x3d, 0x62, 0x61, 0x72, //
};
- SpdyFramer framer(spdy_version_);
- TestSpdyVisitor visitor(spdy_version_);
+ SpdyFramer framer(SpdyFramer::ENABLE_COMPRESSION);
+ TestSpdyVisitor visitor(SpdyFramer::DISABLE_COMPRESSION);
framer.set_visitor(&visitor);
visitor.SimulateInFramer(kInput, sizeof(kInput));
@@ -4893,10 +3249,6 @@ TEST_P(SpdyFramerTest, ReadContinuationOutOfOrder) {
}
TEST_P(SpdyFramerTest, ExpectContinuationReceiveData) {
- if (!IsHttp2()) {
- return;
- }
-
const unsigned char kInput[] = {
0x00, 0x00, 0x10, // Length: 16
0x01, // Type: HEADERS
@@ -4915,8 +3267,8 @@ TEST_P(SpdyFramerTest, ExpectContinuationReceiveData) {
0xde, 0xad, 0xbe, 0xef, // Truncated Frame Header
};
- SpdyFramer framer(spdy_version_);
- TestSpdyVisitor visitor(spdy_version_);
+ SpdyFramer framer(SpdyFramer::ENABLE_COMPRESSION);
+ TestSpdyVisitor visitor(SpdyFramer::DISABLE_COMPRESSION);
framer.set_visitor(&visitor);
visitor.SimulateInFramer(kInput, sizeof(kInput));
@@ -4930,10 +3282,6 @@ TEST_P(SpdyFramerTest, ExpectContinuationReceiveData) {
}
TEST_P(SpdyFramerTest, ExpectContinuationReceiveControlFrame) {
- if (!IsHttp2()) {
- return;
- }
-
const unsigned char kInput[] = {
0x00, 0x00, 0x10, // Length: 16
0x01, // Type: HEADERS
@@ -4954,8 +3302,8 @@ TEST_P(SpdyFramerTest, ExpectContinuationReceiveControlFrame) {
0x3d, 0x62, 0x61, 0x72, //
};
- SpdyFramer framer(spdy_version_);
- TestSpdyVisitor visitor(spdy_version_);
+ SpdyFramer framer(SpdyFramer::ENABLE_COMPRESSION);
+ TestSpdyVisitor visitor(SpdyFramer::DISABLE_COMPRESSION);
framer.set_visitor(&visitor);
visitor.SimulateInFramer(kInput, sizeof(kInput));
@@ -4969,21 +3317,16 @@ TEST_P(SpdyFramerTest, ExpectContinuationReceiveControlFrame) {
}
TEST_P(SpdyFramerTest, ReadGarbage) {
- SpdyFramer framer(spdy_version_);
+ SpdyFramer framer(SpdyFramer::ENABLE_COMPRESSION);
unsigned char garbage_frame[256];
memset(garbage_frame, ~0, sizeof(garbage_frame));
- TestSpdyVisitor visitor(spdy_version_);
- visitor.use_compression_ = false;
+ TestSpdyVisitor visitor(SpdyFramer::DISABLE_COMPRESSION);
visitor.SimulateInFramer(garbage_frame, sizeof(garbage_frame));
EXPECT_EQ(1, visitor.error_count_);
}
TEST_P(SpdyFramerTest, ReadUnknownExtensionFrame) {
- if (!IsHttp2()) {
- return;
- }
-
- SpdyFramer framer(spdy_version_);
+ SpdyFramer framer(SpdyFramer::ENABLE_COMPRESSION);
// The unrecognized frame type should still have a valid length.
const unsigned char unknown_frame[] = {
@@ -4994,21 +3337,17 @@ TEST_P(SpdyFramerTest, ReadUnknownExtensionFrame) {
0xff, 0xff, 0xff, 0xff, // Payload
0xff, 0xff, 0xff, 0xff, //
};
- TestSpdyVisitor visitor(spdy_version_);
+ TestSpdyVisitor visitor(SpdyFramer::DISABLE_COMPRESSION);
// Simulate the case where the stream id validation checks out.
visitor.on_unknown_frame_result_ = true;
- visitor.use_compression_ = false;
visitor.SimulateInFramer(unknown_frame, arraysize(unknown_frame));
EXPECT_EQ(0, visitor.error_count_);
// Follow it up with a valid control frame to make sure we handle
// subsequent frames correctly.
SpdySettingsIR settings_ir;
- settings_ir.AddSetting(SpdyConstants::ParseSettingId(spdy_version_, 1),
- false, // persist
- false, // persisted
- 10);
+ settings_ir.AddSetting(SETTINGS_HEADER_TABLE_SIZE, 10);
SpdySerializedFrame control_frame(framer.SerializeSettings(settings_ir));
visitor.SimulateInFramer(
reinterpret_cast<unsigned char*>(control_frame.data()),
@@ -5019,11 +3358,7 @@ TEST_P(SpdyFramerTest, ReadUnknownExtensionFrame) {
}
TEST_P(SpdyFramerTest, ReadGarbageWithValidLength) {
- if (!IsHttp2()) {
- return;
- }
-
- SpdyFramer framer(spdy_version_);
+ SpdyFramer framer(SpdyFramer::ENABLE_COMPRESSION);
const unsigned char kFrameData[] = {
0x00, 0x00, 0x08, // Length: 8
0xff, // Type: UnknownFrameType(255)
@@ -5032,35 +3367,12 @@ TEST_P(SpdyFramerTest, ReadGarbageWithValidLength) {
0xff, 0xff, 0xff, 0xff, // Payload
0xff, 0xff, 0xff, 0xff, //
};
- TestSpdyVisitor visitor(spdy_version_);
- visitor.use_compression_ = false;
- visitor.SimulateInFramer(kFrameData, arraysize(kFrameData));
- EXPECT_EQ(1, visitor.error_count_);
-}
-
-TEST_P(SpdyFramerTest, ReadGarbageWithValidVersion) {
- if (!IsSpdy3()) {
- return;
- }
-
- SpdyFramer framer(spdy_version_);
- // clang-format off
- const unsigned char kFrameData[] = {
- 0x80, 0x03, 0xff, 0xff,
- 0xff, 0xff, 0xff, 0xff,
- };
- // clang-format on
- TestSpdyVisitor visitor(spdy_version_);
- visitor.use_compression_ = false;
+ TestSpdyVisitor visitor(SpdyFramer::DISABLE_COMPRESSION);
visitor.SimulateInFramer(kFrameData, arraysize(kFrameData));
EXPECT_EQ(1, visitor.error_count_);
}
TEST_P(SpdyFramerTest, ReadGarbageHPACKEncoding) {
- if (!IsHttp2()) {
- return;
- }
-
const unsigned char kInput[] = {
0x00, 0x12, 0x01, // Length: 4609
0x04, // Type: SETTINGS
@@ -5074,45 +3386,27 @@ TEST_P(SpdyFramerTest, ReadGarbageHPACKEncoding) {
0xff, //
};
- TestSpdyVisitor visitor(spdy_version_);
+ TestSpdyVisitor visitor(SpdyFramer::DISABLE_COMPRESSION);
visitor.SimulateInFramer(kInput, arraysize(kInput));
EXPECT_EQ(1, visitor.error_count_);
}
TEST_P(SpdyFramerTest, SizesTest) {
- SpdyFramer framer(spdy_version_);
- if (IsSpdy3()) {
- EXPECT_EQ(8u, framer.GetDataFrameMinimumSize());
- EXPECT_EQ(8u, framer.GetFrameHeaderSize());
- EXPECT_EQ(18u, framer.GetSynStreamMinimumSize());
- EXPECT_EQ(12u, framer.GetSynReplyMinimumSize());
- EXPECT_EQ(16u, framer.GetRstStreamMinimumSize());
- EXPECT_EQ(12u, framer.GetSettingsMinimumSize());
- EXPECT_EQ(12u, framer.GetPingSize());
- EXPECT_EQ(16u, framer.GetGoAwayMinimumSize());
- EXPECT_EQ(12u, framer.GetHeadersMinimumSize());
- EXPECT_EQ(16u, framer.GetWindowUpdateSize());
- EXPECT_EQ(8u, framer.GetFrameMinimumSize());
- EXPECT_EQ(16777223u, framer.GetFrameMaximumSize());
- EXPECT_EQ(16777215u, framer.GetDataFrameMaximumPayload());
- } else {
- EXPECT_EQ(9u, framer.GetDataFrameMinimumSize());
- EXPECT_EQ(9u, framer.GetFrameHeaderSize());
- EXPECT_EQ(14u, framer.GetSynStreamMinimumSize());
- EXPECT_EQ(9u, framer.GetSynReplyMinimumSize());
- EXPECT_EQ(13u, framer.GetRstStreamMinimumSize());
- EXPECT_EQ(9u, framer.GetSettingsMinimumSize());
- EXPECT_EQ(17u, framer.GetPingSize());
- EXPECT_EQ(17u, framer.GetGoAwayMinimumSize());
- EXPECT_EQ(9u, framer.GetHeadersMinimumSize());
- EXPECT_EQ(13u, framer.GetWindowUpdateSize());
- EXPECT_EQ(9u, framer.GetBlockedSize());
- EXPECT_EQ(13u, framer.GetPushPromiseMinimumSize());
- EXPECT_EQ(11u, framer.GetAltSvcMinimumSize());
- EXPECT_EQ(9u, framer.GetFrameMinimumSize());
- EXPECT_EQ(16393u, framer.GetFrameMaximumSize());
- EXPECT_EQ(16384u, framer.GetDataFrameMaximumPayload());
- }
+ SpdyFramer framer(SpdyFramer::ENABLE_COMPRESSION);
+ EXPECT_EQ(9u, framer.GetDataFrameMinimumSize());
+ EXPECT_EQ(9u, framer.GetFrameHeaderSize());
+ EXPECT_EQ(13u, framer.GetRstStreamSize());
+ EXPECT_EQ(9u, framer.GetSettingsMinimumSize());
+ EXPECT_EQ(17u, framer.GetPingSize());
+ EXPECT_EQ(17u, framer.GetGoAwayMinimumSize());
+ EXPECT_EQ(9u, framer.GetHeadersMinimumSize());
+ EXPECT_EQ(13u, framer.GetWindowUpdateSize());
+ EXPECT_EQ(9u, framer.GetBlockedSize());
+ EXPECT_EQ(13u, framer.GetPushPromiseMinimumSize());
+ EXPECT_EQ(11u, framer.GetAltSvcMinimumSize());
+ EXPECT_EQ(9u, framer.GetFrameMinimumSize());
+ EXPECT_EQ(16393u, framer.GetFrameMaximumSize());
+ EXPECT_EQ(16384u, framer.GetDataFrameMaximumPayload());
}
TEST_P(SpdyFramerTest, StateToStringTest) {
@@ -5188,24 +3482,33 @@ TEST_P(SpdyFramerTest, StatusCodeToStringTest) {
EXPECT_STREQ("NO_ERROR", SpdyFramer::StatusCodeToString(RST_STREAM_NO_ERROR));
EXPECT_STREQ("PROTOCOL_ERROR",
SpdyFramer::StatusCodeToString(RST_STREAM_PROTOCOL_ERROR));
- EXPECT_STREQ("INVALID_STREAM",
- SpdyFramer::StatusCodeToString(RST_STREAM_INVALID_STREAM));
- EXPECT_STREQ("REFUSED_STREAM",
- SpdyFramer::StatusCodeToString(RST_STREAM_REFUSED_STREAM));
- EXPECT_STREQ("UNSUPPORTED_VERSION",
- SpdyFramer::StatusCodeToString(RST_STREAM_UNSUPPORTED_VERSION));
- EXPECT_STREQ("CANCEL", SpdyFramer::StatusCodeToString(RST_STREAM_CANCEL));
EXPECT_STREQ("INTERNAL_ERROR",
SpdyFramer::StatusCodeToString(RST_STREAM_INTERNAL_ERROR));
EXPECT_STREQ("FLOW_CONTROL_ERROR",
SpdyFramer::StatusCodeToString(RST_STREAM_FLOW_CONTROL_ERROR));
- EXPECT_STREQ("UNKNOWN_STATUS", SpdyFramer::StatusCodeToString(-1));
+ EXPECT_STREQ("SETTINGS_TIMEOUT",
+ SpdyFramer::StatusCodeToString(RST_STREAM_SETTINGS_TIMEOUT));
+ EXPECT_STREQ("STREAM_CLOSED",
+ SpdyFramer::StatusCodeToString(RST_STREAM_STREAM_CLOSED));
+ EXPECT_STREQ("FRAME_SIZE_ERROR",
+ SpdyFramer::StatusCodeToString(RST_STREAM_FRAME_SIZE_ERROR));
+ EXPECT_STREQ("REFUSED_STREAM",
+ SpdyFramer::StatusCodeToString(RST_STREAM_REFUSED_STREAM));
+ EXPECT_STREQ("CANCEL", SpdyFramer::StatusCodeToString(RST_STREAM_CANCEL));
+ EXPECT_STREQ("COMPRESSION_ERROR",
+ SpdyFramer::StatusCodeToString(RST_STREAM_COMPRESSION_ERROR));
+ EXPECT_STREQ("CONNECT_ERROR",
+ SpdyFramer::StatusCodeToString(RST_STREAM_CONNECT_ERROR));
+ EXPECT_STREQ("ENHANCE_YOUR_CALM",
+ SpdyFramer::StatusCodeToString(RST_STREAM_ENHANCE_YOUR_CALM));
+ EXPECT_STREQ("INADEQUATE_SECURITY",
+ SpdyFramer::StatusCodeToString(RST_STREAM_INADEQUATE_SECURITY));
+ EXPECT_STREQ("HTTP_1_1_REQUIRED",
+ SpdyFramer::StatusCodeToString(RST_STREAM_HTTP_1_1_REQUIRED));
}
TEST_P(SpdyFramerTest, FrameTypeToStringTest) {
EXPECT_STREQ("DATA", SpdyFramer::FrameTypeToString(DATA));
- EXPECT_STREQ("SYN_STREAM", SpdyFramer::FrameTypeToString(SYN_STREAM));
- EXPECT_STREQ("SYN_REPLY", SpdyFramer::FrameTypeToString(SYN_REPLY));
EXPECT_STREQ("RST_STREAM", SpdyFramer::FrameTypeToString(RST_STREAM));
EXPECT_STREQ("SETTINGS", SpdyFramer::FrameTypeToString(SETTINGS));
EXPECT_STREQ("PING", SpdyFramer::FrameTypeToString(PING));
@@ -5216,84 +3519,7 @@ TEST_P(SpdyFramerTest, FrameTypeToStringTest) {
EXPECT_STREQ("CONTINUATION", SpdyFramer::FrameTypeToString(CONTINUATION));
}
-TEST_P(SpdyFramerTest, CatchProbableHttpResponse) {
- if (!IsSpdy3()) {
- // TODO(hkhalil): catch probable HTTP response in HTTP/2?
- return;
- }
-
- {
- testing::StrictMock<test::MockSpdyFramerVisitor> visitor;
- SpdyFramer framer(spdy_version_);
- framer.set_visitor(&visitor);
-
- EXPECT_CALL(visitor, OnError(_));
- framer.ProcessInput("HTTP/1.1", 8);
- EXPECT_TRUE(framer.probable_http_response());
- EXPECT_EQ(SpdyFramer::SPDY_ERROR, framer.state());
- EXPECT_EQ(SpdyFramer::SPDY_INVALID_DATA_FRAME_FLAGS, framer.error_code())
- << SpdyFramer::ErrorCodeToString(framer.error_code());
- }
- {
- testing::StrictMock<test::MockSpdyFramerVisitor> visitor;
- SpdyFramer framer(spdy_version_);
- framer.set_visitor(&visitor);
-
- EXPECT_CALL(visitor, OnError(_));
- framer.ProcessInput("HTTP/1.0", 8);
- EXPECT_TRUE(framer.probable_http_response());
- EXPECT_EQ(SpdyFramer::SPDY_ERROR, framer.state());
- EXPECT_EQ(SpdyFramer::SPDY_INVALID_DATA_FRAME_FLAGS, framer.error_code())
- << SpdyFramer::ErrorCodeToString(framer.error_code());
- }
-}
-
-TEST_P(SpdyFramerTest, DataFrameFlagsV2V3) {
- if (!IsSpdy3()) {
- return;
- }
-
- uint8_t flags = 0;
- do {
- SCOPED_TRACE(testing::Message() << "Flags " << flags << std::hex
- << static_cast<int>(flags));
-
- testing::StrictMock<test::MockSpdyFramerVisitor> visitor;
- SpdyFramer framer(spdy_version_);
- framer.set_visitor(&visitor);
-
- SpdyDataIR data_ir(1, "hello");
- SpdySerializedFrame frame(framer.SerializeData(data_ir));
- SetFrameFlags(&frame, flags, spdy_version_);
-
- if (flags & ~DATA_FLAG_FIN) {
- EXPECT_CALL(visitor, OnError(_));
- } else {
- EXPECT_CALL(visitor, OnDataFrameHeader(1, 5, flags & DATA_FLAG_FIN));
- EXPECT_CALL(visitor, OnStreamFrameData(_, _, 5));
- if (flags & DATA_FLAG_FIN) {
- EXPECT_CALL(visitor, OnStreamEnd(_));
- }
- }
-
- framer.ProcessInput(frame.data(), frame.size());
- if (flags & ~DATA_FLAG_FIN) {
- EXPECT_EQ(SpdyFramer::SPDY_ERROR, framer.state());
- EXPECT_EQ(SpdyFramer::SPDY_INVALID_DATA_FRAME_FLAGS, framer.error_code())
- << SpdyFramer::ErrorCodeToString(framer.error_code());
- } else {
- EXPECT_EQ(SpdyFramer::SPDY_READY_FOR_FRAME, framer.state());
- EXPECT_EQ(SpdyFramer::SPDY_NO_ERROR, framer.error_code())
- << SpdyFramer::ErrorCodeToString(framer.error_code());
- }
- } while (++flags != 0);
-}
-
TEST_P(SpdyFramerTest, DataFrameFlagsV4) {
- if (!IsHttp2()) {
- return;
- }
-
uint8_t valid_data_flags = DATA_FLAG_FIN | DATA_FLAG_PADDED;
uint8_t flags = 0;
@@ -5302,12 +3528,12 @@ TEST_P(SpdyFramerTest, DataFrameFlagsV4) {
<< static_cast<int>(flags));
testing::StrictMock<test::MockSpdyFramerVisitor> visitor;
- SpdyFramer framer(spdy_version_);
+ SpdyFramer framer(SpdyFramer::ENABLE_COMPRESSION);
framer.set_visitor(&visitor);
SpdyDataIR data_ir(1, "hello");
SpdySerializedFrame frame(framer.SerializeData(data_ir));
- SetFrameFlags(&frame, flags, spdy_version_);
+ SetFrameFlags(&frame, flags);
if (flags & ~valid_data_flags) {
EXPECT_CALL(visitor, OnError(_));
@@ -5344,105 +3570,6 @@ TEST_P(SpdyFramerTest, DataFrameFlagsV4) {
} while (++flags != 0);
}
-TEST_P(SpdyFramerTest, SynStreamFrameFlags) {
- if (!IsSpdy3()) {
- return;
- }
-
- uint8_t flags = 0;
- do {
- SCOPED_TRACE(testing::Message() << "Flags " << flags << std::hex
- << static_cast<int>(flags));
-
- testing::StrictMock<test::MockSpdyFramerVisitor> visitor;
- testing::StrictMock<test::MockDebugVisitor> debug_visitor;
- SpdyFramer framer(spdy_version_);
- framer.set_visitor(&visitor);
- framer.set_debug_visitor(&debug_visitor);
-
- EXPECT_CALL(debug_visitor, OnSendCompressedFrame(8, SYN_STREAM, _, _));
-
- SpdySynStreamIR syn_stream(8);
- syn_stream.set_associated_to_stream_id(3);
- syn_stream.set_priority(1);
- syn_stream.SetHeader("foo", "bar");
- SpdySerializedFrame frame(framer.SerializeSynStream(syn_stream));
- SetFrameFlags(&frame, flags, spdy_version_);
-
- if (flags & ~(CONTROL_FLAG_FIN | CONTROL_FLAG_UNIDIRECTIONAL)) {
- EXPECT_CALL(visitor, OnError(_));
- } else {
- EXPECT_CALL(debug_visitor, OnReceiveCompressedFrame(8, SYN_STREAM, _));
- EXPECT_CALL(visitor, OnSynStream(8, 3, 1, flags & CONTROL_FLAG_FIN,
- flags & CONTROL_FLAG_UNIDIRECTIONAL));
- EXPECT_CALL(visitor, OnHeaderFrameStart(8)).Times(1);
- EXPECT_CALL(visitor, OnHeaderFrameEnd(8, _)).Times(1);
- if (flags & DATA_FLAG_FIN) {
- EXPECT_CALL(visitor, OnStreamEnd(_));
- } else {
- // Do not close the stream if we are expecting a CONTINUATION frame.
- EXPECT_CALL(visitor, OnStreamEnd(_)).Times(0);
- }
- }
-
- framer.ProcessInput(frame.data(), frame.size());
- if (flags & ~(CONTROL_FLAG_FIN | CONTROL_FLAG_UNIDIRECTIONAL)) {
- EXPECT_EQ(SpdyFramer::SPDY_ERROR, framer.state());
- EXPECT_EQ(SpdyFramer::SPDY_INVALID_CONTROL_FRAME_FLAGS,
- framer.error_code())
- << SpdyFramer::ErrorCodeToString(framer.error_code());
- } else {
- EXPECT_EQ(SpdyFramer::SPDY_READY_FOR_FRAME, framer.state());
- EXPECT_EQ(SpdyFramer::SPDY_NO_ERROR, framer.error_code())
- << SpdyFramer::ErrorCodeToString(framer.error_code());
- }
- } while (++flags != 0);
-}
-
-TEST_P(SpdyFramerTest, SynReplyFrameFlags) {
- if (!IsSpdy3()) {
- return;
- }
-
- uint8_t flags = 0;
- do {
- SCOPED_TRACE(testing::Message() << "Flags " << flags << std::hex
- << static_cast<int>(flags));
-
- testing::StrictMock<test::MockSpdyFramerVisitor> visitor;
- SpdyFramer framer(spdy_version_);
- framer.set_visitor(&visitor);
-
- SpdySynReplyIR syn_reply(37);
- syn_reply.SetHeader("foo", "bar");
- SpdySerializedFrame frame(framer.SerializeSynReply(syn_reply));
- SetFrameFlags(&frame, flags, spdy_version_);
-
- if (flags & ~CONTROL_FLAG_FIN) {
- EXPECT_CALL(visitor, OnError(_));
- } else {
- EXPECT_CALL(visitor, OnSynReply(37, flags & CONTROL_FLAG_FIN));
- EXPECT_CALL(visitor, OnHeaderFrameStart(37)).Times(1);
- EXPECT_CALL(visitor, OnHeaderFrameEnd(37, _)).Times(1);
- if (flags & DATA_FLAG_FIN) {
- EXPECT_CALL(visitor, OnStreamEnd(_));
- }
- }
-
- framer.ProcessInput(frame.data(), frame.size());
- if (flags & ~CONTROL_FLAG_FIN) {
- EXPECT_EQ(SpdyFramer::SPDY_ERROR, framer.state());
- EXPECT_EQ(SpdyFramer::SPDY_INVALID_CONTROL_FRAME_FLAGS,
- framer.error_code())
- << SpdyFramer::ErrorCodeToString(framer.error_code());
- } else {
- EXPECT_EQ(SpdyFramer::SPDY_READY_FOR_FRAME, framer.state());
- EXPECT_EQ(SpdyFramer::SPDY_NO_ERROR, framer.error_code())
- << SpdyFramer::ErrorCodeToString(framer.error_code());
- }
- } while (++flags != 0);
-}
-
TEST_P(SpdyFramerTest, RstStreamFrameFlags) {
uint8_t flags = 0;
do {
@@ -5450,12 +3577,12 @@ TEST_P(SpdyFramerTest, RstStreamFrameFlags) {
<< static_cast<int>(flags));
testing::StrictMock<test::MockSpdyFramerVisitor> visitor;
- SpdyFramer framer(spdy_version_);
+ SpdyFramer framer(SpdyFramer::ENABLE_COMPRESSION);
framer.set_visitor(&visitor);
SpdyRstStreamIR rst_stream(13, RST_STREAM_CANCEL);
SpdySerializedFrame frame(framer.SerializeRstStream(rst_stream));
- SetFrameFlags(&frame, flags, spdy_version_);
+ SetFrameFlags(&frame, flags);
EXPECT_CALL(visitor, OnRstStream(13, RST_STREAM_CANCEL));
@@ -5467,75 +3594,26 @@ TEST_P(SpdyFramerTest, RstStreamFrameFlags) {
} while (++flags != 0);
}
-TEST_P(SpdyFramerTest, SettingsFrameFlagsOldFormat) {
- if (!IsSpdy3()) {
- return;
- }
-
- uint8_t flags = 0;
- do {
- SCOPED_TRACE(testing::Message() << "Flags " << flags << std::hex
- << static_cast<int>(flags));
-
- testing::StrictMock<test::MockSpdyFramerVisitor> visitor;
- SpdyFramer framer(spdy_version_);
- framer.set_visitor(&visitor);
-
- SpdySettingsIR settings_ir;
- settings_ir.AddSetting(SETTINGS_UPLOAD_BANDWIDTH, false, false, 54321);
- SpdySerializedFrame frame(framer.SerializeSettings(settings_ir));
- SetFrameFlags(&frame, flags, spdy_version_);
-
- if (flags & ~SETTINGS_FLAG_CLEAR_PREVIOUSLY_PERSISTED_SETTINGS) {
- EXPECT_CALL(visitor, OnError(_));
- } else {
- EXPECT_CALL(
- visitor,
- OnSettings(flags &
- SETTINGS_FLAG_CLEAR_PREVIOUSLY_PERSISTED_SETTINGS));
- EXPECT_CALL(visitor, OnSetting(SETTINGS_UPLOAD_BANDWIDTH,
- SETTINGS_FLAG_NONE, 54321));
- EXPECT_CALL(visitor, OnSettingsEnd());
- }
-
- framer.ProcessInput(frame.data(), frame.size());
- if (flags & ~SETTINGS_FLAG_CLEAR_PREVIOUSLY_PERSISTED_SETTINGS) {
- EXPECT_EQ(SpdyFramer::SPDY_ERROR, framer.state());
- EXPECT_EQ(SpdyFramer::SPDY_INVALID_CONTROL_FRAME_FLAGS,
- framer.error_code())
- << SpdyFramer::ErrorCodeToString(framer.error_code());
- } else {
- EXPECT_EQ(SpdyFramer::SPDY_READY_FOR_FRAME, framer.state());
- EXPECT_EQ(SpdyFramer::SPDY_NO_ERROR, framer.error_code())
- << SpdyFramer::ErrorCodeToString(framer.error_code());
- }
- } while (++flags != 0);
-}
-
TEST_P(SpdyFramerTest, SettingsFrameFlags) {
- if (!IsHttp2()) {
- return;
- }
-
uint8_t flags = 0;
do {
SCOPED_TRACE(testing::Message() << "Flags " << flags << std::hex
<< static_cast<int>(flags));
testing::StrictMock<test::MockSpdyFramerVisitor> visitor;
- SpdyFramer framer(spdy_version_);
+ SpdyFramer framer(SpdyFramer::ENABLE_COMPRESSION);
framer.set_visitor(&visitor);
SpdySettingsIR settings_ir;
- settings_ir.AddSetting(SETTINGS_INITIAL_WINDOW_SIZE, 0, 0, 16);
+ settings_ir.AddSetting(SETTINGS_INITIAL_WINDOW_SIZE, 16);
SpdySerializedFrame frame(framer.SerializeSettings(settings_ir));
- SetFrameFlags(&frame, flags, spdy_version_);
+ SetFrameFlags(&frame, flags);
if (flags & SETTINGS_FLAG_ACK) {
EXPECT_CALL(visitor, OnError(_));
} else {
EXPECT_CALL(visitor, OnSettings(flags & SETTINGS_FLAG_ACK));
- EXPECT_CALL(visitor, OnSetting(SETTINGS_INITIAL_WINDOW_SIZE, 0, 16));
+ EXPECT_CALL(visitor, OnSetting(SETTINGS_INITIAL_WINDOW_SIZE, 16));
EXPECT_CALL(visitor, OnSettingsEnd());
}
@@ -5561,14 +3639,14 @@ TEST_P(SpdyFramerTest, GoawayFrameFlags) {
<< static_cast<int>(flags));
testing::StrictMock<test::MockSpdyFramerVisitor> visitor;
- SpdyFramer framer(spdy_version_);
+ SpdyFramer framer(SpdyFramer::ENABLE_COMPRESSION);
framer.set_visitor(&visitor);
- SpdyGoAwayIR goaway_ir(97, GOAWAY_OK, "test");
+ SpdyGoAwayIR goaway_ir(97, GOAWAY_NO_ERROR, "test");
SpdySerializedFrame frame(framer.SerializeGoAway(goaway_ir));
- SetFrameFlags(&frame, flags, spdy_version_);
+ SetFrameFlags(&frame, flags);
- EXPECT_CALL(visitor, OnGoAway(97, GOAWAY_OK));
+ EXPECT_CALL(visitor, OnGoAway(97, GOAWAY_NO_ERROR));
framer.ProcessInput(frame.data(), frame.size());
EXPECT_EQ(SpdyFramer::SPDY_READY_FOR_FRAME, framer.state());
@@ -5584,11 +3662,11 @@ TEST_P(SpdyFramerTest, HeadersFrameFlags) {
<< static_cast<int>(flags));
testing::StrictMock<test::MockSpdyFramerVisitor> visitor;
- SpdyFramer framer(spdy_version_);
+ SpdyFramer framer(SpdyFramer::ENABLE_COMPRESSION);
framer.set_visitor(&visitor);
SpdyHeadersIR headers_ir(57);
- if (IsHttp2() && (flags & HEADERS_FLAG_PRIORITY)) {
+ if (flags & HEADERS_FLAG_PRIORITY) {
headers_ir.set_weight(3);
headers_ir.set_has_priority(true);
headers_ir.set_parent_stream_id(5);
@@ -5597,13 +3675,8 @@ TEST_P(SpdyFramerTest, HeadersFrameFlags) {
headers_ir.SetHeader("foo", "bar");
SpdySerializedFrame frame(
SpdyFramerPeer::SerializeHeaders(&framer, headers_ir));
- uint8_t set_flags = flags;
- if (IsHttp2()) {
- // TODO(jgraettinger): Add padding to SpdyHeadersIR,
- // and implement framing.
- set_flags &= ~HEADERS_FLAG_PADDED;
- }
- SetFrameFlags(&frame, set_flags, spdy_version_);
+ uint8_t set_flags = flags & ~HEADERS_FLAG_PADDED;
+ SetFrameFlags(&frame, set_flags);
// Expected callback values
SpdyStreamId stream_id = 57;
@@ -5612,8 +3685,8 @@ TEST_P(SpdyFramerTest, HeadersFrameFlags) {
SpdyStreamId parent_stream_id = 0;
bool exclusive = false;
bool fin = flags & CONTROL_FLAG_FIN;
- bool end = IsSpdy3() || (flags & HEADERS_FLAG_END_HEADERS);
- if (IsHttp2() && flags & HEADERS_FLAG_PRIORITY) {
+ bool end = flags & HEADERS_FLAG_END_HEADERS;
+ if (flags & HEADERS_FLAG_PRIORITY) {
has_priority = true;
priority = 3;
parent_stream_id = 5;
@@ -5625,8 +3698,7 @@ TEST_P(SpdyFramerTest, HeadersFrameFlags) {
if (end) {
EXPECT_CALL(visitor, OnHeaderFrameEnd(57, _)).Times(1);
}
- if (flags & DATA_FLAG_FIN &&
- (IsSpdy3() || flags & HEADERS_FLAG_END_HEADERS)) {
+ if (flags & DATA_FLAG_FIN && end) {
EXPECT_CALL(visitor, OnStreamEnd(_));
} else {
// Do not close the stream if we are expecting a CONTINUATION frame.
@@ -5647,13 +3719,13 @@ TEST_P(SpdyFramerTest, PingFrameFlags) {
<< static_cast<int>(flags));
testing::StrictMock<test::MockSpdyFramerVisitor> visitor;
- SpdyFramer framer(spdy_version_);
+ SpdyFramer framer(SpdyFramer::ENABLE_COMPRESSION);
framer.set_visitor(&visitor);
SpdySerializedFrame frame(framer.SerializePing(SpdyPingIR(42)));
- SetFrameFlags(&frame, flags, spdy_version_);
+ SetFrameFlags(&frame, flags);
- if (IsHttp2() && (flags & PING_FLAG_ACK)) {
+ if (flags & PING_FLAG_ACK) {
EXPECT_CALL(visitor, OnPing(42, true));
} else {
EXPECT_CALL(visitor, OnPing(42, false));
@@ -5673,12 +3745,12 @@ TEST_P(SpdyFramerTest, WindowUpdateFrameFlags) {
<< static_cast<int>(flags));
testing::StrictMock<test::MockSpdyFramerVisitor> visitor;
- SpdyFramer framer(spdy_version_);
+ SpdyFramer framer(SpdyFramer::ENABLE_COMPRESSION);
framer.set_visitor(&visitor);
SpdySerializedFrame frame(
framer.SerializeWindowUpdate(SpdyWindowUpdateIR(4, 1024)));
- SetFrameFlags(&frame, flags, spdy_version_);
+ SetFrameFlags(&frame, flags);
EXPECT_CALL(visitor, OnWindowUpdate(4, 1024));
@@ -5690,10 +3762,6 @@ TEST_P(SpdyFramerTest, WindowUpdateFrameFlags) {
}
TEST_P(SpdyFramerTest, PushPromiseFrameFlags) {
- if (!IsHttp2()) {
- return;
- }
-
const SpdyStreamId client_id = 123; // Must be odd.
const SpdyStreamId promised_id = 22; // Must be even.
uint8_t flags = 0;
@@ -5703,7 +3771,7 @@ TEST_P(SpdyFramerTest, PushPromiseFrameFlags) {
testing::StrictMock<test::MockSpdyFramerVisitor> visitor;
testing::StrictMock<test::MockDebugVisitor> debug_visitor;
- SpdyFramer framer(spdy_version_);
+ SpdyFramer framer(SpdyFramer::ENABLE_COMPRESSION);
framer.set_visitor(&visitor);
framer.set_debug_visitor(&debug_visitor);
@@ -5715,7 +3783,7 @@ TEST_P(SpdyFramerTest, PushPromiseFrameFlags) {
SpdySerializedFrame frame(framer.SerializePushPromise(push_promise));
// TODO(jgraettinger): Add padding to SpdyPushPromiseIR,
// and implement framing.
- SetFrameFlags(&frame, flags & ~HEADERS_FLAG_PADDED, spdy_version_);
+ SetFrameFlags(&frame, flags & ~HEADERS_FLAG_PADDED);
bool end = flags & PUSH_PROMISE_FLAG_END_PUSH_PROMISE;
EXPECT_CALL(debug_visitor,
@@ -5734,10 +3802,6 @@ TEST_P(SpdyFramerTest, PushPromiseFrameFlags) {
}
TEST_P(SpdyFramerTest, ContinuationFrameFlags) {
- if (!IsHttp2()) {
- return;
- }
-
uint8_t flags = 0;
do {
SCOPED_TRACE(testing::Message() << "Flags " << flags << std::hex
@@ -5745,7 +3809,7 @@ TEST_P(SpdyFramerTest, ContinuationFrameFlags) {
testing::StrictMock<test::MockSpdyFramerVisitor> visitor;
testing::StrictMock<test::MockDebugVisitor> debug_visitor;
- SpdyFramer framer(spdy_version_);
+ SpdyFramer framer(SpdyFramer::ENABLE_COMPRESSION);
framer.set_visitor(&visitor);
framer.set_debug_visitor(&debug_visitor);
@@ -5758,11 +3822,11 @@ TEST_P(SpdyFramerTest, ContinuationFrameFlags) {
headers_ir.SetHeader("foo", "bar");
SpdySerializedFrame frame0(
SpdyFramerPeer::SerializeHeaders(&framer, headers_ir));
- SetFrameFlags(&frame0, 0, spdy_version_);
+ SetFrameFlags(&frame0, 0);
SpdyContinuationIR continuation(42);
SpdySerializedFrame frame(framer.SerializeContinuation(continuation));
- SetFrameFlags(&frame, flags, spdy_version_);
+ SetFrameFlags(&frame, flags);
EXPECT_CALL(debug_visitor, OnReceiveCompressedFrame(42, CONTINUATION, _));
EXPECT_CALL(visitor, OnContinuation(42, flags & HEADERS_FLAG_END_HEADERS));
@@ -5779,66 +3843,12 @@ TEST_P(SpdyFramerTest, ContinuationFrameFlags) {
} while (++flags != 0);
}
-// TODO(mlavan): Add TEST_P(SpdyFramerTest, AltSvcFrameFlags)
+// TODO(mlavan): Add TEST_F(SpdyFramerTest, AltSvcFrameFlags)
-// TODO(hkhalil): Add TEST_P(SpdyFramerTest, BlockedFrameFlags)
-
-TEST_P(SpdyFramerTest, EmptySynStream) {
- if (!IsSpdy3()) {
- return;
- }
-
- testing::StrictMock<test::MockSpdyFramerVisitor> visitor;
- testing::StrictMock<test::MockDebugVisitor> debug_visitor;
- SpdyFramer framer(spdy_version_);
- framer.set_visitor(&visitor);
- framer.set_debug_visitor(&debug_visitor);
-
- EXPECT_CALL(debug_visitor, OnSendCompressedFrame(1, SYN_STREAM, _, _));
-
- SpdySynStreamIR syn_stream(1);
- syn_stream.set_priority(1);
- SpdySerializedFrame frame(framer.SerializeSynStream(syn_stream));
- // Adjust size to remove the header block.
- SetFrameLength(&frame,
- framer.GetSynStreamMinimumSize() - framer.GetFrameHeaderSize(),
- spdy_version_);
-
- EXPECT_CALL(debug_visitor, OnReceiveCompressedFrame(1, SYN_STREAM, _));
- EXPECT_CALL(visitor, OnSynStream(1, 0, 1, false, false));
- EXPECT_CALL(visitor, OnHeaderFrameStart(1)).Times(1);
- EXPECT_CALL(visitor, OnHeaderFrameEnd(1, _)).Times(1);
-
- framer.ProcessInput(frame.data(), framer.GetSynStreamMinimumSize());
- EXPECT_EQ(SpdyFramer::SPDY_READY_FOR_FRAME, framer.state());
- EXPECT_EQ(SpdyFramer::SPDY_NO_ERROR, framer.error_code())
- << SpdyFramer::ErrorCodeToString(framer.error_code());
-}
-
-TEST_P(SpdyFramerTest, SettingsFlagsAndId) {
- const uint32_t kId = 0x020304;
- const uint32_t kFlags = 0x01;
- const uint32_t kWireFormat = base::HostToNet32(0x01020304);
-
- SettingsFlagsAndId id_and_flags =
- SettingsFlagsAndId::FromWireFormat(spdy_version_, kWireFormat);
- EXPECT_EQ(kId, id_and_flags.id());
- EXPECT_EQ(kFlags, id_and_flags.flags());
- EXPECT_EQ(kWireFormat, id_and_flags.GetWireFormat(spdy_version_));
-}
+// TODO(hkhalil): Add TEST_F(SpdyFramerTest, BlockedFrameFlags)
// Test handling of a RST_STREAM with out-of-bounds status codes.
TEST_P(SpdyFramerTest, RstStreamStatusBounds) {
- const unsigned char kRstStreamStatusTooLow = 0x00;
- const unsigned char kRstStreamStatusTooHigh = 0xff;
- // clang-format off
- const unsigned char kV3RstStreamInvalid[] = {
- 0x80, 0x03, 0x00, 0x03,
- 0x00, 0x00, 0x00, 0x08,
- 0x00, 0x00, 0x00, 0x01,
- 0x00, 0x00, 0x00, kRstStreamStatusTooLow
- };
- // clang-format on
const unsigned char kH2RstStreamInvalid[] = {
0x00, 0x00, 0x04, // Length: 4
0x03, // Type: RST_STREAM
@@ -5846,15 +3856,6 @@ TEST_P(SpdyFramerTest, RstStreamStatusBounds) {
0x00, 0x00, 0x00, 0x01, // Stream: 1
0x00, 0x00, 0x00, 0x00, // Error: NO_ERROR
};
-
- // clang-format off
- const unsigned char kV3RstStreamNumStatusCodes[] = {
- 0x80, 0x03, 0x00, 0x03,
- 0x00, 0x00, 0x00, 0x08,
- 0x00, 0x00, 0x00, 0x01,
- 0x00, 0x00, 0x00, kRstStreamStatusTooHigh
- };
- // clang-format on
const unsigned char kH2RstStreamNumStatusCodes[] = {
0x00, 0x00, 0x04, // Length: 4
0x03, // Type: RST_STREAM
@@ -5864,35 +3865,21 @@ TEST_P(SpdyFramerTest, RstStreamStatusBounds) {
};
testing::StrictMock<test::MockSpdyFramerVisitor> visitor;
- SpdyFramer framer(spdy_version_);
+ SpdyFramer framer(SpdyFramer::ENABLE_COMPRESSION);
framer.set_visitor(&visitor);
- if (IsSpdy3()) {
- EXPECT_CALL(visitor, OnRstStream(1, RST_STREAM_NO_ERROR));
- framer.ProcessInput(reinterpret_cast<const char*>(kV3RstStreamInvalid),
- arraysize(kV3RstStreamInvalid));
- } else {
- EXPECT_CALL(visitor, OnRstStream(1, RST_STREAM_NO_ERROR));
- framer.ProcessInput(reinterpret_cast<const char*>(kH2RstStreamInvalid),
- arraysize(kH2RstStreamInvalid));
- }
+ EXPECT_CALL(visitor, OnRstStream(1, RST_STREAM_NO_ERROR));
+ framer.ProcessInput(reinterpret_cast<const char*>(kH2RstStreamInvalid),
+ arraysize(kH2RstStreamInvalid));
EXPECT_EQ(SpdyFramer::SPDY_READY_FOR_FRAME, framer.state());
EXPECT_EQ(SpdyFramer::SPDY_NO_ERROR, framer.error_code())
<< SpdyFramer::ErrorCodeToString(framer.error_code());
framer.Reset();
- if (IsSpdy3()) {
- EXPECT_CALL(visitor, OnRstStream(1, RST_STREAM_NO_ERROR));
- framer.ProcessInput(
- reinterpret_cast<const char*>(kV3RstStreamNumStatusCodes),
- arraysize(kV3RstStreamNumStatusCodes));
- } else {
- EXPECT_CALL(visitor, OnRstStream(1, RST_STREAM_INTERNAL_ERROR));
- framer.ProcessInput(
- reinterpret_cast<const char*>(kH2RstStreamNumStatusCodes),
- arraysize(kH2RstStreamNumStatusCodes));
- }
+ EXPECT_CALL(visitor, OnRstStream(1, RST_STREAM_INTERNAL_ERROR));
+ framer.ProcessInput(reinterpret_cast<const char*>(kH2RstStreamNumStatusCodes),
+ arraysize(kH2RstStreamNumStatusCodes));
EXPECT_EQ(SpdyFramer::SPDY_READY_FOR_FRAME, framer.state());
EXPECT_EQ(SpdyFramer::SPDY_NO_ERROR, framer.error_code())
<< SpdyFramer::ErrorCodeToString(framer.error_code());
@@ -5900,16 +3887,7 @@ TEST_P(SpdyFramerTest, RstStreamStatusBounds) {
// Test handling of GOAWAY frames with out-of-bounds status code.
TEST_P(SpdyFramerTest, GoAwayStatusBounds) {
- SpdyFramer framer(spdy_version_);
-
- // clang-format off
- const unsigned char kV3FrameData[] = {
- 0x80, 0x03, 0x00, 0x07,
- 0x00, 0x00, 0x00, 0x08,
- 0x00, 0x00, 0x00, 0x01, // Stream Id
- 0xff, 0xff, 0xff, 0xff, // Status
- };
- // clang-format on
+ SpdyFramer framer(SpdyFramer::ENABLE_COMPRESSION);
const unsigned char kH2FrameData[] = {
0x00, 0x00, 0x0a, // Length: 10
0x07, // Type: GOAWAY
@@ -5922,15 +3900,9 @@ TEST_P(SpdyFramerTest, GoAwayStatusBounds) {
testing::StrictMock<test::MockSpdyFramerVisitor> visitor;
framer.set_visitor(&visitor);
- if (IsSpdy3()) {
- EXPECT_CALL(visitor, OnGoAway(1, GOAWAY_OK));
- framer.ProcessInput(reinterpret_cast<const char*>(kV3FrameData),
- arraysize(kV3FrameData));
- } else {
- EXPECT_CALL(visitor, OnGoAway(1, GOAWAY_INTERNAL_ERROR));
- framer.ProcessInput(reinterpret_cast<const char*>(kH2FrameData),
- arraysize(kH2FrameData));
- }
+ EXPECT_CALL(visitor, OnGoAway(1, GOAWAY_INTERNAL_ERROR));
+ framer.ProcessInput(reinterpret_cast<const char*>(kH2FrameData),
+ arraysize(kH2FrameData));
EXPECT_EQ(SpdyFramer::SPDY_READY_FOR_FRAME, framer.state());
EXPECT_EQ(SpdyFramer::SPDY_NO_ERROR, framer.error_code())
<< SpdyFramer::ErrorCodeToString(framer.error_code());
@@ -5938,14 +3910,6 @@ TEST_P(SpdyFramerTest, GoAwayStatusBounds) {
// Tests handling of a GOAWAY frame with out-of-bounds stream ID.
TEST_P(SpdyFramerTest, GoAwayStreamIdBounds) {
- // clang-format off
- const unsigned char kV3FrameData[] = {
- 0x80, 0x03, 0x00, 0x07,
- 0x00, 0x00, 0x00, 0x08,
- 0xff, 0xff, 0xff, 0xff,
- 0x00, 0x00, 0x00, 0x00,
- };
- // clang-format on
const unsigned char kH2FrameData[] = {
0x00, 0x00, 0x08, // Length: 8
0x07, // Type: GOAWAY
@@ -5956,31 +3920,22 @@ TEST_P(SpdyFramerTest, GoAwayStreamIdBounds) {
};
testing::StrictMock<test::MockSpdyFramerVisitor> visitor;
- SpdyFramer framer(spdy_version_);
+ SpdyFramer framer(SpdyFramer::ENABLE_COMPRESSION);
framer.set_visitor(&visitor);
- EXPECT_CALL(visitor, OnGoAway(0x7fffffff, GOAWAY_OK));
- if (IsSpdy3()) {
- framer.ProcessInput(reinterpret_cast<const char*>(kV3FrameData),
- arraysize(kV3FrameData));
- } else {
- framer.ProcessInput(reinterpret_cast<const char*>(kH2FrameData),
- arraysize(kH2FrameData));
- }
+ EXPECT_CALL(visitor, OnGoAway(0x7fffffff, GOAWAY_NO_ERROR));
+ framer.ProcessInput(reinterpret_cast<const char*>(kH2FrameData),
+ arraysize(kH2FrameData));
EXPECT_EQ(SpdyFramer::SPDY_READY_FOR_FRAME, framer.state());
EXPECT_EQ(SpdyFramer::SPDY_NO_ERROR, framer.error_code())
<< SpdyFramer::ErrorCodeToString(framer.error_code());
}
TEST_P(SpdyFramerTest, OnBlocked) {
- if (!IsHttp2()) {
- return;
- }
-
const SpdyStreamId kStreamId = 0;
testing::StrictMock<test::MockSpdyFramerVisitor> visitor;
- SpdyFramer framer(spdy_version_);
+ SpdyFramer framer(SpdyFramer::ENABLE_COMPRESSION);
framer.set_visitor(&visitor);
EXPECT_CALL(visitor, OnBlocked(kStreamId));
@@ -5995,14 +3950,10 @@ TEST_P(SpdyFramerTest, OnBlocked) {
}
TEST_P(SpdyFramerTest, OnAltSvc) {
- if (!IsHttp2()) {
- return;
- }
-
const SpdyStreamId kStreamId = 1;
testing::StrictMock<test::MockSpdyFramerVisitor> visitor;
- SpdyFramer framer(spdy_version_);
+ SpdyFramer framer(SpdyFramer::ENABLE_COMPRESSION);
framer.set_visitor(&visitor);
SpdyAltSvcWireFormat::AlternativeService altsvc1(
@@ -6028,14 +3979,10 @@ TEST_P(SpdyFramerTest, OnAltSvc) {
}
TEST_P(SpdyFramerTest, OnAltSvcNoOrigin) {
- if (!IsHttp2()) {
- return;
- }
-
const SpdyStreamId kStreamId = 1;
testing::StrictMock<test::MockSpdyFramerVisitor> visitor;
- SpdyFramer framer(spdy_version_);
+ SpdyFramer framer(SpdyFramer::ENABLE_COMPRESSION);
framer.set_visitor(&visitor);
SpdyAltSvcWireFormat::AlternativeService altsvc1(
@@ -6059,12 +4006,8 @@ TEST_P(SpdyFramerTest, OnAltSvcNoOrigin) {
}
TEST_P(SpdyFramerTest, OnAltSvcEmptyProtocolId) {
- if (!IsHttp2()) {
- return;
- }
-
testing::StrictMock<test::MockSpdyFramerVisitor> visitor;
- SpdyFramer framer(spdy_version_);
+ SpdyFramer framer(SpdyFramer::ENABLE_COMPRESSION);
framer.set_visitor(&visitor);
EXPECT_CALL(visitor, OnError(testing::Eq(&framer)));
@@ -6084,40 +4027,26 @@ TEST_P(SpdyFramerTest, OnAltSvcEmptyProtocolId) {
}
TEST_P(SpdyFramerTest, OnAltSvcBadLengths) {
- if (!IsHttp2()) {
- return;
- }
-
- const SpdyStreamId kStreamId = 1;
+ const char kType = static_cast<unsigned char>(SerializeFrameType(ALTSVC));
+ const unsigned char kFrameDataOriginLenLargerThanFrame[] = {
+ 0x00, 0x00, 0x05, kType, 0x00, 0x00, 0x00,
+ 0x00, 0x03, 0x42, 0x42, 'f', 'o', 'o',
+ };
- testing::StrictMock<test::MockSpdyFramerVisitor> visitor;
- SpdyFramer framer(spdy_version_);
+ TestSpdyVisitor visitor(SpdyFramer::DISABLE_COMPRESSION);
+ SpdyFramer framer(SpdyFramer::ENABLE_COMPRESSION);
framer.set_visitor(&visitor);
+ visitor.SimulateInFramer(kFrameDataOriginLenLargerThanFrame,
+ sizeof(kFrameDataOriginLenLargerThanFrame));
- SpdyAltSvcWireFormat::AlternativeService altsvc(
- "pid", "h1", 443, 10, SpdyAltSvcWireFormat::VersionVector());
- SpdyAltSvcWireFormat::AlternativeServiceVector altsvc_vector;
- altsvc_vector.push_back(altsvc);
- EXPECT_CALL(visitor, OnAltSvc(kStreamId, StringPiece("o1"), altsvc_vector));
-
- SpdyAltSvcIR altsvc_ir(1);
- altsvc_ir.set_origin("o1");
- altsvc_ir.add_altsvc(altsvc);
- SpdySerializedFrame frame(framer.SerializeFrame(altsvc_ir));
- framer.ProcessInput(frame.data(), frame.size());
-
- EXPECT_EQ(SpdyFramer::SPDY_READY_FOR_FRAME, framer.state());
- EXPECT_EQ(SpdyFramer::SPDY_NO_ERROR, framer.error_code())
- << SpdyFramer::ErrorCodeToString(framer.error_code());
+ EXPECT_EQ(1, visitor.error_count_);
+ EXPECT_EQ(SpdyFramer::SPDY_INVALID_CONTROL_FRAME,
+ visitor.framer_.error_code());
}
// Tests handling of ALTSVC frames delivered in small chunks.
TEST_P(SpdyFramerTest, ReadChunkedAltSvcFrame) {
- if (!IsHttp2()) {
- return;
- }
-
- SpdyFramer framer(spdy_version_);
+ SpdyFramer framer(SpdyFramer::ENABLE_COMPRESSION);
SpdyAltSvcIR altsvc_ir(1);
SpdyAltSvcWireFormat::AlternativeService altsvc1(
"pid1", "host", 443, 5, SpdyAltSvcWireFormat::VersionVector());
@@ -6127,8 +4056,7 @@ TEST_P(SpdyFramerTest, ReadChunkedAltSvcFrame) {
altsvc_ir.add_altsvc(altsvc2);
SpdySerializedFrame control_frame(framer.SerializeAltSvc(altsvc_ir));
- TestSpdyVisitor visitor(spdy_version_);
- visitor.use_compression_ = false;
+ TestSpdyVisitor visitor(SpdyFramer::DISABLE_COMPRESSION);
// Read data in small chunks.
size_t framed_data = 0;
@@ -6151,11 +4079,7 @@ TEST_P(SpdyFramerTest, ReadChunkedAltSvcFrame) {
// Tests handling of PRIORITY frames.
TEST_P(SpdyFramerTest, ReadPriority) {
- if (!IsHttp2()) {
- return;
- }
-
- SpdyFramer framer(spdy_version_);
+ SpdyFramer framer(SpdyFramer::ENABLE_COMPRESSION);
SpdyPriorityIR priority(3, 1, 256, false);
SpdySerializedFrame frame(framer.SerializePriority(priority));
testing::StrictMock<test::MockSpdyFramerVisitor> visitor;
@@ -6172,10 +4096,6 @@ TEST_P(SpdyFramerTest, ReadPriority) {
// Tests handling of PRIORITY frame with incorrect size.
TEST_P(SpdyFramerTest, ReadIncorrectlySizedPriority) {
- if (!IsHttp2()) {
- return;
- }
-
// PRIORITY frame of size 4, which isn't correct.
const unsigned char kFrameData[] = {
0x00, 0x00, 0x04, // Length: 4
@@ -6185,7 +4105,7 @@ TEST_P(SpdyFramerTest, ReadIncorrectlySizedPriority) {
0x00, 0x00, 0x00, 0x01, // Priority (Truncated)
};
- TestSpdyVisitor visitor(spdy_version_);
+ TestSpdyVisitor visitor(SpdyFramer::DISABLE_COMPRESSION);
visitor.SimulateInFramer(kFrameData, sizeof(kFrameData));
EXPECT_EQ(SpdyFramer::SPDY_ERROR, visitor.framer_.state());
@@ -6196,10 +4116,6 @@ TEST_P(SpdyFramerTest, ReadIncorrectlySizedPriority) {
// Tests handling of PING frame with incorrect size.
TEST_P(SpdyFramerTest, ReadIncorrectlySizedPing) {
- if (!IsHttp2()) {
- return;
- }
-
// PING frame of size 4, which isn't correct.
const unsigned char kFrameData[] = {
0x00, 0x00, 0x04, // Length: 4
@@ -6209,7 +4125,7 @@ TEST_P(SpdyFramerTest, ReadIncorrectlySizedPing) {
0x00, 0x00, 0x00, 0x01, // Ping (Truncated)
};
- TestSpdyVisitor visitor(spdy_version_);
+ TestSpdyVisitor visitor(SpdyFramer::DISABLE_COMPRESSION);
visitor.SimulateInFramer(kFrameData, sizeof(kFrameData));
EXPECT_EQ(SpdyFramer::SPDY_ERROR, visitor.framer_.state());
@@ -6220,10 +4136,6 @@ TEST_P(SpdyFramerTest, ReadIncorrectlySizedPing) {
// Tests handling of WINDOW_UPDATE frame with incorrect size.
TEST_P(SpdyFramerTest, ReadIncorrectlySizedWindowUpdate) {
- if (!IsHttp2()) {
- return;
- }
-
// WINDOW_UPDATE frame of size 3, which isn't correct.
const unsigned char kFrameData[] = {
0x00, 0x00, 0x03, // Length: 3
@@ -6233,7 +4145,7 @@ TEST_P(SpdyFramerTest, ReadIncorrectlySizedWindowUpdate) {
0x00, 0x00, 0x01, // WindowUpdate (Truncated)
};
- TestSpdyVisitor visitor(spdy_version_);
+ TestSpdyVisitor visitor(SpdyFramer::DISABLE_COMPRESSION);
visitor.SimulateInFramer(kFrameData, sizeof(kFrameData));
EXPECT_EQ(SpdyFramer::SPDY_ERROR, visitor.framer_.state());
@@ -6244,10 +4156,6 @@ TEST_P(SpdyFramerTest, ReadIncorrectlySizedWindowUpdate) {
// Tests handling of RST_STREAM frame with incorrect size.
TEST_P(SpdyFramerTest, ReadIncorrectlySizedRstStream) {
- if (!IsHttp2()) {
- return;
- }
-
// RST_STREAM frame of size 3, which isn't correct.
const unsigned char kFrameData[] = {
0x00, 0x00, 0x03, // Length: 3
@@ -6257,7 +4165,7 @@ TEST_P(SpdyFramerTest, ReadIncorrectlySizedRstStream) {
0x00, 0x00, 0x01, // RstStream (Truncated)
};
- TestSpdyVisitor visitor(spdy_version_);
+ TestSpdyVisitor visitor(SpdyFramer::DISABLE_COMPRESSION);
visitor.SimulateInFramer(kFrameData, sizeof(kFrameData));
EXPECT_EQ(SpdyFramer::SPDY_ERROR, visitor.framer_.state());
@@ -6269,8 +4177,9 @@ TEST_P(SpdyFramerTest, ReadIncorrectlySizedRstStream) {
// Test that SpdyFramer processes, by default, all passed input in one call
// to ProcessInput (i.e. will not be calling set_process_single_input_frame()).
TEST_P(SpdyFramerTest, ProcessAllInput) {
- SpdyFramer framer(spdy_version_);
- std::unique_ptr<TestSpdyVisitor> visitor(new TestSpdyVisitor(spdy_version_));
+ SpdyFramer framer(SpdyFramer::ENABLE_COMPRESSION);
+ std::unique_ptr<TestSpdyVisitor> visitor(
+ new TestSpdyVisitor(SpdyFramer::DISABLE_COMPRESSION));
framer.set_visitor(visitor.get());
// Create two input frames.
@@ -6318,7 +4227,7 @@ TEST_P(SpdyFramerTest, ProcessAllInput) {
// only processes the first when we give it the first frame split at any point,
// or give it more than one frame in the input buffer.
TEST_P(SpdyFramerTest, ProcessAtMostOneFrame) {
- SpdyFramer framer(spdy_version_);
+ SpdyFramer framer(SpdyFramer::ENABLE_COMPRESSION);
framer.set_process_single_input_frame(true);
std::unique_ptr<TestSpdyVisitor> visitor;
@@ -6356,7 +4265,7 @@ TEST_P(SpdyFramerTest, ProcessAtMostOneFrame) {
for (size_t first_size = 0; first_size <= buf_size; ++first_size) {
VLOG(1) << "first_size = " << first_size;
- visitor.reset(new TestSpdyVisitor(spdy_version_));
+ visitor.reset(new TestSpdyVisitor(SpdyFramer::DISABLE_COMPRESSION));
framer.set_visitor(visitor.get());
EXPECT_EQ(SpdyFramer::SPDY_READY_FOR_FRAME, framer.state());
diff --git a/chromium/net/spdy/spdy_header_block.cc b/chromium/net/spdy/spdy_header_block.cc
index 4e36b8927b5..6cbd6ba645c 100644
--- a/chromium/net/spdy/spdy_header_block.cc
+++ b/chromium/net/spdy/spdy_header_block.cc
@@ -19,6 +19,7 @@
using base::StringPiece;
using std::dec;
using std::hex;
+using std::make_pair;
using std::max;
using std::min;
using std::string;
@@ -30,6 +31,16 @@ namespace {
const size_t kDefaultStorageBlockSize = 2048;
const char kCookieKey[] = "cookie";
+const char kNullSeparator = 0;
+
+StringPiece SeparatorForKey(StringPiece key) {
+ if (key == kCookieKey) {
+ static StringPiece cookie_separator = "; ";
+ return cookie_separator;
+ } else {
+ return StringPiece(&kNullSeparator, 1);
+ }
+}
} // namespace
@@ -50,24 +61,6 @@ class SpdyHeaderBlock::Storage {
return StringPiece(arena_.Memdup(s.data(), s.size()), s.size());
}
- // Given value, a string already in the arena, perform a realloc and append
- // separator and more to the end of the value's new location. If value is the
- // most recently added string (via Write), then UnsafeArena will not copy the
- // existing value but instead will increase the space reserved for value.
- StringPiece Realloc(StringPiece value,
- StringPiece separator,
- StringPiece more) {
- size_t total_length = value.size() + separator.size() + more.size();
- char* ptr = const_cast<char*>(value.data());
- ptr = arena_.Realloc(ptr, value.size(), total_length);
- StringPiece result(ptr, total_length);
- ptr += value.size();
- memcpy(ptr, separator.data(), separator.size());
- ptr += separator.size();
- memcpy(ptr, more.data(), more.size());
- return result;
- }
-
// If |s| points to the most recent allocation from arena_, the arena will
// reclaim the memory. Otherwise, this method is a no-op.
void Rewind(const StringPiece s) {
@@ -76,10 +69,77 @@ class SpdyHeaderBlock::Storage {
void Clear() { arena_.Reset(); }
+ // Given a list of fragments and a separator, writes the fragments joined by
+ // the separator to a contiguous region of memory. Returns a StringPiece
+ // pointing to the region of memory.
+ StringPiece WriteFragments(const std::vector<StringPiece>& fragments,
+ StringPiece separator) {
+ if (fragments.empty()) {
+ return StringPiece();
+ }
+ size_t total_size = separator.size() * (fragments.size() - 1);
+ for (const auto fragment : fragments) {
+ total_size += fragment.size();
+ }
+ char* dst = arena_.Alloc(total_size);
+ size_t written = Join(dst, fragments, separator);
+ DCHECK_EQ(written, total_size);
+ return StringPiece(dst, total_size);
+ }
+
+ size_t bytes_allocated() const { return arena_.status().bytes_allocated(); }
+
private:
UnsafeArena arena_;
};
+SpdyHeaderBlock::HeaderValue::HeaderValue(Storage* storage,
+ StringPiece key,
+ StringPiece initial_value)
+ : storage_(storage), fragments_({initial_value}), pair_({key, {}}) {}
+
+SpdyHeaderBlock::HeaderValue::HeaderValue(HeaderValue&& other)
+ : storage_(other.storage_),
+ fragments_(std::move(other.fragments_)),
+ pair_(std::move(other.pair_)) {}
+
+SpdyHeaderBlock::HeaderValue& SpdyHeaderBlock::HeaderValue::operator=(
+ HeaderValue&& other) {
+ storage_ = other.storage_;
+ fragments_ = std::move(other.fragments_);
+ pair_ = std::move(other.pair_);
+ return *this;
+}
+
+SpdyHeaderBlock::HeaderValue::~HeaderValue() {}
+
+StringPiece SpdyHeaderBlock::HeaderValue::ConsolidatedValue() const {
+ if (fragments_.empty()) {
+ return StringPiece();
+ }
+ if (fragments_.size() > 1) {
+ fragments_ = {
+ storage_->WriteFragments(fragments_, SeparatorForKey(pair_.first))};
+ }
+ return fragments_[0];
+}
+
+void SpdyHeaderBlock::HeaderValue::Append(StringPiece fragment) {
+ fragments_.push_back(fragment);
+}
+
+const std::pair<StringPiece, StringPiece>&
+SpdyHeaderBlock::HeaderValue::as_pair() const {
+ pair_.second = ConsolidatedValue();
+ return pair_;
+}
+
+SpdyHeaderBlock::iterator::iterator(MapType::const_iterator it) : it_(it) {}
+
+SpdyHeaderBlock::iterator::iterator(const iterator& other) : it_(other.it_) {}
+
+SpdyHeaderBlock::iterator::~iterator() {}
+
SpdyHeaderBlock::ValueProxy::ValueProxy(
SpdyHeaderBlock::MapType* block,
SpdyHeaderBlock::Storage* storage,
@@ -89,8 +149,7 @@ SpdyHeaderBlock::ValueProxy::ValueProxy(
storage_(storage),
lookup_result_(lookup_result),
key_(key),
- valid_(true) {
-}
+ valid_(true) {}
SpdyHeaderBlock::ValueProxy::ValueProxy(ValueProxy&& other)
: block_(other.block_),
@@ -127,10 +186,14 @@ SpdyHeaderBlock::ValueProxy& SpdyHeaderBlock::ValueProxy::operator=(
if (lookup_result_ == block_->end()) {
DVLOG(1) << "Inserting: (" << key_ << ", " << value << ")";
lookup_result_ =
- block_->insert(std::make_pair(key_, storage_->Write(value))).first;
+ block_
+ ->emplace(make_pair(
+ key_, HeaderValue(storage_, key_, storage_->Write(value))))
+ .first;
} else {
DVLOG(1) << "Updating key: " << key_ << " with value: " << value;
- lookup_result_->second = storage_->Write(value);
+ lookup_result_->second =
+ HeaderValue(storage_, key_, storage_->Write(value));
}
return *this;
}
@@ -139,7 +202,7 @@ string SpdyHeaderBlock::ValueProxy::as_string() const {
if (lookup_result_ == block_->end()) {
return "";
} else {
- return lookup_result_->second.as_string();
+ return lookup_result_->second.value().as_string();
}
}
@@ -160,8 +223,8 @@ SpdyHeaderBlock& SpdyHeaderBlock::operator=(SpdyHeaderBlock&& other) {
SpdyHeaderBlock SpdyHeaderBlock::Clone() const {
SpdyHeaderBlock copy;
- for (auto iter : *this) {
- copy.AppendHeader(iter.first, iter.second);
+ for (const auto& p : *this) {
+ copy.AppendHeader(p.first, p.second);
}
return copy;
}
@@ -181,7 +244,7 @@ string SpdyHeaderBlock::DebugString() const {
string output = "\n{\n";
for (auto it = begin(); it != end(); ++it) {
output +=
- " " + it->first.as_string() + ":" + it->second.as_string() + "\n";
+ " " + it->first.as_string() + " " + it->second.as_string() + "\n";
}
output.append("}\n");
return output;
@@ -192,8 +255,7 @@ void SpdyHeaderBlock::clear() {
storage_.reset();
}
-void SpdyHeaderBlock::insert(
- const SpdyHeaderBlock::MapType::value_type& value) {
+void SpdyHeaderBlock::insert(const SpdyHeaderBlock::value_type& value) {
// TODO(birenroy): Write new value in place of old value, if it fits.
auto iter = block_.find(value.first);
if (iter == block_.end()) {
@@ -202,7 +264,9 @@ void SpdyHeaderBlock::insert(
} else {
DVLOG(1) << "Updating key: " << iter->first
<< " with value: " << value.second;
- iter->second = GetStorage()->Write(value.second);
+ auto storage = GetStorage();
+ iter->second =
+ HeaderValue(storage, iter->first, storage->Write(value.second));
}
}
@@ -232,16 +296,15 @@ void SpdyHeaderBlock::AppendValueOrAddHeader(const StringPiece key,
return;
}
DVLOG(1) << "Updating key: " << iter->first << "; appending value: " << value;
- StringPiece separator("", 1);
- if (key == kCookieKey) {
- separator = "; ";
- }
- iter->second = GetStorage()->Realloc(iter->second, separator, value);
+ iter->second.Append(GetStorage()->Write(value));
}
void SpdyHeaderBlock::AppendHeader(const StringPiece key,
const StringPiece value) {
- block_.emplace(GetStorage()->Write(key), GetStorage()->Write(value));
+ auto storage = GetStorage();
+ auto backed_key = storage->Write(key);
+ block_.emplace(make_pair(
+ backed_key, HeaderValue(storage, backed_key, storage->Write(value))));
}
SpdyHeaderBlock::Storage* SpdyHeaderBlock::GetStorage() {
@@ -293,4 +356,31 @@ bool SpdyHeaderBlockFromNetLogParam(
return true;
}
+size_t SpdyHeaderBlock::bytes_allocated() const {
+ if (storage_ == nullptr) {
+ return 0;
+ } else {
+ return storage_->bytes_allocated();
+ }
+}
+
+size_t Join(char* dst,
+ const std::vector<StringPiece>& fragments,
+ StringPiece separator) {
+ if (fragments.empty()) {
+ return 0;
+ }
+ auto original_dst = dst;
+ auto it = fragments.begin();
+ memcpy(dst, it->data(), it->size());
+ dst += it->size();
+ for (++it; it != fragments.end(); ++it) {
+ memcpy(dst, separator.data(), separator.size());
+ dst += separator.size();
+ memcpy(dst, it->data(), it->size());
+ dst += it->size();
+ }
+ return dst - original_dst;
+}
+
} // namespace net
diff --git a/chromium/net/spdy/spdy_header_block.h b/chromium/net/spdy/spdy_header_block.h
index fef27e8f51a..fe8827f5c8d 100644
--- a/chromium/net/spdy/spdy_header_block.h
+++ b/chromium/net/spdy/spdy_header_block.h
@@ -11,6 +11,7 @@
#include <map>
#include <memory>
#include <string>
+#include <vector>
#include "base/macros.h"
#include "base/strings/string_piece.h"
@@ -27,6 +28,7 @@ namespace net {
class NetLogCaptureMode;
namespace test {
+class SpdyHeaderBlockPeer;
class ValueProxyPeer;
}
@@ -43,16 +45,93 @@ class ValueProxyPeer;
// It's expected that keys are rarely deleted from a SpdyHeaderBlock.
class NET_EXPORT SpdyHeaderBlock {
private:
- using MapType = linked_hash_map<base::StringPiece,
- base::StringPiece,
- base::StringPieceHash>;
class Storage;
+ // Stores a list of value fragments that can be joined later with a
+ // key-dependent separator.
+ class NET_EXPORT HeaderValue {
+ public:
+ HeaderValue(Storage* storage,
+ base::StringPiece key,
+ base::StringPiece initial_value);
+
+ // Moves are allowed.
+ HeaderValue(HeaderValue&& other);
+ HeaderValue& operator=(HeaderValue&& other);
+
+ // Copies are not.
+ HeaderValue(const HeaderValue& other) = delete;
+ HeaderValue& operator=(const HeaderValue& other) = delete;
+
+ ~HeaderValue();
+
+ // Consumes at most |fragment.size()| bytes of memory.
+ void Append(base::StringPiece fragment);
+
+ base::StringPiece value() const { return as_pair().second; }
+ const std::pair<base::StringPiece, base::StringPiece>& as_pair() const;
+
+ private:
+ // May allocate a large contiguous region of memory to hold the concatenated
+ // fragments and separators.
+ base::StringPiece ConsolidatedValue() const;
+
+ mutable Storage* storage_;
+ mutable std::vector<base::StringPiece> fragments_;
+ // The first element is the key; the second is the consolidated value.
+ mutable std::pair<base::StringPiece, base::StringPiece> pair_;
+ };
+
+ typedef linked_hash_map<base::StringPiece, HeaderValue, base::StringPieceHash>
+ MapType;
+
public:
- using iterator = MapType::iterator;
- using const_iterator = MapType::const_iterator;
- using value_type = MapType::value_type;
- using reverse_iterator = MapType::reverse_iterator;
+ typedef std::pair<base::StringPiece, base::StringPiece> value_type;
+
+ // Provides iteration over a sequence of std::pair<StringPiece, StringPiece>,
+ // even though the underlying MapType::value_type is different. Dereferencing
+ // the iterator will result in memory allocation for multi-value headers.
+ class NET_EXPORT iterator {
+ public:
+ // The following type definitions fulfill the requirements for iterator
+ // implementations.
+ typedef std::pair<base::StringPiece, base::StringPiece> value_type;
+ typedef value_type& reference;
+ typedef value_type* pointer;
+ typedef std::forward_iterator_tag iterator_category;
+ typedef MapType::iterator::difference_type difference_type;
+
+ // In practice, this iterator only offers access to const value_type.
+ typedef const value_type& const_reference;
+ typedef const value_type* const_pointer;
+
+ explicit iterator(MapType::const_iterator it);
+ iterator(const iterator& other);
+ ~iterator();
+
+ // This will result in memory allocation if the value consists of multiple
+ // fragments.
+ const_reference operator*() const { return it_->second.as_pair(); }
+
+ const_pointer operator->() const { return &(this->operator*()); }
+ bool operator==(const iterator& it) const { return it_ == it.it_; }
+ bool operator!=(const iterator& it) const { return !(*this == it); }
+
+ iterator& operator++() {
+ it_++;
+ return *this;
+ }
+
+ iterator operator++(int) {
+ auto ret = *this;
+ this->operator++();
+ return ret;
+ }
+
+ private:
+ MapType::const_iterator it_;
+ };
+ typedef iterator const_iterator;
class ValueProxy;
@@ -72,16 +151,16 @@ class NET_EXPORT SpdyHeaderBlock {
// keys and values.
std::string DebugString() const;
- // These methods delegate to our MapType member.
- iterator begin() { return block_.begin(); }
- iterator end() { return block_.end(); }
- const_iterator begin() const { return block_.begin(); }
- const_iterator end() const { return block_.end(); }
+ iterator begin() { return iterator(block_.begin()); }
+ iterator end() { return iterator(block_.end()); }
+ const_iterator begin() const { return const_iterator(block_.begin()); }
+ const_iterator end() const { return const_iterator(block_.end()); }
bool empty() const { return block_.empty(); }
size_t size() const { return block_.size(); }
- iterator find(base::StringPiece key) { return block_.find(key); }
- const_iterator find(base::StringPiece key) const { return block_.find(key); }
- reverse_iterator rbegin() { return block_.rbegin(); }
+ iterator find(base::StringPiece key) { return iterator(block_.find(key)); }
+ const_iterator find(base::StringPiece key) const {
+ return const_iterator(block_.find(key));
+ }
void erase(base::StringPiece key) { block_.erase(key); }
// Clears both our MapType member and the memory used to hold headers.
@@ -91,7 +170,7 @@ class NET_EXPORT SpdyHeaderBlock {
// If key already exists in the block, replaces the value of that key. Else
// adds a new header to the end of the block.
- void insert(const MapType::value_type& value);
+ void insert(const value_type& value);
// If a header with the key is already present, then append the value to the
// existing header value, NUL ("\0") separated unless the key is cookie, in
@@ -140,8 +219,11 @@ class NET_EXPORT SpdyHeaderBlock {
};
private:
+ friend class test::SpdyHeaderBlockPeer;
+
void AppendHeader(const base::StringPiece key, const base::StringPiece value);
Storage* GetStorage();
+ size_t bytes_allocated() const;
// StringPieces held by |block_| point to memory owned by |*storage_|.
// |storage_| might be nullptr as long as |block_| is empty.
@@ -149,6 +231,12 @@ class NET_EXPORT SpdyHeaderBlock {
std::unique_ptr<Storage> storage_;
};
+// Writes |fragments| to |dst|, joined by |separator|. |dst| must be large
+// enough to hold the result. Returns the number of bytes written.
+NET_EXPORT size_t Join(char* dst,
+ const std::vector<base::StringPiece>& fragments,
+ base::StringPiece separator);
+
// Converts a SpdyHeaderBlock into NetLog event parameters.
NET_EXPORT std::unique_ptr<base::Value> SpdyHeaderBlockNetLogCallback(
const SpdyHeaderBlock* headers,
diff --git a/chromium/net/spdy/spdy_header_block_test.cc b/chromium/net/spdy/spdy_header_block_test.cc
index 5f4429dbe35..c2c4a8f4fd8 100644
--- a/chromium/net/spdy/spdy_header_block_test.cc
+++ b/chromium/net/spdy/spdy_header_block_test.cc
@@ -13,8 +13,10 @@
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
+using base::StringPiece;
using std::make_pair;
using std::string;
+using std::vector;
using ::testing::ElementsAre;
namespace net {
@@ -22,13 +24,10 @@ namespace test {
class ValueProxyPeer {
public:
- static base::StringPiece key(SpdyHeaderBlock::ValueProxy* p) {
- return p->key_;
- }
+ static StringPiece key(SpdyHeaderBlock::ValueProxy* p) { return p->key_; }
};
-std::pair<base::StringPiece, base::StringPiece> Pair(base::StringPiece k,
- base::StringPiece v) {
+std::pair<StringPiece, StringPiece> Pair(StringPiece k, StringPiece v) {
return make_pair(k, v);
}
@@ -46,12 +45,12 @@ TEST(SpdyHeaderBlockTest, EmptyBlock) {
TEST(SpdyHeaderBlockTest, KeyMemoryReclaimedOnLookup) {
SpdyHeaderBlock block;
- base::StringPiece copied_key1;
+ StringPiece copied_key1;
{
auto proxy1 = block["some key name"];
copied_key1 = ValueProxyPeer::key(&proxy1);
}
- base::StringPiece copied_key2;
+ StringPiece copied_key2;
{
auto proxy2 = block["some other key name"];
copied_key2 = ValueProxyPeer::key(&proxy2);
@@ -187,12 +186,40 @@ TEST(SpdyHeaderBlockTest, AppendHeaders) {
block.AppendValueOrAddHeader("h1", "h1v3");
block.AppendValueOrAddHeader("h2", "h2v3");
block.AppendValueOrAddHeader("h3", "h3v3");
+ block.AppendValueOrAddHeader("h4", "singleton");
EXPECT_EQ("key1=value1; key2=value2; key3=value3", block["cookie"]);
EXPECT_EQ("baz", block["foo"]);
EXPECT_EQ(string("h1v1\0h1v2\0h1v3", 14), block["h1"]);
EXPECT_EQ(string("h2v1\0h2v2\0h2v3", 14), block["h2"]);
EXPECT_EQ(string("h3v2\0h3v3", 9), block["h3"]);
+ EXPECT_EQ("singleton", block["h4"]);
+}
+
+TEST(JoinTest, JoinEmpty) {
+ vector<StringPiece> empty;
+ StringPiece separator = ", ";
+ char buf[10] = "";
+ size_t written = Join(buf, empty, separator);
+ EXPECT_EQ(0u, written);
+}
+
+TEST(JoinTest, JoinOne) {
+ vector<StringPiece> v = {"one"};
+ StringPiece separator = ", ";
+ char buf[15];
+ size_t written = Join(buf, v, separator);
+ EXPECT_EQ(3u, written);
+ EXPECT_EQ("one", StringPiece(buf, written));
+}
+
+TEST(JoinTest, JoinMultiple) {
+ vector<StringPiece> v = {"one", "two", "three"};
+ StringPiece separator = ", ";
+ char buf[15];
+ size_t written = Join(buf, v, separator);
+ EXPECT_EQ(15u, written);
+ EXPECT_EQ("one, two, three", StringPiece(buf, written));
}
} // namespace test
diff --git a/chromium/net/spdy/spdy_header_indexing.cc b/chromium/net/spdy/spdy_header_indexing.cc
index 8b4a64de838..81b20442cb6 100644
--- a/chromium/net/spdy/spdy_header_indexing.cc
+++ b/chromium/net/spdy/spdy_header_indexing.cc
@@ -10,8 +10,8 @@ using base::StringPiece;
namespace net {
-int32_t FLAGS_gfe_spdy_indexing_set_bound = 300;
-int32_t FLAGS_gfe_spdy_tracking_set_bound = 2000;
+int32_t FLAGS_gfe_spdy_indexing_set_bound = 50;
+int32_t FLAGS_gfe_spdy_tracking_set_bound = 1000;
HeaderIndexing::HeaderIndexing()
: indexing_set_bound_(FLAGS_gfe_spdy_indexing_set_bound),
@@ -135,6 +135,7 @@ void HeaderIndexing::CreateInitIndexingHeaders() {
}
bool HeaderIndexing::ShouldIndex(StringPiece header, StringPiece /* value */) {
+ total_header_count_++;
if (header.empty()) {
return false;
}
@@ -147,9 +148,11 @@ bool HeaderIndexing::ShouldIndex(StringPiece header, StringPiece /* value */) {
if (tracking_set_.find(header_str) != tracking_set_.end()) {
// Seen this header before. Add it to indexing set.
TryInsertHeader(std::move(header_str), &indexing_set_, indexing_set_bound_);
+ missed_header_in_tracking_++;
} else {
// Add header to tracking set.
TryInsertHeader(std::move(header_str), &tracking_set_, tracking_set_bound_);
+ missed_header_in_indexing_++;
}
return false;
}
diff --git a/chromium/net/spdy/spdy_header_indexing.h b/chromium/net/spdy/spdy_header_indexing.h
index 09507b9253d..9dd4bc5a190 100644
--- a/chromium/net/spdy/spdy_header_indexing.h
+++ b/chromium/net/spdy/spdy_header_indexing.h
@@ -5,6 +5,7 @@
#ifndef NET_SPDY_SPDY_HEADER_INDEXING_H_
#define NET_SPDY_SPDY_HEADER_INDEXING_H_
+#include <stdint.h>
#include <memory>
#include <string>
#include <unordered_set>
@@ -41,11 +42,14 @@ class NET_EXPORT HeaderIndexing {
// Not to make the indexing decision but to update sets.
void UpdateSets(base::StringPiece header, base::StringPiece value) {
+ update_only_header_count_++;
ShouldIndex(header, value);
}
- // TODO(yasong): Add function to log statistic info. For example, cache hit
- // and miss rate.
+ int64_t total_header_count() { return total_header_count_; }
+ int64_t update_only_header_count() { return update_only_header_count_; }
+ int64_t missed_headers_in_indexing() { return missed_header_in_indexing_; }
+ int64_t missed_headers_in_tracking() { return missed_header_in_tracking_; }
private:
friend class test::HeaderIndexingPeer;
@@ -56,6 +60,10 @@ class NET_EXPORT HeaderIndexing {
HeaderSet tracking_set_;
const size_t indexing_set_bound_;
const size_t tracking_set_bound_;
+ int64_t total_header_count_ = 0;
+ int64_t update_only_header_count_ = 0;
+ int64_t missed_header_in_indexing_ = 0;
+ int64_t missed_header_in_tracking_ = 0;
};
} // namespace net
diff --git a/chromium/net/spdy/spdy_headers_block_parser.cc b/chromium/net/spdy/spdy_headers_block_parser.cc
index 6eb16fbe438..5e6bc6f59e7 100644
--- a/chromium/net/spdy/spdy_headers_block_parser.cc
+++ b/chromium/net/spdy/spdy_headers_block_parser.cc
@@ -23,7 +23,6 @@ const size_t kLengthFieldSize = sizeof(uint32_t);
const size_t SpdyHeadersBlockParser::kMaximumFieldLength = 16 * 1024;
SpdyHeadersBlockParser::SpdyHeadersBlockParser(
- SpdyMajorVersion spdy_version,
SpdyHeadersHandlerInterface* handler)
: state_(READING_HEADER_BLOCK_LEN),
max_headers_in_block_(MaxNumberOfHeaders()),
@@ -31,8 +30,7 @@ SpdyHeadersBlockParser::SpdyHeadersBlockParser(
remaining_key_value_pairs_for_frame_(0),
handler_(handler),
stream_id_(kInvalidStreamId),
- error_(NO_PARSER_ERROR),
- spdy_version_(spdy_version) {
+ error_(NO_PARSER_ERROR) {
// The handler that we set must not be NULL.
DCHECK(handler_ != NULL);
}
diff --git a/chromium/net/spdy/spdy_headers_block_parser.h b/chromium/net/spdy/spdy_headers_block_parser.h
index 8e2db8b4ca4..1ad7ddf9e1d 100644
--- a/chromium/net/spdy/spdy_headers_block_parser.h
+++ b/chromium/net/spdy/spdy_headers_block_parser.h
@@ -19,12 +19,6 @@
namespace net {
-namespace test {
-
-class SpdyHeadersBlockParserPeer;
-
-} // namespace test
-
// This class handles SPDY headers block bytes and parses out key-value pairs
// as they arrive. This class is not thread-safe, and assumes that all headers
// block bytes are processed in a single thread.
@@ -35,8 +29,7 @@ class NET_EXPORT_PRIVATE SpdyHeadersBlockParser {
// Constructor. The handler's OnHeader will be called for every key
// value pair that we parsed from the headers block.
- SpdyHeadersBlockParser(SpdyMajorVersion spdy_version,
- SpdyHeadersHandlerInterface* handler);
+ explicit SpdyHeadersBlockParser(SpdyHeadersHandlerInterface* handler);
virtual ~SpdyHeadersBlockParser();
@@ -63,8 +56,6 @@ class NET_EXPORT_PRIVATE SpdyHeadersBlockParser {
};
ParserError get_error() const { return error_; }
- SpdyMajorVersion spdy_version() const { return spdy_version_; }
-
// Returns the maximal number of headers in a SPDY headers block.
static size_t MaxNumberOfHeaders();
@@ -119,8 +110,6 @@ class NET_EXPORT_PRIVATE SpdyHeadersBlockParser {
SpdyStreamId stream_id_;
ParserError error_;
-
- const SpdyMajorVersion spdy_version_;
};
} // namespace net
diff --git a/chromium/net/spdy/spdy_headers_block_parser_test.cc b/chromium/net/spdy/spdy_headers_block_parser_test.cc
index ad603539033..00f8fc43fa5 100644
--- a/chromium/net/spdy/spdy_headers_block_parser_test.cc
+++ b/chromium/net/spdy/spdy_headers_block_parser_test.cc
@@ -6,6 +6,7 @@
#include <memory>
#include <string>
+#include <vector>
#include "base/strings/string_number_conversions.h"
#include "base/sys_byteorder.h"
@@ -34,17 +35,14 @@ class MockSpdyHeadersHandler : public SpdyHeadersHandlerInterface {
MOCK_METHOD2(OnHeader, void(StringPiece key, StringPiece value));
};
-class SpdyHeadersBlockParserTest :
- public ::testing::TestWithParam<SpdyMajorVersion> {
+class SpdyHeadersBlockParserTest : public ::testing::Test {
public:
~SpdyHeadersBlockParserTest() override {}
protected:
void SetUp() override {
// Create a parser using the mock handler.
- spdy_version_ = GetParam();
-
- parser_.reset(new SpdyHeadersBlockParser(spdy_version_, &handler_));
+ parser_.reset(new SpdyHeadersBlockParser(&handler_));
}
// Create a header block with a specified number of headers.
@@ -88,8 +86,6 @@ class SpdyHeadersBlockParserTest :
return string(buffer, sizeof(uint32_t));
}
- SpdyMajorVersion spdy_version_;
-
MockSpdyHeadersHandler handler_;
std::unique_ptr<SpdyHeadersBlockParser> parser_;
@@ -104,16 +100,10 @@ class SpdyHeadersBlockParserTest :
const char *const SpdyHeadersBlockParserTest::kBaseKey = "test_key";
const char *const SpdyHeadersBlockParserTest::kBaseValue = "test_value";
-// All tests are run with SPDY/3 and HTTP/2.
-INSTANTIATE_TEST_CASE_P(SpdyHeadersBlockParserTests,
- SpdyHeadersBlockParserTest,
- ::testing::Values(SPDY3, HTTP2));
-
-TEST_P(SpdyHeadersBlockParserTest, BasicTest) {
+TEST_F(SpdyHeadersBlockParserTest, BasicTest) {
// Sanity test, verify that we parse out correctly a block with
// a single key-value pair and that we notify when we start and finish
// handling a headers block.
- EXPECT_EQ(spdy_version_, parser_->spdy_version());
EXPECT_CALL(handler_, OnHeaderBlockStart()).Times(1);
string expect_key = kBaseKey + IntToString(0);
@@ -132,7 +122,7 @@ TEST_P(SpdyHeadersBlockParserTest, BasicTest) {
EXPECT_EQ(SpdyHeadersBlockParser::NO_PARSER_ERROR, parser_->get_error());
}
-TEST_P(SpdyHeadersBlockParserTest, NullsSupportedTest) {
+TEST_F(SpdyHeadersBlockParserTest, NullsSupportedTest) {
// Sanity test, verify that we parse out correctly a block with
// a single key-value pair when the key and value contain null charecters.
EXPECT_CALL(handler_, OnHeaderBlockStart()).Times(1);
@@ -154,7 +144,7 @@ TEST_P(SpdyHeadersBlockParserTest, NullsSupportedTest) {
EXPECT_EQ(SpdyHeadersBlockParser::NO_PARSER_ERROR, parser_->get_error());
}
-TEST_P(SpdyHeadersBlockParserTest, MultipleBlocksAndHeadersWithPartialData) {
+TEST_F(SpdyHeadersBlockParserTest, MultipleBlocksAndHeadersWithPartialData) {
testing::InSequence s;
// CreateHeaders is deterministic; we can call it once for the whole test.
@@ -196,7 +186,7 @@ TEST_P(SpdyHeadersBlockParserTest, MultipleBlocksAndHeadersWithPartialData) {
}
}
-TEST_P(SpdyHeadersBlockParserTest, HandlesEmptyCallsTest) {
+TEST_F(SpdyHeadersBlockParserTest, HandlesEmptyCallsTest) {
EXPECT_CALL(handler_, OnHeaderBlockStart()).Times(1);
string expect_key = kBaseKey + IntToString(0);
@@ -225,7 +215,7 @@ TEST_P(SpdyHeadersBlockParserTest, HandlesEmptyCallsTest) {
}
}
-TEST_P(SpdyHeadersBlockParserTest, LargeBlocksDiscardedTest) {
+TEST_F(SpdyHeadersBlockParserTest, LargeBlocksDiscardedTest) {
// Header block with too many headers.
{
string headers = EncodeLength(parser_->MaxNumberOfHeaders() + 1);
@@ -234,7 +224,7 @@ TEST_P(SpdyHeadersBlockParserTest, LargeBlocksDiscardedTest) {
EXPECT_EQ(SpdyHeadersBlockParser::HEADER_BLOCK_TOO_LARGE,
parser_->get_error());
}
- parser_.reset(new SpdyHeadersBlockParser(spdy_version_, &handler_));
+ parser_.reset(new SpdyHeadersBlockParser(&handler_));
// Header block with one header, which has a too-long key.
{
string headers = EncodeLength(1) + EncodeLength(
@@ -246,7 +236,7 @@ TEST_P(SpdyHeadersBlockParserTest, LargeBlocksDiscardedTest) {
}
}
-TEST_P(SpdyHeadersBlockParserTest, ExtraDataTest) {
+TEST_F(SpdyHeadersBlockParserTest, ExtraDataTest) {
EXPECT_CALL(handler_, OnHeaderBlockStart()).Times(1);
string expect_key = kBaseKey + IntToString(0);
@@ -266,7 +256,7 @@ TEST_P(SpdyHeadersBlockParserTest, ExtraDataTest) {
EXPECT_EQ(SpdyHeadersBlockParser::TOO_MUCH_DATA, parser_->get_error());
}
-TEST_P(SpdyHeadersBlockParserTest, WrongStreamIdTest) {
+TEST_F(SpdyHeadersBlockParserTest, WrongStreamIdTest) {
string headers(CreateHeaders(kNumHeadersInBlock, false));
EXPECT_FALSE(parser_->HandleControlFrameHeadersData(1, headers.data(), 1));
EXPECT_EQ(SpdyHeadersBlockParser::NEED_MORE_DATA, parser_->get_error());
@@ -278,7 +268,7 @@ TEST_P(SpdyHeadersBlockParserTest, WrongStreamIdTest) {
EXPECT_EQ(SpdyHeadersBlockParser::UNEXPECTED_STREAM_ID, parser_->get_error());
}
-TEST_P(SpdyHeadersBlockParserTest, InvalidStreamIdTest) {
+TEST_F(SpdyHeadersBlockParserTest, InvalidStreamIdTest) {
string headers(CreateHeaders(kNumHeadersInBlock, false));
bool result;
EXPECT_SPDY_BUG(
diff --git a/chromium/net/spdy/spdy_http_stream.cc b/chromium/net/spdy/spdy_http_stream.cc
index c7ab1025464..ac30d4160fc 100644
--- a/chromium/net/spdy/spdy_http_stream.cc
+++ b/chromium/net/spdy/spdy_http_stream.cc
@@ -13,7 +13,6 @@
#include "base/location.h"
#include "base/logging.h"
#include "base/single_thread_task_runner.h"
-#include "base/strings/stringprintf.h"
#include "base/threading/thread_task_runner_handle.h"
#include "base/values.h"
#include "net/base/host_port_pair.h"
@@ -34,7 +33,8 @@ const size_t SpdyHttpStream::kRequestBodyBufferSize = 1 << 14; // 16KB
SpdyHttpStream::SpdyHttpStream(const base::WeakPtr<SpdySession>& spdy_session,
bool direct)
- : spdy_session_(spdy_session),
+ : MultiplexedHttpStream(MultiplexedSessionHandle(spdy_session)),
+ spdy_session_(spdy_session),
is_reused_(spdy_session_->IsReused()),
stream_closed_(false),
closed_stream_status_(ERR_FAILED),
@@ -43,7 +43,7 @@ SpdyHttpStream::SpdyHttpStream(const base::WeakPtr<SpdySession>& spdy_session,
closed_stream_sent_bytes_(0),
request_info_(NULL),
response_info_(NULL),
- response_headers_status_(RESPONSE_HEADERS_ARE_INCOMPLETE),
+ response_headers_complete_(false),
user_buffer_len_(0),
request_body_buf_size_(0),
buffered_read_callback_pending_(false),
@@ -71,8 +71,8 @@ int SpdyHttpStream::InitializeStream(const HttpRequestInfo* request_info,
request_info_ = request_info;
if (request_info_->method == "GET") {
- int error = spdy_session_->GetPushStream(request_info_->url, &stream_,
- stream_net_log);
+ int error = spdy_session_->GetPushStream(request_info_->url, priority,
+ &stream_, stream_net_log);
if (error != OK)
return error;
@@ -106,7 +106,7 @@ int SpdyHttpStream::ReadResponseHeaders(const CompletionCallback& callback) {
CHECK(stream_.get());
// Check if we already have the response headers. If so, return synchronously.
- if (response_headers_status_ == RESPONSE_HEADERS_ARE_COMPLETE) {
+ if (response_headers_complete_) {
CHECK(!stream_->IsIdle());
return OK;
}
@@ -158,10 +158,6 @@ void SpdyHttpStream::Close(bool not_reusable) {
DCHECK(!stream_.get());
}
-HttpStream* SpdyHttpStream::RenewStreamForAuth() {
- return NULL;
-}
-
bool SpdyHttpStream::IsResponseBodyComplete() const {
return stream_closed_;
}
@@ -170,15 +166,6 @@ bool SpdyHttpStream::IsConnectionReused() const {
return is_reused_;
}
-void SpdyHttpStream::SetConnectionReused() {
- // SPDY doesn't need an indicator here.
-}
-
-bool SpdyHttpStream::CanReuseConnection() const {
- // SPDY streams aren't considered reusable.
- return false;
-}
-
int64_t SpdyHttpStream::GetTotalReceivedBytes() const {
if (stream_closed_)
return closed_stream_received_bytes_;
@@ -302,7 +289,7 @@ void SpdyHttpStream::Cancel() {
}
}
-void SpdyHttpStream::OnRequestHeadersSent() {
+void SpdyHttpStream::OnHeadersSent() {
if (HasUploadData()) {
ReadAndSendRequestBodyData();
} else {
@@ -310,9 +297,10 @@ void SpdyHttpStream::OnRequestHeadersSent() {
}
}
-SpdyResponseHeadersStatus SpdyHttpStream::OnResponseHeadersUpdated(
+void SpdyHttpStream::OnHeadersReceived(
const SpdyHeaderBlock& response_headers) {
- CHECK_EQ(response_headers_status_, RESPONSE_HEADERS_ARE_INCOMPLETE);
+ DCHECK(!response_headers_complete_);
+ response_headers_complete_ = true;
if (!response_info_) {
DCHECK_EQ(stream_->type(), SPDY_PUSH_STREAM);
@@ -320,13 +308,11 @@ SpdyResponseHeadersStatus SpdyHttpStream::OnResponseHeadersUpdated(
response_info_ = push_response_info_.get();
}
- if (!SpdyHeadersToHttpResponse(response_headers, response_info_)) {
- // We do not have complete headers yet.
- return RESPONSE_HEADERS_ARE_INCOMPLETE;
- }
+ const bool headers_valid =
+ SpdyHeadersToHttpResponse(response_headers, response_info_);
+ DCHECK(headers_valid);
response_info_->response_time = stream_->response_time();
- response_headers_status_ = RESPONSE_HEADERS_ARE_COMPLETE;
// Don't store the SSLInfo in the response here, HttpNetworkTransaction
// will take care of that part.
response_info_->was_alpn_negotiated = was_alpn_negotiated_;
@@ -340,12 +326,10 @@ SpdyResponseHeadersStatus SpdyHttpStream::OnResponseHeadersUpdated(
if (!response_callback_.is_null()) {
DoResponseCallback(OK);
}
-
- return RESPONSE_HEADERS_ARE_COMPLETE;
}
void SpdyHttpStream::OnDataReceived(std::unique_ptr<SpdyBuffer> buffer) {
- CHECK_EQ(response_headers_status_, RESPONSE_HEADERS_ARE_COMPLETE);
+ DCHECK(response_headers_complete_);
// Note that data may be received for a SpdyStream prior to the user calling
// ReadResponseBody(), therefore user_buffer_ may be NULL. This may often
@@ -447,8 +431,7 @@ void SpdyHttpStream::ReadAndSendRequestBodyData() {
void SpdyHttpStream::InitializeStreamHelper() {
stream_->SetDelegate(this);
- stream_->GetSSLInfo(&ssl_info_);
- was_alpn_negotiated_ = stream_->WasNpnNegotiated();
+ was_alpn_negotiated_ = stream_->WasAlpnNegotiated();
}
void SpdyHttpStream::ResetStreamInternal() {
@@ -578,17 +561,6 @@ void SpdyHttpStream::DoResponseCallback(int rv) {
base::ResetAndReturn(&response_callback_).Run(rv);
}
-void SpdyHttpStream::GetSSLInfo(SSLInfo* ssl_info) {
- *ssl_info = ssl_info_;
-}
-
-void SpdyHttpStream::GetSSLCertRequestInfo(
- SSLCertRequestInfo* cert_request_info) {
- // A SPDY stream cannot request client certificates. Client authentication may
- // only occur during the initial SSL handshake.
- NOTREACHED();
-}
-
bool SpdyHttpStream::GetRemoteEndpoint(IPEndPoint* endpoint) {
if (!spdy_session_)
return false;
@@ -596,21 +568,6 @@ bool SpdyHttpStream::GetRemoteEndpoint(IPEndPoint* endpoint) {
return spdy_session_->GetPeerAddress(endpoint) == OK;
}
-Error SpdyHttpStream::GetTokenBindingSignature(crypto::ECPrivateKey* key,
- TokenBindingType tb_type,
- std::vector<uint8_t>* out) {
- if (stream_closed_)
- return ERR_CONNECTION_CLOSED;
-
- return spdy_session_->GetTokenBindingSignature(key, tb_type, out);
-}
-
-void SpdyHttpStream::Drain(HttpNetworkSession* session) {
- NOTREACHED();
- Close(false);
- delete this;
-}
-
void SpdyHttpStream::PopulateNetErrorDetails(NetErrorDetails* details) {
details->connection_info = HttpResponseInfo::CONNECTION_INFO_HTTP2;
return;
diff --git a/chromium/net/spdy/spdy_http_stream.h b/chromium/net/spdy/spdy_http_stream.h
index bcd2fbccfb0..0796e1a6905 100644
--- a/chromium/net/spdy/spdy_http_stream.h
+++ b/chromium/net/spdy/spdy_http_stream.h
@@ -14,14 +14,13 @@
#include "base/memory/weak_ptr.h"
#include "net/base/completion_callback.h"
#include "net/base/net_export.h"
-#include "net/http/http_stream.h"
+#include "net/spdy/multiplexed_http_stream.h"
#include "net/spdy/spdy_read_queue.h"
#include "net/spdy/spdy_session.h"
#include "net/spdy/spdy_stream.h"
namespace net {
-class DrainableIOBuffer;
struct HttpRequestInfo;
class HttpResponseInfo;
class IOBuffer;
@@ -30,7 +29,7 @@ class UploadDataStream;
// The SpdyHttpStream is a HTTP-specific type of stream known to a SpdySession.
class NET_EXPORT_PRIVATE SpdyHttpStream : public SpdyStream::Delegate,
- public HttpStream {
+ public MultiplexedHttpStream {
public:
static const size_t kRequestBodyBufferSize;
// |spdy_session| must not be NULL.
@@ -57,15 +56,12 @@ class NET_EXPORT_PRIVATE SpdyHttpStream : public SpdyStream::Delegate,
int buf_len,
const CompletionCallback& callback) override;
void Close(bool not_reusable) override;
- HttpStream* RenewStreamForAuth() override;
bool IsResponseBodyComplete() const override;
// Must not be called if a NULL SpdySession was pssed into the
// constructor.
bool IsConnectionReused() const override;
- void SetConnectionReused() override;
- bool CanReuseConnection() const override;
// Total number of bytes received over the network of SPDY data, headers, and
// push_promise frames associated with this stream, including the size of
// frame headers, after SSL decryption and not including proxy overhead.
@@ -76,20 +72,13 @@ class NET_EXPORT_PRIVATE SpdyHttpStream : public SpdyStream::Delegate,
// not associated with any stream, and are not included in this value.
int64_t GetTotalSentBytes() const override;
bool GetLoadTimingInfo(LoadTimingInfo* load_timing_info) const override;
- void GetSSLInfo(SSLInfo* ssl_info) override;
- void GetSSLCertRequestInfo(SSLCertRequestInfo* cert_request_info) override;
bool GetRemoteEndpoint(IPEndPoint* endpoint) override;
- Error GetTokenBindingSignature(crypto::ECPrivateKey* key,
- TokenBindingType tb_type,
- std::vector<uint8_t>* out) override;
- void Drain(HttpNetworkSession* session) override;
void PopulateNetErrorDetails(NetErrorDetails* details) override;
void SetPriority(RequestPriority priority) override;
// SpdyStream::Delegate implementation.
- void OnRequestHeadersSent() override;
- SpdyResponseHeadersStatus OnResponseHeadersUpdated(
- const SpdyHeaderBlock& response_headers) override;
+ void OnHeadersSent() override;
+ void OnHeadersReceived(const SpdyHeaderBlock& response_headers) override;
void OnDataReceived(std::unique_ptr<SpdyBuffer> buffer) override;
void OnDataSent() override;
void OnTrailers(const SpdyHeaderBlock& trailers) override;
@@ -168,9 +157,7 @@ class NET_EXPORT_PRIVATE SpdyHttpStream : public SpdyStream::Delegate,
std::unique_ptr<HttpResponseInfo> push_response_info_;
- // We don't use SpdyStream's |response_header_status_| as we
- // sometimes call back into our delegate before it is updated.
- SpdyResponseHeadersStatus response_headers_status_;
+ bool response_headers_complete_;
// We buffer the response body as it arrives asynchronously from the stream.
SpdyReadQueue response_body_queue_;
@@ -195,7 +182,6 @@ class NET_EXPORT_PRIVATE SpdyHttpStream : public SpdyStream::Delegate,
// Is this spdy stream direct to the origin server (or to a proxy).
bool direct_;
- SSLInfo ssl_info_;
bool was_alpn_negotiated_;
base::WeakPtrFactory<SpdyHttpStream> weak_factory_;
diff --git a/chromium/net/spdy/spdy_http_stream_unittest.cc b/chromium/net/spdy/spdy_http_stream_unittest.cc
index aca52c6bd58..812db8d347e 100644
--- a/chromium/net/spdy/spdy_http_stream_unittest.cc
+++ b/chromium/net/spdy/spdy_http_stream_unittest.cc
@@ -10,6 +10,7 @@
#include "base/run_loop.h"
#include "base/stl_util.h"
+#include "base/threading/thread_task_runner_handle.h"
#include "crypto/ec_private_key.h"
#include "crypto/ec_signature_creator.h"
#include "crypto/signature_creator.h"
@@ -35,11 +36,10 @@
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
-using net::test::IsError;
-using net::test::IsOk;
-
namespace net {
+namespace test {
+
namespace {
// Tests the load timing of a stream that's connected and is not the first
@@ -126,11 +126,11 @@ class CancelStreamCallback : public TestCompletionCallbackBase {
class SpdyHttpStreamTest : public testing::Test {
public:
SpdyHttpStreamTest()
- : host_port_pair_(HostPortPair::FromURL(GURL(kDefaultUrl))),
+ : url_(kDefaultUrl),
+ host_port_pair_(HostPortPair::FromURL(url_)),
key_(host_port_pair_, ProxyServer::Direct(), PRIVACY_MODE_DISABLED),
ssl_(SYNCHRONOUS, OK) {
session_deps_.net_log = &net_log_;
- spdy_util_.set_default_url(GURL("http://www.example.org/"));
}
~SpdyHttpStreamTest() override {}
@@ -169,6 +169,7 @@ class SpdyHttpStreamTest : public testing::Test {
SpdyTestUtil spdy_util_;
TestNetLog net_log_;
SpdySessionDependencies session_deps_;
+ const GURL url_;
const HostPortPair host_port_pair_;
const SpdySessionKey key_;
std::unique_ptr<SequencedSocketData> sequenced_data_;
@@ -195,7 +196,7 @@ TEST_F(SpdyHttpStreamTest, SendRequest) {
HttpRequestInfo request;
request.method = "GET";
- request.url = GURL("http://www.example.org/");
+ request.url = url_;
TestCompletionCallback callback;
HttpResponseInfo response;
HttpRequestHeaders headers;
@@ -206,14 +207,13 @@ TEST_F(SpdyHttpStreamTest, SendRequest) {
LoadTimingInfo load_timing_info;
EXPECT_FALSE(http_stream->GetLoadTimingInfo(&load_timing_info));
- ASSERT_EQ(
- OK,
- http_stream->InitializeStream(&request, DEFAULT_PRIORITY,
- net_log, CompletionCallback()));
+ ASSERT_THAT(http_stream->InitializeStream(&request, DEFAULT_PRIORITY, net_log,
+ CompletionCallback()),
+ IsOk());
EXPECT_FALSE(http_stream->GetLoadTimingInfo(&load_timing_info));
- EXPECT_EQ(ERR_IO_PENDING, http_stream->SendRequest(headers, &response,
- callback.callback()));
+ EXPECT_THAT(http_stream->SendRequest(headers, &response, callback.callback()),
+ IsError(ERR_IO_PENDING));
EXPECT_TRUE(HasSpdySession(http_session_->spdy_session_pool(), key_));
EXPECT_FALSE(http_stream->GetLoadTimingInfo(&load_timing_info));
@@ -259,7 +259,7 @@ TEST_F(SpdyHttpStreamTest, LoadTimingTwoRequests) {
HttpRequestInfo request1;
request1.method = "GET";
- request1.url = GURL("http://www.example.org/");
+ request1.url = url_;
TestCompletionCallback callback1;
HttpResponseInfo response1;
HttpRequestHeaders headers1;
@@ -268,7 +268,7 @@ TEST_F(SpdyHttpStreamTest, LoadTimingTwoRequests) {
HttpRequestInfo request2;
request2.method = "GET";
- request2.url = GURL("http://www.example.org/");
+ request2.url = url_;
TestCompletionCallback callback2;
HttpResponseInfo response2;
HttpRequestHeaders headers2;
@@ -276,11 +276,13 @@ TEST_F(SpdyHttpStreamTest, LoadTimingTwoRequests) {
new SpdyHttpStream(session_, true));
// First write.
- ASSERT_EQ(OK, http_stream1->InitializeStream(&request1, DEFAULT_PRIORITY,
- NetLogWithSource(),
- CompletionCallback()));
- EXPECT_EQ(ERR_IO_PENDING, http_stream1->SendRequest(headers1, &response1,
- callback1.callback()));
+ ASSERT_THAT(
+ http_stream1->InitializeStream(&request1, DEFAULT_PRIORITY,
+ NetLogWithSource(), CompletionCallback()),
+ IsOk());
+ EXPECT_THAT(
+ http_stream1->SendRequest(headers1, &response1, callback1.callback()),
+ IsError(ERR_IO_PENDING));
EXPECT_TRUE(HasSpdySession(http_session_->spdy_session_pool(), key_));
EXPECT_LE(0, callback1.WaitForResult());
@@ -292,14 +294,20 @@ TEST_F(SpdyHttpStreamTest, LoadTimingTwoRequests) {
EXPECT_FALSE(http_stream2->GetLoadTimingInfo(&load_timing_info2));
// Second write.
- ASSERT_EQ(OK, http_stream2->InitializeStream(&request2, DEFAULT_PRIORITY,
- NetLogWithSource(),
- CompletionCallback()));
- EXPECT_EQ(ERR_IO_PENDING, http_stream2->SendRequest(headers2, &response2,
- callback2.callback()));
+ ASSERT_THAT(
+ http_stream2->InitializeStream(&request2, DEFAULT_PRIORITY,
+ NetLogWithSource(), CompletionCallback()),
+ IsOk());
+ EXPECT_THAT(
+ http_stream2->SendRequest(headers2, &response2, callback2.callback()),
+ IsError(ERR_IO_PENDING));
EXPECT_TRUE(HasSpdySession(http_session_->spdy_session_pool(), key_));
EXPECT_LE(0, callback2.WaitForResult());
+
+ // Perform all async reads.
+ base::RunLoop().RunUntilIdle();
+
TestLoadTimingReused(*http_stream2);
EXPECT_TRUE(http_stream2->GetLoadTimingInfo(&load_timing_info2));
EXPECT_EQ(load_timing_info1.socket_log_id, load_timing_info2.socket_log_id);
@@ -339,7 +347,7 @@ TEST_F(SpdyHttpStreamTest, SendChunkedPost) {
SpdySerializedFrame resp(spdy_util_.ConstructSpdyPostReply(nullptr, 0));
MockRead reads[] = {
- CreateMockRead(resp, 2), CreateMockRead(body, 3),
+ CreateMockRead(resp, 2), CreateMockRead(body, 3, SYNCHRONOUS),
MockRead(SYNCHRONOUS, 0, 4) // EOF
};
@@ -353,7 +361,7 @@ TEST_F(SpdyHttpStreamTest, SendChunkedPost) {
HttpRequestInfo request;
request.method = "POST";
- request.url = GURL("http://www.example.org/");
+ request.url = url_;
request.upload_data_stream = &upload_stream;
ASSERT_THAT(upload_stream.Init(TestCompletionCallback().callback(),
@@ -365,13 +373,12 @@ TEST_F(SpdyHttpStreamTest, SendChunkedPost) {
HttpRequestHeaders headers;
NetLogWithSource net_log;
SpdyHttpStream http_stream(session_, true);
- ASSERT_EQ(
- OK,
- http_stream.InitializeStream(&request, DEFAULT_PRIORITY,
- net_log, CompletionCallback()));
+ ASSERT_THAT(http_stream.InitializeStream(&request, DEFAULT_PRIORITY, net_log,
+ CompletionCallback()),
+ IsOk());
- EXPECT_EQ(ERR_IO_PENDING, http_stream.SendRequest(
- headers, &response, callback.callback()));
+ EXPECT_THAT(http_stream.SendRequest(headers, &response, callback.callback()),
+ IsError(ERR_IO_PENDING));
EXPECT_TRUE(HasSpdySession(http_session_->spdy_session_pool(), key_));
EXPECT_THAT(callback.WaitForResult(), IsOk());
@@ -398,7 +405,7 @@ TEST_F(SpdyHttpStreamTest, SendChunkedPostLastEmpty) {
SpdySerializedFrame resp(spdy_util_.ConstructSpdyPostReply(nullptr, 0));
MockRead reads[] = {
- CreateMockRead(resp, 2), CreateMockRead(chunk, 3),
+ CreateMockRead(resp, 2), CreateMockRead(chunk, 3, SYNCHRONOUS),
MockRead(SYNCHRONOUS, 0, 4) // EOF
};
@@ -409,7 +416,7 @@ TEST_F(SpdyHttpStreamTest, SendChunkedPostLastEmpty) {
HttpRequestInfo request;
request.method = "POST";
- request.url = GURL("http://www.example.org/");
+ request.url = url_;
request.upload_data_stream = &upload_stream;
ASSERT_THAT(upload_stream.Init(TestCompletionCallback().callback(),
@@ -421,10 +428,11 @@ TEST_F(SpdyHttpStreamTest, SendChunkedPostLastEmpty) {
HttpRequestHeaders headers;
NetLogWithSource net_log;
SpdyHttpStream http_stream(session_, true);
- ASSERT_EQ(OK, http_stream.InitializeStream(&request, DEFAULT_PRIORITY,
- net_log, CompletionCallback()));
- EXPECT_EQ(ERR_IO_PENDING,
- http_stream.SendRequest(headers, &response, callback.callback()));
+ ASSERT_THAT(http_stream.InitializeStream(&request, DEFAULT_PRIORITY, net_log,
+ CompletionCallback()),
+ IsOk());
+ EXPECT_THAT(http_stream.SendRequest(headers, &response, callback.callback()),
+ IsError(ERR_IO_PENDING));
EXPECT_TRUE(HasSpdySession(http_session_->spdy_session_pool(), key_));
EXPECT_THAT(callback.WaitForResult(), IsOk());
@@ -462,7 +470,7 @@ TEST_F(SpdyHttpStreamTest, ConnectionClosedDuringChunkedPost) {
HttpRequestInfo request;
request.method = "POST";
- request.url = GURL("http://www.example.org/");
+ request.url = url_;
request.upload_data_stream = &upload_stream;
ASSERT_THAT(upload_stream.Init(TestCompletionCallback().callback(),
@@ -474,11 +482,12 @@ TEST_F(SpdyHttpStreamTest, ConnectionClosedDuringChunkedPost) {
HttpRequestHeaders headers;
NetLogWithSource net_log;
SpdyHttpStream http_stream(session_, true);
- ASSERT_EQ(OK, http_stream.InitializeStream(&request, DEFAULT_PRIORITY,
- net_log, CompletionCallback()));
+ ASSERT_THAT(http_stream.InitializeStream(&request, DEFAULT_PRIORITY, net_log,
+ CompletionCallback()),
+ IsOk());
- EXPECT_EQ(ERR_IO_PENDING,
- http_stream.SendRequest(headers, &response, callback.callback()));
+ EXPECT_THAT(http_stream.SendRequest(headers, &response, callback.callback()),
+ IsError(ERR_IO_PENDING));
EXPECT_TRUE(HasSpdySession(http_session_->spdy_session_pool(), key_));
EXPECT_THAT(callback.WaitForResult(), IsError(ERR_CONNECTION_CLOSED));
@@ -531,7 +540,7 @@ TEST_F(SpdyHttpStreamTest, DelayedSendChunkedPost) {
HttpRequestInfo request;
request.method = "POST";
- request.url = GURL("http://www.example.org/");
+ request.url = url_;
request.upload_data_stream = &upload_stream;
ASSERT_THAT(upload_stream.Init(TestCompletionCallback().callback(),
@@ -542,16 +551,17 @@ TEST_F(SpdyHttpStreamTest, DelayedSendChunkedPost) {
NetLogWithSource net_log;
std::unique_ptr<SpdyHttpStream> http_stream(
new SpdyHttpStream(session_, true));
- ASSERT_EQ(OK, http_stream->InitializeStream(&request, DEFAULT_PRIORITY,
- net_log, CompletionCallback()));
+ ASSERT_THAT(http_stream->InitializeStream(&request, DEFAULT_PRIORITY, net_log,
+ CompletionCallback()),
+ IsOk());
TestCompletionCallback callback;
HttpRequestHeaders headers;
HttpResponseInfo response;
// This will attempt to Write() the initial request and headers, which will
// complete asynchronously.
- EXPECT_EQ(ERR_IO_PENDING, http_stream->SendRequest(headers, &response,
- callback.callback()));
+ EXPECT_THAT(http_stream->SendRequest(headers, &response, callback.callback()),
+ IsError(ERR_IO_PENDING));
EXPECT_TRUE(HasSpdySession(http_session_->spdy_session_pool(), key_));
// Complete the initial request write and the first chunk.
@@ -625,7 +635,7 @@ TEST_F(SpdyHttpStreamTest, DelayedSendChunkedPostWithEmptyFinalDataFrame) {
HttpRequestInfo request;
request.method = "POST";
- request.url = GURL("http://www.example.org/");
+ request.url = url_;
request.upload_data_stream = &upload_stream;
ASSERT_THAT(upload_stream.Init(TestCompletionCallback().callback(),
@@ -636,16 +646,17 @@ TEST_F(SpdyHttpStreamTest, DelayedSendChunkedPostWithEmptyFinalDataFrame) {
NetLogWithSource net_log;
std::unique_ptr<SpdyHttpStream> http_stream(
new SpdyHttpStream(session_, true));
- ASSERT_EQ(OK, http_stream->InitializeStream(&request, DEFAULT_PRIORITY,
- net_log, CompletionCallback()));
+ ASSERT_THAT(http_stream->InitializeStream(&request, DEFAULT_PRIORITY, net_log,
+ CompletionCallback()),
+ IsOk());
TestCompletionCallback callback;
HttpRequestHeaders headers;
HttpResponseInfo response;
// This will attempt to Write() the initial request and headers, which will
// complete asynchronously.
- EXPECT_EQ(ERR_IO_PENDING, http_stream->SendRequest(headers, &response,
- callback.callback()));
+ EXPECT_THAT(http_stream->SendRequest(headers, &response, callback.callback()),
+ IsError(ERR_IO_PENDING));
EXPECT_TRUE(HasSpdySession(http_session_->spdy_session_pool(), key_));
// Complete the initial request write and the first chunk.
@@ -708,7 +719,7 @@ TEST_F(SpdyHttpStreamTest, ChunkedPostWithEmptyPayload) {
HttpRequestInfo request;
request.method = "POST";
- request.url = GURL("http://www.example.org/");
+ request.url = url_;
request.upload_data_stream = &upload_stream;
ASSERT_THAT(upload_stream.Init(TestCompletionCallback().callback(),
@@ -719,16 +730,17 @@ TEST_F(SpdyHttpStreamTest, ChunkedPostWithEmptyPayload) {
NetLogWithSource net_log;
std::unique_ptr<SpdyHttpStream> http_stream(
new SpdyHttpStream(session_, true));
- ASSERT_EQ(OK, http_stream->InitializeStream(&request, DEFAULT_PRIORITY,
- net_log, CompletionCallback()));
+ ASSERT_THAT(http_stream->InitializeStream(&request, DEFAULT_PRIORITY, net_log,
+ CompletionCallback()),
+ IsOk());
TestCompletionCallback callback;
HttpRequestHeaders headers;
HttpResponseInfo response;
// This will attempt to Write() the initial request and headers, which will
// complete asynchronously.
- EXPECT_EQ(ERR_IO_PENDING, http_stream->SendRequest(headers, &response,
- callback.callback()));
+ EXPECT_THAT(http_stream->SendRequest(headers, &response, callback.callback()),
+ IsError(ERR_IO_PENDING));
EXPECT_TRUE(HasSpdySession(http_session_->spdy_session_pool(), key_));
// Complete writing request, followed by a FIN.
@@ -754,10 +766,10 @@ TEST_F(SpdyHttpStreamTest, ChunkedPostWithEmptyPayload) {
ASSERT_EQ(200, response.headers->response_code());
}
-// Test case for bug: http://code.google.com/p/chromium/issues/detail?id=50058
+// Test case for https://crbug.com/50058.
TEST_F(SpdyHttpStreamTest, SpdyURLTest) {
- const char* const full_url = "http://www.example.org/foo?query=what#anchor";
- const char* const base_url = "http://www.example.org/foo?query=what";
+ const char* const full_url = "https://www.example.org/foo?query=what#anchor";
+ const char* const base_url = "https://www.example.org/foo?query=what";
SpdySerializedFrame req(spdy_util_.ConstructSpdyGet(base_url, 1, LOWEST));
MockWrite writes[] = {
CreateMockWrite(req, 0),
@@ -778,12 +790,12 @@ TEST_F(SpdyHttpStreamTest, SpdyURLTest) {
NetLogWithSource net_log;
std::unique_ptr<SpdyHttpStream> http_stream(
new SpdyHttpStream(session_, true));
- ASSERT_EQ(OK,
- http_stream->InitializeStream(
- &request, DEFAULT_PRIORITY, net_log, CompletionCallback()));
+ ASSERT_THAT(http_stream->InitializeStream(&request, DEFAULT_PRIORITY, net_log,
+ CompletionCallback()),
+ IsOk());
- EXPECT_EQ(ERR_IO_PENDING, http_stream->SendRequest(headers, &response,
- callback.callback()));
+ EXPECT_THAT(http_stream->SendRequest(headers, &response, callback.callback()),
+ IsError(ERR_IO_PENDING));
EXPECT_EQ(base_url, http_stream->stream()->GetUrlFromHeaders().spec());
@@ -821,7 +833,7 @@ TEST_F(SpdyHttpStreamTest, DelayedSendChunkedPostWithWindowUpdate) {
HttpRequestInfo request;
request.method = "POST";
- request.url = GURL("http://www.example.org/");
+ request.url = url_;
request.upload_data_stream = &upload_stream;
ASSERT_THAT(upload_stream.Init(TestCompletionCallback().callback(),
@@ -831,16 +843,17 @@ TEST_F(SpdyHttpStreamTest, DelayedSendChunkedPostWithWindowUpdate) {
NetLogWithSource net_log;
std::unique_ptr<SpdyHttpStream> http_stream(
new SpdyHttpStream(session_, true));
- ASSERT_EQ(OK, http_stream->InitializeStream(&request, DEFAULT_PRIORITY,
- net_log, CompletionCallback()));
+ ASSERT_THAT(http_stream->InitializeStream(&request, DEFAULT_PRIORITY, net_log,
+ CompletionCallback()),
+ IsOk());
HttpRequestHeaders headers;
HttpResponseInfo response;
// This will attempt to Write() the initial request and headers, which will
// complete asynchronously.
TestCompletionCallback callback;
- EXPECT_EQ(ERR_IO_PENDING, http_stream->SendRequest(headers, &response,
- callback.callback()));
+ EXPECT_THAT(http_stream->SendRequest(headers, &response, callback.callback()),
+ IsError(ERR_IO_PENDING));
EXPECT_TRUE(HasSpdySession(http_session_->spdy_session_pool(), key_));
// Complete the initial request write and first chunk.
@@ -926,7 +939,7 @@ TEST_F(SpdyHttpStreamTest, DataReadErrorSynchronous) {
HttpRequestInfo request;
request.method = "POST";
- request.url = GURL("http://www.example.org/");
+ request.url = url_;
request.upload_data_stream = &upload_data_stream;
TestCompletionCallback callback;
@@ -934,12 +947,16 @@ TEST_F(SpdyHttpStreamTest, DataReadErrorSynchronous) {
HttpRequestHeaders headers;
NetLogWithSource net_log;
SpdyHttpStream http_stream(session_, true);
- ASSERT_EQ(OK, http_stream.InitializeStream(&request, DEFAULT_PRIORITY,
- net_log, CompletionCallback()));
+ ASSERT_THAT(http_stream.InitializeStream(&request, DEFAULT_PRIORITY, net_log,
+ CompletionCallback()),
+ IsOk());
int result = http_stream.SendRequest(headers, &response, callback.callback());
EXPECT_THAT(callback.GetResult(result), IsError(ERR_FAILED));
+ // Run posted SpdyHttpStream::ResetStreamInternal() task.
+ base::RunLoop().RunUntilIdle();
+
// Because the server has not closed the connection yet, there shouldn't be
// a stream but a session in the pool
EXPECT_FALSE(HasSpdySession(http_session_->spdy_session_pool(), key_));
@@ -975,7 +992,7 @@ TEST_F(SpdyHttpStreamTest, DataReadErrorAsynchronous) {
HttpRequestInfo request;
request.method = "POST";
- request.url = GURL("http://www.example.org/");
+ request.url = url_;
request.upload_data_stream = &upload_data_stream;
TestCompletionCallback callback;
@@ -983,13 +1000,17 @@ TEST_F(SpdyHttpStreamTest, DataReadErrorAsynchronous) {
HttpRequestHeaders headers;
NetLogWithSource net_log;
SpdyHttpStream http_stream(session_, true);
- ASSERT_EQ(OK, http_stream.InitializeStream(&request, DEFAULT_PRIORITY,
- net_log, CompletionCallback()));
+ ASSERT_THAT(http_stream.InitializeStream(&request, DEFAULT_PRIORITY, net_log,
+ CompletionCallback()),
+ IsOk());
int result = http_stream.SendRequest(headers, &response, callback.callback());
EXPECT_THAT(result, IsError(ERR_IO_PENDING));
EXPECT_THAT(callback.GetResult(result), IsError(ERR_FAILED));
+ // Run posted SpdyHttpStream::ResetStreamInternal() task.
+ base::RunLoop().RunUntilIdle();
+
// Because the server has closed the connection, there shouldn't be a session
// in the pool anymore.
EXPECT_FALSE(HasSpdySession(http_session_->spdy_session_pool(), key_));
@@ -1009,7 +1030,7 @@ TEST_F(SpdyHttpStreamTest, RequestCallbackCancelsStream) {
HttpRequestInfo request;
request.method = "POST";
- request.url = GURL("http://www.example.org/");
+ request.url = url_;
ChunkedUploadDataStream upload_stream(0);
request.upload_data_stream = &upload_stream;
@@ -1030,17 +1051,22 @@ TEST_F(SpdyHttpStreamTest, RequestCallbackCancelsStream) {
HttpResponseInfo response;
// This will attempt to Write() the initial request and headers, which will
// complete asynchronously.
- EXPECT_EQ(ERR_IO_PENDING,
- http_stream.SendRequest(headers, &response, callback.callback()));
+ EXPECT_THAT(http_stream.SendRequest(headers, &response, callback.callback()),
+ IsError(ERR_IO_PENDING));
EXPECT_TRUE(HasSpdySession(http_session_->spdy_session_pool(), key_));
// The callback cancels |http_stream|.
EXPECT_THAT(callback.WaitForResult(), IsOk());
+ // Finish async network reads/writes.
+ base::RunLoop().RunUntilIdle();
+
EXPECT_FALSE(HasSpdySession(http_session_->spdy_session_pool(), key_));
}
// TODO(willchan): Write a longer test for SpdyStream that exercises all
// methods.
+} // namespace test
+
} // namespace net
diff --git a/chromium/net/spdy/spdy_http_utils.cc b/chromium/net/spdy/spdy_http_utils.cc
index f285e8430e1..e1cb9ef99db 100644
--- a/chromium/net/spdy/spdy_http_utils.cc
+++ b/chromium/net/spdy/spdy_http_utils.cc
@@ -108,25 +108,6 @@ void CreateSpdyHeadersFromHttpRequest(const HttpRequestInfo& info,
}
}
-void CreateSpdyHeadersFromHttpResponse(
- const HttpResponseHeaders& response_headers,
- SpdyHeaderBlock* headers) {
- const std::string status_line = response_headers.GetStatusLine();
- std::string::const_iterator after_version =
- std::find(status_line.begin(), status_line.end(), ' ');
- // Get status code only.
- std::string::const_iterator after_status =
- std::find(after_version + 1, status_line.end(), ' ');
- (*headers)[":status"] = std::string(after_version + 1, after_status);
-
- size_t iter = 0;
- std::string raw_name, value;
- while (response_headers.EnumerateHeaderLines(&iter, &raw_name, &value)) {
- std::string name = base::ToLowerASCII(raw_name);
- AddSpdyHeader(name, value, headers);
- }
-}
-
static_assert(HIGHEST - LOWEST < 4 && HIGHEST - MINIMUM_PRIORITY < 6,
"request priority incompatible with spdy");
diff --git a/chromium/net/spdy/spdy_http_utils.h b/chromium/net/spdy/spdy_http_utils.h
index 6989ad5e41e..7181323bebc 100644
--- a/chromium/net/spdy/spdy_http_utils.h
+++ b/chromium/net/spdy/spdy_http_utils.h
@@ -17,7 +17,6 @@ namespace net {
class HttpResponseInfo;
struct HttpRequestInfo;
class HttpRequestHeaders;
-class HttpResponseHeaders;
// Convert a SpdyHeaderBlock into an HttpResponseInfo.
// |headers| input parameter with the SpdyHeaderBlock.
@@ -35,11 +34,6 @@ NET_EXPORT void CreateSpdyHeadersFromHttpRequest(
bool direct,
SpdyHeaderBlock* headers);
-// Create a SpdyHeaderBlock from HttpResponseHeaders.
-NET_EXPORT void CreateSpdyHeadersFromHttpResponse(
- const HttpResponseHeaders& response_headers,
- SpdyHeaderBlock* headers);
-
// Create HttpRequestHeaders from SpdyHeaderBlock.
NET_EXPORT void ConvertHeaderBlockToHttpRequestHeaders(
const SpdyHeaderBlock& spdy_headers,
diff --git a/chromium/net/spdy/spdy_network_transaction_unittest.cc b/chromium/net/spdy/spdy_network_transaction_unittest.cc
index f9a8aa6d4fd..8e14b22ba7e 100644
--- a/chromium/net/spdy/spdy_network_transaction_unittest.cc
+++ b/chromium/net/spdy/spdy_network_transaction_unittest.cc
@@ -26,6 +26,7 @@
#include "net/base/upload_bytes_element_reader.h"
#include "net/base/upload_file_element_reader.h"
#include "net/http/http_auth_scheme.h"
+#include "net/http/http_network_session.h"
#include "net/http/http_network_session_peer.h"
#include "net/http/http_network_transaction.h"
#include "net/http/http_server_properties.h"
@@ -106,7 +107,7 @@ class SpdyNetworkTransactionTest : public ::testing::Test {
std::unique_ptr<SpdySessionDependencies> session_deps)
: request_(request),
priority_(priority),
- session_deps_(session_deps.get() == NULL
+ session_deps_(session_deps.get() == nullptr
? base::MakeUnique<SpdySessionDependencies>()
: std::move(session_deps)),
session_(
@@ -147,6 +148,8 @@ class SpdyNetworkTransactionTest : public ::testing::Test {
void FinishDefaultTest() {
output_.rv = callback_.WaitForResult();
+ // Finish async network reads/writes.
+ base::RunLoop().RunUntilIdle();
if (output_.rv != OK) {
session_->spdy_session_pool()->CloseCurrentSessions(ERR_ABORTED);
return;
@@ -170,6 +173,8 @@ class SpdyNetworkTransactionTest : public ::testing::Test {
void FinishDefaultTestWithoutVerification() {
output_.rv = callback_.WaitForResult();
+ // Finish async network reads/writes.
+ base::RunLoop().RunUntilIdle();
if (output_.rv != OK)
session_->spdy_session_pool()->CloseCurrentSessions(ERR_ABORTED);
}
@@ -440,7 +445,7 @@ class SpdyNetworkTransactionTest : public ::testing::Test {
HttpResponseInfo* push_response,
const std::string& expected) {
NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
- NetLogWithSource(), NULL);
+ NetLogWithSource(), nullptr);
helper.RunPreTestSetup();
helper.AddData(data);
@@ -453,6 +458,9 @@ class SpdyNetworkTransactionTest : public ::testing::Test {
EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
rv = callback.WaitForResult();
+ // Finish async network reads/writes.
+ base::RunLoop().RunUntilIdle();
+
// Request the pushed path.
HttpNetworkTransaction trans2(DEFAULT_PRIORITY, helper.session());
rv = trans2.Start(&CreateGetPushRequest(), callback.callback(),
@@ -506,9 +514,9 @@ class SpdyNetworkTransactionTest : public ::testing::Test {
static void StartTransactionCallback(HttpNetworkSession* session,
GURL url,
int result) {
+ HttpRequestInfo request;
HttpNetworkTransaction trans(DEFAULT_PRIORITY, session);
TestCompletionCallback callback;
- HttpRequestInfo request;
request.method = "GET";
request.url = url;
request.load_flags = 0;
@@ -557,7 +565,7 @@ TEST_F(SpdyNetworkTransactionTest, Get) {
spdy_util_.ConstructSpdyGet(nullptr, 0, 1, LOWEST, true));
MockWrite writes[] = {CreateMockWrite(req, 0)};
- SpdySerializedFrame resp(spdy_util_.ConstructSpdyGetReply(NULL, 0, 1));
+ SpdySerializedFrame resp(spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
SpdySerializedFrame body(spdy_util_.ConstructSpdyDataFrame(1, true));
MockRead reads[] = {
CreateMockRead(resp, 1), CreateMockRead(body, 2),
@@ -566,7 +574,7 @@ TEST_F(SpdyNetworkTransactionTest, Get) {
SequencedSocketData data(reads, arraysize(reads), writes, arraysize(writes));
NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
- NetLogWithSource(), NULL);
+ NetLogWithSource(), nullptr);
helper.RunToCompletion(&data);
TransactionHelperResult out = helper.output();
EXPECT_THAT(out.rv, IsOk());
@@ -624,7 +632,8 @@ TEST_F(SpdyNetworkTransactionTest, GetAtEachPriority) {
arraysize(writes));
HttpRequestInfo http_req = CreateGetRequest();
- NormalSpdyTransactionHelper helper(http_req, p, NetLogWithSource(), NULL);
+ NormalSpdyTransactionHelper helper(http_req, p, NetLogWithSource(),
+ nullptr);
helper.RunToCompletion(&data);
TransactionHelperResult out = helper.output();
EXPECT_THAT(out.rv, IsOk());
@@ -646,19 +655,19 @@ TEST_F(SpdyNetworkTransactionTest, GetAtEachPriority) {
TEST_F(SpdyNetworkTransactionTest, ThreeGets) {
SpdySerializedFrame req(
spdy_util_.ConstructSpdyGet(nullptr, 0, 1, LOWEST, true));
- SpdySerializedFrame resp(spdy_util_.ConstructSpdyGetReply(NULL, 0, 1));
+ SpdySerializedFrame resp(spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
SpdySerializedFrame body(spdy_util_.ConstructSpdyDataFrame(1, false));
SpdySerializedFrame fbody(spdy_util_.ConstructSpdyDataFrame(1, true));
SpdySerializedFrame req2(
spdy_util_.ConstructSpdyGet(nullptr, 0, 3, LOWEST, true));
- SpdySerializedFrame resp2(spdy_util_.ConstructSpdyGetReply(NULL, 0, 3));
+ SpdySerializedFrame resp2(spdy_util_.ConstructSpdyGetReply(nullptr, 0, 3));
SpdySerializedFrame body2(spdy_util_.ConstructSpdyDataFrame(3, false));
SpdySerializedFrame fbody2(spdy_util_.ConstructSpdyDataFrame(3, true));
SpdySerializedFrame req3(
spdy_util_.ConstructSpdyGet(nullptr, 0, 5, LOWEST, true));
- SpdySerializedFrame resp3(spdy_util_.ConstructSpdyGetReply(NULL, 0, 5));
+ SpdySerializedFrame resp3(spdy_util_.ConstructSpdyGetReply(nullptr, 0, 5));
SpdySerializedFrame body3(spdy_util_.ConstructSpdyDataFrame(5, false));
SpdySerializedFrame fbody3(spdy_util_.ConstructSpdyDataFrame(5, true));
@@ -677,13 +686,13 @@ TEST_F(SpdyNetworkTransactionTest, ThreeGets) {
MockRead(ASYNC, 0, 12), // EOF
};
SequencedSocketData data(reads, arraysize(reads), writes, arraysize(writes));
- SequencedSocketData data_placeholder1(NULL, 0, NULL, 0);
- SequencedSocketData data_placeholder2(NULL, 0, NULL, 0);
+ SequencedSocketData data_placeholder1(nullptr, 0, nullptr, 0);
+ SequencedSocketData data_placeholder2(nullptr, 0, nullptr, 0);
NetLogWithSource log;
TransactionHelperResult out;
NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
- NetLogWithSource(), NULL);
+ NetLogWithSource(), nullptr);
helper.RunPreTestSetup();
helper.AddData(&data);
// We require placeholder data because three get requests are sent out at
@@ -691,10 +700,6 @@ TEST_F(SpdyNetworkTransactionTest, ThreeGets) {
// on will negotiate SPDY and will be used for all requests.
helper.AddData(&data_placeholder1);
helper.AddData(&data_placeholder2);
- HttpNetworkTransaction trans1(DEFAULT_PRIORITY, helper.session());
- HttpNetworkTransaction trans2(DEFAULT_PRIORITY, helper.session());
- HttpNetworkTransaction trans3(DEFAULT_PRIORITY, helper.session());
-
TestCompletionCallback callback1;
TestCompletionCallback callback2;
TestCompletionCallback callback3;
@@ -703,6 +708,10 @@ TEST_F(SpdyNetworkTransactionTest, ThreeGets) {
HttpRequestInfo httpreq2 = CreateGetRequest();
HttpRequestInfo httpreq3 = CreateGetRequest();
+ HttpNetworkTransaction trans1(DEFAULT_PRIORITY, helper.session());
+ HttpNetworkTransaction trans2(DEFAULT_PRIORITY, helper.session());
+ HttpNetworkTransaction trans3(DEFAULT_PRIORITY, helper.session());
+
out.rv = trans1.Start(&httpreq1, callback1.callback(), log);
ASSERT_THAT(out.rv, IsError(ERR_IO_PENDING));
out.rv = trans2.Start(&httpreq2, callback2.callback(), log);
@@ -735,13 +744,13 @@ TEST_F(SpdyNetworkTransactionTest, ThreeGets) {
TEST_F(SpdyNetworkTransactionTest, TwoGetsLateBinding) {
SpdySerializedFrame req(
spdy_util_.ConstructSpdyGet(nullptr, 0, 1, LOWEST, true));
- SpdySerializedFrame resp(spdy_util_.ConstructSpdyGetReply(NULL, 0, 1));
+ SpdySerializedFrame resp(spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
SpdySerializedFrame body(spdy_util_.ConstructSpdyDataFrame(1, false));
SpdySerializedFrame fbody(spdy_util_.ConstructSpdyDataFrame(1, true));
SpdySerializedFrame req2(
spdy_util_.ConstructSpdyGet(nullptr, 0, 3, LOWEST, true));
- SpdySerializedFrame resp2(spdy_util_.ConstructSpdyGetReply(NULL, 0, 3));
+ SpdySerializedFrame resp2(spdy_util_.ConstructSpdyGetReply(nullptr, 0, 3));
SpdySerializedFrame body2(spdy_util_.ConstructSpdyDataFrame(3, false));
SpdySerializedFrame fbody2(spdy_util_.ConstructSpdyDataFrame(3, true));
@@ -757,13 +766,13 @@ TEST_F(SpdyNetworkTransactionTest, TwoGetsLateBinding) {
SequencedSocketData data(reads, arraysize(reads), writes, arraysize(writes));
MockConnect never_finishing_connect(SYNCHRONOUS, ERR_IO_PENDING);
- SequencedSocketData data_placeholder(NULL, 0, NULL, 0);
+ SequencedSocketData data_placeholder(nullptr, 0, nullptr, 0);
data_placeholder.set_connect_data(never_finishing_connect);
NetLogWithSource log;
TransactionHelperResult out;
NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
- NetLogWithSource(), NULL);
+ NetLogWithSource(), nullptr);
helper.RunPreTestSetup();
helper.AddData(&data);
// We require placeholder data because two requests are sent out at
@@ -815,13 +824,13 @@ TEST_F(SpdyNetworkTransactionTest, TwoGetsLateBinding) {
TEST_F(SpdyNetworkTransactionTest, TwoGetsLateBindingFromPreconnect) {
SpdySerializedFrame req(
spdy_util_.ConstructSpdyGet(nullptr, 0, 1, LOWEST, true));
- SpdySerializedFrame resp(spdy_util_.ConstructSpdyGetReply(NULL, 0, 1));
+ SpdySerializedFrame resp(spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
SpdySerializedFrame body(spdy_util_.ConstructSpdyDataFrame(1, false));
SpdySerializedFrame fbody(spdy_util_.ConstructSpdyDataFrame(1, true));
SpdySerializedFrame req2(
spdy_util_.ConstructSpdyGet(nullptr, 0, 3, LOWEST, true));
- SpdySerializedFrame resp2(spdy_util_.ConstructSpdyGetReply(NULL, 0, 3));
+ SpdySerializedFrame resp2(spdy_util_.ConstructSpdyGetReply(nullptr, 0, 3));
SpdySerializedFrame body2(spdy_util_.ConstructSpdyDataFrame(3, false));
SpdySerializedFrame fbody2(spdy_util_.ConstructSpdyDataFrame(3, true));
@@ -839,13 +848,13 @@ TEST_F(SpdyNetworkTransactionTest, TwoGetsLateBindingFromPreconnect) {
MockConnect never_finishing_connect(ASYNC, ERR_IO_PENDING);
- SequencedSocketData data_placeholder(NULL, 0, NULL, 0);
+ SequencedSocketData data_placeholder(nullptr, 0, nullptr, 0);
data_placeholder.set_connect_data(never_finishing_connect);
NetLogWithSource log;
TransactionHelperResult out;
NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
- NetLogWithSource(), NULL);
+ NetLogWithSource(), nullptr);
helper.RunPreTestSetup();
helper.AddData(&preconnect_data);
// We require placeholder data because 3 connections are attempted (first is
@@ -910,28 +919,27 @@ TEST_F(SpdyNetworkTransactionTest, ThreeGetsWithMaxConcurrent) {
// Each request fully completes before the next starts.
SpdySerializedFrame req(
spdy_util_.ConstructSpdyGet(nullptr, 0, 1, LOWEST, true));
- SpdySerializedFrame resp(spdy_util_.ConstructSpdyGetReply(NULL, 0, 1));
+ SpdySerializedFrame resp(spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
SpdySerializedFrame body(spdy_util_.ConstructSpdyDataFrame(1, false));
SpdySerializedFrame fbody(spdy_util_.ConstructSpdyDataFrame(1, true));
spdy_util_.UpdateWithStreamDestruction(1);
SpdySerializedFrame req2(
spdy_util_.ConstructSpdyGet(nullptr, 0, 3, LOWEST, true));
- SpdySerializedFrame resp2(spdy_util_.ConstructSpdyGetReply(NULL, 0, 3));
+ SpdySerializedFrame resp2(spdy_util_.ConstructSpdyGetReply(nullptr, 0, 3));
SpdySerializedFrame body2(spdy_util_.ConstructSpdyDataFrame(3, false));
SpdySerializedFrame fbody2(spdy_util_.ConstructSpdyDataFrame(3, true));
spdy_util_.UpdateWithStreamDestruction(3);
SpdySerializedFrame req3(
spdy_util_.ConstructSpdyGet(nullptr, 0, 5, LOWEST, true));
- SpdySerializedFrame resp3(spdy_util_.ConstructSpdyGetReply(NULL, 0, 5));
+ SpdySerializedFrame resp3(spdy_util_.ConstructSpdyGetReply(nullptr, 0, 5));
SpdySerializedFrame body3(spdy_util_.ConstructSpdyDataFrame(5, false));
SpdySerializedFrame fbody3(spdy_util_.ConstructSpdyDataFrame(5, true));
SettingsMap settings;
const uint32_t max_concurrent_streams = 1;
- settings[SETTINGS_MAX_CONCURRENT_STREAMS] =
- SettingsFlagsAndValue(SETTINGS_FLAG_NONE, max_concurrent_streams);
+ settings[SETTINGS_MAX_CONCURRENT_STREAMS] = max_concurrent_streams;
SpdySerializedFrame settings_frame(
spdy_util_.ConstructSpdySettings(settings));
SpdySerializedFrame settings_ack(spdy_util_.ConstructSpdySettingsAck());
@@ -962,7 +970,7 @@ TEST_F(SpdyNetworkTransactionTest, ThreeGetsWithMaxConcurrent) {
TransactionHelperResult out;
{
NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
- NetLogWithSource(), NULL);
+ NetLogWithSource(), nullptr);
helper.RunPreTestSetup();
helper.AddData(&data);
HttpNetworkTransaction trans1(DEFAULT_PRIORITY, helper.session());
@@ -1035,34 +1043,33 @@ TEST_F(SpdyNetworkTransactionTest, FourGetsWithMaxConcurrentPriority) {
// Construct the request.
SpdySerializedFrame req(
spdy_util_.ConstructSpdyGet(nullptr, 0, 1, LOWEST, true));
- SpdySerializedFrame resp(spdy_util_.ConstructSpdyGetReply(NULL, 0, 1));
+ SpdySerializedFrame resp(spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
SpdySerializedFrame body(spdy_util_.ConstructSpdyDataFrame(1, false));
SpdySerializedFrame fbody(spdy_util_.ConstructSpdyDataFrame(1, true));
spdy_util_.UpdateWithStreamDestruction(1);
SpdySerializedFrame req2(
spdy_util_.ConstructSpdyGet(nullptr, 0, 3, LOWEST, true));
- SpdySerializedFrame resp2(spdy_util_.ConstructSpdyGetReply(NULL, 0, 3));
+ SpdySerializedFrame resp2(spdy_util_.ConstructSpdyGetReply(nullptr, 0, 3));
SpdySerializedFrame body2(spdy_util_.ConstructSpdyDataFrame(3, false));
SpdySerializedFrame fbody2(spdy_util_.ConstructSpdyDataFrame(3, true));
spdy_util_.UpdateWithStreamDestruction(3);
SpdySerializedFrame req4(
spdy_util_.ConstructSpdyGet(nullptr, 0, 5, HIGHEST, true));
- SpdySerializedFrame resp4(spdy_util_.ConstructSpdyGetReply(NULL, 0, 5));
+ SpdySerializedFrame resp4(spdy_util_.ConstructSpdyGetReply(nullptr, 0, 5));
SpdySerializedFrame fbody4(spdy_util_.ConstructSpdyDataFrame(5, true));
spdy_util_.UpdateWithStreamDestruction(5);
SpdySerializedFrame req3(
spdy_util_.ConstructSpdyGet(nullptr, 0, 7, LOWEST, true));
- SpdySerializedFrame resp3(spdy_util_.ConstructSpdyGetReply(NULL, 0, 7));
+ SpdySerializedFrame resp3(spdy_util_.ConstructSpdyGetReply(nullptr, 0, 7));
SpdySerializedFrame body3(spdy_util_.ConstructSpdyDataFrame(7, false));
SpdySerializedFrame fbody3(spdy_util_.ConstructSpdyDataFrame(7, true));
SettingsMap settings;
const uint32_t max_concurrent_streams = 1;
- settings[SETTINGS_MAX_CONCURRENT_STREAMS] =
- SettingsFlagsAndValue(SETTINGS_FLAG_NONE, max_concurrent_streams);
+ settings[SETTINGS_MAX_CONCURRENT_STREAMS] = max_concurrent_streams;
SpdySerializedFrame settings_frame(
spdy_util_.ConstructSpdySettings(settings));
SpdySerializedFrame settings_ack(spdy_util_.ConstructSpdySettingsAck());
@@ -1095,7 +1102,7 @@ TEST_F(SpdyNetworkTransactionTest, FourGetsWithMaxConcurrentPriority) {
NetLogWithSource log;
TransactionHelperResult out;
NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
- NetLogWithSource(), NULL);
+ NetLogWithSource(), nullptr);
helper.RunPreTestSetup();
helper.AddData(&data);
@@ -1120,6 +1127,9 @@ TEST_F(SpdyNetworkTransactionTest, FourGetsWithMaxConcurrentPriority) {
out.rv = callback1.WaitForResult();
ASSERT_THAT(out.rv, IsOk());
+ // Finish async network reads and writes associated with |trans1|.
+ base::RunLoop().RunUntilIdle();
+
out.rv = trans2.Start(&httpreq2, callback2.callback(), log);
ASSERT_THAT(out.rv, IsError(ERR_IO_PENDING));
out.rv = trans3.Start(&httpreq3, callback3.callback(), log);
@@ -1182,21 +1192,20 @@ TEST_F(SpdyNetworkTransactionTest, ThreeGetsWithMaxConcurrentDelete) {
// Construct the request.
SpdySerializedFrame req(
spdy_util_.ConstructSpdyGet(nullptr, 0, 1, LOWEST, true));
- SpdySerializedFrame resp(spdy_util_.ConstructSpdyGetReply(NULL, 0, 1));
+ SpdySerializedFrame resp(spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
SpdySerializedFrame body(spdy_util_.ConstructSpdyDataFrame(1, false));
SpdySerializedFrame fbody(spdy_util_.ConstructSpdyDataFrame(1, true));
spdy_util_.UpdateWithStreamDestruction(1);
SpdySerializedFrame req2(
spdy_util_.ConstructSpdyGet(nullptr, 0, 3, LOWEST, true));
- SpdySerializedFrame resp2(spdy_util_.ConstructSpdyGetReply(NULL, 0, 3));
+ SpdySerializedFrame resp2(spdy_util_.ConstructSpdyGetReply(nullptr, 0, 3));
SpdySerializedFrame body2(spdy_util_.ConstructSpdyDataFrame(3, false));
SpdySerializedFrame fbody2(spdy_util_.ConstructSpdyDataFrame(3, true));
SettingsMap settings;
const uint32_t max_concurrent_streams = 1;
- settings[SETTINGS_MAX_CONCURRENT_STREAMS] =
- SettingsFlagsAndValue(SETTINGS_FLAG_NONE, max_concurrent_streams);
+ settings[SETTINGS_MAX_CONCURRENT_STREAMS] = max_concurrent_streams;
SpdySerializedFrame settings_frame(
spdy_util_.ConstructSpdySettings(settings));
SpdySerializedFrame settings_ack(spdy_util_.ConstructSpdySettingsAck());
@@ -1217,7 +1226,7 @@ TEST_F(SpdyNetworkTransactionTest, ThreeGetsWithMaxConcurrentDelete) {
NetLogWithSource log;
TransactionHelperResult out;
NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
- NetLogWithSource(), NULL);
+ NetLogWithSource(), nullptr);
helper.RunPreTestSetup();
helper.AddData(&data);
std::unique_ptr<HttpNetworkTransaction> trans1(
@@ -1309,19 +1318,18 @@ TEST_F(SpdyNetworkTransactionTest, ThreeGetsWithMaxConcurrentSocketClose) {
// Construct the request.
SpdySerializedFrame req(
spdy_util_.ConstructSpdyGet(nullptr, 0, 1, LOWEST, true));
- SpdySerializedFrame resp(spdy_util_.ConstructSpdyGetReply(NULL, 0, 1));
+ SpdySerializedFrame resp(spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
SpdySerializedFrame body(spdy_util_.ConstructSpdyDataFrame(1, false));
SpdySerializedFrame fin_body(spdy_util_.ConstructSpdyDataFrame(1, true));
spdy_util_.UpdateWithStreamDestruction(1);
SpdySerializedFrame req2(
spdy_util_.ConstructSpdyGet(nullptr, 0, 3, LOWEST, true));
- SpdySerializedFrame resp2(spdy_util_.ConstructSpdyGetReply(NULL, 0, 3));
+ SpdySerializedFrame resp2(spdy_util_.ConstructSpdyGetReply(nullptr, 0, 3));
SettingsMap settings;
const uint32_t max_concurrent_streams = 1;
- settings[SETTINGS_MAX_CONCURRENT_STREAMS] =
- SettingsFlagsAndValue(SETTINGS_FLAG_NONE, max_concurrent_streams);
+ settings[SETTINGS_MAX_CONCURRENT_STREAMS] = max_concurrent_streams;
SpdySerializedFrame settings_frame(
spdy_util_.ConstructSpdySettings(settings));
SpdySerializedFrame settings_ack(spdy_util_.ConstructSpdySettingsAck());
@@ -1340,12 +1348,12 @@ TEST_F(SpdyNetworkTransactionTest, ThreeGetsWithMaxConcurrentSocketClose) {
};
SequencedSocketData data(reads, arraysize(reads), writes, arraysize(writes));
- SequencedSocketData data_placeholder(NULL, 0, NULL, 0);
+ SequencedSocketData data_placeholder(nullptr, 0, nullptr, 0);
NetLogWithSource log;
TransactionHelperResult out;
NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
- NetLogWithSource(), NULL);
+ NetLogWithSource(), nullptr);
helper.RunPreTestSetup();
helper.AddData(&data);
// We require placeholder data because three get requests are sent out, so
@@ -1412,7 +1420,7 @@ TEST_F(SpdyNetworkTransactionTest, Put) {
CreateMockWrite(req, 0),
};
- SpdySerializedFrame resp(spdy_util_.ConstructSpdyGetReply(NULL, 0, 1));
+ SpdySerializedFrame resp(spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
SpdySerializedFrame body(spdy_util_.ConstructSpdyDataFrame(1, true));
MockRead reads[] = {
CreateMockRead(resp, 1), CreateMockRead(body, 2),
@@ -1421,7 +1429,7 @@ TEST_F(SpdyNetworkTransactionTest, Put) {
SequencedSocketData data(reads, arraysize(reads), writes, arraysize(writes));
NormalSpdyTransactionHelper helper(request, DEFAULT_PRIORITY,
- NetLogWithSource(), NULL);
+ NetLogWithSource(), nullptr);
helper.RunToCompletion(&data);
TransactionHelperResult out = helper.output();
@@ -1444,7 +1452,7 @@ TEST_F(SpdyNetworkTransactionTest, Head) {
CreateMockWrite(req, 0),
};
- SpdySerializedFrame resp(spdy_util_.ConstructSpdyGetReply(NULL, 0, 1));
+ SpdySerializedFrame resp(spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
SpdySerializedFrame body(spdy_util_.ConstructSpdyDataFrame(1, true));
MockRead reads[] = {
CreateMockRead(resp, 1), CreateMockRead(body, 2),
@@ -1453,7 +1461,7 @@ TEST_F(SpdyNetworkTransactionTest, Head) {
SequencedSocketData data(reads, arraysize(reads), writes, arraysize(writes));
NormalSpdyTransactionHelper helper(request, DEFAULT_PRIORITY,
- NetLogWithSource(), NULL);
+ NetLogWithSource(), nullptr);
helper.RunToCompletion(&data);
TransactionHelperResult out = helper.output();
@@ -1464,13 +1472,13 @@ TEST_F(SpdyNetworkTransactionTest, Head) {
// Test that a simple POST works.
TEST_F(SpdyNetworkTransactionTest, Post) {
SpdySerializedFrame req(spdy_util_.ConstructSpdyPost(
- kDefaultUrl, 1, kUploadDataSize, LOWEST, NULL, 0));
+ kDefaultUrl, 1, kUploadDataSize, LOWEST, nullptr, 0));
SpdySerializedFrame body(spdy_util_.ConstructSpdyDataFrame(1, true));
MockWrite writes[] = {
CreateMockWrite(req, 0), CreateMockWrite(body, 1), // POST upload frame
};
- SpdySerializedFrame resp(spdy_util_.ConstructSpdyPostReply(NULL, 0));
+ SpdySerializedFrame resp(spdy_util_.ConstructSpdyPostReply(nullptr, 0));
MockRead reads[] = {
CreateMockRead(resp, 2), CreateMockRead(body, 3),
MockRead(ASYNC, 0, 4) // EOF
@@ -1478,7 +1486,7 @@ TEST_F(SpdyNetworkTransactionTest, Post) {
SequencedSocketData data(reads, arraysize(reads), writes, arraysize(writes));
NormalSpdyTransactionHelper helper(CreatePostRequest(), DEFAULT_PRIORITY,
- NetLogWithSource(), NULL);
+ NetLogWithSource(), nullptr);
helper.RunToCompletion(&data);
TransactionHelperResult out = helper.output();
EXPECT_THAT(out.rv, IsOk());
@@ -1489,13 +1497,13 @@ TEST_F(SpdyNetworkTransactionTest, Post) {
// Test that a POST with a file works.
TEST_F(SpdyNetworkTransactionTest, FilePost) {
SpdySerializedFrame req(spdy_util_.ConstructSpdyPost(
- kDefaultUrl, 1, kUploadDataSize, LOWEST, NULL, 0));
+ kDefaultUrl, 1, kUploadDataSize, LOWEST, nullptr, 0));
SpdySerializedFrame body(spdy_util_.ConstructSpdyDataFrame(1, true));
MockWrite writes[] = {
CreateMockWrite(req, 0), CreateMockWrite(body, 1), // POST upload frame
};
- SpdySerializedFrame resp(spdy_util_.ConstructSpdyPostReply(NULL, 0));
+ SpdySerializedFrame resp(spdy_util_.ConstructSpdyPostReply(nullptr, 0));
MockRead reads[] = {
CreateMockRead(resp, 2), CreateMockRead(body, 3),
MockRead(ASYNC, 0, 4) // EOF
@@ -1503,7 +1511,7 @@ TEST_F(SpdyNetworkTransactionTest, FilePost) {
SequencedSocketData data(reads, arraysize(reads), writes, arraysize(writes));
NormalSpdyTransactionHelper helper(CreateFilePostRequest(), DEFAULT_PRIORITY,
- NetLogWithSource(), NULL);
+ NetLogWithSource(), nullptr);
helper.RunToCompletion(&data);
TransactionHelperResult out = helper.output();
EXPECT_THAT(out.rv, IsOk());
@@ -1523,7 +1531,7 @@ TEST_F(SpdyNetworkTransactionTest, UnreadableFilePost) {
SequencedSocketData data(reads, arraysize(reads), writes, arraysize(writes));
NormalSpdyTransactionHelper helper(CreateUnreadableFilePostRequest(),
DEFAULT_PRIORITY, NetLogWithSource(),
- NULL);
+ nullptr);
helper.RunPreTestSetup();
helper.AddData(&data);
helper.RunDefaultTest();
@@ -1536,21 +1544,22 @@ TEST_F(SpdyNetworkTransactionTest, UnreadableFilePost) {
// Test that a complex POST works.
TEST_F(SpdyNetworkTransactionTest, ComplexPost) {
SpdySerializedFrame req(spdy_util_.ConstructSpdyPost(
- kDefaultUrl, 1, kUploadDataSize, LOWEST, NULL, 0));
+ kDefaultUrl, 1, kUploadDataSize, LOWEST, nullptr, 0));
SpdySerializedFrame body(spdy_util_.ConstructSpdyDataFrame(1, true));
MockWrite writes[] = {
CreateMockWrite(req, 0), CreateMockWrite(body, 1), // POST upload frame
};
- SpdySerializedFrame resp(spdy_util_.ConstructSpdyPostReply(NULL, 0));
+ SpdySerializedFrame resp(spdy_util_.ConstructSpdyPostReply(nullptr, 0));
MockRead reads[] = {
CreateMockRead(resp, 2), CreateMockRead(body, 3),
MockRead(ASYNC, 0, 4) // EOF
};
SequencedSocketData data(reads, arraysize(reads), writes, arraysize(writes));
- NormalSpdyTransactionHelper helper(
- CreateComplexPostRequest(), DEFAULT_PRIORITY, NetLogWithSource(), NULL);
+ NormalSpdyTransactionHelper helper(CreateComplexPostRequest(),
+ DEFAULT_PRIORITY, NetLogWithSource(),
+ nullptr);
helper.RunToCompletion(&data);
TransactionHelperResult out = helper.output();
EXPECT_THAT(out.rv, IsOk());
@@ -1560,21 +1569,22 @@ TEST_F(SpdyNetworkTransactionTest, ComplexPost) {
// Test that a chunked POST works.
TEST_F(SpdyNetworkTransactionTest, ChunkedPost) {
- SpdySerializedFrame req(spdy_util_.ConstructChunkedSpdyPost(NULL, 0));
+ SpdySerializedFrame req(spdy_util_.ConstructChunkedSpdyPost(nullptr, 0));
SpdySerializedFrame body(spdy_util_.ConstructSpdyDataFrame(1, true));
MockWrite writes[] = {
CreateMockWrite(req, 0), CreateMockWrite(body, 1),
};
- SpdySerializedFrame resp(spdy_util_.ConstructSpdyPostReply(NULL, 0));
+ SpdySerializedFrame resp(spdy_util_.ConstructSpdyPostReply(nullptr, 0));
MockRead reads[] = {
CreateMockRead(resp, 2), CreateMockRead(body, 3),
MockRead(ASYNC, 0, 4) // EOF
};
SequencedSocketData data(reads, arraysize(reads), writes, arraysize(writes));
- NormalSpdyTransactionHelper helper(
- CreateChunkedPostRequest(), DEFAULT_PRIORITY, NetLogWithSource(), NULL);
+ NormalSpdyTransactionHelper helper(CreateChunkedPostRequest(),
+ DEFAULT_PRIORITY, NetLogWithSource(),
+ nullptr);
// These chunks get merged into a single frame when being sent.
const int kFirstChunkSize = kUploadDataSize/2;
@@ -1591,7 +1601,7 @@ TEST_F(SpdyNetworkTransactionTest, ChunkedPost) {
// Test that a chunked POST works with chunks appended after transaction starts.
TEST_F(SpdyNetworkTransactionTest, DelayedChunkedPost) {
- SpdySerializedFrame req(spdy_util_.ConstructChunkedSpdyPost(NULL, 0));
+ SpdySerializedFrame req(spdy_util_.ConstructChunkedSpdyPost(nullptr, 0));
SpdySerializedFrame chunk1(spdy_util_.ConstructSpdyDataFrame(1, false));
SpdySerializedFrame chunk2(spdy_util_.ConstructSpdyDataFrame(1, false));
SpdySerializedFrame chunk3(spdy_util_.ConstructSpdyDataFrame(1, true));
@@ -1600,7 +1610,7 @@ TEST_F(SpdyNetworkTransactionTest, DelayedChunkedPost) {
CreateMockWrite(chunk2, 2), CreateMockWrite(chunk3, 3),
};
- SpdySerializedFrame resp(spdy_util_.ConstructSpdyPostReply(NULL, 0));
+ SpdySerializedFrame resp(spdy_util_.ConstructSpdyPostReply(nullptr, 0));
MockRead reads[] = {
CreateMockRead(resp, 4), CreateMockRead(chunk1, 5),
CreateMockRead(chunk2, 6), CreateMockRead(chunk3, 7),
@@ -1608,8 +1618,9 @@ TEST_F(SpdyNetworkTransactionTest, DelayedChunkedPost) {
};
SequencedSocketData data(reads, arraysize(reads), writes, arraysize(writes));
- NormalSpdyTransactionHelper helper(
- CreateChunkedPostRequest(), DEFAULT_PRIORITY, NetLogWithSource(), NULL);
+ NormalSpdyTransactionHelper helper(CreateChunkedPostRequest(),
+ DEFAULT_PRIORITY, NetLogWithSource(),
+ nullptr);
upload_chunked_data_stream()->AppendData(kUploadData, kUploadDataSize, false);
@@ -1643,7 +1654,7 @@ TEST_F(SpdyNetworkTransactionTest, NullPost) {
request.method = "POST";
request.url = default_url_;
// Create an empty UploadData.
- request.upload_data_stream = NULL;
+ request.upload_data_stream = nullptr;
// When request.upload_data_stream is NULL for post, content-length is
// expected to be 0.
@@ -1656,7 +1667,7 @@ TEST_F(SpdyNetworkTransactionTest, NullPost) {
CreateMockWrite(req, 0),
};
- SpdySerializedFrame resp(spdy_util_.ConstructSpdyPostReply(NULL, 0));
+ SpdySerializedFrame resp(spdy_util_.ConstructSpdyPostReply(nullptr, 0));
SpdySerializedFrame body(spdy_util_.ConstructSpdyDataFrame(1, true));
MockRead reads[] = {
CreateMockRead(resp, 1), CreateMockRead(body, 2),
@@ -1666,7 +1677,7 @@ TEST_F(SpdyNetworkTransactionTest, NullPost) {
SequencedSocketData data(reads, arraysize(reads), writes, arraysize(writes));
NormalSpdyTransactionHelper helper(request, DEFAULT_PRIORITY,
- NetLogWithSource(), NULL);
+ NetLogWithSource(), nullptr);
helper.RunToCompletion(&data);
TransactionHelperResult out = helper.output();
EXPECT_THAT(out.rv, IsOk());
@@ -1697,7 +1708,7 @@ TEST_F(SpdyNetworkTransactionTest, EmptyPost) {
CreateMockWrite(req, 0),
};
- SpdySerializedFrame resp(spdy_util_.ConstructSpdyPostReply(NULL, 0));
+ SpdySerializedFrame resp(spdy_util_.ConstructSpdyPostReply(nullptr, 0));
SpdySerializedFrame body(spdy_util_.ConstructSpdyDataFrame(1, true));
MockRead reads[] = {
CreateMockRead(resp, 1), CreateMockRead(body, 2),
@@ -1707,7 +1718,7 @@ TEST_F(SpdyNetworkTransactionTest, EmptyPost) {
SequencedSocketData data(reads, arraysize(reads), writes, arraysize(writes));
NormalSpdyTransactionHelper helper(request, DEFAULT_PRIORITY,
- NetLogWithSource(), NULL);
+ NetLogWithSource(), nullptr);
helper.RunToCompletion(&data);
TransactionHelperResult out = helper.output();
EXPECT_THAT(out.rv, IsOk());
@@ -1717,12 +1728,12 @@ TEST_F(SpdyNetworkTransactionTest, EmptyPost) {
// While we're doing a post, the server sends the reply before upload completes.
TEST_F(SpdyNetworkTransactionTest, ResponseBeforePostCompletes) {
- SpdySerializedFrame req(spdy_util_.ConstructChunkedSpdyPost(NULL, 0));
+ SpdySerializedFrame req(spdy_util_.ConstructChunkedSpdyPost(nullptr, 0));
SpdySerializedFrame body(spdy_util_.ConstructSpdyDataFrame(1, true));
MockWrite writes[] = {
CreateMockWrite(req, 0), CreateMockWrite(body, 3),
};
- SpdySerializedFrame resp(spdy_util_.ConstructSpdyPostReply(NULL, 0));
+ SpdySerializedFrame resp(spdy_util_.ConstructSpdyPostReply(nullptr, 0));
MockRead reads[] = {
CreateMockRead(resp, 1), CreateMockRead(body, 2),
MockRead(ASYNC, 0, 4) // EOF
@@ -1731,8 +1742,9 @@ TEST_F(SpdyNetworkTransactionTest, ResponseBeforePostCompletes) {
// Write the request headers, and read the complete response
// while still waiting for chunked request data.
SequencedSocketData data(reads, arraysize(reads), writes, arraysize(writes));
- NormalSpdyTransactionHelper helper(
- CreateChunkedPostRequest(), DEFAULT_PRIORITY, NetLogWithSource(), NULL);
+ NormalSpdyTransactionHelper helper(CreateChunkedPostRequest(),
+ DEFAULT_PRIORITY, NetLogWithSource(),
+ nullptr);
helper.RunPreTestSetup();
helper.AddData(&data);
@@ -1753,6 +1765,9 @@ TEST_F(SpdyNetworkTransactionTest, ResponseBeforePostCompletes) {
std::string response_body;
EXPECT_THAT(ReadTransaction(helper.trans(), &response_body), IsOk());
EXPECT_EQ(kUploadData, response_body);
+
+ // Finish async network reads/writes.
+ base::RunLoop().RunUntilIdle();
helper.VerifyDataConsumed();
}
@@ -1769,14 +1784,14 @@ TEST_F(SpdyNetworkTransactionTest, SocketWriteReturnsZero) {
CreateMockWrite(rst, 3, SYNCHRONOUS),
};
- SpdySerializedFrame resp(spdy_util_.ConstructSpdyGetReply(NULL, 0, 1));
+ SpdySerializedFrame resp(spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
MockRead reads[] = {
CreateMockRead(resp, 1, ASYNC), MockRead(ASYNC, 0, 0, 4) // EOF
};
SequencedSocketData data(reads, arraysize(reads), writes, arraysize(writes));
NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
- NetLogWithSource(), NULL);
+ NetLogWithSource(), nullptr);
helper.RunPreTestSetup();
helper.AddData(&data);
helper.StartDefaultTest();
@@ -1807,7 +1822,7 @@ TEST_F(SpdyNetworkTransactionTest, ResponseWithoutHeaders) {
};
SequencedSocketData data(reads, arraysize(reads), writes, arraysize(writes));
NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
- NetLogWithSource(), NULL);
+ NetLogWithSource(), nullptr);
helper.RunToCompletion(&data);
TransactionHelperResult out = helper.output();
EXPECT_THAT(out.rv, IsError(ERR_SPDY_PROTOCOL_ERROR));
@@ -1835,7 +1850,7 @@ TEST_F(SpdyNetworkTransactionTest, ResponseWithTwoSynReplies) {
SequencedSocketData data(reads, arraysize(reads), writes, arraysize(writes));
NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
- NetLogWithSource(), NULL);
+ NetLogWithSource(), nullptr);
helper.RunPreTestSetup();
helper.AddData(&data);
@@ -1881,7 +1896,7 @@ TEST_F(SpdyNetworkTransactionTest, ResetReplyWithTransferEncoding) {
SequencedSocketData data(reads, arraysize(reads), writes, arraysize(writes));
NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
- NetLogWithSource(), NULL);
+ NetLogWithSource(), nullptr);
helper.RunToCompletion(&data);
TransactionHelperResult out = helper.output();
EXPECT_THAT(out.rv, IsError(ERR_SPDY_PROTOCOL_ERROR));
@@ -1894,13 +1909,16 @@ TEST_F(SpdyNetworkTransactionTest, ResetPushWithTransferEncoding) {
// Construct the request.
SpdySerializedFrame req(
spdy_util_.ConstructSpdyGet(nullptr, 0, 1, LOWEST, true));
+ SpdySerializedFrame priority(
+ spdy_util_.ConstructSpdyPriority(2, 1, IDLE, true));
SpdySerializedFrame rst(
spdy_util_.ConstructSpdyRstStream(2, RST_STREAM_PROTOCOL_ERROR));
MockWrite writes[] = {
- CreateMockWrite(req, 0), CreateMockWrite(rst, 4),
+ CreateMockWrite(req, 0), CreateMockWrite(priority, 3),
+ CreateMockWrite(rst, 5),
};
- SpdySerializedFrame resp(spdy_util_.ConstructSpdyGetReply(NULL, 0, 1));
+ SpdySerializedFrame resp(spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
const char* const headers[] = {
"transfer-encoding", "chunked"
};
@@ -1909,13 +1927,13 @@ TEST_F(SpdyNetworkTransactionTest, ResetPushWithTransferEncoding) {
GetDefaultUrlWithPath("/1").c_str()));
SpdySerializedFrame body(spdy_util_.ConstructSpdyDataFrame(1, true));
MockRead reads[] = {
- CreateMockRead(resp, 1), CreateMockRead(push, 2), CreateMockRead(body, 3),
- MockRead(ASYNC, 0, 5) // EOF
+ CreateMockRead(resp, 1), CreateMockRead(push, 2), CreateMockRead(body, 4),
+ MockRead(ASYNC, 0, 6) // EOF
};
SequencedSocketData data(reads, arraysize(reads), writes, arraysize(writes));
NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
- NetLogWithSource(), NULL);
+ NetLogWithSource(), nullptr);
helper.RunToCompletion(&data);
TransactionHelperResult out = helper.output();
EXPECT_THAT(out.rv, IsOk());
@@ -1934,7 +1952,7 @@ TEST_F(SpdyNetworkTransactionTest, CancelledTransaction) {
CreateMockWrite(req),
};
- SpdySerializedFrame resp(spdy_util_.ConstructSpdyGetReply(NULL, 0, 1));
+ SpdySerializedFrame resp(spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
MockRead reads[] = {
CreateMockRead(resp),
// This following read isn't used by the test, except during the
@@ -1948,7 +1966,7 @@ TEST_F(SpdyNetworkTransactionTest, CancelledTransaction) {
writes, arraysize(writes));
NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
- NetLogWithSource(), NULL);
+ NetLogWithSource(), nullptr);
helper.RunPreTestSetup();
helper.AddData(&data);
HttpNetworkTransaction* trans = helper.trans();
@@ -1976,7 +1994,7 @@ TEST_F(SpdyNetworkTransactionTest, CancelledTransactionSendRst) {
CreateMockWrite(rst, 2, SYNCHRONOUS),
};
- SpdySerializedFrame resp(spdy_util_.ConstructSpdyGetReply(NULL, 0, 1));
+ SpdySerializedFrame resp(spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
MockRead reads[] = {
CreateMockRead(resp, 1, ASYNC), MockRead(ASYNC, 0, 0, 3) // EOF
};
@@ -1984,7 +2002,7 @@ TEST_F(SpdyNetworkTransactionTest, CancelledTransactionSendRst) {
SequencedSocketData data(reads, arraysize(reads), writes, arraysize(writes));
NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
- NetLogWithSource(), NULL);
+ NetLogWithSource(), nullptr);
helper.RunPreTestSetup();
helper.AddData(&data);
HttpNetworkTransaction* trans = helper.trans();
@@ -2008,7 +2026,8 @@ TEST_F(SpdyNetworkTransactionTest, StartTransactionOnReadCallback) {
SpdySerializedFrame req(
spdy_util_.ConstructSpdyGet(nullptr, 0, 1, LOWEST, true));
MockWrite writes[] = {CreateMockWrite(req)};
- MockWrite writes2[] = {CreateMockWrite(req, 0)};
+ MockWrite writes2[] = {CreateMockWrite(req, 0),
+ MockWrite(SYNCHRONOUS, ERR_IO_PENDING, 3)};
// The indicated length of this frame is longer than its actual length. When
// the session receives an empty frame after this one, it shuts down the
@@ -2018,7 +2037,7 @@ TEST_F(SpdyNetworkTransactionTest, StartTransactionOnReadCallback) {
0x07, 'h', 'e', 'l', 'l', 'o', '!',
};
- SpdySerializedFrame resp(spdy_util_.ConstructSpdyGetReply(NULL, 0, 1));
+ SpdySerializedFrame resp(spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
MockRead reads[] = {
CreateMockRead(resp, 1),
MockRead(ASYNC, ERR_IO_PENDING, 2), // Force a pause
@@ -2036,7 +2055,7 @@ TEST_F(SpdyNetworkTransactionTest, StartTransactionOnReadCallback) {
arraysize(writes2));
NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
- NetLogWithSource(), NULL);
+ NetLogWithSource(), nullptr);
helper.RunPreTestSetup();
helper.AddData(&data);
helper.AddData(&data2);
@@ -2074,7 +2093,7 @@ TEST_F(SpdyNetworkTransactionTest, DeleteSessionOnReadCallback) {
spdy_util_.ConstructSpdyGet(nullptr, 0, 1, LOWEST, true));
MockWrite writes[] = {CreateMockWrite(req, 0)};
- SpdySerializedFrame resp(spdy_util_.ConstructSpdyGetReply(NULL, 0, 1));
+ SpdySerializedFrame resp(spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
SpdySerializedFrame body(spdy_util_.ConstructSpdyDataFrame(1, true));
MockRead reads[] = {
CreateMockRead(resp, 1),
@@ -2085,7 +2104,7 @@ TEST_F(SpdyNetworkTransactionTest, DeleteSessionOnReadCallback) {
SequencedSocketData data(reads, arraysize(reads), writes, arraysize(writes));
NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
- NetLogWithSource(), NULL);
+ NetLogWithSource(), nullptr);
helper.RunPreTestSetup();
helper.AddData(&data);
HttpNetworkTransaction* trans = helper.trans();
@@ -2171,8 +2190,10 @@ TEST_F(SpdyNetworkTransactionTest,
SpdySerializedFrame req(
spdy_util_.ConstructSpdyHeaders(1, std::move(headers), LOWEST, true));
+ SpdySerializedFrame priority(
+ spdy_util_.ConstructSpdyPriority(2, 1, IDLE, true));
MockWrite writes[] = {
- CreateMockWrite(req, 0),
+ CreateMockWrite(req, 0), CreateMockWrite(priority, 2),
};
SpdySerializedFrame resp(spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
@@ -2193,7 +2214,7 @@ TEST_F(SpdyNetworkTransactionTest,
2, "should not include either", 25, false));
MockRead push_init_read(CreateMockRead(push_init_frame, 1));
- MockRead response_headers(CreateMockRead(resp, 4));
+ MockRead response_headers(CreateMockRead(resp, 5));
// raw_header_size() will contain the size of the push promise frame
// initialization.
int expected_response_headers_size =
@@ -2201,11 +2222,11 @@ TEST_F(SpdyNetworkTransactionTest,
MockRead reads[] = {
push_init_read,
- CreateMockRead(push_headers_frame, 2),
- CreateMockRead(push_body_frame, 3),
+ CreateMockRead(push_headers_frame, 3),
+ CreateMockRead(push_body_frame, 4),
response_headers,
- CreateMockRead(response_body_frame, 5),
- MockRead(ASYNC, 0, 6) // EOF
+ CreateMockRead(response_body_frame, 6),
+ MockRead(ASYNC, 0, 7) // EOF
};
SequencedSocketData data(reads, arraysize(reads), writes, arraysize(writes));
@@ -2265,7 +2286,7 @@ TEST_F(SpdyNetworkTransactionTest, DISABLED_RedirectGetRequest) {
CreateMockWrite(req2, 1),
};
- SpdySerializedFrame resp2(spdy_util_.ConstructSpdyGetReply(NULL, 0, 1));
+ SpdySerializedFrame resp2(spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
SpdySerializedFrame body2(spdy_util_.ConstructSpdyDataFrame(1, true));
MockRead reads2[] = {
CreateMockRead(resp2, 2), CreateMockRead(body2, 3),
@@ -2316,9 +2337,9 @@ TEST_F(SpdyNetworkTransactionTest, DISABLED_RedirectServerPush) {
// Setup writes/reads to www.example.org
SpdySerializedFrame req(
spdy_util_.ConstructSpdyHeaders(1, std::move(headers), LOWEST, true));
- SpdySerializedFrame resp(spdy_util_.ConstructSpdyGetReply(NULL, 0, 1));
+ SpdySerializedFrame resp(spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
SpdySerializedFrame rep(spdy_util_.ConstructSpdyPush(
- NULL, 0, 2, 1, GetDefaultUrlWithPath("/foo.dat").c_str(),
+ nullptr, 0, 2, 1, GetDefaultUrlWithPath("/foo.dat").c_str(),
"301 Moved Permanently", "http://www.foo.com/index.php"));
SpdySerializedFrame body(spdy_util_.ConstructSpdyDataFrame(1, true));
SpdySerializedFrame rst(
@@ -2339,7 +2360,7 @@ TEST_F(SpdyNetworkTransactionTest, DISABLED_RedirectServerPush) {
headers2["accept-encoding"] = "gzip, deflate";
SpdySerializedFrame req2(
spdy_util_.ConstructSpdyHeaders(1, std::move(headers2), LOWEST, true));
- SpdySerializedFrame resp2(spdy_util_.ConstructSpdyGetReply(NULL, 0, 1));
+ SpdySerializedFrame resp2(spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
SpdySerializedFrame body2(spdy_util_.ConstructSpdyDataFrame(1, true));
MockWrite writes2[] = {
CreateMockWrite(req2, 1),
@@ -2395,24 +2416,24 @@ TEST_F(SpdyNetworkTransactionTest, DISABLED_RedirectServerPush) {
TEST_F(SpdyNetworkTransactionTest, ServerPushSingleDataFrame) {
SpdySerializedFrame stream1_syn(
spdy_util_.ConstructSpdyGet(nullptr, 0, 1, LOWEST, true));
- SpdySerializedFrame stream1_body(spdy_util_.ConstructSpdyDataFrame(1, true));
+ SpdySerializedFrame stream2_priority(
+ spdy_util_.ConstructSpdyPriority(2, 1, IDLE, true));
MockWrite writes[] = {
- CreateMockWrite(stream1_syn, 0),
+ CreateMockWrite(stream1_syn, 0), CreateMockWrite(stream2_priority, 3),
};
SpdySerializedFrame stream1_reply(
- spdy_util_.ConstructSpdyGetReply(NULL, 0, 1));
+ spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
SpdySerializedFrame stream2_syn(spdy_util_.ConstructSpdyPush(
- NULL, 0, 2, 1, GetDefaultUrlWithPath("/foo.dat").c_str()));
+ nullptr, 0, 2, 1, GetDefaultUrlWithPath("/foo.dat").c_str()));
+ SpdySerializedFrame stream1_body(spdy_util_.ConstructSpdyDataFrame(1, true));
const char kPushedData[] = "pushed";
SpdySerializedFrame stream2_body(spdy_util_.ConstructSpdyDataFrame(
2, kPushedData, strlen(kPushedData), true));
MockRead reads[] = {
- CreateMockRead(stream1_reply, 1),
- CreateMockRead(stream2_syn, 2),
- CreateMockRead(stream1_body, 3, SYNCHRONOUS),
- CreateMockRead(stream2_body, 4),
- MockRead(SYNCHRONOUS, ERR_IO_PENDING, 5), // Force a pause
+ CreateMockRead(stream1_reply, 1), CreateMockRead(stream2_syn, 2),
+ CreateMockRead(stream1_body, 4), CreateMockRead(stream2_body, 5),
+ MockRead(SYNCHRONOUS, ERR_IO_PENDING, 6), // Force a pause
};
HttpResponseInfo response;
@@ -2436,24 +2457,26 @@ TEST_F(SpdyNetworkTransactionTest, ServerPushSingleDataFrame) {
TEST_F(SpdyNetworkTransactionTest, ServerPushBeforeHeaders) {
SpdySerializedFrame stream1_syn(
spdy_util_.ConstructSpdyGet(nullptr, 0, 1, LOWEST, true));
+ SpdySerializedFrame stream2_priority(
+ spdy_util_.ConstructSpdyPriority(2, 1, IDLE, true));
MockWrite writes[] = {
- CreateMockWrite(stream1_syn, 0),
+ CreateMockWrite(stream1_syn, 0), CreateMockWrite(stream2_priority, 2),
};
SpdySerializedFrame stream2_syn(spdy_util_.ConstructSpdyPush(
nullptr, 0, 2, 1, GetDefaultUrlWithPath("/foo.dat").c_str()));
SpdySerializedFrame stream1_reply(
- spdy_util_.ConstructSpdyGetReply(NULL, 0, 1));
+ spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
SpdySerializedFrame stream1_body(spdy_util_.ConstructSpdyDataFrame(1, true));
const char kPushedData[] = "pushed";
SpdySerializedFrame stream2_body(spdy_util_.ConstructSpdyDataFrame(
2, kPushedData, strlen(kPushedData), true));
MockRead reads[] = {
CreateMockRead(stream2_syn, 1),
- CreateMockRead(stream1_reply, 2),
- CreateMockRead(stream1_body, 3, SYNCHRONOUS),
- CreateMockRead(stream2_body, 4),
- MockRead(SYNCHRONOUS, ERR_IO_PENDING, 5), // Force a pause
+ CreateMockRead(stream1_reply, 3),
+ CreateMockRead(stream1_body, 4, SYNCHRONOUS),
+ CreateMockRead(stream2_body, 5),
+ MockRead(SYNCHRONOUS, ERR_IO_PENDING, 6), // Force a pause
};
HttpResponseInfo response;
@@ -2477,14 +2500,16 @@ TEST_F(SpdyNetworkTransactionTest, ServerPushBeforeHeaders) {
TEST_F(SpdyNetworkTransactionTest, ServerPushSingleDataFrame2) {
SpdySerializedFrame stream1_syn(
spdy_util_.ConstructSpdyGet(nullptr, 0, 1, LOWEST, true));
+ SpdySerializedFrame stream2_priority(
+ spdy_util_.ConstructSpdyPriority(2, 1, IDLE, true));
MockWrite writes[] = {
- CreateMockWrite(stream1_syn, 0),
+ CreateMockWrite(stream1_syn, 0), CreateMockWrite(stream2_priority, 3),
};
SpdySerializedFrame stream1_reply(
- spdy_util_.ConstructSpdyGetReply(NULL, 0, 1));
+ spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
SpdySerializedFrame stream2_syn(spdy_util_.ConstructSpdyPush(
- NULL, 0, 2, 1, GetDefaultUrlWithPath("/foo.dat").c_str()));
+ nullptr, 0, 2, 1, GetDefaultUrlWithPath("/foo.dat").c_str()));
const char kPushedData[] = "pushed";
SpdySerializedFrame stream2_body(spdy_util_.ConstructSpdyDataFrame(
2, kPushedData, strlen(kPushedData), true));
@@ -2492,9 +2517,9 @@ TEST_F(SpdyNetworkTransactionTest, ServerPushSingleDataFrame2) {
MockRead reads[] = {
CreateMockRead(stream1_reply, 1),
CreateMockRead(stream2_syn, 2),
- CreateMockRead(stream2_body, 3),
- CreateMockRead(stream1_body, 4, SYNCHRONOUS),
- MockRead(SYNCHRONOUS, ERR_IO_PENDING, 5), // Force a pause
+ CreateMockRead(stream2_body, 4),
+ CreateMockRead(stream1_body, 5, SYNCHRONOUS),
+ MockRead(SYNCHRONOUS, ERR_IO_PENDING, 6), // Force a pause
};
HttpResponseInfo response;
@@ -2515,31 +2540,141 @@ TEST_F(SpdyNetworkTransactionTest, ServerPushSingleDataFrame2) {
EXPECT_EQ("HTTP/1.1 200", response2.headers->GetStatusLine());
}
+TEST_F(SpdyNetworkTransactionTest, ServerPushUpdatesPriority) {
+ SpdySerializedFrame stream1_headers(
+ spdy_util_.ConstructSpdyGet(nullptr, 0, 1, HIGHEST, true));
+ SpdySerializedFrame stream3_headers(
+ spdy_util_.ConstructSpdyGet(nullptr, 0, 3, MEDIUM, true));
+ SpdySerializedFrame stream5_headers(
+ spdy_util_.ConstructSpdyGet(nullptr, 0, 5, MEDIUM, true));
+
+ // Stream 1 pushes two streams that are initially prioritized below stream 5.
+ // Stream 2 is later prioritized below stream 1 after it matches a request.
+ SpdySerializedFrame stream2_priority(
+ spdy_util_.ConstructSpdyPriority(2, 5, IDLE, true));
+ SpdySerializedFrame stream4_priority(
+ spdy_util_.ConstructSpdyPriority(4, 2, IDLE, true));
+ SpdySerializedFrame stream4_priority_update(
+ spdy_util_.ConstructSpdyPriority(4, 5, IDLE, true));
+ SpdySerializedFrame stream2_priority_update(
+ spdy_util_.ConstructSpdyPriority(2, 1, HIGHEST, true));
+
+ MockWrite writes[] = {
+ CreateMockWrite(stream1_headers, 0),
+ CreateMockWrite(stream3_headers, 1),
+ CreateMockWrite(stream5_headers, 2),
+ CreateMockWrite(stream2_priority, 7),
+ CreateMockWrite(stream4_priority, 9),
+ CreateMockWrite(stream4_priority_update, 11),
+ CreateMockWrite(stream2_priority_update, 12),
+ };
+
+ SpdySerializedFrame stream1_reply(
+ spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
+ SpdySerializedFrame stream3_reply(
+ spdy_util_.ConstructSpdyGetReply(nullptr, 0, 3));
+ SpdySerializedFrame stream5_reply(
+ spdy_util_.ConstructSpdyGetReply(nullptr, 0, 5));
+
+ SpdySerializedFrame stream2_push(spdy_util_.ConstructSpdyPush(
+ nullptr, 0, 2, 1, GetDefaultUrlWithPath("/foo.dat").c_str()));
+ SpdySerializedFrame stream4_push(spdy_util_.ConstructSpdyPush(
+ nullptr, 0, 4, 1, GetDefaultUrlWithPath("/bar.dat").c_str()));
+
+ SpdySerializedFrame stream1_body(spdy_util_.ConstructSpdyDataFrame(1, true));
+ SpdySerializedFrame stream2_body(spdy_util_.ConstructSpdyDataFrame(2, true));
+ SpdySerializedFrame stream3_body(spdy_util_.ConstructSpdyDataFrame(3, true));
+ SpdySerializedFrame stream5_body(spdy_util_.ConstructSpdyDataFrame(5, true));
+
+ MockRead reads[] = {
+ CreateMockRead(stream1_reply, 3),
+ CreateMockRead(stream3_reply, 4),
+ CreateMockRead(stream5_reply, 5),
+ CreateMockRead(stream2_push, 6),
+ CreateMockRead(stream4_push, 8),
+ MockRead(ASYNC, ERR_IO_PENDING, 10),
+ CreateMockRead(stream1_body, 13),
+ CreateMockRead(stream2_body, 14),
+ CreateMockRead(stream3_body, 15),
+ CreateMockRead(stream5_body, 16),
+ MockRead(SYNCHRONOUS, ERR_IO_PENDING, 17), // Force a pause
+ };
+
+ SequencedSocketData data(reads, arraysize(reads), writes, arraysize(writes));
+ SequencedSocketData data_placeholder1(nullptr, 0, nullptr, 0);
+ SequencedSocketData data_placeholder2(nullptr, 0, nullptr, 0);
+ SequencedSocketData data_placeholder3(nullptr, 0, nullptr, 0);
+
+ NormalSpdyTransactionHelper helper(CreateGetRequest(), LOWEST,
+ NetLogWithSource(), nullptr);
+ helper.RunPreTestSetup();
+ helper.AddData(&data);
+ helper.AddData(&data_placeholder1); // other requests reuse the same socket
+ helper.AddData(&data_placeholder2);
+ helper.AddData(&data_placeholder3);
+ HttpNetworkTransaction trans1(HIGHEST, helper.session());
+ HttpNetworkTransaction trans3(MEDIUM, helper.session());
+ HttpNetworkTransaction trans5(MEDIUM, helper.session());
+
+ TestCompletionCallback callback1;
+ TestCompletionCallback callback3;
+ TestCompletionCallback callback5;
+
+ // Start the ordinary requests.
+ NetLogWithSource log;
+ ASSERT_THAT(trans1.Start(&CreateGetRequest(), callback1.callback(), log),
+ IsError(ERR_IO_PENDING));
+ ASSERT_THAT(trans3.Start(&CreateGetRequest(), callback3.callback(), log),
+ IsError(ERR_IO_PENDING));
+ ASSERT_THAT(trans5.Start(&CreateGetRequest(), callback5.callback(), log),
+ IsError(ERR_IO_PENDING));
+ data.RunUntilPaused();
+
+ // Start a request that matches the push.
+ HttpRequestInfo push_req = CreateGetRequest();
+ push_req.url = GURL(GetDefaultUrlWithPath("/foo.dat"));
+
+ HttpNetworkTransaction trans2(HIGHEST, helper.session());
+ TestCompletionCallback callback2;
+ ASSERT_THAT(trans2.Start(&push_req, callback2.callback(), log),
+ IsError(ERR_IO_PENDING));
+ data.Resume();
+
+ base::RunLoop().RunUntilIdle();
+ ASSERT_THAT(callback1.WaitForResult(), IsOk());
+ ASSERT_THAT(callback2.WaitForResult(), IsOk());
+ ASSERT_THAT(callback3.WaitForResult(), IsOk());
+ ASSERT_THAT(callback5.WaitForResult(), IsOk());
+ helper.VerifyDataConsumed();
+}
+
TEST_F(SpdyNetworkTransactionTest, ServerPushServerAborted) {
SpdySerializedFrame stream1_syn(
spdy_util_.ConstructSpdyGet(nullptr, 0, 1, LOWEST, true));
- SpdySerializedFrame stream1_body(spdy_util_.ConstructSpdyDataFrame(1, true));
+ SpdySerializedFrame stream2_priority(
+ spdy_util_.ConstructSpdyPriority(2, 1, IDLE, true));
MockWrite writes[] = {
- CreateMockWrite(stream1_syn, 0),
+ CreateMockWrite(stream1_syn, 0), CreateMockWrite(stream2_priority, 3),
};
SpdySerializedFrame stream1_reply(
- spdy_util_.ConstructSpdyGetReply(NULL, 0, 1));
+ spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
SpdySerializedFrame stream2_syn(spdy_util_.ConstructSpdyPush(
- NULL, 0, 2, 1, GetDefaultUrlWithPath("/foo.dat").c_str()));
+ nullptr, 0, 2, 1, GetDefaultUrlWithPath("/foo.dat").c_str()));
SpdySerializedFrame stream2_rst(
spdy_util_.ConstructSpdyRstStream(2, RST_STREAM_PROTOCOL_ERROR));
+ SpdySerializedFrame stream1_body(spdy_util_.ConstructSpdyDataFrame(1, true));
MockRead reads[] = {
CreateMockRead(stream1_reply, 1),
- CreateMockRead(stream2_syn, 2),
- CreateMockRead(stream2_rst, 3),
- CreateMockRead(stream1_body, 4, SYNCHRONOUS),
- MockRead(SYNCHRONOUS, ERR_IO_PENDING, 5), // Force a pause
+ CreateMockRead(stream2_syn, 2, SYNCHRONOUS),
+ CreateMockRead(stream2_rst, 4),
+ CreateMockRead(stream1_body, 5, SYNCHRONOUS),
+ MockRead(SYNCHRONOUS, ERR_IO_PENDING, 6), // Force a pause
};
SequencedSocketData data(reads, arraysize(reads), writes, arraysize(writes));
NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
- NetLogWithSource(), NULL);
+ NetLogWithSource(), nullptr);
helper.RunPreTestSetup();
helper.AddData(&data);
@@ -2555,6 +2690,7 @@ TEST_F(SpdyNetworkTransactionTest, ServerPushServerAborted) {
EXPECT_THAT(rv, IsOk());
// Verify that we consumed all test data.
+ base::RunLoop().RunUntilIdle();
EXPECT_TRUE(data.AllReadDataConsumed());
EXPECT_TRUE(data.AllWriteDataConsumed());
@@ -2569,29 +2705,34 @@ TEST_F(SpdyNetworkTransactionTest, ServerPushServerAborted) {
TEST_F(SpdyNetworkTransactionTest, ServerPushDuplicate) {
SpdySerializedFrame stream1_syn(
spdy_util_.ConstructSpdyGet(nullptr, 0, 1, LOWEST, true));
- SpdySerializedFrame stream1_body(spdy_util_.ConstructSpdyDataFrame(1, true));
+ SpdySerializedFrame stream2_priority(
+ spdy_util_.ConstructSpdyPriority(2, 1, IDLE, true));
SpdySerializedFrame stream3_rst(
spdy_util_.ConstructSpdyRstStream(4, RST_STREAM_PROTOCOL_ERROR));
MockWrite writes[] = {
- CreateMockWrite(stream1_syn, 0), CreateMockWrite(stream3_rst, 4),
+ CreateMockWrite(stream1_syn, 0), CreateMockWrite(stream2_priority, 3),
+ CreateMockWrite(stream3_rst, 5),
};
SpdySerializedFrame stream1_reply(
- spdy_util_.ConstructSpdyGetReply(NULL, 0, 1));
+ spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
SpdySerializedFrame stream2_syn(spdy_util_.ConstructSpdyPush(
- NULL, 0, 2, 1, GetDefaultUrlWithPath("/foo.dat").c_str()));
+ nullptr, 0, 2, 1, GetDefaultUrlWithPath("/foo.dat").c_str()));
+ SpdySerializedFrame stream3_syn(spdy_util_.ConstructSpdyPush(
+ nullptr, 0, 4, 1, GetDefaultUrlWithPath("/foo.dat").c_str()));
+
const char kPushedData[] = "pushed";
+ SpdySerializedFrame stream1_body(spdy_util_.ConstructSpdyDataFrame(1, true));
SpdySerializedFrame stream2_body(spdy_util_.ConstructSpdyDataFrame(
2, kPushedData, strlen(kPushedData), true));
- SpdySerializedFrame stream3_syn(spdy_util_.ConstructSpdyPush(
- NULL, 0, 4, 1, GetDefaultUrlWithPath("/foo.dat").c_str()));
+
MockRead reads[] = {
CreateMockRead(stream1_reply, 1),
CreateMockRead(stream2_syn, 2),
- CreateMockRead(stream3_syn, 3),
- CreateMockRead(stream1_body, 5),
- CreateMockRead(stream2_body, 6),
- MockRead(SYNCHRONOUS, ERR_IO_PENDING, 7), // Force a pause
+ CreateMockRead(stream3_syn, 4),
+ CreateMockRead(stream1_body, 6),
+ CreateMockRead(stream2_body, 7),
+ MockRead(SYNCHRONOUS, ERR_IO_PENDING, 8), // Force a pause
};
HttpResponseInfo response;
@@ -2615,15 +2756,16 @@ TEST_F(SpdyNetworkTransactionTest, ServerPushDuplicate) {
TEST_F(SpdyNetworkTransactionTest, ServerPushMultipleDataFrame) {
SpdySerializedFrame stream1_syn(
spdy_util_.ConstructSpdyGet(nullptr, 0, 1, LOWEST, true));
- SpdySerializedFrame stream1_body(spdy_util_.ConstructSpdyDataFrame(1, true));
+ SpdySerializedFrame stream2_priority(
+ spdy_util_.ConstructSpdyPriority(2, 1, IDLE, true));
MockWrite writes[] = {
- CreateMockWrite(stream1_syn, 0),
+ CreateMockWrite(stream1_syn, 0), CreateMockWrite(stream2_priority, 3),
};
SpdySerializedFrame stream1_reply(
- spdy_util_.ConstructSpdyGetReply(NULL, 0, 1));
+ spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
SpdySerializedFrame stream2_syn(spdy_util_.ConstructSpdyPush(
- NULL, 0, 2, 1, GetDefaultUrlWithPath("/foo.dat").c_str()));
+ nullptr, 0, 2, 1, GetDefaultUrlWithPath("/foo.dat").c_str()));
static const char kPushedData[] = "pushed my darling hello my baby";
SpdySerializedFrame stream2_body_base(spdy_util_.ConstructSpdyDataFrame(
2, kPushedData, strlen(kPushedData), true));
@@ -2637,15 +2779,16 @@ TEST_F(SpdyNetworkTransactionTest, ServerPushMultipleDataFrame) {
SpdySerializedFrame stream2_body4(stream2_body_base.data() + 3 * kChunkSize,
stream2_body_base.size() - 3 * kChunkSize,
false);
+ SpdySerializedFrame stream1_body(spdy_util_.ConstructSpdyDataFrame(1, true));
MockRead reads[] = {
CreateMockRead(stream1_reply, 1),
CreateMockRead(stream2_syn, 2),
- CreateMockRead(stream2_body1, 3),
- CreateMockRead(stream2_body2, 4),
- CreateMockRead(stream2_body3, 5),
- CreateMockRead(stream2_body4, 6),
- CreateMockRead(stream1_body, 7, SYNCHRONOUS),
- MockRead(SYNCHRONOUS, ERR_IO_PENDING, 8), // Force a pause
+ CreateMockRead(stream2_body1, 4),
+ CreateMockRead(stream2_body2, 5),
+ CreateMockRead(stream2_body3, 6),
+ CreateMockRead(stream2_body4, 7),
+ CreateMockRead(stream1_body, 8, SYNCHRONOUS),
+ MockRead(SYNCHRONOUS, ERR_IO_PENDING, 9), // Force a pause
};
HttpResponseInfo response;
@@ -2666,15 +2809,16 @@ TEST_F(SpdyNetworkTransactionTest, ServerPushMultipleDataFrame) {
TEST_F(SpdyNetworkTransactionTest, ServerPushMultipleDataFrameInterrupted) {
SpdySerializedFrame stream1_syn(
spdy_util_.ConstructSpdyGet(nullptr, 0, 1, LOWEST, true));
- SpdySerializedFrame stream1_body(spdy_util_.ConstructSpdyDataFrame(1, true));
+ SpdySerializedFrame stream2_priority(
+ spdy_util_.ConstructSpdyPriority(2, 1, IDLE, true));
MockWrite writes[] = {
- CreateMockWrite(stream1_syn, 0),
+ CreateMockWrite(stream1_syn, 0), CreateMockWrite(stream2_priority, 3),
};
SpdySerializedFrame stream1_reply(
- spdy_util_.ConstructSpdyGetReply(NULL, 0, 1));
+ spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
SpdySerializedFrame stream2_syn(spdy_util_.ConstructSpdyPush(
- NULL, 0, 2, 1, GetDefaultUrlWithPath("/foo.dat").c_str()));
+ nullptr, 0, 2, 1, GetDefaultUrlWithPath("/foo.dat").c_str()));
static const char kPushedData[] = "pushed my darling hello my baby";
SpdySerializedFrame stream2_body_base(spdy_util_.ConstructSpdyDataFrame(
2, kPushedData, strlen(kPushedData), true));
@@ -2688,15 +2832,16 @@ TEST_F(SpdyNetworkTransactionTest, ServerPushMultipleDataFrameInterrupted) {
SpdySerializedFrame stream2_body4(stream2_body_base.data() + 3 * kChunkSize,
stream2_body_base.size() - 3 * kChunkSize,
false);
+ SpdySerializedFrame stream1_body(spdy_util_.ConstructSpdyDataFrame(1, true));
MockRead reads[] = {
CreateMockRead(stream1_reply, 1),
CreateMockRead(stream2_syn, 2),
- CreateMockRead(stream2_body1, 3),
- CreateMockRead(stream2_body2, 4),
- CreateMockRead(stream2_body3, 5),
- CreateMockRead(stream2_body4, 6),
- CreateMockRead(stream1_body, 7, SYNCHRONOUS),
- MockRead(SYNCHRONOUS, ERR_IO_PENDING, 8) // Force a pause.
+ CreateMockRead(stream2_body1, 4),
+ CreateMockRead(stream2_body2, 5),
+ CreateMockRead(stream2_body3, 6),
+ CreateMockRead(stream2_body4, 7),
+ CreateMockRead(stream1_body, 8, SYNCHRONOUS),
+ MockRead(SYNCHRONOUS, ERR_IO_PENDING, 9) // Force a pause.
};
HttpResponseInfo response;
@@ -2723,16 +2868,16 @@ TEST_F(SpdyNetworkTransactionTest, ServerPushInvalidAssociatedStreamID0) {
};
SpdySerializedFrame stream1_reply(
- spdy_util_.ConstructSpdyGetReply(NULL, 0, 1));
+ spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
SpdySerializedFrame stream2_syn(spdy_util_.ConstructSpdyPush(
- NULL, 0, 2, 0, GetDefaultUrlWithPath("/foo.dat").c_str()));
+ nullptr, 0, 2, 0, GetDefaultUrlWithPath("/foo.dat").c_str()));
MockRead reads[] = {
CreateMockRead(stream1_reply, 1), CreateMockRead(stream2_syn, 2),
};
SequencedSocketData data(reads, arraysize(reads), writes, arraysize(writes));
NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
- NetLogWithSource(), NULL);
+ NetLogWithSource(), nullptr);
helper.RunPreTestSetup();
helper.AddData(&data);
@@ -2747,6 +2892,9 @@ TEST_F(SpdyNetworkTransactionTest, ServerPushInvalidAssociatedStreamID0) {
rv = callback.WaitForResult();
EXPECT_THAT(rv, IsOk());
+ // Finish async network reads/writes.
+ base::RunLoop().RunUntilIdle();
+
// Verify that we consumed all test data.
EXPECT_TRUE(data.AllReadDataConsumed());
EXPECT_TRUE(data.AllWriteDataConsumed());
@@ -2762,15 +2910,15 @@ TEST_F(SpdyNetworkTransactionTest, ServerPushInvalidAssociatedStreamID9) {
spdy_util_.ConstructSpdyGet(nullptr, 0, 1, LOWEST, true));
SpdySerializedFrame stream1_body(spdy_util_.ConstructSpdyDataFrame(1, true));
SpdySerializedFrame stream2_rst(
- spdy_util_.ConstructSpdyRstStream(2, RST_STREAM_INVALID_STREAM));
+ spdy_util_.ConstructSpdyRstStream(2, RST_STREAM_STREAM_CLOSED));
MockWrite writes[] = {
CreateMockWrite(stream1_syn, 0), CreateMockWrite(stream2_rst, 3),
};
SpdySerializedFrame stream1_reply(
- spdy_util_.ConstructSpdyGetReply(NULL, 0, 1));
+ spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
SpdySerializedFrame stream2_syn(spdy_util_.ConstructSpdyPush(
- NULL, 0, 2, 9, GetDefaultUrlWithPath("/foo.dat").c_str()));
+ nullptr, 0, 2, 9, GetDefaultUrlWithPath("/foo.dat").c_str()));
MockRead reads[] = {
CreateMockRead(stream1_reply, 1), CreateMockRead(stream2_syn, 2),
CreateMockRead(stream1_body, 4),
@@ -2779,7 +2927,7 @@ TEST_F(SpdyNetworkTransactionTest, ServerPushInvalidAssociatedStreamID9) {
SequencedSocketData data(reads, arraysize(reads), writes, arraysize(writes));
NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
- NetLogWithSource(), NULL);
+ NetLogWithSource(), nullptr);
helper.RunPreTestSetup();
helper.AddData(&data);
@@ -2794,6 +2942,9 @@ TEST_F(SpdyNetworkTransactionTest, ServerPushInvalidAssociatedStreamID9) {
rv = callback.WaitForResult();
EXPECT_THAT(rv, IsOk());
+ // Finish async network reads/writes.
+ base::RunLoop().RunUntilIdle();
+
// Verify that we consumed all test data.
EXPECT_TRUE(data.AllReadDataConsumed());
EXPECT_TRUE(data.AllWriteDataConsumed());
@@ -2815,7 +2966,7 @@ TEST_F(SpdyNetworkTransactionTest, ServerPushNoURL) {
};
SpdySerializedFrame stream1_reply(
- spdy_util_.ConstructSpdyGetReply(NULL, 0, 1));
+ spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
SpdyHeaderBlock incomplete_headers;
incomplete_headers[spdy_util_.GetStatusKey()] = "200 OK";
incomplete_headers["hello"] = "bye";
@@ -2829,7 +2980,7 @@ TEST_F(SpdyNetworkTransactionTest, ServerPushNoURL) {
SequencedSocketData data(reads, arraysize(reads), writes, arraysize(writes));
NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
- NetLogWithSource(), NULL);
+ NetLogWithSource(), nullptr);
helper.RunPreTestSetup();
helper.AddData(&data);
@@ -2844,6 +2995,9 @@ TEST_F(SpdyNetworkTransactionTest, ServerPushNoURL) {
rv = callback.WaitForResult();
EXPECT_THAT(rv, IsOk());
+ // Finish async network reads/writes.
+ base::RunLoop().RunUntilIdle();
+
// Verify that we consumed all test data.
EXPECT_TRUE(data.AllReadDataConsumed());
EXPECT_TRUE(data.AllWriteDataConsumed());
@@ -2858,21 +3012,24 @@ TEST_F(SpdyNetworkTransactionTest, ServerPushNoURL) {
TEST_F(SpdyNetworkTransactionTest, ServerPushOnPushedStream) {
SpdySerializedFrame stream1_syn(
spdy_util_.ConstructSpdyGet(nullptr, 0, 1, LOWEST, true));
+ SpdySerializedFrame stream2_priority(
+ spdy_util_.ConstructSpdyPriority(2, 1, IDLE, true));
SpdySerializedFrame goaway(spdy_util_.ConstructSpdyGoAway(
2, GOAWAY_PROTOCOL_ERROR, "Push on even stream id."));
MockWrite writes[] = {
- CreateMockWrite(stream1_syn, 0), CreateMockWrite(goaway, 4),
+ CreateMockWrite(stream1_syn, 0), CreateMockWrite(stream2_priority, 3),
+ CreateMockWrite(goaway, 5),
};
SpdySerializedFrame stream1_reply(
- spdy_util_.ConstructSpdyGetReply(NULL, 0, 1));
+ spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
SpdySerializedFrame stream2_syn(spdy_util_.ConstructSpdyPush(
nullptr, 0, 2, 1, GetDefaultUrlWithPath("/foo.dat").c_str()));
SpdySerializedFrame stream3_syn(spdy_util_.ConstructSpdyPush(
nullptr, 0, 4, 2, GetDefaultUrlWithPath("/bar.dat").c_str()));
MockRead reads[] = {
CreateMockRead(stream1_reply, 1), CreateMockRead(stream2_syn, 2),
- CreateMockRead(stream3_syn, 3),
+ CreateMockRead(stream3_syn, 4),
};
SequencedSocketData data(reads, arraysize(reads), writes, arraysize(writes));
@@ -2886,7 +3043,7 @@ TEST_F(SpdyNetworkTransactionTest, ServerPushOnClosedStream) {
SpdySerializedFrame stream1_syn(
spdy_util_.ConstructSpdyGet(nullptr, 0, 1, LOWEST, true));
SpdySerializedFrame rst(
- spdy_util_.ConstructSpdyRstStream(2, RST_STREAM_INVALID_STREAM));
+ spdy_util_.ConstructSpdyRstStream(2, RST_STREAM_STREAM_CLOSED));
MockWrite writes[] = {
CreateMockWrite(stream1_syn, 0), CreateMockWrite(rst, 5),
};
@@ -2914,6 +3071,10 @@ TEST_F(SpdyNetworkTransactionTest, ServerPushOnClosedStream) {
NetLogWithSource());
rv = callback.GetResult(rv);
EXPECT_THAT(rv, IsOk());
+
+ // Finish async network reads/writes.
+ base::RunLoop().RunUntilIdle();
+
HttpResponseInfo response = *trans->GetResponseInfo();
EXPECT_TRUE(response.headers);
EXPECT_EQ("HTTP/1.1 200", response.headers->GetStatusLine());
@@ -2928,10 +3089,13 @@ TEST_F(SpdyNetworkTransactionTest, ServerPushOnClosedStream) {
TEST_F(SpdyNetworkTransactionTest, ServerPushOnClosedPushedStream) {
SpdySerializedFrame stream1_syn(
spdy_util_.ConstructSpdyGet(nullptr, 0, 1, LOWEST, true));
+ SpdySerializedFrame stream2_priority(
+ spdy_util_.ConstructSpdyPriority(2, 1, IDLE, true));
SpdySerializedFrame goaway(spdy_util_.ConstructSpdyGoAway(
2, GOAWAY_PROTOCOL_ERROR, "Push on even stream id."));
MockWrite writes[] = {
- CreateMockWrite(stream1_syn, 0), CreateMockWrite(goaway, 7),
+ CreateMockWrite(stream1_syn, 0), CreateMockWrite(stream2_priority, 3),
+ CreateMockWrite(goaway, 8),
};
SpdySerializedFrame stream1_reply(
@@ -2947,8 +3111,8 @@ TEST_F(SpdyNetworkTransactionTest, ServerPushOnClosedPushedStream) {
MockRead reads[] = {
CreateMockRead(stream1_reply, 1), CreateMockRead(stream2_syn, 2),
- CreateMockRead(stream1_body, 3), CreateMockRead(stream2_body, 4),
- MockRead(ASYNC, ERR_IO_PENDING, 5), CreateMockRead(stream3_syn, 6),
+ CreateMockRead(stream1_body, 4), CreateMockRead(stream2_body, 5),
+ MockRead(ASYNC, ERR_IO_PENDING, 6), CreateMockRead(stream3_syn, 7),
};
SequencedSocketData data(reads, arraysize(reads), writes, arraysize(writes));
@@ -2993,25 +3157,21 @@ TEST_F(SpdyNetworkTransactionTest, ResponseHeaders) {
int num_headers;
const char* extra_headers[5];
SpdyHeaderBlock expected_headers;
- } test_cases[] = {
- // This uses a multi-valued cookie header.
- { 2,
- { "cookie", "val1",
- "cookie", "val2", // will get appended separated by NULL
- NULL
- },
- },
- // This is the minimalist set of headers.
- { 0,
- { NULL },
- },
- // Headers with a comma separated list.
- { 1,
- { "cookie", "val1,val2",
- NULL
- },
- }
- };
+ } test_cases[] = {// This uses a multi-valued cookie header.
+ {
+ 2,
+ {"cookie", "val1", "cookie",
+ "val2", // will get appended separated by nullptr
+ nullptr},
+ },
+ // This is the minimalist set of headers.
+ {
+ 0, {nullptr},
+ },
+ // Headers with a comma separated list.
+ {
+ 1, {"cookie", "val1,val2", nullptr},
+ }};
test_cases[0].expected_headers["status"] = "200";
test_cases[1].expected_headers["status"] = "200";
@@ -3041,7 +3201,7 @@ TEST_F(SpdyNetworkTransactionTest, ResponseHeaders) {
SequencedSocketData data(reads, arraysize(reads), writes,
arraysize(writes));
NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
- NetLogWithSource(), NULL);
+ NetLogWithSource(), nullptr);
helper.RunToCompletion(&data);
TransactionHelperResult out = helper.output();
@@ -3082,27 +3242,27 @@ TEST_F(SpdyNetworkTransactionTest, ResponseHeadersVary) {
// with NUL characters, it needs to be unfolded into multiple headers.
{true,
{1, 3},
- {{"cookie", "val1,val2", NULL},
+ {{"cookie", "val1,val2", nullptr},
{spdy_util_.GetStatusKey(), "200", spdy_util_.GetPathKey(),
- "/index.php", "vary", "cookie", NULL}}},
+ "/index.php", "vary", "cookie", nullptr}}},
{// Multiple vary fields.
true,
{2, 4},
- {{"friend", "barney", "enemy", "snaggletooth", NULL},
+ {{"friend", "barney", "enemy", "snaggletooth", nullptr},
{spdy_util_.GetStatusKey(), "200", spdy_util_.GetPathKey(),
- "/index.php", "vary", "friend", "vary", "enemy", NULL}}},
+ "/index.php", "vary", "friend", "vary", "enemy", nullptr}}},
{// Test a '*' vary field.
false,
{1, 3},
- {{"cookie", "val1,val2", NULL},
+ {{"cookie", "val1,val2", nullptr},
{spdy_util_.GetStatusKey(), "200", spdy_util_.GetPathKey(),
- "/index.php", "vary", "*", NULL}}},
+ "/index.php", "vary", "*", nullptr}}},
{// Multiple comma-separated vary fields.
true,
{2, 3},
- {{"friend", "barney", "enemy", "snaggletooth", NULL},
+ {{"friend", "barney", "enemy", "snaggletooth", nullptr},
{spdy_util_.GetStatusKey(), "200", spdy_util_.GetPathKey(),
- "/index.php", "vary", "friend,enemy", NULL}}}};
+ "/index.php", "vary", "friend,enemy", nullptr}}}};
for (size_t i = 0; i < arraysize(test_cases); ++i) {
SpdyTestUtil spdy_test_util;
@@ -3147,7 +3307,7 @@ TEST_F(SpdyNetworkTransactionTest, ResponseHeadersVary) {
SequencedSocketData data(reads, arraysize(reads), writes,
arraysize(writes));
NormalSpdyTransactionHelper helper(request, DEFAULT_PRIORITY,
- NetLogWithSource(), NULL);
+ NetLogWithSource(), nullptr);
helper.RunToCompletion(&data);
TransactionHelperResult out = helper.output();
@@ -3185,15 +3345,15 @@ TEST_F(SpdyNetworkTransactionTest, InvalidResponseHeaders) {
{
3,
{spdy_util_.GetPathKey(), "/index.php", "cookie", "val1", "cookie",
- "val2", NULL},
+ "val2", nullptr},
},
// Response headers missing version header
{
- 1, {spdy_util_.GetPathKey(), "/index.php", "status", "200", NULL},
+ 1, {spdy_util_.GetPathKey(), "/index.php", "status", "200", nullptr},
},
// Response headers with no headers
{
- 0, {NULL},
+ 0, {nullptr},
},
};
@@ -3221,7 +3381,7 @@ TEST_F(SpdyNetworkTransactionTest, InvalidResponseHeaders) {
SequencedSocketData data(reads, arraysize(reads), writes,
arraysize(writes));
NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
- NetLogWithSource(), NULL);
+ NetLogWithSource(), nullptr);
helper.RunToCompletion(&data);
TransactionHelperResult out = helper.output();
EXPECT_THAT(out.rv, IsError(ERR_SPDY_PROTOCOL_ERROR));
@@ -3238,10 +3398,9 @@ TEST_F(SpdyNetworkTransactionTest, CorruptFrameSessionError) {
// This is the length field that's too short.
SpdySerializedFrame reply_wrong_length(
spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
- size_t right_size =
- reply_wrong_length.size() - SpdyConstants::GetFrameHeaderSize(HTTP2);
+ size_t right_size = reply_wrong_length.size() - kFrameHeaderSize;
size_t wrong_size = right_size - 4;
- test::SetFrameLength(&reply_wrong_length, wrong_size, HTTP2);
+ test::SetFrameLength(&reply_wrong_length, wrong_size);
MockRead reads[] = {
MockRead(ASYNC, reply_wrong_length.data(), reply_wrong_length.size() - 4,
@@ -3250,7 +3409,7 @@ TEST_F(SpdyNetworkTransactionTest, CorruptFrameSessionError) {
SequencedSocketData data(reads, arraysize(reads), writes, arraysize(writes));
NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
- NetLogWithSource(), NULL);
+ NetLogWithSource(), nullptr);
helper.RunToCompletion(&data);
TransactionHelperResult out = helper.output();
EXPECT_THAT(out.rv, IsError(ERR_SPDY_COMPRESSION_ERROR));
@@ -3264,13 +3423,13 @@ TEST_F(SpdyNetworkTransactionTest, GoAwayOnDecompressionFailure) {
MockWrite writes[] = {CreateMockWrite(req, 0), CreateMockWrite(goaway, 2)};
// Read HEADERS with corrupted payload.
- SpdySerializedFrame resp(spdy_util_.ConstructSpdyGetReply(NULL, 0, 1));
+ SpdySerializedFrame resp(spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
memset(resp.data() + 12, 0xcf, resp.size() - 12);
MockRead reads[] = {CreateMockRead(resp, 1)};
SequencedSocketData data(reads, arraysize(reads), writes, arraysize(writes));
NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
- NetLogWithSource(), NULL);
+ NetLogWithSource(), nullptr);
helper.RunToCompletion(&data);
TransactionHelperResult out = helper.output();
EXPECT_THAT(out.rv, IsError(ERR_SPDY_COMPRESSION_ERROR));
@@ -3287,12 +3446,12 @@ TEST_F(SpdyNetworkTransactionTest, GoAwayOnFrameSizeError) {
// Read WINDOW_UPDATE with incorrectly-sized payload.
SpdySerializedFrame bad_window_update(
spdy_util_.ConstructSpdyWindowUpdate(1, 1));
- test::SetFrameLength(&bad_window_update, bad_window_update.size() - 1, HTTP2);
+ test::SetFrameLength(&bad_window_update, bad_window_update.size() - 1);
MockRead reads[] = {CreateMockRead(bad_window_update, 1)};
SequencedSocketData data(reads, arraysize(reads), writes, arraysize(writes));
NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
- NetLogWithSource(), NULL);
+ NetLogWithSource(), nullptr);
helper.RunToCompletion(&data);
TransactionHelperResult out = helper.output();
EXPECT_THAT(out.rv, IsError(ERR_SPDY_FRAME_SIZE_ERROR));
@@ -3316,7 +3475,7 @@ TEST_F(SpdyNetworkTransactionTest, WriteError) {
SequencedSocketData data(reads, arraysize(reads), writes, arraysize(writes));
NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
- NetLogWithSource(), NULL);
+ NetLogWithSource(), nullptr);
helper.RunPreTestSetup();
helper.AddData(&data);
EXPECT_TRUE(helper.StartDefaultTest());
@@ -3338,7 +3497,7 @@ TEST_F(SpdyNetworkTransactionTest, PartialWrite) {
writes[i].sequence_number = i;
}
- SpdySerializedFrame resp(spdy_util_.ConstructSpdyGetReply(NULL, 0, 1));
+ SpdySerializedFrame resp(spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
SpdySerializedFrame body(spdy_util_.ConstructSpdyDataFrame(1, true));
MockRead reads[] = {
CreateMockRead(resp, kChunks), CreateMockRead(body, kChunks + 1),
@@ -3347,7 +3506,7 @@ TEST_F(SpdyNetworkTransactionTest, PartialWrite) {
SequencedSocketData data(reads, arraysize(reads), writes.get(), kChunks);
NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
- NetLogWithSource(), NULL);
+ NetLogWithSource(), nullptr);
helper.RunToCompletion(&data);
TransactionHelperResult out = helper.output();
EXPECT_THAT(out.rv, IsOk());
@@ -3364,7 +3523,7 @@ TEST_F(SpdyNetworkTransactionTest, NetLog) {
spdy_util_.ConstructSpdyGet(kExtraHeaders, 1, 1, LOWEST, true));
MockWrite writes[] = {CreateMockWrite(req, 0)};
- SpdySerializedFrame resp(spdy_util_.ConstructSpdyGetReply(NULL, 0, 1));
+ SpdySerializedFrame resp(spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
SpdySerializedFrame body(spdy_util_.ConstructSpdyDataFrame(1, true));
MockRead reads[] = {
CreateMockRead(resp, 1), CreateMockRead(body, 2),
@@ -3375,7 +3534,7 @@ TEST_F(SpdyNetworkTransactionTest, NetLog) {
SequencedSocketData data(reads, arraysize(reads), writes, arraysize(writes));
NormalSpdyTransactionHelper helper(CreateGetRequestWithUserAgent(),
- DEFAULT_PRIORITY, log.bound(), NULL);
+ DEFAULT_PRIORITY, log.bound(), nullptr);
helper.RunToCompletion(&data);
TransactionHelperResult out = helper.output();
EXPECT_THAT(out.rv, IsOk());
@@ -3461,7 +3620,7 @@ TEST_F(SpdyNetworkTransactionTest, BufferFull) {
SpdySerializedFrame last_frame(
spdy_util_.ConstructSpdyDataFrame(1, "d", 1, /*fin=*/true));
- SpdySerializedFrame resp(spdy_util_.ConstructSpdyGetReply(NULL, 0, 1));
+ SpdySerializedFrame resp(spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
MockRead reads[] = {
CreateMockRead(resp, 1),
MockRead(ASYNC, ERR_IO_PENDING, 2), // Force a pause
@@ -3476,7 +3635,7 @@ TEST_F(SpdyNetworkTransactionTest, BufferFull) {
TestCompletionCallback callback;
NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
- NetLogWithSource(), NULL);
+ NetLogWithSource(), nullptr);
helper.RunPreTestSetup();
helper.AddData(&data);
HttpNetworkTransaction* trans = helper.trans();
@@ -3548,7 +3707,7 @@ TEST_F(SpdyNetworkTransactionTest, Buffering) {
CombineFrames(data_frames, arraysize(data_frames),
combined_data_frames, arraysize(combined_data_frames));
- SpdySerializedFrame resp(spdy_util_.ConstructSpdyGetReply(NULL, 0, 1));
+ SpdySerializedFrame resp(spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
MockRead reads[] = {
CreateMockRead(resp, 1),
MockRead(ASYNC, ERR_IO_PENDING, 2), // Force a pause
@@ -3559,7 +3718,7 @@ TEST_F(SpdyNetworkTransactionTest, Buffering) {
SequencedSocketData data(reads, arraysize(reads), writes, arraysize(writes));
NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
- NetLogWithSource(), NULL);
+ NetLogWithSource(), nullptr);
helper.RunPreTestSetup();
helper.AddData(&data);
HttpNetworkTransaction* trans = helper.trans();
@@ -3625,7 +3784,7 @@ TEST_F(SpdyNetworkTransactionTest, BufferedAll) {
MockWrite writes[] = {CreateMockWrite(req, 0)};
// 5 data frames in a single read.
- SpdySerializedFrame reply(spdy_util_.ConstructSpdyGetReply(NULL, 0, 1));
+ SpdySerializedFrame reply(spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
SpdySerializedFrame data_frame(
spdy_util_.ConstructSpdyDataFrame(1, "message", 7, /*fin=*/false));
SpdySerializedFrame data_frame_fin(
@@ -3645,7 +3804,7 @@ TEST_F(SpdyNetworkTransactionTest, BufferedAll) {
SequencedSocketData data(reads, arraysize(reads), writes, arraysize(writes));
NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
- NetLogWithSource(), NULL);
+ NetLogWithSource(), nullptr);
helper.RunPreTestSetup();
helper.AddData(&data);
HttpNetworkTransaction* trans = helper.trans();
@@ -3716,7 +3875,7 @@ TEST_F(SpdyNetworkTransactionTest, BufferedClosed) {
int combined_data_frames_len =
CombineFrames(data_frames, arraysize(data_frames),
combined_data_frames, arraysize(combined_data_frames));
- SpdySerializedFrame resp(spdy_util_.ConstructSpdyGetReply(NULL, 0, 1));
+ SpdySerializedFrame resp(spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
MockRead reads[] = {
CreateMockRead(resp, 1),
MockRead(ASYNC, ERR_IO_PENDING, 2), // Force a wait
@@ -3727,7 +3886,7 @@ TEST_F(SpdyNetworkTransactionTest, BufferedClosed) {
SequencedSocketData data(reads, arraysize(reads), writes, arraysize(writes));
NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
- NetLogWithSource(), NULL);
+ NetLogWithSource(), nullptr);
helper.RunPreTestSetup();
helper.AddData(&data);
HttpNetworkTransaction* trans = helper.trans();
@@ -3796,7 +3955,7 @@ TEST_F(SpdyNetworkTransactionTest, BufferedCancelled) {
SpdySerializedFrame data_frame(
spdy_util_.ConstructSpdyDataFrame(1, "message", 7, /*fin=*/false));
- SpdySerializedFrame resp(spdy_util_.ConstructSpdyGetReply(NULL, 0, 1));
+ SpdySerializedFrame resp(spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
MockRead reads[] = {
CreateMockRead(resp, 1),
MockRead(ASYNC, ERR_IO_PENDING, 2), // Force a wait
@@ -3806,7 +3965,7 @@ TEST_F(SpdyNetworkTransactionTest, BufferedCancelled) {
SequencedSocketData data(reads, arraysize(reads), writes, arraysize(writes));
NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
- NetLogWithSource(), NULL);
+ NetLogWithSource(), nullptr);
helper.RunPreTestSetup();
helper.AddData(&data);
HttpNetworkTransaction* trans = helper.trans();
@@ -3861,19 +4020,97 @@ TEST_F(SpdyNetworkTransactionTest, GoAwayWithActiveStream) {
SequencedSocketData data(reads, arraysize(reads), writes, arraysize(writes));
NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
- NetLogWithSource(), NULL);
+ NetLogWithSource(), nullptr);
helper.AddData(&data);
helper.RunToCompletion(&data);
TransactionHelperResult out = helper.output();
EXPECT_THAT(out.rv, IsError(ERR_ABORTED));
}
+// A server can gracefully shut down by sending a GOAWAY frame
+// with maximum last-stream-id value.
+// Transactions started before receiving such a GOAWAY frame should succeed,
+// but SpdySession should be unavailable for new streams.
+TEST_F(SpdyNetworkTransactionTest, GracefulGoaway) {
+ SpdySerializedFrame req1(
+ spdy_util_.ConstructSpdyGet(nullptr, 0, 1, LOWEST, true));
+ spdy_util_.UpdateWithStreamDestruction(1);
+ SpdySerializedFrame req2(
+ spdy_util_.ConstructSpdyGet("https://www.example.org/foo", 3, LOWEST));
+ MockWrite writes[] = {CreateMockWrite(req1, 0), CreateMockWrite(req2, 3)};
+
+ SpdySerializedFrame resp1(spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
+ SpdySerializedFrame body1(spdy_util_.ConstructSpdyDataFrame(1, true));
+ SpdySerializedFrame goaway(spdy_util_.ConstructSpdyGoAway(
+ 0x7fffffff, GOAWAY_NO_ERROR, "Graceful shutdown."));
+ SpdySerializedFrame resp2(spdy_util_.ConstructSpdyGetReply(nullptr, 0, 3));
+ SpdySerializedFrame body2(spdy_util_.ConstructSpdyDataFrame(3, true));
+ MockRead reads[] = {CreateMockRead(resp1, 1), CreateMockRead(body1, 2),
+ CreateMockRead(goaway, 4), CreateMockRead(resp2, 5),
+ CreateMockRead(body2, 6), MockRead(ASYNC, 0, 7)};
+
+ // Run first transaction.
+ SequencedSocketData data(reads, arraysize(reads), writes, arraysize(writes));
+ NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
+ NetLogWithSource(), nullptr);
+ helper.RunPreTestSetup();
+ helper.AddData(&data);
+ helper.RunDefaultTest();
+
+ // Verify first response.
+ TransactionHelperResult out = helper.output();
+ EXPECT_THAT(out.rv, IsOk());
+ EXPECT_EQ("HTTP/1.1 200", out.status_line);
+ EXPECT_EQ("hello!", out.response_data);
+
+ // GOAWAY frame has not yet been received, SpdySession should be available.
+ SpdySessionPool* spdy_session_pool = helper.session()->spdy_session_pool();
+ SpdySessionKey key(host_port_pair_, ProxyServer::Direct(),
+ PRIVACY_MODE_DISABLED);
+ NetLogWithSource log;
+ base::WeakPtr<SpdySession> spdy_session =
+ spdy_session_pool->FindAvailableSession(key, GURL(), log);
+ EXPECT_TRUE(spdy_session);
+
+ // Start second transaction.
+ HttpNetworkTransaction trans2(DEFAULT_PRIORITY, helper.session());
+ TestCompletionCallback callback;
+ HttpRequestInfo request2;
+ request2.method = "GET";
+ request2.url = GURL("https://www.example.org/foo");
+ int rv = trans2.Start(&request2, callback.callback(), log);
+ EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
+ rv = callback.WaitForResult();
+ EXPECT_THAT(rv, IsOk());
+
+ // Verify second response.
+ const HttpResponseInfo* response = trans2.GetResponseInfo();
+ ASSERT_TRUE(response);
+ EXPECT_EQ(HttpResponseInfo::CONNECTION_INFO_HTTP2, response->connection_info);
+ ASSERT_TRUE(response->headers);
+ EXPECT_EQ("HTTP/1.1 200", response->headers->GetStatusLine());
+ EXPECT_TRUE(response->was_fetched_via_spdy);
+ EXPECT_TRUE(response->was_alpn_negotiated);
+ EXPECT_EQ("127.0.0.1", response->socket_address.host());
+ EXPECT_EQ(443, response->socket_address.port());
+ std::string response_data;
+ rv = ReadTransaction(&trans2, &response_data);
+ EXPECT_THAT(rv, IsOk());
+ EXPECT_EQ("hello!", response_data);
+
+ // Graceful GOAWAY was received, SpdySession should be unavailable.
+ spdy_session = spdy_session_pool->FindAvailableSession(key, GURL(), log);
+ EXPECT_FALSE(spdy_session);
+
+ helper.VerifyDataConsumed();
+}
+
TEST_F(SpdyNetworkTransactionTest, CloseWithActiveStream) {
SpdySerializedFrame req(
spdy_util_.ConstructSpdyGet(nullptr, 0, 1, LOWEST, true));
MockWrite writes[] = {CreateMockWrite(req, 0)};
- SpdySerializedFrame resp(spdy_util_.ConstructSpdyGetReply(NULL, 0, 1));
+ SpdySerializedFrame resp(spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
MockRead reads[] = {
CreateMockRead(resp, 1), MockRead(SYNCHRONOUS, 0, 2) // EOF
};
@@ -3881,7 +4118,7 @@ TEST_F(SpdyNetworkTransactionTest, CloseWithActiveStream) {
SequencedSocketData data(reads, arraysize(reads), writes, arraysize(writes));
NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
- NetLogWithSource(), NULL);
+ NetLogWithSource(), nullptr);
helper.RunPreTestSetup();
helper.AddData(&data);
helper.StartDefaultTest();
@@ -4087,7 +4324,7 @@ TEST_F(SpdyNetworkTransactionTest, ProxyConnect) {
const char kHTTP200[] = {"HTTP/1.1 200 OK\r\n\r\n"};
SpdySerializedFrame req(
spdy_util_.ConstructSpdyGet(nullptr, 0, 1, LOWEST, true));
- SpdySerializedFrame resp(spdy_util_.ConstructSpdyGetReply(NULL, 0, 1));
+ SpdySerializedFrame resp(spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
SpdySerializedFrame body(spdy_util_.ConstructSpdyDataFrame(1, true));
MockWrite writes[] = {
@@ -4149,7 +4386,7 @@ TEST_F(SpdyNetworkTransactionTest, DirectConnectProxyReconnect) {
CreateMockWrite(req, 0),
};
- SpdySerializedFrame resp(spdy_util_.ConstructSpdyGetReply(NULL, 0, 1));
+ SpdySerializedFrame resp(spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
SpdySerializedFrame body(spdy_util_.ConstructSpdyDataFrame(1, true));
MockRead reads[] = {
CreateMockRead(resp, 1), CreateMockRead(body, 2),
@@ -4199,7 +4436,7 @@ TEST_F(SpdyNetworkTransactionTest, DirectConnectProxyReconnect) {
const char kHTTP200[] = {"HTTP/1.1 200 OK\r\n\r\n"};
SpdySerializedFrame req2(spdy_util_2.ConstructSpdyGet(
GetDefaultUrlWithPath("/foo.dat").c_str(), 1, LOWEST));
- SpdySerializedFrame resp2(spdy_util_2.ConstructSpdyGetReply(NULL, 0, 1));
+ SpdySerializedFrame resp2(spdy_util_2.ConstructSpdyGetReply(nullptr, 0, 1));
SpdySerializedFrame body2(spdy_util_2.ConstructSpdyDataFrame(1, true));
MockWrite writes2[] = {
@@ -4252,7 +4489,7 @@ TEST_F(SpdyNetworkTransactionTest, DirectConnectProxyReconnect) {
// This can happen when a server reboots without saying goodbye, or when
// we're behind a NAT that masked the RST.
TEST_F(SpdyNetworkTransactionTest, VerifyRetryOnConnectionReset) {
- SpdySerializedFrame resp(spdy_util_.ConstructSpdyGetReply(NULL, 0, 1));
+ SpdySerializedFrame resp(spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
SpdySerializedFrame body(spdy_util_.ConstructSpdyDataFrame(1, true));
MockRead reads[] = {
CreateMockRead(resp, 1), CreateMockRead(body, 2),
@@ -4293,7 +4530,7 @@ TEST_F(SpdyNetworkTransactionTest, VerifyRetryOnConnectionReset) {
arraysize(writes2));
NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
- NetLogWithSource(), NULL);
+ NetLogWithSource(), nullptr);
helper.AddData(&data1);
helper.AddData(&data2);
helper.RunPreTestSetup();
@@ -4362,15 +4599,17 @@ TEST_F(SpdyNetworkTransactionTest, SpdyBasicAuth) {
"Basic realm=\"MyRealm\""
};
SpdySerializedFrame resp_authentication(spdy_util_.ConstructSpdyReplyError(
- "401 Authentication Required", kExtraAuthenticationHeaders,
+ "401", kExtraAuthenticationHeaders,
arraysize(kExtraAuthenticationHeaders) / 2, 1));
SpdySerializedFrame body_authentication(
spdy_util_.ConstructSpdyDataFrame(1, true));
- SpdySerializedFrame resp_data(spdy_util_.ConstructSpdyGetReply(NULL, 0, 3));
+ SpdySerializedFrame resp_data(
+ spdy_util_.ConstructSpdyGetReply(nullptr, 0, 3));
SpdySerializedFrame body_data(spdy_util_.ConstructSpdyDataFrame(3, true));
+
MockRead spdy_reads[] = {
CreateMockRead(resp_authentication, 1),
- CreateMockRead(body_authentication, 2),
+ CreateMockRead(body_authentication, 2, SYNCHRONOUS),
CreateMockRead(resp_data, 4),
CreateMockRead(body_data, 5),
MockRead(ASYNC, 0, 6),
@@ -4380,7 +4619,7 @@ TEST_F(SpdyNetworkTransactionTest, SpdyBasicAuth) {
arraysize(spdy_writes));
HttpRequestInfo request(CreateGetRequest());
NormalSpdyTransactionHelper helper(request, DEFAULT_PRIORITY,
- NetLogWithSource(), NULL);
+ NetLogWithSource(), nullptr);
helper.RunPreTestSetup();
helper.AddData(&data);
@@ -4418,14 +4657,16 @@ TEST_F(SpdyNetworkTransactionTest, SpdyBasicAuth) {
ASSERT_TRUE(response_restart);
ASSERT_TRUE(response_restart->headers);
EXPECT_EQ(200, response_restart->headers->response_code());
- EXPECT_TRUE(response_restart->auth_challenge.get() == NULL);
+ EXPECT_TRUE(response_restart->auth_challenge.get() == nullptr);
}
TEST_F(SpdyNetworkTransactionTest, ServerPushWithHeaders) {
SpdySerializedFrame stream1_syn(
spdy_util_.ConstructSpdyGet(nullptr, 0, 1, LOWEST, true));
+ SpdySerializedFrame stream2_priority(
+ spdy_util_.ConstructSpdyPriority(2, 1, IDLE, true));
MockWrite writes[] = {
- CreateMockWrite(stream1_syn, 0),
+ CreateMockWrite(stream1_syn, 0), CreateMockWrite(stream2_priority, 3),
};
SpdySerializedFrame stream1_reply(
@@ -4452,10 +4693,10 @@ TEST_F(SpdyNetworkTransactionTest, ServerPushWithHeaders) {
MockRead reads[] = {
CreateMockRead(stream1_reply, 1),
CreateMockRead(stream2_syn, 2),
- CreateMockRead(stream2_headers, 3),
- CreateMockRead(stream1_body, 4, SYNCHRONOUS),
- CreateMockRead(stream2_body, 5),
- MockRead(SYNCHRONOUS, ERR_IO_PENDING, 6), // Force a pause
+ CreateMockRead(stream2_headers, 4),
+ CreateMockRead(stream1_body, 5, SYNCHRONOUS),
+ CreateMockRead(stream2_body, 6),
+ MockRead(SYNCHRONOUS, ERR_IO_PENDING, 7), // Force a pause
};
HttpResponseInfo response;
@@ -4480,8 +4721,11 @@ TEST_F(SpdyNetworkTransactionTest, ServerPushClaimBeforeHeaders) {
// We push a stream and attempt to claim it before the headers come down.
SpdySerializedFrame stream1_syn(
spdy_util_.ConstructSpdyGet(nullptr, 0, 1, LOWEST, true));
+ SpdySerializedFrame stream2_priority(
+ spdy_util_.ConstructSpdyPriority(2, 1, IDLE, true));
MockWrite writes[] = {
CreateMockWrite(stream1_syn, 0, SYNCHRONOUS),
+ CreateMockWrite(stream2_priority, 3),
};
SpdySerializedFrame stream1_reply(
@@ -4502,9 +4746,9 @@ TEST_F(SpdyNetworkTransactionTest, ServerPushClaimBeforeHeaders) {
2, kPushedData, strlen(kPushedData), true));
MockRead reads[] = {
CreateMockRead(stream1_reply, 1), CreateMockRead(stream2_syn, 2),
- CreateMockRead(stream1_body, 3), MockRead(ASYNC, ERR_IO_PENDING, 4),
- CreateMockRead(stream2_headers, 5), CreateMockRead(stream2_body, 6),
- MockRead(ASYNC, ERR_IO_PENDING, 7), MockRead(ASYNC, 0, 8), // EOF
+ CreateMockRead(stream1_body, 4), MockRead(ASYNC, ERR_IO_PENDING, 5),
+ CreateMockRead(stream2_headers, 6), CreateMockRead(stream2_body, 7),
+ MockRead(ASYNC, ERR_IO_PENDING, 8), MockRead(ASYNC, 0, 9), // EOF
};
HttpResponseInfo response;
@@ -4513,7 +4757,7 @@ TEST_F(SpdyNetworkTransactionTest, ServerPushClaimBeforeHeaders) {
SequencedSocketData data(reads, arraysize(reads), writes, arraysize(writes));
NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
- NetLogWithSource(), NULL);
+ NetLogWithSource(), nullptr);
helper.AddData(&data);
helper.RunPreTestSetup();
@@ -4578,220 +4822,6 @@ TEST_F(SpdyNetworkTransactionTest, ServerPushClaimBeforeHeaders) {
EXPECT_TRUE(data.AllWriteDataConsumed());
}
-// TODO(baranovich): HTTP 2 does not allow multiple HEADERS frames
-TEST_F(SpdyNetworkTransactionTest, ServerPushWithTwoHeaderFrames) {
- // We push a stream and attempt to claim it before the headers come down.
- SpdySerializedFrame stream1_syn(
- spdy_util_.ConstructSpdyGet(nullptr, 0, 1, LOWEST, true));
- MockWrite writes[] = {
- CreateMockWrite(stream1_syn, 0, SYNCHRONOUS),
- };
-
- SpdySerializedFrame stream1_reply(
- spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
-
- SpdyHeaderBlock initial_headers;
- spdy_util_.AddUrlToHeaderBlock(GetDefaultUrlWithPath("/foo.dat"),
- &initial_headers);
- SpdySerializedFrame stream2_syn(spdy_util_.ConstructInitialSpdyPushFrame(
- std::move(initial_headers), 2, 1));
-
- SpdySerializedFrame stream1_body(spdy_util_.ConstructSpdyDataFrame(1, true));
-
- SpdyHeaderBlock middle_headers;
- middle_headers["hello"] = "bye";
- SpdySerializedFrame stream2_headers1(spdy_util_.ConstructSpdyResponseHeaders(
- 2, std::move(middle_headers), false));
-
- SpdyHeaderBlock late_headers;
- late_headers[spdy_util_.GetStatusKey()] = "200";
- SpdySerializedFrame stream2_headers2(spdy_util_.ConstructSpdyResponseHeaders(
- 2, std::move(late_headers), false));
-
- const char kPushedData[] = "pushed";
- SpdySerializedFrame stream2_body(spdy_util_.ConstructSpdyDataFrame(
- 2, kPushedData, strlen(kPushedData), true));
-
- MockRead reads[] = {
- CreateMockRead(stream1_reply, 1), CreateMockRead(stream2_syn, 2),
- CreateMockRead(stream1_body, 3), MockRead(ASYNC, ERR_IO_PENDING, 4),
- CreateMockRead(stream2_headers1, 5),
- // This is needed to work around https://crbug.com/571102.
- MockRead(ASYNC, ERR_IO_PENDING, 6), CreateMockRead(stream2_headers2, 7),
- CreateMockRead(stream2_body, 8), MockRead(ASYNC, ERR_IO_PENDING, 9),
- MockRead(ASYNC, 0, 10), // EOF
- };
-
- HttpResponseInfo response;
- HttpResponseInfo response2;
- std::string expected_push_result("pushed");
- SequencedSocketData data(reads, arraysize(reads), writes, arraysize(writes));
-
- NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
- NetLogWithSource(), NULL);
- helper.AddData(&data);
- helper.RunPreTestSetup();
-
- HttpNetworkTransaction* trans = helper.trans();
-
- // Start the transaction.
- TestCompletionCallback callback;
- int rv = trans->Start(&CreateGetRequest(), callback.callback(),
- NetLogWithSource());
- EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
- // Run until we've received the primary HEADERS, the pushed HEADERS,
- // the first HEADERS frame, and the body of the primary stream, but before
- // we've received the final HEADERS for the pushed stream.
- data.RunUntilPaused();
- EXPECT_EQ(0, callback.WaitForResult());
-
- // Request the pushed path. At this point, we've received the push, but the
- // headers are not yet complete.
- HttpNetworkTransaction trans2(DEFAULT_PRIORITY, helper.session());
- rv = trans2.Start(&CreateGetPushRequest(), callback.callback(),
- NetLogWithSource());
- EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
- data.Resume();
- data.RunUntilPaused();
- base::RunLoop().RunUntilIdle();
- // This is needed to work around https://crbug.com/571102.
- data.Resume();
- data.RunUntilPaused();
- base::RunLoop().RunUntilIdle();
-
- // Read the server push body.
- std::string result2;
- ReadResult(&trans2, &result2);
- // Read the response body.
- std::string result;
- ReadResult(trans, &result);
-
- // Verify that the received push data is same as the expected push data.
- EXPECT_EQ(expected_push_result, result2);
-
- // Verify the response headers.
- // Copy the response info, because trans goes away.
- response = *trans->GetResponseInfo();
- response2 = *trans2.GetResponseInfo();
-
- VerifyStreamsClosed(helper);
-
- // Verify the response headers.
- EXPECT_TRUE(response.headers);
- EXPECT_EQ("HTTP/1.1 200", response.headers->GetStatusLine());
-
- // Verify the pushed stream.
- EXPECT_TRUE(response2.headers);
- EXPECT_EQ("HTTP/1.1 200", response2.headers->GetStatusLine());
-
- // Verify we got all the headers from all header blocks.
- EXPECT_TRUE(response2.headers->HasHeaderValue("hello", "bye"));
- EXPECT_TRUE(response2.headers->HasHeaderValue("status", "200"));
-
- // Read the final EOF (which will close the session)
- data.Resume();
- base::RunLoop().RunUntilIdle();
-
- // Verify that we consumed all test data.
- EXPECT_TRUE(data.AllReadDataConsumed());
- EXPECT_TRUE(data.AllWriteDataConsumed());
-}
-
-TEST_F(SpdyNetworkTransactionTest, ServerPushWithNoStatusHeaderFrames) {
- // We push a stream and attempt to claim it before the headers come down.
- SpdySerializedFrame stream1_syn(
- spdy_util_.ConstructSpdyGet(nullptr, 0, 1, LOWEST, true));
- MockWrite writes[] = {
- CreateMockWrite(stream1_syn, 0, SYNCHRONOUS),
- };
-
- SpdySerializedFrame stream1_reply(
- spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
-
- SpdyHeaderBlock initial_headers;
- spdy_util_.AddUrlToHeaderBlock(GetDefaultUrlWithPath("/foo.dat"),
- &initial_headers);
- SpdySerializedFrame stream2_syn(spdy_util_.ConstructInitialSpdyPushFrame(
- std::move(initial_headers), 2, 1));
-
- SpdySerializedFrame stream1_body(spdy_util_.ConstructSpdyDataFrame(1, true));
-
- SpdyHeaderBlock middle_headers;
- middle_headers["hello"] = "bye";
- SpdySerializedFrame stream2_headers1(spdy_util_.ConstructSpdyResponseHeaders(
- 2, std::move(middle_headers), false));
-
- const char kPushedData[] = "pushed";
- SpdySerializedFrame stream2_body(spdy_util_.ConstructSpdyDataFrame(
- 2, kPushedData, strlen(kPushedData), true));
-
- MockRead reads[] = {
- CreateMockRead(stream1_reply, 1), CreateMockRead(stream2_syn, 2),
- CreateMockRead(stream1_body, 3), MockRead(ASYNC, ERR_IO_PENDING, 4),
- CreateMockRead(stream2_headers1, 5), CreateMockRead(stream2_body, 6),
- MockRead(ASYNC, ERR_IO_PENDING, 7), MockRead(ASYNC, 0, 8), // EOF
- };
-
- SequencedSocketData data(reads, arraysize(reads), writes, arraysize(writes));
-
- NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
- NetLogWithSource(), NULL);
- helper.AddData(&data);
- helper.RunPreTestSetup();
-
- HttpNetworkTransaction* trans = helper.trans();
-
- // Start the transaction.
- TestCompletionCallback callback;
- int rv = trans->Start(&CreateGetRequest(), callback.callback(),
- NetLogWithSource());
- EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
- // Run until we've received the primary HEADERS, the pushed HEADERS,
- // the first HEADERS frame, and the body of the primary stream, but before
- // we've received the final HEADERS for the pushed stream.
- data.RunUntilPaused();
- EXPECT_EQ(0, callback.WaitForResult());
-
- // Request the pushed path. At this point, we've received the push, but the
- // headers are not yet complete.
- HttpNetworkTransaction trans2(DEFAULT_PRIORITY, helper.session());
- rv = trans2.Start(&CreateGetPushRequest(), callback.callback(),
- NetLogWithSource());
- EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
- data.Resume();
- data.RunUntilPaused();
- base::RunLoop().RunUntilIdle();
-
- // Read the server push body.
- std::string result2;
- ReadResult(&trans2, &result2);
- // Read the response body.
- std::string result;
- ReadResult(trans, &result);
- EXPECT_EQ("hello!", result);
-
- // Verify that we haven't received any push data.
- EXPECT_EQ("", result2);
-
- // Verify the response headers.
- // Copy the response info, because trans goes away.
- HttpResponseInfo response = *trans->GetResponseInfo();
-
- VerifyStreamsClosed(helper);
-
- // Verify the response headers.
- EXPECT_TRUE(response.headers);
- EXPECT_EQ("HTTP/1.1 200", response.headers->GetStatusLine());
-
- // Read the final EOF (which will close the session).
- data.Resume();
- base::RunLoop().RunUntilIdle();
-
- // Verify that we consumed all test data.
- EXPECT_TRUE(data.AllReadDataConsumed());
- EXPECT_TRUE(data.AllWriteDataConsumed());
-}
-
TEST_F(SpdyNetworkTransactionTest, ResponseHeadersTwice) {
SpdySerializedFrame req(
spdy_util_.ConstructSpdyGet(nullptr, 0, 1, LOWEST, true));
@@ -4802,7 +4832,7 @@ TEST_F(SpdyNetworkTransactionTest, ResponseHeadersTwice) {
};
SpdySerializedFrame stream1_reply(
- spdy_util_.ConstructSpdyGetReply(NULL, 0, 1));
+ spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
SpdyHeaderBlock late_headers;
late_headers["hello"] = "bye";
@@ -4816,7 +4846,7 @@ TEST_F(SpdyNetworkTransactionTest, ResponseHeadersTwice) {
SequencedSocketData data(reads, arraysize(reads), writes, arraysize(writes));
NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
- NetLogWithSource(), NULL);
+ NetLogWithSource(), nullptr);
helper.RunToCompletion(&data);
TransactionHelperResult out = helper.output();
EXPECT_THAT(out.rv, IsError(ERR_SPDY_PROTOCOL_ERROR));
@@ -4835,7 +4865,7 @@ TEST_F(SpdyNetworkTransactionTest, SyncReplyDataAfterTrailers) {
};
SpdySerializedFrame stream1_reply(
- spdy_util_.ConstructSpdyGetReply(NULL, 0, 1));
+ spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
SpdySerializedFrame stream1_body(spdy_util_.ConstructSpdyDataFrame(1, false));
SpdyHeaderBlock late_headers;
@@ -4851,7 +4881,7 @@ TEST_F(SpdyNetworkTransactionTest, SyncReplyDataAfterTrailers) {
SequencedSocketData data(reads, arraysize(reads), writes, arraysize(writes));
NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
- NetLogWithSource(), NULL);
+ NetLogWithSource(), nullptr);
helper.RunToCompletion(&data);
TransactionHelperResult out = helper.output();
EXPECT_THAT(out.rv, IsError(ERR_SPDY_PROTOCOL_ERROR));
@@ -4927,7 +4957,7 @@ TEST_F(SpdyNetworkTransactionTest, ServerPushCrossOriginCorrectness) {
std::unique_ptr<TestProxyDelegate> proxy_delegate(new TestProxyDelegate());
proxy_delegate->set_trusted_spdy_proxy(net::ProxyServer::FromURI(
"https://123.45.67.89:443", net::ProxyServer::SCHEME_HTTP));
- session_deps->proxy_delegate.reset(proxy_delegate.release());
+ session_deps->proxy_delegate = std::move(proxy_delegate);
NormalSpdyTransactionHelper helper(
request, DEFAULT_PRIORITY, NetLogWithSource(), std::move(session_deps));
helper.RunPreTestSetup();
@@ -4942,6 +4972,9 @@ TEST_F(SpdyNetworkTransactionTest, ServerPushCrossOriginCorrectness) {
EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
rv = callback.WaitForResult();
+ // Finish async network reads/writes.
+ base::RunLoop().RunUntilIdle();
+
// Read the response body.
std::string result;
ReadResult(trans, &result);
@@ -4971,8 +5004,10 @@ TEST_F(SpdyNetworkTransactionTest, ServerPushValidCrossOrigin) {
SpdySerializedFrame headers(
spdy_util_.ConstructSpdyGet(url_to_fetch, 1, LOWEST));
+ SpdySerializedFrame push_priority(
+ spdy_util_.ConstructSpdyPriority(2, 1, IDLE, true));
MockWrite writes[] = {
- CreateMockWrite(headers, 0),
+ CreateMockWrite(headers, 0), CreateMockWrite(push_priority, 3),
};
SpdySerializedFrame reply(spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
@@ -4984,10 +5019,10 @@ TEST_F(SpdyNetworkTransactionTest, ServerPushValidCrossOrigin) {
2, kPushedData, strlen(kPushedData), true));
MockRead reads[] = {
CreateMockRead(reply, 1),
- CreateMockRead(push, 2),
- CreateMockRead(body, 3),
- CreateMockRead(pushed_body, 4),
- MockRead(SYNCHRONOUS, ERR_IO_PENDING, 5),
+ CreateMockRead(push, 2, SYNCHRONOUS),
+ CreateMockRead(body, 4),
+ CreateMockRead(pushed_body, 5, SYNCHRONOUS),
+ MockRead(SYNCHRONOUS, ERR_IO_PENDING, 6),
};
SequencedSocketData data(reads, arraysize(reads), writes, arraysize(writes));
@@ -5032,9 +5067,6 @@ TEST_F(SpdyNetworkTransactionTest, ServerPushValidCrossOrigin) {
EXPECT_TRUE(spdy_session->unclaimed_pushed_streams_.empty());
EXPECT_EQ(0u, spdy_session->unclaimed_pushed_streams_.size());
- helper.VerifyDataConsumed();
- VerifyStreamsClosed(helper);
-
HttpResponseInfo response = *trans0->GetResponseInfo();
EXPECT_TRUE(response.headers);
EXPECT_EQ("HTTP/1.1 200", response.headers->GetStatusLine());
@@ -5050,6 +5082,10 @@ TEST_F(SpdyNetworkTransactionTest, ServerPushValidCrossOrigin) {
std::string result1;
ReadResult(&trans1, &result1);
EXPECT_EQ(kPushedData, result1);
+
+ base::RunLoop().RunUntilIdle();
+ helper.VerifyDataConsumed();
+ VerifyStreamsClosed(helper);
}
// Verify that push works cross origin, even if there is already a connection
@@ -5081,8 +5117,11 @@ TEST_F(SpdyNetworkTransactionTest, ServerPushValidCrossOriginWithOpenSession) {
SpdySerializedFrame headers1(
spdy_util_1.ConstructSpdyGet(url_to_fetch1, 1, LOWEST));
+ SpdySerializedFrame push_priority(
+ spdy_util_.ConstructSpdyPriority(2, 1, IDLE, true));
MockWrite writes1[] = {
CreateMockWrite(headers1, 0),
+ CreateMockWrite(push_priority, 3, SYNCHRONOUS),
};
SpdySerializedFrame reply1(spdy_util_1.ConstructSpdyGetReply(nullptr, 0, 1));
@@ -5097,10 +5136,10 @@ TEST_F(SpdyNetworkTransactionTest, ServerPushValidCrossOriginWithOpenSession) {
MockRead reads1[] = {
CreateMockRead(reply1, 1),
- CreateMockRead(push, 2),
- CreateMockRead(body1, 3),
- CreateMockRead(pushed_body, 4),
- MockRead(SYNCHRONOUS, ERR_IO_PENDING, 5),
+ CreateMockRead(push, 2, SYNCHRONOUS),
+ CreateMockRead(body1, 4),
+ CreateMockRead(pushed_body, 5, SYNCHRONOUS),
+ MockRead(SYNCHRONOUS, ERR_IO_PENDING, 6),
};
SequencedSocketData data1(reads1, arraysize(reads1), writes1,
@@ -5188,9 +5227,6 @@ TEST_F(SpdyNetworkTransactionTest, ServerPushValidCrossOriginWithOpenSession) {
EXPECT_TRUE(spdy_session1->unclaimed_pushed_streams_.empty());
EXPECT_EQ(0u, spdy_session1->unclaimed_pushed_streams_.size());
- helper.VerifyDataConsumed();
- VerifyStreamsClosed(helper);
-
HttpResponseInfo response0 = *trans0->GetResponseInfo();
EXPECT_TRUE(response0.headers);
EXPECT_EQ("HTTP/1.1 200", response0.headers->GetStatusLine());
@@ -5214,6 +5250,10 @@ TEST_F(SpdyNetworkTransactionTest, ServerPushValidCrossOriginWithOpenSession) {
std::string result2;
ReadResult(&trans2, &result2);
EXPECT_EQ(kPushedData, result2);
+
+ base::RunLoop().RunUntilIdle();
+ helper.VerifyDataConsumed();
+ VerifyStreamsClosed(helper);
}
TEST_F(SpdyNetworkTransactionTest, ServerPushInvalidCrossOrigin) {
@@ -5239,9 +5279,9 @@ TEST_F(SpdyNetworkTransactionTest, ServerPushInvalidCrossOrigin) {
2, kPushedData, strlen(kPushedData), true));
MockRead reads[] = {
CreateMockRead(reply, 1),
- CreateMockRead(push, 2),
+ CreateMockRead(push, 2, SYNCHRONOUS),
CreateMockRead(body, 4),
- CreateMockRead(pushed_body, 5),
+ CreateMockRead(pushed_body, 5, SYNCHRONOUS),
MockRead(SYNCHRONOUS, ERR_IO_PENDING, 6),
};
@@ -5274,7 +5314,7 @@ TEST_F(SpdyNetworkTransactionTest, RetryAfterRefused) {
SpdySerializedFrame refused(
spdy_util_.ConstructSpdyRstStream(1, RST_STREAM_REFUSED_STREAM));
- SpdySerializedFrame resp(spdy_util_.ConstructSpdyGetReply(NULL, 0, 3));
+ SpdySerializedFrame resp(spdy_util_.ConstructSpdyGetReply(nullptr, 0, 3));
SpdySerializedFrame body(spdy_util_.ConstructSpdyDataFrame(3, true));
MockRead reads[] = {
CreateMockRead(refused, 1), CreateMockRead(resp, 3),
@@ -5283,7 +5323,7 @@ TEST_F(SpdyNetworkTransactionTest, RetryAfterRefused) {
SequencedSocketData data(reads, arraysize(reads), writes, arraysize(writes));
NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
- NetLogWithSource(), NULL);
+ NetLogWithSource(), nullptr);
helper.RunPreTestSetup();
helper.AddData(&data);
@@ -5298,6 +5338,9 @@ TEST_F(SpdyNetworkTransactionTest, RetryAfterRefused) {
rv = callback.WaitForResult();
EXPECT_THAT(rv, IsOk());
+ // Finish async network reads.
+ base::RunLoop().RunUntilIdle();
+
// Verify that we consumed all test data.
EXPECT_TRUE(data.AllReadDataConsumed());
EXPECT_TRUE(data.AllWriteDataConsumed());
@@ -5337,11 +5380,11 @@ TEST_F(SpdyNetworkTransactionTest, OutOfOrderHeaders) {
CreateMockWrite(req2, 5), CreateMockWrite(req3, 6),
};
- SpdySerializedFrame resp1(spdy_util_.ConstructSpdyGetReply(NULL, 0, 1));
+ SpdySerializedFrame resp1(spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
SpdySerializedFrame body1(spdy_util_.ConstructSpdyDataFrame(1, true));
- SpdySerializedFrame resp2(spdy_util_.ConstructSpdyGetReply(NULL, 0, 3));
+ SpdySerializedFrame resp2(spdy_util_.ConstructSpdyGetReply(nullptr, 0, 3));
SpdySerializedFrame body2(spdy_util_.ConstructSpdyDataFrame(3, true));
- SpdySerializedFrame resp3(spdy_util_.ConstructSpdyGetReply(NULL, 0, 5));
+ SpdySerializedFrame resp3(spdy_util_.ConstructSpdyGetReply(nullptr, 0, 5));
SpdySerializedFrame body3(spdy_util_.ConstructSpdyDataFrame(5, true));
MockRead reads[] = {
CreateMockRead(resp1, 2), MockRead(ASYNC, ERR_IO_PENDING, 3),
@@ -5352,7 +5395,7 @@ TEST_F(SpdyNetworkTransactionTest, OutOfOrderHeaders) {
SequencedSocketData data(reads, arraysize(reads), writes, arraysize(writes));
NormalSpdyTransactionHelper helper(CreateGetRequest(), LOWEST,
- NetLogWithSource(), NULL);
+ NetLogWithSource(), nullptr);
helper.RunPreTestSetup();
helper.AddData(&data);
@@ -5397,6 +5440,13 @@ TEST_F(SpdyNetworkTransactionTest, OutOfOrderHeaders) {
EXPECT_THAT(callback3.WaitForResult(), IsOk());
helper.VerifyDataConsumed();
+
+ // At this point the test is completed and we need to safely destroy
+ // all allocated structures. Helper stores a transaction that has a
+ // reference to a stack allocated request, which has a short lifetime,
+ // and is accessed during the transaction destruction. We need to delete
+ // the transaction while the request is still a valid object.
+ helper.ResetTrans();
}
// Test that sent data frames and received WINDOW_UPDATE frames change
@@ -5425,7 +5475,8 @@ TEST_F(SpdyNetworkTransactionTest, WindowUpdateReceived) {
std::unique_ptr<std::string> content(
new std::string(kMaxSpdyFrameChunkSize, 'a'));
SpdySerializedFrame req(spdy_util_.ConstructSpdyPost(
- kDefaultUrl, 1, kMaxSpdyFrameChunkSize * kFrameCount, LOWEST, NULL, 0));
+ kDefaultUrl, 1, kMaxSpdyFrameChunkSize * kFrameCount, LOWEST, nullptr,
+ 0));
SpdySerializedFrame body(spdy_util_.ConstructSpdyDataFrame(
1, content->c_str(), content->size(), false));
SpdySerializedFrame body_end(spdy_util_.ConstructSpdyDataFrame(
@@ -5442,7 +5493,7 @@ TEST_F(SpdyNetworkTransactionTest, WindowUpdateReceived) {
spdy_util_.ConstructSpdyWindowUpdate(1, kDeltaWindowSize));
SpdySerializedFrame window_update_dummy(
spdy_util_.ConstructSpdyWindowUpdate(2, kDeltaWindowSize));
- SpdySerializedFrame resp(spdy_util_.ConstructSpdyPostReply(NULL, 0));
+ SpdySerializedFrame resp(spdy_util_.ConstructSpdyPostReply(nullptr, 0));
MockRead reads[] = {
CreateMockRead(window_update_dummy, 3),
CreateMockRead(window_update_dummy, 4),
@@ -5473,7 +5524,7 @@ TEST_F(SpdyNetworkTransactionTest, WindowUpdateReceived) {
request.upload_data_stream = &upload_data_stream;
NormalSpdyTransactionHelper helper(request, DEFAULT_PRIORITY,
- NetLogWithSource(), NULL);
+ NetLogWithSource(), nullptr);
helper.AddData(&data);
helper.RunPreTestSetup();
@@ -5536,12 +5587,10 @@ TEST_F(SpdyNetworkTransactionTest, WindowUpdateSent) {
stream_max_recv_window_size / 2 + kChunkSize;
SettingsMap initial_settings;
- initial_settings[SETTINGS_HEADER_TABLE_SIZE] =
- SettingsFlagsAndValue(SETTINGS_FLAG_NONE, kMaxHeaderTableSize);
+ initial_settings[SETTINGS_HEADER_TABLE_SIZE] = kSpdyMaxHeaderTableSize;
initial_settings[SETTINGS_MAX_CONCURRENT_STREAMS] =
- SettingsFlagsAndValue(SETTINGS_FLAG_NONE, kMaxConcurrentPushedStreams);
- initial_settings[SETTINGS_INITIAL_WINDOW_SIZE] =
- SettingsFlagsAndValue(SETTINGS_FLAG_NONE, stream_max_recv_window_size);
+ kSpdyMaxConcurrentPushedStreams;
+ initial_settings[SETTINGS_INITIAL_WINDOW_SIZE] = stream_max_recv_window_size;
SpdySerializedFrame initial_settings_frame(
spdy_util_.ConstructSpdySettings(initial_settings));
SpdySerializedFrame initial_window_update(
@@ -5563,7 +5612,7 @@ TEST_F(SpdyNetworkTransactionTest, WindowUpdateSent) {
writes.push_back(CreateMockWrite(req, writes.size()));
std::vector<MockRead> reads;
- SpdySerializedFrame resp(spdy_util_.ConstructSpdyGetReply(NULL, 0, 1));
+ SpdySerializedFrame resp(spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
reads.push_back(CreateMockRead(resp, writes.size() + reads.size()));
std::vector<SpdySerializedFrame> body_frames;
@@ -5588,16 +5637,20 @@ TEST_F(SpdyNetworkTransactionTest, WindowUpdateSent) {
SequencedSocketData data(reads.data(), reads.size(), writes.data(),
writes.size());
+ auto session_deps = base::MakeUnique<SpdySessionDependencies>();
+ session_deps->session_max_recv_window_size = session_max_recv_window_size;
+ session_deps->http2_settings[SETTINGS_INITIAL_WINDOW_SIZE] =
+ stream_max_recv_window_size;
+
NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
- NetLogWithSource(), NULL);
+ NetLogWithSource(),
+ std::move(session_deps));
helper.AddData(&data);
helper.RunPreTestSetup();
SpdySessionPool* spdy_session_pool = helper.session()->spdy_session_pool();
SpdySessionPoolPeer pool_peer(spdy_session_pool);
pool_peer.SetEnableSendingInitialData(true);
- pool_peer.SetSessionMaxRecvWindowSize(session_max_recv_window_size);
- pool_peer.SetStreamInitialRecvWindowSize(stream_max_recv_window_size);
HttpNetworkTransaction* trans = helper.trans();
TestCompletionCallback callback;
@@ -5608,6 +5661,9 @@ TEST_F(SpdyNetworkTransactionTest, WindowUpdateSent) {
rv = callback.WaitForResult();
EXPECT_THAT(rv, IsOk());
+ // Finish async network reads.
+ base::RunLoop().RunUntilIdle();
+
SpdyHttpStream* stream =
static_cast<SpdyHttpStream*>(trans->stream_.get());
ASSERT_TRUE(stream);
@@ -5646,7 +5702,8 @@ TEST_F(SpdyNetworkTransactionTest, WindowUpdateOverflow) {
std::unique_ptr<std::string> content(
new std::string(kMaxSpdyFrameChunkSize, 'a'));
SpdySerializedFrame req(spdy_util_.ConstructSpdyPost(
- kDefaultUrl, 1, kMaxSpdyFrameChunkSize * kFrameCount, LOWEST, NULL, 0));
+ kDefaultUrl, 1, kMaxSpdyFrameChunkSize * kFrameCount, LOWEST, nullptr,
+ 0));
SpdySerializedFrame body(spdy_util_.ConstructSpdyDataFrame(
1, content->c_str(), content->size(), false));
SpdySerializedFrame rst(
@@ -5682,7 +5739,7 @@ TEST_F(SpdyNetworkTransactionTest, WindowUpdateOverflow) {
request.upload_data_stream = &upload_data_stream;
NormalSpdyTransactionHelper helper(request, DEFAULT_PRIORITY,
- NetLogWithSource(), NULL);
+ NetLogWithSource(), nullptr);
helper.RunPreTestSetup();
helper.AddData(&data);
HttpNetworkTransaction* trans = helper.trans();
@@ -5732,7 +5789,7 @@ TEST_F(SpdyNetworkTransactionTest, FlowControlStallResume) {
SpdySerializedFrame req(spdy_util_.ConstructSpdyPost(
kDefaultUrl, 1,
/*content_length=*/kBufferSize * num_upload_buffers + kUploadDataSize,
- LOWEST, NULL, 0));
+ LOWEST, nullptr, 0));
// Full frames.
SpdySerializedFrame body1(spdy_util_.ConstructSpdyDataFrame(
@@ -5799,7 +5856,7 @@ TEST_F(SpdyNetworkTransactionTest, FlowControlStallResume) {
writes.push_back(CreateMockWrite(body4, i++));
writes.push_back(CreateMockWrite(body5, i++));
- SpdySerializedFrame reply(spdy_util_.ConstructSpdyPostReply(NULL, 0));
+ SpdySerializedFrame reply(spdy_util_.ConstructSpdyPostReply(nullptr, 0));
reads.push_back(CreateMockRead(reply, i++));
reads.push_back(CreateMockRead(body2, i++));
reads.push_back(CreateMockRead(body5, i++));
@@ -5820,7 +5877,7 @@ TEST_F(SpdyNetworkTransactionTest, FlowControlStallResume) {
request.url = default_url_;
request.upload_data_stream = &upload_data_stream;
NormalSpdyTransactionHelper helper(request, DEFAULT_PRIORITY,
- NetLogWithSource(), NULL);
+ NetLogWithSource(), nullptr);
helper.AddData(&data);
helper.RunPreTestSetup();
@@ -5854,6 +5911,10 @@ TEST_F(SpdyNetworkTransactionTest, FlowControlStallResume) {
data.Resume(); // Read in WINDOW_UPDATE frame.
rv = callback.WaitForResult();
+ EXPECT_THAT(rv, IsOk());
+
+ // Finish async network reads.
+ base::RunLoop().RunUntilIdle();
helper.VerifyDataConsumed();
}
@@ -5878,7 +5939,7 @@ TEST_F(SpdyNetworkTransactionTest, FlowControlStallResumeAfterSettings) {
SpdySerializedFrame req(spdy_util_.ConstructSpdyPost(
kDefaultUrl, 1,
/*content_length=*/kBufferSize * num_upload_buffers + kUploadDataSize,
- LOWEST, NULL, 0));
+ LOWEST, nullptr, 0));
// Full frames.
SpdySerializedFrame body1(spdy_util_.ConstructSpdyDataFrame(
@@ -5933,8 +5994,7 @@ TEST_F(SpdyNetworkTransactionTest, FlowControlStallResumeAfterSettings) {
// Construct read frame for SETTINGS that gives enough space to upload the
// rest of the data.
SettingsMap settings;
- settings[SETTINGS_INITIAL_WINDOW_SIZE] =
- SettingsFlagsAndValue(SETTINGS_FLAG_NONE, initial_window_size * 2);
+ settings[SETTINGS_INITIAL_WINDOW_SIZE] = initial_window_size * 2;
SpdySerializedFrame settings_frame_large(
spdy_util_.ConstructSpdySettings(settings));
@@ -5953,7 +6013,7 @@ TEST_F(SpdyNetworkTransactionTest, FlowControlStallResumeAfterSettings) {
writes.push_back(CreateMockWrite(body4, i++));
writes.push_back(CreateMockWrite(body5, i++));
- SpdySerializedFrame reply(spdy_util_.ConstructSpdyPostReply(NULL, 0));
+ SpdySerializedFrame reply(spdy_util_.ConstructSpdyPostReply(nullptr, 0));
reads.push_back(CreateMockRead(reply, i++));
reads.push_back(CreateMockRead(body2, i++));
reads.push_back(CreateMockRead(body5, i++));
@@ -5976,7 +6036,7 @@ TEST_F(SpdyNetworkTransactionTest, FlowControlStallResumeAfterSettings) {
request.url = default_url_;
request.upload_data_stream = &upload_data_stream;
NormalSpdyTransactionHelper helper(request, DEFAULT_PRIORITY,
- NetLogWithSource(), NULL);
+ NetLogWithSource(), nullptr);
helper.RunPreTestSetup();
helper.AddData(&data);
@@ -6016,8 +6076,8 @@ TEST_F(SpdyNetworkTransactionTest, FlowControlStallResumeAfterSettings) {
rv = callback.WaitForResult();
helper.VerifyDataConsumed();
- // If stream is NULL, that means it was unstalled and closed.
- EXPECT_TRUE(stream->stream() == NULL);
+ // If stream is nullptr, that means it was unstalled and closed.
+ EXPECT_TRUE(stream->stream() == nullptr);
}
// Test we correctly handle the case where the SETTINGS frame results in a
@@ -6041,7 +6101,7 @@ TEST_F(SpdyNetworkTransactionTest, FlowControlNegativeSendWindowSize) {
SpdySerializedFrame req(spdy_util_.ConstructSpdyPost(
kDefaultUrl, 1,
/*content_length=*/kBufferSize * num_upload_buffers + kUploadDataSize,
- LOWEST, NULL, 0));
+ LOWEST, nullptr, 0));
// Full frames.
SpdySerializedFrame body1(spdy_util_.ConstructSpdyDataFrame(
@@ -6095,8 +6155,7 @@ TEST_F(SpdyNetworkTransactionTest, FlowControlNegativeSendWindowSize) {
// Construct read frame for SETTINGS that makes the send_window_size
// negative.
SettingsMap new_settings;
- new_settings[SETTINGS_INITIAL_WINDOW_SIZE] =
- SettingsFlagsAndValue(SETTINGS_FLAG_NONE, initial_window_size / 2);
+ new_settings[SETTINGS_INITIAL_WINDOW_SIZE] = initial_window_size / 2;
SpdySerializedFrame settings_frame_small(
spdy_util_.ConstructSpdySettings(new_settings));
// Construct read frames for WINDOW_UPDATE that makes the send_window_size
@@ -6118,7 +6177,7 @@ TEST_F(SpdyNetworkTransactionTest, FlowControlNegativeSendWindowSize) {
writes.push_back(CreateMockWrite(body4, i++));
writes.push_back(CreateMockWrite(body5, i++));
- SpdySerializedFrame reply(spdy_util_.ConstructSpdyPostReply(NULL, 0));
+ SpdySerializedFrame reply(spdy_util_.ConstructSpdyPostReply(nullptr, 0));
reads.push_back(CreateMockRead(reply, i++));
reads.push_back(CreateMockRead(body2, i++));
reads.push_back(CreateMockRead(body5, i++));
@@ -6141,7 +6200,7 @@ TEST_F(SpdyNetworkTransactionTest, FlowControlNegativeSendWindowSize) {
request.url = default_url_;
request.upload_data_stream = &upload_data_stream;
NormalSpdyTransactionHelper helper(request, DEFAULT_PRIORITY,
- NetLogWithSource(), NULL);
+ NetLogWithSource(), nullptr);
helper.RunPreTestSetup();
helper.AddData(&data);
@@ -6196,7 +6255,7 @@ TEST_F(SpdyNetworkTransactionTest, GoAwayOnOddPushStreamId) {
SequencedSocketData data(reads, arraysize(reads), writes, arraysize(writes));
NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
- NetLogWithSource(), NULL);
+ NetLogWithSource(), nullptr);
helper.RunToCompletion(&data);
TransactionHelperResult out = helper.output();
EXPECT_THAT(out.rv, IsError(ERR_SPDY_PROTOCOL_ERROR));
@@ -6205,28 +6264,31 @@ TEST_F(SpdyNetworkTransactionTest, GoAwayOnOddPushStreamId) {
TEST_F(SpdyNetworkTransactionTest,
GoAwayOnPushStreamIdLesserOrEqualThanLastAccepted) {
SpdySerializedFrame push_a(spdy_util_.ConstructSpdyPush(
- NULL, 0, 4, 1, GetDefaultUrlWithPath("/a.dat").c_str()));
+ nullptr, 0, 4, 1, GetDefaultUrlWithPath("/a.dat").c_str()));
SpdyHeaderBlock push_b_headers;
spdy_util_.AddUrlToHeaderBlock(GetDefaultUrlWithPath("/b.dat"),
&push_b_headers);
SpdySerializedFrame push_b(spdy_util_.ConstructInitialSpdyPushFrame(
std::move(push_b_headers), 2, 1));
MockRead reads[] = {
- CreateMockRead(push_a, 1), CreateMockRead(push_b, 2),
+ CreateMockRead(push_a, 1), CreateMockRead(push_b, 3),
};
SpdySerializedFrame req(
spdy_util_.ConstructSpdyGet(nullptr, 0, 1, LOWEST, true));
+ SpdySerializedFrame priority_a(
+ spdy_util_.ConstructSpdyPriority(4, 1, IDLE, true));
SpdySerializedFrame goaway(spdy_util_.ConstructSpdyGoAway(
4, GOAWAY_PROTOCOL_ERROR,
"New push stream id must be greater than the last accepted."));
MockWrite writes[] = {
- CreateMockWrite(req, 0), CreateMockWrite(goaway, 3),
+ CreateMockWrite(req, 0), CreateMockWrite(priority_a, 2),
+ CreateMockWrite(goaway, 4),
};
SequencedSocketData data(reads, arraysize(reads), writes, arraysize(writes));
NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
- NetLogWithSource(), NULL);
+ NetLogWithSource(), nullptr);
helper.RunToCompletion(&data);
TransactionHelperResult out = helper.output();
EXPECT_THAT(out.rv, IsError(ERR_SPDY_PROTOCOL_ERROR));
@@ -6376,6 +6438,86 @@ TEST_F(SpdyNetworkTransactionTest, RstStreamNoErrorAfterResponse) {
EXPECT_EQ("hello!", out.response_data);
}
+TEST_F(SpdyNetworkTransactionTest, 100Continue) {
+ SpdySerializedFrame req(
+ spdy_util_.ConstructSpdyGet(nullptr, 0, 1, LOWEST, true));
+ MockWrite writes[] = {CreateMockWrite(req, 0)};
+
+ SpdyHeaderBlock informational_headers;
+ informational_headers[spdy_util_.GetStatusKey()] = "100";
+ SpdySerializedFrame informational_response(
+ spdy_util_.ConstructSpdyReply(1, std::move(informational_headers)));
+ SpdySerializedFrame resp(spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
+ SpdySerializedFrame body(spdy_util_.ConstructSpdyDataFrame(1, true));
+ MockRead reads[] = {
+ CreateMockRead(informational_response, 1), CreateMockRead(resp, 2),
+ CreateMockRead(body, 3), MockRead(ASYNC, 0, 4) // EOF
+ };
+
+ SequencedSocketData data(reads, arraysize(reads), writes, arraysize(writes));
+ NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
+ NetLogWithSource(), nullptr);
+ helper.RunToCompletion(&data);
+ TransactionHelperResult out = helper.output();
+ EXPECT_THAT(out.rv, IsOk());
+ EXPECT_EQ("HTTP/1.1 200", out.status_line);
+ EXPECT_EQ("hello!", out.response_data);
+}
+
+// "A server can send a complete response prior to the client sending an entire
+// request if the response does not depend on any portion of the request that
+// has not been sent and received." (RFC7540 Section 8.1)
+// Regression test for https://crbug.com/606990. Server responds before POST
+// data are sent and closes connection: this must result in
+// ERR_CONNECTION_CLOSED (as opposed to ERR_SPDY_PROTOCOL_ERROR).
+TEST_F(SpdyNetworkTransactionTest, ResponseBeforePostDataSent) {
+ SpdySerializedFrame req(spdy_util_.ConstructChunkedSpdyPost(nullptr, 0));
+ MockWrite writes[] = {CreateMockWrite(req, 0)};
+
+ SpdySerializedFrame resp(spdy_util_.ConstructSpdyPostReply(nullptr, 0));
+ SpdySerializedFrame body(spdy_util_.ConstructSpdyDataFrame(1, true));
+ MockRead reads[] = {CreateMockRead(resp, 1), CreateMockRead(body, 2),
+ MockRead(ASYNC, 0, 3)};
+
+ SequencedSocketData data(reads, arraysize(reads), writes, arraysize(writes));
+ NormalSpdyTransactionHelper helper(CreateChunkedPostRequest(),
+ DEFAULT_PRIORITY, NetLogWithSource(),
+ nullptr);
+
+ helper.RunPreTestSetup();
+ helper.AddData(&data);
+ helper.StartDefaultTest();
+ EXPECT_THAT(helper.output().rv, IsError(ERR_IO_PENDING));
+ helper.WaitForCallbackToComplete();
+ EXPECT_THAT(helper.output().rv, IsError(ERR_CONNECTION_CLOSED));
+}
+
+// Regression test for https://crbug.com/606990.
+// Server responds before POST data are sent and resets stream with NO_ERROR.
+TEST_F(SpdyNetworkTransactionTest, ResponseAndRstStreamBeforePostDataSent) {
+ SpdySerializedFrame req(spdy_util_.ConstructChunkedSpdyPost(nullptr, 0));
+ MockWrite writes[] = {CreateMockWrite(req, 0)};
+
+ SpdySerializedFrame resp(spdy_util_.ConstructSpdyPostReply(nullptr, 0));
+ SpdySerializedFrame body(spdy_util_.ConstructSpdyDataFrame(1, true));
+ SpdySerializedFrame rst(
+ spdy_util_.ConstructSpdyRstStream(1, RST_STREAM_NO_ERROR));
+ MockRead reads[] = {CreateMockRead(resp, 1), CreateMockRead(body, 2),
+ CreateMockRead(rst, 3), MockRead(ASYNC, 0, 4)};
+
+ SequencedSocketData data(reads, arraysize(reads), writes, arraysize(writes));
+ NormalSpdyTransactionHelper helper(CreateChunkedPostRequest(),
+ DEFAULT_PRIORITY, NetLogWithSource(),
+ nullptr);
+
+ helper.RunToCompletion(&data);
+
+ TransactionHelperResult out = helper.output();
+ EXPECT_THAT(out.rv, IsOk());
+ EXPECT_EQ("HTTP/1.1 200", out.status_line);
+ EXPECT_EQ("hello!", out.response_data);
+}
+
class SpdyNetworkTransactionTLSUsageCheckTest
: public SpdyNetworkTransactionTest {
protected:
@@ -6385,12 +6527,12 @@ class SpdyNetworkTransactionTLSUsageCheckTest
spdy_util_.ConstructSpdyGoAway(0, GOAWAY_INADEQUATE_SECURITY, ""));
MockWrite writes[] = {CreateMockWrite(goaway)};
- StaticSocketDataProvider data(NULL, 0, writes, arraysize(writes));
+ StaticSocketDataProvider data(nullptr, 0, writes, arraysize(writes));
HttpRequestInfo request;
request.method = "GET";
request.url = default_url_;
NormalSpdyTransactionHelper helper(request, DEFAULT_PRIORITY,
- NetLogWithSource(), NULL);
+ NetLogWithSource(), nullptr);
helper.RunToCompletionWithSSLData(&data, std::move(ssl_provider));
TransactionHelperResult out = helper.output();
EXPECT_THAT(out.rv, IsError(ERR_SPDY_INADEQUATE_TRANSPORT_SECURITY));
diff --git a/chromium/net/spdy/spdy_no_op_visitor.h b/chromium/net/spdy/spdy_no_op_visitor.h
index 17ea7bb28bc..cd3d4951e80 100644
--- a/chromium/net/spdy/spdy_no_op_visitor.h
+++ b/chromium/net/spdy/spdy_no_op_visitor.h
@@ -24,12 +24,6 @@ class SpdyNoOpVisitor : public SpdyFramerVisitorInterface,
// SpdyFramerVisitorInterface methods:
void OnError(SpdyFramer* framer) override {}
- void OnSynStream(SpdyStreamId stream_id,
- SpdyStreamId associated_stream_id,
- SpdyPriority priority,
- bool fin,
- bool unidirectional) override {}
- void OnSynReply(SpdyStreamId stream_id, bool fin) override {}
net::SpdyHeadersHandlerInterface* OnHeaderFrameStart(
SpdyStreamId stream_id) override;
void OnHeaderFrameEnd(SpdyStreamId stream_id, bool end_headers) override {}
@@ -43,7 +37,7 @@ class SpdyNoOpVisitor : public SpdyFramerVisitorInterface,
void OnStreamPadding(SpdyStreamId stream_id, size_t len) override {}
void OnRstStream(SpdyStreamId stream_id,
SpdyRstStreamStatus status) override {}
- void OnSetting(SpdySettingsIds id, uint8_t flags, uint32_t value) override {}
+ void OnSetting(SpdySettingsIds id, uint32_t value) override {}
void OnPing(SpdyPingId unique_id, bool is_ack) override {}
void OnSettingsEnd() override {}
void OnSettingsAck() override {}
diff --git a/chromium/net/spdy/spdy_protocol.cc b/chromium/net/spdy/spdy_protocol.cc
index 1cf98811424..1c9254e3045 100644
--- a/chromium/net/spdy/spdy_protocol.cc
+++ b/chromium/net/spdy/spdy_protocol.cc
@@ -45,179 +45,51 @@ SpdyPriority Http2WeightToSpdy3Priority(int weight) {
return static_cast<SpdyPriority>(7.f - (weight - 1) / kSteps);
}
-bool SpdyConstants::IsValidFrameType(SpdyMajorVersion version,
- int frame_type_field) {
- switch (version) {
- case SPDY3:
- // SYN_STREAM is the first valid frame.
- if (frame_type_field < SerializeFrameType(version, SYN_STREAM)) {
- return false;
- }
-
- // WINDOW_UPDATE is the last valid frame.
- if (frame_type_field > SerializeFrameType(version, WINDOW_UPDATE)) {
- return false;
- }
-
- return true;
- case HTTP2:
- // Check for recognized extensions.
- if (frame_type_field == SerializeFrameType(version, ALTSVC) ||
- frame_type_field == SerializeFrameType(version, BLOCKED)) {
- return true;
- }
-
- // DATA is the first valid frame.
- if (frame_type_field < SerializeFrameType(version, DATA)) {
- return false;
- }
-
- // CONTINUATION is the last valid frame.
- if (frame_type_field > SerializeFrameType(version, CONTINUATION)) {
- return false;
- }
-
- return true;
- }
-
- SPDY_BUG << "Unhandled SPDY version " << version;
- return false;
-}
-
-SpdyFrameType SpdyConstants::ParseFrameType(SpdyMajorVersion version,
- int frame_type_field) {
- switch (version) {
- case SPDY3:
- switch (frame_type_field) {
- case 1:
- return SYN_STREAM;
- case 2:
- return SYN_REPLY;
- case 3:
- return RST_STREAM;
- case 4:
- return SETTINGS;
- case 6:
- return PING;
- case 7:
- return GOAWAY;
- case 8:
- return HEADERS;
- case 9:
- return WINDOW_UPDATE;
- }
- break;
- case HTTP2:
- switch (frame_type_field) {
- case 0:
- return DATA;
- case 1:
- return HEADERS;
- case 2:
- return PRIORITY;
- case 3:
- return RST_STREAM;
- case 4:
- return SETTINGS;
- case 5:
- return PUSH_PROMISE;
- case 6:
- return PING;
- case 7:
- return GOAWAY;
- case 8:
- return WINDOW_UPDATE;
- case 9:
- return CONTINUATION;
- case 10:
- return ALTSVC;
- case 11:
- return BLOCKED;
- }
- break;
- }
-
- SPDY_BUG << "Unhandled frame type " << frame_type_field;
- return DATA;
-}
-
-int SpdyConstants::SerializeFrameType(SpdyMajorVersion version,
- SpdyFrameType frame_type) {
- switch (version) {
- case SPDY3:
- switch (frame_type) {
- case SYN_STREAM:
- return 1;
- case SYN_REPLY:
- return 2;
- case RST_STREAM:
- return 3;
- case SETTINGS:
- return 4;
- case PING:
- return 6;
- case GOAWAY:
- return 7;
- case HEADERS:
- return 8;
- case WINDOW_UPDATE:
- return 9;
- default:
- SPDY_BUG << "Serializing unhandled frame type " << frame_type;
- return -1;
- }
- case HTTP2:
- switch (frame_type) {
- case DATA:
- return 0;
- case HEADERS:
- return 1;
- case PRIORITY:
- return 2;
- case RST_STREAM:
- return 3;
- case SETTINGS:
- return 4;
- case PUSH_PROMISE:
- return 5;
- case PING:
- return 6;
- case GOAWAY:
- return 7;
- case WINDOW_UPDATE:
- return 8;
- case CONTINUATION:
- return 9;
- // ALTSVC and BLOCKED are extensions.
- case ALTSVC:
- return 10;
- case BLOCKED:
- return 11;
- default:
- SPDY_BUG << "Serializing unhandled frame type " << frame_type;
- return -1;
- }
- }
-
- SPDY_BUG << "Unhandled SPDY version " << version;
- return -1;
-}
-
-int SpdyConstants::DataFrameType(SpdyMajorVersion version) {
- switch (version) {
- case SPDY3:
- return 0;
- case HTTP2:
- return SerializeFrameType(version, DATA);
+bool IsValidFrameType(int frame_type_field) {
+ return frame_type_field >= MIN_FRAME_TYPE &&
+ frame_type_field <= MAX_FRAME_TYPE;
+}
+
+SpdyFrameType ParseFrameType(int frame_type_field) {
+ SPDY_BUG_IF(!IsValidFrameType(frame_type_field)) << "Invalid frame type.";
+ return static_cast<SpdyFrameType>(frame_type_field);
+}
+
+int SerializeFrameType(SpdyFrameType frame_type) {
+ switch (frame_type) {
+ case DATA:
+ return kDataFrameType;
+ case HEADERS:
+ return 1;
+ case PRIORITY:
+ return 2;
+ case RST_STREAM:
+ return 3;
+ case SETTINGS:
+ return 4;
+ case PUSH_PROMISE:
+ return 5;
+ case PING:
+ return 6;
+ case GOAWAY:
+ return 7;
+ case WINDOW_UPDATE:
+ return 8;
+ case CONTINUATION:
+ return 9;
+ // ALTSVC and BLOCKED are extensions.
+ case ALTSVC:
+ return 10;
+ case BLOCKED:
+ return 11;
+ default:
+ SPDY_BUG << "Serializing unhandled frame type " << frame_type;
+ return -1;
}
-
- SPDY_BUG << "Unhandled SPDY version " << version;
- return 0;
}
-bool SpdyConstants::IsValidHTTP2FrameStreamId(
- SpdyStreamId current_frame_stream_id,
- SpdyFrameType frame_type_field) {
+bool IsValidHTTP2FrameStreamId(SpdyStreamId current_frame_stream_id,
+ SpdyFrameType frame_type_field) {
if (current_frame_stream_id == 0) {
switch (frame_type_field) {
case DATA:
@@ -244,508 +116,225 @@ bool SpdyConstants::IsValidHTTP2FrameStreamId(
}
}
-bool SpdyConstants::IsValidSettingId(SpdyMajorVersion version,
- int setting_id_field) {
- switch (version) {
- case SPDY3:
- // UPLOAD_BANDWIDTH is the first valid setting id.
- if (setting_id_field <
- SerializeSettingId(version, SETTINGS_UPLOAD_BANDWIDTH)) {
- return false;
- }
-
- // INITIAL_WINDOW_SIZE is the last valid setting id.
- if (setting_id_field >
- SerializeSettingId(version, SETTINGS_INITIAL_WINDOW_SIZE)) {
- return false;
- }
+bool ParseSettingsId(int wire_setting_id, SpdySettingsIds* setting_id) {
+ // HEADER_TABLE_SIZE is the first defined setting id.
+ if (wire_setting_id < SETTINGS_MIN) {
+ return false;
+ }
- return true;
- case HTTP2:
- // HEADER_TABLE_SIZE is the first valid setting id.
- if (setting_id_field <
- SerializeSettingId(version, SETTINGS_HEADER_TABLE_SIZE)) {
- return false;
- }
+ // MAX_HEADER_LIST_SIZE is the last defined setting id.
+ if (wire_setting_id > SETTINGS_MAX) {
+ return false;
+ }
- // MAX_HEADER_LIST_SIZE is the last valid setting id.
- if (setting_id_field >
- SerializeSettingId(version, SETTINGS_MAX_HEADER_LIST_SIZE)) {
- return false;
- }
+ *setting_id = static_cast<SpdySettingsIds>(wire_setting_id);
+ return true;
+}
+bool SettingsIdToString(SpdySettingsIds id, const char** settings_id_string) {
+ switch (id) {
+ case SETTINGS_HEADER_TABLE_SIZE:
+ *settings_id_string = "SETTINGS_HEADER_TABLE_SIZE";
+ return true;
+ case SETTINGS_ENABLE_PUSH:
+ *settings_id_string = "SETTINGS_ENABLE_PUSH";
+ return true;
+ case SETTINGS_MAX_CONCURRENT_STREAMS:
+ *settings_id_string = "SETTINGS_MAX_CONCURRENT_STREAMS";
+ return true;
+ case SETTINGS_INITIAL_WINDOW_SIZE:
+ *settings_id_string = "SETTINGS_INITIAL_WINDOW_SIZE";
+ return true;
+ case SETTINGS_MAX_FRAME_SIZE:
+ *settings_id_string = "SETTINGS_MAX_FRAME_SIZE";
+ return true;
+ case SETTINGS_MAX_HEADER_LIST_SIZE:
+ *settings_id_string = "SETTINGS_MAX_HEADER_LIST_SIZE";
return true;
}
- SPDY_BUG << "Unhandled SPDY version " << version;
+ *settings_id_string = "SETTINGS_UNKNOWN";
return false;
}
-SpdySettingsIds SpdyConstants::ParseSettingId(SpdyMajorVersion version,
- int setting_id_field) {
- switch (version) {
- case SPDY3:
- switch (setting_id_field) {
- case 1:
- return SETTINGS_UPLOAD_BANDWIDTH;
- case 2:
- return SETTINGS_DOWNLOAD_BANDWIDTH;
- case 3:
- return SETTINGS_ROUND_TRIP_TIME;
- case 4:
- return SETTINGS_MAX_CONCURRENT_STREAMS;
- case 5:
- return SETTINGS_CURRENT_CWND;
- case 6:
- return SETTINGS_DOWNLOAD_RETRANS_RATE;
- case 7:
- return SETTINGS_INITIAL_WINDOW_SIZE;
- }
- break;
- case HTTP2:
- switch (setting_id_field) {
- case 1:
- return SETTINGS_HEADER_TABLE_SIZE;
- case 2:
- return SETTINGS_ENABLE_PUSH;
- case 3:
- return SETTINGS_MAX_CONCURRENT_STREAMS;
- case 4:
- return SETTINGS_INITIAL_WINDOW_SIZE;
- case 5:
- return SETTINGS_MAX_FRAME_SIZE;
- case 6:
- return SETTINGS_MAX_HEADER_LIST_SIZE;
- }
- break;
+bool IsValidRstStreamStatus(int rst_stream_status_field) {
+ // NO_ERROR is the first valid status code.
+ if (rst_stream_status_field < SerializeRstStreamStatus(RST_STREAM_NO_ERROR)) {
+ return false;
}
- SPDY_BUG << "Unhandled setting ID " << setting_id_field;
- return SETTINGS_UPLOAD_BANDWIDTH;
-}
-
-int SpdyConstants::SerializeSettingId(SpdyMajorVersion version,
- SpdySettingsIds id) {
- switch (version) {
- case SPDY3:
- switch (id) {
- case SETTINGS_UPLOAD_BANDWIDTH:
- return 1;
- case SETTINGS_DOWNLOAD_BANDWIDTH:
- return 2;
- case SETTINGS_ROUND_TRIP_TIME:
- return 3;
- case SETTINGS_MAX_CONCURRENT_STREAMS:
- return 4;
- case SETTINGS_CURRENT_CWND:
- return 5;
- case SETTINGS_DOWNLOAD_RETRANS_RATE:
- return 6;
- case SETTINGS_INITIAL_WINDOW_SIZE:
- return 7;
- default:
- SPDY_BUG << "Serializing unhandled setting id " << id;
- return -1;
- }
- case HTTP2:
- switch (id) {
- case SETTINGS_HEADER_TABLE_SIZE:
- return 1;
- case SETTINGS_ENABLE_PUSH:
- return 2;
- case SETTINGS_MAX_CONCURRENT_STREAMS:
- return 3;
- case SETTINGS_INITIAL_WINDOW_SIZE:
- return 4;
- case SETTINGS_MAX_FRAME_SIZE:
- return 5;
- case SETTINGS_MAX_HEADER_LIST_SIZE:
- return 6;
- default:
- SPDY_BUG << "Serializing unhandled setting id " << id;
- return -1;
- }
+ // TODO(hkhalil): Omit COMPRESSION_ERROR and SETTINGS_TIMEOUT
+ /*
+ // This works because GOAWAY and RST_STREAM share a namespace.
+ if (rst_stream_status_field ==
+ SerializeGoAwayStatus(version, GOAWAY_COMPRESSION_ERROR) ||
+ rst_stream_status_field ==
+ SerializeGoAwayStatus(version, GOAWAY_SETTINGS_TIMEOUT)) {
+ return false;
}
- SPDY_BUG << "Unhandled SPDY version " << version;
- return -1;
-}
-
-bool SpdyConstants::IsValidRstStreamStatus(SpdyMajorVersion version,
- int rst_stream_status_field) {
- switch (version) {
- case SPDY3:
- // PROTOCOL_ERROR is the valid first status code.
- if (rst_stream_status_field <
- SerializeRstStreamStatus(version, RST_STREAM_PROTOCOL_ERROR)) {
- return false;
- }
-
- // FRAME_TOO_LARGE is the valid last status code.
- if (rst_stream_status_field >
- SerializeRstStreamStatus(version, RST_STREAM_FRAME_TOO_LARGE)) {
- return false;
- }
-
- return true;
- case HTTP2:
- // NO_ERROR is the first valid status code.
- if (rst_stream_status_field <
- SerializeRstStreamStatus(version, RST_STREAM_NO_ERROR)) {
- return false;
- }
-
- // TODO(hkhalil): Omit COMPRESSION_ERROR and SETTINGS_TIMEOUT
- /*
- // This works because GOAWAY and RST_STREAM share a namespace.
- if (rst_stream_status_field ==
- SerializeGoAwayStatus(version, GOAWAY_COMPRESSION_ERROR) ||
- rst_stream_status_field ==
- SerializeGoAwayStatus(version, GOAWAY_SETTINGS_TIMEOUT)) {
- return false;
- }
- */
+ */
- // HTTP_1_1_REQUIRED is the last valid status code.
- if (rst_stream_status_field >
- SerializeRstStreamStatus(version, RST_STREAM_HTTP_1_1_REQUIRED)) {
- return false;
- }
-
- return true;
+ // HTTP_1_1_REQUIRED is the last valid status code.
+ if (rst_stream_status_field >
+ SerializeRstStreamStatus(RST_STREAM_HTTP_1_1_REQUIRED)) {
+ return false;
}
- SPDY_BUG << "Unhandled SPDY version " << version;
- return false;
-}
-SpdyRstStreamStatus SpdyConstants::ParseRstStreamStatus(
- SpdyMajorVersion version,
- int rst_stream_status_field) {
- switch (version) {
- case SPDY3:
- switch (rst_stream_status_field) {
- case 1:
- return RST_STREAM_PROTOCOL_ERROR;
- case 2:
- return RST_STREAM_INVALID_STREAM;
- case 3:
- return RST_STREAM_REFUSED_STREAM;
- case 4:
- return RST_STREAM_UNSUPPORTED_VERSION;
- case 5:
- return RST_STREAM_CANCEL;
- case 6:
- return RST_STREAM_INTERNAL_ERROR;
- case 7:
- return RST_STREAM_FLOW_CONTROL_ERROR;
- case 8:
- return RST_STREAM_STREAM_IN_USE;
- case 9:
- return RST_STREAM_STREAM_ALREADY_CLOSED;
- case 11:
- return RST_STREAM_FRAME_TOO_LARGE;
- }
- break;
- case HTTP2:
- switch (rst_stream_status_field) {
- case 0:
- return RST_STREAM_NO_ERROR;
- case 1:
- return RST_STREAM_PROTOCOL_ERROR;
- case 2:
- return RST_STREAM_INTERNAL_ERROR;
- case 3:
- return RST_STREAM_FLOW_CONTROL_ERROR;
- case 5:
- return RST_STREAM_STREAM_CLOSED;
- case 6:
- return RST_STREAM_FRAME_SIZE_ERROR;
- case 7:
- return RST_STREAM_REFUSED_STREAM;
- case 8:
- return RST_STREAM_CANCEL;
- case 10:
- return RST_STREAM_CONNECT_ERROR;
- case 11:
- return RST_STREAM_ENHANCE_YOUR_CALM;
- case 12:
- return RST_STREAM_INADEQUATE_SECURITY;
- case 13:
- return RST_STREAM_HTTP_1_1_REQUIRED;
- }
- break;
+ return true;
+}
+
+SpdyRstStreamStatus ParseRstStreamStatus(int rst_stream_status_field) {
+ switch (rst_stream_status_field) {
+ case 0:
+ return RST_STREAM_NO_ERROR;
+ case 1:
+ return RST_STREAM_PROTOCOL_ERROR;
+ case 2:
+ return RST_STREAM_INTERNAL_ERROR;
+ case 3:
+ return RST_STREAM_FLOW_CONTROL_ERROR;
+ case 5:
+ return RST_STREAM_STREAM_CLOSED;
+ case 6:
+ return RST_STREAM_FRAME_SIZE_ERROR;
+ case 7:
+ return RST_STREAM_REFUSED_STREAM;
+ case 8:
+ return RST_STREAM_CANCEL;
+ case 10:
+ return RST_STREAM_CONNECT_ERROR;
+ case 11:
+ return RST_STREAM_ENHANCE_YOUR_CALM;
+ case 12:
+ return RST_STREAM_INADEQUATE_SECURITY;
+ case 13:
+ return RST_STREAM_HTTP_1_1_REQUIRED;
}
SPDY_BUG << "Invalid RST_STREAM status " << rst_stream_status_field;
return RST_STREAM_PROTOCOL_ERROR;
}
-int SpdyConstants::SerializeRstStreamStatus(
- SpdyMajorVersion version,
- SpdyRstStreamStatus rst_stream_status) {
- switch (version) {
- case SPDY3:
- switch (rst_stream_status) {
- case RST_STREAM_PROTOCOL_ERROR:
- return 1;
- case RST_STREAM_INVALID_STREAM:
- return 2;
- case RST_STREAM_REFUSED_STREAM:
- return 3;
- case RST_STREAM_UNSUPPORTED_VERSION:
- return 4;
- case RST_STREAM_CANCEL:
- return 5;
- case RST_STREAM_INTERNAL_ERROR:
- return 6;
- case RST_STREAM_FLOW_CONTROL_ERROR:
- return 7;
- case RST_STREAM_STREAM_IN_USE:
- return 8;
- case RST_STREAM_STREAM_ALREADY_CLOSED:
- return 9;
- case RST_STREAM_FRAME_TOO_LARGE:
- return 11;
- default:
- SPDY_BUG << "Unhandled RST_STREAM status " << rst_stream_status;
- return -1;
- }
- case HTTP2:
- switch (rst_stream_status) {
- case RST_STREAM_NO_ERROR:
- return 0;
- case RST_STREAM_PROTOCOL_ERROR:
- return 1;
- case RST_STREAM_INTERNAL_ERROR:
- return 2;
- case RST_STREAM_FLOW_CONTROL_ERROR:
- return 3;
- case RST_STREAM_STREAM_CLOSED:
- return 5;
- case RST_STREAM_FRAME_SIZE_ERROR:
- return 6;
- case RST_STREAM_REFUSED_STREAM:
- return 7;
- case RST_STREAM_CANCEL:
- return 8;
- case RST_STREAM_CONNECT_ERROR:
- return 10;
- case RST_STREAM_ENHANCE_YOUR_CALM:
- return 11;
- case RST_STREAM_INADEQUATE_SECURITY:
- return 12;
- case RST_STREAM_HTTP_1_1_REQUIRED:
- return 13;
- default:
- SPDY_BUG << "Unhandled RST_STREAM status " << rst_stream_status;
- return -1;
- }
+int SerializeRstStreamStatus(SpdyRstStreamStatus rst_stream_status) {
+ switch (rst_stream_status) {
+ case RST_STREAM_NO_ERROR:
+ return 0;
+ case RST_STREAM_PROTOCOL_ERROR:
+ return 1;
+ case RST_STREAM_INTERNAL_ERROR:
+ return 2;
+ case RST_STREAM_FLOW_CONTROL_ERROR:
+ return 3;
+ case RST_STREAM_STREAM_CLOSED:
+ return 5;
+ case RST_STREAM_FRAME_SIZE_ERROR:
+ return 6;
+ case RST_STREAM_REFUSED_STREAM:
+ return 7;
+ case RST_STREAM_CANCEL:
+ return 8;
+ case RST_STREAM_CONNECT_ERROR:
+ return 10;
+ case RST_STREAM_ENHANCE_YOUR_CALM:
+ return 11;
+ case RST_STREAM_INADEQUATE_SECURITY:
+ return 12;
+ case RST_STREAM_HTTP_1_1_REQUIRED:
+ return 13;
+ default:
+ SPDY_BUG << "Unhandled RST_STREAM status " << rst_stream_status;
+ return -1;
}
- SPDY_BUG << "Unhandled SPDY version " << version;
- return -1;
}
-bool SpdyConstants::IsValidGoAwayStatus(SpdyMajorVersion version,
- int goaway_status_field) {
- switch (version) {
- case SPDY3:
- // GOAWAY_OK is the first valid status.
- if (goaway_status_field < SerializeGoAwayStatus(version, GOAWAY_OK)) {
- return false;
- }
-
- // GOAWAY_INTERNAL_ERROR is the last valid status.
- if (goaway_status_field > SerializeGoAwayStatus(version,
- GOAWAY_INTERNAL_ERROR)) {
- return false;
- }
-
- return true;
- case HTTP2:
- // GOAWAY_NO_ERROR is the first valid status.
- if (goaway_status_field < SerializeGoAwayStatus(version,
- GOAWAY_NO_ERROR)) {
- return false;
- }
-
- // GOAWAY_HTTP_1_1_REQUIRED is the last valid status.
- if (goaway_status_field >
- SerializeGoAwayStatus(version, GOAWAY_HTTP_1_1_REQUIRED)) {
- return false;
- }
+bool IsValidGoAwayStatus(int goaway_status_field) {
+ // GOAWAY_NO_ERROR is the first valid status.
+ if (goaway_status_field < SerializeGoAwayStatus(GOAWAY_NO_ERROR)) {
+ return false;
+ }
- return true;
+ // GOAWAY_HTTP_1_1_REQUIRED is the last valid status.
+ if (goaway_status_field > SerializeGoAwayStatus(GOAWAY_HTTP_1_1_REQUIRED)) {
+ return false;
}
- SPDY_BUG << "Unknown SpdyMajorVersion " << version;
- return false;
-}
-SpdyGoAwayStatus SpdyConstants::ParseGoAwayStatus(SpdyMajorVersion version,
- int goaway_status_field) {
- switch (version) {
- case SPDY3:
- switch (goaway_status_field) {
- case 0:
- return GOAWAY_OK;
- case 1:
- return GOAWAY_PROTOCOL_ERROR;
- case 2:
- return GOAWAY_INTERNAL_ERROR;
- }
- break;
- case HTTP2:
- switch (goaway_status_field) {
- case 0:
- return GOAWAY_NO_ERROR;
- case 1:
- return GOAWAY_PROTOCOL_ERROR;
- case 2:
- return GOAWAY_INTERNAL_ERROR;
- case 3:
- return GOAWAY_FLOW_CONTROL_ERROR;
- case 4:
- return GOAWAY_SETTINGS_TIMEOUT;
- case 5:
- return GOAWAY_STREAM_CLOSED;
- case 6:
- return GOAWAY_FRAME_SIZE_ERROR;
- case 7:
- return GOAWAY_REFUSED_STREAM;
- case 8:
- return GOAWAY_CANCEL;
- case 9:
- return GOAWAY_COMPRESSION_ERROR;
- case 10:
- return GOAWAY_CONNECT_ERROR;
- case 11:
- return GOAWAY_ENHANCE_YOUR_CALM;
- case 12:
- return GOAWAY_INADEQUATE_SECURITY;
- case 13:
- return GOAWAY_HTTP_1_1_REQUIRED;
- }
- break;
+ return true;
+}
+
+SpdyGoAwayStatus ParseGoAwayStatus(int goaway_status_field) {
+ switch (goaway_status_field) {
+ case 0:
+ return GOAWAY_NO_ERROR;
+ case 1:
+ return GOAWAY_PROTOCOL_ERROR;
+ case 2:
+ return GOAWAY_INTERNAL_ERROR;
+ case 3:
+ return GOAWAY_FLOW_CONTROL_ERROR;
+ case 4:
+ return GOAWAY_SETTINGS_TIMEOUT;
+ case 5:
+ return GOAWAY_STREAM_CLOSED;
+ case 6:
+ return GOAWAY_FRAME_SIZE_ERROR;
+ case 7:
+ return GOAWAY_REFUSED_STREAM;
+ case 8:
+ return GOAWAY_CANCEL;
+ case 9:
+ return GOAWAY_COMPRESSION_ERROR;
+ case 10:
+ return GOAWAY_CONNECT_ERROR;
+ case 11:
+ return GOAWAY_ENHANCE_YOUR_CALM;
+ case 12:
+ return GOAWAY_INADEQUATE_SECURITY;
+ case 13:
+ return GOAWAY_HTTP_1_1_REQUIRED;
}
SPDY_BUG << "Unhandled GOAWAY status " << goaway_status_field;
return GOAWAY_PROTOCOL_ERROR;
}
-int SpdyConstants::SerializeGoAwayStatus(SpdyMajorVersion version,
- SpdyGoAwayStatus status) {
- switch (version) {
- case SPDY3:
- // TODO(jgraettinger): Merge this back to server-side.
- switch (status) {
- case GOAWAY_NO_ERROR:
- return 0;
- case GOAWAY_PROTOCOL_ERROR:
- case GOAWAY_INTERNAL_ERROR:
- case GOAWAY_FLOW_CONTROL_ERROR:
- case GOAWAY_SETTINGS_TIMEOUT:
- case GOAWAY_STREAM_CLOSED:
- case GOAWAY_FRAME_SIZE_ERROR:
- case GOAWAY_REFUSED_STREAM:
- case GOAWAY_CANCEL:
- case GOAWAY_COMPRESSION_ERROR:
- case GOAWAY_CONNECT_ERROR:
- case GOAWAY_ENHANCE_YOUR_CALM:
- case GOAWAY_INADEQUATE_SECURITY:
- case GOAWAY_HTTP_1_1_REQUIRED:
- return 1; // PROTOCOL_ERROR.
- default:
- SPDY_BUG << "Serializing unhandled GOAWAY status " << status;
- return -1;
- }
- case HTTP2:
- switch (status) {
- case GOAWAY_NO_ERROR:
- return 0;
- case GOAWAY_PROTOCOL_ERROR:
- return 1;
- case GOAWAY_INTERNAL_ERROR:
- return 2;
- case GOAWAY_FLOW_CONTROL_ERROR:
- return 3;
- case GOAWAY_SETTINGS_TIMEOUT:
- return 4;
- case GOAWAY_STREAM_CLOSED:
- return 5;
- case GOAWAY_FRAME_SIZE_ERROR:
- return 6;
- case GOAWAY_REFUSED_STREAM:
- return 7;
- case GOAWAY_CANCEL:
- return 8;
- case GOAWAY_COMPRESSION_ERROR:
- return 9;
- case GOAWAY_CONNECT_ERROR:
- return 10;
- case GOAWAY_ENHANCE_YOUR_CALM:
- return 11;
- case GOAWAY_INADEQUATE_SECURITY:
- return 12;
- case GOAWAY_HTTP_1_1_REQUIRED:
- return 13;
- default:
- SPDY_BUG << "Serializing unhandled GOAWAY status " << status;
- return -1;
- }
- }
- SPDY_BUG << "Unknown SpdyMajorVersion " << version;
- return -1;
-}
-
-size_t SpdyConstants::GetFrameHeaderSize(SpdyMajorVersion version) {
- switch (version) {
- case SPDY3:
+int SerializeGoAwayStatus(SpdyGoAwayStatus status) {
+ switch (status) {
+ case GOAWAY_NO_ERROR:
+ return 0;
+ case GOAWAY_PROTOCOL_ERROR:
+ return 1;
+ case GOAWAY_INTERNAL_ERROR:
+ return 2;
+ case GOAWAY_FLOW_CONTROL_ERROR:
+ return 3;
+ case GOAWAY_SETTINGS_TIMEOUT:
+ return 4;
+ case GOAWAY_STREAM_CLOSED:
+ return 5;
+ case GOAWAY_FRAME_SIZE_ERROR:
+ return 6;
+ case GOAWAY_REFUSED_STREAM:
+ return 7;
+ case GOAWAY_CANCEL:
return 8;
- case HTTP2:
+ case GOAWAY_COMPRESSION_ERROR:
return 9;
- }
- SPDY_BUG << "Unhandled SPDY version: " << version;
- return 0;
-}
-
-size_t SpdyConstants::GetDataFrameMinimumSize(SpdyMajorVersion version) {
- return GetFrameHeaderSize(version);
-}
-
-size_t SpdyConstants::GetMaxFrameSizeLimit(SpdyMajorVersion version) {
- return kSpdyMaxFrameSizeLimit + GetFrameHeaderSize(version);
-}
-
-size_t SpdyConstants::GetSizeOfSizeField() {
- return sizeof(uint32_t);
-}
-
-size_t SpdyConstants::GetPerHeaderOverhead(SpdyMajorVersion version) {
- return (version == net::HTTP2) ? 32 : 0;
-}
-
-size_t SpdyConstants::GetSettingSize(SpdyMajorVersion version) {
- return version == SPDY3 ? 8 : 6;
-}
-
-int32_t SpdyConstants::GetInitialStreamWindowSize(SpdyMajorVersion version) {
- return (version == SPDY3) ? (64 * 1024) : (64 * 1024 - 1);
-}
-
-int32_t SpdyConstants::GetInitialSessionWindowSize(SpdyMajorVersion version) {
- return (version == SPDY3) ? (64 * 1024) : (64 * 1024 - 1);
-}
-
-std::string SpdyConstants::GetVersionString(SpdyMajorVersion version) {
- switch (version) {
- case SPDY3:
- return "spdy/3.1";
- case HTTP2:
- return "h2";
+ case GOAWAY_CONNECT_ERROR:
+ return 10;
+ case GOAWAY_ENHANCE_YOUR_CALM:
+ return 11;
+ case GOAWAY_INADEQUATE_SECURITY:
+ return 12;
+ case GOAWAY_HTTP_1_1_REQUIRED:
+ return 13;
default:
- SPDY_BUG << "Unsupported SPDY major version: " << version;
- return "spdy/3.1";
+ SPDY_BUG << "Serializing unhandled GOAWAY status " << status;
+ return -1;
}
}
+const char* const kHttp2Npn = "h2";
+
SpdyFrameWithHeaderBlockIR::SpdyFrameWithHeaderBlockIR(
SpdyStreamId stream_id,
SpdyHeaderBlock header_block)
@@ -786,14 +375,6 @@ void SpdyDataIR::Visit(SpdyFrameVisitor* visitor) const {
return visitor->VisitData(*this);
}
-void SpdySynStreamIR::Visit(SpdyFrameVisitor* visitor) const {
- return visitor->VisitSynStream(*this);
-}
-
-void SpdySynReplyIR::Visit(SpdyFrameVisitor* visitor) const {
- return visitor->VisitSynReply(*this);
-}
-
SpdyRstStreamIR::SpdyRstStreamIR(SpdyStreamId stream_id,
SpdyRstStreamStatus status)
: SpdyFrameWithStreamIdIR(stream_id) {
@@ -806,9 +387,7 @@ void SpdyRstStreamIR::Visit(SpdyFrameVisitor* visitor) const {
return visitor->VisitRstStream(*this);
}
-SpdySettingsIR::SpdySettingsIR()
- : clear_settings_(false),
- is_ack_(false) {}
+SpdySettingsIR::SpdySettingsIR() : is_ack_(false) {}
SpdySettingsIR::~SpdySettingsIR() {}
diff --git a/chromium/net/spdy/spdy_protocol.h b/chromium/net/spdy/spdy_protocol.h
index 489b8df691b..55c87bfd75e 100644
--- a/chromium/net/spdy/spdy_protocol.h
+++ b/chromium/net/spdy/spdy_protocol.h
@@ -31,25 +31,16 @@
namespace net {
-// The major versions of SPDY. Major version differences indicate
-// framer-layer incompatibility, as opposed to minor version numbers
-// which indicate application-layer incompatibility. It is NOT guaranteed
-// that the enum value SPDYn maps to the integer n.
-enum SpdyMajorVersion {
- SPDY3 = 1,
- HTTP2,
-};
-
-// 15 bit version field for SPDY/3 frames.
-const uint16_t kSpdy3Version = 3;
-
-// A SPDY stream id is a 31 bit entity.
+// A stream id is a 31 bit entity.
typedef uint32_t SpdyStreamId;
// Specifies the stream ID used to denote the current session (for
// flow control).
const SpdyStreamId kSessionFlowControlStreamId = 0;
+// Max stream id.
+const SpdyStreamId kMaxStreamId = 0x7fffffff;
+
// The maximum possible frame payload size allowed by the spec.
const uint32_t kSpdyMaxFrameSizeLimit = (1 << 24) - 1;
@@ -67,189 +58,6 @@ const int32_t kSpdyMaximumWindowSize = 0x7FFFFFFF; // Max signed 32bit int
// Maximum padding size in octets for one DATA or HEADERS or PUSH_PROMISE frame.
const int32_t kPaddingSizePerFrame = 256;
-// SPDY 3 dictionary.
-const char kV3Dictionary[] = {
- 0x00, 0x00, 0x00, 0x07, 0x6f, 0x70, 0x74, 0x69, // ....opti
- 0x6f, 0x6e, 0x73, 0x00, 0x00, 0x00, 0x04, 0x68, // ons....h
- 0x65, 0x61, 0x64, 0x00, 0x00, 0x00, 0x04, 0x70, // ead....p
- 0x6f, 0x73, 0x74, 0x00, 0x00, 0x00, 0x03, 0x70, // ost....p
- 0x75, 0x74, 0x00, 0x00, 0x00, 0x06, 0x64, 0x65, // ut....de
- 0x6c, 0x65, 0x74, 0x65, 0x00, 0x00, 0x00, 0x05, // lete....
- 0x74, 0x72, 0x61, 0x63, 0x65, 0x00, 0x00, 0x00, // trace...
- 0x06, 0x61, 0x63, 0x63, 0x65, 0x70, 0x74, 0x00, // .accept.
- 0x00, 0x00, 0x0e, 0x61, 0x63, 0x63, 0x65, 0x70, // ...accep
- 0x74, 0x2d, 0x63, 0x68, 0x61, 0x72, 0x73, 0x65, // t-charse
- 0x74, 0x00, 0x00, 0x00, 0x0f, 0x61, 0x63, 0x63, // t....acc
- 0x65, 0x70, 0x74, 0x2d, 0x65, 0x6e, 0x63, 0x6f, // ept-enco
- 0x64, 0x69, 0x6e, 0x67, 0x00, 0x00, 0x00, 0x0f, // ding....
- 0x61, 0x63, 0x63, 0x65, 0x70, 0x74, 0x2d, 0x6c, // accept-l
- 0x61, 0x6e, 0x67, 0x75, 0x61, 0x67, 0x65, 0x00, // anguage.
- 0x00, 0x00, 0x0d, 0x61, 0x63, 0x63, 0x65, 0x70, // ...accep
- 0x74, 0x2d, 0x72, 0x61, 0x6e, 0x67, 0x65, 0x73, // t-ranges
- 0x00, 0x00, 0x00, 0x03, 0x61, 0x67, 0x65, 0x00, // ....age.
- 0x00, 0x00, 0x05, 0x61, 0x6c, 0x6c, 0x6f, 0x77, // ...allow
- 0x00, 0x00, 0x00, 0x0d, 0x61, 0x75, 0x74, 0x68, // ....auth
- 0x6f, 0x72, 0x69, 0x7a, 0x61, 0x74, 0x69, 0x6f, // orizatio
- 0x6e, 0x00, 0x00, 0x00, 0x0d, 0x63, 0x61, 0x63, // n....cac
- 0x68, 0x65, 0x2d, 0x63, 0x6f, 0x6e, 0x74, 0x72, // he-contr
- 0x6f, 0x6c, 0x00, 0x00, 0x00, 0x0a, 0x63, 0x6f, // ol....co
- 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, // nnection
- 0x00, 0x00, 0x00, 0x0c, 0x63, 0x6f, 0x6e, 0x74, // ....cont
- 0x65, 0x6e, 0x74, 0x2d, 0x62, 0x61, 0x73, 0x65, // ent-base
- 0x00, 0x00, 0x00, 0x10, 0x63, 0x6f, 0x6e, 0x74, // ....cont
- 0x65, 0x6e, 0x74, 0x2d, 0x65, 0x6e, 0x63, 0x6f, // ent-enco
- 0x64, 0x69, 0x6e, 0x67, 0x00, 0x00, 0x00, 0x10, // ding....
- 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x2d, // content-
- 0x6c, 0x61, 0x6e, 0x67, 0x75, 0x61, 0x67, 0x65, // language
- 0x00, 0x00, 0x00, 0x0e, 0x63, 0x6f, 0x6e, 0x74, // ....cont
- 0x65, 0x6e, 0x74, 0x2d, 0x6c, 0x65, 0x6e, 0x67, // ent-leng
- 0x74, 0x68, 0x00, 0x00, 0x00, 0x10, 0x63, 0x6f, // th....co
- 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x2d, 0x6c, 0x6f, // ntent-lo
- 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x00, 0x00, // cation..
- 0x00, 0x0b, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, // ..conten
- 0x74, 0x2d, 0x6d, 0x64, 0x35, 0x00, 0x00, 0x00, // t-md5...
- 0x0d, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, // .content
- 0x2d, 0x72, 0x61, 0x6e, 0x67, 0x65, 0x00, 0x00, // -range..
- 0x00, 0x0c, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, // ..conten
- 0x74, 0x2d, 0x74, 0x79, 0x70, 0x65, 0x00, 0x00, // t-type..
- 0x00, 0x04, 0x64, 0x61, 0x74, 0x65, 0x00, 0x00, // ..date..
- 0x00, 0x04, 0x65, 0x74, 0x61, 0x67, 0x00, 0x00, // ..etag..
- 0x00, 0x06, 0x65, 0x78, 0x70, 0x65, 0x63, 0x74, // ..expect
- 0x00, 0x00, 0x00, 0x07, 0x65, 0x78, 0x70, 0x69, // ....expi
- 0x72, 0x65, 0x73, 0x00, 0x00, 0x00, 0x04, 0x66, // res....f
- 0x72, 0x6f, 0x6d, 0x00, 0x00, 0x00, 0x04, 0x68, // rom....h
- 0x6f, 0x73, 0x74, 0x00, 0x00, 0x00, 0x08, 0x69, // ost....i
- 0x66, 0x2d, 0x6d, 0x61, 0x74, 0x63, 0x68, 0x00, // f-match.
- 0x00, 0x00, 0x11, 0x69, 0x66, 0x2d, 0x6d, 0x6f, // ...if-mo
- 0x64, 0x69, 0x66, 0x69, 0x65, 0x64, 0x2d, 0x73, // dified-s
- 0x69, 0x6e, 0x63, 0x65, 0x00, 0x00, 0x00, 0x0d, // ince....
- 0x69, 0x66, 0x2d, 0x6e, 0x6f, 0x6e, 0x65, 0x2d, // if-none-
- 0x6d, 0x61, 0x74, 0x63, 0x68, 0x00, 0x00, 0x00, // match...
- 0x08, 0x69, 0x66, 0x2d, 0x72, 0x61, 0x6e, 0x67, // .if-rang
- 0x65, 0x00, 0x00, 0x00, 0x13, 0x69, 0x66, 0x2d, // e....if-
- 0x75, 0x6e, 0x6d, 0x6f, 0x64, 0x69, 0x66, 0x69, // unmodifi
- 0x65, 0x64, 0x2d, 0x73, 0x69, 0x6e, 0x63, 0x65, // ed-since
- 0x00, 0x00, 0x00, 0x0d, 0x6c, 0x61, 0x73, 0x74, // ....last
- 0x2d, 0x6d, 0x6f, 0x64, 0x69, 0x66, 0x69, 0x65, // -modifie
- 0x64, 0x00, 0x00, 0x00, 0x08, 0x6c, 0x6f, 0x63, // d....loc
- 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x00, 0x00, 0x00, // ation...
- 0x0c, 0x6d, 0x61, 0x78, 0x2d, 0x66, 0x6f, 0x72, // .max-for
- 0x77, 0x61, 0x72, 0x64, 0x73, 0x00, 0x00, 0x00, // wards...
- 0x06, 0x70, 0x72, 0x61, 0x67, 0x6d, 0x61, 0x00, // .pragma.
- 0x00, 0x00, 0x12, 0x70, 0x72, 0x6f, 0x78, 0x79, // ...proxy
- 0x2d, 0x61, 0x75, 0x74, 0x68, 0x65, 0x6e, 0x74, // -authent
- 0x69, 0x63, 0x61, 0x74, 0x65, 0x00, 0x00, 0x00, // icate...
- 0x13, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x2d, 0x61, // .proxy-a
- 0x75, 0x74, 0x68, 0x6f, 0x72, 0x69, 0x7a, 0x61, // uthoriza
- 0x74, 0x69, 0x6f, 0x6e, 0x00, 0x00, 0x00, 0x05, // tion....
- 0x72, 0x61, 0x6e, 0x67, 0x65, 0x00, 0x00, 0x00, // range...
- 0x07, 0x72, 0x65, 0x66, 0x65, 0x72, 0x65, 0x72, // .referer
- 0x00, 0x00, 0x00, 0x0b, 0x72, 0x65, 0x74, 0x72, // ....retr
- 0x79, 0x2d, 0x61, 0x66, 0x74, 0x65, 0x72, 0x00, // y-after.
- 0x00, 0x00, 0x06, 0x73, 0x65, 0x72, 0x76, 0x65, // ...serve
- 0x72, 0x00, 0x00, 0x00, 0x02, 0x74, 0x65, 0x00, // r....te.
- 0x00, 0x00, 0x07, 0x74, 0x72, 0x61, 0x69, 0x6c, // ...trail
- 0x65, 0x72, 0x00, 0x00, 0x00, 0x11, 0x74, 0x72, // er....tr
- 0x61, 0x6e, 0x73, 0x66, 0x65, 0x72, 0x2d, 0x65, // ansfer-e
- 0x6e, 0x63, 0x6f, 0x64, 0x69, 0x6e, 0x67, 0x00, // ncoding.
- 0x00, 0x00, 0x07, 0x75, 0x70, 0x67, 0x72, 0x61, // ...upgra
- 0x64, 0x65, 0x00, 0x00, 0x00, 0x0a, 0x75, 0x73, // de....us
- 0x65, 0x72, 0x2d, 0x61, 0x67, 0x65, 0x6e, 0x74, // er-agent
- 0x00, 0x00, 0x00, 0x04, 0x76, 0x61, 0x72, 0x79, // ....vary
- 0x00, 0x00, 0x00, 0x03, 0x76, 0x69, 0x61, 0x00, // ....via.
- 0x00, 0x00, 0x07, 0x77, 0x61, 0x72, 0x6e, 0x69, // ...warni
- 0x6e, 0x67, 0x00, 0x00, 0x00, 0x10, 0x77, 0x77, // ng....ww
- 0x77, 0x2d, 0x61, 0x75, 0x74, 0x68, 0x65, 0x6e, // w-authen
- 0x74, 0x69, 0x63, 0x61, 0x74, 0x65, 0x00, 0x00, // ticate..
- 0x00, 0x06, 0x6d, 0x65, 0x74, 0x68, 0x6f, 0x64, // ..method
- 0x00, 0x00, 0x00, 0x03, 0x67, 0x65, 0x74, 0x00, // ....get.
- 0x00, 0x00, 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, // ...statu
- 0x73, 0x00, 0x00, 0x00, 0x06, 0x32, 0x30, 0x30, // s....200
- 0x20, 0x4f, 0x4b, 0x00, 0x00, 0x00, 0x07, 0x76, // .OK....v
- 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x00, 0x00, // ersion..
- 0x00, 0x08, 0x48, 0x54, 0x54, 0x50, 0x2f, 0x31, // ..HTTP.1
- 0x2e, 0x31, 0x00, 0x00, 0x00, 0x03, 0x75, 0x72, // .1....ur
- 0x6c, 0x00, 0x00, 0x00, 0x06, 0x70, 0x75, 0x62, // l....pub
- 0x6c, 0x69, 0x63, 0x00, 0x00, 0x00, 0x0a, 0x73, // lic....s
- 0x65, 0x74, 0x2d, 0x63, 0x6f, 0x6f, 0x6b, 0x69, // et-cooki
- 0x65, 0x00, 0x00, 0x00, 0x0a, 0x6b, 0x65, 0x65, // e....kee
- 0x70, 0x2d, 0x61, 0x6c, 0x69, 0x76, 0x65, 0x00, // p-alive.
- 0x00, 0x00, 0x06, 0x6f, 0x72, 0x69, 0x67, 0x69, // ...origi
- 0x6e, 0x31, 0x30, 0x30, 0x31, 0x30, 0x31, 0x32, // n1001012
- 0x30, 0x31, 0x32, 0x30, 0x32, 0x32, 0x30, 0x35, // 01202205
- 0x32, 0x30, 0x36, 0x33, 0x30, 0x30, 0x33, 0x30, // 20630030
- 0x32, 0x33, 0x30, 0x33, 0x33, 0x30, 0x34, 0x33, // 23033043
- 0x30, 0x35, 0x33, 0x30, 0x36, 0x33, 0x30, 0x37, // 05306307
- 0x34, 0x30, 0x32, 0x34, 0x30, 0x35, 0x34, 0x30, // 40240540
- 0x36, 0x34, 0x30, 0x37, 0x34, 0x30, 0x38, 0x34, // 64074084
- 0x30, 0x39, 0x34, 0x31, 0x30, 0x34, 0x31, 0x31, // 09410411
- 0x34, 0x31, 0x32, 0x34, 0x31, 0x33, 0x34, 0x31, // 41241341
- 0x34, 0x34, 0x31, 0x35, 0x34, 0x31, 0x36, 0x34, // 44154164
- 0x31, 0x37, 0x35, 0x30, 0x32, 0x35, 0x30, 0x34, // 17502504
- 0x35, 0x30, 0x35, 0x32, 0x30, 0x33, 0x20, 0x4e, // 505203.N
- 0x6f, 0x6e, 0x2d, 0x41, 0x75, 0x74, 0x68, 0x6f, // on-Autho
- 0x72, 0x69, 0x74, 0x61, 0x74, 0x69, 0x76, 0x65, // ritative
- 0x20, 0x49, 0x6e, 0x66, 0x6f, 0x72, 0x6d, 0x61, // .Informa
- 0x74, 0x69, 0x6f, 0x6e, 0x32, 0x30, 0x34, 0x20, // tion204.
- 0x4e, 0x6f, 0x20, 0x43, 0x6f, 0x6e, 0x74, 0x65, // No.Conte
- 0x6e, 0x74, 0x33, 0x30, 0x31, 0x20, 0x4d, 0x6f, // nt301.Mo
- 0x76, 0x65, 0x64, 0x20, 0x50, 0x65, 0x72, 0x6d, // ved.Perm
- 0x61, 0x6e, 0x65, 0x6e, 0x74, 0x6c, 0x79, 0x34, // anently4
- 0x30, 0x30, 0x20, 0x42, 0x61, 0x64, 0x20, 0x52, // 00.Bad.R
- 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x34, 0x30, // equest40
- 0x31, 0x20, 0x55, 0x6e, 0x61, 0x75, 0x74, 0x68, // 1.Unauth
- 0x6f, 0x72, 0x69, 0x7a, 0x65, 0x64, 0x34, 0x30, // orized40
- 0x33, 0x20, 0x46, 0x6f, 0x72, 0x62, 0x69, 0x64, // 3.Forbid
- 0x64, 0x65, 0x6e, 0x34, 0x30, 0x34, 0x20, 0x4e, // den404.N
- 0x6f, 0x74, 0x20, 0x46, 0x6f, 0x75, 0x6e, 0x64, // ot.Found
- 0x35, 0x30, 0x30, 0x20, 0x49, 0x6e, 0x74, 0x65, // 500.Inte
- 0x72, 0x6e, 0x61, 0x6c, 0x20, 0x53, 0x65, 0x72, // rnal.Ser
- 0x76, 0x65, 0x72, 0x20, 0x45, 0x72, 0x72, 0x6f, // ver.Erro
- 0x72, 0x35, 0x30, 0x31, 0x20, 0x4e, 0x6f, 0x74, // r501.Not
- 0x20, 0x49, 0x6d, 0x70, 0x6c, 0x65, 0x6d, 0x65, // .Impleme
- 0x6e, 0x74, 0x65, 0x64, 0x35, 0x30, 0x33, 0x20, // nted503.
- 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x20, // Service.
- 0x55, 0x6e, 0x61, 0x76, 0x61, 0x69, 0x6c, 0x61, // Unavaila
- 0x62, 0x6c, 0x65, 0x4a, 0x61, 0x6e, 0x20, 0x46, // bleJan.F
- 0x65, 0x62, 0x20, 0x4d, 0x61, 0x72, 0x20, 0x41, // eb.Mar.A
- 0x70, 0x72, 0x20, 0x4d, 0x61, 0x79, 0x20, 0x4a, // pr.May.J
- 0x75, 0x6e, 0x20, 0x4a, 0x75, 0x6c, 0x20, 0x41, // un.Jul.A
- 0x75, 0x67, 0x20, 0x53, 0x65, 0x70, 0x74, 0x20, // ug.Sept.
- 0x4f, 0x63, 0x74, 0x20, 0x4e, 0x6f, 0x76, 0x20, // Oct.Nov.
- 0x44, 0x65, 0x63, 0x20, 0x30, 0x30, 0x3a, 0x30, // Dec.00.0
- 0x30, 0x3a, 0x30, 0x30, 0x20, 0x4d, 0x6f, 0x6e, // 0.00.Mon
- 0x2c, 0x20, 0x54, 0x75, 0x65, 0x2c, 0x20, 0x57, // ..Tue..W
- 0x65, 0x64, 0x2c, 0x20, 0x54, 0x68, 0x75, 0x2c, // ed..Thu.
- 0x20, 0x46, 0x72, 0x69, 0x2c, 0x20, 0x53, 0x61, // .Fri..Sa
- 0x74, 0x2c, 0x20, 0x53, 0x75, 0x6e, 0x2c, 0x20, // t..Sun..
- 0x47, 0x4d, 0x54, 0x63, 0x68, 0x75, 0x6e, 0x6b, // GMTchunk
- 0x65, 0x64, 0x2c, 0x74, 0x65, 0x78, 0x74, 0x2f, // ed.text.
- 0x68, 0x74, 0x6d, 0x6c, 0x2c, 0x69, 0x6d, 0x61, // html.ima
- 0x67, 0x65, 0x2f, 0x70, 0x6e, 0x67, 0x2c, 0x69, // ge.png.i
- 0x6d, 0x61, 0x67, 0x65, 0x2f, 0x6a, 0x70, 0x67, // mage.jpg
- 0x2c, 0x69, 0x6d, 0x61, 0x67, 0x65, 0x2f, 0x67, // .image.g
- 0x69, 0x66, 0x2c, 0x61, 0x70, 0x70, 0x6c, 0x69, // if.appli
- 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x78, // cation.x
- 0x6d, 0x6c, 0x2c, 0x61, 0x70, 0x70, 0x6c, 0x69, // ml.appli
- 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x78, // cation.x
- 0x68, 0x74, 0x6d, 0x6c, 0x2b, 0x78, 0x6d, 0x6c, // html.xml
- 0x2c, 0x74, 0x65, 0x78, 0x74, 0x2f, 0x70, 0x6c, // .text.pl
- 0x61, 0x69, 0x6e, 0x2c, 0x74, 0x65, 0x78, 0x74, // ain.text
- 0x2f, 0x6a, 0x61, 0x76, 0x61, 0x73, 0x63, 0x72, // .javascr
- 0x69, 0x70, 0x74, 0x2c, 0x70, 0x75, 0x62, 0x6c, // ipt.publ
- 0x69, 0x63, 0x70, 0x72, 0x69, 0x76, 0x61, 0x74, // icprivat
- 0x65, 0x6d, 0x61, 0x78, 0x2d, 0x61, 0x67, 0x65, // emax-age
- 0x3d, 0x67, 0x7a, 0x69, 0x70, 0x2c, 0x64, 0x65, // .gzip.de
- 0x66, 0x6c, 0x61, 0x74, 0x65, 0x2c, 0x73, 0x64, // flate.sd
- 0x63, 0x68, 0x63, 0x68, 0x61, 0x72, 0x73, 0x65, // chcharse
- 0x74, 0x3d, 0x75, 0x74, 0x66, 0x2d, 0x38, 0x63, // t.utf-8c
- 0x68, 0x61, 0x72, 0x73, 0x65, 0x74, 0x3d, 0x69, // harset.i
- 0x73, 0x6f, 0x2d, 0x38, 0x38, 0x35, 0x39, 0x2d, // so-8859-
- 0x31, 0x2c, 0x75, 0x74, 0x66, 0x2d, 0x2c, 0x2a, // 1.utf-..
- 0x2c, 0x65, 0x6e, 0x71, 0x3d, 0x30, 0x2e // .enq.0.
-};
-const int kV3DictionarySize = arraysize(kV3Dictionary);
-
// The HTTP/2 connection header prefix, which must be the first bytes
// sent by the client upon starting an HTTP/2 connection, and which
// must be followed by a SETTINGS frame.
@@ -264,25 +72,23 @@ const char kHttp2ConnectionHeaderPrefix[] = {
const int kHttp2ConnectionHeaderPrefixSize =
arraysize(kHttp2ConnectionHeaderPrefix);
-const char kHttp2VersionString[] = "HTTP/1.1";
-
-// Types of SPDY frames.
+// Types of HTTP2 frames.
enum SpdyFrameType {
- DATA,
- SYN_STREAM,
- SYN_REPLY,
- RST_STREAM,
- SETTINGS,
- PING,
- GOAWAY,
- HEADERS,
- WINDOW_UPDATE,
- PUSH_PROMISE,
- CONTINUATION,
- PRIORITY,
- // BLOCKED and ALTSVC are recognized extensions.
- BLOCKED,
- ALTSVC,
+ DATA = 0x00,
+ MIN_FRAME_TYPE = DATA,
+ HEADERS = 0x01,
+ PRIORITY = 0x02,
+ RST_STREAM = 0x03,
+ SETTINGS = 0x04,
+ PUSH_PROMISE = 0x05,
+ PING = 0x06,
+ GOAWAY = 0x07,
+ WINDOW_UPDATE = 0x08,
+ CONTINUATION = 0x09,
+ // ALTSVC and BLOCKED are recognized extensions.
+ ALTSVC = 0x0a,
+ BLOCKED = 0x0b,
+ MAX_FRAME_TYPE = BLOCKED
};
// Flags on data packets.
@@ -324,68 +130,47 @@ enum Http2SettingsControlFlags {
SETTINGS_FLAG_ACK = 0x01,
};
-// Flags for settings within a SETTINGS frame.
-enum SpdySettingsFlags {
- SETTINGS_FLAG_NONE = 0x00,
- SETTINGS_FLAG_PLEASE_PERSIST = 0x01,
- SETTINGS_FLAG_PERSISTED = 0x02,
-};
-
-// List of known settings. Avoid changing these enum values, as persisted
-// settings are keyed on them, and they are also exposed in net-internals.
enum SpdySettingsIds {
- SETTINGS_UPLOAD_BANDWIDTH = 0x1,
- SETTINGS_DOWNLOAD_BANDWIDTH = 0x2,
- // Network round trip time in milliseconds.
- SETTINGS_ROUND_TRIP_TIME = 0x3,
- // The maximum number of simultaneous live streams in each direction.
- SETTINGS_MAX_CONCURRENT_STREAMS = 0x4,
- // TCP congestion window in packets.
- SETTINGS_CURRENT_CWND = 0x5,
- // Downstream byte retransmission rate in percentage.
- SETTINGS_DOWNLOAD_RETRANS_RATE = 0x6,
- // Initial window size in bytes
- SETTINGS_INITIAL_WINDOW_SIZE = 0x7,
// HPACK header table maximum size.
- SETTINGS_HEADER_TABLE_SIZE = 0x8,
+ SETTINGS_HEADER_TABLE_SIZE = 0x1,
+ SETTINGS_MIN = SETTINGS_HEADER_TABLE_SIZE,
// Whether or not server push (PUSH_PROMISE) is enabled.
- SETTINGS_ENABLE_PUSH = 0x9,
+ SETTINGS_ENABLE_PUSH = 0x2,
+ // The maximum number of simultaneous live streams in each direction.
+ SETTINGS_MAX_CONCURRENT_STREAMS = 0x3,
+ // Initial window size in bytes
+ SETTINGS_INITIAL_WINDOW_SIZE = 0x4,
// The size of the largest frame payload that a receiver is willing to accept.
- SETTINGS_MAX_FRAME_SIZE = 0xa,
+ SETTINGS_MAX_FRAME_SIZE = 0x5,
// The maximum size of header list that the sender is prepared to accept.
- SETTINGS_MAX_HEADER_LIST_SIZE = 0xb,
+ SETTINGS_MAX_HEADER_LIST_SIZE = 0x6,
+ SETTINGS_MAX = SETTINGS_MAX_HEADER_LIST_SIZE
};
+using SettingsMap = std::map<SpdySettingsIds, uint32_t>;
+
// Status codes for RST_STREAM frames.
enum SpdyRstStreamStatus {
RST_STREAM_NO_ERROR = 0,
RST_STREAM_PROTOCOL_ERROR = 1,
- RST_STREAM_INVALID_STREAM = 2,
- RST_STREAM_STREAM_CLOSED = 2, // Equivalent to INVALID_STREAM
- RST_STREAM_REFUSED_STREAM = 3,
- RST_STREAM_UNSUPPORTED_VERSION = 4,
- RST_STREAM_CANCEL = 5,
- RST_STREAM_INTERNAL_ERROR = 6,
- RST_STREAM_FLOW_CONTROL_ERROR = 7,
- RST_STREAM_STREAM_IN_USE = 8,
- RST_STREAM_STREAM_ALREADY_CLOSED = 9,
- // FRAME_TOO_LARGE (defined by SPDY versions 3.1 and below), and
- // FRAME_SIZE_ERROR (defined by HTTP/2) are mapped to the same internal
- // reset status.
- RST_STREAM_FRAME_TOO_LARGE = 11,
- RST_STREAM_FRAME_SIZE_ERROR = 11,
- RST_STREAM_SETTINGS_TIMEOUT = 12,
- RST_STREAM_CONNECT_ERROR = 13,
- RST_STREAM_ENHANCE_YOUR_CALM = 14,
- RST_STREAM_INADEQUATE_SECURITY = 15,
- RST_STREAM_HTTP_1_1_REQUIRED = 16,
- RST_STREAM_NUM_STATUS_CODES = 17
+ RST_STREAM_INTERNAL_ERROR = 2,
+ RST_STREAM_FLOW_CONTROL_ERROR = 3,
+ RST_STREAM_SETTINGS_TIMEOUT = 4,
+ RST_STREAM_STREAM_CLOSED = 5,
+ RST_STREAM_FRAME_SIZE_ERROR = 6,
+ RST_STREAM_REFUSED_STREAM = 7,
+ RST_STREAM_CANCEL = 8,
+ RST_STREAM_COMPRESSION_ERROR = 9,
+ RST_STREAM_CONNECT_ERROR = 10,
+ RST_STREAM_ENHANCE_YOUR_CALM = 11,
+ RST_STREAM_INADEQUATE_SECURITY = 12,
+ RST_STREAM_HTTP_1_1_REQUIRED = 13,
+ RST_STREAM_NUM_STATUS_CODES = 14
};
// Status codes for GOAWAY frames.
enum SpdyGoAwayStatus {
- GOAWAY_OK = 0,
- GOAWAY_NO_ERROR = GOAWAY_OK,
+ GOAWAY_NO_ERROR = 0,
GOAWAY_PROTOCOL_ERROR = 1,
GOAWAY_INTERNAL_ERROR = 2,
GOAWAY_FLOW_CONTROL_ERROR = 3,
@@ -440,121 +225,84 @@ const unsigned int kHttp2RootStreamId = 0;
typedef uint64_t SpdyPingId;
-typedef std::string SpdyProtocolId;
-
-// TODO(hkhalil): Add direct testing for this? It won't increase coverage any,
-// but is good to do anyway.
-class NET_EXPORT_PRIVATE SpdyConstants {
- public:
- // Returns true if a given on-the-wire enumeration of a frame type is valid
- // for a given protocol version, false otherwise.
- static bool IsValidFrameType(SpdyMajorVersion version, int frame_type_field);
-
- // Parses a frame type from an on-the-wire enumeration of a given protocol
- // version.
- // Behavior is undefined for invalid frame type fields; consumers should first
- // use IsValidFrameType() to verify validity of frame type fields.
- static SpdyFrameType ParseFrameType(SpdyMajorVersion version,
- int frame_type_field);
-
- // Serializes a given frame type to the on-the-wire enumeration value for the
- // given protocol version.
- // Returns -1 on failure (I.E. Invalid frame type for the given version).
- static int SerializeFrameType(SpdyMajorVersion version,
- SpdyFrameType frame_type);
-
- // Returns the frame type for non-control (i.e. data) frames
- // in the given SPDY version.
- static int DataFrameType(SpdyMajorVersion version);
-
- // (HTTP/2) All standard frame types except WINDOW_UPDATE are
- // (stream-specific xor connection-level). Returns false iff we know
- // the given frame type does not align with the given streamID.
- static bool IsValidHTTP2FrameStreamId(SpdyStreamId current_frame_stream_id,
- SpdyFrameType frame_type_field);
-
- // Returns true if a given on-the-wire enumeration of a setting id is valid
- // for a given protocol version, false otherwise.
- static bool IsValidSettingId(SpdyMajorVersion version, int setting_id_field);
-
- // Parses a setting id from an on-the-wire enumeration of a given protocol
- // version.
- // Behavior is undefined for invalid setting id fields; consumers should first
- // use IsValidSettingId() to verify validity of setting id fields.
- static SpdySettingsIds ParseSettingId(SpdyMajorVersion version,
- int setting_id_field);
-
- // Serializes a given setting id to the on-the-wire enumeration value for the
- // given protocol version.
- // Returns -1 on failure (I.E. Invalid setting id for the given version).
- static int SerializeSettingId(SpdyMajorVersion version, SpdySettingsIds id);
-
- // Returns true if a given on-the-wire enumeration of a RST_STREAM status code
- // is valid for a given protocol version, false otherwise.
- static bool IsValidRstStreamStatus(SpdyMajorVersion version,
- int rst_stream_status_field);
-
- // Parses a RST_STREAM status code from an on-the-wire enumeration of a given
- // protocol version.
- // Behavior is undefined for invalid RST_STREAM status code fields; consumers
- // should first use IsValidRstStreamStatus() to verify validity of RST_STREAM
- // status code fields..
- static SpdyRstStreamStatus ParseRstStreamStatus(SpdyMajorVersion version,
- int rst_stream_status_field);
-
- // Serializes a given RST_STREAM status code to the on-the-wire enumeration
- // value for the given protocol version.
- // Returns -1 on failure (I.E. Invalid RST_STREAM status code for the given
- // version).
- static int SerializeRstStreamStatus(SpdyMajorVersion version,
- SpdyRstStreamStatus rst_stream_status);
-
- // Returns true if a given on-the-wire enumeration of a GOAWAY status code is
- // valid for the given protocol version, false otherwise.
- static bool IsValidGoAwayStatus(SpdyMajorVersion version,
- int goaway_status_field);
-
- // Parses a GOAWAY status from an on-the-wire enumeration of a given protocol
- // version.
- // Behavior is undefined for invalid GOAWAY status fields; consumers should
- // first use IsValidGoAwayStatus() to verify validity of GOAWAY status fields.
- static SpdyGoAwayStatus ParseGoAwayStatus(SpdyMajorVersion version,
- int goaway_status_field);
-
- // Serializes a given GOAWAY status to the on-the-wire enumeration value for
- // the given protocol version.
- // Returns -1 on failure (I.E. Invalid GOAWAY status for the given version).
- static int SerializeGoAwayStatus(SpdyMajorVersion version,
- SpdyGoAwayStatus status);
-
- // Size, in bytes, of the data frame header. Future versions of SPDY
- // will likely vary this, so we allow for the flexibility of a function call
- // for this value as opposed to a constant.
- static size_t GetDataFrameMinimumSize(SpdyMajorVersion version);
-
- // Number of octets in the frame header.
- static size_t GetFrameHeaderSize(SpdyMajorVersion version);
-
- // Maximum possible configurable size of a frame in octets.
- static size_t GetMaxFrameSizeLimit(SpdyMajorVersion version);
-
- // Returns the size of a header block size field. Valid only for SPDY 3.
- static size_t GetSizeOfSizeField();
-
- // Returns the per-header overhead for block size accounting in bytes.
- static size_t GetPerHeaderOverhead(SpdyMajorVersion version);
-
- // Returns the size (in bytes) of a wire setting ID and value.
- static size_t GetSettingSize(SpdyMajorVersion version);
-
- // Initial window size for a stream in bytes.
- static int32_t GetInitialStreamWindowSize(SpdyMajorVersion version);
-
- // Initial window size for a session in bytes.
- static int32_t GetInitialSessionWindowSize(SpdyMajorVersion version);
-
- static std::string GetVersionString(SpdyMajorVersion version);
-};
+// Returns true if a given on-the-wire enumeration of a frame type is valid
+// for a given protocol version, false otherwise.
+NET_EXPORT_PRIVATE bool IsValidFrameType(int frame_type_field);
+
+// Parses a frame type from an on-the-wire enumeration.
+// Behavior is undefined for invalid frame type fields; consumers should first
+// use IsValidFrameType() to verify validity of frame type fields.
+NET_EXPORT_PRIVATE SpdyFrameType ParseFrameType(int frame_type_field);
+
+// Serializes a given frame type to the on-the-wire enumeration value.
+// Returns -1 on failure (I.E. Invalid frame type).
+NET_EXPORT_PRIVATE int SerializeFrameType(SpdyFrameType frame_type);
+
+// (HTTP/2) All standard frame types except WINDOW_UPDATE are
+// (stream-specific xor connection-level). Returns false iff we know
+// the given frame type does not align with the given streamID.
+NET_EXPORT_PRIVATE bool IsValidHTTP2FrameStreamId(
+ SpdyStreamId current_frame_stream_id,
+ SpdyFrameType frame_type_field);
+
+// If |wire_setting_id| is the on-the-wire representation of a defined SETTINGS
+// parameter, parse it to |*setting_id| and return true.
+NET_EXPORT_PRIVATE bool ParseSettingsId(int wire_setting_id,
+ SpdySettingsIds* setting_id);
+
+// Return if |id| corresponds to a defined setting;
+// stringify |id| to |*settings_id_string| regardless.
+NET_EXPORT_PRIVATE bool SettingsIdToString(SpdySettingsIds id,
+ const char** settings_id_string);
+
+// Returns true if a given on-the-wire enumeration of a RST_STREAM status code
+// is valid, false otherwise.
+NET_EXPORT_PRIVATE bool IsValidRstStreamStatus(int rst_stream_status_field);
+
+// Parses a RST_STREAM status code from an on-the-wire enumeration.
+// Behavior is undefined for invalid RST_STREAM status code fields; consumers
+// should first use IsValidRstStreamStatus() to verify validity of RST_STREAM
+// status code fields..
+NET_EXPORT_PRIVATE SpdyRstStreamStatus
+ParseRstStreamStatus(int rst_stream_status_field);
+
+// Serializes a given RST_STREAM status code to the on-the-wire enumeration
+// value. Returns -1 on failure (I.E. Invalid RST_STREAM status code for the
+// given version).
+NET_EXPORT_PRIVATE int SerializeRstStreamStatus(
+ SpdyRstStreamStatus rst_stream_status);
+
+// Returns true if a given on-the-wire enumeration of a GOAWAY status code is
+// valid, false otherwise.
+NET_EXPORT_PRIVATE bool IsValidGoAwayStatus(int goaway_status_field);
+
+// Parses a GOAWAY status from an on-the-wire enumeration.
+// Behavior is undefined for invalid GOAWAY status fields; consumers should
+// first use IsValidGoAwayStatus() to verify validity of GOAWAY status fields.
+NET_EXPORT_PRIVATE SpdyGoAwayStatus ParseGoAwayStatus(int goaway_status_field);
+
+// Serializes a given GOAWAY status to the on-the-wire enumeration value.
+// Returns -1 on failure (I.E. Invalid GOAWAY status for the given version).
+NET_EXPORT_PRIVATE int SerializeGoAwayStatus(SpdyGoAwayStatus status);
+
+// Frame type for non-control (i.e. data) frames.
+const int kDataFrameType = 0;
+// Number of octets in the frame header.
+const size_t kFrameHeaderSize = 9;
+// Size, in bytes, of the data frame header.
+const size_t kDataFrameMinimumSize = kFrameHeaderSize;
+// Maximum possible configurable size of a frame in octets.
+const size_t kMaxFrameSizeLimit = kSpdyMaxFrameSizeLimit + kFrameHeaderSize;
+// Size of a header block size field. Valid only for SPDY 3.
+const size_t kSizeOfSizeField = sizeof(uint32_t);
+// Per-header overhead for block size accounting in bytes.
+const size_t kPerHeaderOverhead = 32;
+// Initial window size for a stream in bytes.
+const int32_t kInitialStreamWindowSize = 64 * 1024 - 1;
+// Initial window size for a session in bytes.
+const int32_t kInitialSessionWindowSize = 64 * 1024 - 1;
+// The NPN string for HTTP2, "h2".
+extern const char* const kHttp2Npn;
// Variant type (i.e. tagged union) that is either a SPDY 3.x priority value,
// or else an HTTP/2 stream dependency tuple {parent stream ID, weight,
@@ -654,7 +402,7 @@ typedef StreamPrecedence<SpdyStreamId> SpdyStreamPrecedence;
class SpdyFrameVisitor;
-// Intermediate representation for SPDY frames.
+// Intermediate representation for HTTP2 frames.
class NET_EXPORT_PRIVATE SpdyFrameIR {
public:
virtual ~SpdyFrameIR() {}
@@ -804,51 +552,6 @@ class NET_EXPORT_PRIVATE SpdyDataIR
DISALLOW_COPY_AND_ASSIGN(SpdyDataIR);
};
-class NET_EXPORT_PRIVATE SpdySynStreamIR : public SpdyFrameWithHeaderBlockIR {
- public:
- explicit SpdySynStreamIR(SpdyStreamId stream_id)
- : SpdySynStreamIR(stream_id, SpdyHeaderBlock()) {}
- SpdySynStreamIR(SpdyStreamId stream_id, SpdyHeaderBlock header_block)
- : SpdyFrameWithHeaderBlockIR(stream_id, std::move(header_block)),
- associated_to_stream_id_(0),
- priority_(0),
- unidirectional_(false) {}
- SpdyStreamId associated_to_stream_id() const {
- return associated_to_stream_id_;
- }
- void set_associated_to_stream_id(SpdyStreamId stream_id) {
- associated_to_stream_id_ = stream_id;
- }
- SpdyPriority priority() const { return priority_; }
- void set_priority(SpdyPriority priority) { priority_ = priority; }
- bool unidirectional() const { return unidirectional_; }
- void set_unidirectional(bool unidirectional) {
- unidirectional_ = unidirectional;
- }
-
- void Visit(SpdyFrameVisitor* visitor) const override;
-
- private:
- SpdyStreamId associated_to_stream_id_;
- SpdyPriority priority_;
- bool unidirectional_;
-
- DISALLOW_COPY_AND_ASSIGN(SpdySynStreamIR);
-};
-
-class NET_EXPORT_PRIVATE SpdySynReplyIR : public SpdyFrameWithHeaderBlockIR {
- public:
- explicit SpdySynReplyIR(SpdyStreamId stream_id)
- : SpdySynReplyIR(stream_id, SpdyHeaderBlock()) {}
- SpdySynReplyIR(SpdyStreamId stream_id, SpdyHeaderBlock header_block)
- : SpdyFrameWithHeaderBlockIR(stream_id, std::move(header_block)) {}
-
- void Visit(SpdyFrameVisitor* visitor) const override;
-
- private:
- DISALLOW_COPY_AND_ASSIGN(SpdySynReplyIR);
-};
-
class NET_EXPORT_PRIVATE SpdyRstStreamIR : public SpdyFrameWithStreamIdIR {
public:
SpdyRstStreamIR(SpdyStreamId stream_id, SpdyRstStreamStatus status);
@@ -872,33 +575,13 @@ class NET_EXPORT_PRIVATE SpdyRstStreamIR : public SpdyFrameWithStreamIdIR {
class NET_EXPORT_PRIVATE SpdySettingsIR : public SpdyFrameIR {
public:
- // Associates flags with a value.
- struct Value {
- Value() : persist_value(false),
- persisted(false),
- value(0) {}
- bool persist_value;
- bool persisted;
- int32_t value;
- };
- typedef std::map<SpdySettingsIds, Value> ValueMap;
-
SpdySettingsIR();
-
~SpdySettingsIR() override;
// Overwrites as appropriate.
- const ValueMap& values() const { return values_; }
- void AddSetting(SpdySettingsIds id,
- bool persist_value,
- bool persisted,
- int32_t value) {
- values_[id].persist_value = persist_value;
- values_[id].persisted = persisted;
- values_[id].value = value;
- }
+ const SettingsMap& values() const { return values_; }
+ void AddSetting(SpdySettingsIds id, int32_t value) { values_[id] = value; }
- bool clear_settings() const { return clear_settings_; }
bool is_ack() const { return is_ack_; }
void set_is_ack(bool is_ack) {
is_ack_ = is_ack;
@@ -907,8 +590,7 @@ class NET_EXPORT_PRIVATE SpdySettingsIR : public SpdyFrameIR {
void Visit(SpdyFrameVisitor* visitor) const override;
private:
- ValueMap values_;
- bool clear_settings_;
+ SettingsMap values_;
bool is_ack_;
DISALLOW_COPY_AND_ASSIGN(SpdySettingsIR);
@@ -919,7 +601,6 @@ class NET_EXPORT_PRIVATE SpdyPingIR : public SpdyFrameIR {
explicit SpdyPingIR(SpdyPingId id) : id_(id), is_ack_(false) {}
SpdyPingId id() const { return id_; }
- // ACK logic is valid only for SPDY versions 4 and above.
bool is_ack() const { return is_ack_; }
void set_is_ack(bool is_ack) { is_ack_ = is_ack; }
@@ -1241,8 +922,6 @@ class SpdySerializedFrame {
// method of this class will be called.
class SpdyFrameVisitor {
public:
- virtual void VisitSynStream(const SpdySynStreamIR& syn_stream) = 0;
- virtual void VisitSynReply(const SpdySynReplyIR& syn_reply) = 0;
virtual void VisitRstStream(const SpdyRstStreamIR& rst_stream) = 0;
virtual void VisitSettings(const SpdySettingsIR& settings) = 0;
virtual void VisitPing(const SpdyPingIR& ping) = 0;
diff --git a/chromium/net/spdy/spdy_protocol_test.cc b/chromium/net/spdy/spdy_protocol_test.cc
index 290009dc992..3c5d55471a8 100644
--- a/chromium/net/spdy/spdy_protocol_test.cc
+++ b/chromium/net/spdy/spdy_protocol_test.cc
@@ -14,11 +14,12 @@
#include "net/test/gtest_util.h"
#include "testing/gtest/include/gtest/gtest.h"
-using std::ostream;
+using std::string;
namespace net {
-ostream& operator<<(ostream& os, const SpdyStreamPrecedence precedence) {
+std::ostream& operator<<(std::ostream& os,
+ const SpdyStreamPrecedence precedence) {
if (precedence.is_spdy3_priority()) {
os << "SpdyStreamPrecedence[spdy3_priority=" << precedence.spdy3_priority()
<< "]";
@@ -32,83 +33,6 @@ ostream& operator<<(ostream& os, const SpdyStreamPrecedence precedence) {
namespace test {
-TEST(SpdyProtocolDeathTest, TestSpdySettingsAndIdOutOfBounds) {
- std::unique_ptr<SettingsFlagsAndId> flags_and_id;
-
- EXPECT_SPDY_BUG(flags_and_id.reset(new SettingsFlagsAndId(1, 0xffffffff)),
- "SPDY setting ID too large.");
- // Make sure that we get expected values in opt mode.
- if (flags_and_id.get() != nullptr) {
- EXPECT_EQ(1, flags_and_id->flags());
- EXPECT_EQ(0xffffffu, flags_and_id->id());
- }
-}
-
-TEST(SpdyProtocolTest, IsValidHTTP2FrameStreamId) {
- // Stream-specific frames must have non-zero stream ids
- EXPECT_TRUE(SpdyConstants::IsValidHTTP2FrameStreamId(1, DATA));
- EXPECT_FALSE(SpdyConstants::IsValidHTTP2FrameStreamId(0, DATA));
- EXPECT_TRUE(SpdyConstants::IsValidHTTP2FrameStreamId(1, HEADERS));
- EXPECT_FALSE(SpdyConstants::IsValidHTTP2FrameStreamId(0, HEADERS));
- EXPECT_TRUE(SpdyConstants::IsValidHTTP2FrameStreamId(1, PRIORITY));
- EXPECT_FALSE(SpdyConstants::IsValidHTTP2FrameStreamId(0, PRIORITY));
- EXPECT_TRUE(SpdyConstants::IsValidHTTP2FrameStreamId(1, RST_STREAM));
- EXPECT_FALSE(SpdyConstants::IsValidHTTP2FrameStreamId(0, RST_STREAM));
- EXPECT_TRUE(SpdyConstants::IsValidHTTP2FrameStreamId(1, CONTINUATION));
- EXPECT_FALSE(SpdyConstants::IsValidHTTP2FrameStreamId(0, CONTINUATION));
- EXPECT_TRUE(SpdyConstants::IsValidHTTP2FrameStreamId(1, PUSH_PROMISE));
- EXPECT_FALSE(SpdyConstants::IsValidHTTP2FrameStreamId(0, PUSH_PROMISE));
-
- // Connection-level frames must have zero stream ids
- EXPECT_FALSE(SpdyConstants::IsValidHTTP2FrameStreamId(1, GOAWAY));
- EXPECT_TRUE(SpdyConstants::IsValidHTTP2FrameStreamId(0, GOAWAY));
- EXPECT_FALSE(SpdyConstants::IsValidHTTP2FrameStreamId(1, SETTINGS));
- EXPECT_TRUE(SpdyConstants::IsValidHTTP2FrameStreamId(0, SETTINGS));
- EXPECT_FALSE(SpdyConstants::IsValidHTTP2FrameStreamId(1, PING));
- EXPECT_TRUE(SpdyConstants::IsValidHTTP2FrameStreamId(0, PING));
-
- // Frames that are neither stream-specific nor connection-level
- // should not have their stream id declared invalid
- EXPECT_TRUE(SpdyConstants::IsValidHTTP2FrameStreamId(1, WINDOW_UPDATE));
- EXPECT_TRUE(SpdyConstants::IsValidHTTP2FrameStreamId(0, WINDOW_UPDATE));
-}
-
-TEST(SpdyDataIRTest, Construct) {
- // Confirm that it makes a string of zero length from a StringPiece(nullptr).
- base::StringPiece s1;
- SpdyDataIR d1(1, s1);
- EXPECT_EQ(d1.data_len(), 0ul);
- EXPECT_NE(d1.data(), nullptr);
-
- // Confirms makes a copy of char array.
- const char s2[] = "something";
- SpdyDataIR d2(2, s2);
- EXPECT_EQ(base::StringPiece(d2.data(), d2.data_len()), s2);
- EXPECT_NE(base::StringPiece(d1.data(), d1.data_len()), s2);
-
- // Confirm copies a const string.
- const std::string foo = "foo";
- SpdyDataIR d3(3, foo);
- EXPECT_EQ(foo, d3.data());
-
- // Confirm copies a non-const string.
- std::string bar = "bar";
- SpdyDataIR d4(4, bar);
- EXPECT_EQ("bar", bar);
- EXPECT_EQ("bar", base::StringPiece(d4.data(), d4.data_len()));
-
- // Confirm moves an rvalue reference. Note that the test string "baz" is too
- // short to trigger the move optimization, and instead a copy occurs.
- std::string baz = "the quick brown fox";
- SpdyDataIR d5(5, std::move(baz));
- EXPECT_EQ("", baz);
- EXPECT_EQ(base::StringPiece(d5.data(), d5.data_len()), "the quick brown fox");
-
- // Confirms makes a copy of string literal.
- SpdyDataIR d7(7, "something else");
- EXPECT_EQ(base::StringPiece(d7.data(), d7.data_len()), "something else");
-}
-
TEST(SpdyProtocolTest, ClampSpdy3Priority) {
EXPECT_SPDY_BUG(EXPECT_EQ(7, ClampSpdy3Priority(8)), "Invalid priority: 8");
EXPECT_EQ(kV3LowestPriority, ClampSpdy3Priority(kV3LowestPriority));
@@ -153,6 +77,76 @@ TEST(SpdyProtocolTest, Http2WeightToSpdy3Priority) {
EXPECT_EQ(7u, Http2WeightToSpdy3Priority(1));
}
+TEST(SpdyProtocolTest, IsValidHTTP2FrameStreamId) {
+ // Stream-specific frames must have non-zero stream ids
+ EXPECT_TRUE(IsValidHTTP2FrameStreamId(1, DATA));
+ EXPECT_FALSE(IsValidHTTP2FrameStreamId(0, DATA));
+ EXPECT_TRUE(IsValidHTTP2FrameStreamId(1, HEADERS));
+ EXPECT_FALSE(IsValidHTTP2FrameStreamId(0, HEADERS));
+ EXPECT_TRUE(IsValidHTTP2FrameStreamId(1, PRIORITY));
+ EXPECT_FALSE(IsValidHTTP2FrameStreamId(0, PRIORITY));
+ EXPECT_TRUE(IsValidHTTP2FrameStreamId(1, RST_STREAM));
+ EXPECT_FALSE(IsValidHTTP2FrameStreamId(0, RST_STREAM));
+ EXPECT_TRUE(IsValidHTTP2FrameStreamId(1, CONTINUATION));
+ EXPECT_FALSE(IsValidHTTP2FrameStreamId(0, CONTINUATION));
+ EXPECT_TRUE(IsValidHTTP2FrameStreamId(1, PUSH_PROMISE));
+ EXPECT_FALSE(IsValidHTTP2FrameStreamId(0, PUSH_PROMISE));
+
+ // Connection-level frames must have zero stream ids
+ EXPECT_FALSE(IsValidHTTP2FrameStreamId(1, GOAWAY));
+ EXPECT_TRUE(IsValidHTTP2FrameStreamId(0, GOAWAY));
+ EXPECT_FALSE(IsValidHTTP2FrameStreamId(1, SETTINGS));
+ EXPECT_TRUE(IsValidHTTP2FrameStreamId(0, SETTINGS));
+ EXPECT_FALSE(IsValidHTTP2FrameStreamId(1, PING));
+ EXPECT_TRUE(IsValidHTTP2FrameStreamId(0, PING));
+
+ // Frames that are neither stream-specific nor connection-level
+ // should not have their stream id declared invalid
+ EXPECT_TRUE(IsValidHTTP2FrameStreamId(1, WINDOW_UPDATE));
+ EXPECT_TRUE(IsValidHTTP2FrameStreamId(0, WINDOW_UPDATE));
+}
+
+TEST(SpdyProtocolTest, ParseSettingsId) {
+ SpdySettingsIds setting_id;
+ EXPECT_FALSE(ParseSettingsId(0, &setting_id));
+ EXPECT_TRUE(ParseSettingsId(1, &setting_id));
+ EXPECT_EQ(SETTINGS_HEADER_TABLE_SIZE, setting_id);
+ EXPECT_TRUE(ParseSettingsId(2, &setting_id));
+ EXPECT_EQ(SETTINGS_ENABLE_PUSH, setting_id);
+ EXPECT_TRUE(ParseSettingsId(3, &setting_id));
+ EXPECT_EQ(SETTINGS_MAX_CONCURRENT_STREAMS, setting_id);
+ EXPECT_TRUE(ParseSettingsId(4, &setting_id));
+ EXPECT_EQ(SETTINGS_INITIAL_WINDOW_SIZE, setting_id);
+ EXPECT_TRUE(ParseSettingsId(5, &setting_id));
+ EXPECT_EQ(SETTINGS_MAX_FRAME_SIZE, setting_id);
+ EXPECT_TRUE(ParseSettingsId(6, &setting_id));
+ EXPECT_EQ(SETTINGS_MAX_HEADER_LIST_SIZE, setting_id);
+ EXPECT_FALSE(ParseSettingsId(7, &setting_id));
+}
+
+TEST(SpdyProtocolTest, SettingsIdToString) {
+ struct {
+ SpdySettingsIds setting_id;
+ bool expected_bool;
+ const string expected_string;
+ } test_cases[] = {
+ {static_cast<SpdySettingsIds>(0), false, "SETTINGS_UNKNOWN"},
+ {SETTINGS_HEADER_TABLE_SIZE, true, "SETTINGS_HEADER_TABLE_SIZE"},
+ {SETTINGS_ENABLE_PUSH, true, "SETTINGS_ENABLE_PUSH"},
+ {SETTINGS_MAX_CONCURRENT_STREAMS, true,
+ "SETTINGS_MAX_CONCURRENT_STREAMS"},
+ {SETTINGS_INITIAL_WINDOW_SIZE, true, "SETTINGS_INITIAL_WINDOW_SIZE"},
+ {SETTINGS_MAX_FRAME_SIZE, true, "SETTINGS_MAX_FRAME_SIZE"},
+ {SETTINGS_MAX_HEADER_LIST_SIZE, true, "SETTINGS_MAX_HEADER_LIST_SIZE"},
+ {static_cast<SpdySettingsIds>(7), false, "SETTINGS_UNKNOWN"}};
+ for (auto test_case : test_cases) {
+ const char* settings_id_string;
+ EXPECT_EQ(test_case.expected_bool,
+ SettingsIdToString(test_case.setting_id, &settings_id_string));
+ EXPECT_EQ(test_case.expected_string, settings_id_string);
+ }
+}
+
TEST(SpdyStreamPrecedenceTest, Basic) {
SpdyStreamPrecedence spdy3_prec(2);
EXPECT_TRUE(spdy3_prec.is_spdy3_priority());
@@ -225,5 +219,41 @@ TEST(SpdyStreamPrecedenceTest, Equals) {
EXPECT_NE(spdy3_prec, h2_prec);
}
+TEST(SpdyDataIRTest, Construct) {
+ // Confirm that it makes a string of zero length from a StringPiece(nullptr).
+ base::StringPiece s1;
+ SpdyDataIR d1(1, s1);
+ EXPECT_EQ(d1.data_len(), 0ul);
+ EXPECT_NE(d1.data(), nullptr);
+
+ // Confirms makes a copy of char array.
+ const char s2[] = "something";
+ SpdyDataIR d2(2, s2);
+ EXPECT_EQ(base::StringPiece(d2.data(), d2.data_len()), s2);
+ EXPECT_NE(base::StringPiece(d1.data(), d1.data_len()), s2);
+
+ // Confirm copies a const string.
+ const string foo = "foo";
+ SpdyDataIR d3(3, foo);
+ EXPECT_EQ(foo, d3.data());
+
+ // Confirm copies a non-const string.
+ string bar = "bar";
+ SpdyDataIR d4(4, bar);
+ EXPECT_EQ("bar", bar);
+ EXPECT_EQ("bar", base::StringPiece(d4.data(), d4.data_len()));
+
+ // Confirm moves an rvalue reference. Note that the test string "baz" is too
+ // short to trigger the move optimization, and instead a copy occurs.
+ string baz = "the quick brown fox";
+ SpdyDataIR d5(5, std::move(baz));
+ EXPECT_EQ("", baz);
+ EXPECT_EQ(base::StringPiece(d5.data(), d5.data_len()), "the quick brown fox");
+
+ // Confirms makes a copy of string literal.
+ SpdyDataIR d7(7, "something else");
+ EXPECT_EQ(base::StringPiece(d7.data(), d7.data_len()), "something else");
+}
+
} // namespace test
} // namespace net
diff --git a/chromium/net/spdy/spdy_protocol_test_utils.cc b/chromium/net/spdy/spdy_protocol_test_utils.cc
index dd600ded2d5..73cc067cca2 100644
--- a/chromium/net/spdy/spdy_protocol_test_utils.cc
+++ b/chromium/net/spdy/spdy_protocol_test_utils.cc
@@ -164,8 +164,8 @@ namespace test {
DVLOG(1) << "actual doesn't contain param: " << param;
return ::testing::AssertionFailure();
}
- uint32_t expected_value = entry.second.value;
- uint32_t actual_value = actual_itr->second.value;
+ uint32_t expected_value = entry.second;
+ uint32_t actual_value = actual_itr->second;
if (expected_value != actual_value) {
DVLOG(1) << "Values don't match for parameter: " << param;
return ::testing::AssertionFailure();
diff --git a/chromium/net/spdy/spdy_proxy_client_socket.cc b/chromium/net/spdy/spdy_proxy_client_socket.cc
index ea771b3cf82..d2b40c9e826 100644
--- a/chromium/net/spdy/spdy_proxy_client_socket.cc
+++ b/chromium/net/spdy/spdy_proxy_client_socket.cc
@@ -167,7 +167,7 @@ bool SpdyProxyClientSocket::WasEverUsed() const {
return was_ever_used_ || (spdy_stream_.get() && spdy_stream_->WasEverUsed());
}
-bool SpdyProxyClientSocket::WasNpnNegotiated() const {
+bool SpdyProxyClientSocket::WasAlpnNegotiated() const {
return false;
}
@@ -430,26 +430,26 @@ int SpdyProxyClientSocket::DoReadReplyComplete(int result) {
// SpdyStream::Delegate methods:
// Called when SYN frame has been sent.
// Returns true if no more data to be sent after SYN frame.
-void SpdyProxyClientSocket::OnRequestHeadersSent() {
+void SpdyProxyClientSocket::OnHeadersSent() {
DCHECK_EQ(next_state_, STATE_SEND_REQUEST_COMPLETE);
OnIOComplete(OK);
}
-SpdyResponseHeadersStatus SpdyProxyClientSocket::OnResponseHeadersUpdated(
+void SpdyProxyClientSocket::OnHeadersReceived(
const SpdyHeaderBlock& response_headers) {
// If we've already received the reply, existing headers are too late.
// TODO(mbelshe): figure out a way to make HEADERS frames useful after the
// initial response.
if (next_state_ != STATE_READ_REPLY_COMPLETE)
- return RESPONSE_HEADERS_ARE_COMPLETE;
+ return;
// Save the response
- if (!SpdyHeadersToHttpResponse(response_headers, &response_))
- return RESPONSE_HEADERS_ARE_INCOMPLETE;
+ const bool headers_valid =
+ SpdyHeadersToHttpResponse(response_headers, &response_);
+ DCHECK(headers_valid);
OnIOComplete(OK);
- return RESPONSE_HEADERS_ARE_COMPLETE;
}
// Called when data is received or on EOF (if |buffer| is NULL).
diff --git a/chromium/net/spdy/spdy_proxy_client_socket.h b/chromium/net/spdy/spdy_proxy_client_socket.h
index 645f5c56c7d..1471d3f72ae 100644
--- a/chromium/net/spdy/spdy_proxy_client_socket.h
+++ b/chromium/net/spdy/spdy_proxy_client_socket.h
@@ -32,7 +32,6 @@
namespace net {
-class AddressList;
class HttpStream;
class IOBuffer;
class SpdyStream;
@@ -71,7 +70,7 @@ class NET_EXPORT_PRIVATE SpdyProxyClientSocket : public ProxyClientSocket,
void SetSubresourceSpeculation() override;
void SetOmniboxSpeculation() override;
bool WasEverUsed() const override;
- bool WasNpnNegotiated() const override;
+ bool WasAlpnNegotiated() const override;
NextProto GetNegotiatedProtocol() const override;
bool GetSSLInfo(SSLInfo* ssl_info) override;
void GetConnectionAttempts(ConnectionAttempts* out) const override;
@@ -92,9 +91,8 @@ class NET_EXPORT_PRIVATE SpdyProxyClientSocket : public ProxyClientSocket,
int GetLocalAddress(IPEndPoint* address) const override;
// SpdyStream::Delegate implementation.
- void OnRequestHeadersSent() override;
- SpdyResponseHeadersStatus OnResponseHeadersUpdated(
- const SpdyHeaderBlock& response_headers) override;
+ void OnHeadersSent() override;
+ void OnHeadersReceived(const SpdyHeaderBlock& response_headers) override;
void OnDataReceived(std::unique_ptr<SpdyBuffer> buffer) override;
void OnDataSent() override;
void OnTrailers(const SpdyHeaderBlock& trailers) override;
diff --git a/chromium/net/spdy/spdy_proxy_client_socket_unittest.cc b/chromium/net/spdy/spdy_proxy_client_socket_unittest.cc
index 7c09e576b03..23e030b7360 100644
--- a/chromium/net/spdy/spdy_proxy_client_socket_unittest.cc
+++ b/chromium/net/spdy/spdy_proxy_client_socket_unittest.cc
@@ -837,8 +837,8 @@ TEST_F(SpdyProxyClientSocketTest, ReadErrorResponseBody) {
SpdySerializedFrame msg1(ConstructBodyFrame(kMsg1, kLen1));
SpdySerializedFrame msg2(ConstructBodyFrame(kMsg2, kLen2));
MockRead reads[] = {
- CreateMockRead(resp, 1, ASYNC), CreateMockRead(msg1, 2, ASYNC),
- CreateMockRead(msg2, 3, ASYNC), MockRead(ASYNC, 0, 4), // EOF
+ CreateMockRead(resp, 1, ASYNC), CreateMockRead(msg1, 2, SYNCHRONOUS),
+ CreateMockRead(msg2, 3, SYNCHRONOUS), MockRead(SYNCHRONOUS, 0, 4), // EOF
};
Initialize(reads, arraysize(reads), writes, arraysize(writes));
diff --git a/chromium/net/spdy/spdy_read_queue.h b/chromium/net/spdy/spdy_read_queue.h
index 87fc0ab4475..769c2c69689 100644
--- a/chromium/net/spdy/spdy_read_queue.h
+++ b/chromium/net/spdy/spdy_read_queue.h
@@ -2,8 +2,8 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#ifndef NET_SPDY_SPDY_BUFFER_QUEUE_H_
-#define NET_SPDY_SPDY_BUFFER_QUEUE_H_
+#ifndef NET_SPDY_SPDY_READ_QUEUE_H_
+#define NET_SPDY_SPDY_READ_QUEUE_H_
#include <cstddef>
#include <deque>
@@ -50,4 +50,4 @@ class NET_EXPORT_PRIVATE SpdyReadQueue {
} // namespace net
-#endif // NET_SPDY_SPDY_BUFFER_QUEUE_H_
+#endif // NET_SPDY_SPDY_READ_QUEUE_H_
diff --git a/chromium/net/spdy/spdy_session.cc b/chromium/net/spdy/spdy_session.cc
index dd9785986f3..36793c985d0 100644
--- a/chromium/net/spdy/spdy_session.cc
+++ b/chromium/net/spdy/spdy_session.cc
@@ -13,6 +13,7 @@
#include "base/compiler_specific.h"
#include "base/location.h"
#include "base/logging.h"
+#include "base/memory/ptr_util.h"
#include "base/metrics/histogram_macros.h"
#include "base/metrics/sparse_histogram.h"
#include "base/profiler/scoped_tracker.h"
@@ -66,6 +67,35 @@ const int kHungIntervalSeconds = 10;
// Minimum seconds that unclaimed pushed streams will be kept in memory.
const int kMinPushedStreamLifetimeSeconds = 300;
+// Default initial value for HTTP/2 SETTINGS.
+const uint32_t kDefaultInitialHeaderTableSize = 4096;
+const uint32_t kDefaultInitialEnablePush = 1;
+const uint32_t kDefaultInitialInitialWindowSize = 65535;
+const uint32_t kDefaultInitialMaxFrameSize = 16384;
+
+bool IsSpdySettingAtDefaultInitialValue(SpdySettingsIds setting_id,
+ uint32_t value) {
+ switch (setting_id) {
+ case SETTINGS_HEADER_TABLE_SIZE:
+ return value == kDefaultInitialHeaderTableSize;
+ case SETTINGS_ENABLE_PUSH:
+ return value == kDefaultInitialEnablePush;
+ case SETTINGS_MAX_CONCURRENT_STREAMS:
+ // There is no initial limit on the number of concurrent streams.
+ return false;
+ case SETTINGS_INITIAL_WINDOW_SIZE:
+ return value == kDefaultInitialInitialWindowSize;
+ case SETTINGS_MAX_FRAME_SIZE:
+ return value == kDefaultInitialMaxFrameSize;
+ case SETTINGS_MAX_HEADER_LIST_SIZE:
+ // There is no initial limit on the size of the header list.
+ return false;
+ default:
+ // Undefined parameters have no initial value.
+ return false;
+ }
+}
+
std::unique_ptr<base::Value> NetLogSpdyHeadersSentCallback(
const SpdyHeaderBlock* headers,
bool fin,
@@ -75,7 +105,7 @@ std::unique_ptr<base::Value> NetLogSpdyHeadersSentCallback(
SpdyStreamId parent_stream_id,
bool exclusive,
NetLogCaptureMode capture_mode) {
- std::unique_ptr<base::DictionaryValue> dict(new base::DictionaryValue());
+ auto dict = base::MakeUnique<base::DictionaryValue>();
dict->Set("headers", ElideSpdyHeaderBlockForNetLog(*headers, capture_mode));
dict->SetBoolean("fin", fin);
dict->SetInteger("stream_id", stream_id);
@@ -93,7 +123,7 @@ std::unique_ptr<base::Value> NetLogSpdyHeadersReceivedCallback(
bool fin,
SpdyStreamId stream_id,
NetLogCaptureMode capture_mode) {
- std::unique_ptr<base::DictionaryValue> dict(new base::DictionaryValue());
+ auto dict = base::MakeUnique<base::DictionaryValue>();
dict->Set("headers", ElideSpdyHeaderBlockForNetLog(*headers, capture_mode));
dict->SetBoolean("fin", fin);
dict->SetInteger("stream_id", stream_id);
@@ -104,7 +134,7 @@ std::unique_ptr<base::Value> NetLogSpdySessionCloseCallback(
int net_error,
const std::string* description,
NetLogCaptureMode /* capture_mode */) {
- std::unique_ptr<base::DictionaryValue> dict(new base::DictionaryValue());
+ auto dict = base::MakeUnique<base::DictionaryValue>();
dict->SetInteger("net_error", net_error);
dict->SetString("description", *description);
return std::move(dict);
@@ -113,7 +143,7 @@ std::unique_ptr<base::Value> NetLogSpdySessionCloseCallback(
std::unique_ptr<base::Value> NetLogSpdySessionCallback(
const HostPortProxyPair* host_pair,
NetLogCaptureMode /* capture_mode */) {
- std::unique_ptr<base::DictionaryValue> dict(new base::DictionaryValue());
+ auto dict = base::MakeUnique<base::DictionaryValue>();
dict->SetString("host", host_pair->first.ToString());
dict->SetString("proxy", host_pair->second.ToPacString());
return std::move(dict);
@@ -122,7 +152,7 @@ std::unique_ptr<base::Value> NetLogSpdySessionCallback(
std::unique_ptr<base::Value> NetLogSpdyInitializedCallback(
NetLogSource source,
NetLogCaptureMode /* capture_mode */) {
- std::unique_ptr<base::DictionaryValue> dict(new base::DictionaryValue());
+ auto dict = base::MakeUnique<base::DictionaryValue>();
if (source.IsValid()) {
source.AddToEventParameters(dict.get());
}
@@ -133,19 +163,17 @@ std::unique_ptr<base::Value> NetLogSpdyInitializedCallback(
std::unique_ptr<base::Value> NetLogSpdySettingsCallback(
const HostPortPair& host_port_pair,
NetLogCaptureMode /* capture_mode */) {
- std::unique_ptr<base::DictionaryValue> dict(new base::DictionaryValue());
+ auto dict = base::MakeUnique<base::DictionaryValue>();
dict->SetString("host", host_port_pair.ToString());
return std::move(dict);
}
std::unique_ptr<base::Value> NetLogSpdySettingCallback(
SpdySettingsIds id,
- SpdySettingsFlags flags,
uint32_t value,
NetLogCaptureMode /* capture_mode */) {
- std::unique_ptr<base::DictionaryValue> dict(new base::DictionaryValue());
- dict->SetInteger("id", SpdyConstants::SerializeSettingId(HTTP2, id));
- dict->SetInteger("flags", flags);
+ auto dict = base::MakeUnique<base::DictionaryValue>();
+ dict->SetInteger("id", id);
dict->SetInteger("value", value);
return std::move(dict);
}
@@ -153,16 +181,14 @@ std::unique_ptr<base::Value> NetLogSpdySettingCallback(
std::unique_ptr<base::Value> NetLogSpdySendSettingsCallback(
const SettingsMap* settings,
NetLogCaptureMode /* capture_mode */) {
- std::unique_ptr<base::DictionaryValue> dict(new base::DictionaryValue());
- std::unique_ptr<base::ListValue> settings_list(new base::ListValue());
+ auto dict = base::MakeUnique<base::DictionaryValue>();
+ auto settings_list = base::MakeUnique<base::ListValue>();
for (SettingsMap::const_iterator it = settings->begin();
it != settings->end(); ++it) {
const SpdySettingsIds id = it->first;
- const SpdySettingsFlags flags = it->second.first;
- const uint32_t value = it->second.second;
- settings_list->AppendString(base::StringPrintf(
- "[id:%u flags:%u value:%u]",
- SpdyConstants::SerializeSettingId(HTTP2, id), flags, value));
+ const uint32_t value = it->second;
+ settings_list->AppendString(
+ base::StringPrintf("[id:%u value:%u]", id, value));
}
dict->Set("settings", std::move(settings_list));
return std::move(dict);
@@ -172,7 +198,7 @@ std::unique_ptr<base::Value> NetLogSpdyWindowUpdateFrameCallback(
SpdyStreamId stream_id,
uint32_t delta,
NetLogCaptureMode /* capture_mode */) {
- std::unique_ptr<base::DictionaryValue> dict(new base::DictionaryValue());
+ auto dict = base::MakeUnique<base::DictionaryValue>();
dict->SetInteger("stream_id", static_cast<int>(stream_id));
dict->SetInteger("delta", delta);
return std::move(dict);
@@ -182,7 +208,7 @@ std::unique_ptr<base::Value> NetLogSpdySessionWindowUpdateCallback(
int32_t delta,
int32_t window_size,
NetLogCaptureMode /* capture_mode */) {
- std::unique_ptr<base::DictionaryValue> dict(new base::DictionaryValue());
+ auto dict = base::MakeUnique<base::DictionaryValue>();
dict->SetInteger("delta", delta);
dict->SetInteger("window_size", window_size);
return std::move(dict);
@@ -193,7 +219,7 @@ std::unique_ptr<base::Value> NetLogSpdyDataCallback(
int size,
bool fin,
NetLogCaptureMode /* capture_mode */) {
- std::unique_ptr<base::DictionaryValue> dict(new base::DictionaryValue());
+ auto dict = base::MakeUnique<base::DictionaryValue>();
dict->SetInteger("stream_id", static_cast<int>(stream_id));
dict->SetInteger("size", size);
dict->SetBoolean("fin", fin);
@@ -205,7 +231,7 @@ std::unique_ptr<base::Value> NetLogSpdyRstCallback(
int status,
const std::string* description,
NetLogCaptureMode /* capture_mode */) {
- std::unique_ptr<base::DictionaryValue> dict(new base::DictionaryValue());
+ auto dict = base::MakeUnique<base::DictionaryValue>();
dict->SetInteger("stream_id", static_cast<int>(stream_id));
dict->SetInteger("status", status);
dict->SetString("description", *description);
@@ -217,7 +243,7 @@ std::unique_ptr<base::Value> NetLogSpdyPingCallback(
bool is_ack,
const char* type,
NetLogCaptureMode /* capture_mode */) {
- std::unique_ptr<base::DictionaryValue> dict(new base::DictionaryValue());
+ auto dict = base::MakeUnique<base::DictionaryValue>();
dict->SetInteger("unique_id", static_cast<int>(unique_id));
dict->SetString("type", type);
dict->SetBoolean("is_ack", is_ack);
@@ -231,7 +257,7 @@ std::unique_ptr<base::Value> NetLogSpdyGoAwayCallback(
SpdyGoAwayStatus status,
base::StringPiece debug_data,
NetLogCaptureMode capture_mode) {
- std::unique_ptr<base::DictionaryValue> dict(new base::DictionaryValue());
+ auto dict = base::MakeUnique<base::DictionaryValue>();
dict->SetInteger("last_accepted_stream_id",
static_cast<int>(last_stream_id));
dict->SetInteger("active_streams", active_streams);
@@ -247,7 +273,7 @@ std::unique_ptr<base::Value> NetLogSpdyPushPromiseReceivedCallback(
SpdyStreamId stream_id,
SpdyStreamId promised_stream_id,
NetLogCaptureMode capture_mode) {
- std::unique_ptr<base::DictionaryValue> dict(new base::DictionaryValue());
+ auto dict = base::MakeUnique<base::DictionaryValue>();
dict->Set("headers", ElideSpdyHeaderBlockForNetLog(*headers, capture_mode));
dict->SetInteger("id", stream_id);
dict->SetInteger("promised_stream_id", promised_stream_id);
@@ -258,12 +284,42 @@ std::unique_ptr<base::Value> NetLogSpdyAdoptedPushStreamCallback(
SpdyStreamId stream_id,
const GURL* url,
NetLogCaptureMode capture_mode) {
- std::unique_ptr<base::DictionaryValue> dict(new base::DictionaryValue());
+ auto dict = base::MakeUnique<base::DictionaryValue>();
dict->SetInteger("stream_id", stream_id);
dict->SetString("url", url->spec());
return std::move(dict);
}
+std::unique_ptr<base::Value> NetLogSpdySessionStalledCallback(
+ size_t num_active_streams,
+ size_t num_created_streams,
+ size_t num_pushed_streams,
+ size_t max_concurrent_streams,
+ const std::string& url,
+ NetLogCaptureMode capture_mode) {
+ auto dict = base::MakeUnique<base::DictionaryValue>();
+ dict->SetInteger("num_active_streams", num_active_streams);
+ dict->SetInteger("num_created_streams", num_created_streams);
+ dict->SetInteger("num_pushed_streams", num_pushed_streams);
+ dict->SetInteger("max_concurrent_streams", max_concurrent_streams);
+ dict->SetString("url", url);
+ return std::move(dict);
+}
+
+std::unique_ptr<base::Value> NetLogSpdyPriorityCallback(
+ SpdyStreamId stream_id,
+ SpdyStreamId parent_stream_id,
+ int weight,
+ bool exclusive,
+ NetLogCaptureMode capture_mode) {
+ auto dict = base::MakeUnique<base::DictionaryValue>();
+ dict->SetInteger("stream_id", stream_id);
+ dict->SetInteger("parent_stream_id", parent_stream_id);
+ dict->SetInteger("weight", weight);
+ dict->SetBoolean("exclusive", exclusive);
+ return std::move(dict);
+}
+
// Helper function to return the total size of an array of objects
// with .size() member functions.
template <typename T, size_t N> size_t GetTotalSize(const T (&arr)[N]) {
@@ -399,28 +455,26 @@ Error MapFramerErrorToNetError(SpdyFramer::SpdyError err) {
SpdyProtocolErrorDetails MapRstStreamStatusToProtocolError(
SpdyRstStreamStatus status) {
switch (status) {
+ case RST_STREAM_NO_ERROR:
+ return STATUS_CODE_NO_ERROR;
case RST_STREAM_PROTOCOL_ERROR:
return STATUS_CODE_PROTOCOL_ERROR;
- case RST_STREAM_INVALID_STREAM:
- return STATUS_CODE_INVALID_STREAM;
- case RST_STREAM_REFUSED_STREAM:
- return STATUS_CODE_REFUSED_STREAM;
- case RST_STREAM_UNSUPPORTED_VERSION:
- return STATUS_CODE_UNSUPPORTED_VERSION;
- case RST_STREAM_CANCEL:
- return STATUS_CODE_CANCEL;
case RST_STREAM_INTERNAL_ERROR:
return STATUS_CODE_INTERNAL_ERROR;
case RST_STREAM_FLOW_CONTROL_ERROR:
return STATUS_CODE_FLOW_CONTROL_ERROR;
- case RST_STREAM_STREAM_IN_USE:
- return STATUS_CODE_STREAM_IN_USE;
- case RST_STREAM_STREAM_ALREADY_CLOSED:
- return STATUS_CODE_STREAM_ALREADY_CLOSED;
- case RST_STREAM_FRAME_SIZE_ERROR:
- return STATUS_CODE_FRAME_SIZE_ERROR;
case RST_STREAM_SETTINGS_TIMEOUT:
return STATUS_CODE_SETTINGS_TIMEOUT;
+ case RST_STREAM_STREAM_CLOSED:
+ return STATUS_CODE_STREAM_CLOSED;
+ case RST_STREAM_FRAME_SIZE_ERROR:
+ return STATUS_CODE_FRAME_SIZE_ERROR;
+ case RST_STREAM_REFUSED_STREAM:
+ return STATUS_CODE_REFUSED_STREAM;
+ case RST_STREAM_CANCEL:
+ return STATUS_CODE_CANCEL;
+ case RST_STREAM_COMPRESSION_ERROR:
+ return STATUS_CODE_COMPRESSION_ERROR;
case RST_STREAM_CONNECT_ERROR:
return STATUS_CODE_CONNECT_ERROR;
case RST_STREAM_ENHANCE_YOUR_CALM:
@@ -429,8 +483,6 @@ SpdyProtocolErrorDetails MapRstStreamStatusToProtocolError(
return STATUS_CODE_INADEQUATE_SECURITY;
case RST_STREAM_HTTP_1_1_REQUIRED:
return STATUS_CODE_HTTP_1_1_REQUIRED;
- case RST_STREAM_NO_ERROR:
- return STATUS_CODE_NO_ERROR;
default:
NOTREACHED();
return static_cast<SpdyProtocolErrorDetails>(-1);
@@ -539,15 +591,6 @@ void SpdyStreamRequest::Reset() {
callback_.Reset();
}
-SpdySession::ActiveStreamInfo::ActiveStreamInfo()
- : stream(NULL), waiting_for_reply_headers_frame(false) {}
-
-SpdySession::ActiveStreamInfo::ActiveStreamInfo(SpdyStream* stream)
- : stream(stream),
- waiting_for_reply_headers_frame(stream->type() != SPDY_PUSH_STREAM) {}
-
-SpdySession::ActiveStreamInfo::~ActiveStreamInfo() {}
-
SpdySession::UnclaimedPushedStreamContainer::UnclaimedPushedStreamContainer(
SpdySession* spdy_session)
: spdy_session_(spdy_session) {}
@@ -649,8 +692,9 @@ SpdySession::SpdySession(const SpdySessionKey& spdy_session_key,
bool enable_sending_initial_data,
bool enable_ping_based_connection_checking,
size_t session_max_recv_window_size,
- size_t stream_max_recv_window_size,
+ const SettingsMap& initial_settings,
TimeFunc time_func,
+ ServerPushDelegate* push_delegate,
ProxyDelegate* proxy_delegate,
NetLog* net_log)
: in_io_loop_(false),
@@ -662,7 +706,7 @@ SpdySession::SpdySession(const SpdySessionKey& spdy_session_key,
stream_hi_water_mark_(kFirstStreamId),
last_accepted_push_stream_id_(0),
unclaimed_pushed_streams_(this),
- push_delegate_(nullptr),
+ push_delegate_(push_delegate),
num_pushed_streams_(0u),
num_active_pushed_streams_(0u),
bytes_pushed_count_(0u),
@@ -674,8 +718,10 @@ SpdySession::SpdySession(const SpdySessionKey& spdy_session_key,
read_state_(READ_STATE_DO_READ),
write_state_(WRITE_STATE_IDLE),
error_on_close_(OK),
+ initial_settings_(initial_settings),
max_concurrent_streams_(kInitialMaxConcurrentStreams),
- max_concurrent_pushed_streams_(kMaxConcurrentPushedStreams),
+ max_concurrent_pushed_streams_(
+ initial_settings.at(SETTINGS_MAX_CONCURRENT_STREAMS)),
streams_initiated_count_(0),
streams_pushed_count_(0),
streams_pushed_and_claimed_count_(0),
@@ -690,7 +736,9 @@ SpdySession::SpdySession(const SpdySessionKey& spdy_session_key,
session_recv_window_size_(0),
session_unacked_recv_window_bytes_(0),
stream_initial_send_window_size_(kDefaultInitialWindowSize),
- stream_max_recv_window_size_(stream_max_recv_window_size),
+ max_header_table_size_(initial_settings.at(SETTINGS_HEADER_TABLE_SIZE)),
+ stream_max_recv_window_size_(
+ initial_settings.at(SETTINGS_INITIAL_WINDOW_SIZE)),
net_log_(
NetLogWithSource::Make(net_log, NetLogSourceType::HTTP2_SESSION)),
enable_sending_initial_data_(enable_sending_initial_data),
@@ -707,6 +755,11 @@ SpdySession::SpdySession(const SpdySessionKey& spdy_session_key,
base::Bind(&NetLogSpdySessionCallback, &host_port_proxy_pair()));
next_unclaimed_push_stream_sweep_time_ = time_func_() +
base::TimeDelta::FromSeconds(kMinPushedStreamLifetimeSeconds);
+
+ DCHECK(base::ContainsKey(initial_settings_, SETTINGS_HEADER_TABLE_SIZE));
+ DCHECK(base::ContainsKey(initial_settings_, SETTINGS_MAX_CONCURRENT_STREAMS));
+ DCHECK(base::ContainsKey(initial_settings_, SETTINGS_INITIAL_WINDOW_SIZE));
+
// TODO(mbelshe): consider randomization of the stream_hi_water_mark.
}
@@ -748,7 +801,7 @@ void SpdySession::InitializeWithSocket(
buffered_spdy_framer_.reset(new BufferedSpdyFramer());
buffered_spdy_framer_->set_visitor(this);
buffered_spdy_framer_->set_debug_visitor(this);
- buffered_spdy_framer_->UpdateHeaderDecoderTableSize(kMaxHeaderTableSize);
+ buffered_spdy_framer_->UpdateHeaderDecoderTableSize(max_header_table_size_);
net_log_.AddEvent(NetLogEventType::HTTP2_SESSION_INITIALIZED,
base::Bind(&NetLogSpdyInitializedCallback,
@@ -780,6 +833,7 @@ bool SpdySession::VerifyDomainAuthentication(const std::string& domain) {
}
int SpdySession::GetPushStream(const GURL& url,
+ RequestPriority priority,
base::WeakPtr<SpdyStream>* stream,
const NetLogWithSource& stream_net_log) {
CHECK(!in_io_loop_);
@@ -793,7 +847,26 @@ int SpdySession::GetPushStream(const GURL& url,
if (*stream) {
DCHECK_LT(streams_pushed_and_claimed_count_, streams_pushed_count_);
streams_pushed_and_claimed_count_++;
+
+ // If the stream is still open, update its priority to match
+ // the priority of the matching request.
+ if (!(*stream)->IsClosed() && (*stream)->priority() != priority) {
+ (*stream)->set_priority(priority);
+
+ // Send PRIORITY updates.
+ auto updates = priority_dependency_state_.OnStreamUpdate(
+ (*stream)->stream_id(),
+ ConvertRequestPriorityToSpdyPriority(priority));
+ for (auto u : updates) {
+ ActiveStreamMap::iterator it = active_streams_.find(u.id);
+ DCHECK(it != active_streams_.end());
+ int weight = Spdy3PriorityToHttp2Weight(
+ ConvertRequestPriorityToSpdyPriority(it->second->priority()));
+ EnqueuePriorityFrame(u.id, u.dependent_stream_id, weight, u.exclusive);
+ }
+ }
}
+
return OK;
}
@@ -831,7 +904,13 @@ int SpdySession::TryCreateStream(
return CreateStream(*request, stream);
}
- net_log().AddEvent(NetLogEventType::HTTP2_SESSION_STALLED_MAX_STREAMS);
+ if (net_log().IsCapturing()) {
+ net_log().AddEvent(
+ NetLogEventType::HTTP2_SESSION_STALLED_MAX_STREAMS,
+ base::Bind(&NetLogSpdySessionStalledCallback, active_streams_.size(),
+ created_streams_.size(), num_pushed_streams_,
+ max_concurrent_streams_, request->url().spec()));
+ }
RequestPriority priority = request->priority();
CHECK_GE(priority, MINIMUM_PRIORITY);
CHECK_LE(priority, MAXIMUM_PRIORITY);
@@ -980,6 +1059,12 @@ bool SpdySession::CloseOneIdleConnection() {
return false;
}
+void SpdySession::DumpMemoryStats(StreamSocket::SocketMemoryStats* stats,
+ bool* is_session_active) const {
+ *is_session_active = is_active();
+ connection_->DumpMemoryStats(stats);
+}
+
void SpdySession::EnqueueStreamWrite(
const base::WeakPtr<SpdyStream>& stream,
SpdyFrameType frame_type,
@@ -995,7 +1080,7 @@ std::unique_ptr<SpdySerializedFrame> SpdySession::CreateHeaders(
SpdyHeaderBlock block) {
ActiveStreamMap::const_iterator it = active_streams_.find(stream_id);
CHECK(it != active_streams_.end());
- CHECK_EQ(it->second.stream->stream_id(), stream_id);
+ CHECK_EQ(it->second->stream_id(), stream_id);
SendPrefacePingIfNoneInFlight();
@@ -1008,8 +1093,8 @@ std::unique_ptr<SpdySerializedFrame> SpdySession::CreateHeaders(
SpdyStreamId dependent_stream_id = 0;
bool exclusive = false;
- priority_dependency_state_.OnStreamSynSent(stream_id, spdy_priority,
- &dependent_stream_id, &exclusive);
+ priority_dependency_state_.OnStreamCreation(stream_id, spdy_priority,
+ &dependent_stream_id, &exclusive);
if (net_log().IsCapturing()) {
net_log().AddEvent(
@@ -1044,7 +1129,7 @@ std::unique_ptr<SpdyBuffer> SpdySession::CreateDataBuffer(
ActiveStreamMap::const_iterator it = active_streams_.find(stream_id);
CHECK(it != active_streams_.end());
- SpdyStream* stream = it->second.stream;
+ SpdyStream* stream = it->second;
CHECK_EQ(stream->stream_id(), stream_id);
if (len < 0) {
@@ -1199,7 +1284,7 @@ void SpdySession::CloseActiveStreamIterator(ActiveStreamMap::iterator it,
// TODO(mbelshe): We should send a RST_STREAM control frame here
// so that the server can cancel a large send.
- std::unique_ptr<SpdyStream> owned_stream(it->second.stream);
+ std::unique_ptr<SpdyStream> owned_stream(it->second);
active_streams_.erase(it);
priority_dependency_state_.OnStreamDestruction(owned_stream->stream_id());
@@ -1241,7 +1326,7 @@ void SpdySession::ResetStreamIterator(ActiveStreamMap::iterator it,
// Send the RST_STREAM frame first as CloseActiveStreamIterator()
// may close us.
SpdyStreamId stream_id = it->first;
- RequestPriority priority = it->second.stream->priority();
+ RequestPriority priority = it->second->priority();
EnqueueResetStreamFrame(stream_id, priority, status, description);
// Removes any pending writes for the stream except for possibly an
@@ -1267,6 +1352,28 @@ void SpdySession::EnqueueResetStreamFrame(SpdyStreamId stream_id,
RecordProtocolErrorHistogram(MapRstStreamStatusToProtocolError(status));
}
+void SpdySession::EnqueuePriorityFrame(SpdyStreamId stream_id,
+ SpdyStreamId dependency_id,
+ int weight,
+ bool exclusive) {
+ net_log().AddEvent(NetLogEventType::HTTP2_STREAM_SEND_PRIORITY,
+ base::Bind(&NetLogSpdyPriorityCallback, stream_id,
+ dependency_id, weight, exclusive));
+
+ DCHECK(buffered_spdy_framer_.get());
+ std::unique_ptr<SpdySerializedFrame> frame(
+ buffered_spdy_framer_->CreatePriority(stream_id, dependency_id, weight,
+ exclusive));
+
+ // PRIORITY frames describe sequenced updates to the tree, so they must
+ // be serialized. We do this by queueing all PRIORITY frames at HIGHEST
+ // priority.
+ EnqueueWrite(HIGHEST, PRIORITY,
+ base::MakeUnique<SimpleBufferProducer>(
+ base::MakeUnique<SpdyBuffer>(std::move(frame))),
+ base::WeakPtr<SpdyStream>());
+}
+
void SpdySession::PumpReadLoop(ReadState expected_read_state, int result) {
CHECK(!in_io_loop_);
if (availability_state_ == STATE_DRAINING) {
@@ -1690,7 +1797,7 @@ void SpdySession::LogAbandonedStream(SpdyStream* stream, Error status) {
void SpdySession::LogAbandonedActiveStream(ActiveStreamMap::const_iterator it,
Error status) {
DCHECK_GT(it->first, 0u);
- LogAbandonedStream(it->second.stream, status);
+ LogAbandonedStream(it->second, status);
++streams_abandoned_count_;
}
@@ -1848,8 +1955,7 @@ void SpdySession::InsertActivatedStream(std::unique_ptr<SpdyStream> stream) {
SpdyStreamId stream_id = stream->stream_id();
CHECK_NE(stream_id, 0u);
std::pair<ActiveStreamMap::iterator, bool> result =
- active_streams_.insert(
- std::make_pair(stream_id, ActiveStreamInfo(stream.get())));
+ active_streams_.insert(std::make_pair(stream_id, stream.get()));
CHECK(result.second);
ignore_result(stream.release());
}
@@ -1896,8 +2002,8 @@ base::WeakPtr<SpdyStream> SpdySession::GetActivePushStream(const GURL& url) {
net_log_.AddEvent(NetLogEventType::HTTP2_STREAM_ADOPTED_PUSH_STREAM,
base::Bind(&NetLogSpdyAdoptedPushStreamCallback,
- active_it->second.stream->stream_id(), &url));
- return active_it->second.stream->GetWeakPtr();
+ active_it->second->stream_id(), &url));
+ return active_it->second->GetWeakPtr();
}
url::SchemeHostPort SpdySession::GetServer() {
@@ -1905,12 +2011,16 @@ url::SchemeHostPort SpdySession::GetServer() {
host_port_pair().host(), host_port_pair().port());
}
+bool SpdySession::GetRemoteEndpoint(IPEndPoint* endpoint) {
+ return GetPeerAddress(endpoint) == OK;
+}
+
bool SpdySession::GetSSLInfo(SSLInfo* ssl_info) const {
return connection_->socket()->GetSSLInfo(ssl_info);
}
-bool SpdySession::WasNpnNegotiated() const {
- return connection_->socket()->WasNpnNegotiated();
+bool SpdySession::WasAlpnNegotiated() const {
+ return connection_->socket()->WasAlpnNegotiated();
}
NextProto SpdySession::GetNegotiatedProtocol() const {
@@ -1967,7 +2077,7 @@ void SpdySession::OnDataFrameHeader(SpdyStreamId stream_id,
if (it == active_streams_.end())
return;
- SpdyStream* stream = it->second.stream;
+ SpdyStream* stream = it->second;
CHECK_EQ(stream->stream_id(), stream_id);
DCHECK(buffered_spdy_framer_);
@@ -2010,18 +2120,10 @@ void SpdySession::OnStreamFrameData(SpdyStreamId stream_id,
if (it == active_streams_.end())
return;
- SpdyStream* stream = it->second.stream;
+ SpdyStream* stream = it->second;
CHECK_EQ(stream->stream_id(), stream_id);
stream->AddRawReceivedBytes(len);
-
- if (it->second.waiting_for_reply_headers_frame) {
- const std::string& error = "DATA received before HEADERS.";
- stream->LogStreamError(ERR_SPDY_PROTOCOL_ERROR, error);
- ResetStreamIterator(it, RST_STREAM_PROTOCOL_ERROR, error);
- return;
- }
-
stream->OnDataReceived(std::move(buffer));
}
@@ -2032,30 +2134,15 @@ void SpdySession::OnStreamEnd(SpdyStreamId stream_id) {
base::Bind(&NetLogSpdyDataCallback, stream_id, 0, true));
}
- // Build the buffer as early as possible so that we go through the
- // session flow control checks and update
- // |unacked_recv_window_bytes_| properly even when the stream is
- // inactive (since the other side has still reduced its session send
- // window).
- std::unique_ptr<SpdyBuffer> buffer;
-
ActiveStreamMap::iterator it = active_streams_.find(stream_id);
-
// By the time data comes in, the stream may already be inactive.
if (it == active_streams_.end())
return;
- SpdyStream* stream = it->second.stream;
+ SpdyStream* stream = it->second;
CHECK_EQ(stream->stream_id(), stream_id);
- if (it->second.waiting_for_reply_headers_frame) {
- const std::string& error = "DATA received before HEADERS.";
- stream->LogStreamError(ERR_SPDY_PROTOCOL_ERROR, error);
- ResetStreamIterator(it, RST_STREAM_PROTOCOL_ERROR, error);
- return;
- }
-
- stream->OnDataReceived(std::move(buffer));
+ stream->OnDataReceived(std::unique_ptr<SpdyBuffer>());
}
void SpdySession::OnStreamPadding(SpdyStreamId stream_id, size_t len) {
@@ -2071,7 +2158,7 @@ void SpdySession::OnStreamPadding(SpdyStreamId stream_id, size_t len) {
ActiveStreamMap::iterator it = active_streams_.find(stream_id);
if (it == active_streams_.end())
return;
- it->second.stream->OnPaddingConsumed(len);
+ it->second->OnPaddingConsumed(len);
}
void SpdySession::OnSettings() {
@@ -2092,15 +2179,14 @@ void SpdySession::OnSettings() {
buffered_spdy_framer_->SerializeFrame(settings_ir))));
}
-void SpdySession::OnSetting(SpdySettingsIds id, uint8_t flags, uint32_t value) {
+void SpdySession::OnSetting(SpdySettingsIds id, uint32_t value) {
CHECK(in_io_loop_);
HandleSetting(id, value);
// Log the setting.
net_log_.AddEvent(NetLogEventType::HTTP2_SESSION_RECV_SETTING,
- base::Bind(&NetLogSpdySettingCallback, id,
- static_cast<SpdySettingsFlags>(flags), value));
+ base::Bind(&NetLogSpdySettingCallback, id, value));
}
void SpdySession::OnSendCompressedFrame(
@@ -2108,17 +2194,18 @@ void SpdySession::OnSendCompressedFrame(
SpdyFrameType type,
size_t payload_len,
size_t frame_len) {
- if (type != HEADERS)
+ if (type != HEADERS) {
return;
+ }
DCHECK(buffered_spdy_framer_.get());
size_t compressed_len =
- frame_len - buffered_spdy_framer_->GetSynStreamMinimumSize();
+ frame_len - buffered_spdy_framer_->GetFrameMinimumSize();
if (payload_len) {
// Make sure we avoid early decimal truncation.
int compression_pct = 100 - (100 * compressed_len) / payload_len;
- UMA_HISTOGRAM_PERCENTAGE("Net.SpdySynStreamCompressionPercentage",
+ UMA_HISTOGRAM_PERCENTAGE("Net.SpdyHeadersCompressionPercentage",
compression_pct);
}
}
@@ -2130,41 +2217,6 @@ void SpdySession::OnReceiveCompressedFrame(
last_compressed_frame_len_ = frame_len;
}
-int SpdySession::OnInitialResponseHeadersReceived(
- const SpdyHeaderBlock& response_headers,
- base::Time response_time,
- base::TimeTicks recv_first_byte_time,
- SpdyStream* stream) {
- CHECK(in_io_loop_);
- SpdyStreamId stream_id = stream->stream_id();
-
- if (stream->type() == SPDY_PUSH_STREAM) {
- DCHECK(stream->IsReservedRemote());
- if (max_concurrent_pushed_streams_ &&
- num_active_pushed_streams_ >= max_concurrent_pushed_streams_) {
- ResetStream(stream_id,
- RST_STREAM_REFUSED_STREAM,
- "Stream concurrency limit reached.");
- return STATUS_CODE_REFUSED_STREAM;
- }
- }
-
- if (stream->type() == SPDY_PUSH_STREAM) {
- // Will be balanced in DeleteStream.
- num_active_pushed_streams_++;
- }
-
- // May invalidate |stream|.
- int rv = stream->OnInitialResponseHeadersReceived(
- response_headers, response_time, recv_first_byte_time);
- if (rv < 0) {
- DCHECK_NE(rv, ERR_IO_PENDING);
- DCHECK(active_streams_.find(stream_id) == active_streams_.end());
- }
-
- return rv;
-}
-
void SpdySession::DeleteExpiredPushedStreams() {
if (unclaimed_pushed_streams_.empty())
return;
@@ -2190,7 +2242,7 @@ void SpdySession::DeleteExpiredPushedStreams() {
ActiveStreamMap::iterator active_it = active_streams_.find(*to_close_it);
if (active_it == active_streams_.end())
continue;
- bytes_pushed_and_unclaimed_count_ += active_it->second.stream->recv_bytes();
+ bytes_pushed_and_unclaimed_count_ += active_it->second->recv_bytes();
LogAbandonedActiveStream(active_it, ERR_INVALID_SPDY_STREAM);
// CloseActiveStreamIterator() will remove the stream from
@@ -2225,29 +2277,29 @@ void SpdySession::OnHeaders(SpdyStreamId stream_id,
return;
}
- SpdyStream* stream = it->second.stream;
+ SpdyStream* stream = it->second;
CHECK_EQ(stream->stream_id(), stream_id);
stream->AddRawReceivedBytes(last_compressed_frame_len_);
last_compressed_frame_len_ = 0;
- base::Time response_time = base::Time::Now();
- base::TimeTicks recv_first_byte_time = time_func_();
-
- if (it->second.waiting_for_reply_headers_frame) {
- it->second.waiting_for_reply_headers_frame = false;
- ignore_result(OnInitialResponseHeadersReceived(
- headers, response_time, recv_first_byte_time, stream));
- } else if (it->second.stream->IsReservedRemote()) {
- ignore_result(OnInitialResponseHeadersReceived(
- headers, response_time, recv_first_byte_time, stream));
- } else {
- int rv = stream->OnAdditionalResponseHeadersReceived(headers);
- if (rv < 0) {
- DCHECK_NE(rv, ERR_IO_PENDING);
- DCHECK(active_streams_.find(stream_id) == active_streams_.end());
+ if (it->second->IsReservedRemote()) {
+ DCHECK_EQ(SPDY_PUSH_STREAM, stream->type());
+ if (max_concurrent_pushed_streams_ &&
+ num_active_pushed_streams_ >= max_concurrent_pushed_streams_) {
+ ResetStream(stream_id, RST_STREAM_REFUSED_STREAM,
+ "Stream concurrency limit reached.");
+ return;
}
+
+ // Will be balanced in DeleteStream.
+ num_active_pushed_streams_++;
}
+
+ base::Time response_time = base::Time::Now();
+ base::TimeTicks recv_first_byte_time = time_func_();
+ // May invalidate |stream|.
+ stream->OnHeadersReceived(headers, response_time, recv_first_byte_time);
}
void SpdySession::OnAltSvc(
@@ -2278,7 +2330,7 @@ void SpdySession::OnAltSvc(
const ActiveStreamMap::iterator it = active_streams_.find(stream_id);
if (it == active_streams_.end())
return;
- const GURL& gurl(it->second.stream->url());
+ const GURL& gurl(it->second->url());
if (!gurl.SchemeIs("https"))
return;
scheme_host_port = url::SchemeHostPort(gurl);
@@ -2330,7 +2382,7 @@ void SpdySession::OnRstStream(SpdyStreamId stream_id,
return;
}
- CHECK_EQ(it->second.stream->stream_id(), stream_id);
+ CHECK_EQ(it->second->stream_id(), stream_id);
if (status == RST_STREAM_NO_ERROR) {
CloseActiveStreamIterator(it, ERR_SPDY_RST_STREAM_NO_ERROR_RECEIVED);
@@ -2338,7 +2390,7 @@ void SpdySession::OnRstStream(SpdyStreamId stream_id,
CloseActiveStreamIterator(it, ERR_SPDY_SERVER_REFUSED_STREAM);
} else if (status == RST_STREAM_HTTP_1_1_REQUIRED) {
// TODO(bnc): Record histogram with number of open streams capped at 50.
- it->second.stream->LogStreamError(
+ it->second->LogStreamError(
ERR_HTTP_1_1_REQUIRED,
base::StringPrintf(
"SPDY session closed because of stream with status: %d", status));
@@ -2346,7 +2398,7 @@ void SpdySession::OnRstStream(SpdyStreamId stream_id,
} else {
RecordProtocolErrorHistogram(
PROTOCOL_ERROR_RST_STREAM_FOR_NON_ACTIVE_STREAM);
- it->second.stream->LogStreamError(
+ it->second->LogStreamError(
ERR_SPDY_PROTOCOL_ERROR,
base::StringPrintf("SPDY stream closed with status: %d", status));
// TODO(mbelshe): Map from Spdy-protocol errors to something sensical.
@@ -2440,7 +2492,7 @@ void SpdySession::OnWindowUpdate(SpdyStreamId stream_id,
return;
}
- SpdyStream* stream = it->second.stream;
+ SpdyStream* stream = it->second;
CHECK_EQ(stream->stream_id(), stream_id);
if (delta_window_size < 1) {
@@ -2452,20 +2504,19 @@ void SpdySession::OnWindowUpdate(SpdyStreamId stream_id,
return;
}
- CHECK_EQ(it->second.stream->stream_id(), stream_id);
- it->second.stream->IncreaseSendWindowSize(delta_window_size);
+ CHECK_EQ(it->second->stream_id(), stream_id);
+ it->second->IncreaseSendWindowSize(delta_window_size);
}
}
-bool SpdySession::TryCreatePushStream(SpdyStreamId stream_id,
+void SpdySession::TryCreatePushStream(SpdyStreamId stream_id,
SpdyStreamId associated_stream_id,
- SpdyPriority priority,
SpdyHeaderBlock headers) {
// Server-initiated streams should have even sequence numbers.
if ((stream_id & 0x1) != 0) {
LOG(WARNING) << "Received invalid push stream id " << stream_id;
CloseSessionOnError(ERR_SPDY_PROTOCOL_ERROR, "Odd push stream id.");
- return false;
+ return;
}
// Server-initiated streams must be associated with client-initiated streams.
@@ -2473,7 +2524,7 @@ bool SpdySession::TryCreatePushStream(SpdyStreamId stream_id,
LOG(WARNING) << "Received push stream id " << stream_id
<< " with invalid associated stream id";
CloseSessionOnError(ERR_SPDY_PROTOCOL_ERROR, "Push on even stream id.");
- return false;
+ return;
}
if (stream_id <= last_accepted_push_stream_id_) {
@@ -2482,20 +2533,20 @@ bool SpdySession::TryCreatePushStream(SpdyStreamId stream_id,
CloseSessionOnError(
ERR_SPDY_PROTOCOL_ERROR,
"New push stream id must be greater than the last accepted.");
- return false;
+ return;
}
if (IsStreamActive(stream_id)) {
// We should not get here, we'll start going away earlier on
// |last_seen_push_stream_id_| check.
LOG(WARNING) << "Received push for active stream " << stream_id;
- return false;
+ return;
}
last_accepted_push_stream_id_ = stream_id;
- RequestPriority request_priority =
- ConvertSpdyPriorityToRequestPriority(priority);
+ // Pushed streams are speculative, so they start at an IDLE priority.
+ const RequestPriority request_priority = IDLE;
if (availability_state_ == STATE_GOING_AWAY) {
// TODO(akalin): This behavior isn't in the SPDY spec, although it
@@ -2504,7 +2555,7 @@ bool SpdySession::TryCreatePushStream(SpdyStreamId stream_id,
request_priority,
RST_STREAM_REFUSED_STREAM,
"push stream request received when going away");
- return false;
+ return;
}
if (associated_stream_id == 0) {
@@ -2516,7 +2567,7 @@ bool SpdySession::TryCreatePushStream(SpdyStreamId stream_id,
stream_id);
EnqueueResetStreamFrame(
stream_id, request_priority, RST_STREAM_REFUSED_STREAM, description);
- return false;
+ return;
}
streams_pushed_count_++;
@@ -2530,7 +2581,7 @@ bool SpdySession::TryCreatePushStream(SpdyStreamId stream_id,
request_priority,
RST_STREAM_PROTOCOL_ERROR,
"Pushed stream url was invalid: " + gurl.spec());
- return false;
+ return;
}
// Verify we have a valid stream association.
@@ -2538,12 +2589,10 @@ bool SpdySession::TryCreatePushStream(SpdyStreamId stream_id,
active_streams_.find(associated_stream_id);
if (associated_it == active_streams_.end()) {
EnqueueResetStreamFrame(
- stream_id,
- request_priority,
- RST_STREAM_INVALID_STREAM,
+ stream_id, request_priority, RST_STREAM_STREAM_CLOSED,
base::StringPrintf("Received push for inactive associated stream %d",
associated_stream_id));
- return false;
+ return;
}
DCHECK(gurl.is_valid());
@@ -2563,10 +2612,10 @@ bool SpdySession::TryCreatePushStream(SpdyStreamId stream_id,
base::StringPrintf("Rejected push of cross origin HTTPS content %d "
"from trusted proxy",
associated_stream_id));
- return false;
+ return;
}
} else {
- GURL associated_url(associated_it->second.stream->GetUrlFromHeaders());
+ GURL associated_url(associated_it->second->GetUrlFromHeaders());
if (associated_url.SchemeIs("https")) {
SSLInfo ssl_info;
CHECK(GetSSLInfo(&ssl_info));
@@ -2577,7 +2626,7 @@ bool SpdySession::TryCreatePushStream(SpdyStreamId stream_id,
stream_id, request_priority, RST_STREAM_REFUSED_STREAM,
base::StringPrintf("Rejected push stream %d on secure connection",
associated_stream_id));
- return false;
+ return;
}
} else {
// TODO(bnc): Change SpdyNetworkTransactionTests to use secure sockets.
@@ -2587,7 +2636,7 @@ bool SpdySession::TryCreatePushStream(SpdyStreamId stream_id,
base::StringPrintf(
"Rejected cross origin push stream %d on insecure connection",
associated_stream_id));
- return false;
+ return;
}
}
}
@@ -2603,7 +2652,7 @@ bool SpdySession::TryCreatePushStream(SpdyStreamId stream_id,
request_priority,
RST_STREAM_PROTOCOL_ERROR,
"Received duplicate pushed stream with url: " + gurl.spec());
- return false;
+ return;
}
std::unique_ptr<SpdyStream> stream(
@@ -2612,14 +2661,18 @@ bool SpdySession::TryCreatePushStream(SpdyStreamId stream_id,
stream_max_recv_window_size_, net_log_));
stream->set_stream_id(stream_id);
- // In HTTP2 PUSH_PROMISE arrives on associated stream.
- if (associated_it != active_streams_.end()) {
- associated_it->second.stream->AddRawReceivedBytes(
- last_compressed_frame_len_);
- } else {
- stream->AddRawReceivedBytes(last_compressed_frame_len_);
- }
+ // Convert RequestPriority to a SpdyPriority to send in a PRIORITY frame.
+ SpdyPriority spdy_priority =
+ ConvertRequestPriorityToSpdyPriority(request_priority);
+ SpdyStreamId dependency_id = 0;
+ bool exclusive = false;
+ priority_dependency_state_.OnStreamCreation(stream_id, spdy_priority,
+ &dependency_id, &exclusive);
+ EnqueuePriorityFrame(stream_id, dependency_id,
+ Spdy3PriorityToHttp2Weight(spdy_priority), exclusive);
+ // PUSH_PROMISE arrives on associated stream.
+ associated_it->second->AddRawReceivedBytes(last_compressed_frame_len_);
last_compressed_frame_len_ = 0;
UnclaimedPushedStreamContainer::const_iterator inserted_pushed_it =
@@ -2633,7 +2686,7 @@ bool SpdySession::TryCreatePushStream(SpdyStreamId stream_id,
ActiveStreamMap::iterator active_it = active_streams_.find(stream_id);
if (active_it == active_streams_.end()) {
NOTREACHED();
- return false;
+ return;
}
// Notify the push_delegate that a push promise has been received.
@@ -2642,10 +2695,10 @@ bool SpdySession::TryCreatePushStream(SpdyStreamId stream_id,
weak_factory_.GetWeakPtr(), gurl));
}
- active_it->second.stream->OnPushPromiseHeadersReceived(std::move(headers));
- DCHECK(active_it->second.stream->IsReservedRemote());
+ active_it->second->OnPushPromiseHeadersReceived(std::move(headers));
+ DCHECK(active_it->second->IsReservedRemote());
num_pushed_streams_++;
- return true;
+ return;
}
void SpdySession::OnPushPromise(SpdyStreamId stream_id,
@@ -2659,20 +2712,15 @@ void SpdySession::OnPushPromise(SpdyStreamId stream_id,
&headers, stream_id, promised_stream_id));
}
- // Any priority will do.
- // TODO(baranovich): pass parent stream id priority?
- if (!TryCreatePushStream(promised_stream_id, stream_id, 0,
- std::move(headers)))
- return;
+ TryCreatePushStream(promised_stream_id, stream_id, std::move(headers));
}
void SpdySession::SendStreamWindowUpdate(SpdyStreamId stream_id,
uint32_t delta_window_size) {
ActiveStreamMap::const_iterator it = active_streams_.find(stream_id);
CHECK(it != active_streams_.end());
- CHECK_EQ(it->second.stream->stream_id(), stream_id);
- SendWindowUpdateFrame(
- stream_id, delta_window_size, it->second.stream->priority());
+ CHECK_EQ(it->second->stream_id(), stream_id);
+ SendWindowUpdateFrame(stream_id, delta_window_size, it->second->priority());
}
void SpdySession::SendInitialData() {
@@ -2687,15 +2735,13 @@ void SpdySession::SendInitialData() {
std::move(connection_header_prefix_frame));
// First, notify the server about the settings they should use when
- // communicating with us.
+ // communicating with us. Only send settings that have a value different from
+ // the protocol default value.
SettingsMap settings_map;
- settings_map[SETTINGS_HEADER_TABLE_SIZE] =
- SettingsFlagsAndValue(SETTINGS_FLAG_NONE, kMaxHeaderTableSize);
- settings_map[SETTINGS_MAX_CONCURRENT_STREAMS] =
- SettingsFlagsAndValue(SETTINGS_FLAG_NONE, kMaxConcurrentPushedStreams);
- if (stream_max_recv_window_size_ != kDefaultInitialWindowSize) {
- settings_map[SETTINGS_INITIAL_WINDOW_SIZE] =
- SettingsFlagsAndValue(SETTINGS_FLAG_NONE, stream_max_recv_window_size_);
+ for (auto setting : initial_settings_) {
+ if (!IsSpdySettingAtDefaultInitialValue(setting.first, setting.second)) {
+ settings_map.insert(setting);
+ }
}
SendSettings(settings_map);
@@ -2754,7 +2800,7 @@ void SpdySession::HandleSetting(uint32_t id, uint32_t value) {
void SpdySession::UpdateStreamsSendWindowSize(int32_t delta_window_size) {
for (ActiveStreamMap::iterator it = active_streams_.begin();
it != active_streams_.end(); ++it) {
- it->second.stream->AdjustSendWindowSize(delta_window_size);
+ it->second->AdjustSendWindowSize(delta_window_size);
}
for (CreatedStreamSet::const_iterator it = created_streams_.begin();
@@ -2782,7 +2828,7 @@ void SpdySession::SendWindowUpdateFrame(SpdyStreamId stream_id,
RequestPriority priority) {
ActiveStreamMap::const_iterator it = active_streams_.find(stream_id);
if (it != active_streams_.end()) {
- CHECK_EQ(it->second.stream->stream_id(), stream_id);
+ CHECK_EQ(it->second->stream_id(), stream_id);
} else {
CHECK_EQ(stream_id, kSessionFlowControlStreamId);
}
@@ -3058,7 +3104,7 @@ void SpdySession::ResumeSendStalledStreams() {
// to its own send window) but that's okay -- it'll then be
// resumed once its send window increases.
if (it != active_streams_.end())
- it->second.stream->PossiblyResumeIfSendStalled();
+ it->second->PossiblyResumeIfSendStalled();
// The size should decrease unless we got send-stalled again.
if (!IsSendStalled())
diff --git a/chromium/net/spdy/spdy_session.h b/chromium/net/spdy/spdy_session.h
index b7066bc8c0b..6bdb5fcaf24 100644
--- a/chromium/net/spdy/spdy_session.h
+++ b/chromium/net/spdy/spdy_session.h
@@ -33,6 +33,7 @@
#include "net/socket/stream_socket.h"
#include "net/spdy/buffered_spdy_framer.h"
#include "net/spdy/http2_priority_dependencies.h"
+#include "net/spdy/multiplexed_session.h"
#include "net/spdy/server_push_delegate.h"
#include "net/spdy/spdy_alt_svc_wire_format.h"
#include "net/spdy/spdy_buffer.h"
@@ -68,12 +69,6 @@ const int32_t kDefaultInitialWindowSize = 65535;
// sends a SETTINGS frame with a different value.
const size_t kInitialMaxConcurrentStreams = 100;
-// Specifies the maximum HPACK dynamic table size the server is allowed to set.
-const int kMaxHeaderTableSize = 64 * 1024;
-
-// Specifies the maximum concurrent streams server could send (via push).
-const int kMaxConcurrentPushedStreams = 1000;
-
// If more than this many bytes have been read or more than that many
// milliseconds have passed, return ERR_IO_PENDING from ReadLoop.
const int kYieldAfterBytesRead = 32 * 1024;
@@ -116,20 +111,22 @@ enum SpdyProtocolErrorDetails {
// SpdyRstStreamStatus mappings.
STATUS_CODE_NO_ERROR = 41,
STATUS_CODE_PROTOCOL_ERROR = 11,
- STATUS_CODE_INVALID_STREAM = 12,
- STATUS_CODE_REFUSED_STREAM = 13,
- STATUS_CODE_UNSUPPORTED_VERSION = 14,
- STATUS_CODE_CANCEL = 15,
STATUS_CODE_INTERNAL_ERROR = 16,
STATUS_CODE_FLOW_CONTROL_ERROR = 17,
- STATUS_CODE_STREAM_IN_USE = 18,
- STATUS_CODE_STREAM_ALREADY_CLOSED = 19,
- STATUS_CODE_FRAME_SIZE_ERROR = 21,
STATUS_CODE_SETTINGS_TIMEOUT = 32,
+ STATUS_CODE_STREAM_CLOSED = 12,
+ STATUS_CODE_FRAME_SIZE_ERROR = 21,
+ STATUS_CODE_REFUSED_STREAM = 13,
+ STATUS_CODE_CANCEL = 15,
+ STATUS_CODE_COMPRESSION_ERROR = 42,
STATUS_CODE_CONNECT_ERROR = 33,
STATUS_CODE_ENHANCE_YOUR_CALM = 34,
STATUS_CODE_INADEQUATE_SECURITY = 35,
STATUS_CODE_HTTP_1_1_REQUIRED = 36,
+ // Deprecated SpdyRstStrreamStatus mappings.
+ STATUS_CODE_UNSUPPORTED_VERSION = 14,
+ STATUS_CODE_STREAM_IN_USE = 18,
+ STATUS_CODE_STREAM_ALREADY_CLOSED = 19,
// SpdySession errors
PROTOCOL_ERROR_UNEXPECTED_PING = 22,
@@ -141,7 +138,7 @@ enum SpdyProtocolErrorDetails {
PROTOCOL_ERROR_RECEIVE_WINDOW_VIOLATION = 28,
// Next free value.
- NUM_SPDY_PROTOCOL_ERROR_DETAILS = 42,
+ NUM_SPDY_PROTOCOL_ERROR_DETAILS = 43,
};
SpdyProtocolErrorDetails NET_EXPORT_PRIVATE
MapFramerErrorToProtocolError(SpdyFramer::SpdyError error);
@@ -154,7 +151,7 @@ SpdyGoAwayStatus NET_EXPORT_PRIVATE MapNetErrorToGoAwayStatus(Error err);
// to be updated with new values, as do the mapping functions above.
static_assert(17 == SpdyFramer::LAST_ERROR,
"SpdyProtocolErrorDetails / Spdy Errors mismatch");
-static_assert(17 == RST_STREAM_NUM_STATUS_CODES,
+static_assert(14 == RST_STREAM_NUM_STATUS_CODES,
"SpdyProtocolErrorDetails / RstStreamStatus mismatch");
// A helper class used to manage a request to create a stream.
@@ -228,6 +225,7 @@ class NET_EXPORT_PRIVATE SpdyStreamRequest {
class NET_EXPORT SpdySession : public BufferedSpdyFramerVisitorInterface,
public SpdyFramerDebugVisitorInterface,
+ public MultiplexedSession,
public HigherLayeredPool {
public:
// TODO(akalin): Use base::TickClock when it becomes available.
@@ -299,8 +297,9 @@ class NET_EXPORT SpdySession : public BufferedSpdyFramerVisitorInterface,
bool enable_sending_initial_data,
bool enable_ping_based_connection_checking,
size_t session_max_recv_window_size,
- size_t stream_max_recv_window_size,
+ const SettingsMap& initial_settings,
TimeFunc time_func,
+ ServerPushDelegate* push_delegate,
ProxyDelegate* proxy_delegate,
NetLog* net_log);
@@ -323,14 +322,14 @@ class NET_EXPORT SpdySession : public BufferedSpdyFramerVisitorInterface,
// okay to create a new stream (in which case |spdy_stream| is
// reset). Returns an error (not ERR_IO_PENDING) otherwise, and
// resets |spdy_stream|.
+ //
+ // If a stream was found and the stream is still open, the priority
+ // of that stream is updated to match |priority|.
int GetPushStream(const GURL& url,
+ RequestPriority priority,
base::WeakPtr<SpdyStream>* spdy_stream,
const NetLogWithSource& stream_net_log);
- void set_push_delegate(ServerPushDelegate* push_delegate) {
- push_delegate_ = push_delegate;
- }
-
// Called when the pushed stream should be cancelled. If the pushed stream is
// not claimed and active, sends RST to the server to cancel the stream.
void CancelPush(const GURL& url);
@@ -409,23 +408,19 @@ class NET_EXPORT SpdySession : public BufferedSpdyFramerVisitorInterface,
// Returns server infomation in the form of (scheme/host/port).
url::SchemeHostPort GetServer();
- // Fills SSL info in |ssl_info| and returns true when SSL is in use.
- bool GetSSLInfo(SSLInfo* ssl_info) const;
+ // MultiplexedSession methods:
+ bool GetRemoteEndpoint(IPEndPoint* endpoint) override;
+ bool GetSSLInfo(SSLInfo* ssl_info) const override;
+ Error GetTokenBindingSignature(crypto::ECPrivateKey* key,
+ TokenBindingType tb_type,
+ std::vector<uint8_t>* out) override;
// Returns true if ALPN was negotiated for the underlying socket.
- // TODO(bnc): Rename to WasAlpnNegotiated().
- bool WasNpnNegotiated() const;
+ bool WasAlpnNegotiated() const;
// Returns the protocol negotiated via ALPN for the underlying socket.
NextProto GetNegotiatedProtocol() const;
- // Generates the signature used in Token Binding using |*key| and for a Token
- // Binding of type |tb_type|, putting the signature in |*out|. Returns a net
- // error code of OK or ERR_FAILED.
- Error GetTokenBindingSignature(crypto::ECPrivateKey* key,
- TokenBindingType tb_type,
- std::vector<uint8_t>* out);
-
// Send a WINDOW_UPDATE frame for a stream. Called by a stream
// whenever receive window size is increased.
void SendStreamWindowUpdate(SpdyStreamId stream_id,
@@ -565,6 +560,13 @@ class NET_EXPORT SpdySession : public BufferedSpdyFramerVisitorInterface,
// HigherLayeredPool implementation:
bool CloseOneIdleConnection() override;
+ // Dumps memory allocation stats to |stats|. Sets |*is_session_active| to
+ // indicate whether session is active.
+ // |stats| can be assumed as being default initialized upon entry.
+ // Implementation overrides fields in |stats|.
+ void DumpMemoryStats(StreamSocket::SocketMemoryStats* stats,
+ bool* is_session_active) const;
+
private:
friend class test::SpdyStreamTest;
friend class base::RefCounted<SpdySession>;
@@ -614,19 +616,9 @@ class NET_EXPORT SpdySession : public BufferedSpdyFramerVisitorInterface,
FRIEND_TEST_ALL_PREFIXES(SpdyNetworkTransactionTest,
ServerPushValidCrossOriginWithOpenSession);
- typedef std::deque<base::WeakPtr<SpdyStreamRequest> >
+ typedef std::deque<base::WeakPtr<SpdyStreamRequest>>
PendingStreamRequestQueue;
-
- struct ActiveStreamInfo {
- ActiveStreamInfo();
- explicit ActiveStreamInfo(SpdyStream* stream);
- ~ActiveStreamInfo();
-
- SpdyStream* stream;
- bool waiting_for_reply_headers_frame;
- };
- typedef std::map<SpdyStreamId, ActiveStreamInfo> ActiveStreamMap;
-
+ typedef std::map<SpdyStreamId, SpdyStream*> ActiveStreamMap;
typedef std::set<SpdyStream*> CreatedStreamSet;
enum AvailabilityState {
@@ -682,9 +674,8 @@ class NET_EXPORT SpdySession : public BufferedSpdyFramerVisitorInterface,
// possible.
void ProcessPendingStreamRequests();
- bool TryCreatePushStream(SpdyStreamId stream_id,
+ void TryCreatePushStream(SpdyStreamId stream_id,
SpdyStreamId associated_stream_id,
- SpdyPriority priority,
SpdyHeaderBlock headers);
// Close the stream pointed to by the given iterator. Note that that
@@ -704,13 +695,17 @@ class NET_EXPORT SpdySession : public BufferedSpdyFramerVisitorInterface,
// Send a RST_STREAM frame with the given parameters. There should
// either be no active stream with the given ID, or that active
// stream should be closed shortly after this function is called.
- //
- // TODO(akalin): Rename this to EnqueueResetStreamFrame().
void EnqueueResetStreamFrame(SpdyStreamId stream_id,
RequestPriority priority,
SpdyRstStreamStatus status,
const std::string& description);
+ // Send a PRIORITY frame with the given parameters.
+ void EnqueuePriorityFrame(SpdyStreamId stream_id,
+ SpdyStreamId dependency_id,
+ int weight,
+ bool exclusive);
+
// Calls DoReadLoop. Use this function instead of DoReadLoop when
// posting a task to pump the read loop.
void PumpReadLoop(ReadState expected_read_state, int result);
@@ -825,14 +820,6 @@ class NET_EXPORT SpdySession : public BufferedSpdyFramerVisitorInterface,
// list). Returns NULL otherwise.
base::WeakPtr<SpdyStream> GetActivePushStream(const GURL& url);
- // Delegates to |stream->OnInitialResponseHeadersReceived()|. If an
- // error is returned, the last reference to |this| may have been
- // released.
- int OnInitialResponseHeadersReceived(const SpdyHeaderBlock& response_headers,
- base::Time response_time,
- base::TimeTicks recv_first_byte_time,
- SpdyStream* stream);
-
void RecordPingRTTHistogram(base::TimeDelta duration);
void RecordHistograms();
void RecordProtocolErrorHistogram(SpdyProtocolErrorDetails details);
@@ -886,7 +873,7 @@ class NET_EXPORT SpdySession : public BufferedSpdyFramerVisitorInterface,
void OnStreamEnd(SpdyStreamId stream_id) override;
void OnStreamPadding(SpdyStreamId stream_id, size_t len) override;
void OnSettings() override;
- void OnSetting(SpdySettingsIds id, uint8_t flags, uint32_t value) override;
+ void OnSetting(SpdySettingsIds id, uint32_t value) override;
void OnWindowUpdate(SpdyStreamId stream_id, int delta_window_size) override;
void OnPushPromise(SpdyStreamId stream_id,
SpdyStreamId promised_stream_id,
@@ -1106,6 +1093,12 @@ class NET_EXPORT SpdySession : public BufferedSpdyFramerVisitorInterface,
// Initialized to OK.
Error error_on_close_;
+ // Settings that are sent in the initial SETTINGS frame
+ // (if |enable_sending_initial_data_| is true),
+ // and also control SpdySession parameters like initial receive window size
+ // and maximum HPACK dynamic table size.
+ const SettingsMap initial_settings_;
+
// Limits
size_t max_concurrent_streams_;
size_t max_concurrent_pushed_streams_;
@@ -1163,6 +1156,9 @@ class NET_EXPORT SpdySession : public BufferedSpdyFramerVisitorInterface,
// this value for the initial send window size.
int32_t stream_initial_send_window_size_;
+ // The maximum HPACK dynamic table size the server is allowed to set.
+ uint32_t max_header_table_size_;
+
// Initial receive window size for this session's streams. There are
// plans to add a command line switch that would cause a SETTINGS
// frame with window size announcement to be sent on startup. Newly
diff --git a/chromium/net/spdy/spdy_session_key.h b/chromium/net/spdy/spdy_session_key.h
index b1da297d3b8..31d61a3e8af 100644
--- a/chromium/net/spdy/spdy_session_key.h
+++ b/chromium/net/spdy/spdy_session_key.h
@@ -58,4 +58,3 @@ class NET_EXPORT_PRIVATE SpdySessionKey {
} // namespace net
#endif // NET_SPDY_SPDY_SESSION_KEY_H_
-
diff --git a/chromium/net/spdy/spdy_session_pool.cc b/chromium/net/spdy/spdy_session_pool.cc
index 40c6615617f..bba42692024 100644
--- a/chromium/net/spdy/spdy_session_pool.cc
+++ b/chromium/net/spdy/spdy_session_pool.cc
@@ -7,12 +7,17 @@
#include <utility>
#include "base/logging.h"
+#include "base/memory/ptr_util.h"
#include "base/metrics/histogram_macros.h"
#include "base/profiler/scoped_tracker.h"
#include "base/stl_util.h"
+#include "base/strings/stringprintf.h"
+#include "base/trace_event/memory_allocator_dump.h"
+#include "base/trace_event/process_memory_dump.h"
#include "base/trace_event/trace_event.h"
#include "base/values.h"
#include "net/base/address_list.h"
+#include "net/base/trace_constants.h"
#include "net/http/http_network_session.h"
#include "net/http/http_server_properties.h"
#include "net/log/net_log_event_type.h"
@@ -41,7 +46,7 @@ SpdySessionPool::SpdySessionPool(
TransportSecurityState* transport_security_state,
bool enable_ping_based_connection_checking,
size_t session_max_recv_window_size,
- size_t stream_max_recv_window_size,
+ const SettingsMap& initial_settings,
SpdySessionPool::TimeFunc time_func,
ProxyDelegate* proxy_delegate)
: http_server_properties_(http_server_properties),
@@ -52,8 +57,9 @@ SpdySessionPool::SpdySessionPool(
enable_ping_based_connection_checking_(
enable_ping_based_connection_checking),
session_max_recv_window_size_(session_max_recv_window_size),
- stream_max_recv_window_size_(stream_max_recv_window_size),
+ initial_settings_(initial_settings),
time_func_(time_func),
+ push_delegate_(nullptr),
proxy_delegate_(proxy_delegate) {
NetworkChangeNotifier::AddIPAddressObserver(this);
if (ssl_config_service_.get())
@@ -81,16 +87,17 @@ base::WeakPtr<SpdySession> SpdySessionPool::CreateAvailableSessionFromSocket(
std::unique_ptr<ClientSocketHandle> connection,
const NetLogWithSource& net_log,
bool is_secure) {
- TRACE_EVENT0("net", "SpdySessionPool::CreateAvailableSessionFromSocket");
+ TRACE_EVENT0(kNetTracingCategory,
+ "SpdySessionPool::CreateAvailableSessionFromSocket");
UMA_HISTOGRAM_ENUMERATION(
"Net.SpdySessionGet", IMPORTED_FROM_SOCKET, SPDY_SESSION_GET_MAX);
- std::unique_ptr<SpdySession> new_session(new SpdySession(
+ auto new_session = base::MakeUnique<SpdySession>(
key, http_server_properties_, transport_security_state_,
enable_sending_initial_data_, enable_ping_based_connection_checking_,
- session_max_recv_window_size_, stream_max_recv_window_size_, time_func_,
- proxy_delegate_, net_log.net_log()));
+ session_max_recv_window_size_, initial_settings_, time_func_,
+ push_delegate_, proxy_delegate_, net_log.net_log());
new_session->InitializeWithSocket(std::move(connection), this, is_secure);
@@ -361,6 +368,49 @@ void SpdySessionPool::OnCertDBChanged(const X509Certificate* cert) {
CloseCurrentSessions(ERR_CERT_DATABASE_CHANGED);
}
+void SpdySessionPool::DumpMemoryStats(
+ base::trace_event::ProcessMemoryDump* pmd,
+ const std::string& parent_dump_absolute_name) const {
+ std::string dump_name = base::StringPrintf("%s/spdy_session_pool",
+ parent_dump_absolute_name.c_str());
+ base::trace_event::MemoryAllocatorDump* dump =
+ pmd->CreateAllocatorDump(dump_name);
+ size_t total_size = 0;
+ size_t buffer_size = 0;
+ size_t cert_count = 0;
+ size_t serialized_cert_size = 0;
+ size_t num_active_sessions = 0;
+ for (const auto& session : sessions_) {
+ StreamSocket::SocketMemoryStats stats;
+ bool is_session_active = false;
+ session->DumpMemoryStats(&stats, &is_session_active);
+ total_size += stats.total_size;
+ buffer_size += stats.buffer_size;
+ cert_count += stats.cert_count;
+ serialized_cert_size += stats.serialized_cert_size;
+ if (is_session_active)
+ num_active_sessions++;
+ }
+ dump->AddScalar(base::trace_event::MemoryAllocatorDump::kNameSize,
+ base::trace_event::MemoryAllocatorDump::kUnitsBytes,
+ total_size);
+ dump->AddScalar(base::trace_event::MemoryAllocatorDump::kNameObjectCount,
+ base::trace_event::MemoryAllocatorDump::kUnitsObjects,
+ sessions_.size());
+ dump->AddScalar("active_session_count",
+ base::trace_event::MemoryAllocatorDump::kUnitsObjects,
+ num_active_sessions);
+ dump->AddScalar("buffer_size",
+ base::trace_event::MemoryAllocatorDump::kUnitsBytes,
+ buffer_size);
+ dump->AddScalar("cert_count",
+ base::trace_event::MemoryAllocatorDump::kUnitsObjects,
+ cert_count);
+ dump->AddScalar("serialized_cert_size",
+ base::trace_event::MemoryAllocatorDump::kUnitsBytes,
+ serialized_cert_size);
+}
+
bool SpdySessionPool::IsSessionAvailable(
const base::WeakPtr<SpdySession>& session) const {
for (AvailableSessionMap::const_iterator it = available_sessions_.begin();
diff --git a/chromium/net/spdy/spdy_session_pool.h b/chromium/net/spdy/spdy_session_pool.h
index 09df36536e2..661501f1aba 100644
--- a/chromium/net/spdy/spdy_session_pool.h
+++ b/chromium/net/spdy/spdy_session_pool.h
@@ -8,6 +8,7 @@
#include <stddef.h>
#include <map>
+#include <memory>
#include <set>
#include <string>
#include <vector>
@@ -23,12 +24,19 @@
#include "net/cert/cert_database.h"
#include "net/proxy/proxy_config.h"
#include "net/proxy/proxy_server.h"
+#include "net/spdy/server_push_delegate.h"
+#include "net/spdy/spdy_protocol.h"
#include "net/spdy/spdy_session_key.h"
#include "net/ssl/ssl_config_service.h"
+namespace base {
+namespace trace_event {
+class ProcessMemoryDump;
+}
+}
+
namespace net {
-class AddressList;
class ClientSocketHandle;
class HostResolver;
class HttpServerProperties;
@@ -51,7 +59,7 @@ class NET_EXPORT SpdySessionPool
TransportSecurityState* transport_security_state,
bool enable_ping_based_connection_checking,
size_t session_max_recv_window_size,
- size_t stream_max_recv_window_size,
+ const SettingsMap& initial_settings,
SpdySessionPool::TimeFunc time_func,
ProxyDelegate* proxy_delegate);
~SpdySessionPool() override;
@@ -126,6 +134,10 @@ class NET_EXPORT SpdySessionPool
return http_server_properties_;
}
+ void set_server_push_delegate(ServerPushDelegate* push_delegate) {
+ push_delegate_ = push_delegate;
+ }
+
// NetworkChangeNotifier::IPAddressObserver methods:
// We flush all idle sessions and release references to the active ones so
@@ -144,6 +156,9 @@ class NET_EXPORT SpdySessionPool
// is changed.
void OnCertDBChanged(const X509Certificate* cert) override;
+ void DumpMemoryStats(base::trace_event::ProcessMemoryDump* pmd,
+ const std::string& parent_dump_absolute_name) const;
+
private:
friend class SpdySessionPoolPeer; // For testing.
@@ -215,9 +230,17 @@ class NET_EXPORT SpdySessionPool
// Defaults to true. May be controlled via SpdySessionPoolPeer for tests.
bool enable_sending_initial_data_;
bool enable_ping_based_connection_checking_;
+
size_t session_max_recv_window_size_;
- size_t stream_max_recv_window_size_;
+
+ // Settings that are sent in the initial SETTINGS frame
+ // (if |enable_sending_initial_data_| is true),
+ // and also control SpdySession parameters like initial receive window size
+ // and maximum HPACK dynamic table size.
+ const SettingsMap initial_settings_;
+
TimeFunc time_func_;
+ ServerPushDelegate* push_delegate_;
// Determines if a proxy is a trusted SPDY proxy, which is allowed to push
// resources from origins that are different from those of their associated
diff --git a/chromium/net/spdy/spdy_session_pool_unittest.cc b/chromium/net/spdy/spdy_session_pool_unittest.cc
index c9810809a4d..51362da98a7 100644
--- a/chromium/net/spdy/spdy_session_pool_unittest.cc
+++ b/chromium/net/spdy/spdy_session_pool_unittest.cc
@@ -12,6 +12,9 @@
#include "base/memory/ptr_util.h"
#include "base/memory/ref_counted.h"
#include "base/run_loop.h"
+#include "base/trace_event/memory_allocator_dump.h"
+#include "base/trace_event/process_memory_dump.h"
+#include "base/trace_event/trace_event_argument.h"
#include "net/dns/host_cache.h"
#include "net/http/http_network_session.h"
#include "net/log/net_log_with_source.h"
@@ -73,12 +76,9 @@ class SessionOpeningDelegate : public SpdyStream::Delegate {
~SessionOpeningDelegate() override {}
- void OnRequestHeadersSent() override {}
+ void OnHeadersSent() override {}
- SpdyResponseHeadersStatus OnResponseHeadersUpdated(
- const SpdyHeaderBlock& response_headers) override {
- return RESPONSE_HEADERS_ARE_COMPLETE;
- }
+ void OnHeadersReceived(const SpdyHeaderBlock& response_headers) override {}
void OnDataReceived(std::unique_ptr<SpdyBuffer> buffer) override {}
@@ -671,4 +671,60 @@ TEST_F(SpdySessionPoolTest, FindAvailableSession) {
spdy_session_pool_->CloseCurrentSessions(ERR_ABORTED);
}
+TEST_F(SpdySessionPoolTest, DumpMemoryStats) {
+ SpdySessionKey key(HostPortPair("https://www.example.org", 443),
+ ProxyServer::Direct(), PRIVACY_MODE_DISABLED);
+
+ MockRead reads[] = {MockRead(SYNCHRONOUS, ERR_IO_PENDING)};
+ StaticSocketDataProvider data(reads, arraysize(reads), nullptr, 0);
+ data.set_connect_data(MockConnect(SYNCHRONOUS, OK));
+ session_deps_.socket_factory->AddSocketDataProvider(&data);
+
+ SSLSocketDataProvider ssl(SYNCHRONOUS, OK);
+ session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
+
+ CreateNetworkSession();
+
+ base::WeakPtr<SpdySession> session =
+ CreateSecureSpdySession(http_session_.get(), key, NetLogWithSource());
+
+ // Flush the SpdySession::OnReadComplete() task.
+ base::RunLoop().RunUntilIdle();
+
+ EXPECT_TRUE(HasSpdySession(spdy_session_pool_, key));
+ base::trace_event::MemoryDumpArgs dump_args = {
+ base::trace_event::MemoryDumpLevelOfDetail::DETAILED};
+ std::unique_ptr<base::trace_event::ProcessMemoryDump> process_memory_dump(
+ new base::trace_event::ProcessMemoryDump(nullptr, dump_args));
+ base::trace_event::MemoryAllocatorDump* parent_dump =
+ process_memory_dump->CreateAllocatorDump("parent");
+ spdy_session_pool_->DumpMemoryStats(process_memory_dump.get(),
+ parent_dump->absolute_name());
+
+ // Whether SpdySession::DumpMemoryStats() is invoked.
+ bool did_dump = false;
+ const base::trace_event::ProcessMemoryDump::AllocatorDumpsMap&
+ allocator_dumps = process_memory_dump->allocator_dumps();
+ for (const auto& pair : allocator_dumps) {
+ const std::string& dump_name = pair.first;
+ if (dump_name.find("spdy_session_pool") == std::string::npos)
+ continue;
+ std::unique_ptr<base::Value> raw_attrs =
+ pair.second->attributes_for_testing()->ToBaseValue();
+ base::DictionaryValue* attrs;
+ ASSERT_TRUE(raw_attrs->GetAsDictionary(&attrs));
+ base::DictionaryValue* active_session_count_attr;
+ ASSERT_TRUE(attrs->GetDictionary("active_session_count",
+ &active_session_count_attr));
+ std::string active_session_count;
+ ASSERT_TRUE(
+ active_session_count_attr->GetString("value", &active_session_count));
+ // No created stream so the session should be idle.
+ ASSERT_EQ("0", active_session_count);
+ did_dump = true;
+ }
+ EXPECT_TRUE(did_dump);
+ spdy_session_pool_->CloseCurrentSessions(ERR_ABORTED);
+}
+
} // namespace net
diff --git a/chromium/net/spdy/spdy_session_unittest.cc b/chromium/net/spdy/spdy_session_unittest.cc
index 44ec1faa344..2f23164c5f9 100644
--- a/chromium/net/spdy/spdy_session_unittest.cc
+++ b/chromium/net/spdy/spdy_session_unittest.cc
@@ -4,6 +4,7 @@
#include "net/spdy/spdy_session.h"
+#include <algorithm>
#include <memory>
#include <utility>
@@ -123,6 +124,7 @@ class SpdySessionTest : public PlatformTest {
HttpNetworkSession::NORMAL_SOCKET_POOL)),
old_max_pool_sockets_(ClientSocketPoolManager::max_sockets_per_pool(
HttpNetworkSession::NORMAL_SOCKET_POOL)),
+ test_push_delegate_(nullptr),
spdy_session_pool_(nullptr),
test_url_(kDefaultUrl),
test_server_(test_url_),
@@ -151,6 +153,10 @@ class SpdySessionTest : public PlatformTest {
DCHECK(!spdy_session_pool_);
http_session_ =
SpdySessionDependencies::SpdyCreateSession(&session_deps_);
+ std::unique_ptr<TestServerPushDelegate> test_push_delegate(
+ new TestServerPushDelegate());
+ test_push_delegate_ = test_push_delegate.get();
+ http_session_->SetServerPushDelegate(std::move(test_push_delegate));
spdy_session_pool_ = http_session_->spdy_session_pool();
}
@@ -209,7 +215,7 @@ class SpdySessionTest : public PlatformTest {
SpdySessionDependencies session_deps_;
std::unique_ptr<HttpNetworkSession> http_session_;
base::WeakPtr<SpdySession> session_;
- TestServerPushDelegate test_push_delegate_;
+ TestServerPushDelegate* test_push_delegate_;
SpdySessionPool* spdy_session_pool_;
const GURL test_url_;
const url::SchemeHostPort test_server_;
@@ -1126,8 +1132,7 @@ TEST_F(SpdySessionTest, MaxConcurrentStreamsZero) {
// Receive SETTINGS frame that sets max_concurrent_streams to zero.
SettingsMap settings_zero;
- settings_zero[SETTINGS_MAX_CONCURRENT_STREAMS] =
- SettingsFlagsAndValue(SETTINGS_FLAG_NONE, 0);
+ settings_zero[SETTINGS_MAX_CONCURRENT_STREAMS] = 0;
SpdySerializedFrame settings_frame_zero(
spdy_util_.ConstructSpdySettings(settings_zero));
@@ -1136,8 +1141,7 @@ TEST_F(SpdySessionTest, MaxConcurrentStreamsZero) {
// Receive SETTINGS frame that sets max_concurrent_streams to one.
SettingsMap settings_one;
- settings_one[SETTINGS_MAX_CONCURRENT_STREAMS] =
- SettingsFlagsAndValue(SETTINGS_FLAG_NONE, 1);
+ settings_one[SETTINGS_MAX_CONCURRENT_STREAMS] = 1;
SpdySerializedFrame settings_frame_one(
spdy_util_.ConstructSpdySettings(settings_one));
@@ -1209,6 +1213,11 @@ TEST_F(SpdySessionTest, MaxConcurrentStreamsZero) {
EXPECT_THAT(delegate.WaitForClose(), IsOk());
EXPECT_EQ("hello!", delegate.TakeReceivedData());
+ // Finish async network reads/writes.
+ base::RunLoop().RunUntilIdle();
+ EXPECT_TRUE(data.AllWriteDataConsumed());
+ EXPECT_TRUE(data.AllReadDataConsumed());
+
// Session is destroyed.
EXPECT_FALSE(session_);
}
@@ -1286,9 +1295,16 @@ TEST_F(SpdySessionTest, CancelPushAfterSessionGoesAway) {
SpdySerializedFrame req(
spdy_util_.ConstructSpdyGet(nullptr, 0, 1, MEDIUM, true));
- SpdySerializedFrame rst(
+ SpdySerializedFrame priority_a(
+ spdy_util_.ConstructSpdyPriority(2, 1, IDLE, true));
+ SpdySerializedFrame priority_b(
+ spdy_util_.ConstructSpdyPriority(4, 2, IDLE, true));
+ SpdySerializedFrame rst_a(
spdy_util_.ConstructSpdyRstStream(2, RST_STREAM_REFUSED_STREAM));
- MockWrite writes[] = {CreateMockWrite(req, 0), CreateMockWrite(rst, 5)};
+ MockWrite writes[] = {
+ CreateMockWrite(req, 0), CreateMockWrite(priority_a, 2),
+ CreateMockWrite(priority_b, 6), CreateMockWrite(rst_a, 7),
+ };
SpdySerializedFrame push_a(spdy_util_.ConstructSpdyPush(
nullptr, 0, 2, 1, "https://www.example.org/a.dat"));
@@ -1298,9 +1314,9 @@ TEST_F(SpdySessionTest, CancelPushAfterSessionGoesAway) {
SpdySerializedFrame push_b(spdy_util_.ConstructSpdyPush(
nullptr, 0, 4, 1, "https://www.example.org/0.dat"));
MockRead reads[] = {
- CreateMockRead(push_a, 1), CreateMockRead(push_a_body, 2),
- MockRead(ASYNC, ERR_IO_PENDING, 3), CreateMockRead(push_b, 4),
- MockRead(ASYNC, ERR_IO_PENDING, 6), MockRead(ASYNC, 0, 7) // EOF
+ CreateMockRead(push_a, 1), CreateMockRead(push_a_body, 3),
+ MockRead(ASYNC, ERR_IO_PENDING, 4), CreateMockRead(push_b, 5),
+ MockRead(ASYNC, ERR_IO_PENDING, 8), MockRead(ASYNC, 0, 9) // EOF
};
SequencedSocketData data(reads, arraysize(reads), writes, arraysize(writes));
@@ -1310,7 +1326,6 @@ TEST_F(SpdySessionTest, CancelPushAfterSessionGoesAway) {
CreateNetworkSession();
CreateSecureSpdySession();
- session_->set_push_delegate(&test_push_delegate_);
// Process the principal request, and the first push stream request & body.
base::WeakPtr<SpdyStream> spdy_stream =
@@ -1358,7 +1373,7 @@ TEST_F(SpdySessionTest, CancelPushAfterSessionGoesAway) {
// crash.
EXPECT_FALSE(session_);
EXPECT_TRUE(
- test_push_delegate_.CancelPush(GURL("https://www.example.org/a.dat")));
+ test_push_delegate_->CancelPush(GURL("https://www.example.org/a.dat")));
histogram_tester.ExpectBucketCount("Net.SpdySession.PushedBytes", 6, 1);
histogram_tester.ExpectBucketCount("Net.SpdySession.PushedAndUnclaimedBytes",
@@ -1372,9 +1387,16 @@ TEST_F(SpdySessionTest, CancelPushAfterExpired) {
SpdySerializedFrame req(
spdy_util_.ConstructSpdyGet(nullptr, 0, 1, MEDIUM, true));
- SpdySerializedFrame rst(
+ SpdySerializedFrame priority_a(
+ spdy_util_.ConstructSpdyPriority(2, 1, IDLE, true));
+ SpdySerializedFrame priority_b(
+ spdy_util_.ConstructSpdyPriority(4, 2, IDLE, true));
+ SpdySerializedFrame rst_a(
spdy_util_.ConstructSpdyRstStream(2, RST_STREAM_REFUSED_STREAM));
- MockWrite writes[] = {CreateMockWrite(req, 0), CreateMockWrite(rst, 5)};
+ MockWrite writes[] = {
+ CreateMockWrite(req, 0), CreateMockWrite(priority_a, 2),
+ CreateMockWrite(priority_b, 6), CreateMockWrite(rst_a, 7),
+ };
SpdySerializedFrame push_a(spdy_util_.ConstructSpdyPush(
nullptr, 0, 2, 1, "https://www.example.org/a.dat"));
@@ -1384,9 +1406,9 @@ TEST_F(SpdySessionTest, CancelPushAfterExpired) {
SpdySerializedFrame push_b(spdy_util_.ConstructSpdyPush(
nullptr, 0, 4, 1, "https://www.example.org/0.dat"));
MockRead reads[] = {
- CreateMockRead(push_a, 1), CreateMockRead(push_a_body, 2),
- MockRead(ASYNC, ERR_IO_PENDING, 3), CreateMockRead(push_b, 4),
- MockRead(ASYNC, ERR_IO_PENDING, 6), MockRead(ASYNC, 0, 7) // EOF
+ CreateMockRead(push_a, 1), CreateMockRead(push_a_body, 3),
+ MockRead(ASYNC, ERR_IO_PENDING, 4), CreateMockRead(push_b, 5),
+ MockRead(ASYNC, ERR_IO_PENDING, 8), MockRead(ASYNC, 0, 9) // EOF
};
SequencedSocketData data(reads, arraysize(reads), writes, arraysize(writes));
@@ -1396,7 +1418,6 @@ TEST_F(SpdySessionTest, CancelPushAfterExpired) {
CreateNetworkSession();
CreateSecureSpdySession();
- session_->set_push_delegate(&test_push_delegate_);
// Process the principal request, and the first push stream request & body.
base::WeakPtr<SpdyStream> spdy_stream =
@@ -1433,7 +1454,7 @@ TEST_F(SpdySessionTest, CancelPushAfterExpired) {
// Cancel the first push after its expiration.
EXPECT_TRUE(
- test_push_delegate_.CancelPush(GURL("https://www.example.org/a.dat")));
+ test_push_delegate_->CancelPush(GURL("https://www.example.org/a.dat")));
EXPECT_EQ(1u, session_->num_unclaimed_pushed_streams());
EXPECT_TRUE(session_);
@@ -1459,9 +1480,16 @@ TEST_F(SpdySessionTest, CancelPushBeforeClaimed) {
SpdySerializedFrame req(
spdy_util_.ConstructSpdyGet(nullptr, 0, 1, MEDIUM, true));
- SpdySerializedFrame rst(
+ SpdySerializedFrame priority_a(
+ spdy_util_.ConstructSpdyPriority(2, 1, IDLE, true));
+ SpdySerializedFrame priority_b(
+ spdy_util_.ConstructSpdyPriority(4, 2, IDLE, true));
+ SpdySerializedFrame rst_a(
spdy_util_.ConstructSpdyRstStream(2, RST_STREAM_REFUSED_STREAM));
- MockWrite writes[] = {CreateMockWrite(req, 0), CreateMockWrite(rst, 5)};
+ MockWrite writes[] = {
+ CreateMockWrite(req, 0), CreateMockWrite(priority_a, 2),
+ CreateMockWrite(priority_b, 6), CreateMockWrite(rst_a, 7),
+ };
SpdySerializedFrame push_a(spdy_util_.ConstructSpdyPush(
nullptr, 0, 2, 1, "https://www.example.org/a.dat"));
@@ -1471,9 +1499,9 @@ TEST_F(SpdySessionTest, CancelPushBeforeClaimed) {
SpdySerializedFrame push_b(spdy_util_.ConstructSpdyPush(
nullptr, 0, 4, 1, "https://www.example.org/0.dat"));
MockRead reads[] = {
- CreateMockRead(push_a, 1), CreateMockRead(push_a_body, 2),
- MockRead(ASYNC, ERR_IO_PENDING, 3), CreateMockRead(push_b, 4),
- MockRead(ASYNC, ERR_IO_PENDING, 6), MockRead(ASYNC, 0, 7) // EOF
+ CreateMockRead(push_a, 1), CreateMockRead(push_a_body, 3),
+ MockRead(ASYNC, ERR_IO_PENDING, 4), CreateMockRead(push_b, 5),
+ MockRead(ASYNC, ERR_IO_PENDING, 8), MockRead(ASYNC, 0, 9) // EOF
};
SequencedSocketData data(reads, arraysize(reads), writes, arraysize(writes));
@@ -1483,7 +1511,6 @@ TEST_F(SpdySessionTest, CancelPushBeforeClaimed) {
CreateNetworkSession();
CreateSecureSpdySession();
- session_->set_push_delegate(&test_push_delegate_);
// Process the principal request, and the first push stream request & body.
base::WeakPtr<SpdyStream> spdy_stream =
@@ -1524,7 +1551,7 @@ TEST_F(SpdySessionTest, CancelPushBeforeClaimed) {
EXPECT_TRUE(session_);
// Cancel the push before it's claimed.
- EXPECT_TRUE(test_push_delegate_.CancelPush(pushed_url));
+ EXPECT_TRUE(test_push_delegate_->CancelPush(pushed_url));
EXPECT_EQ(0u, session_->num_unclaimed_pushed_streams());
EXPECT_EQ(0u, session_->count_unclaimed_pushed_streams_for_url(pushed_url));
@@ -1544,9 +1571,16 @@ TEST_F(SpdySessionTest, DeleteExpiredPushStreams) {
SpdySerializedFrame req(
spdy_util_.ConstructSpdyGet(nullptr, 0, 1, MEDIUM, true));
- SpdySerializedFrame rst(
+ SpdySerializedFrame priority_a(
+ spdy_util_.ConstructSpdyPriority(2, 1, IDLE, true));
+ SpdySerializedFrame priority_b(
+ spdy_util_.ConstructSpdyPriority(4, 2, IDLE, true));
+ SpdySerializedFrame rst_a(
spdy_util_.ConstructSpdyRstStream(2, RST_STREAM_REFUSED_STREAM));
- MockWrite writes[] = {CreateMockWrite(req, 0), CreateMockWrite(rst, 5)};
+ MockWrite writes[] = {
+ CreateMockWrite(req, 0), CreateMockWrite(priority_a, 2),
+ CreateMockWrite(priority_b, 6), CreateMockWrite(rst_a, 7),
+ };
SpdySerializedFrame push_a(spdy_util_.ConstructSpdyPush(
nullptr, 0, 2, 1, "https://www.example.org/a.dat"));
@@ -1556,9 +1590,9 @@ TEST_F(SpdySessionTest, DeleteExpiredPushStreams) {
SpdySerializedFrame push_b(spdy_util_.ConstructSpdyPush(
nullptr, 0, 4, 1, "https://www.example.org/0.dat"));
MockRead reads[] = {
- CreateMockRead(push_a, 1), CreateMockRead(push_a_body, 2),
- MockRead(ASYNC, ERR_IO_PENDING, 3), CreateMockRead(push_b, 4),
- MockRead(ASYNC, ERR_IO_PENDING, 6), MockRead(ASYNC, 0, 7) // EOF
+ CreateMockRead(push_a, 1), CreateMockRead(push_a_body, 3),
+ MockRead(ASYNC, ERR_IO_PENDING, 4), CreateMockRead(push_b, 5),
+ MockRead(ASYNC, ERR_IO_PENDING, 8), MockRead(ASYNC, 0, 9) // EOF
};
SequencedSocketData data(reads, arraysize(reads), writes, arraysize(writes));
@@ -1623,9 +1657,19 @@ TEST_F(SpdySessionTest, MetricsCollectionOnPushStreams) {
SpdySerializedFrame req(
spdy_util_.ConstructSpdyGet(nullptr, 0, 1, MEDIUM, true));
- SpdySerializedFrame rst(
+ SpdySerializedFrame priority_a(
+ spdy_util_.ConstructSpdyPriority(2, 1, IDLE, true));
+ SpdySerializedFrame priority_b(
+ spdy_util_.ConstructSpdyPriority(4, 2, IDLE, true));
+ SpdySerializedFrame priority_c(
+ spdy_util_.ConstructSpdyPriority(6, 4, IDLE, true));
+ SpdySerializedFrame rst_a(
spdy_util_.ConstructSpdyRstStream(2, RST_STREAM_REFUSED_STREAM));
- MockWrite writes[] = {CreateMockWrite(req, 0), CreateMockWrite(rst, 5)};
+ MockWrite writes[] = {
+ CreateMockWrite(req, 0), CreateMockWrite(priority_a, 2),
+ CreateMockWrite(priority_b, 6), CreateMockWrite(rst_a, 7),
+ CreateMockWrite(priority_c, 10),
+ };
SpdySerializedFrame push_a(spdy_util_.ConstructSpdyPush(
nullptr, 0, 2, 1, "https://www.example.org/a.dat"));
@@ -1640,14 +1684,14 @@ TEST_F(SpdySessionTest, MetricsCollectionOnPushStreams) {
MockRead reads[] = {
CreateMockRead(push_a, 1),
- CreateMockRead(push_a_body, 2),
- MockRead(ASYNC, ERR_IO_PENDING, 3),
- CreateMockRead(push_b, 4),
- MockRead(ASYNC, ERR_IO_PENDING, 6),
- CreateMockRead(push_c, 7),
- CreateMockRead(push_c_body, 8),
- MockRead(ASYNC, ERR_IO_PENDING, 9),
- MockRead(ASYNC, 0, 10) // EOF
+ CreateMockRead(push_a_body, 3),
+ MockRead(ASYNC, ERR_IO_PENDING, 4),
+ CreateMockRead(push_b, 5),
+ MockRead(ASYNC, ERR_IO_PENDING, 8),
+ CreateMockRead(push_c, 9),
+ CreateMockRead(push_c_body, 11),
+ MockRead(ASYNC, ERR_IO_PENDING, 12),
+ MockRead(ASYNC, 0, 13) // EOF
};
SequencedSocketData data(reads, arraysize(reads), writes, arraysize(writes));
@@ -1779,8 +1823,7 @@ TEST_F(SpdySessionTest, OnSettings) {
SettingsMap new_settings;
const uint32_t max_concurrent_streams = kInitialMaxConcurrentStreams + 1;
- new_settings[kSpdySettingsIds] =
- SettingsFlagsAndValue(SETTINGS_FLAG_NONE, max_concurrent_streams);
+ new_settings[kSpdySettingsIds] = max_concurrent_streams;
SpdySerializedFrame settings_frame(
spdy_util_.ConstructSpdySettings(new_settings));
MockRead reads[] = {
@@ -1881,41 +1924,6 @@ TEST_F(SpdySessionTest, CancelPendingCreateStream) {
base::RunLoop().RunUntilIdle();
}
-TEST_F(SpdySessionTest, SendInitialDataOnNewSession) {
- session_deps_.host_resolver->set_synchronous_mode(true);
-
- MockRead reads[] = {
- MockRead(SYNCHRONOUS, ERR_IO_PENDING) // Stall forever.
- };
-
- SettingsMap settings;
- settings[SETTINGS_HEADER_TABLE_SIZE] =
- SettingsFlagsAndValue(SETTINGS_FLAG_NONE, kMaxHeaderTableSize);
- settings[SETTINGS_MAX_CONCURRENT_STREAMS] =
- SettingsFlagsAndValue(SETTINGS_FLAG_NONE, kMaxConcurrentPushedStreams);
- SpdySerializedFrame settings_frame(
- spdy_util_.ConstructSpdySettings(settings));
- MockWrite writes[] = {MockWrite(ASYNC, kHttp2ConnectionHeaderPrefix,
- kHttp2ConnectionHeaderPrefixSize),
- CreateMockWrite(settings_frame)};
-
- StaticSocketDataProvider data(reads, arraysize(reads), writes,
- arraysize(writes));
- session_deps_.socket_factory->AddSocketDataProvider(&data);
-
- AddSSLSocketData();
-
- CreateNetworkSession();
-
- SpdySessionPoolPeer pool_peer(spdy_session_pool_);
- pool_peer.SetEnableSendingInitialData(true);
-
- CreateSecureSpdySession();
-
- base::RunLoop().RunUntilIdle();
- EXPECT_TRUE(data.AllWriteDataConsumed());
-}
-
TEST_F(SpdySessionTest, Initialize) {
session_deps_.host_resolver->set_synchronous_mode(true);
@@ -2053,7 +2061,7 @@ TEST_F(SpdySessionTest, NetLogOnSessionEOF) {
}
}
-TEST_F(SpdySessionTest, SynCompressionHistograms) {
+TEST_F(SpdySessionTest, HeadersCompressionHistograms) {
SpdySerializedFrame req(
spdy_util_.ConstructSpdyGet(nullptr, 0, 1, MEDIUM, true));
MockWrite writes[] = {
@@ -2084,8 +2092,8 @@ TEST_F(SpdySessionTest, SynCompressionHistograms) {
base::RunLoop().RunUntilIdle();
// Regression test of compression performance under the request fixture.
- histogram_tester.ExpectBucketCount("Net.SpdySynStreamCompressionPercentage",
- 81, 1);
+ histogram_tester.ExpectBucketCount("Net.SpdyHeadersCompressionPercentage", 76,
+ 1);
// Read and process EOF.
EXPECT_TRUE(session_);
@@ -2616,8 +2624,7 @@ TEST_F(SpdySessionTest, CloseTwoStalledCreateStream) {
SettingsMap new_settings;
const SpdySettingsIds kSpdySettingsIds1 = SETTINGS_MAX_CONCURRENT_STREAMS;
const uint32_t max_concurrent_streams = 1;
- new_settings[kSpdySettingsIds1] =
- SettingsFlagsAndValue(SETTINGS_FLAG_NONE, max_concurrent_streams);
+ new_settings[kSpdySettingsIds1] = max_concurrent_streams;
SpdySerializedFrame settings_ack(spdy_util_.ConstructSpdySettingsAck());
SpdySerializedFrame req1(
@@ -3656,8 +3663,7 @@ TEST_F(SpdySessionTest, UpdateStreamsSendWindowSize) {
// gets sent.
SettingsMap new_settings;
int32_t window_size = 1;
- new_settings[SETTINGS_INITIAL_WINDOW_SIZE] =
- SettingsFlagsAndValue(SETTINGS_FLAG_NONE, window_size);
+ new_settings[SETTINGS_INITIAL_WINDOW_SIZE] = window_size;
// Set up the socket so we read a SETTINGS frame that sets
// INITIAL_WINDOW_SIZE.
@@ -3891,10 +3897,10 @@ TEST_F(SpdySessionTest, StreamFlowControlTooMuchData) {
AddSSLSocketData();
+ session_deps_.http2_settings[SETTINGS_INITIAL_WINDOW_SIZE] =
+ stream_max_recv_window_size;
CreateNetworkSession();
- SpdySessionPoolPeer pool_peer(spdy_session_pool_);
- pool_peer.SetStreamInitialRecvWindowSize(stream_max_recv_window_size);
CreateSecureSpdySession();
base::WeakPtr<SpdyStream> spdy_stream =
@@ -4029,9 +4035,9 @@ TEST_F(SpdySessionTest, StreamFlowControlTooMuchDataTwoDataFrames) {
AddSSLSocketData();
+ session_deps_.http2_settings[SETTINGS_INITIAL_WINDOW_SIZE] =
+ stream_max_recv_window_size;
CreateNetworkSession();
- SpdySessionPoolPeer pool_peer(spdy_session_pool_);
- pool_peer.SetStreamInitialRecvWindowSize(stream_max_recv_window_size);
CreateSecureSpdySession();
@@ -4399,6 +4405,10 @@ void SpdySessionTest::RunResumeAfterUnstallTest(
EXPECT_TRUE(delegate.send_headers_completed());
EXPECT_EQ("200", delegate.GetResponseHeaderValue(":status"));
EXPECT_EQ(std::string(), delegate.TakeReceivedData());
+
+ // Run SpdySession::PumpWriteLoop which destroys |session_|.
+ base::RunLoop().RunUntilIdle();
+
EXPECT_FALSE(session_);
EXPECT_TRUE(data.AllWriteDataConsumed());
}
@@ -4879,8 +4889,7 @@ TEST_F(SpdySessionTest, GoAwayOnSessionFlowControlError) {
// limit for a long time.
TEST_F(SpdySessionTest, PushedStreamShouldNotCountToClientConcurrencyLimit) {
SettingsMap new_settings;
- new_settings[SETTINGS_MAX_CONCURRENT_STREAMS] =
- SettingsFlagsAndValue(SETTINGS_FLAG_NONE, 2);
+ new_settings[SETTINGS_MAX_CONCURRENT_STREAMS] = 2;
SpdySerializedFrame settings_frame(
spdy_util_.ConstructSpdySettings(new_settings));
SpdySerializedFrame pushed(spdy_util_.ConstructSpdyPush(
@@ -4889,15 +4898,18 @@ TEST_F(SpdySessionTest, PushedStreamShouldNotCountToClientConcurrencyLimit) {
CreateMockRead(settings_frame, 0),
MockRead(ASYNC, ERR_IO_PENDING, 3),
CreateMockRead(pushed, 4),
- MockRead(ASYNC, ERR_IO_PENDING, 5),
- MockRead(ASYNC, 0, 6),
+ MockRead(ASYNC, ERR_IO_PENDING, 6),
+ MockRead(ASYNC, 0, 7),
};
SpdySerializedFrame settings_ack(spdy_util_.ConstructSpdySettingsAck());
SpdySerializedFrame req(
spdy_util_.ConstructSpdyGet(nullptr, 0, 1, LOWEST, true));
+ SpdySerializedFrame priority(
+ spdy_util_.ConstructSpdyPriority(2, 1, IDLE, true));
MockWrite writes[] = {
CreateMockWrite(settings_ack, 1), CreateMockWrite(req, 2),
+ CreateMockWrite(priority, 5),
};
SequencedSocketData data(reads, arraysize(reads), writes, arraysize(writes));
@@ -4969,16 +4981,21 @@ TEST_F(SpdySessionTest, RejectPushedStreamExceedingConcurrencyLimit) {
nullptr, 0, 4, 1, "https://www.example.org/b.dat"));
MockRead reads[] = {
MockRead(ASYNC, ERR_IO_PENDING, 1), CreateMockRead(push_a, 2),
- MockRead(ASYNC, ERR_IO_PENDING, 3), CreateMockRead(push_b, 4),
- MockRead(ASYNC, ERR_IO_PENDING, 6), MockRead(ASYNC, 0, 7),
+ MockRead(ASYNC, ERR_IO_PENDING, 4), CreateMockRead(push_b, 5),
+ MockRead(ASYNC, ERR_IO_PENDING, 8), MockRead(ASYNC, 0, 9),
};
SpdySerializedFrame req(
spdy_util_.ConstructSpdyGet(nullptr, 0, 1, LOWEST, true));
- SpdySerializedFrame rst(
+ SpdySerializedFrame priority_a(
+ spdy_util_.ConstructSpdyPriority(2, 1, IDLE, true));
+ SpdySerializedFrame priority_b(
+ spdy_util_.ConstructSpdyPriority(4, 2, IDLE, true));
+ SpdySerializedFrame rst_b(
spdy_util_.ConstructSpdyRstStream(4, RST_STREAM_REFUSED_STREAM));
MockWrite writes[] = {
- CreateMockWrite(req, 0), CreateMockWrite(rst, 5),
+ CreateMockWrite(req, 0), CreateMockWrite(priority_a, 3),
+ CreateMockWrite(priority_b, 6), CreateMockWrite(rst_b, 7),
};
SequencedSocketData data(reads, arraysize(reads), writes, arraysize(writes));
@@ -5055,18 +5072,21 @@ TEST_F(SpdySessionTest, TrustedSpdyProxy) {
MockRead reads[] = {
MockRead(ASYNC, ERR_IO_PENDING, 1),
CreateMockRead(cross_origin_push, 2),
- MockRead(ASYNC, ERR_IO_PENDING, 3),
- CreateMockRead(cross_origin_https_push, 4),
- MockRead(ASYNC, ERR_IO_PENDING, 6),
- MockRead(ASYNC, 0, 7),
+ MockRead(ASYNC, ERR_IO_PENDING, 4),
+ CreateMockRead(cross_origin_https_push, 5),
+ MockRead(ASYNC, ERR_IO_PENDING, 7),
+ MockRead(ASYNC, 0, 8),
};
SpdySerializedFrame req(
spdy_util_.ConstructSpdyGet(nullptr, 0, 1, LOWEST, true));
- SpdySerializedFrame rst(
+ SpdySerializedFrame priority_http(
+ spdy_util_.ConstructSpdyPriority(2, 1, IDLE, true));
+ SpdySerializedFrame rst_https(
spdy_util_.ConstructSpdyRstStream(4, RST_STREAM_REFUSED_STREAM));
MockWrite writes[] = {
- CreateMockWrite(req, 0), CreateMockWrite(rst, 5),
+ CreateMockWrite(req, 0), CreateMockWrite(priority_http, 3),
+ CreateMockWrite(rst_https, 6),
};
SequencedSocketData data(reads, arraysize(reads), writes, arraysize(writes));
@@ -5076,7 +5096,7 @@ TEST_F(SpdySessionTest, TrustedSpdyProxy) {
proxy_delegate->set_trusted_spdy_proxy(
net::ProxyServer(net::ProxyServer::SCHEME_HTTPS,
HostPortPair(GURL(kDefaultUrl).host(), 443)));
- session_deps_.proxy_delegate.reset(proxy_delegate.release());
+ session_deps_.proxy_delegate = std::move(proxy_delegate);
AddSSLSocketData();
@@ -5204,18 +5224,23 @@ TEST_F(SpdySessionTest, IgnoreReservedRemoteStreamsCount) {
SpdySerializedFrame headers_b(
spdy_util_.ConstructSpdyPushHeaders(4, nullptr, 0));
MockRead reads[] = {
- MockRead(ASYNC, ERR_IO_PENDING, 1), CreateMockRead(push_a, 2),
- MockRead(ASYNC, ERR_IO_PENDING, 3), CreateMockRead(push_b, 4),
- MockRead(ASYNC, ERR_IO_PENDING, 5), CreateMockRead(headers_b, 6),
- MockRead(ASYNC, ERR_IO_PENDING, 8), MockRead(ASYNC, 0, 9),
+ MockRead(ASYNC, ERR_IO_PENDING, 1), CreateMockRead(push_a, 2),
+ MockRead(ASYNC, ERR_IO_PENDING, 4), CreateMockRead(push_b, 5),
+ MockRead(ASYNC, ERR_IO_PENDING, 7), CreateMockRead(headers_b, 8),
+ MockRead(ASYNC, ERR_IO_PENDING, 10), MockRead(ASYNC, 0, 11),
};
SpdySerializedFrame req(
spdy_util_.ConstructSpdyGet(nullptr, 0, 1, LOWEST, true));
- SpdySerializedFrame rst(
+ SpdySerializedFrame priority_a(
+ spdy_util_.ConstructSpdyPriority(2, 1, IDLE, true));
+ SpdySerializedFrame priority_b(
+ spdy_util_.ConstructSpdyPriority(4, 2, IDLE, true));
+ SpdySerializedFrame rst_b(
spdy_util_.ConstructSpdyRstStream(4, RST_STREAM_REFUSED_STREAM));
MockWrite writes[] = {
- CreateMockWrite(req, 0), CreateMockWrite(rst, 7),
+ CreateMockWrite(req, 0), CreateMockWrite(priority_a, 3),
+ CreateMockWrite(priority_b, 6), CreateMockWrite(rst_b, 9),
};
SequencedSocketData data(reads, arraysize(reads), writes, arraysize(writes));
@@ -5293,16 +5318,19 @@ TEST_F(SpdySessionTest, CancelReservedStreamOnHeadersReceived) {
spdy_util_.ConstructSpdyPushHeaders(2, nullptr, 0));
MockRead reads[] = {
MockRead(ASYNC, ERR_IO_PENDING, 1), CreateMockRead(push_promise, 2),
- MockRead(ASYNC, ERR_IO_PENDING, 3), CreateMockRead(headers_frame, 4),
- MockRead(ASYNC, ERR_IO_PENDING, 6), MockRead(ASYNC, 0, 7),
+ MockRead(ASYNC, ERR_IO_PENDING, 4), CreateMockRead(headers_frame, 5),
+ MockRead(ASYNC, ERR_IO_PENDING, 7), MockRead(ASYNC, 0, 8),
};
SpdySerializedFrame req(
spdy_util_.ConstructSpdyGet(nullptr, 0, 1, LOWEST, true));
+ SpdySerializedFrame priority(
+ spdy_util_.ConstructSpdyPriority(2, 1, IDLE, true));
SpdySerializedFrame rst(
spdy_util_.ConstructSpdyRstStream(2, RST_STREAM_CANCEL));
MockWrite writes[] = {
- CreateMockWrite(req, 0), CreateMockWrite(rst, 5),
+ CreateMockWrite(req, 0), CreateMockWrite(priority, 3),
+ CreateMockWrite(rst, 6),
};
SequencedSocketData data(reads, arraysize(reads), writes, arraysize(writes));
@@ -5347,7 +5375,7 @@ TEST_F(SpdySessionTest, CancelReservedStreamOnHeadersReceived) {
EXPECT_EQ(0u, session_->num_active_pushed_streams());
base::WeakPtr<SpdyStream> pushed_stream;
- int rv = session_->GetPushStream(GURL(kPushedUrl), &pushed_stream,
+ int rv = session_->GetPushStream(GURL(kPushedUrl), IDLE, &pushed_stream,
NetLogWithSource());
ASSERT_THAT(rv, IsOk());
ASSERT_TRUE(pushed_stream);
@@ -5398,6 +5426,92 @@ TEST_F(SpdySessionTest, RejectInvalidUnknownFrames) {
EXPECT_FALSE(session_->OnUnknownFrame(8, 0));
}
+class SendInitialSettingsOnNewSpdySessionTest : public SpdySessionTest {
+ protected:
+ void RunInitialSettingsTest(const SettingsMap expected_settings) {
+ session_deps_.host_resolver->set_synchronous_mode(true);
+
+ MockRead reads[] = {MockRead(SYNCHRONOUS, ERR_IO_PENDING)};
+
+ SpdySerializedFrame settings_frame(
+ spdy_util_.ConstructSpdySettings(expected_settings));
+ MockWrite writes[] = {MockWrite(ASYNC, kHttp2ConnectionHeaderPrefix,
+ kHttp2ConnectionHeaderPrefixSize),
+ CreateMockWrite(settings_frame)};
+
+ StaticSocketDataProvider data(reads, arraysize(reads), writes,
+ arraysize(writes));
+ session_deps_.socket_factory->AddSocketDataProvider(&data);
+ AddSSLSocketData();
+
+ CreateNetworkSession();
+
+ SpdySessionPoolPeer pool_peer(spdy_session_pool_);
+ pool_peer.SetEnableSendingInitialData(true);
+
+ CreateSecureSpdySession();
+
+ base::RunLoop().RunUntilIdle();
+ EXPECT_TRUE(data.AllWriteDataConsumed());
+ }
+};
+
+// Setting values when Params::http2_settings is empty. Note that
+// SETTINGS_INITIAL_WINDOW_SIZE is sent in production, because it is set to a
+// non-default value, but it is not sent in tests, because the protocol default
+// value is used in tests.
+TEST_F(SendInitialSettingsOnNewSpdySessionTest, Empty) {
+ SettingsMap expected_settings;
+ expected_settings[SETTINGS_HEADER_TABLE_SIZE] = kSpdyMaxHeaderTableSize;
+ expected_settings[SETTINGS_MAX_CONCURRENT_STREAMS] =
+ kSpdyMaxConcurrentPushedStreams;
+ RunInitialSettingsTest(expected_settings);
+}
+
+// When a setting is set to the protocol default value,
+// no corresponding value is sent on the wire.
+TEST_F(SendInitialSettingsOnNewSpdySessionTest, ProtocolDefault) {
+ // Explicitly set protocol default values for the following settings.
+ session_deps_.http2_settings[SETTINGS_HEADER_TABLE_SIZE] = 4096;
+ session_deps_.http2_settings[SETTINGS_ENABLE_PUSH] = 1;
+ session_deps_.http2_settings[SETTINGS_INITIAL_WINDOW_SIZE] = 64 * 1024 - 1;
+
+ SettingsMap expected_settings;
+ expected_settings[SETTINGS_MAX_CONCURRENT_STREAMS] =
+ kSpdyMaxConcurrentPushedStreams;
+ RunInitialSettingsTest(expected_settings);
+}
+
+// Values set in Params::http2_settings overwrite Chromium's default values.
+TEST_F(SendInitialSettingsOnNewSpdySessionTest, OverwriteValues) {
+ session_deps_.http2_settings[SETTINGS_HEADER_TABLE_SIZE] = 16 * 1024;
+ session_deps_.http2_settings[SETTINGS_ENABLE_PUSH] = 0;
+ session_deps_.http2_settings[SETTINGS_MAX_CONCURRENT_STREAMS] = 42;
+ session_deps_.http2_settings[SETTINGS_INITIAL_WINDOW_SIZE] = 32 * 1024;
+
+ SettingsMap expected_settings;
+ expected_settings[SETTINGS_HEADER_TABLE_SIZE] = 16 * 1024;
+ expected_settings[SETTINGS_ENABLE_PUSH] = 0;
+ expected_settings[SETTINGS_MAX_CONCURRENT_STREAMS] = 42;
+ expected_settings[SETTINGS_INITIAL_WINDOW_SIZE] = 32 * 1024;
+ RunInitialSettingsTest(expected_settings);
+}
+
+// Unknown parameters should still be sent to the server.
+TEST_F(SendInitialSettingsOnNewSpdySessionTest, UnknownSettings) {
+ // The following parameters are not defined in the HTTP/2 specification.
+ session_deps_.http2_settings[static_cast<SpdySettingsIds>(7)] = 1234;
+ session_deps_.http2_settings[static_cast<SpdySettingsIds>(25)] = 5678;
+
+ SettingsMap expected_settings;
+ expected_settings[SETTINGS_HEADER_TABLE_SIZE] = kSpdyMaxHeaderTableSize;
+ expected_settings[SETTINGS_MAX_CONCURRENT_STREAMS] =
+ kSpdyMaxConcurrentPushedStreams;
+ expected_settings[static_cast<SpdySettingsIds>(7)] = 1234;
+ expected_settings[static_cast<SpdySettingsIds>(25)] = 5678;
+ RunInitialSettingsTest(expected_settings);
+}
+
class AltSvcFrameTest : public SpdySessionTest {
public:
AltSvcFrameTest()
diff --git a/chromium/net/spdy/spdy_stream.cc b/chromium/net/spdy/spdy_stream.cc
index f8a36d9ab4e..126176d342f 100644
--- a/chromium/net/spdy/spdy_stream.cc
+++ b/chromium/net/spdy/spdy_stream.cc
@@ -14,6 +14,7 @@
#include "base/metrics/histogram_macros.h"
#include "base/single_thread_task_runner.h"
#include "base/strings/string_number_conversions.h"
+#include "base/strings/string_piece.h"
#include "base/strings/string_util.h"
#include "base/strings/stringprintf.h"
#include "base/threading/thread_task_runner_handle.h"
@@ -29,6 +30,38 @@ namespace net {
namespace {
+enum StatusHeader {
+ STATUS_HEADER_NOT_INCLUDED = 0,
+ STATUS_HEADER_DOES_NOT_START_WITH_NUMBER = 1,
+ STATUS_HEADER_IS_NUMBER = 2,
+ STATUS_HEADER_HAS_STATUS_TEXT = 3,
+ STATUS_HEADER_MAX = STATUS_HEADER_HAS_STATUS_TEXT
+};
+
+StatusHeader ParseStatusHeaderImpl(const SpdyHeaderBlock& response_headers,
+ int* status) {
+ SpdyHeaderBlock::const_iterator it = response_headers.find(":status");
+ if (it == response_headers.end())
+ return STATUS_HEADER_NOT_INCLUDED;
+
+ // Save status in |*status| even if some text follows the status code.
+ base::StringPiece status_string = it->second;
+ base::StringPiece::size_type end = status_string.find(' ');
+ if (!StringToInt(status_string.substr(0, end), status))
+ return STATUS_HEADER_DOES_NOT_START_WITH_NUMBER;
+
+ return end == base::StringPiece::npos ? STATUS_HEADER_IS_NUMBER
+ : STATUS_HEADER_HAS_STATUS_TEXT;
+}
+
+StatusHeader ParseStatusHeader(const SpdyHeaderBlock& response_headers,
+ int* status) {
+ StatusHeader status_header = ParseStatusHeaderImpl(response_headers, status);
+ UMA_HISTOGRAM_ENUMERATION("Net.Http2ResponseStatusHeader", status_header,
+ STATUS_HEADER_MAX + 1);
+ return status_header;
+}
+
std::unique_ptr<base::Value> NetLogSpdyStreamErrorCallback(
SpdyStreamId stream_id,
int status,
@@ -59,8 +92,6 @@ bool ContainsUppercaseAscii(base::StringPiece str) {
} // namespace
-void SpdyStream::Delegate::OnTrailers(const SpdyHeaderBlock& trailers) {}
-
// A wrapper around a stream that calls into ProduceHeadersFrame().
class SpdyStream::HeadersBufferProducer : public SpdyBufferProducer {
public:
@@ -106,7 +137,7 @@ SpdyStream::SpdyStream(SpdyStreamType type,
request_headers_valid_(false),
pending_send_status_(MORE_DATA_TO_SEND),
request_time_(base::Time::Now()),
- response_headers_status_(RESPONSE_HEADERS_ARE_INCOMPLETE),
+ response_state_(READY_FOR_HEADERS),
io_state_(STATE_IDLE),
response_status_(OK),
net_log_(net_log),
@@ -157,28 +188,12 @@ void SpdyStream::PushedStreamReplay() {
base::WeakPtr<SpdyStream> weak_this = GetWeakPtr();
CHECK(delegate_);
- SpdyResponseHeadersStatus status =
- delegate_->OnResponseHeadersUpdated(response_headers_);
- if (status == RESPONSE_HEADERS_ARE_INCOMPLETE) {
- // Since RESPONSE_HEADERS_ARE_INCOMPLETE was returned, we must not
- // have been closed. Since we don't have complete headers, assume
- // we're waiting for another HEADERS frame, and we had better not
- // have any pending data frames.
- CHECK(weak_this);
- if (!pending_recv_data_.empty()) {
- LogStreamError(ERR_SPDY_PROTOCOL_ERROR,
- "Data received with incomplete headers.");
- session_->CloseActiveStream(stream_id_, ERR_SPDY_PROTOCOL_ERROR);
- }
- return;
- }
+ delegate_->OnHeadersReceived(response_headers_);
- // OnResponseHeadersUpdated() may have closed |this|.
+ // OnHeadersReceived() may have closed |this|.
if (!weak_this)
return;
- response_headers_status_ = RESPONSE_HEADERS_ARE_COMPLETE;
-
while (!pending_recv_data_.empty()) {
// Take ownership of the first element of |pending_recv_data_|.
std::unique_ptr<SpdyBuffer> buffer = std::move(pending_recv_data_.at(0));
@@ -389,83 +404,96 @@ void SpdyStream::SetRequestTime(base::Time t) {
request_time_ = t;
}
-int SpdyStream::OnInitialResponseHeadersReceived(
- const SpdyHeaderBlock& initial_response_headers,
- base::Time response_time,
- base::TimeTicks recv_first_byte_time) {
- // SpdySession guarantees that this is called at most once.
- CHECK(response_headers_.empty());
-
- // Check to make sure that we don't receive the response headers
- // before we're ready for it.
- switch (type_) {
- case SPDY_BIDIRECTIONAL_STREAM:
- // For a bidirectional stream, we're ready for the response
- // headers once we've finished sending the request headers.
- if (io_state_ == STATE_IDLE) {
- session_->ResetStream(stream_id_, RST_STREAM_PROTOCOL_ERROR,
- "Response received before request sent");
- return ERR_SPDY_PROTOCOL_ERROR;
+void SpdyStream::OnHeadersReceived(const SpdyHeaderBlock& response_headers,
+ base::Time response_time,
+ base::TimeTicks recv_first_byte_time) {
+ switch (response_state_) {
+ case READY_FOR_HEADERS: {
+ // No header block has been received yet.
+ DCHECK(response_headers_.empty());
+ int status;
+ switch (ParseStatusHeader(response_headers, &status)) {
+ case STATUS_HEADER_NOT_INCLUDED: {
+ const std::string error("Response headers do not include :status.");
+ LogStreamError(ERR_SPDY_PROTOCOL_ERROR, error);
+ session_->ResetStream(stream_id_, RST_STREAM_PROTOCOL_ERROR, error);
+ return;
+ }
+ case STATUS_HEADER_DOES_NOT_START_WITH_NUMBER: {
+ const std::string error("Cannot parse :status.");
+ LogStreamError(ERR_SPDY_PROTOCOL_ERROR, error);
+ session_->ResetStream(stream_id_, RST_STREAM_PROTOCOL_ERROR, error);
+ return;
+ }
+ // Intentional fallthrough for the following two cases,
+ // to maintain compatibility with broken servers that include
+ // status text in the response.
+ case STATUS_HEADER_IS_NUMBER:
+ case STATUS_HEADER_HAS_STATUS_TEXT:
+ // Ignore informational headers.
+ // TODO(bnc): Add support for 103 Early Hints,
+ // https://crbug.com/671310.
+ if (status / 100 == 1) {
+ return;
+ }
}
- break;
- case SPDY_REQUEST_RESPONSE_STREAM:
- // For a request/response stream, we're ready for the response
- // headers once we've finished sending the request headers.
- if (io_state_ == STATE_IDLE) {
- session_->ResetStream(stream_id_, RST_STREAM_PROTOCOL_ERROR,
- "Response received before request sent");
- return ERR_SPDY_PROTOCOL_ERROR;
+ response_state_ = READY_FOR_DATA_OR_TRAILERS;
+
+ switch (type_) {
+ case SPDY_BIDIRECTIONAL_STREAM:
+ case SPDY_REQUEST_RESPONSE_STREAM:
+ // A bidirectional stream or a request/response stream is ready for
+ // the response headers only after request headers are sent.
+ if (io_state_ == STATE_IDLE) {
+ const std::string error("Response received before request sent.");
+ LogStreamError(ERR_SPDY_PROTOCOL_ERROR, error);
+ session_->ResetStream(stream_id_, RST_STREAM_PROTOCOL_ERROR, error);
+ return;
+ }
+ break;
+
+ case SPDY_PUSH_STREAM:
+ // Push streams transition to a locally half-closed state upon
+ // headers. We must continue to buffer data while waiting for a call
+ // to SetDelegate() (which may not ever happen).
+ DCHECK_EQ(io_state_, STATE_RESERVED_REMOTE);
+ if (!delegate_) {
+ io_state_ = STATE_HALF_CLOSED_LOCAL_UNCLAIMED;
+ } else {
+ io_state_ = STATE_HALF_CLOSED_LOCAL;
+ }
+ break;
}
- break;
- case SPDY_PUSH_STREAM:
- // Push streams transition to a locally half-closed state upon headers.
- // We must continue to buffer data while waiting for a call to
- // SetDelegate() (which may not ever happen).
- CHECK_EQ(io_state_, STATE_RESERVED_REMOTE);
- if (!delegate_) {
- io_state_ = STATE_HALF_CLOSED_LOCAL_UNCLAIMED;
- } else {
- io_state_ = STATE_HALF_CLOSED_LOCAL;
- }
- break;
- }
-
- DCHECK_NE(io_state_, STATE_IDLE);
+ DCHECK_NE(io_state_, STATE_IDLE);
- response_time_ = response_time;
- recv_first_byte_time_ = recv_first_byte_time;
- return MergeWithResponseHeaders(initial_response_headers);
-}
+ response_time_ = response_time;
+ recv_first_byte_time_ = recv_first_byte_time;
+ SaveResponseHeaders(response_headers);
-int SpdyStream::OnAdditionalResponseHeadersReceived(
- const SpdyHeaderBlock& additional_response_headers) {
- if (type_ == SPDY_REQUEST_RESPONSE_STREAM) {
- if (response_headers_status_ != RESPONSE_HEADERS_ARE_COMPLETE) {
- session_->ResetStream(
- stream_id_, RST_STREAM_PROTOCOL_ERROR,
- "Additional headers received for request/response stream");
- return ERR_SPDY_PROTOCOL_ERROR;
+ break;
}
- response_headers_status_ = TRAILERS_RECEIVED;
- delegate_->OnTrailers(additional_response_headers);
- return OK;
- }
- if (type_ == SPDY_BIDIRECTIONAL_STREAM) {
- DCHECK_EQ(RESPONSE_HEADERS_ARE_COMPLETE, response_headers_status_);
- response_headers_status_ = TRAILERS_RECEIVED;
- delegate_->OnTrailers(additional_response_headers);
- return OK;
- }
- if (type_ == SPDY_PUSH_STREAM &&
- response_headers_status_ == RESPONSE_HEADERS_ARE_COMPLETE) {
- session_->ResetStream(
- stream_id_, RST_STREAM_PROTOCOL_ERROR,
- "Additional headers received for push stream");
- return ERR_SPDY_PROTOCOL_ERROR;
+ case READY_FOR_DATA_OR_TRAILERS:
+ // Second header block is trailers.
+ if (type_ == SPDY_PUSH_STREAM) {
+ const std::string error("Trailers not supported for push stream.");
+ LogStreamError(ERR_SPDY_PROTOCOL_ERROR, error);
+ session_->ResetStream(stream_id_, RST_STREAM_PROTOCOL_ERROR, error);
+ return;
+ }
+
+ response_state_ = TRAILERS_RECEIVED;
+ delegate_->OnTrailers(response_headers);
+ break;
+
+ case TRAILERS_RECEIVED:
+ // No further header blocks are allowed after trailers.
+ const std::string error("Header block received after trailers.");
+ LogStreamError(ERR_SPDY_PROTOCOL_ERROR, error);
+ session_->ResetStream(stream_id_, RST_STREAM_PROTOCOL_ERROR, error);
+ break;
}
- return MergeWithResponseHeaders(additional_response_headers);
}
void SpdyStream::OnPushPromiseHeadersReceived(SpdyHeaderBlock headers) {
@@ -483,13 +511,26 @@ void SpdyStream::OnPushPromiseHeadersReceived(SpdyHeaderBlock headers) {
void SpdyStream::OnDataReceived(std::unique_ptr<SpdyBuffer> buffer) {
DCHECK(session_->IsStreamActive(stream_id_));
+ if (response_state_ == READY_FOR_HEADERS) {
+ const std::string error("DATA received before headers.");
+ LogStreamError(ERR_SPDY_PROTOCOL_ERROR, error);
+ session_->ResetStream(stream_id_, RST_STREAM_PROTOCOL_ERROR, error);
+ return;
+ }
+
+ if (response_state_ == TRAILERS_RECEIVED && buffer) {
+ const std::string error("DATA received after trailers.");
+ LogStreamError(ERR_SPDY_PROTOCOL_ERROR, error);
+ session_->ResetStream(stream_id_, RST_STREAM_PROTOCOL_ERROR, error);
+ return;
+ }
+
// Track our bandwidth.
recv_bytes_ += buffer ? buffer->GetRemainingSize() : 0;
recv_last_byte_time_ = base::TimeTicks::Now();
- // If we're still buffering data for a push stream, we will do the
- // check for data received with incomplete headers in
- // PushedStreamReplayData().
+ // If we're still buffering data for a push stream, we will do the check for
+ // data received with incomplete headers in PushedStreamReplay().
if (io_state_ == STATE_HALF_CLOSED_LOCAL_UNCLAIMED) {
DCHECK_EQ(type_, SPDY_PUSH_STREAM);
// It should be valid for this to happen in the server push case.
@@ -504,25 +545,6 @@ void SpdyStream::OnDataReceived(std::unique_ptr<SpdyBuffer> buffer) {
return;
}
- if (response_headers_status_ == TRAILERS_RECEIVED && buffer) {
- // TRAILERS_RECEIVED is only used in SPDY_REQUEST_RESPONSE_STREAM and
- // SPDY_BIDIRECTIONAL_STREAM.
- DCHECK(type_ == SPDY_REQUEST_RESPONSE_STREAM ||
- type_ == SPDY_BIDIRECTIONAL_STREAM);
- session_->ResetStream(stream_id_, RST_STREAM_PROTOCOL_ERROR,
- "Data received after trailers");
- return;
- }
-
- // If we have response headers but the delegate has indicated that
- // it's still incomplete, then that's a protocol error.
- if (response_headers_status_ == RESPONSE_HEADERS_ARE_INCOMPLETE) {
- LogStreamError(ERR_SPDY_PROTOCOL_ERROR,
- "Data received with incomplete headers.");
- session_->CloseActiveStream(stream_id_, ERR_SPDY_PROTOCOL_ERROR);
- return;
- }
-
CHECK(!IsClosed());
if (!buffer) {
@@ -567,11 +589,16 @@ void SpdyStream::OnPaddingConsumed(size_t len) {
void SpdyStream::OnFrameWriteComplete(SpdyFrameType frame_type,
size_t frame_size) {
+ // PRIORITY writes are allowed at any time and do not trigger a state update.
+ if (frame_type == PRIORITY) {
+ return;
+ }
+
DCHECK_NE(type_, SPDY_PUSH_STREAM);
CHECK(frame_type == HEADERS || frame_type == DATA) << frame_type;
int result =
- (frame_type == HEADERS) ? OnRequestHeadersSent() : OnDataSent(frame_size);
+ (frame_type == HEADERS) ? OnHeadersSent() : OnDataSent(frame_size);
if (result == ERR_IO_PENDING) {
// The write operation hasn't completed yet.
return;
@@ -592,7 +619,7 @@ void SpdyStream::OnFrameWriteComplete(SpdyFrameType frame_type,
base::WeakPtr<SpdyStream> weak_this = GetWeakPtr();
write_handler_guard_ = true;
if (frame_type == HEADERS) {
- delegate_->OnRequestHeadersSent();
+ delegate_->OnHeadersSent();
} else {
delegate_->OnDataSent();
}
@@ -606,7 +633,7 @@ void SpdyStream::OnFrameWriteComplete(SpdyFrameType frame_type,
}
}
-int SpdyStream::OnRequestHeadersSent() {
+int SpdyStream::OnHeadersSent() {
CHECK_EQ(io_state_, STATE_IDLE);
CHECK_NE(stream_id_, 0u);
@@ -648,7 +675,7 @@ void SpdyStream::OnClose(int status) {
// SpdySession is shutting down while the stream is in an intermediate state.
io_state_ = STATE_CLOSED;
if (status == ERR_SPDY_RST_STREAM_NO_ERROR_RECEIVED) {
- if (response_headers_status_ == RESPONSE_HEADERS_ARE_INCOMPLETE) {
+ if (response_state_ == READY_FOR_HEADERS) {
status = ERR_SPDY_PROTOCOL_ERROR;
} else {
status = OK;
@@ -727,8 +754,8 @@ bool SpdyStream::GetSSLInfo(SSLInfo* ssl_info) const {
return session_->GetSSLInfo(ssl_info);
}
-bool SpdyStream::WasNpnNegotiated() const {
- return session_->WasNpnNegotiated();
+bool SpdyStream::WasAlpnNegotiated() const {
+ return session_->WasAlpnNegotiated();
}
NextProto SpdyStream::GetNegotiatedProtocol() const {
@@ -869,62 +896,31 @@ void SpdyStream::QueueNextDataFrame() {
new SimpleBufferProducer(std::move(data_buffer))));
}
-int SpdyStream::MergeWithResponseHeaders(
- const SpdyHeaderBlock& new_response_headers) {
- if (new_response_headers.find("transfer-encoding") !=
- new_response_headers.end()) {
+void SpdyStream::SaveResponseHeaders(const SpdyHeaderBlock& response_headers) {
+ DCHECK(response_headers_.empty());
+ if (response_headers.find("transfer-encoding") != response_headers.end()) {
session_->ResetStream(stream_id_, RST_STREAM_PROTOCOL_ERROR,
"Received transfer-encoding header");
- return ERR_SPDY_PROTOCOL_ERROR;
+ return;
}
- for (SpdyHeaderBlock::const_iterator it = new_response_headers.begin();
- it != new_response_headers.end(); ++it) {
+ for (SpdyHeaderBlock::const_iterator it = response_headers.begin();
+ it != response_headers.end(); ++it) {
// Disallow uppercase headers.
if (ContainsUppercaseAscii(it->first)) {
session_->ResetStream(
stream_id_, RST_STREAM_PROTOCOL_ERROR,
"Upper case characters in header: " + it->first.as_string());
- return ERR_SPDY_PROTOCOL_ERROR;
- }
-
- SpdyHeaderBlock::iterator it2 = response_headers_.find(it->first);
- // Disallow duplicate headers. This is just to be conservative.
- if (it2 != response_headers_.end()) {
- session_->ResetStream(stream_id_, RST_STREAM_PROTOCOL_ERROR,
- "Duplicate header: " + it->first.as_string());
- return ERR_SPDY_PROTOCOL_ERROR;
+ return;
}
response_headers_.insert(*it);
}
- // If delegate_ is not yet attached, we'll call
- // OnResponseHeadersUpdated() after the delegate gets attached to
- // the stream.
- if (delegate_) {
- // The call to OnResponseHeadersUpdated() below may delete |this|,
- // so use |weak_this| to detect that.
- base::WeakPtr<SpdyStream> weak_this = GetWeakPtr();
-
- SpdyResponseHeadersStatus status =
- delegate_->OnResponseHeadersUpdated(response_headers_);
- if (status == RESPONSE_HEADERS_ARE_INCOMPLETE) {
- // Since RESPONSE_HEADERS_ARE_INCOMPLETE was returned, we must not
- // have been closed.
- CHECK(weak_this);
- // Incomplete headers are OK only for push streams.
- if (type_ != SPDY_PUSH_STREAM) {
- session_->ResetStream(stream_id_, RST_STREAM_PROTOCOL_ERROR,
- "Incomplete headers");
- return ERR_INCOMPLETE_SPDY_HEADERS;
- }
- } else if (weak_this) {
- response_headers_status_ = RESPONSE_HEADERS_ARE_COMPLETE;
- }
- }
-
- return OK;
+ // If delegate is not yet attached, OnHeadersReceived() will be called after
+ // the delegate gets attached to the stream.
+ if (delegate_)
+ delegate_->OnHeadersReceived(response_headers_);
}
#define STATE_CASE(s) \
diff --git a/chromium/net/spdy/spdy_stream.h b/chromium/net/spdy/spdy_stream.h
index b2d6fbbf0d2..01309fdc60e 100644
--- a/chromium/net/spdy/spdy_stream.h
+++ b/chromium/net/spdy/spdy_stream.h
@@ -31,7 +31,6 @@
namespace net {
-class AddressList;
class IPEndPoint;
struct LoadTimingInfo;
class SSLInfo;
@@ -56,18 +55,6 @@ enum SpdySendStatus {
NO_MORE_DATA_TO_SEND
};
-// Returned by SpdyStream::OnResponseHeadersUpdated() to indicate
-// whether the current response headers are complete or not, or whether
-// trailers have been received. TRAILERS_RECEIVED denotes the state where
-// headers are received after DATA frames. TRAILERS_RECEIVED is only used for
-// SPDY_REQUEST_RESPONSE_STREAM, and this state also implies that the response
-// headers are complete.
-enum SpdyResponseHeadersStatus {
- RESPONSE_HEADERS_ARE_INCOMPLETE,
- RESPONSE_HEADERS_ARE_COMPLETE,
- TRAILERS_RECEIVED,
-};
-
// The SpdyStream is used by the SpdySession to represent each stream known
// on the SpdySession. This class provides interfaces for SpdySession to use.
// Streams can be created either by the client or by the server. When they
@@ -84,76 +71,32 @@ class NET_EXPORT_PRIVATE SpdyStream {
// Called when the request headers have been sent. Never called
// for push streams. Must not cause the stream to be closed.
- virtual void OnRequestHeadersSent() = 0;
+ virtual void OnHeadersSent() = 0;
- // WARNING: This function is complicated! Be sure to read the
- // whole comment below if you're working with code that implements
- // or calls this function.
- //
- // Called when the response headers are updated from the
- // server. |response_headers| contains the set of all headers
- // received up to this point; delegates can assume that any
- // headers previously received remain unchanged.
- //
- // This is called at least once before any data is received. If
- // RESPONSE_HEADERS_ARE_INCOMPLETE is returned, this will be
- // called again when more headers are received until
- // RESPONSE_HEADERS_ARE_COMPLETE is returned, and any data
- // received before then will be treated as a protocol error.
- //
- // If RESPONSE_HEADERS_ARE_INCOMPLETE is returned, the delegate
- // must not have closed the stream. Otherwise, if
- // RESPONSE_HEADERS_ARE_COMPLETE is returned, the delegate has
- // processed the headers successfully. However, it still may have
- // closed the stream, e.g. if the headers indicated an error
- // condition.
- //
- // Some type-specific behavior:
- //
- // - For bidirectional streams, this may be called even after
- // data is received, but it is expected that
- // RESPONSE_HEADERS_ARE_COMPLETE is always returned. If
- // RESPONSE_HEADERS_ARE_INCOMPLETE is returned, this is
- // treated as a protocol error.
- //
- // - For request/response streams, this function is called
- // exactly once before data is received, and it is expected
- // that RESPONSE_HEADERS_ARE_COMPLETE is returned. If
- // RESPONSE_HEADERS_ARE_INCOMPLETE is returned, this is
- // treated as a protocol error.
- //
- // - For push streams, it is expected that this function will be
- // called until RESPONSE_HEADERS_ARE_COMPLETE is returned
- // before any data is received; any deviation from this is
- // treated as a protocol error.
- //
- // TODO(jgraettinger): This should be at the semantic (HTTP) rather
- // than stream layer. Streams shouldn't have a notion of header
- // completeness. Move to SpdyHttpStream/SpdyWebsocketStream.
- virtual SpdyResponseHeadersStatus OnResponseHeadersUpdated(
- const SpdyHeaderBlock& response_headers) = 0;
-
- // Called when data is received after all required response
- // headers have been received. |buffer| may be NULL, which signals
- // EOF. Must return OK if the data was received successfully, or
- // a network error code otherwise.
- //
+ // OnHeadersReceived(), OnDataReceived(), OnTrailers(), and OnClose()
+ // are guaranteed to be called in the following order:
+ // - OnHeadersReceived() exactly once;
+ // - OnDataReceived() zero or more times;
+ // - OnTrailers() zero or one times;
+ // - OnClose() exactly once.
+
+ // Called when headers have been received.
+ virtual void OnHeadersReceived(const SpdyHeaderBlock& response_headers) = 0;
+
+ // Called when data is received. |buffer| may be NULL, which signals EOF.
// May cause the stream to be closed.
virtual void OnDataReceived(std::unique_ptr<SpdyBuffer> buffer) = 0;
- // Called when data is sent. Must not cause the stream to be
- // closed.
+ // Called when data is sent. Must not cause the stream to be closed.
virtual void OnDataSent() = 0;
- // Called when trailers are received. Note that trailers HEADER frame will
- // have END_STREAM flag set according to section 8.1 of the HTTP/2 RFC,
- // so this will be followed by OnClose.
+ // Called when trailers are received.
virtual void OnTrailers(const SpdyHeaderBlock& trailers) = 0;
// Called when SpdyStream is closed. No other delegate functions
// will be called after this is called, and the delegate must not
// access the stream after this is called. Must not cause the
- // stream to be be (re-)closed.
+ // stream to be (re-)closed.
//
// TODO(akalin): Allow this function to re-close the stream and
// handle it gracefully.
@@ -199,6 +142,7 @@ class NET_EXPORT_PRIVATE SpdyStream {
const GURL& url() const { return url_; }
RequestPriority priority() const { return priority_; }
+ void set_priority(RequestPriority p) { priority_ = p; }
int32_t send_window_size() const { return send_window_size_; }
@@ -292,19 +236,11 @@ class NET_EXPORT_PRIVATE SpdyStream {
base::Time GetRequestTime() const;
void SetRequestTime(base::Time t);
- // Called at most once by the SpdySession when the initial response headers
- // have been received for this stream. Returns a status code; if it is an
- // error, the stream was closed by this function.
- int OnInitialResponseHeadersReceived(const SpdyHeaderBlock& response_headers,
- base::Time response_time,
- base::TimeTicks recv_first_byte_time);
-
- // Called by the SpdySession (only after
- // OnInitialResponseHeadersReceived() has been called) when
- // late-bound headers are received for a stream. Returns a status
- // code; if it is an error, the stream was closed by this function.
- int OnAdditionalResponseHeadersReceived(
- const SpdyHeaderBlock& additional_response_headers);
+ // Called by SpdySession when headers are received for this stream. May close
+ // the stream.
+ void OnHeadersReceived(const SpdyHeaderBlock& response_headers,
+ base::Time response_time,
+ base::TimeTicks recv_first_byte_time);
// Called by the SpdySession when a frame carrying request headers opening a
// push stream is received. Stream transits to STATE_RESERVED_REMOTE state.
@@ -334,7 +270,7 @@ class NET_EXPORT_PRIVATE SpdyStream {
void OnFrameWriteComplete(SpdyFrameType frame_type, size_t frame_size);
// HEADERS-specific write handler invoked by OnFrameWriteComplete().
- int OnRequestHeadersSent();
+ int OnHeadersSent();
// DATA-specific write handler invoked by OnFrameWriteComplete().
// If more data is already available to be written, the next write is
@@ -367,11 +303,10 @@ class NET_EXPORT_PRIVATE SpdyStream {
// Only one send can be in flight at a time, except for push
// streams, which must not send anything.
- // Sends the request headers. The delegate is called back via
- // OnRequestHeadersSent() when the request headers have completed
- // sending. |send_status| must be MORE_DATA_TO_SEND for
- // bidirectional streams; for request/response streams, it must be
- // MORE_DATA_TO_SEND if the request has data to upload, or
+ // Sends the request headers. The delegate is called back via OnHeadersSent()
+ // when the request headers have completed sending. |send_status| must be
+ // MORE_DATA_TO_SEND for bidirectional streams; for request/response streams,
+ // it must be MORE_DATA_TO_SEND if the request has data to upload, or
// NO_MORE_DATA_TO_SEND if not.
int SendRequestHeaders(SpdyHeaderBlock request_headers,
SpdySendStatus send_status);
@@ -387,8 +322,7 @@ class NET_EXPORT_PRIVATE SpdyStream {
bool GetSSLInfo(SSLInfo* ssl_info) const;
// Returns true if ALPN was negotiated for the underlying socket.
- // TODO(bnc): Rename to WasAlpnNegotiated().
- bool WasNpnNegotiated() const;
+ bool WasAlpnNegotiated() const;
// Returns the protocol negotiated via ALPN for the underlying socket.
NextProto GetNegotiatedProtocol() const;
@@ -455,6 +389,19 @@ class NET_EXPORT_PRIVATE SpdyStream {
STATE_CLOSED,
};
+ // Per RFC 7540 Section 8.1, an HTTP response consists of:
+ // * zero or more header blocks with informational (1xx) HTTP status,
+ // * one header block,
+ // * zero or more DATA frames,
+ // * zero or one header block ("trailers").
+ // Each header block must have a ":status" header field. SpdyStream enforces
+ // these requirements, and resets the stream if they are not met.
+ enum ResponseState {
+ READY_FOR_HEADERS,
+ READY_FOR_DATA_OR_TRAILERS,
+ TRAILERS_RECEIVED
+ };
+
// Update the histograms. Can safely be called repeatedly, but should only
// be called after the stream has completed.
void UpdateHistograms();
@@ -477,11 +424,9 @@ class NET_EXPORT_PRIVATE SpdyStream {
// |pending_send_data_| is set.
void QueueNextDataFrame();
- // Merge the given headers into |response_headers_| and calls
- // OnResponseHeadersUpdated() on the delegate (if attached).
- // Returns a status code; if it is an error, the stream was closed
- // by this function.
- int MergeWithResponseHeaders(const SpdyHeaderBlock& new_response_headers);
+ // Saves the given headers into |response_headers_| and calls
+ // OnHeadersReceived() on the delegate if attached.
+ void SaveResponseHeaders(const SpdyHeaderBlock& response_headers);
static std::string DescribeState(State state);
@@ -489,7 +434,7 @@ class NET_EXPORT_PRIVATE SpdyStream {
SpdyStreamId stream_id_;
const GURL url_;
- const RequestPriority priority_;
+ RequestPriority priority_;
bool send_stalled_by_flow_control_;
@@ -539,7 +484,7 @@ class NET_EXPORT_PRIVATE SpdyStream {
base::Time request_time_;
SpdyHeaderBlock response_headers_;
- SpdyResponseHeadersStatus response_headers_status_;
+ ResponseState response_state_;
base::Time response_time_;
State io_state_;
diff --git a/chromium/net/spdy/spdy_stream_test_util.cc b/chromium/net/spdy/spdy_stream_test_util.cc
index 9b250b2f074..9bef50af813 100644
--- a/chromium/net/spdy/spdy_stream_test_util.cc
+++ b/chromium/net/spdy/spdy_stream_test_util.cc
@@ -23,12 +23,10 @@ ClosingDelegate::ClosingDelegate(
ClosingDelegate::~ClosingDelegate() {}
-void ClosingDelegate::OnRequestHeadersSent() {}
+void ClosingDelegate::OnHeadersSent() {}
-SpdyResponseHeadersStatus ClosingDelegate::OnResponseHeadersUpdated(
- const SpdyHeaderBlock& response_headers) {
- return RESPONSE_HEADERS_ARE_COMPLETE;
-}
+void ClosingDelegate::OnHeadersReceived(
+ const SpdyHeaderBlock& response_headers) {}
void ClosingDelegate::OnDataReceived(std::unique_ptr<SpdyBuffer> buffer) {}
@@ -52,17 +50,16 @@ StreamDelegateBase::StreamDelegateBase(
StreamDelegateBase::~StreamDelegateBase() {
}
-void StreamDelegateBase::OnRequestHeadersSent() {
+void StreamDelegateBase::OnHeadersSent() {
stream_id_ = stream_->stream_id();
EXPECT_NE(stream_id_, 0u);
send_headers_completed_ = true;
}
-SpdyResponseHeadersStatus StreamDelegateBase::OnResponseHeadersUpdated(
+void StreamDelegateBase::OnHeadersReceived(
const SpdyHeaderBlock& response_headers) {
EXPECT_EQ(stream_->type() != SPDY_PUSH_STREAM, send_headers_completed_);
response_headers_ = response_headers.Clone();
- return RESPONSE_HEADERS_ARE_COMPLETE;
}
void StreamDelegateBase::OnDataReceived(std::unique_ptr<SpdyBuffer> buffer) {
@@ -121,15 +118,13 @@ StreamDelegateSendImmediate::StreamDelegateSendImmediate(
StreamDelegateSendImmediate::~StreamDelegateSendImmediate() {
}
-SpdyResponseHeadersStatus StreamDelegateSendImmediate::OnResponseHeadersUpdated(
+void StreamDelegateSendImmediate::OnHeadersReceived(
const SpdyHeaderBlock& response_headers) {
- SpdyResponseHeadersStatus status =
- StreamDelegateBase::OnResponseHeadersUpdated(response_headers);
+ StreamDelegateBase::OnHeadersReceived(response_headers);
if (data_.data()) {
scoped_refptr<StringIOBuffer> buf(new StringIOBuffer(data_.as_string()));
stream()->SendData(buf.get(), buf->size(), MORE_DATA_TO_SEND);
}
- return status;
}
StreamDelegateWithBody::StreamDelegateWithBody(
@@ -141,8 +136,8 @@ StreamDelegateWithBody::StreamDelegateWithBody(
StreamDelegateWithBody::~StreamDelegateWithBody() {
}
-void StreamDelegateWithBody::OnRequestHeadersSent() {
- StreamDelegateBase::OnRequestHeadersSent();
+void StreamDelegateWithBody::OnHeadersSent() {
+ StreamDelegateBase::OnHeadersSent();
stream()->SendData(buf_.get(), buf_->size(), NO_MORE_DATA_TO_SEND);
}
@@ -154,11 +149,9 @@ StreamDelegateCloseOnHeaders::StreamDelegateCloseOnHeaders(
StreamDelegateCloseOnHeaders::~StreamDelegateCloseOnHeaders() {
}
-SpdyResponseHeadersStatus
-StreamDelegateCloseOnHeaders::OnResponseHeadersUpdated(
+void StreamDelegateCloseOnHeaders::OnHeadersReceived(
const SpdyHeaderBlock& response_headers) {
stream()->Cancel();
- return RESPONSE_HEADERS_ARE_COMPLETE;
}
} // namespace test
diff --git a/chromium/net/spdy/spdy_stream_test_util.h b/chromium/net/spdy/spdy_stream_test_util.h
index ef3617f6944..0ec2b646d9b 100644
--- a/chromium/net/spdy/spdy_stream_test_util.h
+++ b/chromium/net/spdy/spdy_stream_test_util.h
@@ -27,9 +27,8 @@ class ClosingDelegate : public SpdyStream::Delegate {
~ClosingDelegate() override;
// SpdyStream::Delegate implementation.
- void OnRequestHeadersSent() override;
- SpdyResponseHeadersStatus OnResponseHeadersUpdated(
- const SpdyHeaderBlock& response_headers) override;
+ void OnHeadersSent() override;
+ void OnHeadersReceived(const SpdyHeaderBlock& response_headers) override;
void OnDataReceived(std::unique_ptr<SpdyBuffer> buffer) override;
void OnDataSent() override;
void OnTrailers(const SpdyHeaderBlock& trailers) override;
@@ -49,9 +48,8 @@ class StreamDelegateBase : public SpdyStream::Delegate {
explicit StreamDelegateBase(const base::WeakPtr<SpdyStream>& stream);
~StreamDelegateBase() override;
- void OnRequestHeadersSent() override;
- SpdyResponseHeadersStatus OnResponseHeadersUpdated(
- const SpdyHeaderBlock& response_headers) override;
+ void OnHeadersSent() override;
+ void OnHeadersReceived(const SpdyHeaderBlock& response_headers) override;
void OnDataReceived(std::unique_ptr<SpdyBuffer> buffer) override;
void OnDataSent() override;
void OnTrailers(const SpdyHeaderBlock& trailers) override;
@@ -95,7 +93,7 @@ class StreamDelegateDoNothing : public StreamDelegateBase {
~StreamDelegateDoNothing() override;
};
-// Test delegate that sends data immediately in OnResponseHeadersUpdated().
+// Test delegate that sends data immediately in OnHeadersReceived().
class StreamDelegateSendImmediate : public StreamDelegateBase {
public:
// |data| can be NULL.
@@ -103,8 +101,7 @@ class StreamDelegateSendImmediate : public StreamDelegateBase {
base::StringPiece data);
~StreamDelegateSendImmediate() override;
- SpdyResponseHeadersStatus OnResponseHeadersUpdated(
- const SpdyHeaderBlock& response_headers) override;
+ void OnHeadersReceived(const SpdyHeaderBlock& response_headers) override;
private:
base::StringPiece data_;
@@ -117,21 +114,20 @@ class StreamDelegateWithBody : public StreamDelegateBase {
base::StringPiece data);
~StreamDelegateWithBody() override;
- void OnRequestHeadersSent() override;
+ void OnHeadersSent() override;
private:
scoped_refptr<StringIOBuffer> buf_;
};
-// Test delegate that closes stream in OnResponseHeadersUpdated().
+// Test delegate that closes stream in OnHeadersReceived().
class StreamDelegateCloseOnHeaders : public StreamDelegateBase {
public:
explicit StreamDelegateCloseOnHeaders(
const base::WeakPtr<SpdyStream>& stream);
~StreamDelegateCloseOnHeaders() override;
- SpdyResponseHeadersStatus OnResponseHeadersUpdated(
- const SpdyHeaderBlock& response_headers) override;
+ void OnHeadersReceived(const SpdyHeaderBlock& response_headers) override;
};
} // namespace test
diff --git a/chromium/net/spdy/spdy_stream_unittest.cc b/chromium/net/spdy/spdy_stream_unittest.cc
index 298b6a20c60..9f60908a9b6 100644
--- a/chromium/net/spdy/spdy_stream_unittest.cc
+++ b/chromium/net/spdy/spdy_stream_unittest.cc
@@ -6,6 +6,7 @@
#include <stdint.h>
+#include <algorithm>
#include <cstddef>
#include <limits>
#include <memory>
@@ -35,9 +36,6 @@
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
-using net::test::IsError;
-using net::test::IsOk;
-
// TODO(ukai): factor out common part with spdy_http_stream_unittest.cc
//
namespace net {
@@ -46,11 +44,17 @@ namespace test {
namespace {
-const char kStreamUrl[] = "http://www.example.org/";
+const char kPushUrl[] = "https://www.example.org/push";
const char kPostBody[] = "\0hello!\xff";
const size_t kPostBodyLength = arraysize(kPostBody);
const base::StringPiece kPostBodyStringPiece(kPostBody, kPostBodyLength);
+static base::TimeTicks g_time_now;
+
+base::TimeTicks InstantaneousReads() {
+ return g_time_now;
+}
+
} // namespace
class SpdyStreamTest : public ::testing::Test {
@@ -60,16 +64,17 @@ class SpdyStreamTest : public ::testing::Test {
typedef base::Callback<void(const base::WeakPtr<SpdyStream>&, int32_t)>
UnstallFunction;
- SpdyStreamTest() : offset_(0), ssl_(SYNCHRONOUS, OK) {
- spdy_util_.set_default_url(GURL(kStreamUrl));
- session_ = SpdySessionDependencies::SpdyCreateSession(&session_deps_);
- }
+ SpdyStreamTest()
+ : url_(kDefaultUrl),
+ session_(SpdySessionDependencies::SpdyCreateSession(&session_deps_)),
+ offset_(0),
+ ssl_(SYNCHRONOUS, OK) {}
~SpdyStreamTest() override {}
base::WeakPtr<SpdySession> CreateDefaultSpdySession() {
- SpdySessionKey key(HostPortPair("www.example.org", 80),
- ProxyServer::Direct(), PRIVACY_MODE_DISABLED);
+ SpdySessionKey key(HostPortPair::FromURL(url_), ProxyServer::Direct(),
+ PRIVACY_MODE_DISABLED);
return CreateSecureSpdySession(session_.get(), key, NetLogWithSource());
}
@@ -131,6 +136,7 @@ class SpdyStreamTest : public ::testing::Test {
session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_);
}
+ const GURL url_;
SpdyTestUtil spdy_util_;
SpdySessionDependencies session_deps_;
std::unique_ptr<HttpNetworkSession> session_;
@@ -144,13 +150,11 @@ class SpdyStreamTest : public ::testing::Test {
};
TEST_F(SpdyStreamTest, SendDataAfterOpen) {
- GURL url(kStreamUrl);
-
SpdySerializedFrame req(spdy_util_.ConstructSpdyPost(
- kStreamUrl, 1, kPostBodyLength, LOWEST, NULL, 0));
+ kDefaultUrl, 1, kPostBodyLength, LOWEST, nullptr, 0));
AddWrite(req);
- SpdySerializedFrame resp(spdy_util_.ConstructSpdyPostReply(NULL, 0));
+ SpdySerializedFrame resp(spdy_util_.ConstructSpdyPostReply(nullptr, 0));
AddRead(resp);
SpdySerializedFrame msg(
@@ -174,7 +178,7 @@ TEST_F(SpdyStreamTest, SendDataAfterOpen) {
base::WeakPtr<SpdySession> session(CreateDefaultSpdySession());
base::WeakPtr<SpdyStream> stream = CreateStreamSynchronously(
- SPDY_BIDIRECTIONAL_STREAM, session, url, LOWEST, NetLogWithSource());
+ SPDY_BIDIRECTIONAL_STREAM, session, url_, LOWEST, NetLogWithSource());
ASSERT_TRUE(stream);
StreamDelegateSendImmediate delegate(stream, kPostBodyStringPiece);
@@ -183,10 +187,10 @@ TEST_F(SpdyStreamTest, SendDataAfterOpen) {
EXPECT_TRUE(stream->GetUrlFromHeaders().is_empty());
SpdyHeaderBlock headers(
- spdy_util_.ConstructPostHeaderBlock(kStreamUrl, kPostBodyLength));
- EXPECT_EQ(ERR_IO_PENDING,
- stream->SendRequestHeaders(std::move(headers), MORE_DATA_TO_SEND));
- EXPECT_EQ(kStreamUrl, stream->GetUrlFromHeaders().spec());
+ spdy_util_.ConstructPostHeaderBlock(kDefaultUrl, kPostBodyLength));
+ EXPECT_THAT(stream->SendRequestHeaders(std::move(headers), MORE_DATA_TO_SEND),
+ IsError(ERR_IO_PENDING));
+ EXPECT_EQ(kDefaultUrl, stream->GetUrlFromHeaders().spec());
EXPECT_THAT(delegate.WaitForClose(), IsError(ERR_CONNECTION_CLOSED));
@@ -216,19 +220,17 @@ class StreamDelegateWithTrailers : public test::StreamDelegateWithBody {
SpdyHeaderBlock trailers_;
};
-// Regression test for crbug.com/481033.
+// Regression test for https://crbug.com/481033.
TEST_F(SpdyStreamTest, Trailers) {
- GURL url(kStreamUrl);
-
SpdySerializedFrame req(spdy_util_.ConstructSpdyPost(
- kStreamUrl, 1, kPostBodyLength, LOWEST, NULL, 0));
+ kDefaultUrl, 1, kPostBodyLength, LOWEST, nullptr, 0));
AddWrite(req);
SpdySerializedFrame msg(
spdy_util_.ConstructSpdyDataFrame(1, kPostBody, kPostBodyLength, true));
AddWrite(msg);
- SpdySerializedFrame resp(spdy_util_.ConstructSpdyPostReply(NULL, 0));
+ SpdySerializedFrame resp(spdy_util_.ConstructSpdyPostReply(nullptr, 0));
AddRead(resp);
SpdySerializedFrame echo(
@@ -254,7 +256,7 @@ TEST_F(SpdyStreamTest, Trailers) {
base::WeakPtr<SpdySession> session(CreateDefaultSpdySession());
base::WeakPtr<SpdyStream> stream = CreateStreamSynchronously(
- SPDY_REQUEST_RESPONSE_STREAM, session, url, LOWEST, NetLogWithSource());
+ SPDY_REQUEST_RESPONSE_STREAM, session, url_, LOWEST, NetLogWithSource());
ASSERT_TRUE(stream);
StreamDelegateWithTrailers delegate(stream, kPostBodyStringPiece);
@@ -263,10 +265,10 @@ TEST_F(SpdyStreamTest, Trailers) {
EXPECT_TRUE(stream->GetUrlFromHeaders().is_empty());
SpdyHeaderBlock headers(
- spdy_util_.ConstructPostHeaderBlock(kStreamUrl, kPostBodyLength));
- EXPECT_EQ(ERR_IO_PENDING,
- stream->SendRequestHeaders(std::move(headers), MORE_DATA_TO_SEND));
- EXPECT_EQ(kStreamUrl, stream->GetUrlFromHeaders().spec());
+ spdy_util_.ConstructPostHeaderBlock(kDefaultUrl, kPostBodyLength));
+ EXPECT_THAT(stream->SendRequestHeaders(std::move(headers), MORE_DATA_TO_SEND),
+ IsError(ERR_IO_PENDING));
+ EXPECT_EQ(kDefaultUrl, stream->GetUrlFromHeaders().spec());
EXPECT_THAT(delegate.WaitForClose(), IsError(ERR_CONNECTION_CLOSED));
@@ -281,6 +283,33 @@ TEST_F(SpdyStreamTest, Trailers) {
}
TEST_F(SpdyStreamTest, PushedStream) {
+ SpdySerializedFrame req(
+ spdy_util_.ConstructSpdyGet(nullptr, 0, 1, LOWEST, true));
+ AddWrite(req);
+
+ SpdySerializedFrame reply(spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
+ AddRead(reply);
+
+ SpdySerializedFrame push(
+ spdy_util_.ConstructSpdyPush(nullptr, 0, 2, 1, kPushUrl));
+ AddRead(push);
+
+ SpdySerializedFrame priority(
+ spdy_util_.ConstructSpdyPriority(2, 1, IDLE, true));
+ AddWrite(priority);
+
+ AddReadPause();
+
+ base::StringPiece pushed_msg("foo");
+ SpdySerializedFrame pushed_body(spdy_util_.ConstructSpdyDataFrame(
+ 2, pushed_msg.data(), pushed_msg.size(), true));
+ AddRead(pushed_body);
+
+ base::StringPiece msg("bar");
+ SpdySerializedFrame body(
+ spdy_util_.ConstructSpdyDataFrame(1, msg.data(), msg.size(), true));
+ AddRead(body);
+
AddReadEOF();
SequencedSocketData data(GetReads(), GetNumReads(), GetWrites(),
@@ -291,69 +320,65 @@ TEST_F(SpdyStreamTest, PushedStream) {
AddSSLSocketData();
- base::WeakPtr<SpdySession> spdy_session(CreateDefaultSpdySession());
+ g_time_now = base::TimeTicks::Now();
+ session_deps_.time_func = InstantaneousReads;
+ session_ = SpdySessionDependencies::SpdyCreateSession(&session_deps_);
- // Conjure up a stream.
- SpdyStreamRequest stream_request;
- int result = stream_request.StartRequest(
- SPDY_PUSH_STREAM, spdy_session, GURL(), DEFAULT_PRIORITY,
- NetLogWithSource(), CompletionCallback());
- ASSERT_THAT(result, IsOk());
- base::WeakPtr<SpdyStream> stream = stream_request.ReleaseStream();
- ActivatePushStream(spdy_session.get(), stream.get());
+ base::WeakPtr<SpdySession> session(CreateDefaultSpdySession());
- EXPECT_TRUE(stream->GetUrlFromHeaders().is_empty());
+ base::WeakPtr<SpdyStream> stream = CreateStreamSynchronously(
+ SPDY_REQUEST_RESPONSE_STREAM, session, url_, LOWEST, NetLogWithSource());
+ ASSERT_TRUE(stream);
- // Set required request headers.
- SpdyHeaderBlock request_headers;
- spdy_util_.AddUrlToHeaderBlock(kStreamUrl, &request_headers);
- stream->OnPushPromiseHeadersReceived(std::move(request_headers));
+ StreamDelegateDoNothing delegate(stream);
+ stream->SetDelegate(&delegate);
- base::Time response_time = base::Time::Now();
- base::TimeTicks first_byte_time = base::TimeTicks::Now();
- // Send some basic response headers.
- SpdyHeaderBlock response;
- response[spdy_util_.GetStatusKey()] = "200";
- stream->OnInitialResponseHeadersReceived(response, response_time,
- first_byte_time);
+ EXPECT_TRUE(stream->GetUrlFromHeaders().is_empty());
- // And some more headers.
- // TODO(baranovich): not valid for HTTP 2.
- SpdyHeaderBlock headers;
- headers["alpha"] = "beta";
- stream->OnAdditionalResponseHeadersReceived(headers);
+ SpdyHeaderBlock headers(spdy_util_.ConstructGetHeaderBlock(kDefaultUrl));
+ EXPECT_THAT(
+ stream->SendRequestHeaders(std::move(headers), NO_MORE_DATA_TO_SEND),
+ IsError(ERR_IO_PENDING));
+ EXPECT_EQ(kDefaultUrl, stream->GetUrlFromHeaders().spec());
- EXPECT_EQ(kStreamUrl, stream->GetUrlFromHeaders().spec());
+ data.RunUntilPaused();
- StreamDelegateDoNothing delegate(stream->GetWeakPtr());
- stream->SetDelegate(&delegate);
+ base::WeakPtr<SpdyStream> push_stream;
+ EXPECT_THAT(session->GetPushStream(GURL(kPushUrl), IDLE, &push_stream,
+ NetLogWithSource()),
+ IsOk());
+ ASSERT_TRUE(push_stream);
+ EXPECT_EQ(kPushUrl, push_stream->GetUrlFromHeaders().spec());
LoadTimingInfo load_timing_info;
- EXPECT_TRUE(stream->GetLoadTimingInfo(&load_timing_info));
- EXPECT_EQ(first_byte_time, load_timing_info.push_start);
+ EXPECT_TRUE(push_stream->GetLoadTimingInfo(&load_timing_info));
+ EXPECT_EQ(g_time_now, load_timing_info.push_start);
EXPECT_TRUE(load_timing_info.push_end.is_null());
- stream->OnDataReceived(nullptr);
- LoadTimingInfo load_timing_info2;
- EXPECT_TRUE(stream->GetLoadTimingInfo(&load_timing_info2));
- EXPECT_FALSE(load_timing_info2.push_end.is_null());
+ StreamDelegateDoNothing push_delegate(push_stream);
+ push_stream->SetDelegate(&push_delegate);
- base::RunLoop().RunUntilIdle();
+ data.Resume();
+ EXPECT_TRUE(push_stream->GetLoadTimingInfo(&load_timing_info));
+ EXPECT_EQ(g_time_now, load_timing_info.push_start);
+ EXPECT_FALSE(load_timing_info.push_end.is_null());
+
+ EXPECT_THAT(delegate.WaitForClose(), IsOk());
EXPECT_EQ("200", delegate.GetResponseHeaderValue(spdy_util_.GetStatusKey()));
- EXPECT_EQ("beta", delegate.GetResponseHeaderValue("alpha"));
+ EXPECT_EQ(msg, delegate.TakeReceivedData());
- EXPECT_FALSE(spdy_session);
+ EXPECT_THAT(push_delegate.WaitForClose(), IsOk());
+ EXPECT_EQ("200", delegate.GetResponseHeaderValue(spdy_util_.GetStatusKey()));
+ EXPECT_EQ(pushed_msg, push_delegate.TakeReceivedData());
}
TEST_F(SpdyStreamTest, StreamError) {
- GURL url(kStreamUrl);
-
SpdySerializedFrame req(spdy_util_.ConstructSpdyPost(
- kStreamUrl, 1, kPostBodyLength, LOWEST, NULL, 0));
+ kDefaultUrl, 1, kPostBodyLength, LOWEST, nullptr, 0));
AddWrite(req);
- SpdySerializedFrame resp(spdy_util_.ConstructSpdyGetReply(NULL, 0, 1));
+ SpdySerializedFrame resp(spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
AddRead(resp);
SpdySerializedFrame msg(
@@ -378,9 +403,8 @@ TEST_F(SpdyStreamTest, StreamError) {
base::WeakPtr<SpdySession> session(CreateDefaultSpdySession());
- base::WeakPtr<SpdyStream> stream =
- CreateStreamSynchronously(
- SPDY_BIDIRECTIONAL_STREAM, session, url, LOWEST, log.bound());
+ base::WeakPtr<SpdyStream> stream = CreateStreamSynchronously(
+ SPDY_BIDIRECTIONAL_STREAM, session, url_, LOWEST, log.bound());
ASSERT_TRUE(stream);
StreamDelegateSendImmediate delegate(stream, kPostBodyStringPiece);
@@ -389,10 +413,10 @@ TEST_F(SpdyStreamTest, StreamError) {
EXPECT_TRUE(stream->GetUrlFromHeaders().is_empty());
SpdyHeaderBlock headers(
- spdy_util_.ConstructPostHeaderBlock(kStreamUrl, kPostBodyLength));
- EXPECT_EQ(ERR_IO_PENDING,
- stream->SendRequestHeaders(std::move(headers), MORE_DATA_TO_SEND));
- EXPECT_EQ(kStreamUrl, stream->GetUrlFromHeaders().spec());
+ spdy_util_.ConstructPostHeaderBlock(kDefaultUrl, kPostBodyLength));
+ EXPECT_THAT(stream->SendRequestHeaders(std::move(headers), MORE_DATA_TO_SEND),
+ IsError(ERR_IO_PENDING));
+ EXPECT_EQ(kDefaultUrl, stream->GetUrlFromHeaders().spec());
EXPECT_THAT(delegate.WaitForClose(), IsError(ERR_CONNECTION_CLOSED));
@@ -418,14 +442,11 @@ TEST_F(SpdyStreamTest, StreamError) {
EXPECT_EQ(static_cast<int>(stream_id), stream_id2);
}
-// Make sure that large blocks of data are properly split up into
-// frame-sized chunks for a request/response (i.e., an HTTP-like)
-// stream.
+// Make sure that large blocks of data are properly split up into frame-sized
+// chunks for a request/response (i.e., an HTTP-like) stream.
TEST_F(SpdyStreamTest, SendLargeDataAfterOpenRequestResponse) {
- GURL url(kStreamUrl);
-
SpdySerializedFrame req(spdy_util_.ConstructSpdyPost(
- kStreamUrl, 1, kPostBodyLength, LOWEST, NULL, 0));
+ kDefaultUrl, 1, kPostBodyLength, LOWEST, nullptr, 0));
AddWrite(req);
std::string chunk_data(kMaxSpdyFrameChunkSize, 'x');
@@ -438,7 +459,7 @@ TEST_F(SpdyStreamTest, SendLargeDataAfterOpenRequestResponse) {
1, chunk_data.data(), chunk_data.length(), true));
AddWrite(last_chunk);
- SpdySerializedFrame resp(spdy_util_.ConstructSpdyPostReply(NULL, 0));
+ SpdySerializedFrame resp(spdy_util_.ConstructSpdyPostReply(nullptr, 0));
AddRead(resp);
AddReadEOF();
@@ -454,7 +475,7 @@ TEST_F(SpdyStreamTest, SendLargeDataAfterOpenRequestResponse) {
base::WeakPtr<SpdySession> session(CreateDefaultSpdySession());
base::WeakPtr<SpdyStream> stream = CreateStreamSynchronously(
- SPDY_REQUEST_RESPONSE_STREAM, session, url, LOWEST, NetLogWithSource());
+ SPDY_REQUEST_RESPONSE_STREAM, session, url_, LOWEST, NetLogWithSource());
ASSERT_TRUE(stream);
std::string body_data(3 * kMaxSpdyFrameChunkSize, 'x');
@@ -464,10 +485,10 @@ TEST_F(SpdyStreamTest, SendLargeDataAfterOpenRequestResponse) {
EXPECT_TRUE(stream->GetUrlFromHeaders().is_empty());
SpdyHeaderBlock headers(
- spdy_util_.ConstructPostHeaderBlock(kStreamUrl, kPostBodyLength));
- EXPECT_EQ(ERR_IO_PENDING,
- stream->SendRequestHeaders(std::move(headers), MORE_DATA_TO_SEND));
- EXPECT_EQ(kStreamUrl, stream->GetUrlFromHeaders().spec());
+ spdy_util_.ConstructPostHeaderBlock(kDefaultUrl, kPostBodyLength));
+ EXPECT_THAT(stream->SendRequestHeaders(std::move(headers), MORE_DATA_TO_SEND),
+ IsError(ERR_IO_PENDING));
+ EXPECT_EQ(kDefaultUrl, stream->GetUrlFromHeaders().spec());
EXPECT_THAT(delegate.WaitForClose(), IsError(ERR_CONNECTION_CLOSED));
@@ -477,17 +498,14 @@ TEST_F(SpdyStreamTest, SendLargeDataAfterOpenRequestResponse) {
EXPECT_TRUE(data.AllWriteDataConsumed());
}
-// Make sure that large blocks of data are properly split up into
-// frame-sized chunks for a bidirectional (i.e., non-HTTP-like)
-// stream.
+// Make sure that large blocks of data are properly split up into frame-sized
+// chunks for a bidirectional (i.e., non-HTTP-like) stream.
TEST_F(SpdyStreamTest, SendLargeDataAfterOpenBidirectional) {
- GURL url(kStreamUrl);
-
SpdySerializedFrame req(spdy_util_.ConstructSpdyPost(
- kStreamUrl, 1, kPostBodyLength, LOWEST, NULL, 0));
+ kDefaultUrl, 1, kPostBodyLength, LOWEST, nullptr, 0));
AddWrite(req);
- SpdySerializedFrame resp(spdy_util_.ConstructSpdyPostReply(NULL, 0));
+ SpdySerializedFrame resp(spdy_util_.ConstructSpdyPostReply(nullptr, 0));
AddRead(resp);
std::string chunk_data(kMaxSpdyFrameChunkSize, 'x');
@@ -510,7 +528,7 @@ TEST_F(SpdyStreamTest, SendLargeDataAfterOpenBidirectional) {
base::WeakPtr<SpdySession> session(CreateDefaultSpdySession());
base::WeakPtr<SpdyStream> stream = CreateStreamSynchronously(
- SPDY_BIDIRECTIONAL_STREAM, session, url, LOWEST, NetLogWithSource());
+ SPDY_BIDIRECTIONAL_STREAM, session, url_, LOWEST, NetLogWithSource());
ASSERT_TRUE(stream);
std::string body_data(3 * kMaxSpdyFrameChunkSize, 'x');
@@ -520,10 +538,10 @@ TEST_F(SpdyStreamTest, SendLargeDataAfterOpenBidirectional) {
EXPECT_TRUE(stream->GetUrlFromHeaders().is_empty());
SpdyHeaderBlock headers(
- spdy_util_.ConstructPostHeaderBlock(kStreamUrl, kPostBodyLength));
- EXPECT_EQ(ERR_IO_PENDING,
- stream->SendRequestHeaders(std::move(headers), MORE_DATA_TO_SEND));
- EXPECT_EQ(kStreamUrl, stream->GetUrlFromHeaders().spec());
+ spdy_util_.ConstructPostHeaderBlock(kDefaultUrl, kPostBodyLength));
+ EXPECT_THAT(stream->SendRequestHeaders(std::move(headers), MORE_DATA_TO_SEND),
+ IsError(ERR_IO_PENDING));
+ EXPECT_EQ(kDefaultUrl, stream->GetUrlFromHeaders().spec());
EXPECT_THAT(delegate.WaitForClose(), IsError(ERR_CONNECTION_CLOSED));
@@ -533,18 +551,15 @@ TEST_F(SpdyStreamTest, SendLargeDataAfterOpenBidirectional) {
EXPECT_TRUE(data.AllWriteDataConsumed());
}
-// Receiving a header with uppercase ASCII should result in a protocol
-// error.
+// Receiving a header with uppercase ASCII should result in a protocol error.
TEST_F(SpdyStreamTest, UpperCaseHeaders) {
- GURL url(kStreamUrl);
-
- SpdySerializedFrame syn(
+ SpdySerializedFrame req(
spdy_util_.ConstructSpdyGet(nullptr, 0, 1, LOWEST, true));
- AddWrite(syn);
+ AddWrite(req);
const char* const kExtraHeaders[] = {"X-UpperCase", "yes"};
- SpdySerializedFrame reply(
- spdy_util_.ConstructSpdyGetReply(kExtraHeaders, 1, 1));
+ SpdySerializedFrame reply(spdy_util_.ConstructSpdyGetReply(
+ kExtraHeaders, arraysize(kExtraHeaders) / 2, 1));
AddRead(reply);
SpdySerializedFrame rst(
@@ -564,7 +579,7 @@ TEST_F(SpdyStreamTest, UpperCaseHeaders) {
base::WeakPtr<SpdySession> session(CreateDefaultSpdySession());
base::WeakPtr<SpdyStream> stream = CreateStreamSynchronously(
- SPDY_REQUEST_RESPONSE_STREAM, session, url, LOWEST, NetLogWithSource());
+ SPDY_REQUEST_RESPONSE_STREAM, session, url_, LOWEST, NetLogWithSource());
ASSERT_TRUE(stream);
StreamDelegateDoNothing delegate(stream);
@@ -572,31 +587,40 @@ TEST_F(SpdyStreamTest, UpperCaseHeaders) {
EXPECT_TRUE(stream->GetUrlFromHeaders().is_empty());
- SpdyHeaderBlock headers(spdy_util_.ConstructGetHeaderBlock(kStreamUrl));
- EXPECT_EQ(ERR_IO_PENDING, stream->SendRequestHeaders(std::move(headers),
- NO_MORE_DATA_TO_SEND));
- EXPECT_EQ(kStreamUrl, stream->GetUrlFromHeaders().spec());
+ SpdyHeaderBlock headers(spdy_util_.ConstructGetHeaderBlock(kDefaultUrl));
+ EXPECT_THAT(
+ stream->SendRequestHeaders(std::move(headers), NO_MORE_DATA_TO_SEND),
+ IsError(ERR_IO_PENDING));
+ EXPECT_EQ(kDefaultUrl, stream->GetUrlFromHeaders().spec());
EXPECT_THAT(delegate.WaitForClose(), IsError(ERR_SPDY_PROTOCOL_ERROR));
+
+ // Finish async network reads and writes.
+ base::RunLoop().RunUntilIdle();
+
+ EXPECT_TRUE(data.AllWriteDataConsumed());
+ EXPECT_TRUE(data.AllReadDataConsumed());
}
-// Receiving a header with uppercase ASCII should result in a protocol
-// error even for a push stream.
+// Receiving a header with uppercase ASCII should result in a protocol error
+// even for a push stream.
TEST_F(SpdyStreamTest, UpperCaseHeadersOnPush) {
- GURL url(kStreamUrl);
-
- SpdySerializedFrame syn(
+ SpdySerializedFrame req(
spdy_util_.ConstructSpdyGet(nullptr, 0, 1, LOWEST, true));
- AddWrite(syn);
+ AddWrite(req);
- SpdySerializedFrame reply(spdy_util_.ConstructSpdyGetReply(NULL, 0, 1));
+ SpdySerializedFrame reply(spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
AddRead(reply);
- const char* const extra_headers[] = {"X-UpperCase", "yes"};
- SpdySerializedFrame push(
- spdy_util_.ConstructSpdyPush(extra_headers, 1, 2, 1, kStreamUrl));
+ const char* const kExtraHeaders[] = {"X-UpperCase", "yes"};
+ SpdySerializedFrame push(spdy_util_.ConstructSpdyPush(
+ kExtraHeaders, arraysize(kExtraHeaders) / 2, 2, 1, kPushUrl));
AddRead(push);
+ SpdySerializedFrame priority(
+ spdy_util_.ConstructSpdyPriority(2, 1, IDLE, true));
+ AddWrite(priority);
+
SpdySerializedFrame rst(
spdy_util_.ConstructSpdyRstStream(2, RST_STREAM_PROTOCOL_ERROR));
AddWrite(rst);
@@ -616,7 +640,7 @@ TEST_F(SpdyStreamTest, UpperCaseHeadersOnPush) {
base::WeakPtr<SpdySession> session(CreateDefaultSpdySession());
base::WeakPtr<SpdyStream> stream = CreateStreamSynchronously(
- SPDY_REQUEST_RESPONSE_STREAM, session, url, LOWEST, NetLogWithSource());
+ SPDY_REQUEST_RESPONSE_STREAM, session, url_, LOWEST, NetLogWithSource());
ASSERT_TRUE(stream);
StreamDelegateDoNothing delegate(stream);
@@ -624,53 +648,169 @@ TEST_F(SpdyStreamTest, UpperCaseHeadersOnPush) {
EXPECT_TRUE(stream->GetUrlFromHeaders().is_empty());
- SpdyHeaderBlock headers(spdy_util_.ConstructGetHeaderBlock(kStreamUrl));
- EXPECT_EQ(ERR_IO_PENDING, stream->SendRequestHeaders(std::move(headers),
- NO_MORE_DATA_TO_SEND));
- EXPECT_EQ(kStreamUrl, stream->GetUrlFromHeaders().spec());
+ SpdyHeaderBlock headers(spdy_util_.ConstructGetHeaderBlock(kDefaultUrl));
+ EXPECT_THAT(
+ stream->SendRequestHeaders(std::move(headers), NO_MORE_DATA_TO_SEND),
+ IsError(ERR_IO_PENDING));
+ EXPECT_EQ(kDefaultUrl, stream->GetUrlFromHeaders().spec());
data.RunUntilPaused();
base::WeakPtr<SpdyStream> push_stream;
- EXPECT_THAT(session->GetPushStream(url, &push_stream, NetLogWithSource()),
+ EXPECT_THAT(session->GetPushStream(GURL(kPushUrl), IDLE, &push_stream,
+ NetLogWithSource()),
IsOk());
EXPECT_FALSE(push_stream);
data.Resume();
EXPECT_THAT(delegate.WaitForClose(), IsError(ERR_CONNECTION_CLOSED));
-}
-// Receiving a header with uppercase ASCII in a HEADERS frame should
-// result in a protocol error.
-TEST_F(SpdyStreamTest, UpperCaseHeadersInHeadersFrame) {
- GURL url(kStreamUrl);
+ EXPECT_TRUE(data.AllWriteDataConsumed());
+ EXPECT_TRUE(data.AllReadDataConsumed());
+}
- SpdySerializedFrame syn(
+TEST_F(SpdyStreamTest, HeadersMustHaveStatus) {
+ SpdySerializedFrame req(
spdy_util_.ConstructSpdyGet(nullptr, 0, 1, LOWEST, true));
- AddWrite(syn);
+ AddWrite(req);
- SpdySerializedFrame reply(spdy_util_.ConstructSpdyGetReply(NULL, 0, 1));
+ // Response headers without ":status" header field: protocol error.
+ SpdyHeaderBlock header_block_without_status;
+ header_block_without_status[spdy_util_.GetMethodKey()] = "GET";
+ header_block_without_status[spdy_util_.GetHostKey()] = "www.example.org";
+ header_block_without_status[spdy_util_.GetSchemeKey()] = "https";
+ header_block_without_status[spdy_util_.GetPathKey()] = "/";
+ SpdySerializedFrame reply(
+ spdy_util_.ConstructSpdyReply(1, std::move(header_block_without_status)));
AddRead(reply);
- SpdySerializedFrame push(
- spdy_util_.ConstructSpdyPush(NULL, 0, 2, 1, kStreamUrl));
- AddRead(push);
+ SpdySerializedFrame rst(
+ spdy_util_.ConstructSpdyRstStream(1, RST_STREAM_PROTOCOL_ERROR));
+ AddWrite(rst);
- AddReadPause();
+ AddReadEOF();
- SpdyHeaderBlock late_headers;
- late_headers["X-UpperCase"] = "yes";
- SpdySerializedFrame headers_frame(
- spdy_util_.ConstructSpdyReply(2, std::move(late_headers)));
- AddRead(headers_frame);
+ SequencedSocketData data(GetReads(), GetNumReads(), GetWrites(),
+ GetNumWrites());
+ MockConnect connect_data(SYNCHRONOUS, OK);
+ data.set_connect_data(connect_data);
+ session_deps_.socket_factory->AddSocketDataProvider(&data);
+
+ AddSSLSocketData();
+
+ base::WeakPtr<SpdySession> session(CreateDefaultSpdySession());
+
+ base::WeakPtr<SpdyStream> stream = CreateStreamSynchronously(
+ SPDY_REQUEST_RESPONSE_STREAM, session, url_, LOWEST, NetLogWithSource());
+ ASSERT_TRUE(stream);
+
+ StreamDelegateDoNothing delegate(stream);
+ stream->SetDelegate(&delegate);
+
+ EXPECT_TRUE(stream->GetUrlFromHeaders().is_empty());
+
+ SpdyHeaderBlock headers(spdy_util_.ConstructGetHeaderBlock(kDefaultUrl));
+ EXPECT_EQ(ERR_IO_PENDING, stream->SendRequestHeaders(std::move(headers),
+ NO_MORE_DATA_TO_SEND));
+ EXPECT_EQ(kDefaultUrl, stream->GetUrlFromHeaders().spec());
+
+ EXPECT_THAT(delegate.WaitForClose(), IsError(ERR_SPDY_PROTOCOL_ERROR));
+
+ // Finish async network reads and writes.
+ base::RunLoop().RunUntilIdle();
+
+ EXPECT_TRUE(data.AllWriteDataConsumed());
+ EXPECT_TRUE(data.AllReadDataConsumed());
+}
+
+TEST_F(SpdyStreamTest, HeadersMustHaveStatusOnPushedStream) {
+ SpdySerializedFrame req(
+ spdy_util_.ConstructSpdyGet(nullptr, 0, 1, LOWEST, true));
+ AddWrite(req);
+
+ SpdySerializedFrame reply(spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
+ AddRead(reply);
- AddWritePause();
+ SpdySerializedFrame push_promise(spdy_util_.ConstructInitialSpdyPushFrame(
+ spdy_util_.ConstructGetHeaderBlock(kPushUrl), 2, 1));
+ AddRead(push_promise);
+
+ SpdySerializedFrame priority(
+ spdy_util_.ConstructSpdyPriority(2, 1, IDLE, true));
+ AddWrite(priority);
+
+ // Response headers without ":status" header field: protocol error.
+ SpdyHeaderBlock header_block_without_status;
+ header_block_without_status[spdy_util_.GetMethodKey()] = "GET";
+ header_block_without_status[spdy_util_.GetHostKey()] = "www.example.org";
+ header_block_without_status[spdy_util_.GetSchemeKey()] = "https";
+ header_block_without_status[spdy_util_.GetPathKey()] = "/";
+ SpdySerializedFrame pushed_reply(
+ spdy_util_.ConstructSpdyReply(2, std::move(header_block_without_status)));
+ AddRead(pushed_reply);
SpdySerializedFrame rst(
spdy_util_.ConstructSpdyRstStream(2, RST_STREAM_PROTOCOL_ERROR));
AddWrite(rst);
+ SpdySerializedFrame body(
+ spdy_util_.ConstructSpdyDataFrame(1, kPostBody, kPostBodyLength, true));
+ AddRead(body);
+
+ AddReadEOF();
+
+ SequencedSocketData data(GetReads(), GetNumReads(), GetWrites(),
+ GetNumWrites());
+ MockConnect connect_data(SYNCHRONOUS, OK);
+ data.set_connect_data(connect_data);
+ session_deps_.socket_factory->AddSocketDataProvider(&data);
+
+ AddSSLSocketData();
+
+ base::WeakPtr<SpdySession> session(CreateDefaultSpdySession());
+
+ base::WeakPtr<SpdyStream> stream = CreateStreamSynchronously(
+ SPDY_REQUEST_RESPONSE_STREAM, session, url_, LOWEST, NetLogWithSource());
+ ASSERT_TRUE(stream);
+
+ StreamDelegateDoNothing delegate(stream);
+ stream->SetDelegate(&delegate);
+
+ EXPECT_TRUE(stream->GetUrlFromHeaders().is_empty());
+
+ SpdyHeaderBlock headers(spdy_util_.ConstructGetHeaderBlock(kDefaultUrl));
+ EXPECT_THAT(
+ stream->SendRequestHeaders(std::move(headers), NO_MORE_DATA_TO_SEND),
+ IsError(ERR_IO_PENDING));
+ EXPECT_EQ(kDefaultUrl, stream->GetUrlFromHeaders().spec());
+
+ EXPECT_THAT(delegate.WaitForClose(), IsOk());
+ EXPECT_EQ("200", delegate.GetResponseHeaderValue(spdy_util_.GetStatusKey()));
+ EXPECT_EQ(std::string(kPostBody, kPostBodyLength),
+ delegate.TakeReceivedData());
+
+ // Finish async network reads and writes.
+ base::RunLoop().RunUntilIdle();
+
+ EXPECT_TRUE(data.AllWriteDataConsumed());
+ EXPECT_TRUE(data.AllReadDataConsumed());
+}
+
+TEST_F(SpdyStreamTest, HeadersMustPreceedData) {
+ SpdySerializedFrame req(
+ spdy_util_.ConstructSpdyGet(nullptr, 0, 1, LOWEST, true));
+ AddWrite(req);
+
+ // Response body not preceeded by headers: protocol error.
+ SpdySerializedFrame body(
+ spdy_util_.ConstructSpdyDataFrame(1, kPostBody, kPostBodyLength, true));
+ AddRead(body);
+
+ SpdySerializedFrame rst(
+ spdy_util_.ConstructSpdyRstStream(1, RST_STREAM_PROTOCOL_ERROR));
+ AddWrite(rst);
+
AddReadEOF();
SequencedSocketData data(GetReads(), GetNumReads(), GetWrites(),
@@ -684,7 +824,7 @@ TEST_F(SpdyStreamTest, UpperCaseHeadersInHeadersFrame) {
base::WeakPtr<SpdySession> session(CreateDefaultSpdySession());
base::WeakPtr<SpdyStream> stream = CreateStreamSynchronously(
- SPDY_REQUEST_RESPONSE_STREAM, session, url, LOWEST, NetLogWithSource());
+ SPDY_REQUEST_RESPONSE_STREAM, session, url_, LOWEST, NetLogWithSource());
ASSERT_TRUE(stream);
StreamDelegateDoNothing delegate(stream);
@@ -692,58 +832,273 @@ TEST_F(SpdyStreamTest, UpperCaseHeadersInHeadersFrame) {
EXPECT_TRUE(stream->GetUrlFromHeaders().is_empty());
- SpdyHeaderBlock headers(spdy_util_.ConstructGetHeaderBlock(kStreamUrl));
+ SpdyHeaderBlock headers(spdy_util_.ConstructGetHeaderBlock(kDefaultUrl));
EXPECT_EQ(ERR_IO_PENDING, stream->SendRequestHeaders(std::move(headers),
NO_MORE_DATA_TO_SEND));
- EXPECT_EQ(kStreamUrl, stream->GetUrlFromHeaders().spec());
+ EXPECT_EQ(kDefaultUrl, stream->GetUrlFromHeaders().spec());
- data.RunUntilPaused();
+ EXPECT_THAT(delegate.WaitForClose(), IsError(ERR_SPDY_PROTOCOL_ERROR));
+}
- base::WeakPtr<SpdyStream> push_stream;
- EXPECT_THAT(session->GetPushStream(url, &push_stream, NetLogWithSource()),
- IsOk());
- EXPECT_TRUE(push_stream);
+TEST_F(SpdyStreamTest, HeadersMustPreceedDataOnPushedStream) {
+ SpdySerializedFrame req(
+ spdy_util_.ConstructSpdyGet(nullptr, 0, 1, LOWEST, true));
+ AddWrite(req);
- data.Resume();
- data.RunUntilPaused();
+ SpdySerializedFrame reply(spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
+ AddRead(reply);
- EXPECT_THAT(session->GetPushStream(url, &push_stream, NetLogWithSource()),
- IsOk());
- EXPECT_FALSE(push_stream);
+ SpdySerializedFrame push_promise(spdy_util_.ConstructInitialSpdyPushFrame(
+ spdy_util_.ConstructGetHeaderBlock(kPushUrl), 2, 1));
+ AddRead(push_promise);
- data.Resume();
+ SpdySerializedFrame priority(
+ spdy_util_.ConstructSpdyPriority(2, 1, IDLE, true));
+ AddWrite(priority);
- EXPECT_THAT(delegate.WaitForClose(), IsError(ERR_CONNECTION_CLOSED));
+ SpdySerializedFrame pushed_body(
+ spdy_util_.ConstructSpdyDataFrame(2, kPostBody, kPostBodyLength, true));
+ AddRead(pushed_body);
+
+ SpdySerializedFrame rst(
+ spdy_util_.ConstructSpdyRstStream(2, RST_STREAM_PROTOCOL_ERROR));
+ AddWrite(rst);
+
+ SpdySerializedFrame body(
+ spdy_util_.ConstructSpdyDataFrame(1, kPostBody, kPostBodyLength, true));
+ AddRead(body);
+
+ AddReadEOF();
+
+ SequencedSocketData data(GetReads(), GetNumReads(), GetWrites(),
+ GetNumWrites());
+ MockConnect connect_data(SYNCHRONOUS, OK);
+ data.set_connect_data(connect_data);
+ session_deps_.socket_factory->AddSocketDataProvider(&data);
+
+ AddSSLSocketData();
+
+ base::WeakPtr<SpdySession> session(CreateDefaultSpdySession());
+
+ base::WeakPtr<SpdyStream> stream = CreateStreamSynchronously(
+ SPDY_REQUEST_RESPONSE_STREAM, session, url_, LOWEST, NetLogWithSource());
+ ASSERT_TRUE(stream);
+
+ StreamDelegateDoNothing delegate(stream);
+ stream->SetDelegate(&delegate);
+
+ EXPECT_TRUE(stream->GetUrlFromHeaders().is_empty());
+
+ SpdyHeaderBlock headers(spdy_util_.ConstructGetHeaderBlock(kDefaultUrl));
+ EXPECT_THAT(
+ stream->SendRequestHeaders(std::move(headers), NO_MORE_DATA_TO_SEND),
+ IsError(ERR_IO_PENDING));
+ EXPECT_EQ(kDefaultUrl, stream->GetUrlFromHeaders().spec());
+
+ EXPECT_THAT(delegate.WaitForClose(), IsOk());
+ EXPECT_EQ("200", delegate.GetResponseHeaderValue(spdy_util_.GetStatusKey()));
+ EXPECT_EQ(std::string(kPostBody, kPostBodyLength),
+ delegate.TakeReceivedData());
+
+ // Finish async network reads and writes.
+ base::RunLoop().RunUntilIdle();
+
+ EXPECT_TRUE(data.AllWriteDataConsumed());
+ EXPECT_TRUE(data.AllReadDataConsumed());
}
-// Receiving a duplicate header in a HEADERS frame should result in a
-// protocol error.
-TEST_F(SpdyStreamTest, DuplicateHeaders) {
- GURL url(kStreamUrl);
+TEST_F(SpdyStreamTest, TrailersMustNotFollowTrailers) {
+ SpdySerializedFrame req(
+ spdy_util_.ConstructSpdyGet(nullptr, 0, 1, LOWEST, true));
+ AddWrite(req);
+
+ SpdySerializedFrame reply(spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
+ AddRead(reply);
+
+ SpdySerializedFrame body(
+ spdy_util_.ConstructSpdyDataFrame(1, kPostBody, kPostBodyLength, false));
+ AddRead(body);
+
+ SpdyHeaderBlock trailers_block;
+ trailers_block["foo"] = "bar";
+ SpdySerializedFrame first_trailers(spdy_util_.ConstructSpdyResponseHeaders(
+ 1, std::move(trailers_block), false));
+ AddRead(first_trailers);
+
+ // Trailers following trailers: procotol error.
+ SpdySerializedFrame second_trailers(spdy_util_.ConstructSpdyResponseHeaders(
+ 1, std::move(trailers_block), true));
+ AddRead(second_trailers);
+
+ SpdySerializedFrame rst(
+ spdy_util_.ConstructSpdyRstStream(1, RST_STREAM_PROTOCOL_ERROR));
+ AddWrite(rst);
+
+ AddReadEOF();
+
+ SequencedSocketData data(GetReads(), GetNumReads(), GetWrites(),
+ GetNumWrites());
+ MockConnect connect_data(SYNCHRONOUS, OK);
+ data.set_connect_data(connect_data);
+ session_deps_.socket_factory->AddSocketDataProvider(&data);
+
+ AddSSLSocketData();
- SpdySerializedFrame syn(
+ base::WeakPtr<SpdySession> session(CreateDefaultSpdySession());
+
+ base::WeakPtr<SpdyStream> stream = CreateStreamSynchronously(
+ SPDY_REQUEST_RESPONSE_STREAM, session, url_, LOWEST, NetLogWithSource());
+ ASSERT_TRUE(stream);
+
+ StreamDelegateDoNothing delegate(stream);
+ stream->SetDelegate(&delegate);
+
+ EXPECT_TRUE(stream->GetUrlFromHeaders().is_empty());
+
+ SpdyHeaderBlock headers(spdy_util_.ConstructGetHeaderBlock(kDefaultUrl));
+ EXPECT_EQ(ERR_IO_PENDING, stream->SendRequestHeaders(std::move(headers),
+ NO_MORE_DATA_TO_SEND));
+ EXPECT_EQ(kDefaultUrl, stream->GetUrlFromHeaders().spec());
+
+ EXPECT_THAT(delegate.WaitForClose(), IsError(ERR_SPDY_PROTOCOL_ERROR));
+
+ // Finish async network reads and writes.
+ base::RunLoop().RunUntilIdle();
+
+ EXPECT_TRUE(data.AllWriteDataConsumed());
+ EXPECT_TRUE(data.AllReadDataConsumed());
+}
+
+TEST_F(SpdyStreamTest, DataMustNotFollowTrailers) {
+ SpdySerializedFrame req(
spdy_util_.ConstructSpdyGet(nullptr, 0, 1, LOWEST, true));
- AddWrite(syn);
+ AddWrite(req);
- SpdySerializedFrame reply(spdy_util_.ConstructSpdyGetReply(NULL, 0, 1));
+ SpdySerializedFrame reply(spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
AddRead(reply);
- SpdySerializedFrame push(
- spdy_util_.ConstructSpdyPush(NULL, 0, 2, 1, kStreamUrl));
- AddRead(push);
+ SpdySerializedFrame body(
+ spdy_util_.ConstructSpdyDataFrame(1, kPostBody, kPostBodyLength, false));
+ AddRead(body);
- AddReadPause();
+ SpdyHeaderBlock trailers_block;
+ trailers_block["foo"] = "bar";
+ SpdySerializedFrame trailers(spdy_util_.ConstructSpdyResponseHeaders(
+ 1, std::move(trailers_block), false));
+ AddRead(trailers);
- SpdyHeaderBlock late_headers;
- late_headers[spdy_util_.GetStatusKey()] = "500 Server Error";
- SpdySerializedFrame headers_frame(
- spdy_util_.ConstructSpdyReply(2, std::move(late_headers)));
- AddRead(headers_frame);
+ // DATA frame following trailers: protocol error.
+ AddRead(body);
- AddReadPause();
+ SpdySerializedFrame rst(
+ spdy_util_.ConstructSpdyRstStream(1, RST_STREAM_PROTOCOL_ERROR));
+ AddWrite(rst);
+
+ AddReadEOF();
+
+ SequencedSocketData data(GetReads(), GetNumReads(), GetWrites(),
+ GetNumWrites());
+ MockConnect connect_data(SYNCHRONOUS, OK);
+ data.set_connect_data(connect_data);
+ session_deps_.socket_factory->AddSocketDataProvider(&data);
+
+ AddSSLSocketData();
+
+ base::WeakPtr<SpdySession> session(CreateDefaultSpdySession());
+
+ base::WeakPtr<SpdyStream> stream = CreateStreamSynchronously(
+ SPDY_REQUEST_RESPONSE_STREAM, session, url_, LOWEST, NetLogWithSource());
+ ASSERT_TRUE(stream);
+
+ StreamDelegateDoNothing delegate(stream);
+ stream->SetDelegate(&delegate);
+
+ EXPECT_TRUE(stream->GetUrlFromHeaders().is_empty());
+
+ SpdyHeaderBlock headers(spdy_util_.ConstructGetHeaderBlock(kDefaultUrl));
+ EXPECT_EQ(ERR_IO_PENDING, stream->SendRequestHeaders(std::move(headers),
+ NO_MORE_DATA_TO_SEND));
+ EXPECT_EQ(kDefaultUrl, stream->GetUrlFromHeaders().spec());
+
+ EXPECT_THAT(delegate.WaitForClose(), IsError(ERR_SPDY_PROTOCOL_ERROR));
+
+ // Finish async network reads and writes.
+ base::RunLoop().RunUntilIdle();
+
+ EXPECT_TRUE(data.AllWriteDataConsumed());
+ EXPECT_TRUE(data.AllReadDataConsumed());
+}
+
+TEST_F(SpdyStreamTest, InformationalHeaders) {
+ SpdySerializedFrame req(
+ spdy_util_.ConstructSpdyGet(nullptr, 0, 1, LOWEST, true));
+ AddWrite(req);
+
+ SpdyHeaderBlock informational_headers;
+ informational_headers[":status"] = "100";
+ SpdySerializedFrame informational_response(
+ spdy_util_.ConstructSpdyResponseHeaders(
+ 1, std::move(informational_headers), false));
+ AddRead(informational_response);
+
+ SpdySerializedFrame reply(spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
+ AddRead(reply);
+
+ SpdySerializedFrame body(
+ spdy_util_.ConstructSpdyDataFrame(1, kPostBody, kPostBodyLength, true));
+ AddRead(body);
+
+ AddReadEOF();
+
+ SequencedSocketData data(GetReads(), GetNumReads(), GetWrites(),
+ GetNumWrites());
+ MockConnect connect_data(SYNCHRONOUS, OK);
+ data.set_connect_data(connect_data);
+ session_deps_.socket_factory->AddSocketDataProvider(&data);
+
+ AddSSLSocketData();
+
+ base::WeakPtr<SpdySession> session(CreateDefaultSpdySession());
+
+ base::WeakPtr<SpdyStream> stream = CreateStreamSynchronously(
+ SPDY_REQUEST_RESPONSE_STREAM, session, url_, LOWEST, NetLogWithSource());
+ ASSERT_TRUE(stream);
+
+ StreamDelegateDoNothing delegate(stream);
+ stream->SetDelegate(&delegate);
+
+ EXPECT_TRUE(stream->GetUrlFromHeaders().is_empty());
+
+ SpdyHeaderBlock headers(spdy_util_.ConstructGetHeaderBlock(kDefaultUrl));
+ EXPECT_EQ(ERR_IO_PENDING, stream->SendRequestHeaders(std::move(headers),
+ NO_MORE_DATA_TO_SEND));
+ EXPECT_EQ(kDefaultUrl, stream->GetUrlFromHeaders().spec());
+
+ EXPECT_THAT(delegate.WaitForClose(), IsOk());
+ EXPECT_EQ("200", delegate.GetResponseHeaderValue(spdy_util_.GetStatusKey()));
+ EXPECT_EQ(std::string(kPostBody, kPostBodyLength),
+ delegate.TakeReceivedData());
+
+ // Finish async network reads and writes.
+ base::RunLoop().RunUntilIdle();
+
+ EXPECT_TRUE(data.AllWriteDataConsumed());
+ EXPECT_TRUE(data.AllReadDataConsumed());
+}
+
+TEST_F(SpdyStreamTest, StatusMustStartWithNumber) {
+ SpdySerializedFrame req(
+ spdy_util_.ConstructSpdyGet(nullptr, 0, 1, LOWEST, true));
+ AddWrite(req);
+
+ SpdyHeaderBlock incorrect_headers;
+ incorrect_headers[":status"] = "nan";
+ SpdySerializedFrame reply(spdy_util_.ConstructSpdyResponseHeaders(
+ 1, std::move(incorrect_headers), false));
+ AddRead(reply);
SpdySerializedFrame rst(
- spdy_util_.ConstructSpdyRstStream(2, RST_STREAM_PROTOCOL_ERROR));
+ spdy_util_.ConstructSpdyRstStream(1, RST_STREAM_PROTOCOL_ERROR));
AddWrite(rst);
AddReadEOF();
@@ -759,7 +1114,7 @@ TEST_F(SpdyStreamTest, DuplicateHeaders) {
base::WeakPtr<SpdySession> session(CreateDefaultSpdySession());
base::WeakPtr<SpdyStream> stream = CreateStreamSynchronously(
- SPDY_REQUEST_RESPONSE_STREAM, session, url, LOWEST, NetLogWithSource());
+ SPDY_REQUEST_RESPONSE_STREAM, session, url_, LOWEST, NetLogWithSource());
ASSERT_TRUE(stream);
StreamDelegateDoNothing delegate(stream);
@@ -767,36 +1122,80 @@ TEST_F(SpdyStreamTest, DuplicateHeaders) {
EXPECT_TRUE(stream->GetUrlFromHeaders().is_empty());
- SpdyHeaderBlock headers(spdy_util_.ConstructGetHeaderBlock(kStreamUrl));
+ SpdyHeaderBlock headers(spdy_util_.ConstructGetHeaderBlock(kDefaultUrl));
EXPECT_EQ(ERR_IO_PENDING, stream->SendRequestHeaders(std::move(headers),
NO_MORE_DATA_TO_SEND));
- EXPECT_EQ(kStreamUrl, stream->GetUrlFromHeaders().spec());
+ EXPECT_EQ(kDefaultUrl, stream->GetUrlFromHeaders().spec());
- data.RunUntilPaused();
+ EXPECT_THAT(delegate.WaitForClose(), IsError(ERR_SPDY_PROTOCOL_ERROR));
- base::WeakPtr<SpdyStream> push_stream;
- EXPECT_THAT(session->GetPushStream(url, &push_stream, NetLogWithSource()),
- IsOk());
- EXPECT_TRUE(push_stream);
+ // Finish async network reads and writes.
+ base::RunLoop().RunUntilIdle();
- data.Resume();
- data.RunUntilPaused();
+ EXPECT_TRUE(data.AllWriteDataConsumed());
+ EXPECT_TRUE(data.AllReadDataConsumed());
+}
- EXPECT_THAT(session->GetPushStream(url, &push_stream, NetLogWithSource()),
- IsOk());
- EXPECT_FALSE(push_stream);
+TEST_F(SpdyStreamTest, StatusCanHaveExtraText) {
+ SpdySerializedFrame req(
+ spdy_util_.ConstructSpdyGet(nullptr, 0, 1, LOWEST, true));
+ AddWrite(req);
- data.Resume();
+ SpdyHeaderBlock headers_with_status_text;
+ headers_with_status_text[":status"] =
+ "200 Some random extra text describing status";
+ SpdySerializedFrame reply(spdy_util_.ConstructSpdyResponseHeaders(
+ 1, std::move(headers_with_status_text), false));
+ AddRead(reply);
- EXPECT_THAT(delegate.WaitForClose(), IsError(ERR_CONNECTION_CLOSED));
+ SpdySerializedFrame body(
+ spdy_util_.ConstructSpdyDataFrame(1, kPostBody, kPostBodyLength, true));
+ AddRead(body);
+
+ AddReadEOF();
+
+ SequencedSocketData data(GetReads(), GetNumReads(), GetWrites(),
+ GetNumWrites());
+ MockConnect connect_data(SYNCHRONOUS, OK);
+ data.set_connect_data(connect_data);
+ session_deps_.socket_factory->AddSocketDataProvider(&data);
+
+ AddSSLSocketData();
+
+ base::WeakPtr<SpdySession> session(CreateDefaultSpdySession());
+
+ base::WeakPtr<SpdyStream> stream = CreateStreamSynchronously(
+ SPDY_REQUEST_RESPONSE_STREAM, session, url_, LOWEST, NetLogWithSource());
+ ASSERT_TRUE(stream);
+
+ StreamDelegateDoNothing delegate(stream);
+ stream->SetDelegate(&delegate);
+
+ EXPECT_TRUE(stream->GetUrlFromHeaders().is_empty());
+
+ SpdyHeaderBlock headers(spdy_util_.ConstructGetHeaderBlock(kDefaultUrl));
+ EXPECT_EQ(ERR_IO_PENDING, stream->SendRequestHeaders(std::move(headers),
+ NO_MORE_DATA_TO_SEND));
+ EXPECT_EQ(kDefaultUrl, stream->GetUrlFromHeaders().spec());
+
+ EXPECT_THAT(delegate.WaitForClose(), IsOk());
+ EXPECT_EQ("200 Some random extra text describing status",
+ delegate.GetResponseHeaderValue(spdy_util_.GetStatusKey()));
+ EXPECT_EQ(std::string(kPostBody, kPostBodyLength),
+ delegate.TakeReceivedData());
+
+ // Finish async network reads and writes.
+ base::RunLoop().RunUntilIdle();
+
+ EXPECT_TRUE(data.AllWriteDataConsumed());
+ EXPECT_TRUE(data.AllReadDataConsumed());
}
-// Call IncreaseSendWindowSize on a stream with a large enough delta
-// to overflow an int32_t. The SpdyStream should handle that case
-// gracefully.
+// Call IncreaseSendWindowSize on a stream with a large enough delta to overflow
+// an int32_t. The SpdyStream should handle that case gracefully.
TEST_F(SpdyStreamTest, IncreaseSendWindowSizeOverflow) {
SpdySerializedFrame req(spdy_util_.ConstructSpdyPost(
- kStreamUrl, 1, kPostBodyLength, LOWEST, NULL, 0));
+ kDefaultUrl, 1, kPostBodyLength, LOWEST, nullptr, 0));
AddWrite(req);
AddReadPause();
@@ -820,20 +1219,18 @@ TEST_F(SpdyStreamTest, IncreaseSendWindowSizeOverflow) {
AddSSLSocketData();
base::WeakPtr<SpdySession> session(CreateDefaultSpdySession());
- GURL url(kStreamUrl);
- base::WeakPtr<SpdyStream> stream =
- CreateStreamSynchronously(
- SPDY_BIDIRECTIONAL_STREAM, session, url, LOWEST, log.bound());
+ base::WeakPtr<SpdyStream> stream = CreateStreamSynchronously(
+ SPDY_BIDIRECTIONAL_STREAM, session, url_, LOWEST, log.bound());
ASSERT_TRUE(stream);
StreamDelegateSendImmediate delegate(stream, kPostBodyStringPiece);
stream->SetDelegate(&delegate);
SpdyHeaderBlock headers(
- spdy_util_.ConstructPostHeaderBlock(kStreamUrl, kPostBodyLength));
- EXPECT_EQ(ERR_IO_PENDING,
- stream->SendRequestHeaders(std::move(headers), MORE_DATA_TO_SEND));
- EXPECT_EQ(kStreamUrl, stream->GetUrlFromHeaders().spec());
+ spdy_util_.ConstructPostHeaderBlock(kDefaultUrl, kPostBodyLength));
+ EXPECT_THAT(stream->SendRequestHeaders(std::move(headers), MORE_DATA_TO_SEND),
+ IsError(ERR_IO_PENDING));
+ EXPECT_EQ(kDefaultUrl, stream->GetUrlFromHeaders().spec());
data.RunUntilPaused();
@@ -842,7 +1239,7 @@ TEST_F(SpdyStreamTest, IncreaseSendWindowSizeOverflow) {
int32_t delta_window_size =
std::numeric_limits<int32_t>::max() - old_send_window_size + 1;
stream->IncreaseSendWindowSize(delta_window_size);
- EXPECT_EQ(NULL, stream.get());
+ EXPECT_FALSE(stream);
data.Resume();
base::RunLoop().RunUntilIdle();
@@ -885,17 +1282,15 @@ void AdjustStreamSendWindowSize(const base::WeakPtr<SpdyStream>& stream,
// and unstall.
void SpdyStreamTest::RunResumeAfterUnstallRequestResponseTest(
const UnstallFunction& unstall_function) {
- GURL url(kStreamUrl);
-
SpdySerializedFrame req(spdy_util_.ConstructSpdyPost(
- kStreamUrl, 1, kPostBodyLength, LOWEST, NULL, 0));
+ kDefaultUrl, 1, kPostBodyLength, LOWEST, nullptr, 0));
AddWrite(req);
SpdySerializedFrame body(
spdy_util_.ConstructSpdyDataFrame(1, kPostBody, kPostBodyLength, true));
AddWrite(body);
- SpdySerializedFrame resp(spdy_util_.ConstructSpdyGetReply(NULL, 0, 1));
+ SpdySerializedFrame resp(spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
AddRead(resp);
AddReadEOF();
@@ -911,7 +1306,7 @@ void SpdyStreamTest::RunResumeAfterUnstallRequestResponseTest(
base::WeakPtr<SpdySession> session(CreateDefaultSpdySession());
base::WeakPtr<SpdyStream> stream = CreateStreamSynchronously(
- SPDY_REQUEST_RESPONSE_STREAM, session, url, LOWEST, NetLogWithSource());
+ SPDY_REQUEST_RESPONSE_STREAM, session, url_, LOWEST, NetLogWithSource());
ASSERT_TRUE(stream);
StreamDelegateWithBody delegate(stream, kPostBodyStringPiece);
@@ -921,10 +1316,10 @@ void SpdyStreamTest::RunResumeAfterUnstallRequestResponseTest(
EXPECT_FALSE(stream->send_stalled_by_flow_control());
SpdyHeaderBlock headers(
- spdy_util_.ConstructPostHeaderBlock(kStreamUrl, kPostBodyLength));
- EXPECT_EQ(ERR_IO_PENDING,
- stream->SendRequestHeaders(std::move(headers), MORE_DATA_TO_SEND));
- EXPECT_EQ(kStreamUrl, stream->GetUrlFromHeaders().spec());
+ spdy_util_.ConstructPostHeaderBlock(kDefaultUrl, kPostBodyLength));
+ EXPECT_THAT(stream->SendRequestHeaders(std::move(headers), MORE_DATA_TO_SEND),
+ IsError(ERR_IO_PENDING));
+ EXPECT_EQ(kDefaultUrl, stream->GetUrlFromHeaders().spec());
StallStream(stream);
@@ -954,20 +1349,17 @@ TEST_F(SpdyStreamTest, ResumeAfterSendWindowSizeAdjustRequestResponse) {
base::Bind(&AdjustStreamSendWindowSize));
}
-// Given an unstall function, runs a test to make sure that a
-// bidirectional (i.e., non-HTTP-like) stream resumes after a stall
-// and unstall.
+// Given an unstall function, runs a test to make sure that a bidirectional
+// (i.e., non-HTTP-like) stream resumes after a stall and unstall.
void SpdyStreamTest::RunResumeAfterUnstallBidirectionalTest(
const UnstallFunction& unstall_function) {
- GURL url(kStreamUrl);
-
SpdySerializedFrame req(spdy_util_.ConstructSpdyPost(
- kStreamUrl, 1, kPostBodyLength, LOWEST, NULL, 0));
+ kDefaultUrl, 1, kPostBodyLength, LOWEST, nullptr, 0));
AddWrite(req);
AddReadPause();
- SpdySerializedFrame resp(spdy_util_.ConstructSpdyGetReply(NULL, 0, 1));
+ SpdySerializedFrame resp(spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
AddRead(resp);
SpdySerializedFrame msg(
@@ -991,7 +1383,7 @@ void SpdyStreamTest::RunResumeAfterUnstallBidirectionalTest(
base::WeakPtr<SpdySession> session(CreateDefaultSpdySession());
base::WeakPtr<SpdyStream> stream = CreateStreamSynchronously(
- SPDY_BIDIRECTIONAL_STREAM, session, url, LOWEST, NetLogWithSource());
+ SPDY_BIDIRECTIONAL_STREAM, session, url_, LOWEST, NetLogWithSource());
ASSERT_TRUE(stream);
StreamDelegateSendImmediate delegate(stream, kPostBodyStringPiece);
@@ -1000,10 +1392,10 @@ void SpdyStreamTest::RunResumeAfterUnstallBidirectionalTest(
EXPECT_TRUE(stream->GetUrlFromHeaders().is_empty());
SpdyHeaderBlock headers(
- spdy_util_.ConstructPostHeaderBlock(kStreamUrl, kPostBodyLength));
- EXPECT_EQ(ERR_IO_PENDING,
- stream->SendRequestHeaders(std::move(headers), MORE_DATA_TO_SEND));
- EXPECT_EQ(kStreamUrl, stream->GetUrlFromHeaders().spec());
+ spdy_util_.ConstructPostHeaderBlock(kDefaultUrl, kPostBodyLength));
+ EXPECT_THAT(stream->SendRequestHeaders(std::move(headers), MORE_DATA_TO_SEND),
+ IsError(ERR_IO_PENDING));
+ EXPECT_EQ(kDefaultUrl, stream->GetUrlFromHeaders().spec());
data.RunUntilPaused();
@@ -1041,15 +1433,13 @@ TEST_F(SpdyStreamTest, ResumeAfterSendWindowSizeAdjustBidirectional) {
// Test calculation of amount of bytes received from network.
TEST_F(SpdyStreamTest, ReceivedBytes) {
- GURL url(kStreamUrl);
-
- SpdySerializedFrame syn(
+ SpdySerializedFrame req(
spdy_util_.ConstructSpdyGet(nullptr, 0, 1, LOWEST, true));
- AddWrite(syn);
+ AddWrite(req);
AddReadPause();
- SpdySerializedFrame reply(spdy_util_.ConstructSpdyGetReply(NULL, 0, 1));
+ SpdySerializedFrame reply(spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
AddRead(reply);
AddReadPause();
@@ -1073,7 +1463,7 @@ TEST_F(SpdyStreamTest, ReceivedBytes) {
base::WeakPtr<SpdySession> session(CreateDefaultSpdySession());
base::WeakPtr<SpdyStream> stream = CreateStreamSynchronously(
- SPDY_REQUEST_RESPONSE_STREAM, session, url, LOWEST, NetLogWithSource());
+ SPDY_REQUEST_RESPONSE_STREAM, session, url_, LOWEST, NetLogWithSource());
ASSERT_TRUE(stream);
StreamDelegateDoNothing delegate(stream);
@@ -1081,19 +1471,20 @@ TEST_F(SpdyStreamTest, ReceivedBytes) {
EXPECT_TRUE(stream->GetUrlFromHeaders().is_empty());
- SpdyHeaderBlock headers(spdy_util_.ConstructGetHeaderBlock(kStreamUrl));
- EXPECT_EQ(ERR_IO_PENDING, stream->SendRequestHeaders(std::move(headers),
- NO_MORE_DATA_TO_SEND));
- EXPECT_EQ(kStreamUrl, stream->GetUrlFromHeaders().spec());
+ SpdyHeaderBlock headers(spdy_util_.ConstructGetHeaderBlock(kDefaultUrl));
+ EXPECT_THAT(
+ stream->SendRequestHeaders(std::move(headers), NO_MORE_DATA_TO_SEND),
+ IsError(ERR_IO_PENDING));
+ EXPECT_EQ(kDefaultUrl, stream->GetUrlFromHeaders().spec());
int64_t reply_frame_len = reply.size();
- int64_t data_header_len = SpdyConstants::GetDataFrameMinimumSize(HTTP2);
+ int64_t data_header_len = kDataFrameMinimumSize;
int64_t data_frame_len = data_header_len + kPostBodyLength;
int64_t response_len = reply_frame_len + data_frame_len;
EXPECT_EQ(0, stream->raw_received_bytes());
- // SYN
+ // REQUEST
data.RunUntilPaused();
EXPECT_EQ(0, stream->raw_received_bytes());
diff --git a/chromium/net/spdy/spdy_test_util_common.cc b/chromium/net/spdy/spdy_test_util_common.cc
index 37d24532f5f..0c796fbbad3 100644
--- a/chromium/net/spdy/spdy_test_util_common.cc
+++ b/chromium/net/spdy/spdy_test_util_common.cc
@@ -17,8 +17,8 @@
#include "net/base/host_port_pair.h"
#include "net/cert/ct_policy_enforcer.h"
#include "net/cert/ct_policy_status.h"
+#include "net/cert/do_nothing_ct_verifier.h"
#include "net/cert/mock_cert_verifier.h"
-#include "net/cert/multi_log_ct_verifier.h"
#include "net/cert/signed_certificate_timestamp_and_status.h"
#include "net/http/http_cache.h"
#include "net/http/http_network_session.h"
@@ -211,7 +211,7 @@ class PriorityGetter : public BufferedSpdyFramerVisitorInterface {
void OnStreamEnd(SpdyStreamId stream_id) override {}
void OnStreamPadding(SpdyStreamId stream_id, size_t len) override {}
void OnSettings() override {}
- void OnSetting(SpdySettingsIds id, uint8_t flags, uint32_t value) override {}
+ void OnSetting(SpdySettingsIds id, uint32_t value) override {}
void OnPing(SpdyPingId unique_id, bool is_ack) override {}
void OnRstStream(SpdyStreamId stream_id,
SpdyRstStreamStatus status) override {}
@@ -330,7 +330,7 @@ SpdySessionDependencies::SpdySessionDependencies(
cert_verifier(new MockCertVerifier),
channel_id_service(nullptr),
transport_security_state(new TransportSecurityState),
- cert_transparency_verifier(new MultiLogCTVerifier),
+ cert_transparency_verifier(new DoNothingCTVerifier),
ct_policy_enforcer(new CTPolicyEnforcer),
proxy_service(std::move(proxy_service)),
ssl_config_service(new SSLConfigServiceDefaults),
@@ -343,7 +343,6 @@ SpdySessionDependencies::SpdySessionDependencies(
enable_user_alternate_protocol_ports(false),
enable_quic(false),
session_max_recv_window_size(kDefaultInitialWindowSize),
- stream_max_recv_window_size(kDefaultInitialWindowSize),
time_func(&base::TimeTicks::Now),
enable_http2_alternative_service_with_different_host(false),
net_log(nullptr),
@@ -355,6 +354,7 @@ SpdySessionDependencies::SpdySessionDependencies(
// lookups allows the test to shutdown cleanly. Until we have
// cancellable TCPConnectJobs, use synchronous lookups.
host_resolver->set_synchronous_mode(true);
+ http2_settings[SETTINGS_INITIAL_WINDOW_SIZE] = kDefaultInitialWindowSize;
}
SpdySessionDependencies::~SpdySessionDependencies() {}
@@ -394,8 +394,7 @@ HttpNetworkSession::Params SpdySessionDependencies::CreateSessionParams(
params.enable_quic = session_deps->enable_quic;
params.spdy_session_max_recv_window_size =
session_deps->session_max_recv_window_size;
- params.spdy_stream_max_recv_window_size =
- session_deps->stream_max_recv_window_size;
+ params.http2_settings = session_deps->http2_settings;
params.time_func = session_deps->time_func;
params.proxy_delegate = session_deps->proxy_delegate.get();
params.enable_http2_alternative_service_with_different_host =
@@ -403,12 +402,13 @@ HttpNetworkSession::Params SpdySessionDependencies::CreateSessionParams(
params.net_log = session_deps->net_log;
params.http_09_on_non_default_ports_enabled =
session_deps->http_09_on_non_default_ports_enabled;
+ params.restrict_to_one_preconnect_for_proxies = true;
return params;
}
class AllowAnyCertCTPolicyEnforcer : public CTPolicyEnforcer {
public:
- AllowAnyCertCTPolicyEnforcer(){};
+ AllowAnyCertCTPolicyEnforcer() {}
~AllowAnyCertCTPolicyEnforcer() override = default;
ct::CertPolicyCompliance DoesConformToCertPolicy(
@@ -427,22 +427,6 @@ class AllowAnyCertCTPolicyEnforcer : public CTPolicyEnforcer {
}
};
-class IgnoresCTVerifier : public net::CTVerifier {
- public:
- IgnoresCTVerifier() = default;
- ~IgnoresCTVerifier() override = default;
-
- int Verify(net::X509Certificate* cert,
- const std::string& stapled_ocsp_response,
- const std::string& sct_list_from_tls_extension,
- SignedCertificateTimestampAndStatusList* output_scts,
- const net::NetLogWithSource& net_log) override {
- return net::OK;
- }
-
- void SetObserver(Observer* observer) override {}
-};
-
SpdyURLRequestContext::SpdyURLRequestContext() : storage_(this) {
storage_.set_host_resolver(
std::unique_ptr<HostResolver>(new MockHostResolver));
@@ -453,7 +437,7 @@ SpdyURLRequestContext::SpdyURLRequestContext() : storage_(this) {
storage_.set_ct_policy_enforcer(
base::WrapUnique(new AllowAnyCertCTPolicyEnforcer()));
storage_.set_cert_transparency_verifier(
- base::WrapUnique(new IgnoresCTVerifier()));
+ base::WrapUnique(new DoNothingCTVerifier()));
storage_.set_ssl_config_service(new SSLConfigServiceDefaults);
storage_.set_http_auth_handler_factory(
HttpAuthHandlerFactory::CreateDefault(host_resolver()));
@@ -614,7 +598,7 @@ class FakeSpdySessionClientSocket : public MockClientSocket {
return false;
}
- bool WasNpnNegotiated() const override {
+ bool WasAlpnNegotiated() const override {
ADD_FAILURE();
return false;
}
@@ -678,18 +662,10 @@ void SpdySessionPoolPeer::SetEnableSendingInitialData(bool enabled) {
pool_->enable_sending_initial_data_ = enabled;
}
-void SpdySessionPoolPeer::SetSessionMaxRecvWindowSize(size_t window) {
- pool_->session_max_recv_window_size_ = window;
-}
-
-void SpdySessionPoolPeer::SetStreamInitialRecvWindowSize(size_t window) {
- pool_->stream_max_recv_window_size_ = window;
-}
-
SpdyTestUtil::SpdyTestUtil()
- : headerless_spdy_framer_(HTTP2),
- request_spdy_framer_(HTTP2),
- response_spdy_framer_(HTTP2),
+ : headerless_spdy_framer_(SpdyFramer::ENABLE_COMPRESSION),
+ request_spdy_framer_(SpdyFramer::ENABLE_COMPRESSION),
+ response_spdy_framer_(SpdyFramer::ENABLE_COMPRESSION),
default_url_(GURL(kDefaultUrl)) {}
SpdyTestUtil::~SpdyTestUtil() {}
@@ -754,14 +730,9 @@ std::string SpdyTestUtil::ConstructSpdyReplyString(
SpdySerializedFrame SpdyTestUtil::ConstructSpdySettings(
const SettingsMap& settings) {
SpdySettingsIR settings_ir;
- for (SettingsMap::const_iterator it = settings.begin();
- it != settings.end();
+ for (SettingsMap::const_iterator it = settings.begin(); it != settings.end();
++it) {
- settings_ir.AddSetting(
- it->first,
- (it->second.first & SETTINGS_FLAG_PLEASE_PERSIST) != 0,
- (it->second.first & SETTINGS_FLAG_PERSISTED) != 0,
- it->second.second);
+ settings_ir.AddSetting(it->first, it->second);
}
return SpdySerializedFrame(
headerless_spdy_framer_.SerializeFrame(settings_ir));
@@ -787,7 +758,7 @@ SpdySerializedFrame SpdyTestUtil::ConstructSpdyGoAway() {
SpdySerializedFrame SpdyTestUtil::ConstructSpdyGoAway(
SpdyStreamId last_good_stream_id) {
- SpdyGoAwayIR go_ir(last_good_stream_id, GOAWAY_OK, "go away");
+ SpdyGoAwayIR go_ir(last_good_stream_id, GOAWAY_NO_ERROR, "go away");
return SpdySerializedFrame(headerless_spdy_framer_.SerializeFrame(go_ir));
}
@@ -816,6 +787,19 @@ SpdySerializedFrame SpdyTestUtil::ConstructSpdyRstStream(
headerless_spdy_framer_.SerializeRstStream(rst_ir));
}
+// TODO(jgraettinger): Eliminate uses of this method in tests (prefer
+// SpdyPriorityIR).
+SpdySerializedFrame SpdyTestUtil::ConstructSpdyPriority(
+ SpdyStreamId stream_id,
+ SpdyStreamId parent_stream_id,
+ RequestPriority request_priority,
+ bool exclusive) {
+ int weight = Spdy3PriorityToHttp2Weight(
+ ConvertRequestPriorityToSpdyPriority(request_priority));
+ SpdyPriorityIR ir(stream_id, parent_stream_id, weight, exclusive);
+ return SpdySerializedFrame(headerless_spdy_framer_.SerializePriority(ir));
+}
+
SpdySerializedFrame SpdyTestUtil::ConstructSpdyGet(
const char* const url,
SpdyStreamId stream_id,
@@ -1005,12 +989,12 @@ SpdySerializedFrame SpdyTestUtil::ConstructSpdyGetReplyRedirect(int stream_id) {
static const char* const kExtraHeaders[] = {
"location", "http://www.foo.com/index.php",
};
- return ConstructSpdyReplyError("301 Moved Permanently", kExtraHeaders,
+ return ConstructSpdyReplyError("301", kExtraHeaders,
arraysize(kExtraHeaders) / 2, stream_id);
}
SpdySerializedFrame SpdyTestUtil::ConstructSpdyReplyError(int stream_id) {
- return ConstructSpdyReplyError("500 Internal Server Error", NULL, 0, 1);
+ return ConstructSpdyReplyError("500", NULL, 0, 1);
}
SpdySerializedFrame SpdyTestUtil::ConstructSpdyGetReply(
@@ -1056,21 +1040,19 @@ SpdySerializedFrame SpdyTestUtil::ConstructSpdyPostReply(
SpdySerializedFrame SpdyTestUtil::ConstructSpdyDataFrame(int stream_id,
bool fin) {
- SpdyFramer framer(HTTP2);
SpdyDataIR data_ir(stream_id,
base::StringPiece(kUploadData, kUploadDataSize));
data_ir.set_fin(fin);
- return SpdySerializedFrame(framer.SerializeData(data_ir));
+ return SpdySerializedFrame(headerless_spdy_framer_.SerializeData(data_ir));
}
SpdySerializedFrame SpdyTestUtil::ConstructSpdyDataFrame(int stream_id,
const char* data,
uint32_t len,
bool fin) {
- SpdyFramer framer(HTTP2);
SpdyDataIR data_ir(stream_id, base::StringPiece(data, len));
data_ir.set_fin(fin);
- return SpdySerializedFrame(framer.SerializeData(data_ir));
+ return SpdySerializedFrame(headerless_spdy_framer_.SerializeData(data_ir));
}
SpdySerializedFrame SpdyTestUtil::ConstructSpdyDataFrame(int stream_id,
@@ -1078,11 +1060,10 @@ SpdySerializedFrame SpdyTestUtil::ConstructSpdyDataFrame(int stream_id,
uint32_t len,
bool fin,
int padding_length) {
- SpdyFramer framer(HTTP2);
SpdyDataIR data_ir(stream_id, base::StringPiece(data, len));
data_ir.set_fin(fin);
data_ir.set_padding_len(padding_length);
- return SpdySerializedFrame(framer.SerializeData(data_ir));
+ return SpdySerializedFrame(headerless_spdy_framer_.SerializeData(data_ir));
}
SpdySerializedFrame SpdyTestUtil::ConstructWrappedSpdyFrame(
diff --git a/chromium/net/spdy/spdy_test_util_common.h b/chromium/net/spdy/spdy_test_util_common.h
index d5495dccad7..6531d1eaf7b 100644
--- a/chromium/net/spdy/spdy_test_util_common.h
+++ b/chromium/net/spdy/spdy_test_util_common.h
@@ -8,6 +8,7 @@
#include <stddef.h>
#include <stdint.h>
+#include <map>
#include <memory>
#include <string>
#include <vector>
@@ -201,7 +202,7 @@ struct SpdySessionDependencies {
bool enable_user_alternate_protocol_ports;
bool enable_quic;
size_t session_max_recv_window_size;
- size_t stream_max_recv_window_size;
+ SettingsMap http2_settings;
SpdySession::TimeFunc time_func;
std::unique_ptr<ProxyDelegate> proxy_delegate;
bool enable_http2_alternative_service_with_different_host;
@@ -271,8 +272,6 @@ class SpdySessionPoolPeer {
void RemoveAliases(const SpdySessionKey& key);
void SetEnableSendingInitialData(bool enabled);
- void SetSessionMaxRecvWindowSize(size_t window);
- void SetStreamInitialRecvWindowSize(size_t window);
private:
SpdySessionPool* const pool_;
@@ -338,6 +337,13 @@ class SpdyTestUtil {
SpdySerializedFrame ConstructSpdyRstStream(SpdyStreamId stream_id,
SpdyRstStreamStatus status);
+ // Construct a PRIORITY frame. The weight is derived from |request_priority|.
+ // Returns the constructed frame. The caller takes ownership of the frame.
+ SpdySerializedFrame ConstructSpdyPriority(SpdyStreamId stream_id,
+ SpdyStreamId parent_stream_id,
+ RequestPriority request_priority,
+ bool exclusive);
+
// Constructs a standard SPDY GET HEADERS frame for |url| with header
// compression.
// |extra_headers| are the extra header-value pairs, which typically
diff --git a/chromium/net/spdy/spdy_test_utils.cc b/chromium/net/spdy/spdy_test_utils.cc
index e2c327eec22..16d39dbe13d 100644
--- a/chromium/net/spdy/spdy_test_utils.cc
+++ b/chromium/net/spdy/spdy_test_utils.cc
@@ -4,8 +4,10 @@
#include "net/spdy/spdy_test_utils.h"
+#include <algorithm>
#include <cstring>
#include <memory>
+#include <utility>
#include <vector>
#include "base/base64.h"
@@ -92,43 +94,15 @@ void CompareCharArraysWithHexError(const string& description,
<< HexDumpWithMarks(actual, actual_len, marks.get(), max_len);
}
-void SetFrameFlags(SpdySerializedFrame* frame,
- uint8_t flags,
- SpdyMajorVersion spdy_version) {
- switch (spdy_version) {
- case SPDY3:
- case HTTP2:
- frame->data()[4] = flags;
- break;
- default:
- LOG(FATAL) << "Unsupported SPDY version.";
- }
+void SetFrameFlags(SpdySerializedFrame* frame, uint8_t flags) {
+ frame->data()[4] = flags;
}
-void SetFrameLength(SpdySerializedFrame* frame,
- size_t length,
- SpdyMajorVersion spdy_version) {
- switch (spdy_version) {
- case SPDY3:
- CHECK_EQ(0u, length & ~kLengthMask);
- {
- int32_t wire_length = base::HostToNet32(length);
- // The length field in SPDY 3 is a 24-bit (3B) integer starting at
- // offset 5.
- memcpy(frame->data() + 5, reinterpret_cast<char*>(&wire_length) + 1, 3);
- }
- break;
- case HTTP2:
- CHECK_GT(1u<<14, length);
- {
- int32_t wire_length = base::HostToNet32(length);
- memcpy(frame->data(),
- reinterpret_cast<char*>(&wire_length) + 1,
- 3);
- }
- break;
- default:
- LOG(FATAL) << "Unsupported SPDY version.";
+void SetFrameLength(SpdySerializedFrame* frame, size_t length) {
+ CHECK_GT(1u << 14, length);
+ {
+ int32_t wire_length = base::HostToNet32(length);
+ memcpy(frame->data(), reinterpret_cast<char*>(&wire_length) + 1, 3);
}
}
diff --git a/chromium/net/spdy/spdy_test_utils.h b/chromium/net/spdy/spdy_test_utils.h
index 8e68a49c43f..eb27d66f4ee 100644
--- a/chromium/net/spdy/spdy_test_utils.h
+++ b/chromium/net/spdy/spdy_test_utils.h
@@ -42,13 +42,9 @@ void CompareCharArraysWithHexError(
const unsigned char* expected,
const int expected_len);
-void SetFrameFlags(SpdySerializedFrame* frame,
- uint8_t flags,
- SpdyMajorVersion spdy_version);
+void SetFrameFlags(SpdySerializedFrame* frame, uint8_t flags);
-void SetFrameLength(SpdySerializedFrame* frame,
- size_t length,
- SpdyMajorVersion spdy_version);
+void SetFrameLength(SpdySerializedFrame* frame, size_t length);
std::string a2b_hex(const char* hex_data);
diff --git a/chromium/net/spdy/spdy_write_queue.h b/chromium/net/spdy/spdy_write_queue.h
index 8ffef3b3a95..acf6b4c30dd 100644
--- a/chromium/net/spdy/spdy_write_queue.h
+++ b/chromium/net/spdy/spdy_write_queue.h
@@ -16,7 +16,6 @@
namespace net {
-class SpdyBuffer;
class SpdyBufferProducer;
class SpdyStream;
diff --git a/chromium/net/ssl/channel_id_service.cc b/chromium/net/ssl/channel_id_service.cc
index 53c3c636cd7..74ab3816958 100644
--- a/chromium/net/ssl/channel_id_service.cc
+++ b/chromium/net/ssl/channel_id_service.cc
@@ -201,9 +201,6 @@ class ChannelIDServiceJob {
bool create_if_missing_;
};
-// static
-const char ChannelIDService::kEPKIPassword[] = "";
-
ChannelIDService::Request::Request() : service_(NULL) {
}
diff --git a/chromium/net/ssl/channel_id_service.h b/chromium/net/ssl/channel_id_service.h
index 0134873d954..617a297e84e 100644
--- a/chromium/net/ssl/channel_id_service.h
+++ b/chromium/net/ssl/channel_id_service.h
@@ -31,7 +31,6 @@ class ECPrivateKey;
namespace net {
class ChannelIDServiceJob;
-class ChannelIDServiceWorker;
// A class for creating and fetching Channel IDs.
@@ -70,11 +69,6 @@ class NET_EXPORT ChannelIDService
ChannelIDServiceJob* job_;
};
- // Password used on EncryptedPrivateKeyInfo data stored in EC private_key
- // values. (This is not used to provide any security, but to workaround NSS
- // being unable to import unencrypted PrivateKeyInfo for EC keys.)
- static const char kEPKIPassword[];
-
// This object owns |channel_id_store|. |task_runner| will
// be used to post channel ID generation worker tasks. The tasks are
// safe for use with WorkerPool and SequencedWorkerPool::CONTINUE_ON_SHUTDOWN.
diff --git a/chromium/net/ssl/ssl_client_session_cache.cc b/chromium/net/ssl/ssl_client_session_cache.cc
index fc817fdba0b..4cb6c9ae025 100644
--- a/chromium/net/ssl/ssl_client_session_cache.cc
+++ b/chromium/net/ssl/ssl_client_session_cache.cc
@@ -7,9 +7,13 @@
#include <utility>
#include "base/memory/memory_coordinator_client_registry.h"
+#include "base/strings/stringprintf.h"
#include "base/time/clock.h"
#include "base/time/default_clock.h"
+#include "base/trace_event/process_memory_dump.h"
+#include "net/cert/x509_util_openssl.h"
#include "third_party/boringssl/src/include/openssl/ssl.h"
+#include "third_party/boringssl/src/include/openssl/x509.h"
namespace net {
@@ -33,7 +37,8 @@ size_t SSLClientSessionCache::size() const {
}
bssl::UniquePtr<SSL_SESSION> SSLClientSessionCache::Lookup(
- const std::string& cache_key) {
+ const std::string& cache_key,
+ int* count) {
base::AutoLock lock(lock_);
// Expire stale sessions.
@@ -43,26 +48,49 @@ bssl::UniquePtr<SSL_SESSION> SSLClientSessionCache::Lookup(
FlushExpiredSessions();
}
+ // Set count to 0 if there's no session in the cache.
+ if (count != nullptr)
+ *count = 0;
+
auto iter = cache_.Get(cache_key);
if (iter == cache_.end())
return nullptr;
- SSL_SESSION* session = iter->second.get();
+ SSL_SESSION* session = iter->second.session.get();
if (IsExpired(session, clock_->Now().ToTimeT())) {
cache_.Erase(iter);
return nullptr;
}
+ iter->second.lookups++;
+ if (count != nullptr) {
+ *count = iter->second.lookups;
+ }
+
SSL_SESSION_up_ref(session);
return bssl::UniquePtr<SSL_SESSION>(session);
}
+void SSLClientSessionCache::ResetLookupCount(const std::string& cache_key) {
+ base::AutoLock lock(lock_);
+
+ // It's possible that the cached session for this key was deleted after the
+ // Lookup. If that's the case, don't do anything.
+ auto iter = cache_.Get(cache_key);
+ if (iter == cache_.end())
+ return;
+
+ iter->second.lookups = 0;
+}
+
void SSLClientSessionCache::Insert(const std::string& cache_key,
SSL_SESSION* session) {
base::AutoLock lock(lock_);
SSL_SESSION_up_ref(session);
- cache_.Put(cache_key, bssl::UniquePtr<SSL_SESSION>(session));
+ Entry entry;
+ entry.session = bssl::UniquePtr<SSL_SESSION>(session);
+ cache_.Put(cache_key, std::move(entry));
}
void SSLClientSessionCache::Flush() {
@@ -82,11 +110,52 @@ bool SSLClientSessionCache::IsExpired(SSL_SESSION* session, time_t now) {
SSL_SESSION_get_time(session) + SSL_SESSION_get_timeout(session);
}
+void SSLClientSessionCache::DumpMemoryStats(
+ base::trace_event::ProcessMemoryDump* pmd) {
+ std::string absolute_name = "net/ssl_session_cache";
+ base::trace_event::MemoryAllocatorDump* cache_dump =
+ pmd->GetAllocatorDump(absolute_name);
+ // This method can be reached from different URLRequestContexts. Since this is
+ // a singleton, only log memory stats once.
+ // TODO(xunjieli): Change this once crbug.com/458365 is fixed.
+ if (cache_dump)
+ return;
+ cache_dump = pmd->CreateAllocatorDump(absolute_name);
+ base::AutoLock lock(lock_);
+ size_t total_serialized_cert_size = 0;
+ size_t total_cert_count = 0;
+ for (const auto& pair : cache_) {
+ const SSL_SESSION* session = pair.second.session.get();
+ size_t cert_count = sk_CRYPTO_BUFFER_num(session->certs);
+ total_cert_count += cert_count;
+ for (size_t i = 0; i < cert_count; ++i) {
+ const CRYPTO_BUFFER* cert = sk_CRYPTO_BUFFER_value(session->certs, i);
+ total_serialized_cert_size += CRYPTO_BUFFER_len(cert);
+ }
+ }
+ // This measures the lower bound of the serialized certificate. It doesn't
+ // measure the actual memory used, which is 4x this amount (see
+ // crbug.com/671420 for more details).
+ cache_dump->AddScalar("serialized_cert_size",
+ base::trace_event::MemoryAllocatorDump::kUnitsBytes,
+ total_serialized_cert_size);
+ cache_dump->AddScalar("cert_count",
+ base::trace_event::MemoryAllocatorDump::kUnitsObjects,
+ total_cert_count);
+ cache_dump->AddScalar(base::trace_event::MemoryAllocatorDump::kNameSize,
+ base::trace_event::MemoryAllocatorDump::kUnitsBytes,
+ total_serialized_cert_size);
+}
+
+SSLClientSessionCache::Entry::Entry() : lookups(0) {}
+SSLClientSessionCache::Entry::Entry(Entry&&) = default;
+SSLClientSessionCache::Entry::~Entry() = default;
+
void SSLClientSessionCache::FlushExpiredSessions() {
time_t now = clock_->Now().ToTimeT();
auto iter = cache_.begin();
while (iter != cache_.end()) {
- if (IsExpired(iter->second.get(), now)) {
+ if (IsExpired(iter->second.session.get(), now)) {
iter = cache_.Erase(iter);
} else {
++iter;
diff --git a/chromium/net/ssl/ssl_client_session_cache.h b/chromium/net/ssl/ssl_client_session_cache.h
index cd668a2614d..0cfefc31e75 100644
--- a/chromium/net/ssl/ssl_client_session_cache.h
+++ b/chromium/net/ssl/ssl_client_session_cache.h
@@ -2,8 +2,8 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#ifndef NET_SSL_SSL_CLIENT_SESSION_CACHE_H
-#define NET_SSL_SSL_CLIENT_SESSION_CACHE_H
+#ifndef NET_SSL_SSL_CLIENT_SESSION_CACHE_H_
+#define NET_SSL_SSL_CLIENT_SESSION_CACHE_H_
#include <stddef.h>
#include <time.h>
@@ -24,6 +24,9 @@
namespace base {
class Clock;
+namespace trace_event {
+class ProcessMemoryDump;
+}
}
namespace net {
@@ -43,8 +46,14 @@ class NET_EXPORT SSLClientSessionCache : public base::MemoryCoordinatorClient {
size_t size() const;
// Returns the session associated with |cache_key| and moves it to the front
- // of the MRU list. Returns nullptr if there is none.
- bssl::UniquePtr<SSL_SESSION> Lookup(const std::string& cache_key);
+ // of the MRU list. Returns nullptr if there is none. If |count| is non-null,
+ // |*count| will contain the number of times this session has been looked up
+ // (including this call).
+ bssl::UniquePtr<SSL_SESSION> Lookup(const std::string& cache_key, int* count);
+
+ // Resets the count returned by Lookup to 0 for the session associated with
+ // |cache_key|.
+ void ResetLookupCount(const std::string& cache_key);
// Inserts |session| into the cache at |cache_key|. If there is an existing
// one, it is released. Every |expiration_check_count| calls, the cache is
@@ -56,7 +65,20 @@ class NET_EXPORT SSLClientSessionCache : public base::MemoryCoordinatorClient {
void SetClockForTesting(std::unique_ptr<base::Clock> clock);
+ // Dumps memory allocation stats. |pmd| is the ProcessMemoryDump of the
+ // browser process.
+ void DumpMemoryStats(base::trace_event::ProcessMemoryDump* pmd);
+
private:
+ struct Entry {
+ Entry();
+ Entry(Entry&&);
+ ~Entry();
+
+ int lookups;
+ bssl::UniquePtr<SSL_SESSION> session;
+ };
+
// base::MemoryCoordinatorClient implementation:
void OnMemoryStateChange(base::MemoryState state) override;
@@ -72,7 +94,7 @@ class NET_EXPORT SSLClientSessionCache : public base::MemoryCoordinatorClient {
std::unique_ptr<base::Clock> clock_;
Config config_;
- base::HashingMRUCache<std::string, bssl::UniquePtr<SSL_SESSION>> cache_;
+ base::HashingMRUCache<std::string, Entry> cache_;
size_t lookups_since_flush_;
// TODO(davidben): After https://crbug.com/458365 is fixed, replace this with
@@ -87,4 +109,4 @@ class NET_EXPORT SSLClientSessionCache : public base::MemoryCoordinatorClient {
} // namespace net
-#endif // NET_SSL_SSL_CLIENT_SESSION_CACHE_H
+#endif // NET_SSL_SSL_CLIENT_SESSION_CACHE_H_
diff --git a/chromium/net/ssl/ssl_client_session_cache_unittest.cc b/chromium/net/ssl/ssl_client_session_cache_unittest.cc
index b3e53469aee..a30a84ef4a6 100644
--- a/chromium/net/ssl/ssl_client_session_cache_unittest.cc
+++ b/chromium/net/ssl/ssl_client_session_cache_unittest.cc
@@ -9,6 +9,9 @@
#include "base/strings/string_number_conversions.h"
#include "base/test/simple_test_clock.h"
#include "base/time/time.h"
+#include "base/trace_event/memory_allocator_dump.h"
+#include "base/trace_event/process_memory_dump.h"
+#include "base/trace_event/trace_event_argument.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "third_party/boringssl/src/include/openssl/ssl.h"
@@ -47,26 +50,26 @@ TEST(SSLClientSessionCacheTest, Basic) {
EXPECT_EQ(1u, session2->references);
EXPECT_EQ(1u, session3->references);
- EXPECT_EQ(nullptr, cache.Lookup("key1").get());
- EXPECT_EQ(nullptr, cache.Lookup("key2").get());
+ EXPECT_EQ(nullptr, cache.Lookup("key1", nullptr).get());
+ EXPECT_EQ(nullptr, cache.Lookup("key2", nullptr).get());
EXPECT_EQ(0u, cache.size());
cache.Insert("key1", session1.get());
- EXPECT_EQ(session1.get(), cache.Lookup("key1").get());
- EXPECT_EQ(nullptr, cache.Lookup("key2").get());
+ EXPECT_EQ(session1.get(), cache.Lookup("key1", nullptr).get());
+ EXPECT_EQ(nullptr, cache.Lookup("key2", nullptr).get());
EXPECT_EQ(1u, cache.size());
cache.Insert("key2", session2.get());
- EXPECT_EQ(session1.get(), cache.Lookup("key1").get());
- EXPECT_EQ(session2.get(), cache.Lookup("key2").get());
+ EXPECT_EQ(session1.get(), cache.Lookup("key1", nullptr).get());
+ EXPECT_EQ(session2.get(), cache.Lookup("key2", nullptr).get());
EXPECT_EQ(2u, cache.size());
EXPECT_EQ(2u, session1->references);
EXPECT_EQ(2u, session2->references);
cache.Insert("key1", session3.get());
- EXPECT_EQ(session3.get(), cache.Lookup("key1").get());
- EXPECT_EQ(session2.get(), cache.Lookup("key2").get());
+ EXPECT_EQ(session3.get(), cache.Lookup("key1", nullptr).get());
+ EXPECT_EQ(session2.get(), cache.Lookup("key2", nullptr).get());
EXPECT_EQ(2u, cache.size());
EXPECT_EQ(1u, session1->references);
@@ -74,9 +77,9 @@ TEST(SSLClientSessionCacheTest, Basic) {
EXPECT_EQ(2u, session3->references);
cache.Flush();
- EXPECT_EQ(nullptr, cache.Lookup("key1").get());
- EXPECT_EQ(nullptr, cache.Lookup("key2").get());
- EXPECT_EQ(nullptr, cache.Lookup("key3").get());
+ EXPECT_EQ(nullptr, cache.Lookup("key1", nullptr).get());
+ EXPECT_EQ(nullptr, cache.Lookup("key2", nullptr).get());
+ EXPECT_EQ(nullptr, cache.Lookup("key3", nullptr).get());
EXPECT_EQ(0u, cache.size());
EXPECT_EQ(1u, session1->references);
@@ -84,6 +87,45 @@ TEST(SSLClientSessionCacheTest, Basic) {
EXPECT_EQ(1u, session3->references);
}
+// Test that pairs of calls to Lookup/ResetLookupCount appropriately log to
+// UMA.
+TEST(SSLClientSessionCacheTest, LookupCountUMA) {
+ SSLClientSessionCache::Config config;
+ SSLClientSessionCache cache(config);
+
+ bssl::UniquePtr<SSL_SESSION> session1(SSL_SESSION_new());
+ bssl::UniquePtr<SSL_SESSION> session2(SSL_SESSION_new());
+ cache.Insert("key1", session1.get());
+ cache.Insert("key2", session2.get());
+
+ // Test that the count returned increments when multiple lookups of the same
+ // key/session occur before the count is reset.
+ int count;
+ EXPECT_EQ(session1.get(), cache.Lookup("key1", &count).get());
+ EXPECT_EQ(1, count);
+ EXPECT_EQ(session1.get(), cache.Lookup("key1", &count).get());
+ EXPECT_EQ(2, count);
+ cache.ResetLookupCount("key1");
+ EXPECT_EQ(session1.get(), cache.Lookup("key1", &count).get());
+ cache.ResetLookupCount("key1");
+ EXPECT_EQ(1, count);
+
+ // Test that independent keys are logged separately.
+ EXPECT_EQ(session1.get(), cache.Lookup("key1", &count).get());
+ EXPECT_EQ(1, count);
+ EXPECT_EQ(session2.get(), cache.Lookup("key2", &count).get());
+ EXPECT_EQ(1, count);
+
+ // Test that the count is 0 if there is a cache miss.
+ EXPECT_EQ(nullptr, cache.Lookup("not present", &count).get());
+ EXPECT_EQ(0, count);
+
+ // Check that ResetLookupCount doesn't explode if there's a cache miss.
+ cache.ResetLookupCount("not present");
+
+ EXPECT_EQ(2u, cache.size());
+}
+
// Test that a session may be inserted at two different keys. This should never
// be necessary, but the API doesn't prohibit it.
TEST(SSLClientSessionCacheTest, DoubleInsert) {
@@ -93,27 +135,27 @@ TEST(SSLClientSessionCacheTest, DoubleInsert) {
bssl::UniquePtr<SSL_SESSION> session(SSL_SESSION_new());
EXPECT_EQ(1u, session->references);
- EXPECT_EQ(nullptr, cache.Lookup("key1").get());
- EXPECT_EQ(nullptr, cache.Lookup("key2").get());
+ EXPECT_EQ(nullptr, cache.Lookup("key1", nullptr).get());
+ EXPECT_EQ(nullptr, cache.Lookup("key2", nullptr).get());
EXPECT_EQ(0u, cache.size());
cache.Insert("key1", session.get());
- EXPECT_EQ(session.get(), cache.Lookup("key1").get());
- EXPECT_EQ(nullptr, cache.Lookup("key2").get());
+ EXPECT_EQ(session.get(), cache.Lookup("key1", nullptr).get());
+ EXPECT_EQ(nullptr, cache.Lookup("key2", nullptr).get());
EXPECT_EQ(1u, cache.size());
EXPECT_EQ(2u, session->references);
cache.Insert("key2", session.get());
- EXPECT_EQ(session.get(), cache.Lookup("key1").get());
- EXPECT_EQ(session.get(), cache.Lookup("key2").get());
+ EXPECT_EQ(session.get(), cache.Lookup("key1", nullptr).get());
+ EXPECT_EQ(session.get(), cache.Lookup("key2", nullptr).get());
EXPECT_EQ(2u, cache.size());
EXPECT_EQ(3u, session->references);
cache.Flush();
- EXPECT_EQ(nullptr, cache.Lookup("key1").get());
- EXPECT_EQ(nullptr, cache.Lookup("key2").get());
+ EXPECT_EQ(nullptr, cache.Lookup("key1", nullptr).get());
+ EXPECT_EQ(nullptr, cache.Lookup("key2", nullptr).get());
EXPECT_EQ(0u, cache.size());
EXPECT_EQ(1u, session->references);
@@ -134,26 +176,26 @@ TEST(SSLClientSessionCacheTest, MaxEntries) {
cache.Insert("key1", session1.get());
cache.Insert("key2", session2.get());
cache.Insert("key3", session3.get());
- EXPECT_EQ(session1.get(), cache.Lookup("key1").get());
- EXPECT_EQ(session2.get(), cache.Lookup("key2").get());
- EXPECT_EQ(session3.get(), cache.Lookup("key3").get());
+ EXPECT_EQ(session1.get(), cache.Lookup("key1", nullptr).get());
+ EXPECT_EQ(session2.get(), cache.Lookup("key2", nullptr).get());
+ EXPECT_EQ(session3.get(), cache.Lookup("key3", nullptr).get());
EXPECT_EQ(3u, cache.size());
// On insertion of a fourth, the first is removed.
cache.Insert("key4", session4.get());
- EXPECT_EQ(nullptr, cache.Lookup("key1").get());
- EXPECT_EQ(session4.get(), cache.Lookup("key4").get());
- EXPECT_EQ(session3.get(), cache.Lookup("key3").get());
- EXPECT_EQ(session2.get(), cache.Lookup("key2").get());
+ EXPECT_EQ(nullptr, cache.Lookup("key1", nullptr).get());
+ EXPECT_EQ(session4.get(), cache.Lookup("key4", nullptr).get());
+ EXPECT_EQ(session3.get(), cache.Lookup("key3", nullptr).get());
+ EXPECT_EQ(session2.get(), cache.Lookup("key2", nullptr).get());
EXPECT_EQ(3u, cache.size());
// Despite being newest, the next to be removed is session4 as it was accessed
// least. recently.
cache.Insert("key1", session1.get());
- EXPECT_EQ(session1.get(), cache.Lookup("key1").get());
- EXPECT_EQ(session2.get(), cache.Lookup("key2").get());
- EXPECT_EQ(session3.get(), cache.Lookup("key3").get());
- EXPECT_EQ(nullptr, cache.Lookup("key4").get());
+ EXPECT_EQ(session1.get(), cache.Lookup("key1", nullptr).get());
+ EXPECT_EQ(session2.get(), cache.Lookup("key2", nullptr).get());
+ EXPECT_EQ(session3.get(), cache.Lookup("key3", nullptr).get());
+ EXPECT_EQ(nullptr, cache.Lookup("key4", nullptr).get());
EXPECT_EQ(3u, cache.size());
}
@@ -189,18 +231,18 @@ TEST(SSLClientSessionCacheTest, Expiration) {
// Perform one fewer lookup than needed to trigger the expiration check. This
// shall not expire any session.
for (size_t i = 0; i < kExpirationCheckCount - 1; i++)
- cache.Lookup("key");
+ cache.Lookup("key", nullptr);
// All entries are still in the cache.
EXPECT_EQ(kNumEntries, cache.size());
// Perform one more lookup. This will expire all sessions but the last one.
- cache.Lookup("key");
+ cache.Lookup("key", nullptr);
EXPECT_EQ(1u, cache.size());
- EXPECT_EQ(session.get(), cache.Lookup("key").get());
+ EXPECT_EQ(session.get(), cache.Lookup("key", nullptr).get());
for (size_t i = 0; i < kNumEntries - 1; i++) {
SCOPED_TRACE(i);
- EXPECT_EQ(nullptr, cache.Lookup(base::SizeTToString(i)));
+ EXPECT_EQ(nullptr, cache.Lookup(base::SizeTToString(i), nullptr));
}
}
@@ -222,7 +264,7 @@ TEST(SSLClientSessionCacheTest, LookupExpirationCheck) {
bssl::UniquePtr<SSL_SESSION> session =
MakeTestSession(clock->Now(), kTimeout);
cache.Insert("key", session.get());
- EXPECT_EQ(session.get(), cache.Lookup("key").get());
+ EXPECT_EQ(session.get(), cache.Lookup("key", nullptr).get());
EXPECT_EQ(1u, cache.size());
// Expire the session.
@@ -232,24 +274,24 @@ TEST(SSLClientSessionCacheTest, LookupExpirationCheck) {
EXPECT_EQ(1u, cache.size());
// But it will not be returned on lookup and gets pruned at that point.
- EXPECT_EQ(nullptr, cache.Lookup("key").get());
+ EXPECT_EQ(nullptr, cache.Lookup("key", nullptr).get());
EXPECT_EQ(0u, cache.size());
// Re-inserting a session does not refresh the lifetime. The expiration
// information in the session is used.
cache.Insert("key", session.get());
- EXPECT_EQ(nullptr, cache.Lookup("key").get());
+ EXPECT_EQ(nullptr, cache.Lookup("key", nullptr).get());
EXPECT_EQ(0u, cache.size());
// Re-insert a fresh copy of the session.
session = MakeTestSession(clock->Now(), kTimeout);
cache.Insert("key", session.get());
- EXPECT_EQ(session.get(), cache.Lookup("key").get());
+ EXPECT_EQ(session.get(), cache.Lookup("key", nullptr).get());
EXPECT_EQ(1u, cache.size());
// Sessions also are treated as expired if the clock rewinds.
clock->Advance(base::TimeDelta::FromSeconds(-1));
- EXPECT_EQ(nullptr, cache.Lookup("key").get());
+ EXPECT_EQ(nullptr, cache.Lookup("key", nullptr).get());
EXPECT_EQ(0u, cache.size());
}
@@ -270,7 +312,7 @@ TEST(SSLClientSessionCacheTest, TestFlushOnMemoryNotifications) {
bssl::UniquePtr<SSL_SESSION> session1 =
MakeTestSession(clock->Now(), kTimeout);
cache.Insert("key1", session1.get());
- EXPECT_EQ(session1.get(), cache.Lookup("key1").get());
+ EXPECT_EQ(session1.get(), cache.Lookup("key1", nullptr).get());
EXPECT_EQ(1u, cache.size());
// Expire the session.
@@ -288,8 +330,8 @@ TEST(SSLClientSessionCacheTest, TestFlushOnMemoryNotifications) {
// Expired session's cache should be flushed.
// Lookup returns nullptr, when cache entry not found.
- EXPECT_FALSE(cache.Lookup("key1"));
- EXPECT_TRUE(cache.Lookup("key2"));
+ EXPECT_FALSE(cache.Lookup("key1", nullptr));
+ EXPECT_TRUE(cache.Lookup("key2", nullptr));
EXPECT_EQ(1u, cache.size());
// Fire notification that will flush everything.
@@ -299,4 +341,40 @@ TEST(SSLClientSessionCacheTest, TestFlushOnMemoryNotifications) {
EXPECT_EQ(0u, cache.size());
}
+// Basic test for dumping memory stats.
+TEST(SSLClientSessionCacheTest, TestDumpMemoryStats) {
+ SSLClientSessionCache::Config config;
+ SSLClientSessionCache cache(config);
+
+ bssl::UniquePtr<SSL_SESSION> session1(SSL_SESSION_new());
+ bssl::UniquePtr<SSL_SESSION> session2(SSL_SESSION_new());
+ bssl::UniquePtr<SSL_SESSION> session3(SSL_SESSION_new());
+
+ // Insert three entries.
+ cache.Insert("key1", session1.get());
+ cache.Insert("key2", session2.get());
+ cache.Insert("key3", session3.get());
+ EXPECT_EQ(session1.get(), cache.Lookup("key1", nullptr).get());
+ EXPECT_EQ(session2.get(), cache.Lookup("key2", nullptr).get());
+ EXPECT_EQ(session3.get(), cache.Lookup("key3", nullptr).get());
+ EXPECT_EQ(3u, cache.size());
+
+ base::trace_event::MemoryDumpArgs dump_args = {
+ base::trace_event::MemoryDumpLevelOfDetail::DETAILED};
+ std::unique_ptr<base::trace_event::ProcessMemoryDump> process_memory_dump(
+ new base::trace_event::ProcessMemoryDump(nullptr, dump_args));
+ cache.DumpMemoryStats(process_memory_dump.get());
+
+ const base::trace_event::MemoryAllocatorDump* dump =
+ process_memory_dump->GetAllocatorDump("net/ssl_session_cache");
+ ASSERT_NE(nullptr, dump);
+ std::unique_ptr<base::Value> raw_attrs =
+ dump->attributes_for_testing()->ToBaseValue();
+ base::DictionaryValue* attrs;
+ ASSERT_TRUE(raw_attrs->GetAsDictionary(&attrs));
+ ASSERT_TRUE(attrs->HasKey("cert_count"));
+ ASSERT_TRUE(attrs->HasKey("serialized_cert_size"));
+ ASSERT_TRUE(attrs->HasKey(base::trace_event::MemoryAllocatorDump::kNameSize));
+}
+
} // namespace net
diff --git a/chromium/net/ssl/ssl_config.cc b/chromium/net/ssl/ssl_config.cc
index 7a4f3373bb4..3275ac47fe9 100644
--- a/chromium/net/ssl/ssl_config.cc
+++ b/chromium/net/ssl/ssl_config.cc
@@ -23,7 +23,7 @@ SSLConfig::CertAndStatus::~CertAndStatus() = default;
SSLConfig::SSLConfig()
: rev_checking_enabled(false),
rev_checking_required_local_anchors(false),
- sha1_local_anchors_enabled(false),
+ sha1_local_anchors_enabled(true),
version_min(kDefaultSSLVersionMin),
version_max(kDefaultSSLVersionMax),
deprecated_cipher_suites_enabled(false),
diff --git a/chromium/net/ssl/ssl_config_service.cc b/chromium/net/ssl/ssl_config_service.cc
index c80113c4e99..2b4388efac5 100644
--- a/chromium/net/ssl/ssl_config_service.cc
+++ b/chromium/net/ssl/ssl_config_service.cc
@@ -4,6 +4,8 @@
#include "net/ssl/ssl_config_service.h"
+#include <tuple>
+
#include "base/lazy_instance.h"
#include "base/synchronization/lock.h"
#include "net/ssl/ssl_config_service_defaults.h"
@@ -84,16 +86,18 @@ SSLConfigService::~SSLConfigService() {
void SSLConfigService::ProcessConfigUpdate(const SSLConfig& orig_config,
const SSLConfig& new_config) {
bool config_changed =
- (orig_config.rev_checking_enabled != new_config.rev_checking_enabled) ||
- (orig_config.rev_checking_required_local_anchors !=
- new_config.rev_checking_required_local_anchors) ||
- (orig_config.version_min != new_config.version_min) ||
- (orig_config.version_max != new_config.version_max) ||
- (orig_config.disabled_cipher_suites !=
- new_config.disabled_cipher_suites) ||
- (orig_config.channel_id_enabled != new_config.channel_id_enabled) ||
- (orig_config.false_start_enabled != new_config.false_start_enabled) ||
- (orig_config.require_ecdhe != new_config.require_ecdhe);
+ std::tie(orig_config.rev_checking_enabled,
+ orig_config.rev_checking_required_local_anchors,
+ orig_config.sha1_local_anchors_enabled, orig_config.version_min,
+ orig_config.version_max, orig_config.disabled_cipher_suites,
+ orig_config.channel_id_enabled, orig_config.false_start_enabled,
+ orig_config.require_ecdhe) !=
+ std::tie(new_config.rev_checking_enabled,
+ new_config.rev_checking_required_local_anchors,
+ new_config.sha1_local_anchors_enabled, new_config.version_min,
+ new_config.version_max, new_config.disabled_cipher_suites,
+ new_config.channel_id_enabled, new_config.false_start_enabled,
+ new_config.require_ecdhe);
if (config_changed)
NotifySSLConfigChange();
diff --git a/chromium/net/ssl/ssl_config_service_unittest.cc b/chromium/net/ssl/ssl_config_service_unittest.cc
index 11f59cd8241..72041ff2412 100644
--- a/chromium/net/ssl/ssl_config_service_unittest.cc
+++ b/chromium/net/ssl/ssl_config_service_unittest.cc
@@ -65,7 +65,10 @@ TEST(SSLConfigServiceTest, NoChangesWontNotifyObservers) {
TEST(SSLConfigServiceTest, ConfigUpdatesNotifyObservers) {
SSLConfig initial_config;
initial_config.rev_checking_enabled = true;
+ initial_config.rev_checking_required_local_anchors = false;
+ initial_config.sha1_local_anchors_enabled = true;
initial_config.false_start_enabled = false;
+ initial_config.require_ecdhe = false;
initial_config.version_min = SSL_PROTOCOL_VERSION_TLS1;
initial_config.version_max = SSL_PROTOCOL_VERSION_TLS1_2;
@@ -79,10 +82,22 @@ TEST(SSLConfigServiceTest, ConfigUpdatesNotifyObservers) {
EXPECT_CALL(observer, OnSSLConfigChanged()).Times(1);
mock_service->SetSSLConfig(initial_config);
+ initial_config.rev_checking_required_local_anchors = true;
+ EXPECT_CALL(observer, OnSSLConfigChanged()).Times(1);
+ mock_service->SetSSLConfig(initial_config);
+
+ initial_config.sha1_local_anchors_enabled = false;
+ EXPECT_CALL(observer, OnSSLConfigChanged()).Times(1);
+ mock_service->SetSSLConfig(initial_config);
+
initial_config.false_start_enabled = true;
EXPECT_CALL(observer, OnSSLConfigChanged()).Times(1);
mock_service->SetSSLConfig(initial_config);
+ initial_config.require_ecdhe = true;
+ EXPECT_CALL(observer, OnSSLConfigChanged()).Times(1);
+ mock_service->SetSSLConfig(initial_config);
+
// Test that changing the SSL version range triggers updates.
initial_config.version_min = SSL_PROTOCOL_VERSION_TLS1_1;
EXPECT_CALL(observer, OnSSLConfigChanged()).Times(1);
diff --git a/chromium/net/ssl/ssl_connection_status_flags.h b/chromium/net/ssl/ssl_connection_status_flags.h
index d3062724ef4..ce6bc55d88a 100644
--- a/chromium/net/ssl/ssl_connection_status_flags.h
+++ b/chromium/net/ssl/ssl_connection_status_flags.h
@@ -22,12 +22,7 @@ enum {
SSL_CONNECTION_COMPRESSION_MASK = 3,
// 1 << 18 was previously used for SSL_CONNECTION_VERSION_FALLBACK.
-
- // The server doesn't support the renegotiation_info extension. If this bit
- // is not set then either the extension isn't supported, or we don't have any
- // knowledge either way. (The latter case will occur when we use an SSL
- // library that doesn't report it, like SChannel.)
- SSL_CONNECTION_NO_RENEGOTIATION_EXTENSION = 1 << 19,
+ // 1 << 19 was previously used for SSL_CONNECTION_NO_RENEGOTIATION_EXTENSION.
// The next three bits are reserved for the SSL version.
SSL_CONNECTION_VERSION_SHIFT = 20,
diff --git a/chromium/net/ssl/ssl_platform_key.h b/chromium/net/ssl/ssl_platform_key.h
index 00924001bce..efb42920ed6 100644
--- a/chromium/net/ssl/ssl_platform_key.h
+++ b/chromium/net/ssl/ssl_platform_key.h
@@ -15,11 +15,11 @@ namespace net {
class SSLPrivateKey;
class X509Certificate;
-// Looks up the private key from the platform key store corresponding to
-// |certificate|'s public key and returns an SSLPrivateKey backed by the
-// playform key.
+// Returns an SSLPrivateKey backed by the platform private key that corresponds
+// to |certificate|'s public key. If |keychain| is nullptr, the process's
+// default search list is used instead.
NET_EXPORT scoped_refptr<SSLPrivateKey> FetchClientCertPrivateKey(
- X509Certificate* certificate);
+ const X509Certificate* certificate);
} // namespace net
diff --git a/chromium/net/ssl/ssl_platform_key_android.cc b/chromium/net/ssl/ssl_platform_key_android.cc
index 492c094b3bd..136c63ad822 100644
--- a/chromium/net/ssl/ssl_platform_key_android.cc
+++ b/chromium/net/ssl/ssl_platform_key_android.cc
@@ -223,7 +223,7 @@ scoped_refptr<SSLPrivateKey> WrapJavaPrivateKey(
}
scoped_refptr<SSLPrivateKey> FetchClientCertPrivateKey(
- X509Certificate* certificate) {
+ const X509Certificate* certificate) {
return OpenSSLClientKeyStore::GetInstance()->FetchClientCertPrivateKey(
certificate);
}
diff --git a/chromium/net/ssl/ssl_platform_key_android_unittest.cc b/chromium/net/ssl/ssl_platform_key_android_unittest.cc
index 118de120509..ff2c2c50359 100644
--- a/chromium/net/ssl/ssl_platform_key_android_unittest.cc
+++ b/chromium/net/ssl/ssl_platform_key_android_unittest.cc
@@ -2,32 +2,23 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
+#include "net/ssl/ssl_platform_key_android.h"
+
+#include <string>
+
#include "base/android/jni_android.h"
#include "base/android/jni_array.h"
#include "base/android/scoped_java_ref.h"
-#include "base/bind.h"
#include "base/files/file_path.h"
#include "base/files/file_util.h"
-#include "base/run_loop.h"
-#include "base/strings/string_number_conversions.h"
-#include "base/strings/string_util.h"
-#include "crypto/openssl_util.h"
#include "net/android/keystore.h"
#include "net/cert/x509_certificate.h"
-#include "net/ssl/ssl_platform_key_android.h"
#include "net/ssl/ssl_private_key.h"
+#include "net/ssl/ssl_private_key_test_util.h"
#include "net/test/cert_test_util.h"
#include "net/test/jni/AndroidKeyStoreTestUtil_jni.h"
#include "net/test/test_data_directory.h"
#include "testing/gtest/include/gtest/gtest.h"
-#include "third_party/boringssl/src/include/openssl/bytestring.h"
-#include "third_party/boringssl/src/include/openssl/digest.h"
-#include "third_party/boringssl/src/include/openssl/ecdsa.h"
-#include "third_party/boringssl/src/include/openssl/err.h"
-#include "third_party/boringssl/src/include/openssl/evp.h"
-#include "third_party/boringssl/src/include/openssl/pem.h"
-#include "third_party/boringssl/src/include/openssl/rsa.h"
-#include "third_party/boringssl/src/include/openssl/x509.h"
namespace net {
@@ -35,63 +26,12 @@ namespace {
typedef base::android::ScopedJavaLocalRef<jobject> ScopedJava;
-// Resize a string to |size| bytes of data, then return its data buffer
-// address cast as an 'unsigned char*', as expected by OpenSSL functions.
-// |str| the target string.
-// |size| the number of bytes to write into the string.
-// Return the string's new buffer in memory, as an 'unsigned char*'
-// pointer.
-unsigned char* OpenSSLWriteInto(std::string* str, size_t size) {
- return reinterpret_cast<unsigned char*>(base::WriteInto(str, size + 1));
-}
-
bool ReadTestFile(const char* filename, std::string* pkcs8) {
base::FilePath certs_dir = GetTestCertsDirectory();
base::FilePath file_path = certs_dir.AppendASCII(filename);
return base::ReadFileToString(file_path, pkcs8);
}
-// Load a given private key file into an EVP_PKEY.
-// |filename| is the key file path.
-// Returns a new EVP_PKEY on success, NULL on failure.
-bssl::UniquePtr<EVP_PKEY> ImportPrivateKeyFile(const char* filename) {
- std::string pkcs8;
- if (!ReadTestFile(filename, &pkcs8))
- return nullptr;
-
- crypto::OpenSSLErrStackTracer err_tracer(FROM_HERE);
- CBS cbs;
- CBS_init(&cbs, reinterpret_cast<const uint8_t*>(pkcs8.data()), pkcs8.size());
- bssl::UniquePtr<EVP_PKEY> pkey(EVP_parse_private_key(&cbs));
- if (!pkey) {
- LOG(ERROR) << "Could not load private key file: " << filename;
- return nullptr;
- }
-
- return pkey;
-}
-
-// Imports the public key from the specified test certificate.
-bssl::UniquePtr<EVP_PKEY> ImportPublicKeyFromCertificateFile(
- const char* filename) {
- crypto::OpenSSLErrStackTracer err_tracer(FROM_HERE);
-
- scoped_refptr<X509Certificate> cert =
- ImportCertFromFile(GetTestCertsDirectory(), filename);
- if (!cert) {
- LOG(ERROR) << "Could not open certificate file: " << filename;
- return nullptr;
- }
-
- bssl::UniquePtr<EVP_PKEY> pkey(X509_get_pubkey(cert->os_cert_handle()));
- if (!pkey) {
- LOG(ERROR) << "Could not load public key from certificate: " << filename;
- return nullptr;
- }
-
- return pkey;
-}
-
// Retrieve a JNI local ref from encoded PKCS#8 data.
ScopedJava GetPKCS8PrivateKeyJava(android::PrivateKeyType key_type,
const std::string& pkcs8_key) {
@@ -107,256 +47,61 @@ ScopedJava GetPKCS8PrivateKeyJava(android::PrivateKeyType key_type,
return key;
}
-const char kTestRsaKeyFile[] = "client_1.pk8";
-const char kTestRsaCertificateFile[] = "client_1.pem";
-
-// Retrieve a JNI local ref for our test RSA key.
-ScopedJava GetRSATestKeyJava() {
- std::string key;
- if (!ReadTestFile(kTestRsaKeyFile, &key))
- return ScopedJava();
- return GetPKCS8PrivateKeyJava(android::PRIVATE_KEY_TYPE_RSA, key);
-}
-
-const char kTestEcdsaKeyFile[] = "client_4.pk8";
-const char kTestEcdsaCertificateFile[] = "client_4.pem";
-
-// Retrieve a JNI local ref for our test ECDSA key.
-ScopedJava GetECDSATestKeyJava() {
- std::string key;
- if (!ReadTestFile(kTestEcdsaKeyFile, &key))
- return ScopedJava();
- return GetPKCS8PrivateKeyJava(android::PRIVATE_KEY_TYPE_ECDSA, key);
-}
-
-// Call this function to verify that one message signed with our
-// test ECDSA private key is correct. Since ECDSA signing introduces
-// random elements in the signature, it is not possible to compare
-// signature bits directly. However, one can use the public key
-// to do the check.
-bool VerifyTestECDSASignature(const base::StringPiece& message,
- const base::StringPiece& signature) {
- crypto::OpenSSLErrStackTracer err_tracer(FROM_HERE);
-
- bssl::UniquePtr<EVP_PKEY> pkey =
- ImportPublicKeyFromCertificateFile(kTestEcdsaCertificateFile);
- if (!pkey)
- return false;
-
- EC_KEY* pub_key = EVP_PKEY_get0_EC_KEY(pkey.get());
- if (!pub_key) {
- LOG(ERROR) << "Could not get ECDSA public key";
- return false;
- }
-
- const unsigned char* digest =
- reinterpret_cast<const unsigned char*>(message.data());
- int digest_len = static_cast<int>(message.size());
- const unsigned char* sigbuf =
- reinterpret_cast<const unsigned char*>(signature.data());
- int siglen = static_cast<int>(signature.size());
-
- if (!ECDSA_verify(0, digest, digest_len, sigbuf, siglen, pub_key)) {
- LOG(ERROR) << "ECDSA_verify() failed";
- return false;
- }
- return true;
-}
-
-// Sign a message with OpenSSL, return the result as a string.
-// |message| is the message to be signed.
-// |openssl_key| is an OpenSSL EVP_PKEY to use.
-// |result| receives the result.
-// Returns true on success, false otherwise.
-bool SignWithOpenSSL(int hash_nid,
- const base::StringPiece& message,
- EVP_PKEY* openssl_key,
- std::string* result) {
- crypto::OpenSSLErrStackTracer err_tracer(FROM_HERE);
-
- RSA* rsa = EVP_PKEY_get0_RSA(openssl_key);
- if (!rsa) {
- LOG(ERROR) << "Could not get RSA from EVP_PKEY";
- return false;
- }
-
- const unsigned char* digest =
- reinterpret_cast<const unsigned char*>(message.data());
- unsigned int digest_len = static_cast<unsigned int>(message.size());
-
- // With RSA, the signature will always be RSA_size() bytes.
- size_t max_signature_size = static_cast<size_t>(RSA_size(rsa));
- std::string signature;
- unsigned char* p = OpenSSLWriteInto(&signature, max_signature_size);
- unsigned int p_len = 0;
- if (!RSA_sign(hash_nid, digest, digest_len, p, &p_len, rsa)) {
- LOG(ERROR) << "RSA_sign() failed";
- return false;
- }
-
- size_t signature_size = static_cast<size_t>(p_len);
- if (signature_size == 0) {
- LOG(ERROR) << "Signature is empty!";
- return false;
- }
- if (signature_size > max_signature_size) {
- LOG(ERROR) << "Signature size mismatch, actual " << signature_size
- << ", expected <= " << max_signature_size;
- return false;
- }
- signature.resize(signature_size);
- result->swap(signature);
- return true;
-}
-
-// Check that a generated signature for a given message matches
-// OpenSSL output byte-by-byte.
-// |message| is the input message.
-// |signature| is the generated signature for the message.
-// |openssl_key| is a raw EVP_PKEY for the same private key than the
-// one which was used to generate the signature.
-// Returns true on success, false otherwise.
-bool CompareSignatureWithOpenSSL(int hash_nid,
- const base::StringPiece& message,
- const base::StringPiece& signature,
- EVP_PKEY* openssl_key) {
- std::string openssl_signature;
- if (!SignWithOpenSSL(hash_nid, message, openssl_key, &openssl_signature))
- return false;
-
- if (signature.size() != openssl_signature.size()) {
- LOG(ERROR) << "Signature size mismatch, actual " << signature.size()
- << ", expected " << openssl_signature.size();
- return false;
- }
- for (size_t n = 0; n < signature.size(); ++n) {
- if (openssl_signature[n] != signature[n]) {
- LOG(ERROR) << "Signature byte mismatch at index " << n << "actual "
- << signature[n] << ", expected " << openssl_signature[n];
- LOG(ERROR) << "Actual signature : "
- << base::HexEncode(signature.data(), signature.size());
- LOG(ERROR) << "Expected signature: "
- << base::HexEncode(openssl_signature.data(),
- openssl_signature.size());
- return false;
- }
- }
- return true;
-}
-
-void OnSignComplete(base::RunLoop* loop,
- Error* out_error,
- std::string* out_signature,
- Error error,
- const std::vector<uint8_t>& signature) {
- *out_error = error;
- out_signature->assign(signature.begin(), signature.end());
- loop->Quit();
-}
-
-void DoKeySigningWithWrapper(SSLPrivateKey* key,
- SSLPrivateKey::Hash hash,
- const base::StringPiece& message,
- std::string* result) {
- Error error;
- base::RunLoop loop;
+struct TestKey {
+ const char* cert_file;
+ const char* key_file;
+ android::PrivateKeyType android_key_type;
+ SSLPrivateKey::Type key_type;
+};
- key->SignDigest(
- hash, message,
- base::Bind(OnSignComplete, base::Unretained(&loop),
- base::Unretained(&error), base::Unretained(result)));
- loop.Run();
+const TestKey kTestKeys[] = {
+ {"client_1.pem", "client_1.pk8", android::PRIVATE_KEY_TYPE_RSA,
+ SSLPrivateKey::Type::RSA},
+ {"client_4.pem", "client_4.pk8", android::PRIVATE_KEY_TYPE_ECDSA,
+ SSLPrivateKey::Type::ECDSA_P256},
+ {"client_5.pem", "client_5.pk8", android::PRIVATE_KEY_TYPE_ECDSA,
+ SSLPrivateKey::Type::ECDSA_P384},
+ {"client_6.pem", "client_6.pk8", android::PRIVATE_KEY_TYPE_ECDSA,
+ SSLPrivateKey::Type::ECDSA_P521},
+};
- ASSERT_EQ(OK, error);
+std::string TestKeyToString(const testing::TestParamInfo<TestKey>& params) {
+ return SSLPrivateKeyTypeToString(params.param.key_type);
}
-static const struct {
- const char* name;
- int nid;
- SSLPrivateKey::Hash hash;
-} kHashes[] = {
- {"MD5-SHA1", NID_md5_sha1, SSLPrivateKey::Hash::MD5_SHA1},
- {"SHA-1", NID_sha1, SSLPrivateKey::Hash::SHA1},
- {"SHA-256", NID_sha256, SSLPrivateKey::Hash::SHA256},
- {"SHA-384", NID_sha384, SSLPrivateKey::Hash::SHA384},
- {"SHA-512", NID_sha512, SSLPrivateKey::Hash::SHA512},
-};
-
} // namespace
-TEST(SSLPlatformKeyAndroid, RSA) {
- crypto::OpenSSLErrStackTracer err_tracer(FROM_HERE);
-
- scoped_refptr<X509Certificate> cert =
- ImportCertFromFile(GetTestCertsDirectory(), kTestRsaCertificateFile);
- ASSERT_TRUE(cert);
- ScopedJava rsa_key = GetRSATestKeyJava();
- ASSERT_FALSE(rsa_key.is_null());
-
- scoped_refptr<SSLPrivateKey> wrapper_key =
- WrapJavaPrivateKey(cert.get(), rsa_key);
- ASSERT_TRUE(wrapper_key);
-
- bssl::UniquePtr<EVP_PKEY> openssl_key = ImportPrivateKeyFile(kTestRsaKeyFile);
- ASSERT_TRUE(openssl_key);
-
- // Check that the wrapper key returns the correct length and type.
- EXPECT_EQ(SSLPrivateKey::Type::RSA, wrapper_key->GetType());
- EXPECT_EQ(static_cast<size_t>(EVP_PKEY_size(openssl_key.get())),
- wrapper_key->GetMaxSignatureLengthInBytes());
+class SSLPlatformKeyAndroidTest : public testing::TestWithParam<TestKey> {};
- // Test signing against each hash.
- for (const auto& hash : kHashes) {
- SCOPED_TRACE(hash.name);
-
- const EVP_MD* md = EVP_get_digestbynid(hash.nid);
- ASSERT_TRUE(md);
- std::string digest(EVP_MD_size(md), 'a');
-
- std::string signature;
- DoKeySigningWithWrapper(wrapper_key.get(), hash.hash, digest, &signature);
- ASSERT_TRUE(CompareSignatureWithOpenSSL(hash.nid, digest, signature,
- openssl_key.get()));
- }
-}
-
-TEST(SSLPlatformKeyAndroid, ECDSA) {
- crypto::OpenSSLErrStackTracer err_tracer(FROM_HERE);
+TEST_P(SSLPlatformKeyAndroidTest, Matches) {
+ const TestKey& test_key = GetParam();
scoped_refptr<X509Certificate> cert =
- ImportCertFromFile(GetTestCertsDirectory(), kTestEcdsaCertificateFile);
+ ImportCertFromFile(GetTestCertsDirectory(), test_key.cert_file);
ASSERT_TRUE(cert);
- ScopedJava ecdsa_key = GetECDSATestKeyJava();
- ASSERT_FALSE(ecdsa_key.is_null());
- scoped_refptr<SSLPrivateKey> wrapper_key =
- WrapJavaPrivateKey(cert.get(), ecdsa_key);
- ASSERT_TRUE(wrapper_key);
+ std::string key_bytes;
+ ASSERT_TRUE(ReadTestFile(test_key.key_file, &key_bytes));
+ ScopedJava java_key =
+ GetPKCS8PrivateKeyJava(test_key.android_key_type, key_bytes);
+ ASSERT_FALSE(java_key.is_null());
- bssl::UniquePtr<EVP_PKEY> openssl_key =
- ImportPrivateKeyFile(kTestEcdsaKeyFile);
- ASSERT_TRUE(openssl_key);
+ scoped_refptr<SSLPrivateKey> key = WrapJavaPrivateKey(cert.get(), java_key);
+ ASSERT_TRUE(key);
- // Check that the wrapper key returns the correct length and type.
- EXPECT_EQ(SSLPrivateKey::Type::ECDSA_P256, wrapper_key->GetType());
- EXPECT_EQ(static_cast<size_t>(EVP_PKEY_size(openssl_key.get())),
- wrapper_key->GetMaxSignatureLengthInBytes());
+ // All Android keys are expected to have the same hash preferences.
+ std::vector<SSLPrivateKey::Hash> expected_hashes = {
+ SSLPrivateKey::Hash::SHA512, SSLPrivateKey::Hash::SHA384,
+ SSLPrivateKey::Hash::SHA256, SSLPrivateKey::Hash::SHA1,
+ };
+ EXPECT_EQ(expected_hashes, key->GetDigestPreferences());
- // Test signing against each hash.
- for (const auto& hash : kHashes) {
- // ECDSA does not sign MD5-SHA1.
- if (hash.nid == NID_md5_sha1)
- continue;
-
- SCOPED_TRACE(hash.name);
- const EVP_MD* md = EVP_get_digestbynid(hash.nid);
- ASSERT_TRUE(md);
- std::string digest(EVP_MD_size(md), 'a');
-
- std::string signature;
- DoKeySigningWithWrapper(wrapper_key.get(), hash.hash, digest, &signature);
- ASSERT_TRUE(VerifyTestECDSASignature(digest, signature));
- }
+ TestSSLPrivateKeyMatches(key.get(), key_bytes);
}
+INSTANTIATE_TEST_CASE_P(,
+ SSLPlatformKeyAndroidTest,
+ testing::ValuesIn(kTestKeys),
+ TestKeyToString);
+
} // namespace net
diff --git a/chromium/net/ssl/ssl_platform_key_chromecast.cc b/chromium/net/ssl/ssl_platform_key_chromecast.cc
index e7857e8b654..5993a3bbe3e 100644
--- a/chromium/net/ssl/ssl_platform_key_chromecast.cc
+++ b/chromium/net/ssl/ssl_platform_key_chromecast.cc
@@ -41,11 +41,8 @@ class SSLPlatformKeyChromecast : public ThreadedSSLPrivateKey::Delegate {
SSLPrivateKey::Type GetType() override { return SSLPrivateKey::Type::RSA; }
std::vector<SSLPrivateKey::Hash> GetDigestPreferences() override {
- static const SSLPrivateKey::Hash kHashes[] = {
- SSLPrivateKey::Hash::SHA256, SSLPrivateKey::Hash::SHA1,
- SSLPrivateKey::Hash::MD5_SHA1};
- return std::vector<SSLPrivateKey::Hash>(kHashes,
- kHashes + arraysize(kHashes));
+ return std::vector<SSLPrivateKey::Hash>{SSLPrivateKey::Hash::SHA256,
+ SSLPrivateKey::Hash::SHA1};
}
size_t GetMaxSignatureLengthInBytes() override {
@@ -119,7 +116,7 @@ class SSLPlatformKeyChromecast : public ThreadedSSLPrivateKey::Delegate {
} // namespace
scoped_refptr<SSLPrivateKey> FetchClientCertPrivateKey(
- X509Certificate* certificate) {
+ const X509Certificate* certificate) {
crypto::ScopedSECKEYPrivateKey key(
PK11_FindKeyByAnyCert(certificate->os_cert_handle(), nullptr));
if (!key) {
diff --git a/chromium/net/ssl/ssl_platform_key_chromecast_unittest.cc b/chromium/net/ssl/ssl_platform_key_chromecast_unittest.cc
new file mode 100644
index 00000000000..78979c50693
--- /dev/null
+++ b/chromium/net/ssl/ssl_platform_key_chromecast_unittest.cc
@@ -0,0 +1,52 @@
+// Copyright 2016 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.
+
+#include "net/ssl/ssl_platform_key.h"
+
+#include <pk11pub.h>
+#include <stdint.h>
+#include <string.h>
+
+#include <memory>
+#include <string>
+#include <vector>
+
+#include "base/files/file_path.h"
+#include "base/files/file_util.h"
+#include "base/memory/ref_counted.h"
+#include "crypto/scoped_test_nss_db.h"
+#include "net/ssl/ssl_private_key.h"
+#include "net/ssl/ssl_private_key_test_util.h"
+#include "net/test/cert_test_util.h"
+#include "net/test/test_data_directory.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace net {
+
+TEST(SSLPlatformKeyChromecastTest, KeyMatches) {
+ std::string pkcs8;
+ base::FilePath pkcs8_path =
+ GetTestCertsDirectory().AppendASCII("client_1.pk8");
+ ASSERT_TRUE(base::ReadFileToString(pkcs8_path, &pkcs8));
+
+ // Import the key into a test NSS database.
+ crypto::ScopedTestNSSDB test_db;
+ scoped_refptr<X509Certificate> cert = ImportClientCertAndKeyFromFile(
+ GetTestCertsDirectory(), "client_1.pem", "client_1.pk8", test_db.slot());
+ ASSERT_TRUE(cert);
+
+ // Look up the key.
+ scoped_refptr<SSLPrivateKey> key = FetchClientCertPrivateKey(cert.get());
+ ASSERT_TRUE(key);
+
+ // Only support SHA-256 and SHA-1.
+ std::vector<SSLPrivateKey::Hash> expected_hashes = {
+ SSLPrivateKey::Hash::SHA256, SSLPrivateKey::Hash::SHA1,
+ };
+ EXPECT_EQ(expected_hashes, key->GetDigestPreferences());
+
+ TestSSLPrivateKeyMatches(key.get(), pkcs8);
+}
+
+} // namespace net
diff --git a/chromium/net/ssl/ssl_platform_key_mac.cc b/chromium/net/ssl/ssl_platform_key_mac.cc
index 439e06b5a6d..373f4323e07 100644
--- a/chromium/net/ssl/ssl_platform_key_mac.cc
+++ b/chromium/net/ssl/ssl_platform_key_mac.cc
@@ -2,8 +2,10 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#include "net/ssl/ssl_platform_key.h"
+#include "net/ssl/ssl_platform_key_mac.h"
+#include <dlfcn.h>
+#include <CoreFoundation/CoreFoundation.h>
#include <Security/cssm.h>
#include <Security/SecBase.h>
#include <Security/SecCertificate.h>
@@ -12,18 +14,23 @@
#include <memory>
+#include "base/lazy_instance.h"
#include "base/location.h"
#include "base/logging.h"
+#include "base/mac/foundation_util.h"
#include "base/mac/mac_logging.h"
+#include "base/mac/mac_util.h"
#include "base/mac/scoped_cftyperef.h"
#include "base/macros.h"
#include "base/memory/ptr_util.h"
#include "base/memory/scoped_policy.h"
+#include "base/numerics/safe_conversions.h"
#include "base/synchronization/lock.h"
#include "crypto/mac_security_services_lock.h"
#include "crypto/openssl_util.h"
#include "net/base/net_errors.h"
#include "net/cert/x509_certificate.h"
+#include "net/ssl/ssl_platform_key.h"
#include "net/ssl/ssl_platform_key_util.h"
#include "net/ssl/ssl_private_key.h"
#include "net/ssl/threaded_ssl_private_key.h"
@@ -32,6 +39,13 @@
#include "third_party/boringssl/src/include/openssl/nid.h"
#include "third_party/boringssl/src/include/openssl/rsa.h"
+#if !defined(MAC_OS_X_VERSION_10_12) || \
+ MAC_OS_X_VERSION_MIN_ALLOWED < MAC_OS_X_VERSION_10_12
+// Redeclare typedefs that only exist in 10.12+ to suppress
+// -Wpartial-availability warnings.
+typedef CFStringRef SecKeyAlgorithm;
+#endif
+
namespace net {
// CSSM functions are deprecated as of OSX 10.7, but have no replacement.
@@ -62,16 +76,17 @@ class ScopedCSSM_CC_HANDLE {
DISALLOW_COPY_AND_ASSIGN(ScopedCSSM_CC_HANDLE);
};
-// Looks up the private key for |certificate| in KeyChain and returns
+// Looks up the private key for |certificate| in |keychain| and returns
// a SecKeyRef or nullptr on failure. The caller takes ownership of the
// result.
-SecKeyRef FetchSecKeyRefForCertificate(const X509Certificate* certificate) {
+SecKeyRef FetchSecKeyRefForCertificate(const X509Certificate* certificate,
+ SecKeychainRef keychain) {
OSStatus status;
base::ScopedCFTypeRef<SecIdentityRef> identity;
{
base::AutoLock lock(crypto::GetMacSecurityServicesLock());
status = SecIdentityCreateWithCertificate(
- nullptr, certificate->os_cert_handle(), identity.InitializeInto());
+ keychain, certificate->os_cert_handle(), identity.InitializeInto());
}
if (status != noErr) {
OSSTATUS_LOG(WARNING, status);
@@ -88,27 +103,88 @@ SecKeyRef FetchSecKeyRefForCertificate(const X509Certificate* certificate) {
return private_key.release();
}
-class SSLPlatformKeyMac : public ThreadedSSLPrivateKey::Delegate {
+// These symbols were added in the 10.12 SDK, but we currently use an older SDK,
+// so look them up with dlsym.
+//
+// TODO(davidben): After https://crbug.com/669240 is fixed, use the APIs
+// directly.
+struct SecKeyAPIs {
+ SecKeyAPIs() { Init(); }
+
+ void Init() {
+ SecKeyCreateSignature = reinterpret_cast<SecKeyCreateSignatureFunc>(
+ dlsym(RTLD_DEFAULT, "SecKeyCreateSignature"));
+ if (!SecKeyCreateSignature) {
+ NOTREACHED();
+ return;
+ }
+
+#define LOOKUP_ALGORITHM(name) \
+ do { \
+ SecKeyAlgorithm* algorithm = \
+ reinterpret_cast<SecKeyAlgorithm*>(dlsym(RTLD_DEFAULT, #name)); \
+ if (!algorithm) { \
+ NOTREACHED(); \
+ return; \
+ } \
+ name = *algorithm; \
+ } while (0)
+
+ LOOKUP_ALGORITHM(kSecKeyAlgorithmRSASignatureDigestPKCS1v15Raw);
+ LOOKUP_ALGORITHM(kSecKeyAlgorithmRSASignatureDigestPKCS1v15SHA1);
+ LOOKUP_ALGORITHM(kSecKeyAlgorithmRSASignatureDigestPKCS1v15SHA256);
+ LOOKUP_ALGORITHM(kSecKeyAlgorithmRSASignatureDigestPKCS1v15SHA384);
+ LOOKUP_ALGORITHM(kSecKeyAlgorithmRSASignatureDigestPKCS1v15SHA512);
+ LOOKUP_ALGORITHM(kSecKeyAlgorithmECDSASignatureDigestX962SHA1);
+ LOOKUP_ALGORITHM(kSecKeyAlgorithmECDSASignatureDigestX962SHA256);
+ LOOKUP_ALGORITHM(kSecKeyAlgorithmECDSASignatureDigestX962SHA384);
+ LOOKUP_ALGORITHM(kSecKeyAlgorithmECDSASignatureDigestX962SHA512);
+
+#undef LOOKUP_ALGORITHM
+
+ valid = true;
+ }
+
+ using SecKeyCreateSignatureFunc = CFDataRef (*)(SecKeyRef key,
+ SecKeyAlgorithm algorithm,
+ CFDataRef dataToSign,
+ CFErrorRef* error);
+
+ bool valid = false;
+ SecKeyCreateSignatureFunc SecKeyCreateSignature = nullptr;
+ SecKeyAlgorithm kSecKeyAlgorithmRSASignatureDigestPKCS1v15Raw = nullptr;
+ SecKeyAlgorithm kSecKeyAlgorithmRSASignatureDigestPKCS1v15SHA1 = nullptr;
+ SecKeyAlgorithm kSecKeyAlgorithmRSASignatureDigestPKCS1v15SHA256 = nullptr;
+ SecKeyAlgorithm kSecKeyAlgorithmRSASignatureDigestPKCS1v15SHA384 = nullptr;
+ SecKeyAlgorithm kSecKeyAlgorithmRSASignatureDigestPKCS1v15SHA512 = nullptr;
+ SecKeyAlgorithm kSecKeyAlgorithmECDSASignatureDigestX962SHA1 = nullptr;
+ SecKeyAlgorithm kSecKeyAlgorithmECDSASignatureDigestX962SHA256 = nullptr;
+ SecKeyAlgorithm kSecKeyAlgorithmECDSASignatureDigestX962SHA384 = nullptr;
+ SecKeyAlgorithm kSecKeyAlgorithmECDSASignatureDigestX962SHA512 = nullptr;
+};
+
+base::LazyInstance<SecKeyAPIs>::Leaky g_sec_key_apis =
+ LAZY_INSTANCE_INITIALIZER;
+
+class SSLPlatformKeyCSSM : public ThreadedSSLPrivateKey::Delegate {
public:
- SSLPlatformKeyMac(SSLPrivateKey::Type type,
- size_t max_length,
- SecKeyRef key,
- const CSSM_KEY* cssm_key)
+ SSLPlatformKeyCSSM(SSLPrivateKey::Type type,
+ size_t max_length,
+ SecKeyRef key,
+ const CSSM_KEY* cssm_key)
: type_(type),
max_length_(max_length),
key_(key, base::scoped_policy::RETAIN),
cssm_key_(cssm_key) {}
- ~SSLPlatformKeyMac() override {}
+ ~SSLPlatformKeyCSSM() override {}
SSLPrivateKey::Type GetType() override { return type_; }
std::vector<SSLPrivateKey::Hash> GetDigestPreferences() override {
- static const SSLPrivateKey::Hash kHashes[] = {
+ return std::vector<SSLPrivateKey::Hash>{
SSLPrivateKey::Hash::SHA512, SSLPrivateKey::Hash::SHA384,
SSLPrivateKey::Hash::SHA256, SSLPrivateKey::Hash::SHA1};
- return std::vector<SSLPrivateKey::Hash>(kHashes,
- kHashes + arraysize(kHashes));
}
size_t GetMaxSignatureLengthInBytes() override { return max_length_; }
@@ -206,35 +282,150 @@ class SSLPlatformKeyMac : public ThreadedSSLPrivateKey::Delegate {
base::ScopedCFTypeRef<SecKeyRef> key_;
const CSSM_KEY* cssm_key_;
- DISALLOW_COPY_AND_ASSIGN(SSLPlatformKeyMac);
+ DISALLOW_COPY_AND_ASSIGN(SSLPlatformKeyCSSM);
+};
+
+class SSLPlatformKeySecKey : public ThreadedSSLPrivateKey::Delegate {
+ public:
+ SSLPlatformKeySecKey(SSLPrivateKey::Type type,
+ size_t max_length,
+ SecKeyRef key)
+ : type_(type),
+ max_length_(max_length),
+ key_(key, base::scoped_policy::RETAIN) {}
+
+ ~SSLPlatformKeySecKey() override {}
+
+ SSLPrivateKey::Type GetType() override { return type_; }
+
+ std::vector<SSLPrivateKey::Hash> GetDigestPreferences() override {
+ return std::vector<SSLPrivateKey::Hash>{
+ SSLPrivateKey::Hash::SHA512, SSLPrivateKey::Hash::SHA384,
+ SSLPrivateKey::Hash::SHA256, SSLPrivateKey::Hash::SHA1};
+ }
+
+ size_t GetMaxSignatureLengthInBytes() override { return max_length_; }
+
+ Error SignDigest(SSLPrivateKey::Hash hash,
+ const base::StringPiece& input,
+ std::vector<uint8_t>* signature) override {
+ const SecKeyAPIs& apis = g_sec_key_apis.Get();
+ if (!apis.valid) {
+ LOG(ERROR) << "SecKey APIs not found";
+ return ERR_SSL_CLIENT_AUTH_SIGNATURE_FAILED;
+ }
+
+ SecKeyAlgorithm algorithm = nullptr;
+ if (type_ == SSLPrivateKey::Type::RSA) {
+ switch (hash) {
+ case SSLPrivateKey::Hash::SHA512:
+ algorithm = apis.kSecKeyAlgorithmRSASignatureDigestPKCS1v15SHA512;
+ break;
+ case SSLPrivateKey::Hash::SHA384:
+ algorithm = apis.kSecKeyAlgorithmRSASignatureDigestPKCS1v15SHA384;
+ break;
+ case SSLPrivateKey::Hash::SHA256:
+ algorithm = apis.kSecKeyAlgorithmRSASignatureDigestPKCS1v15SHA256;
+ break;
+ case SSLPrivateKey::Hash::SHA1:
+ algorithm = apis.kSecKeyAlgorithmRSASignatureDigestPKCS1v15SHA1;
+ break;
+ case SSLPrivateKey::Hash::MD5_SHA1:
+ algorithm = apis.kSecKeyAlgorithmRSASignatureDigestPKCS1v15Raw;
+ break;
+ }
+ } else if (SSLPrivateKey::IsECDSAType(type_)) {
+ switch (hash) {
+ case SSLPrivateKey::Hash::SHA512:
+ algorithm = apis.kSecKeyAlgorithmECDSASignatureDigestX962SHA512;
+ break;
+ case SSLPrivateKey::Hash::SHA384:
+ algorithm = apis.kSecKeyAlgorithmECDSASignatureDigestX962SHA384;
+ break;
+ case SSLPrivateKey::Hash::SHA256:
+ algorithm = apis.kSecKeyAlgorithmECDSASignatureDigestX962SHA256;
+ break;
+ case SSLPrivateKey::Hash::SHA1:
+ algorithm = apis.kSecKeyAlgorithmECDSASignatureDigestX962SHA1;
+ break;
+ case SSLPrivateKey::Hash::MD5_SHA1:
+ // MD5-SHA1 is not used with ECDSA.
+ break;
+ }
+ }
+
+ if (!algorithm) {
+ NOTREACHED();
+ return ERR_FAILED;
+ }
+
+ base::ScopedCFTypeRef<CFDataRef> input_ref(CFDataCreateWithBytesNoCopy(
+ kCFAllocatorDefault, reinterpret_cast<const uint8_t*>(input.data()),
+ base::checked_cast<CFIndex>(input.size()), kCFAllocatorNull));
+
+ base::ScopedCFTypeRef<CFErrorRef> error;
+ base::ScopedCFTypeRef<CFDataRef> signature_ref(apis.SecKeyCreateSignature(
+ key_, algorithm, input_ref, error.InitializeInto()));
+ if (!signature_ref) {
+ LOG(ERROR) << error;
+ return ERR_SSL_CLIENT_AUTH_SIGNATURE_FAILED;
+ }
+
+ signature->assign(
+ CFDataGetBytePtr(signature_ref),
+ CFDataGetBytePtr(signature_ref) + CFDataGetLength(signature_ref));
+ return OK;
+ }
+
+ private:
+ SSLPrivateKey::Type type_;
+ size_t max_length_;
+ base::ScopedCFTypeRef<SecKeyRef> key_;
+
+ DISALLOW_COPY_AND_ASSIGN(SSLPlatformKeySecKey);
};
} // namespace
-scoped_refptr<SSLPrivateKey> FetchClientCertPrivateKey(
- X509Certificate* certificate) {
+scoped_refptr<SSLPrivateKey> FetchClientCertPrivateKeyFromKeychain(
+ const X509Certificate* certificate,
+ SecKeychainRef keychain) {
// Look up the private key.
base::ScopedCFTypeRef<SecKeyRef> private_key(
- FetchSecKeyRefForCertificate(certificate));
+ FetchSecKeyRefForCertificate(certificate, keychain));
if (!private_key)
return nullptr;
- const CSSM_KEY* cssm_key;
- OSStatus status = SecKeyGetCSSMKey(private_key.get(), &cssm_key);
- if (status != noErr)
- return nullptr;
-
SSLPrivateKey::Type key_type;
size_t max_length;
if (!GetClientCertInfo(certificate, &key_type, &max_length))
return nullptr;
+ if (base::mac::IsAtLeastOS10_12()) {
+ return make_scoped_refptr(
+ new ThreadedSSLPrivateKey(base::MakeUnique<SSLPlatformKeySecKey>(
+ key_type, max_length, private_key.get()),
+ GetSSLPlatformKeyTaskRunner()));
+ }
+
+ const CSSM_KEY* cssm_key;
+ OSStatus status = SecKeyGetCSSMKey(private_key.get(), &cssm_key);
+ if (status != noErr) {
+ OSSTATUS_LOG(WARNING, status);
+ return nullptr;
+ }
+
return make_scoped_refptr(new ThreadedSSLPrivateKey(
- base::MakeUnique<SSLPlatformKeyMac>(key_type, max_length,
- private_key.get(), cssm_key),
+ base::MakeUnique<SSLPlatformKeyCSSM>(key_type, max_length,
+ private_key.get(), cssm_key),
GetSSLPlatformKeyTaskRunner()));
}
+scoped_refptr<SSLPrivateKey> FetchClientCertPrivateKey(
+ const X509Certificate* certificate) {
+ return FetchClientCertPrivateKeyFromKeychain(certificate, nullptr);
+}
+
#pragma clang diagnostic pop // "-Wdeprecated-declarations"
} // namespace net
diff --git a/chromium/net/ssl/ssl_platform_key_mac.h b/chromium/net/ssl/ssl_platform_key_mac.h
new file mode 100644
index 00000000000..71a2316ebd3
--- /dev/null
+++ b/chromium/net/ssl/ssl_platform_key_mac.h
@@ -0,0 +1,27 @@
+// Copyright 2016 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.
+
+#ifndef NET_SSL_SSL_PLATFORM_KEY_MAC_H_
+#define NET_SSL_SSL_PLATFORM_KEY_MAC_H_
+
+#include <Security/SecBase.h>
+
+#include "base/memory/ref_counted.h"
+#include "net/base/net_export.h"
+
+namespace net {
+
+class SSLPrivateKey;
+class X509Certificate;
+
+// Returns an SSLPrivateKey backed by the platform private key in |keychain|
+// that corresponds to |certificate|'s public key. If |keychain| is nullptr, the
+// user's default search list is used instead.
+NET_EXPORT_PRIVATE scoped_refptr<SSLPrivateKey>
+FetchClientCertPrivateKeyFromKeychain(const X509Certificate* certificate,
+ SecKeychainRef keychain);
+
+} // namespace net
+
+#endif // NET_SSL_SSL_PLATFORM_KEY_MAC_H_
diff --git a/chromium/net/ssl/ssl_platform_key_mac_unittest.cc b/chromium/net/ssl/ssl_platform_key_mac_unittest.cc
new file mode 100644
index 00000000000..9207dedb086
--- /dev/null
+++ b/chromium/net/ssl/ssl_platform_key_mac_unittest.cc
@@ -0,0 +1,137 @@
+// Copyright 2016 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.
+
+#include "net/ssl/ssl_platform_key_mac.h"
+
+#include <CoreFoundation/CoreFoundation.h>
+#include <Security/SecCertificate.h>
+#include <Security/SecImportExport.h>
+#include <Security/SecKeychain.h>
+
+#include <string>
+
+#include "base/files/file_path.h"
+#include "base/files/file_util.h"
+#include "base/files/scoped_temp_dir.h"
+#include "base/mac/scoped_cftyperef.h"
+#include "base/memory/ref_counted.h"
+#include "net/ssl/ssl_private_key.h"
+#include "net/ssl/ssl_private_key_test_util.h"
+#include "net/test/cert_test_util.h"
+#include "net/test/test_data_directory.h"
+#include "testing/gtest/include/gtest/gtest.h"
+#include "third_party/boringssl/src/include/openssl/bytestring.h"
+#include "third_party/boringssl/src/include/openssl/ec_key.h"
+#include "third_party/boringssl/src/include/openssl/evp.h"
+#include "third_party/boringssl/src/include/openssl/mem.h"
+#include "third_party/boringssl/src/include/openssl/rsa.h"
+
+namespace net {
+
+namespace {
+
+struct TestKey {
+ const char* cert_file;
+ const char* key_file;
+ SSLPrivateKey::Type key_type;
+};
+
+const TestKey kTestKeys[] = {
+ {"client_1.pem", "client_1.pk8", SSLPrivateKey::Type::RSA},
+ {"client_4.pem", "client_4.pk8", SSLPrivateKey::Type::ECDSA_P256},
+ {"client_5.pem", "client_5.pk8", SSLPrivateKey::Type::ECDSA_P384},
+ {"client_6.pem", "client_6.pk8", SSLPrivateKey::Type::ECDSA_P521},
+};
+
+std::string TestKeyToString(const testing::TestParamInfo<TestKey>& params) {
+ return SSLPrivateKeyTypeToString(params.param.key_type);
+}
+
+} // namespace
+
+class SSLPlatformKeyMacTest : public testing::TestWithParam<TestKey> {};
+
+TEST_P(SSLPlatformKeyMacTest, KeyMatches) {
+ const TestKey& test_key = GetParam();
+
+ // Load test data.
+ scoped_refptr<X509Certificate> cert =
+ ImportCertFromFile(GetTestCertsDirectory(), test_key.cert_file);
+ ASSERT_TRUE(cert);
+
+ std::string pkcs8;
+ base::FilePath pkcs8_path =
+ GetTestCertsDirectory().AppendASCII(test_key.key_file);
+ ASSERT_TRUE(base::ReadFileToString(pkcs8_path, &pkcs8));
+
+ // Create a temporary keychain.
+ base::ScopedTempDir keychain_dir;
+ ASSERT_TRUE(keychain_dir.CreateUniqueTempDir());
+ base::FilePath keychain_path =
+ keychain_dir.GetPath().AppendASCII("test_keychain.keychain");
+ base::ScopedCFTypeRef<SecKeychainRef> keychain;
+ ASSERT_EQ(noErr,
+ SecKeychainCreate(keychain_path.value().c_str(), 0, "", FALSE,
+ nullptr, keychain.InitializeInto()));
+
+ // Insert the certificate into the keychain.
+ ASSERT_EQ(noErr,
+ SecCertificateAddToKeychain(cert->os_cert_handle(), keychain));
+
+ // Import the key into the keychain. Apple doesn't accept unencrypted PKCS#8,
+ // but it accepts the low-level RSAPrivateKey and ECPrivateKey types as
+ // "kSecFormatOpenSSL", so produce those. There doesn't appear to be a way to
+ // tell it which key type we have, so leave this unspecified and have it
+ // guess.
+ CBS cbs;
+ CBS_init(&cbs, reinterpret_cast<const uint8_t*>(pkcs8.data()), pkcs8.size());
+ bssl::UniquePtr<EVP_PKEY> openssl_key(EVP_parse_private_key(&cbs));
+ ASSERT_TRUE(openssl_key);
+ EXPECT_EQ(0u, CBS_len(&cbs));
+
+ bssl::ScopedCBB cbb;
+ ASSERT_TRUE(CBB_init(cbb.get(), 0));
+ if (EVP_PKEY_id(openssl_key.get()) == EVP_PKEY_RSA) {
+ ASSERT_TRUE(RSA_marshal_private_key(cbb.get(),
+ EVP_PKEY_get0_RSA(openssl_key.get())));
+ } else if (EVP_PKEY_id(openssl_key.get()) == EVP_PKEY_EC) {
+ ASSERT_TRUE(EC_KEY_marshal_private_key(
+ cbb.get(), EVP_PKEY_get0_EC_KEY(openssl_key.get()), 0));
+ } else {
+ ASSERT_TRUE(false);
+ }
+
+ uint8_t* encoded;
+ size_t encoded_len;
+ ASSERT_TRUE(CBB_finish(cbb.get(), &encoded, &encoded_len));
+ bssl::UniquePtr<uint8_t> scoped_encoded(encoded);
+
+ base::ScopedCFTypeRef<CFDataRef> encoded_ref(CFDataCreateWithBytesNoCopy(
+ kCFAllocatorDefault, encoded, encoded_len, kCFAllocatorNull));
+ SecExternalFormat format = kSecFormatOpenSSL;
+ SecExternalItemType item_type = kSecItemTypePrivateKey;
+ ASSERT_EQ(noErr, SecItemImport(encoded_ref, nullptr, &format, &item_type, 0,
+ nullptr, keychain, nullptr));
+
+ // Finally, test the code to look up the key.
+ scoped_refptr<SSLPrivateKey> key =
+ FetchClientCertPrivateKeyFromKeychain(cert.get(), keychain);
+ ASSERT_TRUE(key);
+
+ // All Mac keys are expected to have the same hash preferences.
+ std::vector<SSLPrivateKey::Hash> expected_hashes = {
+ SSLPrivateKey::Hash::SHA512, SSLPrivateKey::Hash::SHA384,
+ SSLPrivateKey::Hash::SHA256, SSLPrivateKey::Hash::SHA1,
+ };
+ EXPECT_EQ(expected_hashes, key->GetDigestPreferences());
+
+ TestSSLPrivateKeyMatches(key.get(), pkcs8);
+}
+
+INSTANTIATE_TEST_CASE_P(,
+ SSLPlatformKeyMacTest,
+ testing::ValuesIn(kTestKeys),
+ TestKeyToString);
+
+} // namespace net
diff --git a/chromium/net/ssl/ssl_platform_key_nss.cc b/chromium/net/ssl/ssl_platform_key_nss.cc
index b15239efb4f..447b230e22b 100644
--- a/chromium/net/ssl/ssl_platform_key_nss.cc
+++ b/chromium/net/ssl/ssl_platform_key_nss.cc
@@ -159,7 +159,7 @@ class SSLPlatformKeyNSS : public ThreadedSSLPrivateKey::Delegate {
} // namespace
scoped_refptr<SSLPrivateKey> FetchClientCertPrivateKey(
- X509Certificate* certificate) {
+ const X509Certificate* certificate) {
crypto::ScopedSECKEYPrivateKey key(
PK11_FindKeyByAnyCert(certificate->os_cert_handle(), nullptr));
if (!key) {
diff --git a/chromium/net/ssl/ssl_platform_key_nss_unittest.cc b/chromium/net/ssl/ssl_platform_key_nss_unittest.cc
new file mode 100644
index 00000000000..350c46273b7
--- /dev/null
+++ b/chromium/net/ssl/ssl_platform_key_nss_unittest.cc
@@ -0,0 +1,141 @@
+// Copyright 2016 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.
+
+#include "net/ssl/ssl_platform_key.h"
+
+#include <keyhi.h>
+#include <pk11pub.h>
+#include <stdint.h>
+#include <string.h>
+
+#include <memory>
+#include <string>
+#include <vector>
+
+#include "base/files/file_path.h"
+#include "base/files/file_util.h"
+#include "base/memory/ref_counted.h"
+#include "crypto/ec_private_key.h"
+#include "crypto/scoped_nss_types.h"
+#include "crypto/scoped_test_nss_db.h"
+#include "net/ssl/ssl_private_key.h"
+#include "net/ssl/ssl_private_key_test_util.h"
+#include "net/test/cert_test_util.h"
+#include "net/test/test_data_directory.h"
+#include "testing/gtest/include/gtest/gtest.h"
+#include "third_party/boringssl/src/include/openssl/bytestring.h"
+#include "third_party/boringssl/src/include/openssl/ec.h"
+#include "third_party/boringssl/src/include/openssl/ec_key.h"
+#include "third_party/boringssl/src/include/openssl/evp.h"
+#include "third_party/boringssl/src/include/openssl/mem.h"
+
+namespace net {
+
+namespace {
+
+struct TestKey {
+ const char* cert_file;
+ const char* key_file;
+ SSLPrivateKey::Type key_type;
+};
+
+const TestKey kTestKeys[] = {
+ {"client_1.pem", "client_1.pk8", SSLPrivateKey::Type::RSA},
+ {"client_4.pem", "client_4.pk8", SSLPrivateKey::Type::ECDSA_P256},
+ {"client_5.pem", "client_5.pk8", SSLPrivateKey::Type::ECDSA_P384},
+ {"client_6.pem", "client_6.pk8", SSLPrivateKey::Type::ECDSA_P521},
+};
+
+std::string TestKeyToString(const testing::TestParamInfo<TestKey>& params) {
+ return SSLPrivateKeyTypeToString(params.param.key_type);
+}
+
+} // namespace
+
+class SSLPlatformKeyNSSTest : public testing::TestWithParam<TestKey> {};
+
+TEST_P(SSLPlatformKeyNSSTest, KeyMatches) {
+ const TestKey& test_key = GetParam();
+
+ std::string pkcs8;
+ base::FilePath pkcs8_path =
+ GetTestCertsDirectory().AppendASCII(test_key.key_file);
+ ASSERT_TRUE(base::ReadFileToString(pkcs8_path, &pkcs8));
+
+ // Import the key into a test NSS database.
+ crypto::ScopedTestNSSDB test_db;
+ scoped_refptr<X509Certificate> cert;
+ if (SSLPrivateKey::IsECDSAType(test_key.key_type)) {
+ // NSS cannot import unencrypted ECDSA keys, so we encrypt it with an empty
+ // password and import manually.
+ std::vector<uint8_t> pkcs8_vector(pkcs8.begin(), pkcs8.end());
+ std::unique_ptr<crypto::ECPrivateKey> ec_private_key =
+ crypto::ECPrivateKey::CreateFromPrivateKeyInfo(pkcs8_vector);
+ ASSERT_TRUE(ec_private_key);
+ std::vector<uint8_t> encrypted;
+ ASSERT_TRUE(ec_private_key->ExportEncryptedPrivateKey(&encrypted));
+
+ SECItem encrypted_item = {siBuffer, encrypted.data(),
+ static_cast<unsigned>(encrypted.size())};
+ SECKEYEncryptedPrivateKeyInfo epki;
+ memset(&epki, 0, sizeof(epki));
+ crypto::ScopedPLArenaPool arena(PORT_NewArena(DER_DEFAULT_CHUNKSIZE));
+ ASSERT_EQ(SECSuccess,
+ SEC_QuickDERDecodeItem(
+ arena.get(), &epki,
+ SEC_ASN1_GET(SECKEY_EncryptedPrivateKeyInfoTemplate),
+ &encrypted_item));
+
+ // NSS uses the serialized public key in X9.62 form as the "public value"
+ // for key ID purposes.
+ bssl::ScopedCBB cbb;
+ ASSERT_TRUE(CBB_init(cbb.get(), 0));
+ EC_KEY* ec_key = EVP_PKEY_get0_EC_KEY(ec_private_key->key());
+ ASSERT_TRUE(EC_POINT_point2cbb(cbb.get(), EC_KEY_get0_group(ec_key),
+ EC_KEY_get0_public_key(ec_key),
+ POINT_CONVERSION_UNCOMPRESSED, nullptr));
+ uint8_t* public_value;
+ size_t public_value_len;
+ ASSERT_TRUE(CBB_finish(cbb.get(), &public_value, &public_value_len));
+ bssl::UniquePtr<uint8_t> scoped_public_value(public_value);
+ SECItem public_item = {siBuffer, public_value,
+ static_cast<unsigned>(public_value_len)};
+
+ SECItem password_item = {siBuffer, nullptr, 0};
+ ASSERT_EQ(SECSuccess,
+ PK11_ImportEncryptedPrivateKeyInfo(
+ test_db.slot(), &epki, &password_item, nullptr /* nickname */,
+ &public_item, PR_TRUE /* permanent */, PR_TRUE /* private */,
+ ecKey, KU_DIGITAL_SIGNATURE, nullptr /* wincx */));
+
+ cert = ImportCertFromFile(GetTestCertsDirectory(), test_key.cert_file);
+ ASSERT_TRUE(cert);
+ ASSERT_TRUE(ImportClientCertToSlot(cert, test_db.slot()));
+ } else {
+ cert = ImportClientCertAndKeyFromFile(GetTestCertsDirectory(),
+ test_key.cert_file, test_key.key_file,
+ test_db.slot());
+ ASSERT_TRUE(cert);
+ }
+
+ // Look up the key.
+ scoped_refptr<SSLPrivateKey> key = FetchClientCertPrivateKey(cert.get());
+ ASSERT_TRUE(key);
+
+ // All NSS keys are expected to have the same hash preferences.
+ std::vector<SSLPrivateKey::Hash> expected_hashes = {
+ SSLPrivateKey::Hash::SHA512, SSLPrivateKey::Hash::SHA384,
+ SSLPrivateKey::Hash::SHA256, SSLPrivateKey::Hash::SHA1,
+ };
+ EXPECT_EQ(expected_hashes, key->GetDigestPreferences());
+
+ TestSSLPrivateKeyMatches(key.get(), pkcs8);
+}
+
+INSTANTIATE_TEST_CASE_P(,
+ SSLPlatformKeyNSSTest,
+ testing::ValuesIn(kTestKeys),
+ TestKeyToString);
+
+} // namespace net
diff --git a/chromium/net/ssl/ssl_platform_key_util.cc b/chromium/net/ssl/ssl_platform_key_util.cc
index 3e6469831ec..39af9eb6eba 100644
--- a/chromium/net/ssl/ssl_platform_key_util.cc
+++ b/chromium/net/ssl/ssl_platform_key_util.cc
@@ -71,7 +71,8 @@ bool GetClientCertInfo(const X509Certificate* certificate,
return false;
}
- switch (EVP_PKEY_id(key.get())) {
+ int key_type = EVP_PKEY_id(key.get());
+ switch (key_type) {
case EVP_PKEY_RSA:
*out_type = SSLPrivateKey::Type::RSA;
break;
@@ -87,15 +88,17 @@ bool GetClientCertInfo(const X509Certificate* certificate,
*out_type = SSLPrivateKey::Type::ECDSA_P384;
break;
case NID_secp521r1:
- *out_type = SSLPrivateKey::Type::ECDSA_P384;
+ *out_type = SSLPrivateKey::Type::ECDSA_P521;
break;
default:
+ LOG(ERROR) << "Unsupported curve type " << curve;
return false;
}
break;
}
default:
+ LOG(ERROR) << "Unsupported key type " << key_type;
return false;
}
diff --git a/chromium/net/ssl/ssl_platform_key_util_unittest.cc b/chromium/net/ssl/ssl_platform_key_util_unittest.cc
index 1e7b9d3d548..8a00034fecb 100644
--- a/chromium/net/ssl/ssl_platform_key_util_unittest.cc
+++ b/chromium/net/ssl/ssl_platform_key_util_unittest.cc
@@ -31,6 +31,10 @@ bool GetClientCertInfoFromFile(const char* filename,
return GetClientCertInfo(cert.get(), out_type, out_max_length);
}
+size_t BitsToBytes(size_t bits) {
+ return (bits + 7) / 8;
+}
+
} // namespace
TEST(SSLPlatformKeyUtil, GetClientCertInfo) {
@@ -43,7 +47,15 @@ TEST(SSLPlatformKeyUtil, GetClientCertInfo) {
ASSERT_TRUE(GetClientCertInfoFromFile("client_4.pem", &type, &max_length));
EXPECT_EQ(SSLPrivateKey::Type::ECDSA_P256, type);
- EXPECT_EQ(ECDSA_SIG_max_len(256u / 8u), max_length);
+ EXPECT_EQ(ECDSA_SIG_max_len(BitsToBytes(256)), max_length);
+
+ ASSERT_TRUE(GetClientCertInfoFromFile("client_5.pem", &type, &max_length));
+ EXPECT_EQ(SSLPrivateKey::Type::ECDSA_P384, type);
+ EXPECT_EQ(ECDSA_SIG_max_len(BitsToBytes(384)), max_length);
+
+ ASSERT_TRUE(GetClientCertInfoFromFile("client_6.pem", &type, &max_length));
+ EXPECT_EQ(SSLPrivateKey::Type::ECDSA_P521, type);
+ EXPECT_EQ(ECDSA_SIG_max_len(BitsToBytes(521)), max_length);
}
} // namespace net
diff --git a/chromium/net/ssl/ssl_platform_key_win.cc b/chromium/net/ssl/ssl_platform_key_win.cc
index e0b1b9e7ef6..f325a45a9d9 100644
--- a/chromium/net/ssl/ssl_platform_key_win.cc
+++ b/chromium/net/ssl/ssl_platform_key_win.cc
@@ -248,7 +248,7 @@ class SSLPlatformKeyCNG : public ThreadedSSLPrivateKey::Delegate {
} // namespace
scoped_refptr<SSLPrivateKey> FetchClientCertPrivateKey(
- X509Certificate* certificate) {
+ const X509Certificate* certificate) {
// Rather than query the private key for metadata, extract the public key from
// the certificate without using Windows APIs. CAPI and CNG do not
// consistently work depending on the system. See https://crbug.com/468345.
diff --git a/chromium/net/ssl/ssl_private_key_test_util.cc b/chromium/net/ssl/ssl_private_key_test_util.cc
new file mode 100644
index 00000000000..ddeaca7cd31
--- /dev/null
+++ b/chromium/net/ssl/ssl_private_key_test_util.cc
@@ -0,0 +1,221 @@
+// Copyright 2016 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.
+
+#include "net/ssl/ssl_private_key_test_util.h"
+
+#include <stdint.h>
+
+#include <vector>
+
+#include "base/bind.h"
+#include "base/location.h"
+#include "base/logging.h"
+#include "base/run_loop.h"
+#include "base/strings/string_util.h"
+#include "crypto/openssl_util.h"
+#include "net/base/net_errors.h"
+#include "net/ssl/ssl_private_key.h"
+#include "net/test/gtest_util.h"
+#include "testing/gtest/include/gtest/gtest.h"
+#include "third_party/boringssl/src/include/openssl/bytestring.h"
+#include "third_party/boringssl/src/include/openssl/digest.h"
+#include "third_party/boringssl/src/include/openssl/ec.h"
+#include "third_party/boringssl/src/include/openssl/ec_key.h"
+#include "third_party/boringssl/src/include/openssl/evp.h"
+
+using net::test::IsOk;
+
+namespace net {
+
+namespace {
+
+const char* HashToString(SSLPrivateKey::Hash hash) {
+ switch (hash) {
+ case SSLPrivateKey::Hash::MD5_SHA1:
+ return "MD5_SHA1";
+ case SSLPrivateKey::Hash::SHA1:
+ return "SHA1";
+ case SSLPrivateKey::Hash::SHA256:
+ return "SHA256";
+ case SSLPrivateKey::Hash::SHA384:
+ return "SHA384";
+ case SSLPrivateKey::Hash::SHA512:
+ return "SHA512";
+ }
+
+ NOTREACHED();
+ return "";
+}
+
+const EVP_MD* HashToMD(SSLPrivateKey::Hash hash) {
+ switch (hash) {
+ case SSLPrivateKey::Hash::MD5_SHA1:
+ return EVP_md5_sha1();
+ case SSLPrivateKey::Hash::SHA1:
+ return EVP_sha1();
+ case SSLPrivateKey::Hash::SHA256:
+ return EVP_sha256();
+ case SSLPrivateKey::Hash::SHA384:
+ return EVP_sha384();
+ case SSLPrivateKey::Hash::SHA512:
+ return EVP_sha512();
+ }
+
+ NOTREACHED();
+ return nullptr;
+}
+
+SSLPrivateKey::Type TypeForOpenSSLKey(EVP_PKEY* pkey) {
+ switch (EVP_PKEY_id(pkey)) {
+ case EVP_PKEY_RSA:
+ return SSLPrivateKey::Type::RSA;
+ case EVP_PKEY_EC: {
+ switch (EC_GROUP_get_curve_name(
+ EC_KEY_get0_group(EVP_PKEY_get0_EC_KEY(pkey)))) {
+ case NID_X9_62_prime256v1:
+ return SSLPrivateKey::Type::ECDSA_P256;
+ case NID_secp384r1:
+ return SSLPrivateKey::Type::ECDSA_P384;
+ case NID_secp521r1:
+ return SSLPrivateKey::Type::ECDSA_P521;
+ }
+ }
+ }
+
+ NOTREACHED();
+ return SSLPrivateKey::Type::RSA;
+}
+
+// Resize a string to |size| bytes of data, then return its data buffer address
+// cast as an 'uint8_t*', as expected by OpenSSL functions.
+// |str| the target string.
+// |size| the number of bytes to write into the string.
+// Return the string's new buffer in memory, as an 'uint8_t*' pointer.
+uint8_t* OpenSSLWriteInto(std::string* str, size_t size) {
+ return reinterpret_cast<uint8_t*>(base::WriteInto(str, size + 1));
+}
+
+bool VerifyWithOpenSSL(const EVP_MD* md,
+ const base::StringPiece& digest,
+ EVP_PKEY* key,
+ const base::StringPiece& signature) {
+ bssl::UniquePtr<EVP_PKEY_CTX> ctx(EVP_PKEY_CTX_new(key, nullptr));
+ if (!ctx || !EVP_PKEY_verify_init(ctx.get()) ||
+ !EVP_PKEY_CTX_set_signature_md(ctx.get(), md) ||
+ !EVP_PKEY_verify(
+ ctx.get(), reinterpret_cast<const uint8_t*>(signature.data()),
+ signature.size(), reinterpret_cast<const uint8_t*>(digest.data()),
+ digest.size())) {
+ return false;
+ }
+
+ return true;
+}
+
+bool SignWithOpenSSL(const EVP_MD* md,
+ const base::StringPiece& digest,
+ EVP_PKEY* key,
+ std::string* result) {
+ size_t sig_len = EVP_PKEY_size(key);
+ bssl::UniquePtr<EVP_PKEY_CTX> ctx(EVP_PKEY_CTX_new(key, nullptr));
+ if (!ctx || !EVP_PKEY_sign_init(ctx.get()) ||
+ !EVP_PKEY_CTX_set_signature_md(ctx.get(), md) ||
+ !EVP_PKEY_sign(ctx.get(), OpenSSLWriteInto(result, sig_len), &sig_len,
+ reinterpret_cast<const uint8_t*>(digest.data()),
+ digest.size())) {
+ return false;
+ }
+
+ result->resize(sig_len);
+ return true;
+}
+
+void OnSignComplete(base::RunLoop* loop,
+ Error* out_error,
+ std::string* out_signature,
+ Error error,
+ const std::vector<uint8_t>& signature) {
+ *out_error = error;
+ out_signature->assign(signature.begin(), signature.end());
+ loop->Quit();
+}
+
+Error DoKeySigningWithWrapper(SSLPrivateKey* key,
+ SSLPrivateKey::Hash hash,
+ const base::StringPiece& message,
+ std::string* result) {
+ Error error;
+ base::RunLoop loop;
+ key->SignDigest(
+ hash, message,
+ base::Bind(OnSignComplete, base::Unretained(&loop),
+ base::Unretained(&error), base::Unretained(result)));
+ loop.Run();
+ return error;
+}
+
+} // namespace
+
+const char* SSLPrivateKeyTypeToString(SSLPrivateKey::Type type) {
+ switch (type) {
+ case SSLPrivateKey::Type::RSA:
+ return "RSA";
+ case SSLPrivateKey::Type::ECDSA_P256:
+ return "ECDSA_P256";
+ case SSLPrivateKey::Type::ECDSA_P384:
+ return "ECDSA_P384";
+ case SSLPrivateKey::Type::ECDSA_P521:
+ return "ECDSA_P521";
+ }
+
+ NOTREACHED();
+ return "";
+}
+
+void TestSSLPrivateKeyMatches(SSLPrivateKey* key, const std::string& pkcs8) {
+ crypto::OpenSSLErrStackTracer err_tracer(FROM_HERE);
+
+ // Create the equivalent OpenSSL key.
+ CBS cbs;
+ CBS_init(&cbs, reinterpret_cast<const uint8_t*>(pkcs8.data()), pkcs8.size());
+ bssl::UniquePtr<EVP_PKEY> openssl_key(EVP_parse_private_key(&cbs));
+ ASSERT_TRUE(openssl_key);
+ EXPECT_EQ(0u, CBS_len(&cbs));
+
+ // Check the length and type matches.
+ EXPECT_EQ(TypeForOpenSSLKey(openssl_key.get()), key->GetType());
+ EXPECT_EQ(static_cast<size_t>(EVP_PKEY_size(openssl_key.get())),
+ key->GetMaxSignatureLengthInBytes());
+
+ // Test all supported hash algorithms.
+ std::vector<SSLPrivateKey::Hash> hashes = key->GetDigestPreferences();
+
+ // To support TLS 1.1 and earlier, RSA keys must implicitly support MD5-SHA1,
+ // despite not being advertised.
+ if (key->GetType() == SSLPrivateKey::Type::RSA)
+ hashes.push_back(SSLPrivateKey::Hash::MD5_SHA1);
+
+ for (SSLPrivateKey::Hash hash : hashes) {
+ SCOPED_TRACE(HashToString(hash));
+ const EVP_MD* md = HashToMD(hash);
+
+ std::string digest(EVP_MD_size(md), 'a');
+
+ // Test the key generates valid signatures.
+ std::string signature;
+ Error error = DoKeySigningWithWrapper(key, hash, digest, &signature);
+ EXPECT_THAT(error, IsOk());
+ EXPECT_TRUE(VerifyWithOpenSSL(md, digest, openssl_key.get(), signature));
+
+ // RSA signing is deterministic, so further check the signature matches.
+ if (key->GetType() == SSLPrivateKey::Type::RSA) {
+ std::string openssl_signature;
+ ASSERT_TRUE(
+ SignWithOpenSSL(md, digest, openssl_key.get(), &openssl_signature));
+ EXPECT_EQ(openssl_signature, signature);
+ }
+ }
+}
+
+} // namespace net
diff --git a/chromium/net/ssl/ssl_private_key_test_util.h b/chromium/net/ssl/ssl_private_key_test_util.h
new file mode 100644
index 00000000000..ff922f7cad5
--- /dev/null
+++ b/chromium/net/ssl/ssl_private_key_test_util.h
@@ -0,0 +1,24 @@
+// Copyright 2016 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.
+
+#ifndef NET_SSL_SSL_PRIVATE_KEY_TEST_UTIL_H_
+#define NET_SSL_SSL_PRIVATE_KEY_TEST_UTIL_H_
+
+#include <string>
+
+#include "net/ssl/ssl_private_key.h"
+
+namespace net {
+
+const char* SSLPrivateKeyTypeToString(SSLPrivateKey::Type type);
+
+// Tests that |key| matches the private key serialized in |pkcs8|. It checks the
+// reported type and key size are correct, and then it tests all advertised
+// signature algorithms align with |pkcs8|. It does not test unadvertised
+// algorithms, so the caller must check this list is as expected.
+void TestSSLPrivateKeyMatches(SSLPrivateKey* key, const std::string& pkcs8);
+
+} // namespace net
+
+#endif // NET_SSL_SSL_PRIVATE_KEY_TEST_UTIL_H_
diff --git a/chromium/net/ssl/test_ssl_private_key.h b/chromium/net/ssl/test_ssl_private_key.h
index 15e4f91bad4..8508b77aaf5 100644
--- a/chromium/net/ssl/test_ssl_private_key.h
+++ b/chromium/net/ssl/test_ssl_private_key.h
@@ -2,8 +2,8 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#ifndef NET_SSL_TEST_SSL_PLATFORM_KEY_H_
-#define NET_SSL_TEST_SSL_PLATFORM_KEY_H_
+#ifndef NET_SSL_TEST_SSL_PRIVATE_KEY_H_
+#define NET_SSL_TEST_SSL_PRIVATE_KEY_H_
#include "base/memory/ref_counted.h"
#include "net/base/net_export.h"
@@ -20,4 +20,4 @@ NET_EXPORT scoped_refptr<SSLPrivateKey> WrapOpenSSLPrivateKey(
} // namespace net
-#endif // NET_SSL_TEST_SSL_PLATFORM_KEY_H_
+#endif // NET_SSL_TEST_SSL_PRIVATE_KEY_H_
diff --git a/chromium/net/test/cert_test_util.h b/chromium/net/test/cert_test_util.h
index 219ccd87257..f948bd8b06c 100644
--- a/chromium/net/test/cert_test_util.h
+++ b/chromium/net/test/cert_test_util.h
@@ -20,10 +20,6 @@ namespace base {
class FilePath;
}
-namespace crypto {
-class RSAPrivateKey;
-}
-
namespace net {
class EVRootCAMetadata;
diff --git a/chromium/net/test/ct_test_util.h b/chromium/net/test/ct_test_util.h
index 7a52becfce1..d39079690ad 100644
--- a/chromium/net/test/ct_test_util.h
+++ b/chromium/net/test/ct_test_util.h
@@ -2,8 +2,8 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#ifndef NET_CERT_CT_TEST_UTIL_H_
-#define NET_CERT_CT_TEST_UTIL_H_
+#ifndef NET_TEST_CT_TEST_UTIL_H_
+#define NET_TEST_CT_TEST_UTIL_H_
#include <stddef.h>
#include <stdint.h>
@@ -132,4 +132,4 @@ bool CheckForSCTOrigin(const SignedCertificateTimestampAndStatusList& scts,
} // namespace net
-#endif // NET_CERT_CT_TEST_UTIL_H_
+#endif // NET_TEST_CT_TEST_UTIL_H_
diff --git a/chromium/net/test/embedded_test_server/embedded_test_server.cc b/chromium/net/test/embedded_test_server/embedded_test_server.cc
index 7f861d674c0..0f89bd9c9e4 100644
--- a/chromium/net/test/embedded_test_server/embedded_test_server.cc
+++ b/chromium/net/test/embedded_test_server/embedded_test_server.cc
@@ -23,6 +23,7 @@
#include "crypto/rsa_private_key.h"
#include "net/base/ip_endpoint.h"
#include "net/base/net_errors.h"
+#include "net/base/port_util.h"
#include "net/cert/pem_tokenizer.h"
#include "net/cert/test_root_certs.h"
#include "net/log/net_log_source.h"
@@ -92,21 +93,38 @@ bool EmbeddedTestServer::Start() {
bool EmbeddedTestServer::InitializeAndListen() {
DCHECK(!Started());
- listen_socket_.reset(new TCPServerSocket(nullptr, NetLogSource()));
+ const int max_tries = 5;
+ int num_tries = 0;
+ bool is_valid_port = false;
- int result = listen_socket_->ListenWithAddressAndPort("127.0.0.1", 0, 10);
- if (result) {
- LOG(ERROR) << "Listen failed: " << ErrorToString(result);
- listen_socket_.reset();
- return false;
- }
+ do {
+ if (++num_tries > max_tries) {
+ LOG(ERROR) << "Failed to listen on a valid port after " << max_tries
+ << " attempts.";
+ listen_socket_.reset();
+ return false;
+ }
- result = listen_socket_->GetLocalAddress(&local_endpoint_);
- if (result != OK) {
- LOG(ERROR) << "GetLocalAddress failed: " << ErrorToString(result);
- listen_socket_.reset();
- return false;
- }
+ listen_socket_.reset(new TCPServerSocket(nullptr, NetLogSource()));
+
+ int result = listen_socket_->ListenWithAddressAndPort("127.0.0.1", 0, 10);
+ if (result) {
+ LOG(ERROR) << "Listen failed: " << ErrorToString(result);
+ listen_socket_.reset();
+ return false;
+ }
+
+ result = listen_socket_->GetLocalAddress(&local_endpoint_);
+ if (result != OK) {
+ LOG(ERROR) << "GetLocalAddress failed: " << ErrorToString(result);
+ listen_socket_.reset();
+ return false;
+ }
+
+ port_ = local_endpoint_.port();
+ is_valid_port |= net::IsPortAllowedForScheme(
+ port_, is_using_ssl_ ? url::kHttpsScheme : url::kHttpScheme);
+ } while (!is_valid_port);
if (is_using_ssl_) {
base_url_ = GURL("https://" + local_endpoint_.ToString());
@@ -117,7 +135,6 @@ bool EmbeddedTestServer::InitializeAndListen() {
} else {
base_url_ = GURL("http://" + local_endpoint_.ToString());
}
- port_ = local_endpoint_.port();
listen_socket_->DetachFromThread();
@@ -177,6 +194,7 @@ void EmbeddedTestServer::ShutdownOnIOThread() {
void EmbeddedTestServer::HandleRequest(HttpConnection* connection,
std::unique_ptr<HttpRequest> request) {
DCHECK(io_thread_->task_runner()->BelongsToCurrentThread());
+ request->base_url = base_url_;
for (const auto& monitor : request_monitors_)
monitor.Run(*request);
@@ -297,22 +315,22 @@ void EmbeddedTestServer::AddDefaultHandlers(const base::FilePath& directory) {
void EmbeddedTestServer::RegisterRequestHandler(
const HandleRequestCallback& callback) {
- // TODO(svaldez): Add check to prevent RegisterRequestHandler from being
- // called after the server has started. https://crbug.com/546060
+ DCHECK(!io_thread_.get())
+ << "Handlers must be registered before starting the server.";
request_handlers_.push_back(callback);
}
void EmbeddedTestServer::RegisterRequestMonitor(
const MonitorRequestCallback& callback) {
- // TODO(svaldez): Add check to prevent RegisterRequestMonitor from being
- // called after the server has started. https://crbug.com/546060
+ DCHECK(!io_thread_.get())
+ << "Monitors must be registered before starting the server.";
request_monitors_.push_back(callback);
}
void EmbeddedTestServer::RegisterDefaultHandler(
const HandleRequestCallback& callback) {
- // TODO(svaldez): Add check to prevent RegisterDefaultHandler from being
- // called after the server has started. https://crbug.com/546060
+ DCHECK(!io_thread_.get())
+ << "Handlers must be registered before starting the server.";
default_request_handlers_.push_back(callback);
}
diff --git a/chromium/net/test/embedded_test_server/embedded_test_server.h b/chromium/net/test/embedded_test_server/embedded_test_server.h
index bc34d0a3f01..f2a93072720 100644
--- a/chromium/net/test/embedded_test_server/embedded_test_server.h
+++ b/chromium/net/test/embedded_test_server/embedded_test_server.h
@@ -205,16 +205,21 @@ class EmbeddedTestServer {
// The most general purpose method. Any request processing can be added using
// this method. Takes ownership of the object. The |callback| is called
- // on the server's IO thread.
+ // on the server's IO thread so all handlers must be registered before the
+ // server is started.
void RegisterRequestHandler(const HandleRequestCallback& callback);
// Adds request monitors. The |callback| is called before any handlers are
// called, but can not respond it. This is useful to monitor requests that
- // will be handled by other request handlers.
+ // will be handled by other request handlers. The |callback| is called
+ // on the server's IO thread so all monitors must be registered before the
+ // server is started.
void RegisterRequestMonitor(const MonitorRequestCallback& callback);
// Adds default handlers, including those added by AddDefaultHandlers, to be
- // tried after all other user-specified handlers have been tried.
+ // tried after all other user-specified handlers have been tried. The
+ // |callback| is called on the server's IO thread so all handlers must be
+ // registered before the server is started.
void RegisterDefaultHandler(const HandleRequestCallback& callback);
bool FlushAllSocketsAndConnectionsOnUIThread();
diff --git a/chromium/net/test/embedded_test_server/embedded_test_server_unittest.cc b/chromium/net/test/embedded_test_server/embedded_test_server_unittest.cc
index 31c66f4489c..dae43e9709c 100644
--- a/chromium/net/test/embedded_test_server/embedded_test_server_unittest.cc
+++ b/chromium/net/test/embedded_test_server/embedded_test_server_unittest.cc
@@ -15,6 +15,7 @@
#include "base/strings/stringprintf.h"
#include "base/synchronization/lock.h"
#include "base/threading/thread.h"
+#include "base/threading/thread_task_runner_handle.h"
#include "crypto/nss_util.h"
#include "net/base/test_completion_callback.h"
#include "net/http/http_response_headers.h"
@@ -179,9 +180,9 @@ class EmbeddedTestServerTest
HttpStatusCode code,
const HttpRequest& request) {
request_relative_url_ = request.relative_url;
+ request_absolute_url_ = request.GetURL();
- GURL absolute_url = server_->GetURL(request.relative_url);
- if (absolute_url.path() == path) {
+ if (request_absolute_url_.path() == path) {
std::unique_ptr<BasicHttpResponse> http_response(new BasicHttpResponse);
http_response->set_code(code);
http_response->set_content(content);
@@ -196,6 +197,7 @@ class EmbeddedTestServerTest
int num_responses_received_;
int num_responses_expected_;
std::string request_relative_url_;
+ GURL request_absolute_url_;
base::Thread io_thread_;
scoped_refptr<TestURLRequestContextGetter> request_context_getter_;
TestConnectionListener connection_listener_;
@@ -261,6 +263,7 @@ TEST_P(EmbeddedTestServerTest, RegisterRequestHandler) {
EXPECT_EQ("text/html", GetContentTypeFromFetcher(*fetcher));
EXPECT_EQ("/test?q=foo", request_relative_url_);
+ EXPECT_EQ(server_->GetURL("/test?q=foo"), request_absolute_url_);
}
TEST_P(EmbeddedTestServerTest, ServeFilesFromDirectory) {
diff --git a/chromium/net/test/embedded_test_server/http_connection.h b/chromium/net/test/embedded_test_server/http_connection.h
index 0b87fcb218d..ab7d96f50a5 100644
--- a/chromium/net/test/embedded_test_server/http_connection.h
+++ b/chromium/net/test/embedded_test_server/http_connection.h
@@ -24,7 +24,6 @@ class StreamSocket;
namespace test_server {
class HttpConnection;
-class HttpResponse;
// Calblack called when a request is parsed. Response should be sent
// using HttpConnection::SendResponse() on the |connection| argument.
diff --git a/chromium/net/test/embedded_test_server/http_request.cc b/chromium/net/test/embedded_test_server/http_request.cc
index 2c247c614a9..ef624dcc8b0 100644
--- a/chromium/net/test/embedded_test_server/http_request.cc
+++ b/chromium/net/test/embedded_test_server/http_request.cc
@@ -40,7 +40,8 @@ HttpRequest::~HttpRequest() {
}
GURL HttpRequest::GetURL() const {
- // TODO(svaldez): Use real URL from the EmbeddedTestServer.
+ if (base_url.is_valid())
+ return base_url.Resolve(relative_url);
return GURL("http://localhost" + relative_url);
}
diff --git a/chromium/net/test/embedded_test_server/http_request.h b/chromium/net/test/embedded_test_server/http_request.h
index b58f7749d8e..864c094a104 100644
--- a/chromium/net/test/embedded_test_server/http_request.h
+++ b/chromium/net/test/embedded_test_server/http_request.h
@@ -53,10 +53,10 @@ struct HttpRequest {
~HttpRequest();
// Returns a GURL as a convenience to extract the path and query strings.
- // TODO(svaldez): Use provided URL if available.
GURL GetURL() const;
std::string relative_url; // Starts with '/'. Example: "/test?query=foo"
+ GURL base_url;
HttpMethod method;
std::string method_string;
std::string all_headers;
diff --git a/chromium/net/test/embedded_test_server/http_request_unittest.cc b/chromium/net/test/embedded_test_server/http_request_unittest.cc
index 64761cfb7fb..d0e534f4e0a 100644
--- a/chromium/net/test/embedded_test_server/http_request_unittest.cc
+++ b/chromium/net/test/embedded_test_server/http_request_unittest.cc
@@ -145,5 +145,19 @@ TEST(HttpRequestTest, ParseGet) {
EXPECT_FALSE(request->has_content);
}
+TEST(HttpRequestTest, GetURL) {
+ HttpRequest request;
+ request.relative_url = "/foobar.html?q=foo";
+ request.base_url = GURL("https://127.0.0.1:8080");
+ EXPECT_EQ("https://127.0.0.1:8080/foobar.html?q=foo",
+ request.GetURL().spec());
+}
+
+TEST(HttpRequestTest, GetURLFallback) {
+ HttpRequest request;
+ request.relative_url = "/foobar.html?q=foo";
+ EXPECT_EQ("http://localhost/foobar.html?q=foo", request.GetURL().spec());
+}
+
} // namespace test_server
} // namespace net
diff --git a/chromium/net/test/gtest_util.h b/chromium/net/test/gtest_util.h
index 22d82b0bfa9..dec0bb9b396 100644
--- a/chromium/net/test/gtest_util.h
+++ b/chromium/net/test/gtest_util.h
@@ -7,9 +7,14 @@
#ifndef NET_TEST_GTEST_UTIL_H_
#define NET_TEST_GTEST_UTIL_H_
+#include <string>
+
+#include "base/macros.h"
+#include "base/strings/string_piece.h"
#include "base/test/mock_log.h"
#include "net/base/net_errors.h"
#include "net/test/scoped_disable_exit_on_dfatal.h"
+#include "testing/gmock/include/gmock/gmock-matchers.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
@@ -36,6 +41,34 @@ MATCHER(IsOk,
return arg == net::OK;
}
+// A gMock matcher for base::StringPiece arguments.
+// gMock's built-in HasSubstrMatcher does not work,
+// because base::StringPiece cannot be implicitly converted to std::string.
+class StringPieceHasSubstrMatcher {
+ public:
+ explicit StringPieceHasSubstrMatcher(const std::string& substring)
+ : substring_(substring) {}
+
+ bool MatchAndExplain(base::StringPiece s,
+ ::testing::MatchResultListener* listener) const {
+ return s.as_string().find(substring_) != std::string::npos;
+ }
+
+ // Describe what this matcher matches.
+ void DescribeTo(std::ostream* os) const {
+ *os << "has substring " << substring_;
+ }
+
+ void DescribeNegationTo(std::ostream* os) const {
+ *os << "has no substring " << substring_;
+ }
+
+ private:
+ const std::string substring_;
+
+ DISALLOW_ASSIGN(StringPieceHasSubstrMatcher);
+};
+
// Internal implementation for the EXPECT_DFATAL and ASSERT_DFATAL
// macros. Do not use this directly.
#define GTEST_DFATAL_(statement, severity, matcher, fail) \
diff --git a/chromium/net/test/python_utils.cc b/chromium/net/test/python_utils.cc
index 868abbb4e35..57429626b17 100644
--- a/chromium/net/test/python_utils.cc
+++ b/chromium/net/test/python_utils.cc
@@ -23,6 +23,7 @@
#endif
const char kPythonPathEnv[] = "PYTHONPATH";
+const char kPythonVirtualEnv[] = "VIRTUAL_ENV";
void ClearPythonPath() {
std::unique_ptr<base::Environment> env(base::Environment::Create());
@@ -102,6 +103,10 @@ struct PythonExePath {
static base::LazyInstance<PythonExePath>::Leaky g_python_path;
#endif
+bool IsInPythonVirtualEnv() {
+ return base::Environment::Create()->HasVar(kPythonVirtualEnv);
+}
+
bool GetPythonCommand(base::CommandLine* python_cmd) {
DCHECK(python_cmd);
@@ -121,8 +126,10 @@ bool GetPythonCommand(base::CommandLine* python_cmd) {
// gtest output in buildbot log files. See http://crbug.com/147368.
python_cmd->AppendArg("-u");
- // Prevent using system-installed libraries. Use hermetic versioned copies.
- python_cmd->AppendArg("-S");
+ if (!IsInPythonVirtualEnv()) {
+ // Prevent using system-installed libraries. Use hermetic versioned copies.
+ python_cmd->AppendArg("-S");
+ }
return true;
}
diff --git a/chromium/net/test/python_utils.h b/chromium/net/test/python_utils.h
index c72c9445dcb..aba4addddca 100644
--- a/chromium/net/test/python_utils.h
+++ b/chromium/net/test/python_utils.h
@@ -24,6 +24,9 @@ void AppendToPythonPath(const base::FilePath& dir);
// Return the location of the compiler-generated python protobuf.
bool GetPyProtoPath(base::FilePath* dir);
+// Returns if a virtualenv is currently active.
+bool IsInPythonVirtualEnv();
+
// Returns the command that should be used to launch Python.
bool GetPythonCommand(base::CommandLine* python_cmd) WARN_UNUSED_RESULT;
diff --git a/chromium/net/test/run_all_unittests.cc b/chromium/net/test/run_all_unittests.cc
index 604888e07f2..78307f756b0 100644
--- a/chromium/net/test/run_all_unittests.cc
+++ b/chromium/net/test/run_all_unittests.cc
@@ -2,6 +2,7 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
+#include "base/build_time.h"
#include "base/metrics/statistics_recorder.h"
#include "base/test/launcher/unit_test_launcher.h"
#include "build/build_config.h"
@@ -23,6 +24,38 @@
using net::internal::ClientSocketPoolBaseHelper;
+namespace {
+
+bool VerifyBuildIsTimely() {
+ // This lines up with various //net security features, like Certificate
+ // Transparency or HPKP, in that they require the build time be less than 70
+ // days old. Moreover, operating on the assumption that tests are run against
+ // recently compiled builds, this also serves as a sanity check for the
+ // system clock, which should be close to the build date.
+ base::TimeDelta kMaxAge = base::TimeDelta::FromDays(70);
+
+ base::Time build_time = base::GetBuildTime();
+ base::Time now = base::Time::Now();
+
+ if ((now - build_time).magnitude() <= kMaxAge)
+ return true;
+
+ std::cerr
+ << "ERROR: This build is more than " << kMaxAge.InDays()
+ << " days out of date.\n"
+ "This could indicate a problem with the device's clock, or the build "
+ "is simply too old.\n"
+ "See crbug.com/666821 for why this is a problem\n"
+ << " base::Time::Now() --> " << now << " (" << now.ToInternalValue()
+ << ")\n"
+ << " base::GetBuildTime() --> " << build_time << " ("
+ << build_time.ToInternalValue() << ")\n";
+
+ return false;
+}
+
+} // namespace
+
int main(int argc, char** argv) {
// Record histograms, so we can get histograms data in tests.
base::StatisticsRecorder::Initialize();
@@ -42,6 +75,9 @@ int main(int argc, char** argv) {
arraysize(kNetTestRegisteredMethods));
#endif
+ if (!VerifyBuildIsTimely())
+ return 1;
+
NetTestSuite test_suite(argc, argv);
ClientSocketPoolBaseHelper::set_connect_backup_jobs_enabled(false);
diff --git a/chromium/net/test/spawned_test_server/base_test_server.cc b/chromium/net/test/spawned_test_server/base_test_server.cc
index 87838c10a06..c3ffc07bc58 100644
--- a/chromium/net/test/spawned_test_server/base_test_server.cc
+++ b/chromium/net/test/spawned_test_server/base_test_server.cc
@@ -224,6 +224,7 @@ base::FilePath BaseTestServer::SSLOptions::GetCertificateFile() const {
case CERT_BAD_VALIDITY:
return base::FilePath(FILE_PATH_LITERAL("bad_validity.pem"));
case CERT_AUTO:
+ case CERT_AUTO_AIA_INTERMEDIATE:
return base::FilePath();
default:
NOTREACHED();
@@ -481,7 +482,7 @@ bool BaseTestServer::ParseServerData(const std::string& server_data) {
VLOG(1) << "Server data: " << server_data;
base::JSONReader json_reader;
std::unique_ptr<base::Value> value(json_reader.ReadToValue(server_data));
- if (!value.get() || !value->IsType(base::Value::TYPE_DICTIONARY)) {
+ if (!value.get() || !value->IsType(base::Value::Type::DICTIONARY)) {
LOG(ERROR) << "Could not parse server data: "
<< json_reader.GetErrorMessage();
return false;
@@ -592,6 +593,10 @@ bool BaseTestServer::GenerateArguments(base::DictionaryValue* arguments) const {
if (type_ == TYPE_HTTPS) {
arguments->Set("https", base::Value::CreateNullValue());
+ if (ssl_options_.server_certificate ==
+ SSLOptions::CERT_AUTO_AIA_INTERMEDIATE)
+ arguments->Set("aia-intermediate", base::Value::CreateNullValue());
+
std::string ocsp_arg = ssl_options_.GetOCSPArgument();
if (!ocsp_arg.empty())
arguments->SetString("ocsp", ocsp_arg);
diff --git a/chromium/net/test/spawned_test_server/base_test_server.h b/chromium/net/test/spawned_test_server/base_test_server.h
index 24a119b6447..60a9c3b63e2 100644
--- a/chromium/net/test/spawned_test_server/base_test_server.h
+++ b/chromium/net/test/spawned_test_server/base_test_server.h
@@ -58,6 +58,10 @@ class BaseTestServer {
// CERT_AUTO causes the testserver to generate a test certificate issued
// by "Testing CA" (see net/data/ssl/certificates/ocsp-test-root.pem).
CERT_AUTO,
+ // Generate an intermediate cert issued by "Testing CA", and generate a
+ // test certificate issued by that intermediate with an AIA record for
+ // retrieving the intermediate.
+ CERT_AUTO_AIA_INTERMEDIATE,
CERT_MISMATCHED_NAME,
CERT_EXPIRED,
diff --git a/chromium/net/test/spawned_test_server/local_test_server.cc b/chromium/net/test/spawned_test_server/local_test_server.cc
index 30211667249..70ea7a9450c 100644
--- a/chromium/net/test/spawned_test_server/local_test_server.cc
+++ b/chromium/net/test/spawned_test_server/local_test_server.cc
@@ -25,17 +25,17 @@ bool AppendArgumentFromJSONValue(const std::string& key,
base::CommandLine* command_line) {
std::string argument_name = "--" + key;
switch (value_node.GetType()) {
- case base::Value::TYPE_NULL:
+ case base::Value::Type::NONE:
command_line->AppendArg(argument_name);
break;
- case base::Value::TYPE_INTEGER: {
+ case base::Value::Type::INTEGER: {
int value;
bool result = value_node.GetAsInteger(&value);
DCHECK(result);
command_line->AppendArg(argument_name + "=" + base::IntToString(value));
break;
}
- case base::Value::TYPE_STRING: {
+ case base::Value::Type::STRING: {
std::string value;
bool result = value_node.GetAsString(&value);
if (!result || value.empty())
@@ -43,11 +43,11 @@ bool AppendArgumentFromJSONValue(const std::string& key,
command_line->AppendArg(argument_name + "=" + value);
break;
}
- case base::Value::TYPE_BOOLEAN:
- case base::Value::TYPE_DOUBLE:
- case base::Value::TYPE_LIST:
- case base::Value::TYPE_DICTIONARY:
- case base::Value::TYPE_BINARY:
+ case base::Value::Type::BOOLEAN:
+ case base::Value::Type::DOUBLE:
+ case base::Value::Type::LIST:
+ case base::Value::Type::DICTIONARY:
+ case base::Value::Type::BINARY:
default:
NOTREACHED() << "improper json type";
return false;
@@ -207,7 +207,7 @@ bool LocalTestServer::AddCommandLineArguments(
const std::string& key = it.key();
// Add arguments from a list.
- if (value.IsType(base::Value::TYPE_LIST)) {
+ if (value.IsType(base::Value::Type::LIST)) {
const base::ListValue* list = NULL;
if (!value.GetAsList(&list) || !list || list->empty())
return false;
diff --git a/chromium/net/test/spawned_test_server/local_test_server_win.cc b/chromium/net/test/spawned_test_server/local_test_server_win.cc
index 6f325e064c0..65d554eba25 100644
--- a/chromium/net/test/spawned_test_server/local_test_server_win.cc
+++ b/chromium/net/test/spawned_test_server/local_test_server_win.cc
@@ -164,4 +164,3 @@ bool LocalTestServer::WaitToStart() {
}
} // namespace net
-
diff --git a/chromium/net/test/spawned_test_server/remote_test_server.cc b/chromium/net/test/spawned_test_server/remote_test_server.cc
index 1baab8ceab6..17dc21eba2b 100644
--- a/chromium/net/test/spawned_test_server/remote_test_server.cc
+++ b/chromium/net/test/spawned_test_server/remote_test_server.cc
@@ -248,4 +248,3 @@ bool RemoteTestServer::Init(const base::FilePath& document_root) {
}
} // namespace net
-
diff --git a/chromium/net/test/spawned_test_server/remote_test_server.h b/chromium/net/test/spawned_test_server/remote_test_server.h
index 788f68d2fb5..224c0cd6a11 100644
--- a/chromium/net/test/spawned_test_server/remote_test_server.h
+++ b/chromium/net/test/spawned_test_server/remote_test_server.h
@@ -69,4 +69,3 @@ class RemoteTestServer : public BaseTestServer {
} // namespace net
#endif // NET_TEST_SPAWNED_TEST_SERVER_REMOTE_TEST_SERVER_H_
-
diff --git a/chromium/net/test/spawned_test_server/spawned_test_server.h b/chromium/net/test/spawned_test_server/spawned_test_server.h
index 9bf5831d503..aa4e37a7b38 100644
--- a/chromium/net/test/spawned_test_server/spawned_test_server.h
+++ b/chromium/net/test/spawned_test_server/spawned_test_server.h
@@ -24,4 +24,3 @@ typedef LocalTestServer SpawnedTestServer;
} // namespace net
#endif // NET_TEST_SPAWNED_TEST_SERVER_SPAWNED_TEST_SERVER_H_
-
diff --git a/chromium/net/test/spawned_test_server/spawner_communicator.cc b/chromium/net/test/spawned_test_server/spawner_communicator.cc
index 3a1566db4cf..0f294a3c004 100644
--- a/chromium/net/test/spawned_test_server/spawner_communicator.cc
+++ b/chromium/net/test/spawned_test_server/spawner_communicator.cc
@@ -355,7 +355,7 @@ bool SpawnerCommunicator::StartServer(const std::string& arguments,
// Check whether the data returned from spawner server is JSON-formatted.
std::unique_ptr<base::Value> value =
base::JSONReader::Read(server_return_data);
- if (!value.get() || !value->IsType(base::Value::TYPE_DICTIONARY)) {
+ if (!value.get() || !value->IsType(base::Value::Type::DICTIONARY)) {
LOG(ERROR) << "Invalid server data: " << server_return_data.c_str();
return false;
}
diff --git a/chromium/net/test/test_certificate_data.h b/chromium/net/test/test_certificate_data.h
index a2e26a56e11..8c77e2f2c1d 100644
--- a/chromium/net/test/test_certificate_data.h
+++ b/chromium/net/test/test_certificate_data.h
@@ -2,6 +2,9 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
+#ifndef NET_TEST_TEST_CERTIFICATE_DATA_H_
+#define NET_TEST_TEST_CERTIFICATE_DATA_H_
+
#include <stdint.h>
namespace {
@@ -782,3 +785,5 @@ const uint8_t VARIABLE_IS_NOT_USED MITDN[] = {
0x6C, 0x69, 0x65, 0x6E, 0x74, 0x20, 0x43, 0x41, 0x20, 0x76, 0x31};
} // namespace
+
+#endif // NET_TEST_TEST_CERTIFICATE_DATA_H_
diff --git a/chromium/net/test/url_request/url_request_failed_job.cc b/chromium/net/test/url_request/url_request_failed_job.cc
index 3e1e5664934..1de2910eb3f 100644
--- a/chromium/net/test/url_request/url_request_failed_job.cc
+++ b/chromium/net/test/url_request/url_request_failed_job.cc
@@ -84,6 +84,7 @@ URLRequestFailedJob::URLRequestFailedJob(URLRequest* request,
: URLRequestJob(request, network_delegate),
phase_(phase),
net_error_(net_error),
+ total_received_bytes_(0),
weak_factory_(this) {
CHECK_GE(phase, URLRequestFailedJob::FailurePhase::START);
CHECK_LE(phase, URLRequestFailedJob::FailurePhase::READ_ASYNC);
@@ -131,6 +132,10 @@ void URLRequestFailedJob::PopulateNetErrorDetails(
}
}
+int64_t URLRequestFailedJob::GetTotalReceivedBytes() const {
+ return total_received_bytes_;
+}
+
// static
void URLRequestFailedJob::AddUrlHandler() {
return AddUrlHandlerForHostname(kMockHostname);
@@ -190,7 +195,9 @@ void URLRequestFailedJob::StartAsync() {
}
return;
}
- response_info_.headers = new net::HttpResponseHeaders("HTTP/1.1 200 OK");
+ const std::string headers = "HTTP/1.1 200 OK";
+ response_info_.headers = new net::HttpResponseHeaders(headers);
+ total_received_bytes_ = headers.size();
NotifyHeadersComplete();
}
diff --git a/chromium/net/test/url_request/url_request_failed_job.h b/chromium/net/test/url_request/url_request_failed_job.h
index 14c7efc9f5a..0c11c66dc86 100644
--- a/chromium/net/test/url_request/url_request_failed_job.h
+++ b/chromium/net/test/url_request/url_request_failed_job.h
@@ -44,6 +44,7 @@ class URLRequestFailedJob : public URLRequestJob {
int GetResponseCode() const override;
void GetResponseInfo(HttpResponseInfo* info) override;
void PopulateNetErrorDetails(NetErrorDetails* details) const override;
+ int64_t GetTotalReceivedBytes() const override;
// Adds the testing URLs to the URLRequestFilter.
static void AddUrlHandler();
@@ -79,6 +80,7 @@ class URLRequestFailedJob : public URLRequestJob {
HttpResponseInfo response_info_;
const FailurePhase phase_;
const int net_error_;
+ int64_t total_received_bytes_;
base::WeakPtrFactory<URLRequestFailedJob> weak_factory_;
diff --git a/chromium/net/test/url_request/url_request_hanging_read_job.cc b/chromium/net/test/url_request/url_request_hanging_read_job.cc
index 74c680f2418..5223b297b45 100644
--- a/chromium/net/test/url_request/url_request_hanging_read_job.cc
+++ b/chromium/net/test/url_request/url_request_hanging_read_job.cc
@@ -92,6 +92,8 @@ void URLRequestHangingReadJob::GetResponseInfoConst(
}
void URLRequestHangingReadJob::StartAsync() {
+ if (is_done())
+ return;
set_expected_content_size(content_length_);
NotifyHeadersComplete();
}
diff --git a/chromium/net/test/url_request/url_request_hanging_read_job.h b/chromium/net/test/url_request/url_request_hanging_read_job.h
index 62213f29262..f5eba1ef2c7 100644
--- a/chromium/net/test/url_request/url_request_hanging_read_job.h
+++ b/chromium/net/test/url_request/url_request_hanging_read_job.h
@@ -2,8 +2,8 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#ifndef NET_URL_REQUEST_URL_REQUEST_HANGING_READ_JOB_H_
-#define NET_URL_REQUEST_URL_REQUEST_HANGING_READ_JOB_H_
+#ifndef NET_TEST_URL_REQUEST_URL_REQUEST_HANGING_READ_JOB_H_
+#define NET_TEST_URL_REQUEST_URL_REQUEST_HANGING_READ_JOB_H_
#include "base/macros.h"
#include "base/memory/weak_ptr.h"
@@ -44,4 +44,4 @@ class URLRequestHangingReadJob : public URLRequestJob {
} // namespace net
-#endif // NET_URL_REQUEST_URL_REQUEST_SIMPLE_JOB_H_
+#endif // NET_TEST_URL_REQUEST_URL_REQUEST_HANGING_READ_JOB_H_
diff --git a/chromium/net/test/url_request/url_request_mock_data_job.h b/chromium/net/test/url_request/url_request_mock_data_job.h
index 27f3a0953f0..0324201c599 100644
--- a/chromium/net/test/url_request/url_request_mock_data_job.h
+++ b/chromium/net/test/url_request/url_request_mock_data_job.h
@@ -2,8 +2,8 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#ifndef NET_URL_REQUEST_URL_REQUEST_MOCK_DATA_JOB_H_
-#define NET_URL_REQUEST_URL_REQUEST_MOCK_DATA_JOB_H_
+#ifndef NET_TEST_URL_REQUEST_URL_REQUEST_MOCK_DATA_JOB_H_
+#define NET_TEST_URL_REQUEST_URL_REQUEST_MOCK_DATA_JOB_H_
#include <stddef.h>
@@ -71,4 +71,4 @@ class URLRequestMockDataJob : public URLRequestJob {
} // namespace net
-#endif // NET_URL_REQUEST_URL_REQUEST_SIMPLE_JOB_H_
+#endif // NET_TEST_URL_REQUEST_URL_REQUEST_MOCK_DATA_JOB_H_
diff --git a/chromium/net/test/url_request/url_request_mock_http_job.cc b/chromium/net/test/url_request/url_request_mock_http_job.cc
index 5317b846ed0..7fdcfaaf901 100644
--- a/chromium/net/test/url_request/url_request_mock_http_job.cc
+++ b/chromium/net/test/url_request/url_request_mock_http_job.cc
@@ -184,6 +184,7 @@ void URLRequestMockHTTPJob::SetHeadersAndStart(const std::string& raw_headers) {
// ParseRawHeaders expects \0 to end each header line.
base::ReplaceSubstringsAfterOffset(
&raw_headers_, 0, "\n", base::StringPiece("\0", 1));
+ total_received_bytes_ += raw_headers_.size();
URLRequestFileJob::Start();
}
diff --git a/chromium/net/third_party/mozilla_security_manager/nsKeygenHandler.cpp b/chromium/net/third_party/mozilla_security_manager/nsKeygenHandler.cpp
deleted file mode 100644
index 51d15bd0426..00000000000
--- a/chromium/net/third_party/mozilla_security_manager/nsKeygenHandler.cpp
+++ /dev/null
@@ -1,257 +0,0 @@
-/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
- *
- * ***** BEGIN LICENSE BLOCK *****
- * Version: MPL 1.1/GPL 2.0/LGPL 2.1
- *
- * The contents of this file are subject to the Mozilla Public License Version
- * 1.1 (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- * http://www.mozilla.org/MPL/
- *
- * Software distributed under the License is distributed on an "AS IS" basis,
- * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
- * for the specific language governing rights and limitations under the
- * License.
- *
- * The Original Code is mozilla.org code.
- *
- * The Initial Developer of the Original Code is
- * Netscape Communications Corporation.
- * Portions created by the Initial Developer are Copyright (C) 1998
- * the Initial Developer. All Rights Reserved.
- *
- * Contributor(s):
- * Vipul Gupta <vipul.gupta@sun.com>
- * Douglas Stebila <douglas@stebila.ca>
- *
- * Alternatively, the contents of this file may be used under the terms of
- * either the GNU General Public License Version 2 or later (the "GPL"), or
- * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
- * in which case the provisions of the GPL or the LGPL are applicable instead
- * of those above. If you wish to allow use of your version of this file only
- * under the terms of either the GPL or the LGPL, and not to allow others to
- * use your version of this file under the terms of the MPL, indicate your
- * decision by deleting the provisions above and replace them with the notice
- * and other provisions required by the GPL or the LGPL. If you do not delete
- * the provisions above, a recipient may use your version of this file under
- * the terms of any one of the MPL, the GPL or the LGPL.
- *
- * ***** END LICENSE BLOCK ***** */
-
-#include "net/third_party/mozilla_security_manager/nsKeygenHandler.h"
-
-#include <pk11pub.h>
-#include <prerror.h> // PR_GetError()
-#include <secmod.h>
-#include <secder.h> // DER_Encode()
-#include <cryptohi.h> // SEC_DerSignData()
-#include <keyhi.h> // SECKEY_CreateSubjectPublicKeyInfo()
-
-#include "base/base64.h"
-#include "base/logging.h"
-#include "crypto/nss_util.h"
-#include "url/gurl.h"
-
-namespace {
-
-// Template for creating the signed public key structure to be sent to the CA.
-DERTemplate SECAlgorithmIDTemplate[] = {
- { DER_SEQUENCE,
- 0, NULL, sizeof(SECAlgorithmID) },
- { DER_OBJECT_ID,
- offsetof(SECAlgorithmID, algorithm), },
- { DER_OPTIONAL | DER_ANY,
- offsetof(SECAlgorithmID, parameters), },
- { 0, }
-};
-
-DERTemplate CERTSubjectPublicKeyInfoTemplate[] = {
- { DER_SEQUENCE,
- 0, NULL, sizeof(CERTSubjectPublicKeyInfo) },
- { DER_INLINE,
- offsetof(CERTSubjectPublicKeyInfo, algorithm),
- SECAlgorithmIDTemplate, },
- { DER_BIT_STRING,
- offsetof(CERTSubjectPublicKeyInfo, subjectPublicKey), },
- { 0, }
-};
-
-DERTemplate CERTPublicKeyAndChallengeTemplate[] = {
- { DER_SEQUENCE,
- 0, NULL, sizeof(CERTPublicKeyAndChallenge) },
- { DER_ANY,
- offsetof(CERTPublicKeyAndChallenge, spki), },
- { DER_IA5_STRING,
- offsetof(CERTPublicKeyAndChallenge, challenge), },
- { 0, }
-};
-
-} // namespace
-
-namespace mozilla_security_manager {
-
-// This function is based on the nsKeygenFormProcessor::GetPublicKey function
-// in mozilla/security/manager/ssl/src/nsKeygenHandler.cpp.
-std::string GenKeyAndSignChallenge(int key_size_in_bits,
- const std::string& challenge,
- const GURL& url,
- PK11SlotInfo* slot,
- bool stores_key) {
- // Key pair generation mechanism - only RSA is supported at present.
- PRUint32 keyGenMechanism = CKM_RSA_PKCS_KEY_PAIR_GEN; // from nss/pkcs11t.h
-
- // Temporary structures used for generating the result
- // in the right format.
- PK11RSAGenParams rsaKeyGenParams; // Keygen parameters.
- SECOidTag algTag; // used by SEC_DerSignData().
- SECKEYPrivateKey *privateKey = NULL;
- SECKEYPublicKey *publicKey = NULL;
- CERTSubjectPublicKeyInfo *spkInfo = NULL;
- PLArenaPool *arena = NULL;
- SECStatus sec_rv =SECFailure;
- SECItem spkiItem;
- SECItem pkacItem;
- SECItem signedItem;
- CERTPublicKeyAndChallenge pkac;
- void *keyGenParams;
- bool isSuccess = true; // Set to false as soon as a step fails.
-
- std::string result_blob; // the result.
-
- switch (keyGenMechanism) {
- case CKM_RSA_PKCS_KEY_PAIR_GEN:
- rsaKeyGenParams.keySizeInBits = key_size_in_bits;
- rsaKeyGenParams.pe = DEFAULT_RSA_KEYGEN_PE;
- keyGenParams = &rsaKeyGenParams;
-
- algTag = DEFAULT_RSA_KEYGEN_ALG;
- break;
- default:
- // TODO(gauravsh): If we ever support other mechanisms,
- // this can be changed.
- LOG(ERROR) << "Only RSA keygen mechanism is supported";
- isSuccess = false;
- goto failure;
- }
-
- VLOG(1) << "Creating key pair...";
- {
- crypto::AutoNSSWriteLock lock;
- privateKey = PK11_GenerateKeyPair(slot,
- keyGenMechanism,
- keyGenParams,
- &publicKey,
- PR_TRUE, // isPermanent?
- PR_TRUE, // isSensitive?
- NULL);
- }
- VLOG(1) << "done.";
-
- if (!privateKey) {
- LOG(ERROR) << "Generation of Keypair failed!";
- isSuccess = false;
- goto failure;
- }
-
- // Set friendly names for the keys.
- if (url.has_host()) {
- // TODO(davidben): Use something like "Key generated for
- // example.com", but localize it.
- const std::string& label = url.host();
- {
- crypto::AutoNSSWriteLock lock;
- PK11_SetPublicKeyNickname(publicKey, label.c_str());
- PK11_SetPrivateKeyNickname(privateKey, label.c_str());
- }
- }
-
- // The CA expects the signed public key in a specific format
- // Let's create that now.
-
- // Create a subject public key info from the public key.
- spkInfo = SECKEY_CreateSubjectPublicKeyInfo(publicKey);
- if (!spkInfo) {
- LOG(ERROR) << "Couldn't create SubjectPublicKeyInfo from public key";
- isSuccess = false;
- goto failure;
- }
-
- arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
- if (!arena) {
- LOG(ERROR) << "PORT_NewArena: Couldn't allocate memory";
- isSuccess = false;
- goto failure;
- }
-
- // DER encode the whole subjectPublicKeyInfo.
- sec_rv = DER_Encode(arena, &spkiItem, CERTSubjectPublicKeyInfoTemplate,
- spkInfo);
- if (SECSuccess != sec_rv) {
- LOG(ERROR) << "Couldn't DER Encode subjectPublicKeyInfo";
- isSuccess = false;
- goto failure;
- }
-
- // Set up the PublicKeyAndChallenge data structure, then DER encode it.
- pkac.spki = spkiItem;
- pkac.challenge.type = siBuffer;
- pkac.challenge.len = challenge.length();
- pkac.challenge.data = (unsigned char *)challenge.data();
- sec_rv = DER_Encode(arena, &pkacItem, CERTPublicKeyAndChallengeTemplate,
- &pkac);
- if (SECSuccess != sec_rv) {
- LOG(ERROR) << "Couldn't DER Encode PublicKeyAndChallenge";
- isSuccess = false;
- goto failure;
- }
-
- // Sign the DER encoded PublicKeyAndChallenge.
- sec_rv = SEC_DerSignData(arena, &signedItem, pkacItem.data, pkacItem.len,
- privateKey, algTag);
- if (SECSuccess != sec_rv) {
- LOG(ERROR) << "Couldn't sign the DER encoded PublicKeyandChallenge";
- isSuccess = false;
- goto failure;
- }
-
- // Convert the signed public key and challenge into base64/ascii.
- base::Base64Encode(base::StringPiece(reinterpret_cast<char*>(signedItem.data),
- signedItem.len),
- &result_blob);
-
- failure:
- if (!isSuccess) {
- LOG(ERROR) << "SSL Keygen failed! (NSS error code " << PR_GetError() << ")";
- } else {
- VLOG(1) << "SSL Keygen succeeded!";
- }
-
- // Do cleanups
- if (privateKey) {
- // On successful keygen we need to keep the private key, of course,
- // or we won't be able to use the client certificate.
- if (!isSuccess || !stores_key) {
- crypto::AutoNSSWriteLock lock;
- PK11_DestroyTokenObject(privateKey->pkcs11Slot, privateKey->pkcs11ID);
- }
- SECKEY_DestroyPrivateKey(privateKey);
- }
-
- if (publicKey) {
- if (!isSuccess || !stores_key) {
- crypto::AutoNSSWriteLock lock;
- PK11_DestroyTokenObject(publicKey->pkcs11Slot, publicKey->pkcs11ID);
- }
- SECKEY_DestroyPublicKey(publicKey);
- }
- if (spkInfo) {
- SECKEY_DestroySubjectPublicKeyInfo(spkInfo);
- }
- if (arena) {
- PORT_FreeArena(arena, PR_TRUE);
- }
-
- return (isSuccess ? result_blob : std::string());
-}
-
-} // namespace mozilla_security_manager
diff --git a/chromium/net/third_party/mozilla_security_manager/nsKeygenHandler.h b/chromium/net/third_party/mozilla_security_manager/nsKeygenHandler.h
deleted file mode 100644
index 4c20e561710..00000000000
--- a/chromium/net/third_party/mozilla_security_manager/nsKeygenHandler.h
+++ /dev/null
@@ -1,69 +0,0 @@
-/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
- *
- * ***** BEGIN LICENSE BLOCK *****
- * Version: MPL 1.1/GPL 2.0/LGPL 2.1
- *
- * The contents of this file are subject to the Mozilla Public License Version
- * 1.1 (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- * http://www.mozilla.org/MPL/
- *
- * Software distributed under the License is distributed on an "AS IS" basis,
- * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
- * for the specific language governing rights and limitations under the
- * License.
- *
- * The Original Code is mozilla.org code.
- *
- * The Initial Developer of the Original Code is
- * Netscape Communications Corporation.
- * Portions created by the Initial Developer are Copyright (C) 2001
- * the Initial Developer. All Rights Reserved.
- *
- * Contributor(s):
- * David Drinan. (ddrinan@netscape.com)
- *
- * Alternatively, the contents of this file may be used under the terms of
- * either the GNU General Public License Version 2 or later (the "GPL"), or
- * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
- * in which case the provisions of the GPL or the LGPL are applicable instead
- * of those above. If you wish to allow use of your version of this file only
- * under the terms of either the GPL or the LGPL, and not to allow others to
- * use your version of this file under the terms of the MPL, indicate your
- * decision by deleting the provisions above and replace them with the notice
- * and other provisions required by the GPL or the LGPL. If you do not delete
- * the provisions above, a recipient may use your version of this file under
- * the terms of any one of the MPL, the GPL or the LGPL.
- *
- * ***** END LICENSE BLOCK ***** */
-
-#ifndef _NSKEYGENHANDLER_H_
-#define _NSKEYGENHANDLER_H_
-
-#include <string>
-
-class GURL;
-typedef struct PK11SlotInfoStr PK11SlotInfo;
-
-namespace mozilla_security_manager {
-
-#define DEFAULT_RSA_KEYGEN_PE 65537L
-#define DEFAULT_RSA_KEYGEN_ALG SEC_OID_PKCS1_MD5_WITH_RSA_ENCRYPTION
-
-// Generates the key pair and the cert request (SPKAC), and returns a
-// base64-encoded string suitable for use as the form value of <keygen>.
-// Parameters:
-// key_size_in_bits: key size in bits (usually 2048)
-// challenge: challenge string sent by server
-// url: the URL which requested the SPKAC
-// slot: a slot to generate the key in, should be authenticated
-// stores_key: should the generated key pair be stored persistently?
-std::string GenKeyAndSignChallenge(int key_size_in_bits,
- const std::string& challenge,
- const GURL& url,
- PK11SlotInfo* slot,
- bool stores_key);
-
-} // namespace mozilla_security_manager
-
-#endif //_NSKEYGENHANDLER_H_
diff --git a/chromium/net/third_party/mozilla_security_manager/nsPKCS12Blob.cpp b/chromium/net/third_party/mozilla_security_manager/nsPKCS12Blob.cpp
index 0cf3500c6d3..a2466559da4 100644
--- a/chromium/net/third_party/mozilla_security_manager/nsPKCS12Blob.cpp
+++ b/chromium/net/third_party/mozilla_security_manager/nsPKCS12Blob.cpp
@@ -371,7 +371,9 @@ int nsPKCS12Blob_Import(PK11SlotInfo* slot,
// We try both variations, zero length item and empty string,
// without giving a user prompt when trying the different empty password
// flavors.
- if (rv == net::ERR_PKCS12_IMPORT_BAD_PASSWORD && password.empty()) {
+ if ((rv == net::ERR_PKCS12_IMPORT_BAD_PASSWORD ||
+ rv == net::ERR_PKCS12_IMPORT_INVALID_MAC) &&
+ password.empty()) {
rv = nsPKCS12Blob_ImportHelper(pkcs12_data, pkcs12_len, password,
is_extractable, true, slot, imported_certs);
}
diff --git a/chromium/net/tools/cachetool/cachetool.cc b/chromium/net/tools/cachetool/cachetool.cc
index c5ac94fd314..4c3b7c1ba7e 100644
--- a/chromium/net/tools/cachetool/cachetool.cc
+++ b/chromium/net/tools/cachetool/cachetool.cc
@@ -4,15 +4,20 @@
#include <iostream>
#include <memory>
+#include <unordered_map>
#include "base/at_exit.h"
#include "base/command_line.h"
#include "base/files/file_path.h"
+#include "base/format_macros.h"
#include "base/logging.h"
#include "base/macros.h"
+#include "base/md5.h"
#include "base/message_loop/message_loop.h"
#include "base/run_loop.h"
#include "base/strings/string_number_conversions.h"
+#include "base/strings/string_piece.h"
+#include "base/strings/stringprintf.h"
#include "net/base/io_buffer.h"
#include "net/base/test_completion_callback.h"
#include "net/disk_cache/disk_cache.h"
@@ -25,11 +30,18 @@ using disk_cache::Entry;
namespace {
+struct EntryData {
+ std::string url;
+ std::string mime_type;
+ int size;
+};
+
constexpr int kResponseInfoIndex = 0;
+constexpr int kResponseContentIndex = 1;
const char* const kCommandNames[] = {
"stop", "get_size", "list_keys", "get_stream_for_key",
- "delete_stream", "delete_key", "update_raw_headers",
+ "delete_stream", "delete_key", "update_raw_headers", "list_dups",
};
// Prints the command line help.
@@ -50,6 +62,8 @@ void PrintHelp() {
std::cout << " get_stream <key> <index>: Print a particular stream for a"
<< " given key." << std::endl;
std::cout << " list_keys: List all keys in the cache." << std::endl;
+ std::cout << " list_dups: List all resources with duplicate bodies in the "
+ << "cache." << std::endl;
std::cout << " update_raw_headers <key>: Update stdin as the key's raw "
<< "response headers." << std::endl;
std::cout << " stop: Verify that the cache can be opened and return, "
@@ -64,9 +78,9 @@ void PrintHelp() {
// Generic command input/output.
class CommandMarshal {
public:
- CommandMarshal(Backend* cache_backend)
- : command_failed_(false), cache_backend_(cache_backend){};
- virtual ~CommandMarshal(){};
+ explicit CommandMarshal(Backend* cache_backend)
+ : command_failed_(false), cache_backend_(cache_backend) {}
+ virtual ~CommandMarshal() {}
// Reads the next command's name to execute.
virtual std::string ReadCommandName() = 0;
@@ -105,7 +119,7 @@ class CommandMarshal {
virtual void ReturnFailure(const std::string& error_msg) = 0;
// Communicates back command success.
- virtual void ReturnSuccess() { DCHECK(!command_failed_); };
+ virtual void ReturnSuccess() { DCHECK(!command_failed_); }
// Returns whether the command has failed.
inline bool has_failed() { return command_failed_; }
@@ -199,7 +213,7 @@ class ProgramArgumentCommandMarshal final : public CommandMarshal {
// cachetool's main loop.
class StreamCommandMarshal final : public CommandMarshal {
public:
- StreamCommandMarshal(Backend* cache_backend)
+ explicit StreamCommandMarshal(Backend* cache_backend)
: CommandMarshal(cache_backend) {}
// Implements CommandMarshal.
@@ -302,6 +316,153 @@ bool ListKeys(CommandMarshal* command_marshal) {
return true;
}
+bool GetResponseInfoForEntry(disk_cache::Entry* entry,
+ net::HttpResponseInfo* response_info) {
+ int size = entry->GetDataSize(kResponseInfoIndex);
+ if (size == 0)
+ return false;
+ scoped_refptr<net::IOBuffer> buffer = new net::IOBufferWithSize(size);
+ net::TestCompletionCallback cb;
+
+ int bytes_read = 0;
+ while (true) {
+ int rv = entry->ReadData(kResponseInfoIndex, bytes_read, buffer.get(), size,
+ cb.callback());
+ rv = cb.GetResult(rv);
+ if (rv < 0) {
+ entry->Close();
+ return false;
+ }
+
+ if (rv == 0) {
+ bool truncated_response_info = false;
+ net::HttpCache::ParseResponseInfo(buffer->data(), size, response_info,
+ &truncated_response_info);
+ return !truncated_response_info;
+ }
+
+ bytes_read += rv;
+ }
+
+ NOTREACHED();
+ return false;
+}
+
+std::string GetMD5ForResponseBody(disk_cache::Entry* entry) {
+ if (entry->GetDataSize(kResponseContentIndex) == 0)
+ return "";
+
+ const int kInitBufferSize = 80 * 1024;
+ scoped_refptr<net::IOBuffer> buffer =
+ new net::IOBufferWithSize(kInitBufferSize);
+ net::TestCompletionCallback cb;
+
+ base::MD5Context ctx;
+ base::MD5Init(&ctx);
+
+ int bytes_read = 0;
+ while (true) {
+ int rv = entry->ReadData(kResponseContentIndex, bytes_read, buffer.get(),
+ kInitBufferSize, cb.callback());
+ rv = cb.GetResult(rv);
+ if (rv < 0) {
+ entry->Close();
+ return "";
+ }
+
+ if (rv == 0) {
+ base::MD5Digest digest;
+ base::MD5Final(&digest, &ctx);
+ return base::MD5DigestToBase16(digest);
+ }
+
+ bytes_read += rv;
+ MD5Update(&ctx, base::StringPiece(buffer->data(), rv));
+ }
+
+ NOTREACHED();
+ return "";
+}
+
+void ListDups(CommandMarshal* command_marshal) {
+ std::unique_ptr<Backend::Iterator> entry_iterator =
+ command_marshal->cache_backend()->CreateIterator();
+ Entry* entry = nullptr;
+ net::TestCompletionCallback cb;
+ int rv = entry_iterator->OpenNextEntry(&entry, cb.callback());
+ command_marshal->ReturnSuccess();
+
+ std::unordered_map<std::string, std::vector<EntryData>> md5_entries;
+
+ int total_entries = 0;
+
+ while (cb.GetResult(rv) == net::OK) {
+ total_entries += 1;
+ net::HttpResponseInfo response_info;
+ if (!GetResponseInfoForEntry(entry, &response_info)) {
+ entry->Close();
+ entry = nullptr;
+ rv = entry_iterator->OpenNextEntry(&entry, cb.callback());
+ continue;
+ }
+
+ std::string hash = GetMD5ForResponseBody(entry);
+ if (hash.empty()) {
+ // Sparse entries and empty bodies are skipped.
+ entry->Close();
+ entry = nullptr;
+ rv = entry_iterator->OpenNextEntry(&entry, cb.callback());
+ continue;
+ }
+
+ EntryData entry_data;
+
+ entry_data.url = entry->GetKey();
+ entry_data.size = entry->GetDataSize(kResponseContentIndex);
+ if (response_info.headers)
+ response_info.headers->GetMimeType(&entry_data.mime_type);
+
+ auto iter = md5_entries.find(hash);
+ if (iter == md5_entries.end())
+ md5_entries.insert(
+ std::make_pair(hash, std::vector<EntryData>{entry_data}));
+ else
+ iter->second.push_back(entry_data);
+
+ entry->Close();
+ entry = nullptr;
+ rv = entry_iterator->OpenNextEntry(&entry, cb.callback());
+ }
+
+ // Print the duplicates and collect stats.
+ int total_duped_entries = 0;
+ int64_t total_duped_bytes = 0u;
+ for (const auto& hash_and_entries : md5_entries) {
+ if (hash_and_entries.second.size() == 1)
+ continue;
+
+ int dups = hash_and_entries.second.size() - 1;
+ total_duped_entries += dups;
+ total_duped_bytes += hash_and_entries.second[0].size * dups;
+
+ for (const auto& entry : hash_and_entries.second) {
+ std::string out = base::StringPrintf(
+ "%d, %s, %s", entry.size, entry.url.c_str(), entry.mime_type.c_str());
+ command_marshal->ReturnString(out);
+ }
+ }
+
+ // Print the stats.
+ rv = command_marshal->cache_backend()->CalculateSizeOfAllEntries(
+ cb.callback());
+ rv = cb.GetResult(rv);
+ LOG(ERROR) << "Wasted bytes = " << total_duped_bytes;
+ LOG(ERROR) << "Wasted entries = " << total_duped_entries;
+ LOG(ERROR) << "Total entries = " << total_entries;
+ LOG(ERROR) << "Cache size = " << rv;
+ LOG(ERROR) << "Percentage of cache wasted = " << total_duped_bytes * 100 / rv;
+}
+
// Gets a key's stream to a buffer.
scoped_refptr<net::GrowableIOBuffer> GetStreamForKeyBuffer(
CommandMarshal* command_marshal,
@@ -460,6 +621,8 @@ bool ExecuteCommands(CommandMarshal* command_marshal) {
ListKeys(command_marshal);
} else if (subcommand == "update_raw_headers") {
UpdateRawResponseHeaders(command_marshal);
+ } else if (subcommand == "list_dups") {
+ ListDups(command_marshal);
} else {
// The wrong subcommand is originated from the command line.
command_marshal->ReturnFailure("Unknown command.");
diff --git a/chromium/net/tools/cert_verify_tool/cert_verify_tool.cc b/chromium/net/tools/cert_verify_tool/cert_verify_tool.cc
index a9c21fc6952..78e10bfa862 100644
--- a/chromium/net/tools/cert_verify_tool/cert_verify_tool.cc
+++ b/chromium/net/tools/cert_verify_tool/cert_verify_tool.cc
@@ -69,6 +69,7 @@ void PrintUsage(const char* argv0) {
int main(int argc, char** argv) {
base::AtExitManager at_exit_manager;
+ // TODO(eroman): Is this needed?
base::MessageLoopForIO message_loop;
if (!base::CommandLine::Init(argc, argv)) {
std::cerr << "ERROR in CommandLine::Init\n";
diff --git a/chromium/net/tools/cert_verify_tool/verify_using_path_builder.cc b/chromium/net/tools/cert_verify_tool/verify_using_path_builder.cc
index 206eb74b065..b94a08e35d5 100644
--- a/chromium/net/tools/cert_verify_tool/verify_using_path_builder.cc
+++ b/chromium/net/tools/cert_verify_tool/verify_using_path_builder.cc
@@ -9,8 +9,10 @@
#include "base/memory/ptr_util.h"
#include "base/strings/string_number_conversions.h"
#include "base/strings/string_util.h"
+#include "base/synchronization/waitable_event.h"
+#include "base/threading/thread.h"
#include "crypto/sha2.h"
-#include "net/base/test_completion_callback.h"
+#include "net/cert/cert_net_fetcher.h"
#include "net/cert/internal/cert_issuer_source_aia.h"
#include "net/cert/internal/cert_issuer_source_static.h"
#include "net/cert/internal/parse_name.h"
@@ -23,9 +25,11 @@
#include "net/tools/cert_verify_tool/cert_verify_tool_util.h"
#include "net/url_request/url_request_context.h"
#include "net/url_request/url_request_context_builder.h"
+#include "net/url_request/url_request_context_getter.h"
#if defined(USE_NSS_CERTS)
#include "base/threading/thread_task_runner_handle.h"
+#include "net/cert/internal/cert_issuer_source_nss.h"
#include "net/cert/internal/trust_store_nss.h"
#endif
@@ -167,6 +171,35 @@ scoped_refptr<net::ParsedCertificate> ParseCertificate(const CertInput& input) {
return cert;
}
+void SetUpOnNetworkThread(std::unique_ptr<net::URLRequestContext>* context,
+ scoped_refptr<net::CertNetFetcher>* fetcher,
+ base::WaitableEvent* initialization_complete_event) {
+ // TODO(mattm): add command line flags to configure using
+ // CertIssuerSourceAia
+ // (similar to VERIFY_CERT_IO_ENABLED flag for CertVerifyProc).
+ net::URLRequestContextBuilder url_request_context_builder;
+ url_request_context_builder.set_user_agent(GetUserAgent());
+#if defined(OS_LINUX)
+ // On Linux, use a fixed ProxyConfigService, since the default one
+ // depends on glib.
+ //
+ // TODO(akalin): Remove this once http://crbug.com/146421 is fixed.
+ url_request_context_builder.set_proxy_config_service(
+ base::MakeUnique<net::ProxyConfigServiceFixed>(net::ProxyConfig()));
+#endif
+ *context = url_request_context_builder.Build();
+
+ *fetcher = net::CreateCertNetFetcher(context->get());
+ initialization_complete_event->Signal();
+}
+
+void ShutdownOnNetworkThread(
+ std::unique_ptr<net::URLRequestContext>* context,
+ const scoped_refptr<net::CertNetFetcher>& cert_net_fetcher) {
+ cert_net_fetcher->Shutdown();
+ context->reset();
+}
+
} // namespace
// Verifies |target_der_cert| using CertPathBuilder.
@@ -183,7 +216,7 @@ bool VerifyUsingPathBuilder(
net::TrustStoreCollection trust_store;
net::TrustStoreInMemory trust_store_in_memory;
- trust_store.AddTrustStoreSynchronousOnly(&trust_store_in_memory);
+ trust_store.AddTrustStore(&trust_store_in_memory);
for (const auto& der_cert : root_der_certs) {
scoped_refptr<net::ParsedCertificate> cert = ParseCertificate(der_cert);
if (cert) {
@@ -193,9 +226,8 @@ bool VerifyUsingPathBuilder(
}
#if defined(USE_NSS_CERTS)
- net::TrustStoreNSS trust_store_nss(trustSSL,
- base::ThreadTaskRunnerHandle::Get());
- trust_store.SetPrimaryTrustStore(&trust_store_nss);
+ net::TrustStoreNSS trust_store_nss(trustSSL);
+ trust_store.AddTrustStore(&trust_store_nss);
#else
if (root_der_certs.empty()) {
std::cerr << "NOTE: CertPathBuilder does not currently use OS trust "
@@ -221,33 +253,42 @@ bool VerifyUsingPathBuilder(
net::CertPathBuilder path_builder(target_cert, &trust_store,
&signature_policy, time, &result);
path_builder.AddCertIssuerSource(&intermediate_cert_issuer_source);
-
- // TODO(mattm): add command line flags to configure using CertIssuerSourceAia
- // (similar to VERIFY_CERT_IO_ENABLED flag for CertVerifyProc).
- net::URLRequestContextBuilder url_request_context_builder;
- url_request_context_builder.set_user_agent(GetUserAgent());
-#if defined(OS_LINUX)
- // On Linux, use a fixed ProxyConfigService, since the default one
- // depends on glib.
- //
- // TODO(akalin): Remove this once http://crbug.com/146421 is fixed.
- url_request_context_builder.set_proxy_config_service(
- base::MakeUnique<net::ProxyConfigServiceFixed>(net::ProxyConfig()));
+#if defined(USE_NSS_CERTS)
+ net::CertIssuerSourceNSS cert_issuer_source_nss;
+ path_builder.AddCertIssuerSource(&cert_issuer_source_nss);
#endif
- std::unique_ptr<net::URLRequestContext> url_request_context =
- url_request_context_builder.Build();
- net::CertNetFetcherImpl cert_net_fetcher(url_request_context.get());
- net::CertIssuerSourceAia aia_cert_issuer_source(&cert_net_fetcher);
+
+ // Create a network thread to be used for AIA fetches, and wait for a
+ // CertNetFetcher to be constructed on that thread.
+ base::Thread::Options options(base::MessageLoop::TYPE_IO, 0);
+ base::Thread thread("network_thread");
+ CHECK(thread.StartWithOptions(options));
+ // Owned by this thread, but initialized, used, and shutdown on the network
+ // thread.
+ std::unique_ptr<net::URLRequestContext> context;
+ scoped_refptr<net::CertNetFetcher> cert_net_fetcher;
+ base::WaitableEvent initialization_complete_event(
+ base::WaitableEvent::ResetPolicy::MANUAL,
+ base::WaitableEvent::InitialState::NOT_SIGNALED);
+ thread.task_runner()->PostTask(
+ FROM_HERE, base::Bind(&SetUpOnNetworkThread, &context, &cert_net_fetcher,
+ &initialization_complete_event));
+ initialization_complete_event.Wait();
+
+ // Now that the CertNetFetcher has been created on the network thread,
+ // use it to create a CertIssuerSourceAia.
+ net::CertIssuerSourceAia aia_cert_issuer_source(cert_net_fetcher.get());
path_builder.AddCertIssuerSource(&aia_cert_issuer_source);
- net::TestClosure callback;
- net::CompletionStatus rv = path_builder.Run(callback.closure());
+ // Run the path builder.
+ path_builder.Run();
- if (rv == net::CompletionStatus::ASYNC) {
- DVLOG(1) << "waiting for async completion...";
- callback.WaitForResult();
- DVLOG(1) << "async completed.";
- }
+ // Clean up on the network thread and stop it (which waits for the clean up
+ // task to run).
+ thread.task_runner()->PostTask(
+ FROM_HERE,
+ base::Bind(&ShutdownOnNetworkThread, &context, cert_net_fetcher));
+ thread.Stop();
// TODO(crbug.com/634443): Display any errors/warnings associated with path
// building that were not part of a particular
diff --git a/chromium/net/tools/dns_fuzz_stub/dns_fuzz_stub.cc b/chromium/net/tools/dns_fuzz_stub/dns_fuzz_stub.cc
index ed2a7579aae..5a89bf07235 100644
--- a/chromium/net/tools/dns_fuzz_stub/dns_fuzz_stub.cc
+++ b/chromium/net/tools/dns_fuzz_stub/dns_fuzz_stub.cc
@@ -218,4 +218,3 @@ int main(int argc, char** argv) {
return ret;
}
-
diff --git a/chromium/net/tools/domain_security_preload_generator/bit_writer.cc b/chromium/net/tools/domain_security_preload_generator/bit_writer.cc
new file mode 100644
index 00000000000..fa4384235fd
--- /dev/null
+++ b/chromium/net/tools/domain_security_preload_generator/bit_writer.cc
@@ -0,0 +1,53 @@
+// Copyright (c) 2016 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.
+
+#include "net/tools/domain_security_preload_generator/bit_writer.h"
+
+#include "base/logging.h"
+
+namespace net {
+
+namespace transport_security_state {
+
+BitWriter::BitWriter() {}
+
+BitWriter::~BitWriter() {}
+
+void BitWriter::WriteBits(uint32_t bits, uint8_t number_of_bits) {
+ DCHECK(number_of_bits <= 32);
+ for (uint8_t i = 1; i <= number_of_bits; i++) {
+ uint8_t bit = 1 & (bits >> (number_of_bits - i));
+ WriteBit(bit);
+ }
+}
+
+void BitWriter::WriteBit(uint8_t bit) {
+ current_byte_ |= bit << (7 - used_);
+ used_++;
+ position_++;
+
+ if (used_ == 8) {
+ Flush();
+ }
+}
+
+void BitWriter::Flush() {
+ bytes_.push_back(current_byte_);
+
+ used_ = 0;
+ current_byte_ = 0;
+}
+
+uint8_t BitWriter::BitLength(uint32_t input) const {
+ uint8_t number_of_bits = 0;
+ while (input != 0) {
+ number_of_bits++;
+ input >>= 1;
+ }
+ return number_of_bits;
+}
+
+} // namespace transport_security_state
+
+} // namespace net
diff --git a/chromium/net/tools/domain_security_preload_generator/bit_writer.h b/chromium/net/tools/domain_security_preload_generator/bit_writer.h
new file mode 100644
index 00000000000..9aad7ae0ebd
--- /dev/null
+++ b/chromium/net/tools/domain_security_preload_generator/bit_writer.h
@@ -0,0 +1,61 @@
+// Copyright (c) 2016 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.
+
+#ifndef NET_TOOLS_DOMAIN_SECURITY_PRELOAD_GENERATOR_BIT_WRITER_H_
+#define NET_TOOLS_DOMAIN_SECURITY_PRELOAD_GENERATOR_BIT_WRITER_H_
+
+#include <stdint.h>
+
+#include <vector>
+
+namespace net {
+
+namespace transport_security_state {
+
+// BitWriter acts as a buffer to which bits can be written. The bits are stored
+// as bytes in a vector. BitWriter will buffer bits until it contains 8 bits at
+// which point they will be appended to the vector automatically.
+class BitWriter {
+ public:
+ BitWriter();
+ ~BitWriter();
+
+ // Appends |bit| to the end of the buffer.
+ void WriteBit(uint8_t bit);
+
+ // Appends the |number_of_bits| least-significant bits of |bits| to the end of
+ // the buffer.
+ void WriteBits(uint32_t bits, uint8_t number_of_bits);
+
+ // Appends the buffered bits in |current_byte_| to the |bytes_| vector. When
+ // there are less than 8 bits in the buffer, the empty bits will be filled
+ // with zero's.
+ void Flush();
+ uint32_t position() const { return position_; }
+
+ // Returns a reference to |bytes_|. Make sure to call Flush() first so that
+ // the buffered bits are written to |bytes_| as well.
+ const std::vector<uint8_t>& bytes() const { return bytes_; }
+
+ private:
+ // Returns the minimum number of bits needed to represent |input|.
+ uint8_t BitLength(uint32_t input) const;
+
+ // Buffers bits until they fill a whole byte.
+ uint8_t current_byte_ = 0;
+
+ // The number of bits currently in |current_byte_|.
+ uint8_t used_ = 0;
+
+ // Total number of bits written to this BitWriter.
+ uint32_t position_ = 0;
+
+ std::vector<uint8_t> bytes_;
+};
+
+} // namespace transport_security_state
+
+} // namespace net
+
+#endif // NET_TOOLS_DOMAIN_SECURITY_PRELOAD_GENERATOR_BIT_WRITER_H_
diff --git a/chromium/net/tools/domain_security_preload_generator/cert_util.cc b/chromium/net/tools/domain_security_preload_generator/cert_util.cc
new file mode 100644
index 00000000000..6ab00350960
--- /dev/null
+++ b/chromium/net/tools/domain_security_preload_generator/cert_util.cc
@@ -0,0 +1,155 @@
+// Copyright 2016 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.
+
+#include "net/tools/domain_security_preload_generator/cert_util.h"
+
+#include <string>
+
+#include "base/base64.h"
+#include "base/files/file_util.h"
+#include "base/strings/string_util.h"
+#include "base/strings/stringprintf.h"
+#include "net/tools/domain_security_preload_generator/spki_hash.h"
+#include "third_party/boringssl/src/include/openssl/crypto.h"
+
+using net::transport_security_state::SPKIHash;
+
+namespace {
+
+static const char kPEMBeginBlock[] = "-----BEGIN %s-----";
+static const char kPEMEndBlock[] = "-----END %s-----";
+
+// Tries to extract the BASE64 encoded DER structure from |pem_input| by looking
+// for the block type in |expected_block_type|. Only attempts the locate the
+// first matching block. Other blocks are ignored. Returns true on success and
+// copies the der structure to |*der_output|. Returns false on error.
+bool ParsePEM(base::StringPiece pem_input,
+ base::StringPiece expected_block_type,
+ std::string* der_output) {
+ const std::string& block_start =
+ base::StringPrintf(kPEMBeginBlock, expected_block_type.data());
+ const std::string& block_end =
+ base::StringPrintf(kPEMEndBlock, expected_block_type.data());
+
+ size_t block_start_pos = pem_input.find(block_start);
+ if (block_start_pos == std::string::npos)
+ return false;
+ size_t base64_start_pos = block_start_pos + block_start.size();
+
+ size_t block_end_pos = pem_input.find(block_end, base64_start_pos);
+ if (block_end_pos == std::string::npos)
+ return false;
+
+ base::StringPiece base64_encoded =
+ pem_input.substr(base64_start_pos, block_end_pos - base64_start_pos);
+
+ if (!base::Base64Decode(
+ base::CollapseWhitespaceASCII(base64_encoded.as_string(), true),
+ der_output)) {
+ return false;
+ }
+
+ return true;
+}
+
+// Attempts to extract the first entry of type |nid| from |*name|. Returns true
+// if the field exists and was extracted. Returns false when the field was not
+// found or the data could not be extracted.
+bool ExtractFieldFromX509Name(X509_NAME* name, int nid, std::string* field) {
+ int index = X509_NAME_get_index_by_NID(name, nid, -1);
+ if (index == -1) {
+ return false;
+ }
+
+ X509_NAME_ENTRY* entry = X509_NAME_get_entry(name, index);
+ if (!entry) {
+ return false;
+ }
+
+ ASN1_STRING* data = X509_NAME_ENTRY_get_data(entry);
+ if (!data) {
+ return false;
+ }
+
+ uint8_t* buffer = nullptr;
+ size_t length = ASN1_STRING_to_UTF8(&buffer, data);
+ field->assign(reinterpret_cast<const char*>(buffer), length);
+ OPENSSL_free(buffer);
+ return true;
+}
+
+} // namespace
+
+bssl::UniquePtr<X509> GetX509CertificateFromPEM(base::StringPiece pem_data) {
+ std::string der;
+ if (!ParsePEM(pem_data, "CERTIFICATE", &der)) {
+ return bssl::UniquePtr<X509>();
+ }
+
+ const uint8_t* der_data = reinterpret_cast<const uint8_t*>(der.c_str());
+ return bssl::UniquePtr<X509>(
+ d2i_X509(NULL, &der_data, base::checked_cast<long>(der.size())));
+}
+
+bool ExtractSubjectNameFromCertificate(X509* certificate, std::string* name) {
+ DCHECK(certificate);
+ X509_NAME* subject = X509_get_subject_name(certificate);
+ if (!subject) {
+ return false;
+ }
+
+ std::string result;
+ // Try extracting the common name first.
+ if (!ExtractFieldFromX509Name(subject, NID_commonName, &result) ||
+ result.empty()) {
+ std::string organization;
+ if (!ExtractFieldFromX509Name(subject, NID_organizationName,
+ &organization)) {
+ return false;
+ }
+
+ std::string organizational_unit;
+ if (!ExtractFieldFromX509Name(subject, NID_organizationalUnitName,
+ &organizational_unit)) {
+ return false;
+ }
+ result = organization + " " + organizational_unit;
+ }
+
+ name->assign(result);
+ return true;
+}
+
+bool CalculateSPKIHashFromCertificate(X509* certificate, SPKIHash* out_hash) {
+ DCHECK(certificate);
+ bssl::UniquePtr<EVP_PKEY> key(X509_get_pubkey(certificate));
+ if (!key) {
+ return false;
+ }
+
+ uint8_t* spki_der;
+ size_t spki_der_len;
+ bssl::ScopedCBB cbb;
+ if (!CBB_init(cbb.get(), 0) ||
+ !EVP_marshal_public_key(cbb.get(), key.get()) ||
+ !CBB_finish(cbb.get(), &spki_der, &spki_der_len)) {
+ return false;
+ }
+
+ out_hash->CalculateFromBytes(spki_der, spki_der_len);
+ OPENSSL_free(spki_der);
+ return true;
+}
+
+bool CalculateSPKIHashFromKey(base::StringPiece pem_key, SPKIHash* out_hash) {
+ std::string der;
+ bool result = ParsePEM(pem_key, "PUBLIC KEY", &der);
+ if (!result) {
+ return false;
+ }
+
+ out_hash->CalculateFromBytes(reinterpret_cast<const uint8_t*>(der.data()),
+ der.size());
+ return true;
+}
diff --git a/chromium/net/tools/domain_security_preload_generator/cert_util.h b/chromium/net/tools/domain_security_preload_generator/cert_util.h
new file mode 100644
index 00000000000..6d0a3f4f579
--- /dev/null
+++ b/chromium/net/tools/domain_security_preload_generator/cert_util.h
@@ -0,0 +1,46 @@
+// Copyright 2016 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.
+
+#ifndef NET_TOOLS_DOMAIN_SECURITY_PRELOAD_GENERATOR_CERT_UTIL_H_
+#define NET_TOOLS_DOMAIN_SECURITY_PRELOAD_GENERATOR_CERT_UTIL_H_
+
+#include <stdint.h>
+
+#include "base/strings/string_piece.h"
+#include "third_party/boringssl/src/include/openssl/x509v3.h"
+
+namespace net {
+
+namespace transport_security_state {
+class SPKIHash;
+} // namespace transport_security_state
+
+} // namespace net
+
+// Decodes the PEM block in |pem_data| and attempts to parse the resulting
+// structure. Returns a pointer to a X509 instance if successful and NULL
+// otherwise.
+bssl::UniquePtr<X509> GetX509CertificateFromPEM(base::StringPiece pem_data);
+
+// Extracts the SubjectPublicKeyInfo from |*certificate| and copies its SHA256
+// digest to |*out_hash|. Returns true on success and false on failure.
+bool CalculateSPKIHashFromCertificate(
+ X509* certificate,
+ net::transport_security_state::SPKIHash* out_hash);
+
+// Extracts the name from |*certificate| and copies the result to |*name|.
+// Returns true on success and false on failure.
+// On success |*name| will contain the Subject's CommonName if available or the
+// concatenation |OrganizationName| + " " + |OrganizationalUnitName| otherwise.
+bool ExtractSubjectNameFromCertificate(X509* certificate, std::string* name);
+
+// Decodes the PEM block in |pem_key| and sets |*out_hash| to the SHA256 digest
+// of the resulting structure. The encoded PEM block in |pem_key| is expected to
+// be a SubjectPublicKeyInfo structure. Returns true on success and false on
+// failure.
+bool CalculateSPKIHashFromKey(
+ base::StringPiece pem_key,
+ net::transport_security_state::SPKIHash* out_hash);
+
+#endif // NET_TOOLS_DOMAIN_SECURITY_PRELOAD_GENERATOR_CERT_UTIL_H_
diff --git a/chromium/net/tools/domain_security_preload_generator/domain_security_entry.cc b/chromium/net/tools/domain_security_preload_generator/domain_security_entry.cc
new file mode 100644
index 00000000000..cbc8a86c4c6
--- /dev/null
+++ b/chromium/net/tools/domain_security_preload_generator/domain_security_entry.cc
@@ -0,0 +1,15 @@
+// Copyright (c) 2016 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.
+#include "net/tools/domain_security_preload_generator/domain_security_entry.h"
+
+namespace net {
+
+namespace transport_security_state {
+
+DomainSecurityEntry::DomainSecurityEntry() {}
+DomainSecurityEntry::~DomainSecurityEntry() {}
+
+} // namespace transport_security_state
+
+} // namespace \ No newline at end of file
diff --git a/chromium/net/tools/domain_security_preload_generator/domain_security_entry.h b/chromium/net/tools/domain_security_preload_generator/domain_security_entry.h
new file mode 100644
index 00000000000..e9d01f3cd25
--- /dev/null
+++ b/chromium/net/tools/domain_security_preload_generator/domain_security_entry.h
@@ -0,0 +1,60 @@
+// Copyright (c) 2016 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.
+
+#ifndef NET_TOOLS_DOMAIN_SECURITY_PRELOAD_GENERATOR_DOMAIN_SECURITY_ENTRY_H_
+#define NET_TOOLS_DOMAIN_SECURITY_PRELOAD_GENERATOR_DOMAIN_SECURITY_ENTRY_H_
+
+#include <memory>
+#include <string>
+#include <vector>
+
+namespace net {
+
+namespace transport_security_state {
+
+// DomainSecurityEntry represents a preloaded entry.
+struct DomainSecurityEntry {
+ DomainSecurityEntry();
+ ~DomainSecurityEntry();
+
+ std::string hostname;
+
+ bool include_subdomains = false;
+ bool force_https = false;
+
+ bool hpkp_include_subdomains = false;
+ std::string pinset;
+
+ bool expect_ct = false;
+ std::string expect_ct_report_uri;
+
+ bool expect_staple = false;
+ bool expect_staple_include_subdomains = false;
+ std::string expect_staple_report_uri;
+};
+
+using DomainSecurityEntries = std::vector<std::unique_ptr<DomainSecurityEntry>>;
+
+// TODO(Martijnc): Remove the domain IDs from the preload format.
+// https://crbug.com/661206.
+using DomainIDList = std::vector<std::string>;
+
+// ReversedEntry points to a DomainSecurityEntry and contains the reversed
+// hostname for that entry. This is used to construct the trie.
+struct ReversedEntry {
+ ReversedEntry(std::vector<uint8_t> reversed_name,
+ const DomainSecurityEntry* entry);
+ ~ReversedEntry();
+
+ std::vector<uint8_t> reversed_name;
+ const DomainSecurityEntry* entry;
+};
+
+using ReversedEntries = std::vector<std::unique_ptr<ReversedEntry>>;
+
+} // namespace transport_security_state
+
+} // namespace net
+
+#endif // NET_TOOLS_DOMAIN_SECURITY_PRELOAD_GENERATOR_DOMAIN_SECURITY_ENTRY_H_
diff --git a/chromium/net/tools/domain_security_preload_generator/domain_security_preload_generator.cc b/chromium/net/tools/domain_security_preload_generator/domain_security_preload_generator.cc
new file mode 100644
index 00000000000..9ad333ecd63
--- /dev/null
+++ b/chromium/net/tools/domain_security_preload_generator/domain_security_preload_generator.cc
@@ -0,0 +1,632 @@
+// Copyright 2016 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.
+
+#include <iostream>
+
+#include <map>
+#include <set>
+#include <string>
+#include <vector>
+
+#include "base/command_line.h"
+#include "base/files/file_util.h"
+#include "base/json/json_reader.h"
+#include "base/path_service.h"
+#include "base/strings/string_piece.h"
+#include "base/strings/string_split.h"
+#include "base/strings/string_util.h"
+#include "base/strings/utf_string_conversions.h"
+#include "base/values.h"
+#include "crypto/openssl_util.h"
+#include "net/tools/domain_security_preload_generator/cert_util.h"
+#include "net/tools/domain_security_preload_generator/domain_security_entry.h"
+#include "net/tools/domain_security_preload_generator/pinset.h"
+#include "net/tools/domain_security_preload_generator/pinsets.h"
+#include "net/tools/domain_security_preload_generator/preloaded_state_generator.h"
+#include "net/tools/domain_security_preload_generator/spki_hash.h"
+#include "third_party/boringssl/src/include/openssl/x509v3.h"
+
+using net::transport_security_state::DomainSecurityEntry;
+using net::transport_security_state::DomainSecurityEntries;
+using net::transport_security_state::Pinset;
+using net::transport_security_state::Pinsets;
+using net::transport_security_state::PreloadedStateGenerator;
+using net::transport_security_state::DomainIDList;
+using net::transport_security_state::SPKIHash;
+
+namespace {
+
+// Print the command line help.
+void PrintHelp() {
+ std::cout << "domain_security_preload_generator <json-file> <pins-file>"
+ << " <template-file> <output-file> [-v]" << std::endl;
+}
+
+// Parses the |json| string and copies the items under the "entries" key to
+// |entries|, the pinsets under the "pinsets" key to |pinsets|, and the domain
+// IDs under the "domain_ids" key to |domain_ids|.
+//
+// More info on the format can be found in
+// net/http/transport_security_state_static.json
+bool ParseJSON(const std::string& json,
+ DomainSecurityEntries* entries,
+ Pinsets* pinsets,
+ DomainIDList* domain_ids) {
+ std::unique_ptr<base::Value> value = base::JSONReader::Read(json);
+ base::DictionaryValue* dict_value = nullptr;
+ if (!value.get() || !value->GetAsDictionary(&dict_value)) {
+ std::cerr << "Could not parse the input JSON" << std::endl;
+ return false;
+ }
+
+ const base::ListValue* preload_entries = nullptr;
+ if (!dict_value->GetList("entries", &preload_entries)) {
+ std::cerr << "Could not parse the entries in the input JSON" << std::endl;
+ return false;
+ }
+
+ for (size_t i = 0; i < preload_entries->GetSize(); ++i) {
+ const base::DictionaryValue* parsed = nullptr;
+ if (!preload_entries->GetDictionary(i, &parsed)) {
+ std::cerr << "Could not parse entry " << i << std::endl;
+ return false;
+ }
+
+ std::unique_ptr<DomainSecurityEntry> entry(new DomainSecurityEntry());
+
+ if (!parsed->GetString("name", &entry->hostname)) {
+ std::cerr << "Could not extract the name for entry " << i << std::endl;
+ return false;
+ }
+
+ parsed->GetBoolean("include_subdomains", &entry->include_subdomains);
+ std::string mode;
+ parsed->GetString("mode", &mode);
+ entry->force_https = (mode == "force-https");
+ parsed->GetBoolean("include_subdomains_for_pinning",
+ &entry->hpkp_include_subdomains);
+ parsed->GetString("pins", &entry->pinset);
+ parsed->GetBoolean("expect_ct", &entry->expect_ct);
+ parsed->GetString("expect_ct_report_uri", &entry->expect_ct_report_uri);
+ parsed->GetBoolean("expect_staple", &entry->expect_staple);
+ parsed->GetBoolean("include_subdomains_for_expect_staple",
+ &entry->expect_staple_include_subdomains);
+ parsed->GetString("expect_staple_report_uri",
+ &entry->expect_staple_report_uri);
+
+ entries->push_back(std::move(entry));
+ }
+
+ const base::ListValue* pinsets_list = nullptr;
+ if (!dict_value->GetList("pinsets", &pinsets_list)) {
+ std::cerr << "Could not parse the pinsets in the input JSON" << std::endl;
+ return false;
+ }
+
+ for (size_t i = 0; i < pinsets_list->GetSize(); ++i) {
+ const base::DictionaryValue* parsed = nullptr;
+ if (!pinsets_list->GetDictionary(i, &parsed)) {
+ std::cerr << "Could not parse pinset " << i << std::endl;
+ return false;
+ }
+
+ std::string name;
+ if (!parsed->GetString("name", &name)) {
+ std::cerr << "Could not extract the name for pinset " << i << std::endl;
+ return false;
+ }
+
+ std::string report_uri;
+ parsed->GetString("report_uri", &report_uri);
+
+ std::unique_ptr<Pinset> pinset(new Pinset(name, report_uri));
+
+ const base::ListValue* pinset_static_hashes_list = nullptr;
+ if (parsed->GetList("static_spki_hashes", &pinset_static_hashes_list)) {
+ for (size_t i = 0; i < pinset_static_hashes_list->GetSize(); ++i) {
+ std::string hash;
+ pinset_static_hashes_list->GetString(i, &hash);
+ pinset->AddStaticSPKIHash(hash);
+ }
+ }
+
+ const base::ListValue* pinset_bad_static_hashes_list = nullptr;
+ if (parsed->GetList("bad_static_spki_hashes",
+ &pinset_bad_static_hashes_list)) {
+ for (size_t i = 0; i < pinset_bad_static_hashes_list->GetSize(); ++i) {
+ std::string hash;
+ pinset_bad_static_hashes_list->GetString(i, &hash);
+ pinset->AddBadStaticSPKIHash(hash);
+ }
+ }
+
+ pinsets->RegisterPinset(std::move(pinset));
+ }
+
+ // TODO(Martijnc): Remove the domain IDs from the preload format.
+ // https://crbug.com/661206.
+ const base::ListValue* domain_ids_list = nullptr;
+ if (!dict_value->GetList("domain_ids", &domain_ids_list)) {
+ std::cerr << "Failed parsing JSON (domain_ids)" << std::endl;
+ return false;
+ }
+
+ for (size_t i = 0; i < domain_ids_list->GetSize(); ++i) {
+ std::string domain;
+ domain_ids_list->GetString(i, &domain);
+ domain_ids->push_back(domain);
+ }
+
+ return true;
+}
+
+bool IsImportantWordInCertificateName(base::StringPiece name) {
+ const char* const important_words[] = {"Universal", "Global", "EV", "G1",
+ "G2", "G3", "G4", "G5"};
+ for (auto* important_word : important_words) {
+ if (name == important_word) {
+ return true;
+ }
+ }
+ return false;
+}
+
+// Strips all characters not matched by the RegEx [A-Za-z0-9_] from |name| and
+// returns the result.
+std::string FilterName(base::StringPiece name) {
+ std::string filtered;
+ for (const char& character : name) {
+ if ((character >= '0' && character <= '9') ||
+ (character >= 'a' && character <= 'z') ||
+ (character >= 'A' && character <= 'Z') || character == '_') {
+ filtered += character;
+ }
+ }
+ return base::ToLowerASCII(filtered);
+}
+
+// Returns true if |pin_name| is a reasonable match for the certificate name
+// |name|.
+bool MatchCertificateName(base::StringPiece name, base::StringPiece pin_name) {
+ std::vector<base::StringPiece> words = base::SplitStringPiece(
+ name, " ", base::TRIM_WHITESPACE, base::SPLIT_WANT_ALL);
+ if (words.empty()) {
+ std::cerr << "no words in certificate name" << std::endl;
+ return false;
+ }
+ base::StringPiece first_word = words[0];
+
+ if (first_word.ends_with(",")) {
+ first_word = first_word.substr(0, first_word.size() - 1);
+ }
+
+ if (first_word.starts_with("*.")) {
+ first_word = first_word.substr(2, first_word.size() - 2);
+ }
+
+ size_t pos = first_word.find('.');
+ if (pos != std::string::npos) {
+ first_word = first_word.substr(0, first_word.size() - pos);
+ }
+
+ pos = first_word.find('-');
+ if (pos != std::string::npos) {
+ first_word = first_word.substr(0, first_word.size() - pos);
+ }
+
+ if (first_word.empty()) {
+ std::cerr << "first word of certificate name is empty" << std::endl;
+ return false;
+ }
+
+ std::string filtered_word = FilterName(first_word);
+ first_word = filtered_word;
+ if (!base::EqualsCaseInsensitiveASCII(pin_name.substr(0, first_word.size()),
+ first_word)) {
+ std::cerr << "the first word of the certificate name ("
+ << first_word.as_string()
+ << ") isn't a prefix of the variable name ("
+ << pin_name.as_string() << ")" << std::endl;
+ return false;
+ }
+
+ for (size_t i = 0; i < words.size(); ++i) {
+ const base::StringPiece& word = words[i];
+ if (word == "Class" && (i + 1) < words.size()) {
+ std::string class_name = word.as_string();
+ words[i + 1].AppendToString(&class_name);
+
+ size_t pos = pin_name.find(class_name);
+ if (pos == std::string::npos) {
+ std::cerr << "class specification doesn't appear in the variable name"
+ << std::endl;
+ return false;
+ }
+ } else if (word.size() == 1 && word[0] >= '0' && word[0] <= '9') {
+ size_t pos = pin_name.find(word);
+ if (pos == std::string::npos) {
+ std::cerr << "number doesn't appear in the variable name" << std::endl;
+ return false;
+ }
+ } else if (IsImportantWordInCertificateName(word)) {
+ size_t pos = pin_name.find(word);
+ if (pos == std::string::npos) {
+ std::cerr << word.as_string() << " doesn't appear in the variable name"
+ << std::endl;
+ return false;
+ }
+ }
+ }
+
+ return true;
+}
+
+// Returns true iff |candidate| is not empty, the first character is in the
+// range A-Z, and the remaining characters are in the ranges a-Z, 0-9, or '_'.
+bool IsValidName(const std::string& candidate) {
+ if (candidate.empty() || candidate[0] < 'A' || candidate[0] > 'Z') {
+ return false;
+ }
+
+ bool isValid = true;
+ for (const char& character : candidate) {
+ isValid = (character >= '0' && character <= '9') ||
+ (character >= 'a' && character <= 'z') ||
+ (character >= 'A' && character <= 'Z') || character == '_';
+ if (!isValid) {
+ return false;
+ }
+ }
+ return true;
+}
+
+static const char kStartOfCert[] = "-----BEGIN CERTIFICATE";
+static const char kStartOfPublicKey[] = "-----BEGIN PUBLIC KEY";
+static const char kEndOfCert[] = "-----END CERTIFICATE";
+static const char kEndOfPublicKey[] = "-----END PUBLIC KEY";
+static const char kStartOfSHA256[] = "sha256/";
+
+enum class CertificateParserState {
+ PRE_NAME,
+ POST_NAME,
+ IN_CERTIFICATE,
+ IN_PUBLIC_KEY
+};
+
+// Extracts SPKI information from the preloaded pins file. The SPKI's can be
+// in the form of a PEM certificate, a PEM public key, or a BASE64 string.
+//
+// More info on the format can be found in
+// net/http/transport_security_state_static.pins
+bool ParseCertificatesFile(const std::string& certs_input, Pinsets* pinsets) {
+ std::istringstream input_stream(certs_input);
+ std::string line;
+ CertificateParserState current_state = CertificateParserState::PRE_NAME;
+
+ const base::CompareCase& compare_mode = base::CompareCase::INSENSITIVE_ASCII;
+ std::string name;
+ std::string buffer;
+ std::string subject_name;
+ bssl::UniquePtr<X509> certificate;
+ SPKIHash hash;
+
+ for (std::string line; std::getline(input_stream, line);) {
+ if (line[0] == '#') {
+ continue;
+ }
+
+ if (line.empty() && current_state == CertificateParserState::PRE_NAME) {
+ continue;
+ }
+
+ switch (current_state) {
+ case CertificateParserState::PRE_NAME:
+ if (!IsValidName(line)) {
+ std::cerr << "Invalid name in certificates file: " << line;
+ return false;
+ }
+ name = line;
+ current_state = CertificateParserState::POST_NAME;
+ break;
+ case CertificateParserState::POST_NAME:
+ if (base::StartsWith(line, kStartOfSHA256, compare_mode)) {
+ if (!hash.FromString(line)) {
+ std::cerr << "Invalid hash value in certificate file for " << name
+ << std::endl;
+ return false;
+ }
+
+ pinsets->RegisterSPKIHash(name, hash);
+ current_state = CertificateParserState::PRE_NAME;
+ } else if (base::StartsWith(line, kStartOfCert, compare_mode)) {
+ buffer = line + '\n';
+ current_state = CertificateParserState::IN_CERTIFICATE;
+ } else if (base::StartsWith(line, kStartOfPublicKey, compare_mode)) {
+ buffer = line + '\n';
+ current_state = CertificateParserState::IN_PUBLIC_KEY;
+ } else {
+ std::cerr << "Invalid value in certificates file for " << name
+ << std::endl;
+ return false;
+ }
+ break;
+ case CertificateParserState::IN_CERTIFICATE:
+ buffer += line + '\n';
+ if (!base::StartsWith(line, kEndOfCert, compare_mode)) {
+ continue;
+ }
+
+ certificate = GetX509CertificateFromPEM(buffer);
+ if (!certificate) {
+ std::cerr << "Could not parse certificate " << name << std::endl;
+ return false;
+ }
+
+ if (!CalculateSPKIHashFromCertificate(certificate.get(), &hash)) {
+ std::cerr << "Could not extract SPKI from certificate " << name
+ << std::endl;
+ return false;
+ }
+
+ if (!ExtractSubjectNameFromCertificate(certificate.get(),
+ &subject_name)) {
+ std::cerr << "Could not extract name from certificate " << name
+ << std::endl;
+ return false;
+ }
+
+ if (!MatchCertificateName(subject_name, name)) {
+ std::cerr << name << " is not a reasonable name for " << subject_name
+ << std::endl;
+ return false;
+ }
+
+ pinsets->RegisterSPKIHash(name, hash);
+ current_state = CertificateParserState::PRE_NAME;
+ break;
+ case CertificateParserState::IN_PUBLIC_KEY:
+ buffer += line + '\n';
+ if (!base::StartsWith(line, kEndOfPublicKey, compare_mode)) {
+ continue;
+ }
+
+ if (!CalculateSPKIHashFromKey(buffer, &hash)) {
+ std::cerr << "Parsing of the public key " << name << " failed"
+ << std::endl;
+ return false;
+ }
+
+ pinsets->RegisterSPKIHash(name, hash);
+ current_state = CertificateParserState::PRE_NAME;
+ break;
+ default:
+ DCHECK(false) << "Unknown parser state";
+ }
+ }
+
+ return true;
+}
+
+// Checks if there are pins with the same name or the same hash.
+bool CheckForDuplicatePins(const Pinsets& pinsets) {
+ std::set<std::string> seen_names;
+ std::map<std::string, std::string> seen_hashes;
+
+ for (const auto& pin : pinsets.spki_hashes()) {
+ if (seen_names.find(pin.first) != seen_names.cend()) {
+ std::cerr << "Duplicate pin name " << pin.first << std::endl;
+ return false;
+ }
+ seen_names.insert(pin.first);
+
+ std::string hash =
+ std::string(pin.second.data(), pin.second.data() + pin.second.size());
+ std::map<std::string, std::string>::iterator it = seen_hashes.find(hash);
+ if (it != seen_hashes.cend()) {
+ std::cerr << "Duplicate pin hash for " << pin.first
+ << ", already seen as " << it->second << std::endl;
+ return false;
+ }
+ seen_hashes.insert(std::pair<std::string, std::string>(hash, pin.first));
+ }
+
+ return true;
+}
+
+// Checks if there are pinsets that reference non-existing pins, if two
+// pinsets share the same name, or if there are unused pins.
+bool CheckCertificatesInPinsets(const Pinsets& pinsets) {
+ std::set<std::string> pin_names;
+ for (const auto& pin : pinsets.spki_hashes()) {
+ pin_names.insert(pin.first);
+ }
+
+ std::set<std::string> used_pin_names;
+ std::set<std::string> pinset_names;
+ for (const auto& pinset : pinsets.pinsets()) {
+ if (pinset_names.find(pinset.second->name()) != pinset_names.cend()) {
+ std::cerr << "Duplicate pinset name " << pinset.second->name()
+ << std::endl;
+ return false;
+ }
+ pinset_names.insert(pinset.second->name());
+
+ const std::vector<std::string>& good_hashes =
+ pinset.second->static_spki_hashes();
+ const std::vector<std::string>& bad_hashes =
+ pinset.second->bad_static_spki_hashes();
+
+ std::vector<std::string> all_pin_names;
+ all_pin_names.reserve(good_hashes.size() + bad_hashes.size());
+ all_pin_names.insert(all_pin_names.end(), good_hashes.begin(),
+ good_hashes.end());
+ all_pin_names.insert(all_pin_names.end(), bad_hashes.begin(),
+ bad_hashes.end());
+
+ for (const auto& pin_name : all_pin_names) {
+ if (pin_names.find(pin_name) == pin_names.cend()) {
+ std::cerr << "Unknown pin: " << pin_name << std::endl;
+ return false;
+ }
+ used_pin_names.insert(pin_name);
+ }
+ }
+
+ for (const auto& pin_name : pin_names) {
+ if (used_pin_names.find(pin_name) == used_pin_names.cend()) {
+ std::cerr << "Unused pin: " << pin_name << std::endl;
+ return false;
+ }
+ }
+
+ return true;
+}
+
+// Checks if there are two or more entries for the same hostname.
+bool CheckDuplicateEntries(const DomainSecurityEntries& entries) {
+ std::set<std::string> seen_entries;
+ for (const auto& entry : entries) {
+ if (seen_entries.find(entry->hostname) != seen_entries.cend()) {
+ std::cerr << "Duplicate entry for " << entry->hostname << std::endl;
+ return false;
+ }
+ seen_entries.insert(entry->hostname);
+ }
+ return true;
+}
+
+// Checks for entries which have no effect.
+bool CheckNoopEntries(const DomainSecurityEntries& entries) {
+ for (const auto& entry : entries) {
+ if (!entry->force_https && entry->pinset.empty() && !entry->expect_ct &&
+ !entry->expect_staple) {
+ if (entry->hostname == "learn.doubleclick.net") {
+ // This entry is deliberately used as an exclusion.
+ continue;
+ }
+
+ std::cerr
+ << "Entry for " + entry->hostname +
+ " has no mode, no pins and is not expect-CT or expect-staple"
+ << std::endl;
+ return false;
+ }
+ }
+ return true;
+}
+
+// Checks all entries for incorrect usage of the includeSubdomains flags.
+bool CheckSubdomainsFlags(const DomainSecurityEntries& entries) {
+ for (const auto& entry : entries) {
+ if (entry->include_subdomains && entry->hpkp_include_subdomains) {
+ std::cerr << "Entry for \"" << entry->hostname
+ << "\" sets include_subdomains_for_pinning but also sets "
+ "include_subdomains, which implies it"
+ << std::endl;
+ return false;
+ }
+ }
+ return true;
+}
+
+} // namespace
+
+int main(int argc, char* argv[]) {
+ crypto::EnsureOpenSSLInit();
+
+ base::CommandLine::Init(argc, argv);
+ const base::CommandLine& command_line =
+ *base::CommandLine::ForCurrentProcess();
+
+#if defined(OS_WIN)
+ std::vector<std::string> args;
+ base::CommandLine::StringVector wide_args = command_line.GetArgs();
+ for (const auto& arg : wide_args) {
+ args.push_back(base::WideToUTF8(arg));
+ }
+#else
+ base::CommandLine::StringVector args = command_line.GetArgs();
+#endif
+ if (args.size() < 4U) {
+ PrintHelp();
+ return 1;
+ }
+
+ bool verbose = command_line.HasSwitch("v");
+
+ base::FilePath json_filepath = base::FilePath::FromUTF8Unsafe(argv[1]);
+ if (!base::PathExists(json_filepath)) {
+ std::cerr << "Input JSON file doesn't exist." << std::endl;
+ return 1;
+ }
+ json_filepath = base::MakeAbsoluteFilePath(json_filepath);
+
+ std::string json_input;
+ if (!base::ReadFileToString(json_filepath, &json_input)) {
+ std::cerr << "Could not read input JSON file." << std::endl;
+ return 1;
+ }
+
+ base::FilePath pins_filepath = base::FilePath::FromUTF8Unsafe(argv[2]);
+ if (!base::PathExists(pins_filepath)) {
+ std::cerr << "Input pins file doesn't exist." << std::endl;
+ return 1;
+ }
+ pins_filepath = base::MakeAbsoluteFilePath(pins_filepath);
+
+ std::string certs_input;
+ if (!base::ReadFileToString(pins_filepath, &certs_input)) {
+ std::cerr << "Could not read input pins file." << std::endl;
+ return 1;
+ }
+
+ DomainSecurityEntries entries;
+ Pinsets pinsets;
+ DomainIDList domain_ids;
+
+ if (!ParseCertificatesFile(certs_input, &pinsets)) {
+ std::cerr << "Error while parsing the pins file." << std::endl;
+ return 1;
+ }
+ if (!ParseJSON(json_input, &entries, &pinsets, &domain_ids)) {
+ std::cerr << "Error while parsing the JSON file." << std::endl;
+ return 1;
+ }
+
+ if (!CheckDuplicateEntries(entries) || !CheckNoopEntries(entries) ||
+ !CheckSubdomainsFlags(entries) || !CheckForDuplicatePins(pinsets) ||
+ !CheckCertificatesInPinsets(pinsets)) {
+ std::cerr << "Checks failed. Aborting." << std::endl;
+ return 1;
+ }
+
+ base::FilePath template_path = base::FilePath::FromUTF8Unsafe(argv[3]);
+ if (!base::PathExists(template_path)) {
+ std::cerr << "Template file doesn't exist." << std::endl;
+ return 1;
+ }
+ template_path = base::MakeAbsoluteFilePath(template_path);
+
+ std::string preload_template;
+ if (!base::ReadFileToString(template_path, &preload_template)) {
+ std::cerr << "Could not read template file." << std::endl;
+ return 1;
+ }
+
+ std::string result;
+ PreloadedStateGenerator generator;
+ result = generator.Generate(preload_template, entries, domain_ids, pinsets,
+ verbose);
+
+ base::FilePath output_path;
+ output_path = base::FilePath::FromUTF8Unsafe(argv[4]);
+
+ if (base::WriteFile(output_path, result.c_str(),
+ static_cast<uint32_t>(result.size())) <= 0) {
+ std::cerr << "Failed to write output." << std::endl;
+ return 1;
+ }
+
+ return 0;
+}
diff --git a/chromium/net/tools/domain_security_preload_generator/huffman/huffman_frequency_tracker.cc b/chromium/net/tools/domain_security_preload_generator/huffman/huffman_frequency_tracker.cc
new file mode 100644
index 00000000000..f2e68b7c3ef
--- /dev/null
+++ b/chromium/net/tools/domain_security_preload_generator/huffman/huffman_frequency_tracker.cc
@@ -0,0 +1,159 @@
+// Copyright (c) 2016 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.
+
+#include "net/tools/domain_security_preload_generator/huffman/huffman_frequency_tracker.h"
+
+#include <algorithm>
+
+#include "base/logging.h"
+
+namespace net {
+
+namespace transport_security_state {
+
+namespace {
+
+class HuffmanNode {
+ public:
+ HuffmanNode(uint8_t value,
+ uint32_t count,
+ std::unique_ptr<HuffmanNode> left,
+ std::unique_ptr<HuffmanNode> right)
+ : value_(value),
+ count_(count),
+ left_(std::move(left)),
+ right_(std::move(right)) {}
+ ~HuffmanNode() {}
+
+ bool IsLeaf() const {
+ return left_.get() == nullptr && right_.get() == nullptr;
+ }
+
+ uint8_t value() const { return value_; }
+ uint32_t count() const { return count_; }
+ const std::unique_ptr<HuffmanNode>& left() const { return left_; }
+ const std::unique_ptr<HuffmanNode>& right() const { return right_; }
+
+ private:
+ uint8_t value_;
+ uint32_t count_;
+ std::unique_ptr<HuffmanNode> left_;
+ std::unique_ptr<HuffmanNode> right_;
+};
+
+bool CompareNodes(const std::unique_ptr<HuffmanNode>& lhs,
+ const std::unique_ptr<HuffmanNode>& rhs) {
+ return lhs->count() < rhs->count();
+}
+
+} // namespace
+
+HuffmanFrequencyTracker::HuffmanFrequencyTracker() {}
+
+HuffmanFrequencyTracker::~HuffmanFrequencyTracker() {}
+
+void HuffmanFrequencyTracker::RecordUsage(uint8_t character) {
+ counts_[character] += 1;
+}
+
+HuffmanRepresentationTable HuffmanFrequencyTracker::ToTable() {
+ HuffmanRepresentationTable table;
+ std::unique_ptr<HuffmanNode> node(BuildTree());
+
+ TreeToTable(node.get(), 0, 0, &table);
+ return table;
+}
+
+void HuffmanFrequencyTracker::TreeToTable(HuffmanNode* node,
+ uint32_t bits,
+ uint32_t number_of_bits,
+ HuffmanRepresentationTable* table) {
+ if (node->IsLeaf()) {
+ HuffmanRepresentation item;
+ item.bits = bits;
+ item.number_of_bits = number_of_bits;
+
+ table->insert(HuffmanRepresentationPair(node->value(), item));
+ } else {
+ uint32_t new_bits = bits << 1;
+ TreeToTable(node->left().get(), new_bits, number_of_bits + 1, table);
+ TreeToTable(node->right().get(), new_bits | 1, number_of_bits + 1, table);
+ }
+}
+
+std::vector<uint8_t> HuffmanFrequencyTracker::ToVector() {
+ std::vector<uint8_t> bytes;
+ std::unique_ptr<HuffmanNode> node(BuildTree());
+ WriteToVector(node.get(), &bytes);
+ return bytes;
+}
+
+uint32_t HuffmanFrequencyTracker::WriteToVector(HuffmanNode* node,
+ std::vector<uint8_t>* vector) {
+ uint8_t left_value;
+ uint8_t right_value;
+ uint32_t child_position;
+
+ if (node->left()->IsLeaf()) {
+ left_value = 128 | node->left()->value();
+ } else {
+ child_position = WriteToVector(node->left().get(), vector);
+ CHECK(child_position < 512) << "huffman tree too large";
+ left_value = child_position / 2;
+ }
+
+ if (node->right()->IsLeaf()) {
+ right_value = 128 | node->right()->value();
+ } else {
+ child_position = WriteToVector(node->right().get(), vector);
+ CHECK(child_position < 512) << "huffman tree to large";
+ right_value = child_position / 2;
+ }
+
+ uint32_t position = static_cast<uint32_t>(vector->size());
+ vector->push_back(left_value);
+ vector->push_back(right_value);
+ return position;
+}
+
+std::unique_ptr<HuffmanNode> HuffmanFrequencyTracker::BuildTree() {
+ std::vector<std::unique_ptr<HuffmanNode>> nodes;
+ nodes.reserve(counts_.size());
+
+ for (const auto& item : counts_) {
+ if (item.second > 0) {
+ std::unique_ptr<HuffmanNode> node(
+ new HuffmanNode(item.first, item.second, nullptr, nullptr));
+ nodes.push_back(std::move(node));
+ }
+ }
+
+ if (nodes.size() < 2) {
+ return std::move(nodes[0]);
+ }
+
+ std::stable_sort(nodes.begin(), nodes.end(), CompareNodes);
+
+ while (nodes.size() > 1) {
+ std::unique_ptr<HuffmanNode> a = std::move(nodes[0]);
+ std::unique_ptr<HuffmanNode> b = std::move(nodes[1]);
+
+ uint32_t count_a = a->count();
+ uint32_t count_b = b->count();
+
+ std::unique_ptr<HuffmanNode> parent(
+ new HuffmanNode(0, count_a + count_b, std::move(a), std::move(b)));
+
+ nodes.erase(nodes.begin());
+ nodes[0] = std::move(parent);
+
+ std::stable_sort(nodes.begin(), nodes.end(), CompareNodes);
+ }
+
+ return std::move(nodes[0]);
+}
+
+} // namespace transport_security_state
+
+} // namespace net
diff --git a/chromium/net/tools/domain_security_preload_generator/huffman/huffman_frequency_tracker.h b/chromium/net/tools/domain_security_preload_generator/huffman/huffman_frequency_tracker.h
new file mode 100644
index 00000000000..e8c78ebaa22
--- /dev/null
+++ b/chromium/net/tools/domain_security_preload_generator/huffman/huffman_frequency_tracker.h
@@ -0,0 +1,84 @@
+// Copyright (c) 2016 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.
+
+#ifndef NET_TOOLS_DOMAIN_SECURITY_PRELOAD_GENERATOR_HUFFMAN_FREQUENCY_TRACKER_H_
+#define NET_TOOLS_DOMAIN_SECURITY_PRELOAD_GENERATOR_HUFFMAN_FREQUENCY_TRACKER_H_
+
+#include <stdint.h>
+
+#include <map>
+#include <memory>
+#include <vector>
+
+namespace net {
+
+namespace transport_security_state {
+
+namespace {
+class HuffmanNode;
+} // namespace
+
+struct HuffmanRepresentation {
+ uint32_t bits;
+ uint32_t number_of_bits;
+};
+
+// A HuffmanRepresentationTable maps the original characters to their Huffman
+// representation. The Huffman representation consists of the number of bits
+// needed to represent the character and the actual bits.
+using HuffmanRepresentationTable = std::map<uint8_t, HuffmanRepresentation>;
+using HuffmanRepresentationPair = std::pair<uint8_t, HuffmanRepresentation>;
+
+// This class tracks the number of times each character is used and calculates
+// a space efficient way to represent all tracked characters by constructing a
+// Huffman tree based on the number of times each character is seen.
+class HuffmanFrequencyTracker {
+ public:
+ HuffmanFrequencyTracker();
+ ~HuffmanFrequencyTracker();
+
+ // Will increase the count for |character| by one, indicating it has been
+ // used.
+ void RecordUsage(uint8_t character);
+
+ // Returns a HuffmanRepresentationTable based on the usage data collected
+ // through RecordUsage().
+ HuffmanRepresentationTable ToTable();
+
+ // Outputs the Huffman representation as a vector of uint8_t's in a format
+ // Chromium can use to reconstruct the tree.
+ //
+ // The nodes of the tree are pairs of uint8s. The last node in the array is
+ // the root of the tree. Each pair is two uint8_t values, the first is "left"
+ // and the second is "right". If a uint8_t value has the MSB set then it
+ // represents a literal leaf value. Otherwise it's a pointer to the n'th
+ // element of the array.
+ std::vector<uint8_t> ToVector();
+
+ private:
+ // Determines the Huffman representation of the characters under |node| and
+ // inserts them into |*table|. |bits| and |number_of_bits| are used as a
+ // prefix.
+ void TreeToTable(HuffmanNode* node,
+ uint32_t bits,
+ uint32_t number_of_bits,
+ HuffmanRepresentationTable* table);
+
+ // Converts the tree under |*node| into a byte representation in |*vector|.
+ // See ToVector() for more information on the format.
+ uint32_t WriteToVector(HuffmanNode* node, std::vector<uint8_t>* vector);
+
+ // Constructs a Huffman tree based on |counts_|.
+ std::unique_ptr<HuffmanNode> BuildTree();
+
+ // Holds usage information for the tracked characters. Maps the character to
+ // the number of times its usage has been recorded through RecordUsage().
+ std::map<uint8_t, uint32_t> counts_;
+};
+
+} // namespace transport_security_state
+
+} // namespace net
+
+#endif // NET_TOOLS_DOMAIN_SECURITY_PRELOAD_GENERATOR_HUFFMAN_FREQUENCY_TRACKER_H_
diff --git a/chromium/net/tools/domain_security_preload_generator/pinset.cc b/chromium/net/tools/domain_security_preload_generator/pinset.cc
new file mode 100644
index 00000000000..1b35123a092
--- /dev/null
+++ b/chromium/net/tools/domain_security_preload_generator/pinset.cc
@@ -0,0 +1,26 @@
+// Copyright (c) 2016 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.
+
+#include "net/tools/domain_security_preload_generator/pinset.h"
+
+namespace net {
+
+namespace transport_security_state {
+
+Pinset::Pinset(std::string name, std::string report_uri)
+ : name_(name), report_uri_(report_uri) {}
+
+Pinset::~Pinset() {}
+
+void Pinset::AddStaticSPKIHash(const std::string& hash_name) {
+ static_spki_hashes_.push_back(hash_name);
+}
+
+void Pinset::AddBadStaticSPKIHash(const std::string& hash_name) {
+ bad_static_spki_hashes_.push_back(hash_name);
+}
+
+} // namespace transport_security_state
+
+} // namespace net
diff --git a/chromium/net/tools/domain_security_preload_generator/pinset.h b/chromium/net/tools/domain_security_preload_generator/pinset.h
new file mode 100644
index 00000000000..f74ed3a8c26
--- /dev/null
+++ b/chromium/net/tools/domain_security_preload_generator/pinset.h
@@ -0,0 +1,58 @@
+// Copyright (c) 2016 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.
+
+#ifndef NET_TOOLS_DOMAIN_SECURITY_PRELOAD_GENERATOR_PINSET_H_
+#define NET_TOOLS_DOMAIN_SECURITY_PRELOAD_GENERATOR_PINSET_H_
+
+#include <string>
+#include <vector>
+
+#include "base/macros.h"
+
+namespace net {
+
+namespace transport_security_state {
+
+// A Pinset represents the data a website would send in a HPKP header. A pinset
+// is given a name so that multiple entries in the preload list can reference
+// the same pinset.
+class Pinset {
+ public:
+ Pinset(std::string name, std::string report_uri);
+ ~Pinset();
+
+ const std::string& name() const { return name_; }
+ const std::string& report_uri() const { return report_uri_; }
+
+ const std::vector<std::string>& static_spki_hashes() const {
+ return static_spki_hashes_;
+ }
+ const std::vector<std::string>& bad_static_spki_hashes() const {
+ return bad_static_spki_hashes_;
+ }
+
+ // Register a good hash for this pinset. Hashes are referenced by a name, not
+ // by the actual hash.
+ void AddStaticSPKIHash(const std::string& hash_name);
+
+ // Register a bad hash for this pinset. Hashes are referenced by a name, not
+ // by the actual hash.
+ void AddBadStaticSPKIHash(const std::string& hash_name);
+
+ private:
+ std::string name_;
+ std::string report_uri_;
+
+ // These vectors contain names rather than actual hashes.
+ std::vector<std::string> static_spki_hashes_;
+ std::vector<std::string> bad_static_spki_hashes_;
+
+ DISALLOW_COPY_AND_ASSIGN(Pinset);
+};
+
+} // namespace transport_security_state
+
+} // namespace net
+
+#endif // NET_TOOLS_DOMAIN_SECURITY_PRELOAD_GENERATOR_PINSET_H_
diff --git a/chromium/net/tools/domain_security_preload_generator/pinsets.cc b/chromium/net/tools/domain_security_preload_generator/pinsets.cc
new file mode 100644
index 00000000000..a22dd62cd40
--- /dev/null
+++ b/chromium/net/tools/domain_security_preload_generator/pinsets.cc
@@ -0,0 +1,28 @@
+// Copyright (c) 2016 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.
+
+#include "net/tools/domain_security_preload_generator/pinsets.h"
+
+#include "net/tools/domain_security_preload_generator/spki_hash.h"
+
+namespace net {
+
+namespace transport_security_state {
+
+Pinsets::Pinsets() {}
+
+Pinsets::~Pinsets() {}
+
+void Pinsets::RegisterSPKIHash(base::StringPiece name, const SPKIHash& hash) {
+ spki_hashes_.insert(std::pair<std::string, SPKIHash>(name.as_string(), hash));
+}
+
+void Pinsets::RegisterPinset(std::unique_ptr<Pinset> pinset) {
+ pinsets_.insert(std::pair<std::string, std::unique_ptr<Pinset>>(
+ pinset->name(), std::move(pinset)));
+}
+
+} // namespace transport_security_state
+
+} // namespace net
diff --git a/chromium/net/tools/domain_security_preload_generator/pinsets.h b/chromium/net/tools/domain_security_preload_generator/pinsets.h
new file mode 100644
index 00000000000..aa48592edf6
--- /dev/null
+++ b/chromium/net/tools/domain_security_preload_generator/pinsets.h
@@ -0,0 +1,56 @@
+// Copyright (c) 2016 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.
+
+#ifndef NET_TOOLS_DOMAIN_SECURITY_PRELOAD_GENERATOR_PINSETS_H_
+#define NET_TOOLS_DOMAIN_SECURITY_PRELOAD_GENERATOR_PINSETS_H_
+
+#include <map>
+#include <memory>
+#include <string>
+
+#include "base/macros.h"
+#include "base/strings/string_piece.h"
+#include "net/tools/domain_security_preload_generator/cert_util.h"
+#include "net/tools/domain_security_preload_generator/pinset.h"
+#include "net/tools/domain_security_preload_generator/pinsets.h"
+#include "net/tools/domain_security_preload_generator/spki_hash.h"
+
+namespace net {
+
+namespace transport_security_state {
+
+// Contains SPKIHashes and their names. The names are used to reference
+// the hashes from Pinset's.
+using SPKIHashMap = std::map<std::string, SPKIHash>;
+using PinsetMap = std::map<std::string, std::unique_ptr<Pinset>>;
+
+class Pinsets {
+ public:
+ Pinsets();
+ ~Pinsets();
+
+ void RegisterSPKIHash(base::StringPiece name, const SPKIHash& hash);
+ void RegisterPinset(std::unique_ptr<Pinset> set);
+
+ size_t size() const { return pinsets_.size(); }
+ size_t spki_size() const { return spki_hashes_.size(); }
+
+ const SPKIHashMap& spki_hashes() const { return spki_hashes_; }
+ const PinsetMap& pinsets() const { return pinsets_; }
+
+ private:
+ // Contains all SPKI hashes found in the input pins file.
+ SPKIHashMap spki_hashes_;
+
+ // Contains all pinsets in the input JSON file.
+ PinsetMap pinsets_;
+
+ DISALLOW_COPY_AND_ASSIGN(Pinsets);
+};
+
+} // namespace transport_security_state
+
+} // namespace net
+
+#endif // NET_TOOLS_DOMAIN_SECURITY_PRELOAD_GENERATOR_PINSETS_H_
diff --git a/chromium/net/tools/domain_security_preload_generator/preloaded_state_generator.cc b/chromium/net/tools/domain_security_preload_generator/preloaded_state_generator.cc
new file mode 100644
index 00000000000..e5e08a0dcbf
--- /dev/null
+++ b/chromium/net/tools/domain_security_preload_generator/preloaded_state_generator.cc
@@ -0,0 +1,366 @@
+// Copyright (c) 2016 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.
+
+#include "net/tools/domain_security_preload_generator/preloaded_state_generator.h"
+
+#include <iostream>
+
+#include <string>
+
+#include "base/strings/string_util.h"
+#include "base/strings/stringprintf.h"
+#include "net/tools/domain_security_preload_generator/cert_util.h"
+#include "net/tools/domain_security_preload_generator/huffman/huffman_frequency_tracker.h"
+#include "net/tools/domain_security_preload_generator/spki_hash.h"
+
+namespace net {
+
+namespace transport_security_state {
+
+namespace {
+
+static const char kNewLine[] = "\n";
+static const char kIndent[] = " ";
+
+std::string FormatSPKIName(const std::string& name) {
+ return "kSPKIHash_" + name;
+}
+
+std::string FormatAcceptedKeyName(const std::string& name) {
+ return "k" + name + "AcceptableCerts";
+}
+
+std::string FormatRejectedKeyName(const std::string& name) {
+ return "k" + name + "RejectedCerts";
+}
+
+std::string FormatReportURIName(const std::string& name) {
+ return "k" + name + "ReportURI";
+}
+
+// Replaces the first occurrence of "[[" + name + "]]" in |*tpl| with
+// |value|.
+bool ReplaceTag(const std::string& name,
+ const std::string& value,
+ std::string* tpl) {
+ std::string tag = "[[" + name + "]]";
+
+ size_t start_pos = tpl->find(tag);
+ if (start_pos == std::string::npos) {
+ return false;
+ }
+
+ tpl->replace(start_pos, tag.length(), value);
+ return true;
+}
+
+// Formats the bytes in |bytes| as an C++ array initializer and returns the
+// resulting string.
+std::string FormatVectorAsArray(const std::vector<uint8_t>& bytes) {
+ std::string output = "{";
+ output.append(kNewLine);
+ output.append(kIndent);
+ output.append(kIndent);
+
+ size_t bytes_on_current_line = 0;
+
+ for (size_t i = 0; i < bytes.size(); ++i) {
+ base::StringAppendF(&output, "0x%02x,", bytes[i]);
+
+ bytes_on_current_line++;
+ if (bytes_on_current_line >= 12 && i + 1 < bytes.size()) {
+ output.append(kNewLine);
+ output.append(kIndent);
+ output.append(kIndent);
+
+ bytes_on_current_line = 0;
+ } else if (i + 1 < bytes.size()) {
+ output.append(" ");
+ }
+ }
+
+ output.append(kNewLine);
+ output.append("}");
+
+ return output;
+}
+
+std::string WritePinsetList(const std::string& name,
+ const std::vector<std::string>& pins) {
+ std::string output = "static const char* const " + name + "[] = {";
+ output.append(kNewLine);
+
+ for (const auto& pin_name : pins) {
+ output.append(kIndent);
+ output.append(kIndent);
+ output.append(FormatSPKIName(pin_name));
+ output.append(",");
+ output.append(kNewLine);
+ }
+
+ output.append(kIndent);
+ output.append(kIndent);
+ output.append("NULL,");
+ output.append(kNewLine);
+ output.append("};");
+
+ return output;
+}
+
+HuffmanRepresentationTable ApproximateHuffman(
+ const DomainSecurityEntries& entries) {
+ HuffmanFrequencyTracker tracker;
+ for (const auto& entry : entries) {
+ for (const auto& c : entry->hostname) {
+ tracker.RecordUsage(c);
+ }
+
+ tracker.RecordUsage(TrieWriter::kTerminalValue);
+ tracker.RecordUsage(TrieWriter::kEndOfTableValue);
+ }
+
+ return tracker.ToTable();
+}
+
+} // namespace
+
+PreloadedStateGenerator::PreloadedStateGenerator() {}
+
+PreloadedStateGenerator::~PreloadedStateGenerator() {}
+
+std::string PreloadedStateGenerator::Generate(
+ const std::string& preload_template,
+ const DomainSecurityEntries& entries,
+ const DomainIDList& domain_ids,
+ const Pinsets& pinsets,
+ bool verbose) {
+ std::string output = preload_template;
+
+ NameIDMap domain_ids_map;
+ ProcessDomainIds(domain_ids, &domain_ids_map, &output);
+
+ ProcessSPKIHashes(pinsets, &output);
+
+ NameIDMap expect_ct_report_uri_map;
+ ProcessExpectCTURIs(entries, &expect_ct_report_uri_map, &output);
+
+ NameIDMap expect_staple_report_uri_map;
+ ProcessExpectStapleURIs(entries, &expect_staple_report_uri_map, &output);
+
+ NameIDMap pinsets_map;
+ ProcessPinsets(pinsets, &pinsets_map, &output);
+
+ // The trie generation process is ran twice, the first time using an
+ // approximate Huffman table. During this first run, the correct character
+ // frequencies are collected which are then used to calculate the most space
+ // efficient Huffman table for the given inputs. This table is used for the
+ // second run.
+ HuffmanRepresentationTable table = ApproximateHuffman(entries);
+ HuffmanFrequencyTracker tracker;
+ TrieWriter writer(table, domain_ids_map, expect_ct_report_uri_map,
+ expect_staple_report_uri_map, pinsets_map, &tracker);
+ writer.WriteEntries(entries);
+ uint32_t initial_length = writer.position();
+
+ HuffmanRepresentationTable optimal_table = tracker.ToTable();
+ TrieWriter new_writer(optimal_table, domain_ids_map, expect_ct_report_uri_map,
+ expect_staple_report_uri_map, pinsets_map, nullptr);
+
+ uint32_t root_position = new_writer.WriteEntries(entries);
+ uint32_t new_length = new_writer.position();
+
+ std::vector<uint8_t> huffman_tree = tracker.ToVector();
+
+ new_writer.Flush();
+
+ ReplaceTag("HUFFMAN_TREE", FormatVectorAsArray(huffman_tree), &output);
+ ReplaceTag("HSTS_TRIE", FormatVectorAsArray(new_writer.bytes()), &output);
+
+ ReplaceTag("HSTS_TRIE_BITS", std::to_string(new_length), &output);
+ ReplaceTag("HSTS_TRIE_ROOT", std::to_string(root_position), &output);
+
+ if (verbose) {
+ std::cout << "Saved " << std::to_string(initial_length - new_length)
+ << " bits by using accurate Huffman counts." << std::endl;
+ std::cout << "Bit length " << std::to_string(new_length) << std::endl;
+ std::cout << "Root position " << std::to_string(root_position) << std::endl;
+ }
+
+ return output;
+}
+
+void PreloadedStateGenerator::ProcessDomainIds(const DomainIDList& domain_ids,
+ NameIDMap* map,
+ std::string* tpl) {
+ std::string output = "{";
+ output.append(kNewLine);
+
+ for (size_t i = 0; i < domain_ids.size(); ++i) {
+ const std::string& current = domain_ids.at(i);
+ output.append(kIndent);
+ output.append("DOMAIN_" + current + ",");
+ output.append(kNewLine);
+
+ map->insert(NameIDPair(current, static_cast<uint32_t>(i)));
+ }
+
+ output.append(kIndent);
+ output.append("// Boundary value for UMA_HISTOGRAM_ENUMERATION.");
+ output.append(kNewLine);
+ output.append(kIndent);
+ output.append("DOMAIN_NUM_EVENTS,");
+ output.append(kNewLine);
+ output.append("}");
+
+ ReplaceTag("DOMAIN_IDS", output, tpl);
+}
+
+void PreloadedStateGenerator::ProcessSPKIHashes(const Pinsets& pinset,
+ std::string* tpl) {
+ std::string output;
+
+ const SPKIHashMap& hashes = pinset.spki_hashes();
+ for (const auto& current : hashes) {
+ const std::string& name = current.first;
+ const SPKIHash& hash = current.second;
+
+ output.append("static const char " + FormatSPKIName(name) + "[] =");
+ output.append(kNewLine);
+
+ for (size_t i = 0; i < hash.size() / 16; ++i) {
+ output.append(kIndent);
+ output.append(kIndent);
+ output.append("\"");
+
+ for (size_t j = i * 16; j < ((i + 1) * 16); ++j) {
+ base::StringAppendF(&output, "\\x%02x", hash.data()[j]);
+ }
+
+ output.append("\"");
+ if (i + 1 == hash.size() / 16) {
+ output.append(";");
+ }
+ output.append(kNewLine);
+ }
+
+ output.append(kNewLine);
+ }
+
+ base::TrimString(output, kNewLine, &output);
+ ReplaceTag("SPKI_HASHES", output, tpl);
+}
+
+void PreloadedStateGenerator::ProcessExpectCTURIs(
+ const DomainSecurityEntries& entries,
+ NameIDMap* expect_ct_report_uri_map,
+ std::string* tpl) {
+ std::string output = "{";
+ output.append(kNewLine);
+
+ for (const auto& entry : entries) {
+ const std::string& url = entry->expect_ct_report_uri;
+ if (entry->expect_ct && url.size() &&
+ expect_ct_report_uri_map->find(url) ==
+ expect_ct_report_uri_map->cend()) {
+ output.append(kIndent);
+ output.append(kIndent);
+ output.append("\"" + entry->expect_ct_report_uri + "\",");
+ output.append(kNewLine);
+
+ expect_ct_report_uri_map->insert(
+ NameIDPair(entry->expect_ct_report_uri,
+ static_cast<uint32_t>(expect_ct_report_uri_map->size())));
+ }
+ }
+
+ output.append("}");
+ ReplaceTag("EXPECT_CT_REPORT_URIS", output, tpl);
+}
+
+void PreloadedStateGenerator::ProcessExpectStapleURIs(
+ const DomainSecurityEntries& entries,
+ NameIDMap* expect_staple_report_uri_map,
+ std::string* tpl) {
+ std::string output = "{";
+ output.append(kNewLine);
+
+ for (const auto& entry : entries) {
+ const std::string& url = entry->expect_staple_report_uri;
+ if (entry->expect_staple && url.size() &&
+ expect_staple_report_uri_map->find(url) ==
+ expect_staple_report_uri_map->cend()) {
+ output.append(kIndent);
+ output.append(kIndent);
+ output.append("\"" + entry->expect_staple_report_uri + "\",");
+ output.append(kNewLine);
+
+ expect_staple_report_uri_map->insert(NameIDPair(
+ entry->expect_staple_report_uri,
+ static_cast<uint32_t>(expect_staple_report_uri_map->size())));
+ }
+ }
+
+ output.append("}");
+ ReplaceTag("EXPECT_STAPLE_REPORT_URIS", output, tpl);
+}
+
+void PreloadedStateGenerator::ProcessPinsets(const Pinsets& pinset,
+ NameIDMap* pinset_map,
+ std::string* tpl) {
+ std::string certs_output;
+ std::string pinsets_output = "{";
+ pinsets_output.append(kNewLine);
+
+ const PinsetMap& pinsets = pinset.pinsets();
+ for (const auto& current : pinsets) {
+ const std::unique_ptr<Pinset>& pinset = current.second;
+ std::string uppercased_name = pinset->name();
+ uppercased_name[0] = base::ToUpperASCII(uppercased_name[0]);
+
+ const std::string& accepted_pins_names =
+ FormatAcceptedKeyName(uppercased_name);
+ certs_output.append(
+ WritePinsetList(accepted_pins_names, pinset->static_spki_hashes()));
+ certs_output.append(kNewLine);
+
+ std::string rejected_pins_names = "kNoRejectedPublicKeys";
+ if (pinset->bad_static_spki_hashes().size()) {
+ rejected_pins_names = FormatRejectedKeyName(uppercased_name);
+ certs_output.append(WritePinsetList(rejected_pins_names,
+ pinset->bad_static_spki_hashes()));
+ certs_output.append(kNewLine);
+ }
+
+ std::string report_uri = "kNoReportURI";
+ if (pinset->report_uri().size()) {
+ report_uri = FormatReportURIName(uppercased_name);
+ certs_output.append("static const char " + report_uri + "[] = ");
+ certs_output.append("\"");
+ certs_output.append(pinset->report_uri());
+ certs_output.append("\";");
+ certs_output.append(kNewLine);
+ }
+ certs_output.append(kNewLine);
+
+ pinsets_output.append(kIndent);
+ pinsets_output.append(kIndent);
+ pinsets_output.append("{" + accepted_pins_names + ", " +
+ rejected_pins_names + ", " + report_uri + "},");
+ pinsets_output.append(kNewLine);
+
+ pinset_map->insert(
+ NameIDPair(pinset->name(), static_cast<uint32_t>(pinset_map->size())));
+ }
+
+ pinsets_output.append("}");
+
+ base::TrimString(certs_output, kNewLine, &certs_output);
+
+ ReplaceTag("ACCEPTABLE_CERTS", certs_output, tpl);
+ ReplaceTag("PINSETS", pinsets_output, tpl);
+}
+
+} // namespace transport_security_state
+
+} // namespace net
diff --git a/chromium/net/tools/domain_security_preload_generator/preloaded_state_generator.h b/chromium/net/tools/domain_security_preload_generator/preloaded_state_generator.h
new file mode 100644
index 00000000000..037a5959f87
--- /dev/null
+++ b/chromium/net/tools/domain_security_preload_generator/preloaded_state_generator.h
@@ -0,0 +1,59 @@
+// Copyright (c) 2016 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.
+
+#ifndef NET_TOOLS_DOMAIN_SECURITY_PRELOAD_GENERATOR_PRELOADED_STATE_GENERATOR_H_
+#define NET_TOOLS_DOMAIN_SECURITY_PRELOAD_GENERATOR_PRELOADED_STATE_GENERATOR_H_
+
+#include <stdint.h>
+
+#include <memory>
+#include <string>
+
+#include "net/tools/domain_security_preload_generator/domain_security_entry.h"
+#include "net/tools/domain_security_preload_generator/pinset.h"
+#include "net/tools/domain_security_preload_generator/pinsets.h"
+#include "net/tools/domain_security_preload_generator/trie/trie_writer.h"
+
+namespace net {
+
+namespace transport_security_state {
+
+// PreloadedStateGenerator generates C++ code that contains the preloaded
+// entries in a way the Chromium code understands. The code that reads the
+// output can be found in net/http/transport_security_state.cc. The output gets
+// compiled into the binary.
+class PreloadedStateGenerator {
+ public:
+ PreloadedStateGenerator();
+ ~PreloadedStateGenerator();
+
+ std::string Generate(const std::string& preload_template,
+ const DomainSecurityEntries& entries,
+ const DomainIDList& domain_ids,
+ const Pinsets& pinsets,
+ bool verbose);
+
+ private:
+ // TODO(Martijnc): Remove the domain IDs from the preload format.
+ // https://crbug.com/661206.
+ void ProcessDomainIds(const DomainIDList& domain_ids,
+ NameIDMap* map,
+ std::string* tpl);
+ void ProcessSPKIHashes(const Pinsets& pinset, std::string* tpl);
+ void ProcessExpectCTURIs(const DomainSecurityEntries& entries,
+ NameIDMap* expect_ct_report_uri_map,
+ std::string* tpl);
+ void ProcessExpectStapleURIs(const DomainSecurityEntries& entries,
+ NameIDMap* expect_staple_report_uri_map,
+ std::string* tpl);
+ void ProcessPinsets(const Pinsets& pinset,
+ NameIDMap* pinset_map,
+ std::string* tpl);
+};
+
+} // namespace transport_security_state
+
+} // namespace net
+
+#endif // NET_TOOLS_DOMAIN_SECURITY_PRELOAD_GENERATOR_PRELOADED_STATE_GENERATOR_H_
diff --git a/chromium/net/tools/domain_security_preload_generator/resources/transport_security_state_static.template b/chromium/net/tools/domain_security_preload_generator/resources/transport_security_state_static.template
new file mode 100644
index 00000000000..1f76c1d7d32
--- /dev/null
+++ b/chromium/net/tools/domain_security_preload_generator/resources/transport_security_state_static.template
@@ -0,0 +1,50 @@
+// Copyright (c) 2012 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.
+
+#ifndef NET_HTTP_TRANSPORT_SECURITY_STATE_STATIC_H_
+#define NET_HTTP_TRANSPORT_SECURITY_STATE_STATIC_H_
+
+#include <stdint.h>
+
+enum SecondLevelDomainName [[DOMAIN_IDS]];
+
+// These are SubjectPublicKeyInfo hashes for public key pinning. The
+// hashes are SHA256 digests.
+[[SPKI_HASHES]]
+
+static const char* const kExpectCTReportURIs[] = [[EXPECT_CT_REPORT_URIS]];
+
+static const char* const kExpectStapleReportURIs[] = [[EXPECT_STAPLE_REPORT_URIS]];
+
+// kNoRejectedPublicKeys is a placeholder for when no public keys are rejected.
+static const char* const kNoRejectedPublicKeys[] = {
+ NULL,
+};
+
+// kNoReportURI is a placeholder for when a pinset does not have a report URI.
+static const char kNoReportURI[] = "";
+
+[[ACCEPTABLE_CERTS]]
+
+struct Pinset {
+ const char* const* const accepted_pins;
+ const char* const* const rejected_pins;
+ const char* const report_uri;
+};
+
+static const struct Pinset kPinsets[] = [[PINSETS]];
+
+// kHSTSHuffmanTree describes a Huffman tree. The nodes of the tree are pairs
+// of uint8s. The last node in the array is the root of the tree. Each pair is
+// two uint8_t values, the first is "left" and the second is "right". If a
+// uint8_t value has the MSB set then it represents a literal leaf value.
+// Otherwise it's a pointer to the n'th element of the array.
+static const uint8_t kHSTSHuffmanTree[] = [[HUFFMAN_TREE]];
+
+static const uint8_t kPreloadedHSTSData[] = [[HSTS_TRIE]];
+
+static const unsigned kPreloadedHSTSBits = [[HSTS_TRIE_BITS]];
+static const unsigned kHSTSRootPosition = [[HSTS_TRIE_ROOT]];
+
+#endif // NET_HTTP_TRANSPORT_SECURITY_STATE_STATIC_H_
diff --git a/chromium/net/tools/domain_security_preload_generator/spki_hash.cc b/chromium/net/tools/domain_security_preload_generator/spki_hash.cc
new file mode 100644
index 00000000000..d95de696c87
--- /dev/null
+++ b/chromium/net/tools/domain_security_preload_generator/spki_hash.cc
@@ -0,0 +1,50 @@
+// Copyright 2016 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.
+
+#include "net/tools/domain_security_preload_generator/spki_hash.h"
+
+#include <string>
+
+#include "base/base64.h"
+#include "base/logging.h"
+#include "base/strings/string_util.h"
+#include "third_party/boringssl/src/include/openssl/sha.h"
+
+namespace net {
+
+namespace transport_security_state {
+
+SPKIHash::SPKIHash() {}
+
+SPKIHash::~SPKIHash() {}
+
+bool SPKIHash::FromString(const std::string& hash_string) {
+ std::string base64_string;
+
+ if (!base::StartsWith(hash_string, "sha256/",
+ base::CompareCase::INSENSITIVE_ASCII)) {
+ return false;
+ }
+ base64_string = hash_string.substr(7);
+
+ std::string decoded;
+ if (!base::Base64Decode(base64_string, &decoded)) {
+ return false;
+ }
+
+ if (decoded.size() != size()) {
+ return false;
+ }
+
+ memcpy(data_, decoded.data(), decoded.size());
+ return true;
+}
+
+void SPKIHash::CalculateFromBytes(const uint8_t* input, size_t input_length) {
+ SHA256(input, input_length, data_);
+}
+
+} // namespace transport_security_state
+
+} // namespace net
diff --git a/chromium/net/tools/domain_security_preload_generator/spki_hash.h b/chromium/net/tools/domain_security_preload_generator/spki_hash.h
new file mode 100644
index 00000000000..ca07d0a5c83
--- /dev/null
+++ b/chromium/net/tools/domain_security_preload_generator/spki_hash.h
@@ -0,0 +1,49 @@
+// Copyright (c) 2016 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.
+
+#ifndef NET_TOOLS_DOMAIN_SECURITY_PRELOAD_GENERATOR_SPKI_HASH_H_
+#define NET_TOOLS_DOMAIN_SECURITY_PRELOAD_GENERATOR_SPKI_HASH_H_
+
+#include <stdint.h>
+#include <string>
+#include <vector>
+
+namespace net {
+
+namespace transport_security_state {
+
+class SPKIHash {
+ public:
+ enum : size_t { kLength = 32 };
+
+ SPKIHash();
+ ~SPKIHash();
+
+ // Initalizes a hash from the form sha256/<base64-hash-value>. The preloaded
+ // SPKI hashes are SHA256. Other algorithms are not supported. Returns true
+ // on success and copies the decoded bytes to |data_|. Returns false on
+ // failure.
+ bool FromString(const std::string& hash_string);
+
+ // Calculates the SHA256 digest over |*input| and copies the result to
+ // |data_|.
+ void CalculateFromBytes(const uint8_t* input, size_t input_length);
+
+ // Returns the size of the hash in bytes. Harcoded to 32 which is the length
+ // of a SHA256 hash.
+ size_t size() const { return kLength; }
+
+ uint8_t* data() { return data_; }
+ const uint8_t* data() const { return data_; };
+
+ private:
+ // The bytes of the hash. Current hashes are SHA256 and thus 32 bytes long.
+ uint8_t data_[kLength];
+};
+
+} // namespace transport_security_state
+
+} // namespace net
+
+#endif // NET_TOOLS_DOMAIN_SECURITY_PRELOAD_GENERATOR_SPKI_HASH_H_
diff --git a/chromium/net/tools/domain_security_preload_generator/trie/trie_bit_buffer.cc b/chromium/net/tools/domain_security_preload_generator/trie/trie_bit_buffer.cc
new file mode 100644
index 00000000000..93af94b3937
--- /dev/null
+++ b/chromium/net/tools/domain_security_preload_generator/trie/trie_bit_buffer.cc
@@ -0,0 +1,133 @@
+// Copyright (c) 2016 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.
+
+#include "net/tools/domain_security_preload_generator/trie/trie_bit_buffer.h"
+
+#include "base/logging.h"
+#include "net/tools/domain_security_preload_generator/bit_writer.h"
+
+namespace net {
+
+namespace transport_security_state {
+
+TrieBitBuffer::TrieBitBuffer() {}
+
+TrieBitBuffer::~TrieBitBuffer() {}
+
+void TrieBitBuffer::WriteBit(uint8_t bit) {
+ current_byte_ |= bit << (7 - used_);
+ used_++;
+
+ if (used_ == 8) {
+ Flush();
+ }
+}
+
+void TrieBitBuffer::WriteBits(uint32_t bits, uint8_t number_of_bits) {
+ DCHECK(number_of_bits <= 32);
+ for (uint8_t i = 1; i <= number_of_bits; i++) {
+ uint8_t bit = 1 & (bits >> (number_of_bits - i));
+ WriteBit(bit);
+ }
+}
+
+void TrieBitBuffer::WritePosition(uint32_t position, int32_t* last_position) {
+ if (*last_position != -1) {
+ int32_t delta = position - *last_position;
+ DCHECK(delta > 0) << "delta position is not positive.";
+
+ uint8_t number_of_bits = BitLength(delta);
+ DCHECK(number_of_bits <= 7 + 15) << "positive position delta too large.";
+
+ if (number_of_bits <= 7) {
+ WriteBits(0, 1);
+ WriteBits(delta, 7);
+ } else {
+ WriteBits(1, 1);
+ WriteBits(number_of_bits - 8, 4);
+ WriteBits(delta, number_of_bits);
+ }
+
+ *last_position = position;
+ return;
+ }
+
+ if (used_ != 0) {
+ Flush();
+ }
+
+ AppendPositionElement(position);
+
+ *last_position = position;
+}
+
+uint8_t TrieBitBuffer::BitLength(uint32_t input) const {
+ uint8_t number_of_bits = 0;
+ while (input != 0) {
+ number_of_bits++;
+ input >>= 1;
+ }
+ return number_of_bits;
+}
+
+void TrieBitBuffer::WriteChar(uint8_t byte,
+ const HuffmanRepresentationTable& table,
+ HuffmanFrequencyTracker* tracker) {
+ HuffmanRepresentationTable::const_iterator item;
+ item = table.find(byte);
+ DCHECK(item != table.end());
+ if (tracker) {
+ tracker->RecordUsage(byte);
+ }
+ WriteBits(item->second.bits, item->second.number_of_bits);
+}
+
+void TrieBitBuffer::AppendBitsElement(uint8_t bits, uint8_t number_of_bits) {
+ BitsOrPosition element;
+ element.bits = current_byte_;
+ element.number_of_bits = used_;
+ elements_.push_back(element);
+}
+
+void TrieBitBuffer::AppendPositionElement(uint32_t position) {
+ BitsOrPosition element;
+ element.position = position;
+ element.number_of_bits = 0;
+ elements_.push_back(element);
+}
+
+uint32_t TrieBitBuffer::WriteToBitWriter(BitWriter* writer) {
+ Flush();
+
+ uint32_t old_position = writer->position();
+ for (auto const& element : elements_) {
+ if (element.number_of_bits) {
+ writer->WriteBits(element.bits >> (8 - element.number_of_bits),
+ element.number_of_bits);
+ } else {
+ uint32_t current = old_position;
+ uint32_t target = element.position;
+ DCHECK(target < current) << "Reference is not backwards";
+ uint32_t delta = current - target;
+ uint8_t delta_number_of_bits = BitLength(delta);
+ DCHECK(delta_number_of_bits < 32) << "Delta to large";
+ writer->WriteBits(delta_number_of_bits, 5);
+ writer->WriteBits(delta, delta_number_of_bits);
+ }
+ }
+ return old_position;
+}
+
+void TrieBitBuffer::Flush() {
+ if (used_) {
+ AppendBitsElement(current_byte_, used_);
+
+ used_ = 0;
+ current_byte_ = 0;
+ }
+}
+
+} // namespace transport_security_state
+
+} // namespace net
diff --git a/chromium/net/tools/domain_security_preload_generator/trie/trie_bit_buffer.h b/chromium/net/tools/domain_security_preload_generator/trie/trie_bit_buffer.h
new file mode 100644
index 00000000000..f767fbc7d92
--- /dev/null
+++ b/chromium/net/tools/domain_security_preload_generator/trie/trie_bit_buffer.h
@@ -0,0 +1,85 @@
+// Copyright (c) 2016 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.
+
+#ifndef NET_TOOLS_DOMAIN_SECURITY_PRELOAD_GENERATOR_TRIE_TRIE_BIT_BUFFER_H_
+#define NET_TOOLS_DOMAIN_SECURITY_PRELOAD_GENERATOR_TRIE_TRIE_BIT_BUFFER_H_
+
+#include <stdint.h>
+
+#include <vector>
+
+#include "net/tools/domain_security_preload_generator/huffman/huffman_frequency_tracker.h"
+
+namespace net {
+
+namespace transport_security_state {
+
+class BitWriter;
+
+// TrieBitBuffer acts as a buffer for TrieWriter. It can be used to write bits,
+// characters, and positions. The characters are stored as their
+// HuffmanRepresentation. Positions are references to other locations in the
+// trie.
+class TrieBitBuffer {
+ public:
+ TrieBitBuffer();
+ ~TrieBitBuffer();
+
+ // Writes |bit| to the buffer.
+ void WriteBit(uint8_t bit);
+
+ // Writes the |number_of_bits| least-significant bits from |bits| to the
+ // buffer.
+ void WriteBits(uint32_t bits, uint8_t number_of_bits);
+
+ // Write a position to the buffer. Actually writes the difference between
+ // |position| and |last_position|. |*last_position| will be updated to equal
+ // the input |position|.
+ void WritePosition(uint32_t position, int32_t* last_position);
+
+ // Writes the character in |byte| to the buffer using its Huffman
+ // representation in |table|. Optionally tracks usage of the character in
+ // |*tracker|.
+ void WriteChar(uint8_t byte,
+ const HuffmanRepresentationTable& table,
+ HuffmanFrequencyTracker* tracker);
+
+ // Writes the entire buffer to |*writer|. Returns the position |*writer| was
+ // at before the buffer was written to it.
+ uint32_t WriteToBitWriter(BitWriter* writer);
+
+ // Appends the buffered bits in |current_byte_| to |elements_|. Empty bits
+ // are filled with zero's.
+ void Flush();
+
+ private:
+ // Represents either the |number_of_bits| least-significant bits in |bits| or
+ // a position (offset) in the trie.
+ struct BitsOrPosition {
+ uint8_t bits;
+ uint8_t number_of_bits;
+ uint32_t position;
+ };
+
+ // Returns the minimum number of bits needed to represent |input|.
+ uint8_t BitLength(uint32_t input) const;
+
+ // Append a new element to |elements_|.
+ void AppendBitsElement(uint8_t bits, uint8_t number_of_bits);
+ void AppendPositionElement(uint32_t position);
+
+ // Buffers bits until they fill a whole byte.
+ uint8_t current_byte_ = 0;
+
+ // The number of bits currently in |current_byte_|.
+ uint32_t used_ = 0;
+
+ std::vector<BitsOrPosition> elements_;
+};
+
+} // namespace transport_security_state
+
+} // namespace net
+
+#endif // NET_TOOLS_DOMAIN_SECURITY_PRELOAD_GENERATOR_TRIE_TRIE_BIT_BUFFER_H_
diff --git a/chromium/net/tools/domain_security_preload_generator/trie/trie_writer.cc b/chromium/net/tools/domain_security_preload_generator/trie/trie_writer.cc
new file mode 100644
index 00000000000..3e0da3c365c
--- /dev/null
+++ b/chromium/net/tools/domain_security_preload_generator/trie/trie_writer.cc
@@ -0,0 +1,283 @@
+// Copyright (c) 2016 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.
+
+#include "net/tools/domain_security_preload_generator/trie/trie_writer.h"
+
+#include <algorithm>
+
+#include "base/logging.h"
+#include "base/strings/string_piece.h"
+#include "base/strings/string_split.h"
+#include "base/strings/string_util.h"
+#include "net/tools/domain_security_preload_generator/trie/trie_bit_buffer.h"
+
+namespace net {
+
+namespace transport_security_state {
+
+namespace {
+
+bool CompareReversedEntries(const std::unique_ptr<ReversedEntry>& lhs,
+ const std::unique_ptr<ReversedEntry>& rhs) {
+ return lhs->reversed_name < rhs->reversed_name;
+}
+
+std::string DomainConstant(base::StringPiece input) {
+ std::vector<base::StringPiece> parts = base::SplitStringPiece(
+ input, ".", base::TRIM_WHITESPACE, base::SPLIT_WANT_ALL);
+ if (parts.empty()) {
+ return std::string();
+ }
+
+ std::string gtld = parts[parts.size() - 1].as_string();
+ if (parts.size() == 1) {
+ return base::ToUpperASCII(gtld);
+ }
+
+ std::string domain = base::ToUpperASCII(parts[parts.size() - 2].as_string());
+ base::ReplaceChars(domain, "-", "_", &domain);
+
+ return base::ToUpperASCII(domain + "_" + gtld);
+}
+
+} // namespace
+
+ReversedEntry::ReversedEntry(std::vector<uint8_t> reversed_name,
+ const DomainSecurityEntry* entry)
+ : reversed_name(reversed_name), entry(entry) {}
+
+ReversedEntry::~ReversedEntry() {}
+
+TrieWriter::TrieWriter(const HuffmanRepresentationTable& huffman_table,
+ const NameIDMap& domain_ids_map,
+ const NameIDMap& expect_ct_report_uri_map,
+ const NameIDMap& expect_staple_report_uri_map,
+ const NameIDMap& pinsets_map,
+ HuffmanFrequencyTracker* frequency_tracker)
+ : huffman_table_(huffman_table),
+ domain_ids_map_(domain_ids_map),
+ expect_ct_report_uri_map_(expect_ct_report_uri_map),
+ expect_staple_report_uri_map_(expect_staple_report_uri_map),
+ pinsets_map_(pinsets_map),
+ frequency_tracker_(frequency_tracker) {}
+
+TrieWriter::~TrieWriter() {}
+
+uint32_t TrieWriter::WriteEntries(const DomainSecurityEntries& entries) {
+ ReversedEntries reversed_entries;
+
+ for (auto const& entry : entries) {
+ std::unique_ptr<ReversedEntry> reversed_entry(
+ new ReversedEntry(ReverseName(entry->hostname), entry.get()));
+ reversed_entries.push_back(std::move(reversed_entry));
+ }
+
+ std::stable_sort(reversed_entries.begin(), reversed_entries.end(),
+ CompareReversedEntries);
+
+ return WriteDispatchTables(reversed_entries.begin(), reversed_entries.end());
+}
+
+uint32_t TrieWriter::WriteDispatchTables(ReversedEntries::iterator start,
+ ReversedEntries::iterator end) {
+ DCHECK(start != end) << "No entries passed to WriteDispatchTables";
+
+ TrieBitBuffer writer;
+
+ std::vector<uint8_t> prefix = LongestCommonPrefix(start, end);
+ for (size_t i = 0; i < prefix.size(); ++i) {
+ writer.WriteBit(1);
+ }
+ writer.WriteBit(0);
+
+ if (prefix.size()) {
+ for (size_t i = 0; i < prefix.size(); ++i) {
+ writer.WriteChar(prefix.at(i), huffman_table_, frequency_tracker_);
+ }
+ }
+
+ RemovePrefix(prefix.size(), start, end);
+ int32_t last_position = -1;
+
+ while (start != end) {
+ uint8_t candidate = (*start)->reversed_name.at(0);
+ ReversedEntries::iterator sub_entries_end = start + 1;
+
+ for (; sub_entries_end != end; sub_entries_end++) {
+ if ((*sub_entries_end)->reversed_name.at(0) != candidate) {
+ break;
+ }
+ }
+
+ writer.WriteChar(candidate, huffman_table_, frequency_tracker_);
+
+ if (candidate == kTerminalValue) {
+ DCHECK((sub_entries_end - start) == 1)
+ << "Multiple values with the same name";
+ WriteSecurityEntry((*start)->entry, &writer);
+ } else {
+ RemovePrefix(1, start, sub_entries_end);
+ uint32_t position = WriteDispatchTables(start, sub_entries_end);
+ writer.WritePosition(position, &last_position);
+ }
+
+ start = sub_entries_end;
+ }
+
+ writer.WriteChar(kEndOfTableValue, huffman_table_, frequency_tracker_);
+
+ uint32_t position = buffer_.position();
+ writer.Flush();
+ writer.WriteToBitWriter(&buffer_);
+ return position;
+}
+
+void TrieWriter::WriteSecurityEntry(const DomainSecurityEntry* entry,
+ TrieBitBuffer* writer) {
+ uint8_t include_subdomains = 0;
+ if (entry->include_subdomains) {
+ include_subdomains = 1;
+ }
+ writer->WriteBit(include_subdomains);
+
+ uint8_t force_https = 0;
+ if (entry->force_https) {
+ force_https = 1;
+ }
+ writer->WriteBit(force_https);
+
+ if (entry->pinset.size()) {
+ writer->WriteBit(1);
+ NameIDMap::const_iterator pin_id_it = pinsets_map_.find(entry->pinset);
+ DCHECK(pin_id_it != pinsets_map_.cend()) << "invalid pinset";
+ const uint8_t& pin_id = pin_id_it->second;
+ DCHECK(pin_id <= 16) << "too many pinsets";
+ writer->WriteBits(pin_id, 4);
+
+ NameIDMap::const_iterator domain_id_it =
+ domain_ids_map_.find(DomainConstant(entry->hostname));
+ DCHECK(domain_id_it != domain_ids_map_.cend()) << "invalid domain id";
+ uint32_t domain_id = domain_id_it->second;
+ DCHECK(domain_id < 512) << "too many domain ids";
+ writer->WriteBits(domain_id, 9);
+
+ if (!entry->include_subdomains) {
+ uint8_t include_subdomains_for_pinning = 0;
+ if (entry->hpkp_include_subdomains) {
+ include_subdomains_for_pinning = 1;
+ }
+ writer->WriteBit(include_subdomains_for_pinning);
+ }
+ } else {
+ writer->WriteBit(0);
+ }
+
+ if (entry->expect_ct) {
+ writer->WriteBit(1);
+ NameIDMap::const_iterator expect_ct_report_uri_it =
+ expect_ct_report_uri_map_.find(entry->expect_ct_report_uri);
+ DCHECK(expect_ct_report_uri_it != expect_ct_report_uri_map_.cend())
+ << "invalid expect-ct report-uri";
+ const uint8_t& expect_ct_report_id = expect_ct_report_uri_it->second;
+
+ DCHECK(expect_ct_report_id < 16) << "too many expect-ct ids";
+
+ writer->WriteBits(expect_ct_report_id, 4);
+ } else {
+ writer->WriteBit(0);
+ }
+
+ if (entry->expect_staple) {
+ writer->WriteBit(1);
+
+ if (entry->expect_staple_include_subdomains) {
+ writer->WriteBit(1);
+ } else {
+ writer->WriteBit(0);
+ }
+
+ NameIDMap::const_iterator expect_staple_report_uri_it =
+ expect_staple_report_uri_map_.find(entry->expect_staple_report_uri);
+ DCHECK(expect_staple_report_uri_it != expect_staple_report_uri_map_.cend())
+ << "invalid expect-ct report-uri";
+ const uint8_t& expect_staple_report_id =
+ expect_staple_report_uri_it->second;
+ DCHECK(expect_staple_report_id < 16) << "too many expect-staple ids";
+
+ writer->WriteBits(expect_staple_report_id, 4);
+ } else {
+ writer->WriteBit(0);
+ }
+}
+
+void TrieWriter::RemovePrefix(size_t length,
+ ReversedEntries::iterator start,
+ ReversedEntries::iterator end) {
+ for (ReversedEntries::iterator it = start; it != end; ++it) {
+ (*it)->reversed_name.erase((*it)->reversed_name.begin(),
+ (*it)->reversed_name.begin() + length);
+ }
+}
+
+std::vector<uint8_t> TrieWriter::LongestCommonPrefix(
+ ReversedEntries::iterator start,
+ ReversedEntries::iterator end) const {
+ if (start == end) {
+ return std::vector<uint8_t>();
+ }
+
+ std::vector<uint8_t> prefix;
+ for (size_t i = 0;; ++i) {
+ if (i > (*start)->reversed_name.size()) {
+ break;
+ }
+
+ uint8_t candidate = (*start)->reversed_name.at(i);
+ if (candidate == kTerminalValue) {
+ break;
+ }
+
+ bool ok = true;
+ for (ReversedEntries::iterator it = start + 1; it != end; ++it) {
+ if (i > (*it)->reversed_name.size() ||
+ (*it)->reversed_name.at(i) != candidate) {
+ ok = false;
+ break;
+ }
+ }
+
+ if (!ok) {
+ break;
+ }
+
+ prefix.push_back(candidate);
+ }
+
+ return prefix;
+}
+
+std::vector<uint8_t> TrieWriter::ReverseName(
+ const std::string& hostname) const {
+ size_t hostname_size = hostname.size();
+ std::vector<uint8_t> reversed_name(hostname_size + 1);
+
+ for (size_t i = 0; i < hostname_size; ++i) {
+ reversed_name[i] = hostname[hostname_size - i - 1];
+ }
+
+ reversed_name[reversed_name.size() - 1] = kTerminalValue;
+ return reversed_name;
+}
+
+uint32_t TrieWriter::position() const {
+ return buffer_.position();
+}
+
+void TrieWriter::Flush() {
+ buffer_.Flush();
+}
+
+} // namespace transport_security_state
+
+} // namespace net
diff --git a/chromium/net/tools/domain_security_preload_generator/trie/trie_writer.h b/chromium/net/tools/domain_security_preload_generator/trie/trie_writer.h
new file mode 100644
index 00000000000..a28aad235ab
--- /dev/null
+++ b/chromium/net/tools/domain_security_preload_generator/trie/trie_writer.h
@@ -0,0 +1,92 @@
+// Copyright (c) 2016 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.
+
+#ifndef NET_TOOLS_DOMAIN_SECURITY_PRELOAD_GENERATOR_TRIE_TRIE_WRITER_H_
+#define NET_TOOLS_DOMAIN_SECURITY_PRELOAD_GENERATOR_TRIE_TRIE_WRITER_H_
+
+#include <string>
+#include <vector>
+
+#include "net/tools/domain_security_preload_generator/bit_writer.h"
+#include "net/tools/domain_security_preload_generator/domain_security_entry.h"
+#include "net/tools/domain_security_preload_generator/huffman/huffman_frequency_tracker.h"
+
+namespace net {
+
+namespace transport_security_state {
+
+struct DomainSecurityEntry;
+class TrieBitBuffer;
+
+// Maps a name to an index. This is used to track the index of several values
+// in the C++ code. The trie refers to the array index of the values. For
+// example; the pinsets are outputted as a C++ array and the index for the
+// pinset in that array is placed in the trie.
+using NameIDMap = std::map<std::string, uint32_t>;
+using NameIDPair = std::pair<std::string, uint32_t>;
+
+class TrieWriter {
+ public:
+ enum : uint8_t { kTerminalValue = 0, kEndOfTableValue = 127 };
+
+ TrieWriter(const HuffmanRepresentationTable& huffman_table,
+ const NameIDMap& domain_ids_map,
+ const NameIDMap& expect_ct_report_uri_map,
+ const NameIDMap& expect_staple_report_uri_map,
+ const NameIDMap& pinsets_map,
+ HuffmanFrequencyTracker* frequency_tracker);
+ ~TrieWriter();
+
+ // Constructs a trie containing all |entries|. The output is written to
+ // |buffer_|. Returns the position of the trie root.
+ uint32_t WriteEntries(const DomainSecurityEntries& entries);
+
+ // Returns the position |buffer_| is currently at. The returned value
+ // represents the number of bits.
+ uint32_t position() const;
+
+ // Flushes |buffer_|.
+ void Flush();
+
+ // Returns the trie bytes. Call Flush() first to ensure the buffer is
+ // complete.
+ const std::vector<uint8_t>& bytes() const { return buffer_.bytes(); }
+
+ private:
+ uint32_t WriteDispatchTables(ReversedEntries::iterator start,
+ ReversedEntries::iterator end);
+
+ // Serializes |*entry| and writes it to |*writer|.
+ void WriteSecurityEntry(const DomainSecurityEntry* entry,
+ TrieBitBuffer* writer);
+
+ // Removes the first |length| characters from all entries between |start| and
+ // |end|.
+ void RemovePrefix(size_t length,
+ ReversedEntries::iterator start,
+ ReversedEntries::iterator end);
+
+ // Searches for the longest common prefix for all entries between |start| and
+ // |end|.
+ std::vector<uint8_t> LongestCommonPrefix(ReversedEntries::iterator start,
+ ReversedEntries::iterator end) const;
+
+ // Returns the reversed |hostname| as a vector of bytes. The reversed hostname
+ // will be terminated by |kTerminalValue|.
+ std::vector<uint8_t> ReverseName(const std::string& hostname) const;
+
+ BitWriter buffer_;
+ const HuffmanRepresentationTable& huffman_table_;
+ const NameIDMap& domain_ids_map_;
+ const NameIDMap& expect_ct_report_uri_map_;
+ const NameIDMap& expect_staple_report_uri_map_;
+ const NameIDMap& pinsets_map_;
+ HuffmanFrequencyTracker* frequency_tracker_;
+};
+
+} // namespace transport_security_state
+
+} // namespace net
+
+#endif // NET_TOOLS_DOMAIN_SECURITY_PRELOAD_GENERATOR_TRIE_TRIE_WRITER_H_
diff --git a/chromium/net/tools/dump_cache/dump_cache.cc b/chromium/net/tools/dump_cache/dump_cache.cc
index 74cbd4064a7..2b5aafdb053 100644
--- a/chromium/net/tools/dump_cache/dump_cache.cc
+++ b/chromium/net/tools/dump_cache/dump_cache.cc
@@ -12,7 +12,6 @@
#include "base/command_line.h"
#include "base/strings/string16.h"
#include "base/strings/string_util.h"
-#include "base/strings/stringprintf.h"
#include "net/disk_cache/blockfile/disk_format.h"
#include "net/tools/dump_cache/dump_files.h"
diff --git a/chromium/net/tools/epoll_server/epoll_server.cc b/chromium/net/tools/epoll_server/epoll_server.cc
index 042e40320c0..077141032f2 100644
--- a/chromium/net/tools/epoll_server/epoll_server.cc
+++ b/chromium/net/tools/epoll_server/epoll_server.cc
@@ -193,8 +193,8 @@ void EpollServer::RegisterFD(int fd, CB* cb, int event_mask) {
VLOG(3) << "RegisterFD fd=" << fd << " event_mask=" << event_mask;
FDToCBMap::iterator fd_i = cb_map_.find(CBAndEventMask(NULL, 0, fd));
if (cb_map_.end() != fd_i) {
- // do we just abort, or do we just unregister the other guy?
- // for now, lets just unregister the other guy.
+ // do we just abort, or do we just unregister the other callback?
+ // for now, lets just unregister the other callback.
// unregister any callback that may already be registered for this FD.
CB* other_cb = fd_i->cb;
@@ -680,7 +680,7 @@ void EpollServer::CallReadyListCallbacks() {
std::swap(ready_list_.lh_first, tmp_list_.lh_first);
if (tmp_list_.lh_first) {
tmp_list_.lh_first->entry.le_prev = &tmp_list_.lh_first;
- EpollEvent event(0, false);
+ EpollEvent event(0);
while (tmp_list_.lh_first != NULL) {
DCHECK_GT(ready_list_size_, 0);
CBAndEventMask* cb_and_mask = tmp_list_.lh_first;
diff --git a/chromium/net/tools/epoll_server/epoll_server.h b/chromium/net/tools/epoll_server/epoll_server.h
index b5530998714..9c16303e442 100644
--- a/chromium/net/tools/epoll_server/epoll_server.h
+++ b/chromium/net/tools/epoll_server/epoll_server.h
@@ -47,7 +47,7 @@ class EpollAlarmCallbackInterface;
class ReadPipeCallback;
struct EpollEvent {
- EpollEvent(int events, bool is_epoll_wait)
+ EpollEvent(int events)
: in_events(events),
out_ready_mask(0) {
}
@@ -477,13 +477,6 @@ class EpollServer {
// Returns true when the EpollServer() is being destroyed.
bool in_shutdown() const { return in_shutdown_; }
- // Summary:
- // A function for implementing the ready list. It invokes OnEvent for each
- // of the fd in the ready list, and takes care of adding them back to the
- // ready list if the callback requests it (by checking that out_ready_mask
- // is non-zero).
- void CallReadyListCallbacks();
-
protected:
virtual void SetNonblocking(int fd);
@@ -631,6 +624,13 @@ class EpollServer {
int events_size);
// Summary:
+ // A function for implementing the ready list. It invokes OnEvent for each
+ // of the fd in the ready list, and takes care of adding them back to the
+ // ready list if the callback requests it (by checking that out_ready_mask
+ // is non-zero).
+ void CallReadyListCallbacks();
+
+ // Summary:
// An internal function for implementing the ready list. It adds a fd's
// CBAndEventMask to the ready list. If the fd is already on the ready
// list, it is a no-op.
diff --git a/chromium/net/tools/quic/chlo_extractor.cc b/chromium/net/tools/quic/chlo_extractor.cc
index 3e5ce787f7a..14ac9e30067 100644
--- a/chromium/net/tools/quic/chlo_extractor.cc
+++ b/chromium/net/tools/quic/chlo_extractor.cc
@@ -4,13 +4,13 @@
#include "net/tools/quic/chlo_extractor.h"
-#include "base/strings/string_util.h"
#include "net/quic/core/crypto/crypto_framer.h"
#include "net/quic/core/crypto/crypto_handshake_message.h"
#include "net/quic/core/crypto/crypto_protocol.h"
#include "net/quic/core/crypto/quic_decrypter.h"
#include "net/quic/core/crypto/quic_encrypter.h"
#include "net/quic/core/quic_framer.h"
+#include "net/quic/platform/api/quic_text_utils.h"
using base::StringPiece;
@@ -93,7 +93,7 @@ bool ChloFramerVisitor::OnPacketHeader(const QuicPacketHeader& header) {
bool ChloFramerVisitor::OnStreamFrame(const QuicStreamFrame& frame) {
StringPiece data(frame.data_buffer, frame.data_length);
if (frame.stream_id == kCryptoStreamId && frame.offset == 0 &&
- base::StartsWith(data, "CHLO", base::CompareCase::INSENSITIVE_ASCII)) {
+ QuicTextUtils::StartsWith(data, "CHLO")) {
CryptoFramer crypto_framer;
crypto_framer.set_visitor(this);
if (!crypto_framer.ProcessInput(data)) {
diff --git a/chromium/net/tools/quic/chlo_extractor.h b/chromium/net/tools/quic/chlo_extractor.h
index 7820bb596ca..176ad047b81 100644
--- a/chromium/net/tools/quic/chlo_extractor.h
+++ b/chromium/net/tools/quic/chlo_extractor.h
@@ -6,7 +6,7 @@
#define NET_TOOLS_QUIC_CHLO_EXTRACTOR_H_
#include "net/quic/core/crypto/crypto_handshake_message.h"
-#include "net/quic/core/quic_protocol.h"
+#include "net/quic/core/quic_packets.h"
namespace net {
diff --git a/chromium/net/tools/quic/chlo_extractor_test.cc b/chromium/net/tools/quic/chlo_extractor_test.cc
index 1be18208c91..bdce1b81c3a 100644
--- a/chromium/net/tools/quic/chlo_extractor_test.cc
+++ b/chromium/net/tools/quic/chlo_extractor_test.cc
@@ -52,8 +52,6 @@ class ChloExtractorTest : public ::testing::Test {
header_.public_header.reset_flag = false;
header_.public_header.packet_number_length = PACKET_6BYTE_PACKET_NUMBER;
header_.packet_number = 1;
- header_.entropy_flag = false;
- header_.entropy_hash = 0;
}
void MakePacket(QuicStreamFrame* stream_frame) {
diff --git a/chromium/net/tools/quic/crypto_message_printer_bin.cc b/chromium/net/tools/quic/crypto_message_printer_bin.cc
index 11eb8f83410..d0b46c60e9c 100644
--- a/chromium/net/tools/quic/crypto_message_printer_bin.cc
+++ b/chromium/net/tools/quic/crypto_message_printer_bin.cc
@@ -11,7 +11,7 @@
#include "base/command_line.h"
#include "net/quic/core/crypto/crypto_framer.h"
-#include "net/quic/core/quic_utils.h"
+#include "net/quic/platform/api/quic_text_utils.h"
using std::cerr;
using std::cout;
@@ -44,7 +44,7 @@ int main(int argc, char* argv[]) {
net::CryptoMessagePrinter printer;
net::CryptoFramer framer;
framer.set_visitor(&printer);
- std::string input = net::QuicUtils::HexDecode(argv[1]);
+ std::string input = net::QuicTextUtils::HexDecode(argv[1]);
if (!framer.ProcessInput(input)) {
return 1;
}
diff --git a/chromium/net/tools/quic/end_to_end_test.cc b/chromium/net/tools/quic/end_to_end_test.cc
index b9031a1d3bd..93e499d9754 100644
--- a/chromium/net/tools/quic/end_to_end_test.cc
+++ b/chromium/net/tools/quic/end_to_end_test.cc
@@ -8,13 +8,12 @@
#include <cstdint>
#include <list>
#include <memory>
+#include <ostream>
#include <string>
#include <utility>
#include <vector>
-#include "base/memory/ptr_util.h"
#include "base/memory/singleton.h"
-#include "base/strings/string_number_conversions.h"
#include "base/synchronization/waitable_event.h"
#include "base/threading/platform_thread.h"
#include "base/time/time.h"
@@ -26,10 +25,15 @@
#include "net/quic/core/quic_flags.h"
#include "net/quic/core/quic_framer.h"
#include "net/quic/core/quic_packet_creator.h"
-#include "net/quic/core/quic_protocol.h"
+#include "net/quic/core/quic_packets.h"
#include "net/quic/core/quic_server_id.h"
#include "net/quic/core/quic_session.h"
#include "net/quic/core/quic_utils.h"
+#include "net/quic/platform/api/quic_logging.h"
+#include "net/quic/platform/api/quic_ptr_util.h"
+#include "net/quic/platform/api/quic_socket_address.h"
+#include "net/quic/platform/api/quic_str_cat.h"
+#include "net/quic/platform/api/quic_text_utils.h"
#include "net/quic/test_tools/crypto_test_utils.h"
#include "net/quic/test_tools/quic_config_peer.h"
#include "net/quic/test_tools/quic_connection_peer.h"
@@ -42,18 +46,17 @@
#include "net/quic/test_tools/quic_test_utils.h"
#include "net/test/gtest_util.h"
#include "net/tools/epoll_server/epoll_server.h"
+#include "net/tools/quic/platform/impl/quic_socket_utils.h"
#include "net/tools/quic/quic_epoll_connection_helper.h"
-#include "net/tools/quic/quic_in_memory_cache.h"
+#include "net/tools/quic/quic_http_response_cache.h"
#include "net/tools/quic/quic_packet_writer_wrapper.h"
#include "net/tools/quic/quic_server.h"
#include "net/tools/quic/quic_simple_server_stream.h"
-#include "net/tools/quic/quic_socket_utils.h"
#include "net/tools/quic/quic_spdy_client_stream.h"
#include "net/tools/quic/test_tools/packet_dropping_test_writer.h"
#include "net/tools/quic/test_tools/packet_reordering_writer.h"
#include "net/tools/quic/test_tools/quic_client_peer.h"
#include "net/tools/quic/test_tools/quic_dispatcher_peer.h"
-#include "net/tools/quic/test_tools/quic_in_memory_cache_peer.h"
#include "net/tools/quic/test_tools/quic_server_peer.h"
#include "net/tools/quic/test_tools/quic_test_client.h"
#include "net/tools/quic/test_tools/quic_test_server.h"
@@ -63,10 +66,7 @@
using base::IntToString;
using base::StringPiece;
using base::WaitableEvent;
-using net::EpollServer;
-using std::ostream;
using std::string;
-using std::vector;
namespace net {
namespace test {
@@ -98,7 +98,7 @@ struct TestParams {
force_hol_blocking(force_hol_blocking),
use_cheap_stateless_reject(use_cheap_stateless_reject) {}
- friend ostream& operator<<(ostream& os, const TestParams& p) {
+ friend std::ostream& operator<<(std::ostream& os, const TestParams& p) {
os << "{ server_supported_versions: "
<< QuicVersionVectorToString(p.server_supported_versions);
os << " client_supported_versions: "
@@ -109,7 +109,7 @@ struct TestParams {
os << " server_uses_stateless_rejects_if_peer_supported: "
<< p.server_uses_stateless_rejects_if_peer_supported;
os << " congestion_control_tag: "
- << QuicUtils::TagToString(p.congestion_control_tag);
+ << QuicTagToString(p.congestion_control_tag);
os << " disable_hpack_dynamic_table: " << p.disable_hpack_dynamic_table;
os << " force_hol_blocking: " << p.force_hol_blocking;
os << " use_cheap_stateless_reject: " << p.use_cheap_stateless_reject
@@ -139,23 +139,15 @@ std::vector<TestParams> GetTestParams() {
// to do 0-RTT across incompatible versions. Chromium only supports
// a single version at a time anyway. :)
QuicVersionVector all_supported_versions = AllSupportedVersions();
- QuicVersionVector version_buckets[3];
+ // Even though this currently has one element, it may well get another
+ // with future versions of QUIC, so don't remove it.
+ QuicVersionVector version_buckets[1];
for (const QuicVersion version : all_supported_versions) {
- if (version <= QUIC_VERSION_32) {
- // Versions: 31-32
- // v31 adds a hash of the CHLO into the proof signature.
- version_buckets[0].push_back(version);
- } else if (version <= QUIC_VERSION_33) {
- // Versions: 33
- // v33 adds a diversification nonce into the hkdf.
- version_buckets[1].push_back(version);
- } else {
- // Versions: 34+
- // QUIC_VERSION_34 deprecates entropy and uses new ack and stop waiting
- // wire formats.
- version_buckets[2].push_back(version);
- }
+ // Versions: 34+
+ // QUIC_VERSION_34 deprecates entropy and uses new ack and stop waiting
+ // wire formats.
+ version_buckets[0].push_back(version);
}
// This must be kept in sync with the number of nested for-loops below as it
@@ -268,7 +260,7 @@ class ClientDelegate : public PacketDroppingTestWriter::Delegate {
explicit ClientDelegate(QuicClient* client) : client_(client) {}
~ClientDelegate() override {}
void OnCanWrite() override {
- EpollEvent event(EPOLLOUT, false);
+ EpollEvent event(EPOLLOUT);
client_->OnEvent(client_->GetLatestFD(), &event);
}
@@ -280,12 +272,11 @@ class EndToEndTest : public ::testing::TestWithParam<TestParams> {
protected:
EndToEndTest()
: initialized_(false),
- server_address_(IPEndPoint(Loopback4(), 0)),
+ server_address_(QuicSocketAddress(QuicIpAddress::Loopback4(), 0)),
server_hostname_("test.example.com"),
client_writer_(nullptr),
server_writer_(nullptr),
server_started_(false),
- strike_register_no_startup_period_(false),
chlo_multiplier_(0),
stream_factory_(nullptr),
support_server_push_(false) {
@@ -293,7 +284,7 @@ class EndToEndTest : public ::testing::TestWithParam<TestParams> {
server_supported_versions_ = GetParam().server_supported_versions;
negotiated_version_ = GetParam().negotiated_version;
- VLOG(1) << "Using Configuration: " << GetParam();
+ QUIC_LOG(INFO) << "Using Configuration: " << GetParam();
// Use different flow control windows for client/server.
client_config_.SetInitialStreamFlowControlWindowToSend(
@@ -313,7 +304,6 @@ class EndToEndTest : public ::testing::TestWithParam<TestParams> {
server_config_.set_max_time_before_crypto_handshake(timeout);
server_config_.set_max_idle_time_before_crypto_handshake(timeout);
- QuicInMemoryCachePeer::ResetForTests();
AddToCache("/foo", 200, kFooResponseBody);
AddToCache("/bar", 200, kBarResponseBody);
}
@@ -321,7 +311,6 @@ class EndToEndTest : public ::testing::TestWithParam<TestParams> {
~EndToEndTest() override {
// TODO(rtenneti): port RecycleUnusedPort if needed.
// RecycleUnusedPort(server_address_.port());
- QuicInMemoryCachePeer::ResetForTests();
}
virtual void CreateClientWithWriter() {
@@ -350,32 +339,34 @@ class EndToEndTest : public ::testing::TestWithParam<TestParams> {
void set_client_initial_stream_flow_control_receive_window(uint32_t window) {
CHECK(client_.get() == nullptr);
- DVLOG(1) << "Setting client initial stream flow control window: " << window;
+ QUIC_DLOG(INFO) << "Setting client initial stream flow control window: "
+ << window;
client_config_.SetInitialStreamFlowControlWindowToSend(window);
}
void set_client_initial_session_flow_control_receive_window(uint32_t window) {
CHECK(client_.get() == nullptr);
- DVLOG(1) << "Setting client initial session flow control window: "
- << window;
+ QUIC_DLOG(INFO) << "Setting client initial session flow control window: "
+ << window;
client_config_.SetInitialSessionFlowControlWindowToSend(window);
}
void set_server_initial_stream_flow_control_receive_window(uint32_t window) {
CHECK(server_thread_.get() == nullptr);
- DVLOG(1) << "Setting server initial stream flow control window: " << window;
+ QUIC_DLOG(INFO) << "Setting server initial stream flow control window: "
+ << window;
server_config_.SetInitialStreamFlowControlWindowToSend(window);
}
void set_server_initial_session_flow_control_receive_window(uint32_t window) {
CHECK(server_thread_.get() == nullptr);
- DVLOG(1) << "Setting server initial session flow control window: "
- << window;
+ QUIC_DLOG(INFO) << "Setting server initial session flow control window: "
+ << window;
server_config_.SetInitialSessionFlowControlWindowToSend(window);
}
- const QuicSentPacketManagerInterface*
- GetSentPacketManagerFromFirstServerSession() const {
+ const QuicSentPacketManager* GetSentPacketManagerFromFirstServerSession()
+ const {
QuicDispatcher* dispatcher =
QuicServerPeer::GetDispatcher(server_thread_->server());
QuicSession* session = dispatcher->session_map().begin()->second.get();
@@ -385,10 +376,19 @@ class EndToEndTest : public ::testing::TestWithParam<TestParams> {
bool Initialize() {
QuicTagVector copt;
server_config_.SetConnectionOptionsToSend(copt);
+ copt = client_extra_copts_;
// TODO(nimia): Consider setting the congestion control algorithm for the
// client as well according to the test parameter.
copt.push_back(GetParam().congestion_control_tag);
+ if (GetParam().congestion_control_tag == kQBIC &&
+ FLAGS_quic_reloadable_flag_quic_fix_cubic_convex_mode) {
+ copt.push_back(kCCVX);
+ }
+ if (GetParam().congestion_control_tag == kQBIC &&
+ FLAGS_quic_reloadable_flag_quic_fix_cubic_bytes_quantization) {
+ copt.push_back(kCBQT);
+ }
if (support_server_push_) {
copt.push_back(kSPSH);
}
@@ -408,7 +408,7 @@ class EndToEndTest : public ::testing::TestWithParam<TestParams> {
StartServer();
CreateClientWithWriter();
- static EpollEvent event(EPOLLOUT, false);
+ static EpollEvent event(EPOLLOUT);
if (client_writer_ != nullptr) {
client_writer_->Initialize(
QuicConnectionPeer::GetHelper(
@@ -435,25 +435,24 @@ class EndToEndTest : public ::testing::TestWithParam<TestParams> {
}
void StartServer() {
- FLAGS_quic_use_cheap_stateless_rejects =
+ FLAGS_quic_reloadable_flag_quic_use_cheap_stateless_rejects =
GetParam().use_cheap_stateless_reject;
- auto test_server =
- new QuicTestServer(CryptoTestUtils::ProofSourceForTesting(),
- server_config_, server_supported_versions_);
- server_thread_.reset(new ServerThread(test_server, server_address_,
- strike_register_no_startup_period_));
+ auto test_server = new QuicTestServer(
+ CryptoTestUtils::ProofSourceForTesting(), server_config_,
+ server_supported_versions_, &response_cache_);
+ server_thread_.reset(new ServerThread(test_server, server_address_));
if (chlo_multiplier_ != 0) {
server_thread_->server()->SetChloMultiplier(chlo_multiplier_);
}
server_thread_->Initialize();
server_address_ =
- IPEndPoint(server_address_.address(), server_thread_->GetPort());
+ QuicSocketAddress(server_address_.host(), server_thread_->GetPort());
QuicDispatcher* dispatcher =
QuicServerPeer::GetDispatcher(server_thread_->server());
QuicDispatcherPeer::UseWriter(dispatcher, server_writer_);
- FLAGS_enable_quic_stateless_reject_support =
+ FLAGS_quic_reloadable_flag_enable_quic_stateless_reject_support =
GetParam().server_uses_stateless_rejects_if_peer_supported;
server_writer_->Initialize(QuicDispatcherPeer::GetHelper(dispatcher),
@@ -478,8 +477,8 @@ class EndToEndTest : public ::testing::TestWithParam<TestParams> {
}
void AddToCache(StringPiece path, int response_code, StringPiece body) {
- QuicInMemoryCache::GetInstance()->AddSimpleResponse(server_hostname_, path,
- response_code, body);
+ response_cache_.AddSimpleResponse(server_hostname_, path, response_code,
+ body);
}
void SetPacketLossPercentage(int32_t loss) {
@@ -567,8 +566,9 @@ class EndToEndTest : public ::testing::TestWithParam<TestParams> {
QuicFlagSaver flags_; // Save/restore all QUIC flag values.
bool initialized_;
- IPEndPoint server_address_;
+ QuicSocketAddress server_address_;
string server_hostname_;
+ QuicHttpResponseCache response_cache_;
std::unique_ptr<ServerThread> server_thread_;
std::unique_ptr<QuicTestClient> client_;
PacketDroppingTestWriter* client_writer_;
@@ -578,8 +578,8 @@ class EndToEndTest : public ::testing::TestWithParam<TestParams> {
QuicConfig server_config_;
QuicVersionVector client_supported_versions_;
QuicVersionVector server_supported_versions_;
+ QuicTagVector client_extra_copts_;
QuicVersion negotiated_version_;
- bool strike_register_no_startup_period_;
size_t chlo_multiplier_;
QuicTestServer::StreamFactory* stream_factory_;
bool support_server_push_;
@@ -593,23 +593,27 @@ INSTANTIATE_TEST_CASE_P(EndToEndTests,
TEST_P(EndToEndTest, HandshakeSuccessful) {
ASSERT_TRUE(Initialize());
- client_->client()->WaitForCryptoHandshakeConfirmed();
+ EXPECT_TRUE(client_->client()->WaitForCryptoHandshakeConfirmed());
QuicCryptoStream* crypto_stream =
QuicSessionPeer::GetCryptoStream(client_->client()->session());
QuicStreamSequencer* sequencer = QuicStreamPeer::sequencer(crypto_stream);
- EXPECT_NE(FLAGS_quic_release_crypto_stream_buffer,
- QuicStreamSequencerPeer::IsUnderlyingBufferAllocated(sequencer));
+ EXPECT_NE(
+ FLAGS_quic_reloadable_flag_quic_release_crypto_stream_buffer &&
+ FLAGS_quic_reloadable_flag_quic_reduce_sequencer_buffer_memory_life_time, // NOLINT
+ QuicStreamSequencerPeer::IsUnderlyingBufferAllocated(sequencer));
server_thread_->Pause();
QuicDispatcher* dispatcher =
QuicServerPeer::GetDispatcher(server_thread_->server());
QuicSession* server_session = dispatcher->session_map().begin()->second.get();
crypto_stream = QuicSessionPeer::GetCryptoStream(server_session);
sequencer = QuicStreamPeer::sequencer(crypto_stream);
- EXPECT_NE(FLAGS_quic_release_crypto_stream_buffer,
- QuicStreamSequencerPeer::IsUnderlyingBufferAllocated(sequencer));
+ EXPECT_NE(
+ FLAGS_quic_reloadable_flag_quic_release_crypto_stream_buffer &&
+ FLAGS_quic_reloadable_flag_quic_reduce_sequencer_buffer_memory_life_time, // NOLINT
+ QuicStreamSequencerPeer::IsUnderlyingBufferAllocated(sequencer));
}
-TEST_P(EndToEndTest, SimpleRequestResponse) {
+TEST_P(EndToEndTest, SimpleRequestResponsev6) {
ASSERT_TRUE(Initialize());
EXPECT_EQ(kFooResponseBody, client_->SendSynchronousRequest("/foo"));
@@ -630,7 +634,7 @@ TEST_P(EndToEndTest, SimpleRequestResponseWithLargeReject) {
// try bots) and selectively disable this test.
TEST_P(EndToEndTest, DISABLED_SimpleRequestResponsev6) {
server_address_ =
- IPEndPoint(IPAddress::IPv6Localhost(), server_address_.port());
+ QuicSocketAddress(QuicIpAddress::Loopback6(), server_address_.port());
ASSERT_TRUE(Initialize());
EXPECT_EQ(kFooResponseBody, client_->SendSynchronousRequest("/foo"));
@@ -741,11 +745,10 @@ TEST_P(EndToEndTest, PostMissingBytes) {
TEST_P(EndToEndTest, LargePostNoPacketLoss) {
ASSERT_TRUE(Initialize());
- client_->client()->WaitForCryptoHandshakeConfirmed();
+ EXPECT_TRUE(client_->client()->WaitForCryptoHandshakeConfirmed());
// 1 MB body.
- string body;
- GenerateBody(&body, 1024 * 1024);
+ string body(1024 * 1024, 'a');
SpdyHeaderBlock headers;
headers[":method"] = "POST";
headers[":path"] = "/foo";
@@ -763,11 +766,10 @@ TEST_P(EndToEndTest, LargePostNoPacketLoss1sRTT) {
ASSERT_TRUE(Initialize());
SetPacketSendDelay(QuicTime::Delta::FromMilliseconds(1000));
- client_->client()->WaitForCryptoHandshakeConfirmed();
+ EXPECT_TRUE(client_->client()->WaitForCryptoHandshakeConfirmed());
// 100 KB body.
- string body;
- GenerateBody(&body, 100 * 1024);
+ string body(100 * 1024, 'a');
SpdyHeaderBlock headers;
headers[":method"] = "POST";
headers[":path"] = "/foo";
@@ -791,12 +793,11 @@ TEST_P(EndToEndTest, LargePostWithPacketLoss) {
ASSERT_TRUE(Initialize());
// Wait for the server SHLO before upping the packet loss.
- client_->client()->WaitForCryptoHandshakeConfirmed();
+ EXPECT_TRUE(client_->client()->WaitForCryptoHandshakeConfirmed());
SetPacketLossPercentage(30);
// 10 KB body.
- string body;
- GenerateBody(&body, 1024 * 10);
+ string body(1024 * 10, 'a');
SpdyHeaderBlock headers;
headers[":method"] = "POST";
headers[":path"] = "/foo";
@@ -819,13 +820,12 @@ TEST_P(EndToEndTest, LargePostWithPacketLossAndBlockedSocket) {
ASSERT_TRUE(Initialize());
// Wait for the server SHLO before upping the packet loss.
- client_->client()->WaitForCryptoHandshakeConfirmed();
+ EXPECT_TRUE(client_->client()->WaitForCryptoHandshakeConfirmed());
SetPacketLossPercentage(10);
client_writer_->set_fake_blocked_socket_percentage(10);
// 10 KB body.
- string body;
- GenerateBody(&body, 1024 * 10);
+ string body(1024 * 10, 'a');
SpdyHeaderBlock headers;
headers[":method"] = "POST";
headers[":path"] = "/foo";
@@ -839,14 +839,13 @@ TEST_P(EndToEndTest, LargePostWithPacketLossAndBlockedSocket) {
TEST_P(EndToEndTest, LargePostNoPacketLossWithDelayAndReordering) {
ASSERT_TRUE(Initialize());
- client_->client()->WaitForCryptoHandshakeConfirmed();
+ EXPECT_TRUE(client_->client()->WaitForCryptoHandshakeConfirmed());
// Both of these must be called when the writer is not actively used.
SetPacketSendDelay(QuicTime::Delta::FromMilliseconds(2));
SetReorderPercentage(30);
// 1 MB body.
- string body;
- GenerateBody(&body, 1024 * 1024);
+ string body(1024 * 1024, 'a');
SpdyHeaderBlock headers;
headers[":method"] = "POST";
headers[":path"] = "/foo";
@@ -858,15 +857,11 @@ TEST_P(EndToEndTest, LargePostNoPacketLossWithDelayAndReordering) {
}
TEST_P(EndToEndTest, LargePostZeroRTTFailure) {
- // Have the server accept 0-RTT without waiting a startup period.
- strike_register_no_startup_period_ = true;
-
// Send a request and then disconnect. This prepares the client to attempt
// a 0-RTT handshake for the next request.
ASSERT_TRUE(Initialize());
- string body;
- GenerateBody(&body, 20480);
+ string body(20480, 'a');
SpdyHeaderBlock headers;
headers[":method"] = "POST";
headers[":path"] = "/foo";
@@ -895,14 +890,8 @@ TEST_P(EndToEndTest, LargePostZeroRTTFailure) {
EXPECT_EQ(kFooResponseBody,
client_->SendCustomSynchronousRequest(headers, body));
- if (negotiated_version_ <= QUIC_VERSION_32) {
- EXPECT_EQ(expected_num_hellos_latest_session,
- client_->client()->session()->GetNumSentClientHellos());
- EXPECT_EQ(2, client_->client()->GetNumSentClientHellos());
- } else {
- EXPECT_EQ(1, client_->client()->session()->GetNumSentClientHellos());
- EXPECT_EQ(1, client_->client()->GetNumSentClientHellos());
- }
+ EXPECT_EQ(1, client_->client()->session()->GetNumSentClientHellos());
+ EXPECT_EQ(1, client_->client()->GetNumSentClientHellos());
client_->Disconnect();
@@ -928,9 +917,6 @@ TEST_P(EndToEndTest, LargePostZeroRTTFailure) {
}
TEST_P(EndToEndTest, SynchronousRequestZeroRTTFailure) {
- // Have the server accept 0-RTT without waiting a startup period.
- strike_register_no_startup_period_ = true;
-
// Send a request and then disconnect. This prepares the client to attempt
// a 0-RTT handshake for the next request.
ASSERT_TRUE(Initialize());
@@ -955,14 +941,8 @@ TEST_P(EndToEndTest, SynchronousRequestZeroRTTFailure) {
ASSERT_TRUE(client_->client()->connected());
EXPECT_EQ(kFooResponseBody, client_->SendSynchronousRequest("/foo"));
- if (negotiated_version_ <= QUIC_VERSION_32) {
- EXPECT_EQ(expected_num_hellos_latest_session,
- client_->client()->session()->GetNumSentClientHellos());
- EXPECT_EQ(2, client_->client()->GetNumSentClientHellos());
- } else {
- EXPECT_EQ(1, client_->client()->session()->GetNumSentClientHellos());
- EXPECT_EQ(1, client_->client()->GetNumSentClientHellos());
- }
+ EXPECT_EQ(1, client_->client()->session()->GetNumSentClientHellos());
+ EXPECT_EQ(1, client_->client()->GetNumSentClientHellos());
client_->Disconnect();
@@ -987,15 +967,11 @@ TEST_P(EndToEndTest, SynchronousRequestZeroRTTFailure) {
}
TEST_P(EndToEndTest, LargePostSynchronousRequest) {
- // Have the server accept 0-RTT without waiting a startup period.
- strike_register_no_startup_period_ = true;
-
// Send a request and then disconnect. This prepares the client to attempt
// a 0-RTT handshake for the next request.
ASSERT_TRUE(Initialize());
- string body;
- GenerateBody(&body, 20480);
+ string body(20480, 'a');
SpdyHeaderBlock headers;
headers[":method"] = "POST";
headers[":path"] = "/foo";
@@ -1024,14 +1000,8 @@ TEST_P(EndToEndTest, LargePostSynchronousRequest) {
EXPECT_EQ(kFooResponseBody,
client_->SendCustomSynchronousRequest(headers, body));
- if (negotiated_version_ <= QUIC_VERSION_32) {
- EXPECT_EQ(expected_num_hellos_latest_session,
- client_->client()->session()->GetNumSentClientHellos());
- EXPECT_EQ(2, client_->client()->GetNumSentClientHellos());
- } else {
- EXPECT_EQ(1, client_->client()->session()->GetNumSentClientHellos());
- EXPECT_EQ(1, client_->client()->GetNumSentClientHellos());
- }
+ EXPECT_EQ(1, client_->client()->session()->GetNumSentClientHellos());
+ EXPECT_EQ(1, client_->client()->GetNumSentClientHellos());
client_->Disconnect();
@@ -1073,7 +1043,7 @@ TEST_P(EndToEndTest, SetInitialReceivedConnectionOptions) {
initial_received_options));
ASSERT_TRUE(Initialize());
- client_->client()->WaitForCryptoHandshakeConfirmed();
+ EXPECT_TRUE(client_->client()->WaitForCryptoHandshakeConfirmed());
server_thread_->WaitForCryptoHandshakeConfirmed();
EXPECT_FALSE(server_config_.SetInitialReceivedConnectionOptions(
@@ -1098,11 +1068,10 @@ TEST_P(EndToEndTest, LargePostSmallBandwidthLargeBuffer) {
server_writer_->set_max_bandwidth_and_buffer_size(
QuicBandwidth::FromBytesPerSecond(256 * 1024), 256 * 1024);
- client_->client()->WaitForCryptoHandshakeConfirmed();
+ EXPECT_TRUE(client_->client()->WaitForCryptoHandshakeConfirmed());
// 1 MB body.
- string body;
- GenerateBody(&body, 1024 * 1024);
+ string body(1024 * 1024, 'a');
SpdyHeaderBlock headers;
headers[":method"] = "POST";
headers[":path"] = "/foo";
@@ -1123,7 +1092,7 @@ TEST_P(EndToEndTest, DoNotSetResumeWriteAlarmIfConnectionFlowControlBlocked) {
// an infinite loop in the EpollServer, as the alarm fires and is immediately
// rescheduled.
ASSERT_TRUE(Initialize());
- client_->client()->WaitForCryptoHandshakeConfirmed();
+ EXPECT_TRUE(client_->client()->WaitForCryptoHandshakeConfirmed());
// Ensure both stream and connection level are flow control blocked by setting
// the send window offset to 0.
@@ -1158,10 +1127,9 @@ TEST_P(EndToEndTest, DoNotSetResumeWriteAlarmIfConnectionFlowControlBlocked) {
TEST_P(EndToEndTest, InvalidStream) {
ASSERT_TRUE(Initialize());
- client_->client()->WaitForCryptoHandshakeConfirmed();
+ EXPECT_TRUE(client_->client()->WaitForCryptoHandshakeConfirmed());
- string body;
- GenerateBody(&body, kMaxPacketSize);
+ string body(kMaxPacketSize, 'a');
SpdyHeaderBlock headers;
headers[":method"] = "POST";
headers[":path"] = "/foo";
@@ -1181,10 +1149,9 @@ TEST_P(EndToEndTest, InvalidStream) {
// to send a request with overly large headers.
TEST_P(EndToEndTest, LargeHeaders) {
ASSERT_TRUE(Initialize());
- client_->client()->WaitForCryptoHandshakeConfirmed();
+ EXPECT_TRUE(client_->client()->WaitForCryptoHandshakeConfirmed());
- string body;
- GenerateBody(&body, kMaxPacketSize);
+ string body(kMaxPacketSize, 'a');
SpdyHeaderBlock headers;
headers[":method"] = "POST";
headers[":path"] = "/foo";
@@ -1195,7 +1162,7 @@ TEST_P(EndToEndTest, LargeHeaders) {
headers["key3"] = string(15 * 1024, 'a');
client_->SendCustomSynchronousRequest(headers, body);
- if (FLAGS_quic_limit_uncompressed_headers) {
+ if (FLAGS_quic_reloadable_flag_quic_limit_uncompressed_headers) {
EXPECT_EQ(QUIC_HEADERS_TOO_LARGE, client_->stream_error());
} else {
EXPECT_EQ(QUIC_STREAM_NO_ERROR, client_->stream_error());
@@ -1207,10 +1174,9 @@ TEST_P(EndToEndTest, LargeHeaders) {
TEST_P(EndToEndTest, EarlyResponseWithQuicStreamNoError) {
ASSERT_TRUE(Initialize());
- client_->client()->WaitForCryptoHandshakeConfirmed();
+ EXPECT_TRUE(client_->client()->WaitForCryptoHandshakeConfirmed());
- string large_body;
- GenerateBody(&large_body, 1024 * 1024);
+ string large_body(1024 * 1024, 'a');
SpdyHeaderBlock headers;
headers[":method"] = "POST";
headers[":path"] = "/foo";
@@ -1263,7 +1229,7 @@ TEST_P(EndToEndTest, NegotiateMaxOpenStreams) {
// Negotiate 1 max open stream.
client_config_.SetMaxStreamsPerConnection(1, 1);
ASSERT_TRUE(Initialize());
- client_->client()->WaitForCryptoHandshakeConfirmed();
+ EXPECT_TRUE(client_->client()->WaitForCryptoHandshakeConfirmed());
if (negotiated_version_ > QUIC_VERSION_34) {
// Newer versions use max incoming dynamic streams.
@@ -1301,7 +1267,7 @@ TEST_P(EndToEndTest, MaxIncomingDynamicStreamsLimitRespected) {
server_config_.SetMaxIncomingDynamicStreamsToSend(
kServerMaxIncomingDynamicStreams);
ASSERT_TRUE(Initialize());
- client_->client()->WaitForCryptoHandshakeConfirmed();
+ EXPECT_TRUE(client_->client()->WaitForCryptoHandshakeConfirmed());
if (negotiated_version_ <= QUIC_VERSION_34) {
// Earlier versions negotiated max open streams.
@@ -1342,7 +1308,7 @@ TEST_P(EndToEndTest, SetIndependentMaxIncomingDynamicStreamsLimits) {
server_config_.SetMaxIncomingDynamicStreamsToSend(
kServerMaxIncomingDynamicStreams);
ASSERT_TRUE(Initialize());
- client_->client()->WaitForCryptoHandshakeConfirmed();
+ EXPECT_TRUE(client_->client()->WaitForCryptoHandshakeConfirmed());
if (negotiated_version_ <= QUIC_VERSION_34) {
// Earlier versions negotiated max open streams.
@@ -1362,12 +1328,12 @@ TEST_P(EndToEndTest, SetIndependentMaxIncomingDynamicStreamsLimits) {
}
TEST_P(EndToEndTest, NegotiateCongestionControl) {
- FLAGS_quic_allow_new_bbr = true;
+ FLAGS_quic_reloadable_flag_quic_allow_new_bbr = true;
// Disable this flag because if connection uses multipath sent packet manager,
// static_cast here does not work.
- FLAGS_quic_enable_multipath = false;
+ FLAGS_quic_reloadable_flag_quic_enable_multipath = false;
ASSERT_TRUE(Initialize());
- client_->client()->WaitForCryptoHandshakeConfirmed();
+ EXPECT_TRUE(client_->client()->WaitForCryptoHandshakeConfirmed());
CongestionControlType expected_congestion_control_type = kReno;
switch (GetParam().congestion_control_tag) {
@@ -1378,18 +1344,16 @@ TEST_P(EndToEndTest, NegotiateCongestionControl) {
expected_congestion_control_type = kBBR;
break;
case kQBIC:
- expected_congestion_control_type =
- FLAGS_quic_default_enable_cubic_bytes ? kCubicBytes : kCubic;
+ expected_congestion_control_type = kCubicBytes;
break;
default:
- DLOG(FATAL) << "Unexpected congestion control tag";
+ QUIC_DLOG(FATAL) << "Unexpected congestion control tag";
}
server_thread_->Pause();
EXPECT_EQ(expected_congestion_control_type,
QuicSentPacketManagerPeer::GetSendAlgorithm(
- *static_cast<const QuicSentPacketManager*>(
- GetSentPacketManagerFromFirstServerSession()))
+ *GetSentPacketManagerFromFirstServerSession())
->GetCongestionControlType());
server_thread_->Resume();
}
@@ -1401,7 +1365,7 @@ TEST_P(EndToEndTest, LimitMaxOpenStreams) {
client_config_.SetMaxStreamsPerConnection(10, 5);
ASSERT_TRUE(Initialize());
- client_->client()->WaitForCryptoHandshakeConfirmed();
+ EXPECT_TRUE(client_->client()->WaitForCryptoHandshakeConfirmed());
if (negotiated_version_ > QUIC_VERSION_34) {
// No negotiated max streams beyond version 34.
return;
@@ -1416,7 +1380,7 @@ TEST_P(EndToEndTest, ClientSuggestsRTT) {
client_config_.SetInitialRoundTripTimeUsToSend(kInitialRTT);
ASSERT_TRUE(Initialize());
- client_->client()->WaitForCryptoHandshakeConfirmed();
+ EXPECT_TRUE(client_->client()->WaitForCryptoHandshakeConfirmed());
server_thread_->WaitForCryptoHandshakeConfirmed();
// Pause the server so we can access the server's internals without races.
@@ -1424,9 +1388,9 @@ TEST_P(EndToEndTest, ClientSuggestsRTT) {
QuicDispatcher* dispatcher =
QuicServerPeer::GetDispatcher(server_thread_->server());
ASSERT_EQ(1u, dispatcher->session_map().size());
- const QuicSentPacketManagerInterface& client_sent_packet_manager =
+ const QuicSentPacketManager& client_sent_packet_manager =
client_->client()->session()->connection()->sent_packet_manager();
- const QuicSentPacketManagerInterface* server_sent_packet_manager =
+ const QuicSentPacketManager* server_sent_packet_manager =
GetSentPacketManagerFromFirstServerSession();
EXPECT_EQ(kInitialRTT,
@@ -1443,7 +1407,7 @@ TEST_P(EndToEndTest, MaxInitialRTT) {
kMaxInitialRoundTripTimeUs);
ASSERT_TRUE(Initialize());
- client_->client()->WaitForCryptoHandshakeConfirmed();
+ EXPECT_TRUE(client_->client()->WaitForCryptoHandshakeConfirmed());
server_thread_->WaitForCryptoHandshakeConfirmed();
// Pause the server so we can access the server's internals without races.
@@ -1452,7 +1416,7 @@ TEST_P(EndToEndTest, MaxInitialRTT) {
QuicServerPeer::GetDispatcher(server_thread_->server());
ASSERT_EQ(1u, dispatcher->session_map().size());
QuicSession* session = dispatcher->session_map().begin()->second.get();
- const QuicSentPacketManagerInterface& client_sent_packet_manager =
+ const QuicSentPacketManager& client_sent_packet_manager =
client_->client()->session()->connection()->sent_packet_manager();
// Now that acks have been exchanged, the RTT estimate has decreased on the
@@ -1473,7 +1437,7 @@ TEST_P(EndToEndTest, MinInitialRTT) {
client_config_.SetInitialRoundTripTimeUsToSend(0);
ASSERT_TRUE(Initialize());
- client_->client()->WaitForCryptoHandshakeConfirmed();
+ EXPECT_TRUE(client_->client()->WaitForCryptoHandshakeConfirmed());
server_thread_->WaitForCryptoHandshakeConfirmed();
// Pause the server so we can access the server's internals without races.
@@ -1482,9 +1446,9 @@ TEST_P(EndToEndTest, MinInitialRTT) {
QuicServerPeer::GetDispatcher(server_thread_->server());
ASSERT_EQ(1u, dispatcher->session_map().size());
QuicSession* session = dispatcher->session_map().begin()->second.get();
- const QuicSentPacketManagerInterface& client_sent_packet_manager =
+ const QuicSentPacketManager& client_sent_packet_manager =
client_->client()->session()->connection()->sent_packet_manager();
- const QuicSentPacketManagerInterface& server_sent_packet_manager =
+ const QuicSentPacketManager& server_sent_packet_manager =
session->connection()->sent_packet_manager();
// Now that acks have been exchanged, the RTT estimate has decreased on the
@@ -1557,13 +1521,12 @@ TEST_P(EndToEndTest, MaxStreamsUberTest) {
SetPacketLossPercentage(1);
}
ASSERT_TRUE(Initialize());
- string large_body;
- GenerateBody(&large_body, 10240);
+ string large_body(10240, 'a');
int max_streams = 100;
AddToCache("/large_response", 200, large_body);
- client_->client()->WaitForCryptoHandshakeConfirmed();
+ EXPECT_TRUE(client_->client()->WaitForCryptoHandshakeConfirmed());
SetPacketLossPercentage(10);
for (int i = 0; i < max_streams; ++i) {
@@ -1578,12 +1541,11 @@ TEST_P(EndToEndTest, MaxStreamsUberTest) {
TEST_P(EndToEndTest, StreamCancelErrorTest) {
ASSERT_TRUE(Initialize());
- string small_body;
- GenerateBody(&small_body, 256);
+ string small_body(256, 'a');
AddToCache("/small_response", 200, small_body);
- client_->client()->WaitForCryptoHandshakeConfirmed();
+ EXPECT_TRUE(client_->client()->WaitForCryptoHandshakeConfirmed());
QuicSession* session = client_->client()->session();
// Lose the request.
@@ -1606,23 +1568,21 @@ TEST_P(EndToEndTest, StreamCancelErrorTest) {
class WrongAddressWriter : public QuicPacketWriterWrapper {
public:
- WrongAddressWriter() {
- self_address_ = IPEndPoint(IPAddress(127, 0, 0, 2), 0);
- }
+ WrongAddressWriter() { self_address_.FromString("127.0.0.2"); }
WriteResult WritePacket(const char* buffer,
size_t buf_len,
- const IPAddress& /*real_self_address*/,
- const IPEndPoint& peer_address,
+ const QuicIpAddress& /*real_self_address*/,
+ const QuicSocketAddress& peer_address,
PerPacketOptions* options) override {
// Use wrong address!
- return QuicPacketWriterWrapper::WritePacket(
- buffer, buf_len, self_address_.address(), peer_address, options);
+ return QuicPacketWriterWrapper::WritePacket(buffer, buf_len, self_address_,
+ peer_address, options);
}
bool IsWriteBlockedDataBuffered() const override { return false; }
- IPEndPoint self_address_;
+ QuicIpAddress self_address_;
};
TEST_P(EndToEndTest, ConnectionMigrationClientIPChanged) {
@@ -1632,10 +1592,11 @@ TEST_P(EndToEndTest, ConnectionMigrationClientIPChanged) {
EXPECT_EQ("200", client_->response_headers()->find(":status")->second);
// Store the client IP address which was used to send the first request.
- IPAddress old_host = client_->client()->GetLatestClientAddress().address();
+ QuicIpAddress old_host = client_->client()->GetLatestClientAddress().host();
// Migrate socket to the new IP address.
- IPAddress new_host(127, 0, 0, 2);
+ QuicIpAddress new_host;
+ new_host.FromString("127.0.0.2");
EXPECT_NE(old_host, new_host);
ASSERT_TRUE(client_->client()->MigrateSocket(new_host));
@@ -1654,7 +1615,7 @@ TEST_P(EndToEndTest, ConnectionMigrationClientPortChanged) {
EXPECT_EQ("200", client_->response_headers()->find(":status")->second);
// Store the client address which was used to send the first request.
- IPEndPoint old_address = client_->client()->GetLatestClientAddress();
+ QuicSocketAddress old_address = client_->client()->GetLatestClientAddress();
int old_fd = client_->client()->GetLatestFD();
// Create a new socket before closing the old one, which will result in a new
@@ -1676,8 +1637,8 @@ TEST_P(EndToEndTest, ConnectionMigrationClientPortChanged) {
QuicClientPeer::SetClientPort(client_->client(), new_port);
QuicConnectionPeer::SetSelfAddress(
client_->client()->session()->connection(),
- IPEndPoint(
- client_->client()->session()->connection()->self_address().address(),
+ QuicSocketAddress(
+ client_->client()->session()->connection()->self_address().host(),
new_port));
// Register the new FD for epoll events.
@@ -1690,8 +1651,8 @@ TEST_P(EndToEndTest, ConnectionMigrationClientPortChanged) {
EXPECT_EQ("200", client_->response_headers()->find(":status")->second);
// Verify that the client's ephemeral port is different.
- IPEndPoint new_address = client_->client()->GetLatestClientAddress();
- EXPECT_EQ(old_address.address(), new_address.address());
+ QuicSocketAddress new_address = client_->client()->GetLatestClientAddress();
+ EXPECT_EQ(old_address.host(), new_address.host());
EXPECT_NE(old_address.port(), new_address.port());
}
@@ -1712,7 +1673,7 @@ TEST_P(EndToEndTest, DifferentFlowControlWindows) {
ASSERT_TRUE(Initialize());
// Values are exchanged during crypto handshake, so wait for that to finish.
- client_->client()->WaitForCryptoHandshakeConfirmed();
+ EXPECT_TRUE(client_->client()->WaitForCryptoHandshakeConfirmed());
server_thread_->WaitForCryptoHandshakeConfirmed();
// Open a data stream to make sure the stream level flow control is updated.
@@ -1750,6 +1711,53 @@ TEST_P(EndToEndTest, DifferentFlowControlWindows) {
server_thread_->Resume();
}
+// Test negotiation of IFWA connection option.
+TEST_P(EndToEndTest, NegotiatedServerInitialFlowControlWindow) {
+ FLAGS_quic_reloadable_flag_quic_large_ifw_options = true;
+
+ const uint32_t kClientStreamIFCW = 123456;
+ const uint32_t kClientSessionIFCW = 234567;
+ set_client_initial_stream_flow_control_receive_window(kClientStreamIFCW);
+ set_client_initial_session_flow_control_receive_window(kClientSessionIFCW);
+
+ uint32_t kServerStreamIFCW = 32 * 1024;
+ uint32_t kServerSessionIFCW = 48 * 1024;
+ set_server_initial_stream_flow_control_receive_window(kServerStreamIFCW);
+ set_server_initial_session_flow_control_receive_window(kServerSessionIFCW);
+
+ // Bump the window.
+ const uint32_t kExpectedStreamIFCW = 1024 * 1024;
+ const uint32_t kExpectedSessionIFCW = 1.5 * 1024 * 1024;
+ client_extra_copts_.push_back(kIFWA);
+
+ ASSERT_TRUE(Initialize());
+
+ // Values are exchanged during crypto handshake, so wait for that to finish.
+ EXPECT_TRUE(client_->client()->WaitForCryptoHandshakeConfirmed());
+ server_thread_->WaitForCryptoHandshakeConfirmed();
+
+ // Open a data stream to make sure the stream level flow control is updated.
+ QuicSpdyClientStream* stream = client_->GetOrCreateStream();
+ stream->WriteOrBufferBody("hello", false, nullptr);
+
+ // Client should have the right values for server's receive window.
+ EXPECT_EQ(kExpectedStreamIFCW,
+ client_->client()
+ ->session()
+ ->config()
+ ->ReceivedInitialStreamFlowControlWindowBytes());
+ EXPECT_EQ(kExpectedSessionIFCW,
+ client_->client()
+ ->session()
+ ->config()
+ ->ReceivedInitialSessionFlowControlWindowBytes());
+ EXPECT_EQ(kExpectedStreamIFCW, QuicFlowControllerPeer::SendWindowOffset(
+ stream->flow_controller()));
+ EXPECT_EQ(kExpectedSessionIFCW,
+ QuicFlowControllerPeer::SendWindowOffset(
+ client_->client()->session()->flow_controller()));
+}
+
TEST_P(EndToEndTest, HeadersAndCryptoStreamsNoConnectionFlowControl) {
// The special headers and crypto streams should be subject to per-stream flow
// control limits, but should not be subject to connection level flow control
@@ -1765,7 +1773,7 @@ TEST_P(EndToEndTest, HeadersAndCryptoStreamsNoConnectionFlowControl) {
// Wait for crypto handshake to finish. This should have contributed to the
// crypto stream flow control window, but not affected the session flow
// control window.
- client_->client()->WaitForCryptoHandshakeConfirmed();
+ EXPECT_TRUE(client_->client()->WaitForCryptoHandshakeConfirmed());
server_thread_->WaitForCryptoHandshakeConfirmed();
QuicCryptoStream* crypto_stream =
@@ -1808,7 +1816,7 @@ TEST_P(EndToEndTest, FlowControlsSynced) {
ASSERT_TRUE(Initialize());
- client_->client()->WaitForCryptoHandshakeConfirmed();
+ EXPECT_TRUE(client_->client()->WaitForCryptoHandshakeConfirmed());
server_thread_->WaitForCryptoHandshakeConfirmed();
server_thread_->Pause();
@@ -1817,23 +1825,71 @@ TEST_P(EndToEndTest, FlowControlsSynced) {
QuicServerPeer::GetDispatcher(server_thread_->server());
auto server_session = static_cast<QuicSpdySession*>(
dispatcher->session_map().begin()->second.get());
-
ExpectFlowControlsSynced(client_session->flow_controller(),
server_session->flow_controller());
ExpectFlowControlsSynced(
QuicSessionPeer::GetCryptoStream(client_session)->flow_controller(),
QuicSessionPeer::GetCryptoStream(server_session)->flow_controller());
- ExpectFlowControlsSynced(
- QuicSpdySessionPeer::GetHeadersStream(client_session)->flow_controller(),
- QuicSpdySessionPeer::GetHeadersStream(server_session)->flow_controller());
+ SpdyFramer spdy_framer(SpdyFramer::ENABLE_COMPRESSION);
+ SpdySettingsIR settings_frame;
+ settings_frame.AddSetting(SETTINGS_MAX_HEADER_LIST_SIZE,
+ kDefaultMaxUncompressedHeaderSize);
+ SpdySerializedFrame frame(spdy_framer.SerializeFrame(settings_frame));
+ QuicFlowController* client_header_stream_flow_controller =
+ QuicSpdySessionPeer::GetHeadersStream(client_session)->flow_controller();
+ QuicFlowController* server_header_stream_flow_controller =
+ QuicSpdySessionPeer::GetHeadersStream(server_session)->flow_controller();
+ if (FLAGS_quic_reloadable_flag_quic_send_max_header_list_size) {
+ // Both client and server are sending this SETTINGS frame, and the send
+ // window is consumed. But because of timing issue, the server may send or
+ // not send the frame, and the client may send/ not send / receive / not
+ // receive the frame.
+ // TODO(fayang): Rewrite this part because it is hacky.
+ QuicByteCount win_difference1 = QuicFlowControllerPeer::ReceiveWindowSize(
+ server_header_stream_flow_controller) -
+ QuicFlowControllerPeer::SendWindowSize(
+ client_header_stream_flow_controller);
+ QuicByteCount win_difference2 = QuicFlowControllerPeer::ReceiveWindowSize(
+ client_header_stream_flow_controller) -
+ QuicFlowControllerPeer::SendWindowSize(
+ server_header_stream_flow_controller);
+ EXPECT_TRUE(win_difference1 == 0 || win_difference1 == frame.size());
+ EXPECT_TRUE(win_difference2 == 0 || win_difference2 == frame.size());
+ } else {
+ ExpectFlowControlsSynced(
+ QuicSpdySessionPeer::GetHeadersStream(client_session)
+ ->flow_controller(),
+ QuicSpdySessionPeer::GetHeadersStream(server_session)
+ ->flow_controller());
+ }
if (!client_session->force_hol_blocking()) {
- EXPECT_EQ(static_cast<float>(QuicFlowControllerPeer::ReceiveWindowSize(
- client_session->flow_controller())) /
- QuicFlowControllerPeer::ReceiveWindowSize(
- QuicSpdySessionPeer::GetHeadersStream(client_session)
- ->flow_controller()),
- kSessionToStreamRatio);
+ if (FLAGS_quic_reloadable_flag_quic_send_max_header_list_size) {
+ // Client *may* have received the SETTINGs frame.
+ // TODO(fayang): Rewrite this part because it is hacky.
+ float ratio1 =
+ static_cast<float>(QuicFlowControllerPeer::ReceiveWindowSize(
+ client_session->flow_controller())) /
+ QuicFlowControllerPeer::ReceiveWindowSize(
+ QuicSpdySessionPeer::GetHeadersStream(client_session)
+ ->flow_controller());
+ float ratio2 =
+ static_cast<float>(QuicFlowControllerPeer::ReceiveWindowSize(
+ client_session->flow_controller())) /
+ (QuicFlowControllerPeer::ReceiveWindowSize(
+ QuicSpdySessionPeer::GetHeadersStream(client_session)
+ ->flow_controller()) +
+ frame.size());
+ EXPECT_TRUE(ratio1 == kSessionToStreamRatio ||
+ ratio2 == kSessionToStreamRatio);
+ } else {
+ EXPECT_EQ(static_cast<float>(QuicFlowControllerPeer::ReceiveWindowSize(
+ client_session->flow_controller())) /
+ QuicFlowControllerPeer::ReceiveWindowSize(
+ QuicSpdySessionPeer::GetHeadersStream(client_session)
+ ->flow_controller()),
+ kSessionToStreamRatio);
+ }
}
server_thread_->Resume();
@@ -1889,9 +1945,9 @@ class TestResponseListener : public QuicClient::ResponseListener {
void OnCompleteResponse(QuicStreamId id,
const SpdyHeaderBlock& response_headers,
const string& response_body) override {
- string debug_string = response_headers.DebugString();
- DVLOG(1) << "response for stream " << id << " " << debug_string << "\n"
- << response_body;
+ QUIC_DVLOG(1) << "response for stream " << id << " "
+ << response_headers.DebugString() << "\n"
+ << response_body;
}
};
@@ -1908,7 +1964,7 @@ TEST_P(EndToEndTest, AckNotifierWithPacketLossAndBlockedSocket) {
ASSERT_TRUE(Initialize());
// Wait for the server SHLO before upping the packet loss.
- client_->client()->WaitForCryptoHandshakeConfirmed();
+ EXPECT_TRUE(client_->client()->WaitForCryptoHandshakeConfirmed());
SetPacketLossPercentage(30);
client_writer_->set_fake_blocked_socket_percentage(10);
@@ -1922,7 +1978,8 @@ TEST_P(EndToEndTest, AckNotifierWithPacketLossAndBlockedSocket) {
client_->SendMessage(headers, "", /*fin=*/false);
// The TestAckListener will cause a failure if not notified.
- scoped_refptr<TestAckListener> delegate(new TestAckListener(2));
+ QuicReferenceCountedPointer<TestAckListener> ack_listener(
+ new TestAckListener(2));
// Test the AckNotifier's ability to track multiple packets by making the
// request body exceed the size of a single packet.
@@ -1930,7 +1987,7 @@ TEST_P(EndToEndTest, AckNotifierWithPacketLossAndBlockedSocket) {
"a request body bigger than one packet" + string(kMaxPacketSize, '.');
// Send the request, and register the delegate for ACKs.
- client_->SendData(request_string, true, delegate.get());
+ client_->SendData(request_string, true, ack_listener);
client_->WaitForResponse();
EXPECT_EQ(kFooResponseBody, client_->response_body());
EXPECT_EQ("200", client_->response_headers()->find(":status")->second);
@@ -1939,7 +1996,7 @@ TEST_P(EndToEndTest, AckNotifierWithPacketLossAndBlockedSocket) {
client_->SendSynchronousRequest("/bar");
// Make sure the delegate does get the notification it expects.
- while (!delegate->has_been_notified()) {
+ while (!ack_listener->has_been_notified()) {
// Waits for up to 50 ms.
client_->client()->WaitForEvents();
}
@@ -1965,7 +2022,7 @@ TEST_P(EndToEndTest, ServerSendPublicReset) {
// race conditions.
server_thread_->Pause();
server_writer_->WritePacket(
- packet->data(), packet->length(), server_address_.address(),
+ packet->data(), packet->length(), server_address_.host(),
client_->client()->GetLatestClientAddress(), nullptr);
server_thread_->Resume();
@@ -1980,7 +2037,7 @@ TEST_P(EndToEndTest, ServerSendPublicReset) {
TEST_P(EndToEndTest, ServerSendPublicResetWithDifferentConnectionId) {
ASSERT_TRUE(Initialize());
- client_->client()->WaitForCryptoHandshakeConfirmed();
+ EXPECT_TRUE(client_->client()->WaitForCryptoHandshakeConfirmed());
// Send the public reset.
QuicConnectionId incorrect_connection_id =
@@ -2002,7 +2059,7 @@ TEST_P(EndToEndTest, ServerSendPublicResetWithDifferentConnectionId) {
// race conditions.
server_thread_->Pause();
server_writer_->WritePacket(
- packet->data(), packet->length(), server_address_.address(),
+ packet->data(), packet->length(), server_address_.host(),
client_->client()->GetLatestClientAddress(), nullptr);
server_thread_->Resume();
@@ -2032,7 +2089,7 @@ TEST_P(EndToEndTest, ClientSendPublicResetWithDifferentConnectionId) {
framer.BuildPublicResetPacket(header));
client_writer_->WritePacket(
packet->data(), packet->length(),
- client_->client()->GetLatestClientAddress().address(), server_address_,
+ client_->client()->GetLatestClientAddress().host(), server_address_,
nullptr);
// The connection should be unaffected.
@@ -2045,7 +2102,7 @@ TEST_P(EndToEndTest, ClientSendPublicResetWithDifferentConnectionId) {
TEST_P(EndToEndTest, ServerSendVersionNegotiationWithDifferentConnectionId) {
ASSERT_TRUE(Initialize());
- client_->client()->WaitForCryptoHandshakeConfirmed();
+ EXPECT_TRUE(client_->client()->WaitForCryptoHandshakeConfirmed());
// Send the version negotiation packet.
QuicConnectionId incorrect_connection_id =
@@ -2061,7 +2118,7 @@ TEST_P(EndToEndTest, ServerSendVersionNegotiationWithDifferentConnectionId) {
// race conditions.
server_thread_->Pause();
server_writer_->WritePacket(
- packet->data(), packet->length(), server_address_.address(),
+ packet->data(), packet->length(), server_address_.host(),
client_->client()->GetLatestClientAddress(), nullptr);
server_thread_->Resume();
@@ -2088,7 +2145,7 @@ TEST_P(EndToEndTest, BadPacketHeaderTruncated) {
0x11};
client_writer_->WritePacket(
&packet[0], sizeof(packet),
- client_->client()->GetLatestClientAddress().address(), server_address_,
+ client_->client()->GetLatestClientAddress().host(), server_address_,
nullptr);
// Give the server time to process the packet.
base::PlatformThread::Sleep(base::TimeDelta::FromMilliseconds(100));
@@ -2127,7 +2184,7 @@ TEST_P(EndToEndTest, BadPacketHeaderFlags) {
};
client_writer_->WritePacket(
&packet[0], sizeof(packet),
- client_->client()->GetLatestClientAddress().address(), server_address_,
+ client_->client()->GetLatestClientAddress().host(), server_address_,
nullptr);
// Give the server time to process the packet.
base::PlatformThread::Sleep(base::TimeDelta::FromMilliseconds(100));
@@ -2160,10 +2217,10 @@ TEST_P(EndToEndTest, BadEncryptedData) {
// Damage the encrypted data.
string damaged_packet(packet->data(), packet->length());
damaged_packet[30] ^= 0x01;
- DVLOG(1) << "Sending bad packet.";
+ QUIC_DLOG(INFO) << "Sending bad packet.";
client_writer_->WritePacket(
damaged_packet.data(), damaged_packet.length(),
- client_->client()->GetLatestClientAddress().address(), server_address_,
+ client_->client()->GetLatestClientAddress().host(), server_address_,
nullptr);
// Give the server time to process the packet.
base::PlatformThread::Sleep(base::TimeDelta::FromMilliseconds(100));
@@ -2187,18 +2244,20 @@ class ServerStreamWithErrorResponseBody : public QuicSimpleServerStream {
public:
ServerStreamWithErrorResponseBody(QuicStreamId id,
QuicSpdySession* session,
+ QuicHttpResponseCache* response_cache,
string response_body)
- : QuicSimpleServerStream(id, session),
+ : QuicSimpleServerStream(id, session, response_cache),
response_body_(std::move(response_body)) {}
~ServerStreamWithErrorResponseBody() override {}
protected:
void SendErrorResponse() override {
- DVLOG(1) << "Sending error response for stream " << id();
+ QUIC_DLOG(INFO) << "Sending error response for stream " << id();
SpdyHeaderBlock headers;
headers[":status"] = "500";
- headers["content-length"] = base::UintToString(response_body_.size());
+ headers["content-length"] =
+ QuicTextUtils::Uint64ToString(response_body_.size());
// This method must call CloseReadSide to cause the test case, StopReading
// is not sufficient.
QuicStreamPeer::CloseReadSide(this);
@@ -2215,9 +2274,12 @@ class StreamWithErrorFactory : public QuicTestServer::StreamFactory {
~StreamWithErrorFactory() override {}
- QuicSimpleServerStream* CreateStream(QuicStreamId id,
- QuicSpdySession* session) override {
- return new ServerStreamWithErrorResponseBody(id, session, response_body_);
+ QuicSimpleServerStream* CreateStream(
+ QuicStreamId id,
+ QuicSpdySession* session,
+ QuicHttpResponseCache* response_cache) override {
+ return new ServerStreamWithErrorResponseBody(id, session, response_cache,
+ response_body_);
}
private:
@@ -2227,8 +2289,10 @@ class StreamWithErrorFactory : public QuicTestServer::StreamFactory {
// A test server stream that drops all received body.
class ServerStreamThatDropsBody : public QuicSimpleServerStream {
public:
- ServerStreamThatDropsBody(QuicStreamId id, QuicSpdySession* session)
- : QuicSimpleServerStream(id, session) {}
+ ServerStreamThatDropsBody(QuicStreamId id,
+ QuicSpdySession* session,
+ QuicHttpResponseCache* response_cache)
+ : QuicSimpleServerStream(id, session, response_cache) {}
~ServerStreamThatDropsBody() override {}
@@ -2240,7 +2304,8 @@ class ServerStreamThatDropsBody : public QuicSimpleServerStream {
// No more data to read.
break;
}
- DVLOG(1) << "Processed " << iov.iov_len << " bytes for stream " << id();
+ QUIC_DVLOG(1) << "Processed " << iov.iov_len << " bytes for stream "
+ << id();
MarkConsumed(iov.iov_len);
}
@@ -2267,9 +2332,11 @@ class ServerStreamThatDropsBodyFactory : public QuicTestServer::StreamFactory {
~ServerStreamThatDropsBodyFactory() override{};
- QuicSimpleServerStream* CreateStream(QuicStreamId id,
- QuicSpdySession* session) override {
- return new ServerStreamThatDropsBody(id, session);
+ QuicSimpleServerStream* CreateStream(
+ QuicStreamId id,
+ QuicSpdySession* session,
+ QuicHttpResponseCache* response_cache) override {
+ return new ServerStreamThatDropsBody(id, session, response_cache);
}
};
@@ -2278,16 +2345,17 @@ class ServerStreamThatSendsHugeResponse : public QuicSimpleServerStream {
public:
ServerStreamThatSendsHugeResponse(QuicStreamId id,
QuicSpdySession* session,
+ QuicHttpResponseCache* response_cache,
int64_t body_bytes)
- : QuicSimpleServerStream(id, session), body_bytes_(body_bytes) {}
+ : QuicSimpleServerStream(id, session, response_cache),
+ body_bytes_(body_bytes) {}
~ServerStreamThatSendsHugeResponse() override {}
protected:
void SendResponse() override {
- QuicInMemoryCache::Response response;
- string body;
- GenerateBody(&body, body_bytes_);
+ QuicHttpResponseCache::Response response;
+ string body(body_bytes_, 'a');
response.set_body(body);
SendHeadersAndBodyAndTrailers(response.headers().Clone(), response.body(),
response.trailers().Clone());
@@ -2307,9 +2375,12 @@ class ServerStreamThatSendsHugeResponseFactory
~ServerStreamThatSendsHugeResponseFactory() override{};
- QuicSimpleServerStream* CreateStream(QuicStreamId id,
- QuicSpdySession* session) override {
- return new ServerStreamThatSendsHugeResponse(id, session, body_bytes_);
+ QuicSimpleServerStream* CreateStream(
+ QuicStreamId id,
+ QuicSpdySession* session,
+ QuicHttpResponseCache* response_cache) override {
+ return new ServerStreamThatSendsHugeResponse(id, session, response_cache,
+ body_bytes_);
}
int64_t body_bytes_;
@@ -2354,14 +2425,14 @@ class ClientSessionThatDropsBody : public QuicClientSession {
~ClientSessionThatDropsBody() override {}
std::unique_ptr<QuicSpdyClientStream> CreateClientStream() override {
- return base::MakeUnique<ClientStreamThatDropsBody>(
- GetNextOutgoingStreamId(), this);
+ return QuicMakeUnique<ClientStreamThatDropsBody>(GetNextOutgoingStreamId(),
+ this);
}
};
class MockableQuicClientThatDropsBody : public MockableQuicClient {
public:
- MockableQuicClientThatDropsBody(IPEndPoint server_address,
+ MockableQuicClientThatDropsBody(QuicSocketAddress server_address,
const QuicServerId& server_id,
const QuicConfig& config,
const QuicVersionVector& supported_versions,
@@ -2385,7 +2456,7 @@ class MockableQuicClientThatDropsBody : public MockableQuicClient {
class QuicTestClientThatDropsBody : public QuicTestClient {
public:
- QuicTestClientThatDropsBody(IPEndPoint server_address,
+ QuicTestClientThatDropsBody(QuicSocketAddress server_address,
const string& server_hostname,
const QuicConfig& config,
const QuicVersionVector& supported_versions)
@@ -2412,20 +2483,19 @@ TEST_P(EndToEndTest, EarlyResponseFinRecording) {
// receive the FIN of the request
// send the FIN of the response
- string response_body;
// The response body must be larger than the flow control window so the server
// must receive a window update from the client before it can finish sending
// it.
uint32_t response_body_size =
2 * client_config_.GetInitialStreamFlowControlWindowToSend();
- GenerateBody(&response_body, response_body_size);
+ string response_body(response_body_size, 'a');
StreamWithErrorFactory stream_factory(response_body);
SetSpdyStreamFactory(&stream_factory);
ASSERT_TRUE(Initialize());
- client_->client()->WaitForCryptoHandshakeConfirmed();
+ EXPECT_TRUE(client_->client()->WaitForCryptoHandshakeConfirmed());
// A POST that gets an early error response, after the headers are received
// and before the body is received, due to invalid content-length.
@@ -2444,8 +2514,7 @@ TEST_P(EndToEndTest, EarlyResponseFinRecording) {
// before the request FIN is processed but receive the request FIN before the
// response is sent completely.
const uint32_t kRequestBodySize = kMaxPacketSize + 10;
- string request_body;
- GenerateBody(&request_body, kRequestBodySize);
+ string request_body(kRequestBodySize, 'a');
// Send the request.
client_->SendMessage(headers, request_body);
@@ -2480,7 +2549,7 @@ TEST_P(EndToEndTest, LargePostEarlyResponse) {
ASSERT_TRUE(Initialize());
- client_->client()->WaitForCryptoHandshakeConfirmed();
+ EXPECT_TRUE(client_->client()->WaitForCryptoHandshakeConfirmed());
// POST to a URL that gets an early error response, after the headers are
// received and before the body is received.
@@ -2510,7 +2579,7 @@ TEST_P(EndToEndTest, LargePostEarlyResponse) {
TEST_P(EndToEndTest, Trailers) {
// Test sending and receiving HTTP/2 Trailers (trailing HEADERS frames).
ASSERT_TRUE(Initialize());
- client_->client()->WaitForCryptoHandshakeConfirmed();
+ EXPECT_TRUE(client_->client()->WaitForCryptoHandshakeConfirmed());
// Set reordering to ensure that Trailers arriving before body is ok.
SetPacketSendDelay(QuicTime::Delta::FromMilliseconds(2));
@@ -2522,14 +2591,13 @@ TEST_P(EndToEndTest, Trailers) {
SpdyHeaderBlock headers;
headers[":status"] = "200";
headers[":version"] = "HTTP/1.1";
- headers["content-length"] = IntToString(kBody.size());
+ headers["content-length"] = QuicTextUtils::Uint64ToString(kBody.size());
SpdyHeaderBlock trailers;
trailers["some-trailing-header"] = "trailing-header-value";
- QuicInMemoryCache::GetInstance()->AddResponse(
- server_hostname_, "/trailer_url", std::move(headers), kBody,
- trailers.Clone());
+ response_cache_.AddResponse(server_hostname_, "/trailer_url",
+ std::move(headers), kBody, trailers.Clone());
EXPECT_EQ(kBody, client_->SendSynchronousRequest("/trailer_url"));
EXPECT_EQ("200", client_->response_headers()->find(":status")->second);
@@ -2564,24 +2632,26 @@ class EndToEndTestServerPush : public EndToEndTest {
if (use_large_response) {
// Generate a response common body larger than flow control window for
// push response.
- GenerateBody(&large_resource, resource_size);
+ large_resource = string(resource_size, 'a');
}
- std::list<QuicInMemoryCache::ServerPushInfo> push_resources;
+ std::list<QuicHttpResponseCache::ServerPushInfo> push_resources;
for (size_t i = 0; i < num_resources; ++i) {
string url = push_urls[i];
GURL resource_url(url);
- string body = use_large_response
- ? large_resource
- : "This is server push response body for " + url;
+ string body =
+ use_large_response
+ ? large_resource
+ : QuicStrCat("This is server push response body for ", url);
SpdyHeaderBlock response_headers;
response_headers[":version"] = "HTTP/1.1";
response_headers[":status"] = "200";
- response_headers["content-length"] = IntToString(body.size());
- push_resources.push_back(QuicInMemoryCache::ServerPushInfo(
+ response_headers["content-length"] =
+ QuicTextUtils::Uint64ToString(body.size());
+ push_resources.push_back(QuicHttpResponseCache::ServerPushInfo(
resource_url, std::move(response_headers), kV3LowestPriority, body));
}
- QuicInMemoryCache::GetInstance()->AddSimpleResponseWithServerPushResources(
+ response_cache_.AddSimpleResponseWithServerPushResources(
host, path, 200, response_body, push_resources);
}
};
@@ -2593,7 +2663,7 @@ INSTANTIATE_TEST_CASE_P(EndToEndTestsServerPush,
TEST_P(EndToEndTestServerPush, ServerPush) {
ASSERT_TRUE(Initialize());
- client_->client()->WaitForCryptoHandshakeConfirmed();
+ EXPECT_TRUE(client_->client()->WaitForCryptoHandshakeConfirmed());
// Set reordering to ensure that body arriving before PUSH_PROMISE is ok.
SetPacketSendDelay(QuicTime::Delta::FromMilliseconds(2));
@@ -2613,7 +2683,7 @@ TEST_P(EndToEndTestServerPush, ServerPush) {
std::unique_ptr<QuicClientBase::ResponseListener>(
new TestResponseListener));
- DVLOG(1) << "send request for /push_example";
+ QUIC_DVLOG(1) << "send request for /push_example";
EXPECT_EQ(kBody, client_->SendSynchronousRequest(
"https://example.com/push_example"));
QuicHeadersStream* headers_stream =
@@ -2624,14 +2694,17 @@ TEST_P(EndToEndTestServerPush, ServerPush) {
EXPECT_TRUE(QuicStreamSequencerPeer::IsUnderlyingBufferAllocated(sequencer));
for (const string& url : push_urls) {
- DVLOG(1) << "send request for pushed stream on url " << url;
- string expected_body = "This is server push response body for " + url;
+ QUIC_DVLOG(1) << "send request for pushed stream on url " << url;
+ string expected_body =
+ QuicStrCat("This is server push response body for ", url);
string response_body = client_->SendSynchronousRequest(url);
- DVLOG(1) << "response body " << response_body;
+ QUIC_DVLOG(1) << "response body " << response_body;
EXPECT_EQ(expected_body, response_body);
}
- EXPECT_NE(FLAGS_quic_headers_stream_release_sequencer_buffer,
- QuicStreamSequencerPeer::IsUnderlyingBufferAllocated(sequencer));
+ EXPECT_NE(
+ FLAGS_quic_reloadable_flag_quic_headers_stream_release_sequencer_buffer &&
+ FLAGS_quic_reloadable_flag_quic_reduce_sequencer_buffer_memory_life_time, // NOLINT
+ QuicStreamSequencerPeer::IsUnderlyingBufferAllocated(sequencer));
}
TEST_P(EndToEndTestServerPush, ServerPushUnderLimit) {
@@ -2640,7 +2713,7 @@ TEST_P(EndToEndTestServerPush, ServerPushUnderLimit) {
// them with requests later.
ASSERT_TRUE(Initialize());
- client_->client()->WaitForCryptoHandshakeConfirmed();
+ EXPECT_TRUE(client_->client()->WaitForCryptoHandshakeConfirmed());
// Set reordering to ensure that body arriving before PUSH_PROMISE is ok.
SetPacketSendDelay(QuicTime::Delta::FromMilliseconds(2));
@@ -2669,10 +2742,11 @@ TEST_P(EndToEndTestServerPush, ServerPushUnderLimit) {
for (const string& url : push_urls) {
// Sending subsequent requesets will not actually send anything on the wire,
// as the responses are already in the client's cache.
- DVLOG(1) << "send request for pushed stream on url " << url;
- string expected_body = "This is server push response body for " + url;
+ QUIC_DVLOG(1) << "send request for pushed stream on url " << url;
+ string expected_body =
+ QuicStrCat("This is server push response body for ", url);
string response_body = client_->SendSynchronousRequest(url);
- DVLOG(1) << "response body " << response_body;
+ QUIC_DVLOG(1) << "response body " << response_body;
EXPECT_EQ(expected_body, response_body);
}
// Expect only original request has been sent and push responses have been
@@ -2687,7 +2761,7 @@ TEST_P(EndToEndTestServerPush, ServerPushOverLimitNonBlocking) {
// streams should still work because all response streams get closed
// immediately after pushing resources.
ASSERT_TRUE(Initialize());
- client_->client()->WaitForCryptoHandshakeConfirmed();
+ EXPECT_TRUE(client_->client()->WaitForCryptoHandshakeConfirmed());
// Set reordering to ensure that body arriving before PUSH_PROMISE is ok.
SetPacketSendDelay(QuicTime::Delta::FromMilliseconds(2));
@@ -2700,7 +2774,7 @@ TEST_P(EndToEndTestServerPush, ServerPushOverLimitNonBlocking) {
const size_t kNumResources = 1 + kNumMaxStreams; // 11.
string push_urls[11];
for (size_t i = 0; i < kNumResources; ++i) {
- push_urls[i] = "https://example.com/push_resources" + base::UintToString(i);
+ push_urls[i] = QuicStrCat("https://example.com/push_resources", i);
}
AddRequestAndResponseWithServerPush("example.com", "/push_example", kBody,
push_urls, kNumResources, 0);
@@ -2717,7 +2791,7 @@ TEST_P(EndToEndTestServerPush, ServerPushOverLimitNonBlocking) {
for (const string& url : push_urls) {
// Sending subsequent requesets will not actually send anything on the wire,
// as the responses are already in the client's cache.
- EXPECT_EQ("This is server push response body for " + url,
+ EXPECT_EQ(QuicStrCat("This is server push response body for ", url),
client_->SendSynchronousRequest(url));
}
@@ -2745,7 +2819,7 @@ TEST_P(EndToEndTestServerPush, ServerPushOverLimitWithBlocking) {
kBodySize * kNumMaxStreams + 1024);
ASSERT_TRUE(Initialize());
- client_->client()->WaitForCryptoHandshakeConfirmed();
+ EXPECT_TRUE(client_->client()->WaitForCryptoHandshakeConfirmed());
// Set reordering to ensure that body arriving before PUSH_PROMISE is ok.
SetPacketSendDelay(QuicTime::Delta::FromMilliseconds(2));
@@ -2757,7 +2831,7 @@ TEST_P(EndToEndTestServerPush, ServerPushOverLimitWithBlocking) {
const size_t kNumResources = kNumMaxStreams + 1;
string push_urls[11];
for (size_t i = 0; i < kNumResources; ++i) {
- push_urls[i] = "http://example.com/push_resources" + base::UintToString(i);
+ push_urls[i] = QuicStrCat("http://example.com/push_resources", i);
}
AddRequestAndResponseWithServerPush("example.com", "/push_example", kBody,
push_urls, kNumResources, kBodySize);
@@ -2811,9 +2885,9 @@ TEST_P(EndToEndTestServerPush, ServerPushOverLimitWithBlocking) {
}
// TODO(ckrasic) - remove this when deprecating
-// FLAGS_quic_enable_server_push_by_default.
+// FLAGS_quic_reloadable_flag_quic_enable_server_push_by_default.
TEST_P(EndToEndTestServerPush, DisabledWithoutConnectionOption) {
- FLAGS_quic_enable_server_push_by_default = false;
+ FLAGS_quic_reloadable_flag_quic_enable_server_push_by_default = false;
// Tests that server push won't be triggered when kSPSH is not set by client.
support_server_push_ = false;
ASSERT_TRUE(Initialize());
@@ -2837,7 +2911,8 @@ TEST_P(EndToEndTestServerPush, DisabledWithoutConnectionOption) {
for (const string& url : push_urls) {
// Sending subsequent requests will trigger sending real requests because
// client doesn't support server push.
- const string expected_body = "This is server push response body for " + url;
+ const string expected_body =
+ QuicStrCat("This is server push response body for ", url);
const string response_body = client_->SendSynchronousRequest(url);
EXPECT_EQ(expected_body, response_body);
}
@@ -2858,7 +2933,7 @@ TEST_P(EndToEndTest, DISABLED_TestHugePostWithPacketLoss) {
// within a short time.
client_->epoll_server()->set_timeout_in_us(0);
- client_->client()->WaitForCryptoHandshakeConfirmed();
+ EXPECT_TRUE(client_->client()->WaitForCryptoHandshakeConfirmed());
SetPacketLossPercentage(1);
// To avoid storing the whole request body in memory, use a loop to repeatedly
// send body size of kSizeBytes until the whole request body size is reached.
@@ -2866,15 +2941,15 @@ TEST_P(EndToEndTest, DISABLED_TestHugePostWithPacketLoss) {
// Request body size is 4G plus one more kSizeBytes.
int64_t request_body_size_bytes = pow(2, 32) + kSizeBytes;
ASSERT_LT(INT64_C(4294967296), request_body_size_bytes);
- string body;
- GenerateBody(&body, kSizeBytes);
+ string body(kSizeBytes, 'a');
SpdyHeaderBlock headers;
headers[":method"] = "POST";
headers[":path"] = "/foo";
headers[":scheme"] = "https";
headers[":authority"] = server_hostname_;
- headers["content-length"] = IntToString(request_body_size_bytes);
+ headers["content-length"] =
+ QuicTextUtils::Uint64ToString(request_body_size_bytes);
client_->SendMessage(headers, "", /*fin=*/false);
@@ -2907,7 +2982,7 @@ TEST_P(EndToEndTest, DISABLED_TestHugeResponseWithPacketLoss) {
client->UseWriter(client_writer_);
client->Connect();
client_.reset(client);
- static EpollEvent event(EPOLLOUT, false);
+ static EpollEvent event(EPOLLOUT);
client_writer_->Initialize(
QuicConnectionPeer::GetHelper(client_->client()->session()->connection()),
QuicConnectionPeer::GetAlarmFactory(
@@ -2916,7 +2991,7 @@ TEST_P(EndToEndTest, DISABLED_TestHugeResponseWithPacketLoss) {
initialized_ = true;
ASSERT_TRUE(client_->client()->connected());
- client_->client()->WaitForCryptoHandshakeConfirmed();
+ EXPECT_TRUE(client_->client()->WaitForCryptoHandshakeConfirmed());
SetPacketLossPercentage(1);
client_->SendRequest("/huge_response");
client_->WaitForResponse();
@@ -2934,14 +3009,16 @@ TEST_P(EndToEndTest, ReleaseHeadersStreamBufferWhenIdle) {
QuicHeadersStream* headers_stream =
QuicSpdySessionPeer::GetHeadersStream(client_->client()->session());
QuicStreamSequencer* sequencer = QuicStreamPeer::sequencer(headers_stream);
- EXPECT_NE(FLAGS_quic_headers_stream_release_sequencer_buffer,
- QuicStreamSequencerPeer::IsUnderlyingBufferAllocated(sequencer));
+ EXPECT_NE(
+ FLAGS_quic_reloadable_flag_quic_headers_stream_release_sequencer_buffer &&
+ FLAGS_quic_reloadable_flag_quic_reduce_sequencer_buffer_memory_life_time, // NOLINT
+ QuicStreamSequencerPeer::IsUnderlyingBufferAllocated(sequencer));
}
class EndToEndBufferedPacketsTest : public EndToEndTest {
public:
void CreateClientWithWriter() override {
- LOG(ERROR) << "create client with reorder_writer_ ";
+ QUIC_LOG(ERROR) << "create client with reorder_writer_ ";
reorder_writer_ = new PacketReorderingWriter();
client_.reset(EndToEndTest::CreateQuicClient(reorder_writer_));
}
@@ -2961,11 +3038,6 @@ INSTANTIATE_TEST_CASE_P(EndToEndBufferedPacketsTests,
TEST_P(EndToEndBufferedPacketsTest, Buffer0RttRequest) {
ASSERT_TRUE(Initialize());
- if (negotiated_version_ <= QUIC_VERSION_32) {
- // Since no 0-rtt for v32 and under, and this test relies on 0-rtt, skip
- // this test if QUIC doesn't do 0-rtt.
- return;
- }
// Finish one request to make sure handshake established.
client_->SendSynchronousRequest("/foo");
// Disconnect for next 0-rtt request.
diff --git a/chromium/net/tools/quic/quic_epoll_clock.cc b/chromium/net/tools/quic/platform/impl/quic_epoll_clock.cc
index 357bc500c63..ce484dcede5 100644
--- a/chromium/net/tools/quic/quic_epoll_clock.cc
+++ b/chromium/net/tools/quic/platform/impl/quic_epoll_clock.cc
@@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#include "net/tools/quic/quic_epoll_clock.h"
+#include "net/tools/quic/platform/impl/quic_epoll_clock.h"
#include "net/tools/epoll_server/epoll_server.h"
diff --git a/chromium/net/tools/quic/quic_epoll_clock.h b/chromium/net/tools/quic/platform/impl/quic_epoll_clock.h
index 509d3bf7e4d..8c125bcacdc 100644
--- a/chromium/net/tools/quic/quic_epoll_clock.h
+++ b/chromium/net/tools/quic/platform/impl/quic_epoll_clock.h
@@ -2,19 +2,18 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#ifndef NET_TOOLS_QUIC_QUIC_EPOLL_CLOCK_H_
-#define NET_TOOLS_QUIC_QUIC_EPOLL_CLOCK_H_
+#ifndef NET_TOOLS_QUIC_PLATFORM_IMPL_QUIC_EPOLL_CLOCK_H_
+#define NET_TOOLS_QUIC_PLATFORM_IMPL_QUIC_EPOLL_CLOCK_H_
#include "base/compiler_specific.h"
#include "base/macros.h"
-#include "net/quic/core/quic_clock.h"
#include "net/quic/core/quic_time.h"
+#include "net/quic/platform/api/quic_clock.h"
namespace net {
class EpollServer;
-
// Clock to efficiently retrieve an approximately accurate time from an
// EpollServer.
class QuicEpollClock : public QuicClock {
@@ -47,4 +46,4 @@ class QuicEpollClock : public QuicClock {
} // namespace net
-#endif // NET_TOOLS_QUIC_QUIC_EPOLL_CLOCK_H_
+#endif // NET_TOOLS_QUIC_PLATFORM_IMPL_QUIC_EPOLL_CLOCK_H_
diff --git a/chromium/net/tools/quic/quic_epoll_clock_test.cc b/chromium/net/tools/quic/platform/impl/quic_epoll_clock_test.cc
index 03d26b82106..0805429d5c3 100644
--- a/chromium/net/tools/quic/quic_epoll_clock_test.cc
+++ b/chromium/net/tools/quic/platform/impl/quic_epoll_clock_test.cc
@@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#include "net/tools/quic/quic_epoll_clock.h"
+#include "net/tools/quic/platform/impl/quic_epoll_clock.h"
#include "net/tools/quic/test_tools/mock_epoll_server.h"
#include "testing/gmock/include/gmock/gmock.h"
diff --git a/chromium/net/tools/quic/quic_socket_utils.cc b/chromium/net/tools/quic/platform/impl/quic_socket_utils.cc
index a6bc4c0c496..bb1fcbd7aad 100644
--- a/chromium/net/tools/quic/quic_socket_utils.cc
+++ b/chromium/net/tools/quic/platform/impl/quic_socket_utils.cc
@@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#include "net/tools/quic/quic_socket_utils.h"
+#include "net/tools/quic/platform/impl/quic_socket_utils.h"
#include <errno.h>
#include <linux/net_tstamp.h>
@@ -12,37 +12,40 @@
#include <sys/uio.h>
#include <string>
-#include "base/logging.h"
-#include "net/quic/core/quic_bug_tracker.h"
#include "net/quic/core/quic_flags.h"
-#include "net/quic/core/quic_protocol.h"
+#include "net/quic/core/quic_packets.h"
+#include "net/quic/platform/api/quic_bug_tracker.h"
+#include "net/quic/platform/api/quic_logging.h"
+#include "net/quic/platform/api/quic_socket_address.h"
#ifndef SO_RXQ_OVFL
#define SO_RXQ_OVFL 40
#endif
+using std::string;
+
namespace net {
// static
void QuicSocketUtils::GetAddressAndTimestampFromMsghdr(
struct msghdr* hdr,
- IPAddress* address,
+ QuicIpAddress* address,
QuicWallTime* walltimestamp) {
if (hdr->msg_controllen > 0) {
for (cmsghdr* cmsg = CMSG_FIRSTHDR(hdr); cmsg != nullptr;
cmsg = CMSG_NXTHDR(hdr, cmsg)) {
- const uint8_t* addr_data = nullptr;
+ char* addr_data = nullptr;
int len = 0;
if (cmsg->cmsg_type == IPV6_PKTINFO) {
in6_pktinfo* info = reinterpret_cast<in6_pktinfo*>(CMSG_DATA(cmsg));
- addr_data = reinterpret_cast<const uint8_t*>(&info->ipi6_addr);
+ addr_data = reinterpret_cast<char*>(&info->ipi6_addr);
len = sizeof(in6_addr);
- *address = IPAddress(addr_data, len);
+ address->FromPackedString(addr_data, len);
} else if (cmsg->cmsg_type == IP_PKTINFO) {
in_pktinfo* info = reinterpret_cast<in_pktinfo*>(CMSG_DATA(cmsg));
- addr_data = reinterpret_cast<const uint8_t*>(&info->ipi_addr);
+ addr_data = reinterpret_cast<char*>(&info->ipi_addr);
len = sizeof(in_addr);
- *address = IPAddress(addr_data, len);
+ address->FromPackedString(addr_data, len);
} else if (cmsg->cmsg_level == SOL_SOCKET &&
cmsg->cmsg_type == SO_TIMESTAMPING) {
LinuxTimestamping* lts =
@@ -131,9 +134,9 @@ int QuicSocketUtils::ReadPacket(int fd,
char* buffer,
size_t buf_len,
QuicPacketCount* dropped_packets,
- IPAddress* self_address,
+ QuicIpAddress* self_address,
QuicWallTime* walltimestamp,
- IPEndPoint* peer_address) {
+ QuicSocketAddress* peer_address) {
DCHECK(peer_address != nullptr);
char cbuf[kSpaceForCmsg];
memset(cbuf, 0, arraysize(cbuf));
@@ -174,7 +177,7 @@ int QuicSocketUtils::ReadPacket(int fd,
GetOverflowFromMsghdr(&hdr, dropped_packets);
}
- IPAddress stack_address;
+ QuicIpAddress stack_address;
if (self_address == nullptr) {
self_address = &stack_address;
}
@@ -186,21 +189,13 @@ int QuicSocketUtils::ReadPacket(int fd,
GetAddressAndTimestampFromMsghdr(&hdr, self_address, walltimestamp);
- if (raw_address.ss_family == AF_INET) {
- CHECK(peer_address->FromSockAddr(
- reinterpret_cast<const sockaddr*>(&raw_address),
- sizeof(struct sockaddr_in)));
- } else if (raw_address.ss_family == AF_INET6) {
- CHECK(peer_address->FromSockAddr(
- reinterpret_cast<const sockaddr*>(&raw_address),
- sizeof(struct sockaddr_in6)));
- }
-
+ *peer_address = QuicSocketAddress(raw_address);
return bytes_read;
}
-size_t QuicSocketUtils::SetIpInfoInCmsg(const IPAddress& self_address,
+size_t QuicSocketUtils::SetIpInfoInCmsg(const QuicIpAddress& self_address,
cmsghdr* cmsg) {
+ string address_string;
if (self_address.IsIPv4()) {
cmsg->cmsg_len = CMSG_LEN(sizeof(in_pktinfo));
cmsg->cmsg_level = IPPROTO_IP;
@@ -208,8 +203,9 @@ size_t QuicSocketUtils::SetIpInfoInCmsg(const IPAddress& self_address,
in_pktinfo* pktinfo = reinterpret_cast<in_pktinfo*>(CMSG_DATA(cmsg));
memset(pktinfo, 0, sizeof(in_pktinfo));
pktinfo->ipi_ifindex = 0;
- memcpy(&pktinfo->ipi_spec_dst, self_address.bytes().data(),
- self_address.size());
+ address_string = self_address.ToPackedString();
+ memcpy(&pktinfo->ipi_spec_dst, address_string.c_str(),
+ address_string.length());
return sizeof(in_pktinfo);
} else if (self_address.IsIPv6()) {
cmsg->cmsg_len = CMSG_LEN(sizeof(in6_pktinfo));
@@ -217,8 +213,9 @@ size_t QuicSocketUtils::SetIpInfoInCmsg(const IPAddress& self_address,
cmsg->cmsg_type = IPV6_PKTINFO;
in6_pktinfo* pktinfo = reinterpret_cast<in6_pktinfo*>(CMSG_DATA(cmsg));
memset(pktinfo, 0, sizeof(in6_pktinfo));
- memcpy(&pktinfo->ipi6_addr, self_address.bytes().data(),
- self_address.size());
+ address_string = self_address.ToPackedString();
+ memcpy(&pktinfo->ipi6_addr, address_string.c_str(),
+ address_string.length());
return sizeof(in6_pktinfo);
} else {
NOTREACHED() << "Unrecognized IPAddress";
@@ -227,20 +224,19 @@ size_t QuicSocketUtils::SetIpInfoInCmsg(const IPAddress& self_address,
}
// static
-WriteResult QuicSocketUtils::WritePacket(int fd,
- const char* buffer,
- size_t buf_len,
- const IPAddress& self_address,
- const IPEndPoint& peer_address) {
- sockaddr_storage raw_address;
- socklen_t address_len = sizeof(raw_address);
- CHECK(peer_address.ToSockAddr(
- reinterpret_cast<struct sockaddr*>(&raw_address), &address_len));
+WriteResult QuicSocketUtils::WritePacket(
+ int fd,
+ const char* buffer,
+ size_t buf_len,
+ const QuicIpAddress& self_address,
+ const QuicSocketAddress& peer_address) {
+ sockaddr_storage raw_address = peer_address.generic_address();
iovec iov = {const_cast<char*>(buffer), buf_len};
msghdr hdr;
hdr.msg_name = &raw_address;
- hdr.msg_namelen = address_len;
+ hdr.msg_namelen = raw_address.ss_family == AF_INET ? sizeof(sockaddr_in)
+ : sizeof(sockaddr_in6);
hdr.msg_iov = &iov;
hdr.msg_iovlen = 1;
hdr.msg_flags = 0;
@@ -251,7 +247,7 @@ WriteResult QuicSocketUtils::WritePacket(int fd,
const int kSpaceForIp =
(kSpaceForIpv4 < kSpaceForIpv6) ? kSpaceForIpv6 : kSpaceForIpv4;
char cbuf[kSpaceForIp];
- if (self_address.empty()) {
+ if (!self_address.IsInitialized()) {
hdr.msg_control = 0;
hdr.msg_controllen = 0;
} else {
@@ -276,12 +272,12 @@ WriteResult QuicSocketUtils::WritePacket(int fd,
}
// static
-int QuicSocketUtils::CreateUDPSocket(const IPEndPoint& address,
+int QuicSocketUtils::CreateUDPSocket(const QuicSocketAddress& address,
bool* overflow_supported) {
- int address_family = address.GetSockAddrFamily();
+ int address_family = address.host().AddressFamilyToInt();
int fd = socket(address_family, SOCK_DGRAM | SOCK_NONBLOCK, IPPROTO_UDP);
if (fd < 0) {
- LOG(ERROR) << "socket() failed: " << strerror(errno);
+ QUIC_LOG(ERROR) << "socket() failed: " << strerror(errno);
return -1;
}
@@ -289,7 +285,7 @@ int QuicSocketUtils::CreateUDPSocket(const IPEndPoint& address,
int rc = setsockopt(fd, SOL_SOCKET, SO_RXQ_OVFL, &get_overflow,
sizeof(get_overflow));
if (rc < 0) {
- DLOG(WARNING) << "Socket overflow detection not supported";
+ QUIC_DLOG(WARNING) << "Socket overflow detection not supported";
} else {
*overflow_supported = true;
}
@@ -310,8 +306,8 @@ int QuicSocketUtils::CreateUDPSocket(const IPEndPoint& address,
rc = SetGetSoftwareReceiveTimestamp(fd);
if (rc < 0) {
- LOG(WARNING) << "SO_TIMESTAMPING not supported; using fallback: "
- << strerror(errno);
+ QUIC_LOG(WARNING) << "SO_TIMESTAMPING not supported; using fallback: "
+ << strerror(errno);
}
return fd;
diff --git a/chromium/net/tools/quic/quic_socket_utils.h b/chromium/net/tools/quic/platform/impl/quic_socket_utils.h
index f8cc5392c5f..3fb28f92809 100644
--- a/chromium/net/tools/quic/quic_socket_utils.h
+++ b/chromium/net/tools/quic/platform/impl/quic_socket_utils.h
@@ -4,8 +4,8 @@
//
// Some socket related helper methods for quic.
-#ifndef NET_TOOLS_QUIC_QUIC_SOCKET_UTILS_H_
-#define NET_TOOLS_QUIC_QUIC_SOCKET_UTILS_H_
+#ifndef NET_TOOLS_QUIC_PLATFORM_IMPL_QUIC_SOCKET_UTILS_H_
+#define NET_TOOLS_QUIC_PLATFORM_IMPL_QUIC_SOCKET_UTILS_H_
#include <netinet/in.h>
#include <stddef.h>
@@ -20,6 +20,8 @@
#include "net/quic/core/quic_types.h"
namespace net {
+class QuicIpAddress;
+class QuicSocketAddress;
// This is the structure that SO_TIMESTAMPING fills into the cmsg header. It is
// well-defined, but does not have a definition in a public header. See
@@ -51,7 +53,7 @@ class QuicSocketUtils {
// |timestamp| if |hdr| contains |SO_TIMESTAMPING|. |address| and |timestamp|
// must not be null.
static void GetAddressAndTimestampFromMsghdr(struct msghdr* hdr,
- IPAddress* address,
+ QuicIpAddress* address,
QuicWallTime* walltimestamp);
// If the msghdr contains an SO_RXQ_OVFL entry, this will set dropped_packets
@@ -95,9 +97,9 @@ class QuicSocketUtils {
char* buffer,
size_t buf_len,
QuicPacketCount* dropped_packets,
- IPAddress* self_address,
+ QuicIpAddress* self_address,
QuicWallTime* walltimestamp,
- IPEndPoint* peer_address);
+ QuicSocketAddress* peer_address);
// Writes buf_len to the socket. If writing is successful, sets the result's
// status to WRITE_STATUS_OK and sets bytes_written. Otherwise sets the
@@ -106,18 +108,19 @@ class QuicSocketUtils {
static WriteResult WritePacket(int fd,
const char* buffer,
size_t buf_len,
- const IPAddress& self_address,
- const IPEndPoint& peer_address);
+ const QuicIpAddress& self_address,
+ const QuicSocketAddress& peer_address);
// A helper for WritePacket which fills in the cmsg with the supplied self
// address.
// Returns the length of the packet info structure used.
- static size_t SetIpInfoInCmsg(const IPAddress& self_address, cmsghdr* cmsg);
+ static size_t SetIpInfoInCmsg(const QuicIpAddress& self_address,
+ cmsghdr* cmsg);
// Creates a UDP socket and sets appropriate socket options for QUIC.
// Returns the created FD if successful, -1 otherwise.
// |overflow_supported| is set to true if the socket supports it.
- static int CreateUDPSocket(const IPEndPoint& address,
+ static int CreateUDPSocket(const QuicSocketAddress& address,
bool* overflow_supported);
private:
@@ -126,4 +129,4 @@ class QuicSocketUtils {
} // namespace net
-#endif // NET_TOOLS_QUIC_QUIC_SOCKET_UTILS_H_
+#endif // NET_TOOLS_QUIC_PLATFORM_IMPL_QUIC_SOCKET_UTILS_H_
diff --git a/chromium/net/tools/quic/platform/impl/quic_socket_utils_test.cc b/chromium/net/tools/quic/platform/impl/quic_socket_utils_test.cc
new file mode 100644
index 00000000000..58fd70b411c
--- /dev/null
+++ b/chromium/net/tools/quic/platform/impl/quic_socket_utils_test.cc
@@ -0,0 +1,173 @@
+// Copyright 2013 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.
+
+#include "net/tools/quic/platform/impl/quic_socket_utils.h"
+
+#include <fcntl.h>
+
+#include <array>
+
+#include "net/quic/platform/api/quic_logging.h"
+#include "net/quic/platform/api/quic_socket_address.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace net {
+namespace test {
+namespace {
+
+// A test fixture is used to ensure that all sockets are closed down gracefully
+// upon test completion. Also provides a convenient API to Bind not presently
+// available in QuicSocketUtils.
+class QuicSocketUtilsTest : public ::testing::Test {
+ protected:
+ ~QuicSocketUtilsTest() override {
+ for (int fd : open_sockets_) {
+ close(fd);
+ }
+ }
+
+ int CreateUDPSocket(const QuicSocketAddress& address) {
+ bool overflow_supported = false;
+ int fd = QuicSocketUtils::CreateUDPSocket(address, &overflow_supported);
+ if (fd != -1) {
+ open_sockets_.push_back(fd);
+ }
+ return fd;
+ }
+
+ int CreateBoundUDPSocket(QuicSocketAddress* address) {
+ int fd = CreateUDPSocket(*address);
+ *address = BindSocket(fd, *address);
+ if (!address->IsInitialized()) {
+ close(fd);
+ fd = -1;
+ }
+ return fd;
+ }
+
+ QuicSocketAddress BindSocket(int fd, const QuicSocketAddress& address) {
+ QuicSocketAddress bound_address;
+
+ if (fd == -1) {
+ return bound_address;
+ }
+
+ sockaddr_storage bind_addr_native = address.generic_address();
+ socklen_t bind_addr_size = 0;
+
+ switch (address.host().address_family()) {
+ case IpAddressFamily::IP_V4:
+ bind_addr_size = sizeof(struct sockaddr_in);
+ break;
+ case IpAddressFamily::IP_V6:
+ bind_addr_size = sizeof(struct sockaddr_in6);
+ break;
+ case IpAddressFamily::IP_UNSPEC:
+ QUIC_LOG(FATAL) << "Unspecified IP address family";
+ }
+
+ int rc = bind(fd, reinterpret_cast<sockaddr*>(&bind_addr_native),
+ bind_addr_size);
+ if (rc != 0) {
+ QUIC_LOG(ERROR) << "Failed to bind socket to " << address.ToString()
+ << ": " << strerror(errno);
+ return bound_address;
+ }
+
+ rc = bound_address.FromSocket(fd);
+ if (rc != 0) {
+ QUIC_LOG(ERROR) << "Failed to get bound socket address from fd: "
+ << strerror(errno);
+ bound_address = QuicSocketAddress();
+ }
+ return bound_address;
+ }
+
+ private:
+ std::vector<int> open_sockets_;
+};
+
+// This test verifies that QuicSocketUtils creates a non-blocking socket
+// successfully by seeing if a read blocks.
+TEST_F(QuicSocketUtilsTest, NonBlockingSocket) {
+ std::array<char, 512> buffer;
+
+ QuicIpAddress localhost = QuicIpAddress::Loopback4();
+ QuicSocketAddress addr(localhost, 0);
+
+ int fd = CreateUDPSocket(addr);
+ ASSERT_NE(-1, fd);
+
+ int fd_flags = fcntl(fd, F_GETFL, 0);
+
+ // Assert so that the test errors out quickly rather than blocking below and
+ // relying on timeouts.
+ ASSERT_TRUE(fd_flags & O_NONBLOCK) << "Socket not reporting as non-blocking";
+
+ QuicIpAddress target_server_addr;
+ auto walltimestamp = QuicWallTime::Zero();
+ QuicSocketAddress remote_addr;
+ int bytes_read = QuicSocketUtils::ReadPacket(fd, buffer.data(), buffer.size(),
+ nullptr, &target_server_addr,
+ &walltimestamp, &remote_addr);
+ EXPECT_EQ(-1, bytes_read);
+}
+
+// This test verifies that we can successfully WritePacket/ReadPacket between
+// two localhost sockets.
+TEST_F(QuicSocketUtilsTest, PacketRoundTrip) {
+ QuicIpAddress localhost = QuicIpAddress::Loopback4();
+ QuicSocketAddress client_addr(localhost, 0);
+ QuicSocketAddress server_addr(localhost, 0);
+
+ int server_fd = CreateBoundUDPSocket(&server_addr);
+ int client_fd = CreateUDPSocket(client_addr);
+
+ ASSERT_NE(-1, server_fd);
+ ASSERT_NE(-1, client_fd);
+
+ {
+ std::array<char, 512> write_buffer;
+ for (size_t i = 0; i < write_buffer.size(); i++) {
+ write_buffer[i] = static_cast<char>(i);
+ }
+ auto res = QuicSocketUtils::WritePacket(client_fd, write_buffer.data(),
+ write_buffer.size(),
+ QuicIpAddress(), server_addr);
+ ASSERT_EQ(WRITE_STATUS_OK, res.status) << "Failed to write with error "
+ << res.error_code;
+ EXPECT_EQ(512, res.bytes_written);
+ }
+
+ fd_set read_fds;
+ FD_ZERO(&read_fds);
+ FD_SET(server_fd, &read_fds);
+
+ timeval select_timeout;
+ select_timeout.tv_sec = 5;
+ select_timeout.tv_usec = 0;
+
+ int select_rc =
+ select(1 + server_fd, &read_fds, nullptr, nullptr, &select_timeout);
+ EXPECT_EQ(select_rc, 1) << "server_fd didn't become read selectable: "
+ << errno;
+
+ {
+ std::array<char, 1024> read_buffer;
+ QuicIpAddress target_server_addr;
+ auto walltimestamp = QuicWallTime::Zero();
+ QuicSocketAddress remote_addr;
+ int bytes_read = QuicSocketUtils::ReadPacket(
+ server_fd, read_buffer.data(), read_buffer.size(), nullptr,
+ &target_server_addr, &walltimestamp, &remote_addr);
+ EXPECT_EQ(512, bytes_read);
+ for (int i = 0; i < bytes_read; i++) {
+ EXPECT_EQ(static_cast<char>(i), read_buffer[i]);
+ }
+ }
+}
+
+} // namespace
+} // namespace test
+} // namespace net
diff --git a/chromium/net/tools/quic/quic_client.cc b/chromium/net/tools/quic/quic_client.cc
index f745e2e912d..bfd2442cd25 100644
--- a/chromium/net/tools/quic/quic_client.cc
+++ b/chromium/net/tools/quic/quic_client.cc
@@ -11,21 +11,20 @@
#include <sys/socket.h>
#include <unistd.h>
-#include "base/logging.h"
#include "base/run_loop.h"
-#include "base/strings/string_number_conversions.h"
#include "net/base/sockaddr_storage.h"
#include "net/quic/core/crypto/quic_random.h"
-#include "net/quic/core/quic_bug_tracker.h"
#include "net/quic/core/quic_connection.h"
#include "net/quic/core/quic_data_reader.h"
#include "net/quic/core/quic_flags.h"
-#include "net/quic/core/quic_protocol.h"
+#include "net/quic/core/quic_packets.h"
#include "net/quic/core/quic_server_id.h"
#include "net/quic/core/spdy_utils.h"
+#include "net/quic/platform/api/quic_bug_tracker.h"
+#include "net/quic/platform/api/quic_logging.h"
+#include "net/tools/quic/platform/impl/quic_socket_utils.h"
#include "net/tools/quic/quic_epoll_alarm_factory.h"
#include "net/tools/quic/quic_epoll_connection_helper.h"
-#include "net/tools/quic/quic_socket_utils.h"
#ifndef SO_RXQ_OVFL
#define SO_RXQ_OVFL 40
@@ -33,17 +32,14 @@
// TODO(rtenneti): Add support for MMSG_MORE.
#define MMSG_MORE 0
-
using base::StringPiece;
-using base::StringToInt;
using std::string;
-using std::vector;
namespace net {
const int kEpollFlags = EPOLLIN | EPOLLOUT | EPOLLET;
-QuicClient::QuicClient(IPEndPoint server_address,
+QuicClient::QuicClient(QuicSocketAddress server_address,
const QuicServerId& server_id,
const QuicVersionVector& supported_versions,
EpollServer* epoll_server,
@@ -55,7 +51,7 @@ QuicClient::QuicClient(IPEndPoint server_address,
epoll_server,
std::move(proof_verifier)) {}
-QuicClient::QuicClient(IPEndPoint server_address,
+QuicClient::QuicClient(QuicSocketAddress server_address,
const QuicServerId& server_id,
const QuicVersionVector& supported_versions,
const QuicConfig& config,
@@ -85,8 +81,8 @@ QuicClient::~QuicClient() {
CleanUpAllUDPSockets();
}
-bool QuicClient::CreateUDPSocketAndBind(IPEndPoint server_address,
- IPAddress bind_to_address,
+bool QuicClient::CreateUDPSocketAndBind(QuicSocketAddress server_address,
+ QuicIpAddress bind_to_address,
int bind_to_port) {
epoll_server_->set_timeout_in_us(50 * 1000);
@@ -96,30 +92,25 @@ bool QuicClient::CreateUDPSocketAndBind(IPEndPoint server_address,
return false;
}
- IPEndPoint client_address;
- if (bind_to_address.size() != 0) {
- client_address = IPEndPoint(bind_to_address, bind_to_port);
- } else if (server_address.GetSockAddrFamily() == AF_INET) {
- client_address = IPEndPoint(IPAddress::IPv4AllZeros(), bind_to_port);
+ QuicSocketAddress client_address;
+ if (bind_to_address.IsInitialized()) {
+ client_address = QuicSocketAddress(bind_to_address, local_port());
+ } else if (server_address.host().address_family() == IpAddressFamily::IP_V4) {
+ client_address = QuicSocketAddress(QuicIpAddress::Any4(), bind_to_port);
} else {
- client_address = IPEndPoint(IPAddress::IPv6AllZeros(), bind_to_port);
+ client_address = QuicSocketAddress(QuicIpAddress::Any6(), bind_to_port);
}
- sockaddr_storage raw_addr;
- socklen_t raw_addr_len = sizeof(raw_addr);
- CHECK(client_address.ToSockAddr(reinterpret_cast<sockaddr*>(&raw_addr),
- &raw_addr_len));
- int rc =
- bind(fd, reinterpret_cast<const sockaddr*>(&raw_addr), sizeof(raw_addr));
+ sockaddr_storage addr = client_address.generic_address();
+ int rc = bind(fd, reinterpret_cast<sockaddr*>(&addr), sizeof(addr));
if (rc < 0) {
- LOG(ERROR) << "Bind failed: " << strerror(errno);
+ QUIC_LOG(ERROR) << "Bind failed: " << strerror(errno);
return false;
}
- SockaddrStorage storage;
- if (getsockname(fd, storage.addr, &storage.addr_len) != 0 ||
- !client_address.FromSockAddr(storage.addr, storage.addr_len)) {
- LOG(ERROR) << "Unable to get self address. Error: " << strerror(errno);
+ if (client_address.FromSocket(fd) != 0) {
+ QUIC_LOG(ERROR) << "Unable to get self address. Error: "
+ << strerror(errno);
}
fd_address_map_[fd] = client_address;
@@ -134,7 +125,7 @@ void QuicClient::CleanUpUDPSocket(int fd) {
}
void QuicClient::CleanUpAllUDPSockets() {
- for (std::pair<int, IPEndPoint> fd_address : fd_address_map_) {
+ for (std::pair<int, QuicSocketAddress> fd_address : fd_address_map_) {
CleanUpUDPSocketImpl(fd_address.first);
}
fd_address_map_.clear();
@@ -170,7 +161,7 @@ void QuicClient::OnEvent(int fd, EpollEvent* event) {
session()->connection()->OnCanWrite();
}
if (event->in_events & EPOLLERR) {
- DVLOG(1) << "Epollerr";
+ QUIC_DLOG(INFO) << "Epollerr";
}
}
@@ -178,9 +169,9 @@ QuicPacketWriter* QuicClient::CreateQuicPacketWriter() {
return new QuicDefaultPacketWriter(GetLatestFD());
}
-IPEndPoint QuicClient::GetLatestClientAddress() const {
+QuicSocketAddress QuicClient::GetLatestClientAddress() const {
if (fd_address_map_.empty()) {
- return IPEndPoint();
+ return QuicSocketAddress();
}
return fd_address_map_.back().second;
@@ -194,8 +185,8 @@ int QuicClient::GetLatestFD() const {
return fd_address_map_.back().first;
}
-void QuicClient::ProcessPacket(const IPEndPoint& self_address,
- const IPEndPoint& peer_address,
+void QuicClient::ProcessPacket(const QuicSocketAddress& self_address,
+ const QuicSocketAddress& peer_address,
const QuicReceivedPacket& packet) {
session()->ProcessUdpPacket(self_address, peer_address, packet);
}
diff --git a/chromium/net/tools/quic/quic_client.h b/chromium/net/tools/quic/quic_client.h
index 567dc6c837c..7a479f637d1 100644
--- a/chromium/net/tools/quic/quic_client.h
+++ b/chromium/net/tools/quic/quic_client.h
@@ -15,8 +15,6 @@
#include "base/command_line.h"
#include "base/macros.h"
#include "base/strings/string_piece.h"
-#include "net/base/ip_address.h"
-#include "net/base/ip_endpoint.h"
#include "net/quic/core/quic_client_push_promise_index.h"
#include "net/quic/core/quic_config.h"
#include "net/quic/core/quic_spdy_stream.h"
@@ -30,8 +28,6 @@ namespace net {
class QuicServerId;
-class QuicEpollConnectionHelper;
-
namespace test {
class QuicClientPeer;
} // namespace test
@@ -42,12 +38,12 @@ class QuicClient : public QuicClientBase,
public:
// Create a quic client, which will have events managed by an externally owned
// EpollServer.
- QuicClient(IPEndPoint server_address,
+ QuicClient(QuicSocketAddress server_address,
const QuicServerId& server_id,
const QuicVersionVector& supported_versions,
EpollServer* epoll_server,
std::unique_ptr<ProofVerifier> proof_verifier);
- QuicClient(IPEndPoint server_address,
+ QuicClient(QuicSocketAddress server_address,
const QuicServerId& server_id,
const QuicVersionVector& supported_versions,
const QuicConfig& config,
@@ -71,20 +67,20 @@ class QuicClient : public QuicClientBase,
int GetLatestFD() const;
// From QuicClientBase
- IPEndPoint GetLatestClientAddress() const override;
+ QuicSocketAddress GetLatestClientAddress() const override;
// Implements ProcessPacketInterface. This will be called for each received
// packet.
- void ProcessPacket(const IPEndPoint& self_address,
- const IPEndPoint& peer_address,
+ void ProcessPacket(const QuicSocketAddress& self_address,
+ const QuicSocketAddress& peer_address,
const QuicReceivedPacket& packet) override;
protected:
// From QuicClientBase
QuicPacketWriter* CreateQuicPacketWriter() override;
void RunEventLoop() override;
- bool CreateUDPSocketAndBind(IPEndPoint server_address,
- IPAddress bind_to_address,
+ bool CreateUDPSocketAndBind(QuicSocketAddress server_address,
+ QuicIpAddress bind_to_address,
int bind_to_port) override;
void CleanUpAllUDPSockets() override;
@@ -94,7 +90,7 @@ class QuicClient : public QuicClientBase,
EpollServer* epoll_server() { return epoll_server_; }
- const linked_hash_map<int, IPEndPoint>& fd_address_map() const {
+ const linked_hash_map<int, QuicSocketAddress>& fd_address_map() const {
return fd_address_map_;
}
@@ -109,7 +105,7 @@ class QuicClient : public QuicClientBase,
// Map mapping created UDP sockets to their addresses. By using linked hash
// map, the order of socket creation can be recorded.
- linked_hash_map<int, IPEndPoint> fd_address_map_;
+ linked_hash_map<int, QuicSocketAddress> fd_address_map_;
// If overflow_supported_ is true, this will be the number of packets dropped
// during the lifetime of the server.
diff --git a/chromium/net/tools/quic/quic_client_base.cc b/chromium/net/tools/quic/quic_client_base.cc
index c969685d8a4..dc07949d359 100644
--- a/chromium/net/tools/quic/quic_client_base.cc
+++ b/chromium/net/tools/quic/quic_client_base.cc
@@ -4,10 +4,11 @@
#include "net/tools/quic/quic_client_base.h"
-#include "base/strings/string_number_conversions.h"
#include "net/quic/core/crypto/quic_random.h"
#include "net/quic/core/quic_server_id.h"
#include "net/quic/core/spdy_utils.h"
+#include "net/quic/platform/api/quic_logging.h"
+#include "net/quic/platform/api/quic_text_utils.h"
using base::StringPiece;
using base::StringToInt;
@@ -68,7 +69,7 @@ void QuicClientBase::OnClose(QuicSpdyStream* stream) {
auto status = response_headers.find(":status");
if (status == response_headers.end() ||
!StringToInt(status->second, &latest_response_code_)) {
- LOG(ERROR) << "Invalid response headers";
+ QUIC_LOG(ERROR) << "Invalid response headers";
}
latest_response_headers_ = response_headers.DebugString();
latest_response_header_block_ = response_headers.Clone();
@@ -115,7 +116,8 @@ bool QuicClientBase::Connect() {
while (EncryptionBeingEstablished()) {
WaitForEvents();
}
- if (FLAGS_enable_quic_stateless_reject_support && connected()) {
+ if (FLAGS_quic_reloadable_flag_enable_quic_stateless_reject_support &&
+ connected()) {
// Resend any previously queued data.
ResendSavedData();
}
@@ -269,16 +271,16 @@ bool QuicClientBase::WaitForEvents() {
DCHECK(session() != nullptr);
if (!connected() &&
session()->error() == QUIC_CRYPTO_HANDSHAKE_STATELESS_REJECT) {
- DCHECK(FLAGS_enable_quic_stateless_reject_support);
- DVLOG(1) << "Detected stateless reject while waiting for events. "
- << "Attempting to reconnect.";
+ DCHECK(FLAGS_quic_reloadable_flag_enable_quic_stateless_reject_support);
+ QUIC_DLOG(INFO) << "Detected stateless reject while waiting for events. "
+ << "Attempting to reconnect.";
Connect();
}
return session()->num_active_requests() != 0;
}
-bool QuicClientBase::MigrateSocket(const IPAddress& new_host) {
+bool QuicClientBase::MigrateSocket(const QuicIpAddress& new_host) {
if (!connected()) {
return false;
}
@@ -307,12 +309,16 @@ void QuicClientBase::WaitForStreamToClose(QuicStreamId id) {
}
}
-void QuicClientBase::WaitForCryptoHandshakeConfirmed() {
+bool QuicClientBase::WaitForCryptoHandshakeConfirmed() {
DCHECK(connected());
while (connected() && !session_->IsCryptoHandshakeConfirmed()) {
WaitForEvents();
}
+
+ // If the handshake fails due to a timeout, the connection will be closed.
+ QUIC_LOG_IF(ERROR, !connected()) << "Handshake with server failed.";
+ return connected();
}
bool QuicClientBase::connected() const {
@@ -388,7 +394,7 @@ QuicConnectionId QuicClientBase::GenerateNewConnectionId() {
void QuicClientBase::MaybeAddDataToResend(const SpdyHeaderBlock& headers,
StringPiece body,
bool fin) {
- if (!FLAGS_enable_quic_stateless_reject_support) {
+ if (!FLAGS_quic_reloadable_flag_enable_quic_stateless_reject_support) {
return;
}
diff --git a/chromium/net/tools/quic/quic_client_base.h b/chromium/net/tools/quic/quic_client_base.h
index d2bf5fb851c..66472837f7b 100644
--- a/chromium/net/tools/quic/quic_client_base.h
+++ b/chromium/net/tools/quic/quic_client_base.h
@@ -12,7 +12,6 @@
#include <string>
#include "base/macros.h"
-#include "net/base/ip_endpoint.h"
#include "net/quic/core/crypto/crypto_handshake.h"
#include "net/quic/core/crypto/quic_crypto_client_config.h"
#include "net/quic/core/quic_alarm_factory.h"
@@ -21,7 +20,8 @@
#include "net/quic/core/quic_config.h"
#include "net/quic/core/quic_connection.h"
#include "net/quic/core/quic_packet_writer.h"
-#include "net/quic/core/quic_protocol.h"
+#include "net/quic/core/quic_packets.h"
+#include "net/quic/platform/api/quic_socket_address.h"
#include "net/tools/quic/quic_client_session.h"
#include "net/tools/quic/quic_spdy_client_stream.h"
@@ -45,14 +45,17 @@ class QuicClientBase : public QuicClientPushPromiseIndex::Delegate,
// The client uses these objects to keep track of any data to resend upon
// receipt of a stateless reject. Recall that the client API allows callers
- // to optimistically send data to the server prior to handshake-confirmation.
+ // to optimistically send data to the server prior to
+ // handshake-confirmation.
// If the client subsequently receives a stateless reject, it must tear down
- // its existing session, create a new session, and resend all previously sent
+ // its existing session, create a new session, and resend all previously
+ // sent
// data. It uses these objects to keep track of all the sent data, and to
// resend the data upon a subsequent connection.
class QuicDataToResend {
public:
- // |headers| may be null, since it's possible to send data without headers.
+ // |headers| may be null, since it's possible to send data without
+ // headers.
QuicDataToResend(std::unique_ptr<SpdyHeaderBlock> headers,
base::StringPiece body,
bool fin);
@@ -94,7 +97,8 @@ class QuicClientBase : public QuicClientPushPromiseIndex::Delegate,
bool Connect();
// Start the crypto handshake. This can be done in place of the synchronous
- // Connect(), but callers are responsible for making sure the crypto handshake
+ // Connect(), but callers are responsible for making sure the crypto
+ // handshake
// completes.
void StartConnect();
@@ -102,7 +106,8 @@ class QuicClientBase : public QuicClientPushPromiseIndex::Delegate,
void Disconnect();
// Returns true if the crypto handshake has yet to establish encryption.
- // Returns false if encryption is active (even if the server hasn't confirmed
+ // Returns false if encryption is active (even if the server hasn't
+ // confirmed
// the handshake) or if the connection has been closed.
bool EncryptionBeingEstablished();
@@ -128,14 +133,15 @@ class QuicClientBase : public QuicClientPushPromiseIndex::Delegate,
void WaitForStreamToClose(QuicStreamId id);
// Wait for events until the handshake is confirmed.
- void WaitForCryptoHandshakeConfirmed();
+ // Returns true if the crypto handshake succeeds, false otherwise.
+ bool WaitForCryptoHandshakeConfirmed() WARN_UNUSED_RESULT;
// Wait up to 50ms, and handle any events which occur.
// Returns true if there are any outstanding requests.
bool WaitForEvents();
// Migrate to a new socket during an active connection.
- bool MigrateSocket(const IPAddress& new_host);
+ bool MigrateSocket(const QuicIpAddress& new_host);
QuicClientSession* session() { return session_.get(); }
@@ -160,10 +166,12 @@ class QuicClientBase : public QuicClientPushPromiseIndex::Delegate,
}
// UseTokenBinding enables token binding negotiation in the client. This
- // should only be called before the initial Connect(). The client will still
+ // should only be called before the initial Connect(). The client will
+ // still
// need to check that token binding is negotiated with the server, and add
// token binding headers to requests if so. server, and add token binding
- // headers to requests if so. The negotiated token binding parameters can be
+ // headers to requests if so. The negotiated token binding parameters can
+ // be
// found on the QuicCryptoNegotiatedParameters object in
// token_binding_key_param.
void UseTokenBinding() {
@@ -182,7 +190,8 @@ class QuicClientBase : public QuicClientPushPromiseIndex::Delegate,
QuicCryptoClientConfig* crypto_config() { return &crypto_config_; }
- // Change the initial maximum packet size of the connection. Has to be called
+ // Change the initial maximum packet size of the connection. Has to be
+ // called
// before Connect()/StartConnect() in order to have any effect.
void set_initial_max_packet_length(QuicByteCount initial_max_packet_length) {
initial_max_packet_length_ = initial_max_packet_length;
@@ -200,7 +209,8 @@ class QuicClientBase : public QuicClientPushPromiseIndex::Delegate,
// instead.
int GetNumSentClientHellos();
- // Gather the stats for the last session and update the stats for the overall
+ // Gather the stats for the last session and update the stats for the
+ // overall
// connection.
void UpdateStats();
@@ -269,17 +279,19 @@ class QuicClientBase : public QuicClientPushPromiseIndex::Delegate,
response_listener_ = std::move(listener);
}
- void set_bind_to_address(IPAddress address) { bind_to_address_ = address; }
+ void set_bind_to_address(QuicIpAddress address) {
+ bind_to_address_ = address;
+ }
- IPAddress bind_to_address() const { return bind_to_address_; }
+ QuicIpAddress bind_to_address() const { return bind_to_address_; }
void set_local_port(int local_port) { local_port_ = local_port; }
int local_port() const { return local_port_; }
- const IPEndPoint& server_address() const { return server_address_; }
+ const QuicSocketAddress& server_address() const { return server_address_; }
- void set_server_address(const IPEndPoint& server_address) {
+ void set_server_address(const QuicSocketAddress& server_address) {
server_address_ = server_address;
}
@@ -294,10 +306,11 @@ class QuicClientBase : public QuicClientPushPromiseIndex::Delegate,
// Runs one iteration of the event loop.
virtual void RunEventLoop() = 0;
- // Used during initialization: creates the UDP socket FD, sets socket options,
+ // Used during initialization: creates the UDP socket FD, sets socket
+ // options,
// and binds the socket to our address.
- virtual bool CreateUDPSocketAndBind(IPEndPoint server_address,
- IPAddress bind_to_address,
+ virtual bool CreateUDPSocketAndBind(QuicSocketAddress server_address,
+ QuicIpAddress bind_to_address,
int bind_to_port) = 0;
// Unregister and close all open UDP sockets.
@@ -305,14 +318,15 @@ class QuicClientBase : public QuicClientPushPromiseIndex::Delegate,
// If the client has at least one UDP socket, return address of the latest
// created one. Otherwise, return an empty socket address.
- virtual IPEndPoint GetLatestClientAddress() const = 0;
+ virtual QuicSocketAddress GetLatestClientAddress() const = 0;
// Generates the next ConnectionId for |server_id_|. By default, if the
// cached server config contains a server-designated ID, that ID will be
// returned. Otherwise, the next random ID will be returned.
QuicConnectionId GetNextConnectionId();
- // Returns the next server-designated ConnectionId from the cached config for
+ // Returns the next server-designated ConnectionId from the cached config
+ // for
// |server_id_|, if it exists. Otherwise, returns 0.
QuicConnectionId GetNextServerDesignatedConnectionId();
@@ -377,10 +391,10 @@ class QuicClientBase : public QuicClientPushPromiseIndex::Delegate,
bool initialized_;
// Address of the server.
- IPEndPoint server_address_;
+ QuicSocketAddress server_address_;
// If initialized, the address to bind to.
- IPAddress bind_to_address_;
+ QuicIpAddress bind_to_address_;
// Local port to bind to. Initialize to 0.
int local_port_;
@@ -396,7 +410,8 @@ class QuicClientBase : public QuicClientPushPromiseIndex::Delegate,
// Alarm factory to be used by created connections. Must outlive |session_|.
std::unique_ptr<QuicAlarmFactory> alarm_factory_;
- // Writer used to actually send packets to the wire. Must outlive |session_|.
+ // Writer used to actually send packets to the wire. Must outlive
+ // |session_|.
std::unique_ptr<QuicPacketWriter> writer_;
// Index of pending promised streams. Must outlive |session_|.
@@ -406,7 +421,8 @@ class QuicClientBase : public QuicClientPushPromiseIndex::Delegate,
std::unique_ptr<QuicClientSession> session_;
// This vector contains QUIC versions which we currently support.
- // This should be ordered such that the highest supported version is the first
+ // This should be ordered such that the highest supported version is the
+ // first
// element, with subsequent elements in descending order (versions can be
// skipped as necessary). We will always pick supported_versions_[0] as the
// initial version to use.
@@ -418,8 +434,10 @@ class QuicClientBase : public QuicClientPushPromiseIndex::Delegate,
// The number of stateless rejects received during the current/latest
// connection.
- // TODO(jokulik): Consider some consistent naming scheme (or other) for member
- // variables that are kept per-request, per-connection, and over the client's
+ // TODO(jokulik): Consider some consistent naming scheme (or other) for
+ // member
+ // variables that are kept per-request, per-connection, and over the
+ // client's
// lifetime.
int num_stateless_rejects_received_;
@@ -430,7 +448,8 @@ class QuicClientBase : public QuicClientPushPromiseIndex::Delegate,
// opposed to that associated with the last session object).
QuicErrorCode connection_error_;
- // True when the client is attempting to connect or re-connect the session (in
+ // True when the client is attempting to connect or re-connect the session
+ // (in
// the case of a stateless reject). Set to false between a call to
// Disconnect() and the subsequent call to StartConnect(). When
// connected_or_attempting_connect_ is false, the session object corresponds
diff --git a/chromium/net/tools/quic/quic_client_bin.cc b/chromium/net/tools/quic/quic_client_bin.cc
index 9fde3ee2966..c221a55a145 100644
--- a/chromium/net/tools/quic/quic_client_bin.cc
+++ b/chromium/net/tools/quic/quic_client_bin.cc
@@ -42,14 +42,7 @@
#include "base/at_exit.h"
#include "base/command_line.h"
-#include "base/logging.h"
#include "base/message_loop/message_loop.h"
-#include "base/strings/string_number_conversions.h"
-#include "base/strings/string_split.h"
-#include "base/strings/string_util.h"
-#include "base/strings/stringprintf.h"
-#include "net/base/ip_address.h"
-#include "net/base/ip_endpoint.h"
#include "net/base/net_errors.h"
#include "net/base/privacy_mode.h"
#include "net/cert/cert_verifier.h"
@@ -57,9 +50,11 @@
#include "net/http/transport_security_state.h"
#include "net/quic/chromium/crypto/proof_verifier_chromium.h"
#include "net/quic/core/quic_flags.h"
-#include "net/quic/core/quic_protocol.h"
+#include "net/quic/core/quic_packets.h"
#include "net/quic/core/quic_server_id.h"
-#include "net/quic/core/quic_utils.h"
+#include "net/quic/platform/api/quic_socket_address.h"
+#include "net/quic/platform/api/quic_str_cat.h"
+#include "net/quic/platform/api/quic_text_utils.h"
#include "net/spdy/spdy_header_block.h"
#include "net/tools/epoll_server/epoll_server.h"
#include "net/tools/quic/quic_client.h"
@@ -73,12 +68,13 @@ using net::CTVerifier;
using net::MultiLogCTVerifier;
using net::ProofVerifier;
using net::ProofVerifierChromium;
+using net::QuicTextUtils;
using net::SpdyHeaderBlock;
using net::TransportSecurityState;
using std::cout;
using std::cerr;
-using std::string;
using std::endl;
+using std::string;
// The IP or hostname the quic client will connect to.
string FLAGS_host = "";
@@ -223,7 +219,7 @@ int main(int argc, char* argv[]) {
base::MessageLoopForIO message_loop;
// Determine IP address to connect to from supplied hostname.
- net::IPAddress ip_addr;
+ net::QuicIpAddress ip_addr;
GURL url(urls[0]);
string host = FLAGS_host;
@@ -234,7 +230,7 @@ int main(int argc, char* argv[]) {
if (port == 0) {
port = url.EffectiveIntPort();
}
- if (!ip_addr.AssignFromIPLiteral(host)) {
+ if (!ip_addr.FromString(host)) {
net::AddressList addresses;
int rv = net::SynchronousHostResolver::Resolve(host, &addresses);
if (rv != net::OK) {
@@ -242,10 +238,11 @@ int main(int argc, char* argv[]) {
<< "' : " << net::ErrorToShortString(rv);
return 1;
}
- ip_addr = addresses[0].address();
+ ip_addr =
+ net::QuicIpAddress(net::QuicIpAddressImpl(addresses[0].address()));
}
- string host_port = net::IPAddressToStringWithPort(ip_addr, port);
+ string host_port = net::QuicStrCat(ip_addr.ToString(), ":", port);
VLOG(1) << "Resolved " << host << " to " << host_port << endl;
// Build the client, and try to connect.
@@ -261,7 +258,6 @@ int main(int argc, char* argv[]) {
std::unique_ptr<CertVerifier> cert_verifier(CertVerifier::CreateDefault());
std::unique_ptr<TransportSecurityState> transport_security_state(
new TransportSecurityState);
- transport_security_state.reset(new TransportSecurityState);
std::unique_ptr<CTVerifier> ct_verifier(new MultiLogCTVerifier());
std::unique_ptr<CTPolicyEnforcer> ct_policy_enforcer(new CTPolicyEnforcer());
std::unique_ptr<ProofVerifier> proof_verifier;
@@ -272,8 +268,8 @@ int main(int argc, char* argv[]) {
cert_verifier.get(), ct_policy_enforcer.get(),
transport_security_state.get(), ct_verifier.get()));
}
- net::QuicClient client(net::IPEndPoint(ip_addr, port), server_id, versions,
- &epoll_server, std::move(proof_verifier));
+ net::QuicClient client(net::QuicSocketAddress(ip_addr, port), server_id,
+ versions, &epoll_server, std::move(proof_verifier));
client.set_initial_max_packet_length(
FLAGS_initial_mtu != 0 ? FLAGS_initial_mtu : net::kDefaultMaxPacketSize);
if (!client.Initialize()) {
@@ -289,7 +285,7 @@ int main(int argc, char* argv[]) {
return 0;
}
cerr << "Failed to connect to " << host_port
- << ". Error: " << net::QuicUtils::ErrorToString(error) << endl;
+ << ". Error: " << net::QuicErrorCodeToString(error) << endl;
return 1;
}
cout << "Connected to " << host_port << endl;
@@ -298,7 +294,7 @@ int main(int argc, char* argv[]) {
string body = FLAGS_body;
if (!FLAGS_body_hex.empty()) {
DCHECK(FLAGS_body.empty()) << "Only set one of --body and --body_hex.";
- body = net::QuicUtils::HexDecode(FLAGS_body_hex);
+ body = QuicTextUtils::HexDecode(FLAGS_body_hex);
}
// Construct a GET or POST request for supplied URL.
@@ -309,26 +305,20 @@ int main(int argc, char* argv[]) {
header_block[":path"] = url.path();
// Append any additional headers supplied on the command line.
- for (const std::string& header :
- base::SplitString(FLAGS_headers, ";", base::KEEP_WHITESPACE,
- base::SPLIT_WANT_NONEMPTY)) {
- string sp;
- base::TrimWhitespaceASCII(header, base::TRIM_ALL, &sp);
+ for (StringPiece sp : QuicTextUtils::Split(FLAGS_headers, ';')) {
+ QuicTextUtils::RemoveLeadingAndTrailingWhitespace(&sp);
if (sp.empty()) {
continue;
}
- std::vector<string> kv =
- base::SplitString(sp, ":", base::TRIM_WHITESPACE, base::SPLIT_WANT_ALL);
- CHECK_EQ(2u, kv.size());
- string key;
- base::TrimWhitespaceASCII(kv[0], base::TRIM_ALL, &key);
- string value;
- base::TrimWhitespaceASCII(kv[1], base::TRIM_ALL, &value);
+ std::vector<StringPiece> kv = QuicTextUtils::Split(sp, ':');
+ QuicTextUtils::RemoveLeadingAndTrailingWhitespace(&kv[0]);
+ QuicTextUtils::RemoveLeadingAndTrailingWhitespace(&kv[1]);
header_block[kv[0]] = kv[1];
}
// Make sure to store the response, for later output.
client.set_store_response(true);
+
// Send the request.
client.SendRequestAndWaitForResponse(header_block, body, /*fin=*/true);
@@ -339,7 +329,7 @@ int main(int argc, char* argv[]) {
if (!FLAGS_body_hex.empty()) {
// Print the user provided hex, rather than binary body.
cout << "body:\n"
- << net::QuicUtils::HexDump(net::QuicUtils::HexDecode(FLAGS_body_hex))
+ << QuicTextUtils::HexDump(QuicTextUtils::HexDecode(FLAGS_body_hex))
<< endl;
} else {
cout << "body: " << body << endl;
@@ -350,7 +340,7 @@ int main(int argc, char* argv[]) {
string response_body = client.latest_response_body();
if (!FLAGS_body_hex.empty()) {
// Assume response is binary data.
- cout << "body:\n" << net::QuicUtils::HexDump(response_body) << endl;
+ cout << "body:\n" << QuicTextUtils::HexDump(response_body) << endl;
} else {
cout << "body: " << response_body << endl;
}
diff --git a/chromium/net/tools/quic/quic_client_session.cc b/chromium/net/tools/quic/quic_client_session.cc
index bf9f0ed6e4d..8a8e3f0af34 100644
--- a/chromium/net/tools/quic/quic_client_session.cc
+++ b/chromium/net/tools/quic/quic_client_session.cc
@@ -4,13 +4,13 @@
#include "net/tools/quic/quic_client_session.h"
-#include "base/logging.h"
-#include "base/memory/ptr_util.h"
#include "net/log/net_log_with_source.h"
#include "net/quic/chromium/crypto/proof_verifier_chromium.h"
#include "net/quic/core/crypto/crypto_protocol.h"
-#include "net/quic/core/quic_bug_tracker.h"
#include "net/quic/core/quic_server_id.h"
+#include "net/quic/platform/api/quic_bug_tracker.h"
+#include "net/quic/platform/api/quic_logging.h"
+#include "net/quic/platform/api/quic_ptr_util.h"
#include "net/tools/quic/quic_spdy_client_stream.h"
using std::string;
@@ -43,17 +43,17 @@ void QuicClientSession::OnProofVerifyDetailsAvailable(
bool QuicClientSession::ShouldCreateOutgoingDynamicStream() {
if (!crypto_stream_->encryption_established()) {
- DVLOG(1) << "Encryption not active so no outgoing stream created.";
+ QUIC_DLOG(INFO) << "Encryption not active so no outgoing stream created.";
return false;
}
if (GetNumOpenOutgoingStreams() >= max_open_outgoing_streams()) {
- DVLOG(1) << "Failed to create a new outgoing stream. "
- << "Already " << GetNumOpenOutgoingStreams() << " open.";
+ QUIC_DLOG(INFO) << "Failed to create a new outgoing stream. "
+ << "Already " << GetNumOpenOutgoingStreams() << " open.";
return false;
}
if (goaway_received() && respect_goaway_) {
- DVLOG(1) << "Failed to create a new outgoing stream. "
- << "Already received goaway.";
+ QUIC_DLOG(INFO) << "Failed to create a new outgoing stream. "
+ << "Already received goaway.";
return false;
}
return true;
@@ -72,8 +72,7 @@ QuicSpdyClientStream* QuicClientSession::CreateOutgoingDynamicStream(
}
std::unique_ptr<QuicSpdyClientStream> QuicClientSession::CreateClientStream() {
- return base::MakeUnique<QuicSpdyClientStream>(GetNextOutgoingStreamId(),
- this);
+ return QuicMakeUnique<QuicSpdyClientStream>(GetNextOutgoingStreamId(), this);
}
QuicCryptoClientStreamBase* QuicClientSession::GetCryptoStream() {
@@ -99,12 +98,12 @@ bool QuicClientSession::ShouldCreateIncomingDynamicStream(QuicStreamId id) {
return false;
}
if (goaway_received() && respect_goaway_) {
- DVLOG(1) << "Failed to create a new outgoing stream. "
- << "Already received goaway.";
+ QUIC_DLOG(INFO) << "Failed to create a new outgoing stream. "
+ << "Already received goaway.";
return false;
}
if (id % 2 != 0) {
- LOG(WARNING) << "Received invalid push stream id " << id;
+ QUIC_LOG(WARNING) << "Received invalid push stream id " << id;
connection()->CloseConnection(
QUIC_INVALID_STREAM_ID, "Server created odd numbered stream",
ConnectionCloseBehavior::SEND_CONNECTION_CLOSE_PACKET);
@@ -120,13 +119,13 @@ QuicSpdyStream* QuicClientSession::CreateIncomingDynamicStream(
}
QuicSpdyStream* stream = new QuicSpdyClientStream(id, this);
stream->CloseWriteSide();
- ActivateStream(base::WrapUnique(stream));
+ ActivateStream(QuicWrapUnique(stream));
return stream;
}
std::unique_ptr<QuicCryptoClientStreamBase>
QuicClientSession::CreateQuicCryptoStream() {
- return base::MakeUnique<QuicCryptoClientStream>(
+ return QuicMakeUnique<QuicCryptoClientStream>(
server_id_, this, new ProofVerifyContextChromium(0, NetLogWithSource()),
crypto_config_, this);
}
diff --git a/chromium/net/tools/quic/quic_client_session.h b/chromium/net/tools/quic/quic_client_session.h
index 97cb136314a..055fb1c2401 100644
--- a/chromium/net/tools/quic/quic_client_session.h
+++ b/chromium/net/tools/quic/quic_client_session.h
@@ -13,14 +13,13 @@
#include "base/macros.h"
#include "net/quic/core/quic_client_session_base.h"
#include "net/quic/core/quic_crypto_client_stream.h"
-#include "net/quic/core/quic_protocol.h"
+#include "net/quic/core/quic_packets.h"
#include "net/tools/quic/quic_spdy_client_stream.h"
namespace net {
class QuicConnection;
class QuicServerId;
-class QuicStream;
class QuicClientSession : public QuicClientSessionBase {
public:
@@ -48,7 +47,7 @@ class QuicClientSession : public QuicClientSessionBase {
const ProofVerifyDetails& verify_details) override;
// Performs a crypto handshake with the server.
- void CryptoConnect();
+ virtual void CryptoConnect();
// Returns the number of client hello messages that have been sent on the
// crypto stream. If the handshake has completed then this is one greater
diff --git a/chromium/net/tools/quic/quic_client_session_test.cc b/chromium/net/tools/quic/quic_client_session_test.cc
index 367d2fe5bce..25eaa193853 100644
--- a/chromium/net/tools/quic/quic_client_session_test.cc
+++ b/chromium/net/tools/quic/quic_client_session_test.cc
@@ -6,12 +6,12 @@
#include <vector>
-#include "base/memory/ptr_util.h"
#include "base/strings/stringprintf.h"
-#include "net/base/ip_endpoint.h"
#include "net/quic/core/crypto/aes_128_gcm_12_encrypter.h"
#include "net/quic/core/quic_flags.h"
#include "net/quic/core/spdy_utils.h"
+#include "net/quic/platform/api/quic_ptr_util.h"
+#include "net/quic/platform/api/quic_socket_address.h"
#include "net/quic/test_tools/crypto_test_utils.h"
#include "net/quic/test_tools/mock_quic_spdy_client_stream.h"
#include "net/quic/test_tools/quic_config_peer.h"
@@ -22,24 +22,8 @@
#include "net/tools/quic/quic_spdy_client_stream.h"
#include "testing/gtest/include/gtest/gtest.h"
-using base::StringPrintf;
using google::protobuf::implicit_cast;
-using net::test::ConstructEncryptedPacket;
-using net::test::ConstructMisFramedEncryptedPacket;
-using net::test::CryptoTestUtils;
-using net::test::DefaultQuicConfig;
-using net::test::MockQuicConnection;
-using net::test::MockQuicConnectionHelper;
-using net::test::MockQuicSpdyClientStream;
-using net::test::PacketSavingConnection;
-using net::test::QuicConnectionPeer;
-using net::test::QuicPacketCreatorPeer;
-using net::test::QuicSpdySessionPeer;
-using net::test::SupportedVersions;
-using net::test::TestPeerIPAddress;
-using net::test::kClientDataStreamId1;
-using net::test::kServerDataStreamId1;
-using net::test::kTestPort;
+using base::StringPrintf;
using std::string;
using testing::AnyNumber;
using testing::Invoke;
@@ -67,14 +51,14 @@ class TestQuicClientSession : public QuicClientSession {
push_promise_index) {}
std::unique_ptr<QuicSpdyClientStream> CreateClientStream() override {
- return base::MakeUnique<MockQuicSpdyClientStream>(GetNextOutgoingStreamId(),
- this);
+ return QuicMakeUnique<MockQuicSpdyClientStream>(GetNextOutgoingStreamId(),
+ this);
}
MockQuicSpdyClientStream* CreateIncomingDynamicStream(
QuicStreamId id) override {
MockQuicSpdyClientStream* stream = new MockQuicSpdyClientStream(id, this);
- ActivateStream(base::WrapUnique(stream));
+ ActivateStream(QuicWrapUnique(stream));
return stream;
}
};
@@ -259,8 +243,8 @@ static bool CheckForDecryptionError(QuicFramer* framer) {
// Regression test for b/17206611.
TEST_P(QuicClientSessionTest, InvalidPacketReceived) {
- IPEndPoint server_address(TestPeerIPAddress(), kTestPort);
- IPEndPoint client_address(TestPeerIPAddress(), kTestPort);
+ QuicSocketAddress server_address(TestPeerIPAddress(), kTestPort);
+ QuicSocketAddress client_address(TestPeerIPAddress(), kTestPort);
EXPECT_CALL(*connection_, ProcessUdpPacket(server_address, client_address, _))
.WillRepeatedly(Invoke(implicit_cast<MockQuicConnection*>(connection_),
@@ -298,8 +282,8 @@ TEST_P(QuicClientSessionTest, InvalidPacketReceived) {
// A packet with invalid framing should cause a connection to be closed.
TEST_P(QuicClientSessionTest, InvalidFramedPacketReceived) {
- IPEndPoint server_address(TestPeerIPAddress(), kTestPort);
- IPEndPoint client_address(TestPeerIPAddress(), kTestPort);
+ QuicSocketAddress server_address(TestPeerIPAddress(), kTestPort);
+ QuicSocketAddress client_address(TestPeerIPAddress(), kTestPort);
EXPECT_CALL(*connection_, ProcessUdpPacket(server_address, client_address, _))
.WillRepeatedly(Invoke(implicit_cast<MockQuicConnection*>(connection_),
@@ -308,9 +292,10 @@ TEST_P(QuicClientSessionTest, InvalidFramedPacketReceived) {
// Verify that a decryptable packet with bad frames does close the connection.
QuicConnectionId connection_id = session_->connection()->connection_id();
+ QuicVersionVector versions = {GetParam()};
std::unique_ptr<QuicEncryptedPacket> packet(ConstructMisFramedEncryptedPacket(
connection_id, false, false, false, kDefaultPathId, 100, "data",
- PACKET_8BYTE_CONNECTION_ID, PACKET_6BYTE_PACKET_NUMBER, nullptr,
+ PACKET_8BYTE_CONNECTION_ID, PACKET_6BYTE_PACKET_NUMBER, &versions,
Perspective::IS_SERVER));
std::unique_ptr<QuicReceivedPacket> received(
ConstructReceivedPacket(*packet, QuicTime::Zero()));
diff --git a/chromium/net/tools/quic/quic_client_test.cc b/chromium/net/tools/quic/quic_client_test.cc
index dd360de33a7..1037aedc62f 100644
--- a/chromium/net/tools/quic/quic_client_test.cc
+++ b/chromium/net/tools/quic/quic_client_test.cc
@@ -9,38 +9,47 @@
#include <memory>
-#include "base/strings/string_util.h"
+#include "base/files/file_enumerator.h"
+#include "base/files/file_util.h"
+#include "net/quic/platform/api/quic_text_utils.h"
#include "net/quic/test_tools/crypto_test_utils.h"
#include "net/quic/test_tools/quic_test_utils.h"
#include "net/tools/epoll_server/epoll_server.h"
#include "net/tools/quic/test_tools/quic_client_peer.h"
#include "testing/gtest/include/gtest/gtest.h"
-using net::EpollServer;
-using net::test::CryptoTestUtils;
-
namespace net {
namespace test {
namespace {
-int NumOpenFDs() {
- int number_of_open_fds = 0;
- char buf[256];
- struct dirent* dp;
-
- base::snprintf(buf, arraysize(buf), "/proc/%i/fd/", getpid());
- DIR* dir = opendir(buf);
- while ((dp = readdir(dir)) != NULL)
- number_of_open_fds++;
- closedir(dir);
+const char* kPathToFds = "/proc/self/fd";
+
+// Counts the number of open sockets for the current process.
+size_t NumOpenSocketFDs() {
+ base::FileEnumerator fd_entries(
+ base::FilePath(kPathToFds), false,
+ base::FileEnumerator::FILES | base::FileEnumerator::SHOW_SYM_LINKS);
+
+ size_t socket_count = 0;
+ for (base::FilePath entry = fd_entries.Next(); !entry.empty();
+ entry = fd_entries.Next()) {
+ base::FilePath fd_path;
+ if (!base::ReadSymbolicLink(entry, &fd_path)) {
+ continue;
+ }
+ if (QuicTextUtils::StartsWith(fd_path.value(), "socket:")) {
+ socket_count++;
+ }
+ }
- return number_of_open_fds;
+ return socket_count;
}
// Creates a new QuicClient and Initializes it. Caller is responsible for
// deletion.
QuicClient* CreateAndInitializeQuicClient(EpollServer* eps, uint16_t port) {
- IPEndPoint server_address(IPEndPoint(net::test::Loopback4(), port));
+ QuicSocketAddress server_address(
+ QuicSocketAddress(QuicIpAddress::Loopback4(), port));
QuicServerId server_id("hostname", server_address.port(),
PRIVACY_MODE_DISABLED);
QuicVersionVector versions = AllSupportedVersions();
@@ -52,6 +61,9 @@ QuicClient* CreateAndInitializeQuicClient(EpollServer* eps, uint16_t port) {
}
TEST(QuicClientTest, DoNotLeakFDs) {
+ // Make sure that the QuicClient doesn't leak socket FDs. Doing so could cause
+ // port exhaustion in long running processes which repeatedly create clients.
+
// Create a ProofVerifier before counting the number of open FDs to work
// around some ASAN weirdness.
CryptoTestUtils::ProofVerifierForTesting().reset();
@@ -61,7 +73,7 @@ TEST(QuicClientTest, DoNotLeakFDs) {
// Record initial number of FDs, after creation of EpollServer.
EpollServer eps;
- int number_of_open_fds = NumOpenFDs();
+ size_t number_of_open_fds = NumOpenSocketFDs();
// Create a number of clients, initialize them, and verify this has resulted
// in additional FDs being opened.
@@ -71,11 +83,11 @@ TEST(QuicClientTest, DoNotLeakFDs) {
CreateAndInitializeQuicClient(&eps, net::test::kTestPort + i));
// Initializing the client will create a new FD.
- EXPECT_LT(number_of_open_fds, NumOpenFDs());
+ EXPECT_LT(number_of_open_fds, NumOpenSocketFDs());
}
// The FDs created by the QuicClients should now be closed.
- EXPECT_EQ(number_of_open_fds, NumOpenFDs());
+ EXPECT_EQ(number_of_open_fds, NumOpenSocketFDs());
}
TEST(QuicClientTest, CreateAndCleanUpUDPSockets) {
@@ -84,22 +96,22 @@ TEST(QuicClientTest, CreateAndCleanUpUDPSockets) {
CryptoTestUtils::ProofVerifierForTesting().reset();
EpollServer eps;
- int number_of_open_fds = NumOpenFDs();
+ size_t number_of_open_fds = NumOpenSocketFDs();
std::unique_ptr<QuicClient> client(
CreateAndInitializeQuicClient(&eps, net::test::kTestPort));
- EXPECT_EQ(number_of_open_fds + 1, NumOpenFDs());
+ EXPECT_EQ(number_of_open_fds + 1, NumOpenSocketFDs());
// Create more UDP sockets.
EXPECT_TRUE(QuicClientPeer::CreateUDPSocketAndBind(client.get()));
- EXPECT_EQ(number_of_open_fds + 2, NumOpenFDs());
+ EXPECT_EQ(number_of_open_fds + 2, NumOpenSocketFDs());
EXPECT_TRUE(QuicClientPeer::CreateUDPSocketAndBind(client.get()));
- EXPECT_EQ(number_of_open_fds + 3, NumOpenFDs());
+ EXPECT_EQ(number_of_open_fds + 3, NumOpenSocketFDs());
// Clean up UDP sockets.
QuicClientPeer::CleanUpUDPSocket(client.get(), client->GetLatestFD());
- EXPECT_EQ(number_of_open_fds + 2, NumOpenFDs());
+ EXPECT_EQ(number_of_open_fds + 2, NumOpenSocketFDs());
QuicClientPeer::CleanUpUDPSocket(client.get(), client->GetLatestFD());
- EXPECT_EQ(number_of_open_fds + 1, NumOpenFDs());
+ EXPECT_EQ(number_of_open_fds + 1, NumOpenSocketFDs());
}
} // namespace
diff --git a/chromium/net/tools/quic/quic_default_packet_writer.cc b/chromium/net/tools/quic/quic_default_packet_writer.cc
index 66a6440c535..e7aa91df49e 100644
--- a/chromium/net/tools/quic/quic_default_packet_writer.cc
+++ b/chromium/net/tools/quic/quic_default_packet_writer.cc
@@ -4,7 +4,7 @@
#include "net/tools/quic/quic_default_packet_writer.h"
-#include "net/tools/quic/quic_socket_utils.h"
+#include "net/tools/quic/platform/impl/quic_socket_utils.h"
namespace net {
@@ -13,12 +13,13 @@ QuicDefaultPacketWriter::QuicDefaultPacketWriter(int fd)
QuicDefaultPacketWriter::~QuicDefaultPacketWriter() {}
-WriteResult QuicDefaultPacketWriter::WritePacket(const char* buffer,
- size_t buf_len,
- const IPAddress& self_address,
- const IPEndPoint& peer_address,
- PerPacketOptions* options) {
- DCHECK(!IsWriteBlocked());
+WriteResult QuicDefaultPacketWriter::WritePacket(
+ const char* buffer,
+ size_t buf_len,
+ const QuicIpAddress& self_address,
+ const QuicSocketAddress& peer_address,
+ PerPacketOptions* options) {
+ DCHECK(!write_blocked_);
DCHECK(nullptr == options)
<< "QuicDefaultPacketWriter does not accept any options.";
WriteResult result = QuicSocketUtils::WritePacket(fd_, buffer, buf_len,
@@ -42,8 +43,12 @@ void QuicDefaultPacketWriter::SetWritable() {
}
QuicByteCount QuicDefaultPacketWriter::GetMaxPacketSize(
- const IPEndPoint& peer_address) const {
+ const QuicSocketAddress& peer_address) const {
return kMaxPacketSize;
}
+void QuicDefaultPacketWriter::set_write_blocked(bool is_blocked) {
+ write_blocked_ = is_blocked;
+}
+
} // namespace net
diff --git a/chromium/net/tools/quic/quic_default_packet_writer.h b/chromium/net/tools/quic/quic_default_packet_writer.h
index e695637b470..19d75d4b30d 100644
--- a/chromium/net/tools/quic/quic_default_packet_writer.h
+++ b/chromium/net/tools/quic/quic_default_packet_writer.h
@@ -8,9 +8,9 @@
#include <stddef.h>
#include "base/macros.h"
-#include "net/base/ip_endpoint.h"
-#include "net/base/net_export.h"
#include "net/quic/core/quic_packet_writer.h"
+#include "net/quic/platform/api/quic_export.h"
+#include "net/quic/platform/api/quic_socket_address.h"
namespace net {
@@ -18,7 +18,7 @@ struct WriteResult;
// Default packet writer which wraps QuicSocketUtils WritePacket.
-class NET_EXPORT_PRIVATE QuicDefaultPacketWriter : public QuicPacketWriter {
+class QUIC_EXPORT_PRIVATE QuicDefaultPacketWriter : public QuicPacketWriter {
public:
explicit QuicDefaultPacketWriter(int fd);
~QuicDefaultPacketWriter() override;
@@ -26,18 +26,19 @@ class NET_EXPORT_PRIVATE QuicDefaultPacketWriter : public QuicPacketWriter {
// QuicPacketWriter
WriteResult WritePacket(const char* buffer,
size_t buf_len,
- const IPAddress& self_address,
- const IPEndPoint& peer_address,
+ const QuicIpAddress& self_address,
+ const QuicSocketAddress& peer_address,
PerPacketOptions* options) override;
bool IsWriteBlockedDataBuffered() const override;
bool IsWriteBlocked() const override;
void SetWritable() override;
- QuicByteCount GetMaxPacketSize(const IPEndPoint& peer_address) const override;
+ QuicByteCount GetMaxPacketSize(
+ const QuicSocketAddress& peer_address) const override;
void set_fd(int fd) { fd_ = fd; }
protected:
- void set_write_blocked(bool is_blocked) { write_blocked_ = is_blocked; }
+ void set_write_blocked(bool is_blocked);
int fd() { return fd_; }
private:
diff --git a/chromium/net/tools/quic/quic_dispatcher.cc b/chromium/net/tools/quic/quic_dispatcher.cc
index 124148c84e1..18f79ac373d 100644
--- a/chromium/net/tools/quic/quic_dispatcher.cc
+++ b/chromium/net/tools/quic/quic_dispatcher.cc
@@ -7,23 +7,20 @@
#include <utility>
#include "base/debug/stack_trace.h"
-#include "base/logging.h"
#include "base/macros.h"
-#include "base/memory/ptr_util.h"
#include "net/quic/core/crypto/quic_random.h"
-#include "net/quic/core/quic_bug_tracker.h"
#include "net/quic/core/quic_flags.h"
#include "net/quic/core/quic_utils.h"
-
+#include "net/quic/platform/api/quic_bug_tracker.h"
+#include "net/quic/platform/api/quic_logging.h"
+#include "net/quic/platform/api/quic_ptr_util.h"
#include "net/tools/quic/chlo_extractor.h"
#include "net/tools/quic/quic_per_connection_packet_writer.h"
#include "net/tools/quic/quic_simple_server_session.h"
-#include "net/tools/quic/quic_simple_server_session.h"
#include "net/tools/quic/quic_time_wait_list_manager.h"
#include "net/tools/quic/stateless_rejector.h"
using base::StringPiece;
-using std::list;
using std::string;
namespace net {
@@ -58,10 +55,10 @@ class PacketCollector : public QuicPacketCreator::DelegateInterface {
void OnSerializedPacket(SerializedPacket* serialized_packet) override {
// Make a copy of the serialized packet to send later.
packets_.push_back(std::unique_ptr<QuicEncryptedPacket>(
- new QuicEncryptedPacket(QuicUtils::CopyBuffer(*serialized_packet),
+ new QuicEncryptedPacket(CopyBuffer(*serialized_packet),
serialized_packet->encrypted_length, true)));
serialized_packet->encrypted_buffer = nullptr;
- QuicUtils::DeleteFrames(&(serialized_packet->retransmittable_frames));
+ DeleteFrames(&(serialized_packet->retransmittable_frames));
serialized_packet->retransmittable_frames.clear();
}
@@ -90,7 +87,6 @@ class StatelessConnectionTerminator {
framer_(framer),
creator_(connection_id,
framer,
- helper->GetRandomGenerator(),
helper->GetBufferAllocator(),
&collector_),
time_wait_list_manager_(time_wait_list_manager) {}
@@ -158,7 +154,7 @@ class StatelessConnectionTerminator {
class ChloValidator : public ChloExtractor::Delegate {
public:
ChloValidator(QuicCryptoServerStream::Helper* helper,
- IPEndPoint self_address,
+ QuicSocketAddress self_address,
StatelessRejector* rejector)
: helper_(helper),
self_address_(self_address),
@@ -183,7 +179,7 @@ class ChloValidator : public ChloExtractor::Delegate {
private:
QuicCryptoServerStream::Helper* helper_; // Unowned.
- IPEndPoint self_address_;
+ QuicSocketAddress self_address_;
StatelessRejector* rejector_; // Unowned.
bool can_accept_;
string error_details_;
@@ -229,8 +225,8 @@ void QuicDispatcher::InitializeWithWriter(QuicPacketWriter* writer) {
time_wait_list_manager_.reset(CreateQuicTimeWaitListManager());
}
-void QuicDispatcher::ProcessPacket(const IPEndPoint& server_address,
- const IPEndPoint& client_address,
+void QuicDispatcher::ProcessPacket(const QuicSocketAddress& server_address,
+ const QuicSocketAddress& client_address,
const QuicReceivedPacket& packet) {
current_server_address_ = server_address;
current_client_address_ = client_address;
@@ -273,14 +269,14 @@ bool QuicDispatcher::OnUnauthenticatedPublicHeader(
return false;
}
- if (FLAGS_quic_buffer_packets_after_chlo &&
+ if (FLAGS_quic_reloadable_flag_quic_buffer_packets_after_chlo &&
buffered_packets_.HasChloForConnection(connection_id)) {
BufferEarlyPacket(connection_id);
return false;
}
// Check if we are buffering packets for this connection ID
- if (FLAGS_enable_async_get_proof &&
+ if (FLAGS_quic_reloadable_flag_enable_async_get_proof &&
(temporarily_buffered_connections_.find(connection_id) !=
temporarily_buffered_connections_.end())) {
// This packet was received while the a CHLO for the same connection ID was
@@ -312,6 +308,11 @@ bool QuicDispatcher::OnUnauthenticatedPublicHeader(
QuicVersion version = GetSupportedVersions().front();
if (header.version_flag) {
QuicVersion packet_version = header.versions.front();
+ if (FLAGS_quic_reloadable_flag_quic_fix_version_manager &&
+ framer_.supported_versions() != GetSupportedVersions()) {
+ // Reset framer's version if version flags change in flight.
+ framer_.SetSupportedVersions(GetSupportedVersions());
+ }
if (!framer_.IsSupportedVersion(packet_version)) {
if (ShouldCreateSessionForUnknownVersion(framer_.last_version_tag())) {
return true;
@@ -370,12 +371,12 @@ void QuicDispatcher::ProcessUnauthenticatedHeaderFate(
case kFateTimeWait:
// MaybeRejectStatelessly or OnExpiredPackets might have already added the
// connection to time wait, in which case it should not be added again.
- if (!FLAGS_quic_use_cheap_stateless_rejects ||
+ if (!FLAGS_quic_reloadable_flag_quic_use_cheap_stateless_rejects ||
!time_wait_list_manager_->IsConnectionIdInTimeWait(connection_id)) {
// Add this connection_id to the time-wait state, to safely reject
// future packets.
- DVLOG(1) << "Adding connection ID " << connection_id
- << "to time-wait list.";
+ QUIC_DLOG(INFO) << "Adding connection ID " << connection_id
+ << "to time-wait list.";
time_wait_list_manager_->AddConnectionIdToTimeWait(
connection_id, framer_.version(),
/*connection_rejected_statelessly=*/false, nullptr);
@@ -385,7 +386,7 @@ void QuicDispatcher::ProcessUnauthenticatedHeaderFate(
current_server_address_, current_client_address_, connection_id,
packet_number, *current_packet_);
- if (FLAGS_enable_async_get_proof) {
+ if (FLAGS_quic_reloadable_flag_enable_async_get_proof) {
// Any packets which were buffered while the stateless rejector logic
// was running should be discarded. Do not inform the time wait list
// manager, which should already have a made a decision about sending a
@@ -422,13 +423,15 @@ QuicDispatcher::QuicPacketFate QuicDispatcher::ValidityChecks(
// set. Since this may be a client continuing a connection we lost track of
// via server restart, send a rejection to fast-fail the connection.
if (!header.public_header.version_flag) {
- DVLOG(1) << "Packet without version arrived for unknown connection ID "
- << header.public_header.connection_id;
+ QUIC_DLOG(INFO)
+ << "Packet without version arrived for unknown connection ID "
+ << header.public_header.connection_id;
return kFateTimeWait;
}
// Check that the sequence number is within the range that the client is
// expected to send before receiving a response from the server.
+ const int kInvalidPacketNumber = 0;
if (header.packet_number == kInvalidPacketNumber ||
header.packet_number > kMaxReasonableInitialPacketNumber) {
return kFateTimeWait;
@@ -493,14 +496,14 @@ void QuicDispatcher::OnConnectionClosed(QuicConnectionId connection_id,
if (it == session_map_.end()) {
QUIC_BUG << "ConnectionId " << connection_id
<< " does not exist in the session map. Error: "
- << QuicUtils::ErrorToString(error);
+ << QuicErrorCodeToString(error);
QUIC_BUG << base::debug::StackTrace().ToString();
return;
}
DVLOG_IF(1, error != QUIC_NO_ERROR)
<< "Closing connection (" << connection_id
- << ") due to error: " << QuicUtils::ErrorToString(error)
+ << ") due to error: " << QuicErrorCodeToString(error)
<< ", with details: " << error_details;
if (closed_session_list_.empty()) {
@@ -528,7 +531,8 @@ void QuicDispatcher::OnWriteBlocked(
void QuicDispatcher::OnConnectionAddedToTimeWaitList(
QuicConnectionId connection_id) {
- DVLOG(1) << "Connection " << connection_id << " added to time wait list.";
+ QUIC_DLOG(INFO) << "Connection " << connection_id
+ << " added to time wait list.";
}
void QuicDispatcher::OnPacket() {}
@@ -536,7 +540,7 @@ void QuicDispatcher::OnPacket() {}
void QuicDispatcher::OnError(QuicFramer* framer) {
QuicErrorCode error = framer->error();
SetLastError(error);
- DVLOG(1) << QuicUtils::ErrorToString(error);
+ QUIC_DLOG(INFO) << QuicErrorCodeToString(error);
}
bool QuicDispatcher::ShouldCreateSessionForUnknownVersion(QuicTag version_tag) {
@@ -549,7 +553,7 @@ bool QuicDispatcher::OnProtocolVersionMismatch(
current_connection_id_) &&
!ShouldCreateSessionForUnknownVersion(framer_.last_version_tag()))
<< "Unexpected version mismatch: "
- << QuicUtils::TagToString(framer_.last_version_tag());
+ << QuicTagToString(framer_.last_version_tag());
// Keep processing after protocol mismatch - this will be dealt with by the
// time wait list or connection that we will create.
@@ -656,9 +660,8 @@ void QuicDispatcher::ProcessBufferedChlos(size_t max_connections_to_create) {
}
QuicSession* session =
CreateQuicSession(connection_id, packets.front().client_address);
- DVLOG(1) << "Created new session for " << connection_id;
- session_map_.insert(
- std::make_pair(connection_id, base::WrapUnique(session)));
+ QUIC_DLOG(INFO) << "Created new session for " << connection_id;
+ session_map_.insert(std::make_pair(connection_id, QuicWrapUnique(session)));
DeliverPacketsToSession(packets, session);
}
}
@@ -680,8 +683,8 @@ bool QuicDispatcher::HasBufferedPackets(QuicConnectionId connection_id) {
void QuicDispatcher::OnBufferPacketFailure(EnqueuePacketResult result,
QuicConnectionId connection_id) {
- DVLOG(1) << "Fail to buffer packet on connection " << connection_id
- << " because of " << result;
+ QUIC_DLOG(INFO) << "Fail to buffer packet on connection " << connection_id
+ << " because of " << result;
}
void QuicDispatcher::OnConnectionRejectedStatelessly() {}
@@ -699,7 +702,8 @@ QuicTimeWaitListManager* QuicDispatcher::CreateQuicTimeWaitListManager() {
void QuicDispatcher::BufferEarlyPacket(QuicConnectionId connection_id) {
bool is_new_connection = !buffered_packets_.HasBufferedPackets(connection_id);
- if (FLAGS_quic_create_session_after_insertion && is_new_connection &&
+ if (FLAGS_quic_reloadable_flag_quic_create_session_after_insertion &&
+ is_new_connection &&
!ShouldCreateOrBufferPacketForConnection(connection_id)) {
return;
}
@@ -708,19 +712,20 @@ void QuicDispatcher::BufferEarlyPacket(QuicConnectionId connection_id) {
current_client_address_, /*is_chlo=*/false);
if (rs != EnqueuePacketResult::SUCCESS) {
OnBufferPacketFailure(rs, connection_id);
- } else if (!FLAGS_quic_create_session_after_insertion && is_new_connection) {
+ } else if (!FLAGS_quic_reloadable_flag_quic_create_session_after_insertion &&
+ is_new_connection) {
ShouldCreateOrBufferPacketForConnection(connection_id);
}
}
void QuicDispatcher::ProcessChlo() {
- if (FLAGS_quic_create_session_after_insertion &&
+ if (FLAGS_quic_reloadable_flag_quic_create_session_after_insertion &&
!buffered_packets_.HasBufferedPackets(current_connection_id_) &&
!ShouldCreateOrBufferPacketForConnection(current_connection_id_)) {
return;
}
-
- if (FLAGS_quic_limit_num_new_sessions_per_epoll_loop &&
+ if (FLAGS_quic_allow_chlo_buffering &&
+ FLAGS_quic_reloadable_flag_quic_limit_num_new_sessions_per_epoll_loop &&
new_sessions_allowed_per_event_loop_ <= 0) {
// Can't create new session any more. Wait till next event loop.
if (!buffered_packets_.HasChloForConnection(current_connection_id_)) {
@@ -735,8 +740,9 @@ void QuicDispatcher::ProcessChlo() {
current_client_address_, /*is_chlo=*/true);
if (rs != EnqueuePacketResult::SUCCESS) {
OnBufferPacketFailure(rs, current_connection_id_);
- } else if (!FLAGS_quic_create_session_after_insertion &&
- is_new_connection) {
+ } else if (
+ !FLAGS_quic_reloadable_flag_quic_create_session_after_insertion &&
+ is_new_connection) {
ShouldCreateOrBufferPacketForConnection(current_connection_id_);
}
}
@@ -745,13 +751,14 @@ void QuicDispatcher::ProcessChlo() {
// Creates a new session and process all buffered packets for this connection.
QuicSession* session =
CreateQuicSession(current_connection_id_, current_client_address_);
- DVLOG(1) << "Created new session for " << current_connection_id_;
+ QUIC_DLOG(INFO) << "Created new session for " << current_connection_id_;
session_map_.insert(
- std::make_pair(current_connection_id_, base::WrapUnique(session)));
+ std::make_pair(current_connection_id_, QuicWrapUnique(session)));
std::list<BufferedPacket> packets =
buffered_packets_.DeliverPackets(current_connection_id_);
// Check if CHLO is the first packet arrived on this connection.
- if (!FLAGS_quic_create_session_after_insertion && packets.empty()) {
+ if (!FLAGS_quic_reloadable_flag_quic_create_session_after_insertion &&
+ packets.empty()) {
ShouldCreateOrBufferPacketForConnection(current_connection_id_);
}
// Process CHLO at first.
@@ -761,7 +768,7 @@ void QuicDispatcher::ProcessChlo() {
// Do this even when flag is off because there might be still some packets
// buffered in the store before flag is turned off.
DeliverPacketsToSession(packets, session);
- if (FLAGS_quic_limit_num_new_sessions_per_epoll_loop) {
+ if (FLAGS_quic_reloadable_flag_quic_limit_num_new_sessions_per_epoll_loop) {
--new_sessions_allowed_per_event_loop_;
}
}
@@ -818,8 +825,8 @@ class StatelessRejectorProcessDoneCallback
private:
QuicDispatcher* dispatcher_;
- IPEndPoint current_client_address_;
- IPEndPoint current_server_address_;
+ QuicSocketAddress current_client_address_;
+ QuicSocketAddress current_server_address_;
std::unique_ptr<QuicReceivedPacket> current_packet_;
QuicPacketNumber packet_number_;
QuicVersion first_version_;
@@ -828,12 +835,13 @@ class StatelessRejectorProcessDoneCallback
void QuicDispatcher::MaybeRejectStatelessly(QuicConnectionId connection_id,
const QuicPacketHeader& header) {
// TODO(rch): This logic should probably live completely inside the rejector.
- if (!FLAGS_quic_use_cheap_stateless_rejects ||
- !FLAGS_enable_quic_stateless_reject_support ||
- header.public_header.versions.front() <= QUIC_VERSION_32 ||
+ if (!FLAGS_quic_allow_chlo_buffering ||
+ !FLAGS_quic_reloadable_flag_quic_use_cheap_stateless_rejects ||
+ !FLAGS_quic_reloadable_flag_enable_quic_stateless_reject_support ||
!ShouldAttemptCheapStatelessRejection()) {
// Not use cheap stateless reject.
- if (!ChloExtractor::Extract(*current_packet_, GetSupportedVersions(),
+ if (FLAGS_quic_allow_chlo_buffering &&
+ !ChloExtractor::Extract(*current_packet_, GetSupportedVersions(),
nullptr)) {
// Buffer non-CHLO packets.
ProcessUnauthenticatedHeaderFate(kFateBuffer, connection_id,
@@ -880,7 +888,7 @@ void QuicDispatcher::MaybeRejectStatelessly(QuicConnectionId connection_id,
}
// Insert into set of connection IDs to buffer
- if (FLAGS_enable_async_get_proof) {
+ if (FLAGS_quic_reloadable_flag_enable_async_get_proof) {
const bool ok =
temporarily_buffered_connections_.insert(connection_id).second;
QUIC_BUG_IF(!ok)
@@ -897,12 +905,12 @@ void QuicDispatcher::MaybeRejectStatelessly(QuicConnectionId connection_id,
void QuicDispatcher::OnStatelessRejectorProcessDone(
std::unique_ptr<StatelessRejector> rejector,
- const IPEndPoint& current_client_address,
- const IPEndPoint& current_server_address,
+ const QuicSocketAddress& current_client_address,
+ const QuicSocketAddress& current_server_address,
std::unique_ptr<QuicReceivedPacket> current_packet,
QuicPacketNumber packet_number,
QuicVersion first_version) {
- if (FLAGS_enable_async_get_proof) {
+ if (FLAGS_quic_reloadable_flag_enable_async_get_proof) {
// Stop buffering packets on this connection
const auto num_erased =
temporarily_buffered_connections_.erase(rejector->connection_id());
diff --git a/chromium/net/tools/quic/quic_dispatcher.h b/chromium/net/tools/quic/quic_dispatcher.h
index 229362975f6..527eaa5bc10 100644
--- a/chromium/net/tools/quic/quic_dispatcher.h
+++ b/chromium/net/tools/quic/quic_dispatcher.h
@@ -13,7 +13,6 @@
#include <vector>
#include "base/macros.h"
-#include "net/base/ip_endpoint.h"
#include "net/base/linked_hash_map.h"
#include "net/quic/core/crypto/quic_compressed_certs_cache.h"
#include "net/quic/core/crypto/quic_random.h"
@@ -21,22 +20,23 @@
#include "net/quic/core/quic_buffered_packet_store.h"
#include "net/quic/core/quic_connection.h"
#include "net/quic/core/quic_crypto_server_stream.h"
-#include "net/quic/core/quic_protocol.h"
+#include "net/quic/core/quic_packets.h"
#include "net/quic/core/quic_session.h"
+#include "net/quic/core/quic_version_manager.h"
+#include "net/quic/platform/api/quic_socket_address.h"
#include "net/tools/quic/quic_process_packet_interface.h"
#include "net/tools/quic/quic_time_wait_list_manager.h"
#include "net/tools/quic/stateless_rejector.h"
namespace net {
-
-class QuicConfig;
-class QuicCryptoServerConfig;
-
namespace test {
class QuicDispatcherPeer;
} // namespace test
+class QuicConfig;
+class QuicCryptoServerConfig;
+
class QuicDispatcher : public QuicTimeWaitListManager::Visitor,
public ProcessPacketInterface,
public QuicBlockedWriterInterface,
@@ -63,8 +63,8 @@ class QuicDispatcher : public QuicTimeWaitListManager::Visitor,
// Process the incoming packet by creating a new session, passing it to
// an existing session, or passing it to the time wait list.
- void ProcessPacket(const IPEndPoint& server_address,
- const IPEndPoint& client_address,
+ void ProcessPacket(const QuicSocketAddress& server_address,
+ const QuicSocketAddress& client_address,
const QuicReceivedPacket& packet) override;
// Called when the socket becomes writable to allow queued writes to happen.
@@ -89,9 +89,8 @@ class QuicDispatcher : public QuicTimeWaitListManager::Visitor,
void OnWriteBlocked(QuicBlockedWriterInterface* blocked_writer) override;
// QuicTimeWaitListManager::Visitor interface implementation
- // Called whenever the time wait std::list manager adds a new connection to
- // the
- // time-wait std::list.
+ // Called whenever the time wait list manager adds a new connection to the
+ // time-wait list.
void OnConnectionAddedToTimeWaitList(QuicConnectionId connection_id) override;
using SessionMap =
@@ -160,8 +159,9 @@ class QuicDispatcher : public QuicTimeWaitListManager::Visitor,
virtual bool HasChlosBuffered() const;
protected:
- virtual QuicSession* CreateQuicSession(QuicConnectionId connection_id,
- const IPEndPoint& client_address) = 0;
+ virtual QuicSession* CreateQuicSession(
+ QuicConnectionId connection_id,
+ const QuicSocketAddress& client_address) = 0;
// Called when a connection is rejected statelessly.
virtual void OnConnectionRejectedStatelessly();
@@ -212,8 +212,12 @@ class QuicDispatcher : public QuicTimeWaitListManager::Visitor,
const QuicVersionVector& GetSupportedVersions();
QuicConnectionId current_connection_id() { return current_connection_id_; }
- const IPEndPoint& current_server_address() { return current_server_address_; }
- const IPEndPoint& current_client_address() { return current_client_address_; }
+ const QuicSocketAddress& current_server_address() {
+ return current_server_address_;
+ }
+ const QuicSocketAddress& current_client_address() {
+ return current_client_address_;
+ }
const QuicReceivedPacket& current_packet() { return *current_packet_; }
const QuicConfig& config() const { return config_; }
@@ -270,7 +274,7 @@ class QuicDispatcher : public QuicTimeWaitListManager::Visitor,
QuicConnectionId connection_id);
private:
- friend class net::test::QuicDispatcherPeer;
+ friend class test::QuicDispatcherPeer;
friend class StatelessRejectorProcessDoneCallback;
typedef std::unordered_set<QuicConnectionId> QuicConnectionIdSet;
@@ -305,8 +309,8 @@ class QuicDispatcher : public QuicTimeWaitListManager::Visitor,
// Invoked when StatelessRejector::Process completes.
void OnStatelessRejectorProcessDone(
std::unique_ptr<StatelessRejector> rejector,
- const IPEndPoint& current_client_address,
- const IPEndPoint& current_server_address,
+ const QuicSocketAddress& current_client_address,
+ const QuicSocketAddress& current_server_address,
std::unique_ptr<QuicReceivedPacket> current_packet,
QuicPacketNumber packet_number,
QuicVersion first_version);
@@ -338,7 +342,7 @@ class QuicDispatcher : public QuicTimeWaitListManager::Visitor,
// Entity that manages connection_ids in time wait state.
std::unique_ptr<QuicTimeWaitListManager> time_wait_list_manager_;
- // The std::list of closed but not-yet-deleted sessions.
+ // The list of closed but not-yet-deleted sessions.
std::vector<std::unique_ptr<QuicSession>> closed_session_list_;
// The helper used for all connections.
@@ -366,8 +370,8 @@ class QuicDispatcher : public QuicTimeWaitListManager::Visitor,
QuicConnectionIdSet temporarily_buffered_connections_;
// Information about the packet currently being handled.
- IPEndPoint current_client_address_;
- IPEndPoint current_server_address_;
+ QuicSocketAddress current_client_address_;
+ QuicSocketAddress current_server_address_;
const QuicReceivedPacket* current_packet_;
QuicConnectionId current_connection_id_;
diff --git a/chromium/net/tools/quic/quic_dispatcher_test.cc b/chromium/net/tools/quic/quic_dispatcher_test.cc
index 46ad07e9b26..e2d7c1b0016 100644
--- a/chromium/net/tools/quic/quic_dispatcher_test.cc
+++ b/chromium/net/tools/quic/quic_dispatcher_test.cc
@@ -9,13 +9,14 @@
#include <string>
#include "base/macros.h"
-#include "base/strings/string_number_conversions.h"
#include "net/quic/core/crypto/crypto_handshake.h"
#include "net/quic/core/crypto/quic_crypto_server_config.h"
#include "net/quic/core/crypto/quic_random.h"
#include "net/quic/core/quic_crypto_stream.h"
#include "net/quic/core/quic_flags.h"
#include "net/quic/core/quic_utils.h"
+#include "net/quic/platform/api/quic_logging.h"
+#include "net/quic/platform/api/quic_str_cat.h"
#include "net/quic/test_tools/crypto_test_utils.h"
#include "net/quic/test_tools/fake_proof_source.h"
#include "net/quic/test_tools/quic_buffered_packet_store_peer.h"
@@ -37,14 +38,7 @@
#include "testing/gmock_mutant.h"
#include "testing/gtest/include/gtest/gtest.h"
-using base::IntToString;
using base::StringPiece;
-using net::EpollServer;
-using net::test::ConstructEncryptedPacket;
-using net::test::CryptoTestUtils;
-using net::test::MockQuicConnection;
-using net::test::MockQuicConnectionHelper;
-using std::ostream;
using std::string;
using testing::CreateFunctor;
using testing::DoAll;
@@ -92,7 +86,8 @@ class TestQuicSpdyServerSession : public QuicServerSessionBase {
QuicCompressedCertsCache* compressed_certs_cache) override {
return new QuicCryptoServerStream(
crypto_config, compressed_certs_cache,
- FLAGS_enable_quic_stateless_reject_support, this, stream_helper());
+ FLAGS_quic_reloadable_flag_enable_quic_stateless_reject_support, this,
+ stream_helper());
}
void SetCryptoStream(QuicCryptoServerStream* crypto_stream) {
@@ -133,7 +128,7 @@ class TestDispatcher : public QuicDispatcher {
MOCK_METHOD2(CreateQuicSession,
QuicServerSessionBase*(QuicConnectionId connection_id,
- const IPEndPoint& client_address));
+ const QuicSocketAddress& client_address));
MOCK_METHOD1(ShouldCreateOrBufferPacketForConnection,
bool(QuicConnectionId connection_id));
@@ -159,7 +154,7 @@ class MockServerConnection : public MockQuicConnection {
dispatcher_(dispatcher) {}
void UnregisterOnConnectionClosed() {
- LOG(ERROR) << "Unregistering " << connection_id();
+ QUIC_LOG(ERROR) << "Unregistering " << connection_id();
dispatcher_->OnConnectionClosed(connection_id(), QUIC_NO_ERROR,
"Unregistering.");
}
@@ -211,7 +206,7 @@ class QuicDispatcherTest : public ::testing::Test {
// Process a packet with an 8 byte connection id,
// 6 byte packet number, default path id, and packet number 1,
// using the first supported version.
- void ProcessPacket(IPEndPoint client_address,
+ void ProcessPacket(QuicSocketAddress client_address,
QuicConnectionId connection_id,
bool has_version_flag,
bool has_multipath_flag,
@@ -223,7 +218,7 @@ class QuicDispatcherTest : public ::testing::Test {
// Process a packet with a default path id, and packet number 1,
// using the first supported version.
- void ProcessPacket(IPEndPoint client_address,
+ void ProcessPacket(QuicSocketAddress client_address,
QuicConnectionId connection_id,
bool has_version_flag,
bool has_multipath_flag,
@@ -236,7 +231,7 @@ class QuicDispatcherTest : public ::testing::Test {
}
// Process a packet using the first supported version.
- void ProcessPacket(IPEndPoint client_address,
+ void ProcessPacket(QuicSocketAddress client_address,
QuicConnectionId connection_id,
bool has_version_flag,
bool has_multipath_flag,
@@ -251,7 +246,7 @@ class QuicDispatcherTest : public ::testing::Test {
}
// Processes a packet.
- void ProcessPacket(IPEndPoint client_address,
+ void ProcessPacket(QuicSocketAddress client_address,
QuicConnectionId connection_id,
bool has_version_flag,
QuicVersion version,
@@ -292,7 +287,7 @@ class QuicDispatcherTest : public ::testing::Test {
QuicDispatcher* dispatcher,
const QuicConfig& config,
QuicConnectionId connection_id,
- const IPEndPoint& client_address,
+ const QuicSocketAddress& client_address,
MockQuicConnectionHelper* helper,
MockAlarmFactory* alarm_factory,
const QuicCryptoServerConfig* crypto_config,
@@ -333,7 +328,7 @@ class QuicDispatcherTest : public ::testing::Test {
QuicConfig config_;
QuicVersionManager version_manager_;
QuicCryptoServerConfig crypto_config_;
- IPEndPoint server_address_;
+ QuicSocketAddress server_address_;
std::unique_ptr<TestDispatcher> dispatcher_;
MockTimeWaitListManager* time_wait_list_manager_;
TestQuicSpdyServerSession* session1_;
@@ -343,8 +338,8 @@ class QuicDispatcherTest : public ::testing::Test {
};
TEST_F(QuicDispatcherTest, ProcessPackets) {
- IPEndPoint client_address(net::test::Loopback4(), 1);
- server_address_ = IPEndPoint(net::test::Any4(), 5);
+ QuicSocketAddress client_address(QuicIpAddress::Loopback4(), 1);
+ server_address_ = QuicSocketAddress(QuicIpAddress::Any4(), 5);
EXPECT_CALL(*dispatcher_, CreateQuicSession(1, client_address))
.WillOnce(testing::Return(CreateSession(
@@ -379,8 +374,8 @@ TEST_F(QuicDispatcherTest, ProcessPackets) {
}
TEST_F(QuicDispatcherTest, StatelessVersionNegotiation) {
- IPEndPoint client_address(net::test::Loopback4(), 1);
- server_address_ = IPEndPoint(net::test::Any4(), 5);
+ QuicSocketAddress client_address(QuicIpAddress::Loopback4(), 1);
+ server_address_ = QuicSocketAddress(QuicIpAddress::Any4(), 5);
EXPECT_CALL(*dispatcher_, CreateQuicSession(1, client_address)).Times(0);
QuicVersion version = static_cast<QuicVersion>(QuicVersionMin() - 1);
@@ -389,7 +384,7 @@ TEST_F(QuicDispatcherTest, StatelessVersionNegotiation) {
}
TEST_F(QuicDispatcherTest, Shutdown) {
- IPEndPoint client_address(net::test::Loopback4(), 1);
+ QuicSocketAddress client_address(QuicIpAddress::Loopback4(), 1);
EXPECT_CALL(*dispatcher_, CreateQuicSession(_, client_address))
.WillOnce(testing::Return(CreateSession(
@@ -413,7 +408,7 @@ TEST_F(QuicDispatcherTest, TimeWaitListManager) {
CreateTimeWaitListManager();
// Create a new session.
- IPEndPoint client_address(net::test::Loopback4(), 1);
+ QuicSocketAddress client_address(QuicIpAddress::Loopback4(), 1);
QuicConnectionId connection_id = 1;
EXPECT_CALL(*dispatcher_, CreateQuicSession(connection_id, client_address))
.WillOnce(testing::Return(CreateSession(
@@ -449,7 +444,7 @@ TEST_F(QuicDispatcherTest, TimeWaitListManager) {
.WillOnce(
Invoke(reinterpret_cast<MockQuicConnection*>(session1_->connection()),
&MockQuicConnection::ReallyProcessUdpPacket));
- dispatcher_->ProcessPacket(IPEndPoint(), client_address, *received);
+ dispatcher_->ProcessPacket(QuicSocketAddress(), client_address, *received);
EXPECT_TRUE(time_wait_list_manager_->IsConnectionIdInTimeWait(connection_id));
// Dispatcher forwards subsequent packets for this connection_id to the time
@@ -465,7 +460,7 @@ TEST_F(QuicDispatcherTest, TimeWaitListManager) {
TEST_F(QuicDispatcherTest, NoVersionPacketToTimeWaitListManager) {
CreateTimeWaitListManager();
- IPEndPoint client_address(net::test::Loopback4(), 1);
+ QuicSocketAddress client_address(QuicIpAddress::Loopback4(), 1);
QuicConnectionId connection_id = 1;
// Dispatcher forwards all packets for this connection_id to the time wait
// list manager.
@@ -481,8 +476,8 @@ TEST_F(QuicDispatcherTest, NoVersionPacketToTimeWaitListManager) {
TEST_F(QuicDispatcherTest, ProcessPacketWithZeroPort) {
CreateTimeWaitListManager();
- IPEndPoint client_address(net::test::Loopback4(), 0);
- server_address_ = IPEndPoint(net::test::Any4(), 5);
+ QuicSocketAddress client_address(QuicIpAddress::Loopback4(), 0);
+ server_address_ = QuicSocketAddress(QuicIpAddress::Any4(), 5);
// dispatcher_ should drop this packet.
EXPECT_CALL(*dispatcher_, CreateQuicSession(1, client_address)).Times(0);
@@ -493,9 +488,9 @@ TEST_F(QuicDispatcherTest, ProcessPacketWithZeroPort) {
}
TEST_F(QuicDispatcherTest, OKSeqNoPacketProcessed) {
- IPEndPoint client_address(net::test::Loopback4(), 1);
+ QuicSocketAddress client_address(QuicIpAddress::Loopback4(), 1);
QuicConnectionId connection_id = 1;
- server_address_ = IPEndPoint(net::test::Any4(), 5);
+ server_address_ = QuicSocketAddress(QuicIpAddress::Any4(), 5);
EXPECT_CALL(*dispatcher_, CreateQuicSession(1, client_address))
.WillOnce(testing::Return(CreateSession(
@@ -519,7 +514,7 @@ TEST_F(QuicDispatcherTest, OKSeqNoPacketProcessed) {
TEST_F(QuicDispatcherTest, TooBigSeqNoPacketToTimeWaitListManager) {
CreateTimeWaitListManager();
- IPEndPoint client_address(net::test::Loopback4(), 1);
+ QuicSocketAddress client_address(QuicIpAddress::Loopback4(), 1);
QuicConnectionId connection_id = 1;
// Dispatcher forwards this packet for this connection_id to the time wait
// list manager.
@@ -537,6 +532,103 @@ TEST_F(QuicDispatcherTest, TooBigSeqNoPacketToTimeWaitListManager) {
QuicDispatcher::kMaxReasonableInitialPacketNumber + 1);
}
+TEST_F(QuicDispatcherTest, SupportedVersionsChangeInFlight) {
+ static_assert(arraysize(kSupportedQuicVersions) == 4u,
+ "Supported versions out of sync");
+ FLAGS_quic_reloadable_flag_quic_fix_version_manager = true;
+ FLAGS_quic_reloadable_flag_quic_disable_version_34 = false;
+ FLAGS_quic_reloadable_flag_quic_enable_version_36_v3 = true;
+ FLAGS_quic_reloadable_flag_quic_enable_version_37 = true;
+ QuicSocketAddress client_address(QuicIpAddress::Loopback4(), 1);
+ server_address_ = QuicSocketAddress(QuicIpAddress::Any4(), 5);
+ QuicConnectionId connection_id = 1;
+
+ EXPECT_CALL(*dispatcher_, CreateQuicSession(connection_id, client_address))
+ .Times(0);
+ ProcessPacket(client_address, connection_id, true,
+ static_cast<QuicVersion>(QuicVersionMin() - 1), SerializeCHLO(),
+ PACKET_8BYTE_CONNECTION_ID, PACKET_6BYTE_PACKET_NUMBER, 1);
+ ++connection_id;
+ EXPECT_CALL(*dispatcher_, CreateQuicSession(connection_id, client_address))
+ .WillOnce(testing::Return(CreateSession(
+ dispatcher_.get(), config_, connection_id, client_address,
+ &mock_helper_, &mock_alarm_factory_, &crypto_config_,
+ QuicDispatcherPeer::GetCache(dispatcher_.get()), &session1_)));
+ EXPECT_CALL(*reinterpret_cast<MockQuicConnection*>(session1_->connection()),
+ ProcessUdpPacket(_, _, _))
+ .WillOnce(testing::WithArgs<2>(
+ Invoke(CreateFunctor(&QuicDispatcherTest::ValidatePacket,
+ base::Unretained(this), connection_id))));
+ ProcessPacket(client_address, connection_id, true, QuicVersionMin(),
+ SerializeCHLO(), PACKET_8BYTE_CONNECTION_ID,
+ PACKET_6BYTE_PACKET_NUMBER, 1);
+ ++connection_id;
+ EXPECT_CALL(*dispatcher_, CreateQuicSession(connection_id, client_address))
+ .WillOnce(testing::Return(CreateSession(
+ dispatcher_.get(), config_, connection_id, client_address,
+ &mock_helper_, &mock_alarm_factory_, &crypto_config_,
+ QuicDispatcherPeer::GetCache(dispatcher_.get()), &session1_)));
+ EXPECT_CALL(*reinterpret_cast<MockQuicConnection*>(session1_->connection()),
+ ProcessUdpPacket(_, _, _))
+ .WillOnce(testing::WithArgs<2>(
+ Invoke(CreateFunctor(&QuicDispatcherTest::ValidatePacket,
+ base::Unretained(this), connection_id))));
+ ProcessPacket(client_address, connection_id, true, QuicVersionMax(),
+ SerializeCHLO(), PACKET_8BYTE_CONNECTION_ID,
+ PACKET_6BYTE_PACKET_NUMBER, 1);
+ // Turn off version 36.
+ FLAGS_quic_reloadable_flag_quic_enable_version_36_v3 = false;
+ ++connection_id;
+ EXPECT_CALL(*dispatcher_, CreateQuicSession(connection_id, client_address))
+ .Times(0);
+ ProcessPacket(client_address, connection_id, true, QUIC_VERSION_36,
+ SerializeCHLO(), PACKET_8BYTE_CONNECTION_ID,
+ PACKET_6BYTE_PACKET_NUMBER, 1);
+
+ // Turn on version 36.
+ FLAGS_quic_reloadable_flag_quic_enable_version_36_v3 = true;
+ ++connection_id;
+ EXPECT_CALL(*dispatcher_, CreateQuicSession(connection_id, client_address))
+ .WillOnce(testing::Return(CreateSession(
+ dispatcher_.get(), config_, connection_id, client_address,
+ &mock_helper_, &mock_alarm_factory_, &crypto_config_,
+ QuicDispatcherPeer::GetCache(dispatcher_.get()), &session1_)));
+ EXPECT_CALL(*reinterpret_cast<MockQuicConnection*>(session1_->connection()),
+ ProcessUdpPacket(_, _, _))
+ .WillOnce(testing::WithArgs<2>(
+ Invoke(CreateFunctor(&QuicDispatcherTest::ValidatePacket,
+ base::Unretained(this), connection_id))));
+ ProcessPacket(client_address, connection_id, true, QUIC_VERSION_35,
+ SerializeCHLO(), PACKET_8BYTE_CONNECTION_ID,
+ PACKET_6BYTE_PACKET_NUMBER, 1);
+
+ // Turn off version 34.
+ FLAGS_quic_reloadable_flag_quic_disable_version_34 = true;
+ ++connection_id;
+ EXPECT_CALL(*dispatcher_, CreateQuicSession(connection_id, client_address))
+ .Times(0);
+ ProcessPacket(client_address, connection_id, true, QUIC_VERSION_34,
+ SerializeCHLO(), PACKET_8BYTE_CONNECTION_ID,
+ PACKET_6BYTE_PACKET_NUMBER, 1);
+
+ // Turn on version 34.
+ FLAGS_quic_reloadable_flag_quic_disable_version_34 = false;
+ ++connection_id;
+ EXPECT_CALL(*dispatcher_, CreateQuicSession(connection_id, client_address))
+ .WillOnce(testing::Return(CreateSession(
+ dispatcher_.get(), config_, connection_id, client_address,
+ &mock_helper_, &mock_alarm_factory_, &crypto_config_,
+ QuicDispatcherPeer::GetCache(dispatcher_.get()), &session1_)));
+ EXPECT_CALL(*reinterpret_cast<MockQuicConnection*>(session1_->connection()),
+ ProcessUdpPacket(_, _, _))
+ .WillOnce(testing::WithArgs<2>(
+ Invoke(CreateFunctor(&QuicDispatcherTest::ValidatePacket,
+ base::Unretained(this), connection_id))));
+ ProcessPacket(client_address, connection_id, true, QUIC_VERSION_34,
+ SerializeCHLO(), PACKET_8BYTE_CONNECTION_ID,
+ PACKET_6BYTE_PACKET_NUMBER, 1);
+}
+
// Enables mocking of the handshake-confirmation for stateless rejects.
class MockQuicCryptoServerStream : public QuicCryptoServerStream {
public:
@@ -544,11 +636,12 @@ class MockQuicCryptoServerStream : public QuicCryptoServerStream {
QuicCompressedCertsCache* compressed_certs_cache,
QuicServerSessionBase* session,
QuicCryptoServerStream::Helper* helper)
- : QuicCryptoServerStream(&crypto_config,
- compressed_certs_cache,
- FLAGS_enable_quic_stateless_reject_support,
- session,
- helper) {}
+ : QuicCryptoServerStream(
+ &crypto_config,
+ compressed_certs_cache,
+ FLAGS_quic_reloadable_flag_enable_quic_stateless_reject_support,
+ session,
+ helper) {}
void set_handshake_confirmed_for_testing(bool handshake_confirmed) {
handshake_confirmed_ = handshake_confirmed;
}
@@ -617,7 +710,7 @@ class QuicDispatcherStatelessRejectTest
// crypto_stream1_.
void SetUp() override {
QuicDispatcherTest::SetUp();
- FLAGS_enable_quic_stateless_reject_support =
+ FLAGS_quic_reloadable_flag_enable_quic_stateless_reject_support =
GetParam().enable_stateless_rejects_via_flag;
}
@@ -633,7 +726,7 @@ class QuicDispatcherStatelessRejectTest
// the test parameters.
QuicServerSessionBase* CreateSessionBasedOnTestParams(
QuicConnectionId connection_id,
- const IPEndPoint& client_address) {
+ const QuicSocketAddress& client_address) {
CreateSession(dispatcher_.get(), config_, connection_id, client_address,
&mock_helper_, &mock_alarm_factory_, &crypto_config_,
QuicDispatcherPeer::GetCache(dispatcher_.get()), &session1_);
@@ -662,7 +755,7 @@ INSTANTIATE_TEST_CASE_P(QuicDispatcherStatelessRejectTests,
TEST_P(QuicDispatcherStatelessRejectTest, ParameterizedBasicTest) {
CreateTimeWaitListManager();
- IPEndPoint client_address(net::test::Loopback4(), 1);
+ QuicSocketAddress client_address(QuicIpAddress::Loopback4(), 1);
QuicConnectionId connection_id = 1;
EXPECT_CALL(*dispatcher_, CreateQuicSession(connection_id, client_address))
.WillOnce(testing::Return(
@@ -704,10 +797,10 @@ TEST_P(QuicDispatcherStatelessRejectTest, ParameterizedBasicTest) {
}
TEST_P(QuicDispatcherStatelessRejectTest, CheapRejects) {
- FLAGS_quic_use_cheap_stateless_rejects = true;
+ FLAGS_quic_reloadable_flag_quic_use_cheap_stateless_rejects = true;
CreateTimeWaitListManager();
- IPEndPoint client_address(net::test::Loopback4(), 1);
+ QuicSocketAddress client_address(QuicIpAddress::Loopback4(), 1);
QuicConnectionId connection_id = 1;
if (GetParam().enable_stateless_rejects_via_flag) {
EXPECT_CALL(*dispatcher_, CreateQuicSession(connection_id, client_address))
@@ -722,8 +815,8 @@ TEST_P(QuicDispatcherStatelessRejectTest, CheapRejects) {
&QuicDispatcherTest::ValidatePacket, base::Unretained(this), 1))));
}
- VLOG(1) << "ExpectStatelessReject: " << ExpectStatelessReject();
- VLOG(1) << "Params: " << GetParam();
+ QUIC_LOG(INFO) << "ExpectStatelessReject: " << ExpectStatelessReject();
+ QUIC_LOG(INFO) << "Params: " << GetParam();
// Process the first packet for the connection.
// clang-format off
CryptoHandshakeMessage client_hello = CryptoTestUtils::Message(
@@ -747,10 +840,10 @@ TEST_P(QuicDispatcherStatelessRejectTest, CheapRejects) {
}
TEST_P(QuicDispatcherStatelessRejectTest, BufferNonChlo) {
- FLAGS_quic_use_cheap_stateless_rejects = true;
+ FLAGS_quic_reloadable_flag_quic_use_cheap_stateless_rejects = true;
CreateTimeWaitListManager();
- const IPEndPoint client_address(net::test::Loopback4(), 1);
+ const QuicSocketAddress client_address(QuicIpAddress::Loopback4(), 1);
const QuicConnectionId connection_id = 1;
ProcessPacket(client_address, connection_id, true, false,
@@ -801,7 +894,7 @@ TEST_F(QuicDispatcherTestStrayPacketConnectionId,
StrayPacketTruncatedConnectionId) {
CreateTimeWaitListManager();
- IPEndPoint client_address(net::test::Loopback4(), 1);
+ QuicSocketAddress client_address(QuicIpAddress::Loopback4(), 1);
QuicConnectionId connection_id = 1;
// Dispatcher drops this packet.
EXPECT_CALL(*dispatcher_, CreateQuicSession(_, _)).Times(0);
@@ -823,13 +916,13 @@ class BlockingWriter : public QuicPacketWriterWrapper {
WriteResult WritePacket(const char* buffer,
size_t buf_len,
- const IPAddress& self_client_address,
- const IPEndPoint& peer_client_address,
+ const QuicIpAddress& self_client_address,
+ const QuicSocketAddress& peer_client_address,
PerPacketOptions* options) override {
// It would be quite possible to actually implement this method here with
// the fake blocked status, but it would be significantly more work in
// Chromium, and since it's not called anyway, don't bother.
- LOG(DFATAL) << "Not supported";
+ QUIC_LOG(DFATAL) << "Not supported";
return WriteResult();
}
@@ -843,7 +936,7 @@ class QuicDispatcherWriteBlockedListTest : public QuicDispatcherTest {
writer_ = new BlockingWriter;
QuicDispatcherPeer::UseWriter(dispatcher_.get(), writer_);
- IPEndPoint client_address(net::test::Loopback4(), 1);
+ QuicSocketAddress client_address(QuicIpAddress::Loopback4(), 1);
EXPECT_CALL(*dispatcher_, CreateQuicSession(_, client_address))
.WillOnce(testing::Return(CreateSession(
@@ -1029,8 +1122,8 @@ struct BufferedPacketStoreTestParams {
: enable_stateless_rejects_via_flag(enable_stateless_rejects_via_flag),
support_cheap_stateless_reject(support_cheap_stateless_reject) {}
- friend ostream& operator<<(ostream& os,
- const BufferedPacketStoreTestParams& p) {
+ friend std::ostream& operator<<(std::ostream& os,
+ const BufferedPacketStoreTestParams& p) {
os << "{ enable_stateless_rejects_via_flag: "
<< p.enable_stateless_rejects_via_flag << std::endl;
os << " support_cheap_stateless_reject: "
@@ -1063,11 +1156,11 @@ class BufferedPacketStoreTest
public:
BufferedPacketStoreTest()
: QuicDispatcherTest(),
- client_addr_(Loopback4(), 1234),
- proof_(new QuicCryptoProof) {
- FLAGS_quic_use_cheap_stateless_rejects =
+ client_addr_(QuicIpAddress::Loopback4(), 1234),
+ signed_config_(new QuicSignedServerConfig) {
+ FLAGS_quic_reloadable_flag_quic_use_cheap_stateless_rejects =
GetParam().support_cheap_stateless_reject;
- FLAGS_enable_quic_stateless_reject_support =
+ FLAGS_quic_reloadable_flag_enable_quic_stateless_reject_support =
GetParam().enable_stateless_rejects_via_flag;
}
@@ -1081,8 +1174,9 @@ class BufferedPacketStoreTest
chlo.SetVector(net::kCOPT, net::QuicTagVector{net::kSREJ});
// Pass an inchoate CHLO.
CryptoTestUtils::GenerateFullCHLO(
- chlo, &crypto_config_, server_ip_, client_addr_, version, clock_,
- proof_, QuicDispatcherPeer::GetCache(dispatcher_.get()), &full_chlo_);
+ chlo, &crypto_config_, server_addr_, client_addr_, version, clock_,
+ signed_config_, QuicDispatcherPeer::GetCache(dispatcher_.get()),
+ &full_chlo_);
}
string SerializeFullCHLO() {
@@ -1090,9 +1184,9 @@ class BufferedPacketStoreTest
}
protected:
- IPAddress server_ip_;
- IPEndPoint client_addr_;
- scoped_refptr<QuicCryptoProof> proof_;
+ QuicSocketAddress server_addr_;
+ QuicSocketAddress client_addr_;
+ QuicReferenceCountedPointer<QuicSignedServerConfig> signed_config_;
const QuicClock* clock_;
CryptoHandshakeMessage full_chlo_;
};
@@ -1104,8 +1198,8 @@ INSTANTIATE_TEST_CASE_P(
TEST_P(BufferedPacketStoreTest, ProcessNonChloPacketsUptoLimitAndProcessChlo) {
InSequence s;
- IPEndPoint client_address(Loopback4(), 1);
- server_address_ = IPEndPoint(Any4(), 5);
+ QuicSocketAddress client_address(QuicIpAddress::Loopback4(), 1);
+ server_address_ = QuicSocketAddress(QuicIpAddress::Any4(), 5);
QuicConnectionId conn_id = 1;
// A bunch of non-CHLO should be buffered upon arrival, and the first one
// should trigger ShouldCreateOrBufferPacketForConnection().
@@ -1113,9 +1207,8 @@ TEST_P(BufferedPacketStoreTest, ProcessNonChloPacketsUptoLimitAndProcessChlo) {
.Times(1);
for (size_t i = 1; i <= kDefaultMaxUndecryptablePackets + 1; ++i) {
ProcessPacket(client_address, conn_id, true, false,
- "data packet " + IntToString(i + 1),
- PACKET_8BYTE_CONNECTION_ID, PACKET_6BYTE_PACKET_NUMBER,
- kDefaultPathId,
+ QuicStrCat("data packet ", i + 1), PACKET_8BYTE_CONNECTION_ID,
+ PACKET_6BYTE_PACKET_NUMBER, kDefaultPathId,
/*packet_number=*/i + 1);
}
EXPECT_EQ(0u, dispatcher_->session_map().size())
@@ -1145,16 +1238,17 @@ TEST_P(BufferedPacketStoreTest, ProcessNonChloPacketsUptoLimitAndProcessChlo) {
TEST_P(BufferedPacketStoreTest,
ProcessNonChloPacketsForDifferentConnectionsUptoLimit) {
InSequence s;
- server_address_ = IPEndPoint(Any4(), 5);
+ server_address_ = QuicSocketAddress(QuicIpAddress::Any4(), 5);
// A bunch of non-CHLO should be buffered upon arrival.
- size_t kNumConnections = (FLAGS_quic_limit_num_new_sessions_per_epoll_loop
- ? kMaxConnectionsWithoutCHLO
- : kDefaultMaxConnectionsInStore) +
- 1;
+ size_t kNumConnections =
+ (FLAGS_quic_reloadable_flag_quic_limit_num_new_sessions_per_epoll_loop
+ ? kMaxConnectionsWithoutCHLO
+ : kDefaultMaxConnectionsInStore) +
+ 1;
for (size_t i = 1; i <= kNumConnections; ++i) {
- IPEndPoint client_address(Loopback4(), i);
+ QuicSocketAddress client_address(QuicIpAddress::Loopback4(), i);
QuicConnectionId conn_id = i;
- if (FLAGS_quic_create_session_after_insertion) {
+ if (FLAGS_quic_reloadable_flag_quic_create_session_after_insertion) {
EXPECT_CALL(*dispatcher_,
ShouldCreateOrBufferPacketForConnection(conn_id));
} else {
@@ -1167,7 +1261,7 @@ TEST_P(BufferedPacketStoreTest,
}
}
ProcessPacket(client_address, conn_id, true, false,
- "data packet on connection " + IntToString(i),
+ QuicStrCat("data packet on connection ", i),
PACKET_8BYTE_CONNECTION_ID, PACKET_6BYTE_PACKET_NUMBER,
kDefaultPathId,
/*packet_number=*/2);
@@ -1183,9 +1277,9 @@ TEST_P(BufferedPacketStoreTest,
kNumConnections);
// Process CHLOs to create session for these connections.
for (size_t i = 1; i <= kNumConnections; ++i) {
- IPEndPoint client_address(Loopback4(), i);
+ QuicSocketAddress client_address(QuicIpAddress::Loopback4(), i);
QuicConnectionId conn_id = i;
- if (FLAGS_quic_create_session_after_insertion &&
+ if (FLAGS_quic_reloadable_flag_quic_create_session_after_insertion &&
conn_id == kNumConnections) {
// The last CHLO should trigger ShouldCreateOrBufferPacketForConnection()
// since it's the
@@ -1198,7 +1292,7 @@ TEST_P(BufferedPacketStoreTest,
dispatcher_.get(), config_, conn_id, client_address, &mock_helper_,
&mock_alarm_factory_, &crypto_config_,
QuicDispatcherPeer::GetCache(dispatcher_.get()), &session1_)));
- if (!FLAGS_quic_create_session_after_insertion &&
+ if (!FLAGS_quic_reloadable_flag_quic_create_session_after_insertion &&
conn_id == kNumConnections) {
// The last CHLO should trigger ShouldCreateOrBufferPacketForConnection()
// since it's the first packet arrives on that connection.
@@ -1207,9 +1301,10 @@ TEST_P(BufferedPacketStoreTest,
}
// First |kNumConnections| - 1 connections should have buffered
// a packet in store. The rest should have been dropped.
- size_t upper_limit = FLAGS_quic_limit_num_new_sessions_per_epoll_loop
- ? kMaxConnectionsWithoutCHLO
- : kDefaultMaxConnectionsInStore;
+ size_t upper_limit =
+ FLAGS_quic_reloadable_flag_quic_limit_num_new_sessions_per_epoll_loop
+ ? kMaxConnectionsWithoutCHLO
+ : kDefaultMaxConnectionsInStore;
size_t num_packet_to_process = i <= upper_limit ? 2u : 1u;
EXPECT_CALL(*reinterpret_cast<MockQuicConnection*>(session1_->connection()),
ProcessUdpPacket(_, client_address, _))
@@ -1224,7 +1319,7 @@ TEST_P(BufferedPacketStoreTest,
// Tests that store delivers empty packet list if CHLO arrives firstly.
TEST_P(BufferedPacketStoreTest, DeliverEmptyPackets) {
QuicConnectionId conn_id = 1;
- IPEndPoint client_address(Loopback4(), 1);
+ QuicSocketAddress client_address(QuicIpAddress::Loopback4(), 1);
EXPECT_CALL(*dispatcher_, ShouldCreateOrBufferPacketForConnection(conn_id));
EXPECT_CALL(*dispatcher_, CreateQuicSession(conn_id, client_address))
.WillOnce(testing::Return(CreateSession(
@@ -1238,11 +1333,11 @@ TEST_P(BufferedPacketStoreTest, DeliverEmptyPackets) {
// CHLO has been created.
TEST_P(BufferedPacketStoreTest, ReceiveRetransmittedCHLO) {
InSequence s;
- IPEndPoint client_address(Loopback4(), 1);
- server_address_ = IPEndPoint(Any4(), 5);
+ QuicSocketAddress client_address(QuicIpAddress::Loopback4(), 1);
+ server_address_ = QuicSocketAddress(QuicIpAddress::Any4(), 5);
QuicConnectionId conn_id = 1;
ProcessPacket(client_address, conn_id, true, false,
- "data packet " + IntToString(2), PACKET_8BYTE_CONNECTION_ID,
+ QuicStrCat("data packet ", 2), PACKET_8BYTE_CONNECTION_ID,
PACKET_6BYTE_PACKET_NUMBER, kDefaultPathId,
/*packet_number=*/2);
@@ -1273,11 +1368,11 @@ TEST_P(BufferedPacketStoreTest, ReceiveCHLOAfterExpiration) {
QuicDispatcherPeer::GetBufferedPackets(dispatcher_.get());
QuicBufferedPacketStorePeer::set_clock(store, mock_helper_.GetClock());
- IPEndPoint client_address(Loopback4(), 1);
- server_address_ = IPEndPoint(Any4(), 5);
+ QuicSocketAddress client_address(QuicIpAddress::Loopback4(), 1);
+ server_address_ = QuicSocketAddress(QuicIpAddress::Any4(), 5);
QuicConnectionId conn_id = 1;
ProcessPacket(client_address, conn_id, true, false,
- "data packet " + IntToString(2), PACKET_8BYTE_CONNECTION_ID,
+ QuicStrCat("data packet ", 2), PACKET_8BYTE_CONNECTION_ID,
PACKET_6BYTE_PACKET_NUMBER, kDefaultPathId,
/*packet_number=*/2);
@@ -1295,7 +1390,7 @@ TEST_P(BufferedPacketStoreTest, ReceiveCHLOAfterExpiration) {
}
TEST_P(BufferedPacketStoreTest, ProcessCHLOsUptoLimitAndBufferTheRest) {
- FLAGS_quic_limit_num_new_sessions_per_epoll_loop = true;
+ FLAGS_quic_reloadable_flag_quic_limit_num_new_sessions_per_epoll_loop = true;
// Process more than (|kMaxNumSessionsToCreate| +
// |kDefaultMaxConnectionsInStore|) CHLOs,
// the first |kMaxNumSessionsToCreate| should create connections immediately,
@@ -1306,11 +1401,12 @@ TEST_P(BufferedPacketStoreTest, ProcessCHLOsUptoLimitAndBufferTheRest) {
const size_t kNumCHLOs =
kMaxNumSessionsToCreate + kDefaultMaxConnectionsInStore + 1;
for (size_t conn_id = 1; conn_id <= kNumCHLOs; ++conn_id) {
- if (FLAGS_quic_create_session_after_insertion) {
+ if (FLAGS_quic_reloadable_flag_quic_create_session_after_insertion) {
EXPECT_CALL(*dispatcher_,
ShouldCreateOrBufferPacketForConnection(conn_id));
}
- if (!FLAGS_quic_create_session_after_insertion && conn_id < kNumCHLOs) {
+ if (!FLAGS_quic_reloadable_flag_quic_create_session_after_insertion &&
+ conn_id < kNumCHLOs) {
// Except the last connection, all connections for previous CHLOs should
// be regarded as newly added.
EXPECT_CALL(*dispatcher_,
@@ -1371,7 +1467,7 @@ TEST_P(BufferedPacketStoreTest, ProcessCHLOsUptoLimitAndBufferTheRest) {
// Duplicated CHLO shouldn't be buffered.
TEST_P(BufferedPacketStoreTest, BufferDuplicatedCHLO) {
- FLAGS_quic_limit_num_new_sessions_per_epoll_loop = true;
+ FLAGS_quic_reloadable_flag_quic_limit_num_new_sessions_per_epoll_loop = true;
for (QuicConnectionId conn_id = 1; conn_id <= kMaxNumSessionsToCreate + 1;
++conn_id) {
// Last CHLO will be buffered. Others will create connection right away.
@@ -1396,7 +1492,7 @@ TEST_P(BufferedPacketStoreTest, BufferDuplicatedCHLO) {
SerializeFullCHLO());
size_t packets_buffered = 2;
- if (!FLAGS_quic_buffer_packets_after_chlo) {
+ if (!FLAGS_quic_reloadable_flag_quic_buffer_packets_after_chlo) {
// The packet sent above is dropped when flag is off.
packets_buffered = 1;
}
@@ -1418,7 +1514,7 @@ TEST_P(BufferedPacketStoreTest, BufferDuplicatedCHLO) {
}
TEST_P(BufferedPacketStoreTest, BufferNonChloPacketsUptoLimitWithChloBuffered) {
- FLAGS_quic_limit_num_new_sessions_per_epoll_loop = true;
+ FLAGS_quic_reloadable_flag_quic_limit_num_new_sessions_per_epoll_loop = true;
QuicConnectionId last_connection_id = kMaxNumSessionsToCreate + 1;
for (QuicConnectionId conn_id = 1; conn_id <= last_connection_id; ++conn_id) {
// Last CHLO will be buffered. Others will create connection right away.
@@ -1465,7 +1561,7 @@ TEST_P(BufferedPacketStoreTest, BufferNonChloPacketsUptoLimitWithChloBuffered) {
// Tests that when dispatcher's packet buffer is full, a CHLO on connection
// which doesn't have buffered CHLO should be buffered.
TEST_P(BufferedPacketStoreTest, ReceiveCHLOForBufferedConnection) {
- FLAGS_quic_limit_num_new_sessions_per_epoll_loop = true;
+ FLAGS_quic_reloadable_flag_quic_limit_num_new_sessions_per_epoll_loop = true;
QuicBufferedPacketStore* store =
QuicDispatcherPeer::GetBufferedPackets(dispatcher_.get());
@@ -1510,13 +1606,13 @@ class AsyncGetProofTest : public QuicDispatcherTest {
AsyncGetProofTest()
: QuicDispatcherTest(
std::unique_ptr<FakeProofSource>(new FakeProofSource())),
- client_addr_(net::test::Loopback4(), 1234),
+ client_addr_(QuicIpAddress::Loopback4(), 1234),
crypto_config_peer_(&crypto_config_),
- proof_(new QuicCryptoProof) {
- FLAGS_enable_async_get_proof = true;
- FLAGS_enable_quic_stateless_reject_support = true;
- FLAGS_quic_use_cheap_stateless_rejects = true;
- FLAGS_quic_create_session_after_insertion = true;
+ signed_config_(new QuicSignedServerConfig) {
+ FLAGS_quic_reloadable_flag_enable_async_get_proof = true;
+ FLAGS_quic_reloadable_flag_enable_quic_stateless_reject_support = true;
+ FLAGS_quic_reloadable_flag_quic_use_cheap_stateless_rejects = true;
+ FLAGS_quic_reloadable_flag_quic_create_session_after_insertion = true;
}
void SetUp() override {
@@ -1529,8 +1625,9 @@ class AsyncGetProofTest : public QuicDispatcherTest {
chlo_.SetVector(net::kCOPT, net::QuicTagVector{net::kSREJ});
// Pass an inchoate CHLO.
CryptoTestUtils::GenerateFullCHLO(
- chlo_, &crypto_config_, server_ip_, client_addr_, version, clock_,
- proof_, QuicDispatcherPeer::GetCache(dispatcher_.get()), &full_chlo_);
+ chlo_, &crypto_config_, server_addr_, client_addr_, version, clock_,
+ signed_config_, QuicDispatcherPeer::GetCache(dispatcher_.get()),
+ &full_chlo_);
GetFakeProofSource()->Activate();
}
@@ -1575,12 +1672,12 @@ class AsyncGetProofTest : public QuicDispatcherTest {
}
protected:
- const IPEndPoint client_addr_;
+ const QuicSocketAddress client_addr_;
private:
QuicCryptoServerConfigPeer crypto_config_peer_;
- IPAddress server_ip_;
- scoped_refptr<QuicCryptoProof> proof_;
+ QuicSocketAddress server_addr_;
+ QuicReferenceCountedPointer<QuicSignedServerConfig> signed_config_;
const QuicClock* clock_;
CryptoHandshakeMessage chlo_;
CryptoHandshakeMessage full_chlo_;
diff --git a/chromium/net/tools/quic/quic_epoll_alarm_factory.cc b/chromium/net/tools/quic/quic_epoll_alarm_factory.cc
index 56377b237b3..11e8190a658 100644
--- a/chromium/net/tools/quic/quic_epoll_alarm_factory.cc
+++ b/chromium/net/tools/quic/quic_epoll_alarm_factory.cc
@@ -4,7 +4,6 @@
#include "net/tools/quic/quic_epoll_alarm_factory.h"
-#include "base/logging.h"
#include "net/tools/epoll_server/epoll_server.h"
namespace net {
diff --git a/chromium/net/tools/quic/quic_epoll_alarm_factory.h b/chromium/net/tools/quic/quic_epoll_alarm_factory.h
index 1f94b79417e..9c47f56dc7b 100644
--- a/chromium/net/tools/quic/quic_epoll_alarm_factory.h
+++ b/chromium/net/tools/quic/quic_epoll_alarm_factory.h
@@ -2,8 +2,8 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#ifndef NET_QUIC_QUIC_EPOLL_ALARM_FACTORY_H_
-#define NET_QUIC_QUIC_EPOLL_ALARM_FACTORY_H_
+#ifndef NET_TOOLS_QUIC_QUIC_EPOLL_ALARM_FACTORY_H_
+#define NET_TOOLS_QUIC_QUIC_EPOLL_ALARM_FACTORY_H_
#include "net/quic/core/quic_alarm.h"
#include "net/quic/core/quic_alarm_factory.h"
@@ -32,4 +32,4 @@ class QuicEpollAlarmFactory : public QuicAlarmFactory {
} // namespace net
-#endif // NET_QUIC_QUIC_EPOLL_ALARM_FACTORY_H_
+#endif // NET_TOOLS_QUIC_QUIC_EPOLL_ALARM_FACTORY_H_
diff --git a/chromium/net/tools/quic/quic_epoll_alarm_factory_test.cc b/chromium/net/tools/quic/quic_epoll_alarm_factory_test.cc
index 3118be88a91..7ff26f36c2b 100644
--- a/chromium/net/tools/quic/quic_epoll_alarm_factory_test.cc
+++ b/chromium/net/tools/quic/quic_epoll_alarm_factory_test.cc
@@ -4,7 +4,7 @@
#include "net/tools/quic/quic_epoll_alarm_factory.h"
-#include "net/tools/quic/quic_epoll_clock.h"
+#include "net/tools/quic/platform/impl/quic_epoll_clock.h"
#include "net/tools/quic/test_tools/mock_epoll_server.h"
#include "testing/gtest/include/gtest/gtest.h"
diff --git a/chromium/net/tools/quic/quic_epoll_connection_helper.cc b/chromium/net/tools/quic/quic_epoll_connection_helper.cc
index 3f9671080e0..2e687163e47 100644
--- a/chromium/net/tools/quic/quic_epoll_connection_helper.cc
+++ b/chromium/net/tools/quic/quic_epoll_connection_helper.cc
@@ -7,12 +7,10 @@
#include <errno.h>
#include <sys/socket.h>
-#include "base/logging.h"
#include "base/stl_util.h"
-#include "net/base/ip_endpoint.h"
#include "net/quic/core/crypto/quic_random.h"
#include "net/tools/epoll_server/epoll_server.h"
-#include "net/tools/quic/quic_socket_utils.h"
+#include "net/tools/quic/platform/impl/quic_socket_utils.h"
namespace net {
diff --git a/chromium/net/tools/quic/quic_epoll_connection_helper.h b/chromium/net/tools/quic/quic_epoll_connection_helper.h
index 01964b35b9b..d574375f360 100644
--- a/chromium/net/tools/quic/quic_epoll_connection_helper.h
+++ b/chromium/net/tools/quic/quic_epoll_connection_helper.h
@@ -14,11 +14,11 @@
#include "base/macros.h"
#include "net/quic/core/quic_connection.h"
#include "net/quic/core/quic_packet_writer.h"
-#include "net/quic/core/quic_protocol.h"
+#include "net/quic/core/quic_packets.h"
#include "net/quic/core/quic_simple_buffer_allocator.h"
#include "net/quic/core/quic_time.h"
+#include "net/tools/quic/platform/impl/quic_epoll_clock.h"
#include "net/tools/quic/quic_default_packet_writer.h"
-#include "net/tools/quic/quic_epoll_clock.h"
namespace net {
diff --git a/chromium/net/tools/quic/quic_epoll_connection_helper_test.cc b/chromium/net/tools/quic/quic_epoll_connection_helper_test.cc
index 0f9106fe088..e0d66a67996 100644
--- a/chromium/net/tools/quic/quic_epoll_connection_helper_test.cc
+++ b/chromium/net/tools/quic/quic_epoll_connection_helper_test.cc
@@ -8,8 +8,6 @@
#include "net/tools/quic/test_tools/mock_epoll_server.h"
#include "testing/gtest/include/gtest/gtest.h"
-using net::test::MockEpollServer;
-
namespace net {
namespace test {
namespace {
diff --git a/chromium/net/tools/quic/quic_in_memory_cache.cc b/chromium/net/tools/quic/quic_http_response_cache.cc
index 392a848b48c..65ff6390e92 100644
--- a/chromium/net/tools/quic/quic_in_memory_cache.cc
+++ b/chromium/net/tools/quic/quic_http_response_cache.cc
@@ -2,19 +2,18 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#include "net/tools/quic/quic_in_memory_cache.h"
+#include "net/tools/quic/quic_http_response_cache.h"
#include <utility>
#include "base/files/file_enumerator.h"
#include "base/files/file_util.h"
-#include "base/memory/ptr_util.h"
#include "base/stl_util.h"
-#include "base/strings/string_number_conversions.h"
-#include "base/strings/string_util.h"
-#include "base/strings/stringprintf.h"
#include "net/http/http_util.h"
-#include "net/quic/core/quic_bug_tracker.h"
+#include "net/quic/platform/api/quic_bug_tracker.h"
+#include "net/quic/platform/api/quic_logging.h"
+#include "net/quic/platform/api/quic_ptr_util.h"
+#include "net/quic/platform/api/quic_text_utils.h"
#include "net/spdy/spdy_http_utils.h"
using base::FilePath;
@@ -24,26 +23,29 @@ using std::string;
namespace net {
-QuicInMemoryCache::ServerPushInfo::ServerPushInfo(GURL request_url,
- SpdyHeaderBlock headers,
- net::SpdyPriority priority,
- string body)
+QuicHttpResponseCache::ServerPushInfo::ServerPushInfo(
+ GURL request_url,
+ SpdyHeaderBlock headers,
+ net::SpdyPriority priority,
+ string body)
: request_url(request_url),
headers(std::move(headers)),
priority(priority),
body(body) {}
-QuicInMemoryCache::ServerPushInfo::ServerPushInfo(const ServerPushInfo& other)
+QuicHttpResponseCache::ServerPushInfo::ServerPushInfo(
+ const ServerPushInfo& other)
: request_url(other.request_url),
headers(other.headers.Clone()),
priority(other.priority),
body(other.body) {}
-QuicInMemoryCache::Response::Response() : response_type_(REGULAR_RESPONSE) {}
+QuicHttpResponseCache::Response::Response()
+ : response_type_(REGULAR_RESPONSE) {}
-QuicInMemoryCache::Response::~Response() {}
+QuicHttpResponseCache::Response::~Response() {}
-void QuicInMemoryCache::ResourceFile::Read() {
+void QuicHttpResponseCache::ResourceFile::Read() {
base::ReadFileToString(FilePath(file_name_), &file_contents_);
// First read the headers.
@@ -51,8 +53,8 @@ void QuicInMemoryCache::ResourceFile::Read() {
while (start < file_contents_.length()) {
size_t pos = file_contents_.find("\n", start);
if (pos == string::npos) {
- LOG(DFATAL) << "Headers invalid or empty, ignoring: "
- << file_name_.value();
+ QUIC_LOG(DFATAL) << "Headers invalid or empty, ignoring: "
+ << file_name_.value();
return;
}
size_t len = pos - start;
@@ -70,8 +72,8 @@ void QuicInMemoryCache::ResourceFile::Read() {
if (line.substr(0, 4) == "HTTP") {
pos = line.find(" ");
if (pos == string::npos) {
- LOG(DFATAL) << "Headers invalid or empty, ignoring: "
- << file_name_.value();
+ QUIC_LOG(DFATAL) << "Headers invalid or empty, ignoring: "
+ << file_name_.value();
return;
}
spdy_headers_[":status"] = line.substr(pos + 1, 3);
@@ -80,12 +82,12 @@ void QuicInMemoryCache::ResourceFile::Read() {
// Headers are "key: value".
pos = line.find(": ");
if (pos == string::npos) {
- LOG(DFATAL) << "Headers invalid or empty, ignoring: "
- << file_name_.value();
+ QUIC_LOG(DFATAL) << "Headers invalid or empty, ignoring: "
+ << file_name_.value();
return;
}
spdy_headers_.AppendValueOrAddHeader(
- base::ToLowerASCII(line.substr(0, pos)), line.substr(pos + 2));
+ QuicTextUtils::ToLower(line.substr(0, pos)), line.substr(pos + 2));
}
// The connection header is prohibited in HTTP/2.
@@ -121,12 +123,14 @@ void QuicInMemoryCache::ResourceFile::Read() {
StringPiece(file_contents_.data() + start, file_contents_.size() - start);
}
-QuicInMemoryCache::ResourceFile::ResourceFile(const base::FilePath& file_name)
+QuicHttpResponseCache::ResourceFile::ResourceFile(
+ const base::FilePath& file_name)
: file_name_(file_name), file_name_string_(file_name.AsUTF8Unsafe()) {}
-QuicInMemoryCache::ResourceFile::~ResourceFile() {}
+QuicHttpResponseCache::ResourceFile::~ResourceFile() {}
-void QuicInMemoryCache::ResourceFile::SetHostPathFromBase(StringPiece base) {
+void QuicHttpResponseCache::ResourceFile::SetHostPathFromBase(
+ StringPiece base) {
size_t path_start = base.find_first_of('/');
DCHECK_LT(0UL, path_start);
host_ = base.substr(0, path_start);
@@ -138,32 +142,26 @@ void QuicInMemoryCache::ResourceFile::SetHostPathFromBase(StringPiece base) {
}
}
-StringPiece QuicInMemoryCache::ResourceFile::RemoveScheme(StringPiece url) {
- if (base::StartsWith(url, "https://", base::CompareCase::INSENSITIVE_ASCII)) {
+StringPiece QuicHttpResponseCache::ResourceFile::RemoveScheme(StringPiece url) {
+ if (QuicTextUtils::StartsWith(url, "https://")) {
url.remove_prefix(8);
- } else if (base::StartsWith(url, "http://",
- base::CompareCase::INSENSITIVE_ASCII)) {
+ } else if (QuicTextUtils::StartsWith(url, "http://")) {
url.remove_prefix(7);
}
return url;
}
-void QuicInMemoryCache::ResourceFile::HandleXOriginalUrl() {
+void QuicHttpResponseCache::ResourceFile::HandleXOriginalUrl() {
StringPiece url(x_original_url_);
// Remove the protocol so we can add it below.
url = RemoveScheme(url);
SetHostPathFromBase(url);
}
-// static
-QuicInMemoryCache* QuicInMemoryCache::GetInstance() {
- return base::Singleton<QuicInMemoryCache>::get();
-}
-
-const QuicInMemoryCache::Response* QuicInMemoryCache::GetResponse(
+const QuicHttpResponseCache::Response* QuicHttpResponseCache::GetResponse(
StringPiece host,
StringPiece path) const {
- base::AutoLock lock(response_mutex_);
+ QuicWriterMutexLock lock(&response_mutex_);
auto it = responses_.find(GetKey(host, path));
if (it == responses_.end()) {
@@ -177,20 +175,20 @@ const QuicInMemoryCache::Response* QuicInMemoryCache::GetResponse(
return it->second.get();
}
-typedef QuicInMemoryCache::ServerPushInfo ServerPushInfo;
+typedef QuicHttpResponseCache::ServerPushInfo ServerPushInfo;
-void QuicInMemoryCache::AddSimpleResponse(StringPiece host,
- StringPiece path,
- int response_code,
- StringPiece body) {
+void QuicHttpResponseCache::AddSimpleResponse(StringPiece host,
+ StringPiece path,
+ int response_code,
+ StringPiece body) {
SpdyHeaderBlock response_headers;
- response_headers[":status"] = IntToString(response_code);
+ response_headers[":status"] = QuicTextUtils::Uint64ToString(response_code);
response_headers["content-length"] =
- IntToString(static_cast<int>(body.length()));
+ QuicTextUtils::Uint64ToString(body.length());
AddResponse(host, path, std::move(response_headers), body);
}
-void QuicInMemoryCache::AddSimpleResponseWithServerPushResources(
+void QuicHttpResponseCache::AddSimpleResponseWithServerPushResources(
StringPiece host,
StringPiece path,
int response_code,
@@ -200,50 +198,47 @@ void QuicInMemoryCache::AddSimpleResponseWithServerPushResources(
MaybeAddServerPushResources(host, path, push_resources);
}
-void QuicInMemoryCache::AddDefaultResponse(Response* response) {
- base::AutoLock lock(response_mutex_);
+void QuicHttpResponseCache::AddDefaultResponse(Response* response) {
+ QuicWriterMutexLock lock(&response_mutex_);
default_response_.reset(response);
}
-void QuicInMemoryCache::AddResponse(StringPiece host,
- StringPiece path,
- SpdyHeaderBlock response_headers,
- StringPiece response_body) {
+void QuicHttpResponseCache::AddResponse(StringPiece host,
+ StringPiece path,
+ SpdyHeaderBlock response_headers,
+ StringPiece response_body) {
AddResponseImpl(host, path, REGULAR_RESPONSE, std::move(response_headers),
response_body, SpdyHeaderBlock());
}
-void QuicInMemoryCache::AddResponse(StringPiece host,
- StringPiece path,
- SpdyHeaderBlock response_headers,
- StringPiece response_body,
- SpdyHeaderBlock response_trailers) {
+void QuicHttpResponseCache::AddResponse(StringPiece host,
+ StringPiece path,
+ SpdyHeaderBlock response_headers,
+ StringPiece response_body,
+ SpdyHeaderBlock response_trailers) {
AddResponseImpl(host, path, REGULAR_RESPONSE, std::move(response_headers),
response_body, std::move(response_trailers));
}
-void QuicInMemoryCache::AddSpecialResponse(StringPiece host,
- StringPiece path,
- SpecialResponseType response_type) {
+void QuicHttpResponseCache::AddSpecialResponse(
+ StringPiece host,
+ StringPiece path,
+ SpecialResponseType response_type) {
AddResponseImpl(host, path, response_type, SpdyHeaderBlock(), "",
SpdyHeaderBlock());
}
-QuicInMemoryCache::QuicInMemoryCache() {}
-
-void QuicInMemoryCache::ResetForTests() {
- base::AutoLock lock(response_mutex_);
- responses_.clear();
- server_push_resources_.clear();
-}
+QuicHttpResponseCache::QuicHttpResponseCache() {}
-void QuicInMemoryCache::InitializeFromDirectory(const string& cache_directory) {
+void QuicHttpResponseCache::InitializeFromDirectory(
+ const string& cache_directory) {
if (cache_directory.empty()) {
QUIC_BUG << "cache_directory must not be empty.";
return;
}
- VLOG(1) << "Attempting to initialize QuicInMemoryCache from directory: "
- << cache_directory;
+ QUIC_LOG(INFO)
+ << "Attempting to initialize QuicHttpResponseCache from directory: "
+ << cache_directory;
FilePath directory(FilePath::FromUTF8Unsafe(cache_directory));
base::FileEnumerator file_list(directory, true, base::FileEnumerator::FILES);
std::list<std::unique_ptr<ResourceFile>> resource_files;
@@ -290,34 +285,34 @@ void QuicInMemoryCache::InitializeFromDirectory(const string& cache_directory) {
}
}
-std::list<ServerPushInfo> QuicInMemoryCache::GetServerPushResources(
+std::list<ServerPushInfo> QuicHttpResponseCache::GetServerPushResources(
string request_url) {
- base::AutoLock lock(response_mutex_);
+ QuicWriterMutexLock lock(&response_mutex_);
std::list<ServerPushInfo> resources;
auto resource_range = server_push_resources_.equal_range(request_url);
for (auto it = resource_range.first; it != resource_range.second; ++it) {
resources.push_back(it->second);
}
- DVLOG(1) << "Found " << resources.size() << " push resources for "
- << request_url;
+ QUIC_DVLOG(1) << "Found " << resources.size() << " push resources for "
+ << request_url;
return resources;
}
-QuicInMemoryCache::~QuicInMemoryCache() {
+QuicHttpResponseCache::~QuicHttpResponseCache() {
{
- base::AutoLock lock(response_mutex_);
+ QuicWriterMutexLock lock(&response_mutex_);
responses_.clear();
}
}
-void QuicInMemoryCache::AddResponseImpl(StringPiece host,
- StringPiece path,
- SpecialResponseType response_type,
- SpdyHeaderBlock response_headers,
- StringPiece response_body,
- SpdyHeaderBlock response_trailers) {
- base::AutoLock lock(response_mutex_);
+void QuicHttpResponseCache::AddResponseImpl(StringPiece host,
+ StringPiece path,
+ SpecialResponseType response_type,
+ SpdyHeaderBlock response_headers,
+ StringPiece response_body,
+ SpdyHeaderBlock response_trailers) {
+ QuicWriterMutexLock lock(&response_mutex_);
DCHECK(!host.empty()) << "Host must be populated, e.g. \"www.google.com\"";
string key = GetKey(host, path);
@@ -325,20 +320,20 @@ void QuicInMemoryCache::AddResponseImpl(StringPiece host,
QUIC_BUG << "Response for '" << key << "' already exists!";
return;
}
- std::unique_ptr<Response> new_response = base::MakeUnique<Response>();
+ std::unique_ptr<Response> new_response = QuicMakeUnique<Response>();
new_response->set_response_type(response_type);
new_response->set_headers(std::move(response_headers));
new_response->set_body(response_body);
new_response->set_trailers(std::move(response_trailers));
- DVLOG(1) << "Add response with key " << key;
+ QUIC_DVLOG(1) << "Add response with key " << key;
responses_[key] = std::move(new_response);
}
-string QuicInMemoryCache::GetKey(StringPiece host, StringPiece path) const {
+string QuicHttpResponseCache::GetKey(StringPiece host, StringPiece path) const {
return host.as_string() + path.as_string();
}
-void QuicInMemoryCache::MaybeAddServerPushResources(
+void QuicHttpResponseCache::MaybeAddServerPushResources(
StringPiece request_host,
StringPiece request_path,
std::list<ServerPushInfo> push_resources) {
@@ -349,11 +344,12 @@ void QuicInMemoryCache::MaybeAddServerPushResources(
continue;
}
- DVLOG(1) << "Add request-resource association: request url " << request_url
- << " push url " << push_resource.request_url
- << " response headers " << push_resource.headers.DebugString();
+ QUIC_DVLOG(1) << "Add request-resource association: request url "
+ << request_url << " push url " << push_resource.request_url
+ << " response headers "
+ << push_resource.headers.DebugString();
{
- base::AutoLock lock(response_mutex_);
+ QuicWriterMutexLock lock(&response_mutex_);
server_push_resources_.insert(std::make_pair(request_url, push_resource));
}
string host = push_resource.request_url.host();
@@ -363,23 +359,24 @@ void QuicInMemoryCache::MaybeAddServerPushResources(
string path = push_resource.request_url.path();
bool found_existing_response = false;
{
- base::AutoLock lock(response_mutex_);
+ QuicWriterMutexLock lock(&response_mutex_);
found_existing_response =
base::ContainsKey(responses_, GetKey(host, path));
}
if (!found_existing_response) {
// Add a server push response to responses map, if it is not in the map.
StringPiece body = push_resource.body;
- DVLOG(1) << "Add response for push resource: host " << host << " path "
- << path;
+ QUIC_DVLOG(1) << "Add response for push resource: host " << host
+ << " path " << path;
AddResponse(host, path, push_resource.headers.Clone(), body);
}
}
}
-bool QuicInMemoryCache::PushResourceExistsInCache(string original_request_url,
- ServerPushInfo resource) {
- base::AutoLock lock(response_mutex_);
+bool QuicHttpResponseCache::PushResourceExistsInCache(
+ string original_request_url,
+ ServerPushInfo resource) {
+ QuicWriterMutexLock lock(&response_mutex_);
auto resource_range =
server_push_resources_.equal_range(original_request_url);
for (auto it = resource_range.first; it != resource_range.second; ++it) {
diff --git a/chromium/net/tools/quic/quic_in_memory_cache.h b/chromium/net/tools/quic/quic_http_response_cache.h
index b1c4ced33c8..ad274bf05f7 100644
--- a/chromium/net/tools/quic/quic_in_memory_cache.h
+++ b/chromium/net/tools/quic/quic_http_response_cache.h
@@ -2,8 +2,8 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#ifndef NET_TOOLS_QUIC_QUIC_IN_MEMORY_CACHE_H_
-#define NET_TOOLS_QUIC_QUIC_IN_MEMORY_CACHE_H_
+#ifndef NET_TOOLS_QUIC_QUIC_HTTP_RESPONSE_CACHE_H_
+#define NET_TOOLS_QUIC_QUIC_HTTP_RESPONSE_CACHE_H_
#include <list>
#include <map>
@@ -14,32 +14,19 @@
#include "base/files/file_path.h"
#include "base/macros.h"
-#include "base/memory/singleton.h"
#include "base/strings/string_piece.h"
#include "net/http/http_response_headers.h"
#include "net/quic/core/spdy_utils.h"
+#include "net/quic/platform/api/quic_mutex.h"
#include "net/spdy/spdy_framer.h"
#include "url/gurl.h"
-namespace base {
-
-template <typename Type>
-struct DefaultSingletonTraits;
-
-} // namespace base
-
namespace net {
-namespace test {
-class QuicInMemoryCachePeer;
-} // namespace test
-
-class QuicServer;
-
// In-memory cache for HTTP responses.
// Reads from disk cache generated by:
// `wget -p --save_headers <url>`
-class QuicInMemoryCache {
+class QuicHttpResponseCache {
public:
// A ServerPushInfo contains path of the push request and everything needed in
// comprising a response for the push request.
@@ -134,13 +121,13 @@ class QuicInMemoryCache {
private:
base::StringPiece host_;
base::StringPiece path_;
- QuicInMemoryCache* cache_;
+ QuicHttpResponseCache* cache_;
DISALLOW_COPY_AND_ASSIGN(ResourceFile);
};
- // Returns the singleton instance of the cache.
- static QuicInMemoryCache* GetInstance();
+ QuicHttpResponseCache();
+ ~QuicHttpResponseCache();
// Retrieve a response from this cache for a given host and path..
// If no appropriate response exists, nullptr is returned.
@@ -194,14 +181,6 @@ class QuicInMemoryCache {
std::list<ServerPushInfo> GetServerPushResources(std::string request_url);
private:
- friend struct base::DefaultSingletonTraits<QuicInMemoryCache>;
- friend class test::QuicInMemoryCachePeer;
-
- QuicInMemoryCache();
- ~QuicInMemoryCache();
-
- void ResetForTests();
-
void AddResponseImpl(base::StringPiece host,
base::StringPiece path,
SpecialResponseType response_type,
@@ -223,21 +202,23 @@ class QuicInMemoryCache {
ServerPushInfo resource);
// Cached responses.
- std::unordered_map<std::string, std::unique_ptr<Response>> responses_;
+ std::unordered_map<std::string, std::unique_ptr<Response>> responses_
+ GUARDED_BY(response_mutex_);
// The default response for cache misses, if set.
- std::unique_ptr<Response> default_response_;
+ std::unique_ptr<Response> default_response_ GUARDED_BY(response_mutex_);
// A map from request URL to associated server push responses (if any).
- std::multimap<std::string, ServerPushInfo> server_push_resources_;
+ std::multimap<std::string, ServerPushInfo> server_push_resources_
+ GUARDED_BY(response_mutex_);
// Protects against concurrent access from test threads setting responses, and
// server threads accessing those responses.
- mutable base::Lock response_mutex_;
+ mutable QuicMutex response_mutex_;
- DISALLOW_COPY_AND_ASSIGN(QuicInMemoryCache);
+ DISALLOW_COPY_AND_ASSIGN(QuicHttpResponseCache);
};
} // namespace net
-#endif // NET_TOOLS_QUIC_QUIC_IN_MEMORY_CACHE_H_
+#endif // NET_TOOLS_QUIC_QUIC_HTTP_RESPONSE_CACHE_H_
diff --git a/chromium/net/tools/quic/quic_in_memory_cache_test.cc b/chromium/net/tools/quic/quic_http_response_cache_test.cc
index 249f6618f98..fa2fce6da94 100644
--- a/chromium/net/tools/quic/quic_in_memory_cache_test.cc
+++ b/chromium/net/tools/quic/quic_http_response_cache_test.cc
@@ -8,35 +8,27 @@
#include "base/memory/singleton.h"
#include "base/path_service.h"
#include "base/stl_util.h"
-#include "base/strings/string_number_conversions.h"
-#include "base/strings/string_piece.h"
-#include "base/strings/stringprintf.h"
+#include "net/quic/platform/api/quic_str_cat.h"
+#include "net/quic/platform/api/quic_text_utils.h"
#include "net/spdy/spdy_framer.h"
-#include "net/tools/quic/quic_in_memory_cache.h"
-#include "net/tools/quic/test_tools/quic_in_memory_cache_peer.h"
+#include "net/tools/quic/quic_http_response_cache.h"
#include "testing/gtest/include/gtest/gtest.h"
using base::ContainsKey;
-using base::IntToString;
using base::StringPiece;
using net::SpdyHeaderBlock;
-using std::list;
using std::string;
namespace net {
namespace test {
namespace {
-typedef QuicInMemoryCache::Response Response;
-typedef QuicInMemoryCache::ServerPushInfo ServerPushInfo;
+typedef QuicHttpResponseCache::Response Response;
+typedef QuicHttpResponseCache::ServerPushInfo ServerPushInfo;
}; // namespace
-class QuicInMemoryCacheTest : public ::testing::Test {
+class QuicHttpResponseCacheTest : public ::testing::Test {
protected:
- QuicInMemoryCacheTest() { QuicInMemoryCachePeer::ResetForTests(); }
-
- ~QuicInMemoryCacheTest() override { QuicInMemoryCachePeer::ResetForTests(); }
-
void CreateRequest(string host, string path, SpdyHeaderBlock* headers) {
(*headers)[":method"] = "GET";
(*headers)[":path"] = path;
@@ -48,35 +40,35 @@ class QuicInMemoryCacheTest : public ::testing::Test {
base::FilePath path;
PathService::Get(base::DIR_SOURCE_ROOT, &path);
path = path.AppendASCII("net").AppendASCII("data").AppendASCII(
- "quic_in_memory_cache_data");
+ "quic_http_response_cache_data");
// The file path is known to be an ascii string.
return path.MaybeAsASCII();
}
+
+ QuicHttpResponseCache cache_;
};
-TEST_F(QuicInMemoryCacheTest, GetResponseNoMatch) {
- const QuicInMemoryCache::Response* response =
- QuicInMemoryCache::GetInstance()->GetResponse("mail.google.com",
- "/index.html");
+TEST_F(QuicHttpResponseCacheTest, GetResponseNoMatch) {
+ const QuicHttpResponseCache::Response* response =
+ cache_.GetResponse("mail.google.com", "/index.html");
ASSERT_FALSE(response);
}
-TEST_F(QuicInMemoryCacheTest, AddSimpleResponseGetResponse) {
+TEST_F(QuicHttpResponseCacheTest, AddSimpleResponseGetResponse) {
string response_body("hello response");
- QuicInMemoryCache* cache = QuicInMemoryCache::GetInstance();
- cache->AddSimpleResponse("www.google.com", "/", 200, response_body);
+ cache_.AddSimpleResponse("www.google.com", "/", 200, response_body);
SpdyHeaderBlock request_headers;
CreateRequest("www.google.com", "/", &request_headers);
- const QuicInMemoryCache::Response* response =
- cache->GetResponse("www.google.com", "/");
+ const QuicHttpResponseCache::Response* response =
+ cache_.GetResponse("www.google.com", "/");
ASSERT_TRUE(response);
ASSERT_TRUE(ContainsKey(response->headers(), ":status"));
EXPECT_EQ("200", response->headers().find(":status")->second);
EXPECT_EQ(response_body.size(), response->body().length());
}
-TEST_F(QuicInMemoryCacheTest, AddResponse) {
+TEST_F(QuicHttpResponseCacheTest, AddResponse) {
const string kRequestHost = "www.foo.com";
const string kRequestPath = "/";
const string kResponseBody("hello response");
@@ -84,71 +76,66 @@ TEST_F(QuicInMemoryCacheTest, AddResponse) {
SpdyHeaderBlock response_headers;
response_headers[":version"] = "HTTP/1.1";
response_headers[":status"] = "200";
- response_headers["content-length"] = IntToString(kResponseBody.size());
+ response_headers["content-length"] =
+ QuicTextUtils::Uint64ToString(kResponseBody.size());
SpdyHeaderBlock response_trailers;
response_trailers["key-1"] = "value-1";
response_trailers["key-2"] = "value-2";
response_trailers["key-3"] = "value-3";
- QuicInMemoryCache* cache = QuicInMemoryCache::GetInstance();
- cache->AddResponse(kRequestHost, "/", response_headers.Clone(), kResponseBody,
+ cache_.AddResponse(kRequestHost, "/", response_headers.Clone(), kResponseBody,
response_trailers.Clone());
- const QuicInMemoryCache::Response* response =
- cache->GetResponse(kRequestHost, kRequestPath);
+ const QuicHttpResponseCache::Response* response =
+ cache_.GetResponse(kRequestHost, kRequestPath);
EXPECT_EQ(response->headers(), response_headers);
EXPECT_EQ(response->body(), kResponseBody);
EXPECT_EQ(response->trailers(), response_trailers);
}
-TEST_F(QuicInMemoryCacheTest, ReadsCacheDir) {
- QuicInMemoryCache::GetInstance()->InitializeFromDirectory(CacheDirectory());
- const QuicInMemoryCache::Response* response =
- QuicInMemoryCache::GetInstance()->GetResponse("quic.test.url",
- "/index.html");
+TEST_F(QuicHttpResponseCacheTest, ReadsCacheDir) {
+ cache_.InitializeFromDirectory(CacheDirectory());
+ const QuicHttpResponseCache::Response* response =
+ cache_.GetResponse("www.example.com", "/index.html");
ASSERT_TRUE(response);
ASSERT_TRUE(ContainsKey(response->headers(), ":status"));
EXPECT_EQ("200", response->headers().find(":status")->second);
- ASSERT_FALSE(ContainsKey(response->headers(), "connection"));
+ // Connection headers are not valid in HTTP/2.
+ EXPECT_FALSE(ContainsKey(response->headers(), "connection"));
EXPECT_LT(0U, response->body().length());
}
-TEST_F(QuicInMemoryCacheTest, ReadsCacheDirWithServerPushResource) {
- QuicInMemoryCache::GetInstance()->InitializeFromDirectory(CacheDirectory() +
- "_with_push");
- QuicInMemoryCache* cache = QuicInMemoryCache::GetInstance();
- list<ServerPushInfo> resources =
- cache->GetServerPushResources("quic.test.url/");
+TEST_F(QuicHttpResponseCacheTest, ReadsCacheDirWithServerPushResource) {
+ cache_.InitializeFromDirectory(CacheDirectory() + "_with_push");
+ std::list<ServerPushInfo> resources =
+ cache_.GetServerPushResources("www.example.com/");
ASSERT_EQ(1UL, resources.size());
}
-TEST_F(QuicInMemoryCacheTest, ReadsCacheDirWithServerPushResources) {
- QuicInMemoryCache::GetInstance()->InitializeFromDirectory(CacheDirectory() +
- "_with_push");
- QuicInMemoryCache* cache = QuicInMemoryCache::GetInstance();
- list<ServerPushInfo> resources =
- cache->GetServerPushResources("quic.test.url/index2.html");
+TEST_F(QuicHttpResponseCacheTest, ReadsCacheDirWithServerPushResources) {
+ cache_.InitializeFromDirectory(CacheDirectory() + "_with_push");
+ std::list<ServerPushInfo> resources =
+ cache_.GetServerPushResources("www.example.com/index2.html");
ASSERT_EQ(2UL, resources.size());
}
-TEST_F(QuicInMemoryCacheTest, UsesOriginalUrl) {
- QuicInMemoryCache::GetInstance()->InitializeFromDirectory(CacheDirectory());
- const QuicInMemoryCache::Response* response =
- QuicInMemoryCache::GetInstance()->GetResponse("quic.test.url",
- "/index.html");
+TEST_F(QuicHttpResponseCacheTest, UsesOriginalUrl) {
+ cache_.InitializeFromDirectory(CacheDirectory());
+ const QuicHttpResponseCache::Response* response =
+ cache_.GetResponse("www.example.com", "/site_map.html");
ASSERT_TRUE(response);
ASSERT_TRUE(ContainsKey(response->headers(), ":status"));
EXPECT_EQ("200", response->headers().find(":status")->second);
- ASSERT_FALSE(ContainsKey(response->headers(), "connection"));
+ // Connection headers are not valid in HTTP/2.
+ EXPECT_FALSE(ContainsKey(response->headers(), "connection"));
EXPECT_LT(0U, response->body().length());
}
-TEST_F(QuicInMemoryCacheTest, DefaultResponse) {
+TEST_F(QuicHttpResponseCacheTest, DefaultResponse) {
// Verify GetResponse returns nullptr when no default is set.
- QuicInMemoryCache* cache = QuicInMemoryCache::GetInstance();
- const QuicInMemoryCache::Response* response =
- cache->GetResponse("www.google.com", "/");
+ const QuicHttpResponseCache::Response* response =
+ cache_.GetResponse("www.google.com", "/");
ASSERT_FALSE(response);
// Add a default response.
@@ -156,56 +143,57 @@ TEST_F(QuicInMemoryCacheTest, DefaultResponse) {
response_headers[":version"] = "HTTP/1.1";
response_headers[":status"] = "200";
response_headers["content-length"] = "0";
- QuicInMemoryCache::Response* default_response =
- new QuicInMemoryCache::Response;
+ QuicHttpResponseCache::Response* default_response =
+ new QuicHttpResponseCache::Response;
default_response->set_headers(std::move(response_headers));
- cache->AddDefaultResponse(default_response);
+ cache_.AddDefaultResponse(default_response);
// Now we should get the default response for the original request.
- response = cache->GetResponse("www.google.com", "/");
+ response = cache_.GetResponse("www.google.com", "/");
ASSERT_TRUE(response);
ASSERT_TRUE(ContainsKey(response->headers(), ":status"));
EXPECT_EQ("200", response->headers().find(":status")->second);
// Now add a set response for / and make sure it is returned
- cache->AddSimpleResponse("www.google.com", "/", 302, "");
- response = cache->GetResponse("www.google.com", "/");
+ cache_.AddSimpleResponse("www.google.com", "/", 302, "");
+ response = cache_.GetResponse("www.google.com", "/");
ASSERT_TRUE(response);
ASSERT_TRUE(ContainsKey(response->headers(), ":status"));
EXPECT_EQ("302", response->headers().find(":status")->second);
// We should get the default response for other requests.
- response = cache->GetResponse("www.google.com", "/asd");
+ response = cache_.GetResponse("www.google.com", "/asd");
ASSERT_TRUE(response);
ASSERT_TRUE(ContainsKey(response->headers(), ":status"));
EXPECT_EQ("200", response->headers().find(":status")->second);
}
-TEST_F(QuicInMemoryCacheTest, AddSimpleResponseWithServerPushResources) {
+TEST_F(QuicHttpResponseCacheTest, AddSimpleResponseWithServerPushResources) {
string request_host = "www.foo.com";
string response_body("hello response");
const size_t kNumResources = 5;
int NumResources = 5;
- list<QuicInMemoryCache::ServerPushInfo> push_resources;
+ std::list<QuicHttpResponseCache::ServerPushInfo> push_resources;
string scheme = "http";
for (int i = 0; i < NumResources; ++i) {
- string path = "/server_push_src" + base::IntToString(i);
+ string path = "/server_push_src" + QuicTextUtils::Uint64ToString(i);
string url = scheme + "://" + request_host + path;
GURL resource_url(url);
- string body = "This is server push response body for " + path;
+ string body = QuicStrCat("This is server push response body for ", path);
SpdyHeaderBlock response_headers;
response_headers[":version"] = "HTTP/1.1";
response_headers[":status"] = "200";
- response_headers["content-length"] = base::UintToString(body.size());
+ response_headers["content-length"] =
+ QuicTextUtils::Uint64ToString(body.size());
push_resources.push_back(
ServerPushInfo(resource_url, response_headers.Clone(), i, body));
}
- QuicInMemoryCache* cache = QuicInMemoryCache::GetInstance();
- cache->AddSimpleResponseWithServerPushResources(
+ cache_.AddSimpleResponseWithServerPushResources(
request_host, "/", 200, response_body, push_resources);
string request_url = request_host + "/";
- list<ServerPushInfo> resources = cache->GetServerPushResources(request_url);
+ std::list<ServerPushInfo> resources =
+ cache_.GetServerPushResources(request_url);
ASSERT_EQ(kNumResources, resources.size());
for (const auto& push_resource : push_resources) {
ServerPushInfo resource = resources.front();
@@ -215,39 +203,40 @@ TEST_F(QuicInMemoryCacheTest, AddSimpleResponseWithServerPushResources) {
}
}
-TEST_F(QuicInMemoryCacheTest, GetServerPushResourcesAndPushResponses) {
+TEST_F(QuicHttpResponseCacheTest, GetServerPushResourcesAndPushResponses) {
string request_host = "www.foo.com";
string response_body("hello response");
const size_t kNumResources = 4;
int NumResources = 4;
string scheme = "http";
string push_response_status[kNumResources] = {"200", "200", "301", "404"};
- list<QuicInMemoryCache::ServerPushInfo> push_resources;
+ std::list<QuicHttpResponseCache::ServerPushInfo> push_resources;
for (int i = 0; i < NumResources; ++i) {
- string path = "/server_push_src" + base::IntToString(i);
+ string path = "/server_push_src" + QuicTextUtils::Uint64ToString(i);
string url = scheme + "://" + request_host + path;
GURL resource_url(url);
string body = "This is server push response body for " + path;
SpdyHeaderBlock response_headers;
response_headers[":version"] = "HTTP/1.1";
response_headers[":status"] = push_response_status[i];
- response_headers["content-length"] = base::UintToString(body.size());
+ response_headers["content-length"] =
+ QuicTextUtils::Uint64ToString(body.size());
push_resources.push_back(
ServerPushInfo(resource_url, response_headers.Clone(), i, body));
}
- QuicInMemoryCache* cache = QuicInMemoryCache::GetInstance();
- cache->AddSimpleResponseWithServerPushResources(
+ cache_.AddSimpleResponseWithServerPushResources(
request_host, "/", 200, response_body, push_resources);
string request_url = request_host + "/";
- list<ServerPushInfo> resources = cache->GetServerPushResources(request_url);
+ std::list<ServerPushInfo> resources =
+ cache_.GetServerPushResources(request_url);
ASSERT_EQ(kNumResources, resources.size());
int i = 0;
for (const auto& push_resource : push_resources) {
GURL url = resources.front().request_url;
string host = url.host();
string path = url.path();
- const QuicInMemoryCache::Response* response =
- cache->GetResponse(host, path);
+ const QuicHttpResponseCache::Response* response =
+ cache_.GetResponse(host, path);
ASSERT_TRUE(response);
ASSERT_TRUE(ContainsKey(response->headers(), ":status"));
EXPECT_EQ(push_response_status[i++],
diff --git a/chromium/net/tools/quic/quic_packet_printer_bin.cc b/chromium/net/tools/quic/quic_packet_printer_bin.cc
index b6bfaedb929..2ba19b93a04 100644
--- a/chromium/net/tools/quic/quic_packet_printer_bin.cc
+++ b/chromium/net/tools/quic/quic_packet_printer_bin.cc
@@ -21,11 +21,10 @@
// OnUnauthenticatedPublicHeader
// OnUnauthenticatedHeader: { connection_id: 13845207862000976235,
// connection_id_length:8, packet_number_length:1, multipath_flag: 0,
-// reset_flag: 0, version_flag: 0, entropy_flag: 0, entropy hash: 0, path_id: ,
-// packet_number: 4}
+// reset_flag: 0, version_flag: 0, path_id: , packet_number: 4}
// OnDecryptedPacket
// OnPacketHeader
-// OnAckFrame: entropy_hash: 2 largest_observed: 1 ack_delay_time: 3000
+// OnAckFrame: largest_observed: 1 ack_delay_time: 3000
// missing_packets: [ ] is_truncated: 0 received_packets: [ 1 at 466016 ]
// OnStopWaitingFrame
// OnConnectionCloseFrame: error_code { 61 } error_details { Unencrypted stream
@@ -37,10 +36,10 @@
#include <string>
#include "base/command_line.h"
-#include "base/strings/string_number_conversions.h"
#include "base/strings/utf_string_conversions.h"
#include "net/quic/core/quic_framer.h"
#include "net/quic/core/quic_utils.h"
+#include "net/quic/platform/api/quic_text_utils.h"
using std::cerr;
using std::string;
@@ -66,7 +65,7 @@ class QuicPacketPrinter : public QuicFramerVisitorInterface {
explicit QuicPacketPrinter(QuicFramer* framer) : framer_(framer) {}
void OnError(QuicFramer* framer) override {
- cerr << "OnError: " << QuicUtils::ErrorToString(framer->error())
+ cerr << "OnError: " << QuicErrorCodeToString(framer->error())
<< " detail: " << framer->detailed_error() << "\n";
}
bool OnProtocolVersionMismatch(QuicVersion received_version) override {
@@ -104,7 +103,7 @@ class QuicPacketPrinter : public QuicFramerVisitorInterface {
bool OnStreamFrame(const QuicStreamFrame& frame) override {
cerr << "OnStreamFrame: " << frame;
cerr << " data: { "
- << QuicUtils::HexEncode(frame.data_buffer, frame.data_length)
+ << QuicTextUtils::HexEncode(frame.data_buffer, frame.data_length)
<< " }\n";
return true;
}
@@ -182,7 +181,7 @@ int main(int argc, char* argv[]) {
<< " Usage: " << args[0] << " client|server <hex>\n";
return 1;
}
- string hex = net::QuicUtils::HexDecode(ArgToString(args[1]));
+ string hex = net::QuicTextUtils::HexDecode(argv[2]);
net::QuicVersionVector versions = net::AllSupportedVersions();
// Fake a time since we're not actually generating acks.
net::QuicTime start(net::QuicTime::Zero());
diff --git a/chromium/net/tools/quic/quic_packet_reader.cc b/chromium/net/tools/quic/quic_packet_reader.cc
index 0d0c613bc35..27deb9635e0 100644
--- a/chromium/net/tools/quic/quic_packet_reader.cc
+++ b/chromium/net/tools/quic/quic_packet_reader.cc
@@ -10,18 +10,14 @@
#include <features.h>
#endif
#include <string.h>
-#include <sys/epoll.h>
-#include "base/logging.h"
-#include "net/base/ip_address.h"
-#include "net/base/ip_endpoint.h"
-#include "net/quic/core/quic_bug_tracker.h"
#include "net/quic/core/quic_flags.h"
+#include "net/quic/platform/api/quic_bug_tracker.h"
+#include "net/quic/platform/api/quic_logging.h"
+#include "net/quic/platform/api/quic_socket_address.h"
+#include "net/tools/quic/platform/impl/quic_socket_utils.h"
#include "net/tools/quic/quic_dispatcher.h"
#include "net/tools/quic/quic_process_packet_interface.h"
-#include "net/tools/quic/quic_socket_utils.h"
-
-#define MMSG_MORE 0
#ifndef SO_RXQ_OVFL
#define SO_RXQ_OVFL 40
@@ -111,12 +107,13 @@ bool QuicPacketReader::ReadAndDispatchManyPackets(
continue;
}
- IPEndPoint client_address = IPEndPoint(packets_[i].raw_address);
- IPAddress server_ip;
+ QuicSocketAddress client_address =
+ QuicSocketAddress(packets_[i].raw_address);
+ QuicIpAddress server_ip;
QuicWallTime packet_walltimestamp = QuicWallTime::Zero();
QuicSocketUtils::GetAddressAndTimestampFromMsghdr(
&mmsg_hdr_[i].msg_hdr, &server_ip, &packet_walltimestamp);
- if (!IsInitializedAddress(server_ip)) {
+ if (!server_ip.IsInitialized()) {
QUIC_BUG << "Unable to get server address.";
continue;
}
@@ -136,7 +133,7 @@ bool QuicPacketReader::ReadAndDispatchManyPackets(
QuicReceivedPacket packet(reinterpret_cast<char*>(packets_[i].iov.iov_base),
mmsg_hdr_[i].msg_len, timestamp, false, ttl,
has_ttl);
- IPEndPoint server_address(server_ip, port);
+ QuicSocketAddress server_address(server_ip, port);
processor->ProcessPacket(server_address, client_address, packet);
}
@@ -148,7 +145,7 @@ bool QuicPacketReader::ReadAndDispatchManyPackets(
// We may not have read all of the packets available on the socket.
return packets_read == kNumPacketsPerReadMmsgCall;
#else
- LOG(FATAL) << "Unsupported";
+ QUIC_LOG(FATAL) << "Unsupported";
return false;
#endif
}
@@ -162,8 +159,8 @@ bool QuicPacketReader::ReadAndDispatchSinglePacket(
QuicPacketCount* packets_dropped) {
char buf[kMaxPacketSize];
- IPEndPoint client_address;
- IPAddress server_ip;
+ QuicSocketAddress client_address;
+ QuicIpAddress server_ip;
QuicWallTime walltimestamp = QuicWallTime::Zero();
int bytes_read =
QuicSocketUtils::ReadPacket(fd, buf, arraysize(buf), packets_dropped,
@@ -172,7 +169,7 @@ bool QuicPacketReader::ReadAndDispatchSinglePacket(
return false; // ReadPacket failed.
}
- if (server_ip.empty()) {
+ if (!server_ip.IsInitialized()) {
QUIC_BUG << "Unable to get server address.";
return false;
}
@@ -184,7 +181,7 @@ bool QuicPacketReader::ReadAndDispatchSinglePacket(
QuicTime timestamp = clock.ConvertWallTimeToQuicTime(walltimestamp);
QuicReceivedPacket packet(buf, bytes_read, timestamp, false);
- IPEndPoint server_address(server_ip, port);
+ QuicSocketAddress server_address(server_ip, port);
processor->ProcessPacket(server_address, client_address, packet);
// The socket read was successful, so return true even if packet dispatch
diff --git a/chromium/net/tools/quic/quic_packet_reader.h b/chromium/net/tools/quic/quic_packet_reader.h
index 423783f1a6f..13a8ccc89a0 100644
--- a/chromium/net/tools/quic/quic_packet_reader.h
+++ b/chromium/net/tools/quic/quic_packet_reader.h
@@ -8,13 +8,16 @@
#define NET_TOOLS_QUIC_QUIC_PACKET_READER_H_
#include <netinet/in.h>
+// Include here to guarantee this header gets included (for MSG_WAITFORONE)
+// regardless of how the below transitive header include set may change.
#include <sys/socket.h>
#include "base/macros.h"
-#include "net/quic/core/quic_clock.h"
-#include "net/quic/core/quic_protocol.h"
+#include "net/quic/core/quic_packets.h"
+#include "net/quic/platform/api/quic_clock.h"
+#include "net/quic/platform/api/quic_socket_address.h"
+#include "net/tools/quic/platform/impl/quic_socket_utils.h"
#include "net/tools/quic/quic_process_packet_interface.h"
-#include "net/tools/quic/quic_socket_utils.h"
#define MMSG_MORE 0
@@ -25,12 +28,6 @@ namespace net {
const int kNumPacketsPerReadMmsgCall = 16;
#endif
-namespace test {
-class QuicServerPeer;
-} // namespace test
-
-class QuicDispatcher;
-
class QuicPacketReader {
public:
QuicPacketReader();
diff --git a/chromium/net/tools/quic/quic_packet_writer_wrapper.cc b/chromium/net/tools/quic/quic_packet_writer_wrapper.cc
index 6903c29369b..1104e69a786 100644
--- a/chromium/net/tools/quic/quic_packet_writer_wrapper.cc
+++ b/chromium/net/tools/quic/quic_packet_writer_wrapper.cc
@@ -12,11 +12,12 @@ QuicPacketWriterWrapper::QuicPacketWriterWrapper() {}
QuicPacketWriterWrapper::~QuicPacketWriterWrapper() {}
-WriteResult QuicPacketWriterWrapper::WritePacket(const char* buffer,
- size_t buf_len,
- const IPAddress& self_address,
- const IPEndPoint& peer_address,
- PerPacketOptions* options) {
+WriteResult QuicPacketWriterWrapper::WritePacket(
+ const char* buffer,
+ size_t buf_len,
+ const QuicIpAddress& self_address,
+ const QuicSocketAddress& peer_address,
+ PerPacketOptions* options) {
return writer_->WritePacket(buffer, buf_len, self_address, peer_address,
options);
}
@@ -34,7 +35,7 @@ void QuicPacketWriterWrapper::SetWritable() {
}
QuicByteCount QuicPacketWriterWrapper::GetMaxPacketSize(
- const IPEndPoint& peer_address) const {
+ const QuicSocketAddress& peer_address) const {
return writer_->GetMaxPacketSize(peer_address);
}
diff --git a/chromium/net/tools/quic/quic_packet_writer_wrapper.h b/chromium/net/tools/quic/quic_packet_writer_wrapper.h
index 6486ec60bc3..4fc75c6b8ef 100644
--- a/chromium/net/tools/quic/quic_packet_writer_wrapper.h
+++ b/chromium/net/tools/quic/quic_packet_writer_wrapper.h
@@ -26,13 +26,14 @@ class QuicPacketWriterWrapper : public QuicPacketWriter {
// to |writer_|.
WriteResult WritePacket(const char* buffer,
size_t buf_len,
- const IPAddress& self_address,
- const IPEndPoint& peer_address,
+ const QuicIpAddress& self_address,
+ const QuicSocketAddress& peer_address,
PerPacketOptions* options) override;
bool IsWriteBlockedDataBuffered() const override;
bool IsWriteBlocked() const override;
void SetWritable() override;
- QuicByteCount GetMaxPacketSize(const IPEndPoint& peer_address) const override;
+ QuicByteCount GetMaxPacketSize(
+ const QuicSocketAddress& peer_address) const override;
// Takes ownership of |writer|.
void set_writer(QuicPacketWriter* writer);
diff --git a/chromium/net/tools/quic/quic_per_connection_packet_writer.cc b/chromium/net/tools/quic/quic_per_connection_packet_writer.cc
index a83179400cf..0d98cc82bf2 100644
--- a/chromium/net/tools/quic/quic_per_connection_packet_writer.cc
+++ b/chromium/net/tools/quic/quic_per_connection_packet_writer.cc
@@ -15,8 +15,8 @@ QuicPerConnectionPacketWriter::~QuicPerConnectionPacketWriter() {}
WriteResult QuicPerConnectionPacketWriter::WritePacket(
const char* buffer,
size_t buf_len,
- const IPAddress& self_address,
- const IPEndPoint& peer_address,
+ const QuicIpAddress& self_address,
+ const QuicSocketAddress& peer_address,
PerPacketOptions* options) {
return shared_writer_->WritePacket(buffer, buf_len, self_address,
peer_address, options);
@@ -35,7 +35,7 @@ void QuicPerConnectionPacketWriter::SetWritable() {
}
QuicByteCount QuicPerConnectionPacketWriter::GetMaxPacketSize(
- const IPEndPoint& peer_address) const {
+ const QuicSocketAddress& peer_address) const {
return shared_writer_->GetMaxPacketSize(peer_address);
}
diff --git a/chromium/net/tools/quic/quic_per_connection_packet_writer.h b/chromium/net/tools/quic/quic_per_connection_packet_writer.h
index cc48b635e14..35e9131460e 100644
--- a/chromium/net/tools/quic/quic_per_connection_packet_writer.h
+++ b/chromium/net/tools/quic/quic_per_connection_packet_writer.h
@@ -20,19 +20,18 @@ class QuicPerConnectionPacketWriter : public QuicPacketWriter {
explicit QuicPerConnectionPacketWriter(QuicPacketWriter* shared_writer);
~QuicPerConnectionPacketWriter() override;
- QuicPacketWriter* shared_writer() const { return shared_writer_; }
-
// Default implementation of the QuicPacketWriter interface: Passes everything
// to |shared_writer_|.
WriteResult WritePacket(const char* buffer,
size_t buf_len,
- const IPAddress& self_address,
- const IPEndPoint& peer_address,
+ const QuicIpAddress& self_address,
+ const QuicSocketAddress& peer_address,
PerPacketOptions* options) override;
bool IsWriteBlockedDataBuffered() const override;
bool IsWriteBlocked() const override;
void SetWritable() override;
- QuicByteCount GetMaxPacketSize(const IPEndPoint& peer_address) const override;
+ QuicByteCount GetMaxPacketSize(
+ const QuicSocketAddress& peer_address) const override;
private:
QuicPacketWriter* shared_writer_; // Not owned.
diff --git a/chromium/net/tools/quic/quic_process_packet_interface.h b/chromium/net/tools/quic/quic_process_packet_interface.h
index 600bc70844b..e960788d4c2 100644
--- a/chromium/net/tools/quic/quic_process_packet_interface.h
+++ b/chromium/net/tools/quic/quic_process_packet_interface.h
@@ -6,8 +6,8 @@
#define NET_TOOLS_QUIC_QUIC_PROCESS_PACKET_INTERFACE_H_
#include "base/macros.h"
-#include "net/base/ip_endpoint.h"
-#include "net/quic/core/quic_protocol.h"
+#include "net/quic/core/quic_packets.h"
+#include "net/quic/platform/api/quic_socket_address.h"
namespace net {
@@ -15,8 +15,8 @@ namespace net {
class ProcessPacketInterface {
public:
virtual ~ProcessPacketInterface() {}
- virtual void ProcessPacket(const IPEndPoint& server_address,
- const IPEndPoint& client_address,
+ virtual void ProcessPacket(const QuicSocketAddress& server_address,
+ const QuicSocketAddress& client_address,
const QuicReceivedPacket& packet) = 0;
};
diff --git a/chromium/net/tools/quic/quic_server.cc b/chromium/net/tools/quic/quic_server.cc
index 99ae8cbc3b9..69dd41a9b42 100644
--- a/chromium/net/tools/quic/quic_server.cc
+++ b/chromium/net/tools/quic/quic_server.cc
@@ -17,31 +17,30 @@
#include "net/base/sockaddr_storage.h"
#include "net/quic/core/crypto/crypto_handshake.h"
#include "net/quic/core/crypto/quic_random.h"
-#include "net/quic/core/quic_clock.h"
#include "net/quic/core/quic_crypto_stream.h"
#include "net/quic/core/quic_data_reader.h"
-#include "net/quic/core/quic_protocol.h"
+#include "net/quic/core/quic_packets.h"
+#include "net/quic/platform/api/quic_logging.h"
+#include "net/tools/quic/platform/impl/quic_epoll_clock.h"
+#include "net/tools/quic/platform/impl/quic_socket_utils.h"
#include "net/tools/quic/quic_dispatcher.h"
#include "net/tools/quic/quic_epoll_alarm_factory.h"
-#include "net/tools/quic/quic_epoll_clock.h"
#include "net/tools/quic/quic_epoll_connection_helper.h"
-#include "net/tools/quic/quic_in_memory_cache.h"
+#include "net/tools/quic/quic_http_response_cache.h"
#include "net/tools/quic/quic_packet_reader.h"
#include "net/tools/quic/quic_simple_crypto_server_stream_helper.h"
#include "net/tools/quic/quic_simple_dispatcher.h"
-#include "net/tools/quic/quic_socket_utils.h"
#ifndef SO_RXQ_OVFL
#define SO_RXQ_OVFL 40
#endif
-
namespace net {
namespace {
-// Specifies the directory used during QuicInMemoryCache
+// Specifies the directory used during QuicHttpResponseCache
// construction to seed the cache. Cache directory can be
// generated using `wget -p --save-headers <url>`
-std::string FLAGS_quic_in_memory_cache_dir = "";
+std::string FLAGS_quic_response_cache_dir = "";
const int kEpollFlags = EPOLLIN | EPOLLOUT | EPOLLET;
const char kSourceAddressTokenSecret[] = "secret";
@@ -50,17 +49,20 @@ const char kSourceAddressTokenSecret[] = "secret";
const size_t kNumSessionsToCreatePerSocketEvent = 16;
-QuicServer::QuicServer(std::unique_ptr<ProofSource> proof_source)
+QuicServer::QuicServer(std::unique_ptr<ProofSource> proof_source,
+ QuicHttpResponseCache* response_cache)
: QuicServer(std::move(proof_source),
QuicConfig(),
QuicCryptoServerConfig::ConfigOptions(),
- AllSupportedVersions()) {}
+ AllSupportedVersions(),
+ response_cache) {}
QuicServer::QuicServer(
std::unique_ptr<ProofSource> proof_source,
const QuicConfig& config,
const QuicCryptoServerConfig::ConfigOptions& crypto_config_options,
- const QuicVersionVector& supported_versions)
+ const QuicVersionVector& supported_versions,
+ QuicHttpResponseCache* response_cache)
: port_(0),
fd_(-1),
packets_dropped_(0),
@@ -71,7 +73,8 @@ QuicServer::QuicServer(
std::move(proof_source)),
crypto_config_options_(crypto_config_options),
version_manager_(supported_versions),
- packet_reader_(new QuicPacketReader()) {
+ packet_reader_(new QuicPacketReader()),
+ response_cache_(response_cache) {
Initialize();
}
@@ -93,9 +96,8 @@ void QuicServer::Initialize() {
epoll_server_.set_timeout_in_us(50 * 1000);
- if (!FLAGS_quic_in_memory_cache_dir.empty()) {
- QuicInMemoryCache::GetInstance()->InitializeFromDirectory(
- FLAGS_quic_in_memory_cache_dir);
+ if (!FLAGS_quic_response_cache_dir.empty()) {
+ response_cache_->InitializeFromDirectory(FLAGS_quic_response_cache_dir);
}
QuicEpollClock clock(&epoll_server_);
@@ -106,35 +108,28 @@ void QuicServer::Initialize() {
QuicServer::~QuicServer() {}
-bool QuicServer::CreateUDPSocketAndListen(const IPEndPoint& address) {
+bool QuicServer::CreateUDPSocketAndListen(const QuicSocketAddress& address) {
fd_ = QuicSocketUtils::CreateUDPSocket(address, &overflow_supported_);
if (fd_ < 0) {
LOG(ERROR) << "CreateSocket() failed: " << strerror(errno);
return false;
}
- sockaddr_storage raw_addr;
- socklen_t raw_addr_len = sizeof(raw_addr);
- CHECK(address.ToSockAddr(reinterpret_cast<sockaddr*>(&raw_addr),
- &raw_addr_len));
- int rc =
- bind(fd_, reinterpret_cast<const sockaddr*>(&raw_addr), sizeof(raw_addr));
+ sockaddr_storage addr = address.generic_address();
+ int rc = bind(fd_, reinterpret_cast<sockaddr*>(&addr), sizeof(addr));
if (rc < 0) {
- LOG(ERROR) << "Bind failed: " << strerror(errno);
+ QUIC_LOG(ERROR) << "Bind failed: " << strerror(errno);
return false;
}
-
- DVLOG(1) << "Listening on " << address.ToString();
+ QUIC_LOG(INFO) << "Listening on " << address.ToString();
+ port_ = address.port();
if (port_ == 0) {
- SockaddrStorage storage;
- IPEndPoint server_address;
- if (getsockname(fd_, storage.addr, &storage.addr_len) != 0 ||
- !server_address.FromSockAddr(storage.addr, storage.addr_len)) {
- LOG(ERROR) << "Unable to get self address. Error: " << strerror(errno);
- return false;
+ QuicSocketAddress address;
+ if (address.FromSocket(fd_) != 0) {
+ QUIC_LOG(ERROR) << "Unable to get self address. Error: "
+ << strerror(errno);
}
- port_ = server_address.port();
- DVLOG(1) << "Kernel assigned port is " << port_;
+ port_ = address.port();
}
epoll_server_.RegisterFD(fd_, this, kEpollFlags);
@@ -157,7 +152,8 @@ QuicDispatcher* QuicServer::CreateQuicDispatcher() {
std::unique_ptr<QuicCryptoServerStream::Helper>(
new QuicSimpleCryptoServerStreamHelper(QuicRandom::GetInstance())),
std::unique_ptr<QuicEpollAlarmFactory>(
- new QuicEpollAlarmFactory(&epoll_server_)));
+ new QuicEpollAlarmFactory(&epoll_server_)),
+ response_cache_);
}
void QuicServer::WaitForEvents() {
@@ -180,7 +176,7 @@ void QuicServer::OnEvent(int fd, EpollEvent* event) {
if (event->in_events & EPOLLIN) {
DVLOG(1) << "EPOLLIN";
- if (FLAGS_quic_limit_num_new_sessions_per_epoll_loop) {
+ if (FLAGS_quic_reloadable_flag_quic_limit_num_new_sessions_per_epoll_loop) {
dispatcher_->ProcessBufferedChlos(kNumSessionsToCreatePerSocketEvent);
}
@@ -191,7 +187,7 @@ void QuicServer::OnEvent(int fd, EpollEvent* event) {
overflow_supported_ ? &packets_dropped_ : nullptr);
}
- if (FLAGS_quic_limit_num_new_sessions_per_epoll_loop &&
+ if (FLAGS_quic_reloadable_flag_quic_limit_num_new_sessions_per_epoll_loop &&
dispatcher_->HasChlosBuffered()) {
// Register EPOLLIN event to consume buffered CHLO(s).
event->out_ready_mask |= EPOLLIN;
diff --git a/chromium/net/tools/quic/quic_server.h b/chromium/net/tools/quic/quic_server.h
index 0a5b9035e6e..7bce8e6b05c 100644
--- a/chromium/net/tools/quic/quic_server.h
+++ b/chromium/net/tools/quic/quic_server.h
@@ -16,13 +16,15 @@
#include <memory>
#include "base/macros.h"
-#include "net/base/ip_endpoint.h"
#include "net/quic/chromium/quic_chromium_connection_helper.h"
#include "net/quic/core/crypto/quic_crypto_server_config.h"
#include "net/quic/core/quic_config.h"
#include "net/quic/core/quic_framer.h"
+#include "net/quic/core/quic_version_manager.h"
+#include "net/quic/platform/api/quic_socket_address.h"
#include "net/tools/epoll_server/epoll_server.h"
#include "net/tools/quic/quic_default_packet_writer.h"
+#include "net/tools/quic/quic_http_response_cache.h"
namespace net {
@@ -35,16 +37,18 @@ class QuicPacketReader;
class QuicServer : public EpollCallbackInterface {
public:
- explicit QuicServer(std::unique_ptr<ProofSource> proof_source);
+ QuicServer(std::unique_ptr<ProofSource> proof_source,
+ QuicHttpResponseCache* response_cache);
QuicServer(std::unique_ptr<ProofSource> proof_source,
const QuicConfig& config,
const QuicCryptoServerConfig::ConfigOptions& server_config_options,
- const QuicVersionVector& supported_versions);
+ const QuicVersionVector& supported_versions,
+ QuicHttpResponseCache* response_cache);
~QuicServer() override;
// Start listening on the specified address.
- bool CreateUDPSocketAndListen(const IPEndPoint& address);
+ bool CreateUDPSocketAndListen(const QuicSocketAddress& address);
// Wait up to 50ms, and handle any events which occur.
void WaitForEvents();
@@ -60,10 +64,6 @@ class QuicServer : public EpollCallbackInterface {
void OnShutdown(EpollServer* eps, int fd) override {}
- void SetStrikeRegisterNoStartupPeriod() {
- crypto_config_.set_strike_register_no_startup_period();
- }
-
void SetChloMultiplier(size_t multiplier) {
crypto_config_.set_chlo_multiplier(multiplier);
}
@@ -87,6 +87,8 @@ class QuicServer : public EpollCallbackInterface {
QuicVersionManager* version_manager() { return &version_manager_; }
+ QuicHttpResponseCache* response_cache() { return response_cache_; }
+
private:
friend class net::test::QuicServerPeer;
@@ -128,6 +130,8 @@ class QuicServer : public EpollCallbackInterface {
// space than allowed on the stack.
std::unique_ptr<QuicPacketReader> packet_reader_;
+ QuicHttpResponseCache* response_cache_; // unowned.
+
DISALLOW_COPY_AND_ASSIGN(QuicServer);
};
diff --git a/chromium/net/tools/quic/quic_server_bin.cc b/chromium/net/tools/quic/quic_server_bin.cc
index b1eafd73f01..6fc25241361 100644
--- a/chromium/net/tools/quic/quic_server_bin.cc
+++ b/chromium/net/tools/quic/quic_server_bin.cc
@@ -12,11 +12,10 @@
#include "base/logging.h"
#include "base/run_loop.h"
#include "base/strings/string_number_conversions.h"
-#include "net/base/ip_address.h"
-#include "net/base/ip_endpoint.h"
#include "net/quic/chromium/crypto/proof_source_chromium.h"
-#include "net/quic/core/quic_protocol.h"
-#include "net/tools/quic/quic_in_memory_cache.h"
+#include "net/quic/core/quic_packets.h"
+#include "net/quic/platform/api/quic_socket_address.h"
+#include "net/tools/quic/quic_http_response_cache.h"
#include "net/tools/quic/quic_server.h"
// The port the quic server will listen on.
@@ -49,7 +48,7 @@ int main(int argc, char* argv[]) {
"Options:\n"
"-h, --help show this help message and exit\n"
"--port=<port> specify the port to listen on\n"
- "--quic_in_memory_cache_dir directory containing response data\n"
+ "--quic_response_cache_dir directory containing response data\n"
" to load\n"
"--certificate_file=<file> path to the certificate chain\n"
"--key_file=<file> path to the pkcs8 private key\n";
@@ -57,9 +56,10 @@ int main(int argc, char* argv[]) {
exit(0);
}
- if (line->HasSwitch("quic_in_memory_cache_dir")) {
- net::QuicInMemoryCache::GetInstance()->InitializeFromDirectory(
- line->GetSwitchValueASCII("quic_in_memory_cache_dir"));
+ net::QuicHttpResponseCache response_cache;
+ if (line->HasSwitch("quic_response_cache_dir")) {
+ response_cache.InitializeFromDirectory(
+ line->GetSwitchValueASCII("quic_response_cache_dir"));
}
if (line->HasSwitch("port")) {
@@ -79,17 +79,15 @@ int main(int argc, char* argv[]) {
return 1;
}
- auto ip = net::IPAddress::IPv6AllZeros();
-
net::QuicConfig config;
net::QuicServer server(
CreateProofSource(line->GetSwitchValuePath("certificate_file"),
line->GetSwitchValuePath("key_file")),
config, net::QuicCryptoServerConfig::ConfigOptions(),
- net::AllSupportedVersions());
- server.SetStrikeRegisterNoStartupPeriod();
+ net::AllSupportedVersions(), &response_cache);
- int rc = server.CreateUDPSocketAndListen(net::IPEndPoint(ip, FLAGS_port));
+ int rc = server.CreateUDPSocketAndListen(
+ net::QuicSocketAddress(net::QuicIpAddress::Any6(), FLAGS_port));
if (rc < 0) {
return 1;
}
diff --git a/chromium/net/tools/quic/quic_server_test.cc b/chromium/net/tools/quic/quic_server_test.cc
index 20724be2fcb..8c6584eb46b 100644
--- a/chromium/net/tools/quic/quic_server_test.cc
+++ b/chromium/net/tools/quic/quic_server_test.cc
@@ -6,6 +6,8 @@
#include "net/quic/core/crypto/quic_random.h"
#include "net/quic/core/quic_utils.h"
+#include "net/quic/platform/api/quic_logging.h"
+#include "net/quic/platform/api/quic_socket_address.h"
#include "net/quic/test_tools/crypto_test_utils.h"
#include "net/quic/test_tools/mock_quic_dispatcher.h"
#include "net/tools/quic/quic_epoll_alarm_factory.h"
@@ -15,8 +17,6 @@
#include "testing/gtest/include/gtest/gtest.h"
using ::testing::_;
-using net::test::CryptoTestUtils;
-using net::test::MockQuicDispatcher;
namespace net {
namespace test {
@@ -31,13 +31,15 @@ class MockQuicSimpleDispatcher : public QuicSimpleDispatcher {
QuicVersionManager* version_manager,
std::unique_ptr<QuicConnectionHelperInterface> helper,
std::unique_ptr<QuicCryptoServerStream::Helper> session_helper,
- std::unique_ptr<QuicAlarmFactory> alarm_factory)
+ std::unique_ptr<QuicAlarmFactory> alarm_factory,
+ QuicHttpResponseCache* response_cache)
: QuicSimpleDispatcher(config,
crypto_config,
version_manager,
std::move(helper),
std::move(session_helper),
- std::move(alarm_factory)) {}
+ std::move(alarm_factory),
+ response_cache) {}
~MockQuicSimpleDispatcher() override {}
MOCK_METHOD0(OnCanWrite, void());
@@ -48,7 +50,9 @@ class MockQuicSimpleDispatcher : public QuicSimpleDispatcher {
class TestQuicServer : public QuicServer {
public:
- TestQuicServer() : QuicServer(CryptoTestUtils::ProofSourceForTesting()) {}
+ TestQuicServer()
+ : QuicServer(CryptoTestUtils::ProofSourceForTesting(), &response_cache_) {
+ }
~TestQuicServer() override {}
@@ -64,24 +68,27 @@ class TestQuicServer : public QuicServer {
std::unique_ptr<QuicCryptoServerStream::Helper>(
new QuicSimpleCryptoServerStreamHelper(QuicRandom::GetInstance())),
std::unique_ptr<QuicEpollAlarmFactory>(
- new QuicEpollAlarmFactory(epoll_server())));
+ new QuicEpollAlarmFactory(epoll_server())),
+ &response_cache_);
return mock_dispatcher_;
}
MockQuicSimpleDispatcher* mock_dispatcher_;
+ QuicHttpResponseCache response_cache_;
};
class QuicServerEpollInTest : public ::testing::Test {
public:
QuicServerEpollInTest()
- : port_(net::test::kTestPort), server_address_(Loopback4(), port_) {}
+ : port_(net::test::kTestPort),
+ server_address_(QuicIpAddress::Loopback4(), port_) {}
void StartListening() {
server_.CreateUDPSocketAndListen(server_address_);
ASSERT_TRUE(QuicServerPeer::SetSmallSocket(&server_));
if (!server_.overflow_supported()) {
- LOG(WARNING) << "Overflow not supported. Not testing.";
+ QUIC_LOG(WARNING) << "Overflow not supported. Not testing.";
return;
}
}
@@ -89,7 +96,7 @@ class QuicServerEpollInTest : public ::testing::Test {
protected:
QuicFlagSaver saver_;
int port_;
- IPEndPoint server_address_;
+ QuicSocketAddress server_address_;
TestQuicServer server_;
};
@@ -97,7 +104,7 @@ class QuicServerEpollInTest : public ::testing::Test {
// event should try to create connections for them. And set epoll mask with
// EPOLLIN if there are still CHLOs remaining at the end of epoll event.
TEST_F(QuicServerEpollInTest, ProcessBufferedCHLOsOnEpollin) {
- FLAGS_quic_limit_num_new_sessions_per_epoll_loop = true;
+ FLAGS_quic_reloadable_flag_quic_limit_num_new_sessions_per_epoll_loop = true;
// Given an EPOLLIN event, try to create session for buffered CHLOs. In first
// event, dispatcher can't create session for all of CHLOs. So listener should
// register another EPOLLIN event by itself. Even without new packet arrival,
@@ -122,14 +129,12 @@ TEST_F(QuicServerEpollInTest, ProcessBufferedCHLOsOnEpollin) {
char buf[1024];
memset(buf, 0, arraysize(buf));
- sockaddr_storage storage;
+ sockaddr_storage storage = server_address_.generic_address();
socklen_t storage_size = sizeof(storage);
- ASSERT_TRUE(server_address_.ToSockAddr(reinterpret_cast<sockaddr*>(&storage),
- &storage_size));
int rc = sendto(fd, buf, arraysize(buf), 0,
reinterpret_cast<sockaddr*>(&storage), storage_size);
if (rc < 0) {
- DVLOG(1) << errno << " " << strerror(errno);
+ QUIC_DLOG(INFO) << errno << " " << strerror(errno);
}
while (more_chlos) {
@@ -155,12 +160,13 @@ class QuicServerDispatchPacketTest : public ::testing::Test {
new QuicSimpleCryptoServerStreamHelper(
QuicRandom::GetInstance())),
std::unique_ptr<QuicEpollAlarmFactory>(
- new QuicEpollAlarmFactory(&eps_))) {
+ new QuicEpollAlarmFactory(&eps_)),
+ &response_cache_) {
dispatcher_.InitializeWithWriter(new QuicDefaultPacketWriter(1234));
}
void DispatchPacket(const QuicReceivedPacket& packet) {
- IPEndPoint client_addr, server_addr;
+ QuicSocketAddress client_addr, server_addr;
dispatcher_.ProcessPacket(server_addr, client_addr, packet);
}
@@ -169,6 +175,7 @@ class QuicServerDispatchPacketTest : public ::testing::Test {
QuicCryptoServerConfig crypto_config_;
QuicVersionManager version_manager_;
EpollServer eps_;
+ QuicHttpResponseCache response_cache_;
MockQuicDispatcher dispatcher_;
};
@@ -187,9 +194,9 @@ TEST_F(QuicServerDispatchPacketTest, DispatchPacket) {
0x00
};
// clang-format on
- QuicReceivedPacket encrypted_valid_packet(QuicUtils::AsChars(valid_packet),
- arraysize(valid_packet),
- QuicTime::Zero(), false);
+ QuicReceivedPacket encrypted_valid_packet(
+ reinterpret_cast<char*>(valid_packet), arraysize(valid_packet),
+ QuicTime::Zero(), false);
EXPECT_CALL(dispatcher_, ProcessPacket(_, _, _)).Times(1);
DispatchPacket(encrypted_valid_packet);
diff --git a/chromium/net/tools/quic/quic_simple_client.cc b/chromium/net/tools/quic/quic_simple_client.cc
index ad210d382ef..9d9528e4817 100644
--- a/chromium/net/tools/quic/quic_simple_client.cc
+++ b/chromium/net/tools/quic/quic_simple_client.cc
@@ -21,7 +21,7 @@
#include "net/quic/core/crypto/quic_random.h"
#include "net/quic/core/quic_connection.h"
#include "net/quic/core/quic_flags.h"
-#include "net/quic/core/quic_protocol.h"
+#include "net/quic/core/quic_packets.h"
#include "net/quic/core/quic_server_id.h"
#include "net/quic/core/spdy_utils.h"
#include "net/socket/udp_client_socket.h"
@@ -29,31 +29,18 @@
#include "net/spdy/spdy_http_utils.h"
using std::string;
-using std::vector;
using base::StringPiece;
namespace net {
QuicSimpleClient::QuicSimpleClient(
- IPEndPoint server_address,
+ QuicSocketAddress server_address,
const QuicServerId& server_id,
const QuicVersionVector& supported_versions,
std::unique_ptr<ProofVerifier> proof_verifier)
- : QuicSimpleClient(server_address,
- server_id,
- supported_versions,
- QuicConfig(),
- std::move(proof_verifier)) {}
-
-QuicSimpleClient::QuicSimpleClient(
- IPEndPoint server_address,
- const QuicServerId& server_id,
- const QuicVersionVector& supported_versions,
- const QuicConfig& config,
- std::unique_ptr<ProofVerifier> proof_verifier)
: QuicClientBase(server_id,
supported_versions,
- config,
+ QuicConfig(),
CreateQuicConnectionHelper(),
CreateQuicAlarmFactory(),
std::move(proof_verifier)),
@@ -71,23 +58,22 @@ QuicSimpleClient::~QuicSimpleClient() {
}
}
-bool QuicSimpleClient::CreateUDPSocketAndBind(IPEndPoint server_address,
- IPAddress bind_to_address,
+bool QuicSimpleClient::CreateUDPSocketAndBind(QuicSocketAddress server_address,
+ QuicIpAddress bind_to_address,
int bind_to_port) {
std::unique_ptr<UDPClientSocket> socket(
new UDPClientSocket(DatagramSocket::DEFAULT_BIND, RandIntCallback(),
&net_log_, NetLogSource()));
- int address_family = server_address.GetSockAddrFamily();
- if (bind_to_address.size() != 0) {
- client_address_ = IPEndPoint(bind_to_address, bind_to_port);
- } else if (address_family == AF_INET) {
- client_address_ = IPEndPoint(IPAddress::IPv4AllZeros(), bind_to_port);
+ if (bind_to_address.IsInitialized()) {
+ client_address_ = QuicSocketAddress(bind_to_address, local_port());
+ } else if (server_address.host().address_family() == IpAddressFamily::IP_V4) {
+ client_address_ = QuicSocketAddress(QuicIpAddress::Any4(), bind_to_port);
} else {
- client_address_ = IPEndPoint(IPAddress::IPv6AllZeros(), bind_to_port);
+ client_address_ = QuicSocketAddress(QuicIpAddress::Any6(), bind_to_port);
}
- int rc = socket->Connect(server_address);
+ int rc = socket->Connect(server_address.impl().socket_address());
if (rc != OK) {
LOG(ERROR) << "Connect failed: " << ErrorToShortString(rc);
return false;
@@ -105,11 +91,13 @@ bool QuicSimpleClient::CreateUDPSocketAndBind(IPEndPoint server_address,
return false;
}
- rc = socket->GetLocalAddress(&client_address_);
+ IPEndPoint address;
+ rc = socket->GetLocalAddress(&address);
if (rc != OK) {
LOG(ERROR) << "GetLocalAddress failed: " << ErrorToShortString(rc);
return false;
}
+ client_address_ = QuicSocketAddress(QuicSocketAddressImpl(address));
socket_.swap(socket);
packet_reader_.reset(new QuicChromiumPacketReader(
@@ -162,15 +150,16 @@ void QuicSimpleClient::OnReadError(int result,
Disconnect();
}
-IPEndPoint QuicSimpleClient::GetLatestClientAddress() const {
+QuicSocketAddress QuicSimpleClient::GetLatestClientAddress() const {
return client_address_;
}
bool QuicSimpleClient::OnPacket(const QuicReceivedPacket& packet,
IPEndPoint local_address,
IPEndPoint peer_address) {
- session()->connection()->ProcessUdpPacket(local_address, peer_address,
- packet);
+ session()->connection()->ProcessUdpPacket(
+ QuicSocketAddress(QuicSocketAddressImpl(local_address)),
+ QuicSocketAddress(QuicSocketAddressImpl(peer_address)), packet);
if (!session()->connection()->connected()) {
return false;
}
diff --git a/chromium/net/tools/quic/quic_simple_client.h b/chromium/net/tools/quic/quic_simple_client.h
index a7109b190a0..f0bc052bc6d 100644
--- a/chromium/net/tools/quic/quic_simple_client.h
+++ b/chromium/net/tools/quic/quic_simple_client.h
@@ -23,11 +23,11 @@
#include "net/quic/chromium/quic_chromium_packet_reader.h"
#include "net/quic/core/quic_config.h"
#include "net/quic/core/quic_spdy_stream.h"
+#include "net/quic/platform/impl/quic_chromium_clock.h"
#include "net/tools/quic/quic_client_base.h"
namespace net {
-struct HttpRequestInfo;
class QuicChromiumAlarmFactory;
class QuicChromiumConnectionHelper;
class UDPClientSocket;
@@ -40,17 +40,11 @@ class QuicClientPeer;
class QuicSimpleClient : public QuicClientBase,
public QuicChromiumPacketReader::Visitor {
public:
- // Create a quic client, which will have events managed by an externally owned
- // EpollServer.
- QuicSimpleClient(IPEndPoint server_address,
+ // Create a quic client, which will have events managed by the message loop.
+ QuicSimpleClient(QuicSocketAddress server_address,
const QuicServerId& server_id,
const QuicVersionVector& supported_versions,
std::unique_ptr<ProofVerifier> proof_verifier);
- QuicSimpleClient(IPEndPoint server_address,
- const QuicServerId& server_id,
- const QuicVersionVector& supported_versions,
- const QuicConfig& config,
- std::unique_ptr<ProofVerifier> proof_verifier);
~QuicSimpleClient() override;
@@ -61,14 +55,14 @@ class QuicSimpleClient : public QuicClientBase,
IPEndPoint peer_address) override;
// From QuicClientBase
- IPEndPoint GetLatestClientAddress() const override;
+ QuicSocketAddress GetLatestClientAddress() const override;
protected:
// From QuicClientBase
QuicPacketWriter* CreateQuicPacketWriter() override;
void RunEventLoop() override;
- bool CreateUDPSocketAndBind(IPEndPoint server_address,
- IPAddress bind_to_address,
+ bool CreateUDPSocketAndBind(QuicSocketAddress server_address,
+ QuicIpAddress bind_to_address,
int bind_to_port) override;
void CleanUpAllUDPSockets() override;
@@ -84,10 +78,10 @@ class QuicSimpleClient : public QuicClientBase,
void StartPacketReaderIfNotStarted();
// Used by |helper_| to time alarms.
- QuicClock clock_;
+ QuicChromiumClock clock_;
// Address of the client if the client is connected to the server.
- IPEndPoint client_address_;
+ QuicSocketAddress client_address_;
// UDP socket connected to the server.
std::unique_ptr<UDPClientSocket> socket_;
diff --git a/chromium/net/tools/quic/quic_simple_client_bin.cc b/chromium/net/tools/quic/quic_simple_client_bin.cc
index 1ccb8934548..ffa5e54d289 100644
--- a/chromium/net/tools/quic/quic_simple_client_bin.cc
+++ b/chromium/net/tools/quic/quic_simple_client_bin.cc
@@ -44,22 +44,18 @@
#include "base/command_line.h"
#include "base/logging.h"
#include "base/message_loop/message_loop.h"
-#include "base/strings/string_number_conversions.h"
-#include "base/strings/string_split.h"
-#include "base/strings/string_util.h"
-#include "base/strings/stringprintf.h"
-#include "net/base/ip_address.h"
-#include "net/base/ip_endpoint.h"
#include "net/base/net_errors.h"
#include "net/base/privacy_mode.h"
#include "net/cert/cert_verifier.h"
#include "net/cert/multi_log_ct_verifier.h"
-#include "net/http/http_request_info.h"
#include "net/http/transport_security_state.h"
#include "net/quic/chromium/crypto/proof_verifier_chromium.h"
-#include "net/quic/core/quic_protocol.h"
+#include "net/quic/core/quic_error_codes.h"
+#include "net/quic/core/quic_packets.h"
#include "net/quic/core/quic_server_id.h"
-#include "net/quic/core/quic_utils.h"
+#include "net/quic/platform/api/quic_socket_address.h"
+#include "net/quic/platform/api/quic_str_cat.h"
+#include "net/quic/platform/api/quic_text_utils.h"
#include "net/spdy/spdy_header_block.h"
#include "net/spdy/spdy_http_utils.h"
#include "net/tools/quic/quic_simple_client.h"
@@ -73,13 +69,13 @@ using net::CTVerifier;
using net::MultiLogCTVerifier;
using net::ProofVerifier;
using net::ProofVerifierChromium;
+using net::QuicTextUtils;
+using net::SpdyHeaderBlock;
using net::TransportSecurityState;
using std::cout;
using std::cerr;
-using std::map;
-using std::string;
-using std::vector;
using std::endl;
+using std::string;
// The IP or hostname the quic client will connect to.
string FLAGS_host = "";
@@ -114,7 +110,7 @@ class FakeProofVerifier : public ProofVerifier {
const string& server_config,
net::QuicVersion quic_version,
StringPiece chlo_hash,
- const vector<string>& certs,
+ const std::vector<string>& certs,
const string& cert_sct,
const string& signature,
const net::ProofVerifyContext* context,
@@ -224,10 +220,8 @@ int main(int argc, char* argv[]) {
base::MessageLoopForIO message_loop;
// Determine IP address to connect to from supplied hostname.
- net::IPAddress ip_addr;
+ net::QuicIpAddress ip_addr;
- // TODO(rtenneti): GURL's doesn't support default_protocol argument, thus
- // protocol is required in the URL.
GURL url(urls[0]);
string host = FLAGS_host;
if (host.empty()) {
@@ -237,7 +231,7 @@ int main(int argc, char* argv[]) {
if (port == 0) {
port = url.EffectiveIntPort();
}
- if (!ip_addr.AssignFromIPLiteral(host)) {
+ if (!ip_addr.FromString(host)) {
net::AddressList addresses;
int rv = net::SynchronousHostResolver::Resolve(host, &addresses);
if (rv != net::OK) {
@@ -245,10 +239,11 @@ int main(int argc, char* argv[]) {
<< "' : " << net::ErrorToShortString(rv);
return 1;
}
- ip_addr = addresses[0].address();
+ ip_addr =
+ net::QuicIpAddress(net::QuicIpAddressImpl(addresses[0].address()));
}
- string host_port = net::IPAddressToStringWithPort(ip_addr, FLAGS_port);
+ string host_port = net::QuicStrCat(ip_addr.ToString(), ":", port);
VLOG(1) << "Resolved " << host << " to " << host_port << endl;
// Build the client, and try to connect.
@@ -273,7 +268,7 @@ int main(int argc, char* argv[]) {
cert_verifier.get(), ct_policy_enforcer.get(),
transport_security_state.get(), ct_verifier.get()));
}
- net::QuicSimpleClient client(net::IPEndPoint(ip_addr, port), server_id,
+ net::QuicSimpleClient client(net::QuicSocketAddress(ip_addr, port), server_id,
versions, std::move(proof_verifier));
client.set_initial_max_packet_length(
FLAGS_initial_mtu != 0 ? FLAGS_initial_mtu : net::kDefaultMaxPacketSize);
@@ -290,7 +285,7 @@ int main(int argc, char* argv[]) {
return 0;
}
cerr << "Failed to connect to " << host_port
- << ". Error: " << net::QuicUtils::ErrorToString(error) << endl;
+ << ". Error: " << net::QuicErrorCodeToString(error) << endl;
return 1;
}
cout << "Connected to " << host_port << endl;
@@ -299,40 +294,32 @@ int main(int argc, char* argv[]) {
string body = FLAGS_body;
if (!FLAGS_body_hex.empty()) {
DCHECK(FLAGS_body.empty()) << "Only set one of --body and --body_hex.";
- body = net::QuicUtils::HexDecode(FLAGS_body_hex);
+ body = QuicTextUtils::HexDecode(FLAGS_body_hex);
}
// Construct a GET or POST request for supplied URL.
- net::HttpRequestInfo request;
- request.method = body.empty() ? "GET" : "POST";
- request.url = url;
+ SpdyHeaderBlock header_block;
+ header_block[":method"] = body.empty() ? "GET" : "POST";
+ header_block[":scheme"] = url.scheme();
+ header_block[":authority"] = url.host();
+ header_block[":path"] = url.path();
// Append any additional headers supplied on the command line.
- for (const std::string& header :
- base::SplitString(FLAGS_headers, ";", base::KEEP_WHITESPACE,
- base::SPLIT_WANT_NONEMPTY)) {
- string sp;
- base::TrimWhitespaceASCII(header, base::TRIM_ALL, &sp);
+ for (StringPiece sp : QuicTextUtils::Split(FLAGS_headers, ';')) {
+ QuicTextUtils::RemoveLeadingAndTrailingWhitespace(&sp);
if (sp.empty()) {
continue;
}
- vector<string> kv =
- base::SplitString(sp, ":", base::TRIM_WHITESPACE, base::SPLIT_WANT_ALL);
- CHECK_EQ(2u, kv.size());
- string key;
- base::TrimWhitespaceASCII(kv[0], base::TRIM_ALL, &key);
- string value;
- base::TrimWhitespaceASCII(kv[1], base::TRIM_ALL, &value);
- request.extra_headers.SetHeader(key, value);
+ std::vector<StringPiece> kv = QuicTextUtils::Split(sp, ':');
+ QuicTextUtils::RemoveLeadingAndTrailingWhitespace(&kv[0]);
+ QuicTextUtils::RemoveLeadingAndTrailingWhitespace(&kv[1]);
+ header_block[kv[0]] = kv[1];
}
// Make sure to store the response, for later output.
client.set_store_response(true);
// Send the request.
- net::SpdyHeaderBlock header_block;
- net::CreateSpdyHeadersFromHttpRequest(request, request.extra_headers,
- /*direct=*/true, &header_block);
client.SendRequestAndWaitForResponse(header_block, body, /*fin=*/true);
// Print request and response details.
@@ -342,7 +329,7 @@ int main(int argc, char* argv[]) {
if (!FLAGS_body_hex.empty()) {
// Print the user provided hex, rather than binary body.
cout << "body:\n"
- << net::QuicUtils::HexDump(net::QuicUtils::HexDecode(FLAGS_body_hex))
+ << QuicTextUtils::HexDump(QuicTextUtils::HexDecode(FLAGS_body_hex))
<< endl;
} else {
cout << "body: " << body << endl;
@@ -353,10 +340,11 @@ int main(int argc, char* argv[]) {
string response_body = client.latest_response_body();
if (!FLAGS_body_hex.empty()) {
// Assume response is binary data.
- cout << "body:\n" << net::QuicUtils::HexDump(response_body) << endl;
+ cout << "body:\n" << QuicTextUtils::HexDump(response_body) << endl;
} else {
cout << "body: " << response_body << endl;
}
+ cout << "trailers: " << client.latest_response_trailers() << endl;
}
size_t response_code = client.latest_response_code();
diff --git a/chromium/net/tools/quic/quic_simple_client_test.cc b/chromium/net/tools/quic/quic_simple_client_test.cc
index 0a571a797b7..64db2d2a6dd 100644
--- a/chromium/net/tools/quic/quic_simple_client_test.cc
+++ b/chromium/net/tools/quic/quic_simple_client_test.cc
@@ -9,13 +9,11 @@
#include "net/quic/test_tools/quic_test_utils.h"
#include "testing/gtest/include/gtest/gtest.h"
-using net::test::CryptoTestUtils;
-
namespace net {
namespace test {
TEST(QuicSimpleClientTest, Initialize) {
- IPEndPoint server_address(IPEndPoint(net::test::Loopback4(), 80));
+ QuicSocketAddress server_address(QuicIpAddress::Loopback4(), 80);
QuicServerId server_id("hostname", server_address.port(),
PRIVACY_MODE_DISABLED);
QuicVersionVector versions = AllSupportedVersions();
diff --git a/chromium/net/tools/quic/quic_simple_crypto_server_stream_helper.cc b/chromium/net/tools/quic/quic_simple_crypto_server_stream_helper.cc
index 9f2870ac9a7..a25b872275b 100644
--- a/chromium/net/tools/quic/quic_simple_crypto_server_stream_helper.cc
+++ b/chromium/net/tools/quic/quic_simple_crypto_server_stream_helper.cc
@@ -20,7 +20,7 @@ QuicConnectionId
bool QuicSimpleCryptoServerStreamHelper::CanAcceptClientHello(
const CryptoHandshakeMessage& message,
- const IPEndPoint& self_address,
+ const QuicSocketAddress& self_address,
std::string* error_details) const {
return true;
}
diff --git a/chromium/net/tools/quic/quic_simple_crypto_server_stream_helper.h b/chromium/net/tools/quic/quic_simple_crypto_server_stream_helper.h
index 5402a21fc7a..31c257df395 100644
--- a/chromium/net/tools/quic/quic_simple_crypto_server_stream_helper.h
+++ b/chromium/net/tools/quic/quic_simple_crypto_server_stream_helper.h
@@ -2,8 +2,8 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#ifndef NET_QUIC_TOOLS_QUIC_SIMPLE_CRYPTO_SERVER_STREAM_HELPER_H_
-#define NET_QUIC_TOOLS_QUIC_SIMPLE_CRYPTO_SERVER_STREAM_HELPER_H_
+#ifndef NET_TOOLS_QUIC_QUIC_SIMPLE_CRYPTO_SERVER_STREAM_HELPER_H_
+#define NET_TOOLS_QUIC_QUIC_SIMPLE_CRYPTO_SERVER_STREAM_HELPER_H_
#include "net/quic/core/crypto/quic_random.h"
#include "net/quic/core/quic_crypto_server_stream.h"
@@ -23,7 +23,7 @@ class QuicSimpleCryptoServerStreamHelper
QuicConnectionId /*connection_id*/) const override;
bool CanAcceptClientHello(const CryptoHandshakeMessage& message,
- const IPEndPoint& self_address,
+ const QuicSocketAddress& self_address,
std::string* error_details) const override;
private:
@@ -32,4 +32,4 @@ class QuicSimpleCryptoServerStreamHelper
} // namespace net
-#endif // NET_QUIC_TOOLS_QUIC_SIMPLE_CRYPTO_SERVER_STREAM_HELPER_H_
+#endif // NET_TOOLS_QUIC_QUIC_SIMPLE_CRYPTO_SERVER_STREAM_HELPER_H_
diff --git a/chromium/net/tools/quic/quic_simple_dispatcher.cc b/chromium/net/tools/quic/quic_simple_dispatcher.cc
index bcad0565cea..cab2925d5f1 100644
--- a/chromium/net/tools/quic/quic_simple_dispatcher.cc
+++ b/chromium/net/tools/quic/quic_simple_dispatcher.cc
@@ -14,28 +14,30 @@ QuicSimpleDispatcher::QuicSimpleDispatcher(
QuicVersionManager* version_manager,
std::unique_ptr<QuicConnectionHelperInterface> helper,
std::unique_ptr<QuicCryptoServerStream::Helper> session_helper,
- std::unique_ptr<QuicAlarmFactory> alarm_factory)
+ std::unique_ptr<QuicAlarmFactory> alarm_factory,
+ QuicHttpResponseCache* response_cache)
: QuicDispatcher(config,
crypto_config,
version_manager,
std::move(helper),
std::move(session_helper),
- std::move(alarm_factory)) {}
+ std::move(alarm_factory)),
+ response_cache_(response_cache) {}
QuicSimpleDispatcher::~QuicSimpleDispatcher() {}
QuicServerSessionBase* QuicSimpleDispatcher::CreateQuicSession(
QuicConnectionId connection_id,
- const IPEndPoint& client_address) {
+ const QuicSocketAddress& client_address) {
// The QuicServerSessionBase takes ownership of |connection| below.
QuicConnection* connection = new QuicConnection(
connection_id, client_address, helper(), alarm_factory(),
CreatePerConnectionWriter(),
/* owns_writer= */ true, Perspective::IS_SERVER, GetSupportedVersions());
- QuicServerSessionBase* session =
- new QuicSimpleServerSession(config(), connection, this, session_helper(),
- crypto_config(), compressed_certs_cache());
+ QuicServerSessionBase* session = new QuicSimpleServerSession(
+ config(), connection, this, session_helper(), crypto_config(),
+ compressed_certs_cache(), response_cache_);
session->Initialize();
return session;
}
diff --git a/chromium/net/tools/quic/quic_simple_dispatcher.h b/chromium/net/tools/quic/quic_simple_dispatcher.h
index 626c05df2bd..b9df6d9c63c 100644
--- a/chromium/net/tools/quic/quic_simple_dispatcher.h
+++ b/chromium/net/tools/quic/quic_simple_dispatcher.h
@@ -7,6 +7,7 @@
#include "net/quic/core/quic_server_session_base.h"
#include "net/tools/quic/quic_dispatcher.h"
+#include "net/tools/quic/quic_http_response_cache.h"
namespace net {
@@ -18,14 +19,20 @@ class QuicSimpleDispatcher : public QuicDispatcher {
QuicVersionManager* version_manager,
std::unique_ptr<QuicConnectionHelperInterface> helper,
std::unique_ptr<QuicCryptoServerStream::Helper> session_helper,
- std::unique_ptr<QuicAlarmFactory> alarm_factory);
+ std::unique_ptr<QuicAlarmFactory> alarm_factory,
+ QuicHttpResponseCache* response_cache);
~QuicSimpleDispatcher() override;
protected:
QuicServerSessionBase* CreateQuicSession(
QuicConnectionId connection_id,
- const IPEndPoint& client_address) override;
+ const QuicSocketAddress& client_address) override;
+
+ QuicHttpResponseCache* response_cache() { return response_cache_; }
+
+ private:
+ QuicHttpResponseCache* response_cache_; // Unowned.
};
} // namespace net
diff --git a/chromium/net/tools/quic/quic_simple_per_connection_packet_writer.cc b/chromium/net/tools/quic/quic_simple_per_connection_packet_writer.cc
index 57c85dd9307..4889724aa78 100644
--- a/chromium/net/tools/quic/quic_simple_per_connection_packet_writer.cc
+++ b/chromium/net/tools/quic/quic_simple_per_connection_packet_writer.cc
@@ -24,8 +24,8 @@ QuicPacketWriter* QuicSimplePerConnectionPacketWriter::shared_writer() const {
WriteResult QuicSimplePerConnectionPacketWriter::WritePacket(
const char* buffer,
size_t buf_len,
- const IPAddress& self_address,
- const IPEndPoint& peer_address,
+ const QuicIpAddress& self_address,
+ const QuicSocketAddress& peer_address,
PerPacketOptions* options) {
return shared_writer_->WritePacketWithCallback(
buffer, buf_len, self_address, peer_address, options,
@@ -52,7 +52,7 @@ void QuicSimplePerConnectionPacketWriter::OnWriteComplete(WriteResult result) {
}
QuicByteCount QuicSimplePerConnectionPacketWriter::GetMaxPacketSize(
- const IPEndPoint& peer_address) const {
+ const QuicSocketAddress& peer_address) const {
return shared_writer_->GetMaxPacketSize(peer_address);
}
diff --git a/chromium/net/tools/quic/quic_simple_per_connection_packet_writer.h b/chromium/net/tools/quic/quic_simple_per_connection_packet_writer.h
index c5a62bdc452..4c6710ce2c2 100644
--- a/chromium/net/tools/quic/quic_simple_per_connection_packet_writer.h
+++ b/chromium/net/tools/quic/quic_simple_per_connection_packet_writer.h
@@ -2,8 +2,8 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#ifndef NET_QUIC_TOOLS_QUIC_SIMPLE_PER_CONNECTION_PACKET_WRITER_H_
-#define NET_QUIC_TOOLS_QUIC_SIMPLE_PER_CONNECTION_PACKET_WRITER_H_
+#ifndef NET_TOOLS_QUIC_QUIC_SIMPLE_PER_CONNECTION_PACKET_WRITER_H_
+#define NET_TOOLS_QUIC_QUIC_SIMPLE_PER_CONNECTION_PACKET_WRITER_H_
#include <stddef.h>
@@ -35,13 +35,14 @@ class QuicSimplePerConnectionPacketWriter : public QuicPacketWriter {
// to |shared_writer_|.
WriteResult WritePacket(const char* buffer,
size_t buf_len,
- const IPAddress& self_address,
- const IPEndPoint& peer_address,
+ const QuicIpAddress& self_address,
+ const QuicSocketAddress& peer_address,
PerPacketOptions* options) override;
bool IsWriteBlockedDataBuffered() const override;
bool IsWriteBlocked() const override;
void SetWritable() override;
- QuicByteCount GetMaxPacketSize(const IPEndPoint& peer_address) const override;
+ QuicByteCount GetMaxPacketSize(
+ const QuicSocketAddress& peer_address) const override;
private:
void OnWriteComplete(WriteResult result);
@@ -56,4 +57,4 @@ class QuicSimplePerConnectionPacketWriter : public QuicPacketWriter {
} // namespace net
-#endif // NET_QUIC_TOOLS_QUIC_SIMPLE_PER_CONNECTION_PACKET_WRITER_H_
+#endif // NET_TOOLS_QUIC_QUIC_SIMPLE_PER_CONNECTION_PACKET_WRITER_H_
diff --git a/chromium/net/tools/quic/quic_simple_server.cc b/chromium/net/tools/quic/quic_simple_server.cc
index acfa9e3ddef..a9714c2a51f 100644
--- a/chromium/net/tools/quic/quic_simple_server.cc
+++ b/chromium/net/tools/quic/quic_simple_server.cc
@@ -16,7 +16,7 @@
#include "net/quic/core/crypto/quic_random.h"
#include "net/quic/core/quic_crypto_stream.h"
#include "net/quic/core/quic_data_reader.h"
-#include "net/quic/core/quic_protocol.h"
+#include "net/quic/core/quic_packets.h"
#include "net/socket/udp_server_socket.h"
#include "net/tools/quic/quic_simple_dispatcher.h"
#include "net/tools/quic/quic_simple_per_connection_packet_writer.h"
@@ -40,7 +40,8 @@ QuicSimpleServer::QuicSimpleServer(
std::unique_ptr<ProofSource> proof_source,
const QuicConfig& config,
const QuicCryptoServerConfig::ConfigOptions& crypto_config_options,
- const QuicVersionVector& supported_versions)
+ const QuicVersionVector& supported_versions,
+ QuicHttpResponseCache* response_cache)
: version_manager_(supported_versions),
helper_(
new QuicChromiumConnectionHelper(&clock_, QuicRandom::GetInstance())),
@@ -55,6 +56,7 @@ QuicSimpleServer::QuicSimpleServer(
read_pending_(false),
synchronous_read_count_(0),
read_buffer_(new IOBufferWithSize(kReadBufferSize)),
+ response_cache_(response_cache),
weak_factory_(this) {
Initialize();
}
@@ -129,7 +131,7 @@ int QuicSimpleServer::Listen(const IPEndPoint& address) {
std::unique_ptr<QuicConnectionHelperInterface>(helper_),
std::unique_ptr<QuicCryptoServerStream::Helper>(
new QuicSimpleServerSessionHelper(QuicRandom::GetInstance())),
- std::unique_ptr<QuicAlarmFactory>(alarm_factory_)));
+ std::unique_ptr<QuicAlarmFactory>(alarm_factory_), response_cache_));
QuicSimpleServerPacketWriter* writer =
new QuicSimpleServerPacketWriter(socket_.get(), dispatcher_.get());
dispatcher_->InitializeWithWriter(writer);
@@ -199,7 +201,9 @@ void QuicSimpleServer::OnReadComplete(int result) {
QuicReceivedPacket packet(read_buffer_->data(), result,
helper_->GetClock()->Now(), false);
- dispatcher_->ProcessPacket(server_address_, client_address_, packet);
+ dispatcher_->ProcessPacket(
+ QuicSocketAddress(QuicSocketAddressImpl(server_address_)),
+ QuicSocketAddress(QuicSocketAddressImpl(client_address_)), packet);
StartReading();
}
diff --git a/chromium/net/tools/quic/quic_simple_server.h b/chromium/net/tools/quic/quic_simple_server.h
index 4b24d9cef73..f97b9b653ff 100644
--- a/chromium/net/tools/quic/quic_simple_server.h
+++ b/chromium/net/tools/quic/quic_simple_server.h
@@ -5,8 +5,8 @@
// A toy server, which listens on a specified address for QUIC traffic and
// handles incoming responses.
-#ifndef NET_QUIC_TOOLS_QUIC_SIMPLE_SERVER_H_
-#define NET_QUIC_TOOLS_QUIC_SIMPLE_SERVER_H_
+#ifndef NET_TOOLS_QUIC_QUIC_SIMPLE_SERVER_H_
+#define NET_TOOLS_QUIC_QUIC_SIMPLE_SERVER_H_
#include <memory>
@@ -17,8 +17,10 @@
#include "net/quic/chromium/quic_chromium_alarm_factory.h"
#include "net/quic/chromium/quic_chromium_connection_helper.h"
#include "net/quic/core/crypto/quic_crypto_server_config.h"
-#include "net/quic/core/quic_clock.h"
#include "net/quic/core/quic_config.h"
+#include "net/quic/core/quic_version_manager.h"
+#include "net/quic/platform/impl/quic_chromium_clock.h"
+#include "net/tools/quic/quic_http_response_cache.h"
namespace net {
@@ -37,7 +39,8 @@ class QuicSimpleServer {
std::unique_ptr<ProofSource> proof_source,
const QuicConfig& config,
const QuicCryptoServerConfig::ConfigOptions& crypto_config_options,
- const QuicVersionVector& supported_versions);
+ const QuicVersionVector& supported_versions,
+ QuicHttpResponseCache* response_cache);
virtual ~QuicSimpleServer();
@@ -55,10 +58,6 @@ class QuicSimpleServer {
// continues the read loop.
void OnReadComplete(int result);
- void SetStrikeRegisterNoStartupPeriod() {
- crypto_config_.set_strike_register_no_startup_period();
- }
-
QuicDispatcher* dispatcher() { return dispatcher_.get(); }
IPEndPoint server_address() const { return server_address_; }
@@ -75,7 +74,7 @@ class QuicSimpleServer {
std::unique_ptr<QuicDispatcher> dispatcher_;
// Used by the helper_ to time alarms.
- QuicClock clock_;
+ QuicChromiumClock clock_;
// Used to manage the message loop. Owned by dispatcher_.
QuicChromiumConnectionHelper* helper_;
@@ -115,6 +114,8 @@ class QuicSimpleServer {
// The log to use for the socket.
NetLog net_log_;
+ QuicHttpResponseCache* response_cache_;
+
base::WeakPtrFactory<QuicSimpleServer> weak_factory_;
DISALLOW_COPY_AND_ASSIGN(QuicSimpleServer);
@@ -122,4 +123,4 @@ class QuicSimpleServer {
} // namespace net
-#endif // NET_QUIC_TOOLS_QUIC_SIMPLE_SERVER_H_
+#endif // NET_TOOLS_QUIC_QUIC_SIMPLE_SERVER_H_
diff --git a/chromium/net/tools/quic/quic_simple_server_bin.cc b/chromium/net/tools/quic/quic_simple_server_bin.cc
index 9187c9957dc..a652983632c 100644
--- a/chromium/net/tools/quic/quic_simple_server_bin.cc
+++ b/chromium/net/tools/quic/quic_simple_server_bin.cc
@@ -15,8 +15,8 @@
#include "net/base/ip_address.h"
#include "net/base/ip_endpoint.h"
#include "net/quic/chromium/crypto/proof_source_chromium.h"
-#include "net/quic/core/quic_protocol.h"
-#include "net/tools/quic/quic_in_memory_cache.h"
+#include "net/quic/core/quic_packets.h"
+#include "net/tools/quic/quic_http_response_cache.h"
#include "net/tools/quic/quic_simple_server.h"
// The port the quic server will listen on.
@@ -49,7 +49,7 @@ int main(int argc, char* argv[]) {
"Options:\n"
"-h, --help show this help message and exit\n"
"--port=<port> specify the port to listen on\n"
- "--quic_in_memory_cache_dir directory containing response data\n"
+ "--quic_response_cache_dir directory containing response data\n"
" to load\n"
"--certificate_file=<file> path to the certificate chain\n"
"--key_file=<file> path to the pkcs8 private key\n";
@@ -57,9 +57,10 @@ int main(int argc, char* argv[]) {
exit(0);
}
- if (line->HasSwitch("quic_in_memory_cache_dir")) {
- net::QuicInMemoryCache::GetInstance()->InitializeFromDirectory(
- line->GetSwitchValueASCII("quic_in_memory_cache_dir"));
+ net::QuicHttpResponseCache response_cache;
+ if (line->HasSwitch("quic_response_cache_dir")) {
+ response_cache.InitializeFromDirectory(
+ line->GetSwitchValueASCII("quic_response_cache_dir"));
}
if (line->HasSwitch("port")) {
@@ -86,8 +87,7 @@ int main(int argc, char* argv[]) {
CreateProofSource(line->GetSwitchValuePath("certificate_file"),
line->GetSwitchValuePath("key_file")),
config, net::QuicCryptoServerConfig::ConfigOptions(),
- net::AllSupportedVersions());
- server.SetStrikeRegisterNoStartupPeriod();
+ net::AllSupportedVersions(), &response_cache);
int rc = server.Listen(net::IPEndPoint(ip, FLAGS_port));
if (rc < 0) {
diff --git a/chromium/net/tools/quic/quic_simple_server_packet_writer.cc b/chromium/net/tools/quic/quic_simple_server_packet_writer.cc
index ba1ad5ded23..6386cd7dbd5 100644
--- a/chromium/net/tools/quic/quic_simple_server_packet_writer.cc
+++ b/chromium/net/tools/quic/quic_simple_server_packet_writer.cc
@@ -27,8 +27,8 @@ QuicSimpleServerPacketWriter::~QuicSimpleServerPacketWriter() {}
WriteResult QuicSimpleServerPacketWriter::WritePacketWithCallback(
const char* buffer,
size_t buf_len,
- const IPAddress& self_address,
- const IPEndPoint& peer_address,
+ const QuicIpAddress& self_address,
+ const QuicSocketAddress& peer_address,
PerPacketOptions* options,
WriteCallback callback) {
DCHECK(callback_.is_null());
@@ -67,8 +67,8 @@ void QuicSimpleServerPacketWriter::SetWritable() {
WriteResult QuicSimpleServerPacketWriter::WritePacket(
const char* buffer,
size_t buf_len,
- const IPAddress& self_address,
- const IPEndPoint& peer_address,
+ const QuicIpAddress& self_address,
+ const QuicSocketAddress& peer_address,
PerPacketOptions* options) {
scoped_refptr<StringIOBuffer> buf(
new StringIOBuffer(std::string(buffer, buf_len)));
@@ -76,7 +76,8 @@ WriteResult QuicSimpleServerPacketWriter::WritePacket(
int rv;
if (buf_len <= static_cast<size_t>(std::numeric_limits<int>::max())) {
rv = socket_->SendTo(
- buf.get(), static_cast<int>(buf_len), peer_address,
+ buf.get(), static_cast<int>(buf_len),
+ peer_address.impl().socket_address(),
base::Bind(&QuicSimpleServerPacketWriter::OnWriteComplete,
weak_factory_.GetWeakPtr()));
} else {
@@ -96,7 +97,7 @@ WriteResult QuicSimpleServerPacketWriter::WritePacket(
}
QuicByteCount QuicSimpleServerPacketWriter::GetMaxPacketSize(
- const IPEndPoint& peer_address) const {
+ const QuicSocketAddress& peer_address) const {
return kMaxPacketSize;
}
diff --git a/chromium/net/tools/quic/quic_simple_server_packet_writer.h b/chromium/net/tools/quic/quic_simple_server_packet_writer.h
index d4cc814eadf..a08c0daf03c 100644
--- a/chromium/net/tools/quic/quic_simple_server_packet_writer.h
+++ b/chromium/net/tools/quic/quic_simple_server_packet_writer.h
@@ -2,22 +2,20 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#ifndef NET_QUIC_TOOLS_QUIC_SIMPLE_SERVER_PACKET_WRITER_H_
-#define NET_QUIC_TOOLS_QUIC_SIMPLE_SERVER_PACKET_WRITER_H_
+#ifndef NET_TOOLS_QUIC_QUIC_SIMPLE_SERVER_PACKET_WRITER_H_
+#define NET_TOOLS_QUIC_QUIC_SIMPLE_SERVER_PACKET_WRITER_H_
#include <stddef.h>
#include "base/callback.h"
#include "base/macros.h"
#include "base/memory/weak_ptr.h"
-#include "net/base/ip_endpoint.h"
#include "net/quic/core/quic_connection.h"
#include "net/quic/core/quic_packet_writer.h"
-#include "net/quic/core/quic_protocol.h"
+#include "net/quic/core/quic_packets.h"
namespace net {
-class IPAddress;
class QuicBlockedWriterInterface;
class UDPServerSocket;
struct WriteResult;
@@ -36,15 +34,15 @@ class QuicSimpleServerPacketWriter : public QuicPacketWriter {
// Wraps WritePacket, and ensures that |callback| is run on successful write.
WriteResult WritePacketWithCallback(const char* buffer,
size_t buf_len,
- const IPAddress& self_address,
- const IPEndPoint& peer_address,
+ const QuicIpAddress& self_address,
+ const QuicSocketAddress& peer_address,
PerPacketOptions* options,
WriteCallback callback);
WriteResult WritePacket(const char* buffer,
size_t buf_len,
- const IPAddress& self_address,
- const IPEndPoint& peer_address,
+ const QuicIpAddress& self_address,
+ const QuicSocketAddress& peer_address,
PerPacketOptions* options) override;
void OnWriteComplete(int rv);
@@ -53,7 +51,8 @@ class QuicSimpleServerPacketWriter : public QuicPacketWriter {
bool IsWriteBlockedDataBuffered() const override;
bool IsWriteBlocked() const override;
void SetWritable() override;
- QuicByteCount GetMaxPacketSize(const IPEndPoint& peer_address) const override;
+ QuicByteCount GetMaxPacketSize(
+ const QuicSocketAddress& peer_address) const override;
private:
UDPServerSocket* socket_;
@@ -74,4 +73,4 @@ class QuicSimpleServerPacketWriter : public QuicPacketWriter {
} // namespace net
-#endif // NET_QUIC_TOOLS_QUIC_SIMPLE_SERVER_PACKET_WRITER_H_
+#endif // NET_TOOLS_QUIC_QUIC_SIMPLE_SERVER_PACKET_WRITER_H_
diff --git a/chromium/net/tools/quic/quic_simple_server_session.cc b/chromium/net/tools/quic/quic_simple_server_session.cc
index 909f6bc932e..3e60f3a2acf 100644
--- a/chromium/net/tools/quic/quic_simple_server_session.cc
+++ b/chromium/net/tools/quic/quic_simple_server_session.cc
@@ -6,12 +6,12 @@
#include <utility>
-#include "base/logging.h"
-#include "base/memory/ptr_util.h"
#include "net/quic/core/proto/cached_network_parameters.pb.h"
#include "net/quic/core/quic_connection.h"
#include "net/quic/core/quic_flags.h"
#include "net/quic/core/quic_spdy_session.h"
+#include "net/quic/platform/api/quic_logging.h"
+#include "net/quic/platform/api/quic_ptr_util.h"
#include "net/tools/quic/quic_simple_server_stream.h"
#include "url/gurl.h"
@@ -25,14 +25,16 @@ QuicSimpleServerSession::QuicSimpleServerSession(
QuicSession::Visitor* visitor,
QuicCryptoServerStream::Helper* helper,
const QuicCryptoServerConfig* crypto_config,
- QuicCompressedCertsCache* compressed_certs_cache)
+ QuicCompressedCertsCache* compressed_certs_cache,
+ QuicHttpResponseCache* response_cache)
: QuicServerSessionBase(config,
connection,
visitor,
helper,
crypto_config,
compressed_certs_cache),
- highest_promised_stream_id_(0) {}
+ highest_promised_stream_id_(0),
+ response_cache_(response_cache) {}
QuicSimpleServerSession::~QuicSimpleServerSession() {
delete connection();
@@ -42,9 +44,10 @@ QuicCryptoServerStreamBase*
QuicSimpleServerSession::CreateQuicCryptoServerStream(
const QuicCryptoServerConfig* crypto_config,
QuicCompressedCertsCache* compressed_certs_cache) {
- return new QuicCryptoServerStream(crypto_config, compressed_certs_cache,
- FLAGS_enable_quic_stateless_reject_support,
- this, stream_helper());
+ return new QuicCryptoServerStream(
+ crypto_config, compressed_certs_cache,
+ FLAGS_quic_reloadable_flag_enable_quic_stateless_reject_support, this,
+ stream_helper());
}
void QuicSimpleServerSession::StreamDraining(QuicStreamId id) {
@@ -56,7 +59,7 @@ void QuicSimpleServerSession::StreamDraining(QuicStreamId id) {
void QuicSimpleServerSession::OnStreamFrame(const QuicStreamFrame& frame) {
if (!IsIncomingStream(frame.stream_id)) {
- LOG(WARNING) << "Client shouldn't send data on server push stream";
+ QUIC_LOG(WARNING) << "Client shouldn't send data on server push stream";
connection()->CloseConnection(
QUIC_INVALID_STREAM_ID, "Client sent data on server push stream",
ConnectionCloseBehavior::SEND_CONNECTION_CLOSE_PACKET);
@@ -67,14 +70,14 @@ void QuicSimpleServerSession::OnStreamFrame(const QuicStreamFrame& frame) {
void QuicSimpleServerSession::PromisePushResources(
const string& request_url,
- const std::list<QuicInMemoryCache::ServerPushInfo>& resources,
+ const std::list<QuicHttpResponseCache::ServerPushInfo>& resources,
QuicStreamId original_stream_id,
const SpdyHeaderBlock& original_request_headers) {
if (!server_push_enabled()) {
return;
}
- for (QuicInMemoryCache::ServerPushInfo resource : resources) {
+ for (QuicHttpResponseCache::ServerPushInfo resource : resources) {
SpdyHeaderBlock headers = SynthesizePushRequestHeaders(
request_url, resource, original_request_headers);
highest_promised_stream_id_ += 2;
@@ -94,8 +97,9 @@ QuicSpdyStream* QuicSimpleServerSession::CreateIncomingDynamicStream(
return nullptr;
}
- QuicSpdyStream* stream = new QuicSimpleServerStream(id, this);
- ActivateStream(base::WrapUnique(stream));
+ QuicSpdyStream* stream =
+ new QuicSimpleServerStream(id, this, response_cache_);
+ ActivateStream(QuicWrapUnique(stream));
return stream;
}
@@ -105,10 +109,10 @@ QuicSimpleServerStream* QuicSimpleServerSession::CreateOutgoingDynamicStream(
return nullptr;
}
- QuicSimpleServerStream* stream =
- new QuicSimpleServerStream(GetNextOutgoingStreamId(), this);
+ QuicSimpleServerStream* stream = new QuicSimpleServerStream(
+ GetNextOutgoingStreamId(), this, response_cache_);
stream->SetPriority(priority);
- ActivateStream(base::WrapUnique(stream));
+ ActivateStream(QuicWrapUnique(stream));
return stream;
}
@@ -148,7 +152,7 @@ void QuicSimpleServerSession::HandleRstOnValidNonexistentStream(
SpdyHeaderBlock QuicSimpleServerSession::SynthesizePushRequestHeaders(
string request_url,
- QuicInMemoryCache::ServerPushInfo resource,
+ QuicHttpResponseCache::ServerPushInfo resource,
const SpdyHeaderBlock& original_request_headers) {
GURL push_request_url = resource.request_url;
string path = push_request_url.path();
@@ -173,10 +177,10 @@ SpdyHeaderBlock QuicSimpleServerSession::SynthesizePushRequestHeaders(
void QuicSimpleServerSession::SendPushPromise(QuicStreamId original_stream_id,
QuicStreamId promised_stream_id,
SpdyHeaderBlock headers) {
- DVLOG(1) << "stream " << original_stream_id
- << " send PUSH_PROMISE for promised stream " << promised_stream_id;
- headers_stream()->WritePushPromise(original_stream_id, promised_stream_id,
- std::move(headers));
+ QUIC_DLOG(INFO) << "stream " << original_stream_id
+ << " send PUSH_PROMISE for promised stream "
+ << promised_stream_id;
+ WritePushPromise(original_stream_id, promised_stream_id, std::move(headers));
}
void QuicSimpleServerSession::HandlePromisedPushRequests() {
@@ -196,7 +200,7 @@ void QuicSimpleServerSession::HandlePromisedPushRequests() {
CreateOutgoingDynamicStream(promised_info.priority));
DCHECK(promised_stream != nullptr);
DCHECK_EQ(promised_info.stream_id, promised_stream->id());
- DVLOG(1) << "created server push stream " << promised_stream->id();
+ QUIC_DLOG(INFO) << "created server push stream " << promised_stream->id();
SpdyHeaderBlock request_headers(std::move(promised_info.request_headers));
diff --git a/chromium/net/tools/quic/quic_simple_server_session.h b/chromium/net/tools/quic/quic_simple_server_session.h
index e075d1be450..b8efb35ba89 100644
--- a/chromium/net/tools/quic/quic_simple_server_session.h
+++ b/chromium/net/tools/quic/quic_simple_server_session.h
@@ -19,20 +19,17 @@
#include "base/macros.h"
#include "net/quic/core/quic_crypto_server_stream.h"
-#include "net/quic/core/quic_protocol.h"
+#include "net/quic/core/quic_packets.h"
#include "net/quic/core/quic_server_session_base.h"
#include "net/quic/core/quic_spdy_session.h"
-#include "net/tools/quic/quic_in_memory_cache.h"
+#include "net/tools/quic/quic_http_response_cache.h"
#include "net/tools/quic/quic_simple_server_stream.h"
namespace net {
-class QuicBlockedWriterInterface;
class QuicConfig;
class QuicConnection;
class QuicCryptoServerConfig;
-class ReliableQuicStream;
-
namespace test {
class QuicSimpleServerSessionPeer;
@@ -64,7 +61,8 @@ class QuicSimpleServerSession : public QuicServerSessionBase {
QuicSession::Visitor* visitor,
QuicCryptoServerStream::Helper* helper,
const QuicCryptoServerConfig* crypto_config,
- QuicCompressedCertsCache* compressed_certs_cache);
+ QuicCompressedCertsCache* compressed_certs_cache,
+ QuicHttpResponseCache* response_cache);
~QuicSimpleServerSession() override;
@@ -82,7 +80,7 @@ class QuicSimpleServerSession : public QuicServerSessionBase {
// later.
virtual void PromisePushResources(
const std::string& request_url,
- const std::list<QuicInMemoryCache::ServerPushInfo>& resources,
+ const std::list<QuicHttpResponseCache::ServerPushInfo>& resources,
QuicStreamId original_stream_id,
const SpdyHeaderBlock& original_request_headers);
@@ -105,6 +103,8 @@ class QuicSimpleServerSession : public QuicServerSessionBase {
const QuicCryptoServerConfig* crypto_config,
QuicCompressedCertsCache* compressed_certs_cache) override;
+ QuicHttpResponseCache* response_cache() { return response_cache_; }
+
private:
friend class test::QuicSimpleServerSessionPeer;
@@ -116,7 +116,7 @@ class QuicSimpleServerSession : public QuicServerSessionBase {
// request, especially cookies.
SpdyHeaderBlock SynthesizePushRequestHeaders(
std::string request_url,
- QuicInMemoryCache::ServerPushInfo resource,
+ QuicHttpResponseCache::ServerPushInfo resource,
const SpdyHeaderBlock& original_request_headers);
// Send PUSH_PROMISE frame on headers stream.
@@ -150,6 +150,8 @@ class QuicSimpleServerSession : public QuicServerSessionBase {
// highest_promised_stream_id_.
std::deque<PromisedStreamInfo> promised_streams_;
+ QuicHttpResponseCache* response_cache_; // Not owned.
+
DISALLOW_COPY_AND_ASSIGN(QuicSimpleServerSession);
};
diff --git a/chromium/net/tools/quic/quic_simple_server_session_helper.cc b/chromium/net/tools/quic/quic_simple_server_session_helper.cc
index 81ae1347558..51a2e4291ac 100644
--- a/chromium/net/tools/quic/quic_simple_server_session_helper.cc
+++ b/chromium/net/tools/quic/quic_simple_server_session_helper.cc
@@ -18,7 +18,7 @@ QuicConnectionId QuicSimpleServerSessionHelper::GenerateConnectionIdForReject(
bool QuicSimpleServerSessionHelper::CanAcceptClientHello(
const CryptoHandshakeMessage& message,
- const IPEndPoint& self_address,
+ const QuicSocketAddress& self_address,
std::string* error_details) const {
return true;
}
diff --git a/chromium/net/tools/quic/quic_simple_server_session_helper.h b/chromium/net/tools/quic/quic_simple_server_session_helper.h
index a876983b758..00a3bf9c8bb 100644
--- a/chromium/net/tools/quic/quic_simple_server_session_helper.h
+++ b/chromium/net/tools/quic/quic_simple_server_session_helper.h
@@ -22,7 +22,7 @@ class QuicSimpleServerSessionHelper : public QuicCryptoServerStream::Helper {
QuicConnectionId /*connection_id*/) const override;
bool CanAcceptClientHello(const CryptoHandshakeMessage& message,
- const IPEndPoint& self_address,
+ const QuicSocketAddress& self_address,
std::string* error_details) const override;
private:
diff --git a/chromium/net/tools/quic/quic_simple_server_session_test.cc b/chromium/net/tools/quic/quic_simple_server_session_test.cc
index e66bc421234..a808d23e5a3 100644
--- a/chromium/net/tools/quic/quic_simple_server_session_test.cc
+++ b/chromium/net/tools/quic/quic_simple_server_session_test.cc
@@ -15,6 +15,8 @@
#include "net/quic/core/quic_connection.h"
#include "net/quic/core/quic_crypto_server_stream.h"
#include "net/quic/core/quic_utils.h"
+#include "net/quic/platform/api/quic_socket_address.h"
+#include "net/quic/platform/api/quic_text_utils.h"
#include "net/quic/test_tools/crypto_test_utils.h"
#include "net/quic/test_tools/quic_config_peer.h"
#include "net/quic/test_tools/quic_connection_peer.h"
@@ -28,33 +30,16 @@
#include "net/test/gtest_util.h"
#include "net/tools/quic/quic_simple_server_stream.h"
#include "net/tools/quic/test_tools/mock_quic_server_session_visitor.h"
-#include "net/tools/quic/test_tools/quic_in_memory_cache_peer.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
-using net::test::CryptoTestUtils;
-using net::test::GenerateBody;
-using net::test::MockQuicConnection;
-using net::test::MockQuicConnectionHelper;
-using net::test::QuicConfigPeer;
-using net::test::QuicConnectionPeer;
-using net::test::QuicSpdyStreamPeer;
-using net::test::QuicSentPacketManagerPeer;
-using net::test::QuicSessionPeer;
-using net::test::QuicSpdySessionPeer;
-using net::test::QuicSustainedBandwidthRecorderPeer;
-using net::test::SupportedVersions;
-using net::test::kClientDataStreamId1;
-using net::test::kClientDataStreamId2;
-using net::test::kClientDataStreamId3;
-using net::test::kInitialSessionFlowControlWindowForTest;
-using net::test::kInitialStreamFlowControlWindowForTest;
using std::string;
using testing::StrictMock;
using testing::_;
+using testing::AtLeast;
using testing::InSequence;
using testing::Return;
-using testing::AtLeast;
+using testing::StrictMock;
namespace net {
namespace test {
@@ -62,39 +47,39 @@ namespace {
typedef QuicSimpleServerSession::PromisedStreamInfo PromisedStreamInfo;
} // namespace
-class MockQuicHeadersStream : public QuicHeadersStream {
+class QuicSimpleServerSessionPeer {
public:
- explicit MockQuicHeadersStream(QuicSpdySession* session)
- : QuicHeadersStream(session) {}
+ static void SetCryptoStream(QuicSimpleServerSession* s,
+ QuicCryptoServerStream* crypto_stream) {
+ s->crypto_stream_.reset(crypto_stream);
+ s->static_streams()[kCryptoStreamId] = crypto_stream;
+ }
- // Methods taking non-copyable types like SpdyHeaderBlock by value cannot be
- // mocked directly.
- size_t WritePushPromise(QuicStreamId original_stream_id,
- QuicStreamId promised_stream_id,
- SpdyHeaderBlock headers) override {
- return WritePushPromiseMock(original_stream_id, promised_stream_id,
- headers);
+ static QuicSpdyStream* CreateIncomingDynamicStream(QuicSimpleServerSession* s,
+ QuicStreamId id) {
+ return s->CreateIncomingDynamicStream(id);
}
- MOCK_METHOD3(WritePushPromiseMock,
- size_t(QuicStreamId original_stream_id,
- QuicStreamId promised_stream_id,
- const SpdyHeaderBlock& headers));
- size_t WriteHeaders(QuicStreamId stream_id,
- SpdyHeaderBlock headers,
- bool fin,
- SpdyPriority priority,
- QuicAckListenerInterface* ack_listener) override {
- return WriteHeadersMock(stream_id, headers, fin, priority, ack_listener);
+ static QuicSimpleServerStream* CreateOutgoingDynamicStream(
+ QuicSimpleServerSession* s,
+ SpdyPriority priority) {
+ return s->CreateOutgoingDynamicStream(priority);
+ }
+
+ static std::deque<PromisedStreamInfo>* promised_streams(
+ QuicSimpleServerSession* s) {
+ return &(s->promised_streams_);
+ }
+
+ static QuicStreamId hightest_promised_stream_id(QuicSimpleServerSession* s) {
+ return s->highest_promised_stream_id_;
}
- MOCK_METHOD5(WriteHeadersMock,
- size_t(QuicStreamId stream_id,
- const SpdyHeaderBlock& headers,
- bool fin,
- SpdyPriority priority,
- QuicAckListenerInterface* ack_listener));
};
+namespace {
+
+const size_t kMaxStreamsForTest = 10;
+
class MockQuicCryptoServerStream : public QuicCryptoServerStream {
public:
explicit MockQuicCryptoServerStream(
@@ -102,11 +87,12 @@ class MockQuicCryptoServerStream : public QuicCryptoServerStream {
QuicCompressedCertsCache* compressed_certs_cache,
QuicServerSessionBase* session,
QuicCryptoServerStream::Helper* helper)
- : QuicCryptoServerStream(crypto_config,
- compressed_certs_cache,
- FLAGS_enable_quic_stateless_reject_support,
- session,
- helper) {}
+ : QuicCryptoServerStream(
+ crypto_config,
+ compressed_certs_cache,
+ FLAGS_quic_reloadable_flag_enable_quic_stateless_reject_support,
+ session,
+ helper) {}
~MockQuicCryptoServerStream() override {}
MOCK_METHOD1(SendServerConfigUpdate,
@@ -132,47 +118,63 @@ class MockQuicConnectionWithSendStreamData : public MockQuicConnection {
perspective,
supported_versions) {}
- MOCK_METHOD5(SendStreamData,
- QuicConsumedData(QuicStreamId id,
- QuicIOVector iov,
- QuicStreamOffset offset,
- bool fin,
- QuicAckListenerInterface* listern));
+ MOCK_METHOD5(
+ SendStreamData,
+ QuicConsumedData(
+ QuicStreamId id,
+ QuicIOVector iov,
+ QuicStreamOffset offset,
+ bool fin,
+ QuicReferenceCountedPointer<QuicAckListenerInterface> ack_listener));
};
-class QuicSimpleServerSessionPeer {
+class MockQuicSimpleServerSession : public QuicSimpleServerSession {
public:
- static void SetCryptoStream(QuicSimpleServerSession* s,
- QuicCryptoServerStream* crypto_stream) {
- s->crypto_stream_.reset(crypto_stream);
- s->static_streams()[kCryptoStreamId] = crypto_stream;
- }
-
- static QuicSpdyStream* CreateIncomingDynamicStream(QuicSimpleServerSession* s,
- QuicStreamId id) {
- return s->CreateIncomingDynamicStream(id);
- }
-
- static QuicSimpleServerStream* CreateOutgoingDynamicStream(
- QuicSimpleServerSession* s,
- SpdyPriority priority) {
- return s->CreateOutgoingDynamicStream(priority);
- }
-
- static std::deque<PromisedStreamInfo>* promised_streams(
- QuicSimpleServerSession* s) {
- return &(s->promised_streams_);
+ MockQuicSimpleServerSession(const QuicConfig& config,
+ QuicConnection* connection,
+ QuicSession::Visitor* visitor,
+ QuicCryptoServerStream::Helper* helper,
+ const QuicCryptoServerConfig* crypto_config,
+ QuicCompressedCertsCache* compressed_certs_cache,
+ QuicHttpResponseCache* response_cache)
+ : QuicSimpleServerSession(config,
+ connection,
+ visitor,
+ helper,
+ crypto_config,
+ compressed_certs_cache,
+ response_cache) {}
+ // Methods taking non-copyable types like SpdyHeaderBlock by value cannot be
+ // mocked directly.
+ size_t WritePushPromise(QuicStreamId original_stream_id,
+ QuicStreamId promised_stream_id,
+ SpdyHeaderBlock headers) override {
+ return WritePushPromiseMock(original_stream_id, promised_stream_id,
+ headers);
}
+ MOCK_METHOD3(WritePushPromiseMock,
+ size_t(QuicStreamId original_stream_id,
+ QuicStreamId promised_stream_id,
+ const SpdyHeaderBlock& headers));
- static QuicStreamId hightest_promised_stream_id(QuicSimpleServerSession* s) {
- return s->highest_promised_stream_id_;
+ size_t WriteHeaders(QuicStreamId stream_id,
+ SpdyHeaderBlock headers,
+ bool fin,
+ SpdyPriority priority,
+ QuicReferenceCountedPointer<QuicAckListenerInterface>
+ ack_listener) override {
+ return WriteHeadersMock(stream_id, headers, fin, priority, ack_listener);
}
+ MOCK_METHOD5(
+ WriteHeadersMock,
+ size_t(QuicStreamId stream_id,
+ const SpdyHeaderBlock& headers,
+ bool fin,
+ SpdyPriority priority,
+ const QuicReferenceCountedPointer<QuicAckListenerInterface>&
+ ack_listener));
};
-namespace {
-
-const size_t kMaxStreamsForTest = 10;
-
class QuicSimpleServerSessionTest
: public ::testing::TestWithParam<QuicVersion> {
protected:
@@ -194,17 +196,15 @@ class QuicSimpleServerSessionTest
connection_ = new StrictMock<MockQuicConnectionWithSendStreamData>(
&helper_, &alarm_factory_, Perspective::IS_SERVER,
SupportedVersions(GetParam()));
- session_.reset(new QuicSimpleServerSession(config_, connection_, &owner_,
- &stream_helper_, &crypto_config_,
- &compressed_certs_cache_));
+ session_.reset(new MockQuicSimpleServerSession(
+ config_, connection_, &owner_, &stream_helper_, &crypto_config_,
+ &compressed_certs_cache_, &response_cache_));
MockClock clock;
handshake_message_.reset(crypto_config_.AddDefaultConfig(
QuicRandom::GetInstance(), &clock,
QuicCryptoServerConfig::ConfigOptions()));
session_->Initialize();
visitor_ = QuicConnectionPeer::GetVisitor(connection_);
- headers_stream_ = new MockQuicHeadersStream(session_.get());
- QuicSpdySessionPeer::SetHeadersStream(session_.get(), headers_stream_);
session_->OnConfigNegotiated();
}
@@ -217,10 +217,10 @@ class QuicSimpleServerSessionTest
QuicConfig config_;
QuicCryptoServerConfig crypto_config_;
QuicCompressedCertsCache compressed_certs_cache_;
- std::unique_ptr<QuicSimpleServerSession> session_;
+ QuicHttpResponseCache response_cache_;
+ std::unique_ptr<MockQuicSimpleServerSession> session_;
std::unique_ptr<CryptoHandshakeMessage> handshake_message_;
QuicConnectionVisitorInterface* visitor_;
- MockQuicHeadersStream* headers_stream_;
};
INSTANTIATE_TEST_CASE_P(Tests,
@@ -433,16 +433,14 @@ class QuicSimpleServerSessionServerPushTest
connection_ = new StrictMock<MockQuicConnectionWithSendStreamData>(
&helper_, &alarm_factory_, Perspective::IS_SERVER,
SupportedVersions(GetParam()));
- session_.reset(new QuicSimpleServerSession(config_, connection_, &owner_,
- &stream_helper_, &crypto_config_,
- &compressed_certs_cache_));
+ session_.reset(new MockQuicSimpleServerSession(
+ config_, connection_, &owner_, &stream_helper_, &crypto_config_,
+ &compressed_certs_cache_, &response_cache_));
session_->Initialize();
// Needed to make new session flow control window and server push work.
session_->OnConfigNegotiated();
visitor_ = QuicConnectionPeer::GetVisitor(connection_);
- headers_stream_ = new MockQuicHeadersStream(session_.get());
- QuicSpdySessionPeer::SetHeadersStream(session_.get(), headers_stream_);
// Assume encryption already established.
MockQuicCryptoServerStream* crypto_stream = new MockQuicCryptoServerStream(
@@ -464,38 +462,33 @@ class QuicSimpleServerSessionServerPushTest
config_.SetMaxStreamsPerConnection(kMaxStreamsForTest, kMaxStreamsForTest);
- QuicInMemoryCachePeer::ResetForTests();
-
string request_url = "mail.google.com/";
SpdyHeaderBlock request_headers;
string resource_host = "www.google.com";
string partial_push_resource_path = "/server_push_src";
- std::list<QuicInMemoryCache::ServerPushInfo> push_resources;
+ std::list<QuicHttpResponseCache::ServerPushInfo> push_resources;
string scheme = "http";
for (unsigned int i = 1; i <= num_resources; ++i) {
QuicStreamId stream_id = i * 2;
- string path = partial_push_resource_path + base::UintToString(i);
+ string path =
+ partial_push_resource_path + QuicTextUtils::Uint64ToString(i);
string url = scheme + "://" + resource_host + path;
GURL resource_url = GURL(url);
- string body;
- GenerateBody(&body, body_size);
- QuicInMemoryCache::GetInstance()->AddSimpleResponse(resource_host, path,
- 200, body);
- push_resources.push_back(QuicInMemoryCache::ServerPushInfo(
+ string body(body_size, 'a');
+ response_cache_.AddSimpleResponse(resource_host, path, 200, body);
+ push_resources.push_back(QuicHttpResponseCache::ServerPushInfo(
resource_url, SpdyHeaderBlock(), kDefaultPriority, body));
// PUSH_PROMISED are sent for all the resources.
- EXPECT_CALL(*headers_stream_,
+ EXPECT_CALL(*session_,
WritePushPromiseMock(kClientDataStreamId1, stream_id, _));
if (i <= kMaxStreamsForTest) {
// |kMaxStreamsForTest| promised responses should be sent.
- EXPECT_CALL(
- *headers_stream_,
- WriteHeadersMock(stream_id, _, false, kDefaultPriority, nullptr));
+ EXPECT_CALL(*session_,
+ WriteHeadersMock(stream_id, _, false, kDefaultPriority, _));
// Since flow control window is smaller than response body, not the
// whole body will be sent.
if (!session_->force_hol_blocking()) {
- EXPECT_CALL(*connection_,
- SendStreamData(stream_id, _, 0, false, nullptr))
+ EXPECT_CALL(*connection_, SendStreamData(stream_id, _, 0, false, _))
.WillOnce(Return(
QuicConsumedData(kStreamFlowControlWindowSize, false)));
EXPECT_CALL(*connection_, SendBlocked(stream_id));
@@ -504,7 +497,7 @@ class QuicSimpleServerSessionServerPushTest
// HTTP/2 DATA frames within the headers stream. HTTP/2
// DATA frames are limited to a max size of 16KB, so the
// 64KB body will be fragemented into four DATA frames.
- EXPECT_CALL(*connection_, SendStreamData(_, _, _, false, nullptr))
+ EXPECT_CALL(*connection_, SendStreamData(_, _, _, false, _))
.Times(body_size / 16384)
.WillOnce(Return(QuicConsumedData(9 + 16394, false)))
.WillOnce(Return(QuicConsumedData(9 + 16394, false)))
@@ -550,11 +543,10 @@ TEST_P(QuicSimpleServerSessionServerPushTest,
// After an open stream is marked draining, a new stream is expected to be
// created and a response sent on the stream.
- EXPECT_CALL(*headers_stream_,
- WriteHeadersMock(next_out_going_stream_id, _, false,
- kDefaultPriority, nullptr));
+ EXPECT_CALL(*session_, WriteHeadersMock(next_out_going_stream_id, _, false,
+ kDefaultPriority, _));
EXPECT_CALL(*connection_,
- SendStreamData(next_out_going_stream_id, _, 0, false, nullptr))
+ SendStreamData(next_out_going_stream_id, _, 0, false, _))
.WillOnce(Return(QuicConsumedData(kStreamFlowControlWindowSize, false)));
EXPECT_CALL(*connection_, SendBlocked(next_out_going_stream_id));
session_->StreamDraining(2);
@@ -588,14 +580,13 @@ TEST_P(QuicSimpleServerSessionServerPushTest,
// only one queued resource will be sent out.
QuicStreamId stream_not_reset = (kMaxStreamsForTest + 1) * 2;
InSequence s;
- EXPECT_CALL(*headers_stream_, WriteHeadersMock(stream_not_reset, _, false,
- kDefaultPriority, nullptr));
- EXPECT_CALL(*connection_,
- SendStreamData(stream_not_reset, _, 0, false, nullptr))
+ EXPECT_CALL(*session_, WriteHeadersMock(stream_not_reset, _, false,
+ kDefaultPriority, _));
+ EXPECT_CALL(*connection_, SendStreamData(stream_not_reset, _, 0, false, _))
.WillOnce(Return(QuicConsumedData(kStreamFlowControlWindowSize, false)));
EXPECT_CALL(*connection_, SendBlocked(stream_not_reset));
- EXPECT_CALL(*headers_stream_, WriteHeadersMock(stream_got_reset, _, false,
- kDefaultPriority, nullptr))
+ EXPECT_CALL(*session_,
+ WriteHeadersMock(stream_got_reset, _, false, kDefaultPriority, _))
.Times(0);
session_->StreamDraining(2);
@@ -618,10 +609,9 @@ TEST_P(QuicSimpleServerSessionServerPushTest,
QuicStreamId stream_got_reset = 2;
EXPECT_CALL(*connection_,
SendRstStream(stream_got_reset, QUIC_RST_ACKNOWLEDGEMENT, _));
- EXPECT_CALL(*headers_stream_, WriteHeadersMock(stream_to_open, _, false,
- kDefaultPriority, nullptr));
- EXPECT_CALL(*connection_,
- SendStreamData(stream_to_open, _, 0, false, nullptr))
+ EXPECT_CALL(*session_,
+ WriteHeadersMock(stream_to_open, _, false, kDefaultPriority, _));
+ EXPECT_CALL(*connection_, SendStreamData(stream_to_open, _, 0, false, _))
.WillOnce(Return(QuicConsumedData(kStreamFlowControlWindowSize, false)));
EXPECT_CALL(*connection_, SendBlocked(stream_to_open));
diff --git a/chromium/net/tools/quic/quic_simple_server_stream.cc b/chromium/net/tools/quic/quic_simple_server_stream.cc
index 9aa2786616b..7136bd5f7dc 100644
--- a/chromium/net/tools/quic/quic_simple_server_stream.cc
+++ b/chromium/net/tools/quic/quic_simple_server_stream.cc
@@ -7,28 +7,29 @@
#include <list>
#include <utility>
-#include "base/logging.h"
#include "base/stl_util.h"
-#include "base/strings/string_number_conversions.h"
-#include "base/strings/string_piece.h"
-#include "base/strings/string_split.h"
-#include "net/quic/core/quic_bug_tracker.h"
#include "net/quic/core/quic_flags.h"
#include "net/quic/core/quic_spdy_stream.h"
#include "net/quic/core/spdy_utils.h"
+#include "net/quic/platform/api/quic_bug_tracker.h"
+#include "net/quic/platform/api/quic_logging.h"
+#include "net/quic/platform/api/quic_text_utils.h"
#include "net/spdy/spdy_protocol.h"
-#include "net/tools/quic/quic_in_memory_cache.h"
+#include "net/tools/quic/quic_http_response_cache.h"
#include "net/tools/quic/quic_simple_server_session.h"
using base::StringPiece;
-using base::StringToInt;
using std::string;
namespace net {
-QuicSimpleServerStream::QuicSimpleServerStream(QuicStreamId id,
- QuicSpdySession* session)
- : QuicSpdyStream(id, session), content_length_(-1) {}
+QuicSimpleServerStream::QuicSimpleServerStream(
+ QuicStreamId id,
+ QuicSpdySession* session,
+ QuicHttpResponseCache* response_cache)
+ : QuicSpdyServerStreamBase(id, session),
+ content_length_(-1),
+ response_cache_(response_cache) {}
QuicSimpleServerStream::~QuicSimpleServerStream() {}
@@ -39,7 +40,7 @@ void QuicSimpleServerStream::OnInitialHeadersComplete(
QuicSpdyStream::OnInitialHeadersComplete(fin, frame_len, header_list);
if (!SpdyUtils::CopyAndValidateHeaders(header_list, &content_length_,
&request_headers_)) {
- DVLOG(1) << "Invalid headers";
+ QUIC_DVLOG(1) << "Invalid headers";
SendErrorResponse();
}
ConsumeHeaderList();
@@ -60,13 +61,14 @@ void QuicSimpleServerStream::OnDataAvailable() {
// No more data to read.
break;
}
- DVLOG(1) << "Processed " << iov.iov_len << " bytes for stream " << id();
+ QUIC_DVLOG(1) << "Processed " << iov.iov_len << " bytes for stream "
+ << id();
body_.append(static_cast<char*>(iov.iov_base), iov.iov_len);
if (content_length_ >= 0 &&
body_.size() > static_cast<uint64_t>(content_length_)) {
- DVLOG(1) << "Body size (" << body_.size() << ") > content length ("
- << content_length_ << ").";
+ QUIC_DVLOG(1) << "Body size (" << body_.size() << ") > content length ("
+ << content_length_ << ").";
SendErrorResponse();
return;
}
@@ -97,7 +99,8 @@ void QuicSimpleServerStream::PushResponse(
// Change the stream state to emulate a client request.
request_headers_ = std::move(push_request_headers);
content_length_ = 0;
- DVLOG(1) << "Stream " << id() << ": Ready to receive server push response.";
+ QUIC_DVLOG(1) << "Stream " << id()
+ << ": Ready to receive server push response.";
// Set as if stream decompresed the headers and received fin.
QuicSpdyStream::OnInitialHeadersComplete(/*fin=*/true, 0, QuicHeaderList());
@@ -105,48 +108,47 @@ void QuicSimpleServerStream::PushResponse(
void QuicSimpleServerStream::SendResponse() {
if (request_headers_.empty()) {
- DVLOG(1) << "Request headers empty.";
+ QUIC_DVLOG(1) << "Request headers empty.";
SendErrorResponse();
return;
}
if (content_length_ > 0 &&
static_cast<uint64_t>(content_length_) != body_.size()) {
- DVLOG(1) << "Content length (" << content_length_ << ") != body size ("
- << body_.size() << ").";
+ QUIC_DVLOG(1) << "Content length (" << content_length_ << ") != body size ("
+ << body_.size() << ").";
SendErrorResponse();
return;
}
if (!base::ContainsKey(request_headers_, ":authority") ||
!base::ContainsKey(request_headers_, ":path")) {
- DVLOG(1) << "Request headers do not contain :authority or :path.";
+ QUIC_DVLOG(1) << "Request headers do not contain :authority or :path.";
SendErrorResponse();
return;
}
// Find response in cache. If not found, send error response.
- const QuicInMemoryCache::Response* response = nullptr;
+ const QuicHttpResponseCache::Response* response = nullptr;
auto authority = request_headers_.find(":authority");
auto path = request_headers_.find(":path");
if (authority != request_headers_.end() && path != request_headers_.end()) {
- response = QuicInMemoryCache::GetInstance()->GetResponse(authority->second,
- path->second);
+ response = response_cache_->GetResponse(authority->second, path->second);
}
if (response == nullptr) {
- DVLOG(1) << "Response not found in cache.";
+ QUIC_DVLOG(1) << "Response not found in cache.";
SendNotFoundResponse();
return;
}
- if (response->response_type() == QuicInMemoryCache::CLOSE_CONNECTION) {
- DVLOG(1) << "Special response: closing connection.";
+ if (response->response_type() == QuicHttpResponseCache::CLOSE_CONNECTION) {
+ QUIC_DVLOG(1) << "Special response: closing connection.";
CloseConnectionWithDetails(QUIC_NO_ERROR, "Toy server forcing close");
return;
}
- if (response->response_type() == QuicInMemoryCache::IGNORE_REQUEST) {
- DVLOG(1) << "Special response: ignoring request.";
+ if (response->response_type() == QuicHttpResponseCache::IGNORE_REQUEST) {
+ QUIC_DVLOG(1) << "Special response: ignoring request.";
return;
}
@@ -159,11 +161,12 @@ void QuicSimpleServerStream::SendResponse() {
if (!ParseHeaderStatusCode(response_headers, &response_code)) {
auto status = response_headers.find(":status");
if (status == response_headers.end()) {
- LOG(WARNING) << ":status not present in response from cache for request "
- << request_url;
+ QUIC_LOG(WARNING)
+ << ":status not present in response from cache for request "
+ << request_url;
} else {
- LOG(WARNING) << "Illegal (non-integer) response :status from cache: "
- << status->second << " for request " << request_url;
+ QUIC_LOG(WARNING) << "Illegal (non-integer) response :status from cache: "
+ << status->second << " for request " << request_url;
}
SendErrorResponse();
return;
@@ -175,16 +178,16 @@ void QuicSimpleServerStream::SendResponse() {
// This behavior mirrors the HTTP/2 implementation.
bool is_redirection = response_code / 100 == 3;
if (response_code != 200 && !is_redirection) {
- LOG(WARNING) << "Response to server push request " << request_url
- << " result in response code " << response_code;
+ QUIC_LOG(WARNING) << "Response to server push request " << request_url
+ << " result in response code " << response_code;
Reset(QUIC_STREAM_CANCELLED);
return;
}
}
- std::list<QuicInMemoryCache::ServerPushInfo> resources =
- QuicInMemoryCache::GetInstance()->GetServerPushResources(request_url);
- DVLOG(1) << "Found " << resources.size() << " push resources for stream "
- << id();
+ std::list<QuicHttpResponseCache::ServerPushInfo> resources =
+ response_cache_->GetServerPushResources(request_url);
+ QUIC_DVLOG(1) << "Found " << resources.size() << " push resources for stream "
+ << id();
if (!resources.empty()) {
QuicSimpleServerSession* session =
@@ -193,24 +196,26 @@ void QuicSimpleServerStream::SendResponse() {
request_headers_);
}
- DVLOG(1) << "Sending response for stream " << id();
+ QUIC_DVLOG(1) << "Sending response for stream " << id();
SendHeadersAndBodyAndTrailers(response->headers().Clone(), response->body(),
response->trailers().Clone());
}
void QuicSimpleServerStream::SendNotFoundResponse() {
- DVLOG(1) << "Sending not found response for stream " << id();
+ QUIC_DVLOG(1) << "Sending not found response for stream " << id();
SpdyHeaderBlock headers;
headers[":status"] = "404";
- headers["content-length"] = base::IntToString(strlen(kNotFoundResponseBody));
+ headers["content-length"] =
+ QuicTextUtils::Uint64ToString(strlen(kNotFoundResponseBody));
SendHeadersAndBody(std::move(headers), kNotFoundResponseBody);
}
void QuicSimpleServerStream::SendErrorResponse() {
- DVLOG(1) << "Sending error response for stream " << id();
+ QUIC_DVLOG(1) << "Sending error response for stream " << id();
SpdyHeaderBlock headers;
headers[":status"] = "500";
- headers["content-length"] = base::UintToString(strlen(kErrorResponseBody));
+ headers["content-length"] =
+ QuicTextUtils::Uint64ToString(strlen(kErrorResponseBody));
SendHeadersAndBody(std::move(headers), kErrorResponseBody);
}
@@ -231,8 +236,8 @@ void QuicSimpleServerStream::SendHeadersAndBodyAndTrailers(
// Send the headers, with a FIN if there's nothing else to send.
bool send_fin = (body.empty() && response_trailers.empty());
- DVLOG(1) << "Writing headers (fin = " << send_fin
- << ") : " << response_headers.DebugString();
+ QUIC_DLOG(INFO) << "Writing headers (fin = " << send_fin
+ << ") : " << response_headers.DebugString();
WriteHeaders(std::move(response_headers), send_fin, nullptr);
if (send_fin) {
// Nothing else to send.
@@ -241,8 +246,8 @@ void QuicSimpleServerStream::SendHeadersAndBodyAndTrailers(
// Send the body, with a FIN if there's no trailers to send.
send_fin = response_trailers.empty();
- DVLOG(1) << "Writing body (fin = " << send_fin
- << ") with size: " << body.size();
+ QUIC_DLOG(INFO) << "Writing body (fin = " << send_fin
+ << ") with size: " << body.size();
if (!body.empty() || send_fin) {
WriteOrBufferData(body, send_fin, nullptr);
}
@@ -252,8 +257,8 @@ void QuicSimpleServerStream::SendHeadersAndBodyAndTrailers(
}
// Send the trailers. A FIN is always sent with trailers.
- DVLOG(1) << "Writing trailers (fin = true): "
- << response_trailers.DebugString();
+ QUIC_DLOG(INFO) << "Writing trailers (fin = true): "
+ << response_trailers.DebugString();
WriteTrailers(std::move(response_trailers), nullptr);
}
diff --git a/chromium/net/tools/quic/quic_simple_server_stream.h b/chromium/net/tools/quic/quic_simple_server_stream.h
index 731e32f1d45..2aa7b759ce1 100644
--- a/chromium/net/tools/quic/quic_simple_server_stream.h
+++ b/chromium/net/tools/quic/quic_simple_server_stream.h
@@ -10,9 +10,11 @@
#include <string>
#include "base/macros.h"
-#include "net/quic/core/quic_protocol.h"
+#include "net/quic/core/quic_packets.h"
#include "net/quic/core/quic_spdy_stream.h"
#include "net/spdy/spdy_framer.h"
+#include "net/tools/quic/quic_http_response_cache.h"
+#include "net/tools/quic/quic_spdy_server_stream_base.h"
namespace net {
@@ -23,9 +25,11 @@ class QuicSimpleServerStreamPeer;
// All this does right now is aggregate data, and on fin, send an HTTP
// response.
-class QuicSimpleServerStream : public QuicSpdyStream {
+class QuicSimpleServerStream : public QuicSpdyServerStreamBase {
public:
- QuicSimpleServerStream(QuicStreamId id, QuicSpdySession* session);
+ QuicSimpleServerStream(QuicStreamId id,
+ QuicSpdySession* session,
+ QuicHttpResponseCache* response_cache);
~QuicSimpleServerStream() override;
// QuicSpdyStream
@@ -80,6 +84,8 @@ class QuicSimpleServerStream : public QuicSpdyStream {
int64_t content_length_;
std::string body_;
+ QuicHttpResponseCache* response_cache_; // Not owned.
+
DISALLOW_COPY_AND_ASSIGN(QuicSimpleServerStream);
};
diff --git a/chromium/net/tools/quic/quic_simple_server_stream_test.cc b/chromium/net/tools/quic/quic_simple_server_stream_test.cc
index 48c142bed3c..bd1780eb97a 100644
--- a/chromium/net/tools/quic/quic_simple_server_stream_test.cc
+++ b/chromium/net/tools/quic/quic_simple_server_stream_test.cc
@@ -8,34 +8,27 @@
#include <memory>
#include <utility>
-#include "base/memory/ptr_util.h"
#include "base/strings/string_number_conversions.h"
#include "base/strings/string_piece.h"
#include "net/quic/core/quic_connection.h"
#include "net/quic/core/quic_flags.h"
-#include "net/quic/core/quic_protocol.h"
+#include "net/quic/core/quic_packets.h"
#include "net/quic/core/quic_utils.h"
#include "net/quic/core/spdy_utils.h"
+#include "net/quic/platform/api/quic_ptr_util.h"
+#include "net/quic/platform/api/quic_socket_address.h"
#include "net/quic/test_tools/crypto_test_utils.h"
#include "net/quic/test_tools/quic_stream_peer.h"
#include "net/quic/test_tools/quic_test_utils.h"
#include "net/test/gtest_util.h"
#include "net/tools/epoll_server/epoll_server.h"
-#include "net/tools/quic/quic_in_memory_cache.h"
+#include "net/tools/quic/quic_http_response_cache.h"
#include "net/tools/quic/quic_simple_server_session.h"
-#include "net/tools/quic/test_tools/quic_in_memory_cache_peer.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "url/gurl.h"
using base::StringPiece;
-using net::test::MockQuicConnection;
-using net::test::MockQuicConnectionHelper;
-using net::test::MockQuicSpdySession;
-using net::test::QuicStreamPeer;
-using net::test::SupportedVersions;
-using net::test::kInitialSessionFlowControlWindowForTest;
-using net::test::kInitialStreamFlowControlWindowForTest;
using std::string;
using testing::_;
using testing::AnyNumber;
@@ -53,8 +46,10 @@ size_t kFakeFrameLen = 60;
class QuicSimpleServerStreamPeer : public QuicSimpleServerStream {
public:
- QuicSimpleServerStreamPeer(QuicStreamId stream_id, QuicSpdySession* session)
- : QuicSimpleServerStream(stream_id, session) {}
+ QuicSimpleServerStreamPeer(QuicStreamId stream_id,
+ QuicSpdySession* session,
+ QuicHttpResponseCache* response_cache)
+ : QuicSimpleServerStream(stream_id, session, response_cache) {}
~QuicSimpleServerStreamPeer() override{};
@@ -84,6 +79,8 @@ class QuicSimpleServerStreamPeer : public QuicSimpleServerStream {
}
};
+namespace {
+
class MockQuicSimpleServerSession : public QuicSimpleServerSession {
public:
const size_t kMaxStreamsForTest = 100;
@@ -93,13 +90,15 @@ class MockQuicSimpleServerSession : public QuicSimpleServerSession {
MockQuicSessionVisitor* owner,
MockQuicCryptoServerStreamHelper* helper,
QuicCryptoServerConfig* crypto_config,
- QuicCompressedCertsCache* compressed_certs_cache)
+ QuicCompressedCertsCache* compressed_certs_cache,
+ QuicHttpResponseCache* response_cache)
: QuicSimpleServerSession(DefaultQuicConfig(),
connection,
owner,
helper,
crypto_config,
- compressed_certs_cache) {
+ compressed_certs_cache,
+ response_cache) {
set_max_open_incoming_streams(kMaxStreamsForTest);
set_max_open_outgoing_streams(kMaxStreamsForTest);
ON_CALL(*this, WritevData(_, _, _, _, _, _))
@@ -113,13 +112,14 @@ class MockQuicSimpleServerSession : public QuicSimpleServerSession {
const string& error_details,
ConnectionCloseSource source));
MOCK_METHOD1(CreateIncomingDynamicStream, QuicSpdyStream*(QuicStreamId id));
- MOCK_METHOD6(WritevData,
- QuicConsumedData(QuicStream* stream,
- QuicStreamId id,
- QuicIOVector data,
- QuicStreamOffset offset,
- bool fin,
- QuicAckListenerInterface*));
+ MOCK_METHOD6(
+ WritevData,
+ QuicConsumedData(QuicStream* stream,
+ QuicStreamId id,
+ QuicIOVector data,
+ QuicStreamOffset offset,
+ bool fin,
+ QuicReferenceCountedPointer<QuicAckListenerInterface>));
MOCK_METHOD4(OnStreamHeaderList,
void(QuicStreamId stream_id,
bool fin,
@@ -129,20 +129,22 @@ class MockQuicSimpleServerSession : public QuicSimpleServerSession {
void(QuicStreamId stream_id, SpdyPriority priority));
// Methods taking non-copyable types like SpdyHeaderBlock by value cannot be
// mocked directly.
- size_t WriteHeaders(
- QuicStreamId id,
- SpdyHeaderBlock headers,
- bool fin,
- SpdyPriority priority,
- QuicAckListenerInterface* ack_notifier_delegate) override {
- return WriteHeadersMock(id, headers, fin, priority, ack_notifier_delegate);
- }
- MOCK_METHOD5(WriteHeadersMock,
- size_t(QuicStreamId id,
- const SpdyHeaderBlock& headers,
+ size_t WriteHeaders(QuicStreamId id,
+ SpdyHeaderBlock headers,
bool fin,
SpdyPriority priority,
- QuicAckListenerInterface* ack_notifier_delegate));
+ QuicReferenceCountedPointer<QuicAckListenerInterface>
+ ack_listener) override {
+ return WriteHeadersMock(id, headers, fin, priority, ack_listener);
+ }
+ MOCK_METHOD5(
+ WriteHeadersMock,
+ size_t(QuicStreamId id,
+ const SpdyHeaderBlock& headers,
+ bool fin,
+ SpdyPriority priority,
+ const QuicReferenceCountedPointer<QuicAckListenerInterface>&
+ ack_listener));
MOCK_METHOD3(SendRstStream,
void(QuicStreamId stream_id,
QuicRstStreamErrorCode error,
@@ -151,7 +153,7 @@ class MockQuicSimpleServerSession : public QuicSimpleServerSession {
// Matchers cannot be used on non-copyable types like SpdyHeaderBlock.
void PromisePushResources(
const string& request_url,
- const std::list<QuicInMemoryCache::ServerPushInfo>& resources,
+ const std::list<QuicHttpResponseCache::ServerPushInfo>& resources,
QuicStreamId original_stream_id,
const SpdyHeaderBlock& original_request_headers) override {
original_request_headers_ = original_request_headers.Clone();
@@ -160,7 +162,7 @@ class MockQuicSimpleServerSession : public QuicSimpleServerSession {
}
MOCK_METHOD4(PromisePushResourcesMock,
void(const string&,
- const std::list<QuicInMemoryCache::ServerPushInfo>&,
+ const std::list<QuicHttpResponseCache::ServerPushInfo>&,
QuicStreamId,
const SpdyHeaderBlock&));
@@ -172,8 +174,6 @@ class MockQuicSimpleServerSession : public QuicSimpleServerSession {
DISALLOW_COPY_AND_ASSIGN(MockQuicSimpleServerSession);
};
-namespace {
-
class QuicSimpleServerStreamTest
: public ::testing::TestWithParam<QuicVersion> {
public:
@@ -193,7 +193,8 @@ class QuicSimpleServerStreamTest
&session_owner_,
&session_helper_,
crypto_config_.get(),
- &compressed_certs_cache_),
+ &compressed_certs_cache_,
+ &response_cache_),
body_("hello world") {
header_list_.OnHeaderBlockStart();
header_list_.OnHeader(":authority", "www.google.com");
@@ -210,15 +211,9 @@ class QuicSimpleServerStreamTest
session_.config()->SetInitialSessionFlowControlWindowToSend(
kInitialSessionFlowControlWindowForTest);
stream_ = new QuicSimpleServerStreamPeer(::net::test::kClientDataStreamId1,
- &session_);
+ &session_, &response_cache_);
// Register stream_ in dynamic_stream_map_ and pass ownership to session_.
- session_.ActivateStream(base::WrapUnique(stream_));
-
- QuicInMemoryCachePeer::ResetForTests();
- }
-
- ~QuicSimpleServerStreamTest() override {
- QuicInMemoryCachePeer::ResetForTests();
+ session_.ActivateStream(QuicWrapUnique(stream_));
}
const string& StreamBody() {
@@ -237,6 +232,7 @@ class QuicSimpleServerStreamTest
StrictMock<MockQuicCryptoServerStreamHelper> session_helper_;
std::unique_ptr<QuicCryptoServerConfig> crypto_config_;
QuicCompressedCertsCache compressed_certs_cache_;
+ QuicHttpResponseCache response_cache_;
StrictMock<MockQuicSimpleServerSession> session_;
QuicSimpleServerStreamPeer* stream_; // Owned by session_.
string headers_string_;
@@ -324,13 +320,13 @@ TEST_P(QuicSimpleServerStreamTest, SendResponseWithIllegalResponseStatus) {
response_headers_[":status"] = "200 OK";
response_headers_["content-length"] = "5";
string body = "Yummm";
- QuicInMemoryCache::GetInstance()->AddResponse(
- "www.google.com", "/bar", std::move(response_headers_), body);
+ response_cache_.AddResponse("www.google.com", "/bar",
+ std::move(response_headers_), body);
stream_->set_fin_received(true);
InSequence s;
- EXPECT_CALL(session_, WriteHeadersMock(stream_->id(), _, false, _, nullptr));
+ EXPECT_CALL(session_, WriteHeadersMock(stream_->id(), _, false, _, _));
EXPECT_CALL(session_, WritevData(_, _, _, _, _, _))
.Times(1)
.WillOnce(Return(QuicConsumedData(
@@ -355,13 +351,13 @@ TEST_P(QuicSimpleServerStreamTest, SendResponseWithIllegalResponseStatus2) {
response_headers_[":status"] = "+200";
response_headers_["content-length"] = "5";
string body = "Yummm";
- QuicInMemoryCache::GetInstance()->AddResponse(
- "www.google.com", "/bar", std::move(response_headers_), body);
+ response_cache_.AddResponse("www.google.com", "/bar",
+ std::move(response_headers_), body);
stream_->set_fin_received(true);
InSequence s;
- EXPECT_CALL(session_, WriteHeadersMock(stream_->id(), _, false, _, nullptr));
+ EXPECT_CALL(session_, WriteHeadersMock(stream_->id(), _, false, _, _));
EXPECT_CALL(session_, WritevData(_, _, _, _, _, _))
.Times(1)
.WillOnce(Return(QuicConsumedData(
@@ -376,8 +372,8 @@ TEST_P(QuicSimpleServerStreamTest, SendResponseWithIllegalResponseStatus2) {
TEST_P(QuicSimpleServerStreamTest, SendPushResponseWith404Response) {
// Create a new promised stream with even id().
QuicSimpleServerStreamPeer* promised_stream =
- new QuicSimpleServerStreamPeer(2, &session_);
- session_.ActivateStream(base::WrapUnique(promised_stream));
+ new QuicSimpleServerStreamPeer(2, &session_, &response_cache_);
+ session_.ActivateStream(QuicWrapUnique(promised_stream));
// Send a push response with response status 404, which will be regarded as
// invalid server push response.
@@ -391,8 +387,8 @@ TEST_P(QuicSimpleServerStreamTest, SendPushResponseWith404Response) {
response_headers_[":status"] = "404";
response_headers_["content-length"] = "8";
string body = "NotFound";
- QuicInMemoryCache::GetInstance()->AddResponse(
- "www.google.com", "/bar", std::move(response_headers_), body);
+ response_cache_.AddResponse("www.google.com", "/bar",
+ std::move(response_headers_), body);
InSequence s;
EXPECT_CALL(session_,
@@ -413,12 +409,12 @@ TEST_P(QuicSimpleServerStreamTest, SendResponseWithValidHeaders) {
response_headers_[":status"] = "200";
response_headers_["content-length"] = "5";
string body = "Yummm";
- QuicInMemoryCache::GetInstance()->AddResponse(
- "www.google.com", "/bar", std::move(response_headers_), body);
+ response_cache_.AddResponse("www.google.com", "/bar",
+ std::move(response_headers_), body);
stream_->set_fin_received(true);
InSequence s;
- EXPECT_CALL(session_, WriteHeadersMock(stream_->id(), _, false, _, nullptr));
+ EXPECT_CALL(session_, WriteHeadersMock(stream_->id(), _, false, _, _));
EXPECT_CALL(session_, WritevData(_, _, _, _, _, _))
.Times(1)
.WillOnce(Return(QuicConsumedData(body.length(), true)));
@@ -438,11 +434,11 @@ TEST_P(QuicSimpleServerStreamTest, SendReponseWithPushResources) {
string request_path = "/foo";
string body = "Yummm";
string url = host + "/bar";
- QuicInMemoryCache::ServerPushInfo push_info(GURL(url), SpdyHeaderBlock(),
- kDefaultPriority, "Push body");
- std::list<QuicInMemoryCache::ServerPushInfo> push_resources;
+ QuicHttpResponseCache::ServerPushInfo push_info(
+ GURL(url), SpdyHeaderBlock(), kDefaultPriority, "Push body");
+ std::list<QuicHttpResponseCache::ServerPushInfo> push_resources;
push_resources.push_back(push_info);
- QuicInMemoryCache::GetInstance()->AddSimpleResponseWithServerPushResources(
+ response_cache_.AddSimpleResponseWithServerPushResources(
host, request_path, 200, body, push_resources);
SpdyHeaderBlock* request_headers = stream_->mutable_headers();
@@ -456,7 +452,7 @@ TEST_P(QuicSimpleServerStreamTest, SendReponseWithPushResources) {
EXPECT_CALL(session_,
PromisePushResourcesMock(host + request_path, _,
::net::test::kClientDataStreamId1, _));
- EXPECT_CALL(session_, WriteHeadersMock(stream_->id(), _, false, _, nullptr));
+ EXPECT_CALL(session_, WriteHeadersMock(stream_->id(), _, false, _, _));
EXPECT_CALL(session_, WritevData(_, _, _, _, _, _))
.Times(1)
.WillOnce(Return(QuicConsumedData(body.length(), true)));
@@ -480,8 +476,9 @@ TEST_P(QuicSimpleServerStreamTest, PushResponseOnServerInitiatedStream) {
const QuicStreamId kServerInitiatedStreamId = 2;
// Create a server initiated stream and pass it to session_.
QuicSimpleServerStreamPeer* server_initiated_stream =
- new QuicSimpleServerStreamPeer(kServerInitiatedStreamId, &session_);
- session_.ActivateStream(base::WrapUnique(server_initiated_stream));
+ new QuicSimpleServerStreamPeer(kServerInitiatedStreamId, &session_,
+ &response_cache_);
+ session_.ActivateStream(QuicWrapUnique(server_initiated_stream));
const string kHost = "www.foo.com";
const string kPath = "/bar";
@@ -495,24 +492,26 @@ TEST_P(QuicSimpleServerStreamTest, PushResponseOnServerInitiatedStream) {
response_headers_[":status"] = "200";
response_headers_["content-length"] = "5";
const string kBody = "Hello";
- QuicInMemoryCache::GetInstance()->AddResponse(
- kHost, kPath, std::move(response_headers_), kBody);
+ response_cache_.AddResponse(kHost, kPath, std::move(response_headers_),
+ kBody);
// Call PushResponse() should trigger stream to fetch response from cache
// and send it back.
EXPECT_CALL(session_,
WriteHeadersMock(kServerInitiatedStreamId, _, false,
- server_initiated_stream->priority(), nullptr));
+ server_initiated_stream->priority(), _));
EXPECT_CALL(session_, WritevData(_, kServerInitiatedStreamId, _, _, _, _))
.Times(1)
.WillOnce(Return(QuicConsumedData(kBody.size(), true)));
server_initiated_stream->PushResponse(std::move(headers));
- EXPECT_EQ(kPath, QuicSimpleServerStreamPeer::headers(
- server_initiated_stream)[":path"]
- .as_string());
- EXPECT_EQ("GET", QuicSimpleServerStreamPeer::headers(
- server_initiated_stream)[":method"]
- .as_string());
+ EXPECT_EQ(
+ kPath,
+ QuicSimpleServerStreamPeer::headers(server_initiated_stream)[":path"]
+ .as_string());
+ EXPECT_EQ(
+ "GET",
+ QuicSimpleServerStreamPeer::headers(server_initiated_stream)[":method"]
+ .as_string());
}
TEST_P(QuicSimpleServerStreamTest, TestSendErrorResponse) {
@@ -589,7 +588,7 @@ TEST_P(QuicSimpleServerStreamTest, ValidMultipleContentLength) {
TEST_P(QuicSimpleServerStreamTest, SendQuicRstStreamNoErrorWithEarlyResponse) {
InSequence s;
- EXPECT_CALL(session_, WriteHeadersMock(stream_->id(), _, false, _, nullptr));
+ EXPECT_CALL(session_, WriteHeadersMock(stream_->id(), _, false, _, _));
EXPECT_CALL(session_, WritevData(_, _, _, _, _, _))
.Times(1)
.WillOnce(Return(QuicConsumedData(3, true)));
diff --git a/chromium/net/tools/quic/quic_simple_server_test.cc b/chromium/net/tools/quic/quic_simple_server_test.cc
index 091c08761f5..87969d82f55 100644
--- a/chromium/net/tools/quic/quic_simple_server_test.cc
+++ b/chromium/net/tools/quic/quic_simple_server_test.cc
@@ -14,7 +14,6 @@
#include "testing/gtest/include/gtest/gtest.h"
using ::testing::_;
-using net::test::CryptoTestUtils;
namespace net {
namespace test {
@@ -35,14 +34,16 @@ class QuicChromeServerDispatchPacketTest : public ::testing::Test {
new net::test::MockQuicConnectionHelper),
std::unique_ptr<QuicCryptoServerStream::Helper>(
new QuicSimpleServerSessionHelper(QuicRandom::GetInstance())),
- std::unique_ptr<MockAlarmFactory>(
- new net::test::MockAlarmFactory)) {
+ std::unique_ptr<MockAlarmFactory>(new net::test::MockAlarmFactory),
+ &response_cache_) {
dispatcher_.InitializeWithWriter(nullptr);
}
void DispatchPacket(const QuicReceivedPacket& packet) {
IPEndPoint client_addr, server_addr;
- dispatcher_.ProcessPacket(server_addr, client_addr, packet);
+ dispatcher_.ProcessPacket(
+ QuicSocketAddress(QuicSocketAddressImpl(server_addr)),
+ QuicSocketAddress(QuicSocketAddressImpl(client_addr)), packet);
}
protected:
@@ -50,6 +51,7 @@ class QuicChromeServerDispatchPacketTest : public ::testing::Test {
QuicCryptoServerConfig crypto_config_;
QuicVersionManager version_manager_;
net::test::MockQuicDispatcher dispatcher_;
+ QuicHttpResponseCache response_cache_;
};
TEST_F(QuicChromeServerDispatchPacketTest, DispatchPacket) {
@@ -62,9 +64,9 @@ TEST_F(QuicChromeServerDispatchPacketTest, DispatchPacket) {
0xBC, 0x9A, 0x78, 0x56, 0x34, 0x12,
// private flags
0x00};
- QuicReceivedPacket encrypted_valid_packet(QuicUtils::AsChars(valid_packet),
- arraysize(valid_packet),
- QuicTime::Zero(), false);
+ QuicReceivedPacket encrypted_valid_packet(
+ reinterpret_cast<char*>(valid_packet), arraysize(valid_packet),
+ QuicTime::Zero(), false);
EXPECT_CALL(dispatcher_, ProcessPacket(_, _, _)).Times(1);
DispatchPacket(encrypted_valid_packet);
diff --git a/chromium/net/tools/quic/quic_spdy_client_stream.cc b/chromium/net/tools/quic/quic_spdy_client_stream.cc
index 2ac6fd243c6..554c173d0ac 100644
--- a/chromium/net/tools/quic/quic_spdy_client_stream.cc
+++ b/chromium/net/tools/quic/quic_spdy_client_stream.cc
@@ -6,18 +6,16 @@
#include <utility>
-#include "base/logging.h"
#include "base/stl_util.h"
-#include "base/strings/string_number_conversions.h"
#include "net/quic/core/quic_alarm.h"
#include "net/quic/core/quic_client_promised_info.h"
#include "net/quic/core/spdy_utils.h"
+#include "net/quic/platform/api/quic_logging.h"
#include "net/spdy/spdy_protocol.h"
#include "net/tools/quic/quic_client_session.h"
using base::StringPiece;
using std::string;
-using base::StringToInt;
namespace net {
@@ -28,14 +26,15 @@ QuicSpdyClientStream::QuicSpdyClientStream(QuicStreamId id,
response_code_(0),
header_bytes_read_(0),
header_bytes_written_(0),
- session_(session) {}
+ session_(session),
+ has_preliminary_headers_(false) {}
QuicSpdyClientStream::~QuicSpdyClientStream() {}
void QuicSpdyClientStream::OnStreamFrame(const QuicStreamFrame& frame) {
if (!allow_bidirectional_data() && !write_side_closed()) {
- DVLOG(1) << "Got a response before the request was complete. "
- << "Aborting request.";
+ QUIC_DLOG(INFO) << "Got a response before the request was complete. "
+ << "Aborting request.";
CloseWriteSide();
}
QuicSpdyStream::OnStreamFrame(frame);
@@ -51,20 +50,30 @@ void QuicSpdyClientStream::OnInitialHeadersComplete(
header_bytes_read_ += frame_len;
if (!SpdyUtils::CopyAndValidateHeaders(header_list, &content_length_,
&response_headers_)) {
- DLOG(ERROR) << "Failed to parse header list: " << header_list.DebugString();
+ QUIC_DLOG(ERROR) << "Failed to parse header list: "
+ << header_list.DebugString();
Reset(QUIC_BAD_APPLICATION_PAYLOAD);
return;
}
if (!ParseHeaderStatusCode(response_headers_, &response_code_)) {
- DLOG(ERROR) << "Received invalid response code: "
- << response_headers_[":status"].as_string();
+ QUIC_DLOG(ERROR) << "Received invalid response code: "
+ << response_headers_[":status"].as_string();
Reset(QUIC_BAD_APPLICATION_PAYLOAD);
return;
}
+ if (FLAGS_quic_restart_flag_quic_supports_100_continue &&
+ response_code_ == 100 && !has_preliminary_headers_) {
+ // These are preliminary 100 Continue headers, not the actual response
+ // headers.
+ set_headers_decompressed(false);
+ has_preliminary_headers_ = true;
+ preliminary_headers_ = std::move(response_headers_);
+ }
+
ConsumeHeaderList();
- DVLOG(1) << "headers complete for stream " << id();
+ QUIC_DVLOG(1) << "headers complete for stream " << id();
session_->OnInitialHeadersComplete(id(), response_headers_);
}
@@ -86,8 +95,8 @@ void QuicSpdyClientStream::OnPromiseHeaderList(
SpdyHeaderBlock promise_headers;
if (!SpdyUtils::CopyAndValidateHeaders(header_list, &content_length,
&promise_headers)) {
- DLOG(ERROR) << "Failed to parse promise headers: "
- << header_list.DebugString();
+ QUIC_DLOG(ERROR) << "Failed to parse promise headers: "
+ << header_list.DebugString();
Reset(QUIC_BAD_APPLICATION_PAYLOAD);
return;
}
@@ -110,14 +119,14 @@ void QuicSpdyClientStream::OnDataAvailable() {
// No more data to read.
break;
}
- DVLOG(1) << "Client processed " << iov.iov_len << " bytes for stream "
- << id();
+ QUIC_DVLOG(1) << "Client processed " << iov.iov_len << " bytes for stream "
+ << id();
data_.append(static_cast<char*>(iov.iov_base), iov.iov_len);
if (content_length_ >= 0 &&
data_.size() > static_cast<uint64_t>(content_length_)) {
- DLOG(ERROR) << "Invalid content length (" << content_length_
- << ") with data of size " << data_.size();
+ QUIC_DLOG(ERROR) << "Invalid content length (" << content_length_
+ << ") with data of size " << data_.size();
Reset(QUIC_BAD_APPLICATION_PAYLOAD);
return;
}
@@ -133,6 +142,8 @@ void QuicSpdyClientStream::OnDataAvailable() {
size_t QuicSpdyClientStream::SendRequest(SpdyHeaderBlock headers,
StringPiece body,
bool fin) {
+ QuicConnection::ScopedPacketBundler bundler(
+ session_->connection(), QuicConnection::SEND_ACK_IF_QUEUED);
bool send_fin_with_headers = fin && body.empty();
size_t bytes_sent = body.size();
header_bytes_written_ =
diff --git a/chromium/net/tools/quic/quic_spdy_client_stream.h b/chromium/net/tools/quic/quic_spdy_client_stream.h
index 179de25c9c2..cd3d6346734 100644
--- a/chromium/net/tools/quic/quic_spdy_client_stream.h
+++ b/chromium/net/tools/quic/quic_spdy_client_stream.h
@@ -11,7 +11,7 @@
#include "base/macros.h"
#include "base/strings/string_piece.h"
-#include "net/quic/core/quic_protocol.h"
+#include "net/quic/core/quic_packets.h"
#include "net/quic/core/quic_spdy_stream.h"
#include "net/spdy/spdy_framer.h"
@@ -27,8 +27,7 @@ class QuicSpdyClientStream : public QuicSpdyStream {
~QuicSpdyClientStream() override;
// Override the base class to close the write side as soon as we get a
- // response.
- // SPDY/HTTP does not support bidirectional streaming.
+ // response (if bidirectional streaming is not enabled).
void OnStreamFrame(const QuicStreamFrame& frame) override;
// Override the base class to parse and store headers.
@@ -59,6 +58,8 @@ class QuicSpdyClientStream : public QuicSpdyStream {
// Returns whatever headers have been received for this stream.
const SpdyHeaderBlock& response_headers() { return response_headers_; }
+ const SpdyHeaderBlock& preliminary_headers() { return preliminary_headers_; }
+
size_t header_bytes_read() const { return header_bytes_read_; }
size_t header_bytes_written() const { return header_bytes_written_; }
@@ -82,6 +83,12 @@ class QuicSpdyClientStream : public QuicSpdyStream {
QuicClientSession* session_;
+ // These preliminary headers are used for the 100 Continue headers
+ // that may arrive before the response headers when the request has
+ // Expect: 100-continue.
+ bool has_preliminary_headers_;
+ SpdyHeaderBlock preliminary_headers_;
+
DISALLOW_COPY_AND_ASSIGN(QuicSpdyClientStream);
};
diff --git a/chromium/net/tools/quic/quic_spdy_client_stream_test.cc b/chromium/net/tools/quic/quic_spdy_client_stream_test.cc
index 182415bd167..b7233dfff89 100644
--- a/chromium/net/tools/quic/quic_spdy_client_stream_test.cc
+++ b/chromium/net/tools/quic/quic_spdy_client_stream_test.cc
@@ -7,9 +7,11 @@
#include <memory>
#include "base/macros.h"
-#include "base/strings/string_number_conversions.h"
#include "net/quic/core/quic_utils.h"
#include "net/quic/core/spdy_utils.h"
+#include "net/quic/platform/api/quic_logging.h"
+#include "net/quic/platform/api/quic_socket_address.h"
+#include "net/quic/platform/api/quic_text_utils.h"
#include "net/quic/test_tools/crypto_test_utils.h"
#include "net/quic/test_tools/quic_test_utils.h"
#include "net/tools/quic/quic_client_session.h"
@@ -17,16 +19,6 @@
#include "testing/gtest/include/gtest/gtest.h"
using base::IntToString;
-using net::test::CryptoTestUtils;
-using net::test::DefaultQuicConfig;
-using net::test::MockQuicConnection;
-using net::test::MockQuicConnectionHelper;
-using net::test::SupportedVersions;
-using net::test::kClientDataStreamId1;
-using net::test::kServerDataStreamId1;
-using net::test::kInitialSessionFlowControlWindowForTest;
-using net::test::kInitialStreamFlowControlWindowForTest;
-
using std::string;
using testing::StrictMock;
using testing::TestWithParam;
@@ -79,7 +71,7 @@ class QuicSpdyClientStreamTest : public ::testing::Test {
class StreamVisitor : public QuicSpdyClientStream::Visitor {
void OnClose(QuicSpdyStream* stream) override {
- DVLOG(1) << "stream " << stream->id();
+ QUIC_DVLOG(1) << "stream " << stream->id();
}
};
@@ -117,6 +109,34 @@ TEST_F(QuicSpdyClientStreamTest, TestFraming) {
EXPECT_EQ(body_, stream_->data());
}
+TEST_F(QuicSpdyClientStreamTest, TestFraming100Continue) {
+ headers_[":status"] = "100";
+ FLAGS_quic_restart_flag_quic_supports_100_continue = true;
+ auto headers = AsHeaderList(headers_);
+ stream_->OnStreamHeaderList(false, headers.uncompressed_header_bytes(),
+ headers);
+ stream_->OnStreamFrame(
+ QuicStreamFrame(stream_->id(), /*fin=*/false, /*offset=*/0, body_));
+ EXPECT_EQ("100", stream_->preliminary_headers().find(":status")->second);
+ EXPECT_EQ(0u, stream_->response_headers().size());
+ EXPECT_EQ(100, stream_->response_code());
+ EXPECT_EQ("", stream_->data());
+}
+
+TEST_F(QuicSpdyClientStreamTest, TestFraming100ContinueNoFlag) {
+ headers_[":status"] = "100";
+ FLAGS_quic_restart_flag_quic_supports_100_continue = false;
+ auto headers = AsHeaderList(headers_);
+ stream_->OnStreamHeaderList(false, headers.uncompressed_header_bytes(),
+ headers);
+ stream_->OnStreamFrame(
+ QuicStreamFrame(stream_->id(), /*fin=*/false, /*offset=*/0, body_));
+ EXPECT_EQ(0u, stream_->preliminary_headers().size());
+ EXPECT_EQ("100", stream_->response_headers().find(":status")->second);
+ EXPECT_EQ(100, stream_->response_code());
+ EXPECT_EQ(body_, stream_->data());
+}
+
TEST_F(QuicSpdyClientStreamTest, TestFramingOnePacket) {
auto headers = AsHeaderList(headers_);
stream_->OnStreamHeaderList(false, headers.uncompressed_header_bytes(),
@@ -168,7 +188,8 @@ TEST_F(QuicSpdyClientStreamTest, ReceivingTrailers) {
// promised by the final offset field.
SpdyHeaderBlock trailer_block;
trailer_block["trailer key"] = "trailer value";
- trailer_block[kFinalOffsetHeaderKey] = IntToString(body_.size());
+ trailer_block[kFinalOffsetHeaderKey] =
+ QuicTextUtils::Uint64ToString(body_.size());
auto trailers = AsHeaderList(trailer_block);
stream_->OnStreamHeaderList(true, trailers.uncompressed_header_bytes(),
trailers);
diff --git a/chromium/net/tools/quic/quic_spdy_server_stream_base.cc b/chromium/net/tools/quic/quic_spdy_server_stream_base.cc
new file mode 100644
index 00000000000..e84516899b5
--- /dev/null
+++ b/chromium/net/tools/quic/quic_spdy_server_stream_base.cc
@@ -0,0 +1,30 @@
+// Copyright (c) 2016 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.
+
+#include "net/tools/quic/quic_spdy_server_stream_base.h"
+
+#include "net/quic/core/quic_error_codes.h"
+#include "net/quic/platform/api/quic_logging.h"
+
+namespace net {
+
+QuicSpdyServerStreamBase::QuicSpdyServerStreamBase(QuicStreamId id,
+ QuicSpdySession* session)
+ : QuicSpdyStream(id, session) {}
+
+void QuicSpdyServerStreamBase::CloseWriteSide() {
+ if (!fin_received() && !rst_received() && sequencer()->ignore_read_data() &&
+ !rst_sent()) {
+ // Early cancel the stream if it has stopped reading before receiving FIN
+ // or RST.
+ DCHECK(fin_sent());
+ // Tell the peer to stop sending further data.
+ QUIC_DVLOG(0) << " Server: Send QUIC_STREAM_NO_ERROR on stream " << id();
+ Reset(QUIC_STREAM_NO_ERROR);
+ }
+
+ QuicSpdyStream::CloseWriteSide();
+}
+
+} // namespace net
diff --git a/chromium/net/tools/quic/quic_spdy_server_stream_base.h b/chromium/net/tools/quic/quic_spdy_server_stream_base.h
new file mode 100644
index 00000000000..880642a7fea
--- /dev/null
+++ b/chromium/net/tools/quic/quic_spdy_server_stream_base.h
@@ -0,0 +1,26 @@
+// Copyright (c) 2016 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.
+
+#ifndef NET_TOOLS_QUIC_QUIC_SPDY_SERVER_STREAM_BASE_H_
+#define NET_TOOLS_QUIC_QUIC_SPDY_SERVER_STREAM_BASE_H_
+
+#include "net/quic/core/quic_spdy_stream.h"
+
+namespace net {
+
+class QuicSpdyServerStreamBase : public QuicSpdyStream {
+ public:
+ QuicSpdyServerStreamBase(QuicStreamId id, QuicSpdySession* session);
+
+ // Override the base class to send QUIC_STREAM_NO_ERROR to the peer
+ // when the stream has not received all the data.
+ void CloseWriteSide() override;
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(QuicSpdyServerStreamBase);
+};
+
+} // namespace net
+
+#endif // NET_TOOLS_QUIC_QUIC_SPDY_SERVER_STREAM_BASE_H_
diff --git a/chromium/net/tools/quic/quic_spdy_server_stream_base_test.cc b/chromium/net/tools/quic/quic_spdy_server_stream_base_test.cc
new file mode 100644
index 00000000000..95ffe487855
--- /dev/null
+++ b/chromium/net/tools/quic/quic_spdy_server_stream_base_test.cc
@@ -0,0 +1,65 @@
+// Copyright (c) 2016 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.
+
+#include "net/tools/quic/quic_spdy_server_stream_base.h"
+
+#include "net/quic/platform/api/quic_ptr_util.h"
+#include "net/quic/test_tools/quic_test_utils.h"
+#include "testing/gmock/include/gmock/gmock.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+using testing::_;
+
+namespace net {
+namespace test {
+namespace {
+
+class TestQuicSpdyServerStream : public QuicSpdyServerStreamBase {
+ public:
+ TestQuicSpdyServerStream(QuicStreamId id, QuicSpdySession* session)
+ : QuicSpdyServerStreamBase(id, session) {}
+
+ void OnDataAvailable() override {}
+};
+
+class QuicSpdyServerStreamBaseTest : public ::testing::Test {
+ protected:
+ QuicSpdyServerStreamBaseTest()
+ : session_(new MockQuicConnection(&helper_,
+ &alarm_factory_,
+ Perspective::IS_SERVER)) {
+ stream_ = new TestQuicSpdyServerStream(kClientDataStreamId1, &session_);
+ session_.ActivateStream(QuicWrapUnique(stream_));
+ }
+
+ QuicSpdyServerStreamBase* stream_ = nullptr;
+ MockQuicConnectionHelper helper_;
+ MockAlarmFactory alarm_factory_;
+ MockQuicSpdySession session_;
+};
+
+TEST_F(QuicSpdyServerStreamBaseTest,
+ SendQuicRstStreamNoErrorWithEarlyResponse) {
+ stream_->StopReading();
+ EXPECT_CALL(session_, SendRstStream(_, QUIC_STREAM_NO_ERROR, _)).Times(1);
+ stream_->set_fin_sent(true);
+ stream_->CloseWriteSide();
+}
+
+TEST_F(QuicSpdyServerStreamBaseTest,
+ DoNotSendQuicRstStreamNoErrorWithRstReceived) {
+ EXPECT_FALSE(stream_->reading_stopped());
+
+ EXPECT_CALL(session_, SendRstStream(_, QUIC_STREAM_NO_ERROR, _)).Times(0);
+ EXPECT_CALL(session_, SendRstStream(_, QUIC_RST_ACKNOWLEDGEMENT, _)).Times(1);
+ QuicRstStreamFrame rst_frame(stream_->id(), QUIC_STREAM_CANCELLED, 1234);
+ stream_->OnStreamReset(rst_frame);
+
+ EXPECT_TRUE(stream_->reading_stopped());
+ EXPECT_TRUE(stream_->write_side_closed());
+}
+
+} // namespace
+} // namespace test
+} // namespace net
diff --git a/chromium/net/tools/quic/quic_time_wait_list_manager.cc b/chromium/net/tools/quic/quic_time_wait_list_manager.cc
index 7b9c7863122..85918971ab9 100644
--- a/chromium/net/tools/quic/quic_time_wait_list_manager.cc
+++ b/chromium/net/tools/quic/quic_time_wait_list_manager.cc
@@ -8,19 +8,20 @@
#include <memory>
-#include "base/logging.h"
#include "base/macros.h"
-#include "base/memory/ptr_util.h"
-#include "net/base/ip_endpoint.h"
+#include "base/stl_util.h"
#include "net/quic/core/crypto/crypto_protocol.h"
#include "net/quic/core/crypto/quic_decrypter.h"
#include "net/quic/core/crypto/quic_encrypter.h"
-#include "net/quic/core/quic_clock.h"
#include "net/quic/core/quic_flags.h"
#include "net/quic/core/quic_framer.h"
-#include "net/quic/core/quic_protocol.h"
+#include "net/quic/core/quic_packets.h"
#include "net/quic/core/quic_server_session_base.h"
#include "net/quic/core/quic_utils.h"
+#include "net/quic/platform/api/quic_clock.h"
+#include "net/quic/platform/api/quic_logging.h"
+#include "net/quic/platform/api/quic_ptr_util.h"
+#include "net/quic/platform/api/quic_socket_address.h"
using base::StringPiece;
@@ -55,20 +56,20 @@ class ConnectionIdCleanUpAlarm : public QuicAlarm::Delegate {
// created instance takes the ownership of this packet.
class QuicTimeWaitListManager::QueuedPacket {
public:
- QueuedPacket(const IPEndPoint& server_address,
- const IPEndPoint& client_address,
+ QueuedPacket(const QuicSocketAddress& server_address,
+ const QuicSocketAddress& client_address,
std::unique_ptr<QuicEncryptedPacket> packet)
: server_address_(server_address),
client_address_(client_address),
packet_(std::move(packet)) {}
- const IPEndPoint& server_address() const { return server_address_; }
- const IPEndPoint& client_address() const { return client_address_; }
+ const QuicSocketAddress& server_address() const { return server_address_; }
+ const QuicSocketAddress& client_address() const { return client_address_; }
QuicEncryptedPacket* packet() { return packet_.get(); }
private:
- const IPEndPoint server_address_;
- const IPEndPoint client_address_;
+ const QuicSocketAddress server_address_;
+ const QuicSocketAddress client_address_;
std::unique_ptr<QuicEncryptedPacket> packet_;
DISALLOW_COPY_AND_ASSIGN(QueuedPacket);
@@ -147,13 +148,13 @@ void QuicTimeWaitListManager::OnCanWrite() {
}
void QuicTimeWaitListManager::ProcessPacket(
- const IPEndPoint& server_address,
- const IPEndPoint& client_address,
+ const QuicSocketAddress& server_address,
+ const QuicSocketAddress& client_address,
QuicConnectionId connection_id,
QuicPacketNumber packet_number,
const QuicEncryptedPacket& /*packet*/) {
DCHECK(IsConnectionIdInTimeWait(connection_id));
- DVLOG(1) << "Processing " << connection_id << " in time wait state.";
+ QUIC_DLOG(INFO) << "Processing " << connection_id << " in time wait state.";
// TODO(satyamshekhar): Think about handling packets from different client
// addresses.
ConnectionIdMap::iterator it = connection_id_map_.find(connection_id);
@@ -168,11 +169,12 @@ void QuicTimeWaitListManager::ProcessPacket(
if (!connection_data->termination_packets.empty()) {
if (connection_data->connection_rejected_statelessly) {
- DVLOG(3) << "Time wait list sending previous stateless reject response "
- << "for connection " << connection_id;
+ QUIC_DVLOG(3)
+ << "Time wait list sending previous stateless reject response "
+ << "for connection " << connection_id;
}
for (const auto& packet : connection_data->termination_packets) {
- SendOrQueuePacket(base::MakeUnique<QueuedPacket>(
+ SendOrQueuePacket(QuicMakeUnique<QueuedPacket>(
server_address, client_address, packet->Clone()));
}
return;
@@ -184,9 +186,9 @@ void QuicTimeWaitListManager::ProcessPacket(
void QuicTimeWaitListManager::SendVersionNegotiationPacket(
QuicConnectionId connection_id,
const QuicVersionVector& supported_versions,
- const IPEndPoint& server_address,
- const IPEndPoint& client_address) {
- SendOrQueuePacket(base::MakeUnique<QueuedPacket>(
+ const QuicSocketAddress& server_address,
+ const QuicSocketAddress& client_address) {
+ SendOrQueuePacket(QuicMakeUnique<QueuedPacket>(
server_address, client_address, QuicFramer::BuildVersionNegotiationPacket(
connection_id, supported_versions)));
}
@@ -199,8 +201,8 @@ bool QuicTimeWaitListManager::ShouldSendResponse(int received_packet_count) {
}
void QuicTimeWaitListManager::SendPublicReset(
- const IPEndPoint& server_address,
- const IPEndPoint& client_address,
+ const QuicSocketAddress& server_address,
+ const QuicSocketAddress& client_address,
QuicConnectionId connection_id,
QuicPacketNumber rejected_packet_number) {
QuicPublicResetPacket packet;
@@ -212,8 +214,8 @@ void QuicTimeWaitListManager::SendPublicReset(
packet.nonce_proof = 1010101;
packet.client_address = client_address;
// Takes ownership of the packet.
- SendOrQueuePacket(base::MakeUnique<QueuedPacket>(
- server_address, client_address, BuildPublicReset(packet)));
+ SendOrQueuePacket(QuicMakeUnique<QueuedPacket>(server_address, client_address,
+ BuildPublicReset(packet)));
}
std::unique_ptr<QuicEncryptedPacket> QuicTimeWaitListManager::BuildPublicReset(
@@ -239,17 +241,18 @@ bool QuicTimeWaitListManager::WriteToWire(QueuedPacket* queued_packet) {
}
WriteResult result = writer_->WritePacket(
queued_packet->packet()->data(), queued_packet->packet()->length(),
- queued_packet->server_address().address(),
- queued_packet->client_address(), nullptr);
+ queued_packet->server_address().host(), queued_packet->client_address(),
+ nullptr);
if (result.status == WRITE_STATUS_BLOCKED) {
// If blocked and unbuffered, return false to retry sending.
DCHECK(writer_->IsWriteBlocked());
visitor_->OnWriteBlocked(this);
return writer_->IsWriteBlockedDataBuffered();
} else if (result.status == WRITE_STATUS_ERROR) {
- LOG(WARNING) << "Received unknown error while sending reset packet to "
- << queued_packet->client_address().ToString() << ": "
- << strerror(result.error_code);
+ QUIC_LOG_FIRST_N(WARNING, 1)
+ << "Received unknown error while sending reset packet to "
+ << queued_packet->client_address().ToString() << ": "
+ << strerror(result.error_code);
}
return true;
}
@@ -263,7 +266,8 @@ void QuicTimeWaitListManager::SetConnectionIdCleanUpAlarm() {
if (now - oldest_connection_id < time_wait_period_) {
next_alarm_interval = oldest_connection_id + time_wait_period_ - now;
} else {
- LOG(ERROR) << "ConnectionId lingered for longer than time_wait_period_";
+ QUIC_LOG(ERROR)
+ << "ConnectionId lingered for longer than time_wait_period_";
}
} else {
// No connection_ids added so none will expire before time_wait_period_.
diff --git a/chromium/net/tools/quic/quic_time_wait_list_manager.h b/chromium/net/tools/quic/quic_time_wait_list_manager.h
index e036564bfab..3c4dc0223a0 100644
--- a/chromium/net/tools/quic/quic_time_wait_list_manager.h
+++ b/chromium/net/tools/quic/quic_time_wait_list_manager.h
@@ -20,7 +20,7 @@
#include "net/quic/core/quic_connection.h"
#include "net/quic/core/quic_framer.h"
#include "net/quic/core/quic_packet_writer.h"
-#include "net/quic/core/quic_protocol.h"
+#include "net/quic/core/quic_packets.h"
#include "net/quic/core/quic_session.h"
namespace net {
@@ -82,8 +82,8 @@ class QuicTimeWaitListManager : public QuicBlockedWriterInterface {
// connection_id. Sending of the public reset packet is throttled by using
// exponential back off. DCHECKs for the connection_id to be in time wait
// state. virtual to override in tests.
- virtual void ProcessPacket(const IPEndPoint& server_address,
- const IPEndPoint& client_address,
+ virtual void ProcessPacket(const QuicSocketAddress& server_address,
+ const QuicSocketAddress& client_address,
QuicConnectionId connection_id,
QuicPacketNumber packet_number,
const QuicEncryptedPacket& packet);
@@ -113,13 +113,19 @@ class QuicTimeWaitListManager : public QuicBlockedWriterInterface {
virtual void SendVersionNegotiationPacket(
QuicConnectionId connection_id,
const QuicVersionVector& supported_versions,
- const IPEndPoint& server_address,
- const IPEndPoint& client_address);
+ const QuicSocketAddress& server_address,
+ const QuicSocketAddress& client_address);
protected:
virtual std::unique_ptr<QuicEncryptedPacket> BuildPublicReset(
const QuicPublicResetPacket& packet);
+ // Creates a public reset packet and sends it or queues it to be sent later.
+ virtual void SendPublicReset(const QuicSocketAddress& server_address,
+ const QuicSocketAddress& client_address,
+ QuicConnectionId connection_id,
+ QuicPacketNumber rejected_packet_number);
+
private:
friend class test::QuicDispatcherPeer;
friend class test::QuicTimeWaitListManagerPeer;
@@ -131,12 +137,6 @@ class QuicTimeWaitListManager : public QuicBlockedWriterInterface {
// number of received packets.
bool ShouldSendResponse(int received_packet_count);
- // Creates a public reset packet and sends it or queues it to be sent later.
- void SendPublicReset(const IPEndPoint& server_address,
- const IPEndPoint& client_address,
- QuicConnectionId connection_id,
- QuicPacketNumber rejected_packet_number);
-
// Either sends the packet and deletes it or makes pending_packets_queue_ the
// owner of the packet.
void SendOrQueuePacket(std::unique_ptr<QueuedPacket> packet);
diff --git a/chromium/net/tools/quic/quic_time_wait_list_manager_test.cc b/chromium/net/tools/quic/quic_time_wait_list_manager_test.cc
index d5016345d77..a409ead8ca5 100644
--- a/chromium/net/tools/quic/quic_time_wait_list_manager_test.cc
+++ b/chromium/net/tools/quic/quic_time_wait_list_manager_test.cc
@@ -6,6 +6,7 @@
#include <errno.h>
#include <memory>
+#include <ostream>
#include "net/quic/core/crypto/crypto_protocol.h"
#include "net/quic/core/crypto/null_encrypter.h"
@@ -15,7 +16,7 @@
#include "net/quic/core/quic_flags.h"
#include "net/quic/core/quic_framer.h"
#include "net/quic/core/quic_packet_writer.h"
-#include "net/quic/core/quic_protocol.h"
+#include "net/quic/core/quic_packets.h"
#include "net/quic/core/quic_utils.h"
#include "net/quic/test_tools/quic_test_utils.h"
#include "net/quic/test_tools/quic_time_wait_list_manager_peer.h"
@@ -26,13 +27,6 @@
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
-using net::test::kTestPort;
-using net::test::BuildUnsizedDataPacket;
-using net::test::NoOpFramerVisitor;
-using net::test::QuicVersionMax;
-using net::test::QuicVersionMin;
-using net::test::MockPacketWriter;
-
using testing::Args;
using testing::Assign;
using testing::DoAll;
@@ -143,8 +137,8 @@ class QuicTimeWaitListManagerTest : public ::testing::Test {
StrictMock<MockQuicSessionVisitor> visitor_;
QuicTimeWaitListManager time_wait_list_manager_;
QuicConnectionId connection_id_;
- IPEndPoint server_address_;
- IPEndPoint client_address_;
+ QuicSocketAddress server_address_;
+ QuicSocketAddress client_address_;
bool writer_is_blocked_;
};
@@ -170,7 +164,7 @@ class ValidatePublicResetPacketPredicate
packet.public_header.reset_flag &&
!packet.public_header.version_flag &&
packet_number_ == packet.rejected_packet_number &&
- net::test::TestPeerIPAddress() == packet.client_address.address() &&
+ net::test::TestPeerIPAddress() == packet.client_address.host() &&
kTestPort == packet.client_address.port();
}
@@ -210,9 +204,8 @@ TEST_F(QuicTimeWaitListManagerTest, SendVersionNegotiationPacket) {
std::unique_ptr<QuicEncryptedPacket> packet(
QuicFramer::BuildVersionNegotiationPacket(connection_id_,
AllSupportedVersions()));
- EXPECT_CALL(writer_,
- WritePacket(_, packet->length(), server_address_.address(),
- client_address_, _))
+ EXPECT_CALL(writer_, WritePacket(_, packet->length(), server_address_.host(),
+ client_address_, _))
.WillOnce(Return(WriteResult(WRITE_STATUS_OK, 1)));
time_wait_list_manager_.SendVersionNegotiationPacket(
@@ -231,9 +224,8 @@ TEST_F(QuicTimeWaitListManagerTest, SendConnectionClose) {
/*connection_rejected_statelessly=*/false,
&termination_packets);
const int kRandomSequenceNumber = 1;
- EXPECT_CALL(writer_,
- WritePacket(_, kConnectionCloseLength, server_address_.address(),
- client_address_, _))
+ EXPECT_CALL(writer_, WritePacket(_, kConnectionCloseLength,
+ server_address_.host(), client_address_, _))
.WillOnce(Return(WriteResult(WRITE_STATUS_OK, 1)));
ProcessPacket(connection_id_, kRandomSequenceNumber);
@@ -253,9 +245,8 @@ TEST_F(QuicTimeWaitListManagerTest, SendTwoConnectionCloses) {
/*connection_rejected_statelessly=*/false,
&termination_packets);
const int kRandomSequenceNumber = 1;
- EXPECT_CALL(writer_,
- WritePacket(_, kConnectionCloseLength, server_address_.address(),
- client_address_, _))
+ EXPECT_CALL(writer_, WritePacket(_, kConnectionCloseLength,
+ server_address_.host(), client_address_, _))
.Times(2)
.WillRepeatedly(Return(WriteResult(WRITE_STATUS_OK, 1)));
@@ -267,7 +258,7 @@ TEST_F(QuicTimeWaitListManagerTest, SendPublicReset) {
AddConnectionId(connection_id_);
const int kRandomSequenceNumber = 1;
EXPECT_CALL(writer_,
- WritePacket(_, _, server_address_.address(), client_address_, _))
+ WritePacket(_, _, server_address_.host(), client_address_, _))
.With(Args<0, 1>(PublicResetPacketEq(connection_id_, 0)))
.WillOnce(Return(WriteResult(WRITE_STATUS_OK, 0)));
@@ -301,7 +292,7 @@ TEST_F(QuicTimeWaitListManagerTest, NoPublicResetForStatelessConnections) {
const int kRandomSequenceNumber = 1;
EXPECT_CALL(writer_,
- WritePacket(_, _, server_address_.address(), client_address_, _))
+ WritePacket(_, _, server_address_.host(), client_address_, _))
.WillOnce(Return(WriteResult(WRITE_STATUS_OK, 1)));
ProcessPacket(connection_id_, kRandomSequenceNumber);
@@ -362,14 +353,14 @@ TEST_F(QuicTimeWaitListManagerTest, SendQueuedPackets) {
ConstructEncryptedPacket(connection_id, packet_number));
// Let first write through.
EXPECT_CALL(writer_,
- WritePacket(_, _, server_address_.address(), client_address_, _))
+ WritePacket(_, _, server_address_.host(), client_address_, _))
.With(Args<0, 1>(PublicResetPacketEq(connection_id, 0)))
.WillOnce(Return(WriteResult(WRITE_STATUS_OK, packet->length())));
ProcessPacket(connection_id, packet_number);
// write block for the next packet.
EXPECT_CALL(writer_,
- WritePacket(_, _, server_address_.address(), client_address_, _))
+ WritePacket(_, _, server_address_.host(), client_address_, _))
.With(Args<0, 1>(PublicResetPacketEq(connection_id, 0)))
.WillOnce(DoAll(Assign(&writer_is_blocked_, true),
Return(WriteResult(WRITE_STATUS_BLOCKED, EAGAIN))));
@@ -394,11 +385,11 @@ TEST_F(QuicTimeWaitListManagerTest, SendQueuedPackets) {
// Now expect all the write blocked public reset packets to be sent again.
writer_is_blocked_ = false;
EXPECT_CALL(writer_,
- WritePacket(_, _, server_address_.address(), client_address_, _))
+ WritePacket(_, _, server_address_.host(), client_address_, _))
.With(Args<0, 1>(PublicResetPacketEq(connection_id, 0)))
.WillOnce(Return(WriteResult(WRITE_STATUS_OK, packet->length())));
EXPECT_CALL(writer_,
- WritePacket(_, _, server_address_.address(), client_address_, _))
+ WritePacket(_, _, server_address_.host(), client_address_, _))
.With(Args<0, 1>(PublicResetPacketEq(other_connection_id, 0)))
.WillOnce(Return(WriteResult(WRITE_STATUS_OK, other_packet->length())));
time_wait_list_manager_.OnCanWrite();
@@ -447,9 +438,8 @@ TEST_F(QuicTimeWaitListManagerTest, AddConnectionIdTwice) {
EXPECT_TRUE(IsConnectionIdInTimeWait(connection_id_));
EXPECT_EQ(1u, time_wait_list_manager_.num_connections());
- EXPECT_CALL(writer_,
- WritePacket(_, kConnectionCloseLength, server_address_.address(),
- client_address_, _))
+ EXPECT_CALL(writer_, WritePacket(_, kConnectionCloseLength,
+ server_address_.host(), client_address_, _))
.WillOnce(Return(WriteResult(WRITE_STATUS_OK, 1)));
const int kRandomSequenceNumber = 1;
diff --git a/chromium/net/tools/quic/stateless_rejector.cc b/chromium/net/tools/quic/stateless_rejector.cc
index ff3b29e2d06..8c6cb980c34 100644
--- a/chromium/net/tools/quic/stateless_rejector.cc
+++ b/chromium/net/tools/quic/stateless_rejector.cc
@@ -4,9 +4,9 @@
#include "net/tools/quic/stateless_rejector.h"
-#include "net/quic/core/quic_bug_tracker.h"
#include "net/quic/core/quic_crypto_server_stream.h"
#include "net/quic/core/quic_flags.h"
+#include "net/quic/platform/api/quic_bug_tracker.h"
namespace net {
@@ -20,7 +20,7 @@ class StatelessRejector::ValidateCallback
~ValidateCallback() override {}
- void Run(scoped_refptr<Result> result,
+ void Run(QuicReferenceCountedPointer<Result> result,
std::unique_ptr<ProofSource::Details> /* proof_source_details */)
override {
StatelessRejector* rejector_ptr = rejector_.get();
@@ -41,8 +41,8 @@ StatelessRejector::StatelessRejector(
const QuicClock* clock,
QuicRandom* random,
QuicByteCount chlo_packet_size,
- const IPEndPoint& client_address,
- const IPEndPoint& server_address)
+ const QuicSocketAddress& client_address,
+ const QuicSocketAddress& server_address)
: state_(UNKNOWN),
error_(QUIC_INTERNAL_ERROR),
version_(version),
@@ -55,7 +55,7 @@ StatelessRejector::StatelessRejector(
random_(random),
crypto_config_(crypto_config),
compressed_certs_cache_(compressed_certs_cache),
- proof_(new QuicCryptoProof),
+ signed_config_(new QuicSignedServerConfig),
params_(new QuicCryptoNegotiatedParameters) {}
StatelessRejector::~StatelessRejector() {}
@@ -68,10 +68,9 @@ void StatelessRejector::OnChlo(QuicVersion version,
DCHECK_NE(connection_id, server_designated_connection_id);
DCHECK_EQ(state_, UNKNOWN);
- if (!FLAGS_enable_quic_stateless_reject_support ||
- !FLAGS_quic_use_cheap_stateless_rejects ||
- !QuicCryptoServerStream::DoesPeerSupportStatelessRejects(message) ||
- version <= QUIC_VERSION_32) {
+ if (!FLAGS_quic_reloadable_flag_enable_quic_stateless_reject_support ||
+ !FLAGS_quic_reloadable_flag_quic_use_cheap_stateless_rejects ||
+ !QuicCryptoServerStream::DoesPeerSupportStatelessRejects(message)) {
state_ = UNSUPPORTED;
return;
}
@@ -88,9 +87,9 @@ void StatelessRejector::Process(std::unique_ptr<StatelessRejector> rejector,
"has already made a decision";
StatelessRejector* rejector_ptr = rejector.get();
rejector_ptr->crypto_config_->ValidateClientHello(
- rejector_ptr->chlo_, rejector_ptr->client_address_.address(),
- rejector_ptr->server_address_.address(), rejector_ptr->version_,
- rejector_ptr->clock_, rejector_ptr->proof_,
+ rejector_ptr->chlo_, rejector_ptr->client_address_.host(),
+ rejector_ptr->server_address_, rejector_ptr->version_,
+ rejector_ptr->clock_, rejector_ptr->signed_config_,
std::unique_ptr<ValidateCallback>(
new ValidateCallback(std::move(rejector), std::move(done_cb))));
}
@@ -121,17 +120,18 @@ class StatelessRejector::ProcessClientHelloCallback
};
void StatelessRejector::ProcessClientHello(
- scoped_refptr<ValidateClientHelloResultCallback::Result> result,
+ QuicReferenceCountedPointer<ValidateClientHelloResultCallback::Result>
+ result,
std::unique_ptr<StatelessRejector> rejector,
std::unique_ptr<StatelessRejector::ProcessDoneCallback> done_cb) {
std::unique_ptr<ProcessClientHelloCallback> cb(
new ProcessClientHelloCallback(std::move(rejector), std::move(done_cb)));
crypto_config_->ProcessClientHello(
result,
- /*reject_only=*/true, connection_id_, server_address_.address(),
- client_address_, version_, versions_,
+ /*reject_only=*/true, connection_id_, server_address_, client_address_,
+ version_, versions_,
/*use_stateless_rejects=*/true, server_designated_connection_id_, clock_,
- random_, compressed_certs_cache_, params_, proof_,
+ random_, compressed_certs_cache_, params_, signed_config_,
QuicCryptoStream::CryptoMessageFramingOverhead(version_),
chlo_packet_size_, std::move(cb));
}
diff --git a/chromium/net/tools/quic/stateless_rejector.h b/chromium/net/tools/quic/stateless_rejector.h
index dc4f6ef5265..f1771629d04 100644
--- a/chromium/net/tools/quic/stateless_rejector.h
+++ b/chromium/net/tools/quic/stateless_rejector.h
@@ -2,13 +2,13 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#ifndef NET_QUIC_STATELESS_REJECTOR_H_
-#define NET_QUIC_STATELESS_REJECTOR_H_
+#ifndef NET_TOOLS_QUIC_STATELESS_REJECTOR_H_
+#define NET_TOOLS_QUIC_STATELESS_REJECTOR_H_
#include "base/strings/string_piece.h"
#include "net/quic/core/crypto/crypto_framer.h"
#include "net/quic/core/crypto/quic_crypto_server_config.h"
-#include "net/quic/core/quic_protocol.h"
+#include "net/quic/core/quic_packets.h"
namespace net {
@@ -31,8 +31,8 @@ class StatelessRejector {
const QuicClock* clock,
QuicRandom* random,
QuicByteCount chlo_packet_size,
- const IPEndPoint& client_address,
- const IPEndPoint& server_address);
+ const QuicSocketAddress& client_address,
+ const QuicSocketAddress& server_address);
~StatelessRejector();
@@ -79,7 +79,8 @@ class StatelessRejector {
friend class ProcessClientHelloCallback;
void ProcessClientHello(
- scoped_refptr<ValidateClientHelloResultCallback::Result> result,
+ QuicReferenceCountedPointer<ValidateClientHelloResultCallback::Result>
+ result,
std::unique_ptr<StatelessRejector> rejector,
std::unique_ptr<StatelessRejector::ProcessDoneCallback> done_cb);
@@ -98,8 +99,8 @@ class StatelessRejector {
QuicConnectionId connection_id_;
QuicConnectionId server_designated_connection_id_;
QuicByteCount chlo_packet_size_;
- IPEndPoint client_address_;
- IPEndPoint server_address_;
+ QuicSocketAddress client_address_;
+ QuicSocketAddress server_address_;
const QuicClock* clock_;
QuicRandom* random_;
const QuicCryptoServerConfig* crypto_config_;
@@ -107,12 +108,12 @@ class StatelessRejector {
CryptoHandshakeMessage chlo_;
std::unique_ptr<CryptoHandshakeMessage> reply_;
CryptoFramer crypto_framer_;
- scoped_refptr<QuicCryptoProof> proof_;
- scoped_refptr<QuicCryptoNegotiatedParameters> params_;
+ QuicReferenceCountedPointer<QuicSignedServerConfig> signed_config_;
+ QuicReferenceCountedPointer<QuicCryptoNegotiatedParameters> params_;
DISALLOW_COPY_AND_ASSIGN(StatelessRejector);
};
} // namespace net
-#endif // NET_QUIC_STATELESS_REJECTOR_H_
+#endif // NET_TOOLS_QUIC_STATELESS_REJECTOR_H_
diff --git a/chromium/net/tools/quic/stateless_rejector_test.cc b/chromium/net/tools/quic/stateless_rejector_test.cc
index a6a688c0b94..23b6e3a53be 100644
--- a/chromium/net/tools/quic/stateless_rejector_test.cc
+++ b/chromium/net/tools/quic/stateless_rejector_test.cc
@@ -7,16 +7,17 @@
#include <memory>
#include <vector>
-#include "base/memory/ptr_util.h"
-#include "base/strings/stringprintf.h"
#include "net/quic/core/crypto/crypto_handshake_message.h"
#include "net/quic/core/crypto/proof_source.h"
#include "net/quic/core/quic_utils.h"
+#include "net/quic/platform/api/quic_logging.h"
+#include "net/quic/platform/api/quic_ptr_util.h"
+#include "net/quic/platform/api/quic_str_cat.h"
+#include "net/quic/platform/api/quic_text_utils.h"
#include "net/quic/test_tools/crypto_test_utils.h"
#include "net/quic/test_tools/quic_crypto_server_config_peer.h"
#include "net/quic/test_tools/quic_test_utils.h"
-using std::ostream;
using std::string;
namespace net {
@@ -40,7 +41,7 @@ const char* FlagsModeToString(FlagsMode mode) {
case BOTH_DISABLED:
return "BOTH_DISABLED";
default:
- DLOG(FATAL) << "Unexpected FlagsMode";
+ QUIC_DLOG(FATAL) << "Unexpected FlagsMode";
return nullptr;
}
}
@@ -52,8 +53,8 @@ struct TestParams {
};
string TestParamToString(const testing::TestParamInfo<TestParams>& params) {
- return base::StringPrintf("v%i_%s", params.param.version,
- FlagsModeToString(params.param.flags));
+ return QuicStrCat("v", params.param.version, "_",
+ FlagsModeToString(params.param.flags));
}
std::vector<TestParams> GetTestParams() {
@@ -80,7 +81,7 @@ class StatelessRejectorTest : public ::testing::TestWithParam<TestParams> {
config_peer_(&config_),
compressed_certs_cache_(
QuicCompressedCertsCache::kQuicCompressedCertsCacheSize),
- rejector_(base::MakeUnique<StatelessRejector>(
+ rejector_(QuicMakeUnique<StatelessRejector>(
GetParam().version,
AllSupportedVersions(),
&config_,
@@ -88,11 +89,11 @@ class StatelessRejectorTest : public ::testing::TestWithParam<TestParams> {
&clock_,
QuicRandom::GetInstance(),
kDefaultMaxPacketSize,
- IPEndPoint(net::test::Loopback4(), 12345),
- IPEndPoint(net::test::Loopback4(), 443))) {
- FLAGS_enable_quic_stateless_reject_support =
+ QuicSocketAddress(QuicIpAddress::Loopback4(), 12345),
+ QuicSocketAddress(QuicIpAddress::Loopback4(), 443))) {
+ FLAGS_quic_reloadable_flag_enable_quic_stateless_reject_support =
GetParam().flags == ENABLED || GetParam().flags == CHEAP_DISABLED;
- FLAGS_quic_use_cheap_stateless_rejects =
+ FLAGS_quic_reloadable_flag_quic_use_cheap_stateless_rejects =
GetParam().flags == ENABLED || GetParam().flags == STATELESS_DISABLED;
// Add a new primary config.
@@ -100,15 +101,17 @@ class StatelessRejectorTest : public ::testing::TestWithParam<TestParams> {
QuicRandom::GetInstance(), &clock_, config_options_));
// Save the server config.
- scid_hex_ = "#" + QuicUtils::HexEncode(config_peer_.GetPrimaryConfig()->id);
+ scid_hex_ =
+ "#" + QuicTextUtils::HexEncode(config_peer_.GetPrimaryConfig()->id);
// Encode the QUIC version.
- ver_hex_ = QuicUtils::TagToString(QuicVersionToQuicTag(GetParam().version));
+ ver_hex_ = QuicTagToString(QuicVersionToQuicTag(GetParam().version));
// Generate a public value.
char public_value[32];
memset(public_value, 42, sizeof(public_value));
- pubs_hex_ = "#" + QuicUtils::HexEncode(public_value, sizeof(public_value));
+ pubs_hex_ =
+ "#" + QuicTextUtils::HexEncode(public_value, sizeof(public_value));
// Generate a client nonce.
string nonce;
@@ -118,16 +121,16 @@ class StatelessRejectorTest : public ::testing::TestWithParam<TestParams> {
reinterpret_cast<char*>(config_peer_.GetPrimaryConfig()->orbit),
kOrbitSize),
&nonce);
- nonc_hex_ = "#" + QuicUtils::HexEncode(nonce);
+ nonc_hex_ = "#" + QuicTextUtils::HexEncode(nonce);
// Generate a source address token.
SourceAddressTokens previous_tokens;
- IPAddress ip = net::test::Loopback4();
+ QuicIpAddress ip = QuicIpAddress::Loopback4();
MockRandom rand;
string stk = config_peer_.NewSourceAddressToken(
config_peer_.GetPrimaryConfig()->id, previous_tokens, ip, &rand,
clock_.WallNow(), nullptr);
- stk_hex_ = "#" + QuicUtils::HexEncode(stk);
+ stk_hex_ = "#" + QuicTextUtils::HexEncode(stk);
}
protected:
@@ -176,7 +179,7 @@ TEST_P(StatelessRejectorTest, InvalidChlo) {
rejector_->OnChlo(GetParam().version, kConnectionId,
kServerDesignateConnectionId, client_hello);
- if (GetParam().flags != ENABLED || GetParam().version <= QUIC_VERSION_32) {
+ if (GetParam().flags != ENABLED) {
EXPECT_EQ(StatelessRejector::UNSUPPORTED, rejector_->state());
return;
}
@@ -184,7 +187,7 @@ TEST_P(StatelessRejectorTest, InvalidChlo) {
// The StatelessRejector is undecided - proceed with async processing
ASSERT_EQ(StatelessRejector::UNKNOWN, rejector_->state());
StatelessRejector::Process(std::move(rejector_),
- base::MakeUnique<ProcessDoneCallback>(this));
+ QuicMakeUnique<ProcessDoneCallback>(this));
EXPECT_EQ(StatelessRejector::FAILED, rejector_->state());
EXPECT_EQ(QUIC_INVALID_CRYPTO_MESSAGE_PARAMETER, rejector_->error());
@@ -228,7 +231,7 @@ TEST_P(StatelessRejectorTest, RejectChlo) {
rejector_->OnChlo(GetParam().version, kConnectionId,
kServerDesignateConnectionId, client_hello);
- if (GetParam().flags != ENABLED || GetParam().version <= QUIC_VERSION_32) {
+ if (GetParam().flags != ENABLED) {
EXPECT_EQ(StatelessRejector::UNSUPPORTED, rejector_->state());
return;
}
@@ -236,7 +239,7 @@ TEST_P(StatelessRejectorTest, RejectChlo) {
// The StatelessRejector is undecided - proceed with async processing
ASSERT_EQ(StatelessRejector::UNKNOWN, rejector_->state());
StatelessRejector::Process(std::move(rejector_),
- base::MakeUnique<ProcessDoneCallback>(this));
+ QuicMakeUnique<ProcessDoneCallback>(this));
ASSERT_EQ(StatelessRejector::REJECTED, rejector_->state());
const CryptoHandshakeMessage& reply = rejector_->reply();
@@ -253,8 +256,8 @@ TEST_P(StatelessRejectorTest, RejectChlo) {
TEST_P(StatelessRejectorTest, AcceptChlo) {
const uint64_t xlct = CryptoTestUtils::LeafCertHashForTesting();
const string xlct_hex =
- "#" +
- QuicUtils::HexEncode(reinterpret_cast<const char*>(&xlct), sizeof(xlct));
+ "#" + QuicTextUtils::HexEncode(reinterpret_cast<const char*>(&xlct),
+ sizeof(xlct));
// clang-format off
const CryptoHandshakeMessage client_hello = CryptoTestUtils::Message(
"CHLO",
@@ -274,7 +277,7 @@ TEST_P(StatelessRejectorTest, AcceptChlo) {
rejector_->OnChlo(GetParam().version, kConnectionId,
kServerDesignateConnectionId, client_hello);
- if (GetParam().flags != ENABLED || GetParam().version <= QUIC_VERSION_32) {
+ if (GetParam().flags != ENABLED) {
EXPECT_EQ(StatelessRejector::UNSUPPORTED, rejector_->state());
return;
}
@@ -282,7 +285,7 @@ TEST_P(StatelessRejectorTest, AcceptChlo) {
// The StatelessRejector is undecided - proceed with async processing
ASSERT_EQ(StatelessRejector::UNKNOWN, rejector_->state());
StatelessRejector::Process(std::move(rejector_),
- base::MakeUnique<ProcessDoneCallback>(this));
+ QuicMakeUnique<ProcessDoneCallback>(this));
EXPECT_EQ(StatelessRejector::ACCEPTED, rejector_->state());
}
diff --git a/chromium/net/tools/quic/test_tools/limited_mtu_test_writer.cc b/chromium/net/tools/quic/test_tools/limited_mtu_test_writer.cc
index 4af2439759a..3d2ee877381 100644
--- a/chromium/net/tools/quic/test_tools/limited_mtu_test_writer.cc
+++ b/chromium/net/tools/quic/test_tools/limited_mtu_test_writer.cc
@@ -11,11 +11,12 @@ LimitedMtuTestWriter::LimitedMtuTestWriter(QuicByteCount mtu) : mtu_(mtu) {}
LimitedMtuTestWriter::~LimitedMtuTestWriter() {}
-WriteResult LimitedMtuTestWriter::WritePacket(const char* buffer,
- size_t buf_len,
- const IPAddress& self_address,
- const IPEndPoint& peer_address,
- PerPacketOptions* options) {
+WriteResult LimitedMtuTestWriter::WritePacket(
+ const char* buffer,
+ size_t buf_len,
+ const QuicIpAddress& self_address,
+ const QuicSocketAddress& peer_address,
+ PerPacketOptions* options) {
if (buf_len > mtu_) {
// Drop the packet.
return WriteResult(WRITE_STATUS_OK, buf_len);
diff --git a/chromium/net/tools/quic/test_tools/limited_mtu_test_writer.h b/chromium/net/tools/quic/test_tools/limited_mtu_test_writer.h
index c58b7662f26..fb43471e137 100644
--- a/chromium/net/tools/quic/test_tools/limited_mtu_test_writer.h
+++ b/chromium/net/tools/quic/test_tools/limited_mtu_test_writer.h
@@ -8,7 +8,7 @@
#include <stddef.h>
#include "base/macros.h"
-#include "net/quic/core/quic_protocol.h"
+#include "net/quic/core/quic_packets.h"
#include "net/tools/quic/quic_packet_writer_wrapper.h"
namespace net {
@@ -24,8 +24,8 @@ class LimitedMtuTestWriter : public QuicPacketWriterWrapper {
// Inherited from QuicPacketWriterWrapper.
WriteResult WritePacket(const char* buffer,
size_t buf_len,
- const IPAddress& self_address,
- const IPEndPoint& peer_address,
+ const QuicIpAddress& self_address,
+ const QuicSocketAddress& peer_address,
PerPacketOptions* options) override;
private:
diff --git a/chromium/net/tools/quic/test_tools/mock_quic_server_session_visitor.h b/chromium/net/tools/quic/test_tools/mock_quic_server_session_visitor.h
index 9306abd30ca..e141f63d49f 100644
--- a/chromium/net/tools/quic/test_tools/mock_quic_server_session_visitor.h
+++ b/chromium/net/tools/quic/test_tools/mock_quic_server_session_visitor.h
@@ -2,8 +2,8 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#ifndef NET_QUIC_TEST_TOOLS_MOCK_QUIC_SESSION_VISITOR_H_
-#define NET_QUIC_TEST_TOOLS_MOCK_QUIC_SESSION_VISITOR_H_
+#ifndef NET_TOOLS_QUIC_TEST_TOOLS_MOCK_QUIC_SERVER_SESSION_VISITOR_H_
+#define NET_TOOLS_QUIC_TEST_TOOLS_MOCK_QUIC_SERVER_SESSION_VISITOR_H_
#include "base/macros.h"
#include "net/quic/core/quic_crypto_server_stream.h"
@@ -38,7 +38,7 @@ class MockQuicCryptoServerStreamHelper : public QuicCryptoServerStream::Helper {
QuicConnectionId(QuicConnectionId connection_id));
MOCK_CONST_METHOD3(CanAcceptClientHello,
bool(const CryptoHandshakeMessage& message,
- const IPEndPoint& self_address,
+ const QuicSocketAddress& self_address,
std::string* error_details));
private:
diff --git a/chromium/net/tools/quic/test_tools/mock_quic_time_wait_list_manager.h b/chromium/net/tools/quic/test_tools/mock_quic_time_wait_list_manager.h
index f6509783c3a..574000823c0 100644
--- a/chromium/net/tools/quic/test_tools/mock_quic_time_wait_list_manager.h
+++ b/chromium/net/tools/quic/test_tools/mock_quic_time_wait_list_manager.h
@@ -39,8 +39,8 @@ class MockTimeWaitListManager : public QuicTimeWaitListManager {
}
MOCK_METHOD5(ProcessPacket,
- void(const IPEndPoint& server_address,
- const IPEndPoint& client_address,
+ void(const QuicSocketAddress& server_address,
+ const QuicSocketAddress& client_address,
QuicConnectionId connection_id,
QuicPacketNumber packet_number,
const QuicEncryptedPacket& packet));
@@ -48,8 +48,8 @@ class MockTimeWaitListManager : public QuicTimeWaitListManager {
MOCK_METHOD4(SendVersionNegotiationPacket,
void(QuicConnectionId connection_id,
const QuicVersionVector& supported_versions,
- const IPEndPoint& server_address,
- const IPEndPoint& client_address));
+ const QuicSocketAddress& server_address,
+ const QuicSocketAddress& client_address));
};
} // namespace test
diff --git a/chromium/net/tools/quic/test_tools/packet_dropping_test_writer.cc b/chromium/net/tools/quic/test_tools/packet_dropping_test_writer.cc
index 8b2141cfc87..c350c6b395c 100644
--- a/chromium/net/tools/quic/test_tools/packet_dropping_test_writer.cc
+++ b/chromium/net/tools/quic/test_tools/packet_dropping_test_writer.cc
@@ -7,8 +7,9 @@
#include <limits>
#include "base/rand_util.h"
+#include "net/quic/platform/api/quic_logging.h"
+#include "net/tools/quic/platform/impl/quic_socket_utils.h"
#include "net/tools/quic/quic_epoll_connection_helper.h"
-#include "net/tools/quic/quic_socket_utils.h"
namespace net {
namespace test {
@@ -21,7 +22,7 @@ class WriteUnblockedAlarm : public QuicAlarm::Delegate {
: writer_(writer) {}
void OnAlarm() override {
- DVLOG(1) << "Unblocking socket.";
+ QUIC_DLOG(INFO) << "Unblocking socket.";
writer_->OnCanWrite();
}
@@ -59,7 +60,7 @@ PacketDroppingTestWriter::PacketDroppingTestWriter()
fake_bandwidth_(QuicBandwidth::Zero()),
buffer_size_(0) {
uint32_t seed = base::RandInt(0, std::numeric_limits<int32_t>::max());
- VLOG(1) << "Seeding packet loss with " << seed;
+ QUIC_LOG(INFO) << "Seeding packet loss with " << seed;
simple_random_.set_seed(seed);
}
@@ -78,31 +79,31 @@ void PacketDroppingTestWriter::Initialize(QuicConnectionHelperInterface* helper,
WriteResult PacketDroppingTestWriter::WritePacket(
const char* buffer,
size_t buf_len,
- const IPAddress& self_address,
- const IPEndPoint& peer_address,
+ const QuicIpAddress& self_address,
+ const QuicSocketAddress& peer_address,
PerPacketOptions* options) {
++num_calls_to_write_;
ReleaseOldPackets();
- base::AutoLock locked(config_mutex_);
+ QuicReaderMutexLock lock(&config_mutex_);
if (fake_drop_first_n_packets_ > 0 &&
num_calls_to_write_ <=
static_cast<uint64_t>(fake_drop_first_n_packets_)) {
- DVLOG(1) << "Dropping first " << fake_drop_first_n_packets_
- << " packets (packet number " << num_calls_to_write_ << ")";
+ QUIC_DVLOG(1) << "Dropping first " << fake_drop_first_n_packets_
+ << " packets (packet number " << num_calls_to_write_ << ")";
return WriteResult(WRITE_STATUS_OK, buf_len);
}
if (fake_packet_loss_percentage_ > 0 &&
simple_random_.RandUint64() % 100 <
static_cast<uint64_t>(fake_packet_loss_percentage_)) {
- DVLOG(1) << "Dropping packet.";
+ QUIC_DVLOG(1) << "Dropping packet.";
return WriteResult(WRITE_STATUS_OK, buf_len);
}
if (fake_blocked_socket_percentage_ > 0 &&
simple_random_.RandUint64() % 100 <
static_cast<uint64_t>(fake_blocked_socket_percentage_)) {
CHECK(on_can_write_.get() != nullptr);
- DVLOG(1) << "Blocking socket.";
+ QUIC_DVLOG(1) << "Blocking socket.";
if (!write_unblocked_alarm_->IsSet()) {
// Set the alarm to fire immediately.
write_unblocked_alarm_->Set(clock_->ApproximateNow());
@@ -113,7 +114,7 @@ WriteResult PacketDroppingTestWriter::WritePacket(
if (!fake_packet_delay_.IsZero() || !fake_bandwidth_.IsZero()) {
if (buffer_size_ > 0 && buf_len + cur_buffer_size_ > buffer_size_) {
// Drop packets which do not fit into the buffer.
- DVLOG(1) << "Dropping packet because the buffer is full.";
+ QUIC_DVLOG(1) << "Dropping packet because the buffer is full.";
return WriteResult(WRITE_STATUS_OK, buf_len);
}
@@ -168,20 +169,20 @@ QuicTime PacketDroppingTestWriter::ReleaseNextPacket() {
if (delayed_packets_.empty()) {
return QuicTime::Zero();
}
- base::AutoLock locked(config_mutex_);
+ QuicReaderMutexLock lock(&config_mutex_);
DelayedPacketList::iterator iter = delayed_packets_.begin();
// Determine if we should re-order.
if (delayed_packets_.size() > 1 && fake_packet_reorder_percentage_ > 0 &&
simple_random_.RandUint64() % 100 <
static_cast<uint64_t>(fake_packet_reorder_percentage_)) {
- DVLOG(1) << "Reordering packets.";
+ QUIC_DLOG(INFO) << "Reordering packets.";
++iter;
// Swap the send times when re-ordering packets.
delayed_packets_.begin()->send_time = iter->send_time;
}
- DVLOG(1) << "Releasing packet. " << (delayed_packets_.size() - 1)
- << " remaining.";
+ QUIC_DLOG(INFO) << "Releasing packet. " << (delayed_packets_.size() - 1)
+ << " remaining.";
// Grab the next one off the queue and send it.
QuicPacketWriterWrapper::WritePacket(
iter->buffer.data(), iter->buffer.length(), iter->self_address,
@@ -219,8 +220,8 @@ void PacketDroppingTestWriter::OnCanWrite() {
PacketDroppingTestWriter::DelayedWrite::DelayedWrite(
const char* buffer,
size_t buf_len,
- const IPAddress& self_address,
- const IPEndPoint& peer_address,
+ const QuicIpAddress& self_address,
+ const QuicSocketAddress& peer_address,
std::unique_ptr<PerPacketOptions> options,
QuicTime send_time)
: buffer(buffer, buf_len),
diff --git a/chromium/net/tools/quic/test_tools/packet_dropping_test_writer.h b/chromium/net/tools/quic/test_tools/packet_dropping_test_writer.h
index 0ccdbb912ee..c4c28b6f1ba 100644
--- a/chromium/net/tools/quic/test_tools/packet_dropping_test_writer.h
+++ b/chromium/net/tools/quic/test_tools/packet_dropping_test_writer.h
@@ -18,7 +18,7 @@
#include "net/base/ip_address.h"
#include "net/quic/core/quic_alarm.h"
#include "net/quic/test_tools/quic_test_utils.h"
-#include "net/tools/quic/quic_epoll_clock.h"
+#include "net/tools/quic/platform/impl/quic_epoll_clock.h"
#include "net/tools/quic/quic_packet_writer_wrapper.h"
#include "net/tools/quic/test_tools/quic_test_client.h"
@@ -51,8 +51,8 @@ class PacketDroppingTestWriter : public QuicPacketWriterWrapper {
// QuicPacketWriter methods:
WriteResult WritePacket(const char* buffer,
size_t buf_len,
- const IPAddress& self_address,
- const IPEndPoint& peer_address,
+ const QuicIpAddress& self_address,
+ const QuicSocketAddress& peer_address,
PerPacketOptions* options) override;
bool IsWriteBlocked() const override;
@@ -71,14 +71,14 @@ class PacketDroppingTestWriter : public QuicPacketWriterWrapper {
// The percent of time a packet is simulated as being lost.
void set_fake_packet_loss_percentage(int32_t fake_packet_loss_percentage) {
- base::AutoLock locked(config_mutex_);
+ QuicWriterMutexLock lock(&config_mutex_);
fake_packet_loss_percentage_ = fake_packet_loss_percentage;
}
// Simulate dropping the first n packets unconditionally.
// Subsequent packets will be lost at fake_packet_loss_percentage_ if set.
void set_fake_drop_first_n_packets(int32_t fake_drop_first_n_packets) {
- base::AutoLock locked(config_mutex_);
+ QuicWriterMutexLock lock(&config_mutex_);
fake_drop_first_n_packets_ = fake_drop_first_n_packets;
}
@@ -87,14 +87,14 @@ class PacketDroppingTestWriter : public QuicPacketWriterWrapper {
void set_fake_blocked_socket_percentage(
int32_t fake_blocked_socket_percentage) {
DCHECK(clock_);
- base::AutoLock locked(config_mutex_);
+ QuicWriterMutexLock lock(&config_mutex_);
fake_blocked_socket_percentage_ = fake_blocked_socket_percentage;
}
// The percent of time a packet is simulated as being reordered.
void set_fake_reorder_percentage(int32_t fake_packet_reorder_percentage) {
DCHECK(clock_);
- base::AutoLock locked(config_mutex_);
+ QuicWriterMutexLock lock(&config_mutex_);
DCHECK(!fake_packet_delay_.IsZero());
fake_packet_reorder_percentage_ = fake_packet_reorder_percentage;
}
@@ -102,7 +102,7 @@ class PacketDroppingTestWriter : public QuicPacketWriterWrapper {
// The delay before writing this packet.
void set_fake_packet_delay(QuicTime::Delta fake_packet_delay) {
DCHECK(clock_);
- base::AutoLock locked(config_mutex_);
+ QuicWriterMutexLock lock(&config_mutex_);
fake_packet_delay_ = fake_packet_delay;
}
@@ -113,7 +113,7 @@ class PacketDroppingTestWriter : public QuicPacketWriterWrapper {
void set_max_bandwidth_and_buffer_size(QuicBandwidth fake_bandwidth,
QuicByteCount buffer_size) {
DCHECK(clock_);
- base::AutoLock locked(config_mutex_);
+ QuicWriterMutexLock lock(&config_mutex_);
fake_bandwidth_ = fake_bandwidth;
buffer_size_ = buffer_size;
}
@@ -131,8 +131,8 @@ class PacketDroppingTestWriter : public QuicPacketWriterWrapper {
public:
DelayedWrite(const char* buffer,
size_t buf_len,
- const IPAddress& self_address,
- const IPEndPoint& peer_address,
+ const QuicIpAddress& self_address,
+ const QuicSocketAddress& peer_address,
std::unique_ptr<PerPacketOptions> options,
QuicTime send_time);
// TODO(rtenneti): on windows RValue reference gives errors.
@@ -142,8 +142,8 @@ class PacketDroppingTestWriter : public QuicPacketWriterWrapper {
~DelayedWrite();
std::string buffer;
- const IPAddress self_address;
- const IPEndPoint peer_address;
+ const QuicIpAddress self_address;
+ const QuicSocketAddress peer_address;
std::unique_ptr<PerPacketOptions> options;
QuicTime send_time;
@@ -163,14 +163,14 @@ class PacketDroppingTestWriter : public QuicPacketWriterWrapper {
QuicByteCount cur_buffer_size_;
uint64_t num_calls_to_write_;
- base::Lock config_mutex_;
- int32_t fake_packet_loss_percentage_;
- int32_t fake_drop_first_n_packets_;
- int32_t fake_blocked_socket_percentage_;
- int32_t fake_packet_reorder_percentage_;
- QuicTime::Delta fake_packet_delay_;
- QuicBandwidth fake_bandwidth_;
- QuicByteCount buffer_size_;
+ QuicMutex config_mutex_;
+ int32_t fake_packet_loss_percentage_ GUARDED_BY(config_mutex_);
+ int32_t fake_drop_first_n_packets_ GUARDED_BY(config_mutex_);
+ int32_t fake_blocked_socket_percentage_ GUARDED_BY(config_mutex_);
+ int32_t fake_packet_reorder_percentage_ GUARDED_BY(config_mutex_);
+ QuicTime::Delta fake_packet_delay_ GUARDED_BY(config_mutex_);
+ QuicBandwidth fake_bandwidth_ GUARDED_BY(config_mutex_);
+ QuicByteCount buffer_size_ GUARDED_BY(config_mutex_);
DISALLOW_COPY_AND_ASSIGN(PacketDroppingTestWriter);
};
diff --git a/chromium/net/tools/quic/test_tools/packet_reordering_writer.cc b/chromium/net/tools/quic/test_tools/packet_reordering_writer.cc
index a11f7d8e393..a5262847d34 100644
--- a/chromium/net/tools/quic/test_tools/packet_reordering_writer.cc
+++ b/chromium/net/tools/quic/test_tools/packet_reordering_writer.cc
@@ -11,11 +11,12 @@ PacketReorderingWriter::PacketReorderingWriter() {}
PacketReorderingWriter::~PacketReorderingWriter() {}
-WriteResult PacketReorderingWriter::WritePacket(const char* buffer,
- size_t buf_len,
- const IPAddress& self_address,
- const IPEndPoint& peer_address,
- PerPacketOptions* options) {
+WriteResult PacketReorderingWriter::WritePacket(
+ const char* buffer,
+ size_t buf_len,
+ const QuicIpAddress& self_address,
+ const QuicSocketAddress& peer_address,
+ PerPacketOptions* options) {
if (!delay_next_) {
WriteResult wr = QuicPacketWriterWrapper::WritePacket(
buffer, buf_len, self_address, peer_address, options);
diff --git a/chromium/net/tools/quic/test_tools/packet_reordering_writer.h b/chromium/net/tools/quic/test_tools/packet_reordering_writer.h
index d09aeb84a3a..2ac8c35be7d 100644
--- a/chromium/net/tools/quic/test_tools/packet_reordering_writer.h
+++ b/chromium/net/tools/quic/test_tools/packet_reordering_writer.h
@@ -24,8 +24,8 @@ class PacketReorderingWriter : public QuicPacketWriterWrapper {
WriteResult WritePacket(const char* buffer,
size_t buf_len,
- const IPAddress& self_address,
- const IPEndPoint& peer_address,
+ const QuicIpAddress& self_address,
+ const QuicSocketAddress& peer_address,
PerPacketOptions* options) override;
void SetDelay(size_t num_packets_to_wait);
@@ -34,8 +34,8 @@ class PacketReorderingWriter : public QuicPacketWriterWrapper {
bool delay_next_ = false;
size_t num_packets_to_wait_ = 0;
std::string delayed_data_;
- IPAddress delayed_self_address_;
- IPEndPoint delayed_peer_address_;
+ QuicIpAddress delayed_self_address_;
+ QuicSocketAddress delayed_peer_address_;
std::unique_ptr<PerPacketOptions> delayed_options_;
};
diff --git a/chromium/net/tools/quic/test_tools/quic_client_peer.cc b/chromium/net/tools/quic/test_tools/quic_client_peer.cc
index aca80df0c20..0f6d1ba1098 100644
--- a/chromium/net/tools/quic/test_tools/quic_client_peer.cc
+++ b/chromium/net/tools/quic/test_tools/quic_client_peer.cc
@@ -29,7 +29,7 @@ void QuicClientPeer::CleanUpUDPSocket(QuicClient* client, int fd) {
// static
void QuicClientPeer::SetClientPort(QuicClient* client, int port) {
client->fd_address_map_.back().second =
- IPEndPoint(client->GetLatestClientAddress().address(), port);
+ QuicSocketAddress(client->GetLatestClientAddress().host(), port);
}
// static
diff --git a/chromium/net/tools/quic/test_tools/quic_dispatcher_peer.cc b/chromium/net/tools/quic/test_tools/quic_dispatcher_peer.cc
index bb528841e83..cf7dfe7cc89 100644
--- a/chromium/net/tools/quic/test_tools/quic_dispatcher_peer.cc
+++ b/chromium/net/tools/quic/test_tools/quic_dispatcher_peer.cc
@@ -84,8 +84,8 @@ void QuicDispatcherPeer::set_new_sessions_allowed_per_event_loop(
// static
void QuicDispatcherPeer::SendPublicReset(
QuicDispatcher* dispatcher,
- const IPEndPoint& server_address,
- const IPEndPoint& client_address,
+ const QuicSocketAddress& server_address,
+ const QuicSocketAddress& client_address,
QuicConnectionId connection_id,
QuicPacketNumber rejected_packet_number) {
dispatcher->time_wait_list_manager()->SendPublicReset(
diff --git a/chromium/net/tools/quic/test_tools/quic_dispatcher_peer.h b/chromium/net/tools/quic/test_tools/quic_dispatcher_peer.h
index c415fc39ad1..a4a255e50f8 100644
--- a/chromium/net/tools/quic/test_tools/quic_dispatcher_peer.h
+++ b/chromium/net/tools/quic/test_tools/quic_dispatcher_peer.h
@@ -52,8 +52,8 @@ class QuicDispatcherPeer {
size_t num_session_allowed);
static void SendPublicReset(QuicDispatcher* dispatcher,
- const IPEndPoint& server_address,
- const IPEndPoint& client_address,
+ const QuicSocketAddress& server_address,
+ const QuicSocketAddress& client_address,
QuicConnectionId connection_id,
QuicPacketNumber rejected_packet_number);
diff --git a/chromium/net/tools/quic/test_tools/quic_in_memory_cache_peer.cc b/chromium/net/tools/quic/test_tools/quic_in_memory_cache_peer.cc
deleted file mode 100644
index e342e4a39fc..00000000000
--- a/chromium/net/tools/quic/test_tools/quic_in_memory_cache_peer.cc
+++ /dev/null
@@ -1,18 +0,0 @@
-// Copyright 2013 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.
-
-#include "net/tools/quic/test_tools/quic_in_memory_cache_peer.h"
-
-#include "net/tools/quic/quic_in_memory_cache.h"
-
-namespace net {
-namespace test {
-
-// static
-void QuicInMemoryCachePeer::ResetForTests() {
- QuicInMemoryCache::GetInstance()->ResetForTests();
-}
-
-} // namespace test
-} // namespace net
diff --git a/chromium/net/tools/quic/test_tools/quic_in_memory_cache_peer.h b/chromium/net/tools/quic/test_tools/quic_in_memory_cache_peer.h
deleted file mode 100644
index 55d28d3f0e2..00000000000
--- a/chromium/net/tools/quic/test_tools/quic_in_memory_cache_peer.h
+++ /dev/null
@@ -1,26 +0,0 @@
-// Copyright 2013 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.
-
-#ifndef NET_TOOLS_QUIC_TEST_TOOLS_QUIC_IN_MEMORY_CACHE_PEER_H_
-#define NET_TOOLS_QUIC_TEST_TOOLS_QUIC_IN_MEMORY_CACHE_PEER_H_
-
-#include "base/macros.h"
-#include "net/tools/quic/quic_in_memory_cache.h"
-
-namespace net {
-namespace test {
-
-class QuicInMemoryCachePeer {
- public:
- // Resets the singleton QuicInMemoryCache to a fresh state.
- static void ResetForTests();
-
- private:
- DISALLOW_COPY_AND_ASSIGN(QuicInMemoryCachePeer);
-};
-
-} // namespace test
-} // namespace net
-
-#endif // NET_TOOLS_QUIC_TEST_TOOLS_QUIC_IN_MEMORY_CACHE_PEER_H_
diff --git a/chromium/net/tools/quic/test_tools/quic_test_client.cc b/chromium/net/tools/quic/test_tools/quic_test_client.cc
index bf58e1fbf35..f844d4b49ed 100644
--- a/chromium/net/tools/quic/test_tools/quic_test_client.cc
+++ b/chromium/net/tools/quic/test_tools/quic_test_client.cc
@@ -9,7 +9,6 @@
#include <vector>
#include "base/memory/ptr_util.h"
-#include "base/strings/string_util.h"
#include "base/time/time.h"
#include "net/base/completion_callback.h"
#include "net/base/net_errors.h"
@@ -20,6 +19,8 @@
#include "net/quic/core/quic_server_id.h"
#include "net/quic/core/quic_utils.h"
#include "net/quic/core/spdy_utils.h"
+#include "net/quic/platform/api/quic_logging.h"
+#include "net/quic/platform/api/quic_text_utils.h"
#include "net/quic/test_tools/crypto_test_utils.h"
#include "net/quic/test_tools/quic_connection_peer.h"
#include "net/quic/test_tools/quic_spdy_session_peer.h"
@@ -120,7 +121,7 @@ class RecordingProofVerifier : public ProofVerifier {
} // anonymous namespace
MockableQuicClient::MockableQuicClient(
- IPEndPoint server_address,
+ QuicSocketAddress server_address,
const QuicServerId& server_id,
const QuicVersionVector& supported_versions,
EpollServer* epoll_server)
@@ -131,7 +132,7 @@ MockableQuicClient::MockableQuicClient(
epoll_server) {}
MockableQuicClient::MockableQuicClient(
- IPEndPoint server_address,
+ QuicSocketAddress server_address,
const QuicServerId& server_id,
const QuicConfig& config,
const QuicVersionVector& supported_versions,
@@ -144,7 +145,7 @@ MockableQuicClient::MockableQuicClient(
nullptr) {}
MockableQuicClient::MockableQuicClient(
- IPEndPoint server_address,
+ QuicSocketAddress server_address,
const QuicServerId& server_id,
const QuicConfig& config,
const QuicVersionVector& supported_versions,
@@ -161,8 +162,8 @@ MockableQuicClient::MockableQuicClient(
test_writer_(nullptr),
track_last_incoming_packet_(false) {}
-void MockableQuicClient::ProcessPacket(const IPEndPoint& self_address,
- const IPEndPoint& peer_address,
+void MockableQuicClient::ProcessPacket(const QuicSocketAddress& self_address,
+ const QuicSocketAddress& peer_address,
const QuicReceivedPacket& packet) {
QuicClient::ProcessPacket(self_address, peer_address, packet);
if (track_last_incoming_packet_)
@@ -199,7 +200,7 @@ void MockableQuicClient::UseConnectionId(QuicConnectionId connection_id) {
override_connection_id_ = connection_id;
}
-QuicTestClient::QuicTestClient(IPEndPoint server_address,
+QuicTestClient::QuicTestClient(QuicSocketAddress server_address,
const string& server_hostname,
const QuicVersionVector& supported_versions)
: QuicTestClient(server_address,
@@ -207,7 +208,7 @@ QuicTestClient::QuicTestClient(IPEndPoint server_address,
QuicConfig(),
supported_versions) {}
-QuicTestClient::QuicTestClient(IPEndPoint server_address,
+QuicTestClient::QuicTestClient(QuicSocketAddress server_address,
const string& server_hostname,
const QuicConfig& config,
const QuicVersionVector& supported_versions)
@@ -223,7 +224,7 @@ QuicTestClient::QuicTestClient(IPEndPoint server_address,
Initialize();
}
-QuicTestClient::QuicTestClient(IPEndPoint server_address,
+QuicTestClient::QuicTestClient(QuicSocketAddress server_address,
const string& server_hostname,
const QuicConfig& config,
const QuicVersionVector& supported_versions,
@@ -292,7 +293,7 @@ ssize_t QuicTestClient::GetOrCreateStreamAndSendRequest(
const SpdyHeaderBlock* headers,
StringPiece body,
bool fin,
- QuicAckListenerInterface* delegate) {
+ QuicReferenceCountedPointer<QuicAckListenerInterface> ack_listener) {
if (headers) {
QuicClientPushPromiseIndex::TryHandle* handle;
QuicAsyncStatus rv =
@@ -304,7 +305,7 @@ ssize_t QuicTestClient::GetOrCreateStreamAndSendRequest(
std::unique_ptr<SpdyHeaderBlock> new_headers(
new SpdyHeaderBlock(headers->Clone()));
push_promise_data_to_resend_.reset(new TestClientDataToResend(
- std::move(new_headers), body, fin, this, delegate));
+ std::move(new_headers), body, fin, this, std::move(ack_listener)));
return 1;
}
}
@@ -326,17 +327,17 @@ ssize_t QuicTestClient::GetOrCreateStreamAndSendRequest(
ret = stream->SendRequest(std::move(spdy_headers), body, fin);
++num_requests_;
} else {
- stream->WriteOrBufferBody(body.as_string(), fin, delegate);
+ stream->WriteOrBufferBody(body.as_string(), fin, ack_listener);
ret = body.length();
}
- if (FLAGS_enable_quic_stateless_reject_support) {
+ if (FLAGS_quic_reloadable_flag_enable_quic_stateless_reject_support) {
std::unique_ptr<SpdyHeaderBlock> new_headers;
if (headers) {
new_headers.reset(new SpdyHeaderBlock(headers->Clone()));
}
std::unique_ptr<QuicClientBase::QuicDataToResend> data_to_resend(
new TestClientDataToResend(std::move(new_headers), body, fin, this,
- delegate));
+ ack_listener));
client()->MaybeAddQuicDataToResend(std::move(data_to_resend));
}
return ret;
@@ -374,11 +375,12 @@ ssize_t QuicTestClient::SendData(const string& data, bool last_data) {
return SendData(data, last_data, nullptr);
}
-ssize_t QuicTestClient::SendData(const string& data,
- bool last_data,
- QuicAckListenerInterface* delegate) {
+ssize_t QuicTestClient::SendData(
+ const string& data,
+ bool last_data,
+ QuicReferenceCountedPointer<QuicAckListenerInterface> ack_listener) {
return GetOrCreateStreamAndSendRequest(nullptr, StringPiece(data), last_data,
- delegate);
+ std::move(ack_listener));
}
bool QuicTestClient::response_complete() const {
@@ -405,7 +407,7 @@ string QuicTestClient::SendCustomSynchronousRequest(
const SpdyHeaderBlock& headers,
const string& body) {
if (SendMessage(headers, body) == 0) {
- DLOG(ERROR) << "Failed the request for: " << headers.DebugString();
+ QUIC_DLOG(ERROR) << "Failed the request for: " << headers.DebugString();
// Set the response_ explicitly. Otherwise response_ will contain the
// response from the previously successful request.
response_ = "";
@@ -504,7 +506,7 @@ void QuicTestClient::Disconnect() {
connect_attempted_ = false;
}
-IPEndPoint QuicTestClient::local_address() const {
+QuicSocketAddress QuicTestClient::local_address() const {
return client_->GetLatestClientAddress();
}
@@ -569,6 +571,13 @@ const SpdyHeaderBlock* QuicTestClient::response_headers() const {
return &response_headers_;
}
+const SpdyHeaderBlock* QuicTestClient::preliminary_headers() const {
+ if (stream_ != nullptr) {
+ preliminary_headers_ = stream_->preliminary_headers().Clone();
+ }
+ return &preliminary_headers_;
+}
+
const SpdyHeaderBlock& QuicTestClient::response_trailers() const {
return response_trailers_;
}
@@ -615,6 +624,7 @@ void QuicTestClient::OnClose(QuicSpdyStream* stream) {
response_headers_complete_ = stream_->headers_decompressed();
response_headers_ = stream_->response_headers().Clone();
response_trailers_ = stream_->received_trailers().Clone();
+ preliminary_headers_ = stream_->preliminary_headers().Clone();
stream_error_ = stream_->stream_error();
bytes_read_ = stream_->stream_bytes_read() + stream_->header_bytes_read();
bytes_written_ =
@@ -649,19 +659,19 @@ void QuicTestClient::UseConnectionId(QuicConnectionId connection_id) {
client_->UseConnectionId(connection_id);
}
-void QuicTestClient::MigrateSocket(const IPAddress& new_host) {
+void QuicTestClient::MigrateSocket(const QuicIpAddress& new_host) {
client_->MigrateSocket(new_host);
}
-IPAddress QuicTestClient::bind_to_address() const {
+QuicIpAddress QuicTestClient::bind_to_address() const {
return client_->bind_to_address();
}
-void QuicTestClient::set_bind_to_address(IPAddress address) {
+void QuicTestClient::set_bind_to_address(QuicIpAddress address) {
client_->set_bind_to_address(address);
}
-const IPEndPoint& QuicTestClient::address() const {
+const QuicSocketAddress& QuicTestClient::address() const {
return client_->server_address();
}
@@ -671,17 +681,29 @@ void QuicTestClient::WaitForWriteToFlush() {
}
}
+QuicTestClient::TestClientDataToResend::TestClientDataToResend(
+ std::unique_ptr<SpdyHeaderBlock> headers,
+ base::StringPiece body,
+ bool fin,
+ QuicTestClient* test_client,
+ QuicReferenceCountedPointer<QuicAckListenerInterface> ack_listener)
+ : QuicClient::QuicDataToResend(std::move(headers), body, fin),
+ test_client_(test_client),
+ ack_listener_(std::move(ack_listener)) {}
+
+QuicTestClient::TestClientDataToResend::~TestClientDataToResend() {}
+
void QuicTestClient::TestClientDataToResend::Resend() {
test_client_->GetOrCreateStreamAndSendRequest(headers_.get(), body_, fin_,
- delegate_);
+ ack_listener_);
headers_.reset();
}
bool QuicTestClient::PopulateHeaderBlockFromUrl(const string& uri,
SpdyHeaderBlock* headers) {
string url;
- if (base::StartsWith(uri, "https://", base::CompareCase::INSENSITIVE_ASCII) ||
- base::StartsWith(uri, "http://", base::CompareCase::INSENSITIVE_ASCII)) {
+ if (QuicTextUtils::StartsWith(uri, "https://") ||
+ QuicTextUtils::StartsWith(uri, "http://")) {
url = uri;
} else if (uri[0] == '/') {
url = "https://" + client_->server_id().host() + uri;
diff --git a/chromium/net/tools/quic/test_tools/quic_test_client.h b/chromium/net/tools/quic/test_tools/quic_test_client.h
index dcc73a0c95d..f35003ccad5 100644
--- a/chromium/net/tools/quic/test_tools/quic_test_client.h
+++ b/chromium/net/tools/quic/test_tools/quic_test_client.h
@@ -13,12 +13,10 @@
#include <string>
#include "base/macros.h"
-#include "net/base/ip_address.h"
-#include "net/base/ip_endpoint.h"
#include "net/quic/core/proto/cached_network_parameters.pb.h"
#include "net/quic/core/quic_framer.h"
#include "net/quic/core/quic_packet_creator.h"
-#include "net/quic/core/quic_protocol.h"
+#include "net/quic/core/quic_packets.h"
#include "net/tools/epoll_server/epoll_server.h"
#include "net/tools/quic/quic_client.h"
#include "testing/gmock/include/gmock/gmock.h"
@@ -34,24 +32,23 @@ class QuicPacketWriterWrapper;
namespace test {
-class HTTPMessage;
class MockableQuicClient;
// A quic client which allows mocking out reads and writes.
class MockableQuicClient : public QuicClient {
public:
- MockableQuicClient(IPEndPoint server_address,
+ MockableQuicClient(QuicSocketAddress server_address,
const QuicServerId& server_id,
const QuicVersionVector& supported_versions,
EpollServer* epoll_server);
- MockableQuicClient(IPEndPoint server_address,
+ MockableQuicClient(QuicSocketAddress server_address,
const QuicServerId& server_id,
const QuicConfig& config,
const QuicVersionVector& supported_versions,
EpollServer* epoll_server);
- MockableQuicClient(IPEndPoint server_address,
+ MockableQuicClient(QuicSocketAddress server_address,
const QuicServerId& server_id,
const QuicConfig& config,
const QuicVersionVector& supported_versions,
@@ -60,8 +57,8 @@ class MockableQuicClient : public QuicClient {
~MockableQuicClient() override;
- void ProcessPacket(const IPEndPoint& self_address,
- const IPEndPoint& peer_address,
+ void ProcessPacket(const QuicSocketAddress& self_address,
+ const QuicSocketAddress& peer_address,
const QuicReceivedPacket& packet) override;
QuicPacketWriter* CreateQuicPacketWriter() override;
@@ -95,14 +92,14 @@ class MockableQuicClient : public QuicClient {
class QuicTestClient : public QuicSpdyStream::Visitor,
public QuicClientPushPromiseIndex::Delegate {
public:
- QuicTestClient(IPEndPoint server_address,
+ QuicTestClient(QuicSocketAddress server_address,
const std::string& server_hostname,
const QuicVersionVector& supported_versions);
- QuicTestClient(IPEndPoint server_address,
+ QuicTestClient(QuicSocketAddress server_address,
const std::string& server_hostname,
const QuicConfig& config,
const QuicVersionVector& supported_versions);
- QuicTestClient(IPEndPoint server_address,
+ QuicTestClient(QuicSocketAddress server_address,
const std::string& server_hostname,
const QuicConfig& config,
const QuicVersionVector& supported_versions,
@@ -116,9 +113,10 @@ class QuicTestClient : public QuicSpdyStream::Visitor,
// Wraps data in a quic packet and sends it.
ssize_t SendData(const std::string& data, bool last_data);
// As above, but |delegate| will be notified when |data| is ACKed.
- ssize_t SendData(const std::string& data,
- bool last_data,
- QuicAckListenerInterface* delegate);
+ ssize_t SendData(
+ const std::string& data,
+ bool last_data,
+ QuicReferenceCountedPointer<QuicAckListenerInterface> ack_listener);
// Clears any outstanding state and sends a simple GET of 'uri' to the
// server. Returns 0 if the request failed and no bytes were written.
@@ -147,13 +145,14 @@ class QuicTestClient : public QuicSpdyStream::Visitor,
void Connect();
void ResetConnection();
void Disconnect();
- IPEndPoint local_address() const;
+ QuicSocketAddress local_address() const;
void ClearPerRequestState();
bool WaitUntil(int timeout_ms, std::function<bool()> trigger);
ssize_t Send(const void* buffer, size_t size);
bool response_complete() const;
bool response_headers_complete() const;
const SpdyHeaderBlock* response_headers() const;
+ const SpdyHeaderBlock* preliminary_headers() const;
int64_t response_size() const;
int64_t response_body_size() const;
size_t bytes_read() const;
@@ -186,10 +185,10 @@ class QuicTestClient : public QuicSpdyStream::Visitor,
WaitUntil(timeout_ms, [this]() { return response_size() != 0; });
}
- void MigrateSocket(const IPAddress& new_host);
- IPAddress bind_to_address() const;
- void set_bind_to_address(IPAddress address);
- const IPEndPoint& address() const;
+ void MigrateSocket(const QuicIpAddress& new_host);
+ QuicIpAddress bind_to_address() const;
+ void set_bind_to_address(QuicIpAddress address);
+ const QuicSocketAddress& address() const;
// Returns the response trailers as received by the |stream_|.
const SpdyHeaderBlock& response_trailers() const;
@@ -218,10 +217,11 @@ class QuicTestClient : public QuicSpdyStream::Visitor,
// Calls GetOrCreateStream(), sends the request on the stream, and
// stores the request in case it needs to be resent. If |headers| is
// null, only the body will be sent on the stream.
- ssize_t GetOrCreateStreamAndSendRequest(const SpdyHeaderBlock* headers,
- base::StringPiece body,
- bool fin,
- QuicAckListenerInterface* delegate);
+ ssize_t GetOrCreateStreamAndSendRequest(
+ const SpdyHeaderBlock* headers,
+ base::StringPiece body,
+ bool fin,
+ QuicReferenceCountedPointer<QuicAckListenerInterface> ack_listener);
QuicRstStreamErrorCode stream_error() { return stream_error_; }
QuicErrorCode connection_error();
@@ -257,7 +257,7 @@ class QuicTestClient : public QuicSpdyStream::Visitor,
size_t num_responses() const { return num_responses_; }
- void set_server_address(const IPEndPoint& server_address) {
+ void set_server_address(const QuicSocketAddress& server_address) {
client_->set_server_address(server_address);
}
@@ -278,22 +278,20 @@ class QuicTestClient : public QuicSpdyStream::Visitor,
private:
class TestClientDataToResend : public QuicClient::QuicDataToResend {
public:
- TestClientDataToResend(std::unique_ptr<SpdyHeaderBlock> headers,
- base::StringPiece body,
- bool fin,
- QuicTestClient* test_client,
- QuicAckListenerInterface* delegate)
- : QuicClient::QuicDataToResend(std::move(headers), body, fin),
- test_client_(test_client),
- delegate_(delegate) {}
+ TestClientDataToResend(
+ std::unique_ptr<SpdyHeaderBlock> headers,
+ base::StringPiece body,
+ bool fin,
+ QuicTestClient* test_client,
+ QuicReferenceCountedPointer<QuicAckListenerInterface> ack_listener);
- ~TestClientDataToResend() override {}
+ ~TestClientDataToResend() override;
void Resend() override;
protected:
QuicTestClient* test_client_;
- QuicAckListenerInterface* delegate_;
+ QuicReferenceCountedPointer<QuicAckListenerInterface> ack_listener_;
};
// Given |uri|, populates the fields in |headers| for a simple GET
@@ -313,6 +311,7 @@ class QuicTestClient : public QuicSpdyStream::Visitor,
bool response_complete_;
bool response_headers_complete_;
mutable SpdyHeaderBlock response_headers_;
+ mutable SpdyHeaderBlock preliminary_headers_;
// Parsed response trailers (if present), copied from the stream in OnClose.
SpdyHeaderBlock response_trailers_;
diff --git a/chromium/net/tools/quic/test_tools/quic_test_server.cc b/chromium/net/tools/quic/test_tools/quic_test_server.cc
index 27424569cf6..ae4f15b166f 100644
--- a/chromium/net/tools/quic/test_tools/quic_test_server.cc
+++ b/chromium/net/tools/quic/test_tools/quic_test_server.cc
@@ -5,11 +5,9 @@
#include "net/tools/quic/test_tools/quic_test_server.h"
#include "base/logging.h"
-#include "base/memory/ptr_util.h"
#include "base/run_loop.h"
#include "base/synchronization/lock.h"
#include "base/threading/thread_task_runner_handle.h"
-#include "net/base/ip_endpoint.h"
#include "net/base/net_errors.h"
#include "net/quic/chromium/quic_chromium_connection_helper.h"
#include "net/quic/core/crypto/crypto_handshake.h"
@@ -18,7 +16,8 @@
#include "net/quic/core/quic_config.h"
#include "net/quic/core/quic_connection.h"
#include "net/quic/core/quic_packet_writer.h"
-#include "net/quic/core/quic_protocol.h"
+#include "net/quic/core/quic_packets.h"
+#include "net/quic/platform/api/quic_ptr_util.h"
#include "net/tools/quic/quic_epoll_alarm_factory.h"
#include "net/tools/quic/quic_epoll_connection_helper.h"
#include "net/tools/quic/quic_simple_crypto_server_stream_helper.h"
@@ -38,15 +37,17 @@ class CustomStreamSession : public QuicSimpleServerSession {
QuicCryptoServerStream::Helper* helper,
const QuicCryptoServerConfig* crypto_config,
QuicCompressedCertsCache* compressed_certs_cache,
- QuicTestServer::StreamFactory* factory,
- QuicTestServer::CryptoStreamFactory* crypto_stream_factory)
+ QuicTestServer::StreamFactory* stream_factory,
+ QuicTestServer::CryptoStreamFactory* crypto_stream_factory,
+ QuicHttpResponseCache* response_cache)
: QuicSimpleServerSession(config,
connection,
visitor,
helper,
crypto_config,
- compressed_certs_cache),
- stream_factory_(factory),
+ compressed_certs_cache,
+ response_cache),
+ stream_factory_(stream_factory),
crypto_stream_factory_(crypto_stream_factory) {}
QuicSpdyStream* CreateIncomingDynamicStream(QuicStreamId id) override {
@@ -54,8 +55,9 @@ class CustomStreamSession : public QuicSimpleServerSession {
return nullptr;
}
if (stream_factory_) {
- QuicSpdyStream* stream = stream_factory_->CreateStream(id, this);
- ActivateStream(base::WrapUnique(stream));
+ QuicSpdyStream* stream =
+ stream_factory_->CreateStream(id, this, response_cache());
+ ActivateStream(QuicWrapUnique(stream));
return stream;
}
return QuicSimpleServerSession::CreateIncomingDynamicStream(id);
@@ -84,20 +86,23 @@ class QuicTestDispatcher : public QuicSimpleDispatcher {
QuicVersionManager* version_manager,
std::unique_ptr<QuicConnectionHelperInterface> helper,
std::unique_ptr<QuicCryptoServerStream::Helper> session_helper,
- std::unique_ptr<QuicAlarmFactory> alarm_factory)
+ std::unique_ptr<QuicAlarmFactory> alarm_factory,
+ QuicHttpResponseCache* response_cache)
: QuicSimpleDispatcher(config,
crypto_config,
version_manager,
std::move(helper),
std::move(session_helper),
- std::move(alarm_factory)),
+ std::move(alarm_factory),
+ response_cache),
session_factory_(nullptr),
stream_factory_(nullptr),
crypto_stream_factory_(nullptr) {}
- QuicServerSessionBase* CreateQuicSession(QuicConnectionId id,
- const IPEndPoint& client) override {
- base::AutoLock lock(factory_lock_);
+ QuicServerSessionBase* CreateQuicSession(
+ QuicConnectionId id,
+ const QuicSocketAddress& client) override {
+ QuicReaderMutexLock lock(&factory_lock_);
if (session_factory_ == nullptr && stream_factory_ == nullptr &&
crypto_stream_factory_ == nullptr) {
return QuicSimpleDispatcher::CreateQuicSession(id, client);
@@ -111,18 +116,19 @@ class QuicTestDispatcher : public QuicSimpleDispatcher {
if (stream_factory_ != nullptr || crypto_stream_factory_ != nullptr) {
session = new CustomStreamSession(
config(), connection, this, session_helper(), crypto_config(),
- compressed_certs_cache(), stream_factory_, crypto_stream_factory_);
+ compressed_certs_cache(), stream_factory_, crypto_stream_factory_,
+ response_cache());
} else {
session = session_factory_->CreateSession(
config(), connection, this, session_helper(), crypto_config(),
- compressed_certs_cache());
+ compressed_certs_cache(), response_cache());
}
session->Initialize();
return session;
}
void SetSessionFactory(QuicTestServer::SessionFactory* factory) {
- base::AutoLock lock(factory_lock_);
+ QuicWriterMutexLock lock(&factory_lock_);
DCHECK(session_factory_ == nullptr);
DCHECK(stream_factory_ == nullptr);
DCHECK(crypto_stream_factory_ == nullptr);
@@ -130,36 +136,39 @@ class QuicTestDispatcher : public QuicSimpleDispatcher {
}
void SetStreamFactory(QuicTestServer::StreamFactory* factory) {
- base::AutoLock lock(factory_lock_);
+ QuicWriterMutexLock lock(&factory_lock_);
DCHECK(session_factory_ == nullptr);
DCHECK(stream_factory_ == nullptr);
stream_factory_ = factory;
}
void SetCryptoStreamFactory(QuicTestServer::CryptoStreamFactory* factory) {
- base::AutoLock lock(factory_lock_);
+ QuicWriterMutexLock lock(&factory_lock_);
DCHECK(session_factory_ == nullptr);
DCHECK(crypto_stream_factory_ == nullptr);
crypto_stream_factory_ = factory;
}
private:
- base::Lock factory_lock_;
+ QuicMutex factory_lock_;
QuicTestServer::SessionFactory* session_factory_; // Not owned.
QuicTestServer::StreamFactory* stream_factory_; // Not owned.
QuicTestServer::CryptoStreamFactory* crypto_stream_factory_; // Not owned.
};
-QuicTestServer::QuicTestServer(std::unique_ptr<ProofSource> proof_source)
- : QuicServer(std::move(proof_source)) {}
+QuicTestServer::QuicTestServer(std::unique_ptr<ProofSource> proof_source,
+ QuicHttpResponseCache* response_cache)
+ : QuicServer(std::move(proof_source), response_cache) {}
QuicTestServer::QuicTestServer(std::unique_ptr<ProofSource> proof_source,
const QuicConfig& config,
- const QuicVersionVector& supported_versions)
+ const QuicVersionVector& supported_versions,
+ QuicHttpResponseCache* response_cache)
: QuicServer(std::move(proof_source),
config,
QuicCryptoServerConfig::ConfigOptions(),
- supported_versions) {}
+ supported_versions,
+ response_cache) {}
QuicDispatcher* QuicTestServer::CreateQuicDispatcher() {
return new QuicTestDispatcher(
@@ -169,7 +178,8 @@ QuicDispatcher* QuicTestServer::CreateQuicDispatcher() {
std::unique_ptr<QuicCryptoServerStream::Helper>(
new QuicSimpleCryptoServerStreamHelper(QuicRandom::GetInstance())),
std::unique_ptr<QuicEpollAlarmFactory>(
- new QuicEpollAlarmFactory(epoll_server())));
+ new QuicEpollAlarmFactory(epoll_server())),
+ response_cache());
}
void QuicTestServer::SetSessionFactory(SessionFactory* factory) {
@@ -194,13 +204,15 @@ ImmediateGoAwaySession::ImmediateGoAwaySession(
QuicSession::Visitor* visitor,
QuicCryptoServerStream::Helper* helper,
const QuicCryptoServerConfig* crypto_config,
- QuicCompressedCertsCache* compressed_certs_cache)
+ QuicCompressedCertsCache* compressed_certs_cache,
+ QuicHttpResponseCache* response_cache)
: QuicSimpleServerSession(config,
connection,
visitor,
helper,
crypto_config,
- compressed_certs_cache) {}
+ compressed_certs_cache,
+ response_cache) {}
void ImmediateGoAwaySession::OnStreamFrame(const QuicStreamFrame& frame) {
SendGoAway(QUIC_PEER_GOING_AWAY, "");
diff --git a/chromium/net/tools/quic/test_tools/quic_test_server.h b/chromium/net/tools/quic/test_tools/quic_test_server.h
index 806b5e2375c..26a8e766992 100644
--- a/chromium/net/tools/quic/test_tools/quic_test_server.h
+++ b/chromium/net/tools/quic/test_tools/quic_test_server.h
@@ -37,7 +37,8 @@ class QuicTestServer : public QuicServer {
QuicSession::Visitor* visitor,
QuicCryptoServerStream::Helper* helper,
const QuicCryptoServerConfig* crypto_config,
- QuicCompressedCertsCache* compressed_certs_cache) = 0;
+ QuicCompressedCertsCache* compressed_certs_cache,
+ QuicHttpResponseCache* response_cache) = 0;
};
// Factory for creating QuicSimpleServerStreams.
@@ -46,8 +47,10 @@ class QuicTestServer : public QuicServer {
virtual ~StreamFactory() {}
// Returns a new stream owned by the caller.
- virtual QuicSimpleServerStream* CreateStream(QuicStreamId id,
- QuicSpdySession* session) = 0;
+ virtual QuicSimpleServerStream* CreateStream(
+ QuicStreamId id,
+ QuicSpdySession* session,
+ QuicHttpResponseCache* response_cache) = 0;
};
class CryptoStreamFactory {
@@ -60,10 +63,12 @@ class QuicTestServer : public QuicServer {
QuicServerSessionBase* session) = 0;
};
- explicit QuicTestServer(std::unique_ptr<ProofSource> proof_source);
+ QuicTestServer(std::unique_ptr<ProofSource> proof_source,
+ QuicHttpResponseCache* response_cache);
QuicTestServer(std::unique_ptr<ProofSource> proof_source,
const QuicConfig& config,
- const QuicVersionVector& supported_versions);
+ const QuicVersionVector& supported_versions,
+ QuicHttpResponseCache* response_cache);
// Create a custom dispatcher which creates custom sessions.
QuicDispatcher* CreateQuicDispatcher() override;
@@ -93,7 +98,9 @@ class ImmediateGoAwaySession : public QuicSimpleServerSession {
QuicSession::Visitor* visitor,
QuicCryptoServerStream::Helper* helper,
const QuicCryptoServerConfig* crypto_config,
- QuicCompressedCertsCache* compressed_certs_cache);
+ QuicCompressedCertsCache* compressed_certs_cache,
+ QuicHttpResponseCache* response_cache);
+
// Override to send GoAway.
void OnStreamFrame(const QuicStreamFrame& frame) override;
};
diff --git a/chromium/net/tools/quic/test_tools/server_thread.cc b/chromium/net/tools/quic/test_tools/server_thread.cc
index 872aa449386..a04311e944d 100644
--- a/chromium/net/tools/quic/test_tools/server_thread.cc
+++ b/chromium/net/tools/quic/test_tools/server_thread.cc
@@ -11,9 +11,7 @@
namespace net {
namespace test {
-ServerThread::ServerThread(QuicServer* server,
- const IPEndPoint& address,
- bool strike_register_no_startup_period)
+ServerThread::ServerThread(QuicServer* server, const QuicSocketAddress& address)
: SimpleThread("server_thread"),
confirmed_(base::WaitableEvent::ResetPolicy::MANUAL,
base::WaitableEvent::InitialState::NOT_SIGNALED),
@@ -28,11 +26,7 @@ ServerThread::ServerThread(QuicServer* server,
server_(server),
address_(address),
port_(0),
- initialized_(false) {
- if (strike_register_no_startup_period) {
- server_->SetStrikeRegisterNoStartupPeriod();
- }
-}
+ initialized_(false) {}
ServerThread::~ServerThread() {}
@@ -77,7 +71,7 @@ int ServerThread::GetPort() {
void ServerThread::Schedule(std::function<void()> action) {
DCHECK(!quit_.IsSignaled());
- base::AutoLock lock(scheduled_actions_lock_);
+ QuicWriterMutexLock lock(&scheduled_actions_lock_);
scheduled_actions_.push_back(std::move(action));
}
@@ -123,7 +117,7 @@ void ServerThread::MaybeNotifyOfHandshakeConfirmation() {
void ServerThread::ExecuteScheduledActions() {
std::deque<std::function<void()>> actions;
{
- base::AutoLock lock(scheduled_actions_lock_);
+ QuicWriterMutexLock lock(&scheduled_actions_lock_);
actions.swap(scheduled_actions_);
}
while (!actions.empty()) {
diff --git a/chromium/net/tools/quic/test_tools/server_thread.h b/chromium/net/tools/quic/test_tools/server_thread.h
index 3fecb06485a..77f00736abb 100644
--- a/chromium/net/tools/quic/test_tools/server_thread.h
+++ b/chromium/net/tools/quic/test_tools/server_thread.h
@@ -8,10 +8,10 @@
#include <memory>
#include "base/macros.h"
-#include "base/synchronization/lock.h"
#include "base/threading/simple_thread.h"
-#include "net/base/ip_endpoint.h"
#include "net/quic/core/quic_config.h"
+#include "net/quic/platform/api/quic_mutex.h"
+#include "net/quic/platform/api/quic_socket_address.h"
#include "net/tools/quic/quic_server.h"
namespace net {
@@ -20,9 +20,7 @@ namespace test {
// Simple wrapper class to run QuicServer in a dedicated thread.
class ServerThread : public base::SimpleThread {
public:
- ServerThread(QuicServer* server,
- const IPEndPoint& address,
- bool strike_register_no_startup_period);
+ ServerThread(QuicServer* server, const QuicSocketAddress& address);
~ServerThread() override;
@@ -71,14 +69,15 @@ class ServerThread : public base::SimpleThread {
base::WaitableEvent quit_; // Notified when the server should quit.
std::unique_ptr<QuicServer> server_;
- IPEndPoint address_;
+ QuicSocketAddress address_;
base::Lock port_lock_;
int port_;
bool initialized_;
- base::Lock scheduled_actions_lock_;
- std::deque<std::function<void()>> scheduled_actions_;
+ QuicMutex scheduled_actions_lock_;
+ std::deque<std::function<void()>> scheduled_actions_
+ GUARDED_BY(scheduled_actions_lock_);
DISALLOW_COPY_AND_ASSIGN(ServerThread);
};
diff --git a/chromium/net/tools/testserver/minica.py b/chromium/net/tools/testserver/minica.py
index d7f39a1d691..3395daf97ac 100644
--- a/chromium/net/tools/testserver/minica.py
+++ b/chromium/net/tools/testserver/minica.py
@@ -128,55 +128,84 @@ def Name(cn = None, c = None, o = None):
# The private key and root certificate name are hard coded here:
-# This is the private key
-KEY = RSA(0x00a71998f2930bfe73d031a87f133d2f378eeeeed52a77e44d0fc9ff6f07ff32cbf3da999de4ed65832afcb0807f98787506539d258a0ce3c2c77967653099a9034a9b115a876c39a8c4e4ed4acd0c64095946fb39eeeb47a0704dbb018acf48c3a1c4b895fc409fb4a340a986b1afc45519ab9eca47c30185c771c64aa5ecf07d,
- 3,
- 0x6f6665f70cb2a9a28acbc5aa0cd374cfb49f49e371a542de0a86aa4a0554cc87f7e71113edf399021ca875aaffbafaf8aee268c3b15ded2c84fb9a4375bbc6011d841e57833bc6f998d25daf6fa7f166b233e3e54a4bae7a5aaaba21431324967d5ff3e1d4f413827994262115ca54396e7068d0afa7af787a5782bc7040e6d3)
-
-# And the same thing in PEM format
-KEY_PEM = '''-----BEGIN RSA PRIVATE KEY-----
-MIICXAIBAAKBgQCnGZjykwv+c9AxqH8TPS83ju7u1Sp35E0Pyf9vB/8yy/PamZ3k
-7WWDKvywgH+YeHUGU50ligzjwsd5Z2UwmakDSpsRWodsOajE5O1KzQxkCVlG+znu
-60egcE27AYrPSMOhxLiV/ECftKNAqYaxr8RVGaueykfDAYXHccZKpezwfQIBAwKB
-gG9mZfcMsqmiisvFqgzTdM+0n0njcaVC3gqGqkoFVMyH9+cRE+3zmQIcqHWq/7r6
-+K7iaMOxXe0shPuaQ3W7xgEdhB5XgzvG+ZjSXa9vp/FmsjPj5UpLrnpaqrohQxMk
-ln1f8+HU9BOCeZQmIRXKVDlucGjQr6eveHpXgrxwQObTAkEA2wBAfuduw5G0/VfN
-Wx66D5fbPccfYFqLM5LuTimLmNqzK2gIKXckB2sm44gJZ6wVlumaB1CSNug2LNYx
-3cAjUwJBAMNUo1hbI8ugqqwI9kpxv9+2Heea4BlnXbS6tYF8pvkHMoliuxNbXmmB
-u4zNB5iZ6V0ZZ4nvtUNo2cGr/h/Lcu8CQQCSACr/RPSCYSNTj948vya1D+d+hL+V
-kbIiYfQ0G7Jl5yIc8AVw+hgE8hntBVuacrkPRmaviwwkms7IjsvpKsI3AkEAgjhs
-5ZIX3RXHHVtO3EvVP86+mmdAEO+TzdHOVlMZ+1ohsOx8t5I+8QEnszNaZbvw6Lua
-W/UjgkXmgR1UFTJMnwJBAKErmAw21/g3SST0a4wlyaGT/MbXL8Ouwnb5IOKQVe55
-CZdeVeSh6cJ4hAcQKfr2s1JaZTJFIBPGKAif5HqpydA=
------END RSA PRIVATE KEY-----
-'''
+# This is the root private key
+ROOT_KEY = RSA(0x00c1541fac63d3b969aa231a02cb2e0d9ee7b26724f136c121b2c28bdae5caa87733cc407ad83842ef20ec67d941b448a1ce3557cf5ddebf3c9bde8f36f253ee73e670d1c4c6631d1ddc0e39cbde09b833f66347ea379c3fa891d61a0ca005b38b0b2cad1058e3589c9f30600be81e4ff4ac220972c17b74f92f03d72b496f643543d0b27a5227f1efee13c138888b23cb101877b3b4dc091f0b3bb6fc3c792187b05ab38e97862f8af6156bcbfbb824385132c6741e6c65cfcd5f13142421a210b95185884c4866f3ea644dfb8006133d14e72a4704f3e700cf827ca5ffd2ef74c2ab6a5259ffff40f0f7f607891388f917fc9fc9e65742df1bfa0b322140bb65,
+ 65537,
+ 0x00980f2db66ef249e4954074a5fbdf663135363a3071554ac4d19079661bd5b179c890ffaa5fc4a8c8e3116e81104fd7cd049f2a48dd2165332bb9fad511f6f817cb09b3c45cf1fa25d13e9331099c8578c173c74dae9dc3e83784ba0a7216e9e8144af8786221b741c167d033ad47a245e4da04aa710a44aff5cdc480b48adbba3575d1315555690f081f9f69691e801e34c21240bcd3df9573ec5f9aa290c5ed19404fb911ab28b7680e0be086487273db72da6621f24d8c66197a5f1b7687efe1d9e3b6655af2891d4540482e1246ff5f62ce61b8b5dcb2c66ade6bb41e0bf071445fb8544aa0a489780f770a6f1031ee19347641794f4ad17354d579a9d061)
# Root certificate CN
-ISSUER_CN = "Testing CA"
+ROOT_CN = "Testing CA"
# All certificates are issued under this policy OID, in the Google arc:
CERT_POLICY_OID = asn1.OID([1, 3, 6, 1, 4, 1, 11129, 2, 4, 1])
# These result in the following root certificate:
# -----BEGIN CERTIFICATE-----
-# MIIBzTCCATagAwIBAgIBATANBgkqhkiG9w0BAQsFADAVMRMwEQYDVQQDEwpUZXN0aW5nIENBMB4X
-# DTEwMDEwMTA2MDAwMFoXDTMyMTIwMTA2MDAwMFowFTETMBEGA1UEAxMKVGVzdGluZyBDQTCBnTAN
-# BgkqhkiG9w0BAQEFAAOBiwAwgYcCgYEApxmY8pML/nPQMah/Ez0vN47u7tUqd+RND8n/bwf/Msvz
-# 2pmd5O1lgyr8sIB/mHh1BlOdJYoM48LHeWdlMJmpA0qbEVqHbDmoxOTtSs0MZAlZRvs57utHoHBN
-# uwGKz0jDocS4lfxAn7SjQKmGsa/EVRmrnspHwwGFx3HGSqXs8H0CAQOjLzAtMBIGA1UdEwEB/wQI
-# MAYBAf8CAQAwFwYDVR0gBBAwDjAMBgorBgEEAdZ5AgQBMA0GCSqGSIb3DQEBCwUAA4GBAHJJigXg
-# ArH/E9n3AilgivA58hawSRVqiTHHv7oAguDRrA4zC8IvsL6b/6LV7nA3KWM0OUSZSGE3zQb9UlB2
-# nNYsPMdv0Ls4GuOzVfy4bnQXqMWIflRw9L5Z5KH8Vu5U3ohoOUCfWN1sYMoeS9/22K9xtRsDPS+d
-# pQo7Q6ZoOo8o
+# MIIC1DCCAbygAwIBAgIBATANBgkqhkiG9w0BAQsFADAVMRMwEQYDVQQDEwpUZXN0
+# aW5nIENBMB4XDTEwMDEwMTA2MDAwMFoXDTMyMTIwMTA2MDAwMFowFTETMBEGA1UE
+# AxMKVGVzdGluZyBDQTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAMFU
+# H6xj07lpqiMaAssuDZ7nsmck8TbBIbLCi9rlyqh3M8xAetg4Qu8g7GfZQbRIoc41
+# V89d3r88m96PNvJT7nPmcNHExmMdHdwOOcveCbgz9mNH6jecP6iR1hoMoAWziwss
+# rRBY41icnzBgC+geT/SsIglywXt0+S8D1ytJb2Q1Q9CyelIn8e/uE8E4iIsjyxAY
+# d7O03AkfCzu2/Dx5IYewWrOOl4YvivYVa8v7uCQ4UTLGdB5sZc/NXxMUJCGiELlR
+# hYhMSGbz6mRN+4AGEz0U5ypHBPPnAM+CfKX/0u90wqtqUln//0Dw9/YHiROI+Rf8
+# n8nmV0LfG/oLMiFAu2UCAwEAAaMvMC0wEgYDVR0TAQH/BAgwBgEB/wIBATAXBgNV
+# HSAEEDAOMAwGCisGAQQB1nkCBAEwDQYJKoZIhvcNAQELBQADggEBADNrvoAyqAVm
+# bydPBBfLRqyH4DXt2vuMVmnSdnWnOxYiEezGmNSNiO1k1ZFBwVSsd+JHrT24lax9
+# kvU1yQDW//PBu3ijfZOCaIUleQiGXHMGfV4MjzgYbxpvHOvEUC6IXmYCsIEwcZgK
+# lrwnfJQ3MVU4hOgGTlOTWYPtCwvTsBObNRLdIs+ifMQiWmzPBlM8XeX4e5acDjTb
+# emcN4szU3EcgmCA0LvBIRI4F6NWpaIJl2WnLyMUDyKq4vjpRJOZkNwAC+525duDr
+# JFE4PKR2Lh53nJQIJv6mcTZQkX1mmw0yzqWxcGCoHACma3TgSwOHryvSopL+t26+
+# ZlQvP2ygwqY=
# -----END CERTIFICATE-----
# If you update any of the above, you can generate a new root by running this
# file as a script.
+INTERMEDIATE_KEY = RSA(0x00c661afcc659f88855a83ade8fb792dc13d0cf388b17bece9149cf0b8556d27b19101d081fb2a842d13a2ac95d8308ddd66783843ecc5806513959eb6b30dd69b2845d97e10d0bbbf653d686dc8828935022cc96f9e030b567157257d3d6526734080bb9727cee0d30f4209d5820e1d662f358fc789c0e9366d84f89adf1beb8d843f74e6f325876ac35d5c11691fcb296967c06edf69450c16bb2314c14599fe90725d5ec90f2db6698afae72bba0cfbf77967c7e8b49f2172f9381827c27ab7f9471c62bd8da4a6c657966ec1385cf41d739449835888f30d64971619dcd380408cd74f25c3be19833a92620c9cf710da67e15ac8cef69bc7e4e5e7f813c1ed,
+ 65537,
+ 0x77c5e2edf52d2cafd6c649e9b06aa9455226cfa26805fa337f4e81c7c94bedfb3721715208e2d28aa4a042b2f5a3db03212ad44dae564ffeb6a44efedf7c2b65e21aca056301a3591b36c82600394fbdc16268fc0adaabadb5207871f4ef6d17888a30b84240955cd889768681cf23d0de0fe88f008c8841643e341acd397e2d1104a23242e566088b7617c26ae8b48a85b6c9b7dc64ef1fa5e9b124ff8c1659a82d8225f28a820cc6ca07beff0354364c631a9142309fea1d8b054f6e00e23c54b493a21fcbe89a646b39d1acba5bc2ace9bba0252671d42a15202f3afccc912114d6c20eb3131e74289f2c744c5b39e7d3780fe21402ab1c3ae65854fee401)
+
+# Intermediate certificate CN
+INTERMEDIATE_CN = "Testing Intermediate CA"
+
+LEAF_KEY = RSA(0x00cd12d317b39cfbb160fb1dc9c9f0dc8fef3604dda4d8c557392ce1d616483713f78216cadbefd1c76ea0f3bbbe410e24b233b1b73583922b09314e249b2cfde1be0995e13f160fb630c10d447750da20ffaa4880006717feaa3e4db602e4f511b5cc312f770f44b037784effec62640f948aa189c3769f03bdd0e22a36ecfa5951f5577de195a4fba33c879b657968b79138fd7ab389a9968522f7389c6052be1ff78bc168d3ea961e132a044eba33ac07ead95367c7b815e91eca924d914fd0d811349b8bf500707ba71a43a2901a545f34e1792e72654f6649fab9716f4ba17379ee8042186bbba9b9bac416a60474cc60686f0e6e4b01259cc3cb5873edf9,
+ 65537,
+ 0x009c23e81bd4c30314743dded9646b82d408937db2f0afa7d9988be6cba59d886a287aa13605ad9c7117776efc94885de76cd3554da46e301d9a5b331f4613449edb9ddac36cd0345848d8c46c4bd880acbd5cfee48ee9efe813e16a33da124fd213348c8292494ac84d03ca4aabc5e25fc67ea32e0c6845fc884b01d8988768b8b931c41de49708dbcd5fcb61823f9a1f7507c6f364be4cb5a8cf24af4925997030dd4f67a0c9c6813401cc8b2f5d1971ee0022770239b7042fde8228c33942e9c0a0b18854cb1b5542be928338ab33ac936bbba174e55457007b16f36011dbb8f4258abe64e42b1cfa79803d30170b7ecf3e7c595d42003fff72591e07acd9cd)
+
+LEAF_KEY_PEM = '''-----BEGIN RSA PRIVATE KEY-----
+MIIEpQIBAAKCAQEAzRLTF7Oc+7Fg+x3JyfDcj+82BN2k2MVXOSzh1hZINxP3ghbK
+2+/Rx26g87u+QQ4ksjOxtzWDkisJMU4kmyz94b4JleE/Fg+2MMENRHdQ2iD/qkiA
+AGcX/qo+TbYC5PURtcwxL3cPRLA3eE7/7GJkD5SKoYnDdp8DvdDiKjbs+llR9Vd9
+4ZWk+6M8h5tleWi3kTj9erOJqZaFIvc4nGBSvh/3i8Fo0+qWHhMqBE66M6wH6tlT
+Z8e4FekeypJNkU/Q2BE0m4v1AHB7pxpDopAaVF804XkucmVPZkn6uXFvS6Fzee6A
+Qhhru6m5usQWpgR0zGBobw5uSwElnMPLWHPt+QIDAQABAoIBAQCcI+gb1MMDFHQ9
+3tlka4LUCJN9svCvp9mYi+bLpZ2Iaih6oTYFrZxxF3du/JSIXeds01VNpG4wHZpb
+Mx9GE0Se253aw2zQNFhI2MRsS9iArL1c/uSO6e/oE+FqM9oST9ITNIyCkklKyE0D
+ykqrxeJfxn6jLgxoRfyISwHYmIdouLkxxB3klwjbzV/LYYI/mh91B8bzZL5MtajP
+JK9JJZlwMN1PZ6DJxoE0AcyLL10Zce4AIncCObcEL96CKMM5QunAoLGIVMsbVUK+
+koM4qzOsk2u7oXTlVFcAexbzYBHbuPQlir5k5Csc+nmAPTAXC37PPnxZXUIAP/9y
+WR4HrNnNAoGBAPmOqTe7ntto6rDEsU1cKOJFKIZ7UVcSByyz8aLrvj1Rb2mkrNJU
+SdTqJvtqrvDXgO0HuGtFOzsZrRV9+XRPd2P0mP0uhfRiYGWT8hnILGyI2+7zlC/w
+HDtLEefelhtdOVKgUaLQXptSn7aGalUHghZKWjRNT5ah+U85MoI2ZkDbAoGBANJe
+KvrBBPSFLj+x2rsMhG+ksK0I6tivapVvSTtDV3ME1DvA/4BIMV/nIZyoH4AYI72c
+m/vD66+eCqh75cq5BzbVD63tR+ZRi/VdT1HJcl2IFXynk6eaBw8v7gpQyx6t3iSK
+lx/dIdpLt1BQuR4qI6x1wYp7Utn98soEkiFXzgq7AoGBAJTLBYPQXvgNBxlcPSaV
+016Nw4rjTe0vN43kwCbWjjf7LQV9BPnm/Zpv/cwboLDCnQE2gDOdNKKZPYS59pjt
+pI65UNpr+bxrR3RpEIlku2/+7br8ChfG/t4vdT6djTxFih8ErYf42t+bFNT8Mbv+
+3QYzULMsgU6bxo0A2meezbrPAoGBAK/IxmtQXP6iRxosWRUSCZxs5sFAgVVdh1el
+bXEa/Xj8IQhpZlbgfHmh3oFULzZPdZYcxm7jsQ7HpipRlZwHbtLPyNFSRFFd9PCr
+7vrttSYY77OBKC3V1G5JY8S07HYPXV/1ewDCPGZ3/I8dVQKyvap/n6FDGeFUhctv
+dFhuUZq/AoGAWLXlbcIl1cvOhfFJ5owohJhzh9oW9tlCtjV5/dlix2RaE5CtDZWS
+oMm4sQu9HiA8jLDP1MEEMRFPrPXdrZnxnSqVd1DgabSegD1/ZCb1QlWwQWkk5QU+
+wotPOMI33L50kZqUaDP+1XSL0Dyfo/pYpm4tYy/5QmP6WKXCtFUXybI=
+-----END RSA PRIVATE KEY-----
+'''
# Various OIDs
AIA_OCSP = asn1.OID([1, 3, 6, 1, 5, 5, 7, 48, 1])
+AIA_CA_ISSUERS = asn1.OID([1, 3, 6, 1, 5, 5, 7, 48, 2])
AUTHORITY_INFORMATION_ACCESS = asn1.OID([1, 3, 6, 1, 5, 5, 7, 1, 1])
BASIC_CONSTRAINTS = asn1.OID([2, 5, 29, 19])
CERT_POLICIES = asn1.OID([2, 5, 29, 32])
@@ -190,7 +219,8 @@ SHA256_WITH_RSA_ENCRYPTION = asn1.OID([1, 2, 840, 113549, 1, 1, 11])
def MakeCertificate(
- issuer_cn, subject_cn, serial, pubkey, privkey, ocsp_url = None):
+ issuer_cn, subject_cn, serial, pubkey, privkey, ocsp_url = None,
+ ca_issuers_url = None, is_ca=False, path_len=None):
'''MakeCertificate returns a DER encoded certificate, signed by privkey.'''
extensions = asn1.SEQUENCE([])
@@ -198,7 +228,7 @@ def MakeCertificate(
c = "XX"
o = "Testing Org"
- if issuer_cn == subject_cn:
+ if is_ca:
# Root certificate.
c = None
o = None
@@ -207,24 +237,33 @@ def MakeCertificate(
BASIC_CONSTRAINTS,
True,
asn1.OCTETSTRING(asn1.ToDER(asn1.SEQUENCE([
- True, # IsCA
- 0, # Path len
- ]))),
+ True, # IsCA
+ ] + ([path_len] if path_len is not None else []) # Path len
+ ))),
]))
- if ocsp_url is not None:
+ if ocsp_url is not None or ca_issuers_url is not None:
+ aia_entries = []
+ if ocsp_url is not None:
+ aia_entries.append(
+ asn1.SEQUENCE([
+ AIA_OCSP,
+ asn1.Raw(asn1.TagAndLength(0x86, len(ocsp_url)) + ocsp_url),
+ ]))
+ if ca_issuers_url is not None:
+ aia_entries.append(
+ asn1.SEQUENCE([
+ AIA_CA_ISSUERS,
+ asn1.Raw(asn1.TagAndLength(0x86,
+ len(ca_issuers_url)) + ca_issuers_url),
+ ]))
extensions.children.append(
asn1.SEQUENCE([
AUTHORITY_INFORMATION_ACCESS,
# There is implicitly a critical=False here. Since false is the default,
# encoding the value would be invalid DER.
- asn1.OCTETSTRING(asn1.ToDER(asn1.SEQUENCE([
- asn1.SEQUENCE([
- AIA_OCSP,
- asn1.Raw(asn1.TagAndLength(0x86, len(ocsp_url)) + ocsp_url),
- ]),
- ]))),
- ]))
+ asn1.OCTETSTRING(asn1.ToDER(asn1.SEQUENCE(aia_entries))),
+ ]))
extensions.children.append(
asn1.SEQUENCE([
@@ -401,8 +440,8 @@ def GenerateCertKeyAndOCSP(subject = "127.0.0.1",
if serial == 0:
serial = RandomNumber(16)
- cert_der = MakeCertificate(ISSUER_CN, bytes(subject), serial, KEY, KEY,
- bytes(ocsp_url))
+ cert_der = MakeCertificate(ROOT_CN, bytes(subject), serial, LEAF_KEY,
+ ROOT_KEY, bytes(ocsp_url))
cert_pem = DERToPEM(cert_der)
ocsp_der = None
@@ -424,7 +463,7 @@ def GenerateCertKeyAndOCSP(subject = "127.0.0.1",
SHA256_WITH_RSA_ENCRYPTION,
None,
]),
- asn1.BitString(KEY.Sign(invalid_data)),
+ asn1.BitString(ROOT_KEY.Sign(invalid_data)),
])
resp = asn1.SEQUENCE([
asn1.ENUMERATED(0),
@@ -436,9 +475,31 @@ def GenerateCertKeyAndOCSP(subject = "127.0.0.1",
ocsp_der = asn1.ToDER(resp)
else:
ocsp_der = MakeOCSPResponse(
- ISSUER_CN, KEY, serial, ocsp_states, ocsp_dates, ocsp_produced)
+ ROOT_CN, ROOT_KEY, serial, ocsp_states, ocsp_dates, ocsp_produced)
+
+ return (cert_pem + LEAF_KEY_PEM, ocsp_der)
+
+
+def GenerateCertKeyAndIntermediate(subject, ca_issuers_url, serial=0):
+ '''Returns a (cert_and_key_pem, intermediate_cert_pem) where:
+ * cert_and_key_pem contains a certificate and private key in PEM format
+ with the given subject common name and caIssuers URL.
+ * intermediate_cert_pem contains a PEM encoded certificate that signed
+ cert_and_key_pem and was signed by ocsp-test-root.pem.'''
+ if serial == 0:
+ serial = RandomNumber(16)
+ target_cert_der = MakeCertificate(INTERMEDIATE_CN, bytes(subject), serial,
+ LEAF_KEY, INTERMEDIATE_KEY,
+ ca_issuers_url=bytes(ca_issuers_url))
+ target_cert_pem = DERToPEM(target_cert_der)
+
+ intermediate_serial = RandomNumber(16)
+ intermediate_cert_der = MakeCertificate(ROOT_CN, INTERMEDIATE_CN,
+ intermediate_serial,
+ INTERMEDIATE_KEY, ROOT_KEY,
+ is_ca=True)
- return (cert_pem + KEY_PEM, ocsp_der)
+ return target_cert_pem + LEAF_KEY_PEM, intermediate_cert_der
if __name__ == '__main__':
@@ -450,7 +511,8 @@ if __name__ == '__main__':
'..', 'data', 'ssl', 'scripts'))
import crlsetutil
- der_root = MakeCertificate(ISSUER_CN, ISSUER_CN, 1, KEY, KEY, None)
+ der_root = MakeCertificate(ROOT_CN, ROOT_CN, 1, ROOT_KEY, ROOT_KEY,
+ is_ca=True, path_len=1)
print 'ocsp-test-root.pem:'
print DERToPEM(der_root)
diff --git a/chromium/net/tools/testserver/testserver.py b/chromium/net/tools/testserver/testserver.py
index e8241cb6e38..8fd723629c4 100755
--- a/chromium/net/tools/testserver/testserver.py
+++ b/chromium/net/tools/testserver/testserver.py
@@ -1683,13 +1683,17 @@ class TestPageHandler(testserver_base.BasePageHandler):
class OCSPHandler(testserver_base.BasePageHandler):
def __init__(self, request, client_address, socket_server):
- handlers = [self.OCSPResponse]
+ handlers = [self.OCSPResponse, self.CaIssuersResponse]
self.ocsp_response = socket_server.ocsp_response
+ self.ca_issuers_response = socket_server.ca_issuers_response
testserver_base.BasePageHandler.__init__(self, request, client_address,
socket_server, [], handlers, [],
handlers, [])
def OCSPResponse(self):
+ if not self._ShouldHandleRequest("/ocsp"):
+ return False
+ print 'handling ocsp request'
self.send_response(200)
self.send_header('Content-Type', 'application/ocsp-response')
self.send_header('Content-Length', str(len(self.ocsp_response)))
@@ -1697,6 +1701,17 @@ class OCSPHandler(testserver_base.BasePageHandler):
self.wfile.write(self.ocsp_response)
+ def CaIssuersResponse(self):
+ if not self._ShouldHandleRequest("/ca_issuers"):
+ return False
+ print 'handling ca_issuers request'
+ self.send_response(200)
+ self.send_header('Content-Type', 'application/pkix-cert')
+ self.send_header('Content-Length', str(len(self.ca_issuers_response)))
+ self.end_headers()
+
+ self.wfile.write(self.ca_issuers_response)
+
class TCPEchoHandler(SocketServer.BaseRequestHandler):
"""The RequestHandler class for TCP echo server.
@@ -1898,6 +1913,20 @@ class ServerRunner(testserver_base.TestServerRunner):
'specified server cert file not found: ' +
self.options.cert_and_key_file + ' exiting...')
pem_cert_and_key = file(self.options.cert_and_key_file, 'r').read()
+ elif self.options.aia_intermediate:
+ self.__ocsp_server = OCSPServer((host, 0), OCSPHandler)
+ print ('AIA server started on %s:%d...' %
+ (host, self.__ocsp_server.server_port))
+
+ (pem_cert_and_key, intermediate_cert_der) = \
+ minica.GenerateCertKeyAndIntermediate(
+ subject = "127.0.0.1",
+ ca_issuers_url = ("http://%s:%d/ca_issuers" %
+ (host, self.__ocsp_server.server_port)),
+ serial = self.options.cert_serial)
+
+ self.__ocsp_server.ocsp_response = None
+ self.__ocsp_server.ca_issuers_response = intermediate_cert_der
else:
# generate a new certificate and run an OCSP server for it.
self.__ocsp_server = OCSPServer((host, 0), OCSPHandler)
@@ -1976,6 +2005,7 @@ class ServerRunner(testserver_base.TestServerRunner):
self.__ocsp_server.ocsp_response = '30030a0103'.decode('hex')
else:
self.__ocsp_server.ocsp_response = ocsp_der
+ self.__ocsp_server.ca_issuers_response = None
for ca_cert in self.options.ssl_client_ca:
if not os.path.isfile(ca_cert):
@@ -2137,6 +2167,11 @@ class ServerRunner(testserver_base.TestServerRunner):
'path to the file containing the certificate '
'and private key for the server in PEM '
'format')
+ self.option_parser.add_option('--aia-intermediate', action='store_true',
+ dest='aia_intermediate',
+ help='generate a certificate chain that '
+ 'requires AIA cert fetching, and run a '
+ 'server to respond to the AIA request.')
self.option_parser.add_option('--ocsp', dest='ocsp', default='ok',
help='The type of OCSP response generated '
'for the automatically generated '
diff --git a/chromium/net/tools/testserver/testserver.pydeps b/chromium/net/tools/testserver/testserver.pydeps
index 3a7da8c8e8b..b3b97fa0e1e 100644
--- a/chromium/net/tools/testserver/testserver.pydeps
+++ b/chromium/net/tools/testserver/testserver.pydeps
@@ -1,5 +1,5 @@
# Generated by running:
-# build/print_python_deps.py --root net/tools/testserver --output net/tools/testserver/testserver.pydeps net/tools/testserver/testserver.py
+# build/print_python_deps.py --root net/tools/testserver --output net/tools/testserver/testserver.pydeps --whitelist third_party/tlslite/tlslite/utils net/tools/testserver/testserver.py
../../../third_party/pyftpdlib/src/pyftpdlib/__init__.py
../../../third_party/pyftpdlib/src/pyftpdlib/ftpserver.py
../../../third_party/pywebsocket/src/mod_pywebsocket/__init__.py
@@ -53,6 +53,7 @@
../../../third_party/tlslite/tlslite/utils/codec.py
../../../third_party/tlslite/tlslite/utils/compat.py
../../../third_party/tlslite/tlslite/utils/cryptomath.py
+../../../third_party/tlslite/tlslite/utils/datefuncs.py
../../../third_party/tlslite/tlslite/utils/keyfactory.py
../../../third_party/tlslite/tlslite/utils/openssl_aes.py
../../../third_party/tlslite/tlslite/utils/openssl_rc4.py
diff --git a/chromium/net/url_request/http_user_agent_settings.h b/chromium/net/url_request/http_user_agent_settings.h
index 54bdfaccbc6..487f235c2e2 100644
--- a/chromium/net/url_request/http_user_agent_settings.h
+++ b/chromium/net/url_request/http_user_agent_settings.h
@@ -10,8 +10,6 @@
#include "base/macros.h"
#include "net/base/net_export.h"
-class GURL;
-
namespace net {
// The interface used by HTTP jobs to retrieve HTTP Accept-Language
@@ -34,4 +32,3 @@ class NET_EXPORT HttpUserAgentSettings {
} // namespace net
#endif // NET_URL_REQUEST_HTTP_USER_AGENT_SETTINGS_H_
-
diff --git a/chromium/net/url_request/sdch_dictionary_fetcher.h b/chromium/net/url_request/sdch_dictionary_fetcher.h
index 8c622b6aef6..8096b6ac1b8 100644
--- a/chromium/net/url_request/sdch_dictionary_fetcher.h
+++ b/chromium/net/url_request/sdch_dictionary_fetcher.h
@@ -27,7 +27,6 @@ namespace net {
class NetLogWithSource;
class URLRequest;
-class URLRequestThrottlerEntryInterface;
// This class is used by embedder SDCH policy object to fetch
// dictionaries. It queues requests for dictionaries and dispatches
diff --git a/chromium/net/url_request/static_http_user_agent_settings.cc b/chromium/net/url_request/static_http_user_agent_settings.cc
index dd74f965eb3..84f82c46056 100644
--- a/chromium/net/url_request/static_http_user_agent_settings.cc
+++ b/chromium/net/url_request/static_http_user_agent_settings.cc
@@ -25,4 +25,3 @@ std::string StaticHttpUserAgentSettings::GetUserAgent() const {
}
} // namespace net
-
diff --git a/chromium/net/url_request/static_http_user_agent_settings.h b/chromium/net/url_request/static_http_user_agent_settings.h
index 991af6af688..f6d90bdf758 100644
--- a/chromium/net/url_request/static_http_user_agent_settings.h
+++ b/chromium/net/url_request/static_http_user_agent_settings.h
@@ -36,4 +36,3 @@ class NET_EXPORT StaticHttpUserAgentSettings : public HttpUserAgentSettings {
} // namespace net
#endif // NET_URL_REQUEST_STATIC_HTTP_USER_AGENT_SETTINGS_H_
-
diff --git a/chromium/net/url_request/url_fetcher.h b/chromium/net/url_request/url_fetcher.h
index 725cf66afa2..7ac195432c7 100644
--- a/chromium/net/url_request/url_fetcher.h
+++ b/chromium/net/url_request/url_fetcher.h
@@ -32,7 +32,6 @@ class Origin;
namespace net {
class HostPortPair;
-class HttpRequestHeaders;
class HttpResponseHeaders;
class URLFetcherDelegate;
class URLFetcherResponseWriter;
@@ -68,8 +67,8 @@ class URLRequestStatus;
// the URLFetcher instance. If the URLFetcher instance is destroyed before the
// callback happens, the fetch will be canceled and no callback will occur.
//
-// You may create the URLFetcher instance on any thread; OnURLFetchComplete()
-// will be called back on the same thread you use to create the instance.
+// You may create the URLFetcher instance on any sequence; OnURLFetchComplete()
+// will be called back on the same sequence you use to create the instance.
//
//
// NOTE: By default URLFetcher requests are NOT intercepted, except when
diff --git a/chromium/net/url_request/url_fetcher_core.cc b/chromium/net/url_request/url_fetcher_core.cc
index e5ae45dc258..2a7a4d28998 100644
--- a/chromium/net/url_request/url_fetcher_core.cc
+++ b/chromium/net/url_request/url_fetcher_core.cc
@@ -14,7 +14,7 @@
#include "base/sequenced_task_runner.h"
#include "base/single_thread_task_runner.h"
#include "base/stl_util.h"
-#include "base/threading/thread_task_runner_handle.h"
+#include "base/threading/sequenced_task_runner_handle.h"
#include "base/tracked_objects.h"
#include "net/base/elements_upload_data_stream.h"
#include "net/base/io_buffer.h"
@@ -79,7 +79,7 @@ URLFetcherCore::URLFetcherCore(URLFetcher* fetcher,
original_url_(original_url),
request_type_(request_type),
delegate_(d),
- delegate_task_runner_(base::ThreadTaskRunnerHandle::Get()),
+ delegate_task_runner_(base::SequencedTaskRunnerHandle::Get()),
load_flags_(LOAD_NORMAL),
response_code_(URLFetcher::RESPONSE_CODE_INVALID),
buffer_(new IOBuffer(kBufferSize)),
@@ -109,7 +109,7 @@ URLFetcherCore::URLFetcherCore(URLFetcher* fetcher,
}
void URLFetcherCore::Start() {
- DCHECK(delegate_task_runner_.get());
+ DCHECK(delegate_task_runner_);
DCHECK(request_context_getter_.get()) << "We need an URLRequestContext!";
if (network_task_runner_.get()) {
DCHECK_EQ(network_task_runner_,
@@ -124,8 +124,8 @@ void URLFetcherCore::Start() {
}
void URLFetcherCore::Stop() {
- if (delegate_task_runner_.get()) // May be NULL in tests.
- DCHECK(delegate_task_runner_->BelongsToCurrentThread());
+ if (delegate_task_runner_) // May be NULL in tests.
+ DCHECK(delegate_task_runner_->RunsTasksOnCurrentThread());
delegate_ = NULL;
fetcher_ = NULL;
@@ -204,7 +204,7 @@ void URLFetcherCore::SetChunkedUpload(const std::string& content_type) {
void URLFetcherCore::AppendChunkToUpload(const std::string& content,
bool is_last_chunk) {
- DCHECK(delegate_task_runner_.get());
+ DCHECK(delegate_task_runner_);
DCHECK(network_task_runner_.get());
DCHECK(is_chunked_upload_);
network_task_runner_->PostTask(
@@ -289,21 +289,21 @@ void URLFetcherCore::SetAutomaticallyRetryOnNetworkChanges(int max_retries) {
void URLFetcherCore::SaveResponseToFileAtPath(
const base::FilePath& file_path,
scoped_refptr<base::SequencedTaskRunner> file_task_runner) {
- DCHECK(delegate_task_runner_->BelongsToCurrentThread());
+ DCHECK(delegate_task_runner_->RunsTasksOnCurrentThread());
SaveResponseWithWriter(std::unique_ptr<URLFetcherResponseWriter>(
new URLFetcherFileWriter(file_task_runner, file_path)));
}
void URLFetcherCore::SaveResponseToTemporaryFile(
scoped_refptr<base::SequencedTaskRunner> file_task_runner) {
- DCHECK(delegate_task_runner_->BelongsToCurrentThread());
+ DCHECK(delegate_task_runner_->RunsTasksOnCurrentThread());
SaveResponseWithWriter(std::unique_ptr<URLFetcherResponseWriter>(
new URLFetcherFileWriter(file_task_runner, base::FilePath())));
}
void URLFetcherCore::SaveResponseWithWriter(
std::unique_ptr<URLFetcherResponseWriter> response_writer) {
- DCHECK(delegate_task_runner_->BelongsToCurrentThread());
+ DCHECK(delegate_task_runner_->RunsTasksOnCurrentThread());
response_writer_ = std::move(response_writer);
}
@@ -351,7 +351,7 @@ int URLFetcherCore::GetResponseCode() const {
}
void URLFetcherCore::ReceivedContentWasMalformed() {
- DCHECK(delegate_task_runner_->BelongsToCurrentThread());
+ DCHECK(delegate_task_runner_->RunsTasksOnCurrentThread());
if (network_task_runner_.get()) {
network_task_runner_->PostTask(
FROM_HERE, base::Bind(&URLFetcherCore::NotifyMalformedContent, this));
@@ -373,7 +373,7 @@ bool URLFetcherCore::GetResponseAsString(
bool URLFetcherCore::GetResponseAsFilePath(bool take_ownership,
base::FilePath* out_response_path) {
- DCHECK(delegate_task_runner_->BelongsToCurrentThread());
+ DCHECK(delegate_task_runner_->RunsTasksOnCurrentThread());
URLFetcherFileWriter* file_writer =
response_writer_ ? response_writer_->AsFileWriter() : NULL;
@@ -670,7 +670,7 @@ void URLFetcherCore::StartURLRequestWhenAppropriate() {
original_url_throttler_entry_->ReserveSendingTimeForNextRequest(
GetBackoffReleaseTime());
if (delay != 0) {
- base::ThreadTaskRunnerHandle::Get()->PostDelayedTask(
+ network_task_runner_->PostDelayedTask(
FROM_HERE, base::Bind(&URLFetcherCore::StartURLRequest, this),
base::TimeDelta::FromMilliseconds(delay));
return;
@@ -710,7 +710,7 @@ void URLFetcherCore::CancelURLRequest(int error) {
void URLFetcherCore::OnCompletedURLRequest(
base::TimeDelta backoff_delay) {
- DCHECK(delegate_task_runner_->BelongsToCurrentThread());
+ DCHECK(delegate_task_runner_->RunsTasksOnCurrentThread());
// Save the status and backoff_delay so that delegates can read it.
if (delegate_) {
@@ -720,7 +720,7 @@ void URLFetcherCore::OnCompletedURLRequest(
}
void URLFetcherCore::InformDelegateFetchIsComplete() {
- DCHECK(delegate_task_runner_->BelongsToCurrentThread());
+ DCHECK(delegate_task_runner_->RunsTasksOnCurrentThread());
if (delegate_)
delegate_->OnURLFetchComplete(fetcher_);
}
@@ -911,16 +911,16 @@ void URLFetcherCore::InformDelegateUploadProgress() {
delegate_task_runner_->PostTask(
FROM_HERE,
base::Bind(
- &URLFetcherCore::InformDelegateUploadProgressInDelegateThread,
+ &URLFetcherCore::InformDelegateUploadProgressInDelegateSequence,
this, current, total));
}
}
}
-void URLFetcherCore::InformDelegateUploadProgressInDelegateThread(
+void URLFetcherCore::InformDelegateUploadProgressInDelegateSequence(
int64_t current,
int64_t total) {
- DCHECK(delegate_task_runner_->BelongsToCurrentThread());
+ DCHECK(delegate_task_runner_->RunsTasksOnCurrentThread());
if (delegate_)
delegate_->OnURLFetchUploadProgress(fetcher_, current, total);
}
@@ -936,16 +936,16 @@ void URLFetcherCore::InformDelegateDownloadProgress() {
delegate_task_runner_->PostTask(
FROM_HERE,
base::Bind(
- &URLFetcherCore::InformDelegateDownloadProgressInDelegateThread, this,
- current_response_bytes_, total_response_bytes_,
+ &URLFetcherCore::InformDelegateDownloadProgressInDelegateSequence,
+ this, current_response_bytes_, total_response_bytes_,
request_->GetTotalReceivedBytes()));
}
-void URLFetcherCore::InformDelegateDownloadProgressInDelegateThread(
+void URLFetcherCore::InformDelegateDownloadProgressInDelegateSequence(
int64_t current,
int64_t total,
int64_t current_network_bytes) {
- DCHECK(delegate_task_runner_->BelongsToCurrentThread());
+ DCHECK(delegate_task_runner_->RunsTasksOnCurrentThread());
if (delegate_)
delegate_->OnURLFetchDownloadProgress(fetcher_, current, total,
current_network_bytes);
diff --git a/chromium/net/url_request/url_fetcher_core.h b/chromium/net/url_request/url_fetcher_core.h
index 704697a1352..570c0f8e414 100644
--- a/chromium/net/url_request/url_fetcher_core.h
+++ b/chromium/net/url_request/url_fetcher_core.h
@@ -27,6 +27,7 @@
#include "url/gurl.h"
namespace base {
+class SequencedTaskRunner;
class SingleThreadTaskRunner;
} // namespace base
@@ -216,10 +217,10 @@ class URLFetcherCore : public base::RefCountedThreadSafe<URLFetcherCore>,
// Notify Delegate about the progress of upload/download.
void InformDelegateUploadProgress();
- void InformDelegateUploadProgressInDelegateThread(int64_t current,
- int64_t total);
+ void InformDelegateUploadProgressInDelegateSequence(int64_t current,
+ int64_t total);
void InformDelegateDownloadProgress();
- void InformDelegateDownloadProgressInDelegateThread(
+ void InformDelegateDownloadProgressInDelegateSequence(
int64_t current,
int64_t total,
int64_t current_network_bytes);
@@ -233,8 +234,8 @@ class URLFetcherCore : public base::RefCountedThreadSafe<URLFetcherCore>,
URLFetcher::RequestType request_type_; // What type of request is this?
URLRequestStatus status_; // Status of the request
URLFetcherDelegate* delegate_; // Object to notify on completion
- // Task runner for the creating thread. Used to interact with the delegate.
- scoped_refptr<base::SingleThreadTaskRunner> delegate_task_runner_;
+ // Task runner for the creating sequence. Used to interact with the delegate.
+ const scoped_refptr<base::SequencedTaskRunner> delegate_task_runner_;
// Task runner for network operations.
scoped_refptr<base::SingleThreadTaskRunner> network_task_runner_;
// Task runner for upload file access.
diff --git a/chromium/net/url_request/url_fetcher_impl_unittest.cc b/chromium/net/url_request/url_fetcher_impl_unittest.cc
index d48f74987de..62777bfa014 100644
--- a/chromium/net/url_request/url_fetcher_impl_unittest.cc
+++ b/chromium/net/url_request/url_fetcher_impl_unittest.cc
@@ -25,6 +25,8 @@
#include "base/strings/string_util.h"
#include "base/strings/stringprintf.h"
#include "base/synchronization/waitable_event.h"
+#include "base/task_scheduler/post_task.h"
+#include "base/test/scoped_task_scheduler.h"
#include "base/test/test_timeouts.h"
#include "base/threading/platform_thread.h"
#include "base/threading/thread.h"
@@ -515,6 +517,33 @@ TEST_F(URLFetcherTest, DifferentThreadsTest) {
EXPECT_EQ(kDefaultResponseBody, data);
}
+// Create the fetcher from a sequenced (not single-threaded) task. Verify that
+// the expected response is received.
+TEST_F(URLFetcherTest, SequencedTaskTest) {
+ base::test::ScopedTaskScheduler scoped_task_scheduler(
+ base::MessageLoop::current());
+ auto sequenced_task_runner =
+ base::CreateSequencedTaskRunnerWithTraits(base::TaskTraits());
+
+ auto delegate = base::MakeUnique<WaitingURLFetcherDelegate>();
+ sequenced_task_runner->PostTask(
+ FROM_HERE, base::Bind(&WaitingURLFetcherDelegate::CreateFetcher,
+ base::Unretained(delegate.get()),
+ test_server_->GetURL(kDefaultResponsePath),
+ URLFetcher::GET, CreateCrossThreadContextGetter()));
+ base::RunLoop().RunUntilIdle();
+ delegate->StartFetcherAndWait();
+
+ EXPECT_TRUE(delegate->fetcher()->GetStatus().is_success());
+ EXPECT_EQ(200, delegate->fetcher()->GetResponseCode());
+ std::string data;
+ ASSERT_TRUE(delegate->fetcher()->GetResponseAsString(&data));
+ EXPECT_EQ(kDefaultResponseBody, data);
+
+ sequenced_task_runner->DeleteSoon(FROM_HERE, delegate.release());
+ base::RunLoop().RunUntilIdle();
+}
+
// Tests to make sure CancelAll() will successfully cancel existing URLFetchers.
TEST_F(URLFetcherTest, CancelAll) {
EXPECT_EQ(0, GetNumFetcherCores());
diff --git a/chromium/net/url_request/url_fetcher_response_writer.h b/chromium/net/url_request/url_fetcher_response_writer.h
index 7b644b622e1..972da0e7222 100644
--- a/chromium/net/url_request/url_fetcher_response_writer.h
+++ b/chromium/net/url_request/url_fetcher_response_writer.h
@@ -21,7 +21,6 @@ class SequencedTaskRunner;
namespace net {
-class DrainableIOBuffer;
class FileStream;
class IOBuffer;
class URLFetcherFileWriter;
diff --git a/chromium/net/url_request/url_request.cc b/chromium/net/url_request/url_request.cc
index eb4be23b475..ec9d0015246 100644
--- a/chromium/net/url_request/url_request.cc
+++ b/chromium/net/url_request/url_request.cc
@@ -294,7 +294,7 @@ std::unique_ptr<base::Value> URLRequest::GetStateAsValue() const {
if (!load_state.param.empty())
dict->SetString("load_state_param", load_state.param);
if (!blocked_by_.empty())
- dict->SetString("delegate_info", blocked_by_);
+ dict->SetString("delegate_blocked_by", blocked_by_);
dict->SetString("method", method_);
dict->SetBoolean("has_upload", has_upload());
@@ -335,8 +335,9 @@ void URLRequest::LogBlockedBy(const char* blocked_by) {
blocked_by_ = blocked_by;
use_blocked_by_as_load_param_ = false;
- net_log_.BeginEvent(NetLogEventType::DELEGATE_INFO,
- NetLog::StringCallback("delegate_info", &blocked_by_));
+ net_log_.BeginEvent(
+ NetLogEventType::DELEGATE_INFO,
+ NetLog::StringCallback("delegate_blocked_by", &blocked_by_));
}
void URLRequest::LogAndReportBlockedBy(const char* source) {
@@ -579,12 +580,15 @@ URLRequest::URLRequest(const GURL& url,
base::Unretained(this))),
has_notified_completion_(false),
received_response_content_length_(0),
- creation_time_(base::TimeTicks::Now()) {
+ creation_time_(base::TimeTicks::Now()),
+ raw_header_size_(0) {
// Sanity check out environment.
DCHECK(base::ThreadTaskRunnerHandle::IsSet());
context->url_requests()->insert(this);
- net_log_.BeginEvent(NetLogEventType::REQUEST_ALIVE);
+ net_log_.BeginEvent(
+ NetLogEventType::REQUEST_ALIVE,
+ base::Bind(&NetLogURLRequestConstructorCallback, &url, priority_));
}
void URLRequest::BeforeRequestComplete(int error) {
@@ -627,7 +631,6 @@ void URLRequest::StartJob(URLRequestJob* job) {
net_log_.BeginEvent(
NetLogEventType::URL_REQUEST_START_JOB,
base::Bind(&NetLogURLRequestStartCallback, &url(), &method_, load_flags_,
- priority_,
upload_data_stream_ ? upload_data_stream_->identifier() : -1));
job_.reset(job);
@@ -762,14 +765,14 @@ int URLRequest::Read(IOBuffer* dest, int dest_size) {
}
int rv = job_->Read(dest, dest_size);
- if (rv == ERR_IO_PENDING)
+ if (rv == ERR_IO_PENDING) {
set_status(URLRequestStatus::FromError(ERR_IO_PENDING));
+ } else if (rv <= 0) {
+ NotifyRequestCompleted();
+ }
// If rv is not 0 or actual bytes read, the status cannot be success.
DCHECK(rv >= 0 || status_.status() != URLRequestStatus::SUCCESS);
-
- if (rv == 0 && status_.is_success())
- NotifyRequestCompleted();
return rv;
}
@@ -1024,12 +1027,11 @@ void URLRequest::SetPriority(RequestPriority priority) {
return;
priority_ = priority;
- if (job_.get()) {
- net_log_.AddEvent(
- NetLogEventType::URL_REQUEST_SET_PRIORITY,
- NetLog::StringCallback("priority", RequestPriorityToString(priority_)));
+ net_log_.AddEvent(
+ NetLogEventType::URL_REQUEST_SET_PRIORITY,
+ NetLog::StringCallback("priority", RequestPriorityToString(priority_)));
+ if (job_.get())
job_->SetPriority(priority_);
- }
}
void URLRequest::NotifyAuthRequired(AuthChallengeInfo* auth_info) {
diff --git a/chromium/net/url_request/url_request.h b/chromium/net/url_request/url_request.h
index 9ef191c98e4..e1406f33633 100644
--- a/chromium/net/url_request/url_request.h
+++ b/chromium/net/url_request/url_request.h
@@ -40,10 +40,6 @@
namespace base {
class Value;
-
-namespace debug {
-class StackTrace;
-} // namespace debug
} // namespace base
namespace net {
diff --git a/chromium/net/url_request/url_request_context.cc b/chromium/net/url_request/url_request_context.cc
index 1e3dc4ead60..cefa7b9db25 100644
--- a/chromium/net/url_request/url_request_context.cc
+++ b/chromium/net/url_request/url_request_context.cc
@@ -8,9 +8,16 @@
#include "base/debug/alias.h"
#include "base/memory/ptr_util.h"
#include "base/strings/string_util.h"
+#include "base/strings/stringprintf.h"
+#include "base/threading/thread_task_runner_handle.h"
+#include "base/trace_event/memory_allocator_dump.h"
+#include "base/trace_event/memory_dump_manager.h"
+#include "base/trace_event/process_memory_dump.h"
+#include "net/base/sdch_manager.h"
#include "net/cookies/cookie_store.h"
#include "net/dns/host_resolver.h"
#include "net/http/http_transaction_factory.h"
+#include "net/socket/ssl_client_socket_impl.h"
#include "net/url_request/http_user_agent_settings.h"
#include "net/url_request/url_request.h"
@@ -37,10 +44,16 @@ URLRequestContext::URLRequestContext()
sdch_manager_(nullptr),
network_quality_estimator_(nullptr),
url_requests_(new std::set<const URLRequest*>),
- enable_brotli_(false) {}
+ enable_brotli_(false),
+ check_cleartext_permitted_(false) {
+ base::trace_event::MemoryDumpManager::GetInstance()->RegisterDumpProvider(
+ this, "URLRequestContext", base::ThreadTaskRunnerHandle::Get());
+}
URLRequestContext::~URLRequestContext() {
AssertNoURLRequests();
+ base::trace_event::MemoryDumpManager::GetInstance()->UnregisterDumpProvider(
+ this);
}
void URLRequestContext::CopyFrom(const URLRequestContext* other) {
@@ -66,6 +79,7 @@ void URLRequestContext::CopyFrom(const URLRequestContext* other) {
set_http_user_agent_settings(other->http_user_agent_settings_);
set_network_quality_estimator(other->network_quality_estimator_);
set_enable_brotli(other->enable_brotli_);
+ set_check_cleartext_permitted(other->check_cleartext_permitted_);
}
const HttpNetworkSession::Params* URLRequestContext::GetNetworkSessionParams(
@@ -108,4 +122,26 @@ void URLRequestContext::AssertNoURLRequests() const {
}
}
+bool URLRequestContext::OnMemoryDump(
+ const base::trace_event::MemoryDumpArgs& args,
+ base::trace_event::ProcessMemoryDump* pmd) {
+ if (name_.empty())
+ name_ = "unknown";
+ base::trace_event::MemoryAllocatorDump* dump = pmd->CreateAllocatorDump(
+ base::StringPrintf("net/url_request_context/%s_%p", name_.c_str(), this));
+ dump->AddScalar(base::trace_event::MemoryAllocatorDump::kNameObjectCount,
+ base::trace_event::MemoryAllocatorDump::kUnitsObjects,
+ url_requests_->size());
+ HttpTransactionFactory* transaction_factory = http_transaction_factory();
+ if (transaction_factory) {
+ HttpNetworkSession* network_session = transaction_factory->GetSession();
+ if (network_session)
+ network_session->DumpMemoryStats(pmd, dump->absolute_name());
+ }
+ SSLClientSocketImpl::DumpSSLClientSessionMemoryStats(pmd);
+ if (sdch_manager_)
+ sdch_manager_->DumpMemoryStats(pmd, dump->absolute_name());
+ return true;
+}
+
} // namespace net
diff --git a/chromium/net/url_request/url_request_context.h b/chromium/net/url_request/url_request_context.h
index 0158d9aca17..8aeb1e01205 100644
--- a/chromium/net/url_request/url_request_context.h
+++ b/chromium/net/url_request/url_request_context.h
@@ -16,6 +16,7 @@
#include "base/memory/ref_counted.h"
#include "base/memory/weak_ptr.h"
#include "base/threading/non_thread_safe.h"
+#include "base/trace_event/memory_dump_provider.h"
#include "net/base/net_export.h"
#include "net/base/request_priority.h"
#include "net/http/http_network_session.h"
@@ -24,6 +25,12 @@
#include "net/ssl/ssl_config_service.h"
#include "net/url_request/url_request.h"
+namespace base {
+namespace trace_event {
+class ProcessMemoryDump;
+}
+}
+
namespace net {
class CertVerifier;
class ChannelIDService;
@@ -51,10 +58,11 @@ class URLRequestThrottlerManager;
// URLRequestContext rather than creating a new one, as guaranteeing that the
// URLRequestContext is destroyed before its members can be difficult.
class NET_EXPORT URLRequestContext
- : NON_EXPORTED_BASE(public base::NonThreadSafe) {
+ : NON_EXPORTED_BASE(public base::NonThreadSafe),
+ public base::trace_event::MemoryDumpProvider {
public:
URLRequestContext();
- virtual ~URLRequestContext();
+ ~URLRequestContext() override;
// Copies the state from |other| into this context.
void CopyFrom(const URLRequestContext* other);
@@ -230,6 +238,24 @@ class NET_EXPORT URLRequestContext
bool enable_brotli() const { return enable_brotli_; }
+ // Sets the |check_cleartext_permitted| flag, which controls whether to check
+ // system policy before allowing a cleartext http or ws request.
+ void set_check_cleartext_permitted(bool check_cleartext_permitted) {
+ check_cleartext_permitted_ = check_cleartext_permitted;
+ }
+
+ // Returns current value of the |check_cleartext_permitted| flag.
+ bool check_cleartext_permitted() const { return check_cleartext_permitted_; }
+
+ // Sets a name for this URLRequestContext. Currently the name is used in
+ // MemoryDumpProvier to annotate memory usage. The name does not need to be
+ // unique.
+ void set_name(const std::string& name) { name_ = name; }
+
+ // MemoryDumpProvider implementation:
+ bool OnMemoryDump(const base::trace_event::MemoryDumpArgs& args,
+ base::trace_event::ProcessMemoryDump* pmd) override;
+
private:
// ---------------------------------------------------------------------------
// Important: When adding any new members below, consider whether they need to
@@ -268,6 +294,14 @@ class NET_EXPORT URLRequestContext
// Enables Brotli Content-Encoding support.
bool enable_brotli_;
+ // Enables checking system policy before allowing a cleartext http or ws
+ // request. Only used on Android.
+ bool check_cleartext_permitted_;
+
+ // An optional name which can be set to describe this URLRequestContext.
+ // Used in MemoryDumpProvier to annotate memory usage. The name does not need
+ // to be unique.
+ std::string name_;
DISALLOW_COPY_AND_ASSIGN(URLRequestContext);
};
diff --git a/chromium/net/url_request/url_request_context_builder.h b/chromium/net/url_request/url_request_context_builder.h
index 3ed1ab50faf..1f93bb6427a 100644
--- a/chromium/net/url_request/url_request_context_builder.h
+++ b/chromium/net/url_request/url_request_context_builder.h
@@ -35,7 +35,7 @@
#include "net/net_features.h"
#include "net/proxy/proxy_config_service.h"
#include "net/proxy/proxy_service.h"
-#include "net/quic/core/quic_protocol.h"
+#include "net/quic/core/quic_packets.h"
#include "net/socket/next_proto.h"
#include "net/url_request/url_request_job_factory.h"
@@ -49,7 +49,6 @@ class CertVerifier;
class ChannelIDService;
class CookieStore;
class CTVerifier;
-class FtpTransactionFactory;
class HostMappingRules;
class HttpAuthHandlerFactory;
class HttpServerProperties;
diff --git a/chromium/net/url_request/url_request_context_getter.h b/chromium/net/url_request/url_request_context_getter.h
index 3e6cd084766..081c97c7004 100644
--- a/chromium/net/url_request/url_request_context_getter.h
+++ b/chromium/net/url_request/url_request_context_getter.h
@@ -16,7 +16,6 @@ class SingleThreadTaskRunner;
} // namespace base
namespace net {
-class CookieStore;
class URLRequestContext;
class URLRequestContextGetterObserver;
diff --git a/chromium/net/url_request/url_request_context_storage.h b/chromium/net/url_request/url_request_context_storage.h
index d5b08022839..0e4a8a51ea1 100644
--- a/chromium/net/url_request/url_request_context_storage.h
+++ b/chromium/net/url_request/url_request_context_storage.h
@@ -18,7 +18,6 @@ class ChannelIDService;
class CookieStore;
class CTPolicyEnforcer;
class CTVerifier;
-class FtpTransactionFactory;
class HostResolver;
class HttpAuthHandlerFactory;
class HttpNetworkSession;
diff --git a/chromium/net/url_request/url_request_context_unittest.cc b/chromium/net/url_request/url_request_context_unittest.cc
new file mode 100644
index 00000000000..bae16853a7d
--- /dev/null
+++ b/chromium/net/url_request/url_request_context_unittest.cc
@@ -0,0 +1,59 @@
+// Copyright 2016 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.
+
+#include "net/url_request/url_request_context.h"
+
+#include <memory>
+
+#include "base/memory/ptr_util.h"
+#include "base/trace_event/process_memory_dump.h"
+#include "net/proxy/proxy_config_service_fixed.h"
+#include "net/url_request/url_request_context_builder.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace net {
+
+// Checks if the dump provider runs without crashing and dumps root objects.
+TEST(URLRequestContextTest, MemoryDumpProvider) {
+ base::trace_event::MemoryDumpArgs dump_args = {
+ base::trace_event::MemoryDumpLevelOfDetail::DETAILED};
+ std::unique_ptr<base::trace_event::ProcessMemoryDump> process_memory_dump(
+ new base::trace_event::ProcessMemoryDump(nullptr, dump_args));
+ URLRequestContextBuilder builder;
+#if defined(OS_LINUX) || defined(OS_ANDROID)
+ builder.set_proxy_config_service(
+ base::MakeUnique<ProxyConfigServiceFixed>(ProxyConfig::CreateDirect()));
+#endif // defined(OS_LINUX) || defined(OS_ANDROID)
+ std::unique_ptr<URLRequestContext> context(builder.Build());
+ context->OnMemoryDump(dump_args, process_memory_dump.get());
+ const base::trace_event::ProcessMemoryDump::AllocatorDumpsMap&
+ allocator_dumps = process_memory_dump->allocator_dumps();
+
+ bool did_dump_http_network_session = false;
+ bool did_dump_ssl_client_session_cache = false;
+ bool did_dump_url_request_context = false;
+ bool did_dump_url_request_context_http_network_session = false;
+ for (const auto& it : allocator_dumps) {
+ const std::string& dump_name = it.first;
+ if (dump_name.find("net/http_network_session") != std::string::npos)
+ did_dump_http_network_session = true;
+ if (dump_name.find("net/ssl_session_cache") != std::string::npos)
+ did_dump_ssl_client_session_cache = true;
+ if (dump_name.find("net/url_request_context") != std::string::npos) {
+ // A sub allocator dump to take into account of the sharing relationship.
+ if (dump_name.find("http_network_session") != std::string::npos) {
+ did_dump_url_request_context_http_network_session = true;
+ } else {
+ did_dump_url_request_context = true;
+ }
+ }
+ }
+ ASSERT_TRUE(did_dump_http_network_session);
+ ASSERT_TRUE(did_dump_ssl_client_session_cache);
+ ASSERT_TRUE(did_dump_url_request_context);
+ ASSERT_TRUE(did_dump_url_request_context_http_network_session);
+}
+
+// TODO(xunjieli): Add more granular tests on the MemoryDumpProvider.
+} // namespace net
diff --git a/chromium/net/url_request/url_request_data_job_fuzzer.cc b/chromium/net/url_request/url_request_data_job_fuzzer.cc
index faed541973e..003edd5cb22 100644
--- a/chromium/net/url_request/url_request_data_job_fuzzer.cc
+++ b/chromium/net/url_request/url_request_data_job_fuzzer.cc
@@ -9,6 +9,7 @@
#include "base/memory/singleton.h"
#include "base/run_loop.h"
#include "base/test/fuzzed_data_provider.h"
+#include "base/threading/thread_task_runner_handle.h"
#include "net/http/http_request_headers.h"
#include "net/url_request/data_protocol_handler.h"
#include "net/url_request/url_request.h"
diff --git a/chromium/net/url_request/url_request_file_dir_job_unittest.cc b/chromium/net/url_request/url_request_file_dir_job_unittest.cc
index 922402a59f0..25f1d3d6994 100644
--- a/chromium/net/url_request/url_request_file_dir_job_unittest.cc
+++ b/chromium/net/url_request/url_request_file_dir_job_unittest.cc
@@ -13,6 +13,7 @@
#include "base/macros.h"
#include "base/memory/ref_counted.h"
#include "base/run_loop.h"
+#include "base/threading/thread_task_runner_handle.h"
#include "net/base/filename_util.h"
#include "net/base/io_buffer.h"
#include "net/base/net_errors.h"
diff --git a/chromium/net/url_request/url_request_file_job.cc b/chromium/net/url_request/url_request_file_job.cc
index 8f96f404c91..4924e023491 100644
--- a/chromium/net/url_request/url_request_file_job.cc
+++ b/chromium/net/url_request/url_request_file_job.cc
@@ -172,12 +172,14 @@ void URLRequestFileJob::SetExtraRequestHeaders(
// because we need to do multipart encoding here.
// TODO(hclam): decide whether we want to support multiple range
// requests.
- range_parse_result_ = net::ERR_REQUEST_RANGE_NOT_SATISFIABLE;
+ range_parse_result_ = ERR_REQUEST_RANGE_NOT_SATISFIABLE;
}
}
}
}
+void URLRequestFileJob::OnOpenComplete(int result) {}
+
void URLRequestFileJob::OnSeekComplete(int64_t result) {}
void URLRequestFileJob::OnReadComplete(IOBuffer* buf, int result) {
@@ -239,20 +241,15 @@ void URLRequestFileJob::DidFetchMetaInfo(const FileMetaInfo* meta_info) {
}
void URLRequestFileJob::DidOpen(int result) {
+ OnOpenComplete(result);
if (result != OK) {
NotifyStartError(URLRequestStatus(URLRequestStatus::FAILED, result));
return;
}
- if (range_parse_result_ != net::OK) {
- NotifyStartError(
- URLRequestStatus(URLRequestStatus::FAILED, range_parse_result_));
- return;
- }
-
- if (!byte_range_.ComputeBounds(meta_info_.file_size)) {
- NotifyStartError(URLRequestStatus(URLRequestStatus::FAILED,
- net::ERR_REQUEST_RANGE_NOT_SATISFIABLE));
+ if (range_parse_result_ != OK ||
+ !byte_range_.ComputeBounds(meta_info_.file_size)) {
+ DidSeek(ERR_REQUEST_RANGE_NOT_SATISFIABLE);
return;
}
@@ -264,11 +261,8 @@ void URLRequestFileJob::DidOpen(int result) {
int rv = stream_->Seek(byte_range_.first_byte_position(),
base::Bind(&URLRequestFileJob::DidSeek,
weak_ptr_factory_.GetWeakPtr()));
- if (rv != ERR_IO_PENDING) {
- // stream_->Seek() failed, so pass an intentionally erroneous value
- // into DidSeek().
- DidSeek(-1);
- }
+ if (rv != ERR_IO_PENDING)
+ DidSeek(ERR_REQUEST_RANGE_NOT_SATISFIABLE);
} else {
// We didn't need to call stream_->Seek() at all, so we pass to DidSeek()
// the value that would mean seek success. This way we skip the code
@@ -278,8 +272,10 @@ void URLRequestFileJob::DidOpen(int result) {
}
void URLRequestFileJob::DidSeek(int64_t result) {
+ DCHECK(result < 0 || result == byte_range_.first_byte_position());
+
OnSeekComplete(result);
- if (result != byte_range_.first_byte_position()) {
+ if (result < 0) {
NotifyStartError(URLRequestStatus(URLRequestStatus::FAILED,
ERR_REQUEST_RANGE_NOT_SATISFIABLE));
return;
diff --git a/chromium/net/url_request/url_request_file_job.h b/chromium/net/url_request/url_request_file_job.h
index f5697fc0233..ec907679481 100644
--- a/chromium/net/url_request/url_request_file_job.h
+++ b/chromium/net/url_request/url_request_file_job.h
@@ -24,9 +24,6 @@
namespace base {
class TaskRunner;
}
-namespace file_util {
-struct FileInfo;
-}
namespace net {
@@ -49,7 +46,18 @@ class NET_EXPORT URLRequestFileJob : public URLRequestJob {
void SetExtraRequestHeaders(const HttpRequestHeaders& headers) override;
// An interface for subclasses who wish to monitor read operations.
+ //
+ // |result| is the net::Error code resulting from attempting to open the file.
+ // Called before OnSeekComplete, only called if the request advanced to the
+ // point the file was opened, without being canceled.
+ virtual void OnOpenComplete(int result);
+ // Called at most once. On success, |result| is the non-negative offset into
+ // the file that the request will read from. On seek failure, it's a negative
+ // net:Error code.
virtual void OnSeekComplete(int64_t result);
+ // Called once per read attempt. |buf| contains the read data, if any.
+ // |result| is the number of read bytes. 0 (net::OK) indicates EOF, negative
+ // numbers indicate it's a net::Error code.
virtual void OnReadComplete(IOBuffer* buf, int result);
protected:
diff --git a/chromium/net/url_request/url_request_file_job_unittest.cc b/chromium/net/url_request/url_request_file_job_unittest.cc
index 613353dd866..2e5aafffbc2 100644
--- a/chromium/net/url_request/url_request_file_job_unittest.cc
+++ b/chromium/net/url_request/url_request_file_job_unittest.cc
@@ -15,6 +15,7 @@
#include "base/threading/sequenced_worker_pool.h"
#include "base/threading/thread_task_runner_handle.h"
#include "net/base/filename_util.h"
+#include "net/base/net_errors.h"
#include "net/url_request/url_request.h"
#include "net/url_request/url_request_test_util.h"
#include "testing/gtest/include/gtest/gtest.h"
@@ -34,30 +35,45 @@ class TestURLRequestFileJob : public URLRequestFileJob {
NetworkDelegate* network_delegate,
const base::FilePath& file_path,
const scoped_refptr<base::TaskRunner>& file_task_runner,
+ int* open_result,
int64_t* seek_position,
std::string* observed_content)
: URLRequestFileJob(request,
network_delegate,
file_path,
file_task_runner),
+ open_result_(open_result),
seek_position_(seek_position),
observed_content_(observed_content) {
- *seek_position_ = 0;
+ *open_result_ = ERR_IO_PENDING;
+ *seek_position_ = ERR_IO_PENDING;
observed_content_->clear();
}
~TestURLRequestFileJob() override {}
protected:
+ void OnOpenComplete(int result) override {
+ // Should only be called once.
+ ASSERT_EQ(ERR_IO_PENDING, *open_result_);
+ *open_result_ = result;
+ }
+
void OnSeekComplete(int64_t result) override {
- ASSERT_EQ(*seek_position_, 0);
+ // Should only call this if open succeeded.
+ EXPECT_EQ(OK, *open_result_);
+ // Should only be called once.
+ ASSERT_EQ(ERR_IO_PENDING, *seek_position_);
*seek_position_ = result;
}
void OnReadComplete(IOBuffer* buf, int result) override {
+ // Should only call this if seek succeeded.
+ EXPECT_GE(*seek_position_, 0);
observed_content_->append(std::string(buf->data(), result));
}
+ int* const open_result_;
int64_t* const seek_position_;
std::string* const observed_content_;
};
@@ -67,11 +83,14 @@ class TestURLRequestFileJob : public URLRequestFileJob {
class TestJobFactory : public URLRequestJobFactory {
public:
TestJobFactory(const base::FilePath& path,
+ int* open_result,
int64_t* seek_position,
std::string* observed_content)
: path_(path),
+ open_result_(open_result),
seek_position_(seek_position),
observed_content_(observed_content) {
+ CHECK(open_result_);
CHECK(seek_position_);
CHECK(observed_content_);
}
@@ -82,11 +101,13 @@ class TestJobFactory : public URLRequestJobFactory {
const std::string& scheme,
URLRequest* request,
NetworkDelegate* network_delegate) const override {
+ CHECK(open_result_);
CHECK(seek_position_);
CHECK(observed_content_);
URLRequestJob* job = new TestURLRequestFileJob(
request, network_delegate, path_, base::ThreadTaskRunnerHandle::Get(),
- seek_position_, observed_content_);
+ open_result_, seek_position_, observed_content_);
+ open_result_ = nullptr;
seek_position_ = nullptr;
observed_content_ = nullptr;
return job;
@@ -120,6 +141,7 @@ class TestJobFactory : public URLRequestJobFactory {
const base::FilePath path_;
// These are mutable because MaybeCreateJobWithProtocolHandler is const.
+ mutable int* open_result_;
mutable int64_t* seek_position_;
mutable std::string* observed_content_;
};
@@ -147,28 +169,41 @@ struct Range {
}
};
-// A superclass for tests of the OnSeekComplete / OnReadComplete functions of
-// URLRequestFileJob.
+// A superclass for tests of the OnReadComplete / OnSeekComplete /
+// OnReadComplete functions of URLRequestFileJob.
class URLRequestFileJobEventsTest : public testing::Test {
public:
URLRequestFileJobEventsTest();
protected:
+ void TearDown() override;
+
// This creates a file with |content| as the contents, and then creates and
- // runs a URLRequestFileJobWithCallbacks job to get the contents out of it,
+ // runs a TestURLRequestFileJob job to get the contents out of it,
// and makes sure that the callbacks observed the correct bytes. If a Range
// is provided, this function will add the appropriate Range http header to
// the request and verify that only the bytes in that range (inclusive) were
// observed.
- void RunRequest(const std::string& content, const Range* range);
+ void RunSuccessfulRequestWithString(const std::string& content,
+ const Range* range);
// This is the same as the method above it, except that it will make sure
// the content matches |expected_content| and allow caller to specify the
// extension of the filename in |file_extension|.
- void RunRequest(const std::string& content,
- const std::string& expected_content,
- const base::FilePath::StringPieceType& file_extension,
- const Range* range);
+ void RunSuccessfulRequestWithString(
+ const std::string& content,
+ const std::string& expected_content,
+ const base::FilePath::StringPieceType& file_extension,
+ const Range* range);
+
+ // Creates and runs a TestURLRequestFileJob job to read from file provided by
+ // |path|. If |range| value is provided, it will be passed in the range
+ // header.
+ void RunRequestWithPath(const base::FilePath& path,
+ const std::string& range,
+ int* open_result,
+ int64_t* seek_position,
+ std::string* observed_content);
TestURLRequestContext context_;
TestDelegate delegate_;
@@ -176,12 +211,19 @@ class URLRequestFileJobEventsTest : public testing::Test {
URLRequestFileJobEventsTest::URLRequestFileJobEventsTest() {}
-void URLRequestFileJobEventsTest::RunRequest(const std::string& content,
- const Range* range) {
- RunRequest(content, content, FILE_PATH_LITERAL(""), range);
+void URLRequestFileJobEventsTest::TearDown() {
+ // Gives a chance to close the opening file.
+ base::RunLoop().RunUntilIdle();
+}
+
+void URLRequestFileJobEventsTest::RunSuccessfulRequestWithString(
+ const std::string& content,
+ const Range* range) {
+ RunSuccessfulRequestWithString(content, content, FILE_PATH_LITERAL(""),
+ range);
}
-void URLRequestFileJobEventsTest::RunRequest(
+void URLRequestFileJobEventsTest::RunSuccessfulRequestWithString(
const std::string& raw_content,
const std::string& expected_content,
const base::FilePath::StringPieceType& file_extension,
@@ -193,29 +235,23 @@ void URLRequestFileJobEventsTest::RunRequest(
path = path.AddExtension(file_extension);
ASSERT_TRUE(CreateFileWithContent(raw_content, path));
+ std::string range_value;
+ if (range) {
+ ASSERT_GE(range->start, 0);
+ ASSERT_GE(range->end, 0);
+ ASSERT_LE(range->start, range->end);
+ ASSERT_LT(static_cast<unsigned int>(range->end), expected_content.length());
+ range_value = base::StringPrintf("bytes=%d-%d", range->start, range->end);
+ }
+
{
+ int open_result;
int64_t seek_position;
std::string observed_content;
- TestJobFactory factory(path, &seek_position, &observed_content);
- context_.set_job_factory(&factory);
-
- std::unique_ptr<URLRequest> request(context_.CreateRequest(
- FilePathToFileURL(path), DEFAULT_PRIORITY, &delegate_));
- if (range) {
- ASSERT_GE(range->start, 0);
- ASSERT_GE(range->end, 0);
- ASSERT_LE(range->start, range->end);
- ASSERT_LT(static_cast<unsigned int>(range->end),
- expected_content.length());
- std::string range_value =
- base::StringPrintf("bytes=%d-%d", range->start, range->end);
- request->SetExtraRequestHeaderByName(HttpRequestHeaders::kRange,
- range_value, true /*overwrite*/);
- }
- request->Start();
-
- base::RunLoop().Run();
+ RunRequestWithPath(path, range_value, &open_result, &seek_position,
+ &observed_content);
+ EXPECT_EQ(OK, open_result);
EXPECT_FALSE(delegate_.request_failed());
int expected_length =
range ? (range->end - range->start + 1) : expected_content.length();
@@ -234,8 +270,26 @@ void URLRequestFileJobEventsTest::RunRequest(
EXPECT_EQ(expected_data_received, delegate_.data_received());
EXPECT_EQ(seek_position, range ? range->start : 0);
}
+}
- base::RunLoop().RunUntilIdle();
+void URLRequestFileJobEventsTest::RunRequestWithPath(
+ const base::FilePath& path,
+ const std::string& range,
+ int* open_result,
+ int64_t* seek_position,
+ std::string* observed_content) {
+ TestJobFactory factory(path, open_result, seek_position, observed_content);
+ context_.set_job_factory(&factory);
+
+ std::unique_ptr<URLRequest> request(context_.CreateRequest(
+ FilePathToFileURL(path), DEFAULT_PRIORITY, &delegate_));
+ if (!range.empty()) {
+ request->SetExtraRequestHeaderByName(HttpRequestHeaders::kRange, range,
+ true /*overwrite*/);
+ }
+ request->Start();
+
+ base::RunLoop().Run();
}
// Helper function to make a character array filled with |size| bytes of
@@ -251,15 +305,15 @@ std::string MakeContentOfSize(int size) {
}
TEST_F(URLRequestFileJobEventsTest, TinyFile) {
- RunRequest(std::string("hello world"), NULL);
+ RunSuccessfulRequestWithString(std::string("hello world"), NULL);
}
TEST_F(URLRequestFileJobEventsTest, SmallFile) {
- RunRequest(MakeContentOfSize(17 * 1024), NULL);
+ RunSuccessfulRequestWithString(MakeContentOfSize(17 * 1024), NULL);
}
TEST_F(URLRequestFileJobEventsTest, BigFile) {
- RunRequest(MakeContentOfSize(3 * 1024 * 1024), NULL);
+ RunSuccessfulRequestWithString(MakeContentOfSize(3 * 1024 * 1024), NULL);
}
TEST_F(URLRequestFileJobEventsTest, Range) {
@@ -267,7 +321,7 @@ TEST_F(URLRequestFileJobEventsTest, Range) {
// not aligned on any likely page boundaries.
int size = 15 * 1024;
Range range(1701, (6 * 1024) + 3);
- RunRequest(MakeContentOfSize(size), &range);
+ RunSuccessfulRequestWithString(MakeContentOfSize(size), &range);
}
TEST_F(URLRequestFileJobEventsTest, DecodeSvgzFile) {
@@ -278,8 +332,77 @@ TEST_F(URLRequestFileJobEventsTest, DecodeSvgzFile) {
0x1f, 0x8b, 0x08, 0x00, 0x2b, 0x02, 0x84, 0x55, 0x00, 0x03, 0xf3,
0x48, 0xcd, 0xc9, 0xc9, 0xd7, 0x51, 0x08, 0xcf, 0x2f, 0xca, 0x49,
0x51, 0x04, 0x00, 0xd0, 0xc3, 0x4a, 0xec, 0x0d, 0x00, 0x00, 0x00};
- RunRequest(std::string(reinterpret_cast<char*>(gzip_data), sizeof(gzip_data)),
- expected_content, FILE_PATH_LITERAL("svgz"), nullptr);
+ RunSuccessfulRequestWithString(
+ std::string(reinterpret_cast<char*>(gzip_data), sizeof(gzip_data)),
+ expected_content, FILE_PATH_LITERAL("svgz"), nullptr);
+}
+
+TEST_F(URLRequestFileJobEventsTest, OpenNonExistentFile) {
+ base::FilePath path;
+ PathService::Get(base::DIR_SOURCE_ROOT, &path);
+ path = path.Append(
+ FILE_PATH_LITERAL("net/data/url_request_unittest/non-existent.txt"));
+
+ int open_result;
+ int64_t seek_position;
+ std::string observed_content;
+ RunRequestWithPath(path, std::string(), &open_result, &seek_position,
+ &observed_content);
+
+ EXPECT_EQ(ERR_FILE_NOT_FOUND, open_result);
+ EXPECT_TRUE(delegate_.request_failed());
+}
+
+TEST_F(URLRequestFileJobEventsTest, MultiRangeRequestNotSupported) {
+ base::FilePath path;
+ PathService::Get(base::DIR_SOURCE_ROOT, &path);
+ path = path.Append(
+ FILE_PATH_LITERAL("net/data/url_request_unittest/BullRunSpeech.txt"));
+
+ int open_result;
+ int64_t seek_position;
+ std::string observed_content;
+ RunRequestWithPath(path, "bytes=1-5,20-30", &open_result, &seek_position,
+ &observed_content);
+
+ EXPECT_EQ(OK, open_result);
+ EXPECT_EQ(ERR_REQUEST_RANGE_NOT_SATISFIABLE, seek_position);
+ EXPECT_TRUE(delegate_.request_failed());
+}
+
+TEST_F(URLRequestFileJobEventsTest, RangeExceedingFileSize) {
+ base::FilePath path;
+ PathService::Get(base::DIR_SOURCE_ROOT, &path);
+ path = path.Append(
+ FILE_PATH_LITERAL("net/data/url_request_unittest/BullRunSpeech.txt"));
+
+ int open_result;
+ int64_t seek_position;
+ std::string observed_content;
+ RunRequestWithPath(path, "bytes=50000-", &open_result, &seek_position,
+ &observed_content);
+
+ EXPECT_EQ(OK, open_result);
+ EXPECT_EQ(ERR_REQUEST_RANGE_NOT_SATISFIABLE, seek_position);
+ EXPECT_TRUE(delegate_.request_failed());
+}
+
+TEST_F(URLRequestFileJobEventsTest, IgnoreRangeParsingError) {
+ base::FilePath path;
+ PathService::Get(base::DIR_SOURCE_ROOT, &path);
+ path = path.Append(
+ FILE_PATH_LITERAL("net/data/url_request_unittest/simple.html"));
+
+ int open_result;
+ int64_t seek_position;
+ std::string observed_content;
+ RunRequestWithPath(path, "bytes=3-z", &open_result, &seek_position,
+ &observed_content);
+
+ EXPECT_EQ(OK, open_result);
+ EXPECT_EQ(0, seek_position);
+ EXPECT_EQ("hello\n", observed_content);
+ EXPECT_FALSE(delegate_.request_failed());
}
} // namespace
diff --git a/chromium/net/url_request/url_request_ftp_fuzzer.cc b/chromium/net/url_request/url_request_ftp_fuzzer.cc
new file mode 100644
index 00000000000..4f64b5ae8d9
--- /dev/null
+++ b/chromium/net/url_request/url_request_ftp_fuzzer.cc
@@ -0,0 +1,89 @@
+// Copyright 2016 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.
+
+#include "net/url_request/url_request.h"
+
+#include <stddef.h>
+#include <stdint.h>
+
+#include <memory>
+
+#include "base/macros.h"
+#include "base/memory/ptr_util.h"
+#include "base/run_loop.h"
+#include "base/test/fuzzed_data_provider.h"
+#include "net/base/request_priority.h"
+#include "net/dns/fuzzed_host_resolver.h"
+#include "net/ftp/ftp_network_transaction.h"
+#include "net/ftp/ftp_transaction_factory.h"
+#include "net/socket/client_socket_factory.h"
+#include "net/socket/fuzzed_socket_factory.h"
+#include "net/url_request/ftp_protocol_handler.h"
+#include "net/url_request/url_request.h"
+#include "net/url_request/url_request_context.h"
+#include "net/url_request/url_request_job_factory_impl.h"
+#include "net/url_request/url_request_test_util.h"
+#include "url/gurl.h"
+
+namespace {
+
+// Returns FtpNetworkTransactions using the specified HostResolver
+// and ClientSocketFactory.
+class FuzzedFtpTransactionFactory : public net::FtpTransactionFactory {
+ public:
+ FuzzedFtpTransactionFactory(net::HostResolver* host_resolver,
+ net::ClientSocketFactory* client_socket_factory)
+ : host_resolver_(host_resolver),
+ client_socket_factory_(client_socket_factory) {}
+
+ // FtpTransactionFactory:
+ std::unique_ptr<net::FtpTransaction> CreateTransaction() override {
+ return base::MakeUnique<net::FtpNetworkTransaction>(host_resolver_,
+ client_socket_factory_);
+ }
+
+ void Suspend(bool suspend) override { NOTREACHED(); }
+
+ private:
+ net::HostResolver* host_resolver_;
+ net::ClientSocketFactory* client_socket_factory_;
+
+ DISALLOW_COPY_AND_ASSIGN(FuzzedFtpTransactionFactory);
+};
+
+} // namespace
+
+// Integration fuzzer for URLRequestFtpJob.
+extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
+ base::FuzzedDataProvider data_provider(data, size);
+ net::TestURLRequestContext url_request_context(true);
+ net::FuzzedSocketFactory fuzzed_socket_factory(&data_provider);
+ url_request_context.set_client_socket_factory(&fuzzed_socket_factory);
+
+ // Need to fuzz the HostResolver to select between IPv4 and IPv6.
+ net::FuzzedHostResolver host_resolver(net::HostResolver::Options(), nullptr,
+ &data_provider);
+ url_request_context.set_host_resolver(&host_resolver);
+
+ net::URLRequestJobFactoryImpl job_factory;
+ job_factory.SetProtocolHandler(
+ "ftp", net::FtpProtocolHandler::CreateForTesting(
+ base::MakeUnique<FuzzedFtpTransactionFactory>(
+ &host_resolver, &fuzzed_socket_factory)));
+ url_request_context.set_job_factory(&job_factory);
+
+ url_request_context.Init();
+
+ net::TestDelegate delegate;
+
+ std::unique_ptr<net::URLRequest> url_request(
+ url_request_context.CreateRequest(
+ GURL("ftp://foo/" + data_provider.ConsumeRandomLengthString(1000)),
+ net::DEFAULT_PRIORITY, &delegate));
+ url_request->Start();
+ // TestDelegate quits the message loop on completion.
+ base::RunLoop().Run();
+
+ return 0;
+}
diff --git a/chromium/net/url_request/url_request_fuzzer.cc b/chromium/net/url_request/url_request_fuzzer.cc
index a4d7b6a3a30..788e3a7a542 100644
--- a/chromium/net/url_request/url_request_fuzzer.cc
+++ b/chromium/net/url_request/url_request_fuzzer.cc
@@ -21,7 +21,7 @@
// Integration fuzzer for URLRequest's handling of HTTP requests. Can follow
// redirects, both on the same server (using a new socket or the old one) and
// across servers.
-// TODO(mmenke): Add support for testing HTTPS, FTP, auth, proxies, uploading,
+// TODO(mmenke): Add support for testing HTTPS, auth, proxies, uploading,
// cancelation, deferring reads / redirects, using preconnected sockets, SPDY,
// QUIC, DNS failures (they all currently resolve to localhost), IPv6 DNS
// results, URLs with IPs instead of hostnames (v4 and v6), etc.
diff --git a/chromium/net/url_request/url_request_http_job.cc b/chromium/net/url_request/url_request_http_job.cc
index 6934c78006c..67151f6bf09 100644
--- a/chromium/net/url_request/url_request_http_job.cc
+++ b/chromium/net/url_request/url_request_http_job.cc
@@ -31,6 +31,7 @@
#include "net/base/registry_controlled_domains/registry_controlled_domain.h"
#include "net/base/sdch_manager.h"
#include "net/base/sdch_problem_codes.h"
+#include "net/base/trace_constants.h"
#include "net/base/url_util.h"
#include "net/cert/cert_status_flags.h"
#include "net/cookies/cookie_store.h"
@@ -67,6 +68,10 @@
#include "net/websockets/websocket_handshake_stream_base.h"
#include "url/origin.h"
+#if defined(OS_ANDROID)
+#include "net/android/network_library.h"
+#endif
+
static const char kAvailDictionaryHeader[] = "Avail-Dictionary";
namespace {
@@ -168,27 +173,6 @@ void LogChannelIDAndCookieStores(const GURL& url,
EPHEMERALITY_MAX);
}
-net::URLRequestRedirectJob* MaybeInternallyRedirect(
- net::URLRequest* request,
- net::NetworkDelegate* network_delegate) {
- const GURL& url = request->url();
- if (url.SchemeIsCryptographic())
- return nullptr;
-
- net::TransportSecurityState* hsts =
- request->context()->transport_security_state();
- if (!hsts || !hsts->ShouldUpgradeToSSL(url.host()))
- return nullptr;
-
- GURL::Replacements replacements;
- replacements.SetSchemeStr(url.SchemeIs(url::kHttpScheme) ? url::kHttpsScheme
- : url::kWssScheme);
- return new net::URLRequestRedirectJob(
- request, network_delegate, url.ReplaceComponents(replacements),
- // Use status code 307 to preserve the method, so POST requests work.
- net::URLRequestRedirectJob::REDIRECT_307_TEMPORARY_REDIRECT, "HSTS");
-}
-
} // namespace
namespace net {
@@ -207,10 +191,34 @@ URLRequestJob* URLRequestHttpJob::Factory(URLRequest* request,
request, network_delegate, ERR_INVALID_ARGUMENT);
}
- URLRequestRedirectJob* redirect =
- MaybeInternallyRedirect(request, network_delegate);
- if (redirect)
- return redirect;
+ const GURL& url = request->url();
+
+ // Check for reasons not to return a URLRequestHttpJob. These don't apply to
+ // https and wss requests.
+ if (!url.SchemeIsCryptographic()) {
+ // Check for HSTS upgrade.
+ TransportSecurityState* hsts =
+ request->context()->transport_security_state();
+ if (hsts && hsts->ShouldUpgradeToSSL(url.host())) {
+ GURL::Replacements replacements;
+ replacements.SetSchemeStr(
+ url.SchemeIs(url::kHttpScheme) ? url::kHttpsScheme : url::kWssScheme);
+ return new URLRequestRedirectJob(
+ request, network_delegate, url.ReplaceComponents(replacements),
+ // Use status code 307 to preserve the method, so POST requests work.
+ URLRequestRedirectJob::REDIRECT_307_TEMPORARY_REDIRECT, "HSTS");
+ }
+
+#if defined(OS_ANDROID)
+ // Check whether the app allows cleartext traffic to this host, and return
+ // ERR_CLEARTEXT_NOT_PERMITTED if not.
+ if (request->context()->check_cleartext_permitted() &&
+ !android::IsCleartextPermitted(url.host())) {
+ return new URLRequestErrorJob(request, network_delegate,
+ ERR_CLEARTEXT_NOT_PERMITTED);
+ }
+#endif
+ }
return new URLRequestHttpJob(request,
network_delegate,
@@ -679,7 +687,9 @@ void URLRequestHttpJob::AddCookieHeaderAndStart() {
//
// * Include both "strict" and "lax" same-site cookies if the request's
// |url|, |initiator|, and |first_party_for_cookies| all have the same
- // registrable domain.
+ // registrable domain. Note: this also covers the case of a request
+ // without an initiator (only happens for browser-initiated main frame
+ // navigations).
//
// * Include only "lax" same-site cookies if the request's |URL| and
// |first_party_for_cookies| have the same registrable domain, _and_ the
@@ -689,14 +699,12 @@ void URLRequestHttpJob::AddCookieHeaderAndStart() {
// which target a top-level browsing context.
//
// * Otherwise, do not include same-site cookies.
- url::Origin requested_origin(request_->url());
- url::Origin site_for_cookies(request_->first_party_for_cookies());
-
if (registry_controlled_domains::SameDomainOrHost(
- requested_origin, site_for_cookies,
+ request_->url(), request_->first_party_for_cookies(),
registry_controlled_domains::INCLUDE_PRIVATE_REGISTRIES)) {
- if (registry_controlled_domains::SameDomainOrHost(
- requested_origin, request_->initiator(),
+ if (!request_->initiator() ||
+ registry_controlled_domains::SameDomainOrHost(
+ request_->url(), request_->initiator().value().GetURL(),
registry_controlled_domains::INCLUDE_PRIVATE_REGISTRIES)) {
options.set_same_site_cookie_mode(
CookieOptions::SameSiteCookieMode::INCLUDE_STRICT_AND_LAX);
@@ -855,8 +863,7 @@ void URLRequestHttpJob::ProcessExpectCTHeader() {
}
void URLRequestHttpJob::OnStartCompleted(int result) {
- TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("net"),
- "URLRequestHttpJob::OnStartCompleted");
+ TRACE_EVENT0(kNetTracingCategory, "URLRequestHttpJob::OnStartCompleted");
RecordTimer();
// If the job is done (due to cancellation), can just ignore this
@@ -938,8 +945,7 @@ void URLRequestHttpJob::OnHeadersReceivedCallback(int result) {
}
void URLRequestHttpJob::OnReadCompleted(int result) {
- TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("net"),
- "URLRequestHttpJob::OnReadCompleted");
+ TRACE_EVENT0(kNetTracingCategory, "URLRequestHttpJob::OnReadCompleted");
read_in_progress_ = false;
DCHECK_NE(ERR_IO_PENDING, result);
@@ -1071,6 +1077,9 @@ std::unique_ptr<SourceStream> URLRequestHttpJob::SetUpSourceStream() {
base::LowerCaseEqualsASCII(type, kXGZip)) {
types.push_back(SourceStream::TYPE_GZIP);
} else if (base::LowerCaseEqualsASCII(type, kSdch)) {
+ // If SDCH support is not configured, pass through raw response.
+ if (!request()->context()->sdch_manager())
+ return upstream;
types.push_back(SourceStream::TYPE_SDCH);
} else {
// Unknown encoding type. Pass through raw response body.
@@ -1484,12 +1493,25 @@ void URLRequestHttpJob::RecordPerfHistograms(CompletionCause reason) {
total_time);
}
}
+
+ UMA_HISTOGRAM_CUSTOM_COUNTS("Net.HttpJob.PrefilterBytesRead",
+ prefilter_bytes_read(), 1, 50000000, 50);
if (response_info_->was_cached) {
UMA_HISTOGRAM_TIMES("Net.HttpJob.TotalTimeCached", total_time);
+ UMA_HISTOGRAM_CUSTOM_COUNTS("Net.HttpJob.PrefilterBytesRead.Cache",
+ prefilter_bytes_read(), 1, 50000000, 50);
+
if (response_info_->unused_since_prefetch)
UMA_HISTOGRAM_COUNTS("Net.Prefetch.HitBytes", prefilter_bytes_read());
} else {
UMA_HISTOGRAM_TIMES("Net.HttpJob.TotalTimeNotCached", total_time);
+ UMA_HISTOGRAM_CUSTOM_COUNTS("Net.HttpJob.PrefilterBytesRead.Net",
+ prefilter_bytes_read(), 1, 50000000, 50);
+
+ if (request_info_.load_flags & LOAD_PREFETCH) {
+ UMA_HISTOGRAM_COUNTS("Net.Prefetch.PrefilterBytesReadFromNetwork",
+ prefilter_bytes_read());
+ }
if (is_https_google) {
if (used_quic) {
UMA_HISTOGRAM_MEDIUM_TIMES(
@@ -1502,10 +1524,6 @@ void URLRequestHttpJob::RecordPerfHistograms(CompletionCause reason) {
}
}
- if (request_info_.load_flags & LOAD_PREFETCH && !request_->was_cached())
- UMA_HISTOGRAM_COUNTS("Net.Prefetch.PrefilterBytesReadFromNetwork",
- prefilter_bytes_read());
-
start_time_ = base::TimeTicks();
}
diff --git a/chromium/net/url_request/url_request_http_job.h b/chromium/net/url_request/url_request_http_job.h
index bbacdf45ed1..26ad8d27975 100644
--- a/chromium/net/url_request/url_request_http_job.h
+++ b/chromium/net/url_request/url_request_http_job.h
@@ -37,7 +37,6 @@ class HttpUserAgentSettings;
class ProxyInfo;
class SSLPrivateKey;
class UploadDataStream;
-class URLRequestContext;
// A URLRequestJob subclass that is built on top of HttpTransaction. It
// provides an implementation for both HTTP and HTTPS.
diff --git a/chromium/net/url_request/url_request_http_job_unittest.cc b/chromium/net/url_request/url_request_http_job_unittest.cc
index a8b3b54af08..dbaea28f76e 100644
--- a/chromium/net/url_request/url_request_http_job_unittest.cc
+++ b/chromium/net/url_request/url_request_http_job_unittest.cc
@@ -40,6 +40,12 @@
#include "url/gurl.h"
#include "url/url_constants.h"
+#if defined(OS_ANDROID)
+#include "base/android/build_info.h"
+#include "base/android/jni_android.h"
+#include "jni/AndroidNetworkLibraryTestUtil_jni.h"
+#endif
+
using net::test::IsError;
using net::test::IsOk;
@@ -161,8 +167,7 @@ TEST_F(URLRequestHttpJobSetUpSourceTest, UnknownEncoding) {
}
// Received a malformed SDCH encoded response when there is no SdchManager.
-TEST_F(URLRequestHttpJobSetUpSourceTest,
- SdchNotAdvertisedGotMalformedSdchResponse) {
+TEST_F(URLRequestHttpJobSetUpSourceTest, SdchNotAdvertisedGotSdchResponse) {
MockWrite writes[] = {MockWrite(kSimpleGetMockWrite)};
MockRead reads[] = {MockRead("HTTP/1.1 200 OK\r\n"
"Content-Encoding: sdch\r\n"
@@ -184,7 +189,9 @@ TEST_F(URLRequestHttpJobSetUpSourceTest,
request->Start();
base::RunLoop().Run();
- EXPECT_EQ(ERR_CONTENT_DECODING_INIT_FAILED, delegate_.request_status());
+ // Pass through the raw response the same way as if received unknown encoding.
+ EXPECT_EQ(OK, delegate_.request_status());
+ EXPECT_EQ("Test Content", delegate_.data_received());
}
class URLRequestHttpJobTest : public ::testing::Test {
@@ -776,6 +783,44 @@ class URLRequestHttpJobWithSdchSupportTest : public ::testing::Test {
TestURLRequestContext context_;
};
+// Received a malformed SDCH encoded response that has no valid dictionary id.
+TEST_F(URLRequestHttpJobWithSdchSupportTest,
+ SdchAdvertisedGotMalformedSdchResponse) {
+ MockWrite writes[] = {
+ MockWrite("GET / HTTP/1.1\r\n"
+ "Host: www.example.com\r\n"
+ "Connection: keep-alive\r\n"
+ "User-Agent:\r\n"
+ "Accept-Encoding: gzip, deflate, sdch\r\n"
+ "Accept-Language: en-us,fr\r\n\r\n")};
+ MockRead reads[] = {MockRead("HTTP/1.1 200 OK\r\n"
+ "Content-Encoding: sdch\r\n"
+ "Content-Length: 12\r\n\r\n"),
+ MockRead("Test Content")};
+
+ StaticSocketDataProvider socket_data(reads, arraysize(reads), writes,
+ arraysize(writes));
+ socket_factory_.AddSocketDataProvider(&socket_data);
+
+ MockSdchObserver sdch_observer;
+ SdchManager sdch_manager;
+ sdch_manager.AddObserver(&sdch_observer);
+ context_.set_sdch_manager(&sdch_manager);
+ TestDelegate delegate;
+ std::unique_ptr<URLRequest> request = context_.CreateRequest(
+ GURL("http://www.example.com"), DEFAULT_PRIORITY, &delegate);
+ request->Start();
+
+ base::RunLoop().Run();
+ // SdchPolicyDelegate::OnDictionaryIdError() detects that the response is
+ // malformed (missing dictionary), and will issue a pass-through of the raw
+ // response.
+ EXPECT_EQ(OK, delegate.request_status());
+ EXPECT_EQ("Test Content", delegate.data_received());
+ // Cleanup manager.
+ sdch_manager.RemoveObserver(&sdch_observer);
+}
+
TEST_F(URLRequestHttpJobWithSdchSupportTest, GetDictionary) {
MockWrite writes[] = {
MockWrite("GET / HTTP/1.1\r\n"
@@ -899,6 +944,46 @@ TEST_F(URLRequestHttpJobWithBrotliSupportTest, BrotliAdvertisement) {
request->GetTotalReceivedBytes());
}
+#if defined(OS_ANDROID)
+TEST_F(URLRequestHttpJobTest, AndroidCleartextPermittedTest) {
+ context_.set_check_cleartext_permitted(true);
+
+ struct TestCase {
+ const char* url;
+ bool cleartext_permitted;
+ bool should_block;
+ } cases[] = {
+ {"http://blocked.test/", true, false},
+ {"https://blocked.test/", true, false},
+ {"http://blocked.test/", false, true},
+ {"https://blocked.test/", false, false},
+ };
+
+ for (const TestCase& test : cases) {
+ JNIEnv* env = base::android::AttachCurrentThread();
+ Java_AndroidNetworkLibraryTestUtil_setUpSecurityPolicyForTesting(
+ env, test.cleartext_permitted);
+
+ TestDelegate delegate;
+ std::unique_ptr<URLRequest> request =
+ context_.CreateRequest(GURL(test.url), DEFAULT_PRIORITY, &delegate);
+ request->Start();
+ base::RunLoop().Run();
+
+ int sdk_int = base::android::BuildInfo::GetInstance()->sdk_int();
+ bool expect_blocked = (sdk_int >= base::android::SDK_VERSION_MARSHMALLOW &&
+ test.should_block);
+ if (expect_blocked) {
+ EXPECT_THAT(delegate.request_status(),
+ IsError(ERR_CLEARTEXT_NOT_PERMITTED));
+ } else {
+ // Should fail since there's no test server running
+ EXPECT_THAT(delegate.request_status(), IsError(ERR_FAILED));
+ }
+ }
+}
+#endif
+
// This base class just serves to set up some things before the TestURLRequest
// constructor is called.
class URLRequestHttpJobWebSocketTestBase : public ::testing::Test {
diff --git a/chromium/net/url_request/url_request_intercepting_job_factory.cc b/chromium/net/url_request/url_request_intercepting_job_factory.cc
index add05c9853d..45a13fca3fc 100644
--- a/chromium/net/url_request/url_request_intercepting_job_factory.cc
+++ b/chromium/net/url_request/url_request_intercepting_job_factory.cc
@@ -14,10 +14,21 @@ namespace net {
URLRequestInterceptingJobFactory::URLRequestInterceptingJobFactory(
std::unique_ptr<URLRequestJobFactory> job_factory,
std::unique_ptr<URLRequestInterceptor> interceptor)
- : job_factory_(std::move(job_factory)),
- interceptor_(std::move(interceptor)) {}
+ : owning_(true),
+ job_factory_(job_factory.release()),
+ interceptor_(interceptor.release()) {}
-URLRequestInterceptingJobFactory::~URLRequestInterceptingJobFactory() {}
+URLRequestInterceptingJobFactory::URLRequestInterceptingJobFactory(
+ URLRequestJobFactory* job_factory,
+ URLRequestInterceptor* interceptor)
+ : owning_(false), job_factory_(job_factory), interceptor_(interceptor) {}
+
+URLRequestInterceptingJobFactory::~URLRequestInterceptingJobFactory() {
+ if (owning_) {
+ delete job_factory_;
+ delete interceptor_;
+ }
+}
URLRequestJob* URLRequestInterceptingJobFactory::
MaybeCreateJobWithProtocolHandler(
diff --git a/chromium/net/url_request/url_request_intercepting_job_factory.h b/chromium/net/url_request/url_request_intercepting_job_factory.h
index e4d616a3b20..f6bd70ec23b 100644
--- a/chromium/net/url_request/url_request_intercepting_job_factory.h
+++ b/chromium/net/url_request/url_request_intercepting_job_factory.h
@@ -32,9 +32,14 @@ class URLRequestInterceptor;
class NET_EXPORT URLRequestInterceptingJobFactory
: public URLRequestJobFactory {
public:
+ // Takes ownership of |job_factory| and |interceptor|.
URLRequestInterceptingJobFactory(
std::unique_ptr<URLRequestJobFactory> job_factory,
std::unique_ptr<URLRequestInterceptor> interceptor);
+ // Does not take ownership of |job_factory| and |interceptor|. Necessary if
+ // ownership is held elsewhere.
+ URLRequestInterceptingJobFactory(URLRequestJobFactory* job_factory,
+ URLRequestInterceptor* interceptor);
~URLRequestInterceptingJobFactory() override;
// URLRequestJobFactory implementation
@@ -57,8 +62,10 @@ class NET_EXPORT URLRequestInterceptingJobFactory
bool IsSafeRedirectTarget(const GURL& location) const override;
private:
- std::unique_ptr<URLRequestJobFactory> job_factory_;
- std::unique_ptr<URLRequestInterceptor> interceptor_;
+ // |owning_| indicates if this object owns |job_factory_| and |interceptor_|.
+ bool owning_;
+ URLRequestJobFactory* job_factory_;
+ URLRequestInterceptor* interceptor_;
DISALLOW_COPY_AND_ASSIGN(URLRequestInterceptingJobFactory);
};
diff --git a/chromium/net/url_request/url_request_job.cc b/chromium/net/url_request/url_request_job.cc
index b315664de1a..cdf60f80fda 100644
--- a/chromium/net/url_request/url_request_job.cc
+++ b/chromium/net/url_request/url_request_job.cc
@@ -84,6 +84,9 @@ URLRequest::ReferrerPolicy ProcessReferrerPolicyHeaderOnRedirect(
base::SplitString(referrer_policy_header, ",", base::TRIM_WHITESPACE,
base::SPLIT_WANT_NONEMPTY);
+ UMA_HISTOGRAM_BOOLEAN("Net.URLRequest.ReferrerPolicyHeaderPresentOnRedirect",
+ !policy_tokens.empty());
+
for (const auto& token : policy_tokens) {
if (base::CompareCaseInsensitiveASCII(token, "no-referrer") == 0) {
new_policy = URLRequest::NO_REFERRER;
@@ -495,8 +498,9 @@ void URLRequestJob::NotifyHeadersComplete() {
source_stream_ = SetUpSourceStream();
if (!source_stream_) {
- NotifyDone(URLRequestStatus(URLRequestStatus::FAILED,
- ERR_CONTENT_DECODING_INIT_FAILED));
+ OnDone(URLRequestStatus(URLRequestStatus::FAILED,
+ ERR_CONTENT_DECODING_INIT_FAILED),
+ true);
return;
}
if (source_stream_->type() == SourceStream::TYPE_NONE) {
@@ -563,7 +567,7 @@ void URLRequestJob::NotifyStartError(const URLRequestStatus &status) {
// |this| may have been deleted here.
}
-void URLRequestJob::NotifyDone(const URLRequestStatus &status) {
+void URLRequestJob::OnDone(const URLRequestStatus& status, bool notify_done) {
DCHECK(!done_) << "Job sending done notification twice";
if (done_)
return;
@@ -589,15 +593,18 @@ void URLRequestJob::NotifyDone(const URLRequestStatus &status) {
MaybeNotifyNetworkBytes();
- // Complete this notification later. This prevents us from re-entering the
- // delegate if we're done because of a synchronous call.
- base::ThreadTaskRunnerHandle::Get()->PostTask(
- FROM_HERE, base::Bind(&URLRequestJob::CompleteNotifyDone,
- weak_factory_.GetWeakPtr()));
+ if (notify_done) {
+ // Complete this notification later. This prevents us from re-entering the
+ // delegate if we're done because of a synchronous call.
+ base::ThreadTaskRunnerHandle::Get()->PostTask(
+ FROM_HERE,
+ base::Bind(&URLRequestJob::NotifyDone, weak_factory_.GetWeakPtr()));
+ }
}
-void URLRequestJob::CompleteNotifyDone() {
- // Check if we should notify the delegate that we're done because of an error.
+void URLRequestJob::NotifyDone() {
+ // Check if we should notify the URLRequest that we're done because of an
+ // error.
if (!request_->status().is_success()) {
// We report the error differently depending on whether we've called
// OnResponseStarted yet.
@@ -613,7 +620,7 @@ void URLRequestJob::CompleteNotifyDone() {
void URLRequestJob::NotifyCanceled() {
if (!done_) {
- NotifyDone(URLRequestStatus(URLRequestStatus::CANCELED, ERR_ABORTED));
+ OnDone(URLRequestStatus(URLRequestStatus::CANCELED, ERR_ABORTED), true);
}
}
@@ -669,20 +676,21 @@ void URLRequestJob::SourceStreamReadComplete(bool synchronous, int result) {
pending_read_buffer_ = nullptr;
if (result < 0) {
- NotifyDone(URLRequestStatus::FromError(result));
+ OnDone(URLRequestStatus::FromError(result), !synchronous);
return;
}
if (result > 0) {
postfilter_bytes_read_ += result;
- if (!synchronous)
- request_->NotifyReadCompleted(result);
- return;
+ } else {
+ DCHECK_EQ(0, result);
+ DoneReading();
+ // In the synchronous case, the caller will notify the URLRequest of
+ // completion. In the async case, the NotifyReadCompleted call will.
+ // TODO(mmenke): Can this be combined with the error case?
+ OnDone(URLRequestStatus(), false);
}
- DCHECK_EQ(0, result);
- DoneReading();
- NotifyDone(URLRequestStatus());
if (!synchronous)
request_->NotifyReadCompleted(result);
}
@@ -713,7 +721,7 @@ int URLRequestJob::ReadRawDataHelper(IOBuffer* buf,
void URLRequestJob::FollowRedirect(const RedirectInfo& redirect_info) {
int rv = request_->Redirect(redirect_info);
if (rv != OK)
- NotifyDone(URLRequestStatus(URLRequestStatus::FAILED, rv));
+ OnDone(URLRequestStatus(URLRequestStatus::FAILED, rv), true);
}
void URLRequestJob::GatherRawReadStats(int bytes_read) {
diff --git a/chromium/net/url_request/url_request_job.h b/chromium/net/url_request/url_request_job.h
index 288644e8124..2341999ae54 100644
--- a/chromium/net/url_request/url_request_job.h
+++ b/chromium/net/url_request/url_request_job.h
@@ -31,7 +31,6 @@ namespace net {
class AuthChallengeInfo;
class AuthCredentials;
class CookieOptions;
-class Filter;
class HttpRequestHeaders;
class HttpResponseInfo;
class IOBuffer;
@@ -361,15 +360,19 @@ class NET_EXPORT URLRequestJob : public base::PowerObserver {
// |bytes_read| unfiltered bytes have been read for this job.
void RecordBytesRead(int bytes_read);
- // NotifyDone marks that request is done. It is really a glorified
+ // OnDone marks that request is done. It is really a glorified
// set_status, but also does internal state checking and job tracking. It
// should be called once per request, when the job is finished doing all IO.
- void NotifyDone(const URLRequestStatus& status);
-
- // Some work performed by NotifyDone must be completed asynchronously so
- // as to avoid re-entering URLRequest::Delegate. This method performs that
- // work.
- void CompleteNotifyDone();
+ //
+ // If |notify_done| is true, will notify the URLRequest if there was an error
+ // asynchronously. Otherwise, the caller will need to do this itself,
+ // possibly through a synchronous return value.
+ // TODO(mmenke): Remove |notify_done|, and make caller handle notification.
+ void OnDone(const URLRequestStatus& status, bool notify_done);
+
+ // Takes care of the notification initiated by OnDone() to avoid re-entering
+ // the URLRequest::Delegate.
+ void NotifyDone();
// Subclasses may implement this method to record packet arrival times.
// The default implementation does nothing. Only invoked when bytes have been
diff --git a/chromium/net/url_request/url_request_job_manager.h b/chromium/net/url_request/url_request_job_manager.h
index ab67c8a9876..4460060d3fd 100644
--- a/chromium/net/url_request/url_request_job_manager.h
+++ b/chromium/net/url_request/url_request_job_manager.h
@@ -59,10 +59,10 @@ class NET_EXPORT URLRequestJobManager {
URLRequestJobManager();
~URLRequestJobManager();
- // The first guy to call this function sets the allowed thread. This way we
- // avoid needing to define that thread externally. Since we expect all
- // callers to be on the same thread, we don't worry about threads racing to
- // set the allowed thread.
+ // The first call to this function sets the allowed thread. This way we avoid
+ // needing to define that thread externally. Since we expect all callers to
+ // be on the same thread, we don't worry about threads racing to set the
+ // allowed thread.
bool IsAllowedThread() const {
#if 0
return thread_checker_.CalledOnValidThread();
diff --git a/chromium/net/url_request/url_request_netlog_params.cc b/chromium/net/url_request/url_request_netlog_params.cc
index 97b67badcda..9fc0f22db50 100644
--- a/chromium/net/url_request/url_request_netlog_params.cc
+++ b/chromium/net/url_request/url_request_netlog_params.cc
@@ -13,18 +13,26 @@
namespace net {
+std::unique_ptr<base::Value> NetLogURLRequestConstructorCallback(
+ const GURL* url,
+ RequestPriority priority,
+ NetLogCaptureMode /* capture_mode */) {
+ std::unique_ptr<base::DictionaryValue> dict(new base::DictionaryValue());
+ dict->SetString("url", url->possibly_invalid_spec());
+ dict->SetString("priority", RequestPriorityToString(priority));
+ return std::move(dict);
+}
+
std::unique_ptr<base::Value> NetLogURLRequestStartCallback(
const GURL* url,
const std::string* method,
int load_flags,
- RequestPriority priority,
int64_t upload_id,
NetLogCaptureMode /* capture_mode */) {
std::unique_ptr<base::DictionaryValue> dict(new base::DictionaryValue());
dict->SetString("url", url->possibly_invalid_spec());
dict->SetString("method", *method);
dict->SetInteger("load_flags", load_flags);
- dict->SetString("priority", RequestPriorityToString(priority));
if (upload_id > -1)
dict->SetString("upload_id", base::Int64ToString(upload_id));
return std::move(dict);
diff --git a/chromium/net/url_request/url_request_netlog_params.h b/chromium/net/url_request/url_request_netlog_params.h
index a42ca3f3bc9..2d672f5767c 100644
--- a/chromium/net/url_request/url_request_netlog_params.h
+++ b/chromium/net/url_request/url_request_netlog_params.h
@@ -23,12 +23,17 @@ namespace net {
class NetLogCaptureMode;
+// Returns a Value containing NetLog parameters for constructing a URLRequest.
+NET_EXPORT std::unique_ptr<base::Value> NetLogURLRequestConstructorCallback(
+ const GURL* url,
+ RequestPriority priority,
+ NetLogCaptureMode /* capture_mode */);
+
// Returns a Value containing NetLog parameters for starting a URLRequest.
NET_EXPORT std::unique_ptr<base::Value> NetLogURLRequestStartCallback(
const GURL* url,
const std::string* method,
int load_flags,
- RequestPriority priority,
int64_t upload_id,
NetLogCaptureMode /* capture_mode */);
diff --git a/chromium/net/url_request/url_request_quic_unittest.cc b/chromium/net/url_request/url_request_quic_unittest.cc
index e37baffe69a..c285100d10d 100644
--- a/chromium/net/url_request/url_request_quic_unittest.cc
+++ b/chromium/net/url_request/url_request_quic_unittest.cc
@@ -20,9 +20,8 @@
#include "net/test/cert_test_util.h"
#include "net/test/gtest_util.h"
#include "net/test/test_data_directory.h"
-#include "net/tools/quic/quic_in_memory_cache.h"
+#include "net/tools/quic/quic_http_response_cache.h"
#include "net/tools/quic/quic_simple_server.h"
-#include "net/tools/quic/test_tools/quic_in_memory_cache_peer.h"
#include "net/url_request/url_request.h"
#include "net/url_request/url_request_test_util.h"
#include "testing/gmock/include/gmock/gmock.h"
@@ -93,9 +92,8 @@ class URLRequestQuicTest : public ::testing::Test {
private:
void StartQuicServer() {
// Set up in-memory cache.
- test::QuicInMemoryCachePeer::ResetForTests();
- QuicInMemoryCache::GetInstance()->AddSimpleResponse(
- kTestServerHost, kHelloPath, kHelloStatus, kHelloBodyValue);
+ response_cache_.AddSimpleResponse(kTestServerHost, kHelloPath, kHelloStatus,
+ kHelloBodyValue);
net::QuicConfig config;
// Set up server certs.
std::unique_ptr<net::ProofSourceChromium> proof_source(
@@ -107,7 +105,8 @@ class URLRequestQuicTest : public ::testing::Test {
directory.Append(FILE_PATH_LITERAL("quic_test.example.com.key.sct"))));
server_.reset(new QuicSimpleServer(
test::CryptoTestUtils::ProofSourceForTesting(), config,
- net::QuicCryptoServerConfig::ConfigOptions(), AllSupportedVersions()));
+ net::QuicCryptoServerConfig::ConfigOptions(), AllSupportedVersions(),
+ &response_cache_));
int rv = server_->Listen(
net::IPEndPoint(net::IPAddress::IPv4AllZeros(), kTestServerPort));
EXPECT_GE(rv, 0) << "Quic server fails to start";
@@ -125,6 +124,7 @@ class URLRequestQuicTest : public ::testing::Test {
std::unique_ptr<MappedHostResolver> host_resolver_;
std::unique_ptr<QuicSimpleServer> server_;
std::unique_ptr<TestURLRequestContext> context_;
+ QuicHttpResponseCache response_cache_;
MockCertVerifier cert_verifier_;
};
diff --git a/chromium/net/url_request/url_request_test_job.cc b/chromium/net/url_request/url_request_test_job.cc
index 1f5824babc1..ab359b4e67b 100644
--- a/chromium/net/url_request/url_request_test_job.cc
+++ b/chromium/net/url_request/url_request_test_job.cc
@@ -44,18 +44,31 @@ class TestJobProtocolHandler : public URLRequestJobFactory::ProtocolHandler {
GURL URLRequestTestJob::test_url_1() {
return GURL("test:url1");
}
+
GURL URLRequestTestJob::test_url_2() {
return GURL("test:url2");
}
+
GURL URLRequestTestJob::test_url_3() {
return GURL("test:url3");
}
+
GURL URLRequestTestJob::test_url_4() {
return GURL("test:url4");
}
+
+GURL URLRequestTestJob::test_url_auto_advance_async_reads_1() {
+ return GURL("test:url_auto_advance_async_reads_1");
+}
+
GURL URLRequestTestJob::test_url_error() {
return GURL("test:error");
}
+
+GURL URLRequestTestJob::test_url_redirect_to_url_1() {
+ return GURL("test:redirect_to_1");
+}
+
GURL URLRequestTestJob::test_url_redirect_to_url_2() {
return GURL("test:redirect_to_2");
}
@@ -93,6 +106,17 @@ std::string URLRequestTestJob::test_redirect_headers() {
}
// static getter for redirect response headers
+std::string URLRequestTestJob::test_redirect_to_url_1_headers() {
+ std::string headers = "HTTP/1.1 302 MOVED";
+ headers.push_back('\n');
+ headers += "Location: ";
+ headers += test_url_1().spec();
+ headers.push_back('\n');
+ headers.push_back('\n');
+ return headers;
+}
+
+// static getter for redirect response headers
std::string URLRequestTestJob::test_redirect_to_url_2_headers() {
std::string headers = "HTTP/1.1 302 MOVED";
headers.push_back('\n');
@@ -119,15 +143,7 @@ URLRequestTestJob::CreateProtocolHandler() {
URLRequestTestJob::URLRequestTestJob(URLRequest* request,
NetworkDelegate* network_delegate)
- : URLRequestJob(request, network_delegate),
- auto_advance_(false),
- stage_(WAITING),
- priority_(DEFAULT_PRIORITY),
- offset_(0),
- async_buf_(NULL),
- async_buf_size_(0),
- response_headers_length_(0),
- weak_factory_(this) {}
+ : URLRequestTestJob(request, network_delegate, false) {}
URLRequestTestJob::URLRequestTestJob(URLRequest* request,
NetworkDelegate* network_delegate,
@@ -140,6 +156,7 @@ URLRequestTestJob::URLRequestTestJob(URLRequest* request,
async_buf_(NULL),
async_buf_size_(0),
response_headers_length_(0),
+ async_reads_(false),
weak_factory_(this) {}
URLRequestTestJob::URLRequestTestJob(URLRequest* request,
@@ -153,12 +170,13 @@ URLRequestTestJob::URLRequestTestJob(URLRequest* request,
priority_(DEFAULT_PRIORITY),
response_data_(response_data),
offset_(0),
- async_buf_(NULL),
+ async_buf_(nullptr),
async_buf_size_(0),
response_headers_(new net::HttpResponseHeaders(
net::HttpUtil::AssembleRawHeaders(response_headers.c_str(),
response_headers.size()))),
response_headers_length_(response_headers.size()),
+ async_reads_(false),
weak_factory_(this) {}
URLRequestTestJob::~URLRequestTestJob() {
@@ -190,16 +208,22 @@ void URLRequestTestJob::Start() {
void URLRequestTestJob::StartAsync() {
if (!response_headers_.get()) {
SetResponseHeaders(test_headers());
- if (request_->url().spec() == test_url_1().spec()) {
+ if (request_->url() == test_url_1()) {
response_data_ = test_data_1();
stage_ = DATA_AVAILABLE; // Simulate a synchronous response for this one.
- } else if (request_->url().spec() == test_url_2().spec()) {
+ } else if (request_->url() == test_url_2()) {
response_data_ = test_data_2();
- } else if (request_->url().spec() == test_url_3().spec()) {
+ } else if (request_->url() == test_url_3()) {
response_data_ = test_data_3();
- } else if (request_->url().spec() == test_url_4().spec()) {
+ } else if (request_->url() == test_url_4()) {
response_data_ = test_data_4();
- } else if (request_->url().spec() == test_url_redirect_to_url_2().spec()) {
+ } else if (request_->url() == test_url_auto_advance_async_reads_1()) {
+ response_data_ = test_data_1();
+ stage_ = DATA_AVAILABLE; // Data is available immediately.
+ async_reads_ = true; // All reads complete asynchronously.
+ } else if (request_->url() == test_url_redirect_to_url_1()) {
+ SetResponseHeaders(test_redirect_to_url_1_headers());
+ } else if (request_->url() == test_url_redirect_to_url_2()) {
SetResponseHeaders(test_redirect_to_url_2_headers());
} else {
AdvanceJob();
@@ -227,24 +251,33 @@ void URLRequestTestJob::SetResponseHeaders(
response_headers_length_ = response_headers.size();
}
+int URLRequestTestJob::CopyDataForRead(IOBuffer* buf, int buf_size) {
+ int bytes_read = 0;
+ if (offset_ < static_cast<int>(response_data_.length())) {
+ bytes_read = buf_size;
+ if (bytes_read + offset_ > static_cast<int>(response_data_.length()))
+ bytes_read = static_cast<int>(response_data_.length()) - offset_;
+
+ memcpy(buf->data(), &response_data_.c_str()[offset_], bytes_read);
+ offset_ += bytes_read;
+ }
+ return bytes_read;
+}
+
int URLRequestTestJob::ReadRawData(IOBuffer* buf, int buf_size) {
- if (stage_ == WAITING) {
+ if (stage_ == WAITING || async_reads_) {
async_buf_ = buf;
async_buf_size_ = buf_size;
+ if (stage_ != WAITING) {
+ stage_ = WAITING;
+ base::ThreadTaskRunnerHandle::Get()->PostTask(
+ FROM_HERE, base::Bind(&URLRequestTestJob::ProcessNextOperation,
+ weak_factory_.GetWeakPtr()));
+ }
return ERR_IO_PENDING;
}
- if (offset_ >= static_cast<int>(response_data_.length()))
- return 0; // done reading
-
- int to_read = buf_size;
- if (to_read + offset_ > static_cast<int>(response_data_.length()))
- to_read = static_cast<int>(response_data_.length()) - offset_;
-
- memcpy(buf->data(), &response_data_.c_str()[offset_], to_read);
- offset_ += to_read;
-
- return to_read;
+ return CopyDataForRead(buf, buf_size);
}
void URLRequestTestJob::GetResponseInfo(HttpResponseInfo* info) {
@@ -306,7 +339,7 @@ void URLRequestTestJob::ProcessNextOperation() {
stage_ = DATA_AVAILABLE;
// OK if ReadRawData wasn't called yet.
if (async_buf_) {
- int result = ReadRawData(async_buf_, async_buf_size_);
+ int result = CopyDataForRead(async_buf_, async_buf_size_);
if (result < 0)
NOTREACHED() << "Reads should not fail in DATA_AVAILABLE.";
if (NextReadAsync()) {
diff --git a/chromium/net/url_request/url_request_test_job.h b/chromium/net/url_request/url_request_test_job.h
index 162d5094aa2..70826789045 100644
--- a/chromium/net/url_request/url_request_test_job.h
+++ b/chromium/net/url_request/url_request_test_job.h
@@ -63,12 +63,28 @@ class NET_EXPORT_PRIVATE URLRequestTestJob : public URLRequestJob {
// The canned URLs this handler will respond to without having been
// explicitly initialized with response headers and data.
- // FIXME(brettw): we should probably also have a redirect one
+
+ // URL that, by default, automatically advances through each state. Reads
+ // complete synchronously.
static GURL test_url_1();
+
+ // URLs that, by default, must be manually advanced through each state.
static GURL test_url_2();
static GURL test_url_3();
static GURL test_url_4();
+
+ // URL that, by default, automatically advances through each state. Reads
+ // complete asynchronously. Has same response body as test_url_1(), which is
+ // (test_data_1()).
+ static GURL test_url_auto_advance_async_reads_1();
+
+ // URL that fails with ERR_INVALID_URL.
static GURL test_url_error();
+
+ // Redirects to test_url_1().
+ static GURL test_url_redirect_to_url_1();
+
+ // Redirects to test_url_2().
static GURL test_url_redirect_to_url_2();
// The data that corresponds to each of the URLs above
@@ -83,6 +99,9 @@ class NET_EXPORT_PRIVATE URLRequestTestJob : public URLRequestJob {
// The headers for a redirect response
static std::string test_redirect_headers();
+ // The headers for a redirect response to the first test url.
+ static std::string test_redirect_to_url_1_headers();
+
// The headers for a redirect response to the second test url.
static std::string test_redirect_to_url_2_headers();
@@ -147,6 +166,10 @@ class NET_EXPORT_PRIVATE URLRequestTestJob : public URLRequestJob {
// Assigns |response_headers_| and |response_headers_length_|.
void SetResponseHeaders(const std::string& response_headers);
+ // Copies as much of the response body as will into |buf|, and returns number
+ // of bytes written.
+ int CopyDataForRead(IOBuffer* buf, int buf_size);
+
bool auto_advance_;
Stage stage_;
@@ -174,6 +197,8 @@ class NET_EXPORT_PRIVATE URLRequestTestJob : public URLRequestJob {
// Original size in bytes of the response headers before decoding.
int response_headers_length_;
+ bool async_reads_;
+
base::WeakPtrFactory<URLRequestTestJob> weak_factory_;
};
diff --git a/chromium/net/url_request/url_request_test_util.cc b/chromium/net/url_request/url_request_test_util.cc
index cc56ef300f1..7ce435a23e6 100644
--- a/chromium/net/url_request/url_request_test_util.cc
+++ b/chromium/net/url_request/url_request_test_util.cc
@@ -290,15 +290,22 @@ void TestDelegate::OnReadCompleted(URLRequest* request, int bytes_read) {
if (response_started_count_ == 0)
received_data_before_response_ = true;
- if (cancel_in_rd_)
- request_status_ = request->Cancel();
-
if (bytes_read >= 0) {
// There is data to read.
received_bytes_count_ += bytes_read;
- // consume the data
+ // Consume the data.
data_received_.append(buf_->data(), bytes_read);
+
+ if (cancel_in_rd_) {
+ request_status_ = request->Cancel();
+ // If bytes_read is 0, won't get a notification on cancelation.
+ if (bytes_read == 0 && quit_on_complete_) {
+ base::ThreadTaskRunnerHandle::Get()->PostTask(
+ FROM_HERE, base::MessageLoop::QuitWhenIdleClosure());
+ }
+ return;
+ }
}
// If it was not end of stream, request to read more.
diff --git a/chromium/net/url_request/url_request_test_util.h b/chromium/net/url_request/url_request_test_util.h
index 6a023ed2e7d..3a90f5f70d7 100644
--- a/chromium/net/url_request/url_request_test_util.h
+++ b/chromium/net/url_request/url_request_test_util.h
@@ -165,6 +165,7 @@ class TestDelegate : public URLRequest::Delegate {
const std::string& data_received() const { return data_received_; }
int bytes_received() const { return static_cast<int>(data_received_.size()); }
int response_started_count() const { return response_started_count_; }
+ int received_bytes_count() const { return received_bytes_count_; }
int received_redirect_count() const { return received_redirect_count_; }
bool received_data_before_response() const {
return received_data_before_response_;
diff --git a/chromium/net/url_request/url_request_throttler_entry.h b/chromium/net/url_request/url_request_throttler_entry.h
index 2d1d32a6f5c..d683a1e5589 100644
--- a/chromium/net/url_request/url_request_throttler_entry.h
+++ b/chromium/net/url_request/url_request_throttler_entry.h
@@ -19,7 +19,6 @@
namespace net {
-class NetworkDelegate;
class URLRequestThrottlerManager;
// URLRequestThrottlerEntry represents an entry of URLRequestThrottlerManager.
diff --git a/chromium/net/url_request/url_request_throttler_entry_interface.h b/chromium/net/url_request/url_request_throttler_entry_interface.h
index 44a56124791..b232265cb95 100644
--- a/chromium/net/url_request/url_request_throttler_entry_interface.h
+++ b/chromium/net/url_request/url_request_throttler_entry_interface.h
@@ -16,9 +16,7 @@
namespace net {
-class NetworkDelegate;
class URLRequest;
-class URLRequestThrottlerHeaderInterface;
// Interface provided on entries of the URL request throttler manager.
class NET_EXPORT URLRequestThrottlerEntryInterface
diff --git a/chromium/net/url_request/url_request_throttler_unittest.cc b/chromium/net/url_request/url_request_throttler_unittest.cc
index 54be21c2b23..bda138ef7f0 100644
--- a/chromium/net/url_request/url_request_throttler_unittest.cc
+++ b/chromium/net/url_request/url_request_throttler_unittest.cc
@@ -8,7 +8,6 @@
#include "base/pickle.h"
#include "base/stl_util.h"
#include "base/strings/string_number_conversions.h"
-#include "base/strings/stringprintf.h"
#include "base/test/histogram_tester.h"
#include "base/time/time.h"
#include "net/base/load_flags.h"
diff --git a/chromium/net/url_request/url_request_unittest.cc b/chromium/net/url_request/url_request_unittest.cc
index a91224a5ed3..580768775a6 100644
--- a/chromium/net/url_request/url_request_unittest.cc
+++ b/chromium/net/url_request/url_request_unittest.cc
@@ -60,7 +60,7 @@
#include "net/base/url_util.h"
#include "net/cert/ct_policy_enforcer.h"
#include "net/cert/ct_policy_status.h"
-#include "net/cert/ct_verifier.h"
+#include "net/cert/do_nothing_ct_verifier.h"
#include "net/cert/ev_root_ca_metadata.h"
#include "net/cert/mock_cert_verifier.h"
#include "net/cert/signed_certificate_timestamp_and_status.h"
@@ -388,8 +388,18 @@ class BlockingNetworkDelegate : public TestNetworkDelegate {
USER_CALLBACK, // User takes care of doing a callback. |retval_| and
// |auth_retval_| are ignored. In every blocking stage the
// message loop is quit.
+ USER_NOTIFY, // User is notified by a provided callback of the
+ // blocking, and synchronously returns instructions
+ // for handling it.
};
+ using NotificationCallback =
+ base::Callback<Error(const CompletionCallback&, const URLRequest*)>;
+
+ using NotificationAuthCallback =
+ base::Callback<NetworkDelegate::AuthRequiredResponse(const AuthCallback&,
+ const URLRequest*)>;
+
// Creates a delegate which does not block at all.
explicit BlockingNetworkDelegate(BlockMode block_mode);
@@ -426,6 +436,17 @@ class BlockingNetworkDelegate : public TestNetworkDelegate {
block_on_ = block_on;
}
+ // Only valid if |block_mode_| == USER_NOTIFY
+ void set_notification_callback(
+ const NotificationCallback& notification_callback) {
+ notification_callback_ = notification_callback;
+ }
+
+ void set_notification_auth_callback(
+ const NotificationAuthCallback& notification_auth_callback) {
+ notification_auth_callback_ = notification_auth_callback;
+ }
+
// Allows the user to check in which state did we block.
Stage stage_blocked_for_callback() const {
EXPECT_EQ(USER_CALLBACK, block_mode_);
@@ -464,7 +485,9 @@ class BlockingNetworkDelegate : public TestNetworkDelegate {
// Checks whether we should block in |stage|. If yes, returns an error code
// and optionally sets up callback based on |block_mode_|. If no, returns OK.
- int MaybeBlockStage(Stage stage, const CompletionCallback& callback);
+ int MaybeBlockStage(Stage stage,
+ const URLRequest* request,
+ const CompletionCallback& callback);
// Configuration parameters, can be adjusted by public methods:
const BlockMode block_mode_;
@@ -491,6 +514,10 @@ class BlockingNetworkDelegate : public TestNetworkDelegate {
CompletionCallback callback_;
AuthCallback auth_callback_;
+ // Callback to request user instructions for blocking.
+ NotificationCallback notification_callback_;
+ NotificationAuthCallback notification_auth_callback_;
+
base::WeakPtrFactory<BlockingNetworkDelegate> weak_factory_;
DISALLOW_COPY_AND_ASSIGN(BlockingNetworkDelegate);
@@ -550,7 +577,7 @@ int BlockingNetworkDelegate::OnBeforeURLRequest(
if (!redirect_url_.is_empty())
*new_url = redirect_url_;
- return MaybeBlockStage(ON_BEFORE_URL_REQUEST, callback);
+ return MaybeBlockStage(ON_BEFORE_URL_REQUEST, request, callback);
}
int BlockingNetworkDelegate::OnBeforeStartTransaction(
@@ -559,7 +586,7 @@ int BlockingNetworkDelegate::OnBeforeStartTransaction(
HttpRequestHeaders* headers) {
TestNetworkDelegate::OnBeforeStartTransaction(request, callback, headers);
- return MaybeBlockStage(ON_BEFORE_SEND_HEADERS, callback);
+ return MaybeBlockStage(ON_BEFORE_SEND_HEADERS, request, callback);
}
int BlockingNetworkDelegate::OnHeadersReceived(
@@ -574,7 +601,7 @@ int BlockingNetworkDelegate::OnHeadersReceived(
override_response_headers,
allowed_unsafe_redirect_url);
- return MaybeBlockStage(ON_HEADERS_RECEIVED, callback);
+ return MaybeBlockStage(ON_HEADERS_RECEIVED, request, callback);
}
NetworkDelegate::AuthRequiredResponse BlockingNetworkDelegate::OnAuthRequired(
@@ -612,6 +639,11 @@ NetworkDelegate::AuthRequiredResponse BlockingNetworkDelegate::OnAuthRequired(
base::ThreadTaskRunnerHandle::Get()->PostTask(
FROM_HERE, base::MessageLoop::QuitWhenIdleClosure());
return AUTH_REQUIRED_RESPONSE_IO_PENDING;
+
+ case USER_NOTIFY:
+ // If the callback returns ERR_IO_PENDING, the user has accepted
+ // responsibility for running the callback in the future.
+ return notification_auth_callback_.Run(callback, request);
}
NOTREACHED();
return AUTH_REQUIRED_RESPONSE_NO_ACTION; // Dummy value.
@@ -626,6 +658,7 @@ void BlockingNetworkDelegate::Reset() {
int BlockingNetworkDelegate::MaybeBlockStage(
BlockingNetworkDelegate::Stage stage,
+ const URLRequest* request,
const CompletionCallback& callback) {
// Check that the user has provided callback for the previous blocked stage.
EXPECT_EQ(NOT_BLOCKED, stage_blocked_for_callback_);
@@ -651,6 +684,11 @@ int BlockingNetworkDelegate::MaybeBlockStage(
base::ThreadTaskRunnerHandle::Get()->PostTask(
FROM_HERE, base::MessageLoop::QuitWhenIdleClosure());
return ERR_IO_PENDING;
+
+ case USER_NOTIFY:
+ // If the callback returns ERR_IO_PENDING, the user has accepted
+ // responsibility for running the callback in the future.
+ return notification_callback_.Run(callback, request);
}
NOTREACHED();
return 0;
@@ -2724,6 +2762,23 @@ TEST_F(URLRequestTest, SameSiteCookies) {
EXPECT_EQ(0, network_delegate.blocked_set_cookie_count());
}
+ // Verify that both cookies are sent when the request has no initiator (can
+ // happen for main frame browser-initiated navigations).
+ {
+ TestDelegate d;
+ std::unique_ptr<URLRequest> req(default_context_.CreateRequest(
+ test_server.GetURL(kHost, "/echoheader?Cookie"), DEFAULT_PRIORITY, &d));
+ req->set_first_party_for_cookies(test_server.GetURL(kHost, "/"));
+ req->Start();
+ base::RunLoop().Run();
+
+ EXPECT_NE(std::string::npos,
+ d.data_received().find("StrictSameSiteCookie=1"));
+ EXPECT_NE(std::string::npos, d.data_received().find("LaxSameSiteCookie=1"));
+ EXPECT_EQ(0, network_delegate.blocked_get_cookies_count());
+ EXPECT_EQ(0, network_delegate.blocked_set_cookie_count());
+ }
+
// Verify that both cookies are sent for same-registrable-domain requests.
{
TestDelegate d;
@@ -4806,7 +4861,7 @@ class AsyncDelegateLogger : public base::RefCounted<AsyncDelegateLogger> {
std::string delegate_info;
EXPECT_EQ(NetLogEventType::DELEGATE_INFO, entries[log_position].type);
EXPECT_EQ(NetLogEventPhase::BEGIN, entries[log_position].phase);
- EXPECT_TRUE(entries[log_position].GetStringValue("delegate_info",
+ EXPECT_TRUE(entries[log_position].GetStringValue("delegate_blocked_by",
&delegate_info));
EXPECT_EQ(kFirstDelegateInfo, delegate_info);
@@ -4817,7 +4872,7 @@ class AsyncDelegateLogger : public base::RefCounted<AsyncDelegateLogger> {
++log_position;
EXPECT_EQ(NetLogEventType::DELEGATE_INFO, entries[log_position].type);
EXPECT_EQ(NetLogEventPhase::BEGIN, entries[log_position].phase);
- EXPECT_TRUE(entries[log_position].GetStringValue("delegate_info",
+ EXPECT_TRUE(entries[log_position].GetStringValue("delegate_blocked_by",
&delegate_info));
EXPECT_EQ(kSecondDelegateInfo, delegate_info);
@@ -5391,8 +5446,8 @@ TEST_F(URLRequestTestHTTP, URLRequestDelegateOnRedirectCancelled) {
for (size_t test_case = 0; test_case < arraysize(kCancelStages);
++test_case) {
AsyncLoggingUrlRequestDelegate request_delegate(kCancelStages[test_case]);
- TestURLRequestContext context(true);
TestNetLog net_log;
+ TestURLRequestContext context(true);
context.set_network_delegate(NULL);
context.set_net_log(&net_log);
context.Init();
@@ -5511,7 +5566,7 @@ TEST_F(URLRequestTestHTTP, RedirectWithHeaderRemovalTest) {
EXPECT_EQ("None", d.data_received());
}
-TEST_F(URLRequestTestHTTP, CancelTest) {
+TEST_F(URLRequestTestHTTP, CancelAfterStart) {
TestDelegate d;
{
std::unique_ptr<URLRequest> r(default_context_.CreateRequest(
@@ -5532,7 +5587,7 @@ TEST_F(URLRequestTestHTTP, CancelTest) {
}
}
-TEST_F(URLRequestTestHTTP, CancelTest2) {
+TEST_F(URLRequestTestHTTP, CancelInResponseStarted) {
ASSERT_TRUE(http_test_server()->Start());
TestDelegate d;
@@ -5554,11 +5609,34 @@ TEST_F(URLRequestTestHTTP, CancelTest2) {
}
}
-TEST_F(URLRequestTestHTTP, CancelTest3) {
+TEST_F(URLRequestTestHTTP, CancelOnDataReceived) {
+ ASSERT_TRUE(http_test_server()->Start());
+
+ TestDelegate d;
+ {
+ std::unique_ptr<URLRequest> r(default_context_.CreateRequest(
+ http_test_server()->GetURL("/defaultresponse"), DEFAULT_PRIORITY, &d));
+
+ d.set_cancel_in_received_data(true);
+
+ r->Start();
+ EXPECT_TRUE(r->is_pending());
+
+ base::RunLoop().Run();
+
+ EXPECT_EQ(1, d.response_started_count());
+ EXPECT_NE(0, d.received_bytes_count());
+ EXPECT_FALSE(d.received_data_before_response());
+ EXPECT_EQ(ERR_ABORTED, d.request_status());
+ }
+}
+
+TEST_F(URLRequestTestHTTP, CancelDuringEofRead) {
ASSERT_TRUE(http_test_server()->Start());
TestDelegate d;
{
+ // This returns an empty response (With headers).
std::unique_ptr<URLRequest> r(default_context_.CreateRequest(
http_test_server()->GetURL("/"), DEFAULT_PRIORITY, &d));
@@ -5570,16 +5648,13 @@ TEST_F(URLRequestTestHTTP, CancelTest3) {
base::RunLoop().Run();
EXPECT_EQ(1, d.response_started_count());
- // There is no guarantee about how much data was received
- // before the cancel was issued. It could have been 0 bytes,
- // or it could have been all the bytes.
- // EXPECT_EQ(0, d.bytes_received());
+ EXPECT_EQ(0, d.received_bytes_count());
EXPECT_FALSE(d.received_data_before_response());
EXPECT_EQ(ERR_ABORTED, d.request_status());
}
}
-TEST_F(URLRequestTestHTTP, CancelTest4) {
+TEST_F(URLRequestTestHTTP, CancelByDestroyingAfterStart) {
ASSERT_TRUE(http_test_server()->Start());
TestDelegate d;
@@ -5605,7 +5680,7 @@ TEST_F(URLRequestTestHTTP, CancelTest4) {
EXPECT_EQ(0, d.bytes_received());
}
-TEST_F(URLRequestTestHTTP, CancelTest5) {
+TEST_F(URLRequestTestHTTP, CancelWhileReadingFromCache) {
ASSERT_TRUE(http_test_server()->Start());
// populate cache
@@ -6046,7 +6121,7 @@ TEST_F(URLRequestTestHTTP, ProcessPKPAndSendReport) {
std::unique_ptr<base::Value> value(
base::JSONReader::Read(mock_report_sender.latest_report()));
ASSERT_TRUE(value);
- ASSERT_TRUE(value->IsType(base::Value::TYPE_DICTIONARY));
+ ASSERT_TRUE(value->IsType(base::Value::Type::DICTIONARY));
base::DictionaryValue* report_dict;
ASSERT_TRUE(value->GetAsDictionary(&report_dict));
std::string report_hostname;
@@ -6111,7 +6186,7 @@ TEST_F(URLRequestTestHTTP, ProcessPKPReportOnly) {
std::unique_ptr<base::Value> value(
base::JSONReader::Read(mock_report_sender.latest_report()));
ASSERT_TRUE(value);
- ASSERT_TRUE(value->IsType(base::Value::TYPE_DICTIONARY));
+ ASSERT_TRUE(value->IsType(base::Value::Type::DICTIONARY));
base::DictionaryValue* report_dict;
ASSERT_TRUE(value->GetAsDictionary(&report_dict));
std::string report_hostname;
@@ -6369,23 +6444,6 @@ class MockExpectCTReporter : public TransportSecurityState::ExpectCTReporter {
uint32_t num_failures_;
};
-// A CTVerifier that returns net::OK for every certificate.
-class MockCTVerifier : public CTVerifier {
- public:
- MockCTVerifier() {}
- ~MockCTVerifier() override {}
-
- int Verify(X509Certificate* cert,
- const std::string& stapled_ocsp_response,
- const std::string& sct_list_from_tls_extension,
- SignedCertificateTimestampAndStatusList* output_scts,
- const NetLogWithSource& net_log) override {
- return net::OK;
- }
-
- void SetObserver(Observer* observer) override {}
-};
-
// A CTPolicyEnforcer that returns a default CertPolicyCompliance value
// for every certificate.
class MockCTPolicyEnforcer : public CTPolicyEnforcer {
@@ -6433,9 +6491,9 @@ TEST_F(URLRequestTestHTTP, ExpectCTHeader) {
verify_result.is_issued_by_known_root = true;
cert_verifier.AddResultForCert(cert.get(), verify_result, OK);
- // Set up a MockCTVerifier and MockCTPolicyEnforcer to trigger an Expect CT
- // violation.
- MockCTVerifier ct_verifier;
+ // Set up a DoNothingCTVerifier and MockCTPolicyEnforcer to trigger an Expect
+ // CT violation.
+ DoNothingCTVerifier ct_verifier;
MockCTPolicyEnforcer ct_policy_enforcer;
ct_policy_enforcer.set_default_result(
ct::CertPolicyCompliance::CERT_POLICY_NOT_ENOUGH_SCTS);
@@ -7807,7 +7865,7 @@ TEST_F(URLRequestTestHTTP, NetworkAccessedClearOnLoadOnlyFromCache) {
EXPECT_FALSE(req->response_info().network_accessed);
}
-// Test that a single job with a throttled priority completes
+// Test that a single job with a THROTTLED priority completes
// correctly in the absence of contention.
TEST_F(URLRequestTestHTTP, ThrottledPriority) {
ASSERT_TRUE(http_test_server()->Start());
@@ -7822,6 +7880,281 @@ TEST_F(URLRequestTestHTTP, ThrottledPriority) {
EXPECT_TRUE(req->status().is_success());
}
+// A class to hold state for responding to USER_NOTIFY callbacks from
+// BlockingNetworkDelegate. It also accepts a RunLoop that will be
+// signaled via QuitWhenIdle() when any request is blocked.
+//
+class NotificationCallbackHandler {
+ public:
+ // Default constructed object doesn't block anything.
+ NotificationCallbackHandler() : run_loop_(nullptr) {}
+
+ void AddURLRequestToBlockList(const URLRequest* request) {
+ requests_to_block_.insert(request);
+ }
+
+ Error ShouldBlockRequest(const CompletionCallback& callback,
+ const URLRequest* request) {
+ if (requests_to_block_.find(request) == requests_to_block_.end()) {
+ return OK;
+ }
+
+ DCHECK(blocked_callbacks_.find(request) == blocked_callbacks_.end());
+ blocked_callbacks_[request] = callback;
+ if (run_loop_ && blocked_callbacks_.size() == requests_to_block_.size())
+ run_loop_->QuitWhenIdle();
+ return ERR_IO_PENDING;
+ }
+
+ // Erases object's memory of blocked callbacks as a side effect.
+ void GetBlockedCallbacks(
+ std::map<const URLRequest*, CompletionCallback>* blocked_callbacks) {
+ blocked_callbacks_.swap(*blocked_callbacks);
+ }
+
+ // Set a RunLoop that, if non-null, will be signaled if any request
+ // is blocked. It is the callers responsibility to make sure the
+ // passed object lives past the destruction of this class or
+ // next call to SetRunLoop().
+ void SetRunLoop(base::RunLoop* run_loop) { run_loop_ = run_loop; }
+
+ private:
+ std::set<const URLRequest*> requests_to_block_;
+ std::map<const URLRequest*, CompletionCallback> blocked_callbacks_;
+
+ base::RunLoop* run_loop_;
+
+ DISALLOW_COPY_AND_ASSIGN(NotificationCallbackHandler);
+};
+
+TEST_F(URLRequestTestHTTP, MultiThrottledPriority) {
+ ASSERT_TRUE(http_test_server()->Start());
+
+ base::RunLoop run_until_request_blocked;
+
+ NotificationCallbackHandler notification_handler;
+ notification_handler.SetRunLoop(&run_until_request_blocked);
+ BlockingNetworkDelegate network_delegate(
+ BlockingNetworkDelegate::USER_NOTIFY);
+ network_delegate.set_block_on(BlockingNetworkDelegate::ON_HEADERS_RECEIVED);
+ network_delegate.set_notification_callback(
+ base::Bind(&NotificationCallbackHandler::ShouldBlockRequest,
+ // Both objects are owned by this function, and
+ // |*network_delegate| will be destroyed first, so
+ // it's safe to pass it an unretained pointer.
+ base::Unretained(&notification_handler)));
+
+ TestURLRequestContext context(true);
+ context.set_network_delegate(&network_delegate);
+ context.Init();
+
+ // Use different test URLs to make sure all three requests turn into
+ // HttpNetworkTransacations. Use different URLRequest::Delegates so that
+ // the requests may be waited on separately.
+ TestDelegate d1;
+ std::unique_ptr<URLRequest> req1(context.CreateRequest(
+ http_test_server()->GetURL("/echoall/l"), THROTTLED, &d1));
+ notification_handler.AddURLRequestToBlockList(req1.get());
+
+ TestDelegate d2;
+ std::unique_ptr<URLRequest> req2(context.CreateRequest(
+ http_test_server()->GetURL("/echoall/2"), THROTTLED, &d2));
+ notification_handler.AddURLRequestToBlockList(req2.get());
+
+ TestDelegate d3;
+ std::unique_ptr<URLRequest> req3(context.CreateRequest(
+ http_test_server()->GetURL("/echoall/3"), THROTTLED, &d3));
+ req1->Start();
+ req2->Start();
+ req3->Start();
+ run_until_request_blocked.Run();
+ notification_handler.SetRunLoop(nullptr);
+
+ // The first two requests should be blocked based on the notification
+ // callback, and their status should have blocked the third request
+ // through throttling.
+ EXPECT_TRUE(req1->status().is_io_pending());
+ EXPECT_TRUE(req2->status().is_io_pending());
+ EXPECT_TRUE(req3->status().is_io_pending());
+
+ std::map<const URLRequest*, CompletionCallback> blocked_callbacks;
+ notification_handler.GetBlockedCallbacks(&blocked_callbacks);
+ ASSERT_EQ(2u, blocked_callbacks.size());
+ ASSERT_TRUE(blocked_callbacks.find(req1.get()) != blocked_callbacks.end());
+ ASSERT_TRUE(blocked_callbacks.find(req2.get()) != blocked_callbacks.end());
+
+ // Unblocking one of the requests blocked on the notification callback
+ // should let it complete, which should then let the third request
+ // complete. Unblock the second request, then wait for the third
+ // request to complete.
+ // TODO(rdsmith): Find something to wait on other than the third
+ // requests completion; if there's a bug in throttling, that will
+ // result in this test hanging rather than failing quickly.
+ d1.set_quit_on_complete(false);
+ d2.set_quit_on_complete(false);
+ d3.set_quit_on_complete(true);
+ blocked_callbacks[req2.get()].Run(OK);
+ base::RunLoop().Run();
+
+ notification_handler.GetBlockedCallbacks(&blocked_callbacks);
+ EXPECT_EQ(0u, blocked_callbacks.size());
+ EXPECT_TRUE(req1->status().is_io_pending());
+ // req3 is only unblocked after req2 completes, so req2's
+ // success is guaranteed at this point in the function.
+ EXPECT_EQ(URLRequestStatus::SUCCESS, req2->status().status());
+ EXPECT_EQ(URLRequestStatus::SUCCESS, req3->status().status());
+}
+
+// Confirm that failing a request unblocks following requests.
+TEST_F(URLRequestTestHTTP, ThrottledFailure) {
+ ASSERT_TRUE(http_test_server()->Start());
+
+ base::RunLoop run_until_request_blocked;
+
+ NotificationCallbackHandler notification_handler;
+ notification_handler.SetRunLoop(&run_until_request_blocked);
+ BlockingNetworkDelegate network_delegate(
+ BlockingNetworkDelegate::USER_NOTIFY);
+ network_delegate.set_block_on(BlockingNetworkDelegate::ON_HEADERS_RECEIVED);
+ network_delegate.set_notification_callback(
+ base::Bind(&NotificationCallbackHandler::ShouldBlockRequest,
+ // Both objects are owned by this function, and
+ // |*network_delegate| will be destroyed first, so
+ // it's safe to pass it an unretained pointer.
+ base::Unretained(&notification_handler)));
+
+ TestURLRequestContext context(true);
+ context.set_network_delegate(&network_delegate);
+ context.Init();
+
+ // Use different test URLs to make sure all three requests turn into
+ // HttpNetworkTransacations. Use different URLRequest::Delegates so that
+ // the requests may be waited on separately.
+ TestDelegate d1;
+ std::unique_ptr<URLRequest> req1(context.CreateRequest(
+ http_test_server()->GetURL("/echoall/l"), THROTTLED, &d1));
+ notification_handler.AddURLRequestToBlockList(req1.get());
+
+ TestDelegate d2;
+ std::unique_ptr<URLRequest> req2(context.CreateRequest(
+ http_test_server()->GetURL("/echoall/2"), THROTTLED, &d2));
+ notification_handler.AddURLRequestToBlockList(req2.get());
+
+ TestDelegate d3;
+ std::unique_ptr<URLRequest> req3(context.CreateRequest(
+ http_test_server()->GetURL("/echoall/3"), THROTTLED, &d3));
+ req1->Start();
+ req2->Start();
+ req3->Start();
+ run_until_request_blocked.Run();
+ notification_handler.SetRunLoop(nullptr);
+
+ // The first two requests should be blocked based on the notification
+ // callback, and their status should have blocked the third request
+ // through throttling.
+ EXPECT_TRUE(req1->status().is_io_pending());
+ EXPECT_TRUE(req2->status().is_io_pending());
+ EXPECT_TRUE(req3->status().is_io_pending());
+
+ std::map<const URLRequest*, CompletionCallback> blocked_callbacks;
+ notification_handler.GetBlockedCallbacks(&blocked_callbacks);
+ ASSERT_EQ(2u, blocked_callbacks.size());
+ ASSERT_TRUE(blocked_callbacks.find(req1.get()) != blocked_callbacks.end());
+ ASSERT_TRUE(blocked_callbacks.find(req2.get()) != blocked_callbacks.end());
+
+ // Confirm canceling one of the outstanding requests allows the
+ // blocked request to complete.
+
+ // TODO(rdsmith): Find something to wait on other than the third
+ // requests completion; if there's a bug in throttling, that will
+ // result in this test hanging rather than failing quickly.
+ d1.set_quit_on_complete(false);
+ d2.set_quit_on_complete(false);
+ d3.set_quit_on_complete(true);
+ req2->Cancel();
+ base::RunLoop().Run();
+
+ notification_handler.GetBlockedCallbacks(&blocked_callbacks);
+ EXPECT_EQ(0u, blocked_callbacks.size());
+ EXPECT_TRUE(req1->status().is_io_pending());
+ EXPECT_EQ(URLRequestStatus::CANCELED, req2->status().status());
+ EXPECT_EQ(URLRequestStatus::SUCCESS, req3->status().status());
+}
+
+TEST_F(URLRequestTestHTTP, ThrottledRepriUnblock) {
+ ASSERT_TRUE(http_test_server()->Start());
+
+ base::RunLoop run_until_request_blocked;
+
+ NotificationCallbackHandler notification_handler;
+ notification_handler.SetRunLoop(&run_until_request_blocked);
+ BlockingNetworkDelegate network_delegate(
+ BlockingNetworkDelegate::USER_NOTIFY);
+ network_delegate.set_block_on(BlockingNetworkDelegate::ON_HEADERS_RECEIVED);
+ network_delegate.set_notification_callback(
+ base::Bind(&NotificationCallbackHandler::ShouldBlockRequest,
+ // Both objects are owned by this function, and
+ // |*network_delegate| will be destroyed first, so
+ // it's safe to pass it an unretained pointer.
+ base::Unretained(&notification_handler)));
+
+ TestURLRequestContext context(true);
+ context.set_network_delegate(&network_delegate);
+ context.Init();
+
+ // Use different test URLs to make sure all three requests turn into
+ // HttpNetworkTransacations. Use different URLRequest::Delegates so that
+ // the requests may be waited on separately.
+ TestDelegate d1;
+ std::unique_ptr<URLRequest> req1(context.CreateRequest(
+ http_test_server()->GetURL("/echoall/l"), THROTTLED, &d1));
+ notification_handler.AddURLRequestToBlockList(req1.get());
+
+ TestDelegate d2;
+ std::unique_ptr<URLRequest> req2(context.CreateRequest(
+ http_test_server()->GetURL("/echoall/2"), THROTTLED, &d2));
+ notification_handler.AddURLRequestToBlockList(req2.get());
+
+ TestDelegate d3;
+ std::unique_ptr<URLRequest> req3(context.CreateRequest(
+ http_test_server()->GetURL("/echoall/3"), THROTTLED, &d3));
+ req1->Start();
+ req2->Start();
+ req3->Start();
+ run_until_request_blocked.Run();
+ notification_handler.SetRunLoop(nullptr);
+
+ // The first two requests should be blocked based on the notification
+ // callback, and their status should have blocked the third request
+ // through throttling.
+ EXPECT_TRUE(req1->status().is_io_pending());
+ EXPECT_TRUE(req2->status().is_io_pending());
+ EXPECT_TRUE(req3->status().is_io_pending());
+
+ std::map<const URLRequest*, CompletionCallback> blocked_callbacks;
+ notification_handler.GetBlockedCallbacks(&blocked_callbacks);
+ ASSERT_EQ(2u, blocked_callbacks.size());
+ ASSERT_TRUE(blocked_callbacks.find(req1.get()) != blocked_callbacks.end());
+ ASSERT_TRUE(blocked_callbacks.find(req2.get()) != blocked_callbacks.end());
+
+ // Confirm raising the priority of the third request allows it to complete.
+
+ // TODO(rdsmith): Find something to wait on other than the third
+ // requests completion; if there's a bug in throttling, that will
+ // result in this test hanging rather than failing quickly.
+ d1.set_quit_on_complete(false);
+ d2.set_quit_on_complete(false);
+ d3.set_quit_on_complete(true);
+ req3->SetPriority(IDLE);
+ base::RunLoop().Run();
+
+ notification_handler.GetBlockedCallbacks(&blocked_callbacks);
+ EXPECT_EQ(0u, blocked_callbacks.size());
+ EXPECT_TRUE(req1->status().is_io_pending());
+ EXPECT_TRUE(req2->status().is_io_pending());
+ EXPECT_EQ(URLRequestStatus::SUCCESS, req3->status().status());
+}
+
TEST_F(URLRequestTestHTTP, RawBodyBytesNoContentEncoding) {
ASSERT_TRUE(http_test_server()->Start());
@@ -8927,18 +9260,17 @@ TEST_F(HTTPSSessionTest, DontResumeSessionsForInvalidCertificates) {
// This the fingerprint of the "Testing CA" certificate used by the testserver.
// See net/data/ssl/certificates/ocsp-test-root.pem.
static const SHA1HashValue kOCSPTestCertFingerprint = {{
- 0xa7, 0xea, 0x4b, 0x0d, 0x13, 0xc1, 0x63, 0xbf, 0xb8, 0x4e,
- 0x9a, 0xaf, 0x33, 0x05, 0xb0, 0x8f, 0x9c, 0xbe, 0x23, 0xe9,
+ 0x80, 0x37, 0xe7, 0xee, 0x12, 0x19, 0xeb, 0x10, 0x79, 0x36,
+ 0x00, 0x48, 0x57, 0x5a, 0xa6, 0x1e, 0x2b, 0x24, 0x1a, 0xd7,
}};
// This is the SHA256, SPKI hash of the "Testing CA" certificate used by the
// testserver.
-static const SHA256HashValue kOCSPTestCertSPKI = { {
- 0xee, 0xe6, 0x51, 0x2d, 0x4c, 0xfa, 0xf7, 0x3e,
- 0x6c, 0xd8, 0xca, 0x67, 0xed, 0xb5, 0x5d, 0x49,
- 0x76, 0xe1, 0x52, 0xa7, 0x6e, 0x0e, 0xa0, 0x74,
- 0x09, 0x75, 0xe6, 0x23, 0x24, 0xbd, 0x1b, 0x28,
-} };
+static const SHA256HashValue kOCSPTestCertSPKI = {{
+ 0x05, 0xa8, 0xf6, 0xfd, 0x8e, 0x10, 0xfe, 0x92, 0x2f, 0x22, 0x75,
+ 0x46, 0x40, 0xf4, 0xc4, 0x57, 0x06, 0x0d, 0x95, 0xfd, 0x60, 0x31,
+ 0x3b, 0xf3, 0xfc, 0x12, 0x47, 0xe7, 0x66, 0x1a, 0x82, 0xa3,
+}};
// This is the policy OID contained in the certificates that testserver
// generates.
@@ -9287,6 +9619,65 @@ TEST_F(HTTPSOCSPTest, ExpectStapleReportSentOnMissing) {
mock_report_sender.latest_report_uri());
}
+// Tests that Expect-Staple reports are not sent for connections on which there
+// is a certificate error.
+TEST_F(HTTPSOCSPTest, ExpectStapleReportNotSentOnMissingWithCertError) {
+ EmbeddedTestServer https_test_server(net::EmbeddedTestServer::TYPE_HTTPS);
+ https_test_server.SetSSLConfig(
+ net::EmbeddedTestServer::CERT_COMMON_NAME_IS_DOMAIN);
+ https_test_server.ServeFilesFromSourceDirectory(
+ base::FilePath(kTestFilePath));
+ ASSERT_TRUE(https_test_server.Start());
+
+ // Set up a MockCertVerifier to report an error for the certificate
+ // and indicate that there was no stapled OCSP response.
+ scoped_refptr<X509Certificate> cert = https_test_server.GetCertificate();
+ ASSERT_TRUE(cert);
+ MockCertVerifier cert_verifier;
+ CertVerifyResult verify_result;
+ verify_result.cert_status = CERT_STATUS_DATE_INVALID;
+ verify_result.verified_cert = cert;
+ verify_result.is_issued_by_known_root = true;
+ verify_result.ocsp_result.response_status = OCSPVerifyResult::MISSING;
+ cert_verifier.AddResultForCert(cert.get(), verify_result,
+ ERR_CERT_DATE_INVALID);
+
+ // Set up a mock report sender so that the test can check that an
+ // Expect-Staple report is not sent.
+ TransportSecurityState transport_security_state;
+ MockCertificateReportSender mock_report_sender;
+ transport_security_state.SetReportSender(&mock_report_sender);
+
+ TestNetworkDelegate network_delegate;
+ TestURLRequestContext context(true);
+
+ // Force |kExpectStapleStaticHostname| to resolve to |https_test_server|.
+ MockHostResolver host_resolver;
+ context.set_host_resolver(&host_resolver);
+
+ context.set_transport_security_state(&transport_security_state);
+ context.set_network_delegate(&network_delegate);
+ context.set_cert_verifier(&cert_verifier);
+ context.Init();
+
+ // Make a connection to |kExpectStapleStaticHostname|. Because the
+ // |verify_result| used with the |cert_verifier| will indicate a certificate
+ // error, an Expect-Staple report should not be sent.
+ TestDelegate d;
+ GURL url = https_test_server.GetURL("/");
+ GURL::Replacements replace_host;
+ replace_host.SetHostStr(kExpectStapleStaticHostname);
+ url = url.ReplaceComponents(replace_host);
+ std::unique_ptr<URLRequest> violating_request(
+ context.CreateRequest(url, DEFAULT_PRIORITY, &d));
+ violating_request->Start();
+ base::RunLoop().Run();
+
+ // Confirm a report was not sent.
+ EXPECT_TRUE(mock_report_sender.latest_report().empty());
+ EXPECT_EQ(GURL(), mock_report_sender.latest_report_uri());
+}
+
TEST_F(HTTPSOCSPTest, ExpectStapleReportNotSentOnValid) {
EmbeddedTestServer https_test_server(net::EmbeddedTestServer::TYPE_HTTPS);
https_test_server.SetSSLConfig(
@@ -9339,6 +9730,65 @@ TEST_F(HTTPSOCSPTest, ExpectStapleReportNotSentOnValid) {
EXPECT_EQ(GURL(), mock_report_sender.latest_report_uri());
}
+// Tests that an Expect-Staple report is not sent when OCSP details are not
+// checked on the connection.
+TEST_F(HTTPSOCSPTest, ExpectStapleReportNotSentOnNotChecked) {
+ EmbeddedTestServer https_test_server(net::EmbeddedTestServer::TYPE_HTTPS);
+ https_test_server.SetSSLConfig(
+ net::EmbeddedTestServer::CERT_COMMON_NAME_IS_DOMAIN);
+ https_test_server.ServeFilesFromSourceDirectory(
+ base::FilePath(kTestFilePath));
+ ASSERT_TRUE(https_test_server.Start());
+
+ // Set up a MockCertVerifier to accept the certificate that the server sends,
+ // and set |ocsp_result| to indicate that OCSP stapling details were not
+ // checked on the connection.
+ scoped_refptr<X509Certificate> cert = https_test_server.GetCertificate();
+ ASSERT_TRUE(cert);
+ MockCertVerifier cert_verifier;
+ CertVerifyResult verify_result;
+ verify_result.verified_cert = cert;
+ verify_result.is_issued_by_known_root = true;
+ verify_result.ocsp_result.response_status = OCSPVerifyResult::NOT_CHECKED;
+ cert_verifier.AddResultForCert(cert.get(), verify_result, OK);
+
+ // Set up a mock report sender so that the test can check that an
+ // Expect-Staple report is not sent.
+ TransportSecurityState transport_security_state;
+ MockCertificateReportSender mock_report_sender;
+ transport_security_state.SetReportSender(&mock_report_sender);
+
+ TestNetworkDelegate network_delegate;
+ TestURLRequestContext context(true);
+
+ // Force |kExpectStapleStaticHostname| to resolve to |https_test_server|.
+ MockHostResolver host_resolver;
+ context.set_host_resolver(&host_resolver);
+
+ context.set_transport_security_state(&transport_security_state);
+ context.set_network_delegate(&network_delegate);
+ context.set_cert_verifier(&cert_verifier);
+ context.Init();
+
+ // Make a connection to |kExpectStapleStaticHostname|. Because the
+ // |verify_result| used with the |cert_verifier| will indicate that OCSP
+ // stapling details were not checked on the connection, an Expect-Staple
+ // report should not be sent.
+ TestDelegate d;
+ GURL url = https_test_server.GetURL("/");
+ GURL::Replacements replace_host;
+ replace_host.SetHostStr(kExpectStapleStaticHostname);
+ url = url.ReplaceComponents(replace_host);
+ std::unique_ptr<URLRequest> ok_request(
+ context.CreateRequest(url, DEFAULT_PRIORITY, &d));
+ ok_request->Start();
+ base::RunLoop().Run();
+
+ // Check that no report was sent.
+ EXPECT_TRUE(mock_report_sender.latest_report().empty());
+ EXPECT_EQ(GURL(), mock_report_sender.latest_report_uri());
+}
+
static const struct OCSPVerifyTestData {
std::vector<SpawnedTestServer::SSLOptions::OCSPSingleResponse> ocsp_responses;
SpawnedTestServer::SSLOptions::OCSPProduced ocsp_produced;
@@ -9600,6 +10050,59 @@ INSTANTIATE_TEST_CASE_P(OCSPVerify,
HTTPSOCSPVerifyTest,
testing::ValuesIn(kOCSPVerifyData));
+static bool SystemSupportsAIA() {
+#if defined(OS_ANDROID)
+ return false;
+#else
+ return true;
+#endif
+}
+
+class HTTPSAIATest : public HTTPSOCSPTest {
+ public:
+ void SetupContext() override {
+ context_.set_ssl_config_service(new TestSSLConfigService(
+ false /* check for EV */, false /* online revocation checking */,
+ false /* require rev. checking for local anchors */,
+ false /* token binding enabled */));
+ }
+};
+
+TEST_F(HTTPSAIATest, AIAFetching) {
+ SpawnedTestServer::SSLOptions ssl_options(
+ SpawnedTestServer::SSLOptions::CERT_AUTO_AIA_INTERMEDIATE);
+ SpawnedTestServer test_server(
+ SpawnedTestServer::TYPE_HTTPS, ssl_options,
+ base::FilePath(FILE_PATH_LITERAL("net/data/ssl")));
+ ASSERT_TRUE(test_server.Start());
+
+ TestDelegate d;
+ d.set_allow_certificate_errors(true);
+ std::unique_ptr<URLRequest> r(context_.CreateRequest(
+ test_server.GetURL("/defaultresponse"), DEFAULT_PRIORITY, &d));
+
+ r->Start();
+ EXPECT_TRUE(r->is_pending());
+
+ base::RunLoop().Run();
+
+ EXPECT_EQ(1, d.response_started_count());
+
+ CertStatus cert_status = r->ssl_info().cert_status;
+ if (SystemSupportsAIA()) {
+ EXPECT_EQ(OK, d.request_status());
+ EXPECT_EQ(0u, cert_status & CERT_STATUS_ALL_ERRORS);
+ ASSERT_TRUE(r->ssl_info().cert);
+ EXPECT_EQ(2u, r->ssl_info().cert->GetIntermediateCertificates().size());
+ } else {
+ EXPECT_EQ(CERT_STATUS_AUTHORITY_INVALID,
+ cert_status & CERT_STATUS_ALL_ERRORS);
+ }
+ ASSERT_TRUE(r->ssl_info().unverified_cert);
+ EXPECT_EQ(
+ 0u, r->ssl_info().unverified_cert->GetIntermediateCertificates().size());
+}
+
class HTTPSHardFailTest : public HTTPSOCSPTest {
protected:
void SetupContext() override {
diff --git a/chromium/net/websockets/OWNERS b/chromium/net/websockets/OWNERS
index 6c81c618dad..9530ca98f36 100644
--- a/chromium/net/websockets/OWNERS
+++ b/chromium/net/websockets/OWNERS
@@ -1,3 +1,6 @@
tyoshino@chromium.org
ricea@chromium.org
yhirano@chromium.org
+
+# TEAM: blink-network-stack@google.com
+# COMPONENT: Blink>Network>WebSockets
diff --git a/chromium/net/websockets/websocket_deflate_stream.h b/chromium/net/websockets/websocket_deflate_stream.h
index bcccd06d753..a68d512d757 100644
--- a/chromium/net/websockets/websocket_deflate_stream.h
+++ b/chromium/net/websockets/websocket_deflate_stream.h
@@ -19,8 +19,6 @@
#include "net/websockets/websocket_inflater.h"
#include "net/websockets/websocket_stream.h"
-class GURL;
-
namespace net {
class WebSocketDeflateParameters;
diff --git a/chromium/net/websockets/websocket_deflate_stream_test.cc b/chromium/net/websockets/websocket_deflate_stream_test.cc
index f4dde0872e5..db9bd875f36 100644
--- a/chromium/net/websockets/websocket_deflate_stream_test.cc
+++ b/chromium/net/websockets/websocket_deflate_stream_test.cc
@@ -18,6 +18,7 @@
#include "base/macros.h"
#include "base/memory/ptr_util.h"
#include "base/memory/ref_counted.h"
+#include "base/test/mock_callback.h"
#include "net/base/completion_callback.h"
#include "net/base/io_buffer.h"
#include "net/base/net_errors.h"
@@ -38,7 +39,6 @@ using net::test::IsOk;
namespace net {
namespace {
-typedef ::testing::MockFunction<void(int)> MockCallback; // NOLINT
using ::testing::_;
using ::testing::InSequence;
using ::testing::Invoke;
@@ -403,22 +403,21 @@ TEST_F(WebSocketDeflateStreamTest, ReadUncompressedFrameImmediately) {
TEST_F(WebSocketDeflateStreamTest, ReadUncompressedFrameAsync) {
ReadFramesStub stub(ERR_IO_PENDING);
std::vector<std::unique_ptr<WebSocketFrame>> frames;
- MockCallback mock_callback, checkpoint;
- CompletionCallback callback =
- base::Bind(&MockCallback::Call, base::Unretained(&mock_callback));
+ base::MockCallback<CompletionCallback> mock_callback;
+ base::MockCallback<base::Closure> checkpoint;
{
InSequence s;
EXPECT_CALL(*mock_stream_, ReadFrames(&frames, _))
.WillOnce(Invoke(&stub, &ReadFramesStub::Call));
- EXPECT_CALL(checkpoint, Call(0));
- EXPECT_CALL(mock_callback, Call(OK));
+ EXPECT_CALL(checkpoint, Run());
+ EXPECT_CALL(mock_callback, Run(OK));
}
- ASSERT_THAT(deflate_stream_->ReadFrames(&frames, callback),
+ ASSERT_THAT(deflate_stream_->ReadFrames(&frames, mock_callback.Get()),
IsError(ERR_IO_PENDING));
ASSERT_EQ(0u, frames.size());
- checkpoint.Call(0);
+ checkpoint.Run();
AppendTo(stub.frames_passed(),
WebSocketFrameHeader::kOpCodeText,
@@ -435,22 +434,21 @@ TEST_F(WebSocketDeflateStreamTest, ReadUncompressedFrameAsync) {
TEST_F(WebSocketDeflateStreamTest, ReadFailedAsync) {
ReadFramesStub stub(ERR_IO_PENDING);
std::vector<std::unique_ptr<WebSocketFrame>> frames;
- MockCallback mock_callback, checkpoint;
- CompletionCallback callback =
- base::Bind(&MockCallback::Call, base::Unretained(&mock_callback));
+ base::MockCallback<CompletionCallback> mock_callback;
+ base::MockCallback<base::Closure> checkpoint;
{
InSequence s;
EXPECT_CALL(*mock_stream_, ReadFrames(&frames, _))
.WillOnce(Invoke(&stub, &ReadFramesStub::Call));
- EXPECT_CALL(checkpoint, Call(0));
- EXPECT_CALL(mock_callback, Call(ERR_FAILED));
+ EXPECT_CALL(checkpoint, Run());
+ EXPECT_CALL(mock_callback, Run(ERR_FAILED));
}
- ASSERT_THAT(deflate_stream_->ReadFrames(&frames, callback),
+ ASSERT_THAT(deflate_stream_->ReadFrames(&frames, mock_callback.Get()),
IsError(ERR_IO_PENDING));
ASSERT_EQ(0u, frames.size());
- checkpoint.Call(0);
+ checkpoint.Run();
AppendTo(stub.frames_passed(),
WebSocketFrameHeader::kOpCodeText,
@@ -484,21 +482,21 @@ TEST_F(WebSocketDeflateStreamTest, ReadCompressedFrameImmediately) {
TEST_F(WebSocketDeflateStreamTest, ReadCompressedFrameAsync) {
ReadFramesStub stub(ERR_IO_PENDING);
- MockCallback mock_callback, checkpoint;
- CompletionCallback callback =
- base::Bind(&MockCallback::Call, base::Unretained(&mock_callback));
+
+ base::MockCallback<CompletionCallback> mock_callback;
+ base::MockCallback<base::Closure> checkpoint;
std::vector<std::unique_ptr<WebSocketFrame>> frames;
{
InSequence s;
EXPECT_CALL(*mock_stream_, ReadFrames(&frames, _))
.WillOnce(Invoke(&stub, &ReadFramesStub::Call));
- EXPECT_CALL(checkpoint, Call(0));
- EXPECT_CALL(mock_callback, Call(OK));
+ EXPECT_CALL(checkpoint, Run());
+ EXPECT_CALL(mock_callback, Run(OK));
}
- ASSERT_THAT(deflate_stream_->ReadFrames(&frames, callback),
+ ASSERT_THAT(deflate_stream_->ReadFrames(&frames, mock_callback.Get()),
IsError(ERR_IO_PENDING));
- checkpoint.Call(0);
+ checkpoint.Run();
AppendTo(stub.frames_passed(),
WebSocketFrameHeader::kOpCodeText,
@@ -523,9 +521,8 @@ TEST_F(WebSocketDeflateStreamTest,
kReserved1,
data1);
ReadFramesStub stub1(OK, &frames_to_output), stub2(ERR_IO_PENDING);
- MockCallback mock_callback, checkpoint;
- CompletionCallback callback =
- base::Bind(&MockCallback::Call, base::Unretained(&mock_callback));
+ base::MockCallback<CompletionCallback> mock_callback;
+ base::MockCallback<base::Closure> checkpoint;
std::vector<std::unique_ptr<WebSocketFrame>> frames;
{
@@ -533,10 +530,10 @@ TEST_F(WebSocketDeflateStreamTest,
EXPECT_CALL(*mock_stream_, ReadFrames(&frames, _))
.WillOnce(Invoke(&stub1, &ReadFramesStub::Call))
.WillOnce(Invoke(&stub2, &ReadFramesStub::Call));
- EXPECT_CALL(checkpoint, Call(0));
- EXPECT_CALL(mock_callback, Call(OK));
+ EXPECT_CALL(checkpoint, Run());
+ EXPECT_CALL(mock_callback, Run(OK));
}
- ASSERT_THAT(deflate_stream_->ReadFrames(&frames, callback),
+ ASSERT_THAT(deflate_stream_->ReadFrames(&frames, mock_callback.Get()),
IsError(ERR_IO_PENDING));
ASSERT_EQ(0u, frames.size());
@@ -545,7 +542,7 @@ TEST_F(WebSocketDeflateStreamTest,
kFinal,
data2);
- checkpoint.Call(0);
+ checkpoint.Run();
stub2.callback().Run(OK);
ASSERT_EQ(1u, frames.size());
@@ -987,9 +984,7 @@ TEST_F(WebSocketDeflateStreamTest, ReadEmptyAsyncFrame) {
std::vector<std::unique_ptr<ReadFramesStub>> stub_vector;
stub_vector.push_back(base::WrapUnique(new ReadFramesStub(ERR_IO_PENDING)));
stub_vector.push_back(base::WrapUnique(new ReadFramesStub(ERR_IO_PENDING)));
- MockCallback mock_callback;
- CompletionCallback callback =
- base::Bind(&MockCallback::Call, base::Unretained(&mock_callback));
+ base::MockCallback<CompletionCallback> mock_callback;
std::vector<std::unique_ptr<WebSocketFrame>> frames;
{
@@ -1000,10 +995,10 @@ TEST_F(WebSocketDeflateStreamTest, ReadEmptyAsyncFrame) {
EXPECT_CALL(*mock_stream_, ReadFrames(&frames, _))
.WillOnce(Invoke(stub_vector[1].get(), &ReadFramesStub::Call));
- EXPECT_CALL(mock_callback, Call(OK));
+ EXPECT_CALL(mock_callback, Run(OK));
}
- ASSERT_THAT(deflate_stream_->ReadFrames(&frames, callback),
+ ASSERT_THAT(deflate_stream_->ReadFrames(&frames, mock_callback.Get()),
IsError(ERR_IO_PENDING));
AppendTo(stub_vector[0]->frames_passed(),
WebSocketFrameHeader::kOpCodeText,
@@ -1070,23 +1065,22 @@ TEST_F(WebSocketDeflateStreamTest, WriteFrameImmediately) {
TEST_F(WebSocketDeflateStreamTest, WriteFrameAsync) {
WriteFramesStub stub(predictor_, ERR_IO_PENDING);
- MockCallback mock_callback, checkpoint;
- CompletionCallback callback =
- base::Bind(&MockCallback::Call, base::Unretained(&mock_callback));
+ base::MockCallback<CompletionCallback> mock_callback;
+ base::MockCallback<base::Closure> checkpoint;
std::vector<std::unique_ptr<WebSocketFrame>> frames;
{
InSequence s;
EXPECT_CALL(*mock_stream_, WriteFrames(&frames, _))
.WillOnce(Invoke(&stub, &WriteFramesStub::Call));
- EXPECT_CALL(checkpoint, Call(0));
- EXPECT_CALL(mock_callback, Call(OK));
+ EXPECT_CALL(checkpoint, Run());
+ EXPECT_CALL(mock_callback, Run(OK));
}
AppendTo(&frames, WebSocketFrameHeader::kOpCodeText, kFinal, "Hello");
predictor_->AddFramesToBeInput(frames);
- ASSERT_THAT(deflate_stream_->WriteFrames(&frames, callback),
+ ASSERT_THAT(deflate_stream_->WriteFrames(&frames, mock_callback.Get()),
IsError(ERR_IO_PENDING));
- checkpoint.Call(0);
+ checkpoint.Run();
stub.callback().Run(OK);
const std::vector<std::unique_ptr<WebSocketFrame>>& frames_passed =
diff --git a/chromium/net/websockets/websocket_stream.cc b/chromium/net/websockets/websocket_stream.cc
index 8cca3655ec0..b700519a3c3 100644
--- a/chromium/net/websockets/websocket_stream.cc
+++ b/chromium/net/websockets/websocket_stream.cc
@@ -11,7 +11,6 @@
#include "base/memory/ptr_util.h"
#include "base/metrics/histogram_macros.h"
#include "base/metrics/sparse_histogram.h"
-#include "base/strings/stringprintf.h"
#include "base/time/time.h"
#include "base/timer/timer.h"
#include "net/base/load_flags.h"
@@ -149,9 +148,13 @@ class WebSocketStreamRequestImpl : public WebSocketStreamRequest {
timer_->Stop();
+ std::unique_ptr<URLRequest> url_request = std::move(url_request_);
WebSocketHandshakeStreamBase* handshake_stream = handshake_stream_;
handshake_stream_ = nullptr;
connect_delegate_->OnSuccess(handshake_stream->Upgrade());
+
+ // This is safe even if |this| has already been deleted.
+ url_request->CancelWithError(ERR_WS_UPGRADE);
}
std::string FailureMessageFromNetError(int net_error) {
diff --git a/chromium/net/websockets/websocket_stream_test.cc b/chromium/net/websockets/websocket_stream_test.cc
index 091c28db163..5945e24c13a 100644
--- a/chromium/net/websockets/websocket_stream_test.cc
+++ b/chromium/net/websockets/websocket_stream_test.cc
@@ -337,6 +337,8 @@ TEST_F(WebSocketStreamCreateTest, SimpleSuccess) {
EXPECT_TRUE(stream_);
EXPECT_TRUE(request_info_);
EXPECT_TRUE(response_info_);
+ EXPECT_EQ(ERR_WS_UPGRADE,
+ url_request_context_host_.network_delegate().last_error());
}
TEST_F(WebSocketStreamCreateTest, HandshakeInfo) {
@@ -483,6 +485,8 @@ TEST_F(WebSocketStreamCreateTest, UnsolicitedSubProtocol) {
"Response must not include 'Sec-WebSocket-Protocol' header "
"if not present in request: chatv20.chromium.org",
failure_message());
+ EXPECT_EQ(ERR_INVALID_RESPONSE,
+ url_request_context_host_.network_delegate().last_error());
}
// Missing sub-protocol response is rejected.
diff --git a/chromium/net/websockets/websocket_test_util.h b/chromium/net/websockets/websocket_test_util.h
index 1a080867e4a..23769404aa8 100644
--- a/chromium/net/websockets/websocket_test_util.h
+++ b/chromium/net/websockets/websocket_test_util.h
@@ -14,12 +14,6 @@
#include "net/url_request/url_request_test_util.h"
#include "net/websockets/websocket_stream.h"
-class GURL;
-
-namespace base {
-class Timer;
-} // namespace base
-
namespace url {
class Origin;
} // namespace url
@@ -27,11 +21,9 @@ class Origin;
namespace net {
class MockClientSocketFactory;
-class NetLogWithSource;
class ProxyService;
class SequencedSocketData;
struct SSLSocketDataProvider;
-class URLRequestContext;
class LinearCongruentialGenerator {
public:
@@ -134,6 +126,10 @@ struct WebSocketTestURLRequestContextHost {
// returned pointer remains owned by this object.
TestURLRequestContext* GetURLRequestContext();
+ const TestNetworkDelegate& network_delegate() const {
+ return network_delegate_;
+ }
+
private:
WebSocketMockClientSocketFactoryMaker maker_;
TestURLRequestContext url_request_context_;